mirror of
https://github.com/gopher64/gopher64.git
synced 2026-11-05 22:03:52 +01:00
improve RSP timing (#1332)
This commit is contained in:
1 parent
1baa4a15cc
commit
7071e90579
6 files changed
+35
-20
No files matched your search
+1
-1
@@ -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
@@ -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
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
@@ -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] {
|
||||
|
||||
Reference in new issue
Block a user