Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

UI: Add MemoryInspector #111

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion emu/src/arm7tdmi.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::cell::RefCell;
use std::cell::{Ref, RefCell};
use std::convert::TryInto;
use std::rc::Rc;

Expand Down Expand Up @@ -57,6 +57,7 @@ const OPCODE_ARM_SIZE: usize = 4;

impl Cpu for Arm7tdmi {
type OpCodeType = ArmModeOpcode;
type Memory = InternalMemory;

fn fetch(&self) -> u32 {
let instruction_index = self.registers.program_counter();
Expand Down Expand Up @@ -110,6 +111,10 @@ impl Cpu for Arm7tdmi {
fn registers(&self) -> Vec<u32> {
self.registers.to_vec()
}

fn get_memory(&self) -> Ref<'_, InternalMemory> {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can return Rc<RefCell<InternalMemory>> instead with self.memory.clone() that returns another usable instance of the Rc. But I don't want to keep it for later, because cpu doesn't need to return the memory, but gba. No problem for now, just a reminder for later.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Once you merge #111 and I rebase this get_memory fn will probably go away

self.memory.borrow()
}
}

impl Arm7tdmi {
Expand Down
7 changes: 7 additions & 0 deletions emu/src/cpu.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
use std::cell::Ref;

use crate::memory::io_device::IoDevice;

pub trait Cpu {
/// Size of Opcode: it can be changed
type OpCodeType;
type Memory: IoDevice<Address = u32, Value = u8>;

/// It generally takes the next instruction from PC
fn fetch(&self) -> u32;
Expand All @@ -17,4 +22,6 @@ pub trait Cpu {

/// Get the value of all registers
fn registers(&self) -> Vec<u32>;

fn get_memory(&self) -> Ref<'_, Self::Memory>;
}
9 changes: 7 additions & 2 deletions ui/src/dashboard.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ use emu::{arm7tdmi::Arm7tdmi, cartridge_header::CartridgeHeader, gba::Gba};

use super::about::About;
use super::cpu_inspector::CpuInspector;
use crate::{gba_display::GbaDisplay, palette_visualizer::PaletteVisualizer, ui_traits::UiTool};
use crate::{
gba_display::GbaDisplay, memory_inspector::MemoryInspector,
palette_visualizer::PaletteVisualizer, ui_traits::UiTool,
};

use std::{
collections::BTreeSet,
Expand Down Expand Up @@ -40,7 +43,8 @@ impl UiTools {
Box::new(About::default()),
Box::new(CpuInspector::new(arc_gba.clone())),
Box::new(GbaDisplay::new(arc_gba.clone())),
Box::new(PaletteVisualizer::new(arc_gba)),
Box::new(PaletteVisualizer::new(arc_gba.clone())),
Box::new(MemoryInspector::new(arc_gba)),
])
}

Expand All @@ -51,6 +55,7 @@ impl UiTools {
open.insert(tools[1].name().to_owned());
open.insert(tools[2].name().to_owned());
open.insert(tools[3].name().to_owned());
open.insert(tools[4].name().to_owned());

Self { tools, open }
}
Expand Down
1 change: 1 addition & 0 deletions ui/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@ pub mod app;
pub mod cpu_inspector;
pub mod dashboard;
pub mod gba_display;
pub mod memory_inspector;
pub mod palette_visualizer;
pub mod ui_traits;
73 changes: 73 additions & 0 deletions ui/src/memory_inspector.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
use emu::{cpu::Cpu, gba::Gba, memory::io_device::IoDevice};

use crate::ui_traits::{UiTool, View};

use std::{
borrow::Borrow,
sync::{Arc, Mutex},
};

pub struct MemoryInspector<T: Cpu> {
address_string: String,
value: u8,
base: Base,
gba: Arc<Mutex<Gba<T>>>,
}

impl<T: Cpu> MemoryInspector<T> {
pub fn new(gba: Arc<Mutex<Gba<T>>>) -> Self {
Self {
gba,
address_string: String::from("0"),
value: 0,
base: Base::Dec,
}
}
}

impl<T: Cpu> UiTool for MemoryInspector<T> {
fn name(&self) -> &'static str {
"Memory Inspector"
}

fn show(&mut self, ctx: &egui::Context, open: &mut bool) {
egui::Window::new(self.name())
.default_width(320.0)
.open(open)
.show(ctx, |ui| {
use View as _;
self.ui(ui);
});
}
}

#[derive(PartialEq)]
enum Base {
Dec,
Hex,
}

impl<T: Cpu> View for MemoryInspector<T> {
fn ui(&mut self, ui: &mut egui::Ui) {
ui.radio_value(&mut self.base, Base::Dec, "Dec");
ui.radio_value(&mut self.base, Base::Hex, "Hex");

ui.horizontal(|ui| {
ui.label("Memory address:");
ui.text_edit_singleline(&mut self.address_string);
if ui.button("Read").clicked() {
if let Ok(gba) = self.gba.lock() {
let radix = match self.base {
Base::Dec => 10,
Base::Hex => 16,
};

let address = u32::from_str_radix(&self.address_string, radix).unwrap();
self.value = gba.borrow().cpu.get_memory().borrow().read_at(address);
}
}
});

ui.label(format!("Value: {}", self.value));
}
}