Compare commits

...

2 commits

Author SHA1 Message Date
Lionel Flandrin
e9fa58615c SPU: fix CD ram writeback
Fixes Crash Team Racing
2024-03-22 19:08:17 +00:00
Lionel Flandrin
cc78bfbbb8 SPU: don't crash on unexpected register writes 2024-03-22 17:25:48 +00:00
2 changed files with 15 additions and 8 deletions

View file

@ -385,6 +385,10 @@ fn run_cycle(psx: &mut Psx) {
let [cd_left, cd_right] = cd::run_audio_cycle(psx);
// Write CD audio (pre-volume) to the RAM
ram_write(psx, psx.spu.capture_index, cd_left as u16);
ram_write(psx, psx.spu.capture_index | 0x200, cd_right as u16);
if psx.spu.cd_audio_enabled() {
let cd_left = (i32::from(cd_left) * i32::from(psx.spu.cd_volume_left)) >> 15;
let cd_right = (i32::from(cd_right) * i32::from(psx.spu.cd_volume_right)) >> 15;
@ -674,6 +678,7 @@ fn run_reverb_cycle(psx: &mut Psx, (left_in, right_in): (i16, i16)) -> (i16, i16
>> 1,
);
// All-pass filter
let apf_in1 = i32::from(load_reverb_sample(
psx,
psx.spu.regs[regmap::REVERB_APF_LEFT1]
@ -798,7 +803,7 @@ fn run_voice_decoder(psx: &mut Psx, voice: u8) {
// This is important if the IRQ is enabled since it means that it would trigger a bit earlier
// when the block is read.
//
// This is still not entirely cycle accurate, so we could be improved further with more
// This is still not entirely cycle accurate, so it could be further improved with more
// testing. Mednafen's codebase has a few comments giving hints on what could be done. More
// testing required.
if psx.spu[voice].decoder_fifo.len() >= 11 {
@ -831,7 +836,7 @@ fn run_voice_decoder(psx: &mut Psx, voice: u8) {
if psx.spu.irq_enabled() {
// Test current address
check_for_irq(psx, psx.spu[voice].cur_index);
// This is taken from mednafen, not shure why it's necessary
// This is taken from mednafen, not sure why it's necessary
check_for_irq(psx, psx.spu[voice].cur_index & 0x3_fff8);
}
@ -988,11 +993,12 @@ fn store16(psx: &mut Psx, off: u32, val: u16) {
regmap::EXT_VOLUME_RIGHT => (),
// Reverb configuration
regmap::REVERB_APF_OFFSET1..=regmap::REVERB_INPUT_VOLUME_RIGHT => (),
_ => unimplemented!(
"SPU store index {:x} (off = {:x}, abs = {:x})",
_ => warn!(
"SPU store index {:x} (off = {:x}, abs = {:x}): {:x}",
index,
off,
0x1f80_1c00 + off
0x1f80_1c00 + off,
val
),
}
} else if index < 0x130 {
@ -1355,9 +1361,9 @@ impl Voice {
/// Saturating cast from i32 to i16
fn saturate_to_i16(v: i32) -> i16 {
if v < i16::min_value() as i32 {
if v < i32::from(i16::min_value()) {
i16::min_value()
} else if v > i16::max_value() as i32 {
} else if v > i32::from(i16::max_value()) {
i16::max_value()
} else {
v as i16

View file

@ -49,7 +49,8 @@ impl Default for ReverbResampler {
}
}
/// FIR coefficients
/// FIR coefficients. Mednafen and No$ use the same (although Mednafen uses an optimization that
/// removes zeroes and special-cases the resampling, not sure if it's worth it).
static FIR_COEFFS: [i16; 39] = [
-1, 0, 2, 0, -10, 0, 35, 0, -103, 0, 266, 0, -616, 0, 1332, 0, -2960, 0, 10246, 16384, 10246,
0, -2960, 0, 1332, 0, -616, 0, 266, 0, -103, 0, 35, 0, -10, 0, 2, 0, -1,