Add system-specific boot symbols and CPU instruction tests
Introduced symbol files for various Game Boy systems (CGB, AGB, MGB, SGB) to define boot sequences and functionalities. Included CPU instruction behavior tests, with detailed coverage of standard operations and interrupt handling. Added documentation for test execution and internal framework operations.
This commit is contained in:
46
src/main.rs
46
src/main.rs
@@ -9,6 +9,8 @@ struct CPU {
|
||||
pc: u16,
|
||||
bus: MemoryBus,
|
||||
sp: u16,
|
||||
boot_rom: Vec<u8>,
|
||||
game_rom: Vec<u8>,
|
||||
}
|
||||
const VRAM_BEGIN: usize = 0x8000;
|
||||
const VRAM_END: usize = 0x9FFF;
|
||||
@@ -117,14 +119,14 @@ impl MemoryBus {
|
||||
self.write_byte(address.wrapping_add(1), high);
|
||||
}
|
||||
}
|
||||
#[derive(Clone, Copy)]
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
enum Target {
|
||||
U8Register(TargetRegister),
|
||||
U16Register(TargetU16Register),
|
||||
Address(u16),
|
||||
Immediate(u8)
|
||||
}
|
||||
#[derive(Clone, Copy)]
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
enum Condition {
|
||||
NZ, // Not Zero
|
||||
Z, // Zero
|
||||
@@ -133,7 +135,7 @@ enum Condition {
|
||||
None
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
enum LoadTarget{
|
||||
CopyR8R8(TargetRegister, TargetRegister),
|
||||
CopyR8N8(TargetRegister, u8),
|
||||
@@ -162,6 +164,7 @@ enum LoadTarget{
|
||||
}
|
||||
|
||||
|
||||
#[derive(Debug)]
|
||||
enum Instruction {
|
||||
ADC(Target),
|
||||
ADD(Target),
|
||||
@@ -208,11 +211,28 @@ enum Instruction {
|
||||
SWAP(Target),
|
||||
XOR(Target),
|
||||
}
|
||||
#[derive(Clone, Copy)]
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
enum TargetRegister { A, B, C, D, E, H, L, }
|
||||
#[derive(Clone, Copy)]
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
enum TargetU16Register {AF, BC, DE, HL, SP, PC}
|
||||
impl CPU {
|
||||
|
||||
fn init(&mut self) {
|
||||
let l = self.bus.memory.len();
|
||||
println!("{l}");
|
||||
println!("CPU init");
|
||||
// println!("Boot ROM: {:02X?}", self.boot_rom);
|
||||
for (address, byte) in self.boot_rom.iter().enumerate() {
|
||||
self.bus.write_byte(address as u16, *byte);
|
||||
}
|
||||
// println!("Game ROM: {:02X?}", self.game_rom);
|
||||
for (address, byte) in self.game_rom.iter().enumerate() {
|
||||
if address < 0x100 { continue; }
|
||||
if address >= 0x4000 { break; }
|
||||
self.bus.write_byte(address as u16, *byte);
|
||||
}
|
||||
|
||||
}
|
||||
fn check_condition(&self, condition: Condition) -> bool {
|
||||
match condition {
|
||||
Condition::NZ => !self.registers.f.zero,
|
||||
@@ -1264,11 +1284,23 @@ impl CPU {
|
||||
|
||||
|
||||
fn main() {
|
||||
let boot_rom = std::fs::read("boot/dmg.bin").unwrap();
|
||||
let game_rom = std::fs::read("cpu_instrs/cpu_instrs.gb").unwrap();
|
||||
|
||||
let gameboy = CPU{
|
||||
let mut gameboy = CPU{
|
||||
registers:Registers{a:0,b:0,c:0,d:0,e:0,f:FlagsRegister::from(0),h:0,l:0},
|
||||
pc:0,
|
||||
bus:MemoryBus{ memory: [0xFFu8; 0xFFFF], gpu:GPU{ vram: Vec::with_capacity(VRAM_END-VRAM_BEGIN), tile_set: [[[TilePixelValue::Zero; 8]; 8]; 384] }},
|
||||
sp: 0
|
||||
sp: 0,
|
||||
boot_rom,
|
||||
game_rom,
|
||||
};
|
||||
gameboy.init();
|
||||
let sp = gameboy.sp;
|
||||
println!("{sp:?}");
|
||||
let f = gameboy.next_instruction();
|
||||
println!("{f:?}");
|
||||
gameboy.execute(f);
|
||||
let sp = gameboy.sp;
|
||||
println!("{sp:?}");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user