*********************************
* PART 12:  BREAKING THE CYPHER *  
*********************************

<12.1> Introduction-----------------------------------------------------------   

Each Game Genie Code represents a 24-bit memory address
in the game (the last 6 digits of the code), as well as 8-bit
data with which the value of that memory address is set.

<12.2> The CPU Address; Game Genie to PAR conversion--------------------------   

This is where things start to get a little complex.  In
the Game Genie code, Galoob has created a double substitution
cypher.  The first step is switching from Game Genie Hex to normal
hex.  The table just above this section will allow you to do that.

So, if you have the Game Genie Code DF47-E76D, that becomes
0123-F380 in normal hex.

The next step is to drop the first two digits (the value, in
this case it's 01), but REMEMBER them; you'll need it later.  Now
you have a six-digit hex number, $23F380.

Then, convert the six-digit hex number into binary.  You
should get a 24-bit binary number.  Append zeroes to the beginning
until the number is 24 bits:

$23F380 = 1000111111001110000000 = 0010 0011 1111 0011 1000 0000

Now, this binary number is ALSO encoded (damn those people
at Galoob!  How hard were they trying to make it?).  You have 24
digits, arranged in this order and labelled "a" through "x":

00100011 11110011 10000000
ijklqrst opabcduv wxefghmn  :  24-bit encoded data.

Shift the bits around, and rearrange them in this order:

abcdefgh ijklmnop qrstuvwx  :  24-bit decoded data.
11000000 00100011 00111110

Convert this number to hex ($C0233E), and what you have is known
as the CPU ADDRESS.  This, incidentally, is also the equivalent Pro
Action Replay code for your Game Genie code.

<12.3> Finding the ROM Address: HiROM Games---------------------------------

Before you proceed any further towards decoding your Game Genie code to an
actual address in the game's ROM, you need to know what kind of game you're
dealing with -- HiROM or LoROM.  This information is usually within the ROM
itself, though it can be hard to locate.  Some emulators, such as the old,
Windows-based SNES97, will display the HiROM / LoROM information upon the
opening of a ROM image to play (note: neither the author nor the GGCCC
endorses the use of emulators, which are, in most cases, illegal).

* If the game uses the HiROM memory system (usually newer games), the 
  CPUaddresses you find will be between $C00000 and $FFFFFF (or, more
  rarely, between $400000 and $7FFFFF).  Because there is a correlation
  between consecutive ROMaddresses and consecutive CPUaddresses in HiROM
  games, conversion is relatively easy.  Merely subtract the $C00000 (if
  the CPUaddress is between $C00000 and $FFFFFF) or the $400000 (if the
  CPUaddress is between $400000 and $7FFFFF).  Then, add back $200 for 
  the 512-byte ROM header.  So, for a HiROM game,

  If $C00000 <= CPUaddress <= $FFFFFF, then
     
     ROMaddress = CPUaddress - $BFFE00
     CPUaddress = ROMaddress + $BFFE00

  If $400000 <= CPUaddress <= $7FFFFF, then

     ROMaddress = CPUaddress - $3FFE00
     CPUaddress = ROMaddress + $3FFE00

  
<12.4> Finding the ROM Address: LoROM Games-----------------------------------   

HiROM conversion was relatively simple.  LoROM conversion is not so easy.
This stems from the fact that the CPUaddresses do not correlate with 
consecutive addresses in the ROM for LoROM games.

LoROM CPUaddresses start from either $808000 or (more rarely) $008000.
But while the second digit of the ROMaddress increases every 32K (as is
normal), the second digit of the CPUaddress increases every _16K_.  That is,
ROMaddresses $000000 to $007FFF correspond to CPUaddresses $808000 to $80FFFF;
ROMaddresses $008000 to $00FFFF correspond to CPUaddresses $818000 to $81FFFF;
ROMaddresses $010000 to $017FFF correspond to CPUaddresses $828000 to $82FFFF;
and so on.  This pattern, while predictable, makes CPUaddress -> ROMaddress
conversion a more complex process.

The reason for the pattern lies in the fact that for LoROM games, _bit 15 of
the CPUaddress is always high_.  In other words, the CPUaddress is converted
into a 24-bit binary number, the sixteenth bit from the right will always be
a "1" (bits are numbered from right to left, starting with 0).  This creates 
the effect of making the third hex digit in the CPUaddress always between 
8 and F.

Take, for example, the address $81D2F4:

8    1    D    2    F    4             Note that the bit labelled "A15"
1000 0001 1101 0010 1111 0100          is always a "1".  Looking at the
-----------------------------          chart in <11.3>, you can see that
AAAA AAAA AAAA AAAA AAAA AAAA   B      this restricts the values of the
2222 1111 1111 11               I      third hex digit to between 8 and F.
3210 9876 5432 1098 7654 3210 <-T      
          *

Note: from here on, the notation "bit 15" will be replaced with "A15",
which is the traditional way to refer to bits in an address.


<<12.4.1>> From CPUaddress to ROMaddress-------------------------------------

To properly convert LoROM CPUaddresses into ROMaddresses and vice versa,
it is necessary to do some bitwise Boolean operations.  In case the reader
is not familiar with these, we take a moment to review them here:

Bitwise AND:  If both operands are high, the result bit is high.  
              Otherwise, it is low.  Consider each bit individually.

              0 AND 0 = 0         1010 AND 1001 = 1000       
              0 AND 1 = 0         
              1 AND 0 = 0         
              1 AND 1 = 1

              $1E3 AND $276 = (0001 1110 0011) AND (0010 0111 0110)
              = 0000 0110 0010 = $062.
  
Bitwise OR:   If either operand is high, the result is high.  If neither
              operand is high, the result is low.  Consider each bit
              individually.

              0 OR 0 = 0          1010 OR 1001 = 1011
              0 OR 1 = 1
              1 OR 0 = 1
              1 OR 1 = 1              
             
              $1E3 OR $276 = (0001 1110 0011) AND (0010 0111 0110)
              = 0011 1111 0111 = $3F7.

The equations make use of two additional operations:

shl(x):  Shift all bits (x) bits to the right, appending a 0 to the
         left of the highest-valued bit (since we are working with
         24-bit sequences, this means that A23 will become 0).
shr(x):  Shift all bits (x) bits to the left, appending a 0 to the
         right of the lowest-valued bit (i.e., A0 becomes 0).

Now, the equation to convert CPUaddress to ROMaddress for a LoROM game:

 -------------------------------------------------------------------------
| ROMaddr = ((CPUaddr and $7FFF) or ((CPUaddr and $FF0000) shl 1)) + $200 |
 -------------------------------------------------------------------------

It's easy enough to do the bitwise operations by hand, and you can
perform the hex conversions using a good scientific calculator (or the
calculator that comes with Windows).

Here's an explanation of what the equation does.

Let's say you have a 24-bit CPUaddress,

abcd efgh ijkl mnop qrst uvwx

* "CPUaddr & $7FFF"  will give you the portion of the CPUaddress that 
is bits 14 - 0 (0000 0000 0jkl mnop qrst uvwx)

* "CPUaddr & $FF0000" will give you the portion of the CPUaddress that 
is bits 16 - 23 (abcd efgh 0000 0000 0000 0000). 
"shl 1" will shift the bits to the right (0abc defg h000 0000 0000 0000).

* The OR operator puts these two together (0abc defg hjkl mnop qrst uvwx).  
Note that bit "i" (A15) gets lost in the mix.  This is because, as we 
mentioned above, this bit will _always_ be a "1" in the CPUaddress, and
holds no real information in terms of a memory location.

* The equation looks more complicated than it is.  In reality, all you 
have to do is remove A15 and shift the higher-valued bits one to the
right to "fill in the gap".

* The $200, in most cases, will need to be added at the end to 
compensate for the 512-byte ROM header which is often present.


<<12.4.2>> From ROMaddress to CPUaddress----------------------------------------

To reverse the process:

 ------------------------------------------------------
| CPUaddr = [(((ROMaddr - $200) and $FF8000) shr 1) or |
|           ((ROMaddr - $200) and $7FFF)] or $8000     |
 ------------------------------------------------------

This equation, too, looks more complicated than it is.  Simply 
subtract $200 from the ROMaddress to compensate for the header,
then convert this number to binary.  A15 to A22 should become
A16 to A23.  Insert a "1" in A15.  This will be your CPUaddress,
assuming the game is LoROM.

* For some games, you will need to make A23 high when converting from
  ROMaddress to CPUaddress.  This will be the case if the CPUaddresses 
  for this game are in the $808000 and up range.  You can find this out
  if there are (non-7E**) Pro Action Replay codes for the game you are 
  working on; if the codes start with an 8 or above, you'll want to make
  A23 high when converting from ROMaddress to CPUaddress.  If there are
  no appropriate PAR codes, then you'll just have to find out by trial and
  error. ;)

  ** PAR codes beginning with 7E affect a game's RAM, and not its ROM.
     Game Genie can only affect the ROM.

