@database Heddley
@master smd.guide
@$VER: 1.3
@author "Pan"
@(c) "OCT. 1994"
@index HeddleyAutoIndex
@remark Created with Heddley v1.1 (c) Edd Dumbill 1994

@node "Main" "SUPER MAGIC DISASSEMBLER v1.4"
@{i}@{bg fill}=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-@{ui}@{bg back}
                       @{i}SUPER MAGIC DISASSEMBLER v1.4@{ui}

                         @{u}Coded by @{uu}@{fg fill}@{"-Pan- of ANTHROX" link "Pan" 0}
@{i}@{fg text}@{bg fill}=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-@{ui}@{bg back}

           @{"INTRODUCTION" link "intro" 0}               About, Changes from last version...
           @{"CONTENTS" link "contents1" 0}                   What's inside
           @{"INSTALL" link "install1" 0}                    How to install SMD
           @{"COMMANDS" link "command" 0}                   SMD commands
           @{"SPC700 COMMANDS" link "SPC700" 0}            SPC700 specific SMD commands
           @{"GAME BOY COMMANDS" link "Gameboycom" 0}          How To use the GB commands
           @{"GAME BOY TRAINING TIPS" link "GameBoytrain" 0}     Training on Game Boy
           @{"HOW TO USE" link "tipssnes" 0}                 Tips on using the disassembler
           @{"SOUND ADVICE" link "tipsspc" 0}               Tips on disassembling sound code
           @{"GREETS" link "greets1" 0}                     My greets to peeps
           ---------------------------------------------------------------
           @{"HOW TO REGISTER" link "register" 0}            How to register
@endnode

@node "intro" "Introduction to SUPER MAGIC DISASSEMBLER"
@{b}@{i}=============================================================================@{ub}@{ui}
                 @{fg shadow}@{bg shine}INTRODUCTION TO THE SUPER MAGIC DISASSEMBLER@{fg text}@{bg back}
@{b}@{i}=============================================================================@{ub}@{ui}

   @{fg shine}@{bg fill}Hi and welcome to the only publicly released SNES file disassembler for the
AMIGA!@{fg text}@{bg back}

   I coded this masterpiece back in October 1993 to help me train and debug
SNES programs. When I had started out in the SNES scene the only public
disassembler available was DSFX for the @{b}@{fg shine}PC (YUCK!!)@{ub}@{fg text}. After wasting my time
with the PC I set out to create a utility to conform with my needs and those
of other Amiga users.

   The outcome was a simple SNES file disassembler in the fashion of common
machine language monitors. Since @{fg fill}many Amiga users are European and POOR :)@{fg text},
they could not afford much ram. A 16mbit game would require 2 Megabytes of ram
in a real monitor.   To escape this problem I decided to edit straight off the
file, thereby @{bg shine}decreasing the amount of ram needed from 2 Megs to only 50k!@{bg back}

   Super Magic Disassembler features:

   - @{bg fill}100% Assembly Code@{bg back}
   - @{bg fill}Dissassembles SMC files or binary images@{bg back}
   - @{bg fill}Supports hi-rom addressing@{bg back}
   - @{bg fill}Does not load entire file into ram: SAVES MEMORY!@{bg back}
   - @{bg fill}EOR command used for decrytion of text, bytes@{bg back}
   - @{bg fill}Save feature for ripping@{bg back}
   - @{bg fill}Trainer possiblity finder@{bg back}
   - @{bg fill}Working on ALL Amiga operating systems!@{bg back}

=============================================================================

   @{i}@{fg shine}SMD v1.3 updates@{ui}:@{fg text}

   - Fixed Find trainer command (F) - added mouse button stop
   - Fixed a bug in opcode $f9 (SBC) skipped only 2 bytes, instead of 3
   - Added carriage return to repeat last command (Added by El Dio)
   - Added WB1.3 dos fix (Added by El Dio)
   - Added parallel send ability
   - Added CLI access directly through disassembler window
   - Added join ability to insert files into/outside another file
   - Fixed bank address, would miscalculate over $BF in lo-rom
   - Added write ability to change bytes in a file
   - Fixed Hunt command (text hunt is no longer case sensitive)
   - Added SPC700 disassembler + new command set

=============================================================================
 
   @{i}@{fg shine}SMD v1.4 updates@{ui}@{fg text}

   - Fixed bug with an SPC700 opcode in the vector table. It jumped to
     an actual address instead of a label
   - Corrected the help screen (.?) so that it would not constantly cycle
     after pressing return too many times
   - Added RAW SNES to Game Genie converter (make Game Genie codes)  (GS)
   - Added Game Genie to RAW SNES converter (decrypt Game Genie codes) (GG)
   - Optimized the code
   - Optimized vector tables
   - Added Game Boy Disassembler (GB)


=============================================================================


   SMD usage:

   SMD14.exe @{fg fill}[file]@{fg text}
@endnode

@node "command" "SUPER MAGIC DISASSEMBLER COMMANDS"
=============================================================================
                        @{i}Super Magic Disassembler Commands@{ui}
=============================================================================
@{fg shine}Commands:@{fg text}

 @{b}D@{ub} - Disassemble 65816 code.
     example: @{bg shine}.D 8000@{bg back}
 
 This will start disassembling at $008000. If you were disassembling a  lo-rom
game it would start at the beginning of the file.
 

@{bg shine}.D@{bg back}
 
 This will disassemble at the current address.

-----------------------------------------------------------------------------

 @{b}T@{ub} - Show as ASCII Text.
     example: @{bg shine}.T 8000@{bg back}
 This will show 64 ASCII characters per line starting at $008000.


@{bg shine}.T@{bg back}
 
 This will show 64 ASCII characters per line at the current address

-----------------------------------------------------------------------------
 
 @{b}H@{ub} - Hunt for bytes.
     example: @{bg shine}.H a2 04 ?? 8e ?? 43@{bg back}
 
 This will scan the entire file for the requested sequence.
 ?? is a wildcard flag, it simply means to includes any digit.
 If any sequence is found, the address it lies at will be printed on
 the screen. To stop hunting, hold down BOTH mouse buttons.

@{bg shine}.H "hey Man@{bg back}

 This will scan the entire file for the requested TEXT sequence
 To start a TEXT hunt you must make the first character a quote.
 You may then entire up to 16 characters to search for.
 The text is NOT case sensitive.
 You are limited to 16 bytes maximum for hunting.

-----------------------------------------------------------------------------

 @{b}EOR@{ub} - Exclusive Or bytes.
     example: @{bg shine}.EOR 30@{bg back}

 This will set internal EOR value to #$30.
 When using T or M commands, the bytes shown on screen will be
 EORd with the set value. This is used for decrypting EORd texts.


-----------------------------------------------------------------------------

 @{b}SMC@{ub} - toggle SMC header
     example: @{bg shine}.SMC@{bg back}
 
 Toggles SMC header. When the disassembler is first run it sets the
 flag to SMC header off. This is used for disassembling standard 
 Super Magicom files.

-----------------------------------------------------------------------------

 @{b}S@{ub} - Save bytes
     example: @{bg shine}.S ram:pan.bin 38000 7fefa@{bg back}
 
  This will save from SNES memory $038000 to $07fefa
  This feature requires you have enough ram. It will calculate
  the amount of bytes to be saved and then allocate the necessary
  memory. Trying to save more bytes than you have free RAM will give you
  an Allocation error.
  If you try to save more bytes than the file contains, or try to
  save past the last byte in the file, the disassembler will save
  starting at the address you've specified to the end of the file. 

-----------------------------------------------------------------------------

 @{b}L@{ub} - Load new file for disassembling
     example: @{bg shine}.L SNES:supermario.smc@{bg back}
 
  This will change the current file to what you've specified.
  If no file is found an error message will be reported back.
  You will not be allowed to disassemble unless a file is 'loaded'.

-----------------------------------------------------------------------------

 @{b}F@{ub} - Find trainer possibilities
    example: @{bg shine}.F 03@{bg back}
 
  This will search the entire file for LDA, STA commands with reference to
 the value #$03. it searches for these patterns:
 a9 xx 8d    (LDA #$XX, STA $YYYY)
 a9 xx 00 8d (LDA #$00XX, STA $YYYY)
 a9 xx 8f    (LDA #$XX, STA $YYYYYY)
 a9 xx 00 8f (LDA #$00XX, STA $YYYYYY)
 a9 xx 85    (LDA #$XX, STA $YY)
 a9 xx 00 85 (LDA #$00XX, STA $YY)
 
 It excludes all registers ($21xx, $42xx, $43xx) to reduce the number
 of possibilities.
 If any match is found, the address will be printed on the screen.

 To stop the search, hold down both mouse buttons.

-----------------------------------------------------------------------------

 @{b}REP@{ub} - Changes 16 bit status, acts like 65816 command.
     example: @{bg shine}.REP 30@{bg back}
 
 This instruction is a replacement for the DSFX command REG, which changes
 Accumulator and Index bit length. The problem I didn't like with the DSFX
 REG command was that it worked backwards. For example:
 REG 00 set A, Y, X to 16 bit, while REG 11 set A, X, Y to 8 bit.
 figuring that SNES starts up in 8 bit mode why would 0, which logically
 means NO, NONE, or OFF be used to go into 16 bit mode. Its like turning the
 light switch off and having the lights turn on! Not to mention that you
 had to specify an address to which it would change the status.
  My REP command works just like the 65816 code. This reduces confusion a bit
since the programmer will be thinking in 65816 code when disassembling. REP 30
sets A, X, Y to 16 bit REP 20 sets A to 16 bit REP 10 sets X, Y to 16 bit

-----------------------------------------------------------------------------

 @{b}SEP@{ub} - Changes 8 bit status, acts like 65826 command.
     example: @{bg shine}.SEP 10@{bg back}
 
 Works exactly like REP above, but sets to 8 bit.

-----------------------------------------------------------------------------

 @{b}M@{ub} - Show hex bytes, ascci characters.
     example: @{bg shine}.M 040000@{bg back}
 
 This will show bytes as hex characters and ascii characters on the screen
 starting at the specified address.

@{bg shine}.M@{bg back}
 
 This will show bytes starting at the current address

 This command is universal in ML monitors and is known as 'Modify'
 This disassembler does not change bytes nor modifies, but since this
 command is widely used, I included it without changing it's name.

-----------------------------------------------------------------------------

 @{b}?@{ub} - Help screen.
     example: @{bg shine}.?@{bg back}

 Shows lists of commands with an example

-----------------------------------------------------------------------------

 @{b}I@{ub} - Internal Nintendo info
     example: @{bg shine}.I@{bg back}

 This will show a block of memory starting at $ffc0 as useful information
 such as reset vectors, irq vectors, brk vectors, game name.

-----------------------------------------------------------------------------

 @{b}HROM@{ub} - Selects Hi-rom addressing
     example: @{bg shine}.HROM@{bg back}           or @{bg shine}.HR@{bg back}
    
 This will change all addressing to HI-ROM for HI-ROM games

-----------------------------------------------------------------------------

 @{b}LROM@{ub} - Selects Lo-rom addressing
     example: @{bg shine}.LROM@{bg back}           or @{bg shine}.LR@{bg back}
 
 This will change all addressing to Lo-rom for normal games

-----------------------------------------------------------------------------
 @{b}X@{ub} - Exit to shell, quit disassembler
    example: @{bg shine}.X@{bg back}
-----------------------------------------------------------------------------


 @{b}STAT@{ub} - Show statitics of REP, SEP, EOR, Lrom/Hrom, current file
    example: @{bg shine}.STAT@{bg back}

-----------------------------------------------------------------------------
 
 @{b}RESET@{ub} - RESETS REP, SEP, EOR, LROM
    example: @{bg shine}.RESET@{bg back}

 Sets:
 SEP 30, EOR 00, LROM, SNES DISASSEMBLER MODE
 
 Acts as if you've just executed the disassembler.

-----------------------------------------------------------------------------
 
  @{b}SEND@{ub} - Sends current file to the copier via parallel port.
    example: @{bg shine}.SEND@{bg back}
 
   * requires "@{fg fill}SSEND@{fg text}" util to be in C: directory.

-----------------------------------------------------------------------------

  @{b}CLI@{ub} - Access CLI through current disassembler window.
    example: @{bg shine}.CLI@{bg back}

    To exit, enter: @{fg fill}@{bg shine}ENDCLI >NIL:@{fg text}@{bg back}

-----------------------------------------------------------------------------

  @{b}J@{ub} - Join/Insert files into "loaded" file.
    example: @{bg shine}.J ram:intro.obj 108000@{bg back}

    This will attempt to join/insert the file INTRO.OBJ into the loaded file.
    If the loaded file was 4mbit, INTRO.OBJ would be attached to the end of
    the loaded file.
    @{fg fill}@{bg shine}The file to be joined/inserted must be a MAXIMUM of 128k bytes long!@{fg text}@{bg back}

-----------------------------------------------------------------------------

 @{b}W@{ub} - Write bytes to file.
    example: @{bg shine}.W 8000 a9 8f 8d 00 21@{bg back}

    This will attempt to edit the file by changing the bytes.
    If the loaded file was a lo-rom SMC file, it would have changed the first
    five bytes of the Nintendo code.

-----------------------------------------------------------------------------

 @{b}GG@{ub} - Convert Game Genie Code to SNES data and address.
    example: @{bg shine}.GG c222-d4dd@{bg back}

    This will convert a Game Genie code to SNES data and address.
    This is good to check out how certain codes effect a game.
    No more wondering about the code again, it's been decrypted.


-----------------------------------------------------------------------------

 @{b}GS@{ub} - Convert SNES data and address to Game Genie Code.
    example: @{bg shine}.GS ad00d0d8@{bg back}

    This will take the address and byte to change into the
    Game Genie Code. The format is BYTE BANK ADDRESS

    ad = byte
    00 = bank
    d0d8 = address

    This is useful so you can start mailing in your Game Genie Codes to
    your favorite magazine and start getting free games or Tee-Shirts.
    Send in a lot to make them go broke! :)


-----------------------------------------------------------------------------

 @{b}GB@{ub}  - Enable Game Boy disassembler
     example: @{fg shadow}@{bg highlight}.GB@{fg text}@{bg back}

     This will enter the Game Boy disassembler. To exit back to the SNES
     disassembler just enter @{fg shadow}@{bg shine}SNES@{fg text}@{bg back}.

-----------------------------------------------------------------------------
@endnode

@node "Pan" "Info on Pan"
@{u}@{fg shine}=============================================================================@{uu}@{fg text}
                                  @{i}@{bg fill}About the author@{ui}@{bg back}
@{u}@{fg shine}=============================================================================@{uu}@{fg text}


      Hi! If you need to contact me regarding this disassembler or unspecified
commercial interests I can be reached on three BBS's ONLY! These are:
            @{i}U.S.S. Enterprise@{ui}   - (412) 233-2611
            @{i}Insignia@{ui}            - (718) 591-4526
            @{i}Prowl's Place@{ui}       - (718) 271-0478

         or call my 90% working answering machine at @{fg fill}718-381-7504@{fg text}

 I'm currently 22 years old and live in @{fg highlight}@{bg shadow}New York City@{fg text}@{bg back}, home of rats. I've been
coding assembler on computers for over 6 years and have taught myself
everything I know about coding (Unlike some people who demand to know how.
Don't ASK, DO!) on a variety of platforms ranging from 8 bit to 32 bit
machines (computers/console). I prefer assembler over anything else!

 SMD was created using ASM-One V1.06 (!) on an A4000/040 over a period of
time. V1.0 took approx. 2 Weeks of lazy coding. V1.1 took about 3 days of even
more lazy coding! V1.3 took around a week of even more than 'even more' lazy
coding!

 SMD 1.4 was coded in about 1 week, with 5 days in between to check out
 Washington D.C. with a few friends.

 SMD 1.4 was finished 2 days after returning to the disgusting hell hole
 some people refer to as New York City. Hey why is that 5 days in D.C.
 I haven't seen 1 bum, homeless, crazed maniac, -fill in the blank-, weirdo
 on the Metro. But as soon as I get on the R train from Penn Station
 a filthy homeless beggar stinks up the car annoying EVERYONE.
 Garbage is everywhere. The attitude of the people change from friendly
 to "Ay YOU! Get the FUCK OUTTA MY WAY!"

 But then again.. Washington D.C. isn't that great.. Go check out South East
 D.C.!

 OKOK enuff of that fun...

@endnode

@node "SPC700" "SPC700 DISASSEMBLER COMMANDS"
@{u}@{fg fill}=============================================================================@{uu}@{fg text}
                         @{i}@{fg highlight}SPC700 DISASSEMBLER COMMANDS@{ui}@{fg text}
@{u}@{fg fill}=============================================================================@{uu}@{fg text}
@{u}Commands:@{uu}

-----------------------------------------------------------------------------

 @{b}SPC@{ub}  - Make 65816 address equal to SPC700 address and enable SPC700
        disassembler mode

    example: @{bg highlight}.SPC 18000 0200@{bg back}

        This disassembler was made to disassemble a SNES file and
        to treat the data as if it were actually in SNES memory.
        The sound, however, has it's own processor and ram (64k).
        The sound code can be assembled to any 16bit address in Sound Ram.
        This causes a little difficulty in determining what the actual
        address is when all the data must be copied from SNES memory to
        Sound Ram.
        To fix this problem and to treat the sound code as it would be
        in sound ram, we need to tell the disassembler where the data
        is located in SNES memory, and the start address in the Sound Ram
        where the data is being sent.
        @{bg fill}The above example tells the disassembler that the Sound data is@{bg back}
        @{bg fill}in SNES address $18000 and that the starting SPC700 address is@{bg back}
        @{bg fill}$0200.@{bg back}
        @{bg fill}It then tells the disassembler to enter SPC700 disassembler mode@{bg back}
        @{bg fill}for use with the @{bg shine}D@{bg fill} or @{bg shine}DS@{bg fill} (see below) commands.@{bg back}

-----------------------------------------------------------------------------

 @{b}DS@{ub}   - Disassemble SPC700 address

     example: @{bg shine}.DS 0200@{bg back}

        This example will disassemble SPC700 code starting at RELATIVE 
        SPC700 address $0200.
        
        You may also use the @{bg shine}D@{bg back} command to disassemble SPC700 code by
        using a 65816 address, for instance:

        @{bg shine}.SPC 18000 200@{bg back}

        @{bg shine}.DS 200@{bg back} would be the same as @{bg shine}.D 18000@{bg back}

-----------------------------------------------------------------------------

  @{b}E6@{ub}  - Show equivilent SPC700 address of a 65816 address

      example: @{bg shine}.E6 18000@{bg back}

        If we were to use the same address equates as in the DS command, 
        the disassembler would show $0200 as the equate.
        @{bg shine}.E6 18001@{bg back} would show $0201, and so on..

        This is necessary since only the @{bg shine}D@{bg back} and @{bg shine}DS@{bg back} commands understand
        SPC700 adresses. other commands like @{bg fill}.S@{bg back}, @{bg fill}.M@{bg back}, @{bg fill}.T@{bg back}, etc ONLY
        understand 65816 SNES memory locations.

        If you need to save a portion of code then you must convert
        the SPC700 address to 65816 address. You do this by using the
        @{bg shine}.E6@{bg back} and @{bg shine}.E7@{bg back} (see below) commands.

-----------------------------------------------------------------------------

  @{b}E7 @{ub} - Show equivilent 65816 address of an SPC700 address

      example: @{bg shine}.E7 200@{bg back}

        Again, if we use the same address equates as before (18000=0200)
        then the disassembler would show $18000 as the equate.
        This converts an SPC700 address to the relative SNES address.

-----------------------------------------------------------------------------

  @{b}SNES@{ub} - Exit SPC700 disassembler mode and go back to SNES 65816 mode

      example: @{bg shine}.SNES@{bg back}

         This will allow you to disassemble the SNES 65816 memory again
         when using the @{bg shine}D@{bg back} command (@{fg shine}@{bg fill}DS is not used in 65816 mode@{fg text}@{bg back}).

-----------------------------------------------------------------------------
@endnode

@node "register" "HOW TO REGISTER"
============================================================================
            @{b}@{fg shine}How To Register For Super Magic Disassembler V1.4@{ub}@{fg text}
============================================================================

 Super Magic Disassembler 1.3 was released with some timer protections
 in it so I could see the popularity of the program. To receive SMD all you
 had to show was interest in the SNES. @{b}@{fg fill}SMD 1.4 was to be released FREE.@{ub}@{fg text}
 After returning from a 5 day trip I wasn't too thrilled to see a "cracked"
 copy of 1.3 floating around. Anyone could have gotten it just by asking me.
 I guess some people don't like having to register.
 @{fg highlight}Cracking the protection wasn't so hard.@{fg text} The file was not packed and
 all routines were OS safe.

 SMD 1.4 has a new protection which opens unclosable windows each time you
 enter a command. It's annoying as hell. :)

 @{fg shine}SMD 1.4 will be MUCH harder to crack.@{fg text} Why?

 Cawz someone liked to "FUCK WITH PAN".

 Now comes the good news. Thanks to the @{fg fill}Hong Kong Dirty Boys@{fg text} I am charging
 a FEE to register for v1.4! @{fg shine}@{bg fill}$35 for non registered users, and $5 for
 registered users.@{fg text}@{bg back}

 To get a copy you must CONTACT ME. I will then give you a P.O. Box # to send
 a money order or international check to.

 The disk will be sent when I cash the check or money order.

 If you don't like this, then go @{fg shadow}@{bg shine}find someone in Hong Kong and kick their
@{fg text}@{bg back} @{bg highlight}Asian ass@{bg back}.. err..
 


               You may contact me at these three boards:

                  @{i}U.S.S. Enterprise@{ui} - (412) 233-2611
                  @{i}Insignia@{ui}          - (718) 591-4526
                  @{i}Prowl's Place @{ui}    - (718) 271-0478

                  or call me voice at (718) 381-7504


 Only 2 people will get a reserved copy FREE OF ANY CHARGE. They are:
 @{fg fill}@{bg shine}The White Knight and Ayatollah.@{fg text}@{bg back} Without their help 1.4 wouldn't be
 an update.
@endnode

@node "tipsspc" "TIPS ON USING SPC700 DISASSEMBLER"
@{b}@{i}@{fg fill}=============================================================================@{ub}@{ui}@{fg text}
                     @{fg fill}@{bg shadow}TIPS ON USING THE SPC700 DISASSEMBLER@{fg text}@{bg back}
@{b}@{i}@{fg fill}=============================================================================@{ub}@{ui}@{fg text}

One problem with disassembling unfamiliar sound code is where the code is
located at and where it's sent in Sound Ram.

In Sound Ram location @{fg shine}$FFC0@{fg text} there is a @{fg shine}ROM mask@{fg text} which contains a necessary
transfer routine. It's like downloading data from 65816. But of course when
you download, then other guy must upload! This means there must be a routine
to transfer the data to the receiving SPC700 routine.

The 65816 routine used in intros is common and you can find it easily!

Let's take the @{fg shine}@{bg shadow}ATX.SMC@{fg text}@{bg back} file for example.

This program is a trainer menu which I stopped using because of 'OLD AGE'.
let's load it up with SMD:

@{bg shine}.l ram:atx.smc@{bg back}

ok, now that it's loaded we need to search for the sound transfer routine.

The SPC700 when in reset state will try to communicate with the 65816 through
the @{fg shine}$2140@{fg text} and @{fg shine}$2141@{fg text} registers. It will send @{fg shine}@{bg shadow}#$BBAA@{fg text}@{bg back} to announce that it is
ready to receive data.

The 65816 routine simply reads the @{fg shine}$2140@{fg text} and @{fg shine}$2141@{fg text} data and compares it with
@{fg shine}@{bg shadow}#$BBAA@{fg text}@{bg back}. If it gets the right message it can transfer the data to the SPC.

We need to look for this 65816 routine so we can find out where the sound data
is located in SNES memory.

We need to search for anything that reads @{fg shine}$2140@{fg text}.

@{bg shine}.H 40 21@{bg back}

This will hunt for $40 $21 in memory and show it's address when found.

You'll notice there are 9 possibilities.

What's important to know is that the check for @{fg shine}@{bg shadow}#$BBAA@{fg text}@{bg back} is usually at the START
of the program, so we'll just check the first few addresses.

The second address print is the correct one, and it's location was @{fg shine}@{bg fill}$B61D@{fg text}@{bg back}.

We'll need to back step a bit to go to the beginning of the routine.

@{bg shine}.d b604@{bg back}

This will disassemble at the start of the 65816 transfer routine. You should
be aware that the first thing it did was to set up some zero page data before
checking @{fg shine}$2140@{fg text}. If you examine closely to the routine you should see:

 00B604:  E2 20       SEP #$20
 00B606:  8B          PHB ; get current bank (#$00)
 00B607:  68          PLA
 00B608:  1A          INC A ; increase it (#$01)
 00B609:  85 A5       STA $A5 ; store it in $a5
 00B60B:  A9 80       LDA #$80
 00B60D:  85 A4       STA $A4 ; put #$80 into $a4
 00B60F:  A9 00       LDA #$00
 00B611:  85 A3       STA $A3 ; put #$00 into $a3
 00B613:  08          PHP
 00B614:  C2 30       REP #$30 ; $a3,$a4,$a5 = 24 bit address @{fg fill}018000@{fg text}
 00B616:  A0 00 00    LDY #$0000
 00B619:  A9 AA BB    LDA @{fg shine}@{bg shadow}#$BBAA@{fg text}@{bg back} ;
 00B61C:  CD 40 21    CMP @{fg shine}$2140@{fg text} ; check if it's ok to send
 00B61F:  D0 FB       BNE $00B61C
 00B621:  E2 20       SEP #$20
 00B623:  A9 CC       LDA #$CC
 00B625:  80 34       BRA $00B65B
 00B627:  B7 A3       LDA [$A3],y
 00B629:  C8          INY
 00B62A:  10 05       BPL $00B631
 00B62C:  A0 00 00    LDY #$0000
 00B62F:  E6 A5       INC $A5
 00B631:  EB          XBA
 00B632:  A9 00       LDA #$00
 00B634:  80 12       BRA $00B648
 00B636:  EB          XBA
 00B637:  B7 A3       LDA [$A3],y
 00B639:  C8          INY
 00B63A:  10 05       BPL $00B641
 00B63C:  A0 00 00    LDY #$0000
 00B63F:  E6 A5       INC $A5
 00B641:  EB          XBA
 00B642:  CD 40 21    CMP $2140
 00B645:  D0 FB       BNE $00B642


In this portion of the routine one thing should strike out: It's reading [$A3]
and doing something.  It should, $A3 contains the start address of the sound
data!

@{bg shine}.m 18000@{bg back}

018000: 91 0D 80 03 20 CD 1F BD E8 00 5D AF C8 F0 D0 FB .... .½.]šŠ

ok, I don't want to get into all of this nonsense too much, but I will try to
explain what the transfer routine does.

It reads the first 2 bytes and makes it the amount to transfer. So far we can
see that the amount is @{fg shine}@{bg fill}#$0d91@{fg text}@{bg back}

Then it reads the next 2 bytes and makes it the SPC700 address destination.
That address is: @{fg fill}@{bg shine}$0380@{fg text}@{bg back}

Starting from $18004 it will copy @{fg shine}@{bg fill}#$0d91@{fg text}@{bg back} bytes.

It will then start the process over again.

It will read two bytes, and make it the amount to copy. Then it will read the
next 2 bytes and make them the SPC700 address to copy to.

If the bytes which make up the amount to copy is equal to @{fg back}@{bg shine}#$0000@{fg text}@{bg back} it will STOP
copying, otherwise the process keeps going.

The last two bytes of the sound data are the starting jump address. In our
case it's #$80 #$03 or, @{fg fill}@{bg shine}$0380@{fg text}@{bg back}. The same as the first address the data was
copied to.



To disassemble SPC700 we first have to tell the disassembler where the sound
data is located, and also what SPC700 address to emulate.

The sound data is located at @{fg fill}$18000@{fg text}, but since the first 4 bytes are flags for
the transfer routine, we know that @{fg fill}@{bg shadow}$18004@{fg text}@{bg back} is the start of the real data.

@{bg shine}.spc 18004 0380@{bg back}

SPC700 disassembler enabled

This will set up a relative address. @{fg fill}@{bg shadow}$18004@{fg text}@{bg back} = @{fg fill}@{bg shine}$0380@{fg text}@{bg back} SMD now knows where the
sound data is, and what SPC700 address it should be at.

@{bg shine}.ds 0380@{bg back}

 018004: 0380: 20               CLRP
 018005: 0381: CD 1F            MOV     X,#$1F
 018007: 0383: BD               MOV     SP,X
 018008: 0384: E8 00            MOV     A,#$00
 01800A: 0386: 5D               MOV     X,A
 01800B: 0387: AF               MOV     (X)+,A
 01800C: 0388: C8 F0            CMP     X,#$F0
 01800E: 038A: D0 FB            BNE     $0387
 018010: 038C: 5D               MOV     X,A
 018011: 038D: D5 00 01         MOV     $0100+X,A
 018014: 0390: D5 00 02         MOV     $0200+X,A
 018017: 0393: C8 80            CMP     X,#$80
 018019: 0395: B0 03            BCS     $039A
 01801B: 0397: D5 00 03         MOV     $0300+X,A
 01801E: 039A: 3D               INC     X
 01801F: 039B: D0 F0            BNE     $038D
 018021: 039D: FD               MOV     Y,A
 018022: 039E: DA F4            MOV     $F4,YA
 018024: 03A0: DA F6            MOV     $F6,YA
 018026: 03A2: BC               INC     A

TADA! ok it worked! We can disassemble SPC700 code now!

@{fg shine}@{bg fill}This routine is not the same with every game/intro. But it is quite common.
You may find games/intros/demos which will be hard to find the start address,
but you must remember:@{fg text}@{bg back}

@{fg fill}@{bg shine}It must always load the data from somewhere!@{fg text}@{bg back}


@{bg shine}.e6 0380@{bg back}
 The SNES equivilent of this SPC700 address is $018004

@{bg shine}.e7 1801f@{bg back}
 The SPC700 equivilent of this SNES address is $039B

Now in case we need to use the @{bg shine}.T@{bg back}, @{bg shine}.M@{bg back}, @{bg shine}.W@{bg back}, @{bg shine}.S@{bg back}  or other commands we'll need to
convert the SPC700 relative address to SNES address.

As you can see above, it's very easy.

E6 will print the 65816 equivilent of an SPC700 address.

E7 will print the SPC700 equivilent of a 65816 address.

To exit the SPC700 disassembler mode, just enter:

@{bg shine}.SNES@{bg back}

 SNES 65816 disassembler enabled


Now the only thing you need to worry about is getting an SPC700 assembler. But
don't look at me! I have one, but I can't give it out... oh well..
@endnode

@node "tipssnes" "TIPS ON USING SUPER MAGIC DISASSEMBLER"
@{fg shine}@{bg shadow}===========================================================================@{fg text}@{bg back}
                    @{fg shadow}@{bg shine}TIPS ON USING SUPER MAGIC DISASSEMBLER@{fg text}@{bg back}
@{fg shine}@{bg shadow}===========================================================================@{fg text}@{bg back}

Most of the time you'll be using SMD to debug your code. Other times you may
want to look into other people's code. And even more importantly, change other
people's code.

If you plan to train a snes game then you should have some knowledge of 6502
or 65816 before you start.

Training is easy on SNES. Using the F command in SMD is only useful if you
have not already created an Action Replay type of program already.

@{bg shine}.F 03@{bg back}

This will search for possiblilities of the value #$03.

This could be 3 lives, 3 coins.. etc etc.

But @{fg fill}@{bg text}this function is extremely primitive@{fg text}@{bg back}. If you were to write a small program
that would exmaine the contents of ram with a previous copy of ram you could
compare the two datas and see which had changed. Much like Action Replay does.
I suggest that if you wish to train that you should first write a program like
AR, it would make your life a lot easier.


@{fg fill}@{bg shine}How to find invincibility:@{fg text}@{bg back}

This is so simple it's rediculous. If you can't think like a program then you
might as well give up. A program just moves data and compares data, nothing
else.

@{fg fill}@{bg shine}What is invincibility?@{fg text}@{bg back}

Invincibility is the ABILITY NOT to react to enemy sprites. If Mario were to
hit a turtle he would jump off the screen and lose a life.

If he were invincible he could walk right past the turtles as if they were
nothing.

@{fg fill}@{bg shine}Where do you look?@{fg text}@{bg back}

The easiest way to find invincibility is to find the health or energy bar. If
it's a game like Mario where once you are touched you die, you will have a lot
of code to search through.

Once you find the health or energy bar address you should look for where the
program decreases it.

Once found simply go back a few instructions and look for a branch that would
skip over the routine.

for example:

      lda $1000
      and #$2040         this checks if some flag is set
      bne $3a9ea         and if so skip over the decrease

      ldy $1e            reads the amount to decrease

      lda $1200
      sec                this decreases health/energy
      sbc ($20),y
      sta $1200
      beq $3ab54         if health/energy is 0 or less then die
      bmi $3ab54

      lda #$5012
      sta $132a          this sets up flags that will make the character
      lda #$0020         be affected when touched
      sta $1478
 3a9ea:
      rts


 3ab54:
      lda #$ffff
      sta $132a          sets up death flags
      stz $1478
      rts


$1000 is most likely the invincibility flag. To test it make the program
constantly write #$2040 into $1000

You could use Wild Smeg and enter these action replay codes:
 7e100040
 7e100120

If it worked you should not be affected when you are touched.

If you are still affected, then you should back track even further. maybe even
look for something that will JSR to that routine and look for a branch that
would skip over it.


Another good tip for training is to first find the lives counter and then look
for other stuff next to it. Lets say that the counter is $0f00

we'd search for $8d $00 $0f

if we got an address back, we'd disassemble it and look for other STA's next
to it.

  example:

      lda #$03
      sta $0f00
      lda #$06
      sta $0f02
      stz $0f03
      stz $0f04
      lda #$01
      sta $0f06

@{fg shine}@{bg fill}notice how after the STA $0f00 there are more STA's.@{fg text}@{bg back}

That sta $0f02 looks pretty strange to me.  It could be a health counter.
Let's say the game did have 6 dots for health, and each time you got hit it
would take away a dot. $0f02 would be a very good possibility for the health
counter.

$0f03, $0f04, $0f06 could be weapons or something else, change them and see
what happens.

To find level select you simply should use the above method or search for some
text. You may see some text like "@{fg back}@{bg shadow}FORREST1@{fg text}@{bg back}" "@{fg back}@{bg shadow}FORREST2@{fg text}@{bg back}" etc. Find out where the
address it's located at and then see if the program reads it.  Most of the
time it'll be in an array.

sorta like this:

 00 80 08 80 10 80 18 80 20 80 28 80

 or: 8000, 8008, 8010, 8018, 8020, 8028

 to read the data the program may do this:

 ldx $1f00         ; read a value and make it an offset
 lda $038900,x     ; read the text addres data
 tax               ; transfer that value to the X register
 phx               ; push X to stack

 ...

 038900: 00 80 08 80 10 80 18 80 20 80 28 80

 $1f00 is probably the level counter!


Another quickie tip:

To look for a decrease you could search for:
 38 e9 01

 or:
 SBC
 SEC #$01


 @{fg fill}@{bg shine}Too many tips could spoil the trainer maker. This is where I end!@{fg text}@{bg back}
@endnode

@node "contents1" "What's in the package?"
@{b}@{i}@{fg fill}===========================================================================@{ub}@{ui}@{fg text}
                             @{i}@{fg shine}CONTENTS OF FILES@{ui}@{fg text}
@{b}@{i}@{fg fill}===========================================================================@{ub}@{ui}@{fg text}


                @{fg highlight}@{bg fill}SMD14.EXE - Super Magic Disassembler v1.4@{fg text}@{bg back}

                @{fg shine}@{bg fill}SMD.GUIDE - The docs (this!).@{fg text}@{bg back}

                @{fg shine}@{bg fill}ATX.SMC   - Trainer file for sound example.@{fg text}@{bg back}

                @{fg shine}@{bg fill}ADDRESS1.IFF - Diagram of Game Boy Addressing

@{fg text}@{bg back}                @{fg shine}@{bg fill}ADDRESS2.IFF - Diagram of Game Boy Memory Map

@{fg text}@{bg back}                @{fg shine}@{bg fill}SSEND     - Send program for use with the 'SEND' command@{fg text}@{bg back}
@endnode

@node "greets1" "Yo what up bro?!"
@{b}@{i}@{u}@{fg fill}===========================================================================@{ub}@{ui}@{uu}@{fg text}
                                  @{fg shine}@{bg fill}Hi Guy!@{fg text}@{bg back}
@{b}@{i}@{u}@{fg fill}===========================================================================@{ub}@{ui}@{uu}@{fg text}

   I'd like to greet some people who may or may not have helped me
   at whatever I've done:

                           @{fg shine}@{bg fill}The White Knight@{fg text}@{bg back}

                           @{fg fill}@{bg shine}Ayatollah@{fg text}@{bg back}

                           @{fg shine}@{bg fill}Sigma Seven@{fg text}@{bg back}

                           @{fg fill}@{bg shine}Pothead@{fg text}@{bg back}

                           @{fg shine}@{bg fill}Wildfire@{fg text}@{bg back}

                           @{fg fill}@{bg shine}Picard@{fg text}@{bg back}

                           @{fg shine}@{bg fill}ALKAID@{fg text}@{bg back}

                           @{fg fill}@{bg shine}All the dudes in Nightfall@{fg text}@{bg back}

                           @{fg shine}@{bg shadow}And others I can't think of now.. (sorry!)@{fg text}@{bg back}


 Special thanks must go to the United Forces of The White Knight and
 Ayatollah for their part in @{fg shine}@{bg fill}Operation 5 Finger@{fg text}@{bg back} - The Liberation of the
 Game Boy Manual from the evil clutches of Sigma Seven!


@{b}@{i}@{u}@{fg fill}============================================================================@{ub}@{ui}@{uu}@{fg text}
@endnode

@node "install1" "How to Install Super Magic Disassembler"
@{fg shine}@{bg shadow}===========================================================================@{fg text}@{bg back}
                          @{bg shine}HOW TO INSTALL SMD 1.4@{bg back}
@{fg shine}@{bg shadow}===========================================================================@{fg text}@{bg back}

 @{fg shine}Gee, this shouldn't be too hard.@{fg text}

           @{fg fill}@{bg shine}1. Copy '@{fg shine}@{bg fill}SSEND@{fg fill}@{bg shine}' to C:@{fg text}@{bg back}

           @{fg fill}@{bg shine}2. Copy '@{fg shine}@{bg fill}SMD14.EXE@{fg fill}@{bg shine}' to C:@{fg text}@{bg back}


 @{fg back}@{bg fill}You've just installed Super Magic Disassembler!@{fg text}@{bg back}
@endnode

@node "Gameboycom" "How to use SMD's Game Boy Disassembler"
@{fg shine}@{bg shadow}============================================================================@{fg text}@{bg back}
                     @{fg fill}@{bg shine}How to use the Game Boy Commands@{fg text}@{bg back}
@{fg shine}@{bg shadow}============================================================================@{fg text}@{bg back}

      The commands allowed in the Game Boy mode are the following:


    D  - Disassemble ROM address
    DC - Disassemble CPU address
    T  - Show TEXT
    H  - Hunt for bytes or text
    EOR - Exclusive OR the data for decryption
    SMC - Toggle header. The Game Boy mode starts up with the header on
                         since most GB files do not have headers.
    S  - Save data
    L  - Load new file
    M  - Shows hex bytes/text
    F  - Find trainer posibilities
    I  - Show Internal Info Block
    X  - Exit disassembler
    "Enter/Return" - Repeat last command
    CLI - open CLI
    J  - Join/Insert
    W  - Change bytes in file
    SNES - go back to SNES disassembler


----------------------------------------------------------------------------

              @{bg fill}All commands use ROM addressing except DC (CPU)@{bg back}

----------------------------------------------------------------------------

  From what I've read in the Game Boy manual it seems that there are
  2 ways of reading data. Since the GB is only 8 bit it requires BANKS
  for extra data. The Z80 processor is weak. It's based on Intel's 8080
  processor (now you know why! INTEL OUTSIDE!!) The Z80 is an enhanced
  version made by Zilog (the Z in Z80). The Z80 in the GB seems to be
  a variant or probably even an economy version. There are different commands
  and probably commands removed. I can't be too sure on the removal part,
  but I suspect it since less transistors generally means less power
  consumption.

  The Z80 is 8 bit with a few 16 bit instructions, but what is important
  to know is that it can only address 16 bits ($0-$FFFF).
  To be able to read 4 mbits it will need to switch banks.
  Please look at the IFF diagrams to visualize how it works.

  Basically the ROM address is much like an offset. If all the memory
  were chained together they'd run sequentially from $0 to $3FFFFF.

  Unfortunately addresses $8000-$FFFF are needed, so you are stuck with
  addresses $0 to $7FFF.

  Unfortunately $0-$3FFF are fixed as the home address so whenever you
  access within this address it will always be BANK 0.

  You are stuck with addresses $4000-$7FFF.

  This is how the banking works.

  Bank 0 is the fixed address. It is always from $0-$3FFF

  When accessing higher than $7FFF you will enter the VRAM, REGISTERS,
  and STACK.

  Every other bank starts at $4000 and ends at $7FFF.

  It is possible to read Bank 0 Address $4000.

  Bank 0 goes from $0-$FFFF, but when it reaches $4000 it is also Bank 1
  and when you reach $8000+ you enter VRAM, etc..

  Let's check out some Game Boy code for an example:

  Smurfs - released by Outlaws
  

  ROM     CPU     OPCODE         PSUEDO CODE

 000150: 000150: C3 53 01       JP $0153         <- jump to $153
 000153: 000153: F3             DI               <- disable interrupts
 000154: 000154: AF             XOR A            <- EOR A with A (like STZ)
 000155: 000155: E0 FF          LD ($FF),A
 000157: 000157: 31 00 E0       LD SP,$E000      <- #$E000 to STACK
 00015A: 00015A: 21 80 FF       LD HL,$FF80      <- #$ff80 to reg. pair HL
 00015D: 00015D: 0E 7F          LD C,#$7F        <- #$7f to reg. C
 00015F: 00015F: AF             XOR A            <- stz a
 000160: 000160: 22             LD (HLI),A       <- put A into HL and inc HL
 000161: 000161: 0D             DEC C            <- dec C
 000162: 000162: 20 FC          JR NZ,$000160    <- branch if Not Zero
 000164: 000164: 21 00 C0       LD HL,$C000
 000167: 000167: 01 00 20       LD BC,$2000
 00016A: 00016A: 3E FF          LD A,#$FF
 00016C: 00016C: 22             LD (HLI),A
 00016D: 00016D: 0B             DEC BC           <- the rest is
 00016E: 00016E: 78             LD A,B              just like above..
 00016F: 00016F: B1             OR C
 000170: 000170: 20 F8          JR NZ,$00016A
 000172: 000172: 3E 01          LD A,#$01

 
   When the ROM address and CPU address are lower than $4000 they are the same
since CPU's Bank 0 starts at $0000. As soon as the Rom address reaches $4000
the CPU address will be $14000.

----------------------------------------------------------------------------

                          @{fg shine}Internal Info Block@{fg text}

----------------------------------------------------------------------------


 .i
        $0130   Title:            'SMURFS..........'
        $0147   Cartridge Type:   ROM+MBC1
        $0148   Rom Size:         1M-BIT
        $0149   Ram Size:         NONE
        $014a   Maker Code:       $0170
        $014c   Version Number:   $00
        $014d   Complement Check: $93
        $014e   Check-Sum:        $63DD
        $0102   Start Address:    $0150

 The only important thing here really is the Start Address.
 MBC1 and MBC2 are two different memory controllers. MBC2 includes backup
 RAM which can be expanded to 2 mbit.

 RAM size means how much EXTRA ram the cart has.


----------------------------------------------------------------------------

                       Find Trainer Possibilities

----------------------------------------------------------------------------

 The most common way of putting a number into RAM is this:
 ld a,#$03
 ld ($c100),a

 The above example puts a #$03 into RAM address $C100.

 Since normal unexpanded ram lies between $C000 and $DFFF it is possible to
 look for certainties.

 .F 03  will search for something similar to the above example.
        It will search for 3E 03 EA xx C/Dx

        3E 03 EA xx Cx
        3E 03 EA xx Dx

 A few possibilities will be listed. If we try this with the Smurfs
 and use #$03 as our value we get:

 .f 03
 00300C 0033C9 003507 006A51 006A86 00B759
 End of file.

 Now you just have to disassemble those addresses and write down the address
 #$03 is being put in.

 Lets look at $300C first.

 LD A,#$03            
 LD ($D9B5),A         <- put 3 in here
 LD ($D9B6),A         <- and 3 in here

 We can change the #$03 to another value and test it on the Game Boy to see
 if our lives have changed. OR we can take the address $D9B5 and see
 if it will decrease the value in it.

 that would look like:

 DEC A
 LD ($D9B5),A

 or:

 3D EA B5 D9

 lets use the H command to find it.

 .h 3D EA B5 D9
  0035EB
 End of file.

 Uh Huh...  check out $35EB

 DEC A LLD ($D9B5),A


 If we go backwards we can see:

 LD A,($D9B5)
 DEC A
 LD ($D9B5),A

 A complete decrease. And since it only found one of these we can assume
 that it is lives or health.

 change the DEC A to NOP.

 just make the #$3d to #$00 using the W command.

 .w 35EB 00

 Now test it out. It works! tada! Almost as easy as training a SNES game..
 well.. at least 3 years ago...





----------------------------------------------------------------------------
@endnode

@node "GameBoytrain" "Some info on training Game Boy games"
============================================================================
             @{fg shine}Training The Smurfs and Contra Spirits on Game Boy@{fg text}
============================================================================


                     @{fg shine}@{bg fill}The Smurfs - Released by Outlaws@{fg text}@{bg back}


   The Smurfs was trained easily using the F command. The first
   possibility listed was the correct one. In fact, it showed
   a +2 (Lives and Health).

   .F 03
    00300C 0033C9 003507 006A51 006A86 00B759
   End of file.

   check out $300C:

   LD A,#$03
   LD ($D9B5),A  <- Lives
   LD ($D9B6),A  <- Health (hearts or whatever)

   We want a real trainer, not just 255 lives... So we need to check for the
   decrease.

   .H 3d ea b5 d9
    0035EB
   End of file.

   .d 35eb

 0035EB: 0035EB: 3D             DEC A
 0035EC: 0035EC: EA B5 D9       LD ($D9B5),A

   Let's back track a bit...

   .d 35e5

 0035E5: 0035E5: CD 8C 1D       CALL $1D8C
 0035E8: 0035E8: FA B5 D9       LD A,($D9B5)
 0035EB: 0035EB: 3D             DEC A        <- aha! the culprit!
 0035EC: 0035EC: EA B5 D9       LD ($D9B5),A

   We'll fix it! :)

  .w 35EB 00

  Let's check it out again!

  .d 35e5

 0035E5: 0035E5: CD 8C 1D       CALL $1D8C
 0035E8: 0035E8: FA B5 D9       LD A,($D9B5)
 0035EB: 0035EB: 00             NOP          <- YAY! unlimited lives!!
 0035EC: 0035EC: EA B5 D9       LD ($D9B5),A


  Now to do the health!

  .h 3d ea b6 d9
   0056D7 005902
  End of file.

   Hmm... 2 possibilities.. we'll check out both!

   .d 56D0 <- i'll start a few bytes back!

 0056D0: 0156D0: AF             XOR A
 0056D1: 0156D1: EA AF D9       LD ($D9AF),A
 0056D4: 0156D4: FA B6 D9       LD A,($D9B6)
 0056D7: 0156D7: 3D             DEC A          <- ok! this one seems alright!
 0056D8: 0156D8: EA B6 D9       LD ($D9B6),A
 0056DB: 0156DB: FE FF          CP #$FF
 0056DD: 0156DD: 28 25          JR Z,$015704
 0056DF: 0156DF: 3E 32          LD A,#$32
 0056E1: 0156E1: EA AA D9       LD ($D9AA),A

   .w 56D7 00  <- put an NOP there!

   Lets peep at the other one!

   .d 58f0  <- i'm gonna go back a few bytes to get a good picture

 0058F0: 0158F0: 00             NOP
 0058F1: 0158F1: 03             INC BC
 0058F2: 0158F2: 01 00 03       LD BC,$0300
 0058F5: 0158F5: 01 00 03       LD BC,$0300
 0058F8: 0158F8: 01 00 03       LD BC,$0300
 0058FB: 0158FB: 00             NOP
 0058FC: 0158FC: 00             NOP
 0058FD: 0158FD: 03             INC BC
 0058FE: 0158FE: AF             XOR A
 0058FF: 0158FF: EA AF D9       LD ($D9AF),A
 005902: 015902: 3D             DEC A         <- this looks wrong..
 005903: 015903: EA B6 D9       LD ($D9B6),A  <- it takes another value
 005906: 015906: 3E 08          LD A,#$08     <- decreases it and stores it?
 005908: 015908: E0 E3          LD ($E3),A    <- look at the LD BC on top!
                                                 this is all garbage!
                                                 probably just data.. leave
                                                 it!.

 ok cool! we have a +2!! but if you can find health you can usually
 find invincibility!  Let's re-examine that health decrease routine!


  .d 56b3  <- i'm gonna go way up and read the program!

 0056B3: 0156B3: FA A1 D9       LD A,($D9A1)
 0056B6: 0156B6: FE 90          CP #$90
 0056B8: 0156B8: 20 11          JR NZ,$0156CB <- This jumps to decrease
 0056BA: 0156BA: FA 65 D9       LD A,($D965)     routine if NOT EQUAL
 0056BD: 0156BD: A7             AND A
 0056BE: 0156BE: 28 4A          JR Z,$01570A
 0056C0: 0156C0: AF             XOR A
 0056C1: 0156C1: EA 65 D9       LD ($D965),A
 0056C4: 0156C4: E0 D2          LD ($D2),A
 0056C6: 0156C6: 3C             INC A
 0056C7: 0156C7: E0 D3          LD ($D3),A
 0056C9: 0156C9: 18 3F          JR $01570A    <- JUMPS somewhere
 0056CB: 0156CB: 3E 06          LD A,#$06     <- start of another routine
 0056CD: 0156CD: EA 42 D9       LD ($D942),A     which happens to be the
 0056D0: 0156D0: AF             XOR A            decrease routine!
 0056D1: 0156D1: EA AF D9       LD ($D9AF),A
 0056D4: 0156D4: FA B6 D9       LD A,($D9B6)
 0056D7: 0156D7: 00             NOP           <- used to decrease!
 0056D8: 0156D8: EA B6 D9       LD ($D9B6),A
 0056DB: 0156DB: FE FF          CP #$FF

 Lets change the branch to the decrease routine so that it never goes there!

  .w 56B9 00 <- change the branch value to 0, making it go to the next
                instruction instead of another address!

  .d 56b3 <- let's check it out to make sure!!!

 0056B3: 0156B3: FA A1 D9       LD A,($D9A1)
 0056B6: 0156B6: FE 90          CP #$90
 0056B8: 0156B8: 20 00          JR NZ,$0156BA  <- now it always goes to 
 0056BA: 0156BA: FA 65 D9       LD A,($D965)   <<-- here!
 0056BD: 0156BD: A7             AND A
 0056BE: 0156BE: 28 4A          JR Z,$01570A

  now we have a +3! lives, health, invincibility!




----------------------------------------------------------------------------

                @{fg shine}@{bg fill}Contra Spirits  - Released by Premiere@{fg text}@{bg back}

----------------------------------------------------------------------------

 Contra Spirits was a little trickier to train. One thing to remember
 when training is that there are diffrent ways to store data.
 For instance:

 ld a,#$03
 nop
 ld ($c100),a

 this is the same as:

 ld a,#$03
 ld ($c100),a

 The .F command can't find the first example, but usually such a method
 is not used.

 When you play Contra Spirits you'll notice that there are difficulty
 levels. If you choose the easy one you'll have 5 lives.
 If you choose the normal or hard ones you'll have 3 lives.

 When this happens you can be sure that the routine that stores lives
 when check the difficulty, then set the according life value.

 .f 03 didn't work on Contra Spirits. but maybe .f 05 will?!

 .f 05
  0002B6 000416 002202 0023BB 004E80 00757E
 End of file.

 Let's check out $2b6..

 .d 2a9 <- I'll skip a few bytes back

 0002A9: 0002A9: 3C             INC A
 0002AA: 0002AA: CD D7 39       CALL $39D7
 0002AD: 0002AD: FA D6 C1       LD A,($C1D6)
 0002B0: 0002B0: FE 00          CP #$00        <- a check?
 0002B2: 0002B2: 3E 03          LD A,#$03      <- hmm.. a #$03
 0002B4: 0002B4: 20 02          JR NZ,$0002B8  <- ah hmm... a branch?
 0002B6: 0002B6: 3E 05          LD A,#$05      <- hmm.. a #$05
 0002B8: 0002B8: EA D8 C1       LD ($C1D8),A
 0002BB: 0002BB: 3E 00          LD A,#$00
 0002BD: 0002BD: EA E8 C1       LD ($C1E8),A
 0002C0: 0002C0: 3E 01          LD A,#$01
 0002C2: 0002C2: EA DA C1       LD ($C1DA),A

 Let's try to translate the program...
 It increases A.. then goes to some routine..
 Then it reads an address and compares it with #$00.
 If it's Not Zero it stores a #$03. If it is Zero it stores a #$05.

 This seems fishy to me! We know that the easy level has 5 lives
 and the rest has 3. If it is 0 (least, easy) then store a 5. If not
 then store 3.

 I think we found lives..

 let's check if $C1D8 gets decreased!

 .h 3d ea d8 c1
  00380E
 End of file.

 Cool! It happens only once!
 Ok now to see what it does!

 .d 3800 <- i'm going backwards again!

 003800: 003800: C9             RET
 003801: 003801: FA D8 C1       LD A,($C1D8)   <- read $c1d8
 003804: 003804: A7             AND A          <- and it with itself for
 003805: 003805: 28 12          JR Z,$003819      Z compare
 003807: 003807: 21 E4 C1       LD HL,$C1E4
 00380A: 00380A: CB 46          BIT 0,(HL)
 00380C: 00380C: 20 01          JR NZ,$00380F  <- check and branch
 00380E: 00380E: 3D             DEC A          <- decrease A
 00380F: 00380F: EA D8 C1       LD ($C1D8),A   <- store A in $c1d8
 003812: 003812: 21 8D FF       LD HL,$FF8D
 003815: 003815: CB D6          SET 2,(HL)
 003817: 003817: F6 01          OR #$01
 003819: 003819: C9             RET

 This is a strange routine. It checks if the $c1d8 value is 0.
 If so, don't decrease. if not, check $c1e4 and see if the first bit is
 on. If it's on then don't decrease, otherwise decrease and store.

 That $c1e4 is a flag of some sort, and since it's just before the life
 decrease I'm gonna think it's part of a cheat mode.

 let's change the DEC to NOP.

 .w 380E 00

 Ok we should have unlimited lives. If you test it, you'll see we were
 right!

 Hmm.. +1 trainers suck.. lets try to get unlimited bombs!
 From experience I know that when setting item values it's usually done
 together in the same routine (like the lives and hearts in The Smurfs)

 Let's go back to $2b6 and check out what else is there.

 .d 2b6

 0002B6: 0002B6: 3E 05          LD A,#$05
 0002B8: 0002B8: EA D8 C1       LD ($C1D8),A  <- lives
 0002BB: 0002BB: 3E 00          LD A,#$00
 0002BD: 0002BD: EA E8 C1       LD ($C1E8),A  <- dunno..?
 0002C0: 0002C0: 3E 01          LD A,#$01
 0002C2: 0002C2: EA DA C1       LD ($C1DA),A  <- hmm..?
 0002C5: 0002C5: FA DB C1       LD A,($C1DB)

 When playing the game you'll notice you get 1 bomb no matter what
 the difficulty setting is.

 The #$01 up there seems interesting. We could change the value and
 replay the game and see if the number of bombs has changed.
 Or we could look for a decrease..

 .h 3d ea da c1
  0037E3
 End of file.

 Aha! Just one! I think we got it! Let's whip out the D command!

 .d 37d8 <- go back!

 0037D8: 0037D8: 94             SUB H
 0037D9: 0037D9: 93             SUB E
 0037DA: 0037DA: 93             SUB E
 0037DB: 0037DB: 0A             LD A,(BC)
 0037DC: 0037DC: 0A             LD A,(BC)
 0037DD: 0037DD: FA DA C1       LD A,($C1DA)  <- read it
 0037E0: 0037E0: A7             AND A         <- check if zero!
 0037E1: 0037E1: 28 06          JR Z,$0037E9  <- if so, don't decrease
 0037E3: 0037E3: 3D             DEC A         <- decrease it
 0037E4: 0037E4: EA DA C1       LD ($C1DA),A  <- store it!
 0037E7: 0037E7: 18 29          JR $003812
 0037E9: 0037E9: C9             RET           <- exit routine

 Ok this almost looks like the life decrease, minus that strange cheat (?)
 thing.

 Let's change the DEC A to NOP

 .w 37E3 00

 tada! a +2!

 Now you can complete the game by blowing everything away!


 Small rule:

 The smaller the game, the easier it is to train.

 Small 32k or 64k games can be trained in seconds.

 Before I finished this disassembler I was training Mr. Do and Pacman
 and Ms. Pacman, etc etc, just with a file editor!

 Have fun training. You don't have to be an expert in Z80 to train.
 I've never programmed Z80 before, but as you can see, it's no problem!

----------------------------------------------------------------------------
@endnode

@node HeddleyAutoIndex "Index"
@remark Index auto-generated by Heddley
Index of database Heddley

Documents

@{"How to Install Super Magic Disassembler" link "install1"}
@{"HOW TO REGISTER" link "register"}
@{"How to use SMD's Game Boy Disassembler" link "Gameboycom"}
@{"Info on Pan" link "Pan"}
@{"Introduction to SUPER MAGIC DISASSEMBLER" link "intro"}
@{"Some info on training Game Boy games" link "GameBoytrain"}
@{"SPC700 DISASSEMBLER COMMANDS" link "SPC700"}
@{"SUPER MAGIC DISASSEMBLER COMMANDS" link "command"}
@{"SUPER MAGIC DISASSEMBLER v1.4" link "Main"}
@{"TIPS ON USING SPC700 DISASSEMBLER" link "tipsspc"}
@{"TIPS ON USING SUPER MAGIC DISASSEMBLER" link "tipssnes"}
@{"What's in the package?" link "contents1"}
@{"Yo what up bro?!" link "greets1"}

Buttons

@{"-Pan- of ANTHROX" link "Pan" 0}
@{"COMMANDS" link "command" 0}
@{"CONTENTS" link "contents1" 0}
@{"GAME BOY COMMANDS" link "Gameboycom" 0}
@{"GAME BOY TRAINING TIPS" link "GameBoytrain" 0}
@{"GREETS" link "greets1" 0}
@{"HOW TO REGISTER" link "register" 0}
@{"HOW TO USE" link "tipssnes" 0}
@{"INSTALL" link "install1" 0}
@{"INTRODUCTION" link "intro" 0}
@{"SOUND ADVICE" link "tipsspc" 0}
@{"SPC700 COMMANDS" link "SPC700" 0}
@endnode
