mirror of
https://github.com/FranLMSP/snes.git
synced 2026-01-01 07:21:35 -05:00
display PPU registers and VRAM debug info
This commit is contained in:
@@ -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]
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -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(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user