This commit is contained in:
Trevor Merritt 2024-09-14 08:04:11 -04:00
parent 95d4e6c32c
commit a12b5f254c
4 changed files with 192 additions and 24 deletions

View File

@ -39,8 +39,14 @@ fn main() {
hello_world_window(ui);
EmmaGui::SystemMemoryRender(system.memory, ui);
let mut to_display = Box::new(Vec::new());
for i in 0..0xFF {
to_display.push(i);
}
EmmaGui::hex_memory_display(to_display, 0x7F, 0x80,ui);
EmmaGui::system_memory_render(system.memory, ui);
system.memory.gui_render(ui);

View File

@ -3,11 +3,21 @@ use emmaemu::chip8::system_memory::Chip8SystemMemory;
use emmaemu::constants::{CHIP8_VIDEO_HEIGHT, CHIP8_VIDEO_WIDTH};
pub struct EmmaGui {}
const cell_width: i32 = 5i32;
const cell_height: i32 = 5i32;
const CELL_WIDTH: i32 = 5i32;
const CELL_HEIGHT: i32 = 5i32;
impl EmmaGui {
pub fn SystemMemoryRender(memory: Chip8SystemMemory, ui: &Ui) {
pub fn hex_memory_display(bytes: Box<Vec<u8>>, rows: i32, cols: i32, ui: &Ui) {
// display a block of data
for current_row in 0..rows {
for current_column in 0..cols {
let data_offset = current_row * cols + current_column;
ui.text(format!("{:02x}", bytes[data_offset as usize]));
}
}
}
pub fn system_memory_render(memory: Chip8SystemMemory, ui: &Ui) {
ui.window("System Memory")
.size([300.0, 100.0], Condition::FirstUseEver)
.build(|| {
@ -16,11 +26,11 @@ impl EmmaGui {
let mut idx = 0;
for row in 0..CHIP8_VIDEO_HEIGHT {
for column in 0..CHIP8_VIDEO_WIDTH {
let x_offset = column * cell_width;
let y_offset = row * cell_width;
let x_offset = column * CELL_WIDTH;
let y_offset = row * CELL_WIDTH;
let start_point = [x_offset as f32, y_offset as f32];
let end_point = [(x_offset + cell_width) as f32,
(y_offset + cell_height) as f32
let end_point = [(x_offset + CELL_WIDTH) as f32,
(y_offset + CELL_HEIGHT) as f32
];
let memory_offset = (row * CHIP8_VIDEO_WIDTH) + column;
let target_color = if memory.peek(memory_offset as u16) == 0 {
@ -29,7 +39,7 @@ impl EmmaGui {
ImColor32::WHITE
};
draw_list.add_rect([x_offset as f32, y_offset as f32],
[(x_offset + cell_width) as f32, (y_offset + cell_height) as f32],
[(x_offset + CELL_WIDTH) as f32, (y_offset + CELL_HEIGHT) as f32],
target_color).build();
idx += 1;
}

View File

@ -53,7 +53,7 @@ impl Chip8Computer {
match (self.state, decided_instruction) {
(Chip8CpuStates::WaitingForInstruction, Chip8CpuInstructions::SysAddr(target_address)) => {
self.pc = target_address;
self.pc = target_address as u16;
},
(Chip8CpuStates::WaitingForInstruction, Chip8CpuInstructions::CLS) => todo!(),
(Chip8CpuStates::WaitingForInstruction, Chip8CpuInstructions::RET) => todo!(),
@ -216,27 +216,27 @@ impl Chip8Computer {
0x0000..=0x0FFF => {
// 0nnn - SYS addr
// Jump to a machine code routine at nnn.
decoded_instruction = Chip8CpuInstructions::SysAddr(addr_param);
decoded_instruction = Chip8CpuInstructions::SysAddr(addr_param as i16);
}
0x1000..=0x1FFF => {
// 1nnn - JP addr
// Jump to location nnn.
decoded_instruction = Chip8CpuInstructions::JpAddr(addr_param);
decoded_instruction = Chip8CpuInstructions::JpAddr(addr_param as i16);
}
0x2000..=0x2FFF => {
// 2nnn - CALL addr
// Call subroutine at nnn.
decoded_instruction = Chip8CpuInstructions::CallAddr(addr_param);
decoded_instruction = Chip8CpuInstructions::CallAddr(addr_param as i16);
}
0x3000..=0x3FFF => {
// 3xkk - SE Vx, byte
// Skip next instruction if Vx = kk.
decoded_instruction = Chip8CpuInstructions::SeVxByte(x_param, byte_param)
decoded_instruction = Chip8CpuInstructions::SeVxByte(x_param as i16, byte_param as i16)
}
0x4000..=0x4FFF => {
// 4xkk - SNE Vx, byte
// Skip next instruction if Vx != kk.
decoded_instruction = Chip8CpuInstructions::SneVxByte(x_param, byte_param);
decoded_instruction = Chip8CpuInstructions::SneVxByte(x_param as i16, byte_param as i16);
}
0x5000..=0x5FF0 => {
// 5xy0 - SE Vx, Vy

View File

@ -1,13 +1,13 @@
pub enum Chip8CpuInstructions {
SysAddr(u16), // 0x0nnn Exit to System Call
CLS, // 0x00E0 Clear Screen
SysAddr(i16), // 0x0nnn Exit to System Call
CLS, // * 0x00E0 Clear Screen
RET, // 0x00EE Return from Subroutine
JpAddr(u16), // 0x1nnn Jump to Address
CallAddr(u16), // 0x2nnn Call Subroutine
SeVxByte(u16, u16), // 0x3xkk Skip next instruction if Vx = kk.
SneVxByte(u16, u16), // 0x4xkk Skip next instruction if Vx != kk
JpAddr(i16), // 0x1nnn Jump to Address
CallAddr(i16), // 0x2nnn Call Subroutine
SeVxByte(i16, i16), // 0x3xkk Skip next instruction if Vx = kk.
SneVxByte(i16, i16), // 0x4xkk Skip next instruction if Vx != kk
SeVxVy(u16, u16), // 0x5xy0 Skip next instruction if Vx == Vy
LdVxByte(u16, u16), // 0x6xkk Set Vx = kk
LdVxByte(u16, u16), // * 0x6xkk Set Vx = kk
AddVxByte(u16, u16), // 0x7xkk Set Vx = Vx + kk
LdVxVy(u16, u16), // 0x8xy0 Set value of Vy in Vx
OrVxVy(u16, u16), // 0x8xy1 Set Vx = Vx OR Vy
@ -19,10 +19,10 @@ pub enum Chip8CpuInstructions {
SubnVxVy(u16, u16), // 0x8xy7 Set Vx = Vy - Vx (Set VF NOT Borrow)
ShlVxVy(u16, u16), // 0x8xyE Shift Left
SneVxVy(u16, u16), // 0x9xy0 Skip next instruction if Vx != Vy
LdIAddr(u16), // 0xAnnn VI = nnn
LdIAddr(u16), // * 0xAnnn VI = nnn
JpV0Addr(u16), // 0xBnnn Jump to nnn+V0
RndVxByte(u16, u16), // 0xCxkk Vx = random byte AND kk
DrawVxVyNibble(u16, u16, u16), // 0xDxyn Display N byte sprite starting at Vx to Vy
DrawVxVyNibble(u16, u16, u16), // * 0xDxyn Display N byte sprite starting at Vx to Vy
SkpVx(u16), // 0xE09E Skip next instruction if key in Vx pressed
SnkpVx(u16), // 0xE0A1 Skip next instruction if key in Vx NOT pressed
LdVxDt(u16), // 0xFx07 Set Vx = Delay timer
@ -36,3 +36,155 @@ pub enum Chip8CpuInstructions {
LdVxI(u16), // 0xFx65 Load V0 to Vx in memory starting at I
XXXXERRORINSTRUCTION,
}
#[derive(Clone)]
struct Chip8SystemState {
pub video_memory: [bool; 512],
pub memory: [u8; 4096],
pub registers: [u8; 16],
pub i: i16,
pub pc: i16,
pub sound_timer: i8,
pub delay_timer: i8
}
trait Chip8Instruction {
fn execute(&self, input: Chip8SystemState) -> Chip8SystemState;
}
impl Chip8Instruction for Chip8CpuInstructions {
fn execute(&self, mut input: Chip8SystemState) -> Chip8SystemState {
match self {
Chip8CpuInstructions::SysAddr(new_address) => {
let mut new_state = input.clone();
new_state.pc = *new_address;
new_state
}
Chip8CpuInstructions::CLS => {
input.video_memory = [false; 512];
input
}
Chip8CpuInstructions::RET => {
input
}
Chip8CpuInstructions::JpAddr(new_address) => {
input
}
Chip8CpuInstructions::CallAddr(_) => {
input
}
Chip8CpuInstructions::SeVxByte(_, _) => {
input
}
Chip8CpuInstructions::SneVxByte(_, _) => {
input
}
Chip8CpuInstructions::SeVxVy(_, _) => {
input
}
Chip8CpuInstructions::LdVxByte(register, byte) => {
input.registers[*register as usize] = byte.to_be_bytes()[0];
input
}
Chip8CpuInstructions::AddVxByte(_, _) => {
input
}
Chip8CpuInstructions::LdVxVy(_, _) => {
input
}
Chip8CpuInstructions::OrVxVy(_, _) => {
input
}
Chip8CpuInstructions::AndVxVy(_, _) => {
input
}
Chip8CpuInstructions::XorVxVy(_, _) => {
input
}
Chip8CpuInstructions::AddVxVy(_, _) => {
input
}
Chip8CpuInstructions::SubVxVy(_, _) => {
input
}
Chip8CpuInstructions::ShrVxVy(_, _) => {
input
}
Chip8CpuInstructions::SubnVxVy(_, _) => {
input
}
Chip8CpuInstructions::ShlVxVy(_, _) => {
input
}
Chip8CpuInstructions::SneVxVy(_, _) => {
input
}
Chip8CpuInstructions::LdIAddr(new_index) => {
input.i = *new_index as i16;
input
}
Chip8CpuInstructions::JpV0Addr(_) => {
input
}
Chip8CpuInstructions::RndVxByte(_, _) => {
input
}
Chip8CpuInstructions::DrawVxVyNibble(x, y, n) => {
// read nibble bytes from memory starting at I
let mut did_change: bool = false;
for draw_x in 0..*n {
let mut new_value = input.memory[(input.i + draw_x as i16) as usize];
for draw_y in 0..8 {
}
}
if did_change {
input.registers[0xF] = 1u8;
} else {
input.registers[0xF] = 0u8;
}
input
}
Chip8CpuInstructions::SkpVx(_) => {
input
}
Chip8CpuInstructions::SnkpVx(_) => {
input
}
Chip8CpuInstructions::LdVxDt(_) => {
input
}
Chip8CpuInstructions::LdVxK(_) => {
input
}
Chip8CpuInstructions::LdDtVx(_) => {
input
}
Chip8CpuInstructions::LdStVx(_) => {
input
}
Chip8CpuInstructions::AddIVx(_) => {
input
}
Chip8CpuInstructions::LdFVu(_) => {
input
}
Chip8CpuInstructions::LdBVx(_) => {
input
}
Chip8CpuInstructions::LdIVx(_) => {
input
}
Chip8CpuInstructions::LdVxI(_) => {
input
}
Chip8CpuInstructions::XXXXERRORINSTRUCTION => {
input
}
}
}
}