Skip to content

Commit

Permalink
Debugger (#119)
Browse files Browse the repository at this point in the history
Add a cli debugger to magenboy sdl frontend

The debugger included breakpoints, disassembler, hex view, ppu viewer and  memory watch points,
all the commands are documented in the docs folder

- Core now uses std if the dbg feature is enabled in order to allocate the debugger memory on the heap 
in order to avoid stack overflow (and the code is much simpler

- Fixed an unsoundness in SDL usage: 
been calling SDL_PumpEvents in the incorrect thread + managed the windows not in the video subsystem initializing thread.
  • Loading branch information
alloncm authored Sep 19, 2024
1 parent 98ce189 commit 6694eac
Show file tree
Hide file tree
Showing 44 changed files with 1,315 additions and 341 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ or with more configuration options:
cargo build --release --package magenboy_sdl --features [optional_features]
```
#### Optional features:
* `dbg` - Enable debugger
* `static-sdl` - will link statically to sdl2, On by default
* `sdl-resample` - Use the audio resampler from sdl2 library and a manual one I wrote
* `push-audio` - Use a push methododlogy instead of pull for the delivery of the sound samples to sdl2
Expand Down
4 changes: 3 additions & 1 deletion common/src/joypad_menu/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,12 @@ impl<'a, T, S: AsRef<str>, MR:MenuRenderer<T, S>> JoypadMenu<'a, T, S, MR>{
}
}
}
// Busy wait untill A is released in order to not leak the button press to the emulation

// Busy wait until A is released in order to not leak the button press to the emulation
while joypad.buttons[Button::A as usize]{
provider.provide(&mut joypad);
}

return &self.options[self.selection].value;
}
}
2 changes: 2 additions & 0 deletions core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@ edition.workspace = true

[dependencies]
log = "0.4"
cfg-if = "1"

[features]
u16pixel = []
apu = []
dbg = []

[dev-dependencies]
criterion = "0.3"
Expand Down
7 changes: 3 additions & 4 deletions core/src/cpu/gb_cpu.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use crate::mmu::interrupts_handler::InterruptRequest;
use crate::mmu::memory::Memory;
use crate::mmu::{interrupts_handler::InterruptRequest, Memory};

use super::register::Reg;
use super::flag::Flag;
Expand Down Expand Up @@ -84,10 +83,10 @@ impl GbCpu {
}

pub fn inc_hl(&mut self){
*self.hl.value() = (*self.hl.value()).wrapping_add(1);
*self.hl.value_mut() = self.hl.value().wrapping_add(1);
}

pub fn dec_hl(&mut self){
*self.hl.value() = (*self.hl.value()).wrapping_sub(1);
*self.hl.value_mut() = self.hl.value().wrapping_sub(1);
}
}
2 changes: 1 addition & 1 deletion core/src/cpu/opcode_runner.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::mmu::memory::Memory;
use crate::mmu::Memory;
use super::{
gb_cpu::GbCpu,
opcodes::{
Expand Down
4 changes: 2 additions & 2 deletions core/src/cpu/opcodes/arithmetic_16bit_instructions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,14 @@ use super::opcodes_utils::{
pub fn add_hl_rr(cpu:&mut GbCpu, opcode:u8)->u8{
let reg = opcode >> 4;
let reg = *get_arithmetic_16reg(cpu, reg);
let hl_value = *cpu.hl.value();
let hl_value = cpu.hl.value();

let (value,overflow) = hl_value.overflowing_add(reg);
cpu.set_by_value(Flag::Carry, overflow);
cpu.set_by_value(Flag::HalfCarry, check_for_half_carry_third_nible_add(hl_value, reg));
cpu.unset_flag(Flag::Subtraction);

*cpu.hl.value() = value;
*cpu.hl.value_mut() = value;

// 2 cycles - 1 reading opcode, 1 internal operation
return 1;
Expand Down
28 changes: 13 additions & 15 deletions core/src/cpu/opcodes/arithmetic_8bit_instructions.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
use crate::cpu::gb_cpu::GbCpu;
use crate::cpu::flag::Flag;
use crate::mmu::memory::Memory;
use crate::{cpu::{gb_cpu::GbCpu, flag::Flag}, mmu::Memory};
use super::opcodes_utils::{
get_src_register,
check_for_half_carry_first_nible_add,
Expand Down Expand Up @@ -114,7 +112,7 @@ pub fn add_a_nn(cpu:&mut GbCpu, opcode:u16)->u8{

//add A and (hl)
pub fn add_a_hl(cpu:&mut GbCpu, memory:&mut impl Memory)->u8{
let src = memory.read(*cpu.hl.value(), 1);
let src = memory.read(cpu.hl.value(), 1);
let dest = *cpu.af.high();
*cpu.af.high() = add(cpu, dest, src);

Expand Down Expand Up @@ -144,7 +142,7 @@ pub fn adc_a_nn(cpu:&mut GbCpu, opcode:u16)->u8{

//add A and (hl) + Scarry
pub fn adc_a_hl(cpu:&mut GbCpu, memory:&mut impl Memory)->u8{
let src = memory.read(*cpu.hl.value(), 1);
let src = memory.read(cpu.hl.value(), 1);
let dest = *cpu.af.high();
*cpu.af.high() = adc(cpu, dest, src);

Expand Down Expand Up @@ -174,7 +172,7 @@ pub fn sub_a_nn(cpu:&mut GbCpu, opcode:u16)->u8{

//sub A and (hl)
pub fn sub_a_hl(cpu:&mut GbCpu, memory:&mut impl Memory)->u8{
let src = memory.read(*cpu.hl.value(), 1);
let src = memory.read(cpu.hl.value(), 1);
let dest = *cpu.af.high();
*cpu.af.high() = sub(cpu, dest, src);

Expand Down Expand Up @@ -205,7 +203,7 @@ pub fn sbc_a_nn(cpu:&mut GbCpu, opcode:u16)->u8{

//sub A and (hl)
pub fn sbc_a_hl(cpu:&mut GbCpu, memory:&mut impl Memory)->u8{
let src = memory.read(*cpu.hl.value(), 1);
let src = memory.read(cpu.hl.value(), 1);
let dest = *cpu.af.high();
*cpu.af.high() = subc(cpu, dest, src);

Expand Down Expand Up @@ -235,7 +233,7 @@ pub fn and_a_nn(cpu:&mut GbCpu, opcode:u16)->u8{

//and A and (hl)
pub fn and_a_hl(cpu:&mut GbCpu, memory:&mut impl Memory)->u8{
let src = memory.read(*cpu.hl.value(), 1);
let src = memory.read(cpu.hl.value(), 1);
let dest = *cpu.af.high();
*cpu.af.high() = and(cpu, dest, src);

Expand Down Expand Up @@ -265,7 +263,7 @@ pub fn xor_a_nn(cpu:&mut GbCpu, opcode:u16)->u8{

//xor A and (hl)
pub fn xor_a_hl(cpu:&mut GbCpu, memory:&mut impl Memory)->u8{
let src = memory.read(*cpu.hl.value(), 1);
let src = memory.read(cpu.hl.value(), 1);
let dest = *cpu.af.high();
*cpu.af.high() = xor(cpu, dest, src);

Expand Down Expand Up @@ -295,7 +293,7 @@ pub fn or_a_nn(cpu:&mut GbCpu, opcode:u16)->u8{

//or A and (hl)
pub fn or_a_hl(cpu:&mut GbCpu, memory:&mut impl Memory)->u8{
let src = memory.read(*cpu.hl.value(), 1);
let src = memory.read(cpu.hl.value(), 1);
let dest = *cpu.af.high();
*cpu.af.high() = or(cpu, dest, src);

Expand Down Expand Up @@ -325,7 +323,7 @@ pub fn cp_a_nn(cpu:&mut GbCpu, opcode:u16)->u8{

//or A and (hl)
pub fn cp_a_hl(cpu:&mut GbCpu, memory:&mut impl Memory)->u8{
let src = memory.read(*cpu.hl.value(), 1);
let src = memory.read(cpu.hl.value(), 1);
let dest = *cpu.af.high();
sub(cpu, dest, src);

Expand All @@ -351,9 +349,9 @@ pub fn inc_r(cpu:&mut GbCpu, opcode:u8)->u8{
}

pub fn inc_hl(cpu:&mut GbCpu, memory:&mut impl Memory)->u8{
let value = memory.read(*cpu.hl.value(), 1);
let value = memory.read(cpu.hl.value(), 1);
let altered_value = value.wrapping_add(1);
memory.write(*cpu.hl.value(), altered_value, 1);
memory.write(cpu.hl.value(), altered_value, 1);

cpu.set_by_value(Flag::Zero, altered_value == 0);
cpu.set_by_value(Flag::HalfCarry, check_for_half_carry_first_nible_add(value, 1));
Expand Down Expand Up @@ -381,9 +379,9 @@ pub fn dec_r(cpu:&mut GbCpu, opcode:u8)->u8{
}

pub fn dec_hl(cpu:&mut GbCpu, memory:&mut impl Memory)->u8{
let value = memory.read(*cpu.hl.value(), 1);
let value = memory.read(cpu.hl.value(), 1);
let altered_value = value.wrapping_sub(1);
memory.write(*cpu.hl.value(), altered_value, 1);
memory.write(cpu.hl.value(), altered_value, 1);

cpu.set_by_value(Flag::Zero, altered_value == 0);
cpu.set_by_value(Flag::HalfCarry, check_for_half_carry_first_nible_sub(value, altered_value));
Expand Down
2 changes: 1 addition & 1 deletion core/src/cpu/opcodes/cpu_control_instructions.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::{mmu::memory::Memory, cpu::{gb_cpu::GbCpu, flag::Flag}, utils::memory_registers::{IE_REGISTER_ADDRESS, JOYP_REGISTER_ADDRESS, KEY1_REGISTER_ADDRESS}};
use crate::{mmu::Memory, cpu::{gb_cpu::GbCpu, flag::Flag}, utils::memory_registers::{IE_REGISTER_ADDRESS, JOYP_REGISTER_ADDRESS, KEY1_REGISTER_ADDRESS}};

pub fn ccf(cpu:&mut GbCpu)->u8{
let carry:bool = cpu.get_flag(Flag::Carry);
Expand Down
11 changes: 3 additions & 8 deletions core/src/cpu/opcodes/jump_instructions.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
use crate::cpu::gb_cpu::GbCpu;
use crate::cpu::flag::Flag;
use crate::mmu::memory::Memory;
use super::opcodes_utils::{
pop,
push
};
use crate::{cpu::{gb_cpu::GbCpu, flag::Flag}, mmu::Memory};
use super::opcodes_utils::{pop,push};

fn push_pc(cpu:&mut GbCpu, memory: &mut impl Memory){
push(cpu, memory, cpu.program_counter);
Expand Down Expand Up @@ -134,7 +129,7 @@ pub fn jump_cc(cpu:&mut GbCpu, opcode:u32)->u8{
}

pub fn jump_hl(cpu:&mut GbCpu)->u8{
cpu.program_counter = *cpu.hl.value();
cpu.program_counter = cpu.hl.value();

// 1 cycles - 1 reading opcode
return 0;
Expand Down
18 changes: 8 additions & 10 deletions core/src/cpu/opcodes/load_16bit_instructions.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
use crate::cpu::gb_cpu::GbCpu;
use crate::cpu::flag::Flag;
use crate::mmu::memory::Memory;
use crate::{cpu::{gb_cpu::GbCpu, flag::Flag}, mmu::Memory};
use super::opcodes_utils::{
get_arithmetic_16reg,
opcode_to_u16_value,
Expand All @@ -24,7 +22,7 @@ pub fn load_rr_nn(cpu:&mut GbCpu, opcode:u32)->u8{

//loads register HL into the SP
pub fn load_sp_hl(cpu:&mut GbCpu)->u8{
cpu.stack_pointer = *cpu.hl.value();
cpu.stack_pointer = cpu.hl.value();

// 2 cycles - 1 reading opcode, 1 internal operation
return 1;
Expand All @@ -42,7 +40,7 @@ pub fn pop(cpu:&mut GbCpu, memory:&mut impl Memory, opcode:u8)->u8{
_=>panic!("no register")
};

*reg.value() = poped_value;
*reg.value_mut() = poped_value;

// 3 cycles - 1 reading opcode, 2 reading sp address and sp+1 address
return 0;
Expand All @@ -52,10 +50,10 @@ pub fn pop(cpu:&mut GbCpu, memory:&mut impl Memory, opcode:u8)->u8{
pub fn push(cpu:&mut GbCpu, memory:&mut impl Memory, opcode:u8)->u8{
let reg = (opcode&0xF0)>>4;
let value = match reg{
0xC=>*cpu.bc.value(),
0xD=>*cpu.de.value(),
0xE=>*cpu.hl.value(),
0xF=>*cpu.af.value(),
0xC=>cpu.bc.value(),
0xD=>cpu.de.value(),
0xE=>cpu.hl.value(),
0xF=>cpu.af.value(),
_=>panic!("no register")
};

Expand All @@ -71,7 +69,7 @@ pub fn ld_hl_spdd(cpu:&mut GbCpu, opcode:u16)->u8{
let temp:i32 = cpu.stack_pointer as i32;
let value = temp.wrapping_add(dd as i32);

*cpu.hl.value() = value as u16;
*cpu.hl.value_mut() = value as u16;

//check for carry
cpu.set_by_value(Flag::Carry, signed_check_for_carry_first_nible_add(temp as i16, dd));
Expand Down
30 changes: 13 additions & 17 deletions core/src/cpu/opcodes/load_8bit_instructions.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
use crate::cpu::gb_cpu::GbCpu;
use crate::mmu::memory::Memory;
use super::opcodes_utils::{
get_src_register,
get_reg_two_rows
};
use crate::{cpu::gb_cpu::GbCpu, mmu::Memory};
use super::opcodes_utils::{get_src_register, get_reg_two_rows};

const IO_PORTS_ADDRESS:u16 = 0xFF00;

Expand Down Expand Up @@ -46,7 +42,7 @@ pub fn ld_r_n(cpu: &mut GbCpu, opcode:u16)->u8 {
//load the value in address of HL into dest register
pub fn ld_r_hl(cpu:&mut GbCpu, memory:&mut impl Memory, opcode:u8)->u8{
let reg = opcode>>3;
let hl_value = *cpu.hl.value();
let hl_value = cpu.hl.value();
let reg = match reg{
0x8=>cpu.bc.high(),
0x9=>cpu.bc.low(),
Expand All @@ -66,7 +62,7 @@ pub fn ld_r_hl(cpu:&mut GbCpu, memory:&mut impl Memory, opcode:u8)->u8{

//load the value in reg_src into the address of HL in memory
pub fn ld_hl_r(cpu:&mut GbCpu, memory:&mut impl Memory, opcode:u8)->u8{
memory.write(*cpu.hl.value(), *get_src_register(cpu, opcode), 1);
memory.write(cpu.hl.value(), *get_src_register(cpu, opcode), 1);

// 2 cycles, 1 reading opcode, 1 writing hl address
return 0;
Expand All @@ -75,23 +71,23 @@ pub fn ld_hl_r(cpu:&mut GbCpu, memory:&mut impl Memory, opcode:u8)->u8{
//load the valie src into the address HL in memory
pub fn ld_hl_n(cpu: &mut GbCpu, memory:&mut impl Memory, opcode:u16)->u8{
let src = (0xFF & opcode) as u8;
memory.write(*cpu.hl.value(), src, 1);
memory.write(cpu.hl.value(), src, 1);

// 3 cycles - 2 reading opcode, 1 writing hl address
return 0;
}

//load the value in address of BC into register A
pub fn ld_a_bc(cpu: &mut GbCpu, memory:&mut impl Memory)->u8{
*cpu.af.high() = memory.read(*cpu.bc.value(), 1);
*cpu.af.high() = memory.read(cpu.bc.value(), 1);

// 2 cycles - 1 reading opcode, 1 reading bc address
return 0;
}

//load the value in address of DE into register A
pub fn ld_a_de(cpu: &mut GbCpu, memory:&mut impl Memory)->u8{
*cpu.af.high() = memory.read(*cpu.de.value(), 1);
*cpu.af.high() = memory.read(cpu.de.value(), 1);

// 2 cycles - 1 reading opcode, 1 reading de address
return 0;
Expand All @@ -109,15 +105,15 @@ pub fn ld_a_nn(cpu: &mut GbCpu, memory:&mut impl Memory, opcode:u32)->u8{

//load the value in register A into the address of BC
pub fn ld_bc_a(cpu: &mut GbCpu, memory:&mut impl Memory)->u8{
memory.write(*cpu.bc.value(), *cpu.af.high(), 1);
memory.write(cpu.bc.value(), *cpu.af.high(), 1);

// 2 cycles - 1 reading opcode, 1 writing bc address
return 0;
}

//load the value in register A into the address of DE
pub fn ld_de_a(cpu: &mut GbCpu, memory:&mut impl Memory)->u8{
memory.write(*cpu.de.value(), *cpu.af.high(), 1);
memory.write(cpu.de.value(), *cpu.af.high(), 1);

// 2 cycles - 1 reading opcode, 1 writing de address
return 0;
Expand All @@ -135,7 +131,7 @@ pub fn ld_nn_a(cpu: &mut GbCpu, memory:&mut impl Memory, opcode:u32)->u8{

//load value in register A into address HL and then increment register HL value
pub fn ldi_hl_a(cpu: &mut GbCpu, memory:&mut impl Memory)->u8{
memory.write(*cpu.hl.value(), *cpu.af.high(), 1);
memory.write(cpu.hl.value(), *cpu.af.high(), 1);
cpu.inc_hl();

// 2 cycles - 1 reading opcode, 1 writing hl address
Expand All @@ -144,7 +140,7 @@ pub fn ldi_hl_a(cpu: &mut GbCpu, memory:&mut impl Memory)->u8{

//load into register A the value in address HL and then increment register HL value
pub fn ldi_a_hl(cpu: &mut GbCpu, memory:&mut impl Memory)->u8{
*cpu.af.high() = memory.read(*cpu.hl.value(), 1);
*cpu.af.high() = memory.read(cpu.hl.value(), 1);
cpu.inc_hl();

// 2 cycles - 1 reading opcode, 1 reading hl address
Expand All @@ -153,7 +149,7 @@ pub fn ldi_a_hl(cpu: &mut GbCpu, memory:&mut impl Memory)->u8{

//load value in register A into address HL and then decrement register HL value
pub fn ldd_hl_a(cpu: &mut GbCpu, memory:&mut impl Memory)->u8{
memory.write(*cpu.hl.value(), *cpu.af.high(), 1);
memory.write(cpu.hl.value(), *cpu.af.high(), 1);
cpu.dec_hl();

// 2 cycles - 1 reading opcode, 1 writing hl address
Expand All @@ -162,7 +158,7 @@ pub fn ldd_hl_a(cpu: &mut GbCpu, memory:&mut impl Memory)->u8{

//load into register A the value in address HL and then decrement register HL value
pub fn ldd_a_hl(cpu: &mut GbCpu, memory:&mut impl Memory)->u8{
*cpu.af.high() = memory.read(*cpu.hl.value(), 1);
*cpu.af.high() = memory.read(cpu.hl.value(), 1);
cpu.dec_hl();

// 2 cycles - 1 reading opcode, 1 reading hl address
Expand Down
Loading

0 comments on commit 6694eac

Please sign in to comment.