From 92c685412be539dc886b92c8155498807f7adad9 Mon Sep 17 00:00:00 2001 From: Brooke Chalmers Date: Fri, 29 Dec 2023 17:19:53 -0800 Subject: [PATCH 1/7] Move existing CPU impl into mos6502 module Co-authored-by: Ava Silver --- src/cpu/mod.rs | 194 +---------------------------- src/cpu/{ => mos6502}/execute.rs | 8 +- src/cpu/{ => mos6502}/fetch.rs | 2 +- src/cpu/mos6502/mod.rs | 193 ++++++++++++++++++++++++++++ src/cpu/{ => mos6502}/registers.rs | 0 src/main.rs | 2 +- src/systems/basic.rs | 2 +- src/systems/c64/mod.rs | 2 +- src/systems/easy.rs | 2 +- src/systems/klaus.rs | 2 +- src/systems/pet/mod.rs | 2 +- src/systems/vic/mod.rs | 2 +- 12 files changed, 207 insertions(+), 204 deletions(-) rename src/cpu/{ => mos6502}/execute.rs (99%) rename src/cpu/{ => mos6502}/fetch.rs (98%) create mode 100644 src/cpu/mos6502/mod.rs rename src/cpu/{ => mos6502}/registers.rs (100%) diff --git a/src/cpu/mod.rs b/src/cpu/mod.rs index 616ac7d9..61fb2e7f 100644 --- a/src/cpu/mod.rs +++ b/src/cpu/mod.rs @@ -1,193 +1 @@ -mod execute; -mod fetch; -mod registers; -use crate::memory::{ActiveInterrupt, Memory, SystemInfo}; -use execute::Execute; -use fetch::Fetch; -use registers::{flags, Registers}; - -const CLOCKS_PER_POLL: u32 = 100; - -#[derive(Copy, Clone, PartialEq)] -pub enum Mos6502Variant { - /// 6502 - NMOS, - /// 65C02 - CMOS, -} - -/// The MOS 6502 CPU and its associated memory. -pub struct Mos6502 { - pub registers: Registers, - pub memory: Box, - cycle_count: u64, - cycles_since_poll: u32, - variant: Mos6502Variant, -} - -/// Read and write from the system's memory. -pub trait MemoryIO { - /// Read a byte from the given address in memory. - fn read(&mut self, address: u16) -> u8; - - /// Write a byte to the given address in memory. - fn write(&mut self, address: u16, value: u8); - - /// Read a word (little-endian) from the given address in memory. - fn read_word(&mut self, address: u16) -> u16; - - /// Write a word (little-endian) to the given address in memory. - fn write_word(&mut self, address: u16, value: u16); -} - -impl MemoryIO for Mos6502 { - fn read(&mut self, address: u16) -> u8 { - self.memory.read(address) - } - - fn read_word(&mut self, address: u16) -> u16 { - let lo = self.memory.read(address); - let hi = self.memory.read(address + 1); - (hi as u16) << 8 | lo as u16 - } - - fn write(&mut self, address: u16, value: u8) { - self.memory.write(address, value); - } - - fn write_word(&mut self, address: u16, value: u16) { - self.memory.write(address, value as u8); - self.memory.write(address + 1, (value >> 8) as u8); - } -} - -/// Push and pop values from the stack. -pub trait Stack { - /// Push a byte onto the stack. - fn push(&mut self, value: u8); - - /// Pop a byte from the stack. - fn pop(&mut self) -> u8; - - /// Push a word (little-endian) onto the stack. - fn push_word(&mut self, value: u16); - - /// Pop a word (little-endian) from the stack. - fn pop_word(&mut self) -> u16; -} - -impl Stack for Mos6502 { - fn push(&mut self, value: u8) { - self.write(self.registers.sp.address(), value); - self.registers.sp.push(); - } - - fn pop(&mut self) -> u8 { - self.registers.sp.pop(); - self.read(self.registers.sp.address()) - } - - fn push_word(&mut self, value: u16) { - self.push((value >> 8) as u8); - self.push((value & 0xFF) as u8); - } - - fn pop_word(&mut self) -> u16 { - let lo = self.pop(); - let hi = self.pop(); - (hi as u16) << 8 | lo as u16 - } -} - -/// Handle interrupts by setting the applicable flags, pushing the program counter -/// onto the stack, and loading the interrupt vector into the program counter. -pub trait InterruptHandler { - fn interrupt(&mut self, maskable: bool, set_brk: bool); -} - -impl InterruptHandler for Mos6502 { - fn interrupt(&mut self, maskable: bool, break_instr: bool) { - if maskable && !break_instr && self.registers.sr.read(flags::INTERRUPT) { - return; - } - - self.push_word(self.registers.pc.address()); - - if break_instr { - self.push(self.registers.sr.get() | flags::BREAK); - } else { - self.push(self.registers.sr.get() & !flags::BREAK); - } - - if let Mos6502Variant::CMOS = self.variant { - self.registers.sr.clear(flags::DECIMAL); - } - - self.registers.sr.set(flags::INTERRUPT); - - let dest = match maskable { - false => self.read_word(0xFFFA), - true => self.read_word(0xFFFE), - }; - - self.registers.pc.load(dest); - } -} - -impl Mos6502 { - pub fn new(memory: impl Memory + 'static, variant: Mos6502Variant) -> Mos6502 { - Mos6502 { - registers: Registers::new(), - memory: Box::new(memory), - cycle_count: 0, - cycles_since_poll: 0, - variant, - } - } - - pub fn reset(&mut self) { - self.memory.reset(); - self.registers.reset(); - let pc_address = self.read_word(0xFFFC); - self.registers.pc.load(pc_address); - } - - /// Return a SystemInfo struct containing the current system status. - pub fn get_info(&self) -> SystemInfo { - SystemInfo { - cycle_count: self.cycle_count, - } - } - - /// Execute a single instruction. - pub fn tick(&mut self) -> u8 { - let opcode = self.fetch(); - match self.execute(opcode) { - Ok(cycles) => { - self.cycle_count += cycles as u64; - self.cycles_since_poll += cycles as u32; - - if self.cycles_since_poll >= CLOCKS_PER_POLL { - let info = self.get_info(); - - match self.memory.poll(self.cycles_since_poll, &info) { - ActiveInterrupt::None => (), - ActiveInterrupt::NMI => self.interrupt(false, false), - ActiveInterrupt::IRQ => self.interrupt(true, false), - } - - self.cycles_since_poll = 0; - } - - cycles - } - Err(_) => { - panic!( - "Failed to execute instruction {:02x} at {:04x}", - opcode, - self.registers.pc.address() - ); - } - } - } -} +pub mod mos6502; diff --git a/src/cpu/execute.rs b/src/cpu/mos6502/execute.rs similarity index 99% rename from src/cpu/execute.rs rename to src/cpu/mos6502/execute.rs index a19402e2..db57ce01 100644 --- a/src/cpu/execute.rs +++ b/src/cpu/mos6502/execute.rs @@ -1,6 +1,8 @@ -use crate::cpu::fetch::Fetch; -use crate::cpu::registers::{flags, Alu}; -use crate::cpu::{InterruptHandler, MemoryIO, Mos6502, Stack}; +use crate::cpu::mos6502::{ + fetch::Fetch, + registers::{flags, Alu}, + InterruptHandler, MemoryIO, Mos6502, Stack, +}; use super::Mos6502Variant; diff --git a/src/cpu/fetch.rs b/src/cpu/mos6502/fetch.rs similarity index 98% rename from src/cpu/fetch.rs rename to src/cpu/mos6502/fetch.rs index e1615ed8..7c0c9a7f 100644 --- a/src/cpu/fetch.rs +++ b/src/cpu/mos6502/fetch.rs @@ -1,4 +1,4 @@ -use crate::cpu::{MemoryIO, Mos6502}; +use crate::cpu::mos6502::{MemoryIO, Mos6502}; use super::Mos6502Variant; diff --git a/src/cpu/mos6502/mod.rs b/src/cpu/mos6502/mod.rs new file mode 100644 index 00000000..616ac7d9 --- /dev/null +++ b/src/cpu/mos6502/mod.rs @@ -0,0 +1,193 @@ +mod execute; +mod fetch; +mod registers; +use crate::memory::{ActiveInterrupt, Memory, SystemInfo}; +use execute::Execute; +use fetch::Fetch; +use registers::{flags, Registers}; + +const CLOCKS_PER_POLL: u32 = 100; + +#[derive(Copy, Clone, PartialEq)] +pub enum Mos6502Variant { + /// 6502 + NMOS, + /// 65C02 + CMOS, +} + +/// The MOS 6502 CPU and its associated memory. +pub struct Mos6502 { + pub registers: Registers, + pub memory: Box, + cycle_count: u64, + cycles_since_poll: u32, + variant: Mos6502Variant, +} + +/// Read and write from the system's memory. +pub trait MemoryIO { + /// Read a byte from the given address in memory. + fn read(&mut self, address: u16) -> u8; + + /// Write a byte to the given address in memory. + fn write(&mut self, address: u16, value: u8); + + /// Read a word (little-endian) from the given address in memory. + fn read_word(&mut self, address: u16) -> u16; + + /// Write a word (little-endian) to the given address in memory. + fn write_word(&mut self, address: u16, value: u16); +} + +impl MemoryIO for Mos6502 { + fn read(&mut self, address: u16) -> u8 { + self.memory.read(address) + } + + fn read_word(&mut self, address: u16) -> u16 { + let lo = self.memory.read(address); + let hi = self.memory.read(address + 1); + (hi as u16) << 8 | lo as u16 + } + + fn write(&mut self, address: u16, value: u8) { + self.memory.write(address, value); + } + + fn write_word(&mut self, address: u16, value: u16) { + self.memory.write(address, value as u8); + self.memory.write(address + 1, (value >> 8) as u8); + } +} + +/// Push and pop values from the stack. +pub trait Stack { + /// Push a byte onto the stack. + fn push(&mut self, value: u8); + + /// Pop a byte from the stack. + fn pop(&mut self) -> u8; + + /// Push a word (little-endian) onto the stack. + fn push_word(&mut self, value: u16); + + /// Pop a word (little-endian) from the stack. + fn pop_word(&mut self) -> u16; +} + +impl Stack for Mos6502 { + fn push(&mut self, value: u8) { + self.write(self.registers.sp.address(), value); + self.registers.sp.push(); + } + + fn pop(&mut self) -> u8 { + self.registers.sp.pop(); + self.read(self.registers.sp.address()) + } + + fn push_word(&mut self, value: u16) { + self.push((value >> 8) as u8); + self.push((value & 0xFF) as u8); + } + + fn pop_word(&mut self) -> u16 { + let lo = self.pop(); + let hi = self.pop(); + (hi as u16) << 8 | lo as u16 + } +} + +/// Handle interrupts by setting the applicable flags, pushing the program counter +/// onto the stack, and loading the interrupt vector into the program counter. +pub trait InterruptHandler { + fn interrupt(&mut self, maskable: bool, set_brk: bool); +} + +impl InterruptHandler for Mos6502 { + fn interrupt(&mut self, maskable: bool, break_instr: bool) { + if maskable && !break_instr && self.registers.sr.read(flags::INTERRUPT) { + return; + } + + self.push_word(self.registers.pc.address()); + + if break_instr { + self.push(self.registers.sr.get() | flags::BREAK); + } else { + self.push(self.registers.sr.get() & !flags::BREAK); + } + + if let Mos6502Variant::CMOS = self.variant { + self.registers.sr.clear(flags::DECIMAL); + } + + self.registers.sr.set(flags::INTERRUPT); + + let dest = match maskable { + false => self.read_word(0xFFFA), + true => self.read_word(0xFFFE), + }; + + self.registers.pc.load(dest); + } +} + +impl Mos6502 { + pub fn new(memory: impl Memory + 'static, variant: Mos6502Variant) -> Mos6502 { + Mos6502 { + registers: Registers::new(), + memory: Box::new(memory), + cycle_count: 0, + cycles_since_poll: 0, + variant, + } + } + + pub fn reset(&mut self) { + self.memory.reset(); + self.registers.reset(); + let pc_address = self.read_word(0xFFFC); + self.registers.pc.load(pc_address); + } + + /// Return a SystemInfo struct containing the current system status. + pub fn get_info(&self) -> SystemInfo { + SystemInfo { + cycle_count: self.cycle_count, + } + } + + /// Execute a single instruction. + pub fn tick(&mut self) -> u8 { + let opcode = self.fetch(); + match self.execute(opcode) { + Ok(cycles) => { + self.cycle_count += cycles as u64; + self.cycles_since_poll += cycles as u32; + + if self.cycles_since_poll >= CLOCKS_PER_POLL { + let info = self.get_info(); + + match self.memory.poll(self.cycles_since_poll, &info) { + ActiveInterrupt::None => (), + ActiveInterrupt::NMI => self.interrupt(false, false), + ActiveInterrupt::IRQ => self.interrupt(true, false), + } + + self.cycles_since_poll = 0; + } + + cycles + } + Err(_) => { + panic!( + "Failed to execute instruction {:02x} at {:04x}", + opcode, + self.registers.pc.address() + ); + } + } + } +} diff --git a/src/cpu/registers.rs b/src/cpu/mos6502/registers.rs similarity index 100% rename from src/cpu/registers.rs rename to src/cpu/mos6502/registers.rs diff --git a/src/main.rs b/src/main.rs index 77c4e014..eefbab9b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -55,7 +55,7 @@ struct Args { #[cfg(not(target_arch = "wasm32"))] fn main() { - use libnoentiendo::{cpu::Mos6502Variant, systems::klaus::KlausSystemConfig}; + use libnoentiendo::{cpu::mos6502::Mos6502Variant, systems::klaus::KlausSystemConfig}; let args = Args::parse(); diff --git a/src/systems/basic.rs b/src/systems/basic.rs index f4e90fc3..462e7961 100644 --- a/src/systems/basic.rs +++ b/src/systems/basic.rs @@ -1,6 +1,6 @@ use instant::Duration; -use crate::cpu::{Mos6502, Mos6502Variant}; +use crate::cpu::mos6502::{Mos6502, Mos6502Variant}; use crate::memory::{ActiveInterrupt, Memory, SystemInfo}; use crate::memory::{BlockMemory, BranchMemory}; use crate::platform::{PlatformProvider, WindowConfig}; diff --git a/src/systems/c64/mod.rs b/src/systems/c64/mod.rs index 5670a09e..a13d6458 100644 --- a/src/systems/c64/mod.rs +++ b/src/systems/c64/mod.rs @@ -5,7 +5,7 @@ use std::{ }; use crate::{ - cpu::{Mos6502, Mos6502Variant}, + cpu::mos6502::{Mos6502, Mos6502Variant}, keyboard::{ commodore::{C64KeyboardAdapter, C64SymbolAdapter, C64VirtualAdapter}, KeyAdapter, KeyMappingStrategy, SymbolAdapter, diff --git a/src/systems/easy.rs b/src/systems/easy.rs index a4ca9183..dff58e58 100644 --- a/src/systems/easy.rs +++ b/src/systems/easy.rs @@ -1,6 +1,6 @@ use instant::Duration; -use crate::cpu::{MemoryIO, Mos6502, Mos6502Variant}; +use crate::cpu::mos6502::{MemoryIO, Mos6502, Mos6502Variant}; use crate::keyboard::KeyPosition; use crate::memory::{ActiveInterrupt, BlockMemory, BranchMemory, Memory, SystemInfo}; use crate::platform::{Color, PlatformProvider, WindowConfig}; diff --git a/src/systems/klaus.rs b/src/systems/klaus.rs index a43f1d93..ff136243 100644 --- a/src/systems/klaus.rs +++ b/src/systems/klaus.rs @@ -1,6 +1,6 @@ use instant::Duration; -use crate::cpu::{Mos6502, Mos6502Variant}; +use crate::cpu::mos6502::{Mos6502, Mos6502Variant}; use crate::memory::BlockMemory; use crate::platform::{PlatformProvider, WindowConfig}; use crate::roms::RomFile; diff --git a/src/systems/pet/mod.rs b/src/systems/pet/mod.rs index 222f0433..efaadf83 100644 --- a/src/systems/pet/mod.rs +++ b/src/systems/pet/mod.rs @@ -1,4 +1,4 @@ -use crate::cpu::{MemoryIO, Mos6502, Mos6502Variant}; +use crate::cpu::mos6502::{MemoryIO, Mos6502, Mos6502Variant}; use crate::keyboard::{KeyAdapter, KeyMappingStrategy, SymbolAdapter}; use crate::memory::mos652x::{Pia, Via}; use crate::memory::{BlockMemory, BranchMemory, NullMemory, NullPort, Port, SystemInfo}; diff --git a/src/systems/vic/mod.rs b/src/systems/vic/mod.rs index 8293a536..94879687 100644 --- a/src/systems/vic/mod.rs +++ b/src/systems/vic/mod.rs @@ -1,4 +1,4 @@ -use crate::cpu::{Mos6502, Mos6502Variant}; +use crate::cpu::mos6502::{Mos6502, Mos6502Variant}; use crate::keyboard::commodore::C64VirtualAdapter; use crate::keyboard::{ commodore::{C64KeyboardAdapter, C64SymbolAdapter}, From c62509c559ceb21508a1b5c84d3ab3f832c9ec0b Mon Sep 17 00:00:00 2001 From: Brooke Chalmers Date: Fri, 29 Dec 2023 17:43:02 -0800 Subject: [PATCH 2/7] Extract CPU interface to trait, remove SystemInfo struct Co-authored-by: Ava Silver --- src/cpu/mod.rs | 10 ++++++++ src/cpu/mos6502/mod.rs | 26 ++++++++++---------- src/memory/banked.rs | 6 ++--- src/memory/block.rs | 4 ++-- src/memory/branch.rs | 6 ++--- src/memory/logging.rs | 6 ++--- src/memory/mod.rs | 9 +------ src/memory/mos6510.rs | 6 ++--- src/memory/mos652x/cia.rs | 50 ++++++++++++++++++--------------------- src/memory/mos652x/mod.rs | 10 ++++---- src/memory/mos652x/pia.rs | 12 +++++----- src/memory/mos652x/via.rs | 50 ++++++++++++++++++++++----------------- src/memory/null.rs | 4 ++-- src/memory/ports.rs | 6 ++--- src/systems/basic.rs | 9 ++++--- src/systems/c64/mod.rs | 8 +++---- src/systems/c64/vic_ii.rs | 6 ++--- src/systems/easy.rs | 9 ++++--- src/systems/klaus.rs | 5 +++- src/systems/pet/mod.rs | 15 +++++++----- src/systems/vic/chip.rs | 4 ++-- src/systems/vic/mod.rs | 13 ++++++---- 22 files changed, 147 insertions(+), 127 deletions(-) diff --git a/src/cpu/mod.rs b/src/cpu/mod.rs index 61fb2e7f..639411f0 100644 --- a/src/cpu/mod.rs +++ b/src/cpu/mod.rs @@ -1 +1,11 @@ pub mod mos6502; + +pub trait Cpu { + fn reset(&mut self); + + /// Return the number of cycles elapsed since the system last reset. + fn get_cycle_count(&self) -> u64; + + /// Execute a single instruction. Return the number of cycles elapsed. + fn tick(&mut self) -> u8; +} diff --git a/src/cpu/mos6502/mod.rs b/src/cpu/mos6502/mod.rs index 616ac7d9..347aa38b 100644 --- a/src/cpu/mos6502/mod.rs +++ b/src/cpu/mos6502/mod.rs @@ -1,12 +1,14 @@ mod execute; mod fetch; mod registers; -use crate::memory::{ActiveInterrupt, Memory, SystemInfo}; +use crate::memory::{ActiveInterrupt, Memory}; use execute::Execute; use fetch::Fetch; use registers::{flags, Registers}; -const CLOCKS_PER_POLL: u32 = 100; +use super::Cpu; + +const CLOCKS_PER_POLL: u64 = 100; #[derive(Copy, Clone, PartialEq)] pub enum Mos6502Variant { @@ -21,7 +23,7 @@ pub struct Mos6502 { pub registers: Registers, pub memory: Box, cycle_count: u64, - cycles_since_poll: u32, + cycles_since_poll: u64, variant: Mos6502Variant, } @@ -144,8 +146,10 @@ impl Mos6502 { variant, } } +} - pub fn reset(&mut self) { +impl Cpu for Mos6502 { + fn reset(&mut self) { self.memory.reset(); self.registers.reset(); let pc_address = self.read_word(0xFFFC); @@ -153,24 +157,22 @@ impl Mos6502 { } /// Return a SystemInfo struct containing the current system status. - pub fn get_info(&self) -> SystemInfo { - SystemInfo { - cycle_count: self.cycle_count, - } + fn get_cycle_count(&self) -> u64 { + self.cycle_count } /// Execute a single instruction. - pub fn tick(&mut self) -> u8 { + fn tick(&mut self) -> u8 { let opcode = self.fetch(); match self.execute(opcode) { Ok(cycles) => { self.cycle_count += cycles as u64; - self.cycles_since_poll += cycles as u32; + self.cycles_since_poll += cycles as u64; if self.cycles_since_poll >= CLOCKS_PER_POLL { - let info = self.get_info(); + let total_cycle_count = self.get_cycle_count(); - match self.memory.poll(self.cycles_since_poll, &info) { + match self.memory.poll(self.cycles_since_poll, total_cycle_count) { ActiveInterrupt::None => (), ActiveInterrupt::NMI => self.interrupt(false, false), ActiveInterrupt::IRQ => self.interrupt(true, false), diff --git a/src/memory/banked.rs b/src/memory/banked.rs index d3a108e4..e965ec3e 100644 --- a/src/memory/banked.rs +++ b/src/memory/banked.rs @@ -1,6 +1,6 @@ use std::{cell::Cell, rc::Rc}; -use super::{ActiveInterrupt, Memory, SystemInfo}; +use super::{ActiveInterrupt, Memory}; /// Represents the memory banking features found in the Commodore 64 and other /// devices. Multiple memory implementations are all mapped to the same @@ -48,11 +48,11 @@ impl Memory for BankedMemory { } } - fn poll(&mut self, cycles: u32, info: &SystemInfo) -> ActiveInterrupt { + fn poll(&mut self, cycles_since_poll: u64, total_cycle_count: u64) -> ActiveInterrupt { let mut highest = ActiveInterrupt::None; for mapped in &mut self.banks { - let interrupt = mapped.poll(cycles, info); + let interrupt = mapped.poll(cycles_since_poll, total_cycle_count); match interrupt { ActiveInterrupt::None => (), diff --git a/src/memory/block.rs b/src/memory/block.rs index 95e90353..4de9b01d 100644 --- a/src/memory/block.rs +++ b/src/memory/block.rs @@ -1,4 +1,4 @@ -use crate::memory::{ActiveInterrupt, Memory, SystemInfo}; +use crate::memory::{ActiveInterrupt, Memory}; use crate::roms::RomFile; /// Represents a simple block of contiguous memory, with no additional hardware. @@ -85,7 +85,7 @@ impl Memory for BlockMemory { } } - fn poll(&mut self, _cycles: u32, _info: &SystemInfo) -> ActiveInterrupt { + fn poll(&mut self, _cycles_since_poll: u64, _total_cycle_count: u64) -> ActiveInterrupt { ActiveInterrupt::None } } diff --git a/src/memory/branch.rs b/src/memory/branch.rs index 64f120f0..71222919 100644 --- a/src/memory/branch.rs +++ b/src/memory/branch.rs @@ -1,4 +1,4 @@ -use crate::memory::{ActiveInterrupt, Memory, SystemInfo}; +use crate::memory::{ActiveInterrupt, Memory}; /// Maps several Memory objects into a single contiguous address space. /// Each mapped object is assigned a starting address, and reads and writes @@ -66,11 +66,11 @@ impl Memory for BranchMemory { } } - fn poll(&mut self, cycles: u32, info: &SystemInfo) -> ActiveInterrupt { + fn poll(&mut self, cycles_since_poll: u64, total_cycle_count: u64) -> ActiveInterrupt { let mut highest = ActiveInterrupt::None; for (_, mapped) in &mut self.mapping { - let interrupt = mapped.poll(cycles, info); + let interrupt = mapped.poll(cycles_since_poll, total_cycle_count); match interrupt { ActiveInterrupt::None => (), diff --git a/src/memory/logging.rs b/src/memory/logging.rs index e7b841eb..b60f4622 100644 --- a/src/memory/logging.rs +++ b/src/memory/logging.rs @@ -1,4 +1,4 @@ -use super::{ActiveInterrupt, Memory, SystemInfo}; +use super::{ActiveInterrupt, Memory}; pub struct LoggingMemory { backing: Box, @@ -43,8 +43,8 @@ impl Memory for LoggingMemory { println!("[Memory Reset]: {}", self.message); } - fn poll(&mut self, cycles: u32, info: &SystemInfo) -> ActiveInterrupt { + fn poll(&mut self, cycles_since_poll: u64, total_cycle_count: u64) -> ActiveInterrupt { // println!("[Memory Poll]: {}", self.message); - self.backing.poll(cycles, info) + self.backing.poll(cycles_since_poll, total_cycle_count) } } diff --git a/src/memory/mod.rs b/src/memory/mod.rs index 9b8e44c3..ce76cd8c 100644 --- a/src/memory/mod.rs +++ b/src/memory/mod.rs @@ -27,13 +27,6 @@ pub enum ActiveInterrupt { IRQ, } -/// Information about the system that Memory implementations can use to -/// determine if an interrupt should be triggered. -#[derive(Debug, Default)] -pub struct SystemInfo { - pub cycle_count: u64, -} - /// Represents a contiguous block of memory which can be read, written, /// reset, and polled to see if an interrupt has been triggered. pub trait Memory { @@ -52,5 +45,5 @@ pub trait Memory { /// Poll this memory to see if an interrupt has been triggered. /// Implementations may trigger an NMI or IRQ for any /// implementation-dependent reason. - fn poll(&mut self, cycles: u32, info: &SystemInfo) -> ActiveInterrupt; + fn poll(&mut self, cycles_since_poll: u64, total_cycle_count: u64) -> ActiveInterrupt; } diff --git a/src/memory/mos6510.rs b/src/memory/mos6510.rs index 16ae7d96..ec2b17bb 100644 --- a/src/memory/mos6510.rs +++ b/src/memory/mos6510.rs @@ -1,4 +1,4 @@ -use super::{ActiveInterrupt, Memory, Port, SystemInfo}; +use super::{ActiveInterrupt, Memory, Port}; /// Represents the port built into a MOS 6510 processor, mapped to memory addresses 0x0000 (for the DDR) and 0x0001 (for the port itself). pub struct Mos6510Port { @@ -50,8 +50,8 @@ impl Memory for Mos6510Port { self.port.reset(); } - fn poll(&mut self, cycles: u32, info: &SystemInfo) -> ActiveInterrupt { - match self.port.poll(cycles, info) { + fn poll(&mut self, cycles_since_poll: u64, total_cycle_count: u64) -> ActiveInterrupt { + match self.port.poll(cycles_since_poll, total_cycle_count) { true => ActiveInterrupt::IRQ, false => ActiveInterrupt::None, } diff --git a/src/memory/mos652x/cia.rs b/src/memory/mos652x/cia.rs index 03de9bef..973c4899 100644 --- a/src/memory/mos652x/cia.rs +++ b/src/memory/mos652x/cia.rs @@ -1,6 +1,6 @@ use crate::memory::{ mos652x::{InterruptRegister, PortRegisters, ShiftRegister, Timer}, - ActiveInterrupt, Memory, Port, SystemInfo, + ActiveInterrupt, Memory, Port, }; struct TimeRegisters { @@ -208,20 +208,22 @@ impl Memory for Cia { self.interrupts.reset(); } - fn poll(&mut self, cycles: u32, info: &SystemInfo) -> ActiveInterrupt { - if self.timer_a.poll(cycles, info) + fn poll(&mut self, cycles_since_poll: u64, total_cycle_count: u64) -> ActiveInterrupt { + if self.timer_a.poll(cycles_since_poll, total_cycle_count) && (self.interrupts.interrupt_enable & interrupt_bits::TIMER_A) != 0 { return ActiveInterrupt::IRQ; } - if self.timer_b.poll(cycles, info) + if self.timer_b.poll(cycles_since_poll, total_cycle_count) && (self.interrupts.interrupt_enable & interrupt_bits::TIMER_B) != 0 { return ActiveInterrupt::IRQ; } - if self.a.poll(cycles, info) || self.b.poll(cycles, info) { + if self.a.poll(cycles_since_poll, total_cycle_count) + || self.b.poll(cycles_since_poll, total_cycle_count) + { return ActiveInterrupt::IRQ; } @@ -276,14 +278,14 @@ mod tests { cia.write(0x0E, 0b0000_1001); for _ in 0..0x0F { - assert_eq!(ActiveInterrupt::None, cia.poll(1, &SystemInfo::default())); + assert_eq!(ActiveInterrupt::None, cia.poll(1, 0)); } - assert_eq!(ActiveInterrupt::IRQ, cia.poll(1, &SystemInfo::default())); + assert_eq!(ActiveInterrupt::IRQ, cia.poll(1, 0)); // polling again shouldn't do anything for _ in 0..0x20 { - assert_eq!(ActiveInterrupt::None, cia.poll(1, &SystemInfo::default())); + assert_eq!(ActiveInterrupt::None, cia.poll(1, 0)); } } @@ -302,10 +304,10 @@ mod tests { cia.write(0x0F, 0b0000_1001); for _ in 0..0x1233 { - assert_eq!(ActiveInterrupt::None, cia.poll(1, &SystemInfo::default())); + assert_eq!(ActiveInterrupt::None, cia.poll(1, 0)); } - assert_eq!(ActiveInterrupt::IRQ, cia.poll(1, &SystemInfo::default())); + assert_eq!(ActiveInterrupt::IRQ, cia.poll(1, 0)); } #[test] @@ -322,19 +324,13 @@ mod tests { // start the timer, and enable continuous operation cia.write(0x0E, 0b0000_0001); - assert_eq!( - ActiveInterrupt::None, - cia.poll(0x0F, &SystemInfo::default()) - ); + assert_eq!(ActiveInterrupt::None, cia.poll(0x0F, 0)); - assert_eq!(ActiveInterrupt::IRQ, cia.poll(1, &SystemInfo::default())); + assert_eq!(ActiveInterrupt::IRQ, cia.poll(1, 0)); - assert_eq!( - ActiveInterrupt::None, - cia.poll(0x0F, &SystemInfo::default()) - ); + assert_eq!(ActiveInterrupt::None, cia.poll(0x0F, 0)); - assert_eq!(ActiveInterrupt::IRQ, cia.poll(1, &SystemInfo::default())); + assert_eq!(ActiveInterrupt::IRQ, cia.poll(1, 0)); } #[test] @@ -358,10 +354,10 @@ mod tests { // timer 1 should interrupt first for _ in 0..0x0F { - assert_eq!(ActiveInterrupt::None, cia.poll(1, &SystemInfo::default())); + assert_eq!(ActiveInterrupt::None, cia.poll(1, 0)); } - assert_eq!(ActiveInterrupt::IRQ, cia.poll(1, &SystemInfo::default())); + assert_eq!(ActiveInterrupt::IRQ, cia.poll(1, 0)); } #[test] @@ -384,7 +380,7 @@ mod tests { // timer 2 shouldn't trigger an interrupt for _ in 0..0x08 { - assert_eq!(ActiveInterrupt::None, cia.poll(1, &SystemInfo::default())); + assert_eq!(ActiveInterrupt::None, cia.poll(1, 0)); } // ...but the flag register should be set @@ -395,9 +391,9 @@ mod tests { // timer 1 should then trigger an interrupt for _ in 0..0x07 { - assert_eq!(ActiveInterrupt::None, cia.poll(1, &SystemInfo::default())); + assert_eq!(ActiveInterrupt::None, cia.poll(1, 0)); } - assert_eq!(ActiveInterrupt::IRQ, cia.poll(1, &SystemInfo::default())); + assert_eq!(ActiveInterrupt::IRQ, cia.poll(1, 0)); // ...and set the corresponding flag, plus the master bit assert_eq!( @@ -410,8 +406,8 @@ mod tests { // if we let timer 1 run again, it should set the flag again for _ in 0..0x0F { - assert_eq!(ActiveInterrupt::None, cia.poll(1, &SystemInfo::default())); + assert_eq!(ActiveInterrupt::None, cia.poll(1, 0)); } - assert_eq!(ActiveInterrupt::IRQ, cia.poll(1, &SystemInfo::default())); + assert_eq!(ActiveInterrupt::IRQ, cia.poll(1, 0)); } } diff --git a/src/memory/mos652x/mod.rs b/src/memory/mos652x/mod.rs index c8048af6..792a63e1 100644 --- a/src/memory/mos652x/mod.rs +++ b/src/memory/mos652x/mod.rs @@ -6,7 +6,7 @@ pub use cia::Cia; pub use pia::Pia; pub use via::Via; -use crate::memory::{Port, SystemInfo}; +use crate::memory::Port; /// A port and its associated registers on the MOS 6522 VIA or MOS 6526 CIA. pub struct PortRegisters { @@ -45,8 +45,8 @@ impl PortRegisters { } /// Poll the underlying port for interrupts. - pub fn poll(&mut self, cycles: u32, info: &SystemInfo) -> bool { - self.port.poll(cycles, info) + pub fn poll(&mut self, cycles_since_poll: u64, total_cycle_count: u64) -> bool { + self.port.poll(cycles_since_poll, total_cycle_count) } /// Reset the port to its initial state. @@ -127,7 +127,7 @@ impl Timer { } /// Poll the timer (decrement the counter, fire the interrupt if necessary). - pub fn poll(&mut self, cycles: u32, _info: &SystemInfo) -> bool { + pub fn poll(&mut self, cycles_since_poll: u64, _total_cycle_count: u64) -> bool { if self.counter <= 0 { if self.continuous { self.counter += self.latch as i32; @@ -138,7 +138,7 @@ impl Timer { } if self.running { - self.counter -= cycles as i32; + self.counter -= cycles_since_poll as i32; if self.counter <= 0 { // The counter underflowed diff --git a/src/memory/mos652x/pia.rs b/src/memory/mos652x/pia.rs index 9b10cb8b..a112b5ff 100644 --- a/src/memory/mos652x/pia.rs +++ b/src/memory/mos652x/pia.rs @@ -1,4 +1,4 @@ -use crate::memory::{ActiveInterrupt, Memory, Port, SystemInfo}; +use crate::memory::{ActiveInterrupt, Memory, Port}; // MOS 6520 @@ -55,8 +55,8 @@ impl PiaPortRegisters { } /// Poll the underlying port for interrupts. - pub fn poll(&mut self, cycles: u32, info: &SystemInfo) -> bool { - self.port.poll(cycles, info) + pub fn poll(&mut self, cycles_since_poll: u64, total_cycle_count: u64) -> bool { + self.port.poll(cycles_since_poll, total_cycle_count) } /// Reset the DDR, control register, and underlying port. @@ -122,9 +122,9 @@ impl Memory for Pia { self.b.reset(); } - fn poll(&mut self, cycles: u32, info: &SystemInfo) -> ActiveInterrupt { - let a = self.a.poll(cycles, info); - let b = self.b.poll(cycles, info); + fn poll(&mut self, cycles_since_poll: u64, total_cycle_count: u64) -> ActiveInterrupt { + let a = self.a.poll(cycles_since_poll, total_cycle_count); + let b = self.b.poll(cycles_since_poll, total_cycle_count); if a || b { ActiveInterrupt::IRQ diff --git a/src/memory/mos652x/via.rs b/src/memory/mos652x/via.rs index fc864c81..3e5ab2e5 100644 --- a/src/memory/mos652x/via.rs +++ b/src/memory/mos652x/via.rs @@ -1,6 +1,6 @@ use crate::memory::{ mos652x::{InterruptRegister, PortRegisters, ShiftRegister, Timer, TimerOutput}, - ActiveInterrupt, Memory, Port, SystemInfo, + ActiveInterrupt, Memory, Port, }; #[allow(dead_code)] @@ -183,16 +183,22 @@ impl Memory for Via { self.b.reset(); } - fn poll(&mut self, cycles: u32, info: &SystemInfo) -> ActiveInterrupt { - if self.t1.poll(cycles, info) && self.interrupts.is_enabled(interrupt_bits::T1_ENABLE) { + fn poll(&mut self, cycles_since_poll: u64, total_cycle_count: u64) -> ActiveInterrupt { + if self.t1.poll(cycles_since_poll, total_cycle_count) + && self.interrupts.is_enabled(interrupt_bits::T1_ENABLE) + { return ActiveInterrupt::IRQ; } - if self.t2.poll(cycles, info) && self.interrupts.is_enabled(interrupt_bits::T2_ENABLE) { + if self.t2.poll(cycles_since_poll, total_cycle_count) + && self.interrupts.is_enabled(interrupt_bits::T2_ENABLE) + { return ActiveInterrupt::IRQ; } - if self.a.poll(cycles, info) || self.b.poll(cycles, info) { + if self.a.poll(cycles_since_poll, total_cycle_count) + || self.b.poll(cycles_since_poll, total_cycle_count) + { return ActiveInterrupt::IRQ; } @@ -244,14 +250,14 @@ mod tests { via.write(0x05, 0x00); for _ in 0..0x0F { - assert_eq!(ActiveInterrupt::None, via.poll(1, &SystemInfo::default())); + assert_eq!(ActiveInterrupt::None, via.poll(1, 0)); } - assert_eq!(ActiveInterrupt::IRQ, via.poll(1, &SystemInfo::default())); + assert_eq!(ActiveInterrupt::IRQ, via.poll(1, 0)); // polling again shouldn't do anything for _ in 0..0x20 { - assert_eq!(ActiveInterrupt::None, via.poll(1, &SystemInfo::default())); + assert_eq!(ActiveInterrupt::None, via.poll(1, 0)); } } @@ -266,16 +272,16 @@ mod tests { via.write(0x08, 0x34); // polling now shouldn't do anything - assert_eq!(ActiveInterrupt::None, via.poll(1, &SystemInfo::default())); + assert_eq!(ActiveInterrupt::None, via.poll(1, 0)); // timer begins when the high byte is written via.write(0x09, 0x12); for _ in 0..0x1233 { - assert_eq!(ActiveInterrupt::None, via.poll(1, &SystemInfo::default())); + assert_eq!(ActiveInterrupt::None, via.poll(1, 0)); } - assert_eq!(ActiveInterrupt::IRQ, via.poll(1, &SystemInfo::default())); + assert_eq!(ActiveInterrupt::IRQ, via.poll(1, 0)); } #[test] @@ -293,16 +299,16 @@ mod tests { via.write(0x05, 0x00); for _ in 0..0x0F { - assert_eq!(ActiveInterrupt::None, via.poll(1, &SystemInfo::default())); + assert_eq!(ActiveInterrupt::None, via.poll(1, 0)); } - assert_eq!(ActiveInterrupt::IRQ, via.poll(1, &SystemInfo::default())); + assert_eq!(ActiveInterrupt::IRQ, via.poll(1, 0)); for _ in 0..0x0F { - assert_eq!(ActiveInterrupt::None, via.poll(1, &SystemInfo::default())); + assert_eq!(ActiveInterrupt::None, via.poll(1, 0)); } - assert_eq!(ActiveInterrupt::IRQ, via.poll(1, &SystemInfo::default())); + assert_eq!(ActiveInterrupt::IRQ, via.poll(1, 0)); } #[test] @@ -353,10 +359,10 @@ mod tests { // timer 1 should interrupt first for _ in 0..0x0F { - assert_eq!(ActiveInterrupt::None, via.poll(1, &SystemInfo::default())); + assert_eq!(ActiveInterrupt::None, via.poll(1, 0)); } - assert_eq!(ActiveInterrupt::IRQ, via.poll(1, &SystemInfo::default())); + assert_eq!(ActiveInterrupt::IRQ, via.poll(1, 0)); } #[test] @@ -379,7 +385,7 @@ mod tests { // timer 2 shouldn't trigger an interrupt for _ in 0..0x08 { - assert_eq!(ActiveInterrupt::None, via.poll(1, &SystemInfo::default())); + assert_eq!(ActiveInterrupt::None, via.poll(1, 0)); } // ...but the flag register should be set @@ -387,9 +393,9 @@ mod tests { // timer 1 should then trigger an interrupt for _ in 0..0x07 { - assert_eq!(ActiveInterrupt::None, via.poll(1, &SystemInfo::default())); + assert_eq!(ActiveInterrupt::None, via.poll(1, 0)); } - assert_eq!(ActiveInterrupt::IRQ, via.poll(1, &SystemInfo::default())); + assert_eq!(ActiveInterrupt::IRQ, via.poll(1, 0)); // ...and set the corresponding flag, plus the master bit assert_eq!( @@ -414,8 +420,8 @@ mod tests { // if we let timer 1 run again, it should set the flag again for _ in 0..0x0F { - assert_eq!(ActiveInterrupt::None, via.poll(1, &SystemInfo::default())); + assert_eq!(ActiveInterrupt::None, via.poll(1, 0)); } - assert_eq!(ActiveInterrupt::IRQ, via.poll(1, &SystemInfo::default())); + assert_eq!(ActiveInterrupt::IRQ, via.poll(1, 0)); } } diff --git a/src/memory/null.rs b/src/memory/null.rs index f5066739..9e6fe05b 100644 --- a/src/memory/null.rs +++ b/src/memory/null.rs @@ -1,4 +1,4 @@ -use crate::memory::{ActiveInterrupt, Memory, SystemInfo}; +use crate::memory::{ActiveInterrupt, Memory}; /// Memory that does nothing when read or written to. #[derive(Default)] @@ -36,7 +36,7 @@ impl Memory for NullMemory { fn reset(&mut self) {} - fn poll(&mut self, _cycles: u32, _info: &SystemInfo) -> ActiveInterrupt { + fn poll(&mut self, _cycles_since_poll: u64, _total_cycle_count: u64) -> ActiveInterrupt { ActiveInterrupt::None } } diff --git a/src/memory/ports.rs b/src/memory/ports.rs index 5fc99dc7..1df290f8 100644 --- a/src/memory/ports.rs +++ b/src/memory/ports.rs @@ -1,5 +1,3 @@ -use crate::memory::SystemInfo; - /// A Port that can be read from, written to, reset, or polled for interrupts. /// Used in the MOS 6520 PIA and the 6522 VIA. pub trait Port { @@ -12,7 +10,7 @@ pub trait Port { /// Poll the port for interrupts. A port may trigger an interrupt for any /// implementation-defined reason. - fn poll(&mut self, cycles: u32, info: &SystemInfo) -> bool; + fn poll(&mut self, cycles_since_poll: u64, total_cycle_count: u64) -> bool; /// Reset the port to its initial state, analogous to a system reboot. fn reset(&mut self); @@ -52,7 +50,7 @@ impl Port for NullPort { } } - fn poll(&mut self, _cycles: u32, _info: &SystemInfo) -> bool { + fn poll(&mut self, _cycles_since_poll: u64, _total_cycle_count: u64) -> bool { false } diff --git a/src/systems/basic.rs b/src/systems/basic.rs index 462e7961..b5fc1cdb 100644 --- a/src/systems/basic.rs +++ b/src/systems/basic.rs @@ -1,7 +1,10 @@ use instant::Duration; -use crate::cpu::mos6502::{Mos6502, Mos6502Variant}; -use crate::memory::{ActiveInterrupt, Memory, SystemInfo}; +use crate::cpu::{ + mos6502::{Mos6502, Mos6502Variant}, + Cpu, +}; +use crate::memory::{ActiveInterrupt, Memory}; use crate::memory::{BlockMemory, BranchMemory}; use crate::platform::{PlatformProvider, WindowConfig}; use crate::roms::RomFile; @@ -60,7 +63,7 @@ impl Memory for MappedStdIO { fn reset(&mut self) {} - fn poll(&mut self, _cycles: u32, _info: &SystemInfo) -> ActiveInterrupt { + fn poll(&mut self, _cycles_since_poll: u64, _total_cycle_count: u64) -> ActiveInterrupt { ActiveInterrupt::None } } diff --git a/src/systems/c64/mod.rs b/src/systems/c64/mod.rs index a13d6458..b49ed032 100644 --- a/src/systems/c64/mod.rs +++ b/src/systems/c64/mod.rs @@ -6,13 +6,13 @@ use std::{ use crate::{ cpu::mos6502::{Mos6502, Mos6502Variant}, + cpu::Cpu, keyboard::{ commodore::{C64KeyboardAdapter, C64SymbolAdapter, C64VirtualAdapter}, KeyAdapter, KeyMappingStrategy, SymbolAdapter, }, memory::{ mos652x::Cia, BankedMemory, BlockMemory, BranchMemory, Mos6510Port, NullMemory, NullPort, Port, - SystemInfo, }, platform::{PlatformProvider, WindowConfig}, systems::System, @@ -59,7 +59,7 @@ impl Port for C64Cia1PortA { self.keyboard_row.set(value); } - fn poll(&mut self, _cycles: u32, _info: &SystemInfo) -> bool { + fn poll(&mut self, _cycles_since_poll: u64, _total_cycle_count: u64) -> bool { false } @@ -119,7 +119,7 @@ impl Port for C64Cia1PortB { panic!("Tried to write to keyboard row"); } - fn poll(&mut self, _cycles: u32, _info: &SystemInfo) -> bool { + fn poll(&mut self, _cycles_since_poll: u64, _total_cycle_count: u64) -> bool { false } @@ -188,7 +188,7 @@ impl Port for C64BankSwitching { self.selectors[5].set(if !self.hiram { 1 } else { 0 }); } - fn poll(&mut self, _cycles: u32, _info: &SystemInfo) -> bool { + fn poll(&mut self, _cycles_since_poll: u64, _total_cycle_count: u64) -> bool { false } diff --git a/src/systems/c64/vic_ii.rs b/src/systems/c64/vic_ii.rs index 653cfc5b..d9d807bf 100644 --- a/src/systems/c64/vic_ii.rs +++ b/src/systems/c64/vic_ii.rs @@ -1,4 +1,4 @@ -use crate::memory::{ActiveInterrupt, Memory, SystemInfo}; +use crate::memory::{ActiveInterrupt, Memory}; use crate::platform::{Color, WindowConfig}; use std::cell::RefCell; use std::rc::Rc; @@ -450,8 +450,8 @@ impl Memory for VicIIChipIO { self.chip.borrow_mut().reset(); } - fn poll(&mut self, _cycles: u32, info: &SystemInfo) -> ActiveInterrupt { - self.chip.borrow_mut().raster_counter = ((info.cycle_count / 83) % 312) as u16; + fn poll(&mut self, _cycles_since_poll: u64, total_cycle_count: u64) -> ActiveInterrupt { + self.chip.borrow_mut().raster_counter = ((total_cycle_count / 83) % 312) as u16; ActiveInterrupt::None } diff --git a/src/systems/easy.rs b/src/systems/easy.rs index dff58e58..2652d84e 100644 --- a/src/systems/easy.rs +++ b/src/systems/easy.rs @@ -1,8 +1,11 @@ use instant::Duration; -use crate::cpu::mos6502::{MemoryIO, Mos6502, Mos6502Variant}; +use crate::cpu::{ + mos6502::{MemoryIO, Mos6502, Mos6502Variant}, + Cpu, +}; use crate::keyboard::KeyPosition; -use crate::memory::{ActiveInterrupt, BlockMemory, BranchMemory, Memory, SystemInfo}; +use crate::memory::{ActiveInterrupt, BlockMemory, BranchMemory, Memory}; use crate::platform::{Color, PlatformProvider, WindowConfig}; use crate::roms::RomFile; use crate::systems::{System, SystemBuilder}; @@ -52,7 +55,7 @@ impl Memory for EasyIO { fn reset(&mut self) {} - fn poll(&mut self, _cycles: u32, _info: &SystemInfo) -> ActiveInterrupt { + fn poll(&mut self, _cycles_since_poll: u64, _total_cycle_count: u64) -> ActiveInterrupt { ActiveInterrupt::None } } diff --git a/src/systems/klaus.rs b/src/systems/klaus.rs index ff136243..9e8a9d60 100644 --- a/src/systems/klaus.rs +++ b/src/systems/klaus.rs @@ -1,6 +1,9 @@ use instant::Duration; -use crate::cpu::mos6502::{Mos6502, Mos6502Variant}; +use crate::cpu::{ + mos6502::{Mos6502, Mos6502Variant}, + Cpu, +}; use crate::memory::BlockMemory; use crate::platform::{PlatformProvider, WindowConfig}; use crate::roms::RomFile; diff --git a/src/systems/pet/mod.rs b/src/systems/pet/mod.rs index efaadf83..b07371c4 100644 --- a/src/systems/pet/mod.rs +++ b/src/systems/pet/mod.rs @@ -1,7 +1,10 @@ -use crate::cpu::mos6502::{MemoryIO, Mos6502, Mos6502Variant}; +use crate::cpu::{ + mos6502::{MemoryIO, Mos6502, Mos6502Variant}, + Cpu, +}; use crate::keyboard::{KeyAdapter, KeyMappingStrategy, SymbolAdapter}; use crate::memory::mos652x::{Pia, Via}; -use crate::memory::{BlockMemory, BranchMemory, NullMemory, NullPort, Port, SystemInfo}; +use crate::memory::{BlockMemory, BranchMemory, NullMemory, NullPort, Port}; use crate::platform::{Color, PlatformProvider, WindowConfig}; use crate::systems::{System, SystemBuilder}; use instant::Instant; @@ -60,16 +63,16 @@ impl Port for PetPia1PortA { self.keyboard_row.set(value & 0b1111); } - fn poll(&mut self, _cycles: u32, info: &SystemInfo) -> bool { + fn poll(&mut self, _cycles_since_poll: u64, total_cycle_count: u64) -> bool { // let min_elapsed = ((info.cycles_per_second as f64 / 60.0) * (2.0 / 3.0)) as u64; let min_elapsed = 0; // TODO: fix match self.last_draw_instant { Some(last_draw) => { if (last_draw.elapsed() > Duration::from_millis(17)) - && (info.cycle_count > self.last_draw_cycle + min_elapsed) + && (total_cycle_count > self.last_draw_cycle + min_elapsed) { - self.last_draw_cycle = info.cycle_count; + self.last_draw_cycle = total_cycle_count; self.last_draw_instant = Some(Instant::now()); true // false @@ -136,7 +139,7 @@ impl Port for PetPia1PortB { fn write(&mut self, _value: u8) {} - fn poll(&mut self, _cycles: u32, _info: &SystemInfo) -> bool { + fn poll(&mut self, _cycles_since_poll: u64, _total_cycle_count: u64) -> bool { false } diff --git a/src/systems/vic/chip.rs b/src/systems/vic/chip.rs index dd3d3861..d5bd598b 100644 --- a/src/systems/vic/chip.rs +++ b/src/systems/vic/chip.rs @@ -1,4 +1,4 @@ -use crate::memory::{ActiveInterrupt, Memory, SystemInfo}; +use crate::memory::{ActiveInterrupt, Memory}; use crate::platform::{Color, PlatformProvider, WindowConfig}; use std::cell::RefCell; use std::rc::Rc; @@ -493,7 +493,7 @@ impl Memory for VicChipIO { self.chip.borrow_mut().reset(); } - fn poll(&mut self, _cycles: u32, _info: &SystemInfo) -> ActiveInterrupt { + fn poll(&mut self, _cycles_since_poll: u64, _total_cycle_count: u64) -> ActiveInterrupt { ActiveInterrupt::None } } diff --git a/src/systems/vic/mod.rs b/src/systems/vic/mod.rs index 94879687..f0aca798 100644 --- a/src/systems/vic/mod.rs +++ b/src/systems/vic/mod.rs @@ -1,11 +1,14 @@ -use crate::cpu::mos6502::{Mos6502, Mos6502Variant}; +use crate::cpu::{ + mos6502::{Mos6502, Mos6502Variant}, + Cpu, +}; use crate::keyboard::commodore::C64VirtualAdapter; use crate::keyboard::{ commodore::{C64KeyboardAdapter, C64SymbolAdapter}, KeyAdapter, KeyMappingStrategy, SymbolAdapter, }; use crate::memory::mos652x::Via; -use crate::memory::{BlockMemory, BranchMemory, NullMemory, NullPort, Port, SystemInfo}; +use crate::memory::{BlockMemory, BranchMemory, NullMemory, NullPort, Port}; use crate::platform::{PlatformProvider, WindowConfig}; use crate::roms::RomFile; use crate::systems::System; @@ -137,7 +140,7 @@ impl Port for VicVia1PortA { fn write(&mut self, _value: u8) {} - fn poll(&mut self, _cycles: u32, _info: &SystemInfo) -> bool { + fn poll(&mut self, _cycles_since_poll: u64, _total_cycle_count: u64) -> bool { false } @@ -175,7 +178,7 @@ impl Port for VicVia2PortB { self.keyboard_col.set(value); } - fn poll(&mut self, _cycles: u32, _info: &SystemInfo) -> bool { + fn poll(&mut self, _cycles_since_poll: u64, _total_cycle_count: u64) -> bool { false } @@ -234,7 +237,7 @@ impl Port for VicVia2PortA { fn write(&mut self, _value: u8) {} - fn poll(&mut self, _cycles: u32, _info: &SystemInfo) -> bool { + fn poll(&mut self, _cycles_since_poll: u64, _total_cycle_count: u64) -> bool { false } From 712012e0ad9e073e2e106c898366dd1d256fb91c Mon Sep 17 00:00:00 2001 From: Brooke Chalmers Date: Fri, 29 Dec 2023 18:03:23 -0800 Subject: [PATCH 3/7] Remove SystemBuilder structs, refactor trait into BuildableSystem Co-authored-by: Ava Silver --- src/main.rs | 20 ++++++++++---------- src/systems/basic.rs | 7 ++----- src/systems/c64/mod.rs | 7 ++----- src/systems/easy.rs | 6 ++---- src/systems/klaus.rs | 10 ++++------ src/systems/mod.rs | 4 ++-- src/systems/pet/mod.rs | 7 ++----- src/systems/vic/mod.rs | 7 ++----- 8 files changed, 26 insertions(+), 42 deletions(-) diff --git a/src/main.rs b/src/main.rs index eefbab9b..a3f7814a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,10 +4,10 @@ use libnoentiendo::{ platform::{SyncPlatform, TextPlatform, WinitPlatform}, roms::DiskLoadable, systems::{ - basic::BasicSystemBuilder, c64::C64SystemBuilder, c64::C64SystemConfig, c64::C64SystemRoms, - easy::Easy6502SystemBuilder, klaus::KlausSystemBuilder, pet::PetSystemBuilder, - pet::PetSystemConfig, pet::PetSystemRoms, vic::Vic20SystemBuilder, vic::Vic20SystemConfig, - vic::Vic20SystemRoms, SystemBuilder, + basic::BasicSystem, c64::C64System, c64::C64SystemConfig, c64::C64SystemRoms, + easy::Easy6502System, klaus::KlausSystem, pet::PetSystem, pet::PetSystemConfig, + pet::PetSystemRoms, vic::Vic20System, vic::Vic20SystemConfig, vic::Vic20SystemRoms, + BuildableSystem, }, }; @@ -75,9 +75,9 @@ fn main() { }; let system = match args.system { - SystemArg::Basic => BasicSystemBuilder::build(romfile.unwrap(), (), platform.provider()), - SystemArg::Easy => Easy6502SystemBuilder::build(romfile.unwrap(), (), platform.provider()), - SystemArg::Klaus => KlausSystemBuilder::build( + SystemArg::Basic => BasicSystem::build(romfile.unwrap(), (), platform.provider()), + SystemArg::Easy => Easy6502System::build(romfile.unwrap(), (), platform.provider()), + SystemArg::Klaus => KlausSystem::build( romfile.unwrap(), KlausSystemConfig { pc_report: None, @@ -85,12 +85,12 @@ fn main() { }, platform.provider(), ), - SystemArg::Pet => PetSystemBuilder::build( + SystemArg::Pet => PetSystem::build( PetSystemRoms::from_disk(), PetSystemConfig { mapping }, platform.provider(), ), - SystemArg::Vic => Vic20SystemBuilder::build( + SystemArg::Vic => Vic20System::build( Vic20SystemRoms::from_disk(match romfile { Some(_) => Some(args.rom_path.as_str()), None => None, @@ -98,7 +98,7 @@ fn main() { Vic20SystemConfig { mapping }, platform.provider(), ), - SystemArg::C64 => C64SystemBuilder::build( + SystemArg::C64 => C64System::build( C64SystemRoms::from_disk(), C64SystemConfig { mapping }, platform.provider(), diff --git a/src/systems/basic.rs b/src/systems/basic.rs index b5fc1cdb..10f7d63f 100644 --- a/src/systems/basic.rs +++ b/src/systems/basic.rs @@ -8,7 +8,7 @@ use crate::memory::{ActiveInterrupt, Memory}; use crate::memory::{BlockMemory, BranchMemory}; use crate::platform::{PlatformProvider, WindowConfig}; use crate::roms::RomFile; -use crate::systems::{System, SystemBuilder}; +use crate::systems::{BuildableSystem, System}; use std::io::Write; use std::sync::Arc; @@ -68,10 +68,7 @@ impl Memory for MappedStdIO { } } -/// A factory for creating a BasicSystem. -pub struct BasicSystemBuilder; - -impl SystemBuilder for BasicSystemBuilder { +impl BuildableSystem for BasicSystem { fn build(rom: RomFile, _config: (), platform: Arc) -> Box { let ram = BlockMemory::ram(0x4000); let io = MappedStdIO::new(platform); diff --git a/src/systems/c64/mod.rs b/src/systems/c64/mod.rs index b49ed032..5aefcfe7 100644 --- a/src/systems/c64/mod.rs +++ b/src/systems/c64/mod.rs @@ -30,7 +30,7 @@ use self::{ vic_ii::{VicIIChip, VicIIChipIO}, }; -use super::SystemBuilder; +use super::BuildableSystem; /// Port A on the first CIA chip on the C64 deals with setting the keyboard row being scanned. struct C64Cia1PortA { @@ -204,10 +204,7 @@ pub struct C64SystemConfig { pub mapping: KeyMappingStrategy, } -/// A factory for creating a Commodore 64 system. -pub struct C64SystemBuilder; - -impl SystemBuilder for C64SystemBuilder { +impl BuildableSystem for C64System { fn build( roms: C64SystemRoms, config: C64SystemConfig, diff --git a/src/systems/easy.rs b/src/systems/easy.rs index 2652d84e..1edf220e 100644 --- a/src/systems/easy.rs +++ b/src/systems/easy.rs @@ -8,7 +8,7 @@ use crate::keyboard::KeyPosition; use crate::memory::{ActiveInterrupt, BlockMemory, BranchMemory, Memory}; use crate::platform::{Color, PlatformProvider, WindowConfig}; use crate::roms::RomFile; -use crate::systems::{System, SystemBuilder}; +use crate::systems::{BuildableSystem, System}; use std::sync::Arc; const WIDTH: u32 = 32; @@ -61,9 +61,7 @@ impl Memory for EasyIO { } /// A factory for the Easy6502 system. -pub struct Easy6502SystemBuilder; - -impl SystemBuilder for Easy6502SystemBuilder { +impl BuildableSystem for Easy6502System { fn build(rom: RomFile, _config: (), platform: Arc) -> Box { platform.request_window(WindowConfig::new(WIDTH, WIDTH, SCALE as f64)); diff --git a/src/systems/klaus.rs b/src/systems/klaus.rs index 9e8a9d60..9be407a1 100644 --- a/src/systems/klaus.rs +++ b/src/systems/klaus.rs @@ -12,7 +12,7 @@ use std::cell::Cell; use std::rc::Rc; use std::sync::Arc; -use super::SystemBuilder; +use super::BuildableSystem; pub struct KlausSystemConfig { pub pc_report: Option>>, @@ -20,9 +20,7 @@ pub struct KlausSystemConfig { } /// A factory for creating a system that runs Klaus Dormann's 6502 CPU test suite. -pub struct KlausSystemBuilder; - -impl SystemBuilder for KlausSystemBuilder { +impl BuildableSystem for KlausSystem { fn build( rom: RomFile, config: KlausSystemConfig, @@ -77,7 +75,7 @@ mod tests { let platform = TextPlatform::new(); let pc = Rc::new(Cell::new(0)); - let mut system = KlausSystemBuilder::build( + let mut system = KlausSystem::build( roms, KlausSystemConfig { pc_report: Some(pc.clone()), @@ -99,7 +97,7 @@ mod tests { let platform = TextPlatform::new(); let pc = Rc::new(Cell::new(0)); - let mut system = KlausSystemBuilder::build( + let mut system = KlausSystem::build( roms, KlausSystemConfig { pc_report: Some(pc.clone()), diff --git a/src/systems/mod.rs b/src/systems/mod.rs index ad2c1537..d27f2a79 100644 --- a/src/systems/mod.rs +++ b/src/systems/mod.rs @@ -9,8 +9,8 @@ pub mod klaus; pub mod pet; pub mod vic; -pub trait SystemBuilder { - /// Create a new system from the given roms, configuration, and with I/O provided by the given +pub trait BuildableSystem { + /// Instantiate this system from the given roms, configuration, and with I/O provided by the given /// platform provider. fn build( roms: RomRegistry, diff --git a/src/systems/pet/mod.rs b/src/systems/pet/mod.rs index b07371c4..72c9ac7c 100644 --- a/src/systems/pet/mod.rs +++ b/src/systems/pet/mod.rs @@ -6,7 +6,7 @@ use crate::keyboard::{KeyAdapter, KeyMappingStrategy, SymbolAdapter}; use crate::memory::mos652x::{Pia, Via}; use crate::memory::{BlockMemory, BranchMemory, NullMemory, NullPort, Port}; use crate::platform::{Color, PlatformProvider, WindowConfig}; -use crate::systems::{System, SystemBuilder}; +use crate::systems::{BuildableSystem, System}; use instant::Instant; use std::cell::Cell; use std::rc::Rc; @@ -151,10 +151,7 @@ pub struct PetSystemConfig { pub mapping: KeyMappingStrategy, } -/// A factory for the Commodore PET. -pub struct PetSystemBuilder; - -impl SystemBuilder for PetSystemBuilder { +impl BuildableSystem for PetSystem { fn build( roms: PetSystemRoms, config: PetSystemConfig, diff --git a/src/systems/vic/mod.rs b/src/systems/vic/mod.rs index f0aca798..e1461d84 100644 --- a/src/systems/vic/mod.rs +++ b/src/systems/vic/mod.rs @@ -34,7 +34,7 @@ use wasm_bindgen::JsCast; #[cfg(target_arch = "wasm32")] use js_sys::Uint8Array; -use super::SystemBuilder; +use super::BuildableSystem; /// The set of ROM files required to run a VIC-20 system. pub struct Vic20SystemRoms { @@ -249,10 +249,7 @@ pub struct Vic20SystemConfig { pub mapping: KeyMappingStrategy, } -/// A factory for creating a VIC-20 system. -pub struct Vic20SystemBuilder; - -impl SystemBuilder for Vic20SystemBuilder { +impl BuildableSystem for Vic20System { fn build( roms: Vic20SystemRoms, config: Vic20SystemConfig, From 327cf3108a77165cab174ead92dad22fffbb9d43 Mon Sep 17 00:00:00 2001 From: Brooke Chalmers Date: Fri, 29 Dec 2023 19:19:51 -0800 Subject: [PATCH 4/7] Fix WASM entry point --- src/wasm.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/wasm.rs b/src/wasm.rs index 9f4dfffc..18326a17 100644 --- a/src/wasm.rs +++ b/src/wasm.rs @@ -18,10 +18,10 @@ use crate::{ keyboard::KeyMappingStrategy, platform::{AsyncPlatform, CanvasPlatform, Platform}, systems::{ - c64::{C64SystemBuilder, C64SystemConfig, C64SystemRoms}, - pet::{PetSystemBuilder, PetSystemConfig, PetSystemRoms}, - vic::{Vic20SystemBuilder, Vic20SystemConfig, Vic20SystemRoms}, - System, SystemBuilder, + c64::{C64System, C64SystemConfig, C64SystemRoms}, + pet::{PetSystem, PetSystemConfig, PetSystemRoms}, + vic::{Vic20System, Vic20SystemConfig, Vic20SystemRoms}, + BuildableSystem, System, }, }; @@ -79,21 +79,21 @@ impl NoentiendoBuilder { let system = self.system.as_ref().expect("System not set"); let mut system = match system.as_str() { - "pet" => PetSystemBuilder::build( + "pet" => PetSystem::build( pet_roms, PetSystemConfig { mapping: KeyMappingStrategy::Symbolic, }, platform.provider(), ), - "vic" => Vic20SystemBuilder::build( + "vic" => Vic20System::build( vic_roms, Vic20SystemConfig { mapping: KeyMappingStrategy::Symbolic, }, platform.provider(), ), - "c64" => C64SystemBuilder::build( + "c64" => C64System::build( c64_roms, C64SystemConfig { mapping: KeyMappingStrategy::Symbolic, From 6e3285e528e15c9b1f5b06594712633b952d4b1d Mon Sep 17 00:00:00 2001 From: Brooke Chalmers Date: Fri, 29 Dec 2023 19:28:44 -0800 Subject: [PATCH 5/7] Add get_cpu method to System trait Co-authored-by: Ava Silver --- src/systems/basic.rs | 4 ++++ src/systems/c64/mod.rs | 4 ++++ src/systems/easy.rs | 4 ++++ src/systems/klaus.rs | 4 ++++ src/systems/mod.rs | 8 +++++++- src/systems/pet/mod.rs | 4 ++++ src/systems/vic/mod.rs | 4 ++++ 7 files changed, 31 insertions(+), 1 deletion(-) diff --git a/src/systems/basic.rs b/src/systems/basic.rs index 10f7d63f..d1ac3f6f 100644 --- a/src/systems/basic.rs +++ b/src/systems/basic.rs @@ -91,6 +91,10 @@ pub struct BasicSystem { } impl System for BasicSystem { + fn get_cpu(&self) -> Box<&dyn Cpu> { + Box::new(&self.cpu) + } + fn tick(&mut self) -> Duration { Duration::from_secs_f64(1.0 / 20_000.0) * self.cpu.tick().into() } diff --git a/src/systems/c64/mod.rs b/src/systems/c64/mod.rs index 5aefcfe7..e46a8c7c 100644 --- a/src/systems/c64/mod.rs +++ b/src/systems/c64/mod.rs @@ -313,6 +313,10 @@ pub struct C64System { } impl System for C64System { + fn get_cpu(&self) -> Box<&dyn Cpu> { + Box::new(&self.cpu) + } + fn tick(&mut self) -> Duration { Duration::from_secs_f64(1.0 / 1_000_000.0) * self.cpu.tick() as u32 } diff --git a/src/systems/easy.rs b/src/systems/easy.rs index 1edf220e..e0529255 100644 --- a/src/systems/easy.rs +++ b/src/systems/easy.rs @@ -93,6 +93,10 @@ pub struct Easy6502System { } impl System for Easy6502System { + fn get_cpu(&self) -> Box<&dyn Cpu> { + Box::new(&self.cpu) + } + fn tick(&mut self) -> Duration { Duration::from_secs_f64(1.0 / 20_000.0) * self.cpu.tick().into() } diff --git a/src/systems/klaus.rs b/src/systems/klaus.rs index 9be407a1..bac98073 100644 --- a/src/systems/klaus.rs +++ b/src/systems/klaus.rs @@ -45,6 +45,10 @@ pub struct KlausSystem { } impl System for KlausSystem { + fn get_cpu(&self) -> Box<&dyn Cpu> { + Box::new(&self.cpu) + } + fn tick(&mut self) -> Duration { self.cpu.tick(); if let Some(pc) = &self.pc { diff --git a/src/systems/mod.rs b/src/systems/mod.rs index d27f2a79..fe9c6059 100644 --- a/src/systems/mod.rs +++ b/src/systems/mod.rs @@ -1,4 +1,7 @@ -use crate::platform::{PlatformProvider, WindowConfig}; +use crate::{ + cpu::Cpu, + platform::{PlatformProvider, WindowConfig}, +}; use instant::Duration; use std::sync::Arc; @@ -21,6 +24,9 @@ pub trait BuildableSystem { /// A representation of an emulated system. pub trait System { + /// Return a mutable reference to the CPU used in this system. + fn get_cpu(&self) -> Box<&dyn Cpu>; + /// Advance the system by one tick. fn tick(&mut self) -> Duration; diff --git a/src/systems/pet/mod.rs b/src/systems/pet/mod.rs index 72c9ac7c..6a2c6078 100644 --- a/src/systems/pet/mod.rs +++ b/src/systems/pet/mod.rs @@ -210,6 +210,10 @@ pub struct PetSystem { } impl System for PetSystem { + fn get_cpu(&self) -> Box<&dyn Cpu> { + Box::new(&self.cpu) + } + fn tick(&mut self) -> Duration { Duration::from_secs_f64(1.0 / 1_000_000.0) * self.cpu.tick() as u32 } diff --git a/src/systems/vic/mod.rs b/src/systems/vic/mod.rs index e1461d84..71c1a616 100644 --- a/src/systems/vic/mod.rs +++ b/src/systems/vic/mod.rs @@ -311,6 +311,10 @@ pub struct Vic20System { } impl System for Vic20System { + fn get_cpu(&self) -> Box<&dyn Cpu> { + Box::new(&self.cpu) + } + fn tick(&mut self) -> instant::Duration { Duration::from_secs_f64(1.0 / 1_000_000.0) * self.cpu.tick() as u32 } From bca14bfaf975c1957e56cf275731460174f74478 Mon Sep 17 00:00:00 2001 From: Brooke Chalmers Date: Fri, 29 Dec 2023 19:53:47 -0800 Subject: [PATCH 6/7] Add cleanup method to System trait (currently only invoked for Winit) Co-authored-by: Ava Silver --- src/platform/mod.rs | 5 +++++ src/platform/winit/mod.rs | 7 ++++++- src/systems/mod.rs | 5 +++++ src/wasm.rs | 2 +- 4 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/platform/mod.rs b/src/platform/mod.rs index 454c649b..4ed73c9c 100644 --- a/src/platform/mod.rs +++ b/src/platform/mod.rs @@ -23,18 +23,23 @@ pub use self::winit::{WinitPlatform, WinitPlatformProvider}; /// It handles starting and ticking the system, and provides a PlatformProvider /// to the system for screen/keyboard/etc. access. pub trait Platform { + /// Return a reference to a provider for systems to interact with this platform. fn provider(&self) -> Arc; } /// A platform which can be run synchronously. pub trait SyncPlatform: Platform { + /// Run the given system within this platform. fn run(&mut self, system: Box); } /// A platform which can be run asynchronously. #[async_trait(?Send)] pub trait AsyncPlatform: Platform { + /// Set up this platform for use. async fn setup(&mut self); + + /// Execute one "step" of this platform. A step is implementation-defined. async fn tick(&mut self, system: &mut Box); } diff --git a/src/platform/winit/mod.rs b/src/platform/winit/mod.rs index 4ee4f0da..021c0533 100644 --- a/src/platform/winit/mod.rs +++ b/src/platform/winit/mod.rs @@ -183,7 +183,12 @@ impl SyncPlatform for WinitPlatform { key_state.lock().unwrap().release(key); } }, - WindowEvent::CloseRequested => *control_flow = ControlFlow::Exit, + WindowEvent::CloseRequested => { + if let Err(msg) = system.cleanup() { + println!("Error during cleanup: {}", msg); + } + *control_flow = ControlFlow::Exit; + } _ => (), }, _ => (), diff --git a/src/systems/mod.rs b/src/systems/mod.rs index fe9c6059..79b2f616 100644 --- a/src/systems/mod.rs +++ b/src/systems/mod.rs @@ -35,4 +35,9 @@ pub trait System { /// Render the current state of the system to the given framebuffer. fn render(&mut self, framebuffer: &mut [u8], window: WindowConfig); + + /// Clean up any resources used by this system. + fn cleanup(&mut self) -> Result<(), &str> { + Ok(()) + } } diff --git a/src/wasm.rs b/src/wasm.rs index 18326a17..cf6ef38b 100644 --- a/src/wasm.rs +++ b/src/wasm.rs @@ -141,7 +141,7 @@ impl Noentiendo { let interval_id = { let system = system.clone(); - let handler: Box ()> = Box::new(move || { + let handler: Box = Box::new(move || { if platform_ready.get() { let platform = platform.clone(); let system = system.clone(); From 688de5e2b4f498e0a86ba458b4e7746652b1b18f Mon Sep 17 00:00:00 2001 From: Brooke Chalmers Date: Fri, 29 Dec 2023 20:04:52 -0800 Subject: [PATCH 7/7] Change `get_cpu` to return mutable reference Co-authored-by: Ava Silver --- src/systems/basic.rs | 4 ++-- src/systems/c64/mod.rs | 4 ++-- src/systems/easy.rs | 4 ++-- src/systems/klaus.rs | 4 ++-- src/systems/mod.rs | 2 +- src/systems/pet/mod.rs | 4 ++-- src/systems/vic/mod.rs | 4 ++-- 7 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/systems/basic.rs b/src/systems/basic.rs index d1ac3f6f..fab01177 100644 --- a/src/systems/basic.rs +++ b/src/systems/basic.rs @@ -91,8 +91,8 @@ pub struct BasicSystem { } impl System for BasicSystem { - fn get_cpu(&self) -> Box<&dyn Cpu> { - Box::new(&self.cpu) + fn get_cpu_mut(&mut self) -> Box<&mut dyn Cpu> { + Box::new(&mut self.cpu) } fn tick(&mut self) -> Duration { diff --git a/src/systems/c64/mod.rs b/src/systems/c64/mod.rs index e46a8c7c..52d57526 100644 --- a/src/systems/c64/mod.rs +++ b/src/systems/c64/mod.rs @@ -313,8 +313,8 @@ pub struct C64System { } impl System for C64System { - fn get_cpu(&self) -> Box<&dyn Cpu> { - Box::new(&self.cpu) + fn get_cpu_mut(&mut self) -> Box<&mut dyn Cpu> { + Box::new(&mut self.cpu) } fn tick(&mut self) -> Duration { diff --git a/src/systems/easy.rs b/src/systems/easy.rs index e0529255..4895b9a1 100644 --- a/src/systems/easy.rs +++ b/src/systems/easy.rs @@ -93,8 +93,8 @@ pub struct Easy6502System { } impl System for Easy6502System { - fn get_cpu(&self) -> Box<&dyn Cpu> { - Box::new(&self.cpu) + fn get_cpu_mut(&mut self) -> Box<&mut dyn Cpu> { + Box::new(&mut self.cpu) } fn tick(&mut self) -> Duration { diff --git a/src/systems/klaus.rs b/src/systems/klaus.rs index bac98073..cb81f1c3 100644 --- a/src/systems/klaus.rs +++ b/src/systems/klaus.rs @@ -45,8 +45,8 @@ pub struct KlausSystem { } impl System for KlausSystem { - fn get_cpu(&self) -> Box<&dyn Cpu> { - Box::new(&self.cpu) + fn get_cpu_mut(&mut self) -> Box<&mut dyn Cpu> { + Box::new(&mut self.cpu) } fn tick(&mut self) -> Duration { diff --git a/src/systems/mod.rs b/src/systems/mod.rs index 79b2f616..3f7e9861 100644 --- a/src/systems/mod.rs +++ b/src/systems/mod.rs @@ -25,7 +25,7 @@ pub trait BuildableSystem { /// A representation of an emulated system. pub trait System { /// Return a mutable reference to the CPU used in this system. - fn get_cpu(&self) -> Box<&dyn Cpu>; + fn get_cpu_mut(&mut self) -> Box<&mut dyn Cpu>; /// Advance the system by one tick. fn tick(&mut self) -> Duration; diff --git a/src/systems/pet/mod.rs b/src/systems/pet/mod.rs index 6a2c6078..9ee8f5b9 100644 --- a/src/systems/pet/mod.rs +++ b/src/systems/pet/mod.rs @@ -210,8 +210,8 @@ pub struct PetSystem { } impl System for PetSystem { - fn get_cpu(&self) -> Box<&dyn Cpu> { - Box::new(&self.cpu) + fn get_cpu_mut(&mut self) -> Box<&mut dyn Cpu> { + Box::new(&mut self.cpu) } fn tick(&mut self) -> Duration { diff --git a/src/systems/vic/mod.rs b/src/systems/vic/mod.rs index 71c1a616..bbd78401 100644 --- a/src/systems/vic/mod.rs +++ b/src/systems/vic/mod.rs @@ -311,8 +311,8 @@ pub struct Vic20System { } impl System for Vic20System { - fn get_cpu(&self) -> Box<&dyn Cpu> { - Box::new(&self.cpu) + fn get_cpu_mut(&mut self) -> Box<&mut dyn Cpu> { + Box::new(&mut self.cpu) } fn tick(&mut self) -> instant::Duration {