diff options
Diffstat (limited to 'src/libui_sdl/main.cpp')
-rw-r--r-- | src/libui_sdl/main.cpp | 401 |
1 files changed, 381 insertions, 20 deletions
diff --git a/src/libui_sdl/main.cpp b/src/libui_sdl/main.cpp index 6736fbc..4c19314 100644 --- a/src/libui_sdl/main.cpp +++ b/src/libui_sdl/main.cpp @@ -1,5 +1,5 @@ /* - Copyright 2016-2017 StapleButter + Copyright 2016-2019 StapleButter This file is part of melonDS. @@ -24,6 +24,7 @@ #include "libui/ui.h" #include "../types.h" +#include "../melon_fopen.h" #include "../version.h" #include "../Config.h" @@ -37,6 +38,13 @@ #include "../Platform.h" #include "../Config.h" +#include "../Savestate.h" + + +// savestate slot mapping +// 1-8: regular slots (quick access) +// '9': load/save arbitrary file +const int kSavestateNum[9] = {1, 2, 3, 4, 5, 6, 7, 8, 0}; const int kScreenRot[4] = {0, 1, 2, 3}; const int kScreenGap[6] = {0, 1, 8, 64, 90, 128}; @@ -47,10 +55,19 @@ const int kScreenSizing[4] = {0, 1, 2, 3}; uiWindow* MainWindow; uiArea* MainDrawArea; +uiMenuItem* MenuItem_SaveState; +uiMenuItem* MenuItem_LoadState; +uiMenuItem* MenuItem_UndoStateLoad; + +uiMenuItem* MenuItem_SaveStateSlot[9]; +uiMenuItem* MenuItem_LoadStateSlot[9]; + uiMenuItem* MenuItem_Pause; uiMenuItem* MenuItem_Reset; uiMenuItem* MenuItem_Stop; +uiMenuItem* MenuItem_SavestateSRAMReloc; + uiMenuItem* MenuItem_ScreenRot[4]; uiMenuItem* MenuItem_ScreenGap[6]; uiMenuItem* MenuItem_ScreenLayout[3]; @@ -62,6 +79,10 @@ volatile int EmuStatus; bool RunningSomething; char ROMPath[1024]; +char SRAMPath[1024]; +char PrevSRAMPath[1024]; // for savestate 'undo load' + +bool SavestateLoaded; bool ScreenDrawInited = false; uiDrawBitmap* ScreenBitmap = NULL; @@ -88,6 +109,20 @@ SDL_Joystick* Joystick; void SetupScreenRects(int width, int height); +void SaveState(int slot); +void LoadState(int slot); +void UndoStateLoad(); +void GetSavestateName(int slot, char* filename, int len); + + + +bool FileExists(char* name) +{ + FILE* f = melon_fopen(name, "rb"); + if (!f) return false; + fclose(f); + return true; +} void UpdateWindowTitle(void* data) @@ -301,8 +336,6 @@ int EmuThreadFunc(void* burp) } else { - EmuStatus = 2; - // paused nframes = 0; lasttick = SDL_GetTicks(); @@ -310,7 +343,13 @@ int EmuThreadFunc(void* burp) lastmeasuretick = lasttick; fpslimitcount = 0; - uiAreaQueueRedrawAll(MainDrawArea); + if (EmuRunning == 2) + { + uiAreaQueueRedrawAll(MainDrawArea); + } + + EmuStatus = EmuRunning; + SDL_Delay(100); } } @@ -438,6 +477,10 @@ int OnAreaKeyEvent(uiAreaHandler* handler, uiArea* area, uiAreaKeyEvent* evt) if (evt->Modifiers == 0x2) // ALT+key return 0; + // d0rp + if (!RunningSomething) + return 1; + if (evt->Up) { for (int i = 0; i < 12; i++) @@ -446,6 +489,22 @@ int OnAreaKeyEvent(uiAreaHandler* handler, uiArea* area, uiAreaKeyEvent* evt) } else if (!evt->Repeat) { + // F keys: 3B-44, 57-58 | SHIFT: mod. 0x4 + if (evt->Scancode >= 0x3B && evt->Scancode <= 0x42) // F1-F8, quick savestate + { + if (evt->Modifiers == 0x4) SaveState(1 + (evt->Scancode - 0x3B)); + else if (evt->Modifiers == 0x0) LoadState(1 + (evt->Scancode - 0x3B)); + } + else if (evt->Scancode == 0x43) // F9, savestate from/to file + { + if (evt->Modifiers == 0x4) SaveState(0); + else if (evt->Modifiers == 0x0) LoadState(0); + } + else if (evt->Scancode == 0x58) // F12, undo savestate + { + if (evt->Modifiers == 0x0) UndoStateLoad(); + } + for (int i = 0; i < 12; i++) if (evt->Scancode == Config::KeyMapping[i]) KeyInputMask &= ~(1<<i); @@ -710,6 +769,25 @@ void Run() EmuRunning = 1; RunningSomething = true; + uiMenuItemEnable(MenuItem_SaveState); + uiMenuItemEnable(MenuItem_LoadState); + + if (SavestateLoaded) + uiMenuItemEnable(MenuItem_UndoStateLoad); + else + uiMenuItemDisable(MenuItem_UndoStateLoad); + + for (int i = 0; i < 8; i++) + { + char ssfile[1024]; + GetSavestateName(i+1, ssfile, 1024); + if (FileExists(ssfile)) uiMenuItemEnable(MenuItem_LoadStateSlot[i]); + else uiMenuItemDisable(MenuItem_LoadStateSlot[i]); + } + + for (int i = 0; i < 9; i++) uiMenuItemEnable(MenuItem_SaveStateSlot[i]); + uiMenuItemEnable(MenuItem_LoadStateSlot[8]); + uiMenuItemEnable(MenuItem_Pause); uiMenuItemEnable(MenuItem_Reset); uiMenuItemEnable(MenuItem_Stop); @@ -723,6 +801,12 @@ void Stop(bool internal) while (EmuStatus != 2); RunningSomething = false; + uiWindowSetTitle(MainWindow, "melonDS " MELONDS_VERSION); + + for (int i = 0; i < 9; i++) uiMenuItemDisable(MenuItem_SaveStateSlot[i]); + for (int i = 0; i < 9; i++) uiMenuItemDisable(MenuItem_LoadStateSlot[i]); + uiMenuItemDisable(MenuItem_UndoStateLoad); + uiMenuItemDisable(MenuItem_Pause); uiMenuItemDisable(MenuItem_Reset); uiMenuItemDisable(MenuItem_Stop); @@ -732,16 +816,33 @@ void Stop(bool internal) uiAreaQueueRedrawAll(MainDrawArea); } +void SetupSRAMPath() +{ + strncpy(SRAMPath, ROMPath, 1023); + SRAMPath[1023] = '\0'; + strncpy(SRAMPath + strlen(ROMPath) - 3, "sav", 3); +} + void TryLoadROM(char* file, int prevstatus) { char oldpath[1024]; + char oldsram[1024]; strncpy(oldpath, ROMPath, 1024); + strncpy(oldsram, SRAMPath, 1024); strncpy(ROMPath, file, 1023); ROMPath[1023] = '\0'; - if (NDS::LoadROM(ROMPath, Config::DirectBoot)) + SetupSRAMPath(); + + if (NDS::LoadROM(ROMPath, SRAMPath, Config::DirectBoot)) + { + SavestateLoaded = false; + uiMenuItemDisable(MenuItem_UndoStateLoad); + + strncpy(PrevSRAMPath, SRAMPath, 1024); // safety Run(); + } else { uiMsgBoxError(MainWindow, @@ -749,18 +850,194 @@ void TryLoadROM(char* file, int prevstatus) "Make sure the file can be accessed and isn't opened in another application."); strncpy(ROMPath, oldpath, 1024); + strncpy(SRAMPath, oldsram, 1024); EmuRunning = prevstatus; } } -int OnCloseWindow(uiWindow* window, void* blarg) +// SAVESTATE TODO +// * configurable paths. not everyone wants their ROM directory to be polluted, I guess. + +void GetSavestateName(int slot, char* filename, int len) { - if (RunningSomething) + int pos; + + if (ROMPath[0] == '\0') // running firmware, no ROM { - EmuRunning = 2; - while (EmuStatus != 2); + strcpy(filename, "firmware"); + pos = 8; + } + else + { + int l = strlen(ROMPath); + pos = l; + while (ROMPath[pos] != '.' && pos > 0) pos--; + if (pos == 0) pos = l; + + // avoid buffer overflow. shoddy + if (pos > len-5) pos = len-5; + + strncpy(&filename[0], ROMPath, pos); + } + strcpy(&filename[pos], ".ml"); + filename[pos+3] = '0'+slot; + filename[pos+4] = '\0'; +} + +void LoadState(int slot) +{ + int prevstatus = EmuRunning; + EmuRunning = 2; + while (EmuStatus != 2); + + char filename[1024]; + + if (slot > 0) + { + GetSavestateName(slot, filename, 1024); + } + else + { + char* file = uiOpenFile(MainWindow, "melonDS savestate (any)|*.ml1;*.ml2;*.ml3;*.ml4;*.ml5;*.ml6;*.ml7;*.ml8;*.mln", NULL); + if (!file) + { + EmuRunning = prevstatus; + return; + } + + strncpy(filename, file, 1023); + filename[1023] = '\0'; + uiFreeText(file); + } + + if (!FileExists(filename)) + { + EmuRunning = prevstatus; + return; + } + + // backup + Savestate* backup = new Savestate("timewarp.mln", true); + NDS::DoSavestate(backup); + delete backup; + + 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); + } + + NDS::DoSavestate(state); + delete state; + + if (Config::SavestateRelocSRAM && ROMPath[0]!='\0') + { + strncpy(PrevSRAMPath, SRAMPath, 1024); + + strncpy(SRAMPath, filename, 1019); + int len = strlen(SRAMPath); + strcpy(&SRAMPath[len], ".sav"); + SRAMPath[len+4] = '\0'; + + NDS::RelocateSave(SRAMPath, false); + } + + SavestateLoaded = true; + uiMenuItemEnable(MenuItem_UndoStateLoad); + + EmuRunning = prevstatus; +} + +void SaveState(int slot) +{ + int prevstatus = EmuRunning; + EmuRunning = 2; + while (EmuStatus != 2); + + char filename[1024]; + + if (slot > 0) + { + GetSavestateName(slot, filename, 1024); } + else + { + char* file = uiSaveFile(MainWindow, "melonDS savestate (*.mln)|*.mln", NULL); + if (!file) + { + EmuRunning = prevstatus; + return; + } + + strncpy(filename, file, 1023); + filename[1023] = '\0'; + uiFreeText(file); + } + + Savestate* state = new Savestate(filename, true); + if (state->Error) + { + delete state; + + uiMsgBoxError(MainWindow, "Error", "Could not save state."); + } + else + { + NDS::DoSavestate(state); + delete state; + + if (slot > 0) + uiMenuItemEnable(MenuItem_LoadStateSlot[slot-1]); + + if (Config::SavestateRelocSRAM && ROMPath[0]!='\0') + { + strncpy(SRAMPath, filename, 1019); + int len = strlen(SRAMPath); + strcpy(&SRAMPath[len], ".sav"); + SRAMPath[len+4] = '\0'; + + NDS::RelocateSave(SRAMPath, true); + } + } + + EmuRunning = prevstatus; +} + +void UndoStateLoad() +{ + if (!SavestateLoaded) return; + + int prevstatus = EmuRunning; + EmuRunning = 2; + while (EmuStatus != 2); + + // 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[0]!='\0') + { + strncpy(SRAMPath, PrevSRAMPath, 1024); + NDS::RelocateSave(SRAMPath, false); + } + + EmuRunning = prevstatus; +} + + +int OnCloseWindow(uiWindow* window, void* blarg) +{ + EmuRunning = 3; + while (EmuStatus != 3); uiQuit(); return 1; @@ -795,6 +1072,9 @@ void OnLoseFocus(uiWindow* window, void* blarg) void OnCloseByMenu(uiMenuItem* item, uiWindow* window, void* blarg) { + EmuRunning = 3; + while (EmuStatus != 3); + uiControlDestroy(uiControl(window)); uiQuit(); } @@ -816,6 +1096,23 @@ void OnOpenFile(uiMenuItem* item, uiWindow* window, void* blarg) uiFreeText(file); } +void OnSaveState(uiMenuItem* item, uiWindow* window, void* param) +{ + int slot = *(int*)param; + SaveState(slot); +} + +void OnLoadState(uiMenuItem* item, uiWindow* window, void* param) +{ + int slot = *(int*)param; + LoadState(slot); +} + +void OnUndoStateLoad(uiMenuItem* item, uiWindow* window, void* param) +{ + UndoStateLoad(); +} + void OnRun(uiMenuItem* item, uiWindow* window, void* blarg) { if (!RunningSomething) @@ -852,10 +1149,16 @@ void OnReset(uiMenuItem* item, uiWindow* window, void* blarg) EmuRunning = 2; while (EmuStatus != 2); + SavestateLoaded = false; + uiMenuItemDisable(MenuItem_UndoStateLoad); + if (ROMPath[0] == '\0') NDS::LoadBIOS(); else - NDS::LoadROM(ROMPath, Config::DirectBoot); + { + SetupSRAMPath(); + NDS::LoadROM(ROMPath, SRAMPath, Config::DirectBoot); + } Run(); } @@ -878,6 +1181,12 @@ void OnOpenInputConfig(uiMenuItem* item, uiWindow* window, void* blarg) } +void OnSetSavestateSRAMReloc(uiMenuItem* item, uiWindow* window, void* param) +{ + Config::SavestateRelocSRAM = uiMenuItemChecked(item) ? 1:0; +} + + void EnsureProperMinSize() { bool isHori = (ScreenRotation == 1 || ScreenRotation == 3); @@ -1005,15 +1314,6 @@ void ApplyNewSettings() } -bool _fileexists(char* name) -{ - FILE* f = fopen(name, "rb"); - if (!f) return false; - fclose(f); - return true; -} - - int main(int argc, char** argv) { srand(time(NULL)); @@ -1072,6 +1372,48 @@ int main(int argc, char** argv) menuitem = uiMenuAppendItem(menu, "Open ROM..."); uiMenuItemOnClicked(menuitem, OnOpenFile, NULL); uiMenuAppendSeparator(menu); + { + uiMenu* submenu = uiNewMenu("Save state"); + + for (int i = 0; i < 9; i++) + { + char name[32]; + if (i < 8) + sprintf(name, "%d\tShift+F%d", kSavestateNum[i], kSavestateNum[i]); + else + strcpy(name, "File...\tShift+F9"); + + uiMenuItem* ssitem = uiMenuAppendItem(submenu, name); + uiMenuItemOnClicked(ssitem, OnSaveState, (void*)&kSavestateNum[i]); + + MenuItem_SaveStateSlot[i] = ssitem; + } + + MenuItem_SaveState = uiMenuAppendSubmenu(menu, submenu); + } + { + uiMenu* submenu = uiNewMenu("Load state"); + + for (int i = 0; i < 9; i++) + { + char name[32]; + if (i < 8) + sprintf(name, "%d\tF%d", kSavestateNum[i], kSavestateNum[i]); + else + strcpy(name, "File...\tF9"); + + uiMenuItem* ssitem = uiMenuAppendItem(submenu, name); + uiMenuItemOnClicked(ssitem, OnLoadState, (void*)&kSavestateNum[i]); + + MenuItem_LoadStateSlot[i] = ssitem; + } + + MenuItem_LoadState = uiMenuAppendSubmenu(menu, submenu); + } + menuitem = uiMenuAppendItem(menu, "Undo state load\tF12"); + uiMenuItemOnClicked(menuitem, OnUndoStateLoad, NULL); + MenuItem_UndoStateLoad = menuitem; + uiMenuAppendSeparator(menu); menuitem = uiMenuAppendItem(menu, "Quit"); uiMenuItemOnClicked(menuitem, OnCloseByMenu, NULL); @@ -1096,6 +1438,15 @@ int main(int argc, char** argv) uiMenuItemOnClicked(menuitem, OnOpenInputConfig, NULL); uiMenuAppendSeparator(menu); { + uiMenu* submenu = uiNewMenu("Savestate settings"); + + MenuItem_SavestateSRAMReloc = uiMenuAppendCheckItem(submenu, "Separate savefiles"); + uiMenuItemOnClicked(MenuItem_SavestateSRAMReloc, OnSetSavestateSRAMReloc, NULL); + + uiMenuAppendSubmenu(menu, submenu); + } + uiMenuAppendSeparator(menu); + { uiMenu* submenu = uiNewMenu("Screen rotation"); for (int i = 0; i < 4; i++) @@ -1167,6 +1518,12 @@ int main(int argc, char** argv) uiWindowOnGetFocus(MainWindow, OnGetFocus, NULL); uiWindowOnLoseFocus(MainWindow, OnLoseFocus, NULL); + //uiMenuItemDisable(MenuItem_SaveState); + //uiMenuItemDisable(MenuItem_LoadState); + for (int i = 0; i < 9; i++) uiMenuItemDisable(MenuItem_SaveStateSlot[i]); + for (int i = 0; i < 9; i++) uiMenuItemDisable(MenuItem_LoadStateSlot[i]); + uiMenuItemDisable(MenuItem_UndoStateLoad); + uiMenuItemDisable(MenuItem_Pause); uiMenuItemDisable(MenuItem_Reset); uiMenuItemDisable(MenuItem_Stop); @@ -1195,6 +1552,8 @@ int main(int argc, char** argv) SANITIZE(ScreenSizing, 0, 3); #undef SANITIZE + uiMenuItemSetChecked(MenuItem_SavestateSRAMReloc, Config::SavestateRelocSRAM?1:0); + uiMenuItemSetChecked(MenuItem_ScreenRot[ScreenRotation], 1); uiMenuItemSetChecked(MenuItem_ScreenLayout[ScreenLayout], 1); uiMenuItemSetChecked(MenuItem_ScreenSizing[ScreenSizing], 1); @@ -1221,7 +1580,9 @@ int main(int argc, char** argv) strncpy(ROMPath, file, 1023); ROMPath[1023] = '\0'; - if (NDS::LoadROM(ROMPath, Config::DirectBoot)) + SetupSRAMPath(); + + if (NDS::LoadROM(ROMPath, SRAMPath, Config::DirectBoot)) Run(); } } |