Re: [hatari-devel] Hatari state save/restore for Falcon emulation |
[ Thread Index |
Date Index
| More lists.tuxfamily.org/hatari-devel Archives
]
Le 22/09/2014 23:49, Eero Tamminen a écrit :
And if the version is same, but content turns out to be incompatible
(e.g. wrong lenght) after loading, should emulation be able to
revert the state change?
(Reverting could be done by writing current state to a temporary
file before trying to restore user given state file.)
If you consider that each component is saved with a structure that
contains :
- a component ID
- a version ID
- size of the structure in bytes
- data for this component
Then you can easily walk through the savestate, parse only the component
where the ID is recognized and adapt the parsing depending on the
version ID of the saved component.
This requires that you can't have same version ID for a component if the
data has a different meaning between 2 Hatari versions, so the risk of
loading incompatible data is lowered (it could still happen if savestate
gets corrupted)
The size of the structure in bytes has 2 meaning :
- if you encounter a block with an unknown component ID, then you can
skip it by reading as many bytes as in "size of the structure", and you
will point to the next block to parse (so for example some winuae's
specific component (MMU for example) could be ignored when trying to
load a snapshot made with Hatari "new winuae core" into Hataro "old uae
core"
- if you encounter a known block, then you can check that the size
matches the expected size for given version of the component (for
example, you expect the YM2149 part version 1.8.0 to be 60 bytes,else
there's an error in the saved component you're tryring to restore).
This way, we could also keep previous snapshots and use them with more
recent version of Hatari, which can be useful if you use snapshot to
save some games' progress (this is something that is possible with
WinUAE or Steem since years for example, and I think it's a good
feature).
What do you think ?
Sounds good. It would require either saving all of them to
separate files (instead of filename, user could select state save
directory), or completely rewriting how state saving is currently
done in Hatari.
I think we could save everything to the same file as we do today, then
compressing the result.
The components' version could be similar to the Hatari's version. So we
would start with "1.8.0" for example.
Then when Hatari 1.8.1 is released, all component that were not modified
would keep their 1.8.0 version, only updated component would have a
version's change to indicate a difference (eg a new fdc.c component
could have version 1.8.1)
Now what would be good is that "fdc 1.8.1" be able to load an older
snapshot made with "fdc 1.8.0", but this can become quite hard to do the
transition between this old state and the new one, as we're only dealing
with bytes, sometimes a component is just a whole structure written to
the savestate, and nothing more, with no indication of what is in the
structure. This means for example fdc.c 1.8.1 would need to know how to
parse 1.8.1, but also all previous state versions to be able to add the
missing default values.
In the end, to achieve this, I wonder if a savestate file should not be
stored as text and not as byte, this way you can easily store each data
as a "key=value" pair.
This way, it's easier when loading a savestate to look for key
"videomode" for example. If it's found, you use the value, else you use
a default value.
Using "key=value" pairs make sense only for structures used to emulate
each component (video, fdc, sound, acia, cpu, ...) but to save the
content of the RAM for example, we would still store it as byte, not as
text.
So, code wise we could have sthg like :
structure component {
int component_id,
char version[8],
int size,
void *data
}
then data would point to another structure made of several "key" =
"value" with a type (indicating if value
structure {
int size, /* size of this structure */
char *key, /* '\0' terminated */
void *value, /* as many bytes as "size - strlen( key ) */
}
Then we would have an API such as MemorySnapShot_Store to save each
"key=value" (eg State_Store ( "ram" , pRamStart , RamSize ) )
We would also need some functions to start and close a components block.
In the end, this looks a lot like a config file, where we have sections
between [], then values for each section are stored with key=value.
Difference with a config file is that this would not necessarily be
stored as plain text (but plain text could be an option, this way a
memory file could even be loaded in a text editor)
Well, that's just some random thoughts I had since some times about the
savestate format, feel free to add your own idea.
Nicolas