Infocom overwrote the PSEUDO-OBJECT’s “hardware name” in the object table to reflect the noun that matched it:
So… I guess the takeaway here is that very few games use a @jump instruction in the small integer operand form given that Yazmin didn’t implement it correctly and yet runs dozens of existing games just fine.
(I did see there were several other issues of bizarre behavior in the GitHub issues tracker, it’s possible some or all of them have the same root cause I just fixed)
The other takeaway is @get_parent 0 and @get_prop 0 should both just return zero by default unless you opt into strict behavior.
-Dave
I’m curious what 8-bit platform you’re working on? I had the idea of shadowing the globals into separate arrays of low and high bytes so I could index all 240 of them easily. On routine entry, I could copy all locals into slots 1-15 of that array (also split) so that the variable operand type could be handled with very few branches (only TOS might need special handling).
-Dave
Just realized if you do shadow globals for efficiency you need to put them back in their original location before you save.
Dave
Yep. I remember bringing up something about hoisting anything out of dynmem means you need to handle writing it back before saving. I don’t recall the specifics though. You theoretically also need to deal with direct memory writes invalidating your separate cached data, but practically you can probably get away with it, mostly.
Sigh. My C++ interpreter seems pretty robust for Z3 games, enough that I could use it to debug (via comparing debug output) my 6502 interpreter.
But I can crash Lost Pig in four moves. listen. listen. ne. x torch.
It’s trying to access property 90 on an object, which is obviously wrong. As far as I can tell, the 90 is coming from a @loadw 0x9425 0. But without source code I can’t really tell how it’s reached that point.
Any suggestions? I’m on a Mac, so C# stuff doesn’t really work out of the box.
-Dave
Dave, not sure if this will help, but this is the runtime disassembly output from my interpreter executing the first four moves from Lost Pig as a single command input.
z-dump.txt.zip (404.3 KB)
This assumes you are using Lost Pig Release 2 / Serial Number 080406.
That’s a huge help, thanks Jon. Strangely, running “listen. listen. ne. x torch” all on one line doesn’t crash. (EDIT - the game doesn’t seem to support that syntax. “listen. listen. ne” just produces “Grunk not know what that mean.”)
29078: JZ (L3 [9428]) [False] 290A5
290A5: GET_PROP_ADDR (L1 [5C] L2 [5A]) → G240
290A9: JZ (G240 [0]) [True] 290AF
That’s the exact line I’m crashing on. Property 90 will never exist on an object. I guess this is another case of “people developed games with forgiving interpreters and shipped with bugs so newer interpreters also need to be forgiving.”
I extended my existing “strict” mode to just return zero on bad properties and got past the crash.
Jon, I like how you indented the call stacks in the debug output, that’s really quite nice, I think I’ll borrow that idea. Thank you again!
-Dave
Dave, the game does support “listen. listen. ne” so there may be another problem, possibly with your AREAD instruction processing as it behaves slightly differently than the equivalent V3 input processing (and that tripped me up for a while). Let me know if you want another dump of just the “listen. listen. ne” command string for comparison as Grunk should know what you mean!
Ah, right. Multiple commands per line do work in other games, but I can’t say I got that 100% correct in my interpreter. I’ll double-check my implementation against the standard.