Solid Z-machine interpreter that can show disassembly?

Requirements:

  • Runs on a mac
  • Ideally doesn’t have a zillion dependencies

I’ve been working on an interpreter and a compiler for a few months now.

The interpreter works reasonably well and passes every test suite (Czech, etude, praxix, etc) I can find.

It also crashes on some games I’ve been trying to play with it.

Easiest repro is Anchorhead. If I press R at startup, my interpreter crashes because something is calling @get_parentget_parent on object zero. Couldn’t see anything in the standard on what should happen here.

If I start a new game, as soon as I get the keys from the office and take inventory, it crashes because @get_prop on object zero is also out of range.

Should I just be ignoring these errors in my ‘terp?

Are there interpreters out there that can dump a live disassembly so I can compare and figure out where mine is diverging?

Thanks,

-Dave

EDIT: I had downloaded Yazmin, but it didn’t seem to support disassembly. Then I thought to look at its source code, and yup… for get_prop, it will “assert” the object is greater than zero, then just return 0 for 0. And for get_parent, calling with 0 returns 0 without even an assert, so I guess it’s just one of those things not written down anywhere that people just do.

It’s illegal. Older games do it anyway, assuming the interpreter will return zero.

Around 1998 or 1999, I think, we started a crusade against the “vile zero error from hell”. This meant setting up interpreters to show a (non-fatal) warning, and also setting up the Inform compiler to support run-time error checking.

I guess it’s just one of those things not written down anywhere that people just do.

There was a lot of discussion 25 years ago! It’s timed out, I guess.

5 Likes

This is why, e.g., Frotz has a -Z error-checking mode whose options are “don’t show warnings, always show warnings, show warning at most once.”

1 Like

The standard does allude to it in Appendix A:

A number of post-Infocom games have been released which contain errors, most often trying to perform illegal operations on object 0. Many interpreters silently ignored these errors, which can make it very to notice and track down bugs.

This is in the context of urging interpreter authors to manage this behavior:

It is desirable for modern interpreters to be able to notify players about these bugs, but this can also ruin gameplay. It is highly recommended, then, that interpreters have four levels of error checking, selectable by the user (through a command-line or menu option, or similar):

  • Never report the bug.

  • Report the first instance of each type of error.

  • Report every error.

  • Fatal error and close the interpreter on any error.

3 Likes

Okay. I guess I kind of expected a modern classic like Anchorhead to not have two VZEFH’s in the first five minutes of gameplay :slight_smile:

I guess my question does still stand though, it would be interesting to see if I’ve done something else terribly wrong that’s going to cause other issues later. I’d hate to accidentally release a buggy game that only works properly on my own buggy interpreter.

(I do have Yazmin now at least as one reference point)

-Dave

1 Like

That’s one thing that kind of blows my mind about IF and my life, I guess.

I was always a fan of interactive fiction. I remember playing Theatre soon after it came out in the 90’s on a unix machine at work. This was back when r.a.i-f was still a thing.

Then… well, I got married, had kids, had a career (still ongoing) in video games, kids grew up, partner and I moved to the UK, and I got interested in IF again just in time to have half the content of ifdb blocked by the stupid, pointless UK online safety act.

And the many of the same people I recognize from 30 years ago… are still around.

And I’m writing modern tools that target machines from 45 years ago because, why not.

-Dave

2 Likes

Ugh, I just tried my demo game on Yazmin and it behaves differently (not all exits show up as you move around the map) and Yazmin crashes on undefined opcode zero if I take inventory.

So either I’m generating bad Z-code that my bad interpreter knows how to handle, or there are bugs in Yazmin.

-Dave

ZVM has no special handing for get_parent or get_prop, so if you pass in object 0 it just acts as if there was an object 0. I don’t know if that’s better or worse than testing and returning 0 would have been. Never had any bug reports about Anchorhead though.

ConsoleZLR shows the current instruction as you step through in the debugger, and WinZLR has a disassembly tab.

Nice. Unfortunately I couldn’t find pre-built versions for Mac on (link to foss heptapod removed by forum software) and I’m not set up for C# development.

-Dave

Okay, here’s a technical question - when generating code that produces temporaries on the stack, my compiler evaluates the operands in reverse order so that if they do go to TOS, the first parameter will end up first on the stack.

Then my interpreter evaluates parameters from left to right.

Those obviously work well together, but if the rest of the planet does that differently, no wonder I’m not playing well with others.

EDIT: Just checked Frotz source (which refuses to compile properly, unfortunately, due to weird unix audio dependencies and blorb support that refuses to disable) and it works the way I expect.

-Dave

First operand will take the top of the stack, second operand will take the new top of the stack, etc.

Does it pass Praxix? Pretty sure it tests things like that.

Yup. That’s why I’m confused. I’ll double-check though. Yup, all tests pass.

Is there somewhere I can upload my 4k test game online and see if it works on Parchment or whatever?

-Dave

Yeah most places (other than Itch) will work, including here in the forum.

Wait what? Let’s see…

demogame.z3 (4.1 KB)

Huh, just downloads it, can’t figure out how to make it playable.

Here’s what my interpreter does. In Yazmin, the other exits are missing and inventory crashes the terp.

DemoGame for TinyZ

Release 1 compiled on 260224 by tinyzc v0.00

Nestled in the shade of the forest, this grotto is calm, quiet, and cooler than the rest of the area.

There is an exit to the north.

n

The river is dry here, and rocks and dead reeds litter the shoreline

There is an exit to the north.

South leads to Secluded Grotto.

There is an exit to the west.

i

You are empty-handed.

It works, but Bocfel says the dynamic memory is too small. I guess your compiler is shrinking the unused globals?

Previous discussion about that: Squashed globals in Z-code

Though from that discussion the consensus was that it’s okay for the globals to overlap other things. It should really be testing that the end of the globals and the end of the prop table are in dynamic memory, not that dynamic memory is longer than both added together.

Yeah, that’s expected. In a “real” game I imagine there will be enough other things after the globals in dynamic memory.

But I wonder if some interpreters can’t cope with fewer than 240 globals. I’ll add an option to pad them out and see if that fixes it running properly on Yazmin.

Interesting. I wrote code to add padding (even including the default properties, although I store them after globals anyway), but Yazmin still crashes.

Also, I write the header, the globals, the default properties, and then the rest of the object table, and the top of static memory is more than 480 bytes away from the globals.

I’ll try forcing all 240 globals next.

But here’s a version with an extra 44 bytes of padding.

demogame.z3 (4.1 KB)

Forced 240 globals (version below) and it still crashes Yazmin.

demogame_240.z3 (4.5 KB)

When you’re ready for z5, this is another small game you can use for tests: The Dragon and the Troll - Details

1 Like

My interpreter already supports 3/4/5/8 just fine. Well, modulo crashing Anchorhead twice :slight_smile:

Thanks for the link, I just added @print_unicode support a few days ago and this might exercise that.

The Dragon and the Troll

Steal the treasure

You are on a plain

You see

troll

The troll wants its ring back.

You can go n,e,

? i

Inventory:

You are on a plain

You see

troll

You can go n,e,

? n

You are in the desert

You see

You can go n,s,e,

?

The “You see” with nothing after it, and trailing comma, both worry me. Ah, it’s the same on Yazmin so I guess it’s fine.