From 81d671dc1ab995349efe92d8c4de3aab4eccc8d2 Mon Sep 17 00:00:00 2001 From: LinesPrower Date: Wed, 24 Jun 2009 09:46:09 +0000 Subject: [PATCH] Aligned VideoInterface events with scanline updates. git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@3541 8ced0084-cf51-0410-be5f-012b33b47a6e --- Source/Core/Core/Src/HW/SystemTimers.cpp | 11 +- Source/Core/Core/Src/HW/VideoInterface.cpp | 124 ++++++++++----------- Source/Core/Core/Src/HW/VideoInterface.h | 2 + 3 files changed, 63 insertions(+), 74 deletions(-) diff --git a/Source/Core/Core/Src/HW/SystemTimers.cpp b/Source/Core/Core/Src/HW/SystemTimers.cpp index 8b5ec04c73..cdd1216530 100644 --- a/Source/Core/Core/Src/HW/SystemTimers.cpp +++ b/Source/Core/Core/Src/HW/SystemTimers.cpp @@ -112,11 +112,6 @@ int et_FakeGPWD; // for DC watchdog hack // These are badly educated guesses // Feel free to experiment. Set these in Init below. int - // update VI often to let it go through its scanlines with decent accuracy - // Maybe should actually align this with the scanline update? Current method in - // VideoInterface::Update is stupid! - VI_PERIOD, - // 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 @@ -185,7 +180,7 @@ void VICallback(u64 userdata, int cyclesLate) WII_IPC_HLE_Interface::Update(); VideoInterface::Update(); - CoreTiming::ScheduleEvent(VI_PERIOD-cyclesLate, et_VI); + CoreTiming::ScheduleEvent(VideoInterface::getTicksPerLine() - cyclesLate, et_VI); } void SICallback(u64 userdata, int cyclesLate) @@ -241,7 +236,6 @@ void Init() if (Core::GetStartupParameter().bWii) { CPU_CORE_CLOCK = 729000000u; - VI_PERIOD = GetTicksPerSecond() / (60*120); SI_PERIOD = GetTicksPerSecond() / 60; // once a frame is good for controllers if (!Core::GetStartupParameter().bDSPThread) { @@ -258,7 +252,6 @@ void Init() else { CPU_CORE_CLOCK = 486000000; - VI_PERIOD = GetTicksPerSecond() / (60*120); SI_PERIOD = GetTicksPerSecond() / 60; // once a frame is good for controllers if (!Core::GetStartupParameter().bDSPThread) { @@ -285,7 +278,7 @@ void Init() et_FakeGPWD = CoreTiming::RegisterEvent("FakeGPWatchdogCallback", FakeGPWatchdogCallback); CoreTiming::ScheduleEvent(AI_PERIOD, et_AI); - CoreTiming::ScheduleEvent(VI_PERIOD, et_VI); + CoreTiming::ScheduleEvent(VideoInterface::getTicksPerLine(), et_VI); CoreTiming::ScheduleEvent(DSP_PERIOD, et_DSP); CoreTiming::ScheduleEvent(SI_PERIOD, et_SI); CoreTiming::ScheduleEvent(CPU_CORE_CLOCK / (32000 * 4 / 32), et_AudioFifo); diff --git a/Source/Core/Core/Src/HW/VideoInterface.cpp b/Source/Core/Core/Src/HW/VideoInterface.cpp index bb35437666..670dbb5a30 100644 --- a/Source/Core/Core/Src/HW/VideoInterface.cpp +++ b/Source/Core/Core/Src/HW/VideoInterface.cpp @@ -336,7 +336,6 @@ static UVIBorderBlankRegister m_BorderHBlank; static u32 TicksPerFrame = 0; static u32 LineCount = 0; static u32 LinesPerField = 0; -static u64 LastTime = 0; static u32 NextXFBRender = 0; int TargetRefreshRate = 0; s64 SyncTicksProgress = 0; @@ -372,7 +371,6 @@ void DoState(PointerWrap &p) p.Do(TicksPerFrame); p.Do(LineCount); p.Do(LinesPerField); - p.Do(LastTime); p.Do(NextXFBRender); } @@ -380,7 +378,6 @@ void PreInit(bool _bNTSC) { TicksPerFrame = 0; LineCount = 0; - LastTime = 0; m_VerticalTimingRegister.EQU = 6; @@ -1036,7 +1033,11 @@ void UpdateTiming() } } - +int getTicksPerLine() { + if (LineCount == 0) + return 100000; + return TicksPerFrame / LineCount; +} // Purpose 1: Send VI interrupt for every screen refresh @@ -1067,77 +1068,70 @@ void Update() SyncTicksProgress = 0; } - - // Go through all lines - while ((CoreTiming::GetTicks() - LastTime) > (TicksPerFrame / LineCount)) + m_VBeamPos++; + if (m_VBeamPos > LineCount) { - LastTime += (TicksPerFrame / LineCount); + m_VBeamPos = 1; + } - m_VBeamPos++; - if (m_VBeamPos > LineCount) - { - m_VBeamPos = 1; - } + if (m_VBeamPos == NextXFBRender) + { + u8* xfbPtr = 0; + int yOffset = 0; - if (m_VBeamPos == NextXFBRender) + // (mb2) hack: We request XFB updates from CPUthread (here) only when homebrews use directly XFB without FIFO and CP + if (!Core::GetStartupParameter().bUseDualCore || CommandProcessor::IsCommandProcessorNotUsed()) { - u8* xfbPtr = 0; - int yOffset = 0; - - // (mb2) hack: We request XFB updates from CPUthread (here) only when homebrews use directly XFB without FIFO and CP - if (!Core::GetStartupParameter().bUseDualCore || CommandProcessor::IsCommandProcessorNotUsed()) + if (NextXFBRender == 1) { - if (NextXFBRender == 1) - { - NextXFBRender = LinesPerField; - // TODO: proper VI regs typedef and logic for XFB to work. - // eg. Animal Crossing gc have smth in TFBL.XOF bitfield. - // "XOF - Horizontal Offset of the left-most pixel within the first word of the fetched picture." - xfbPtr = GetXFBPointerTop(); - _dbg_assert_msg_(VIDEOINTERFACE, xfbPtr, "Bad top XFB address"); - } + NextXFBRender = LinesPerField; + // TODO: proper VI regs typedef and logic for XFB to work. + // eg. Animal Crossing gc have smth in TFBL.XOF bitfield. + // "XOF - Horizontal Offset of the left-most pixel within the first word of the fetched picture." + xfbPtr = GetXFBPointerTop(); + _dbg_assert_msg_(VIDEOINTERFACE, xfbPtr, "Bad top XFB address"); + } + else + { + NextXFBRender = 1; + // Previously checked m_XFBInfoTop.POFF then used m_XFBInfoBottom.FBB, try reverting if there are problems + xfbPtr = GetXFBPointerBottom(); + _dbg_assert_msg_(VIDEOINTERFACE, xfbPtr, "Bad bottom XFB address"); + yOffset = -1; + } + + Common::PluginVideo* video = CPluginManager::GetInstance().GetVideo(); + + if (xfbPtr && video->IsValid()) + { + int fbWidth = m_HorizontalStepping.FieldSteps * 16; + int fbHeight = (m_HorizontalStepping.FbSteps / m_HorizontalStepping.FieldSteps) * m_VerticalTimingRegister.ACV; + + DEBUG_LOG(VIDEOINTERFACE, "(VI->XFBUpdate): ptr: %p | %ix%i | xoff: %i", + xfbPtr, fbWidth, fbHeight, m_XFBInfoTop.XOFF); + + if (Core::GetStartupParameter().bUseDualCore) + // scheduled on EmuThread in DC mode + video->Video_UpdateXFB(xfbPtr, fbWidth, fbHeight, yOffset, TRUE); else - { - NextXFBRender = 1; - // Previously checked m_XFBInfoTop.POFF then used m_XFBInfoBottom.FBB, try reverting if there are problems - xfbPtr = GetXFBPointerBottom(); - _dbg_assert_msg_(VIDEOINTERFACE, xfbPtr, "Bad bottom XFB address"); - yOffset = -1; - } - - Common::PluginVideo* video = CPluginManager::GetInstance().GetVideo(); - - if (xfbPtr && video->IsValid()) - { - int fbWidth = m_HorizontalStepping.FieldSteps * 16; - int fbHeight = (m_HorizontalStepping.FbSteps / m_HorizontalStepping.FieldSteps) * m_VerticalTimingRegister.ACV; - - DEBUG_LOG(VIDEOINTERFACE, "(VI->XFBUpdate): ptr: %p | %ix%i | xoff: %i", - xfbPtr, fbWidth, fbHeight, m_XFBInfoTop.XOFF); - - if (Core::GetStartupParameter().bUseDualCore) - // scheduled on EmuThread in DC mode - video->Video_UpdateXFB(xfbPtr, fbWidth, fbHeight, yOffset, TRUE); - else - // otherwise do it now from here (CPUthread) - video->Video_UpdateXFB(xfbPtr, fbWidth, fbHeight, yOffset, FALSE); - } + // otherwise do it now from here (CPUthread) + video->Video_UpdateXFB(xfbPtr, fbWidth, fbHeight, yOffset, FALSE); } } + } - // check INT_PRERETRACE - if (m_InterruptRegister[0].VCT == m_VBeamPos) - { - m_InterruptRegister[0].IR_INT = 1; - UpdateInterrupts(); - } + // check INT_PRERETRACE + if (m_InterruptRegister[0].VCT == m_VBeamPos) + { + m_InterruptRegister[0].IR_INT = 1; + UpdateInterrupts(); + } - // INT_POSTRETRACE - if (m_InterruptRegister[1].VCT == m_VBeamPos) - { - m_InterruptRegister[1].IR_INT = 1; - UpdateInterrupts(); - } + // INT_POSTRETRACE + if (m_InterruptRegister[1].VCT == m_VBeamPos) + { + m_InterruptRegister[1].IR_INT = 1; + UpdateInterrupts(); } } diff --git a/Source/Core/Core/Src/HW/VideoInterface.h b/Source/Core/Core/Src/HW/VideoInterface.h index 983cffa175..f85928fdf3 100644 --- a/Source/Core/Core/Src/HW/VideoInterface.h +++ b/Source/Core/Core/Src/HW/VideoInterface.h @@ -63,6 +63,8 @@ namespace VideoInterface // Change values pertaining to video mode void UpdateTiming(); + + int getTicksPerLine(); }; #endif // _VIDEOINTERFACE_H