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
This commit is contained in:
parent
95cfca08e2
commit
e9734084ee
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -101,6 +101,7 @@ struct SCoreStartupParameter
|
|||
int iRenderWindowXPos, iRenderWindowYPos;
|
||||
int iRenderWindowWidth, iRenderWindowHeight;
|
||||
bool bFullscreen, bRenderToMain;
|
||||
bool bProgressive;
|
||||
|
||||
int iTheme;
|
||||
int iPosX, iPosY, iWidth, iHeight;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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++)
|
||||
|
@ -819,62 +845,10 @@ void Update()
|
|||
}
|
||||
UpdateInterrupts();
|
||||
|
||||
if (m_DisplayControlRegister.NIN)
|
||||
if (++m_VBeamPos > s_lineCount)
|
||||
{
|
||||
// Progressive
|
||||
BeginField(FIELD_PROGRESSIVE);
|
||||
m_VBeamPos = (NewVBeamPos > s_lineCount) ? 1 : NewVBeamPos;
|
||||
}
|
||||
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();
|
||||
}
|
||||
|
||||
/*
|
||||
// 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
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue