New Rust V1-V8 Z Machine interpreter

I’m in the middle of developing a new z machine interpreter in Rust. I’m mostly doing it for myself, because I’ve always loved Infocom games ever since I played one on my Atari 800xl :slight_smile:

I just thought I’d put feelers out there to see if anyone else would be interested in this project, or will there be crickets when I’m finished…

I have the core VM finished, and most of the screen output done. I have three layers in the design: the rust VM core, a rust front end (which draws the game on a frame buffer), and a platform layer that displays the frame buffer, plays sounds received from the rust front end, loads fonts, saves games, provides keys and mouse clicks to the rust front end, etc.

So the platform layer will be super thin, and easy to port to anything. The rust layers do no system I/O at all.

I’m targeting all versions, including V6.

Oh, and I implemented a saved draw list, so I can do things like pinch to zoom, and keep crisp text when zooming/resizing.

For rendering, I’m using vello and tiny-skia, along with cosmic-text.

I’m also toying with the idea of incorporating a simple gcc style debugger in the rust frontend (the platform layer doesn’t have to know anything about it), so the frame buffer would just be split between the game and the debugger.

If anyone is interested, I’ll plan on releasing the source under the MIT license once it’s in a good state.

Once I have the GTK platform up and running, I’ll do an Android one, with Google’s handwriting recognition, I think.

What do you all think? I know there seems to be more interest in Glulx and stuff, but I’ve always had a soft spot for the z machine. I’m calling it RustyGrue by the way.

7 Likes

I started working on my own recently too!

What I’d be most interested in is a Glk mode. Z6 can be excluded for that (so too for Z1-2 and Z7..)

That’s cool! How far along are you on it?

I thought about using Glk, but I really wanted to have accurate support for V6, and that just didn’t seem possible with how windows are handled in V6. And supporting both seemed like a pain…

For what it’s worth, I do have a feature-complete Glulx interpreter written in Rust, with some kind of unfinished Glk implementation, but not sure how useful or useable it would be outside of my interpreter.

But maybe you were thinking about plugging the C Glk implementations directly?

(If people are interested in my Glulx terp, I could make a dedicated topic.)

3 Likes

I cast about for a Z-machine in Rust for my Folly project a few years back, but everything was half finished and unmaintained. So I finished one of them! That code is here: folly/encrusted-heart at master · bkirwi/folly · GitHub

It doesn’t seem like exactly what you were hoping to build yourself, but it might be useful for inspiration or tests.

And I can imagine switching to a better-supported VM if one existed. (The main special feature I did need was a non-blocking I/O model, where the VM effectively pauses itself every time it needs input.)

1 Like

Very cool, I didn’t realize there were so many rust interpreters in work!

That’s how I designed my VM core as well – I call a ‘step’ function that runs the interpreter until it needs some sort of input, and then it returns. And the frontend does whatever the VM asked for, and then calls step again.

1 Like

Yeah, I inherited that approach from the project I forked, but it ends up being very nice: simple to embed in all sorts of contexts, makes things like autosave pretty easy, etc.

1 Like

I have a Rust-based z-machine interpreter and library I’ve not released publicly (Yet. Perfect is the enemy of good apparently).

The library is very opinionated:
It supports all aspects of the standard z-machine versions 1-8 and abstracts all I/O.
It supports debugging and extensive hooks into z-machine internals - variable, object, and stack inspection/manipulation and arbitrary z-machine memory reads/writes.
It runs one cycle of the machine per call into the library guaranteed non-blocking even in the face of interrupts or input.
It validates and reports every error condition in a story file that I could think of.
Despite the aggressive validation, it will attempt sane default behavior no matter how badly malformed the story file is and never refuses to run. (People just want to play games - even broken ones)
It never panics.
It only uses heap allocation at machine creation, never at runtime.

I have several interpreter front-ends that use the library, including a CLI one and a web-based one. For the latter the z-machine itself runs on the server (communication is handled via WebTransport). The UI is either WASM in the browser, or a local UI app. The web-based one also supports graphical map, inventory and status displays driven by game state via the hooks I mentioned. Custom maps and displays are SVG files created in Inkscape and tie into game logic via a naming convention I created. I also extended the save format to save/restore these displays.

3 Likes