Sega Genesis coprocessor bus is now working

I've added skeleton devices for the sound chips, and added the bank
register and banked area of ram mapped to the Z80's bus.  Sonic1 will
now run (if the ym2612 device's size is set to 0x1000 instead of 0x04)
This commit is contained in:
transistor 2021-12-06 14:51:57 -08:00
parent 8743c83834
commit 9a751e5e90
6 changed files with 213 additions and 7 deletions

View File

@ -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<H: Host>(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))?;

View File

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

View File

@ -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<Address>,
}
impl CoprocessorBankRegister {
pub fn new(base: Signal<Address>) -> 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<Address>,
pub bus: Rc<RefCell<Bus>>,
}
impl CoprocessorBankArea {
pub fn new(base: Signal<Address>, bus: Rc<RefCell<Bus>>) -> 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)
}
}

View File

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

57
src/peripherals/ym2612.rs Normal file
View File

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

View File

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