Aligned VideoInterface events with scanline updates.

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@3541 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
LinesPrower 2009-06-24 09:46:09 +00:00
parent 103bc58c83
commit 81d671dc1a
3 changed files with 63 additions and 74 deletions

View File

@ -112,11 +112,6 @@ int et_FakeGPWD; // for DC watchdog hack
// 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
// 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. // TODO: The SI in fact actually has a register that determines the polling frequency.
// We should obey that instead of arbitrarly checking at 60fps. // We should obey that instead of arbitrarly checking at 60fps.
SI_PERIOD, // once a frame is good for controllers SI_PERIOD, // once a frame is good for controllers
@ -185,7 +180,7 @@ void VICallback(u64 userdata, int cyclesLate)
WII_IPC_HLE_Interface::Update(); WII_IPC_HLE_Interface::Update();
VideoInterface::Update(); VideoInterface::Update();
CoreTiming::ScheduleEvent(VI_PERIOD-cyclesLate, et_VI); CoreTiming::ScheduleEvent(VideoInterface::getTicksPerLine() - cyclesLate, et_VI);
} }
void SICallback(u64 userdata, int cyclesLate) void SICallback(u64 userdata, int cyclesLate)
@ -241,7 +236,6 @@ void Init()
if (Core::GetStartupParameter().bWii) if (Core::GetStartupParameter().bWii)
{ {
CPU_CORE_CLOCK = 729000000u; CPU_CORE_CLOCK = 729000000u;
VI_PERIOD = GetTicksPerSecond() / (60*120);
SI_PERIOD = GetTicksPerSecond() / 60; // once a frame is good for controllers SI_PERIOD = GetTicksPerSecond() / 60; // once a frame is good for controllers
if (!Core::GetStartupParameter().bDSPThread) { if (!Core::GetStartupParameter().bDSPThread) {
@ -258,7 +252,6 @@ void Init()
else else
{ {
CPU_CORE_CLOCK = 486000000; CPU_CORE_CLOCK = 486000000;
VI_PERIOD = GetTicksPerSecond() / (60*120);
SI_PERIOD = GetTicksPerSecond() / 60; // once a frame is good for controllers SI_PERIOD = GetTicksPerSecond() / 60; // once a frame is good for controllers
if (!Core::GetStartupParameter().bDSPThread) { if (!Core::GetStartupParameter().bDSPThread) {
@ -285,7 +278,7 @@ void Init()
et_FakeGPWD = CoreTiming::RegisterEvent("FakeGPWatchdogCallback", FakeGPWatchdogCallback); et_FakeGPWD = CoreTiming::RegisterEvent("FakeGPWatchdogCallback", FakeGPWatchdogCallback);
CoreTiming::ScheduleEvent(AI_PERIOD, et_AI); 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(DSP_PERIOD, et_DSP);
CoreTiming::ScheduleEvent(SI_PERIOD, et_SI); CoreTiming::ScheduleEvent(SI_PERIOD, et_SI);
CoreTiming::ScheduleEvent(CPU_CORE_CLOCK / (32000 * 4 / 32), et_AudioFifo); CoreTiming::ScheduleEvent(CPU_CORE_CLOCK / (32000 * 4 / 32), et_AudioFifo);

View File

@ -336,7 +336,6 @@ static UVIBorderBlankRegister m_BorderHBlank;
static u32 TicksPerFrame = 0; static u32 TicksPerFrame = 0;
static u32 LineCount = 0; static u32 LineCount = 0;
static u32 LinesPerField = 0; static u32 LinesPerField = 0;
static u64 LastTime = 0;
static u32 NextXFBRender = 0; static u32 NextXFBRender = 0;
int TargetRefreshRate = 0; int TargetRefreshRate = 0;
s64 SyncTicksProgress = 0; s64 SyncTicksProgress = 0;
@ -372,7 +371,6 @@ void DoState(PointerWrap &p)
p.Do(TicksPerFrame); p.Do(TicksPerFrame);
p.Do(LineCount); p.Do(LineCount);
p.Do(LinesPerField); p.Do(LinesPerField);
p.Do(LastTime);
p.Do(NextXFBRender); p.Do(NextXFBRender);
} }
@ -380,7 +378,6 @@ void PreInit(bool _bNTSC)
{ {
TicksPerFrame = 0; TicksPerFrame = 0;
LineCount = 0; LineCount = 0;
LastTime = 0;
m_VerticalTimingRegister.EQU = 6; 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 // Purpose 1: Send VI interrupt for every screen refresh
@ -1067,77 +1068,70 @@ void Update()
SyncTicksProgress = 0; SyncTicksProgress = 0;
} }
m_VBeamPos++;
// Go through all lines if (m_VBeamPos > LineCount)
while ((CoreTiming::GetTicks() - LastTime) > (TicksPerFrame / LineCount))
{ {
LastTime += (TicksPerFrame / LineCount); m_VBeamPos = 1;
}
m_VBeamPos++; if (m_VBeamPos == NextXFBRender)
if (m_VBeamPos > LineCount) {
{ u8* xfbPtr = 0;
m_VBeamPos = 1; 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; if (NextXFBRender == 1)
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) NextXFBRender = LinesPerField;
{ // TODO: proper VI regs typedef and logic for XFB to work.
NextXFBRender = LinesPerField; // eg. Animal Crossing gc have smth in TFBL.XOF bitfield.
// TODO: proper VI regs typedef and logic for XFB to work. // "XOF - Horizontal Offset of the left-most pixel within the first word of the fetched picture."
// eg. Animal Crossing gc have smth in TFBL.XOF bitfield. xfbPtr = GetXFBPointerTop();
// "XOF - Horizontal Offset of the left-most pixel within the first word of the fetched picture." _dbg_assert_msg_(VIDEOINTERFACE, xfbPtr, "Bad top XFB address");
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 else
{ // otherwise do it now from here (CPUthread)
NextXFBRender = 1; video->Video_UpdateXFB(xfbPtr, fbWidth, fbHeight, yOffset, FALSE);
// 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);
}
} }
} }
}
// check INT_PRERETRACE // check INT_PRERETRACE
if (m_InterruptRegister[0].VCT == m_VBeamPos) if (m_InterruptRegister[0].VCT == m_VBeamPos)
{ {
m_InterruptRegister[0].IR_INT = 1; m_InterruptRegister[0].IR_INT = 1;
UpdateInterrupts(); UpdateInterrupts();
} }
// INT_POSTRETRACE // INT_POSTRETRACE
if (m_InterruptRegister[1].VCT == m_VBeamPos) if (m_InterruptRegister[1].VCT == m_VBeamPos)
{ {
m_InterruptRegister[1].IR_INT = 1; m_InterruptRegister[1].IR_INT = 1;
UpdateInterrupts(); UpdateInterrupts();
}
} }
} }

View File

@ -63,6 +63,8 @@ namespace VideoInterface
// Change values pertaining to video mode // Change values pertaining to video mode
void UpdateTiming(); void UpdateTiming();
int getTicksPerLine();
}; };
#endif // _VIDEOINTERFACE_H #endif // _VIDEOINTERFACE_H