make things neater :)
This commit is contained in:
parent
d6276a1478
commit
ab3cba1ec0
112
src/main.rs
112
src/main.rs
|
@ -6,7 +6,7 @@ use clap::{ArgGroup, Parser};
|
|||
use minifb::{Window, WindowOptions};
|
||||
use processor::{
|
||||
memory::{rom::ROM, Memory},
|
||||
Registers, CPU,
|
||||
CPU,
|
||||
};
|
||||
use std::{
|
||||
fs,
|
||||
|
@ -66,32 +66,6 @@ struct Args {
|
|||
step_by: Option<usize>,
|
||||
}
|
||||
|
||||
fn cpu_ram_init(cpu: &mut CPU) {
|
||||
cpu.memory.set(0xFF04, 0xAD);
|
||||
cpu.memory.set(0xFF10, 0x80);
|
||||
cpu.memory.set(0xFF11, 0xBF);
|
||||
cpu.memory.set(0xFF12, 0xF3);
|
||||
cpu.memory.set(0xFF14, 0xBF);
|
||||
cpu.memory.set(0xFF16, 0x3F);
|
||||
cpu.memory.set(0xFF19, 0xBF);
|
||||
cpu.memory.set(0xFF1A, 0x7F);
|
||||
cpu.memory.set(0xFF1B, 0xFF);
|
||||
cpu.memory.set(0xFF1C, 0x9F);
|
||||
cpu.memory.set(0xFF1E, 0xBF);
|
||||
cpu.memory.set(0xFF20, 0xFF);
|
||||
cpu.memory.set(0xFF23, 0xBF);
|
||||
cpu.memory.set(0xFF24, 0x77);
|
||||
cpu.memory.set(0xFF25, 0xF3);
|
||||
cpu.memory.set(0xFF26, 0xF1);
|
||||
cpu.memory.set(0xFF40, 0x91);
|
||||
cpu.memory.set(0xFF47, 0xFC);
|
||||
cpu.memory.set(0xFF48, 0xFF);
|
||||
cpu.memory.set(0xFF49, 0xFF);
|
||||
for i in 0xC000..0xE000 {
|
||||
cpu.memory.set(i, if rand::random() { 0xFF } else { 0x00 });
|
||||
}
|
||||
}
|
||||
|
||||
static mut PAUSE_ENABLED: bool = false;
|
||||
static mut PAUSE_QUEUED: bool = false;
|
||||
// static mut VERBOSE: bool = false;
|
||||
|
@ -111,14 +85,14 @@ fn main() {
|
|||
let rom: ROM = match fs::read(args.rom) {
|
||||
Ok(data) => ROM::load(data),
|
||||
Err(e) => {
|
||||
println!("Error reading ROM: {}", e.to_string());
|
||||
println!("Error reading ROM: {e}");
|
||||
return;
|
||||
}
|
||||
};
|
||||
let bootrom: Vec<u8> = match fs::read(args.bootrom) {
|
||||
Ok(data) => data,
|
||||
Err(e) => {
|
||||
println!("Error reading bootROM: {}", e.to_string());
|
||||
println!("Error reading bootROM: {e}");
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
@ -130,7 +104,7 @@ fn main() {
|
|||
WindowOptions::default(),
|
||||
)
|
||||
.unwrap_or_else(|e| {
|
||||
panic!("{}", e);
|
||||
panic!("{e}");
|
||||
});
|
||||
|
||||
window.set_position(500, 50);
|
||||
|
@ -141,17 +115,10 @@ fn main() {
|
|||
Memory::init(bootrom, args.run_bootrom, rom),
|
||||
window,
|
||||
args.tile_window,
|
||||
args.run_bootrom,
|
||||
);
|
||||
|
||||
if !args.run_bootrom {
|
||||
cpu.reg.pc = 0x0100;
|
||||
cpu_ram_init(&mut cpu);
|
||||
}
|
||||
|
||||
let mut cycle_num = 0;
|
||||
let mut instructions_seen = vec![];
|
||||
let mut last_state = cpu.reg.clone();
|
||||
let mut next_state = last_state;
|
||||
|
||||
verbose_println!("\n\n Begin execution...\n");
|
||||
match args.step_by {
|
||||
|
@ -161,80 +128,57 @@ fn main() {
|
|||
if args.cycle_count {
|
||||
print_cycles(&cycle_num);
|
||||
}
|
||||
run_cycle(
|
||||
&mut cpu,
|
||||
&mut next_state,
|
||||
&mut last_state,
|
||||
&mut instructions_seen,
|
||||
);
|
||||
run_cycle(&mut cpu);
|
||||
}
|
||||
print!(
|
||||
" ...{} cycles - press enter to continue\r",
|
||||
cycle_num
|
||||
);
|
||||
print!(" ...{cycle_num} cycles - press enter to continue\r");
|
||||
stdout().flush().unwrap();
|
||||
pause_once();
|
||||
pause();
|
||||
},
|
||||
None => loop {
|
||||
cycle_num += 1;
|
||||
if args.cycle_count {
|
||||
print_cycles(&cycle_num);
|
||||
}
|
||||
run_cycle(
|
||||
&mut cpu,
|
||||
&mut next_state,
|
||||
&mut last_state,
|
||||
&mut instructions_seen,
|
||||
);
|
||||
run_cycle(&mut cpu);
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn run_cycle(
|
||||
cpu: &mut CPU,
|
||||
next_state: &mut Registers,
|
||||
last_state: &mut Registers,
|
||||
instructions_seen: &mut Vec<u8>,
|
||||
) {
|
||||
let will_pause;
|
||||
unsafe {
|
||||
will_pause = PAUSE_QUEUED.clone();
|
||||
}
|
||||
fn run_cycle(cpu: &mut CPU) {
|
||||
let will_pause = unsafe { PAUSE_QUEUED };
|
||||
let pause_enabled = unsafe { PAUSE_ENABLED };
|
||||
cpu.exec_next();
|
||||
unsafe {
|
||||
*next_state = cpu.reg;
|
||||
if !PAUSE_ENABLED {
|
||||
if next_state.pc >= 0x100 {
|
||||
PAUSE_ENABLED = true;
|
||||
if !pause_enabled {
|
||||
if cpu.reg.pc >= 0x100 {
|
||||
unsafe { PAUSE_ENABLED = true };
|
||||
}
|
||||
}
|
||||
*last_state = *next_state;
|
||||
if will_pause {
|
||||
pause();
|
||||
}
|
||||
}
|
||||
match instructions_seen.contains(&cpu.last_instruction) {
|
||||
true => {}
|
||||
false => {
|
||||
// println!("new instruction enountered: {:#X}", cpu.last_instruction);
|
||||
instructions_seen.push(cpu.last_instruction);
|
||||
}
|
||||
pause_then_step();
|
||||
}
|
||||
}
|
||||
|
||||
fn pause() {
|
||||
fn pause_then_step() {
|
||||
unsafe {
|
||||
if PAUSE_ENABLED {
|
||||
let line = &mut String::new();
|
||||
io::stdin().read_line(line).unwrap();
|
||||
let line = pause();
|
||||
PAUSE_QUEUED = !line.contains("continue");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
fn pause_once() {
|
||||
println!("paused...");
|
||||
io::stdin().read_line(&mut String::new()).unwrap();
|
||||
pause();
|
||||
}
|
||||
|
||||
fn pause() -> String {
|
||||
let mut line = String::new();
|
||||
match io::stdin().read_line(&mut line) {
|
||||
Ok(_) => line,
|
||||
Err(_) => String::from(""),
|
||||
}
|
||||
}
|
||||
|
||||
fn print_cycles(cycles: &i32) {
|
||||
|
|
|
@ -41,7 +41,7 @@ impl GPU {
|
|||
WindowOptions::default(),
|
||||
)
|
||||
.unwrap_or_else(|e| {
|
||||
panic!("{}", e);
|
||||
panic!("{e}");
|
||||
});
|
||||
|
||||
window.set_position((550 + (WIDTH * FACTOR)) as isize, 50);
|
||||
|
|
|
@ -287,4 +287,30 @@ impl Memory {
|
|||
self.joypad.b = keys.contains(&Key::Semicolon);
|
||||
self.joypad != old
|
||||
}
|
||||
|
||||
pub(super) fn cpu_ram_init(&mut self) {
|
||||
self.set(0xFF04, 0xAD);
|
||||
self.set(0xFF10, 0x80);
|
||||
self.set(0xFF11, 0xBF);
|
||||
self.set(0xFF12, 0xF3);
|
||||
self.set(0xFF14, 0xBF);
|
||||
self.set(0xFF16, 0x3F);
|
||||
self.set(0xFF19, 0xBF);
|
||||
self.set(0xFF1A, 0x7F);
|
||||
self.set(0xFF1B, 0xFF);
|
||||
self.set(0xFF1C, 0x9F);
|
||||
self.set(0xFF1E, 0xBF);
|
||||
self.set(0xFF20, 0xFF);
|
||||
self.set(0xFF23, 0xBF);
|
||||
self.set(0xFF24, 0x77);
|
||||
self.set(0xFF25, 0xF3);
|
||||
self.set(0xFF26, 0xF1);
|
||||
self.set(0xFF40, 0x91);
|
||||
self.set(0xFF47, 0xFC);
|
||||
self.set(0xFF48, 0xFF);
|
||||
self.set(0xFF49, 0xFF);
|
||||
for i in 0xC000..0xE000 {
|
||||
self.set(i, if rand::random() { 0xFF } else { 0x00 });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,9 +26,9 @@ pub struct CPU {
|
|||
pub memory: Memory,
|
||||
pub reg: Registers,
|
||||
pub last_instruction: u8,
|
||||
pub last_instruction_addr: u16,
|
||||
pub window: Window,
|
||||
pub gpu: GPU,
|
||||
last_instruction_addr: u16,
|
||||
window: Window,
|
||||
gpu: GPU,
|
||||
halted: bool,
|
||||
}
|
||||
|
||||
|
@ -38,10 +38,18 @@ const SPEEDUP: f64 = 1.;
|
|||
const FF04_SPEED: f64 = 16384.;
|
||||
|
||||
impl CPU {
|
||||
pub fn new(memory: Memory, window: Window, enable_tile_window: bool) -> Self {
|
||||
pub fn new(
|
||||
mut memory: Memory,
|
||||
window: Window,
|
||||
enable_tile_window: bool,
|
||||
run_bootrom: bool,
|
||||
) -> Self {
|
||||
if run_bootrom {
|
||||
memory.cpu_ram_init();
|
||||
}
|
||||
Self {
|
||||
memory,
|
||||
reg: Registers::default(),
|
||||
reg: Registers::init(run_bootrom),
|
||||
last_instruction: 0x0,
|
||||
last_instruction_addr: 0x0,
|
||||
window,
|
||||
|
@ -196,16 +204,26 @@ pub struct Registers {
|
|||
pub pc: u16,
|
||||
}
|
||||
|
||||
impl Default for Registers {
|
||||
fn default() -> Self {
|
||||
// default post-bootrom values
|
||||
impl Registers {
|
||||
fn init(run_bootrom: bool) -> Self {
|
||||
if run_bootrom {
|
||||
Self {
|
||||
af: 0,
|
||||
bc: 0,
|
||||
de: 0,
|
||||
hl: 0,
|
||||
sp: 0xFFFE,
|
||||
pc: 0,
|
||||
}
|
||||
} else {
|
||||
Self {
|
||||
af: 0x01B0,
|
||||
bc: 0x0013,
|
||||
de: 0x00D8,
|
||||
hl: 0x014D,
|
||||
sp: 0xFFFE,
|
||||
pc: 0x0000,
|
||||
pc: 0x0100,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue