I need something where ONLY the opcodes are visible, so that I can run it back through a compiler and get the EXACT rom back out of it.
The simple answer: you can't.
Disassemblers aren't smart enough to detect code from data. So it's going to try turning the data into junk opcodes.
There have been other topics before stating why building a disassembler that IS smart enough is practically impossible.
Disassembly is only useful if you have small piece of the ROM you know is code (like a subroutine) and you don't want to have to trace every possible branch in an emulator.
I want to generate the full disassembly of a game (lets say Super Mario World so I can hack some cheats into it), then recompile the rom so I can play on an emulator. How do I do that. Say I want to disassemble SMW starting at $103C, but I don't know if $103C is RIGHT IN THE MIDDLE OF A COMMAND, or if it is at the border BETWEEN 2 commands. How do I know which it is. If I try to insert my own code at a point IN THE MIDDLE OF A COMMAND, then I'm going to break the rom. If I insert it BETWEEN to commands, then I'm good, EXCEPT in the event that absolute-location based JMP commands now no longer point to the right place (Would NOT cause a problem though if the JMP command was relative).
As for disassembling the full code, that should be easy.
One clue to detect code from data is this. Looking at some info online, ROM can be accessed by calling to these memory locations.
$8000-$FFFF ROM Data that is mapped here depends on the cartridge.
$40-$7D $0000-$FFFF ROM Data that is mapped here depends on the cartridge.
IN other words, raw data pressent in the rom can be read from here.
So if there is code earlier in the rom that calls for reading from these locations, then these locations are being used for data NOT CODE, thus the regions of the rom used data regions can be mapped out and stored in a separate data file (which WILL be needed when recompiled, so that the game's data can be reinserted), and therefore NOT mistaken for code. If lets say the disassembler read this from an earlier point in the rom
LDA #$00 ;set counter to 0
STA $0000 ;set counter to 0
MyLoop:
LDA $(8000+$0000) ;take rom data represented by memory location $(8000 + counter) and
STA $(0001+$0000) ;put it in ram memory location $(0001 + counter)
INC $0000
LDA $0000
CMP #$FF
BEQ SomewhereOutsideThisLoop
JMP MyLoop
SomewhereOutsideThisLoop:
more ASM code down here...
then the didsassembler will know by the fact that memory locations $8000 to $80FE were read means clearly that ROM locations $0000 to $00FE contain GAME DATA, and NOT programing code, and therefore this region of ROM should be sent to a separate data file, and IGNORED by the disassembler.
It's as simple as that.
By the way, the game I'm disassembling isn't a standard SNES game in this case. I've been trying to disassemble a Satellaview game, BS Zelda.