diff --git a/core/hw/pvr/spg.cpp b/core/hw/pvr/spg.cpp index cd69dd7f..d3b63af1 100644 --- a/core/hw/pvr/spg.cpp +++ b/core/hw/pvr/spg.cpp @@ -59,6 +59,24 @@ void CalculateSync(void) sh4_sched_request(vblank_schid, Line_Cycles); } +/* + * Actual emulated vertical refresh rate, derived from the same SPG timing the + * scheduler runs on: pixel_clock / ((hcount+1) * (vcount+1)), i.e. + * SH4_MAIN_CLOCK / (Line_Cycles * pvr_numscanlines). This is the rate at which + * frames (and thus audio) are actually produced, so reporting it to the + * frontend via retro_get_system_av_info keeps timing.fps in step with the core + * instead of a bucketed 60/59.94/50 guess. It naturally yields the hardware + * figures: ~59.94 for VGA and 480i, ~59.83 for 240p NTSC, 50.00 for PAL 480i, + * and the higher NAOMI rates for boards that program the SPG accordingly. + * Falls back to 60 before CalculateSync has run. + */ +double spg_get_refresh_rate(void) +{ + if (Line_Cycles == 0 || pvr_numscanlines == 0) + return 60.0; + return (double)SH4_MAIN_CLOCK / ((double)Line_Cycles * (double)pvr_numscanlines); +} + //called from sh4 context , should update pvr/ta state and everything else int spg_line_sched(int tag, int cycl, int jit) diff --git a/core/hw/pvr/spg.h b/core/hw/pvr/spg.h index e98c7806..3b2f121d 100644 --- a/core/hw/pvr/spg.h +++ b/core/hw/pvr/spg.h @@ -6,6 +6,7 @@ void spg_Term(); void spg_Reset(bool Manual); void CalculateSync(); +double spg_get_refresh_rate(); void read_lightgun_position(int x, int y); struct TA_context; void SetREP(TA_context* cntx); diff --git a/core/libretro/libretro.cpp b/core/libretro/libretro.cpp index 43918578..283e8aa1 100644 --- a/core/libretro/libretro.cpp +++ b/core/libretro/libretro.cpp @@ -2304,10 +2304,6 @@ void retro_get_system_info(struct retro_system_info *info) void retro_get_system_av_info(struct retro_system_av_info *info) { - /* 00=VGA 01=NTSC 10=PAL, 11=illegal/undocumented */ - const int spg_clks[4] = { 26944080, 13458568, 13462800, 26944080 }; - u32 pixel_clock= spg_clks[(SPG_CONTROL.full >> 6) & 3]; - if (cheatManager.Reset()) { info->geometry.aspect_ratio = 16.0 / 9.0; @@ -2336,24 +2332,11 @@ void retro_get_system_av_info(struct retro_system_av_info *info) if (rotate_screen) info->geometry.aspect_ratio = 1 / info->geometry.aspect_ratio; - switch (pixel_clock) - { - case 26944080: - info->timing.fps = 60.00; /* (VGA 480 @ 60.00) */ - break; - case 26917135: - info->timing.fps = 59.94; /* (NTSC 480 @ 59.94) */ - break; - case 13462800: - info->timing.fps = 50.00; /* (PAL 240 @ 50.00) */ - break; - case 13458568: - info->timing.fps = 59.94; /* (NTSC 240 @ 59.94) */ - break; - case 25925600: - info->timing.fps = 50.00; /* (PAL 480 @ 50.00) */ - break; - } + /* Report the actual emulated refresh rate, derived from the SPG timing the + * scheduler runs on, so the frontend's frame pacing matches the rate frames + * and audio are really produced at (~59.94 VGA/480i, ~59.83 240p NTSC, + * 50.00 PAL 480i, higher for NAOMI) rather than a bucketed 60/59.94/50. */ + info->timing.fps = spg_get_refresh_rate(); info->timing.sample_rate = 44100.0; }