Remove fox32core support

This works around the issue with building on Windows.
This commit is contained in:
Ry 2022-07-23 17:56:09 -07:00
parent 16b43cc87a
commit bd7eba3ddb
12 changed files with 116 additions and 478 deletions

View File

@ -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:

View File

@ -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

2
.gitignore vendored
View File

@ -1,6 +1,4 @@
**/.vscode/
**/fox32core/
**/debug/
**/target/

102
Cargo.lock generated
View File

@ -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"

View File

@ -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"

View File

@ -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

View File

@ -6,7 +6,7 @@ use std::sync::{Arc, Mutex};
use std::io::{Write, stdout};
pub struct Bus {
pub memory: Box<dyn Memory>,
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<u32> {
Some(self.read_io(port))
}
fn io_write(&mut self, port: u32, value: u32) -> Option<()> {
self.write_io(port, value);
Some(())
}
}

View File

@ -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();

View File

@ -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<dyn Runtime>, 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::<u16>();
let (interrupt_sender, interrupt_receiver) = mpsc::channel::<Interrupt>();
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;

View File

@ -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<MemoryRam>,
rom: Box<MemoryRom>,
}
impl dyn Memory {
fn arrayslice<T, const ARRAY_LEN: usize, const SLICE_LEN: usize>(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<const S: usize>(&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<const S: usize>(&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<UnsafeCell<MemoryInner>>);
// 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 Memory {
pub fn new(rom: &[u8]) -> Self {
Self(Arc::new(UnsafeCell::new(MemoryInner::new(rom))))
}
static MEMORY_RAM_LAYOUT: alloc::Layout = alloc::Layout::new::<MemoryRam>();
static MEMORY_ROM_LAYOUT: alloc::Layout = alloc::Layout::new::<MemoryRom>();
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<UnsafeCell<MemoryBufferInner>>);
unsafe impl Send for MemoryBuffer {}
unsafe impl Sync for MemoryBuffer {}
impl MemoryBuffer {
pub fn new() -> Self {
Self::default()
}
fn inner(&self) -> &mut MemoryBufferInner {
fn inner(&self) -> &mut MemoryInner {
unsafe { &mut *self.0.get() }
}
pub fn ram(&self) -> &mut MemoryRam { &mut self.inner().ram }
pub fn rom(&self) -> &mut MemoryRom { &mut self.inner().rom }
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 MemoryBuffer {
fn ram(&self) -> &mut MemoryRam { unsafe { &mut *self.inner().ram } }
fn rom(&self) -> &mut MemoryRom { unsafe { &mut *self.inner().rom } }
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
}
#[derive(Default, Clone, Copy)]
pub struct MemoryStub();
pub fn write_8(&self, address: u32, byte: u8) {
let address = address as usize;
impl Memory for MemoryStub {
fn ram(&self) -> &mut MemoryRam { unimplemented!() }
fn rom(&self) -> &mut MemoryRom { unimplemented!() }
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);
}
}

View File

@ -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);
}
}
}

View File

@ -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<dyn Memory>);
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<RefCell<Bus>>);
impl BusWrapped {
pub fn new(bus: Bus) -> Self {
Self(Arc::new(RefCell::new(bus)))
}
}
impl Deref for BusWrapped {
type Target = RefCell<Bus>;
fn deref(&self) -> &Self::Target { &self.0 }
}
impl fox32core::Bus for BusWrapped {
fn io_read(&mut self, port: u32) -> Option<u32> {
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<UnsafeCell<fox32core::State>>);
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() }
}