Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 16 additions & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,22 @@ own 1 back, so read `exitCode` out of the report if you need to tell them apart.
They are not one machine at two speeds: 312 scanlines against 262, 3.2 dots to a CPU cycle against
3, 50.0070 frames a second against 60.0988, and a different APU table for everything counted in CPU
cycles. So **a PAL run and an NTSC run of the same ROM are not comparable** -- `run.region` in the
report is part of what to check before diffing two of them, alongside `run.state.startedFromPowerOn`.
report is part of what to check before diffing two of them, alongside `run.state.startedFromPowerOn`
and `run.hacks`.

`run.hacks` is the third thing in that list, and it is there for the same reason: `--hack
unlimited-sprites` draws the sprites the chip would have dropped, so a scanline holding more than
eight of them stops flickering. Nothing a game can observe changes -- the overflow flag still rises,
$2004 still answers with what the sprite hardware is holding, and the cartridge sees the same address
bus, which is what keeps MMC3's scanline counter honest -- but the picture is not the one the
hardware would have drawn, so two runs that disagree about it are not two measurements of the same
thing. Every hack is off unless it is named. `hack unlimited-sprites on|off` does the same thing
inside an interactive session, which is how to take the same frame twice and diff the pictures.

Do not go looking for a game to see it on. A cartridge is written to stay under eight sprites a line
and they mostly manage it -- Punch-Out!!'s first fight peaks at seven, Battletoads' first level at
eight -- so the demonstration is `sprite-limit/sprite-limit.nes`, which puts all sixty four on one
line and is assembled by `SpriteLimitROM` beside it rather than vendored as bytes.

Everything that differs is in `Region`, including the PPU's OAM decay window, which has to outlast
the machine's own blanking interval or every sprite in the game vanishes once a frame. Its tables
Expand Down
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,11 @@ A CHR viewer shows every tile of a bank with a zoomed preview, coloured with any
palettes the game is using, and it updates live as CHR RAM is rewritten and palettes change. There
are also toggles to hide the background or the sprite layer without the game noticing.

A **Hacks** menu, for the things the console does not do. **Unlimited Sprites** draws the sprites the
chip would have dropped, so a scanline holding more than eight of them stops flickering; the game
cannot tell, since the overflow flag still rises and the cartridge still sees the same address bus.
It is off unless it is ticked, and the tick is remembered.

All of it is in headless mode too — `break`, `watch`, `step` and `disasm` are commands in the
interactive session, so the same questions can be asked from a script.

Expand Down Expand Up @@ -276,6 +281,12 @@ seconds to start up, the jar about a third of one.
run without a patched file existing anywhere. The report's `cart.patches` says how many records
each one held, and `cart.sha256` is the digest of the patched image rather than the file on disk —
a patch that turns out to hold no records is one cut against a different dump of the game.
- **`--hack NAME`** switches on one of the things the console does not do, all of which are off
otherwise. There is one so far, `unlimited-sprites`, which draws the sprites the chip would have
dropped so that a scanline holding more than eight of them stops flickering. Nothing a game can
observe changes — the overflow flag still rises and the cartridge sees the same address bus — but
the picture is not the one the hardware would have produced, so `run.hacks` in the report is part
of what to check before diffing two of them.
- **`--interactive`** reads commands on standard input and answers each with a line of JSON, for
when you do not yet know the question well enough to write it down. It is also where the debugger
lives without a window: `break`, `watch`, `step` and `disasm`, with `run` reporting back what
Expand Down
Loading