Skip to content
Permalink
Browse files

VideoInterface: start counting half-lines at 0 instead of 1

- Re-organize VideoInterface::Update() to count half-lines starting at 0 instead of 1
- Use horizontal position when checking if we should assert some display interrupt
- Add some more descriptive comments
  • Loading branch information...
hosaka-corp committed Aug 27, 2019
1 parent 230ff47 commit 9e3b867c6ae41df296ebf3112db6dd14c47abb37
Showing with 36 additions and 18 deletions.
  1. +36 −18 Source/Core/Core/HW/VideoInterface.cpp
@@ -191,7 +191,7 @@ void Preset(bool _bNTSC)
m_BorderHBlank.Hex = 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_current_field = FieldType::Odd;

@@ -317,7 +317,7 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base)
// MMIOs with unimplemented writes that trigger warnings.
mmio->Register(
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) {
WARN_LOG(VIDEOINTERFACE,
"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)
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)
{
SerialInterface::UpdateDevices();

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)
{
BeginField(FieldType::Even, ticks);
@@ -756,30 +774,30 @@ void Update(u64 ticks)
EndField();
}

for (UVIInterruptRegister& reg : m_InterruptRegister)
{
if (s_half_line_count + 1 == 2u * reg.VCT)
{
reg.IR_INT = 1;
}
}
// 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())
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
s_half_line_count = 0;
}

if (s_half_line_count == GetHalfLinesPerEvenField())
if (!(s_half_line_count & 1))
{
s_half_line_of_next_si_poll = GetHalfLinesPerEvenField() + num_half_lines_for_si_poll;
s_ticks_last_line_start = CoreTiming::GetTicks();
}

if (s_half_line_count & 1)
// 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)
{
s_ticks_last_line_start = CoreTiming::GetTicks();
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;
}
}

UpdateInterrupts();

0 comments on commit 9e3b867

Please sign in to comment.
You can’t perform that action at this time.