verify BIOS and firmware before booting games/firmware

This commit is contained in:
Arisotura 2020-05-17 05:42:09 +02:00
parent 49b24ea2b3
commit c5c9434ac9
5 changed files with 149 additions and 18 deletions

View File

@ -587,7 +587,7 @@ bool DoSavestate_Scheduler(Savestate* file)
} }
if (funcid == -1) if (funcid == -1)
{ {
printf("savestate: VERY BAD!!!!! FUNCTION POINTER FOR EVENT %d NOT IN HACKY LIST. CANNOT SAVE. SMACK STAPLEBUTTER.\n", i); printf("savestate: VERY BAD!!!!! FUNCTION POINTER FOR EVENT %d NOT IN HACKY LIST. CANNOT SAVE. SMACK ARISOTURA.\n", i);
return false; return false;
} }
} }

View File

@ -32,6 +32,24 @@ enum
ROMSlot_MAX ROMSlot_MAX
}; };
enum
{
Load_OK = 0,
Load_BIOS9Missing,
Load_BIOS9Bad,
Load_BIOS7Missing,
Load_BIOS7Bad,
Load_FirmwareMissing,
Load_FirmwareBad,
Load_FirmwareNotBootable,
// TODO: more precise errors for ROM loading
Load_ROMLoadError,
};
extern char ROMPath [ROMSlot_MAX][1024]; extern char ROMPath [ROMSlot_MAX][1024];
extern char SRAMPath[ROMSlot_MAX][1024]; extern char SRAMPath[ROMSlot_MAX][1024];
extern bool SavestateLoaded; extern bool SavestateLoaded;
@ -41,11 +59,11 @@ extern bool SavestateLoaded;
void Init_ROM(); void Init_ROM();
// load the BIOS/firmware and boot from it // load the BIOS/firmware and boot from it
bool LoadBIOS(); int LoadBIOS();
// load a ROM file to the specified cart slot // load a ROM file to the specified cart slot
// note: loading a ROM to the NDS slot resets emulation // note: loading a ROM to the NDS slot resets emulation
bool LoadROM(const char* file, int slot); int LoadROM(const char* file, int slot);
// get the filename associated with the given savestate slot (1-8) // get the filename associated with the given savestate slot (1-8)
void GetSavestateName(int slot, char* filename, int len); void GetSavestateName(int slot, char* filename, int len);

View File

@ -57,8 +57,77 @@ void SetupSRAMPath(int slot)
strncpy(SRAMPath[slot] + strlen(ROMPath[slot]) - 3, "sav", 3); strncpy(SRAMPath[slot] + strlen(ROMPath[slot]) - 3, "sav", 3);
} }
bool LoadBIOS() int VerifyDSBIOS()
{ {
FILE* f;
long len;
f = Platform::OpenLocalFile(Config::BIOS9Path, "rb");
if (!f) return Load_BIOS9Missing;
fseek(f, 0, SEEK_END);
len = ftell(f);
if (len != 0x1000)
{
fclose(f);
return Load_BIOS9Bad;
}
fclose(f);
f = Platform::OpenLocalFile(Config::BIOS7Path, "rb");
if (!f) return Load_BIOS7Missing;
fseek(f, 0, SEEK_END);
len = ftell(f);
if (len != 0x4000)
{
fclose(f);
return Load_BIOS7Bad;
}
fclose(f);
return Load_OK;
}
int VerifyDSFirmware()
{
FILE* f;
long len;
f = Platform::OpenLocalFile(Config::FirmwarePath, "rb");
if (!f) return Load_FirmwareMissing;
fseek(f, 0, SEEK_END);
len = ftell(f);
if (len == 0x20000)
{
// 128KB firmware, not bootable
fclose(f);
return Load_FirmwareNotBootable;
}
else if (len != 0x40000 && len != 0x80000)
{
fclose(f);
return Load_FirmwareBad;
}
fclose(f);
return Load_OK;
}
int LoadBIOS()
{
int res;
res = VerifyDSBIOS();
if (res != Load_OK) return res;
res = VerifyDSFirmware();
if (res != Load_OK) return res;
// TODO: // TODO:
// original code in the libui frontend called NDS::LoadGBAROM() if needed // original code in the libui frontend called NDS::LoadGBAROM() if needed
// should this be carried over here? // should this be carried over here?
@ -71,12 +140,26 @@ bool LoadBIOS()
SavestateLoaded = false; SavestateLoaded = false;
// TODO: error reporting? return Load_OK;
return true;
} }
bool LoadROM(const char* file, int slot) int LoadROM(const char* file, int slot)
{ {
int res;
bool directboot = Config::DirectBoot != 0;
res = VerifyDSBIOS();
if (res != Load_OK) return res;
res = VerifyDSFirmware();
if (res != Load_OK)
{
if (res == Load_FirmwareNotBootable)
directboot = true;
else
return res;
}
char oldpath[1024]; char oldpath[1024];
char oldsram[1024]; char oldsram[1024];
strncpy(oldpath, ROMPath[slot], 1024); strncpy(oldpath, ROMPath[slot], 1024);
@ -88,28 +171,29 @@ bool LoadROM(const char* file, int slot)
SetupSRAMPath(0); SetupSRAMPath(0);
SetupSRAMPath(1); SetupSRAMPath(1);
if (slot == ROMSlot_NDS && NDS::LoadROM(ROMPath[slot], SRAMPath[slot], Config::DirectBoot)) if (slot == ROMSlot_NDS && NDS::LoadROM(ROMPath[slot], SRAMPath[slot], directboot))
{ {
SavestateLoaded = false; SavestateLoaded = false;
// Reload the inserted GBA cartridge (if any) // Reload the inserted GBA cartridge (if any)
// TODO: report failure there??
if (ROMPath[ROMSlot_GBA][0] != '\0') NDS::LoadGBAROM(ROMPath[ROMSlot_GBA], SRAMPath[ROMSlot_GBA]); if (ROMPath[ROMSlot_GBA][0] != '\0') NDS::LoadGBAROM(ROMPath[ROMSlot_GBA], SRAMPath[ROMSlot_GBA]);
strncpy(PrevSRAMPath[slot], SRAMPath[slot], 1024); // safety strncpy(PrevSRAMPath[slot], SRAMPath[slot], 1024); // safety
return true; return Load_OK;
} }
else if (slot == ROMSlot_GBA && NDS::LoadGBAROM(ROMPath[slot], SRAMPath[slot])) else if (slot == ROMSlot_GBA && NDS::LoadGBAROM(ROMPath[slot], SRAMPath[slot]))
{ {
SavestateLoaded = false; SavestateLoaded = false;
strncpy(PrevSRAMPath[slot], SRAMPath[slot], 1024); // safety strncpy(PrevSRAMPath[slot], SRAMPath[slot], 1024); // safety
return true; return Load_OK;
} }
else else
{ {
strncpy(ROMPath[slot], oldpath, 1024); strncpy(ROMPath[slot], oldpath, 1024);
strncpy(SRAMPath[slot], oldsram, 1024); strncpy(SRAMPath[slot], oldsram, 1024);
return false; return Load_ROMLoadError;
} }
} }

