[WINDOWS] Add function to open unicode files. (#644)

We have some issues when trying to open files on Windows that contains
characters not included in the current codepage. Using `fopen` fails
when that happens.

One example is using the `pt_BR` codepage and then using a name with
japanese chars for the battery file.

The games and BIOS work since they use `blargg_open`. It converts a
`const char *` to `const wchat_t *` and uses `_wfopen` for windows.
(doing a multibyte to widechar conversion)

Since we want to avoid doing many code changes on our cores, we need
some `util*` functions for the matter.

Replace `mb_fn_str` by UTF-8 strings.

Replace all occurrences of `fopen` for `utilOpenFile` on GBA core.

Replace all occurrences of `fopen` for `utilOpenFile` on GBA e-reader.

Adjust e-readers calls on wx frontend.

Replace all occurrences of `fopen` for `utilOpenFile` on Patcher files.

Always apply UTF-8 when dealing with path strings.

On our wx frontend we should always send UTF-8 `char *` to our cores
functions. This way we can have consistency when dealing with them for
each platform.

On Windows, we will convert all multibyte to wide chars and use proper
functions for I/O operation.

Create function to deal with unicode calls of `gzopen`.

We use `gzopen_w` (`zlib>=1.27`).

Replace all occurrences of `fopen` for `utilOpenFile` on Config Manager.

Replace all occurrences of `fopen` for `utilOpenFile` on Cheat files.

Use proper functions for unicode on GB core.

Use function instead of macro for `UTF8()`.

Use `nullptr` instead of `NULL`.

Print wide char strings on status bar.
This commit is contained in:
Edênis Freindorfer Azevedo 2020-04-21 10:24:28 -03:00 committed by GitHub
parent ed438d6e52
commit 0b14e9f885
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 173 additions and 114 deletions

View File

@ -5,6 +5,10 @@
#define winlog log
#ifdef __LIBRETRO__
#define utilOpenFile fopen
#endif
class SoundDriver;
struct EmulatedSystem {

View File

@ -72,6 +72,45 @@ bool FileExists(const char *filename)
#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%/
@ -504,10 +543,6 @@ static bool utilIsImage(const char *file)
return utilIsGBAImage(file) || utilIsGBImage(file);
}
#ifdef WIN32
#include <windows.h>
#endif
IMAGE_TYPE utilFindType(const char *file, char (&buffer)[2048]);
IMAGE_TYPE utilFindType(const char *file)
@ -722,6 +757,19 @@ void utilWriteData(gzFile gzFile, variable_desc *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;
@ -729,7 +777,7 @@ gzFile utilGzOpen(const char *file, const char *mode)
utilGzCloseFunc = gzclose;
utilGzSeekFunc = gzseek;
return gzopen(file, mode);
return utilAutoGzOpen(file, mode);
}
gzFile utilMemGzOpen(char *memory, int available, const char *mode)

View File

@ -53,6 +53,8 @@ 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);

View File

