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
|
||||
#define AMBASEBOARDDEBUG OSREPORT
|
||||
|
||||
// "JAMMA Video Standard" I/O
|
||||
class JVSIOMessage
|
||||
{
|
||||
public:
|
||||
|
@ -84,6 +85,8 @@ public:
|
|||
}
|
||||
}; // end class JVSIOMessage
|
||||
|
||||
|
||||
// AM-Baseboard device on SI
|
||||
CSIDevice_AMBaseboard::CSIDevice_AMBaseboard(int _iDeviceNumber)
|
||||
: ISIDevice(_iDeviceNumber)
|
||||
{
|
||||
|
|
|
@ -16,50 +16,47 @@
|
|||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
|
||||
// This file controls all system timers
|
||||
|
||||
// File description: This file controls all system timers
|
||||
/* -------------
|
||||
"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
|
||||
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
|
||||
often controlled by time instead and may not have maximum framerates.
|
||||
/* (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
|
||||
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
|
||||
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
|
||||
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
|
||||
different conditions on the way to PluginWiimote::Wiimote_Update() the updates may actually
|
||||
be time related after all, or not?
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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()
|
||||
//////////////////////////*/
|
||||
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]
|
||||
would mean one update per frame and [GetTicksPerSecond() / 250] would mean four updates per
|
||||
frame.
|
||||
|
||||
|
||||
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 "../PatchEngine.h"
|
||||
#include "SystemTimers.h"
|
||||
|
@ -81,14 +78,25 @@
|
|||
namespace SystemTimers
|
||||
{
|
||||
|
||||
|
||||
// Declarations and definitions
|
||||
// -------------
|
||||
u32 CPU_CORE_CLOCK = 486000000u; // 486 mhz (its not 485, stop bugging me!)
|
||||
|
||||
s64 fakeDec;
|
||||
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.
|
||||
// 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.
|
||||
|
@ -106,15 +114,12 @@ int et_AI;
|
|||
int et_AudioFifo;
|
||||
int et_DSP;
|
||||
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
|
||||
// Feel free to experiment. Set these in Init below.
|
||||
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.
|
||||
AI_PERIOD,
|
||||
|
||||
|
@ -123,7 +128,7 @@ int
|
|||
|
||||
// This is completely arbitrary. If we find that we need lower latency, we can just
|
||||
// increase this number.
|
||||
IPC_HLE_PERIOD,
|
||||
IPC_HLE_PERIOD,
|
||||
|
||||
// For DC watchdog hack
|
||||
// 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)
|
||||
{
|
||||
// ~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);
|
||||
}
|
||||
|
||||
|
@ -169,8 +174,8 @@ void AudioFifoCallback(u64 userdata, int cyclesLate)
|
|||
|
||||
void IPC_HLE_UpdateCallback(u64 userdata, int cyclesLate)
|
||||
{
|
||||
WII_IPC_HLE_Interface::UpdateDevices();
|
||||
CoreTiming::ScheduleEvent(IPC_HLE_PERIOD-cyclesLate, et_IPC_HLE);
|
||||
WII_IPC_HLE_Interface::UpdateDevices();
|
||||
CoreTiming::ScheduleEvent(IPC_HLE_PERIOD-cyclesLate, et_IPC_HLE);
|
||||
}
|
||||
|
||||
void VICallback(u64 userdata, int cyclesLate)
|
||||
|
@ -184,18 +189,15 @@ void VICallback(u64 userdata, int cyclesLate)
|
|||
|
||||
void SICallback(u64 userdata, int cyclesLate)
|
||||
{
|
||||
// TODO make this obey the SIPoll register
|
||||
SerialInterface::UpdateDevices();
|
||||
CoreTiming::ScheduleEvent(SI_PERIOD-cyclesLate, et_SI);
|
||||
|
||||
// This is once per frame - good candidate for patching stuff
|
||||
// Patch mem and run the Action Replay
|
||||
PatchEngine::ApplyFramePatches();
|
||||
PatchEngine::ApplyARPatches();
|
||||
CoreTiming::ScheduleEvent((GetTicksPerSecond() / 60) - cyclesLate, et_SI);
|
||||
}
|
||||
|
||||
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;
|
||||
PowerPC::ppcState.spr[SPR_DEC] = 0xFFFFFFFF;
|
||||
PowerPC::ppcState.Exceptions |= EXCEPTION_DECREMENTER;
|
||||
|
@ -211,13 +213,13 @@ void DecrementerSet()
|
|||
|
||||
void AdvanceCallback(int cyclesExecuted)
|
||||
{
|
||||
if (PowerPC::GetState() != PowerPC::CPU_RUNNING)
|
||||
return;
|
||||
if (PowerPC::GetState() != PowerPC::CPU_RUNNING)
|
||||
return;
|
||||
|
||||
fakeDec -= cyclesExecuted;
|
||||
u64 timebase_ticks = CoreTiming::GetTicks() / TIMER_RATIO;
|
||||
*(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;
|
||||
}
|
||||
|
||||
|
@ -225,43 +227,49 @@ void AdvanceCallback(int cyclesExecuted)
|
|||
// For DC watchdog hack
|
||||
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);
|
||||
}
|
||||
|
||||
void PatchEngineCallback(u64 userdata, int cyclesLate)
|
||||
{
|
||||
// Patch mem and run the Action Replay
|
||||
PatchEngine::ApplyFramePatches();
|
||||
PatchEngine::ApplyARPatches();
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
CPU_CORE_CLOCK = 729000000u;
|
||||
SI_PERIOD = GetTicksPerSecond() / 60; // once a frame is good for controllers
|
||||
|
||||
//if (!Core::GetStartupParameter().bDSPThread) {
|
||||
// DSP_PERIOD = 12000; // TO BE TWEAKED
|
||||
//} else {
|
||||
if (!UsingDSPLLE)
|
||||
DSP_PERIOD = (int)(GetTicksPerSecond() * 0.003f);
|
||||
//}
|
||||
|
||||
// This is the biggest question mark.
|
||||
AI_PERIOD = GetTicksPerSecond() / 80;
|
||||
|
||||
IPC_HLE_PERIOD = (int)(GetTicksPerSecond() * 0.003f);
|
||||
IPC_HLE_PERIOD = (int)(GetTicksPerSecond() * 0.003f);
|
||||
}
|
||||
else
|
||||
{
|
||||
CPU_CORE_CLOCK = 486000000;
|
||||
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);
|
||||
//}
|
||||
CPU_CORE_CLOCK = 486000000u;
|
||||
|
||||
// This is the biggest question mark.
|
||||
AI_PERIOD = GetTicksPerSecond() / 80;
|
||||
if (!UsingDSPLLE)
|
||||
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();
|
||||
// store and convert localtime at boot to timebase ticks
|
||||
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);
|
||||
// Always register this. Increases chances of DC/SC save state compatibility.
|
||||
et_FakeGPWD = CoreTiming::RegisterEvent("FakeGPWatchdogCallback", FakeGPWatchdogCallback);
|
||||
et_PatchEngine = CoreTiming::RegisterEvent("PatchEngine", PatchEngineCallback);
|
||||
|
||||
CoreTiming::ScheduleEvent(AI_PERIOD, et_AI);
|
||||
CoreTiming::ScheduleEvent(VideoInterface::getTicksPerLine(), et_VI);
|
||||
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);
|
||||
|
||||
// For DC watchdog hack
|
||||
|
@ -288,9 +297,11 @@ void Init()
|
|||
CoreTiming::ScheduleEvent(FAKE_GP_WATCHDOG_PERIOD, et_FakeGPWD);
|
||||
}
|
||||
|
||||
if (Core::GetStartupParameter().bWii)
|
||||
CoreTiming::ScheduleEvent(IPC_HLE_PERIOD, et_IPC_HLE);
|
||||
|
||||
CoreTiming::ScheduleEvent(GetTicksPerSecond() / 60, et_PatchEngine);
|
||||
|
||||
if (Core::GetStartupParameter().bWii)
|
||||
CoreTiming::ScheduleEvent(IPC_HLE_PERIOD, et_IPC_HLE);
|
||||
|
||||
CoreTiming::RegisterAdvanceCallback(&AdvanceCallback);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue