Add cowgod docs, small changes to main, add experimental opcode parsing
This commit is contained in:
parent
0b0353c923
commit
e12bbe91a0
1200
notes/cowgod-chip8-techref.html
Normal file
1200
notes/cowgod-chip8-techref.html
Normal file
File diff suppressed because it is too large
Load Diff
Binary file not shown.
45
src/chip8.rs
45
src/chip8.rs
|
|
@ -11,6 +11,16 @@ pub const MAX_PRG_SIZE: usize = 3584;
|
||||||
// Instruction constants
|
// Instruction constants
|
||||||
const INSTR_NOOP: u16 = 0x0000;
|
const INSTR_NOOP: u16 = 0x0000;
|
||||||
const INSTR_EXIT: u16 = 0x00FD;
|
const INSTR_EXIT: u16 = 0x00FD;
|
||||||
|
const INSTR_CLS: u16 = 0x00E0;
|
||||||
|
const INSTR_RET: u16 = 0x00EE;
|
||||||
|
|
||||||
|
// Commonn Instruction Masks
|
||||||
|
const INSTR_MASK_SYS: u16 = 0x0000;
|
||||||
|
const INSTR_MASK_JP: u16 = 0x1000;
|
||||||
|
const INSTR_MASK_CALL: u16 = 0x2000;
|
||||||
|
|
||||||
|
const ADDR_MASK: u16 = 0x0FFF;
|
||||||
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct EmulationState {
|
struct EmulationState {
|
||||||
|
|
@ -73,7 +83,7 @@ fn exec_program(state: &mut EmulationState) {
|
||||||
|
|
||||||
let mut head_byte: u8;
|
let mut head_byte: u8;
|
||||||
let mut tail_byte: u8;
|
let mut tail_byte: u8;
|
||||||
let mut instruction_tuple: (u8, u8);
|
let mut instruction: u16;
|
||||||
|
|
||||||
for _i in PRGRM_START+usize::from(state.program_counter)..MAX_MEM_SIZE {
|
for _i in PRGRM_START+usize::from(state.program_counter)..MAX_MEM_SIZE {
|
||||||
// Grab the first byte of instruction
|
// Grab the first byte of instruction
|
||||||
|
|
@ -84,20 +94,47 @@ fn exec_program(state: &mut EmulationState) {
|
||||||
tail_byte = state.memory[PRGRM_START + usize::from(state.program_counter)];
|
tail_byte = state.memory[PRGRM_START + usize::from(state.program_counter)];
|
||||||
state.program_counter += 1;
|
state.program_counter += 1;
|
||||||
|
|
||||||
instruction_tuple = (head_byte, tail_byte);
|
instruction = util::u8_tuple_to_u16((head_byte, tail_byte));
|
||||||
|
|
||||||
|
|
||||||
println!("0x{:02X?}{:02X?}", head_byte, tail_byte);
|
println!("0x{:02X?}{:02X?}", head_byte, tail_byte);
|
||||||
|
|
||||||
if util::u8_tuple_to_u16(instruction_tuple) == INSTR_EXIT {
|
if instruction == INSTR_EXIT {
|
||||||
println!("Read exit instruction, stopping emulation");
|
println!("Read exit instruction, stopping emulation");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if util::u8_tuple_to_u16(instruction_tuple) == INSTR_NOOP {
|
if instruction == INSTR_NOOP {
|
||||||
println!("Read no-op instruction, stopping emulation");
|
println!("Read no-op instruction, stopping emulation");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
parse_instruction(state, instruction);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_instruction(state: &mut EmulationState, instr: u16) {
|
||||||
|
|
||||||
|
if (instr == INSTR_CLS) {
|
||||||
|
println!("Clear screen");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (instr == INSTR_RET) {
|
||||||
|
println!("Return");
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((instr & INSTR_MASK_SYS) > 0) {
|
||||||
|
let addr: u16 = (instr & ADDR_MASK);
|
||||||
|
println!("Got SYS instruction {:04X?} with address {:04X?}", instr, addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((instr & INSTR_MASK_JP) > 0) {
|
||||||
|
let addr: u16 = (instr & ADDR_MASK);
|
||||||
|
println!("Got JP instruction {:04X?} with address {:04X?}", instr, addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((instr & INSTR_MASK_CALL) > 0) {
|
||||||
|
let addr: u16 = (instr & ADDR_MASK);
|
||||||
|
println!("Got CALL instruction {:04X?} with address {:04X?}", instr, addr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
11
src/main.rs
11
src/main.rs
|
|
@ -11,8 +11,6 @@ fn main()
|
||||||
{
|
{
|
||||||
// Collect our execution args
|
// Collect our execution args
|
||||||
let args: Vec<String> = env::args().collect();
|
let args: Vec<String> = env::args().collect();
|
||||||
// let mut inject_mode: bool = false;
|
|
||||||
// let mut patch_file_path: &String = &"".to_string();
|
|
||||||
|
|
||||||
// Grab our filepath from our options
|
// Grab our filepath from our options
|
||||||
if &args.len() < &2
|
if &args.len() < &2
|
||||||
|
|
@ -22,11 +20,12 @@ fn main()
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
let file_path: &String = &args[1];
|
// Read last argument as path of chip8 executable
|
||||||
|
let file_path: &String = &args[args.len()-1];
|
||||||
|
|
||||||
if path::Path::new(file_path).exists()
|
if path::Path::new(file_path).exists()
|
||||||
{
|
{
|
||||||
println!("File exists, reading '{}'...", file_path);
|
println!("'{}' exists, reading...", file_path);
|
||||||
|
|
||||||
let contents: Result<Vec<u8>, std::io::Error> = fs::read(file_path);
|
let contents: Result<Vec<u8>, std::io::Error> = fs::read(file_path);
|
||||||
|
|
||||||
|
|
@ -49,9 +48,9 @@ fn main()
|
||||||
|
|
||||||
println!("Read {} bytes of program data", file_data.len());
|
println!("Read {} bytes of program data", file_data.len());
|
||||||
chip8::start_emulation(program);
|
chip8::start_emulation(program);
|
||||||
|
|
||||||
}
|
}
|
||||||
} else
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
println!("[Error] File '{}' does not exist", file_path);
|
println!("[Error] File '{}' does not exist", file_path);
|
||||||
exit(-1);
|
exit(-1);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user