Beyond Zork passing invalid values to @get_prop_addr

This concerns Beyond Zork release 60, although other versions may well be affected. This version can be found at Zarf’s Obsessively Complete Inform Catalog.

This came via a Spatterlight bug report which includes steps to reproduce, including a save file to get right to the problematic section.

What’s happening is that @get_prop_addr is being called with object number 41920, which is not valid. I’ve tried tracking down why this is occurring, in hopes to dynamically patch the problematic code to not use invalid objects. What I’ve found follows.

The disassembly:

Routine fd84, 5 locals

 fd85:  52 01 31 04             GET_PROP_ADDR   L00,#31 -> L03

The call site:

2fbfa:  f9 00 3f 61 a3 c0 ab b2 d3 24
                               CALL_VN         fd84 ("circlet","film","zzzp")

The source code for this can be found at the Obsessively Complete list. From what I can tell, the following function is the offender (i.e. is the code at 0xfd85):

<ROUTINE REPLACE-SYN? (OBJ OLD NEW "AUX" TBL LEN)
         <SET TBL <GETPT .OBJ ,P?SYNONYM>>
         <COND (<ZERO? .TBL>    
                <RFALSE>)>
         <SET LEN </ <PTSIZE .TBL> 2>>
         <REPEAT () 
            <COND (<DLESS? LEN 0>
                   <RFALSE>)
                  (<EQUAL? <GET .TBL .LEN> .OLD>
                   <PUT .TBL .LEN .NEW>
                   <RTRUE>)>>>

The caller:

<ROUTINE KILL-FILM ()
         <UNMAKE ,CIRCLET ,SEEN>
         <REPLACE-SYN? ,W?CIRCLET ,W?FILM ,W?ZZZP>
         <REPLACE-ADJ? ,W?CIRCLET ,W?SWIRLING ,W?ZZZP>
         <RFALSE>>

At this point I’ve exhausted my ability to track this down. Does anybody more well-versed in ZIL see what could be causing this? ,W?CIRCLET seems to be the “wrong” value here, but I’m not sure at all how it could be so.

I thought this was well known: Copying form http://ifarchive.org/if-archive/infocom/interpreters/zip/zip_bugs.txt:

-> [2] A bug in "Beyond Zork" can cause serious trouble. Some Zip
   ports might crash close to the end of the game.

When the player types "BLOW CIRCLET", the game tries to

  get_prop_addr 41460... (or similar)

which results from confusing the address of the dictionary entry
"circlet" with the object id of "circlet". The interpreter may
simply return 0, but it should not crash.
2 Likes

Thank you! I wasn’t aware of this particular bug. This should be enough to easily craft a patch to simply not make the invalid call.

Thanks again.

1 Like

I guess the idea is to modify the circlet’s SYNONYM and ADJECTIVE properties so that you can no longer refer to it as “FILM” or “SWIRLING”, replacing them with dummy words. The first parameter should be an object though, not a dictionary word.

The routines are used in several places, e.g. for changing the butterfly into a caterpillar. At a quick glance, it looks like KILL-FILM and RENEW-FILM are the only routines that use them incorrectly.

1 Like

That sounds right: W?CIRCLET is accidentally used instead of CIRCLET, it appears. Infocom’s interpreters must have been lax about invalid objects, at least in some cases.

Thanks!

1 Like