From 7f8e00af2355524d090b4763c56f1f802f471463 Mon Sep 17 00:00:00 2001 From: august kline Date: Thu, 4 Jul 2024 22:01:27 -0400 Subject: [PATCH] the only thing broken is interrupts lol --- Cargo.lock | 214 ++++++++++++++++- Cargo.toml | 1 + src/cpu.rs | 17 +- src/instructions.rs | 285 +++++++++++++++++++++- src/keyboard.rs | 562 +++++++++++++------------------------------- src/main.rs | 51 ++-- src/memory.rs | 2 + src/video.rs | 28 +-- 8 files changed, 684 insertions(+), 476 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 264c171..b43c63d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -69,6 +69,31 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "crossterm" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f476fe445d41c9e991fd07515a6f463074b782242ccf4a5b7b1d1012e70824df" +dependencies = [ + "bitflags 2.5.0", + "crossterm_winapi", + "libc", + "mio", + "parking_lot", + "signal-hook", + "signal-hook-mio", + "winapi", +] + +[[package]] +name = "crossterm_winapi" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acdd7c62a3665c7f6830a51635d9ac9b23ed385797f70a83bb8bafe9c572ab2b" +dependencies = [ + "winapi", +] + [[package]] name = "dlib" version = "0.5.2" @@ -97,7 +122,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" dependencies = [ "libc", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] @@ -201,6 +226,7 @@ version = "0.1.0" dependencies = [ "anyhow", "bdf", + "crossterm", "minifb", "serde", "termion", @@ -263,7 +289,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e310b3a6b5907f99202fcdb4960ff45b93735d7c7d96b760fcff8db2dc0e103d" dependencies = [ "cfg-if", - "windows-targets", + "windows-targets 0.52.5", ] [[package]] @@ -274,7 +300,7 @@ checksum = "3af92c55d7d839293953fcd0fda5ecfe93297cfde6ffbdec13b41d99c0ba6607" dependencies = [ "bitflags 2.5.0", "libc", - "redox_syscall", + "redox_syscall 0.4.1", ] [[package]] @@ -283,6 +309,16 @@ version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" +[[package]] +name = "lock_api" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +dependencies = [ + "autocfg", + "scopeguard", +] + [[package]] name = "log" version = "0.4.21" @@ -330,6 +366,18 @@ dependencies = [ "x11-dl", ] +[[package]] +name = "mio" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" +dependencies = [ + "libc", + "log", + "wasi", + "windows-sys 0.48.0", +] + [[package]] name = "nix" version = "0.24.3" @@ -366,6 +414,29 @@ dependencies = [ "sdl2-sys", ] +[[package]] +name = "parking_lot" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall 0.5.2", + "smallvec", + "windows-targets 0.52.5", +] + [[package]] name = "pin-project-lite" version = "0.2.14" @@ -417,6 +488,15 @@ dependencies = [ "bitflags 1.3.2", ] +[[package]] +name = "redox_syscall" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c82cf8cff14456045f55ec4241383baeff27af886adb72ffb2162f99911de0fd" +dependencies = [ + "bitflags 2.5.0", +] + [[package]] name = "redox_termios" version = "0.1.3" @@ -433,7 +513,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] @@ -442,6 +522,12 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + [[package]] name = "sdl2" version = "0.35.2" @@ -494,6 +580,36 @@ dependencies = [ "serde", ] +[[package]] +name = "signal-hook" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8621587d4798caf8eb44879d42e56b9a93ea5dcd315a6487c357130095b62801" +dependencies = [ + "libc", + "signal-hook-registry", +] + +[[package]] +name = "signal-hook-mio" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29ad2e15f37ec9a6cc544097b78a1ec90001e9f71b81338ca39f430adaca99af" +dependencies = [ + "libc", + "mio", + "signal-hook", +] + +[[package]] +name = "signal-hook-registry" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" +dependencies = [ + "libc", +] + [[package]] name = "slab" version = "0.4.9" @@ -529,7 +645,7 @@ dependencies = [ "cfg-if", "fastrand", "rustix", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] @@ -610,6 +726,12 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "579a42fc0b8e0c63b76519a339be31bed574929511fa53c1a3acae26eb258f29" +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + [[package]] name = "wasm-bindgen" version = "0.2.92" @@ -781,13 +903,37 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", +] + [[package]] name = "windows-sys" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets", + "windows-targets 0.52.5", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", ] [[package]] @@ -796,28 +942,46 @@ version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", + "windows_aarch64_gnullvm 0.52.5", + "windows_aarch64_msvc 0.52.5", + "windows_i686_gnu 0.52.5", "windows_i686_gnullvm", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows_i686_msvc 0.52.5", + "windows_x86_64_gnu 0.52.5", + "windows_x86_64_gnullvm 0.52.5", + "windows_x86_64_msvc 0.52.5", ] +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + [[package]] name = "windows_aarch64_gnullvm" version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + [[package]] name = "windows_aarch64_msvc" version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + [[package]] name = "windows_i686_gnu" version = "0.52.5" @@ -830,24 +994,48 @@ version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + [[package]] name = "windows_i686_msvc" version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + [[package]] name = "windows_x86_64_gnu" version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + [[package]] name = "windows_x86_64_gnullvm" version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + [[package]] name = "windows_x86_64_msvc" version = "0.52.5" diff --git a/Cargo.toml b/Cargo.toml index ece112d..9690b4d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,6 +8,7 @@ edition = "2021" [dependencies] anyhow = "1.0.81" bdf = "0.6.0" +crossterm = "0.27.0" minifb = "0.27.0" # minifb = "0.25.0" # ratatui = "0.26.3" diff --git a/src/cpu.rs b/src/cpu.rs index 26f2b6a..96805da 100644 --- a/src/cpu.rs +++ b/src/cpu.rs @@ -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); 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, stopped: bool, - // cycle_count: usize, - // state_tx: Sender, + cycle: bool, // cycle_count: usize, + // state_tx: Sender, } 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 { diff --git a/src/instructions.rs b/src/instructions.rs index 30b7f6c..600b165 100644 --- a/src/instructions.rs +++ b/src/instructions.rs @@ -2,6 +2,8 @@ use core::panic; +use termion::cursor::Goto; + use crate::cpu::{Cpu, StatusFlag}; use crate::memory::{MemoryReader, MemoryWriter}; @@ -9,28 +11,37 @@ type InstrFn = fn(&mut Cpu, Option); type AddressFn = fn(&mut Cpu) -> u16; #[derive(Clone, Copy, Debug)] -pub struct Instruction { - instr_fn: Option, - address_fn: Option, - cycles: u8, +pub struct Instruction<'a> { + pub instr_fn: Option, + pub address_fn: Option, + pub cycles: u8, + pub name: &'a str, } -impl Instruction { +impl Instruction<'_> { pub fn call(&self, cpu: &mut Cpu) { cpu.pc = cpu.pc.wrapping_add(1); // read instruction byte + // println!( + // "{}instruction: {:?}, pc: {:#04x}", + // Goto(0, 31), + // self.name, + // cpu.pc + // ); match self.instr_fn { // existence of instr_fn means this is a valid instruction Some(instr_fn) => { cpu.pending_cycles += self.cycles as usize; match self.address_fn { // if we have address_fn, that means - // addressing mode isn't implied, + // addressing mode isn't implied/stack, // so we need to get an address Some(address_fn) => { let address = address_fn(cpu); instr_fn(cpu, Some(address)); } - None => instr_fn(cpu, None), // None for address_fn implies it's implied (lol) + None => { + instr_fn(cpu, None); + } // None for address_fn implies it's implied (lol)/stack } } None => { @@ -881,1289 +892,1545 @@ fn wai(cpu: &mut Cpu, _address: Option) { } // if you want to optimize this later https://llx.com/Neil/a2/opcodes.html -pub fn get_instruction(opcode: u8) -> Instruction { +pub fn get_instruction(opcode: u8) -> Instruction<'static> { OPCODES[opcode as usize] } -static OPCODES: [Instruction; 256] = [ +const OPCODES: [Instruction; 256] = [ Instruction { instr_fn: Some(brk), address_fn: None, cycles: 7, + name: "brk", }, Instruction { instr_fn: Some(ora), address_fn: Some(zero_page_indexed_indirect), cycles: 6, + name: "ora", }, Instruction { instr_fn: None, address_fn: None, cycles: 0, + name: "none", }, Instruction { instr_fn: None, address_fn: None, cycles: 0, + name: "none", }, Instruction { instr_fn: Some(tsb), address_fn: Some(zero_page), cycles: 5, + name: "tsb", }, Instruction { instr_fn: Some(ora), address_fn: Some(zero_page), cycles: 3, + name: "ora", }, Instruction { instr_fn: Some(asl), address_fn: Some(zero_page), cycles: 5, + name: "asl", }, Instruction { instr_fn: Some(rmb0), address_fn: Some(zero_page), cycles: 5, + name: "rmb0", }, Instruction { instr_fn: Some(php), address_fn: None, cycles: 3, + name: "php", }, Instruction { instr_fn: Some(ora), address_fn: Some(immediate), cycles: 2, + name: "ora", }, Instruction { instr_fn: Some(asl_a), address_fn: Some(accumulator), cycles: 2, + name: "asl_a", }, Instruction { instr_fn: None, address_fn: None, cycles: 0, + name: "none", }, Instruction { instr_fn: Some(tsb), address_fn: Some(absolute_a), cycles: 6, + name: "tsb", }, Instruction { instr_fn: Some(ora), address_fn: Some(absolute_a), cycles: 4, + name: "ora", }, Instruction { instr_fn: Some(asl), address_fn: Some(absolute_a), cycles: 6, + name: "asl", }, Instruction { instr_fn: Some(bbr0), address_fn: Some(relative_test), cycles: 4, + name: "bbr0", }, Instruction { instr_fn: Some(bpl), address_fn: Some(relative), cycles: 2, + name: "bpl", }, Instruction { instr_fn: Some(ora), address_fn: Some(absolute_indexed_with_y), cycles: 5, + name: "ora", }, Instruction { instr_fn: Some(ora), address_fn: Some(zero_page_indirect), cycles: 5, + name: "ora", }, Instruction { instr_fn: None, address_fn: None, cycles: 0, + name: "none", }, Instruction { instr_fn: Some(trb), address_fn: Some(zero_page), cycles: 5, + name: "trb", }, Instruction { instr_fn: Some(ora), address_fn: Some(zero_page_indexed_with_x), cycles: 4, + name: "ora", }, Instruction { instr_fn: Some(asl), address_fn: Some(zero_page_indexed_with_x), cycles: 6, + name: "asl", }, Instruction { instr_fn: Some(rmb1), address_fn: Some(zero_page), cycles: 5, + name: "rmb1", }, Instruction { instr_fn: Some(clc), address_fn: None, cycles: 2, + name: "clc", }, Instruction { instr_fn: Some(ora), address_fn: Some(absolute_indexed_with_y), cycles: 4, + name: "ora", }, Instruction { instr_fn: Some(inc_a), address_fn: Some(accumulator), cycles: 2, + name: "inc_a", }, Instruction { instr_fn: None, address_fn: None, cycles: 0, + name: "none", }, Instruction { instr_fn: Some(trb), address_fn: Some(absolute_a), cycles: 6, + name: "trb", }, Instruction { instr_fn: Some(ora), address_fn: Some(absolute_indexed_with_x), cycles: 4, + name: "ora", }, Instruction { instr_fn: Some(asl), address_fn: Some(absolute_indexed_with_x), cycles: 7, + name: "asl", }, Instruction { instr_fn: Some(bbr1), address_fn: Some(relative_test), cycles: 4, + name: "bbr1", }, Instruction { instr_fn: Some(jsr), address_fn: Some(absolute_a), cycles: 6, + name: "jsr", }, Instruction { instr_fn: Some(and), address_fn: Some(zero_page_indexed_indirect), cycles: 6, + name: "and", }, Instruction { instr_fn: None, address_fn: None, cycles: 0, + name: "none", }, Instruction { instr_fn: None, address_fn: None, cycles: 0, + name: "none", }, Instruction { instr_fn: Some(bit), address_fn: Some(zero_page), cycles: 3, + name: "bit", }, Instruction { instr_fn: Some(and), address_fn: Some(zero_page), cycles: 3, + name: "and", }, Instruction { instr_fn: Some(rol), address_fn: Some(zero_page), cycles: 5, + name: "rol", }, Instruction { instr_fn: Some(rmb2), address_fn: Some(zero_page), cycles: 5, + name: "rmb2", }, Instruction { instr_fn: Some(plp), address_fn: None, cycles: 4, + name: "plp", }, Instruction { instr_fn: Some(and), address_fn: Some(immediate), cycles: 2, + name: "and", }, Instruction { instr_fn: Some(rol_a), address_fn: Some(accumulator), cycles: 2, + name: "rol_a", }, Instruction { instr_fn: None, address_fn: None, cycles: 0, + name: "none", }, Instruction { instr_fn: Some(bit), address_fn: Some(absolute_a), cycles: 4, + name: "bit", }, Instruction { instr_fn: Some(and), address_fn: Some(absolute_a), cycles: 4, + name: "and", }, Instruction { instr_fn: Some(rol), address_fn: Some(absolute_a), cycles: 6, + name: "rol", }, Instruction { instr_fn: Some(bbr2), address_fn: Some(relative_test), cycles: 4, + name: "bbr2", }, Instruction { instr_fn: Some(bmi), address_fn: Some(relative), cycles: 2, + name: "bmi", }, Instruction { instr_fn: Some(and), address_fn: Some(zero_page_indirect_indexed_with_y), cycles: 5, + name: "and", }, Instruction { instr_fn: Some(and), address_fn: Some(zero_page_indirect), cycles: 5, + name: "and", }, Instruction { instr_fn: None, address_fn: None, cycles: 0, + name: "none", }, Instruction { instr_fn: Some(bit), address_fn: Some(zero_page_indexed_with_x), cycles: 3, + name: "bit", }, Instruction { instr_fn: Some(and), address_fn: Some(zero_page_indexed_with_x), cycles: 4, + name: "and", }, Instruction { instr_fn: Some(rol), address_fn: Some(zero_page_indexed_with_x), cycles: 6, + name: "rol", }, Instruction { instr_fn: Some(rmb3), address_fn: Some(zero_page), cycles: 5, + name: "rmb3", }, Instruction { instr_fn: Some(sec), address_fn: None, cycles: 2, + name: "sec", }, Instruction { instr_fn: Some(and), address_fn: Some(absolute_indexed_with_y), cycles: 4, + name: "and", }, Instruction { instr_fn: Some(dec_a), address_fn: Some(accumulator), cycles: 2, + name: "dec_a", }, Instruction { instr_fn: None, address_fn: None, cycles: 0, + name: "none", }, Instruction { instr_fn: Some(bit), address_fn: Some(absolute_indexed_with_x), cycles: 4, + name: "bit", }, Instruction { instr_fn: Some(and), address_fn: Some(absolute_indexed_with_x), cycles: 4, + name: "and", }, Instruction { instr_fn: Some(rol), address_fn: Some(absolute_indexed_with_x), cycles: 7, + name: "rol", }, Instruction { instr_fn: Some(bbr3), address_fn: Some(relative_test), cycles: 4, + name: "bbr3", }, Instruction { instr_fn: Some(rti), address_fn: None, cycles: 6, + name: "rti", }, Instruction { instr_fn: Some(eor), address_fn: Some(zero_page_indexed_indirect), cycles: 6, + name: "eor", }, Instruction { instr_fn: None, address_fn: None, cycles: 0, + name: "none", }, Instruction { instr_fn: None, address_fn: None, cycles: 0, + name: "none", }, Instruction { instr_fn: None, address_fn: None, cycles: 0, + name: "none", }, Instruction { instr_fn: Some(eor), address_fn: Some(zero_page), cycles: 3, + name: "eor", }, Instruction { instr_fn: Some(lsr), address_fn: Some(zero_page), cycles: 5, + name: "lsr", }, Instruction { instr_fn: Some(rmb4), address_fn: Some(zero_page), cycles: 5, + name: "rmb4", }, Instruction { instr_fn: Some(pha), address_fn: None, cycles: 3, + name: "pha", }, Instruction { instr_fn: Some(eor), address_fn: Some(immediate), cycles: 2, + name: "eor", }, Instruction { instr_fn: Some(lsr_a), address_fn: Some(accumulator), cycles: 2, + name: "lsr_a", }, Instruction { instr_fn: None, address_fn: None, cycles: 0, + name: "none", }, Instruction { instr_fn: Some(jmp), address_fn: Some(absolute_a), cycles: 3, + name: "jmp", }, Instruction { instr_fn: Some(eor), address_fn: Some(absolute_a), cycles: 4, + name: "eor", }, Instruction { instr_fn: Some(lsr), address_fn: Some(absolute_a), cycles: 6, + name: "lsr", }, Instruction { instr_fn: Some(bbr4), address_fn: Some(relative_test), cycles: 4, + name: "bbr4", }, Instruction { instr_fn: Some(bvc), address_fn: Some(relative), cycles: 2, + name: "bvc", }, Instruction { instr_fn: Some(eor), address_fn: Some(zero_page_indirect_indexed_with_y), cycles: 5, + name: "eor", }, Instruction { instr_fn: Some(eor), address_fn: Some(zero_page_indirect), cycles: 5, + name: "eor", }, Instruction { instr_fn: None, address_fn: None, cycles: 0, + name: "none", }, Instruction { instr_fn: None, address_fn: None, cycles: 0, + name: "none", }, Instruction { instr_fn: Some(eor), address_fn: Some(zero_page_indexed_with_x), cycles: 4, + name: "eor", }, Instruction { instr_fn: Some(lsr), address_fn: Some(zero_page_indexed_with_x), cycles: 6, + name: "lsr", }, Instruction { instr_fn: Some(rmb5), address_fn: Some(zero_page), cycles: 5, + name: "rmb5", }, Instruction { instr_fn: Some(cli), address_fn: None, cycles: 2, + name: "cli", }, Instruction { instr_fn: Some(eor), address_fn: Some(absolute_indexed_with_y), cycles: 4, + name: "eor", }, Instruction { instr_fn: Some(phy), address_fn: None, cycles: 3, + name: "phy", }, Instruction { instr_fn: None, address_fn: None, cycles: 0, + name: "none", }, Instruction { instr_fn: None, address_fn: None, cycles: 0, + name: "none", }, Instruction { instr_fn: Some(eor), address_fn: Some(absolute_indexed_with_x), cycles: 4, + name: "eor", }, Instruction { instr_fn: Some(lsr), address_fn: Some(absolute_indexed_with_x), cycles: 7, + name: "lsr", }, Instruction { instr_fn: Some(bbr5), address_fn: Some(relative_test), cycles: 4, + name: "bbr5", }, Instruction { instr_fn: Some(rts), address_fn: None, cycles: 6, + name: "rts", }, Instruction { instr_fn: Some(adc), address_fn: Some(zero_page_indexed_indirect), cycles: 6, + name: "adc", }, Instruction { instr_fn: None, address_fn: None, cycles: 0, + name: "none", }, Instruction { instr_fn: None, address_fn: None, cycles: 0, + name: "none", }, Instruction { instr_fn: Some(stz), address_fn: Some(zero_page), cycles: 3, + name: "stz", }, Instruction { instr_fn: Some(adc), address_fn: Some(zero_page), cycles: 3, + name: "adc", }, Instruction { instr_fn: Some(ror), address_fn: Some(zero_page), cycles: 5, + name: "ror", }, Instruction { instr_fn: Some(rmb6), address_fn: Some(zero_page), cycles: 5, + name: "rmb6", }, Instruction { instr_fn: Some(pla), address_fn: None, cycles: 4, + name: "pla", }, Instruction { instr_fn: Some(adc), address_fn: Some(immediate), cycles: 2, + name: "adc", }, Instruction { instr_fn: Some(ror_a), address_fn: Some(accumulator), cycles: 2, + name: "ror_a", }, Instruction { instr_fn: None, address_fn: None, cycles: 0, + name: "none", }, Instruction { instr_fn: Some(jmp), address_fn: Some(absolute_indirect), cycles: 5, + name: "jmp", }, Instruction { instr_fn: Some(adc), address_fn: Some(absolute_a), cycles: 4, + name: "adc", }, Instruction { instr_fn: Some(ror), address_fn: Some(absolute_a), cycles: 6, + name: "ror", }, Instruction { instr_fn: Some(bbr6), address_fn: Some(relative), cycles: 4, + name: "bbr6", }, Instruction { instr_fn: Some(bvs), address_fn: Some(relative), cycles: 2, + name: "bvs", }, Instruction { instr_fn: Some(adc), address_fn: Some(zero_page_indirect_indexed_with_y), cycles: 5, + name: "adc", }, Instruction { instr_fn: Some(adc), address_fn: Some(zero_page_indirect), cycles: 5, + name: "adc", }, Instruction { instr_fn: None, address_fn: None, cycles: 0, + name: "none", }, Instruction { instr_fn: Some(stz), address_fn: Some(zero_page_indexed_with_x), cycles: 4, + name: "stz", }, Instruction { instr_fn: Some(adc), address_fn: Some(zero_page_indexed_with_x), cycles: 4, + name: "adc", }, Instruction { instr_fn: Some(ror), address_fn: Some(zero_page_indexed_with_x), cycles: 6, + name: "ror", }, Instruction { instr_fn: Some(rmb7), address_fn: Some(zero_page), cycles: 5, + name: "rmb7", }, Instruction { instr_fn: Some(sei), address_fn: None, cycles: 2, + name: "sei", }, Instruction { instr_fn: Some(adc), address_fn: Some(absolute_indexed_with_y), cycles: 4, + name: "adc", }, Instruction { instr_fn: Some(ply), address_fn: None, cycles: 4, + name: "ply", }, Instruction { instr_fn: None, address_fn: None, cycles: 0, + name: "none", }, Instruction { instr_fn: Some(jmp), address_fn: Some(absolute_indexed_indirect), cycles: 6, + name: "jmp", }, Instruction { instr_fn: Some(adc), address_fn: Some(absolute_indexed_with_x), cycles: 4, + name: "adc", }, Instruction { instr_fn: Some(ror), address_fn: Some(absolute_indexed_with_x), cycles: 7, + name: "ror", }, Instruction { instr_fn: Some(bbr7), address_fn: Some(relative_test), cycles: 4, + name: "bbr7", }, Instruction { instr_fn: Some(bra), address_fn: Some(relative), cycles: 3, + name: "bra", }, Instruction { instr_fn: Some(sta), address_fn: Some(zero_page_indexed_indirect), cycles: 6, + name: "sta", }, Instruction { instr_fn: None, address_fn: None, cycles: 0, + name: "none", }, Instruction { instr_fn: None, address_fn: None, cycles: 0, + name: "none", }, Instruction { instr_fn: Some(sty), address_fn: Some(zero_page), cycles: 3, + name: "sty", }, Instruction { instr_fn: Some(sta), address_fn: Some(zero_page), cycles: 3, + name: "sta", }, Instruction { instr_fn: Some(stx), address_fn: Some(zero_page), cycles: 3, + name: "stx", }, Instruction { instr_fn: Some(smb0), address_fn: Some(zero_page), cycles: 5, + name: "smb0", }, Instruction { instr_fn: Some(dey), address_fn: None, cycles: 2, + name: "dey", }, Instruction { instr_fn: Some(bit), address_fn: Some(immediate), cycles: 3, + name: "bit", }, Instruction { instr_fn: Some(txa), address_fn: None, cycles: 2, + name: "txa", }, Instruction { instr_fn: None, address_fn: None, cycles: 0, + name: "none", }, Instruction { instr_fn: Some(sty), address_fn: Some(absolute_a), cycles: 4, + name: "sty", }, Instruction { instr_fn: Some(sta), address_fn: Some(absolute_a), cycles: 4, + name: "sta", }, Instruction { instr_fn: Some(stx), address_fn: Some(absolute_a), cycles: 4, + name: "stx", }, Instruction { instr_fn: Some(bbs0), address_fn: Some(relative_test), cycles: 4, + name: "bbs0", }, Instruction { instr_fn: Some(bcc), address_fn: Some(relative), cycles: 2, + name: "bcc", }, Instruction { instr_fn: Some(sta), address_fn: Some(zero_page_indirect_indexed_with_y), cycles: 6, + name: "sta", }, Instruction { instr_fn: Some(sta), address_fn: Some(zero_page_indirect), cycles: 5, + name: "sta", }, Instruction { instr_fn: None, address_fn: None, cycles: 0, + name: "none", }, Instruction { instr_fn: Some(sty), address_fn: Some(zero_page_indexed_with_x), cycles: 4, + name: "sty", }, Instruction { instr_fn: Some(sta), address_fn: Some(zero_page_indexed_with_x), cycles: 4, + name: "sta", }, Instruction { instr_fn: Some(stx), address_fn: Some(zero_page_indexed_with_y), cycles: 4, + name: "stx", }, Instruction { instr_fn: Some(smb1), address_fn: Some(zero_page), cycles: 5, + name: "smb1", }, Instruction { instr_fn: Some(tya), address_fn: None, cycles: 2, + name: "tya", }, Instruction { instr_fn: Some(sta), address_fn: Some(absolute_indexed_with_y), cycles: 5, + name: "sta", }, Instruction { instr_fn: Some(txs), address_fn: None, cycles: 2, + name: "txs", }, Instruction { instr_fn: None, address_fn: None, cycles: 0, + name: "none", }, Instruction { instr_fn: Some(stz), address_fn: Some(absolute_a), cycles: 4, + name: "stz", }, Instruction { instr_fn: Some(sta), address_fn: Some(absolute_indexed_with_x), cycles: 5, + name: "sta", }, Instruction { instr_fn: Some(stz), address_fn: Some(absolute_indexed_with_x), cycles: 5, + name: "stz", }, Instruction { instr_fn: Some(bbs1), address_fn: Some(relative_test), cycles: 4, + name: "bbs1", }, Instruction { instr_fn: Some(ldy), address_fn: Some(immediate), cycles: 2, + name: "ldy", }, Instruction { instr_fn: Some(lda), address_fn: Some(zero_page_indexed_indirect), cycles: 6, + name: "lda", }, Instruction { instr_fn: Some(ldx), address_fn: Some(immediate), cycles: 2, + name: "ldx", }, Instruction { instr_fn: None, address_fn: None, cycles: 0, + name: "none", }, Instruction { instr_fn: Some(ldy), address_fn: Some(zero_page), cycles: 3, + name: "ldy", }, Instruction { instr_fn: Some(lda), address_fn: Some(zero_page), cycles: 3, + name: "lda", }, Instruction { instr_fn: Some(ldx), address_fn: Some(zero_page), cycles: 3, + name: "ldx", }, Instruction { instr_fn: Some(smb2), address_fn: Some(zero_page), cycles: 5, + name: "smb2", }, Instruction { instr_fn: Some(tay), address_fn: None, cycles: 2, + name: "tay", }, Instruction { instr_fn: Some(lda), address_fn: Some(immediate), cycles: 2, + name: "lda", }, Instruction { instr_fn: Some(tax), address_fn: None, cycles: 2, + name: "tax", }, Instruction { instr_fn: None, address_fn: None, cycles: 0, + name: "none", }, Instruction { instr_fn: Some(ldy), address_fn: Some(absolute_a), cycles: 4, + name: "ldy", }, Instruction { instr_fn: Some(lda), address_fn: Some(absolute_a), cycles: 4, + name: "lda", }, Instruction { instr_fn: Some(ldx), address_fn: Some(absolute_a), cycles: 4, + name: "ldx", }, Instruction { instr_fn: Some(bbs2), address_fn: Some(relative_test), cycles: 4, + name: "bbs2", }, Instruction { instr_fn: Some(bcs), address_fn: Some(relative), cycles: 2, + name: "bcs", }, Instruction { instr_fn: Some(lda), address_fn: Some(zero_page_indirect_indexed_with_y), cycles: 5, + name: "lda", }, Instruction { instr_fn: Some(lda), address_fn: Some(zero_page_indirect), cycles: 5, // Unsure, see https://cx16.dk/65c02/reference.html#LDA + name: "lda", }, Instruction { instr_fn: None, address_fn: None, cycles: 0, + name: "none", }, Instruction { instr_fn: Some(ldy), address_fn: Some(zero_page_indexed_with_x), cycles: 4, + name: "ldy", }, Instruction { instr_fn: Some(lda), address_fn: Some(zero_page_indexed_with_x), cycles: 4, + name: "lda", }, Instruction { instr_fn: Some(ldx), address_fn: Some(zero_page_indexed_with_y), cycles: 4, + name: "ldx", }, Instruction { instr_fn: Some(smb3), address_fn: Some(zero_page), cycles: 5, + name: "smb3", }, Instruction { instr_fn: Some(clv), address_fn: None, cycles: 2, + name: "clv", }, Instruction { instr_fn: Some(lda), address_fn: Some(absolute_indexed_with_y), cycles: 4, + name: "lda", }, Instruction { instr_fn: Some(tsx), address_fn: None, cycles: 2, + name: "tsx", }, Instruction { instr_fn: None, address_fn: None, cycles: 0, + name: "none", }, Instruction { instr_fn: Some(ldy), address_fn: Some(absolute_indexed_with_x), cycles: 4, + name: "ldy", }, Instruction { instr_fn: Some(lda), address_fn: Some(absolute_indexed_with_x), cycles: 4, + name: "lda", }, Instruction { instr_fn: Some(ldx), address_fn: Some(absolute_indexed_with_y), cycles: 4, + name: "ldx", }, Instruction { instr_fn: Some(bbs3), address_fn: Some(relative_test), cycles: 4, + name: "bbs3", }, Instruction { instr_fn: Some(cpy), address_fn: Some(immediate), cycles: 2, + name: "cpy", }, Instruction { instr_fn: Some(cmp), address_fn: Some(zero_page_indexed_indirect), cycles: 6, + name: "cmp", }, Instruction { instr_fn: None, address_fn: None, cycles: 0, + name: "none", }, Instruction { instr_fn: None, address_fn: None, cycles: 0, + name: "none", }, Instruction { instr_fn: Some(cpy), address_fn: Some(zero_page), cycles: 3, + name: "cpy", }, Instruction { instr_fn: Some(cmp), address_fn: Some(zero_page), cycles: 3, + name: "cmp", }, Instruction { instr_fn: Some(dec), address_fn: Some(zero_page), cycles: 5, + name: "dec", }, Instruction { instr_fn: Some(smb4), address_fn: Some(zero_page), cycles: 5, + name: "smb4", }, Instruction { instr_fn: Some(iny), address_fn: None, cycles: 2, + name: "iny", }, Instruction { instr_fn: Some(cmp), address_fn: Some(immediate), cycles: 2, + name: "cmp", }, Instruction { instr_fn: Some(dex), address_fn: None, cycles: 2, + name: "dex", }, Instruction { instr_fn: Some(wai), address_fn: None, cycles: 3, + name: "wai", }, Instruction { instr_fn: Some(cpy), address_fn: Some(absolute_a), cycles: 4, + name: "cpy", }, Instruction { instr_fn: Some(cmp), address_fn: Some(absolute_a), cycles: 4, + name: "cmp", }, Instruction { instr_fn: Some(dec), address_fn: Some(absolute_a), cycles: 6, + name: "dec", }, Instruction { instr_fn: Some(bbs4), address_fn: Some(relative_test), cycles: 4, + name: "bbs4", }, Instruction { instr_fn: Some(bne), address_fn: Some(relative), cycles: 2, + name: "bne", }, Instruction { instr_fn: Some(cmp), address_fn: Some(zero_page_indirect_indexed_with_y), cycles: 5, + name: "cmp", }, Instruction { instr_fn: Some(cmp), address_fn: Some(zero_page_indirect), cycles: 5, // Unsure, look here: https://cx16.dk/65c02/reference.html#CMP + name: "cmp", }, Instruction { instr_fn: None, address_fn: None, cycles: 0, + name: "none", }, Instruction { instr_fn: None, address_fn: None, cycles: 0, + name: "none", }, Instruction { instr_fn: Some(cmp), address_fn: Some(zero_page_indexed_with_x), cycles: 4, + name: "cmp", }, Instruction { instr_fn: Some(dec), address_fn: Some(zero_page_indexed_with_x), cycles: 6, + name: "dec", }, Instruction { instr_fn: Some(smb5), address_fn: Some(zero_page), cycles: 5, + name: "smb5", }, Instruction { instr_fn: Some(cld), address_fn: None, cycles: 2, + name: "cld", }, Instruction { instr_fn: Some(cmp), address_fn: Some(absolute_indexed_with_y), cycles: 4, + name: "cmp", }, Instruction { instr_fn: Some(phx), address_fn: None, cycles: 3, + name: "phx", }, Instruction { instr_fn: Some(stp), address_fn: None, cycles: 3, + name: "stp", }, Instruction { instr_fn: None, address_fn: None, cycles: 0, + name: "none", }, Instruction { instr_fn: Some(cmp), address_fn: Some(absolute_indexed_with_x), cycles: 4, + name: "cmp", }, Instruction { instr_fn: Some(dec), address_fn: Some(absolute_indexed_with_x), cycles: 7, + name: "dec", }, Instruction { instr_fn: Some(bbs5), address_fn: Some(relative_test), cycles: 4, + name: "bbs5", }, Instruction { instr_fn: Some(cpx), address_fn: Some(immediate), cycles: 2, + name: "cpx", }, Instruction { instr_fn: Some(sbc), address_fn: Some(zero_page_indexed_indirect), cycles: 6, + name: "sbc", }, Instruction { instr_fn: None, address_fn: None, cycles: 0, + name: "none", }, Instruction { instr_fn: None, address_fn: None, cycles: 0, + name: "none", }, Instruction { instr_fn: Some(cpx), address_fn: Some(zero_page), cycles: 3, + name: "cpx", }, Instruction { instr_fn: Some(sbc), address_fn: Some(zero_page), cycles: 3, + name: "sbc", }, Instruction { instr_fn: Some(inc), address_fn: Some(zero_page), cycles: 5, + name: "inc", }, Instruction { instr_fn: Some(smb6), address_fn: Some(zero_page), cycles: 5, + name: "smb6", }, Instruction { instr_fn: Some(inx), address_fn: None, cycles: 2, + name: "inx", }, Instruction { instr_fn: Some(sbc), address_fn: Some(immediate), cycles: 2, + name: "sbc", }, Instruction { instr_fn: Some(nop), address_fn: None, cycles: 2, + name: "nop", }, Instruction { instr_fn: None, address_fn: None, cycles: 0, + name: "none", }, Instruction { instr_fn: Some(cpx), address_fn: Some(absolute_a), cycles: 4, + name: "cpx", }, Instruction { instr_fn: Some(sbc), address_fn: Some(absolute_a), cycles: 4, + name: "sbc", }, Instruction { instr_fn: Some(inc), address_fn: Some(absolute_a), cycles: 6, + name: "inc", }, Instruction { instr_fn: Some(bbs6), address_fn: Some(relative_test), cycles: 4, + name: "bbs6", }, Instruction { instr_fn: Some(beq), address_fn: Some(relative), cycles: 2, + name: "beq", }, Instruction { instr_fn: Some(sbc), address_fn: Some(zero_page_indirect_indexed_with_y), cycles: 5, + name: "sbc", }, Instruction { instr_fn: Some(sbc), address_fn: Some(zero_page_indirect), cycles: 5, + name: "sbc", }, Instruction { instr_fn: None, address_fn: None, cycles: 0, + name: "none", }, Instruction { instr_fn: None, address_fn: None, cycles: 0, + name: "none", }, Instruction { instr_fn: Some(sbc), address_fn: Some(zero_page_indexed_with_x), cycles: 4, + name: "sbc", }, Instruction { instr_fn: Some(inc), address_fn: Some(zero_page_indexed_with_x), cycles: 6, + name: "inc", }, Instruction { instr_fn: Some(smb7), address_fn: Some(zero_page), cycles: 5, + name: "smb7", }, Instruction { instr_fn: Some(sed), address_fn: None, cycles: 2, + name: "sed", }, Instruction { instr_fn: Some(sbc), address_fn: Some(absolute_indexed_with_y), cycles: 4, + name: "sbc", }, Instruction { instr_fn: Some(plx), address_fn: None, cycles: 4, + name: "plx", }, Instruction { instr_fn: None, address_fn: None, cycles: 0, + name: "none", }, Instruction { instr_fn: None, address_fn: None, cycles: 0, + name: "none", }, Instruction { instr_fn: Some(sbc), address_fn: Some(absolute_indexed_with_x), cycles: 4, + name: "sbc", }, Instruction { instr_fn: Some(inc), address_fn: Some(absolute_indexed_with_x), cycles: 7, + name: "inc", }, Instruction { instr_fn: Some(bbs7), address_fn: Some(relative_test), cycles: 4, + name: "bbs7", }, ]; diff --git a/src/keyboard.rs b/src/keyboard.rs index a165be6..82f072f 100644 --- a/src/keyboard.rs +++ b/src/keyboard.rs @@ -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 { - iter: Keys, -} - -impl Iterator for PlainKeys { - type Item = Result; - fn next(&mut self) -> Option { - 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 { - iter: Keys, - extra: Option, -} - -impl Iterator for ControlKeys { - type Item = Result; - fn next(&mut self) -> Option { - 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 - where - Self: Sized; - fn get_modifiers(self) -> ControlKeys - where - Self: Sized; -} - -impl GetKeys for R { - fn get_plain(self) -> PlainKeys - where - Self: Sized, - { - PlainKeys { iter: self.keys() } - } - fn get_modifiers(self) -> ControlKeys - 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); + } +} diff --git a/src/main.rs b/src/main.rs index fa678db..c173507 100644 --- a/src/main.rs +++ b/src/main.rs @@ -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)); } diff --git a/src/memory.rs b/src/memory.rs index 175327d..58df25b 100644 --- a/src/memory.rs +++ b/src/memory.rs @@ -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}; diff --git a/src/video.rs b/src/video.rs index 7846061..22d3a42 100644 --- a/src/video.rs +++ b/src/video.rs @@ -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, - // renderer: TerminalRenderer<'a>, controller: CpuController, } @@ -183,7 +176,7 @@ impl Screen { pub fn new(config: &Config, controller: CpuController, memory: MemHandle) -> Self { let renderer: Box = 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(); }