From d6efb03248e3c7751b0c7e5d3b6398ea671325b0 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Mon, 27 Apr 2020 20:59:11 +0200 Subject: HARK HARK HARK --- src/frontend/Util_ROM.cpp | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 src/frontend/Util_ROM.cpp (limited to 'src/frontend/Util_ROM.cpp') diff --git a/src/frontend/Util_ROM.cpp b/src/frontend/Util_ROM.cpp new file mode 100644 index 0000000..b3077f7 --- /dev/null +++ b/src/frontend/Util_ROM.cpp @@ -0,0 +1,17 @@ +/* + Copyright 2016-2020 Arisotura + + This file is part of melonDS. + + melonDS is free software: you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free + Software Foundation, either version 3 of the License, or (at your option) + any later version. + + melonDS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with melonDS. If not, see http://www.gnu.org/licenses/. +*/ -- cgit v1.2.3 From 931da1c66fb50138109f8bf4cb157db8f1e79c64 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Mon, 27 Apr 2020 22:02:45 +0200 Subject: add a bunch of code --- src/CMakeLists.txt | 2 + src/Config.h | 2 + src/frontend/FrontendUtil.h | 38 ++++++- src/frontend/Util_ROM.cpp | 236 +++++++++++++++++++++++++++++++++++++++++++ src/frontend/qt_sdl/main.cpp | 19 ++-- 5 files changed, 284 insertions(+), 13 deletions(-) (limited to 'src/frontend/Util_ROM.cpp') diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 64d922c..dca0ca9 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -26,6 +26,8 @@ add_library(core STATIC Savestate.cpp SPI.cpp SPU.cpp + types.h + version.h Wifi.cpp WifiAP.cpp ) diff --git a/src/Config.h b/src/Config.h index 84fd57b..0aeab85 100644 --- a/src/Config.h +++ b/src/Config.h @@ -19,6 +19,8 @@ #ifndef CONFIG_H #define CONFIG_H +#include + #include "types.h" namespace Config diff --git a/src/frontend/FrontendUtil.h b/src/frontend/FrontendUtil.h index 6a199b7..7e171ce 100644 --- a/src/frontend/FrontendUtil.h +++ b/src/frontend/FrontendUtil.h @@ -21,10 +21,44 @@ #include "types.h" -namespace FrontendUtil +namespace Frontend { -// +enum +{ + ROMSlot_NDS = 0, + ROMSlot_GBA, + + ROMSlot_MAX +}; + +extern char ROMPath [ROMSlot_MAX][1024]; +extern char SRAMPath[ROMSlot_MAX][1024]; +extern bool SavestateLoaded; + + +// initialize the ROM handling utility +void Init_ROM(); + +// load a ROM file to the specified cart slot +// note: loading a ROM to the NDS slot resets emulation +bool LoadROM(char* file, int slot); + +// get the filename associated with the given savestate slot +void GetSavestateName(int slot, char* filename, int len); + +// determine whether the given savestate slot does contain a savestate +bool SavestateExists(int slot); + +// load the given savestate file +// if successful, emulation will continue from the savestate's point +bool LoadState(const char* filename); + +// save the current emulator state to the given file +bool SaveState(const char* filename); + +// undo the latest savestate load +void UndoStateLoad(); } diff --git a/src/frontend/Util_ROM.cpp b/src/frontend/Util_ROM.cpp index b3077f7..574148b 100644 --- a/src/frontend/Util_ROM.cpp +++ b/src/frontend/Util_ROM.cpp @@ -15,3 +15,239 @@ You should have received a copy of the GNU General Public License along with melonDS. If not, see http://www.gnu.org/licenses/. */ + +#include +#include + +#include "FrontendUtil.h" +#include "Config.h" +#include "qt_sdl/PlatformConfig.h" // FIXME!!! +#include "Platform.h" + +#include "NDS.h" +#include "GBACart.h" + + +namespace Frontend +{ + +char ROMPath [ROMSlot_MAX][1024]; +char SRAMPath [ROMSlot_MAX][1024]; +char PrevSRAMPath[ROMSlot_MAX][1024]; // for savestate 'undo load' + +bool SavestateLoaded; + + +void Init_ROM() +{ + SavestateLoaded = false; + + memset(ROMPath[ROMSlot_NDS], 0, 1024); + memset(ROMPath[ROMSlot_GBA], 0, 1024); + memset(SRAMPath[ROMSlot_NDS], 0, 1024); + memset(SRAMPath[ROMSlot_GBA], 0, 1024); + memset(PrevSRAMPath[ROMSlot_NDS], 0, 1024); + memset(PrevSRAMPath[ROMSlot_GBA], 0, 1024); +} + +void SetupSRAMPath(int slot) +{ + strncpy(SRAMPath[slot], ROMPath[slot], 1023); + SRAMPath[slot][1023] = '\0'; + strncpy(SRAMPath[slot] + strlen(ROMPath[slot]) - 3, "sav", 3); +} + +bool LoadROM(char* file, int slot) +{ + char oldpath[1024]; + char oldsram[1024]; + strncpy(oldpath, ROMPath[slot], 1024); + strncpy(oldsram, SRAMPath[slot], 1024); + + strncpy(ROMPath[slot], file, 1023); + ROMPath[slot][1023] = '\0'; + + SetupSRAMPath(0); + SetupSRAMPath(1); + + if (slot == ROMSlot_NDS && NDS::LoadROM(ROMPath[slot], SRAMPath[slot], Config::DirectBoot)) + { + SavestateLoaded = false; + + // Reload the inserted GBA cartridge (if any) + if (ROMPath[ROMSlot_GBA][0] != '\0') NDS::LoadGBAROM(ROMPath[ROMSlot_GBA], SRAMPath[ROMSlot_GBA]); + + strncpy(PrevSRAMPath[slot], SRAMPath[slot], 1024); // safety + return true; + } + else if (slot == ROMSlot_GBA && NDS::LoadGBAROM(ROMPath[slot], SRAMPath[slot])) + { + SavestateLoaded = false; + + strncpy(PrevSRAMPath[slot], SRAMPath[slot], 1024); // safety + return true; + } + else + { + strncpy(ROMPath[slot], oldpath, 1024); + strncpy(SRAMPath[slot], oldsram, 1024); + return false; + } +} + + +// SAVESTATE TODO +// * configurable paths. not everyone wants their ROM directory to be polluted, I guess. + +void GetSavestateName(int slot, char* filename, int len) +{ + int pos; + + if (ROMPath[ROMSlot_NDS][0] == '\0') // running firmware, no ROM + { + strcpy(filename, "firmware"); + pos = 8; + } + else + { + int l = strlen(ROMPath[ROMSlot_NDS]); + pos = l; + while (ROMPath[ROMSlot_NDS][pos] != '.' && pos > 0) pos--; + if (pos == 0) pos = l; + + // avoid buffer overflow. shoddy + if (pos > len-5) pos = len-5; + + strncpy(&filename[0], ROMPath[ROMSlot_NDS], pos); + } + strcpy(&filename[pos], ".ml"); + filename[pos+3] = '0'+slot; + filename[pos+4] = '\0'; +} + +bool SavestateExists(int slot) +{ + char ssfile[1024]; + GetSavestateName(slot, ssfile, 1024); + return Platform::FileExists(ssfile); +} + +bool LoadState(const char* filename) +{ + u32 oldGBACartCRC = GBACart::CartCRC; + + // backup + Savestate* backup = new Savestate("timewarp.mln", true); + NDS::DoSavestate(backup); + delete backup; + + bool failed = false; + + Savestate* state = new Savestate(filename, false); + if (state->Error) + { + delete state; + + //uiMsgBoxError(MainWindow, "Error", "Could not load savestate file."); + + // current state might be crapoed, so restore from sane backup + state = new Savestate("timewarp.mln", false); + failed = true; + } + + NDS::DoSavestate(state); + delete state; + + if (!failed) + { + if (Config::SavestateRelocSRAM && ROMPath[ROMSlot_NDS][0]!='\0') + { + strncpy(PrevSRAMPath[ROMSlot_NDS], SRAMPath[0], 1024); + + strncpy(SRAMPath[ROMSlot_NDS], filename, 1019); + int len = strlen(SRAMPath[ROMSlot_NDS]); + strcpy(&SRAMPath[ROMSlot_NDS][len], ".sav"); + SRAMPath[ROMSlot_NDS][len+4] = '\0'; + + NDS::RelocateSave(SRAMPath[ROMSlot_NDS], false); + } + + bool loadedPartialGBAROM = false; + + // in case we have a GBA cart inserted, and the GBA ROM changes + // due to having loaded a save state, we do not want to reload + // the previous cartridge on reset, or commit writes to any + // loaded save file. therefore, their paths are "nulled". + if (GBACart::CartInserted && GBACart::CartCRC != oldGBACartCRC) + { + ROMPath[ROMSlot_GBA][0] = '\0'; + SRAMPath[ROMSlot_GBA][0] = '\0'; + loadedPartialGBAROM = true; + } + + // TODO forward this to user in a meaningful way!! + /*char msg[64]; + if (slot > 0) sprintf(msg, "State loaded from slot %d%s", + slot, loadedPartialGBAROM ? " (GBA ROM header only)" : ""); + else sprintf(msg, "State loaded from file%s", + loadedPartialGBAROM ? " (GBA ROM header only)" : ""); + OSD::AddMessage(0, msg);*/ + + SavestateLoaded = true; + } + + return !failed; +} + +bool SaveState(const char* filename) +{ + Savestate* state = new Savestate(filename, true); + if (state->Error) + { + delete state; + return false; + } + else + { + NDS::DoSavestate(state); + delete state; + + if (Config::SavestateRelocSRAM && ROMPath[ROMSlot_NDS][0]!='\0') + { + strncpy(SRAMPath[ROMSlot_NDS], filename, 1019); + int len = strlen(SRAMPath[ROMSlot_NDS]); + strcpy(&SRAMPath[ROMSlot_NDS][len], ".sav"); + SRAMPath[ROMSlot_NDS][len+4] = '\0'; + + NDS::RelocateSave(SRAMPath[ROMSlot_NDS], true); + } + } + + /*char msg[64]; + if (slot > 0) sprintf(msg, "State saved to slot %d", slot); + else sprintf(msg, "State saved to file"); + OSD::AddMessage(0, msg);*/ + return true; +} + +void UndoStateLoad() +{ + if (!SavestateLoaded) return; + + // pray that this works + // what do we do if it doesn't??? + // but it should work. + Savestate* backup = new Savestate("timewarp.mln", false); + NDS::DoSavestate(backup); + delete backup; + + if (ROMPath[ROMSlot_NDS][0]!='\0') + { + strncpy(SRAMPath[ROMSlot_NDS], PrevSRAMPath[ROMSlot_NDS], 1024); + NDS::RelocateSave(SRAMPath[ROMSlot_NDS], false); + } + + //OSD::AddMessage(0, "State load undone"); +} + +} diff --git a/src/frontend/qt_sdl/main.cpp b/src/frontend/qt_sdl/main.cpp index 4999d94..648cd99 100644 --- a/src/frontend/qt_sdl/main.cpp +++ b/src/frontend/qt_sdl/main.cpp @@ -49,11 +49,6 @@ char* EmuDirectory; bool RunningSomething; -char ROMPath[2][1024]; -char SRAMPath[2][1024]; -char PrevSRAMPath[2][1024]; // for savestate 'undo load' - -bool SavestateLoaded; MainWindow* mainWindow; EmuThread* emuThread; @@ -334,8 +329,8 @@ void EmuThread::emuPause(bool refresh) { int status = refresh ? 2:3; PrevEmuStatus = EmuRunning; - EmuRunning = status;printf("emuPause %d -> %d %d\n", PrevEmuStatus, EmuRunning, EmuStatus); - while (EmuStatus != status);printf("wait done\n"); + EmuRunning = status; + while (EmuStatus != status); } void EmuThread::emuUnpause() @@ -370,7 +365,7 @@ void MainWindowPanel::paintEvent(QPaintEvent* event) MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent) { - setWindowTitle("melonDS - assfucking Qt version"); + setWindowTitle("melonDS " MELONDS_VERSION); QMenuBar* menubar = new QMenuBar(); { @@ -569,6 +564,7 @@ int main(int argc, char** argv) emuThread->start(); emuThread->emuPause(true); + #if 0 if (argc > 1) { char* file = argv[1]; @@ -601,11 +597,12 @@ int main(int argc, char** argv) } } } + #endif int ret = melon.exec(); -printf("melon over\n"); - emuThread->emuStop();printf("STOP\n"); - emuThread->wait();printf("farked\n"); + + emuThread->emuStop(); + emuThread->wait(); Config::Save(); -- cgit v1.2.3 From 3c883a2152c699b432c951b3498a1adc3d4c21b1 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Mon, 27 Apr 2020 22:32:33 +0200 Subject: hey look, it runs shit now! --- src/frontend/FrontendUtil.h | 2 +- src/frontend/Util_ROM.cpp | 2 +- src/frontend/qt_sdl/main.cpp | 60 +++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 58 insertions(+), 6 deletions(-) (limited to 'src/frontend/Util_ROM.cpp') diff --git a/src/frontend/FrontendUtil.h b/src/frontend/FrontendUtil.h index 7e171ce..91f3cdd 100644 --- a/src/frontend/FrontendUtil.h +++ b/src/frontend/FrontendUtil.h @@ -42,7 +42,7 @@ void Init_ROM(); // load a ROM file to the specified cart slot // note: loading a ROM to the NDS slot resets emulation -bool LoadROM(char* file, int slot); +bool LoadROM(const char* file, int slot); // get the filename associated with the given savestate slot void GetSavestateName(int slot, char* filename, int len); diff --git a/src/frontend/Util_ROM.cpp b/src/frontend/Util_ROM.cpp index 574148b..ffee69a 100644 --- a/src/frontend/Util_ROM.cpp +++ b/src/frontend/Util_ROM.cpp @@ -57,7 +57,7 @@ void SetupSRAMPath(int slot) strncpy(SRAMPath[slot] + strlen(ROMPath[slot]) - 3, "sav", 3); } -bool LoadROM(char* file, int slot) +bool LoadROM(const char* file, int slot) { char oldpath[1024]; char oldsram[1024]; diff --git a/src/frontend/qt_sdl/main.cpp b/src/frontend/qt_sdl/main.cpp index 648cd99..6b4c873 100644 --- a/src/frontend/qt_sdl/main.cpp +++ b/src/frontend/qt_sdl/main.cpp @@ -35,13 +35,15 @@ #include "types.h" #include "version.h" +#include "FrontendUtil.h" + #include "NDS.h" -#include "GBACart.h" #include "GPU.h" #include "SPU.h" #include "Wifi.h" #include "Platform.h" #include "Config.h" +#include "PlatformConfig.h" #include "Savestate.h" @@ -102,7 +104,7 @@ void EmuThread::run() char melontitle[100]; SDL_mutex* titlemutex = SDL_CreateMutex(); void* titledata[2] = {melontitle, titlemutex}; -printf("emu thread start: %d\n", EmuRunning); + while (EmuRunning != 0) { /*ProcessInput(); @@ -389,8 +391,56 @@ MainWindow::~MainWindow() void MainWindow::onOpenFile() { - QString filename = QFileDialog::getOpenFileName(this, "Open ROM", "", "DS ROMs (*.nds *.srl);;Any file (*.*)"); - printf("fark: %p %d %s\n", filename, filename.isEmpty(), filename.toStdString().c_str()); + emuThread->emuPause(true); + + QString filename = QFileDialog::getOpenFileName(this, + "Open ROM", + Config::LastROMFolder, + "DS ROMs (*.nds *.srl);;GBA ROMs (*.gba);;Any file (*.*)"); + if (filename.isEmpty()) + { + emuThread->emuUnpause(); + return; + } + + // this shit is stupid + char file[1024]; + strncpy(file, filename.toStdString().c_str(), 1023); file[1023] = '\0'; + + int pos = strlen(file)-1; + while (file[pos] != '/' && file[pos] != '\\' && pos > 0) pos--; + strncpy(Config::LastROMFolder, file, pos); + Config::LastROMFolder[pos] = '\0'; + char* ext = &file[strlen(file)-3]; + + int slot; bool res; + if (!strcasecmp(ext, "gba")) + { + slot = 1; + res = Frontend::LoadROM(file, Frontend::ROMSlot_GBA); + } + else + { + slot = 0; + res = Frontend::LoadROM(file, Frontend::ROMSlot_NDS); + } + + if (!res) + { + QMessageBox::critical(this, + "melonDS", + "Failed to load the ROM.\n\nMake sure the file is accessible and isn't used by another application."); + emuThread->emuUnpause(); + } + else if (slot == 1) + { + // checkme + emuThread->emuUnpause(); + } + else + { + emuThread->emuRun(); + } } @@ -557,6 +607,8 @@ int main(int argc, char** argv) } #endif + RunningSomething = false; + mainWindow = new MainWindow(); mainWindow->show(); -- cgit v1.2.3 From 63efc2e02aa51c44c9cb5abc621624aa1d7bf1e5 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Tue, 28 Apr 2020 22:45:11 +0200 Subject: add menu items for running the firmware and for quitting. --- src/frontend/FrontendUtil.h | 3 +++ src/frontend/Util_ROM.cpp | 16 ++++++++++++++++ src/frontend/qt_sdl/main.cpp | 44 +++++++++++++++++++++++++++++++++++++++++--- src/frontend/qt_sdl/main.h | 9 +++++++++ 4 files changed, 69 insertions(+), 3 deletions(-) (limited to 'src/frontend/Util_ROM.cpp') diff --git a/src/frontend/FrontendUtil.h b/src/frontend/FrontendUtil.h index 91f3cdd..eb4cb38 100644 --- a/src/frontend/FrontendUtil.h +++ b/src/frontend/FrontendUtil.h @@ -40,6 +40,9 @@ extern bool SavestateLoaded; // initialize the ROM handling utility void Init_ROM(); +// load the BIOS/firmware and boot from it +bool LoadBIOS(); + // load a ROM file to the specified cart slot // note: loading a ROM to the NDS slot resets emulation bool LoadROM(const char* file, int slot); diff --git a/src/frontend/Util_ROM.cpp b/src/frontend/Util_ROM.cpp index ffee69a..cf40a78 100644 --- a/src/frontend/Util_ROM.cpp +++ b/src/frontend/Util_ROM.cpp @@ -57,6 +57,22 @@ void SetupSRAMPath(int slot) strncpy(SRAMPath[slot] + strlen(ROMPath[slot]) - 3, "sav", 3); } +bool LoadBIOS() +{ + // TODO: + // original code in the libui frontend called NDS::LoadGBAROM() if needed + // should this be carried over here? + // is that behavior consistent with that of LoadROM() below? + + ROMPath[ROMSlot_NDS][0] = '\0'; + SRAMPath[ROMSlot_NDS][0] = '\0'; + + NDS::LoadBIOS(); + + // TODO: error reporting? + return true; +} + bool LoadROM(const char* file, int slot) { char oldpath[1024]; diff --git a/src/frontend/qt_sdl/main.cpp b/src/frontend/qt_sdl/main.cpp index e9b9122..cadcec9 100644 --- a/src/frontend/qt_sdl/main.cpp +++ b/src/frontend/qt_sdl/main.cpp @@ -394,10 +394,17 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent) QMenuBar* menubar = new QMenuBar(); { QMenu* menu = menubar->addMenu("File"); - QAction* act; - act = menu->addAction("Open file..."); - connect(act, &QAction::triggered, this, &MainWindow::onOpenFile); + actOpenROM = menu->addAction("Open file..."); + connect(actOpenROM, &QAction::triggered, this, &MainWindow::onOpenFile); + + actBootFirmware = menu->addAction("Launch DS menu"); + connect(actBootFirmware, &QAction::triggered, this, &MainWindow::onBootFirmware); + + menu->addSeparator(); + + actQuit = menu->addAction("Quit"); + connect(actQuit, &QAction::triggered, this, &MainWindow::onQuit); } setMenuBar(menubar); @@ -411,6 +418,12 @@ MainWindow::~MainWindow() } +void MainWindow::keyPressEvent(QKeyEvent* event) +{ + printf("key press. %d %d %08X %08X\n", event->key(), event->nativeScanCode(), event->modifiers(), event->nativeModifiers()); +} + + void MainWindow::onOpenFile() { emuThread->emuPause(true); @@ -465,6 +478,31 @@ void MainWindow::onOpenFile() } } +void MainWindow::onBootFirmware() +{ + // TODO: ensure the firmware is actually bootable!! + // TODO: check the whole GBA cart shito + + emuThread->emuPause(true); + + bool res = Frontend::LoadBIOS(); + if (!res) + { + // TODO! + + emuThread->emuUnpause(); + } + else + { + emuThread->emuRun(); + } +} + +void MainWindow::onQuit() +{ + QApplication::quit(); +} + void MainWindow::onTitleUpdate(QString title) { diff --git a/src/frontend/qt_sdl/main.h b/src/frontend/qt_sdl/main.h index a1093fe..9ccbddd 100644 --- a/src/frontend/qt_sdl/main.h +++ b/src/frontend/qt_sdl/main.h @@ -75,13 +75,22 @@ public: explicit MainWindow(QWidget* parent = nullptr); ~MainWindow(); +protected: + void keyPressEvent(QKeyEvent* event) override; + private slots: void onOpenFile(); + void onBootFirmware(); + void onQuit(); void onTitleUpdate(QString title); private: MainWindowPanel* panel; + + QAction* actOpenROM; + QAction* actBootFirmware; + QAction* actQuit; }; #endif // MAIN_H -- cgit v1.2.3 From 5fbad464c27fd5290c837d78a72378215ee8e77f Mon Sep 17 00:00:00 2001 From: Arisotura Date: Wed, 29 Apr 2020 00:50:23 +0200 Subject: hook up savestate shito --- src/frontend/FrontendUtil.h | 2 +- src/frontend/Util_ROM.cpp | 2 + src/frontend/qt_sdl/main.cpp | 141 ++++++++++++++++++++++++++++++++++++++++++- src/frontend/qt_sdl/main.h | 6 ++ 4 files changed, 149 insertions(+), 2 deletions(-) (limited to 'src/frontend/Util_ROM.cpp') diff --git a/src/frontend/FrontendUtil.h b/src/frontend/FrontendUtil.h index eb4cb38..d9f5c58 100644 --- a/src/frontend/FrontendUtil.h +++ b/src/frontend/FrontendUtil.h @@ -47,7 +47,7 @@ bool LoadBIOS(); // note: loading a ROM to the NDS slot resets emulation bool LoadROM(const char* file, int slot); -// get the filename associated with the given savestate slot +// get the filename associated with the given savestate slot (1-8) void GetSavestateName(int slot, char* filename, int len); // determine whether the given savestate slot does contain a savestate diff --git a/src/frontend/Util_ROM.cpp b/src/frontend/Util_ROM.cpp index cf40a78..19c8eb9 100644 --- a/src/frontend/Util_ROM.cpp +++ b/src/frontend/Util_ROM.cpp @@ -69,6 +69,8 @@ bool LoadBIOS() NDS::LoadBIOS(); + SavestateLoaded = false; + // TODO: error reporting? return true; } diff --git a/src/frontend/qt_sdl/main.cpp b/src/frontend/qt_sdl/main.cpp index af4fd4b..a6a1423 100644 --- a/src/frontend/qt_sdl/main.cpp +++ b/src/frontend/qt_sdl/main.cpp @@ -395,7 +395,7 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent) { QMenu* menu = menubar->addMenu("File"); - actOpenROM = menu->addAction("Open file..."); + actOpenROM = menu->addAction("Open ROM..."); connect(actOpenROM, &QAction::triggered, this, &MainWindow::onOpenFile); //actBootFirmware = menu->addAction("Launch DS menu"); @@ -404,6 +404,49 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent) menu->addSeparator(); + { + QMenu* submenu = menu->addMenu("Save state"); + + for (int i = 1; i < 9; i++) + { + char title[16]; + sprintf(title, "%d", i); + actSaveState[i] = submenu->addAction(title); + actSaveState[i]->setShortcut(QKeySequence(Qt::ShiftModifier | (Qt::Key_F1+i-1))); + actSaveState[i]->setData(QVariant(i)); + connect(actSaveState[i], &QAction::triggered, this, &MainWindow::onSaveState); + } + + actSaveState[0] = submenu->addAction("File..."); + actSaveState[0]->setShortcut(QKeySequence(Qt::ShiftModifier | Qt::Key_F9)); + actSaveState[0]->setData(QVariant(0)); + connect(actSaveState[0], &QAction::triggered, this, &MainWindow::onSaveState); + } + { + QMenu* submenu = menu->addMenu("Load state"); + + for (int i = 1; i < 9; i++) + { + char title[16]; + sprintf(title, "%d", i); + actLoadState[i] = submenu->addAction(title); + actLoadState[i]->setShortcut(QKeySequence(Qt::Key_F1+i-1)); + actLoadState[i]->setData(QVariant(i)); + connect(actLoadState[i], &QAction::triggered, this, &MainWindow::onLoadState); + } + + actLoadState[0] = submenu->addAction("File..."); + actLoadState[0]->setShortcut(QKeySequence(Qt::Key_F9)); + actLoadState[0]->setData(QVariant(0)); + connect(actLoadState[0], &QAction::triggered, this, &MainWindow::onLoadState); + } + + actUndoStateLoad = menu->addAction("Undo state load"); + actUndoStateLoad->setShortcut(QKeySequence(Qt::Key_F12)); + connect(actUndoStateLoad, &QAction::triggered, this, &MainWindow::onUndoStateLoad); + + menu->addSeparator(); + actQuit = menu->addAction("Quit"); connect(actQuit, &QAction::triggered, this, &MainWindow::onQuit); } @@ -499,6 +542,102 @@ void MainWindow::onBootFirmware() } } +void MainWindow::onSaveState() +{ + int slot = ((QAction*)sender())->data().toInt(); + + emuThread->emuPause(true); + + char filename[1024]; + if (slot > 0) + { + Frontend::GetSavestateName(slot, filename, 1024); + } + else + { + // TODO: specific 'last directory' for savestate files? + QString qfilename = QFileDialog::getSaveFileName(this, + "Save state", + Config::LastROMFolder, + "melonDS savestates (*.mln);;Any file (*.*)"); + if (qfilename.isEmpty()) + { + emuThread->emuUnpause(); + return; + } + + strncpy(filename, qfilename.toStdString().c_str(), 1023); filename[1023] = '\0'; + } + + if (Frontend::SaveState(filename)) + { + // TODO: OSD message + } + else + { + // TODO: OSD error message? + } + + emuThread->emuUnpause(); +} + +void MainWindow::onLoadState() +{ + int slot = ((QAction*)sender())->data().toInt(); + + emuThread->emuPause(true); + + char filename[1024]; + if (slot > 0) + { + Frontend::GetSavestateName(slot, filename, 1024); + } + else + { + // TODO: specific 'last directory' for savestate files? + QString qfilename = QFileDialog::getOpenFileName(this, + "Load state", + Config::LastROMFolder, + "melonDS savestates (*.ml*);;Any file (*.*)"); + if (qfilename.isEmpty()) + { + emuThread->emuUnpause(); + return; + } + + strncpy(filename, qfilename.toStdString().c_str(), 1023); filename[1023] = '\0'; + } + + if (!Platform::FileExists(filename)) + { + /*char msg[64]; + if (slot > 0) sprintf(msg, "State slot %d is empty", slot); + else sprintf(msg, "State file does not exist"); + OSD::AddMessage(0xFFA0A0, msg);*/ + + emuThread->emuUnpause(); + return; + } + + if (Frontend::LoadState(filename)) + { + // TODO: OSD message + } + else + { + // TODO: OSD error message? + } + + emuThread->emuUnpause(); +} + +void MainWindow::onUndoStateLoad() +{ + emuThread->emuPause(true); + Frontend::UndoStateLoad(); + emuThread->emuUnpause(); +} + void MainWindow::onQuit() { QApplication::quit(); diff --git a/src/frontend/qt_sdl/main.h b/src/frontend/qt_sdl/main.h index 9ccbddd..8694838 100644 --- a/src/frontend/qt_sdl/main.h +++ b/src/frontend/qt_sdl/main.h @@ -81,6 +81,9 @@ protected: private slots: void onOpenFile(); void onBootFirmware(); + void onSaveState(); + void onLoadState(); + void onUndoStateLoad(); void onQuit(); void onTitleUpdate(QString title); @@ -90,6 +93,9 @@ private: QAction* actOpenROM; QAction* actBootFirmware; + QAction* actSaveState[9]; + QAction* actLoadState[9]; + QAction* actUndoStateLoad; QAction* actQuit; }; -- cgit v1.2.3 From c5c9434ac9abaa0ae9c3125ee6e8bc4653846ebd Mon Sep 17 00:00:00 2001 From: Arisotura Date: Sun, 17 May 2020 05:42:09 +0200 Subject: verify BIOS and firmware before booting games/firmware --- src/NDS.cpp | 2 +- src/frontend/FrontendUtil.h | 22 +++++++++- src/frontend/Util_ROM.cpp | 100 +++++++++++++++++++++++++++++++++++++++---- src/frontend/qt_sdl/main.cpp | 41 +++++++++++++++--- src/frontend/qt_sdl/main.h | 2 + 5 files changed, 149 insertions(+), 18 deletions(-) (limited to 'src/frontend/Util_ROM.cpp') diff --git a/src/NDS.cpp b/src/NDS.cpp index 1d425a8..745ed28 100644 --- a/src/NDS.cpp +++ b/src/NDS.cpp @@ -587,7 +587,7 @@ bool DoSavestate_Scheduler(Savestate* file) } 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; } } diff --git a/src/frontend/FrontendUtil.h b/src/frontend/FrontendUtil.h index 32f28d1..f4f6850 100644 --- a/src/frontend/FrontendUtil.h +++ b/src/frontend/FrontendUtil.h @@ -32,6 +32,24 @@ enum 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 SRAMPath[ROMSlot_MAX][1024]; extern bool SavestateLoaded; @@ -41,11 +59,11 @@ extern bool SavestateLoaded; void Init_ROM(); // load the BIOS/firmware and boot from it -bool LoadBIOS(); +int LoadBIOS(); // load a ROM file to the specified cart slot // 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) void GetSavestateName(int slot, char* filename, int len); diff --git a/src/frontend/Util_ROM.cpp b/src/frontend/Util_ROM.cpp index 19c8eb9..3200de4 100644 --- a/src/frontend/Util_ROM.cpp +++ b/src/frontend/Util_ROM.cpp @@ -57,8 +57,77 @@ void SetupSRAMPath(int slot) 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: // original code in the libui frontend called NDS::LoadGBAROM() if needed // should this be carried over here? @@ -71,12 +140,26 @@ bool LoadBIOS() SavestateLoaded = false; - // TODO: error reporting? - return true; + return Load_OK; } -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 oldsram[1024]; strncpy(oldpath, ROMPath[slot], 1024); @@ -88,28 +171,29 @@ bool LoadROM(const char* file, int slot) SetupSRAMPath(0); 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; // 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]); strncpy(PrevSRAMPath[slot], SRAMPath[slot], 1024); // safety - return true; + return Load_OK; } else if (slot == ROMSlot_GBA && NDS::LoadGBAROM(ROMPath[slot], SRAMPath[slot])) { SavestateLoaded = false; strncpy(PrevSRAMPath[slot], SRAMPath[slot], 1024); // safety - return true; + return Load_OK; } else { strncpy(ROMPath[slot], oldpath, 1024); strncpy(SRAMPath[slot], oldsram, 1024); - return false; + return Load_ROMLoadError; } } diff --git a/src/frontend/qt_sdl/main.cpp b/src/frontend/qt_sdl/main.cpp index 8b97320..ec4b04b 100644 --- a/src/frontend/qt_sdl/main.cpp +++ b/src/frontend/qt_sdl/main.cpp @@ -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() { emuThread->emuPause(true); @@ -584,6 +605,11 @@ void MainWindow::onOpenFile() return; } + // TODO: validate the input file!! + // * check that it is a proper ROM + // * ensure the binary offsets are sane + // * etc + // this shit is stupid char file[1024]; strncpy(file, filename.toStdString().c_str(), 1023); file[1023] = '\0'; @@ -594,7 +620,7 @@ void MainWindow::onOpenFile() Config::LastROMFolder[pos] = '\0'; char* ext = &file[strlen(file)-3]; - int slot; bool res; + int slot; int res; if (!strcasecmp(ext, "gba")) { slot = 1; @@ -606,11 +632,11 @@ void MainWindow::onOpenFile() res = Frontend::LoadROM(file, Frontend::ROMSlot_NDS); } - if (!res) + if (res != Frontend::Load_OK) { QMessageBox::critical(this, "melonDS", - "Failed to load the ROM.\n\nMake sure the file is accessible and isn't used by another application."); + loadErrorStr(res)); emuThread->emuUnpause(); } else if (slot == 1) @@ -631,11 +657,12 @@ void MainWindow::onBootFirmware() emuThread->emuPause(true); - bool res = Frontend::LoadBIOS(); - if (!res) + int res = Frontend::LoadBIOS(); + if (res != Frontend::Load_OK) { - // TODO! - + QMessageBox::critical(this, + "melonDS", + loadErrorStr(res)); emuThread->emuUnpause(); } else diff --git a/src/frontend/qt_sdl/main.h b/src/frontend/qt_sdl/main.h index bb5e903..ee0094f 100644 --- a/src/frontend/qt_sdl/main.h +++ b/src/frontend/qt_sdl/main.h @@ -110,6 +110,8 @@ private slots: void onOpenEmuSettings(); private: + QString loadErrorStr(int error); + MainWindowPanel* panel; QAction* actOpenROM; -- cgit v1.2.3 From 2ebb21ce3bcf1a445dce7b13f64e44d6098a3acd Mon Sep 17 00:00:00 2001 From: Arisotura Date: Wed, 20 May 2020 22:22:22 +0200 Subject: hook up pause and reset, w/ relevant hotkeys --- src/frontend/FrontendUtil.h | 3 ++ src/frontend/Util_ROM.cpp | 47 +++++++++++++++++++++- src/frontend/qt_sdl/main.cpp | 93 +++++++++++++++++++++++--------------------- src/frontend/qt_sdl/main.h | 10 +++-- 4 files changed, 104 insertions(+), 49 deletions(-) (limited to 'src/frontend/Util_ROM.cpp') diff --git a/src/frontend/FrontendUtil.h b/src/frontend/FrontendUtil.h index f4f6850..d838b63 100644 --- a/src/frontend/FrontendUtil.h +++ b/src/frontend/FrontendUtil.h @@ -65,6 +65,9 @@ int LoadBIOS(); // note: loading a ROM to the NDS slot resets emulation int LoadROM(const char* file, int slot); +// reset execution of the current ROM +int Reset(); + // get the filename associated with the given savestate slot (1-8) void GetSavestateName(int slot, char* filename, int len); diff --git a/src/frontend/Util_ROM.cpp b/src/frontend/Util_ROM.cpp index 3200de4..e13eb2c 100644 --- a/src/frontend/Util_ROM.cpp +++ b/src/frontend/Util_ROM.cpp @@ -50,6 +50,11 @@ void Init_ROM() memset(PrevSRAMPath[ROMSlot_GBA], 0, 1024); } +// TODO: currently, when failing to load a ROM for whatever reason, we attempt +// to revert to the previous state and resume execution; this may not be a very +// good thing, depending on what state the core was left in. +// should we do a better state revert (via the savestate system)? completely stop? + void SetupSRAMPath(int slot) { strncpy(SRAMPath[slot], ROMPath[slot], 1023); @@ -184,7 +189,7 @@ int LoadROM(const char* file, int slot) } else if (slot == ROMSlot_GBA && NDS::LoadGBAROM(ROMPath[slot], SRAMPath[slot])) { - SavestateLoaded = false; + SavestateLoaded = false; // checkme?? strncpy(PrevSRAMPath[slot], SRAMPath[slot], 1024); // safety return Load_OK; @@ -197,6 +202,46 @@ int LoadROM(const char* file, int slot) } } +int Reset() +{ + 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; + } + + SavestateLoaded = false; + + if (ROMPath[ROMSlot_NDS][0] == '\0') + { + NDS::LoadBIOS(); + } + else + { + SetupSRAMPath(0); + if (!NDS::LoadROM(ROMPath[ROMSlot_NDS], SRAMPath[ROMSlot_NDS], directboot)) + return Load_ROMLoadError; + } + + if (ROMPath[ROMSlot_GBA][0] != '\0') + { + SetupSRAMPath(1); + if (!NDS::LoadGBAROM(ROMPath[ROMSlot_GBA], SRAMPath[ROMSlot_GBA])) + return Load_ROMLoadError; + } + + return Load_OK; +} + // SAVESTATE TODO // * configurable paths. not everyone wants their ROM directory to be polluted, I guess. diff --git a/src/frontend/qt_sdl/main.cpp b/src/frontend/qt_sdl/main.cpp index 35eac70..a73362d 100644 --- a/src/frontend/qt_sdl/main.cpp +++ b/src/frontend/qt_sdl/main.cpp @@ -113,6 +113,8 @@ EmuThread::EmuThread(QObject* parent) : QThread(parent) connect(this, SIGNAL(windowTitleChange(QString)), mainWindow, SLOT(onTitleUpdate(QString))); connect(this, SIGNAL(windowEmuStart()), mainWindow, SLOT(onEmuStart())); connect(this, SIGNAL(windowEmuStop()), mainWindow, SLOT(onEmuStop())); + connect(this, SIGNAL(windowEmuPause()), mainWindow->actPause, SLOT(trigger())); + connect(this, SIGNAL(windowEmuReset()), mainWindow->actReset, SLOT(trigger())); emit windowEmuStop(); } @@ -152,14 +154,10 @@ void EmuThread::run() { Input::Process(); - /*if (Input::HotkeyPressed(HK_FastForwardToggle)) - { - Config::LimitFPS = !Config::LimitFPS; - // TODO: reflect in UI! - }*/ + if (Input::HotkeyPressed(HK_FastForwardToggle)) emit windowLimitFPSChange(); - //if (Input::HotkeyPressed(HK_Pause)) uiQueueMain(TogglePause, NULL); - //if (Input::HotkeyPressed(HK_Reset)) uiQueueMain(Reset, NULL); + if (Input::HotkeyPressed(HK_Pause)) emit windowEmuPause(); + if (Input::HotkeyPressed(HK_Reset)) emit windowEmuReset(); if (GBACart::CartInserted && GBACart::HasSolarSensor) { @@ -318,18 +316,15 @@ void EmuThread::run() lastmeasuretick = lasttick; fpslimitcount = 0; - if (EmuRunning == 2) + /*if (Screen_UseGL) { - /*if (Screen_UseGL) - { - uiGLBegin(GLContext); - uiGLMakeContextCurrent(GLContext); - GLScreen_DrawScreen(); - uiGLEnd(GLContext); - } - uiAreaQueueRedrawAll(MainDrawArea);*/ - mainWindow->update(); + uiGLBegin(GLContext); + uiGLMakeContextCurrent(GLContext); + GLScreen_DrawScreen(); + uiGLEnd(GLContext); } + uiAreaQueueRedrawAll(MainDrawArea);*/ + mainWindow->update(); //if (Screen_UseGL) uiGLMakeContextCurrent(NULL); @@ -338,7 +333,7 @@ void EmuThread::run() sprintf(melontitle, "melonDS " MELONDS_VERSION); changeWindowTitle(melontitle); - SDL_Delay(100); + SDL_Delay(75); } } @@ -375,12 +370,11 @@ void EmuThread::emuRun() if (audioDevice) SDL_PauseAudioDevice(audioDevice, 0); } -void EmuThread::emuPause(bool refresh) +void EmuThread::emuPause() { - int status = refresh ? 2:3; PrevEmuStatus = EmuRunning; - EmuRunning = status; - while (EmuStatus != status); + EmuRunning = 2; + while (EmuStatus != 2); //emit windowEmuPause(); if (audioDevice) SDL_PauseAudioDevice(audioDevice, 1); @@ -774,7 +768,7 @@ void MainWindow::dropEvent(QDropEvent* event) QList urls = event->mimeData()->urls(); if (urls.count() > 1) return; // not handling more than one file at once - emuThread->emuPause(true); + emuThread->emuPause(); QString filename = urls.at(0).toLocalFile(); QString ext = filename.right(3); @@ -836,7 +830,7 @@ QString MainWindow::loadErrorStr(int error) void MainWindow::onOpenFile() { - emuThread->emuPause(true); + emuThread->emuPause(); QString filename = QFileDialog::getOpenFileName(this, "Open ROM", @@ -897,7 +891,7 @@ void MainWindow::onBootFirmware() { // TODO: check the whole GBA cart shito - emuThread->emuPause(true); + emuThread->emuPause(); int res = Frontend::LoadBIOS(); if (res != Frontend::Load_OK) @@ -917,7 +911,7 @@ void MainWindow::onSaveState() { int slot = ((QAction*)sender())->data().toInt(); - emuThread->emuPause(true); + emuThread->emuPause(); char filename[1024]; if (slot > 0) @@ -958,7 +952,7 @@ void MainWindow::onLoadState() { int slot = ((QAction*)sender())->data().toInt(); - emuThread->emuPause(true); + emuThread->emuPause(); char filename[1024]; if (slot > 0) @@ -1006,7 +1000,7 @@ void MainWindow::onLoadState() void MainWindow::onUndoStateLoad() { - emuThread->emuPause(true); + emuThread->emuPause(); Frontend::UndoStateLoad(); emuThread->emuUnpause(); } @@ -1019,9 +1013,11 @@ void MainWindow::onQuit() void MainWindow::onPause(bool checked) { - if (emuThread->emuIsRunning()) + if (!RunningSomething) return; + + if (checked) { - emuThread->emuPause(true); + emuThread->emuPause(); } else { @@ -1031,7 +1027,26 @@ void MainWindow::onPause(bool checked) void MainWindow::onReset() { - // + if (!RunningSomething) return; + + emuThread->emuPause(); + + actUndoStateLoad->setEnabled(false); + + int res = Frontend::Reset(); + if (res != Frontend::Load_OK) + { + QMessageBox::critical(this, + "melonDS", + loadErrorStr(res)); + emuThread->emuUnpause(); + } + else + { + // OSD::AddMessage(0, "Reset"); + + emuThread->emuRun(); + } } void MainWindow::onStop() @@ -1047,7 +1062,7 @@ void MainWindow::onOpenEmuSettings() void MainWindow::onOpenInputConfig() { - emuThread->emuPause(true); + emuThread->emuPause(); InputConfigDialog* dlg = InputConfigDialog::openDlg(this); connect(dlg, &InputConfigDialog::finished, this, &MainWindow::onInputConfigFinished); @@ -1143,7 +1158,7 @@ void MainWindow::onEmuStart() } actSaveState[0]->setEnabled(true); actLoadState[0]->setEnabled(true); - actUndoStateLoad->setEnabled(true); + actUndoStateLoad->setEnabled(false); actPause->setEnabled(true); actPause->setChecked(false); @@ -1165,16 +1180,6 @@ void MainWindow::onEmuStop() actStop->setEnabled(false); } -void MainWindow::onEmuPause() -{ - // -} - -void MainWindow::onEmuUnpause() -{ - // -} - int main(int argc, char** argv) @@ -1281,7 +1286,7 @@ int main(int argc, char** argv) emuThread = new EmuThread(); emuThread->start(); - emuThread->emuPause(true); + emuThread->emuPause(); if (argc > 1) { diff --git a/src/frontend/qt_sdl/main.h b/src/frontend/qt_sdl/main.h index b478f4e..22f045f 100644 --- a/src/frontend/qt_sdl/main.h +++ b/src/frontend/qt_sdl/main.h @@ -38,7 +38,7 @@ public: // to be called from the UI thread void emuRun(); - void emuPause(bool refresh); + void emuPause(); void emuUnpause(); void emuStop(); @@ -49,7 +49,10 @@ signals: void windowEmuStart(); void windowEmuStop(); - void windowPauseToggle(); + void windowEmuPause(); + void windowEmuReset(); + + void windowLimitFPSChange(); private: volatile int EmuStatus; @@ -130,14 +133,13 @@ private slots: void onEmuStart(); void onEmuStop(); - void onEmuPause(); - void onEmuUnpause(); private: QString loadErrorStr(int error); MainWindowPanel* panel; +public: QAction* actOpenROM; QAction* actBootFirmware; QAction* actSaveState[9]; -- cgit v1.2.3 From a9b275bc253510d77b8b6fcd80e6d24b56bc8680 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Wed, 20 May 2020 22:58:04 +0200 Subject: reimplement Stop --- src/SPU.cpp | 3 +++ src/frontend/FrontendUtil.h | 4 ++++ src/frontend/Util_ROM.cpp | 14 ++++++++++++++ src/frontend/qt_sdl/Platform.cpp | 4 ++-- src/frontend/qt_sdl/main.cpp | 37 +++++++++++++++++++++++++++++++------ 5 files changed, 54 insertions(+), 8 deletions(-) (limited to 'src/frontend/Util_ROM.cpp') diff --git a/src/SPU.cpp b/src/SPU.cpp index 710533e..1ebfd4c 100644 --- a/src/SPU.cpp +++ b/src/SPU.cpp @@ -116,6 +116,9 @@ void Reset() void Stop() { memset(OutputBuffer, 0, 2*OutputBufferSize*2); + + OutputReadOffset = 0; + OutputWriteOffset = 0; } void DoSavestate(Savestate* file) diff --git a/src/frontend/FrontendUtil.h b/src/frontend/FrontendUtil.h index d838b63..faa29de 100644 --- a/src/frontend/FrontendUtil.h +++ b/src/frontend/FrontendUtil.h @@ -65,6 +65,10 @@ int LoadBIOS(); // note: loading a ROM to the NDS slot resets emulation int LoadROM(const char* file, int slot); +// unload the ROM loaded in the specified cart slot +// simulating ejection of the cartridge +void UnloadROM(int slot); + // reset execution of the current ROM int Reset(); diff --git a/src/frontend/Util_ROM.cpp b/src/frontend/Util_ROM.cpp index e13eb2c..ec3186a 100644 --- a/src/frontend/Util_ROM.cpp +++ b/src/frontend/Util_ROM.cpp @@ -202,6 +202,20 @@ int LoadROM(const char* file, int slot) } } +void UnloadROM(int slot) +{ + if (slot == ROMSlot_NDS) + { + // TODO! + } + else if (slot == ROMSlot_GBA) + { + GBACart::Eject(); + } + + ROMPath[slot][0] = '\0'; +} + int Reset() { int res; diff --git a/src/frontend/qt_sdl/Platform.cpp b/src/frontend/qt_sdl/Platform.cpp index 6a5b466..dd838d7 100644 --- a/src/frontend/qt_sdl/Platform.cpp +++ b/src/frontend/qt_sdl/Platform.cpp @@ -55,7 +55,7 @@ char* EmuDirectory; -void Stop(bool internal); +void emuStop(); namespace Platform @@ -133,7 +133,7 @@ void DeInit() void StopEmu() { - //Stop(true); + emuStop(); } diff --git a/src/frontend/qt_sdl/main.cpp b/src/frontend/qt_sdl/main.cpp index a73362d..67272af 100644 --- a/src/frontend/qt_sdl/main.cpp +++ b/src/frontend/qt_sdl/main.cpp @@ -115,8 +115,6 @@ EmuThread::EmuThread(QObject* parent) : QThread(parent) connect(this, SIGNAL(windowEmuStop()), mainWindow, SLOT(onEmuStop())); connect(this, SIGNAL(windowEmuPause()), mainWindow->actPause, SLOT(trigger())); connect(this, SIGNAL(windowEmuReset()), mainWindow->actReset, SLOT(trigger())); - - emit windowEmuStop(); } void EmuThread::run() @@ -140,7 +138,6 @@ void EmuThread::run() } Input::Init(); - /*Touching = false;*/ u32 nframes = 0; u32 starttick = SDL_GetTicks(); @@ -376,7 +373,6 @@ void EmuThread::emuPause() EmuRunning = 2; while (EmuStatus != 2); - //emit windowEmuPause(); if (audioDevice) SDL_PauseAudioDevice(audioDevice, 1); } @@ -384,7 +380,6 @@ void EmuThread::emuUnpause() { EmuRunning = PrevEmuStatus; - //emit windowEmuUnpause(); if (audioDevice) SDL_PauseAudioDevice(audioDevice, 0); } @@ -703,6 +698,18 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent) panel->setMinimumSize(256, 384); + for (int i = 0; i < 9; i++) + { + actSaveState[i]->setEnabled(false); + actLoadState[i]->setEnabled(false); + } + actUndoStateLoad->setEnabled(false); + + actPause->setEnabled(false); + actReset->setEnabled(false); + actStop->setEnabled(false); + + actSavestateSRAMReloc->setChecked(Config::SavestateRelocSRAM != 0); actScreenRotation[Config::ScreenRotation]->setChecked(true); @@ -1051,7 +1058,10 @@ void MainWindow::onReset() void MainWindow::onStop() { - // + if (!RunningSomething) return; + + emuThread->emuPause(); + NDS::Stop(); } @@ -1168,6 +1178,8 @@ void MainWindow::onEmuStart() void MainWindow::onEmuStop() { + emuThread->emuPause(); + for (int i = 0; i < 9; i++) { actSaveState[i]->setEnabled(false); @@ -1181,6 +1193,19 @@ void MainWindow::onEmuStop() } +void emuStop() +{ + RunningSomething = false; + + Frontend::UnloadROM(Frontend::ROMSlot_NDS); + Frontend::UnloadROM(Frontend::ROMSlot_GBA); + + emit emuThread->windowEmuStop(); + + //OSD::AddMessage(0xFFC040, "Shutdown"); +} + + int main(int argc, char** argv) { -- cgit v1.2.3 From a2004785a4d49f02f8257a38489eb57a29ce4e91 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Thu, 28 May 2020 18:22:02 +0200 Subject: re-add all old OSD messages --- src/frontend/Util_ROM.cpp | 6 ------ src/frontend/qt_sdl/main.cpp | 41 +++++++++++++++++++++++++---------------- 2 files changed, 25 insertions(+), 22 deletions(-) (limited to 'src/frontend/Util_ROM.cpp') diff --git a/src/frontend/Util_ROM.cpp b/src/frontend/Util_ROM.cpp index ec3186a..3f64b9d 100644 --- a/src/frontend/Util_ROM.cpp +++ b/src/frontend/Util_ROM.cpp @@ -384,10 +384,6 @@ bool SaveState(const char* filename) } } - /*char msg[64]; - if (slot > 0) sprintf(msg, "State saved to slot %d", slot); - else sprintf(msg, "State saved to file"); - OSD::AddMessage(0, msg);*/ return true; } @@ -407,8 +403,6 @@ void UndoStateLoad() strncpy(SRAMPath[ROMSlot_NDS], PrevSRAMPath[ROMSlot_NDS], 1024); NDS::RelocateSave(SRAMPath[ROMSlot_NDS], false); } - - //OSD::AddMessage(0, "State load undone"); } } diff --git a/src/frontend/qt_sdl/main.cpp b/src/frontend/qt_sdl/main.cpp index 78f64f6..bea33b0 100644 --- a/src/frontend/qt_sdl/main.cpp +++ b/src/frontend/qt_sdl/main.cpp @@ -364,16 +364,16 @@ void EmuThread::run() if (Input::HotkeyPressed(HK_SolarSensorDecrease)) { if (GBACart_SolarSensor::LightLevel > 0) GBACart_SolarSensor::LightLevel--; - //char msg[64]; - //sprintf(msg, "Solar sensor level set to %d", GBACart_SolarSensor::LightLevel); - //OSD::AddMessage(0, msg); + char msg[64]; + sprintf(msg, "Solar sensor level set to %d", GBACart_SolarSensor::LightLevel); + OSD::AddMessage(0, msg); } if (Input::HotkeyPressed(HK_SolarSensorIncrease)) { if (GBACart_SolarSensor::LightLevel < 10) GBACart_SolarSensor::LightLevel++; - //char msg[64]; - //sprintf(msg, "Solar sensor level set to %d", GBACart_SolarSensor::LightLevel); - //OSD::AddMessage(0, msg); + char msg[64]; + sprintf(msg, "Solar sensor level set to %d", GBACart_SolarSensor::LightLevel); + OSD::AddMessage(0, msg); } } @@ -411,7 +411,7 @@ void EmuThread::run() { bool lid = !NDS::IsLidClosed(); NDS::SetLidClosed(lid); - //OSD::AddMessage(0, lid ? "Lid closed" : "Lid opened"); + OSD::AddMessage(0, lid ? "Lid closed" : "Lid opened"); } // microphone input @@ -1493,13 +1493,16 @@ void MainWindow::onSaveState() if (Frontend::SaveState(filename)) { - // TODO: OSD message + char msg[64]; + if (slot > 0) sprintf(msg, "State saved to slot %d", slot); + else sprintf(msg, "State saved to file"); + OSD::AddMessage(0, msg); actLoadState[slot]->setEnabled(true); } else { - // TODO: OSD error message? + OSD::AddMessage(0xFFA0A0, "State save failed"); } emuThread->emuUnpause(); @@ -1534,10 +1537,10 @@ void MainWindow::onLoadState() if (!Platform::FileExists(filename)) { - /*char msg[64]; + char msg[64]; if (slot > 0) sprintf(msg, "State slot %d is empty", slot); else sprintf(msg, "State file does not exist"); - OSD::AddMessage(0xFFA0A0, msg);*/ + OSD::AddMessage(0xFFA0A0, msg); emuThread->emuUnpause(); return; @@ -1545,11 +1548,14 @@ void MainWindow::onLoadState() if (Frontend::LoadState(filename)) { - // TODO: OSD message + char msg[64]; + if (slot > 0) sprintf(msg, "State loaded from slot %d", slot); + else sprintf(msg, "State loaded from file"); + OSD::AddMessage(0, msg); } else { - // TODO: OSD error message? + OSD::AddMessage(0xFFA0A0, "State load failed"); } emuThread->emuUnpause(); @@ -1560,6 +1566,8 @@ void MainWindow::onUndoStateLoad() emuThread->emuPause(); Frontend::UndoStateLoad(); emuThread->emuUnpause(); + + OSD::AddMessage(0, "State load undone"); } void MainWindow::onQuit() @@ -1575,10 +1583,12 @@ void MainWindow::onPause(bool checked) if (checked) { emuThread->emuPause(); + OSD::AddMessage(0, "Paused"); } else { emuThread->emuUnpause(); + OSD::AddMessage(0, "Resumed"); } } @@ -1600,8 +1610,7 @@ void MainWindow::onReset() } else { - // OSD::AddMessage(0, "Reset"); - + OSD::AddMessage(0, "Reset"); emuThread->emuRun(); } } @@ -1835,7 +1844,7 @@ void emuStop() emit emuThread->windowEmuStop(); - //OSD::AddMessage(0xFFC040, "Shutdown"); + OSD::AddMessage(0xFFC040, "Shutdown"); } -- cgit v1.2.3 From 8a15adb38bf5c141e41b1a5f9984ee363d64786f Mon Sep 17 00:00:00 2001 From: Arisotura Date: Sat, 30 May 2020 03:26:06 +0200 Subject: modern melonDSi HARK HARK HARK --- src/frontend/Util_ROM.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src/frontend/Util_ROM.cpp') diff --git a/src/frontend/Util_ROM.cpp b/src/frontend/Util_ROM.cpp index 3f64b9d..d410550 100644 --- a/src/frontend/Util_ROM.cpp +++ b/src/frontend/Util_ROM.cpp @@ -110,6 +110,7 @@ int VerifyDSFirmware() { // 128KB firmware, not bootable fclose(f); + return Load_OK; // FIXME!!!! return Load_FirmwareNotBootable; } else if (len != 0x40000 && len != 0x80000) -- cgit v1.2.3 From 43e045357f7d74eecff61b0c8af8068b31e963b3 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Mon, 1 Jun 2020 20:36:30 +0200 Subject: make it able to switch between DS and DSi modes --- src/ARM.cpp | 46 +++++++++ src/ARM.h | 43 ++++---- src/CP15.cpp | 30 ++---- src/DMA.cpp | 29 ++++-- src/DMA.h | 5 + src/DSi.cpp | 7 +- src/NDS.cpp | 54 +++++++--- src/NDS.h | 5 + src/NDSCart.cpp | 15 ++- src/SPI.cpp | 32 ++++-- src/SPU.cpp | 16 ++- src/SPU.h | 6 ++ src/frontend/FrontendUtil.h | 9 ++ src/frontend/Util_ROM.cpp | 163 +++++++++++++++++++++++++++--- src/frontend/qt_sdl/EmuSettingsDialog.cpp | 2 +- src/frontend/qt_sdl/main.cpp | 45 +++++++-- 16 files changed, 396 insertions(+), 111 deletions(-) (limited to 'src/frontend/Util_ROM.cpp') diff --git a/src/ARM.cpp b/src/ARM.cpp index 2d8c807..68cac59 100644 --- a/src/ARM.cpp +++ b/src/ARM.cpp @@ -18,6 +18,7 @@ #include #include "NDS.h" +#include "DSi.h" #include "ARM.h" #include "ARMInterpreter.h" #include "AREngine.h" @@ -101,10 +102,55 @@ void ARM::Reset() void ARMv5::Reset() { + if (NDS::ConsoleType == 1) + { + BusRead8 = DSi::ARM9Read8; + BusRead16 = DSi::ARM9Read16; + BusRead32 = DSi::ARM9Read32; + BusWrite8 = DSi::ARM9Write8; + BusWrite16 = DSi::ARM9Write16; + BusWrite32 = DSi::ARM9Write32; + GetMemRegion = DSi::ARM9GetMemRegion; + } + else + { + BusRead8 = NDS::ARM9Read8; + BusRead16 = NDS::ARM9Read16; + BusRead32 = NDS::ARM9Read32; + BusWrite8 = NDS::ARM9Write8; + BusWrite16 = NDS::ARM9Write16; + BusWrite32 = NDS::ARM9Write32; + GetMemRegion = NDS::ARM9GetMemRegion; + } + CP15Reset(); ARM::Reset(); } +void ARMv4::Reset() +{ + if (NDS::ConsoleType) + { + BusRead8 = DSi::ARM7Read8; + BusRead16 = DSi::ARM7Read16; + BusRead32 = DSi::ARM7Read32; + BusWrite8 = DSi::ARM7Write8; + BusWrite16 = DSi::ARM7Write16; + BusWrite32 = DSi::ARM7Write32; + } + else + { + BusRead8 = NDS::ARM7Read8; + BusRead16 = NDS::ARM7Read16; + BusRead32 = NDS::ARM7Read32; + BusWrite8 = NDS::ARM7Write8; + BusWrite16 = NDS::ARM7Write16; + BusWrite32 = NDS::ARM7Write32; + } + + ARM::Reset(); +} + void ARM::DoSavestate(Savestate* file) { diff --git a/src/ARM.h b/src/ARM.h index 95c41d4..e0832e2 100644 --- a/src/ARM.h +++ b/src/ARM.h @@ -23,7 +23,6 @@ #include "types.h" #include "NDS.h" -#include "DSi.h" #define ROR(x, n) (((x) >> (n)) | ((x) << (32-(n)))) @@ -133,6 +132,14 @@ public: NDS::MemRegion CodeMem; static u32 ConditionTable[16]; + +protected: + u8 (*BusRead8)(u32 addr); + u16 (*BusRead16)(u32 addr); + u32 (*BusRead32)(u32 addr); + void (*BusWrite8)(u32 addr, u8 val); + void (*BusWrite16)(u32 addr, u16 val); + void (*BusWrite32)(u32 addr, u32 val); }; class ARMv5 : public ARM @@ -260,6 +267,8 @@ public: s32 RegionCodeCycles; u8* CurICacheLine; + + bool (*GetMemRegion)(u32 addr, bool write, NDS::MemRegion* region); }; class ARMv4 : public ARM @@ -267,26 +276,25 @@ class ARMv4 : public ARM public: ARMv4(); + void Reset(); + void JumpTo(u32 addr, bool restorecpsr = false); void Execute(); u16 CodeRead16(u32 addr) { - //return NDS::ARM7Read16(addr); - return DSi::ARM7Read16(addr); + return BusRead16(addr); } u32 CodeRead32(u32 addr) { - //return NDS::ARM7Read32(addr); - return DSi::ARM7Read32(addr); + return BusRead32(addr); } void DataRead8(u32 addr, u32* val) { - *val = DSi::ARM7Read8(addr); - //*val = NDS::ARM7Read8(addr); + *val = BusRead8(addr); DataRegion = addr >> 24; DataCycles = NDS::ARM7MemTimings[DataRegion][0]; } @@ -295,8 +303,7 @@ public: { addr &= ~1; - *val = DSi::ARM7Read16(addr); - //*val = NDS::ARM7Read16(addr); + *val = BusRead16(addr); DataRegion = addr >> 24; DataCycles = NDS::ARM7MemTimings[DataRegion][0]; } @@ -305,8 +312,7 @@ public: { addr &= ~3; - *val = DSi::ARM7Read32(addr); - //*val = NDS::ARM7Read32(addr); + *val = BusRead32(addr); DataRegion = addr >> 24; DataCycles = NDS::ARM7MemTimings[DataRegion][2]; } @@ -315,15 +321,13 @@ public: { addr &= ~3; - *val = DSi::ARM7Read32(addr); - //*val = NDS::ARM7Read32(addr); + *val = BusRead32(addr); DataCycles += NDS::ARM7MemTimings[DataRegion][3]; } void DataWrite8(u32 addr, u8 val) { - DSi::ARM7Write8(addr, val); - //NDS::ARM7Write8(addr, val); + BusWrite8(addr, val); DataRegion = addr >> 24; DataCycles = NDS::ARM7MemTimings[DataRegion][0]; } @@ -332,8 +336,7 @@ public: { addr &= ~1; - DSi::ARM7Write16(addr, val); - //NDS::ARM7Write16(addr, val); + BusWrite16(addr, val); DataRegion = addr >> 24; DataCycles = NDS::ARM7MemTimings[DataRegion][0]; } @@ -342,8 +345,7 @@ public: { addr &= ~3; - DSi::ARM7Write32(addr, val); - //NDS::ARM7Write32(addr, val); + BusWrite32(addr, val); DataRegion = addr >> 24; DataCycles = NDS::ARM7MemTimings[DataRegion][2]; } @@ -352,8 +354,7 @@ public: { addr &= ~3; - DSi::ARM7Write32(addr, val); - //NDS::ARM7Write32(addr, val); + BusWrite32(addr, val); DataCycles += NDS::ARM7MemTimings[DataRegion][3]; } diff --git a/src/CP15.cpp b/src/CP15.cpp index b61cc45..d340b9e 100644 --- a/src/CP15.cpp +++ b/src/CP15.cpp @@ -720,8 +720,7 @@ u32 ARMv5::CodeRead32(u32 addr, bool branch) if (CodeMem.Mem) return *(u32*)&CodeMem.Mem[addr & CodeMem.Mask]; - //return NDS::ARM9Read32(addr); - return DSi::ARM9Read32(addr); + return BusRead32(addr); } @@ -740,8 +739,7 @@ void ARMv5::DataRead8(u32 addr, u32* val) return; } - *val = DSi::ARM9Read8(addr); - //*val = NDS::ARM9Read8(addr); + *val = BusRead8(addr); DataCycles = MemTimings[addr >> 12][1]; } @@ -762,8 +760,7 @@ void ARMv5::DataRead16(u32 addr, u32* val) return; } - *val = DSi::ARM9Read16(addr); - //*val = NDS::ARM9Read16(addr); + *val = BusRead16(addr); DataCycles = MemTimings[addr >> 12][1]; } @@ -784,8 +781,7 @@ void ARMv5::DataRead32(u32 addr, u32* val) return; } - *val = DSi::ARM9Read32(addr); - //*val = NDS::ARM9Read32(addr); + *val = BusRead32(addr); DataCycles = MemTimings[addr >> 12][2]; } @@ -806,8 +802,7 @@ void ARMv5::DataRead32S(u32 addr, u32* val) return; } - *val = DSi::ARM9Read32(addr); - //*val = NDS::ARM9Read32(addr); + *val = BusRead32(addr); DataCycles += MemTimings[addr >> 12][3]; } @@ -826,8 +821,7 @@ void ARMv5::DataWrite8(u32 addr, u8 val) return; } - DSi::ARM9Write8(addr, val); - //NDS::ARM9Write8(addr, val); + BusWrite8(addr, val); DataCycles = MemTimings[addr >> 12][1]; } @@ -848,8 +842,7 @@ void ARMv5::DataWrite16(u32 addr, u16 val) return; } - DSi::ARM9Write16(addr, val); - //NDS::ARM9Write16(addr, val); + BusWrite16(addr, val); DataCycles = MemTimings[addr >> 12][1]; } @@ -870,8 +863,7 @@ void ARMv5::DataWrite32(u32 addr, u32 val) return; } - DSi::ARM9Write32(addr, val); - //NDS::ARM9Write32(addr, val); + BusWrite32(addr, val); DataCycles = MemTimings[addr >> 12][2]; } @@ -892,8 +884,7 @@ void ARMv5::DataWrite32S(u32 addr, u32 val) return; } - DSi::ARM9Write32(addr, val); - //NDS::ARM9Write32(addr, val); + BusWrite32(addr, val); DataCycles += MemTimings[addr >> 12][3]; } @@ -906,7 +897,6 @@ void ARMv5::GetCodeMemRegion(u32 addr, NDS::MemRegion* region) return; }*/ - DSi::ARM9GetMemRegion(addr, false, &CodeMem); - //NDS::ARM9GetMemRegion(addr, false, &CodeMem); + GetMemRegion(addr, false, &CodeMem); } diff --git a/src/DMA.cpp b/src/DMA.cpp index 8e294fc..cd2df45 100644 --- a/src/DMA.cpp +++ b/src/DMA.cpp @@ -53,8 +53,6 @@ DMA::DMA(u32 cpu, u32 num) CountMask = 0x001FFFFF; else CountMask = (num==3 ? 0x0000FFFF : 0x00003FFF); - - Reset(); } DMA::~DMA() @@ -77,6 +75,21 @@ void DMA::Reset() Running = false; InProgress = false; + + if (NDS::ConsoleType == 1) + { + BusRead16 = (CPU==0) ? DSi::ARM9Read16 : DSi::ARM7Read16; + BusRead32 = (CPU==0) ? DSi::ARM9Read32 : DSi::ARM7Read32; + BusWrite16 = (CPU==0) ? DSi::ARM9Write16 : DSi::ARM7Write16; + BusWrite32 = (CPU==0) ? DSi::ARM9Write32 : DSi::ARM7Write32; + } + else + { + BusRead16 = (CPU==0) ? NDS::ARM9Read16 : NDS::ARM7Read16; + BusRead32 = (CPU==0) ? NDS::ARM9Read32 : NDS::ARM7Read32; + BusWrite16 = (CPU==0) ? NDS::ARM9Write16 : NDS::ARM7Write16; + BusWrite32 = (CPU==0) ? NDS::ARM9Write32 : NDS::ARM7Write32; + } } void DMA::DoSavestate(Savestate* file) @@ -227,8 +240,7 @@ void DMA::Run9() { NDS::ARM9Timestamp += (unitcycles << NDS::ARM9ClockShift); - //NDS::ARM9Write16(CurDstAddr, NDS::ARM9Read16(CurSrcAddr)); - DSi::ARM9Write16(CurDstAddr, DSi::ARM9Read16(CurSrcAddr)); + BusWrite16(CurDstAddr, BusRead16(CurSrcAddr)); CurSrcAddr += SrcAddrInc<<1; CurDstAddr += DstAddrInc<<1; @@ -264,8 +276,7 @@ void DMA::Run9() { NDS::ARM9Timestamp += (unitcycles << NDS::ARM9ClockShift); - //NDS::ARM9Write32(CurDstAddr, NDS::ARM9Read32(CurSrcAddr)); - DSi::ARM9Write32(CurDstAddr, DSi::ARM9Read32(CurSrcAddr)); + BusWrite32(CurDstAddr, BusRead32(CurSrcAddr)); CurSrcAddr += SrcAddrInc<<2; CurDstAddr += DstAddrInc<<2; @@ -341,8 +352,7 @@ void DMA::Run7() { NDS::ARM7Timestamp += unitcycles; - //NDS::ARM7Write16(CurDstAddr, NDS::ARM7Read16(CurSrcAddr)); - DSi::ARM7Write16(CurDstAddr, DSi::ARM7Read16(CurSrcAddr)); + BusWrite16(CurDstAddr, BusRead16(CurSrcAddr)); CurSrcAddr += SrcAddrInc<<1; CurDstAddr += DstAddrInc<<1; @@ -378,8 +388,7 @@ void DMA::Run7() { NDS::ARM7Timestamp += unitcycles; - //NDS::ARM7Write32(CurDstAddr, NDS::ARM7Read32(CurSrcAddr)); - DSi::ARM7Write32(CurDstAddr, DSi::ARM7Read32(CurSrcAddr)); + BusWrite32(CurDstAddr, BusRead32(CurSrcAddr)); CurSrcAddr += SrcAddrInc<<2; CurDstAddr += DstAddrInc<<2; diff --git a/src/DMA.h b/src/DMA.h index 2e7678c..0344fba 100644 --- a/src/DMA.h +++ b/src/DMA.h @@ -86,6 +86,11 @@ private: bool Stall; bool IsGXFIFODMA; + + u16 (*BusRead16)(u32 addr); + u32 (*BusRead32)(u32 addr); + void (*BusWrite16)(u32 addr, u16 val); + void (*BusWrite32)(u32 addr, u32 val); }; #endif diff --git a/src/DSi.cpp b/src/DSi.cpp index 58f39c2..520b269 100644 --- a/src/DSi.cpp +++ b/src/DSi.cpp @@ -18,6 +18,7 @@ #include #include +#include "Config.h" #include "NDS.h" #include "DSi.h" #include "ARM.h" @@ -221,7 +222,7 @@ bool LoadBIOS() memset(ARM9iBIOS, 0, 0x10000); memset(ARM7iBIOS, 0, 0x10000); - f = Platform::OpenLocalFile("bios9i.bin", "rb"); + f = Platform::OpenLocalFile(Config::DSiBIOS9Path, "rb"); if (!f) { printf("ARM9i BIOS not found\n"); @@ -238,7 +239,7 @@ bool LoadBIOS() fclose(f); } - f = Platform::OpenLocalFile("bios7i.bin", "rb"); + f = Platform::OpenLocalFile(Config::DSiBIOS7Path, "rb"); if (!f) { printf("ARM7i BIOS not found\n"); @@ -283,7 +284,7 @@ bool LoadNAND() memset(NWRAMEnd, 0, sizeof(NWRAMEnd)); memset(NWRAMMask, 0, sizeof(NWRAMMask)); - FILE* f = Platform::OpenLocalFile("nand.bin", "rb"); + FILE* f = Platform::OpenLocalFile(Config::DSiNANDPath, "rb"); if (f) { u32 bootparams[8]; diff --git a/src/NDS.cpp b/src/NDS.cpp index 001dfe6..22368ae 100644 --- a/src/NDS.cpp +++ b/src/NDS.cpp @@ -62,6 +62,8 @@ namespace NDS // // timings for GBA slot and wifi are set up at runtime +int ConsoleType; + u8 ARM9MemTimings[0x40000][4]; u8 ARM7MemTimings[0x20000][4]; @@ -296,6 +298,8 @@ void InitTimings() // TODO: +3c nonseq waitstate doesn't apply to DMA! // but of course mainRAM always gets 8c nonseq waitstate + // TODO: DSi-specific timings!! + SetARM9RegionTimings(0x00000000, 0xFFFFFFFF, 32, 1 + 3, 1); // void SetARM9RegionTimings(0xFFFF0000, 0xFFFFFFFF, 32, 1 + 3, 1); // BIOS @@ -321,6 +325,12 @@ void InitTimings() void SetupDirectBoot() { + if (ConsoleType == 1) + { + printf("!! DIRECT BOOT NOT SUPPORTED IN DSI MODE\n"); + return; + } + u32 bootparams[8]; memcpy(bootparams, &NDSCart::CartROM[0x20], 8*4); @@ -469,7 +479,7 @@ void Reset() fclose(f); } - if (true) + if (ConsoleType == 1) { DSi::LoadBIOS(); DSi::LoadNAND(); @@ -559,8 +569,11 @@ void Reset() RTC::Reset(); Wifi::Reset(); - DSi::Reset(); - KeyInput &= ~(1 << (16+6)); // TODO + if (ConsoleType == 1) + { + DSi::Reset(); + KeyInput &= ~(1 << (16+6)); + } AREngine::Reset(); } @@ -670,6 +683,11 @@ bool DoSavestate(Savestate* file) { file->Section("NDSG"); + // TODO: + // * do something for bool's (sizeof=1) + // * do something for 'loading DSi-mode savestate in DS mode' and vice-versa + // * add IE2/IF2 there + file->VarArray(MainRAM, 0x400000); file->VarArray(SharedWRAM, 0x8000); file->VarArray(ARM7WRAM, 0x10000); @@ -772,6 +790,11 @@ bool DoSavestate(Savestate* file) return true; } +void SetConsoleType(int type) +{ + ConsoleType = type; +} + bool LoadROM(const char* path, const char* sram, bool direct) { if (NDSCart::LoadROM(path, sram, direct)) @@ -883,7 +906,7 @@ u32 RunFrame() if (!(CPUStop & 0x80000000)) DMAs[1]->Run(); if (!(CPUStop & 0x80000000)) DMAs[2]->Run(); if (!(CPUStop & 0x80000000)) DMAs[3]->Run(); - DSi::RunNDMAs(0); + if (ConsoleType == 1) DSi::RunNDMAs(0); } else { @@ -906,7 +929,7 @@ u32 RunFrame() DMAs[5]->Run(); DMAs[6]->Run(); DMAs[7]->Run(); - DSi::RunNDMAs(1); + if (ConsoleType == 1) DSi::RunNDMAs(1); } else { @@ -990,7 +1013,7 @@ void CancelEvent(u32 id) void TouchScreen(u16 x, u16 y) { - if (true) // TODO!! + if (ConsoleType == 1) { DSi_SPI_TSC::SetTouchCoords(x, y); } @@ -1003,7 +1026,7 @@ void TouchScreen(u16 x, u16 y) void ReleaseScreen() { - if (true) // TODO!! + if (ConsoleType == 1) { DSi_SPI_TSC::SetTouchCoords(0x000, 0xFFF); } @@ -1144,7 +1167,8 @@ void UpdateIRQ(u32 cpu) if (IME[cpu] & 0x1) { arm->IRQ = IE[cpu] & IF[cpu]; - if (cpu) arm->IRQ |= (IE2 & IF2); + if ((ConsoleType == 1) && cpu) + arm->IRQ |= (IE2 & IF2); } else { @@ -1223,7 +1247,7 @@ void GXFIFOStall() DMAs[1]->StallIfRunning(); DMAs[2]->StallIfRunning(); DMAs[3]->StallIfRunning(); - DSi::StallNDMAs(); + if (ConsoleType == 1) DSi::StallNDMAs(); } } @@ -1361,6 +1385,7 @@ void NocashPrint(u32 ncpu, u32 addr) void MonitorARM9Jump(u32 addr) { // checkme: can the entrypoint addr be THUMB? + // also TODO: make it work in DSi mode if ((!RunningGame) && NDSCart::CartROM) { @@ -1468,7 +1493,7 @@ bool DMAsInMode(u32 cpu, u32 mode) if (DMAs[cpu+2]->IsInMode(mode)) return true; if (DMAs[cpu+3]->IsInMode(mode)) return true; - if (true) + if (ConsoleType == 1) { cpu >>= 2; return DSi::NDMAsInMode(cpu, NDMAModes[mode]); @@ -1484,7 +1509,10 @@ bool DMAsRunning(u32 cpu) if (DMAs[cpu+1]->IsRunning()) return true; if (DMAs[cpu+2]->IsRunning()) return true; if (DMAs[cpu+3]->IsRunning()) return true; - if (DSi::NDMAsRunning(cpu>>2)) return true; + if (ConsoleType == 1) + { + if (DSi::NDMAsRunning(cpu>>2)) return true; + } return false; } @@ -1496,7 +1524,7 @@ void CheckDMAs(u32 cpu, u32 mode) DMAs[cpu+2]->StartIfNeeded(mode); DMAs[cpu+3]->StartIfNeeded(mode); - if (true) + if (ConsoleType == 1) { cpu >>= 2; DSi::CheckNDMAs(cpu, NDMAModes[mode]); @@ -1511,7 +1539,7 @@ void StopDMAs(u32 cpu, u32 mode) DMAs[cpu+2]->StopIfNeeded(mode); DMAs[cpu+3]->StopIfNeeded(mode); - if (true) + if (ConsoleType == 1) { cpu >>= 2; DSi::StopNDMAs(cpu, NDMAModes[mode]); diff --git a/src/NDS.h b/src/NDS.h index 26931de..9c5fe3d 100644 --- a/src/NDS.h +++ b/src/NDS.h @@ -133,6 +133,8 @@ typedef struct } MemRegion; +extern int ConsoleType; + extern u8 ARM9MemTimings[0x40000][4]; extern u8 ARM7MemTimings[0x20000][4]; @@ -174,6 +176,9 @@ bool DoSavestate(Savestate* file); void SetARM9RegionTimings(u32 addrstart, u32 addrend, int buswidth, int nonseq, int seq); void SetARM7RegionTimings(u32 addrstart, u32 addrend, int buswidth, int nonseq, int seq); +// 0=DS 1=DSi +void SetConsoleType(int type); + bool LoadROM(const char* path, const char* sram, bool direct); bool LoadGBAROM(const char* path, const char* sram); void LoadBIOS(); diff --git a/src/NDSCart.cpp b/src/NDSCart.cpp index 9497d33..b326dd6 100644 --- a/src/NDSCart.cpp +++ b/src/NDSCart.cpp @@ -561,11 +561,18 @@ void Key1_ApplyKeycode(u32* keycode, u32 mod) void Key1_InitKeycode(bool dsi, u32 idcode, u32 level, u32 mod) { - //memcpy(Key1_KeyBuf, &NDS::ARM7BIOS[0x30], 0x1048); // hax - if (dsi) - memcpy(Key1_KeyBuf, &DSi::ARM7Init[0x254], 0x1048); // hax + // TODO: source the key data from different possible places + if (NDS::ConsoleType == 1) + { + if (dsi) + memcpy(Key1_KeyBuf, &DSi::ARM7Init[0x254], 0x1048); // hax + else + memcpy(Key1_KeyBuf, &DSi::ITCMInit[0x4894], 0x1048); // hax + } else - memcpy(Key1_KeyBuf, &DSi::ITCMInit[0x4894], 0x1048); // hax + { + memcpy(Key1_KeyBuf, &NDS::ARM7BIOS[0x30], 0x1048); // hax + } u32 keycode[3] = {idcode, idcode>>1, idcode<<1}; if (level >= 1) Key1_ApplyKeycode(keycode, mod); diff --git a/src/SPI.cpp b/src/SPI.cpp index 29f3321..ac40707 100644 --- a/src/SPI.cpp +++ b/src/SPI.cpp @@ -93,7 +93,10 @@ void Reset() if (Firmware) delete[] Firmware; Firmware = NULL; - strncpy(FirmwarePath, Config::FirmwarePath, 1023); + if (NDS::ConsoleType == 1) + strncpy(FirmwarePath, Config::DSiFirmwarePath, 1023); + else + strncpy(FirmwarePath, Config::FirmwarePath, 1023); FILE* f = Platform::OpenLocalFile(FirmwarePath, "rb"); if (!f) @@ -620,7 +623,7 @@ void Reset() SPI_Firmware::Reset(); SPI_Powerman::Reset(); SPI_TSC::Reset(); - DSi_SPI_TSC::Reset(); + if (NDS::ConsoleType == 1) DSi_SPI_TSC::Reset(); } void DoSavestate(Savestate* file) @@ -633,7 +636,7 @@ void DoSavestate(Savestate* file) SPI_Firmware::DoSavestate(file); SPI_Powerman::DoSavestate(file); SPI_TSC::DoSavestate(file); - DSi_SPI_TSC::DoSavestate(file); + if (NDS::ConsoleType == 1) DSi_SPI_TSC::DoSavestate(file); } @@ -647,8 +650,12 @@ void WriteCnt(u16 val) { case 0x0000: SPI_Powerman::Hold = 0; break; case 0x0100: SPI_Firmware::Hold = 0; break; - //case 0x0200: SPI_TSC::DataPos = 0; break; - case 0x0200: DSi_SPI_TSC::DataPos = 0; break; + case 0x0200: + if (NDS::ConsoleType == 1) + DSi_SPI_TSC::DataPos = 0; + else + SPI_TSC::DataPos = 0; + break; } } @@ -674,8 +681,11 @@ u8 ReadData() { case 0x0000: return SPI_Powerman::Read(); case 0x0100: return SPI_Firmware::Read(); - //case 0x0200: return SPI_TSC::Read(); - case 0x0200: return DSi_SPI_TSC::Read(); + case 0x0200: + if (NDS::ConsoleType == 1) + return DSi_SPI_TSC::Read(); + else + return SPI_TSC::Read(); default: return 0; } } @@ -691,8 +701,12 @@ void WriteData(u8 val) { case 0x0000: SPI_Powerman::Write(val, Cnt&(1<<11)); break; case 0x0100: SPI_Firmware::Write(val, Cnt&(1<<11)); break; - //case 0x0200: SPI_TSC::Write(val, Cnt&(1<<11)); break; - case 0x0200: DSi_SPI_TSC::Write(val, Cnt&(1<<11)); break; + case 0x0200: + if (NDS::ConsoleType == 1) + DSi_SPI_TSC::Write(val, Cnt&(1<<11)); + else + SPI_TSC::Write(val, Cnt&(1<<11)); + break; default: printf("SPI to unknown device %04X %02X\n", Cnt, val); break; } diff --git a/src/SPU.cpp b/src/SPU.cpp index 959de12..9f6b107 100644 --- a/src/SPU.cpp +++ b/src/SPU.cpp @@ -155,6 +155,11 @@ Channel::~Channel() void Channel::Reset() { + if (NDS::ConsoleType == 1) + BusRead32 = DSi::ARM7Read32; + else + BusRead32 = NDS::ARM7Read32; + SetCnt(0); SrcAddr = 0; TimerReload = 0; @@ -217,8 +222,7 @@ void Channel::FIFO_BufferData() for (u32 i = 0; i < burstlen; i += 4) { - //FIFO[FIFOWritePos] = NDS::ARM7Read32(SrcAddr + FIFOReadOffset); - FIFO[FIFOWritePos] = DSi::ARM7Read32(SrcAddr + FIFOReadOffset); + FIFO[FIFOWritePos] = BusRead32(SrcAddr + FIFOReadOffset); FIFOReadOffset += 4; FIFOWritePos++; FIFOWritePos &= 0x7; @@ -466,6 +470,11 @@ CaptureUnit::~CaptureUnit() void CaptureUnit::Reset() { + if (NDS::ConsoleType == 1) + BusWrite32 = DSi::ARM7Write32; + else + BusWrite32 = NDS::ARM7Write32; + SetCnt(0); DstAddr = 0; TimerReload = 0; @@ -501,8 +510,7 @@ void CaptureUnit::FIFO_FlushData() { for (u32 i = 0; i < 4; i++) { - //NDS::ARM7Write32(DstAddr + FIFOWriteOffset, FIFO[FIFOReadPos]); - DSi::ARM7Write32(DstAddr + FIFOWriteOffset, FIFO[FIFOReadPos]); + BusWrite32(DstAddr + FIFOWriteOffset, FIFO[FIFOReadPos]); FIFOReadPos++; FIFOReadPos &= 0x3; diff --git a/src/SPU.h b/src/SPU.h index 74a4471..8ab17a0 100644 --- a/src/SPU.h +++ b/src/SPU.h @@ -142,6 +142,9 @@ public: } void PanOutput(s32* inbuf, u32 samples, s32* leftbuf, s32* rightbuf); + +private: + u32 (*BusRead32)(u32 addr); }; class CaptureUnit @@ -196,6 +199,9 @@ public: } void Run(s32 sample); + +private: + void (*BusWrite32)(u32 addr, u32 val); }; } diff --git a/src/frontend/FrontendUtil.h b/src/frontend/FrontendUtil.h index 6b83cbc..099583f 100644 --- a/src/frontend/FrontendUtil.h +++ b/src/frontend/FrontendUtil.h @@ -46,6 +46,15 @@ enum Load_FirmwareBad, Load_FirmwareNotBootable, + Load_DSiBIOS9Missing, + Load_DSiBIOS9Bad, + + Load_DSiBIOS7Missing, + Load_DSiBIOS7Bad, + + Load_DSiNANDMissing, + Load_DSiNANDBad, + // TODO: more precise errors for ROM loading Load_ROMLoadError, }; diff --git a/src/frontend/Util_ROM.cpp b/src/frontend/Util_ROM.cpp index d410550..8116a93 100644 --- a/src/frontend/Util_ROM.cpp +++ b/src/frontend/Util_ROM.cpp @@ -96,6 +96,42 @@ int VerifyDSBIOS() return Load_OK; } +int VerifyDSiBIOS() +{ + FILE* f; + long len; + + // TODO: check the first 32 bytes + + f = Platform::OpenLocalFile(Config::DSiBIOS9Path, "rb"); + if (!f) return Load_DSiBIOS9Missing; + + fseek(f, 0, SEEK_END); + len = ftell(f); + if (len != 0x10000) + { + fclose(f); + return Load_DSiBIOS9Bad; + } + + fclose(f); + + f = Platform::OpenLocalFile(Config::DSiBIOS7Path, "rb"); + if (!f) return Load_DSiBIOS7Missing; + + fseek(f, 0, SEEK_END); + len = ftell(f); + if (len != 0x10000) + { + fclose(f); + return Load_DSiBIOS7Bad; + } + + fclose(f); + + return Load_OK; +} + int VerifyDSFirmware() { FILE* f; @@ -110,7 +146,6 @@ int VerifyDSFirmware() { // 128KB firmware, not bootable fclose(f); - return Load_OK; // FIXME!!!! return Load_FirmwareNotBootable; } else if (len != 0x40000 && len != 0x80000) @@ -124,6 +159,45 @@ int VerifyDSFirmware() return Load_OK; } +int VerifyDSiFirmware() +{ + FILE* f; + long len; + + f = Platform::OpenLocalFile(Config::DSiFirmwarePath, "rb"); + if (!f) return Load_FirmwareMissing; + + fseek(f, 0, SEEK_END); + len = ftell(f); + if (len != 0x20000) + { + // not 128KB + // TODO: check whether those work + fclose(f); + return Load_FirmwareBad; + } + + fclose(f); + + return Load_OK; +} + +int VerifyDSiNAND() +{ + FILE* f; + long len; + + f = Platform::OpenLocalFile(Config::DSiNANDPath, "rb"); + if (!f) return Load_DSiNANDMissing; + + // TODO: some basic checks + // check that it has the nocash footer, and all + + fclose(f); + + return Load_OK; +} + int LoadBIOS() { int res; @@ -131,8 +205,22 @@ int LoadBIOS() res = VerifyDSBIOS(); if (res != Load_OK) return res; - res = VerifyDSFirmware(); - if (res != Load_OK) return res; + if (Config::ConsoleType == 1) + { + res = VerifyDSiBIOS(); + if (res != Load_OK) return res; + + res = VerifyDSiFirmware(); + if (res != Load_OK) return res; + + res = VerifyDSiNAND(); + if (res != Load_OK) return res; + } + else + { + res = VerifyDSFirmware(); + if (res != Load_OK) return res; + } // TODO: // original code in the libui frontend called NDS::LoadGBAROM() if needed @@ -142,6 +230,7 @@ int LoadBIOS() ROMPath[ROMSlot_NDS][0] = '\0'; SRAMPath[ROMSlot_NDS][0] = '\0'; + NDS::SetConsoleType(Config::ConsoleType); NDS::LoadBIOS(); SavestateLoaded = false; @@ -154,16 +243,39 @@ int LoadROM(const char* file, int slot) int res; bool directboot = Config::DirectBoot != 0; + if (Config::ConsoleType == 1 && slot == 1) + { + // cannot load a GBA ROM into a DSi + return Load_ROMLoadError; + } + res = VerifyDSBIOS(); if (res != Load_OK) return res; - res = VerifyDSFirmware(); - if (res != Load_OK) + if (Config::ConsoleType == 1) { - if (res == Load_FirmwareNotBootable) - directboot = true; - else - return res; + res = VerifyDSiBIOS(); + if (res != Load_OK) return res; + + res = VerifyDSiFirmware(); + if (res != Load_OK) return res; + + res = VerifyDSiNAND(); + if (res != Load_OK) return res; + + GBACart::Eject(); + ROMPath[ROMSlot_GBA][0] = '\0'; + } + else + { + res = VerifyDSFirmware(); + if (res != Load_OK) + { + if (res == Load_FirmwareNotBootable) + directboot = true; + else + return res; + } } char oldpath[1024]; @@ -177,6 +289,8 @@ int LoadROM(const char* file, int slot) SetupSRAMPath(0); SetupSRAMPath(1); + NDS::SetConsoleType(Config::ConsoleType); + if (slot == ROMSlot_NDS && NDS::LoadROM(ROMPath[slot], SRAMPath[slot], directboot)) { SavestateLoaded = false; @@ -225,17 +339,36 @@ int Reset() res = VerifyDSBIOS(); if (res != Load_OK) return res; - res = VerifyDSFirmware(); - if (res != Load_OK) + if (Config::ConsoleType == 1) { - if (res == Load_FirmwareNotBootable) - directboot = true; - else - return res; + res = VerifyDSiBIOS(); + if (res != Load_OK) return res; + + res = VerifyDSiFirmware(); + if (res != Load_OK) return res; + + res = VerifyDSiNAND(); + if (res != Load_OK) return res; + + GBACart::Eject(); + ROMPath[ROMSlot_GBA][0] = '\0'; + } + else + { + res = VerifyDSFirmware(); + if (res != Load_OK) + { + if (res == Load_FirmwareNotBootable) + directboot = true; + else + return res; + } } SavestateLoaded = false; + NDS::SetConsoleType(Config::ConsoleType); + if (ROMPath[ROMSlot_NDS][0] == '\0') { NDS::LoadBIOS(); diff --git a/src/frontend/qt_sdl/EmuSettingsDialog.cpp b/src/frontend/qt_sdl/EmuSettingsDialog.cpp index 7760a88..09faf4e 100644 --- a/src/frontend/qt_sdl/EmuSettingsDialog.cpp +++ b/src/frontend/qt_sdl/EmuSettingsDialog.cpp @@ -49,7 +49,7 @@ EmuSettingsDialog::EmuSettingsDialog(QWidget* parent) : QDialog(parent), ui(new ui->txtDSiNANDPath->setText(Config::DSiNANDPath); ui->cbxConsoleType->addItem("DS"); - ui->cbxConsoleType->addItem("DSi"); + ui->cbxConsoleType->addItem("DSi (experimental)"); ui->cbxConsoleType->setCurrentIndex(Config::ConsoleType); ui->chkDirectBoot->setChecked(Config::DirectBoot != 0); diff --git a/src/frontend/qt_sdl/main.cpp b/src/frontend/qt_sdl/main.cpp index ef21bc7..7b3d5cd 100644 --- a/src/frontend/qt_sdl/main.cpp +++ b/src/frontend/qt_sdl/main.cpp @@ -1360,17 +1360,40 @@ QString MainWindow::loadErrorStr(int error) { switch (error) { - case Frontend::Load_BIOS9Missing: return "DS ARM9 BIOS was not found or could not be accessed. Check your emu settings."; - 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. Check your emu settings."; - 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. Check your emu settings."; - 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."; + case Frontend::Load_BIOS9Missing: + return "DS ARM9 BIOS was not found or could not be accessed. Check your emu settings."; + 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. Check your emu settings."; + 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. Check your emu settings."; + 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_DSiBIOS9Missing: + return "DSi ARM9 BIOS was not found or could not be accessed. Check your emu settings."; + case Frontend::Load_DSiBIOS9Bad: + return "DSi ARM9 BIOS is not a valid BIOS dump."; + + case Frontend::Load_DSiBIOS7Missing: + return "DSi ARM7 BIOS was not found or could not be accessed. Check your emu settings."; + case Frontend::Load_DSiBIOS7Bad: + return "DSi ARM7 BIOS is not a valid BIOS dump."; + + case Frontend::Load_DSiNANDMissing: + return "DSi NAND was not found or could not be accessed. Check your emu settings."; + case Frontend::Load_DSiNANDBad: + return "DSi NAND is not a valid NAND dump."; + + 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."; } -- cgit v1.2.3