use std::rc::Rc; use std::cell::RefCell; use femtos::{Instant, Frequency}; use emulator_hal::{Instant as EmuInstant, BusAccess}; use moa_core::{Address, Bus, BusPort}; use moa_signals::Signal; use crate::debugger::Z80Debugger; use crate::execute::Z80Cycle; use crate::instructions::{Instruction, Register, InterruptMode}; #[allow(dead_code)] #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] pub enum Z80Type { Z80, } #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum Status { Init, Running, Halted, } #[repr(u8)] #[allow(dead_code)] #[derive(Copy, Clone, Debug, PartialEq, Eq)] #[rustfmt::skip] pub enum Flags { Carry = 0x01, AddSubtract = 0x02, Parity = 0x04, F3 = 0x08, HalfCarry = 0x10, F5 = 0x20, Zero = 0x40, Sign = 0x80, } #[derive(Clone, Debug, PartialEq, Eq)] pub struct Z80State { pub status: Status, pub pc: u16, pub sp: u16, pub ix: u16, pub iy: u16, pub reg: [u8; 8], pub shadow_reg: [u8; 8], pub i: u8, pub r: u8, pub iff1: bool, pub iff2: bool, pub im: InterruptMode, } impl Default for Z80State { fn default() -> Self { Self { status: Status::Init, pc: 0, sp: 0, ix: 0, iy: 0, reg: [0; 8], shadow_reg: [0; 8], i: 0, r: 0, iff1: false, iff2: false, im: InterruptMode::Mode0, } } } impl Z80State { pub fn get_register(&mut self, reg: Register) -> u8 { self.reg[reg as usize] } pub fn set_register(&mut self, reg: Register, value: u8) { self.reg[reg as usize] = value; } } #[derive(Clone, Debug, Default)] pub struct Z80Signals { //pub reset: bool, //pub bus_request: bool, pub reset: Signal, pub bus_request: Signal, } #[derive(Clone, Debug, thiserror::Error)] pub enum Z80Error /* */ { #[error("cpu halted")] Halted, #[error("breakpoint reached")] Breakpoint, #[error("unimplemented instruction {0:?}")] Unimplemented(Instruction), #[error("bus error: {0}")] BusError(String /* B */), } pub type Z80Address = u16; pub type Z80IOAddress = u16; pub enum Z80AddressSpace { Memory(Z80Address), IO(Z80IOAddress), } #[derive(Clone)] pub struct Z80 { pub cputype: Z80Type, pub frequency: Frequency, pub state: Z80State, pub debugger: Z80Debugger, pub previous_cycle: Z80Cycle, pub signals: Z80Signals, // TODO activate later //pub reset: Signal, //pub bus_request: Signal, } impl Z80 where Instant: EmuInstant, { pub fn new(cputype: Z80Type, frequency: Frequency) -> Self { Self { cputype, frequency, state: Z80State::default(), debugger: Z80Debugger::default(), previous_cycle: Z80Cycle::at_time(Instant::START), signals: Z80Signals::default(), //reset: Signal::new(false), //bus_request: Signal::new(false), } } pub fn from_type(cputype: Z80Type, frequency: Frequency) -> Self { match cputype { Z80Type::Z80 => Self::new(cputype, frequency), } } #[allow(dead_code)] pub fn clear_state(&mut self) { self.state = Z80State::default(); self.debugger = Z80Debugger::default(); } pub fn dump_state(&mut self, clock: Instant, bus: &mut Bus) where Bus: BusAccess, { println!("Status: {:?}", self.state.status); println!("PC: {:#06x}", self.state.pc); println!("SP: {:#06x}", self.state.sp); println!("IX: {:#06x}", self.state.ix); println!("IY: {:#06x}", self.state.iy); println!( "A: {:#04x} F: {:#04x} A': {:#04x} F': {:#04x}", self.state.reg[Register::A as usize], self.state.reg[Register::F as usize], self.state.shadow_reg[Register::A as usize], self.state.shadow_reg[Register::F as usize] ); println!( "B: {:#04x} C: {:#04x} B': {:#04x} C': {:#04x}", self.state.reg[Register::B as usize], self.state.reg[Register::C as usize], self.state.shadow_reg[Register::B as usize], self.state.shadow_reg[Register::C as usize] ); println!( "D: {:#04x} E: {:#04x} D': {:#04x} E': {:#04x}", self.state.reg[Register::D as usize], self.state.reg[Register::E as usize], self.state.shadow_reg[Register::D as usize], self.state.shadow_reg[Register::E as usize] ); println!( "H: {:#04x} L: {:#04x} H': {:#04x} L': {:#04x}", self.state.reg[Register::H as usize], self.state.reg[Register::L as usize], self.state.shadow_reg[Register::H as usize], self.state.shadow_reg[Register::L as usize] ); println!("I: {:#04x} R: {:#04x}", self.state.i, self.state.r); println!("IM: {:?} IFF1: {:?} IFF2: {:?}", self.state.im, self.state.iff1, self.state.iff2); 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 //self.port.dump_memory(clock, self.state.sp as Address, 0x40); println!(); } }