# [Z-MACHINE] Packed Address Calculation Anomaly

I have code like this for computing a packed address:

``````if self.version < 4:
elif self.version < 6:
elif self.version < 8 and is_routine:
return 4 * address + (8 * self.routine_offset)
elif self.version < 8:
return 4 * address + (8 * self.string_offset)
else:
``````

That seems to match what the spec is telling me in section 1.2.3.

A decompilation of Zork 0 shows the following:

Routines offset: 0e930
Strings offset: 362e0

So those are the addresses I should get. I’ll focus on the routines offset here. I try to get those addresses via:

``````self.routine_offset = self.get_word(0x28)
self.string_offset = self.get_word(0x2A)
``````

Here my `get_word()` implementation is this:

``````def get_word(self, address: int) -> int:
``````

Here’s the problem. When I use the above calculation on Zork 0 v6, the following branch path is (correctly) executed:

``````return 4 * address + (8 * self.routine_offset)
``````

However on that Zork 0 v6 file, it returns this:

Routines offset: 0x1d26
Static strings offset: 0x6c5c

Those are wrong compared to the decompilation. But if I just do this:

``````8 * self.routine_offset
``````

Then the calculation is right and the correct address is returned.

So to bring it home:

``````4 * address + (8 * self.routine_offset)  # incorrectly returns 0x1d26
8 * self.routine_offset                  # correctly returns 0e930
``````

What am I misreading here or doing incorrectly?

Actually, I think my question is stupid. I’m conflating getting a specific packed address with the offset location. For example, to get the starting location for the program counter I have logic like this:

``````if self.version == 6:
self.pc = self.get_packed(self.get_word(0x06), True)
else:
self.pc = self.get_word(0x06)
``````

Here you can see how I’m using my `get_packed` (which contains that calculation I started my previous post with). And that is returning the correct starting address for Zork 0 v6 as per the decompilation.

So my silly mistake here was conflating my output for the address locations with that.

What I should have recognized is that I can do the following:

``````self.routine_offset = self.get_word(0x28)
self.string_offset = self.get_word(0x2A)

print(f"Routines offset: {hex(8 * self.routine_offset)}")
print(f"Static strings offset: {hex(8 * self.string_offset)}")
``````

Notice the `8 * ` bit there. With the problem as I originally posed it, I was just printing the offset information without the `8 *` and expected it to match.

Which was silly.