data/claims/pokecrystal-av.yamlPokémon Crystal graphics (pret/pokecrystal)
Game: Pokémon Crystal.
The game sets the STAT interrupt to fire at every horizontal blank, and the handler copies the byte for the current line from a 144-entry table, wLYOverrides, into whichever video register hLCDCPointer names; while that pointer is 0 the handler does nothing. The handler runs in the horizontal blank after line LY, so entry n takes effect from line n + 1, and line 0 shows the register's value from before the frame (the Magnet Train writes its top band's scroll to hSCX for that line). pokecrystal-av/ly-overrides
About: Pokémon Crystal Raster effects
Value
{
"trigger": "mode-0",
"table": "wLYOverrides"
}home/init.asm#L111-L112ld a, STAT_MODE_0 ldh [rSTAT], apokecrystal: disassembly of Pokémon Crystal · home/header.asm#L46-L47SECTION "lcd", ROM0[$0048] jp LCDpokecrystal: disassembly of Pokémon Crystal · home/lcd.asm#L12-L31LCD:: push af ldh a, [hLCDCPointer] and a jr z, .done … ldh a, [rLY] ld c, a ld b, HIGH(wLYOverrides) ld a, [bc] ld b, a ldh a, [hLCDCPointer] ld c, a ld a, b ldh [c], apokecrystal: disassembly of Pokémon Crystal · ram/wram.asm#L3628wLYOverrides:: ds SCREEN_HEIGHT_PXpokecrystal: disassembly of Pokémon Crystal · constants/hardware.inc#L997def SCREEN_HEIGHT_PX equ 144 ; height of screen in pixelsChecked by claude-agent, 2026-10-21 — read the STAT setup in Init, the $0048 vector, the LCD handler, and the table's declarationSTAT_MODE_0 is bit 3, "HBlank triggers the PPU interrupt" (constants/hardware.inc#L497). Effects that use it include the battle intro slide, the map name sign, the title screen, and the Magnet Train.
The Magnet Train ride fills the per-line table with three bands each frame, 47 lines, 48 lines, and 49 lines, and points the handler at SCX; the top and bottom bands take twice a running offset that moves 2 a frame, so the scenery scrolls 4 pixels a frame, while the middle band holds the train's own position. pokecrystal-av/magnet-train
About: Pokémon Crystal Raster effects
Value
{
"bands": [
47,
48,
49
],
"sceneryPixelsPerFrame": 4,
"register": "SCX"
}engine/events/magnet_train.asm#L86-L114MagnetTrain_UpdateLYOverrides: ld hl, wLYOverridesBackup ld c, 6 * TILE_WIDTH - 1 ld a, [wMagnetTrainOffset] add a ldh [hSCX], a call .loadloop ld c, 6 * TILE_WIDTH ld a, [wMagnetTrainPosition] call .loadloop ld c, 6 * TILE_WIDTH + 1 ld a, [wMagnetTrainOffset] add a call .loadloop … ld hl, wMagnetTrainOffset ld a, [hl] add d add d ld [hl], apokecrystal: disassembly of Pokémon Crystal · engine/events/magnet_train.asm#L229-L240MagnetTrain_InitLYOverrides: … ld a, LOW(rSCX) ldh [hLCDCPointer], apokecrystal: disassembly of Pokémon Crystal · engine/events/magnet_train.asm#L50-L53call MagnetTrain_UpdateLYOverrides call PushLYOverrides call DelayFrame jr .looppokecrystal: disassembly of Pokémon Crystal · constants/hardware.inc#L1008def TILE_WIDTH equ 8 ; width of tile in pixelsChecked by claude-agent, 2026-10-21 — read the ride's loop, its per-frame table fill, and the init that points hLCDCPointer at rSCX; d is wMagnetTrainDirection, 1 or -1The bands are built in wLYOverridesBackup and copied to wLYOverrides by PushLYOverrides; 47 + 48 + 49 = 144, the visible lines.
Cited by: Raster effects