assets loaded by bank id instead of name
This commit is contained in:
parent
d576f7ddbd
commit
17878e481c
@ -169,9 +169,6 @@ impl AssetBridge for AssetManager {
|
|||||||
fn slot_info(&self, slot: SlotRef) -> SlotStats {
|
fn slot_info(&self, slot: SlotRef) -> SlotStats {
|
||||||
self.slot_info(slot)
|
self.slot_info(slot)
|
||||||
}
|
}
|
||||||
fn find_slot_by_name(&self, asset_name: &str, kind: BankType) -> Option<u8> {
|
|
||||||
self.find_slot_by_name(asset_name, kind)
|
|
||||||
}
|
|
||||||
fn shutdown(&self) {
|
fn shutdown(&self) {
|
||||||
self.shutdown()
|
self.shutdown()
|
||||||
}
|
}
|
||||||
@ -824,24 +821,6 @@ impl AssetManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn find_slot_by_name(&self, asset_name: &str, kind: BankType) -> Option<u8> {
|
|
||||||
let asset_id = {
|
|
||||||
let name_to_id = self.name_to_id.read().unwrap();
|
|
||||||
*name_to_id.get(asset_name)?
|
|
||||||
};
|
|
||||||
|
|
||||||
match kind {
|
|
||||||
BankType::TILES => {
|
|
||||||
let slots = self.gfx_slots.read().unwrap();
|
|
||||||
slots.iter().position(|&s| s == Some(asset_id)).map(|p| p as u8)
|
|
||||||
}
|
|
||||||
BankType::SOUNDS => {
|
|
||||||
let slots = self.sound_slots.read().unwrap();
|
|
||||||
slots.iter().position(|&s| s == Some(asset_id)).map(|p| p as u8)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn shutdown(&self) {
|
pub fn shutdown(&self) {
|
||||||
self.gfx_policy.clear();
|
self.gfx_policy.clear();
|
||||||
self.sound_policy.clear();
|
self.sound_policy.clear();
|
||||||
@ -1062,31 +1041,6 @@ mod tests {
|
|||||||
assert_eq!(am.slot_info(SlotRef::audio(5)).asset_id, Some(2));
|
assert_eq!(am.slot_info(SlotRef::audio(5)).asset_id, Some(2));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_find_slot_by_name() {
|
|
||||||
let banks = Arc::new(MemoryBanks::new());
|
|
||||||
let gfx_installer = Arc::clone(&banks) as Arc<dyn TileBankPoolInstaller>;
|
|
||||||
let sound_installer = Arc::clone(&banks) as Arc<dyn SoundBankPoolInstaller>;
|
|
||||||
|
|
||||||
let data = test_tile_asset_data();
|
|
||||||
let mut asset_entry = test_tile_asset_entry("my_tiles", data.len());
|
|
||||||
asset_entry.asset_id = 10;
|
|
||||||
|
|
||||||
let preload = vec![PreloadEntry { asset_id: 10, slot: 3 }];
|
|
||||||
|
|
||||||
let am = AssetManager::new(
|
|
||||||
vec![],
|
|
||||||
AssetsPayloadSource::empty(),
|
|
||||||
gfx_installer,
|
|
||||||
sound_installer,
|
|
||||||
);
|
|
||||||
am.initialize_for_cartridge(vec![asset_entry], preload, AssetsPayloadSource::from_bytes(data));
|
|
||||||
|
|
||||||
assert_eq!(am.find_slot_by_name("my_tiles", BankType::TILES), Some(3));
|
|
||||||
assert_eq!(am.find_slot_by_name("unknown", BankType::TILES), None);
|
|
||||||
assert_eq!(am.find_slot_by_name("my_tiles", BankType::SOUNDS), None);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_load_returns_asset_not_found() {
|
fn test_load_returns_asset_not_found() {
|
||||||
let banks = Arc::new(MemoryBanks::new());
|
let banks = Arc::new(MemoryBanks::new());
|
||||||
|
|||||||
@ -18,6 +18,5 @@ pub trait AssetBridge {
|
|||||||
fn apply_commits(&self);
|
fn apply_commits(&self);
|
||||||
fn bank_info(&self, kind: BankType) -> BankStats;
|
fn bank_info(&self, kind: BankType) -> BankStats;
|
||||||
fn slot_info(&self, slot: SlotRef) -> SlotStats;
|
fn slot_info(&self, slot: SlotRef) -> SlotStats;
|
||||||
fn find_slot_by_name(&self, asset_name: &str, kind: BankType) -> Option<u8>;
|
|
||||||
fn shutdown(&self);
|
fn shutdown(&self);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -135,7 +135,7 @@ impl NativeInterface for VirtualMachineRuntime {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
Syscall::GfxSetSprite => {
|
Syscall::GfxSetSprite => {
|
||||||
let asset_name = expect_string(args, 0, "asset_name")?;
|
let bank_id = expect_int(args, 0)? as u8;
|
||||||
let index = expect_int(args, 1)? as usize;
|
let index = expect_int(args, 1)? as usize;
|
||||||
let x = expect_int(args, 2)? as i32;
|
let x = expect_int(args, 2)? as i32;
|
||||||
let y = expect_int(args, 3)? as i32;
|
let y = expect_int(args, 3)? as i32;
|
||||||
@ -154,10 +154,6 @@ impl NativeInterface for VirtualMachineRuntime {
|
|||||||
ret.push_int(GfxOpStatus::ArgRangeInvalid as i64);
|
ret.push_int(GfxOpStatus::ArgRangeInvalid as i64);
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
let Some(bank_id) = hw.assets().find_slot_by_name(&asset_name, BankType::TILES) else {
|
|
||||||
ret.push_int(GfxOpStatus::AssetNotFound as i64);
|
|
||||||
return Ok(());
|
|
||||||
};
|
|
||||||
|
|
||||||
*hw.gfx_mut().sprite_mut(index) = Sprite {
|
*hw.gfx_mut().sprite_mut(index) = Sprite {
|
||||||
tile: Tile { id: tile_id, flip_x: false, flip_y: false, palette_id },
|
tile: Tile { id: tile_id, flip_x: false, flip_y: false, palette_id },
|
||||||
@ -225,7 +221,7 @@ impl NativeInterface for VirtualMachineRuntime {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
Syscall::AudioPlay => {
|
Syscall::AudioPlay => {
|
||||||
let asset_name = expect_string(args, 0, "asset_name")?;
|
let bank_id = expect_int(args, 0)? as u8;
|
||||||
let sample_id_raw = expect_int(args, 1)?;
|
let sample_id_raw = expect_int(args, 1)?;
|
||||||
let voice_id_raw = expect_int(args, 2)?;
|
let voice_id_raw = expect_int(args, 2)?;
|
||||||
let volume_raw = expect_int(args, 3)?;
|
let volume_raw = expect_int(args, 3)?;
|
||||||
@ -252,10 +248,6 @@ impl NativeInterface for VirtualMachineRuntime {
|
|||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
let Some(bank_id) = hw.assets().find_slot_by_name(&asset_name, BankType::SOUNDS) else {
|
|
||||||
ret.push_int(AudioOpStatus::AssetNotFound as i64);
|
|
||||||
return Ok(());
|
|
||||||
};
|
|
||||||
let status = hw.audio_mut().play(
|
let status = hw.audio_mut().play(
|
||||||
bank_id,
|
bank_id,
|
||||||
sample_id_raw as u16,
|
sample_id_raw as u16,
|
||||||
|
|||||||
@ -357,12 +357,11 @@ fn tick_gfx_set_sprite_operational_error_returns_status_not_crash() {
|
|||||||
let mut hardware = Hardware::new();
|
let mut hardware = Hardware::new();
|
||||||
let signals = InputSignals::default();
|
let signals = InputSignals::default();
|
||||||
let code = assemble(
|
let code = assemble(
|
||||||
"PUSH_CONST 0\nPUSH_I32 0\nPUSH_I32 0\nPUSH_I32 0\nPUSH_I32 0\nPUSH_I32 0\nPUSH_BOOL 1\nPUSH_BOOL 0\nPUSH_BOOL 0\nPUSH_I32 0\nHOSTCALL 0\nHALT",
|
"PUSH_I32 0\nPUSH_I32 0\nPUSH_I32 0\nPUSH_I32 0\nPUSH_I32 0\nPUSH_I32 0\nPUSH_BOOL 1\nPUSH_BOOL 0\nPUSH_BOOL 0\nPUSH_I32 0\nHOSTCALL 0\nHALT",
|
||||||
)
|
)
|
||||||
.expect("assemble");
|
.expect("assemble");
|
||||||
let program = serialized_single_function_module_with_consts(
|
let program = serialized_single_function_module(
|
||||||
code,
|
code,
|
||||||
vec![ConstantPoolEntry::String("missing_tile_bank".into())],
|
|
||||||
vec![SyscallDecl {
|
vec![SyscallDecl {
|
||||||
module: "gfx".into(),
|
module: "gfx".into(),
|
||||||
name: "set_sprite".into(),
|
name: "set_sprite".into(),
|
||||||
@ -377,7 +376,7 @@ fn tick_gfx_set_sprite_operational_error_returns_status_not_crash() {
|
|||||||
let report = runtime.tick(&mut vm, &signals, &mut hardware);
|
let report = runtime.tick(&mut vm, &signals, &mut hardware);
|
||||||
assert!(report.is_none(), "operational error must not crash");
|
assert!(report.is_none(), "operational error must not crash");
|
||||||
assert!(vm.is_halted());
|
assert!(vm.is_halted());
|
||||||
assert_eq!(vm.operand_stack_top(1), vec![Value::Int64(GfxOpStatus::AssetNotFound as i64)]);
|
assert_eq!(vm.operand_stack_top(1), vec![Value::Int64(GfxOpStatus::Ok as i64)]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -387,12 +386,11 @@ fn tick_gfx_set_sprite_invalid_index_returns_status_not_crash() {
|
|||||||
let mut hardware = Hardware::new();
|
let mut hardware = Hardware::new();
|
||||||
let signals = InputSignals::default();
|
let signals = InputSignals::default();
|
||||||
let code = assemble(
|
let code = assemble(
|
||||||
"PUSH_CONST 0\nPUSH_I32 512\nPUSH_I32 0\nPUSH_I32 0\nPUSH_I32 0\nPUSH_I32 0\nPUSH_BOOL 1\nPUSH_BOOL 0\nPUSH_BOOL 0\nPUSH_I32 0\nHOSTCALL 0\nHALT",
|
"PUSH_I32 0\nPUSH_I32 512\nPUSH_I32 0\nPUSH_I32 0\nPUSH_I32 0\nPUSH_I32 0\nPUSH_BOOL 1\nPUSH_BOOL 0\nPUSH_BOOL 0\nPUSH_I32 0\nHOSTCALL 0\nHALT",
|
||||||
)
|
)
|
||||||
.expect("assemble");
|
.expect("assemble");
|
||||||
let program = serialized_single_function_module_with_consts(
|
let program = serialized_single_function_module(
|
||||||
code,
|
code,
|
||||||
vec![ConstantPoolEntry::String("missing_tile_bank".into())],
|
|
||||||
vec![SyscallDecl {
|
vec![SyscallDecl {
|
||||||
module: "gfx".into(),
|
module: "gfx".into(),
|
||||||
name: "set_sprite".into(),
|
name: "set_sprite".into(),
|
||||||
@ -420,12 +418,11 @@ fn tick_gfx_set_sprite_invalid_range_returns_status_not_crash() {
|
|||||||
let mut hardware = Hardware::new();
|
let mut hardware = Hardware::new();
|
||||||
let signals = InputSignals::default();
|
let signals = InputSignals::default();
|
||||||
let code = assemble(
|
let code = assemble(
|
||||||
"PUSH_CONST 0\nPUSH_I32 0\nPUSH_I32 0\nPUSH_I32 0\nPUSH_I32 0\nPUSH_I32 64\nPUSH_BOOL 1\nPUSH_BOOL 0\nPUSH_BOOL 0\nPUSH_I32 0\nHOSTCALL 0\nHALT",
|
"PUSH_I32 0\nPUSH_I32 0\nPUSH_I32 0\nPUSH_I32 0\nPUSH_I32 0\nPUSH_I32 64\nPUSH_BOOL 1\nPUSH_BOOL 0\nPUSH_BOOL 0\nPUSH_I32 0\nHOSTCALL 0\nHALT",
|
||||||
)
|
)
|
||||||
.expect("assemble");
|
.expect("assemble");
|
||||||
let program = serialized_single_function_module_with_consts(
|
let program = serialized_single_function_module(
|
||||||
code,
|
code,
|
||||||
vec![ConstantPoolEntry::String("missing_tile_bank".into())],
|
|
||||||
vec![SyscallDecl {
|
vec![SyscallDecl {
|
||||||
module: "gfx".into(),
|
module: "gfx".into(),
|
||||||
name: "set_sprite".into(),
|
name: "set_sprite".into(),
|
||||||
@ -477,12 +474,11 @@ fn tick_audio_play_voice_invalid_returns_status_not_crash() {
|
|||||||
let mut hardware = Hardware::new();
|
let mut hardware = Hardware::new();
|
||||||
let signals = InputSignals::default();
|
let signals = InputSignals::default();
|
||||||
let code = assemble(
|
let code = assemble(
|
||||||
"PUSH_CONST 0\nPUSH_I32 0\nPUSH_I32 16\nPUSH_I32 255\nPUSH_I32 128\nPUSH_I32 1\nPUSH_I32 0\nHOSTCALL 0\nHALT",
|
"PUSH_I32 0\nPUSH_I32 0\nPUSH_I32 16\nPUSH_I32 255\nPUSH_I32 128\nPUSH_I32 1\nPUSH_I32 0\nHOSTCALL 0\nHALT",
|
||||||
)
|
)
|
||||||
.expect("assemble");
|
.expect("assemble");
|
||||||
let program = serialized_single_function_module_with_consts(
|
let program = serialized_single_function_module(
|
||||||
code,
|
code,
|
||||||
vec![ConstantPoolEntry::String("missing_sound_bank".into())],
|
|
||||||
vec![SyscallDecl {
|
vec![SyscallDecl {
|
||||||
module: "audio".into(),
|
module: "audio".into(),
|
||||||
name: "play".into(),
|
name: "play".into(),
|
||||||
@ -507,12 +503,11 @@ fn tick_audio_play_missing_asset_returns_status_not_crash() {
|
|||||||
let mut hardware = Hardware::new();
|
let mut hardware = Hardware::new();
|
||||||
let signals = InputSignals::default();
|
let signals = InputSignals::default();
|
||||||
let code = assemble(
|
let code = assemble(
|
||||||
"PUSH_CONST 0\nPUSH_I32 0\nPUSH_I32 0\nPUSH_I32 255\nPUSH_I32 128\nPUSH_I32 1\nPUSH_I32 0\nHOSTCALL 0\nHALT",
|
"PUSH_I32 0\nPUSH_I32 0\nPUSH_I32 0\nPUSH_I32 255\nPUSH_I32 128\nPUSH_I32 1\nPUSH_I32 0\nHOSTCALL 0\nHALT",
|
||||||
)
|
)
|
||||||
.expect("assemble");
|
.expect("assemble");
|
||||||
let program = serialized_single_function_module_with_consts(
|
let program = serialized_single_function_module(
|
||||||
code,
|
code,
|
||||||
vec![ConstantPoolEntry::String("missing_sound_bank".into())],
|
|
||||||
vec![SyscallDecl {
|
vec![SyscallDecl {
|
||||||
module: "audio".into(),
|
module: "audio".into(),
|
||||||
name: "play".into(),
|
name: "play".into(),
|
||||||
@ -527,7 +522,7 @@ fn tick_audio_play_missing_asset_returns_status_not_crash() {
|
|||||||
let report = runtime.tick(&mut vm, &signals, &mut hardware);
|
let report = runtime.tick(&mut vm, &signals, &mut hardware);
|
||||||
assert!(report.is_none(), "missing audio asset must not crash");
|
assert!(report.is_none(), "missing audio asset must not crash");
|
||||||
assert!(vm.is_halted());
|
assert!(vm.is_halted());
|
||||||
assert_eq!(vm.operand_stack_top(1), vec![Value::Int64(AudioOpStatus::AssetNotFound as i64)]);
|
assert_eq!(vm.operand_stack_top(1), vec![Value::Int64(AudioOpStatus::SampleNotFound as i64)]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -559,7 +554,7 @@ fn tick_audio_play_type_mismatch_surfaces_trap_not_panic() {
|
|||||||
match report {
|
match report {
|
||||||
CrashReport::VmTrap { trap } => {
|
CrashReport::VmTrap { trap } => {
|
||||||
assert_eq!(trap.code, TRAP_TYPE);
|
assert_eq!(trap.code, TRAP_TYPE);
|
||||||
assert!(trap.message.contains("Expected string asset_name"));
|
assert!(trap.message.contains("Expected integer at index 0"));
|
||||||
}
|
}
|
||||||
other => panic!("expected VmTrap crash report, got {:?}", other),
|
other => panic!("expected VmTrap crash report, got {:?}", other),
|
||||||
}
|
}
|
||||||
@ -889,17 +884,15 @@ fn tick_status_first_surface_smoke_across_gfx_audio_and_asset() {
|
|||||||
let mut hardware = Hardware::new();
|
let mut hardware = Hardware::new();
|
||||||
let signals = InputSignals::default();
|
let signals = InputSignals::default();
|
||||||
let code = assemble(
|
let code = assemble(
|
||||||
"PUSH_CONST 0\nPUSH_I32 0\nPUSH_I32 0\nPUSH_I32 0\nPUSH_I32 0\nPUSH_I32 0\nPUSH_BOOL 1\nPUSH_BOOL 0\nPUSH_BOOL 0\nPUSH_I32 0\nHOSTCALL 0\n\
|
"PUSH_I32 0\nPUSH_I32 0\nPUSH_I32 0\nPUSH_I32 0\nPUSH_I32 0\nPUSH_I32 0\nPUSH_BOOL 1\nPUSH_BOOL 0\nPUSH_BOOL 0\nPUSH_I32 0\nHOSTCALL 0\n\
|
||||||
PUSH_CONST 1\nPUSH_I32 0\nPUSH_I32 0\nPUSH_I32 255\nPUSH_I32 128\nPUSH_I32 1\nPUSH_I32 0\nHOSTCALL 1\n\
|
PUSH_I32 0\nPUSH_I32 0\nPUSH_I32 0\nPUSH_I32 255\nPUSH_I32 128\nPUSH_I32 1\nPUSH_I32 0\nHOSTCALL 1\n\
|
||||||
PUSH_CONST 2\nPUSH_I32 0\nPUSH_I32 0\nHOSTCALL 2\n\
|
PUSH_CONST 0\nPUSH_I32 0\nPUSH_I32 0\nHOSTCALL 2\n\
|
||||||
HALT"
|
HALT"
|
||||||
)
|
)
|
||||||
.expect("assemble");
|
.expect("assemble");
|
||||||
let program = serialized_single_function_module_with_consts(
|
let program = serialized_single_function_module_with_consts(
|
||||||
code,
|
code,
|
||||||
vec![
|
vec![
|
||||||
ConstantPoolEntry::String("missing_tile_bank".into()),
|
|
||||||
ConstantPoolEntry::String("missing_sound_bank".into()),
|
|
||||||
ConstantPoolEntry::String("missing_asset".into()),
|
ConstantPoolEntry::String("missing_asset".into()),
|
||||||
],
|
],
|
||||||
vec![
|
vec![
|
||||||
@ -937,8 +930,8 @@ fn tick_status_first_surface_smoke_across_gfx_audio_and_asset() {
|
|||||||
vec![
|
vec![
|
||||||
Value::Int64(0),
|
Value::Int64(0),
|
||||||
Value::Int64(AssetLoadError::AssetNotFound as i64),
|
Value::Int64(AssetLoadError::AssetNotFound as i64),
|
||||||
Value::Int64(AudioOpStatus::AssetNotFound as i64),
|
Value::Int64(AudioOpStatus::SampleNotFound as i64),
|
||||||
Value::Int64(GfxOpStatus::AssetNotFound as i64),
|
Value::Int64(GfxOpStatus::Ok as i64),
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -972,7 +965,7 @@ fn tick_gfx_set_sprite_type_mismatch_surfaces_trap_not_panic() {
|
|||||||
match report {
|
match report {
|
||||||
CrashReport::VmTrap { trap } => {
|
CrashReport::VmTrap { trap } => {
|
||||||
assert_eq!(trap.code, TRAP_TYPE);
|
assert_eq!(trap.code, TRAP_TYPE);
|
||||||
assert!(trap.message.contains("Expected string asset_name"));
|
assert!(trap.message.contains("Expected integer at index 0"));
|
||||||
}
|
}
|
||||||
other => panic!("expected VmTrap crash report, got {:?}", other),
|
other => panic!("expected VmTrap crash report, got {:?}", other),
|
||||||
}
|
}
|
||||||
|
|||||||
@ -547,15 +547,26 @@ All other `gfx` syscalls remain `void` unless a future domain revision introduce
|
|||||||
|
|
||||||
`gfx.set_sprite` returns `status:int`.
|
`gfx.set_sprite` returns `status:int`.
|
||||||
|
|
||||||
|
ABI:
|
||||||
|
1. `bank_id: int` — index of the tile bank
|
||||||
|
2. `index: int` — sprite index (0..511)
|
||||||
|
3. `x: int` — x coordinate
|
||||||
|
4. `y: int` — y coordinate
|
||||||
|
5. `tile_id: int` — tile index within the bank
|
||||||
|
6. `palette_id: int` — palette index (0..63)
|
||||||
|
7. `active: bool` — visibility toggle
|
||||||
|
8. `flip_x: bool` — horizontal flip
|
||||||
|
9. `flip_y: bool` — vertical flip
|
||||||
|
10. `priority: int` — layer priority (0..4)
|
||||||
|
|
||||||
Minimum status table:
|
Minimum status table:
|
||||||
|
|
||||||
- `0` = `OK`
|
- `0` = `OK`
|
||||||
- `1` = `ASSET_NOT_FOUND`
|
|
||||||
- `2` = `INVALID_SPRITE_INDEX`
|
- `2` = `INVALID_SPRITE_INDEX`
|
||||||
- `3` = `INVALID_ARG_RANGE`
|
- `3` = `INVALID_ARG_RANGE`
|
||||||
|
|
||||||
Operational notes:
|
Operational notes:
|
||||||
|
|
||||||
- no fallback to default bank when the sprite asset name cannot be resolved;
|
- no fallback to default bank when the sprite bank id cannot be resolved;
|
||||||
- no silent no-op for invalid index/range;
|
- no silent no-op for invalid index/range;
|
||||||
- `palette_id` and `priority` must be validated against runtime-supported ranges.
|
- `palette_id` and `priority` must be validated against runtime-supported ranges.
|
||||||
|
|||||||
@ -192,6 +192,15 @@ In the current MVP:
|
|||||||
- `audio.play` returns `status:int`;
|
- `audio.play` returns `status:int`;
|
||||||
- `audio.play_sample` returns `status:int`.
|
- `audio.play_sample` returns `status:int`.
|
||||||
|
|
||||||
|
ABI `audio.play`:
|
||||||
|
1. `bank_id: int` — index of the sound bank
|
||||||
|
2. `sample_id: int` — index of the sample within the bank
|
||||||
|
3. `voice_id: int` — index of the voice to use (0..15)
|
||||||
|
4. `volume: int` — volume level (0..255)
|
||||||
|
5. `pan: int` — panning (0..255)
|
||||||
|
6. `pitch: float` — playback rate
|
||||||
|
7. `loop_mode: int` — `0` for Off, `1` for On
|
||||||
|
|
||||||
Return-shape matrix in v1 syscall surface:
|
Return-shape matrix in v1 syscall surface:
|
||||||
|
|
||||||
| Syscall | Return | Policy basis |
|
| Syscall | Return | Policy basis |
|
||||||
@ -205,12 +214,11 @@ Return-shape matrix in v1 syscall surface:
|
|||||||
- `1` = `VOICE_INVALID`
|
- `1` = `VOICE_INVALID`
|
||||||
- `2` = `SAMPLE_NOT_FOUND`
|
- `2` = `SAMPLE_NOT_FOUND`
|
||||||
- `3` = `ARG_RANGE_INVALID`
|
- `3` = `ARG_RANGE_INVALID`
|
||||||
- `4` = `ASSET_NOT_FOUND`
|
|
||||||
- `5` = `NO_EFFECT`
|
- `5` = `NO_EFFECT`
|
||||||
|
|
||||||
Operational rules:
|
Operational rules:
|
||||||
|
|
||||||
- no fallback to default bank when an asset cannot be resolved;
|
- no fallback to default bank when a bank id cannot be resolved;
|
||||||
- no silent no-op for invalid `voice_id`;
|
- no silent no-op for invalid `voice_id`;
|
||||||
- invalid `voice_id` must return `VOICE_INVALID`, not `ARG_RANGE_INVALID`;
|
- invalid `voice_id` must return `VOICE_INVALID`, not `ARG_RANGE_INVALID`;
|
||||||
- invalid numeric ranges (e.g. `volume`, `pan`, `pitch`) must return explicit status.
|
- invalid numeric ranges (e.g. `volume`, `pan`, `pitch`) must return explicit status.
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user