From 12f2060edb5eb26be4243e124a487dfe2caeb9e9 Mon Sep 17 00:00:00 2001 From: Alexandros Mandravillis Date: Mon, 31 Aug 2026 03:01:23 +0300 Subject: [PATCH] Present full depth24 scanout canvas --- runtime/include/display_scanout.h | 9 +++++++++ runtime/src/main.cpp | 11 ++++++----- runtime/tests/test_display_scanout.c | 8 ++++++++ 3 files changed, 23 insertions(+), 5 deletions(-) diff --git a/runtime/include/display_scanout.h b/runtime/include/display_scanout.h index 64ab7b1d..b2f24dd5 100644 --- a/runtime/include/display_scanout.h +++ b/runtime/include/display_scanout.h @@ -14,6 +14,15 @@ typedef struct { int valid; } PsxDisplayVerticalLayout; +/* Depth24 staging expands the visible source into the full active-video + * canvas. Every presentation backend must therefore consume the canvas + * height, while ordinary 15-bit display keeps its source height. */ +static inline uint32_t psx_display_present_height( + int depth24, uint32_t source_height, uint32_t canvas_height) +{ + return depth24 && canvas_height != 0u ? canvas_height : source_height; +} + /* Intersect a GP1(07h) range with the PAL or NTSC active region. The canvas * preserves the television scanout position without discarding visible VRAM * rows. source_skip_y owns rows before the active region; canvas_origin_y owns diff --git a/runtime/src/main.cpp b/runtime/src/main.cpp index 90830341..6ca20e8d 100644 --- a/runtime/src/main.cpp +++ b/runtime/src/main.cpp @@ -6970,7 +6970,7 @@ static NetplayVblankEpilogue sdl_vblank_present_body(void) { /* ---- Display from our VRAM ---- */ probe_reached = 1; - uint32_t w = 0, h = 0; + uint32_t w = 0, h = 0, present_h = 0; uint32_t present_w = 0; /* display width actually presented (w + native-wide EXTRA) */ int active_scale = 1; /* hi-res mirror used only for 15-bit display */ bool fmv_frame = false; /* FMV/boot — present pillarboxed 4:3 in widescreen */ @@ -7017,7 +7017,8 @@ static NetplayVblankEpilogue sdl_vblank_present_body(void) { s_disabled_frame_presented = false; s_force_present_after_load = false; w = di.width; h = di.height; - const uint32_t present_h = di.depth24 ? di.screen_height : h; + present_h = psx_display_present_height( + di.depth24, h, di.screen_height); /* 4:3-pinned frames: the pre-game BIOS boot, plus (once engaged) every * frame the widescreen layer presents native — FMV video and full-2D * menu/title screens. gpu_ws_present_native_43() is the single source @@ -7259,7 +7260,7 @@ static NetplayVblankEpilogue sdl_vblank_present_body(void) { * leave the active image stuck in the upper-left portion of the window. */ #ifndef PSX_SDL_NO_RENDER int src_w = (int)present_w * active_scale; - int src_h = (int)h * active_scale; + int src_h = (int)present_h * active_scale; if (local_viewport_crop_applied && src_w >= 2) src_w /= 2; if (g_gl_active) { @@ -7313,8 +7314,8 @@ static NetplayVblankEpilogue sdl_vblank_present_body(void) { int dst_h = 480 * tex_scale; SDL_Rect dst = { (g_logical_w - dst_w) / 2, 0, dst_w, dst_h }; /* Match GL: short display bands letterbox inside the 4:3 rect. */ - if (pin_43 && h > 0 && h < 240) { - int content_h = (dst_h * (int)h) / 240; + if (pin_43 && present_h > 0 && present_h < 240) { + int content_h = (dst_h * (int)present_h) / 240; if (content_h < 1) content_h = 1; dst.y = (dst_h - content_h) / 2; dst.h = content_h; diff --git a/runtime/tests/test_display_scanout.c b/runtime/tests/test_display_scanout.c index c774345a..f2d14e65 100644 --- a/runtime/tests/test_display_scanout.c +++ b/runtime/tests/test_display_scanout.c @@ -12,6 +12,13 @@ static void test_vertical_offsets(void) assert(psx_display_vertical_offset(1, 400, 500) == 0); } +static void test_present_height(void) +{ + assert(psx_display_present_height(0, 225, 288) == 225); + assert(psx_display_present_height(1, 225, 288) == 288); + assert(psx_display_present_height(1, 225, 0) == 225); +} + static void test_vertical_layout(void) { PsxDisplayVerticalLayout alundra = psx_display_vertical_layout(1, 83, 312); @@ -36,5 +43,6 @@ int main(void) { test_vertical_offsets(); test_vertical_layout(); + test_present_height(); return 0; }