From 6b4298541cc1aa806ab2dab4a542f34cc03cc151 Mon Sep 17 00:00:00 2001 From: Connor McLaughlin Date: Fri, 18 Oct 2019 00:23:11 +1000 Subject: [PATCH] DMA: Fix DICR write breaking FMVs in FF7 --- src/core/dma.cpp | 40 ++++++++++++++++++++++++++++++---------- src/core/dma.h | 5 ++--- 2 files changed, 32 insertions(+), 13 deletions(-) diff --git a/src/core/dma.cpp b/src/core/dma.cpp index 0c2564936..c9cdda6ad 100644 --- a/src/core/dma.cpp +++ b/src/core/dma.cpp @@ -30,7 +30,6 @@ bool DMA::Initialize(System* system, Bus* bus, InterruptController* interrupt_co void DMA::Reset() { - m_transfer_ticks = 0; m_transfer_in_progress = false; m_state = {}; m_DPCR.bits = 0x07654321; @@ -61,11 +60,20 @@ u32 DMA::ReadRegister(u32 offset) switch (offset & UINT32_C(0x0F)) { case 0x00: + { + Log_TracePrintf("DMA%u base address -> 0x%08X", channel_index, m_state[channel_index].base_address); return m_state[channel_index].base_address; + } case 0x04: + { + Log_TracePrintf("DMA%u block control -> 0x%08X", channel_index, m_state[channel_index].block_control.bits); return m_state[channel_index].block_control.bits; + } case 0x08: + { + Log_TracePrintf("DMA%u channel control -> 0x%08X", channel_index, m_state[channel_index].channel_control.bits); return m_state[channel_index].channel_control.bits; + } default: break; } @@ -73,9 +81,15 @@ u32 DMA::ReadRegister(u32 offset) else { if (offset == 0x70) + { + Log_TracePrintf("DPCR -> 0x%08X", m_DPCR.bits); return m_DPCR.bits; + } else if (offset == 0x74) + { + Log_TracePrintf("DPCR -> 0x%08X", m_DPCR.bits); return m_DICR.bits; + } } Log_ErrorPrintf("Unhandled register read: %02X", offset); @@ -133,7 +147,7 @@ void DMA::WriteRegister(u32 offset, u32 value) { Log_TracePrintf("DCIR <- 0x%08X", value); m_DICR.bits = (m_DICR.bits & ~DICR_WRITE_MASK) | (value & DICR_WRITE_MASK); - m_DICR.bits = (m_DICR.bits & ~DICR_RESET_MASK) & (value ^ DICR_RESET_MASK); + m_DICR.bits = m_DICR.bits & ~(value & DICR_RESET_MASK); m_DICR.UpdateMasterFlag(); return; } @@ -186,6 +200,16 @@ bool DMA::CanRunAnyChannels() const return false; } +void DMA::UpdateIRQ() +{ + m_DICR.UpdateMasterFlag(); + if (m_DICR.master_flag) + { + Log_TracePrintf("Firing DMA master interrupt"); + m_interrupt_controller->InterruptRequest(InterruptController::IRQ::DMA); + } +} + void DMA::Transfer() { if (m_transfer_in_progress) @@ -276,8 +300,9 @@ void DMA::TransferChannel(Channel channel) case SyncMode::Request: { - Log_DebugPrintf("DMA%u: Copying %u blocks of size %u %s 0x%08X", static_cast(channel), + Log_DebugPrintf("DMA%u: Copying %u blocks of size %u (%u total words) %s 0x%08X", static_cast(channel), cs.block_control.request.GetBlockCount(), cs.block_control.request.GetBlockSize(), + cs.block_control.request.GetBlockCount() * cs.block_control.request.GetBlockSize(), copy_to_device ? "from" : "to", current_address); const u32 block_size = cs.block_control.request.GetBlockSize(); @@ -320,14 +345,9 @@ void DMA::TransferChannel(Channel channel) cs.channel_control.enable_busy = false; if (m_DICR.IsIRQEnabled(channel)) { - Log_TracePrintf("Set DMA interrupt for channel %u", static_cast(channel)); + Log_DebugPrintf("Set DMA interrupt for channel %u", static_cast(channel)); m_DICR.SetIRQFlag(channel); - m_DICR.UpdateMasterFlag(); - if (m_DICR.master_flag) - { - Log_TracePrintf("Firing DMA interrupt"); - m_interrupt_controller->InterruptRequest(InterruptController::IRQ::DMA); - } + UpdateIRQ(); } } diff --git a/src/core/dma.h b/src/core/dma.h index 42e4d3601..d201e9d16 100644 --- a/src/core/dma.h +++ b/src/core/dma.h @@ -60,6 +60,7 @@ private: // is everything enabled for a channel to operate? bool CanTransferChannel(Channel channel) const; bool CanRunAnyChannels() const; + void UpdateIRQ(); void Transfer(); void TransferChannel(Channel channel); @@ -78,10 +79,8 @@ private: SPU* m_spu = nullptr; MDEC* m_mdec = nullptr; - TickCount m_transfer_ticks = 0; - bool m_transfer_in_progress = false; - std::vector m_transfer_buffer; + bool m_transfer_in_progress = false; struct ChannelState {