From 2c71c20f204215ba0c3e218c33aa1d8772150f9e Mon Sep 17 00:00:00 2001 From: Simon Gellis Date: Mon, 17 Feb 2025 22:19:38 -0500 Subject: [PATCH] Edit worlds --- src/window/vram/world.rs | 169 ++++++++++++++++++++++++++++++++++----- 1 file changed, 147 insertions(+), 22 deletions(-) diff --git a/src/window/vram/world.rs b/src/window/vram/world.rs index 4c0df76..4596b1b 100644 --- a/src/window/vram/world.rs +++ b/src/window/vram/world.rs @@ -10,7 +10,7 @@ use fixed::{ FixedI32, }; use num_derive::{FromPrimitive, ToPrimitive}; -use num_traits::FromPrimitive; +use num_traits::{FromPrimitive, ToPrimitive}; use crate::{ emulator::SimId, @@ -27,6 +27,7 @@ use super::utils::{self, shade, CellData, Object}; pub struct WorldWindow { sim_id: SimId, loader: Arc, + memory: Arc, worlds: MemoryView, bgmaps: MemoryView, index: usize, @@ -37,7 +38,7 @@ pub struct WorldWindow { } impl WorldWindow { - pub fn new(sim_id: SimId, memory: &MemoryClient, vram: &mut VramProcessor) -> Self { + pub fn new(sim_id: SimId, memory: &Arc, vram: &mut VramProcessor) -> Self { let initial_params = WorldParams { index: 31, generic_palette: false, @@ -50,7 +51,8 @@ impl WorldWindow { Self { sim_id, loader: Arc::new(loader), - worlds: memory.watch(sim_id, 0x3d800, 0x400), + memory: memory.clone(), + worlds: memory.watch(sim_id, 0x0003d800, 0x400), bgmaps: memory.watch(sim_id, 0x00020000, 0x20000), index: params.index, param_index: 0, @@ -80,7 +82,7 @@ impl WorldWindow { ui.label("Address"); }); row.col(|ui| { - let address = 0x3d800 + self.index * 32; + let address = 0x0003d800 + self.index * 32; let mut address_str = format!("{address:08x}"); ui.add_enabled( false, @@ -89,7 +91,7 @@ impl WorldWindow { }); }); }); - let data = { + let mut data = { let worlds = self.worlds.borrow(); worlds.read(self.index) }; @@ -270,6 +272,10 @@ impl WorldWindow { }); }); }); + if world.update(&mut data) { + let address = 0x0003d800 + self.index * 32; + self.memory.write(self.sim_id, address as u32, &data); + } if world.header.mode == WorldMode::HBias { ui.section("H-bias", |ui| { TableBuilder::new(ui) @@ -317,6 +323,7 @@ impl WorldWindow { ui.add(NumberEdit::new(&mut param.right).range(-4096..4096)); }); }); + param.save(&self.memory, self.sim_id, base); }); }); } else if world.header.mode == WorldMode::Affine { @@ -390,6 +397,7 @@ impl WorldWindow { ui.add(NumberEdit::new(&mut param.dy).precision(9)); }); }); + param.save(&self.memory, self.sim_id, base); }); }); } else { @@ -599,6 +607,12 @@ impl WorldRenderer { fn render_world(&mut self, world: World, params: &WorldParams, image: &mut VramImage) { image.clear(); + let width = if world.header.mode == WorldMode::Affine { + world.width & 0x03ff + } else { + world.width + }; + let height = if world.header.mode == WorldMode::Affine { world.height.max(8) } else { @@ -606,7 +620,7 @@ impl WorldRenderer { }; let dx1 = world.dst_x; - let dx2 = dx1 + world.width; + let dx2 = dx1 + width; if dx1 - world.dst_parallax > 384 || dx2 + world.dst_parallax < 0 { return; } @@ -642,7 +656,7 @@ impl WorldRenderer { continue; } - for x in 0..world.width { + for x in 0..width { let dx = x + world.dst_x - world.dst_parallax; if world.header.lon && (0..384).contains(&dx) { let (sx, sy) = source.left(x, y); @@ -739,6 +753,52 @@ impl World { } } + fn update(&self, source: &mut [u16; 16]) -> bool { + let mut changed = self.header.update(&mut source[0]); + + let new_dst_x = (self.dst_x as u16 & 0x03ff) | (source[1] & 0xfc00); + changed |= source[1] != new_dst_x; + source[1] = new_dst_x; + + let new_dst_parallax = (self.dst_parallax as u16 & 0x03ff) | (source[2] & 0xfc00); + changed |= source[2] != new_dst_parallax; + source[2] = new_dst_parallax; + + let new_dst_y = self.dst_y as u16; + changed |= source[3] != new_dst_y; + source[3] = new_dst_y; + + let new_src_x = (self.src_x as u16 & 0x1fff) | (source[4] & 0xe000); + changed |= source[4] != new_src_x; + source[4] = new_src_x; + + let new_src_parallax = (self.src_parallax as u16 & 0x7fff) | (source[4] & 0x8000); + changed |= source[5] != new_src_parallax; + source[5] = new_src_parallax; + + let new_src_y = (self.src_y as u16 & 0x1fff) | (source[6] & 0xe000); + changed |= source[6] != new_src_y; + source[6] = new_src_y; + + let new_width = ((self.width - 1) as u16 & 0x1fff) | (source[7] & 0xe000); + changed |= source[7] != new_width; + source[7] = new_width; + + let new_height = (self.height - 1) as u16; + changed |= source[8] != new_height; + source[8] = new_height; + + let new_param_base = self.param_base as u16; + changed |= source[9] != new_param_base; + source[9] = new_param_base; + + let new_overplane = self.overplane as u16; + changed |= source[10] != new_overplane; + source[10] = new_overplane; + + changed + } + fn source_cell(&self, sx: i16, sy: i16) -> usize { if self.header.over { let bg_width = 1 << self.header.scx << 9; @@ -794,6 +854,21 @@ impl WorldHeader { base, } } + + fn update(&self, source: &mut u16) -> bool { + let new_value = (*source & 0x0030) + | if self.lon { 0x8000 } else { 0x0000 } + | if self.ron { 0x4000 } else { 0x0000 } + | self.mode.to_u16().unwrap() << 12 + | ((self.scx as u16) << 10) + | ((self.scy as u16) << 8) + | if self.over { 0x0080 } else { 0x0000 } + | if self.end { 0x0040 } else { 0x0000 } + | (self.base as u16 & 0x000f); + let changed = *source != new_value; + *source = new_value; + changed + } } #[derive(Clone, Copy, PartialEq, Eq, FromPrimitive, ToPrimitive)] @@ -954,13 +1029,29 @@ enum SourceParam { struct HBiasParam { left: i16, right: i16, + data: [u16; 2], } impl HBiasParam { fn load(params: &MemoryRef, index: usize) -> Self { - let left = params.read::(index) << 3 >> 3; - let right = params.read::(index | 1) << 3 >> 3; - Self { left, right } + let data = [params.read::(index), params.read::(index | 1)]; + let left = (data[0] as i16) << 3 >> 3; + let right = (data[1] as i16) << 3 >> 3; + Self { left, right, data } + } + + fn save(&self, memory: &MemoryClient, sim: SimId, index: usize) { + let new_left = (self.left as u16 & 0x1fff) | (self.data[0] & 0xe000); + if new_left != self.data[0] { + let address = 0x00020000 + (index * 2); + memory.write(sim, address as u32, &new_left); + } + + let new_right = (self.right as u16 & 0x1fff) | (self.data[1] & 0xe000); + if new_right != self.data[1] { + let address = 0x00020000 + ((index | 1) * 2); + memory.write(sim, address as u32, &new_right); + } } } @@ -970,23 +1061,24 @@ struct AffineParam { src_y: FixedI32, dx: FixedI32, dy: FixedI32, + data: [u16; 5], } impl AffineParam { fn load(params: &MemoryRef, index: usize) -> Self { - let src_x = params.read::(index & 0x1ffff); - let src_x = FixedI32::from_bits(src_x as i32); + let data = [ + params.read(index & 0xffff), + params.read((index + 1) & 0xffff), + params.read((index + 2) & 0xffff), + params.read((index + 3) & 0xffff), + params.read((index + 4) & 0xffff), + ]; - let src_parallax = params.read::((index + 1) & 0x1ffff); - - let src_y = params.read::((index + 2) & 0x1ffff); - let src_y = FixedI32::from_bits(src_y as i32); - - let dx = params.read::((index + 3) & 0x1ffff); - let dx = FixedI32::from_bits(dx as i32); - - let dy = params.read::((index + 4) & 0x1ffff); - let dy = FixedI32::from_bits(dy as i32); + let src_x = FixedI32::from_bits(data[0] as i16 as i32); + let src_parallax = data[1] as i16; + let src_y = FixedI32::from_bits(data[2] as i16 as i32); + let dx = FixedI32::from_bits(data[3] as i16 as i32); + let dy = FixedI32::from_bits(data[4] as i16 as i32); AffineParam { src_x, @@ -994,6 +1086,39 @@ impl AffineParam { src_y, dx, dy, + data, + } + } + + fn save(&self, memory: &MemoryClient, sim: SimId, index: usize) { + let new_src_x = self.src_x.to_bits() as u16; + if new_src_x != self.data[0] { + let address = 0x00020000 + 2 * (index & 0xffff); + memory.write(sim, address as u32, &new_src_x); + } + + let new_src_parallax = self.src_parallax as u16; + if new_src_parallax != self.data[1] { + let address = 0x00020000 + 2 * ((index + 1) & 0xffff); + memory.write(sim, address as u32, &new_src_parallax); + } + + let new_src_y = self.src_y.to_bits() as u16; + if new_src_y != self.data[2] { + let address = 0x00020000 + 2 * ((index + 2) & 0xffff); + memory.write(sim, address as u32, &new_src_y); + } + + let new_dx = self.dx.to_bits() as u16; + if new_dx != self.data[3] { + let address = 0x00020000 + 2 * ((index + 3) & 0xffff); + memory.write(sim, address as u32, &new_dx); + } + + let new_dy = self.dy.to_bits() as u16; + if new_dy != self.data[4] { + let address = 0x00020000 + 2 * ((index + 4) & 0xffff); + memory.write(sim, address as u32, &new_dy); } } }