aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJesse Talavera-Greenberg <jesse@jesse.tg>2023-08-18 16:50:57 -0400
committerGitHub <noreply@github.com>2023-08-18 22:50:57 +0200
commitee5567708630441d8d3210e81d6e03d028fb7bbd (patch)
treeab92234123b16ec414d6c0da9bb0716c1b798229
parentf454eba3c3243b095f0e6b9ddde3e68b095c5d8d (diff)
Assorted portability enhancements (#1800)
* Introduce some Platform calls for managing dynamic libraries * Add Platform::WriteFATSectors * Introduce some Platform calls for managing dynamic libraries * Add Platform::WriteFATSectors * Change includes of "../types.h" to "types.h" - Makes it easier to directly include these headers in downstream projects * Change an include of "../Wifi.h" to "Wifi.h" * Allow CommonFuncs.cpp to compile on Android * Tidy up some logging calls - Use Platform::Log in LAN_Socket.cpp - Soften some warnings to Debug logs (since they don't necessarily represent problems) * Add Platform::EnterGBAMode - Gracefully stop the emulator if trying to enter GBA mode * Soften some logs that most players won't care about * Soften some more logs * Introduce Platform wrappers for file operations * Fix pointer spacing * Fix more style nits * Log the errno when ftruncate fails * Fix FileSeek offset argument - With an s32 offset, we couldn't access files larger than 2GB * Revise Platform::StopEmu to address feedback - Remove Platform::EnterGBAMode in favor of adding a reason to Platform::StopEmu - Also rename Platform::StopEmu to Platform::SignalStop - Add an optional argument to NDS::Stop - Use the new argument everywhere that the console stops itself * Rename FileGetString to FileReadLine - It conveys the meaning better * Rename FileSeekOrigin::Set to Start - It conveys the meaning better * Change definition of FileGetString to FileReadLine - Oops, almost forgot it * Rename FlushFile to FileFlush - To remain consistent with the other File functions * Add a FileType usage * Fix line break in FileSeekOrigin * Document Platform::DeInit * Clarify that StopReason::Unknown doesn't always mean an error * Move and document FileType::HostFile * Remove Platform::OpenDataFile - Nothing currently uses it * Refactor Platform::OpenFile and Platform::OpenLocalFile to accept a FileMode enum instead of a string - The enum is converted to fopen flags under the hood - The file type is used to decide whether to add the "b" flag - Some helper functions are exposed for the benefit of consistent behavior among frontends - Equivalent behavior is maintained * Fix a tab that should be spaces * Use Windows' 64-bit implementations of fseek/ftell * Move Platform::IsBinaryFile to Platform.cpp - It could vary by frontend * Remove an unused FileType * Rename an enum constant * Document various Platform items * Use Platform::DynamicLibrary to load libandroid - And clean it up at the end * Fix a typo * Pass the correct filetype to FATStorage - Since it can be used for DSI NAND images or for SD cards * Remove Platform::FileType
-rw-r--r--src/ARCodeFile.cpp37
-rw-r--r--src/ARM.cpp2
-rw-r--r--src/ARMJIT_Memory.cpp23
-rw-r--r--src/CP15.cpp4
-rw-r--r--src/DSi.cpp39
-rw-r--r--src/DSi_Camera.cpp16
-rw-r--r--src/DSi_I2C.cpp2
-rw-r--r--src/DSi_NAND.cpp52
-rw-r--r--src/DSi_NAND.h2
-rw-r--r--src/DSi_NWifi.cpp16
-rw-r--r--src/DSi_SD.cpp17
-rw-r--r--src/DSi_SD.h2
-rw-r--r--src/FATStorage.cpp97
-rw-r--r--src/FATStorage.h9
-rw-r--r--src/GBACart.cpp2
-rw-r--r--src/GPU2D.cpp6
-rw-r--r--src/GPU3D.cpp10
-rw-r--r--src/NDS.cpp100
-rw-r--r--src/NDS.h5
-rw-r--r--src/Platform.h261
-rw-r--r--src/SPI.cpp61
-rw-r--r--src/Wifi.cpp4
-rw-r--r--src/WifiAP.cpp8
-rw-r--r--src/dolphin/CommonFuncs.cpp3
-rw-r--r--src/frontend/qt_sdl/Config.cpp27
-rw-r--r--src/frontend/qt_sdl/Config.h1
-rw-r--r--src/frontend/qt_sdl/EmuSettingsDialog.cpp13
-rw-r--r--src/frontend/qt_sdl/LAN_PCap.cpp15
-rw-r--r--src/frontend/qt_sdl/LAN_PCap.h2
-rw-r--r--src/frontend/qt_sdl/LAN_Socket.cpp24
-rw-r--r--src/frontend/qt_sdl/LAN_Socket.h2
-rw-r--r--src/frontend/qt_sdl/Platform.cpp203
-rw-r--r--src/frontend/qt_sdl/ROMManager.cpp127
-rw-r--r--src/frontend/qt_sdl/SaveManager.cpp15
-rw-r--r--src/frontend/qt_sdl/TitleManagerDialog.cpp11
-rw-r--r--src/frontend/qt_sdl/main.cpp14
36 files changed, 788 insertions, 444 deletions
diff --git a/src/ARCodeFile.cpp b/src/ARCodeFile.cpp
index 45583ca..79c582d 100644
--- a/src/ARCodeFile.cpp
+++ b/src/ARCodeFile.cpp
@@ -21,8 +21,7 @@
#include "ARCodeFile.h"
#include "Platform.h"
-using Platform::Log;
-using Platform::LogLevel;
+using namespace Platform;
// TODO: import codes from other sources (usrcheat.dat, ...)
// TODO: more user-friendly error reporting
@@ -47,7 +46,7 @@ ARCodeFile::~ARCodeFile()
bool ARCodeFile::Load()
{
- FILE* f = Platform::OpenFile(Filename, "r");
+ FileHandle* f = OpenFile(Filename, FileMode::ReadText);
if (!f) return true;
Categories.clear();
@@ -59,9 +58,9 @@ bool ARCodeFile::Load()
ARCode curcode;
char linebuf[1024];
- while (!feof(f))
+ while (!IsEndOfFile(f))
{
- if (fgets(linebuf, 1024, f) == nullptr)
+ if (!FileReadLine(linebuf, 1024, f))
break;
linebuf[1023] = '\0';
@@ -82,7 +81,7 @@ bool ARCodeFile::Load()
if (ret < 1)
{
Log(LogLevel::Error, "AR: malformed CAT line: %s\n", start);
- fclose(f);
+ CloseFile(f);
return false;
}
@@ -105,14 +104,14 @@ bool ARCodeFile::Load()
if (ret < 2)
{
Log(LogLevel::Error, "AR: malformed CODE line: %s\n", start);
- fclose(f);
+ CloseFile(f);
return false;
}
if (!isincat)
{
Log(LogLevel::Error, "AR: encountered CODE line with no category started\n");
- fclose(f);
+ CloseFile(f);
return false;
}
@@ -131,21 +130,21 @@ bool ARCodeFile::Load()
if (ret < 2)
{
Log(LogLevel::Error, "AR: malformed data line: %s\n", start);
- fclose(f);
+ CloseFile(f);
return false;
}
if (!isincode)
{
Log(LogLevel::Error, "AR: encountered data line with no code started\n");
- fclose(f);
+ CloseFile(f);
return false;
}
if (curcode.CodeLen >= 2*64)
{
Log(LogLevel::Error, "AR: code too long!\n");
- fclose(f);
+ CloseFile(f);
return false;
}
@@ -159,36 +158,36 @@ bool ARCodeFile::Load()
if (isincode) curcat.Codes.push_back(curcode);
if (isincat) Categories.push_back(curcat);
- fclose(f);
+ CloseFile(f);
return true;
}
bool ARCodeFile::Save()
{
- FILE* f = Platform::OpenFile(Filename, "w");
+ FileHandle* f = Platform::OpenFile(Filename, FileMode::WriteText);
if (!f) return false;
for (ARCodeCatList::iterator it = Categories.begin(); it != Categories.end(); it++)
{
ARCodeCat& cat = *it;
- if (it != Categories.begin()) fprintf(f, "\r\n");
- fprintf(f, "CAT %s\r\n\r\n", cat.Name.c_str());
+ if (it != Categories.begin()) FileWriteFormatted(f, "\r\n");
+ FileWriteFormatted(f, "CAT %s\r\n\r\n", cat.Name.c_str());
for (ARCodeList::iterator jt = cat.Codes.begin(); jt != cat.Codes.end(); jt++)
{
ARCode& code = *jt;
- fprintf(f, "CODE %d %s\r\n", code.Enabled, code.Name.c_str());
+ FileWriteFormatted(f, "CODE %d %s\r\n", code.Enabled, code.Name.c_str());
for (u32 i = 0; i < code.CodeLen; i+=2)
{
- fprintf(f, "%08X %08X\r\n", code.Code[i], code.Code[i+1]);
+ FileWriteFormatted(f, "%08X %08X\r\n", code.Code[i], code.Code[i + 1]);
}
- fprintf(f, "\r\n");
+ FileWriteFormatted(f, "\r\n");
}
}
- fclose(f);
+ CloseFile(f);
return true;
}
diff --git a/src/ARM.cpp b/src/ARM.cpp
index 6063bca..b59530d 100644
--- a/src/ARM.cpp
+++ b/src/ARM.cpp
@@ -548,7 +548,7 @@ void ARMv5::PrefetchAbort()
if (!(PU_Map[ExceptionBase>>12] & 0x04))
{
Log(LogLevel::Error, "!!!!! EXCEPTION REGION NOT EXECUTABLE. THIS IS VERY BAD!!\n");
- NDS::Stop();
+ NDS::Stop(Platform::StopReason::BadExceptionRegion);
return;
}
diff --git a/src/ARMJIT_Memory.cpp b/src/ARMJIT_Memory.cpp
index 0901248..8e6a9f6 100644
--- a/src/ARMJIT_Memory.cpp
+++ b/src/ARMJIT_Memory.cpp
@@ -112,6 +112,7 @@ bool FaultHandler(FaultDescription& faultDesc);
#if defined(__ANDROID__)
#define ASHMEM_DEVICE "/dev/ashmem"
+Platform::DynamicLibrary* Libandroid = nullptr;
#endif
#if defined(__SWITCH__)
@@ -753,14 +754,13 @@ void Init()
MemoryBase = MemoryBase + AddrSpaceSize*2;
#if defined(__ANDROID__)
- static void* libandroid = dlopen("libandroid.so", RTLD_LAZY | RTLD_LOCAL);
+ Libandroid = Platform::DynamicLibrary_Load("libandroid.so");
using type_ASharedMemory_create = int(*)(const char* name, size_t size);
- static void* symbol = dlsym(libandroid, "ASharedMemory_create");
- static auto shared_memory_create = reinterpret_cast<type_ASharedMemory_create>(symbol);
+ auto ASharedMemory_create = reinterpret_cast<type_ASharedMemory_create>(Platform::DynamicLibrary_LoadFunction(Libandroid, "ASharedMemory_create"));
- if (shared_memory_create)
+ if (ASharedMemory_create)
{
- MemoryFile = shared_memory_create("melondsfastmem", MemoryTotalSize);
+ MemoryFile = ASharedMemory_create("melondsfastmem", MemoryTotalSize);
}
else
{
@@ -775,13 +775,13 @@ void Init()
MemoryFile = shm_open(fastmemPidName, O_RDWR | O_CREAT | O_EXCL, 0600);
if (MemoryFile == -1)
{
- Log(LogLevel::Error, "Failed to open memory using shm_open!");
+ Log(LogLevel::Error, "Failed to open memory using shm_open! (%s)", strerror(errno));
}
shm_unlink(fastmemPidName);
#endif
if (ftruncate(MemoryFile, MemoryTotalSize) < 0)
{
- Log(LogLevel::Error, "Failed to allocate memory using ftruncate!");
+ Log(LogLevel::Error, "Failed to allocate memory using ftruncate! (%s)", strerror(errno));
}
struct sigaction sa;
@@ -830,6 +830,15 @@ void DeInit()
munmap(MemoryBase, MemoryTotalSize);
close(MemoryFile);
+
+#if defined(__ANDROID__)
+ if (Libandroid)
+ {
+ Platform::DynamicLibrary_Unload(Libandroid);
+ Libandroid = nullptr;
+ }
+#endif
+
#endif
}
diff --git a/src/CP15.cpp b/src/CP15.cpp
index 7db7b60..52fd560 100644
--- a/src/CP15.cpp
+++ b/src/CP15.cpp
@@ -668,7 +668,7 @@ void ARMv5::CP15Write(u32 id, u32 val)
return;
if ((id & 0xF00) != 0x700)
- Log(LogLevel::Warn, "unknown CP15 write op %03X %08X\n", id, val);
+ Log(LogLevel::Debug, "unknown CP15 write op %03X %08X\n", id, val);
}
u32 ARMv5::CP15Read(u32 id)
@@ -764,7 +764,7 @@ u32 ARMv5::CP15Read(u32 id)
if ((id & 0xF00) == 0xF00) // test/debug shit?
return 0;
- Log(LogLevel::Warn, "unknown CP15 read op %03X\n", id);
+ Log(LogLevel::Debug, "unknown CP15 read op %03X\n", id);
return 0;
}
diff --git a/src/DSi.cpp b/src/DSi.cpp
index c6df5df..2f92a5d 100644
--- a/src/DSi.cpp
+++ b/src/DSi.cpp
@@ -43,8 +43,7 @@
#include "tiny-AES-c/aes.hpp"
-using Platform::Log;
-using Platform::LogLevel;
+using namespace Platform;
namespace DSi
{
@@ -719,13 +718,13 @@ void SoftReset()
bool LoadBIOS()
{
- FILE* f;
+ Platform::FileHandle* f;
u32 i;
memset(ARM9iBIOS, 0, 0x10000);
memset(ARM7iBIOS, 0, 0x10000);
- f = Platform::OpenLocalFile(Platform::GetConfigString(Platform::DSi_BIOS9Path), "rb");
+ f = Platform::OpenLocalFile(Platform::GetConfigString(Platform::DSi_BIOS9Path), FileMode::Read);
if (!f)
{
Log(LogLevel::Warn, "ARM9i BIOS not found\n");
@@ -735,14 +734,14 @@ bool LoadBIOS()
}
else
{
- fseek(f, 0, SEEK_SET);
- fread(ARM9iBIOS, 0x10000, 1, f);
+ FileRewind(f);
+ FileRead(ARM9iBIOS, 0x10000, 1, f);
Log(LogLevel::Info, "ARM9i BIOS loaded\n");
- fclose(f);
+ Platform::CloseFile(f);
}
- f = Platform::OpenLocalFile(Platform::GetConfigString(Platform::DSi_BIOS7Path), "rb");
+ f = Platform::OpenLocalFile(Platform::GetConfigString(Platform::DSi_BIOS7Path), FileMode::Read);
if (!f)
{
Log(LogLevel::Warn, "ARM7i BIOS not found\n");
@@ -754,11 +753,11 @@ bool LoadBIOS()
{
// TODO: check if the first 32 bytes are crapoed
- fseek(f, 0, SEEK_SET);
- fread(ARM7iBIOS, 0x10000, 1, f);
+ FileRewind(f);
+ FileRead(ARM7iBIOS, 0x10000, 1, f);
Log(LogLevel::Info, "ARM7i BIOS loaded\n");
- fclose(f);
+ CloseFile(f);
}
if (!Platform::GetConfigBool(Platform::DSi_FullBIOSBoot))
@@ -785,7 +784,7 @@ bool LoadNAND()
return false;
}
- FILE* nand = DSi_NAND::GetFile();
+ FileHandle* nand = DSi_NAND::GetFile();
// Make sure NWRAM is accessible.
// The Bits are set to the startup values in Reset() and we might
@@ -829,8 +828,8 @@ bool LoadNAND()
}
else
{
- fseek(nand, 0x220, SEEK_SET);
- fread(bootparams, 4, 8, nand);
+ FileSeek(nand, 0x220, FileSeekOrigin::Start);
+ FileRead(bootparams, 4, 8, nand);
Log(LogLevel::Debug, "ARM9: offset=%08X size=%08X RAM=%08X size_aligned=%08X\n",
bootparams[0], bootparams[1], bootparams[2], bootparams[3]);
@@ -843,8 +842,8 @@ bool LoadNAND()
MBK[1][8] = 0;
u32 mbk[12];
- fseek(nand, 0x380, SEEK_SET);
- fread(mbk, 4, 12, nand);
+ FileSeek(nand, 0x380, FileSeekOrigin::Start);
+ FileRead(mbk, 4, 12, nand);
MapNWRAM_A(0, mbk[0] & 0xFF);
MapNWRAM_A(1, (mbk[0] >> 8) & 0xFF);
@@ -898,12 +897,12 @@ bool LoadNAND()
AES_init_ctx_iv(&ctx, boot2key, boot2iv);
- fseek(nand, bootparams[0], SEEK_SET);
+ FileSeek(nand, bootparams[0], FileSeekOrigin::Start);
dstaddr = bootparams[2];
for (u32 i = 0; i < bootparams[3]; i += 16)
{
u8 data[16];
- fread(data, 16, 1, nand);
+ FileRead(data, 16, 1, nand);
for (int j = 0; j < 16; j++) tmp[j] = data[15-j];
AES_CTR_xcrypt_buffer(&ctx, tmp, 16);
@@ -923,12 +922,12 @@ bool LoadNAND()
AES_init_ctx_iv(&ctx, boot2key, boot2iv);
- fseek(nand, bootparams[4], SEEK_SET);
+ FileSeek(nand, bootparams[4], FileSeekOrigin::Start);
dstaddr = bootparams[6];
for (u32 i = 0; i < bootparams[7]; i += 16)
{
u8 data[16];
- fread(data, 16, 1, nand);
+ FileRead(data, 16, 1, nand);
for (int j = 0; j < 16; j++) tmp[j] = data[15-j];
AES_CTR_xcrypt_buffer(&ctx, tmp, 16);
diff --git a/src/DSi_Camera.cpp b/src/DSi_Camera.cpp
index 19e6c5e..9f45a6a 100644
--- a/src/DSi_Camera.cpp
+++ b/src/DSi_Camera.cpp
@@ -247,7 +247,7 @@ u8 Read8(u32 addr)
{
//
- Log(LogLevel::Warn, "unknown DSi cam read8 %08X\n", addr);
+ Log(LogLevel::Debug, "unknown DSi cam read8 %08X\n", addr);
return 0;
}
@@ -259,7 +259,7 @@ u16 Read16(u32 addr)
case 0x04004202: return Cnt;
}
- Log(LogLevel::Warn, "unknown DSi cam read16 %08X\n", addr);
+ Log(LogLevel::Debug, "unknown DSi cam read16 %08X\n", addr);
return 0;
}
@@ -285,7 +285,7 @@ u32 Read32(u32 addr)
case 0x04004214: return CropEnd;
}
- Log(LogLevel::Warn, "unknown DSi cam read32 %08X\n", addr);
+ Log(LogLevel::Debug, "unknown DSi cam read32 %08X\n", addr);
return 0;
}
@@ -293,7 +293,7 @@ void Write8(u32 addr, u8 val)
{
//
- Log(LogLevel::Warn, "unknown DSi cam write8 %08X %02X\n", addr, val);
+ Log(LogLevel::Debug, "unknown DSi cam write8 %08X %02X\n", addr, val);
}
void Write16(u32 addr, u16 val)
@@ -372,7 +372,7 @@ void Write16(u32 addr, u16 val)
return;
}
- Log(LogLevel::Warn, "unknown DSi cam write16 %08X %04X\n", addr, val);
+ Log(LogLevel::Debug, "unknown DSi cam write16 %08X %04X\n", addr, val);
}
void Write32(u32 addr, u32 val)
@@ -389,7 +389,7 @@ void Write32(u32 addr, u32 val)
return;
}
- Log(LogLevel::Warn, "unknown DSi cam write32 %08X %08X\n", addr, val);
+ Log(LogLevel::Debug, "unknown DSi cam write32 %08X %08X\n", addr, val);
}
@@ -638,7 +638,7 @@ u16 Camera::I2C_ReadReg(u16 addr)
case 0x301A: return ((~StandbyCnt) & 0x4000) >> 12;
}
- if(Num==1) Log(LogLevel::Warn, "DSi_Camera%d: unknown read %04X\n", Num, addr);
+ if(Num==1) Log(LogLevel::Debug, "DSi_Camera%d: unknown read %04X\n", Num, addr);
return 0;
}
@@ -704,7 +704,7 @@ void Camera::I2C_WriteReg(u16 addr, u16 val)
return;
}
- if(Num==1) Log(LogLevel::Warn, "DSi_Camera%d: unknown write %04X %04X\n", Num, addr, val);
+ if(Num==1) Log(LogLevel::Debug, "DSi_Camera%d: unknown write %04X %04X\n", Num, addr, val);
}
diff --git a/src/DSi_I2C.cpp b/src/DSi_I2C.cpp
index 7bb7e1d..c4ad50c 100644
--- a/src/DSi_I2C.cpp
+++ b/src/DSi_I2C.cpp
@@ -199,7 +199,7 @@ void DoHardwareReset(bool direct)
void DoShutdown()
{
ResetButtonState();
- NDS::Stop();
+ NDS::Stop(Platform::StopReason::PowerOff);
}
diff --git a/src/DSi_NAND.cpp b/src/DSi_NAND.cpp
index 6adfcff..38f8c52 100644
--- a/src/DSi_NAND.cpp
+++ b/src/DSi_NAND.cpp
@@ -29,13 +29,12 @@
#include "fatfs/ff.h"
-using Platform::Log;
-using Platform::LogLevel;
+using namespace Platform;
namespace DSi_NAND
{
-FILE* CurFile;
+FileHandle* CurFile;
FATFS CurFS;
u8 eMMC_CID[16];
@@ -58,21 +57,19 @@ bool Init(u8* es_keyY)
std::string nandpath = Platform::GetConfigString(Platform::DSi_NANDPath);
std::string instnand = nandpath + Platform::InstanceFileSuffix();
- FILE* nandfile = Platform::OpenLocalFile(instnand, "r+b");
+ FileHandle* nandfile = Platform::OpenLocalFile(instnand, FileMode::ReadWriteExisting);
if ((!nandfile) && (Platform::InstanceID() > 0))
{
- FILE* orig = Platform::OpenLocalFile(nandpath, "rb");
+ FileHandle* orig = Platform::OpenLocalFile(nandpath, FileMode::Read);
if (!orig)
{
Log(LogLevel::Error, "Failed to open DSi NAND\n");
return false;
}
- fseek(orig, 0, SEEK_END);
- long len = ftell(orig);
- fseek(orig, 0, SEEK_SET);
+ long len = FileLength(orig);
- nandfile = Platform::OpenLocalFile(instnand, "w+b");
+ nandfile = Platform::OpenLocalFile(instnand, FileMode::ReadWrite);
if (nandfile)
{
u8* tmpbuf = new u8[0x10000];
@@ -81,23 +78,22 @@ bool Init(u8* es_keyY)
long blklen = 0x10000;
if ((i+blklen) > len) blklen = len-i;
- fread(tmpbuf, blklen, 1, orig);
- fwrite(tmpbuf, blklen, 1, nandfile);
+ FileRead(tmpbuf, blklen, 1, orig);
+ FileWrite(tmpbuf, blklen, 1, nandfile);
}
delete[] tmpbuf;
}
- fclose(orig);
- fclose(nandfile);
+ Platform::CloseFile(orig);
+ Platform::CloseFile(nandfile);
- nandfile = Platform::OpenLocalFile(instnand, "r+b");
+ nandfile = Platform::OpenLocalFile(instnand, FileMode::ReadWriteExisting);
}
if (!nandfile)
return false;
- fseek(nandfile, 0, SEEK_END);
- u64 nandlen = ftell(nandfile);
+ u64 nandlen = FileLength(nandfile);
ff_disk_open(FF_ReadNAND, FF_WriteNAND, (LBA_t)(nandlen>>9));
@@ -113,18 +109,18 @@ bool Init(u8* es_keyY)
// read the nocash footer
- fseek(nandfile, -0x40, SEEK_END);
+ FileSeek(nandfile, -0x40, FileSeekOrigin::End);
char nand_footer[16];
const char* nand_footer_ref = "DSi eMMC CID/CPU";
- fread(nand_footer, 1, 16, nandfile);
+ FileRead(nand_footer, 1, 16, nandfile);
if (memcmp(nand_footer, nand_footer_ref, 16))
{
// There is another copy of the footer at 000FF800h for the case
// that by external tools the image was cut off
// See https://problemkaputt.de/gbatek.htm#dsisdmmcimages
- fseek(nandfile, 0x000FF800, SEEK_SET);
- fread(nand_footer, 1, 16, nandfile);
+ FileSeek(nandfile, 0x000FF800, FileSeekOrigin::Start);
+ FileRead(nand_footer, 1, 16, nandfile);
if (memcmp(nand_footer, nand_footer_ref, 16))
{
Log(LogLevel::Error, "ERROR: NAND missing nocash footer\n");
@@ -132,8 +128,8 @@ bool Init(u8* es_keyY)
}
}
- fread(eMMC_CID, 1, 16, nandfile);
- fread(&ConsoleID, 1, 8, nandfile);
+ FileRead(eMMC_CID, 1, 16, nandfile);
+ FileRead(&ConsoleID, 1, 8, nandfile);
// init NAND crypto
@@ -180,12 +176,12 @@ void DeInit()
f_unmount("0:");
ff_disk_close();
- if (CurFile) fclose(CurFile);
+ if (CurFile) CloseFile(CurFile);
CurFile = nullptr;
}
-FILE* GetFile()
+FileHandle* GetFile()
{
return CurFile;
}
@@ -229,8 +225,8 @@ u32 ReadFATBlock(u64 addr, u32 len, u8* buf)
AES_ctx ctx;
SetupFATCrypto(&ctx, ctr);
- fseek(CurFile, addr, SEEK_SET);
- u32 res = fread(buf, len, 1, CurFile);
+ FileSeek(CurFile, addr, FileSeekOrigin::Start);
+ u32 res = FileRead(buf, len, 1, CurFile);
if (!res) return 0;
for (u32 i = 0; i < len; i += 16)
@@ -251,7 +247,7 @@ u32 WriteFATBlock(u64 addr, u32 len, u8* buf)
AES_ctx ctx;
SetupFATCrypto(&ctx, ctr);
- fseek(CurFile, addr, SEEK_SET);
+ FileSeek(CurFile, addr, FileSeekOrigin::Start);
for (u32 s = 0; s < len; s += 0x200)
{
@@ -265,7 +261,7 @@ u32 WriteFATBlock(u64 addr, u32 len, u8* buf)
DSi_AES::Swap16(&tempbuf[i], tmp);
}
- u32 res = fwrite(tempbuf, 0x200, 1, CurFile);
+ u32 res = FileWrite(tempbuf, sizeof(tempbuf), 1, CurFile);
if (!res) return 0;
}
diff --git a/src/DSi_NAND.h b/src/DSi_NAND.h
index 76d5ee2..14599b2 100644
--- a/src/DSi_NAND.h
+++ b/src/DSi_NAND.h
@@ -38,7 +38,7 @@ enum
bool Init(u8* es_keyY);
void DeInit();
-FILE* GetFile();
+Platform::FileHandle* GetFile();
void GetIDs(u8* emmc_cid, u64& consoleid);
diff --git a/src/DSi_NWifi.cpp b/src/DSi_NWifi.cpp
index b07d7a7..2f84cdc 100644
--- a/src/DSi_NWifi.cpp
+++ b/src/DSi_NWifi.cpp
@@ -356,7 +356,7 @@ u8 DSi_NWifi::F0_Read(u32 addr)
return CIS1[addr & 0xFF];
}
- Log(LogLevel::Warn, "NWIFI: unknown func0 read %05X\n", addr);
+ Log(LogLevel::Debug, "NWIFI: unknown func0 read %05X\n", addr);
return 0;
}
@@ -370,7 +370,7 @@ void DSi_NWifi::F0_Write(u32 addr, u8 val)
return;
}
- Log(LogLevel::Warn, "NWIFI: unknown func0 write %05X %02X\n", addr, val);
+ Log(LogLevel::Debug, "NWIFI: unknown func0 write %05X %02X\n", addr, val);
}
@@ -582,7 +582,7 @@ void DSi_NWifi::F1_Write(u32 addr, u8 val)
return;
}
- Log(LogLevel::Warn, "NWIFI: unknown func1 write %05X %02X\n", addr, val);
+ Log(LogLevel::Debug, "NWIFI: unknown func1 write %05X %02X\n", addr, val);
}
@@ -594,7 +594,7 @@ u8 DSi_NWifi::SDIO_Read(u32 func, u32 addr)
case 1: return F1_Read(addr);
}
- Log(LogLevel::Warn, "NWIFI: unknown SDIO read %d %05X\n", func, addr);
+ Log(LogLevel::Debug, "NWIFI: unknown SDIO read %d %05X\n", func, addr);
return 0;
}
@@ -606,7 +606,7 @@ void DSi_NWifi::SDIO_Write(u32 func, u32 addr, u8 val)
case 1: return F1_Write(addr, val);
}
- Log(LogLevel::Warn, "NWIFI: unknown SDIO write %d %05X %02X\n", func, addr, val);
+ Log(LogLevel::Debug, "NWIFI: unknown SDIO write %d %05X %02X\n", func, addr, val);
}
@@ -874,7 +874,7 @@ void DSi_NWifi::HTC_Command()
{
u16 svc_id = MB_Read16(0);
u16 conn_flags = MB_Read16(0);
- Log(LogLevel::Info, "service connect %04X %04X %04X\n", svc_id, conn_flags, MB_Read16(0));
+ Log(LogLevel::Debug, "service connect %04X %04X %04X\n", svc_id, conn_flags, MB_Read16(0));
u8 svc_resp[8];
// responses from hardware:
@@ -952,7 +952,7 @@ void DSi_NWifi::WMI_Command()
if (ConnectionStatus != 1)
Log(LogLevel::Warn, "WMI: ?? trying to disconnect while not connected\n");
- Log(LogLevel::Info, "WMI: disconnect\n");
+ Log(LogLevel::Debug, "WMI: disconnect\n");
ConnectionStatus = 0;
u8 reply[11];
@@ -1218,7 +1218,7 @@ void DSi_NWifi::WMI_ConnectToNetwork()
return;
}
- Log(LogLevel::Info, "WMI: connecting to network %s\n", ssid);
+ Log(LogLevel::Debug, "WMI: connecting to network %s\n", ssid);
u8 reply[20];
diff --git a/src/DSi_SD.cpp b/src/DSi_SD.cpp
index 59262cb..4f287b1 100644
--- a/src/DSi_SD.cpp
+++ b/src/DSi_SD.cpp
@@ -23,8 +23,7 @@
#include "DSi_NWifi.h"
#include "Platform.h"
-using Platform::Log;
-using Platform::LogLevel;
+using namespace Platform;
// observed IRQ behavior during transfers
//
@@ -773,7 +772,7 @@ DSi_MMCStorage::DSi_MMCStorage(DSi_SDHost* host, bool internal, const std::strin
: DSi_SDDevice(host)
{
Internal = internal;
- File = Platform::OpenLocalFile(filename, "r+b");
+ File = Platform::OpenLocalFile(filename, FileMode::ReadWriteExisting);
SD = nullptr;
@@ -801,7 +800,7 @@ DSi_MMCStorage::~DSi_MMCStorage()
}
if (File)
{
- fclose(File);
+ CloseFile(File);
}
}
@@ -926,7 +925,7 @@ void DSi_MMCStorage::SendCMD(u8 cmd, u32 param)
case 12: // stop operation
SetState(0x04);
- if (File) fflush(File);
+ if (File) FileFlush(File);
RWCommand = 0;
Host->SendResponse(CSR, true);
return;
@@ -1055,8 +1054,8 @@ u32 DSi_MMCStorage::ReadBlock(u64 addr)
}
else if (File)
{
- fseek(File, addr, SEEK_SET);
- fread(&data[addr & 0x1FF], 1, len, File);
+ FileSeek(File, addr, FileSeekOrigin::Start);
+ FileRead(&data[addr & 0x1FF], 1, len, File);
}
return Host->DataRX(&data[addr & 0x1FF], len);
@@ -1085,8 +1084,8 @@ u32 DSi_MMCStorage::WriteBlock(u64 addr)
}
else if (File)
{
- fseek(File, addr, SEEK_SET);
- fwrite(&data[addr & 0x1FF], 1, len, File);
+ FileSeek(File, addr, FileSeekOrigin::Start);
+ FileWrite(&data[addr & 0x1FF], 1, len, File);
}
}
}
diff --git a/src/DSi_SD.h b/src/DSi_SD.h
index 75101ed..fe9e23a 100644
--- a/src/DSi_SD.h
+++ b/src/DSi_SD.h
@@ -142,7 +142,7 @@ public:
private:
bool Internal;
- FILE* File;
+ Platform::FileHandle* File;
FATStorage* SD;
u8 CID[16];
diff --git a/src/FATStorage.cpp b/src/FATStorage.cpp
index 07cf491..d882f8d 100644
--- a/src/FATStorage.cpp
+++ b/src/FATStorage.cpp
@@ -25,17 +25,7 @@
#include "Platform.h"
namespace fs = std::filesystem;
-
-
-// really, Windows?
-#ifdef __WIN32__
- #define melon_fseek _fseeki64
- #define melon_ftell _ftelli64
-#else
- #define melon_fseek fseek
- #define melon_ftell ftell
-#endif // __WIN32__
-
+using namespace Platform;
FATStorage::FATStorage(const std::string& filename, u64 size, bool readonly, const std::string& sourcedir)
{
@@ -53,7 +43,7 @@ FATStorage::~FATStorage()
bool FATStorage::Open()
{
- File = Platform::OpenLocalFile(FilePath.c_str(), "r+b");
+ File = Platform::OpenLocalFile(FilePath, FileMode::ReadWriteExisting);
if (!File)
{
return false;
@@ -64,7 +54,7 @@ bool FATStorage::Open()
void FATStorage::Close()
{
- if (File) fclose(File);
+ if (File) CloseFile(File);
File = nullptr;
}
@@ -124,7 +114,7 @@ u32 FATStorage::WriteSectors(u32 start, u32 num, u8* data)
}
-FILE* FATStorage::FF_File;
+FileHandle* FATStorage::FF_File;
u64 FATStorage::FF_FileSize;
UINT FATStorage::FF_ReadStorage(BYTE* buf, LBA_t sector, UINT num)
@@ -138,7 +128,7 @@ UINT FATStorage::FF_WriteStorage(BYTE* buf, LBA_t sector, UINT num)
}
-u32 FATStorage::ReadSectorsInternal(FILE* file, u64 filelen, u32 start, u32 num, u8* data)
+u32 FATStorage::ReadSectorsInternal(FileHandle* file, u64 filelen, u32 start, u32 num, u8* data)
{
if (!file) return 0;
@@ -152,12 +142,12 @@ u32 FATStorage::ReadSectorsInternal(FILE* file, u64 filelen, u32 start, u32 num,
num = len >> 9;
}
- melon_fseek(file, addr, SEEK_SET);
+ FileSeek(file, addr, FileSeekOrigin::Start);
- u32 res = fread(data, 0x200, num, file);
+ u32 res = FileRead(data, 0x200, num, file);
if (res < num)
{
- if (feof(file))
+ if (IsEndOfFile(file))
{
memset(&data[0x200*res], 0, 0x200*(num-res));
return num;
@@ -167,7 +157,7 @@ u32 FATStorage::ReadSectorsInternal(FILE* file, u64 filelen, u32 start, u32 num,
return res;
}
-u32 FATStorage::WriteSectorsInternal(FILE* file, u64 filelen, u32 start, u32 num, u8* data)
+u32 FATStorage::WriteSectorsInternal(FileHandle* file, u64 filelen, u32 start, u32 num, u8* data)
{
if (!file) return 0;
@@ -181,9 +171,9 @@ u32 FATStorage::WriteSectorsInternal(FILE* file, u64 filelen, u32 start, u32 num
num = len >> 9;
}
- melon_fseek(file, addr, SEEK_SET);
+ FileSeek(file, addr, FileSeekOrigin::Start);
- u32 res = fwrite(data, 0x200, num, file);
+ u32 res = Platform::FileWrite(data, 0x200, num, file);
return res;
}
@@ -193,13 +183,13 @@ void FATStorage::LoadIndex()
DirIndex.clear();
FileIndex.clear();
- FILE* f = Platform::OpenLocalFile(IndexPath.c_str(), "r");
+ FileHandle* f = OpenLocalFile(IndexPath, FileMode::ReadText);
if (!f) return;
char linebuf[1536];
- while (!feof(f))
+ while (!IsEndOfFile(f))
{
- if (fgets(linebuf, 1536, f) == nullptr)
+ if (!FileReadLine(linebuf, 1536, f))
break;
if (linebuf[0] == 'S')
@@ -258,7 +248,7 @@ void FATStorage::LoadIndex()
}
}
- fclose(f);
+ CloseFile(f);
// ensure the indexes are sane
@@ -325,31 +315,31 @@ void FATStorage::LoadIndex()
void FATStorage::SaveIndex()
{
- FILE* f = Platform::OpenLocalFile(IndexPath.c_str(), "w");
+ FileHandle* f = OpenLocalFile(IndexPath, FileMode::WriteText);
if (!f) return;
- fprintf(f, "SIZE %" PRIu64 "\r\n", FileSize);
+ FileWriteFormatted(f, "SIZE %" PRIu64 "\r\n", FileSize);
for (const auto& [key, val] : DirIndex)
{
- fprintf(f, "DIR %u %s\r\n",
+ FileWriteFormatted(f, "DIR %u %s\r\n",
val.IsReadOnly?1:0, val.Path.c_str());
}
for (const auto& [key, val] : FileIndex)
{
- fprintf(f, "FILE %u %" PRIu64 " %" PRId64 " %u %s\r\n",
+ FileWriteFormatted(f, "FILE %u %" PRIu64 " %" PRId64 " %u %s\r\n",
val.IsReadOnly?1:0, val.Size, val.LastModified, val.LastModifiedInternal, val.Path.c_str());
}
- fclose(f);
+ CloseFile(f);
}
bool FATStorage::ExportFile(const std::string& path, fs::path out)
{
FF_FIL file;
- FILE* fout;
+ FileHandle* fout;
FRESULT res;
res = f_open(&file, path.c_str(), FA_OPEN_EXISTING | FA_READ);
@@ -367,7 +357,7 @@ bool FATStorage::ExportFile(const std::string& path, fs::path out)
err);
}
- fout = Platform::OpenFile(out.u8string().c_str(), "wb");
+ fout = OpenFile(out.u8string(), FileMode::Write);
if (!fout)
{
f_close(&file);
@@ -385,10 +375,10 @@ bool FATStorage::ExportFile(const std::string& path, fs::path out)
u32 nread;
f_read(&file, buf, blocklen, &nread);
- fwrite(buf, blocklen, 1, fout);
+ FileWrite(buf, blocklen, 1, fout);
}
- fclose(fout);
+ CloseFile(fout);
f_close(&file);
return true;
@@ -782,27 +772,25 @@ void FATStorage::CleanupDirectory(const std::string& sourcedir, const std::strin
bool FATStorage::ImportFile(const std::string& path, fs::path in)
{
FF_FIL file;
- FILE* fin;
+ FileHandle* fin;
FRESULT res;
- fin = Platform::OpenFile(in.u8string().c_str(), "rb");
+ fin = Platform::OpenFile(in.u8string(), FileMode::Read);
if (!fin)
return false;
- fseek(fin, 0, SEEK_END);
- u32 len = (u32)ftell(fin);
- fseek(fin, 0, SEEK_SET);
+ u32 len = FileLength(fin);
if (!CanFitFile(len))
{
- fclose(fin);
+ CloseFile(fin);
return false;
}
res = f_open(&file, path.c_str(), FA_CREATE_ALWAYS | FA_WRITE);
if (res != FR_OK)
{
- fclose(fin);
+ CloseFile(fin);
return false;
}
@@ -816,11 +804,11 @@ bool FATStorage::ImportFile(const std::string& path, fs::path in)
blocklen = 0x1000;
u32 nwrite;
- fread(buf, blocklen, 1, fin);
+ FileRead(buf, blocklen, 1, fin);
f_write(&file, buf, blocklen, &nwrite);
}
- fclose(fin);
+ CloseFile(fin);
f_close(&file);
return true;
@@ -961,16 +949,10 @@ bool FATStorage::Load(const std::string& filename, u64 size, const std::string&
// * if no image: if sourcing from a directory, size is calculated from that
// with a minimum 128MB extra, otherwise size is defaulted to 512MB
- bool isnew = false;
- FF_File = Platform::OpenLocalFile(filename.c_str(), "r+b");
+ bool isnew = !Platform::LocalFileExists(filename);
+ FF_File = Platform::OpenLocalFile(filename, static_cast<FileMode>(FileMode::ReadWrite | FileMode::Preserve));
if (!FF_File)
- {
- FF_File = Platform::OpenLocalFile(filename.c_str(), "w+b");
- if (!FF_File)
- return false;
-
- isnew = true;
- }
+ return false;
IndexPath = FilePath + ".idx";
if (isnew)
@@ -985,8 +967,7 @@ bool FATStorage::Load(const std::string& filename, u64 size, const std::string&
if (FileSize == 0)
{
- melon_fseek(FF_File, 0, SEEK_END);
- FileSize = melon_ftell(FF_File);
+ FileSize = FileLength(FF_File);
}
}
@@ -1076,7 +1057,7 @@ bool FATStorage::Load(const std::string& filename, u64 size, const std::string&
f_unmount("0:");
ff_disk_close();
- fclose(FF_File);
+ CloseFile(FF_File);
FF_File = nullptr;
return true;
@@ -1089,7 +1070,7 @@ bool FATStorage::Save()
return true;
}
- FF_File = Platform::OpenLocalFile(FilePath.c_str(), "r+b");
+ FF_File = Platform::OpenLocalFile(FilePath, FileMode::ReadWriteExisting);
if (!FF_File)
{
return false;
@@ -1105,7 +1086,7 @@ bool FATStorage::Save()
if (res != FR_OK)
{
ff_disk_close();
- fclose(FF_File);
+ CloseFile(FF_File);
FF_File = nullptr;
return false;
}
@@ -1117,7 +1098,7 @@ bool FATStorage::Save()
f_unmount("0:");
ff_disk_close();
- fclose(FF_File);
+ CloseFile(FF_File);
FF_File = nullptr;
return true;
diff --git a/src/FATStorage.h b/src/FATStorage.h
index 250f023..6b9beb5 100644
--- a/src/FATStorage.h
+++ b/src/FATStorage.h
@@ -24,6 +24,7 @@
#include <map>
#include <filesystem>
+#include "Platform.h"
#include "types.h"
#include "fatfs/ff.h"
@@ -48,16 +49,16 @@ private:
std::string SourceDir;
bool ReadOnly;
- FILE* File;
+ Platform::FileHandle* File;
u64 FileSize;
- static FILE* FF_File;
+ static Platform::FileHandle* FF_File;
static u64 FF_FileSize;
static UINT FF_ReadStorage(BYTE* buf, LBA_t sector, UINT num);
static UINT FF_WriteStorage(BYTE* buf, LBA_t sector, UINT num);
- static u32 ReadSectorsInternal(FILE* file, u64 filelen, u32 start, u32 num, u8* data);
- static u32 WriteSectorsInternal(FILE* file, u64 filelen, u32 start, u32 num, u8* data);
+ static u32 ReadSectorsInternal(Platform::FileHandle* file, u64 filelen, u32 start, u32 num, u8* data);
+ static u32 WriteSectorsInternal(Platform::FileHandle* file, u64 filelen, u32 start, u32 num, u8* data);
void LoadIndex();
void SaveIndex();
diff --git a/src/GBACart.cpp b/src/GBACart.cpp
index d35edf2..020219d 100644
--- a/src/GBACart.cpp
+++ b/src/GBACart.cpp
@@ -519,7 +519,7 @@ void CartGame::SRAMWrite_FLASH(u32 addr, u8 val)
return;
}
- Log(LogLevel::Warn, "GBACart_SRAM::Write_Flash: unknown write 0x%02X @ 0x%04X (state: 0x%02X)\n",
+ Log(LogLevel::Debug, "GBACart_SRAM::Write_Flash: unknown write 0x%02X @ 0x%04X (state: 0x%02X)\n",
val, addr, SRAMFlashState.state);
}
diff --git a/src/GPU2D.cpp b/src/GPU2D.cpp
index 9d616d3..d5df992 100644
--- a/src/GPU2D.cpp
+++ b/src/GPU2D.cpp
@@ -220,7 +220,7 @@ u8 Unit::Read8(u32 addr)
case 0x04D: return 0;
}
- Log(LogLevel::Warn, "unknown GPU read8 %08X\n", addr);
+ Log(LogLevel::Debug, "unknown GPU read8 %08X\n", addr);
return 0;
}
@@ -249,7 +249,7 @@ u16 Unit::Read16(u32 addr)
case 0x06C: return MasterBrightness;
}
- Log(LogLevel::Warn, "unknown GPU read16 %08X\n", addr);
+ Log(LogLevel::Debug, "unknown GPU read16 %08X\n", addr);
return 0;
}
@@ -366,7 +366,7 @@ void Unit::Write8(u32 addr, u8 val)
return;
}
- Log(LogLevel::Warn, "unknown GPU write8 %08X %02X\n", addr, val);
+ Log(LogLevel::Debug, "unknown GPU write8 %08X %02X\n", addr, val);
}
void Unit::Write16(u32 addr, u16 val)
diff --git a/src/GPU3D.cpp b/src/GPU3D.cpp
index 145b689..5611b14 100644
--- a/src/GPU3D.cpp
+++ b/src/GPU3D.cpp
@@ -2727,7 +2727,7 @@ u8 Read8(u32 addr)
}
}
- Log(LogLevel::Warn, "unknown GPU3D read8 %08X\n", addr);
+ Log(LogLevel::Debug, "unknown GPU3D read8 %08X\n", addr);
return 0;
}
@@ -2771,7 +2771,7 @@ u16 Read16(u32 addr)
case 0x04000634: return VecTestResult[2];
}
- Log(LogLevel::Warn, "unknown GPU3D read16 %08X\n", addr);
+ Log(LogLevel::Debug, "unknown GPU3D read16 %08X\n", addr);
return 0;
}
@@ -2875,7 +2875,7 @@ void Write8(u32 addr, u8 val)
return;
}
- Log(LogLevel::Warn, "unknown GPU3D write8 %08X %02X\n", addr, val);
+ Log(LogLevel::Debug, "unknown GPU3D write8 %08X %02X\n", addr, val);
}
void Write16(u32 addr, u16 val)
@@ -2962,7 +2962,7 @@ void Write16(u32 addr, u16 val)
return;
}
- Log(LogLevel::Warn, "unknown GPU3D write16 %08X %04X\n", addr, val);
+ Log(LogLevel::Debug, "unknown GPU3D write16 %08X %04X\n", addr, val);
}
void Write32(u32 addr, u32 val)
@@ -3059,7 +3059,7 @@ void Write32(u32 addr, u32 val)
return;
}
- Log(LogLevel::Warn, "unknown GPU3D write32 %08X %08X\n", addr, val);
+ Log(LogLevel::Debug, "unknown GPU3D write32 %08X %08X\n", addr, val);
}
Renderer3D::Renderer3D(bool Accelerated)
diff --git a/src/NDS.cpp b/src/NDS.cpp
index 5caaaee..b329c10 100644
--- a/src/NDS.cpp
+++ b/src/NDS.cpp
@@ -45,8 +45,7 @@
#include "DSi_Camera.h"
#include "DSi_DSP.h"
-using Platform::Log;
-using Platform::LogLevel;
+using namespace Platform;
namespace NDS
{
@@ -509,7 +508,7 @@ void SetupDirectBoot(const std::string& romname)
void Reset()
{
- FILE* f;
+ Platform::FileHandle* f;
u32 i;
#ifdef JIT_ENABLED
@@ -527,7 +526,7 @@ void Reset()
if (Platform::GetConfigBool(Platform::ExternalBIOSEnable))
{
- f = Platform::OpenLocalFile(Platform::GetConfigString(Platform::BIOS9Path), "rb");
+ f = Platform::OpenLocalFile(Platform::GetConfigString(Platform::BIOS9Path), FileMode::Read);
if (!f)
{
Log(LogLevel::Warn, "ARM9 BIOS not found\n");
@@ -537,14 +536,14 @@ void Reset()
}
else
{
- fseek(f, 0, SEEK_SET);
- fread(ARM9BIOS, 0x1000, 1, f);
+ FileRewind(f);
+ FileRead(ARM9BIOS, 0x1000, 1, f);
Log(LogLevel::Info, "ARM9 BIOS loaded\n");
- fclose(f);
+ Platform::CloseFile(f);
}
- f = Platform::OpenLocalFile(Platform::GetConfigString(Platform::BIOS7Path), "rb");
+ f = Platform::OpenLocalFile(Platform::GetConfigString(Platform::BIOS7Path), FileMode::Read);
if (!f)
{
Log(LogLevel::Warn, "ARM7 BIOS not found\n");
@@ -554,11 +553,11 @@ void Reset()
}
else
{
- fseek(f, 0, SEEK_SET);
- fread(ARM7BIOS, 0x4000, 1, f);
+ FileRewind(f);
+ FileRead(ARM7BIOS, 0x4000, 1, f);
Log(LogLevel::Info, "ARM7 BIOS loaded\n");
- fclose(f);
+ Platform::CloseFile(f);
}
}
else
@@ -694,11 +693,44 @@ void Start()
Running = true;
}
-void Stop()
+static const char* StopReasonName(Platform::StopReason reason)
{
- Log(LogLevel::Info, "Stopping: shutdown\n");
+ switch (reason)
+ {
+ case Platform::StopReason::External:
+ return "External";
+ case Platform::StopReason::PowerOff:
+ return "PowerOff";
+ case Platform::StopReason::GBAModeNotSupported:
+ return "GBAModeNotSupported";
+ case Platform::StopReason::BadExceptionRegion:
+ return "BadExceptionRegion";
+ default:
+ return "Unknown";
+ }
+}
+
+void Stop(Platform::StopReason reason)
+{
+ Platform::LogLevel level;
+ switch (reason)
+ {
+ case Platform::StopReason::External:
+ case Platform::StopReason::PowerOff:
+ level = LogLevel::Info;
+ break;
+ case Platform::StopReason::GBAModeNotSupported:
+ case Platform::StopReason::BadExceptionRegion:
+ level = LogLevel::Error;
+ break;
+ default:
+ level = LogLevel::Warn;
+ break;
+ }
+
+ Log(level, "Stopping emulated console (Reason: %s)\n", StopReasonName(reason));
Running = false;
- Platform::StopEmu();
+ Platform::SignalStop(reason);
GPU::Stop();
SPU::Stop();
@@ -2105,7 +2137,7 @@ u8 ARM9Read8(u32 addr)
return GBACart::SRAMRead(addr);
}
- Log(LogLevel::Warn, "unknown arm9 read8 %08X\n", addr);
+ Log(LogLevel::Debug, "unknown arm9 read8 %08X\n", addr);
return 0;
}
@@ -2272,7 +2304,7 @@ void ARM9Write8(u32 addr, u8 val)
return;
}
- Log(LogLevel::Warn, "unknown arm9 write8 %08X %02X\n", addr, val);
+ Log(LogLevel::Debug, "unknown arm9 write8 %08X %02X\n", addr, val);
}
void ARM9Write16(u32 addr, u16 val)
@@ -2504,7 +2536,7 @@ u8 ARM7Read8(u32 addr)
return GBACart::SRAMRead(addr);
}
- Log(LogLevel::Warn, "unknown arm7 read8 %08X %08X %08X/%08X\n", addr, ARM7->R[15], ARM7->R[0], ARM7->R[1]);
+ Log(LogLevel::Debug, "unknown arm7 read8 %08X %08X %08X/%08X\n", addr, ARM7->R[15], ARM7->R[0], ARM7->R[1]);
return 0;
}
@@ -2570,7 +2602,7 @@ u16 ARM7Read16(u32 addr)
(GBACart::SRAMRead(addr+1) << 8);
}
- Log(LogLevel::Warn, "unknown arm7 read16 %08X %08X\n", addr, ARM7->R[15]);
+ Log(LogLevel::Debug, "unknown arm7 read16 %08X %08X\n", addr, ARM7->R[15]);
return 0;
}
@@ -2707,7 +2739,7 @@ void ARM7Write8(u32 addr, u8 val)
//if (ARM7->R[15] > 0x00002F30) // ARM7 BIOS bug
if (addr >= 0x01000000)
- Log(LogLevel::Warn, "unknown arm7 write8 %08X %02X @ %08X\n", addr, val, ARM7->R[15]);
+ Log(LogLevel::Debug, "unknown arm7 write8 %08X %02X @ %08X\n", addr, val, ARM7->R[15]);
}
void ARM7Write16(u32 addr, u16 val)
@@ -2787,7 +2819,7 @@ void ARM7Write16(u32 addr, u16 val)
}
if (addr >= 0x01000000)
- Log(LogLevel::Warn, "unknown arm7 write16 %08X %04X @ %08X\n", addr, val, ARM7->R[15]);
+ Log(LogLevel::Debug, "unknown arm7 write16 %08X %04X @ %08X\n", addr, val, ARM7->R[15]);
}
void ARM7Write32(u32 addr, u32 val)
@@ -2871,7 +2903,7 @@ void ARM7Write32(u32 addr, u32 val)
}
if (addr >= 0x01000000)
- Log(LogLevel::Warn, "unknown arm7 write32 %08X %08X @ %08X\n", addr, val, ARM7->R[15]);
+ Log(LogLevel::Debug, "unknown arm7 write32 %08X %08X @ %08X\n", addr, val, ARM7->R[15]);
}
bool ARM7GetMemRegion(u32 addr, bool write, MemRegion* region)
@@ -3032,7 +3064,7 @@ u8 ARM9IORead8(u32 addr)
}
if ((addr & 0xFFFFF000) != 0x04004000)
- Log(LogLevel::Warn, "unknown ARM9 IO read8 %08X %08X\n", addr, ARM9->R[15]);
+ Log(LogLevel::Debug, "unknown ARM9 IO read8 %08X %08X\n", addr, ARM9->R[15]);
return 0;
}
@@ -3179,7 +3211,7 @@ u16 ARM9IORead16(u32 addr)
}
if ((addr & 0xFFFFF000) != 0x04004000)
- Log(LogLevel::Warn, "unknown ARM9 IO read16 %08X %08X\n", addr, ARM9->R[15]);
+ Log(LogLevel::Debug, "unknown ARM9 IO read16 %08X %08X\n", addr, ARM9->R[15]);
return 0;
}
@@ -3323,7 +3355,7 @@ u32 ARM9IORead32(u32 addr)
}
if ((addr & 0xFFFFF000) != 0x04004000)
- Log(LogLevel::Warn, "unknown ARM9 IO read32 %08X %08X\n", addr, ARM9->R[15]);
+ Log(LogLevel::Debug, "unknown ARM9 IO read32 %08X %08X\n", addr, ARM9->R[15]);
return 0;
}
@@ -3404,7 +3436,7 @@ void ARM9IOWrite8(u32 addr, u8 val)
return;
}
- Log(LogLevel::Warn, "unknown ARM9 IO write8 %08X %02X %08X\n", addr, val, ARM9->R[15]);
+ Log(LogLevel::Debug, "unknown ARM9 IO write8 %08X %02X %08X\n", addr, val, ARM9->R[15]);
}
void ARM9IOWrite16(u32 addr, u16 val)
@@ -3588,7 +3620,7 @@ void ARM9IOWrite16(u32 addr, u16 val)
return;
}
- Log(LogLevel::Warn, "unknown ARM9 IO write16 %08X %04X %08X\n", addr, val, ARM9->R[15]);
+ Log(LogLevel::Debug, "unknown ARM9 IO write16 %08X %04X %08X\n", addr, val, ARM9->R[15]);
}
void ARM9IOWrite32(u32 addr, u32 val)
@@ -3786,7 +3818,7 @@ void ARM9IOWrite32(u32 addr, u32 val)
return;
}
- Log(LogLevel::Warn, "unknown ARM9 IO write32 %08X %08X %08X\n", addr, val, ARM9->R[15]);
+ Log(LogLevel::Debug, "unknown ARM9 IO write32 %08X %08X %08X\n", addr, val, ARM9->R[15]);
}
@@ -3860,7 +3892,7 @@ u8 ARM7IORead8(u32 addr)
}
if ((addr & 0xFFFFF000) != 0x04004000)
- Log(LogLevel::Warn, "unknown ARM7 IO read8 %08X %08X\n", addr, ARM7->R[15]);
+ Log(LogLevel::Debug, "unknown ARM7 IO read8 %08X %08X\n", addr, ARM7->R[15]);
return 0;
}
@@ -3954,7 +3986,7 @@ u16 ARM7IORead16(u32 addr)
}
if ((addr & 0xFFFFF000) != 0x04004000)
- Log(LogLevel::Warn, "unknown ARM7 IO read16 %08X %08X\n", addr, ARM7->R[15]);
+ Log(LogLevel::Debug, "unknown ARM7 IO read16 %08X %08X\n", addr, ARM7->R[15]);
return 0;
}
@@ -4055,7 +4087,7 @@ u32 ARM7IORead32(u32 addr)
}
if ((addr & 0xFFFFF000) != 0x04004000)
- Log(LogLevel::Warn, "unknown ARM7 IO read32 %08X %08X\n", addr, ARM7->R[15]);
+ Log(LogLevel::Debug, "unknown ARM7 IO read32 %08X %08X\n", addr, ARM7->R[15]);
return 0;
}
@@ -4121,7 +4153,7 @@ void ARM7IOWrite8(u32 addr, u8 val)
case 0x04000301:
val &= 0xC0;
- if (val == 0x40) Log(LogLevel::Warn, "!! GBA MODE NOT SUPPORTED\n");
+ if (val == 0x40) Stop(StopReason::GBAModeNotSupported);
else if (val == 0x80) ARM7->Halt(1);
else if (val == 0xC0) EnterSleepMode();
return;
@@ -4133,7 +4165,7 @@ void ARM7IOWrite8(u32 addr, u8 val)
return;
}
- Log(LogLevel::Warn, "unknown ARM7 IO write8 %08X %02X %08X\n", addr, val, ARM7->R[15]);
+ Log(LogLevel::Debug, "unknown ARM7 IO write8 %08X %02X %08X\n", addr, val, ARM7->R[15]);
}
void ARM7IOWrite16(u32 addr, u16 val)
@@ -4288,7 +4320,7 @@ void ARM7IOWrite16(u32 addr, u16 val)
return;
}
- Log(LogLevel::Warn, "unknown ARM7 IO write16 %08X %04X %08X\n", addr, val, ARM7->R[15]);
+ Log(LogLevel::Debug, "unknown ARM7 IO write16 %08X %04X %08X\n", addr, val, ARM7->R[15]);
}
void ARM7IOWrite32(u32 addr, u32 val)
@@ -4422,7 +4454,7 @@ void ARM7IOWrite32(u32 addr, u32 val)
return;
}
- Log(LogLevel::Warn, "unknown ARM7 IO write32 %08X %08X %08X\n", addr, val, ARM7->R[15]);
+ Log(LogLevel::Debug, "unknown ARM7 IO write32 %08X %08X %08X\n", addr, val, ARM7->R[15]);
}
}
diff --git a/src/NDS.h b/src/NDS.h
index 404e07c..571952d 100644
--- a/src/NDS.h
+++ b/src/NDS.h
@@ -21,6 +21,7 @@
#include <string>
+#include "Platform.h"
#include "Savestate.h"
#include "types.h"
@@ -226,7 +227,9 @@ bool Init();
void DeInit();
void Reset();
void Start();
-void Stop();
+
+/// Stop the emulator.
+void Stop(Platform::StopReason reason = Platform::StopReason::External);
bool DoSavestate(Savestate* file);
diff --git a/src/Platform.h b/src/Platform.h
index 59e7c02..91da4c1 100644
--- a/src/Platform.h
+++ b/src/Platform.h
@@ -28,12 +28,64 @@ namespace Platform
{
void Init(int argc, char** argv);
+
+/**
+ * Frees all resources that were allocated in \c Init
+ * or by any other \c Platform function.
+ */
void DeInit();
-void StopEmu();
+enum StopReason {
+ /**
+ * The emulator stopped for some unspecified reason.
+ * Not necessarily an error.
+ */
+ Unknown,
+
+ /**
+ * The emulator stopped due to an external call to \c NDS::Stop,
+ * most likely because the user stopped the game manually.
+ */
+ External,
+
+ /**
+ * The emulator stopped because it tried to enter GBA mode,
+ * which melonDS does not support.
+ */
+ GBAModeNotSupported,
+
+ /**
+ * The emulator stopped because of an error in the emulated console,
+ * not necessarily because of an error in melonDS.
+ */
+ BadExceptionRegion,
+
+ /**
+ * The emulated console shut itself down normally,
+ * likely because its system settings were adjusted
+ * or its "battery" ran out.
+ */
+ PowerOff,
+};
-// instance ID, for local multiplayer
+/**
+ * Signals to the frontend that no more frames should be requested.
+ * Frontends should not call this directly;
+ * use \c NDS::Stop instead.
+ */
+void SignalStop(StopReason reason);
+
+/**
+ * @returns The ID of the running melonDS instance if running in local multiplayer mode,
+ * or 0 if not.
+ */
int InstanceID();
+
+/**
+ * @returns A suffix that should be appended to all instance-specific paths
+ * if running in local multiplayer mode,
+ * or the empty string if not.
+ */
std::string InstanceFileSuffix();
// configuration values
@@ -82,6 +134,8 @@ enum ConfigEntry
Firm_Message,
Firm_MAC,
+ WifiSettingsPath,
+
AudioBitDepth,
DSi_FullBIOSBoot
@@ -92,43 +146,154 @@ bool GetConfigBool(ConfigEntry entry);
std::string GetConfigString(ConfigEntry entry);
bool GetConfigArray(ConfigEntry entry, void* data);
-// fopen() wrappers
-// * OpenFile():
-// simple fopen() wrapper that supports UTF8.
-// can be optionally restricted to only opening a file that already exists.
-// * OpenLocalFile():
-// opens files local to the emulator (melonDS.ini, BIOS, firmware, ...)
-// For Windows builds, or portable UNIX builds it checks, by order of priority:
-// * current working directory
-// * emulator directory (essentially where the melonDS executable is) if supported
-// * any platform-specific application data directories
-// in create mode, if the file doesn't exist, it will be created in the emulator
-// directory if supported, or in the current directory otherwise
-// For regular UNIX builds, the user's configuration directory is always used.
-// * OpenDataFile():
-// Opens a file that was installed alongside melonDS on UNIX systems in /usr/share, etc.
-// Looks in the user's data directory first, then the system's.
-// If on Windows or a portable UNIX build, this simply calls OpenLocalFile().
-
-FILE* OpenFile(const std::string& path, const std::string& mode, bool mustexist=false);
-FILE* OpenLocalFile(const std::string& path, const std::string& mode);
-FILE* OpenDataFile(const std::string& path);
-
-inline bool FileExists(const std::string& name)
-{
- FILE* f = OpenFile(name, "rb");
- if (!f) return false;
- fclose(f);
- return true;
-}
+/**
+ * Denotes how a file will be opened and accessed.
+ * Flags may or may not correspond to the operating system's file API.
+ */
+enum FileMode : unsigned {
+ None = 0,
+
+ /**
+ * Opens a file for reading.
+ * Either this or \c Write must be set.
+ * Similar to \c "r" in \c fopen.
+ */
+ Read = 0b00'00'01,
+
+ /**
+ * Opens a file for writing, creating it if it doesn't exist.
+ * Will truncate existing files unless \c Preserve is set.
+ * Either this or \c Read must be set.
+ * Similar to <tt>fopen</tt>'s \c "w" flag.
+ */
+ Write = 0b00'00'10,
+
+ /**
+ * Opens an existing file as-is without truncating it.
+ * The file may still be created unless \c NoCreate is set.
+ * @note This flag has no effect if \c Write is not set.
+ */
+ Preserve = 0b00'01'00,
+
+ /**
+ * Do not create the file if it doesn't exist.
+ * @note This flag has no effect if \c Write is not set.
+ */
+ NoCreate = 0b00'10'00,
+
+ /**
+ * Opens a file in text mode,
+ * rather than the default binary mode.
+ * Text-mode files may have their line endings converted
+ * to match the operating system,
+ * and may also be line-buffered.
+ */
+ Text = 0b01'00'00,
+
+ /**
+ * Opens a file for reading and writing.
+ * Equivalent to <tt>Read | Write</tt>.
+ */
+ ReadWrite = Read | Write,
+
+ /**
+ * Opens a file for reading and writing
+ * without truncating it or creating a new one.
+ * Equivalent to <tt>Read | Write | Preserve | NoCreate</tt>.
+ */
+ ReadWriteExisting = Read | Write | Preserve | NoCreate,
+
+ /**
+ * Opens a file for reading in text mode.
+ * Equivalent to <tt>Read | Text</tt>.
+ */
+ ReadText = Read | Text,
+
+ /**
+ * Opens a file for writing in text mode,
+ * creating it if it doesn't exist.
+ * Equivalent to <tt>Write | Text</tt>.
+ */
+ WriteText = Write | Text,
+};
-inline bool LocalFileExists(const std::string& name)
+/**
+ * Denotes the origin of a seek operation.
+ * Similar to \c fseek's \c SEEK_* constants.
+ */
+enum class FileSeekOrigin
{
- FILE* f = OpenLocalFile(name, "rb");
- if (!f) return false;
- fclose(f);
- return true;
-}
+ Start,
+ Current,
+ End,
+};
+
+/**
+ * Opaque handle for a file object.
+ * This can be implemented as a struct defined by the frontend,
+ * or as a simple pointer cast.
+ * The core will never look inside this struct,
+ * but frontends may do so freely.
+ */
+struct FileHandle;
+
+// Simple fopen() wrapper that supports UTF8.
+// Can be optionally restricted to only opening a file that already exists.
+FileHandle* OpenFile(const std::string& path, FileMode mode);
+
+// opens files local to the emulator (melonDS.ini, BIOS, firmware, ...)
+// For Windows builds, or portable UNIX builds it checks, by order of priority:
+// * current working directory
+// * emulator directory (essentially where the melonDS executable is) if supported
+// * any platform-specific application data directories
+// in create mode, if the file doesn't exist, it will be created in the emulator
+// directory if supported, or in the current directory otherwise
+// For regular UNIX builds, the user's configuration directory is always used.
+FileHandle* OpenLocalFile(const std::string& path, FileMode mode);
+
+/// Returns true if the given file exists.
+bool FileExists(const std::string& name);
+bool LocalFileExists(const std::string& name);
+
+/** Close a file opened with \c OpenFile.
+ * @returns \c true if the file was closed successfully, false otherwise.
+ * @post \c file is no longer valid and should not be used.
+ * The underlying object may still be allocated (e.g. if the frontend refcounts files),
+ * but that's an implementation detail.
+ * @see fclose
+ */
+bool CloseFile(FileHandle* file);
+
+/// @returns \c true if there is no more data left to read in this file,
+/// \c false if there is still data left to read or if there was an error.
+/// @see feof
+bool IsEndOfFile(FileHandle* file);
+
+/// @see fgets
+bool FileReadLine(char* str, int count, FileHandle* file);
+
+/// @see fseek
+bool FileSeek(FileHandle* file, s64 offset, FileSeekOrigin origin);
+
+/// @see rewind
+void FileRewind(FileHandle* file);
+
+/// @see fread
+u64 FileRead(void* data, u64 size, u64 count, FileHandle* file);
+
+/// @see fflush
+bool FileFlush(FileHandle* file);
+
+/// @see fwrite
+u64 FileWrite(const void* data, u64 size, u64 count, FileHandle* file);
+
+/// @see fprintf
+u64 FileWriteFormatted(FileHandle* file, const char* fmt, ...);
+
+/// @returns The length of the file in bytes, or 0 if there was an error.
+/// @note If this function checks the length by using \c fseek and \c ftell
+/// (or local equivalents), it must leave the stream position as it was found.
+u64 FileLength(FileHandle* file);
enum LogLevel
{
@@ -201,6 +366,28 @@ void Camera_Start(int num);
void Camera_Stop(int num);
void Camera_CaptureFrame(int num, u32* frame, int width, int height, bool yuv);
+struct DynamicLibrary;
+
+/**
+ * @param lib The name of the library to load.
+ * @return A handle to the loaded library, or \c nullptr if the library could not be loaded.
+ */
+DynamicLibrary* DynamicLibrary_Load(const char* lib);
+
+/**
+ * Releases a loaded library.
+ * Pointers to functions in the library will be invalidated.
+ * @param lib The library to unload.
+ */
+void DynamicLibrary_Unload(DynamicLibrary* lib);
+
+/**
+ * Loads a function from a library.
+ * @param lib The library to load the function from.
+ * @param name The name of the function to load.
+ * @return A pointer to the loaded function, or \c nullptr if the function could not be loaded.
+ */
+void* DynamicLibrary_LoadFunction(DynamicLibrary* lib, const char* name);
}
#endif // PLATFORM_H
diff --git a/src/SPI.cpp b/src/SPI.cpp
index c83a77c..bbfacbf 100644
--- a/src/SPI.cpp
+++ b/src/SPI.cpp
@@ -29,8 +29,7 @@
#include "DSi_SPI_TSC.h"
#include "Platform.h"
-using Platform::Log;
-using Platform::LogLevel;
+using namespace Platform;
namespace SPI_Firmware
{
@@ -223,13 +222,15 @@ void LoadDefaultFirmware()
// wifi access points
// TODO: WFC ID??
- FILE* f = Platform::OpenLocalFile("wfcsettings.bin"+Platform::InstanceFileSuffix(), "rb");
- if (!f) f = Platform::OpenLocalFile("wfcsettings.bin", "rb");
+ std::string wfcsettings = Platform::GetConfigString(ConfigEntry::WifiSettingsPath);
+
+ FileHandle* f = Platform::OpenLocalFile(wfcsettings + Platform::InstanceFileSuffix(), FileMode::Read);
+ if (!f) f = Platform::OpenLocalFile(wfcsettings, FileMode::Read);
if (f)
{
u32 apdata = userdata - 0xA00;
- fread(&Firmware[apdata], 0x900, 1, f);
- fclose(f);
+ FileRead(&Firmware[apdata], 0x900, 1, f);
+ CloseFile(f);
}
else
{
@@ -268,29 +269,27 @@ void LoadDefaultFirmware()
}
}
-void LoadFirmwareFromFile(FILE* f, bool makecopy)
+void LoadFirmwareFromFile(FileHandle* f, bool makecopy)
{
- fseek(f, 0, SEEK_END);
-
- FirmwareLength = FixFirmwareLength((u32)ftell(f));
+ FirmwareLength = FixFirmwareLength(FileLength(f));
Firmware = new u8[FirmwareLength];
- fseek(f, 0, SEEK_SET);
- fread(Firmware, 1, FirmwareLength, f);
+ FileRewind(f);
+ FileRead(Firmware, 1, FirmwareLength, f);
// take a backup
std::string fwBackupPath;
if (!makecopy) fwBackupPath = FirmwarePath + ".bak";
else fwBackupPath = FirmwarePath;
- FILE* bf = Platform::OpenLocalFile(fwBackupPath, "rb");
+ FileHandle* bf = Platform::OpenLocalFile(fwBackupPath, FileMode::Read);
if (!bf)
{
- bf = Platform::OpenLocalFile(fwBackupPath, "wb");
+ bf = Platform::OpenLocalFile(fwBackupPath, FileMode::Write);
if (bf)
{
- fwrite(Firmware, 1, FirmwareLength, bf);
- fclose(bf);
+ FileWrite(Firmware, 1, FirmwareLength, bf);
+ CloseFile(bf);
}
else
{
@@ -299,7 +298,7 @@ void LoadFirmwareFromFile(FILE* f, bool makecopy)
}
else
{
- fclose(bf);
+ CloseFile(bf);
}
}
@@ -350,10 +349,10 @@ void Reset()
std::string origpath = FirmwarePath;
FirmwarePath += Platform::InstanceFileSuffix();
- FILE* f = Platform::OpenLocalFile(FirmwarePath, "rb");
+ FileHandle* f = Platform::OpenLocalFile(FirmwarePath, FileMode::Read);
if (!f)
{
- f = Platform::OpenLocalFile(origpath, "rb");
+ f = Platform::OpenLocalFile(origpath, FileMode::Read);
makecopy = true;
}
if (!f)
@@ -364,7 +363,7 @@ void Reset()
else
{
LoadFirmwareFromFile(f, makecopy);
- fclose(f);
+ CloseFile(f);
}
}
@@ -604,28 +603,26 @@ void Write(u8 val, u32 hold)
{
if (!FirmwarePath.empty())
{
- FILE* f = Platform::OpenLocalFile(FirmwarePath, "r+b");
+ FileHandle* f = Platform::OpenLocalFile(FirmwarePath, FileMode::ReadWriteExisting);
if (f)
{
u32 cutoff = ((NDS::ConsoleType==1) ? 0x7F400 : 0x7FA00) & FirmwareMask;
- fseek(f, cutoff, SEEK_SET);
- fwrite(&Firmware[cutoff], FirmwareLength-cutoff, 1, f);
- fclose(f);
+ FileSeek(f, cutoff, FileSeekOrigin::Start);
+ FileWrite(&Firmware[cutoff], FirmwareLength-cutoff, 1, f);
+ CloseFile(f);
}
}
else
{
- char wfcfile[50] = {0};
- int inst = Platform::InstanceID();
- if (inst > 0) snprintf(wfcfile, 49, "wfcsettings.bin", Platform::InstanceID());
- else strncpy(wfcfile, "wfcsettings.bin", 49);
+ std::string wfcfile = Platform::GetConfigString(ConfigEntry::WifiSettingsPath);
+ if (Platform::InstanceID() > 0) wfcfile += Platform::InstanceFileSuffix();
- FILE* f = Platform::OpenLocalFile(wfcfile, "wb");
+ FileHandle* f = Platform::OpenLocalFile(wfcfile, FileMode::Write);
if (f)
{
u32 cutoff = 0x7F400 & FirmwareMask;
- fwrite(&Firmware[cutoff], 0x900, 1, f);
- fclose(f);
+ FileWrite(&Firmware[cutoff], 0x900, 1, f);
+ CloseFile(f);
}
}
}
@@ -725,7 +722,7 @@ void Write(u8 val, u32 hold)
switch (regid)
{
case 0:
- if (val & 0x40) NDS::Stop(); // shutdown
+ if (val & 0x40) NDS::Stop(StopReason::PowerOff); // shutdown
//printf("power %02X\n", val);
break;
case 4:
diff --git a/src/Wifi.cpp b/src/Wifi.cpp
index aa3cf1d..298ba9d 100644
--- a/src/Wifi.cpp
+++ b/src/Wifi.cpp
@@ -385,7 +385,7 @@ void UpdatePowerOn()
PowerOn = on;
if (on)
{
- Log(LogLevel::Info, "WIFI: ON\n");
+ Log(LogLevel::Debug, "WIFI: ON\n");
ScheduleTimer(true);
@@ -393,7 +393,7 @@ void UpdatePowerOn()
}
else
{
- Log(LogLevel::Info, "WIFI: OFF\n");
+ Log(LogLevel::Debug, "WIFI: OFF\n");
NDS::CancelEvent(NDS::Event_Wifi);
diff --git a/src/WifiAP.cpp b/src/WifiAP.cpp
index 898ee16..9fef220 100644
--- a/src/WifiAP.cpp
+++ b/src/WifiAP.cpp
@@ -163,7 +163,7 @@ int HandleManagementFrame(u8* data, int len)
}
ClientStatus = 2;
- Log(LogLevel::Info, "wifiAP: client associated\n");
+ Log(LogLevel::Debug, "wifiAP: client associated\n");
PWRITE_16(p, 0x0010);
PWRITE_16(p, 0x0000); // duration??
@@ -213,7 +213,7 @@ int HandleManagementFrame(u8* data, int len)
return 0;
ClientStatus = 1;
- Log(LogLevel::Info, "wifiAP: client deassociated\n");
+ Log(LogLevel::Debug, "wifiAP: client deassociated\n");
PWRITE_16(p, 0x00A0);
PWRITE_16(p, 0x0000); // duration??
@@ -235,7 +235,7 @@ int HandleManagementFrame(u8* data, int len)
return 0;
ClientStatus = 1;
- Log(LogLevel::Info, "wifiAP: client authenticated\n");
+ Log(LogLevel::Debug, "wifiAP: client authenticated\n");
PWRITE_16(p, 0x00B0);
PWRITE_16(p, 0x0000); // duration??
@@ -259,7 +259,7 @@ int HandleManagementFrame(u8* data, int len)
return 0;
ClientStatus = 0;
- Log(LogLevel::Info, "wifiAP: client deauthenticated\n");
+ Log(LogLevel::Debug, "wifiAP: client deauthenticated\n");
PWRITE_16(p, 0x00C0);
PWRITE_16(p, 0x0000); // duration??
diff --git a/src/dolphin/CommonFuncs.cpp b/src/dolphin/CommonFuncs.cpp
index f85051d..c15a609 100644
--- a/src/dolphin/CommonFuncs.cpp
+++ b/src/dolphin/CommonFuncs.cpp
@@ -29,7 +29,8 @@ std::string LastStrerrorString()
// We check defines in order to figure out variant is in use, and we store the returned value
// to a variable so that we'll get a compile-time check that our assumption was correct.
-#if defined(__GLIBC__) && (_GNU_SOURCE || (_POSIX_C_SOURCE < 200112L && _XOPEN_SOURCE < 600))
+#if (defined(__GLIBC__) || __ANDROID_API__ >= 23) && \
+ (_GNU_SOURCE || (_POSIX_C_SOURCE < 200112L && _XOPEN_SOURCE < 600))
const char* str = strerror_r(errno, error_message, BUFFER_SIZE);
return std::string(str);
#else
diff --git a/src/frontend/qt_sdl/Config.cpp b/src/frontend/qt_sdl/Config.cpp
index b4d78f7..898e4a1 100644
--- a/src/frontend/qt_sdl/Config.cpp
+++ b/src/frontend/qt_sdl/Config.cpp
@@ -106,6 +106,7 @@ int FirmwareBirthdayDay;
int FirmwareFavouriteColour;
std::string FirmwareMessage;
std::string FirmwareMAC;
+std::string WifiSettingsPath = "wfcsettings.bin"; // Should this be configurable?
int MPAudioMode;
int MPRecvTimeout;
@@ -353,24 +354,24 @@ ConfigEntry ConfigFile[] =
void LoadFile(int inst)
{
- FILE* f;
+ Platform::FileHandle* f;
if (inst > 0)
{
char name[100] = {0};
snprintf(name, 99, kUniqueConfigFile, inst+1);
- f = Platform::OpenLocalFile(name, "r");
+ f = Platform::OpenLocalFile(name, Platform::FileMode::ReadText);
}
else
- f = Platform::OpenLocalFile(kConfigFile, "r");
+ f = Platform::OpenLocalFile(kConfigFile, Platform::FileMode::ReadText);
if (!f) return;
char linebuf[1024];
char entryname[32];
char entryval[1024];
- while (!feof(f))
+ while (!Platform::IsEndOfFile(f))
{
- if (fgets(linebuf, 1024, f) == nullptr)
+ if (!Platform::FileReadLine(linebuf, 1024, f))
break;
int ret = sscanf(linebuf, "%31[A-Za-z_0-9]=%[^\t\r\n]", entryname, entryval);
@@ -396,7 +397,7 @@ void LoadFile(int inst)
}
}
- fclose(f);
+ CloseFile(f);
}
void Load()
@@ -423,15 +424,15 @@ void Save()
{
int inst = Platform::InstanceID();
- FILE* f;
+ Platform::FileHandle* f;
if (inst > 0)
{
char name[100] = {0};
snprintf(name, 99, kUniqueConfigFile, inst+1);
- f = Platform::OpenLocalFile(name, "w");
+ f = Platform::OpenLocalFile(name, Platform::FileMode::WriteText);
}
else
- f = Platform::OpenLocalFile(kConfigFile, "w");
+ f = Platform::OpenLocalFile(kConfigFile, Platform::FileMode::WriteText);
if (!f) return;
@@ -442,13 +443,13 @@ void Save()
switch (entry->Type)
{
- case 0: fprintf(f, "%s=%d\r\n", entry->Name, *(int*)entry->Value); break;
- case 1: fprintf(f, "%s=%d\r\n", entry->Name, *(bool*)entry->Value ? 1:0); break;
- case 2: fprintf(f, "%s=%s\r\n", entry->Name, (*(std::string*)entry->Value).c_str()); break;
+ case 0: Platform::FileWriteFormatted(f, "%s=%d\r\n", entry->Name, *(int*)entry->Value); break;
+ case 1: Platform::FileWriteFormatted(f, "%s=%d\r\n", entry->Name, *(bool*)entry->Value ? 1:0); break;
+ case 2: Platform::FileWriteFormatted(f, "%s=%s\r\n", entry->Name, (*(std::string*)entry->Value).c_str()); break;
}
}
- fclose(f);
+ CloseFile(f);
}
}
diff --git a/src/frontend/qt_sdl/Config.h b/src/frontend/qt_sdl/Config.h
index 1cd0e56..504c068 100644
--- a/src/frontend/qt_sdl/Config.h
+++ b/src/frontend/qt_sdl/Config.h
@@ -152,6 +152,7 @@ extern int FirmwareBirthdayDay;
extern int FirmwareFavouriteColour;
extern std::string FirmwareMessage;
extern std::string FirmwareMAC;
+extern std::string WifiSettingsPath;
extern int MPAudioMode;
extern int MPRecvTimeout;
diff --git a/src/frontend/qt_sdl/EmuSettingsDialog.cpp b/src/frontend/qt_sdl/EmuSettingsDialog.cpp
index b984e05..0bdbb5c 100644
--- a/src/frontend/qt_sdl/EmuSettingsDialog.cpp
+++ b/src/frontend/qt_sdl/EmuSettingsDialog.cpp
@@ -29,6 +29,7 @@
#include "EmuSettingsDialog.h"
#include "ui_EmuSettingsDialog.h"
+using namespace Platform;
EmuSettingsDialog* EmuSettingsDialog::currentDlg = nullptr;
@@ -156,19 +157,19 @@ void EmuSettingsDialog::verifyFirmware()
// bytes 0x0C-0x14 are different.
std::string filename = ui->txtFirmwarePath->text().toStdString();
- FILE* f = Platform::OpenLocalFile(filename, "rb");
+ FileHandle* f = Platform::OpenLocalFile(filename, FileMode::Read);
if (!f) return;
u8 chk1[0x180], chk2[0x180];
- fseek(f, 0, SEEK_SET);
- fread(chk1, 1, 0x180, f);
- fseek(f, -0x380, SEEK_END);
- fread(chk2, 1, 0x180, f);
+ FileRewind(f);
+ FileRead(chk1, 1, 0x180, f);
+ FileSeek(f, -0x380, FileSeekOrigin::End);
+ FileRead(chk2, 1, 0x180, f);
memset(&chk1[0x0C], 0, 8);
memset(&chk2[0x0C], 0, 8);
- fclose(f);
+ CloseFile(f);
if (!memcmp(chk1, chk2, 0x180))
{
diff --git a/src/frontend/qt_sdl/LAN_PCap.cpp b/src/frontend/qt_sdl/LAN_PCap.cpp
index 2a04e70..f5bf436 100644
--- a/src/frontend/qt_sdl/LAN_PCap.cpp
+++ b/src/frontend/qt_sdl/LAN_PCap.cpp
@@ -21,9 +21,8 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <SDL2/SDL.h>
#include <pcap/pcap.h>
-#include "../Wifi.h"
+#include "Wifi.h"
#include "LAN_PCap.h"
#include "Config.h"
#include "Platform.h"
@@ -88,7 +87,7 @@ const char* PCapLibNames[] =
AdapterData* Adapters = NULL;
int NumAdapters = 0;
-void* PCapLib = NULL;
+Platform::DynamicLibrary* PCapLib = NULL;
pcap_t* PCapAdapter = NULL;
AdapterData* PCapAdapterData;
@@ -98,10 +97,10 @@ volatile int RXNum;
#define LOAD_PCAP_FUNC(sym) \
- ptr_##sym = (type_##sym)SDL_LoadFunction(lib, #sym); \
+ ptr_##sym = (type_##sym)DynamicLibrary_LoadFunction(lib, #sym); \
if (!ptr_##sym) return false;
-bool TryLoadPCap(void* lib)
+bool TryLoadPCap(Platform::DynamicLibrary *lib)
{
LOAD_PCAP_FUNC(pcap_findalldevs)
LOAD_PCAP_FUNC(pcap_freealldevs)
@@ -130,12 +129,12 @@ bool Init(bool open_adapter)
for (int i = 0; PCapLibNames[i]; i++)
{
- void* lib = SDL_LoadObject(PCapLibNames[i]);
+ Platform::DynamicLibrary* lib = Platform::DynamicLibrary_Load(PCapLibNames[i]);
if (!lib) continue;
if (!TryLoadPCap(lib))
{
- SDL_UnloadObject(lib);
+ Platform::DynamicLibrary_Unload(lib);
continue;
}
@@ -355,7 +354,7 @@ void DeInit()
PCapAdapter = NULL;
}
- SDL_UnloadObject(PCapLib);
+ Platform::DynamicLibrary_Unload(PCapLib);
PCapLib = NULL;
}
}
diff --git a/src/frontend/qt_sdl/LAN_PCap.h b/src/frontend/qt_sdl/LAN_PCap.h
index 610c0ae..2f4663f 100644
--- a/src/frontend/qt_sdl/LAN_PCap.h
+++ b/src/frontend/qt_sdl/LAN_PCap.h
@@ -19,7 +19,7 @@
#ifndef LAN_PCAP_H
#define LAN_PCAP_H
-#include "../types.h"
+#include "types.h"
namespace LAN_PCap
{
diff --git a/src/frontend/qt_sdl/LAN_Socket.cpp b/src/frontend/qt_sdl/LAN_Socket.cpp
index 6c00b58..6753bb8 100644
--- a/src/frontend/qt_sdl/LAN_Socket.cpp
+++ b/src/frontend/qt_sdl/LAN_Socket.cpp
@@ -24,6 +24,7 @@
#include "Wifi.h"
#include "LAN_Socket.h"
#include "FIFO.h"
+#include "Platform.h"
#include <slirp/libslirp.h>
@@ -40,6 +41,9 @@
namespace LAN_Socket
{
+using Platform::Log;
+using Platform::LogLevel;
+
const u32 kSubnet = 0x0A400000;
const u32 kServerIP = kSubnet | 0x01;
const u32 kDNSIP = kSubnet | 0x02;
@@ -87,7 +91,7 @@ void RXEnqueue(const void* buf, int len)
if (!RXBuffer.CanFit(totallen >> 2))
{
- printf("slirp: !! NOT ENOUGH SPACE IN RX BUFFER\n");
+ Log(LogLevel::Warn, "slirp: !! NOT ENOUGH SPACE IN RX BUFFER\n");
return;
}
@@ -101,11 +105,11 @@ ssize_t SlirpCbSendPacket(const void* buf, size_t len, void* opaque)
{
if (len > 2048)
{
- printf("slirp: packet too big (%zu)\n", len);
+ Log(LogLevel::Warn, "slirp: packet too big (%zu)\n", len);
return 0;
}
- printf("slirp: response packet of %zu bytes, type %04X\n", len, ntohs(((u16*)buf)[6]));
+ Log(LogLevel::Debug, "slirp: response packet of %zu bytes, type %04X\n", len, ntohs(((u16*)buf)[6]));
RXEnqueue(buf, len);
@@ -114,7 +118,7 @@ ssize_t SlirpCbSendPacket(const void* buf, size_t len, void* opaque)
void SlirpCbGuestError(const char* msg, void* opaque)
{
- printf("SLIRP: error: %s\n", msg);
+ Log(LogLevel::Error, "SLIRP: error: %s\n", msg);
}
int64_t SlirpCbClockGetNS(void* opaque)
@@ -139,7 +143,7 @@ void SlirpCbTimerMod(void* timer, int64_t expire_time, void* opaque)
void SlirpCbRegisterPollFD(int fd, void* opaque)
{
- printf("Slirp: register poll FD %d\n", fd);
+ Log(LogLevel::Debug, "Slirp: register poll FD %d\n", fd);
/*if (FDListSize >= FDListMax)
{
@@ -158,7 +162,7 @@ void SlirpCbRegisterPollFD(int fd, void* opaque)
void SlirpCbUnregisterPollFD(int fd, void* opaque)
{
- printf("Slirp: unregister poll FD %d\n", fd);
+ Log(LogLevel::Debug, "Slirp: unregister poll FD %d\n", fd);
/*if (FDListSize < 1)
{
@@ -178,7 +182,7 @@ void SlirpCbUnregisterPollFD(int fd, void* opaque)
void SlirpCbNotify(void* opaque)
{
- printf("Slirp: notify???\n");
+ Log(LogLevel::Debug, "Slirp: notify???\n");
}
SlirpCb cb =
@@ -283,7 +287,7 @@ void HandleDNSFrame(u8* data, int len)
u16 numauth = ntohs(*(u16*)&dnsbody[8]);
u16 numadd = ntohs(*(u16*)&dnsbody[10]);
- printf("DNS: ID=%04X, flags=%04X, Q=%d, A=%d, auth=%d, add=%d\n",
+ Log(LogLevel::Debug, "DNS: ID=%04X, flags=%04X, Q=%d, A=%d, auth=%d, add=%d\n",
id, flags, numquestions, numanswers, numauth, numadd);
// for now we only take 'simple' DNS requests
@@ -429,7 +433,7 @@ int SendPacket(u8* data, int len)
if (len > 2048)
{
- printf("LAN_SendPacket: error: packet too long (%d)\n", len);
+ Log(LogLevel::Error, "LAN_SendPacket: error: packet too long (%d)\n", len);
return 0;
}
@@ -461,7 +465,7 @@ int SlirpCbAddPoll(int fd, int events, void* opaque)
{
if (PollListSize >= PollListMax)
{
- printf("slirp: POLL LIST FULL\n");
+ Log(LogLevel::Error, "slirp: POLL LIST FULL\n");
return -1;
}
diff --git a/src/frontend/qt_sdl/LAN_Socket.h b/src/frontend/qt_sdl/LAN_Socket.h
index 2073d1b..f2c7ed4 100644
--- a/src/frontend/qt_sdl/LAN_Socket.h
+++ b/src/frontend/qt_sdl/LAN_Socket.h
@@ -19,7 +19,7 @@
#ifndef LAN_SOCKET_H
#define LAN_SOCKET_H
-#include "../types.h"
+#include "types.h"
namespace LAN_Socket
{
diff --git a/src/frontend/qt_sdl/Platform.cpp b/src/frontend/qt_sdl/Platform.cpp
index eef9934..5263377 100644
--- a/src/frontend/qt_sdl/Platform.cpp
+++ b/src/frontend/qt_sdl/Platform.cpp
@@ -29,6 +29,7 @@
#include <QMutex>
#include <QOpenGLContext>
#include <QSharedMemory>
+#include <SDL_loadso.h>
#include "Platform.h"
#include "Config.h"
@@ -37,7 +38,12 @@
#include "LAN_Socket.h"
#include "LAN_PCap.h"
#include "LocalMP.h"
+#include "OSD.h"
+#ifdef __WIN32__
+#define fseek _fseeki64
+#define ftell _ftelli64
+#endif // __WIN32__
std::string EmuDirectory;
@@ -149,10 +155,24 @@ void DeInit()
IPCDeInit();
}
-
-void StopEmu()
+void SignalStop(StopReason reason)
{
emuStop();
+ switch (reason)
+ {
+ case StopReason::GBAModeNotSupported:
+ Log(LogLevel::Error, "!! GBA MODE NOT SUPPORTED\n");
+ OSD::AddMessage(0xFFA0A0, "GBA mode not supported.");
+ break;
+ case StopReason::BadExceptionRegion:
+ OSD::AddMessage(0xFFA0A0, "Internal error.");
+ break;
+ case StopReason::PowerOff:
+ case StopReason::External:
+ OSD::AddMessage(0xFFC040, "Shutdown");
+ default:
+ break;
+ }
}
@@ -246,6 +266,7 @@ std::string GetConfigString(ConfigEntry entry)
case Firm_Username: return Config::FirmwareUsername;
case Firm_Message: return Config::FirmwareMessage;
+ case WifiSettingsPath: return Config::WifiSettingsPath;
}
return "";
@@ -288,45 +309,72 @@ bool GetConfigArray(ConfigEntry entry, void* data)
return false;
}
+constexpr char AccessMode(FileMode mode, bool file_exists)
+{
+ if (!(mode & FileMode::Write))
+ // If we're only opening the file for reading...
+ return 'r';
+
+ if (mode & (FileMode::NoCreate))
+ // If we're not allowed to create a new file...
+ return 'r'; // Open in "r+" mode (IsExtended will add the "+")
+
+ if ((mode & FileMode::Preserve) && file_exists)
+ // If we're not allowed to overwrite a file that already exists...
+ return 'r'; // Open in "r+" mode (IsExtended will add the "+")
+
+ return 'w';
+}
-FILE* OpenFile(const std::string& path, const std::string& mode, bool mustexist)
+constexpr bool IsExtended(FileMode mode)
{
- QFile f(QString::fromStdString(path));
+ // fopen's "+" flag always opens the file for read/write
+ return (mode & FileMode::ReadWrite) == FileMode::ReadWrite;
+}
- if (mustexist && !f.exists())
- {
+static std::string GetModeString(FileMode mode, bool file_exists)
+{
+ std::string modeString;
+
+ modeString += AccessMode(mode, file_exists);
+
+ if (IsExtended(mode))
+ modeString += '+';
+
+ if (!(mode & FileMode::Text))
+ modeString += 'b';
+
+ return modeString;
+}
+
+FileHandle* OpenFile(const std::string& path, FileMode mode)
+{
+ if ((mode & FileMode::ReadWrite) == FileMode::None)
+ { // If we aren't reading or writing, then we can't open the file
+ Log(LogLevel::Error, "Attempted to open \"%s\" in neither read nor write mode (FileMode 0x%x)\n", path.c_str(), mode);
return nullptr;
}
- QIODevice::OpenMode qmode;
- if (mode.length() > 1 && mode[0] == 'r' && mode[1] == '+')
- {
- qmode = QIODevice::OpenModeFlag::ReadWrite;
- }
- else if (mode.length() > 1 && mode[0] == 'w' && mode[1] == '+')
- {
- qmode = QIODevice::OpenModeFlag::Truncate | QIODevice::OpenModeFlag::ReadWrite;
- }
- else if (mode[0] == 'w')
+ bool file_exists = QFile::exists(QString::fromStdString(path));
+ std::string modeString = GetModeString(mode, file_exists);
+
+ FILE* file = fopen(path.c_str(), modeString.c_str());
+ if (file)
{
- qmode = QIODevice::OpenModeFlag::Truncate | QIODevice::OpenModeFlag::WriteOnly;
+ Log(LogLevel::Debug, "Opened \"%s\" with FileMode 0x%x (effective mode \"%s\")\n", path.c_str(), mode, modeString.c_str());
+ return reinterpret_cast<FileHandle *>(file);
}
else
{
- qmode = QIODevice::OpenModeFlag::ReadOnly;
+ Log(LogLevel::Warn, "Failed to open \"%s\" with FileMode 0x%x (effective mode \"%s\")\n", path.c_str(), mode, modeString.c_str());
+ return nullptr;
}
-
- f.open(qmode);
- FILE* file = fdopen(dup(f.handle()), mode.c_str());
- f.close();
-
- return file;
}
-FILE* OpenLocalFile(const std::string& path, const std::string& mode)
+FileHandle* OpenLocalFile(const std::string& path, FileMode mode)
{
QString qpath = QString::fromStdString(path);
- QDir dir(qpath);
+ QDir dir(qpath);
QString fullpath;
if (dir.isAbsolute())
@@ -347,7 +395,93 @@ FILE* OpenLocalFile(const std::string& path, const std::string& mode)
#endif
}
- return OpenFile(fullpath.toStdString(), mode, mode[0] != 'w');
+ return OpenFile(fullpath.toStdString(), mode);
+}
+
+bool CloseFile(FileHandle* file)
+{
+ return fclose(reinterpret_cast<FILE *>(file)) == 0;
+}
+
+bool IsEndOfFile(FileHandle* file)
+{
+ return feof(reinterpret_cast<FILE *>(file)) != 0;
+}
+
+bool FileReadLine(char* str, int count, FileHandle* file)
+{
+ return fgets(str, count, reinterpret_cast<FILE *>(file)) != nullptr;
+}
+
+bool FileExists(const std::string& name)
+{
+ FileHandle* f = OpenFile(name, FileMode::Read);
+ if (!f) return false;
+ CloseFile(f);
+ return true;
+}
+
+bool LocalFileExists(const std::string& name)
+{
+ FileHandle* f = OpenLocalFile(name, FileMode::Read);
+ if (!f) return false;
+ CloseFile(f);
+ return true;
+}
+
+bool FileSeek(FileHandle* file, s64 offset, FileSeekOrigin origin)
+{
+ int stdorigin;
+ switch (origin)
+ {
+ case FileSeekOrigin::Start: stdorigin = SEEK_SET; break;
+ case FileSeekOrigin::Current: stdorigin = SEEK_CUR; break;
+ case FileSeekOrigin::End: stdorigin = SEEK_END; break;
+ }
+
+ return fseek(reinterpret_cast<FILE *>(file), offset, stdorigin) == 0;
+}
+
+void FileRewind(FileHandle* file)
+{
+ rewind(reinterpret_cast<FILE *>(file));
+}
+
+u64 FileRead(void* data, u64 size, u64 count, FileHandle* file)
+{
+ return fread(data, size, count, reinterpret_cast<FILE *>(file));
+}
+
+bool FileFlush(FileHandle* file)
+{
+ return fflush(reinterpret_cast<FILE *>(file)) == 0;
+}
+
+u64 FileWrite(const void* data, u64 size, u64 count, FileHandle* file)
+{
+ return fwrite(data, size, count, reinterpret_cast<FILE *>(file));
+}
+
+u64 FileWriteFormatted(FileHandle* file, const char* fmt, ...)
+{
+ if (fmt == nullptr)
+ return 0;
+
+ va_list args;
+ va_start(args, fmt);
+ u64 ret = vfprintf(reinterpret_cast<FILE *>(file), fmt, args);
+ va_end(args);
+ return ret;
+}
+
+u64 FileLength(FileHandle* file)
+{
+ FILE* stdfile = reinterpret_cast<FILE *>(file);
+ long pos = ftell(stdfile);
+ fseek(stdfile, 0, SEEK_END);
+ long len = ftell(stdfile);
+ fseek(stdfile, pos, SEEK_SET);
+ return len;
}
void Log(LogLevel level, const char* fmt, ...)
@@ -566,4 +700,19 @@ void Camera_CaptureFrame(int num, u32* frame, int width, int height, bool yuv)
return camManager[num]->captureFrame(frame, width, height, yuv);
}
+DynamicLibrary* DynamicLibrary_Load(const char* lib)
+{
+ return (DynamicLibrary*) SDL_LoadObject(lib);
+}
+
+void DynamicLibrary_Unload(DynamicLibrary* lib)
+{
+ SDL_UnloadObject(lib);
+}
+
+void* DynamicLibrary_LoadFunction(DynamicLibrary* lib, const char* name)
+{
+ return SDL_LoadFunction(lib, name);
+}
+
}
diff --git a/src/frontend/qt_sdl/ROMManager.cpp b/src/frontend/qt_sdl/ROMManager.cpp
index 3b2b72b..a2a5fca 100644
--- a/src/frontend/qt_sdl/ROMManager.cpp
+++ b/src/frontend/qt_sdl/ROMManager.cpp
@@ -36,6 +36,7 @@
#include "SPI.h"
#include "DSi_I2C.h"
+using namespace Platform;
namespace ROMManager
{
@@ -119,137 +120,131 @@ std::string GetAssetPath(bool gba, const std::string& configpath, const std::str
QString VerifyDSBIOS()
{
- FILE* f;
+ FileHandle* f;
long len;
- f = Platform::OpenLocalFile(Config::BIOS9Path, "rb");
+ f = Platform::OpenLocalFile(Config::BIOS9Path, FileMode::Read);
if (!f) return "DS ARM9 BIOS was not found or could not be accessed. Check your emu settings.";
- fseek(f, 0, SEEK_END);
- len = ftell(f);
+ len = FileLength(f);
if (len != 0x1000)
{
- fclose(f);
+ CloseFile(f);
return "DS ARM9 BIOS is not a valid BIOS dump.";
}
- fclose(f);
+ CloseFile(f);
- f = Platform::OpenLocalFile(Config::BIOS7Path, "rb");
+ f = Platform::OpenLocalFile(Config::BIOS7Path, FileMode::Read);
if (!f) return "DS ARM7 BIOS was not found or could not be accessed. Check your emu settings.";
- fseek(f, 0, SEEK_END);
- len = ftell(f);
+ len = FileLength(f);
if (len != 0x4000)
{
- fclose(f);
+ CloseFile(f);
return "DS ARM7 BIOS is not a valid BIOS dump.";
}
- fclose(f);
+ CloseFile(f);
return "";
}
QString VerifyDSiBIOS()
{
- FILE* f;
+ FileHandle* f;
long len;
// TODO: check the first 32 bytes
- f = Platform::OpenLocalFile(Config::DSiBIOS9Path, "rb");
+ f = Platform::OpenLocalFile(Config::DSiBIOS9Path, FileMode::Read);
if (!f) return "DSi ARM9 BIOS was not found or could not be accessed. Check your emu settings.";
- fseek(f, 0, SEEK_END);
- len = ftell(f);
+ len = FileLength(f);
if (len != 0x10000)
{
- fclose(f);
+ CloseFile(f);
return "DSi ARM9 BIOS is not a valid BIOS dump.";
}
- fclose(f);
+ CloseFile(f);
- f = Platform::OpenLocalFile(Config::DSiBIOS7Path, "rb");
+ f = Platform::OpenLocalFile(Config::DSiBIOS7Path, FileMode::Read);
if (!f) return "DSi ARM7 BIOS was not found or could not be accessed. Check your emu settings.";
- fseek(f, 0, SEEK_END);
- len = ftell(f);
+ len = FileLength(f);
if (len != 0x10000)
{
- fclose(f);
+ CloseFile(f);
return "DSi ARM7 BIOS is not a valid BIOS dump.";
}
- fclose(f);
+ CloseFile(f);
return "";
}
QString VerifyDSFirmware()
{
- FILE* f;
+ FileHandle* f;
long len;
- f = Platform::OpenLocalFile(Config::FirmwarePath, "rb");
+ f = Platform::OpenLocalFile(Config::FirmwarePath, FileMode::Read);
if (!f) return "DS firmware was not found or could not be accessed. Check your emu settings.";
- fseek(f, 0, SEEK_END);
- len = ftell(f);
+ len = FileLength(f);
if (len == 0x20000)
{
// 128KB firmware, not bootable
- fclose(f);
+ CloseFile(f);
// TODO report it somehow? detect in core?
return "";
}
else if (len != 0x40000 && len != 0x80000)
{
- fclose(f);
+ CloseFile(f);
return "DS firmware is not a valid firmware dump.";
}
- fclose(f);
+ CloseFile(f);
return "";
}
QString VerifyDSiFirmware()
{
- FILE* f;
+ FileHandle* f;
long len;
- f = Platform::OpenLocalFile(Config::DSiFirmwarePath, "rb");
+ f = Platform::OpenLocalFile(Config::DSiFirmwarePath, FileMode::Read);
if (!f) return "DSi firmware was not found or could not be accessed. Check your emu settings.";
- fseek(f, 0, SEEK_END);
- len = ftell(f);
+ len = FileLength(f);
if (len != 0x20000)
{
// not 128KB
// TODO: check whether those work
- fclose(f);
+ CloseFile(f);
return "DSi firmware is not a valid firmware dump.";
}
- fclose(f);
+ CloseFile(f);
return "";
}
QString VerifyDSiNAND()
{
- FILE* f;
+ FileHandle* f;
long len;
- f = Platform::OpenLocalFile(Config::DSiNANDPath, "r+b");
+ f = Platform::OpenLocalFile(Config::DSiNANDPath, FileMode::ReadWriteExisting);
if (!f) return "DSi NAND was not found or could not be accessed. Check your emu settings.";
// TODO: some basic checks
// check that it has the nocash footer, and all
- fclose(f);
+ CloseFile(f);
return "";
}
@@ -659,29 +654,28 @@ bool LoadROM(QStringList filepath, bool reset)
// regular file
std::string filename = filepath.at(0).toStdString();
- FILE* f = Platform::OpenFile(filename, "rb", true);
+ Platform::FileHandle* f = Platform::OpenFile(filename, FileMode::Read);
if (!f) return false;
- fseek(f, 0, SEEK_END);
- long len = ftell(f);
+ long len = Platform::FileLength(f);
if (len > 0x40000000)
{
- fclose(f);
+ Platform::CloseFile(f);
delete[] filedata;
return false;
}
- fseek(f, 0, SEEK_SET);
+ Platform::FileRewind(f);
filedata = new u8[len];
- size_t nread = fread(filedata, (size_t)len, 1, f);
+ size_t nread = Platform::FileRead(filedata, (size_t)len, 1, f);
if (nread != 1)
{
- fclose(f);
+ Platform::CloseFile(f);
delete[] filedata;
return false;
}
- fclose(f);
+ Platform::CloseFile(f);
filelen = (u32)len;
if (filename.length() > 4 && filename.substr(filename.length() - 4) == ".zst")
@@ -754,17 +748,16 @@ bool LoadROM(QStringList filepath, bool reset)
std::string origsav = savname;
savname += Platform::InstanceFileSuffix();
- FILE* sav = Platform::OpenFile(savname, "rb", true);
- if (!sav) sav = Platform::OpenFile(origsav, "rb", true);
+ FileHandle* sav = Platform::OpenFile(savname, FileMode::Read);
+ if (!sav) sav = Platform::OpenFile(origsav, FileMode::Read);
if (sav)
{
- fseek(sav, 0, SEEK_END);
- savelen = (u32)ftell(sav);
+ savelen = (u32)Platform::FileLength(sav);
- fseek(sav, 0, SEEK_SET);
+ FileRewind(sav);
savedata = new u8[savelen];
- fread(savedata, savelen, 1, sav);
- fclose(sav);
+ FileRead(savedata, savelen, 1, sav);
+ CloseFile(sav);
}
bool res = NDS::LoadCart(filedata, filelen, savedata, savelen);
@@ -841,28 +834,27 @@ bool LoadGBAROM(QStringList filepath)
// regular file
std::string filename = filepath.at(0).toStdString();
- FILE* f = Platform::OpenFile(filename, "rb", true);
+ FileHandle* f = Platform::OpenFile(filename, FileMode::Read);
if (!f) return false;
- fseek(f, 0, SEEK_END);
- long len = ftell(f);
+ long len = FileLength(f);
if (len > 0x40000000)
{
- fclose(f);
+ CloseFile(f);
return false;
}
- fseek(f, 0, SEEK_SET);
+ FileRewind(f);
filedata = new u8[len];
- size_t nread = fread(filedata, (size_t)len, 1, f);
+ size_t nread = FileRead(filedata, (size_t)len, 1, f);
if (nread != 1)
{
- fclose(f);
+ CloseFile(f);
delete[] filedata;
return false;
}
- fclose(f);
+ CloseFile(f);
filelen = (u32)len;
if (filename.length() > 4 && filename.substr(filename.length() - 4) == ".zst")
@@ -926,17 +918,16 @@ bool LoadGBAROM(QStringList filepath)
std::string origsav = savname;
savname += Platform::InstanceFileSuffix();
- FILE* sav = Platform::OpenFile(savname, "rb", true);
- if (!sav) sav = Platform::OpenFile(origsav, "rb", true);
+ FileHandle* sav = Platform::OpenFile(savname, FileMode::Read);
+ if (!sav) sav = Platform::OpenFile(origsav, FileMode::Read);
if (sav)
{
- fseek(sav, 0, SEEK_END);
- savelen = (u32)ftell(sav);
+ savelen = (u32)FileLength(sav);
- fseek(sav, 0, SEEK_SET);
+ FileRewind(sav);
savedata = new u8[savelen];
- fread(savedata, savelen, 1, sav);
- fclose(sav);
+ FileRead(savedata, savelen, 1, sav);
+ CloseFile(sav);
}
bool res = NDS::LoadGBACart(filedata, filelen, savedata, savelen);
diff --git a/src/frontend/qt_sdl/SaveManager.cpp b/src/frontend/qt_sdl/SaveManager.cpp
index 005219b..034b48f 100644
--- a/src/frontend/qt_sdl/SaveManager.cpp
+++ b/src/frontend/qt_sdl/SaveManager.cpp
@@ -22,8 +22,7 @@
#include "SaveManager.h"
#include "Platform.h"
-using Platform::Log;
-using Platform::LogLevel;
+using namespace Platform;
SaveManager::SaveManager(const std::string& path) : QThread()
{
@@ -77,11 +76,11 @@ void SaveManager::SetPath(const std::string& path, bool reload)
if (reload)
{
- FILE* f = Platform::OpenFile(Path, "rb", true);
+ FileHandle* f = Platform::OpenFile(Path, FileMode::Read);
if (f)
{
- fread(Buffer, 1, Length, f);
- fclose(f);
+ FileRead(Buffer, 1, Length, f);
+ CloseFile(f);
}
}
else
@@ -177,12 +176,12 @@ void SaveManager::FlushSecondaryBuffer(u8* dst, u32 dstLength)
}
else
{
- FILE* f = Platform::OpenFile(Path, "wb");
+ FileHandle* f = Platform::OpenFile(Path, FileMode::Write);
if (f)
{
Log(LogLevel::Info, "SaveManager: Written\n");
- fwrite(SecondaryBuffer, SecondaryBufferLength, 1, f);
- fclose(f);
+ FileWrite(SecondaryBuffer, SecondaryBufferLength, 1, f);
+ CloseFile(f);
}
}
PreviousFlushVersion = FlushVersion;
diff --git a/src/frontend/qt_sdl/TitleManagerDialog.cpp b/src/frontend/qt_sdl/TitleManagerDialog.cpp
index 3d52bdd..d5147fc 100644
--- a/src/frontend/qt_sdl/TitleManagerDialog.cpp
+++ b/src/frontend/qt_sdl/TitleManagerDialog.cpp
@@ -30,8 +30,7 @@
#include "ui_TitleManagerDialog.h"
#include "ui_TitleImportDialog.h"
-using Platform::Log;
-using Platform::LogLevel;
+using namespace Platform;
bool TitleManagerDialog::NANDInited = false;
TitleManagerDialog* TitleManagerDialog::currentDlg = nullptr;
@@ -140,14 +139,14 @@ bool TitleManagerDialog::openNAND()
{
NANDInited = false;
- FILE* bios7i = Platform::OpenLocalFile(Config::DSiBIOS7Path, "rb");
+ FileHandle* bios7i = Platform::OpenLocalFile(Config::DSiBIOS7Path, FileMode::Read);
if (!bios7i)
return false;
u8 es_keyY[16];
- fseek(bios7i, 0x8308, SEEK_SET);
- fread(es_keyY, 16, 1, bios7i);
- fclose(bios7i);
+ FileSeek(bios7i, 0x8308, FileSeekOrigin::Start);
+ FileRead(es_keyY, 16, 1, bios7i);
+ CloseFile(bios7i);
if (!DSi_NAND::Init(es_keyY))
{
diff --git a/src/frontend/qt_sdl/main.cpp b/src/frontend/qt_sdl/main.cpp
index e5e1977..de4c09a 100644
--- a/src/frontend/qt_sdl/main.cpp
+++ b/src/frontend/qt_sdl/main.cpp
@@ -2639,7 +2639,7 @@ void MainWindow::onImportSavefile()
return;
}
- FILE* f = Platform::OpenFile(path.toStdString(), "rb", true);
+ Platform::FileHandle* f = Platform::OpenFile(path.toStdString(), Platform::FileMode::Read);
if (!f)
{
QMessageBox::critical(this, "melonDS", "Could not open the given savefile.");
@@ -2661,18 +2661,16 @@ void MainWindow::onImportSavefile()
ROMManager::Reset();
}
- u32 len;
- fseek(f, 0, SEEK_END);
- len = (u32)ftell(f);
+ u32 len = FileLength(f);
u8* data = new u8[len];
- fseek(f, 0, SEEK_SET);
- fread(data, len, 1, f);
+ Platform::FileRewind(f);
+ Platform::FileRead(data, len, 1, f);
NDS::LoadSave(data, len);
delete[] data;
- fclose(f);
+ CloseFile(f);
emuThread->emuUnpause();
}
@@ -3196,8 +3194,6 @@ void emuStop()
RunningSomething = false;
emit emuThread->windowEmuStop();
-
- OSD::AddMessage(0xFFC040, "Shutdown");
}
MelonApplication::MelonApplication(int& argc, char** argv)