BUGFIX: Collision works better, not 100%
BUGFIX: Video Reset works.
This commit is contained in:
parent
5e290d825b
commit
448aeab154
@ -673,30 +673,29 @@ impl Chip8CpuInstructions {
|
|||||||
// it wraps around to the opposite side of the screen.
|
// it wraps around to the opposite side of the screen.
|
||||||
|
|
||||||
let source_memory_offset = input.registers.peek_i();
|
let source_memory_offset = input.registers.peek_i();
|
||||||
|
|
||||||
let x_offset = input.registers.peek(*x as u8);
|
let x_offset = input.registers.peek(*x as u8);
|
||||||
let y_offset = input.registers.peek(*y as u8);
|
let y_offset = input.registers.peek(*y as u8);
|
||||||
|
|
||||||
debug!("X_OFFSET = {x_offset} / y_offset = {y_offset}");
|
|
||||||
let target_memory_offset = x_offset as u16 * 64 + y_offset as u16;
|
|
||||||
|
|
||||||
debug!("CHIP8CPUINSTRUCTION:DRAWVXNIBBLE -> STARTING AT {source_memory_offset} WRITING TO {target_memory_offset}");
|
// let target_memory_offset = x_offset as u16 * 64 + y_offset as u16;
|
||||||
|
|
||||||
let num_bytes_to_read = *n;
|
let num_bytes_to_read = *n;
|
||||||
debug!("CHIP8CPUINSTRUCTION:DRAWVXNIBBLE -> PREPARING TO READ {num_bytes_to_read} BYTES FROM MEMORY TO VIDEO");
|
let mut did_change = false;
|
||||||
|
|
||||||
for byte_index in 0..num_bytes_to_read {
|
for byte_index in 0..num_bytes_to_read {
|
||||||
let current_byte = input.memory.peek(byte_index as u16 + source_memory_offset);
|
let current_byte = input.memory.peek(byte_index as u16 + source_memory_offset);
|
||||||
debug!("CHIP8CPUINSTRUCTION:DRAWVXNIBBLE -> READ BYTE [0x{byte_index:2x}]\t{current_byte:02x}\t{current_byte:08b}");
|
|
||||||
for bit_index in 0..8 {
|
for bit_index in 0..8 {
|
||||||
let data_offset = ((x_offset as u16 + byte_index as u16) * 64) + (y_offset as u16 + bit_index as u16) as u16;
|
let data_offset = ((x_offset as u16 + byte_index as u16) * 64) + (y_offset as u16 + bit_index as u16) as u16;
|
||||||
let current_bit = (current_byte.shr(7 - bit_index) & 0x1u8) == 0x1u8;
|
let current_bit = (current_byte & (0x80 >> bit_index)) != 0;
|
||||||
|
let previous_bit = input.video_memory.peek(data_offset);
|
||||||
|
let new_bit = previous_bit ^ current_bit;
|
||||||
|
if previous_bit && !new_bit {
|
||||||
|
did_change = true;
|
||||||
|
}
|
||||||
input.video_memory.poke(data_offset, current_bit);
|
input.video_memory.poke(data_offset, current_bit);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
debug!("PPOOSSTT -> CHIP8CPUINSTRUCTION:DRAWVXNIBBLE -> {}", input.video_memory.format_as_string());
|
|
||||||
|
|
||||||
let mut did_change: bool = input.video_memory.has_frame_changed;
|
|
||||||
|
|
||||||
if did_change {
|
if did_change {
|
||||||
input.registers.poke(0xf, 1u8);
|
input.registers.poke(0xf, 1u8);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@ -8,16 +8,9 @@ pub struct Chip8Video {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Chip8Video {
|
impl Chip8Video {
|
||||||
fn int_cls(&self) -> Chip8Video {
|
pub fn reset(&mut self) {
|
||||||
let mut x = Chip8Video::default();
|
self.cls();
|
||||||
for i in 0..CHIP8_VIDEO_WIDTH {
|
self.start_frame();
|
||||||
x.poke(i as u16, false);
|
|
||||||
}
|
|
||||||
x
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn reset(&mut self) -> Self {
|
|
||||||
self.int_cls()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn cls(&mut self) {
|
pub fn cls(&mut self) {
|
||||||
@ -38,10 +31,15 @@ impl Chip8Video {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn peek(self, address: u16) -> bool {
|
pub fn peek(self, address: u16) -> bool {
|
||||||
self.memory[address as usize]
|
let effective_address = if address >= 2048 {
|
||||||
|
address - 2048
|
||||||
|
} else {
|
||||||
|
address
|
||||||
|
};
|
||||||
|
self.memory[effective_address as usize]
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn poke(&mut self, address: u16, new_value: bool) -> Self {
|
pub fn poke(&mut self, address: u16, new_value: bool) {
|
||||||
// println!("OFFSET: {address} - POKING {new_value}");
|
// println!("OFFSET: {address} - POKING {new_value}");
|
||||||
|
|
||||||
// Loop the address
|
// Loop the address
|
||||||
@ -56,12 +54,14 @@ impl Chip8Video {
|
|||||||
let value_changed = old_value != xored_value; // From True to False is a change.
|
let value_changed = old_value != xored_value; // From True to False is a change.
|
||||||
|
|
||||||
self.has_frame_changed = if xored_value && value_changed { false } else { true };
|
self.has_frame_changed = if xored_value && value_changed { false } else { true };
|
||||||
|
if value_changed {
|
||||||
|
self.has_frame_changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
self.memory[effective_address as usize] = xored_value;
|
self.memory[effective_address as usize] = xored_value;
|
||||||
self.to_owned()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn poke_byte(&mut self, first_address: u16, to_write: u8) -> Self {
|
pub fn poke_byte(&mut self, first_address: u16, to_write: u8) {
|
||||||
for i in (0..8).rev() {
|
for i in (0..8).rev() {
|
||||||
let shifted = ((1 << i) & to_write) >> i;
|
let shifted = ((1 << i) & to_write) >> i;
|
||||||
//
|
//
|
||||||
@ -69,7 +69,6 @@ impl Chip8Video {
|
|||||||
let is_set = shifted == 1;
|
let is_set = shifted == 1;
|
||||||
self.poke(target_address, is_set);
|
self.poke(target_address, is_set);
|
||||||
}
|
}
|
||||||
self.to_owned()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn poke_sprite(&mut self, first_address: u16, to_write: Vec<u8>) -> Self {
|
pub fn poke_sprite(&mut self, first_address: u16, to_write: Vec<u8>) -> Self {
|
||||||
@ -421,7 +420,7 @@ mod test {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
x = x.reset();
|
x.reset();
|
||||||
assert_eq!(x.format_as_string(), read_test_result("test_reset_clears_video.asc"));
|
assert_eq!(x.format_as_string(), read_test_result("test_reset_clears_video.asc"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -452,6 +451,17 @@ mod test {
|
|||||||
|
|
||||||
// now set a no-collision value
|
// now set a no-collision value
|
||||||
x.poke_byte(0x00, 0b00001111);
|
x.poke_byte(0x00, 0b00001111);
|
||||||
assert_eq!(false, x.has_frame_changed);
|
assert_eq!(true, x.has_frame_changed);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn peek_out_of_bounds_doesnt_panic() {
|
||||||
|
let x = Chip8Video::default();
|
||||||
|
|
||||||
|
let y = x.peek(2049);
|
||||||
|
let y = x.peek(0);
|
||||||
|
|
||||||
|
// if we got here we didn't panic
|
||||||
|
assert!(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -31,7 +31,7 @@ fn reset_clears_video() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
x.reset();
|
x.reset();
|
||||||
x.video_memory = x.video_memory.reset();
|
x.video_memory.reset();
|
||||||
|
|
||||||
assert_eq!(x.dump_video_to_string(), x.video_memory.format_as_string());
|
assert_eq!(x.dump_video_to_string(), x.video_memory.format_as_string());
|
||||||
|
|
||||||
|
|||||||
@ -50,7 +50,7 @@ impl GemmaEguiSupport {
|
|||||||
}
|
}
|
||||||
if ui.button("Reset").clicked() {
|
if ui.button("Reset").clicked() {
|
||||||
system.reset();
|
system.reset();
|
||||||
system.video_memory = system.video_memory.reset();
|
system.video_memory.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ui.button("Load initial rom").clicked() {
|
if ui.button("Load initial rom").clicked() {
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
|
use std::ffi::OsString;
|
||||||
use gemma::constants::CHIP8_KEYBOARD;
|
use gemma::constants::CHIP8_KEYBOARD;
|
||||||
use std::fs::File;
|
use std::fs::{File, read_dir};
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
@ -23,16 +24,23 @@ impl GuiFileList {
|
|||||||
pub fn display_path(root: PathBuf, selected_filename: &String, ui: &Ui) -> String {
|
pub fn display_path(root: PathBuf, selected_filename: &String, ui: &Ui) -> String {
|
||||||
let mut working_filename = selected_filename.clone();
|
let mut working_filename = selected_filename.clone();
|
||||||
ui.text(format!("Displaying {}", root.to_str().unwrap_or("Unable to parse path")));
|
ui.text(format!("Displaying {}", root.to_str().unwrap_or("Unable to parse path")));
|
||||||
for (index, entry) in std::fs::read_dir(root.as_path()).unwrap().enumerate() {
|
|
||||||
let filename = entry.unwrap().file_name();
|
let mut known_files: Vec<OsString> = vec![];
|
||||||
let filename = filename.to_str().unwrap();
|
|
||||||
let mut working_select = ui.selectable_config(format!("{}", filename));
|
for entry in read_dir(root.as_path()).unwrap() {
|
||||||
if filename == selected_filename {
|
known_files.push(entry.unwrap().file_name());
|
||||||
|
}
|
||||||
|
|
||||||
|
known_files.sort();
|
||||||
|
|
||||||
|
for (index, entry) in known_files.iter().enumerate() {
|
||||||
|
let mut working_select = ui.selectable_config(format!("{}", entry.clone().into_string().unwrap()));
|
||||||
|
if entry.to_str().unwrap().to_string() == selected_filename.as_str().to_string() {
|
||||||
working_select = working_select.selected(true);
|
working_select = working_select.selected(true);
|
||||||
}
|
}
|
||||||
if working_select.build() {
|
if working_select.build() {
|
||||||
debug!("SELECTED {index} / {filename}");
|
debug!("SELECTED {index} / {entry:?}");
|
||||||
working_filename = filename.to_string();
|
working_filename = entry.clone().into_string().unwrap();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
working_filename
|
working_filename
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user