data/claims/smb3-av.yamlSuper Mario Bros. 3 graphics and sound (Southbird's disassembly)
Game: Super Mario Bros. 3.
Each frame the NMI handler loads the MMC3's scanline counter with 192, and the IRQ it raises points the PPU at the status bar's nametable rows and swaps in the status bar's tile banks. smb3-av/irq-status-bar
About: Super Mario Bros. 3 Status bar split
Value: 192 scanlines
Codesmb3: Super Mario Bros. 3 disassembly for NESASM (captainsouthbird/smb3) ·PRG/prg031.asm#L1595-L1601; This sets the status bar scroll fix for everything after the title screen!
; At scanline 192, the name table scroll is fixed to always display the status bar
LDA #192 ; A = 192
STA MMC3_IRQCNT ; Store 192 into the IRQ count
STA MMC3_IRQLATCH ; Store it into the latch (will be used later)
STA MMC3_IRQENABLE ; Start the IRQ counter
CLI ; Enable maskable interruptssmb3: Super Mario Bros. 3 disassembly for NESASM (captainsouthbird/smb3) · PRG/prg031.asm#L2197-L2203; Because vertical scroll will not change after frame begins (second write to
; PPU_SCROLL will always be unused until next frame), the hack for MMC3 split
; vertical scrolling is to change the nametable address that the PPU is reading
; at to where we would like it to be...
LDY #$07
STY PPU_VRAM_ADDR
STX PPU_VRAM_ADDR ; ... so we're now reading at $0700Checked by claude, 2026-10-21 — read the NMI's IRQ setup and IntIRQ_Standard at the pinned commitThe MMC3 counts rendered scanlines (nes-hardware/mmc3-irq), so the count of 192 is the split's line; the status bar fills the rows below it.
Cited by: Status bar split
At 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. smb3-av/status-bar-banks
About: Super Mario Bros. 3 CHR bank switching
Codesmb3: Super Mario Bros. 3 disassembly for NESASM (captainsouthbird/smb3) ·PRG/prg031.asm#L2214-L2230; Load status bar graphics and hide any sprites from appearing over the status bar
…
LDA #MMC3_2K_TO_PPU_0000
STA MMC3_COMMAND
LDA StatusBarCHR_0000
STA MMC3_PAGE
LDA #MMC3_2K_TO_PPU_0800
STA MMC3_COMMAND
LDA StatusBarCHR_0800
STA MMC3_PAGE
…
; Use blank tiles for all sprite graphics
…Checked by claude, 2026-10-21 — read IntIRQ_Standard's bank writes at the pinned commitCited by: CHR bank switching
In 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. smb3-av/tile-animation
About: Super Mario Bros. 3 CHR bank switching
Value
{
"banks": [
96,
98,
100,
102
],
"framesPerStep": 8,
"loopFrames": 32,
"ppuAddress": "$0800",
"bankKB": 2,
"pSwitchBank": 62
}PRG/prg030.asm#L2294-L2305PRG030_8E4F:
; REGULAR LEVEL ANIMATIONS
LDA <Counter_1
AND #$18
LSR A
LSR A
LSR A
TAX ; 0-3, changing every 8 ticks
LDA PT2_Anim,X
STA PatTable_BankSel+1 ; Set pattern for this ticksmb3: Super Mario Bros. 3 disassembly for NESASM (captainsouthbird/smb3) · PRG/prg030.asm#L423PT2_Anim: .byte $60, $62, $64, $66smb3: Super Mario Bros. 3 disassembly for NESASM (captainsouthbird/smb3) · smb3.asm#L2019-L2024; Each byte of PatTable_BankSel sets the VROM available at
; 0000 (first half BG), 0800 (second half BG, typ animated),
…
PatTable_BankSel: .ds 6 ; $0719-$071E Provides an array of 6 pages to set the entire Pattern Table [BG_Full_CHRROM_Switch]smb3: Super Mario Bros. 3 disassembly for NESASM (captainsouthbird/smb3) · PRG/prg030.asm#L2257-L2262LDA Level_PSwitchCnt
BEQ PRG030_8E31 ; If P-Switch is not active, jump to PRG030_8E31
; Otherwise force pattern override to $3E
LDA #$3e
STA PatTable_BankSel+1Checked by claude, 2026-10-21 — read the level animation code, PT2_Anim, and the PatTable_BankSel comment at the pinned commitAirship levels step their own banks from $70 to $74 every 4 frames instead (PRG/prg030.asm, just above). Which tiles the banks animate (question blocks, coins, water) was not read from the CHR data.
Cited by: CHR bank switching
In the N-Spade card game three IRQs, at scanlines 32, 84, and 136, each give one row its own horizontal scroll and set the next IRQ 52 lines on, and a fourth restores the status bar, so three bands of the screen slide independently. smb3-av/spade-raster
About: Super Mario Bros. 3 Raster effects
Value
{
"firstLine": 32,
"rowGap": [
52,
52,
52
],
"rows": 3
}PRG/prg022.asm#L2602-L2606; Fire on scanline 32
LDA #$20
STA MMC3_IRQCNT
STA MMC3_IRQLATCH
STA MMC3_IRQENABLEsmb3: Super Mario Bros. 3 disassembly for NESASM (captainsouthbird/smb3) · PRG/prg031.asm#L2491-L2496; Based on the current Raster_State, set next scanline delay
LDA Roulette_RasterDiv,Y
STA MMC3_IRQCNTsmb3: Super Mario Bros. 3 disassembly for NESASM (captainsouthbird/smb3) · PRG/prg031.asm#L2474-L2478; This table tells how many lines to skip to the next row.
…
Roulette_RasterDiv: ; Raster_State = 0,1,2
.byte $34, $34, $34smb3: Super Mario Bros. 3 disassembly for NESASM (captainsouthbird/smb3) · PRG/prg031.asm#L2550-L2559LDA Roulette_PosHi,Y ; Get position for this row
…
LDA Roulette_Pos,Y ; Get horizontal scroll position for this row
STA PPU_SCROLL ; Store the horizontal
LDA #$00 ;
STA PPU_SCROLL ; Vertical = 0
INY ;
STY Raster_State ; Raster_State++Checked by claude, 2026-10-21 — read UpdSel_Roulette's IRQ setup and IntIRQ_SpadeGame with its tables at the pinned commitRaster state 3 restores the status bar's banks and scroll. That the game is the N-Spade card-matching game is the disassembly's label (UPDATERASTER_SPADEGAME, "Spade Bonus Game (3 sliding rows)" in smb3.asm), not a probe.
Cited by: Raster effects
The music data has a sample track beside the other channels' tracks; each note byte on it queues a sample, and Music_PlayDMC loads that sample's rate, address, and length from three 16-entry tables and restarts the DMC. smb3-av/dmc-track
About: Super Mario Bros. 3 DPCM samples
Codesmb3: Super Mario Bros. 3 disassembly for NESASM (captainsouthbird/smb3) ·PRG/prg031.asm#L926-L936LDA Music_PCMTrkPos
BEQ PRG031_E738 ; If Music_PCMTrkPos = 0 (disabled), jump to PRG031_E738
…
LDA [Music_Base_L],Y ; Get next byte in music segment tracksmb3: Super Mario Bros. 3 disassembly for NESASM (captainsouthbird/smb3) · PRG/prg031.asm#L950STA DMC_Queue ; Store note into DMC queuesmb3: Super Mario Bros. 3 disassembly for NESASM (captainsouthbird/smb3) · PRG/prg031.asm#L91-L110LDA DMC_MODCTL_LUT-1,Y ; Subtract 1 from LUT address since $00 is disabled and $01 is first DMC sound
STA PAPU_MODCTL ; Update PAPU_MODCTL
…
LDA DMC_MODADDR_LUT-1,Y ; Subtract 1 from LUT address since $00 is disabled and $01 is first DMC sound
STA PAPU_MODADDR ; Set PAPU_MODADDR (address of sound)
…
LDA #$0f
STA PAPU_EN ; Disable DMC
LDA #$1f
STA PAPU_EN ; Enable DMCChecked by claude, 2026-10-21 — read the DMC track reader and Music_PlayDMC at the pinned commitThe 16 sample entries play 9 recordings, some reused at a lower rate or cut short; their rate bytes are $0F (33,144 Hz) for most, and $0E (24,858 Hz) or $0D (21,307 Hz) for some of the reused copies. smb3-av/dmc-samples
About: Super Mario Bros. 3 DPCM samples
Value
{
"entries": 16,
"recordings": 9,
"rates": [
15,
15,
15,
15,
15,
15,
14,
15,
14,
15,
14,
13,
15,
15,
14,
13
],
"ratesHz": {
"13": 21307,
"14": 24858,
"15": 33144
}
}PRG/prg031.asm#L163-L179DMC_MODCTL_LUT:
.byte $0F ; Sample 0 (DMC01)
…
.byte $0E ; Sample 6 (DMC05 3/4 length)
…
.byte $0E ; Sample 8 (DMC06 slower)
…
.byte $0D ; Sample 15 (DMC09 even slower)smb3: Super Mario Bros. 3 disassembly for NESASM (captainsouthbird/smb3) · PRG/prg031.asm#L113-L117; The address are $C000 | (value << 6)
MADR .func ((\1 & $3FFF) >> 6)
…
MLEN .func ((\2 - \1) >> 4)APU DMC · Pitch tableFor example, on NTSC (1.789773 MHz), a rate of 428 gives a frequency of 1789773/428 Hz = 4181.71 Hz.Checked by claude, 2026-10-21 — read the three DMC tables and their comments at the pinned commit; Hz from the NTSC rate table (nes-hardware/dmc)Rates $F, $E, $D are 54, 72, and 84 CPU cycles per bit (nes-hardware/dmc). Southbird's comment marks entry 3 as a bad length that would play DMC02 "and just continue on through code". What each recording is (timpani, bongo, and so on) is not labeled in the disassembly.
Cited by: DPCM samples