After seeing a bug report about a crash in Stationfall (github.com/garglk/garglk/issues/284), I did some digging to see what was going on.
It looks like Stationfall has a bug in the very beginning of the game, in the form-reading slot. Inserting a non-form item into the slot will either trigger an “item too large” message, or “the slot spits the item back”. However, the way the game determines whether an item is too large is totally invalid. Some Z-machine disassembly follows…
Routine e282, 0 locals ()
e283: 41 92 37 01 a7 JE G82,#37 [FALSE] e42d
e288: 41 d8 fe 01 a2 JE Gc8,#fe [FALSE] e42d
e28d: 41 77 88 67 JE G67,#88 [FALSE] e2b6
e291: b3 ... PRINT_RET "The form's crumpledness
prevents it from sliding into the slot."
e2b6: 41 77 62 78 JE G67,#62 [FALSE] e2f0
...
Routine e282 looks like the handler for insertion of items into the slot. At the point it’s called, global variable G67 contains the object number of the item being inserted. #37 is the object “crumpled form”, #62 is “Class Three Spacecraft Activation Form HB-56-V”, etc, over all the forms. But later on:
e3fe: 31 0c 77 00 GET_PROP "Level Three",G67 -> -(SP)
e402: 42 00 03 61 JL (SP)+,#03 [FALSE] e425
e406: b2 ... PRINT "The slot swallows"
e411: e0 3f 2b 46 00 CALL 568c -> -(SP)
e416: b3 ... PRINT_RET " and then spits it back."
e425: e0 0f 7a 79 d5 b4 00 CALL f4f2 (S100) -> -(SP)
e42c: b8 RET_POPPED
Here’s the bug. At e3fe, the property stored in G67 is looked up for the “Level Three” object. If that value is less than 3, the slot spits the item back, otherwise it calls the routine at f4f2, which just prints out a “too large” message.
But the problem here is that in a version 3 game, there can’t be a property larger than 64; however, object IDs can be larger than 64 (and right at the start of the game, the uniform is object 229, and the ID is object 81). So these invalid properties are looked up and treated as the size (I assume, anyway, that’s the goal here) of the item.
Most interpreters wind up looking for these properties in the property defaults table, which has only 64 entries, so the result is reading a word outside the bounds of the table, which contains a junk value. This value is then compared to 3 to determine which message to print.
This seems totally harmless, since memory is large enough so that even the largest object will at least not break the bounds of the entire story file, and in both cases, the item can’t be put in the slot, so in the worst case, the error message is simply nonsensical (e.g. a huge object being spit out, but a small object being rejected for not fitting).
And I have no idea why the “Level Three” would be the source of item sizes, even if the lookup code made sense. It seems that something just went wrong in the source, but playtesting wouldn’t have discovered it: in the beginning, at least, by happenstance, the two smaller objects (watch and ID card) get spit back, but the uniform is considered too large. I think that’s coincidence, but it would have been enough, it seems, to have passed playtesting if anybody tried it.
Nothing earth-shattering but I found it a bit interesting.