From ee5567708630441d8d3210e81d6e03d028fb7bbd Mon Sep 17 00:00:00 2001 From: Jesse Talavera-Greenberg Date: Fri, 18 Aug 2023 16:50:57 -0400 Subject: [PATCH] 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 --- src/ARCodeFile.cpp | 37 ++- src/ARM.cpp | 2 +- src/ARMJIT_Memory.cpp | 23 +- src/CP15.cpp | 4 +- src/DSi.cpp | 39 ++-- src/DSi_Camera.cpp | 16 +- src/DSi_I2C.cpp | 2 +- src/DSi_NAND.cpp | 52 ++--- src/DSi_NAND.h | 2 +- src/DSi_NWifi.cpp | 16 +- src/DSi_SD.cpp | 17 +- src/DSi_SD.h | 2 +- src/FATStorage.cpp | 97 ++++---- src/FATStorage.h | 9 +- src/GBACart.cpp | 2 +- src/GPU2D.cpp | 6 +- src/GPU3D.cpp | 10 +- src/NDS.cpp | 100 +++++--- src/NDS.h | 5 +- src/Platform.h | 257 ++++++++++++++++++--- src/SPI.cpp | 61 +++-- src/Wifi.cpp | 4 +- src/WifiAP.cpp | 8 +- src/dolphin/CommonFuncs.cpp | 3 +- src/frontend/qt_sdl/Config.cpp | 27 +-- src/frontend/qt_sdl/Config.h | 1 + src/frontend/qt_sdl/EmuSettingsDialog.cpp | 13 +- src/frontend/qt_sdl/LAN_PCap.cpp | 15 +- src/frontend/qt_sdl/LAN_PCap.h | 2 +- src/frontend/qt_sdl/LAN_Socket.cpp | 24 +- src/frontend/qt_sdl/LAN_Socket.h | 2 +- src/frontend/qt_sdl/Platform.cpp | 205 +++++++++++++--- src/frontend/qt_sdl/ROMManager.cpp | 127 +++++----- src/frontend/qt_sdl/SaveManager.cpp | 15 +- src/frontend/qt_sdl/TitleManagerDialog.cpp | 11 +- src/frontend/qt_sdl/main.cpp | 14 +- 36 files changed, 787 insertions(+), 443 deletions(-) diff --git a/src/ARCodeFile.cpp b/src/ARCodeFile.cpp index 45583ca8..79c582d1 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 6063bca0..b59530d1 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 0901248e..8e6a9f6a 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(symbol); + auto ASharedMemory_create = reinterpret_cast(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 7db7b602..52fd5604 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 c6df5dfd..2f92a5df 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 19e6c5ee..9f45a6aa 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 7bb7e1d7..c4ad50c5 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 6adfcffa..38f8c52b 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 76d5ee2b..14599b26 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 b07d7a7f..2f84cdc5 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 59262cbd..4f287b17 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 75101edc..fe9e23ab 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 07cf4917..d882f8dc 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::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 250f0239..6b9beb50 100644 --- a/src/FATStorage.h +++ b/src/FATStorage.h @@ -24,6 +24,7 @@ #include #include +#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 d35edf2d..020219df 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 9d616d31..d5df9929 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 145b689f..5611b146 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 5caaaee6..b329c10c 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 404e07c2..571952df 100644 --- a/src/NDS.h +++ b/src/NDS.h @@ -21,6 +21,7 @@ #include +#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 59e7c02b..91da4c1e 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, -// instance ID, for local multiplayer + /** + * 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, +}; + +/** + * 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(). +/** + * 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, -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); + /** + * Opens a file for reading. + * Either this or \c Write must be set. + * Similar to \c "r" in \c fopen. + */ + Read = 0b00'00'01, -inline bool FileExists(const std::string& name) + /** + * 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 fopen'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 Read | Write. + */ + ReadWrite = Read | Write, + + /** + * Opens a file for reading and writing + * without truncating it or creating a new one. + * Equivalent to Read | Write | Preserve | NoCreate. + */ + ReadWriteExisting = Read | Write | Preserve | NoCreate, + + /** + * Opens a file for reading in text mode. + * Equivalent to Read | Text. + */ + ReadText = Read | Text, + + /** + * Opens a file for writing in text mode, + * creating it if it doesn't exist. + * Equivalent to Write | Text. + */ + WriteText = Write | Text, +}; + +/** + * Denotes the origin of a seek operation. + * Similar to \c fseek's \c SEEK_* constants. + */ +enum class FileSeekOrigin { - FILE* f = OpenFile(name, "rb"); - if (!f) return false; - fclose(f); - return true; -} + Start, + Current, + End, +}; -inline bool LocalFileExists(const std::string& name) -{ - FILE* f = OpenLocalFile(name, "rb"); - if (!f) return false; - fclose(f); - return true; -} +/** + * 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 c83a77c9..bbfacbf2 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 aa3cf1d7..298ba9dd 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 898ee167..9fef220d 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 f85051d2..c15a6099 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 b4d78f7c..898e4a16 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 1cd0e562..504c068d 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 b984e05d..0bdbb5c7 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 2a04e701..f5bf4366 100644 --- a/src/frontend/qt_sdl/LAN_PCap.cpp +++ b/src/frontend/qt_sdl/LAN_PCap.cpp @@ -21,9 +21,8 @@ #include #include #include -#include #include -#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 610c0ae2..2f4663f0 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 6c00b582..6753bb87 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 @@ -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 2073d1b2..f2c7ed44 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 eef9934a..5263377e 100644 --- a/src/frontend/qt_sdl/Platform.cpp +++ b/src/frontend/qt_sdl/Platform.cpp @@ -29,6 +29,7 @@ #include #include #include +#include #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; } - -FILE* OpenFile(const std::string& path, const std::string& mode, bool mustexist) +constexpr char AccessMode(FileMode mode, bool file_exists) { - QFile f(QString::fromStdString(path)); + if (!(mode & FileMode::Write)) + // If we're only opening the file for reading... + return 'r'; - if (mustexist && !f.exists()) - { + 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'; +} + +constexpr bool IsExtended(FileMode mode) +{ + // fopen's "+" flag always opens the file for read/write + return (mode & FileMode::ReadWrite) == FileMode::ReadWrite; +} + +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] == '+') + 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::ReadWrite; - } - else if (mode.length() > 1 && mode[0] == 'w' && mode[1] == '+') - { - qmode = QIODevice::OpenModeFlag::Truncate | QIODevice::OpenModeFlag::ReadWrite; - } - else if (mode[0] == 'w') - { - 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(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)) == 0; +} + +bool IsEndOfFile(FileHandle* file) +{ + return feof(reinterpret_cast(file)) != 0; +} + +bool FileReadLine(char* str, int count, FileHandle* file) +{ + return fgets(str, count, reinterpret_cast(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), offset, stdorigin) == 0; +} + +void FileRewind(FileHandle* file) +{ + rewind(reinterpret_cast(file)); +} + +u64 FileRead(void* data, u64 size, u64 count, FileHandle* file) +{ + return fread(data, size, count, reinterpret_cast(file)); +} + +bool FileFlush(FileHandle* file) +{ + return fflush(reinterpret_cast(file)) == 0; +} + +u64 FileWrite(const void* data, u64 size, u64 count, FileHandle* file) +{ + return fwrite(data, size, count, reinterpret_cast(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), fmt, args); + va_end(args); + return ret; +} + +u64 FileLength(FileHandle* file) +{ + FILE* stdfile = reinterpret_cast(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 3b2b72b6..a2a5fca6 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 005219b8..034b48f3 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 3d52bddf..d5147fc6 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 e5e1977b..de4c09a1 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)