---
title: "R.O.B. (Reverse-engineering Opcode Buddy)"
url: https://manvsmidi.com/projects/rob/
category: tool
status: wip
date: 2026-04-22
tags: [nes, decompilation, python, game-genie, emulation]
related: [rommage, streetkombat, supersonic, dungeonremaster2, mario3d, exhumed-prince]
---

# R.O.B. (Reverse-engineering Opcode Buddy)

> A 6502 disassembler for NROM NES games that writes one hyperlinked HTML listing, plus a scripted-emulator harness for discovering what RAM bytes and routines actually mean. Developed against Capcom's 1942.

Tool · In progress · 2026-04-22

- [Source](https://github.com/sadovsky/rob)

R.O.B. takes an iNES ROM and produces a single self-contained HTML page: address, bytes, label, mnemonic, operand and comment columns, in the style of the well-known Super Mario Bros. disassembly, with every jump target and data reference turned into an in-page link. The test subject is *1942* (Capcom, 1985). The ROM isn't in the repo; a pre-rendered `1942.html` is.

## Disassembly

`disasm.py` is plain Python with no dependencies.

- Recursive descent from the NMI, RESET and IRQ vectors, following `JSR`, `JMP abs` and branches.
- Routines reached only through dispatch tables are recovered heuristically: the byte after every `RTS`/`RTI`/`JMP`/`BRK` is tried as an entry point, and so is every 16-bit word in unclaimed data that points into PRG. A tentative trace only counts if it runs at least six clean instructions, ends in a terminator and contains no `BRK`.
- Anything not reached is emitted as `.byte` data. Hardware registers get names (`PPUCTRL`, `OAMDMA`, ...).
- `roundtrip.py` reparses the HTML and checks it rebuilds the PRG exactly: 32768 of 32768 bytes on 1942.

Limits: mapper 0 only, no bank switching, no indirect-jump tracing, no CHR decoding.

## Finding out what things mean

Auto-labels like `L_c2e8` only get you so far. `scenarios.py` boots the ROM in nes-py, plays scripted button sequences (press start, autofire, idle, die once, ...), snapshots RAM at checkpoints, and joins every changed byte to the store instructions in the disassembly that write it. `drift.py` adds per-byte timelines tagged UP, DOWN, SAW or FLIP.

There's Game Genie tooling too: `genie.py` decodes codes to an address in the listing, and `genie_candidates.py` ranks patchable bytes (counter decrements, comparisons, dispatch-table entries) and suggests codes to try. `fiber_trace.py` walks 1942's coroutine-style entity system one fiber at a time. Results go into `labels.json`, which is up to 211 named addresses.

![The RAM map section of 1942.html: named addresses such as Joypad1_State, Score_D4, Lives_Ones and ExtraLife_PendingFlag, each with a comment on what reads or writes it](https://manvsmidi.com/_astro/ram-map.BbTZClHb.png)
*Part of the RAM map in 1942.html, built from labels.json. Each name comes with notes on the code that touches it.*

```bash
python3 disasm.py 1942.nes -o 1942.html
python3 scenarios.py press_start
```

## Connected projects

- [rommage](https://manvsmidi.com/projects/rommage/index.md): shared tags: game-genie, emulation
- [Mortal Kombat vs Street Fighter II](https://manvsmidi.com/projects/streetkombat/index.md): shared tags: emulation
- [Super Sonic Bros.](https://manvsmidi.com/projects/supersonic/index.md): shared tags: emulation
- [dungeonremaster2](https://manvsmidi.com/projects/dungeonremaster2/index.md): shared tags: decompilation
- [mario3d](https://manvsmidi.com/projects/mario3d/index.md): shared tags: decompilation
- [Prince of Persia Apple II: Modern Port Experiments](https://manvsmidi.com/projects/exhumed-prince/index.md): shared tags: decompilation
