diff --git a/docs/dev-firmware-micro-vm.md b/docs/dev-firmware-micro-vm.md index 6dad7f9..92de1d2 100644 --- a/docs/dev-firmware-micro-vm.md +++ b/docs/dev-firmware-micro-vm.md @@ -95,9 +95,28 @@ This system call is used to wait for machine events. Use R0 to mask events to wa Example: ``` - mov r0, + mov r0, 0b1000 + syscall 2 ``` +## SYSCALL 3 (Send signal) + +Send a specific signal event to the machine. +Use R0 register to pass the signal argument. + +``` + mov r0, 42 + syscall 3 +``` + +Supported signals: + +| Signal | Number | +|------- |-------- | +| reserved | 0 | +| Quit story | 1 | + + # Assembler Basic grammar diff --git a/story-editor/scripts/media.chip32 b/story-editor/scripts/media.chip32 index 38231aa..e203dbe 100644 --- a/story-editor/scripts/media.chip32 +++ b/story-editor/scripts/media.chip32 @@ -29,7 +29,7 @@ mov t5, r0 ; save it ; wait for event - lcons r0, 0b111 ; mask for OK, previous and next buttons + lcons r0, 0b100111 ; mask for OK, previous and next buttons, home button syscall 2 ; Event is stored in R0 @@ -45,6 +45,11 @@ skipz r1 ; not OK, skip jump jump .media_previous + lcons r1, 0b100000 ; mask for home button + and r1, r0 ; r1 = r1 AND r0 + skipz r1 ; not Home, skip jump + jump .media_exit + ; all other events mean: next node eq r0, t0, t4 ; t4 est le dernier élément skipz r0 ; zéro, on peut incrémenter l'adresse @@ -71,4 +76,9 @@ call t5 ; jump to the node lcons r0, 0b10000100001 ; mask for end of audio, Ok, and home buttons syscall 2 ; wait for event (OK, home or end of audio), return to choice loop - jump .media_loop \ No newline at end of file + jump .media_loop + +.media_exit: + lcons r0, 1 ; Home button pressed, send signal to exit story + syscall 3 ; exit story, we should never return from this call + halt ; just in case diff --git a/story-player/lib/libstory/storyvm.dart b/story-player/lib/libstory/storyvm.dart index a0911b4..dbebf6e 100644 --- a/story-player/lib/libstory/storyvm.dart +++ b/story-player/lib/libstory/storyvm.dart @@ -22,6 +22,12 @@ class MediaEvent { MediaEvent(this.image, this.sound); } +class SignalEvent { + int signal; + + SignalEvent(this.signal); +} + Completer periodic(Duration interval, Function(int cycle) callback) { final done = Completer(); () async { @@ -96,8 +102,10 @@ class StoryVm { if (i == 0) { eventBus.fire(MediaEvent(file, "")); - } else { + } else if (i == 1) { eventBus.fire(MediaEvent("", file)); + } else if (i == 2) { + eventBus.fire(SignalEvent(1)); } } diff --git a/story-player/lib/main.dart b/story-player/lib/main.dart index d1fc71e..473fc13 100644 --- a/story-player/lib/main.dart +++ b/story-player/lib/main.dart @@ -160,6 +160,14 @@ class _MyHomePageState extends State { } }); + eventBus.on().listen((event) { + if (event.signal == 1) { + state = PlayerState.indexFile; + showCurrentStoryIndex(); + } + }); + + audioPlayerSub = player.onPlayerComplete.listen((event) { if (state == PlayerState.inStory) { // Send end of music event diff --git a/story-player/storyvm/storyvm.cpp b/story-player/storyvm/storyvm.cpp index dcf8396..1638ff7 100644 --- a/story-player/storyvm/storyvm.cpp +++ b/story-player/storyvm/storyvm.cpp @@ -118,6 +118,19 @@ uint8_t story_player_syscall(chip32_ctx_t *ctx, uint8_t code) event_mask = ctx->registers[R0]; retCode = SYSCALL_RET_WAIT_EV; // set the VM in pause } + else if (code == 3) // Signal + { + if (ctx->registers[R0] == 1) + { + // EXIT + std::cout << "[STORYVM] Syscall 3 (exit)" << std::endl; + if (gMediaCallback) + { + std::cout << "[STORYVM] Execute callback (sound)" << std::endl; + gMediaCallback(2, ""); + } + } + } return retCode; }