From 29d531f6226cab683f9e8d6ca25db0a9719783bb Mon Sep 17 00:00:00 2001 From: bQUARKz Date: Fri, 1 May 2026 05:54:23 +0100 Subject: [PATCH] (fix) issues regarding tilemap cache and render --- .../prometeu-drivers/src/frame_composer.rs | 68 +++++++++++++++++-- 1 file changed, 64 insertions(+), 4 deletions(-) diff --git a/crates/console/prometeu-drivers/src/frame_composer.rs b/crates/console/prometeu-drivers/src/frame_composer.rs index 7f6c476b..55d424be 100644 --- a/crates/console/prometeu-drivers/src/frame_composer.rs +++ b/crates/console/prometeu-drivers/src/frame_composer.rs @@ -4,7 +4,9 @@ use prometeu_hal::GfxBridge; use prometeu_hal::glyph::Glyph; use prometeu_hal::scene_bank::SceneBank; use prometeu_hal::scene_viewport_cache::SceneViewportCache; -use prometeu_hal::scene_viewport_resolver::{CacheRefreshRequest, SceneViewportResolver}; +use prometeu_hal::scene_viewport_resolver::{ + CacheRefreshRequest, ResolverUpdate, SceneViewportResolver, +}; use prometeu_hal::sprite::Sprite; use std::sync::Arc; @@ -257,6 +259,7 @@ impl FrameComposer { panic!("SCENE runtime invariant broken: active scene without cache/resolver"); }; let update = resolver.update(scene, self.camera_x_px, self.camera_y_px); + Self::sync_cache_windows(cache, &update); Self::apply_refresh_requests(cache, scene, &update.refresh_requests); // `FrameComposer` owns only canonical game-frame composition. // Deferred `gfx.*` primitives are drained later by a separate @@ -334,6 +337,16 @@ impl FrameComposer { } } } + + fn sync_cache_windows(cache: &mut SceneViewportCache, update: &ResolverUpdate) { + for request in &update.copy_requests { + cache.move_layer_window_to( + request.layer_index, + request.cache_origin_tile_x, + request.cache_origin_tile_y, + ); + } + } } #[cfg(test)] @@ -360,6 +373,16 @@ mod tests { glyph_asset_id: AssetId, palette_id: u8, tile_size: TileSize, + ) -> SceneBank { + make_scene_grid(glyph_asset_id, palette_id, tile_size, 2, 2) + } + + fn make_scene_grid( + glyph_asset_id: AssetId, + palette_id: u8, + tile_size: TileSize, + width: usize, + height: usize, ) -> SceneBank { let layer = SceneLayer { active: true, @@ -367,8 +390,8 @@ mod tests { tile_size, parallax_factor: ParallaxFactor { x: 1.0, y: 0.5 }, tilemap: TileMap { - width: 2, - height: 2, + width, + height, tiles: vec![ Tile { active: true, @@ -376,7 +399,7 @@ mod tests { flip_x: false, flip_y: false, }; - 4 + width * height ], }, }; @@ -768,6 +791,43 @@ mod tests { assert_eq!(gfx.front_buffer()[0], Color::BLUE.raw()); } + #[test] + fn render_frame_realigns_cache_window_before_refresh_when_camera_moves() { + let banks = Arc::new(MemoryBanks::new()); + let scene = Arc::new(make_scene_grid(0, 2, TileSize::Size8, 16, 16)); + banks.install_glyph_bank(0, Arc::new(make_glyph_bank(TileSize::Size8, 2, Color::BLUE))); + banks.install_scene_bank(0, Arc::clone(&scene)); + + let mut frame_composer = FrameComposer::new( + 16, + 16, + Arc::clone(&banks) as Arc, + make_glyph_slot_index(&[(0, 0)]), + ); + assert!(frame_composer.bind_scene(0)); + + let mut expected_resolver = FrameComposer::build_scene_runtime(16, 16, &scene).1; + expected_resolver.update(&scene, 0, 0); + let expected_update = expected_resolver.update(&scene, 40, 0); + + let mut gfx = Gfx::new(16, 16, Arc::clone(&banks) as Arc); + gfx.scene_fade_level = 31; + gfx.hud_fade_level = 31; + + frame_composer.render_frame(&mut gfx); + frame_composer.set_camera(40, 0); + frame_composer.render_frame(&mut gfx); + + let cache = frame_composer.cache().expect("cache should exist"); + assert_eq!( + cache.layers[0].logical_origin(), + ( + expected_update.copy_requests[0].cache_origin_tile_x, + expected_update.copy_requests[0].cache_origin_tile_y, + ) + ); + } + #[test] fn render_frame_survives_scene_transition_through_unbind_and_rebind() { let banks = Arc::new(MemoryBanks::new());