summaryrefslogtreecommitdiff
path: root/Source/Core
diff options
context:
space:
mode:
authorShawn Hoffman <godisgovernment@gmail.com>2009-10-21 04:24:36 +0000
committerShawn Hoffman <godisgovernment@gmail.com>2009-10-21 04:24:36 +0000
commit68ea37f2fbd2a26e37fcb41f6114e3318f2d499e (patch)
tree5e21625438bc59d63360cc10508de2b52d58af2f /Source/Core
parent224009ee3e31c69dd8f1a169071214cf93587a0b (diff)
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
Diffstat (limited to 'Source/Core')
-rw-r--r--Source/Core/Core/Src/HW/SI_DeviceAMBaseboard.cpp3
-rw-r--r--Source/Core/Core/Src/HW/SystemTimers.cpp191
2 files changed, 104 insertions, 90 deletions
diff --git a/Source/Core/Core/Src/HW/SI_DeviceAMBaseboard.cpp b/Source/Core/Core/Src/HW/SI_DeviceAMBaseboard.cpp
index d5ee4f83ea..0c1d16121e 100644
--- a/Source/Core/Core/Src/HW/SI_DeviceAMBaseboard.cpp
+++ b/Source/Core/Core/Src/HW/SI_DeviceAMBaseboard.cpp
@@ -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)
{
diff --git a/Source/Core/Core/Src/HW/SystemTimers.cpp b/Source/Core/Core/Src/HW/SystemTimers.cpp
index a6fb5439b6..a325379a62 100644
--- a/Source/Core/Core/Src/HW/SystemTimers.cpp
+++ b/Source/Core/Core/Src/HW/SystemTimers.cpp
@@ -16,50 +16,47 @@
// http://code.google.com/p/dolphin-emu/
+// 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
+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 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 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()
+*/
+
-// 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.
-
- 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?
-
- 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()
-//////////////////////////*/
-
-
-
-// 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);
}