Fixed genesis Z80 bus issue

This commit is contained in:
transistor 2024-04-13 11:35:43 -07:00
parent 471695aff5
commit 90e617c5de
9 changed files with 70 additions and 58 deletions

View File

@ -8,4 +8,4 @@ log = "0.4"
femtos = "0.1"
thiserror = "1.0"
moa-host = { path = "../libraries/host" }
emulator-hal = { path = "../libraries/emulator-hal/emulator-hal" }
emulator-hal = { path = "../libraries/emulator-hal/emulator-hal", features = ["femtos"] }

View File

@ -82,9 +82,9 @@ where
}
pub(crate) fn step_one(&mut self) -> Result<u16, Z80Error> {
let clocks = if self.signals.reset {
let clocks = if self.signals.reset.get() {
self.reset()?
} else if self.signals.bus_request {
} else if self.signals.bus_request.get() {
4
} else {
self.step_internal()?

View File

@ -3,10 +3,13 @@ mod decode;
mod emuhal;
mod execute;
mod instructions;
mod moa;
mod state;
mod timing;
//#[cfg(feature = "moa")]
pub mod moa;
pub use crate::moa::MoaZ80;
pub use crate::state::{Z80, Z80Type, Z80Error, Z80State, Status, Flags};
pub use crate::decode::Z80Decoder;
pub use crate::execute::Z80Cycle;

View File

@ -1,36 +1,45 @@
use std::any::Any;
use std::rc::Rc;
use std::cell::RefCell;
use femtos::{Instant, Duration};
use emulator_hal::{BusAdapter, Instant as EmuInstant};
use moa_core::{System, Error, Address, Steppable, Addressable, Interruptable, Signalable, Signal, Debuggable, Transmutable};
use moa_core::{System, Error, Bus, Address, Steppable, Addressable, Interruptable, Signalable, Signal, Debuggable, Transmutable};
use crate::{Z80, Z80Error, Z80Decoder};
use crate::instructions::Register;
impl Steppable for Z80<Instant>
pub struct MoaZ80<Instant>
where
Instant: EmuInstant,
{
pub bus: Rc<RefCell<Bus>>,
pub cpu: Z80<Instant>,
}
impl Steppable for MoaZ80<Instant>
where
Instant: EmuInstant,
{
fn step(&mut self, system: &System) -> Result<Duration, Error> {
let bus = &mut *system.bus.borrow_mut();
let mut bus = &mut *self.bus.borrow_mut();
let mut adapter = BusAdapter::new(bus, |addr| addr as u64, |err| Z80Error::BusError(format!("{:?}", err)));
let mut executor = self.begin(system.clock, &mut adapter)?;
let mut executor = self.cpu.begin(system.clock, &mut adapter)?;
let clocks = executor.step_one()?;
self.previous_cycle = executor.end();
Ok(Instant::hertz_to_duration(self.frequency.as_hz() as u64) * clocks as u32)
self.cpu.previous_cycle = executor.end();
Ok(Instant::hertz_to_duration(self.cpu.frequency.as_hz() as u64) * clocks as u32)
}
fn on_error(&mut self, system: &System) {
let bus = &mut *system.bus.borrow_mut();
let mut adapter = BusAdapter::new(bus, |addr| addr as u64, |err| Z80Error::BusError(format!("{:?}", err)));
self.dump_state(system.clock, &mut adapter);
self.cpu.dump_state(system.clock, &mut adapter);
}
}
impl Interruptable for Z80<Instant> {}
impl Interruptable for MoaZ80<Instant> {}
/*
impl Signalable for Z80<Instant> {
fn set_signal(&mut self, signal: Signal, flag: bool) -> Result<(), Error> {
match signal {
@ -47,8 +56,9 @@ impl Signalable for Z80<Instant> {
}
}
}
*/
impl Transmutable for Z80<Instant> {
impl Transmutable for MoaZ80<Instant> {
fn as_steppable(&mut self) -> Option<&mut dyn Steppable> {
Some(self)
}
@ -61,10 +71,10 @@ impl Transmutable for Z80<Instant> {
Some(self)
}
#[inline]
fn as_signalable(&mut self) -> Option<&mut dyn Signalable> {
Some(self)
}
//#[inline]
//fn as_signalable(&mut self) -> Option<&mut dyn Signalable> {
// Some(self)
//}
}
impl From<Z80Error> for Error {
@ -88,14 +98,14 @@ impl From<Error> for Z80Error {
}
}
impl Debuggable for Z80<Instant> {
impl Debuggable for MoaZ80<Instant> {
fn add_breakpoint(&mut self, addr: Address) {
self.debugger.breakpoints.push(addr as u16);
self.cpu.debugger.breakpoints.push(addr as u16);
}
fn remove_breakpoint(&mut self, addr: Address) {
if let Some(index) = self.debugger.breakpoints.iter().position(|a| *a == addr as u16) {
self.debugger.breakpoints.remove(index);
if let Some(index) = self.cpu.debugger.breakpoints.iter().position(|a| *a == addr as u16) {
self.cpu.debugger.breakpoints.remove(index);
}
}
@ -103,9 +113,9 @@ impl Debuggable for Z80<Instant> {
let bus = &mut *system.bus.borrow_mut();
let mut adapter = BusAdapter::new(bus, |addr| addr as u64, |err| Z80Error::BusError(format!("{:?}", err)));
let decoder = Z80Decoder::decode_at(&mut adapter, system.clock, self.state.pc)?;
self.previous_cycle.decoder.dump_decoded(&mut adapter);
self.dump_state(system.clock, &mut adapter);
let decoder = Z80Decoder::decode_at(&mut adapter, system.clock, self.cpu.state.pc)?;
self.cpu.previous_cycle.decoder.dump_decoded(&mut adapter);
self.cpu.dump_state(system.clock, &mut adapter);
Ok(())
}
@ -118,7 +128,7 @@ impl Debuggable for Z80<Instant> {
fn run_command(&mut self, _system: &System, args: &[&str]) -> Result<bool, Error> {
match args[0] {
"l" => self.state.reg[Register::L as usize] = 0x05,
"l" => self.cpu.state.reg[Register::L as usize] = 0x05,
_ => {
return Ok(true);
},

View File

@ -94,8 +94,10 @@ impl Z80State {
#[derive(Clone, Debug, Default)]
pub struct Z80Signals {
pub reset: bool,
pub bus_request: bool,
//pub reset: bool,
//pub bus_request: bool,
pub reset: Signal<bool>,
pub bus_request: Signal<bool>,
}
#[derive(Clone, Debug, thiserror::Error)]

View File

@ -19,7 +19,7 @@ type Input<T> = Signal<T>;
#[allow(dead_code)]
type TriState<T> = Signal<T>;
#[derive(Clone, Debug)]
#[derive(Clone, Debug, Default)]
pub struct Signal<T: Copy>(Rc<Cell<T>>);
impl<T: Copy> Signal<T> {

View File

@ -1,27 +1,23 @@
use std::rc::Rc;
use std::cell::{Cell, RefCell};
use std::any::Any;
use femtos::Instant;
use moa_core::{Bus, Device, Error, Address, Addressable, Signal, Transmutable};
//use moa_signals::Signal;
use moa_z80::Z80;
use moa_core::{Bus, Error, Address, Addressable, Transmutable};
use moa_signals::Signal;
const DEV_NAME: &str = "coprocessor";
pub struct CoprocessorCoordinator {
z80: Device,
//bus_request: Signal<bool>,
//reset: Signal<bool>,
bus_request: Signal<bool>,
reset: Signal<bool>,
}
impl CoprocessorCoordinator {
pub fn new(z80: Device) -> Self {
pub fn new(reset: Signal<bool>, bus_request: Signal<bool>) -> Self {
Self {
z80,
//bus_request,
//reset,
bus_request,
reset,
}
}
}
@ -34,9 +30,7 @@ impl Addressable for CoprocessorCoordinator {
fn read(&mut self, _clock: Instant, addr: Address, data: &mut [u8]) -> Result<(), Error> {
match addr {
0x100 => {
let mut device = self.z80.borrow_mut();
let z80 = device.as_signalable().unwrap();
data[0] = if z80.signal(Signal::BusRequest).unwrap_or(false) && z80.signal(Signal::Reset).unwrap_or(false) {
data[0] = if self.bus_request.get() && self.reset.get() {
0x01
} else {
0x00
@ -55,14 +49,10 @@ impl Addressable for CoprocessorCoordinator {
match addr {
0x000 => { /* ROM vs DRAM mode */ },
0x100 => {
let mut device = self.z80.borrow_mut();
let z80 = device.as_signalable().unwrap();
z80.set_signal(Signal::BusRequest, data[0] == 0)?;
self.bus_request.set(data[0] != 0);
},
0x200 => {
let mut device = self.z80.borrow_mut();
let z80 = device.as_signalable().unwrap();
z80.set_signal(Signal::Reset, data[0] == 0)?;
self.reset.set(data[0] == 0);
},
_ => {
log::warn!("{}: !!! unhandled write {:0x} to {:0x}", DEV_NAME, data[0], addr);

View File

@ -8,7 +8,7 @@ use moa_core::{System, Error, MemoryBlock, Bus, Address, Addressable, Device};
use moa_host::Host;
use moa_m68k::{M68k, M68kType};
use moa_z80::{Z80, Z80Type};
use moa_z80::{MoaZ80, Z80, Z80Type};
use moa_peripherals_yamaha::Ym2612;
use moa_peripherals_yamaha::Sn76489;
@ -69,13 +69,16 @@ pub fn build_genesis<H: Host>(host: &mut H, mut options: SegaGenesisOptions) ->
coproc_bus.borrow_mut().insert(0x7f11, coproc_sn_sound.clone());
coproc_bus.borrow_mut().insert(0x8000, coproc_area);
let coproc = Z80::from_type(Z80Type::Z80, Frequency::from_hz(3_579_545));
//let mut reset = coproc.reset.clone();
//let mut bus_request = coproc.bus_request.clone();
//reset.set(true);
//bus_request.set(true);
let coproc = MoaZ80 {
bus: coproc_bus,
cpu: coproc,
};
let mut reset = coproc.cpu.signals.reset.clone();
let mut bus_request = coproc.cpu.signals.bus_request.clone();
reset.set(true);
bus_request.set(true);
let coproc = Device::new(coproc);
// 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)?;
@ -89,7 +92,7 @@ pub fn build_genesis<H: Host>(host: &mut H, mut options: SegaGenesisOptions) ->
let interrupt = controllers.get_interrupt_signal();
system.add_addressable_device(0x00a10000, Device::new(controllers))?;
let coproc = CoprocessorCoordinator::new(coproc);
let coproc = CoprocessorCoordinator::new(reset, bus_request);
system.add_addressable_device(0x00a11000, Device::new(coproc))?;
let vdp = Ym7101::new(host, interrupt, coproc_sn_sound)?;

View File

@ -3,7 +3,7 @@ use femtos::Frequency;
use moa_core::{System, Error, MemoryBlock, Device};
use moa_host::Host;
use moa_z80::{Z80, Z80Type};
use moa_z80::{MoaZ80, Z80, Z80Type};
use crate::peripherals::model1::{Model1Keyboard, Model1Video};
@ -45,6 +45,10 @@ pub fn build_trs80<H: Host>(host: &mut H, options: Trs80Options) -> Result<Syste
// TODO the ioport needs to be hooked up
let cpu = Z80::from_type(Z80Type::Z80, options.frequency);
let cpu = MoaZ80 {
bus: system.bus.clone(),
cpu,
};
system.add_interruptable_device("cpu", Device::new(cpu))?;