Glulx/Quixe vm_save & vm_restore

Hello again, all. I’m hoping someone can help me understand how to properly save games. Right now, when I type save, I pop up a system file selection window, choose the save file, then grab the data generated by vm_save in quixe.js. Basically, instead of

Glk.glk_put_buffer_stream(str, quetzal);

I have

opt_save_func(quetzal);

Which then uses NodeJS fs.writeFileSync to output the data as utf8 to a file. This seems to go okay. However, when I reverse the process for restore, the data isn’t accepted. Specifically

vm_restore failed: file doesn't start with FORM/IFZS header

which suggests that unpack_iff_chunks(), quixe.js line 5876, “succeeded” but that there’s something wrong with the data that it returns.

Any help is appreciated!

Taking a step back, what are you trying to accomplish? Any reason you’re not just using electrofs.js?

If you post a sample save file, we could try to see what’s wrong with it.

Dannii’s question is also valid. :)

Honestly, wouldn’t even know how to interact with it. My terp doesn’t use Dialog at all, so I’m not sure how electro.fs would fit in to the whole thing. I’ve been making my own GlkOte, so I’ve been slowly reimplementing the functionality. I’ve got the interface feature where I want them so now I have to make sure it can save and load games so that it’s actually usable as an alternative IF player.

Here is the most recent output from my save code: Save Game.glksave - pCloud

Well, the obvious observation is that this is a list of byte values stored as ASCII integers separated by commas:

70,79,82,77,0,0,5,232,...

It would be usual to convert these to actual bytes in the output file.

Either way, when you load the file back in, you need to convert it to a JS array of integers:

[70,79,82,77,0,0,5,232,...]

That’s what unpack_iff_chunks() and so on are set up to handle.

If you’re already doing that, good, we can try the next question…

For what it’s worth, the save file appears to be valid once you decode the ASCII into bytes.

Zarf has explained it, but I would suggest considering again whether you could just use one of the Dialog libraries. Then you wouldn’t need to completely reimplement GlkOte and a filesystem system, just GlkOte. And it would make reimplementing GlkOte simpler as whenever it calls out to Dialog your implementation could too. One good thing about how Zarf has written Quixe et al is that the environment-dependent functionality is limited and isolated, so it’s not too hard to port it to new environments.

Eventually, I’m going to need to wrap save data in other data related to my terp. Would that still be viable (without using multiple files) while using Dialog?

That’s the bunny. I wasn’t converting to binary (which I’m now doing and see the FORM header :P) but more importantly I wasn’t properly converting the file’s contents back to an array of integers. Now that I do that, it loads fine.