Skip to content

Commit

Permalink
Change Arc<Mutex<Gameboy>> to Rc<RefCell<Gameboy>>, as mandated by Cl…
Browse files Browse the repository at this point in the history
…ippy
  • Loading branch information
diogotito committed Mar 19, 2024
1 parent 84df887 commit 3ec8613
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 49 deletions.
57 changes: 30 additions & 27 deletions fpt-cli/src/debugger.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ use std::fmt;
use std::fs::File;
use std::io::Write;
use std::rc::Rc;
use std::sync::{Arc, Mutex, MutexGuard};

use fpt::Gameboy;
use hlua::AnyHashableLuaValue as LuaValue;
Expand Down Expand Up @@ -76,30 +75,26 @@ impl Breakpoint {
}
}
pub struct Debugger {
gameboy: Arc<Mutex<Gameboy>>,
gameboy: Rc<RefCell<Gameboy>>,
breakpoints: Vec<Breakpoint>,
}

impl Debugger {
fn new() -> Self {
let gameboy = Arc::new(Mutex::new(Gameboy::new()));
let gameboy = Rc::new(RefCell::new(Gameboy::new()));
Self::with_gameboy(gameboy)
}

pub fn with_gameboy(gameboy: Arc<Mutex<Gameboy>>) -> Self {
pub fn with_gameboy(gameboy: Rc<RefCell<Gameboy>>) -> Self {
Self {
gameboy,
breakpoints: Vec::new(),
}
}

pub fn gameboy(&self) -> MutexGuard<'_, Gameboy> {
self.gameboy.lock().unwrap()
}

pub fn check(&self) -> bool {
for breakpoint in &self.breakpoints {
if breakpoint.check(&self.gameboy()) {
if breakpoint.check(&self.gameboy.borrow()) {
return true;
}
}
Expand All @@ -108,7 +103,7 @@ impl Debugger {
}

pub fn start(&mut self) {
let mut gameboy = self.gameboy();
let mut gameboy = self.gameboy.borrow_mut();
loop {
println!("{:#02X}: {}", gameboy.cpu().pc(), gameboy.cpu().decode());
if self.check() {
Expand All @@ -120,7 +115,7 @@ impl Debugger {
}

pub fn next(&mut self) {
let mut gameboy = self.gameboy();
let mut gameboy = self.gameboy.borrow_mut();
println!("{:#02X}: {}", gameboy.cpu().pc(), gameboy.cpu().decode());
gameboy.instruction();
}
Expand All @@ -137,8 +132,8 @@ impl Debugger {
.collect::<String>()
}

pub fn pc(&mut self) -> u16 {
self.gameboy().cpu().pc()
pub fn pc(&self) -> u16 {
self.gameboy.borrow().cpu().pc()
}
}

Expand Down Expand Up @@ -258,71 +253,78 @@ impl DebuggerTextInterface<'_> {
debug_commands.set(
"pc",
hlua::function0(move || -> LuaValue {
LuaValue::LuaNumber(d1.borrow_mut().pc().into())
LuaValue::LuaNumber(d1.borrow().pc().into())
}),
);

let d1 = dbg_pointer.clone();
debug_commands.set(
"af",
hlua::function0(move || -> LuaValue {
LuaValue::LuaNumber(d1.borrow_mut().gameboy().cpu().af().into())
LuaValue::LuaNumber(d1.borrow().gameboy.borrow().cpu().af().into())
}),
);

let d1 = dbg_pointer.clone();
debug_commands.set(
"bc",
hlua::function0(move || -> LuaValue {
LuaValue::LuaNumber(d1.borrow_mut().gameboy().cpu().bc().into())
LuaValue::LuaNumber(d1.borrow().gameboy.borrow().cpu().bc().into())
}),
);

let d1 = dbg_pointer.clone();
debug_commands.set(
"de",
hlua::function0(move || -> LuaValue {
LuaValue::LuaNumber(d1.borrow_mut().gameboy().cpu().de().into())
LuaValue::LuaNumber(d1.borrow().gameboy.borrow().cpu().de().into())
}),
);

let d1 = dbg_pointer.clone();
debug_commands.set(
"hl",
hlua::function0(move || -> LuaValue {
LuaValue::LuaNumber(d1.borrow_mut().gameboy().cpu().hl().into())
LuaValue::LuaNumber(d1.borrow().gameboy.borrow().cpu().hl().into())
}),
);

let d1 = dbg_pointer.clone();
debug_commands.set(
"sp",
hlua::function0(move || -> LuaValue {
LuaValue::LuaNumber(d1.borrow_mut().gameboy().cpu().sp().into())
LuaValue::LuaNumber(d1.borrow().gameboy.borrow().cpu().sp().into())
}),
);

let d1 = dbg_pointer.clone();
debug_commands.set(
"mem",
hlua::function1(move |address: u16| -> LuaValue {
LuaValue::LuaNumber(d1.borrow_mut().gameboy().cpu().mem8(address).into())
LuaValue::LuaNumber(d1.borrow().gameboy.borrow().cpu().mem8(address).into())
}),
);

let d1 = dbg_pointer.clone();
debug_commands.set(
"next_cb",
hlua::function0(move || -> LuaValue {
LuaValue::LuaNumber(d1.borrow_mut().gameboy().cpu().next_cb().into())
LuaValue::LuaNumber(d1.borrow().gameboy.borrow().cpu().next_cb().into())
}),
);

let d1 = dbg_pointer.clone();
debug_commands.set(
"clock_cycle",
hlua::function0(move || -> LuaValue {
LuaValue::LuaString(d1.borrow_mut().gameboy().cpu().clock_cycles().to_string())
LuaValue::LuaString(
d1.borrow()
.gameboy
.borrow()
.cpu()
.clock_cycles()
.to_string(),
)
}),
);

Expand All @@ -331,10 +333,11 @@ impl DebuggerTextInterface<'_> {
"load_rom",
hlua::function1(move |filename: String| -> LuaValue {
let rom = std::fs::read(filename).unwrap();
d1.borrow_mut().gameboy().load_rom(&rom);
d1.borrow().gameboy.borrow_mut().load_rom(&rom);
let game_name = String::from_utf8(
d1.borrow()
.gameboy()
.gameboy
.borrow()
.bus()
.memory()
.slice(0x134..0x143)
Expand All @@ -355,7 +358,7 @@ impl DebuggerTextInterface<'_> {
format!(
"{:#02X} {:#02X}",
i,
d1.borrow_mut().gameboy().cpu().mem8(i)
d1.borrow().gameboy.borrow().cpu().mem8(i)
)
})
.intersperse("\n".to_string())
Expand All @@ -374,7 +377,7 @@ impl DebuggerTextInterface<'_> {
format!(
"{:#02X} {:#02X}",
i,
d1.borrow_mut().gameboy().cpu().mem8(i)
d1.borrow().gameboy.borrow().cpu().mem8(i)
)
})
.intersperse("\n".to_string())
Expand All @@ -398,7 +401,7 @@ impl DebuggerTextInterface<'_> {

// Our Game Boy's framebuffer seems to have a direct correspondence to this!
let d1 = d1.borrow();
let gameboy = d1.gameboy();
let gameboy = d1.gameboy.borrow();
let frame = gameboy.get_frame();

for line in frame.array_chunks::<160>() {
Expand Down
41 changes: 19 additions & 22 deletions fpt-egui/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
#![feature(lazy_cell)]
#![feature(array_chunks)]

use std::sync::{Arc, Mutex, MutexGuard};
use std::cell::RefCell;
use std::rc::Rc;
use std::time::Duration;

use eframe::Frame;
Expand Down Expand Up @@ -81,14 +82,14 @@ pub struct FPT {
bg_map: egui::ColorImage,
bg_map_texture: Option<egui::TextureHandle>,

gb: Arc<Mutex<fpt::Gameboy>>,
gb: Rc<RefCell<fpt::Gameboy>>,
db: Debugger,
paused: bool,
}

impl Default for FPT {
fn default() -> Self {
let gameboy = Arc::new(Mutex::new(fpt::Gameboy::new()));
let gameboy = Rc::new(RefCell::new(fpt::Gameboy::new()));
Self {
egui_frame_count: 0,
gb_frame_count: 0,
Expand All @@ -114,18 +115,14 @@ impl FPT {
if std::env::var("CI").is_err() {
const ROM_PATH: &str = "roms/Tetris_World_Rev_1.gb";
if let Ok(rom) = std::fs::read(ROM_PATH) {
app.gb().load_rom(&rom);
app.gb.borrow_mut().load_rom(&rom);
} else {
panic!("Unable to open {}", ROM_PATH);
}
}
app
}

pub fn gb(&self) -> MutexGuard<fpt::Gameboy> {
self.gb.lock().unwrap()
}

fn top_panel(&mut self, ctx: &Context) {
#[cfg(not(target_arch = "wasm32"))]
egui::TopBottomPanel::top("top_panel").show(ctx, |ui| {
Expand All @@ -147,12 +144,12 @@ impl FPT {
if self.accum_time >= GB_FRAME_IN_SECONDS {
self.gb_frame_count += 1;
self.accum_time -= GB_FRAME_IN_SECONDS;
// I didn't manage to work with a reference from self.gb().frame()
// I didn't manage to work with a reference from self.gb.borrow().frame()
// because that borrows self immutably,
// and then `self.image[(x, y)] = ... frame[z] ...` borrows self mutably and reads frame
let frame = {
let mut ppu_frame_copy: fpt::ppu::Frame = [0; 23040]; // should be optimized away?
ppu_frame_copy.copy_from_slice(self.gb().frame());
ppu_frame_copy.copy_from_slice(self.gb.borrow_mut().frame());
ppu_frame_copy
};
for z in 0..(WIDTH * HEIGHT) {
Expand Down Expand Up @@ -212,14 +209,14 @@ impl FPT {
}

fn get_tile(&self, tile_i: usize) -> Tile {
let [start, end] = if bitwise::test_bit8::<4>(self.gb().bus().lcdc()) {
let [start, end] = if bitwise::test_bit8::<4>(self.gb.borrow().bus().lcdc()) {
[0x8000 + tile_i * 16, 0x8000 + (tile_i + 1) * 16]
} else if tile_i >= 128 {
[0x8800 + tile_i * 16, 0x8800 + (tile_i + 1) * 16]
} else {
[0x9000 + tile_i * 16, 0x9000 + (tile_i + 1) * 16]
};
let tile_vec = self.gb().bus().slice(start..end);
let tile_vec = self.gb.borrow().bus().slice(start..end);
let tile_slice: [u8; 16] = tile_vec.try_into().unwrap();
Tile::load(&tile_slice)
}
Expand Down Expand Up @@ -279,10 +276,10 @@ impl FPT {
ui.image((texture.id(), TV_TEXTURE_SCALE * texture.size_vec2()));
});

let bg_map = if bitwise::test_bit8::<3>(self.gb().bus().lcdc()) {
self.gb().bus().slice(0x9C00..0xA000)
let bg_map = if bitwise::test_bit8::<3>(self.gb.borrow().bus().lcdc()) {
self.gb.borrow().bus().slice(0x9C00..0xA000)
} else {
self.gb().bus().slice(0x9800..0x9C00)
self.gb.borrow().bus().slice(0x9800..0x9C00)
};
for (i, tile_address) in bg_map.iter().enumerate() {
let tile = self.get_tile(*tile_address as usize);
Expand All @@ -304,10 +301,10 @@ impl FPT {
self.bg_map[(0, y)] = Color32::TRANSPARENT;
self.bg_map[(BMV_X_SIZE - 1, y)] = Color32::TRANSPARENT;
}
let top = self.gb().bus().scy() as usize;
let left = self.gb().bus().scx() as usize;
let bottom = ((self.gb().bus().scy() as u16 + 143u16) % 256u16) as usize;
let right = ((self.gb().bus().scx() as u16 + 159u16) % 256u16) as usize;
let top = self.gb.borrow().bus().scy() as usize;
let left = self.gb.borrow().bus().scx() as usize;
let bottom = ((self.gb.borrow().bus().scy() as u16 + 143u16) % 256u16) as usize;
let right = ((self.gb.borrow().bus().scx() as u16 + 159u16) % 256u16) as usize;
let btop = top;
let bleft = left;
let bbottom = bottom + 2 * BMV_BORDER_SIZE;
Expand Down Expand Up @@ -336,7 +333,7 @@ impl FPT {
});
ui.collapsing("Registers", |ui| {
ui.horizontal(|ui| {
let gb = self.gb();
let gb = self.gb.borrow();
let bus = gb.bus();
egui::Grid::new("VRAM-registers-1").striped(true).show(ui, |ui| {
ui.monospace("LCDC");
Expand Down Expand Up @@ -379,7 +376,7 @@ impl FPT {
$ui.colored_label(Color32::LIGHT_BLUE, $low_label);
}
}
let gb = self.gb();
let gb = self.gb.borrow();
let cpu = gb.cpu();
egui::Grid::new("cpu_registers_a-e").num_columns(4).min_col_width(10.0).striped(true).show(ui, |ui| {
cpu_register!(ui, "A": cpu.a(), "F": cpu.f()); ui.end_row();
Expand Down Expand Up @@ -410,7 +407,7 @@ impl FPT {
self.paused = true;
}
if ui.button("Step").clicked() {
self.gb().frame();
self.gb.borrow_mut().frame();
}
if ui.button("Continue").clicked() {
self.paused = false;
Expand Down

0 comments on commit 3ec8613

Please sign in to comment.