From 54f65f58e679e51f2e60ab1532bd078a1621ca09 Mon Sep 17 00:00:00 2001 From: bQUARKz Date: Fri, 10 Apr 2026 06:00:47 +0100 Subject: [PATCH] Glyph Bank Domain Naming Contract --- crates/console/prometeu-drivers/src/asset.rs | 214 ++++++++--------- crates/console/prometeu-drivers/src/gfx.rs | 38 +-- .../console/prometeu-drivers/src/hardware.rs | 10 +- .../prometeu-drivers/src/memory_banks.rs | 38 +-- crates/console/prometeu-hal/src/asset.rs | 14 +- .../prometeu-hal/src/cartridge_loader.rs | 30 +-- .../src/{tile_bank.rs => glyph_bank.rs} | 16 +- crates/console/prometeu-hal/src/lib.rs | 2 +- crates/console/prometeu-hal/src/tile_layer.rs | 4 +- .../src/virtual_machine_runtime/dispatch.rs | 4 +- .../src/virtual_machine_runtime/tests.rs | 42 ++-- .../src/virtual_machine_runtime/tick.rs | 2 +- crates/tools/pbxgen-stress/src/lib.rs | 2 +- discussion/index.ndjson | 3 +- .../LSN-0009-mental-model-asset-management.md | 10 +- .../LSN-0011-mental-model-gfx.md | 10 +- ...LSN-0022-tilemap-empty-cell-convergence.md | 2 +- .../LSN-0023-typed-asset-metadata-helpers.md | 4 +- ...0-tile-bank-vs-glyph-bank-domain-naming.md | 221 ++++++++++++++++++ ...-0006-glyph-bank-domain-naming-contract.md | 93 ++++++++ ...0005-glyph-bank-domain-naming-execution.md | 161 +++++++++++++ 21 files changed, 700 insertions(+), 220 deletions(-) rename crates/console/prometeu-hal/src/{tile_bank.rs => glyph_bank.rs} (84%) create mode 100644 discussion/workflow/agendas/AGD-0020-tile-bank-vs-glyph-bank-domain-naming.md create mode 100644 discussion/workflow/decisions/DEC-0006-glyph-bank-domain-naming-contract.md create mode 100644 discussion/workflow/plans/PLN-0005-glyph-bank-domain-naming-execution.md diff --git a/crates/console/prometeu-drivers/src/asset.rs b/crates/console/prometeu-drivers/src/asset.rs index 73397f18..88558910 100644 --- a/crates/console/prometeu-drivers/src/asset.rs +++ b/crates/console/prometeu-drivers/src/asset.rs @@ -1,5 +1,5 @@ #![allow(clippy::collapsible_if)] -use crate::memory_banks::{SoundBankPoolInstaller, TileBankPoolInstaller}; +use crate::memory_banks::{GlyphBankPoolInstaller, SoundBankPoolInstaller}; use prometeu_hal::AssetBridge; use prometeu_hal::asset::{ AssetCodec, AssetEntry, AssetId, AssetLoadError, AssetOpStatus, BankStats, BankType, HandleId, @@ -7,19 +7,19 @@ use prometeu_hal::asset::{ }; use prometeu_hal::cartridge::AssetsPayloadSource; use prometeu_hal::color::Color; +use prometeu_hal::glyph_bank::{GlyphBank, TileSize}; use prometeu_hal::sample::Sample; use prometeu_hal::sound_bank::SoundBank; -use prometeu_hal::tile_bank::{TileBank, TileSize}; use std::collections::HashMap; use std::io::Read; use std::sync::{Arc, Mutex, RwLock}; use std::thread; use std::time::Instant; -const TILE_BANK_PALETTE_COUNT_V1: usize = 64; -const TILE_BANK_COLORS_PER_PALETTE: usize = 16; -const TILE_BANK_PALETTE_BYTES_V1: usize = - TILE_BANK_PALETTE_COUNT_V1 * TILE_BANK_COLORS_PER_PALETTE * std::mem::size_of::(); +const GLYPH_BANK_PALETTE_COUNT_V1: usize = 64; +const GLYPH_BANK_COLORS_PER_PALETTE: usize = 16; +const GLYPH_BANK_PALETTE_BYTES_V1: usize = + GLYPH_BANK_PALETTE_COUNT_V1 * GLYPH_BANK_COLORS_PER_PALETTE * std::mem::size_of::(); /// Resident metadata for a decoded/materialized asset inside a BankPolicy. #[derive(Debug)] @@ -115,15 +115,15 @@ pub struct AssetManager { assets_data: Arc>, /// Narrow hardware interfaces - gfx_installer: Arc, + gfx_installer: Arc, sound_installer: Arc, /// Track what is installed in each hardware slot (for stats/info). gfx_slots: Arc; 16]>>, sound_slots: Arc; 16]>>, - /// Residency policy for GFX tile banks. - gfx_policy: BankPolicy, + /// Residency policy for GFX glyph banks. + gfx_policy: BankPolicy, /// Residency policy for sound banks. sound_policy: BankPolicy, @@ -179,10 +179,10 @@ impl AssetBridge for AssetManager { } impl AssetManager { - fn decode_tile_bank_layout( + fn decode_glyph_bank_layout( entry: &AssetEntry, ) -> Result<(TileSize, usize, usize, usize), String> { - let meta = entry.metadata_as_tiles()?; + let meta = entry.metadata_as_glyphs()?; let tile_size = match meta.tile_size { 8 => TileSize::Size8, @@ -191,32 +191,32 @@ impl AssetManager { _ => return Err(format!("Invalid tile_size: {}", meta.tile_size)), }; - if meta.palette_count as usize != TILE_BANK_PALETTE_COUNT_V1 { + if meta.palette_count as usize != GLYPH_BANK_PALETTE_COUNT_V1 { return Err(format!("Invalid palette_count: {}", meta.palette_count)); } let width = meta.width as usize; let height = meta.height as usize; - let logical_pixels = width.checked_mul(height).ok_or("TileBank dimensions overflow")?; + let logical_pixels = width.checked_mul(height).ok_or("GlyphBank dimensions overflow")?; let serialized_pixel_bytes = logical_pixels.div_ceil(2); let serialized_size = serialized_pixel_bytes - .checked_add(TILE_BANK_PALETTE_BYTES_V1) - .ok_or("TileBank serialized size overflow")?; + .checked_add(GLYPH_BANK_PALETTE_BYTES_V1) + .ok_or("GlyphBank serialized size overflow")?; let decoded_size = logical_pixels - .checked_add(TILE_BANK_PALETTE_BYTES_V1) - .ok_or("TileBank decoded size overflow")?; + .checked_add(GLYPH_BANK_PALETTE_BYTES_V1) + .ok_or("GlyphBank decoded size overflow")?; if entry.size != serialized_size as u64 { return Err(format!( - "Invalid TILEBANK serialized size: expected {}, got {}", + "Invalid GLYPHBANK serialized size: expected {}, got {}", serialized_size, entry.size )); } if entry.decoded_size != decoded_size as u64 { return Err(format!( - "Invalid TILEBANK decoded_size: expected {}, got {}", + "Invalid GLYPHBANK decoded_size: expected {}, got {}", decoded_size, entry.decoded_size )); } @@ -224,7 +224,7 @@ impl AssetManager { Ok((tile_size, width, height, serialized_pixel_bytes)) } - fn unpack_tile_bank_pixels(packed_pixels: &[u8], logical_pixels: usize) -> Vec { + fn unpack_glyph_bank_pixels(packed_pixels: &[u8], logical_pixels: usize) -> Vec { let mut pixel_indices = Vec::with_capacity(logical_pixels); for &packed in packed_pixels { if pixel_indices.len() < logical_pixels { @@ -239,7 +239,7 @@ impl AssetManager { fn op_mode_for(entry: &AssetEntry) -> Result { match (entry.bank_type, entry.codec) { - (BankType::TILES, AssetCodec::None) => Ok(AssetOpMode::StageInMemory), + (BankType::GLYPH, AssetCodec::None) => Ok(AssetOpMode::StageInMemory), (BankType::SOUNDS, AssetCodec::None) => Ok(AssetOpMode::DirectFromSlice), } } @@ -247,7 +247,7 @@ impl AssetManager { pub fn new( assets: Vec, assets_data: AssetsPayloadSource, - gfx_installer: Arc, + gfx_installer: Arc, sound_installer: Arc, ) -> Self { let mut asset_map = HashMap::new(); @@ -296,9 +296,9 @@ impl AssetManager { if let Some(entry) = entry_opt { let slot_index = item.slot; match entry.bank_type { - BankType::TILES => { + BankType::GLYPH => { if let Ok(bank) = - Self::perform_load_tile_bank(&entry, self.assets_data.clone()) + Self::perform_load_glyph_bank(&entry, self.assets_data.clone()) { let bank_arc = Arc::new(bank); self.gfx_policy.put_resident( @@ -306,7 +306,7 @@ impl AssetManager { Arc::clone(&bank_arc), entry.decoded_size as usize, ); - self.gfx_installer.install_tile_bank(slot_index, bank_arc); + self.gfx_installer.install_glyph_bank(slot_index, bank_arc); let mut slots = self.gfx_slots.write().unwrap(); if slot_index < slots.len() { slots[slot_index] = Some(entry.asset_id); @@ -367,7 +367,7 @@ impl AssetManager { assets.get(&asset_id).ok_or(AssetLoadError::AssetNotFound)?.clone() }; let slot = match entry.bank_type { - BankType::TILES => SlotRef::gfx(slot_index), + BankType::GLYPH => SlotRef::gfx(slot_index), BankType::SOUNDS => SlotRef::audio(slot_index), }; @@ -377,7 +377,7 @@ impl AssetManager { // Check if already resident (Dedup) let already_resident = match entry.bank_type { - BankType::TILES => { + BankType::GLYPH => { if let Some(bank) = self.gfx_policy.get_resident(asset_id) { self.gfx_policy.stage(handle_id, bank); true @@ -435,8 +435,8 @@ impl AssetManager { } match entry_clone.bank_type { - BankType::TILES => { - let result = Self::perform_load_tile_bank(&entry_clone, assets_data); + BankType::GLYPH => { + let result = Self::perform_load_glyph_bank(&entry_clone, assets_data); if let Ok(tilebank) = result { let bank_arc = Arc::new(tilebank); let resident_arc = { @@ -507,10 +507,10 @@ impl AssetManager { Ok(handle_id) } - fn perform_load_tile_bank( + fn perform_load_glyph_bank( entry: &AssetEntry, assets_data: Arc>, - ) -> Result { + ) -> Result { let op_mode = Self::op_mode_for(entry)?; let slice = { let assets_data = assets_data.read().unwrap(); @@ -523,30 +523,33 @@ impl AssetManager { AssetOpMode::StageInMemory => { let buffer = slice.read_all().map_err(|_| "Asset payload read failed".to_string())?; - Self::decode_tile_bank_from_buffer(entry, &buffer) + Self::decode_glyph_bank_from_buffer(entry, &buffer) } AssetOpMode::DirectFromSlice => { let mut reader = slice.open_reader().map_err(|_| "Asset payload read failed".to_string())?; - Self::decode_tile_bank_from_reader(entry, &mut reader) + Self::decode_glyph_bank_from_reader(entry, &mut reader) } } } - fn decode_tile_bank_from_buffer(entry: &AssetEntry, buffer: &[u8]) -> Result { - let (tile_size, width, height, packed_pixel_bytes) = Self::decode_tile_bank_layout(entry)?; - if buffer.len() < packed_pixel_bytes + TILE_BANK_PALETTE_BYTES_V1 { - return Err("Buffer too small for TILEBANK".to_string()); + fn decode_glyph_bank_from_buffer( + entry: &AssetEntry, + buffer: &[u8], + ) -> Result { + let (tile_size, width, height, packed_pixel_bytes) = Self::decode_glyph_bank_layout(entry)?; + if buffer.len() < packed_pixel_bytes + GLYPH_BANK_PALETTE_BYTES_V1 { + return Err("Buffer too small for GLYPHBANK".to_string()); } let logical_pixels = width * height; let packed_pixels = &buffer[0..packed_pixel_bytes]; - let pixel_indices = Self::unpack_tile_bank_pixels(packed_pixels, logical_pixels); + let pixel_indices = Self::unpack_glyph_bank_pixels(packed_pixels, logical_pixels); let palette_data = - &buffer[packed_pixel_bytes..packed_pixel_bytes + TILE_BANK_PALETTE_BYTES_V1]; + &buffer[packed_pixel_bytes..packed_pixel_bytes + GLYPH_BANK_PALETTE_BYTES_V1]; let mut palettes = - [[Color::BLACK; TILE_BANK_COLORS_PER_PALETTE]; TILE_BANK_PALETTE_COUNT_V1]; + [[Color::BLACK; GLYPH_BANK_COLORS_PER_PALETTE]; GLYPH_BANK_PALETTE_COUNT_V1]; for (p, pal) in palettes.iter_mut().enumerate() { for (c, slot) in pal.iter_mut().enumerate() { let offset = (p * 16 + c) * 2; @@ -556,29 +559,29 @@ impl AssetManager { } } - Ok(TileBank { tile_size, width, height, pixel_indices, palettes }) + Ok(GlyphBank { tile_size, width, height, pixel_indices, palettes }) } - fn decode_tile_bank_from_reader( + fn decode_glyph_bank_from_reader( entry: &AssetEntry, reader: &mut impl Read, - ) -> Result { - let (tile_size, width, height, packed_pixel_bytes) = Self::decode_tile_bank_layout(entry)?; + ) -> Result { + let (tile_size, width, height, packed_pixel_bytes) = Self::decode_glyph_bank_layout(entry)?; let logical_pixels = width * height; let mut packed_pixels = vec![0_u8; packed_pixel_bytes]; reader .read_exact(&mut packed_pixels) - .map_err(|_| "Buffer too small for TILEBANK".to_string())?; + .map_err(|_| "Buffer too small for GLYPHBANK".to_string())?; - let pixel_indices = Self::unpack_tile_bank_pixels(&packed_pixels, logical_pixels); + let pixel_indices = Self::unpack_glyph_bank_pixels(&packed_pixels, logical_pixels); - let mut palette_data = [0_u8; TILE_BANK_PALETTE_BYTES_V1]; + let mut palette_data = [0_u8; GLYPH_BANK_PALETTE_BYTES_V1]; reader .read_exact(&mut palette_data) - .map_err(|_| "Buffer too small for TILEBANK".to_string())?; + .map_err(|_| "Buffer too small for GLYPHBANK".to_string())?; let mut palettes = - [[Color::BLACK; TILE_BANK_COLORS_PER_PALETTE]; TILE_BANK_PALETTE_COUNT_V1]; + [[Color::BLACK; GLYPH_BANK_COLORS_PER_PALETTE]; GLYPH_BANK_PALETTE_COUNT_V1]; for (p, pal) in palettes.iter_mut().enumerate() { for (c, slot) in pal.iter_mut().enumerate() { let offset = (p * 16 + c) * 2; @@ -588,7 +591,7 @@ impl AssetManager { } } - Ok(TileBank { tile_size, width, height, pixel_indices, palettes }) + Ok(GlyphBank { tile_size, width, height, pixel_indices, palettes }) } fn perform_load_sound_bank( @@ -695,9 +698,9 @@ impl AssetManager { if let Some(h) = handles.get_mut(&handle_id) { if h.status == LoadStatus::READY { match h.slot.asset_type { - BankType::TILES => { + BankType::GLYPH => { if let Some(bank) = self.gfx_policy.take_staging(handle_id) { - self.gfx_installer.install_tile_bank(h.slot.index, bank); + self.gfx_installer.install_glyph_bank(h.slot.index, bank); let mut slots = self.gfx_slots.write().unwrap(); if h.slot.index < slots.len() { slots[h.slot.index] = Some(h._asset_id); @@ -723,7 +726,7 @@ impl AssetManager { pub fn bank_info(&self, kind: BankType) -> BankStats { match kind { - BankType::TILES => { + BankType::GLYPH => { let mut used_bytes = 0; { let resident = self.gfx_policy.resident.read().unwrap(); @@ -814,7 +817,7 @@ impl AssetManager { pub fn slot_info(&self, slot: SlotRef) -> SlotStats { match slot.asset_type { - BankType::TILES => { + BankType::GLYPH => { let slots = self.gfx_slots.read().unwrap(); let asset_id = slots.get(slot.index).and_then(|s| *s); @@ -872,93 +875,94 @@ impl AssetManager { #[cfg(test)] mod tests { use super::*; - use crate::memory_banks::{MemoryBanks, SoundBankPoolAccess, TileBankPoolAccess}; + use crate::memory_banks::{GlyphBankPoolAccess, MemoryBanks, SoundBankPoolAccess}; use prometeu_hal::asset::AssetCodec; - fn expected_tile_payload_size(width: usize, height: usize) -> usize { - (width * height).div_ceil(2) + TILE_BANK_PALETTE_BYTES_V1 + fn expected_glyph_payload_size(width: usize, height: usize) -> usize { + (width * height).div_ceil(2) + GLYPH_BANK_PALETTE_BYTES_V1 } - fn expected_tile_decoded_size(width: usize, height: usize) -> usize { - width * height + TILE_BANK_PALETTE_BYTES_V1 + fn expected_glyph_decoded_size(width: usize, height: usize) -> usize { + width * height + GLYPH_BANK_PALETTE_BYTES_V1 } - fn test_tile_asset_data() -> Vec { + fn test_glyph_asset_data() -> Vec { let mut data = vec![0x11u8; 128]; - data.extend_from_slice(&[0u8; TILE_BANK_PALETTE_BYTES_V1]); + data.extend_from_slice(&[0u8; GLYPH_BANK_PALETTE_BYTES_V1]); data } - fn test_tile_asset_entry(asset_name: &str, width: usize, height: usize) -> AssetEntry { + fn test_glyph_asset_entry(asset_name: &str, width: usize, height: usize) -> AssetEntry { AssetEntry { asset_id: 0, asset_name: asset_name.to_string(), - bank_type: BankType::TILES, + bank_type: BankType::GLYPH, offset: 0, - size: expected_tile_payload_size(width, height) as u64, - decoded_size: expected_tile_decoded_size(width, height) as u64, + size: expected_glyph_payload_size(width, height) as u64, + decoded_size: expected_glyph_decoded_size(width, height) as u64, codec: AssetCodec::None, metadata: serde_json::json!({ "tile_size": 16, "width": width, "height": height, - "palette_count": TILE_BANK_PALETTE_COUNT_V1, - "palette_authored": TILE_BANK_PALETTE_COUNT_V1 + "palette_count": GLYPH_BANK_PALETTE_COUNT_V1, + "palette_authored": GLYPH_BANK_PALETTE_COUNT_V1 }), } } #[test] - fn test_decode_tile_bank_unpacks_packed_pixels_and_reads_palette_colors() { - let entry = test_tile_asset_entry("tiles", 2, 2); + fn test_decode_glyph_bank_unpacks_packed_pixels_and_reads_palette_colors() { + let entry = test_glyph_asset_entry("tiles", 2, 2); let mut data = vec![0x10, 0x23]; - data.extend_from_slice(&[0u8; TILE_BANK_PALETTE_BYTES_V1]); + data.extend_from_slice(&[0u8; GLYPH_BANK_PALETTE_BYTES_V1]); data[2] = 0x34; data[3] = 0x12; - let bank = AssetManager::decode_tile_bank_from_buffer(&entry, &data).expect("tile decode"); + let bank = + AssetManager::decode_glyph_bank_from_buffer(&entry, &data).expect("glyph decode"); assert_eq!(bank.pixel_indices, vec![1, 0, 2, 3]); assert_eq!(bank.palettes[0][0], Color(0x1234)); } #[test] - fn test_decode_tile_bank_rejects_short_packed_buffer() { - let entry = test_tile_asset_entry("tiles", 16, 16); - let data = vec![0u8; expected_tile_payload_size(16, 16) - 1]; + fn test_decode_glyph_bank_rejects_short_packed_buffer() { + let entry = test_glyph_asset_entry("tiles", 16, 16); + let data = vec![0u8; expected_glyph_payload_size(16, 16) - 1]; - let err = match AssetManager::decode_tile_bank_from_buffer(&entry, &data) { - Ok(_) => panic!("tile decode should reject short buffer"), + let err = match AssetManager::decode_glyph_bank_from_buffer(&entry, &data) { + Ok(_) => panic!("glyph decode should reject short buffer"), Err(err) => err, }; - assert_eq!(err, "Buffer too small for TILEBANK"); + assert_eq!(err, "Buffer too small for GLYPHBANK"); } #[test] - fn test_decode_tile_bank_requires_palette_count_64() { - let mut entry = test_tile_asset_entry("tiles", 16, 16); + fn test_decode_glyph_bank_requires_palette_count_64() { + let mut entry = test_glyph_asset_entry("tiles", 16, 16); entry.metadata["palette_count"] = serde_json::json!(32); - let err = match AssetManager::decode_tile_bank_from_buffer(&entry, &test_tile_asset_data()) - { - Ok(_) => panic!("tile decode should reject invalid palette_count"), - Err(err) => err, - }; + let err = + match AssetManager::decode_glyph_bank_from_buffer(&entry, &test_glyph_asset_data()) { + Ok(_) => panic!("glyph decode should reject invalid palette_count"), + Err(err) => err, + }; assert_eq!(err, "Invalid palette_count: 32"); } #[test] - fn test_op_mode_for_tiles_none_stages_in_memory() { - let entry = test_tile_asset_entry("tiles", 16, 16); + fn test_op_mode_for_glyphs_none_stages_in_memory() { + let entry = test_glyph_asset_entry("tiles", 16, 16); assert_eq!(AssetManager::op_mode_for(&entry), Ok(AssetOpMode::StageInMemory)); } #[test] - fn test_op_mode_for_tiles_none_uses_typed_codec() { - let entry = test_tile_asset_entry("tiles", 16, 16); + fn test_op_mode_for_glyphs_none_uses_typed_codec() { + let entry = test_glyph_asset_entry("tiles", 16, 16); assert_eq!(AssetManager::op_mode_for(&entry), Ok(AssetOpMode::StageInMemory)); } @@ -984,11 +988,11 @@ mod tests { #[test] fn test_asset_loading_flow() { let banks = Arc::new(MemoryBanks::new()); - let gfx_installer = Arc::clone(&banks) as Arc; + let gfx_installer = Arc::clone(&banks) as Arc; let sound_installer = Arc::clone(&banks) as Arc; - let data = test_tile_asset_data(); - let asset_entry = test_tile_asset_entry("test_tiles", 16, 16); + let data = test_glyph_asset_data(); + let asset_entry = test_glyph_asset_entry("test_tiles", 16, 16); let am = AssetManager::new( vec![asset_entry], @@ -1016,17 +1020,17 @@ mod tests { am.apply_commits(); assert_eq!(am.status(handle), LoadStatus::COMMITTED); - assert!(banks.tile_bank_slot(0).is_some()); + assert!(banks.glyph_bank_slot(0).is_some()); } #[test] fn test_asset_dedup() { let banks = Arc::new(MemoryBanks::new()); - let gfx_installer = Arc::clone(&banks) as Arc; + let gfx_installer = Arc::clone(&banks) as Arc; let sound_installer = Arc::clone(&banks) as Arc; - let data = test_tile_asset_data(); - let asset_entry = test_tile_asset_entry("test_tiles", 16, 16); + let data = test_glyph_asset_data(); + let asset_entry = test_glyph_asset_entry("test_tiles", 16, 16); let am = AssetManager::new( vec![asset_entry], @@ -1053,7 +1057,7 @@ mod tests { #[test] fn test_sound_asset_loading() { let banks = Arc::new(MemoryBanks::new()); - let gfx_installer = Arc::clone(&banks) as Arc; + let gfx_installer = Arc::clone(&banks) as Arc; let sound_installer = Arc::clone(&banks) as Arc; // 100 samples of 16-bit PCM (zeros) @@ -1098,7 +1102,7 @@ mod tests { #[test] fn test_preload_on_init() { let banks = Arc::new(MemoryBanks::new()); - let gfx_installer = Arc::clone(&banks) as Arc; + let gfx_installer = Arc::clone(&banks) as Arc; let sound_installer = Arc::clone(&banks) as Arc; let data = vec![0u8; 200]; @@ -1139,7 +1143,7 @@ mod tests { #[test] fn test_load_returns_asset_not_found() { let banks = Arc::new(MemoryBanks::new()); - let gfx_installer = Arc::clone(&banks) as Arc; + let gfx_installer = Arc::clone(&banks) as Arc; let sound_installer = Arc::clone(&banks) as Arc; let am = AssetManager::new(vec![], AssetsPayloadSource::empty(), gfx_installer, sound_installer); @@ -1152,11 +1156,11 @@ mod tests { #[test] fn test_load_returns_slot_index_invalid() { let banks = Arc::new(MemoryBanks::new()); - let gfx_installer = Arc::clone(&banks) as Arc; + let gfx_installer = Arc::clone(&banks) as Arc; let sound_installer = Arc::clone(&banks) as Arc; - let data = test_tile_asset_data(); + let data = test_glyph_asset_data(); let am = AssetManager::new( - vec![test_tile_asset_entry("test_tiles", 16, 16)], + vec![test_glyph_asset_entry("test_tiles", 16, 16)], AssetsPayloadSource::from_bytes(data), gfx_installer, sound_installer, @@ -1170,7 +1174,7 @@ mod tests { #[test] fn test_status_returns_unknown_handle() { let banks = Arc::new(MemoryBanks::new()); - let gfx_installer = Arc::clone(&banks) as Arc; + let gfx_installer = Arc::clone(&banks) as Arc; let sound_installer = Arc::clone(&banks) as Arc; let am = AssetManager::new(vec![], AssetsPayloadSource::empty(), gfx_installer, sound_installer); @@ -1181,11 +1185,11 @@ mod tests { #[test] fn test_commit_and_cancel_return_explicit_statuses() { let banks = Arc::new(MemoryBanks::new()); - let gfx_installer = Arc::clone(&banks) as Arc; + let gfx_installer = Arc::clone(&banks) as Arc; let sound_installer = Arc::clone(&banks) as Arc; - let data = test_tile_asset_data(); + let data = test_glyph_asset_data(); let am = AssetManager::new( - vec![test_tile_asset_entry("test_tiles", 16, 16)], + vec![test_glyph_asset_entry("test_tiles", 16, 16)], AssetsPayloadSource::from_bytes(data), gfx_installer, sound_installer, diff --git a/crates/console/prometeu-drivers/src/gfx.rs b/crates/console/prometeu-drivers/src/gfx.rs index 13acba61..ae525130 100644 --- a/crates/console/prometeu-drivers/src/gfx.rs +++ b/crates/console/prometeu-drivers/src/gfx.rs @@ -1,10 +1,10 @@ -use crate::memory_banks::TileBankPoolAccess; +use crate::memory_banks::GlyphBankPoolAccess; use prometeu_hal::GfxBridge; use prometeu_hal::color::Color; use prometeu_hal::glyph::Glyph; +use prometeu_hal::glyph_bank::{GlyphBank, TileSize}; use prometeu_hal::sprite::Sprite; use prometeu_hal::tile::Tile; -use prometeu_hal::tile_bank::{TileBank, TileSize}; use prometeu_hal::tile_layer::{HudTileLayer, ScrollableTileLayer, TileMap}; use std::sync::Arc; @@ -57,12 +57,12 @@ pub struct Gfx { /// Back buffer: the "Work RAM" where new frames are composed. back: Vec, - /// 4 scrollable background layers. Each can have its own scroll (X, Y) and TileBank. + /// 4 scrollable background layers. Each can have its own scroll (X, Y) and GlyphBank. pub layers: [ScrollableTileLayer; 4], /// 1 fixed layer for User Interface (HUD). It doesn't scroll. pub hud: HudTileLayer, /// Shared access to graphical memory banks (tiles and palettes). - pub tile_banks: Arc, + pub glyph_banks: Arc, /// Hardware sprite list (512 slots). Equivalent to OAM (Object Attribute Memory). pub sprites: [Sprite; 512], @@ -274,7 +274,7 @@ impl GfxBridge for Gfx { impl Gfx { /// Initializes the graphics system with a specific resolution and shared memory banks. - pub fn new(w: usize, h: usize, tile_banks: Arc) -> Self { + pub fn new(w: usize, h: usize, glyph_banks: Arc) -> Self { const EMPTY_GLYPH: Glyph = Glyph { glyph_id: 0, palette_id: 0 }; const EMPTY_SPRITE: Sprite = Sprite { @@ -303,7 +303,7 @@ impl Gfx { back: vec![0; len], layers, hud: HudTileLayer::new(64, 32), - tile_banks, + glyph_banks, sprites: [EMPTY_SPRITE; 512], scene_fade_level: 31, scene_fade_color: Color::BLACK, @@ -583,14 +583,14 @@ impl Gfx { self.h, &self.priority_buckets[0], &self.sprites, - &*self.tile_banks, + &*self.glyph_banks, ); // 2. Main layers and prioritized sprites. // Order: Layer 0 -> Sprites 1 -> Layer 1 -> Sprites 2 ... for i in 0..self.layers.len() { let bank_id = self.layers[i].bank_id as usize; - if let Some(bank) = self.tile_banks.tile_bank_slot(bank_id) { + if let Some(bank) = self.glyph_banks.glyph_bank_slot(bank_id) { Self::draw_tile_map( &mut self.back, self.w, @@ -609,7 +609,7 @@ impl Gfx { self.h, &self.priority_buckets[i + 1], &self.sprites, - &*self.tile_banks, + &*self.glyph_banks, ); } @@ -617,7 +617,7 @@ impl Gfx { Self::apply_fade_to_buffer(&mut self.back, self.scene_fade_level, self.scene_fade_color); // 5. HUD: The fixed interface layer, always drawn on top of the world. - Self::render_hud_with_pool(&mut self.back, self.w, self.h, &self.hud, &*self.tile_banks); + Self::render_hud_with_pool(&mut self.back, self.w, self.h, &self.hud, &*self.glyph_banks); // 6. HUD Fade: Independent fade effect for the UI. Self::apply_fade_to_buffer(&mut self.back, self.hud_fade_level, self.hud_fade_color); @@ -633,7 +633,7 @@ impl Gfx { let scroll_x = self.layers[layer_idx].scroll_x; let scroll_y = self.layers[layer_idx].scroll_y; - let bank = match self.tile_banks.tile_bank_slot(bank_id) { + let bank = match self.glyph_banks.glyph_bank_slot(bank_id) { Some(b) => b, _ => return, }; @@ -651,7 +651,7 @@ impl Gfx { /// Renders the HUD (fixed position, no scroll). pub fn render_hud(&mut self) { - Self::render_hud_with_pool(&mut self.back, self.w, self.h, &self.hud, &*self.tile_banks); + Self::render_hud_with_pool(&mut self.back, self.w, self.h, &self.hud, &*self.glyph_banks); } fn render_hud_with_pool( @@ -659,10 +659,10 @@ impl Gfx { w: usize, h: usize, hud: &HudTileLayer, - tile_banks: &dyn TileBankPoolAccess, + glyph_banks: &dyn GlyphBankPoolAccess, ) { let bank_id = hud.bank_id as usize; - let bank = match tile_banks.tile_bank_slot(bank_id) { + let bank = match glyph_banks.glyph_bank_slot(bank_id) { Some(b) => b, _ => return, }; @@ -676,7 +676,7 @@ impl Gfx { screen_w: usize, screen_h: usize, map: &TileMap, - bank: &TileBank, + bank: &GlyphBank, scroll_x: i32, scroll_y: i32, ) { @@ -739,7 +739,7 @@ impl Gfx { x: i32, y: i32, tile: Tile, - bank: &TileBank, + bank: &GlyphBank, ) { let size = bank.tile_size as usize; @@ -781,12 +781,12 @@ impl Gfx { screen_h: usize, bucket: &[usize], sprites: &[Sprite], - tile_banks: &dyn TileBankPoolAccess, + glyph_banks: &dyn GlyphBankPoolAccess, ) { for &idx in bucket { let s = &sprites[idx]; let bank_id = s.bank_id as usize; - if let Some(bank) = tile_banks.tile_bank_slot(bank_id) { + if let Some(bank) = glyph_banks.glyph_bank_slot(bank_id) { Self::draw_sprite_pixel_by_pixel(back, screen_w, screen_h, s, &bank); } } @@ -797,7 +797,7 @@ impl Gfx { screen_w: usize, screen_h: usize, sprite: &Sprite, - bank: &TileBank, + bank: &GlyphBank, ) { // ... (same bounds/clipping calculation we already had) ... let size = bank.tile_size as usize; diff --git a/crates/console/prometeu-drivers/src/hardware.rs b/crates/console/prometeu-drivers/src/hardware.rs index 21834223..1eb6598e 100644 --- a/crates/console/prometeu-drivers/src/hardware.rs +++ b/crates/console/prometeu-drivers/src/hardware.rs @@ -2,8 +2,8 @@ use crate::asset::AssetManager; use crate::audio::Audio; use crate::gfx::Gfx; use crate::memory_banks::{ - MemoryBanks, SoundBankPoolAccess, SoundBankPoolInstaller, TileBankPoolAccess, - TileBankPoolInstaller, + GlyphBankPoolAccess, GlyphBankPoolInstaller, MemoryBanks, SoundBankPoolAccess, + SoundBankPoolInstaller, }; use crate::pad::Pad; use crate::touch::Touch; @@ -32,7 +32,7 @@ pub struct Hardware { pub pad: Pad, /// The absolute pointer input device (Mouse/Touchscreen). pub touch: Touch, - /// The Asset Management system (DMA). Handles loading data into VRAM (TileBanks) and ARAM (SoundBanks). + /// The Asset Management system (DMA). Handles loading data into VRAM (GlyphBanks) and ARAM (SoundBanks). pub assets: AssetManager, } @@ -92,7 +92,7 @@ impl Hardware { gfx: Gfx::new( Self::W, Self::H, - Arc::clone(&memory_banks) as Arc, + Arc::clone(&memory_banks) as Arc, ), audio: Audio::new(Arc::clone(&memory_banks) as Arc), pad: Pad::default(), @@ -100,7 +100,7 @@ impl Hardware { assets: AssetManager::new( vec![], AssetsPayloadSource::empty(), - Arc::clone(&memory_banks) as Arc, + Arc::clone(&memory_banks) as Arc, Arc::clone(&memory_banks) as Arc, ), } diff --git a/crates/console/prometeu-drivers/src/memory_banks.rs b/crates/console/prometeu-drivers/src/memory_banks.rs index d4d59fd6..b2b48307 100644 --- a/crates/console/prometeu-drivers/src/memory_banks.rs +++ b/crates/console/prometeu-drivers/src/memory_banks.rs @@ -1,19 +1,19 @@ +use prometeu_hal::glyph_bank::GlyphBank; use prometeu_hal::sound_bank::SoundBank; -use prometeu_hal::tile_bank::TileBank; use std::sync::{Arc, RwLock}; -/// Non-generic interface for peripherals to access graphical tile banks. -pub trait TileBankPoolAccess: Send + Sync { - /// Returns a reference to the resident TileBank in the specified slot, if any. - fn tile_bank_slot(&self, slot: usize) -> Option>; +/// Non-generic interface for peripherals to access graphical glyph banks. +pub trait GlyphBankPoolAccess: Send + Sync { + /// Returns a reference to the resident GlyphBank in the specified slot, if any. + fn glyph_bank_slot(&self, slot: usize) -> Option>; /// Returns the total number of slots available in this bank. - fn tile_bank_slot_count(&self) -> usize; + fn glyph_bank_slot_count(&self) -> usize; } -/// Non-generic interface for the AssetManager to install graphical tile banks. -pub trait TileBankPoolInstaller: Send + Sync { - /// Atomically swaps the resident TileBank in the specified slot. - fn install_tile_bank(&self, slot: usize, bank: Arc); +/// Non-generic interface for the AssetManager to install graphical glyph banks. +pub trait GlyphBankPoolInstaller: Send + Sync { + /// Atomically swaps the resident GlyphBank in the specified slot. + fn install_glyph_bank(&self, slot: usize, bank: Arc); } /// Non-generic interface for peripherals to access sound banks. @@ -36,7 +36,7 @@ pub trait SoundBankPoolInstaller: Send + Sync { /// Peripherals consume this state via narrow, non-generic traits. /// AssetManager coordinates residency and installs assets into these slots. pub struct MemoryBanks { - tile_bank_pool: Arc>; 16]>>, + glyph_bank_pool: Arc>; 16]>>, sound_bank_pool: Arc>; 16]>>, } @@ -50,26 +50,26 @@ impl MemoryBanks { /// Creates a new set of memory banks with empty slots. pub fn new() -> Self { Self { - tile_bank_pool: Arc::new(RwLock::new(std::array::from_fn(|_| None))), + glyph_bank_pool: Arc::new(RwLock::new(std::array::from_fn(|_| None))), sound_bank_pool: Arc::new(RwLock::new(std::array::from_fn(|_| None))), } } } -impl TileBankPoolAccess for MemoryBanks { - fn tile_bank_slot(&self, slot: usize) -> Option> { - let pool = self.tile_bank_pool.read().unwrap(); +impl GlyphBankPoolAccess for MemoryBanks { + fn glyph_bank_slot(&self, slot: usize) -> Option> { + let pool = self.glyph_bank_pool.read().unwrap(); pool.get(slot).and_then(|s| s.as_ref().map(Arc::clone)) } - fn tile_bank_slot_count(&self) -> usize { + fn glyph_bank_slot_count(&self) -> usize { 16 } } -impl TileBankPoolInstaller for MemoryBanks { - fn install_tile_bank(&self, slot: usize, bank: Arc) { - let mut pool = self.tile_bank_pool.write().unwrap(); +impl GlyphBankPoolInstaller for MemoryBanks { + fn install_glyph_bank(&self, slot: usize, bank: Arc) { + let mut pool = self.glyph_bank_pool.write().unwrap(); if slot < 16 { pool[slot] = Some(bank); } diff --git a/crates/console/prometeu-hal/src/asset.rs b/crates/console/prometeu-hal/src/asset.rs index 8e9346eb..443595f3 100644 --- a/crates/console/prometeu-hal/src/asset.rs +++ b/crates/console/prometeu-hal/src/asset.rs @@ -6,7 +6,7 @@ pub type AssetId = i32; #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Deserialize, Serialize)] #[allow(non_camel_case_types)] pub enum BankType { - TILES, + GLYPH, SOUNDS, // TILEMAPS, // BLOBS, @@ -31,7 +31,7 @@ pub struct AssetEntry { } #[derive(Debug, Clone, Deserialize, Serialize)] -pub struct TilesMetadata { +pub struct GlyphsMetadata { pub tile_size: u32, pub width: u32, pub height: u32, @@ -46,15 +46,15 @@ pub struct SoundsMetadata { } impl AssetEntry { - pub fn metadata_as_tiles(&self) -> Result { - if self.bank_type != BankType::TILES { + pub fn metadata_as_glyphs(&self) -> Result { + if self.bank_type != BankType::GLYPH { return Err(format!( - "Asset {} is not a TILES bank (type: {:?})", + "Asset {} is not a GLYPH bank (type: {:?})", self.asset_id, self.bank_type )); } serde_json::from_value(self.metadata.clone()) - .map_err(|e| format!("Invalid TILES metadata for asset {}: {}", self.asset_id, e)) + .map_err(|e| format!("Invalid GLYPH metadata for asset {}: {}", self.asset_id, e)) } pub fn metadata_as_sounds(&self) -> Result { @@ -130,7 +130,7 @@ pub struct SlotRef { impl SlotRef { pub fn gfx(index: usize) -> Self { - Self { asset_type: BankType::TILES, index } + Self { asset_type: BankType::GLYPH, index } } pub fn audio(index: usize) -> Self { diff --git a/crates/console/prometeu-hal/src/cartridge_loader.rs b/crates/console/prometeu-hal/src/cartridge_loader.rs index 4b410015..ed46a15f 100644 --- a/crates/console/prometeu-hal/src/cartridge_loader.rs +++ b/crates/console/prometeu-hal/src/cartridge_loader.rs @@ -200,7 +200,7 @@ mod tests { use super::*; use crate::asset::{AssetCodec, AssetEntry, BankType, PreloadEntry}; use crate::cartridge::{ASSETS_PA_MAGIC, ASSETS_PA_SCHEMA_VERSION, AssetsPackPrelude}; - use crate::tile_bank::TILE_BANK_PALETTE_COUNT_V1; + use crate::glyph_bank::GLYPH_BANK_PALETTE_COUNT_V1; use serde_json::json; use std::path::{Path, PathBuf}; use std::sync::atomic::{AtomicU64, Ordering}; @@ -363,17 +363,17 @@ mod tests { AssetEntry { asset_id: 7, asset_name: "tiles".to_string(), - bank_type: BankType::TILES, + bank_type: BankType::GLYPH, offset, size, - decoded_size: 16 * 16 + (TILE_BANK_PALETTE_COUNT_V1 as u64 * 16 * 2), + decoded_size: 16 * 16 + (GLYPH_BANK_PALETTE_COUNT_V1 as u64 * 16 * 2), codec: AssetCodec::None, metadata: json!({ "tile_size": 16, "width": 16, "height": 16, - "palette_count": TILE_BANK_PALETTE_COUNT_V1, - "palette_authored": TILE_BANK_PALETTE_COUNT_V1 + "palette_count": GLYPH_BANK_PALETTE_COUNT_V1, + "palette_authored": GLYPH_BANK_PALETTE_COUNT_V1 }), } } @@ -446,17 +446,17 @@ mod tests { AssetEntry { asset_id: 8, asset_name: "other_tiles".to_string(), - bank_type: BankType::TILES, + bank_type: BankType::GLYPH, offset: 4, size: 4, - decoded_size: 16 * 16 + (TILE_BANK_PALETTE_COUNT_V1 as u64 * 16 * 2), + decoded_size: 16 * 16 + (GLYPH_BANK_PALETTE_COUNT_V1 as u64 * 16 * 2), codec: AssetCodec::None, metadata: json!({ "tile_size": 16, "width": 16, "height": 16, - "palette_count": TILE_BANK_PALETTE_COUNT_V1, - "palette_authored": TILE_BANK_PALETTE_COUNT_V1 + "palette_count": GLYPH_BANK_PALETTE_COUNT_V1, + "palette_authored": GLYPH_BANK_PALETTE_COUNT_V1 }), }, ]; @@ -507,7 +507,7 @@ mod tests { "asset_table": [{ "asset_id": 7, "asset_name": "tiles", - "bank_type": "TILES", + "bank_type": "GLYPH", "offset": 0, "size": 4, "decoded_size": 768, @@ -516,8 +516,8 @@ mod tests { "tile_size": 16, "width": 16, "height": 16, - "palette_count": TILE_BANK_PALETTE_COUNT_V1, - "palette_authored": TILE_BANK_PALETTE_COUNT_V1 + "palette_count": GLYPH_BANK_PALETTE_COUNT_V1, + "palette_authored": GLYPH_BANK_PALETTE_COUNT_V1 } }], "preload": [] @@ -549,7 +549,7 @@ mod tests { "asset_table": [{ "asset_id": 7, "asset_name": "tiles", - "bank_type": "TILES", + "bank_type": "GLYPH", "offset": 0, "size": 4, "decoded_size": 768, @@ -558,8 +558,8 @@ mod tests { "tile_size": 16, "width": 16, "height": 16, - "palette_count": TILE_BANK_PALETTE_COUNT_V1, - "palette_authored": TILE_BANK_PALETTE_COUNT_V1 + "palette_count": GLYPH_BANK_PALETTE_COUNT_V1, + "palette_authored": GLYPH_BANK_PALETTE_COUNT_V1 } }], "preload": [] diff --git a/crates/console/prometeu-hal/src/tile_bank.rs b/crates/console/prometeu-hal/src/glyph_bank.rs similarity index 84% rename from crates/console/prometeu-hal/src/tile_bank.rs rename to crates/console/prometeu-hal/src/glyph_bank.rs index 422ba496..5c8bbce1 100644 --- a/crates/console/prometeu-hal/src/tile_bank.rs +++ b/crates/console/prometeu-hal/src/glyph_bank.rs @@ -1,7 +1,7 @@ use crate::color::Color; -pub const TILE_BANK_PALETTE_COUNT_V1: usize = 64; -pub const TILE_BANK_COLORS_PER_PALETTE: usize = 16; +pub const GLYPH_BANK_PALETTE_COUNT_V1: usize = 64; +pub const GLYPH_BANK_COLORS_PER_PALETTE: usize = 16; /// Standard sizes for square tiles. #[derive(Clone, Copy, Debug, PartialEq)] @@ -16,12 +16,12 @@ pub enum TileSize { /// A container for graphical assets. /// -/// A TileBank stores the decoded runtime representation of a tile-bank asset. +/// A GlyphBank stores the decoded runtime representation of a glyph-bank asset. /// /// Serialized `assets.pa` payloads keep pixel indices packed as `4bpp` nibbles. /// After decode, the runtime expands them to one `u8` palette index per pixel /// while preserving the same `0..15` logical range. -pub struct TileBank { +pub struct GlyphBank { /// Dimension of each individual tile in the bank. pub tile_size: TileSize, /// Width of the full bank sheet in pixels. @@ -34,18 +34,18 @@ pub struct TileBank { /// Index 0 is always reserved for transparency. pub pixel_indices: Vec, /// Runtime-facing v1 palette table: 64 palettes of 16 RGB565 colors each. - pub palettes: [[Color; TILE_BANK_COLORS_PER_PALETTE]; TILE_BANK_PALETTE_COUNT_V1], + pub palettes: [[Color; GLYPH_BANK_COLORS_PER_PALETTE]; GLYPH_BANK_PALETTE_COUNT_V1], } -impl TileBank { - /// Creates an empty tile bank with the specified dimensions. +impl GlyphBank { + /// Creates an empty glyph bank with the specified dimensions. pub fn new(tile_size: TileSize, width: usize, height: usize) -> Self { Self { tile_size, width, height, pixel_indices: vec![0; width * height], // Index 0 = Transparent - palettes: [[Color::BLACK; TILE_BANK_COLORS_PER_PALETTE]; TILE_BANK_PALETTE_COUNT_V1], + palettes: [[Color::BLACK; GLYPH_BANK_COLORS_PER_PALETTE]; GLYPH_BANK_PALETTE_COUNT_V1], } } diff --git a/crates/console/prometeu-hal/src/lib.rs b/crates/console/prometeu-hal/src/lib.rs index 1f7bd7af..cd789e09 100644 --- a/crates/console/prometeu-hal/src/lib.rs +++ b/crates/console/prometeu-hal/src/lib.rs @@ -8,6 +8,7 @@ pub mod color; pub mod debugger_protocol; pub mod gfx_bridge; pub mod glyph; +pub mod glyph_bank; pub mod hardware_bridge; pub mod host_context; pub mod host_return; @@ -22,7 +23,6 @@ pub mod sprite; pub mod syscalls; pub mod telemetry; pub mod tile; -pub mod tile_bank; pub mod tile_layer; pub mod touch_bridge; pub mod vm_fault; diff --git a/crates/console/prometeu-hal/src/tile_layer.rs b/crates/console/prometeu-hal/src/tile_layer.rs index 07078ebd..7ac6afea 100644 --- a/crates/console/prometeu-hal/src/tile_layer.rs +++ b/crates/console/prometeu-hal/src/tile_layer.rs @@ -1,6 +1,6 @@ +use crate::glyph_bank::TileSize; +use crate::glyph_bank::TileSize::Size8; use crate::tile::Tile; -use crate::tile_bank::TileSize; -use crate::tile_bank::TileSize::Size8; pub struct TileMap { pub width: usize, diff --git a/crates/console/prometeu-system/src/virtual_machine_runtime/dispatch.rs b/crates/console/prometeu-system/src/virtual_machine_runtime/dispatch.rs index d8fd483e..2504f0b1 100644 --- a/crates/console/prometeu-system/src/virtual_machine_runtime/dispatch.rs +++ b/crates/console/prometeu-system/src/virtual_machine_runtime/dispatch.rs @@ -481,7 +481,7 @@ impl NativeInterface for VirtualMachineRuntime { } Syscall::BankInfo => { let asset_type = match expect_int(args, 0)? as u32 { - 0 => BankType::TILES, + 0 => BankType::GLYPH, 1 => BankType::SOUNDS, _ => return Err(VmFault::Trap(TRAP_TYPE, "Invalid asset type".to_string())), }; @@ -492,7 +492,7 @@ impl NativeInterface for VirtualMachineRuntime { } Syscall::BankSlotInfo => { let asset_type = match expect_int(args, 0)? as u32 { - 0 => BankType::TILES, + 0 => BankType::GLYPH, 1 => BankType::SOUNDS, _ => return Err(VmFault::Trap(TRAP_TYPE, "Invalid asset type".to_string())), }; diff --git a/crates/console/prometeu-system/src/virtual_machine_runtime/tests.rs b/crates/console/prometeu-system/src/virtual_machine_runtime/tests.rs index 2dd34c41..293a35a9 100644 --- a/crates/console/prometeu-system/src/virtual_machine_runtime/tests.rs +++ b/crates/console/prometeu-system/src/virtual_machine_runtime/tests.rs @@ -12,8 +12,8 @@ use prometeu_hal::asset::{ AssetCodec, AssetEntry, AssetLoadError, AssetOpStatus, BankType, LoadStatus, }; use prometeu_hal::cartridge::{AssetsPayloadSource, Cartridge}; +use prometeu_hal::glyph_bank::GLYPH_BANK_PALETTE_COUNT_V1; use prometeu_hal::syscalls::caps; -use prometeu_hal::tile_bank::TILE_BANK_PALETTE_COUNT_V1; use prometeu_vm::VmInitError; use std::collections::HashMap; @@ -94,37 +94,37 @@ fn serialized_single_function_module_with_consts( .serialize() } -fn test_tile_payload_size(width: usize, height: usize) -> usize { - (width * height).div_ceil(2) + (TILE_BANK_PALETTE_COUNT_V1 * 16 * std::mem::size_of::()) +fn test_glyph_payload_size(width: usize, height: usize) -> usize { + (width * height).div_ceil(2) + (GLYPH_BANK_PALETTE_COUNT_V1 * 16 * std::mem::size_of::()) } -fn test_tile_decoded_size(width: usize, height: usize) -> usize { - width * height + (TILE_BANK_PALETTE_COUNT_V1 * 16 * std::mem::size_of::()) +fn test_glyph_decoded_size(width: usize, height: usize) -> usize { + width * height + (GLYPH_BANK_PALETTE_COUNT_V1 * 16 * std::mem::size_of::()) } -fn test_tile_asset_entry(asset_name: &str, data_len: usize) -> AssetEntry { +fn test_glyph_asset_entry(asset_name: &str, data_len: usize) -> AssetEntry { AssetEntry { asset_id: 7, asset_name: asset_name.to_string(), - bank_type: BankType::TILES, + bank_type: BankType::GLYPH, offset: 0, size: data_len as u64, - decoded_size: test_tile_decoded_size(16, 16) as u64, + decoded_size: test_glyph_decoded_size(16, 16) as u64, codec: AssetCodec::None, metadata: serde_json::json!({ "tile_size": 16, "width": 16, "height": 16, - "palette_count": TILE_BANK_PALETTE_COUNT_V1, - "palette_authored": TILE_BANK_PALETTE_COUNT_V1 + "palette_count": GLYPH_BANK_PALETTE_COUNT_V1, + "palette_authored": GLYPH_BANK_PALETTE_COUNT_V1 }), } } -fn test_tile_asset_data() -> Vec { +fn test_glyph_asset_data() -> Vec { let mut data = - vec![0x11u8; test_tile_payload_size(16, 16) - (TILE_BANK_PALETTE_COUNT_V1 * 16 * 2)]; - data.extend_from_slice(&[0u8; TILE_BANK_PALETTE_COUNT_V1 * 16 * 2]); + vec![0x11u8; test_glyph_payload_size(16, 16) - (GLYPH_BANK_PALETTE_COUNT_V1 * 16 * 2)]; + data.extend_from_slice(&[0u8; GLYPH_BANK_PALETTE_COUNT_V1 * 16 * 2]); data } @@ -439,10 +439,10 @@ fn tick_gfx_set_sprite_invalid_range_returns_status_not_crash() { }], ); let cartridge = cartridge_with_program(program, caps::GFX); - let asset_data = test_tile_asset_data(); + let asset_data = test_glyph_asset_data(); hardware.assets.initialize_for_cartridge( - vec![test_tile_asset_entry("tile_asset", asset_data.len())], + vec![test_glyph_asset_entry("tile_asset", asset_data.len())], vec![prometeu_hal::asset::PreloadEntry { asset_id: 7, slot: 0 }], AssetsPayloadSource::from_bytes(asset_data), ); @@ -637,9 +637,9 @@ fn tick_asset_load_invalid_slot_returns_status_and_zero_handle() { let mut vm = VirtualMachine::default(); let mut hardware = Hardware::new(); let signals = InputSignals::default(); - let asset_data = test_tile_asset_data(); + let asset_data = test_glyph_asset_data(); hardware.assets.initialize_for_cartridge( - vec![test_tile_asset_entry("tile_asset", asset_data.len())], + vec![test_glyph_asset_entry("tile_asset", asset_data.len())], vec![], AssetsPayloadSource::from_bytes(asset_data), ); @@ -721,9 +721,9 @@ fn tick_asset_commit_invalid_transition_returns_status_not_crash() { ); let cartridge = cartridge_with_program(program, caps::ASSET); - let asset_data = test_tile_asset_data(); + let asset_data = test_glyph_asset_data(); hardware.assets.initialize_for_cartridge( - vec![test_tile_asset_entry("tile_asset", asset_data.len())], + vec![test_glyph_asset_entry("tile_asset", asset_data.len())], vec![], AssetsPayloadSource::from_bytes(asset_data), ); @@ -782,9 +782,9 @@ fn tick_asset_cancel_invalid_transition_returns_status_not_crash() { ); let cartridge = cartridge_with_program(program, caps::ASSET); - let asset_data = test_tile_asset_data(); + let asset_data = test_glyph_asset_data(); hardware.assets.initialize_for_cartridge( - vec![test_tile_asset_entry("tile_asset", asset_data.len())], + vec![test_glyph_asset_entry("tile_asset", asset_data.len())], vec![], AssetsPayloadSource::from_bytes(asset_data), ); diff --git a/crates/console/prometeu-system/src/virtual_machine_runtime/tick.rs b/crates/console/prometeu-system/src/virtual_machine_runtime/tick.rs index 61d19946..40c4f951 100644 --- a/crates/console/prometeu-system/src/virtual_machine_runtime/tick.rs +++ b/crates/console/prometeu-system/src/virtual_machine_runtime/tick.rs @@ -166,7 +166,7 @@ impl VirtualMachineRuntime { self.last_frame_cpu_time_us = start.elapsed().as_micros() as u64; - let gfx_stats = hw.assets().bank_info(BankType::TILES); + let gfx_stats = hw.assets().bank_info(BankType::GLYPH); self.telemetry_current.gfx_used_bytes = gfx_stats.used_bytes; self.telemetry_current.gfx_inflight_bytes = gfx_stats.inflight_bytes; self.telemetry_current.gfx_slots_occupied = gfx_stats.slots_occupied as u32; diff --git a/crates/tools/pbxgen-stress/src/lib.rs b/crates/tools/pbxgen-stress/src/lib.rs index 14bb6bea..79a42dfc 100644 --- a/crates/tools/pbxgen-stress/src/lib.rs +++ b/crates/tools/pbxgen-stress/src/lib.rs @@ -67,7 +67,7 @@ pub fn generate() -> Result<()> { const_pool: vec![ ConstantPoolEntry::String("stress".into()), ConstantPoolEntry::String("frame".into()), - ConstantPoolEntry::String("missing_tile_bank".into()), + ConstantPoolEntry::String("missing_glyph_bank".into()), ], functions, code: rom, diff --git a/discussion/index.ndjson b/discussion/index.ndjson index 4f6a488d..eb065250 100644 --- a/discussion/index.ndjson +++ b/discussion/index.ndjson @@ -1,6 +1,7 @@ -{"type":"meta","next_id":{"DSC":22,"AGD":20,"DEC":6,"PLN":5,"LSN":25,"CLSN":1}} +{"type":"meta","next_id":{"DSC":23,"AGD":21,"DEC":7,"PLN":6,"LSN":25,"CLSN":1}} {"type":"discussion","id":"DSC-0020","status":"done","ticket":"jenkins-gitea-integration","title":"Jenkins Gitea Integration and Relocation","created_at":"2026-04-07","updated_at":"2026-04-07","tags":["ci","jenkins","gitea"],"agendas":[{"id":"AGD-0018","file":"workflow/agendas/AGD-0018-jenkins-gitea-integration-and-relocation.md","status":"done","created_at":"2026-04-07","updated_at":"2026-04-07"}],"decisions":[{"id":"DEC-0003","file":"workflow/decisions/DEC-0003-jenkins-gitea-strategy.md","status":"accepted","created_at":"2026-04-07","updated_at":"2026-04-07"}],"plans":[{"id":"PLN-0003","file":"workflow/plans/PLN-0003-jenkins-gitea-execution.md","status":"done","created_at":"2026-04-07","updated_at":"2026-04-07"}],"lessons":[{"id":"LSN-0021","file":"lessons/DSC-0020-jenkins-gitea-integration/LSN-0021-jenkins-gitea-integration.md","status":"done","created_at":"2026-04-07","updated_at":"2026-04-07"}]} {"type":"discussion","id":"DSC-0021","status":"done","ticket":"asset-entry-codec-enum-with-metadata","title":"Asset Entry Codec Enum Contract","created_at":"2026-04-09","updated_at":"2026-04-09","tags":["asset","runtime","codec","metadata"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0024","file":"lessons/DSC-0021-asset-entry-codec-enum-contract/LSN-0024-string-on-the-wire-enum-in-runtime.md","status":"done","created_at":"2026-04-09","updated_at":"2026-04-09"}]} +{"type":"discussion","id":"DSC-0022","status":"open","ticket":"tile-bank-vs-glyph-bank-domain-naming","title":"Glyph Bank Domain Naming Contract","created_at":"2026-04-09","updated_at":"2026-04-10","tags":["gfx","runtime","naming","domain-model"],"agendas":[{"id":"AGD-0020","file":"AGD-0020-tile-bank-vs-glyph-bank-domain-naming.md","status":"accepted","created_at":"2026-04-09","updated_at":"2026-04-10"}],"decisions":[{"id":"DEC-0006","file":"DEC-0006-glyph-bank-domain-naming-contract.md","status":"accepted","created_at":"2026-04-10","updated_at":"2026-04-10","ref_agenda":"AGD-0020"}],"plans":[{"id":"PLN-0005","file":"PLN-0005-glyph-bank-domain-naming-execution.md","status":"accepted","created_at":"2026-04-10","updated_at":"2026-04-10","ref_decisions":["DEC-0006"]}],"lessons":[]} {"type":"discussion","id":"DSC-0001","status":"done","ticket":"legacy-runtime-learn-import","title":"Import legacy runtime learn into discussion lessons","created_at":"2026-03-27","updated_at":"2026-03-27","tags":["migration","tech-debt"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0001","file":"lessons/DSC-0001-runtime-learn-legacy-import/LSN-0001-prometeu-learn-index.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0002","file":"lessons/DSC-0001-runtime-learn-legacy-import/LSN-0002-historical-asset-status-first-fault-and-return-contract.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0003","file":"lessons/DSC-0001-runtime-learn-legacy-import/LSN-0003-historical-audio-status-first-fault-and-return-contract.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0004","file":"lessons/DSC-0001-runtime-learn-legacy-import/LSN-0004-historical-cartridge-boot-protocol-and-manifest-authority.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0005","file":"lessons/DSC-0001-runtime-learn-legacy-import/LSN-0005-historical-game-memcard-slots-surface-and-semantics.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0006","file":"lessons/DSC-0001-runtime-learn-legacy-import/LSN-0006-historical-gfx-status-first-fault-and-return-contract.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0007","file":"lessons/DSC-0001-runtime-learn-legacy-import/LSN-0007-historical-retired-fault-and-input-decisions.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0008","file":"lessons/DSC-0001-runtime-learn-legacy-import/LSN-0008-historical-vm-core-and-assets.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0009","file":"lessons/DSC-0001-runtime-learn-legacy-import/LSN-0009-mental-model-asset-management.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0010","file":"lessons/DSC-0001-runtime-learn-legacy-import/LSN-0010-mental-model-audio.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0011","file":"lessons/DSC-0001-runtime-learn-legacy-import/LSN-0011-mental-model-gfx.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0012","file":"lessons/DSC-0001-runtime-learn-legacy-import/LSN-0012-mental-model-input.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0013","file":"lessons/DSC-0001-runtime-learn-legacy-import/LSN-0013-mental-model-observability-and-debugging.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0014","file":"lessons/DSC-0001-runtime-learn-legacy-import/LSN-0014-mental-model-portability-and-cross-platform.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0015","file":"lessons/DSC-0001-runtime-learn-legacy-import/LSN-0015-mental-model-save-memory-and-memcard.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0016","file":"lessons/DSC-0001-runtime-learn-legacy-import/LSN-0016-mental-model-status-first-and-fault-thinking.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0017","file":"lessons/DSC-0001-runtime-learn-legacy-import/LSN-0017-mental-model-time-and-cycles.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0018","file":"lessons/DSC-0001-runtime-learn-legacy-import/LSN-0018-mental-model-touch.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"}]} {"type":"discussion","id":"DSC-0002","status":"open","ticket":"runtime-edge-test-plan","title":"Agenda - Runtime Edge Test Plan","created_at":"2026-03-27","updated_at":"2026-03-27","tags":[],"agendas":[{"id":"AGD-0001","file":"workflow/agendas/AGD-0001-runtime-edge-test-plan.md","status":"open","created_at":"2026-03-27","updated_at":"2026-03-27"}],"decisions":[],"plans":[],"lessons":[]} {"type":"discussion","id":"DSC-0003","status":"open","ticket":"packed-cartridge-loader-pmc","title":"Agenda - Packed Cartridge Loader PMC","created_at":"2026-03-27","updated_at":"2026-03-27","tags":[],"agendas":[{"id":"AGD-0002","file":"workflow/agendas/AGD-0002-packed-cartridge-loader-pmc.md","status":"open","created_at":"2026-03-27","updated_at":"2026-03-27"}],"decisions":[],"plans":[],"lessons":[]} diff --git a/discussion/lessons/DSC-0001-runtime-learn-legacy-import/LSN-0009-mental-model-asset-management.md b/discussion/lessons/DSC-0001-runtime-learn-legacy-import/LSN-0009-mental-model-asset-management.md index 59e6a78b..fddf9d11 100644 --- a/discussion/lessons/DSC-0001-runtime-learn-legacy-import/LSN-0009-mental-model-asset-management.md +++ b/discussion/lessons/DSC-0001-runtime-learn-legacy-import/LSN-0009-mental-model-asset-management.md @@ -123,7 +123,7 @@ The current asset model works better if you do not treat every bank as equally g Some banks are specialized: -- `TILES` +- `GLYPH` - `SOUNDS` For these, the bank contract already carries most of the important format rules. That means: @@ -163,7 +163,7 @@ It does not say: One of the most important asset-management lessons in the current runtime is that `codec = NONE` does not mean "bitwise identical to in-memory layout". -The tile-bank path is the concrete example: +The glyph-bank path is the concrete example: - there is no additional generic codec layer for the asset; - the serialized payload stores indexed pixels as packed `4bpp`; @@ -182,13 +182,13 @@ That is why `AssetEntry.size` and `AssetEntry.decoded_size` must be thought of a If those two numbers are treated as interchangeable, telemetry, budgets, and validation all become misleading. -## Tile Banks Teach The Real Boundary +## Glyph Banks Teach The Real Boundary -Tile banks are useful because they show the real separation of concerns: +Glyph banks are useful because they show the real separation of concerns: - `assets.pa` defines the serialized envelope and metadata needed to reconstruct the bank; - the runtime validates that metadata against the expected v1 contract; -- the resident `TileBank` is a runtime object, not a direct view over the cold bytes. +- the resident `GlyphBank` is a runtime object, not a direct view over the cold bytes. This is the right PROMETEU mental model: diff --git a/discussion/lessons/DSC-0001-runtime-learn-legacy-import/LSN-0011-mental-model-gfx.md b/discussion/lessons/DSC-0001-runtime-learn-legacy-import/LSN-0011-mental-model-gfx.md index 36c0a623..584ee5d0 100644 --- a/discussion/lessons/DSC-0001-runtime-learn-legacy-import/LSN-0011-mental-model-gfx.md +++ b/discussion/lessons/DSC-0001-runtime-learn-legacy-import/LSN-0011-mental-model-gfx.md @@ -18,7 +18,7 @@ PROMETEU treats graphics as an explicit peripheral, not as a modern GPU. The right mental model is a retro 2D machine with: - framebuffer; -- tile banks; +- glyph banks; - tile layers; - sprites ordered by draw order; - deterministic composition per frame. @@ -67,7 +67,7 @@ That enables: - HUD themes; - day and night cycles. -In the current tile-bank v1 baseline, this palette model is intentionally bounded: +In the current glyph-bank v1 baseline, this palette model is intentionally bounded: - each bank carries `64` palettes; - each palette carries `16` colors; @@ -75,7 +75,7 @@ In the current tile-bank v1 baseline, this palette model is intentionally bounde That limit is not incidental bookkeeping. It is part of how art packaging, runtime validation, and rendering stay aligned. -## Tile Banks Are Decoded Runtime Objects +## Glyph Banks Are Decoded Runtime Objects The most useful intuition is to separate three layers: @@ -83,13 +83,13 @@ The most useful intuition is to separate three layers: - serialized cart payload; - resident runtime bank. -For tile banks in v1: +For glyph banks in v1: - authored pixels are logical indices `0..15`; - serialized payload stores those indices as packed `4bpp`; - runtime memory expands them to one `u8` index per pixel after decode. -So when reading the graphics model, do not imagine the renderer reading packed nibbles directly from cartridge storage. The renderer consumes a decoded `TileBank` object whose memory shape is optimized for runtime lookup, not for transport density. +So when reading the graphics model, do not imagine the renderer reading packed nibbles directly from cartridge storage. The renderer consumes a decoded `GlyphBank` object whose memory shape is optimized for runtime lookup, not for transport density. ## Use Cases diff --git a/discussion/lessons/DSC-0016-tilemap-empty-cell-semantics/LSN-0022-tilemap-empty-cell-convergence.md b/discussion/lessons/DSC-0016-tilemap-empty-cell-semantics/LSN-0022-tilemap-empty-cell-convergence.md index 98cfe356..938f6672 100644 --- a/discussion/lessons/DSC-0016-tilemap-empty-cell-semantics/LSN-0022-tilemap-empty-cell-convergence.md +++ b/discussion/lessons/DSC-0016-tilemap-empty-cell-semantics/LSN-0022-tilemap-empty-cell-convergence.md @@ -1,7 +1,7 @@ # LSN-0022: Tilemap Empty Cell Semantics and Glyph Convergence ## Context -During the initial runtime design, `tile_id = 0` was used as a sentinel value for "empty" or "missing" tiles in tilemaps. However, as the asset banking and packer systems evolved, it became clear that `0` should be a valid index for any asset bank, including tile banks. This conflict was formally tracked in `AGD-0015`. +During the initial runtime design, `tile_id = 0` was used as a sentinel value for "empty" or "missing" tiles in tilemaps. However, as the asset banking and packer systems evolved, it became clear that `0` should be a valid index for any asset bank, including glyph banks. This conflict was formally tracked in `AGD-0015`. ## Lessons Learned diff --git a/discussion/lessons/DSC-0017-asset-metadata-normalization/LSN-0023-typed-asset-metadata-helpers.md b/discussion/lessons/DSC-0017-asset-metadata-normalization/LSN-0023-typed-asset-metadata-helpers.md index 51b462c5..5c7d779d 100644 --- a/discussion/lessons/DSC-0017-asset-metadata-normalization/LSN-0023-typed-asset-metadata-helpers.md +++ b/discussion/lessons/DSC-0017-asset-metadata-normalization/LSN-0023-typed-asset-metadata-helpers.md @@ -16,8 +16,8 @@ O uso de `serde_json::Value` diretamente nos loaders do runtime introduz riscos Para mitigar isso, implementamos o padrão de **Typed Metadata Helpers**: -1. **Structs Dedicadas**: Criamos structs Rust (ex: `TilesMetadata`, `SoundsMetadata`) que representam o contrato exato de cada banco. -2. **Conversion Methods**: Adicionamos métodos ao `AssetEntry` (ex: `metadata_as_tiles()`) que utilizam `serde_json::from_value` para realizar o "cast" do JSON dinâmico para a struct tipada. +1. **Structs Dedicadas**: Criamos structs Rust (ex: `GlyphsMetadata`, `SoundsMetadata`) que representam o contrato exato de cada banco. +2. **Conversion Methods**: Adicionamos métodos ao `AssetEntry` (ex: `metadata_as_glyphs()`) que utilizam `serde_json::from_value` para realizar o "cast" do JSON dinâmico para a struct tipada. 3. **Fail-Fast**: A falha no parsing dos metadados deve ser tratada como erro de carregamento do asset, garantindo que o motor não opere com metadados corrompidos ou incompletos. ### Benefícios diff --git a/discussion/workflow/agendas/AGD-0020-tile-bank-vs-glyph-bank-domain-naming.md b/discussion/workflow/agendas/AGD-0020-tile-bank-vs-glyph-bank-domain-naming.md new file mode 100644 index 00000000..7eda50a4 --- /dev/null +++ b/discussion/workflow/agendas/AGD-0020-tile-bank-vs-glyph-bank-domain-naming.md @@ -0,0 +1,221 @@ +--- +id: AGD-0020 +ticket: tile-bank-vs-glyph-bank-domain-naming +title: Agenda - Tile Bank vs Glyph Bank Domain Naming +status: accepted +created: 2026-04-09 +resolved: 2026-04-10 +decision: DEC-0006 +tags: [gfx, runtime, naming, domain-model] +--- + +# Agenda - Tile Bank vs Glyph Bank Domain Naming + +## Contexto + +Hoje o runtime usa `TileBank`, `tile_bank.rs`, `TileBankPool*` e termos derivados para nomear o banco grafico consumido pelo renderer e pelo pipeline de assets. + +Ao mesmo tempo, existe a vontade de elevar `Tile` para um conceito mais amplo do dominio, nao restrito ao sheet grafico concreto. Nessa leitura: + +- `Tile` passa a ser uma ideia mais geral da grade/elemento logico; +- o que hoje e o artefato grafico concreto chamado `TileBank` deveria passar a se chamar `GlyphBank`; +- a intencao inicial nao e mudar formato, memoria, payload ou algoritmo, e sim alinhar a linguagem do projeto. + +Esse tema ja encosta em documentacao e lessons existentes, porque o vocabulario atual mistura: + +- tile como unidade de composicao visual; +- tile bank como sheet grafico concreto; +- referencias esparsas a glyph em lições e agendas. + +## Problema + +Se o projeto mudar o centro semantico de `tile` e `glyph` sem uma decisao explicita, o repositorio tende a ficar com vocabulário hibrido: + +- tipos antigos com nome legado; +- docs novas com nome novo; +- renderer e assets falando uma lingua; +- lessons e discussoes falando outra. + +O problema principal nao e tecnico-algoritmico. E semantico e operacional: qual vocabulario o projeto quer tornar canonico para o banco grafico concreto, e qual parte dessa mudanca e apenas rename mecanico versus mudanca real de modelo. + +## Pontos Criticos + +1. Escopo da mudanca. + Precisamos separar rename de dominio de qualquer mudanca de formato ou comportamento. + +2. Contrato externo. + Precisamos fechar quais contratos externos tambem entram no rename. Ja existe direcao para migrar `BankType::TILES` para `BankType::GLYPH`. + +3. Consistencia de linguagem. + A mudanca so vale a pena se atingir codigo, tests, docs e lessons de forma coordenada. + +4. Custo de churn. + Mesmo sem mudar comportamento, o rename atravessa muitos modulos (`hal`, `drivers`, renderer, pools, mensagens de erro, tests e docs). + +5. Fronteira conceitual. + Precisamos definir o que `Tile` passa a significar depois do rename, para evitar trocar um overload semantico por outro. + +## Opcoes + +### Opcao A - Manter `TileBank` como esta + +- **Abordagem:** preservar `TileBank` como nome canonico do banco grafico concreto e aceitar que `tile` continue carregando tanto o lado logico quanto o lado visual. +- **Pro:** zero churn nominal imediato e nenhuma migracao de docs/codigo. +- **Con:** o overload conceitual de `tile` permanece e pode continuar poluindo a linguagem de dominio. +- **Tradeoff:** economiza trabalho agora ao custo de clareza futura. + +### Opcao B - Renomear `TileBank` para `GlyphBank` como refactor semantico + +- **Abordagem:** tratar a mudanca como rename consistente de tipos, modulos, docs, testes e mensagens, sem alterar formato de payload, layout em memoria ou renderer. +- **Pro:** melhora a linguagem do projeto sem reabrir a arquitetura grafica. +- **Con:** exige disciplina para manter a promessa de “rename only” e nao misturar isso com redesign. +- **Tradeoff:** churn mecanico relativamente alto para ganhar clareza conceitual. + +### Opcao C - Fazer rename parcial + +- **Abordagem:** adotar `glyph` apenas em docs novas ou em algumas camadas, preservando nomes antigos em APIs e modulos centrais. +- **Pro:** menor custo inicial. +- **Con:** cria o pior estado intermediario: dois vocabulários concorrentes para o mesmo conceito. +- **Tradeoff:** parece barato, mas deixa a linguagem do projeto menos confiavel. + +## Sugestao / Recomendacao + +Seguir inicialmente com a **Opcao B**, desde que a discussao confirme que a mudanca e de nomenclatura e nao de semantica operacional. + +A recomendacao provisoria e: + +- `GlyphBank` se torna o nome do artefato grafico concreto que hoje chamamos de `TileBank`; +- `Tile` fica livre para representar um conceito mais geral do dominio; +- `BankType::TILES` passa a `BankType::GLYPH`; +- a migracao deve ser consistente em codigo, tests, docs e lessons; +- `TileLayer` e derivados nao entram automaticamente no rename, porque ja pertencem a outra fronteira de dominio e precisam de triagem separada; +- a discussao deve explicitar quais superfícies mudam juntas para impedir vocabulario hibrido sem reabrir a arquitetura grafica. + +## Perguntas em Aberto + +- Confirmar a superficie exata do rename para evitar misturar banco grafico concreto com conceitos de layer/mapa. + +## Discussao + +### Direcao fechada ate aqui + +1. **Natureza da mudanca** + A mudanca e `rename-only`. Nao ha intencao de alterar formato, algoritmo, layout em memoria ou comportamento. + +2. **Contrato externo** + `BankType::TILES` nao deve permanecer. O contrato deve migrar para `BankType::GLYPH`. + +3. **Escopo documental** + A migracao deve ser completa, inclusive em documentacao e lessons historicas. + +4. **Colisao semantica** + `glyph` nao colide com outro artefato canonico relevante nesta etapa. + +### Fronteira importante + +Nem todo `Tile*` deve migrar automaticamente para `Glyph*`. + +Existe uma fronteira entre: + +- nomes que descrevem o banco grafico concreto e seu circuito de carga/uso; e +- nomes que ja descrevem dominio de layer, mapa, grade ou composicao. + +Por isso, a proxima resposta que falta precisa ser dada por superficie concreta, e nao por regra global simplista. + +### Lista para voto `sim` / `nao` + +Responda `sim` ou `nao` para cada grupo abaixo. + +1. **Banco concreto e modulo base** + Inclui `TileBank`, `tile_bank.rs`, comentarios e docs especificos desse tipo. + +2. **Enum e contrato de asset** + Inclui `BankType::TILES -> BankType::GLYPH`, mensagens de erro, metadata helpers e referencias equivalentes no path de assets. + +3. **Pools e interfaces de memoria** + Inclui `TileBankPoolAccess`, `TileBankPoolInstaller`, `tile_bank_slot`, `install_tile_bank`, campos internos como `tile_bank_pool`. + +4. **Asset manager e loader path** + Inclui funcoes como `decode_tile_bank_*`, `perform_load_tile_bank`, variaveis locais, testes e mensagens associadas ao load do banco grafico. + +5. **Renderer e hardware references ao banco** + Inclui usos em `gfx.rs` e `hardware.rs` que referenciam o banco concreto, por exemplo campos `tile_banks`, docs sobre VRAM `TileBanks`, parametros `bank: &TileBank`. + +6. **Modulo e tipos de layer/mapa** + Inclui `tile_layer.rs`, `TileMap`, `TileLayer`, `ScrollableTileLayer`, `HudTileLayer`. + Este grupo e o mais sensivel porque pode nao ser rename de banco concreto, e sim outro dominio. + +7. **TileSize** + Inclui `TileSize` e referencias ao tamanho de tile como unidade geometrica. + Este grupo pode continuar como `TileSize` mesmo se o banco virar `GlyphBank`. + +8. **Strings, fixtures e test names** + Inclui nomes de testes, helper names, snapshots, mensagens e dados de teste que ainda falam em tile bank. + +9. **Lessons e docs historicas** + Inclui lessons ja publicadas e material de discussao/mental model que hoje falam em `TileBank`. + +### Votos registrados + +1. **Banco concreto e modulo base**: `sim` + `TileBank`, `tile_bank.rs`, modulo base e documentacao associada entram na migracao. + +2. **Enum e contrato de asset**: `sim` + `BankType::TILES` e o contrato textual equivalente entram na migracao para `GLYPH`. + +3. **Pools e interfaces de memoria**: `sim` + `TileBankPool*`, `tile_bank_slot` e derivados entram na migracao. + +4. **Asset manager e loader path**: `sim` + Helpers, decode path, mensagens e testes associados ao banco grafico concreto entram na migracao. + +5. **Renderer e hardware references ao banco**: `sim` + Referencias ao banco concreto em renderer e hardware entram na migracao. + +6. **Modulo e tipos de layer/mapa**: `nao` + `TileLayer`, `TileMap`, `ScrollableTileLayer` e `HudTileLayer` ficam fora desta rodada. + +7. **TileSize**: `nao` + `TileSize` permanece como conceito geometrico e nao entra automaticamente no rename. + +8. **Strings, fixtures e test names**: `sim` + Helpers, fixtures, mensagens e nomes de testes entram na migracao para evitar residuos do vocabulario antigo. + +9. **Lessons e docs historicas**: `sim` + A migracao documental e historica entra no escopo, seguindo a mesma fronteira desta agenda: renomear o banco grafico concreto sem arrastar automaticamente o dominio de layer/mapa. + +## Resolucao Provisoria + +Ha consenso provisoriamente estabelecido sobre os seguintes pontos: + +- a mudanca e `rename-only`; +- o vocabulario canonico do banco grafico concreto passa de `TileBank` para `GlyphBank`; +- `BankType::TILES` deve migrar para `BankType::GLYPH`; +- pools, contrato de asset, loader path, renderer, hardware references, fixtures e nomes de teste entram na migracao; +- `TileLayer`/`TileMap` e derivados ficam fora desta rodada; +- `TileSize` fica fora desta rodada; +- docs e lessons historicas entram no escopo, respeitando essa mesma fronteira. + +O principal ponto restante para encerrar a agenda e confirmar se essa resolucao ja e suficiente para virar decisao normativa, ou se ainda falta detalhar como a migracao documental deve tratar referencias historicas em texto corrido quando `tile` continuar correto para layer/mapa. + +## Resolucao + +A agenda fica encerrada com a seguinte orientacao: + +- a mudanca e `rename-only`; +- o banco grafico concreto passa a se chamar `GlyphBank`; +- `BankType::TILES` passa a `BankType::GLYPH`; +- pools, contrato de asset, loader path, renderer, hardware references, fixtures, nomes de teste, docs e lessons entram na migracao; +- `TileLayer`, `TileMap` e derivados ficam fora; +- `TileSize` fica fora; +- docs e lessons antigas devem migrar referencias ao banco grafico concreto para `GlyphBank`, mantendo `tile` quando o assunto for layer, mapa, grade ou geometria. + +## Criterio para Encerrar + +Esta agenda pode ser encerrada quando houver consenso escrito sobre: + +- se a mudanca e rename-only ou nao; +- qual vocabulario passa a ser canonico; +- quais contratos externos entram no rename; +- quais grupos concretos entram ou nao na migracao; +- como evitar que `TileLayer`/`TileMap` sejam arrastados automaticamente sem decisao propria. diff --git a/discussion/workflow/decisions/DEC-0006-glyph-bank-domain-naming-contract.md b/discussion/workflow/decisions/DEC-0006-glyph-bank-domain-naming-contract.md new file mode 100644 index 00000000..65a66ebf --- /dev/null +++ b/discussion/workflow/decisions/DEC-0006-glyph-bank-domain-naming-contract.md @@ -0,0 +1,93 @@ +--- +id: DEC-0006 +ticket: tile-bank-vs-glyph-bank-domain-naming +title: Glyph Bank Domain Naming Contract +status: accepted +created: 2026-04-10 +accepted: 2026-04-10 +agenda: AGD-0020 +plans: [PLN-0005] +tags: [gfx, runtime, naming, domain-model] +--- + +## Status + +Accepted on 2026-04-10. + +## Contexto + +The runtime currently uses `TileBank` and related names for the concrete graphical bank consumed by the asset pipeline and renderer. At the same time, the project wants `Tile` to remain available as a broader domain concept for grid, layer, map, and geometric tile semantics. + +This decision closes the naming contract by separating: + +- the concrete graphical bank artifact; +- the logical tile/layer/map domain; +- the migration boundary for code, tests, docs, and historical lessons. + +The change is explicitly rename-only. It does not alter format, runtime behavior, memory layout, payload structure, or renderer algorithms. + +## Decisao + +1. The concrete graphical bank currently named `TileBank` MUST be renamed to `GlyphBank`. +2. This rename MUST be treated as nomenclature-only. It MUST NOT change payload format, runtime behavior, memory layout, codec behavior, metadata structure, or rendering semantics. +3. `BankType::TILES` MUST be renamed to `BankType::GLYPH`. +4. The asset contract and runtime code that refer to the concrete graphical bank MUST migrate to `Glyph*` naming consistently. +5. The following groups MUST be included in the rename: + - concrete bank type and module; + - asset contract and asset-facing terminology; + - memory pools and bank installation/access interfaces; + - asset manager decode/load path; + - renderer and hardware references to the concrete bank; + - fixtures, test names, helper names, and user-facing/runtime-facing strings for the concrete bank; + - documentation and historical lessons, subject to the editorial boundary below. +6. The following groups MUST NOT be renamed as part of this decision: + - `TileLayer`, `TileMap`, `ScrollableTileLayer`, `HudTileLayer`, and related layer/map structures; + - `TileSize` and geometric tile-size concepts. +7. Documentation and historical lessons MUST be updated with the following editorial rule: + - references to the concrete graphical bank artifact MUST migrate to `GlyphBank` and equivalent `Glyph*` naming; + - references to layer, map, grid, or geometric tile concepts MUST remain `tile` when that is the correct domain meaning. +8. The project MUST NOT adopt a partial mixed vocabulary where the same concrete bank artifact is simultaneously described as both `TileBank` and `GlyphBank` in active code or maintained documentation. +9. `glyph` is treated as a new canonical artifact name for this stage and does not conflict with an existing canonical artifact that would block adoption. + +## Rationale + +- The current name overloads `tile` across both logical map/layer concepts and the concrete graphical bank artifact. +- Renaming only the concrete bank artifact improves domain clarity without reopening graphics architecture. +- Excluding `TileLayer`, `TileMap`, and `TileSize` preserves established semantics where `tile` still means the logical or geometric concept. +- A full migration across code, tests, docs, and lessons avoids the unstable mixed-language state that tends to follow partial renames. + +## Invariantes / Contrato + +- `GlyphBank` is the canonical name for the concrete graphical bank artifact. +- `tile` remains canonical for layer/map/geometric concepts unless a later decision explicitly changes that. +- `BankType::GLYPH` is the canonical asset-bank enum variant for the concrete graphical bank. +- This decision is a rename boundary, not a behavior-change boundary. +- Documentation must follow artifact meaning, not mechanical string replacement. + +## Impactos + +- `prometeu-hal` will need type/module/enum renames for the concrete graphical bank path. +- `prometeu-drivers` will need renderer, memory-pool, hardware, and asset-manager naming migration for bank-specific references. +- Tests, fixtures, and helper names need coordinated updates to avoid mixed terminology. +- Docs and lessons need targeted rewriting rather than blind search-and-replace, because `tile` remains correct in map/layer contexts. + +## Referencias + +- AGD-0020: Tile Bank vs Glyph Bank Domain Naming +- LSN-0022: Tilemap Empty Cell Convergence +- `crates/console/prometeu-hal/src/tile_bank.rs` +- `crates/console/prometeu-hal/src/tile_layer.rs` +- `crates/console/prometeu-drivers/src/gfx.rs` +- `crates/console/prometeu-drivers/src/memory_banks.rs` +- `crates/console/prometeu-drivers/src/asset.rs` + +## Propagacao Necessaria + +- Write an execution plan before code and documentation migration. +- Rename the concrete bank surface consistently across runtime crates. +- Preserve `tile` naming in layer/map/geometric surfaces excluded by this decision. +- Update docs and lessons according to artifact meaning, not blanket replacement. + +## Revision Log + +- 2026-04-10: Initial accepted decision from AGD-0020. diff --git a/discussion/workflow/plans/PLN-0005-glyph-bank-domain-naming-execution.md b/discussion/workflow/plans/PLN-0005-glyph-bank-domain-naming-execution.md new file mode 100644 index 00000000..77465faf --- /dev/null +++ b/discussion/workflow/plans/PLN-0005-glyph-bank-domain-naming-execution.md @@ -0,0 +1,161 @@ +--- +id: PLN-0005 +ticket: tile-bank-vs-glyph-bank-domain-naming +title: Glyph Bank Domain Naming Execution +status: accepted +created: 2026-04-10 +completed: +tags: [gfx, runtime, naming, domain-model] +--- + +## Briefing + +Implement DEC-0006 by renaming the concrete graphical bank artifact from `TileBank` to `GlyphBank` across runtime code, tests, documentation, and historical lessons, while preserving behavior and keeping the excluded tile-domain surfaces untouched. This is a rename-only migration. It must not alter payload format, rendering semantics, codec behavior, metadata structure, or memory layout. + +## Decisions de Origem + +- DEC-0006: Glyph Bank Domain Naming Contract + +## Alvo + +Land a consistent runtime-and-docs migration that: + +- renames the concrete bank artifact and its module/type surface to `GlyphBank`; +- renames `BankType::TILES` to `BankType::GLYPH`; +- renames pool and loader/runtime bank-specific APIs accordingly; +- preserves `TileLayer`, `TileMap`, `ScrollableTileLayer`, `HudTileLayer`, and `TileSize`; +- rewrites maintained docs and lessons according to artifact meaning rather than blanket token replacement. + +## Escopo + +- `prometeu-hal` concrete bank type/module/enum renames. +- `prometeu-drivers` renderer, memory-bank, hardware, and asset-manager bank-specific renames. +- `prometeu-system` callsites and dispatch paths that refer to the asset-bank enum variant. +- Tests, helpers, fixtures, and strings that still describe the concrete bank as `TileBank`. +- Discussion lessons and maintained discussion artifacts that refer to the concrete graphical bank artifact. + +## Fora de Escopo + +- Any format, algorithm, codec, metadata, or layout change. +- Renaming `TileLayer`, `TileMap`, `ScrollableTileLayer`, `HudTileLayer`, or related layer/map structures. +- Renaming `TileSize` or geometric tile-size concepts. +- Redesigning tile/glyph semantics beyond the naming boundary established by DEC-0006. + +## Plano de Execucao + +### Step 1 - Rename the HAL concrete bank surface + +**What:** +Rename the concrete bank module and type surface in `prometeu-hal` from `TileBank` to `GlyphBank`. + +**How:** +Rename `tile_bank.rs` to `glyph_bank.rs`, update `lib.rs` exports/import paths, rename `TileBank` to `GlyphBank`, and rename concrete-bank-specific constants if they are artifact-specific rather than geometric. Keep `TileSize` unchanged even if it continues to live near the bank implementation or must be re-exported from the renamed module in a compatibility-preserving layout inside this refactor. + +**File(s):** +- `crates/console/prometeu-hal/src/tile_bank.rs` +- `crates/console/prometeu-hal/src/lib.rs` +- any direct imports of `prometeu_hal::tile_bank::*` in runtime crates + +### Step 2 - Rename the asset-bank contract + +**What:** +Migrate the asset-bank enum and related asset-facing terminology from `TILES` to `GLYPH`. + +**How:** +Rename `BankType::TILES` to `BankType::GLYPH`, update any JSON/serde expectations and validation paths, and rename asset-facing metadata helpers only where they describe the concrete bank artifact rather than the geometric tile model. Preserve behavior and fail-fast semantics unchanged. + +**File(s):** +- `crates/console/prometeu-hal/src/asset.rs` +- `crates/console/prometeu-hal/src/cartridge_loader.rs` +- `crates/console/prometeu-system/src/virtual_machine_runtime/dispatch.rs` +- `crates/console/prometeu-system/src/virtual_machine_runtime/tick.rs` +- `crates/console/prometeu-system/src/virtual_machine_runtime/tests.rs` + +### Step 3 - Rename memory pools and concrete-bank runtime APIs + +**What:** +Rename bank-specific pool interfaces and storage paths that refer to the concrete graphical bank. + +**How:** +Rename `TileBankPoolAccess`, `TileBankPoolInstaller`, `tile_bank_slot`, `install_tile_bank`, `tile_bank_pool`, and related fields/traits/vars to `Glyph*` equivalents. Keep semantics and slot behavior unchanged. + +**File(s):** +- `crates/console/prometeu-drivers/src/memory_banks.rs` +- `crates/console/prometeu-drivers/src/hardware.rs` +- `crates/console/prometeu-drivers/src/gfx.rs` +- `crates/console/prometeu-drivers/src/asset.rs` + +### Step 4 - Rename concrete-bank decode/load path and tests + +**What:** +Update the asset manager and concrete-bank decode path to the new artifact name. + +**How:** +Rename functions such as `decode_tile_bank_*`, `perform_load_tile_bank`, and related test helpers/messages to `GlyphBank` naming. Keep payload interpretation, palette handling, and runtime materialization identical to current behavior. Do not rename `TileSize`. + +**File(s):** +- `crates/console/prometeu-drivers/src/asset.rs` +- affected tests in `crates/console/prometeu-drivers/src/asset.rs` +- any helper or stress/test utility strings such as `missing_tile_bank` + +### Step 5 - Apply renderer and hardware editorial cleanup + +**What:** +Rename only the references that describe the concrete bank artifact inside renderer and hardware documentation/comments. + +**How:** +Update comments, docs, field names, and user-facing/runtime-facing strings so that references to the bank artifact become `GlyphBank`/`glyph bank`, while preserving `tile` terminology for layers, maps, and geometric concepts. Review `gfx.rs` carefully because it contains both domains. + +**File(s):** +- `crates/console/prometeu-drivers/src/gfx.rs` +- `crates/console/prometeu-drivers/src/hardware.rs` +- any crate-level docs/comments on the bank artifact path + +### Step 6 - Rewrite maintained lessons and discussion docs by meaning + +**What:** +Migrate maintained lessons and relevant discussion text to the new canonical artifact name. + +**How:** +Update published lessons and maintained discussion artifacts so that references to the concrete graphical bank become `GlyphBank`, but references to tile layers, tilemaps, grid semantics, or tile geometry remain `tile`. Use manual review, not blanket replacement. + +**File(s):** +- `discussion/lessons/DSC-0016-tilemap-empty-cell-semantics/LSN-0022-tilemap-empty-cell-convergence.md` +- `discussion/lessons/DSC-0001-runtime-learn-legacy-import/LSN-0011-mental-model-gfx.md` +- `discussion/lessons/DSC-0001-runtime-learn-legacy-import/LSN-0009-mental-model-asset-management.md` +- any maintained agenda/decision/plan artifacts still intentionally retained and referencing the concrete bank artifact + +## Criterios de Aceite + +- The canonical concrete bank type/module name in runtime code is `GlyphBank`. +- The canonical asset-bank enum variant is `BankType::GLYPH`. +- Pool interfaces and concrete-bank runtime helpers use `Glyph*` naming consistently. +- `TileLayer`, `TileMap`, `ScrollableTileLayer`, `HudTileLayer`, and `TileSize` remain unchanged. +- No behavior, payload format, or renderer semantics change as part of this migration. +- Tests, helper names, and runtime-facing strings do not keep active mixed `TileBank`/`GlyphBank` naming for the same artifact. +- Maintained lessons and docs use `GlyphBank` for the concrete bank artifact while preserving `tile` where it refers to layer/map/geometric concepts. + +## Tests / Validacao + +### Unit Tests + +- Update and run unit tests that directly construct or decode the concrete graphical bank path. +- Confirm renamed bank/pool/helper symbols compile without compatibility shims. + +### Integration Tests + +- Run `prometeu-hal`, `prometeu-drivers`, and `prometeu-system` test targets affected by the rename. +- Verify asset loading still succeeds for the renamed `BankType::GLYPH` path. + +### Manual Verification + +- Review representative docs and lessons to confirm `GlyphBank` only replaces the concrete bank artifact meaning. +- Review `gfx.rs` and `tile_layer.rs` boundaries to confirm tile-domain structures were not accidentally renamed. +- Search the repository for residual `TileBank` references and classify any remaining occurrence as either acceptable historical residue outside scope or a migration miss. + +## Riscos + +- The repository uses `tile` in two different domains, so blind search-and-replace is likely to over-rename excluded surfaces. +- Renaming the enum variant from `TILES` to `GLYPH` touches serialization contracts and can break test fixtures or external packer assumptions if not coordinated. +- Moving `tile_bank.rs` to `glyph_bank.rs` may cause broad import churn across crates and tests. +- Historical lessons can easily drift into editorial inconsistency if the rewrite is done mechanically instead of semantically.