Skip to content
SMASH.NES

Tiles, OAM, and animation

Fighter art starts as four authored sheets on a shared 32×40 canvas. The generator slices 8×8 cells, removes transparent cells, deduplicates identical tiles, and also recognizes flipped variants. It emits compact visible-cell commands plus semantic frame and timing tables. The runtime does not scan a mostly transparent canvas during battle.

Generated source data

Animation timeline viewer

Choose a fighter and action, then scrub the authored frame timeline. Poses and frame durations come from generated fighter metadata; attack windows come from the matching character specification.

Selected source-sprite pose

Orange means collision is active for a melee action. Projectile specials launch on accepted input; their visual timeline is not projectile startup.

Rizer curls in the air with a small bullet to his right. Simon remains grounded.
native capture · 256 × 240
  1. W, then K: the bullet travels straight.
  2. He keeps the curl while airborne.
Shoot on the way through.Rizer fires without leaving his airborne curl.

draw_fighter() selects exactly one semantic pose. Hurt overrides everything. Rizer’s airborne curl overrides action poses while airborne. Otherwise special precedes jab; airborne non-Rizer fighters choose rise, apex, or fall from vertical velocity; grounded motion uses the authored walk cadence; idle alternates at its authored rate.

The viewer reads cadence from the four character.toml sources. It is a guide to generated tables, rather than a frame-exact preview of the PPU: hardware flips, OAM priority, game-frame phase, and character position are resolved by the ROM.

NES sprite memory stores four bytes per entry: Y, tile, attributes, X. The runtime fills a RAM OAM buffer from packed cells, hides unused entries below the visible scanlines, then triggers DMA during vblank. Rendering follows simulation, so the next displayed frame matches the state that the test export reports.

The project budget is explicit: 244 deduplicated fighter tiles plus eight effect tiles leave four slots in the 256-tile sprite pattern table. Effects draw before fighters; Simon’s whip adds extension sprites only during active jab frames. draw_character_icon() recovers horizontal flip through attribute bits rather than storing another tile.

Screenshots verify presentation alongside state

Section titled “Screenshots verify presentation alongside state”

The emulator suite reads rendered frame IDs at $06FE, then waits an additional game tick before saving a screenshot so the corresponding OAM buffer has reached the PPU. Fighter scenarios cover idle, movement, jump, jab, special, hurt, and recovery; Rizer includes all four curl poses. See fighter_tas.lua.

The source generator and the verification boundary are covered next in testing.