1use crate::{DebugRenderContext, DebugRenderFn}; 2use egui::{Context, Grid, Vec2, Window}; 3use jgenesis_common::frontend::Color; 4use pce_core::api::PcEngineEmulator; 5 6const VRAM_TEXTURE_WIDTH: usize = 64; 7const VRAM_TEXTURE_HEIGHT: usize = 32; 8 9struct State { 10 palettes_buffer: Vec<Color>, 11 bg_palettes_texture: Option<egui::TextureId>, 12 sprite_palettes_texture: Option<egui::TextureId>, 13 vram_palette: u16, 14 vram_buffer_2d: Box<[[Color; 64]; 2048]>, 15 vram_buffer_1d: Vec<Color>, 16 vram_texture: Option<egui::TextureId>, 17} 18 19impl State { 20 fn new() -> Self { 21 Self { 22 palettes_buffer: vec![Color::default(); 512], 23 bg_palettes_texture: None, 24 sprite_palettes_texture: None, 25 vram_palette: 0, 26 vram_buffer_2d: vec![[Color::default(); 64]; 2048] 27 .into_boxed_slice() 28 .try_into() 29 .unwrap(), 30 vram_buffer_1d: vec![Color::default(); 64 * 2048], 31 vram_texture: None, 32 } 33 } 34} 35 36#[must_use] 37pub fn render_fn() -> Box<DebugRenderFn<PcEngineEmulator>> { 38 let mut state = State::new(); 39 Box::new(move |ctx, emulator| render(ctx, emulator, &mut state)) 40} 41 42fn render(ctx: DebugRenderContext<'_>, emulator: &mut PcEngineEmulator, state: &mut State) { 43 update_palette_textures(ctx.egui_ui, emulator, state); 44 45 Window::new("BG Palettes").resizable(true).default_width(400.0).show(ctx.egui_ui, |ui| { 46 let size = clamp_palette_image_size(ui.available_size()); 47 48 if let Some(bg_palettes_texture) = state.bg_palettes_texture { 49 ui.image((bg_palettes_texture, size)); 50 } 51 }); 52 53 Window::new("Sprite Palettes").resizable(true).default_width(400.0).show(ctx.egui_ui, |ui| { 54 let size = clamp_palette_image_size(ui.available_size()); 55 56 if let Some(sprite_palettes_texture) = state.sprite_palettes_texture { 57 ui.image((sprite_palettes_texture, size)); 58 } 59 }); 60 61 Window::new("VRAM").resizable(true).show(ctx.egui_ui, |ui| { 62 update_vram_texture(ui, emulator, state); 63 64 ui.spacing_mut().item_spacing = [2.0, 3.0].into(); 65 66 Grid::new("pce_vram_grid").show(ui, |ui| { 67 ui.label("BG palette:"); 68 69 for palette in 0..16 { 70 ui.radio_value(&mut state.vram_palette, palette, palette.to_string()); 71 } 72 73 ui.end_row(); 74 75 ui.label("Sprite palette:"); 76 77 for palette in 0..16 { 78 ui.radio_value(&mut state.vram_palette, palette | (1 << 4), palette.to_string()); 79 } 80 81 ui.end_row(); 82 }); 83 84 if let Some(vram_texture) = state.vram_texture { 85 let mut size = ui.available_size(); 86 if size.y > size.x * 0.5 { 87 size.y = size.x * 0.5; 88 } 89 if size.x > size.y * 2.0 { 90 size.x = size.y * 2.0; 91 } 92 93 ui.image((vram_texture, size)); 94 } 95 }); 96} 97 98fn clamp_palette_image_size(mut size: Vec2) -> Vec2 { 99 if size.y > size.x { 100 size.y = size.x; 101 } 102 103 if size.x > size.y { 104 size.x = size.y; 105 } 106 107 size 108} 109 110fn update_palette_textures(ctx: &Context, emulator: &mut PcEngineEmulator, state: &mut State) { 111 emulator.dump_palettes(&mut state.palettes_buffer); 112 113 crate::update_egui_texture( 114 ctx, 115 [16, 16], 116 &state.palettes_buffer[..256], 117 &mut state.bg_palettes_texture, 118 ); 119 120 crate::update_egui_texture( 121 ctx, 122 [16, 16], 123 &state.palettes_buffer[256..], 124 &mut state.sprite_palettes_texture, 125 ); 126} 127 128fn update_vram_texture(ctx: &Context, emulator: &mut PcEngineEmulator, state: &mut State) { 129 const WIDTH: usize = VRAM_TEXTURE_WIDTH; 130 131 emulator.dump_vram(state.vram_palette, state.vram_buffer_2d.as_mut_slice()); 132 133 // Copy from 2D buffer to a 1D buffer, 64x32 tiles 134 for (tile_number, tile) in state.vram_buffer_2d.iter().enumerate() { 135 let tile_base_addr = (tile_number / WIDTH) * WIDTH * 8 * 8 + (tile_number % WIDTH) * 8; 136 137 for tile_row in 0..8 { 138 for tile_col in 0..8 { 139 state.vram_buffer_1d[tile_base_addr + tile_row * WIDTH * 8 + tile_col] = 140 tile[8 * tile_row + tile_col]; 141 } 142 } 143 } 144 145 crate::update_egui_texture( 146 ctx, 147 [8 * VRAM_TEXTURE_WIDTH, 8 * VRAM_TEXTURE_HEIGHT], 148 &state.vram_buffer_1d, 149 &mut state.vram_texture, 150 ); 151}