add support for save files etc

This commit is contained in:
Wengier 2020-10-13 20:00:40 -04:00
parent 7f1fce4689
commit a00a4ff910
5 changed files with 102 additions and 18 deletions

View File

@ -13,10 +13,18 @@
"core=dynamic_x86" or "core=dynamic_rec" for either "core=dynamic_x86" or "core=dynamic_rec" for either
the dynamic_x86 core or the dynamic_rec core. Also the dynamic_x86 core or the dynamic_rec core. Also
thank joncampbell123 for the 64-bit fix. (Wengier) 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 - Save state feature now allows users to optionally
enter remarks when saving a state. A toggle menu enter remarks when saving a state. A submenu group
item "No remark when saving state" (in "Capture") "Save/load option" is added (under "Capture") where
is added to disable input of remarks. (Wengier) 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 - DOSBox-X will now use native dialog box to display
quit warnings and save state errors. (Wengier) quit warnings and save state errors. (Wengier)
- Updated the Windows installer to default to the - Updated the Windows installer to default to the

View File

@ -299,7 +299,7 @@ public:
void load (size_t slot) const; //throw (Error) void load (size_t slot) const; //throw (Error)
bool isEmpty(size_t slot) const; bool isEmpty(size_t slot) const;
void removeState(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 //initialization: register relevant components on program startup
struct Component struct Component

View File

@ -310,6 +310,8 @@ unsigned long long update_clockdom_from_now(ClockDomain &dst) {
#include "paging.h" #include "paging.h"
extern std::string savefilename;
extern bool use_save_file;
extern bool rom_bios_vptable_enable; extern bool rom_bios_vptable_enable;
extern bool rom_bios_8x8_cga_font; extern bool rom_bios_8x8_cga_font;
extern bool allow_port_92_reset; 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 (log) LOG_MSG("%s",message.c_str());
#if !defined(HX_DOS) #if !defined(HX_DOS)
MAPPER_ReleaseAllKeys();
GFX_LosingFocus();
tinyfd_messageBox("Error",message.c_str(),"ok","error", 1); tinyfd_messageBox("Error",message.c_str(),"ok","error", 1);
MAPPER_ReleaseAllKeys();
GFX_LosingFocus();
#endif #endif
} }
@ -5095,7 +5101,7 @@ void SaveState::save(size_t slot) { //throw (Error)
std::stringstream slotname; std::stringstream slotname;
slotname << slot+1; slotname << slot+1;
temp=path; 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()); remove(save.c_str());
std::ofstream file (save.c_str()); std::ofstream file (save.c_str());
file << ""; file << "";
@ -5224,7 +5230,11 @@ delete_all:
void savestatecorrupt(const char* part) { void savestatecorrupt(const char* part) {
LOG_MSG("Save state corrupted! Program in inconsistent state! - %s", part); LOG_MSG("Save state corrupted! Program in inconsistent state! - %s", part);
#if !defined(HX_DOS) #if !defined(HX_DOS)
MAPPER_ReleaseAllKeys();
GFX_LosingFocus();
tinyfd_messageBox("Error","Save state corrupted! Program may not work.","ok","error", 1); tinyfd_messageBox("Error","Save state corrupted! Program may not work.","ok","error", 1);
MAPPER_ReleaseAllKeys();
GFX_LosingFocus();
#endif #endif
} }
@ -5276,12 +5286,12 @@ void SaveState::load(size_t slot) const { //throw (Error)
temp = path; temp = path;
std::stringstream slotname; std::stringstream slotname;
slotname << slot+1; 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; std::ifstream check_slot;
check_slot.open(save.c_str(), std::ifstream::in); check_slot.open(save.c_str(), std::ifstream::in);
if(check_slot.fail()) { if(check_slot.fail()) {
LOG_MSG("No saved slot - %d (%s)",(int)slot+1,save.c_str()); 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; load_err=true;
return; 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]"; if (slot >= SLOT_COUNT*MAX_PAGE) return "[Empty slot]";
std::string path; std::string path;
bool Get_Custom_SaveDir(std::string& savedir); bool Get_Custom_SaveDir(std::string& savedir);
@ -5570,10 +5580,10 @@ std::string SaveState::getName(size_t slot) const {
temp = path; temp = path;
std::stringstream slotname; std::stringstream slotname;
slotname << slot+1; 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; std::ifstream check_slot;
check_slot.open(save.c_str(), std::ifstream::in); 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()); my_miniunz((char **)save.c_str(),"Program_Name",temp.c_str());
std::ifstream check_title; std::ifstream check_title;
int length = 8; int length = 8;
@ -5591,7 +5601,7 @@ std::string SaveState::getName(size_t slot) const {
check_title.close(); check_title.close();
remove(tempname.c_str()); remove(tempname.c_str());
buffer1[length]='\0'; 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()); my_miniunz((char **)save.c_str(),"Time_Stamp",temp.c_str());
length=18; length=18;
tempname = temp+"Time_Stamp"; tempname = temp+"Time_Stamp";
@ -5608,7 +5618,7 @@ std::string SaveState::getName(size_t slot) const {
check_title.close(); check_title.close();
remove(tempname.c_str()); remove(tempname.c_str());
buffer2[length]='\0'; 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()); my_miniunz((char **)save.c_str(),"Save_Remark",temp.c_str());
length=30; length=30;
tempname = temp+"Save_Remark"; tempname = temp+"Save_Remark";
@ -5625,6 +5635,6 @@ std::string SaveState::getName(size_t slot) const {
check_title.close(); check_title.close();
remove(tempname.c_str()); remove(tempname.c_str());
buffer3[length]='\0'; 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; return ret;
} }

View File

@ -567,11 +567,13 @@ static const char *def_menu_capture[] =
"mapper_caprawmidi", "mapper_caprawmidi",
"--", "--",
#endif #endif
"noremark_savestate", "saveoptionmenu",
"force_loadstate",
"mapper_savestate", "mapper_savestate",
"mapper_loadstate", "mapper_loadstate",
"saveslotmenu", "saveslotmenu",
"usesavefile",
"browsesavefile",
"showstate",
NULL NULL
}; };
@ -589,6 +591,14 @@ static const char *def_menu_capture_format[] =
# endif # endif
#endif #endif
/* Save/load options */
static const char *save_load_options[] =
{
"noremark_savestate",
"force_loadstate",
NULL
};
/* Save slots */ /* Save slots */
static const char *def_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); ConstructSubMenu(mainMenu.get_item("CaptureFormatMenu").get_master_id(), def_menu_capture_format);
# endif # endif
#endif #endif
ConstructSubMenu(mainMenu.get_item("saveoptionmenu").get_master_id(), save_load_options);
ConstructSubMenu(mainMenu.get_item("saveslotmenu").get_master_id(), def_save_slots); ConstructSubMenu(mainMenu.get_item("saveslotmenu").get_master_id(), def_save_slots);
/* Drive menu */ /* Drive menu */

