pr 00.1 optimize imports and created hinfra

This commit is contained in:
bQUARKz 2026-02-03 19:44:40 +00:00
parent 567ab21709
commit 60384bf720
Signed by: bquarkz
SSH Key Fingerprint: SHA256:Z7dgqoglWwoK6j6u4QC87OveEq74WOhFN+gitsxtkf8
40 changed files with 42 additions and 806 deletions

8
Cargo.lock generated
View File

@ -2241,6 +2241,14 @@ dependencies = [
"url",
]
[[package]]
name = "prometeu-hinfra"
version = "0.1.0"
dependencies = [
"serde",
"serde_json",
]
[[package]]
name = "prometeu-lsp"
version = "0.1.0"

View File

@ -8,6 +8,7 @@ members = [
"crates/prometeu-compiler",
"crates/prometeu-analysis",
"crates/prometeu-lsp",
"crates/prometeu-hinfra"
]
resolver = "2"

View File

@ -3,7 +3,7 @@ mod log_source;
mod log_event;
mod log_service;
pub use log_level::LogLevel;
pub use log_source::LogSource;
pub use log_event::LogEvent;
pub use log_level::LogLevel;
pub use log_service::LogService;
pub use log_source::LogSource;

View File

@ -1,4 +1,3 @@
use crate::abi::SourceSpan;
use crate::opcode::OpCode;
use serde::{Deserialize, Serialize};

View File

