Added a hacky Signalable trait to replace the Z80 signals

This commit is contained in:
transistor 2024-04-07 10:38:41 -07:00
parent 1bb66e3308
commit 59199533eb
14 changed files with 215 additions and 139 deletions

3
Cargo.lock generated
View File

@ -1247,9 +1247,10 @@ name = "rad-tests"
version = "0.1.0"
dependencies = [
"clap 3.2.25",
"emulator-hal",
"emulator-hal-memory",
"femtos",
"flate2",
"moa-core",
"moa-z80",
"serde",
"serde_derive",

View File

@ -171,6 +171,16 @@ pub trait Inspectable {
fn inspect(&mut self, system: &System, args: &[&str]) -> Result<(), Error>;
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum Signal {
Reset,
BusRequest,
}
pub trait Signalable {
fn set_signal(&mut self, signal: Signal, flag: bool) -> Result<(), Error>;
fn signal(&mut self, signal: Signal) -> Option<bool>;
}
pub trait Transmutable {
#[inline]
@ -197,6 +207,11 @@ pub trait Transmutable {
fn as_inspectable(&mut self) -> Option<&mut dyn Inspectable> {
None
}
#[inline]
fn as_signalable(&mut self) -> Option<&mut dyn Signalable> {
None
}
}
pub type TransmutableBox = Rc<RefCell<Box<dyn Transmutable>>>;

View File

@ -7,7 +7,8 @@ mod memory;
mod system;
pub use crate::devices::{
Address, Addressable, Steppable, Interruptable, Debuggable, Inspectable, Transmutable, TransmutableBox, Device,
Address, Addressable, Steppable, Interruptable, Debuggable, Inspectable, Signalable, Signal, Transmutable, TransmutableBox,
Device,
};
pub use crate::devices::{
read_beu16, read_beu32, read_leu16, read_leu32, write_beu16, write_beu32, write_leu16, write_leu32, wrap_transmutable,
@ -17,4 +18,4 @@ pub use crate::interrupts::InterruptController;
pub use crate::memory::{MemoryBlock, AddressTranslator, AddressRepeater, Bus, BusPort, dump_slice, dump_memory};
pub use crate::system::System;
pub use emulator_hal::bus::{BusAccess};
pub use emulator_hal::BusAccess;

View File

@ -4,6 +4,7 @@ use std::rc::Rc;
use std::cell::RefCell;
use std::fmt::Write;
use femtos::Instant;
use emulator_hal::{self, BusAccess, Error as EmuError};
use crate::error::Error;
use crate::devices::{Address, Addressable, Transmutable, Device, read_beu16};
@ -236,7 +237,7 @@ impl Bus {
let to = if count < 16 { count / 2 } else { 8 };
for _ in 0..to {
let word = self.read_beu16(clock, addr);
let word = Addressable::read_beu16(self, clock, addr);
if word.is_err() {
println!("{}", line);
return;
@ -353,7 +354,7 @@ impl Addressable for BusPort {
for i in (0..data.len()).step_by(self.data_width as usize) {
let addr_index = (addr + i as Address) & self.address_mask;
let end = cmp::min(i + self.data_width as usize, data.len());
subdevice.read(clock, addr_index, &mut data[i..end])?;
Addressable::read(&mut *subdevice, clock, addr_index, &mut data[i..end])?;
}
Ok(())
}
@ -364,7 +365,7 @@ impl Addressable for BusPort {
for i in (0..data.len()).step_by(self.data_width as usize) {
let addr_index = (addr + i as Address) & self.address_mask;
let end = cmp::min(i + self.data_width as usize, data.len());
subdevice.write(clock, addr_index, &data[i..end])?;
Addressable::write(&mut *subdevice, clock, addr_index, &data[i..end])?;
}
Ok(())
}
@ -412,9 +413,7 @@ where
}
}
use emulator_hal::bus::{self, BusAccess};
impl bus::Error for Error {}
impl EmuError for Error {}
impl BusAccess<u64> for &mut dyn Addressable {
type Instant = Instant;
@ -430,3 +429,18 @@ impl BusAccess<u64> for &mut dyn Addressable {
Ok(data.len())
}
}
impl BusAccess<u64> for Bus {
type Instant = Instant;
type Error = Error;
fn read(&mut self, now: Instant, addr: Address, data: &mut [u8]) -> Result<usize, Self::Error> {
Addressable::read(self, now, addr, data)?;
Ok(data.len())
}
fn write(&mut self, now: Instant, addr: Address, data: &[u8]) -> Result<usize, Self::Error> {
Addressable::write(self, now, addr, data)?;
Ok(data.len())
}
}

View File

@ -1,7 +1,7 @@
use core::fmt::Write;
use emulator_hal::{BusAccess, Instant as EmuInstant};
use crate::state::{Z80Error, Z80Address} ;
use crate::state::{Z80Error, Z80Address};
use crate::instructions::{
Direction, Condition, Register, RegisterPair, IndexRegister, IndexRegisterHalf, SpecialRegister, InterruptMode, Target,
LoadTarget, UndocumentedCopy, Instruction,
@ -55,27 +55,16 @@ impl Z80Decoder {
Ok(decoder.decoder)
}
/*
pub fn format_instruction_bytes(&mut self) -> String {
let mut ins_data = String::new();
for offset in 0..self.decoder.end.saturating_sub(self.decoder.start) {
write!(ins_data, "{:02x} ", self.bus.read_u8(self.clock, self.decoder.start + offset).unwrap()).unwrap()
}
ins_data
}
pub fn dump_decoded(&mut self) {
let ins_data = self.format_instruction_bytes();
println!("{:#06x}: {}\n\t{:?}\n", self.decoder.start, ins_data, self.decoder.instruction);
}
pub fn dump_disassembly(&mut self, start: Z80Address, length: Z80Address) {
pub fn dump_disassembly<Bus>(bus: &mut Bus, start: Z80Address, length: Z80Address)
where
Bus: BusAccess<Z80Address>,
{
let mut next = start;
while next < (start + length) {
match self.decode_at(self.clock, next) {
Ok(()) => {
self.dump_decoded();
next = self.decoder.end;
match Z80Decoder::decode_at(bus, Bus::Instant::START, next) {
Ok(mut decoder) => {
decoder.dump_decoded(bus);
next = decoder.end;
},
Err(err) => {
println!("{:?}", err);
@ -84,7 +73,25 @@ impl Z80Decoder {
}
}
}
*/
pub fn dump_decoded<Bus>(&mut self, bus: &mut Bus)
where
Bus: BusAccess<Z80Address>,
{
let ins_data = self.format_instruction_bytes(bus);
println!("{:#06x}: {}\n\t{:?}\n", self.start, ins_data, self.instruction);
}
pub fn format_instruction_bytes<Bus>(&mut self, bus: &mut Bus) -> String
where
Bus: BusAccess<Z80Address>,
{
let mut ins_data = String::new();
for offset in 0..self.end.saturating_sub(self.start) {
write!(ins_data, "{:02x} ", bus.read_u8(Bus::Instant::START, self.start + offset).unwrap()).unwrap()
}
ins_data
}
}
pub struct DecodeNext<'a, Bus, Instant>
@ -107,11 +114,7 @@ where
Ok(())
}
pub fn decode_bare(
&mut self,
ins: u8,
extra_instruction_bytes: u16,
) -> Result<Instruction, Z80Error> {
pub fn decode_bare(&mut self, ins: u8, extra_instruction_bytes: u16) -> Result<Instruction, Z80Error> {
self.decoder.extra_instruction_bytes = extra_instruction_bytes;
match get_ins_x(ins) {
0 => match get_ins_z(ins) {
@ -559,11 +562,7 @@ where
}
}
fn decode_index_target(
&mut self,
index_reg: IndexRegister,
z: u8,
) -> Result<Option<Target>, Z80Error> {
fn decode_index_target(&mut self, index_reg: IndexRegister, z: u8) -> Result<Option<Target>, Z80Error> {
let result = match z {
4 => Some(Target::DirectRegHalf(get_index_register_half(index_reg, 0))),
5 => Some(Target::DirectRegHalf(get_index_register_half(index_reg, 1))),
@ -578,7 +577,9 @@ where
fn read_instruction_byte(&mut self) -> Result<u8, Z80Error> {
let byte = self.bus.read_u8(self.clock, self.decoder.end)
let byte = self
.bus
.read_u8(self.clock, self.decoder.end)
.map_err(|err| Z80Error::BusError(format!("{:?}", err)))?;
self.decoder.end = self.decoder.end.wrapping_add(1);
Ok(byte)
@ -587,7 +588,9 @@ where
fn read_instruction_word(&mut self) -> Result<u16, Z80Error> {
let mut bytes = [0; 2];
for byte in bytes.iter_mut() {
*byte = self.bus.read_u8(self.clock, self.decoder.end & 0xFFFF)
*byte = self
.bus
.read_u8(self.clock, self.decoder.end & 0xFFFF)
.map_err(|err| Z80Error::BusError(format!("{:?}", err)))?;
self.decoder.end = self.decoder.end.wrapping_add(1);
}

View File

@ -1,4 +1,3 @@
use emulator_hal::{BusAccess, Instant as EmuInstant, Error as EmuError, Step, Inspect, Debug, IntoAddress};
use crate::state::{Z80, Z80Error, Z80Address, Status};
@ -23,10 +22,9 @@ where
fn step(&mut self, now: Self::Instant, bus: &mut Bus) -> Result<Self::Instant, Self::Error> {
let mut executor = self.begin(now, bus)?;
executor.step_one()?;
let clocks = executor.step_one()?;
self.previous_cycle = executor.end();
// TODO fix this
Ok(now)
Ok(now + Instant::hertz_to_duration(self.frequency.as_hz() as u64) * clocks as u32)
}
}
@ -51,11 +49,9 @@ where
fn step(&mut self, now: Self::Instant, bus: (&mut MemBus, &mut IoBus)) -> Result<Self::Instant, Self::Error> {
let executor = self.begin(now, bus)?;
executor.step_one()?;
let clocks = executor.step_one()?;
self.previous_cycle = executor.end();
// TODO fix this
Ok(now)
Ok(now + Instant::hertz_to_duration(self.frequency.as_hz() as u64) * clocks as u32)
}
}
*/

View File

@ -5,7 +5,7 @@ use crate::instructions::{
Condition, Instruction, LoadTarget, Target, Register, InterruptMode, RegisterPair, IndexRegister, SpecialRegister,
IndexRegisterHalf, Size, Direction, UndocumentedCopy,
};
use crate::state::{Z80, Z80Error, Z80State, Z80Address, Status, Flags};
use crate::state::{Z80, Z80Error, Z80State, Z80Signals, Z80Address, Status, Flags};
use crate::timing::Z80InstructionCycles;
use crate::debugger::Z80Debugger;
@ -41,12 +41,17 @@ impl<Instant> Z80<Instant>
where
Instant: EmuInstant,
{
pub(crate) fn begin<'a, Bus>(&'a mut self, clock: Instant, bus: &'a mut Bus) -> Result<ExecuteNext<'a, &mut Bus, Instant>, Z80Error>
pub(crate) fn begin<'a, Bus>(
&'a mut self,
clock: Instant,
bus: &'a mut Bus,
) -> Result<ExecuteNext<'a, &'a mut Bus, Instant>, Z80Error>
where
Bus: BusAccess<Z80Address, Instant = Instant>,
{
let executor = ExecuteNext {
state: &mut self.state,
signals: &mut self.signals,
debugger: &mut self.debugger,
cycle: Z80Cycle::at_time(clock),
bus,
@ -61,6 +66,7 @@ where
Bus: BusAccess<Z80Address, Instant = Instant>,
{
state: &'a mut Z80State,
signals: &'a mut Z80Signals,
debugger: &'a mut Z80Debugger,
cycle: Z80Cycle<Instant>,
bus: Bus,
@ -71,28 +77,22 @@ where
Bus: BusAccess<Z80Address, Instant = Instant>,
Instant: EmuInstant,
{
pub(crate) fn end(mut self) -> Z80Cycle<Instant> {
pub(crate) fn end(self) -> Z80Cycle<Instant> {
self.cycle
}
pub(crate) fn step_one(&mut self) -> Result<u16, Z80Error> {
// TODO restore the reset and bus request signals
//let clocks = if self.reset.get() {
// self.reset()?
//} else if self.bus_request.get() {
// 4
//} else {
// self.step_internal(self.cycle.current_clock)?
//};
//Ok(self.frequency.period_duration() * clocks as u64)
// TODO remove this when done
let clocks = self.step_internal(self.cycle.current_clock)?;
let clocks = if self.signals.reset {
self.reset()?
} else if self.signals.bus_request {
4
} else {
self.step_internal()?
};
Ok(clocks)
}
fn step_internal(&mut self, clock: Instant) -> Result<u16, Z80Error> {
fn step_internal(&mut self) -> Result<u16, Z80Error> {
match self.state.status {
Status::Init => self.init(),
Status::Halted => Err(Z80Error::Halted),
@ -630,7 +630,9 @@ where
let parity = if count != 0 { Flags::Parity as u8 } else { 0 };
self.set_flags(mask, parity);
if (self.cycle.decoder.instruction == Instruction::LDIR || self.cycle.decoder.instruction == Instruction::LDDR) && count != 0 {
if (self.cycle.decoder.instruction == Instruction::LDIR || self.cycle.decoder.instruction == Instruction::LDDR)
&& count != 0
{
self.cycle.took_branch = true;
self.state.pc -= 2;
}
@ -1126,13 +1128,17 @@ where
fn read_port_u8(&mut self, addr: u16) -> Result<u8, Z80Error> {
self.increment_refresh(1);
Ok(self.bus.read_u8(self.cycle.current_clock, addr as Z80Address)
Ok(self
.bus
.read_u8(self.cycle.current_clock, addr as Z80Address)
.map_err(|err| Z80Error::BusError(format!("{:?}", err)))?)
}
fn write_port_u8(&mut self, addr: u16, value: u8) -> Result<(), Z80Error> {
self.increment_refresh(1);
Ok(self.bus.write_u8(self.cycle.current_clock, addr as Z80Address, value)
Ok(self
.bus
.write_u8(self.cycle.current_clock, addr as Z80Address, value)
.map_err(|err| Z80Error::BusError(format!("{:?}", err)))?)
}
@ -1144,7 +1150,9 @@ where
let mut bytes = [0; 2];
for byte in bytes.iter_mut() {
self.increment_refresh(1);
*byte = self.bus.read_u8(self.cycle.current_clock, addr & 0xFFFF)
*byte = self
.bus
.read_u8(self.cycle.current_clock, addr & 0xFFFF)
.map_err(|err| Z80Error::BusError(format!("{:?}", err)))?;
addr = addr.wrapping_add(1);
}
@ -1159,7 +1167,8 @@ where
let mut bytes = value.to_le_bytes();
for byte in bytes.iter_mut() {
self.increment_refresh(1);
self.bus.write_u8(self.cycle.current_clock, addr & 0xFFFF, *byte)
self.bus
.write_u8(self.cycle.current_clock, addr & 0xFFFF, *byte)
.map_err(|err| Z80Error::BusError(format!("{:?}", err)))?;
addr = addr.wrapping_add(1);
}
@ -1172,7 +1181,7 @@ where
//if let Some(io) = self.ioport.as_mut() {
// Ok(io.read_u8(self.cycle.current_clock, addr)?)
//} else {
Ok(0)
Ok(0)
//}
}

View File

@ -1,11 +1,11 @@
mod debugger;
mod decode;
mod emuhal;
mod execute;
mod instructions;
mod moa;
mod state;
mod timing;
mod moa;
mod emuhal;
pub use crate::state::{Z80, Z80Type, Z80Error, Z80State, Status, Flags};
pub use crate::decode::Z80Decoder;

View File

@ -1,8 +1,8 @@
use std::any::Any;
use femtos::{Instant, Duration};
use emulator_hal::{BusAdapter, Instant as EmuInstant};
use moa_core::{System, Error, Address, Steppable, Addressable, Interruptable, Debuggable, Transmutable};
use moa_core::{System, Error, Address, Steppable, Addressable, Interruptable, Signalable, Signal, Debuggable, Transmutable};
use crate::{Z80, Z80Error, Z80Decoder};
use crate::instructions::Register;
@ -22,13 +22,32 @@ where
}
fn on_error(&mut self, system: &System) {
self.dump_state(system.clock);
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);
}
}
impl Interruptable for Z80<Instant> {}
impl Signalable for Z80<Instant> {
fn set_signal(&mut self, signal: Signal, flag: bool) -> Result<(), Error> {
match signal {
Signal::Reset => self.signals.reset = flag,
Signal::BusRequest => self.signals.bus_request = flag,
}
Ok(())
}
fn signal(&mut self, signal: Signal) -> Option<bool> {
match signal {
Signal::Reset => Some(self.signals.reset),
Signal::BusRequest => Some(self.signals.bus_request),
}
}
}
impl Transmutable for Z80<Instant> {
fn as_steppable(&mut self) -> Option<&mut dyn Steppable> {
Some(self)
@ -41,6 +60,11 @@ impl Transmutable for Z80<Instant> {
fn as_debuggable(&mut self) -> Option<&mut dyn Debuggable> {
Some(self)
}
#[inline]
fn as_signalable(&mut self) -> Option<&mut dyn Signalable> {
Some(self)
}
}
impl From<Z80Error> for Error {
@ -80,16 +104,16 @@ impl Debuggable for Z80<Instant> {
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)?;
// TODO disabled until decoder is fixed
//self.decoder.dump_decoded(&mut self.port);
self.dump_state(system.clock);
self.previous_cycle.decoder.dump_decoded(&mut adapter);
self.dump_state(system.clock, &mut adapter);
Ok(())
}
fn print_disassembly(&mut self, _system: &System, addr: Address, count: usize) {
// TODO disabled until decoder is fixed
//let mut decoder = Z80Decoder::default();
//decoder.dump_disassembly(&mut self.port, addr as u16, count as u16);
fn print_disassembly(&mut self, system: &System, addr: Address, count: usize) {
let bus = &mut *system.bus.borrow_mut();
let mut adapter = BusAdapter::new(bus, |addr| addr as u64, |err| Z80Error::BusError(format!("{:?}", err)));
Z80Decoder::dump_disassembly(&mut adapter, addr as u16, count as u16);
}
fn run_command(&mut self, _system: &System, args: &[&str]) -> Result<bool, Error> {
@ -102,5 +126,3 @@ impl Debuggable for Z80<Instant> {
Ok(false)
}
}

View File

@ -1,7 +1,7 @@
use std::rc::Rc;
use std::cell::RefCell;
use femtos::{Instant, Frequency};
use emulator_hal::Instant as EmuInstant;
use emulator_hal::{Instant as EmuInstant, BusAccess};
use moa_core::{Address, Bus, BusPort};
use moa_signals::Signal;
@ -92,6 +92,12 @@ impl Z80State {
}
}
#[derive(Clone, Debug, Default)]
pub struct Z80Signals {
pub reset: bool,
pub bus_request: bool,
}
#[derive(Clone, Debug, thiserror::Error)]
pub enum Z80Error /* <B: fmt::Display> */ {
#[error("cpu halted")]
@ -120,8 +126,7 @@ pub struct Z80<Instant> {
pub state: Z80State,
pub debugger: Z80Debugger,
pub previous_cycle: Z80Cycle<Instant>,
//pub port: BusPort,
//pub ioport: Option<BusPort>,
pub signals: Z80Signals,
// TODO activate later
//pub reset: Signal<bool>,
//pub bus_request: Signal<bool>,
@ -131,34 +136,22 @@ impl<Instant> Z80<Instant>
where
Instant: EmuInstant,
{
pub fn new(cputype: Z80Type, frequency: Frequency /*, port: BusPort, ioport: Option<BusPort>*/) -> Self {
pub fn new(cputype: Z80Type, frequency: Frequency) -> Self {
Self {
cputype,
frequency,
state: Z80State::default(),
debugger: Z80Debugger::default(),
previous_cycle: Z80Cycle::at_time(Instant::START),
//port,
//ioport,
signals: Z80Signals::default(),
//reset: Signal::new(false),
//bus_request: Signal::new(false),
}
}
pub fn from_type(
cputype: Z80Type,
frequency: Frequency,
bus: Rc<RefCell<Bus>>,
addr_offset: Address,
io_bus: Option<(Rc<RefCell<Bus>>, Address)>,
) -> Self {
pub fn from_type(cputype: Z80Type, frequency: Frequency) -> Self {
match cputype {
Z80Type::Z80 => Self::new(
cputype,
frequency,
//BusPort::new(addr_offset, 16, 8, bus),
//io_bus.map(|(io_bus, io_offset)| BusPort::new(io_offset, 16, 8, io_bus)),
),
Z80Type::Z80 => Self::new(cputype, frequency),
}
}
@ -168,7 +161,10 @@ where
self.debugger = Z80Debugger::default();
}
pub fn dump_state(&mut self, clock: Instant) {
pub fn dump_state<Bus>(&mut self, clock: Instant, bus: &mut Bus)
where
Bus: BusAccess<Z80Address, Instant = Instant>,
{
println!("Status: {:?}", self.state.status);
println!("PC: {:#06x}", self.state.pc);
println!("SP: {:#06x}", self.state.sp);
@ -207,12 +203,11 @@ where
println!("I: {:#04x} R: {:#04x}", self.state.i, self.state.r);
println!("IM: {:?} IFF1: {:?} IFF2: {:?}", self.state.im, self.state.iff1, self.state.iff2);
// TODO disabled until function is reimplemented
//println!(
// "Current Instruction: {} {:?}",
// self.decoder.format_instruction_bytes(&mut self.port),
// self.decoder.instruction
//);
println!(
"Current Instruction: {} {:?}",
self.previous_cycle.decoder.format_instruction_bytes(bus),
self.previous_cycle.decoder.instruction
);
println!("Previous Instruction: {:?}", self.previous_cycle.decoder.instruction);
println!();
// TODO disabled until function is reimplemented

View File

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

View File

@ -2,7 +2,7 @@ use std::mem;
use std::rc::Rc;
use std::cell::RefCell;
use femtos::Frequency;
use femtos::{Instant, Frequency};
use moa_core::{System, Error, MemoryBlock, Bus, Address, Addressable, Device};
use moa_host::Host;
@ -68,11 +68,13 @@ pub fn build_genesis<H: Host>(host: &mut H, mut options: SegaGenesisOptions) ->
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 coproc = Z80::from_type(Z80Type::Z80, Frequency::from_hz(3_579_545), coproc_bus, 0, None);
let mut reset = coproc.reset.clone();
let mut bus_request = coproc.bus_request.clone();
reset.set(true);
bus_request.set(true);
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 = Device::new(coproc);
// Add coprocessor devices to the system bus so the 68000 can access them too
system.add_addressable_device(0x00a00000, coproc_ram)?;
@ -80,14 +82,14 @@ pub fn build_genesis<H: Host>(host: &mut H, mut options: SegaGenesisOptions) ->
system.add_addressable_device(0x00a06000, coproc_register)?;
//system.add_addressable_device(0x00c00010, coproc_sn_sound)?;
system.add_device("sn_sound", coproc_sn_sound.clone())?;
system.add_device("coproc", Device::new(coproc))?;
system.add_device("coproc", coproc.clone())?;
let controllers = GenesisControllers::new(host)?;
let interrupt = controllers.get_interrupt_signal();
system.add_addressable_device(0x00a10000, Device::new(controllers))?;
let coproc = CoprocessorCoordinator::new(reset, bus_request);
let coproc = CoprocessorCoordinator::new(coproc);
system.add_addressable_device(0x00a11000, Device::new(coproc))?;
let vdp = Ym7101::new(host, interrupt, coproc_sn_sound)?;

View File

@ -44,7 +44,7 @@ pub fn build_trs80<H: Host>(host: &mut H, options: Trs80Options) -> Result<Syste
system.add_addressable_device(0x37E0 + 0x420, Device::new(video)).unwrap();
// TODO the ioport needs to be hooked up
let cpu = Z80::from_type(Z80Type::Z80, options.frequency, system.bus.clone(), 0, None);
let cpu = Z80::from_type(Z80Type::Z80, options.frequency);
system.add_interruptable_device("cpu", Device::new(cpu))?;

View File

@ -148,7 +148,11 @@ impl TestCase {
}
fn init_execute_test(cputype: Z80Type, state: &TestState, ports: &[TestPort]) -> Result<(Z80<Instant>, MemoryBlock<Instant>, MemoryBlock<Instant>), Error> {
fn init_execute_test(
cputype: Z80Type,
state: &TestState,
ports: &[TestPort],
) -> Result<(Z80<Instant>, MemoryBlock<Instant>, MemoryBlock<Instant>), Error> {
// Insert basic initialization
let len = 0x1_0000;
let mut data = Vec::with_capacity(len);
@ -220,7 +224,8 @@ fn load_state(
// Load data bytes into memory
for (addr, byte) in initial.ram.iter() {
memory.write_u8(Instant::START, *addr, *byte)
memory
.write_u8(Instant::START, *addr, *byte)
.map_err(|err| Error::Bus(format!("{:?}", err)))?;
}
@ -281,7 +286,8 @@ fn assert_state(
// Load data bytes into memory
for (addr, byte) in expected.ram.iter() {
let actual = memory.read_u8(Instant::START, *addr)
let actual = memory
.read_u8(Instant::START, *addr)
.map_err(|err| Error::Bus(format!("{:?}", err)))?;
assert_value(actual, *byte, &format!("ram at {:x}", addr))?;
}
@ -289,7 +295,8 @@ fn assert_state(
// Load data bytes into io space
for port in ports.iter() {
if port.atype == "w" {
let actual = io.read_u8(Instant::START, port.addr)
let actual = io
.read_u8(Instant::START, port.addr)
.map_err(|err| Error::Bus(format!("{:?}", err)))?;
assert_value(actual, port.value, &format!("port value at {:x}", port.addr))?;
}
@ -306,7 +313,8 @@ fn step_cpu_and_assert(
args: &Args,
) -> Result<(), Error> {
//let clock_elapsed = cpu.step((memory, io))?;
let clock_elapsed = cpu.step(Instant::START, memory)
let clock_elapsed = cpu
.step(Instant::START, memory)
.map_err(|err| Error::Step(format!("{:?}", err)))?;
assert_state(cpu, memory, io, &case.final_state, args.check_extra_flags, &case.ports)?;
@ -338,8 +346,8 @@ fn run_test(case: &TestCase, args: &Args) -> Result<(), Error> {
if args.debug {
case.dump();
println!();
initial_cpu.dump_state(Instant::START);
cpu.dump_state(Instant::START);
initial_cpu.dump_state(Instant::START, &mut memory);
cpu.dump_state(Instant::START, &mut memory);
}
println!("FAILED: {:?}", err);
}