Adds more util methods for swapping endianness and extracting data from instructions
Adds tests for new util methods
This commit is contained in:
@@ -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,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)]
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ impl InstructionTrait for Add {
|
||||
}
|
||||
|
||||
fn decode(from: Vec<u8>) -> &dyn InstructionTrait {
|
||||
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user