[Build] Move file-related utilities to core/base

* Remove duplicate function definitions between the libretro and other
  frontends by merging them into a common source file.
* Also move `systemMessage()` and message IDs definitions to core/base.
* Clean up and modernize many file utility methods.
This commit is contained in:
Fabrice de Gans 2024-03-14 17:36:09 -07:00 committed by Fabrice de Gans
parent ce12db1e06
commit 8f92d99968
36 changed files with 548 additions and 686 deletions

View File

@ -249,6 +249,7 @@ set(SDL2_TARGETS SDL2::SDL2 ${SDL2_LIBRARY_TEMP})
set(
VBAMCORE_LIBS
vbamcore
vbam-core-base
vbam-fex
${SDL2_TARGETS}
${SFML_LIBRARIES}
@ -385,15 +386,16 @@ endif()
if(NOT TRANSLATIONS_ONLY)
add_subdirectory(src/core/fex)
add_subdirectory(src/core/base)
endif()
set(
SRC_MAIN
src/Util.cpp
src/Util_common.cpp
src/common/dictionary.c
src/common/iniparser.c
src/common/Patch.cpp
src/common/memgzio.c
src/common/SoundSDL.cpp
)
@ -408,7 +410,6 @@ set(
src/common/array.h
src/common/dictionary.h
src/common/iniparser.h
src/common/memgzio.h
src/common/Port.h
src/common/sizes.h
src/common/SoundDriver.h
@ -424,10 +425,6 @@ if(ENABLE_FFMPEG)
set(HDR_MAIN ${HDR_MAIN} src/common/ffmpeg.h)
endif()
if(ENABLE_NLS)
set(HDR_MAIN ${HDR_MAIN} src/NLS.h)
endif()
set(
SRC_GBA
src/gba/agbprint.cpp

View File

@ -3,6 +3,8 @@
#include "common/Types.h"
#include "core/base/message.h"
#define winlog log
#ifdef __LIBRETRO__
@ -86,7 +88,6 @@ extern bool systemReadJoypads();
// return information about the given joystick, -1 for default joystick
extern uint32_t systemReadJoypad(int);
extern uint32_t systemGetClock();
extern void systemMessage(int, const char *, ...);
extern void systemSetTitle(const char *);
extern SoundDriver *systemSoundInit();
extern void systemOnWriteDataToSoundBuffer(const uint16_t *finalWave, int length);

View File

@ -25,23 +25,12 @@ extern "C" {
#include "stb_image_write.h"
}
#include "NLS.h"
#include "core/fex/fex.h"
#include "core/base/file_util.h"
#include "core/base/message.h"
#include "System.h"
#include "Util.h"
#include "common/Port.h"
#include "gba/Flash.h"
#include "gba/GBA.h"
#include "gba/Globals.h"
#include "gba/RTC.h"
#include "core/fex/fex.h"
extern "C" {
#include "common/memgzio.h"
}
#include "gb/gbGlobals.h"
#include "gba/gbafilter.h"
#ifndef _MSC_VER
#define _stricmp strcasecmp
@ -55,62 +44,8 @@ extern int systemBlueShift;
extern uint16_t systemColorMap16[0x10000];
extern uint32_t systemColorMap32[0x10000];
static int(ZEXPORT *utilGzWriteFunc)(gzFile, const voidp, unsigned int) = NULL;
static int(ZEXPORT *utilGzReadFunc)(gzFile, voidp, unsigned int) = NULL;
static int(ZEXPORT *utilGzCloseFunc)(gzFile) = NULL;
static z_off_t(ZEXPORT *utilGzSeekFunc)(gzFile, z_off_t, int) = NULL;
#define MAX_CART_SIZE 0x8000000 // 128MB
bool FileExists(const char *filename)
{
#ifdef _WIN32
return (_access(filename, 0) != -1);
#else
struct stat buffer;
return (stat(filename, &buffer) == 0);
#endif
}
#ifdef _WIN32
#include <windows.h>
wchar_t* utf8ToUtf16(const char *utf8)
{
wchar_t *utf16 = nullptr;
size_t size = MultiByteToWideChar(CP_UTF8, 0, utf8, -1, NULL , 0);
if (size == 0) return nullptr; // error
utf16 = new wchar_t[size];
size = MultiByteToWideChar(CP_UTF8, 0, utf8 , -1, utf16, size);
if (size == 0) {
delete[] utf16;
return nullptr; // error
}
return utf16;
}
#endif // _WIN32
FILE* utilOpenFile(const char *filename, const char *mode)
{
FILE *f = NULL;
#ifdef _WIN32
wchar_t *wfilename = utf8ToUtf16(filename);
if (!wfilename) return nullptr;
wchar_t *wmode = utf8ToUtf16(mode);
if (!wmode) {
delete[] wfilename;
return nullptr;
}
f = _wfopen(wfilename, wmode);
delete[] wfilename;
delete[] wmode;
#else
f = fopen(filename, mode);
#endif // _WIN32
return f;
}
// Get user-specific config dir manually.
// apple: ~/Library/Application Support/
// windows: %APPDATA%/
@ -293,21 +228,6 @@ bool utilWritePNGFile(const char *fileName, int w, int h, uint8_t *pix)
return ret;
}
void utilPutDword(uint8_t *p, uint32_t value)
{
*p++ = value & 255;
*p++ = (value >> 8) & 255;
*p++ = (value >> 16) & 255;
*p = (value >> 24) & 255;
}
void utilPutWord(uint8_t *p, uint16_t value)
{
*p++ = value & 255;
*p = (value >> 8) & 255;
}
#ifndef __LIBRETRO__
bool utilWriteBMPFile(const char *fileName, int w, int h, uint8_t *pix)
{
uint8_t writeBuffer[512 * 3];
@ -426,43 +346,6 @@ bool utilWriteBMPFile(const char *fileName, int w, int h, uint8_t *pix)
return true;
}
#endif /* !__LIBRETRO__ */
bool utilIsGBAImage(const char *file)
{
coreOptions.cpuIsMultiBoot = false;
if (strlen(file) > 4) {
const char *p = strrchr(file, '.');
if (p != NULL) {
if ((_stricmp(p, ".agb") == 0) || (_stricmp(p, ".gba") == 0) ||
(_stricmp(p, ".bin") == 0) || (_stricmp(p, ".elf") == 0))
return true;
if (_stricmp(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 ((_stricmp(p, ".dmg") == 0) || (_stricmp(p, ".gb") == 0) ||
(_stricmp(p, ".gbc") == 0) || (_stricmp(p, ".cgb") == 0) ||
(_stricmp(p, ".sgb") == 0))
return true;
}
}
return false;
}
bool utilIsGzipFile(const char *file)
{
@ -480,20 +363,6 @@ bool utilIsGzipFile(const char *file)
return false;
}
// strip .gz or .z off end
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;
}
}
// 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])
@ -552,35 +421,11 @@ IMAGE_TYPE utilFindType(const char *file)
IMAGE_TYPE utilFindType(const char *file, char (&buffer)[2048])
{
#ifdef WIN32
DWORD dwNum = MultiByteToWideChar(CP_ACP, 0, file, -1, NULL, 0);
wchar_t *pwText;
pwText = new wchar_t[dwNum];
if (!pwText) {
return IMAGE_UNKNOWN;
}
MultiByteToWideChar(CP_ACP, 0, file, -1, pwText, dwNum);
//char *file_conv = fex_wide_to_path(file);
char *file_conv = (char *)file;
// if ( !utilIsImage( file_conv ) ) // TODO: utilIsArchive() instead?
// {
fex_t *fe = scan_arc(file_conv, utilIsImage, buffer);
if (!fe)
return IMAGE_UNKNOWN;
fex_close(fe);
file = buffer;
// }
//free(file_conv);
#else
// if ( !utilIsImage( file ) ) // TODO: utilIsArchive() instead?
// {
fex_t *fe = scan_arc(file, utilIsImage, buffer);
if (!fe)
return IMAGE_UNKNOWN;
fex_close(fe);
file = buffer;
// }
#endif
return utilIsGBAImage(file) ? IMAGE_GBA : IMAGE_GB;
}
@ -596,26 +441,10 @@ uint8_t *utilLoad(const char *file, bool (*accept)(const char *), uint8_t *data,
{
// find image file
char buffer[2048];
#ifdef WIN32
DWORD dwNum = MultiByteToWideChar(CP_ACP, 0, file, -1, NULL, 0);
wchar_t *pwText;
pwText = new wchar_t[dwNum];
if (!pwText) {
return NULL;
}
MultiByteToWideChar(CP_ACP, 0, file, -1, pwText, dwNum);
//char *file_conv = fex_wide_to_path(file);
char *file_conv = (char *)file;
delete[] pwText;
fex_t *fe = scan_arc(file_conv, accept, buffer);
if (!fe)
return NULL;
//free(file_conv);
#else
fex_t *fe = scan_arc(file, accept, buffer);
if (!fe)
return NULL;
#endif
// Allocate space for image
fex_err_t err = fex_stat(fe);
int fileSize = fex_size(fe);
@ -670,241 +499,3 @@ void replaceAll(std::string &str, const std::string &from, const std::string &to
// 'yx'
}
}
void utilExtract(const char *filepath, const char *filename)
{
fex_t *fex;
std::string archive_name(filepath);
archive_name.append(filename);
fex_open(&fex, archive_name.c_str());
while (!fex_done(fex)) {
std::string extracted_filename(filepath);
extracted_filename.append(fex_name(fex));
#ifdef WIN32
replaceAll(extracted_filename, "/", "\\");
#endif
std::string new_dir(filepath);
new_dir.append(fex_name(fex));
#ifdef WIN32
replaceAll(new_dir, "/", "\\");
#endif
new_dir = new_dir.substr(0, new_dir.find_last_of("\\"));
if (!FileExists(new_dir.c_str()))
mkdir(new_dir.c_str()
#ifndef WIN32
,
0777
#endif
);
if (FileExists(extracted_filename.c_str())) {
std::string new_name(filepath);
new_name.append("old-");
new_name.append(fex_name(fex));
#ifdef WIN32
replaceAll(new_name, "/", "\\");
#endif
remove(new_name.c_str());
rename(extracted_filename.c_str(), new_name.c_str());
}
FILE *extracted_file = fopen(extracted_filename.c_str(), "wb");
const void *p;
fex_data(fex, &p);
fwrite(p, fex_size(fex), 1, extracted_file);
fclose(extracted_file);
fex_next(fex);
}
fex_close(fex);
}
void utilWriteInt(gzFile gzFile, int i)
{
utilGzWrite(gzFile, &i, sizeof(int));
}
int utilReadInt(gzFile gzFile)
{
int i = 0;
utilGzRead(gzFile, &i, sizeof(int));
return i;
}
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++;
}
}
void utilWriteData(gzFile gzFile, variable_desc *data)
{
while (data->address) {
utilGzWrite(gzFile, data->address, data->size);
data++;
}
}
gzFile utilAutoGzOpen(const char *file, const char *mode)
{
#ifdef _WIN32
wchar_t *wfile = utf8ToUtf16(file);
if (!wfile) return nullptr;
gzFile handler = gzopen_w(wfile, mode);
delete[] wfile;
return handler;
#else
return gzopen(file, mode);
#endif
}
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 utilGBAFindSave(const int size)
{
uint32_t *p = (uint32_t *)&g_rom[0];
uint32_t *end = (uint32_t *)(&g_rom[0] + size);
int detectedSaveType = 0;
int flashSize = 0x10000;
bool rtcFound = false;
while (p < end) {
uint32_t d = READ32LE(p);
if (d == 0x52504545) {
if (memcmp(p, "EEPROM_", 7) == 0) {
if (detectedSaveType == 0 || detectedSaveType == 4)
detectedSaveType = 1;
}
} else if (d == 0x4D415253) {
if (memcmp(p, "SRAM_", 5) == 0) {
if (detectedSaveType == 0 || detectedSaveType == 1 ||
detectedSaveType == 4)
detectedSaveType = 2;
}
} else if (d == 0x53414C46) {
if (memcmp(p, "FLASH1M_", 8) == 0) {
if (detectedSaveType == 0) {
detectedSaveType = 3;
flashSize = 0x20000;
}
} else if (memcmp(p, "FLASH512_", 9) == 0) {
if (detectedSaveType == 0) {
detectedSaveType = 3;
flashSize = 0x10000;
}
} else if (memcmp(p, "FLASH", 5) == 0) {
if (detectedSaveType == 0) {
detectedSaveType = 4;
flashSize = 0x10000;
}
}
} else if (d == 0x52494953) {
if (memcmp(p, "SIIRTC_V", 8) == 0)
rtcFound = true;
}
p++;
}
// if no matches found, then set it to NONE
if (detectedSaveType == 0) {
detectedSaveType = 5;
}
if (detectedSaveType == 4) {
detectedSaveType = 3;
}
rtcEnable(rtcFound);
rtcEnableRumble(!rtcFound);
coreOptions.saveType = detectedSaveType;
flashSetSize(flashSize);
}
void utilUpdateSystemColorMaps(bool lcd)
{
switch (systemColorDepth) {
case 16: {
for (int i = 0; i < 0x10000; i++) {
systemColorMap16[i] = ((i & 0x1f) << systemRedShift) |
(((i & 0x3e0) >> 5) << systemGreenShift) |
(((i & 0x7c00) >> 10) << systemBlueShift);
}
if (lcd)
gbafilter_pal(systemColorMap16, 0x10000);
} break;
case 24:
case 32: {
for (int i = 0; i < 0x10000; i++) {
systemColorMap32[i] = ((i & 0x1f) << systemRedShift) |
(((i & 0x3e0) >> 5) << systemGreenShift) |
(((i & 0x7c00) >> 10) << systemBlueShift);
}
if (lcd)
gbafilter_pal32(systemColorMap32, 0x10000);
} break;
}
}
// Check for existence of file.
bool utilFileExists(const char *filename)
{
FILE *f = fopen(filename, "r");
if (f == NULL) {
return false;
} else {
fclose(f);
return true;
}
}

View File

@ -1,8 +1,8 @@
#ifndef UTIL_H
#define UTIL_H
#include <cstdint>
#include <string>
#include "System.h"
#ifdef _WIN32
#define FILE_SEP '\\'
@ -14,14 +14,6 @@
enum IMAGE_TYPE { IMAGE_UNKNOWN = -1, IMAGE_GBA = 0, IMAGE_GB = 1 };
// save game
typedef struct {
void *address;
int size;
} variable_desc;
bool FileExists(const char *filename);
std::string get_xdg_user_config_home();
std::string get_xdg_user_data_home();
@ -30,45 +22,13 @@ void utilReadScreenPixels(uint8_t *dest, int w, int h);
bool utilWritePNGFile(const char *, int, int, uint8_t *);
bool utilWriteBMPFile(const char *, int, int, uint8_t *);
#endif
void utilApplyIPS(const char *ips, uint8_t **rom, int *size);
bool utilIsGBAImage(const char *);
bool utilIsGBImage(const char *);
bool utilIsGzipFile(const char *);
bool utilIsZipFile(const char *);
void utilStripDoubleExtension(const char *, char *);
IMAGE_TYPE utilFindType(const char *);
uint8_t *utilLoad(const char *, bool (*)(const char *), uint8_t *, int &);
void utilExtract(const char *filepath, const char *filename);
void utilPutDword(uint8_t *, uint32_t);
void utilPutWord(uint8_t *, uint16_t);
void utilGBAFindSave(const int);
void utilUpdateSystemColorMaps(bool lcd = false);
bool utilFileExists(const char *filename);
#ifdef __LIBRETRO__
void utilWriteIntMem(uint8_t *&data, int);
void utilWriteMem(uint8_t *&data, const void *in_data, unsigned size);
void utilWriteDataMem(uint8_t *&data, variable_desc *);
int utilReadIntMem(const uint8_t *&data);
void utilReadMem(void *buf, const uint8_t *&data, unsigned size);
void utilReadDataMem(const uint8_t *&data, variable_desc *);
#else
FILE* utilOpenFile(const char *filename, const char *mode);
gzFile utilAutoGzOpen(const char *file, const char *mode);
gzFile utilGzOpen(const char *file, const char *mode);
gzFile utilMemGzOpen(char *memory, int available, const char *mode);
int utilGzWrite(gzFile file, const voidp buffer, unsigned int len);
int utilGzRead(gzFile file, voidp buffer, unsigned int len);
int utilGzClose(gzFile file);
z_off_t utilGzSeek(gzFile file, z_off_t offset, int whence);
long utilGzMemTell(gzFile file);
void utilWriteData(gzFile, variable_desc *);
void utilReadData(gzFile, variable_desc *);
void utilReadDataSkip(gzFile, variable_desc *);
int utilReadInt(gzFile);
void utilWriteInt(gzFile, int);
#endif
#endif // UTIL_H

134
src/Util_common.cpp Normal file
View File

@ -0,0 +1,134 @@
#include "Util.h"
#include <cstring>
#include "System.h"
#include "common/Port.h"
#include "gba/Globals.h"
#include "gba/RTC.h"
#include "gba/gbafilter.h"
#if defined(_MSC_VER)
#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: {
for (int i = 0; i < 0x10000; i++) {
systemColorMap16[i] = ((i & 0x1f) << systemRedShift) |
(((i & 0x3e0) >> 5) << systemGreenShift) |
(((i & 0x7c00) >> 10) << systemBlueShift);
}
if (lcd)
gbafilter_pal(systemColorMap16, 0x10000);
} break;
case 24:
case 32: {
for (int i = 0; i < 0x10000; i++) {
systemColorMap32[i] = ((i & 0x1f) << systemRedShift) |
(((i & 0x3e0) >> 5) << systemGreenShift) |
(((i & 0x7c00) >> 10) << systemBlueShift);
}
if (lcd)
gbafilter_pal32(systemColorMap32, 0x10000);
} break;
}
}
void utilGBAFindSave(const int size) {
uint32_t* p = (uint32_t*)&g_rom[0];
uint32_t* end = (uint32_t*)(&g_rom[0] + size);
int detectedSaveType = 0;
int flashSize = 0x10000;
bool rtcFound = false;
while (p < end) {
uint32_t d = READ32LE(p);
if (d == 0x52504545) {
if (memcmp(p, "EEPROM_", 7) == 0) {
if (detectedSaveType == 0 || detectedSaveType == 4)
detectedSaveType = 1;
}
} else if (d == 0x4D415253) {
if (memcmp(p, "SRAM_", 5) == 0) {
if (detectedSaveType == 0 || detectedSaveType == 1 || detectedSaveType == 4)
detectedSaveType = 2;
}
} else if (d == 0x53414C46) {
if (memcmp(p, "FLASH1M_", 8) == 0) {
if (detectedSaveType == 0) {
detectedSaveType = 3;
flashSize = 0x20000;
}
} else if (memcmp(p, "FLASH512_", 9) == 0) {
if (detectedSaveType == 0) {
detectedSaveType = 3;
flashSize = 0x10000;
}
} else if (memcmp(p, "FLASH", 5) == 0) {
if (detectedSaveType == 0) {
detectedSaveType = 4;
flashSize = 0x10000;
}
}
} else if (d == 0x52494953) {
if (memcmp(p, "SIIRTC_V", 8) == 0)
rtcFound = true;
}
p++;
}
// if no matches found, then set it to NONE
if (detectedSaveType == 0) {
detectedSaveType = 5;
}
if (detectedSaveType == 4) {
detectedSaveType = 3;
}
rtcEnable(rtcFound);
rtcEnableRumble(!rtcFound);
coreOptions.saveType = detectedSaveType;
flashSetSize(flashSize);
}

