Merge pull request #8334 from hosaka-corp/vi-update-reorg

VideoInterface: start counting half-lines at 0 instead of 1
This commit is contained in:
Connor McLaughlin 2019-08-28 16:07:37 +10:00 committed by GitHub
commit 71ff97cf1c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 40 additions and 22 deletions

View File

@ -191,7 +191,7 @@ void Preset(bool _bNTSC)
m_BorderHBlank.Hex = 0; m_BorderHBlank.Hex = 0;
s_ticks_last_line_start = 0; s_ticks_last_line_start = 0;
s_half_line_count = 1; s_half_line_count = 0;
s_half_line_of_next_si_poll = num_half_lines_for_si_poll; // first sampling starts at vsync s_half_line_of_next_si_poll = num_half_lines_for_si_poll; // first sampling starts at vsync
s_current_field = FieldType::Odd; s_current_field = FieldType::Odd;
@ -317,7 +317,7 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base)
// MMIOs with unimplemented writes that trigger warnings. // MMIOs with unimplemented writes that trigger warnings.
mmio->Register( mmio->Register(
base | VI_VERTICAL_BEAM_POSITION, base | VI_VERTICAL_BEAM_POSITION,
MMIO::ComplexRead<u16>([](u32) { return 1 + (s_half_line_count - 1) / 2; }), MMIO::ComplexRead<u16>([](u32) { return 1 + (s_half_line_count) / 2; }),
MMIO::ComplexWrite<u16>([](u32, u16 val) { MMIO::ComplexWrite<u16>([](u32, u16 val) {
WARN_LOG(VIDEOINTERFACE, WARN_LOG(VIDEOINTERFACE,
"Changing vertical beam position to 0x%04x - not documented or implemented yet", "Changing vertical beam position to 0x%04x - not documented or implemented yet",
@ -733,12 +733,30 @@ static void EndField()
// Run when: When a frame is scanned (progressive/interlace) // Run when: When a frame is scanned (progressive/interlace)
void Update(u64 ticks) void Update(u64 ticks)
{ {
// If an SI poll is scheduled to happen on this half-line, do it!
if (s_half_line_of_next_si_poll == s_half_line_count) if (s_half_line_of_next_si_poll == s_half_line_count)
{ {
SerialInterface::UpdateDevices(); SerialInterface::UpdateDevices();
s_half_line_of_next_si_poll += 2 * SerialInterface::GetPollXLines(); s_half_line_of_next_si_poll += 2 * SerialInterface::GetPollXLines();
} }
// If this half-line is at the actual boundary of either field, schedule an SI poll to happen
// some number of half-lines in the future
if (s_half_line_count == 0)
{
s_half_line_of_next_si_poll = num_half_lines_for_si_poll; // first results start at vsync
}
if (s_half_line_count == GetHalfLinesPerEvenField())
{
s_half_line_of_next_si_poll = GetHalfLinesPerEvenField() + num_half_lines_for_si_poll;
}
// If this half-line is at some boundary of the "active video lines" in either field, we either
// need to (a) send a request to the GPU thread to actually render the XFB, or (b) increment
// the number of frames we've actually drawn
if (s_half_line_count == s_even_field_first_hl) if (s_half_line_count == s_even_field_first_hl)
{ {
BeginField(FieldType::Even, ticks); BeginField(FieldType::Even, ticks);
@ -756,32 +774,32 @@ void Update(u64 ticks)
EndField(); EndField();
} }
// Move to the next half-line and potentially roll-over the count to zero. If we've reached
// the beginning of a new full-line, update the timer
s_half_line_count++;
if (s_half_line_count == GetHalfLinesPerEvenField() + GetHalfLinesPerOddField())
{
s_half_line_count = 0;
}
if (!(s_half_line_count & 1))
{
s_ticks_last_line_start = CoreTiming::GetTicks();
}
// Check if we need to assert IR_INT. Note that the granularity of our current horizontal
// position is limited to half-lines.
for (UVIInterruptRegister& reg : m_InterruptRegister) for (UVIInterruptRegister& reg : m_InterruptRegister)
{ {
if (s_half_line_count + 1 == 2u * reg.VCT) u32 target_halfline = (reg.HCT > m_HTiming0.HLW) ? 1 : 0;
if ((1 + (s_half_line_count) / 2 == reg.VCT) && ((s_half_line_count & 1) == target_halfline))
{ {
reg.IR_INT = 1; reg.IR_INT = 1;
} }
} }
s_half_line_count++;
if (s_half_line_count > GetHalfLinesPerEvenField() + GetHalfLinesPerOddField())
{
s_half_line_count = 1;
s_half_line_of_next_si_poll = num_half_lines_for_si_poll; // first results start at vsync
}
if (s_half_line_count == GetHalfLinesPerEvenField())
{
s_half_line_of_next_si_poll = GetHalfLinesPerEvenField() + num_half_lines_for_si_poll;
}
if (s_half_line_count & 1)
{
s_ticks_last_line_start = CoreTiming::GetTicks();
}
UpdateInterrupts(); UpdateInterrupts();
} }