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
This commit is contained in:
Jesse Talavera-Greenberg 2023-08-18 16:50:57 -04:00 committed by GitHub
parent f454eba3c3
commit ee55677086
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
36 changed files with 787 additions and 443 deletions

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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
}

View File

@ -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;
}

View File

@ -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);

View File

@ -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);
}

View File

@ -199,7 +199,7 @@ void DoHardwareReset(bool direct)
void DoShutdown()
{
ResetButtonState();
NDS::Stop();
NDS::Stop(Platform::StopReason::PowerOff);
}

View File

@ -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;
}

View File

@ -38,7 +38,7 @@ enum
bool Init(u8* es_keyY);
void DeInit();
FILE* GetFile();
Platform::FileHandle* GetFile();
void GetIDs(u8* emmc_cid, u64& consoleid);

View File

@ -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];

View File

@ -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);
}
}
}

View File

@ -142,7 +142,7 @@ public:
private:
bool Internal;
FILE* File;
Platform::FileHandle* File;
FATStorage* SD;
u8 CID[16];

View File

@ -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;

View File

@ -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();

View File

@ -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);
}

View File

@ -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)

View File

@ -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)

View File

@ -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]);
}
}

View File

@ -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);

View File

@ -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 <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,
};
/**
* 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

View File

@ -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:

View File

@ -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);

View File

@ -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??

View File

@ -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

View File

@ -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);
}
}

View File

@ -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;

View File

@ -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))
{

View File

@ -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;
}
}

View File

@ -19,7 +19,7 @@
#ifndef LAN_PCAP_H
#define LAN_PCAP_H
#include "../types.h"
#include "types.h"
namespace LAN_PCap
{

View File

@ -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;
}

View File

@ -19,7 +19,7 @@
#ifndef LAN_SOCKET_H
#define LAN_SOCKET_H
#include "../types.h"
#include "types.h"
namespace LAN_Socket
{

View File

@ -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;
}
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<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);
}
}

View File

@ -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);

View File

@ -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;

View File

@ -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))
{

View File

@ -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)