use std::io::{self, Write};
use u880::{Cpu, Revision, pins};
const Z80TYPE: &[u8] = include_bytes!("assets/z80type.com");
fn run_z80type_test(rom: &[u8], revision: Revision, expected: &str) {
let mut cpu = Cpu::with_revision(revision);
let mut mem = vec![0u8; 1 << 16];
let mut bus;
mem[0x0100..0x0100 + rom.len()].copy_from_slice(rom);
mem[0x0005] = 0xC9;
bus = cpu.prefetch(0x0100);
let mut output = String::new();
loop {
bus = cpu.tick(bus);
if bus & pins::MREQ != 0 {
let addr = pins::addr(bus) as usize;
if bus & pins::RD != 0 {
bus = pins::set_data(bus, mem[addr]);
} else if bus & pins::WR != 0 {
mem[addr] = pins::data(bus);
}
} else if bus & pins::IORQ != 0 {
if bus & pins::RD != 0 {
bus = pins::set_data(bus, 0x00);
}
}
if cpu.opdone() {
let pc = pins::addr(bus);
if pc == 0x0000 {
let _ = io::stdout().write_all(b"\n");
break;
} else if pc == 0x0005 {
match cpu.regs.c {
2 => {
let ch = cpu.regs.e as char;
print!("{}", ch);
let _ = io::stdout().flush();
output.push(ch);
}
9 => {
let mut addr = cpu.regs.de() as usize;
let mut msg = String::new();
loop {
let ch = mem[addr] as char;
if ch == '$' {
break;
}
if ch != '\r' {
msg.push(ch);
}
addr = (addr + 1) & 0xFFFF;
}
print!("{}", msg);
let _ = io::stdout().flush();
output.push_str(&msg);
}
_ => panic!(),
}
}
}
}
assert!(output.contains(expected));
}
#[test]
#[ignore]
fn test_z80type() {
run_z80type_test(
Z80TYPE,
Revision::Older,
"Detected CPU type: Older MME U880",
);
run_z80type_test(
Z80TYPE,
Revision::Newer,
"Detected CPU type: Newer MME U880, Thesys Z80, Microelectronica MMN 80CPU",
);
}