Or you could look at the full decompilation of Gold Rush that I posted in
this thread.
Logic 42 in GR (rm.SternShipInterior) does have messages that go up to #134. But several of them (42, 47, 48, 53, 56, 67, 73-76, 87, 96-112, 121, 132) have invalid pointers. Specifically, they have an offset value of zero.
This happens a lot in Sierra logics. It's a result of how their original compiler handles messages that are not defined when a logic was compiled.
The message section of a logic is formatted as follows (where X is offset to last byte of command data):
offset(bytes) data
X+1 | highest index of messages in the logic
X+2, X+3 | word offset to last byte of actual text data (measured from start of message section, X+1)
X+4 - X+4+Z | message text offset table, equals highest index value times 2 (i.e. two bytes per message)
Z = (highest message index * 2) - 1
X+4+Z+1 - EOR | message text, encrypted with 'Avis Durgan'
The values in the offset table are relative to the location of the offset to last byte of actual text data, i.e. X+2. What this means is to calculate the start of a message, you add the value from the offset table to X+2.
For logic 42 in GR, X = 4671, so the message section starts at 4672. The reference point for calculating offsets (and pointer to end of text data) is at 4673. The message text offset table starts at 4675 and runs through 4942 (268 bytes for 134 messages). The text data starts at 4943.
The offset values for the invalid messages listed above are all zero. Which means if you tried to use them in a logic, they would point to 4673 (X+2). This is because when Sierra's compiler (CG.EXE) creates a logic, it defaults to a value of zero for message text offsets, and only updates it if a message was assigned in source code using the #message command.
Note that if a null string was assigned, the compiler would add a zero length string (a single \x00 byte), and adjust the message table offset value accordingly. So invalid messages are not the same as null messages.
Also, the interpreter actually checks for cases where a logic tries to access a message that hasn't been defined; if the offset of a message passed in a command is zero, AGI will raise trappable error 14 (the WinAGI Help file contains a detailed description of that error code). So you can't access an undefined message. This is one of the rare instances where AGI actually validates data used in AGI commands.
While original Sierra source files do use a separate, included file for messages, it was not required. But unlike modern compilers, messages could only be referenced in commands by their number, i.e. 'm1', 'm2'; you couldn't compile messages in line (i.e. this would NOT compile in CG.EXE):
print("sample message");
The original AGI specs describe a convention for AGI source syntax that AGI Studio and WinAGI both conform to.( I also added additional features to WinAGI that aren't in AGI Studio - if interested, see the WinAGI help file or ask me for details.)
The syntax rules for original Sierra compiler can be found in the agiwiki, or in
this post. They are derived from a full disassembly of CG.EXE. There are several significant differences between original Sierra syntax rules and what the AGI Specs consider 'canon'. But since the specs have been around for so long, and most non-Sierra compilers are based on the AGI Specs, there doesn't seem to be much reason to change. I am considering adding a 'CG.EXE compatible' mode to WinAGI at some point just for nostalgia, which would allow it to compile original Sierra source with no modifications. But it would only be for nostalgia, and wouldn't be of much practical use.