View File

@ -1,3 +1,5 @@
#include "Patch.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -6,7 +8,6 @@
#include <zlib.h>
#endif
#include "Patch.h"
#if defined(__FreeBSD__) || defined(__NetBSD__)
#include <sys/param.h>
@ -25,6 +26,8 @@
#endif
#endif
#include "core/base/file_util.h"
#ifdef __GNUC__
#if defined(__MUSL__) || defined(__APPLE__) || defined(BSD) || defined(__NetBSD__)
typedef off_t __off64_t; /* off_t is 64 bits on BSD. */

View File

@ -0,0 +1,28 @@
# This defines the `vbam-core-base` target.
# `vbam-core-base` is a collection of utilies and definitions use by the core
# and frontends.
add_library(vbam-core-base OBJECT)
target_sources(vbam-core-base
PRIVATE
file_util.cpp
file_util_common.cpp
internal/file_util_internal.cpp
internal/file_util_internal.h
internal/memgzio.c
internal/memgzio.h
PUBLIC
file_util.h
message.h
)
target_include_directories(vbam-core-base
PUBLIC ${ZLIB_INCLUDE_DIR}
)
target_link_libraries(vbam-core-base
INTERFACE vbam-fex
PUBLIC ${ZLIB_LIBRARY}
)

137
src/core/base/file_util.cpp Normal file
View File

