Sunday 26 February 2017

Everyone's a Wally (Mikro-Gen) Part 2

Following on from the last post where we hacked Everyone's a Wally to get infinite lives, let's have a look at how the game items are stored.

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