Refactor boot process and instruction execution
Introduce clearer boot ROM handling and streamline `execute_next_instruction` for better readability and accuracy. Add program counter (`pc`) updates within each instruction, improving program flow consistency.
This commit is contained in:
171
src/main.rs
171
src/main.rs
@@ -119,12 +119,14 @@ struct CPU {
|
||||
pc: u16,
|
||||
bus: MemoryBus,
|
||||
sp: u16,
|
||||
boot_rom: Vec<u8>,
|
||||
}
|
||||
const BOOT_BEGIN: usize = 0x0000;
|
||||
const BOOT_END: usize = 0x00FF;
|
||||
const CART_BEGIN: usize = 0x0100;
|
||||
const CART_END: usize = 0x7FFF;
|
||||
const VRAM_BEGIN: usize = 0x8000;
|
||||
const VRAM_END: usize = 0x9FFF;
|
||||
const CART_BEGIN: usize = 0x0000;
|
||||
const CART_END: usize = 0x7FFF;
|
||||
|
||||
struct GPU { vram: Vec<u8>, tile_set: [[[TilePixelValue; 8]; 8]; 384] }
|
||||
#[derive(Copy, Clone)]
|
||||
enum TilePixelValue { Three, Two, One, Zero }
|
||||
@@ -134,7 +136,7 @@ impl GPU {
|
||||
self.vram[address]
|
||||
}
|
||||
fn write_vram(&mut self, index: usize, value: u8) {
|
||||
self.vram[index] = value;
|
||||
// self.vram[index] = value;
|
||||
// If our index is greater than 0x1800, we're not writing to the tile set storage
|
||||
// so we can just return.
|
||||
if index >= 0x1800 { return }
|
||||
@@ -199,6 +201,7 @@ struct MemoryBus {
|
||||
memory: [u8; 0xFFFF],
|
||||
gpu: GPU,
|
||||
rom: GameRom,
|
||||
boot: Vec<u8>,
|
||||
}
|
||||
impl MemoryBus {
|
||||
fn read_byte(&self, address: u16) -> u8 {
|
||||
@@ -207,8 +210,15 @@ impl MemoryBus {
|
||||
VRAM_BEGIN ..= VRAM_END => {
|
||||
self.gpu.read_vram(address - VRAM_BEGIN)
|
||||
}
|
||||
BOOT_BEGIN..=BOOT_END => {
|
||||
if self.memory[0xFF50] == 0x00 {
|
||||
self.boot[address]
|
||||
}else {
|
||||
self.rom.read_byte(address)
|
||||
}
|
||||
}
|
||||
CART_BEGIN ..= CART_END => {self.rom.read_byte(address)}
|
||||
_ => self.memory[address as usize]
|
||||
_ => self.memory[address]
|
||||
}
|
||||
}
|
||||
fn write_byte(&mut self, address: u16, value: u8) {
|
||||
@@ -334,12 +344,7 @@ impl CPU {
|
||||
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);
|
||||
|
||||
self.bus.write_byte(0xFF50, 0x00);
|
||||
}
|
||||
fn check_condition(&self, condition: Condition) -> bool {
|
||||
match condition {
|
||||
@@ -942,6 +947,14 @@ impl CPU {
|
||||
_ => { panic!("Invalid u16 opcode: {:02X}", opcode); }
|
||||
}
|
||||
}
|
||||
fn execute_next_instruction(&mut self) {
|
||||
if self.pc >= 0x100 {
|
||||
println!("Boot Complete");
|
||||
}
|
||||
let inst = self.next_instruction();
|
||||
println!("{} {:?}", self.pc, inst);
|
||||
self.execute(inst);
|
||||
}
|
||||
fn execute(&mut self, instruction: Instruction) {
|
||||
match instruction {
|
||||
Instruction::ADC(target) => {
|
||||
@@ -953,6 +966,10 @@ impl CPU {
|
||||
self.registers.f.subtract = false;
|
||||
self.registers.f.carry = did_overflow;
|
||||
self.registers.f.half_carry = (self.registers.a & 0xF) + (value & 0xF) > 0xF;
|
||||
self.pc += match target {
|
||||
Target::Immediate(_) => {2}
|
||||
_ => {1}
|
||||
};
|
||||
}
|
||||
Instruction::ADD(target) => {
|
||||
let value = self.get_target_value(target);
|
||||
@@ -962,6 +979,10 @@ impl CPU {
|
||||
self.registers.f.subtract = false;
|
||||
self.registers.f.carry = did_overflow;
|
||||
self.registers.f.half_carry = (self.registers.a & 0xF) + (value & 0xF) > 0xF;
|
||||
self.pc += match target {
|
||||
Target::Immediate(_) => {2}
|
||||
_ => {1}
|
||||
};
|
||||
}
|
||||
Instruction::ADDHL(target) => {
|
||||
let value = self.get_u16_reg_value(target);
|
||||
@@ -971,6 +992,7 @@ impl CPU {
|
||||
self.registers.f.subtract = false;
|
||||
self.registers.f.carry = did_overflow;
|
||||
self.registers.f.half_carry = (new_value & 0xFF) + (value & 0xFF) > 0xFF;
|
||||
self.pc += 1;
|
||||
}
|
||||
Instruction::ADDSP(value) => {
|
||||
let offset = (value as i16) as u16;
|
||||
@@ -980,6 +1002,7 @@ impl CPU {
|
||||
self.registers.f.subtract = false;
|
||||
self.registers.f.carry = did_overflow;
|
||||
self.registers.f.half_carry = (new_value & 0xFF) + (offset & 0xFF) > 0xFF;
|
||||
self.pc += 2;
|
||||
}
|
||||
Instruction::AND(target) => {
|
||||
let value = self.get_target_value(target);
|
||||
@@ -988,17 +1011,22 @@ impl CPU {
|
||||
self.registers.f.subtract = false;
|
||||
self.registers.f.carry = false;
|
||||
self.registers.f.half_carry = true;
|
||||
self.pc += match target {
|
||||
Target::Immediate(_) => {2}
|
||||
_ => {1}
|
||||
};
|
||||
}
|
||||
Instruction::BIT(bit, target) => {
|
||||
let value = self.get_target_value(target);
|
||||
self.registers.f.zero = value >> bit & 0x1 == 0;
|
||||
self.registers.f.subtract = false;
|
||||
self.registers.f.half_carry = true;
|
||||
self.pc += 2;
|
||||
}
|
||||
Instruction::CALL(condition, address) => {
|
||||
if self.check_condition(condition) {
|
||||
self.sp = self.sp.wrapping_sub(2);
|
||||
let pc = self.pc;
|
||||
let pc = self.pc+3;
|
||||
self.bus.write_byte(self.sp + 1, ((pc >> 8) & 0xFF) as u8);
|
||||
self.bus.write_byte(self.sp, (pc & 0xFF) as u8);
|
||||
self.pc = address;
|
||||
@@ -1008,6 +1036,7 @@ impl CPU {
|
||||
self.registers.f.subtract = false;
|
||||
self.registers.f.half_carry = false;
|
||||
self.registers.f.carry = !self.registers.f.carry;
|
||||
self.pc += 1;
|
||||
}
|
||||
Instruction::CP(target) => {
|
||||
let value = self.get_target_value(target);
|
||||
@@ -1016,11 +1045,16 @@ impl CPU {
|
||||
self.registers.f.subtract = true;
|
||||
self.registers.f.carry = did_overflow;
|
||||
self.registers.f.half_carry = (self.registers.a & 0xF) + (value & 0xF) > 0xF;
|
||||
self.pc += match target {
|
||||
Target::Immediate(_) => {2}
|
||||
_ => {1}
|
||||
};
|
||||
}
|
||||
Instruction::CPL => {
|
||||
self.registers.a = !self.registers.a;
|
||||
self.registers.f.subtract = true;
|
||||
self.registers.f.half_carry = true;
|
||||
self.pc += 1;
|
||||
}
|
||||
Instruction::DAA => {
|
||||
let new_value;
|
||||
@@ -1047,6 +1081,7 @@ impl CPU {
|
||||
self.registers.f.carry = did_overflow;
|
||||
self.registers.f.zero = new_value == 0;
|
||||
self.registers.f.half_carry = false;
|
||||
self.pc += 1;
|
||||
}
|
||||
Instruction::DEC(target) => {
|
||||
match target {
|
||||
@@ -1066,6 +1101,7 @@ impl CPU {
|
||||
Target::Address(_) => {}
|
||||
Target::Immediate(_) => {}
|
||||
}
|
||||
self.pc += 1;
|
||||
}
|
||||
Instruction::DECHL(register) => {
|
||||
let target = Target::U16Register(register);
|
||||
@@ -1075,10 +1111,17 @@ impl CPU {
|
||||
self.registers.f.zero = new_value == 0;
|
||||
self.registers.f.subtract = true;
|
||||
self.registers.f.half_carry = (new_value & 0xF) + (value & 0xF) > 0xF;
|
||||
self.pc += 1;
|
||||
}
|
||||
Instruction::DI => {
|
||||
self.pc += 1;
|
||||
}
|
||||
Instruction::EI => {
|
||||
self.pc += 1;
|
||||
}
|
||||
Instruction::HALT => {
|
||||
self.pc += 1;
|
||||
}
|
||||
Instruction::DI => {}
|
||||
Instruction::EI => {}
|
||||
Instruction::HALT => {todo!();}
|
||||
|
||||
Instruction::INC(target) => {
|
||||
match target {
|
||||
@@ -1098,6 +1141,7 @@ impl CPU {
|
||||
Target::Address(_) => {}
|
||||
Target::Immediate(_) => {}
|
||||
}
|
||||
self.pc += 1;
|
||||
}
|
||||
Instruction::INCHL(register) => {
|
||||
let target = Target::U16Register(register);
|
||||
@@ -1107,6 +1151,7 @@ impl CPU {
|
||||
self.registers.f.zero = new_value == 0;
|
||||
self.registers.f.subtract = true;
|
||||
self.registers.f.half_carry = (new_value & 0xF) + (value & 0xF) > 0xF;
|
||||
self.pc += 1;
|
||||
}
|
||||
Instruction::JP(condition, address) => {
|
||||
if self.check_condition(condition) {
|
||||
@@ -1119,7 +1164,7 @@ impl CPU {
|
||||
Instruction::JR(condition, offset) => {
|
||||
if self.check_condition(condition) {
|
||||
self.pc = if offset.is_negative() {
|
||||
self.pc.wrapping_sub(offset.abs() as u16)
|
||||
self.pc.wrapping_sub(offset.abs() as u16 - 1)
|
||||
} else {
|
||||
self.pc.wrapping_add(offset as u16)
|
||||
}
|
||||
@@ -1130,94 +1175,116 @@ impl CPU {
|
||||
LoadTarget::CopyR8R8(dest_register, source_register) => {
|
||||
let value = self.get_u8_reg_value(source_register);
|
||||
self.set_u8_reg_value(dest_register, value);
|
||||
self.pc += 1;
|
||||
}
|
||||
LoadTarget::CopyR8N8(dest_register, value) => {
|
||||
self.set_u8_reg_value(dest_register, value);
|
||||
self.pc += 2;
|
||||
}
|
||||
LoadTarget::CopyR16N16(dest_register, value) => {
|
||||
self.set_u16_reg_value(dest_register, value);
|
||||
self.pc += 3;
|
||||
}
|
||||
LoadTarget::CopyHLR8(source_register) => {
|
||||
let value = self.get_u8_reg_value(source_register);
|
||||
let address = self.registers.get_hl();
|
||||
self.bus.write_byte(address, value);
|
||||
self.pc += 1;
|
||||
}
|
||||
LoadTarget::CopyHLN8(value) => {
|
||||
let address = self.registers.get_hl();
|
||||
self.bus.write_byte(address, value);
|
||||
self.pc += 2;
|
||||
}
|
||||
LoadTarget::CopyR8HL(dest_register) => {
|
||||
let address = self.registers.get_hl();
|
||||
let value = self.bus.read_byte(address);
|
||||
self.set_u8_reg_value(dest_register, value);
|
||||
self.pc += 1;
|
||||
}
|
||||
LoadTarget::CopyR16A(dest_register) => {
|
||||
let address = self.get_u16_reg_value(dest_register);
|
||||
self.bus.write_byte(address, self.registers.a);
|
||||
self.pc += 1;
|
||||
}
|
||||
LoadTarget::CopyN16A(address) => {
|
||||
self.bus.write_byte(address, self.registers.a);
|
||||
self.pc += 3;
|
||||
}
|
||||
LoadTarget::CopyPortA(target) => {
|
||||
let offset = self.get_target_value(target);
|
||||
let address = 0xFF00 | offset as u16;
|
||||
self.bus.write_byte(address, self.registers.a);
|
||||
self.pc += 2;
|
||||
}
|
||||
LoadTarget::CopyAPort(target) => {
|
||||
let offset = self.get_target_value(target);
|
||||
let address = 0xFF00 | offset as u16;
|
||||
self.registers.a = self.bus.read_byte(address);
|
||||
self.pc += 2;
|
||||
}
|
||||
LoadTarget::CopyHN16A(address) => {
|
||||
if address >= 0xFF00 {
|
||||
self.bus.write_byte(address, self.registers.a)
|
||||
}
|
||||
self.pc += 2;
|
||||
}
|
||||
LoadTarget::CopyHCA => {
|
||||
let address = 0xFF00 + self.registers.c as u16;
|
||||
self.bus.write_byte(address, self.registers.a)
|
||||
self.bus.write_byte(address, self.registers.a);
|
||||
self.pc += 1;
|
||||
}
|
||||
LoadTarget::CopyAR16(source_register) => {
|
||||
let address = self.get_u16_reg_value(source_register);
|
||||
self.registers.a = self.bus.read_byte(address);
|
||||
self.pc += 1;
|
||||
}
|
||||
LoadTarget::CopyAN16(address) => {
|
||||
self.registers.a = self.bus.read_byte(address);
|
||||
self.pc += 3;
|
||||
}
|
||||
LoadTarget::CopyHAN16(address) => {
|
||||
if address >= 0xFF00 {
|
||||
self.registers.a = self.bus.read_byte(address)
|
||||
self.registers.a = self.bus.read_byte(address);
|
||||
}
|
||||
self.pc += 2;
|
||||
}
|
||||
LoadTarget::CopyHAC => {
|
||||
self.registers.a = self.bus.read_byte(0xFF00+self.registers.c as u16)
|
||||
self.registers.a = self.bus.read_byte(0xFF00+self.registers.c as u16);
|
||||
self.pc += 1;
|
||||
}
|
||||
LoadTarget::CopyHLIA => {
|
||||
let address = self.registers.get_hl();
|
||||
self.bus.write_byte(address, self.registers.a);
|
||||
self.registers.set_hl(address.wrapping_add(1));
|
||||
self.pc += 1;
|
||||
}
|
||||
LoadTarget::CopyHLDA => {
|
||||
let address = self.registers.get_hl();
|
||||
self.bus.write_byte(address, self.registers.a);
|
||||
self.registers.set_hl(address.wrapping_sub(1));
|
||||
self.pc += 1;
|
||||
}
|
||||
LoadTarget::CopyAHLI => {
|
||||
let address = self.registers.get_hl();
|
||||
self.registers.a = self.bus.read_byte(address);
|
||||
self.registers.set_hl(address.wrapping_add(1));
|
||||
self.pc += 1;
|
||||
}
|
||||
LoadTarget::CopyAHLD => {
|
||||
let address = self.registers.get_hl();
|
||||
self.registers.a = self.bus.read_byte(address);
|
||||
self.registers.set_hl(address.wrapping_sub(1));
|
||||
self.pc += 1;
|
||||
}
|
||||
LoadTarget::CopySPN16(value) => {
|
||||
self.sp = value;
|
||||
self.pc += 3;
|
||||
}
|
||||
LoadTarget::CopyN16SP(address) => {
|
||||
self.bus.write_byte(address, (0xF & self.sp) as u8);
|
||||
self.bus.write_byte(address + 1, (self.sp >> 8) as u8);
|
||||
self.pc += 3;
|
||||
}
|
||||
LoadTarget::CopyHLSPE8(value) => {
|
||||
|
||||
@@ -1230,14 +1297,17 @@ impl CPU {
|
||||
self.registers.f.subtract = false;
|
||||
self.registers.f.carry = (new_value & 0xFF) + (self.sp & 0xFF) > 0xFF;
|
||||
self.registers.f.half_carry = (new_value & 0xF) + (self.sp & 0xF) > 0xF;
|
||||
|
||||
self.pc += 2;
|
||||
}
|
||||
LoadTarget::CopySPHL => {
|
||||
self.sp = self.registers.get_hl();
|
||||
self.pc += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
Instruction::NOP => {}
|
||||
Instruction::NOP => {
|
||||
self.pc += 1;
|
||||
}
|
||||
Instruction::OR(target) => {
|
||||
let value = self.get_target_value(target);
|
||||
self.registers.a = value | self.registers.a;
|
||||
@@ -1245,23 +1315,32 @@ impl CPU {
|
||||
self.registers.f.subtract = false;
|
||||
self.registers.f.carry = false;
|
||||
self.registers.f.half_carry = false;
|
||||
self.pc += match target {
|
||||
Target::Immediate(_) => {2}
|
||||
_ => {1}
|
||||
};
|
||||
}
|
||||
Instruction::POP(target) => {
|
||||
let value = self.pop_stack();
|
||||
self.set_u16_reg_value(target, value);
|
||||
self.pc += 1;
|
||||
}
|
||||
Instruction::PUSH(target) => {
|
||||
let value = self.get_u16_reg_value(target);
|
||||
self.push_stack(value);
|
||||
self.pc += 1;
|
||||
}
|
||||
Instruction::RES(bit, target) => {
|
||||
let mut value = self.get_target_value(target);
|
||||
value &= !(1 << bit);
|
||||
self.set_target_value(target, value);
|
||||
self.pc += 2;
|
||||
}
|
||||
Instruction::RET(condition) => {
|
||||
if self.check_condition(condition) {
|
||||
self.pc = self.pop_stack();
|
||||
} else {
|
||||
self.pc += 1;
|
||||
}
|
||||
}
|
||||
Instruction::RETI => {
|
||||
@@ -1276,6 +1355,10 @@ impl CPU {
|
||||
self.registers.f.zero = false;
|
||||
self.registers.f.subtract = false;
|
||||
self.registers.f.half_carry = false;
|
||||
self.pc += match self.bus.read_byte(self.pc) {
|
||||
0x17 => {1}
|
||||
_ => {2}
|
||||
}
|
||||
}
|
||||
Instruction::RLC(target) => {
|
||||
let old_value = self.get_target_value(target);
|
||||
@@ -1285,6 +1368,10 @@ impl CPU {
|
||||
self.registers.f.zero = false;
|
||||
self.registers.f.subtract = false;
|
||||
self.registers.f.half_carry = false;
|
||||
self.pc += match self.bus.read_byte(self.pc) {
|
||||
0x07 => {1}
|
||||
_ => {2}
|
||||
}
|
||||
}
|
||||
Instruction::RR(target) => {
|
||||
let old_value = self.get_target_value(target);
|
||||
@@ -1295,6 +1382,10 @@ impl CPU {
|
||||
self.registers.f.zero = false;
|
||||
self.registers.f.subtract = false;
|
||||
self.registers.f.half_carry = false;
|
||||
self.pc += match self.bus.read_byte(self.pc) {
|
||||
0x1F => {1}
|
||||
_ => {2}
|
||||
}
|
||||
}
|
||||
Instruction::RRC(target) => {
|
||||
let old_value = self.get_target_value(target);
|
||||
@@ -1304,6 +1395,10 @@ impl CPU {
|
||||
self.registers.f.zero = false;
|
||||
self.registers.f.subtract = false;
|
||||
self.registers.f.half_carry = false;
|
||||
self.pc += match self.bus.read_byte(self.pc) {
|
||||
0x0F => {1}
|
||||
_ => {2}
|
||||
}
|
||||
}
|
||||
Instruction::RST(idx) => {
|
||||
self.push_stack(self.pc);
|
||||
@@ -1319,16 +1414,22 @@ impl CPU {
|
||||
self.registers.f.subtract = true;
|
||||
self.registers.f.carry = did_overflow;
|
||||
self.registers.f.half_carry = (self.registers.a & 0xF) + (value & 0xF) > 0xF;
|
||||
self.pc += match target {
|
||||
Target::Immediate(_) => {2}
|
||||
_ => {1}
|
||||
};
|
||||
}
|
||||
Instruction::SCF => {
|
||||
self.registers.f.carry = true;
|
||||
self.registers.f.subtract = false;
|
||||
self.registers.f.half_carry = false;
|
||||
self.pc += 1;
|
||||
}
|
||||
Instruction::SET(bit, target) => {
|
||||
let mut value = self.get_target_value(target);
|
||||
value |= 1 << bit;
|
||||
self.set_target_value(target, value);
|
||||
self.pc += 2;
|
||||
}
|
||||
Instruction::SLA(target) => {
|
||||
let value = self.get_target_value(target);
|
||||
@@ -1338,6 +1439,7 @@ impl CPU {
|
||||
self.registers.f.subtract = false;
|
||||
self.registers.f.carry = value & 0x80 == 0x80;
|
||||
self.registers.f.half_carry = false;
|
||||
self.pc += 2;
|
||||
}
|
||||
Instruction::SRA(target) => {
|
||||
let value = self.get_target_value(target);
|
||||
@@ -1347,6 +1449,7 @@ impl CPU {
|
||||
self.registers.f.subtract = false;
|
||||
self.registers.f.carry = value & 0x80 == 0x80;
|
||||
self.registers.f.half_carry = false;
|
||||
self.pc += 2;
|
||||
}
|
||||
Instruction::SRL(target) => {
|
||||
let value = self.get_target_value(target);
|
||||
@@ -1356,9 +1459,10 @@ impl CPU {
|
||||
self.registers.f.subtract = false;
|
||||
self.registers.f.carry = value & 0x1 == 0x1;
|
||||
self.registers.f.half_carry = false;
|
||||
self.pc += 2;
|
||||
}
|
||||
Instruction::STOP(_) => {
|
||||
|
||||
self.pc += 2;
|
||||
}
|
||||
Instruction::SUB(target) => {
|
||||
let value = self.get_target_value(target);
|
||||
@@ -1368,6 +1472,10 @@ impl CPU {
|
||||
self.registers.f.subtract = true;
|
||||
self.registers.f.carry = did_overflow;
|
||||
self.registers.f.half_carry = (self.registers.a & 0xF) + (value & 0xF) > 0xF;
|
||||
self.pc += match target {
|
||||
Target::Immediate(_) => {2}
|
||||
_ => {1}
|
||||
};
|
||||
}
|
||||
Instruction::SWAP(target) => {
|
||||
let value = self.get_target_value(target);
|
||||
@@ -1377,6 +1485,7 @@ impl CPU {
|
||||
self.registers.f.subtract = false;
|
||||
self.registers.f.carry = false;
|
||||
self.registers.f.half_carry = false;
|
||||
self.pc += 2;
|
||||
}
|
||||
Instruction::XOR(target) => {
|
||||
let value = self.get_target_value(target);
|
||||
@@ -1385,6 +1494,10 @@ impl CPU {
|
||||
self.registers.f.subtract = false;
|
||||
self.registers.f.carry = false;
|
||||
self.registers.f.half_carry = false;
|
||||
self.pc += match target {
|
||||
Target::Immediate(_) => {2}
|
||||
_ => {1}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1402,18 +1515,14 @@ fn main() {
|
||||
pc:0,
|
||||
bus:MemoryBus{
|
||||
memory: [0xFFu8; 0xFFFF],
|
||||
gpu:GPU{ vram: Vec::with_capacity(VRAM_END-VRAM_BEGIN), tile_set: [[[TilePixelValue::Zero; 8]; 8]; 384] },
|
||||
gpu:GPU{ vram: vec![0xFFu8;VRAM_END-VRAM_BEGIN+1], tile_set: [[[TilePixelValue::Zero; 8]; 8]; 384] },
|
||||
rom: game_rom,
|
||||
boot: boot_rom,
|
||||
},
|
||||
sp: 0,
|
||||
boot_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:?}");
|
||||
loop {
|
||||
gameboy.execute_next_instruction()
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user