mirror of
https://github.com/libretro/beetle-psx-libretro.git
synced 2024-11-27 10:50:29 +00:00
Implement true CPU frequency scaling/overclocking
This commit is contained in:
parent
ac3fec5c36
commit
8e7ae9c61f
23
libretro.cpp
23
libretro.cpp
@ -19,6 +19,7 @@
|
|||||||
#include "input.h"
|
#include "input.h"
|
||||||
|
|
||||||
#include "mednafen/mednafen-endian.h"
|
#include "mednafen/mednafen-endian.h"
|
||||||
|
#include "mednafen/psx/psx.h"
|
||||||
|
|
||||||
#include "../pgxp/pgxp_main.h"
|
#include "../pgxp/pgxp_main.h"
|
||||||
|
|
||||||
@ -47,6 +48,9 @@ bool cd_async = false;
|
|||||||
bool cd_warned_slow = false;
|
bool cd_warned_slow = false;
|
||||||
int64 cd_slow_timeout = 8000; // microseconds
|
int64 cd_slow_timeout = 8000; // microseconds
|
||||||
|
|
||||||
|
// CPU overclock factor (or 0 if disabled)
|
||||||
|
int32_t psx_overclock_factor = 0;
|
||||||
|
|
||||||
// Sets how often (in number of output frames/retro_run invocations)
|
// Sets how often (in number of output frames/retro_run invocations)
|
||||||
// the internal framerace counter should be updated if
|
// the internal framerace counter should be updated if
|
||||||
// display_internal_framerate is true.
|
// display_internal_framerate is true.
|
||||||
@ -2673,6 +2677,24 @@ static void check_variables(bool startup)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
var.key = option_cpu_freq_scale;
|
||||||
|
|
||||||
|
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
|
||||||
|
{
|
||||||
|
int scale_percent = atoi(var.value);
|
||||||
|
|
||||||
|
if (scale_percent == 100) {
|
||||||
|
psx_overclock_factor = 0;
|
||||||
|
} else {
|
||||||
|
psx_overclock_factor = ((scale_percent << OVERCLOCK_SHIFT) + 50) / 100;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
psx_overclock_factor = 0;
|
||||||
|
|
||||||
|
// Need to adjust the CPU<->GPU frequency ratio if the overclocking changes
|
||||||
|
GPU_RecalcClockRatio();
|
||||||
|
|
||||||
var.key = option_gte_overclock;
|
var.key = option_gte_overclock;
|
||||||
|
|
||||||
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
|
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
|
||||||
@ -3775,6 +3797,7 @@ void retro_set_environment(retro_environment_t cb)
|
|||||||
#endif
|
#endif
|
||||||
{ option_widescreen_hack, "Widescreen mode hack; disabled|enabled" },
|
{ option_widescreen_hack, "Widescreen mode hack; disabled|enabled" },
|
||||||
{ option_frame_duping, "Frame duping (speedup); disabled|enabled" },
|
{ option_frame_duping, "Frame duping (speedup); disabled|enabled" },
|
||||||
|
{ option_cpu_freq_scale, "CPU frequency scaling (overclock); 100% (native)|110%|120%|130%|140%|150%|160%|170%|180%|190%|200%|300%|400%|500%|90%|80%|70%|60%|50%" },
|
||||||
{ option_gte_overclock, "GTE Overclock; disabled|enabled" },
|
{ option_gte_overclock, "GTE Overclock; disabled|enabled" },
|
||||||
{ option_skip_bios, "Skip BIOS; disabled|enabled" },
|
{ option_skip_bios, "Skip BIOS; disabled|enabled" },
|
||||||
{ option_dither_mode, "Dithering pattern; 1x(native)|internal resolution|disabled" },
|
{ option_dither_mode, "Dithering pattern; 1x(native)|internal resolution|disabled" },
|
||||||
|
@ -42,6 +42,7 @@
|
|||||||
#define option_multitap2 "beetle_psx_hw_enable_multitap_port2"
|
#define option_multitap2 "beetle_psx_hw_enable_multitap_port2"
|
||||||
#define option_mouse_sensitivity "beetle_psx_hw_mouse_sensitivity"
|
#define option_mouse_sensitivity "beetle_psx_hw_mouse_sensitivity"
|
||||||
#define option_gun_cursor "beetle_psx_hw_gun_cursor"
|
#define option_gun_cursor "beetle_psx_hw_gun_cursor"
|
||||||
|
#define option_cpu_freq_scale "beetle_psx_hw_cpu_freq_scale"
|
||||||
#define option_gte_overclock "beetle_psx_hw_gte_overclock"
|
#define option_gte_overclock "beetle_psx_hw_gte_overclock"
|
||||||
#define option_cd_access_method "beetle_psx_hw_cd_access_method"
|
#define option_cd_access_method "beetle_psx_hw_cd_access_method"
|
||||||
#define option_skip_bios "beetle_psx_hw_skipbios"
|
#define option_skip_bios "beetle_psx_hw_skipbios"
|
||||||
@ -79,6 +80,7 @@
|
|||||||
#define option_multitap2 "beetle_psx_enable_multitap_port2"
|
#define option_multitap2 "beetle_psx_enable_multitap_port2"
|
||||||
#define option_mouse_sensitivity "beetle_psx_mouse_sensitivity"
|
#define option_mouse_sensitivity "beetle_psx_mouse_sensitivity"
|
||||||
#define option_gun_cursor "beetle_psx_gun_cursor"
|
#define option_gun_cursor "beetle_psx_gun_cursor"
|
||||||
|
#define option_cpu_freq_scale "beetle_psx_cpu_freq_scale"
|
||||||
#define option_gte_overclock "beetle_psx_gte_overclock"
|
#define option_gte_overclock "beetle_psx_gte_overclock"
|
||||||
#define option_cd_access_method "beetle_psx_cd_access_method"
|
#define option_cd_access_method "beetle_psx_cd_access_method"
|
||||||
#define option_skip_bios "beetle_psx_skipbios"
|
#define option_skip_bios "beetle_psx_skipbios"
|
||||||
|
@ -146,6 +146,8 @@ int32 PS_CDC::CalcNextEvent(void)
|
|||||||
|
|
||||||
//fprintf(stderr, "%d %d %d %d --- %d\n", PSRCounter, PendingCommandCounter, CDCReadyReceiveCounter, DiscStartupDelay, next_event);
|
//fprintf(stderr, "%d %d %d %d --- %d\n", PSRCounter, PendingCommandCounter, CDCReadyReceiveCounter, DiscStartupDelay, next_event);
|
||||||
|
|
||||||
|
overclock_device_to_cpu(next_event);
|
||||||
|
|
||||||
return(next_event);
|
return(next_event);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1122,6 +1124,8 @@ int32_t PS_CDC::Update(const int32_t timestamp)
|
|||||||
{
|
{
|
||||||
int32 clocks = timestamp - lastts;
|
int32 clocks = timestamp - lastts;
|
||||||
|
|
||||||
|
overclock_cpu_to_device(clocks);
|
||||||
|
|
||||||
//doom_ts = timestamp;
|
//doom_ts = timestamp;
|
||||||
|
|
||||||
while(clocks > 0)
|
while(clocks > 0)
|
||||||
|
@ -511,6 +511,8 @@ static INLINE int32_t CalcNextEvent(int32_t next_event)
|
|||||||
if(DMACycleCounter < next_event)
|
if(DMACycleCounter < next_event)
|
||||||
next_event = DMACycleCounter;
|
next_event = DMACycleCounter;
|
||||||
|
|
||||||
|
overclock_device_to_cpu(next_event);
|
||||||
|
|
||||||
return(next_event);
|
return(next_event);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -519,6 +521,9 @@ int32_t DMA_Update(const int32_t timestamp)
|
|||||||
int32_t clocks, i;
|
int32_t clocks, i;
|
||||||
// uint32_t dc = (DMAControl >> (ch * 4)) & 0xF;
|
// uint32_t dc = (DMAControl >> (ch * 4)) & 0xF;
|
||||||
clocks = timestamp - lastts;
|
clocks = timestamp - lastts;
|
||||||
|
|
||||||
|
overclock_cpu_to_device(clocks);
|
||||||
|
|
||||||
lastts = timestamp;
|
lastts = timestamp;
|
||||||
|
|
||||||
GPU_Update(timestamp);
|
GPU_Update(timestamp);
|
||||||
|
@ -470,8 +470,12 @@ int32_t FrontIO::CalcNextEventTS(int32_t timestamp, int32_t next_event)
|
|||||||
if(dsr_pulse_delay[i] > 0 && next_event > dsr_pulse_delay[i])
|
if(dsr_pulse_delay[i] > 0 && next_event > dsr_pulse_delay[i])
|
||||||
next_event = dsr_pulse_delay[i];
|
next_event = dsr_pulse_delay[i];
|
||||||
|
|
||||||
|
overclock_device_to_cpu(next_event);
|
||||||
|
|
||||||
ret = timestamp + next_event;
|
ret = timestamp + next_event;
|
||||||
|
|
||||||
|
/* XXX Not sure if this is overclock-proof. This is probably only
|
||||||
|
useful for lightgun support however */
|
||||||
if(irq10_pulse_ts[0] < ret)
|
if(irq10_pulse_ts[0] < ret)
|
||||||
ret = irq10_pulse_ts[0];
|
ret = irq10_pulse_ts[0];
|
||||||
|
|
||||||
@ -700,13 +704,19 @@ int32_t FrontIO::Update(int32_t timestamp)
|
|||||||
|
|
||||||
clocks = timestamp - lastts;
|
clocks = timestamp - lastts;
|
||||||
|
|
||||||
|
overclock_cpu_to_device(clocks);
|
||||||
|
|
||||||
for(i = 0; i < 4; i++)
|
for(i = 0; i < 4; i++)
|
||||||
if(dsr_pulse_delay[i] > 0)
|
if(dsr_pulse_delay[i] > 0)
|
||||||
{
|
{
|
||||||
dsr_pulse_delay[i] -= clocks;
|
dsr_pulse_delay[i] -= clocks;
|
||||||
if(dsr_pulse_delay[i] <= 0)
|
if(dsr_pulse_delay[i] <= 0)
|
||||||
{
|
{
|
||||||
dsr_active_until_ts[i] = timestamp + 32 + dsr_pulse_delay[i];
|
int32_t off = 32 + dsr_pulse_delay[i];
|
||||||
|
|
||||||
|
overclock_device_to_cpu(off);
|
||||||
|
|
||||||
|
dsr_active_until_ts[i] = timestamp + off;
|
||||||
DoDSRIRQ();
|
DoDSRIRQ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -630,10 +630,7 @@ void GPU_Init(bool pal_clock_and_tv,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(GPU.HardwarePALType == false) // NTSC clock
|
GPU_RecalcClockRatio();
|
||||||
GPU.GPUClockRatio = 103896; // 65536 * 53693181.818 / (44100 * 768)
|
|
||||||
else // PAL clock
|
|
||||||
GPU.GPUClockRatio = 102948; // 65536 * 53203425 / (44100 * 768)
|
|
||||||
|
|
||||||
memset(GPU.RGB8SAT_Under, 0, sizeof(GPU.RGB8SAT_Under));
|
memset(GPU.RGB8SAT_Under, 0, sizeof(GPU.RGB8SAT_Under));
|
||||||
|
|
||||||
@ -651,6 +648,15 @@ void GPU_Init(bool pal_clock_and_tv,
|
|||||||
GPU.dither_upscale_shift = 0;
|
GPU.dither_upscale_shift = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GPU_RecalcClockRatio(void) {
|
||||||
|
if(GPU.HardwarePALType == false) // NTSC clock
|
||||||
|
GPU.GPUClockRatio = 103896; // 65536 * 53693181.818 / (44100 * 768)
|
||||||
|
else // PAL clock
|
||||||
|
GPU.GPUClockRatio = 102948; // 65536 * 53203425 / (44100 * 768)
|
||||||
|
|
||||||
|
overclock_cpu_to_device(GPU.GPUClockRatio);
|
||||||
|
}
|
||||||
|
|
||||||
void GPU_Destroy(void)
|
void GPU_Destroy(void)
|
||||||
{
|
{
|
||||||
delete [] GPU.vram;
|
delete [] GPU.vram;
|
||||||
|
@ -194,7 +194,7 @@ struct PS_GPU
|
|||||||
uint32 DotClockCounter;
|
uint32 DotClockCounter;
|
||||||
|
|
||||||
uint64 GPUClockCounter;
|
uint64 GPUClockCounter;
|
||||||
uint32 GPUClockRatio;
|
int32 GPUClockRatio;
|
||||||
int32 LineClockCounter;
|
int32 LineClockCounter;
|
||||||
int32 LinePhase;
|
int32 LinePhase;
|
||||||
|
|
||||||
@ -247,6 +247,8 @@ void GPU_Init(bool pal_clock_and_tv,
|
|||||||
|
|
||||||
void GPU_SoftReset(void);
|
void GPU_SoftReset(void);
|
||||||
|
|
||||||
|
void GPU_RecalcClockRatio(void);
|
||||||
|
|
||||||
void GPU_Destroy(void);
|
void GPU_Destroy(void);
|
||||||
|
|
||||||
void GPU_Rescale(uint8 ushift);
|
void GPU_Rescale(uint8 ushift);
|
||||||
|
@ -102,4 +102,31 @@ extern PS_CDC *CDC;
|
|||||||
extern PS_SPU *SPU;
|
extern PS_SPU *SPU;
|
||||||
extern MultiAccessSizeMem<2048 * 1024, uint32_t, false> MainRAM;
|
extern MultiAccessSizeMem<2048 * 1024, uint32_t, false> MainRAM;
|
||||||
|
|
||||||
|
#define OVERCLOCK_SHIFT 8
|
||||||
|
extern int32_t psx_overclock_factor;
|
||||||
|
|
||||||
|
static INLINE void overclock_device_to_cpu(int32_t &clock) {
|
||||||
|
if (psx_overclock_factor) {
|
||||||
|
int64_t n = clock;
|
||||||
|
|
||||||
|
n = (n * psx_overclock_factor) + (1 << (OVERCLOCK_SHIFT)) - 1;
|
||||||
|
|
||||||
|
n >>= OVERCLOCK_SHIFT;
|
||||||
|
|
||||||
|
clock = n;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static INLINE void overclock_cpu_to_device(int32_t &clock) {
|
||||||
|
if (psx_overclock_factor) {
|
||||||
|
int64_t n = clock;
|
||||||
|
|
||||||
|
n = (n << OVERCLOCK_SHIFT) + (psx_overclock_factor - 1);
|
||||||
|
|
||||||
|
n /= psx_overclock_factor;
|
||||||
|
|
||||||
|
clock = n;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -113,7 +113,7 @@ static int32_t lastts;
|
|||||||
|
|
||||||
static uint32_t CalcNextEvent(void)
|
static uint32_t CalcNextEvent(void)
|
||||||
{
|
{
|
||||||
uint32_t next_event = 1024; /**/
|
int32_t next_event = 1024; /**/
|
||||||
|
|
||||||
unsigned i;
|
unsigned i;
|
||||||
for(i = 0; i < 3; i++)
|
for(i = 0; i < 3; i++)
|
||||||
@ -154,6 +154,8 @@ static uint32_t CalcNextEvent(void)
|
|||||||
next_event = tmp_clocks;
|
next_event = tmp_clocks;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
overclock_device_to_cpu(next_event);
|
||||||
|
|
||||||
return(next_event);
|
return(next_event);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -343,6 +345,8 @@ MDFN_FASTCALL int32_t TIMER_Update(const int32_t timestamp)
|
|||||||
{
|
{
|
||||||
int32_t cpu_clocks = timestamp - lastts;
|
int32_t cpu_clocks = timestamp - lastts;
|
||||||
|
|
||||||
|
overclock_cpu_to_device(cpu_clocks);
|
||||||
|
|
||||||
int32_t i;
|
int32_t i;
|
||||||
for(i = 0; i < 3; i++)
|
for(i = 0; i < 3; i++)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user