mirror of
https://github.com/RetroDECK/Duckstation.git
synced 2024-11-29 00:55:41 +00:00
SPU: Bypass FIFO for direct memory writes
Aconcagua writes a single halfword with transfers halted, but never enables DMA.. so when it eventually does later on, there's an extra halfword written out to memory, which corrupted part of a sound effect.
This commit is contained in:
parent
2c2304b5b7
commit
1aa3be70c7
|
@ -1195,7 +1195,7 @@ void SPU::IncrementCaptureBufferPosition()
|
||||||
s_SPUSTAT.second_half_capture_buffer = s_capture_buffer_position >= (CAPTURE_BUFFER_SIZE_PER_CHANNEL / 2);
|
s_SPUSTAT.second_half_capture_buffer = s_capture_buffer_position >= (CAPTURE_BUFFER_SIZE_PER_CHANNEL / 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ALWAYS_INLINE SPU::ExecuteFIFOReadFromRAM(TickCount& ticks)
|
ALWAYS_INLINE_RELEASE void SPU::ExecuteFIFOReadFromRAM(TickCount& ticks)
|
||||||
{
|
{
|
||||||
while (ticks > 0 && !s_transfer_fifo.IsFull())
|
while (ticks > 0 && !s_transfer_fifo.IsFull())
|
||||||
{
|
{
|
||||||
|
@ -1213,7 +1213,7 @@ void ALWAYS_INLINE SPU::ExecuteFIFOReadFromRAM(TickCount& ticks)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ALWAYS_INLINE SPU::ExecuteFIFOWriteToRAM(TickCount& ticks)
|
ALWAYS_INLINE_RELEASE void SPU::ExecuteFIFOWriteToRAM(TickCount& ticks)
|
||||||
{
|
{
|
||||||
while (ticks > 0 && !s_transfer_fifo.IsEmpty())
|
while (ticks > 0 && !s_transfer_fifo.IsEmpty())
|
||||||
{
|
{
|
||||||
|
@ -1233,7 +1233,7 @@ void ALWAYS_INLINE SPU::ExecuteFIFOWriteToRAM(TickCount& ticks)
|
||||||
void SPU::ExecuteTransfer(void* param, TickCount ticks, TickCount ticks_late)
|
void SPU::ExecuteTransfer(void* param, TickCount ticks, TickCount ticks_late)
|
||||||
{
|
{
|
||||||
const RAMTransferMode mode = s_SPUCNT.ram_transfer_mode;
|
const RAMTransferMode mode = s_SPUCNT.ram_transfer_mode;
|
||||||
Assert(mode != RAMTransferMode::Stopped);
|
DebugAssert(mode != RAMTransferMode::Stopped);
|
||||||
|
|
||||||
if (mode == RAMTransferMode::DMARead)
|
if (mode == RAMTransferMode::DMARead)
|
||||||
{
|
{
|
||||||
|
@ -1286,14 +1286,21 @@ void SPU::ExecuteTransfer(void* param, TickCount ticks, TickCount ticks_late)
|
||||||
|
|
||||||
void SPU::ManualTransferWrite(u16 value)
|
void SPU::ManualTransferWrite(u16 value)
|
||||||
{
|
{
|
||||||
if (s_transfer_fifo.IsFull())
|
if (!s_transfer_fifo.IsEmpty() && s_SPUCNT.ram_transfer_mode != RAMTransferMode::DMARead)
|
||||||
{
|
{
|
||||||
Log_WarningPrintf("FIFO full, dropping write of 0x%04X", value);
|
Log_WarningPrintf("FIFO not empty on manual SPU write, draining to hopefully avoid corruption. Game is silly.");
|
||||||
return;
|
if (s_SPUCNT.ram_transfer_mode != RAMTransferMode::Stopped)
|
||||||
|
ExecuteTransfer(nullptr, std::numeric_limits<s32>::max(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
s_transfer_fifo.Push(value);
|
std::memcpy(&s_ram[s_transfer_address], &value, sizeof(u16));
|
||||||
UpdateTransferEvent();
|
s_transfer_address = (s_transfer_address + sizeof(u16)) & RAM_MASK;
|
||||||
|
|
||||||
|
if (IsRAMIRQTriggerable() && CheckRAMIRQ(s_transfer_address))
|
||||||
|
{
|
||||||
|
Log_DebugPrintf("Trigger IRQ @ %08X %04X from manual write", s_transfer_address, s_transfer_address / 8);
|
||||||
|
TriggerRAMIRQ();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SPU::UpdateTransferEvent()
|
void SPU::UpdateTransferEvent()
|
||||||
|
|
Loading…
Reference in a new issue