@ -1,9 +1,9 @@
use crate::building::output::{CompiledModule};
use crate::building::output::CompiledModule;
use crate::building::plan::BuildStep;
use prometeu_bytecode::opcode::OpCode;
use prometeu_bytecode::{ConstantPoolEntry, DebugInfo};
use prometeu_core::virtual_machine::{ProgramImage, Value};
use std::collections::{HashMap};
use std::collections::HashMap;
#[derive(Debug, PartialEq, Eq, Clone)]
pub enum LinkError {
@ -276,14 +276,14 @@ impl Linker {
#[cfg(test)]
mod tests {
use std::collections::BTreeMap;
use super::*;
use crate::building::output::{ExportKey, ExportMetadata, ImportKey, ImportMetadata};
use crate::semantics::export_surface::ExportSurfaceKind;
use crate::building::plan::BuildTarget;
use crate::deps::resolver::ProjectId;
use crate::semantics::export_surface::ExportSurfaceKind;
use prometeu_bytecode::opcode::OpCode;
use prometeu_bytecode::FunctionMeta;
use std::collections::BTreeMap;
#[test]
fn test_link_root_and_lib() {

View File

@ -12,8 +12,8 @@ use crate::frontends::pbs::resolver::{ModuleProvider, Resolver};
use crate::frontends::pbs::symbols::{ModuleSymbols, Namespace, Symbol, SymbolKind, Visibility};
use crate::frontends::pbs::typecheck::TypeChecker;
use crate::frontends::pbs::types::PbsType;
use crate::semantics::export_surface::ExportSurfaceKind;
use crate::lowering::core_to_vm;
use crate::semantics::export_surface::ExportSurfaceKind;
use prometeu_bytecode::{ConstantPoolEntry, DebugInfo, FunctionMeta};
use serde::{Deserialize, Serialize};
use std::collections::{BTreeMap, HashMap};

View File

@ -1,5 +1,5 @@
use serde::{Serialize, Deserialize};
use crate::common::spans::Span;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
#[derive(Debug, Clone)]

View File

@ -5,9 +5,9 @@
use crate::backend;
use crate::common::config::ProjectConfig;
use crate::common::symbols::{DebugSymbol, RawSymbol, SymbolsFile, ProjectSymbols};
use crate::common::files::FileManager;
use crate::common::spans::Span;
use crate::common::symbols::{DebugSymbol, ProjectSymbols, RawSymbol, SymbolsFile};
use anyhow::Result;
use prometeu_bytecode::BytecodeModule;
use std::path::Path;

View File

@ -1,5 +1,5 @@
use super::ids::ValueId;
use super::instr::{InstrKind};
use super::instr::InstrKind;
use super::program::Program;
use super::terminator::Terminator;
use std::collections::{HashMap, VecDeque};

View File

@ -1,12 +1,12 @@
use std::collections::{BTreeMap, HashMap};
use std::path::PathBuf;
use tempfile::tempdir;
use prometeu_compiler::building::output::CompiledModule;
use prometeu_compiler::building::output::{compile_project, CompileError, ExportKey, ExportMetadata};
use prometeu_compiler::building::plan::{BuildStep, BuildTarget};
use prometeu_compiler::common::files::FileManager;
use prometeu_compiler::deps::resolver::ProjectId;
use prometeu_compiler::semantics::export_surface::ExportSurfaceKind;
use prometeu_compiler::building::output::CompiledModule;
use std::collections::{BTreeMap, HashMap};
use std::path::PathBuf;
use tempfile::tempdir;
use std::fs;

View File

@ -1,6 +1,6 @@
use prometeu_compiler::compiler::compile;
use prometeu_core::hardware::{AssetManager, Audio, Gfx, HardwareBridge, MemoryBanks, Pad, Touch};
use prometeu_core::virtual_machine::{HostReturn, LogicalFrameEndingReason, NativeInterface, Value, VirtualMachine, VmFault, HostContext};
use prometeu_core::virtual_machine::{HostContext, HostReturn, LogicalFrameEndingReason, NativeInterface, Value, VirtualMachine, VmFault};
use std::path::PathBuf;
use std::sync::Arc;

View File

@ -101,7 +101,6 @@ pub enum DebugEvent {
#[cfg(test)]
mod tests {
use super::*;
use crate::virtual_machine::Value;
#[test]

View File

@ -24,9 +24,9 @@ mod prometeu_hub;
// Facade/reexports for ABI modules (temporary during PR-00.x)
pub use prometeu_abi as abi;
pub use prometeu_abi::model;
pub use prometeu_abi::log;
pub use prometeu_abi::telemetry;
pub use prometeu_abi::debugger_protocol;
pub use prometeu_abi::log;
pub use prometeu_abi::model;
pub use prometeu_abi::telemetry;
pub use hardware::hardware::Hardware;

View File

@ -1,13 +0,0 @@
use crate::log::LogLevel;
use crate::log::LogSource;
#[derive(Debug, Clone)]
pub struct LogEvent {
pub seq: u64,
pub ts_ms: u64,
pub frame: u64,
pub level: LogLevel,
pub source: LogSource,
pub tag: u16,
pub msg: String,
}

View File

@ -1,8 +0,0 @@
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum LogLevel {
Trace,
Debug,
Info,
Warn,
Error,
}

View File

@ -1,93 +0,0 @@
use crate::log::{LogEvent, LogLevel, LogSource};
use std::collections::VecDeque;
pub struct LogService {
events: VecDeque<LogEvent>,
capacity: usize,
next_seq: u64,
}
impl LogService {
pub fn new(capacity: usize) -> Self {
Self {
events: VecDeque::with_capacity(capacity),
capacity,
next_seq: 0,
}
}
pub fn log(&mut self, ts_ms: u64, frame: u64, level: LogLevel, source: LogSource, tag: u16, msg: String) {
if self.events.len() >= self.capacity {
self.events.pop_front();
}
self.events.push_back(LogEvent {
seq: self.next_seq,
ts_ms,
frame,
level,
source,
tag,
msg,
});
self.next_seq += 1;
}
pub fn get_recent(&self, n: usize) -> Vec<LogEvent> {
self.events.iter().rev().take(n).cloned().collect::<Vec<_>>().into_iter().rev().collect()
}
pub fn get_after(&self, seq: u64) -> Vec<LogEvent> {
self.events.iter().filter(|e| e.seq > seq).cloned().collect()
}
pub fn last_seq(&self) -> Option<u64> {
self.events.back().map(|e| e.seq)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_ring_buffer_capacity() {
let mut service = LogService::new(3);
service.log(100, 1, LogLevel::Info, LogSource::Pos, 0, "Log 1".to_string());
service.log(110, 1, LogLevel::Info, LogSource::Pos, 0, "Log 2".to_string());
service.log(120, 1, LogLevel::Info, LogSource::Pos, 0, "Log 3".to_string());
assert_eq!(service.events.len(), 3);
assert_eq!(service.events[0].msg, "Log 1");
service.log(130, 1, LogLevel::Info, LogSource::Pos, 0, "Log 4".to_string());
assert_eq!(service.events.len(), 3);
assert_eq!(service.events[0].msg, "Log 2");
assert_eq!(service.events[2].msg, "Log 4");
}
#[test]
fn test_get_recent() {
let mut service = LogService::new(10);
for i in 0..5 {
service.log(i as u64, 1, LogLevel::Info, LogSource::Pos, 0, format!("Log {}", i));
}
let recent = service.get_recent(2);
assert_eq!(recent.len(), 2);
assert_eq!(recent[0].msg, "Log 3");
assert_eq!(recent[1].msg, "Log 4");
}
#[test]
fn test_get_after() {
let mut service = LogService::new(10);
for i in 0..5 {
service.log(i as u64, 1, LogLevel::Info, LogSource::Pos, 0, format!("Log {}", i));
}
let after = service.get_after(2); // seqs are 0, 1, 2, 3, 4. Should return 3 and 4.
assert_eq!(after.len(), 2);
assert_eq!(after[0].msg, "Log 3");
assert_eq!(after[1].msg, "Log 4");
}
}

View File

@ -1,8 +0,0 @@
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum LogSource {
Pos,
Hub,
Vm,
Fs,
App { app_id: u32 },
}

View File

@ -1,9 +0,0 @@
mod log_level;
mod log_source;
mod log_event;
mod log_service;
pub use log_event::LogEvent;
pub use log_level::LogLevel;
pub use log_service::LogService;
pub use log_source::LogSource;

View File

@ -1,80 +0,0 @@
use serde::{Deserialize, Serialize};
pub type HandleId = u32;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Deserialize, Serialize)]
#[allow(non_camel_case_types)]
pub enum BankType {
TILES,
SOUNDS,
// TILEMAPS,
// BLOBS,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct AssetEntry {
pub asset_id: u32,
pub asset_name: String,
pub bank_type: BankType,
pub offset: u64,
pub size: u64,
pub decoded_size: u64,
pub codec: String, // e.g., "RAW"
pub metadata: serde_json::Value,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct PreloadEntry {
pub asset_name: String,
pub slot: usize,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum LoadStatus {
PENDING,
LOADING,
READY,
COMMITTED,
CANCELED,
ERROR,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct BankStats {
pub total_bytes: usize,
pub used_bytes: usize,
pub free_bytes: usize,
pub inflight_bytes: usize,
pub slot_count: usize,
pub slots_occupied: usize,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SlotStats {
pub asset_id: Option<u32>,
pub asset_name: Option<String>,
pub generation: u32,
pub resident_bytes: usize,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct SlotRef {
pub asset_type: BankType,
pub index: usize,
}
impl SlotRef {
pub fn gfx(index: usize) -> Self {
Self {
asset_type: BankType::TILES,
index,
}
}
pub fn audio(index: usize) -> Self {
Self {
asset_type: BankType::SOUNDS,
index,
}
}
}

View File

@ -1,40 +0,0 @@
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u32)]
pub enum ButtonId {
Up = 0,
Down = 1,
Left = 2,
Right = 3,
A = 4,
B = 5,
X = 6,
Y = 7,
L = 8,
R = 9,
Start = 10,
Select = 11,
}
#[derive(Default, Clone, Copy, Debug)]
pub struct Button {
pub pressed: bool,
pub released: bool,
pub down: bool,
pub hold_frames: u32,
}
impl Button {
pub fn begin_frame(&mut self, is_down_now: bool) {
let was_down = self.down;
self.down = is_down_now.clone();
self.pressed = !was_down && self.down;
self.released = was_down && !self.down;
if self.down {
self.hold_frames = self.hold_frames.saturating_add(1);
} else {
self.hold_frames = 0;
}
}
}

View File

@ -1,77 +0,0 @@
use crate::model::asset::{AssetEntry, PreloadEntry};
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)]
pub enum AppMode {
Game,
System,
}
#[derive(Debug, Clone)]
pub struct Cartridge {
pub app_id: u32,
pub title: String,
pub app_version: String,
pub app_mode: AppMode,
pub entrypoint: String,
pub program: Vec<u8>,
pub assets: Vec<u8>,
pub asset_table: Vec<AssetEntry>,
pub preload: Vec<PreloadEntry>,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct CartridgeDTO {
pub app_id: u32,
pub title: String,
pub app_version: String,
pub app_mode: AppMode,
pub entrypoint: String,
pub program: Vec<u8>,
pub assets: Vec<u8>,
#[serde(default)]
pub asset_table: Vec<AssetEntry>,
#[serde(default)]
pub preload: Vec<PreloadEntry>,
}
impl From<CartridgeDTO> for Cartridge {
fn from(dto: CartridgeDTO) -> Self {
Self {
app_id: dto.app_id,
title: dto.title,
app_version: dto.app_version,
app_mode: dto.app_mode,
entrypoint: dto.entrypoint,
program: dto.program,
assets: dto.assets,
asset_table: dto.asset_table,
preload: dto.preload,
}
}
}
#[derive(Debug)]
pub enum CartridgeError {
NotFound,
InvalidFormat,
InvalidManifest,
UnsupportedVersion,
MissingProgram,
IoError,
}
#[derive(Deserialize)]
pub struct CartridgeManifest {
pub magic: String,
pub cartridge_version: u32,
pub app_id: u32,
pub title: String,
pub app_version: String,
pub app_mode: AppMode,
pub entrypoint: String,
#[serde(default)]
pub asset_table: Vec<AssetEntry>,
#[serde(default)]
pub preload: Vec<PreloadEntry>,
}

View File

@ -1,80 +0,0 @@
use crate::model::cartridge::{Cartridge, CartridgeDTO, CartridgeError, CartridgeManifest};
use std::fs;
use std::path::Path;
pub struct CartridgeLoader;
impl CartridgeLoader {
pub fn load(path: impl AsRef<Path>) -> Result<Cartridge, CartridgeError> {
let path = path.as_ref();
if !path.exists() {
return Err(CartridgeError::NotFound);
}
if path.is_dir() {
DirectoryCartridgeLoader::load(path)
} else if path.extension().is_some_and(|ext| ext == "pmc") {
PackedCartridgeLoader::load(path)
} else {
Err(CartridgeError::InvalidFormat)
}
}
}
pub struct DirectoryCartridgeLoader;
impl DirectoryCartridgeLoader {
pub fn load(path: &Path) -> Result<Cartridge, CartridgeError> {
let manifest_path = path.join("manifest.json");
if !manifest_path.exists() {
return Err(CartridgeError::InvalidManifest);
}
let manifest_content = fs::read_to_string(manifest_path).map_err(|_| CartridgeError::IoError)?;
let manifest: CartridgeManifest = serde_json::from_str(&manifest_content).map_err(|_| CartridgeError::InvalidManifest)?;
// Additional validation as per requirements
if manifest.magic != "PMTU" {
return Err(CartridgeError::InvalidManifest);
}
if manifest.cartridge_version != 1 {
return Err(CartridgeError::UnsupportedVersion);
}
let program_path = path.join("program.pbc");
if !program_path.exists() {
return Err(CartridgeError::MissingProgram);
}
let program = fs::read(program_path).map_err(|_| CartridgeError::IoError)?;
let assets_pa_path = path.join("assets.pa");
let assets = if assets_pa_path.exists() {
fs::read(assets_pa_path).map_err(|_| CartridgeError::IoError)?
} else {
Vec::new()
};
let dto = CartridgeDTO {
app_id: manifest.app_id,
title: manifest.title,
app_version: manifest.app_version,
app_mode: manifest.app_mode,
entrypoint: manifest.entrypoint,
program,
assets,
asset_table: manifest.asset_table,
preload: manifest.preload,
};
Ok(Cartridge::from(dto))
}
}
pub struct PackedCartridgeLoader;
impl PackedCartridgeLoader {
pub fn load(_path: &Path) -> Result<Cartridge, CartridgeError> {
Err(CartridgeError::InvalidFormat)
}
}

View File

@ -1,76 +0,0 @@
/// Represents a 16-bit color in the RGB565 format.
///
/// The RGB565 format is a common high-color representation for embedded systems:
/// - **Red**: 5 bits (0..31)
/// - **Green**: 6 bits (0..63)
/// - **Blue**: 5 bits (0..31)
///
/// Prometeu does not have a hardware alpha channel. Transparency is achieved
/// by using a specific color key (Magenta / 0xF81F) which the GFX engine
/// skips during rendering.
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub struct Color(pub u16);
impl Color {
pub const BLACK: Self = Self::rgb(0, 0, 0); // 0x0000
pub const WHITE: Self = Self::rgb(255, 255, 255); // 0xFFFF
pub const RED: Self = Self::rgb(255, 0, 0); // 0xF800
pub const GREEN: Self = Self::rgb(0, 255, 0); // 0x07E0
pub const BLUE: Self = Self::rgb(0, 0, 255); // 0x001F
pub const YELLOW: Self = Self::rgb(255, 255, 0); // 0xFFE0
pub const ORANGE: Self = Self::rgb(255, 128, 0);
pub const INDIGO: Self = Self::rgb(75, 0, 130);
pub const GRAY: Self = Self::rgb(128, 128, 128);
pub const CYAN: Self = Self::rgb(0, 255, 255); // 0x07FF
pub const MAGENTA: Self = Self::rgb(255, 0, 255); // 0xF81F
pub const COLOR_KEY: Self = Self::MAGENTA;
pub const TRANSPARENT: Self = Self::MAGENTA;
/// Extracts channels in the native RGB565 range:
/// R: 0..31, G: 0..63, B: 0..31
#[inline(always)]
pub const fn unpack_to_native(px: u16) -> (u8, u8, u8) {
let r = ((px >> 11) & 0x1F) as u8;
let g = ((px >> 5) & 0x3F) as u8;
let b = (px & 0x1F) as u8;
(r, g, b)
}
/// Packs channels from the native RGB565 range into a pixel:
/// R: 0..31, G: 0..63, B: 0..31
#[inline(always)]
pub const fn pack_from_native(r: u8, g: u8, b: u8) -> u16 {
((r as u16 & 0x1F) << 11) | ((g as u16 & 0x3F) << 5) | (b as u16 & 0x1F)
}
/// Creates an RGB565 color from 8-bit components (0..255).
pub const fn rgb(r: u8, g: u8, b: u8) -> Self {
let r5 = (r as u16 >> 3) & 0x1F;
let g6 = (g as u16 >> 2) & 0x3F;
let b5 = (b as u16 >> 3) & 0x1F;
Self((r5 << 11) | (g6 << 5) | b5)
}
pub const fn gray_scale(c: u8) -> Self {
Self::rgb(c, c, c)
}
pub const fn from_raw(raw: u16) -> Self {
Self(raw)
}
pub const fn raw(self) -> u16 {
self.0
}
pub const fn hex(self) -> i32 {
let (r5, g6, b5) = Self::unpack_to_native(self.0);
let r8 = ((r5 as u32) << 3) | ((r5 as u32) >> 2);
let g8 = ((g6 as u32) << 2) | ((g6 as u32) >> 4);
let b8 = ((b5 as u32) << 3) | ((b5 as u32) >> 2);
let hex = r8 << 16 | g8 << 8 | b8;
hex as i32
}
}

View File

@ -1,25 +0,0 @@
mod asset;
mod color;
mod button;
mod tile;
mod tile_layer;
mod tile_bank;
mod sound_bank;
mod sprite;
mod sample;
mod cartridge;
mod cartridge_loader;
mod window;
pub use asset::{AssetEntry, BankStats, BankType, HandleId, LoadStatus, PreloadEntry, SlotRef, SlotStats};
pub use button::{Button, ButtonId};
pub use cartridge::{AppMode, Cartridge, CartridgeDTO, CartridgeError};
pub use cartridge_loader::{CartridgeLoader, DirectoryCartridgeLoader, PackedCartridgeLoader};
pub use color::Color;
pub use sample::Sample;
pub use sound_bank::SoundBank;
pub use sprite::Sprite;
pub use tile::Tile;
pub use tile_bank::{TileBank, TileSize};
pub use tile_layer::{HudTileLayer, ScrollableTileLayer, TileMap};
pub use window::{Rect, Window, WindowId};

View File

@ -1,27 +0,0 @@
pub struct Sample {
pub sample_rate: u32,
pub data: Vec<i16>,
pub loop_start: Option<u32>,
pub loop_end: Option<u32>,
}
impl Sample {
pub fn new(sample_rate: u32, data: Vec<i16>) -> Self {
Self {
sample_rate,
data,
loop_start: None,
loop_end: None,
}
}
pub fn with_loop(mut self, start: u32, end: u32) -> Self {
self.loop_start = Some(start);
self.loop_end = Some(end);
self
}
pub fn frames_len(&self) -> usize {
self.data.len()
}
}

View File

@ -1,16 +0,0 @@
use crate::model::Sample;
use std::sync::Arc;
/// A container for audio assets.
///
/// A SoundBank stores multiple audio samples that can be played by the
/// audio subsystem.
pub struct SoundBank {
pub samples: Vec<Arc<Sample>>,
}
impl SoundBank {
pub fn new(samples: Vec<Arc<Sample>>) -> Self {
Self { samples }
}
}

View File

@ -1,13 +0,0 @@
use crate::model::Tile;
#[derive(Clone, Copy, Debug, Default)]
pub struct Sprite {
pub tile: Tile,
pub x: i32,
pub y: i32,
pub bank_id: u8,
pub active: bool,
pub flip_x: bool,
pub flip_y: bool,
pub priority: u8,
}

View File

@ -1,7 +0,0 @@
#[derive(Clone, Copy, Debug, Default)]
pub struct Tile {
pub id: u16,
pub flip_x: bool,
pub flip_y: bool,
pub palette_id: u8,
}

View File

@ -1,75 +0,0 @@
use crate::model::Color;
/// Standard sizes for square tiles.
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum TileSize {
/// 8x8 pixels.
Size8 = 8,
/// 16x16 pixels.
Size16 = 16,
/// 32x32 pixels.
Size32 = 32,
}
/// A container for graphical assets.
///
/// A TileBank stores both the raw pixel data (as palette indices) and the
/// color palettes themselves. This encapsulates all the information needed
/// to render a set of tiles.
pub struct TileBank {
/// Dimension of each individual tile in the bank.
pub tile_size: TileSize,
/// Width of the full bank sheet in pixels.
pub width: usize,
/// Height of the full bank sheet in pixels.
pub height: usize,
/// Pixel data stored as 4-bit indices (packed into 8-bit values).
/// Index 0 is always reserved for transparency.
pub pixel_indices: Vec<u8>,
/// Table of 64 palettes, each containing 16 RGB565 colors, total of 1024 colors for a bank.
pub palettes: [[Color; 16]; 64],
}
impl TileBank {
/// Creates an empty tile 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; 16]; 64],
}
}
/// Resolves a global tile ID and local pixel coordinates to a palette index.
/// tile_id: the tile index in the bank
/// local_x, local_y: the pixel position inside the tile (0 to tile_size-1)
pub fn get_pixel_index(&self, tile_id: u16, local_x: usize, local_y: usize) -> u8 {
let size = self.tile_size as usize;
let tiles_per_row = self.width / size;
let tile_x = (tile_id as usize % tiles_per_row) * size;
let tile_y = (tile_id as usize / tiles_per_row) * size;
let pixel_x = tile_x + local_x;
let pixel_y = tile_y + local_y;
if pixel_x < self.width && pixel_y < self.height {
self.pixel_indices[pixel_y * self.width + pixel_x]
} else {
0 // Default to transparent if out of bounds
}
}
/// Maps a 4-bit index to a real RGB565 Color using the specified palette.
pub fn resolve_color(&self, palette_id: u8, pixel_index: u8) -> Color {
// Hardware Rule: Index 0 is always transparent.
// We use Magenta as the 'transparent' signal color during composition.
if pixel_index == 0 {
return Color::COLOR_KEY;
}
self.palettes[palette_id as usize][pixel_index as usize]
}
}

View File

@ -1,109 +0,0 @@
use crate::model::tile_bank::TileSize;
use crate::model::Tile;
use crate::model::TileSize::Size8;
pub struct TileMap {
pub width: usize,
pub height: usize,
pub tiles: Vec<Tile>,
}
impl TileMap {
fn create(width: usize, height: usize) -> Self {
Self {
width,
height,
tiles: vec![Tile::default(); width * height],
}
}
pub fn set_tile(&mut self, x: usize, y: usize, tile: Tile) {
if x < self.width && y < self.height {
self.tiles[y * self.width + x] = tile;
}
}
}
pub struct TileLayer {
pub bank_id: u8,
pub tile_size: TileSize,
pub map: TileMap,
}
impl TileLayer {
fn create(width: usize, height: usize, tile_size: TileSize) -> Self {
Self {
bank_id: 0,
tile_size,
map: TileMap::create(width, height),
}
}
}
impl std::ops::Deref for TileLayer {
type Target = TileMap;
fn deref(&self) -> &Self::Target {
&self.map
}
}
impl std::ops::DerefMut for TileLayer {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.map
}
}
pub struct ScrollableTileLayer {
pub layer: TileLayer,
pub scroll_x: i32,
pub scroll_y: i32,
}
impl ScrollableTileLayer {
pub fn new(width: usize, height: usize, tile_size: TileSize) -> Self {
Self {
layer: TileLayer::create(width, height, tile_size),
scroll_x: 0,
scroll_y: 0,
}
}
}
impl std::ops::Deref for ScrollableTileLayer {
type Target = TileLayer;
fn deref(&self) -> &Self::Target {
&self.layer
}
}
impl std::ops::DerefMut for ScrollableTileLayer {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.layer
}
}
pub struct HudTileLayer {
pub layer: TileLayer,
}
impl HudTileLayer {
pub fn new(width: usize, height: usize) -> Self {
Self {
layer: TileLayer::create(width, height, Size8),
}
}
}
impl std::ops::Deref for HudTileLayer {
type Target = TileLayer;
fn deref(&self) -> &Self::Target {
&self.layer
}
}
impl std::ops::DerefMut for HudTileLayer {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.layer
}
}

View File

@ -1,21 +0,0 @@
use crate::model::Color;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Rect {
pub x: i32,
pub y: i32,
pub w: i32,
pub h: i32,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct WindowId(pub u32);
#[derive(Debug, Clone)]
pub struct Window {
pub id: WindowId,
pub viewport: Rect,
pub has_focus: bool,
pub title: String,
pub color: Color,
}

View File

@ -1,11 +1,11 @@
use crate::fs::{FsBackend, FsState, VirtualFS};
use crate::abi::syscalls::Syscall;
use crate::fs::{FsBackend, FsState, VirtualFS};
use crate::hardware::{HardwareBridge, InputSignals};
use crate::log::{LogLevel, LogService, LogSource};
use crate::model::{BankType, Cartridge, Color};
use crate::prometeu_os::NativeInterface;
use crate::telemetry::{CertificationConfig, Certifier, TelemetryFrame};
use crate::virtual_machine::{expect_bool, expect_int, HostReturn, SyscallId, Value, VirtualMachine, VmFault, HostContext};
use crate::virtual_machine::{expect_bool, expect_int, HostContext, HostReturn, SyscallId, Value, VirtualMachine, VmFault};
use std::collections::HashMap;
use std::time::Instant;

View File

@ -10,9 +10,9 @@ pub mod verifier;
pub use host_context::{HostContext, HostContextProvider};
pub use program::ProgramImage;
pub use prometeu_abi::virtual_machine::Value;
pub use prometeu_bytecode::abi::TrapInfo;
pub use prometeu_bytecode::opcode::OpCode;
pub use prometeu_abi::virtual_machine::Value;
pub use verifier::VerifierError;
pub use virtual_machine::{BudgetReport, LogicalFrameEndingReason, VirtualMachine};

View File

@ -107,8 +107,6 @@ impl Value {
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_value_equality() {
assert_eq!(Value::Int32(10), Value::Int32(10));

View File

@ -1,8 +1,8 @@
use crate::abi::syscalls::Syscall;
use crate::virtual_machine::bytecode::decoder::{decode_at, DecodeError};
use prometeu_bytecode::opcode::OpCode;
use prometeu_bytecode::FunctionMeta;
use std::collections::{HashMap, HashSet, VecDeque};
use crate::abi::syscalls::Syscall;
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum VerifierError {

View File

@ -1,7 +1,7 @@
use crate::virtual_machine::call_frame::CallFrame;
use crate::virtual_machine::scope_frame::ScopeFrame;
use crate::virtual_machine::Value;
use crate::virtual_machine::{NativeInterface, ProgramImage, VmInitError, HostContext};
use crate::virtual_machine::{HostContext, NativeInterface, ProgramImage, VmInitError};
use prometeu_bytecode::abi::{TrapInfo, TRAP_BAD_RET_SLOTS, TRAP_DIV_ZERO, TRAP_INVALID_FUNC, TRAP_OOB, TRAP_TYPE};
use prometeu_bytecode::opcode::OpCode;

View File

@ -1,8 +1,7 @@
use prometeu_core::hardware::HardwareBridge;
use prometeu_core::virtual_machine::HostReturn;
use prometeu_core::virtual_machine::NativeInterface;
use prometeu_core::virtual_machine::Value;
use prometeu_core::virtual_machine::{LogicalFrameEndingReason, VirtualMachine, HostContext};
use prometeu_core::virtual_machine::{HostContext, LogicalFrameEndingReason, VirtualMachine};
use prometeu_core::Hardware;
use std::fs;
use std::path::Path;

View File

@ -0,0 +1,9 @@
[package]
name = "prometeu-hinfra"
version = "0.1.0"
edition = "2024"
license.workspace = true
[dependencies]
serde = { version = "1.0.228", features = ["derive"] }
serde_json = "1.0.149"

View File