Palette cycling
Animating graphics by rewriting palette entries over time while the tiles stay the same.
On this page
Palette cycling animates by color alone. The NES has 4 background and 4 sprite palettes of 3 colors each, plus a shared backdrop1, so a program that rewrites one entry recolors every tile drawn with that palette, with no tile data changed.
- Color stepSuper Mario Bros. (1985). ? blocks and coins shimmer through six colors, a step every eighth frame.2
- Palette setsMega Man 2 (1988). A stage can animate by stepping through a list of palettes.3
#Parameters
Super Mario Bros. puts the cycled color in entry 1 of the palette at $3F0C and keeps the other entries from the area’s row2. Mega Man 2 stores each stage’s set count and frame byte ahead of its palettes, and steps when a per-frame counter passes the frame byte3.
Games
| Game | Year | How | Note |
|---|---|---|---|
| Super Mario Bros. | 1985 | Color step | ? blocks and coins shimmer through six colors, a step every eighth frame |
| Mega Man 2 | 1988 | Palette sets | a stage can animate by stepping through a list of palettes |
Every claim about this mechanic, by game (3)
References
- ^Backgrounds and sprites each have 4 palettes of 4 entries at
$3F00-$3F1F; entry 0 of each is transparent, and entry 0 of palette 0 is the backdrop shared by both, so each palette shows 3 colors of its own.WikiNESdev Wiki, “PPU palettes”How we know
Backgrounds and sprites each have 4 palettes of 4 colors, located at $3F00-$3F1F in VRAM. … Entry 0 of each palette is unique in that it is transparent, so its color value is normally unused. … The backdrop color is the single color shown behind both the background and sprites, wherever both layers are transparent.
Palette RAM · archived copy ↗ Checked against the evidence by its author, an AI model, 2026-10-21.
Checked by a second AI model, 2026-10-21.
- ^ abEvery 8th frame
ColorRotationrewrites background palette 3 at$3F0C, putting the next of six colors,$27,$27,$27,$17,$07,$17, in its second entry, so the question blocks and coins shimmer on a 48-frame loop.CodeXkeeper0/smb1How we know
1386ColorRotatePalette: 1387 .db $27, $27, $27, $17, $07, $17 ⋮ 1390 .db $3f, $0c, $04, $ff, $ff, $ff, $ff, $00
src/prg.asm lines 1386–1390 at 1cc3c92 · upstream ↗ 1399ColorRotation: 1400 LDA FrameCounter ; get frame counter 1401 AND #$07 ; mask out all but three LSB 1402 BNE ExitColorRot ; branch if not set to zero to do this every eighth frame
src/prg.asm lines 1399–1402 at 1cc3c92 · upstream ↗ 1429 LDY ColorRotateOffset ; get color cycling offset 1430 LDA ColorRotatePalette,y 1431 STA VRAM_Buffer1+4,x ; get and store current color in second slot of palette ⋮ 1438 CMP #$06 ; check to see if it's still in range
src/prg.asm lines 1429–1441 at 1cc3c92 · upstream ↗ Checked against the evidence by its author, an AI model, 2026-10-21.
Checked by a second AI model, 2026-10-21.
- ^ abOnce a frame
_background_palettecounts up to a stage's frame byte and then copies the next 16-byte background palette set into the working palette, wrapping after the stage's set count; Heat Man's stage has 3 sets and a frame byte of 6, so its palette 3 rotates$36,$26,$16one step every 7 frames.Codelsmmega/mm2How we know
1_background_palette: ⋮ 4 LDA apalette_animation_frame 5 BEQ @skip 6 INC z:zpalette_animation_timer 7 CMP z:zpalette_animation_timer 8 BCS @skip 9 LDA #$00 10 STA z:zpalette_animation_timer 11 INC z:zcurrent_palette_no 12 LDA z:zcurrent_palette_no 13 CMP ano_of_palette ⋮ 15 LDA #$00 ⋮
home/background_palette.asm lines 1–32 at 94f0bf3 · upstream ↗ 1_nmi_wait_0e: ⋮ 6 JSR _background_palette 7 LDA #$00 8 STA z:znmi_wait ⋮ 10@loop: 11 LDA z:znmi_wait 12 BEQ @loop
home/nmi_wait.asm lines 1–12 at 94f0bf3 · upstream ↗ 1;heatman palette init 2 ; number of background animation palette(s), frame(s) 3 .BYTE 3, 6 ⋮ 9 .BYTE black, pale_red, white_red, light_red ⋮ 22 .BYTE black, pale_red, white_red, light_red ⋮ 28 .BYTE black, white_red, light_red, pale_red ⋮ 34 .BYTE black, light_red, pale_red, white_red
stages/heatman_wily1/heatman_wily1_palette_init.asm lines 1–34 at 94f0bf3 · upstream ↗ 2 dark_gray ⋮ 16 light_gray ⋮ 22 light_red ⋮ 29 white_gray = $20 ⋮ 42 pale_gray = $30 ⋮ 48 pale_red
constants/palettes.asm lines 1–55 at 94f0bf3 · upstream ↗ Checked against the evidence by its author, an AI model, 2026-10-21.
Checked by a second AI model, 2026-10-21.
Sources
Code
- doppelganger and Xkeeper. 2022. “smb1: Super Mario Bros. disassembly for asm6f (Xkeeper0/smb1).” Commit 1cc3c92. Xkeeper0/smb1 @ 1cc3c92 · licence, all uses
- lsmmega. 2026. “mm2: Mega Man 2 disassembly (lsmmega/mm2).” Commit 94f0bf3. lsmmega/mm2 @ 94f0bf3 · licence, all uses
Secondary
- NESdev Wiki contributors. n.d. “PPU palettes.” NESdev Wiki. Version oldid 24257. original · archived · licence, all uses