On this page
  1. Parameters
  2. Related
  3. Games
  4. References
  5. Sources

A cartridge’s mapper can switch which banks of CHR ROM fill the PPU’s pattern space; the MMC3 offers two 2 KB and four 1 KB banks1. A game that switches a bank changes every tile drawn from it at once. A game without a mapper keeps one set of tiles and animates by other means.

  • FixedSuper Mario Bros. (1985). One set of tiles for the whole game.2
  • Mid-frameSuper Mario Bros. 3 (1988). The status bar gets its own tile banks, and background tiles animate by cycling banks every 8 frames.3,4

#Parameters

Super Mario Bros. 3 indexes PT2_Anim with bits 3-4 of its frame counter, so each of the four banks shows for 8 frames4. A P-Switch forces one bank in its place4. At the status bar the IRQ handler loads the bar’s two background banks and blank sprite banks, so no sprite draws over the bar3. Super Mario Bros., with one tile bank, cycles a palette entry for its blocks instead5.

Games

GameYearHowNote
Super Mario Bros.1985Fixedone set of tiles for the whole game
Super Mario Bros. 31988Mid-framethe status bar gets its own tile banks, and background tiles animate by cycling banks every 8 frames
Every claim about this mechanic, by game (4)

References

  1. ^The MMC3 maps the PPU's 8 KB of pattern space as two switchable 2 KB banks and four switchable 1 KB banks, each selected by a register write.WikiNESdev Wiki, “MMC3”
    How we know
    PPU $0800-$0FFF (or $1800-$1FFF): 2 KB switchable CHR bank … PPU $1C00-$1FFF (or $0C00-$0FFF): 1 KB switchable CHR bank
    CHR Banks · archived copy ↗

    Checked against the evidence by its author, an AI model, 2026-10-21.

    Checked by a second AI model, 2026-10-21.

    In the claim ledger

  2. ^The cartridge header declares two 16 KB PRG ROM pages and one 8 KB CHR ROM page, so the game's tile set never changes.CodeXkeeper0/smb1
    How we know
    4	.db "NES", $1a ; identification of the iNES header
    ⋮
    6	.db 2 ; number of 16KB PRG-ROM pages
    7	.db 1 ; number of 8KB CHR-ROM pages
    ⋮
    10	.db 1 ; mapper/mirroring/whatever
    
    smb1.asm lines 4–10 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.

    In the claim ledger

  3. ^ abAt the status bar the IRQ handler switches the background's two 2 KB CHR banks to the status bar's tiles and all four 1 KB sprite banks to blank tiles, so no sprite shows over the bar.CodeSouthbird's SMB3 disassembly
    How we know
    2214	; Load status bar graphics and hide any sprites from appearing over the status bar
    ⋮
    2217	LDA #MMC3_2K_TO_PPU_0000
    2218	STA MMC3_COMMAND
    2219	LDA StatusBarCHR_0000
    2220	STA MMC3_PAGE	
    2221 	LDA #MMC3_2K_TO_PPU_0800
    2222	STA MMC3_COMMAND
    2223	LDA StatusBarCHR_0800
    2224	STA MMC3_PAGE
    ⋮
    2226	STA MMC3_COMMAND
    ⋮
    2228	; Use blank tiles for all sprite graphics
    2229	LDA SpriteHideCHR_1000	
    ⋮
    
    PRG/prg031.asm lines 2214–2230 at 09b1bd8 · upstream ↗

    Checked against the evidence by its author, an AI model, 2026-10-21.

    Checked by a second AI model, 2026-10-21.

    In the claim ledger

  4. ^ abcIn ordinary levels the game picks the 2 KB background bank at PPU $0800 from PT2_Anim, banks $60, $62, $64, $66, by frame-counter bits 3-4, so the animated tiles step every 8 frames on a 32-frame loop; an active P-Switch forces bank $3E.CodeSouthbird's SMB3 disassembly
    How we know
    2294PRG030_8E4F:
    2295	; REGULAR LEVEL ANIMATIONS
    ⋮
    2297	LDA <Counter_1
    2298	AND #$18
    2299	LSR A	
    2300	LSR A	
    2301	LSR A		
    2302	TAX	        ; 0-3, changing every 8 ticks
    ⋮
    2304	LDA PT2_Anim,X	
    2305	STA PatTable_BankSel+1 ; Set pattern for this tick
    
    PRG/prg030.asm lines 2294–2305 at 09b1bd8 · upstream ↗
    423PT2_Anim:	.byte $60, $62, $64, $66
    
    PRG/prg030.asm line 423 at 09b1bd8 · upstream ↗
    2020	; Each byte of PatTable_BankSel sets the VROM available at
    2021	; 0000 (first half BG), 0800 (second half BG, typ animated), 
    ⋮
    2024	PatTable_BankSel:	.ds 6	; $0719-$071E  Provides an array of 6 pages to set the entire Pattern Table [BG_Full_CHRROM_Switch]
    
    smb3.asm lines 2019–2024 at 09b1bd8 · upstream ↗
    2257	LDA Level_PSwitchCnt
    2258	BEQ PRG030_8E31	 	; If P-Switch is not active, jump to PRG030_8E31
    ⋮
    2260	; Otherwise force pattern override to $3E
    2261	LDA #$3e
    2262	STA PatTable_BankSel+1
    
    PRG/prg030.asm lines 2257–2262 at 09b1bd8 · upstream ↗

    Checked against the evidence by its author, an AI model, 2026-10-21.

    Checked by a second AI model, 2026-10-21.

    In the claim ledger

  5. ^Every 8th frame ColorRotation rewrites 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/smb1
    How 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.

    In the claim ledger

Sources

Code

Secondary