the only thing broken is interrupts lol

This commit is contained in:
2024-07-04 22:01:27 -04:00
parent fb4fae430b
commit 7f8e00af23
8 changed files with 684 additions and 476 deletions
+13 -4
View File
@@ -1,6 +1,8 @@
use crate::instructions::{get_instruction, Instruction};
use crate::memory::{MemHandle, MemoryReader, MemoryWriter};
use std::fmt::Display;
use std::io::{self, Write};
use std::process::exit;
use std::sync::mpsc::{channel, Receiver, Sender};
use std::thread::sleep;
use std::time::Duration;
@@ -19,6 +21,7 @@ pub enum StatusFlag {
Carry = 0b0000_0001,
}
#[derive(Clone)]
pub struct CpuController(Sender<CpuControl>);
pub enum CpuControl {
@@ -27,6 +30,7 @@ pub enum CpuControl {
Stop,
Resume,
Data,
Cycle,
}
impl CpuController {
@@ -45,6 +49,9 @@ impl CpuController {
pub fn resume(&self) {
self.0.send(CpuControl::Resume);
}
pub fn cycle(&self) {
self.0.send(CpuControl::Cycle);
}
pub fn data(&self) {
self.0.send(CpuControl::Data);
}
@@ -70,8 +77,8 @@ pub struct Cpu {
pub pending_cycles: usize,
receiver: Option<CpuReceiver>,
stopped: bool,
// cycle_count: usize,
// state_tx: Sender<CpuState>,
cycle: bool, // cycle_count: usize,
// state_tx: Sender<CpuState>,
}
impl Display for Cpu {
@@ -107,8 +114,8 @@ impl Cpu {
memory,
stopped: false,
pending_cycles: 0,
// cycle_count: 0,
// state_tx,
cycle: false, // cycle_count: 0,
// state_tx,
}
}
pub fn with_receiver(mut self, receiver: CpuReceiver) -> Self {
@@ -125,6 +132,7 @@ impl Cpu {
pub fn reset(&mut self) {
let reset_vector_pointer = self.read_word(0xFFFC);
self.pc = reset_vector_pointer;
self.a = 0;
self.pending_cycles = 0;
}
pub fn read_word(&self, address: u16) -> u16 {
@@ -209,6 +217,7 @@ impl Cpu {
CpuControl::Irq => self.irq = true,
CpuControl::Stop => self.stopped = true,
CpuControl::Resume => self.stopped = false,
CpuControl::Cycle => self.cycle = true,
CpuControl::Data => {} // self
// .state_tx
// .send(CpuState {
+276 -9
View File
File diff suppressed because it is too large Load Diff
+158 -404
View File
@@ -1,10 +1,6 @@
use std::io::{self, stdin, Read};
// use minifb::{InputCallback, Key};
use termion::{
event::Key,
input::{Keys, TermRead},
};
use minifb::InputCallback;
use minifb::Key as MKey;
use termion::event::Key;
use crate::memory::{MemHandle, MemoryWriter};
@@ -12,280 +8,6 @@ pub struct Keyboard {
memory: MemHandle,
}
struct PlainKeys<R> {
iter: Keys<R>,
}
impl<R: Read> Iterator for PlainKeys<R> {
type Item = Result<char, io::Error>;
fn next(&mut self) -> Option<Self::Item> {
loop {
match self.iter.next() {
Some(Ok(key)) => match key {
Key::Ctrl(char) => return Some(Ok(char)),
Key::Alt(char) => return Some(Ok(char)),
Key::Char('A') => return Some(Ok('a')),
Key::Char('B') => return Some(Ok('b')),
Key::Char('C') => return Some(Ok('c')),
Key::Char('D') => return Some(Ok('d')),
Key::Char('E') => return Some(Ok('e')),
Key::Char('F') => return Some(Ok('f')),
Key::Char('G') => return Some(Ok('g')),
Key::Char('H') => return Some(Ok('h')),
Key::Char('I') => return Some(Ok('i')),
Key::Char('J') => return Some(Ok('j')),
Key::Char('K') => return Some(Ok('k')),
Key::Char('L') => return Some(Ok('l')),
Key::Char('M') => return Some(Ok('m')),
Key::Char('N') => return Some(Ok('n')),
Key::Char('O') => return Some(Ok('o')),
Key::Char('P') => return Some(Ok('p')),
Key::Char('Q') => return Some(Ok('q')),
Key::Char('R') => return Some(Ok('r')),
Key::Char('S') => return Some(Ok('s')),
Key::Char('T') => return Some(Ok('t')),
Key::Char('U') => return Some(Ok('u')),
Key::Char('V') => return Some(Ok('v')),
Key::Char('W') => return Some(Ok('w')),
Key::Char('X') => return Some(Ok('x')),
Key::Char('Y') => return Some(Ok('y')),
Key::Char('Z') => return Some(Ok('z')),
Key::Char('!') => return Some(Ok('1')),
Key::Char('@') => return Some(Ok('2')),
Key::Char('#') => return Some(Ok('3')),
Key::Char('$') => return Some(Ok('4')),
Key::Char('%') => return Some(Ok('5')),
Key::Char('^') => return Some(Ok('6')),
Key::Char('&') => return Some(Ok('7')),
Key::Char('*') => return Some(Ok('8')),
Key::Char('(') => return Some(Ok('9')),
Key::Char(')') => return Some(Ok('0')),
Key::Char('~') => return Some(Ok('`')),
Key::Char('_') => return Some(Ok('-')),
Key::Char('+') => return Some(Ok('=')),
Key::Char('|') => return Some(Ok('\\')),
Key::Char('}') => return Some(Ok(']')),
Key::Char('{') => return Some(Ok('[')),
Key::Char('"') => return Some(Ok('\'')),
Key::Char(':') => return Some(Ok(';')),
Key::Char('?') => return Some(Ok('/')),
Key::Char('>') => return Some(Ok('.')),
Key::Char('<') => return Some(Ok(',')),
Key::Char(char) => return Some(Ok(char)),
_ => continue,
},
Some(Err(e)) => return Some(Err(e)),
None => return None,
}
}
}
}
#[derive(Clone, Copy, Debug, Ord, Eq, PartialEq, PartialOrd)]
enum ControlKey {
Alt,
Shift,
Ctrl,
Left,
Right,
Up,
Down,
Esc,
Enter,
Home,
End,
Tab,
Backspace,
Delete,
Insert,
PageDown,
PageUp,
}
struct ControlKeys<R> {
iter: Keys<R>,
extra: Option<ControlKey>,
}
impl<R: Read> Iterator for ControlKeys<R> {
type Item = Result<ControlKey, io::Error>;
fn next(&mut self) -> Option<Self::Item> {
loop {
if let Some(key) = self.extra {
return Some(Ok(key));
}
match self.iter.next() {
Some(Ok(key)) => match key {
Key::Ctrl(char) => match char {
'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' | '!' | '@' | '#' | '$' | '%' | '^' | '&' | '*' | '(' | ')'
| '~' | '_' | '+' | '|' | '}' | '{' | '"' | ':' | '?' | '>' | '<' => {
self.extra = Some(ControlKey::Shift);
return Some(Ok(ControlKey::Ctrl));
}
_ => return Some(Ok(ControlKey::Ctrl)),
},
Key::CtrlUp => {
self.extra = Some(ControlKey::Ctrl);
return Some(Ok(ControlKey::Up));
}
Key::CtrlDown => {
self.extra = Some(ControlKey::Ctrl);
return Some(Ok(ControlKey::Down));
}
Key::CtrlRight => {
self.extra = Some(ControlKey::Ctrl);
return Some(Ok(ControlKey::Right));
}
Key::CtrlLeft => {
self.extra = Some(ControlKey::Ctrl);
return Some(Ok(ControlKey::Left));
}
Key::CtrlEnd => {
self.extra = Some(ControlKey::Ctrl);
return Some(Ok(ControlKey::End));
}
Key::CtrlHome => {
self.extra = Some(ControlKey::Ctrl);
return Some(Ok(ControlKey::Home));
}
Key::Alt(char) => match char {
'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' | '!' | '@' | '#' | '$' | '%' | '^' | '&' | '*' | '(' | ')'
| '~' | '_' | '+' | '|' | '}' | '{' | '"' | ':' | '?' | '>' | '<' => {
self.extra = Some(ControlKey::Shift);
return Some(Ok(ControlKey::Alt));
}
_ => return Some(Ok(ControlKey::Alt)),
},
Key::AltUp => {
self.extra = Some(ControlKey::Alt);
return Some(Ok(ControlKey::Up));
}
Key::AltDown => {
self.extra = Some(ControlKey::Alt);
return Some(Ok(ControlKey::Down));
}
Key::AltRight => {
self.extra = Some(ControlKey::Alt);
return Some(Ok(ControlKey::Right));
}
Key::AltLeft => {
self.extra = Some(ControlKey::Alt);
return Some(Ok(ControlKey::Left));
}
Key::Char('A')
| Key::Char('B')
| Key::Char('C')
| Key::Char('D')
| Key::Char('E')
| Key::Char('F')
| Key::Char('G')
| Key::Char('H')
| Key::Char('I')
| Key::Char('J')
| Key::Char('K')
| Key::Char('L')
| Key::Char('M')
| Key::Char('N')
| Key::Char('O')
| Key::Char('P')
| Key::Char('Q')
| Key::Char('R')
| Key::Char('S')
| Key::Char('T')
| Key::Char('U')
| Key::Char('V')
| Key::Char('W')
| Key::Char('X')
| Key::Char('Y')
| Key::Char('Z')
| Key::Char('!')
| Key::Char('@')
| Key::Char('#')
| Key::Char('$')
| Key::Char('%')
| Key::Char('^')
| Key::Char('&')
| Key::Char('*')
| Key::Char('(')
| Key::Char(')')
| Key::Char('~')
| Key::Char('_')
| Key::Char('+')
| Key::Char('|')
| Key::Char('}')
| Key::Char('{')
| Key::Char('"')
| Key::Char(':')
| Key::Char('?')
| Key::Char('>')
| Key::Char('<') => return Some(Ok(ControlKey::Shift)),
Key::ShiftUp => {
self.extra = Some(ControlKey::Shift);
return Some(Ok(ControlKey::Up));
}
Key::ShiftDown => {
self.extra = Some(ControlKey::Shift);
return Some(Ok(ControlKey::Down));
}
Key::ShiftRight => {
self.extra = Some(ControlKey::Shift);
return Some(Ok(ControlKey::Right));
}
Key::ShiftLeft => {
self.extra = Some(ControlKey::Shift);
return Some(Ok(ControlKey::Left));
}
Key::Backspace => return Some(Ok(ControlKey::Backspace)),
Key::Up => return Some(Ok(ControlKey::Up)),
Key::Down => return Some(Ok(ControlKey::Down)),
Key::Right => return Some(Ok(ControlKey::Right)),
Key::Left => return Some(Ok(ControlKey::Left)),
Key::Home => return Some(Ok(ControlKey::Home)),
Key::End => return Some(Ok(ControlKey::End)),
Key::PageUp => return Some(Ok(ControlKey::PageUp)),
Key::PageDown => return Some(Ok(ControlKey::PageDown)),
Key::Insert => return Some(Ok(ControlKey::Insert)),
Key::Delete => return Some(Ok(ControlKey::Delete)),
_ => continue,
},
Some(Err(e)) => return Some(Err(e)),
None => return None,
}
}
}
}
trait GetKeys {
fn get_plain(self) -> PlainKeys<Self>
where
Self: Sized;
fn get_modifiers(self) -> ControlKeys<Self>
where
Self: Sized;
}
impl<R: Read + TermRead> GetKeys for R {
fn get_plain(self) -> PlainKeys<Self>
where
Self: Sized,
{
PlainKeys { iter: self.keys() }
}
fn get_modifiers(self) -> ControlKeys<Self>
where
Self: Sized,
{
ControlKeys {
iter: self.keys(),
extra: None,
}
}
}
impl Keyboard {
pub fn new(memory: MemHandle) -> Self {
Self { memory }
@@ -300,8 +22,7 @@ impl Keyboard {
self.memory.write(0x4405, 0x00);
}
// pub fn read_keys(&self, key: KeyEvent) {
pub fn read_keys(&self) {
pub fn read_keys(&self, key: Key) {
let mut row0 = 0;
let mut row1 = 0;
let mut row2 = 0;
@@ -309,60 +30,100 @@ impl Keyboard {
let mut row4 = 0;
let mut row5 = 0;
let modifiers = termion::async_stdin().get_modifiers();
for m in modifiers {
match m.unwrap() {
ControlKey::Shift => row2 ^= 0b1000_0000,
ControlKey::Ctrl => row3 ^= 0b1000_0000,
ControlKey::Alt => row4 ^= 0b1000_0000,
ControlKey::Esc => row0 ^= 0b1000_0000,
ControlKey::Backspace => row0 ^= 0b0000_0001,
ControlKey::Tab => row1 ^= 0b1000_0000,
ControlKey::Enter => row1 ^= 0b0000_0001,
_ => {}
}
// these are just so the match statements are easier to read lol
macro_rules! set_shift {
($char:expr) => {
match $char {
'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' | '!' | '@' | '#' | '$' | '%' | '^' | '&' | '*' | '(' | ')' | '~'
| '_' | '+' | '|' | '}' | '{' | '"' | ':' | '?' | '>' | '<' => {
row2 ^= 0b1000_0000
}
_ => {}
}
};
}
let keys = termion::async_stdin().get_plain();
for k in keys {
match k.unwrap() {
'w' => row0 ^= 0b0100_0000,
'e' => row0 ^= 0b0010_0000,
'r' => row0 ^= 0b0001_0000,
't' => row0 ^= 0b0000_1000,
'u' => row0 ^= 0b0000_0100,
'o' => row0 ^= 0b0000_0010,
'q' => row1 ^= 0b0100_0000,
's' => row1 ^= 0b0010_0000,
'g' => row1 ^= 0b0001_0000,
'y' => row1 ^= 0b0000_1000,
'i' => row1 ^= 0b0000_0100,
'p' => row1 ^= 0b0000_0010,
'd' => row2 ^= 0b0100_0000,
'v' => row2 ^= 0b0010_0000,
'h' => row2 ^= 0b0001_0000,
'k' => row2 ^= 0b0000_1000,
'\\' => row2 ^= 0b0000_0100,
'/' => row2 ^= 0b0000_0010,
'a' => row2 ^= 0b0000_0001,
'z' => row3 ^= 0b0100_0000,
'f' => row3 ^= 0b0010_0000,
'b' => row3 ^= 0b0001_0000,
'j' => row3 ^= 0b0000_1000,
'l' => row3 ^= 0b0000_0100,
'2' => row3 ^= 0b0000_0010,
'4' => row3 ^= 0b0000_0001,
'x' => row4 ^= 0b0100_0000,
'c' => row4 ^= 0b0010_0000,
'n' => row4 ^= 0b0001_0000,
'm' => row4 ^= 0b0000_1000,
',' => row4 ^= 0b0000_0100,
'1' => row4 ^= 0b0000_0010,
'3' => row4 ^= 0b0000_0001,
' ' => row5 ^= 0b0100_0000,
_ => {}
}
macro_rules! set_plain {
($char:expr) => {
match $char {
'w' | 'W' => row0 ^= 0b0100_0000,
'e' | 'E' => row0 ^= 0b0010_0000,
'r' | 'R' => row0 ^= 0b0001_0000,
't' | 'T' => row0 ^= 0b0000_1000,
'u' | 'U' => row0 ^= 0b0000_0100,
'o' | 'O' => row0 ^= 0b0000_0010,
'q' | 'Q' => row1 ^= 0b0100_0000,
's' | 'S' => row1 ^= 0b0010_0000,
'g' | 'G' => row1 ^= 0b0001_0000,
'y' | 'Y' => row1 ^= 0b0000_1000,
'i' | 'I' => row1 ^= 0b0000_0100,
'p' | 'P' => row1 ^= 0b0000_0010,
'd' | 'D' => row2 ^= 0b0100_0000,
'v' | 'V' => row2 ^= 0b0010_0000,
'h' | 'H' => row2 ^= 0b0001_0000,
'k' | 'K' => row2 ^= 0b0000_1000,
'\\' | '|' => row2 ^= 0b0000_0100,
'/' | '?' => row2 ^= 0b0000_0010,
'a' | 'A' => row2 ^= 0b0000_0001,
'z' | 'Z' => row3 ^= 0b0100_0000,
'f' | 'F' => row3 ^= 0b0010_0000,
'b' | 'B' => row3 ^= 0b0001_0000,
'j' | 'J' => row3 ^= 0b0000_1000,
'l' | 'L' => row3 ^= 0b0000_0100,
'2' | '@' => row3 ^= 0b0000_0010,
'4' | '$' => row3 ^= 0b0000_0001,
'x' | 'X' => row4 ^= 0b0100_0000,
'c' | 'C' => row4 ^= 0b0010_0000,
'n' | 'N' => row4 ^= 0b0001_0000,
'm' | 'M' => row4 ^= 0b0000_1000,
',' | '<' => row4 ^= 0b0000_0100,
'1' | '!' => row4 ^= 0b0000_0010,
'3' | '#' => row4 ^= 0b0000_0001,
' ' => row5 ^= 0b0100_0000,
_ => {}
}
};
}
match key {
Key::Esc => row0 ^= 0b1000_0000,
Key::Backspace => row0 ^= 0b0000_0001,
Key::Char('\t') => row1 ^= 0b1000_0000,
Key::Char('\n') | Key::Char('\r') => row1 ^= 0b0000_0001,
Key::Char(char) => {
set_shift!(char);
set_plain!(char);
}
Key::ShiftLeft | Key::ShiftUp | Key::ShiftDown | Key::ShiftRight => row2 ^= 0b1000_0000,
Key::Ctrl(char) => {
set_shift!(char);
set_plain!(char);
row3 ^= 0b1000_0000;
}
Key::CtrlUp | Key::CtrlLeft | Key::CtrlDown | Key::CtrlRight => {
row3 ^= 0b1000_0000;
}
Key::Alt(char) => {
set_plain!(char);
set_shift!(char);
row4 ^= 0b1000_0000;
}
Key::AltUp | Key::AltLeft | Key::AltDown | Key::AltRight => {
row4 ^= 0b1000_0000;
}
_ => {}
}
self.memory.write(0x4400, row0);
self.memory.write(0x4401, row1);
self.memory.write(0x4402, row2);
self.memory.write(0x4403, row3);
self.memory.write(0x4404, row4);
self.memory.write(0x4405, row5);
// keeping this list around to make future changes easier
// match key.code {
// KeyCode::Esc => row0 ^= 0b1000_0000,
// KeyCode::Char('w') => row0 ^= 0b0100_0000,
@@ -411,13 +172,6 @@ impl Keyboard {
// row5 = 0;
// }
// };
self.memory.write(0x4400, row0);
self.memory.write(0x4401, row1);
self.memory.write(0x4402, row2);
self.memory.write(0x4403, row3);
self.memory.write(0x4404, row4);
self.memory.write(0x4405, row5);
}
}
@@ -430,68 +184,68 @@ impl MemoryWriter for Keyboard {
}
}
// impl InputCallback for Keyboard {
// fn add_char(&mut self, _uni_char: u32) {}
// fn set_key_state(&mut self, key: Key, _state: bool) {
// let mut row0 = 0;
// let mut row1 = 0;
// let mut row2 = 0;
// let mut row3 = 0;
// let mut row4 = 0;
// let mut row5 = 0;
impl InputCallback for Keyboard {
fn add_char(&mut self, _uni_char: u32) {}
fn set_key_state(&mut self, key: MKey, _state: bool) {
let mut row0 = 0;
let mut row1 = 0;
let mut row2 = 0;
let mut row3 = 0;
let mut row4 = 0;
let mut row5 = 0;
// match key {
// Key::Escape => row0 ^= 0b1000_0000,
// Key::W => row0 ^= 0b0100_0000,
// Key::E => row0 ^= 0b0010_0000,
// Key::R => row0 ^= 0b0001_0000,
// Key::T => row0 ^= 0b0000_1000,
// Key::U => row0 ^= 0b0000_0100,
// Key::O => row0 ^= 0b0000_0010,
// Key::Backspace => row0 ^= 0b0000_0001,
// Key::Tab => row1 ^= 0b1000_0000,
// Key::Q => row1 ^= 0b0100_0000,
// Key::S => row1 ^= 0b0010_0000,
// Key::G => row1 ^= 0b0001_0000,
// Key::Y => row1 ^= 0b0000_1000,
// Key::I => row1 ^= 0b0000_0100,
// Key::P => row1 ^= 0b0000_0010,
// Key::Enter => row1 ^= 0b0000_0001,
// Key::LeftShift | Key::RightShift => row2 ^= 0b1000_0000,
// Key::D => row2 ^= 0b0100_0000,
// Key::V => row2 ^= 0b0010_0000,
// Key::H => row2 ^= 0b0001_0000,
// Key::K => row2 ^= 0b0000_1000,
// Key::Apostrophe => row2 ^= 0b0000_0100,
// Key::Slash => row2 ^= 0b0000_0010,
// Key::A => row2 ^= 0b0000_0001,
// Key::LeftCtrl | Key::RightCtrl => row3 ^= 0b1000_0000,
// Key::Z => row3 ^= 0b0100_0000,
// Key::F => row3 ^= 0b0010_0000,
// Key::B => row3 ^= 0b0001_0000,
// Key::J => row3 ^= 0b0000_1000,
// Key::L => row3 ^= 0b0000_0100,
// Key::Key2 => row3 ^= 0b0000_0010,
// Key::Key4 => row3 ^= 0b0000_0001,
// Key::LeftAlt | Key::RightAlt => row4 ^= 0b1000_0000,
// Key::X => row4 ^= 0b0100_0000,
// Key::C => row4 ^= 0b0010_0000,
// Key::N => row4 ^= 0b0001_0000,
// Key::M => row4 ^= 0b0000_1000,
// Key::Comma => row4 ^= 0b0000_0100,
// Key::Key1 => row4 ^= 0b0000_0010,
// Key::Key3 => row4 ^= 0b0000_0001,
// Key::LeftSuper => row5 ^= 0b1000_0000,
// Key::Space => row5 ^= 0b0100_0000,
// Key::RightSuper => row5 ^= 0b0010_0000,
// _ => {}
// };
match key {
MKey::Escape => row0 ^= 0b1000_0000,
MKey::W => row0 ^= 0b0100_0000,
MKey::E => row0 ^= 0b0010_0000,
MKey::R => row0 ^= 0b0001_0000,
MKey::T => row0 ^= 0b0000_1000,
MKey::U => row0 ^= 0b0000_0100,
MKey::O => row0 ^= 0b0000_0010,
MKey::Backspace => row0 ^= 0b0000_0001,
MKey::Tab => row1 ^= 0b1000_0000,
MKey::Q => row1 ^= 0b0100_0000,
MKey::S => row1 ^= 0b0010_0000,
MKey::G => row1 ^= 0b0001_0000,
MKey::Y => row1 ^= 0b0000_1000,
MKey::I => row1 ^= 0b0000_0100,
MKey::P => row1 ^= 0b0000_0010,
MKey::Enter => row1 ^= 0b0000_0001,
MKey::LeftShift | MKey::RightShift => row2 ^= 0b1000_0000,
MKey::D => row2 ^= 0b0100_0000,
MKey::V => row2 ^= 0b0010_0000,
MKey::H => row2 ^= 0b0001_0000,
MKey::K => row2 ^= 0b0000_1000,
MKey::Apostrophe => row2 ^= 0b0000_0100,
MKey::Slash => row2 ^= 0b0000_0010,
MKey::A => row2 ^= 0b0000_0001,
MKey::LeftCtrl | MKey::RightCtrl => row3 ^= 0b1000_0000,
MKey::Z => row3 ^= 0b0100_0000,
MKey::F => row3 ^= 0b0010_0000,
MKey::B => row3 ^= 0b0001_0000,
MKey::J => row3 ^= 0b0000_1000,
MKey::L => row3 ^= 0b0000_0100,
MKey::Key2 => row3 ^= 0b0000_0010,
MKey::Key4 => row3 ^= 0b0000_0001,
MKey::LeftAlt | MKey::RightAlt => row4 ^= 0b1000_0000,
MKey::X => row4 ^= 0b0100_0000,
MKey::C => row4 ^= 0b0010_0000,
MKey::N => row4 ^= 0b0001_0000,
MKey::M => row4 ^= 0b0000_1000,
MKey::Comma => row4 ^= 0b0000_0100,
MKey::Key1 => row4 ^= 0b0000_0010,
MKey::Key3 => row4 ^= 0b0000_0001,
MKey::LeftSuper => row5 ^= 0b1000_0000,
MKey::Space => row5 ^= 0b0100_0000,
MKey::RightSuper => row5 ^= 0b0010_0000,
_ => {}
};
// self.memory.write(0x4400, row0);
// self.memory.write(0x4401, row1);
// self.memory.write(0x4402, row2);
// self.memory.write(0x4403, row3);
// self.memory.write(0x4404, row4);
// self.memory.write(0x4405, row5);
// }
// }
self.memory.write(0x4400, row0);
self.memory.write(0x4401, row1);
self.memory.write(0x4402, row2);
self.memory.write(0x4403, row3);
self.memory.write(0x4404, row4);
self.memory.write(0x4405, row5);
}
}
+22 -29
View File
@@ -13,34 +13,25 @@ use crate::memory::Mem;
use crate::video::Screen;
use cli::get_input;
// use cpu::CpuController;
use crossterm::cursor;
use memory::MemHandle;
use std::io::{stdin, stdout, Result};
use std::io::{stdout, Read, Result, Write};
use std::thread::{self, sleep};
use std::time::Duration;
use termion::cursor::Goto;
use termion::event::Key;
use termion::input::TermRead;
use termion::raw::IntoRawMode;
// use termion::raw::IntoRawMode;
use std::io::Write;
use termion::{self, clear, cursor, screen};
fn main() -> Result<()> {
let mut stdout = stdout().into_raw_mode().unwrap();
// let (cols, rows) = size()?;
use termion::screen::IntoAlternateScreen;
use termion::{async_stdin, clear, screen};
fn main() {
let _stdout = stdout().into_raw_mode();
let config = get_input();
let mut memory = Mem::new();
let _ = memory.load_rom(&config.rom);
write!(stdout, "{}{}", cursor::Hide, screen::ToAlternateScreen)?;
// execute!(stdout, SetSize(64, 29), cursor::Hide, EnterAlternateScreen)?;
// enable_raw_mode()?;
let shared_memory = MemHandle::new(memory);
let screen_memory = shared_memory.clone();
let cpu_memory = shared_memory.clone();
@@ -49,30 +40,32 @@ fn main() -> Result<()> {
let keyboard = Keyboard::new(keyboard_memory);
let (mut cpu, cpu_controller) = Cpu::new_with_control(cpu_memory);
let _ = cpu.reset();
cpu.reset();
thread::spawn(move || loop {
cpu.cycle();
});
let mut screen = Screen::new(&config, cpu_controller, screen_memory);
let screen_remote = cpu_controller.clone();
loop {
keyboard.clear_keys(); // nasty hack until i can figure out a good way of clearing keyboard
// memory when no keys are pressed
let mut screen = Screen::new(&config, screen_remote, screen_memory);
let mut stdin = async_stdin().keys();
print!("{}{}", cursor::Hide, clear::All,);
'main: loop {
screen.draw();
// if event::poll(std::time::Duration::from_millis(16))? {
keyboard.read_keys();
for key in stdin().keys() {
match key.unwrap() {
if let Some(Ok(key)) = stdin.next() {
match key {
Key::Char('q') => {
write!(stdout, "{}", clear::All)?;
return Ok(());
break 'main;
}
_ => {}
// Key::Char(' ') => cpu_controller.stop(),
// Key::Char('\n') => cpu_controller.resume(),
_ => keyboard.read_keys(key),
}
}
// }
sleep(Duration::from_millis(16));
}
print!("{}{}{}", clear::All, cursor::Show, Goto(1, 1));
}
+2
View File
@@ -1,7 +1,9 @@
use anyhow::{bail, Result};
use core::panic;
use std::cell::RefCell;
use std::io::{self, Write};
use std::path::{Path, PathBuf};
use std::process::exit;
use std::rc::Rc;
use std::str::FromStr;
use std::sync::{Arc, Mutex};
+11 -17
View File
@@ -3,11 +3,13 @@ use serde::{Deserialize, Serialize};
use termion::{
color::{self, Bg, Color, Fg},
cursor::Goto,
screen::IntoAlternateScreen,
};
use crate::{
cli::Config,
cpu::CpuController,
keyboard::Keyboard,
memory::{MemHandle, MemoryReader},
types::{Byte, Word},
};
@@ -16,7 +18,8 @@ use std::{
io::{self, Read, Write},
path::Path,
process::exit,
time::Instant,
thread::sleep,
time::{Duration, Instant},
};
const FG_COLOR: u32 = 0xFFCC00;
@@ -95,11 +98,10 @@ impl Renderer for WindowRenderer {
}
}
}
self.window
.update_with_buffer(&buffer, WIDTH, HEIGHT)
.unwrap();
}
self.window
.update_with_buffer(&buffer, WIDTH, HEIGHT)
.unwrap();
}
}
@@ -109,22 +111,16 @@ impl MemoryReader for WindowRenderer {
}
}
// pub struct TerminalRenderer<'a> {
pub struct TerminalRenderer {
memory: MemHandle,
// stdout: Stdout,
// stdout: StdoutLock<'a>,
}
// impl<'a> TerminalRenderer<'a> {
impl TerminalRenderer {
// pub fn new(memory: MemHandle, stdout: StdoutLock<'a>) -> Self {
pub fn new(memory: MemHandle) -> Self {
Self { memory }
}
}
// impl MemoryReader for TerminalRenderer<'_> {
impl MemoryReader for TerminalRenderer {
fn read(&self, address: Word) -> Byte {
self.memory.read(address)
@@ -148,7 +144,6 @@ const ASCII_LOOPUP: [&str; 256] = [
"", "", "", "", "🎁", "", "", "", "", "", "", "", "", "",
];
// impl Renderer for TerminalRenderer<'_> {
impl Renderer for TerminalRenderer {
fn render(&mut self) {
let mut stdout = io::stdout();
@@ -172,10 +167,8 @@ impl Renderer for TerminalRenderer {
}
}
// pub struct Screen<'a> {
pub struct Screen {
renderer: Box<dyn Renderer>,
// renderer: TerminalRenderer<'a>,
controller: CpuController,
}
@@ -183,7 +176,7 @@ impl Screen {
pub fn new(config: &Config, controller: CpuController, memory: MemHandle) -> Self {
let renderer: Box<dyn Renderer> = match config.screen {
ScreenType::Window => {
let window = Window::new(
let mut window = Window::new(
"ʕ·ᴥ·ʔ-☆",
512,
380,
@@ -192,13 +185,14 @@ impl Screen {
borderless: true,
title: true,
transparency: false,
scale: Scale::X2,
scale: Scale::FitScreen,
scale_mode: ScaleMode::AspectRatioStretch,
topmost: false,
none: true,
},
)
.unwrap();
window.set_input_callback(Box::new(Keyboard::new(memory.clone())));
Box::new(WindowRenderer::new(memory, config.char_rom.clone(), window))
}
ScreenType::Terminal => Box::new(TerminalRenderer::new(memory)),
@@ -210,7 +204,7 @@ impl Screen {
}
}
pub fn draw(&mut self) {
self.controller.irq();
// self.controller.irq();
self.renderer.render();
}