gpulib: remove some unreliable heuristics master github/master
authornotaz <notasas@gmail.com>
Sat, 21 Mar 2026 21:36:55 +0000 (23:36 +0200)
committernotaz <notasas@gmail.com>
Sat, 21 Mar 2026 21:50:41 +0000 (23:50 +0200)
Make it another hack option instead.
Sucks but I don't have a better solution for now.

libretro/pcsx_rearmed#915

frontend/libretro.c
frontend/libretro_core_options.h
frontend/main.c
frontend/menu.c
frontend/plugin.c
frontend/plugin_lib.h
libpcsxcore/database.c
libpcsxcore/psxcommon.h
plugins/gpulib/gpu.c
plugins/gpulib/gpu.h

index 22898b5..936bd93 100644 (file)
@@ -2667,6 +2667,18 @@ static void update_variables(bool in_flight)
          Config.FractionalFramerate = -1;
    }
 
+   var.value = NULL;
+   var.key = "pcsx_rearmed_alt_flip";
+   if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
+   {
+      if (strcmp(var.value, "early") == 0)
+         Config.AlternativeFlip = 1;
+      else if (strcmp(var.value, "late") == 0)
+         Config.AlternativeFlip = 0;
+      else // auto
+         Config.AlternativeFlip = -1;
+   }
+
    var.value = NULL;
    var.key = "pcsx_rearmed_screen_centering";
    if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
index eb0c3b5..e049c6f 100644 (file)
@@ -446,6 +446,21 @@ struct retro_core_option_v2_definition option_defs_us[] = {
       },
       "auto",
    },
