Adds more util methods for swapping endianness and extracting data from instructions

Adds tests for new util methods
This commit is contained in:
2025-05-26 08:40:15 -04:00
parent 74bf2e71e4
commit d27d2e8e45
10 changed files with 300 additions and 33 deletions
+1 -2
View File
@@ -1,4 +1,3 @@
use gemma::chip8::computer::Chip8Computer;
use gemma::chip8::computer_manager::Chip8ComputerManager;
use std::fs::File;
use std::io::Read;
@@ -24,7 +23,7 @@ fn main() {
let mut num_cycles = 0;
// how many instructions in 10s.
let end_time = start_time.add(Duration::from_secs(10));
while (Instant::now().le(&end_time)) {
while Instant::now().le(&end_time) {
num_cycles += 1;
x.step();
}
+1 -2
View File
@@ -1,7 +1,6 @@
use clap::{Parser, Subcommand};
use flate2::{write::{GzEncoder, GzDecoder}, Compression};
use std::io::prelude::*;
use std::io::{self, Write};
use std::io::Write;
#[derive(Parser)]
#[command(author, version, about = "Compress or decompress a string", long_about = None)]
-4
View File
@@ -92,10 +92,6 @@ impl Chip8Computer {
self.registers.set_pc(offset);
}
pub fn execute_instruction(&mut self, instruction_to_execute: Chip8CpuInstructions) {
//
}
pub fn step_system(&mut self) -> &mut Chip8Computer {
println!("Stepping System 1 Step");
+5 -9
View File
@@ -9,7 +9,6 @@ use rand::Rng;
use serde::{Deserialize, Serialize};
use std::fmt::{Debug, Display, Formatter};
use std::ops::BitAnd;
use std::time::Instant;
/*
nnn or addr - A 12-bit value, the lowest 12 bits of the instruction
@@ -681,7 +680,7 @@ impl Chip8CpuInstructions {
}
pub fn execute(&self, input: &mut Chip8Computer) -> Chip8Computer {
// print!("INSTRUCTION {}", self);
let start_time = Instant::now();
// let start_time = Instant::now();
let start_pc = input.registers.peek_pc();
input.registers.poke_pc(start_pc + 2);
match self {
@@ -796,7 +795,7 @@ impl Chip8CpuInstructions {
let lhs = input.registers.peek(*x);
let rhs = input.registers.peek(*y);
let mut result = 0;
let result;
let borrow_flag: u8 = if rhs > lhs {
result = (lhs as u16 + 0x100) - rhs as u16;
@@ -1003,7 +1002,7 @@ impl Chip8CpuInstructions {
let value_to_set = input.delay_timer.current();
input.registers.poke(*x, value_to_set);
}
Chip8CpuInstructions::LDRK(x) => {
Chip8CpuInstructions::LDRK(_) => {
// Fx0A - LD Vx, K
// Wait for a key press, store the value of the key in Vx.
//
@@ -1061,9 +1060,6 @@ impl Chip8CpuInstructions {
// whats the leftover when dividing by 10
let units = to_convert % 10;
// Convert to BCD
let result =
((hundreds as u16) << 8) | units as u16 | ((tens as u16) << 4) | units as u16;
// write them to the memory pointed to by I, I+1, and I+2
let target_start_offset = input.registers.peek_i();
input.memory.poke(target_start_offset, hundreds);
@@ -1191,11 +1187,11 @@ impl Chip8CpuInstructions {
}
}
}
DW(addr) => {
DW(_) => {
println!("DATA WORD FOUND...");
}
};
let cycle_time = Instant::now().duration_since(start_time).as_nanos();
// let cycle_time = Instant::now().duration_since(start_time).as_nanos();
// println!("\t\tTook {cycle_time}ms");
input.to_owned()
}
+64 -7
View File
@@ -1,6 +1,8 @@
pub struct InstructionUtil {}
impl InstructionUtil {
/// Byte To Bools
/// Convert a u8 byte to an array of bool
pub fn byte_to_bools(to_convert: u8) -> [bool; 8] {
let mut return_values = [false; 8];
for i in 0..8 {
@@ -10,6 +12,8 @@ impl InstructionUtil {
return_values
}
/// Byte To Bools
/// Convert an array of bool to a u8
pub fn bools_to_byte(to_convert: [bool; 8]) -> u8 {
let mut return_value = 0u8;
for i in 0..to_convert.len() {
@@ -21,6 +25,8 @@ impl InstructionUtil {
return_value
}
/// Split Bytes
/// Split a u16 into a pair of u8 values for high and low byte
pub fn split_bytes(to_split: u16) -> (u8, u8) {
let high = to_split.rotate_left(8) as u8;
let low = (to_split & 0xff) as u8;
@@ -28,37 +34,88 @@ impl InstructionUtil {
(high, low)
}
/// Join Bytes
/// Joins 2 u8 into a single u16 with high and low
/// bytes provided
pub fn join_bytes(high: u8, low: u8) -> u16 {
(high as u16) << 8 | low as u16
}
// nnn or addr - A 12-bit value, the lowest 12 bits of the instruction
/// Swap Endian
/// Swaps the endianess of a value
/// 0xabcd -> 0xcdab
pub fn swap_endian(to_swap:u16) -> u16 {
let low = to_swap & 0xff;
let high = to_swap & 0xff00;
low << 8 | high >> 8
}
/// Split Bytes Swap Endian
/// Swaps endianness and return both bytes separately
pub fn split_bytes_swap_endian(to_split: u16) -> (u8, u8) {
InstructionUtil::split_bytes(InstructionUtil::swap_endian(to_split))
}
/// Join Bytes Swap Endian
/// Swaps endianness and returns the combined bytes
pub fn join_bytes_swap_endian(high :u8, low: u8) -> u16 {
InstructionUtil::swap_endian(InstructionUtil::join_bytes(high, low))
}
/// Read Address from Instruction
/// Reads the 'address' portion of an instruction
/// Returns the 12 LSB
/// 0xabcd -> 0x0bcd
pub fn read_addr_from_instruction(instruction_to_read_from: u16) -> u16 {
instruction_to_read_from & 0x0FFF
}
// n or nibble - A 4-bit value, the lowest 4 bits of the instruction
/// Read Nibble from Instruction
/// Returns the lowest 4 bits of the instruction
/// 0xabcd -> 0x0d
pub fn read_nibble_from_instruction(instruction_to_read_from: u16) -> u8 {
( instruction_to_read_from & 0x000F )as u8
}
// x - A 4-bit value, the lower 4 bits of the high byte of the instruction
/// Read X From Instruction
/// Returns the 4 LSB of the high byte of the instruction
/// Returns bits 9-13
/// 0xabcd -> 0x0b
pub fn read_x_from_instruction(instruction_to_read_from: u16) -> u8 {
(instruction_to_read_from & 0x0F00).rotate_right(8) as u8
}
// y - A 4-bit value, the upper 4 bits of the low byte of the instruction
/// Read Y from Instruction
/// Returns the 4 MSB from the low byte of the instruction
/// Returns bits 5-8
/// 0xabcd -> 0x0c
pub fn read_y_from_instruction(instruction_to_read_from: u16) -> u8 {
(instruction_to_read_from & 0x00F0).rotate_right(4) as u8
}
// kk or byte - An 8-bit value, the lowest 8 bits of the instruction
/// Read Byte from Instruction
/// Returns the 8 LSB from the instruction
/// Returns bits 0-7
/// 0xabcd -> 0xcd
pub fn read_byte_from_instruction(instruction_to_read_from: u16) -> u8 {
(instruction_to_read_from & 0x00FF) as u8
}
/// Alias for read_x_from_instruction
pub fn read_upper_byte_lower_nibble(to_read_from: u16) -> u8 {
((to_read_from & 0x0f00) >> 8) as u8
InstructionUtil::read_x_from_instruction(to_read_from)
}
pub fn read_bits_from_instruction(instruction_bytes: u16, first_bit: u8, last_bit: u8) -> u16 {
// shift the value over by the 'first bit' bits
let working = instruction_bytes.rotate_right(first_bit as u32);
let mut working_mask: i32 = 0x00;
// build the mask
for _ in first_bit..=last_bit {
working_mask = working_mask.rotate_left(1) | 0x01;
}
// apply the mask to the working value
working & working_mask as u16
}
}
+6 -6
View File
@@ -152,7 +152,7 @@ impl Chip8Video {
}
pub fn scroll_right(&mut self) {
println!("SCROLLRIGHTPRE:::[{}]", self.format_as_string());
// println!("SCROLLRIGHTPRE:::[{}]", self.format_as_string());
let (width, height) = self.get_resolution();
for current_row in 0..height {
@@ -168,11 +168,11 @@ impl Chip8Video {
// Clear the first 4 pixels in the current row
self.memory[row_offset..row_offset + 4].fill(false);
}
println!("SCROLLRIGHTPOST:::[{}]", self.format_as_string());
// println!("SCROLLRIGHTPOST:::[{}]", self.format_as_string());
}
pub fn scroll_left(&mut self) {
println!("SCROLLLEFTPRE:::[{}]", self.format_as_string());
// println!("SCROLLLEFTPRE:::[{}]", self.format_as_string());
let (width, height) = self.get_resolution();
for current_row in 0..height {
@@ -181,7 +181,7 @@ impl Chip8Video {
let target: usize = (row_offset + current_column) as usize;
let source: usize = target + 4;
self.memory[target] = self.memory[source];
println!("Moving from {source} to {target}");
// println!("Moving from {source} to {target}");
}
let clear_start: usize = (row_offset + width - 4) as usize;
@@ -189,7 +189,7 @@ impl Chip8Video {
self.memory[clear_start..clear_end].fill(false);
}
println!("SCROLLLEFTPOST:::[{}]", self.format_as_string());
// println!("SCROLLLEFTPOST:::[{}]", self.format_as_string());
}
pub fn scroll_up(&mut self, how_far: &u8) {
@@ -240,7 +240,7 @@ impl Default for Chip8Video {
Chip8Video {
memory: mem,
has_frame_changed: false,
current_res: Chip8VideoModes::LowRes,
current_res: LowRes,
}
}
}
+1
View File
@@ -18,6 +18,7 @@ impl InstructionTrait for Add {
}
fn decode(from: Vec<u8>) -> &dyn InstructionTrait {
todo!()
}
}