That's data, not code. 100% certain. I can tell by the pattern. You get a kind of "gut feeling" for this stuff the familiar you get with it; pretty sure everyone here can attest to that. :-)
You cannot simply take a ROM and dissassemble it and expect "obvious" results. It doesn't work like that. It's up to you, the individual doing the reverse-engineering, to figure out what is code vs. data. Disassemblers tend to not cater well to this kind of thing**. You get to put in long, long, long hours. PRG doesn't always mean "program/code" either, as many games use CHR-RAM thus graphical data is stored in PRG (and sometimes is compressed too, varies per game). You get to RE all of it. :-)
You're better off if you can pinpoint something you want to reverse-engineer -- try to use breakpoints in FCEUX/Mesen/etc. to find out "where" the code might be, disassemble things (hopefully with the correct PRG bank and origin address), then look at that specific code. You will be working in the emulator in real-time *as well* as referring to the dissassembly. Large games that involve mappers (i.e. switch PRG) make this a bit more complicated.
I could show you what I did with the Neo Demiforce FF2e/FF2j intro replacement, where I had to disassemble the last PRG bank (which represented $C000-FFFF) + inject my intro code and graphics + reassemble the entire thing (meaning I had to use a dissasembler that generated code that could be reassembled by a compatible assembler), but I haven't gotten around to putting together something official/clear/concise that explains it. It's a mess -- RE'ing always is. Here's the directory listing and bat file, which won't make much sense to you, but gives you some idea of the mess. The disassembler I used was TRaCER for MS-DOS (I'm the author) and the assembler I used was x816 for MS-DOS. Note neither of these programs work on present-day Windows:
Code: Select all
1998-08-23 13:38 116,397 C000.ASM
1998-08-23 13:48 16,384 C000.BIN
1998-08-23 13:48 553,527 C000.LST
1998-03-19 00:28 245,776 FF2-MOD.NES
1998-08-23 13:48 262,160 ff2-test.nes
1998-08-24 03:59 8,192 ff2-test.sav
1998-06-13 15:53 169,479 FF2-TEST.ZIP
1998-08-23 13:48 8,638 INTRO.ASM
1998-03-16 09:52 111 make.bat
1998-03-26 14:09 1,736 pal.txt
make.bat:
Code: Select all
@echo off
x816 -l c000.asm
del ff2-test.nes
copy /b ff2-mod.nes+c000.bin ff2-test.nes > nul
dir ff2-*.*
Other random brain dump stuff:
Part of the above process involved using
fc /b to compare the newly-assembled ROM to that of the old, to ensure only the bytes that differed were the stuff I had changed. Back then hex editors like HxD didn't exist, but there were other tools that did it similarly; I just happen to be used to
fc which came with DOS/Windows.
I recommend doing exactly that with a straight disassembly (i.e. no changes) as well: disassemble something, then reassemble it using a compatible assembler, and see if the results are identical. If they aren't, then you get to figure out why -- it's often the assembler picking some wrong addressing mode, an incompatibility between disassembler and assembler, or a downright bug in the assembler.
If things match, great. After that, you get to try and start "piecing together" bits. That often means going and editing the disassembly by hand to deal with places where there are code and data intermixed, turning the data into
.db statements, and then manually fixing the code so it's legible. This often happens on a "data/code boundary", where the piece of data happens to be a legitimate instruction (but isn't actually code), thus disassembled code with an operand, but the *actual* code is all of, or part of, the operand bytes themselves. This is hard to describe in words so here's an example. Take these addresses and their raw bytes:
Code: Select all
f9fb: d4
f9fc: 15
f9fd: e2
f9fe: ea
f9ff: 45
fa00: 4c
fa01: 9e
fa02: fa
These might get disassembled like so:
Code: Select all
f9fb: d4 .db $d4 ; invalid opcode
f9fc: 15 e2 ora $e2,x
f9fe: ea nop
f9ff: 45 4c eor $4c
fa01: 9e .db $9e ; invalid opcode
fa02: fa .db $fa ; invalid opcode
But after appropriate analysis/reverse-engineering, it's determined that $FA00 is actually code, while preceding bytes are data. So once cleaned up manually, you get this:
Code: Select all
f9fb: d4 .db $d4
f9fc: 15 .db $15
f9fd: e2 .db $e2
f9fe: ea .db $ea
f9ff: 45 .db $45
fa00: 4c 9e fa jmp $fa9e
How you determine this is through a combination of using an emulator to "walk through" the code in real-time to figure out what's actual code vs. data, and staring at the disassembly + following it carefully. In this example, I learned that there was code doing
jmp $fa00 so I therefore knew $fa00 itself had to contain code -- then later found some code that read $f970 to $f9ff as data. Hence, I knew what was what.
I'll add that this was in the days *before* there were emulators with CDL capability... but it doesn't change a thing -- you still have to know what it is you're looking at, you can't rely on a machine to "magically figure it out".
If your reaction is "oh my god, doesn't that take a lot of time to do?!?!" the answer is a
big fat yes. Welcome to reverse-engineering.
As for games which use mappers / multiple banks of PRG, quite often you have to split the ROM up into its individual PRG banks and dissassemble each as needed. An example of some of the never-completed work I did on Rampart (Japanese release) required that (I've since deleted all my work since someone last year or the year before made an English release so my work was pointless), ditto with some work I was doing on RoboWarrior / Bomber King:
Code: Select all
2016-09-19 00:12 557,626 prg00.asm
2016-09-19 00:07 16,384 prg00.bin
2016-09-19 00:58 553,584 prg01.asm
2016-09-19 00:07 16,384 prg01.bin
2016-09-19 00:07 16,384 prg02.bin
2016-09-19 00:07 16,384 prg03.bin
2016-09-19 00:07 16,384 prg04.bin
2016-09-19 00:07 16,384 prg05.bin
2016-09-19 01:35 524,844 prg06.asm
2016-09-19 00:07 16,384 prg06.bin
2016-09-19 01:00 470,263 prg07.asm
2016-09-19 00:07 16,384 prg07.bin
2016-06-13 22:45 131,088 Robo Warrior (U) [!].nes
2016-09-19 00:09 131,072 rom.bin
RoboWarrior is
mapper 2 / UNROM game, so the last 16KB bank is hard-wired to $C000-FFFF. You'll probably notice how I disassembled certain banks: prg00, prg01, and prg06 all had scattered code I was needing to examine/RE, and of course, prg07 (the last bank, thus a good starting point since it contains all 6502 vectors; for mappers like this it tends to contain "the guts" with critical routines that get used everywhere, etc.). Started with the last bank, then gradually worked through the code (emulator + disassembler combined) until I figured out what other PRG banks I needed to look at, disassembled them, blah blah. The disassembler I used for this was
disasm6 v1.5. There's no
.bat file because I was doing everything manually by hand.
Starting to get the picture?
** Warning to pedants: yes I'm aware of a PHP-based disassembler that can read/use CDL files. You cannot tote this as a one-line "solution", and shouldn't. Because then you have to explain how to generate a CDL file, and how an emulator generates that file, and how the emulator determines code vs. data, and how the person playing the game while generating the CDL has to do every single thing possible in the game, down to miniscule things like loading a menu from point A vs. point B, pressing up vs. down vs. left vs. right in every place in the game including pause screens, etc. -- when I say LITERALLY DO EVERY SINGLE THING, I do mean LITERALLY **EVERY SINGLE THING**.