@ -0,0 +1,137 @@
#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));
}

51
src/core/base/file_util.h Normal file
View File

@ -0,0 +1,51 @@
#ifndef VBAM_CORE_BASE_FILE_UTIL_H_
#define VBAM_CORE_BASE_FILE_UTIL_H_
#include <cstdio>
#if defined(__LIBRETRO__)
#include <cstdint>
#else // !defined(__LIBRETRO__)
#include <zlib.h>
#endif // defined(__LIBRETRO__)
// save game
typedef struct {
void *address;
int size;
} variable_desc;
FILE* utilOpenFile(const char *filename, const char *mode);
#if defined(__LIBRETRO__)
void utilWriteIntMem(uint8_t *&data, int);
void utilWriteMem(uint8_t *&data, const void *in_data, unsigned size);
void utilWriteDataMem(uint8_t *&data, variable_desc *);
int utilReadIntMem(const uint8_t *&data);
void utilReadMem(void *buf, const uint8_t *&data, unsigned size);
void utilReadDataMem(const uint8_t *&data, variable_desc *);
#else // !defined(__LIBRETRO__)
// strip .gz or .z off end
void utilStripDoubleExtension(const char *, char *);
gzFile utilAutoGzOpen(const char *file, const char *mode);
gzFile utilGzOpen(const char *file, const char *mode);
gzFile utilMemGzOpen(char *memory, int available, const char *mode);
int utilGzWrite(gzFile file, const voidp buffer, unsigned int len);
int utilGzRead(gzFile file, voidp buffer, unsigned int len);
int utilGzClose(gzFile file);
z_off_t utilGzSeek(gzFile file, z_off_t offset, int whence);
long utilGzMemTell(gzFile file);
void utilWriteData(gzFile, variable_desc *);
void utilReadData(gzFile, variable_desc *);
void utilReadDataSkip(gzFile, variable_desc *);
int utilReadInt(gzFile);
void utilWriteInt(gzFile, int);
#endif // defined(__LIBRETRO__)
#endif // VBAM_CORE_BASE_FILE_UTIL_H_

