I talked about the synthesised speech in Impossible Mission provided by ESS in a previous post. Now let's have a look at this great game itself.
Published in 1984 by Epyx and written by Dennis Caswell. There are various write-ups in the retro gaming media so I doubt I can add anything new. In short, it's a great game and a must-play if you've never played it before.
Let's hack it... (assume using .d64 image from well-known C64 site)
Summary of POKEs:
POKE 33697,96 - Stop the clock (1s tick)
POKE 33731,165 - Stop the clock on falling, touching a robot, using the modem, etc.
POKE 13369,137 - Add maximum (9) Snooze passwords
POKE 13382,137 - Add maximum (9) Lift passwords
POKE 41422,234 - Prevent snooze/lift passwords from decrementing on use
POKE 41423,234
POKE 41424,234 (must enter all 3 pokes)
POKE 36809,234 - Disable robot laser beams
POKE 36810,234
POKE 36811,234 (must enter all 3 pokes)
POKE 39075,234 - Remove object "Searching" delay
POKE 39076,234
POKE 39077,234 (must enter all 3 pokes)
The Long Version:
CIA2 Port A
$DD00 = $C6 1100 0110
VIC-II Bank (10) = 1 $4000-$7fff
VIC-II Mode
$d011 = $1b 0001 1011 Text Mode, Extended background off
$d016 = $d8 1101 1000 Multicolour mode on
Lift Shaft Screen:
$d018 = $03 0000 0011 Character memory 001 = $0800-$0fff
Screen memory 0000 = $0000-$03ff
VIC-II is running in text mode.
Screen Memory = $4000-$43ff
Colour Memory = $d800-$dbe7
Character Memory = $4800-$4fff (Lift)
Character Memory = $5000-$57ff (Room)
1. Hack the clock. Clock starts at 12:00:00 and stops as 06:00:00 when game ends. It's displayed on the "Computer" screen when in the lift shaft screen.
Let's find the screen memory where clock is displayed. Without doing maths, let's freeze and fill the lower half of the screen with a known value, unfreeze and let the game update the clock, then re-freeze and see what changed.
f 4300 43ff ff
m 4300 43ff
>C:4390 ff ff ff ff ff ff ff ff ff ff ff ff ............
>C:439c ff ff ff ff ff ff ff ff ff ff ff ff ............
>C:43a8 ff ff ff ff 81 82 ff 80 80 ff 81 85 ............
>C:43b4 ff ff ff ff ff ff ff ff ff ff ff ff ............
>C:43c0 ff ff ff ff ff ff ff ff ff ff ff ff ............
Clock characters are drawn at...
(C:$dd03) m 43ac 43b3
>C:43ac 81 82 f6 80 80 f6 82 83 ........
Trace code where these characters are updated:
watch store 43b3
#1 (Stop on store 43b3) 259 029
.C:851d 8D B3 43 STA $43B3 - A:83 X:88 Y:D1 SP:fc N.-..... 137569034
.C:8520 A5 D2 LDA $D2 - A:83 X:88 Y:D1 SP:fc N.-..... 137569034
Looks like it's the routine at $8516
Time is in zero page $d2(ss) $d3(mm) $d4(hh)
m d2 d4
>C:00d2 25 00 12 %..
Time reads = 12:00:25
Lets test it:
> d2 30 15 05
Yes, time now displayed as 5:15:30 on computer.
We can slow down the time by altering the time delay at $83a8, e.g. with:
a 83a8
.83a8 cmp #$ff
.83a8
Or we can stop the clock completely with:
(C:$83cb) a 83a1
.83a1 nop
.83a2 nop
.83a3
(POKE 33697,96)
2. Stop the clock decrementing on falling, touching a robot, using the modem, etc.
watch store d3
WATCH: 1 C:$00d3 (Stop on store)
(C:$dd03) x
#1 (Stop on store 00d3) 266 036
.C:83c5 85 D3 STA $D3 - A:10 X:FF Y:5A SP:f9 ..-.DI.. 872526978
.C:83c7 C9 60 CMP #$60 - A:10 X:FF Y:5A SP:f9 ..-.DI.. 872526978
(C:$83c7) bt
(0) 96f2
(2) 860d
(4) 7288
Looks like routine at 83c2 adds minutes to clock from A register.
Fix for all cases, stop $83c2 routine from adding to minutes counter $d3.
a 83c3
.83c3 lda $d3
.83c5
(POKE 33731,165)
2. Change the number of Snooze and Lift passwords.
We already know from earlier that the ':' character is $f6 and zero is $80, so we're looking for f6 80 in the previous line of screen memory.
(C:$4425) m 437d
>C:437d f6 80 53 71 6e 6b 79 53 6e 73 6e 79 ..SqnkySnsny
>C:4389 78 f6 80 2b 2c 62 63 2d 62 63 2d 62 x..+,bc-bc-b
Snoozes = $437e, Lifts = $438b
Trace where this gets written when computer display is opened...
(C:$4425) watch store 437e
.C:801d 99 76 43 STA $4376,Y - A:80 X:FF Y:08 SP:fd N.-..... 1283098714
.C:8020 B9 C1 35 LDA $35C1,Y - A:80 X:FF Y:08 SP:fd N.-..... 1283098714
(must be this one... it's writing char $80 ('0') to screen mem.
(C:$3b12) d 8018
.C:8018 A0 3D LDY #$3D
.C:801a B9 31 34 LDA $3431,Y
.C:801d 99 76 43 STA $4376,Y ; When Y=$08 (A=$80)
.C:8020 B9 C1 35 LDA $35C1,Y
.C:8023 99 76 DB STA $DB76,Y
.C:8026 88 DEY
.C:8027 10 F1 BPL $801A
.C:8029 60 RTS
Above routine copies bytes to screen mem from offset $3d downwards, including snoozes and lifts at offset $08 and snoozes at offset $15. Looks like simple copy from $3431 + offset.
(C:$8043) m $3431
>C:3431 78 73 74 74 7f 6a 78 f6 80 53 71 6e xstt.jx..Sqn
>C:343d 6b 79 53 6e 73 6e 79 78 f6 80 2b 2c kySnsnyx..+,
Snoozes = 3439, Lifts = 3446
Let's watch 3439 and try and find the routine that updates the Snooze password count.
(C:$8606) watch store 3439
WATCH: 13 C:$3439 (Stop on store)
(C:$8606) x
#13 (Stop on store 3439) 014 039
.C:9953 FE 39 34 INC $3439,X - A:80 X:00 Y:FF SP:fb N.-..... 1337277225
.C:9956 20 83 9B JSR $9B83 - A:80 X:00 Y:FF SP:fb N.-..... 1337277225
.C:9940 50 88 BVC $98CA
.C:9942 C0 FF CPY #$FF
.C:9944 D0 F6 BNE $993C
.C:9946 E6 D7 INC $D7 ; High Score passwords found total
.C:9948 BD 1A A2 LDA $A21A,X
.C:994b AA TAX
.C:994c BD 39 34 LDA $3439,X
.C:994f C9 89 CMP #$89 ; Maximum of 9 passwords
.C:9951 B0 03 BCS $9956
.C:9953 FE 39 34 INC $3439,X ; Increment char (80-89)
.C:9956 20 83 9B JSR $9B83
.C:9959 4C B4 99 JMP $99B4
Game appears to keep track of passwords by storing character in screen mem backing store only. Lets test it:
> 3439 89
> 3446 89
(POKE 13369,137)
(POKE 13382,137)
Yes, we now have 9 of each password.
Decrement occurs at:
#13 (Stop on store 3439) 178 000
.C:a1ce DE 39 34 DEC $3439,X - A:89 X:00 Y:25 SP:cf N.-..I.C 1820510622
.C:a1d1 08 PHP - A:89 X:00 Y:25 SP:cf N.-..I.C 1820510622
Prevent passwords from decrementing with:
(C:$a1e2) a a1ce
.a1ce nop
.a1cf nop
.a1d0 nop
.a1d1
(C:$a1d1) x
(POKE 41422,234)
(POKE 41423,234)
(POKE 41424,234)
3. Disable robot laser beam sprites:
Sprites:
1 = Robot laser
2 = Character
3 = Character
4 = Character
5 = Robot 1 (top down)
6 = Robot 2
7 = Robot 3
8 = Robot 4
Sprite 5 (robot 1) X, Y updates:
(C:$8f82) watch store d00a
WATCH: 2 C:$d00a (Stop on store)
(C:$8f82) x
#2 (Stop on store d00a) 268 041
.C:91b1 99 08 D0 STA $D008,Y - A:7D X:06 Y:02 SP:ee ..-..I.. 1541342165
.C:91b4 90 0C BCC $91C2 - A:7D X:06 Y:02 SP:ee ..-..I.. 1541342165
(C:$91b4) bt
(0) 8340
(13) 871e
(15) 7288
JSR $8ECA Robot movement and lasers
JSR $92C1 "Rover" ball movement
Disable laser beam sprite mux:
Trace sprite control register $d015
#3 (Stop on store d015) 269 022
.C:8fc9 8D 15 D0 STA $D015 - A:0F X:06 Y:01 SP:ee ..-B.I.. 1723415737
.C:8fcc AD 1C D0 LDA $D01C - A:0F X:06 Y:01 SP:ee ..-B.I.. 1723415737
(C:$8fcc) bt
(0) 8340
(13) 7f70
(15) 7249
(C:$8fcc) a 8fc9
.8fc9 nop
.8fca nop
.8fcb nop
.8fcc
(C:$8fcc) x
(POKE 36809,234)
(POKE 36810,234)
(POKE 36811,234)
4. Remove variable delay when "Searching" an object.
Find where "Searching" box is drawn from....
Put a trace on screen memory where Searching box is going to appear next.
#7 (Stop on store 4180) 286 022
.C:9ba6 91 10 STA ($10),Y - A:52 X:1B Y:04 SP:f9 ..-..... 1819790176
.C:9ba8 A9 01 LDA #$01 - A:52 X:1B Y:04 SP:f9 ..-..... 1819790176
(C:$9ba8) bt
(0) 98a0
(2) 92bd
(4) 726f
.C:98a0 20 96 9B JSR $9B96 ; Overlay Searching box
.C:98a3 20 6B 7F JSR $7F6B ; Searching delay
Remove delay entirely:
(Note that delay routine at $7f6b) is used elsewhere, e.g. when riding elevator platforms, so can't be sped up/removed globally without side effects.)
(C:$8606) a 98a3
.98a3 nop
.98a4 nop
.98a5 nop
.98a6
(POKE 39075,234)
(POKE 39076,234)
(POKE 39077,234)
|
All puzzles solved, password to control room found. |
|
Elvin Atombender (No, No, Nooooo!) |
I went ahead and completed the game with a couple of minor pokes enabled. I used the 'fast searching' hack and switched off robot lasers. Even so, I was still down to less than 1 hour to go at game completion. Room 00 used up a lot of time by falling or touching robots whilst attempting to get the jumps timed just right.
A quick cheat is to disable sprite collisions with a freeze cartridge but that takes all the fun out of the game.