1use crate::{DebugRenderContext, DebugRenderFn}; 2use egui::{Grid, Pos2, ScrollArea, Vec2, Window}; 3use jgenesis_common::frontend::Color; 4use smsgg_core::SmsGgEmulator; 5 6struct State { 7 vram_palette: u8, 8 cram_texture: Option<(wgpu::Texture, egui::TextureId)>, 9 vram_texture: Option<(wgpu::Texture, egui::TextureId)>, 10 cram_buffer: Box<[Color; 32]>, 11 vram_buffer: Box<[Color; 512 * 64]>, 12} 13 14impl State { 15 fn new() -> Self { 16 Self { 17 vram_palette: 0, 18 cram_texture: None, 19 vram_texture: None, 20 cram_buffer: vec![Color::default(); 32].into_boxed_slice().try_into().unwrap(), 21 vram_buffer: vec![Color::default(); 512 * 64].into_boxed_slice().try_into().unwrap(), 22 } 23 } 24} 25 26#[must_use] 27pub fn render_fn() -> Box<DebugRenderFn<SmsGgEmulator>> { 28 let mut state = State::new(); 29 Box::new(move |ctx, emulator| render(ctx, emulator, &mut state)) 30} 31 32fn render(mut ctx: DebugRenderContext<'_>, emulator: &mut SmsGgEmulator, state: &mut State) { 33 update_cram_texture(&mut ctx, emulator, state); 34 update_vram_texture(&mut ctx, emulator, state); 35 36 let screen_width = crate::screen_width(ctx.egui_ui); 37 38 Window::new("CRAM").default_width(screen_width * 0.95).show(ctx.egui_ui, |ui| { 39 let mut height = ui.available_width() * 0.125; 40 if height > ui.available_height() { 41 height = ui.available_height(); 42 } 43 let width = height * 8.0; 44 45 let cram_texture = state.cram_texture.as_ref().unwrap().1; 46 ui.image((cram_texture, Vec2::new(width, height))); 47 }); 48 49 Window::new("VRAM").default_width(screen_width * 0.95).show(ctx.egui_ui, |ui| { 50 ui.horizontal(|ui| { 51 ui.label("Palette"); 52 53 ui.radio_value(&mut state.vram_palette, 0, "0"); 54 ui.radio_value(&mut state.vram_palette, 1, "1"); 55 }); 56 57 ui.add_space(5.0); 58 59 let mut height = ui.available_width() * 0.5; 60 if height > ui.available_height() { 61 height = ui.available_height(); 62 } 63 let width = height * 2.0; 64 65 let vram_texture = state.vram_texture.as_ref().unwrap().1; 66 ui.image((vram_texture, Vec2::new(width, height))); 67 }); 68 69 Window::new("VDP Registers").default_open(false).default_pos(Pos2::new(5.0, 5.0)).show( 70 ctx.egui_ui, 71 |ui| { 72 ScrollArea::vertical().show(ui, |ui| { 73 Grid::new("smsgg_vdp_registers").num_columns(2).show(ui, |ui| { 74 emulator.dump_vdp_registers(|register, fields| { 75 ui.heading(format!("Register #{register}")); 76 ui.end_row(); 77 78 for &(name, value) in fields { 79 ui.label(format!(" {name}:")); 80 ui.label(value); 81 ui.end_row(); 82 } 83 }); 84 }); 85 }); 86 }, 87 ); 88} 89 90fn update_cram_texture( 91 ctx: &mut DebugRenderContext<'_>, 92 emulator: &mut SmsGgEmulator, 93 state: &mut State, 94) { 95 emulator.copy_cram(state.cram_buffer.as_mut()); 96 97 if state.cram_texture.is_none() { 98 let (wgpu_texture, egui_texture) = 99 crate::create_texture("debug_smsgg_cram", 16, 2, ctx.device, ctx.renderer); 100 state.cram_texture = Some((wgpu_texture, egui_texture)); 101 } 102 103 let (wgpu_texture, egui_texture) = state.cram_texture.as_ref().unwrap(); 104 105 crate::write_textures( 106 wgpu_texture, 107 *egui_texture, 108 bytemuck::cast_slice(state.cram_buffer.as_ref()), 109 ctx, 110 ); 111} 112 113fn update_vram_texture( 114 ctx: &mut DebugRenderContext<'_>, 115 emulator: &mut SmsGgEmulator, 116 state: &mut State, 117) { 118 emulator.copy_vram(state.vram_buffer.as_mut(), state.vram_palette, 32); 119 120 if state.vram_texture.is_none() { 121 let (wgpu_texture, egui_texture) = 122 crate::create_texture("debug_smsgg_vram", 32 * 8, 16 * 8, ctx.device, ctx.renderer); 123 state.vram_texture = Some((wgpu_texture, egui_texture)); 124 } 125 126 let (wgpu_texture, egui_texture) = state.vram_texture.as_ref().unwrap(); 127 128 crate::write_textures( 129 wgpu_texture, 130 *egui_texture, 131 bytemuck::cast_slice(state.vram_buffer.as_ref()), 132 ctx, 133 ); 134}