From e9734084ee1058e8c76d5c39d686bae728adbcb9 Mon Sep 17 00:00:00 2001 From: skidau Date: Thu, 21 Oct 2010 14:50:42 +0000 Subject: [PATCH] VideoInterface and Progressive Scan fixes The "Enable Progressive Scan" option in the Wii menu now controls whether the Wii/GC will detect a progressive scan display. This affects the timing of some games (both GC and Wii). Usually, the checkbox should be unticked as progressive scan displays require higher bandwidth. This fixes the slow speed in NBA JAM. This also fixes the hang in Megaman Network Transmission. This should fix Deadly Creatures (turn off progressive scan). Fixes issue 3314. Fixes issue 3066. Fixes issue 2571. git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@6297 8ced0084-cf51-0410-be5f-012b33b47a6e --- Source/Core/Core/Src/ConfigManager.cpp | 2 + Source/Core/Core/Src/CoreParameter.cpp | 1 + Source/Core/Core/Src/CoreParameter.h | 1 + Source/Core/Core/Src/HW/SystemTimers.cpp | 6 +- Source/Core/Core/Src/HW/VideoInterface.cpp | 146 ++++++++------------ Source/Core/DolphinWX/Src/ConfigMain.cpp | 1 + Source/Core/DolphinWX/Src/ISOProperties.cpp | 6 +- Source/Plugins/Plugin_VideoDX9/Src/main.cpp | 14 +- Source/Plugins/Plugin_VideoOGL/Src/main.cpp | 14 +- 9 files changed, 81 insertions(+), 110 deletions(-) diff --git a/Source/Core/Core/Src/ConfigManager.cpp b/Source/Core/Core/Src/ConfigManager.cpp index a97c325251..d611200252 100644 --- a/Source/Core/Core/Src/ConfigManager.cpp +++ b/Source/Core/Core/Src/ConfigManager.cpp @@ -121,6 +121,7 @@ void SConfig::SaveSettings() ini.Set("Display", "RenderWindowYPos", m_LocalCoreStartupParameter.iRenderWindowYPos); ini.Set("Display", "RenderWindowWidth", m_LocalCoreStartupParameter.iRenderWindowWidth); ini.Set("Display", "RenderWindowHeight", m_LocalCoreStartupParameter.iRenderWindowHeight); + ini.Set("Display", "ProgressiveScan", m_LocalCoreStartupParameter.bProgressive); // Game List Control ini.Set("GameList", "ListDrives", m_ListDrives); @@ -243,6 +244,7 @@ void SConfig::LoadSettings() ini.Get("Display", "RenderWindowYPos", &m_LocalCoreStartupParameter.iRenderWindowYPos, 0); ini.Get("Display", "RenderWindowWidth", &m_LocalCoreStartupParameter.iRenderWindowWidth, 640); ini.Get("Display", "RenderWindowHeight", &m_LocalCoreStartupParameter.iRenderWindowHeight, 480); + ini.Get("Display", "ProgressiveScan", &m_LocalCoreStartupParameter.bProgressive, false); // Game List Control ini.Get("GameList", "ListDrives", &m_ListDrives, false); diff --git a/Source/Core/Core/Src/CoreParameter.cpp b/Source/Core/Core/Src/CoreParameter.cpp index 8a712f798e..68f2392252 100644 --- a/Source/Core/Core/Src/CoreParameter.cpp +++ b/Source/Core/Core/Src/CoreParameter.cpp @@ -56,6 +56,7 @@ SCoreStartupParameter::SCoreStartupParameter() iRenderWindowXPos(0), iRenderWindowYPos(0), iRenderWindowWidth(640), iRenderWindowHeight(480), bFullscreen(false), bRenderToMain(false), + bProgressive(false), iTheme(0), iPosX(100), iPosY(100), iWidth(800), iHeight(600) { diff --git a/Source/Core/Core/Src/CoreParameter.h b/Source/Core/Core/Src/CoreParameter.h index 03c8f4e6f6..ca7cd6196e 100644 --- a/Source/Core/Core/Src/CoreParameter.h +++ b/Source/Core/Core/Src/CoreParameter.h @@ -101,6 +101,7 @@ struct SCoreStartupParameter int iRenderWindowXPos, iRenderWindowYPos; int iRenderWindowWidth, iRenderWindowHeight; bool bFullscreen, bRenderToMain; + bool bProgressive; int iTheme; int iPosX, iPosY, iWidth, iHeight; diff --git a/Source/Core/Core/Src/HW/SystemTimers.cpp b/Source/Core/Core/Src/HW/SystemTimers.cpp index bd67d8bb92..99d209ad69 100644 --- a/Source/Core/Core/Src/HW/SystemTimers.cpp +++ b/Source/Core/Core/Src/HW/SystemTimers.cpp @@ -182,7 +182,7 @@ void IPC_HLE_UpdateCallback(u64 userdata, int cyclesLate) void VICallback(u64 userdata, int cyclesLate) { VideoInterface::Update(); - CoreTiming::ScheduleEvent(VideoInterface::GetTicksPerFrame() - cyclesLate, et_VI); + CoreTiming::ScheduleEvent(VideoInterface::GetTicksPerLine() - cyclesLate, et_VI); } void SICallback(u64 userdata, int cyclesLate) @@ -278,7 +278,7 @@ void Init() // This is the biggest question mark. AI_PERIOD = GetTicksPerSecond() / 80; - // System internal sample rate is fixed at 32KHz + // System internal sample rate is fixed at 32KHz * 4 (16bit Stereo) / 32 bytes DMA AUDIO_DMA_PERIOD = CPU_CORE_CLOCK / (32000 * 4 / 32); Common::Timer::IncreaseResolution(); @@ -301,7 +301,7 @@ void Init() et_PatchEngine = CoreTiming::RegisterEvent("PatchEngine", PatchEngineCallback); CoreTiming::ScheduleEvent(AI_PERIOD, et_AI); - CoreTiming::ScheduleEvent(VideoInterface::GetTicksPerFrame(), et_VI); + CoreTiming::ScheduleEvent(VideoInterface::GetTicksPerLine(), et_VI); CoreTiming::ScheduleEvent(DSP_PERIOD, et_DSP); CoreTiming::ScheduleEvent(VideoInterface::GetTicksPerFrame(), et_SI); CoreTiming::ScheduleEvent(AUDIO_DMA_PERIOD, et_AudioDMA); diff --git a/Source/Core/Core/Src/HW/VideoInterface.cpp b/Source/Core/Core/Src/HW/VideoInterface.cpp index 96f58ceff4..422c76e547 100644 --- a/Source/Core/Core/Src/HW/VideoInterface.cpp +++ b/Source/Core/Core/Src/HW/VideoInterface.cpp @@ -145,17 +145,18 @@ void Preset(bool _bNTSC) m_VBeamPos = 1; // 54MHz, capable of progressive scan - m_Clock = 1; + m_Clock = Core::g_CoreStartupParameter.bProgressive?1:0; // Say component cable is plugged - m_DTVStatus = 1; + m_DTVStatus = Core::g_CoreStartupParameter.bProgressive?1:0; UpdateParameters(); } void SetRegionReg(char _region) { - m_DTVStatus = _region | (m_DTVStatus & 1); + if (Core::g_CoreStartupParameter.bProgressive) + m_DTVStatus = _region | (m_DTVStatus & 1); } void Init() @@ -280,6 +281,8 @@ void Read16(u16& _uReturnValue, const u32 _iAddress) // RETRACE STUFF ... case VI_PRERETRACE_HI: _uReturnValue = m_InterruptRegister[0].Hi; + m_InterruptRegister[0].IR_INT = 0; + UpdateInterrupts(); return; case VI_PRERETRACE_LO: _uReturnValue = m_InterruptRegister[0].Lo; @@ -287,6 +290,8 @@ void Read16(u16& _uReturnValue, const u32 _iAddress) case VI_POSTRETRACE_HI: _uReturnValue = m_InterruptRegister[1].Hi; + m_InterruptRegister[1].IR_INT = 0; + UpdateInterrupts(); return; case VI_POSTRETRACE_LO: _uReturnValue = m_InterruptRegister[1].Lo; @@ -294,6 +299,8 @@ void Read16(u16& _uReturnValue, const u32 _iAddress) case VI_DISPLAY_INTERRUPT_2_HI: _uReturnValue = m_InterruptRegister[2].Hi; + m_InterruptRegister[2].IR_INT = 0; + UpdateInterrupts(); return; case VI_DISPLAY_INTERRUPT_2_LO: _uReturnValue = m_InterruptRegister[2].Lo; @@ -301,6 +308,8 @@ void Read16(u16& _uReturnValue, const u32 _iAddress) case VI_DISPLAY_INTERRUPT_3_HI: _uReturnValue = m_InterruptRegister[3].Hi; + m_InterruptRegister[3].IR_INT = 0; + UpdateInterrupts(); return; case VI_DISPLAY_INTERRUPT_3_LO: _uReturnValue = m_InterruptRegister[3].Lo; @@ -528,7 +537,6 @@ void Write16(const u16 _iValue, const u32 _iAddress) // RETRACE STUFF ... case VI_PRERETRACE_HI: m_InterruptRegister[0].Hi = _iValue; - UpdateInterrupts(); break; case VI_PRERETRACE_LO: m_InterruptRegister[0].Lo = _iValue; @@ -536,7 +544,6 @@ void Write16(const u16 _iValue, const u32 _iAddress) case VI_POSTRETRACE_HI: m_InterruptRegister[1].Hi = _iValue; - UpdateInterrupts(); break; case VI_POSTRETRACE_LO: m_InterruptRegister[1].Lo = _iValue; @@ -544,7 +551,6 @@ void Write16(const u16 _iValue, const u32 _iAddress) case VI_DISPLAY_INTERRUPT_2_HI: m_InterruptRegister[2].Hi = _iValue; - UpdateInterrupts(); break; case VI_DISPLAY_INTERRUPT_2_LO: m_InterruptRegister[2].Lo = _iValue; @@ -552,7 +558,6 @@ void Write16(const u16 _iValue, const u32 _iAddress) case VI_DISPLAY_INTERRUPT_3_HI: m_InterruptRegister[3].Hi = _iValue; - UpdateInterrupts(); break; case VI_DISPLAY_INTERRUPT_3_LO: m_InterruptRegister[3].Lo = _iValue; @@ -717,23 +722,19 @@ void UpdateParameters() case 0: // NTSC case 2: // PAL-M TargetRefreshRate = NTSC_FIELD_RATE; - // AyuanX: Some games are pretty sensitive to this value - // So we have to make it run a little faster to prevent potential time out - TicksPerFrame = SystemTimers::GetTicksPerSecond() / (NTSC_FIELD_RATE + 1); - s_lineCount = m_DisplayControlRegister.NIN ? NTSC_LINE_COUNT : (NTSC_LINE_COUNT+1)/2; - //s_upperFieldBegin = NTSC_UPPER_BEGIN; - //s_lowerFieldBegin = NTSC_LOWER_BEGIN; - break; + TicksPerFrame = SystemTimers::GetTicksPerSecond() / (NTSC_FIELD_RATE / 2); + s_lineCount = NTSC_LINE_COUNT; + s_upperFieldBegin = NTSC_UPPER_BEGIN; + s_lowerFieldBegin = NTSC_LOWER_BEGIN; + break; case 1: // PAL TargetRefreshRate = PAL_FIELD_RATE; - // AyuanX: Some games are pretty sensitive to this value - // So we have to make it run a little faster to prevent potential time out - TicksPerFrame = SystemTimers::GetTicksPerSecond() / (PAL_FIELD_RATE + 1); - s_lineCount = m_DisplayControlRegister.NIN ? PAL_LINE_COUNT : (PAL_LINE_COUNT+1)/2; - //s_upperFieldBegin = PAL_UPPER_BEGIN; - //s_lowerFieldBegin = PAL_LOWER_BEGIN; - break; + TicksPerFrame = SystemTimers::GetTicksPerSecond() / (PAL_FIELD_RATE / 2); + s_lineCount = PAL_LINE_COUNT; + s_upperFieldBegin = PAL_UPPER_BEGIN; + s_lowerFieldBegin = PAL_LOWER_BEGIN; + break; case 3: // Debug PanicAlert("Debug video mode not implemented"); @@ -748,9 +749,13 @@ void UpdateParameters() int GetTicksPerLine() { if (s_lineCount == 0) - return 100000; + { + return 1; + } else - return TicksPerFrame / s_lineCount; + { + return TicksPerFrame / (s_lineCount * 2); + } } int GetTicksPerFrame() @@ -781,35 +786,56 @@ static void BeginField(FieldType field) video->Video_BeginField(xfbAddr, field, fbWidth, fbHeight); } -/* static void EndField() { Common::PluginVideo* video = CPluginManager::GetInstance().GetVideo(); if (video->IsValid()) + { video->Video_EndField(); + Core::VideoThrottle(); + } } -*/ -// AyuanX: No need to update per scan line, update per frame is good enough, and faster // Purpose: Send VI interrupt when triggered -// Run when: When a frame is scaned (progressive/interlace) +// Run when: When a frame is scanned (progressive/interlace) void Update() { - u16 NewVBeamPos; + u16 NewVBeamPos = 0; + if (m_DisplayControlRegister.NIN) { // Progressive NewVBeamPos = s_lineCount + 1; + BeginField(FIELD_PROGRESSIVE); } - else if (m_VBeamPos == s_lineCount) + else if (m_VBeamPos == s_upperFieldBegin) { // Interlace Upper NewVBeamPos = s_lineCount * 2; + BeginField(FIELD_UPPER); } - else + else if (m_VBeamPos == s_lowerFieldBegin) { // Interlace Lower NewVBeamPos = s_lineCount; + BeginField(FIELD_LOWER); + } + + if (m_DisplayControlRegister.NIN) + { + // Progressive + if (m_VBeamPos == s_lineCount) + EndField(); + } + else if (m_VBeamPos == s_upperFieldBegin + m_VerticalTimingRegister.ACV) + { + // Interlace Upper. Do not EndField (swapBuffer) at the end of the upper field. + //EndField(); + } + else if (m_VBeamPos == s_lowerFieldBegin + m_VerticalTimingRegister.ACV) + { + // Interlace Lower + EndField(); } for (int i = 0; i < 4; i++) @@ -818,63 +844,11 @@ void Update() m_InterruptRegister[i].IR_INT = 1; } UpdateInterrupts(); - - if (m_DisplayControlRegister.NIN) - { - // Progressive - BeginField(FIELD_PROGRESSIVE); - } - else if (m_VBeamPos == s_lineCount) - { - // Interlace Upper - BeginField(FIELD_UPPER); - } - else - { - // Interlace Lower - BeginField(FIELD_LOWER); - } - m_VBeamPos = (NewVBeamPos > s_lineCount) ? 1 : NewVBeamPos; - - - Core::VideoThrottle(); + if (++m_VBeamPos > s_lineCount) + { + m_VBeamPos = (NewVBeamPos > s_lineCount) ? 1 : NewVBeamPos; + } } -/* -// Purpose: Send VI interrupt when triggered -// Run when: When a line is scaned -void Update() -{ - - // TODO: What's the correct behavior for progressive mode? - if (m_VBeamPos == s_upperFieldBegin + m_VerticalTimingRegister.ACV) - EndField(); - else if (m_VBeamPos == s_lowerFieldBegin + m_VerticalTimingRegister.ACV) - EndField(); - - - if (++m_VBeamPos > s_lineCount) - { - m_VBeamPos = 1; - // Apply video throttle whenever a full screen scan finishes - Core::VideoThrottle(); - } - - for (int i = 0; i < 4; ++i) - { - if (m_InterruptRegister[i].VCT == m_VBeamPos) - m_InterruptRegister[i].IR_INT = 1; - } - UpdateInterrupts(); - - - if (m_VBeamPos == s_upperFieldBegin) - BeginField(m_DisplayControlRegister.NIN ? FIELD_PROGRESSIVE : FIELD_UPPER); - else if (m_VBeamPos == s_lowerFieldBegin) - BeginField(m_DisplayControlRegister.NIN ? FIELD_PROGRESSIVE : FIELD_LOWER); - -} -*/ - } // namespace diff --git a/Source/Core/DolphinWX/Src/ConfigMain.cpp b/Source/Core/DolphinWX/Src/ConfigMain.cpp index d14b486ca5..83a2d611fb 100644 --- a/Source/Core/DolphinWX/Src/ConfigMain.cpp +++ b/Source/Core/DolphinWX/Src/ConfigMain.cpp @@ -1039,6 +1039,7 @@ void CConfigMain::WiiSettingsChanged(wxCommandEvent& event) break; case ID_WII_IPL_PGS: SConfig::GetInstance().m_SYSCONF->SetData("IPL.PGS", WiiProgressiveScan->IsChecked()); + SConfig::GetInstance().m_LocalCoreStartupParameter.bProgressive = WiiProgressiveScan->IsChecked(); break; case ID_WII_IPL_E60: SConfig::GetInstance().m_SYSCONF->SetData("IPL.E60", WiiEuRGB60->IsChecked()); diff --git a/Source/Core/DolphinWX/Src/ISOProperties.cpp b/Source/Core/DolphinWX/Src/ISOProperties.cpp index ef5da260d8..5f427e77d0 100644 --- a/Source/Core/DolphinWX/Src/ISOProperties.cpp +++ b/Source/Core/DolphinWX/Src/ISOProperties.cpp @@ -863,7 +863,7 @@ void CISOProperties::LoadGameConfig() else BlockMerging->Set3StateValue(wxCHK_UNDETERMINED); - if (GameIni.Get("Wii", "ProgressiveScan", &bTemp)) + if (GameIni.Get("Display", "ProgressiveScan", &bTemp)) EnableProgressiveScan->Set3StateValue((wxCheckBoxState)bTemp); else EnableProgressiveScan->Set3StateValue(wxCHK_UNDETERMINED); @@ -980,9 +980,9 @@ bool CISOProperties::SaveGameConfig() GameIni.Set("Core", "BlockMerging", BlockMerging->Get3StateValue()); if (EnableProgressiveScan->Get3StateValue() == wxCHK_UNDETERMINED) - GameIni.DeleteKey("Wii", "ProgressiveScan"); + GameIni.DeleteKey("Display", "ProgressiveScan"); else - GameIni.Set("Wii", "ProgressiveScan", EnableProgressiveScan->Get3StateValue()); + GameIni.Set("Display", "ProgressiveScan", EnableProgressiveScan->Get3StateValue()); if (EnableWideScreen->Get3StateValue() == wxCHK_UNDETERMINED) GameIni.DeleteKey("Wii", "Widescreen"); diff --git a/Source/Plugins/Plugin_VideoDX9/Src/main.cpp b/Source/Plugins/Plugin_VideoDX9/Src/main.cpp index 6a800f557c..a67d0853f5 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/main.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/main.cpp @@ -357,26 +357,22 @@ void Video_BeginField(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight) { if (s_PluginInitialized && g_ActiveConfig.bUseXFB) { - if (g_VideoInitialize.bOnThread) - { - while (Common::AtomicLoadAcquire(s_swapRequested) && !s_FifoShuttingDown) - //Common::SleepCurrentThread(1); - Common::YieldCPU(); - } - else + if (!g_VideoInitialize.bOnThread) VideoFifo_CheckSwapRequest(); s_beginFieldArgs.xfbAddr = xfbAddr; s_beginFieldArgs.field = field; s_beginFieldArgs.fbWidth = fbWidth; s_beginFieldArgs.fbHeight = fbHeight; - - Common::AtomicStoreRelease(s_swapRequested, TRUE); } } // Run from the CPU thread (from VideoInterface.cpp) void Video_EndField() { + if (s_PluginInitialized) + { + Common::AtomicStoreRelease(s_swapRequested, TRUE); + } } void Video_AddMessage(const char* pstr, u32 milliseconds) diff --git a/Source/Plugins/Plugin_VideoOGL/Src/main.cpp b/Source/Plugins/Plugin_VideoOGL/Src/main.cpp index 0f83984783..b25f1482b6 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/main.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/main.cpp @@ -387,26 +387,22 @@ void Video_BeginField(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight) { if (s_PluginInitialized && g_ActiveConfig.bUseXFB) { - if (g_VideoInitialize.bOnThread) - { - while (Common::AtomicLoadAcquire(s_swapRequested) && !s_FifoShuttingDown) - //Common::SleepCurrentThread(1); - Common::YieldCPU(); - } - else + if (!g_VideoInitialize.bOnThread) VideoFifo_CheckSwapRequest(); s_beginFieldArgs.xfbAddr = xfbAddr; s_beginFieldArgs.field = field; s_beginFieldArgs.fbWidth = fbWidth; s_beginFieldArgs.fbHeight = fbHeight; - - Common::AtomicStoreRelease(s_swapRequested, TRUE); } } // Run from the CPU thread (from VideoInterface.cpp) void Video_EndField() { + if (s_PluginInitialized) + { + Common::AtomicStoreRelease(s_swapRequested, TRUE); + } } void Video_AddMessage(const char* pstr, u32 milliseconds)