Does anyone have any experience with implementing the Z-machine in BASIC?
I’m playing about with writing one (initially for v3) for the obscure Colour Maximite (http://geoffg.net/maximite.html) - this is an odd little machine which is really a 32-bit microcontroller that has been convinced it is an 8-bit microcomputer. Because of how it works the only development language available for it is BASIC unless you actually want to reprogram the flash on the microcontroller itself.
It’s only got ~80K RAM to play with, but it does have an SD card that I can use to page the Z-machine’s static memory from. That sounds like it might just be enough, but BASIC is not the most memory efficient language so I’m wondering whether the task is even possible, can anyone offer any insight?
Note that even if I succeed I doubt there are half a dozen potential users, so this is really just for my own entertainment / a technical challenge.
With 80K of RAM it seems likely to me that you’d be able to write an interpreter that can play at least some Z-Machine games, even if it can’t handle those that use the full 64K RAM. So I’d say go for it, get an initial version working, and then you can see what the overheads are. If it leaves you with 60K for the interpreter’s RAM, then with some work you might be able to optimise your code enough to allow for the full 64K; if only 40K is left then you probably can’t without changing to another language.
Even if there’s only 40K of free RAM, using the SD card as a swap file might be practical for games that need the full 64K. Infocom’s virtual memory system was ROM-only, but there’s no reason a modern one backed by flash would have to be.
Thanks for the positive responses, I’ll press on and see what I can achieve.
Regarding the RetroBSD option, I was only peripherally aware of it but it doesn’t change my plans. I (a) want something that doesn’t require replacing the Maximite firmware and (b) want to revise my BASIC for if/when it is time to teach my kids.
This looks like a very interesting project. I thought of doing something similar with a Pyboard using python obviously. As I experimented, the limitations with the Pyboard were too much for me to overcome.
I enjoy working with the Raspberry Pi platform. There are several BASIC interpreters available for the RPi. Just about any language is available. The RPi hardware resources are large enough that there would be few limitations. Also, the RPi is inexpensive and readily available.
As you develop your project for the Maximite, I would be interested is trying to port it to the RPi if it is open source and available. I may also purchase a Maximite from CircuitGizmo to experiment with.
That’s depending on how advanced the Basic is. Many Basics don’t have support for bit shift operations, and a Z-machine interpreter will be harder to write without them.
It seems like a quite fast Basic. Reuse code in functions / procedures / gosubs a lot to keep code size down.
Also note: You don’t have to be able to support all Z-machine games for this to be worthwile. If you can support say 30 KB of dynamic memory, that’s enough to play pretty much all Infocom games and most Inform 6 games.
As for how useful this terp will be: Do it for the fun and for the learning experience. If you write code that’s somewhat easy to read and understand, others may port your code to other platforms as well. To support this, I would probably write the program with lots of comments and long variable names and write a program which minifies the code to create the version actually used when playing games.
I can’t comment on how advanced the BASIC is, but it doesn’t have the shift ops so I would have to implement those. Fortunately my understanding is that it is 100s of times faster than old 8-bit BASICs.
Thanks for the info regarding the ~30K dynamic memory. My understanding of the spec is that it would be something like that, but the earlier post suggesting I would need 64K of z-machine storage in RAM had me worried.
I was coming to the same conclusion regarding the need to have a long-hand version of the code and a tool to shrink it for actual execution.
I will make the code public if I get anywhere, although I can’t imagine why someone would want to port a BASIC implementation to another platform when there are several implementations in more suitable languages.
I made good progress writing code to read and dump various structures from the Z-machine input immediately after I made the original post, but since then my day job and young family have meant I haven’t even had time to switch the Maximite on
Added to that I aquired a reconditioned BBC Master on tueday so I have a new distraction.
One of the most difficult aspects of writing a Z-machine emulator for a primitive BASIC would be the call stack structure. Finding an easy way to handle the pushing and popping efficiently and the space may be hard. Good luck though.
Implementing the stack shouldn’t be any harder than in C or assembler really. Dedicate a memory area for this purpose and use a variable for a stack pointer.
Yes. I don’t anticipate any problems with this. I can allocate arbitrary buffers and peek/poke bytes into them.
Having spoken with Fredrik earlier in the week I’m pretty convinced an interpreter can be written that will be capable of running the majority of z3 games.
Ahh. So it’s a combination of BASIC and assembly. I was trying to fathom creating quick and efficient routines to handle the stack. That makes more sense.
No. It’s pure BASIC, assuming the BASIC has PEEK and POKE functions like the 8-bit BASICs I’m familiar with all did.
Off the top of my head my first UNTESTED implementation is:
' Storage for the stack (512 x 16 bit words)
' This allocates enough memory for 256 x 32-bit floats = 1K
Dim stack(255)
' Stack pointer, a byte offset into the memory behind 'stack'
Let sp = -1
Sub push(word)
sp = sp + 1
Poke Var stack(0), sp, word \ 256
sp = sp + 1
Poke Var stack(0), sp, word Mod 256
End Sub
Function pop()
pop = Peek(Var stack(0), sp)
sp = sp - 1
pop = pop + Peek(Var stack(0), sp) * 256
sp = sp - 1
End Function
However I then had another think and the following is “probably” better performing and provided the stack doesn’t need to be too large may be worth the expense:
' Storage for the stack (512 x 16 bit words)
' Storing each 16-bit word as a 32-bit float
Dim stack(511)
' Stack pointer, a simple index into 'stack'
Let sp = -1
Sub push(word)
sp = sp + 1
stack(sp) = word
End Sub
Function pop()
pop = stack(sp)
sp = sp - 1
End Function
But without digging into those benchmarks it’s probably not going to be as fast as ozmoo running on a 1 MHz 6502.
If I get anywhere (and I’m probably only able to spend 10 hrs/month) then I will cross my fingers that MMBasic 5 (for the Micromite) will be back-ported to the Maximite (currently MMBasic 4.5) as the later version has the ability to embed “C” and PIC-32 assembler.
Oh, I have no doubt you can can implement a stack in BASIC. Z-machine emulation is fairly straightforward even in BASIC. I was alluding to the speed of various data structure processing (tokenizing the input buffer) and pushing/popping carious data blocks into the call stack. But it sounds like the BASIC you’re using will hopefully work. I was curious if something like this could be done in Applesoft BASIC, but I think it’d be too slow.
Well I’ll have to suck it and see. I have the code to read from memory, decode and print zstrings written and there is a barely perceptible “typewriter effect” as the characters are printed. But I haven’t done any optimisation yet, so I’m still hopeful.
Sorry if reviving such an old thread is considered bad form, but with Fredrik’s help I have now implemented a Z-machine in MMBasic and it is published on github: https://github.com/thwill1000/zmim
Near the end of development I switched to the faster / much more powerful Colour Maximite 2. Whilst the original Colour Maximite might be capable of running a Z-machine (I’m “porting” to it) I don’t believe it is capable of running it at a speed anyone would have the patience to play
Fantastic project! I was just about to start the same idea and stumbled over your project - brilliant work! Just one question please: almost all Infocom story files I own are in z5 format - is this supported? Thanks and keep up the good work