1
2use std::io::{Write, stdin, stdout};
7use std::sync::mpsc;
8use std::sync::mpsc::Receiver;
9use std::sync::mpsc::TryRecvError;
10use std::thread;
11use std::time::Duration;
12
13use iz80::Cpu;
14use iz80::Machine;
15use iz80::TimedRunner;
16
17static TINY_BASIC: &[u8] = include_bytes!("rom/tinybasic2dms.bin");
18const MHZ: f64 = 4.0;
19
20fn main() {
21 let mut machine = VilleMachine::new();
22 let mut cpu = Cpu::new();
23 let mut timed_runner = TimedRunner::default();
24 timed_runner.set_mhz(&cpu, MHZ, 1000);
25
26 let mut stdout = stdout();
28 let stdin_channel = spawn_stdin_channel();
29 let mut in_char_waiting = false;
30
31 let code = TINY_BASIC;
33 for (i, e) in code.iter().enumerate() {
34 machine.poke(i as u16, *e);
35 }
36
37 cpu.registers().set_pc(0x0000);
39 machine.in_values[3] = 1; loop {
42 timed_runner.execute(&mut cpu, &mut machine);
43
44 if let Some(port) = machine.out_port {
45 match port {
46 2 => {
47 print!("{}", machine.out_value as char);
48 stdout.flush().unwrap();
49 },
50 3 => {},
51 _ => panic!("BDOS command not implemented")
52 }
53 machine.out_port = None;
54 }
55
56 if let Some(port) = machine.in_port {
57 match port {
58 2 => {
59 in_char_waiting = false;
60 },
61 3 => {},
62 _ => panic!("BDOS command not implemented")
63 }
64 machine.in_port = None;
65
66 if MHZ == 0.0 {
68 thread::sleep(Duration::from_millis(1));
69 }
70 }
71
72 if !in_char_waiting {
73 match stdin_channel.try_recv() {
75 Ok(key) => {
76 machine.in_values[2] = key;
77 in_char_waiting = true;
78 machine.in_values[3] = 3; },
80 Err(TryRecvError::Empty) => {
81 machine.in_values[3] = 1; },
83 Err(TryRecvError::Disconnected) => {},
84 }
85 }
86 }
87}
88
89fn spawn_stdin_channel() -> Receiver<u8> {
90 let (tx, rx) = mpsc::channel::<u8>();
91 thread::spawn(move || loop {
92 let mut buffer = String::new();
93 stdin().read_line(&mut buffer).unwrap();
94 for mut c in buffer.bytes() {
95 if c == 10 {c = 13};
96 tx.send(c).unwrap();
97 }
98 });
99 rx
100}
101
102struct VilleMachine {
103 mem: [u8; 65536],
104 in_values: [u8; 256],
105 in_port: Option<u8>,
106 out_port: Option<u8>,
107 out_value: u8
108}
109
110impl VilleMachine {
111 pub fn new() -> VilleMachine {
112 VilleMachine {
113 mem: [0; 65536],
114 in_values: [0; 256],
115 out_port: None,
116 out_value: 0,
117 in_port: None
118 }
119 }
120}
121
122impl Machine for VilleMachine {
123 fn peek(&self, address: u16) -> u8 {
124 self.mem[address as usize]
125 }
126
127 fn poke(&mut self, address: u16, value: u8) {
128 self.mem[address as usize] = value;
129 }
130
131 fn port_in(&mut self, address: u16) -> u8 {
132 let value = self.in_values[address as u8 as usize];
133 if value != 1 {
134 }
136 self.in_port = Some(address as u8);
137 value
138 }
139
140 fn port_out(&mut self, address: u16, value: u8) {
141 self.out_port = Some(address as u8);
143 self.out_value = value;
144 }
145}
146
147