mirror of
https://github.com/FranLMSP/snes.git
synced 2026-10-03 07:55:17 -04:00
memory map viewer
This commit is contained in:
@@ -1098,7 +1098,7 @@ impl CPU {
|
|||||||
self.increment_cycles_test(addressing_mode);
|
self.increment_cycles_test(addressing_mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run(&mut self, bus: &mut Bus) {
|
pub fn tick(&mut self, bus: &mut Bus) {
|
||||||
let opcode = bus.read(self.registers.get_pc_address());
|
let opcode = bus.read(self.registers.get_pc_address());
|
||||||
self.execute_opcode(opcode, bus);
|
self.execute_opcode(opcode, bus);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ pub struct Registers {
|
|||||||
impl Registers {
|
impl Registers {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
sp: 0,
|
sp: 0x01FC,
|
||||||
x: 0,
|
x: 0,
|
||||||
y: 0,
|
y: 0,
|
||||||
a: 0,
|
a: 0,
|
||||||
|
|||||||
@@ -20,8 +20,8 @@ impl Emulator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run(&mut self) {
|
pub fn tick(&mut self) {
|
||||||
self.cpu.run(&mut self.bus);
|
self.cpu.tick(&mut self.bus);
|
||||||
self.bus.ppu.tick(self.cpu.cycles);
|
self.bus.ppu.tick(self.cpu.cycles);
|
||||||
|
|
||||||
self.cpu.cycles = 0;
|
self.cpu.cycles = 0;
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ edition = "2021"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
snes-core = { path = "../snes-core" }
|
snes-core = { path = "../snes-core" }
|
||||||
|
regex = "1.8.1"
|
||||||
winit = "0.26.1"
|
winit = "0.26.1"
|
||||||
imgui = "0.8.2"
|
imgui = "0.8.2"
|
||||||
wgpu = "0.12.0"
|
wgpu = "0.12.0"
|
||||||
|
|||||||
+91
-13
@@ -18,6 +18,9 @@ extern crate snes_core;
|
|||||||
use snes_core::emulator::Emulator;
|
use snes_core::emulator::Emulator;
|
||||||
use snes_frontend::ppu as ppu_render;
|
use snes_frontend::ppu as ppu_render;
|
||||||
|
|
||||||
|
|
||||||
|
// TODO: refactor this please
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
// Windowing state
|
// Windowing state
|
||||||
let mut state = State::new();
|
let mut state = State::new();
|
||||||
@@ -78,7 +81,7 @@ fn main() {
|
|||||||
);
|
);
|
||||||
imgui.set_ini_filename(None);
|
imgui.set_ini_filename(None);
|
||||||
|
|
||||||
let font_size = (12.0 * hidpi_factor) as f32;
|
let font_size = (14.0 * hidpi_factor) as f32;
|
||||||
imgui.io_mut().font_global_scale = (1.0 / hidpi_factor) as f32;
|
imgui.io_mut().font_global_scale = (1.0 / hidpi_factor) as f32;
|
||||||
|
|
||||||
imgui.fonts().add_font(&[FontSource::DefaultFontData {
|
imgui.fonts().add_font(&[FontSource::DefaultFontData {
|
||||||
@@ -219,7 +222,7 @@ fn main() {
|
|||||||
{
|
{
|
||||||
match emulator.bus.rom.load(&String::from(path.to_str().unwrap())) {
|
match emulator.bus.rom.load(&String::from(path.to_str().unwrap())) {
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
state.emulation.is_paused = false;
|
// state.emulation.is_paused = false;
|
||||||
},
|
},
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
state.error_message.show = true;
|
state.error_message.show = true;
|
||||||
@@ -247,11 +250,27 @@ fn main() {
|
|||||||
.size([300.0, 100.0], Condition::FirstUseEver)
|
.size([300.0, 100.0], Condition::FirstUseEver)
|
||||||
.opened(&mut state.debug_options.show_debug_window)
|
.opened(&mut state.debug_options.show_debug_window)
|
||||||
.build(&ui, || {
|
.build(&ui, || {
|
||||||
|
ui.text("Controls:");
|
||||||
|
let pause_text = if state.emulation.is_paused {"Resume"} else {"Pause"};
|
||||||
|
if ui.button(pause_text) {
|
||||||
|
state.emulation.is_paused = !state.emulation.is_paused;
|
||||||
|
}
|
||||||
|
ui.disabled(!state.emulation.is_paused, || {
|
||||||
|
if ui.button("Tick") {
|
||||||
|
emulator.tick();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
ui.separator();
|
||||||
|
|
||||||
ui.checkbox(
|
ui.checkbox(
|
||||||
"Enable debugging",
|
"Enable debugging",
|
||||||
&mut state.debug_options.is_enabled,
|
&mut state.debug_options.is_enabled,
|
||||||
);
|
);
|
||||||
ui.separator();
|
ui.separator();
|
||||||
|
ui.checkbox(
|
||||||
|
"Show Memory Map",
|
||||||
|
&mut state.debug_options.memory_map.is_enabled ,
|
||||||
|
);
|
||||||
ui.checkbox(
|
ui.checkbox(
|
||||||
"Show PPU debugging options",
|
"Show PPU debugging options",
|
||||||
&mut state.ppudebug.is_enabled,
|
&mut state.ppudebug.is_enabled,
|
||||||
@@ -295,16 +314,75 @@ fn main() {
|
|||||||
window
|
window
|
||||||
.size([150.0, 200.0], Condition::FirstUseEver)
|
.size([150.0, 200.0], Condition::FirstUseEver)
|
||||||
.build(&ui, || {
|
.build(&ui, || {
|
||||||
ui.text(format!("SP: | {:#06X}", emulator.cpu.registers.sp));
|
ui.text(format!("SP: | {:#06X}", emulator.cpu.registers.sp));
|
||||||
ui.text(format!("X: | {:#06X}", emulator.cpu.registers.x));
|
ui.text(format!("X: | {:#06X}", emulator.cpu.registers.x));
|
||||||
ui.text(format!("Y: | {:#06X}", emulator.cpu.registers.y));
|
ui.text(format!("Y: | {:#06X}", emulator.cpu.registers.y));
|
||||||
ui.text(format!("A: | {:#06X}", emulator.cpu.registers.a));
|
ui.text(format!("A: | {:#06X}", emulator.cpu.registers.a));
|
||||||
ui.text(format!("P: | {:#04X}", emulator.cpu.registers.p));
|
ui.text(format!("P: | {:#04X}", emulator.cpu.registers.p));
|
||||||
ui.text(format!("D: | {:#06X}", emulator.cpu.registers.d));
|
ui.text(format!("D: | {:#06X}", emulator.cpu.registers.d));
|
||||||
ui.text(format!("PBR: | {:#04X}", emulator.cpu.registers.pbr));
|
ui.text(format!("PBR: | {:#04X}", emulator.cpu.registers.pbr));
|
||||||
ui.text(format!("DBR: | {:#04X}", emulator.cpu.registers.dbr));
|
ui.text(format!("DBR: | {:#04X}", emulator.cpu.registers.dbr));
|
||||||
ui.text(format!("PC: | {:#06X}", emulator.cpu.registers.pc));
|
ui.text(format!("PC: | {:#06X}", emulator.cpu.registers.pc));
|
||||||
ui.text(format!("EMU MODE: | {}", emulator.cpu.registers.emulation_mode));
|
ui.text(format!("EMU MODE: | {}", emulator.cpu.registers.emulation_mode));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if state.debug_options.memory_map.is_enabled {
|
||||||
|
let window = imgui::Window::new("Memory Map");
|
||||||
|
window
|
||||||
|
.size([400.0, 400.0], Condition::FirstUseEver)
|
||||||
|
.build(&ui, || {
|
||||||
|
let page_start_input = ui.input_text(
|
||||||
|
"Page start",
|
||||||
|
&mut state.debug_options.memory_map.page_start_input
|
||||||
|
);
|
||||||
|
page_start_input.build();
|
||||||
|
|
||||||
|
let page_end_input = ui.input_text(
|
||||||
|
"Page end",
|
||||||
|
&mut state.debug_options.memory_map.page_end_input
|
||||||
|
);
|
||||||
|
page_end_input.build();
|
||||||
|
|
||||||
|
let address_start_input = ui.input_text(
|
||||||
|
"Address start",
|
||||||
|
&mut state.debug_options.memory_map.address_start_input
|
||||||
|
);
|
||||||
|
address_start_input.build();
|
||||||
|
|
||||||
|
let address_end_input = ui.input_text(
|
||||||
|
"Address end",
|
||||||
|
&mut state.debug_options.memory_map.address_end_input,
|
||||||
|
);
|
||||||
|
address_end_input.build();
|
||||||
|
|
||||||
|
if ui.button("Apply") {
|
||||||
|
state.debug_options.memory_map.set_values_from_inputs();
|
||||||
|
}
|
||||||
|
|
||||||
|
ui.separator();
|
||||||
|
let page_start = state.debug_options.memory_map.page_start;
|
||||||
|
let page_end = state.debug_options.memory_map.page_end;
|
||||||
|
let address_start = state.debug_options.memory_map.address_start;
|
||||||
|
let address_end = state.debug_options.memory_map.address_end;
|
||||||
|
let mut header = String::from(" | ");
|
||||||
|
for page in (page_start..=page_end).rev() {
|
||||||
|
header = format!("{}{:02X} ", header, page);
|
||||||
|
}
|
||||||
|
ui.text(header);
|
||||||
|
let mut divider = String::from("-----|-");
|
||||||
|
for _page in (page_start..=page_end).rev() {
|
||||||
|
divider = format!("{}---", divider);
|
||||||
|
}
|
||||||
|
ui.text(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(bus_address));
|
||||||
|
}
|
||||||
|
ui.text(address_row);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -314,7 +392,7 @@ fn main() {
|
|||||||
// We want to keep the emulator running
|
// We want to keep the emulator running
|
||||||
// as long as we are not at the end of the frame
|
// as long as we are not at the end of the frame
|
||||||
while !emulator.is_frame_ending {
|
while !emulator.is_frame_ending {
|
||||||
emulator.run()
|
emulator.tick()
|
||||||
}
|
}
|
||||||
// Reset the flag because otherwise the emulator will never continue running
|
// Reset the flag because otherwise the emulator will never continue running
|
||||||
emulator.is_frame_ending = false
|
emulator.is_frame_ending = false
|
||||||
|
|||||||
@@ -4,14 +4,86 @@ use snes_core::ppu::registers::{
|
|||||||
MAX_BG_WIDTH,
|
MAX_BG_WIDTH,
|
||||||
MAX_BG_HEIGHT,
|
MAX_BG_HEIGHT,
|
||||||
};
|
};
|
||||||
|
use regex::Regex;
|
||||||
|
|
||||||
|
|
||||||
|
pub struct MemoryMap {
|
||||||
|
pub is_enabled: bool,
|
||||||
|
pub page_start: u8,
|
||||||
|
pub page_end: u8,
|
||||||
|
pub address_start: u16,
|
||||||
|
pub address_end: u16,
|
||||||
|
pub page_start_input: String,
|
||||||
|
pub page_end_input: String,
|
||||||
|
pub address_start_input: String,
|
||||||
|
pub address_end_input: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MemoryMap {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
is_enabled: true,
|
||||||
|
page_start: 0xF0,
|
||||||
|
page_end: 0xFF,
|
||||||
|
address_start: 0xFFF0,
|
||||||
|
address_end: 0xFFFF,
|
||||||
|
page_start_input: String::from("0xF0"),
|
||||||
|
page_end_input: String::from("0xFF"),
|
||||||
|
address_start_input: String::from("0xFFF0"),
|
||||||
|
address_end_input: String::from("0xFFFF"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn validate_values(&mut self) {
|
||||||
|
if self.page_start > self.page_end {
|
||||||
|
self.page_start = self.page_end;
|
||||||
|
}
|
||||||
|
if self.page_end < self.page_start {
|
||||||
|
self.page_end = self.page_start;
|
||||||
|
}
|
||||||
|
if self.address_start > self.address_end {
|
||||||
|
self.address_start = self.address_end;
|
||||||
|
}
|
||||||
|
if self.address_end < self.address_start {
|
||||||
|
self.address_end = self.address_start;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_values_from_inputs(&mut self) {
|
||||||
|
let page_regex = Regex::new(r"^(0x)?[0-9a-fA-F]{2,2}$").unwrap();
|
||||||
|
let address_regex = Regex::new(r"^(0x)?[0-9a-fA-F]{4,4}$").unwrap();
|
||||||
|
|
||||||
|
if !page_regex.is_match(&self.page_start_input) {
|
||||||
|
println!("Page start didn't match");
|
||||||
|
self.page_start_input = String::from("0x00");
|
||||||
|
}
|
||||||
|
if !page_regex.is_match(&self.page_end_input) {
|
||||||
|
println!("Page end didn't match");
|
||||||
|
self.page_end_input = String::from("0x00");
|
||||||
|
}
|
||||||
|
if !address_regex.is_match(&self.address_start_input) {
|
||||||
|
println!("Addr start didn't match");
|
||||||
|
self.address_start_input = String::from("0x0000");
|
||||||
|
}
|
||||||
|
if !address_regex.is_match(&self.address_end_input) {
|
||||||
|
println!("Addr end didn't match");
|
||||||
|
self.address_end_input = String::from("0x0000");
|
||||||
|
}
|
||||||
|
|
||||||
|
self.page_start = u8::from_str_radix(&self.page_start_input.trim_start_matches("0x"), 16).unwrap();
|
||||||
|
self.page_end = u8::from_str_radix(&self.page_end_input.trim_start_matches("0x"), 16).unwrap();
|
||||||
|
self.address_start = u16::from_str_radix(&self.address_start_input.trim_start_matches("0x"), 16).unwrap();
|
||||||
|
self.address_end = u16::from_str_radix(&self.address_end_input.trim_start_matches("0x"), 16).unwrap();
|
||||||
|
self.validate_values()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct DebugOptions {
|
pub struct DebugOptions {
|
||||||
pub is_enabled: bool,
|
pub is_enabled: bool,
|
||||||
pub show_debug_window: bool,
|
pub show_debug_window: bool,
|
||||||
pub show_cpu_registers: bool,
|
pub show_cpu_registers: bool,
|
||||||
pub show_spc700_registers: bool,
|
pub show_spc700_registers: bool,
|
||||||
pub show_cpu_memory: bool,
|
pub memory_map: MemoryMap,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DebugOptions {
|
impl DebugOptions {
|
||||||
@@ -21,7 +93,7 @@ impl DebugOptions {
|
|||||||
show_debug_window: true,
|
show_debug_window: true,
|
||||||
show_cpu_registers: true,
|
show_cpu_registers: true,
|
||||||
show_spc700_registers: true,
|
show_spc700_registers: true,
|
||||||
show_cpu_memory: true,
|
memory_map: MemoryMap::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -105,4 +177,4 @@ impl State {
|
|||||||
emulation: Emulation::new(),
|
emulation: Emulation::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user