It should be possible for even large .z8 stories like Anchorhead to run on an original Pico, even with full undo support.
The dynamic memory of the Z machine is capped at 64k, plus another 64k for an undo buffer, still leaves 128k of RAM for other stuff.
The static memory can be kept in flash on the Pico — it’s read-only. Copy the entire story file into flash, then make a copy of the dynamic part into normal memory. Then a restart is just a memcpy from flash. You can use way less than 64k for an undo buffer by just storing the differences between current dynamic memory and the original story data, which is how Quetzsal save compression works anyway, but it’s probably overkill.
Apologies if you knew this and already support it! Coincidentally, I too was working on a basic text / sdcard library with a language IDE, bit off more than I could chew, and got sidetracked implementing a Z machine, although I did it completely from scratch because I was inspired by mojozork doing the same thing.
No, I wasn’t planning to do this. My aim of this port was to capture the glory days of IF, text only on a phosphor display.
Changing times forced them to add images and sound. You don’t see either in novels, and from a purest IF point-of-view, they should not be there either.
Update README to reflect support for 64-column display
Add configuration settings globally or for each story (phosphor and width)
Add save path settings with directory listing
This release adds a settings file where you can set the phosphor colour and the number of columns on the story selection screen. You can also set which phosphor, number of columns and the location of saved stories for a particular story.
Also when saving or restoring your game, you can now get a list of the currently saved games.
This release will be the last feature release for a bit. I am moving on to another project, though I will make bug fixes or small updates going forward.
There’s no need to put anything into flash when the SD card is still there, and it’s not slow. You just read the high-memory blocks from the storyfile as and when they’re accessed, since they’re all read-only.
Frotz doesn’t directly support virtual memory (at least, all the extant versions back into the mists of time rely on the all-in-memory implementation in fastmem.c) but that doesn’t mean it couldn’t be implemented.
(not expecting you do do this, Blair! Thanks for everything you’ve already done!)
I really shouldn’t take on another project until I have the bootloader stuff squared away…
Yeah, I understand that’s how the ancient 8-bit interpreters worked (explains the disk access when playing Zork I on my 48k Apple 2 clone in the early 80’s!) but since flash is mapped to cpu visible memory and the sdcard is not, it’s far simpler IMO to just load the story into flash. The entire z machine (with some very limited VT100 terminal support baked in for testing on my laptop) is about 1600 lines of code (which I know isn’t the best metric, but still).
If Blair’s library had existed a month or two ago I wouldn’t have written mine, it was exactly what I was looking for at the time. And somebody finally put together a concise, simple audio driver example! Thank you Blair.
I’m not going to dictate what direction someone else should take with their own work; I just think flash is more trouble than it’s worth, especially since the Z-machine is specifically designed to be used this way.
(and my work on the bootloader keeps finding annoying edge cases with using flash dynamically so I’m predisposed to advise against it when there’s literally any alternative… )
It’s mostly around the question “what is the highest page you can write to without problems?”
My RP2040 bootloader lives at the top of flash, but it turns out I’m not the only thing trying to use that space - the BT stack on the pico_w also wants to store stuff up there, and I’ve seen discussion of other people wanting to use the high memory area as well. And on the RP2350 you could be in a partition that’s smaller than the true flash size.
So if you want to use flash for something other than the original application, just yolo-ing it might be fine, or it might crash in the most confusing ways. I write code for embedded devices in the field, so I’m hyper-fixated on robustness at all times, and the thought of having intermittent failures like that brings me out in hives. shudder
Ah, yeah, I can see how that would be an issue. It would be nice if there was some sort of standard, like this
struct FlashHeader {
uint32_t readBlockSize, eraseBlockSize, flashSizeInEraseBlocks;
uint8_t usageMask[0]; // one bit per erase block, lowest address in MSB.
};
with, obviously the size of the header itself marked off in the usage mask.
Well, if you’re managing a boot loader, you have the option of “creating” a standard and publishing a really simple library for people to use. There could be a header block with some magic string in it that code could search for if there isn’t a good fixed place for it, and 4k is enough space to store a tiny directory where allocations all have a human-readable name and provide functions to allocate private space (you pass in a FOURCC code for your application and a FOURCC code for your specific “document” and it will either allocate it for you or return the existing one).
Your boot loader could then display the current allocations and allow people to delete things to free up space. You could probably also have it compact / defragment memory too. If you were going that route, I’d allow for 8 or 12 bytes for the application “name” though so it’s human-readable.
Anyway, I’m getting wayy off topic now. Interactive fiction is great, you should all play it!
Took a quick look, and while you can “patch” Frotz by providing implementations of various os_... functions, it doesn’t seem like you can control memory the same way so Frotz itself, which is otherwise a submodule, would have to be forked and patched separately? But honestly I’m barely competent at git despite using it for years for personal projects.
Well, what I did was to include Frotz as a submodule in my repo, then I cherry pick the source files from that in the CMakeLists.txt file. So it would be easy to replace, say fastmem.c with one of your own design.