improve RSP timing (#1332)

This commit is contained in:
Logan McNaughton authored and GitHub committed 2026-11-02 15:14:24 +00:00
1 parent 1baa4a15cc
commit 7071e90579
6 files changed
+35 -20

No files matched your search

+1 -1
View File
@@ -478,7 +478,6 @@ impl Device {
},
broken: false,
running: false,
halted: false,
sync_point: false,
cycle_counter: 0,
gpr: [0; 32],
@@ -511,6 +510,7 @@ impl Device {
mem: [0; 0x2000],
last_status_value: 0,
run_after_dma: false,
pending_status: 0,
fifo: [rsp_interface::RspDma {
dir: rsp_interface::DmaDir::None,
length: 0,
+4 -2
View File
@@ -37,8 +37,10 @@ fn get_remaining_dma_length(device: &device::Device) -> u64 {
return 0;
}
let remaining_dma_duration =
next_ai_event.unwrap().count - device.cpu.cop0.regs[device::cop0::COP0_COUNT_REG];
let remaining_dma_duration = next_ai_event
.unwrap()
.count
.saturating_sub(device.cpu.cop0.regs[device::cop0::COP0_COUNT_REG]);
let dma_length = remaining_dma_duration * device.ai.fifo[0].length / device.ai.fifo[0].duration;
dma_length & !7
-1
View File
@@ -35,7 +35,6 @@ pub struct Cpu {
pub branch_state: BranchState,
pub broken: bool,
pub running: bool,
pub halted: bool,
pub sync_point: bool,
pub cycle_counter: u64,
#[serde(
+25 -5
View File
@@ -86,6 +86,7 @@ pub struct Rsp {
pub fifo: [RspDma; 2],
pub last_status_value: u32,
pub run_after_dma: bool,
pub pending_status: u32,
}
pub fn read_mem_fast(
@@ -209,10 +210,15 @@ fn do_dma(device: &mut device::Device, dma: RspDma) {
device.rsp.regs[SP_RD_LEN_REG] = 0xff8;
device.rsp.regs[SP_WR_LEN_REG] = 0xff8;
let rsp_cycles = if device.rsp.cpu.running {
device::rsp_cpu::elapsed_cpu_cycles(device)
} else {
0
};
device::events::create_event(
device,
device::events::EVENT_TYPE_SPDMA,
device::rdram::rdram_calculate_cycles((count * length) as u64) + 9,
rsp_cycles + device::rdram::rdram_calculate_cycles((count * length) as u64) + 9,
);
}
@@ -312,7 +318,15 @@ pub fn read_regs(
pub fn write_regs(device: &mut device::Device, address: u64, value: u32, mask: u32) {
let reg = (address & 0xFFFF) >> 2;
match reg as usize {
SP_STATUS_REG => update_sp_status(device, value),
SP_STATUS_REG => {
if device.rsp.cpu.running {
device.rsp.pending_status = value;
device.rsp.cpu.sync_point = true;
} else {
apply_pending_status(device);
update_sp_status(device, value)
}
}
SP_RD_LEN_REG => {
device::memory::masked_write_32(&mut device.rsp.regs[reg as usize], value, mask);
fifo_push(device, DmaDir::Write)
@@ -459,7 +473,6 @@ fn update_sp_status(device: &mut device::Device, w: u32) {
if device.rsp.regs[SP_STATUS_REG] & SP_STATUS_HALT == 0 && was_halted {
device.rsp.cpu.broken = false;
device.rsp.cpu.halted = false;
do_task(device);
}
}
@@ -477,7 +490,15 @@ fn do_task(device: &mut device::Device) {
}
}
fn apply_pending_status(device: &mut device::Device) {
let pending = std::mem::take(&mut device.rsp.pending_status);
if pending != 0 {
update_sp_status(device, pending)
}
}
pub fn rsp_event(device: &mut device::Device) {
apply_pending_status(device);
if device.rsp.cpu.broken {
device.rsp.regs[SP_STATUS_REG] |= SP_STATUS_HALT | SP_STATUS_BROKE;
@@ -486,8 +507,7 @@ pub fn rsp_event(device: &mut device::Device) {
}
return;
}
if device.rsp.cpu.halted {
device.rsp.regs[SP_STATUS_REG] |= SP_STATUS_HALT;
if device.rsp.regs[SP_STATUS_REG] & SP_STATUS_HALT != 0 {
return;
}
do_task(device)
-7
View File
@@ -580,13 +580,6 @@ pub fn mtc0(device: &mut device::Device, opcode: u32) {
0xFFFFFFFF,
)
}
if rd(opcode) as usize == device::rsp_interface::SP_STATUS_REG
&& device.rsp.cpu.gpr[rt(opcode) as usize] & device::rsp_interface::SP_SET_HALT != 0
{
device.rsp.regs[device::rsp_interface::SP_STATUS_REG] &=
!device::rsp_interface::SP_STATUS_HALT; // set halt when event happens
device.rsp.cpu.halted = true // the RSP can halt itself by setting SP_SET_HALT
}
}
pub fn mfc2(device: &mut device::Device, opcode: u32) {
+5 -4
View File
@@ -51,10 +51,11 @@ fn set_vertical_interrupt(device: &mut device::Device) {
fn set_current_line(device: &mut device::Device) {
if let Some(next_vi) = device::events::get_event(device, device::events::EVENT_TYPE_VI) {
device.vi.regs[VI_CURRENT_REG] =
((device.vi.delay.saturating_sub(
next_vi.count - device.cpu.cop0.regs[device::cop0::COP0_COUNT_REG],
)) / device.vi.count_per_scanline) as u32;
device.vi.regs[VI_CURRENT_REG] = ((device.vi.delay.saturating_sub(
next_vi
.count
.saturating_sub(device.cpu.cop0.regs[device::cop0::COP0_COUNT_REG]),
)) / device.vi.count_per_scanline) as u32;
// wrap around VI_CURRENT_REG if needed
if device.vi.regs[VI_CURRENT_REG] >= device.vi.regs[VI_V_SYNC_REG] {