apply of clippy.

fixed missing imports and builds and tests as expected again
This commit is contained in:
Trevor Merritt 2024-10-30 09:48:59 -04:00
parent 4fb2d6af29
commit 011874bca6
20 changed files with 114 additions and 154 deletions

View File

@ -2,7 +2,6 @@ use log::{debug};
use crate::chip8::delay_timer::DelayTimer; use crate::chip8::delay_timer::DelayTimer;
use crate::chip8::keypad::Keypad; use crate::chip8::keypad::Keypad;
use crate::chip8::quirk_modes::QuirkMode; use crate::chip8::quirk_modes::QuirkMode;
use crate::chip8::quirk_modes::QuirkMode::Chip8;
use crate::chip8::registers::Chip8Registers; use crate::chip8::registers::Chip8Registers;
use crate::chip8::sound_timer::SoundTimer; use crate::chip8::sound_timer::SoundTimer;
use crate::chip8::stack::Chip8Stack; use crate::chip8::stack::Chip8Stack;

View File

@ -1,6 +1,5 @@
use std::sync::mpsc::{channel, Sender};
use std::thread; use std::thread;
use std::thread::{sleep, JoinHandle, Thread}; use std::thread::sleep;
use std::time::{Duration, Instant}; use std::time::{Duration, Instant};
use crate::chip8::computer::Chip8Computer; use crate::chip8::computer::Chip8Computer;
use crate::chip8::cpu_states::Chip8CpuStates; use crate::chip8::cpu_states::Chip8CpuStates;
@ -69,14 +68,11 @@ impl Chip8ComputerManager {
// println!("STARTING TICK"); // println!("STARTING TICK");
let mut did_tick: bool = false; let mut did_tick: bool = false;
if self.one_step | self.core_should_run { if self.one_step | self.core_should_run {
match self.computer.state { if let WaitingForInstruction = self.computer.state {
WaitingForInstruction => { self.core_last_cycle_start = Instant::now();
self.core_last_cycle_start = Instant::now(); self.computer.step_system();
self.computer.step_system(); did_tick = true
did_tick = true // println!("SYSTEM STEP");
// println!("SYSTEM STEP");
}
_ => {}
} }
}; };
if self.one_step { if self.one_step {

View File

@ -3,6 +3,12 @@ pub struct DelayTimer {
counter: u8 counter: u8
} }
impl Default for DelayTimer {
fn default() -> Self {
Self::new()
}
}
impl DelayTimer { impl DelayTimer {
pub fn current(&self) -> u8 { pub fn current(&self) -> u8 {
self.counter self.counter
@ -19,7 +25,7 @@ impl DelayTimer {
} }
pub fn set_timer(&mut self, new_value: u8) { pub fn set_timer(&mut self, new_value: u8) {
self.counter = new_value as u8 self.counter = new_value
} }
pub fn tick(&mut self) { pub fn tick(&mut self) {

View File

@ -1,10 +1,8 @@
use std::arch::x86_64::_mm_xor_pd;
use std::fmt::{Debug, Display, Formatter}; use std::fmt::{Debug, Display, Formatter};
use std::ops::{BitAnd, Deref, Shr}; use std::ops::BitAnd;
use std::time::Instant; use std::time::Instant;
use chrono::ParseMonthError;
use log::debug; use log::debug;
use rand::{random, Rng}; use rand::Rng;
use crate::chip8::computer::{Chip8Computer}; use crate::chip8::computer::{Chip8Computer};
use crate::chip8::cpu_states::Chip8CpuStates::WaitingForKey; use crate::chip8::cpu_states::Chip8CpuStates::WaitingForKey;
use crate::chip8::instructions::Chip8CpuInstructions::*; use crate::chip8::instructions::Chip8CpuInstructions::*;
@ -548,11 +546,11 @@ impl Chip8CpuInstructions {
pub fn encode(&self) -> u16 { pub fn encode(&self) -> u16 {
match self { match self {
Chip8CpuInstructions::SYS(target) => 0x0000 | (target & 0x0FFF) as u16, Chip8CpuInstructions::SYS(target) => target & 0x0FFF,
Chip8CpuInstructions::CLS => 0x00E0, Chip8CpuInstructions::CLS => 0x00E0,
Chip8CpuInstructions::RET => 0x00EE, Chip8CpuInstructions::RET => 0x00EE,
Chip8CpuInstructions::JPA(new_addr) => 0x1000 | (new_addr & 0x0FFF) as u16, Chip8CpuInstructions::JPA(new_addr) => 0x1000 | (new_addr & 0x0FFF),
Chip8CpuInstructions::CALL(address) => 0x2000 | (address & 0x0FFF) as u16, Chip8CpuInstructions::CALL(address) => 0x2000 | (address & 0x0FFF),
Chip8CpuInstructions::SEX(vx_register, byte) => 0x3000 | ((*vx_register as u16) << 8) | (*byte as u16), Chip8CpuInstructions::SEX(vx_register, byte) => 0x3000 | ((*vx_register as u16) << 8) | (*byte as u16),
Chip8CpuInstructions::SNEB(vx_register, byte) => 0x4000 | ((*vx_register as u16) << 8) | (*byte as u16), Chip8CpuInstructions::SNEB(vx_register, byte) => 0x4000 | ((*vx_register as u16) << 8) | (*byte as u16),
Chip8CpuInstructions::SEY(x_register, y_register) => 0x5000 | ((*x_register as u16) << 8) | ((*y_register as u16) << 4), Chip8CpuInstructions::SEY(x_register, y_register) => 0x5000 | ((*x_register as u16) << 8) | ((*y_register as u16) << 4),
@ -695,10 +693,10 @@ impl Chip8CpuInstructions {
let start_time = Instant::now(); let start_time = Instant::now();
let start_pc = input.registers.peek_pc(); let start_pc = input.registers.peek_pc();
input.registers.poke_pc(start_pc + 2); input.registers.poke_pc(start_pc + 2);
let _ = match self { match self {
// 0x0nnn Exit to System Call // 0x0nnn Exit to System Call
Chip8CpuInstructions::SYS(new_address) => { Chip8CpuInstructions::SYS(new_address) => {
input.registers.poke_pc(*new_address as u16); input.registers.poke_pc(*new_address);
} }
// * 0x00E0 Clear Screen // * 0x00E0 Clear Screen
Chip8CpuInstructions::CLS => { Chip8CpuInstructions::CLS => {
@ -710,17 +708,17 @@ impl Chip8CpuInstructions {
} }
// 0x1nnn Jump to Address // 0x1nnn Jump to Address
Chip8CpuInstructions::JPA(new_address) => { Chip8CpuInstructions::JPA(new_address) => {
input.registers.poke_pc(*new_address as u16); input.registers.poke_pc(*new_address);
} }
// 0x2nnn Call Subroutine // 0x2nnn Call Subroutine
Chip8CpuInstructions::CALL(new_address) => { Chip8CpuInstructions::CALL(new_address) => {
let return_address = input.registers.peek_pc(); let return_address = input.registers.peek_pc();
input.registers.poke_pc(*new_address as u16); input.registers.poke_pc(*new_address);
input.stack.push(&return_address); input.stack.push(&return_address);
} }
// 0x3xkk Skip next instruction if Vx = kk. // 0x3xkk Skip next instruction if Vx = kk.
Chip8CpuInstructions::SEX(vx_register, byte) => { Chip8CpuInstructions::SEX(vx_register, byte) => {
if input.registers.peek(*vx_register as u8) == *byte as u8 { if input.registers.peek(*vx_register) == { *byte } {
input.registers.advance_pc(); input.registers.advance_pc();
} }
} }
@ -737,7 +735,7 @@ impl Chip8CpuInstructions {
} }
// 0x5xy0 Skip next instruction if Vx == Vy // 0x5xy0 Skip next instruction if Vx == Vy
Chip8CpuInstructions::SEY(x, y) => { Chip8CpuInstructions::SEY(x, y) => {
if input.registers.peek(*x as u8) == input.registers.peek(*y as u8) { if input.registers.peek(*x) == input.registers.peek(*y) {
input.registers.advance_pc(); input.registers.advance_pc();
} }
} }
@ -751,37 +749,37 @@ impl Chip8CpuInstructions {
} }
// 0x8xy0 Set value of Vy in Vx // 0x8xy0 Set value of Vy in Vx
Chip8CpuInstructions::LDR_Y(x, y) => { Chip8CpuInstructions::LDR_Y(x, y) => {
input.registers.poke(*x as u8, input.registers.peek(*y as u8)); input.registers.poke(*x, input.registers.peek(*y));
} }
// 0x8xy1 Set Vx = Vx OR Vy // 0x8xy1 Set Vx = Vx OR Vy
Chip8CpuInstructions::OR(x, y) => { Chip8CpuInstructions::OR(x, y) => {
// shift them to 16 bit // shift them to 16 bit
let working_16_x = input.registers.peek(*x as u8) as u16; let working_16_x = input.registers.peek(*x) as u16;
let working_16_y = input.registers.peek(*y as u8) as u16; let working_16_y = input.registers.peek(*y) as u16;
// OR them // OR them
let working_16_or = working_16_x | working_16_y; let working_16_or = working_16_x | working_16_y;
// shift them back to 8 bit. // shift them back to 8 bit.
input.registers.poke(*x as u8, working_16_or as u8); input.registers.poke(*x, working_16_or as u8);
debug!("OrVxVy [0x{x:1x}] [0x{y:1x}]") debug!("OrVxVy [0x{x:1x}] [0x{y:1x}]")
} }
// 0x8xy2 Set Vx = Vx AND Vy // 0x8xy2 Set Vx = Vx AND Vy
Chip8CpuInstructions::AND(x, y) => { Chip8CpuInstructions::AND(x, y) => {
let lhs_16 = input.registers.peek(*x as u8) as u16; let lhs_16 = input.registers.peek(*x) as u16;
let rhs_16 = input.registers.peek(*y as u8) as u16; let rhs_16 = input.registers.peek(*y) as u16;
input.registers.poke(*x as u8, (lhs_16 & rhs_16) as u8); input.registers.poke(*x, (lhs_16 & rhs_16) as u8);
} }
// 0x8xy3 Set Vx = Vx XOR Vy // 0x8xy3 Set Vx = Vx XOR Vy
Chip8CpuInstructions::ORY(x, y) => { Chip8CpuInstructions::ORY(x, y) => {
let lhs_16 = input.registers.peek(*x as u8) as u16; let lhs_16 = input.registers.peek(*x) as u16;
let rhs_16 = input.registers.peek(*y as u8) as u16; let rhs_16 = input.registers.peek(*y) as u16;
input.registers.poke(*x as u8, (lhs_16 ^ rhs_16) as u8); input.registers.poke(*x, (lhs_16 ^ rhs_16) as u8);
} }
// 0x8xy4 Set Vx = Vx + Vy (SET VF on Carry) // 0x8xy4 Set Vx = Vx + Vy (SET VF on Carry)
Chip8CpuInstructions::ADDR(x, y) => { Chip8CpuInstructions::ADDR(x, y) => {
let lhs = input.registers.peek(*x as u8) as i16; let lhs = input.registers.peek(*x) as i16;
let rhs = input.registers.peek(*y as u8) as i16; let rhs = input.registers.peek(*y) as i16;
let working = lhs + rhs; let working = lhs + rhs;
input.registers.poke(*x as u8, working as u8); input.registers.poke(*x, working as u8);
if working >= 0x100 { if working >= 0x100 {
input.registers.poke(0xf, 0x01); input.registers.poke(0xf, 0x01);
@ -808,7 +806,7 @@ impl Chip8CpuInstructions {
1 1
}; };
input.registers.poke(*x as u8, result as u8); input.registers.poke(*x, result as u8);
input.registers.poke(0x0f, borrow_flag); input.registers.poke(0x0f, borrow_flag);
} }
Chip8CpuInstructions::SHR(x, _) => { Chip8CpuInstructions::SHR(x, _) => {
@ -820,7 +818,7 @@ impl Chip8CpuInstructions {
// overflow check // overflow check
let rotated = initial_value >> 1; let rotated = initial_value >> 1;
input.registers.poke(*x as u8, rotated); input.registers.poke(*x, rotated);
if initial_value.bitand(0b1) == 1 { if initial_value.bitand(0b1) == 1 {
input.registers.poke(0x0f, 0x01); input.registers.poke(0x0f, 0x01);
} else { } else {
@ -832,8 +830,8 @@ impl Chip8CpuInstructions {
// Set Vx = Vy - Vx, set VF = NOT borrow. // Set Vx = Vy - Vx, set VF = NOT borrow.
// //
// If Vy > Vx, then VF is set to 1, otherwise 0. Then Vx is subtracted from Vy, and the results stored in Vx. // If Vy > Vx, then VF is set to 1, otherwise 0. Then Vx is subtracted from Vy, and the results stored in Vx.
let y_register = input.registers.peek(*y as u8); let y_register = input.registers.peek(*y);
let x_register = input.registers.peek(*x as u8); let x_register = input.registers.peek(*x);
let mut value_to_poke = 0; let mut value_to_poke = 0;
let new_value = if y_register < x_register { let new_value = if y_register < x_register {
@ -859,7 +857,7 @@ impl Chip8CpuInstructions {
// overflow check // overflow check
let rotated = initial_value << 1; let rotated = initial_value << 1;
input.registers.poke(*x as u8, rotated); input.registers.poke(*x, rotated);
if initial_value.bitand(0b10000000) == 0b10000000 { if initial_value.bitand(0b10000000) == 0b10000000 {
input.registers.poke(0x0f, 0x01); input.registers.poke(0x0f, 0x01);
} else { } else {
@ -872,8 +870,8 @@ impl Chip8CpuInstructions {
// //
// The values of Vx and Vy are compared, and if they are not equal, the program counter is increased by 2. // The values of Vx and Vy are compared, and if they are not equal, the program counter is increased by 2.
let x_reg_value = input.registers.peek(*vx_register as u8); let x_reg_value = input.registers.peek(*vx_register);
let y_reg_value = input.registers.peek(*vy_register as u8); let y_reg_value = input.registers.peek(*vy_register);
if x_reg_value != y_reg_value { if x_reg_value != y_reg_value {
input.registers.advance_pc(); input.registers.advance_pc();
} }
@ -912,7 +910,7 @@ impl Chip8CpuInstructions {
let and_value: u8 = *byte; let and_value: u8 = *byte;
let result = new_value & and_value; let result = new_value & and_value;
debug!("RANDOM: [{new_value:02x}] AND: [{and_value:02x} Result: [{result:02x}]"); debug!("RANDOM: [{new_value:02x}] AND: [{and_value:02x} Result: [{result:02x}]");
input.registers.poke(*x as u8, new_value & *byte as u8) input.registers.poke(*x, new_value & { *byte })
} }
Chip8CpuInstructions::DRW(y, x, n) => { Chip8CpuInstructions::DRW(y, x, n) => {
// Display n-byte sprite starting at memory location I at (Vx, Vy), set VF = collision. // Display n-byte sprite starting at memory location I at (Vx, Vy), set VF = collision.
@ -968,7 +966,7 @@ impl Chip8CpuInstructions {
// Skip next instruction if key with the value of Vx is pressed. // Skip next instruction if key with the value of Vx is pressed.
// //
// Checks the keyboard, and if the key corresponding to the value of Vx is currently in the down position, PC is increased by 2. // Checks the keyboard, and if the key corresponding to the value of Vx is currently in the down position, PC is increased by 2.
let key_to_check = input.registers.peek(*x as u8); let key_to_check = input.registers.peek(*x);
let is_pressed = input.keypad.pressed(key_to_check); let is_pressed = input.keypad.pressed(key_to_check);
if is_pressed { if is_pressed {
input.registers.advance_pc(); input.registers.advance_pc();
@ -982,7 +980,7 @@ impl Chip8CpuInstructions {
// Checks the keyboard, // Checks the keyboard,
// and if the key corresponding to the value of Vx is currently in the up position, // and if the key corresponding to the value of Vx is currently in the up position,
// PC is increased by 2. // PC is increased by 2.
let target_key = input.registers.peek(*x as u8); let target_key = input.registers.peek(*x);
let is_pressed = input.keypad.pressed(target_key); let is_pressed = input.keypad.pressed(target_key);
debug!("SnKpVx [{x:1x}]"); debug!("SnKpVx [{x:1x}]");
if !is_pressed { if !is_pressed {
@ -995,7 +993,7 @@ impl Chip8CpuInstructions {
// //
// The value of DT is placed into Vx. // The value of DT is placed into Vx.
let value_to_set = input.delay_timer.current(); let value_to_set = input.delay_timer.current();
input.registers.poke(*x as u8, value_to_set as u8); input.registers.poke(*x, value_to_set);
} }
Chip8CpuInstructions::LDRK(x) => { Chip8CpuInstructions::LDRK(x) => {
// Fx0A - LD Vx, K // Fx0A - LD Vx, K
@ -1009,11 +1007,11 @@ impl Chip8CpuInstructions {
// Set delay timer = Vx. // Set delay timer = Vx.
// //
// DT is set equal to the value of Vx. // DT is set equal to the value of Vx.
let new_time = input.registers.peek(*source_register as u8); let new_time = input.registers.peek(*source_register);
input.delay_timer.set_timer(new_time); input.delay_timer.set_timer(new_time);
} }
Chip8CpuInstructions::LDIS(new_time) => { Chip8CpuInstructions::LDIS(new_time) => {
let new_value = input.registers.peek(*new_time as u8); let new_value = input.registers.peek(*new_time);
input.sound_timer.set_timer(new_value as i32); input.sound_timer.set_timer(new_value as i32);
} }
Chip8CpuInstructions::ADDI(x) => { Chip8CpuInstructions::ADDI(x) => {
@ -1022,7 +1020,7 @@ impl Chip8CpuInstructions {
// //
// The values of I and Vx are added, and the results are stored in I. // The values of I and Vx are added, and the results are stored in I.
let base = input.registers.peek_i(); let base = input.registers.peek_i();
let x_value = input.registers.peek(*x as u8); let x_value = input.registers.peek(*x);
input.registers.poke_i(base + x_value as u16); input.registers.poke_i(base + x_value as u16);
} }
Chip8CpuInstructions::LDFX(x) => { Chip8CpuInstructions::LDFX(x) => {
@ -1036,7 +1034,7 @@ impl Chip8CpuInstructions {
let x_value: u8 = input.registers.peek(*x); let x_value: u8 = input.registers.peek(*x);
let real_offset = x_value as u16 * 5; let real_offset = x_value as u16 * 5;
input.registers.poke_i(real_offset as u16); input.registers.poke_i(real_offset);
} }
Chip8CpuInstructions::BCD(x) => { Chip8CpuInstructions::BCD(x) => {
// Fx33 - LD B, Vx // Fx33 - LD B, Vx
@ -1046,7 +1044,7 @@ impl Chip8CpuInstructions {
// digit in memory at location in I, the tens digit at location I+1, // digit in memory at location in I, the tens digit at location I+1,
// and the ones digit at location I+2. // and the ones digit at location I+2.
let to_convert = input.registers.peek(*x as u8); let to_convert = input.registers.peek(*x);
// how many hundreds // how many hundreds
let hundreds = to_convert / 100; let hundreds = to_convert / 100;
@ -1070,7 +1068,7 @@ impl Chip8CpuInstructions {
// starting at the address in I. // starting at the address in I.
let offset = input.registers.peek_i(); let offset = input.registers.peek_i();
for i in 0..=*x { for i in 0..=*x {
input.memory.poke(offset + i as u16, input.registers.peek(i as u8)); input.memory.poke(offset + i as u16, input.registers.peek(i));
} }
input.registers.poke_i(offset + 1); input.registers.poke_i(offset + 1);
} }
@ -1084,7 +1082,7 @@ impl Chip8CpuInstructions {
debug!("WILL READ {num_loops:x} BYTES"); debug!("WILL READ {num_loops:x} BYTES");
for index in 0..num_loops { for index in 0..num_loops {
let src_value = input.memory.peek(index as u16 + offset); let src_value = input.memory.peek(index as u16 + offset);
input.registers.poke(index as u8, src_value); input.registers.poke(index, src_value);
debug!("POKING Register 0x{index:02x} with 0x{src_value:04x} using offset 0x{offset:04x}"); debug!("POKING Register 0x{index:02x} with 0x{src_value:04x} using offset 0x{offset:04x}");
} }
input.registers.poke_i(offset + 1); input.registers.poke_i(offset + 1);

View File

@ -1,6 +1,7 @@
use crate::constants::CHIP8_KEYBOARD; use crate::constants::CHIP8_KEYBOARD;
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
#[derive(Default)]
pub struct Keypad { pub struct Keypad {
keys: [bool; 0x10], keys: [bool; 0x10],
} }
@ -30,13 +31,6 @@ impl Keypad {
} }
} }
impl Default for Keypad {
fn default() -> Self {
Keypad {
keys: [ false; 16]
}
}
}
impl Keypad { impl Keypad {
pub fn push_key(&mut self, key_index: u8) { pub fn push_key(&mut self, key_index: u8) {

View File

@ -5,6 +5,12 @@ pub struct SoundTimer {
counter: i32 counter: i32
} }
impl Default for SoundTimer {
fn default() -> Self {
Self::new()
}
}
impl SoundTimer { impl SoundTimer {
pub fn current(&self) -> i32 { pub fn current(&self) -> i32 {
self.counter self.counter

View File

@ -1,15 +1,9 @@
#[derive(Clone)] #[derive(Clone)]
#[derive(Default)]
pub struct Chip8Stack { pub struct Chip8Stack {
items: Vec<u16> items: Vec<u16>
} }
impl Default for Chip8Stack {
fn default() -> Self {
Chip8Stack {
items: vec![],
}
}
}
impl Chip8Stack { impl Chip8Stack {
pub fn push(&mut self, new_value: &u16) { pub fn push(&mut self, new_value: &u16) {

View File

@ -15,7 +15,7 @@ impl InstructionUtil {
for i in 0..to_convert.len() { for i in 0..to_convert.len() {
let new_bit = 0x1 << i; let new_bit = 0x1 << i;
if to_convert[i] { if to_convert[i] {
return_value = return_value | new_bit return_value |= new_bit
} }
} }
return_value return_value
@ -29,8 +29,8 @@ impl InstructionUtil {
} }
pub fn join_bytes(high: u8, low: u8) -> u16 { pub fn join_bytes(high: u8, low: u8) -> u16 {
let result = (high as u16) << 8 | low as u16;
result (high as u16) << 8 | low as u16
} }
// nnn or addr - A 12-bit value, the lowest 12 bits of the instruction // nnn or addr - A 12-bit value, the lowest 12 bits of the instruction

View File

@ -1,5 +1,4 @@
use log::{debug}; use log::{debug};
use crate::chip8::util::InstructionUtil;
use crate::chip8::video::Chip8VideoModes::{HighRes, LowRes}; use crate::chip8::video::Chip8VideoModes::{HighRes, LowRes};
use crate::constants::{CHIP8_VIDEO_HEIGHT, CHIP8_VIDEO_MEMORY, CHIP8_VIDEO_WIDTH, SCHIP_VIDE_MEMORY, SCHIP_VIDEO_HEIGHT, SCHIP_VIDEO_WIDTH}; use crate::constants::{CHIP8_VIDEO_HEIGHT, CHIP8_VIDEO_MEMORY, CHIP8_VIDEO_WIDTH, SCHIP_VIDE_MEMORY, SCHIP_VIDEO_HEIGHT, SCHIP_VIDEO_WIDTH};
@ -86,10 +85,8 @@ impl Chip8Video {
let old_value = self.memory[effective_address as usize]; let old_value = self.memory[effective_address as usize];
let xored_value = new_value ^ old_value; // XOR of the video let xored_value = new_value ^ old_value; // XOR of the video
// if the frame has already changed we dont care if it changed again. // if the frame has already changed we dont care if it changed again.
if !self.has_frame_changed { if !self.has_frame_changed && old_value != xored_value {
if old_value != xored_value { self.has_frame_changed = true
self.has_frame_changed = true
};
} }
// println!("VIDEO POKE COMPLETE WITH {effective_address} SET TO {xored_value}"); // println!("VIDEO POKE COMPLETE WITH {effective_address} SET TO {xored_value}");
@ -164,7 +161,7 @@ impl Chip8Video {
for current_row in 0..height { for current_row in 0..height {
let row_offset = current_row * width; let row_offset = current_row * width;
for current_column in (0..width - 4) { for current_column in 0..width - 4 {
let source: usize = (row_offset + current_column) as usize; let source: usize = (row_offset + current_column) as usize;
let target: usize = source + 4; let target: usize = source + 4;
self.memory[target] = self.memory[source]; self.memory[target] = self.memory[source];
@ -184,7 +181,7 @@ impl Chip8Video {
let max_source_row = height - how_far; let max_source_row = height - how_far;
for current_source_row in (0..max_source_row).rev() { for current_source_row in (0..max_source_row).rev() {
let current_source_offset = current_source_row * width; let current_source_offset = current_source_row * width;
for current_source_column in (0..width) { for current_source_column in 0..width {
let base_offset: usize = (current_source_offset + current_source_column) as usize; let base_offset: usize = (current_source_offset + current_source_column) as usize;
let extended_offset: usize = base_offset + row_shift as usize; let extended_offset: usize = base_offset + row_shift as usize;
self.memory[extended_offset] = self.memory[base_offset]; self.memory[extended_offset] = self.memory[base_offset];

View File

@ -34,7 +34,7 @@ fn reset_clears_video() {
fn level1_test() { fn level1_test() {
let mut x = Chip8Computer::new(); let mut x = Chip8Computer::new();
let level_1_rom = load_rom("1-chip8-logo.ch8"); let level_1_rom = load_rom("1-chip8-logo.ch8");
x.load_bytes_to_memory(0x200, (&level_1_rom).into()); x.load_bytes_to_memory(0x200, (&level_1_rom));
// run for 0x40 cycles // run for 0x40 cycles
while x.num_cycles < 0x40 { while x.num_cycles < 0x40 {
@ -49,7 +49,7 @@ fn level2_test() {
// Load the IBM rom and run it. // Load the IBM rom and run it.
// it takes 39 cycles to get to the end so lets run it 40. // it takes 39 cycles to get to the end so lets run it 40.
let test_rom_to_run = load_rom("2-ibm-logo.ch8"); let test_rom_to_run = load_rom("2-ibm-logo.ch8");
x.load_bytes_to_memory(0x200, (&test_rom_to_run).into()); x.load_bytes_to_memory(0x200, (&test_rom_to_run));
for _ in 0..40 { for _ in 0..40 {
x.step_system(); x.step_system();
} }
@ -64,7 +64,7 @@ fn level3_test() {
let mut x = Chip8Computer::new(); let mut x = Chip8Computer::new();
x.load_bytes_to_memory( x.load_bytes_to_memory(
0x200, (&load_rom("3-corax+.ch8")).into() 0x200, (&load_rom("3-corax+.ch8"))
); );
for i in 0..0x180 { for i in 0..0x180 {
x.step_system(); x.step_system();
@ -76,7 +76,7 @@ fn level3_test() {
#[test] #[test]
fn rps_test() { fn rps_test() {
let mut x = Chip8Computer::new(); let mut x = Chip8Computer::new();
x.load_bytes_to_memory(0x200, &load_rom("RPS.ch8").into()); x.load_bytes_to_memory(0x200, &load_rom("RPS.ch8"));
for _ in 0..0xF0 { for _ in 0..0xF0 {
x.step_system(); x.step_system();
} }
@ -92,7 +92,7 @@ fn rps_test() {
fn level4_test() { fn level4_test() {
// flags // flags
let mut x = Chip8Computer::new(); let mut x = Chip8Computer::new();
x.load_bytes_to_memory(0x200, &load_rom("4-flags.ch8").into()); x.load_bytes_to_memory(0x200, &load_rom("4-flags.ch8"));
for _ in 0..0x400 { for _ in 0..0x400 {
x.step_system(); x.step_system();
} }

View File

@ -1,12 +1,10 @@
use std::collections::{BTreeMap, BTreeSet};
use log::debug; use log::debug;
use rand::random; use rand::random;
use gemma::chip8::computer::Chip8Computer; use gemma::chip8::computer::Chip8Computer;
use gemma::chip8::delay_timer::DelayTimer; use gemma::chip8::delay_timer::DelayTimer;
use gemma::chip8::instructions::Chip8CpuInstructions; use gemma::chip8::instructions::Chip8CpuInstructions;
use gemma::chip8::instructions::Chip8CpuInstructions::JPA;
use gemma::chip8::keypad::Keypad; use gemma::chip8::keypad::Keypad;
use gemma::chip8::quirk_modes::QuirkMode::{Chip8, SChipModern, XOChip}; use gemma::chip8::quirk_modes::QuirkMode::Chip8;
use gemma::chip8::registers::Chip8Registers; use gemma::chip8::registers::Chip8Registers;
use gemma::chip8::sound_timer::SoundTimer; use gemma::chip8::sound_timer::SoundTimer;
use gemma::chip8::stack::Chip8Stack; use gemma::chip8::stack::Chip8Stack;
@ -300,7 +298,7 @@ fn cls_test() {
Chip8CpuInstructions::CLS.execute(&mut x); Chip8CpuInstructions::CLS.execute(&mut x);
assert_eq!(x.registers.peek_pc(), 0x202); assert_eq!(x.registers.peek_pc(), 0x202);
for i in 0..CHIP8_VIDEO_MEMORY { for i in 0..CHIP8_VIDEO_MEMORY {
assert_eq!(x.video_memory.peek(i as u16), false); assert!(!x.video_memory.peek(i as u16));
} }
// draw some thing to the video memory // draw some thing to the video memory
x.video_memory.poke(0x01, true); x.video_memory.poke(0x01, true);
@ -310,7 +308,7 @@ fn cls_test() {
Chip8CpuInstructions::CLS.execute(&mut x); Chip8CpuInstructions::CLS.execute(&mut x);
for i in 0..CHIP8_VIDEO_MEMORY { for i in 0..CHIP8_VIDEO_MEMORY {
assert_eq!(x.video_memory.peek(i as u16), false); assert!(!x.video_memory.peek(i as u16));
} }
} }
@ -778,7 +776,7 @@ fn keypad_keys_check() {
#[test] #[test]
fn keypad_string_format_test() { fn keypad_string_format_test() {
let mut k = Keypad::new(); let k = Keypad::new();
assert_eq!(k.format_as_string(), read_test_result("gemma_keypad_string_result.asc")); assert_eq!(k.format_as_string(), read_test_result("gemma_keypad_string_result.asc"));
@ -998,7 +996,7 @@ fn video_default_test() {
for i in 0..CHIP8_VIDEO_MEMORY { for i in 0..CHIP8_VIDEO_MEMORY {
assert!(!x.clone().peek(i as u16)); assert!(!x.clone().peek(i as u16));
// then flip the value and test again. // then flip the value and test again.
&x.poke(i as u16, true); x.poke(i as u16, true);
assert!(x.clone().peek(i as u16)); assert!(x.clone().peek(i as u16));
} }
} }
@ -1050,7 +1048,7 @@ fn video_poke_2byte_test() {
let mut expected = String::new(); let mut expected = String::new();
expected = "** **** **** ".to_string() + &*" ".repeat(64 - 16).to_string() + "\n"; expected = "** **** **** ".to_string() + &*" ".repeat(64 - 16).to_string() + "\n";
for i in 0..31 { for i in 0..31 {
expected += &*((&*" ".repeat(64)).to_string() + "\n"); expected += &*((*" ".repeat(64)).to_string() + "\n");
} }
assert_eq!(expected, x.format_as_string()); assert_eq!(expected, x.format_as_string());
@ -1065,7 +1063,7 @@ fn video_poke_multirow_2_byte_sprite() {
fn video_cls_stddef() { fn video_cls_stddef() {
let width = 64; let width = 64;
let height = 32; let height = 32;
let mut initial_memory = vec![]; let initial_memory = vec![];
let mut ws = String::new(); let mut ws = String::new();
let mut set_x = Chip8Video::new(initial_memory.into()); let mut set_x = Chip8Video::new(initial_memory.into());
for cbr in 0..32 { for cbr in 0..32 {
@ -1186,7 +1184,7 @@ fn video_verify_change_registered() {
#[test] #[test]
fn video_write_checkboard() { fn video_write_checkboard() {
let mut v = build_checkerboard(); let v = build_checkerboard();
assert_eq!(v.clone().format_as_string(), read_test_result("test_video_write_checkerboard.asc")); assert_eq!(v.clone().format_as_string(), read_test_result("test_video_write_checkerboard.asc"));
} }
@ -1234,23 +1232,23 @@ fn video_collision_test() {
// set the cell thats already set... // set the cell thats already set...
x.poke(0x00, true); x.poke(0x00, true);
// it becomes unset and theres a frame changed // it becomes unset and theres a frame changed
assert_eq!(false, x.peek(0x00)); assert!(!x.peek(0x00));
assert_eq!(true, x.clone().has_frame_changed); assert!(x.clone().has_frame_changed);
} }
#[test] #[test]
fn video_collision_test2() { fn video_collision_test2() {
let mut x = Chip8Video::default(); let mut x = Chip8Video::default();
x.poke_byte(0x00, 0b11110000); x.poke_byte(0x00, 0b11110000);
assert_eq!(true, x.has_frame_changed); assert!(x.has_frame_changed);
x.tick(); x.tick();
assert_eq!(false, x.has_frame_changed); assert!(!x.has_frame_changed);
// clear the 'has changed' flag // clear the 'has changed' flag
// now set a no-collision value // now set a no-collision value
x.poke_byte(0x00, 0b00001111); x.poke_byte(0x00, 0b00001111);
assert_eq!(true, x.has_frame_changed); assert!(x.has_frame_changed);
} }
#[test] #[test]
@ -1280,7 +1278,7 @@ fn video_scroll_down_10_row_test() {
#[test] #[test]
fn video_high_res_has_right_resolution() { fn video_high_res_has_right_resolution() {
let mut x = build_checkboard_hd(); let x = build_checkboard_hd();
println!("[{}]", x.format_as_string()); println!("[{}]", x.format_as_string());
assert_eq!(read_test_result("test_video_highdef.asc"), x.format_as_string()); assert_eq!(read_test_result("test_video_highdef.asc"), x.format_as_string());
} }

View File

@ -1,9 +1,8 @@
use std::path::PathBuf; use std::path::PathBuf;
use std::time::Instant; use std::time::Instant;
use crate::support::gemma_egui_support::{EGuiFileList, GemmaEguiSupport}; use crate::support::gemma_egui_support::{EGuiFileList, GemmaEguiSupport};
use crate::support::gemma_egui_state::GemmaEGuiState;
use eframe::egui; use eframe::egui;
use egui::{Key, Ui}; use egui::Key;
use gemma::chip8::computer::Chip8Computer; use gemma::chip8::computer::Chip8Computer;
use gemma::chip8::computer_manager::Chip8ComputerManager; use gemma::chip8::computer_manager::Chip8ComputerManager;
@ -58,7 +57,7 @@ fn main() -> eframe::Result {
}; };
eframe::run_simple_native("EGUI Gemma", options, move |ctx, _frame| { eframe::run_simple_native("EGUI Gemma", options, move |ctx, _frame| {
catppuccin_egui::set_theme(&ctx, catppuccin_egui::MOCHA); catppuccin_egui::set_theme(ctx, catppuccin_egui::MOCHA);
egui::CentralPanel::default().show(ctx, |ui| { egui::CentralPanel::default().show(ctx, |ui| {
let frame_start_time = Instant::now(); let frame_start_time = Instant::now();
@ -70,11 +69,11 @@ fn main() -> eframe::Result {
ui.heading("EGUI Gemma"); ui.heading("EGUI Gemma");
// if state.display_memory { // if state.display_memory {
GemmaEguiSupport::memory_view(&local_computer, ui); GemmaEguiSupport::memory_view(local_computer, ui);
// } // }
// if state.display_registers { // if state.display_registers {
GemmaEguiSupport::registers_view(&local_computer, ui); GemmaEguiSupport::registers_view(local_computer, ui);
// } // }
ui.with_layout(egui::Layout::left_to_right(egui::Align::TOP), |ui| { ui.with_layout(egui::Layout::left_to_right(egui::Align::TOP), |ui| {
if ui.button("Start").clicked() { if ui.button("Start").clicked() {
@ -100,7 +99,7 @@ fn main() -> eframe::Result {
computer.load_bytes_to_system_memory(read_bin); computer.load_bytes_to_system_memory(read_bin);
}; };
EGuiFileList::display_path(PathBuf::from("resources/roms"), &mut state.selected_filename, ui); EGuiFileList::display_path(PathBuf::from("resources/roms"), &mut state.selected_filename, ui);
let input = ctx.input(|input| { ctx.input(|input| {
// loop through the keys we are checking... // loop through the keys we are checking...
for row in LIN_KEYS { for row in LIN_KEYS {
for (keyboard_key, keypad_key) in row { for (keyboard_key, keypad_key) in row {

View File

@ -1,13 +1,9 @@
use std::fs::read_dir; use std::fs::read_dir;
use std::ops::Index; use std::path::PathBuf;
use std::path::{Display, PathBuf}; use egui::{Align, Color32, ComboBox, Pos2, TextBuffer};
use std::thread;
use std::time::Duration;
use egui::{Align, Color32, ComboBox, Direction, Pos2, Response, TextBuffer};
use egui::Rect; use egui::Rect;
use egui::Vec2; use egui::Vec2;
use egui::Ui; use egui::Ui;
use egui::WidgetType::SelectableLabel;
use crate::Chip8Computer; use crate::Chip8Computer;
const CELL_WIDTH: f32 = 5.0; const CELL_WIDTH: f32 = 5.0;
@ -16,7 +12,7 @@ const CELL_HEIGHT: f32 = 5.0;
pub struct EGuiFileList {} pub struct EGuiFileList {}
impl EGuiFileList { impl EGuiFileList {
pub fn display_path(root: PathBuf, selected_filename: &mut String, ui: &mut Ui) { pub fn display_path(root: PathBuf, selected_filename: &mut String, ui: &mut Ui) {
let mut working_filename = selected_filename.clone(); let working_filename = selected_filename.clone();
ui.with_layout(egui::Layout::left_to_right(egui::Align::TOP), |ui| { ui.with_layout(egui::Layout::left_to_right(egui::Align::TOP), |ui| {
// ui.label(format!("Displaying {}", root.to_str().unwrap_or("Unable to Load Path"))); // ui.label(format!("Displaying {}", root.to_str().unwrap_or("Unable to Load Path")));
ComboBox::from_label("Select ROM") ComboBox::from_label("Select ROM")

View File

@ -1,20 +1,7 @@
use std::default::Default; use std::default::Default;
use std::fs::DirEntry;
use std::time::Instant; use std::time::Instant;
use gemma::{
chip8::computer::Chip8Computer,
constants::{CHIP8_MEMORY_SIZE, CHIP8_VIDEO_HEIGHT, CHIP8_VIDEO_WIDTH},
};
use imgui::*;
use sys::{ImColor, ImVec2, ImVector_ImU32};
use rand::random;
use gemma::chip8::computer_manager::Chip8ComputerManager; use gemma::chip8::computer_manager::Chip8ComputerManager;
use gemma::chip8::cpu_states::Chip8CpuStates::WaitingForInstruction;
use gemma::chip8::system_memory::Chip8SystemMemory;
use support::{emmagui_support::GemmaImguiSupport, ui_state::ImGuiUiState}; use support::{emmagui_support::GemmaImguiSupport, ui_state::ImGuiUiState};
use clap::{Parser, Subcommand};
use gemma::chip8::quirk_modes::QuirkMode;
use gemma::chip8::quirk_modes::QuirkMode::Chip8;
mod support; mod support;
@ -78,22 +65,22 @@ fn main() {
} }
// GUI Parts // GUI Parts
if ui_state.show_video { if ui_state.show_video {
GemmaImguiSupport::video_display(&system.state(), &ui_state, ui); GemmaImguiSupport::video_display(system.state(), &ui_state, ui);
} }
GemmaImguiSupport::system_controls(&mut system, &mut ui_state, ui); GemmaImguiSupport::system_controls(&mut system, &mut ui_state, ui);
if ui_state.show_registers { if ui_state.show_registers {
GemmaImguiSupport::registers_view(&system.state(), ui); GemmaImguiSupport::registers_view(system.state(), ui);
} }
if ui_state.show_memory { if ui_state.show_memory {
let active_instruction = system.state().registers.peek_pc(); let active_instruction = system.state().registers.peek_pc();
GemmaImguiSupport::hex_memory_display(system.state().memory.clone(), (0x100, 0x10), active_instruction as i16, ui); GemmaImguiSupport::hex_memory_display(system.state().memory, (0x100, 0x10), active_instruction as i16, ui);
} }
if ui_state.show_keypad { if ui_state.show_keypad {
GemmaImguiSupport::keypad_display(&system.state(), ui); GemmaImguiSupport::keypad_display(system.state(), ui);
} }
}); });
} }

View File

@ -1,20 +1,15 @@
use std::ffi::OsString;
use gemma::constants::CHIP8_KEYBOARD; use gemma::constants::CHIP8_KEYBOARD;
use std::fs::{File, read_dir}; use std::fs::File;
use std::io::Read; use std::io::Read;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::time::Duration;
use imgui::{Condition, ImColor32, Ui}; use imgui::{Condition, ImColor32, Ui};
use log::debug; use log::debug;
use gemma::chip8::computer::Chip8Computer; use gemma::chip8::computer::Chip8Computer;
use gemma::chip8::computer_manager::Chip8ComputerManager; use gemma::chip8::computer_manager::Chip8ComputerManager;
use gemma::chip8::computer_manager::ManagerDumpables::{Keyboard, Registers, Video}; use gemma::chip8::computer_manager::ManagerDumpables::{Keyboard, Registers, Video};
use gemma::chip8::keypad::Keypad;
use gemma::chip8::system_memory::Chip8SystemMemory; use gemma::chip8::system_memory::Chip8SystemMemory;
use gemma::constants::{CHIP8_VIDEO_HEIGHT, CHIP8_VIDEO_WIDTH};
use crate::ImGuiUiState; use crate::ImGuiUiState;
use crate::support::gui_file_list::GuiFileList; use crate::support::gui_file_list::GuiFileList;
use super::ui_state;
const ROM_ROOT: &str = "/home/tmerritt/Projects/chip8_toy/resources/roms"; const ROM_ROOT: &str = "/home/tmerritt/Projects/chip8_toy/resources/roms";
@ -25,7 +20,7 @@ const CELL_HEIGHT: i32 = 5i32;
impl GemmaImguiSupport { impl GemmaImguiSupport {
pub fn keypad_display(system_to_display: &Chip8Computer, ui: &Ui) { pub fn keypad_display(system_to_display: &Chip8Computer, ui: &Ui) {
ui.window(format!("Keypad")) ui.window("Keypad".to_string())
.size([100.0, 100.0], Condition::FirstUseEver) .size([100.0, 100.0], Condition::FirstUseEver)
.build(|| { .build(|| {
for row in CHIP8_KEYBOARD { for row in CHIP8_KEYBOARD {
@ -35,7 +30,7 @@ impl GemmaImguiSupport {
} else { } else {
format!("{:1x}", key) format!("{:1x}", key)
}; };
ui.text(format!("{}", label)); ui.text(&label);
ui.same_line(); ui.same_line();
} }
ui.text(""); ui.text("");

View File

@ -20,8 +20,8 @@ impl GuiFileList {
known_files.sort(); known_files.sort();
for (index, entry) in known_files.iter().enumerate() { for (index, entry) in known_files.iter().enumerate() {
let mut working_select = ui.selectable_config(format!("{}", entry.clone().into_string().unwrap())); let mut working_select = ui.selectable_config(entry.clone().into_string().unwrap().to_string());
if entry.to_str().unwrap().to_string() == selected_filename.as_str().to_string() { if *entry.to_str().unwrap() == *selected_filename.as_str() {
working_select = working_select.selected(true); working_select = working_select.selected(true);
} }
if working_select.build() { if working_select.build() {

View File

@ -37,7 +37,7 @@ async fn run() -> anyhow::Result<String> {
let mut event_pump = sdl.event_pump().map_err(|e| anyhow::anyhow!("Failed to get SDL event pump: {}", e))?; let mut event_pump = sdl.event_pump().map_err(|e| anyhow::anyhow!("Failed to get SDL event pump: {}", e))?;
// Initial settings // Initial settings
let mut color = [0.0, 0.0, 0.0, 1.0]; // Background color let color = [0.0, 0.0, 0.0, 1.0]; // Background color
let start_time = Instant::now(); let start_time = Instant::now();
let mut timestep = TimeStep::new(); let mut timestep = TimeStep::new();

View File

@ -1,13 +1,9 @@
use std::fs::read_dir; use std::fs::read_dir;
use std::ops::Index; use std::path::PathBuf;
use std::path::{Display, PathBuf}; use egui::{Align, Color32, ComboBox, Pos2, TextBuffer};
use std::thread;
use std::time::Duration;
use egui::{Align, Color32, ComboBox, Direction, Pos2, Response, TextBuffer};
use egui::Rect; use egui::Rect;
use egui::Vec2; use egui::Vec2;
use egui::Ui; use egui::Ui;
use egui::WidgetType::SelectableLabel;
use crate::Chip8Computer; use crate::Chip8Computer;
const CELL_WIDTH: f32 = 5.0; const CELL_WIDTH: f32 = 5.0;
@ -16,7 +12,7 @@ const CELL_HEIGHT: f32 = 5.0;
pub struct EGuiFileList {} pub struct EGuiFileList {}
impl EGuiFileList { impl EGuiFileList {
pub fn display_path(root: PathBuf, selected_filename: &mut String, ui: &mut Ui) { pub fn display_path(root: PathBuf, selected_filename: &mut String, ui: &mut Ui) {
let mut working_filename = selected_filename.clone(); let working_filename = selected_filename.clone();
ui.with_layout(egui::Layout::left_to_right(egui::Align::TOP), |ui| { ui.with_layout(egui::Layout::left_to_right(egui::Align::TOP), |ui| {
// ui.label(format!("Displaying {}", root.to_str().unwrap_or("Unable to Load Path"))); // ui.label(format!("Displaying {}", root.to_str().unwrap_or("Unable to Load Path")));
ComboBox::from_label("Select ROM") ComboBox::from_label("Select ROM")
@ -46,7 +42,7 @@ impl EGuiFileList {
pub struct GemmaEguiSupport {} pub struct GemmaEguiSupport {}
impl GemmaEguiSupport { impl GemmaEguiSupport {
pub fn controls_view(mut system: &mut Chip8Computer, ui: &mut Ui) { pub fn controls_view(system: &mut Chip8Computer, ui: &mut Ui) {
ui.with_layout(egui::Layout::left_to_right(egui::Align::TOP), |ui| { ui.with_layout(egui::Layout::left_to_right(egui::Align::TOP), |ui| {
if ui.button("Start").clicked() { if ui.button("Start").clicked() {
println!("Start"); println!("Start");

View File

@ -1,7 +1,7 @@
use std::fs::File; use std::fs::File;
use std::io; use std::io;
use std::io::{BufReader, Read}; use std::io::{BufReader, Read};
use clap::{Arg, Command, ArgAction, ValueEnum}; use clap::{Arg, Command};
#[derive(Debug)] #[derive(Debug)]
struct CliArgs { struct CliArgs {

View File

@ -14,8 +14,6 @@ pub struct Chip8AsmParser;
fn main() { fn main() {
println!("Taxation is Theft"); println!("Taxation is Theft");
let unparsed = fs::read_to_string("resources/test/gemma_disassembler_1_chip_logo_ch8_asm.asc").expect("Unable to read input"); let unparsed = fs::read_to_string("resources/test/gemma_disassembler_1_chip_logo_ch8_asm.asc").expect("Unable to read input");
let file = Chip8AsmParser::parse(Rule::file, &unparsed).expect("Unable to parse. Try again.") let file = Chip8AsmParser::parse(Rule::file, &unparsed).expect("Unable to parse. Try again.")
@ -34,7 +32,8 @@ fn main() {
} }
mod test { mod test {
use super::*; use pest::Parser;
use crate::{Chip8AsmParser, Rule};
#[test] #[test]
fn bits_all_parse() { fn bits_all_parse() {