View File

@ -0,0 +1,21 @@
#include "file_util.h"
#include "core/base/internal/file_util_internal.h"
FILE* utilOpenFile(const char* filename, const char* mode) {
#ifdef _WIN32
std::wstring wfilename = core::internal::ToUTF16(filename);
if (wfilename.empty()) {
return nullptr;
}
std::wstring wmode = core::internal::ToUTF16(mode);
if (wmode.empty()) {
return nullptr;
}
return _wfopen(wfilename.data(), wmode.data());
#else
return fopen(filename, mode);
#endif // _WIN32
}

View File

@ -0,0 +1,44 @@
#include "core/base/file_util.h"
#if !defined(__LIBRETRO__)
#error "This file is only for libretro builds"
#endif
#include <cstring>
// 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));
data += sizeof(int);
}
void utilWriteMem(uint8_t*& data, const void* in_data, unsigned size) {
memcpy(data, in_data, size);
data += size;
}
void utilWriteDataMem(uint8_t*& data, variable_desc* desc) {
while (desc->address) {
utilWriteMem(data, desc->address, desc->size);
desc++;
}
}
int utilReadIntMem(const uint8_t*& data) {
int res;
memcpy(&res, data, sizeof(int));
data += sizeof(int);
return res;
}
void utilReadMem(void* buf, const uint8_t*& data, unsigned size) {
memcpy(buf, data, size);
data += size;
}
void utilReadDataMem(const uint8_t*& data, variable_desc* desc) {
while (desc->address) {
utilReadMem(desc->address, data, desc->size);
desc++;
}
}

