View hbias worlds
This commit is contained in:
parent
2a4599756c
commit
3cdc0583a6
|
@ -98,8 +98,11 @@ macro_rules! primitive_memory_value_impl {
|
|||
}
|
||||
|
||||
primitive_memory_value_impl!(u8, 1);
|
||||
primitive_memory_value_impl!(i8, 2);
|
||||
primitive_memory_value_impl!(u16, 2);
|
||||
primitive_memory_value_impl!(i16, 2);
|
||||
primitive_memory_value_impl!(u32, 4);
|
||||
primitive_memory_value_impl!(i32, 2);
|
||||
|
||||
impl<const N: usize, T: MemoryValue> MemoryValue for [T; N] {
|
||||
#[inline]
|
||||
|
|
|
@ -34,10 +34,11 @@ pub trait UiExt {
|
|||
|
||||
impl UiExt for Ui {
|
||||
fn section(&mut self, title: impl Into<String>, add_contents: impl FnOnce(&mut Ui)) {
|
||||
let title: String = title.into();
|
||||
let mut frame = Frame::group(self.style());
|
||||
frame.outer_margin.top += 10.0;
|
||||
frame.inner_margin.top += 2.0;
|
||||
let res = frame.show(self, add_contents);
|
||||
let res = self.push_id(&title, |ui| frame.show(ui, add_contents));
|
||||
let text = RichText::new(title).background_color(self.style().visuals.panel_fill);
|
||||
let old_rect = res.response.rect;
|
||||
let mut text_rect = old_rect;
|
||||
|
@ -133,12 +134,14 @@ impl<'a, T: Number> NumberEdit<'a, T> {
|
|||
|
||||
impl<T: Number> Widget for NumberEdit<'_, T> {
|
||||
fn ui(self, ui: &mut Ui) -> Response {
|
||||
let id = ui.id();
|
||||
|
||||
let (last_value, mut str, focus) = ui.memory(|m| {
|
||||
let (lv, s) = m
|
||||
.data
|
||||
.get_temp(ui.id())
|
||||
.get_temp(id)
|
||||
.unwrap_or((*self.value, self.value.to_string()));
|
||||
let focus = m.has_focus(ui.id());
|
||||
let focus = m.has_focus(id);
|
||||
(lv, s, focus)
|
||||
});
|
||||
let mut stale = false;
|
||||
|
@ -174,7 +177,7 @@ impl<T: Number> Widget for NumberEdit<'_, T> {
|
|||
}
|
||||
let text = TextEdit::singleline(&mut str)
|
||||
.horizontal_align(Align::Max)
|
||||
.id(ui.id())
|
||||
.id(id)
|
||||
.margin(Margin {
|
||||
left: 4.0,
|
||||
right: 20.0,
|
||||
|
@ -242,7 +245,7 @@ impl<T: Number> Widget for NumberEdit<'_, T> {
|
|||
stale = true;
|
||||
}
|
||||
if stale {
|
||||
ui.memory_mut(|m| m.data.insert_temp(ui.id(), (*self.value, str)));
|
||||
ui.memory_mut(|m| m.data.insert_temp(id, (*self.value, str)));
|
||||
}
|
||||
res
|
||||
}
|
||||
|
|
|
@ -24,7 +24,9 @@ pub struct WorldWindow {
|
|||
sim_id: SimId,
|
||||
loader: Arc<VramTextureLoader>,
|
||||
worlds: MemoryView,
|
||||
bgmaps: MemoryView,
|
||||
index: usize,
|
||||
param_index: usize,
|
||||
generic_palette: bool,
|
||||
params: VramParams<WorldParams>,
|
||||
scale: f32,
|
||||
|
@ -45,7 +47,9 @@ impl WorldWindow {
|
|||
sim_id,
|
||||
loader: Arc::new(loader),
|
||||
worlds: memory.watch(sim_id, 0x3d800, 0x400),
|
||||
bgmaps: memory.watch(sim_id, 0x00020000, 0x20000),
|
||||
index: params.index,
|
||||
param_index: 0,
|
||||
generic_palette: params.generic_palette,
|
||||
params,
|
||||
scale: 1.0,
|
||||
|
@ -262,6 +266,57 @@ impl WorldWindow {
|
|||
});
|
||||
});
|
||||
});
|
||||
if world.header.mode == WorldMode::HBias {
|
||||
ui.section("H-bias", |ui| {
|
||||
TableBuilder::new(ui)
|
||||
.column(Column::remainder())
|
||||
.column(Column::remainder())
|
||||
.body(|mut body| {
|
||||
body.row(row_height, |mut row| {
|
||||
row.col(|ui| {
|
||||
ui.label("Index");
|
||||
});
|
||||
row.col(|ui| {
|
||||
ui.add(NumberEdit::new(&mut self.param_index).range(0..32));
|
||||
});
|
||||
});
|
||||
let base = world.param_base + self.param_index * 2;
|
||||
let mut param = HBiasParam::load(&self.bgmaps.borrow(), base);
|
||||
body.row(row_height, |mut row| {
|
||||
row.col(|ui| {
|
||||
ui.label("Address");
|
||||
});
|
||||
row.col(|ui| {
|
||||
let address = 0x00020000 + base * 2;
|
||||
let mut address_str = format!("{address:08x}");
|
||||
ui.add_enabled(
|
||||
false,
|
||||
TextEdit::singleline(&mut address_str)
|
||||
.horizontal_align(Align::Max),
|
||||
);
|
||||
});
|
||||
});
|
||||
body.row(row_height, |mut row| {
|
||||
row.col(|ui| {
|
||||
ui.label("Left");
|
||||
});
|
||||
row.col(|ui| {
|
||||
ui.add(NumberEdit::new(&mut param.left).range(-4096..4096));
|
||||
});
|
||||
});
|
||||
body.row(row_height, |mut row| {
|
||||
row.col(|ui| {
|
||||
ui.label("Right");
|
||||
});
|
||||
row.col(|ui| {
|
||||
ui.add(NumberEdit::new(&mut param.right).range(-4096..4096));
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
} else {
|
||||
self.param_index = 0;
|
||||
}
|
||||
ui.section("Display", |ui| {
|
||||
ui.horizontal(|ui| {
|
||||
ui.label("Scale");
|
||||
|
@ -497,44 +552,39 @@ impl WorldRenderer {
|
|||
]
|
||||
};
|
||||
|
||||
let mut chars = CharCache::new(self.chardata.borrow());
|
||||
let mut cells = CellCache::new(self.bgmaps.borrow());
|
||||
let chardata = self.chardata.borrow();
|
||||
let bgmaps = self.bgmaps.borrow();
|
||||
let mut chars = [CharCache::new(&chardata), CharCache::new(&chardata)];
|
||||
let mut cells = [CellCache::new(&bgmaps), CellCache::new(&bgmaps)];
|
||||
let mut source = SourceCoordCalculator::new(&bgmaps, &world);
|
||||
|
||||
for y in 0..height {
|
||||
let dy = y + world.dst_y;
|
||||
if !(0..224).contains(&dy) {
|
||||
continue;
|
||||
}
|
||||
let sy = y + world.src_y;
|
||||
|
||||
// left side
|
||||
for x in 0..world.width {
|
||||
let dx = x + world.dst_x - world.dst_parallax;
|
||||
if !(0..384).contains(&dx) {
|
||||
continue;
|
||||
}
|
||||
let sx = x + world.src_x - world.src_parallax;
|
||||
if world.header.lon && (0..384).contains(&dx) {
|
||||
let (sx, sy) = source.left(x, y);
|
||||
|
||||
let cell_index = world.source_cell(sx, sy);
|
||||
let cell = cells.get(cell_index);
|
||||
let char = chars.get(cell.char_index);
|
||||
let cell = cells[0].get(cell_index);
|
||||
let char = chars[0].get(cell.char_index);
|
||||
let row = (sy & 0x7) as usize;
|
||||
let col = (sx & 0x7) as usize;
|
||||
let pixel = utils::read_char_pixel(char, cell.hflip, cell.vflip, row, col);
|
||||
image.add((dx as usize, dy as usize), colors[0][pixel as usize]);
|
||||
}
|
||||
|
||||
// right side
|
||||
for x in 0..world.width {
|
||||
let dx = x + world.dst_x + world.dst_parallax;
|
||||
if !(0..384).contains(&dx) {
|
||||
continue;
|
||||
}
|
||||
let sx = x + world.src_x + world.src_parallax;
|
||||
if world.header.ron && (0..384).contains(&dx) {
|
||||
let (sx, sy) = source.right(x, y);
|
||||
|
||||
let cell_index = world.source_cell(sx, sy);
|
||||
let cell = cells.get(cell_index);
|
||||
let char = chars.get(cell.char_index);
|
||||
let cell = cells[1].get(cell_index);
|
||||
let char = chars[1].get(cell.char_index);
|
||||
let row = (sy & 0x7) as usize;
|
||||
let col = (sx & 0x7) as usize;
|
||||
let pixel = utils::read_char_pixel(char, cell.hflip, cell.vflip, row, col);
|
||||
|
@ -542,6 +592,7 @@ impl WorldRenderer {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl VramRenderer<1> for WorldRenderer {
|
||||
|
@ -556,7 +607,7 @@ impl VramRenderer<1> for WorldRenderer {
|
|||
|
||||
let worlds = self.worlds.borrow();
|
||||
let header = WorldHeader::parse(worlds.read(params.index * 16));
|
||||
if header.end || (!header.lon && header.ron) {
|
||||
if header.end || (!header.lon && !header.ron) {
|
||||
image.clear();
|
||||
return;
|
||||
}
|
||||
|
@ -693,13 +744,13 @@ impl Display for WorldMode {
|
|||
}
|
||||
|
||||
struct CellCache<'a> {
|
||||
bgmaps: MemoryRef<'a>,
|
||||
bgmaps: &'a MemoryRef<'a>,
|
||||
index: usize,
|
||||
cell: CellData,
|
||||
}
|
||||
|
||||
impl<'a> CellCache<'a> {
|
||||
fn new(bgmaps: MemoryRef<'a>) -> Self {
|
||||
fn new(bgmaps: &'a MemoryRef<'a>) -> Self {
|
||||
Self {
|
||||
bgmaps,
|
||||
index: 0x10000,
|
||||
|
@ -718,13 +769,13 @@ impl<'a> CellCache<'a> {
|
|||
}
|
||||
|
||||
struct CharCache<'a> {
|
||||
chardata: MemoryRef<'a>,
|
||||
chardata: &'a MemoryRef<'a>,
|
||||
index: usize,
|
||||
char: [u16; 8],
|
||||
}
|
||||
|
||||
impl<'a> CharCache<'a> {
|
||||
fn new(chardata: MemoryRef<'a>) -> Self {
|
||||
fn new(chardata: &'a MemoryRef<'a>) -> Self {
|
||||
Self {
|
||||
chardata,
|
||||
index: 2048,
|
||||
|
@ -740,3 +791,82 @@ impl<'a> CharCache<'a> {
|
|||
&self.char
|
||||
}
|
||||
}
|
||||
|
||||
struct SourceCoordCalculator<'a> {
|
||||
params: &'a MemoryRef<'a>,
|
||||
world: &'a World,
|
||||
y: i16,
|
||||
param: SourceParam,
|
||||
}
|
||||
|
||||
impl<'a> SourceCoordCalculator<'a> {
|
||||
fn new(params: &'a MemoryRef<'a>, world: &'a World) -> Self {
|
||||
Self {
|
||||
params,
|
||||
world,
|
||||
y: -1,
|
||||
param: SourceParam::Normal,
|
||||
}
|
||||
}
|
||||
|
||||
fn left(&mut self, x: i16, y: i16) -> (i16, i16) {
|
||||
self.update_param(y);
|
||||
match &self.param {
|
||||
SourceParam::HBias(HBiasParam { left, .. }) => {
|
||||
let sx = x + self.world.src_x - self.world.src_parallax + *left;
|
||||
let sy = y + self.world.src_y;
|
||||
(sx, sy)
|
||||
}
|
||||
SourceParam::Normal => {
|
||||
let sx = x + self.world.src_x - self.world.src_parallax;
|
||||
let sy = y + self.world.src_y;
|
||||
(sx, sy)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn right(&mut self, x: i16, y: i16) -> (i16, i16) {
|
||||
self.update_param(y);
|
||||
match &self.param {
|
||||
SourceParam::HBias(HBiasParam { right, .. }) => {
|
||||
let sx = x + self.world.src_x + self.world.src_parallax + *right;
|
||||
let sy = y + self.world.src_y;
|
||||
(sx, sy)
|
||||
}
|
||||
SourceParam::Normal => {
|
||||
let sx = x + self.world.src_x + self.world.src_parallax;
|
||||
let sy = y + self.world.src_y;
|
||||
(sx, sy)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn update_param(&mut self, y: i16) {
|
||||
if self.y == y {
|
||||
return;
|
||||
}
|
||||
if self.world.header.mode == WorldMode::HBias {
|
||||
let base = self.world.param_base + (2 * y as usize);
|
||||
self.param = SourceParam::HBias(HBiasParam::load(self.params, base));
|
||||
}
|
||||
self.y = y;
|
||||
}
|
||||
}
|
||||
|
||||
enum SourceParam {
|
||||
Normal,
|
||||
HBias(HBiasParam),
|
||||
}
|
||||
|
||||
struct HBiasParam {
|
||||
left: i16,
|
||||
right: i16,
|
||||
}
|
||||
|
||||
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 }
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue