99 lines
4.7 KiB
Plaintext
99 lines
4.7 KiB
Plaintext
From rec.games.video Fri Jan 8 10:05:34 1993
|
||
Newsgroups: rec.games.video
|
||
Path: netnews.louisville.edu!ukma!darwin.sura.net!spool.mu.edu!uunet!digibd!merlyn
|
||
From: merlyn@digibd.com (Merlyn LeRoy)
|
||
Subject: Game Genie for Genesis decoder
|
||
Organization: DigiBoard Incorporated, Eden Prairie, MN
|
||
Date: Thu, 07 Jan 1993 16:31:27 GMT
|
||
Message-ID: <1993Jan07.163127.8219@digibd.com>
|
||
Lines: 353
|
||
|
||
|
||
I've figured out the Genesis Game Genie 8-letter codes; all the codes are
|
||
for a 24-bit address and 16-bit data for the 68000. The Game Genie
|
||
lies to the CPU about those addresses, substituting the 16-bit instruction
|
||
at that address. For example, the codes for Sonic 1 to make each ring
|
||
worth 2 rings, SCRA-BJX0, decodes to 009c76: 5478, which is an addq #2,...
|
||
instruction (instead of adding 1 to the total, add 2). Since the 68000
|
||
has a regular instruction set for addq 1..8, you can make rings worth
|
||
1 to 8 each. The instruction 5478 disassembles into addq.w #2, <word addr>,
|
||
so if we instead change the instruction to bra.s +2 (branch over the
|
||
word address), rings are worth nothing. bra.s +2 is 6002, so putting
|
||
009c76: 6002 into the decoder gives us ALRA-AA50. Using this code makes
|
||
all loose rings worthless; only monitors give you rings, and picking up
|
||
rings after getting hit does nothing.
|
||
|
||
Unfortunately, the Game Genie seems to erase all of RAM when it resets;
|
||
if it didn't, it would be possible to use the GG to write a small program
|
||
in RAM and execute it to dump a game cartridge ROM. Another possibility
|
||
is using the battery-backup RAM of a game to hold the program (assuming
|
||
such games use normal-looking RAM, and has enough to hold a program).
|
||
I'll play around with this possibility, but it doesn't look promising.
|
||
|
||
In any case, it's still possible to dump the ROM of a game veeeeery
|
||
slowly. What you do is find a section of code that you can clobber
|
||
with 4 or 5 words of code, and insert code that does a btst #n, addr
|
||
followed by a beq.s -2 (if the bit tested is zero, branch to itself,
|
||
otherwise, continue). This will hang if you find a 0 and continue if
|
||
you find a 1. The btst instruction can have a 1 or 2 word address.
|
||
btst.b #3, 1111 would be 0838 0003 1111 and btst.b #4, 12345 would
|
||
be 0839 0004 0001 2345; beq.s -2 is 67fe. Addresses greater than
|
||
7fff need the 2-word form.
|
||
|
||
In Sonic 1, you can test this with the following:
|
||
00039a: 0838 0000 0007 67fe
|
||
Which becomes:
|
||
HABT-ATE4 AABT-AAE6 A6BT-AAE8 92BT-AR7A
|
||
|
||
This tests the LSB of byte 7, the LS byte of the initial PC value on reset.
|
||
This has to be zero (even addresses only), so the game will hang after the
|
||
SEGA banner (39a is just after the banner call). If you change the bit to
|
||
test to 1 by changing AABT-AAE6 to AEBT-AAE6, the program will NOT hang (but
|
||
it will crash later) and you know bit 1 of byte 7 is 1. And so on...
|
||
|
||
You can also find out things faster if you can have the game help you.
|
||
For example, Sonic 1 has the exception vectors display data, so you
|
||
can load a word in memory into a register, optionally add 1 to it,
|
||
then jump to it. If the value is odd, you will get an address exception
|
||
with the data you loaded displayed (if it isn't odd, change your add 1
|
||
instruction and try again). Here's that code:
|
||
|
||
move addr, a1 2279 0000 0004
|
||
addq.l #1, a1 5289 ; if you don't get addr error at 3a4, change this
|
||
jmp (a1) 4ed1 ; to addq.l #1, a0 (5288)
|
||
|
||
Remember to unsubtract the 1 if you are adding 1 to it to make it odd.
|
||
Here it is to read the longword at 4, the initial PC value, which we know
|
||
must be even (so we'll add 1 to make it odd, and remember to subtract 1).
|
||
|
||
39a: 2279 0000 0004 5289 4ed1
|
||
|
||
Here's the full format of what the decoder prints:
|
||
SEBT-AEN4 = 00039a: 2279
|
||
AABT-AAE6 [ 0] = 00039c: 0000
|
||
ATBT-AAE8 [ 4] = 00039e: 0004
|
||
VEBT-BEZA +1 = 0003a0: 5289
|
||
4EBT-A6ZC = 0003a2: 4ed1
|
||
|
||
The number in brackets are the decimal values of the bottom 8 bits; this is
|
||
shown if the 68000 instruction is a move immediate, or if all the high bits
|
||
are zero. This is for GG codes like "starting number of lives"; you can
|
||
type the genie code with your own number in brackets to make it whatever
|
||
value you want. Similarly, the "+1" indicates an addq instruction; you can
|
||
add a +1..+8 or -1..-8 to change it. To not add 1 to a1, change VEBT-BEZA
|
||
to VABT-BEZA, which adds one to a0.
|
||
|
||
Anyway, if you plug in these codes, you'll get an address exception after
|
||
the Sega banner. You should see, in a very unreadable italic font:
|
||
|
||
ADDRESS ERROR $000003A4$00000207
|
||
|
||
Which means the value at 4: is 00000206
|
||
|
||
Too bad Sonic 2 doesn't have the exception code anymore.
|
||
|
||
Anyway, if anyone out there knows either 1) RAM that the GG doesn't touch, or
|
||
2) battery-backed-up RAM addresses for a Genesis game, please send email.
|
||
|
||
|
||
|