From: notaz Date: Mon, 15 Apr 2024 21:38:14 +0000 (+0300) Subject: cdrom: change pause timing again X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?p=pcsx_rearmed.git;a=commitdiff_plain;h=refs%2Fremotes%2Fgithub%2Fmaster;hp=3047daea4d4f6f00fdaa0467c15efd128b822367 cdrom: change pause timing again for DDR series --- diff --git a/.gitmodules b/.gitmodules index 691f8309..44495e68 100644 --- a/.gitmodules +++ b/.gitmodules @@ -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 diff --git a/Makefile b/Makefile index 8b2b87d9..32cd6cf9 100644 --- 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 index 00000000..5c598c2d --- /dev/null +++ b/deps/libchdr @@ -0,0 +1 @@ +Subproject commit 5c598c2df3a7717552a76410d79f5af01ff51b1d diff --git a/frontend/libretro.c b/frontend/libretro.c index ffd64c7e..6a719ae4 100644 --- a/frontend/libretro.c +++ b/frontend/libretro.c @@ -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 diff --git a/frontend/libretro_core_options.h b/frontend/libretro_core_options.h index be9e8abf..451ee478 100644 --- a/frontend/libretro_core_options.h +++ b/frontend/libretro_core_options.h @@ -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 }, diff --git a/frontend/main.c b/frontend/main.c index 53f31b0a..ce7eca6c 100644 --- a/frontend/main.c +++ b/frontend/main.c @@ -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 = diff --git a/frontend/menu.c b/frontend/menu.c index 6c669dc3..58efd218 100644 --- a/frontend/menu.c +++ b/frontend/menu.c @@ -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; } diff --git a/frontend/plugin_lib.c b/frontend/plugin_lib.c index 0deab157..9b6faf44 100644 --- a/frontend/plugin_lib.c +++ b/frontend/plugin_lib.c @@ -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 index 54bfb871..00000000 --- a/libchdr +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 54bfb871ccae31903b95a8feb7f2bf7121f304be diff --git a/libpcsxcore/cdrom.c b/libpcsxcore/cdrom.c index 5da24c82..d4d14742 100644 --- a/libpcsxcore/cdrom.c +++ b/libpcsxcore/cdrom.c @@ -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; diff --git a/libpcsxcore/database.c b/libpcsxcore/database.c index 86a24a49..ef990ac4 100644 --- a/libpcsxcore/database.c +++ b/libpcsxcore/database.c @@ -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 */ diff --git a/libpcsxcore/psxcommon.h b/libpcsxcore/psxcommon.h index a25e6252..53bda973 100644 --- a/libpcsxcore/psxcommon.h +++ b/libpcsxcore/psxcommon.h @@ -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; diff --git a/libpcsxcore/psxcounters.c b/libpcsxcore/psxcounters.c index c6271203..887fe8a4 100644 --- a/libpcsxcore/psxcounters.c +++ b/libpcsxcore/psxcounters.c @@ -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++; diff --git a/libpcsxcore/psxcounters.h b/libpcsxcore/psxcounters.h index 03cd4684..77025a61 100644 --- a/libpcsxcore/psxcounters.h +++ b/libpcsxcore/psxcounters.h @@ -56,6 +56,8 @@ u32 psxRcntRtarget(u32 index); s32 psxRcntFreeze(void *f, s32 Mode); +double psxGetFps(); + #ifdef __cplusplus } #endif diff --git a/plugins/dfsound/externals.h b/plugins/dfsound/externals.h index ac0960f6..6dbbac67 100644 --- a/plugins/dfsound/externals.h +++ b/plugins/dfsound/externals.h @@ -58,7 +58,7 @@ #define MAXCHAN 24 // note: must be even due to the way reverb works now -#define NSSIZE ((44100 / 50 + 16) & ~1) +#define NSSIZE ((44100 / 50 + 32) & ~1) /////////////////////////////////////////////////////////// // struct defines @@ -214,6 +214,7 @@ typedef struct int iLeftXAVol; int iRightXAVol; + int cdClearSamples; // extra samples to clear the capture buffers struct { // channel volume in the cd controller unsigned char ll, lr, rl, rr; // see cdr.Attenuator* in cdrom.c } cdv; // applied on spu side for easier emulation diff --git a/plugins/dfsound/freeze.c b/plugins/dfsound/freeze.c index bddf0ada..36b89959 100644 --- a/plugins/dfsound/freeze.c +++ b/plugins/dfsound/freeze.c @@ -338,6 +338,7 @@ long CALLBACK SPUfreeze(unsigned int ulFreezeMode, SPUFreeze_t * pF, spu.XAPlay = spu.XAFeed = spu.XAStart; spu.CDDAPlay = spu.CDDAFeed = spu.CDDAStart; + spu.cdClearSamples = 512; if (pFO && pFO->xa_left && pF->xaS.nsamples) { // start xa again FeedXA(&pF->xaS); spu.XAPlay = spu.XAFeed - pFO->xa_left; diff --git a/plugins/dfsound/spu.c b/plugins/dfsound/spu.c index 022a1e3d..ed5b4b5c 100644 --- a/plugins/dfsound/spu.c +++ b/plugins/dfsound/spu.c @@ -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; } diff --git a/plugins/dfsound/xa.c b/plugins/dfsound/xa.c index 6b5433fb..380d1388 100644 --- a/plugins/dfsound/xa.c +++ b/plugins/dfsound/xa.c @@ -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; + } } ////////////////////////////////////////////////////////////////////////