Fix title Pikachu mirror and post-title window artifact

Two visual bugs both rooted in the 20x18 -> 40x25 viewport widening
(SCREEN_TILES_W 20->40, SCREEN_TILES_H 18->25), which silently broke two
spots that still assumed the GB's 32-wide tilemap / 20-wide screen.

Bug 1 (title Pikachu split/mirrored): the non-overworld render path read
the 40-wide wTileMap through the 32-wide GB VRAM tilemap. render_bg's
.decode_vram wrapped columns at 32 (`and edx,31`), duplicating Pikachu's
left columns onto the far right. Rewrite .decode_vram to read wTileMap
directly with row/col bounds (blank $7F past col 40 / row 25), mirroring
the overworld path's native-width read of wSurroundingTiles. This removes
the lossy VRAM hop and the column wrap entirely, and also lets menus/text
wider than 32 tiles render correctly. The window layer (TILEMAP1) is
untouched.

Bug 2 (post-title blank rectangle): LCDC default $E3 leaves window-enable
(bit 5) permanently set, so render_window runs every frame gated only on
WY/WX. The title's go_to_main_menu leaves H_WY=0, and ResetMapVariables
never reset the window registers, so a stale window block painted over the
overworld. Park the window off-screen (WY=RENDER_H, WX=7) in
ResetMapVariables; dialog code re-shows the box at WY=152/WX=87 when needed.

Both verified to assemble clean (nasm -f coff). Neither bug reproduces
under SKIP_TITLE=1, consistent with both being title-path issues.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GcHpAsg8pwsVATD6LWPsoR
This commit is contained in:
Claude
2026-06-25 17:35:24 +00:00
parent 4fe3d82fb1
commit 8f8d5aa1e2
2 changed files with 27 additions and 11 deletions

View File

@@ -884,6 +884,14 @@ ResetMapVariables:
mov byte [ebp + W_UNUSED_CUR_MAP_TILESET_COPY], al
mov byte [ebp + W_SPRITE_SET_ID], al
mov byte [ebp + W_WALK_BIKE_SURF_STATE_COPY], al
; Park the window layer off-screen on map entry. LCDC bit 5 (window enable)
; is permanently set (LCDC default $E3), so render_window runs every frame
; gated only on WY/WX. The title's go_to_main_menu leaves H_WY=0, which would
; otherwise leak in here and paint a stale window block over the overworld.
; RENDER_H = off-screen; dialog code re-shows the box at WY=152/WX=87.
mov byte [ebp + H_WY], RENDER_H
mov byte [ebp + IO_WY], RENDER_H
mov byte [ebp + IO_WX], 7
ret
; ---------------------------------------------------------------------------

View File

@@ -155,20 +155,28 @@ render_bg:
jmp .got_tile
.decode_vram:
; Non-overworld path (title / menus / text). Read the 40-wide wTileMap WRAM
; buffer DIRECTLY into bg_surface, mirroring the overworld branch's
; native-width read of wSurroundingTiles above. The old code funnelled the
; 40-wide buffer through the 32-wide GB VRAM tilemap (do_bg_transfer) and
; re-read it with `and edx,31`, which wrapped surface cols 32-47 back to
; cols 0-15 — duplicating the left of the screen onto the right (the title
; Pikachu "mirror"). wTileMap is 40 (SCREEN_TILES_W) x 25 (SCREEN_TILES_H);
; the 48x36 surface's extra cols (>=40) and rows (>=25) render as blank $7F.
mov eax, ebx
mov ecx, 48
xor edx, edx
div ecx
and edx, 31
shl eax, 5
add eax, edx
mov ecx, GB_TILEMAP0
test byte [ebp + IO_LCDC], 1 << 3
jz .read_vram
mov ecx, GB_TILEMAP1
.read_vram:
add eax, ecx
mov al, [ebp + eax]
div ecx ; EAX = surface row, EDX = surface col
cmp eax, SCREEN_TILES_H ; row >= 25 -> off-buffer
jae .vram_blank
cmp edx, SCREEN_TILES_W ; col >= 40 -> right padding
jae .vram_blank
imul eax, eax, SCREEN_TILES_W ; row * 40
add eax, edx ; + col
mov al, [ebp + W_TILEMAP + eax]
jmp .got_tile
.vram_blank:
mov al, 0x7F ; blank space tile (matches ClearScreen fill)
.got_tile: