diff --git a/.github/workflows/fox32-unstable-linux.yml b/.github/workflows/fox32-unstable-linux.yml index a1143be..22cbd91 100644 --- a/.github/workflows/fox32-unstable-linux.yml +++ b/.github/workflows/fox32-unstable-linux.yml @@ -13,12 +13,6 @@ jobs: steps: - uses: actions/checkout@v2 - - name: Check out fox32core - uses: actions/checkout@v2 - with: - repository: fox32-arch/fox32core - path: ./fox32core - - name: Install Rust toolchain uses: actions-rs/toolchain@v1 with: diff --git a/.github/workflows/fox32-unstable-windows.yml b/.github/workflows/fox32-unstable-windows.yml index 8901555..09e671c 100644 --- a/.github/workflows/fox32-unstable-windows.yml +++ b/.github/workflows/fox32-unstable-windows.yml @@ -7,34 +7,22 @@ on: name: fox32 Unstable - Windows jobs: - fox32-unstable-linux: + fox32-unstable-windows: name: Build - runs-on: ubuntu-latest + runs-on: windows-latest steps: - uses: actions/checkout@v2 - - name: Check out fox32core - uses: actions/checkout@v2 - with: - repository: fox32-arch/fox32core - path: ./fox32core - - name: Install Rust toolchain uses: actions-rs/toolchain@v1 with: toolchain: stable override: true - target: x86_64-pc-windows-gnu - - - name: Install libgtk-3-dev, libasound2-dev, and mingw-w64 - run: | - sudo apt update - sudo apt install -y libgtk-3-dev libasound2-dev mingw-w64 - name: Build - run: cargo build --release --target x86_64-pc-windows-gnu + run: cargo build --release - - name: Upload Artifact + - name: Upload artifact uses: actions/upload-artifact@v2 with: name: fox32.exe diff --git a/.gitignore b/.gitignore index 3b49df3..a997dfc 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,4 @@ **/.vscode/ -**/fox32core/ - **/debug/ **/target/ diff --git a/Cargo.lock b/Cargo.lock index cc1783f..bc5b259 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -51,15 +51,6 @@ dependencies = [ "pkg-config", ] -[[package]] -name = "ansi_term" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" -dependencies = [ - "winapi", -] - [[package]] name = "anyhow" version = "1.0.53" @@ -199,17 +190,6 @@ dependencies = [ "system-deps", ] -[[package]] -name = "atty" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" -dependencies = [ - "hermit-abi", - "libc", - "winapi", -] - [[package]] name = "autocfg" version = "1.0.1" @@ -225,18 +205,14 @@ dependencies = [ "bitflags", "cexpr", "clang-sys", - "clap", - "env_logger", "lazy_static", "lazycell", - "log", "peeking_take_while", "proc-macro2", "quote", "regex", "rustc-hash", "shlex", - "which", ] [[package]] @@ -397,21 +373,6 @@ dependencies = [ "libloading", ] -[[package]] -name = "clap" -version = "2.34.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" -dependencies = [ - "ansi_term", - "atty", - "bitflags", - "strsim 0.8.0", - "textwrap", - "unicode-width", - "vec_map", -] - [[package]] name = "claxon" version = "0.4.3" @@ -706,7 +667,7 @@ dependencies = [ "ident_case", "proc-macro2", "quote", - "strsim 0.10.0", + "strsim", "syn", ] @@ -815,19 +776,6 @@ dependencies = [ "syn", ] -[[package]] -name = "env_logger" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b2cf0344971ee6c64c31be0d530793fba457d322dfec2810c453d0ef228f9c3" -dependencies = [ - "atty", - "humantime", - "log", - "regex", - "termcolor", -] - [[package]] name = "event-listener" version = "2.5.2" @@ -920,7 +868,6 @@ name = "fox32" version = "0.1.0" dependencies = [ "anyhow", - "fox32core", "image", "log", "pixels", @@ -932,15 +879,6 @@ dependencies = [ "winit_input_helper", ] -[[package]] -name = "fox32core" -version = "0.1.0" -dependencies = [ - "bindgen", - "cc", - "libc", -] - [[package]] name = "futures" version = "0.3.19" @@ -1298,12 +1236,6 @@ version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a164bb2ceaeff4f42542bdb847c41517c78a60f5649671b2a07312b6e117549" -[[package]] -name = "humantime" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" - [[package]] name = "ident_case" version = "1.0.1" @@ -2544,12 +2476,6 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef5430c8e36b713e13b48a9f709cc21e046723fe44ce34587b73a830203b533e" -[[package]] -name = "strsim" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" - [[package]] name = "strsim" version = "0.10.0" @@ -2589,15 +2515,6 @@ dependencies = [ "winapi-util", ] -[[package]] -name = "textwrap" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" -dependencies = [ - "unicode-width", -] - [[package]] name = "thiserror" version = "1.0.30" @@ -2733,12 +2650,6 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" -[[package]] -name = "vec_map" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" - [[package]] name = "vergen" version = "6.0.2" @@ -3045,17 +2956,6 @@ dependencies = [ "bitflags", ] -[[package]] -name = "which" -version = "4.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c4fb54e6113b6a8772ee41c3404fb0301ac79604489467e0a9ce1f3e97c24ae" -dependencies = [ - "either", - "lazy_static", - "libc", -] - [[package]] name = "wide" version = "0.6.5" diff --git a/Cargo.toml b/Cargo.toml index e39c3bd..47e8401 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,7 +8,6 @@ build = "build.rs" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -fox32core = { path = "./fox32core" } image = "0.24" log = "0.4" pixels = "0.9.0" diff --git a/README.md b/README.md index cbeef32..26241b3 100644 --- a/README.md +++ b/README.md @@ -12,9 +12,7 @@ ### Building -Clone this repository, `cd` into it, then clone the [fox32core](https://github.com/fox32-arch/fox32core) repository in a folder called `fox32core`. - -After that, just run `cargo build --release`. The resulting binary will be saved as `target/release/fox32` +Simply run `cargo build --release`. The resulting binary will be saved as `target/release/fox32`. You can also run `cargo run --release` if you want to run it directly. ### Usage diff --git a/src/bus.rs b/src/bus.rs index 16a20d0..ec81fc8 100644 --- a/src/bus.rs +++ b/src/bus.rs @@ -6,7 +6,7 @@ use std::sync::{Arc, Mutex}; use std::io::{Write, stdout}; pub struct Bus { - pub memory: Box, + pub memory: Memory, pub disk_controller: DiskController, @@ -99,7 +99,7 @@ impl Bus { panic!("invalid disk ID"); } match &self.disk_controller.disk[id as usize] { - Some(disk) => disk.size() as u32, // return size if this disk is inserted + Some(_) => self.disk_controller.get_size(id) as u32, // return size if this disk is inserted None => 0, // return 0 if this disk is not inserted } } @@ -226,14 +226,3 @@ impl Bus { } } } - -impl fox32core::Bus for Bus { - fn io_read(&mut self, port: u32) -> Option { - Some(self.read_io(port)) - } - - fn io_write(&mut self, port: u32, value: u32) -> Option<()> { - self.write_io(port, value); - Some(()) - } -} diff --git a/src/disk.rs b/src/disk.rs index a8ed301..8e1185b 100644 --- a/src/disk.rs +++ b/src/disk.rs @@ -20,10 +20,6 @@ impl Disk { current_sector: 0, } } - - pub fn size(&self) -> u64 { - self.size - } } pub struct DiskController { @@ -33,7 +29,7 @@ pub struct DiskController { impl DiskController { pub fn new() -> Self { - Self { + DiskController { disk: [None, None, None, None], buffer_pointer: 0x00000000 } @@ -60,24 +56,20 @@ impl DiskController { self.disk[disk_id as usize] = None; } - fn disk_mut(&mut self, disk_id: u8) -> &mut Disk { - self.disk[disk_id as usize].as_mut().expect("attempted to access unmounted disk") + pub fn get_size(&self, disk_id: u8) -> u64 { + self.disk[disk_id as usize].as_ref().expect("attempted to access unmounted disk").size } - - pub fn get_size(&mut self, disk_id: u8) -> u64 { - self.disk_mut(disk_id).size - } - pub fn get_current_sector(&mut self, disk_id: u8) -> u32 { - self.disk_mut(disk_id).current_sector + pub fn get_current_sector(&self, disk_id: u8) -> u32 { + self.disk[disk_id as usize].as_ref().expect("attempted to access unmounted disk").current_sector } pub fn set_current_sector(&mut self, disk_id: u8, sector: u32) { - let disk = self.disk_mut(disk_id); + let mut disk = self.disk[disk_id as usize].as_mut().expect("attempted to access unmounted disk"); disk.current_sector = sector; disk.file.seek(SeekFrom::Start(sector as u64 * 512)).expect("attempted to seek to sector beyond edge of disk"); } pub fn read_into_memory(&mut self, disk_id: u8, ram: &mut MemoryRam) -> usize { - let disk = self.disk_mut(disk_id); + let disk = self.disk[disk_id as usize].as_mut().expect("attempted to access unmounted disk"); let mut temp_buffer = [0u8; 512]; let number_of_bytes_read = disk.file.read(&mut temp_buffer).unwrap(); diff --git a/src/main.rs b/src/main.rs index 0ba18ba..728d725 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,8 +7,6 @@ pub mod cpu; pub mod keyboard; pub mod mouse; pub mod disk; -pub mod runtime; -pub mod wrapped; use audio::Audio; use bus::Bus; @@ -16,13 +14,8 @@ use cpu::{Cpu, Interrupt}; use keyboard::Keyboard; use mouse::Mouse; use disk::DiskController; -use memory::{MEMORY_RAM_START, MEMORY_ROM_START, MemoryRam, Memory, MemoryStub, MemoryBuffer}; -use runtime::Runtime; -use wrapped::*; +use memory::{MEMORY_RAM_START, MEMORY_ROM_START, MemoryRam, Memory}; -use std::io::Write; -use std::mem; -use std::ops::Deref; use std::sync::{Arc, mpsc, Mutex}; use std::thread; use std::time; @@ -92,8 +85,9 @@ fn main() { let audio = Arc::new(Mutex::new(Audio::new())); + let memory = Memory::new(read_rom().as_slice()); let mut bus = Bus { - memory: Box::new(MemoryStub()), + memory: memory.clone(), audio: audio.clone(), disk_controller: DiskController::new(), keyboard: keyboard.clone(), @@ -109,38 +103,6 @@ fn main() { } } - let (mut runtime, memory): (Box, MemoryWrapped) = { - if env::var("FOX32_RUNTIME").unwrap_or_default() == "core" { - - println!("Using \"fox32core\" runtime"); - - let bus_wrapped = BusWrapped::new(bus); - let state = fox32core::State::new(bus_wrapped.clone()); - *state.debug() = env::var("FOX32_DEBUG").is_ok(); - let state_wrapped = CoreWrapped::new(state); - let state_memory_wrapped = MemoryWrapped::new(CoreMemoryWrapped::new(state_wrapped.clone())); - - mem::drop(mem::replace(&mut bus_wrapped.deref().borrow_mut().memory, Box::new(state_memory_wrapped.clone()))); - - (Box::new(state_wrapped.clone()), state_memory_wrapped.clone()) - - } else { - - println!("Using \"rust\" runtime"); - - let memory = MemoryWrapped::new(MemoryBuffer::new()); - - mem::drop(mem::replace(&mut bus.memory, Box::new(memory.clone()))); - - (Box::new(Cpu::new(bus)), memory) - - } - }; - - memory.rom().as_mut_slice().write(read_rom().as_slice()).expect("failed to write ROM"); - - runtime.halted_set(false); - let memory_audio = memory.clone(); let memory_cpu = memory.clone(); let memory_eventloop = memory.clone(); @@ -155,6 +117,8 @@ fn main() { let rom_top_address = rom_bottom_address + rom_size - 1; println!("ROM: {:.2} KiB mapped at {:#010X}-{:#010X}", rom_size / 1024, rom_bottom_address, rom_top_address); + let mut cpu = Cpu::new(bus); + let event_loop = EventLoop::new(); let mut input = WinitInputHelper::new(); let icon = image::load_from_memory(include_bytes!("32.png")).unwrap(); @@ -177,26 +141,26 @@ fn main() { Pixels::new(WIDTH as u32, HEIGHT as u32, surface_texture).unwrap() }; - let (interrupt_sender, interrupt_receiver) = mpsc::channel::(); + let (interrupt_sender, interrupt_receiver) = mpsc::channel::(); let builder = thread::Builder::new().name("cpu".to_string()); builder.spawn({ move || { loop { - while !runtime.halted_get() { + while !cpu.halted { if let Ok(interrupt) = interrupt_receiver.try_recv() { - runtime.raise(interrupt); + cpu.interrupt(interrupt); } - runtime.step(); + cpu.execute_memory_instruction(); } - if !runtime.flag_interrupt_get() { + if !cpu.flag.interrupt { // the cpu was halted and interrupts are disabled // at this point, the cpu is dead and cannot resume, break out of the loop break; } if let Ok(interrupt) = interrupt_receiver.recv() { - runtime.halted_set(false); - runtime.raise(interrupt); + cpu.halted = false; + cpu.interrupt(interrupt); } else { // sender is closed, break break; @@ -226,7 +190,7 @@ fn main() { let buffer = SamplesBuffer::new(1, 22050, current_buffer); sink.append(buffer); drop(audio_lock); - interrupt_sender_audio.send(0xFE).unwrap(); // audio interrupt, swap audio buffers + interrupt_sender_audio.send(Interrupt::Request(0xFE)).unwrap(); // audio interrupt, swap audio buffers thread::sleep(time::Duration::from_millis(500)); } } @@ -240,7 +204,7 @@ fn main() { if let Event::MainEventsCleared = event { // update internal state and request a redraw - match interrupt_sender.send(0xFF) { // vsync interrupt + match interrupt_sender.send(Interrupt::Request(0xFF)) { // vsync interrupt Ok(_) => {}, Err(_) => { *control_flow = ControlFlow::Exit; diff --git a/src/memory.rs b/src/memory.rs index d49d19a..23ccd3d 100644 --- a/src/memory.rs +++ b/src/memory.rs @@ -1,6 +1,7 @@ // memory.rs -use std::alloc; +use crate::error; + use std::cell::UnsafeCell; use std::sync::Arc; use std::io::Write; @@ -15,104 +16,103 @@ pub const MEMORY_ROM_START: usize = 0xF0000000; pub type MemoryRam = [u8; MEMORY_RAM_SIZE]; pub type MemoryRom = [u8; MEMORY_ROM_SIZE]; -pub trait Memory: Send { - fn ram(&self) -> &mut MemoryRam; - fn rom(&self) -> &mut MemoryRom; +struct MemoryInner { + ram: Box, + rom: Box, } -impl dyn Memory { - fn arrayslice(array: &mut [T; ARRAY_LEN], offset: usize) -> &mut [T; SLICE_LEN] { - assert!(ARRAY_LEN >= SLICE_LEN + offset, "attempted slice [{}..{}] of array with length {}", offset, offset + SLICE_LEN, ARRAY_LEN); - unsafe { &mut *array.as_mut_ptr().offset(offset as isize).cast() } - } - - fn find(&self, address: u32) -> Option<&mut [u8; S]> { - let head = address as usize; - let tail = head.checked_add(S).expect("unexpected overflow computing tail address"); - if head >= MEMORY_RAM_START && tail - MEMORY_RAM_START <= MEMORY_RAM_SIZE { - return Self::arrayslice(self.ram(), head - MEMORY_RAM_START).into() - } - if head >= MEMORY_ROM_START && tail - MEMORY_ROM_START <= MEMORY_ROM_SIZE { - return Self::arrayslice(self.rom(), head - MEMORY_ROM_START).into() - } - return None - } - fn find_unwrapped(&self, address: u32) -> &mut [u8; S] { - self.find(address).unwrap_or_else(|| panic!("attempted to access unmapped memory at {:#010X}", address)) - } - - pub fn read_8(&self, address: u32) -> u8 { u8::from_le_bytes(*self.find_unwrapped(address)) } - pub fn read_16(&self, address: u32) -> u16 { u16::from_le_bytes(*self.find_unwrapped(address)) } - pub fn read_32(&self, address: u32) -> u32 { u32::from_le_bytes(*self.find_unwrapped(address)) } - - pub fn write_8(&self, address: u32, value: u8) { *self.find_unwrapped(address) = u8::to_le_bytes(value) } - pub fn write_16(&self, address: u32, value: u16) { *self.find_unwrapped(address) = u16::to_le_bytes(value) } - pub fn write_32(&self, address: u32, value: u32) { *self.find_unwrapped(address) = u32::to_le_bytes(value) } - - pub fn dump(&self) { - File::create("memory.dump") - .expect("failed to open memory dump file") - .write_all(self.ram()) - .expect("failed to write memory dump file"); +impl MemoryInner { + pub fn new(rom: &[u8]) -> Self { + let mut this = Self { + // HACK: allocate directly on the heap to avoid a stack overflow + // at runtime while trying to move around a 64MB array + ram: unsafe { Box::from_raw(Box::into_raw(vec![0u8; MEMORY_RAM_SIZE].into_boxed_slice()) as *mut MemoryRam) }, + rom: unsafe { Box::from_raw(Box::into_raw(vec![0u8; MEMORY_ROM_SIZE].into_boxed_slice()) as *mut MemoryRom) }, + }; + this.rom.as_mut_slice().write(rom).expect("failed to copy ROM to memory"); + this } } -struct MemoryBufferInner { - ram: *mut MemoryRam, - rom: *mut MemoryRom, -} +#[derive(Clone)] +pub struct Memory(Arc>); -static MEMORY_RAM_LAYOUT: alloc::Layout = alloc::Layout::new::(); -static MEMORY_ROM_LAYOUT: alloc::Layout = alloc::Layout::new::(); +// SAFETY: once MemoryInner is initialzed, there is no way to modify the Box +// pointers it contains and it does not matter if contents of the byte +// arrays are corrupted +unsafe impl Send for Memory {} +unsafe impl Sync for Memory {} -impl Default for MemoryBufferInner { - fn default() -> Self { - unsafe { - let ram = alloc::alloc_zeroed(MEMORY_RAM_LAYOUT); - if ram.is_null() { alloc::handle_alloc_error(MEMORY_RAM_LAYOUT) } - - let rom = alloc::alloc_zeroed(MEMORY_ROM_LAYOUT); - if rom.is_null() { alloc::handle_alloc_error(MEMORY_ROM_LAYOUT) } - - Self { ram: ram.cast(), rom: rom.cast() } - } - } -} - -impl Drop for MemoryBufferInner { - fn drop(&mut self) { - unsafe { - alloc::dealloc(self.ram.cast(), MEMORY_RAM_LAYOUT); - alloc::dealloc(self.rom.cast(), MEMORY_ROM_LAYOUT); - } - } -} - -#[derive(Default, Clone)] -pub struct MemoryBuffer(Arc>); - -unsafe impl Send for MemoryBuffer {} -unsafe impl Sync for MemoryBuffer {} - -impl MemoryBuffer { - pub fn new() -> Self { - Self::default() +impl Memory { + pub fn new(rom: &[u8]) -> Self { + Self(Arc::new(UnsafeCell::new(MemoryInner::new(rom)))) } - fn inner(&self) -> &mut MemoryBufferInner { + fn inner(&self) -> &mut MemoryInner { unsafe { &mut *self.0.get() } } -} -impl Memory for MemoryBuffer { - fn ram(&self) -> &mut MemoryRam { unsafe { &mut *self.inner().ram } } - fn rom(&self) -> &mut MemoryRom { unsafe { &mut *self.inner().rom } } -} + pub fn ram(&self) -> &mut MemoryRam { &mut self.inner().ram } + pub fn rom(&self) -> &mut MemoryRom { &mut self.inner().rom } -#[derive(Default, Clone, Copy)] -pub struct MemoryStub(); + pub fn dump(&self) { + let mut file = File::create("memory.dump").expect("failed to open memory dump file"); + file.write_all(self.ram()).expect("failed to write memory dump file"); + } -impl Memory for MemoryStub { - fn ram(&self) -> &mut MemoryRam { unimplemented!() } - fn rom(&self) -> &mut MemoryRom { unimplemented!() } + pub fn read_8(&self, address: u32) -> u8 { + let address = address as usize; + + let result = if address >= MEMORY_ROM_START && address < MEMORY_ROM_START + MEMORY_ROM_SIZE { + self.rom().get(address - MEMORY_ROM_START) + } else { + self.ram().get(address - MEMORY_RAM_START) + }; + + match result { + Some(value) => { + *value + } + None => { + error(&format!("attempting to read from unmapped memory address: {:#010X}", address)); + } + } + } + pub fn read_16(&self, address: u32) -> u16 { + (self.read_8(address) as u16) | + (self.read_8(address + 1) as u16) << 8 + } + pub fn read_32(&self, address: u32) -> u32 { + (self.read_8(address) as u32) | + (self.read_8(address + 1) as u32) << 8 | + (self.read_8(address + 2) as u32) << 16 | + (self.read_8(address + 3) as u32) << 24 + } + + pub fn write_8(&self, address: u32, byte: u8) { + let address = address as usize; + + if address >= MEMORY_ROM_START && address < MEMORY_ROM_START + MEMORY_ROM_SIZE { + error(&format!("attempting to write to ROM address: {:#010X}", address)); + } + + match self.ram().get_mut(address - MEMORY_RAM_START) { + Some(value) => { + *value = byte; + } + None => { + error(&format!("attempting to write to unmapped memory address: {:#010X}", address)); + } + } + } + pub fn write_16(&self, address: u32, half: u16) { + self.write_8(address, (half & 0x00FF) as u8); + self.write_8(address + 1, (half >> 8) as u8); + } + pub fn write_32(&self, address: u32, word: u32) { + self.write_8(address, (word & 0x000000FF) as u8); + self.write_8(address + 1, ((word & 0x0000FF00) >> 8) as u8); + self.write_8(address + 2, ((word & 0x00FF0000) >> 16) as u8); + self.write_8(address + 3, ((word & 0xFF000000) >> 24) as u8); + } } diff --git a/src/runtime.rs b/src/runtime.rs deleted file mode 100644 index 163f668..0000000 --- a/src/runtime.rs +++ /dev/null @@ -1,68 +0,0 @@ -// runtime.rs - -pub trait Runtime: Send { - fn halted_get(&mut self) -> bool; - fn halted_set(&mut self, halted: bool); - - fn flag_interrupt_get(&mut self) -> bool; - fn flag_interrupt_set(&mut self, flag_interrupt: bool); - - fn raise(&mut self, vector: u16); - - fn step(&mut self); -} - -impl Runtime for crate::Cpu { - fn halted_get(&mut self) -> bool { - self.halted - } - fn halted_set(&mut self, halted: bool) { - self.halted = halted - } - - fn flag_interrupt_get(&mut self) -> bool { - self.flag.interrupt - } - fn flag_interrupt_set(&mut self, flag_interrupt: bool) { - self.flag.interrupt = flag_interrupt - } - - fn raise(&mut self, vector: u16) { - self.interrupt(crate::Interrupt::Request(vector as u8)); - } - - fn step(&mut self) { - self.execute_memory_instruction(); - } -} - -impl Runtime for fox32core::State { - fn halted_get(&mut self) -> bool { - *self.halted() - } - fn halted_set(&mut self, halted: bool) { - *self.halted() = halted; - } - - fn flag_interrupt_get(&mut self) -> bool { - *self.flag_interrupt() - } - fn flag_interrupt_set(&mut self, flag_interrupt: bool) { - *self.flag_interrupt() = flag_interrupt; - } - - fn raise(&mut self, vector: u16) { - match fox32core::State::raise(self, vector) { - Some(fox32core::Error::InterruptsDisabled) | None => {} - Some(error) => { - panic!("fox32core failed to raise interrupt {:#06X}: {}", vector, error); - } - } - } - - fn step(&mut self) { - if let Some(error) = fox32core::State::step(self) { - panic!("fox32core failed to execute next instruction: {}", error); - } - } -} diff --git a/src/wrapped.rs b/src/wrapped.rs deleted file mode 100644 index d8c7490..0000000 --- a/src/wrapped.rs +++ /dev/null @@ -1,116 +0,0 @@ -// wrapped.rs - -use std::ops::Deref; -use std::cell::RefCell; -use std::cell::UnsafeCell; -use std::sync::Arc; - -use crate::bus::Bus; -use crate::memory::*; -use crate::runtime::*; - -#[derive(Clone)] -pub struct MemoryWrapped(Arc); - -unsafe impl Send for MemoryWrapped {} -unsafe impl Sync for MemoryWrapped {} - -impl MemoryWrapped { - pub fn new(memory: impl Memory + 'static) -> Self { - Self(Arc::new(memory)) - } -} - -impl Memory for MemoryWrapped { - fn ram(&self) -> &mut MemoryRam { self.0.ram() } - fn rom(&self) -> &mut MemoryRom { self.0.rom() } -} - -impl Memory for fox32core::State { - fn ram(&self) -> &mut MemoryRam { self.memory_ram() } - fn rom(&self) -> &mut MemoryRom { self.memory_rom() } -} - -#[derive(Clone)] -pub struct BusWrapped(Arc>); - -impl BusWrapped { - pub fn new(bus: Bus) -> Self { - Self(Arc::new(RefCell::new(bus))) - } -} - -impl Deref for BusWrapped { - type Target = RefCell; - fn deref(&self) -> &Self::Target { &self.0 } -} - -impl fox32core::Bus for BusWrapped { - fn io_read(&mut self, port: u32) -> Option { - self.borrow_mut().io_read(port) - } - fn io_write(&mut self, port: u32, value: u32) -> Option<()> { - self.borrow_mut().io_write(port, value) - } -} - -#[derive(Clone)] -pub struct CoreWrapped(Arc>); - -unsafe impl Send for CoreWrapped {} - -impl CoreWrapped { - pub fn new(state: fox32core::State) -> Self { - Self(Arc::new(UnsafeCell::new(state))) - } - - fn inner(&self) -> *mut fox32core::State { - self.0.get() - } -} - -impl Memory for CoreWrapped { - fn ram(&self) -> &mut MemoryRam { unsafe { (*self.inner()).ram() } } - fn rom(&self) -> &mut MemoryRom { unsafe { (*self.inner()).rom() } } -} - -impl Runtime for CoreWrapped { - fn halted_get(&mut self) -> bool { - unsafe { (*self.inner()).halted_get() } - } - fn halted_set(&mut self, halted: bool) { - unsafe { (*self.inner()).halted_set(halted) } - } - - fn flag_interrupt_get(&mut self) -> bool { - unsafe { (*self.inner()).flag_interrupt_get() } - } - fn flag_interrupt_set(&mut self, flag_interrupt: bool) { - unsafe { (*self.inner()).flag_interrupt_set(flag_interrupt) } - } - - fn raise(&mut self, vector: u16) { - unsafe { Runtime::raise(&mut *self.inner(), vector) } - } - - fn step(&mut self) { - unsafe { Runtime::step(&mut *self.inner()) } - } -} - -#[derive(Clone)] -pub struct CoreMemoryWrapped(CoreWrapped); - -unsafe impl Send for CoreMemoryWrapped {} -unsafe impl Sync for CoreMemoryWrapped {} - -impl CoreMemoryWrapped { - pub fn new(state_wrapped: CoreWrapped) -> Self { - Self(state_wrapped) - } -} - -impl Memory for CoreMemoryWrapped { - fn ram(&self) -> &mut MemoryRam { self.0.ram() } - fn rom(&self) -> &mut MemoryRom { self.0.rom() } -}