You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The stray line above the logo is a raster-effect bug, not DIV/TIMA
The game does not touch the timer at all here: over the whole intro (9000 frames
traced, every access to FF00-FF4F) there is not a single read or write of
FF04/FF05/FF06/FF07 - TAC stays 0 the entire time. So DIV/TIMA timing is not
involved.
What the game actually does
The unfolding "ZELDA" logo is driven by a per-scanline SCY effect. The routine
at $6DB7 (bank 1):
6DE6 F0 44 LDH A,($FF44) ; wait for LY == $10
6DE8 FE 10 CP $10
6DEA 20 FA JR NZ,$6DE6
6DEC F0 41 LDH A,($FF41) ; wait for HBlank (mode 0)
6DEE E6 03 AND $03
6DF0 20 FA JR NZ,$6DEC
...
6E1A 7E LD A,(HL) ; table[i]
6E1E 86 ADD A,(HL) ; + SCY base at $FF97
6E1F E0 42 LDH ($FF42),A ; SCY for this line
It writes SCY once per line for lines $11..$4A, from the 17 stage tables at $6D84/$6DA6 (base $FF97 walks $5F -> $6F), plus BGP=$55 to blank the
part of the screen that is not revealed yet.
Root cause
gb.cpp drew the line before the CPU's mode 3 time:
STAT_MODE(3);
ppu_refreshline(); // line already drawn ...
execute(43); // ... but the CPU writes SCY in here
The game's SCY write lands a few M-cycles into line N (STAT reads 42/43), so it
belongs to line N - the PPU reads SCX/SCY while it fetches the line. Drawing the
line first pushed that write onto line N+1.
On line 17 the game asks for SCY $5F/$6B depending on the stage, i.e. source
row 112/124 - a blank row. The emulator used the previous SCY $6F, which is
source row 128, i.e. row 0 of the logo bitmap (ROM $3C900 copied to VRAM $8800 at $2CF0). That row is exactly the thin light line - hence
"some weird line above ZELDA logo", floating above the logo during the unfold.
Fix
Draw the line after the CPU has had its mode 3 time (one line moved, gb.cpp):
STAT_MODE(3); /* no interrupt here !! */
execute(43);
ppu_refreshline();
Verification
Tested with the ZELDA.st0 attached to this issue (debug build, frame dumps):
the dump frame matches the screenshot in the report;
with the fix the stray line is gone, and the logo unfolds cleanly;
the fix changes only frames 251..283 (the unfold); frames before and after
are pixel identical;
Activity
ppu: latch the scanline registers after the CPU's mode 3 time (issue #2)
ogamespec commentedon Oct 2, 2026
The stray line above the logo is a raster-effect bug, not DIV/TIMA
The game does not touch the timer at all here: over the whole intro (9000 frames
traced, every access to FF00-FF4F) there is not a single read or write of
FF04/FF05/FF06/FF07 - TAC stays 0 the entire time. So DIV/TIMA timing is not
involved.
What the game actually does
The unfolding "ZELDA" logo is driven by a per-scanline SCY effect. The routine
at
$6DB7(bank 1):It writes SCY once per line for lines
$11..$4A, from the 17 stage tables at$6D84/$6DA6(base$FF97walks$5F -> $6F), plusBGP=$55to blank thepart of the screen that is not revealed yet.
Root cause
gb.cppdrew the line before the CPU's mode 3 time:The game's SCY write lands a few M-cycles into line N (STAT reads 42/43), so it
belongs to line N - the PPU reads SCX/SCY while it fetches the line. Drawing the
line first pushed that write onto line N+1.
On line 17 the game asks for SCY
$5F/$6Bdepending on the stage, i.e. sourcerow 112/124 - a blank row. The emulator used the previous SCY
$6F, which issource row 128, i.e. row 0 of the logo bitmap (ROM
$3C900copied to VRAM$8800at$2CF0). That row is exactly the thin light line - hence"some weird line above ZELDA logo", floating above the logo during the unfold.
Fix
Draw the line after the CPU has had its mode 3 time (one line moved,
gb.cpp):Verification
Tested with the
ZELDA.st0attached to this issue (debug build, frame dumps):are pixel identical;