View File

@ -570,6 +570,27 @@ void MainWindow::keyPressEvent(QKeyEvent* event)
} }
QString MainWindow::loadErrorStr(int error)
{
switch (error)
{
case Frontend::Load_BIOS9Missing: return "DS ARM9 BIOS was not found or could not be accessed.";
case Frontend::Load_BIOS9Bad: return "DS ARM9 BIOS is not a valid BIOS dump.";
case Frontend::Load_BIOS7Missing: return "DS ARM7 BIOS was not found or could not be accessed.";
case Frontend::Load_BIOS7Bad: return "DS ARM7 BIOS is not a valid BIOS dump.";
case Frontend::Load_FirmwareMissing: return "DS firmware was not found or could not be accessed.";
case Frontend::Load_FirmwareBad: return "DS firmware is not a valid firmware dump.";
case Frontend::Load_FirmwareNotBootable: return "DS firmware is not bootable.";
case Frontend::Load_ROMLoadError: return "Failed to load the ROM. Make sure the file is accessible and isn't used by another application.";
default: return "Unknown error during launch; smack Arisotura.";
}
}
void MainWindow::onOpenFile() void MainWindow::onOpenFile()
{ {
emuThread->emuPause(true); emuThread->emuPause(true);
@ -584,6 +605,11 @@ void MainWindow::onOpenFile()
return; return;
} }
// TODO: validate the input file!!
// * check that it is a proper ROM
// * ensure the binary offsets are sane
// * etc
// this shit is stupid // this shit is stupid
char file[1024]; char file[1024];
strncpy(file, filename.toStdString().c_str(), 1023); file[1023] = '\0'; strncpy(file, filename.toStdString().c_str(), 1023); file[1023] = '\0';
@ -594,7 +620,7 @@ void MainWindow::onOpenFile()
Config::LastROMFolder[pos] = '\0'; Config::LastROMFolder[pos] = '\0';
char* ext = &file[strlen(file)-3]; char* ext = &file[strlen(file)-3];
int slot; bool res; int slot; int res;
if (!strcasecmp(ext, "gba")) if (!strcasecmp(ext, "gba"))
{ {
slot = 1; slot = 1;
@ -606,11 +632,11 @@ void MainWindow::onOpenFile()
res = Frontend::LoadROM(file, Frontend::ROMSlot_NDS); res = Frontend::LoadROM(file, Frontend::ROMSlot_NDS);
} }
if (!res) if (res != Frontend::Load_OK)
{ {
QMessageBox::critical(this, QMessageBox::critical(this,
"melonDS", "melonDS",
"Failed to load the ROM.\n\nMake sure the file is accessible and isn't used by another application."); loadErrorStr(res));
emuThread->emuUnpause(); emuThread->emuUnpause();
} }
else if (slot == 1) else if (slot == 1)
@ -631,11 +657,12 @@ void MainWindow::onBootFirmware()
emuThread->emuPause(true); emuThread->emuPause(true);
bool res = Frontend::LoadBIOS(); int res = Frontend::LoadBIOS();
if (!res) if (res != Frontend::Load_OK)
{ {
// TODO! QMessageBox::critical(this,
"melonDS",
loadErrorStr(res));
emuThread->emuUnpause(); emuThread->emuUnpause();
} }
else else

View File

@ -110,6 +110,8 @@ private slots:
void onOpenEmuSettings(); void onOpenEmuSettings();
private: private:
QString loadErrorStr(int error);
MainWindowPanel* panel; MainWindowPanel* panel;
QAction* actOpenROM; QAction* actOpenROM;