SPU: Ignore End+Mute flag for noise channels

Fixes the noise effects cutting out too early in Motor Toon Grand Prix.
This commit is contained in:
Stenzek 2024-03-29 15:08:12 +10:00
parent d4d3518e68
commit f9f9447013
No known key found for this signature in database

View file

@ -430,10 +430,10 @@ void SPU::Initialize()
void SPU::CreateOutputStream() void SPU::CreateOutputStream()
{ {
Log_InfoPrintf( Log_InfoFmt("Creating '{}' audio stream, sample rate = {}, channels = {}, buffer = {}, latency = {}, stretching = {}",
"Creating '%s' audio stream, sample rate = %u, channels = %u, buffer = %u, latency = %u, stretching = %s", Settings::GetAudioBackendName(g_settings.audio_backend), static_cast<u32>(SAMPLE_RATE),
Settings::GetAudioBackendName(g_settings.audio_backend), SAMPLE_RATE, NUM_CHANNELS, g_settings.audio_buffer_ms, static_cast<u32>(NUM_CHANNELS), g_settings.audio_buffer_ms, g_settings.audio_output_latency_ms,
g_settings.audio_output_latency_ms, AudioStream::GetStretchModeName(g_settings.audio_stretch_mode)); AudioStream::GetStretchModeName(g_settings.audio_stretch_mode));
s_audio_stream = s_audio_stream =
Host::CreateAudioStream(g_settings.audio_backend, SAMPLE_RATE, NUM_CHANNELS, g_settings.audio_buffer_ms, Host::CreateAudioStream(g_settings.audio_backend, SAMPLE_RATE, NUM_CHANNELS, g_settings.audio_buffer_ms,
@ -656,28 +656,28 @@ u16 SPU::ReadRegister(u32 offset)
return s_reverb_registers.mBASE; return s_reverb_registers.mBASE;
case 0x1F801DA4 - SPU_BASE: case 0x1F801DA4 - SPU_BASE:
Log_TracePrintf("SPU IRQ address -> 0x%04X", ZeroExtend32(s_irq_address)); Log_TraceFmt("SPU IRQ address -> 0x{:04X}", s_irq_address);
return s_irq_address; return s_irq_address;
case 0x1F801DA6 - SPU_BASE: case 0x1F801DA6 - SPU_BASE:
Log_TracePrintf("SPU transfer address register -> 0x%04X", ZeroExtend32(s_transfer_address_reg)); Log_TraceFmt("SPU transfer address register -> 0x{:04X}", s_transfer_address_reg);
return s_transfer_address_reg; return s_transfer_address_reg;
case 0x1F801DA8 - SPU_BASE: case 0x1F801DA8 - SPU_BASE:
Log_TracePrintf("SPU transfer data register read"); Log_TraceFmt("SPU transfer data register read");
return UINT16_C(0xFFFF); return UINT16_C(0xFFFF);
case 0x1F801DAA - SPU_BASE: case 0x1F801DAA - SPU_BASE:
Log_TracePrintf("SPU control register -> 0x%04X", ZeroExtend32(s_SPUCNT.bits)); Log_TraceFmt("SPU control register -> 0x{:04X}", s_SPUCNT.bits);
return s_SPUCNT.bits; return s_SPUCNT.bits;
case 0x1F801DAC - SPU_BASE: case 0x1F801DAC - SPU_BASE:
Log_TracePrintf("SPU transfer control register -> 0x%04X", ZeroExtend32(s_transfer_control.bits)); Log_TraceFmt("SPU transfer control register -> 0x{:04X}", s_transfer_control.bits);
return s_transfer_control.bits; return s_transfer_control.bits;
case 0x1F801DAE - SPU_BASE: case 0x1F801DAE - SPU_BASE:
GeneratePendingSamples(); GeneratePendingSamples();
Log_TracePrintf("SPU status register -> 0x%04X", ZeroExtend32(s_SPUCNT.bits)); Log_TraceFmt("SPU status register -> 0x{:04X}", s_SPUCNT.bits);
return s_SPUSTAT.bits; return s_SPUSTAT.bits;
case 0x1F801DB0 - SPU_BASE: case 0x1F801DB0 - SPU_BASE:
@ -718,7 +718,7 @@ u16 SPU::ReadRegister(u32 offset)
return s_voices[voice_index].right_volume.current_level; return s_voices[voice_index].right_volume.current_level;
} }
Log_DevPrintf("Unknown SPU register read: offset 0x%X (address 0x%08X)", offset, offset | SPU_BASE); Log_DevFmt("Unknown SPU register read: offset 0x{:X} (address 0x{:08X})", offset, offset | SPU_BASE);
return UINT16_C(0xFFFF); return UINT16_C(0xFFFF);
} }
} }
@ -730,7 +730,7 @@ void SPU::WriteRegister(u32 offset, u16 value)
{ {
case 0x1F801D80 - SPU_BASE: case 0x1F801D80 - SPU_BASE:
{ {
Log_DebugPrintf("SPU main volume left <- 0x%04X", ZeroExtend32(value)); Log_DebugFmt("SPU main volume left <- 0x{:04X}", value);
GeneratePendingSamples(); GeneratePendingSamples();
s_main_volume_left_reg.bits = value; s_main_volume_left_reg.bits = value;
s_main_volume_left.Reset(s_main_volume_left_reg); s_main_volume_left.Reset(s_main_volume_left_reg);
@ -739,7 +739,7 @@ void SPU::WriteRegister(u32 offset, u16 value)
case 0x1F801D82 - SPU_BASE: case 0x1F801D82 - SPU_BASE:
{ {
Log_DebugPrintf("SPU main volume right <- 0x%04X", ZeroExtend32(value)); Log_DebugFmt("SPU main volume right <- 0x{:04X}", value);
GeneratePendingSamples(); GeneratePendingSamples();
s_main_volume_right_reg.bits = value; s_main_volume_right_reg.bits = value;
s_main_volume_right.Reset(s_main_volume_right_reg); s_main_volume_right.Reset(s_main_volume_right_reg);
@ -748,7 +748,7 @@ void SPU::WriteRegister(u32 offset, u16 value)
case 0x1F801D84 - SPU_BASE: case 0x1F801D84 - SPU_BASE:
{ {
Log_DebugPrintf("SPU reverb output volume left <- 0x%04X", ZeroExtend32(value)); Log_DebugFmt("SPU reverb output volume left <- 0x{:04X}", value);
GeneratePendingSamples(); GeneratePendingSamples();
s_reverb_registers.vLOUT = value; s_reverb_registers.vLOUT = value;
return; return;
@ -756,7 +756,7 @@ void SPU::WriteRegister(u32 offset, u16 value)
case 0x1F801D86 - SPU_BASE: case 0x1F801D86 - SPU_BASE:
{ {
Log_DebugPrintf("SPU reverb output volume right <- 0x%04X", ZeroExtend32(value)); Log_DebugFmt("SPU reverb output volume right <- 0x{:04X}", value);
GeneratePendingSamples(); GeneratePendingSamples();
s_reverb_registers.vROUT = value; s_reverb_registers.vROUT = value;
return; return;
@ -764,7 +764,7 @@ void SPU::WriteRegister(u32 offset, u16 value)
case 0x1F801D88 - SPU_BASE: case 0x1F801D88 - SPU_BASE:
{ {
Log_DebugPrintf("SPU key on low <- 0x%04X", ZeroExtend32(value)); Log_DebugFmt("SPU key on low <- 0x{:04X}", value);
GeneratePendingSamples(); GeneratePendingSamples();
s_key_on_register = (s_key_on_register & 0xFFFF0000) | ZeroExtend32(value); s_key_on_register = (s_key_on_register & 0xFFFF0000) | ZeroExtend32(value);
} }
@ -772,7 +772,7 @@ void SPU::WriteRegister(u32 offset, u16 value)
case 0x1F801D8A - SPU_BASE: case 0x1F801D8A - SPU_BASE:
{ {
Log_DebugPrintf("SPU key on high <- 0x%04X", ZeroExtend32(value)); Log_DebugFmt("SPU key on high <- 0x{:04X}", value);
GeneratePendingSamples(); GeneratePendingSamples();
s_key_on_register = (s_key_on_register & 0x0000FFFF) | (ZeroExtend32(value) << 16); s_key_on_register = (s_key_on_register & 0x0000FFFF) | (ZeroExtend32(value) << 16);
} }
@ -780,7 +780,7 @@ void SPU::WriteRegister(u32 offset, u16 value)
case 0x1F801D8C - SPU_BASE: case 0x1F801D8C - SPU_BASE:
{ {
Log_DebugPrintf("SPU key off low <- 0x%04X", ZeroExtend32(value)); Log_DebugFmt("SPU key off low <- 0x{:04X}", value);
GeneratePendingSamples(); GeneratePendingSamples();
s_key_off_register = (s_key_off_register & 0xFFFF0000) | ZeroExtend32(value); s_key_off_register = (s_key_off_register & 0xFFFF0000) | ZeroExtend32(value);
} }
@ -788,7 +788,7 @@ void SPU::WriteRegister(u32 offset, u16 value)
case 0x1F801D8E - SPU_BASE: case 0x1F801D8E - SPU_BASE:
{ {
Log_DebugPrintf("SPU key off high <- 0x%04X", ZeroExtend32(value)); Log_DebugFmt("SPU key off high <- 0x{:04X}", value);
GeneratePendingSamples(); GeneratePendingSamples();
s_key_off_register = (s_key_off_register & 0x0000FFFF) | (ZeroExtend32(value) << 16); s_key_off_register = (s_key_off_register & 0x0000FFFF) | (ZeroExtend32(value) << 16);
} }
@ -798,7 +798,7 @@ void SPU::WriteRegister(u32 offset, u16 value)
{ {
GeneratePendingSamples(); GeneratePendingSamples();
s_pitch_modulation_enable_register = (s_pitch_modulation_enable_register & 0xFFFF0000) | ZeroExtend32(value); s_pitch_modulation_enable_register = (s_pitch_modulation_enable_register & 0xFFFF0000) | ZeroExtend32(value);
Log_DebugPrintf("SPU pitch modulation enable register <- 0x%08X", s_pitch_modulation_enable_register); Log_DebugFmt("SPU pitch modulation enable register <- 0x{:08X}", s_pitch_modulation_enable_register);
} }
break; break;
@ -807,13 +807,13 @@ void SPU::WriteRegister(u32 offset, u16 value)
GeneratePendingSamples(); GeneratePendingSamples();
s_pitch_modulation_enable_register = s_pitch_modulation_enable_register =
(s_pitch_modulation_enable_register & 0x0000FFFF) | (ZeroExtend32(value) << 16); (s_pitch_modulation_enable_register & 0x0000FFFF) | (ZeroExtend32(value) << 16);
Log_DebugPrintf("SPU pitch modulation enable register <- 0x%08X", s_pitch_modulation_enable_register); Log_DebugFmt("SPU pitch modulation enable register <- 0x{:08X}", s_pitch_modulation_enable_register);
} }
break; break;
case 0x1F801D94 - SPU_BASE: case 0x1F801D94 - SPU_BASE:
{ {
Log_DebugPrintf("SPU noise mode register <- 0x%04X", ZeroExtend32(value)); Log_DebugFmt("SPU noise mode register <- 0x{:04X}", value);
GeneratePendingSamples(); GeneratePendingSamples();
s_noise_mode_register = (s_noise_mode_register & 0xFFFF0000) | ZeroExtend32(value); s_noise_mode_register = (s_noise_mode_register & 0xFFFF0000) | ZeroExtend32(value);
} }
@ -821,7 +821,7 @@ void SPU::WriteRegister(u32 offset, u16 value)
case 0x1F801D96 - SPU_BASE: case 0x1F801D96 - SPU_BASE:
{ {
Log_DebugPrintf("SPU noise mode register <- 0x%04X", ZeroExtend32(value)); Log_DebugFmt("SPU noise mode register <- 0x{:04X}", value);
GeneratePendingSamples(); GeneratePendingSamples();
s_noise_mode_register = (s_noise_mode_register & 0x0000FFFF) | (ZeroExtend32(value) << 16); s_noise_mode_register = (s_noise_mode_register & 0x0000FFFF) | (ZeroExtend32(value) << 16);
} }
@ -829,7 +829,7 @@ void SPU::WriteRegister(u32 offset, u16 value)
case 0x1F801D98 - SPU_BASE: case 0x1F801D98 - SPU_BASE:
{ {
Log_DebugPrintf("SPU reverb on register <- 0x%04X", ZeroExtend32(value)); Log_DebugFmt("SPU reverb on register <- 0x{:04X}", value);
GeneratePendingSamples(); GeneratePendingSamples();
s_reverb_on_register = (s_reverb_on_register & 0xFFFF0000) | ZeroExtend32(value); s_reverb_on_register = (s_reverb_on_register & 0xFFFF0000) | ZeroExtend32(value);
} }
@ -837,7 +837,7 @@ void SPU::WriteRegister(u32 offset, u16 value)
case 0x1F801D9A - SPU_BASE: case 0x1F801D9A - SPU_BASE:
{ {
Log_DebugPrintf("SPU reverb on register <- 0x%04X", ZeroExtend32(value)); Log_DebugFmt("SPU reverb on register <- 0x{:04X}", value);
GeneratePendingSamples(); GeneratePendingSamples();
s_reverb_on_register = (s_reverb_on_register & 0x0000FFFF) | (ZeroExtend32(value) << 16); s_reverb_on_register = (s_reverb_on_register & 0x0000FFFF) | (ZeroExtend32(value) << 16);
} }
@ -845,7 +845,7 @@ void SPU::WriteRegister(u32 offset, u16 value)
case 0x1F801DA2 - SPU_BASE: case 0x1F801DA2 - SPU_BASE:
{ {
Log_DebugPrintf("SPU reverb base address < 0x%04X", ZeroExtend32(value)); Log_DebugFmt("SPU reverb base address < 0x{:04X}", value);
GeneratePendingSamples(); GeneratePendingSamples();
s_reverb_registers.mBASE = value; s_reverb_registers.mBASE = value;
s_reverb_base_address = ZeroExtend32(value << 2) & 0x3FFFFu; s_reverb_base_address = ZeroExtend32(value << 2) & 0x3FFFFu;
@ -855,7 +855,7 @@ void SPU::WriteRegister(u32 offset, u16 value)
case 0x1F801DA4 - SPU_BASE: case 0x1F801DA4 - SPU_BASE:
{ {
Log_DebugPrintf("SPU IRQ address register <- 0x%04X", ZeroExtend32(value)); Log_DebugFmt("SPU IRQ address register <- 0x{:04X}", value);
GeneratePendingSamples(); GeneratePendingSamples();
s_irq_address = value; s_irq_address = value;
@ -867,14 +867,14 @@ void SPU::WriteRegister(u32 offset, u16 value)
case 0x1F801DA6 - SPU_BASE: case 0x1F801DA6 - SPU_BASE:
{ {
Log_DebugPrintf("SPU transfer address register <- 0x%04X", ZeroExtend32(value)); Log_DebugFmt("SPU transfer address register <- 0x{:04X}", value);
s_transfer_event->InvokeEarly(); s_transfer_event->InvokeEarly();
s_transfer_address_reg = value; s_transfer_address_reg = value;
s_transfer_address = ZeroExtend32(value) * 8; s_transfer_address = ZeroExtend32(value) * 8;
if (IsRAMIRQTriggerable() && CheckRAMIRQ(s_transfer_address)) if (IsRAMIRQTriggerable() && CheckRAMIRQ(s_transfer_address))
{ {
Log_DebugPrintf("Trigger IRQ @ %08X %04X from transfer address reg set", s_transfer_address, Log_DebugFmt("Trigger IRQ @ {:08X} {:04X} from transfer address reg set", s_transfer_address,
s_transfer_address / 8); s_transfer_address / 8);
TriggerRAMIRQ(); TriggerRAMIRQ();
} }
return; return;
@ -882,8 +882,8 @@ void SPU::WriteRegister(u32 offset, u16 value)
case 0x1F801DA8 - SPU_BASE: case 0x1F801DA8 - SPU_BASE:
{ {
Log_TracePrintf("SPU transfer data register <- 0x%04X (RAM offset 0x%08X)", ZeroExtend32(value), Log_TraceFmt("SPU transfer data register <- 0x{:04X} (RAM offset 0x{:08X})", ZeroExtend32(value),
s_transfer_address); s_transfer_address);
ManualTransferWrite(value); ManualTransferWrite(value);
return; return;
@ -891,7 +891,7 @@ void SPU::WriteRegister(u32 offset, u16 value)
case 0x1F801DAA - SPU_BASE: case 0x1F801DAA - SPU_BASE:
{ {
Log_DebugPrintf("SPU control register <- 0x%04X", ZeroExtend32(value)); Log_DebugFmt("SPU control register <- 0x{:04X}", value);
GeneratePendingSamples(); GeneratePendingSamples();
const SPUCNT new_value{value}; const SPUCNT new_value{value};
@ -905,14 +905,14 @@ void SPU::WriteRegister(u32 offset, u16 value)
{ {
// I would guess on the console it would gradually write the FIFO out. Hopefully nothing relies on this // I would guess on the console it would gradually write the FIFO out. Hopefully nothing relies on this
// level of timing granularity if we force it all out here. // level of timing granularity if we force it all out here.
Log_WarningPrintf("Draining write SPU transfer FIFO with %u bytes left", s_transfer_fifo.GetSize()); Log_WarningFmt("Draining write SPU transfer FIFO with {} bytes left", s_transfer_fifo.GetSize());
TickCount ticks = std::numeric_limits<TickCount>::max(); TickCount ticks = std::numeric_limits<TickCount>::max();
ExecuteFIFOWriteToRAM(ticks); ExecuteFIFOWriteToRAM(ticks);
DebugAssert(s_transfer_fifo.IsEmpty()); DebugAssert(s_transfer_fifo.IsEmpty());
} }
else else
{ {
Log_DebugPrintf("Clearing read SPU transfer FIFO with %u bytes left", s_transfer_fifo.GetSize()); Log_DebugFmt("Clearing read SPU transfer FIFO with {} bytes left", s_transfer_fifo.GetSize());
s_transfer_fifo.Clear(); s_transfer_fifo.Clear();
} }
} }
@ -947,14 +947,14 @@ void SPU::WriteRegister(u32 offset, u16 value)
case 0x1F801DAC - SPU_BASE: case 0x1F801DAC - SPU_BASE:
{ {
Log_DebugPrintf("SPU transfer control register <- 0x%04X", ZeroExtend32(value)); Log_DebugFmt("SPU transfer control register <- 0x{:04X}", value);
s_transfer_control.bits = value; s_transfer_control.bits = value;
return; return;
} }
case 0x1F801DB0 - SPU_BASE: case 0x1F801DB0 - SPU_BASE:
{ {
Log_DebugPrintf("SPU left cd audio register <- 0x%04X", ZeroExtend32(value)); Log_DebugFmt("SPU left cd audio register <- 0x{:04X}", value);
GeneratePendingSamples(); GeneratePendingSamples();
s_cd_audio_volume_left = value; s_cd_audio_volume_left = value;
} }
@ -962,7 +962,7 @@ void SPU::WriteRegister(u32 offset, u16 value)
case 0x1F801DB2 - SPU_BASE: case 0x1F801DB2 - SPU_BASE:
{ {
Log_DebugPrintf("SPU right cd audio register <- 0x%04X", ZeroExtend32(value)); Log_DebugFmt("SPU right cd audio register <- 0x{:04X}", value);
GeneratePendingSamples(); GeneratePendingSamples();
s_cd_audio_volume_right = value; s_cd_audio_volume_right = value;
} }
@ -971,7 +971,7 @@ void SPU::WriteRegister(u32 offset, u16 value)
case 0x1F801DB4 - SPU_BASE: case 0x1F801DB4 - SPU_BASE:
{ {
// External volumes aren't used, so don't bother syncing. // External volumes aren't used, so don't bother syncing.
Log_DebugPrintf("SPU left external volume register <- 0x%04X", ZeroExtend32(value)); Log_DebugFmt("SPU left external volume register <- 0x{:04X}", value);
s_external_volume_left = value; s_external_volume_left = value;
} }
break; break;
@ -979,7 +979,7 @@ void SPU::WriteRegister(u32 offset, u16 value)
case 0x1F801DB6 - SPU_BASE: case 0x1F801DB6 - SPU_BASE:
{ {
// External volumes aren't used, so don't bother syncing. // External volumes aren't used, so don't bother syncing.
Log_DebugPrintf("SPU right external volume register <- 0x%04X", ZeroExtend32(value)); Log_DebugFmt("SPU right external volume register <- 0x{:04X}", value);
s_external_volume_right = value; s_external_volume_right = value;
} }
break; break;
@ -1001,14 +1001,14 @@ void SPU::WriteRegister(u32 offset, u16 value)
if (offset >= (0x1F801DC0 - SPU_BASE) && offset < (0x1F801E00 - SPU_BASE)) if (offset >= (0x1F801DC0 - SPU_BASE) && offset < (0x1F801E00 - SPU_BASE))
{ {
const u32 reg = (offset - (0x1F801DC0 - SPU_BASE)) / 2; const u32 reg = (offset - (0x1F801DC0 - SPU_BASE)) / 2;
Log_DebugPrintf("SPU reverb register %u <- 0x%04X", reg, value); Log_DebugFmt("SPU reverb register {} <- 0x{:04X}", reg, value);
GeneratePendingSamples(); GeneratePendingSamples();
s_reverb_registers.rev[reg] = value; s_reverb_registers.rev[reg] = value;
return; return;
} }
Log_DevPrintf("Unknown SPU register write: offset 0x%X (address 0x%08X) value 0x%04X", offset, offset | SPU_BASE, Log_DevFmt("Unknown SPU register write: offset 0x{:X} (address 0x{:08X}) value 0x{:04X}", offset,
ZeroExtend32(value)); offset | SPU_BASE, value);
return; return;
} }
} }
@ -1025,7 +1025,7 @@ u16 SPU::ReadVoiceRegister(u32 offset)
if (reg_index >= 6 && (voice.IsOn() || s_key_on_register & (1u << voice_index))) if (reg_index >= 6 && (voice.IsOn() || s_key_on_register & (1u << voice_index)))
GeneratePendingSamples(); GeneratePendingSamples();
Log_TracePrintf("Read voice %u register %u -> 0x%02X", voice_index, reg_index, voice.regs.index[reg_index]); Log_TraceFmt("Read voice {} register {} -> 0x{:02X}", voice_index, reg_index, voice.regs.index[reg_index]);
return voice.regs.index[reg_index]; return voice.regs.index[reg_index];
} }
@ -1044,7 +1044,7 @@ void SPU::WriteVoiceRegister(u32 offset, u16 value)
{ {
case 0x00: // volume left case 0x00: // volume left
{ {
Log_DebugPrintf("SPU voice %u volume left <- 0x%04X", voice_index, value); Log_DebugFmt("SPU voice {} volume left <- 0x{:04X}", voice_index, value);
voice.regs.volume_left.bits = value; voice.regs.volume_left.bits = value;
voice.left_volume.Reset(voice.regs.volume_left); voice.left_volume.Reset(voice.regs.volume_left);
} }
@ -1052,7 +1052,7 @@ void SPU::WriteVoiceRegister(u32 offset, u16 value)
case 0x02: // volume right case 0x02: // volume right
{ {
Log_DebugPrintf("SPU voice %u volume right <- 0x%04X", voice_index, value); Log_DebugFmt("SPU voice {} volume right <- 0x{:04X}", voice_index, value);
voice.regs.volume_right.bits = value; voice.regs.volume_right.bits = value;
voice.right_volume.Reset(voice.regs.volume_right); voice.right_volume.Reset(voice.regs.volume_right);
} }
@ -1060,21 +1060,21 @@ void SPU::WriteVoiceRegister(u32 offset, u16 value)
case 0x04: // sample rate case 0x04: // sample rate
{ {
Log_DebugPrintf("SPU voice %u ADPCM sample rate <- 0x%04X", voice_index, value); Log_DebugFmt("SPU voice {} ADPCM sample rate <- 0x{:04X}", voice_index, value);
voice.regs.adpcm_sample_rate = value; voice.regs.adpcm_sample_rate = value;
} }
break; break;
case 0x06: // start address case 0x06: // start address
{ {
Log_DebugPrintf("SPU voice %u ADPCM start address <- 0x%04X", voice_index, value); Log_DebugFmt("SPU voice {} ADPCM start address <- 0x{:04X}", voice_index, value);
voice.regs.adpcm_start_address = value; voice.regs.adpcm_start_address = value;
} }
break; break;
case 0x08: // adsr low case 0x08: // adsr low
{ {
Log_DebugPrintf("SPU voice %u ADSR low <- 0x%04X (was 0x%04X)", voice_index, value, voice.regs.adsr.bits_low); Log_DebugFmt("SPU voice {} ADSR low <- 0x{:04X} (was 0x{:04X})", voice_index, value, voice.regs.adsr.bits_low);
voice.regs.adsr.bits_low = value; voice.regs.adsr.bits_low = value;
if (voice.IsOn()) if (voice.IsOn())
voice.UpdateADSREnvelope(); voice.UpdateADSREnvelope();
@ -1083,7 +1083,7 @@ void SPU::WriteVoiceRegister(u32 offset, u16 value)
case 0x0A: // adsr high case 0x0A: // adsr high
{ {
Log_DebugPrintf("SPU voice %u ADSR high <- 0x%04X (was 0x%04X)", voice_index, value, voice.regs.adsr.bits_low); Log_DebugFmt("SPU voice {} ADSR high <- 0x{:04X} (was 0x{:04X})", voice_index, value, voice.regs.adsr.bits_low);
voice.regs.adsr.bits_high = value; voice.regs.adsr.bits_high = value;
if (voice.IsOn()) if (voice.IsOn())
voice.UpdateADSREnvelope(); voice.UpdateADSREnvelope();
@ -1092,7 +1092,7 @@ void SPU::WriteVoiceRegister(u32 offset, u16 value)
case 0x0C: // adsr volume case 0x0C: // adsr volume
{ {
Log_DebugPrintf("SPU voice %u ADSR volume <- 0x%04X (was 0x%04X)", voice_index, value, voice.regs.adsr_volume); Log_DebugFmt("SPU voice {} ADSR volume <- 0x{:04X} (was 0x{:04X})", voice_index, value, voice.regs.adsr_volume);
voice.regs.adsr_volume = value; voice.regs.adsr_volume = value;
} }
break; break;
@ -1106,22 +1106,22 @@ void SPU::WriteVoiceRegister(u32 offset, u16 value)
// - Valkyrie Profile // - Valkyrie Profile
const bool ignore_loop_address = voice.IsOn() && !voice.is_first_block; const bool ignore_loop_address = voice.IsOn() && !voice.is_first_block;
Log_DebugPrintf("SPU voice %u ADPCM repeat address <- 0x%04X", voice_index, value); Log_DebugFmt("SPU voice {} ADPCM repeat address <- 0x{:04X}", voice_index, value);
voice.regs.adpcm_repeat_address = value; voice.regs.adpcm_repeat_address = value;
voice.ignore_loop_address |= ignore_loop_address; voice.ignore_loop_address |= ignore_loop_address;
if (!ignore_loop_address) if (!ignore_loop_address)
{ {
Log_DevPrintf("Not ignoring loop address, the ADPCM repeat address of 0x%04X for voice %u will be overwritten", Log_DevFmt("Not ignoring loop address, the ADPCM repeat address of 0x{:04X} for voice {} will be overwritten",
value, voice_index); value, voice_index);
} }
} }
break; break;
default: default:
{ {
Log_ErrorPrintf("Unknown SPU voice %u register write: offset 0x%X (address 0x%08X) value 0x%04X", offset, Log_ErrorFmt("Unknown SPU voice {} register write: offset 0x%X (address 0x{:08X}) value 0x{:04X}", offset,
voice_index, offset | SPU_BASE, ZeroExtend32(value)); voice_index, offset | SPU_BASE, ZeroExtend32(value));
} }
break; break;
} }
@ -1168,7 +1168,7 @@ void SPU::CheckForLateRAMIRQs()
{ {
if (CheckRAMIRQ(s_transfer_address)) if (CheckRAMIRQ(s_transfer_address))
{ {
Log_DebugPrintf("Trigger IRQ @ %08X %04X from late transfer", s_transfer_address, s_transfer_address / 8); Log_DebugFmt("Trigger IRQ @ {:08X} {:04X} from late transfer", s_transfer_address, s_transfer_address / 8);
TriggerRAMIRQ(); TriggerRAMIRQ();
return; return;
} }
@ -1184,7 +1184,7 @@ void SPU::CheckForLateRAMIRQs()
const u32 address = v.current_address * 8; const u32 address = v.current_address * 8;
if (CheckRAMIRQ(address) || CheckRAMIRQ((address + 8) & RAM_MASK)) if (CheckRAMIRQ(address) || CheckRAMIRQ((address + 8) & RAM_MASK))
{ {
Log_DebugPrintf("Trigger IRQ @ %08X %04X from late", address, address / 8); Log_DebugFmt("Trigger IRQ @ {:08X} ({:04X}) from late", address, address / 8);
TriggerRAMIRQ(); TriggerRAMIRQ();
return; return;
} }
@ -1194,11 +1194,11 @@ void SPU::CheckForLateRAMIRQs()
void SPU::WriteToCaptureBuffer(u32 index, s16 value) void SPU::WriteToCaptureBuffer(u32 index, s16 value)
{ {
const u32 ram_address = (index * CAPTURE_BUFFER_SIZE_PER_CHANNEL) | ZeroExtend16(s_capture_buffer_position); const u32 ram_address = (index * CAPTURE_BUFFER_SIZE_PER_CHANNEL) | ZeroExtend16(s_capture_buffer_position);
// Log_DebugPrintf("write to capture buffer %u (0x%08X) <- 0x%04X", index, ram_address, u16(value)); // Log_DebugFmt("write to capture buffer {} (0x{:08X}) <- 0x{:04X}", index, ram_address, u16(value));
std::memcpy(&s_ram[ram_address], &value, sizeof(value)); std::memcpy(&s_ram[ram_address], &value, sizeof(value));
if (IsRAMIRQTriggerable() && CheckRAMIRQ(ram_address)) if (IsRAMIRQTriggerable() && CheckRAMIRQ(ram_address))
{ {
Log_DebugPrintf("Trigger IRQ @ %08X %04X from capture buffer", ram_address, ram_address / 8); Log_DebugFmt("Trigger IRQ @ {:08X} ({:04X}) from capture buffer", ram_address, ram_address / 8);
TriggerRAMIRQ(); TriggerRAMIRQ();
} }
} }
@ -1222,7 +1222,7 @@ ALWAYS_INLINE_RELEASE void SPU::ExecuteFIFOReadFromRAM(TickCount& ticks)
if (IsRAMIRQTriggerable() && CheckRAMIRQ(s_transfer_address)) if (IsRAMIRQTriggerable() && CheckRAMIRQ(s_transfer_address))
{ {
Log_DebugPrintf("Trigger IRQ @ %08X %04X from transfer read", s_transfer_address, s_transfer_address / 8); Log_DebugFmt("Trigger IRQ @ {:08X} ({:04X}) from transfer read", s_transfer_address, s_transfer_address / 8);
TriggerRAMIRQ(); TriggerRAMIRQ();
} }
} }
@ -1239,7 +1239,7 @@ ALWAYS_INLINE_RELEASE void SPU::ExecuteFIFOWriteToRAM(TickCount& ticks)
if (IsRAMIRQTriggerable() && CheckRAMIRQ(s_transfer_address)) if (IsRAMIRQTriggerable() && CheckRAMIRQ(s_transfer_address))
{ {
Log_DebugPrintf("Trigger IRQ @ %08X %04X from transfer write", s_transfer_address, s_transfer_address / 8); Log_DebugFmt("Trigger IRQ @ {:08X} ({:04X}) from transfer write", s_transfer_address, s_transfer_address / 8);
TriggerRAMIRQ(); TriggerRAMIRQ();
} }
} }
@ -1303,7 +1303,7 @@ void SPU::ManualTransferWrite(u16 value)
{ {
if (!s_transfer_fifo.IsEmpty() && s_SPUCNT.ram_transfer_mode != RAMTransferMode::DMARead) if (!s_transfer_fifo.IsEmpty() && s_SPUCNT.ram_transfer_mode != RAMTransferMode::DMARead)
{ {
Log_WarningPrintf("FIFO not empty on manual SPU write, draining to hopefully avoid corruption. Game is silly."); Log_WarningPrint("FIFO not empty on manual SPU write, draining to hopefully avoid corruption. Game is silly.");
if (s_SPUCNT.ram_transfer_mode != RAMTransferMode::Stopped) if (s_SPUCNT.ram_transfer_mode != RAMTransferMode::Stopped)
ExecuteTransfer(nullptr, std::numeric_limits<s32>::max(), 0); ExecuteTransfer(nullptr, std::numeric_limits<s32>::max(), 0);
} }
@ -1313,7 +1313,7 @@ void SPU::ManualTransferWrite(u16 value)
if (IsRAMIRQTriggerable() && CheckRAMIRQ(s_transfer_address)) if (IsRAMIRQTriggerable() && CheckRAMIRQ(s_transfer_address))
{ {
Log_DebugPrintf("Trigger IRQ @ %08X %04X from manual write", s_transfer_address, s_transfer_address / 8); Log_DebugFmt("Trigger IRQ @ {:08X} ({:04X}) from manual write", s_transfer_address, s_transfer_address / 8);
TriggerRAMIRQ(); TriggerRAMIRQ();
} }
} }
@ -1431,7 +1431,7 @@ void SPU::DMARead(u32* words, u32 word_count)
fill_value = halfwords[size - 1]; fill_value = halfwords[size - 1];
} }
Log_WarningPrintf("Transfer FIFO underflow, filling with 0x%04X", fill_value); Log_WarningFmt("Transfer FIFO underflow, filling with 0x{:04X}", fill_value);
std::fill_n(&halfwords[size], halfword_count - size, fill_value); std::fill_n(&halfwords[size], halfword_count - size, fill_value);
} }
else else
@ -1452,7 +1452,7 @@ void SPU::DMAWrite(const u32* words, u32 word_count)
s_transfer_fifo.PushRange(halfwords, words_to_transfer); s_transfer_fifo.PushRange(halfwords, words_to_transfer);
if (words_to_transfer != halfword_count) [[unlikely]] if (words_to_transfer != halfword_count) [[unlikely]]
Log_WarningPrintf("Transfer FIFO overflow, dropping %u halfwords", halfword_count - words_to_transfer); Log_WarningFmt("Transfer FIFO overflow, dropping {} halfwords", halfword_count - words_to_transfer);
UpdateDMARequest(); UpdateDMARequest();
UpdateTransferEvent(); UpdateTransferEvent();
@ -1491,7 +1491,7 @@ bool SPU::StartDumpingAudio(const char* filename)
s_dump_writer = std::make_unique<WAVWriter>(); s_dump_writer = std::make_unique<WAVWriter>();
if (!s_dump_writer->Open(filename, SAMPLE_RATE, 2)) if (!s_dump_writer->Open(filename, SAMPLE_RATE, 2))
{ {
Log_ErrorPrintf("Failed to open '%s'", filename); Log_ErrorFmt("Failed to open '{}'", filename);
s_dump_writer.reset(); s_dump_writer.reset();
return false; return false;
} }
@ -1511,7 +1511,7 @@ bool SPU::StartDumpingAudio(const char* filename)
const std::string voice_filename = Path::ReplaceExtension(filename, new_suffix); const std::string voice_filename = Path::ReplaceExtension(filename, new_suffix);
if (!s_voice_dump_writers[i]->Open(voice_filename.c_str(), SAMPLE_RATE, 2)) if (!s_voice_dump_writers[i]->Open(voice_filename.c_str(), SAMPLE_RATE, 2))
{ {
Log_ErrorPrintf("Failed to open voice dump filename '%s'", voice_filename.c_str()); Log_ErrorFmt("Failed to open voice dump filename '{}'", voice_filename.c_str());
s_voice_dump_writers[i].reset(); s_voice_dump_writers[i].reset();
} }
} }
@ -1916,7 +1916,7 @@ void SPU::ReadADPCMBlock(u16 address, ADPCMBlock* block)
u32 ram_address = (ZeroExtend32(address) * 8) & RAM_MASK; u32 ram_address = (ZeroExtend32(address) * 8) & RAM_MASK;
if (IsRAMIRQTriggerable() && (CheckRAMIRQ(ram_address) || CheckRAMIRQ((ram_address + 8) & RAM_MASK))) if (IsRAMIRQTriggerable() && (CheckRAMIRQ(ram_address) || CheckRAMIRQ((ram_address + 8) & RAM_MASK)))
{ {
Log_DebugPrintf("Trigger IRQ @ %08X %04X from ADPCM reader", ram_address, ram_address / 8); Log_DebugFmt("Trigger IRQ @ {:08X} ({:04X}) from ADPCM reader", ram_address, ram_address / 8);
TriggerRAMIRQ(); TriggerRAMIRQ();
} }
@ -1965,7 +1965,7 @@ ALWAYS_INLINE_RELEASE std::tuple<s32, s32> SPU::SampleVoice(u32 voice_index)
if (voice.current_block_flags.loop_start && !voice.ignore_loop_address) if (voice.current_block_flags.loop_start && !voice.ignore_loop_address)
{ {
Log_TracePrintf("Voice %u loop start @ 0x%08X", voice_index, ZeroExtend32(voice.current_address)); Log_TraceFmt("Voice {} loop start @ 0x{:08X}", voice_index, voice.current_address);
voice.regs.adpcm_repeat_address = voice.current_address; voice.regs.adpcm_repeat_address = voice.current_address;
} }
} }
@ -2024,12 +2024,20 @@ ALWAYS_INLINE_RELEASE std::tuple<s32, s32> SPU::SampleVoice(u32 voice_index)
if (!voice.current_block_flags.loop_repeat) if (!voice.current_block_flags.loop_repeat)
{ {
Log_TracePrintf("Voice %u loop end+mute @ 0x%08X", voice_index, ZeroExtend32(voice.current_address)); // End+Mute flags are ignored when noise is enabled. ADPCM data is still decoded.
voice.ForceOff(); if (!IsVoiceNoiseEnabled(voice_index))
{
Log_TraceFmt("Voice {} loop end+mute @ 0x{:04X}", voice_index, voice.current_address);
voice.ForceOff();
}
else
{
Log_TraceFmt("IGNORING voice {} loop end+mute @ 0x{:04X}", voice_index, voice.current_address);
}
} }
else else
{ {
Log_TracePrintf("Voice %u loop end+repeat @ 0x%08X", voice_index, ZeroExtend32(voice.current_address)); Log_TraceFmt("Voice {} loop end+repeat @ 0x{:04X}", voice_index, voice.current_address);
} }
} }
} }