core: Properly set SharedInterruptFlags pointer for all interrupt generating devices when restoring state.
Serde doesn't like Rc that much :( Fixes #142 Former-commit-id: e1e8a96b4867e351d103fb7d92d71b0434e8fc31 Former-commit-id: 28366bbb36b3e93b574f397b103a483844fd8131
This commit is contained in:
parent
4050dcdf2f
commit
554edd62b0
|
@ -1,5 +1,5 @@
|
|||
use super::cartridge::BackupMedia;
|
||||
use super::interrupt::{self, Interrupt, SharedInterruptFlags};
|
||||
use super::interrupt::{self, Interrupt, InterruptConnect, SharedInterruptFlags};
|
||||
use super::iodev::consts::{REG_FIFO_A, REG_FIFO_B};
|
||||
use super::sysbus::SysBus;
|
||||
use super::Bus;
|
||||
|
@ -196,6 +196,14 @@ pub struct DmaController {
|
|||
cycles: usize,
|
||||
}
|
||||
|
||||
impl InterruptConnect for DmaController {
|
||||
fn connect_irq(&mut self, interrupt_flags: SharedInterruptFlags) {
|
||||
for channel in &mut self.channels {
|
||||
channel.interrupt_flags = interrupt_flags.clone();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl DmaController {
|
||||
pub fn new(interrupt_flags: SharedInterruptFlags) -> DmaController {
|
||||
DmaController {
|
||||
|
|
|
@ -28,11 +28,13 @@ pub struct GameBoyAdvance {
|
|||
pub cycles_to_next_event: usize,
|
||||
|
||||
overshoot_cycles: usize,
|
||||
interrupt_flags: SharedInterruptFlags,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct SaveState {
|
||||
sysbus: Box<SysBus>,
|
||||
interrupt_flags: u16,
|
||||
cpu: arm7tdmi::Core,
|
||||
}
|
||||
|
||||
|
@ -87,6 +89,7 @@ impl GameBoyAdvance {
|
|||
|
||||
cycles_to_next_event: 1,
|
||||
overshoot_cycles: 0,
|
||||
interrupt_flags: interrupt_flags,
|
||||
};
|
||||
|
||||
gba.sysbus.created();
|
||||
|
@ -102,9 +105,17 @@ impl GameBoyAdvance {
|
|||
) -> bincode::Result<GameBoyAdvance> {
|
||||
let decoded: Box<SaveState> = bincode::deserialize_from(savestate)?;
|
||||
|
||||
let arm7tdmi = decoded.cpu;
|
||||
let mut sysbus = decoded.sysbus;
|
||||
let interrupts = Rc::new(Cell::new(IrqBitmask(decoded.interrupt_flags)));
|
||||
|
||||
sysbus.io.connect_irq(interrupts.clone());
|
||||
|
||||
Ok(GameBoyAdvance {
|
||||
cpu: decoded.cpu,
|
||||
sysbus: decoded.sysbus,
|
||||
cpu: arm7tdmi,
|
||||
sysbus: sysbus,
|
||||
|
||||
interrupt_flags: interrupts,
|
||||
|
||||
video_device: video_device,
|
||||
audio_device: audio_device,
|
||||
|
@ -120,6 +131,7 @@ impl GameBoyAdvance {
|
|||
let s = SaveState {
|
||||
cpu: self.cpu.clone(),
|
||||
sysbus: self.sysbus.clone(),
|
||||
interrupt_flags: self.interrupt_flags.get().value(),
|
||||
};
|
||||
|
||||
bincode::serialize(&s)
|
||||
|
@ -130,6 +142,11 @@ impl GameBoyAdvance {
|
|||
|
||||
self.cpu = decoded.cpu;
|
||||
self.sysbus = decoded.sysbus;
|
||||
self.interrupt_flags = Rc::new(Cell::new(IrqBitmask(decoded.interrupt_flags)));
|
||||
|
||||
// Redistribute shared pointer for interrupts
|
||||
self.sysbus.io.connect_irq(self.interrupt_flags.clone());
|
||||
|
||||
self.cycles_to_next_event = 1;
|
||||
|
||||
self.sysbus.created();
|
||||
|
|
|
@ -6,7 +6,7 @@ use serde::{Deserialize, Serialize};
|
|||
|
||||
use super::bus::*;
|
||||
use super::dma::{DmaNotifer, TIMING_HBLANK, TIMING_VBLANK};
|
||||
use super::interrupt::{self, Interrupt, SharedInterruptFlags};
|
||||
use super::interrupt::{self, Interrupt, InterruptConnect, SharedInterruptFlags};
|
||||
pub use super::sysbus::consts::*;
|
||||
use super::util::BoxedMemory;
|
||||
use super::VideoInterface;
|
||||
|
@ -213,6 +213,12 @@ pub struct Gpu {
|
|||
pub(super) frame_buffer: Vec<u32>,
|
||||
}
|
||||
|
||||
impl InterruptConnect for Gpu {
|
||||
fn connect_irq(&mut self, interrupt_flags: SharedInterruptFlags) {
|
||||
self.interrupt_flags = interrupt_flags;
|
||||
}
|
||||
}
|
||||
|
||||
impl Gpu {
|
||||
pub fn new(interrupt_flags: SharedInterruptFlags) -> Gpu {
|
||||
Gpu {
|
||||
|
|
|
@ -3,6 +3,12 @@ use std::rc::Rc;
|
|||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
pub trait InterruptConnect {
|
||||
|
||||
// Connect a SharedInterruptFlags to this interrupt source
|
||||
fn connect_irq(&mut self, interrupt_flags: SharedInterruptFlags);
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Primitive, Copy, Clone, PartialEq)]
|
||||
#[allow(non_camel_case_types)]
|
||||
pub enum Interrupt {
|
||||
|
@ -52,6 +58,12 @@ impl InterruptController {
|
|||
}
|
||||
}
|
||||
|
||||
impl InterruptConnect for InterruptController {
|
||||
fn connect_irq(&mut self, interrupt_flags: SharedInterruptFlags) {
|
||||
self.interrupt_flags = interrupt_flags;
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn signal_irq(interrupt_flags: &SharedInterruptFlags, i: Interrupt) {
|
||||
let _if = interrupt_flags.get();
|
||||
|
|
|
@ -4,7 +4,7 @@ use super::bus::*;
|
|||
use super::dma::DmaController;
|
||||
use super::gpu::regs::WindowFlags;
|
||||
use super::gpu::*;
|
||||
use super::interrupt::InterruptController;
|
||||
use super::interrupt::{InterruptConnect, InterruptController, SharedInterruptFlags};
|
||||
use super::keypad;
|
||||
use super::sound::SoundController;
|
||||
use super::sysbus::SysBusPtr;
|
||||
|
@ -68,6 +68,15 @@ impl IoDevices {
|
|||
}
|
||||
}
|
||||
|
||||
impl InterruptConnect for IoDevices {
|
||||
fn connect_irq(&mut self, interrupt_flags: SharedInterruptFlags) {
|
||||
self.intc.connect_irq(interrupt_flags.clone());
|
||||
self.gpu.connect_irq(interrupt_flags.clone());
|
||||
self.dmac.connect_irq(interrupt_flags.clone());
|
||||
self.timers.connect_irq(interrupt_flags.clone());
|
||||
}
|
||||
}
|
||||
|
||||
impl Bus for IoDevices {
|
||||
fn read_16(&self, addr: Addr) -> u16 {
|
||||
let io = self;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use super::interrupt::{self, Interrupt, SharedInterruptFlags};
|
||||
use super::interrupt::{self, Interrupt, InterruptConnect, SharedInterruptFlags};
|
||||
use super::iodev::consts::*;
|
||||
use super::sysbus::SysBus;
|
||||
|
||||
|
@ -78,6 +78,14 @@ pub struct Timers {
|
|||
pub trace: bool,
|
||||
}
|
||||
|
||||
impl InterruptConnect for Timers {
|
||||
fn connect_irq(&mut self, interrupt_flags: SharedInterruptFlags) {
|
||||
for timer in &mut self.timers {
|
||||
timer.interrupt_flags = interrupt_flags.clone();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Index<usize> for Timers {
|
||||
type Output = Timer;
|
||||
fn index(&self, index: usize) -> &Self::Output {
|
||||
|
|
Reference in a new issue