bootrom boot

This commit is contained in:
Alex Janka 2023-01-18 12:46:15 +11:00
parent 9533768bd9
commit d1dae1aa73

View file

@ -4,7 +4,10 @@ mod processor;
use clap::Parser; use clap::Parser;
use processor::CPU; use processor::CPU;
use std::{fs, io}; use std::{
fs,
io::{self, stdout, Write},
};
/// Simple program to greet a person /// Simple program to greet a person
#[derive(Parser, Debug)] #[derive(Parser, Debug)]
@ -43,6 +46,8 @@ union Register {
} }
pub struct Memory { pub struct Memory {
bootrom: ROM,
bootrom_enabled: bool,
rom: ROM, rom: ROM,
vram: [u8; 8192], vram: [u8; 8192],
ram: [u8; 8192], ram: [u8; 8192],
@ -50,11 +55,14 @@ pub struct Memory {
cpu_ram: [u8; 128], cpu_ram: [u8; 128],
oam: [u8; 160], oam: [u8; 160],
ime: bool, ime: bool,
io: [u8; 76],
} }
impl Memory { impl Memory {
fn init(rom: ROM) -> Self { fn init(bootrom: ROM, bootrom_enabled: bool, rom: ROM) -> Self {
Self { Self {
bootrom,
bootrom_enabled,
rom, rom,
vram: [0x0; 8192], vram: [0x0; 8192],
ram: [0x0; 8192], ram: [0x0; 8192],
@ -62,6 +70,7 @@ impl Memory {
cpu_ram: [0x0; 128], cpu_ram: [0x0; 128],
oam: [0x0; 160], oam: [0x0; 160],
ime: false, ime: false,
io: [0x0; 76],
} }
} }
@ -70,6 +79,9 @@ impl Memory {
0x0..0x8000 => { 0x0..0x8000 => {
// rom access // rom access
// todo - switchable rom banks // todo - switchable rom banks
if self.bootrom_enabled && (address as usize) < self.bootrom.len() {
return self.bootrom[address as usize];
}
return self.rom[address as usize]; return self.rom[address as usize];
} }
0x8000..0xA000 => { 0x8000..0xA000 => {
@ -88,13 +100,14 @@ impl Memory {
return self.oam[(address - 0xFE00) as usize]; return self.oam[(address - 0xFE00) as usize];
} }
0xFEA0..0xFF00 => { 0xFEA0..0xFF00 => {
panic!("empty space read") return 0x0;
} }
0xFF00..0xFF4C => { 0xFF00..0xFF4C => {
panic!("I/O read"); return self.io[(address - 0xFF00) as usize];
} }
0xFF4C..0xFF80 => { 0xFF4C..0xFF80 => {
panic!("empty space 2 read"); // println!("empty space 2 read");
return 0x0;
} }
0xFF80..0xFFFF => { 0xFF80..0xFFFF => {
return self.cpu_ram[(address - 0xFF80) as usize]; return self.cpu_ram[(address - 0xFF80) as usize];
@ -109,7 +122,7 @@ impl Memory {
match address { match address {
0x0..0x8000 => { 0x0..0x8000 => {
// change this with MBC code... // change this with MBC code...
println!("tried to write {:#5X} at {:#X}", data, address); // println!("tried to write {:#5X} at {:#X}", data, address);
} }
0x8000..0xA000 => { 0x8000..0xA000 => {
self.vram[(address - 0x8000) as usize] = data; self.vram[(address - 0x8000) as usize] = data;
@ -127,19 +140,24 @@ impl Memory {
self.oam[(address - 0xFE00) as usize] = data; self.oam[(address - 0xFE00) as usize] = data;
} }
0xFEA0..0xFF00 => { 0xFEA0..0xFF00 => {
panic!("empty space write") // println!("empty space write: {:#X} to addr {:#X}", data, address);
} }
0xFF00..0xFF4C => { 0xFF00..0xFF4C => {
panic!("I/O write"); if address == 0xFF02 && data == 0x81 {
print!("{}", self.get(0xFF01) as char);
stdout().flush().unwrap();
}
self.io[(address - 0xFF00) as usize] = data;
} }
0xFF4C..0xFF80 => { 0xFF4C..0xFF80 => {
panic!("empty space 2 write"); // println!("empty space 2 write: {:#X} to addr {:#X}", data, address);
} }
0xFF80..0xFFFF => { 0xFF80..0xFFFF => {
self.cpu_ram[(address - 0xFF80) as usize] = data; self.cpu_ram[(address - 0xFF80) as usize] = data;
} }
0xFFFF => match data { 0xFFFF => match data {
0x0 => self.ime = false, 0x0 => self.ime = false,
0x1 => self.ime = true,
_ => panic!("wrote weird number to ime: {:#X}", data), _ => panic!("wrote weird number to ime: {:#X}", data),
}, },
} }
@ -175,26 +193,39 @@ fn main() {
let rom: ROM = fs::read(args.rom).expect("Could not load ROM"); let rom: ROM = fs::read(args.rom).expect("Could not load ROM");
let bootrom: ROM = fs::read(args.bootrom).expect("Could not load BootROM"); let bootrom: ROM = fs::read(args.bootrom).expect("Could not load BootROM");
let mut state = State::default(); let mut state = State::default();
let run_rom = if args.run_bootrom { if args.run_bootrom {
state.pc = Register { as_u16: 0x0 }; state.pc = Register { as_u16: 0x0 };
bootrom }
} else {
rom
};
let mut cpu = CPU { let mut cpu = CPU {
memory: Memory::init(run_rom), memory: Memory::init(bootrom, args.run_bootrom, rom),
state, state,
last_instruction: 0x0,
last_instruction_addr: 0x0,
}; };
#[allow(unused_variables)]
let mut cycle_num = 0;
match args.step_by { match args.step_by {
Some(step_size) => loop { Some(step_size) => loop {
for _ in 0..step_size { for _ in 0..step_size {
cycle_num += 1;
cpu.exec_next(); cpu.exec_next();
println!(
"exec {:#4X} from {:#4X}",
cpu.last_instruction, cpu.last_instruction_addr
);
} }
print!(
" ...{} cycles - press enter to continue\r",
cycle_num
);
stdout().flush().unwrap();
pause(); pause();
}, },
None => loop { None => loop {
cpu.exec_next() cycle_num += 1;
print_cycles(&cycle_num);
cpu.exec_next();
}, },
} }
} }
@ -203,3 +234,17 @@ fn main() {
fn pause() { fn pause() {
io::stdin().read_line(&mut String::new()).unwrap(); io::stdin().read_line(&mut String::new()).unwrap();
} }
#[allow(dead_code)]
fn print_cycles(cycles: &i32) {
if *cycles % 456 != 0 {
return;
}
let instructions_per_second = 400000;
print!(
"cycle {} - approx {} seconds on real hardware\r",
cycles,
cycles / instructions_per_second
);
stdout().flush().unwrap();
}