Fixed VBeam emulation in interlaced mode, removing the hacks in the audio timing.

Fixed VBeam emulation in progressive scan mode.
Retained the old VBeam speed hack.  This option has now been switched so that the accurate behaviour is on by default and the speed hack (inaccurate behaviour) is enabled when the option is checked.
This commit is contained in:
skidau 2013-04-15 20:23:25 +10:00
parent ef4d59a21e
commit 61c11284ea
5 changed files with 31 additions and 27 deletions

View File

@ -29,6 +29,7 @@
#include "ConfigManager.h"
#include "Core.h"
#include "HW/SystemTimers.h"
#include "HW/VideoInterface.h"
DSPHLE::DSPHLE() {
m_InitMixer = false;
@ -91,7 +92,7 @@ void DSPHLE::DSP_Update(int cycles)
u32 DSPHLE::DSP_UpdateRate()
{
// AX HLE uses 3ms (Wii) or 5ms (GC) timing period
int fields = SConfig::GetInstance().m_LocalCoreStartupParameter.bVBeam ? 2 : 1;
int fields = VideoInterface::GetNumFields();
if (m_pUCode != NULL)
return (SystemTimers::GetTicksPerSecond() / 1000) * m_pUCode->GetUpdateMs() / fields;
else

View File

@ -152,7 +152,7 @@ void DSPCallback(u64 userdata, int cyclesLate)
void AudioDMACallback(u64 userdata, int cyclesLate)
{
int fields = SConfig::GetInstance().m_LocalCoreStartupParameter.bVBeam?2:1;
int fields = VideoInterface::GetNumFields();
int period = CPU_CORE_CLOCK / (AudioInterface::GetAIDSampleRate() * 4 / 32 * fields);
DSP::UpdateAudioDMA(); // Push audio to speakers.
CoreTiming::ScheduleEvent(period - cyclesLate, et_AudioDMA);

View File

@ -68,7 +68,7 @@ static u32 TicksPerFrame = 0;
static u32 s_lineCount = 0;
static u32 s_upperFieldBegin = 0;
static u32 s_lowerFieldBegin = 0;
static int fields = 2;
static int fields = 1;
void DoState(PointerWrap &p)
{
@ -181,7 +181,7 @@ void Init()
m_BorderHBlank.Hex = 0;
memset(&m_FilterCoefTables, 0, sizeof(m_FilterCoefTables));
fields = Core::g_CoreStartupParameter.bVBeam ? 1 : 2;
fields = 1;
m_DTVStatus.ntsc_j = Core::g_CoreStartupParameter.bForceNTSCJ;
@ -746,11 +746,13 @@ u32 GetXFBAddressBottom()
void UpdateParameters()
{
fields = m_DisplayControlRegister.NIN ? 2 : 1;
switch (m_DisplayControlRegister.FMT)
{
case 0: // NTSC
TargetRefreshRate = NTSC_FIELD_RATE;
TicksPerFrame = SystemTimers::GetTicksPerSecond() / (NTSC_FIELD_RATE / fields);
TicksPerFrame = SystemTimers::GetTicksPerSecond() / NTSC_FIELD_RATE;
s_lineCount = NTSC_LINE_COUNT;
s_upperFieldBegin = NTSC_UPPER_BEGIN;
s_lowerFieldBegin = NTSC_LOWER_BEGIN;
@ -758,7 +760,7 @@ void UpdateParameters()
case 2: // PAL-M
TargetRefreshRate = NTSC_FIELD_RATE;
TicksPerFrame = SystemTimers::GetTicksPerSecond() / (NTSC_FIELD_RATE / fields);
TicksPerFrame = SystemTimers::GetTicksPerSecond() / NTSC_FIELD_RATE;
s_lineCount = PAL_LINE_COUNT;
s_upperFieldBegin = PAL_UPPER_BEGIN;
s_lowerFieldBegin = PAL_LOWER_BEGIN;
@ -766,7 +768,7 @@ void UpdateParameters()
case 1: // PAL
TargetRefreshRate = PAL_FIELD_RATE;
TicksPerFrame = SystemTimers::GetTicksPerSecond() / (PAL_FIELD_RATE / fields);
TicksPerFrame = SystemTimers::GetTicksPerSecond() / PAL_FIELD_RATE;
s_lineCount = PAL_LINE_COUNT;
s_upperFieldBegin = PAL_UPPER_BEGIN;
s_lowerFieldBegin = PAL_LOWER_BEGIN;
@ -782,6 +784,14 @@ void UpdateParameters()
}
}
int GetNumFields()
{
if (Core::g_CoreStartupParameter.bVBeam)
return (2 / fields);
else
return 1;
}
unsigned int GetTicksPerLine()
{
if (s_lineCount == 0)
@ -790,7 +800,10 @@ unsigned int GetTicksPerLine()
}
else
{
return TicksPerFrame / (s_lineCount * fields);
if (Core::g_CoreStartupParameter.bVBeam)
return TicksPerFrame / s_lineCount;
else
return TicksPerFrame / (s_lineCount / (2 / fields)) ;
}
}
@ -831,39 +844,27 @@ static void EndField()
// Run when: When a frame is scanned (progressive/interlace)
void Update()
{
u16 NewVBeamPos = 0;
if (m_DisplayControlRegister.NIN)
{
// Progressive
NewVBeamPos = s_lineCount + 1;
if (m_VBeamPos == 1)
BeginField(FIELD_PROGRESSIVE);
}
else if (m_VBeamPos == s_upperFieldBegin)
{
// Interlace Upper
NewVBeamPos = s_lineCount * 2;
BeginField(FIELD_UPPER);
}
else if (m_VBeamPos == s_lowerFieldBegin)
{
// Interlace Lower
NewVBeamPos = s_lineCount;
BeginField(FIELD_LOWER);
}
if (m_DisplayControlRegister.NIN)
if (m_VBeamPos == s_upperFieldBegin + m_VerticalTimingRegister.ACV)
{
// 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.
if (Core::g_CoreStartupParameter.bVBeam)
EndField();
// Interlace Upper.
EndField();
}
else if (m_VBeamPos == s_lowerFieldBegin + m_VerticalTimingRegister.ACV)
{
@ -871,8 +872,8 @@ void Update()
EndField();
}
if (++m_VBeamPos > s_lineCount)
m_VBeamPos = (NewVBeamPos > s_lineCount || Core::g_CoreStartupParameter.bVBeam) ? 1 : NewVBeamPos;
if (++m_VBeamPos > s_lineCount * fields)
m_VBeamPos = 1;
for (int i = 0; i < 4; i++)
{

View File

@ -359,6 +359,8 @@ union UVIDTVStatus
unsigned int GetTicksPerLine();
unsigned int GetTicksPerFrame();
int GetNumFields();
};
#endif // _VIDEOINTERFACE_H

View File

@ -327,8 +327,8 @@ void CISOProperties::CreateGUIControls(bool IsWad)
TLBHack->SetToolTip(_("Fast version of the MMU. Does not work for every game."));
DCBZOFF = new wxCheckBox(m_GameConfig, ID_DCBZOFF, _("Skip DCBZ clearing"), wxDefaultPosition, wxDefaultSize, wxCHK_3STATE|wxCHK_ALLOW_3RD_STATE_FOR_USER, wxDefaultValidator);
DCBZOFF->SetToolTip(_("Bypass the clearing of the data cache by the DCBZ instruction. Usually leave this option disabled."));
VBeam = new wxCheckBox(m_GameConfig, ID_VBEAM, _("Accurate VBeam emulation"), wxDefaultPosition, wxDefaultSize, wxCHK_3STATE|wxCHK_ALLOW_3RD_STATE_FOR_USER, wxDefaultValidator);
VBeam->SetToolTip(_("If the FPS is erratic, this option may help. (ON = Compatible, OFF = Fast)"));
VBeam = new wxCheckBox(m_GameConfig, ID_VBEAM, _("VBeam Speed Hack"), wxDefaultPosition, wxDefaultSize, wxCHK_3STATE|wxCHK_ALLOW_3RD_STATE_FOR_USER, wxDefaultValidator);
VBeam->SetToolTip(_("Doubles the emulated GPU clock rate. May speed up some games (ON = Fast, OFF = Compatible)"));
SyncGPU = new wxCheckBox(m_GameConfig, ID_SYNCGPU, _("Synchronize GPU thread"), wxDefaultPosition, wxDefaultSize, wxCHK_3STATE|wxCHK_ALLOW_3RD_STATE_FOR_USER, wxDefaultValidator);
SyncGPU->SetToolTip(_("Synchronizes the GPU and CPU threads to help prevent random freezes in Dual Core mode. (ON = Compatible, OFF = Fast)"));
FastDiscSpeed = new wxCheckBox(m_GameConfig, ID_DISCSPEED, _("Speed up Disc Transfer Rate"), wxDefaultPosition, wxDefaultSize, wxCHK_3STATE|wxCHK_ALLOW_3RD_STATE_FOR_USER, wxDefaultValidator);