summaryrefslogtreecommitdiff
path: root/Source/Core
diff options
context:
space:
mode:
authorConnor McLaughlin <stenzek@gmail.com>2019-08-28 16:07:37 +1000
committerGitHub <noreply@github.com>2019-08-28 16:07:37 +1000
commit71ff97cf1cf6ccaed34826a8f8d14cad0e292d7c (patch)
tree8e4701895dc6007de1664ccca441a3150a95bfcf /Source/Core
parent230ff47c0a9482bf24d6da63ce599d4973f3d62c (diff)
parent9e3b867c6ae41df296ebf3112db6dd14c47abb37 (diff)
Merge pull request #8334 from hosaka-corp/vi-update-reorg
VideoInterface: start counting half-lines at 0 instead of 1
Diffstat (limited to 'Source/Core')
-rw-r--r--Source/Core/Core/HW/VideoInterface.cpp54
1 files changed, 36 insertions, 18 deletions
diff --git a/Source/Core/Core/HW/VideoInterface.cpp b/Source/Core/Core/HW/VideoInterface.cpp
index ccd9700663..9af6f9f46a 100644
--- a/Source/Core/Core/HW/VideoInterface.cpp
+++ b/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();