This commit is contained in:
bQUARKz 2026-02-04 01:59:28 +00:00
parent d6bbef06a5
commit eb3156dd8c
Signed by: bquarkz
SSH Key Fingerprint: SHA256:Z7dgqoglWwoK6j6u4QC87OveEq74WOhFN+gitsxtkf8
21 changed files with 86 additions and 181 deletions

14
Cargo.lock generated
View File

@ -1920,6 +1920,7 @@ dependencies = [
"prometeu-abi",
"prometeu-bytecode",
"prometeu-hardware-contract",
"prometeu-kernel",
"prometeu-vm",
"serde",
"serde_json",
@ -1936,6 +1937,19 @@ dependencies = [
"serde_json",
]
[[package]]
name = "prometeu-kernel"
version = "0.1.0"
dependencies = [
"prometeu-abi",
"prometeu-bytecode",
"prometeu-core",
"prometeu-hardware-contract",
"prometeu-vm",
"serde",
"serde_json",
]
[[package]]
name = "prometeu-lsp"
version = "0.1.0"

View File

@ -2,6 +2,7 @@
members = [
"crates/prometeu-abi",
"crates/prometeu-vm",
"crates/prometeu-kernel",
"crates/prometeu-core",
"crates/prometeu-runtime-desktop",
"crates/prometeu",

View File

@ -8,6 +8,7 @@ license.workspace = true
serde = { version = "1.0.228", features = ["derive"] }
serde_json = "1.0.149"
prometeu-vm = { path = "../prometeu-vm" }
prometeu-kernel = { path = "../prometeu-kernel" }
prometeu-bytecode = { path = "../prometeu-bytecode" }
prometeu-abi = { path = "../prometeu-abi" }
prometeu-hardware-contract = { path = "../prometeu-hardware-contract" }

View File

@ -4,6 +4,7 @@ use std::collections::HashMap;
use std::sync::{Arc, Mutex, RwLock};
use std::thread;
use std::time::Instant;
use prometeu_hardware_contract::AssetBridge;
/// Resident metadata for a decoded/materialized asset inside a BankPolicy.
#[derive(Debug)]
@ -93,19 +94,6 @@ impl<T> BankPolicy<T> {
}
}
pub trait AssetBridge {
fn initialize_for_cartridge(&self, assets: Vec<AssetEntry>, preload: Vec<PreloadEntry>, assets_data: Vec<u8>);
fn load(&self, asset_name: &str, slot: SlotRef) -> Result<HandleId, String>;
fn status(&self, handle: HandleId) -> LoadStatus;
fn commit(&self, handle: HandleId);
fn cancel(&self, handle: HandleId);
fn apply_commits(&self);
fn bank_info(&self, kind: BankType) -> BankStats;
fn slot_info(&self, slot: SlotRef) -> SlotStats;
fn find_slot_by_name(&self, asset_name: &str, kind: BankType) -> Option<u8>;
fn shutdown(&self);
}
pub struct AssetManager {
assets: Arc<RwLock<HashMap<u32, AssetEntry>>>,
name_to_id: Arc<RwLock<HashMap<String, u32>>>,
@ -136,7 +124,7 @@ struct LoadHandleInfo {
status: LoadStatus,
}
impl prometeu_hardware_contract::AssetBridge for AssetManager {
impl AssetBridge for AssetManager {
fn initialize_for_cartridge(&self, assets: Vec<AssetEntry>, preload: Vec<PreloadEntry>, assets_data: Vec<u8>) { self.initialize_for_cartridge(assets, preload, assets_data) }
fn load(&self, asset_name: &str, slot: SlotRef) -> Result<HandleId, String> { self.load(asset_name, slot) }
fn status(&self, handle: HandleId) -> LoadStatus { self.status(handle) }

View File

@ -1,6 +1,7 @@
use crate::hardware::memory_banks::SoundBankPoolAccess;
use crate::model::Sample;
use std::sync::Arc;
use prometeu_hardware_contract::AudioBridge;
/// Maximum number of simultaneous audio voices supported by the hardware.
pub const MAX_CHANNELS: usize = 16;
@ -101,17 +102,6 @@ pub enum AudioCommand {
/// - **16 Simultaneous Voices**: Independent volume, pan, and pitch.
/// - **Sample-based Synthesis**: Plays PCM data stored in SoundBanks.
/// - **Stereo Output**: 48kHz output target.
pub trait AudioBridge {
fn play(&mut self, bank_id: u8, sample_id: u16, voice_id: usize, volume: u8, pan: u8, pitch: f64, priority: u8, loop_mode: LoopMode) -> ();
fn play_sample(&mut self, sample: Arc<Sample>, voice_id: usize, volume: u8, pan: u8, pitch: f64, priority: u8, loop_mode: LoopMode) -> ();
fn stop(&mut self, voice_id: usize) -> ();
fn set_volume(&mut self, voice_id: usize, volume: u8) -> ();
fn set_pan(&mut self, voice_id: usize, pan: u8) -> ();
fn set_pitch(&mut self, voice_id: usize, pitch: f64) -> ();
fn is_playing(&self, voice_id: usize) -> bool;
fn clear_commands(&mut self) -> ();
}
pub struct Audio {
/// Local state of the hardware voices. This state is used for logic
/// (e.g., checking if a sound is still playing) and is synchronized with the Host.
@ -123,7 +113,7 @@ pub struct Audio {
pub sound_banks: Arc<dyn SoundBankPoolAccess>,
}
impl prometeu_hardware_contract::AudioBridge for Audio {
impl AudioBridge for Audio {
fn play(&mut self, bank_id: u8, sample_id: u16, voice_id: usize, volume: u8, pan: u8, pitch: f64, priority: u8, loop_mode: prometeu_hardware_contract::LoopMode) {
let lm = match loop_mode { prometeu_hardware_contract::LoopMode::Off => LoopMode::Off, prometeu_hardware_contract::LoopMode::On => LoopMode::On };
self.play(bank_id, sample_id, voice_id, volume, pan, pitch, priority, lm)

View File

@ -1,6 +1,7 @@
use crate::hardware::memory_banks::TileBankPoolAccess;
use crate::model::{Color, HudTileLayer, ScrollableTileLayer, Sprite, TileBank, TileMap, TileSize};
use std::sync::Arc;
use prometeu_hardware_contract::GfxBridge;
/// Blending modes inspired by classic 16-bit hardware.
/// Defines how source pixels are combined with existing pixels in the framebuffer.
@ -41,47 +42,6 @@ pub enum BlendMode {
/// 6. **Scene Fade**: Global brightness/color filter.
/// 7. **HUD Layer**: Fixed UI elements (always on top).
/// 8. **HUD Fade**: Independent fade for the UI.
pub trait GfxBridge {
fn size(&self) -> (usize, usize);
fn front_buffer(&self) -> &[u16];
fn clear(&mut self, color: Color) -> ();
fn fill_rect_blend(&mut self, x: i32, y: i32, w: i32, h: i32, color: Color, mode: BlendMode) -> ();
fn fill_rect(&mut self, x: i32, y: i32, w: i32, h: i32, color: Color) -> ();
fn draw_pixel(&mut self, x: i32, y: i32, color: Color) -> ();
fn draw_line(&mut self, x0: i32, y0: i32, x1: i32, y1: i32, color: Color) -> ();
fn draw_circle(&mut self, xc: i32, yc: i32, r: i32, color: Color) -> ();
fn draw_circle_points(&mut self, xc: i32, yc: i32, x: i32, y: i32, color: Color) -> ();
fn fill_circle(&mut self, xc: i32, yc: i32, r: i32, color: Color) -> ();
fn draw_circle_lines(&mut self, xc: i32, yc: i32, x: i32, y: i32, color: Color) -> ();
fn draw_disc(&mut self, x: i32, y: i32, r: i32, border_color: Color, fill_color: Color) -> ();
fn draw_rect(&mut self, x: i32, y: i32, w: i32, h: i32, color: Color) -> ();
fn draw_square(&mut self, x: i32, y: i32, w: i32, h: i32, border_color: Color, fill_color: Color) -> ();
fn draw_horizontal_line(&mut self, x0: i32, x1: i32, y: i32, color: Color) -> ();
fn draw_vertical_line(&mut self, x: i32, y0: i32, y1: i32, color: Color) -> ();
fn present(&mut self) -> ();
fn render_all(&mut self) -> ();
fn render_layer(&mut self, layer_idx: usize) -> ();
fn render_hud(&mut self) -> ();
fn draw_text(&mut self, x: i32, y: i32, text: &str, color: Color) -> ();
fn draw_char(&mut self, x: i32, y: i32, c: char, color: Color) -> ();
fn layer(&self, index: usize) -> &ScrollableTileLayer;
fn layer_mut(&mut self, index: usize) -> &mut ScrollableTileLayer;
fn hud(&self) -> &HudTileLayer;
fn hud_mut(&mut self) -> &mut HudTileLayer;
fn sprite(&self, index: usize) -> &Sprite;
fn sprite_mut(&mut self, index: usize) -> &mut Sprite;
fn scene_fade_level(&self) -> u8;
fn set_scene_fade_level(&mut self, level: u8);
fn scene_fade_color(&self) -> Color;
fn set_scene_fade_color(&mut self, color: Color);
fn hud_fade_level(&self) -> u8;
fn set_hud_fade_level(&mut self, level: u8);
fn hud_fade_color(&self) -> Color;
fn set_hud_fade_color(&mut self, color: Color);
}
pub struct Gfx {
/// Width of the internal framebuffer in pixels.
w: usize,
@ -114,7 +74,7 @@ pub struct Gfx {
priority_buckets: [Vec<usize>; 5],
}
impl prometeu_hardware_contract::GfxBridge for Gfx {
impl GfxBridge for Gfx {
fn size(&self) -> (usize, usize) { self.size() }
fn front_buffer(&self) -> &[u16] { self.front_buffer() }
fn clear(&mut self, color: Color) { self.clear(color) }

View File

@ -1,26 +0,0 @@
#[derive(Default, Clone, Copy, Debug)]
pub struct InputSignals {
// PAD
pub up_signal: bool,
pub down_signal: bool,
pub left_signal: bool,
pub right_signal: bool,
pub a_signal: bool,
pub b_signal: bool,
pub x_signal: bool,
pub y_signal: bool,
pub l_signal: bool,
pub r_signal: bool,
pub start_signal: bool,
pub select_signal: bool,
// TOUCH
pub f_signal: bool,
pub x_pos: i32,
pub y_pos: i32,
}
impl InputSignals {
}

View File

@ -1,24 +1,7 @@
use prometeu_hardware_contract::PadBridge;
use crate::hardware::InputSignals;
use crate::model::Button;
pub trait PadBridge {
fn begin_frame(&mut self, signals: &InputSignals);
fn any(&self) -> bool;
fn up(&self) -> &Button;
fn down(&self) -> &Button;
fn left(&self) -> &Button;
fn right(&self) -> &Button;
fn a(&self) -> &Button;
fn b(&self) -> &Button;
fn x(&self) -> &Button;
fn y(&self) -> &Button;
fn l(&self) -> &Button;
fn r(&self) -> &Button;
fn start(&self) -> &Button;
fn select(&self) -> &Button;
}
#[derive(Default, Clone, Copy, Debug)]
pub struct Pad {
pub up: Button,
@ -37,7 +20,7 @@ pub struct Pad {
pub select: Button,
}
impl prometeu_hardware_contract::PadBridge for Pad {
impl PadBridge for Pad {
fn begin_frame(&mut self, signals: &InputSignals) { self.begin_frame(signals) }
fn any(&self) -> bool { self.any() }

View File

@ -1,13 +1,7 @@
use prometeu_hardware_contract::TouchBridge;
use crate::hardware::InputSignals;
use crate::model::Button;
pub trait TouchBridge {
fn begin_frame(&mut self, signals: &InputSignals);
fn f(&self) -> &Button;
fn x(&self) -> i32;
fn y(&self) -> i32;
}
#[derive(Default, Clone, Copy, Debug)]
pub struct Touch {
pub f: Button,
@ -15,7 +9,7 @@ pub struct Touch {
pub y: i32,
}
impl prometeu_hardware_contract::TouchBridge for Touch {
impl TouchBridge for Touch {
fn begin_frame(&mut self, signals: &InputSignals) { self.begin_frame(signals) }
fn f(&self) -> &Button { &self.f }
fn x(&self) -> i32 { self.x }

View File

@ -17,10 +17,18 @@
pub mod hardware;
pub mod firmware;
pub mod fs;
pub mod prometeu_os;
// pub mod fs;
// pub mod prometeu_os;
mod prometeu_hub;
pub mod fs {
pub use prometeu_kernel::fs::*;
}
pub mod prometeu_os {
pub use prometeu_kernel::*;
}
// Facade/reexports for ABI modules (temporary during PR-00.x)
pub use prometeu_abi as abi;
pub use prometeu_abi::debugger_protocol;

View File

@ -0,0 +1,16 @@
[package]
name = "prometeu-kernel"
version = "0.1.0"
edition = "2024"
license.workspace = true
[dependencies]
serde = { version = "1.0.228", features = ["derive"] }
serde_json = "1.0.149"
prometeu-vm = { path = "../prometeu-vm" }
prometeu-bytecode = { path = "../prometeu-bytecode" }
prometeu-abi = { path = "../prometeu-abi" }
prometeu-hardware-contract = { path = "../prometeu-hardware-contract" }
[dev-dependencies]
prometeu-core = { path = "../prometeu-core" }

View File

@ -1,3 +1,4 @@
pub mod fs;
mod prometeu_os;
pub use prometeu_os::PrometeuOS;

View File

@ -1,9 +1,9 @@
use crate::abi::syscalls::Syscall;
use prometeu_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::telemetry::{CertificationConfig, Certifier, TelemetryFrame};
use prometeu_hardware_contract::{HardwareBridge, InputSignals};
use prometeu_abi::log::{LogLevel, LogService, LogSource};
use prometeu_abi::model::{BankType, Cartridge, Color};
use prometeu_abi::telemetry::{CertificationConfig, Certifier, TelemetryFrame};
use std::collections::HashMap;
use std::time::Instant;
use prometeu_abi::virtual_machine::{Value, VmFault};
@ -51,7 +51,7 @@ pub struct PrometeuOS {
pub current_app_id: u32,
pub current_cartridge_title: String,
pub current_cartridge_app_version: String,
pub current_cartridge_app_mode: crate::model::AppMode,
pub current_cartridge_app_mode: prometeu_abi::model::AppMode,
pub current_entrypoint: String,
/// Rate-limiter to prevent apps from flooding the log buffer and killing performance.
pub logs_written_this_frame: HashMap<u32, u32>,
@ -101,7 +101,7 @@ impl PrometeuOS {
current_app_id: 0,
current_cartridge_title: String::new(),
current_cartridge_app_version: String::new(),
current_cartridge_app_mode: crate::model::AppMode::Game,
current_cartridge_app_mode: prometeu_abi::model::AppMode::Game,
current_entrypoint: String::new(),
logs_written_this_frame: HashMap::new(),
telemetry_current: TelemetryFrame::default(),
@ -375,7 +375,7 @@ impl PrometeuOS {
}
// Helper para syscalls
pub fn get_button<'a>(&self, id: u32, hw: &'a dyn HardwareBridge) -> Option<&'a crate::model::Button> {
pub fn get_button<'a>(&self, id: u32, hw: &'a dyn HardwareBridge) -> Option<&'a prometeu_abi::model::Button> {
let pad = hw.pad();
match id {
0 => Some(pad.up()),
@ -416,11 +416,10 @@ impl PrometeuOS {
#[cfg(test)]
mod tests {
use prometeu_abi::virtual_machine::Value;
use prometeu_hardware_contract::HostReturn;
use prometeu_hardware_contract::{HostReturn, InputSignals};
use super::*;
use crate::hardware::InputSignals;
use crate::model::{AppMode, Cartridge};
use crate::Hardware;
use prometeu_abi::model::{AppMode, Cartridge};
use prometeu_core::Hardware;
fn call_syscall(os: &mut PrometeuOS, id: u32, vm: &mut VirtualMachine, hw: &mut dyn HardwareBridge) -> Result<(), VmFault> {
let args_count = Syscall::from_u32(id).expect(&format!("Invalid syscall id: 0x{:08X}", id)).args_count();
@ -756,7 +755,7 @@ mod tests {
fn test_os_unknown_syscall_returns_trap() {
let mut os = PrometeuOS::new(None);
let mut vm = VirtualMachine::default();
let mut hw = crate::Hardware::new();
let mut hw = Hardware::new();
let mut ret = HostReturn::new(&mut vm.operand_stack);
let res = os.syscall(0xDEADBEEF, &[], &mut ret, &mut HostContext::new(Some(&mut hw)));
@ -959,11 +958,11 @@ impl NativeInterface for PrometeuOS {
let flip_y = expect_bool(args, 8)?;
let priority = expect_int(args, 9)? as u8;
let bank_id = hw.assets().find_slot_by_name(&asset_name, crate::model::BankType::TILES).unwrap_or(0);
let bank_id = hw.assets().find_slot_by_name(&asset_name, prometeu_abi::model::BankType::TILES).unwrap_or(0);
if index < 512 {
*hw.gfx_mut().sprite_mut(index) = crate::model::Sprite {
tile: crate::model::Tile { id: tile_id, flip_x: false, flip_y: false, palette_id },
*hw.gfx_mut().sprite_mut(index) = prometeu_abi::model::Sprite {
tile: prometeu_abi::model::Tile { id: tile_id, flip_x: false, flip_y: false, palette_id },
x,
y,
bank_id,
@ -1094,7 +1093,7 @@ impl NativeInterface for PrometeuOS {
_ => return Err(VmFault::Trap(prometeu_bytecode::abi::TRAP_TYPE, "Expected number for pitch".into())),
};
hw.audio_mut().play(0, sample_id as u16, voice_id, volume, pan, pitch, 0, crate::hardware::LoopMode::Off);
hw.audio_mut().play(0, sample_id as u16, voice_id, volume, pan, pitch, 0, prometeu_hardware_contract::LoopMode::Off);
ret.push_null();
Ok(())
}
@ -1117,11 +1116,11 @@ impl NativeInterface for PrometeuOS {
_ => return Err(VmFault::Trap(prometeu_bytecode::abi::TRAP_TYPE, "Expected number for pitch".into())),
};
let loop_mode = match expect_int(args, 6)? {
0 => crate::hardware::LoopMode::Off,
_ => crate::hardware::LoopMode::On,
0 => prometeu_hardware_contract::LoopMode::Off,
_ => prometeu_hardware_contract::LoopMode::On,
};
let bank_id = hw.assets().find_slot_by_name(&asset_name, crate::model::BankType::SOUNDS).unwrap_or(0);
let bank_id = hw.assets().find_slot_by_name(&asset_name, prometeu_abi::model::BankType::SOUNDS).unwrap_or(0);
hw.audio_mut().play(bank_id, sample_id, voice_id, volume, pan, pitch, 0, loop_mode);
ret.push_null();
@ -1253,11 +1252,11 @@ impl NativeInterface for PrometeuOS {
let slot_index = expect_int(args, 2)? as usize;
let asset_type = match asset_type_val {
0 => crate::model::BankType::TILES,
1 => crate::model::BankType::SOUNDS,
0 => prometeu_abi::model::BankType::TILES,
1 => prometeu_abi::model::BankType::SOUNDS,
_ => return Err(VmFault::Trap(prometeu_bytecode::abi::TRAP_TYPE, "Invalid asset type".to_string())),
};
let slot = crate::model::SlotRef { asset_type, index: slot_index };
let slot = prometeu_abi::model::SlotRef { asset_type, index: slot_index };
match hw.assets().load(&asset_id, slot) {
Ok(handle) => {
@ -1271,12 +1270,12 @@ impl NativeInterface for PrometeuOS {
let handle = expect_int(args, 0)? as u32;
let status = hw.assets().status(handle);
let status_val = match status {
crate::model::LoadStatus::PENDING => 0,
crate::model::LoadStatus::LOADING => 1,
crate::model::LoadStatus::READY => 2,
crate::model::LoadStatus::COMMITTED => 3,
crate::model::LoadStatus::CANCELED => 4,
crate::model::LoadStatus::ERROR => 5,
prometeu_abi::model::LoadStatus::PENDING => 0,
prometeu_abi::model::LoadStatus::LOADING => 1,
prometeu_abi::model::LoadStatus::READY => 2,
prometeu_abi::model::LoadStatus::COMMITTED => 3,
prometeu_abi::model::LoadStatus::CANCELED => 4,
prometeu_abi::model::LoadStatus::ERROR => 5,
};
ret.push_int(status_val);
Ok(())
@ -1296,8 +1295,8 @@ impl NativeInterface for PrometeuOS {
Syscall::BankInfo => {
let asset_type_val = expect_int(args, 0)? as u32;
let asset_type = match asset_type_val {
0 => crate::model::BankType::TILES,
1 => crate::model::BankType::SOUNDS,
0 => prometeu_abi::model::BankType::TILES,
1 => prometeu_abi::model::BankType::SOUNDS,
_ => return Err(VmFault::Trap(prometeu_bytecode::abi::TRAP_TYPE, "Invalid asset type".to_string())),
};
let info = hw.assets().bank_info(asset_type);
@ -1309,11 +1308,11 @@ impl NativeInterface for PrometeuOS {
let asset_type_val = expect_int(args, 0)? as u32;
let slot_index = expect_int(args, 1)? as usize;
let asset_type = match asset_type_val {
0 => crate::model::BankType::TILES,
1 => crate::model::BankType::SOUNDS,
0 => prometeu_abi::model::BankType::TILES,
1 => prometeu_abi::model::BankType::SOUNDS,
_ => return Err(VmFault::Trap(prometeu_bytecode::abi::TRAP_TYPE, "Invalid asset type".to_string())),
};
let slot = crate::model::SlotRef { asset_type, index: slot_index };
let slot = prometeu_abi::model::SlotRef { asset_type, index: slot_index };
let info = hw.assets().slot_info(slot);
let json = serde_json::to_string(&info).unwrap_or_default();
ret.push_string(json);

View File

@ -405,30 +405,6 @@ pub struct AnalysisDb {
---
## PR-00.2 — Extrair `prometeu-vm` do `prometeu-core`
**Branch:** `pr-00-2-prometeu-vm`
### Objetivo
Mover `virtual_machine/*` para `crates/prometeu-vm/`.
### Passos prescritivos
1. Criar crate `crates/prometeu-vm/`.
2. Mover `crates/prometeu-core/src/virtual_machine/**``crates/prometeu-vm/src/**`.
3. Ajustar `use` paths em todos os crates.
4. Adicionar shim temporário no `prometeu-core` (se ainda existir):
* `pub mod virtual_machine { pub use prometeu_vm::*; }`
### Critérios de aceite
* `cargo test` verde.
* runtime desktop ainda roda.
---
## PR-00.3 — Extrair `prometeu-kernel` (OS + FS + syscalls)
**Branch:** `pr-00-3-prometeu-kernel`