Added TRS-80 simulation to test Z80 impl
This commit is contained in:
parent
7e999d4c3a
commit
5bfde2bff0
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,43 @@
|
||||||
|
|
||||||
|
use std::thread;
|
||||||
|
use std::time::Duration;
|
||||||
|
use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
|
use moa::machines::trs80::build_trs80;
|
||||||
|
use moa_minifb::MiniFrontendBuilder;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
/*
|
||||||
|
let mut frontend = Arc::new(Mutex::new(MiniFrontendBuilder::new()));
|
||||||
|
|
||||||
|
{
|
||||||
|
let frontend = frontend.clone();
|
||||||
|
thread::spawn(move || {
|
||||||
|
let mut system = build_trs80(&mut *(frontend.lock().unwrap())).unwrap();
|
||||||
|
frontend.lock().unwrap().finalize();
|
||||||
|
system.run_loop();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
wait_until_initialized(frontend.clone());
|
||||||
|
|
||||||
|
frontend
|
||||||
|
.lock().unwrap()
|
||||||
|
.build()
|
||||||
|
.start(None);
|
||||||
|
*/
|
||||||
|
|
||||||
|
let mut frontend = MiniFrontendBuilder::new();
|
||||||
|
let mut system = build_trs80(&mut frontend).unwrap();
|
||||||
|
|
||||||
|
frontend
|
||||||
|
.build()
|
||||||
|
.start(Some(system));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn wait_until_initialized(frontend: Arc<Mutex<MiniFrontendBuilder>>) {
|
||||||
|
while frontend.lock().unwrap().finalized == false {
|
||||||
|
thread::sleep(Duration::from_millis(10));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,112 @@
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||||
|
pub enum Key {
|
||||||
|
A,
|
||||||
|
B,
|
||||||
|
C,
|
||||||
|
D,
|
||||||
|
E,
|
||||||
|
F,
|
||||||
|
G,
|
||||||
|
H,
|
||||||
|
I,
|
||||||
|
J,
|
||||||
|
K,
|
||||||
|
L,
|
||||||
|
M,
|
||||||
|
N,
|
||||||
|
O,
|
||||||
|
P,
|
||||||
|
Q,
|
||||||
|
R,
|
||||||
|
S,
|
||||||
|
T,
|
||||||
|
U,
|
||||||
|
V,
|
||||||
|
W,
|
||||||
|
X,
|
||||||
|
Y,
|
||||||
|
Z,
|
||||||
|
Num1,
|
||||||
|
Num2,
|
||||||
|
Num3,
|
||||||
|
Num4,
|
||||||
|
Num5,
|
||||||
|
Num6,
|
||||||
|
Num7,
|
||||||
|
Num8,
|
||||||
|
Num9,
|
||||||
|
Num0,
|
||||||
|
Enter,
|
||||||
|
Escape,
|
||||||
|
Backspace,
|
||||||
|
Tab,
|
||||||
|
Space,
|
||||||
|
Minus,
|
||||||
|
Equals,
|
||||||
|
LeftBracket,
|
||||||
|
RightBracket,
|
||||||
|
Backslash,
|
||||||
|
Semicolon,
|
||||||
|
Apostrophe,
|
||||||
|
Backquote,
|
||||||
|
Comma,
|
||||||
|
Period,
|
||||||
|
Slash,
|
||||||
|
F1,
|
||||||
|
F2,
|
||||||
|
F3,
|
||||||
|
F4,
|
||||||
|
F5,
|
||||||
|
F6,
|
||||||
|
F7,
|
||||||
|
F8,
|
||||||
|
F9,
|
||||||
|
F10,
|
||||||
|
F11,
|
||||||
|
F12,
|
||||||
|
PrintScreen,
|
||||||
|
ScrollLock,
|
||||||
|
Pause,
|
||||||
|
Insert,
|
||||||
|
Home,
|
||||||
|
PageUp,
|
||||||
|
Delete,
|
||||||
|
End,
|
||||||
|
PageDown,
|
||||||
|
Right,
|
||||||
|
Left,
|
||||||
|
Down,
|
||||||
|
Up,
|
||||||
|
|
||||||
|
NumLock,
|
||||||
|
CapsLock,
|
||||||
|
LeftShift,
|
||||||
|
RightShift,
|
||||||
|
LeftCtrl,
|
||||||
|
RightCtrl,
|
||||||
|
LeftAlt,
|
||||||
|
RightAlt,
|
||||||
|
LeftSuper,
|
||||||
|
RightSuper,
|
||||||
|
|
||||||
|
NumPad0,
|
||||||
|
NumPad1,
|
||||||
|
NumPad2,
|
||||||
|
NumPad3,
|
||||||
|
NumPad4,
|
||||||
|
NumPad5,
|
||||||
|
NumPad6,
|
||||||
|
NumPad7,
|
||||||
|
NumPad8,
|
||||||
|
NumPad9,
|
||||||
|
NumPadDot,
|
||||||
|
NumPadSlash,
|
||||||
|
NumPadAsterisk,
|
||||||
|
NumPadMinus,
|
||||||
|
NumPadPlus,
|
||||||
|
NumPadEnter,
|
||||||
|
|
||||||
|
Unknown,
|
||||||
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
|
|
||||||
pub mod computie;
|
pub mod computie;
|
||||||
pub mod genesis;
|
pub mod genesis;
|
||||||
|
pub mod trs80;
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
|
||||||
|
use crate::error::Error;
|
||||||
|
use crate::system::System;
|
||||||
|
use crate::devices::{Debuggable, wrap_transmutable};
|
||||||
|
use crate::memory::{MemoryBlock, BusPort};
|
||||||
|
|
||||||
|
use crate::cpus::z80::{Z80, Z80Type};
|
||||||
|
use crate::peripherals::trs80;
|
||||||
|
|
||||||
|
use crate::host::traits::Host;
|
||||||
|
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")?;
|
||||||
|
rom.read_only();
|
||||||
|
system.add_addressable_device(0x0000, wrap_transmutable(rom))?;
|
||||||
|
|
||||||
|
let mut ram = MemoryBlock::new(vec![0; 0xC000]);
|
||||||
|
system.add_addressable_device(0x4000, wrap_transmutable(ram))?;
|
||||||
|
|
||||||
|
let model1 = trs80::model1::Model1Peripherals::create(host)?;
|
||||||
|
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()));
|
||||||
|
system.add_interruptable_device("cpu", wrap_transmutable(cpu))?;
|
||||||
|
|
||||||
|
Ok(system)
|
||||||
|
}
|
||||||
|
|
|
@ -2,4 +2,5 @@
|
||||||
pub mod ata;
|
pub mod ata;
|
||||||
pub mod mc68681;
|
pub mod mc68681;
|
||||||
pub mod genesis;
|
pub mod genesis;
|
||||||
|
pub mod trs80;
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,693 @@
|
||||||
|
|
||||||
|
const CHARACTERS: [[u8; 8]; 64] = [
|
||||||
|
// Blank
|
||||||
|
[ 0b00000,
|
||||||
|
0b00000,
|
||||||
|
0b00000,
|
||||||
|
0b00000,
|
||||||
|
0b00000,
|
||||||
|
0b00000,
|
||||||
|
0b00000,
|
||||||
|
0b00000 ],
|
||||||
|
|
||||||
|
// Character !
|
||||||
|
[ 0b00100,
|
||||||
|
0b00100,
|
||||||
|
0b00100,
|
||||||
|
0b00100,
|
||||||
|
0b00100,
|
||||||
|
0b00000,
|
||||||
|
0b00100,
|
||||||
|
0b00000 ],
|
||||||
|
|
||||||
|
// Character "
|
||||||
|
[ 0b01010,
|
||||||
|
0b01010,
|
||||||
|
0b01010,
|
||||||
|
0b00000,
|
||||||
|
0b00000,
|
||||||
|
0b00000,
|
||||||
|
0b00000,
|
||||||
|
0b00000 ],
|
||||||
|
|
||||||
|
// Character #
|
||||||
|
[ 0b01010,
|
||||||
|
0b01010,
|
||||||
|
0b11111,
|
||||||
|
0b01010,
|
||||||
|
0b11111,
|
||||||
|
0b01010,
|
||||||
|
0b01010,
|
||||||
|
0b00000 ],
|
||||||
|
|
||||||
|
// Character $
|
||||||
|
[ 0b01110,
|
||||||
|
0b10101,
|
||||||
|
0b10100,
|
||||||
|
0b01110,
|
||||||
|
0b00101,
|
||||||
|
0b10101,
|
||||||
|
0b01110,
|
||||||
|
0b00100 ],
|
||||||
|
|
||||||
|
|
||||||
|
// Character %
|
||||||
|
[ 0b11001,
|
||||||
|
0b11010,
|
||||||
|
0b00010,
|
||||||
|
0b00100,
|
||||||
|
0b01000,
|
||||||
|
0b01011,
|
||||||
|
0b10011,
|
||||||
|
0b00000 ],
|
||||||
|
|
||||||
|
// Character &
|
||||||
|
[ 0b00100,
|
||||||
|
0b01010,
|
||||||
|
0b01010,
|
||||||
|
0b00100,
|
||||||
|
0b01100,
|
||||||
|
0b10011,
|
||||||
|
0b01110,
|
||||||
|
0b00000 ],
|
||||||
|
|
||||||
|
// Character '
|
||||||
|
[ 0b01000,
|
||||||
|
0b01000,
|
||||||
|
0b01000,
|
||||||
|
0b00000,
|
||||||
|
0b00000,
|
||||||
|
0b00000,
|
||||||
|
0b00000,
|
||||||
|
0b00000 ],
|
||||||
|
|
||||||
|
// Character (
|
||||||
|
[ 0b00100,
|
||||||
|
0b01000,
|
||||||
|
0b10000,
|
||||||
|
0b10000,
|
||||||
|
0b10000,
|
||||||
|
0b01000,
|
||||||
|
0b00100,
|
||||||
|
0b00000 ],
|
||||||
|
|
||||||
|
// Character )
|
||||||
|
[ 0b00100,
|
||||||
|
0b00010,
|
||||||
|
0b00001,
|
||||||
|
0b00001,
|
||||||
|
0b00001,
|
||||||
|
0b00010,
|
||||||
|
0b00100,
|
||||||
|
0b00000 ],
|
||||||
|
|
||||||
|
// Character *
|
||||||
|
[ 0b00000,
|
||||||
|
0b00000,
|
||||||
|
0b01010,
|
||||||
|
0b00100,
|
||||||
|
0b01010,
|
||||||
|
0b00000,
|
||||||
|
0b00000,
|
||||||
|
0b00000 ],
|
||||||
|
|
||||||
|
// Character +
|
||||||
|
[ 0b00000,
|
||||||
|
0b00000,
|
||||||
|
0b00100,
|
||||||
|
0b01110,
|
||||||
|
0b00100,
|
||||||
|
0b00000,
|
||||||
|
0b00000,
|
||||||
|
0b00000 ],
|
||||||
|
|
||||||
|
// Character ,
|
||||||
|
[ 0b00000,
|
||||||
|
0b00000,
|
||||||
|
0b00000,
|
||||||
|
0b00000,
|
||||||
|
0b00010,
|
||||||
|
0b00010,
|
||||||
|
0b00100,
|
||||||
|
0b00000 ],
|
||||||
|
|
||||||
|
// Character -
|
||||||
|
[ 0b00000,
|
||||||
|
0b00000,
|
||||||
|
0b00000,
|
||||||
|
0b01110,
|
||||||
|
0b00000,
|
||||||
|
0b00000,
|
||||||
|
0b00000,
|
||||||
|
0b00000 ],
|
||||||
|
|
||||||
|
// Character .
|
||||||
|
[ 0b00000,
|
||||||
|
0b00000,
|
||||||
|
0b00000,
|
||||||
|
0b00000,
|
||||||
|
0b00110,
|
||||||
|
0b00110,
|
||||||
|
0b00000,
|
||||||
|
0b00000 ],
|
||||||
|
|
||||||
|
// Character /
|
||||||
|
[ 0b00010,
|
||||||
|
0b00010,
|
||||||
|
0b00100,
|
||||||
|
0b00100,
|
||||||
|
0b01000,
|
||||||
|
0b01000,
|
||||||
|
0b10000,
|
||||||
|
0b00000 ],
|
||||||
|
|
||||||
|
// Character 0
|
||||||
|
[ 0b01100,
|
||||||
|
0b10010,
|
||||||
|
0b11010,
|
||||||
|
0b10110,
|
||||||
|
0b10010,
|
||||||
|
0b10010,
|
||||||
|
0b01100,
|
||||||
|
0b00000 ],
|
||||||
|
|
||||||
|
// Character 1
|
||||||
|
[ 0b00100,
|
||||||
|
0b01100,
|
||||||
|
0b00100,
|
||||||
|
0b00100,
|
||||||
|
0b00100,
|
||||||
|
0b00100,
|
||||||
|
0b01110,
|
||||||
|
0b00000 ],
|
||||||
|
|
||||||
|
// Character 2
|
||||||
|
[ 0b01100,
|
||||||
|
0b10010,
|
||||||
|
0b00010,
|
||||||
|
0b00100,
|
||||||
|
0b01000,
|
||||||
|
0b10000,
|
||||||
|
0b11110,
|
||||||
|
0b00000 ],
|
||||||
|
|
||||||
|
// Character 3
|
||||||
|
[ 0b11100,
|
||||||
|
0b00010,
|
||||||
|
0b00010,
|
||||||
|
0b01100,
|
||||||
|
0b00010,
|
||||||
|
0b00010,
|
||||||
|
0b11100,
|
||||||
|
0b00000 ],
|
||||||
|
|
||||||
|
// Character 4
|
||||||
|
[ 0b00010,
|
||||||
|
0b00110,
|
||||||
|
0b01010,
|
||||||
|
0b10010,
|
||||||
|
0b11110,
|
||||||
|
0b00010,
|
||||||
|
0b00010,
|
||||||
|
0b00000 ],
|
||||||
|
|
||||||
|
// Character 5
|
||||||
|
[ 0b11110,
|
||||||
|
0b10000,
|
||||||
|
0b10000,
|
||||||
|
0b11110,
|
||||||
|
0b00010,
|
||||||
|
0b00010,
|
||||||
|
0b11100,
|
||||||
|
0b00000 ],
|
||||||
|
|
||||||
|
// Character 6
|
||||||
|
[ 0b01100,
|
||||||
|
0b10010,
|
||||||
|
0b10000,
|
||||||
|
0b11110,
|
||||||
|
0b10010,
|
||||||
|
0b10010,
|
||||||
|
0b01100,
|
||||||
|
0b00000 ],
|
||||||
|
|
||||||
|
// Character 7
|
||||||
|
[ 0b11110,
|
||||||
|
0b00010,
|
||||||
|
0b00100,
|
||||||
|
0b01000,
|
||||||
|
0b01000,
|
||||||
|
0b01000,
|
||||||
|
0b01000,
|
||||||
|
0b00000 ],
|
||||||
|
|
||||||
|
// Character 8
|
||||||
|
[ 0b01100,
|
||||||
|
0b10010,
|
||||||
|
0b10010,
|
||||||
|
0b01100,
|
||||||
|
0b10010,
|
||||||
|
0b10010,
|
||||||
|
0b01100,
|
||||||
|
0b00000 ],
|
||||||
|
|
||||||
|
// Character 9
|
||||||
|
[ 0b01100,
|
||||||
|
0b10010,
|
||||||
|
0b10010,
|
||||||
|
0b01110,
|
||||||
|
0b00010,
|
||||||
|
0b00010,
|
||||||
|
0b01100,
|
||||||
|
0b00000 ],
|
||||||
|
|
||||||
|
// Character :
|
||||||
|
[ 0b00000,
|
||||||
|
0b00000,
|
||||||
|
0b01100,
|
||||||
|
0b01100,
|
||||||
|
0b00000,
|
||||||
|
0b01100,
|
||||||
|
0b01100,
|
||||||
|
0b00000 ],
|
||||||
|
|
||||||
|
// Character ;
|
||||||
|
[ 0b00000,
|
||||||
|
0b00000,
|
||||||
|
0b01100,
|
||||||
|
0b01100,
|
||||||
|
0b00000,
|
||||||
|
0b00100,
|
||||||
|
0b00100,
|
||||||
|
0b00000 ],
|
||||||
|
|
||||||
|
// Character <
|
||||||
|
[ 0b00010,
|
||||||
|
0b00100,
|
||||||
|
0b01000,
|
||||||
|
0b10000,
|
||||||
|
0b01000,
|
||||||
|
0b00100,
|
||||||
|
0b00010,
|
||||||
|
0b00000 ],
|
||||||
|
|
||||||
|
// Character =
|
||||||
|
[ 0b00000,
|
||||||
|
0b00000,
|
||||||
|
0b11110,
|
||||||
|
0b00000,
|
||||||
|
0b11110,
|
||||||
|
0b00000,
|
||||||
|
0b00000,
|
||||||
|
0b00000 ],
|
||||||
|
|
||||||
|
// Character >
|
||||||
|
[ 0b10000,
|
||||||
|
0b01000,
|
||||||
|
0b00100,
|
||||||
|
0b00010,
|
||||||
|
0b00100,
|
||||||
|
0b01000,
|
||||||
|
0b10000,
|
||||||
|
0b00000 ],
|
||||||
|
|
||||||
|
// Character ?
|
||||||
|
[ 0b01100,
|
||||||
|
0b10010,
|
||||||
|
0b00010,
|
||||||
|
0b00100,
|
||||||
|
0b01000,
|
||||||
|
0b00000,
|
||||||
|
0b01000,
|
||||||
|
0b00000 ],
|
||||||
|
|
||||||
|
// Character @
|
||||||
|
[ 0b01100,
|
||||||
|
0b10010,
|
||||||
|
0b10010,
|
||||||
|
0b10110,
|
||||||
|
0b11110,
|
||||||
|
0b11110,
|
||||||
|
0b01100,
|
||||||
|
0b00000 ],
|
||||||
|
|
||||||
|
|
||||||
|
// Letter A
|
||||||
|
[ 0b01100,
|
||||||
|
0b10010,
|
||||||
|
0b10010,
|
||||||
|
0b11110,
|
||||||
|
0b10010,
|
||||||
|
0b10010,
|
||||||
|
0b10010,
|
||||||
|
0b00000 ],
|
||||||
|
|
||||||
|
// Letter B
|
||||||
|
[ 0b11100,
|
||||||
|
0b10010,
|
||||||
|
0b10010,
|
||||||
|
0b11100,
|
||||||
|
0b10010,
|
||||||
|
0b10010,
|
||||||
|
0b11100,
|
||||||
|
0b00000 ],
|
||||||
|
|
||||||
|
// Letter C
|
||||||
|
[ 0b01100,
|
||||||
|
0b10010,
|
||||||
|
0b10000,
|
||||||
|
0b10000,
|
||||||
|
0b10000,
|
||||||
|
0b10010,
|
||||||
|
0b01100,
|
||||||
|
0b00000 ],
|
||||||
|
|
||||||
|
// Letter D
|
||||||
|
[ 0b11100,
|
||||||
|
0b10010,
|
||||||
|
0b10010,
|
||||||
|
0b10010,
|
||||||
|
0b10010,
|
||||||
|
0b10010,
|
||||||
|
0b11100,
|
||||||
|
0b00000 ],
|
||||||
|
|
||||||
|
// Letter E
|
||||||
|
[ 0b11110,
|
||||||
|
0b10000,
|
||||||
|
0b10000,
|
||||||
|
0b11110,
|
||||||
|
0b10000,
|
||||||
|
0b10000,
|
||||||
|
0b11110,
|
||||||
|
0b00000 ],
|
||||||
|
|
||||||
|
// Letter F
|
||||||
|
[ 0b11110,
|
||||||
|
0b10000,
|
||||||
|
0b10000,
|
||||||
|
0b11110,
|
||||||
|
0b10000,
|
||||||
|
0b10000,
|
||||||
|
0b10000,
|
||||||
|
0b00000 ],
|
||||||
|
|
||||||
|
// Letter G
|
||||||
|
[ 0b01100,
|
||||||
|
0b10010,
|
||||||
|
0b10000,
|
||||||
|
0b10110,
|
||||||
|
0b10010,
|
||||||
|
0b10010,
|
||||||
|
0b01110,
|
||||||
|
0b00000 ],
|
||||||
|
|
||||||
|
// Letter H
|
||||||
|
[ 0b10010,
|
||||||
|
0b10010,
|
||||||
|
0b10010,
|
||||||
|
0b11110,
|
||||||
|
0b10010,
|
||||||
|
0b10010,
|
||||||
|
0b10010,
|
||||||
|
0b00000 ],
|
||||||
|
|
||||||
|
// Letter I
|
||||||
|
[ 0b00100,
|
||||||
|
0b00100,
|
||||||
|
0b00100,
|
||||||
|
0b00100,
|
||||||
|
0b00100,
|
||||||
|
0b00100,
|
||||||
|
0b00100,
|
||||||
|
0b00000 ],
|
||||||
|
|
||||||
|
// Letter J
|
||||||
|
[ 0b00010,
|
||||||
|
0b00010,
|
||||||
|
0b00010,
|
||||||
|
0b00010,
|
||||||
|
0b00010,
|
||||||
|
0b10010,
|
||||||
|
0b01100,
|
||||||
|
0b00000 ],
|
||||||
|
|
||||||
|
// Letter K
|
||||||
|
[ 0b10010,
|
||||||
|
0b10010,
|
||||||
|
0b10100,
|
||||||
|
0b11000,
|
||||||
|
0b10100,
|
||||||
|
0b10010,
|
||||||
|
0b10010,
|
||||||
|
0b00000 ],
|
||||||
|
|
||||||
|
// Letter L
|
||||||
|
[ 0b10000,
|
||||||
|
0b10000,
|
||||||
|
0b10000,
|
||||||
|
0b10000,
|
||||||
|
0b10000,
|
||||||
|
0b10000,
|
||||||
|
0b11110,
|
||||||
|
0b00000 ],
|
||||||
|
|
||||||
|
// Letter M
|
||||||
|
[ 0b00000,
|
||||||
|
0b10001,
|
||||||
|
0b11011,
|
||||||
|
0b10101,
|
||||||
|
0b10001,
|
||||||
|
0b10001,
|
||||||
|
0b10001,
|
||||||
|
0b00000 ],
|
||||||
|
|
||||||
|
// Letter N
|
||||||
|
[ 0b00000,
|
||||||
|
0b10010,
|
||||||
|
0b11010,
|
||||||
|
0b10110,
|
||||||
|
0b10010,
|
||||||
|
0b10010,
|
||||||
|
0b10010,
|
||||||
|
0b00000 ],
|
||||||
|
|
||||||
|
// Letter O
|
||||||
|
[ 0b01100,
|
||||||
|
0b10010,
|
||||||
|
0b10010,
|
||||||
|
0b10010,
|
||||||
|
0b10010,
|
||||||
|
0b10010,
|
||||||
|
0b01100,
|
||||||
|
0b00000 ],
|
||||||
|
|
||||||
|
// Letter P
|
||||||
|
[ 0b11100,
|
||||||
|
0b10010,
|
||||||
|
0b10010,
|
||||||
|
0b11100,
|
||||||
|
0b10000,
|
||||||
|
0b10000,
|
||||||
|
0b10000,
|
||||||
|
0b00000 ],
|
||||||
|
|
||||||
|
// Letter Q
|
||||||
|
[ 0b01100,
|
||||||
|
0b10010,
|
||||||
|
0b10010,
|
||||||
|
0b10010,
|
||||||
|
0b10010,
|
||||||
|
0b10110,
|
||||||
|
0b01110,
|
||||||
|
0b00000 ],
|
||||||
|
|
||||||
|
// Letter R
|
||||||
|
[ 0b11100,
|
||||||
|
0b10010,
|
||||||
|
0b10010,
|
||||||
|
0b11100,
|
||||||
|
0b10010,
|
||||||
|
0b10010,
|
||||||
|
0b10010,
|
||||||
|
0b00000 ],
|
||||||
|
|
||||||
|
// Letter S
|
||||||
|
[ 0b01110,
|
||||||
|
0b10000,
|
||||||
|
0b10000,
|
||||||
|
0b01100,
|
||||||
|
0b00010,
|
||||||
|
0b00010,
|
||||||
|
0b11100,
|
||||||
|
0b00000 ],
|
||||||
|
|
||||||
|
// Letter T
|
||||||
|
[ 0b11111,
|
||||||
|
0b00100,
|
||||||
|
0b00100,
|
||||||
|
0b00100,
|
||||||
|
0b00100,
|
||||||
|
0b00100,
|
||||||
|
0b00100,
|
||||||
|
0b00000 ],
|
||||||
|
|
||||||
|
// Letter U
|
||||||
|
[ 0b10010,
|
||||||
|
0b10010,
|
||||||
|
0b10010,
|
||||||
|
0b10010,
|
||||||
|
0b10010,
|
||||||
|
0b10010,
|
||||||
|
0b01100,
|
||||||
|
0b00000 ],
|
||||||
|
|
||||||
|
// Letter V
|
||||||
|
[ 0b10001,
|
||||||
|
0b10001,
|
||||||
|
0b10001,
|
||||||
|
0b10001,
|
||||||
|
0b10001,
|
||||||
|
0b01010,
|
||||||
|
0b00100,
|
||||||
|
0b00000 ],
|
||||||
|
|
||||||
|
// Letter W
|
||||||
|
[ 0b10001,
|
||||||
|
0b10001,
|
||||||
|
0b10001,
|
||||||
|
0b10001,
|
||||||
|
0b10101,
|
||||||
|
0b10101,
|
||||||
|
0b01010,
|
||||||
|
0b00000 ],
|
||||||
|
|
||||||
|
// Letter X
|
||||||
|
[ 0b00000,
|
||||||
|
0b10001,
|
||||||
|
0b01010,
|
||||||
|
0b00100,
|
||||||
|
0b00100,
|
||||||
|
0b01010,
|
||||||
|
0b10001,
|
||||||
|
0b00000 ],
|
||||||
|
|
||||||
|
// Letter Y
|
||||||
|
[ 0b10001,
|
||||||
|
0b10001,
|
||||||
|
0b10001,
|
||||||
|
0b01010,
|
||||||
|
0b00100,
|
||||||
|
0b00100,
|
||||||
|
0b00100,
|
||||||
|
0b00000 ],
|
||||||
|
|
||||||
|
// Letter Z
|
||||||
|
[ 0b11110,
|
||||||
|
0b00010,
|
||||||
|
0b00100,
|
||||||
|
0b01000,
|
||||||
|
0b10000,
|
||||||
|
0b10000,
|
||||||
|
0b11110,
|
||||||
|
0b00000 ],
|
||||||
|
|
||||||
|
|
||||||
|
//////// LEFT TO DO ///////
|
||||||
|
|
||||||
|
// Blank
|
||||||
|
[ 0b00000,
|
||||||
|
0b00000,
|
||||||
|
0b00000,
|
||||||
|
0b00000,
|
||||||
|
0b00000,
|
||||||
|
0b00000,
|
||||||
|
0b00000,
|
||||||
|
0b00000 ],
|
||||||
|
|
||||||
|
// Blank
|
||||||
|
[ 0b00000,
|
||||||
|
0b00000,
|
||||||
|
0b00000,
|
||||||
|
0b00000,
|
||||||
|
0b00000,
|
||||||
|
0b00000,
|
||||||
|
0b00000,
|
||||||
|
0b00000 ],
|
||||||
|
|
||||||
|
// Blank
|
||||||
|
[ 0b00000,
|
||||||
|
0b00000,
|
||||||
|
0b00000,
|
||||||
|
0b00000,
|
||||||
|
0b00000,
|
||||||
|
0b00000,
|
||||||
|
0b00000,
|
||||||
|
0b00000 ],
|
||||||
|
|
||||||
|
// Blank
|
||||||
|
[ 0b00000,
|
||||||
|
0b00000,
|
||||||
|
0b00000,
|
||||||
|
0b00000,
|
||||||
|
0b00000,
|
||||||
|
0b00000,
|
||||||
|
0b00000,
|
||||||
|
0b00000 ],
|
||||||
|
|
||||||
|
// Blank
|
||||||
|
[ 0b00000,
|
||||||
|
0b00000,
|
||||||
|
0b00000,
|
||||||
|
0b00000,
|
||||||
|
0b00000,
|
||||||
|
0b00000,
|
||||||
|
0b00000,
|
||||||
|
0b00000 ],
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
pub struct CharacterGenerator {
|
||||||
|
pub row: i8,
|
||||||
|
pub col: i8,
|
||||||
|
pub data: &'static [u8; 8],
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CharacterGenerator {
|
||||||
|
pub fn new(ch: u8) -> Self {
|
||||||
|
Self {
|
||||||
|
row: 0,
|
||||||
|
col: 4,
|
||||||
|
data: &CHARACTERS[ch as usize],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Iterator for CharacterGenerator {
|
||||||
|
type Item = u32;
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
if self.row >= 8 {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
let bit = (self.data[self.row as usize] & (1 << self.col)) != 0;
|
||||||
|
|
||||||
|
self.col -= 1;
|
||||||
|
if self.col < 0 {
|
||||||
|
self.col = 4;
|
||||||
|
self.row += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if bit {
|
||||||
|
Some(0xC0C0C0)
|
||||||
|
} else {
|
||||||
|
Some(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,54 @@
|
||||||
|
|
||||||
|
use crate::host::keys::Key;
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn set_bit(data: &mut [u8; 8], index: usize, bit: u8, state: bool) {
|
||||||
|
let mask = 1 << bit;
|
||||||
|
data[index] = (data[index] & !mask) | (if state { mask } else { 0 });
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn record_key_press(data: &mut [u8; 8], key: Key, state: bool) {
|
||||||
|
match key {
|
||||||
|
Key::A => set_bit(data, 0, 1, state),
|
||||||
|
Key::B => set_bit(data, 0, 2, state),
|
||||||
|
Key::C => set_bit(data, 0, 3, state),
|
||||||
|
Key::D => set_bit(data, 0, 4, state),
|
||||||
|
Key::E => set_bit(data, 0, 5, state),
|
||||||
|
Key::F => set_bit(data, 0, 6, state),
|
||||||
|
Key::G => set_bit(data, 0, 7, state),
|
||||||
|
Key::H => set_bit(data, 1, 0, state),
|
||||||
|
Key::I => set_bit(data, 1, 1, state),
|
||||||
|
Key::J => set_bit(data, 1, 2, state),
|
||||||
|
Key::K => set_bit(data, 1, 3, state),
|
||||||
|
Key::L => set_bit(data, 1, 4, state),
|
||||||
|
Key::M => set_bit(data, 1, 5, state),
|
||||||
|
Key::N => set_bit(data, 1, 6, state),
|
||||||
|
Key::O => set_bit(data, 1, 7, state),
|
||||||
|
Key::P => set_bit(data, 2, 0, state),
|
||||||
|
Key::Q => set_bit(data, 2, 1, state),
|
||||||
|
Key::R => set_bit(data, 2, 2, state),
|
||||||
|
Key::S => set_bit(data, 2, 3, state),
|
||||||
|
Key::T => set_bit(data, 2, 4, state),
|
||||||
|
Key::U => set_bit(data, 2, 5, state),
|
||||||
|
Key::V => set_bit(data, 2, 6, state),
|
||||||
|
Key::W => set_bit(data, 2, 7, state),
|
||||||
|
Key::X => set_bit(data, 3, 0, state),
|
||||||
|
Key::Y => set_bit(data, 3, 1, state),
|
||||||
|
Key::Z => set_bit(data, 3, 2, state),
|
||||||
|
Key::Num0 => set_bit(data, 4, 0, state),
|
||||||
|
Key::Num1 => set_bit(data, 4, 1, state),
|
||||||
|
Key::Num2 => set_bit(data, 4, 2, state),
|
||||||
|
Key::Num3 => set_bit(data, 4, 3, state),
|
||||||
|
Key::Num4 => set_bit(data, 4, 4, state),
|
||||||
|
Key::Num5 => set_bit(data, 4, 5, state),
|
||||||
|
Key::Num6 => set_bit(data, 4, 6, state),
|
||||||
|
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::LeftShift | Key::RightShift => set_bit(data, 7, 0, state),
|
||||||
|
_ => { },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
|
||||||
|
pub mod model1;
|
||||||
|
pub mod keymap;
|
||||||
|
pub mod charset;
|
||||||
|
|
|
@ -0,0 +1,116 @@
|
||||||
|
|
||||||
|
use std::slice::Iter;
|
||||||
|
use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
|
use crate::error::Error;
|
||||||
|
use crate::system::System;
|
||||||
|
use crate::devices::{ClockElapsed, Address, Addressable, Steppable, Transmutable};
|
||||||
|
|
||||||
|
use crate::host::keys::Key;
|
||||||
|
use crate::host::gfx::{Frame, FrameSwapper};
|
||||||
|
use crate::host::traits::{Host, BlitableSurface, KeyboardUpdater};
|
||||||
|
|
||||||
|
use super::keymap;
|
||||||
|
use super::charset::CharacterGenerator;
|
||||||
|
|
||||||
|
|
||||||
|
const DEV_NAME: &'static str = "model1";
|
||||||
|
|
||||||
|
pub struct Model1Peripherals {
|
||||||
|
pub swapper: Arc<Mutex<FrameSwapper>>,
|
||||||
|
pub keyboard_mem: Arc<Mutex<[u8; 8]>>,
|
||||||
|
pub video_mem: [u8; 1024],
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Model1Peripherals {
|
||||||
|
pub fn create<H: Host>(host: &mut H) -> Result<Self, Error> {
|
||||||
|
let swapper = FrameSwapper::new_shared(320, 128);
|
||||||
|
let keyboard_mem = Arc::new(Mutex::new([0; 8]));
|
||||||
|
|
||||||
|
host.add_window(FrameSwapper::to_boxed(swapper.clone()))?;
|
||||||
|
host.register_keyboard(Box::new(Model1KeyboardUpdater(keyboard_mem.clone())))?;
|
||||||
|
|
||||||
|
Ok(Self {
|
||||||
|
swapper,
|
||||||
|
keyboard_mem,
|
||||||
|
video_mem: [0; 1024],
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Model1KeyboardUpdater(Arc<Mutex<[u8; 8]>>);
|
||||||
|
|
||||||
|
impl KeyboardUpdater for Model1KeyboardUpdater {
|
||||||
|
fn update_keyboard(&mut self, key: Key, state: bool) {
|
||||||
|
println!(">>> {:?}", key);
|
||||||
|
keymap::record_key_press(&mut self.0.lock().unwrap(), key, state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Steppable for Model1Peripherals {
|
||||||
|
fn step(&mut self, system: &System) -> Result<ClockElapsed, Error> {
|
||||||
|
let mut swapper = self.swapper.lock().unwrap();
|
||||||
|
swapper.current.clear(0);
|
||||||
|
for y in 0..16 {
|
||||||
|
for x in 0..64 {
|
||||||
|
//let iter = self.get_char_generator(self.video_mem[x + (y * 64)]);
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(16_630_000)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Addressable for Model1Peripherals {
|
||||||
|
fn len(&self) -> usize {
|
||||||
|
0x820
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read(&mut self, addr: Address, data: &mut [u8]) -> Result<(), Error> {
|
||||||
|
if addr >= 0x20 && addr <= 0xA0 {
|
||||||
|
let offset = addr - 0x20;
|
||||||
|
data[0] = 0;
|
||||||
|
if (offset & 0x01) != 0 { data[0] |= self.keyboard_mem.lock().unwrap()[0]; }
|
||||||
|
if (offset & 0x02) != 0 { data[0] |= self.keyboard_mem.lock().unwrap()[1]; }
|
||||||
|
if (offset & 0x04) != 0 { data[0] |= self.keyboard_mem.lock().unwrap()[2]; }
|
||||||
|
if (offset & 0x08) != 0 { data[0] |= self.keyboard_mem.lock().unwrap()[3]; }
|
||||||
|
if (offset & 0x10) != 0 { data[0] |= self.keyboard_mem.lock().unwrap()[4]; }
|
||||||
|
if (offset & 0x20) != 0 { data[0] |= self.keyboard_mem.lock().unwrap()[5]; }
|
||||||
|
if (offset & 0x40) != 0 { data[0] |= self.keyboard_mem.lock().unwrap()[6]; }
|
||||||
|
if (offset & 0x80) != 0 { data[0] |= self.keyboard_mem.lock().unwrap()[7]; }
|
||||||
|
//info!("{}: read from keyboard {:x} of {:?}", DEV_NAME, addr, data);
|
||||||
|
} else if addr >= 0x420 && addr <= 0x820 {
|
||||||
|
data[0] = self.video_mem[addr as usize - 0x420];
|
||||||
|
} else {
|
||||||
|
warning!("{}: !!! unhandled read from {:0x}", DEV_NAME, addr);
|
||||||
|
}
|
||||||
|
debug!("{}: read from register {:x} of {:?}", DEV_NAME, addr, data);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write(&mut self, addr: Address, data: &[u8]) -> Result<(), Error> {
|
||||||
|
info!("{}: 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 {
|
||||||
|
warning!("{}: !!! unhandled write {:0x} to {:0x}", DEV_NAME, data[0], addr);
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Transmutable for Model1Peripherals {
|
||||||
|
fn as_addressable(&mut self) -> Option<&mut dyn Addressable> {
|
||||||
|
Some(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn as_steppable(&mut self) -> Option<&mut dyn Steppable> {
|
||||||
|
Some(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue