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:
Shawn Hoffman 2009-10-21 04:24:36 +00:00
parent 224009ee3e
commit 68ea37f2fb
2 changed files with 99 additions and 85 deletions

View File

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

View File

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