erkyrath / lectrote

The IF interpreter in an Electron shell
Other
248 stars 28 forks source link

Emglken autosaving #109

Open curiousdannii opened 6 years ago

curiousdannii commented 6 years ago

I've started working on getting autosaving to work for the Emglken VMs.

First hiccup: the games are loaded by creating a memory stream, as that's what most of the VMs want. But then when I call Glk.save_allstate() it wants to include the full memory stream in the JSON (stored the least efficient way possible.) Any ideas of how to exclude it?

One possibility: a new function akin to glkunix_stream_open_pathname_gen which would set a property on the stream to exclude it from save_allstate, and operating in memory rather than the file system. Though a file system version would also be useful for creating the profiling stream.

Or should save_allstate skip any streams with a rock of 0? There's not really any way for them to be meaningfully restored, is there? Or for non retained streams with a rock of 0 at least?

curiousdannii commented 6 years ago

Filtering out the game stream when autosaving is easy enough. But now I've run into the next problem: Glk won't restore the state because the game stream already exists. I'm wondering if I could make a fake stream instead, one that doesn't get inserted into gli_streamlist.

curiousdannii commented 6 years ago

After making a fake stream, and copying some code from iosstart.m, I have autosaves working in Glulxe :D

I still think something like glkunix_stream_open_pathname_gen could be worthwhile.

Qn: Quixe saves the random state, but iosGlulxe doesn't seem to. Am I right to think it should ideally be saved?

Edit: ah I see Glulxe is just using the libc seeded random feature, so there may not be a way to get the current state easily.

erkyrath commented 6 years ago

Long-term, it might be better to give the interpreters a "read the whole game file into memory and close the stream" option. (Could be a compile-time option.)

Of course who knows what "long term" means at this point, since I'm spending so little time on the interpreters any more.

Rock value isn't supposed to be meaningful; 0 is just a conventional default.

curiousdannii commented 6 years ago

Could be. That's how Git already is. But the stream reading code is deeply embedded in the terps, and I know almost nothing about how Hugo works internally.

curiousdannii commented 6 years ago

Continuing to make progress. I'm now getting the following error when trying to restore the Glk state:

Glulxe fatal error: Unable to re-find array argument in Glk call.

If I'm understanding correctly, I should either serialise arrays (from glkop.c) or else get the gidispatch_set_autorestore_registry functions working. If you could tell me what the bufkey and arrayref params of glulxe_array_restore mean, that would be a huge help!

Edit: Hmm, or do I comment out all calls to gli_register_arr and gli_unregister_arr etc, and track things only in the JS dispatch layer, and not also the C dispatch layer. That might work, I'll give it a try.

erkyrath commented 6 years ago

Gah, I haven't looked at this code in years...

glulxe_array_locate and glulxe_array_restore get handed to the library so that objects like glk_stream can be serialized and deserialized. glulxe_array_locate returns the VM address of a given retained array (the array that a memory stream is reading/writing to, for example.) The stream serializes this, along with the contents of the array.

glulxe_array_restore does the opposite: given a VM address (bufkey), it allocates a fresh array and hands it back (through arrayref). The memory stream stashes this as its retained array, fills it in with deserialized data, and then it's ready to continue operation.

The reason glulxe_array_restore needs the VM address info is that, when the memory stream is closed, that array will need to be shoved back into VM memory. This is handled entirely by glkop.c is normal operation. It only gets weird when you have to autosave/autorestore a live memstream.

curiousdannii commented 6 years ago

Sorry I didn't post an update. I think I mostly figured out these functions. Particularly tricky was that the bufkey was relative to memmap (but it does make sense). I'm not getting an errors currently, but the VM does seem to be quitting one turn after an autorestore. Will dig into that more soon.