use std::rc::Rc; use std::cell::RefCell; use moa_core::{System, Bus, Error, Observable, Clock, ClockElapsed, Address, Addressable, AddressRepeater, Steppable, Transmutable, TransmutableBox, wrap_transmutable}; use moa_peripherals_mos::Mos6522; use moa_peripherals_zilog::Z8530; use crate::peripherals::iwm::IWM; const DEV_NAME: &str = "mac"; pub struct Mainboard { lower_bus: Rc>, scc1: Z8530, scc2: Z8530, iwm: IWM, via: Mos6522, phase_read: PhaseRead, last_sec: Clock, } impl Mainboard { pub fn create(ram: TransmutableBox, rom: TransmutableBox) -> Result { let scc1 = Z8530::default(); let scc2 = Z8530::default(); let iwm = IWM::default(); let via = Mos6522::default(); let phase_read = PhaseRead::default(); let lower_bus = Rc::new(RefCell::new(Bus::default())); let mainboard = Self { lower_bus: lower_bus.clone(), scc1, scc2, iwm, via, phase_read, last_sec: 0, }; mainboard.via.port_a.set_observer(move |port| { if (port.data & 0x10) == 0 { println!("{}: overlay is 0 (normal)", DEV_NAME); lower_bus.borrow_mut().clear_all_bus_devices(); lower_bus.borrow_mut().insert(0x000000, wrap_transmutable(AddressRepeater::new(ram.clone(), 0x400000))); lower_bus.borrow_mut().insert(0x400000, wrap_transmutable(AddressRepeater::new(rom.clone(), 0x100000))); lower_bus.borrow_mut().insert(0x600000, wrap_transmutable(AddressRepeater::new(rom.clone(), 0x100000))); } else { println!("{}: overlay is 1 (startup)", DEV_NAME); lower_bus.borrow_mut().clear_all_bus_devices(); lower_bus.borrow_mut().insert(0x000000, wrap_transmutable(AddressRepeater::new(rom.clone(), 0x100000))); lower_bus.borrow_mut().insert(0x200000, wrap_transmutable(AddressRepeater::new(rom.clone(), 0x100000))); lower_bus.borrow_mut().insert(0x400000, wrap_transmutable(AddressRepeater::new(rom.clone(), 0x100000))); lower_bus.borrow_mut().insert(0x600000, wrap_transmutable(AddressRepeater::new(ram.clone(), 0x200000))); } }); mainboard.via.port_a.notify(); Ok(mainboard) } } impl Addressable for Mainboard { fn len(&self) -> usize { 0x01000000 } fn read(&mut self, addr: Address, data: &mut [u8]) -> Result<(), Error> { if addr < 0x800000 { self.lower_bus.borrow_mut().read(addr, data) } else if (0x900000..0xA00000).contains(&addr) { self.scc1.read((addr >> 9) & 0x0F, data) } else if (0xB00000..0xC00000).contains(&addr) { self.scc2.read((addr >> 9) & 0x0F, data) } else if (0xD00000..0xE00000).contains(&addr) { self.iwm.read((addr >> 9) & 0x0F, data) } else if (0xE80000..0xF00000).contains(&addr) { self.via.read((addr >> 9) & 0x0F, data) } else if (0xF00000..0xF80000).contains(&addr) { self.phase_read.read(addr, data) } else if (0xF80000..0xF80010).contains(&addr) { // Debugger Ok(()) } else { Err(Error::new(&format!("Error reading address {:#010x}", addr))) } } fn write(&mut self, addr: Address, data: &[u8]) -> Result<(), Error> { if addr < 0x800000 { self.lower_bus.borrow_mut().write(addr, data) } else if (0x900000..0xA00000).contains(&addr) { self.scc1.write((addr >> 9) & 0x0F, data) } else if (0xB00000..0xC00000).contains(&addr) { self.scc2.write((addr >> 9) & 0x0F, data) } else if (0xD00000..0xE00000).contains(&addr) { self.iwm.write((addr >> 9) & 0x0F, data) } else if (0xE80000..0xF00000).contains(&addr) { self.via.write((addr >> 9) & 0x0F, data) } else if (0xF00000..0xF80000).contains(&addr) { self.phase_read.write(addr, data) } else { Err(Error::new(&format!("Error writing address {:#010x}", addr))) } } } impl Steppable for Mainboard { fn step(&mut self, system: &System) -> Result { let elapsed = self.via.step(system)?; // TODO should this be 1 second, or a multiple of 979_200, which is an 8th of the CPU clock if self.last_sec + 1_000_000_000 > system.clock { self.last_sec += 1_000_000_000; //let port_a = self.via.port_a.borrow_mut(); // TODO how will the ca1/ca2 cb1/cb2 pins work in the via system.get_interrupt_controller().set(true, 1, 25)?; } Ok(elapsed) } } impl Transmutable for Mainboard { fn as_addressable(&mut self) -> Option<&mut dyn Addressable> { Some(self) } fn as_steppable(&mut self) -> Option<&mut dyn Steppable> { Some(self) } } #[derive(Default)] pub struct PhaseRead { } impl Addressable for PhaseRead { fn len(&self) -> usize { 0x80000 } fn read(&mut self, _addr: Address, data: &mut [u8]) -> Result<(), Error> { // TODO I'm not sure how this is supposed to work data[0] = 0x00; Ok(()) } fn write(&mut self, _addr: Address, _data: &[u8]) -> Result<(), Error> { // TODO I'm not sure how this is supposed to work Ok(()) } }