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.

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

I bought Everyone's a Wally as a budget title back in the 80s on cassette for the Commodore 64.  I owned and played several of the Wally games but kept going back to this one, although I never got close to finishing it.

Everyone's a Wally (C64) - Town square

Looking at the game now, it was certainly very well-featured for the budget price.  There are 5 playable characters you can switch between and they continue to roam the map and pick up/drop objects as they go around.  There's several interesting puzzles to complete and the aim of the game is to collect several letters (B-R-E-A-K) and take them to the Bank to finish.  If all this wasn't enough, the graphics are bright and colourful, there's a back story for all the characters and there's a music single on the B side of the tape.

The first puzzle game I really got into in a big way was Adventure for the Atari 2600 and this game is similar in some respects, e.g. objects being moved around randomly by other characters (The Bat), nasties roaming the map (Dragons), puzzles (Keys/Castles/Bridge/Magnet), collecting items and taking them to a special location to finish the game (Chalice and Yellow Castle).

This YouTube video has the Mike Berry song from the tape B side and shows the C64 gameplay.  Note the character inventory in the top left and the energy/lives at top right.

 

Back in the day I found the game difficult to complete because I ran out of lives quickly and it's often time consuming to track down specific items as they could either be carried by another character or in one of the many locations.  The longer you roam the map looking for items, the greater the likelihood of running into a nasty.  I didn't have any pokes for the game and my early Datel Action Replay Mk IV couldn't locate the lives counter.

Looking at the game today, the newer Action Replay Mk VI correctly finds the code for decrementing the lives counter (for all characters) as follows:

Infinite lives poke:
POKE 36317,189        (Switches STA to LDA instruction)

However, that's way too easy.  Let's hack this the hard way for fun and get a better understanding of the Commodore 64 memory map and play with some 6502.

