gb-emu/lib/src/util.rs

159 lines
3.4 KiB
Rust
Raw Normal View History

2023-03-08 11:01:18 +11:00
use crate::{
processor::{memory::mmio::gpu::Colour, Direction},
PAUSE_ENABLED, PAUSE_QUEUED, VERBOSE,
};
2023-03-06 19:20:47 +11:00
use std::{io, 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");
}
}
}
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 is_verbose() -> bool {
match VERBOSE.get() {
Some(v) => *v,
None => false,
}
}
2023-02-12 09:27:41 +11:00
pub(crate) fn as_signed(unsigned: u8) -> i8 {
2023-02-20 10:01:53 +11:00
unsafe { transmute(unsigned) }
2023-02-12 09:27:41 +11:00
}
pub(crate) fn get_bit(byte: u8, flag: u8) -> bool {
let mask = 1 << flag;
let got = byte & mask;
2023-02-12 09:41:34 +11:00
got > 0x0
2023-02-12 09:27:41 +11:00
}
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;
2023-02-12 09:41:34 +11:00
(r, carry)
2023-02-12 09:27:41 +11:00
}
Direction::Right => {
let carry = get_bit(byte, 0);
let r = byte >> 1;
2023-02-12 09:41:34 +11:00
(r, carry)
2023-02-12 09:27:41 +11:00
}
}
}
pub(crate) fn get_rotation_carry(direction: &Direction) -> u8 {
match direction {
Direction::Left => 0b1,
Direction::Right => 0b10000000,
}
}
2023-02-20 10:01:53 +11:00
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);
}
}
2023-03-08 11:01:18 +11:00
pub fn scale_buffer<T: From<Colour> + Copy>(
buffer: &[T],
width: usize,
height: usize,
factor: usize,
) -> Vec<T> {
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
}
2023-03-09 11:52:24 +11:00
pub fn scale_buffer_in_place<T: From<Colour> + Copy>(
buffer: &[T],
target: &mut [T],
width: usize,
height: usize,
factor: usize,
) {
for y in 0..height {
for y_2 in 0..factor {
for x in 0..width {
for x_2 in 0..factor {
target[(((y * factor) + y_2) * (width * factor)) + (x * factor) + x_2] =
buffer[(y * width) + x];
}
}
}
}
}