View File

@ -0,0 +1,26 @@
#include "core/base/internal/file_util_internal.h"
#if defined(_WIN32)
#include <Windows.h>
#endif // defined(_WIN32)
namespace core {
namespace internal {
#if defined(_WIN32)
std::wstring ToUTF16(const char* utf8) {
int len = MultiByteToWideChar(CP_UTF8, 0, utf8, -1, nullptr, 0);
if (len == 0) {
return std::wstring();
}
std::wstring result(len, 0);
MultiByteToWideChar(CP_UTF8, 0, utf8, -1, result.data(), len);
return result;
}
#endif // defined(_WIN32)
} // namespace internal
} // namespace core

View File

@ -0,0 +1,21 @@
#ifndef VBAM_CORE_BASE_INTERNAL_FILE_UTIL_INTERNAL_H_
#define VBAM_CORE_BASE_INTERNAL_FILE_UTIL_INTERNAL_H_
#if defined(_WIN32)
#include <string>
#endif // defined(_WIN32)
namespace core {
namespace internal {
#if defined(_WIN32)
// Convert UTF-8 to UTF-16. Returns an empty string on error.
std::wstring ToUTF16(const char* utf8);
#endif // defined(_WIN32)
} // namespace internal
} // namespace core
#endif // VBAM_CORE_BASE_INTERNAL_FILE_UTIL_INTERNAL_H_

