Implement true CPU frequency scaling/overclocking

This commit is contained in:
Lionel Flandrin 2018-02-08 12:14:56 +01:00
parent ac3fec5c36
commit 8e7ae9c61f
9 changed files with 91 additions and 8 deletions

View File

@ -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" },

View File

@ -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"

View File

@ -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)

View File

@ -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);

View File

@ -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();
} }
} }

View File

@ -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;

View File

@ -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);

View File

@ -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

View File

@ -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);
} }
@ -342,7 +344,9 @@ void TIMER_ClockHRetrace(void)
MDFN_FASTCALL int32_t TIMER_Update(const int32_t timestamp) 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++)
{ {