I used the following cracked .d64 for this (I do own the physical tape so don't judge me!).

006980209167de90736f18fd032e059b  Everyone's a wally.DC.d64

Infinite Lives

The game sets up the 64's VIC-II graphics as follows:

CIA2 Port A
$DD00 = $C4 (1100 0100)

VIC-II Bank = 3 (00), memory mapped $c000-$ffff

VIC-II Mode
$d011 = $bb (1011 1011) Bitmap Mode, Extended bg mode off
$d016 = $c8 (1100 1000) Multicolour mode off
$d018 = $39 (0011 1001) Char memory 1xx = $2000-$3fff
                        Screen memory 0011 = $0c00-$0fff

So we're running in VIC-II bitmap mode at 320x200.

    Screen memory (colour)  = $cc00-cfff
    Bitmap/Character memory = $e000-$efff

Let's find the character memory location where the lives (heart symbols) are drawn on screen.  We can do this with maths or by trial and error writing to $e000 onwards.

$e3a0-$e3a7

We can overwrite the character with FF to prove this is the correct location:
> f e3a0 e3a7 ff

Let's watch this memory location for updates.

watch e3a0

Now touch a nasty and/or lose a life.  Note how both the energy bar and the lives remaining are always redrawn every time energy is decremented even if a life isn't actually lost.

#4 (Stop on  load e3a0)  098 037
.C:3c2d  91 0A       STA ($0A),Y    - A:6C X:24 Y:00 SP:78 ..-..I..  171937243
.C:3c2f  C8          INY            - A:6C X:24 Y:00 SP:78 ..-..I..  171937243


Add breakpoint on 3c2d where bitmap memory update occurs.

break $3c2d

#6 (Stop on  exec 3c2d)  106 049
.C:3c2d  91 0A       STA ($0A),Y    - A:6C X:24 Y:00 SP:78 ..-..I..  125117167
(C:$3c2d) bt
(0) 8e0f
(2) 9acc
(4) 4f07
(6) 4edb
(118) 0b77
(131) a677


$3bd5 subroutine updates the lives bitmap (decrement happens before this)

.C:8de2  4C 51 43    JMP $4351
.C:8de5  84 42       STY $42
.C:8de7  A9 70       LDA #$70
.C:8de9  85 0C       STA $0C
.C:8deb  A9 92       LDA #$92
.C:8ded  8D EE 3B    STA $3BEE
.C:8df0  A9 83       LDA #$83
.C:8df2  8D F5 3B    STA $3BF5
.C:8df5  A6 0F       LDX $0F
.C:8df7  BD 18 5C    LDA $5C18,X    ; Probably lives?
.C:8dfa  85 23       STA $23

.C:8dfc  C6 23       DEC $23
.C:8dfe  A2 24       LDX #$24
.C:8e00  A0 02       LDY #$02
.C:8e02  84 24       STY $24
.C:8e04  A5 23       LDA $23
.C:8e06  D0 05       BNE $8E0D
.C:8e08  A9 20       LDA #$20
.C:8e0a  4C 0F 8E    JMP $8E0F
.C:8e0d  A9 1F       LDA #$1F
.C:8e0f  20 D5 3B    JSR $3BD5


Looks like lives are probably stored in memory at $5c18 onwards:
The offset is for the character being played (5 different characters).

>C:5c18  03 03 03 03  03 00 08 10  18 20 00 00   ......... ..

Lose a life (Wally)...
>C:5c18  02 03 03 03  03 04 0c 14  1c 20 00 00   ......... ..

Yep, this is it.  Let's prove it by restoring the starting number of lives (Wally):
> 5c18 3

Watch this memory location for writes...

watch store 5c18
WATCH: 10  C:$5c18  (Stop on store)

#10 (Stop on store 5c18)  033 050
.C:8ddd  DE 18 5C    DEC $5C18,X    - A:80 X:00 Y:01 SP:7a ..-..I.C  215883977
.C:8de0  D0 03       BNE $8DE5      - A:80 X:00 Y:01 SP:7a ..-..I.C  215883977



Found it! Remaining lives counters are decremented by the DEC instruction at $8ddd


Remove the 3 byte DEC instruction and test it:
a 8ddd
nop
nop
nop
x

Yes, we now have unlimited lives.  Let's make this an Action Replay style poke by switching the STA to an LDA instruction with the same addressing mode which takes the same number of bytes in memory.

Infinite lives poke:
POKE 36317,189        (Switch STA to LDA instruction)


Note that this poke matches the poke determined by Datel's Action Replay Mk VI cartridge (see above), which demonstrates just how clever that cartridge was.

Remaining lives memory locations:

    5c18    Lives Wally
    5c19    Lives Wilma
    5c1a    Lives Tom
    5c1b    Lives Dick
    5c1c    Lives Harry

More tracing and disassembly to come in the next post...

Wednesday 22 February 2017

Speech synthesis and the C64

Growing up with the Commodore 64 I was completely blown away when several games were released featuring synthesised speech.  In particular, the two noteworthy games I owned back in the day were Impossible Mission by Epyx, and Ghostbusters by Activision.

Anyone who owned these games will remember the speech samples for "Destroy him my robots!", "He slimed me!" and "Ghostbusters!".

It was only recently whilst researching the hardware speech board for the arcade game Berzerk by Stern Elecontronics (1980) that I discovered there's a connection between Berzerk and these Commodore 64 titles featuring speech.

Firstly, here's the game Berzerk in its arcade and home computer guises.  If you don't follow Mamemeister on YouTube already, please do so.



The speech board (VSU-1000) in the arcade cabinet version of Berzerk is based around the Telesensory Systems Inc. S14001A.  You can see the IC (large chip lower, middle) and the ROMs containing the speech data (lower right).
 

Stern Electronics, VSU-1000 Speech Board

The development history of the TSI S14001A integrated circuit for use in the Speech+ talking calculator can be found on this page:

http://www.vintagecalculators.com/html/development_of_the_tsi_speech-.html

There's a great video showing the TSI Speech+ calculator in use.  Notice how the synthesised voice sounds just like the robot voice in Berzerk ("The humanoid must not escape!").



The inventor behind the technology is Forrest S. Mozer and his son Todd.

Electronic Speech Systems (ESS), founded by Forrest S. Mozer, then appears to have developed a software based solution which was used in several Commodore 64 titles, notably: Impossible Mission, Ghostbusters, Kennedy Approach.  Presumably this is the Software Speech (TM) product shown in the credits below.

Ghostbusters by Activision 1984 (Commodore 64)
Loading screen for Activision's Ghostbusters, crediting Software Speech (TM) by Electronic Speech Systems.

Impossible Mission by Epyx 1984 (Commodore 64)
This is the ESS credit from the loading screen of Impossible Mission.  There's an interview with Dennis Caswell (Edge/Retro Gamer) which explains how ESS were asked to produce the speech and never used by Epyx subsequently.

Finally, here's a couple of Commodore 64 demos (Chaos Speech I & II) featuring ripped samples from several games using ESS speech.



Tuesday 21 February 2017

Name that (SID) tune

Back in January 1990 I bought the latest issue of Commodore Disk User for my beloved Commodore 64 and it had a cool new menu screen complete with music and scrolling text.  Oddly this only lasted for one issue and they reverted back to the static menu from the next issue.

Anyway, I really liked the SID tune.




I didn't know the name of the tune and hadn't found it in the High Voltage SID Collection (HVSC) so far.  As the collection contains over 48,000 files it's probably not surprising.

There's a fantastic tool called SID Known (sidknown.exe) by Wilfred Bos which will examine .prg files for known SID tunes by comparing the signature with hashes of the entire HVSC database.

Here's the tool in action on the .d64 disk image for Commodore Disk User 303.

5ad08fc15f9d990168a7e3c0a872dd75  cdu303.d64

1. First use the command line tool c1541 to extract the PRG file for the main menu from the disk image.
2. Run sidknown.exe (with the latest hash database) to check for matches.

Example tutorial:

$ c1541
C1541 Version 4.00.
Copyright 1995-2016 The VICE Development Team.
C1541 is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type `show copying' to see the conditions.
There is absolutely no warranty for C1541.  Type `show warranty' for details.
c1541 #8> attach cdu303.d64

c1541 #8> dir
0 "cdu-january '90 " 33 2a
12    "aNALYTICAL"        usr
19    "sHADOW"            usr
16    "wOODLANDS"         usr
31    "lE gRAT"           usr
45    "1+margo"           prg
42    "2+blackjack"       prg
31    "3+4 in a row"      prg
78    "4+jetrace 2000"    prg
36    "5+frogs in space"  prg
51    "6+l. of darkness"  prg
40    "7+font ed.      "  prg
15    "8+6510+ unass.  "  prg
5     "9+colour r. note"  prg
20    "colour restorer"   prg
1     "scr.code"          prg
5     "file copier"       prg
4     "0+trivia -read- "  prg
13    "trivia install"    prg
162   "trivia.1"          usr
37    "menu"              prg
0 blocks free.
c1541 #8> read menu menu.prg
Reading file `menu' from unit 8.
c1541 #8> quit



$ wine sidknown.exe menu.prg Processing...
502ff4b571b5440d9522dc985c9fd4ea=/menu.prg #1 -> same as: /MUSICIANS/L/Link/TV3_Tune.sid #1

Total time: 00:00:03 (+136 milliseconds)


Gotcha! It correctly matched the following SID tune...
TV3 Tune by Klaus Grøngaard (Link)

Here's its entry on CSDb