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:
parent
f454eba3c3
commit
ee55677086
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
39
src/DSi.cpp
39
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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -199,7 +199,7 @@ void DoHardwareReset(bool direct)
|
|||
void DoShutdown()
|
||||
{
|
||||
ResetButtonState();
|
||||
NDS::Stop();
|
||||
NDS::Stop(Platform::StopReason::PowerOff);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@ enum
|
|||
bool Init(u8* es_keyY);
|
||||
void DeInit();
|
||||
|
||||
FILE* GetFile();
|
||||
Platform::FileHandle* GetFile();
|
||||
|
||||
void GetIDs(u8* emmc_cid, u64& consoleid);
|
||||
|
||||
|
|
|
@ -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];
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -142,7 +142,7 @@ public:
|
|||
|
||||
private:
|
||||
bool Internal;
|
||||
FILE* File;
|
||||
Platform::FileHandle* File;
|
||||
FATStorage* SD;
|
||||
|
||||
u8 CID[16];
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
100
src/NDS.cpp
100
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]);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
257
src/Platform.h
257
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 <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
|
||||
|
|
61
src/SPI.cpp
61
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:
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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??
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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))
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
#ifndef LAN_PCAP_H
|
||||
#define LAN_PCAP_H
|
||||
|
||||
#include "../types.h"
|
||||
#include "types.h"
|
||||
|
||||
namespace LAN_PCap
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
#ifndef LAN_SOCKET_H
|
||||
#define LAN_SOCKET_H
|
||||
|
||||
#include "../types.h"
|
||||
#include "types.h"
|
||||
|
||||
namespace LAN_Socket
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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))
|
||||
{
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue