cdrom: change pause timing again master github/master
authornotaz <notasas@gmail.com>
Mon, 15 Apr 2024 21:38:14 +0000 (00:38 +0300)
committernotaz <notasas@gmail.com>
Mon, 15 Apr 2024 21:38:14 +0000 (00:38 +0300)
for DDR series

18 files changed:
.gitmodules
Makefile
deps/libchdr [new submodule]
frontend/libretro.c
frontend/libretro_core_options.h
frontend/main.c
frontend/menu.c
frontend/plugin_lib.c
libchdr [deleted submodule]
libpcsxcore/cdrom.c
libpcsxcore/database.c
libpcsxcore/psxcommon.h
libpcsxcore/psxcounters.c
libpcsxcore/psxcounters.h
plugins/dfsound/externals.h
plugins/dfsound/freeze.c
plugins/dfsound/spu.c
plugins/dfsound/xa.c

index 691f830..44495e6 100644 (file)
@@ -5,5 +5,5 @@
        path = frontend/warm
        url = https://github.com/notaz/warm.git
 [submodule "libchdr"]
-       path = libchdr
+       path = deps/libchdr
        url = https://github.com/rtissera/libchdr.git
index 8b2b87d..32cd6cf 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -168,18 +168,47 @@ endif
 
 # cdrcimg
 OBJS += plugins/cdrcimg/cdrcimg.o
-#ifeq "$(CHD_SUPPORT)" "1"
-OBJS += libchdr/src/libchdr_bitstream.o
-OBJS += libchdr/src/libchdr_cdrom.o
-OBJS += libchdr/src/libchdr_chd.o
-OBJS += libchdr/src/libchdr_flac.o
-OBJS += libchdr/src/libchdr_huffman.o
-OBJS += libchdr/deps/lzma-19.00/src/Alloc.o libchdr/deps/lzma-19.00/src/Bra86.o libchdr/deps/lzma-19.00/src/BraIA64.o libchdr/deps/lzma-19.00/src/CpuArch.o libchdr/deps/lzma-19.00/src/Delta.o
-OBJS += libchdr/deps/lzma-19.00/src/LzFind.o libchdr/deps/lzma-19.00/src/Lzma86Dec.o libchdr/deps/lzma-19.00/src/LzmaDec.o libchdr/deps/lzma-19.00/src/LzmaEnc.o libchdr/deps/lzma-19.00/src/Sort.o
-CFLAGS += -DHAVE_CHD -Ilibchdr/include
+
+# libchdr
+#ifeq "$(HAVE_CHD)" "1"
+LCHDR = deps/libchdr
+LCHDR_LZMA = $(LCHDR)/deps/lzma-22.01
+LCHDR_ZSTD = $(LCHDR)/deps/zstd-1.5.5/lib
+OBJS += $(LCHDR)/src/libchdr_bitstream.o
+OBJS += $(LCHDR)/src/libchdr_cdrom.o
+OBJS += $(LCHDR)/src/libchdr_chd.o
+OBJS += $(LCHDR)/src/libchdr_flac.o
+OBJS += $(LCHDR)/src/libchdr_huffman.o
+$(LCHDR)/src/%.o: CFLAGS += -Wno-unused -std=gnu11
+OBJS += $(LCHDR_LZMA)/src/Alloc.o
+OBJS += $(LCHDR_LZMA)/src/Bra86.o
+OBJS += $(LCHDR_LZMA)/src/BraIA64.o
+OBJS += $(LCHDR_LZMA)/src/CpuArch.o
+OBJS += $(LCHDR_LZMA)/src/Delta.o
+OBJS += $(LCHDR_LZMA)/src/LzFind.o
+OBJS += $(LCHDR_LZMA)/src/Lzma86Dec.o
+OBJS += $(LCHDR_LZMA)/src/LzmaDec.o
+OBJS += $(LCHDR_LZMA)/src/LzmaEnc.o
+OBJS += $(LCHDR_LZMA)/src/Sort.o
+$(LCHDR_LZMA)/src/%.o: CFLAGS += -Wno-unused -D_7ZIP_ST -I$(LCHDR_LZMA)/include
+$(LCHDR)/src/%.o: CFLAGS += -I$(LCHDR_LZMA)/include
+OBJS += $(LCHDR_ZSTD)/common/debug.o
+OBJS += $(LCHDR_ZSTD)/common/entropy_common.o
+OBJS += $(LCHDR_ZSTD)/common/error_private.o
+OBJS += $(LCHDR_ZSTD)/common/fse_decompress.o
+OBJS += $(LCHDR_ZSTD)/common/pool.o
+OBJS += $(LCHDR_ZSTD)/common/threading.o
+OBJS += $(LCHDR_ZSTD)/common/xxhash.o
+OBJS += $(LCHDR_ZSTD)/common/zstd_common.o
+OBJS += $(LCHDR_ZSTD)/decompress/huf_decompress.o
+OBJS += $(LCHDR_ZSTD)/decompress/zstd_ddict.o
+OBJS += $(LCHDR_ZSTD)/decompress/zstd_decompress_block.o
+OBJS += $(LCHDR_ZSTD)/decompress/zstd_decompress.o
+$(LCHDR_ZSTD)/common/%.o \
+$(LCHDR_ZSTD)/decompress/%.o: CFLAGS += -DZSTD_DISABLE_ASM -I$(LCHDR_ZSTD)
+$(LCHDR)/src/%.o: CFLAGS += -I$(LCHDR_ZSTD)
 libpcsxcore/cdriso.o: CFLAGS += -Wno-unused-function
