organized syscall maps

This commit is contained in:
Nilton Constantino 2026-01-20 11:45:46 +00:00
parent 313480fec4
commit 1883ce8e37
No known key found for this signature in database
9 changed files with 175 additions and 41 deletions

1
Cargo.lock generated
View File

@ -1919,6 +1919,7 @@ dependencies = [
"oxc_parser", "oxc_parser",
"oxc_span", "oxc_span",
"prometeu-bytecode", "prometeu-bytecode",
"prometeu-core",
"serde", "serde",
"serde_json", "serde_json",
] ]

View File

@ -6,7 +6,7 @@ pub mod firmware;
pub mod fs; pub mod fs;
pub mod telemetry; pub mod telemetry;
pub mod debugger_protocol; pub mod debugger_protocol;
mod prometeu_os; pub mod prometeu_os;
mod prometeu_hub; mod prometeu_hub;
pub use hardware::hardware::Hardware; pub use hardware::hardware::Hardware;

View File

@ -1,3 +1,20 @@
#[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)] #[derive(Default, Clone, Copy, Debug)]
pub struct Button { pub struct Button {
pub pressed: bool, pub pressed: bool,

View File

@ -9,7 +9,7 @@ mod cartridge;
mod cartridge_loader; mod cartridge_loader;
mod window; mod window;
pub use button::Button; pub use button::{Button, ButtonId};
pub use cartridge::{AppMode, Cartridge, CartridgeDTO, CartridgeError}; pub use cartridge::{AppMode, Cartridge, CartridgeDTO, CartridgeError};
pub use cartridge_loader::{CartridgeLoader, DirectoryCartridgeLoader, PackedCartridgeLoader}; pub use cartridge_loader::{CartridgeLoader, DirectoryCartridgeLoader, PackedCartridgeLoader};
pub use color::Color; pub use color::Color;

View File

@ -1,4 +1,6 @@
mod prometeu_os; mod prometeu_os;
pub mod syscalls;
pub use prometeu_os::PrometeuOS; pub use prometeu_os::PrometeuOS;
pub use syscalls::Syscall;
pub use crate::virtual_machine::native_interface::NativeInterface; pub use crate::virtual_machine::native_interface::NativeInterface;

View File

@ -2,7 +2,7 @@ use crate::fs::{FsBackend, FsState, VirtualFS};
use crate::hardware::{HardwareBridge, InputSignals}; use crate::hardware::{HardwareBridge, InputSignals};
use crate::log::{LogLevel, LogService, LogSource}; use crate::log::{LogLevel, LogService, LogSource};
use crate::model::{Cartridge, Color, Sample}; use crate::model::{Cartridge, Color, Sample};
use crate::prometeu_os::NativeInterface; use crate::prometeu_os::{NativeInterface, Syscall};
use crate::telemetry::{CertificationConfig, Certifier, TelemetryFrame}; use crate::telemetry::{CertificationConfig, Certifier, TelemetryFrame};
use crate::virtual_machine::{Value, VirtualMachine}; use crate::virtual_machine::{Value, VirtualMachine};
use std::collections::HashMap; use std::collections::HashMap;
@ -554,17 +554,18 @@ impl NativeInterface for PrometeuOS {
/// Each syscall returns the number of virtual cycles it consumed. /// Each syscall returns the number of virtual cycles it consumed.
fn syscall(&mut self, id: u32, vm: &mut VirtualMachine, hw: &mut dyn HardwareBridge) -> Result<u64, String> { fn syscall(&mut self, id: u32, vm: &mut VirtualMachine, hw: &mut dyn HardwareBridge) -> Result<u64, String> {
self.telemetry_current.syscalls += 1; self.telemetry_current.syscalls += 1;
match id { let syscall = Syscall::from_u32(id).ok_or_else(|| format!("Unknown syscall: 0x{:08X}", id))?;
match syscall {
// --- System Syscalls --- // --- System Syscalls ---
// system.has_cart() -> bool // system.has_cart() -> bool
0x0001 => { Syscall::SystemHasCart => {
// Returns true if a cartridge is available. // Returns true if a cartridge is available.
vm.push(Value::Boolean(true)); // For now, assume true or check state vm.push(Value::Boolean(true)); // For now, assume true or check state
Ok(10) Ok(10)
} }
// system.run_cart() -> null // system.run_cart() -> null
0x0002 => { Syscall::SystemRunCart => {
// Triggers loading and execution of the current cartridge. // Triggers loading and execution of the current cartridge.
vm.push(Value::Null); vm.push(Value::Null);
Ok(100) Ok(100)
@ -573,7 +574,7 @@ impl NativeInterface for PrometeuOS {
// --- GFX Syscalls --- // --- GFX Syscalls ---
// gfx.clear(color_index) -> null // gfx.clear(color_index) -> null
0x1001 => { Syscall::GfxClear => {
let color_idx = vm.pop_integer()? as usize; let color_idx = vm.pop_integer()? as usize;
let color = self.get_color(color_idx, hw); let color = self.get_color(color_idx, hw);
hw.gfx_mut().clear(color); hw.gfx_mut().clear(color);
@ -581,7 +582,7 @@ impl NativeInterface for PrometeuOS {
Ok(100) Ok(100)
} }
// gfx.draw_rect(x, y, w, h, color_index) -> null // gfx.draw_rect(x, y, w, h, color_index) -> null
0x1002 => { Syscall::GfxFillRect => {
let color_idx = vm.pop_integer()? as usize; let color_idx = vm.pop_integer()? as usize;
let h = vm.pop_integer()? as i32; let h = vm.pop_integer()? as i32;
let w = vm.pop_integer()? as i32; let w = vm.pop_integer()? as i32;
@ -593,7 +594,7 @@ impl NativeInterface for PrometeuOS {
Ok(200) Ok(200)
} }
// gfx.draw_line(x1, y1, x2, y2, color_index) -> null // gfx.draw_line(x1, y1, x2, y2, color_index) -> null
0x1003 => { Syscall::GfxDrawLine => {
let color_idx = vm.pop_integer()? as usize; let color_idx = vm.pop_integer()? as usize;
let y2 = vm.pop_integer()? as i32; let y2 = vm.pop_integer()? as i32;
let x2 = vm.pop_integer()? as i32; let x2 = vm.pop_integer()? as i32;
@ -605,7 +606,7 @@ impl NativeInterface for PrometeuOS {
Ok(200) Ok(200)
} }
// gfx.draw_circle(x, y, r, color_index) -> null // gfx.draw_circle(x, y, r, color_index) -> null
0x1004 => { Syscall::GfxDrawCircle => {
let color_idx = vm.pop_integer()? as usize; let color_idx = vm.pop_integer()? as usize;
let r = vm.pop_integer()? as i32; let r = vm.pop_integer()? as i32;
let y = vm.pop_integer()? as i32; let y = vm.pop_integer()? as i32;
@ -616,7 +617,7 @@ impl NativeInterface for PrometeuOS {
Ok(200) Ok(200)
} }
// gfx.draw_disc(x, y, r, border_color_idx, fill_color_idx) -> null // gfx.draw_disc(x, y, r, border_color_idx, fill_color_idx) -> null
0x1005 => { Syscall::GfxDrawDisc => {
let fill_color_idx = vm.pop_integer()? as usize; let fill_color_idx = vm.pop_integer()? as usize;
let border_color_idx = vm.pop_integer()? as usize; let border_color_idx = vm.pop_integer()? as usize;
let r = vm.pop_integer()? as i32; let r = vm.pop_integer()? as i32;
@ -629,7 +630,7 @@ impl NativeInterface for PrometeuOS {
Ok(300) Ok(300)
} }
// gfx.draw_square(x, y, w, h, border_color_idx, fill_color_idx) -> null // gfx.draw_square(x, y, w, h, border_color_idx, fill_color_idx) -> null
0x1006 => { Syscall::GfxDrawSquare => {
let fill_color_idx = vm.pop_integer()? as usize; let fill_color_idx = vm.pop_integer()? as usize;
let border_color_idx = vm.pop_integer()? as usize; let border_color_idx = vm.pop_integer()? as usize;
let h = vm.pop_integer()? as i32; let h = vm.pop_integer()? as i32;
@ -646,7 +647,7 @@ impl NativeInterface for PrometeuOS {
// --- Input Syscalls --- // --- Input Syscalls ---
// input.get_pad(button_id) -> bool // input.get_pad(button_id) -> bool
0x2001 => { Syscall::InputGetPad => {
let button_id = vm.pop_integer()? as u32; let button_id = vm.pop_integer()? as u32;
let is_down = self.is_button_down(button_id, hw); let is_down = self.is_button_down(button_id, hw);
vm.push(Value::Boolean(is_down)); vm.push(Value::Boolean(is_down));
@ -656,7 +657,7 @@ impl NativeInterface for PrometeuOS {
// --- Audio Syscalls --- // --- Audio Syscalls ---
// audio.play_sample(sample_id, voice_id, volume, pan, pitch) // audio.play_sample(sample_id, voice_id, volume, pan, pitch)
0x3001 => { Syscall::AudioPlaySample => {
let pitch = vm.pop_number()?; let pitch = vm.pop_number()?;
let pan = vm.pop_integer()? as u8; let pan = vm.pop_integer()? as u8;
let volume = vm.pop_integer()? as u8; let volume = vm.pop_integer()? as u8;
@ -681,7 +682,7 @@ impl NativeInterface for PrometeuOS {
// FS_OPEN(path) -> handle // FS_OPEN(path) -> handle
// Opens a file in the virtual sandbox and returns a numeric handle. // Opens a file in the virtual sandbox and returns a numeric handle.
0x4001 => { Syscall::FsOpen => {
let path = match vm.pop()? { let path = match vm.pop()? {
Value::String(s) => s, Value::String(s) => s,
_ => return Err("Expected string path".into()), _ => return Err("Expected string path".into()),
@ -697,7 +698,7 @@ impl NativeInterface for PrometeuOS {
Ok(200) Ok(200)
} }
// FS_READ(handle) -> content // FS_READ(handle) -> content
0x4002 => { Syscall::FsRead => {
let handle = vm.pop_integer()? as u32; let handle = vm.pop_integer()? as u32;
let path = self.open_files.get(&handle).ok_or("Invalid handle")?; let path = self.open_files.get(&handle).ok_or("Invalid handle")?;
match self.fs.read_file(path) { match self.fs.read_file(path) {
@ -713,7 +714,7 @@ impl NativeInterface for PrometeuOS {
} }
} }
// FS_WRITE(handle, content) // FS_WRITE(handle, content)
0x4003 => { Syscall::FsWrite => {
let content = match vm.pop()? { let content = match vm.pop()? {
Value::String(s) => s, Value::String(s) => s,
_ => return Err("Expected string content".into()), _ => return Err("Expected string content".into()),
@ -732,14 +733,14 @@ impl NativeInterface for PrometeuOS {
} }
} }
// FS_CLOSE(handle) // FS_CLOSE(handle)
0x4004 => { Syscall::FsClose => {
let handle = vm.pop_integer()? as u32; let handle = vm.pop_integer()? as u32;
self.open_files.remove(&handle); self.open_files.remove(&handle);
vm.push(Value::Null); vm.push(Value::Null);
Ok(100) Ok(100)
} }
// FS_LISTDIR(path) // FS_LISTDIR(path)
0x4005 => { Syscall::FsListDir => {
let path = match vm.pop()? { let path = match vm.pop()? {
Value::String(s) => s, Value::String(s) => s,
_ => return Err("Expected string path".into()), _ => return Err("Expected string path".into()),
@ -758,7 +759,7 @@ impl NativeInterface for PrometeuOS {
} }
} }
// FS_EXISTS(path) -> bool // FS_EXISTS(path) -> bool
0x4006 => { Syscall::FsExists => {
let path = match vm.pop()? { let path = match vm.pop()? {
Value::String(s) => s, Value::String(s) => s,
_ => return Err("Expected string path".into()), _ => return Err("Expected string path".into()),
@ -767,7 +768,7 @@ impl NativeInterface for PrometeuOS {
Ok(100) Ok(100)
} }
// FS_DELETE(path) // FS_DELETE(path)
0x4007 => { Syscall::FsDelete => {
let path = match vm.pop()? { let path = match vm.pop()? {
Value::String(s) => s, Value::String(s) => s,
_ => return Err("Expected string path".into()), _ => return Err("Expected string path".into()),
@ -782,7 +783,7 @@ impl NativeInterface for PrometeuOS {
// --- Log Syscalls (0x5000) --- // --- Log Syscalls (0x5000) ---
// LOG_WRITE(level, msg) // LOG_WRITE(level, msg)
0x5001 => { Syscall::LogWrite => {
let msg = match vm.pop()? { let msg = match vm.pop()? {
Value::String(s) => s, Value::String(s) => s,
_ => return Err("Expected string message".into()), _ => return Err("Expected string message".into()),
@ -791,7 +792,7 @@ impl NativeInterface for PrometeuOS {
self.syscall_log_write(vm, level, 0, msg) self.syscall_log_write(vm, level, 0, msg)
} }
// LOG_WRITE_TAG(level, tag, msg) // LOG_WRITE_TAG(level, tag, msg)
0x5002 => { Syscall::LogWriteTag => {
let msg = match vm.pop()? { let msg = match vm.pop()? {
Value::String(s) => s, Value::String(s) => s,
_ => return Err("Expected string message".into()), _ => return Err("Expected string message".into()),
@ -800,8 +801,6 @@ impl NativeInterface for PrometeuOS {
let level = vm.pop_integer()?; let level = vm.pop_integer()?;
self.syscall_log_write(vm, level, tag, msg) self.syscall_log_write(vm, level, tag, msg)
} }
_ => Err(format!("Unknown syscall: 0x{:08X}", id)),
} }
} }
} }

View File

@ -0,0 +1,110 @@
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u32)]
pub enum Syscall {
// System
SystemHasCart = 0x0001,
SystemRunCart = 0x0002,
// GFX
GfxClear = 0x1001,
GfxFillRect = 0x1002,
GfxDrawLine = 0x1003,
GfxDrawCircle = 0x1004,
GfxDrawDisc = 0x1005,
GfxDrawSquare = 0x1006,
// Input
InputGetPad = 0x2001,
// Audio
AudioPlaySample = 0x3001,
// FS
FsOpen = 0x4001,
FsRead = 0x4002,
FsWrite = 0x4003,
FsClose = 0x4004,
FsListDir = 0x4005,
FsExists = 0x4006,
FsDelete = 0x4007,
// Log
LogWrite = 0x5001,
LogWriteTag = 0x5002,
}
impl Syscall {
pub fn from_u32(id: u32) -> Option<Self> {
match id {
0x0001 => Some(Self::SystemHasCart),
0x0002 => Some(Self::SystemRunCart),
0x1001 => Some(Self::GfxClear),
0x1002 => Some(Self::GfxFillRect),
0x1003 => Some(Self::GfxDrawLine),
0x1004 => Some(Self::GfxDrawCircle),
0x1005 => Some(Self::GfxDrawDisc),
0x1006 => Some(Self::GfxDrawSquare),
0x2001 => Some(Self::InputGetPad),
0x3001 => Some(Self::AudioPlaySample),
0x4001 => Some(Self::FsOpen),
0x4002 => Some(Self::FsRead),
0x4003 => Some(Self::FsWrite),
0x4004 => Some(Self::FsClose),
0x4005 => Some(Self::FsListDir),
0x4006 => Some(Self::FsExists),
0x4007 => Some(Self::FsDelete),
0x5001 => Some(Self::LogWrite),
0x5002 => Some(Self::LogWriteTag),
_ => None,
}
}
pub fn as_str(&self) -> &'static str {
match self {
Self::SystemHasCart => "system.has_cart",
Self::SystemRunCart => "system.run_cart",
Self::GfxClear => "gfx.clear",
Self::GfxFillRect => "gfx.fillRect",
Self::GfxDrawLine => "gfx.drawLine",
Self::GfxDrawCircle => "gfx.drawCircle",
Self::GfxDrawDisc => "gfx.drawDisc",
Self::GfxDrawSquare => "gfx.drawSquare",
Self::InputGetPad => "input.get_pad",
Self::AudioPlaySample => "audio.playSample",
Self::FsOpen => "fs.open",
Self::FsRead => "fs.read",
Self::FsWrite => "fs.write",
Self::FsClose => "fs.close",
Self::FsListDir => "fs.listDir",
Self::FsExists => "fs.exists",
Self::FsDelete => "fs.delete",
Self::LogWrite => "log.write",
Self::LogWriteTag => "log.writeTag",
}
}
pub fn from_name(name: &str) -> Option<Self> {
match name {
"system.has_cart" => Some(Self::SystemHasCart),
"system.run_cart" => Some(Self::SystemRunCart),
"gfx.clear" => Some(Self::GfxClear),
"gfx.fillRect" | "gfx.draw_rect" => Some(Self::GfxFillRect),
"gfx.drawLine" | "gfx.draw_line" => Some(Self::GfxDrawLine),
"gfx.drawCircle" | "gfx.draw_circle" => Some(Self::GfxDrawCircle),
"gfx.drawDisc" | "gfx.draw_disc" => Some(Self::GfxDrawDisc),
"gfx.drawSquare" | "gfx.draw_square" => Some(Self::GfxDrawSquare),
"input.get_pad" => Some(Self::InputGetPad),
"audio.playSample" | "audio.play_sample" => Some(Self::AudioPlaySample),
"fs.open" => Some(Self::FsOpen),
"fs.read" => Some(Self::FsRead),
"fs.write" => Some(Self::FsWrite),
"fs.close" => Some(Self::FsClose),
"fs.listDir" => Some(Self::FsListDir),
"fs.exists" => Some(Self::FsExists),
"fs.delete" => Some(Self::FsDelete),
"log.write" => Some(Self::LogWrite),
"log.writeTag" => Some(Self::LogWriteTag),
_ => None,
}
}
}

View File

@ -5,6 +5,7 @@ edition = "2021"
[dependencies] [dependencies]
prometeu-bytecode = { path = "../prometeu-bytecode" } prometeu-bytecode = { path = "../prometeu-bytecode" }
prometeu-core = { path = "../prometeu-core" }
oxc_parser = "0.48.0" oxc_parser = "0.48.0"
oxc_allocator = "0.48.0" oxc_allocator = "0.48.0"
oxc_ast = "0.48.0" oxc_ast = "0.48.0"

View File

@ -1,23 +1,27 @@
pub const SYS_GFX_FILL_RECT: u32 = 0x1002; use prometeu_core::prometeu_os::Syscall;
pub const SYS_INPUT_GET_PAD: u32 = 0x2001; use prometeu_core::model::ButtonId;
pub const BTN_UP: u32 = 0; pub const BTN_UP: u32 = ButtonId::Up as u32;
pub const BTN_DOWN: u32 = 1; pub const BTN_DOWN: u32 = ButtonId::Down as u32;
pub const BTN_LEFT: u32 = 2; pub const BTN_LEFT: u32 = ButtonId::Left as u32;
pub const BTN_RIGHT: u32 = 3; pub const BTN_RIGHT: u32 = ButtonId::Right as u32;
pub const BTN_A: u32 = 4; pub const BTN_A: u32 = ButtonId::A as u32;
pub const BTN_B: u32 = 5; pub const BTN_B: u32 = ButtonId::B as u32;
pub const BTN_X: u32 = 6; pub const BTN_X: u32 = ButtonId::X as u32;
pub const BTN_Y: u32 = 7; pub const BTN_Y: u32 = ButtonId::Y as u32;
pub const BTN_L: u32 = 8; pub const BTN_L: u32 = ButtonId::L as u32;
pub const BTN_R: u32 = 9; pub const BTN_R: u32 = ButtonId::R as u32;
pub const BTN_START: u32 = 10; pub const BTN_START: u32 = ButtonId::Start as u32;
pub const BTN_SELECT: u32 = 11; pub const BTN_SELECT: u32 = ButtonId::Select as u32;
pub fn map_syscall(name: &str) -> Option<u32> { pub fn map_syscall(name: &str) -> Option<u32> {
if let Some(syscall) = Syscall::from_name(name) {
return Some(syscall as u32);
}
// Fallback para nomes especiais do compilador
match name { match name {
"gfx.fillRect" => Some(SYS_GFX_FILL_RECT), "input.btnA" | "input.btnB" => Some(Syscall::InputGetPad as u32),
"input.btnA" | "input.btnB" | "input.get_pad" => Some(SYS_INPUT_GET_PAD),
_ => None, _ => None,
} }
} }