Merge pull request #3252 from booto/vi-timing-adjust

VI: wait until start of ACV to sample XFB addr
This commit is contained in:
Pierre Bourdon 2015-12-14 04:00:24 +01:00
commit 2ab0bad137
1 changed files with 73 additions and 22 deletions

View File

@ -518,12 +518,61 @@ float GetAspectRatio(bool wide)
return ((float)width / (float)height) * pixelAR; return ((float)width / (float)height) * pixelAR;
} }
// This function updates:
// a) the scanlines that are considered the 'active region' of each field
// b) the equivalent refresh rate for the current timing configuration
//
// Each pair of fields is laid out like:
// [typical values are for NTSC interlaced]
//
// <---------- one scanline width ---------->
// EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE
// ... lines omitted, 9 total E scanlines
// ... is typical
// EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE
// RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
// ... lines omitted, 12 total R scanlines
// ... is typical
// RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
// AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
// ... lines omitted, 240 total A scanlines
// ... is typical
// AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
// SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS
// SSSSSSSSSSSSSSSSSSSSSeeeeeeeeeeeeeeeeeeeee
// eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
// ... lines omitted, 9 total e scanlines
// ... is typical
// eeeeeeeeeeeeeeeeeeeeerrrrrrrrrrrrrrrrrrrrr
// rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr
// ... lines omitted, 12.5 total r scanlines
// ... is typical
// rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr
// aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
// ... line omitted, 240 total a scanlines
// ... is typical
// aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
// ssssssssssssssssssssssssssssssssssssssssss
//
// Uppercase is field 1, lowercase is field 2
// E,e = pre-equ/vert-sync/post-equ
// = (m_VerticalTimingRegister.EQU*3) half-scanlines
// R,r = preblanking
// = (m_VBlankTimingX.PRB) half-scanlines
// A,a = active lines
// = (m_VerticalTimingRegister.ACV*2) half-scanlines
// S,s = postblanking
// = (m_VBlankTimingX.PSB) half-scanlines
//
// NB: for double-strike modes, the second field
// does not get offset by half a scanline
void UpdateParameters() void UpdateParameters()
{ {
s_even_field_first_hl = 1; s_even_field_first_hl = 3 * m_VerticalTimingRegister.EQU + m_VBlankTimingEven.PRB + 1;
s_odd_field_first_hl = s_even_field_first_hl + GetHalfLinesPerEvenField(); s_odd_field_first_hl = GetHalfLinesPerEvenField() + 3 * m_VerticalTimingRegister.EQU + m_VBlankTimingOdd.PRB + 1;
s_even_field_last_hl = s_odd_field_first_hl - 1; s_even_field_last_hl = s_even_field_first_hl + m_VerticalTimingRegister.ACV * 2;
s_odd_field_last_hl = s_odd_field_first_hl + GetHalfLinesPerOddField() - 1; s_odd_field_last_hl = s_odd_field_first_hl + m_VerticalTimingRegister.ACV * 2;
TargetRefreshRate = lround(2.0 * SystemTimers::GetTicksPerSecond() / (GetTicksPerEvenField() + GetTicksPerOddField())); TargetRefreshRate = lround(2.0 * SystemTimers::GetTicksPerSecond() / (GetTicksPerEvenField() + GetTicksPerOddField()));
} }
@ -548,6 +597,15 @@ static void BeginField(FieldType field)
u32 xfbAddr; u32 xfbAddr;
if (field == FieldType::FIELD_EVEN)
{
xfbAddr = GetXFBAddressBottom();
}
else
{
xfbAddr = GetXFBAddressTop();
}
if (interlaced_xfb && g_ActiveConfig.bForceProgressive) { if (interlaced_xfb && g_ActiveConfig.bForceProgressive) {
// Strictly speaking, in interlaced mode, we're only supposed to read // Strictly speaking, in interlaced mode, we're only supposed to read
// half of the lines of the XFB, and use that to display a field; the // half of the lines of the XFB, and use that to display a field; the
@ -558,24 +616,17 @@ static void BeginField(FieldType field)
// videos in Metroid Prime don't render correctly using this hack. // videos in Metroid Prime don't render correctly using this hack.
fbStride /= 2; fbStride /= 2;
fbHeight *= 2; fbHeight *= 2;
if (m_VBlankTimingOdd.PRB < m_VBlankTimingEven.PRB)
{ // PRB for the different fields should only ever differ by 1 in
xfbAddr = GetXFBAddressTop(); // interlaced mode, and which is less determines which field
// has the first line. For the field with the second line, we
// offset the xfb by (-stride_of_one_line) to get the start
// address of the full xfb.
if ((field == FieldType::FIELD_ODD) && (m_VBlankTimingOdd.PRB == m_VBlankTimingEven.PRB + 1)) {
xfbAddr -= (fbStride * 2);
} }
else if ((field == FieldType::FIELD_EVEN) && (m_VBlankTimingOdd.PRB == m_VBlankTimingEven.PRB - 1)) {
{ xfbAddr -= (fbStride * 2);
xfbAddr = GetXFBAddressBottom();
}
}
else
{
if (field == FieldType::FIELD_EVEN)
{
xfbAddr = GetXFBAddressTop();
}
else
{
xfbAddr = GetXFBAddressBottom();
} }
} }
@ -636,7 +687,7 @@ void Update()
s_half_line_count++; s_half_line_count++;
if (s_half_line_count > s_odd_field_last_hl) { if (s_half_line_count > GetHalfLinesPerEvenField() + GetHalfLinesPerOddField()) {
s_half_line_count = 1; s_half_line_count = 1;
} }