[Build] Move System.h and most of Util.h to core/

* Move System.h to core/base.
* Move most of the functionality out of Util.h to core/base.
* Fix corresponding headers.
This commit is contained in:
Fabrice de Gans 2024-03-15 18:25:04 -07:00 committed by Fabrice de Gans
parent f8374b52a8
commit 33cb9a66d4
78 changed files with 924 additions and 1021 deletions

View File

@ -385,14 +385,15 @@ if(ENABLE_NLS)
endif()
if(NOT TRANSLATIONS_ONLY)
add_subdirectory(third_party/include/stb)
add_subdirectory(src/core/fex)
add_subdirectory(src/core/base)
endif()
set(
SRC_MAIN
src/Util.cpp
src/Util_common.cpp
src/Util_desktop.cpp
src/common/SoundSDL.cpp
)
@ -402,9 +403,7 @@ endif()
set(
HDR_MAIN
src/System.h
src/Util.h
src/common/SoundDriver.h
src/common/SoundSDL.h
)
@ -640,16 +639,9 @@ if(ENABLE_DEBUGGER)
)
endif()
set(
HDR_STB_IMAGE
third_party/include/stb/stb_image.h
third_party/include/stb/stb_image_write.h
)
include_directories(
${ZLIB_INCLUDE_DIR}
third_party/include
third_party/include/stb
)
if(ENABLE_FFMPEG)
@ -675,7 +667,6 @@ if(NOT TRANSLATIONS_ONLY)
${HDR_FILTERS}
${SRC_DEBUGGER}
${HDR_DEBUGGER}
${HDR_STB_IMAGE}
)
target_include_directories(vbamcore PUBLIC ${SDL2_INCLUDE_DIRS})
endif()

View File

@ -1,501 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <string>
#ifndef _WIN32
#include <sys/stat.h>
#include <unistd.h>
#else // _WIN32
#include <direct.h>
#include <io.h>
#endif // _WIN32
#include <zlib.h>
#define STB_IMAGE_IMPLEMENTATION
extern "C" {
#include "stb_image.h"
}
#define STBI_MSC_SECURE_CRT
#define STB_IMAGE_WRITE_IMPLEMENTATION
extern "C" {
#include "stb_image_write.h"
}
#include "core/fex/fex.h"
#include "core/base/file_util.h"
#include "core/base/message.h"
#include "System.h"
#include "Util.h"
#include "gba/Globals.h"
#ifndef _MSC_VER
#define _stricmp strcasecmp
#endif // ! _MSC_VER
extern int systemColorDepth;
extern int systemRedShift;
extern int systemGreenShift;
extern int systemBlueShift;
extern uint16_t systemColorMap16[0x10000];
extern uint32_t systemColorMap32[0x10000];
#define MAX_CART_SIZE 0x8000000 // 128MB
// Get user-specific config dir manually.
// apple: ~/Library/Application Support/
// windows: %APPDATA%/
// unix: ${XDG_CONFIG_HOME:-~/.config}/
std::string get_xdg_user_config_home()
{
std::string path;
#ifdef __APPLE__
std::string home(getenv("HOME"));
path = home + "/Library/Application Support";
#elif _WIN32
char *app_data_env = getenv("LOCALAPPDATA");
if (!app_data_env) app_data_env = getenv("APPDATA");
std::string app_data(app_data_env);
path = app_data;
#else // Unix
char *xdg_var = getenv("XDG_CONFIG_HOME");
if (!xdg_var || !*xdg_var)
{
std::string xdg_default(getenv("HOME"));
path = xdg_default + "/.config";
}
else
{
path = xdg_var;
}
#endif
return path + FILE_SEP;
}
// Get user-specific data dir manually.
// apple: ~/Library/Application Support/
// windows: %APPDATA%/
// unix: ${XDG_DATA_HOME:-~/.local/share}/
std::string get_xdg_user_data_home()
{
std::string path;
#ifdef __APPLE__
std::string home(getenv("HOME"));
path = home + "/Library/Application Support";
#elif _WIN32
char *app_data_env = getenv("LOCALAPPDATA");
if (!app_data_env) app_data_env = getenv("APPDATA");
std::string app_data(app_data_env);
path = app_data;
#else // Unix
char *xdg_var = getenv("XDG_DATA_HOME");
if (!xdg_var || !*xdg_var)
{
std::string xdg_default(getenv("HOME"));
path = xdg_default + "/.local/share";
}
else
{
path = xdg_var;
}
#endif
return path + FILE_SEP;
}
void utilReadScreenPixels(uint8_t *dest, int w, int h)
{
uint8_t *b = dest;
int sizeX = w;
int sizeY = h;
switch (systemColorDepth) {
case 16: {
uint16_t *p = (uint16_t *)(g_pix + (w + 2) * 2); // skip first black line
for (int y = 0; y < sizeY; y++) {
for (int x = 0; x < sizeX; x++) {
uint16_t v = *p++;
*b++ = ((v >> systemRedShift) & 0x001f) << 3; // R
*b++ = ((v >> systemGreenShift) & 0x001f) << 3; // G
*b++ = ((v >> systemBlueShift) & 0x01f) << 3; // B
}
p++; // skip black pixel for filters
p++; // skip black pixel for filters
}
} break;
case 24: {
uint8_t *pixU8 = (uint8_t *)g_pix;
for (int y = 0; y < sizeY; y++) {
for (int x = 0; x < sizeX; x++) {
if (systemRedShift < systemBlueShift) {
*b++ = *pixU8++; // R
*b++ = *pixU8++; // G
*b++ = *pixU8++; // B
} else {
uint8_t blue = *pixU8++;
uint8_t green = *pixU8++;
uint8_t red = *pixU8++;
*b++ = red;
*b++ = green;
*b++ = blue;
}
}
}
} break;
case 32: {
uint32_t *pixU32 = (uint32_t *)(g_pix + 4 * (w + 1));
for (int y = 0; y < sizeY; y++) {
for (int x = 0; x < sizeX; x++) {
uint32_t v = *pixU32++;
*b++ = ((v >> systemBlueShift) & 0x001f) << 3; // B
*b++ = ((v >> systemGreenShift) & 0x001f) << 3; // G
*b++ = ((v >> systemRedShift) & 0x001f) << 3; // R
}
pixU32++;
}
} break;
}
}
#define CHANNEL_NUM 3 // RGB
bool utilWritePNGFile(const char *fileName, int w, int h, uint8_t *pix)
{
uint8_t *writeBuffer = new uint8_t[w * h * CHANNEL_NUM];
uint8_t *b = writeBuffer;
int sizeX = w;
int sizeY = h;
switch (systemColorDepth)
{
case 16: {
uint16_t *p = (uint16_t *)(pix + (w + 2) * 2); // skip first black line
for (int y = 0; y < sizeY; y++) {
for (int x = 0; x < sizeX; x++) {
uint16_t v = *p++;
*b++ = ((v >> systemRedShift) & 0x001f) << 3; // R
*b++ = ((v >> systemGreenShift) & 0x001f) << 3; // G
*b++ = ((v >> systemBlueShift) & 0x01f) << 3; // B
}
p++; // skip black pixel for filters
p++; // skip black pixel for filters
}
} break;
case 24: {
uint8_t *pixU8 = (uint8_t *)pix;
for (int y = 0; y < sizeY; y++) {
for (int x = 0; x < sizeX; x++) {
if (systemRedShift < systemBlueShift) {
*b++ = *pixU8++; // R
*b++ = *pixU8++; // G
*b++ = *pixU8++; // B
} else {
uint8_t blue = *pixU8++;
uint8_t green = *pixU8++;
uint8_t red = *pixU8++;
*b++ = red;
*b++ = green;
*b++ = blue;
}
}
}
} break;
case 32: {
uint32_t *pixU32 = (uint32_t *)(pix + 4 * (w + 1));
for (int y = 0; y < sizeY; y++) {
for (int x = 0; x < sizeX; x++) {
uint32_t v = *pixU32++;
*b++ = ((v >> systemRedShift) & 0x001f) << 3; // R
*b++ = ((v >> systemGreenShift) & 0x001f) << 3; // G
*b++ = ((v >> systemBlueShift) & 0x001f) << 3; // B
}
pixU32++;
}
} break;
}
bool ret = (0 != stbi_write_png(fileName, w, h, CHANNEL_NUM, writeBuffer, w * CHANNEL_NUM));
delete[] writeBuffer;
return ret;
}
bool utilWriteBMPFile(const char *fileName, int w, int h, uint8_t *pix)
{
uint8_t writeBuffer[512 * 3];
FILE *fp = fopen(fileName, "wb");
if (!fp) {
systemMessage(MSG_ERROR_CREATING_FILE, N_("Error creating file %s"), fileName);
return false;
}
struct {
uint8_t ident[2];
uint8_t filesize[4];
uint8_t reserved[4];
uint8_t dataoffset[4];
uint8_t headersize[4];
uint8_t width[4];
uint8_t height[4];
uint8_t planes[2];
uint8_t bitsperpixel[2];
uint8_t compression[4];
uint8_t datasize[4];
uint8_t hres[4];
uint8_t vres[4];
uint8_t colors[4];
uint8_t importantcolors[4];
// uint8_t pad[2];
} bmpheader;
memset(&bmpheader, 0, sizeof(bmpheader));
bmpheader.ident[0] = 'B';
bmpheader.ident[1] = 'M';
uint32_t fsz = sizeof(bmpheader) + w * h * 3;
utilPutDword(bmpheader.filesize, fsz);
utilPutDword(bmpheader.dataoffset, 0x36);
utilPutDword(bmpheader.headersize, 0x28);
utilPutDword(bmpheader.width, w);
utilPutDword(bmpheader.height, h);
utilPutDword(bmpheader.planes, 1);
utilPutDword(bmpheader.bitsperpixel, 24);
utilPutDword(bmpheader.datasize, 3 * w * h);
fwrite(&bmpheader, 1, sizeof(bmpheader), fp);
uint8_t *b = writeBuffer;
int sizeX = w;
int sizeY = h;
switch (systemColorDepth) {
case 16: {
uint16_t *p = (uint16_t *)(pix + (w + 2) * (h)*2); // skip first black line
for (int y = 0; y < sizeY; y++) {
for (int x = 0; x < sizeX; x++) {
uint16_t v = *p++;
*b++ = ((v >> systemBlueShift) & 0x01f) << 3; // B
*b++ = ((v >> systemGreenShift) & 0x001f) << 3; // G
*b++ = ((v >> systemRedShift) & 0x001f) << 3; // R
}
p++; // skip black pixel for filters
p++; // skip black pixel for filters
p -= 2 * (w + 2);
fwrite(writeBuffer, 1, 3 * w, fp);
b = writeBuffer;
}
} break;
case 24: {
uint8_t *pixU8 = (uint8_t *)pix + 3 * w * (h - 1);
for (int y = 0; y < sizeY; y++) {
for (int x = 0; x < sizeX; x++) {
if (systemRedShift > systemBlueShift) {
*b++ = *pixU8++; // B
*b++ = *pixU8++; // G
*b++ = *pixU8++; // R
} else {
uint8_t red = *pixU8++;
uint8_t green = *pixU8++;
uint8_t blue = *pixU8++;
*b++ = blue;
*b++ = green;
*b++ = red;
}
}
pixU8 -= 2 * 3 * w;
fwrite(writeBuffer, 1, 3 * w, fp);
b = writeBuffer;
}
} break;
case 32: {
uint32_t *pixU32 = (uint32_t *)(pix + 4 * (w + 1) * (h));
for (int y = 0; y < sizeY; y++) {
for (int x = 0; x < sizeX; x++) {
uint32_t v = *pixU32++;
*b++ = ((v >> systemBlueShift) & 0x001f) << 3; // B
*b++ = ((v >> systemGreenShift) & 0x001f) << 3; // G
*b++ = ((v >> systemRedShift) & 0x001f) << 3; // R
}
pixU32++;
pixU32 -= 2 * (w + 1);
fwrite(writeBuffer, 1, 3 * w, fp);
b = writeBuffer;
}
} break;
}
fclose(fp);
return true;
}
bool utilIsGzipFile(const char *file)
{
if (strlen(file) > 3) {
const char *p = strrchr(file, '.');
if (p != NULL) {
if (_stricmp(p, ".gz") == 0)
return true;
if (_stricmp(p, ".z") == 0)
return true;
}
}
return false;
}
// Opens and scans archive using accept(). Returns fex_t if found.
// If error or not found, displays message and returns NULL.
static fex_t *scan_arc(const char *file, bool (*accept)(const char *), char (&buffer)[2048])
{
fex_t *fe;
fex_err_t err = fex_open(&fe, file);
if (!fe) {
systemMessage(MSG_CANNOT_OPEN_FILE, N_("Cannot open file %s: %s"), file, err);
return NULL;
}
// Scan filenames
bool found = false;
while (!fex_done(fe)) {
strncpy(buffer, fex_name(fe), sizeof buffer);
buffer[sizeof buffer - 1] = '\0';
utilStripDoubleExtension(buffer, buffer);
if (accept(buffer)) {
found = true;
break;
}
err = fex_next(fe);
if (err) {
systemMessage(MSG_BAD_ZIP_FILE,
N_("Cannot read archive %s: %s"),
file,
err);
fex_close(fe);
return NULL;
}
}
if (!found) {
systemMessage(MSG_NO_IMAGE_ON_ZIP, N_("No image found in file %s"), file);
fex_close(fe);
return NULL;
}
return fe;
}
static bool utilIsImage(const char *file)
{
return utilIsGBAImage(file) || utilIsGBImage(file);
}
IMAGE_TYPE utilFindType(const char *file, char (&buffer)[2048]);
IMAGE_TYPE utilFindType(const char *file)
{
char buffer[2048];
return utilFindType(file, buffer);
}
IMAGE_TYPE utilFindType(const char *file, char (&buffer)[2048])
{
fex_t *fe = scan_arc(file, utilIsImage, buffer);
if (!fe)
return IMAGE_UNKNOWN;
fex_close(fe);
file = buffer;
return utilIsGBAImage(file) ? IMAGE_GBA : IMAGE_GB;
}
static int utilGetSize(int size)
{
int res = 1;
while (res < size)
res <<= 1;
return res;
}
uint8_t *utilLoad(const char *file, bool (*accept)(const char *), uint8_t *data, int &size)
{
// find image file
char buffer[2048];
fex_t *fe = scan_arc(file, accept, buffer);
if (!fe)
return NULL;
// Allocate space for image
fex_err_t err = fex_stat(fe);
int fileSize = fex_size(fe);
if (size == 0)
size = fileSize;
if (size > MAX_CART_SIZE)
return NULL;
uint8_t *image = data;
if (image == NULL) {
// allocate buffer memory if none was passed to the function
image = (uint8_t *)malloc(utilGetSize(size));
if (image == NULL) {
fex_close(fe);
systemMessage(MSG_OUT_OF_MEMORY,
N_("Failed to allocate memory for %s"),
"data");
return NULL;
}
size = fileSize;
}
// Read image
int read = fileSize <= size ? fileSize : size; // do not read beyond file
err = fex_read(fe, image, read);
fex_close(fe);
if (err) {
systemMessage(MSG_ERROR_READING_IMAGE,
N_("Error reading image from %s: %s"),
buffer,
err);
if (data == NULL)
free(image);
return NULL;
}
size = fileSize;
return image;
}
void replaceAll(std::string &str, const std::string &from, const std::string &to)
{
if (from.empty())
return;
size_t start_pos = 0;
while ((start_pos = str.find(from, start_pos)) != std::string::npos) {
str.replace(start_pos, from.length(), to);
start_pos += to.length(); // In case 'to' contains 'from', like replacing 'x' with
// 'yx'
}
}

View File

@ -1,7 +1,6 @@
#ifndef UTIL_H
#define UTIL_H
#include <cstdint>
#include <string>
#ifdef _WIN32
@ -10,24 +9,9 @@
#define FILE_SEP '/'
#endif
#define FREAD_UNCHECKED(A,B,C,D) (void)(fread(A,B,C,D) + 1)
enum IMAGE_TYPE { IMAGE_UNKNOWN = -1, IMAGE_GBA = 0, IMAGE_GB = 1 };
std::string get_xdg_user_config_home();
std::string get_xdg_user_data_home();
void utilReadScreenPixels(uint8_t *dest, int w, int h);
#ifndef __LIBRETRO__
bool utilWritePNGFile(const char *, int, int, uint8_t *);
bool utilWriteBMPFile(const char *, int, int, uint8_t *);
#endif
bool utilIsGBAImage(const char *);
bool utilIsGBImage(const char *);
IMAGE_TYPE utilFindType(const char *);
uint8_t *utilLoad(const char *, bool (*)(const char *), uint8_t *, int &);
void utilPutDword(uint8_t *, uint32_t);
void utilGBAFindSave(const int);
void utilUpdateSystemColorMaps(bool lcd = false);

View File

@ -2,8 +2,8 @@
#include <cstring>
#include "System.h"
#include "core/base/port.h"
#include "core/base/system.h"
#include "gba/Globals.h"
#include "gba/RTC.h"
#include "gba/gbafilter.h"
@ -12,47 +12,6 @@
#define strcasecmp _stricmp
#endif // defined(_MSC_VER)
bool utilIsGBAImage(const char* file) {
coreOptions.cpuIsMultiBoot = false;
if (strlen(file) > 4) {
const char* p = strrchr(file, '.');
if (p != NULL) {
if ((strcasecmp(p, ".agb") == 0) || (strcasecmp(p, ".gba") == 0) ||
(strcasecmp(p, ".bin") == 0) || (strcasecmp(p, ".elf") == 0))
return true;
if (strcasecmp(p, ".mb") == 0) {
coreOptions.cpuIsMultiBoot = true;
return true;
}
}
}
return false;
}
bool utilIsGBImage(const char* file) {
if (strlen(file) > 4) {
const char* p = strrchr(file, '.');
if (p != NULL) {
if ((strcasecmp(p, ".dmg") == 0) || (strcasecmp(p, ".gb") == 0) ||
(strcasecmp(p, ".gbc") == 0) || (strcasecmp(p, ".cgb") == 0) ||
(strcasecmp(p, ".sgb") == 0))
return true;
}
}
return false;
}
void utilPutDword(uint8_t* p, uint32_t value) {
*p++ = value & 255;
*p++ = (value >> 8) & 255;
*p++ = (value >> 16) & 255;
*p = (value >> 24) & 255;
}
void utilUpdateSystemColorMaps(bool lcd) {
switch (systemColorDepth) {
case 16: {

58
src/Util_desktop.cpp Normal file
View File

@ -0,0 +1,58 @@
#include "Util.h"
#include <cstdlib>
// Get user-specific config dir manually.
// apple: ~/Library/Application Support/
// windows: %APPDATA%/
// unix: ${XDG_CONFIG_HOME:-~/.config}/
std::string get_xdg_user_config_home()
{
std::string path;
#ifdef __APPLE__
std::string home(getenv("HOME"));
path = home + "/Library/Application Support";
#elif _WIN32
char *app_data_env = getenv("LOCALAPPDATA");
if (!app_data_env) app_data_env = getenv("APPDATA");
std::string app_data(app_data_env);
path = app_data;
#else // Unix
char *xdg_var = getenv("XDG_CONFIG_HOME");
if (!xdg_var || !*xdg_var) {
std::string xdg_default(getenv("HOME"));
path = xdg_default + "/.config";
} else {
path = xdg_var;
}
#endif
return path + FILE_SEP;
}
// Get user-specific data dir manually.
// apple: ~/Library/Application Support/
// windows: %APPDATA%/
// unix: ${XDG_DATA_HOME:-~/.local/share}/
std::string get_xdg_user_data_home()
{
std::string path;
#ifdef __APPLE__
std::string home(getenv("HOME"));
path = home + "/Library/Application Support";
#elif _WIN32
char *app_data_env = getenv("LOCALAPPDATA");
if (!app_data_env) app_data_env = getenv("APPDATA");
std::string app_data(app_data_env);
path = app_data;
#else // Unix
char *xdg_var = getenv("XDG_DATA_HOME");
if (!xdg_var || !*xdg_var) {
std::string xdg_default(getenv("HOME"));
path = xdg_default + "/.local/share";
} else {
path = xdg_var;
}
#endif
return path + FILE_SEP;
}

View File

@ -1,64 +0,0 @@
// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
// Copyright (C) 2015 VBA-M development team
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2, or(at your option)
// any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software Foundation,
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#ifndef __VBA_SOUND_DRIVER_H__
#define __VBA_SOUND_DRIVER_H__
#include <stdint.h> // for uint16_t
/**
* Sound driver abstract interface for the core to use to output sound.
* Subclass this to implement a new sound driver.
*/
class SoundDriver
{
public:
/**
* Destructor. Free the resources allocated by the sound driver.
*/
virtual ~SoundDriver(){};
/**
* Initialize the sound driver.
* @param sampleRate In Hertz
*/
virtual bool init(long sampleRate) = 0;
/**
* Tell the driver that the sound stream has paused
*/
virtual void pause() = 0;
/**
* Reset the sound driver
*/
virtual void reset() = 0;
/**
* Tell the driver that the sound stream has resumed
*/
virtual void resume() = 0;
/**
* Write length bytes of data from the finalWave buffer to the driver output buffer.
*/
virtual void write(uint16_t *finalWave, int length) = 0;
virtual void setThrottle(unsigned short throttle) = 0;
};
#endif // __VBA_SOUND_DRIVER_H__

View File

@ -21,7 +21,7 @@
#include <SDL.h>
#include "core/base/ringbuffer.h"
#include "SoundDriver.h"
#include "core/base/sound_driver.h"
class SoundSDL : public SoundDriver {
public:

View File

@ -26,8 +26,9 @@ add_dependencies(vbam-core-base vbam-core-base-generated)
target_sources(vbam-core-base
PRIVATE
file_util.cpp
file_util_common.cpp
file_util_desktop.cpp
image_util.cpp
internal/file_util_internal.cpp
internal/file_util_internal.h
internal/memgzio.c
@ -38,18 +39,23 @@ target_sources(vbam-core-base
PUBLIC
array.h
file_util.h
image_util.h
message.h
patch.h
port.h
ringbuffer.h
sizes.h
sound_driver.h
system.h
version.h
)
target_include_directories(vbam-core-base
PRIVATE ${STB_INCLUDE_DIR}
PUBLIC ${ZLIB_INCLUDE_DIR}
)
target_link_libraries(vbam-core-base
INTERFACE vbam-fex
INTERFACE vbam-fex stb-image
PUBLIC ${ZLIB_LIBRARY}
)

View File

@ -1,137 +0,0 @@
#include "file_util.h"
#if defined(__LIBRETRO__)
#error "This file is only for non-libretro builds"
#endif
#include <cstring>
#include "core/base/internal/file_util_internal.h"
#include "core/base/internal/memgzio.h"
#if defined(_MSC_VER)
#define strcasecmp _stricmp
#endif // defined(_MSC_VER)
namespace {
bool utilIsGzipFile(const char* file) {
if (strlen(file) > 3) {
const char* p = strrchr(file, '.');
if (p != nullptr) {
if (strcasecmp(p, ".gz") == 0)
return true;
if (strcasecmp(p, ".z") == 0)
return true;
}
}
return false;
}
int(ZEXPORT *utilGzWriteFunc)(gzFile, const voidp, unsigned int) = nullptr;
int(ZEXPORT *utilGzReadFunc)(gzFile, voidp, unsigned int) = nullptr;
int(ZEXPORT *utilGzCloseFunc)(gzFile) = nullptr;
z_off_t(ZEXPORT *utilGzSeekFunc)(gzFile, z_off_t, int) = nullptr;
} // namespace
void utilStripDoubleExtension(const char* file, char* buffer) {
if (buffer != file) // allows conversion in place
strcpy(buffer, file);
if (utilIsGzipFile(file)) {
char* p = strrchr(buffer, '.');
if (p)
*p = 0;
}
}
gzFile utilAutoGzOpen(const char* file, const char* mode) {
#if defined(_WIN32)
std::wstring wfile = core::internal::ToUTF16(file);
if (wfile.empty()) {
return nullptr;
}
return gzopen_w(wfile.data(), mode);
#else // !defined(_WIN32)
return gzopen(file, mode);
#endif // defined(_WIN32)
}
gzFile utilGzOpen(const char* file, const char* mode) {
utilGzWriteFunc = (int(ZEXPORT*)(gzFile, void* const, unsigned int))gzwrite;
utilGzReadFunc = gzread;
utilGzCloseFunc = gzclose;
utilGzSeekFunc = gzseek;
return utilAutoGzOpen(file, mode);
}
gzFile utilMemGzOpen(char* memory, int available, const char* mode) {
utilGzWriteFunc = memgzwrite;
utilGzReadFunc = memgzread;
utilGzCloseFunc = memgzclose;
utilGzSeekFunc = memgzseek;
return memgzopen(memory, available, mode);
}
int utilGzWrite(gzFile file, const voidp buffer, unsigned int len) {
return utilGzWriteFunc(file, buffer, len);
}
int utilGzRead(gzFile file, voidp buffer, unsigned int len) {
return utilGzReadFunc(file, buffer, len);
}
int utilGzClose(gzFile file) {
return utilGzCloseFunc(file);
}
z_off_t utilGzSeek(gzFile file, z_off_t offset, int whence) {
return utilGzSeekFunc(file, offset, whence);
}
long utilGzMemTell(gzFile file) {
return memtell(file);
}
void utilWriteData(gzFile gzFile, variable_desc* data) {
while (data->address) {
utilGzWrite(gzFile, data->address, data->size);
data++;
}
}
void utilReadData(gzFile gzFile, variable_desc* data) {
while (data->address) {
utilGzRead(gzFile, data->address, data->size);
data++;
}
}
void utilReadDataSkip(gzFile gzFile, variable_desc* data) {
while (data->address) {
utilGzSeek(gzFile, data->size, SEEK_CUR);
data++;
}
}
int utilReadInt(gzFile gzFile) {
int i = 0;
utilGzRead(gzFile, &i, sizeof(int));
return i;
}
void utilWriteInt(gzFile gzFile, int i) {
utilGzWrite(gzFile, &i, sizeof(int));
}

View File

@ -2,6 +2,7 @@
#define VBAM_CORE_BASE_FILE_UTIL_H_
#include <cstdio>
#include <cstdint>
#if defined(__LIBRETRO__)
#include <cstdint>
@ -9,13 +10,22 @@
#include <zlib.h>
#endif // defined(__LIBRETRO__)
#include "core/base/system.h"
#define FREAD_UNCHECKED(A,B,C,D) (void)(fread(A,B,C,D) + 1)
// save game
typedef struct {
void *address;
int size;
} variable_desc;
void utilPutDword(uint8_t *, uint32_t);
FILE* utilOpenFile(const char *filename, const char *mode);
uint8_t *utilLoad(const char *, bool (*)(const char *), uint8_t *, int &);
IMAGE_TYPE utilFindType(const char *);
bool utilIsGBAImage(const char *);
bool utilIsGBImage(const char *);
#if defined(__LIBRETRO__)

View File

@ -1,7 +1,20 @@
#include "file_util.h"
#include <cstring>
#include "core/base/internal/file_util_internal.h"
#if defined(_MSC_VER)
#define strcasecmp _stricmp
#endif // defined(_MSC_VER)
void utilPutDword(uint8_t* p, uint32_t value) {
*p++ = value & 255;
*p++ = (value >> 8) & 255;
*p++ = (value >> 16) & 255;
*p = (value >> 24) & 255;
}
FILE* utilOpenFile(const char* filename, const char* mode) {
#ifdef _WIN32
std::wstring wfilename = core::internal::ToUTF16(filename);
@ -19,3 +32,37 @@ FILE* utilOpenFile(const char* filename, const char* mode) {
return fopen(filename, mode);
#endif // _WIN32
}
bool utilIsGBAImage(const char* file) {
coreOptions.cpuIsMultiBoot = false;
if (strlen(file) > 4) {
const char* p = strrchr(file, '.');
if (p != nullptr) {
if ((strcasecmp(p, ".agb") == 0) || (strcasecmp(p, ".gba") == 0) ||
(strcasecmp(p, ".bin") == 0) || (strcasecmp(p, ".elf") == 0))
return true;
if (strcasecmp(p, ".mb") == 0) {
coreOptions.cpuIsMultiBoot = true;
return true;
}
}
}
return false;
}
bool utilIsGBImage(const char* file) {
if (strlen(file) > 4) {
const char* p = strrchr(file, '.');
if (p != nullptr) {
if ((strcasecmp(p, ".dmg") == 0) || (strcasecmp(p, ".gb") == 0) ||
(strcasecmp(p, ".gbc") == 0) || (strcasecmp(p, ".cgb") == 0) ||
(strcasecmp(p, ".sgb") == 0))
return true;
}
}
return false;
}

View File

@ -0,0 +1,252 @@
#include "file_util.h"
#if defined(__LIBRETRO__)
#error "This file is only for non-libretro builds"
#endif
#include <cstdlib>
#include <cstring>
#include "core/base/internal/file_util_internal.h"
#include "core/base/internal/memgzio.h"
#include "core/base/message.h"
#include "core/fex/fex.h"
#if defined(_MSC_VER)
#define strcasecmp _stricmp
#endif // defined(_MSC_VER)
#define MAX_CART_SIZE 0x8000000 // 128MB
namespace {
bool utilIsGzipFile(const char* file) {
if (strlen(file) > 3) {
const char* p = strrchr(file, '.');
if (p != nullptr) {
if (strcasecmp(p, ".gz") == 0)
return true;
if (strcasecmp(p, ".z") == 0)
return true;
}
}
return false;
}
// Opens and scans archive using accept(). Returns fex_t if found.
// If error or not found, displays message and returns nullptr.
fex_t* scanArchive(const char* file, bool (*accept)(const char*), char (&buffer)[2048]) {
fex_t* fe;
fex_err_t err = fex_open(&fe, file);
if (!fe) {
systemMessage(MSG_CANNOT_OPEN_FILE, N_("Cannot open file %s: %s"), file, err);
return nullptr;
}
// Scan filenames
bool found = false;
while (!fex_done(fe)) {
strncpy(buffer, fex_name(fe), sizeof buffer);
buffer[sizeof buffer - 1] = '\0';
utilStripDoubleExtension(buffer, buffer);
if (accept(buffer)) {
found = true;
break;
}
err = fex_next(fe);
if (err) {
systemMessage(MSG_BAD_ZIP_FILE, N_("Cannot read archive %s: %s"), file, err);
fex_close(fe);
return nullptr;
}
}
if (!found) {
systemMessage(MSG_NO_IMAGE_ON_ZIP, N_("No image found in file %s"), file);
fex_close(fe);
return nullptr;
}
return fe;
}
bool utilIsImage(const char* file) {
return utilIsGBAImage(file) || utilIsGBImage(file);
}
int utilGetSize(int size) {
int res = 1;
while (res < size)
res <<= 1;
return res;
}
IMAGE_TYPE utilFindType(const char* file, char (&buffer)[2048]) {
fex_t* fe = scanArchive(file, utilIsImage, buffer);
if (!fe) {
return IMAGE_UNKNOWN;
}
fex_close(fe);
file = buffer;
return utilIsGBAImage(file) ? IMAGE_GBA : IMAGE_GB;
}
int(ZEXPORT* utilGzWriteFunc)(gzFile, const voidp, unsigned int) = nullptr;
int(ZEXPORT* utilGzReadFunc)(gzFile, voidp, unsigned int) = nullptr;
int(ZEXPORT* utilGzCloseFunc)(gzFile) = nullptr;
z_off_t(ZEXPORT* utilGzSeekFunc)(gzFile, z_off_t, int) = nullptr;
} // namespace
uint8_t* utilLoad(const char* file, bool (*accept)(const char*), uint8_t* data, int& size) {
// find image file
char buffer[2048];
fex_t* fe = scanArchive(file, accept, buffer);
if (!fe)
return nullptr;
// Allocate space for image
fex_err_t err = fex_stat(fe);
int fileSize = fex_size(fe);
if (size == 0)
size = fileSize;
if (size > MAX_CART_SIZE)
return nullptr;
uint8_t* image = data;
if (image == nullptr) {
// allocate buffer memory if none was passed to the function
image = (uint8_t*)malloc(utilGetSize(size));
if (image == nullptr) {
fex_close(fe);
systemMessage(MSG_OUT_OF_MEMORY, N_("Failed to allocate memory for %s"), "data");
return nullptr;
}
size = fileSize;
}
// Read image
int read = fileSize <= size ? fileSize : size; // do not read beyond file
err = fex_read(fe, image, read);
fex_close(fe);
if (err) {
systemMessage(MSG_ERROR_READING_IMAGE, N_("Error reading image from %s: %s"), buffer, err);
if (data == nullptr)
free(image);
return nullptr;
}
size = fileSize;
return image;
}
IMAGE_TYPE utilFindType(const char* file) {
char buffer[2048];
return utilFindType(file, buffer);
}
void utilStripDoubleExtension(const char* file, char* buffer) {
if (buffer != file) // allows conversion in place
strcpy(buffer, file);
if (utilIsGzipFile(file)) {
char* p = strrchr(buffer, '.');
if (p)
*p = 0;
}
}
gzFile utilAutoGzOpen(const char* file, const char* mode) {
#if defined(_WIN32)
std::wstring wfile = core::internal::ToUTF16(file);
if (wfile.empty()) {
return nullptr;
}
return gzopen_w(wfile.data(), mode);
#else // !defined(_WIN32)
return gzopen(file, mode);
#endif // defined(_WIN32)
}
gzFile utilGzOpen(const char* file, const char* mode) {
utilGzWriteFunc = (int(ZEXPORT*)(gzFile, void* const, unsigned int))gzwrite;
utilGzReadFunc = gzread;
utilGzCloseFunc = gzclose;
utilGzSeekFunc = gzseek;
return utilAutoGzOpen(file, mode);
}
gzFile utilMemGzOpen(char* memory, int available, const char* mode) {
utilGzWriteFunc = memgzwrite;
utilGzReadFunc = memgzread;
utilGzCloseFunc = memgzclose;
utilGzSeekFunc = memgzseek;
return memgzopen(memory, available, mode);
}
int utilGzWrite(gzFile file, const voidp buffer, unsigned int len) {
return utilGzWriteFunc(file, buffer, len);
}
int utilGzRead(gzFile file, voidp buffer, unsigned int len) {
return utilGzReadFunc(file, buffer, len);
}
int utilGzClose(gzFile file) {
return utilGzCloseFunc(file);
}
z_off_t utilGzSeek(gzFile file, z_off_t offset, int whence) {
return utilGzSeekFunc(file, offset, whence);
}
long utilGzMemTell(gzFile file) {
return memtell(file);
}
void utilWriteData(gzFile gzFile, variable_desc* data) {
while (data->address) {
utilGzWrite(gzFile, data->address, data->size);
data++;
}
}
void utilReadData(gzFile gzFile, variable_desc* data) {
while (data->address) {
utilGzRead(gzFile, data->address, data->size);
data++;
}
}
void utilReadDataSkip(gzFile gzFile, variable_desc* data) {
while (data->address) {
utilGzSeek(gzFile, data->size, SEEK_CUR);
data++;
}
}
int utilReadInt(gzFile gzFile) {
int i = 0;
utilGzRead(gzFile, &i, sizeof(int));
return i;
}
void utilWriteInt(gzFile gzFile, int i) {
utilGzWrite(gzFile, &i, sizeof(int));
}

View File

@ -4,8 +4,58 @@
#error "This file is only for libretro builds"
#endif
#include <cstdlib>
#include <cstring>
IMAGE_TYPE utilFindType(const char* file) {
if (utilIsGBAImage(file))
return IMAGE_GBA;
if (utilIsGBImage(file))
return IMAGE_GB;
return IMAGE_UNKNOWN;
}
static int utilGetSize(int size) {
int res = 1;
while (res < size)
res <<= 1;
return res;
}
uint8_t* utilLoad(const char* file, bool (*)(const char*), uint8_t* data, int& size) {
FILE* fp = nullptr;
fp = fopen(file, "rb");
if (!fp) {
log("Failed to open file %s", file);
return nullptr;
}
fseek(fp, 0, SEEK_END); // go to end
size = ftell(fp); // get position at end (length)
rewind(fp);
uint8_t* image = data;
if (image == nullptr) {
image = (uint8_t*)malloc(utilGetSize(size));
if (image == nullptr) {
log("Failed to allocate memory for %s", file);
return nullptr;
}
}
if (fread(image, 1, size, fp) != (size_t)size) {
log("Failed to read from %s", file);
fclose(fp);
return nullptr;
}
fclose(fp);
return image;
}
// Not endian safe, but VBA itself doesn't seem to care, so hey <_<
void utilWriteIntMem(uint8_t*& data, int val) {
memcpy(data, &val, sizeof(int));

View File

@ -0,0 +1,193 @@
#include "image_util.h"
#define STB_IMAGE_IMPLEMENTATION
#define STB_IMAGE_WRITE_IMPLEMENTATION
extern "C" {
#include <stb_image_write.h>
} // extern "C"
#include "core/base/file_util.h"
#include "core/base/system.h"
#include "core/base/message.h"
bool utilWritePNGFile(const char* fileName, int w, int h, uint8_t* pix) {
static constexpr size_t kNumChannels = 3;
uint8_t* writeBuffer = new uint8_t[w * h * kNumChannels];
uint8_t* b = writeBuffer;
int sizeX = w;
int sizeY = h;
switch (systemColorDepth) {
case 16: {
uint16_t* p = (uint16_t*)(pix + (w + 2) * 2); // skip first black line
for (int y = 0; y < sizeY; y++) {
for (int x = 0; x < sizeX; x++) {
uint16_t v = *p++;
*b++ = ((v >> systemRedShift) & 0x001f) << 3; // R
*b++ = ((v >> systemGreenShift) & 0x001f) << 3; // G
*b++ = ((v >> systemBlueShift) & 0x01f) << 3; // B
}
p++; // skip black pixel for filters
p++; // skip black pixel for filters
}
} break;
case 24: {
uint8_t* pixU8 = (uint8_t*)pix;
for (int y = 0; y < sizeY; y++) {
for (int x = 0; x < sizeX; x++) {
if (systemRedShift < systemBlueShift) {
*b++ = *pixU8++; // R
*b++ = *pixU8++; // G
*b++ = *pixU8++; // B
} else {
uint8_t blue = *pixU8++;
uint8_t green = *pixU8++;
uint8_t red = *pixU8++;
*b++ = red;
*b++ = green;
*b++ = blue;
}
}
}
} break;
case 32: {
uint32_t* pixU32 = (uint32_t*)(pix + 4 * (w + 1));
for (int y = 0; y < sizeY; y++) {
for (int x = 0; x < sizeX; x++) {
uint32_t v = *pixU32++;
*b++ = ((v >> systemRedShift) & 0x001f) << 3; // R
*b++ = ((v >> systemGreenShift) & 0x001f) << 3; // G
*b++ = ((v >> systemBlueShift) & 0x001f) << 3; // B
}
pixU32++;
}
} break;
}
bool ret = (0 != stbi_write_png(fileName, w, h, kNumChannels, writeBuffer, w * kNumChannels));
delete[] writeBuffer;
return ret;
}
bool utilWriteBMPFile(const char* fileName, int w, int h, uint8_t* pix) {
uint8_t writeBuffer[512 * 3];
FILE* fp = fopen(fileName, "wb");
if (!fp) {
systemMessage(MSG_ERROR_CREATING_FILE, N_("Error creating file %s"), fileName);
return false;
}
struct {
uint8_t ident[2];
uint8_t filesize[4];
uint8_t reserved[4];
uint8_t dataoffset[4];
uint8_t headersize[4];
uint8_t width[4];
uint8_t height[4];
uint8_t planes[2];
uint8_t bitsperpixel[2];
uint8_t compression[4];
uint8_t datasize[4];
uint8_t hres[4];
uint8_t vres[4];
uint8_t colors[4];
uint8_t importantcolors[4];
// uint8_t pad[2];
} bmpheader;
memset(&bmpheader, 0, sizeof(bmpheader));
bmpheader.ident[0] = 'B';
bmpheader.ident[1] = 'M';
uint32_t fsz = sizeof(bmpheader) + w * h * 3;
utilPutDword(bmpheader.filesize, fsz);
utilPutDword(bmpheader.dataoffset, 0x36);
utilPutDword(bmpheader.headersize, 0x28);
utilPutDword(bmpheader.width, w);
utilPutDword(bmpheader.height, h);
utilPutDword(bmpheader.planes, 1);
utilPutDword(bmpheader.bitsperpixel, 24);
utilPutDword(bmpheader.datasize, 3 * w * h);
fwrite(&bmpheader, 1, sizeof(bmpheader), fp);
uint8_t* b = writeBuffer;
int sizeX = w;
int sizeY = h;
switch (systemColorDepth) {
case 16: {
uint16_t* p = (uint16_t*)(pix + (w + 2) * (h) * 2); // skip first black line
for (int y = 0; y < sizeY; y++) {
for (int x = 0; x < sizeX; x++) {
uint16_t v = *p++;
*b++ = ((v >> systemBlueShift) & 0x01f) << 3; // B
*b++ = ((v >> systemGreenShift) & 0x001f) << 3; // G
*b++ = ((v >> systemRedShift) & 0x001f) << 3; // R
}
p++; // skip black pixel for filters
p++; // skip black pixel for filters
p -= 2 * (w + 2);
fwrite(writeBuffer, 1, 3 * w, fp);
b = writeBuffer;
}
} break;
case 24: {
uint8_t* pixU8 = (uint8_t*)pix + 3 * w * (h - 1);
for (int y = 0; y < sizeY; y++) {
for (int x = 0; x < sizeX; x++) {
if (systemRedShift > systemBlueShift) {
*b++ = *pixU8++; // B
*b++ = *pixU8++; // G
*b++ = *pixU8++; // R
} else {
uint8_t red = *pixU8++;
uint8_t green = *pixU8++;
uint8_t blue = *pixU8++;
*b++ = blue;
*b++ = green;
*b++ = red;
}
}
pixU8 -= 2 * 3 * w;
fwrite(writeBuffer, 1, 3 * w, fp);
b = writeBuffer;
}
} break;
case 32: {
uint32_t* pixU32 = (uint32_t*)(pix + 4 * (w + 1) * (h));
for (int y = 0; y < sizeY; y++) {
for (int x = 0; x < sizeX; x++) {
uint32_t v = *pixU32++;
*b++ = ((v >> systemBlueShift) & 0x001f) << 3; // B
*b++ = ((v >> systemGreenShift) & 0x001f) << 3; // G
*b++ = ((v >> systemRedShift) & 0x001f) << 3; // R
}
pixU32++;
pixU32 -= 2 * (w + 1);
fwrite(writeBuffer, 1, 3 * w, fp);
b = writeBuffer;
}
} break;
}
fclose(fp);
return true;
}

View File

@ -0,0 +1,13 @@
#ifndef VBAM_CORE_BASE_IMAGE_UTIL_H_
#define VBAM_CORE_BASE_IMAGE_UTIL_H_
#if defined(__LIBRETRO__)
#error "This file is not meant for compilation in libretro builds."
#endif // defined(__LIBRETRO__)
#include <cstdint>
bool utilWritePNGFile(const char*, int, int, uint8_t*);
bool utilWriteBMPFile(const char*, int, int, uint8_t*);
#endif // VBAM_CORE_BASE_IMAGE_UTIL_H_

View File

@ -0,0 +1,48 @@
// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
// Copyright (C) 2015 VBA-M development team
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2, or(at your option)
// any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software Foundation,
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#ifndef VBAM_CORE_BASE_SOUND_DRIVER_H_
#define VBAM_CORE_BASE_SOUND_DRIVER_H_
#include <cstdint>
// Sound driver abstract interface for the core to use to output sound.
// Subclass this to implement a new sound driver.
class SoundDriver {
public:
virtual ~SoundDriver() = default;
// Initialize the sound driver. `sampleRate` in Hertz.
// Returns true if the driver was successfully initialized.
virtual bool init(long sampleRate) = 0;
// Pause the sound driver.
virtual void pause() = 0;
// Reset the sound driver.
virtual void reset() = 0;
// Resume the sound driver, following a pause.
virtual void resume() = 0;
// Write length bytes of data from the finalWave buffer to the driver output buffer.
virtual void write(uint16_t* finalWave, int length) = 0;
virtual void setThrottle(unsigned short throttle) = 0;
};
#endif // VBAM_CORE_BASE_SOUND_DRIVER_H_

View File

@ -1,50 +1,55 @@
#ifndef SYSTEM_H
#define SYSTEM_H
#ifndef VBAM_CORE_BASE_SYSTEM_H_
#define VBAM_CORE_BASE_SYSTEM_H_
#include <cstdint>
#include "core/base/message.h"
class SoundDriver;
struct EmulatedSystem {
// main emulation function
void (*emuMain)(int);
// reset emulator
void (*emuReset)();
// clean up memory
void (*emuCleanUp)();
// load battery file
bool (*emuReadBattery)(const char *);
// write battery file
bool (*emuWriteBattery)(const char *);
#ifdef __LIBRETRO__
// load state
bool (*emuReadState)(const uint8_t *);
// load state
unsigned (*emuWriteState)(uint8_t *);
#else
// load state
bool (*emuReadState)(const char *);
// save state
bool (*emuWriteState)(const char *);
#endif
// load memory state (rewind)
bool (*emuReadMemState)(char *, int);
// write memory state (rewind)
bool (*emuWriteMemState)(char *, int, long &);
// write PNG file
bool (*emuWritePNG)(const char *);
// write BMP file
bool (*emuWriteBMP)(const char *);
// emulator update CPSR (ARM only)
void (*emuUpdateCPSR)();
// emulator has debugger
bool emuHasDebugger;
// clock ticks to emulate
int emuCount;
enum IMAGE_TYPE {
IMAGE_UNKNOWN = -1,
IMAGE_GBA = 0,
IMAGE_GB = 1
};
struct EmulatedSystem {
// main emulation function
void (*emuMain)(int);
// reset emulator
void (*emuReset)();
// clean up memory
void (*emuCleanUp)();
// load battery file
bool (*emuReadBattery)(const char*);
// write battery file
bool (*emuWriteBattery)(const char*);
#ifdef __LIBRETRO__
// load state
bool (*emuReadState)(const uint8_t*);
// load state
unsigned (*emuWriteState)(uint8_t*);
#else
// load state
bool (*emuReadState)(const char*);
// save state
bool (*emuWriteState)(const char*);
#endif
// load memory state (rewind)
bool (*emuReadMemState)(char*, int);
// write memory state (rewind)
bool (*emuWriteMemState)(char*, int, long&);
// write PNG file
bool (*emuWritePNG)(const char*);
// write BMP file
bool (*emuWriteBMP)(const char*);
// emulator update CPSR (ARM only)
void (*emuUpdateCPSR)();
// emulator has debugger
bool emuHasDebugger;
// clock ticks to emulate
int emuCount;
};
// The `coreOptions` object must be instantiated by the embedder.
extern struct CoreOptions {
bool cpuIsMultiBoot = false;
bool mirroringEnable = true;
@ -67,13 +72,14 @@ extern struct CoreOptions {
uint32_t speedup_throttle = 100;
uint32_t speedup_frame_skip = 9;
uint32_t throttle = 100;
const char *loadDotCodeFile = nullptr;
const char *saveDotCodeFile = nullptr;
const char* loadDotCodeFile = nullptr;
const char* saveDotCodeFile = nullptr;
} coreOptions;
extern void log(const char *, ...);
// The following functions must be implemented by the emulator.
extern void log(const char*, ...);
extern bool systemPauseOnFrame();
extern void systemGbPrint(uint8_t *, int, int, int, int, int);
extern void systemGbPrint(uint8_t*, int, int, int, int, int);
extern void systemScreenCapture(int);
extern void systemDrawScreen();
extern void systemSendScreen();
@ -82,11 +88,11 @@ extern bool systemReadJoypads();
// return information about the given joystick, -1 for default joystick
extern uint32_t systemReadJoypad(int);
extern uint32_t systemGetClock();
extern void systemSetTitle(const char *);
extern SoundDriver *systemSoundInit();
extern void systemOnWriteDataToSoundBuffer(const uint16_t *finalWave, int length);
extern void systemSetTitle(const char*);
extern SoundDriver* systemSoundInit();
extern void systemOnWriteDataToSoundBuffer(const uint16_t* finalWave, int length);
extern void systemOnSoundShutdown();
extern void systemScreenMessage(const char *);
extern void systemScreenMessage(const char*);
extern void systemUpdateMotionSensor();
extern int systemGetSensorX();
extern int systemGetSensorY();
@ -100,7 +106,7 @@ extern void systemShowSpeed(int);
extern void system10Frames();
extern void systemFrame();
extern void systemGbBorderOn();
extern void (*dbgOutput)(const char *s, uint32_t addr);
extern void (*dbgOutput)(const char* s, uint32_t addr);
extern void (*dbgSignal)(int sig, int number);
extern uint16_t systemColorMap16[0x10000];
extern uint32_t systemColorMap32[0x10000];
@ -113,7 +119,9 @@ extern int systemVerbose;
extern int systemFrameSkip;
extern int systemSaveUpdateCounter;
extern int systemSpeed;
#define MAX_CHEATS 16384
#define SYSTEM_SAVE_UPDATED 30
#define SYSTEM_SAVE_NOT_UPDATED 0
#endif // SYSTEM_H
#endif // VBAM_CORE_BASE_SYSTEM_H_

View File

@ -1,4 +1,4 @@
#include "../System.h"
#include "core/base/system.h"
extern int RGB_LOW_BITS_MASK;

View File

@ -35,7 +35,7 @@
* - the whole source code of the program is released with the binary.
*/
#include "../System.h"
#include <cstdint>
#ifdef MMX
extern "C" bool cpu_mmx;

View File

@ -4,7 +4,7 @@
** Written: 6/14/00 - JSF
**/
#include "../System.h"
#include "core/base/system.h"
#define RGB(r,g,b) ((r)>>3) << systemRedShift |\
((g) >> 3) << systemGreenShift |\

View File

@ -27,7 +27,7 @@
* file, but you are not obligated to do so. If you do not wish to
* do so, delete this exception statement from your version.
*/
#include "../System.h"
#include "interp.h"
/***************************************************************************/

View File

@ -1,9 +1,7 @@
#include "../System.h"
#include <stdlib.h>
#include <memory.h>
#include "interframe.hpp"
#include <cstdlib>
#ifdef MMX
extern "C" bool cpu_mmx;
#endif

View File

@ -3,6 +3,8 @@
#ifndef INTERFRAME_HPP
#define INTERFRAME_HPP
#include <cstdint>
extern int RGB_LOW_BITS_MASK;
void InterframeFilterInit();

View File

@ -1,4 +1,4 @@
#include "../System.h"
#include <cstdint>
extern int RGB_LOW_BITS_MASK;

View File

@ -1,4 +1,4 @@
#include "../System.h"
#include <cstdint>
extern int RGB_LOW_BITS_MASK;

View File

@ -1,4 +1,4 @@
#include "../System.h"
#include <cstdint>
void Simple2x16(uint8_t *srcPtr, uint32_t srcPitch, uint8_t * /* deltaPtr */,
uint8_t *dstPtr, uint32_t dstPitch, int width, int height)

View File

@ -1,4 +1,4 @@
#include "../System.h"
#include <cstdint>
#include "xBRZ/xbrz.h"

View File

@ -8,12 +8,12 @@
#include <cstring>
#include <vector>
#include "core/base/file_util.h"
#include "core/base/sizes.h"
#include "../System.h"
#include "../Util.h"
#include "../gba/GBALink.h"
#include "../gba/Sound.h"
#include "core/base/file_util.h"
#include "core/base/message.h"
#include "core/base/sizes.h"
#include "core/base/system.h"
#include "gbCheats.h"
#include "gbGlobals.h"
#include "gbMemory.h"
@ -21,6 +21,7 @@
#include "gbSound.h"
#if !defined(__LIBRETRO__)
#include "core/base/image_util.h"
#include "core/base/patch.h"
#endif // defined(__LIBRETRO__)

View File

@ -1,14 +1,14 @@
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "gbCheats.h"
#include "../System.h"
#include "../Util.h"
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include "core/base/message.h"
#include "core/base/system.h"
#include "core/base/file_util.h"
#include "gb.h"
#include "gbCheats.h"
#include "gbGlobals.h"
gbCheat gbCheatList[MAX_CHEATS];

View File

@ -7,7 +7,7 @@
#include <zlib.h>
#endif // defined(__LIBRETRO__)
#include "../System.h"
#include "core/base/system.h"
struct gbXxCheat {
char cheatDesc[100];

View File

@ -1,7 +1,5 @@
#include <stdio.h>
#include <string.h>
#include <cstdio>
#include "../System.h"
#include "gbGlobals.h"
typedef struct {

View File

@ -1,6 +1,6 @@
#include <memory.h>
#include "../System.h"
#include "core/base/system.h"
#include "gbGlobals.h"
#include "gbSGB.h"

View File

@ -2,11 +2,12 @@
#include <cstdint>
#include "../System.h"
#include "core/base/port.h"
#include "core/base/sizes.h"
#include "core/base/system.h"
#include "gb.h"
#include "gbGlobals.h"
uint8_t gbDaysinMonth[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
extern int gbGBCColorType;
extern gbRegister PC;

View File

@ -1,6 +1,9 @@
#include "../System.h"
#include <memory.h>
#include <stdio.h>
#include "gbPrinter.h"
#include <cstdint>
#include <cstring>
#include "core/base/system.h"
uint8_t gbPrinterStatus = 0;
int gbPrinterState = 0;

View File

@ -1,7 +1,7 @@
#ifndef GBPRINTER_H
#define GBPRINTER_H
#include "../System.h"
#include <cstdint>
uint8_t gbPrinterSend(uint8_t b);

View File

@ -3,7 +3,7 @@
#include "core/base/file_util.h"
#include "core/base/port.h"
#include "../System.h"
#include "core/base/system.h"
#include "gb.h"
#include "gbGlobals.h"

View File

@ -2,7 +2,7 @@
#include <cstring>
#include "../System.h"
#include "core/base/system.h"
#include "core/base/file_util.h"
#include "../gba/Sound.h"
#include "gb.h"

View File

@ -1,7 +1,7 @@
#ifndef CHEATSEARCH_H
#define CHEATSEARCH_H
#include "../System.h"
#include <cstdint>
struct CheatSearchBlock {
int size;

View File

@ -1,11 +1,10 @@
#include <ctype.h>
#include <memory.h>
#include <stdio.h>
#include <string.h>
#include "Cheats.h"
#include <cstdio>
#include <cstring>
#include "core/base/file_util.h"
#include "../Util.h"
#include "Cheats.h"
#include "core/base/message.h"
#include "GBA.h"
#include "GBAinline.h"
#include "Globals.h"

View File

@ -3,7 +3,7 @@
#include <cstdint>
#include "../System.h"
#include "core/base/system.h"
#if !defined(__LIBRETRO__)
#include <zlib.h>

View File

@ -1,23 +1,7 @@
#include <memory.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "../System.h"
#include "../Util.h"
#include "Cheats.h"
#include "EEprom.h"
#include "Flash.h"
#include "GBA.h"
#include "GBAcpu.h"
#include "GBAinline.h"
#include "Globals.h"
#include "Sound.h"
#include "Sram.h"
#include "agbprint.h"
#include "bios.h"
#include "elf.h"
#include "remote.h"
#ifdef PROFILING

View File

@ -1,26 +1,15 @@
#include <memory.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#ifndef _MSC_VER
#include <strings.h>
#endif
#include "../System.h"
#include "../Util.h"
#include "Cheats.h"
#include "EEprom.h"
#include "Flash.h"
#include "GBA.h"
#include "GBAcpu.h"
#include "GBAinline.h"
#include "Globals.h"
#include "Sound.h"
#include "Sram.h"
#include "agbprint.h"
#include "bios.h"
#include "elf.h"
#include "remote.h"
#ifdef PROFILING

View File

@ -10,8 +10,8 @@
#endif
#include "core/base/file_util.h"
#include "../System.h"
#include "../Util.h"
#include "core/base/message.h"
#include "core/base/system.h"
#include "core/base/port.h"
#include "core/base/sizes.h"
#include "Cheats.h"
@ -30,6 +30,10 @@
#include "elf.h"
#include "ereader.h"
#if !defined(__LIBRETRO__)
#include "core/base/image_util.h"
#endif // !__LIBRETRO__
#ifdef PROFILING
#include "prof/prof.h"
#endif

View File

@ -3,8 +3,7 @@
#include <cstdint>
#include "../System.h"
#include "../Util.h"
#include "core/base/system.h"
const uint64_t TICKS_PER_SECOND = 16777216;

View File

@ -1,6 +1,8 @@
#include <string.h>
#include "GBAGfx.h"
#include "../System.h"
#if defined(TILED_RENDERING)
#include <cstring>
#endif // defined(TILED_RENDERING)
int g_coeff[32] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,

View File

@ -3,7 +3,7 @@
#include <type_traits>
#include "../System.h"
#include "core/base/system.h"
#include "core/base/port.h"
#include "GBALink.h"
#include "GBAcpu.h"

View File

@ -1,13 +1,15 @@
#include "../System.h"
#include "RTC.h"
#include <cstring>
#include <ctime>
#include "core/base/file_util.h"
#include "core/base/message.h"
#include "core/base/port.h"
#include "GBA.h"
#include "GBAinline.h"
#include "Globals.h"
#include "core/base/file_util.h"
#include <memory.h>
#include <string.h>
#include <time.h>
enum RTCSTATE {
IDLE = 0,

View File

@ -5,14 +5,13 @@
#include "core/base/file_util.h"
#include "core/base/port.h"
#include "core/base/sound_driver.h"
#include "GBA.h"
#include "Globals.h"
#include "../apu/Gb_Apu.h"
#include "../apu/Multi_Buffer.h"
#include "../common/SoundDriver.h"
#define NR10 0x60
#define NR11 0x62
#define NR12 0x63

View File

@ -1,8 +1,6 @@
#include <stdio.h>
#include <string.h>
#include "agbprint.h"
#include "core/base/port.h"
#include "../System.h"
#include "GBA.h"
#include "Globals.h"

View File

@ -1,6 +1,8 @@
#ifndef AGBPRINT_H
#define AGBPRINT_H
#include <cstdint>
void agbPrintEnable(bool enable);
bool agbPrintIsEnabled();
void agbPrintReset();

View File

@ -1,11 +1,11 @@
#include "armdis.h"
/************************************************************************/
/* Arm/Thumb command set disassembler */
/************************************************************************/
#include <stdio.h>
#include <cstring>
#include "core/base/port.h"
#include "../System.h"
#include "GBA.h"
#include "armdis.h"
#include "elf.h"

View File

@ -78,13 +78,11 @@
#include <stdio.h>
#include "../System.h"
#include "GBA.h"
#include "core/base/port.h"
#include <string>
#include <map>
#include <iostream>
unsigned int dexp_result = 0;
extern int dexp_error(const char *);

View File

@ -1,13 +1,11 @@
%{
#include <stdio.h>
#include "../System.h"
#include "GBA.h"
#include "core/base/port.h"
#include <string>
#include <map>
#include <iostream>
unsigned int dexp_result = 0;
extern int dexp_error(const char *);

View File

@ -2,6 +2,7 @@
#include <stdlib.h>
#include <string.h>
#include "core/base/message.h"
#include "core/base/port.h"
#include "GBA.h"
#include "elf.h"

View File

@ -1,6 +1,9 @@
#ifndef ELF_H
#define ELF_H
#include <cstdint>
#include <cstdio>
enum LocationType { LOCATION_register,
LOCATION_memory,
LOCATION_value };

View File

@ -1,5 +1,10 @@
#include "../System.h"
#ifndef VBAM_GBA_GBAFILTER_H_
#define VBAM_GBA_GBAFILTER_H_
#include <cstdint>
void gbafilter_pal(uint16_t* buf, int count);
void gbafilter_pal32(uint32_t* buf, int count);
void gbafilter_pad(uint8_t* buf, int count);
#endif // VBAM_GBA_GBAFILTER_H_

View File

@ -22,7 +22,6 @@ SOURCES_CXX += \
SOURCES_CXX += \
$(CORE_DIR)/libretro/libretro.cpp \
$(CORE_DIR)/libretro/UtilRetro.cpp \
$(CORE_DIR)/libretro/SoundRetro.cpp
SOURCES_CXX += \

View File

@ -18,7 +18,7 @@
#ifndef __VBA_SOUND_RETRO_H__
#define __VBA_SOUND_RETRO_H__
#include "../common/SoundDriver.h"
#include "core/base/sound_driver.h"
class SoundRetro : public SoundDriver {
public:

View File

@ -1,61 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "Util.h"
#include "gba/gbafilter.h"
IMAGE_TYPE utilFindType(const char* file)
{
if (utilIsGBAImage(file))
return IMAGE_GBA;
if (utilIsGBImage(file))
return IMAGE_GB;
return IMAGE_UNKNOWN;
}
static int utilGetSize(int size)
{
int res = 1;
while(res < size)
res <<= 1;
return res;
}
uint8_t *utilLoad(const char *file, bool (*accept)(const char *), uint8_t *data, int &size)
{
FILE *fp = NULL;
fp = fopen(file,"rb");
if (!fp)
{
log("Failed to open file %s", file);
return NULL;
}
fseek(fp, 0, SEEK_END); //go to end
size = ftell(fp); // get position at end (length)
rewind(fp);
uint8_t *image = data;
if(image == NULL)
{
image = (uint8_t *)malloc(utilGetSize(size));
if(image == NULL)
{
log("Failed to allocate memory for %s", file);
return NULL;
}
}
if (fread(image, 1, size, fp) != (size_t)size) {
log("Failed to read from %s", file);
fclose(fp);
return NULL;
}
fclose(fp);
return image;
}

View File

@ -10,8 +10,9 @@
#include "libretro_core_options.h"
#include "scrc32.h"
#include "../System.h"
#include "core/base/system.h"
#include "../Util.h"
#include "core/base/file_util.h"
#include "core/base/port.h"
#include "core/base/sizes.h"
#include "../apu/Blip_Buffer.h"

View File

@ -3,21 +3,17 @@
#pragma once
#include "../System.h"
#include "core/base/system.h"
#include "../sdl/filters.h"
#include <stdio.h>
#ifndef __GNUC__
#define HAVE_DECL_GETOPT 0
#define __STDC__ 1
#ifndef __LIBRETRO__
#include "getopt.h"
#endif
#else // ! __GNUC__
#define HAVE_DECL_GETOPT 1
#ifndef __LIBRETRO__
#include <getopt.h>
#endif
#endif // ! __GNUC__
extern const char *biosFileNameGB;

View File

@ -44,6 +44,7 @@
#include <SDL.h>
#include "core/base/file_util.h"
#include "core/base/message.h"
#include "core/base/patch.h"
#include "core/base/version.h"
#include "../Util.h"
@ -56,7 +57,6 @@
#include "../gba/GBA.h"
#include "../gba/RTC.h"
#include "../gba/Sound.h"
#include "../gba/agbprint.h"
#include "../common/SoundSDL.h"

View File

@ -289,11 +289,11 @@ static void debuggerPrintBaseType(Type* t, uint32_t value, uint32_t location,
}
if (t->size == 8) {
u64 value = 0;
uint64_t value = 0;
if (type == LOCATION_memory) {
value = debuggerReadMemory(location) | ((u64)debuggerReadMemory(location + 4) << 32);
value = debuggerReadMemory(location) | ((uint64_t)debuggerReadMemory(location + 4) << 32);
} else if (type == LOCATION_register) {
value = reg[location].I | ((u64)reg[location + 1].I << 32);
value = reg[location].I | ((uint64_t)reg[location + 1].I << 32);
}
switch (t->encoding) {
case DW_ATE_signed:
@ -1590,8 +1590,8 @@ void debuggerDoSearch()
SearchStart = 0x02000000;
continue;
} else {
start = bios + (SearchStart & 0x3FFF);
end = bios + 0x3FFF;
start = g_bios + (SearchStart & 0x3FFF);
end = g_bios + 0x3FFF;
break;
};
case 2:
@ -1655,8 +1655,8 @@ void debuggerDoSearch()
case 12:
case 13:
if (final <= 0x09FFFFFF) {
start = rom + (SearchStart & 0x01FFFFFF);
end = rom + 0x01FFFFFF;
start = g_rom + (SearchStart & 0x01FFFFFF);
end = g_rom + 0x01FFFFFF;
break;
};
default:
@ -1698,8 +1698,8 @@ void debuggerDoSearch()
unsigned int AddressToGBA(uint8_t* mem)
{
if (mem >= &bios[0] && mem <= &bios[0x3fff])
return 0x00000000 + (mem - &bios[0]);
if (mem >= &g_bios[0] && mem <= &g_bios[0x3fff])
return 0x00000000 + (mem - &g_bios[0]);
else if (mem >= &g_workRAM[0] && mem <= &g_workRAM[0x3ffff])
return 0x02000000 + (mem - &g_workRAM[0]);
else if (mem >= &g_internalRAM[0] && mem <= &g_internalRAM[0x7fff])
@ -1712,8 +1712,8 @@ unsigned int AddressToGBA(uint8_t* mem)
return 0x06000000 + (mem - &g_vram[0]);
else if (mem >= &g_oam[0] && mem <= &g_oam[0x3ff])
return 0x07000000 + (mem - &g_oam[0]);
else if (mem >= &rom[0] && mem <= &rom[0x1ffffff])
return 0x08000000 + (mem - &rom[0]);
else if (mem >= &g_rom[0] && mem <= &g_rom[0x1ffffff])
return 0x08000000 + (mem - &g_rom[0]);
else
return 0xFFFFFFFF;
};

View File

@ -90,8 +90,6 @@ enum yytokentype {
#include <string.h>
#include <cstdlib>
#include "../System.h"
#include "../gba/elf.h"
#include "exprNode.h"
extern int yyerror(const char*);

View File

@ -4,7 +4,7 @@
#include <string.h>
#include <cstdlib>
#include "../System.h"
#include "core/base/system.h"
#include "../gba/elf.h"
#include "exprNode.h"

View File

@ -17,6 +17,8 @@
// along with this program; if not, write to the Free Software Foundation,
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "../gba/elf.h"
struct Node {
Type* type;
uint32_t location;

View File

@ -20,7 +20,7 @@
/* Code originally from fceu/drawing.h file, adapted by Forgotten
*/
#include "../System.h"
#include "core/base/system.h"
extern int RGB_LOW_BITS_MASK;

View File

@ -10,7 +10,7 @@
#include <wx/log.h>
#include <wx/translation.h>
#include "../System.h"
#include "core/base/system.h"
#include "../gba/Sound.h"
#include "../gb/gbGlobals.h"
#include "opts.h"

View File

@ -2,9 +2,8 @@
#include "wxvbam.h"
// Internals
#include "../System.h"
#include "../common/SoundDriver.h"
#include "../gba/GBA.h"
#include "core/base/sound_driver.h"
#include "core/base/system.h"
#include "../gba/Globals.h"
#include "../gba/Sound.h"

View File

@ -5,7 +5,7 @@
#include <stdio.h>
// Interface
#include "../common/SoundDriver.h"
#include "core/base/sound_driver.h"
// FAudio
#include <faudio.h>
@ -16,7 +16,7 @@
#include <vector>
// Internals
#include "../System.h" // for systemMessage()
#include "core/base/system.h" // for systemMessage()
#include "../gba/Globals.h"
int GetFADevices(FAudio* fa, wxArrayString* names, wxArrayString* ids,

View File

@ -9,6 +9,63 @@
#include "viewsupt.h"
#include "wxvbam.h"
namespace {
void utilReadScreenPixels(uint8_t* dest, int w, int h) {
uint8_t* b = dest;
int sizeX = w;
int sizeY = h;
switch (systemColorDepth) {
case 16: {
uint16_t* p = (uint16_t*)(g_pix + (w + 2) * 2); // skip first black line
for (int y = 0; y < sizeY; y++) {
for (int x = 0; x < sizeX; x++) {
uint16_t v = *p++;
*b++ = ((v >> systemRedShift) & 0x001f) << 3; // R
*b++ = ((v >> systemGreenShift) & 0x001f) << 3; // G
*b++ = ((v >> systemBlueShift) & 0x01f) << 3; // B
}
p++; // skip black pixel for filters
p++; // skip black pixel for filters
}
} break;
case 24: {
uint8_t* pixU8 = (uint8_t*)g_pix;
for (int y = 0; y < sizeY; y++) {
for (int x = 0; x < sizeX; x++) {
if (systemRedShift < systemBlueShift) {
*b++ = *pixU8++; // R
*b++ = *pixU8++; // G
*b++ = *pixU8++; // B
} else {
uint8_t blue = *pixU8++;
uint8_t green = *pixU8++;
uint8_t red = *pixU8++;
*b++ = red;
*b++ = green;
*b++ = blue;
}
}
}
} break;
case 32: {
uint32_t* pixU32 = (uint32_t*)(g_pix + 4 * (w + 1));
for (int y = 0; y < sizeY; y++) {
for (int x = 0; x < sizeX; x++) {
uint32_t v = *pixU32++;
*b++ = ((v >> systemBlueShift) & 0x001f) << 3; // B
*b++ = ((v >> systemGreenShift) & 0x001f) << 3; // G
*b++ = ((v >> systemRedShift) & 0x001f) << 3; // R
}
pixU32++;
}
} break;
}
}
} // namespace
// FIXME: many of these read e.g. palette data directly without regard to
// byte order. Need to determine where things are stored in emulated machine
// order and where in native order, and swap the latter on big-endian

View File

@ -8,7 +8,6 @@
#include "wxvbam.h"
#include <cmath>
#include <algorithm>
#include <stdexcept>
#include <typeinfo>
@ -33,11 +32,10 @@
#include <wx/valtext.h>
#include <wx/wfstream.h>
#include "../Util.h"
#include "../gba/CheatSearch.h"
#include "config/game-control.h"
#include "config/option-proxy.h"
#include "config/option.h"
#include "config/user-input.h"
#include "dialogs/accel-config.h"
#include "dialogs/directories-config.h"
#include "dialogs/display-config.h"
@ -46,7 +44,6 @@
#include "dialogs/joypad-config.h"
#include "opts.h"
#include "widgets/option-validator.h"
#include "widgets/user-input-ctrl.h"
#include "wxhead.h"
#if defined(__WXGTK__)

View File

@ -8,7 +8,7 @@
#include "wxvbam.h"
// Interface
#include "../common/SoundDriver.h"
#include "core/base/sound_driver.h"
// OpenAL
#include "openal.h"

View File

@ -21,6 +21,8 @@
#include <wx/menu.h>
#include <SDL_joystick.h>
#include "../Util.h"
#include "core/base/file_util.h"
#include "core/base/patch.h"
#include "core/base/version.h"
#include "../gb/gbPrinter.h"

View File

@ -6,6 +6,7 @@
#include <wx/printdlg.h>
#include <SDL.h>
#include "core/base/image_util.h"
#include "../common/SoundSDL.h"
#include "config/game-control.h"
#include "config/option-proxy.h"

View File

@ -37,6 +37,7 @@
// The built-in vba-over.ini
#include "builtin-over.h"
#include "../Util.h"
#include "config/game-control.h"
#include "config/option-proxy.h"
#include "config/option.h"
@ -45,7 +46,6 @@
#include "wayland.h"
#include "widgets/group-check-box.h"
#include "widgets/user-input-ctrl.h"
#include "wxhead.h"
#ifdef __WXGTK__
#include <gdk/gdk.h>

View File

@ -5,7 +5,7 @@
#include <stdio.h>
// Interface
#include "../common/SoundDriver.h"
#include "core/base/sound_driver.h"
// XAudio2
#if _MSC_VER
@ -20,7 +20,7 @@
#include <vector>
// Internals
#include "../System.h" // for systemMessage()
#include "core/base/system.h" // for systemMessage()
#include "../gba/Globals.h"
int GetXA2Devices(IXAudio2* xa, wxArrayString* names, wxArrayString* ids,

View File

@ -0,0 +1,9 @@
# Defines the `STB_INCLUDE_DIR` variable and `stb-image` target.
# STB Image library dependency (header-only).
set(STB_INCLUDE_DIR ${CMAKE_CURRENT_LIST_DIR} PARENT_SCOPE)
add_library(stb-image INTERFACE)
target_sources(stb-image
INTERFACE
stb_image_write.h
)