mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-21 05:09:34 -06:00
Reformat all the things. Have fun with merge conflicts.
This commit is contained in:
@ -4,7 +4,8 @@
|
||||
|
||||
// This file controls all system timers
|
||||
|
||||
/* (shuffle2) I don't know who wrote this, but take it with salt. For starters, "time" is contextual...
|
||||
/* (shuffle2) I don't know who wrote this, but take it with salt. For starters, "time" is
|
||||
contextual...
|
||||
"Time" is measured in frames, not time: These update frequencies are determined by the passage
|
||||
of frames. So if a game runs slow, on a slow computer for example, these updates will occur
|
||||
less frequently. This makes sense because almost all console games are controlled by frames
|
||||
@ -25,54 +26,53 @@ frame.
|
||||
|
||||
|
||||
IPC_HLE_PERIOD: For the Wiimote this is the call schedule:
|
||||
IPC_HLE_UpdateCallback() // In this file
|
||||
IPC_HLE_UpdateCallback() // In this file
|
||||
|
||||
// This function seems to call all devices' Update() function four times per frame
|
||||
WII_IPC_HLE_Interface::Update()
|
||||
// This function seems to call all devices' Update() function four times per frame
|
||||
WII_IPC_HLE_Interface::Update()
|
||||
|
||||
// If the AclFrameQue is empty this will call Wiimote_Update() and make it send
|
||||
the current input status to the game. I'm not sure if this occurs approximately
|
||||
once every frame or if the frequency is not exactly tied to rendered frames
|
||||
CWII_IPC_HLE_Device_usb_oh1_57e_305::Update()
|
||||
PluginWiimote::Wiimote_Update()
|
||||
// If the AclFrameQue is empty this will call Wiimote_Update() and make it send
|
||||
the current input status to the game. I'm not sure if this occurs approximately
|
||||
once every frame or if the frequency is not exactly tied to rendered frames
|
||||
CWII_IPC_HLE_Device_usb_oh1_57e_305::Update()
|
||||
PluginWiimote::Wiimote_Update()
|
||||
|
||||
// This is also a device updated by WII_IPC_HLE_Interface::Update() but it doesn't
|
||||
seem to ultimately call PluginWiimote::Wiimote_Update(). However it can be called
|
||||
by the /dev/usb/oh1 device if the AclFrameQue is empty.
|
||||
CWII_IPC_HLE_WiiMote::Update()
|
||||
// This is also a device updated by WII_IPC_HLE_Interface::Update() but it doesn't
|
||||
seem to ultimately call PluginWiimote::Wiimote_Update(). However it can be called
|
||||
by the /dev/usb/oh1 device if the AclFrameQue is empty.
|
||||
CWII_IPC_HLE_WiiMote::Update()
|
||||
*/
|
||||
|
||||
#include "Core/HW/SystemTimers.h"
|
||||
#include "Common/Atomic.h"
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "Common/Logging/Log.h"
|
||||
#include "Common/Thread.h"
|
||||
#include "Common/Timer.h"
|
||||
#include "Common/Logging/Log.h"
|
||||
#include "Core/ConfigManager.h"
|
||||
#include "Core/Core.h"
|
||||
#include "Core/CoreTiming.h"
|
||||
#include "Core/DSPEmulator.h"
|
||||
#include "Core/PatchEngine.h"
|
||||
#include "Core/HW/AudioInterface.h"
|
||||
#include "Core/HW/DSP.h"
|
||||
#include "Core/HW/EXI_DeviceIPL.h"
|
||||
#include "Core/HW/SystemTimers.h"
|
||||
#include "Core/HW/VideoInterface.h"
|
||||
#include "Core/IPC_HLE/WII_IPC_HLE.h"
|
||||
#include "Core/PatchEngine.h"
|
||||
#include "Core/PowerPC/PowerPC.h"
|
||||
#include "VideoCommon/Fifo.h"
|
||||
|
||||
namespace SystemTimers
|
||||
{
|
||||
|
||||
static int et_Dec;
|
||||
static int et_VI;
|
||||
static int et_AudioDMA;
|
||||
static int et_DSP;
|
||||
static int et_IPC_HLE;
|
||||
static int et_PatchEngine; // PatchEngine updates every 1/60th of a second by default
|
||||
static int et_PatchEngine; // PatchEngine updates every 1/60th of a second by default
|
||||
static int et_Throttle;
|
||||
|
||||
static u32 s_cpu_core_clock = 486000000u; // 486 mhz (its not 485, stop bugging me!)
|
||||
static u32 s_cpu_core_clock = 486000000u; // 486 mhz (its not 485, stop bugging me!)
|
||||
|
||||
// These two are badly educated guesses.
|
||||
// Feel free to experiment. Set them in Init below.
|
||||
@ -83,169 +83,172 @@ static int s_audio_dma_period;
|
||||
// we can just increase this number.
|
||||
static int s_ipc_hle_period;
|
||||
|
||||
|
||||
|
||||
u32 GetTicksPerSecond()
|
||||
{
|
||||
return s_cpu_core_clock;
|
||||
return s_cpu_core_clock;
|
||||
}
|
||||
|
||||
// DSP/CPU timeslicing.
|
||||
static void DSPCallback(u64 userdata, s64 cyclesLate)
|
||||
{
|
||||
//splits up the cycle budget in case lle is used
|
||||
//for hle, just gives all of the slice to hle
|
||||
DSP::UpdateDSPSlice(static_cast<int>(DSP::GetDSPEmulator()->DSP_UpdateRate() - cyclesLate));
|
||||
CoreTiming::ScheduleEvent(DSP::GetDSPEmulator()->DSP_UpdateRate() - cyclesLate, et_DSP);
|
||||
// splits up the cycle budget in case lle is used
|
||||
// for hle, just gives all of the slice to hle
|
||||
DSP::UpdateDSPSlice(static_cast<int>(DSP::GetDSPEmulator()->DSP_UpdateRate() - cyclesLate));
|
||||
CoreTiming::ScheduleEvent(DSP::GetDSPEmulator()->DSP_UpdateRate() - cyclesLate, et_DSP);
|
||||
}
|
||||
|
||||
static void AudioDMACallback(u64 userdata, s64 cyclesLate)
|
||||
{
|
||||
int period = s_cpu_core_clock / (AudioInterface::GetAIDSampleRate() * 4 / 32);
|
||||
DSP::UpdateAudioDMA(); // Push audio to speakers.
|
||||
CoreTiming::ScheduleEvent(period - cyclesLate, et_AudioDMA);
|
||||
int period = s_cpu_core_clock / (AudioInterface::GetAIDSampleRate() * 4 / 32);
|
||||
DSP::UpdateAudioDMA(); // Push audio to speakers.
|
||||
CoreTiming::ScheduleEvent(period - cyclesLate, et_AudioDMA);
|
||||
}
|
||||
|
||||
static void IPC_HLE_UpdateCallback(u64 userdata, s64 cyclesLate)
|
||||
{
|
||||
if (SConfig::GetInstance().bWii)
|
||||
{
|
||||
WII_IPC_HLE_Interface::UpdateDevices();
|
||||
CoreTiming::ScheduleEvent(s_ipc_hle_period - cyclesLate, et_IPC_HLE);
|
||||
}
|
||||
if (SConfig::GetInstance().bWii)
|
||||
{
|
||||
WII_IPC_HLE_Interface::UpdateDevices();
|
||||
CoreTiming::ScheduleEvent(s_ipc_hle_period - cyclesLate, et_IPC_HLE);
|
||||
}
|
||||
}
|
||||
|
||||
static void VICallback(u64 userdata, s64 cyclesLate)
|
||||
{
|
||||
VideoInterface::Update();
|
||||
CoreTiming::ScheduleEvent(VideoInterface::GetTicksPerHalfLine() - cyclesLate, et_VI);
|
||||
VideoInterface::Update();
|
||||
CoreTiming::ScheduleEvent(VideoInterface::GetTicksPerHalfLine() - cyclesLate, et_VI);
|
||||
}
|
||||
|
||||
static void DecrementerCallback(u64 userdata, s64 cyclesLate)
|
||||
{
|
||||
PowerPC::ppcState.spr[SPR_DEC] = 0xFFFFFFFF;
|
||||
PowerPC::ppcState.Exceptions |= EXCEPTION_DECREMENTER;
|
||||
PowerPC::ppcState.spr[SPR_DEC] = 0xFFFFFFFF;
|
||||
PowerPC::ppcState.Exceptions |= EXCEPTION_DECREMENTER;
|
||||
}
|
||||
|
||||
void DecrementerSet()
|
||||
{
|
||||
u32 decValue = PowerPC::ppcState.spr[SPR_DEC];
|
||||
u32 decValue = PowerPC::ppcState.spr[SPR_DEC];
|
||||
|
||||
CoreTiming::RemoveEvent(et_Dec);
|
||||
if ((decValue & 0x80000000) == 0)
|
||||
{
|
||||
CoreTiming::SetFakeDecStartTicks(CoreTiming::GetTicks());
|
||||
CoreTiming::SetFakeDecStartValue(decValue);
|
||||
CoreTiming::RemoveEvent(et_Dec);
|
||||
if ((decValue & 0x80000000) == 0)
|
||||
{
|
||||
CoreTiming::SetFakeDecStartTicks(CoreTiming::GetTicks());
|
||||
CoreTiming::SetFakeDecStartValue(decValue);
|
||||
|
||||
CoreTiming::ScheduleEvent(decValue * TIMER_RATIO, et_Dec);
|
||||
}
|
||||
CoreTiming::ScheduleEvent(decValue * TIMER_RATIO, et_Dec);
|
||||
}
|
||||
}
|
||||
|
||||
u32 GetFakeDecrementer()
|
||||
{
|
||||
return (CoreTiming::GetFakeDecStartValue() - (u32)((CoreTiming::GetTicks() - CoreTiming::GetFakeDecStartTicks()) / TIMER_RATIO));
|
||||
return (CoreTiming::GetFakeDecStartValue() -
|
||||
(u32)((CoreTiming::GetTicks() - CoreTiming::GetFakeDecStartTicks()) / TIMER_RATIO));
|
||||
}
|
||||
|
||||
void TimeBaseSet()
|
||||
{
|
||||
CoreTiming::SetFakeTBStartTicks(CoreTiming::GetTicks());
|
||||
CoreTiming::SetFakeTBStartValue(*((u64 *)&TL));
|
||||
CoreTiming::SetFakeTBStartTicks(CoreTiming::GetTicks());
|
||||
CoreTiming::SetFakeTBStartValue(*((u64*)&TL));
|
||||
}
|
||||
|
||||
u64 GetFakeTimeBase()
|
||||
{
|
||||
return CoreTiming::GetFakeTBStartValue() + ((CoreTiming::GetTicks() - CoreTiming::GetFakeTBStartTicks()) / TIMER_RATIO);
|
||||
return CoreTiming::GetFakeTBStartValue() +
|
||||
((CoreTiming::GetTicks() - CoreTiming::GetFakeTBStartTicks()) / TIMER_RATIO);
|
||||
}
|
||||
|
||||
static void PatchEngineCallback(u64 userdata, s64 cyclesLate)
|
||||
{
|
||||
// Patch mem and run the Action Replay
|
||||
PatchEngine::ApplyFramePatches();
|
||||
CoreTiming::ScheduleEvent(VideoInterface::GetTicksPerField() - cyclesLate, et_PatchEngine);
|
||||
// Patch mem and run the Action Replay
|
||||
PatchEngine::ApplyFramePatches();
|
||||
CoreTiming::ScheduleEvent(VideoInterface::GetTicksPerField() - cyclesLate, et_PatchEngine);
|
||||
}
|
||||
|
||||
static void ThrottleCallback(u64 last_time, s64 cyclesLate)
|
||||
{
|
||||
// Allow the GPU thread to sleep. Setting this flag here limits the wakeups to 1 kHz.
|
||||
Fifo::GpuMaySleep();
|
||||
// Allow the GPU thread to sleep. Setting this flag here limits the wakeups to 1 kHz.
|
||||
Fifo::GpuMaySleep();
|
||||
|
||||
u32 time = Common::Timer::GetTimeMs();
|
||||
u32 time = Common::Timer::GetTimeMs();
|
||||
|
||||
int diff = (u32)last_time - time;
|
||||
const SConfig& config = SConfig::GetInstance();
|
||||
bool frame_limiter = config.m_EmulationSpeed > 0.0f && !Core::GetIsThrottlerTempDisabled();
|
||||
u32 next_event = GetTicksPerSecond()/1000;
|
||||
if (frame_limiter)
|
||||
{
|
||||
if (config.m_EmulationSpeed != 1.0f)
|
||||
next_event = u32(next_event * config.m_EmulationSpeed);
|
||||
const int max_fallback = config.iTimingVariance;
|
||||
if (abs(diff) > max_fallback)
|
||||
{
|
||||
DEBUG_LOG(COMMON, "system too %s, %d ms skipped", diff<0 ? "slow" : "fast", abs(diff) - max_fallback);
|
||||
last_time = time - max_fallback;
|
||||
}
|
||||
else if (diff > 0)
|
||||
Common::SleepCurrentThread(diff);
|
||||
}
|
||||
CoreTiming::ScheduleEvent(next_event - cyclesLate, et_Throttle, last_time + 1);
|
||||
int diff = (u32)last_time - time;
|
||||
const SConfig& config = SConfig::GetInstance();
|
||||
bool frame_limiter = config.m_EmulationSpeed > 0.0f && !Core::GetIsThrottlerTempDisabled();
|
||||
u32 next_event = GetTicksPerSecond() / 1000;
|
||||
if (frame_limiter)
|
||||
{
|
||||
if (config.m_EmulationSpeed != 1.0f)
|
||||
next_event = u32(next_event * config.m_EmulationSpeed);
|
||||
const int max_fallback = config.iTimingVariance;
|
||||
if (abs(diff) > max_fallback)
|
||||
{
|
||||
DEBUG_LOG(COMMON, "system too %s, %d ms skipped", diff < 0 ? "slow" : "fast",
|
||||
abs(diff) - max_fallback);
|
||||
last_time = time - max_fallback;
|
||||
}
|
||||
else if (diff > 0)
|
||||
Common::SleepCurrentThread(diff);
|
||||
}
|
||||
CoreTiming::ScheduleEvent(next_event - cyclesLate, et_Throttle, last_time + 1);
|
||||
}
|
||||
|
||||
// split from Init to break a circular dependency between VideoInterface::Init and SystemTimers::Init
|
||||
// split from Init to break a circular dependency between VideoInterface::Init and
|
||||
// SystemTimers::Init
|
||||
void PreInit()
|
||||
{
|
||||
if (SConfig::GetInstance().bWii)
|
||||
s_cpu_core_clock = 729000000u;
|
||||
else
|
||||
s_cpu_core_clock = 486000000u;
|
||||
if (SConfig::GetInstance().bWii)
|
||||
s_cpu_core_clock = 729000000u;
|
||||
else
|
||||
s_cpu_core_clock = 486000000u;
|
||||
}
|
||||
|
||||
void Init()
|
||||
{
|
||||
if (SConfig::GetInstance().bWii)
|
||||
{
|
||||
// AyuanX: TO BE TWEAKED
|
||||
// Now the 1500 is a pure assumption
|
||||
// We need to figure out the real frequency though
|
||||
if (SConfig::GetInstance().bWii)
|
||||
{
|
||||
// AyuanX: TO BE TWEAKED
|
||||
// Now the 1500 is a pure assumption
|
||||
// We need to figure out the real frequency though
|
||||
|
||||
// FYI, WII_IPC_HLE_Interface::Update is also called in WII_IPCInterface::Write32
|
||||
const int freq = 1500;
|
||||
s_ipc_hle_period = GetTicksPerSecond() / freq;
|
||||
}
|
||||
// FYI, WII_IPC_HLE_Interface::Update is also called in WII_IPCInterface::Write32
|
||||
const int freq = 1500;
|
||||
s_ipc_hle_period = GetTicksPerSecond() / freq;
|
||||
}
|
||||
|
||||
// System internal sample rate is fixed at 32KHz * 4 (16bit Stereo) / 32 bytes DMA
|
||||
s_audio_dma_period = s_cpu_core_clock / (AudioInterface::GetAIDSampleRate() * 4 / 32);
|
||||
// System internal sample rate is fixed at 32KHz * 4 (16bit Stereo) / 32 bytes DMA
|
||||
s_audio_dma_period = s_cpu_core_clock / (AudioInterface::GetAIDSampleRate() * 4 / 32);
|
||||
|
||||
Common::Timer::IncreaseResolution();
|
||||
// store and convert localtime at boot to timebase ticks
|
||||
CoreTiming::SetFakeTBStartValue((u64)(s_cpu_core_clock / TIMER_RATIO) * (u64)CEXIIPL::GetGCTime());
|
||||
CoreTiming::SetFakeTBStartTicks(CoreTiming::GetTicks());
|
||||
Common::Timer::IncreaseResolution();
|
||||
// store and convert localtime at boot to timebase ticks
|
||||
CoreTiming::SetFakeTBStartValue((u64)(s_cpu_core_clock / TIMER_RATIO) *
|
||||
(u64)CEXIIPL::GetGCTime());
|
||||
CoreTiming::SetFakeTBStartTicks(CoreTiming::GetTicks());
|
||||
|
||||
CoreTiming::SetFakeDecStartValue(0xFFFFFFFF);
|
||||
CoreTiming::SetFakeDecStartTicks(CoreTiming::GetTicks());
|
||||
CoreTiming::SetFakeDecStartValue(0xFFFFFFFF);
|
||||
CoreTiming::SetFakeDecStartTicks(CoreTiming::GetTicks());
|
||||
|
||||
et_Dec = CoreTiming::RegisterEvent("DecCallback", DecrementerCallback);
|
||||
et_VI = CoreTiming::RegisterEvent("VICallback", VICallback);
|
||||
et_DSP = CoreTiming::RegisterEvent("DSPCallback", DSPCallback);
|
||||
et_AudioDMA = CoreTiming::RegisterEvent("AudioDMACallback", AudioDMACallback);
|
||||
et_IPC_HLE = CoreTiming::RegisterEvent("IPC_HLE_UpdateCallback", IPC_HLE_UpdateCallback);
|
||||
et_PatchEngine = CoreTiming::RegisterEvent("PatchEngine", PatchEngineCallback);
|
||||
et_Throttle = CoreTiming::RegisterEvent("Throttle", ThrottleCallback);
|
||||
et_Dec = CoreTiming::RegisterEvent("DecCallback", DecrementerCallback);
|
||||
et_VI = CoreTiming::RegisterEvent("VICallback", VICallback);
|
||||
et_DSP = CoreTiming::RegisterEvent("DSPCallback", DSPCallback);
|
||||
et_AudioDMA = CoreTiming::RegisterEvent("AudioDMACallback", AudioDMACallback);
|
||||
et_IPC_HLE = CoreTiming::RegisterEvent("IPC_HLE_UpdateCallback", IPC_HLE_UpdateCallback);
|
||||
et_PatchEngine = CoreTiming::RegisterEvent("PatchEngine", PatchEngineCallback);
|
||||
et_Throttle = CoreTiming::RegisterEvent("Throttle", ThrottleCallback);
|
||||
|
||||
CoreTiming::ScheduleEvent(VideoInterface::GetTicksPerHalfLine(), et_VI);
|
||||
CoreTiming::ScheduleEvent(0, et_DSP);
|
||||
CoreTiming::ScheduleEvent(s_audio_dma_period, et_AudioDMA);
|
||||
CoreTiming::ScheduleEvent(0, et_Throttle, Common::Timer::GetTimeMs());
|
||||
CoreTiming::ScheduleEvent(VideoInterface::GetTicksPerHalfLine(), et_VI);
|
||||
CoreTiming::ScheduleEvent(0, et_DSP);
|
||||
CoreTiming::ScheduleEvent(s_audio_dma_period, et_AudioDMA);
|
||||
CoreTiming::ScheduleEvent(0, et_Throttle, Common::Timer::GetTimeMs());
|
||||
|
||||
CoreTiming::ScheduleEvent(VideoInterface::GetTicksPerField(), et_PatchEngine);
|
||||
CoreTiming::ScheduleEvent(VideoInterface::GetTicksPerField(), et_PatchEngine);
|
||||
|
||||
if (SConfig::GetInstance().bWii)
|
||||
CoreTiming::ScheduleEvent(s_ipc_hle_period, et_IPC_HLE);
|
||||
if (SConfig::GetInstance().bWii)
|
||||
CoreTiming::ScheduleEvent(s_ipc_hle_period, et_IPC_HLE);
|
||||
}
|
||||
|
||||
void Shutdown()
|
||||
{
|
||||
Common::Timer::RestoreResolution();
|
||||
Common::Timer::RestoreResolution();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
Reference in New Issue
Block a user