TRS-80 Model 1 Basic is now working

This commit is contained in:
transistor 2021-11-07 22:44:40 -08:00
parent 6cb9b985ad
commit d3efa072c2
6 changed files with 559 additions and 539 deletions

View File

@ -107,7 +107,7 @@ pub enum Instruction {
EXX,
EXafaf,
EXhlde,
EXhlsp,
EXsp(RegisterPair),
HALT,
IM(u8),
INC16(RegisterPair),
@ -119,7 +119,7 @@ pub enum Instruction {
INic(Register),
INx(u8),
JP(u16),
JPIndirectHL,
JPIndirect(RegisterPair),
JPcc(Condition, u16),
JR(i8),
JRcc(Condition, i8),
@ -300,7 +300,7 @@ impl Z80Decoder {
match get_ins_p(ins) {
0 => Ok(Instruction::RET),
1 => Ok(Instruction::EXX),
2 => Ok(Instruction::JPIndirectHL),
2 => Ok(Instruction::JPIndirect(RegisterPair::HL)),
3 => Ok(Instruction::LD(LoadTarget::DirectRegWord(RegisterPair::SP), LoadTarget::DirectRegWord(RegisterPair::HL))),
_ => panic!("InternalError: impossible value"),
}
@ -327,7 +327,7 @@ impl Z80Decoder {
let port = self.read_instruction_byte(memory)?;
Ok(Instruction::INx(port))
},
4 => Ok(Instruction::EXhlsp),
4 => Ok(Instruction::EXsp(RegisterPair::HL)),
5 => Ok(Instruction::EXhlde),
6 => Ok(Instruction::DI),
7 => Ok(Instruction::EI),
@ -578,8 +578,14 @@ impl Z80Decoder {
panic!("");
},
3 => {
panic!("");
match ins {
0xE1 => Ok(Instruction::POP(get_register_pair_from_index(index_reg))),
0xE3 => Ok(Instruction::EXsp(get_register_pair_from_index(index_reg))),
0xE5 => Ok(Instruction::PUSH(get_register_pair_from_index(index_reg))),
0xE9 => Ok(Instruction::JPIndirect(get_register_pair_from_index(index_reg))),
0xF9 => Ok(Instruction::LD(LoadTarget::DirectRegWord(RegisterPair::SP), LoadTarget::DirectRegWord(get_register_pair_from_index(index_reg)))),
_ => Ok(Instruction::NOP),
}
},
_ => panic!("InternalError: impossible value"),
}

View File

@ -158,7 +158,7 @@ impl Z80 {
Instruction::BIT(bit, target) => {
let value = self.get_target_value(target)?;
let result = (value & (1 << bit));
self.set_numeric_flags(result as u16, Size::Byte);
self.set_flag(Flags::Zero, result == 0);
self.set_flag(Flags::AddSubtract, false);
self.set_flag(Flags::HalfCarry, true);
},
@ -173,9 +173,9 @@ impl Z80 {
}
},
Instruction::CCF => {
self.set_flag(Flags::HalfCarry, self.get_flag(Flags::Carry));
self.set_flag(Flags::AddSubtract, false);
self.set_flag(Flags::Carry, false);
self.set_flag(Flags::HalfCarry, self.get_flag(Flags::Carry));
self.set_flag(Flags::Carry, !self.get_flag(Flags::Carry));
},
Instruction::CP(target) => {
let src = self.get_target_value(target)?;
@ -244,17 +244,18 @@ impl Z80 {
self.state.shadow_reg[i] = normal;
}
},
Instruction::EXhlsp => {
let (sp_addr, hl) = (self.get_register_pair_value(RegisterPair::SP), self.get_register_pair_value(RegisterPair::HL));
let sp = self.port.read_leu16(sp_addr as Address)?;
self.set_register_pair_value(RegisterPair::HL, sp);
self.port.write_leu16(sp_addr as Address, hl)?;
},
Instruction::EXhlde => {
let (hl, de) = (self.get_register_pair_value(RegisterPair::HL), self.get_register_pair_value(RegisterPair::DE));
self.set_register_pair_value(RegisterPair::DE, hl);
self.set_register_pair_value(RegisterPair::HL, de);
},
Instruction::EXsp(regpair) => {
let reg_value = self.get_register_pair_value(regpair);
let sp = self.get_register_pair_value(RegisterPair::SP);
let sp_value = self.port.read_leu16(sp as Address)?;
self.set_register_pair_value(regpair, sp_value);
self.port.write_leu16(sp as Address, reg_value)?;
},
Instruction::HALT => {
self.state.status = Status::Halted;
},
@ -290,10 +291,10 @@ impl Z80 {
Instruction::JP(addr) => {
self.state.pc = addr;
},
Instruction::JPIndirectHL => {
let hl = self.get_register_pair_value(RegisterPair::HL);
let addr = self.port.read_leu16(hl as Address)?;
self.state.pc = addr;
Instruction::JPIndirect(regpair) => {
let value = self.get_register_pair_value(regpair);
//let addr = self.port.read_leu16(value as Address)?;
self.state.pc = value;
},
Instruction::JPcc(cond, addr) => {
if self.get_current_condition(cond) {

View File

@ -14,7 +14,9 @@ use crate::host::tty::SimplePty;
pub fn build_trs80<H: Host>(host: &mut H) -> Result<System, Error> {
let mut system = System::new();
let mut rom = MemoryBlock::load("binaries/trs80/level1.rom")?;
let mut rom = MemoryBlock::new(vec![0; 0x4000]);
rom.load_at(0x0000, "binaries/trs80/level1.rom")?;
rom.load_at(0x1000, "binaries/trs80/level2.rom")?;
rom.read_only();
system.add_addressable_device(0x0000, wrap_transmutable(rom))?;
@ -25,6 +27,12 @@ pub fn build_trs80<H: Host>(host: &mut H) -> Result<System, Error> {
system.add_addressable_device(0x37E0, wrap_transmutable(model1)).unwrap();
let mut cpu = Z80::new(Z80Type::Z80, 4_000_000, BusPort::new(0, 16, 8, system.bus.clone()));
//cpu.add_breakpoint(0x0);
//cpu.add_breakpoint(0xb55);
//cpu.add_breakpoint(0xb76);
//cpu.add_breakpoint(0x1e5);
//cpu.add_breakpoint(0x340); // "exec", the function that executes the line typed in
//cpu.add_breakpoint(0x357);
system.add_interruptable_device("cpu", wrap_transmutable(cpu))?;
Ok(system)

File diff suppressed because it is too large Load Diff

View File

@ -45,8 +45,13 @@ pub fn record_key_press(data: &mut [u8; 8], key: Key, state: bool) {
Key::Num7 => set_bit(data, 4, 7, state),
Key::Num8 => set_bit(data, 5, 0, state),
Key::Num9 => set_bit(data, 5, 1, state),
Key::Enter => set_bit(data, 6, 0, state),
Key::Space => set_bit(data, 6, 7, state),
Key::Equals => set_bit(data, 5, 5, state),
Key::Enter => set_bit(data, 6, 0, state),
Key::Up => set_bit(data, 6, 3, state),
Key::Down => set_bit(data, 6, 4, state),
Key::Left => set_bit(data, 6, 5, state),
Key::Right => set_bit(data, 6, 6, state),
Key::Space => set_bit(data, 6, 7, state),
Key::LeftShift | Key::RightShift => set_bit(data, 7, 0, state),
_ => { },
}

View File

@ -24,7 +24,7 @@ pub struct Model1Peripherals {
impl Model1Peripherals {
pub fn create<H: Host>(host: &mut H) -> Result<Self, Error> {
let swapper = FrameSwapper::new_shared(320, 128);
let swapper = FrameSwapper::new_shared(384, 128);
let keyboard_mem = Arc::new(Mutex::new([0; 8]));
host.add_window(FrameSwapper::to_boxed(swapper.clone()))?;
@ -58,7 +58,7 @@ impl Steppable for Model1Peripherals {
let ch = self.video_mem[x + (y * 64)];
// TODO this is totally a hack for now!!!!!
let iter = CharacterGenerator::new((ch - 0x20) % 64);
swapper.current.blit((x * 5) as u32, (y * 8) as u32, iter, 5, 8);
swapper.current.blit((x * 6) as u32, (y * 8) as u32, iter, 6, 8);
}
}
@ -94,7 +94,7 @@ impl Addressable for Model1Peripherals {
}
fn write(&mut self, addr: Address, data: &[u8]) -> Result<(), Error> {
info!("{}: write to register {:x} with {:x}", DEV_NAME, addr, data[0]);
debug!("{}: write to register {:x} with {:x}", DEV_NAME, addr, data[0]);
if addr > 0x420 && addr < 0x820 {
self.video_mem[addr as usize - 0x420] = data[0];
} else {