<12.5> Example from a HiROM Game----------------------------------------------   

[FINAL FANTASY III]	
135C-7B85	Terra starts with 110 Vigor

STEP 1:  Convert GG Cypher into Normal Hex
------------------------------------------
Game Genie  --->    Hex
135C-7B85	  --->    6E7A-39B7

STEP 2:  Cut down to six digits
-------------------------------
$7A39B7

STEP 3:  Convert to binary & decypher
-------------------------------------
11110100011100110110111

01111010 00111001 10110111
ijklqrst opabcduv wxefghmn

abcdefgh ijklmnop qrstuvwx
11101101 01111100 10100110

STEP 4: Get CPU Address
-----------------------
111011010111110010100110 = $ED7CA6

STEP 5: Convert to ROM Address
------------------------------

ROMaddress = CPUaddress - $BFFE00
ROMaddress = $ED7CA6 - $BFFE00
ROMaddress = $2D7EA6.

STEP 6: Set the address to the appropriate value
------------------------------------------------
[2D7EA6:6E] is the ROM address and value
            to set Terra's initial Vigor
            to 110.  Go to this offset
            in a hex editor, change it
            to 6E, and Terra will start
            with 110 vigor without the GG!

<12.6> Example from a LoROM game----------------------------------------------   

[FINAL FANTASY II]
00CE-6D69	The Gunslinger Code
This is probably the most famous Game Genie code of all time,
so I'll use it for the example.

Note that FF2's CPUaddresses start at $008000, rather than at $808000,
which is the norm for LoROM games.  Some older games will start at 
$000000, but doing that makes the SNES run at 2/3 speed (thanks to
Cheatmaster for that bit of information).

STEP 1:  Convert GG Cypher into Normal Hex
------------------------------------------
Game Genie  --->    Hex
00CE-6D69   --->    44AF-8085

STEP 2:  Cut down to six digits
-------------------------------
$AF8085

STEP 3:  Convert to binary & decypher
-------------------------------------
101011111000000010000101

10101111 10000000 10000101
ijklqrst opabcduv wxefghmn

abcdefgh ijklmnop qrstuvwx
00000001 10100110 11110010

STEP 4: Get CPU Address
-----------------------
000000011010011011110010 = 01A6F2h

STEP 5: Convert to ROM Address
------------------------------
000000011010011011110010

> Remove A15
00000001_010011011110010
> Shift bits right 1
000000001010011011110010
> Convert to Hex
$00A6F2
> Add 200h
$00A8F2
> Put your value in
[00A8F2:44] is the ROM address and value
            to have a permanent Gunslinger
            code!