mirror of
https://github.com/RetroPortingToolKit/psxrecomp
synced 2026-10-26 10:19:47 -04:00
Merge commit 'refs/review/20261014/pr661' into integrate/pr658plus-regressions-20261014
This commit is contained in:
@@ -1821,6 +1821,9 @@ if(BUILD_TESTING)
|
||||
--cc ${CMAKE_C_COMPILER})
|
||||
endif()
|
||||
add_test(NAME fntrace_c_linkage_test COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/tests/test_fntrace_c_linkage.py)
|
||||
add_test(NAME depth24_present_hold_vblank_test
|
||||
COMMAND ${Python3_EXECUTABLE}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tests/test_depth24_present_hold_vblank.py)
|
||||
add_test(NAME netplay_load_apply_flow_test
|
||||
COMMAND ${Python3_EXECUTABLE}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tests/test_netplay_load_apply_flow.py)
|
||||
|
||||
+14
-3
@@ -3408,6 +3408,12 @@ static uint16_t vram_write_pixels[1024 * 512];
|
||||
* gpu_depth24_rgb_limit — declared early so gpu_reset_state can clear it. */
|
||||
static uint32_t s_d24_upload_x1 = 0;
|
||||
static int s_d24_present_hold = 0; /* vblanks to skip Swap after GP1(07h) */
|
||||
/* Host side of the hold: whether the present after the latest guest VBlank
|
||||
* skips its Swap. The count itself is guest state (in the GPU snap) and moves
|
||||
* only at guest VBlank, so a live run, a rollback replay and a headless run
|
||||
* all hold the same span (#636: a present-ticked hold stuck at 3 in headless
|
||||
* live play and was zeroed by a rollback load, so replay != live). */
|
||||
static int s_d24_present_skip = 0;
|
||||
static uint32_t s_d24_prev_disp_h = 0; /* last GP1(07h) band height */
|
||||
static void depth24_note_upload(uint32_t x, uint32_t w);
|
||||
|
||||
@@ -3880,6 +3886,7 @@ static void gpu_reset_state(int clear_vram) {
|
||||
ws_scene_hold_reset(&s_ws_scene_hold);
|
||||
s_d24_upload_x1 = 0;
|
||||
s_d24_present_hold = 0;
|
||||
s_d24_present_skip = 0;
|
||||
s_d24_prev_disp_h = 0;
|
||||
}
|
||||
|
||||
@@ -4145,6 +4152,9 @@ void gpu_vblank_tick(void) {
|
||||
* poll first became reachable in this runtime. */
|
||||
if (vertical_interlace)
|
||||
interlace_field = (lcf ^ 1) & 1;
|
||||
s_d24_present_skip = s_d24_present_hold > 0;
|
||||
if (s_d24_present_hold > 0)
|
||||
s_d24_present_hold--;
|
||||
/* snapshot per-frame draw-offset-Y range for the strobe instrumentation */
|
||||
if (g_doff_cnt_this) {
|
||||
g_doff_min_last = g_doff_min_this;
|
||||
@@ -4232,15 +4242,16 @@ void gpu_depth24_upload_span_reset(void) {
|
||||
}
|
||||
|
||||
int gpu_depth24_present_hold_tick(void) {
|
||||
if (s_d24_present_hold <= 0) return 0;
|
||||
s_d24_present_hold--;
|
||||
return 1;
|
||||
int skip = s_d24_present_skip;
|
||||
s_d24_present_skip = 0; /* one skipped Swap per guest VBlank */
|
||||
return skip;
|
||||
}
|
||||
|
||||
void gpu_depth24_on_savestate_loaded(void) {
|
||||
/* Hold skips Swap — after restore we want the restored VRAM visible now.
|
||||
* Upload span / prev_h were restored from the GPU snap. */
|
||||
s_d24_present_hold = 0;
|
||||
s_d24_present_skip = 0;
|
||||
}
|
||||
|
||||
/* ---- Present-time screen-colour LUT (verified-enhancement, opt-in) -------
|
||||
|
||||
@@ -1122,7 +1122,9 @@ extern "C" void psx_frontend_on_rb_snap_loaded(void) {
|
||||
const int media = gpu_display_is_depth24() || mdec_recently_active(8) ||
|
||||
cdrom_fmv_stream_pending() || cdrom_xa_stream_active();
|
||||
g_audio_cycle_resync = 1;
|
||||
gpu_depth24_on_savestate_loaded();
|
||||
/* The depth24 present hold came back with the GPU snap and is guest state
|
||||
* now (ticked at guest VBlank): keep it, so the replay matches the live
|
||||
* run of the same ticks. */
|
||||
s_d24_cutover_blank = 0;
|
||||
if (media) {
|
||||
s_d24_saw_gap = 0;
|
||||
@@ -9034,9 +9036,8 @@ static NetplayVblankEpilogue sdl_vblank_present_body(void) {
|
||||
|
||||
/* Depth24 GP1(07h) retarget (MotK intro→crawl): keep the prior Swap for a
|
||||
* few vblanks so stale trailing VRAM never flashes on the right edge.
|
||||
* Must tick every present — gpu.c arms s_d24_present_hold and also
|
||||
* freezes upload-span tracking while hold > 0; without this call the hold
|
||||
* sticks and depth24_fix_trailing_margin blanks the whole FMV forever. */
|
||||
* gpu.c counts the hold down at guest VBlank (it also freezes upload-span
|
||||
* tracking while > 0); this skips the Swap of each held VBlank. */
|
||||
if (gpu_depth24_present_hold_tick())
|
||||
return ep;
|
||||
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
#!/usr/bin/env python3
|
||||
"""The depth24 present hold is guest state, counted down at guest VBlank.
|
||||
|
||||
GP1(07h) arms s_d24_present_hold (skip a few Swaps after a depth24 band
|
||||
retarget). It is in the GPU snap. It used to count down only at host present,
|
||||
so a headless run never moved it, and a rollback snap load zeroed it: the
|
||||
replayed save of a tick differed from the live save in the GPU section
|
||||
(psxrecomp #636). Guards: gpu_vblank_tick counts it down, the present-side
|
||||
query never touches it, and a rollback snap load keeps the restored value.
|
||||
"""
|
||||
from pathlib import Path
|
||||
|
||||
from test_netplay_load_apply_flow import function_body
|
||||
|
||||
SRC = Path(__file__).resolve().parents[1] / "src"
|
||||
|
||||
|
||||
def main():
|
||||
gpu = (SRC / "gpu.c").read_text()
|
||||
vblank = function_body(gpu, "void gpu_vblank_tick(void)")
|
||||
assert "s_d24_present_hold--" in vblank
|
||||
tick = function_body(gpu, "int gpu_depth24_present_hold_tick(void)")
|
||||
assert "s_d24_present_hold" not in tick, "the hold must not move at host present"
|
||||
|
||||
main_cpp = (SRC / "main.cpp").read_text()
|
||||
rb_loaded = function_body(main_cpp, 'extern "C" void psx_frontend_on_rb_snap_loaded(void)')
|
||||
assert "gpu_depth24_on_savestate_loaded" not in rb_loaded
|
||||
print("depth24 present hold: ok")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user