From 68ea37f2fbd2a26e37fcb41f6114e3318f2d499e Mon Sep 17 00:00:00 2001 From: Shawn Hoffman Date: Wed, 21 Oct 2009 04:24:36 +0000 Subject: [PATCH] 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 --- .../Core/Core/Src/HW/SI_DeviceAMBaseboard.cpp | 3 + Source/Core/Core/Src/HW/SystemTimers.cpp | 181 ++++++++++-------- 2 files changed, 99 insertions(+), 85 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 -// 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); }