mirror of
https://github.com/transistorfet/moa.git
synced 2024-09-26 09:55:26 +00:00
Compare commits
2 Commits
4bc1794d0f
...
b34588d73a
Author | SHA1 | Date | |
---|---|---|---|
|
b34588d73a | ||
|
90e617c5de |
@ -8,4 +8,4 @@ log = "0.4"
|
|||||||
femtos = "0.1"
|
femtos = "0.1"
|
||||||
thiserror = "1.0"
|
thiserror = "1.0"
|
||||||
moa-host = { path = "../libraries/host" }
|
moa-host = { path = "../libraries/host" }
|
||||||
emulator-hal = { path = "../libraries/emulator-hal/emulator-hal" }
|
emulator-hal = { path = "../libraries/emulator-hal/emulator-hal", features = ["femtos"] }
|
||||||
|
@ -82,9 +82,9 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn step_one(&mut self) -> Result<u16, Z80Error> {
|
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()?
|
self.reset()?
|
||||||
} else if self.signals.bus_request {
|
} else if self.signals.bus_request.get() {
|
||||||
4
|
4
|
||||||
} else {
|
} else {
|
||||||
self.step_internal()?
|
self.step_internal()?
|
||||||
|
@ -3,10 +3,13 @@ mod decode;
|
|||||||
mod emuhal;
|
mod emuhal;
|
||||||
mod execute;
|
mod execute;
|
||||||
mod instructions;
|
mod instructions;
|
||||||
mod moa;
|
|
||||||
mod state;
|
mod state;
|
||||||
mod timing;
|
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::state::{Z80, Z80Type, Z80Error, Z80State, Status, Flags};
|
||||||
pub use crate::decode::Z80Decoder;
|
pub use crate::decode::Z80Decoder;
|
||||||
pub use crate::execute::Z80Cycle;
|
pub use crate::execute::Z80Cycle;
|
||||||
|
@ -1,36 +1,45 @@
|
|||||||
use std::any::Any;
|
use std::rc::Rc;
|
||||||
|
use std::cell::RefCell;
|
||||||
use femtos::{Instant, Duration};
|
use femtos::{Instant, Duration};
|
||||||
use emulator_hal::{BusAdapter, Instant as EmuInstant};
|
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::{Z80, Z80Error, Z80Decoder};
|
||||||
use crate::instructions::Register;
|
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
|
where
|
||||||
Instant: EmuInstant,
|
Instant: EmuInstant,
|
||||||
{
|
{
|
||||||
fn step(&mut self, system: &System) -> Result<Duration, Error> {
|
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 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()?;
|
let clocks = executor.step_one()?;
|
||||||
self.previous_cycle = executor.end();
|
self.cpu.previous_cycle = executor.end();
|
||||||
Ok(Instant::hertz_to_duration(self.frequency.as_hz() as u64) * clocks as u32)
|
Ok(Instant::hertz_to_duration(self.cpu.frequency.as_hz() as u64) * clocks as u32)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_error(&mut self, system: &System) {
|
fn on_error(&mut self, system: &System) {
|
||||||
let bus = &mut *system.bus.borrow_mut();
|
let bus = &mut *system.bus.borrow_mut();
|
||||||
let mut adapter = BusAdapter::new(bus, |addr| addr as u64, |err| Z80Error::BusError(format!("{:?}", err)));
|
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> {
|
impl Signalable for Z80<Instant> {
|
||||||
fn set_signal(&mut self, signal: Signal, flag: bool) -> Result<(), Error> {
|
fn set_signal(&mut self, signal: Signal, flag: bool) -> Result<(), Error> {
|
||||||
match signal {
|
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> {
|
fn as_steppable(&mut self) -> Option<&mut dyn Steppable> {
|
||||||
Some(self)
|
Some(self)
|
||||||
}
|
}
|
||||||
@ -61,10 +71,10 @@ impl Transmutable for Z80<Instant> {
|
|||||||
Some(self)
|
Some(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
//#[inline]
|
||||||
fn as_signalable(&mut self) -> Option<&mut dyn Signalable> {
|
//fn as_signalable(&mut self) -> Option<&mut dyn Signalable> {
|
||||||
Some(self)
|
// Some(self)
|
||||||
}
|
//}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Z80Error> for Error {
|
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) {
|
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) {
|
fn remove_breakpoint(&mut self, addr: Address) {
|
||||||
if let Some(index) = self.debugger.breakpoints.iter().position(|a| *a == addr as u16) {
|
if let Some(index) = self.cpu.debugger.breakpoints.iter().position(|a| *a == addr as u16) {
|
||||||
self.debugger.breakpoints.remove(index);
|
self.cpu.debugger.breakpoints.remove(index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -103,9 +113,9 @@ impl Debuggable for Z80<Instant> {
|
|||||||
let bus = &mut *system.bus.borrow_mut();
|
let bus = &mut *system.bus.borrow_mut();
|
||||||
let mut adapter = BusAdapter::new(bus, |addr| addr as u64, |err| Z80Error::BusError(format!("{:?}", err)));
|
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)?;
|
let decoder = Z80Decoder::decode_at(&mut adapter, system.clock, self.cpu.state.pc)?;
|
||||||
self.previous_cycle.decoder.dump_decoded(&mut adapter);
|
self.cpu.previous_cycle.decoder.dump_decoded(&mut adapter);
|
||||||
self.dump_state(system.clock, &mut adapter);
|
self.cpu.dump_state(system.clock, &mut adapter);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -118,7 +128,7 @@ impl Debuggable for Z80<Instant> {
|
|||||||
|
|
||||||
fn run_command(&mut self, _system: &System, args: &[&str]) -> Result<bool, Error> {
|
fn run_command(&mut self, _system: &System, args: &[&str]) -> Result<bool, Error> {
|
||||||
match args[0] {
|
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);
|
return Ok(true);
|
||||||
},
|
},
|
||||||
|
@ -94,8 +94,10 @@ impl Z80State {
|
|||||||
|
|
||||||
#[derive(Clone, Debug, Default)]
|
#[derive(Clone, Debug, Default)]
|
||||||
pub struct Z80Signals {
|
pub struct Z80Signals {
|
||||||
pub reset: bool,
|
//pub reset: bool,
|
||||||
pub bus_request: bool,
|
//pub bus_request: bool,
|
||||||
|
pub reset: Signal<bool>,
|
||||||
|
pub bus_request: Signal<bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, thiserror::Error)]
|
#[derive(Clone, Debug, thiserror::Error)]
|
||||||
|
@ -19,7 +19,7 @@ type Input<T> = Signal<T>;
|
|||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
type TriState<T> = Signal<T>;
|
type TriState<T> = Signal<T>;
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug, Default)]
|
||||||
pub struct Signal<T: Copy>(Rc<Cell<T>>);
|
pub struct Signal<T: Copy>(Rc<Cell<T>>);
|
||||||
|
|
||||||
impl<T: Copy> Signal<T> {
|
impl<T: Copy> Signal<T> {
|
||||||
|
@ -1,27 +1,23 @@
|
|||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::cell::{Cell, RefCell};
|
use std::cell::{Cell, RefCell};
|
||||||
use std::any::Any;
|
|
||||||
use femtos::Instant;
|
use femtos::Instant;
|
||||||
|
|
||||||
use moa_core::{Bus, Device, Error, Address, Addressable, Signal, Transmutable};
|
use moa_core::{Bus, Error, Address, Addressable, Transmutable};
|
||||||
//use moa_signals::Signal;
|
use moa_signals::Signal;
|
||||||
use moa_z80::Z80;
|
|
||||||
|
|
||||||
const DEV_NAME: &str = "coprocessor";
|
const DEV_NAME: &str = "coprocessor";
|
||||||
|
|
||||||
pub struct CoprocessorCoordinator {
|
pub struct CoprocessorCoordinator {
|
||||||
z80: Device,
|
bus_request: Signal<bool>,
|
||||||
//bus_request: Signal<bool>,
|
reset: Signal<bool>,
|
||||||
//reset: Signal<bool>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
impl CoprocessorCoordinator {
|
impl CoprocessorCoordinator {
|
||||||
pub fn new(z80: Device) -> Self {
|
pub fn new(reset: Signal<bool>, bus_request: Signal<bool>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
z80,
|
bus_request,
|
||||||
//bus_request,
|
reset,
|
||||||
//reset,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -34,9 +30,7 @@ impl Addressable for CoprocessorCoordinator {
|
|||||||
fn read(&mut self, _clock: Instant, addr: Address, data: &mut [u8]) -> Result<(), Error> {
|
fn read(&mut self, _clock: Instant, addr: Address, data: &mut [u8]) -> Result<(), Error> {
|
||||||
match addr {
|
match addr {
|
||||||
0x100 => {
|
0x100 => {
|
||||||
let mut device = self.z80.borrow_mut();
|
data[0] = if self.bus_request.get() && self.reset.get() {
|
||||||
let z80 = device.as_signalable().unwrap();
|
|
||||||
data[0] = if z80.signal(Signal::BusRequest).unwrap_or(false) && z80.signal(Signal::Reset).unwrap_or(false) {
|
|
||||||
0x01
|
0x01
|
||||||
} else {
|
} else {
|
||||||
0x00
|
0x00
|
||||||
@ -55,14 +49,10 @@ impl Addressable for CoprocessorCoordinator {
|
|||||||
match addr {
|
match addr {
|
||||||
0x000 => { /* ROM vs DRAM mode */ },
|
0x000 => { /* ROM vs DRAM mode */ },
|
||||||
0x100 => {
|
0x100 => {
|
||||||
let mut device = self.z80.borrow_mut();
|
self.bus_request.set(data[0] != 0);
|
||||||
let z80 = device.as_signalable().unwrap();
|
|
||||||
z80.set_signal(Signal::BusRequest, data[0] == 0)?;
|
|
||||||
},
|
},
|
||||||
0x200 => {
|
0x200 => {
|
||||||
let mut device = self.z80.borrow_mut();
|
self.reset.set(data[0] == 0);
|
||||||
let z80 = device.as_signalable().unwrap();
|
|
||||||
z80.set_signal(Signal::Reset, data[0] == 0)?;
|
|
||||||
},
|
},
|
||||||
_ => {
|
_ => {
|
||||||
log::warn!("{}: !!! unhandled write {:0x} to {:0x}", DEV_NAME, data[0], addr);
|
log::warn!("{}: !!! unhandled write {:0x} to {:0x}", DEV_NAME, data[0], addr);
|
||||||
|
@ -8,7 +8,7 @@ use moa_core::{System, Error, MemoryBlock, Bus, Address, Addressable, Device};
|
|||||||
use moa_host::Host;
|
use moa_host::Host;
|
||||||
|
|
||||||
use moa_m68k::{M68k, M68kType};
|
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::Ym2612;
|
||||||
use moa_peripherals_yamaha::Sn76489;
|
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(0x7f11, coproc_sn_sound.clone());
|
||||||
coproc_bus.borrow_mut().insert(0x8000, coproc_area);
|
coproc_bus.borrow_mut().insert(0x8000, coproc_area);
|
||||||
let coproc = Z80::from_type(Z80Type::Z80, Frequency::from_hz(3_579_545));
|
let coproc = Z80::from_type(Z80Type::Z80, Frequency::from_hz(3_579_545));
|
||||||
//let mut reset = coproc.reset.clone();
|
let coproc = MoaZ80 {
|
||||||
//let mut bus_request = coproc.bus_request.clone();
|
bus: coproc_bus,
|
||||||
//reset.set(true);
|
cpu: coproc,
|
||||||
//bus_request.set(true);
|
};
|
||||||
|
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);
|
let coproc = Device::new(coproc);
|
||||||
|
|
||||||
|
|
||||||
// Add coprocessor devices to the system bus so the 68000 can access them too
|
// 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(0x00a00000, coproc_ram)?;
|
||||||
system.add_addressable_device(0x00a04000, coproc_ym_sound)?;
|
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();
|
let interrupt = controllers.get_interrupt_signal();
|
||||||
system.add_addressable_device(0x00a10000, Device::new(controllers))?;
|
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))?;
|
system.add_addressable_device(0x00a11000, Device::new(coproc))?;
|
||||||
|
|
||||||
let vdp = Ym7101::new(host, interrupt, coproc_sn_sound)?;
|
let vdp = Ym7101::new(host, interrupt, coproc_sn_sound)?;
|
||||||
|
@ -3,7 +3,7 @@ use femtos::Frequency;
|
|||||||
use moa_core::{System, Error, MemoryBlock, Device};
|
use moa_core::{System, Error, MemoryBlock, Device};
|
||||||
use moa_host::Host;
|
use moa_host::Host;
|
||||||
|
|
||||||
use moa_z80::{Z80, Z80Type};
|
use moa_z80::{MoaZ80, Z80, Z80Type};
|
||||||
|
|
||||||
use crate::peripherals::model1::{Model1Keyboard, Model1Video};
|
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
|
// TODO the ioport needs to be hooked up
|
||||||
let cpu = Z80::from_type(Z80Type::Z80, options.frequency);
|
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))?;
|
system.add_interruptable_device("cpu", Device::new(cpu))?;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user