diff --git a/src/machines/genesis.rs b/src/machines/genesis.rs index 8a953c8..ba12083 100644 --- a/src/machines/genesis.rs +++ b/src/machines/genesis.rs @@ -4,12 +4,16 @@ use std::cell::RefCell; use crate::error::Error; use crate::system::System; +use crate::signals::Signal; use crate::memory::{MemoryBlock, Bus, BusPort}; use crate::devices::{wrap_transmutable, Address, Addressable, Debuggable}; use crate::cpus::m68k::{M68k, M68kType}; use crate::cpus::z80::{Z80, Z80Type}; +use crate::peripherals::ym2612::YM2612; +use crate::peripherals::sn76489::SN76489; use crate::peripherals::genesis; +use crate::peripherals::genesis::coprocessor::{CoprocessorBankRegister, CoprocessorBankArea}; use crate::host::traits::{Host}; @@ -56,14 +60,28 @@ pub fn build_genesis(host: &mut H, options: SegaGenesisOptions) -> Resu system.add_addressable_device(0x00ff0000, wrap_transmutable(ram)).unwrap(); + // Build the Coprocessor's Bus + let bank_register = Signal::new(0); let coproc_bus = Rc::new(RefCell::new(Bus::new())); - let coproc_mem = wrap_transmutable(MemoryBlock::new(vec![0; 0x00010000])); - coproc_bus.borrow_mut().insert(0x0000, coproc_mem.borrow_mut().as_addressable().unwrap().len(), coproc_mem.clone()); + let coproc_ram = wrap_transmutable(MemoryBlock::new(vec![0; 0x00002000])); + let coproc_ym_sound = wrap_transmutable(YM2612::new()); + let coproc_sn_sound = wrap_transmutable(SN76489::new()); + let coproc_register = wrap_transmutable(CoprocessorBankRegister::new(bank_register.clone())); + let coproc_area = wrap_transmutable(CoprocessorBankArea::new(bank_register, system.bus.clone())); + coproc_bus.borrow_mut().insert(0x0000, coproc_ram.clone()); + coproc_bus.borrow_mut().insert(0x4000, coproc_ym_sound.clone()); + coproc_bus.borrow_mut().insert(0x6000, coproc_register.clone()); + coproc_bus.borrow_mut().insert(0x7f11, coproc_sn_sound.clone()); + coproc_bus.borrow_mut().insert(0x8000, coproc_area); let mut coproc = Z80::new(Z80Type::Z80, 3_579_545, BusPort::new(0, 16, 8, coproc_bus.clone())); let reset = coproc.reset.clone(); let bus_request = coproc.bus_request.clone(); - system.add_addressable_device(0x00a00000, coproc_mem)?; + // Add coprocessor devices to the system bus so the 68000 can access them too + system.add_addressable_device(0x00a00000, coproc_ram)?; + system.add_addressable_device(0x00a04000, coproc_ym_sound)?; + system.add_addressable_device(0x00a06000, coproc_register)?; + system.add_addressable_device(0x00c00010, coproc_sn_sound)?; system.add_device("coproc", wrap_transmutable(coproc))?; diff --git a/src/memory.rs b/src/memory.rs index 9e4a4a1..fb20079 100644 --- a/src/memory.rs +++ b/src/memory.rs @@ -128,7 +128,8 @@ impl Bus { } } - pub fn insert(&mut self, base: Address, length: usize, dev: TransmutableBox) { + pub fn insert(&mut self, base: Address, dev: TransmutableBox) { + let length = dev.borrow_mut().as_addressable().unwrap().len(); let block = Block { base, length, dev }; let i = self.blocks.iter().position(|cur| cur.base > block.base).unwrap_or(self.blocks.len()); self.blocks.insert(i, block); diff --git a/src/peripherals/genesis/coprocessor.rs b/src/peripherals/genesis/coprocessor.rs index f75a727..e4a2e68 100644 --- a/src/peripherals/genesis/coprocessor.rs +++ b/src/peripherals/genesis/coprocessor.rs @@ -1,7 +1,11 @@ +use std::rc::Rc; +use std::cell::RefCell; + +use crate::memory::Bus; use crate::error::Error; use crate::signals::Signal; -use crate::devices::{Address, Addressable, Transmutable}; +use crate::devices::{Address, Addressable, Transmutable, TransmutableBox}; const DEV_NAME: &'static str = "coprocessor"; @@ -68,3 +72,73 @@ impl Transmutable for CoprocessorCoordinator { } +pub struct CoprocessorBankRegister { + pub base: Signal
, +} + +impl CoprocessorBankRegister { + pub fn new(base: Signal
) -> Self { + Self { + base, + } + } +} + +impl Addressable for CoprocessorBankRegister { + fn len(&self) -> usize { + 0x01 + } + + fn read(&mut self, addr: Address, data: &mut [u8]) -> Result<(), Error> { + Ok(()) + } + + fn write(&mut self, addr: Address, data: &[u8]) -> Result<(), Error> { + let value = ((self.base.get() >> 1) | ((data[0] as Address) << 23)) & 0xFF8000; + println!("New base is {:x}", value); + self.base.set(value); + Ok(()) + } +} + +impl Transmutable for CoprocessorBankRegister { + fn as_addressable(&mut self) -> Option<&mut dyn Addressable> { + Some(self) + } +} + + +pub struct CoprocessorBankArea { + pub base: Signal
, + pub bus: Rc>, +} + +impl CoprocessorBankArea { + pub fn new(base: Signal
, bus: Rc>) -> Self { + Self { + base, + bus, + } + } +} + +impl Addressable for CoprocessorBankArea { + fn len(&self) -> usize { + 0x8000 + } + + fn read(&mut self, addr: Address, data: &mut [u8]) -> Result<(), Error> { + self.bus.borrow_mut().read(self.base.get() + addr, data) + } + + fn write(&mut self, addr: Address, data: &[u8]) -> Result<(), Error> { + self.bus.borrow_mut().write(self.base.get() + addr, data) + } +} + +impl Transmutable for CoprocessorBankArea { + fn as_addressable(&mut self) -> Option<&mut dyn Addressable> { + Some(self) + } +} + diff --git a/src/peripherals/sn76489.rs b/src/peripherals/sn76489.rs new file mode 100644 index 0000000..a2503f4 --- /dev/null +++ b/src/peripherals/sn76489.rs @@ -0,0 +1,57 @@ + +use crate::error::Error; +use crate::system::System; +use crate::devices::{ClockElapsed, Address, Addressable, Steppable, Transmutable}; + +const DEV_NAME: &'static str = "sn76489"; + +pub struct SN76489 { + +} + +impl SN76489 { + pub fn new() -> Self { + Self { + + } + } +} + +impl Addressable for SN76489 { + fn len(&self) -> usize { + 0x01 + } + + fn read(&mut self, addr: Address, data: &mut [u8]) -> Result<(), Error> { + match addr { + _ => { + warning!("{}: !!! unhandled read from {:0x}", DEV_NAME, addr); + }, + } + debug!("{}: read from register {:x} of {:?}", DEV_NAME, addr, data); + Ok(()) + } + + fn write(&mut self, addr: Address, data: &[u8]) -> Result<(), Error> { + debug!("{}: write to register {:x} with {:x}", DEV_NAME, addr, data[0]); + match addr { + _ => { + warning!("{}: !!! unhandled write {:0x} to {:0x}", DEV_NAME, data[0], addr); + }, + } + Ok(()) + } +} + + +impl Transmutable for SN76489 { + fn as_addressable(&mut self) -> Option<&mut dyn Addressable> { + Some(self) + } + + //fn as_steppable(&mut self) -> Option<&mut dyn Steppable> { + // Some(self) + //} +} + + diff --git a/src/peripherals/ym2612.rs b/src/peripherals/ym2612.rs new file mode 100644 index 0000000..9fadc0a --- /dev/null +++ b/src/peripherals/ym2612.rs @@ -0,0 +1,57 @@ + +use crate::error::Error; +use crate::system::System; +use crate::devices::{ClockElapsed, Address, Addressable, Steppable, Transmutable}; + +const DEV_NAME: &'static str = "ym2612"; + +pub struct YM2612 { + +} + +impl YM2612 { + pub fn new() -> Self { + Self { + + } + } +} + +impl Addressable for YM2612 { + fn len(&self) -> usize { + 0x04 + } + + fn read(&mut self, addr: Address, data: &mut [u8]) -> Result<(), Error> { + match addr { + _ => { + warning!("{}: !!! unhandled read from {:0x}", DEV_NAME, addr); + }, + } + debug!("{}: read from register {:x} of {:?}", DEV_NAME, addr, data); + Ok(()) + } + + fn write(&mut self, addr: Address, data: &[u8]) -> Result<(), Error> { + debug!("{}: write to register {:x} with {:x}", DEV_NAME, addr, data[0]); + match addr { + _ => { + warning!("{}: !!! unhandled write {:0x} to {:0x}", DEV_NAME, data[0], addr); + }, + } + Ok(()) + } +} + + +impl Transmutable for YM2612 { + fn as_addressable(&mut self) -> Option<&mut dyn Addressable> { + Some(self) + } + + //fn as_steppable(&mut self) -> Option<&mut dyn Steppable> { + // Some(self) + //} +} + + diff --git a/src/system.rs b/src/system.rs index 8c7ac1a..5a0ecf5 100644 --- a/src/system.rs +++ b/src/system.rs @@ -56,8 +56,7 @@ impl System { } pub fn add_peripheral(&mut self, name: &str, addr: Address, device: TransmutableBox) -> Result<(), Error> { - let length = device.borrow_mut().as_addressable().unwrap().len(); - self.bus.borrow_mut().insert(addr, length, device.clone()); + self.bus.borrow_mut().insert(addr, device.clone()); self.try_queue_device(device.clone()); self.devices.insert(name.to_string(), device); Ok(())