my first schip rom works in my schip emulator.

BUGFIX: Corrects runaway after drawing in my first schip rom
scroll down, left, right all test with test rom
assembler now assembles to the expected output it seems
fixes incorrect loading of schip font to memory
replaces schip font from new chatgpt feedback
This commit is contained in:
2024-11-05 10:02:19 -05:00
parent 434cf92414
commit 67ca71ccb7
39 changed files with 509 additions and 1052 deletions
+29 -11
View File
@@ -2,7 +2,9 @@ use gemma::chip8::computer::Chip8Computer;
use gemma::constants::CHIP8_VIDEO_MEMORY;
#[test]
fn smoke() { assert!(true) }
fn smoke() {
assert!(true)
}
fn load_result(to_load: &str) -> String {
std::fs::read_to_string(format!("../resources/test/{}", to_load)).unwrap()
@@ -20,7 +22,7 @@ fn reset_clears_video() {
x.video_memory.poke(i as u16, i % 2 == 0);
}
x.reset();
x.reset(gemma::chip8::quirk_modes::QuirkMode::Chip8);
x.video_memory.reset();
assert_eq!(x.dump_video_to_string(), x.video_memory.format_as_string());
@@ -40,7 +42,10 @@ fn level1_test() {
while x.num_cycles < 0x40 {
x.step_system();
}
assert_eq!(x.dump_video_to_string(), load_result("gemma_integration_level_1_test.asc"));
assert_eq!(
x.dump_video_to_string(),
load_result("gemma_integration_level_1_test.asc")
);
}
#[test]
@@ -56,21 +61,25 @@ fn level2_test() {
// ...then verify that the current video memory of the chip-8
// simulator matches what we expect it to be
assert_eq!(x.dump_video_to_string(), load_result("gemma_integration_ibm_rom_output.asc"));
assert_eq!(
x.dump_video_to_string(),
load_result("gemma_integration_ibm_rom_output.asc")
);
}
#[test]
fn level3_test() {
let mut x = Chip8Computer::new();
x.load_bytes_to_memory(
0x200, (&load_rom("3-corax+.ch8"))
);
x.load_bytes_to_memory(0x200, (&load_rom("3-corax+.ch8")));
for i in 0..0x180 {
x.step_system();
}
assert_eq!(x.dump_video_to_string(), load_result("gemma_integration_corax_plus.asc"));
assert_eq!(
x.dump_video_to_string(),
load_result("gemma_integration_corax_plus.asc")
);
}
#[test]
@@ -80,12 +89,18 @@ fn rps_test() {
for _ in 0..0xF0 {
x.step_system();
}
assert_eq!(x.dump_video_to_string(), load_result("gemma_integration_rps_stage1.asc"));
assert_eq!(
x.dump_video_to_string(),
load_result("gemma_integration_rps_stage1.asc")
);
x.keypad.push_key(0x01);
for _ in 0..0x200 {
x.step_system();
}
assert_eq!(x.dump_video_to_string(), load_result("gemma_integration_rps_stage2.asc"));
assert_eq!(
x.dump_video_to_string(),
load_result("gemma_integration_rps_stage2.asc")
);
}
#[test]
@@ -97,5 +112,8 @@ fn level4_test() {
x.step_system();
}
assert_eq!(x.dump_video_to_string(), load_result("gemma_integration_flags.asc"));
assert_eq!(
x.dump_video_to_string(),
load_result("gemma_integration_flags.asc")
);
}
+43 -20
View File
@@ -1,34 +1,55 @@
use flate2::write::{GzEncoder, GzDecoder};
use flate2::write::{GzDecoder, GzEncoder};
use flate2::Compression;
use std::io::prelude::*;
use gemma::chip8::computer::Chip8Computer;
use std::io::prelude::*;
fn load_result(to_load: &str) -> String {
std::fs::read_to_string(format!("resources/test/state/{}", to_load)).unwrap()
let full_path = format!("resources/test/state/{}", to_load);
println!("Loading state => (([{}]))", full_path);
std::fs::read_to_string(full_path).unwrap()
}
fn load_compressed_result(to_load: &str) -> String {
// load the file...
// ...then uncompress the string.
let mut decoder = GzDecoder::new(Vec::new());
decoder.write_all(load_result(to_load).as_ref()).expect("Decompression failed");
let decompressed_data = decoder.finish().expect("Failed to finish decompression");
String::from_utf8(decompressed_data).expect("Invalid UTF-8")
fn load_compressed_result(file_path: &str) -> io::Result<String> {
// Load the compressed file contents
let compressed_data = fs::read(file_path)?;
// Create a GzDecoder to uncompress the data
let mut decoder = GzDecoder::new(&compressed_data[..]);
let mut decompressed_data = String::new();
// Read the decompressed data directly into a String
decoder.read_to_string(&mut decompressed_data)?;
Ok(decompressed_data)
}
fn load_rom(to_load: &str) -> Vec<u8> {
std::fs::read(format!("resources/roms/{}", to_load)).unwrap()
std::fs::read(format!("resources/test/roms/{}", to_load)).unwrap()
}
#[test]
fn smoke_round_trip_serialize_deserialize() {
let x = Chip8Computer::new();
let expected_string = load_result("smoke_001_round_trip_serialize_deserialize.json");
let serialized = serde_json::to_string(&x).unwrap();
let deserialized: Chip8Computer = serde_json::from_str(&expected_string).unwrap();
println!("SERIALIZED [{}]", serialized);
// TODO: using trim here is a hack to handle editors adding a newline at the end of a file...even a 1 line file
assert_eq!(serialized.trim(), expected_string.trim());
assert_eq!(deserialized, x);
fn test_serialization_round_trip() {
let original_computer = Chip8Computer::new();
let expected_json = load_result("smoke_001_round_trip_serialize_deserialize.json");
// Serialize the Chip8Computer instance
let serialized = serde_json::to_string(&original_computer).expect("Serialization failed");
// Compare the serialized output to the expected JSON
println!("Serialized Output: [{}]", serialized);
assert_eq!(
serialized.trim(),
expected_json.trim(),
"Serialized output does not match expected JSON"
);
// Deserialize back to Chip8Computer and assert equality
let deserialized_computer: Chip8Computer =
serde_json::from_str(&serialized).expect("Deserialization failed");
assert_eq!(
deserialized_computer, original_computer,
"Deserialized instance does not match the original"
);
}
#[test]
@@ -36,5 +57,7 @@ fn computer_001_system_zero_state() {
let x = Chip8Computer::new();
let expected_string = load_compressed_result("smoke_002_round_trip_serialize_deserialize.tflt");
let serialized = serde_json::to_string(&x).unwrap();
assert_eq!(serialized, expected_string);
}
}
+25 -1
View File
@@ -4,7 +4,7 @@ use gemma::chip8::delay_timer::DelayTimer;
use gemma::chip8::instructions::Chip8CpuInstructions;
use gemma::chip8::instructions::Chip8CpuInstructions::JPX;
use gemma::chip8::keypad::Keypad;
use gemma::chip8::quirk_modes::QuirkMode::{Chip8, SChipModern, XOChip};
use gemma::chip8::quirk_modes::QuirkMode::{self, Chip8, SChipModern, XOChip};
use gemma::chip8::registers::Chip8Registers;
use gemma::chip8::sound_timer::SoundTimer;
use gemma::chip8::stack::Chip8Stack;
@@ -14,6 +14,7 @@ use gemma::chip8::video::{Chip8Video, Chip8VideoModes};
use gemma::constants::*;
use log::debug;
use rand::random;
use serde::Serialize;
const TEST_OUTPUT_SAMPLE_DIR: &str = "../resources/test/";
@@ -1497,3 +1498,26 @@ fn system_memory_new() {
let x = Chip8SystemMemory::new();
assert!(true);
}
#[test]
fn video_lowres_schip_draw_chip8_sprite() {
let mut x = Chip8Computer::new();
x.quirk_mode = QuirkMode::SChipModern;
x.video_memory.set_lowres();
// point at the 1 from chip8
x.registers.poke_i(0x0005);
// point to 1,2 for the drawing
x.registers.poke(0x01, 0x01);
x.registers.poke(0x02, 0x02);
Chip8CpuInstructions::DRW(0x01, 0x01, 0x08).execute(&mut x);
let expected_state = read_test_result("state/video_lowres_schip_draw_chip8_sprite_result.json");
let actual_state = serde_json::to_string(&x).unwrap();
assert_eq!(expected_state, actual_state);
}
#[test]
fn video_lowres_schip_draw_schip_sprite() {}
#[test]
fn video_highres_schip_draw_chip8_sprite() {}
#[test]
fn video_highres_schip_draw_schip_sprite() {}