Open ghost opened 6 years ago
I agree. It's just a matter of how to format and store/load the data to a file/directory, and a general architecture for each part of DOSBox-X to listen for and respond to load/save events.
Perhaps the VM event system could define a LOAD_STATE and SAVE_STATE event for other parts of DOSBox-X to register for?
By the way, not only would this help gamers, but it would also help the demoscene testing I do. If the demo crashes, I can roll back to a point prior to the crash and debug it easier.
The OP is kind of over simplificating things though no? Isn't the problem the persistent storage? saving RAM should be feasible, but you also need a snapshot of the whole filesystem and that could be anything...
Particularly if the user has a lot of active mountpoints.
Load/Save stating could be done incrementally, starting with simple things and working outward.
The filesystem stuff could be done a lot later.
Ignoring the filesystem, save/load states could be done for games that don't modify the filesystem.
Most software doesn't care if a file is there or not as long as they're not currently accessing it. And if they are accessing it, they probably don't care as long as the file hasn't changed across state loads. I'd say the filesystem is the least part to worry about.
Incidentally, it's very common for console emulators to not bother savestating the saved games (allowing you to not lose your proper saved progress if you go back to a previous savestate... and yes, that does technically result in time travel paradoxes, but let's not get started on that).
It is very recommended for every gamer at least to know the consequences of saving and loading states if the game he/she is playing commands the operating system (that is the emulator the gamer is using to play the game) to access some files on his/her disk/drive that are not saved in the state and know how to use these two functions wisely.
Even though saving and loading states may cause troubles if used wrongly, according to what you said in the comments, the developers of DOSBox Daum already implemented saving and loading states, but the emulator gives the gamer 10 slots only for all MS-DOS games.
In my feature request I wish that saving and loading states can be done with a file browser and not with limited 10 slots only for all games, like VisualBoyAdvance-M allows you to do this, but with GameBoy games only.
@buruto Agreed, you should be able to name your save states. Gamers however might appreciate a "quick load" and "quick save" shortcut though.
I don't suggest to remove the slots, I just suggest to append new "to file" item in the popup menu of "Save State" and append new "from file" item in the popup menu of "Load State".
This will be fine if there are still 10 slots to use for saving and loading states quickly in the emulator.
Note that VisualBoyAdvance-M also gives the gamer 10 slots to use for saving and loading states in addition to the "to file" item in the "Save State" popup menu and "from file" item in the "Load State" popup menu.
Quick load and quick save could work on the last loaded state (and if no state has been used yet, they work like their "slower" counterparts i.e. explicitly bring up the file dialog).
Also would be probably a very good idea to keep track of the last state used ever to always default to said folder (even across sessions). Nothing more annoying than having to browse back to where you store your files every single time, especially if to reach there you need to go through a crowded folder.
Oh, and the slots idea is probably awful if it's not per-software (otherwise you will get annoyed when you run out of slots - I have this issue with save slots in Doom mods and it really irks me >_>). And the emulator can't just rely on the executable due to games that are spread across multiple executables that are run in sequence.
Also I just wondered about the idea that instead of savestate files there could be savestate archives (each holding multiple slots).
You mean 10 archives and each archive contains 10 slots and in total 100 slots per game?
Sounds like a great idea!
Note that I am not for removing slotted states, but I will be for adding more extra states and that states will be per game and not for all games, I just want to say that saving with file browsing can allow the gamer to name the state.
I know that these options to save state to file and load state from file won't be used frequently and often, but this is still can be very useful sometimes, if for example, the gamer plays a puzzle game that has a lot of puzzles, but the game doesn't allow the gamer to start playing any puzzle quickly and if the gamer wants to play any puzzle of the game quickly then he/she can save new state for each new puzzle he/she arrives and gives it the name of the new puzzle that he/she arrived.
At last he/she will have a state for each puzzle of the game and he/she can load state the puzzle he/she wants to play right now, but in order to recognize the states, this can be very useful if he/she can name the states as the names of the puzzles.
Also there can be unique and special states that the gamer will want to experience over and over again, because he/she likes these states, because these states are fun and exciting for him/her and make him/her laugh, and this can be very bothersome to reach these states from the beginning of the game over and over again, so he/she can actually save all these states and for each give it a unique and special name since these states are unique and special for him/her.
These states won't be loaded frequently, but sometimes yes why not.
This is always better to have more options, settings and functions in the software, even if they are not necessary and won't be used frequently and often, as long as this is not too hard, difficult, complicated, complex and take too much time to implement them.
I know that saving state to a file and loading state to a file features is not big effort to implement at all if in windows you already have the GetSaveFileName and GetOpenFileName Win32 API functions. The file browser is already implemented in windows by Microsoft, so this should not be a question and doesn't worth a consideration if to implement this feature or not.
Just do it to satisfy more gamers.
Even though you say that saving state to a file and loading state from a file is not necessary and this is another waste of time, the developers of VisualBoyAdvance-M already implemented this feature with GameBoy games, because they already know what I already know what this feature can be used for.
You mean 10 archives and each archive contains 10 slots and in total 100 slots per game?
Where did you get 10 archives? @_@
The idea is you have 1 archive per game (or whatever you want to keep state of) and each archive holds e.g. 10 slots (or however many are implemented). This way you can keep slots separate for each game easily without having to implement complex error-prone logic in the emulator to guess what game it actually belongs to.
And in case you wonder: yes, the archives are the ones you'd be loading with the file dialog.
Random remark: the traditional 10 slot limit comes from mapping them to number keys on the keyboard (i.e. it's arbitrary based entirely on how many shortcuts you're willing to implement). There's nothing preventing the emulator from offering even more slots (in a less convenient way).
I know that saving state to a file and loading state to a file features is not big effort to implement at all if in windows you already have the GetSaveFileName and GetOpenFileName Win32 API functions. The file browser is already implemented in windows by Microsoft, so this should not be a question and doesn't worth a consideration if to implement this feature or not.
DOSBox-X supports more than just Windows so it'd probably end up using whatever it already uses internally instead.
I will be satisfied if this feature is at least available in windows.
Just to note, there are similar issues at https://github.com/joncampbell123/dosbox-x/issues/166 and https://github.com/joncampbell123/dosbox-x/issues/246
Maybe those should be closed if this is the active issue? https://github.com/joncampbell123/dosbox-x/issues/246 has a couple links to some code that I think is from DOSBox SVN Daum.
There seems to be so focused on the GUI/user experience, I do think that's just... tiny details compared with the real task of supporting save states :P
Yes. Function over form. Getting a save state implementation started and working first is more important than the GUI to drive it.
The initial GUI will likely be a list of save state slots in the menu. I envision the menu showing 10 save state slots. If all slots are filled, then it will show an 11th, then a 12th, etc. to allow more than 10 (up to 100).
Future ideas:
It might be helpful to the user to allow them to name the save states (and show that name in the menu).
A quick load shortcut would load the most recently selected save state.
Not certain yet if to add a quick save or what it would do.
The user might appreciate the ability to delete slots as well.
To simplify examining save states, the save state file would use the ZIP file format (uncompressed to keep it simple at first, then eventually deflate compression would be added) and store the bits of data in that. Examining the contents would be as simple as unpacking the file with your favorite archiver tool (7-zip, pkunzip, etc.). It would enable each part of DOSBox-X to store their data by name in one file.
Emulation will change over time as will the saved data, so it would help if the save state included a version number that changes whenever the saved data format changes. Newer versions of DOSBox-X could import older saves and older versions would know the data is a newer format it can't understand.
The overall collection of save state slots would be stored by default in a "general save states" folder in the current working directory of the process. At any time, the UI should allow the user to choose a different folder name to define the save state slots. The user can have one folder for DOOM save states, another for Descent, etc.
The ZIP format is not very complicated at all, it's actually a pretty simple format to support and the specification is open and free.
Don't get wrapped up in file permissions and certificates and junk like that and ZIP is very straightforward. You can use zlib for ZIP compression easily.
The overall collection of save state slots would be stored by default in a "general save states" folder in the current working directory of the process. At any time, the UI should allow the user to choose a different folder name to define the save state slots. The user can have one folder for DOOM save states, another for Descent, etc.
This is precisely where I was going with the archive idea.
The problem is that in our case there's no clear boundary between games (unlike most emulators, where a game is loaded directly within the emulator UI instead of being part of the emulated environment) and you definitely don't want to have a limited number of slots to be shared among them - and determining where to leave the boundaries is something you want to figure out before starting to implement savestates.
Most logical thing is to actually ditch slots and focus on individual states loaded directly from files (especially since slots are rather pointless if they can't be picked quickly with shortcuts anyway). But thinking on the organization and accounting for with it may need can be a good idea before it turns into a mess.
Of course there's no clear boundary between games, that's what the folder selection is for. You select the folder and the save states are managed there (slots or not).
Perhaps dosbox.conf could also specify the save state folder at startup as well.
I just committed new code, a very basic ZIP reader/writer (uncompressed only) to build save state code on and two VM events that code can register for to respond to save state/load state events.
I will be glad when the feature has been implemented.
@joncampbell123 just food for thought. Would it be possible to make savestates to a memory buffer first.
Then the frontend code would flush them/read them to/from disk. Just asking because it would help people like me trying to port dosbox-x to libretro or openemu to have feature parity.
I'm almost there with dosbox-svn-libretro, once I'm done I'll tackle dosbox-x in the most upstream friendly manner I can.
It could, but that's potentially a lot of memory to allocate.
Remember that DOSBox-X supports memsize up to about 2GB.
The ZIPFile interface could support allocating a 4MB buffer and writing through that to help though, since it's abstract enough.
okay
I've written the basic load/save state code, and some example code to load/save VGA and system memory. It's not stable to use yet, of course, since CPU state isn't saved yet, but it's the start.
"10 slots only for all games" rings a lot of bells. Please allow a .conf entry to define the savestates to be used (i.e. a save states group name). If the entry is not available, use the default set.
Now, if you launch games/apps/demos individually with their own conf, you would only see save states according to the individual game/app/demo.
Spoiler: I'm an emulation frontend dev 😛
(edit) ignore me, you already had that idea in mind (save state folder in .conf)
joncampbell123 where are you going to upload your newest version of DOSBox-X with my feature when you think that it is ready to be uploaded?
Are you going to provide a link in a comment that allows everyone to download your newest version of DOSBox-X with my feature?
@buruto You need a beta release binary? I suppose I could spin up VS2017 tonight and put one out in the Releases section for Windows.
It's not going to be usable for a long time considering the amount of state involved, but it will develop over time and the groundwork has already been laid for the save/load state function.
@buruto I believe the save/load event handling is straightforward enough to figure out and add on to when modifying the source code. If it's not, I can answer questions about it here. Are you able to work on the save/load state functions @buruto?
I have some suggestions to help keep the state human-readable where necessary when debugging is needed, ideally as name=value pairs in plain text. Storing the CPU registers as register=hexadecimal text, for example.
The idea behind using the ZIP container is that virtually everything out there can unpack it's contents, even Windows itself. As save/load state develops it's going to be important for debugging reasons to be able to examine the saved state for errors and verify it's being loaded back into DOSBox-X properly.
I just finished the code so that it saves/loads system memory, VGA memory, and basic CPU state (it does not yet load/save protected mode registers). As long as you load/save games that have similar state, that don't touch files too often, that don't use EMS/XMS or don't change anything related to XMS/EMS, save/load actually works quite well.
Games that save/load well so far:
Some games act a bit funny:
joncampbell123 your last comment makes me happy.
Thank you very much.
I want to try your build.
All what you need to do now is simply provide a link that clicking on it downloads your build to the downloader's machine.
I am aware that the functions are not complete yet and I am ready to deal with some issues, but at least this is better to have a function that works sometimes rather than not having a function that does the work/job at all, at least for me.
@buruto How is the build?
Hostkey+F1 to save state. Hostkey+F2 to load state.
Host key is F11 on Windows, F12 on any other system.
For best practices on savestates, just look at the tasing emulators.
joncampbell123, I don't find it better than DOSBox Daum, because DOSBox Daum already allows saving and loading states up to 10 slots both through menus (with mouse) and through keyboard only.
In DOSBox Daum, press Alt+F5 to save state to current slot and Alt+F9 to load state from current slot or Alt+F9 to save and Alt+F5 to load I just don't remember right now, but it doesn't matter.
This is excellent what you have done right now and this should be like this, but for me this gonna be even better if you add new "save state to file" and "load state from file" items to the "Main" popup menu.
Clicking "save state to file" Main's popup menu item invokes GetSaveFileName function (of windows) and GetSaveFileName shows the file browser of windows.
Then, through the file browser, the user selects the path and the name of the state to be saved and when he/she clicks the "Save" button of the file browser of windows, the file browser of windows disappears and the emulator saves the current state to the file selected by the user in the file browser.
Clicking "load state from file" Main's popup menu item invokes GetOpenFileName function (of windows) and GetOpenFileName shows the file browser of windows.
Then, through the file browser, the user selects the path and the name of the state to be loaded and when he/she clicks the "Open" button of the file browser of windows, the file browser of windows disappears and the emulator loads from selected file the state and overwrites the current state.
My request was that saving and loading states will be done with file browsing, because this cannot be done with DOSBox Daum, but thank you very much for your effort and time for implementing the hard part of my feature.
Implementing the other and final part of my feature should be easy in windows, but I appreciate you.
@buruto Of course that's the future plan. What was added now is the base foundation that will grow into file selection and slots.
Note how the save state system allows the code to specify ANY file name, even though it's currently hardcoded to a fixed filename.
@joncampbell123 I completely understand you. This is okay and alright, take your time, I am not rushing.
I am patient person.
From my experience, I already know that coding, programming, implementing, developing and analyzing algorithms and applications is one of the hardest tasks in the universe in general.
By the way, I downloaded the latest version of your DOSBox-X emulator and I did save state with F11+F1 and load state with F11+F2 and it worked.
I think that this is the time to remove the hard code limitation and implementing the GUI of the feature.
I think that this is over.
I just tried the F11+F1 / F11+F2 to save and reload but it doesn't manage to load the saved state due to a "memory size mismatch" :/ I'm using the latest version of DOSBox-X. Is there any progress on this feature? It would really be great.
That error means you changed the memory size from the last snapshot.
I'm going to be too busy in the coming months to implement much more, but I can provide guidance on how to develop it. Are you interested?
That error means you changed the memory size from the last snapshot.
Interesting, because I was just trying to test the feature, so I saved, moved my character a little bit to the right, and then tried to load, but nothing happened. So I don't know how the memory size could have changed in between.
I'm going to be too busy in the coming months to implement much more
That's totally understandable, it's no problem. I merely wanted this to help my girlfriend play the old Rayman DOS game with quick saves.
but I can provide guidance on how to develop it. Are you interested?
I really don't feel familiar enough with the domain to contribute, unfortunately, but thanks for being willing to help.
You all realize that dosbox-x can leverage qcow2 filesystem images to create differencing disks for filesystem snapshots, right? That can be adapted for save states pretty easily I would think.
qcow2 is how I maintain unique pristine Windows environments for each of my games without wasting tons of disk space on multiple Windows installs. Beneficial side-effects include: No Windows rot. Easy restore to freshly installed state. No game requirement conflicts (direct-x, quicktime, etc.) It's really the best of all worlds.
I can finally close this, because the feature has already been implemented in the most recent, latest, newest DOSBox-X version!
Reopened, because a bug issue was found in the both save and load state feature. I will permanently close this once the bug issue is resolved and there won't be a new one.
I've tried this save state thing in a game in a guest OS, and as you know, guest OSes have a tendency to crash and hang, plus it's completely impossible to load what you have stored in the guest OS, if the DOSBox has been quitted first, probably because you are going to create a paradox. So my idea is for someone to add a section that means you won't change anything in the mounted folders, even if you do something in DOSBox that would normally make changes to the mounted folders, which would also mean that the changes won't will be there the next time you start DOSBox-X. It will be the same as when you play any DOS game in the DOSBox in archive.org. I doubt if something like that would prevent the creation of paradoxes to begin with, but it might be a start, unless someone else has a better idea. I also don't know if there is such a function in DOSBox-X already either, clearly because I don't know what to call such a section.
I've tried the saving and loading thing for the first time a few days ago and yes, that bug is still there. Are you still working on the case? I see that this issue was reopened on 2 December 2020, almost 2 years ago. I still think my idea wasn't bad.
Has anyone tried to find the bug in the save file itself? I know it can be opened with, for example, a hex editor and notepad - unfortunately I don't understand any of what the text in the save file means. Only one save file appears, even if I save other times, and I don't know if it should actually be like that. Personally, I don't mind editing something on the save file, if that would be the only solution.
@BridgeHeadland - on the "only one save file" - there are different ways to create/load saves, in some 100 files/slots can be saved: The "Capture" menu
DOSBox-X will be a great emulator if it will allow the gamer to save and load named states with file browser whenever he/she wants exactly like you can do in VisualBoyAdvance-M emulator.
There are old MS-DOS games that have limited number of saved games allowed and there are also old MS-DOS games that doesn't allow the gamer to save the game at all.
There are also old MS-DOS games that save the game by checkpoints but this is not the same as save state.
This means that the gamer cannot save the game at any time or whenever he/she wants.
There are also old MS-DOS games that allow the gamer to save the game but without allowing the gamer to specify a name for the saved game, but the game itself decides the name for the saved game.
States can be very useful to save all gamer's progress in the MS-DOS game that he/she is playing and continue exactly from where he/she left off.
Theoretically the emulator can allow the gamer to save and load state at any time or whenever he/she wants.
I already know that DOSBox Daum allows the gamer to save and load states but this is limited.
DOSBox Daum has only 10 slots for saving and loading states for all MS-DOS games!
10 slots is too few and can run out very quickly.
Also named states are better than slotted states, because named states are more readable than slotted states.
When the gamer sees a named state he/she can remembers both immediately and quickly what is this state and what it is for and he/she can predict what will happen if he/she will load this state.
Slotted states are very difficult to remember if they are very old and a lot of time has passed since the last time the slotted state was loaded.
If the gamer cannot remember what is this slotted state and what is it for and cannot predict what will happen if he/she will load this state then he/she will have to load this slotted state to see what it is and overwrite the current state of the emulator. If the gamer doesn't want to lose progress he/she will have to save another state of the current state in another slot if available just to see what the slotted state is. If there is no slot available the gamer will have to overwrite existing slot or overwrite current state and all this is frustrating indeed.
Like in VisualBoyAdvance-M emulator that allows the gamer to save state to a file and load state from a file with a file browser, this is going to be very cool and nice if DOSBox-X emulator will also allow the gamer to save state to a file and load state from a file too by using a file browser.
Using file browser in windows is pretty easy.
When saving state simply invoke GetSaveFileName function.
When loading state simply invoke GetOpenFileName function.
This is so simple.
You can see DOSBox Daum C++ source code to learn how does the emulator save and load states.