aboutsummaryrefslogtreecommitdiff

readrom is an objdump-like utility that reads a given NES/Famicom ROM file and shows information about it. You can run it by simply passing a ROM file to it. For example, for the Jetpac NTSC ROM file:

$ readrom jetpac.NTSC.nes
# => output
Header:
  Kind:             NES 2.0
  PRG ROM size:     32768 bytes (32KB)
  CHR ROM size:     8192 bytes (8KB)
  Mapper:           NROM
  Mirroring:        Horizontal
  CPU/PPU timing:   NTSC
Vectors:
  NMI:              0xa2f8
  Reset:            0xa3c2
  IRQ:              0xa3c1

But this utility can do some more complex things. For example, you can tell it to disassemble a subroutine via the -d/--disassemble flag. If the above output is telling us that NMI code starts at 0xa2f8, we can try:

$ readrom -d '$a2f8' jetpac.NTSC.nes
# => output
$A2F8:  24 20       bit $20

Note that hexadecimal values can also be formatted like this 0xa2fb or simply a2fb, whatever feels more convenient to use. In any case, they should be written as a 16-bit address.

All of that being said, poking for addresses can be tedious. That's why you can also pass names that you already know. For that, you will need to also pass the -n/--nasm-directory, pointing to the path to your .nasm/ directory. With that, if you have assembled the ROM file with nasm with the --write-info flag, you will have something like this:

# On the jetpac.nes repository
$ nasm --write-info -o jetpac.NTSC.nes src/jetpac.s
$ readrom -d nmi -n .nasm/ jetpac.NTSC.nes
# => output
$A2F8:  24 20       bit $20
$A2FA:  30 01       bmi @save_registers
$A2FC:  40      rti

  @save_registers:
$A2FD:  48      pha
$A2FE:  8A      txa
$A2FF:  48      pha
$A300:  98      tya
$A301:  48      pha
$A302:  A9 00       lda #$00
$A304:  8D 03 20    sta $2003
$A307:  A9 02       lda #$02
$A309:  8D 14 40    sta $4014
$A30C:  24 28       bit $28
$A30E:  10 03       bpl @check_pause
$A310:  20 EE 8C    jsr nmi_update_scores

  @check_pause:
$A313:  24 38       bit $38
$A315:  50 03       bvc @increase_rand
$A317:  20 62 A2    jsr nmi_hud_toggle_pause

# and much more...

Moreover, if you have built your ROM file with the --asan flag from nasm, then you will have the memory.txt file inside of .nasm/. This tool is able to pick up this file and decorate some of the values from the previous output. Hence:

# On the jetpac.nes repository
$ nasm --write-info --asan -o jetpac.NTSC.nes src/jetpac.s
$ readrom -d nmi -n .nasm/ jetpac.NTSC.nes
# => output
$A2F8:  24 20       bit Globals::zp_flags
$A2FA:  30 01       bmi @save_registers
$A2FC:  40      rti

  @save_registers:
$A2FD:  48      pha
$A2FE:  8A      txa
$A2FF:  48      pha
$A300:  98      tya
$A301:  48      pha
$A302:  A9 00       lda #$00
$A304:  8D 03 20    sta OAM::m_address
$A307:  A9 02       lda #$02
$A309:  8D 14 40    sta OAM::m_dma
$A30C:  24 28       bit Globals::zp_extra_flags
$A30E:  10 03       bpl @check_pause
$A310:  20 EE 8C    jsr nmi_update_scores

  @check_pause:
$A313:  24 38       bit Driver::zp_flags
$A315:  50 03       bvc @increase_rand
$A317:  20 62 A2    jsr nmi_hud_toggle_pause

# and much more...

Now you can see the same output as before, but the first instruction reads as bit Globals::zp_flags instead of bit $20, because readrom now knows that the memory address $20 is associated with this variable.

Moreover, and as you can tell, by default readrom will print things in a human-readable format. But you can also tell it to just write all the bytes with the --raw flag so you can further manipulate the related bytes with another tool. For example:

# On the jetpac.nes repository
$ nasm --write-info -o jetpac.NTSC.nes src/jetpac.s
$ readrom -d nmi -n .nasm/ --raw jetpac.NTSC.nes | hexdump -C
# => output
00000000  24 20 30 01 40 48 8a 48  98 48 a9 00 8d 03 20 a9  |$ 0.@H.H.H.... .|
00000010  02 8d 14 40 24 28 10 03  20 ee 8c 24 38 50 03 20  |...@$(.. ..$8P. |
00000020  62 a2 e6 0a a9 08 25 20  d0 6e 24 2e 10 0b a9 00  |b.....% .n$.....|
00000030  50 02 a9 70 85 04 20 bc  a2 a5 50 29 08 f0 34 2c  |P..p.. ...P)..4,|
00000040  02 20 a9 28 8d 06 20 a9  4b 8d 06 20 a5 53 18 69  |. .(.. .K.. .S.i|
00000050  10 8d 07 20 24 27 10 15  2c 02 20 a9 28 8d 06 20  |... $'..,. .(.. |
00000060  a9 56 8d 06 20 a5 54 18  69 10 8d 07 20 a5 50 29  |.V.. .T.i... .P)|
00000070  f7 85 50 a5 20 aa 29 20  f0 13 a5 cb d0 06 20 78  |..P. .) ...... x|
00000080  89 4c 7f a3 20 59 91 a5  20 29 df 85 20 8a 29 01  |.L.. Y.. ).. .).|
00000090  d0 06 a5 30 f0 02 c6 30  24 20 50 13 a9 bf 25 20  |...0...0$ P...% |
000000a0  85 20 2c 02 20 a5 81 8d  01 20 a5 80 8d 00 20 2c  |. ,. .... .... ,|
000000b0  02 20 a9 00 8d 05 20 8d  05 20 20 1d 8b a9 7f 25  |. .... ..  ....%|
000000c0  20 85 20 68 a8 68 aa 68  40                       | . h.h.h@|