diff --git a/src/frontend/qt_sdl/ROMLoader.cpp b/src/frontend/qt_sdl/ROMLoader.cpp index 7d54a150..0b0bc099 100644 --- a/src/frontend/qt_sdl/ROMLoader.cpp +++ b/src/frontend/qt_sdl/ROMLoader.cpp @@ -26,7 +26,7 @@ #include "ArchiveUtil.h" #endif #include "ROMLoader.h" -#include "SharedConfig.h" +#include "Config.h" #include "Platform.h" #include "NDS.h" @@ -39,51 +39,47 @@ namespace ROMLoader { -std::string ROMPath [ROMSlot_MAX]; -std::string SRAMPath [ROMSlot_MAX]; -std::string PrevSRAMPath[ROMSlot_MAX]; // for savestate 'undo load' - -std::string NDSROMExtension; - -bool SavestateLoaded; - -ARCodeFile* CheatFile; -bool CheatsOn; +std::string FullROMPath; +std::string BaseROMDir; +std::string BaseROMName; -/*void Init_ROM() +int LastSep(std::string path) { - SavestateLoaded = false; + int i = path.length() - 1; + while (i >= 0) + { + if (path[i] == '/' || path[i] == '\\') + return i; - ROMPath[ROMSlot_NDS] = ""; - ROMPath[ROMSlot_GBA] = ""; - SRAMPath[ROMSlot_NDS] = ""; - SRAMPath[ROMSlot_GBA] = ""; - PrevSRAMPath[ROMSlot_NDS] = ""; - PrevSRAMPath[ROMSlot_GBA] = ""; + i--; + } - CheatFile = nullptr; - CheatsOn = false; + return -1; } -void DeInit_ROM() +std::string GetAssetPath(std::string configpath, std::string ext) { - if (CheatFile) + if (configpath.empty()) + configpath = BaseROMDir; + + for (;;) { - delete CheatFile; - CheatFile = nullptr; + int i = configpath.length() - 1; + if (configpath[i] == '/' || configpath[i] == '\\') + configpath = configpath.substr(0, i); + else + break; } -}*/ -// 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? + if (!configpath.empty()) + configpath += "/"; + + return configpath + BaseROMName + ext; +} + + -/*void SetupSRAMPath(int slot) -{ - SRAMPath[slot] = ROMPath[slot].substr(0, ROMPath[slot].length() - 3) + "sav"; -}*/ QString VerifyDSBIOS() { @@ -266,12 +262,16 @@ bool LoadROM(QStringList filepath, bool reset) u8* filedata; u32 filelen; + std::string basepath; + std::string romname; + int num = filepath.count(); if (num == 1) { // regular file - FILE* f = Platform::OpenFile(filepath.at(0).toStdString(), "rb", true); + std::string filename = filepath.at(0).toStdString(); + FILE* f = Platform::OpenFile(filename, "rb", true); if (!f) return false; fseek(f, 0, SEEK_END); @@ -294,13 +294,19 @@ bool LoadROM(QStringList filepath, bool reset) fclose(f); filelen = (u32)len; + + int pos = LastSep(filename); + basepath = filename.substr(0, pos); + romname = filename.substr(pos+1); } #ifdef ARCHIVE_SUPPORT_ENABLED else if (num == 2) { // file inside archive - u32 lenread = Archive::ExtractFileFromArchive(filepath.at(0), filepath.at(1), &filedata, &filelen); + QString archivepath = filepath.at(0); + + u32 lenread = Archive::ExtractFileFromArchive(archivepath, filepath.at(1), &filedata, &filelen); if (lenread < 0) return false; if (!filedata) return false; if (lenread != filelen) @@ -308,247 +314,55 @@ bool LoadROM(QStringList filepath, bool reset) delete[] filedata; return false; } + + std::string std_archivepath = archivepath.toStdString(); + basepath = std_archivepath.substr(0, LastSep(std_archivepath)); + + std::string std_romname = filepath.at(1).toStdString(); + romname = std_romname.substr(LastSep(std_romname)+1); } #endif else return false; + // + printf("BASE PATH IS %s\n", basepath.c_str()); + printf("ROM NAME IS %s\n", romname.c_str()); + BaseROMDir = basepath; + + BaseROMName = romname.substr(0, romname.rfind('.')); + if (reset) { NDS::Reset(); } - // TODO: SAVE - return NDS::LoadCart(filedata, filelen, nullptr, 0); + u32 savelen = 0; + u8* savedata = nullptr; + + std::string savname = GetAssetPath(Config::SaveFilePath, ".sav"); + FILE* sav = Platform::OpenFile(savname, "rb", true); + if (sav) + { + fseek(sav, 0, SEEK_END); + savelen = (u32)ftell(sav); + + fseek(sav, 0, SEEK_SET); + savedata = new u8[savelen]; + fread(savedata, savelen, 1, sav); + fclose(sav); + } + + bool res = NDS::LoadCart(filedata, filelen, savedata, savelen); + + delete[] savedata; + delete[] filedata; + return res; } -void LoadCheats() -{ - if (CheatFile) - { - delete CheatFile; - CheatFile = nullptr; - } - std::string filename; - if (!ROMPath[ROMSlot_NDS].empty()) - { - filename = ROMPath[ROMSlot_NDS].substr(0, ROMPath[ROMSlot_NDS].length() - 3) + "mch"; - } - else - { - filename = "firmware.mch"; - } - - // TODO: add custom path here - - // TODO: check for error (malformed cheat file, ...) - CheatFile = new ARCodeFile(filename); - - AREngine::SetCodeFile(CheatsOn ? CheatFile : nullptr); -} - -/*int LoadBIOS() -{ - DSi::CloseDSiNAND(); - - int res; - - res = VerifyDSBIOS(); - 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 = SetupDSiNAND(); - 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 - // should this be carried over here? - // is that behavior consistent with that of LoadROM() below? - - ROMPath[ROMSlot_NDS] = ""; - SRAMPath[ROMSlot_NDS] = ""; - - NDS::SetConsoleType(Config::ConsoleType); - NDS::LoadBIOS(); - - SavestateLoaded = false; - - LoadCheats(); - - return Load_OK; -} - -int LoadROM(const u8 *romdata, u32 romlength, const char *archivefilename, const char *romfilename, const char *sramfilename, int slot) -{ - int res; - bool directboot = Config::DirectBoot; - - 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; - - if (Config::ConsoleType == 1) - { - res = VerifyDSiBIOS(); - if (res != Load_OK) return res; - - res = VerifyDSiFirmware(); - if (res != Load_OK) return res; - - res = SetupDSiNAND(); - if (res != Load_OK) return res; - - GBACart::Eject(); - ROMPath[ROMSlot_GBA] = ""; - } - else - { - res = VerifyDSFirmware(); - if (res != Load_OK) - { - if (res == Load_FirmwareNotBootable) - directboot = true; - else - return res; - } - } - - std::string oldpath = ROMPath[slot]; - std::string oldsram = SRAMPath[slot]; - - SRAMPath[slot] = sramfilename; - ROMPath[slot] = archivefilename; - - NDS::SetConsoleType(Config::ConsoleType); - -/* if (slot == ROMSlot_NDS && NDS::LoadROM(romdata, romlength, SRAMPath[slot].c_str(), directboot)) - { - SavestateLoaded = false; - - LoadCheats(); - - // Reload the inserted GBA cartridge (if any) - // TODO: report failure there?? - //if (!ROMPath[ROMSlot_GBA].empty()) NDS::LoadGBAROM(ROMPath[ROMSlot_GBA], SRAMPath[ROMSlot_GBA]); - - PrevSRAMPath[slot] = SRAMPath[slot]; // safety - return Load_OK; - } - else if (slot == ROMSlot_GBA && NDS::LoadGBAROM(romdata, romlength, romfilename, SRAMPath[slot].c_str())) - { - SavestateLoaded = false; // checkme?? - - PrevSRAMPath[slot] = SRAMPath[slot]; // safety - return Load_OK; - } - else*-/ - { - ROMPath[slot] = oldpath; - SRAMPath[slot] = oldsram; - return Load_ROMLoadError; - } -} - -int LoadROM(const char* file, int slot) -{ - DSi::CloseDSiNAND(); - - 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; - - if (Config::ConsoleType == 1) - { - res = VerifyDSiBIOS(); - if (res != Load_OK) return res; - - res = VerifyDSiFirmware(); - if (res != Load_OK) return res; - - res = SetupDSiNAND(); - if (res != Load_OK) return res; - - GBACart::Eject(); - ROMPath[ROMSlot_GBA] = ""; - } - else - { - res = VerifyDSFirmware(); - if (res != Load_OK) - { - if (res == Load_FirmwareNotBootable) - directboot = true; - else - return res; - } - } - - std::string oldpath = ROMPath[slot]; - std::string oldsram = SRAMPath[slot]; - - ROMPath[slot] = file; - - SetupSRAMPath(0); - SetupSRAMPath(1); - - NDS::SetConsoleType(Config::ConsoleType); - - /*if (slot == ROMSlot_NDS && NDS::LoadROM(ROMPath[slot].c_str(), SRAMPath[slot].c_str(), directboot)) - { - SavestateLoaded = false; - - LoadCheats(); - - // Reload the inserted GBA cartridge (if any) - // TODO: report failure there?? - if (!ROMPath[ROMSlot_GBA].empty()) NDS::LoadGBAROM(ROMPath[ROMSlot_GBA].c_str(), SRAMPath[ROMSlot_GBA].c_str()); - - PrevSRAMPath[slot] = SRAMPath[slot]; // safety - return Load_OK; - } - else if (slot == ROMSlot_GBA && NDS::LoadGBAROM(ROMPath[slot].c_str(), SRAMPath[slot].c_str())) - { - SavestateLoaded = false; // checkme?? - - PrevSRAMPath[slot] = SRAMPath[slot]; // safety - return Load_OK; - } - else*-/ - { - ROMPath[slot] = oldpath; - SRAMPath[slot] = oldsram; - return Load_ROMLoadError; - } -}*/ void ROMIcon(u8 (&data)[512], u16 (&palette)[16], u32* iconRef) { @@ -616,318 +430,4 @@ void AnimatedROMIcon(u8 (&data)[8][512], u16 (&palette)[8][16], u16 (&sequence)[ } } -void UnloadROM(int slot) -{ - if (slot == ROMSlot_NDS) - { - // TODO! - } - else if (slot == ROMSlot_GBA) - { - GBACart::Eject(); - } - - ROMPath[slot] = ""; - - DSi::CloseDSiNAND(); -} - -int Reset() -{ - /*DSi::CloseDSiNAND(); - - int res; - bool directboot = Config::DirectBoot != 0; - - res = VerifyDSBIOS(); - 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 = SetupDSiNAND(); - 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].empty()) - { - NDS::LoadBIOS(); - } - else - { - std::string ext = ROMPath[ROMSlot_NDS].substr(ROMPath[ROMSlot_NDS].length() - 4); - std::transform(ext.begin(), ext.end(), ext.begin(), tolower); - - if (ext == ".nds" || ext == ".srl" || ext == ".dsi") - { - SetupSRAMPath(0); - //if (!NDS::LoadROM(ROMPath[ROMSlot_NDS].c_str(), SRAMPath[ROMSlot_NDS].c_str(), directboot)) - // return Load_ROMLoadError; - } -#ifdef ARCHIVE_SUPPORT_ENABLED - else - { - // TODO!!! - // THIS WILL BREAK IF CUSTOM SRAM PATHS ARE ADDED - - /*u8 *romdata = nullptr; u32 romlen; - char romfilename[1024] = {0}, sramfilename[1024]; - strncpy(sramfilename, SRAMPath[ROMSlot_NDS], 1024); // Use existing SRAMPath - - int pos = strlen(sramfilename) - 1; - while (pos > 0 && sramfilename[pos] != '/' && sramfilename[pos] != '\\') - --pos; - - strncpy(romfilename, &sramfilename[pos + 1], 1024); - strncpy(&romfilename[strlen(romfilename) - 3], NDSROMExtension, 3); // extension could be nds, srl or dsi - printf("RESET loading from archive : %s\n", romfilename); - romlen = Archive::ExtractFileFromArchive(ROMPath[ROMSlot_NDS], romfilename, &romdata); - if (!romdata) - return Load_ROMLoadError; - - bool ok = NDS::LoadROM(romdata, romlen, sramfilename, directboot); - delete romdata; - if (!ok)*-/ - return Load_ROMLoadError; - } -#endif - } - - if (!ROMPath[ROMSlot_GBA].empty()) - { - std::string ext = ROMPath[ROMSlot_GBA].substr(ROMPath[ROMSlot_GBA].length() - 4); - std::transform(ext.begin(), ext.end(), ext.begin(), tolower); - - if (ext == ".gba") - { - SetupSRAMPath(1); - //if (!NDS::LoadGBAROM(ROMPath[ROMSlot_GBA].c_str(), SRAMPath[ROMSlot_GBA].c_str())) - // return Load_ROMLoadError; - } -#ifdef ARCHIVE_SUPPORT_ENABLED - else - { - // TODO!! SAME AS ABOVE - - /*u8 *romdata = nullptr; u32 romlen; - char romfilename[1024] = {0}, sramfilename[1024]; - strncpy(sramfilename, SRAMPath[ROMSlot_GBA], 1024); // Use existing SRAMPath - - int pos = strlen(sramfilename) - 1; - while (pos > 0 && sramfilename[pos] != '/' && sramfilename[pos] != '\\') - --pos; - - strncpy(romfilename, &sramfilename[pos + 1], 1024); - strncpy(&romfilename[strlen(romfilename) - 3], "gba", 3); - printf("RESET loading from archive : %s\n", romfilename); - romlen = Archive::ExtractFileFromArchive(ROMPath[ROMSlot_GBA], romfilename, &romdata); - if (!romdata) - return Load_ROMLoadError; - - bool ok = NDS::LoadGBAROM(romdata, romlen, romfilename, SRAMPath[ROMSlot_GBA]); - delete romdata; - if (!ok)*-/ - return Load_ROMLoadError; - } -#endif - } - - LoadCheats();*/ - - return Load_OK; -} - - -// SAVESTATE TODO -// * configurable paths. not everyone wants their ROM directory to be polluted, I guess. - -std::string GetSavestateName(int slot) -{ - std::string filename; - - if (ROMPath[ROMSlot_NDS].empty()) // running firmware, no ROM - { - filename = "firmware"; - } - else - { - std::string rompath; - std::string ext = ROMPath[ROMSlot_NDS].substr(ROMPath[ROMSlot_NDS].length() - 4); - std::transform(ext.begin(), ext.end(), ext.begin(), tolower); - - // TODO!!! MORE SHIT THAT IS GONNA ASPLODE - if (ext == ".nds" || ext == ".srl" || ext == ".dsi") - rompath = ROMPath[ROMSlot_NDS]; - else - rompath = SRAMPath[ROMSlot_NDS]; // If archive, construct ssname from sram file - - filename = rompath.substr(0, rompath.rfind('.')); - } - - filename += ".ml"; - filename += ('0'+slot); - - return filename; -} - -bool SavestateExists(int slot) -{ - std::string ssfile = GetSavestateName(slot); - return Platform::FileExists(ssfile); -} - -bool LoadState(std::string 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].empty()) - { - PrevSRAMPath[ROMSlot_NDS] = SRAMPath[ROMSlot_NDS]; - - // TODO: how should this interact with custom paths? - SRAMPath[ROMSlot_NDS] = filename + ".sav"; - - //NDS::RelocateSave(SRAMPath[ROMSlot_NDS].c_str(), 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] = ""; - SRAMPath[ROMSlot_GBA] = ""; - 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(std::string 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].empty()) - { - // TODO: how should this interact with custom paths? - SRAMPath[ROMSlot_NDS] = filename + ".sav"; - - //NDS::RelocateSave(SRAMPath[ROMSlot_NDS].c_str(), true); - } - } - - 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].empty()) - { - SRAMPath[ROMSlot_NDS] = PrevSRAMPath[ROMSlot_NDS]; - //NDS::RelocateSave(SRAMPath[ROMSlot_NDS].c_str(), false); - } -} - -int ImportSRAM(const char* filename) -{ - /*FILE* file = fopen(filename, "rb"); - fseek(file, 0, SEEK_END); - u32 size = ftell(file); - u8* importData = new u8[size]; - rewind(file); - fread(importData, size, 1, file); - fclose(file); - - int diff = NDS::ImportSRAM(importData, size); - delete[] importData; - return diff;*/ - return 0; -} - -void EnableCheats(bool enable) -{ - CheatsOn = enable; - if (CheatFile) - AREngine::SetCodeFile(CheatsOn ? CheatFile : nullptr); -} - }