View File

@ -18,7 +18,7 @@
#include <stdlib.h>
#include <string.h>
#include "memgzio.h"
#include "core/base/internal/memgzio.h"
#ifndef local
#define local static

View File

@ -1,5 +1,5 @@
#ifndef MEMGZIO_H
#define MEMGZIO_H
#ifndef VBAM_CORE_BASE_INTERNAL_MEMGZIO_H_
#define VBAM_CORE_BASE_INTERNAL_MEMGZIO_H_
/* gzio.c -- IO on .gz files
* Copyright (C) 1995-2002 Jean-loup Gailly.
@ -14,6 +14,10 @@
#include <zlib.h>
#ifdef __cplusplus
extern "C" {
#endif
gzFile ZEXPORT memgzopen(char *memory, int available, const char *mode);
int ZEXPORT memgzread(gzFile file, voidp buf, unsigned len);
int ZEXPORT memgzwrite(gzFile file, const voidp buf, unsigned len);
@ -30,4 +34,8 @@ z_off_t ZEXPORT memgzseek(gzFile file, z_off_t off, int whence);
# endif
#endif
#endif // MEMGZIO_H
#ifdef __cplusplus
} // extern "C"
#endif
#endif // VBAM_CORE_BASE_INTERNAL_MEMGZIO_H_

View File

@ -1,4 +1,12 @@
#ifndef VBAM_CORE_BASE_MESSAGE_H_
#define VBAM_CORE_BASE_MESSAGE_H_
// Display a message to the user. To be implemented by the frontend.
void systemMessage(int, const char *, ...);
#if !defined(N_)
#define N_(String) (String)
#endif // !defined(N_)
#define MSG_UNSUPPORTED_VBA_SGM 1
#define MSG_CANNOT_LOAD_SGM 2
@ -45,3 +53,5 @@
#define MSG_UNSUPPORTED_GAMESHARK_CODE 43
#define MSG_INVALID_GAME_BOY_NINTENDO_LOGO 44
#define MSG_INVALID_HEADER_CHECKSUM 45
#endif // VBAM_CORE_BASE_MESSAGE_H_

View File

@ -8,7 +8,7 @@
#include <cstring>
#include <vector>
#include "../NLS.h"
#include "core/base/file_util.h"
#include "../System.h"
#include "../Util.h"
#include "../common/sizes.h"

View File

@ -3,10 +3,10 @@
#include <stdlib.h>
#include <string.h>
#include "../NLS.h"
#include "../System.h"
#include "../Util.h"
#include "core/base/file_util.h"
#include "gb.h"
#include "gbCheats.h"
#include "gbGlobals.h"

View File

@ -1,6 +1,6 @@
#include <memory.h>
#include "../Util.h"
#include "../System.h"
#include "gbGlobals.h"
#include "gbSGB.h"
@ -53,7 +53,7 @@ void gbRenderLine()
bank1 = &gbVram[0x2000];
} else {
bank0 = &gbMemory[0x8000];
bank1 = NULL;
bank1 = nullptr;
}
int tile_map = 0x1800;
@ -90,7 +90,7 @@ void gbRenderLine()
int tile_map_address = tile_map_line_y + tx;
uint8_t attrs = 0;
if (bank1 != NULL)
if (bank1 != nullptr)
attrs = bank1[tile_map_address];
uint8_t tile = bank0[tile_map_address];
@ -404,7 +404,7 @@ void gbDrawSpriteTile(int tile, int x, int y, int t, int flags,
bank1 = &gbVram[0x2000];
} else {
bank0 = &gbMemory[0x8000];
bank1 = NULL;
bank1 = nullptr;
}
int SpritesTicks = gbSpritesTicks[x + 8] * (gbSpeed ? 2 : 4);

View File

@ -1,8 +1,8 @@
#include <memory.h>
#include <stdlib.h>
#include "core/base/file_util.h"
#include "../System.h"
#include "../Util.h"
#include "../common/Port.h"
#include "gb.h"
#include "gbGlobals.h"

View File

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

View File

@ -3,7 +3,7 @@
#include <stdio.h>
#include <string.h>
#include "../NLS.h"
#include "core/base/file_util.h"
#include "../Util.h"
#include "Cheats.h"
#include "GBA.h"

View File

@ -1,8 +1,9 @@
#include "EEprom.h"
#include "../Util.h"
#include <cstring>
#include "core/base/file_util.h"
#include "GBA.h"
#include <memory.h>
#include <string.h>
extern int cpuDmaCount;

View File

@ -1,12 +1,13 @@
#include "Flash.h"
#include "../Util.h"
#include "GBA.h"
#include "Globals.h"
#include "Sram.h"
#include <memory.h>
#include <stdio.h>
#include <string.h>
#include "core/base/file_util.h"
#include "GBA.h"
#include "Sram.h"
#define FLASH_READ_ARRAY 0
#define FLASH_CMD_1 1
#define FLASH_CMD_2 2

View File

@ -4,7 +4,6 @@
#include <stdlib.h>
#include <string.h>
#include "../NLS.h"
#include "../System.h"
#include "../Util.h"
#include "Cheats.h"

View File

@ -7,7 +7,6 @@
#include <strings.h>
#endif
#include "../NLS.h"
#include "../System.h"
#include "../Util.h"
#include "Cheats.h"

View File

@ -5,10 +5,12 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifndef _MSC_VER
#include <strings.h>
#endif
#include "../NLS.h"
#include "core/base/file_util.h"
#include "../System.h"
#include "../Util.h"
#include "../common/Port.h"

View File

@ -67,6 +67,7 @@ uint16_t IP_LINK_PORT = 5738;
std::string IP_LINK_BIND_ADDRESS = "*";
#include "core/base/message.h"
#include "../common/Port.h"
#include "GBA.h"
#include "GBALink.h"
@ -80,7 +81,6 @@ std::string IP_LINK_BIND_ADDRESS = "*";
#else
#define _(x) x
#endif
#define N_(x) x
#if (defined __WIN32__ || defined _WIN32)
#include <windows.h>

View File

@ -1,11 +1,10 @@
#include "../NLS.h"
#include "../System.h"
#include "../Util.h"
#include "../common/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>

View File

@ -3,7 +3,7 @@
#include <array>
#include <cstring>
#include "../Util.h"
#include "core/base/file_util.h"
#include "../common/Port.h"
#include "GBA.h"
#include "Globals.h"

View File

@ -2,7 +2,6 @@
#include <stdlib.h>
#include <string.h>
#include "../NLS.h"
#include "../common/Port.h"
#include "GBA.h"
#include "elf.h"

View File

@ -3,6 +3,7 @@
#include <stdlib.h>
#include <string.h>
#include "core/base/file_util.h"
#include "GBA.h"
#include "GBAinline.h"
#include "Globals.h"

View File

@ -16,11 +16,20 @@ VBA_DEFINES += -DNO_LINK
endif
SOURCES_CXX :=
SOURCES_CXX += \
$(CORE_DIR)/Util_common.cpp \
SOURCES_CXX += \
$(CORE_DIR)/libretro/libretro.cpp \
$(CORE_DIR)/libretro/UtilRetro.cpp \
$(CORE_DIR)/libretro/SoundRetro.cpp
SOURCES_CXX += \
$(CORE_DIR)/core/base/internal/file_util_internal.cpp \
$(CORE_DIR)/core/base/file_util_common.cpp \
$(CORE_DIR)/core/base/file_util_libretro.cpp
SOURCES_CXX += \
$(CORE_DIR)/apu/Gb_Oscs.cpp \
$(CORE_DIR)/apu/Gb_Apu_State.cpp \

View File

@ -2,75 +2,9 @@
#include <stdlib.h>
#include <string.h>
#include <libretro.h>
#include "NLS.h"
#include "System.h"
#include "Util.h"
#include "common/Port.h"
#include "gba/Flash.h"
#include "gba/GBA.h"
#include "gba/Globals.h"
#include "gba/RTC.h"
#include "gb/gbGlobals.h"
#include "gba/gbafilter.h"
#ifndef _MSC_VER
#include <strings.h>
#define _stricmp strcasecmp
#endif // ! _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;
}
void utilPutWord(uint8_t* p, uint16_t value)
{
*p++ = value & 255;
*p = (value >> 8) & 255;
}
bool utilIsGBAImage(const char* file)
{
coreOptions.cpuIsMultiBoot = false;
if (strlen(file) > 4) {
const char* p = strrchr(file, '.');
if (p != NULL) {
if ((_stricmp(p, ".agb") == 0) || (_stricmp(p, ".gba") == 0) || (_stricmp(p, ".bin") == 0) || (_stricmp(p, ".elf") == 0))
return true;
if (_stricmp(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 ((_stricmp(p, ".dmg") == 0) || (_stricmp(p, ".gb") == 0)
|| (_stricmp(p, ".gbc") == 0) || (_stricmp(p, ".cgb") == 0)
|| (_stricmp(p, ".sgb") == 0)) {
return true;
}
}
}
return false;
}
IMAGE_TYPE utilFindType(const char* file)
{
if (utilIsGBAImage(file))
@ -125,133 +59,3 @@ uint8_t *utilLoad(const char *file, bool (*accept)(const char *), uint8_t *data,
fclose(fp);
return image;
}
void utilGBAFindSave(const int size)
{
bool rtcFound_ = false;
int detectedSaveType = 0;
int flashSize_ = 0x10000;
uint32_t *p = (uint32_t *)&g_rom[0];
uint32_t *end = (uint32_t *)(&g_rom[0] + size);
while (p < end) {
uint32_t d = READ32LE(p);
if (d == 0x52504545) {
if (memcmp(p, "EEPROM_", 7) == 0) {
if (detectedSaveType == 0 || detectedSaveType == 4) {
detectedSaveType = 1;
}
}
} else if (d == 0x4D415253) {
if (memcmp(p, "SRAM_", 5) == 0) {
if (detectedSaveType == 0 || detectedSaveType == 1
|| detectedSaveType == 4) {
detectedSaveType = 2;
flashSize_ = 0x8000;
}
}
} else if (d == 0x53414C46) {
if (memcmp(p, "FLASH1M_", 8) == 0) {
if (detectedSaveType == 0) {
detectedSaveType = 3;
flashSize_ = 0x20000;
}
} else if (memcmp(p, "FLASH512_", 9) == 0) {
if (detectedSaveType == 0) {
detectedSaveType = 3;
flashSize_ = 0x10000;
}
} else if (memcmp(p, "FLASH", 5) == 0) {
if (detectedSaveType == 0) {
detectedSaveType = 4;
flashSize_ = 0x10000;
}
}
} else if (d == 0x52494953) {
if (memcmp(p, "SIIRTC_V", 8) == 0) {
rtcFound_ = true;
}
}
p++;
}
// if no matches found, then set it to NONE
if (detectedSaveType == 0)
detectedSaveType = 5;
if (detectedSaveType == 4)
detectedSaveType = 3;
coreOptions.cpuSaveType = detectedSaveType;
coreOptions.rtcEnabled = rtcFound_;
g_flashSize = flashSize_;
}
void utilUpdateSystemColorMaps(bool lcd)
{
int i = 0;
switch (systemColorDepth) {
case 16:
for (i = 0; i < 0x10000; i++) {
systemColorMap16[i] = ((i & 0x1f) << systemRedShift) |
(((i & 0x3e0) >> 5) << systemGreenShift) |
(((i & 0x7c00) >> 10) << systemBlueShift);
}
if (lcd)
gbafilter_pal(systemColorMap16, 0x10000);
break;
case 24:
case 32:
for (i = 0; i < 0x10000; i++) {
systemColorMap32[i] = ((i & 0x1f) << systemRedShift) |
(((i & 0x3e0) >> 5) << systemGreenShift) |
(((i & 0x7c00) >> 10) << systemBlueShift);
}
if (lcd)
gbafilter_pal32(systemColorMap32, 0x10000);
break;
}
}
// 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));
data += sizeof(int);
}
void utilWriteMem(uint8_t*& data, const void* in_data, unsigned size)
{
memcpy(data, in_data, size);
data += size;
}
void utilWriteDataMem(uint8_t*& data, variable_desc* desc)
{
while (desc->address) {
utilWriteMem(data, desc->address, desc->size);
desc++;
}
}
int utilReadIntMem(const uint8_t*& data)
{
int res;
memcpy(&res, data, sizeof(int));
data += sizeof(int);
return res;
}
void utilReadMem(void* buf, const uint8_t*& data, unsigned size)
{
memcpy(buf, data, size);
data += size;
}
void utilReadDataMem(const uint8_t*& data, variable_desc* desc)
{
while (desc->address) {
utilReadMem(desc->address, data, desc->size);
desc++;
}
}

View File

@ -17,6 +17,7 @@ extern "C" {
#include <cmath>
#include <cerrno>
#include "core/base/file_util.h"
#include "../common/Patch.h"
#include "../gba/GBA.h"
#include "../gba/agbprint.h"
@ -35,6 +36,7 @@ extern "C" {
#define GETCWD getcwd
#else // _WIN32
#include <direct.h>
#include <io.h>
#define GETCWD _getcwd
#define stat _stat
#define mkdir(X,Y) (_mkdir(X))
@ -55,6 +57,19 @@ extern "C" {
#include <string>
#include <sstream>
namespace {
bool FileExists(const char *filename) {
#ifdef _WIN32
return (_access(filename, 0) != -1);
#else
struct stat buffer;
return (stat(filename, &buffer) == 0);
#endif
}
} // namespace
enum named_opts
{
OPT_AGB_PRINT = 1000,

View File

@ -45,6 +45,7 @@
#include "SDL.h"
#include "core/base/file_util.h"
#include "../Util.h"
#include "../common/Patch.h"
#include "../gb/gb.h"