From a00a4ff9102b36232e5dead71dbecb5774d5ecfe Mon Sep 17 00:00:00 2001 From: Wengier Date: Tue, 13 Oct 2020 20:00:40 -0400 Subject: [PATCH] add support for save files etc --- CHANGELOG | 14 ++++++++--- include/dosbox.h | 2 +- src/dosbox.cpp | 28 ++++++++++++++------- src/gui/menu.cpp | 15 +++++++++-- src/gui/sdlmain.cpp | 61 ++++++++++++++++++++++++++++++++++++++++++--- 5 files changed, 102 insertions(+), 18 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 0706dc55b..907e01d70 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -13,10 +13,18 @@ "core=dynamic_x86" or "core=dynamic_rec" for either the dynamic_x86 core or the dynamic_rec core. Also thank joncampbell123 for the 64-bit fix. (Wengier) + - You can now use your own save file (in addition to + save slots! There are now a "Use save file" toggle + item and "Browse save file..." for browsing save + files on your computer. A new menu item "Display + state information" is added as well to display the + information of the saved state. (Wengier) - Save state feature now allows users to optionally - enter remarks when saving a state. A toggle menu - item "No remark when saving state" (in "Capture") - is added to disable input of remarks. (Wengier) + enter remarks when saving a state. A submenu group + "Save/load option" is added (under "Capture") where + you can toggle menu items "No remark when saving + state" (for disabling input of remarks when saving) + and "force load state mode". (Wengier) - DOSBox-X will now use native dialog box to display quit warnings and save state errors. (Wengier) - Updated the Windows installer to default to the diff --git a/include/dosbox.h b/include/dosbox.h index f4092b3ea..138d6fd23 100644 --- a/include/dosbox.h +++ b/include/dosbox.h @@ -299,7 +299,7 @@ public: void load (size_t slot) const; //throw (Error) bool isEmpty(size_t slot) const; void removeState(size_t slot) const; - std::string getName(size_t slot) const; + std::string getName(size_t slot, bool nl=false) const; //initialization: register relevant components on program startup struct Component diff --git a/src/dosbox.cpp b/src/dosbox.cpp index 4b690e8bc..578aadc87 100644 --- a/src/dosbox.cpp +++ b/src/dosbox.cpp @@ -310,6 +310,8 @@ unsigned long long update_clockdom_from_now(ClockDomain &dst) { #include "paging.h" +extern std::string savefilename; +extern bool use_save_file; extern bool rom_bios_vptable_enable; extern bool rom_bios_8x8_cga_font; extern bool allow_port_92_reset; @@ -783,7 +785,11 @@ void notifyError(const std::string& message, bool log=true) { if (log) LOG_MSG("%s",message.c_str()); #if !defined(HX_DOS) + MAPPER_ReleaseAllKeys(); + GFX_LosingFocus(); tinyfd_messageBox("Error",message.c_str(),"ok","error", 1); + MAPPER_ReleaseAllKeys(); + GFX_LosingFocus(); #endif } @@ -5095,7 +5101,7 @@ void SaveState::save(size_t slot) { //throw (Error) std::stringstream slotname; slotname << slot+1; temp=path; - std::string save=temp+slotname.str()+".sav"; + std::string save=use_save_file&&savefilename.size()?savefilename:temp+slotname.str()+".sav"; remove(save.c_str()); std::ofstream file (save.c_str()); file << ""; @@ -5224,7 +5230,11 @@ delete_all: void savestatecorrupt(const char* part) { LOG_MSG("Save state corrupted! Program in inconsistent state! - %s", part); #if !defined(HX_DOS) + MAPPER_ReleaseAllKeys(); + GFX_LosingFocus(); tinyfd_messageBox("Error","Save state corrupted! Program may not work.","ok","error", 1); + MAPPER_ReleaseAllKeys(); + GFX_LosingFocus(); #endif } @@ -5276,12 +5286,12 @@ void SaveState::load(size_t slot) const { //throw (Error) temp = path; std::stringstream slotname; slotname << slot+1; - std::string save=temp+slotname.str()+".sav"; + std::string save=use_save_file&&savefilename.size()?savefilename:temp+slotname.str()+".sav"; std::ifstream check_slot; check_slot.open(save.c_str(), std::ifstream::in); if(check_slot.fail()) { LOG_MSG("No saved slot - %d (%s)",(int)slot+1,save.c_str()); - notifyError("The selected save slot is an empty slot.", false); + notifyError(use_save_file&&savefilename.size()?"The selected save file is currently empty.":"The selected save slot is an empty slot.", false); load_err=true; return; } @@ -5548,7 +5558,7 @@ void SaveState::removeState(size_t slot) const { } } -std::string SaveState::getName(size_t slot) const { +std::string SaveState::getName(size_t slot, bool nl) const { if (slot >= SLOT_COUNT*MAX_PAGE) return "[Empty slot]"; std::string path; bool Get_Custom_SaveDir(std::string& savedir); @@ -5570,10 +5580,10 @@ std::string SaveState::getName(size_t slot) const { temp = path; std::stringstream slotname; slotname << slot+1; - std::string save=temp+slotname.str()+".sav"; + std::string save=nl&&use_save_file&&savefilename.size()?savefilename:temp+slotname.str()+".sav"; std::ifstream check_slot; check_slot.open(save.c_str(), std::ifstream::in); - if (check_slot.fail()) return "[Empty slot]"; + if (check_slot.fail()) return nl?"(Empty state)":"[Empty slot]"; my_miniunz((char **)save.c_str(),"Program_Name",temp.c_str()); std::ifstream check_title; int length = 8; @@ -5591,7 +5601,7 @@ std::string SaveState::getName(size_t slot) const { check_title.close(); remove(tempname.c_str()); buffer1[length]='\0'; - std::string ret="[Program: "+std::string(buffer1)+"]"; + std::string ret=nl?"Program: "+(!strlen(buffer1)?"-":std::string(buffer1))+"\n":"[Program: "+std::string(buffer1)+"]"; my_miniunz((char **)save.c_str(),"Time_Stamp",temp.c_str()); length=18; tempname = temp+"Time_Stamp"; @@ -5608,7 +5618,7 @@ std::string SaveState::getName(size_t slot) const { check_title.close(); remove(tempname.c_str()); buffer2[length]='\0'; - if (strlen(buffer2)) ret+=" ("+std::string(buffer2); + if (strlen(buffer2)) ret+=nl?"Timestamp: "+(!strlen(buffer2)?"-":std::string(buffer2))+"\n":" ("+std::string(buffer2); my_miniunz((char **)save.c_str(),"Save_Remark",temp.c_str()); length=30; tempname = temp+"Save_Remark"; @@ -5625,6 +5635,6 @@ std::string SaveState::getName(size_t slot) const { check_title.close(); remove(tempname.c_str()); buffer3[length]='\0'; - if (strlen(buffer3)) ret+=" - "+std::string(buffer3)+")"; + if (strlen(buffer3)) ret+=nl?"Remark: "+(!strlen(buffer3)?"-":std::string(buffer3))+"\n":" - "+std::string(buffer3)+")"; return ret; } diff --git a/src/gui/menu.cpp b/src/gui/menu.cpp index 61c121a4b..6317ef736 100644 --- a/src/gui/menu.cpp +++ b/src/gui/menu.cpp @@ -567,11 +567,13 @@ static const char *def_menu_capture[] = "mapper_caprawmidi", "--", #endif - "noremark_savestate", - "force_loadstate", + "saveoptionmenu", "mapper_savestate", "mapper_loadstate", "saveslotmenu", + "usesavefile", + "browsesavefile", + "showstate", NULL }; @@ -589,6 +591,14 @@ static const char *def_menu_capture_format[] = # endif #endif +/* Save/load options */ +static const char *save_load_options[] = +{ + "noremark_savestate", + "force_loadstate", + NULL +}; + /* Save slots */ static const char *def_save_slots[] = { @@ -1417,6 +1427,7 @@ void ConstructMenu(void) { ConstructSubMenu(mainMenu.get_item("CaptureFormatMenu").get_master_id(), def_menu_capture_format); # endif #endif + ConstructSubMenu(mainMenu.get_item("saveoptionmenu").get_master_id(), save_load_options); ConstructSubMenu(mainMenu.get_item("saveslotmenu").get_master_id(), def_save_slots); /* Drive menu */ diff --git a/src/gui/sdlmain.cpp b/src/gui/sdlmain.cpp index 637a985bb..353879946 100644 --- a/src/gui/sdlmain.cpp +++ b/src/gui/sdlmain.cpp @@ -45,7 +45,7 @@ extern bool noremark_save_state; extern bool force_load_state; extern bool use_quick_reboot; extern bool enable_config_as_shell_commands; -bool winrun=false; +bool winrun=false, use_save_file=false; bool direct_mouse_clipboard=false; #if defined(WIN32) extern int dos_clipboard_device_access; @@ -814,7 +814,7 @@ extern bool keep_private_area_on_boot; extern bool dos_kernel_disabled; bool guest_machine_power_on = false; -std::string custom_savedir; +std::string custom_savedir, savefilename = ""; void SHELL_Run(); void DisableINT33(); @@ -8446,6 +8446,53 @@ bool force_loadstate_menu_callback(DOSBoxMenu * const menu, DOSBoxMenu::item * c return true; } +bool browse_save_file_menu_callback(DOSBoxMenu * const menu, DOSBoxMenu::item * const menuitem) { + (void)menu;//UNUSED + const char *mname = menuitem->get_name().c_str(); + if (!strcmp(mname, "browsesavefile")&&!use_save_file) return false; + +#if !defined(HX_DOS) + char CurrentDir[512]; + char * Temp_CurrentDir = CurrentDir; + getcwd(Temp_CurrentDir, 512); + const char *lFilterPatterns[] = {"*.sav","*.SAV"}; + const char *lFilterDescription = "Save files (*.sav)"; + char const * lTheSaveFileName = tinyfd_saveFileDialog("Select an save file","",2,lFilterPatterns,lFilterDescription); + if (lTheSaveFileName!=NULL) { + savefilename = std::string(lTheSaveFileName); + mainMenu.get_item("usesavefile").set_text("Use save file"+(savefilename.size()?" ("+savefilename+")":"")).refresh_item(mainMenu); + } + chdir( Temp_CurrentDir ); +#endif + return true; +} + +bool use_save_file_menu_callback(DOSBoxMenu * const menu, DOSBoxMenu::item * const menuitem) { + (void)menu;//UNUSED + (void)menuitem;//UNUSED + if (use_save_file) use_save_file=false; + else if (savefilename.size()) use_save_file=true; + else { + browse_save_file_menu_callback(menu, menuitem); + if (savefilename.size()) use_save_file=true; + } + mainMenu.get_item("usesavefile").check(use_save_file).refresh_item(mainMenu); + mainMenu.get_item("browsesavefile").enable(use_save_file).refresh_item(mainMenu); + return true; +} + +bool show_save_state_menu_callback(DOSBoxMenu * const menu, DOSBoxMenu::item * const menuitem) { + (void)menu;//UNUSED + (void)menuitem;//UNUSED + MAPPER_ReleaseAllKeys(); + GFX_LosingFocus(); + std::string message = "Save to: "+(use_save_file&&savefilename.size()?"File "+savefilename:"Slot "+std::to_string(GetGameState_Run()+1))+"\n"+SaveState::instance().getName(GetGameState_Run(), true); + bool ret=tinyfd_messageBox("Saved state information", message.c_str(), "ok","info", 1); + MAPPER_ReleaseAllKeys(); + GFX_LosingFocus(); + return true; +} + void refresh_slots() { mainMenu.get_item("current_page").set_text("Current page: "+to_string(page+1)+"/10").refresh_item(mainMenu); for (unsigned int i=0; i