+   {
+      "pcsx_rearmed_alt_flip",
+      "Framebuffer readout",
+      NULL,
+      "Some games make changes to the framebuffer while it's being sent to the display, which is currently not emulated. However this option allows to choose if the emulator takes the video frame before the emulated PSX active display period ('Early') or after ('Late'). Normally this should be left at 'Auto'.",
+      NULL,
+      "video",
+      {
+         { "auto",  "Auto" },
+         { "early", "Early" },
+         { "late",  "Late" },
+         { NULL, NULL },
+      },
+      "auto",
+   },
    {
       "pcsx_rearmed_rgb32_output",
       "RGB32 output",
index 267eb84..ee2de1c 100644 (file)
@@ -114,6 +114,7 @@ void emu_set_default_config(void)
        Config.cycle_multiplier = CYCLE_MULT_DEFAULT;
        Config.GpuListWalking = -1;
        Config.FractionalFramerate = -1;
+       Config.AlternativeFlip = -1;
 
        pl_rearmed_cbs.dithering = 1;
        pl_rearmed_cbs.gpu_neon.allow_interlace = 2; // auto
index fd1bebe..0491908 100644 (file)
@@ -112,7 +112,7 @@ static int psx_clock;
 static int memcard1_sel = -1, memcard2_sel = -1;
 static int cd_buf_count;
 extern int g_autostateld_opt;
-static int menu_iopts[8];
+static int menu_iopts[9];
 int g_opts, g_scaler, g_gamma = 100;
 int scanlines, scanline_level = 20;
 int soft_scaling, analog_deadzone; // for Caanoo
@@ -420,6 +420,7 @@ static const struct {
        CE_CONFIG_VAL(Cpu),
        CE_CONFIG_VAL(GpuListWalking),
        CE_CONFIG_VAL(FractionalFramerate),
+       CE_CONFIG_VAL(AlternativeFlip),
        CE_CONFIG_VAL(PreciseExceptions),
        CE_CONFIG_VAL(TurboCD),
        CE_CONFIG_VAL(SlowBoot),
@@ -1424,7 +1425,7 @@ static menu_entry e_menu_gfx_options[] =
        mee_range_h   ("Gamma adjustment",         MA_OPT_GAMMA, g_gamma, 1, 200, h_gamma),
        mee_onoff     ("OpenGL Vsync",             MA_OPT_VSYNC, g_opts, OPT_VSYNC),
        mee_cust_h    ("Setup custom scaler",      MA_OPT_VARSCALER_C, menu_loop_cscaler, NULL, h_cscaler),
-       mee_onoff_h   ("Force low resolution",     0, pl_rearmed_cbs.scale_hires, 1, h_lowres),
+       mee_onoff_h   ("Force low resolution",     0, menu_iopts[0], 1, h_lowres),
        mee_end,
 };
 
@@ -1432,8 +1433,12 @@ static int menu_loop_gfx_options(int id, int keys)
 {
        static int sel = 0;
 
+       menu_iopts[0] = pl_rearmed_cbs.scale_hires;
+
        me_loop(e_menu_gfx_options, &sel);
 
+       pl_rearmed_cbs.scale_hires = menu_iopts[0];
+
        return 0;
 }
 
@@ -1617,7 +1622,7 @@ static menu_entry e_menu_plugin_options[] =
 #ifdef USE_ASYNC_GPU
        mee_enum      ("GPU multithreading",            0, menu_iopts[1], men_autooo),
 #endif
-       mee_enum      ("GPU dithering",                 0, pl_rearmed_cbs.dithering, men_gpu_dithering),
+       mee_enum      ("GPU dithering",                 0, menu_iopts[2], men_gpu_dithering),
        mee_enum_h    ("SPU plugin",                    0, spu_plugsel, spu_plugins, h_plugin_spu),
 #ifndef C64X_DSP
        mee_onoff_h   ("SPU multithreading",            MA_OPT_SPU_THREAD, spu_config.iUseThread, 1, h_sputhr),
@@ -1635,12 +1640,16 @@ static int menu_loop_plugin_options(int id, int keys)
        int spu_thread_old = spu_config.iUseThread;
        menu_iopts[0] = Config.SlowBoot;
        menu_iopts[1] = pl_rearmed_cbs.thread_rendering + 1;
+       menu_iopts[2] = pl_rearmed_cbs.dithering;
 #ifndef C64X_DSP
        me_enable(e_menu_plugin_options, MA_OPT_SPU_THREAD, pcsxr_sthread_core_count > 1);
 #endif
+
        me_loop(e_menu_plugin_options, &sel);
+
        Config.SlowBoot = menu_iopts[0];
        pl_rearmed_cbs.thread_rendering = menu_iopts[1] - 1;
+       pl_rearmed_cbs.dithering = menu_iopts[2];
        if (spu_config.iUseThread != spu_thread_old)
                SPU_configure();
 
@@ -1684,6 +1693,8 @@ static int menu_loop_speed_hacks(int id, int keys)
        return 0;
 }
 
+static const char *men_aflip[]  = { "Auto", "Late", "Early", NULL };
+
 static const char h_cfg_cpul[]   = "Shows CPU usage in %";
 static const char h_cfg_spu[]    = "Shows active SPU channels\n"
                                   "(green: normal, red: fmod, blue: noise)";
@@ -1707,7 +1718,10 @@ static const char h_cfg_tcd[]    = "Greatly reduce CD load times. Breaks some ga
 static const char h_cfg_psxclk[]  = "Over/under-clock the PSX, default is " DEFAULT_PSX_CLOCK_S "\n"
                                    "(adjust this if the game is too slow/too fast/hangs)";
 
