PR002: implement gfx status-first contract for set_sprite

This commit is contained in:
bQUARKz 2026-03-09 06:56:53 +00:00
parent b241db7011
commit fe6931d420
Signed by: bquarkz
SSH Key Fingerprint: SHA256:Z7dgqoglWwoK6j6u4QC87OveEq74WOhFN+gitsxtkf8
3 changed files with 58 additions and 15 deletions

View File

@ -80,7 +80,7 @@ pub(crate) const ENTRIES: &[SyscallRegistryEntry] = &[
"set_sprite",
1,
10,
0,
1,
caps::GFX,
Determinism::Deterministic,
false,

View File

@ -10,6 +10,11 @@ use prometeu_hal::vm_fault::VmFault;
use prometeu_hal::{HostContext, HostReturn, NativeInterface, SyscallId, expect_bool, expect_int};
impl VirtualMachineRuntime {
const GFX_STATUS_OK: i64 = 0;
const GFX_STATUS_ASSET_NOT_FOUND: i64 = 1;
const GFX_STATUS_INVALID_SPRITE_INDEX: i64 = 2;
const GFX_STATUS_INVALID_ARG_RANGE: i64 = 3;
fn syscall_log_write(&mut self, level_val: i64, tag: u16, msg: String) -> Result<(), VmFault> {
let level = match level_val {
0 => LogLevel::Trace,
@ -147,21 +152,30 @@ impl NativeInterface for VirtualMachineRuntime {
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, BankType::TILES).unwrap_or(0);
if index < 512 {
*hw.gfx_mut().sprite_mut(index) = Sprite {
tile: Tile { id: tile_id, flip_x: false, flip_y: false, palette_id },
x,
y,
bank_id,
active,
flip_x,
flip_y,
priority,
};
if index >= 512 {
ret.push_int(Self::GFX_STATUS_INVALID_SPRITE_INDEX);
return Ok(());
}
if palette_id >= 64 || priority >= 5 {
ret.push_int(Self::GFX_STATUS_INVALID_ARG_RANGE);
return Ok(());
}
let Some(bank_id) = hw.assets().find_slot_by_name(&asset_name, BankType::TILES) else {
ret.push_int(Self::GFX_STATUS_ASSET_NOT_FOUND);
return Ok(());
};
*hw.gfx_mut().sprite_mut(index) = Sprite {
tile: Tile { id: tile_id, flip_x: false, flip_y: false, palette_id },
x,
y,
bank_id,
active,
flip_x,
flip_y,
priority,
};
ret.push_int(Self::GFX_STATUS_OK);
Ok(())
}
Syscall::GfxDrawText => {

View File

@ -511,3 +511,32 @@ The system can measure:
- `palettes_referenced_this_frame`
- `tiles_drawn_by_palette_id`
- `sprites_drawn_by_palette_id`
---
## 19. Syscall Return and Fault Policy
`gfx` follows status-first policy for operations with operational failure modes.
Fault boundary:
- `Trap`: structural ABI misuse (type/arity/capability/shape mismatch);
- `status`: operational failure;
- `Panic`: internal runtime invariant break only.
### 19.1 `gfx.set_sprite`
`gfx.set_sprite` returns `status:int`.
Minimum status table:
- `0` = `OK`
- `1` = `ASSET_NOT_FOUND`
- `2` = `INVALID_SPRITE_INDEX`
- `3` = `INVALID_ARG_RANGE`
Operational notes:
- no fallback to default bank when the sprite asset name cannot be resolved;
- no silent no-op for invalid index/range;
- `palette_id` and `priority` must be validated against runtime-supported ranges.