107 lines
3.4 KiB
Rust
107 lines
3.4 KiB
Rust
use crate::device;
|
|
use crate::ui;
|
|
|
|
pub const EVENT_TYPE_NONE: usize = 0;
|
|
pub const EVENT_TYPE_AI: usize = 1;
|
|
pub const EVENT_TYPE_SI: usize = 2;
|
|
pub const EVENT_TYPE_VI: usize = 3;
|
|
pub const EVENT_TYPE_PI: usize = 4;
|
|
pub const EVENT_TYPE_DP: usize = 5;
|
|
pub const EVENT_TYPE_SP: usize = 6;
|
|
pub const EVENT_TYPE_INT: usize = 7;
|
|
pub const EVENT_TYPE_SPDMA: usize = 8;
|
|
pub const EVENT_TYPE_COMPARE: usize = 9;
|
|
pub const EVENT_TYPE_VRU: usize = 10;
|
|
pub const EVENT_TYPE_PAK: usize = 11;
|
|
pub const EVENT_TYPE_SAVE: usize = 12;
|
|
pub const EVENT_TYPE_NMI: usize = 13;
|
|
pub const EVENT_TYPE_UPDATE_SCREEN: usize = 14;
|
|
pub const EVENT_TYPE_COUNT: usize = 15;
|
|
|
|
#[derive(PartialEq, Copy, Clone, serde::Serialize, serde::Deserialize)]
|
|
pub struct Event {
|
|
pub enabled: bool,
|
|
pub count: u64,
|
|
}
|
|
|
|
pub fn create_event(device: &mut device::Device, name: usize, when: u64) {
|
|
device.cpu.events[name] = Event {
|
|
enabled: true,
|
|
count: device.cpu.cop0.regs[device::cop0::COP0_COUNT_REG] + when,
|
|
};
|
|
set_next_event(device);
|
|
}
|
|
|
|
pub fn create_event_at(device: &mut device::Device, name: usize, when: u64) {
|
|
device.cpu.events[name] = Event {
|
|
enabled: true,
|
|
count: when,
|
|
};
|
|
set_next_event(device);
|
|
}
|
|
|
|
pub fn get_event(device: &device::Device, name: usize) -> Option<&Event> {
|
|
if device.cpu.events[name].enabled {
|
|
return Some(&device.cpu.events[name]);
|
|
}
|
|
None
|
|
}
|
|
|
|
pub fn remove_event(device: &mut device::Device, name: usize) {
|
|
device.cpu.events[name].enabled = false;
|
|
}
|
|
|
|
fn get_event_handler(name: usize) -> fn(&mut device::Device) {
|
|
match name {
|
|
EVENT_TYPE_AI => device::ai::dma_event,
|
|
EVENT_TYPE_SI => device::si::dma_event,
|
|
EVENT_TYPE_VI => device::vi::vertical_interrupt_event,
|
|
EVENT_TYPE_PI => device::pi::dma_event,
|
|
EVENT_TYPE_DP => device::rdp::rdp_interrupt_event,
|
|
EVENT_TYPE_SP => device::rsp_interface::rsp_event,
|
|
EVENT_TYPE_INT => device::exceptions::interrupt_exception,
|
|
EVENT_TYPE_SPDMA => device::rsp_interface::fifo_pop,
|
|
EVENT_TYPE_COMPARE => device::cop0::compare_event,
|
|
EVENT_TYPE_VRU => device::controller::vru::vru_talking_event,
|
|
EVENT_TYPE_PAK => device::controller::pak_switch_event,
|
|
EVENT_TYPE_SAVE => ui::storage::save_event,
|
|
EVENT_TYPE_NMI => device::exceptions::reset_event,
|
|
EVENT_TYPE_UPDATE_SCREEN => device::vi::update_screen,
|
|
_ => dummy_event,
|
|
}
|
|
}
|
|
|
|
pub fn trigger_event(device: &mut device::Device) {
|
|
let next_event_name = device.cpu.next_event;
|
|
device.cpu.events[next_event_name].enabled = false;
|
|
|
|
let handler = get_event_handler(next_event_name);
|
|
device.cpu.cop0.is_event = true;
|
|
handler(device);
|
|
device.cpu.cop0.is_event = false;
|
|
set_next_event(device);
|
|
}
|
|
|
|
fn set_next_event(device: &mut device::Device) {
|
|
device.cpu.next_event_count = u64::MAX;
|
|
for (pos, i) in device.cpu.events.iter().enumerate() {
|
|
if i.enabled && i.count < device.cpu.next_event_count {
|
|
device.cpu.next_event_count = i.count;
|
|
device.cpu.next_event = pos;
|
|
}
|
|
}
|
|
}
|
|
|
|
pub fn translate_events(device: &mut device::Device, old_count: u64, new_count: u64) {
|
|
for i in device.cpu.events.iter_mut() {
|
|
if i.enabled {
|
|
i.count = i.count - old_count + new_count;
|
|
}
|
|
}
|
|
set_next_event(device);
|
|
}
|
|
|
|
pub fn dummy_event(_device: &mut device::Device) {
|
|
panic!("dummy event")
|
|
}
|