From 04fa5454ef309ed6a6a418315af8608123e93c9b Mon Sep 17 00:00:00 2001 From: dogeystamp Date: Sat, 6 Jan 2024 18:05:35 -0500 Subject: [PATCH] src/vm/terminal_io: setup termios --- Cargo.lock | 101 ++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 2 + src/main.rs | 6 ++- src/vm/instruction.rs | 5 ++- src/vm/memory.rs | 6 ++- src/vm/mod.rs | 1 + src/vm/terminal_io.rs | 38 ++++++++++++++++ 7 files changed, 155 insertions(+), 4 deletions(-) create mode 100644 src/vm/terminal_io.rs diff --git a/Cargo.lock b/Cargo.lock index a4fcddd..9d94c0e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,17 +2,41 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "bitflags" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" + [[package]] name = "byteorder" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "ctrlc" +version = "3.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b467862cc8610ca6fc9a1532d7777cee0804e678ab45410897b9396495994a0b" +dependencies = [ + "nix", + "windows-sys", +] + [[package]] name = "lc3" version = "0.1.0" dependencies = [ "byteorder", + "ctrlc", + "libc", "termios", ] @@ -22,6 +46,17 @@ version = "0.2.151" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "302d7ab3130588088d277783b1e2d2e10c9e9e4a16dd9050e6ec93fb3e7048f4" +[[package]] +name = "nix" +version = "0.27.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053" +dependencies = [ + "bitflags", + "cfg-if", + "libc", +] + [[package]] name = "termios" version = "0.3.3" @@ -30,3 +65,69 @@ checksum = "411c5bf740737c7918b8b1fe232dca4dc9f8e754b8ad5e20966814001ed0ac6b" dependencies = [ "libc", ] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" diff --git a/Cargo.toml b/Cargo.toml index 62d08be..e6c1966 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,4 +7,6 @@ edition = "2021" [dependencies] byteorder = "1.5.0" +ctrlc = "3.4.2" +libc = "0.2.151" termios = "0.3.3" diff --git a/src/main.rs b/src/main.rs index f60e0c8..435545a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,11 +3,13 @@ ////////////////////////////// mod vm; -use crate::vm::VM; +use crate::vm::{terminal_io, VM}; use std::env; fn main() { - let args : Vec<_> = env::args().collect(); + let args: Vec<_> = env::args().collect(); + + terminal_io::setup_terminal(); let mut vm = VM::new(); vm.read_program(args.get(1).expect("No program file given")); diff --git a/src/vm/instruction.rs b/src/vm/instruction.rs index f3d3b9f..c080876 100644 --- a/src/vm/instruction.rs +++ b/src/vm/instruction.rs @@ -224,7 +224,10 @@ fn op_add(vm: &mut VM, instr: u16) { if (instr >> 5) & 1 == 0 { let sr2 = instr & 0b111; - let res = vm.registers.get_reg(sr1).wrapping_add(vm.registers.get_reg(sr2)); + let res = vm + .registers + .get_reg(sr1) + .wrapping_add(vm.registers.get_reg(sr2)); vm.registers.set_reg_with_cond(dr, res); } else { let imm = instr & 0x1f; diff --git a/src/vm/memory.rs b/src/vm/memory.rs index 27ab6e9..eb1da07 100644 --- a/src/vm/memory.rs +++ b/src/vm/memory.rs @@ -6,6 +6,8 @@ // memory interface //////////////// +use super::terminal_io; + pub const MEM_SIZE: usize = 1 << 16; pub struct Memory { @@ -25,7 +27,9 @@ impl Memory { pub fn get_mem(&self, addr: u16) -> u16 { if addr >= 0xFE00 { - unimplemented!("mem-map: {:#X}", addr); + match addr { + _ => unimplemented!("mem-map: {:#X}", addr), + } } return self.data[addr as usize]; } diff --git a/src/vm/mod.rs b/src/vm/mod.rs index 0c67a04..80fa6d8 100644 --- a/src/vm/mod.rs +++ b/src/vm/mod.rs @@ -13,6 +13,7 @@ use std::{fs::File, io::BufReader}; mod instruction; mod memory; +pub mod terminal_io; //////////////// // registers diff --git a/src/vm/terminal_io.rs b/src/vm/terminal_io.rs new file mode 100644 index 0000000..ca1b82d --- /dev/null +++ b/src/vm/terminal_io.rs @@ -0,0 +1,38 @@ +////////////////////////////// +////// terminal input/output +////////////////////////////// + +extern crate termios; +use termios::*; + +extern crate libc; +use libc::STDIN_FILENO; + +extern crate ctrlc; + +/// Configure raw input (see termios(3) man-page) +pub fn setup_terminal() { + let mut term: Termios = Termios::from_fd(STDIN_FILENO).unwrap(); + // ICANON (canonical) is line-by-line input (i.e. press enter to send) + // ECHO is showing the characters you type + // what this means is that LC-3 will receive characters immediately and without displaying them + term.c_lflag &= !(ICANON | ECHO); + // TCSANOW: "the change occurs immediately" + tcsetattr(STDIN_FILENO, TCSANOW, &term).unwrap(); + + // when leaving the program we want to be polite and undo the above changes + ctrlc::set_handler(|| { + restore_terminal(); + // typical CTRL-C exit code + std::process::exit(130); + }) + .expect("Failed to set CTRL-C handler"); +} + +/// Restore terminal to initial state +fn restore_terminal() { + // Ideally we'd store the original state but I was too lazy + let mut term: Termios = Termios::from_fd(STDIN_FILENO).unwrap(); + term.c_lflag |= ICANON | ECHO; + tcsetattr(STDIN_FILENO, TCSANOW, &term).unwrap() +}