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
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

View File

@ -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

View File

@ -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;
}

View File

@ -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 */

View File

@ -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<SaveState::SLOT_COUNT; i++) {
@ -9829,9 +9876,17 @@ int main(int argc, char* argv[]) SDL_MAIN_NOEXCEPT {
}
# 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");
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,"prev_page").set_text("Previous page").set_callback_function(prev_page_menu_callback);