View File

@ -45,7 +45,7 @@ extern bool noremark_save_state;
extern bool force_load_state; extern bool force_load_state;
extern bool use_quick_reboot; extern bool use_quick_reboot;
extern bool enable_config_as_shell_commands; extern bool enable_config_as_shell_commands;
bool winrun=false; bool winrun=false, use_save_file=false;
bool direct_mouse_clipboard=false; bool direct_mouse_clipboard=false;
#if defined(WIN32) #if defined(WIN32)
extern int dos_clipboard_device_access; extern int dos_clipboard_device_access;
@ -814,7 +814,7 @@ extern bool keep_private_area_on_boot;
extern bool dos_kernel_disabled; extern bool dos_kernel_disabled;
bool guest_machine_power_on = false; bool guest_machine_power_on = false;
std::string custom_savedir; std::string custom_savedir, savefilename = "";
void SHELL_Run(); void SHELL_Run();
void DisableINT33(); void DisableINT33();
@ -8446,6 +8446,53 @@ bool force_loadstate_menu_callback(DOSBoxMenu * const menu, DOSBoxMenu::item * c
return true; 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() { void refresh_slots() {
mainMenu.get_item("current_page").set_text("Current page: "+to_string(page+1)+"/10").refresh_item(mainMenu); mainMenu.get_item("current_page").set_text("Current page: "+to_string(page+1)+"/10").refresh_item(mainMenu);
for (unsigned int i=0; i<SaveState::SLOT_COUNT; i++) { for (unsigned int i=0; i<SaveState::SLOT_COUNT; i++) {
@ -9829,9 +9876,17 @@ int main(int argc, char* argv[]) SDL_MAIN_NOEXCEPT {
} }
# endif # endif
{ {
DOSBoxMenu::item &item = mainMenu.alloc_item(DOSBoxMenu::submenu_type_id,"saveoptionmenu");
item.set_text("Save/load option");
}
{
DOSBoxMenu::item &item = mainMenu.alloc_item(DOSBoxMenu::submenu_type_id,"saveslotmenu"); DOSBoxMenu::item &item = mainMenu.alloc_item(DOSBoxMenu::submenu_type_id,"saveslotmenu");
item.set_text("Select save slot"); item.set_text("Select save slot");
}
{
mainMenu.alloc_item(DOSBoxMenu::item_type_id, "usesavefile").set_text("Use save file").set_callback_function(use_save_file_menu_callback).check(use_save_file);
mainMenu.alloc_item(DOSBoxMenu::item_type_id, "browsesavefile").set_text("Browse save file...").set_callback_function(browse_save_file_menu_callback).enable(use_save_file);
mainMenu.alloc_item(DOSBoxMenu::item_type_id, "showstate").set_text("Display state information").set_callback_function(show_save_state_menu_callback);
{ {
mainMenu.alloc_item(DOSBoxMenu::item_type_id,"current_page").set_text("Current page: 1/10").enable(false).set_callback_function(refresh_slots_menu_callback); mainMenu.alloc_item(DOSBoxMenu::item_type_id,"current_page").set_text("Current page: 1/10").enable(false).set_callback_function(refresh_slots_menu_callback);
mainMenu.alloc_item(DOSBoxMenu::item_type_id,"prev_page").set_text("Previous page").set_callback_function(prev_page_menu_callback); mainMenu.alloc_item(DOSBoxMenu::item_type_id,"prev_page").set_text("Previous page").set_callback_function(prev_page_menu_callback);