News: 11 March 2016 - Forum Rules

Author Topic: SNES Code Regenerator  (Read 3007 times)


  • Jr. Member
  • **
  • Posts: 32
    • View Profile
SNES Code Regenerator
« on: July 21, 2015, 11:34:50 am »
Hi I'm oziphantom and I come from C64 land. Which is technically ROM hacking( if its a Cart or OS...) but doesn't seem to get much of a looking here..anyhoo.
I'm getting back into SNES work, to which I figured, owing to the numerous awesome hacks, translations et al, would have amazing tools 8) Alas to my soft 64 cushioned eyes, turns out it is a barren wasteland...  :o

So I've decided to port my #1 C64 tool to SNES. Regenerator AKA Interactive Dissasembler

What does it do?
  • Open a ROM and it will start dissaembling from bank 0 - at the moment it is mostly hard coded/hacked up to be LOROM FAST so bank $80
  • From which you can then mark sections of the code as Code, Bytes, Words, Longs and a couple of extra types. Text at some point too
  • It will scan the code and make Auto Labels(see below) that make the code more readable
  • Of cause you can add your own/edit the autos to be something more meaningful. Once a label is updated all references to it are updated automatically,both ROM and RAM locs
  • You can add side comments like ; this does a thing, full line coming eventually as well
  • There are build in helps for comments, that will read the data and comment it as what it does, REP #$30 - a,x,y 16bit, or 4200 0F, Screen on Full brightness etc does 42XX,43XX DMA, Controller,Dec,Binary
  • Constants, you can make a table that assigns a string to a number for an "enum", then tell it what RAM loc uses that enum and it will find all LD? X ST? RAM and change the X to the enum value string.
    It will also find all LD? CM? # and change that the enum string, it will then find the BNE/BEQ and change their labels to be _String or _notString depending on BN/EQ,it also follows the branch to see if it is a chain
  • Goto Address, why scroll for it, let the computer find it
  • Goto Param, with Return, handy for following a JMP/JSR, it will push the spot you where at onto a stack so you can R to return back, makes it so much easier to follow code
  • Search, hunts for raw text, so address, labels, hex, word etc, but not the fancy table text stuff
  • Manually set the A,X,Y size. While the dissasembler does a linear walk through code it does keep track of REP/SEP its not 100%, I should maybe add PLP, PHP as well to it. But seems to work 99% so far.
  • Limited banks, if a bank is all data then don't tick it, let the dissassemler just skip it
  • Custom data formatters,if you know the data is stored in a 1 long, 2 words and a byte format, you can make a string in a text file, and then have the tool make that format on lines, saves you having to do L, Shift+W, B, - - 100x times

Auto Label
This take something like
Code: [Select]
80/8014 5C 18 80 80               jmp $808018
80/8018 C2 30                     rep #$30
and makes it
Code: [Select]
80/8014 5C 18 80 80               jmp j808018
80/8018 C2 30       j808018       rep #$30
The system looks how how each lable is used.
If it it is LD? then it becomes aXXXXXX so you know that it is probably data
LD? () or [] then pXXXXXX also probably data
BXX then bXXXXXX so you know that it is only this bank
JMP/JSR then jXXXXXX , so you know that it only this bank, should be rts
JMP Long/ JSR Long then jlXXXXXX, so you know that it is not just this bank, should be rtl
JMP (), [] then jpXXXXXX, so you know it is a pointer table, you can then make this a word or long block, which you can then turn into labels, and it will add the pointers as labels as well.

Comment Helpers
REP/SEP, so it will read the $10,20 or $30 and comment with ;a-8/16 xy-8/16 as appropriate
42XX etc, it will look up the params and comment like so LDA #0F ; screen enable, full brightness

It will understand LD?, STZ, CM?, AND and OR. When if you do AND #7F for example it will say ;enable Screen, if you do ORA #80 it will say ;disable Screen.

Same you have a enum like so, gameMode
And you have code like
Code: [Select]
80/D5CF AF FE 38 7E lda $7E38FE
80/D5D3 C9 03 00    cmp #$0003
80/D5D6 F0 10       beq $80D5E8
80/D5D8 C9 01 00    cmp #$0001
80/D5DB D0 20       bne $80D7DD
Tell it that 7E38FE is that enum and it will make the code
Code: [Select]
80/D5CF AF FE 38 7E lda $7E38FE
80/D5D3 C9 03 00    cmp #gameMode.Puzzle
80/D5D6 F0 10       beq _Puzzle
80/D5D8 C9 01 00    cmp #gameMode.timeTrial
80/D5DB D0 20       bne _notTimeTrial
80/D5E8 _Puzzle
80/D7DD _notTimeTrial

