mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-01-25 07:21:14 +01:00
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:
parent
103bc58c83
commit
81d671dc1a
@ -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);
|
||||||
|
@ -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();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
Loading…
x
Reference in New Issue
Block a user