Remember we found the lives for each of the 5 characters are stored at $5c18 onwards:
>C:5c18 03 03 03 03 03 00 08 10 18 20 00 00 ......... ..
5c18 Lives Wally
5c19 Lives Wilma
5c1a Lives Tom
5c1b Lives Dick
5c1c Lives Harry
It's a safe assumption that this area of memory is also used for other state information for each character, for example which items they're currently carrying. Each character holds exactly 2 items in their inventory at all times.
(C:$582e) m 5c18
>C:5c18 03 03 03 03 03 04 08 10 1c 20 00 00 ......... ..
>C:5c24 00 00 00 ff ff 00 01 ff 01 01 ff ff ............
>C:5c30 01 00 00 00 00 00 0c 0c 0c 0c 0c 23 ...........#
>C:5c3c 01 08 1f 26 18 19 20 27 06 04 1f 05 ...&.. '....
By picking up/dropping different items it's easy to determine that the following memory locations are used by each character for holding their current inventory:
5c3b & 5c40 - Wally
5c3c & 5c41 - Wilma
5c3d & 5c42 - Tom
5c3e & 5c43 - Dick
5c3f & 5c44 - Harry
The item IDs are as follows:
00 The Plunger
01 Letter A
02 Book Two
03 The Sand
04 The Battery
05 Letter K
06 The Cement
07 Book Three
08 The Trowel
09 The Matches
0A The Cracked Insulator
0B Book One
0C The Monkey Nuts
0D The Money
0E Superglue
0F The Chewing Gum
10 The Bucket
11 The Jump Leads
12 The Bunsen Burner
13 The Letter B
14 The Gas Mask
15 The Parcel
16 The Fuse
17 The Meat
18 The Monkey Wrench
19 The Screwdriver
1A Letter E
1B The Hook
1C The Patch
1D The Pipe
1E Letter R
1F The Oil Can
20 The Fuse Wire
21 The Good Insulator
22 The Bottle
23 The Red Herring
24 The Test Tube
25 The Can of Beans
26 The Rubber Stamp
27 The Pliers
28 The Whistle
This is quite useful for completing the game because we can work our whether another character has picked up the item we're looking for by checking their inventory, e.g. for Wally, Wilma, Tom, Dick, Harry
m 5c3b,5c40
m 5c3c,5c41
m 5c3d,5c42
m 5c3e,5c43
m 5c3f,5c44
The first & last bytes printed are inventory position 1 & 2, ignore the middle bytes. The game already displays the map location of each character by pressing 1-5 on the keyboard so we don't need to work that out ourselves.
OK, that's useful for knowing which character is holding an item, but it would be great if we could determine where all the other game items are without having to search the entire map.
Let's figure this out the hard way rather than just looking for the known item IDs in memory. By using watch points & break points on the character memory map where the items are drawn on screen, we can eventually locate the subroutine that draws the items at $3db to -$3e68.
Interestingly this routine is called several times per second and constantly re-draws any items present in the room. Note that the currently held 2 inventory items at the top of the screen are only redrawn when they change or when switching characters. This constant redraw effect is used for animating items, e.g. the flickering flame outside of the Bee-Pee garage from the cave gas leak.
It's also interesting to note that the items drawn are all 2 or 3 bytes in width and 2 characters high.
The routine at $3db0 draws the item ID specified in the Accumulator with the x, y position taken from addresses in zero page ($29, $2a). The item IDs are the same as listed above.
The item draw routine is called from the periodic update polling routine in $a1ca to $a1ed. It appears to read the variable length item for each room from memory as follows:
.C:a1d6 B1 04 LDA ($04),Y $04 = 6030
.C:a1d8 C9 FF CMP #$FF
.C:a1da F0 14 BEQ $A1F0
.C:a1dc 48 PHA
>C:6030 0b 38 90 9f 12 78 90 9f 13 c0 90 9f .8...x......
So the routine reads the Item data structure (ID, x pos, y pos, etc.) for each room from memory somewhere around $c030 until it reaches $FF. In this example $c030 is the room location for the Library which draws 3 items, e.g. in this example
0b 38 90 9f = Book One at position 38,90
12 78 90 9f = Bunsen Burner at position 78, 90
13 c0 90 9f = Letter B at position c0, 90
So for example, we can manipulate the Library (room offset $6030) as follows and move items around the screen.
> 6030 0b 38 a8 9f 4e 78 90 9f 07 df 68 9f
The Library with modified item placement |
By examining memory from $5fd8 to $6070 the room offsets can be determined as follows:
5fd8 Town Square
5fda Post Office
5fdf Market Street
5fe0 Supermarket
5fe9 Park
5fee Wobbly Walk
5fef Rubble Road
5ff0 Wall Street
5ff9 Pete Street
5ffe Workshop
600b School Lane
6010 School
6015 Baker Street
6016 Bakery
601b Red Lion
6020 Motor Way
6021 Kemco
602a Bee-Pee
602f Reference Road
6030 Library
603d Penny Lane
603e Bank
6043 Wally's House
6048 Meat Street
6049 Butchers
6052 Trunk Road
6053 Zoo
6058 Rail Road
6059 Station
605e Dock
6067 Sewer
606c Cave
This is quite useful because we can now use the following command to locate a required item and determine which rooms it's in:
m 5fd8 6070
If the required item doesn't appear in any location it's being carried by another character which we can check with the following (see first & last byte) as described above.
m 5c3b,5c40
m 5c3c,5c41
m 5c3d,5c42
m 5c3e,5c43
m 5c3f,5c44
So armed with this inside information I went ahead and played the game to completion. I did have infinite lives enabled but I reckon it's possible to complete the game without it if you know exactly where all the items are to be found to avoid endlessly walking the map and switching characters. It still takes quite some time to complete and several times another character had picked up an item before I had time to walk to the the room it was held in. No, I didn't complete every task so the final monetary haul is reduced from the maximum £3,000.
Bank with all letters collected and safe opened |
End game screen |
End game score table |
What an excellent game! I've got as much enjoyment out of it from reverse engineering the code as I did from playing it properly back in the 80s.
No comments:
Post a Comment