-libchdr/src/%.o: CFLAGS += -Wno-unused -Ilibchdr/deps/lzma-19.00/include -std=gnu11
-libchdr/deps/lzma-19.00/src/%.o: CFLAGS += -Wno-unused -D_7ZIP_ST -Ilibchdr/deps/lzma-19.00/include
+CFLAGS += -DHAVE_CHD -I$(LCHDR)/include
 #endif
 
 # frontend/gui
diff --git a/deps/libchdr b/deps/libchdr
new file mode 160000 (submodule)
index 0000000..5c598c2
--- /dev/null
@@ -0,0 +1 @@
+Subproject commit 5c598c2df3a7717552a76410d79f5af01ff51b1d
index ffd64c7..6a719ae 100644 (file)
@@ -131,7 +131,8 @@ static unsigned previous_width = 0;
 static unsigned previous_height = 0;
 
 static int plugins_opened;
-static int is_pal_mode;
+
+#define is_pal_mode Config.PsxType
 
 /* memory card data */
 extern char Mcd1Data[MCD_SIZE];
@@ -294,16 +295,17 @@ static void convert(void *buf, size_t bytes)
 static void addCrosshair(int port, int crosshair_color, unsigned short *buffer, int bufferStride, int pos_x, int pos_y, int thickness, int size_x, int size_y) {
    for (port = 0; port < 2; port++) {
       // Draw the horizontal line of the crosshair
-      for (int i = pos_y - thickness / 2; i <= pos_y + thickness / 2; i++) {
-         for (int j = pos_x - size_x / 2; j <= pos_x + size_x / 2; j++) {
+      int i, j;
+      for (i = pos_y - thickness / 2; i <= pos_y + thickness / 2; i++) {
+         for (j = pos_x - size_x / 2; j <= pos_x + size_x / 2; j++) {
             if ((i + vout_height) >= 0 && (i + vout_height) < bufferStride && j >= 0 && j < bufferStride && in_enable_crosshair[port] > 0)
                buffer[i * bufferStride + j] = crosshair_color;
-      }
          }
+      }
 
       // Draw the vertical line of the crosshair
-      for (int i = pos_x - thickness / 2; i <= pos_x + thickness / 2; i++) {
-         for (int j = pos_y - size_y / 2; j <= pos_y + size_y / 2; j++) {
+      for (i = pos_x - thickness / 2; i <= pos_x + thickness / 2; i++) {
+         for (j = pos_y - size_y / 2; j <= pos_y + size_y / 2; j++) {
             if (i >= 0 && i < bufferStride && (j + vout_height) >= 0 && (j + vout_height) < bufferStride && in_enable_crosshair[port] > 0)
                buffer[j * bufferStride + i] = crosshair_color;
          }
@@ -366,8 +368,8 @@ static void vout_flip(const void *vram, int stride, int bgr24,
    for (port = 0; port < 2; port++) {
       if (in_enable_crosshair[port] > 0 && (in_type[port] == PSE_PAD_TYPE_GUNCON || in_type[port] == PSE_PAD_TYPE_GUN))
       {
-        struct CrosshairInfo crosshairInfo;
-        CrosshairDimensions(port, &crosshairInfo);
+         struct CrosshairInfo crosshairInfo;
+         CrosshairDimensions(port, &crosshairInfo);
          addCrosshair(port, in_enable_crosshair[port], dest, dstride, crosshairInfo.pos_x, crosshairInfo.pos_y, crosshairInfo.thickness, crosshairInfo.size_x, crosshairInfo.size_y);
       }
    }
@@ -585,7 +587,6 @@ void pl_frame_limit(void)
 
 void pl_timing_prepare(int is_pal)
 {
-   is_pal_mode = is_pal;
 }
 
 void plat_trigger_vibrate(int pad, int low, int high)
@@ -727,8 +728,8 @@ static bool update_option_visibility(void)
             "pcsx_rearmed_negcon_deadzone",
             "pcsx_rearmed_negcon_response",
             "pcsx_rearmed_input_sensitivity",
-           "pcsx_rearmed_crosshair1",
-           "pcsx_rearmed_crosshair2",
+            "pcsx_rearmed_crosshair1",
+            "pcsx_rearmed_crosshair2",
             "pcsx_rearmed_konamigunadjustx",
             "pcsx_rearmed_konamigunadjusty",
             "pcsx_rearmed_gunconadjustx",
@@ -1001,7 +1002,7 @@ void retro_get_system_av_info(struct retro_system_av_info *info)
    unsigned geom_width           = vout_width;
 
    memset(info, 0, sizeof(*info));
-   info->timing.fps              = is_pal_mode ? 50.0 : 60.0;
+   info->timing.fps              = psxGetFps();
    info->timing.sample_rate      = 44100.0;
    info->geometry.base_width     = geom_width;
    info->geometry.base_height    = geom_height;
@@ -2264,6 +2265,7 @@ static void update_variables(bool in_flight)
    int gpu_peops_fix = GPU_PEOPS_OLD_FRAME_SKIP;
 #endif
    frameskip_type_t prev_frameskip_type;
+   double old_fps = psxGetFps();
 
    var.value = NULL;
    var.key = "pcsx_rearmed_frameskip_type";
@@ -2705,6 +2707,18 @@ static void update_variables(bool in_flight)
          Config.GpuListWalking = -1;
    }
 
+   var.value = NULL;
+   var.key = "pcsx_rearmed_fractional_framerate";
+   if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
+   {
+      if (strcmp(var.value, "disabled") == 0)
+         Config.FractionalFramerate = 0;
+      else if (strcmp(var.value, "enabled") == 0)
+         Config.FractionalFramerate = 1;
+      else // auto
+         Config.FractionalFramerate = -1;
+   }
+
    var.value = NULL;
    var.key = "pcsx_rearmed_screen_centering";
    if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
@@ -3004,6 +3018,13 @@ static void update_variables(bool in_flight)
    }
 
    update_option_visibility();
+
+   if (old_fps != psxGetFps())
+   {
+      struct retro_system_av_info info;
+      retro_get_system_av_info(&info);
+      environ_cb(RETRO_ENVIRONMENT_SET_SYSTEM_AV_INFO, &info);
+   }
 }
 
 // Taken from beetle-psx-libretro
index be9e8ab..451ee47 100644 (file)
@@ -425,6 +425,21 @@ struct retro_core_option_v2_definition option_defs_us[] = {
       },
       "disabled",
    },
+   {
+      "pcsx_rearmed_fractional_framerate",
+      "Use fractional frame rate",
+      NULL,
+      "Instead of the exact 50 or 60 (maximum) fps for PAL/NTSC the real console runs closer to something like 49.75 and 59.81fps (varies slightly between hw versions). PCSX-ReARMed uses the former \"round\" framerates to better match modern displays, however that may cause audio/video desync in games like DDR and Spyro 2 (intro). With this option you can try to use fractional framerates.",
+      NULL,
+      "video",
+      {
+         { "auto", "Auto" },
+         { "disabled", NULL },
+         { "enabled",  NULL },
+         { NULL, NULL },
+      },
+      "auto",
+   },
    {
       "pcsx_rearmed_gpu_slow_llists",
       "(GPU) Slow linked list processing",
@@ -433,7 +448,7 @@ struct retro_core_option_v2_definition option_defs_us[] = {
       NULL,
       "video",
       {
-         { "auto", NULL },
+         { "auto", "Auto" },
          { "disabled", NULL },
          { "enabled",  NULL },
          { NULL, NULL },
index 53f31b0..ce7eca6 100644 (file)
@@ -136,6 +136,7 @@ void emu_set_default_config(void)
        Config.PsxAuto = 1;
        Config.cycle_multiplier = CYCLE_MULT_DEFAULT;
        Config.GpuListWalking = -1;
+       Config.FractionalFramerate = -1;
 
        pl_rearmed_cbs.gpu_neon.allow_interlace = 2; // auto
        pl_rearmed_cbs.gpu_neon.enhancement_enable =
index 6c669dc..58efd21 100644 (file)
@@ -408,6 +408,7 @@ static const struct {
        CE_CONFIG_VAL(DisableStalls),
        CE_CONFIG_VAL(Cpu),
        CE_CONFIG_VAL(GpuListWalking),
+       CE_CONFIG_VAL(FractionalFramerate),
        CE_CONFIG_VAL(PreciseExceptions),
        CE_INTVAL(region),
        CE_INTVAL_V(g_scaler, 3),
@@ -1638,7 +1639,7 @@ static int menu_loop_speed_hacks(int id, int keys)
        return 0;
 }
 
-static const char *men_gpul[]    = { "Auto", "Off", "On", NULL };
+static const char *men_autooo[]  = { "Auto", "Off", "On", NULL };
 
 static const char h_cfg_cpul[]   = "Shows CPU usage in %";
 static const char h_cfg_spu[]    = "Shows active SPU channels\n"
@@ -1657,10 +1658,12 @@ static const char h_cfg_exc[]    = "Emulate some PSX's debug hw like breakpoints
                                   "and exceptions (slow, interpreter only, keep off)";
 static const char h_cfg_gpul[]   = "Try enabling this if the game misses some graphics\n"
                                   "causes a performance hit";
+static const char h_cfg_ffps[]   = "Instead of 50/60fps for PAL/NTSC use ~49.75/59.81\n"
+                                  "Closer to real hw but doesn't match modern displays.";
 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 };
+enum { AMO_XA, AMO_CDDA, AMO_IC, AMO_BP, AMO_CPU, AMO_GPUL, AMO_FFPS };
 
 static menu_entry e_menu_adv_options[] =
 {
@@ -1671,7 +1674,8 @@ static menu_entry e_menu_adv_options[] =
        mee_onoff_h   ("Disable CD Audio",       0, menu_iopts[AMO_CDDA], 1, h_cfg_cdda),
        mee_onoff_h   ("ICache emulation",       0, menu_iopts[AMO_IC],   1, h_cfg_icache),
        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_gpul, h_cfg_gpul),
+       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),
 #if !defined(DRC_DISABLE) || defined(LIGHTREC)
        mee_onoff_h   ("Disable dynarec (slow!)",0, menu_iopts[AMO_CPU],  1, h_cfg_nodrc),
 #endif
@@ -1697,12 +1701,14 @@ static int menu_loop_adv_options(int id, int keys)
        for (i = 0; i < ARRAY_SIZE(opts); i++)
                *opts[i].mopt = *opts[i].opt;
        menu_iopts[AMO_GPUL] = Config.GpuListWalking + 1;
+       menu_iopts[AMO_FFPS] = Config.FractionalFramerate + 1;
 
        me_loop(e_menu_adv_options, &sel);
 
        for (i = 0; i < ARRAY_SIZE(opts); i++)
                *opts[i].opt = *opts[i].mopt;
        Config.GpuListWalking = menu_iopts[AMO_GPUL] - 1;
+       Config.FractionalFramerate = menu_iopts[AMO_FFPS] - 1;
 
        return 0;
 }
index 0deab15..9b6faf4 100644 (file)
@@ -35,6 +35,7 @@
 #include "../libpcsxcore/psxmem_map.h"
 #include "../libpcsxcore/gpu.h"
 #include "../libpcsxcore/r3000a.h"
+#include "../libpcsxcore/psxcounters.h"
 
 #define HUD_HEIGHT 10
 
@@ -778,18 +779,20 @@ void pl_frame_limit(void)
 
 void pl_timing_prepare(int is_pal_)
 {
+       double fps;
        pl_rearmed_cbs.fskip_advice = 0;
        pl_rearmed_cbs.flips_per_sec = 0;
        pl_rearmed_cbs.cpu_usage = 0;
 
        is_pal = is_pal_;
-       frame_interval = is_pal ? 20000 : 16667;
-       frame_interval1024 = is_pal ? 20000*1024 : 17066667;
+       fps = psxGetFps();
+       frame_interval = (int)(1000000.0 / fps);
+       frame_interval1024 = (int)(1000000.0 * 1024.0 / fps);
 
        // used by P.E.Op.S. frameskip code
-       pl_rearmed_cbs.gpu_peops.fFrameRateHz = is_pal ? 50.0f : 59.94f;
+       pl_rearmed_cbs.gpu_peops.fFrameRateHz = (float)fps;
        pl_rearmed_cbs.gpu_peops.dwFrameRateTicks =
-               (100000*100 / (unsigned long)(pl_rearmed_cbs.gpu_peops.fFrameRateHz*100));
+               (100000*100 / (int)(pl_rearmed_cbs.gpu_peops.fFrameRateHz*100));
 }
 
 static void pl_get_layer_pos(int *x, int *y, int *w, int *h)
diff --git a/libchdr b/libchdr
deleted file mode 160000 (submodule)
index 54bfb87..0000000
--- a/libchdr
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit 54bfb871ccae31903b95a8feb7f2bf7121f304be
index 5da24c8..d4d1474 100644 (file)
@@ -583,19 +583,15 @@ static int cdrSeekTime(unsigned char *target)
        int cyclesSinceRS = psxRegs.cycle - cdr.LastReadSeekCycles;
        seekTime = MAX_VALUE(seekTime, 20000);
 
-       // need this stupidly long penalty or else Spyro2 intro desyncs
-       // note: if misapplied this breaks MGS cutscenes among other things
-       if (cdr.DriveState == DRIVESTATE_PAUSED && cyclesSinceRS > cdReadTime * 50)
-               seekTime += cdReadTime * 25;
        // Transformers Beast Wars Transmetals does Setloc(x),SeekL,Setloc(x),ReadN
        // and then wants some slack time
-       else if (cdr.DriveState == DRIVESTATE_PAUSED || cyclesSinceRS < cdReadTime *3/2)
+       if (cdr.DriveState == DRIVESTATE_PAUSED || cyclesSinceRS < cdReadTime *3/2)
                seekTime += cdReadTime;
 
        seekTime = MIN_VALUE(seekTime, PSXCLK * 2 / 3);
-       CDR_LOG("seek: %.2f %.2f (%.2f) st %d\n", (float)seekTime / PSXCLK,
+       CDR_LOG("seek: %.2f %.2f (%.2f) st %d di %d\n", (float)seekTime / PSXCLK,
                (float)seekTime / cdReadTime, (float)cyclesSinceRS / cdReadTime,
-               cdr.DriveState);
+               cdr.DriveState, diff);
        return seekTime;
 }
 
@@ -975,27 +971,19 @@ void cdrInterrupt(void) {
                        cdr.sectorsRead = 0;
 
                        /*
-                       Gundam Battle Assault 2: much slower (*)
-                       - Fixes boot, gameplay
-
-                       Hokuto no Ken 2: slower
-                       - Fixes intro + subtitles
-
-                       InuYasha - Feudal Fairy Tale: slower
-                       - Fixes battles
+                       Gundam Battle Assault 2
+                       Hokuto no Ken 2
+                       InuYasha - Feudal Fairy Tale
+                       Dance Dance Revolution Konamix
+                       ...
                        */
-                       /* Gameblabla - Tightening the timings (as taken from Duckstation). 
-                        * The timings from Duckstation are based upon hardware tests.
-                        * Mednafen's timing don't work for Gundam Battle Assault 2 in PAL/50hz mode,
-                        * seems to be timing sensitive as it can depend on the CPU's clock speed.
-                        * */
                        if (!(cdr.StatP & (STATUS_PLAY | STATUS_READ)))
                        {
                                second_resp_time = 7000;
                        }
                        else
                        {
-                               second_resp_time = (((cdr.Mode & MODE_SPEED) ? 1 : 2) * 1097107);
+                               second_resp_time = 2 * 1097107;
                        }
                        SetPlaySeekRead(cdr.StatP, 0);
                        DriveStateOld = cdr.DriveState;
@@ -1399,7 +1387,7 @@ static void cdrReadInterrupt(void)
                        subhdr->file, subhdr->chan, cdr.CurFile, cdr.CurChannel, cdr.FilterFile, cdr.FilterChannel);
                if ((cdr.Mode & MODE_SF) && (subhdr->file != cdr.FilterFile || subhdr->chan != cdr.FilterChannel))
                        break;
-               if (subhdr->chan & 0xe0) { // ?
+               if (subhdr->chan & 0x80) { // ?
                        if (subhdr->chan != 0xff)
                                log_unhandled("adpcm %d:%d\n", subhdr->file, subhdr->chan);
                        break;
index 86a24a4..ef990ac 100644 (file)
@@ -59,6 +59,22 @@ static const char * const dualshock_init_analog_hack_db[] =
        "SLUS00546",
 };
 
+static const char * const fractional_Framerate_hack_db[] =
+{
+       /* Dance Dance Revolution */
+       "SLPM86503", // 3rd Mix
+       "SLPM86752", // 4th Mix
+       "SLPM86266", // 4thMix: The Beat Goes On
+       "SLPM86831", // Extra Mix
+       "SLUS01446", // Konamix
+       /* Dancing Stage Fever */
+       "SLES04097",
+       /* Dancing Stage Fusion */
+       "SLES04163",
+       /* Spyro 2 */
+       "SCUS94425", "SCES02104",
+};
+
 #define HACK_ENTRY(var, list) \
        { #var, &Config.hacks.var, list, ARRAY_SIZE(list) }
 
@@ -76,6 +92,7 @@ hack_db[] =
        HACK_ENTRY(gpu_centering, gpu_centering_hack_db),
        HACK_ENTRY(gpu_timing1024, dualshock_timing1024_hack_db),
        HACK_ENTRY(dualshock_init_analog, dualshock_init_analog_hack_db),
+       HACK_ENTRY(fractional_Framerate, fractional_Framerate_hack_db),
 };
 
 static const struct
@@ -91,6 +108,8 @@ cycle_multiplier_overrides[] =
        /* Super Robot Taisen Alpha - on the edge with 175,
         * changing memcard settings is enough to break/unbreak it */
        { 190, { "SLPS02528", "SLPS02636" } },
+       /* Colin McRae Rally - language selection menu does not work with 175 */
+       { 174, { "SLES00477" } },
        /* Brave Fencer Musashi - cd sectors arrive too fast */
        { 170, { "SLUS00726", "SLPS01490" } },
 #if defined(DRC_DISABLE) || defined(LIGHTREC) /* new_dynarec has a hack for this game */
index a25e625..53bda97 100644 (file)
@@ -142,9 +142,10 @@ typedef struct {
        boolean icache_emulation;
        boolean DisableStalls;
        boolean PreciseExceptions;
-       int GpuListWalking;
        int cycle_multiplier; // 100 for 1.0
        int cycle_multiplier_override;
+       s8 GpuListWalking;
+       s8 FractionalFramerate; // ~49.75 and ~59.81 instead of 50 and 60
        u8 Cpu; // CPU_DYNAREC or CPU_INTERPRETER
        u8 PsxType; // PSX_TYPE_NTSC or PSX_TYPE_PAL
        struct {
@@ -153,6 +154,7 @@ typedef struct {
                boolean gpu_centering;
                boolean dualshock_init_analog;
                boolean gpu_timing1024;
+               boolean fractional_Framerate;
        } hacks;
 } PcsxConfig;
 
index c627120..887fe8a 100644 (file)
@@ -79,9 +79,40 @@ u32 psxNextCounter = 0, psxNextsCounter = 0;
 
 /******************************************************************************/
 
+#define FPS_FRACTIONAL_PAL  (53203425/314./3406) // ~49.75
+#define FPS_FRACTIONAL_NTSC (53693175/263./3413) // ~59.81
+
+static inline
+u32 frameCycles(void)
+{
+    int ff = Config.FractionalFramerate >= 0
+        ? Config.FractionalFramerate : Config.hacks.fractional_Framerate;
+    if (ff)
+    {
+        if (Config.PsxType)
+            return (u32)(PSXCLK / FPS_FRACTIONAL_PAL);
+        else
+            return (u32)(PSXCLK / FPS_FRACTIONAL_NTSC);
+    }
+    return Config.PsxType ? (PSXCLK / 50) : (PSXCLK / 60);
+}
+
+// used to inform the frontend about the exact framerate
+double psxGetFps()
+{
+    int ff = Config.FractionalFramerate >= 0
+        ? Config.FractionalFramerate : Config.hacks.fractional_Framerate;
+    if (ff)
+        return Config.PsxType ? FPS_FRACTIONAL_PAL : FPS_FRACTIONAL_NTSC;
+    else
+        return Config.PsxType ? 50.0 : 60.0;
+}
+
+// to inform the frontend about the exact famerate
 static inline
 u32 lineCycles(void)
 {
+    // should be more like above, but our timing is already poor anyway
     if (Config.PsxType)
         return PSXCLK / 50 / HSyncTotal[1];
     else
@@ -308,7 +339,7 @@ static void scheduleRcntBase(void)
 
     if (hSyncCount + hsync_steps == HSyncTotal[Config.PsxType])
     {
-        rcnts[3].cycle = Config.PsxType ? PSXCLK / 50 : PSXCLK / 60;
+        rcnts[3].cycle = frameCycles();
     }
     else
     {
@@ -380,7 +411,7 @@ void psxRcntUpdate()
         if( hSyncCount >= HSyncTotal[Config.PsxType] )
         {
             u32 status, field = 0;
-            rcnts[3].cycleStart += Config.PsxType ? PSXCLK / 50 : PSXCLK / 60;
+            rcnts[3].cycleStart += frameCycles();
             hSyncCount = 0;
             frame_counter++;
 
index 03cd468..77025a6 100644 (file)
@@ -56,6 +56,8 @@ u32 psxRcntRtarget(u32 index);
 
 s32 psxRcntFreeze(void *f, s32 Mode);
 
+double psxGetFps();
+
 #ifdef __cplusplus
 }
 #endif
index ac0960f..6dbbac6 100644 (file)
@@ -58,7 +58,7 @@
 #define MAXCHAN     24\r
 \r
 // note: must be even due to the way reverb works now\r
-#define NSSIZE ((44100 / 50 + 16) & ~1)\r
+#define NSSIZE ((44100 / 50 + 32) & ~1)\r
 \r
 ///////////////////////////////////////////////////////////\r
 // struct defines\r
@@ -214,6 +214,7 @@ typedef struct
  int             iLeftXAVol;\r
  int             iRightXAVol;\r
 \r
+ int             cdClearSamples;       // extra samples to clear the capture buffers\r
  struct {                              // channel volume in the cd controller\r
   unsigned char  ll, lr, rl, rr;       // see cdr.Attenuator* in cdrom.c\r
  } cdv;                                // applied on spu side for easier emulation\r
index bddf0ad..36b8995 100644 (file)
@@ -338,6 +338,7 @@ long CALLBACK SPUfreeze(unsigned int ulFreezeMode, SPUFreeze_t * pF,
 \r
  spu.XAPlay = spu.XAFeed = spu.XAStart;\r
  spu.CDDAPlay = spu.CDDAFeed = spu.CDDAStart;\r
+ spu.cdClearSamples = 512;\r
  if (pFO && pFO->xa_left && pF->xaS.nsamples) {        // start xa again\r
   FeedXA(&pF->xaS);\r
   spu.XAPlay = spu.XAFeed - pFO->xa_left;\r
index 022a1e3..ed5b4b5 100644 (file)
@@ -1389,6 +1389,7 @@ void CALLBACK SPUplayADPCMchannel(xa_decode_t *xap, unsigned int cycle, int is_s
 
  FeedXA(xap);                          // call main XA feeder
  spu.xapGlobal = xap;                  // store info for save states
+ spu.cdClearSamples = 512;
 }
 
 // CDDA AUDIO
@@ -1401,6 +1402,7 @@ int CALLBACK SPUplayCDDAchannel(short *pcm, int nbytes, unsigned int cycle, int
   do_samples(cycle, 1);                // catch up to prevent source underflows later
 
  FeedCDDA((unsigned char *)pcm, nbytes);
+ spu.cdClearSamples = 512;
  return 0;
 }
 
index 6b5433f..380d138 100644 (file)
@@ -152,8 +152,16 @@ INLINE void MixCD(int *SSumLR, int *RVB, int ns_to, int decode_pos)
    }
   spu.XALastVal = v;
  }
- else
+ else if (spu.cdClearSamples > 0)
+ {
+  for(ns = 0; ns < ns_to; ns++)
+   {
+    spu.spuMem[cursor] = spu.spuMem[cursor + 0x400/2] = 0;
+    cursor = (cursor + 1) & 0x1ff;
+   }
+  spu.cdClearSamples -= ns_to;
   spu.XALastVal = 0;
+ }
 }
 
 ////////////////////////////////////////////////////////////////////////