From ac1bb905fec29a5d6258d1e9fe14a3c5c347ffc2 Mon Sep 17 00:00:00 2001 From: Stenzek Date: Thu, 13 Jun 2024 18:29:12 +1000 Subject: [PATCH] GPU: Set idle bit during VRAM upload Tenga Seiha does a bunch of completely-invalid VRAM writes on boot, then expects GPU idle to be set. It's unclear what actually happens, I need to write another test, but for now, just skip these uploads. Not setting GPU idle during the write command breaks Doom, so that's not an option. --- src/core/gpu.cpp | 17 +---------------- src/core/gpu_commands.cpp | 21 +++++++++++++++++---- 2 files changed, 18 insertions(+), 20 deletions(-) diff --git a/src/core/gpu.cpp b/src/core/gpu.cpp index 8e6bf8173..1cc0771b7 100644 --- a/src/core/gpu.cpp +++ b/src/core/gpu.cpp @@ -445,22 +445,7 @@ void GPU::UpdateDMARequest() void GPU::UpdateGPUIdle() { - switch (m_blitter_state) - { - case BlitterState::Idle: - case BlitterState::DrawingPolyLine: - m_GPUSTAT.gpu_idle = (m_pending_command_ticks <= 0 && m_fifo.IsEmpty()); - break; - - case BlitterState::WritingVRAM: - case BlitterState::ReadingVRAM: - m_GPUSTAT.gpu_idle = m_fifo.IsEmpty(); - break; - - default: - UnreachableCode(); - break; - } + m_GPUSTAT.gpu_idle = (m_blitter_state == BlitterState::Idle && m_pending_command_ticks <= 0 && m_fifo.IsEmpty()); } u32 GPU::ReadRegister(u32 offset) diff --git a/src/core/gpu_commands.cpp b/src/core/gpu_commands.cpp index b2086e8c5..06a18f6cb 100644 --- a/src/core/gpu_commands.cpp +++ b/src/core/gpu_commands.cpp @@ -479,10 +479,23 @@ bool GPU::HandleCopyRectangleCPUToVRAMCommand() CHECK_COMMAND_SIZE(3); m_fifo.RemoveOne(); - const u32 dst_x = FifoPeek() & VRAM_WIDTH_MASK; - const u32 dst_y = (FifoPop() >> 16) & VRAM_HEIGHT_MASK; - const u32 copy_width = ReplaceZero(FifoPeek() & VRAM_WIDTH_MASK, 0x400); - const u32 copy_height = ReplaceZero((FifoPop() >> 16) & VRAM_HEIGHT_MASK, 0x200); + const u32 coords = FifoPop(); + const u32 size = FifoPop(); + + // Tenga Seiha does a bunch of completely-invalid VRAM writes on boot, then expects GPU idle to be set. + // It's unclear what actually happens, I need to write another test, but for now, just skip these uploads. + // Not setting GPU idle during the write command breaks Doom, so that's not an option. + if (size == 0xFFFFFFFFu) [[unlikely]] + { + ERROR_LOG("Ignoring likely-invalid VRAM write to ({},{})", (coords & VRAM_WIDTH_MASK), + ((coords >> 16) & VRAM_HEIGHT_MASK)); + return true; + } + + const u32 dst_x = coords & VRAM_WIDTH_MASK; + const u32 dst_y = (coords >> 16) & VRAM_HEIGHT_MASK; + const u32 copy_width = ReplaceZero(size & VRAM_WIDTH_MASK, 0x400); + const u32 copy_height = ReplaceZero((size >> 16) & VRAM_HEIGHT_MASK, 0x200); const u32 num_pixels = copy_width * copy_height; const u32 num_words = ((num_pixels + 1) / 2);