memory map viewer

This commit is contained in:
2023-12-10 22:15:57 -05:00
parent 034a56cfdd
commit d67edcba54
6 changed files with 140 additions and 5 deletions
+1
View File
@@ -12,3 +12,4 @@ snes-core = { path = "../snes-core" }
eframe = "0.24.1" eframe = "0.24.1"
env_logger = "0.10.1" env_logger = "0.10.1"
rfd = "0.12.1" rfd = "0.12.1"
regex = "1.10.2"
+23 -1
View File
@@ -1,6 +1,26 @@
pub struct MemoryMapInputs {
pub page_start: String,
pub page_end: String,
pub address_start: String,
pub address_end: String,
}
impl MemoryMapInputs {
pub fn new() -> Self {
Self {
page_start: String::from("00"),
page_end: String::from("0F"),
address_start: String::from("0000"),
address_end: String::from("01FF"),
}
}
}
pub struct DebugOptions { pub struct DebugOptions {
pub enable_debugging: bool, pub enable_debugging: bool,
pub show_debug_options_window: bool, pub show_debug_options_window: bool,
pub show_memory_map: bool,
pub memory_map_inputs: MemoryMapInputs,
} }
impl DebugOptions { impl DebugOptions {
@@ -8,6 +28,8 @@ impl DebugOptions {
Self { Self {
enable_debugging: true, enable_debugging: true,
show_debug_options_window: true, show_debug_options_window: true,
show_memory_map: true,
memory_map_inputs: MemoryMapInputs::new(),
} }
} }
} }
+22 -2
View File
@@ -1,9 +1,12 @@
use eframe::egui; use eframe::egui;
use snes_core::emulator::Emulator;
use crate::emu_state::AppState; use crate::emu_state::AppState;
use super::memory_map::build_memory_map_window;
pub fn build_debug_window(ctx: &egui::Context, app_state: &mut AppState) {
fn build_debug_options_window(ctx: &egui::Context, app_state: &mut AppState) {
egui::Window::new("Debug") egui::Window::new("Debug")
.open(&mut app_state.debug_options.show_debug_options_window) .open(&mut app_state.debug_options.show_debug_options_window)
.show(ctx, |ui| { .show(ctx, |ui| {
@@ -11,5 +14,22 @@ pub fn build_debug_window(ctx: &egui::Context, app_state: &mut AppState) {
&mut app_state.debug_options.enable_debugging, &mut app_state.debug_options.enable_debugging,
"Enable debugging", "Enable debugging",
); );
ui.separator();
if ui.selectable_label(
app_state.debug_options.show_memory_map,
"Show memory map"
).clicked() {
app_state.debug_options.show_memory_map = !app_state.debug_options.show_memory_map;
}
}); });
} }
pub fn build_all_debug_options(ctx: &egui::Context, app_state: &mut AppState, emulator: &Emulator) {
build_debug_options_window(ctx, app_state);
if !app_state.debug_options.enable_debugging {
return;
}
build_memory_map_window(ctx, app_state, emulator);
}
@@ -0,0 +1,91 @@
use eframe::egui;
use regex::Regex;
use snes_core::emulator::Emulator;
use crate::emu_state::{AppState, debug_options::MemoryMapInputs};
pub fn build_memory_map_window(ctx: &egui::Context, app_state: &mut AppState, emulator: &Emulator) {
if !app_state.debug_options.show_memory_map {
return
}
egui::Window::new("Memory Map")
.min_size([400.0, 400.0])
.open(&mut app_state.debug_options.show_memory_map)
.show(ctx, |ui| {
build_inputs(ui, &mut app_state.debug_options.memory_map_inputs);
ui.separator();
egui::ScrollArea::both().show(ui, |ui| {
build_memory_map_text(
ui,
&app_state.debug_options.memory_map_inputs,
emulator,
);
});
});
}
fn build_inputs(ui: &mut egui::Ui, input_values: &mut MemoryMapInputs) {
ui.horizontal(|ui| {
ui.label("Page Start: ");
ui.text_edit_singleline(&mut input_values.page_start);
});
ui.horizontal(|ui| {
ui.label("Page End: ");
ui.text_edit_singleline(&mut input_values.page_end);
});
ui.horizontal(|ui| {
ui.label("Address Start: ");
ui.text_edit_singleline(&mut input_values.address_start);
});
ui.horizontal(|ui| {
ui.label("Address End: ");
ui.text_edit_singleline(&mut input_values.address_end);
});
if ui.button("Search").clicked() {
sanitize_input(&mut input_values.page_start, true);
sanitize_input(&mut input_values.page_end, true);
sanitize_input(&mut input_values.address_start, false);
sanitize_input(&mut input_values.address_end, false);
}
}
fn sanitize_input(input: &mut String, is_page: bool) {
let re = Regex::new(r"^(0x)?[0-9a-fA-F]{2,4}$").unwrap();
if !re.is_match(input) {
*input = String::from("0x00");
}
let trimmed_input = input.trim_start_matches("0x");
*input = match is_page {
true => format!("{:02X}", u8::from_str_radix(&trimmed_input, 16).unwrap()),
false => format!("{:04X}", u16::from_str_radix(&trimmed_input, 16).unwrap()),
}
}
fn build_memory_map_text(ui: &mut egui::Ui, input_values: &MemoryMapInputs, emulator: &Emulator) {
let page_start = u8::from_str_radix(&input_values.page_start, 16).unwrap();
let page_end = u8::from_str_radix(&input_values.page_end, 16).unwrap();
let address_start = u16::from_str_radix(&input_values.address_start, 16).unwrap();
let address_end = u16::from_str_radix(&input_values.address_end, 16).unwrap();
let mut header = String::from(" | ");
for page in (page_start..=page_end).rev() {
header = format!("{}{:02X} ", header, page);
}
ui.monospace(header);
let mut divider = String::from("-----|-");
for _page in (page_start..=page_end).rev() {
divider = format!("{}---", divider);
}
ui.monospace(divider);
for address in (address_start..=address_end).rev() {
let mut address_row = format!("{:04X} | ", address);
for page in (page_start..=page_end).rev() {
let bus_address = ((page as u32) << 16) | (address as u32);
address_row = format!("{}{:02X} ", address_row, emulator.bus.read_external(bus_address));
}
ui.monospace(address_row);
}
}
+2 -1
View File
@@ -1,3 +1,4 @@
pub mod debug; pub mod debug;
pub mod memory_map;
pub use debug::build_debug_window; pub use debug::build_all_debug_options;
+1 -1
View File
@@ -24,7 +24,7 @@ impl eframe::App for SnesEmulatorApp {
ui.separator(); ui.separator();
// ui::game::build_game_window(ctx); // ui::game::build_game_window(ctx);
}); });
emu_ui::debug::build_debug_window(ctx, &mut self.state); emu_ui::debug::build_all_debug_options(ctx, &mut self.state, &self.emulator);
} }
} }