@ -758,7 +758,7 @@ void SaveConfigFile()
if (configFile != NULL)
{
FILE *f = fopen(configFile, "w");
FILE *f = utilOpenFile(configFile, "w");
if (f == NULL) {
char err_msg[4096] = "unknown error";
strncpy(err_msg, strerror(errno), 4096);
@ -896,7 +896,7 @@ int ReadOpts(int argc, char ** argv)
log("Missing config file name\n");
break;
}
FILE *f = fopen(optarg, "r");
FILE *f = utilOpenFile(optarg, "r");
if (f == NULL) {
log("File not found %s\n", optarg);
break;

View File

@ -145,7 +145,7 @@ static uLong computePatchCRC(FILE* f, unsigned int size)
static bool patchApplyIPS(const char* patchname, uint8_t** r, int* s)
{
// from the IPS spec at http://zerosoft.zophar.net/ips.htm
FILE* f = fopen(patchname, "rb");
FILE* f = utilOpenFile(patchname, "rb");
if (!f)
return false;
@ -207,7 +207,7 @@ static bool patchApplyUPS(const char* patchname, uint8_t** rom, int* size)
{
int64_t srcCRC, dstCRC, patchCRC;
FILE* f = fopen(patchname, "rb");
FILE* f = utilOpenFile(patchname, "rb");
if (!f)
return false;
@ -297,7 +297,7 @@ static bool patchApplyBPS(const char* patchname, uint8_t** rom, int* size)
{
int64_t srcCRC, dstCRC, patchCRC;
FILE* f = fopen(patchname, "rb");
FILE* f = utilOpenFile(patchname, "rb");
if (!f)
return false;
@ -570,7 +570,7 @@ static bool patchApplyPPF3(FILE* f, uint8_t** rom, int* size)
static bool patchApplyPPF(const char* patchname, uint8_t** rom, int* size)
{
FILE* f = fopen(patchname, "rb");
FILE* f = utilOpenFile(patchname, "rb");
if (!f)
return false;

View File

@ -1,6 +1,7 @@
#ifndef PATCH_H
#define PATCH_H
#include "../Util.h"
#include "Types.h"
bool applyPatch(const char *patchname, uint8_t **rom, int *size);

View File

@ -2860,7 +2860,7 @@ void gbReset()
void gbWriteSaveMBC1(const char* name)
{
if (gbRam) {
FILE* gzFile = fopen(name, "wb");
FILE* gzFile = utilOpenFile(name, "wb");
if (gzFile == NULL) {
systemMessage(MSG_ERROR_CREATING_FILE, N_("Error creating file %s"), name);
@ -2879,7 +2879,7 @@ void gbWriteSaveMBC1(const char* name)
void gbWriteSaveMBC2(const char* name)
{
if (gbRam) {
FILE* file = fopen(name, "wb");
FILE* file = utilOpenFile(name, "wb");
if (file == NULL) {
systemMessage(MSG_ERROR_CREATING_FILE, N_("Error creating file %s"), name);
@ -2898,7 +2898,7 @@ void gbWriteSaveMBC2(const char* name)
void gbWriteSaveMBC3(const char* name, bool extendedSave)
{
if (gbRam || extendedSave) {
FILE* gzFile = fopen(name, "wb");
FILE* gzFile = utilOpenFile(name, "wb");
if (gbRam) {
if (gzFile == NULL) {
@ -2925,7 +2925,7 @@ void gbWriteSaveMBC3(const char* name, bool extendedSave)
void gbWriteSaveMBC5(const char* name)
{
if (gbRam) {
FILE* gzFile = fopen(name, "wb");
FILE* gzFile = utilOpenFile(name, "wb");
if (gzFile == NULL) {
systemMessage(MSG_ERROR_CREATING_FILE, N_("Error creating file %s"), name);
@ -2944,7 +2944,7 @@ void gbWriteSaveMBC5(const char* name)
void gbWriteSaveMBC7(const char* name)
{
if (gbRam) {
FILE* file = fopen(name, "wb");
FILE* file = utilOpenFile(name, "wb");
if (file == NULL) {
systemMessage(MSG_ERROR_CREATING_FILE, N_("Error creating file %s"), name);
@ -2962,7 +2962,7 @@ void gbWriteSaveMBC7(const char* name)
void gbWriteSaveTAMA5(const char* name, bool extendedSave)
{
FILE* gzFile = fopen(name, "wb");
FILE* gzFile = utilOpenFile(name, "wb");
if (gzFile == NULL) {
systemMessage(MSG_ERROR_CREATING_FILE, N_("Error creating file %s"), name);
@ -2991,7 +2991,7 @@ void gbWriteSaveTAMA5(const char* name, bool extendedSave)
void gbWriteSaveMMM01(const char* name)
{
if (gbRam) {
FILE* gzFile = fopen(name, "wb");
FILE* gzFile = utilOpenFile(name, "wb");
if (gzFile == NULL) {
systemMessage(MSG_ERROR_CREATING_FILE, N_("Error creating file %s"), name);
@ -3010,7 +3010,7 @@ void gbWriteSaveMMM01(const char* name)
bool gbReadSaveMBC1(const char* name)
{
if (gbRam) {
gzFile gzFile = gzopen(name, "rb");
gzFile gzFile = utilAutoGzOpen(name, "rb");
if (gzFile == NULL) {
return false;
@ -3052,7 +3052,7 @@ bool gbReadSaveMBC1(const char* name)
bool gbReadSaveMBC2(const char* name)
{
if (gbRam) {
FILE* file = fopen(name, "rb");
FILE* file = utilOpenFile(name, "rb");
if (file == NULL) {
return false;
@ -3095,7 +3095,7 @@ bool gbReadSaveMBC2(const char* name)
bool gbReadSaveMBC3(const char* name)
{
gzFile gzFile = gzopen(name, "rb");
gzFile gzFile = utilAutoGzOpen(name, "rb");
if (gzFile == NULL) {
return false;
@ -3151,7 +3151,7 @@ bool gbReadSaveMBC3(const char* name)
bool gbReadSaveMBC5(const char* name)
{
if (gbRam) {
gzFile gzFile = gzopen(name, "rb");
gzFile gzFile = utilAutoGzOpen(name, "rb");
if (gzFile == NULL) {
return false;
@ -3193,7 +3193,7 @@ bool gbReadSaveMBC5(const char* name)
bool gbReadSaveMBC7(const char* name)
{
if (gbRam) {
FILE* file = fopen(name, "rb");
FILE* file = utilOpenFile(name, "rb");
if (file == NULL) {
return false;
@ -3236,7 +3236,7 @@ bool gbReadSaveMBC7(const char* name)
bool gbReadSaveTAMA5(const char* name)
{
gzFile gzFile = gzopen(name, "rb");
gzFile gzFile = utilAutoGzOpen(name, "rb");
if (gzFile == NULL) {
return false;
@ -3295,7 +3295,7 @@ bool gbReadSaveTAMA5(const char* name)
bool gbReadSaveMMM01(const char* name)
{
if (gbRam) {
gzFile gzFile = gzopen(name, "rb");
gzFile gzFile = utilAutoGzOpen(name, "rb");
if (gzFile == NULL) {
return false;
@ -3489,7 +3489,7 @@ bool gbReadBatteryFile(const char* file)
bool gbReadGSASnapshot(const char* fileName)
{
FILE* file = fopen(fileName, "rb");
FILE* file = utilOpenFile(fileName, "rb");
if (!file) {
systemMessage(MSG_CANNOT_OPEN_FILE, N_("Cannot open file %s"), fileName);

View File

@ -105,7 +105,7 @@ void gbCheatsSaveCheatList(const char* file)
{
if (gbCheatNumber == 0)
return;
FILE* f = fopen(file, "wb");
FILE* f = utilOpenFile(file, "wb");
if (f == NULL)
return;
int version = 1;
@ -125,7 +125,7 @@ bool gbCheatsLoadCheatList(const char* file)
int count = 0;
FILE* f = fopen(file, "rb");
FILE* f = utilOpenFile(file, "rb");
if (f == NULL)
return false;
@ -396,7 +396,7 @@ void gbCheatDisable(int i)
bool gbCheatReadGSCodeFile(const char* fileName)
{
FILE* file = fopen(fileName, "rb");
FILE* file = utilOpenFile(fileName, "rb");
if (!file) {
systemMessage(MSG_CANNOT_OPEN_FILE, N_("Cannot open file %s"), fileName);

View File

@ -2035,7 +2035,7 @@ void cheatsAddGSACode(const char* code, const char* desc, bool v3)
bool cheatsImportGSACodeFile(const char* name, int game, bool v3)
{
FILE* f = fopen(name, "rb");
FILE* f = utilOpenFile(name, "rb");
if (!f)
return false;
@ -2674,7 +2674,7 @@ void cheatsSaveCheatList(const char* file)
{
if (cheatsNumber == 0)
return;
FILE* f = fopen(file, "wb");
FILE* f = utilOpenFile(file, "wb");
if (f == NULL)
return;
int version = 1;
@ -2691,7 +2691,7 @@ bool cheatsLoadCheatList(const char* file)
int count = 0;
FILE* f = fopen(file, "rb");
FILE* f = utilOpenFile(file, "rb");
if (f == NULL)
return false;

View File

@ -951,7 +951,7 @@ bool CPUReadState(const char* file)
bool CPUExportEepromFile(const char* fileName)
{
if (eepromInUse) {
FILE* file = fopen(fileName, "wb");
FILE* file = utilOpenFile(fileName, "wb");
if (!file) {
systemMessage(MSG_ERROR_CREATING_FILE, N_("Error creating file %s"),
@ -976,7 +976,7 @@ bool CPUExportEepromFile(const char* fileName)
bool CPUWriteBatteryFile(const char* fileName)
{
if ((saveType) && (saveType != GBA_SAVE_NONE)) {
FILE* file = fopen(fileName, "wb");
FILE* file = utilOpenFile(fileName, "wb");
if (!file) {
systemMessage(MSG_ERROR_CREATING_FILE, N_("Error creating file %s"),
@ -1011,7 +1011,7 @@ bool CPUWriteBatteryFile(const char* fileName)
bool CPUReadGSASnapshot(const char* fileName)
{
int i;
FILE* file = fopen(fileName, "rb");
FILE* file = utilOpenFile(fileName, "rb");
if (!file) {
systemMessage(MSG_CANNOT_OPEN_FILE, N_("Cannot open file %s"), fileName);
@ -1080,8 +1080,8 @@ bool CPUReadGSASPSnapshot(const char* fileName)
const size_t footerpos = 0x42c, footersz = 4;
char footer[footersz + 1], romname[namesz + 1], savename[namesz + 1];
;
FILE* file = fopen(fileName, "rb");
FILE* file = utilOpenFile(fileName, "rb");
if (!file) {
systemMessage(MSG_CANNOT_OPEN_FILE, N_("Cannot open file %s"), fileName);
@ -1134,7 +1134,7 @@ bool CPUWriteGSASnapshot(const char* fileName,
const char* desc,
const char* notes)
{
FILE* file = fopen(fileName, "wb");
FILE* file = utilOpenFile(fileName, "wb");
if (!file) {
systemMessage(MSG_CANNOT_OPEN_FILE, N_("Cannot open file %s"), fileName);
@ -1191,7 +1191,7 @@ bool CPUWriteGSASnapshot(const char* fileName,
bool CPUImportEepromFile(const char* fileName)
{
FILE* file = fopen(fileName, "rb");
FILE* file = utilOpenFile(fileName, "rb");
if (!file)
return false;
@ -1235,7 +1235,7 @@ bool CPUImportEepromFile(const char* fileName)
bool CPUReadBatteryFile(const char* fileName)
{
FILE* file = fopen(fileName, "rb");
FILE* file = utilOpenFile(fileName, "rb");
if (!file)
return false;
@ -1488,7 +1488,7 @@ int CPULoadRom(const char* szFile)
#ifndef NO_DEBUGGER
if (CPUIsELF(szFile)) {
FILE* f = fopen(szFile, "rb");
FILE* f = utilOpenFile(szFile, "rb");
if (!f) {
systemMessage(MSG_ERROR_OPENING_IMAGE, N_("Error opening image %s"),
szFile);
@ -1715,8 +1715,7 @@ const char* GetSaveDotCodeFile()
void ResetLoadDotCodeFile()
{
if(loadDotCodeFile)
{
if (loadDotCodeFile) {
free((char*)loadDotCodeFile);
}
@ -1730,8 +1729,7 @@ void SetLoadDotCodeFile(const char* szFile)
void ResetSaveDotCodeFile()
{
if (saveDotCodeFile)
{
if (saveDotCodeFile) {
free((char*)saveDotCodeFile);
}

View File

@ -236,9 +236,9 @@ void BIOS_EReader_ScanCard(int swi_num)
reg[0].I = 0x301;
return;
}
f = fopen(loadDotCodeFile, "rb");
//f=fopen(filebuffer,"rb");
//f=fopen("dotcode4.raw","rb");
f = utilOpenFile(loadDotCodeFile, "rb");
//f=utilOpenFile(filebuffer,"rb");
//f=utilOpenFile("dotcode4.raw","rb");
if (f == NULL) {
reg[0].I = 0x303;
return;
@ -502,7 +502,7 @@ void BIOS_EReader_ScanCard(int swi_num)
}
if (swi_num == 0xE3) {
const char* loadDotCodeFile = GetLoadDotCodeFile();
f = fopen(loadDotCodeFile, "rb+");
f = utilOpenFile(loadDotCodeFile, "rb+");
if (f != NULL) {
fwrite(dotcodedata, 1, j, f);
fclose(f);
@ -510,7 +510,7 @@ void BIOS_EReader_ScanCard(int swi_num)
} else {
const char* saveDotCodeFile = GetSaveDotCodeFile();
if (saveDotCodeFile) {
f = fopen(saveDotCodeFile, "wb");
f = utilOpenFile(saveDotCodeFile, "wb");
if (f != NULL) {
fwrite(dotcodedata, 1, j, f);
fwrite(Signature, 1, 0x28, f);

View File

@ -856,7 +856,7 @@ EVT_HANDLER_MASK(SetLoadingDotCodeFile, "Load e-Reader Dot Code...", CMDEN_GBA)
return;
loaddotcodefile_path = dlg.GetPath();
SetLoadDotCodeFile(loaddotcodefile_path.mb_str());
SetLoadDotCodeFile(UTF8(loaddotcodefile_path));
}
EVT_HANDLER_MASK(ResetSavingDotCodeFile, "Reset Saving e-Reader Dot Code", CMDEN_GBA)
@ -878,7 +878,7 @@ EVT_HANDLER_MASK(SetSavingDotCodeFile, "Save e-Reader Dot Code...", CMDEN_GBA)
return;
savedotcodefile_path = dlg.GetPath();
SetSaveDotCodeFile(savedotcodefile_path.mb_str());
SetSaveDotCodeFile(UTF8(savedotcodefile_path));
}
static wxString batimp_path;
@ -903,10 +903,10 @@ EVT_HANDLER_MASK(ImportBatteryFile, "Import battery file...", CMDEN_GB | CMDEN_G
if (ret == wxYES) {
wxString msg;
if (panel->emusys->emuReadBattery(fn.mb_fn_str()))
msg.Printf(_("Loaded battery %s"), fn.c_str());
if (panel->emusys->emuReadBattery(UTF8(fn)))
msg.Printf(_("Loaded battery %s"), fn.wc_str());
else
msg.Printf(_("Error loading battery %s"), fn.c_str());
msg.Printf(_("Error loading battery %s"), fn.wc_str());
systemScreenMessage(msg);
}
@ -936,7 +936,7 @@ EVT_HANDLER_MASK(ImportGamesharkCodeFile, "Import GameShark code file...", CMDEN
// FIXME: this routine will not work on big-endian systems
// if the underlying file format is little-endian
// (fix in gb/gbCheats.cpp)
res = gbCheatReadGSCodeFile(fn.mb_fn_str());
res = gbCheatReadGSCodeFile(UTF8(fn));
else {
// need to select game first
wxFFile f(fn, wxT("rb"));
@ -1018,13 +1018,13 @@ EVT_HANDLER_MASK(ImportGamesharkCodeFile, "Import GameShark code file...", CMDEN
// FIXME: this routine will not work on big-endian systems
// if the underlying file format is little-endian
// (fix in gba/Cheats.cpp)
res = cheatsImportGSACodeFile(fn.mb_fn_str(), game, v3);
res = cheatsImportGSACodeFile(UTF8(fn), game, v3);
}
if (res)
msg.Printf(_("Loaded code file %s"), fn.c_str());
msg.Printf(_("Loaded code file %s"), fn.wc_str());
else
msg.Printf(_("Error loading code file %s"), fn.c_str());
msg.Printf(_("Error loading code file %s"), fn.wc_str());
systemScreenMessage(msg);
}
@ -1053,7 +1053,7 @@ EVT_HANDLER_MASK(ImportGamesharkActionReplaySnapshot,
bool res;
if (panel->game_type() == IMAGE_GB)
res = gbReadGSASnapshot(fn.mb_fn_str());
res = gbReadGSASnapshot(UTF8(fn));
else {
bool gsv = fn.size() >= 4 && wxString(fn.substr(fn.size() - 4)).IsSameAs(wxT(".gsv"), false);
@ -1061,18 +1061,18 @@ EVT_HANDLER_MASK(ImportGamesharkActionReplaySnapshot,
// FIXME: this will fail on big-endian machines if
// file format is little-endian
// fix in GBA.cpp
res = CPUReadGSASPSnapshot(fn.mb_fn_str());
res = CPUReadGSASPSnapshot(UTF8(fn));
else
// FIXME: this will fail on big-endian machines if
// file format is little-endian
// fix in GBA.cpp
res = CPUReadGSASnapshot(fn.mb_fn_str());
res = CPUReadGSASnapshot(UTF8(fn));
}
if (res)
msg.Printf(_("Loaded snapshot file %s"), fn.c_str());
msg.Printf(_("Loaded snapshot file %s"), fn.wc_str());
else
msg.Printf(_("Error loading snapshot file %s"), fn.c_str());
msg.Printf(_("Error loading snapshot file %s"), fn.wc_str());
systemScreenMessage(msg);
}
@ -1094,10 +1094,10 @@ EVT_HANDLER_MASK(ExportBatteryFile, "Export battery file...", CMDEN_GB | CMDEN_G
wxString fn = dlg.GetPath();
wxString msg;
if (panel->emusys->emuWriteBattery(fn.mb_fn_str()))
msg.Printf(_("Wrote battery %s"), fn.c_str());
if (panel->emusys->emuWriteBattery(UTF8(fn)))
msg.Printf(_("Wrote battery %s"), fn.wc_str());
else
msg.Printf(_("Error writing battery %s"), fn.c_str());
msg.Printf(_("Error writing battery %s"), fn.wc_str());
systemScreenMessage(msg);
}
@ -1138,9 +1138,9 @@ EVT_HANDLER_MASK(ExportGamesharkSnapshot, "Export GameShark snapshot...", CMDEN_
// fix in GBA.cpp
if (CPUWriteGSASnapshot(fn.utf8_str(), tit->GetValue().utf8_str(),
dsc->GetValue().utf8_str(), n->GetValue().utf8_str()))
msg.Printf(_("Saved snapshot file %s"), fn.c_str());
msg.Printf(_("Saved snapshot file %s"), fn.wc_str());
else
msg.Printf(_("Error saving snapshot file %s"), fn.c_str());
msg.Printf(_("Error saving snapshot file %s"), fn.wc_str());
systemScreenMessage(msg);
}
@ -1175,12 +1175,12 @@ EVT_HANDLER_MASK(ScreenCapture, "Screen capture...", CMDEN_GB | CMDEN_GBA)
}
if (fmt == 0)
panel->emusys->emuWritePNG(fn.mb_fn_str());
panel->emusys->emuWritePNG(UTF8(fn));
else
panel->emusys->emuWriteBMP(fn.mb_fn_str());
panel->emusys->emuWriteBMP(UTF8(fn));
wxString msg;
msg.Printf(_("Wrote snapshot %s"), fn.c_str());
msg.Printf(_("Wrote snapshot %s"), fn.wc_str());
systemScreenMessage(msg);
}
@ -2208,7 +2208,7 @@ void MainFrame::GDBBreak()
if (!debugOpenPty())
return;
msg.Printf(_("Waiting for connection at %s"), debugGetSlavePty().c_str());
msg.Printf(_("Waiting for connection at %s"), debugGetSlavePty().wc_str());
} else
#endif
{

View File

@ -246,10 +246,10 @@ public:
bool cld;
if (isgb)
cld = gbCheatsLoadCheatList(cheatfn.mb_fn_str());
cld = gbCheatsLoadCheatList(UTF8(cheatfn));
else {
if (cheatfn.EndsWith(wxT(".clt"))) {
cld = cheatsLoadCheatList(cheatfn.mb_fn_str());
cld = cheatsLoadCheatList(UTF8(cheatfn));
if (cld) {
*dirty = cheatfn != deffn;
@ -298,9 +298,9 @@ public:
// note that there is no way to test for succes of save
if (isgb)
gbCheatsSaveCheatList(cheatfn.mb_fn_str());
gbCheatsSaveCheatList(UTF8(cheatfn));
else
cheatsSaveCheatList(cheatfn.mb_fn_str());
cheatsSaveCheatList(UTF8(cheatfn));
if (cheatfn == deffn)
*dirty = false;

View File

@ -81,7 +81,7 @@ void GameArea::LoadGame(const wxString& name)
// auto-conversion of wxCharBuffer to const char * seems broken
// so save underlying wxCharBuffer (or create one of none is used)
wxCharBuffer fnb(fnfn.GetFullPath().mb_str(wxConvUTF8));
wxCharBuffer fnb(UTF8(fnfn.GetFullPath()));
const char* fn = fnb.data();
IMAGE_TYPE t = badfile ? IMAGE_UNKNOWN : utilFindType(fn);
@ -158,7 +158,7 @@ void GameArea::LoadGame(const wxString& name)
if (loadpatch) {
int size = rom_size;
applyPatch(pfn.GetFullPath().mb_str(), &gbRom, &size);
applyPatch(UTF8(pfn.GetFullPath()), &gbRom, &size);
if (size != (int)rom_size)
gbUpdateSizes();
@ -183,7 +183,9 @@ void GameArea::LoadGame(const wxString& name)
gbGetHardwareType();
bool use_bios = gbCgbMode ? useBiosFileGBC : useBiosFileGB;
const char* fn = (gbCgbMode ? gopts.gbc_bios : gopts.gb_bios).mb_str();
wxCharBuffer fnb(UTF8((gbCgbMode ? gopts.gbc_bios : gopts.gb_bios)));
const char* fn = fnb.data();
gbCPUInit(fn, use_bios);
@ -223,7 +225,7 @@ void GameArea::LoadGame(const wxString& name)
// don't use real rom size or it might try to resize rom[]
// instead, use known size of rom[]
int size = 0x2000000 < rom_size ? 0x2000000 : rom_size;
applyPatch(pfn.GetFullPath().mb_str(), &rom, &size);
applyPatch(UTF8(pfn.GetFullPath()), &rom, &size);
// that means we no longer really know rom_size either <sigh>
gbaUpdateRomSize(size);
@ -285,7 +287,7 @@ void GameArea::LoadGame(const wxString& name)
rtcEnableRumble(true);
CPUInit(gopts.gba_bios.mb_fn_str(), useBiosFileGBA);
CPUInit(UTF8(gopts.gba_bios), useBiosFileGBA);
if (useBiosFileGBA && !useBios) {
wxLogError(_("Could not load BIOS %s"), gopts.gba_bios.mb_str());
@ -355,9 +357,9 @@ void GameArea::LoadGame(const wxString& name)
bname.append(wxT(".sav"));
wxFileName bat(batdir, bname);
if (emusys->emuReadBattery(bat.GetFullPath().mb_str())) {
if (emusys->emuReadBattery(UTF8(bat.GetFullPath()))) {
wxString msg;
msg.Printf(_("Loaded battery %s"), bat.GetFullPath().mb_str());
msg.Printf(_("Loaded battery %s"), bat.GetFullPath().wc_str());
systemScreenMessage(msg);
if (cpuSaveType == 0 && ovSaveType == 0 && t == IMAGE_GBA) {
@ -409,9 +411,9 @@ void GameArea::LoadGame(const wxString& name)
bool cld;
if (loaded == IMAGE_GB)
cld = gbCheatsLoadCheatList(cfn.GetFullPath().mb_fn_str());
cld = gbCheatsLoadCheatList(UTF8(cfn.GetFullPath()));
else
cld = cheatsLoadCheatList(cfn.GetFullPath().mb_fn_str());
cld = cheatsLoadCheatList(UTF8(cfn.GetFullPath()));
if (cld) {
systemScreenMessage(_("Loaded cheats"));
@ -424,7 +426,7 @@ void GameArea::LoadGame(const wxString& name)
if (gopts.link_auto) {
linkMode = mf->GetConfiguredLinkMode();
BootLink(linkMode, gopts.link_host.mb_str(wxConvUTF8), linkTimeout, linkHacks, linkNumPlayers);
BootLink(linkMode, UTF8(gopts.link_host), linkTimeout, linkHacks, linkNumPlayers);
}
#endif
@ -496,12 +498,12 @@ void GameArea::UnloadGame(bool destruct)
if (!gbCheatNumber)
wxRemoveFile(cfn.GetFullPath());
else
gbCheatsSaveCheatList(cfn.GetFullPath().mb_fn_str());
gbCheatsSaveCheatList(UTF8(cfn.GetFullPath()));
} else {
if (!cheatsNumber)
wxRemoveFile(cfn.GetFullPath());
else
cheatsSaveCheatList(cfn.GetFullPath().mb_fn_str());
cheatsSaveCheatList(UTF8(cfn.GetFullPath()));
}
}
@ -578,14 +580,14 @@ bool GameArea::LoadState()
bool GameArea::LoadState(int slot)
{
wxString fname;
fname.Printf(SAVESLOT_FMT, game_name().mb_str(), slot);
fname.Printf(SAVESLOT_FMT, game_name().wc_str(), slot);
return LoadState(wxFileName(statedir, fname));
}
bool GameArea::LoadState(const wxFileName& fname)
{
// FIXME: first save to backup state if not backup state
bool ret = emusys->emuReadState(fname.GetFullPath().mb_fn_str());
bool ret = emusys->emuReadState(UTF8(fname.GetFullPath()));
if (ret && num_rewind_states) {
MainFrame* mf = wxGetApp().frame;
@ -612,7 +614,7 @@ bool GameArea::LoadState(const wxFileName& fname)
wxString msg;
msg.Printf(ret ? _("Loaded state %s") : _("Error loading state %s"),
fname.GetFullPath().mb_str());
fname.GetFullPath().wc_str());
systemScreenMessage(msg);
return ret;
}
@ -625,18 +627,18 @@ bool GameArea::SaveState()
bool GameArea::SaveState(int slot)
{
wxString fname;
fname.Printf(SAVESLOT_FMT, game_name().mb_str(), slot);
fname.Printf(SAVESLOT_FMT, game_name().wc_str(), slot);
return SaveState(wxFileName(statedir, fname));
}
bool GameArea::SaveState(const wxFileName& fname)
{
// FIXME: first copy to backup state if not backup state
bool ret = emusys->emuWriteState(fname.GetFullPath().mb_fn_str());
bool ret = emusys->emuWriteState(UTF8(fname.GetFullPath()));
wxGetApp().frame->update_state_ts(true);
wxString msg;
msg.Printf(ret ? _("Saved state %s") : _("Error saving state %s"),
fname.GetFullPath().mb_str());
fname.GetFullPath().wc_str());
systemScreenMessage(msg);
return ret;
}
@ -662,7 +664,7 @@ void GameArea::SaveBattery()
// FIXME: add option to support ring of backups
// of course some games just write battery way too often for such
// a thing to be useful
if (!emusys->emuWriteBattery(fn.mb_str()))
if (!emusys->emuWriteBattery(UTF8(fn)))
wxLogError(_("Error writing battery %s"), fn.mb_str());
systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED;
@ -1858,7 +1860,7 @@ void DrawingPanelBase::DrawArea(uint8_t** data)
if (panel->osdstat.size())
drawText(todraw + outstride * (systemColorDepth != 24), outstride,
10, 20, panel->osdstat.mb_str(), showSpeedTransparent);
10, 20, UTF8(panel->osdstat), showSpeedTransparent);
if (!disableStatusMessages && !panel->osdtext.empty()) {
if (systemGetClock() - panel->osdtime < OSD_TIME) {
@ -1866,7 +1868,7 @@ void DrawingPanelBase::DrawArea(uint8_t** data)
int linelen = std::ceil(width * scale - 20) / 8;
int nlines = (message.size() + linelen - 1) / linelen;
int cury = height - 14 - nlines * 10;
char* buf = strdup(message.mb_str());
char* buf = strdup(UTF8(message));
char* ptr = buf;
while (nlines > 1) {
@ -2394,7 +2396,7 @@ void GameArea::StartVidRecording(const wxString& fname)
recording::MediaRet ret;
vid_rec.SetSampleRate(soundGetSampleRate());
if ((ret = vid_rec.Record(fname.mb_str(), basic_width, basic_height,
if ((ret = vid_rec.Record(UTF8(fname), basic_width, basic_height,
systemColorDepth))
!= recording::MRET_OK)
wxLogError(_("Unable to begin recording to %s (%s)"), fname.mb_str(),
@ -2425,7 +2427,7 @@ void GameArea::StartSoundRecording(const wxString& fname)
recording::MediaRet ret;
snd_rec.SetSampleRate(soundGetSampleRate());
if ((ret = snd_rec.Record(fname.mb_str())) != recording::MRET_OK)
if ((ret = snd_rec.Record(UTF8(fname))) != recording::MRET_OK)
wxLogError(_("Unable to begin recording to %s (%s)"), fname.mb_str(),
media_err(ret));
else {

View File

@ -141,7 +141,7 @@ void systemStartGameRecording(const wxString& fname)
fn[fn.size() - 1] = wxT('0');
if (!panel->emusys->emuWriteState(fn.mb_fn_str())) {
if (!panel->emusys->emuWriteState(UTF8(fn))) {
wxLogError(_("Error writing game recording"));
game_file.Close();
return;
@ -212,7 +212,7 @@ void systemStartGamePlayback(const wxString& fname)
game_next_joypad = wxUINT32_SWAP_ON_BE(jp);
fn[fn.size() - 1] = wxT('0');
if (!panel->emusys->emuReadState(fn.mb_fn_str())) {
if (!panel->emusys->emuReadState(UTF8(fn))) {
wxLogError(_("Error reading game recording"));
game_file.Close();
return;
@ -442,12 +442,12 @@ void systemScreenCapture(int num)
fn.Mkdir(0777, wxPATH_MKDIR_FULL);
if (captureFormat == 0)
panel->emusys->emuWritePNG(fn.GetFullPath().mb_fn_str());
panel->emusys->emuWritePNG(UTF8(fn.GetFullPath()));
else // if(gopts.cap_format == 1)
panel->emusys->emuWriteBMP(fn.GetFullPath().mb_fn_str());
panel->emusys->emuWriteBMP(UTF8(fn.GetFullPath()));
wxString msg;
msg.Printf(_("Wrote snapshot %s"), fn.GetFullPath().c_str());
msg.Printf(_("Wrote snapshot %s"), fn.GetFullPath().wc_str());
systemScreenMessage(msg);
}
@ -822,7 +822,7 @@ void PrintDialog::DoSave(wxCommandEvent&)
if (scimg.SaveFile(of)) {
wxString msg;
msg.Printf(_("Wrote printer output to %s"), of.c_str());
msg.Printf(_("Wrote printer output to %s"), of.wc_str());
systemScreenMessage(msg);
wxButton* cb = wxStaticCast(dlg->FindWindow(wxID_CANCEL), wxButton);
@ -1001,11 +1001,11 @@ void systemGbPrint(uint8_t* data, int len, int pages, int feed, int pal, int con
systemGreenShift = 5;
systemBlueShift = 0;
wxString of = fn.GetFullPath();
bool ret = captureFormat == 0 ? utilWritePNGFile(of.mb_fn_str(), 160, lines, (uint8_t*)to_print) : utilWriteBMPFile(of.mb_fn_str(), 160, lines, (uint8_t*)to_print);
bool ret = captureFormat == 0 ? utilWritePNGFile(UTF8(of), 160, lines, (uint8_t*)to_print) : utilWriteBMPFile(UTF8(of), 160, lines, (uint8_t*)to_print);
if (ret) {
wxString msg;
msg.Printf(_("Wrote printer output to %s"), of.c_str());
msg.Printf(_("Wrote printer output to %s"), of.wc_str());
systemScreenMessage(msg);
}
@ -1040,7 +1040,7 @@ void systemGbPrint(uint8_t* data, int len, int pages, int feed, int pal, int con
void systemScreenMessage(const wxString& msg)
{
if (wxGetApp().frame && wxGetApp().frame->IsShown()) {
wxPuts(msg);
wxPuts(UTF8(msg)); // show **something** on terminal
MainFrame* f = wxGetApp().frame;
GameArea* panel = f->GetPanel();

View File

@ -113,8 +113,12 @@ static inline void DoSetAccel(wxMenuItem* mi, wxAcceleratorEntry* acc)
#define XRCCTRL(win, id, type) XRCCTRL_I(win, XRCID(id), type)
#define XRCCTRL_D(win, id, type) XRCCTRL_I(win, XRCID_D(id), type)
// wxWidgets provides fn_str(), but no mb_fn_str() or equiv.
#define mb_fn_str() mb_str(wxConvFile)
// Keep a single entry point for converting wxString to UTF8.
// Use this function whenever we want to get
static inline const wxCharBuffer UTF8(wxString str)
{
return str.mb_str(wxConvUTF8);
}
// by default, only 9 recent items
#define wxID_FILE10 (wxID_FILE9 + 1)

View File

@ -970,7 +970,7 @@ void MainFrame::update_state_ts(bool force)
if (panel->game_type() != IMAGE_UNKNOWN) {
wxString fn;
fn.Printf(SAVESLOT_FMT, panel->game_name().c_str(), i + 1);
fn.Printf(SAVESLOT_FMT, panel->game_name().wc_str(), i + 1);
wxFileName fp(panel->state_dir(), fn);
wxDateTime ts; // = wxInvalidDateTime