Plan for new save format
This plan is almost entirely complete. See RSAV for information about the new save format.
The current save format is a big binary file with fixed offsets. it is pretty messy, wastes a lot of space, and is inconvenient and bug-prone to extend.
A new save format would accomplish the following goals:
- Easier to extend while maintaining back/forward compatibility
- Each save slot should be one separate file (or folder?)
- Each type of save data should be a separate lump (or file?)
- Space should be provided for optionally storing things which are not already stored
- saved NPC state
- saved map state
- the script interpreter state: all currently running scripts
- other script object state such as strings or slices
- Some provisions should be made for RPG file upgrades obsoleting certain SAV data (this is a problem in the current SAV format for things like shop stock and hero spell lists)
- It is possible that this could be as simple as a game-specific version number that could be used to display a warning message about possible bugs when opening SAV files created with older versions of the same RPG file.
- Some of the items above, like script interpreter state, are going to be impossible to recover if the relevant game data (ie compiled scripts) has changed in the slightest, unless maybe a copy of the old data is available for examination (eg temporarily load old instead of new copy of script).
- It might make sense to store some kind of checksum or hash of this sort of upgrade-volatile data so that it can be invalidated if necessary at load-time.
- Old SAV files need to be convertible into the new format.
- The import globals and export globals commands will need to be re-written for the new format.
Contents
A modified proposal[edit]
Save game data will be a collection of files in a specially named subdirectory. On Windows this will be inside %APPDATA%\OHRRPGCE\GameName\ and on Linux it will be in $HOME/.ohrrpgce/GameName/ (see the prefsdir global var for access to this location)
Inside that location would be a folder named saves and inside that would be numbered RELOAD files, one for each save slot. So for example, save slot zero for Wandering Hamster being run by a user named Fred on Windows XP would be something like:
C:\Documents and Settings\Fred\Application Data\OHRRPGCE\wander\saves\0.rsav
Core functionality[edit]
See RSAV documentation
Extended functionality[edit]
Additional features that we can add one-by-one later.
Reload Node | Description |
---|---|
version | Contains the game's version number (optional: incremented by the game author) Obsolete game version number would show a warning before loading to tell the player they are using a save that may contain incorrect data for the new version of the game. (Unless the game author provides a on-obsolete-save script for this situation, which game authors can write. It would be run before the on-load script to automatically update things) |
mapstates | Map saved state containing the same data that is used for temporary map state saving (Note that the current temporary format takes twice as much space as necessary, presumably we'd get around to fixing it). |
plotstrings | Plotstrings: other state such as postion and color for each string |
scriptobjs | (*) Persistant storage of all non-integer script variables, including things like NPC extras, eg. strings, arrays, user defined objects. Would probably be same format as the lump doing the same thing in .RPG files. |
scrinterpreter | (*) A resumable dump of the script interpreter's state. |
slices | (*) Store state of slice tree (but what if a slice has a modified graphic, supposing that we ever add such support?) |
(*) - Currently only somewhat wishful thinking
The above should duplicate everything that the old .SAV format can store, plus a little, and it should be easy to extend.
Implementation plan[edit]
- Move all save code to a single module (done)
- separate public interfaces for saving/loading from old save game format saving/loading (done)
- Implement saving game state to a reload document (done)
- Implement writing a game state reload document to disk (done)
- Implement loading a game state reload document from disk (done)
- Implement restoring game state from a reload document (done)
- Implement reading old-style save data into a reload document (done)
- Implement reading just globals for scripting from a reload document (done)
- Implement reading just slot preview data from a reload document (done)
- Implement conversion of old save slots to new save slots
- After a successful conversion, it should move gamename.sav to gamename.sav.old
- Save and use new format by default (done)
- Remove all old save format code except the one for reading old save slots into reload documents
Sharing Data Between Games[edit]
Based on discussion, the best way to do this would probably be to allow games to read the globals of another game, either by ID number, or by name, or both. With the Plan for dynamic types in HamsterSpeak this will allow for sharing of not just integers, but also more complex data structures.
before-save scripts[edit]
A "before save" script trigger should be provided. As an argument it would get the slot number that the player has chosen to save into. This would make it easy for game authors to tie together the saving of shared data with the normal save system. (although there is no reason why shared data couldn't be read or written at other times too)