make SystemTimers's DSP_PERIOD setting be dependent on which dsp plugin you are using. Too ugly to do it this way -> revert :)
Put PatchEngine into it's own event. Also, why is DSP_PERIOD 12000, and the value sent to DSP_Update() is 12000/6?? Shouldn't it be GetTicksPerSecond()/6 (=81MHz or 121MHz) ? git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@4445 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
parent
224009ee3e
commit
68ea37f2fb
|
@ -24,6 +24,7 @@
|
||||||
// where to put baseboard debug
|
// where to put baseboard debug
|
||||||
#define AMBASEBOARDDEBUG OSREPORT
|
#define AMBASEBOARDDEBUG OSREPORT
|
||||||
|
|
||||||
|
// "JAMMA Video Standard" I/O
|
||||||
class JVSIOMessage
|
class JVSIOMessage
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -84,6 +85,8 @@ public:
|
||||||
}
|
}
|
||||||
}; // end class JVSIOMessage
|
}; // end class JVSIOMessage
|
||||||
|
|
||||||
|
|
||||||
|
// AM-Baseboard device on SI
|
||||||
CSIDevice_AMBaseboard::CSIDevice_AMBaseboard(int _iDeviceNumber)
|
CSIDevice_AMBaseboard::CSIDevice_AMBaseboard(int _iDeviceNumber)
|
||||||
: ISIDevice(_iDeviceNumber)
|
: ISIDevice(_iDeviceNumber)
|
||||||
{
|
{
|
||||||
|
|
|
@ -16,50 +16,47 @@
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
|
|
||||||
|
// This file controls all system timers
|
||||||
|
|
||||||
// File description: This file controls all system timers
|
/* (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
|
||||||
"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
|
||||||
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
|
||||||
less frequently. This makes sense because almost all console games are controlled by frames
|
rather than time, so if a game can't keep up with the normal framerate all animations and
|
||||||
rather than time, so if a game can't keep up with the normal framerate all animations and
|
actions slows down and the game runs to slow. This is different from PC games that are are
|
||||||
actions slows down and the game runs to slow. This is different from PC games that are are
|
often controlled by time instead and may not have maximum framerates.
|
||||||
often controlled by time instead and may not have maximum framerates.
|
|
||||||
|
|
||||||
However, I'm not sure if the Bluetooth communication for the Wiimote is entirely frame
|
However, I'm not sure if the Bluetooth communication for the Wiimote is entirely frame
|
||||||
dependent, the timing problems with the ack command in Zelda - TP may be related to
|
dependent, the timing problems with the ack command in Zelda - TP may be related to
|
||||||
time rather than frames? For now the IPC_HLE_PERIOD is frame dependet, but bcause of
|
time rather than frames? For now the IPC_HLE_PERIOD is frame dependent, but because of
|
||||||
different conditions on the way to PluginWiimote::Wiimote_Update() the updates may actually
|
different conditions on the way to PluginWiimote::Wiimote_Update() the updates may actually
|
||||||
be time related after all, or not?
|
be time related after all, or not?
|
||||||
|
|
||||||
I'm not sure about this but the text below seems to assume that 60 fps means that the game
|
I'm not sure about this but the text below seems to assume that 60 fps means that the game
|
||||||
runs in the normal intended speed. In that case an update time of [GetTicksPerSecond() / 60]
|
runs in the normal intended speed. In that case an update time of [GetTicksPerSecond() / 60]
|
||||||
would mean one update per frame and [GetTicksPerSecond() / 250] would mean four updates per
|
would mean one update per frame and [GetTicksPerSecond() / 250] would mean four updates per
|
||||||
frame.
|
frame.
|
||||||
|
|
||||||
|
|
||||||
IPC_HLE_PERIOD: For the Wiimote this is the call scedule:
|
|
||||||
IPC_HLE_UpdateCallback() // In this file
|
|
||||||
|
|
||||||
// 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()
|
|
||||||
|
|
||||||
// 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()
|
|
||||||
//////////////////////////*/
|
|
||||||
|
|
||||||
|
|
||||||
|
IPC_HLE_PERIOD: For the Wiimote this is the call schedule:
|
||||||
|
IPC_HLE_UpdateCallback() // In this file
|
||||||
|
|
||||||
|
// 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()
|
||||||
|
|
||||||
|
// 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()
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
// Inlude
|
|
||||||
// -------------
|
|
||||||
#include "Common.h"
|
#include "Common.h"
|
||||||
#include "../PatchEngine.h"
|
#include "../PatchEngine.h"
|
||||||
#include "SystemTimers.h"
|
#include "SystemTimers.h"
|
||||||
|
@ -81,14 +78,25 @@
|
||||||
namespace SystemTimers
|
namespace SystemTimers
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
// Declarations and definitions
|
|
||||||
// -------------
|
|
||||||
u32 CPU_CORE_CLOCK = 486000000u; // 486 mhz (its not 485, stop bugging me!)
|
u32 CPU_CORE_CLOCK = 486000000u; // 486 mhz (its not 485, stop bugging me!)
|
||||||
|
|
||||||
s64 fakeDec;
|
s64 fakeDec;
|
||||||
u64 startTimeBaseTicks;
|
u64 startTimeBaseTicks;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Gamecube MHz
|
||||||
|
flipper <-> ARAM bus: 81 (DSP)
|
||||||
|
gekko <-> flipper bus: 162
|
||||||
|
flipper <-> 1T-SRAM bus: 324
|
||||||
|
gekko: 486
|
||||||
|
|
||||||
|
These contain some guesses:
|
||||||
|
Wii MHz
|
||||||
|
hollywood <-> GDDR3 RAM bus: ??? no idea really
|
||||||
|
broadway <-> hollywood bus: 243
|
||||||
|
hollywood <-> 1T-SRAM bus: 486
|
||||||
|
broadway: 729
|
||||||
|
*/
|
||||||
// Ratio of TB and Decrementer to clock cycles.
|
// Ratio of TB and Decrementer to clock cycles.
|
||||||
// TB clk is 1/4 of BUS clk. And it seems BUS clk is really 1/3 of CPU clk.
|
// TB clk is 1/4 of BUS clk. And it seems BUS clk is really 1/3 of CPU clk.
|
||||||
// So, ratio is 1 / (1/4 * 1/3 = 1/12) = 12.
|
// So, ratio is 1 / (1/4 * 1/3 = 1/12) = 12.
|
||||||
|
@ -106,15 +114,12 @@ int et_AI;
|
||||||
int et_AudioFifo;
|
int et_AudioFifo;
|
||||||
int et_DSP;
|
int et_DSP;
|
||||||
int et_IPC_HLE;
|
int et_IPC_HLE;
|
||||||
int et_FakeGPWD; // for DC watchdog hack
|
int et_FakeGPWD; // DC watchdog hack
|
||||||
|
int et_PatchEngine; // PatchEngine updates every 1/60th of a second by default
|
||||||
|
|
||||||
// These are badly educated guesses
|
// These are badly educated guesses
|
||||||
// Feel free to experiment. Set these in Init below.
|
// Feel free to experiment. Set these in Init below.
|
||||||
int
|
int
|
||||||
// TODO: The SI in fact actually has a register that determines the polling frequency.
|
|
||||||
// We should obey that instead of arbitrarly checking at 60fps.
|
|
||||||
SI_PERIOD, // once a frame is good for controllers
|
|
||||||
|
|
||||||
// This one should simply be determined by the increasing counter in AI.
|
// This one should simply be determined by the increasing counter in AI.
|
||||||
AI_PERIOD,
|
AI_PERIOD,
|
||||||
|
|
||||||
|
@ -123,7 +128,7 @@ int
|
||||||
|
|
||||||
// This is completely arbitrary. If we find that we need lower latency, we can just
|
// This is completely arbitrary. If we find that we need lower latency, we can just
|
||||||
// increase this number.
|
// increase this number.
|
||||||
IPC_HLE_PERIOD,
|
IPC_HLE_PERIOD,
|
||||||
|
|
||||||
// For DC watchdog hack
|
// For DC watchdog hack
|
||||||
// Once every 4 frame-period seems to be enough (arbitrary taking 60fps as the ref).
|
// Once every 4 frame-period seems to be enough (arbitrary taking 60fps as the ref).
|
||||||
|
@ -155,7 +160,7 @@ void AICallback(u64 userdata, int cyclesLate)
|
||||||
void DSPCallback(u64 userdata, int cyclesLate)
|
void DSPCallback(u64 userdata, int cyclesLate)
|
||||||
{
|
{
|
||||||
// ~1/6th as many cycles as the period PPC-side.
|
// ~1/6th as many cycles as the period PPC-side.
|
||||||
CPluginManager::GetInstance().GetDSP()->DSP_Update(DSP_PERIOD / 6);
|
CPluginManager::GetInstance().GetDSP()->DSP_Update(DSP_PERIOD / 6);
|
||||||
CoreTiming::ScheduleEvent(DSP_PERIOD - cyclesLate, et_DSP);
|
CoreTiming::ScheduleEvent(DSP_PERIOD - cyclesLate, et_DSP);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -169,8 +174,8 @@ void AudioFifoCallback(u64 userdata, int cyclesLate)
|
||||||
|
|
||||||
void IPC_HLE_UpdateCallback(u64 userdata, int cyclesLate)
|
void IPC_HLE_UpdateCallback(u64 userdata, int cyclesLate)
|
||||||
{
|
{
|
||||||
WII_IPC_HLE_Interface::UpdateDevices();
|
WII_IPC_HLE_Interface::UpdateDevices();
|
||||||
CoreTiming::ScheduleEvent(IPC_HLE_PERIOD-cyclesLate, et_IPC_HLE);
|
CoreTiming::ScheduleEvent(IPC_HLE_PERIOD-cyclesLate, et_IPC_HLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VICallback(u64 userdata, int cyclesLate)
|
void VICallback(u64 userdata, int cyclesLate)
|
||||||
|
@ -184,18 +189,15 @@ void VICallback(u64 userdata, int cyclesLate)
|
||||||
|
|
||||||
void SICallback(u64 userdata, int cyclesLate)
|
void SICallback(u64 userdata, int cyclesLate)
|
||||||
{
|
{
|
||||||
|
// TODO make this obey the SIPoll register
|
||||||
SerialInterface::UpdateDevices();
|
SerialInterface::UpdateDevices();
|
||||||
CoreTiming::ScheduleEvent(SI_PERIOD-cyclesLate, et_SI);
|
CoreTiming::ScheduleEvent((GetTicksPerSecond() / 60) - cyclesLate, et_SI);
|
||||||
|
|
||||||
// This is once per frame - good candidate for patching stuff
|
|
||||||
// Patch mem and run the Action Replay
|
|
||||||
PatchEngine::ApplyFramePatches();
|
|
||||||
PatchEngine::ApplyARPatches();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DecrementerCallback(u64 userdata, int cyclesLate)
|
void DecrementerCallback(u64 userdata, int cyclesLate)
|
||||||
{
|
{
|
||||||
//Why is fakeDec too big here?
|
// Why is fakeDec too big here?
|
||||||
|
// A: Because it's 64bit (0xffffffffffffffff)...?
|
||||||
fakeDec = -1;
|
fakeDec = -1;
|
||||||
PowerPC::ppcState.spr[SPR_DEC] = 0xFFFFFFFF;
|
PowerPC::ppcState.spr[SPR_DEC] = 0xFFFFFFFF;
|
||||||
PowerPC::ppcState.Exceptions |= EXCEPTION_DECREMENTER;
|
PowerPC::ppcState.Exceptions |= EXCEPTION_DECREMENTER;
|
||||||
|
@ -211,13 +213,13 @@ void DecrementerSet()
|
||||||
|
|
||||||
void AdvanceCallback(int cyclesExecuted)
|
void AdvanceCallback(int cyclesExecuted)
|
||||||
{
|
{
|
||||||
if (PowerPC::GetState() != PowerPC::CPU_RUNNING)
|
if (PowerPC::GetState() != PowerPC::CPU_RUNNING)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
fakeDec -= cyclesExecuted;
|
fakeDec -= cyclesExecuted;
|
||||||
u64 timebase_ticks = CoreTiming::GetTicks() / TIMER_RATIO;
|
u64 timebase_ticks = CoreTiming::GetTicks() / TIMER_RATIO;
|
||||||
*(u64*)&TL = timebase_ticks + startTimeBaseTicks; //works since we are little endian and TL comes first :)
|
*(u64*)&TL = timebase_ticks + startTimeBaseTicks; //works since we are little endian and TL comes first :)
|
||||||
if (fakeDec >= 0)
|
if (fakeDec >= 0)
|
||||||
PowerPC::ppcState.spr[SPR_DEC] = (u32)fakeDec / TIMER_RATIO;
|
PowerPC::ppcState.spr[SPR_DEC] = (u32)fakeDec / TIMER_RATIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -225,43 +227,49 @@ void AdvanceCallback(int cyclesExecuted)
|
||||||
// For DC watchdog hack
|
// For DC watchdog hack
|
||||||
void FakeGPWatchdogCallback(u64 userdata, int cyclesLate)
|
void FakeGPWatchdogCallback(u64 userdata, int cyclesLate)
|
||||||
{
|
{
|
||||||
CPluginManager::GetInstance().GetVideo()->Video_WaitForFrameFinish(); // lock CPUThread until frame finish
|
CPluginManager::GetInstance().GetVideo()->Video_WaitForFrameFinish(); // lock CPUThread until frame finish
|
||||||
CoreTiming::ScheduleEvent(FAKE_GP_WATCHDOG_PERIOD-cyclesLate, et_FakeGPWD);
|
CoreTiming::ScheduleEvent(FAKE_GP_WATCHDOG_PERIOD-cyclesLate, et_FakeGPWD);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PatchEngineCallback(u64 userdata, int cyclesLate)
|
||||||
|
{
|
||||||
|
// Patch mem and run the Action Replay
|
||||||
|
PatchEngine::ApplyFramePatches();
|
||||||
|
PatchEngine::ApplyARPatches();
|
||||||
|
}
|
||||||
|
|
||||||
void Init()
|
void Init()
|
||||||
{
|
{
|
||||||
FAKE_GP_WATCHDOG_PERIOD = GetTicksPerSecond() / 60;
|
PLUGIN_INFO DSPType;
|
||||||
|
(*CPluginManager::GetInstance().GetDSP()).GetInfo(DSPType);
|
||||||
|
std::string DSPName(DSPType.Name);
|
||||||
|
bool UsingDSPLLE = (DSPName.find("LLE") != std::string::npos) || (DSPName.find("lle") != std::string::npos);
|
||||||
|
|
||||||
if (Core::GetStartupParameter().bWii)
|
if (Core::GetStartupParameter().bWii)
|
||||||
{
|
{
|
||||||
CPU_CORE_CLOCK = 729000000u;
|
CPU_CORE_CLOCK = 729000000u;
|
||||||
SI_PERIOD = GetTicksPerSecond() / 60; // once a frame is good for controllers
|
|
||||||
|
|
||||||
//if (!Core::GetStartupParameter().bDSPThread) {
|
if (!UsingDSPLLE)
|
||||||
// DSP_PERIOD = 12000; // TO BE TWEAKED
|
|
||||||
//} else {
|
|
||||||
DSP_PERIOD = (int)(GetTicksPerSecond() * 0.003f);
|
DSP_PERIOD = (int)(GetTicksPerSecond() * 0.003f);
|
||||||
//}
|
|
||||||
|
|
||||||
// This is the biggest question mark.
|
IPC_HLE_PERIOD = (int)(GetTicksPerSecond() * 0.003f);
|
||||||
AI_PERIOD = GetTicksPerSecond() / 80;
|
|
||||||
|
|
||||||
IPC_HLE_PERIOD = (int)(GetTicksPerSecond() * 0.003f);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
CPU_CORE_CLOCK = 486000000;
|
CPU_CORE_CLOCK = 486000000u;
|
||||||
SI_PERIOD = GetTicksPerSecond() / 60; // once a frame is good for controllers
|
|
||||||
|
|
||||||
//if (!Core::GetStartupParameter().bDSPThread) {
|
|
||||||
// DSP_PERIOD = 12000; // TO BE TWEAKED
|
|
||||||
//} else {
|
|
||||||
DSP_PERIOD = (int)(GetTicksPerSecond() * 0.005f);
|
|
||||||
//}
|
|
||||||
|
|
||||||
// This is the biggest question mark.
|
if (!UsingDSPLLE)
|
||||||
AI_PERIOD = GetTicksPerSecond() / 80;
|
DSP_PERIOD = (int)(GetTicksPerSecond() * 0.005f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (UsingDSPLLE)
|
||||||
|
DSP_PERIOD = 12000; // TO BE TWEAKED
|
||||||
|
|
||||||
|
FAKE_GP_WATCHDOG_PERIOD = GetTicksPerSecond() / 60;
|
||||||
|
|
||||||
|
// This is the biggest question mark.
|
||||||
|
AI_PERIOD = GetTicksPerSecond() / 80;
|
||||||
|
|
||||||
Common::Timer::IncreaseResolution();
|
Common::Timer::IncreaseResolution();
|
||||||
// store and convert localtime at boot to timebase ticks
|
// store and convert localtime at boot to timebase ticks
|
||||||
startTimeBaseTicks = (u64)(CPU_CORE_CLOCK / TIMER_RATIO) * (u64)CEXIIPL::GetGCTime();
|
startTimeBaseTicks = (u64)(CPU_CORE_CLOCK / TIMER_RATIO) * (u64)CEXIIPL::GetGCTime();
|
||||||
|
@ -275,11 +283,12 @@ void Init()
|
||||||
et_IPC_HLE = CoreTiming::RegisterEvent("IPC_HLE_UpdateCallback", IPC_HLE_UpdateCallback);
|
et_IPC_HLE = CoreTiming::RegisterEvent("IPC_HLE_UpdateCallback", IPC_HLE_UpdateCallback);
|
||||||
// Always register this. Increases chances of DC/SC save state compatibility.
|
// Always register this. Increases chances of DC/SC save state compatibility.
|
||||||
et_FakeGPWD = CoreTiming::RegisterEvent("FakeGPWatchdogCallback", FakeGPWatchdogCallback);
|
et_FakeGPWD = CoreTiming::RegisterEvent("FakeGPWatchdogCallback", FakeGPWatchdogCallback);
|
||||||
|
et_PatchEngine = CoreTiming::RegisterEvent("PatchEngine", PatchEngineCallback);
|
||||||
|
|
||||||
CoreTiming::ScheduleEvent(AI_PERIOD, et_AI);
|
CoreTiming::ScheduleEvent(AI_PERIOD, et_AI);
|
||||||
CoreTiming::ScheduleEvent(VideoInterface::getTicksPerLine(), et_VI);
|
CoreTiming::ScheduleEvent(VideoInterface::getTicksPerLine(), et_VI);
|
||||||
CoreTiming::ScheduleEvent(DSP_PERIOD, et_DSP);
|
CoreTiming::ScheduleEvent(DSP_PERIOD, et_DSP);
|
||||||
CoreTiming::ScheduleEvent(SI_PERIOD, et_SI);
|
CoreTiming::ScheduleEvent(GetTicksPerSecond() / 60, et_SI);
|
||||||
CoreTiming::ScheduleEvent(CPU_CORE_CLOCK / (32000 * 4 / 32), et_AudioFifo);
|
CoreTiming::ScheduleEvent(CPU_CORE_CLOCK / (32000 * 4 / 32), et_AudioFifo);
|
||||||
|
|
||||||
// For DC watchdog hack
|
// For DC watchdog hack
|
||||||
|
@ -288,9 +297,11 @@ void Init()
|
||||||
CoreTiming::ScheduleEvent(FAKE_GP_WATCHDOG_PERIOD, et_FakeGPWD);
|
CoreTiming::ScheduleEvent(FAKE_GP_WATCHDOG_PERIOD, et_FakeGPWD);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Core::GetStartupParameter().bWii)
|
CoreTiming::ScheduleEvent(GetTicksPerSecond() / 60, et_PatchEngine);
|
||||||
CoreTiming::ScheduleEvent(IPC_HLE_PERIOD, et_IPC_HLE);
|
|
||||||
|
if (Core::GetStartupParameter().bWii)
|
||||||
|
CoreTiming::ScheduleEvent(IPC_HLE_PERIOD, et_IPC_HLE);
|
||||||
|
|
||||||
CoreTiming::RegisterAdvanceCallback(&AdvanceCallback);
|
CoreTiming::RegisterAdvanceCallback(&AdvanceCallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue