display PPU registers and VRAM debug info

This commit is contained in:
2023-07-07 21:58:15 -05:00
parent e6d97f7203
commit 3e32e9d606
4 changed files with 206 additions and 7 deletions

View File

@@ -36,8 +36,6 @@ pub const M7B: u16 = 0x211C; // Rotation/Scaling Parameter B (and Math
pub const M7C: u16 = 0x211D; // Rotation/Scaling Parameter C (W)
pub const M7D: u16 = 0x211E; // Rotation/Scaling Parameter D (W)
pub const M7HOFS: u16 = 0x210D; // BG1 Horizontal Scroll (X) (W)
pub const M7VOFS: u16 = 0x210E; // BG1 Vertical Scroll (Y) (W)
pub const M7X: u16 = 0x211F; // Rotation/Scaling Center Coordinate X (W)
pub const M7Y: u16 = 0x2120; // Rotation/Scaling Center Coordinate Y (W)
@@ -156,6 +154,14 @@ impl PPURegisters {
}
}
pub fn registers(&self) -> &[u8] {
&self.data
}
pub fn vram(&self) -> &[u8] {
&self.vram
}
fn _read(&self, address: u16) -> u8 {
self.data[(address as usize) - 0x2100]
}

View File

@@ -298,13 +298,28 @@ fn main() {
.size([300.0, 400.0], Condition::FirstUseEver)
.build(&ui, || {
ui.text("Backgrounds:");
for bgdebug in state.ppudebug.backgrounds.iter_mut() {
ui.checkbox(
format!("Show {:?}", bgdebug.background),
&mut bgdebug.is_enabled,
);
}
ui.separator();
ui.text("Registers:");
ui.checkbox(
"Show PPU Registers",
&mut state.ppudebug.show_registers,
);
ui.separator();
ui.text("VRAM:");
ui.checkbox(
"Show PPU VRAM",
&mut state.ppudebug.show_vram,
);
});
for bgdebug in state.ppudebug.backgrounds.iter_mut() {
ppu_render::background_window(
@@ -315,6 +330,23 @@ fn main() {
&queue,
)
}
if state.ppudebug.show_registers {
ppu_render::registers_window(
&emulator.bus.ppu.registers,
&mut state.ppudebug.show_registers,
&ui,
)
}
if state.ppudebug.show_vram {
ppu_render::vram_window(
&emulator.bus.ppu.registers,
&mut state.ppudebug.vram_map,
&mut state.ppudebug.show_vram,
&ui,
)
}
}
if state.debug_options.show_cpu_registers {

View File

@@ -8,7 +8,8 @@ use snes_core::ppu::registers::{
use imgui_wgpu::Renderer;
use imgui::TextureId;
use wgpu::{Device, Queue};
use super::state::BgDebug;
use super::state::{BgDebug, VRAMMap};
pub fn background_texture(
@@ -63,12 +64,122 @@ pub fn background_window(bgdebug: &mut BgDebug, registers: &PPURegisters, ui: &i
let tex = renderer.textures.get_mut(texture_id).unwrap();
tex.write(queue, &bgdebug.framebuffer, MAX_BG_WIDTH as u32, MAX_BG_HEIGHT as u32);
let game_window = imgui::Window::new(format!("BG: {:?}", bgdebug.background));
game_window
let bg_window = imgui::Window::new(format!("BG: {:?}", bgdebug.background));
bg_window
.size([MAX_BG_WIDTH as f32, MAX_BG_HEIGHT as f32], imgui::Condition::FirstUseEver)
.opened(&mut bgdebug.is_enabled)
.build(ui, || {
let game_image = imgui::Image::new(texture_id, [MAX_BG_WIDTH as f32, MAX_BG_HEIGHT as f32]);
game_image.build(&ui);
});
}
}
fn get_register_name(register: u16) -> &'static str {
match register {
snes_core::ppu::registers::INIDISP => "INIDISP",
snes_core::ppu::registers::TM => "TM ",
snes_core::ppu::registers::TS => "TS ",
snes_core::ppu::registers::SETINI => "SETINI ",
snes_core::ppu::registers::BGMODE => "BGMODE ",
snes_core::ppu::registers::MOSAIC => "MOSAIC ",
snes_core::ppu::registers::BG1SC => "BG1SC ",
snes_core::ppu::registers::BG2SC => "BG2SC ",
snes_core::ppu::registers::BG3SC => "BG3SC ",
snes_core::ppu::registers::BG4SC => "BG4SC ",
snes_core::ppu::registers::BG12NBA => "BG12NBA",
snes_core::ppu::registers::BG34NBA => "BG34NBA",
snes_core::ppu::registers::BG1HOFS => "BG1HOFS",
snes_core::ppu::registers::BG2HOFS => "BG2HOFS",
snes_core::ppu::registers::BG3HOFS => "BG3HOFS",
snes_core::ppu::registers::BG4HOFS => "BG4HOFS",
snes_core::ppu::registers::M7SEL => "M7SEL ",
snes_core::ppu::registers::M7A => "M7A ",
snes_core::ppu::registers::M7B => "M7B ",
snes_core::ppu::registers::M7C => "M7C ",
snes_core::ppu::registers::M7D => "M7D ",
snes_core::ppu::registers::M7X => "M7X ",
snes_core::ppu::registers::M7Y => "M7Y ",
snes_core::ppu::registers::OBSEL => "OBSEL ",
snes_core::ppu::registers::WH0 => "WH0 ",
snes_core::ppu::registers::WH1 => "WH1 ",
snes_core::ppu::registers::WH2 => "WH2 ",
snes_core::ppu::registers::WH3 => "WH3 ",
snes_core::ppu::registers::W12SEL => "W12SEL ",
snes_core::ppu::registers::W34SEL => "W34SEL ",
snes_core::ppu::registers::WOBJSEL => "WOBJSEL",
snes_core::ppu::registers::WBGLOG => "WBGLOG ",
snes_core::ppu::registers::WOBJLOG => "WOBJLOG",
snes_core::ppu::registers::TMW => "TMW ",
snes_core::ppu::registers::TSW => "TSW ",
snes_core::ppu::registers::RDNMI => "RDNMI ",
snes_core::ppu::registers::VMAIN => "VMAIN ",
snes_core::ppu::registers::VMADDH => "VMADDH ",
snes_core::ppu::registers::VMDATAL => "VMDATAL",
snes_core::ppu::registers::VMDATAH => "VMDATAH",
snes_core::ppu::registers::RDVRAML => "RDVRAML",
snes_core::ppu::registers::RDVRAMH => "RDVRAMH",
_ => "N/A ",
}
}
pub fn registers_window(ppu_registers: &PPURegisters, show_registers: &mut bool, ui: &imgui::Ui) {
let window = imgui::Window::new("PPU Registers");
window
.size([300.0, 400.0], imgui::Condition::FirstUseEver)
.opened(show_registers)
.build(ui, || {
ui.text("Registers:");
for (index, register_value) in ppu_registers.registers().iter().enumerate() {
let register = (index as u16) + 0x2100;
let register_name = get_register_name(register);
ui.text(format!("{:04X} {}: {:02X} {:08b}", register, register_name, register_value, register_value));
}
});
}
pub fn vram_window(ppu_registers: &PPURegisters, vram_debug: &mut VRAMMap, show_vram: &mut bool, ui: &imgui::Ui) {
let window = imgui::Window::new("VRAM");
window
.size([300.0, 400.0], imgui::Condition::FirstUseEver)
.opened(show_vram)
.build(ui, || {
let address_start_input = ui.input_text(
"Address start",
&mut vram_debug.address_start_input
);
address_start_input.build();
let address_end_input = ui.input_text(
"Address end",
&mut vram_debug.address_end_input,
);
address_end_input.build();
if ui.button("Apply") {
vram_debug.set_values_from_inputs();
}
ui.separator();
let address_start = vram_debug.address_start;
let address_end = vram_debug.address_end;
let mut header = String::from(" | ");
for page in 0x00..=0x0F {
header = format!("{}{:02X} ", header, page);
}
ui.text(header);
let mut divider = String::from("-----|-");
for _ in 0x00..=0x0F {
divider = format!("{}---", divider);
}
ui.text(divider);
let vector = (address_start..=address_end).collect::<Vec<u16>>();
let chunks = vector.chunks(0x10);
for row in chunks {
let mut address_row = format!("{:04X} | ", row[0]);
for address in row {
address_row = format!("{}{:02X} ", address_row, ppu_registers.vram()[(*address) as usize]);
}
ui.text(address_row);
}
});
}

View File

@@ -78,6 +78,50 @@ impl MemoryMap {
}
}
pub struct VRAMMap {
pub address_start: u16,
pub address_end: u16,
pub address_start_input: String,
pub address_end_input: String,
}
impl VRAMMap {
pub fn new() -> Self {
Self {
address_start: 0x0000,
address_end: 0x00FF,
address_start_input: String::from("0000"),
address_end_input: String::from("0100"),
}
}
fn validate_values(&mut self) {
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 address_regex = Regex::new(r"^(0x)?[0-9a-fA-F]{4,4}$").unwrap();
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.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 is_enabled: bool,
pub show_debug_window: bool,
@@ -134,19 +178,25 @@ impl BgDebug {
pub struct PPUDebug {
pub is_enabled: bool,
pub show_registers: bool,
pub show_vram: bool,
pub backgrounds: [BgDebug; 4],
pub vram_map: VRAMMap,
}
impl PPUDebug {
pub fn new() -> Self {
Self {
is_enabled: true,
show_registers: true,
show_vram: true,
backgrounds: [
BgDebug::new(PPUBg::Bg1),
BgDebug::new(PPUBg::Bg2),
BgDebug::new(PPUBg::Bg3),
BgDebug::new(PPUBg::Bg4),
],
vram_map: VRAMMap::new(),
}
}
}