VIP inspection tooling #4
			
				
			
		
		
		
	| 
						 | 
				
			
			@ -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<VramTextureLoader>,
 | 
			
		||||
    memory: Arc<MemoryClient>,
 | 
			
		||||
    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<MemoryClient>, 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::<i16>(index) << 3 >> 3;
 | 
			
		||||
        let right = params.read::<i16>(index | 1) << 3 >> 3;
 | 
			
		||||
        Self { left, right }
 | 
			
		||||
        let data = [params.read::<u16>(index), params.read::<u16>(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<U3>,
 | 
			
		||||
    dx: FixedI32<U9>,
 | 
			
		||||
    dy: FixedI32<U9>,
 | 
			
		||||
    data: [u16; 5],
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl AffineParam {
 | 
			
		||||
    fn load(params: &MemoryRef, index: usize) -> Self {
 | 
			
		||||
        let src_x = params.read::<i16>(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::<i16>((index + 1) & 0x1ffff);
 | 
			
		||||
 | 
			
		||||
        let src_y = params.read::<i16>((index + 2) & 0x1ffff);
 | 
			
		||||
        let src_y = FixedI32::from_bits(src_y as i32);
 | 
			
		||||
 | 
			
		||||
        let dx = params.read::<i16>((index + 3) & 0x1ffff);
 | 
			
		||||
        let dx = FixedI32::from_bits(dx as i32);
 | 
			
		||||
 | 
			
		||||
        let dy = params.read::<i16>((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);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue