From 49b5ea3d0766a790d417e8923bf636bd575b1d5a Mon Sep 17 00:00:00 2001 From: Stenzek Date: Sun, 21 Sep 2025 16:20:11 +1000 Subject: [PATCH] DMA: Skip chopping on tiny blocks My theory is if the DMAC uses burst transfers, then chopping will have no effect. Dotchi Mecha! transfers out the CD header then data separately, and if the first transfer is delayed ends up in a read loop. I suspect our handling of chopping is wrong anyway, since the calculated cycle counts for a sector transfer are way too high regardless... --- src/core/dma.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/core/dma.cpp b/src/core/dma.cpp index bf6ed216e..9906c92d7 100644 --- a/src/core/dma.cpp +++ b/src/core/dma.cpp @@ -394,12 +394,12 @@ void DMA::WriteRegister(u32 offset, u32 value) // Figure out how roughly many CPU cycles it'll take for the transfer to complete, and delay the transfer. // Needed for Lagnacure Legend, which sets DICR to enable interrupts after CHCR to kickstart the transfer. // This has an artificial 500 cycle cap, setting it too high causes Namco Museum Vol. 4 and a couple of - // other games to crash... so clearly something is missing here. - const u32 block_words = (1u << state.channel_control.chopping_dma_window_size); + // other games to crash... so clearly something is missing here. Small blocks are similarly excluded, + // Dotchi Mecha! sets up a 3 word transfer for the CD sector header and expects it to complete immediately. const u32 cpu_cycles_per_block = (1u << state.channel_control.chopping_cpu_window_size); - const u32 blocks = state.block_control.manual.word_count / block_words; + const u32 blocks = state.block_control.manual.word_count >> state.channel_control.chopping_dma_window_size; const TickCount delay_cycles = std::min(static_cast(cpu_cycles_per_block * blocks), 500); - if (delay_cycles > 1 && true) + if (state.block_control.manual.word_count > 4 && delay_cycles > 1) { DEV_LOG("Delaying {} transfer by {} cycles due to chopping", static_cast(channel_index), delay_cycles);