diff --git a/src/core/gpu.cpp b/src/core/gpu.cpp index a2fe8957b..4ce3ae239 100644 --- a/src/core/gpu.cpp +++ b/src/core/gpu.cpp @@ -79,6 +79,8 @@ void GPU::Reset() void GPU::SoftReset() { FlushRender(); + if (m_blitter_state == BlitterState::WritingVRAM) + FinishVRAMWrite(); m_GPUSTAT.bits = 0x14802000; m_GPUSTAT.pal_mode = System::IsPALRegion(); @@ -922,6 +924,11 @@ void GPU::WriteGP1(u32 value) Log_DebugPrintf("GP1 clear FIFO"); m_command_tick_event->InvokeEarly(); SynchronizeCRTC(); + + // flush partial writes + if (m_blitter_state == BlitterState::WritingVRAM) + FinishVRAMWrite(); + m_blitter_state = BlitterState::Idle; m_command_total_words = 0; m_vram_transfer = {}; diff --git a/src/core/gpu_commands.cpp b/src/core/gpu_commands.cpp index 4db537e43..db69c3081 100644 --- a/src/core/gpu_commands.cpp +++ b/src/core/gpu_commands.cpp @@ -497,7 +497,7 @@ bool GPU::HandleCopyRectangleCPUToVRAMCommand() void GPU::FinishVRAMWrite() { - if (g_settings.debugging.dump_cpu_to_vram_copies) + if (g_settings.debugging.dump_cpu_to_vram_copies && m_blit_remaining_words == 0) { DumpVRAMToFile(StringUtil::StdStringFromFormat("cpu_to_vram_copy_%u.png", s_cpu_to_vram_dump_id++).c_str(), m_vram_transfer.width, m_vram_transfer.height, sizeof(u16) * m_vram_transfer.width, @@ -509,7 +509,36 @@ void GPU::FinishVRAMWrite() FlushRender(); - UpdateVRAM(m_vram_transfer.x, m_vram_transfer.y, m_vram_transfer.width, m_vram_transfer.height, m_blit_buffer.data()); + if (m_blit_remaining_words == 0) + { + UpdateVRAM(m_vram_transfer.x, m_vram_transfer.y, m_vram_transfer.width, m_vram_transfer.height, + m_blit_buffer.data()); + } + else + { + const u32 num_pixels = ZeroExtend32(m_vram_transfer.width) * ZeroExtend32(m_vram_transfer.height); + const u32 num_words = (num_pixels + 1) / 2; + const u32 transferred_words = num_words - m_blit_remaining_words; + const u32 transferred_pixels = transferred_words * 2; + const u32 transferred_full_rows = transferred_pixels / m_vram_transfer.width; + const u32 transferred_width_last_row = transferred_pixels % m_vram_transfer.width; + + Log_WarningPrintf( + "Partial VRAM write - transfer finished with %u of %u words remaining (%u full rows, %u last row)", + m_blit_remaining_words, num_words, transferred_full_rows, transferred_width_last_row); + + const u8* blit_ptr = reinterpret_cast(m_blit_buffer.data()); + if (transferred_full_rows > 0) + { + UpdateVRAM(m_vram_transfer.x, m_vram_transfer.y, m_vram_transfer.width, transferred_full_rows, blit_ptr); + blit_ptr += (ZeroExtend32(m_vram_transfer.width) * transferred_full_rows) * sizeof(u16); + } + if (transferred_width_last_row > 0) + { + UpdateVRAM(m_vram_transfer.x, m_vram_transfer.y + transferred_full_rows, transferred_width_last_row, 1, blit_ptr); + } + } + m_blit_buffer.clear(); m_vram_transfer = {}; m_blitter_state = BlitterState::Idle;