mirror of
https://github.com/transistorfet/moa.git
synced 2024-09-28 08:54:40 +00:00
TRS-80 Model 1 Basic is now working
This commit is contained in:
parent
6cb9b985ad
commit
d3efa072c2
@ -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"),
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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
@ -45,7 +45,12 @@ 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::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),
|
||||
_ => { },
|
||||
|
@ -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 {
|
||||
|
Loading…
Reference in New Issue
Block a user