mod headless_emulator; mod graphical_emulator; mod dynamic_emulator; pub use headless_emulator::*; pub use graphical_emulator::*; pub use dynamic_emulator::*; use crate::*; use ansi::*; pub struct EmulatorConfig { pub initial_dimensions: ScreenDimensions, pub fullscreen: bool, pub zoom: NonZeroU32, pub override_palette: Option<[Colour; 16]>, pub show_cursor: bool, pub decode_stdin: bool, pub encode_stdout: bool, pub symbols_path: Option, pub metadata: Option, } pub struct DebugState { pub enabled: bool, last_cycle: usize, last_mark: Instant, symbols: DebugSymbols, } impl DebugState { pub fn new>(enabled: bool, symbols_path: Option

) -> Self { Self { enabled, last_cycle: 0, last_mark: Instant::now(), symbols: DebugSymbols::from_path_opt(symbols_path), } } pub fn debug_summary(&mut self, core: &BedrockCore) { if self.enabled { let prev_pc = core.mem.pc.wrapping_sub(1); eprintln!("\n PC: 0x{:04x} Cycles: {} (+{} in {:.2?})", prev_pc, core.cycle, core.cycle.saturating_sub(self.last_cycle), self.last_mark.elapsed(), ); eprint!("WST: "); debug_stack(&core.wst, 0x10); eprint!("RST: "); debug_stack(&core.rst, 0x10); // Print information about the closest symbol. if let Some(symbol) = self.symbols.for_address(prev_pc) { let name = &symbol.name; let address = &symbol.address; eprint!("SYM: {BLUE}@{name}{NORMAL} 0x{address:04x}"); if let Some(location) = &symbol.location { eprint!(" {DIM}{location}{NORMAL}"); } eprintln!(); } } self.last_cycle = core.cycle; self.last_mark = Instant::now(); } } fn debug_stack(stack: &Stack, len: usize) { for i in 0..len { if i == stack.sp as usize { eprint!("{YELLOW}"); } eprint!("{:02x} ", stack.mem[i]); } eprintln!("{NORMAL}"); }