diff --git a/Source/Core/Core/FifoPlayer/FifoDataFile.cpp b/Source/Core/Core/FifoPlayer/FifoDataFile.cpp index af693688f8..9b3d03d69a 100644 --- a/Source/Core/Core/FifoPlayer/FifoDataFile.cpp +++ b/Source/Core/Core/FifoPlayer/FifoDataFile.cpp @@ -72,6 +72,11 @@ FifoDataFile::FifoDataFile() = default; FifoDataFile::~FifoDataFile() = default; +bool FifoDataFile::ShouldGenerateFakeVIUpdates() const +{ + return true; +} + bool FifoDataFile::HasBrokenEFBCopies() const { return m_Version < 2; diff --git a/Source/Core/Core/FifoPlayer/FifoDataFile.h b/Source/Core/Core/FifoPlayer/FifoDataFile.h index f57f2fcf4a..a3825ffd2c 100644 --- a/Source/Core/Core/FifoPlayer/FifoDataFile.h +++ b/Source/Core/Core/FifoPlayer/FifoDataFile.h @@ -60,6 +60,7 @@ public: void SetIsWii(bool isWii); bool GetIsWii() const; bool HasBrokenEFBCopies() const; + bool ShouldGenerateFakeVIUpdates() const; u32* GetBPMem() { return m_BPMem; } u32* GetCPMem() { return m_CPMem; } diff --git a/Source/Core/Core/FifoPlayer/FifoPlayer.cpp b/Source/Core/Core/FifoPlayer/FifoPlayer.cpp index f84b783e68..32d0c0871c 100644 --- a/Source/Core/Core/FifoPlayer/FifoPlayer.cpp +++ b/Source/Core/Core/FifoPlayer/FifoPlayer.cpp @@ -162,6 +162,16 @@ std::unique_ptr FifoPlayer::GetCPUCore() return std::make_unique(this); } +bool FifoPlayer::IsRunningWithFakeVideoInterfaceUpdates() const +{ + if (!m_File || m_File->GetFrameCount() == 0) + { + return false; + } + + return m_File->ShouldGenerateFakeVIUpdates(); +} + u32 FifoPlayer::GetFrameObjectCount() const { if (m_CurrentFrame < m_FrameInfo.size()) diff --git a/Source/Core/Core/FifoPlayer/FifoPlayer.h b/Source/Core/Core/FifoPlayer/FifoPlayer.h index b291415ead..b2db00cb0f 100644 --- a/Source/Core/Core/FifoPlayer/FifoPlayer.h +++ b/Source/Core/Core/FifoPlayer/FifoPlayer.h @@ -94,6 +94,8 @@ public: void SetFrameWrittenCallback(CallbackFunc callback) { m_FrameWrittenCb = callback; } static FifoPlayer& GetInstance(); + bool IsRunningWithFakeVideoInterfaceUpdates() const; + private: class CPUCore; diff --git a/Source/Core/Core/HW/VideoInterface.cpp b/Source/Core/Core/HW/VideoInterface.cpp index d02a9be81d..c8ec4a3d0b 100644 --- a/Source/Core/Core/HW/VideoInterface.cpp +++ b/Source/Core/Core/HW/VideoInterface.cpp @@ -18,6 +18,7 @@ #include "Core/ConfigManager.h" #include "Core/Core.h" #include "Core/CoreTiming.h" +#include "Core/FifoPlayer/FifoPlayer.h" #include "Core/HW/MMIO.h" #include "Core/HW/ProcessorInterface.h" #include "Core/HW/SI/SI.h" @@ -549,8 +550,9 @@ float GetAspectRatio() // 5. Calculate the final ratio and scale to 4:3 float ratio = horizontal_active_ratio / vertical_active_ratio; - if (std::isnormal( - ratio)) // Check we have a sane ratio and haven't propagated any infs/nans/zeros + bool running_fifo_log = FifoPlayer::GetInstance().IsRunningWithFakeVideoInterfaceUpdates(); + if (std::isnormal(ratio) && // Check we have a sane ratio without any infs/nans/zeros + !running_fifo_log) // we don't know the correct ratio for fifos return ratio * (4.0f / 3.0f); // Scale to 4:3 else return (4.0f / 3.0f); // VI isn't initialized correctly, just return 4:3 instead @@ -775,4 +777,44 @@ void Update(u64 ticks) UpdateInterrupts(); } +// Create a fake VI mode for a fifolog +void FakeVIUpdate(u32 xfb_address, u32 fb_width, u32 fb_height) +{ + u32 fb_stride = fb_width; + + bool interlaced = fb_height > 480 / 2; + if (interlaced) + { + fb_height = fb_height / 2; + fb_stride = fb_stride * 2; + } + + m_XFBInfoTop.POFF = 1; + m_XFBInfoBottom.POFF = 1; + m_VerticalTimingRegister.ACV = fb_height; + m_VerticalTimingRegister.EQU = 6; + m_VBlankTimingOdd.PRB = 502 - fb_height * 2; + m_VBlankTimingOdd.PSB = 5; + m_VBlankTimingEven.PRB = 503 - fb_height * 2; + m_VBlankTimingEven.PSB = 4; + m_PictureConfiguration.WPL = fb_width / 16; + m_PictureConfiguration.STD = fb_stride / 16; + + UpdateParameters(); + + u32 total_halflines = GetHalfLinesPerEvenField() + GetHalfLinesPerOddField(); + + if ((s_half_line_count - s_even_field_first_hl) % total_halflines < + (s_half_line_count - s_odd_field_first_hl) % total_halflines) + { + // Even/Bottom field is next. + m_XFBInfoBottom.FBB = interlaced ? (xfb_address + fb_width * 2) >> 5 : xfb_address >> 5; + } + else + { + // Odd/Top field is next + m_XFBInfoTop.FBB = (xfb_address >> 5); + } +} + } // namespace diff --git a/Source/Core/Core/HW/VideoInterface.h b/Source/Core/Core/HW/VideoInterface.h index 6d5a07edf9..7f0ebf8400 100644 --- a/Source/Core/Core/HW/VideoInterface.h +++ b/Source/Core/Core/HW/VideoInterface.h @@ -373,4 +373,7 @@ u32 GetTicksPerField(); // result by 1.33333.. float GetAspectRatio(); +// Create a fake VI mode for a fifolog +void FakeVIUpdate(u32 xfb_address, u32 fb_width, u32 fb_height); + } // namespace VideoInterface diff --git a/Source/Core/VideoCommon/BPStructs.cpp b/Source/Core/VideoCommon/BPStructs.cpp index 977cc46b3e..e721831481 100644 --- a/Source/Core/VideoCommon/BPStructs.cpp +++ b/Source/Core/VideoCommon/BPStructs.cpp @@ -12,8 +12,10 @@ #include "Common/StringUtil.h" #include "Common/Thread.h" #include "Core/ConfigManager.h" +#include "Core/FifoPlayer/FifoPlayer.h" #include "Core/FifoPlayer/FifoRecorder.h" #include "Core/HW/Memmap.h" +#include "Core/HW/VideoInterface.h" #include "VideoCommon/BPFunctions.h" #include "VideoCommon/BPMemory.h" @@ -263,6 +265,11 @@ static void BPWritten(const BPCmd& bp) // This stays in to signal end of a "frame" g_renderer->RenderToXFB(destAddr, srcRect, destStride, height, s_gammaLUT[PE_copy.gamma]); + + if (FifoPlayer::GetInstance().IsRunningWithFakeVideoInterfaceUpdates()) + { + VideoInterface::FakeVIUpdate(destAddr, srcRect.GetWidth(), height); + } } // Clear the rectangular region after copying it.