mirror of
https://github.com/joncampbell123/dosbox-x.git
synced 2025-06-15 05:40:46 +08:00
add support for save files etc
This commit is contained in:
parent
7f1fce4689
commit
a00a4ff910
14
CHANGELOG
14
CHANGELOG
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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 */
|
||||||
|
@ -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);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user