-enum { AMO_XA, AMO_CDDA, AMO_IC, AMO_BP, AMO_CPU, AMO_GPUL, AMO_FFPS, AMO_TCD };
+enum {
+       AMO_XA, AMO_CDDA, AMO_IC, AMO_BP, AMO_CPU,
+       AMO_GPUL, AMO_FFPS, AMO_TCD, AMO_AFLIP,
+};
 
 static menu_entry e_menu_adv_options[] =
 {
@@ -1720,6 +1734,7 @@ static menu_entry e_menu_adv_options[] =
        mee_onoff_h   ("BP exception emulation", 0, menu_iopts[AMO_BP],   1, h_cfg_exc),
        mee_enum_h    ("GPU l-list slow walking",0, menu_iopts[AMO_GPUL], men_autooo, h_cfg_gpul),
        mee_enum_h    ("Fractional framerate",   0, menu_iopts[AMO_FFPS], men_autooo, h_cfg_ffps),
+       mee_enum      ("Framebuffer readout",    0, menu_iopts[AMO_AFLIP], men_aflip),
        mee_onoff_h   ("Turbo CD-ROM ",          0, menu_iopts[AMO_TCD], 1, h_cfg_tcd),
 #ifdef USE_ASYNC_CDROM
        mee_range     ("CD-ROM read-ahead",      0, cd_buf_count, 0, 1024),
@@ -1751,6 +1766,7 @@ static int menu_loop_adv_options(int id, int keys)
                *opts[i].mopt = *opts[i].opt;
        menu_iopts[AMO_GPUL] = Config.GpuListWalking + 1;
        menu_iopts[AMO_FFPS] = Config.FractionalFramerate + 1;
+       menu_iopts[AMO_AFLIP] = Config.AlternativeFlip + 1;
 
        me_loop(e_menu_adv_options, &sel);
 
@@ -1758,6 +1774,7 @@ static int menu_loop_adv_options(int id, int keys)
                *opts[i].opt = *opts[i].mopt;
        Config.GpuListWalking = menu_iopts[AMO_GPUL] - 1;
        Config.FractionalFramerate = menu_iopts[AMO_FFPS] - 1;
+       Config.AlternativeFlip = menu_iopts[AMO_AFLIP] - 1;
        cdra_set_buf_count(cd_buf_count);
 
        return 0;
index 20f2e93..e7ae209 100644 (file)
@@ -167,6 +167,8 @@ void plugin_call_rearmed_cbs(void)
 
        pl_rearmed_cbs.screen_centering_type_default =
                Config.hacks.gpu_centering ? C_INGAME : C_AUTO;
+       pl_rearmed_cbs.alt_flip = Config.AlternativeFlip > 0 ||
+               (Config.AlternativeFlip < 0 && Config.hacks.alt_flip);
 
        rearmed_set_cbs = SysLoadSym(hGPUDriver, "GPUrearmedCallbacks");
        if (rearmed_set_cbs != NULL)
index 1118f20..4ff3ddf 100644 (file)
@@ -76,9 +76,10 @@ struct rearmed_cbs {
        unsigned int *gpu_frame_count;
        unsigned int *gpu_hcnt;
        unsigned int flip_cnt; // increment manually if not using pl_vout_flip
-       unsigned int only_16bpp; // platform is 16bpp-only
-       unsigned int dithering; // 0 off, 1 on, 2 force
-       unsigned int scale_hires;
+       unsigned char only_16bpp; // platform is 16bpp-only
+       unsigned char dithering; // 0 off, 1 on, 2 force
+       unsigned char scale_hires;
+       unsigned char alt_flip;
        int   thread_rendering; // -1 auto, 0 off, 1 on
        struct {
                int   allow_interlace; // 0 off, 1 on, 2 guess
index b728539..2ee4aec 100644 (file)
@@ -94,6 +94,14 @@ static const char * const f1_hack_db[] =
        "SCES03404", "SCES03423", "SCES03424", "SCES03524",
 };
 
+static const char * const alt_flip_db[] =
+{
+       /* Darius Gaiden (Japan) */
+       "SLPS00574", "SLPM80054",
+       /* NFS3 */
+       "SLUS00620",
+};
+
 #define HACK_ENTRY(var, list) \
        { #var, &Config.hacks.var, list, ARRAY_SIZE(list) }
 
@@ -112,6 +120,7 @@ hack_db[] =
        HACK_ENTRY(dualshock_init_analog, dualshock_init_analog_hack_db),
        HACK_ENTRY(fractional_Framerate, fractional_Framerate_hack_db),
        HACK_ENTRY(f1, f1_hack_db),
+       HACK_ENTRY(alt_flip, alt_flip_db),
 };
 
 static const struct
index d181eb2..cd12cfe 100644 (file)
@@ -133,8 +133,9 @@ typedef struct {
        int cycle_multiplier; // 100 for 1.0
        int cycle_multiplier_override;
        int gpu_timing_override;
-       s8 GpuListWalking;
-       s8 FractionalFramerate; // ~49.75 and ~59.81 instead of 50 and 60
+       s8 GpuListWalking; // -1..1: -1 = auto, 0/1 = off/on
+       s8 FractionalFramerate; // -1..1, ~49.75 and ~59.81 instead of 50 and 60
+       s8 AlternativeFlip; // -1..1
        u8 Cpu; // CPU_DYNAREC or CPU_INTERPRETER
        u8 PsxType; // PSX_TYPE_NTSC or PSX_TYPE_PAL
        u8 PsxRegion; // PSX_REGION_US, PSX_REGION_JP, PSX_REGION_EU
@@ -145,6 +146,7 @@ typedef struct {
                boolean dualshock_init_analog;
                boolean fractional_Framerate;
                boolean f1;
+               boolean alt_flip;
        } hacks;
 } PcsxConfig;
 
index bc1150e..0e967d6 100644 (file)
@@ -418,16 +418,6 @@ void GPUwriteStatus(uint32_t data)
         gpu.frameskip.last_flip_frame = *gpu.state.frame_count;
       }
       if (changed) {
-        if (!gpu.state.vblank && !(gpu.status & PSX_GPU_STATUS_BLANKING) &&
-            !gpu.state.use_alternative_flip)
-        {
-          uint32_t fdiff = frame - gpu.state.last_adflip_frame;
-          gpu.state.last_adflip_frame = frame;
-          if (fdiff < 9u) {
-            log_anomaly(&gpu, "active display flip detected\n");
-            gpu.state.use_alternative_flip = 1;
-          }
-        }
         if (gpu_async_enabled(&gpu))
           gpu_async_notify_screen_change(&gpu);
         else
@@ -1171,7 +1161,6 @@ static void GPUupdateLace(void)
 void GPUvBlank(int is_vblank, int lcf)
 {
   int interlace;
-  gpu.state.vblank = is_vblank;
   interlace = gpu.state.allow_interlace
     && (gpu.status & PSX_GPU_STATUS_INTERLACE)
     && (gpu.status & PSX_GPU_STATUS_DHEIGHT);
@@ -1223,7 +1212,7 @@ void GPUrearmedCallbacks(const struct rearmed_cbs *cbs)
   gpu.state.enhancement_enable = cbs->gpu_neon.enhancement_enable;
   gpu.state.enhancement_active = 0;
   gpu.state.downscale_enable = cbs->scale_hires;
-  gpu.state.use_alternative_flip = 0;
+  gpu.state.use_alternative_flip = cbs->alt_flip;
   gpu.state.screen_centering_type_default = cbs->screen_centering_type_default;
   if (gpu.state.screen_centering_type != cbs->screen_centering_type
       || gpu.state.screen_centering_x != cbs->screen_centering_x
index 21ce832..371706a 100644 (file)
@@ -86,7 +86,6 @@ struct psx_gpu {
     uint32_t old_interlace:1;
     uint32_t allow_interlace:2;
     uint32_t blanked:1;
-    uint32_t vblank:1;
     uint32_t use_alternative_flip:1;
     uint32_t enhancement_enable:1;
     uint32_t enhancement_active:1;
@@ -103,7 +102,6 @@ struct psx_gpu {
       uint32_t hcnt;
     } last_list;
     uint32_t last_vram_read_frame;
-    uint32_t last_adflip_frame;
     uint16_t w_out_old, h_out_old, src_y_old;
     uint32_t status_vo_old;
     short screen_centering_type;