Skip to content

Fix 8x16 sprite tile fetch for odd tile numbers - #784

Open
IronCodeStudios wants to merge 1 commit into
bfirsh:mainfrom
IronCodeStudios:fix/8x16-sprite-odd-tile
Open

Fix 8x16 sprite tile fetch for odd tile numbers#784
IronCodeStudios wants to merge 1 commit into
bfirsh:mainfrom
IronCodeStudios:fix/8x16-sprite-odd-tile

Conversation

@IronCodeStudios

Copy link
Copy Markdown

Summary

In 8×16 sprite mode, a sprite whose tile index is odd selects the $1000
pattern table. Tiles for that table live at ptTile[] indices 256..511, so
the top tile of the pair should map to topTileNum + 256.

The current code computes topTileNum - 1 + 256, which is off by one for
odd tile numbers and fetches the wrong pattern tile — scrambling 8×16 sprites in
MMC3 games that lean on them, most visibly Super Mario Bros. 3 and Kirby's
Adventure
. This is the sprite-layer corruption reported in #771.

Fix

let top = topTileNum + ((sprTile & 1) !== 0 ? 256 : 0);

Even tiles ($0000) are unchanged; odd tiles ($1000) now index topTileNum + 256.
The latchAccess calls below already use topTileNum against sprBaseAddr, so
they were correct and are untouched.

Testing

  • npm run build clean; npm test583 passed / 0 failed / 29 skipped,
    AccuracyCoin 107/27 (unchanged from main), prettier --check passes.
  • Verified visually on a real Super Mario Bros. 3 ROM: sprites render cleanly and
    the scramble is gone (compared against stock and 2.0.0).

Relationship to #666

#666 also fixes this same off-by-one but bundles it with a CPU IRQ-latching
change and MMC5 nametable changes. This PR isolates just the sprite fix.

Heads-up for maintainers: #666's IRQ-latching change (leaving masked IRQs latched
until serviced) regresses the APU "Frame Counter IRQ" AccuracyCoin test — the
frame-counter IRQ is a level line the APU de-asserts on acknowledgement, so
latching leaves a stale request that fires spuriously. This sprite-only PR avoids
that area. (#771 also reports an audio symptom that's out of scope here.)

In 8x16 sprite mode, an odd tile index selects the $1000 pattern table,
whose tiles live at ptTile[] indices 256..511 — so the top tile should be
`topTileNum + 256`. The code used `topTileNum - 1 + 256`, which is off by
one and fetches the wrong tile, scrambling 8x16 sprites in MMC3 games such
as Super Mario Bros. 3 and Kirby's Adventure (the sprite-layer corruption
reported in bfirsh#771).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant