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