use crate::{processor::Direction, PAUSE_ENABLED, PAUSE_QUEUED, VERBOSE}; use std::{ io::{self, stdout, Write}, mem::transmute, }; #[macro_export] macro_rules! verbose_println { ($($tts:tt)*) => { if $crate::util::is_verbose() { println!($($tts)*); } }; } #[macro_export] macro_rules! verbose_print { ($($tts:tt)*) => { if $crate::util::is_verbose() { print!($($tts)*); } }; } pub(crate) fn pause_then_step() { unsafe { if PAUSE_ENABLED { let line = pause(); PAUSE_QUEUED = !line.contains("continue"); } } } #[allow(dead_code)] pub(crate) fn pause_once() { println!("paused..."); pause(); } pub(crate) fn pause() -> String { let mut line = String::new(); match io::stdin().read_line(&mut line) { Ok(_) => line, Err(_) => String::from(""), } } pub(crate) fn print_cycles(cycles: &i32) { if *cycles % 45678 != 0 { return; } let instructions_per_second = 400000; print!( "cycle {} - approx {} seconds on real hardware\r", cycles, cycles / instructions_per_second ); stdout().flush().unwrap(); } pub(crate) fn is_verbose() -> bool { match VERBOSE.get() { Some(v) => *v, None => false, } } pub(crate) fn as_signed(unsigned: u8) -> i8 { unsafe { transmute(unsigned) } } pub(crate) fn get_bit(byte: u8, flag: u8) -> bool { let mask = 1 << flag; let got = byte & mask; got > 0x0 } pub(crate) fn set_or_clear_bit(byte: u8, flag: u8, condition: bool) -> u8 { if condition { set_bit(byte, flag) } else { clear_bit(byte, flag) } } pub(crate) fn set_bit(byte: u8, flag: u8) -> u8 { byte | (1 << flag) } pub(crate) fn clear_bit(byte: u8, flag: u8) -> u8 { byte & (!(1 << flag)) } pub(crate) fn rotate(byte: u8, direction: &Direction) -> (u8, bool) { match direction { Direction::Left => { let carry = get_bit(byte, 7); let r = byte << 1; (r, carry) } Direction::Right => { let carry = get_bit(byte, 0); let r = byte >> 1; (r, carry) } } } pub(crate) fn get_rotation_carry(direction: &Direction) -> u8 { match direction { Direction::Left => 0b1, Direction::Right => 0b10000000, } } pub trait Nibbles { fn get_low_nibble(&self) -> u8; fn get_high_nibble(&self) -> u8; fn set_low_nibble(&mut self, val: u8); fn set_high_nibble(&mut self, val: u8); } impl Nibbles for u8 { fn get_low_nibble(&self) -> u8 { *self & 0x0F } fn get_high_nibble(&self) -> u8 { (*self >> 4) & 0x0F } fn set_low_nibble(&mut self, val: u8) { *self = (*self & 0xF0) | (val & 0x0F); } fn set_high_nibble(&mut self, val: u8) { *self = (*self & 0x0F) | (val << 4); } } pub fn scale_buffer(buffer: &[u32], width: usize, height: usize, factor: usize) -> Vec { let mut v = vec![]; for y in 0..height { for _ in 0..factor { for x in 0..width { for _ in 0..factor { v.push(buffer[(y * width) + x]); } } } } v }