diff --git a/src/window/game.rs b/src/window/game.rs index 2e4823b..e3dbe9b 100644 --- a/src/window/game.rs +++ b/src/window/game.rs @@ -124,25 +124,38 @@ impl GameWindow { ChildWindow::CharacterData => AppWrapper::of_dyn(CharacterDataWindow::new( self.sim_id, &self.memory, + &self.persistence, + &self.images, + )), + ChildWindow::BgMap => AppWrapper::of_dyn(BgMapWindow::new( + self.sim_id, + &self.memory, + &self.persistence, + &self.images, + )), + ChildWindow::Objects => AppWrapper::of_dyn(ObjectWindow::new( + self.sim_id, + &self.memory, + &self.persistence, + &self.images, + )), + ChildWindow::Worlds => AppWrapper::of_dyn(WorldWindow::new( + self.sim_id, + &self.memory, + &self.persistence, &self.images, )), - ChildWindow::BgMap => { - AppWrapper::of_dyn(BgMapWindow::new(self.sim_id, &self.memory, &self.images)) - } - ChildWindow::Objects => { - AppWrapper::of_dyn(ObjectWindow::new(self.sim_id, &self.memory, &self.images)) - } - ChildWindow::Worlds => { - AppWrapper::of_dyn(WorldWindow::new(self.sim_id, &self.memory, &self.images)) - } ChildWindow::FrameBuffers => AppWrapper::of_dyn(FrameBufferWindow::new( self.sim_id, &self.memory, + &self.persistence, &self.images, )), - ChildWindow::Registers => { - AppWrapper::of_dyn(RegisterWindow::new(self.sim_id, &self.memory)) - } + ChildWindow::Registers => AppWrapper::of_dyn(RegisterWindow::new( + self.sim_id, + &self.memory, + &self.persistence, + )), ChildWindow::Terminal => { AppWrapper::of_dyn(TerminalWindow::new(self.sim_id, &self.client)) } diff --git a/src/window/vip/bgmap.rs b/src/window/vip/bgmap.rs index 4739ab3..f94612f 100644 --- a/src/window/vip/bgmap.rs +++ b/src/window/vip/bgmap.rs @@ -1,14 +1,16 @@ use std::sync::Arc; use egui::{ - Align, CentralPanel, Checkbox, Color32, ComboBox, Image, ScrollArea, Slider, TextEdit, - TextureOptions, Ui, ViewportBuilder, + Align, CentralPanel, Checkbox, ComboBox, Image, ScrollArea, Slider, TextEdit, TextureOptions, + Ui, ViewportBuilder, }; use egui_extras::{Column, Size, StripBuilder, TableBuilder}; use serde::{Deserialize, Serialize}; use crate::{ + config::{Config, SimConfig}, emulator::SimId, + filesystem::Persistence, images::{ImageBuffer, ImageParams, ImageRenderer, ImageTextureLoader}, memory::{MemoryClient, MemoryView}, window::{ @@ -46,9 +48,14 @@ pub struct BgMapWindow { } impl BgMapWindow { - pub fn new(sim_id: SimId, memory: &Arc, images: &ImageTextureLoader) -> Self { + pub fn new( + sim_id: SimId, + memory: &Arc, + persistence: &Persistence, + images: &ImageTextureLoader, + ) -> Self { let state: UiData = UiData::new(); - let renderer = BgMapRenderer::new(sim_id, memory); + let renderer = BgMapRenderer::new(sim_id, persistence, memory); let params = images.add( sim_id, renderer, @@ -229,6 +236,7 @@ struct BgMapParams { } struct BgMapRenderer { + config: Config, chardata: MemoryView, bgmaps: MemoryView, brightness: MemoryView, @@ -236,8 +244,9 @@ struct BgMapRenderer { } impl BgMapRenderer { - pub fn new(sim_id: SimId, memory: &MemoryClient) -> Self { + pub fn new(sim_id: SimId, persistence: &Persistence, memory: &MemoryClient) -> Self { Self { + config: SimConfig::load(persistence, sim_id), chardata: memory.watch(sim_id, 0x00078000, 0x8000), bgmaps: memory.watch(sim_id, 0x00020000, 0x20000), brightness: memory.watch(sim_id, 0x0005f824, 8), @@ -246,6 +255,8 @@ impl BgMapRenderer { } fn render_bgmap(&self, image: &mut ImageBuffer, bgmap_index: usize, generic_palette: bool) { + let color = self.config.colors[0]; + let chardata = self.chardata.borrow(); let bgmaps = self.bgmaps.borrow(); let brightness = self.brightness.borrow(); @@ -253,9 +264,9 @@ impl BgMapRenderer { let brts = brightness.read::<[u8; 8]>(0); let colors = if generic_palette { - [utils::generic_palette(Color32::RED); 4] + [utils::generic_palette(color); 4] } else { - [0, 2, 4, 6].map(|i| utils::palette_colors(palettes.read(i), &brts, Color32::RED)) + [0, 2, 4, 6].map(|i| utils::palette_colors(palettes.read(i), &brts, color)) }; for (i, cell) in bgmaps.range::(bgmap_index * 4096, 4096).enumerate() { @@ -279,6 +290,8 @@ impl BgMapRenderer { } fn render_bgmap_cell(&self, image: &mut ImageBuffer, index: usize, generic_palette: bool) { + let color = self.config.colors[0]; + let chardata = self.chardata.borrow(); let bgmaps = self.bgmaps.borrow(); let brightness = self.brightness.borrow(); @@ -296,9 +309,9 @@ impl BgMapRenderer { } = CellData::parse(cell); let char = chardata.read::<[u16; 8]>(char_index); let palette = if generic_palette { - utils::generic_palette(Color32::RED) + utils::generic_palette(color) } else { - utils::palette_colors(palettes.read(palette_index * 2), &brts, Color32::RED) + utils::palette_colors(palettes.read(palette_index * 2), &brts, color) }; for row in 0..8 { @@ -321,6 +334,7 @@ impl ImageRenderer<2> for BgMapRenderer { } fn render(&mut self, params: &Self::Params, images: &mut [ImageBuffer; 2]) { + self.config.refresh(); self.render_bgmap_cell(&mut images[0], params.cell_index, params.generic_palette); self.render_bgmap( &mut images[1], diff --git a/src/window/vip/chardata.rs b/src/window/vip/chardata.rs index 5ababc9..44284e3 100644 --- a/src/window/vip/chardata.rs +++ b/src/window/vip/chardata.rs @@ -8,7 +8,9 @@ use egui_extras::{Column, Size, StripBuilder, TableBuilder}; use serde::{Deserialize, Serialize}; use crate::{ + config::{Config, SimConfig}, emulator::SimId, + filesystem::Persistence, images::{ImageBuffer, ImageParams, ImageRenderer, ImageTextureLoader}, memory::{MemoryClient, MemoryView}, window::{ @@ -99,6 +101,7 @@ impl Default for State { pub struct CharacterDataWindow { sim_id: SimId, + config: Config, brightness: MemoryView, palettes: MemoryView, params: ImageParams, @@ -106,7 +109,13 @@ pub struct CharacterDataWindow { } impl CharacterDataWindow { - pub fn new(sim_id: SimId, memory: &MemoryClient, images: &ImageTextureLoader) -> Self { + pub fn new( + sim_id: SimId, + memory: &MemoryClient, + persistence: &Persistence, + images: &ImageTextureLoader, + ) -> Self { + let config = SimConfig::load(persistence, sim_id); let state: UiData = UiData::new(); let renderer = CharDataRenderer::new(sim_id, memory); let params = images.add( @@ -115,10 +124,12 @@ impl CharacterDataWindow { CharDataParams { palette: state.palette, index: state.index, + color: config.colors[0], }, ); Self { sim_id, + config, brightness: memory.watch(sim_id, 0x0005f824, 8), palettes: memory.watch(sim_id, 0x0005f860, 16), params, @@ -226,17 +237,19 @@ impl CharacterDataWindow { self.params.write(CharDataParams { palette: self.state.palette, index: self.state.index, + color: self.config.colors[0], }); } fn load_palette_colors(&self) -> [Color32; 4] { + let color = self.config.colors[0]; let Some(offset) = self.state.palette.offset() else { - return utils::generic_palette(Color32::RED); + return utils::generic_palette(color); }; let palette = self.palettes.borrow().read(offset); let brightnesses = self.brightness.borrow(); let brts = brightnesses.read(0); - utils::palette_colors(palette, &brts, Color32::RED) + utils::palette_colors(palette, &brts, color) } fn show_chardata(&mut self, ui: &mut Ui) { @@ -262,6 +275,7 @@ impl AppWindow for CharacterDataWindow { } fn show(&mut self, ui: &mut Ui) { + self.config.refresh(); self.state.load(ui); CentralPanel::default().show(ui, |ui| { ui.horizontal_top(|ui| { @@ -286,8 +300,8 @@ impl AppWindow for CharacterDataWindow { struct CharDataParams { palette: Palette, index: usize, + color: Color32, } - struct CharDataRenderer { chardata: MemoryView, brightness: MemoryView, @@ -306,8 +320,8 @@ impl ImageRenderer<2> for CharDataRenderer { } fn render(&mut self, params: &Self::Params, image: &mut [ImageBuffer; 2]) { - self.render_character(&mut image[0], params.palette, params.index); - self.render_character_data(&mut image[1], params.palette); + self.render_character(&mut image[0], params.palette, params.index, params.color); + self.render_character_data(&mut image[1], params.palette, params.color); } } @@ -320,11 +334,17 @@ impl CharDataRenderer { } } - fn render_character(&self, image: &mut ImageBuffer, palette: Palette, index: usize) { + fn render_character( + &self, + image: &mut ImageBuffer, + palette: Palette, + index: usize, + color: Color32, + ) { if index >= 2048 { return; } - let palette = self.load_palette(palette); + let palette = self.load_palette(palette, color); let chardata = self.chardata.borrow(); let character = chardata.range::(index * 8, 8); for (row, pixels) in character.enumerate() { @@ -335,8 +355,8 @@ impl CharDataRenderer { } } - fn render_character_data(&self, image: &mut ImageBuffer, palette: Palette) { - let palette = self.load_palette(palette); + fn render_character_data(&self, image: &mut ImageBuffer, palette: Palette, color: Color32) { + let palette = self.load_palette(palette, color); let chardata = self.chardata.borrow(); for (row, pixels) in chardata.range::(0, 8 * 2048).enumerate() { let char_index = row / 8; @@ -350,13 +370,13 @@ impl CharDataRenderer { } } - fn load_palette(&self, palette: Palette) -> [Color32; 4] { + fn load_palette(&self, palette: Palette, color: Color32) -> [Color32; 4] { let Some(offset) = palette.offset() else { - return utils::GENERIC_PALETTE.map(|p| utils::shade(p, Color32::RED)); + return utils::GENERIC_PALETTE.map(|p| utils::shade(p, color)); }; let palette = self.palettes.borrow().read(offset); let brightnesses = self.brightness.borrow(); let brts = brightnesses.read(0); - utils::palette_colors(palette, &brts, Color32::RED) + utils::palette_colors(palette, &brts, color) } } diff --git a/src/window/vip/framebuffer.rs b/src/window/vip/framebuffer.rs index 71de888..587b474 100644 --- a/src/window/vip/framebuffer.rs +++ b/src/window/vip/framebuffer.rs @@ -6,7 +6,9 @@ use egui_extras::{Column, Size, StripBuilder, TableBuilder}; use serde::{Deserialize, Serialize}; use crate::{ + config::{Config, SimConfig}, emulator::SimId, + filesystem::Persistence, images::{ImageBuffer, ImageParams, ImageRenderer, ImageTextureLoader}, memory::{MemoryClient, MemoryView}, window::{ @@ -44,9 +46,14 @@ pub struct FrameBufferWindow { } impl FrameBufferWindow { - pub fn new(sim_id: SimId, memory: &MemoryClient, images: &ImageTextureLoader) -> Self { + pub fn new( + sim_id: SimId, + memory: &MemoryClient, + persistence: &Persistence, + images: &ImageTextureLoader, + ) -> Self { let state: UiData = UiData::new(); - let renderer = FrameBufferRenderer::new(sim_id, memory); + let renderer = FrameBufferRenderer::new(sim_id, memory, persistence); let params = images.add( sim_id, renderer, @@ -55,8 +62,6 @@ impl FrameBufferWindow { left: state.left, right: state.right, generic_palette: state.generic_palette, - left_color: Color32::from_rgb(0xff, 0x00, 0x00), - right_color: Color32::from_rgb(0x00, 0xc6, 0xf0), }, ); Self { @@ -138,7 +143,6 @@ impl FrameBufferWindow { left: self.state.left, right: self.state.right, generic_palette: self.state.generic_palette, - ..*self.params }); } @@ -188,18 +192,18 @@ struct FrameBufferParams { left: bool, right: bool, generic_palette: bool, - left_color: Color32, - right_color: Color32, } struct FrameBufferRenderer { + config: Config, buffers: [MemoryView; 4], brightness: MemoryView, } impl FrameBufferRenderer { - fn new(sim_id: SimId, memory: &MemoryClient) -> Self { + fn new(sim_id: SimId, memory: &MemoryClient, persistence: &Persistence) -> Self { Self { + config: SimConfig::load(persistence, sim_id), buffers: [ memory.watch(sim_id, 0x00000000, 0x6000), memory.watch(sim_id, 0x00008000, 0x6000), @@ -223,6 +227,7 @@ impl ImageRenderer<1> for FrameBufferRenderer { } fn render(&mut self, params: &Self::Params, images: &mut [ImageBuffer; 1]) { + self.config.refresh(); let image = &mut images[0]; let left_buffer = self.buffers[params.index].borrow(); @@ -230,15 +235,15 @@ impl ImageRenderer<1> for FrameBufferRenderer { let colors = if params.generic_palette { [ - utils::generic_palette(params.left_color), - utils::generic_palette(params.right_color), + utils::generic_palette(self.config.colors[0]), + utils::generic_palette(self.config.colors[1]), ] } else { let brts = self.brightness.borrow().read::<[u8; 8]>(0); let shades = utils::parse_shades(&brts); [ - shades.map(|s| utils::shade(s, params.left_color)), - shades.map(|s| utils::shade(s, params.right_color)), + shades.map(|s| utils::shade(s, self.config.colors[0])), + shades.map(|s| utils::shade(s, self.config.colors[1])), ] }; diff --git a/src/window/vip/object.rs b/src/window/vip/object.rs index 18d348e..2fba04f 100644 --- a/src/window/vip/object.rs +++ b/src/window/vip/object.rs @@ -1,14 +1,16 @@ use std::sync::Arc; use egui::{ - Align, CentralPanel, Checkbox, Color32, ComboBox, Image, ScrollArea, Slider, TextEdit, - TextureOptions, Ui, ViewportBuilder, + Align, CentralPanel, Checkbox, ComboBox, Image, ScrollArea, Slider, TextEdit, TextureOptions, + Ui, ViewportBuilder, }; use egui_extras::{Column, Size, StripBuilder, TableBuilder}; use serde::{Deserialize, Serialize}; use crate::{ + config::{Config, SimConfig}, emulator::SimId, + filesystem::Persistence, images::{ImageBuffer, ImageParams, ImageRenderer, ImageTextureLoader}, memory::{MemoryClient, MemoryView}, window::{ @@ -44,17 +46,20 @@ pub struct ObjectWindow { } impl ObjectWindow { - pub fn new(sim_id: SimId, memory: &Arc, images: &ImageTextureLoader) -> Self { + pub fn new( + sim_id: SimId, + memory: &Arc, + persistence: &Persistence, + images: &ImageTextureLoader, + ) -> Self { let state: UiData = UiData::new(); - let renderer = ObjectRenderer::new(sim_id, memory); + let renderer = ObjectRenderer::new(sim_id, memory, persistence); let params = images.add( sim_id, renderer, ObjectParams { index: state.index, generic_palette: state.generic_palette, - left_color: Color32::from_rgb(0xff, 0x00, 0x00), - right_color: Color32::from_rgb(0x00, 0xc6, 0xf0), }, ); Self { @@ -194,7 +199,6 @@ impl ObjectWindow { self.params.write(ObjectParams { index: self.state.index, generic_palette: self.state.generic_palette, - ..*self.params }); } @@ -242,8 +246,6 @@ impl AppWindow for ObjectWindow { struct ObjectParams { index: usize, generic_palette: bool, - left_color: Color32, - right_color: Color32, } enum Eye { @@ -252,6 +254,7 @@ enum Eye { } struct ObjectRenderer { + config: Config, chardata: MemoryView, objects: MemoryView, brightness: MemoryView, @@ -259,8 +262,9 @@ struct ObjectRenderer { } impl ObjectRenderer { - pub fn new(sim_id: SimId, memory: &MemoryClient) -> Self { + pub fn new(sim_id: SimId, memory: &MemoryClient, persistence: &Persistence) -> Self { Self { + config: SimConfig::load(persistence, sim_id), chardata: memory.watch(sim_id, 0x00078000, 0x8000), objects: memory.watch(sim_id, 0x0003e000, 0x2000), brightness: memory.watch(sim_id, 0x0005f824, 8), @@ -302,8 +306,8 @@ impl ObjectRenderer { }; let color = match eye { - Eye::Left => params.left_color, - Eye::Right => params.right_color, + Eye::Left => self.config.colors[0], + Eye::Right => self.config.colors[1], }; let char = chardata.read::<[u16; 8]>(obj.data.char_index); @@ -343,6 +347,7 @@ impl ImageRenderer<2> for ObjectRenderer { } fn render(&mut self, params: &Self::Params, images: &mut [ImageBuffer; 2]) { + self.config.refresh(); images[0].clear(); self.render_object(&mut images[0], params, false, Eye::Left); self.render_object(&mut images[0], params, false, Eye::Right); diff --git a/src/window/vip/registers.rs b/src/window/vip/registers.rs index 70a6bb3..1090808 100644 --- a/src/window/vip/registers.rs +++ b/src/window/vip/registers.rs @@ -1,13 +1,15 @@ use std::sync::Arc; use egui::{ - Align, Button, CentralPanel, Checkbox, Color32, Direction, Label, Layout, ScrollArea, TextEdit, - Ui, ViewportBuilder, + Align, Button, CentralPanel, Checkbox, Direction, Label, Layout, ScrollArea, TextEdit, Ui, + ViewportBuilder, }; use egui_extras::{Column, Size, StripBuilder, TableBuilder}; use crate::{ + config::{Config, SimConfig}, emulator::SimId, + filesystem::Persistence, memory::{MemoryClient, MemoryRef, MemoryValue, MemoryView}, window::{ AppWindow, @@ -19,14 +21,16 @@ use super::utils; pub struct RegisterWindow { sim_id: SimId, + config: Config, memory: Arc, registers: MemoryView, } impl RegisterWindow { - pub fn new(sim_id: SimId, memory: &Arc) -> Self { + pub fn new(sim_id: SimId, memory: &Arc, persistence: &Persistence) -> Self { Self { sim_id, + config: SimConfig::load(persistence, sim_id), memory: memory.clone(), registers: memory.watch(sim_id, 0x0005f800, 0x72), } @@ -366,7 +370,7 @@ impl RegisterWindow { }); body.row(row_height, |mut row| { row.col(|_ui| {}); - for shade in utils::parse_brts(&brts, Color32::RED) { + for shade in utils::parse_brts(&brts, self.config.colors[0]) { row.col(|ui| { ui.painter().rect_filled( ui.available_rect_before_wrap(), @@ -641,6 +645,7 @@ impl AppWindow for RegisterWindow { } fn show(&mut self, ui: &mut Ui) { + self.config.refresh(); CentralPanel::default().show(ui, |ui| { ScrollArea::vertical().show(ui, |ui| { ui.horizontal_top(|ui| { diff --git a/src/window/vip/world.rs b/src/window/vip/world.rs index 248ace2..88aadd7 100644 --- a/src/window/vip/world.rs +++ b/src/window/vip/world.rs @@ -14,7 +14,9 @@ use num_traits::{FromPrimitive, ToPrimitive}; use serde::{Deserialize, Serialize}; use crate::{ + config::{Config, SimConfig}, emulator::SimId, + filesystem::Persistence, images::{ImageBuffer, ImageParams, ImageRenderer, ImageTextureLoader}, memory::{MemoryClient, MemoryRef, MemoryView}, window::{ @@ -47,6 +49,7 @@ impl Default for State { pub struct WorldWindow { sim_id: SimId, + config: Config, memory: Arc, worlds: MemoryView, bgmaps: MemoryView, @@ -55,7 +58,13 @@ pub struct WorldWindow { } impl WorldWindow { - pub fn new(sim_id: SimId, memory: &Arc, images: &ImageTextureLoader) -> Self { + pub fn new( + sim_id: SimId, + memory: &Arc, + persistence: &Persistence, + images: &ImageTextureLoader, + ) -> Self { + let config = SimConfig::load(persistence, sim_id); let state: UiData = UiData::new(); let renderer = WorldRenderer::new(sim_id, memory); let params = images.add( @@ -64,12 +73,13 @@ impl WorldWindow { WorldParams { index: state.index, generic_palette: state.generic_palette, - left_color: Color32::from_rgb(0xff, 0x00, 0x00), - right_color: Color32::from_rgb(0x00, 0xc6, 0xf0), + left_color: config.colors[0], + right_color: config.colors[1], }, ); Self { sim_id, + config, memory: memory.clone(), worlds: memory.watch(sim_id, 0x0003d800, 0x400), bgmaps: memory.watch(sim_id, 0x00020000, 0x20000), @@ -538,6 +548,12 @@ impl AppWindow for WorldWindow { } fn show(&mut self, ui: &mut Ui) { + self.config.refresh(); + self.params.write(WorldParams { + left_color: self.config.colors[0], + right_color: self.config.colors[1], + ..*self.params + }); self.state.load(ui); CentralPanel::default().show(ui, |ui| { ui.horizontal_top(|ui| {