Will it be perfect, no. 65816 has some sweet features, that can also be used horribly which means something just can't be don't nicely. Stack relative look ups for example. But since most of the SNES code was written by a person using  a Macro Assembler, this is the rare case.
Also doing stuff like this
Code: [Select]
ldx #1856
lda $0000,x
to reference 1856, is annoying, and I will need to add a label look up to handle it, but it will need a manual hunt and search though.

My question is.

What else is a must/nice to have as I have only just started pulling apart SNES ROMs I'm not really sure of the all patterns, features I will need.
Is setting Data Bank per code a big thing, that I need to handle?
Being able to Logical vs Org changes to handle code that is copied to WRAM ( is this really done? )

Any other ideas/ thought appreciated.


  • Jr. Member
  • **
  • Posts: 32
    • View Profile
Re: SNES Code Regenerator
« Reply #1 on: September 23, 2015, 04:32:50 am »
Finally got around to making it somewhat release ready, this the Alpha 0.2 version

Still only supports LOROM FAST, I've tested it on Tetris attack and Harvest Moon so far.  Windows, should support at least 8 and 10, probably 7 as well. Will need .net 4.5.2/4.6

The Docs

Super Regenerator   0.2

Main Windows
Top Left - Banks selection
This selects which banks get processed. It is best for speed to keep this down to just code banks.
To add a bank, click on the bank, then click it again. This will add it to the list and start disassembly.
Warning clicking a row that is already selected and ticked will untick it and delete the Blocks for that bank.
Adding a bank won't start doing auto labels. I recommend scanning the new bank first for obvious data areas. To help cut down misleading Auto Labels and generation time.
Then Save Data, then Open ROM again to start the Auto Parse.

Middle Left - Jump Address Stack
This shows the address you currently have on your Return stack. Bottom is the next to be returned to.

Bottom Left - ROM info, probably wrong as it looks at the snes header.

Middle - Code window
This will show the disassembly of the active bank

Open Rom
This will open and start parsing the ROM, it currently only handles LOROM FAST, it will start at 808000 and do 32K banks

Save Data
This will save all the data you have added into a folder in the ROM's location

Reload Constants
While reading the code you will work out enums to use. Since Open ROM can be slow due to Auto Labels, use this to add new values or types to the Constants system.

do Auto Constant
This will bring up a dialog as follows
This should be a LONG address in the range of 7E0000-7FFFFF
Select the name of the constant you want that address to be interpreted.
This will then scan the current banks for all
LD? [RAM loc]
then set all CM? to use the constant
then all BNE, BEQ to be _constant or _notconstant
It will then follow the branch location to follow the chain

If it finds a ST? [RAM loc] it looks at the line before for a LD? and sets that to be constant

do Group Label
Start Address - this should be a full ROM address
Count - number of labels to make
CountDown - make the first label the first number or the last number
Skip - number of bytes to skip per label
Label Base - the start string that will have the number appended to it

So if your start at 808000 and Count 5, Skip 3 with a Label Base of pLoadFunc
It will add
pLoadFunc0 at 808000
PLoadFunc1 at 808003
PLoadFunc2 at 808006
PLoadFunc3 at 808009
PLoadFunc4 at 80800C

Copy Selection - No Hex this will copy the selected code in the following format
j808F52                          dec a7E014A,x
Copy Selection - Full will copy the selected code in the following format
80/8F52 DE 4A 01    j808F52                          dec a7E014A,x

Right Click Menu

Add/Edit Label Here
This will open the dialog to add or edit the existing label for this address
Add/Edit Param Label
This will open the dialog to add or edit the existing label for the address at the param
Add Generic Label
This will let you add a label for any address
Remove Label
This will delete the label at the current address

