mirror of
https://github.com/pret/pokeyellow.git
synced 2026-08-24 03:14:44 -05:00
Fix textbox rendering: composite window over sprites, clamp to box width
Two PPU fixes for the dialog/menu window layer: - Render the window layer AFTER sprites (was before) so the textbox occludes NPCs standing under it. This inverts GB hardware layer order on purpose: the window here is only the bottom dialog/menu box, and the artifact is port-specific to our extended 40x25 player-centered viewport exposing NPCs the 20x18 GB screen never put under the box. - Clamp the window blit to SCREEN_W (the 20-tile box content width) instead of the 256px row_buf size, so the TILE_SPC filler in tilemap cols 20-31 no longer paints blank tiles over the BG to the right of the box. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -560,7 +560,13 @@ render_sprites:
|
||||
; This prevents visual drift when the window starts mid-frame. The implementation
|
||||
; stores WLY in win_line_ctr (BSS) and increments it after each active scanline.
|
||||
;
|
||||
; Call after render_bg and before render_sprites.
|
||||
; Call after render_bg AND render_sprites. NOTE: this inverts the GB hardware
|
||||
; layer order — on real DMG/CGB, OBJ sprites draw over the window, so the HW
|
||||
; order is BG → window → sprites. We diverge on purpose: the window here is only
|
||||
; the bottom dialog/menu box (WY=152), which must occlude NPCs under it. The
|
||||
; bug only shows up because this port's extended 40×25 player-centered viewport
|
||||
; renders NPCs in the bottom rows that the GB's 20×18 screen never put under the
|
||||
; box. See the DIVERGENCE note in src/video/frame.asm:DelayFrame.
|
||||
; In: EBP = GB memory base. All registers preserved.
|
||||
; ---------------------------------------------------------------------------
|
||||
render_window:
|
||||
@@ -642,10 +648,16 @@ render_window:
|
||||
push ecx
|
||||
mov ecx, RENDER_W
|
||||
sub ecx, edx ; pixels to reach the right edge
|
||||
cmp ecx, 256
|
||||
; Clamp to SCREEN_W (160px = 20 tiles), the dialog/menu box's content width.
|
||||
; row_buf holds 256 decoded px (32 tiles), but only cols 0-19 carry the box;
|
||||
; cols 20-31 are TILE_SPC filler added to pad the 32-wide GB tilemap row, and
|
||||
; must NOT be blitted — otherwise they paint blank tiles over the BG to the
|
||||
; right of the box (the box is 160px centered in our 320px viewport, so BG is
|
||||
; visible past its right edge). 160 < 256, so this also stays within row_buf.
|
||||
cmp ecx, SCREEN_W
|
||||
jbe .do_right_copy
|
||||
mov ecx, 256 ; clamp — row_buf holds only 256 decoded px
|
||||
.do_right_copy: ; (32 tiles); never read past it into BSS
|
||||
mov ecx, SCREEN_W
|
||||
.do_right_copy:
|
||||
add edi, edx ; advance dest to screen_x_start
|
||||
rep movsb
|
||||
pop ecx
|
||||
@@ -657,11 +669,11 @@ render_window:
|
||||
lea esi, [row_buf + edx]
|
||||
push ecx
|
||||
mov ecx, RENDER_W
|
||||
mov eax, 256
|
||||
sub eax, edx ; bytes remaining in row_buf after the clip
|
||||
mov eax, SCREEN_W ; box content width (see right-copy clamp above)
|
||||
sub eax, edx ; content px remaining after the clip
|
||||
cmp ecx, eax
|
||||
jbe .do_left_copy
|
||||
mov ecx, eax ; clamp — never read past row_buf end
|
||||
mov ecx, eax ; clamp — only blit real box content, not filler
|
||||
.do_left_copy:
|
||||
rep movsb
|
||||
pop ecx
|
||||
|
||||
@@ -57,8 +57,17 @@ DelayFrame:
|
||||
call update_oam ; PrepareOAMData → shadow OAM, then DMA to OAM
|
||||
call joypad_update
|
||||
call render_bg
|
||||
call render_window ; composite window layer over BG (before sprites)
|
||||
call render_sprites ; composite OAM sprites over BG+window
|
||||
call render_sprites ; composite OAM sprites over BG
|
||||
; DIVERGENCE FROM GB HARDWARE (intentional): on real DMG/CGB, OBJ sprites
|
||||
; draw OVER the window layer, so the GB order is BG → window → sprites. We
|
||||
; deliberately invert that here (window LAST, over sprites) because the
|
||||
; window layer in this port is only ever the bottom dialog/menu box (WY=152),
|
||||
; and that box must occlude NPCs standing under it. The artifact this guards
|
||||
; against is port-specific: our extended 40×25 player-centered viewport shows
|
||||
; far more of the map than the GB's 20×18 screen, exposing NPCs in the bottom
|
||||
; rows that the original camera never placed under the textbox. The player
|
||||
; sprite sits at screen center (well above WY=152), so it is never occluded.
|
||||
call render_window ; composite window layer (textbox/menu) OVER sprites
|
||||
call draw_player_marker ; legacy placeholder (no-op unless explicitly enabled)
|
||||
call present
|
||||
cmp byte [pad_quit], 0
|
||||
|
||||
Reference in New Issue
Block a user