From 7356287030ab06816096c5cddaff7ca90145595c Mon Sep 17 00:00:00 2001 From: Simon Gellis Date: Sat, 15 Feb 2025 00:28:37 -0500 Subject: [PATCH] Finish object view --- src/window/vram/bgmap.rs | 23 ++++++-- src/window/vram/object.rs | 119 ++++++++++++++++++++++++-------------- src/window/vram/utils.rs | 57 ++++++++++++++++-- 3 files changed, 145 insertions(+), 54 deletions(-) diff --git a/src/window/vram/bgmap.rs b/src/window/vram/bgmap.rs index 67f1279..550933c 100644 --- a/src/window/vram/bgmap.rs +++ b/src/window/vram/bgmap.rs @@ -16,7 +16,7 @@ use crate::{ }, }; -use super::utils::{self, CharacterGrid}; +use super::utils::{self, CellData, CharacterGrid}; pub struct BgMapWindow { sim_id: SimId, @@ -94,7 +94,12 @@ impl BgMapWindow { ui.add(image); ui.section("Cell", |ui| { let cell = self.bgmaps.borrow().read::(self.cell_index); - let (char_index, mut vflip, mut hflip, palette_index) = utils::parse_cell(cell); + let CellData { + char_index, + mut vflip, + mut hflip, + palette_index, + } = CellData::parse(cell); TableBuilder::new(ui) .column(Column::remainder()) .column(Column::remainder()) @@ -245,7 +250,12 @@ impl BgMapRenderer { .iter() .enumerate() { - let (char_index, vflip, hflip, palette_index) = utils::parse_cell(*cell); + let CellData { + char_index, + vflip, + hflip, + palette_index, + } = CellData::parse(*cell); let char = chardata.range::(char_index * 8, 8); let palette = &colors[palette_index]; @@ -269,7 +279,12 @@ impl BgMapRenderer { let cell = bgmaps.read::(index); - let (char_index, vflip, hflip, palette_index) = utils::parse_cell(cell); + let CellData { + char_index, + vflip, + hflip, + palette_index, + } = CellData::parse(cell); let char = chardata.range::(char_index * 8, 8); let palette = if generic_palette { utils::generic_palette(Color32::RED) diff --git a/src/window/vram/object.rs b/src/window/vram/object.rs index 756aff0..0b543d7 100644 --- a/src/window/vram/object.rs +++ b/src/window/vram/object.rs @@ -16,7 +16,7 @@ use crate::{ }, }; -use super::utils; +use super::utils::{self, Object}; pub struct ObjectWindow { sim_id: SimId, @@ -31,8 +31,9 @@ pub struct ObjectWindow { impl ObjectWindow { pub fn new(sim_id: SimId, memory: &mut MemoryMonitor, vram: &mut VramProcessor) -> Self { let renderer = ObjectRenderer::new(sim_id, memory); - let ([object], params) = vram.add(renderer); - let loader = VramTextureLoader::new([("vram://object".into(), object)]); + let ([zoom, full], params) = vram.add(renderer); + let loader = + VramTextureLoader::new([("vram://zoom".into(), zoom), ("vram://full".into(), full)]); Self { sim_id, loader: Arc::new(loader), @@ -59,14 +60,27 @@ impl ObjectWindow { ui.add(NumberEdit::new(&mut self.index).range(0..1024)); }); }); + body.row(row_height, |mut row| { + row.col(|ui| { + ui.label("Address"); + }); + row.col(|ui| { + let address = 0x3e000 + self.index * 8; + let mut address_str = format!("{address:08x}"); + ui.add_enabled( + false, + TextEdit::singleline(&mut address_str).horizontal_align(Align::Max), + ); + }); + }); }); + let image = Image::new("vram://zoom") + .maintain_aspect_ratio(true) + .texture_options(TextureOptions::NEAREST); + ui.add(image); ui.section("Properties", |ui| { let object = self.objects.borrow().read::<[u16; 4]>(self.index); - let mut x = ((object[0] & 0x3ff) << 6 >> 6) as i16; - let mut parallax = ((object[1] & 0x3ff) << 6 >> 6) as i16; - let mut y = ((object[2] & 0x0ff) << 8 >> 8) as i16; - let (mut char_index, mut vflip, mut hflip, palette_index) = - utils::parse_cell(object[3]); + let mut obj = Object::parse(object); TableBuilder::new(ui) .column(Column::remainder()) .column(Column::remainder()) @@ -78,7 +92,7 @@ impl ObjectWindow { row.col(|ui| { ui.add_enabled( false, - NumberEdit::new(&mut char_index).range(0..2048), + NumberEdit::new(&mut obj.data.char_index).range(0..2048), ); }); }); @@ -87,7 +101,7 @@ impl ObjectWindow { ui.label("Palette"); }); row.col(|ui| { - let mut palette = format!("OBJ {}", palette_index); + let mut palette = format!("OBJ {}", obj.data.palette_index); ui.add_enabled( false, TextEdit::singleline(&mut palette).horizontal_align(Align::Max), @@ -99,7 +113,7 @@ impl ObjectWindow { ui.label("X"); }); row.col(|ui| { - ui.add_enabled(false, NumberEdit::new(&mut x).range(-512..512)); + ui.add_enabled(false, NumberEdit::new(&mut obj.x).range(-512..512)); }); }); body.row(row_height, |mut row| { @@ -107,7 +121,7 @@ impl ObjectWindow { ui.label("Y"); }); row.col(|ui| { - ui.add_enabled(false, NumberEdit::new(&mut y).range(-8..=224)); + ui.add_enabled(false, NumberEdit::new(&mut obj.y).range(-8..=224)); }); }); body.row(row_height, |mut row| { @@ -117,17 +131,27 @@ impl ObjectWindow { row.col(|ui| { ui.add_enabled( false, - NumberEdit::new(&mut parallax).range(-512..512), + NumberEdit::new(&mut obj.parallax).range(-512..512), ); }); }); body.row(row_height, |mut row| { row.col(|ui| { - let checkbox = Checkbox::new(&mut hflip, "H-flip"); + let checkbox = Checkbox::new(&mut obj.data.hflip, "H-flip"); ui.add_enabled(false, checkbox); }); row.col(|ui| { - let checkbox = Checkbox::new(&mut vflip, "V-flip"); + let checkbox = Checkbox::new(&mut obj.data.vflip, "V-flip"); + ui.add_enabled(false, checkbox); + }); + }); + body.row(row_height, |mut row| { + row.col(|ui| { + let checkbox = Checkbox::new(&mut obj.lon, "Left"); + ui.add_enabled(false, checkbox); + }); + row.col(|ui| { + let checkbox = Checkbox::new(&mut obj.ron, "Right"); ui.add_enabled(false, checkbox); }); }); @@ -153,7 +177,7 @@ impl ObjectWindow { } fn show_object(&mut self, ui: &mut Ui) { - let image = Image::new("vram://object") + let image = Image::new("vram://full") .fit_to_original_size(self.scale) .texture_options(TextureOptions::NEAREST); ui.add(image); @@ -172,7 +196,7 @@ impl AppWindow for ObjectWindow { fn initial_viewport(&self) -> ViewportBuilder { ViewportBuilder::default() .with_title(format!("Object Data ({})", self.sim_id)) - .with_inner_size((640.0, 480.0)) + .with_inner_size((640.0, 500.0)) } fn on_init(&mut self, ctx: &Context, _render_state: &egui_wgpu::RenderState) { @@ -239,50 +263,55 @@ impl ObjectRenderer { } } - fn render_object(&self, image: &mut VramImage, params: &ObjectParams, eye: Eye) { + fn render_object(&self, image: &mut VramImage, params: &ObjectParams, use_pos: bool, eye: Eye) { let chardata = self.chardata.borrow(); let objects = self.objects.borrow(); let brightness = self.brightness.borrow(); let palettes = self.palettes.borrow(); let object: [u16; 4] = objects.read(params.index); + let obj = Object::parse(object); - let ron = object[1] & 0x4000 != 0; - let lon = object[1] & 0x8000 != 0; if match eye { - Eye::Left => !lon, - Eye::Right => !ron, + Eye::Left => !obj.lon, + Eye::Right => !obj.ron, } { return; } let brts = brightness.range::(0, 8); - - let x = ((object[0] & 0x3ff) << 6 >> 6) as i16; - let parallax = ((object[1] & 0x3ff) << 6 >> 6) as i16; - let y = ((object[2] & 0x0ff) << 8 >> 8) as i16; - - let (x, color) = match eye { - Eye::Left => (x - parallax, params.left_color), - Eye::Right => (x + parallax, params.right_color), + let (x, y) = if use_pos { + let x = match eye { + Eye::Left => obj.x - obj.parallax, + Eye::Right => obj.x + obj.parallax, + }; + (x, obj.y) + } else { + (0, 0) }; - let (char_index, vflip, hflip, palette_index) = utils::parse_cell(object[3]); - let char = chardata.range::(char_index * 8, 8); + let color = match eye { + Eye::Left => params.left_color, + Eye::Right => params.right_color, + }; + + let char = chardata.range::(obj.data.char_index * 8, 8); let palette = if params.generic_palette { utils::generic_palette(color) } else { - utils::parse_palette(palettes.read(8 + palette_index * 2), brts, color) + utils::parse_palette(palettes.read(8 + obj.data.palette_index * 2), brts, color) }; for row in 0..8 { let real_y = y + row as i16; - if !(0..384).contains(&real_y) { + if !(0..224).contains(&real_y) { continue; } - for (col, pixel) in utils::read_char_row(char, hflip, vflip, row).enumerate() { + for (col, pixel) in + utils::read_char_row(char, obj.data.hflip, obj.data.vflip, row).enumerate() + { let real_x = x + col as i16; - if !(0..224).contains(&real_x) { + if !(0..384).contains(&real_x) { continue; } image.add((real_x as usize, real_y as usize), palette[pixel as usize]); @@ -291,17 +320,19 @@ impl ObjectRenderer { } } -impl VramRenderer<1> for ObjectRenderer { +impl VramRenderer<2> for ObjectRenderer { type Params = ObjectParams; - fn sizes(&self) -> [[usize; 2]; 1] { - [[384, 224]] + fn sizes(&self) -> [[usize; 2]; 2] { + [[8, 8], [384, 224]] } - fn render(&mut self, params: &Self::Params, images: &mut [VramImage; 1]) { - let image = &mut images[0]; - image.clear(); - self.render_object(image, params, Eye::Left); - self.render_object(image, params, Eye::Right); + fn render(&mut self, params: &Self::Params, images: &mut [VramImage; 2]) { + images[0].clear(); + self.render_object(&mut images[0], params, false, Eye::Left); + self.render_object(&mut images[0], params, false, Eye::Right); + images[1].clear(); + self.render_object(&mut images[1], params, true, Eye::Left); + self.render_object(&mut images[1], params, true, Eye::Right); } } diff --git a/src/window/vram/utils.rs b/src/window/vram/utils.rs index e8bf69f..c605302 100644 --- a/src/window/vram/utils.rs +++ b/src/window/vram/utils.rs @@ -28,12 +28,57 @@ pub fn parse_palette(palette: u8, brts: &[u8], color: Color32) -> [Color32; 4] { ] } -pub fn parse_cell(cell: u16) -> (usize, bool, bool, usize) { - let char_index = (cell & 0x7ff) as usize; - let vflip = cell & 0x1000 != 0; - let hflip = cell & 0x2000 != 0; - let palette_index = (cell >> 14) as usize; - (char_index, vflip, hflip, palette_index) +pub struct Object { + pub x: i16, + pub lon: bool, + pub ron: bool, + pub parallax: i16, + pub y: i16, + pub data: CellData, +} + +impl Object { + pub fn parse(object: [u16; 4]) -> Self { + let x = ((object[0] & 0x3ff) << 6 >> 6) as i16; + let parallax = ((object[1] & 0x3ff) << 6 >> 6) as i16; + let lon = object[1] & 0x8000 != 0; + let ron = object[1] & 0x4000 != 0; + let y = (object[2] & 0x0ff) as i16; + // Y is stored as the bottom 8 bits of an i16, + // so only sign extend if it's out of range. + let y = if y > 224 { y << 8 >> 8 } else { y }; + let data = CellData::parse(object[3]); + Self { + x, + lon, + ron, + parallax, + y, + data, + } + } +} + +pub struct CellData { + pub palette_index: usize, + pub hflip: bool, + pub vflip: bool, + pub char_index: usize, +} + +impl CellData { + pub fn parse(cell: u16) -> Self { + let char_index = (cell & 0x7ff) as usize; + let vflip = cell & 0x1000 != 0; + let hflip = cell & 0x2000 != 0; + let palette_index = (cell >> 14) as usize; + Self { + char_index, + vflip, + hflip, + palette_index, + } + } } pub fn read_char_row(