scroll down works on CHIP-8 and High-Res modes
scroll left and right work in stdef and hidef adds octo test roms adds schip fonts to memory
This commit is contained in:
@@ -44,6 +44,7 @@ impl Chip8Computer {
|
||||
self.registers.reset();
|
||||
self.delay_timer.reset();
|
||||
self.sound_timer.reset();
|
||||
self.stack.reset();
|
||||
}
|
||||
|
||||
pub fn dump_keypad_to_string(&self) -> String {
|
||||
@@ -55,7 +56,7 @@ impl Chip8Computer {
|
||||
}
|
||||
|
||||
pub fn dump_video_to_string(&self) -> String {
|
||||
self.video_memory.format_as_string()
|
||||
self.clone().video_memory.format_as_string()
|
||||
}
|
||||
|
||||
pub fn new_with_program(new_program: Vec<u16>) -> Self {
|
||||
|
||||
@@ -5,14 +5,12 @@ use std::time::{Duration, Instant};
|
||||
use crate::chip8::computer::Chip8Computer;
|
||||
use crate::chip8::cpu_states::Chip8CpuStates;
|
||||
use crate::chip8::cpu_states::Chip8CpuStates::WaitingForInstruction;
|
||||
|
||||
pub enum ManagerDumpables {
|
||||
Video,
|
||||
Registers,
|
||||
Keyboard
|
||||
}
|
||||
|
||||
|
||||
pub struct Chip8ComputerManager {
|
||||
core_should_run: bool,
|
||||
one_step: bool,
|
||||
@@ -76,7 +74,7 @@ impl Chip8ComputerManager {
|
||||
WaitingForInstruction => {
|
||||
self.core_last_cycle_start = Instant::now();
|
||||
self.computer.step_system();
|
||||
println!("SYSTEM STEP");
|
||||
// println!("SYSTEM STEP");
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
@@ -880,25 +880,27 @@ impl Chip8CpuInstructions {
|
||||
}
|
||||
Chip8CpuInstructions::XXXXERRORINSTRUCTION => {}
|
||||
Chip8CpuInstructions::SDN(x) => {
|
||||
println!("SCROLLING DOWN {x} LINES");
|
||||
input.video_memory.scroll_down(*x as i32);
|
||||
}
|
||||
Chip8CpuInstructions::SRT => {
|
||||
println!("SCROLING RIGHT 4 LINES");
|
||||
input.video_memory.scroll_right();
|
||||
}
|
||||
Chip8CpuInstructions::SLF => {
|
||||
println!("SCROLLING LEFT 4 LINES");
|
||||
input.video_memory.scroll_left();
|
||||
}
|
||||
Chip8CpuInstructions::DIS => {
|
||||
println!("DISABLE VIDEO MODE");
|
||||
input.video_memory.set_lowres();
|
||||
}
|
||||
Chip8CpuInstructions::ENA => {
|
||||
println!("ENABLE VIDEO MODE");
|
||||
input.video_memory.set_highres();
|
||||
}
|
||||
Chip8CpuInstructions::EXIT => {
|
||||
println!("EXIT INTERPRETER");
|
||||
}
|
||||
Chip8CpuInstructions::LDF2(x) => {
|
||||
println!("POINTING TO FONT AT {x:02x}");
|
||||
// base = 0x100 + 0x0A*X
|
||||
input.registers.poke_i(0x100 + (0xA * x) as u16);
|
||||
}
|
||||
Chip8CpuInstructions::STR(x) => {
|
||||
println!("STORING FROM RPL FOR {x}");
|
||||
@@ -922,7 +924,7 @@ impl Chip8CpuInstructions {
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use crate::chip8::system_memory::{CHIP8FONT_0, CHIP8FONT_1, CHIP8FONT_2, CHIP8FONT_9};
|
||||
use crate::chip8::system_memory::{*};
|
||||
use crate::constants::CHIP8_VIDEO_MEMORY;
|
||||
use super::*;
|
||||
|
||||
|
||||
@@ -34,6 +34,10 @@ impl Chip8Stack {
|
||||
items: vec![]
|
||||
}
|
||||
}
|
||||
|
||||
pub fn reset(&mut self) {
|
||||
self.items = vec![]
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
@@ -1,24 +1,6 @@
|
||||
use log::{trace};
|
||||
|
||||
use crate::constants::{CHIP8_MEMORY_SIZE};
|
||||
|
||||
pub const CHIP8_PROGRAM_LOAD_OFFSET: i32 = 0x200;
|
||||
pub const CHIP8FONT_0: [u8; 5] = [0xF0, 0x90, 0x90, 0x90, 0xF0];
|
||||
pub const CHIP8FONT_1: [u8; 5] = [0x20, 0x60, 0x20, 0x20, 0x70];
|
||||
pub const CHIP8FONT_2: [u8; 5] = [0xF0, 0x10, 0xF0, 0x80, 0xF0];
|
||||
pub const CHIP8FONT_3: [u8; 5] = [0xF0, 0x10, 0xF0, 0x10, 0xF0];
|
||||
pub const CHIP8FONT_4: [u8; 5] = [0x90, 0x90, 0xF0, 0x10, 0x10];
|
||||
pub const CHIP8FONT_5: [u8; 5] = [0xF0, 0x80, 0xF0, 0x10, 0xF0];
|
||||
pub const CHIP8FONT_6: [u8; 5] = [0xF0, 0x80, 0xF0, 0x90, 0xF0];
|
||||
pub const CHIP8FONT_7: [u8; 5] = [0xF0, 0x10, 0x20, 0x40, 0x40];
|
||||
pub const CHIP8FONT_8: [u8; 5] = [0xF0, 0x90, 0xF0, 0x90, 0xF0];
|
||||
pub const CHIP8FONT_9: [u8; 5] = [0xF0, 0x90, 0xF0, 0x10, 0xF0];
|
||||
pub const CHIP8FONT_A: [u8; 5] = [0xF0, 0x90, 0xF0, 0x90, 0x90];
|
||||
pub const CHIP8FONT_B: [u8; 5] = [0xE0, 0x90, 0xE0, 0x90, 0xE0];
|
||||
pub const CHIP8FONT_C: [u8; 5] = [0xF0, 0x80, 0x80, 0x80, 0xF0];
|
||||
pub const CHIP8FONT_D: [u8; 5] = [0xE0, 0x90, 0x90, 0x90, 0xE0];
|
||||
pub const CHIP8FONT_E: [u8; 5] = [0xF0, 0x80, 0xF0, 0x80, 0xF0];
|
||||
pub const CHIP8FONT_F: [u8; 5] = [0xF0, 0x80, 0xF0, 0x80, 0x80];
|
||||
use crate::constants::*;
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct Chip8SystemMemory {
|
||||
@@ -33,6 +15,7 @@ impl Default for Chip8SystemMemory {
|
||||
};
|
||||
|
||||
x.load_fonts_to_memory();
|
||||
x.load_schip_fonts_to_memory();
|
||||
x
|
||||
}
|
||||
}
|
||||
@@ -87,6 +70,22 @@ impl Chip8SystemMemory {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn load_schip_fonts_to_memory(&mut self) {
|
||||
let all_font_characters = [
|
||||
SCHIPFONT_0, SCHIPFONT_1, SCHIPFONT_2, SCHIPFONT_3,
|
||||
SCHIPFONT_4, SCHIPFONT_5, SCHIPFONT_6, SCHIPFONT_7,
|
||||
SCHIPFONT_8, SCHIPFONT_9, SCHIPFONT_A, SCHIPFONT_B,
|
||||
SCHIPFONT_C, SCHIPFONT_D, SCHIPFONT_E, SCHIPFONT_F
|
||||
];
|
||||
for (font_index, current_font) in all_font_characters.iter().enumerate() {
|
||||
let base_offset = 0x100;
|
||||
for font_mem_offset in 0..=4 {
|
||||
let real_offset = base_offset + font_index * 0x10 + font_mem_offset;
|
||||
self.poke(real_offset as u16, current_font[font_mem_offset]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
+213
-102
@@ -1,18 +1,18 @@
|
||||
use log::{debug};
|
||||
use crate::chip8::video::Chip8VideoModes::{HighRes, LowRes};
|
||||
use crate::constants::{CHIP8_VIDEO_MEMORY, CHIP8_VIDEO_WIDTH, SCHIP_VIDE_MEMORY};
|
||||
use crate::constants::{CHIP8_VIDEO_HEIGHT, CHIP8_VIDEO_MEMORY, CHIP8_VIDEO_WIDTH, SCHIP_VIDE_MEMORY, SCHIP_VIDEO_HEIGHT, SCHIP_VIDEO_WIDTH};
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
enum Chip8VideoModes {
|
||||
LowRes,
|
||||
HighRes
|
||||
HighRes,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
#[derive(Clone)]
|
||||
pub struct Chip8Video {
|
||||
memory: [bool; CHIP8_VIDEO_MEMORY],
|
||||
memory: Vec<bool>,
|
||||
pub has_frame_changed: bool,
|
||||
current_res: Chip8VideoModes
|
||||
current_res: Chip8VideoModes,
|
||||
}
|
||||
|
||||
impl Chip8Video {
|
||||
@@ -21,13 +21,13 @@ impl Chip8Video {
|
||||
self.start_frame();
|
||||
}
|
||||
|
||||
|
||||
pub fn is_highres(&self) -> bool {
|
||||
matches!(self.current_res, HighRes)
|
||||
}
|
||||
|
||||
pub fn set_highres(&mut self) {
|
||||
self.current_res = HighRes
|
||||
self.current_res = HighRes;
|
||||
self.cls();
|
||||
}
|
||||
|
||||
pub fn set_lowres(&mut self) {
|
||||
@@ -39,14 +39,17 @@ impl Chip8Video {
|
||||
}
|
||||
|
||||
pub fn cls(&mut self) {
|
||||
match self.current_res {
|
||||
self.memory.clear();
|
||||
let num_loops = match self.current_res {
|
||||
LowRes => {
|
||||
self.memory = [false; CHIP8_VIDEO_MEMORY];
|
||||
CHIP8_VIDEO_MEMORY
|
||||
}
|
||||
HighRes => {
|
||||
|
||||
// self.memory = [0u8; ]
|
||||
SCHIP_VIDE_MEMORY
|
||||
}
|
||||
};
|
||||
for i in 0..num_loops {
|
||||
self.memory.push(false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,15 +57,15 @@ impl Chip8Video {
|
||||
self.has_frame_changed = false;
|
||||
}
|
||||
|
||||
pub fn new(initial_configuration: [bool; CHIP8_VIDEO_MEMORY]) -> Self {
|
||||
pub fn new(initial_configuration: Box<Vec<bool>>) -> Self {
|
||||
Self {
|
||||
memory: initial_configuration,
|
||||
memory: *initial_configuration,
|
||||
has_frame_changed: false,
|
||||
current_res: Chip8VideoModes::LowRes,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn peek(self, address: u16) -> bool {
|
||||
pub fn peek(&self, address: u16) -> bool {
|
||||
let loop_value: u16 = if self.is_highres() {
|
||||
SCHIP_VIDE_MEMORY as u16
|
||||
} else {
|
||||
@@ -75,12 +78,7 @@ impl Chip8Video {
|
||||
}
|
||||
|
||||
pub fn poke(&mut self, address: u16, new_value: bool) {
|
||||
// println!("OFFSET: {address} - POKING {new_value}");
|
||||
let loop_value: u16 = if self.is_highres() {
|
||||
SCHIP_VIDE_MEMORY as u16
|
||||
} else {
|
||||
CHIP8_VIDEO_MEMORY as u16
|
||||
};
|
||||
let loop_value: u16 = self.get_memory_size() as u16;
|
||||
// Loop the address
|
||||
let effective_address = address % loop_value;
|
||||
|
||||
@@ -93,6 +91,7 @@ impl Chip8Video {
|
||||
};
|
||||
}
|
||||
|
||||
// println!("VIDEO POKE COMPLETE WITH {effective_address} SET TO {xored_value}");
|
||||
self.memory[effective_address as usize] = xored_value;
|
||||
}
|
||||
|
||||
@@ -110,13 +109,15 @@ impl Chip8Video {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn format_as_string(self) -> String {
|
||||
pub fn format_as_string(&self) -> String {
|
||||
let (width, height) = self.get_resolution();
|
||||
println!("FORMATTING {width}x{height}");
|
||||
let mut output = String::new();
|
||||
for row in 0..32 {
|
||||
for column in 0..64 {
|
||||
let data_offset = row * 64 + column;
|
||||
debug!("Rendering {data_offset} with value {}", self.memory[data_offset]);
|
||||
if self.memory[data_offset] {
|
||||
for row in 0..height {
|
||||
for column in 0..width {
|
||||
let data_offset = row * width + column;
|
||||
debug!("Rendering {data_offset} with value {}", self.memory[data_offset as usize]);
|
||||
if self.memory[data_offset as usize] {
|
||||
output += "*"
|
||||
} else {
|
||||
output += " "
|
||||
@@ -124,39 +125,127 @@ impl Chip8Video {
|
||||
}
|
||||
output += "\n";
|
||||
}
|
||||
|
||||
output
|
||||
}
|
||||
|
||||
pub fn get_resolution(&self) -> (i32, i32) {
|
||||
if self.is_highres() {
|
||||
(SCHIP_VIDEO_WIDTH, SCHIP_VIDEO_HEIGHT)
|
||||
} else {
|
||||
(CHIP8_VIDEO_WIDTH, CHIP8_VIDEO_HEIGHT)
|
||||
}
|
||||
}
|
||||
|
||||
fn get_memory_size(&self) -> i32 {
|
||||
let w = self.get_resolution();
|
||||
w.1 * w.0
|
||||
}
|
||||
|
||||
pub fn tick(&mut self) {
|
||||
self.has_frame_changed = false;
|
||||
}
|
||||
|
||||
pub fn scroll_right(&mut self) {
|
||||
let (width, height) = self.get_resolution();
|
||||
|
||||
for current_row in 0..height {
|
||||
let row_offset: usize = (current_row * width) as usize;
|
||||
for current_column in (0..(width - 4)).rev() {
|
||||
let source_address = row_offset + current_column as usize;
|
||||
let target_address = source_address + 4;
|
||||
self.memory[target_address] = self.memory[source_address];
|
||||
}
|
||||
self.memory[row_offset..row_offset + 4].fill(false);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn scroll_left(&mut self) {
|
||||
let (width, height) = self.get_resolution();
|
||||
|
||||
for current_row in 0..height {
|
||||
let row_offset = current_row * width;
|
||||
for current_column in (0..width - 4) {
|
||||
let source: usize = (row_offset + current_column) as usize;
|
||||
let target: usize = source + 4;
|
||||
self.memory[target] = self.memory[source];
|
||||
}
|
||||
|
||||
let clear_start: usize = (row_offset + width - 4) as usize;
|
||||
let clear_end: usize = clear_start + 4;
|
||||
|
||||
self.memory[clear_start..clear_end].fill(false);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn scroll_down(&mut self, how_far: i32) {
|
||||
let (width, height) = self.get_resolution();
|
||||
let row_shift = how_far * width;
|
||||
|
||||
let max_source_row = height - how_far;
|
||||
for current_source_row in (0..max_source_row).rev() {
|
||||
let current_source_offset = current_source_row * width;
|
||||
for current_source_column in (0..width) {
|
||||
let base_offset: usize = (current_source_offset + current_source_column) as usize;
|
||||
let extended_offset: usize = base_offset + row_shift as usize;
|
||||
self.memory[extended_offset] = self.memory[base_offset];
|
||||
};
|
||||
}
|
||||
|
||||
// Clear the new top rows after shifting
|
||||
let clear_end = (how_far * width) as usize;
|
||||
self.memory[0..clear_end].fill(false);
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Chip8Video {
|
||||
fn default() -> Self {
|
||||
Chip8Video { memory: [false; CHIP8_VIDEO_MEMORY], has_frame_changed: false, current_res: Chip8VideoModes::LowRes }
|
||||
let mut mem = vec![];
|
||||
for _ in 0..CHIP8_VIDEO_MEMORY { mem.push(false); }
|
||||
Chip8Video { memory: mem, has_frame_changed: false, current_res: Chip8VideoModes::LowRes }
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use std::io::Read;
|
||||
use crate::chip8::system_memory::{CHIP8FONT_0, CHIP8FONT_1, CHIP8FONT_2, CHIP8FONT_3, CHIP8FONT_4, CHIP8FONT_5, CHIP8FONT_6, CHIP8FONT_7};
|
||||
use crate::constants::*;
|
||||
use super::*;
|
||||
|
||||
const TEST_OUTPUT_SAMPLE_DIR: &str = "../resources/test/";
|
||||
|
||||
fn build_checkerboard() -> Chip8Video {
|
||||
fn real_build_checkboard(in_hd: bool) -> Chip8Video {
|
||||
let mut r = Chip8Video::default();
|
||||
let (width, height) = if in_hd {
|
||||
r.set_highres();
|
||||
(SCHIP_VIDEO_WIDTH, SCHIP_VIDEO_HEIGHT)
|
||||
} else {
|
||||
(CHIP8_VIDEO_WIDTH, CHIP8_VIDEO_HEIGHT)
|
||||
};
|
||||
|
||||
for i in 0..CHIP8_VIDEO_MEMORY {
|
||||
r.poke(i as u16, i % 2 == 0);
|
||||
println!("BUILDING BOARD WITH SIZE OF {width}x{height}");
|
||||
|
||||
for row in 0..height {
|
||||
let data_offset = row * width;
|
||||
|
||||
for col in 0..width {
|
||||
// XOR row and column indices to alternate in a checkerboard pattern
|
||||
let to_poke = (row % 2) ^ (col % 2) == 1;
|
||||
let local_offset: u16 = (data_offset + col) as u16;
|
||||
|
||||
r.poke(local_offset, to_poke);
|
||||
}
|
||||
}
|
||||
|
||||
r
|
||||
}
|
||||
|
||||
fn build_checkboard_hd() -> Chip8Video {
|
||||
real_build_checkboard(true)
|
||||
}
|
||||
|
||||
fn build_checkerboard() -> Chip8Video {
|
||||
real_build_checkboard(false)
|
||||
}
|
||||
|
||||
fn read_test_result(suffix: &str) -> String {
|
||||
std::fs::read_to_string(TEST_OUTPUT_SAMPLE_DIR.to_owned() + suffix)
|
||||
.unwrap()
|
||||
@@ -178,36 +267,7 @@ mod test {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn string_test_1() {
|
||||
let mut x = Chip8Video::default();
|
||||
let mut working_string = String::new();
|
||||
for i in 0..32 {
|
||||
working_string += &*(" ".repeat(64) + "\n");
|
||||
}
|
||||
|
||||
assert_eq!(working_string, x.format_as_string());
|
||||
|
||||
let mut working_string = String::new();
|
||||
// set a checkerboard...
|
||||
for cb_row in 0..32 {
|
||||
for cb_col in 0..64 {
|
||||
let data_offset = cb_row * 64 + cb_col;
|
||||
if data_offset % 2 == 0 {
|
||||
x.poke(data_offset, true);
|
||||
working_string += "*";
|
||||
} else {
|
||||
x.poke(data_offset, false);
|
||||
working_string += " ";
|
||||
}
|
||||
}
|
||||
working_string += "\n";
|
||||
}
|
||||
|
||||
assert_eq!(working_string, x.format_as_string());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn set_initial_memory() {
|
||||
fn set_initial_memory_sd() {
|
||||
let mut x = Chip8Video::default();
|
||||
// let mut initial_memory = [false; CHIP8_VIDEO_MEMORY];
|
||||
let mut ws = String::new();
|
||||
@@ -242,10 +302,10 @@ mod test {
|
||||
|
||||
#[test]
|
||||
fn poke_2byte_test() {
|
||||
let to_poke: [u8; 2] = [
|
||||
0b11001111,
|
||||
0b00111100
|
||||
];
|
||||
let to_poke: [u8; 2] = [
|
||||
0b11001111,
|
||||
0b00111100
|
||||
];
|
||||
|
||||
let mut x = Chip8Video::default();
|
||||
x.poke_2byte(0x00, to_poke);
|
||||
@@ -265,22 +325,18 @@ mod test {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cls() {
|
||||
let mut initial_memory = [false; CHIP8_VIDEO_MEMORY];
|
||||
fn cls_stddef() {
|
||||
let width = 64;
|
||||
let height = 32;
|
||||
let mut initial_memory = vec![];
|
||||
let mut ws = String::new();
|
||||
|
||||
let mut set_x = Chip8Video::new(initial_memory.into());
|
||||
for cbr in 0..32 {
|
||||
for cbc in 0..64 {
|
||||
let dof = cbr * 64 + cbc;
|
||||
if (dof as i32 % 2) == 0 {
|
||||
initial_memory[dof] = true;
|
||||
}
|
||||
ws += " ";
|
||||
}
|
||||
ws += &*" ".repeat(width);
|
||||
ws += "\n";
|
||||
}
|
||||
let mut set_x = Chip8Video::new(initial_memory);
|
||||
set_x.cls();
|
||||
|
||||
assert_eq!(set_x.format_as_string(), ws);
|
||||
}
|
||||
|
||||
@@ -289,16 +345,16 @@ mod test {
|
||||
let to_poke = 0b10101010;
|
||||
let mut v = Chip8Video::default();
|
||||
v.poke_byte(0x00, to_poke);
|
||||
assert!(v.peek(0x00));
|
||||
assert!(!v.peek(0x01));
|
||||
assert!(v.peek(0x02));
|
||||
assert!(!v.peek(0x03));
|
||||
assert!(v.peek(0x04));
|
||||
assert!(!v.peek(0x05));
|
||||
assert!(v.peek(0x06));
|
||||
assert!(!v.peek(0x07));
|
||||
assert!(v.clone().peek(0x00));
|
||||
assert!(!v.clone().peek(0x01));
|
||||
assert!(v.clone().peek(0x02));
|
||||
assert!(!v.clone().peek(0x03));
|
||||
assert!(v.clone().peek(0x04));
|
||||
assert!(!v.clone().peek(0x05));
|
||||
assert!(v.clone().peek(0x06));
|
||||
assert!(!v.clone().peek(0x07));
|
||||
for i in 0x8..CHIP8_VIDEO_MEMORY {
|
||||
assert!(!v.peek(i as u16));
|
||||
assert!(!v.clone().peek(i as u16));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -329,7 +385,7 @@ mod test {
|
||||
assert!(v.clone().peek(0x47));
|
||||
|
||||
// row 3 column 1
|
||||
assert!(!v.peek(0xC0));
|
||||
assert!(!v.clone().peek(0xC0));
|
||||
assert!(v.clone().peek(0xC1));
|
||||
assert!(!v.clone().peek(0xC2));
|
||||
assert!(v.clone().peek(0xC3));
|
||||
@@ -360,7 +416,7 @@ mod test {
|
||||
}
|
||||
|
||||
let test_offset = (x_offset * 64 + y_offset) as u16;
|
||||
assert!(!v.peek(test_offset));
|
||||
assert!(!v.clone().peek(test_offset));
|
||||
assert!(!v.clone().peek(test_offset + 1));
|
||||
assert!(!v.clone().peek(test_offset + 2));
|
||||
assert!(!v.clone().peek(test_offset + 3));
|
||||
@@ -394,8 +450,7 @@ mod test {
|
||||
#[test]
|
||||
fn write_checkboard() {
|
||||
let mut v = build_checkerboard();
|
||||
|
||||
assert_eq!(v.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"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -426,16 +481,7 @@ mod test {
|
||||
|
||||
#[test]
|
||||
fn reset_test() {
|
||||
let mut x = Chip8Video::default();
|
||||
|
||||
let to_draw = [CHIP8FONT_0, CHIP8FONT_1, CHIP8FONT_2, CHIP8FONT_3, CHIP8FONT_4, CHIP8FONT_5, CHIP8FONT_6, CHIP8FONT_7];
|
||||
for (index, sprite) in to_draw.iter().enumerate() {
|
||||
let data_base_offset = index * 0x8;
|
||||
for (index, offset) in (0..=0x100).step_by(0x40).enumerate() {
|
||||
x.poke_byte((data_base_offset + offset) as u16, sprite[index]);
|
||||
}
|
||||
}
|
||||
|
||||
let mut x = build_checkerboard();
|
||||
x.reset();
|
||||
assert_eq!(x.format_as_string(), read_test_result("test_reset_clears_video.asc"));
|
||||
}
|
||||
@@ -453,7 +499,7 @@ mod test {
|
||||
// it becomes unset and theres a frame changed
|
||||
assert_eq!(false, x.peek(0x00));
|
||||
|
||||
assert_eq!(true, x.has_frame_changed);
|
||||
assert_eq!(true, x.clone().has_frame_changed);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -481,5 +527,70 @@ mod test {
|
||||
assert!(true);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn scroll_down_1_row_test() {
|
||||
let mut x = build_checkerboard();
|
||||
x.scroll_down(1);
|
||||
assert_eq!(read_test_result("test_video_scroll_down_1.asc"), x.format_as_string());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn scroll_down_10_row_test() {
|
||||
let mut x = build_checkerboard();
|
||||
x.scroll_down(10);
|
||||
assert_eq!(read_test_result("test_video_scroll_down_10.asc"), x.format_as_string());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn high_res_has_right_resolution() {
|
||||
let mut x = build_checkboard_hd();
|
||||
println!("[{}]", x.format_as_string());
|
||||
assert_eq!(read_test_result("test_video_highdef.asc"), x.format_as_string());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn scroll_down_1_row_test_schip() {
|
||||
let mut x = build_checkboard_hd();
|
||||
x.scroll_down(1);
|
||||
|
||||
println!("[{}]", x.format_as_string());
|
||||
println!("[{}]", read_test_result("test_scroll_down_1_hd.asc"));
|
||||
|
||||
assert_eq!(read_test_result("test_scroll_down_1_hd.asc"), x.format_as_string());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn scroll_down_10_row_test_schip() {
|
||||
let mut x = build_checkboard_hd();
|
||||
x.scroll_down(10);
|
||||
assert_eq!(read_test_result("test_scroll_down_10_hd.asc"), x.format_as_string());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn scroll_left_4_row_test_std_def() {
|
||||
let mut x = build_checkerboard();
|
||||
x.scroll_left();
|
||||
assert_eq!(read_test_result("test_scroll_left_4.asc"), x.format_as_string());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn scroll_left_4_row_test_high_def() {
|
||||
let mut x = build_checkboard_hd();
|
||||
x.scroll_left();
|
||||
assert_eq!(read_test_result("test_scroll_left_4_hd.asc"), x.format_as_string());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn scroll_right_4_row_test_std_def() {
|
||||
let mut x = build_checkerboard();
|
||||
x.scroll_right();
|
||||
assert_eq!(read_test_result("test_scroll_right_4.asc"), x.format_as_string());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn scroll_right_4_row_test_high_def() {
|
||||
let mut x = build_checkboard_hd();
|
||||
x.scroll_right();
|
||||
assert_eq!(read_test_result("test_scroll_right_4_hd.asc"), x.format_as_string());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,3 +63,65 @@ pub const INST_ORY: &str = "ORY";
|
||||
|
||||
|
||||
|
||||
pub const CHIP8_PROGRAM_LOAD_OFFSET: i32 = 0x200;
|
||||
pub const CHIP8FONT_0: [u8; 5] = [0xF0, 0x90, 0x90, 0x90, 0xF0];
|
||||
pub const CHIP8FONT_1: [u8; 5] = [0x20, 0x60, 0x20, 0x20, 0x70];
|
||||
pub const CHIP8FONT_2: [u8; 5] = [0xF0, 0x10, 0xF0, 0x80, 0xF0];
|
||||
pub const CHIP8FONT_3: [u8; 5] = [0xF0, 0x10, 0xF0, 0x10, 0xF0];
|
||||
pub const CHIP8FONT_4: [u8; 5] = [0x90, 0x90, 0xF0, 0x10, 0x10];
|
||||
pub const CHIP8FONT_5: [u8; 5] = [0xF0, 0x80, 0xF0, 0x10, 0xF0];
|
||||
pub const CHIP8FONT_6: [u8; 5] = [0xF0, 0x80, 0xF0, 0x90, 0xF0];
|
||||
pub const CHIP8FONT_7: [u8; 5] = [0xF0, 0x10, 0x20, 0x40, 0x40];
|
||||
pub const CHIP8FONT_8: [u8; 5] = [0xF0, 0x90, 0xF0, 0x90, 0xF0];
|
||||
pub const CHIP8FONT_9: [u8; 5] = [0xF0, 0x90, 0xF0, 0x10, 0xF0];
|
||||
pub const CHIP8FONT_A: [u8; 5] = [0xF0, 0x90, 0xF0, 0x90, 0x90];
|
||||
pub const CHIP8FONT_B: [u8; 5] = [0xE0, 0x90, 0xE0, 0x90, 0xE0];
|
||||
pub const CHIP8FONT_C: [u8; 5] = [0xF0, 0x80, 0x80, 0x80, 0xF0];
|
||||
pub const CHIP8FONT_D: [u8; 5] = [0xE0, 0x90, 0x90, 0x90, 0xE0];
|
||||
pub const CHIP8FONT_E: [u8; 5] = [0xF0, 0x80, 0xF0, 0x80, 0xF0];
|
||||
pub const CHIP8FONT_F: [u8; 5] = [0xF0, 0x80, 0xF0, 0x80, 0x80];
|
||||
|
||||
|
||||
pub const SCHIPFONT_0: [u8; 0x10] = [0xF0, 0xFC, 0xFE, 0xFF, 0xF3, 0xE1, 0xE0, 0xE0,
|
||||
0xE0, 0xE0, 0xE0, 0xF1, 0xFB, 0xFF, 0xFE, 0x7C];
|
||||
pub const SCHIPFONT_1: [u8; 0x10] = [0x18, 0x3C, 0x7E, 0xFF, 0xF7, 0xE3, 0xC1, 0xC0,
|
||||
0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0
|
||||
];
|
||||
pub const SCHIPFONT_2: [u8; 0x10] = [0x7C, 0xFE, 0xFF, 0xFF, 0xC7, 0xC3, 0xC0, 0xE0,
|
||||
0xF0, 0x78, 0x3C, 0x1E, 0x0F, 0x07, 0xFF, 0xFF
|
||||
];
|
||||
pub const SCHIPFONT_3: [u8; 0x10] = [0x7C, 0xFE, 0xFF, 0xFF, 0xC7, 0xC3, 0xC0, 0xE0,
|
||||
0xF0, 0x78, 0x3C, 0x1E, 0x0F, 0x07, 0xFF, 0xFF];
|
||||
pub const SCHIPFONT_4: [u8; 0x10] = [0xE0, 0xF0, 0xF8, 0xFC, 0xFE, 0xF7, 0xF3, 0xF1,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0xC0, 0xC0, 0xC0];
|
||||
pub const SCHIPFONT_5: [u8; 0x10] = [0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x3F, 0x7F, 0x7F,
|
||||
0x01, 0x01, 0xC1, 0xE3, 0xFF, 0xFE, 0xFC, 0x78];
|
||||
pub const SCHIPFONT_6: [u8; 0x10] = [0x78, 0xFE, 0xFF, 0xFF, 0x83, 0x01, 0x01, 0xFF,
|
||||
0xFF, 0xFF, 0xC3, 0xE3, 0xFF, 0xFE, 0xFC, 0x78
|
||||
];
|
||||
pub const SCHIPFONT_7: [u8; 0x10] = [0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0xF0, 0x78, 0x3C,
|
||||
0x1E, 0x0F, 0x07, 0x03, 0x01, 0x01, 0x01, 0x01
|
||||
];
|
||||
pub const SCHIPFONT_8: [u8; 0x10] = [0x7C, 0xFE, 0xFF, 0xFF, 0xC3, 0xC3, 0xC3, 0xFF,
|
||||
0x7E, 0xFE, 0xC3, 0xC3, 0xFF, 0xFF, 0xFE, 0x7C
|
||||
];
|
||||
pub const SCHIPFONT_9: [u8; 0x10] = [0x7C, 0xFE, 0xFF, 0xFF, 0xC3, 0xC3, 0xC3, 0xFF,
|
||||
0xFF, 0x7F, 0x03, 0x03, 0xC7, 0xFF, 0xFE, 0x7C
|
||||
];
|
||||
pub const SCHIPFONT_A: [u8; 0x10] = [0x7C, 0xFE, 0xFF, 0xFF, 0xC3, 0xC3, 0xC3, 0xFF,
|
||||
0xFF, 0xFF, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3
|
||||
];
|
||||
pub const SCHIPFONT_B: [u8; 0x10] = [0xFE, 0xFF, 0xFF, 0xFF, 0xC3, 0xC3, 0xFE, 0xFF,
|
||||
0xFF, 0xFF, 0xC3, 0xC3, 0xC3, 0xFF, 0xFF, 0xFE
|
||||
];
|
||||
pub const SCHIPFONT_C: [u8; 0x10] = [0x7C, 0xFE, 0xFF, 0xFF, 0xC3, 0xC3, 0x01, 0x01,
|
||||
0x01, 0x01, 0xC3, 0xC3, 0xFF, 0xFE, 0xFC, 0x78
|
||||
];
|
||||
pub const SCHIPFONT_D: [u8; 0x10] = [0xFE, 0xFF, 0xFF, 0xFF, 0xC3, 0xC3, 0xC3, 0xC3,
|
||||
0xC3, 0xC3, 0xC3, 0xC3, 0xFF, 0xFF, 0xFE, 0x7C
|
||||
];
|
||||
pub const SCHIPFONT_E: [u8; 0x10] = [0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x03, 0x03, 0xFF,
|
||||
0xFF, 0xFF, 0x03, 0x03, 0xFF, 0xFF, 0xFF, 0xFF
|
||||
];
|
||||
pub const SCHIPFONT_F: [u8; 0x10] = [0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x03, 0x03, 0xFF,
|
||||
0xFF, 0xFF, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03];
|
||||
|
||||
Reference in New Issue
Block a user