Add/Edit comment
Allows you to add or edit a side comment ; style
Comment As
   REP/SEP - will parse the param and comment what it changes A X and Y to, eg ; A 8 bit
   2100 - will handle a LD? AND OR and STZ, commenting on what is enabled/disabled by the param
   2101 - ""
   2105 - ""
   2106 - ""
   2107_8_9_A - ""
   210B_C - ""
   43X0 DMA - handles the LD? STZ case of these registers treats as a normal DMA
   43X1 - ""
   43X0 HDMA - same but treats the value as a HDMA value
   Decimal - Byte or Word this will add a comment with the decimal value
   Binary - Byte or Word this will add a comment with the binary string
   Std Controller - Byte Lo, Byte Hi, Word. This will handle LD?, CM? and BIT and comment on which buttons are checked
Apply Comment Group
    First you select the lines you want it to be applied to, the A, X and Y based Loads, then it will look up the comment group file and apply the comments that match
    To make Comment Groups, make a folder "CommentGroups" in your SNESRegen folder, then in side that make a txt file like so

X;VRAM Dest ptr
Y;Tranfer count

   And sae it with the name of the group.
Apply Last Comment Here (Q)
   This will add the same comment you typed last time, useful for when you work out what a shared variable does and want to comment all the local places it is used. Only works on normal comments not groups

Change AXY Size
   The Disassembler tracks register size in a linear fashion this works 95% of the time, when it fails you can change the size here.
Make Param Constant
   This will include all the constant files it finds, allowing you to flag the line as using one.
   To add a new constant, make a directory call "Constants" then add a txt file with the name of the constant
   the file format is
   NAME=Value you can use $ to denote Hex value. No spaces

Make Code Block (C)
This will flag selected lines as Code
Make Byte Block (B)
This will show the selected lines as bytes, 16 per line
Use Shift to force 2 Bytes
Make Byte Block (W)
This will show the selected lines as words, 8 per line
Use Shift to force 2 Words
Make Long Block (L)
This will show the selected lines as longs, 5 per line
Use Shift to force 2 Longs

Make Pointer Add Labels
Once you have made a block words or longs, use this to make them into labels and to add a pADDR label at the address
Words will add <>Label, Longs will just add the label

Make Pointer Add Labels 8000+
Sometimes developers add 0000 or other data in with the data, this will only make labels out of the values over 8000

Insert Custom Data Format
This allows you to make pre packaged formats of Longs Words and Bytes. So for example you have a function that sets up DMA
it takes a Long src address, a word, dest address, a word, count and a byte for DMA mode.
The format is Name=X # X #
where X is L,W or B and # is the number of them, so the example above would be
When you select one of these it will add exactly that above layout into your code.
You can add and extend these in the data.lay file in the data directory

Inc Block (+numpad)
This allows you to extend a current Byte, Word or Long block by either 1,2 or 3 bytes.
+ numpad will automatically detect the block type and extend it by 1 of its type.

Dec Block (-numpad)
This allows you to shrink a current Byte, Word or Long block by either 1,2 or 3 bytes.
- numpad will automatically detect the block type and shrink it by 1 of its type.

Goto (Ctrl+G)
This will take you to the line of the given 24bit address.

Goto Param (Ctrl+Shift+G)
This will take you to the line that the param of the current line. It will then push the address on to the Return stack.

Return (R)
Pulls an address of the stack and Gotos it.

Search (F)
Lets you search for Text or hex Case Sensitive. It looks at the string in each line so will find all results. F3 will move the the next result. Search current bank only.

Make Long Pointer
Select a Word and a Byte LD? instructions, This will then set the Word to be <>Address and the Byte to be ^Address, and add said address as a label if it is not already
I'm trying to work out how to do B,B,B long pointers, Has anybody seen a Byte,Word format address rather than the Word,Byte?


  • Sr. Member
  • ****
  • Posts: 358
    • View Profile
Re: SNES Code Regenerator
« Reply #2 on: September 23, 2015, 01:33:09 pm »
SNES disassembler...

Is the output compatible with any of the SNES assemblers? -- blog/tutorial on programming for the NES


  • Jr. Member
  • **
  • Posts: 32
    • View Profile
Re: SNES Code Regenerator
« Reply #3 on: September 24, 2015, 06:17:26 am »
Interactive disassembler, makes things move faster  :)

After looking around and finding they either lack X,Y and Z, or don't work on Windows 7+ or the pages are broken... Not sure. Schasm has potential, but TASS64 has just added some improvements to the '816 mode so might stick with that for now.