pr 00.1 decouple more code from vm and hardware
This commit is contained in:
parent
0cacf4fed8
commit
ba2344e324
4
Cargo.lock
generated
4
Cargo.lock
generated
@ -2192,6 +2192,7 @@ dependencies = [
|
||||
name = "prometeu-abi"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"prometeu-bytecode",
|
||||
"serde",
|
||||
"serde_json",
|
||||
]
|
||||
@ -2236,6 +2237,7 @@ version = "0.1.0"
|
||||
dependencies = [
|
||||
"prometeu-abi",
|
||||
"prometeu-bytecode",
|
||||
"prometeu-hardware-contract",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"url",
|
||||
@ -2245,6 +2247,8 @@ dependencies = [
|
||||
name = "prometeu-hardware-contract"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"prometeu-abi",
|
||||
"prometeu-bytecode",
|
||||
"serde",
|
||||
"serde_json",
|
||||
]
|
||||
|
||||
@ -1,604 +0,0 @@
|
||||
Checking prometeu-core v0.1.0 (/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/crates/prometeu-core)
|
||||
error[E0615]: attempted to take value of method `start` on type `&dyn PadBridge`
|
||||
--> crates/prometeu-core/src/firmware/firmware_step_hub_home.rs:20:29
|
||||
|
|
||||
20 | if ctx.hw.pad().start.down {
|
||||
| ^^^^^ method, not a field
|
||||
|
|
||||
help: use parentheses to call the method
|
||||
|
|
||||
20 | if ctx.hw.pad().start().down {
|
||||
| ++
|
||||
|
||||
error[E0615]: attempted to take value of method `start` on type `&dyn PadBridge`
|
||||
--> crates/prometeu-core/src/firmware/firmware_step_crash_screen.rs:27:25
|
||||
|
|
||||
27 | if ctx.hw.pad().start.down {
|
||||
| ^^^^^ method, not a field
|
||||
|
|
||||
help: use parentheses to call the method
|
||||
|
|
||||
27 | if ctx.hw.pad().start().down {
|
||||
| ++
|
||||
|
||||
error[E0615]: attempted to take value of method `up` on type `&dyn PadBridge`
|
||||
--> crates/prometeu-core/src/prometeu_os/prometeu_os.rs:380:28
|
||||
|
|
||||
380 | 0 => Some(&pad.up),
|
||||
| ^^ method, not a field
|
||||
|
|
||||
help: use parentheses to call the method
|
||||
|
|
||||
380 | 0 => Some(&pad.up()),
|
||||
| ++
|
||||
|
||||
error[E0615]: attempted to take value of method `down` on type `&dyn PadBridge`
|
||||
--> crates/prometeu-core/src/prometeu_os/prometeu_os.rs:381:28
|
||||
|
|
||||
381 | 1 => Some(&pad.down),
|
||||
| ^^^^ method, not a field
|
||||
|
|
||||
help: use parentheses to call the method
|
||||
|
|
||||
381 | 1 => Some(&pad.down()),
|
||||
| ++
|
||||
|
||||
error[E0615]: attempted to take value of method `left` on type `&dyn PadBridge`
|
||||
--> crates/prometeu-core/src/prometeu_os/prometeu_os.rs:382:28
|
||||
|
|
||||
382 | 2 => Some(&pad.left),
|
||||
| ^^^^ method, not a field
|
||||
|
|
||||
help: use parentheses to call the method
|
||||
|
|
||||
382 | 2 => Some(&pad.left()),
|
||||
| ++
|
||||
|
||||
error[E0615]: attempted to take value of method `right` on type `&dyn PadBridge`
|
||||
--> crates/prometeu-core/src/prometeu_os/prometeu_os.rs:383:28
|
||||
|
|
||||
383 | 3 => Some(&pad.right),
|
||||
| ^^^^^ method, not a field
|
||||
|
|
||||
help: use parentheses to call the method
|
||||
|
|
||||
383 | 3 => Some(&pad.right()),
|
||||
| ++
|
||||
|
||||
error[E0615]: attempted to take value of method `a` on type `&dyn PadBridge`
|
||||
--> crates/prometeu-core/src/prometeu_os/prometeu_os.rs:384:28
|
||||
|
|
||||
384 | 4 => Some(&pad.a),
|
||||
| ^ method, not a field
|
||||
|
|
||||
help: use parentheses to call the method
|
||||
|
|
||||
384 | 4 => Some(&pad.a()),
|
||||
| ++
|
||||
|
||||
error[E0615]: attempted to take value of method `b` on type `&dyn PadBridge`
|
||||
--> crates/prometeu-core/src/prometeu_os/prometeu_os.rs:385:28
|
||||
|
|
||||
385 | 5 => Some(&pad.b),
|
||||
| ^ method, not a field
|
||||
|
|
||||
help: use parentheses to call the method
|
||||
|
|
||||
385 | 5 => Some(&pad.b()),
|
||||
| ++
|
||||
|
||||
error[E0615]: attempted to take value of method `x` on type `&dyn PadBridge`
|
||||
--> crates/prometeu-core/src/prometeu_os/prometeu_os.rs:386:28
|
||||
|
|
||||
386 | 6 => Some(&pad.x),
|
||||
| ^ method, not a field
|
||||
|
|
||||
help: use parentheses to call the method
|
||||
|
|
||||
386 | 6 => Some(&pad.x()),
|
||||
| ++
|
||||
|
||||
error[E0615]: attempted to take value of method `y` on type `&dyn PadBridge`
|
||||
--> crates/prometeu-core/src/prometeu_os/prometeu_os.rs:387:28
|
||||
|
|
||||
387 | 7 => Some(&pad.y),
|
||||
| ^ method, not a field
|
||||
|
|
||||
help: use parentheses to call the method
|
||||
|
|
||||
387 | 7 => Some(&pad.y()),
|
||||
| ++
|
||||
|
||||
error[E0615]: attempted to take value of method `l` on type `&dyn PadBridge`
|
||||
--> crates/prometeu-core/src/prometeu_os/prometeu_os.rs:388:28
|
||||
|
|
||||
388 | 8 => Some(&pad.l),
|
||||
| ^ method, not a field
|
||||
|
|
||||
help: use parentheses to call the method
|
||||
|
|
||||
388 | 8 => Some(&pad.l()),
|
||||
| ++
|
||||
|
||||
error[E0615]: attempted to take value of method `r` on type `&dyn PadBridge`
|
||||
--> crates/prometeu-core/src/prometeu_os/prometeu_os.rs:389:28
|
||||
|
|
||||
389 | 9 => Some(&pad.r),
|
||||
| ^ method, not a field
|
||||
|
|
||||
help: use parentheses to call the method
|
||||
|
|
||||
389 | 9 => Some(&pad.r()),
|
||||
| ++
|
||||
|
||||
error[E0615]: attempted to take value of method `start` on type `&dyn PadBridge`
|
||||
--> crates/prometeu-core/src/prometeu_os/prometeu_os.rs:390:29
|
||||
|
|
||||
390 | 10 => Some(&pad.start),
|
||||
| ^^^^^ method, not a field
|
||||
|
|
||||
help: use parentheses to call the method
|
||||
|
|
||||
390 | 10 => Some(&pad.start()),
|
||||
| ++
|
||||
|
||||
error[E0615]: attempted to take value of method `select` on type `&dyn PadBridge`
|
||||
--> crates/prometeu-core/src/prometeu_os/prometeu_os.rs:391:29
|
||||
|
|
||||
391 | 11 => Some(&pad.select),
|
||||
| ^^^^^^ method, not a field
|
||||
|
|
||||
help: use parentheses to call the method
|
||||
|
|
||||
391 | 11 => Some(&pad.select()),
|
||||
| ++
|
||||
|
||||
error[E0615]: attempted to take value of method `up` on type `&dyn PadBridge`
|
||||
--> crates/prometeu-core/src/prometeu_os/prometeu_os.rs:398:27
|
||||
|
|
||||
398 | 0 => hw.pad().up.down,
|
||||
| ^^ method, not a field
|
||||
|
|
||||
help: use parentheses to call the method
|
||||
|
|
||||
398 | 0 => hw.pad().up().down,
|
||||
| ++
|
||||
|
||||
error[E0615]: attempted to take value of method `down` on type `&dyn PadBridge`
|
||||
--> crates/prometeu-core/src/prometeu_os/prometeu_os.rs:399:27
|
||||
|
|
||||
399 | 1 => hw.pad().down.down,
|
||||
| ^^^^ method, not a field
|
||||
|
|
||||
help: use parentheses to call the method
|
||||
|
|
||||
399 | 1 => hw.pad().down().down,
|
||||
| ++
|
||||
|
||||
error[E0615]: attempted to take value of method `left` on type `&dyn PadBridge`
|
||||
--> crates/prometeu-core/src/prometeu_os/prometeu_os.rs:400:27
|
||||
|
|
||||
400 | 2 => hw.pad().left.down,
|
||||
| ^^^^ method, not a field
|
||||
|
|
||||
help: use parentheses to call the method
|
||||
|
|
||||
400 | 2 => hw.pad().left().down,
|
||||
| ++
|
||||
|
||||
error[E0615]: attempted to take value of method `right` on type `&dyn PadBridge`
|
||||
--> crates/prometeu-core/src/prometeu_os/prometeu_os.rs:401:27
|
||||
|
|
||||
401 | 3 => hw.pad().right.down,
|
||||
| ^^^^^ method, not a field
|
||||
|
|
||||
help: use parentheses to call the method
|
||||
|
|
||||
401 | 3 => hw.pad().right().down,
|
||||
| ++
|
||||
|
||||
error[E0615]: attempted to take value of method `a` on type `&dyn PadBridge`
|
||||
--> crates/prometeu-core/src/prometeu_os/prometeu_os.rs:402:27
|
||||
|
|
||||
402 | 4 => hw.pad().a.down,
|
||||
| ^ method, not a field
|
||||
|
|
||||
help: use parentheses to call the method
|
||||
|
|
||||
402 | 4 => hw.pad().a().down,
|
||||
| ++
|
||||
|
||||
error[E0615]: attempted to take value of method `b` on type `&dyn PadBridge`
|
||||
--> crates/prometeu-core/src/prometeu_os/prometeu_os.rs:403:27
|
||||
|
|
||||
403 | 5 => hw.pad().b.down,
|
||||
| ^ method, not a field
|
||||
|
|
||||
help: use parentheses to call the method
|
||||
|
|
||||
403 | 5 => hw.pad().b().down,
|
||||
| ++
|
||||
|
||||
error[E0615]: attempted to take value of method `x` on type `&dyn PadBridge`
|
||||
--> crates/prometeu-core/src/prometeu_os/prometeu_os.rs:404:27
|
||||
|
|
||||
404 | 6 => hw.pad().x.down,
|
||||
| ^ method, not a field
|
||||
|
|
||||
help: use parentheses to call the method
|
||||
|
|
||||
404 | 6 => hw.pad().x().down,
|
||||
| ++
|
||||
|
||||
error[E0615]: attempted to take value of method `y` on type `&dyn PadBridge`
|
||||
--> crates/prometeu-core/src/prometeu_os/prometeu_os.rs:405:27
|
||||
|
|
||||
405 | 7 => hw.pad().y.down,
|
||||
| ^ method, not a field
|
||||
|
|
||||
help: use parentheses to call the method
|
||||
|
|
||||
405 | 7 => hw.pad().y().down,
|
||||
| ++
|
||||
|
||||
error[E0615]: attempted to take value of method `l` on type `&dyn PadBridge`
|
||||
--> crates/prometeu-core/src/prometeu_os/prometeu_os.rs:406:27
|
||||
|
|
||||
406 | 8 => hw.pad().l.down,
|
||||
| ^ method, not a field
|
||||
|
|
||||
help: use parentheses to call the method
|
||||
|
|
||||
406 | 8 => hw.pad().l().down,
|
||||
| ++
|
||||
|
||||
error[E0615]: attempted to take value of method `r` on type `&dyn PadBridge`
|
||||
--> crates/prometeu-core/src/prometeu_os/prometeu_os.rs:407:27
|
||||
|
|
||||
407 | 9 => hw.pad().r.down,
|
||||
| ^ method, not a field
|
||||
|
|
||||
help: use parentheses to call the method
|
||||
|
|
||||
407 | 9 => hw.pad().r().down,
|
||||
| ++
|
||||
|
||||
error[E0615]: attempted to take value of method `start` on type `&dyn PadBridge`
|
||||
--> crates/prometeu-core/src/prometeu_os/prometeu_os.rs:408:28
|
||||
|
|
||||
408 | 10 => hw.pad().start.down,
|
||||
| ^^^^^ method, not a field
|
||||
|
|
||||
help: use parentheses to call the method
|
||||
|
|
||||
408 | 10 => hw.pad().start().down,
|
||||
| ++
|
||||
|
||||
error[E0615]: attempted to take value of method `select` on type `&dyn PadBridge`
|
||||
--> crates/prometeu-core/src/prometeu_os/prometeu_os.rs:409:28
|
||||
|
|
||||
409 | 11 => hw.pad().select.down,
|
||||
| ^^^^^^ method, not a field
|
||||
|
|
||||
help: use parentheses to call the method
|
||||
|
|
||||
409 | 11 => hw.pad().select().down,
|
||||
| ++
|
||||
|
||||
error[E0609]: no field `sprites` on type `&mut dyn GfxBridge`
|
||||
--> crates/prometeu-core/src/prometeu_os/prometeu_os.rs:963:34
|
||||
|
|
||||
963 | hw.gfx_mut().sprites[index] = crate::model::Sprite {
|
||||
| ^^^^^^^ unknown field
|
||||
|
||||
error[E0615]: attempted to take value of method `x` on type `&dyn TouchBridge`
|
||||
--> crates/prometeu-core/src/prometeu_os/prometeu_os.rs:1031:41
|
||||
|
|
||||
1031 | ret.push_int(hw.touch().x as i64);
|
||||
| ^ method, not a field
|
||||
|
|
||||
help: use parentheses to call the method
|
||||
|
|
||||
1031 | ret.push_int(hw.touch().x() as i64);
|
||||
| ++
|
||||
|
||||
error[E0615]: attempted to take value of method `y` on type `&dyn TouchBridge`
|
||||
--> crates/prometeu-core/src/prometeu_os/prometeu_os.rs:1035:41
|
||||
|
|
||||
1035 | ret.push_int(hw.touch().y as i64);
|
||||
| ^ method, not a field
|
||||
|
|
||||
help: use parentheses to call the method
|
||||
|
|
||||
1035 | ret.push_int(hw.touch().y() as i64);
|
||||
| ++
|
||||
|
||||
error[E0615]: attempted to take value of method `f` on type `&dyn TouchBridge`
|
||||
--> crates/prometeu-core/src/prometeu_os/prometeu_os.rs:1039:42
|
||||
|
|
||||
1039 | ret.push_bool(hw.touch().f.down);
|
||||
| ^ method, not a field
|
||||
|
|
||||
help: use parentheses to call the method
|
||||
|
|
||||
1039 | ret.push_bool(hw.touch().f().down);
|
||||
| ++
|
||||
|
||||
error[E0615]: attempted to take value of method `f` on type `&dyn TouchBridge`
|
||||
--> crates/prometeu-core/src/prometeu_os/prometeu_os.rs:1043:42
|
||||
|
|
||||
1043 | ret.push_bool(hw.touch().f.pressed);
|
||||
| ^ method, not a field
|
||||
|
|
||||
help: use parentheses to call the method
|
||||
|
|
||||
1043 | ret.push_bool(hw.touch().f().pressed);
|
||||
| ++
|
||||
|
||||
error[E0615]: attempted to take value of method `f` on type `&dyn TouchBridge`
|
||||
--> crates/prometeu-core/src/prometeu_os/prometeu_os.rs:1047:42
|
||||
|
|
||||
1047 | ret.push_bool(hw.touch().f.released);
|
||||
| ^ method, not a field
|
||||
|
|
||||
help: use parentheses to call the method
|
||||
|
|
||||
1047 | ret.push_bool(hw.touch().f().released);
|
||||
| ++
|
||||
|
||||
error[E0615]: attempted to take value of method `f` on type `&dyn TouchBridge`
|
||||
--> crates/prometeu-core/src/prometeu_os/prometeu_os.rs:1051:41
|
||||
|
|
||||
1051 | ret.push_int(hw.touch().f.hold_frames as i64);
|
||||
| ^ method, not a field
|
||||
|
|
||||
help: use parentheses to call the method
|
||||
|
|
||||
1051 | ret.push_int(hw.touch().f().hold_frames as i64);
|
||||
| ++
|
||||
|
||||
error[E0615]: attempted to take value of method `up` on type `&dyn PadBridge`
|
||||
--> crates/prometeu-core/src/prometeu_os/prometeu_os.rs:1057:26
|
||||
|
|
||||
1057 | &pad.up, &pad.down, &pad.left, &pad.right,
|
||||
| ^^ method, not a field
|
||||
|
|
||||
help: use parentheses to call the method
|
||||
|
|
||||
1057 | &pad.up(), &pad.down, &pad.left, &pad.right,
|
||||
| ++
|
||||
|
||||
error[E0615]: attempted to take value of method `down` on type `&dyn PadBridge`
|
||||
--> crates/prometeu-core/src/prometeu_os/prometeu_os.rs:1057:35
|
||||
|
|
||||
1057 | &pad.up, &pad.down, &pad.left, &pad.right,
|
||||
| ^^^^ method, not a field
|
||||
|
|
||||
help: use parentheses to call the method
|
||||
|
|
||||
1057 | &pad.up, &pad.down(), &pad.left, &pad.right,
|
||||
| ++
|
||||
|
||||
error[E0615]: attempted to take value of method `left` on type `&dyn PadBridge`
|
||||
--> crates/prometeu-core/src/prometeu_os/prometeu_os.rs:1057:46
|
||||
|
|
||||
1057 | &pad.up, &pad.down, &pad.left, &pad.right,
|
||||
| ^^^^ method, not a field
|
||||
|
|
||||
help: use parentheses to call the method
|
||||
|
|
||||
1057 | &pad.up, &pad.down, &pad.left(), &pad.right,
|
||||
| ++
|
||||
|
||||
error[E0615]: attempted to take value of method `right` on type `&dyn PadBridge`
|
||||
--> crates/prometeu-core/src/prometeu_os/prometeu_os.rs:1057:57
|
||||
|
|
||||
1057 | &pad.up, &pad.down, &pad.left, &pad.right,
|
||||
| ^^^^^ method, not a field
|
||||
|
|
||||
help: use parentheses to call the method
|
||||
|
|
||||
1057 | &pad.up, &pad.down, &pad.left, &pad.right(),
|
||||
| ++
|
||||
|
||||
error[E0615]: attempted to take value of method `a` on type `&dyn PadBridge`
|
||||
--> crates/prometeu-core/src/prometeu_os/prometeu_os.rs:1058:26
|
||||
|
|
||||
1058 | &pad.a, &pad.b, &pad.x, &pad.y,
|
||||
| ^ method, not a field
|
||||
|
|
||||
help: use parentheses to call the method
|
||||
|
|
||||
1058 | &pad.a(), &pad.b, &pad.x, &pad.y,
|
||||
| ++
|
||||
|
||||
error[E0615]: attempted to take value of method `b` on type `&dyn PadBridge`
|
||||
--> crates/prometeu-core/src/prometeu_os/prometeu_os.rs:1058:34
|
||||
|
|
||||
1058 | &pad.a, &pad.b, &pad.x, &pad.y,
|
||||
| ^ method, not a field
|
||||
|
|
||||
help: use parentheses to call the method
|
||||
|
|
||||
1058 | &pad.a, &pad.b(), &pad.x, &pad.y,
|
||||
| ++
|
||||
|
||||
error[E0615]: attempted to take value of method `x` on type `&dyn PadBridge`
|
||||
--> crates/prometeu-core/src/prometeu_os/prometeu_os.rs:1058:42
|
||||
|
|
||||
1058 | &pad.a, &pad.b, &pad.x, &pad.y,
|
||||
| ^ method, not a field
|
||||
|
|
||||
help: use parentheses to call the method
|
||||
|
|
||||
1058 | &pad.a, &pad.b, &pad.x(), &pad.y,
|
||||
| ++
|
||||
|
||||
error[E0615]: attempted to take value of method `y` on type `&dyn PadBridge`
|
||||
--> crates/prometeu-core/src/prometeu_os/prometeu_os.rs:1058:50
|
||||
|
|
||||
1058 | &pad.a, &pad.b, &pad.x, &pad.y,
|
||||
| ^ method, not a field
|
||||
|
|
||||
help: use parentheses to call the method
|
||||
|
|
||||
1058 | &pad.a, &pad.b, &pad.x, &pad.y(),
|
||||
| ++
|
||||
|
||||
error[E0615]: attempted to take value of method `l` on type `&dyn PadBridge`
|
||||
--> crates/prometeu-core/src/prometeu_os/prometeu_os.rs:1059:26
|
||||
|
|
||||
1059 | &pad.l, &pad.r, &pad.start, &pad.select,
|
||||
| ^ method, not a field
|
||||
|
|
||||
help: use parentheses to call the method
|
||||
|
|
||||
1059 | &pad.l(), &pad.r, &pad.start, &pad.select,
|
||||
| ++
|
||||
|
||||
error[E0615]: attempted to take value of method `r` on type `&dyn PadBridge`
|
||||
--> crates/prometeu-core/src/prometeu_os/prometeu_os.rs:1059:34
|
||||
|
|
||||
1059 | &pad.l, &pad.r, &pad.start, &pad.select,
|
||||
| ^ method, not a field
|
||||
|
|
||||
help: use parentheses to call the method
|
||||
|
|
||||
1059 | &pad.l, &pad.r(), &pad.start, &pad.select,
|
||||
| ++
|
||||
|
||||
error[E0615]: attempted to take value of method `start` on type `&dyn PadBridge`
|
||||
--> crates/prometeu-core/src/prometeu_os/prometeu_os.rs:1059:42
|
||||
|
|
||||
1059 | &pad.l, &pad.r, &pad.start, &pad.select,
|
||||
| ^^^^^ method, not a field
|
||||
|
|
||||
help: use parentheses to call the method
|
||||
|
|
||||
1059 | &pad.l, &pad.r, &pad.start(), &pad.select,
|
||||
| ++
|
||||
|
||||
error[E0615]: attempted to take value of method `select` on type `&dyn PadBridge`
|
||||
--> crates/prometeu-core/src/prometeu_os/prometeu_os.rs:1059:54
|
||||
|
|
||||
1059 | &pad.l, &pad.r, &pad.start, &pad.select,
|
||||
| ^^^^^^ method, not a field
|
||||
|
|
||||
help: use parentheses to call the method
|
||||
|
|
||||
1059 | &pad.l, &pad.r, &pad.start, &pad.select(),
|
||||
| ++
|
||||
|
||||
error[E0615]: attempted to take value of method `f` on type `&dyn TouchBridge`
|
||||
--> crates/prometeu-core/src/prometeu_os/prometeu_os.rs:1070:37
|
||||
|
|
||||
1070 | ret.push_bool(touch.f.pressed);
|
||||
| ^ method, not a field
|
||||
|
|
||||
help: use parentheses to call the method
|
||||
|
|
||||
1070 | ret.push_bool(touch.f().pressed);
|
||||
| ++
|
||||
|
||||
error[E0615]: attempted to take value of method `f` on type `&dyn TouchBridge`
|
||||
--> crates/prometeu-core/src/prometeu_os/prometeu_os.rs:1071:37
|
||||
|
|
||||
1071 | ret.push_bool(touch.f.released);
|
||||
| ^ method, not a field
|
||||
|
|
||||
help: use parentheses to call the method
|
||||
|
|
||||
1071 | ret.push_bool(touch.f().released);
|
||||
| ++
|
||||
|
||||
error[E0615]: attempted to take value of method `f` on type `&dyn TouchBridge`
|
||||
--> crates/prometeu-core/src/prometeu_os/prometeu_os.rs:1072:37
|
||||
|
|
||||
1072 | ret.push_bool(touch.f.down);
|
||||
| ^ method, not a field
|
||||
|
|
||||
help: use parentheses to call the method
|
||||
|
|
||||
1072 | ret.push_bool(touch.f().down);
|
||||
| ++
|
||||
|
||||
error[E0615]: attempted to take value of method `f` on type `&dyn TouchBridge`
|
||||
--> crates/prometeu-core/src/prometeu_os/prometeu_os.rs:1073:36
|
||||
|
|
||||
1073 | ret.push_int(touch.f.hold_frames as i64);
|
||||
| ^ method, not a field
|
||||
|
|
||||
help: use parentheses to call the method
|
||||
|
|
||||
1073 | ret.push_int(touch.f().hold_frames as i64);
|
||||
| ++
|
||||
|
||||
error[E0615]: attempted to take value of method `x` on type `&dyn TouchBridge`
|
||||
--> crates/prometeu-core/src/prometeu_os/prometeu_os.rs:1074:36
|
||||
|
|
||||
1074 | ret.push_int(touch.x as i64);
|
||||
| ^ method, not a field
|
||||
|
|
||||
help: use parentheses to call the method
|
||||
|
|
||||
1074 | ret.push_int(touch.x() as i64);
|
||||
| ++
|
||||
|
||||
error[E0615]: attempted to take value of method `y` on type `&dyn TouchBridge`
|
||||
--> crates/prometeu-core/src/prometeu_os/prometeu_os.rs:1075:36
|
||||
|
|
||||
1075 | ret.push_int(touch.y as i64);
|
||||
| ^ method, not a field
|
||||
|
|
||||
help: use parentheses to call the method
|
||||
|
|
||||
1075 | ret.push_int(touch.y() as i64);
|
||||
| ++
|
||||
|
||||
error[E0615]: attempted to take value of method `a` on type `&dyn PadBridge`
|
||||
--> crates/prometeu-core/src/prometeu_hub/prometeu_hub.rs:28:21
|
||||
|
|
||||
28 | if hw.pad().a.pressed {
|
||||
| ^ method, not a field
|
||||
|
|
||||
help: use parentheses to call the method
|
||||
|
|
||||
28 | if hw.pad().a().pressed {
|
||||
| ++
|
||||
|
||||
error[E0615]: attempted to take value of method `b` on type `&dyn PadBridge`
|
||||
--> crates/prometeu-core/src/prometeu_hub/prometeu_hub.rs:31:28
|
||||
|
|
||||
31 | } else if hw.pad().b.pressed {
|
||||
| ^ method, not a field
|
||||
|
|
||||
help: use parentheses to call the method
|
||||
|
|
||||
31 | } else if hw.pad().b().pressed {
|
||||
| ++
|
||||
|
||||
error[E0615]: attempted to take value of method `x` on type `&dyn PadBridge`
|
||||
--> crates/prometeu-core/src/prometeu_hub/prometeu_hub.rs:34:28
|
||||
|
|
||||
34 | } else if hw.pad().x.pressed {
|
||||
| ^ method, not a field
|
||||
|
|
||||
help: use parentheses to call the method
|
||||
|
|
||||
34 | } else if hw.pad().x().pressed {
|
||||
| ++
|
||||
|
||||
error[E0615]: attempted to take value of method `y` on type `&dyn PadBridge`
|
||||
--> crates/prometeu-core/src/prometeu_hub/prometeu_hub.rs:37:28
|
||||
|
|
||||
37 | } else if hw.pad().y.pressed {
|
||||
| ^ method, not a field
|
||||
|
|
||||
help: use parentheses to call the method
|
||||
|
|
||||
37 | } else if hw.pad().y().pressed {
|
||||
| ++
|
||||
|
||||
Some errors have detailed explanations: E0609, E0615.
|
||||
For more information about an error, try `rustc --explain E0609`.
|
||||
error: could not compile `prometeu-core` (lib) due to 55 previous errors
|
||||
@ -1,69 +0,0 @@
|
||||
Checking prometeu-core v0.1.0 (/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/crates/prometeu-core)
|
||||
error[E0615]: attempted to take value of method `start` on type `&dyn PadBridge`
|
||||
--> crates/prometeu-core/src/firmware/firmware_step_hub_home.rs:20:29
|
||||
|
|
||||
20 | if ctx.hw.pad().start.down {
|
||||
| ^^^^^ method, not a field
|
||||
|
|
||||
help: use parentheses to call the method
|
||||
|
|
||||
20 | if ctx.hw.pad().start().down {
|
||||
| ++
|
||||
|
||||
error[E0615]: attempted to take value of method `start` on type `&dyn PadBridge`
|
||||
--> crates/prometeu-core/src/firmware/firmware_step_crash_screen.rs:27:25
|
||||
|
|
||||
27 | if ctx.hw.pad().start.down {
|
||||
| ^^^^^ method, not a field
|
||||
|
|
||||
help: use parentheses to call the method
|
||||
|
|
||||
27 | if ctx.hw.pad().start().down {
|
||||
| ++
|
||||
|
||||
error[E0615]: attempted to take value of method `a` on type `&dyn PadBridge`
|
||||
--> crates/prometeu-core/src/prometeu_hub/prometeu_hub.rs:28:21
|
||||
|
|
||||
28 | if hw.pad().a.pressed {
|
||||
| ^ method, not a field
|
||||
|
|
||||
help: use parentheses to call the method
|
||||
|
|
||||
28 | if hw.pad().a().pressed {
|
||||
| ++
|
||||
|
||||
error[E0615]: attempted to take value of method `b` on type `&dyn PadBridge`
|
||||
--> crates/prometeu-core/src/prometeu_hub/prometeu_hub.rs:31:28
|
||||
|
|
||||
31 | } else if hw.pad().b.pressed {
|
||||
| ^ method, not a field
|
||||
|
|
||||
help: use parentheses to call the method
|
||||
|
|
||||
31 | } else if hw.pad().b().pressed {
|
||||
| ++
|
||||
|
||||
error[E0615]: attempted to take value of method `x` on type `&dyn PadBridge`
|
||||
--> crates/prometeu-core/src/prometeu_hub/prometeu_hub.rs:34:28
|
||||
|
|
||||
34 | } else if hw.pad().x.pressed {
|
||||
| ^ method, not a field
|
||||
|
|
||||
help: use parentheses to call the method
|
||||
|
|
||||
34 | } else if hw.pad().x().pressed {
|
||||
| ++
|
||||
|
||||
error[E0615]: attempted to take value of method `y` on type `&dyn PadBridge`
|
||||
--> crates/prometeu-core/src/prometeu_hub/prometeu_hub.rs:37:28
|
||||
|
|
||||
37 | } else if hw.pad().y.pressed {
|
||||
| ^ method, not a field
|
||||
|
|
||||
help: use parentheses to call the method
|
||||
|
|
||||
37 | } else if hw.pad().y().pressed {
|
||||
| ++
|
||||
|
||||
For more information about this error, try `rustc --explain E0615`.
|
||||
error: could not compile `prometeu-core` (lib) due to 6 previous errors
|
||||
@ -7,3 +7,4 @@ license.workspace = true
|
||||
[dependencies]
|
||||
serde = { version = "1.0.228", features = ["derive"] }
|
||||
serde_json = "1.0.149"
|
||||
prometeu-bytecode = { path = "../prometeu-bytecode" }
|
||||
|
||||
@ -6,8 +6,4 @@ pub mod telemetry;
|
||||
pub mod debugger_protocol;
|
||||
pub mod syscalls;
|
||||
|
||||
// Tipos da VM que fazem parte do contrato (ex.: inspeção de pilha pelo debugger)
|
||||
pub mod virtual_machine {
|
||||
mod value;
|
||||
pub use value::Value;
|
||||
}
|
||||
pub mod virtual_machine;
|
||||
|
||||
12
crates/prometeu-abi/src/virtual_machine/mod.rs
Normal file
12
crates/prometeu-abi/src/virtual_machine/mod.rs
Normal file
@ -0,0 +1,12 @@
|
||||
mod value;
|
||||
mod vm_init_error;
|
||||
|
||||
pub use value::Value;
|
||||
pub use vm_init_error::VmInitError;
|
||||
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub enum VmFault {
|
||||
Trap(u32, String),
|
||||
Panic(String),
|
||||
Unavailable,
|
||||
}
|
||||
8
crates/prometeu-abi/src/virtual_machine/vm_init_error.rs
Normal file
8
crates/prometeu-abi/src/virtual_machine/vm_init_error.rs
Normal file
@ -0,0 +1,8 @@
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum VmInitError<E> {
|
||||
InvalidFormat,
|
||||
UnsupportedFormat,
|
||||
PbsV0LoadFailed(prometeu_bytecode::LoadError),
|
||||
EntrypointNotFound,
|
||||
VerificationFailed(E),
|
||||
}
|
||||
@ -9,4 +9,5 @@ serde = { version = "1.0.228", features = ["derive"] }
|
||||
serde_json = "1.0.149"
|
||||
prometeu-bytecode = { path = "../prometeu-bytecode" }
|
||||
prometeu-abi = { path = "../prometeu-abi" }
|
||||
prometeu-hardware-contract = { path = "../prometeu-hardware-contract" }
|
||||
url = "2.5.8"
|
||||
@ -1,146 +0,0 @@
|
||||
use crate::model::AppMode;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::virtual_machine::Value;
|
||||
|
||||
pub const DEVTOOLS_PROTOCOL_VERSION: u32 = 1;
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
#[serde(tag = "type")]
|
||||
pub enum DebugCommand {
|
||||
#[serde(rename = "ok")]
|
||||
Ok,
|
||||
#[serde(rename = "start")]
|
||||
Start,
|
||||
#[serde(rename = "pause")]
|
||||
Pause,
|
||||
#[serde(rename = "resume")]
|
||||
Resume,
|
||||
#[serde(rename = "step")]
|
||||
Step,
|
||||
#[serde(rename = "stepFrame")]
|
||||
StepFrame,
|
||||
#[serde(rename = "getState")]
|
||||
GetState,
|
||||
#[serde(rename = "setBreakpoint")]
|
||||
SetBreakpoint { pc: usize },
|
||||
#[serde(rename = "listBreakpoints")]
|
||||
ListBreakpoints,
|
||||
#[serde(rename = "clearBreakpoint")]
|
||||
ClearBreakpoint { pc: usize },
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
#[serde(tag = "type")]
|
||||
pub enum DebugResponse {
|
||||
#[serde(rename = "handshake")]
|
||||
Handshake {
|
||||
protocol_version: u32,
|
||||
runtime_version: String,
|
||||
cartridge: HandshakeCartridge,
|
||||
},
|
||||
#[serde(rename = "getState")]
|
||||
GetState {
|
||||
pc: usize,
|
||||
stack_top: Vec<Value>,
|
||||
frame_index: u64,
|
||||
app_id: u32,
|
||||
},
|
||||
#[serde(rename = "breakpoints")]
|
||||
Breakpoints {
|
||||
pcs: Vec<usize>,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct HandshakeCartridge {
|
||||
pub app_id: u32,
|
||||
pub title: String,
|
||||
pub app_version: String,
|
||||
pub app_mode: AppMode,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
#[serde(tag = "event")]
|
||||
pub enum DebugEvent {
|
||||
#[serde(rename = "breakpointHit")]
|
||||
BreakpointHit {
|
||||
pc: usize,
|
||||
frame_index: u64,
|
||||
},
|
||||
#[serde(rename = "log")]
|
||||
Log {
|
||||
level: String,
|
||||
source: String,
|
||||
msg: String,
|
||||
},
|
||||
#[serde(rename = "telemetry")]
|
||||
Telemetry {
|
||||
frame_index: u64,
|
||||
vm_steps: u32,
|
||||
syscalls: u32,
|
||||
cycles: u64,
|
||||
cycles_budget: u64,
|
||||
host_cpu_time_us: u64,
|
||||
violations: u32,
|
||||
gfx_used_bytes: usize,
|
||||
gfx_inflight_bytes: usize,
|
||||
gfx_slots_occupied: u32,
|
||||
audio_used_bytes: usize,
|
||||
audio_inflight_bytes: usize,
|
||||
audio_slots_occupied: u32,
|
||||
},
|
||||
#[serde(rename = "cert")]
|
||||
Cert {
|
||||
rule: String,
|
||||
used: u64,
|
||||
limit: u64,
|
||||
frame_index: u64,
|
||||
},
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::virtual_machine::Value;
|
||||
|
||||
#[test]
|
||||
fn test_telemetry_event_serialization() {
|
||||
let event = DebugEvent::Telemetry {
|
||||
frame_index: 10,
|
||||
vm_steps: 100,
|
||||
syscalls: 5,
|
||||
cycles: 5000,
|
||||
cycles_budget: 10000,
|
||||
host_cpu_time_us: 1200,
|
||||
violations: 0,
|
||||
gfx_used_bytes: 1024,
|
||||
gfx_inflight_bytes: 0,
|
||||
gfx_slots_occupied: 1,
|
||||
audio_used_bytes: 2048,
|
||||
audio_inflight_bytes: 0,
|
||||
audio_slots_occupied: 2,
|
||||
};
|
||||
|
||||
let json = serde_json::to_string(&event).unwrap();
|
||||
assert!(json.contains("\"event\":\"telemetry\""));
|
||||
assert!(json.contains("\"cycles\":5000"));
|
||||
assert!(json.contains("\"cycles_budget\":10000"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_get_state_serialization() {
|
||||
let resp = DebugResponse::GetState {
|
||||
pc: 42,
|
||||
stack_top: vec![Value::Int64(10), Value::String("test".into()), Value::Boolean(true)],
|
||||
frame_index: 5,
|
||||
app_id: 1,
|
||||
};
|
||||
|
||||
let json = serde_json::to_string(&resp).unwrap();
|
||||
assert!(json.contains("\"type\":\"getState\""));
|
||||
assert!(json.contains("\"pc\":42"));
|
||||
assert!(json.contains("\"stack_top\":[10,\"test\",true]"));
|
||||
assert!(json.contains("\"frame_index\":5"));
|
||||
assert!(json.contains("\"app_id\":1"));
|
||||
}
|
||||
}
|
||||
@ -136,7 +136,7 @@ struct LoadHandleInfo {
|
||||
status: LoadStatus,
|
||||
}
|
||||
|
||||
impl AssetBridge for AssetManager {
|
||||
impl prometeu_hardware_contract::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) }
|
||||
|
||||
@ -7,15 +7,8 @@ pub const MAX_CHANNELS: usize = 16;
|
||||
/// Standard sample rate for the final audio output.
|
||||
pub const OUTPUT_SAMPLE_RATE: u32 = 48000;
|
||||
|
||||
/// Defines if a sample should stop at the end or repeat indefinitely.
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Default)]
|
||||
pub enum LoopMode {
|
||||
/// Play once and stop.
|
||||
#[default]
|
||||
Off,
|
||||
/// Return to the start (or loop_start) when reaching the end.
|
||||
On,
|
||||
}
|
||||
/// Looping mode for samples (re-exported from the hardware contract).
|
||||
pub use prometeu_hardware_contract::LoopMode;
|
||||
|
||||
/// State of a single playback voice (channel).
|
||||
///
|
||||
@ -130,9 +123,15 @@ pub struct Audio {
|
||||
pub sound_banks: Arc<dyn SoundBankPoolAccess>,
|
||||
}
|
||||
|
||||
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: LoopMode) { self.play(bank_id, sample_id, voice_id, volume, pan, pitch, priority, loop_mode) }
|
||||
fn play_sample(&mut self, sample: Arc<Sample>, voice_id: usize, volume: u8, pan: u8, pitch: f64, priority: u8, loop_mode: LoopMode) { self.play_sample(sample, voice_id, volume, pan, pitch, priority, loop_mode) }
|
||||
impl prometeu_hardware_contract::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)
|
||||
}
|
||||
fn play_sample(&mut self, sample: Arc<Sample>, 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_sample(sample, voice_id, volume, pan, pitch, priority, lm)
|
||||
}
|
||||
fn stop(&mut self, voice_id: usize) { self.stop(voice_id) }
|
||||
fn set_volume(&mut self, voice_id: usize, volume: u8) { self.set_volume(voice_id, volume) }
|
||||
fn set_pan(&mut self, voice_id: usize, pan: u8) { self.set_pan(voice_id, pan) }
|
||||
|
||||
@ -114,11 +114,11 @@ pub struct Gfx {
|
||||
priority_buckets: [Vec<usize>; 5],
|
||||
}
|
||||
|
||||
impl GfxBridge for Gfx {
|
||||
impl prometeu_hardware_contract::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) }
|
||||
fn fill_rect_blend(&mut self, x: i32, y: i32, w: i32, h: i32, color: Color, mode: BlendMode) { self.fill_rect_blend(x, y, w, h, color, mode) }
|
||||
fn fill_rect_blend(&mut self, x: i32, y: i32, w: i32, h: i32, color: Color, mode: prometeu_hardware_contract::BlendMode) { let m = match mode { prometeu_hardware_contract::BlendMode::None => BlendMode::None, prometeu_hardware_contract::BlendMode::Half => BlendMode::Half, prometeu_hardware_contract::BlendMode::HalfPlus => BlendMode::HalfPlus, prometeu_hardware_contract::BlendMode::HalfMinus => BlendMode::HalfMinus, prometeu_hardware_contract::BlendMode::Full => BlendMode::Full }; self.fill_rect_blend(x, y, w, h, color, m) }
|
||||
fn fill_rect(&mut self, x: i32, y: i32, w: i32, h: i32, color: Color) { self.fill_rect(x, y, w, h, color) }
|
||||
fn draw_pixel(&mut self, x: i32, y: i32, color: Color) { self.draw_pixel(x, y, color) }
|
||||
fn draw_line(&mut self, x0: i32, y0: i32, x1: i32, y1: i32, color: Color) { self.draw_line(x0, y0, x1, y1, color) }
|
||||
|
||||
@ -2,34 +2,19 @@ mod asset;
|
||||
mod gfx;
|
||||
mod pad;
|
||||
mod touch;
|
||||
mod input_signal;
|
||||
mod audio;
|
||||
mod memory_banks;
|
||||
pub mod hardware;
|
||||
|
||||
pub use crate::model::HandleId;
|
||||
pub use asset::{AssetBridge, AssetManager};
|
||||
pub use audio::{Audio, AudioBridge, AudioCommand, Channel, LoopMode, MAX_CHANNELS, OUTPUT_SAMPLE_RATE};
|
||||
pub use gfx::BlendMode;
|
||||
pub use gfx::{Gfx, GfxBridge};
|
||||
pub use input_signal::InputSignals;
|
||||
pub use asset::AssetManager;
|
||||
pub use audio::{Audio, AudioCommand, Channel, MAX_CHANNELS, OUTPUT_SAMPLE_RATE};
|
||||
pub use gfx::Gfx;
|
||||
pub use memory_banks::MemoryBanks;
|
||||
pub use pad::{Pad, PadBridge};
|
||||
pub use touch::{Touch, TouchBridge};
|
||||
pub use pad::Pad;
|
||||
pub use touch::Touch;
|
||||
|
||||
pub trait HardwareBridge {
|
||||
fn gfx(&self) -> &dyn GfxBridge;
|
||||
fn gfx_mut(&mut self) -> &mut dyn GfxBridge;
|
||||
|
||||
fn audio(&self) -> &dyn AudioBridge;
|
||||
fn audio_mut(&mut self) -> &mut dyn AudioBridge;
|
||||
|
||||
fn pad(&self) -> &dyn PadBridge;
|
||||
fn pad_mut(&mut self) -> &mut dyn PadBridge;
|
||||
|
||||
fn touch(&self) -> &dyn TouchBridge;
|
||||
fn touch_mut(&mut self) -> &mut dyn TouchBridge;
|
||||
|
||||
fn assets(&self) -> &dyn AssetBridge;
|
||||
fn assets_mut(&mut self) -> &mut dyn AssetBridge;
|
||||
}
|
||||
pub use prometeu_hardware_contract::{
|
||||
AssetBridge, AudioBridge, BlendMode, GfxBridge, HardwareBridge, InputSignals, LoopMode,
|
||||
PadBridge, TouchBridge,
|
||||
};
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
use crate::hardware::input_signal::InputSignals;
|
||||
use crate::hardware::InputSignals;
|
||||
use crate::model::Button;
|
||||
|
||||
pub trait PadBridge {
|
||||
@ -37,7 +37,7 @@ pub struct Pad {
|
||||
pub select: Button,
|
||||
}
|
||||
|
||||
impl PadBridge for Pad {
|
||||
impl prometeu_hardware_contract::PadBridge for Pad {
|
||||
fn begin_frame(&mut self, signals: &InputSignals) { self.begin_frame(signals) }
|
||||
fn any(&self) -> bool { self.any() }
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
use crate::hardware::input_signal::InputSignals;
|
||||
use crate::hardware::InputSignals;
|
||||
use crate::model::Button;
|
||||
|
||||
pub trait TouchBridge {
|
||||
@ -15,7 +15,7 @@ pub struct Touch {
|
||||
pub y: i32,
|
||||
}
|
||||
|
||||
impl TouchBridge for Touch {
|
||||
impl prometeu_hardware_contract::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 }
|
||||
|
||||
@ -5,9 +5,10 @@ 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, HostContext, HostReturn, SyscallId, Value, VirtualMachine, VmFault};
|
||||
use crate::virtual_machine::{HostContext, HostReturn, SyscallId, Value, VirtualMachine, VmFault};
|
||||
use std::collections::HashMap;
|
||||
use std::time::Instant;
|
||||
use prometeu_hardware_contract::{expect_bool, expect_int};
|
||||
|
||||
/// PrometeuOS (POS): The central system firmware and resource manager.
|
||||
///
|
||||
|
||||
@ -1,123 +0,0 @@
|
||||
use crate::log::{LogLevel, LogService, LogSource};
|
||||
|
||||
#[derive(Debug, Clone, Copy, Default)]
|
||||
pub struct TelemetryFrame {
|
||||
pub frame_index: u64,
|
||||
pub vm_steps: u32,
|
||||
pub cycles_used: u64,
|
||||
pub cycles_budget: u64,
|
||||
pub syscalls: u32,
|
||||
pub host_cpu_time_us: u64,
|
||||
pub violations: u32,
|
||||
|
||||
// GFX Banks
|
||||
pub gfx_used_bytes: usize,
|
||||
pub gfx_inflight_bytes: usize,
|
||||
pub gfx_slots_occupied: u32,
|
||||
|
||||
// Audio Banks
|
||||
pub audio_used_bytes: usize,
|
||||
pub audio_inflight_bytes: usize,
|
||||
pub audio_slots_occupied: u32,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Default)]
|
||||
pub struct CertificationConfig {
|
||||
pub enabled: bool,
|
||||
pub cycles_budget_per_frame: Option<u64>,
|
||||
pub max_syscalls_per_frame: Option<u32>,
|
||||
pub max_host_cpu_us_per_frame: Option<u64>,
|
||||
}
|
||||
|
||||
pub struct Certifier {
|
||||
pub config: CertificationConfig,
|
||||
}
|
||||
|
||||
impl Certifier {
|
||||
pub fn new(config: CertificationConfig) -> Self {
|
||||
Self { config }
|
||||
}
|
||||
|
||||
pub fn evaluate(&self, telemetry: &TelemetryFrame, log_service: &mut LogService, ts_ms: u64) -> usize {
|
||||
if !self.config.enabled {
|
||||
return 0;
|
||||
}
|
||||
|
||||
let mut violations = 0;
|
||||
|
||||
if let Some(budget) = self.config.cycles_budget_per_frame {
|
||||
if telemetry.cycles_used > budget {
|
||||
log_service.log(
|
||||
ts_ms,
|
||||
telemetry.frame_index,
|
||||
LogLevel::Warn,
|
||||
LogSource::Pos,
|
||||
0xCA01,
|
||||
format!("Cert: cycles_used exceeded budget ({} > {})", telemetry.cycles_used, budget),
|
||||
);
|
||||
violations += 1;
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(limit) = self.config.max_syscalls_per_frame {
|
||||
if telemetry.syscalls > limit {
|
||||
log_service.log(
|
||||
ts_ms,
|
||||
telemetry.frame_index,
|
||||
LogLevel::Warn,
|
||||
LogSource::Pos,
|
||||
0xCA02,
|
||||
format!("Cert: syscalls per frame exceeded limit ({} > {})", telemetry.syscalls, limit),
|
||||
);
|
||||
violations += 1;
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(limit) = self.config.max_host_cpu_us_per_frame {
|
||||
if telemetry.host_cpu_time_us > limit {
|
||||
log_service.log(
|
||||
ts_ms,
|
||||
telemetry.frame_index,
|
||||
LogLevel::Warn,
|
||||
LogSource::Pos,
|
||||
0xCA03,
|
||||
format!("Cert: host_cpu_time_us exceeded limit ({} > {})", telemetry.host_cpu_time_us, limit),
|
||||
);
|
||||
violations += 1;
|
||||
}
|
||||
}
|
||||
|
||||
violations
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::log::LogService;
|
||||
|
||||
#[test]
|
||||
fn test_certifier_violations() {
|
||||
let config = CertificationConfig {
|
||||
enabled: true,
|
||||
cycles_budget_per_frame: Some(100),
|
||||
max_syscalls_per_frame: Some(5),
|
||||
max_host_cpu_us_per_frame: Some(1000),
|
||||
};
|
||||
let cert = Certifier::new(config);
|
||||
let mut ls = LogService::new(10);
|
||||
|
||||
let mut tel = TelemetryFrame::default();
|
||||
tel.cycles_used = 150;
|
||||
tel.syscalls = 10;
|
||||
tel.host_cpu_time_us = 500;
|
||||
|
||||
let violations = cert.evaluate(&tel, &mut ls, 1000);
|
||||
assert_eq!(violations, 2);
|
||||
|
||||
let logs = ls.get_recent(10);
|
||||
assert_eq!(logs.len(), 2);
|
||||
assert!(logs[0].msg.contains("cycles_used"));
|
||||
assert!(logs[1].msg.contains("syscalls"));
|
||||
}
|
||||
}
|
||||
@ -2,101 +2,18 @@ mod virtual_machine;
|
||||
mod call_frame;
|
||||
mod scope_frame;
|
||||
mod program;
|
||||
pub mod host_context;
|
||||
pub mod local_addressing;
|
||||
pub mod opcode_spec;
|
||||
pub mod bytecode;
|
||||
pub mod verifier;
|
||||
|
||||
pub use host_context::{HostContext, HostContextProvider};
|
||||
pub use program::ProgramImage;
|
||||
pub use prometeu_abi::virtual_machine::Value;
|
||||
pub use prometeu_abi::virtual_machine::{Value, VmFault};
|
||||
pub use prometeu_bytecode::abi::TrapInfo;
|
||||
pub use prometeu_bytecode::opcode::OpCode;
|
||||
pub use prometeu_hardware_contract::{
|
||||
HostContext, HostReturn, NativeInterface, SyscallId,
|
||||
};
|
||||
pub type VmInitError = prometeu_abi::virtual_machine::VmInitError<VerifierError>;
|
||||
pub use verifier::VerifierError;
|
||||
pub use virtual_machine::{BudgetReport, LogicalFrameEndingReason, VirtualMachine};
|
||||
|
||||
pub type SyscallId = u32;
|
||||
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub enum VmFault {
|
||||
Trap(u32, String),
|
||||
Panic(String),
|
||||
Unavailable,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum VmInitError {
|
||||
InvalidFormat,
|
||||
UnsupportedFormat,
|
||||
PbsV0LoadFailed(prometeu_bytecode::LoadError),
|
||||
EntrypointNotFound,
|
||||
VerificationFailed(VerifierError),
|
||||
}
|
||||
|
||||
pub struct HostReturn<'a> {
|
||||
stack: &'a mut Vec<Value>
|
||||
}
|
||||
|
||||
impl<'a> HostReturn<'a> {
|
||||
pub fn new(stack: &'a mut Vec<Value>) -> Self {
|
||||
Self { stack }
|
||||
}
|
||||
pub fn push_bool(&mut self, v: bool) {
|
||||
self.stack.push(Value::Boolean(v));
|
||||
}
|
||||
pub fn push_int(&mut self, v: i64) {
|
||||
self.stack.push(Value::Int64(v));
|
||||
}
|
||||
pub fn push_bounded(&mut self, v: u32) -> Result<(), VmFault> {
|
||||
if v > 0xFFFF {
|
||||
return Err(VmFault::Trap(prometeu_bytecode::abi::TRAP_OOB, format!(
|
||||
"bounded overflow: {}", v
|
||||
)));
|
||||
}
|
||||
self.stack.push(Value::Bounded(v));
|
||||
Ok(())
|
||||
}
|
||||
pub fn push_null(&mut self) {
|
||||
self.stack.push(Value::Null);
|
||||
}
|
||||
pub fn push_gate(&mut self, g: usize) {
|
||||
self.stack.push(Value::Gate(g));
|
||||
}
|
||||
pub fn push_string(&mut self, s: String) {
|
||||
self.stack.push(Value::String(s));
|
||||
}
|
||||
}
|
||||
|
||||
pub trait NativeInterface {
|
||||
/// Dispatches a syscall from the Virtual Machine to the native implementation.
|
||||
///
|
||||
/// ABI Rule: Arguments for the syscall are passed in `args`.
|
||||
///
|
||||
/// Returns are written via `ret`.
|
||||
fn syscall(&mut self, id: SyscallId, args: &[Value], ret: &mut HostReturn, ctx: &mut HostContext) -> Result<(), VmFault>;
|
||||
}
|
||||
|
||||
pub fn expect_bounded(args: &[Value], idx: usize) -> Result<u32, VmFault> {
|
||||
args.get(idx)
|
||||
.and_then(|v| match v {
|
||||
Value::Bounded(b) => Some(*b),
|
||||
_ => None,
|
||||
})
|
||||
.ok_or_else(|| VmFault::Trap(prometeu_bytecode::abi::TRAP_TYPE, format!("Expected bounded at index {}", idx)))
|
||||
}
|
||||
|
||||
pub fn expect_int(args: &[Value], idx: usize) -> Result<i64, VmFault> {
|
||||
args.get(idx)
|
||||
.and_then(|v| v.as_integer())
|
||||
.ok_or_else(|| VmFault::Trap(prometeu_bytecode::abi::TRAP_TYPE, format!("Expected integer at index {}", idx)))
|
||||
}
|
||||
|
||||
pub fn expect_bool(args: &[Value], idx: usize) -> Result<bool, VmFault> {
|
||||
args.get(idx)
|
||||
.and_then(|v| match v {
|
||||
Value::Boolean(b) => Some(*b),
|
||||
_ => None,
|
||||
})
|
||||
.ok_or_else(|| VmFault::Trap(prometeu_bytecode::abi::TRAP_TYPE, format!("Expected boolean at index {}", idx)))
|
||||
}
|
||||
|
||||
@ -931,9 +931,10 @@ mod tests {
|
||||
}]);
|
||||
vm
|
||||
}
|
||||
use crate::virtual_machine::{expect_int, HostReturn, Value, VmFault};
|
||||
use crate::virtual_machine::{HostReturn, Value, VmFault};
|
||||
use prometeu_bytecode::abi::SourceSpan;
|
||||
use prometeu_bytecode::FunctionMeta;
|
||||
use prometeu_hardware_contract::expect_int;
|
||||
|
||||
struct MockNative;
|
||||
impl NativeInterface for MockNative {
|
||||
|
||||
@ -5,5 +5,7 @@ edition = "2024"
|
||||
license.workspace = true
|
||||
|
||||
[dependencies]
|
||||
prometeu-abi = { path = "../prometeu-abi" }
|
||||
prometeu-bytecode = { path = "../prometeu-bytecode" }
|
||||
serde = { version = "1.0.228", features = ["derive"] }
|
||||
serde_json = "1.0.149"
|
||||
21
crates/prometeu-hardware-contract/src/asset.rs
Normal file
21
crates/prometeu-hardware-contract/src/asset.rs
Normal file
@ -0,0 +1,21 @@
|
||||
use prometeu_abi::model::{
|
||||
AssetEntry, BankStats, BankType, HandleId, LoadStatus, PreloadEntry, SlotRef, SlotStats,
|
||||
};
|
||||
|
||||
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);
|
||||
}
|
||||
38
crates/prometeu-hardware-contract/src/audio.rs
Normal file
38
crates/prometeu-hardware-contract/src/audio.rs
Normal file
@ -0,0 +1,38 @@
|
||||
use prometeu_abi::model::Sample;
|
||||
use std::sync::Arc;
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum LoopMode {
|
||||
Off,
|
||||
On,
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
51
crates/prometeu-hardware-contract/src/gfx.rs
Normal file
51
crates/prometeu-hardware-contract/src/gfx.rs
Normal file
@ -0,0 +1,51 @@
|
||||
use prometeu_abi::model::{Color, HudTileLayer, ScrollableTileLayer, Sprite};
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum BlendMode {
|
||||
None,
|
||||
Half,
|
||||
HalfPlus,
|
||||
HalfMinus,
|
||||
Full,
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
22
crates/prometeu-hardware-contract/src/hardware.rs
Normal file
22
crates/prometeu-hardware-contract/src/hardware.rs
Normal file
@ -0,0 +1,22 @@
|
||||
use crate::asset::AssetBridge;
|
||||
use crate::audio::AudioBridge;
|
||||
use crate::gfx::GfxBridge;
|
||||
use crate::pad::PadBridge;
|
||||
use crate::touch::TouchBridge;
|
||||
|
||||
pub trait HardwareBridge {
|
||||
fn gfx(&self) -> &dyn GfxBridge;
|
||||
fn gfx_mut(&mut self) -> &mut dyn GfxBridge;
|
||||
|
||||
fn audio(&self) -> &dyn AudioBridge;
|
||||
fn audio_mut(&mut self) -> &mut dyn AudioBridge;
|
||||
|
||||
fn pad(&self) -> &dyn PadBridge;
|
||||
fn pad_mut(&mut self) -> &mut dyn PadBridge;
|
||||
|
||||
fn touch(&self) -> &dyn TouchBridge;
|
||||
fn touch_mut(&mut self) -> &mut dyn TouchBridge;
|
||||
|
||||
fn assets(&self) -> &dyn AssetBridge;
|
||||
fn assets_mut(&mut self) -> &mut dyn AssetBridge;
|
||||
}
|
||||
@ -1,5 +1,5 @@
|
||||
use crate::hardware::HardwareBridge;
|
||||
use crate::virtual_machine::VmFault;
|
||||
use prometeu_abi::virtual_machine::VmFault;
|
||||
|
||||
pub struct HostContext<'a> {
|
||||
pub hw: Option<&'a mut dyn HardwareBridge>,
|
||||
@ -22,10 +22,3 @@ impl<'a> HostContext<'a> {
|
||||
pub trait HostContextProvider {
|
||||
fn make_ctx(&'_ mut self) -> HostContext<'_>;
|
||||
}
|
||||
|
||||
impl<T: HardwareBridge> HostContextProvider for T {
|
||||
#[inline]
|
||||
fn make_ctx(&'_ mut self) -> HostContext {
|
||||
HostContext::new(Some(self))
|
||||
}
|
||||
}
|
||||
33
crates/prometeu-hardware-contract/src/host_return.rs
Normal file
33
crates/prometeu-hardware-contract/src/host_return.rs
Normal file
@ -0,0 +1,33 @@
|
||||
use prometeu_abi::virtual_machine::Value;
|
||||
|
||||
pub struct HostReturn<'a> {
|
||||
stack: &'a mut Vec<Value>
|
||||
}
|
||||
|
||||
impl<'a> HostReturn<'a> {
|
||||
pub fn new(stack: &'a mut Vec<Value>) -> Self {
|
||||
Self { stack }
|
||||
}
|
||||
pub fn push_bool(&mut self, v: bool) {
|
||||
self.stack.push(Value::Boolean(v));
|
||||
}
|
||||
pub fn push_int(&mut self, v: i64) {
|
||||
self.stack.push(Value::Int64(v));
|
||||
}
|
||||
pub fn push_bounded(&mut self, v: u32) -> Result<(), prometeu_abi::virtual_machine::VmFault> {
|
||||
if v > 0xFFFF {
|
||||
return Err(prometeu_abi::virtual_machine::VmFault::Trap(prometeu_bytecode::abi::TRAP_OOB, "Bounded value overflow".into()));
|
||||
}
|
||||
self.stack.push(Value::Bounded(v));
|
||||
Ok(())
|
||||
}
|
||||
pub fn push_null(&mut self) {
|
||||
self.stack.push(Value::Null);
|
||||
}
|
||||
pub fn push_gate(&mut self, g: usize) {
|
||||
self.stack.push(Value::Gate(g));
|
||||
}
|
||||
pub fn push_string(&mut self, s: String) {
|
||||
self.stack.push(Value::String(s));
|
||||
}
|
||||
}
|
||||
23
crates/prometeu-hardware-contract/src/input_signals.rs
Normal file
23
crates/prometeu-hardware-contract/src/input_signals.rs
Normal file
@ -0,0 +1,23 @@
|
||||
#[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,
|
||||
}
|
||||
@ -0,0 +1,23 @@
|
||||
pub mod asset;
|
||||
pub mod audio;
|
||||
pub mod gfx;
|
||||
pub mod hardware;
|
||||
pub mod host_context;
|
||||
pub mod host_return;
|
||||
pub mod input_signals;
|
||||
pub mod native_interface;
|
||||
pub mod pad;
|
||||
pub mod touch;
|
||||
pub mod native_helpers;
|
||||
|
||||
pub use asset::AssetBridge;
|
||||
pub use audio::{AudioBridge, LoopMode};
|
||||
pub use gfx::{BlendMode, GfxBridge};
|
||||
pub use hardware::HardwareBridge;
|
||||
pub use host_context::{HostContext, HostContextProvider};
|
||||
pub use host_return::HostReturn;
|
||||
pub use input_signals::InputSignals;
|
||||
pub use native_interface::{NativeInterface, SyscallId};
|
||||
pub use pad::PadBridge;
|
||||
pub use touch::TouchBridge;
|
||||
pub use native_helpers::{expect_bool, expect_bounded, expect_int};
|
||||
25
crates/prometeu-hardware-contract/src/native_helpers.rs
Normal file
25
crates/prometeu-hardware-contract/src/native_helpers.rs
Normal file
@ -0,0 +1,25 @@
|
||||
use prometeu_abi::virtual_machine::{Value, VmFault};
|
||||
|
||||
pub fn expect_bounded(args: &[Value], idx: usize) -> Result<u32, VmFault> {
|
||||
args.get(idx)
|
||||
.and_then(|v| match v {
|
||||
Value::Bounded(b) => Some(*b),
|
||||
_ => None,
|
||||
})
|
||||
.ok_or_else(|| VmFault::Trap(prometeu_bytecode::abi::TRAP_TYPE, format!("Expected bounded at index {}", idx)))
|
||||
}
|
||||
|
||||
pub fn expect_int(args: &[Value], idx: usize) -> Result<i64, VmFault> {
|
||||
args.get(idx)
|
||||
.and_then(|v| v.as_integer())
|
||||
.ok_or_else(|| VmFault::Trap(prometeu_bytecode::abi::TRAP_TYPE, format!("Expected integer at index {}", idx)))
|
||||
}
|
||||
|
||||
pub fn expect_bool(args: &[Value], idx: usize) -> Result<bool, VmFault> {
|
||||
args.get(idx)
|
||||
.and_then(|v| match v {
|
||||
Value::Boolean(b) => Some(*b),
|
||||
_ => None,
|
||||
})
|
||||
.ok_or_else(|| VmFault::Trap(prometeu_bytecode::abi::TRAP_TYPE, format!("Expected boolean at index {}", idx)))
|
||||
}
|
||||
14
crates/prometeu-hardware-contract/src/native_interface.rs
Normal file
14
crates/prometeu-hardware-contract/src/native_interface.rs
Normal file
@ -0,0 +1,14 @@
|
||||
use prometeu_abi::virtual_machine::{Value, VmFault};
|
||||
use crate::host_context::HostContext;
|
||||
use crate::host_return::HostReturn;
|
||||
|
||||
pub type SyscallId = u32;
|
||||
|
||||
pub trait NativeInterface {
|
||||
/// Dispatches a syscall from the Virtual Machine to the native implementation.
|
||||
///
|
||||
/// ABI Rule: Arguments for the syscall are passed in `args`.
|
||||
///
|
||||
/// Returns are written via `ret`.
|
||||
fn syscall(&mut self, id: SyscallId, args: &[Value], ret: &mut HostReturn, ctx: &mut HostContext) -> Result<(), VmFault>;
|
||||
}
|
||||
20
crates/prometeu-hardware-contract/src/pad.rs
Normal file
20
crates/prometeu-hardware-contract/src/pad.rs
Normal file
@ -0,0 +1,20 @@
|
||||
use crate::input_signals::InputSignals;
|
||||
use prometeu_abi::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;
|
||||
}
|
||||
9
crates/prometeu-hardware-contract/src/touch.rs
Normal file
9
crates/prometeu-hardware-contract/src/touch.rs
Normal file
@ -0,0 +1,9 @@
|
||||
use crate::input_signals::InputSignals;
|
||||
use prometeu_abi::model::Button;
|
||||
|
||||
pub trait TouchBridge {
|
||||
fn begin_frame(&mut self, signals: &InputSignals);
|
||||
fn f(&self) -> &Button;
|
||||
fn x(&self) -> i32;
|
||||
fn y(&self) -> i32;
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user