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...
pull/3576/head
Stenzek 1 month ago
parent e877ae41b0
commit 49b5ea3d07
No known key found for this signature in database

@ -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. // 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. // 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 // 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. // other games to crash... so clearly something is missing here. Small blocks are similarly excluded,
const u32 block_words = (1u << state.channel_control.chopping_dma_window_size); // 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 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<TickCount>(cpu_cycles_per_block * blocks), 500); const TickCount delay_cycles = std::min(static_cast<TickCount>(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>(channel_index), DEV_LOG("Delaying {} transfer by {} cycles due to chopping", static_cast<Channel>(channel_index),
delay_cycles); delay_cycles);

Loading…
Cancel
Save