diff options
Diffstat (limited to 'src/libui_sdl')
-rw-r--r-- | src/libui_sdl/DlgEmuSettings.cpp | 2 | ||||
-rw-r--r-- | src/libui_sdl/DlgEmuSettings.h | 2 | ||||
-rw-r--r-- | src/libui_sdl/DlgInputConfig.cpp | 4 | ||||
-rw-r--r-- | src/libui_sdl/DlgInputConfig.h | 2 | ||||
-rw-r--r-- | src/libui_sdl/Platform.cpp | 2 | ||||
-rw-r--r-- | src/libui_sdl/libui/unix/area.c | 4 | ||||
-rw-r--r-- | src/libui_sdl/libui/unix/menu.c | 17 | ||||
-rw-r--r-- | src/libui_sdl/main.cpp | 401 |
8 files changed, 401 insertions, 33 deletions
diff --git a/src/libui_sdl/DlgEmuSettings.cpp b/src/libui_sdl/DlgEmuSettings.cpp index 8cb2ccc..77bb18e 100644 --- a/src/libui_sdl/DlgEmuSettings.cpp +++ b/src/libui_sdl/DlgEmuSettings.cpp @@ -1,5 +1,5 @@ /* - Copyright 2016-2017 StapleButter + Copyright 2016-2019 StapleButter This file is part of melonDS. diff --git a/src/libui_sdl/DlgEmuSettings.h b/src/libui_sdl/DlgEmuSettings.h index f26ae14..f8da148 100644 --- a/src/libui_sdl/DlgEmuSettings.h +++ b/src/libui_sdl/DlgEmuSettings.h @@ -1,5 +1,5 @@ /* - Copyright 2016-2017 StapleButter + Copyright 2016-2019 StapleButter This file is part of melonDS. diff --git a/src/libui_sdl/DlgInputConfig.cpp b/src/libui_sdl/DlgInputConfig.cpp index 5a98a91..6496307 100644 --- a/src/libui_sdl/DlgInputConfig.cpp +++ b/src/libui_sdl/DlgInputConfig.cpp @@ -1,5 +1,5 @@ /* - Copyright 2016-2017 StapleButter + Copyright 2016-2019 StapleButter This file is part of melonDS. @@ -309,7 +309,7 @@ void Open() uiBoxAppend(in_ctrl, uiControl(g_key), 1); uiGrid* b_key = uiNewGrid(); uiGroupSetChild(g_key, uiControl(b_key)); - + const int width = 120; for (int i = 0; i < 12; i++) diff --git a/src/libui_sdl/DlgInputConfig.h b/src/libui_sdl/DlgInputConfig.h index 33529c2..c044016 100644 --- a/src/libui_sdl/DlgInputConfig.h +++ b/src/libui_sdl/DlgInputConfig.h @@ -1,5 +1,5 @@ /* - Copyright 2016-2017 StapleButter + Copyright 2016-2019 StapleButter This file is part of melonDS. diff --git a/src/libui_sdl/Platform.cpp b/src/libui_sdl/Platform.cpp index 80aa0e9..0c29f6b 100644 --- a/src/libui_sdl/Platform.cpp +++ b/src/libui_sdl/Platform.cpp @@ -1,5 +1,5 @@ /* - Copyright 2016-2017 StapleButter + Copyright 2016-2019 StapleButter This file is part of melonDS. diff --git a/src/libui_sdl/libui/unix/area.c b/src/libui_sdl/libui/unix/area.c index ea31676..40f8624 100644 --- a/src/libui_sdl/libui/unix/area.c +++ b/src/libui_sdl/libui/unix/area.c @@ -77,6 +77,10 @@ static void areaWidget_init(areaWidget *aw) static void areaWidget_dispose(GObject *obj) { + // remove any draw order that might still be pending + areaWidget *aw = areaWidget(obj); + while (g_idle_remove_by_data(aw->a)); + G_OBJECT_CLASS(areaWidget_parent_class)->dispose(obj); } diff --git a/src/libui_sdl/libui/unix/menu.c b/src/libui_sdl/libui/unix/menu.c index d6aa398..d641426 100644 --- a/src/libui_sdl/libui/unix/menu.c +++ b/src/libui_sdl/libui/unix/menu.c @@ -305,13 +305,13 @@ static void appendMenuItem(GtkMenuShell *submenu, uiMenuItem *item, uiWindow *w) { int j; uiMenu* m; - GtkWidget *submenu; + GtkWidget *c_submenu; m = item->popupchild; - submenu = gtk_menu_new(); - gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), submenu); + c_submenu = gtk_menu_new(); + gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), c_submenu); for (j = 0; j < m->items->len; j++) - appendMenuItem(GTK_MENU_SHELL(submenu), g_array_index(m->items, uiMenuItem *, j), w); + appendMenuItem(GTK_MENU_SHELL(c_submenu), g_array_index(m->items, uiMenuItem *, j), w); } } @@ -347,6 +347,7 @@ GtkWidget *makeMenubar(uiWindow *w) struct freeMenuItemData { GArray *items; guint i; + guint* parent_i; }; static void freeMenu(GtkWidget *widget, gpointer data); @@ -359,7 +360,7 @@ static void freeMenuItem(GtkWidget *widget, gpointer data) item = g_array_index(fmi->items, uiMenuItem *, fmi->i); if (item->popupchild != NULL) - freeMenu(widget, &item->popupchild->id); + freeMenu(widget, fmi->parent_i);//&item->popupchild->id); w = (struct menuItemWindow *) g_hash_table_lookup(item->windows, widget); if (g_hash_table_remove(item->windows, widget) == FALSE) implbug("GtkMenuItem %p not in menu item's item/window map", widget); @@ -374,14 +375,16 @@ static void freeMenu(GtkWidget *widget, gpointer data) GtkMenuItem *item; GtkWidget *submenu; struct freeMenuItemData fmi; - + m = g_array_index(menus, uiMenu *, *i); item = GTK_MENU_ITEM(widget); submenu = gtk_menu_item_get_submenu(item); fmi.items = m->items; fmi.i = 0; - gtk_container_foreach(GTK_CONTAINER(submenu), freeMenuItem, &fmi); (*i)++; + fmi.parent_i = i; + gtk_container_foreach(GTK_CONTAINER(submenu), freeMenuItem, &fmi); + //(*i)++; } void freeMenubar(GtkWidget *mb) 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(); } } |