From bea3f76aa717a7b848f2c458699ecb93e1d91bea Mon Sep 17 00:00:00 2001 From: bQUARKz Date: Thu, 14 May 2026 13:25:24 +0100 Subject: [PATCH] implements PLN-0047 firmware profile dispatch --- .../src/firmware/firmware.rs | 9 +++-- .../src/firmware/firmware_state.rs | 2 ++ .../firmware/firmware_step_load_cartridge.rs | 6 ++-- .../firmware/firmware_step_system_running.rs | 34 +++++++++++++++++++ .../prometeu-firmware/src/firmware/mod.rs | 1 + discussion/index.ndjson | 2 +- ...-0047-firmware-runtime-profile-dispatch.md | 2 +- 7 files changed, 48 insertions(+), 8 deletions(-) create mode 100644 crates/console/prometeu-firmware/src/firmware/firmware_step_system_running.rs diff --git a/crates/console/prometeu-firmware/src/firmware/firmware.rs b/crates/console/prometeu-firmware/src/firmware/firmware.rs index c2ef3be9..ac5db226 100644 --- a/crates/console/prometeu-firmware/src/firmware/firmware.rs +++ b/crates/console/prometeu-firmware/src/firmware/firmware.rs @@ -108,6 +108,7 @@ impl Firmware { FirmwareState::HubHome(s) => s.on_enter(&mut req), FirmwareState::LoadCartridge(s) => s.on_enter(&mut req), FirmwareState::GameRunning(s) => s.on_enter(&mut req), + FirmwareState::SystemRunning(s) => s.on_enter(&mut req), FirmwareState::AppCrashes(s) => s.on_enter(&mut req), } } @@ -134,6 +135,7 @@ impl Firmware { FirmwareState::HubHome(s) => s.on_update(&mut req), FirmwareState::LoadCartridge(s) => s.on_update(&mut req), FirmwareState::GameRunning(s) => s.on_update(&mut req), + FirmwareState::SystemRunning(s) => s.on_update(&mut req), FirmwareState::AppCrashes(s) => s.on_update(&mut req), } } @@ -155,6 +157,7 @@ impl Firmware { FirmwareState::HubHome(s) => s.on_exit(&mut req), FirmwareState::LoadCartridge(s) => s.on_exit(&mut req), FirmwareState::GameRunning(s) => s.on_exit(&mut req), + FirmwareState::SystemRunning(s) => s.on_exit(&mut req), FirmwareState::AppCrashes(s) => s.on_exit(&mut req), } } @@ -327,7 +330,7 @@ mod tests { } #[test] - fn load_cartridge_routes_system_apps_back_to_hub_home() { + fn load_cartridge_routes_system_apps_to_system_running() { let mut firmware = Firmware::new(None); let mut hardware = Hardware::new(); let signals = InputSignals::default(); @@ -335,7 +338,9 @@ mod tests { firmware.load_cartridge(valid_cartridge(AppMode::System)); firmware.tick(&signals, &mut hardware); - assert!(matches!(firmware.state, FirmwareState::HubHome(_))); + assert!(matches!(firmware.state, FirmwareState::SystemRunning(_))); + assert!(firmware.hub.window_manager.focused.is_some()); + assert_eq!(firmware.hub.window_manager.windows.len(), 1); } #[test] diff --git a/crates/console/prometeu-firmware/src/firmware/firmware_state.rs b/crates/console/prometeu-firmware/src/firmware/firmware_state.rs index e388721b..c8baa62d 100644 --- a/crates/console/prometeu-firmware/src/firmware/firmware_state.rs +++ b/crates/console/prometeu-firmware/src/firmware/firmware_state.rs @@ -5,6 +5,7 @@ pub use crate::firmware::firmware_step_launch_hub::LaunchHubStep; pub use crate::firmware::firmware_step_load_cartridge::LoadCartridgeStep; pub use crate::firmware::firmware_step_reset::ResetStep; pub use crate::firmware::firmware_step_splash_screen::SplashScreenStep; +pub use crate::firmware::firmware_step_system_running::SystemRunningStep; #[derive(Debug, Clone)] pub enum FirmwareState { @@ -14,5 +15,6 @@ pub enum FirmwareState { HubHome(HubHomeStep), LoadCartridge(LoadCartridgeStep), GameRunning(GameRunningStep), + SystemRunning(SystemRunningStep), AppCrashes(AppCrashesStep), } diff --git a/crates/console/prometeu-firmware/src/firmware/firmware_step_load_cartridge.rs b/crates/console/prometeu-firmware/src/firmware/firmware_step_load_cartridge.rs index ea6e937f..3fdb9956 100644 --- a/crates/console/prometeu-firmware/src/firmware/firmware_step_load_cartridge.rs +++ b/crates/console/prometeu-firmware/src/firmware/firmware_step_load_cartridge.rs @@ -1,5 +1,5 @@ use crate::firmware::firmware_state::{ - AppCrashesStep, FirmwareState, GameRunningStep, HubHomeStep, + AppCrashesStep, FirmwareState, GameRunningStep, SystemRunningStep, }; use crate::firmware::prometeu_context::PrometeuContext; use prometeu_hal::cartridge::{AppMode, Cartridge}; @@ -50,9 +50,7 @@ impl LoadCartridgeStep { ); ctx.hub.window_manager.set_focus(id); - // System apps do not change the firmware state to GameRunning. - // They run in the background or via windows in the Hub. - return Some(FirmwareState::HubHome(HubHomeStep)); + return Some(FirmwareState::SystemRunning(SystemRunningStep)); } Some(FirmwareState::GameRunning(GameRunningStep)) diff --git a/crates/console/prometeu-firmware/src/firmware/firmware_step_system_running.rs b/crates/console/prometeu-firmware/src/firmware/firmware_step_system_running.rs new file mode 100644 index 00000000..10922c6f --- /dev/null +++ b/crates/console/prometeu-firmware/src/firmware/firmware_step_system_running.rs @@ -0,0 +1,34 @@ +use crate::firmware::firmware_state::{AppCrashesStep, FirmwareState, HubHomeStep}; +use crate::firmware::prometeu_context::PrometeuContext; +use prometeu_hal::log::{LogLevel, LogSource}; + +#[derive(Debug, Clone)] +pub struct SystemRunningStep; + +impl SystemRunningStep { + pub fn on_enter(&mut self, ctx: &mut PrometeuContext) { + ctx.os.log(LogLevel::Info, LogSource::Hub, 0, "Entering SystemRunning".to_string()); + } + + pub fn on_update(&mut self, ctx: &mut PrometeuContext) -> Option { + let mut error = None; + + ctx.hub.gui_update(ctx.os, ctx.hw); + + if let Some(focused_id) = ctx.hub.window_manager.focused { + if ctx.hw.pad().start().down { + ctx.hub.window_manager.remove_window(focused_id); + return Some(FirmwareState::HubHome(HubHomeStep)); + } + + error = ctx.os.tick(ctx.vm, ctx.signals, ctx.hw); + } + + ctx.hub.render(ctx.os, ctx.hw); + ctx.hw.gfx_mut().present(); + + error.map(|report| FirmwareState::AppCrashes(AppCrashesStep { report })) + } + + pub fn on_exit(&mut self, _ctx: &mut PrometeuContext) {} +} diff --git a/crates/console/prometeu-firmware/src/firmware/mod.rs b/crates/console/prometeu-firmware/src/firmware/mod.rs index abe505ee..38e3a002 100644 --- a/crates/console/prometeu-firmware/src/firmware/mod.rs +++ b/crates/console/prometeu-firmware/src/firmware/mod.rs @@ -10,6 +10,7 @@ pub(crate) mod firmware_step_launch_hub; pub(crate) mod firmware_step_load_cartridge; pub(crate) mod firmware_step_reset; pub(crate) mod firmware_step_splash_screen; +pub(crate) mod firmware_step_system_running; mod prometeu_context; pub use boot_target::BootTarget; diff --git a/discussion/index.ndjson b/discussion/index.ndjson index 52cc911f..4d3b1169 100644 --- a/discussion/index.ndjson +++ b/discussion/index.ndjson @@ -29,4 +29,4 @@ {"type":"discussion","id":"DSC-0018","status":"done","ticket":"asset-load-asset-id-int-contract","title":"Asset Load Asset ID Int Contract","created_at":"2026-03-27","updated_at":"2026-03-27","tags":["asset","runtime","abi"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0019","file":"discussion/lessons/DSC-0018-asset-load-asset-id-int-contract/LSN-0019-asset-load-id-abi-convergence.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"}]} {"type":"discussion","id":"DSC-0019","status":"done","ticket":"jenkinsfile-correction","title":"Jenkinsfile Correction and Relocation","created_at":"2026-04-07","updated_at":"2026-04-07","tags":["ci","jenkins"],"agendas":[{"id":"AGD-0017","file":"AGD-0017-jenkinsfile-correction.md","status":"done","created_at":"2026-04-07","updated_at":"2026-04-07"}],"decisions":[{"id":"DEC-0002","file":"DEC-0002-jenkinsfile-strategy.md","status":"accepted","created_at":"2026-04-07","updated_at":"2026-04-07"}],"plans":[{"id":"PLN-0002","file":"PLN-0002-jenkinsfile-execution.md","status":"done","created_at":"2026-04-07","updated_at":"2026-04-07"}],"lessons":[{"id":"LSN-0020","file":"discussion/lessons/DSC-0019-jenkins-ci-standardization/LSN-0020-jenkins-standard-relocation.md","status":"done","created_at":"2026-04-07","updated_at":"2026-04-07"}]} {"type":"discussion","id":"DSC-0030","status":"done","ticket":"internal-viewport-270p","title":"Agenda - Internal Viewport 270p (480x270)","created_at":"2026-04-27","updated_at":"2026-04-28","tags":["gfx","runtime","viewport","resolution","frame-composer","host"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0039","file":"discussion/lessons/DSC-0030-internal-viewport-270p/LSN-0039-resolution-baseline-changes-are-runtime-wide-contracts.md","status":"done","created_at":"2026-04-28","updated_at":"2026-04-28"}]} -{"type":"discussion","id":"DSC-0031","status":"in_progress","ticket":"runtime-mode-separation-game-system","title":"Agenda - Runtime Mode Separation: Game and System","created_at":"2026-05-11","updated_at":"2026-05-14","tags":["runtime","firmware","hub","system-apps","game-mode","scheduler"],"agendas":[{"id":"AGD-0031","file":"AGD-0031-runtime-mode-separation-game-system.md","status":"accepted","created_at":"2026-05-11","updated_at":"2026-05-14"}],"decisions":[{"id":"DEC-0023","file":"DEC-0023-system-pipeline-separation.md","status":"accepted","created_at":"2026-05-14","updated_at":"2026-05-14"}],"plans":[{"id":"PLN-0046","file":"PLN-0046-profile-separation-specification.md","status":"done","created_at":"2026-05-14","updated_at":"2026-05-14","ref_decisions":["DEC-0023"]},{"id":"PLN-0047","file":"PLN-0047-firmware-runtime-profile-dispatch.md","status":"open","created_at":"2026-05-14","updated_at":"2026-05-14","ref_decisions":["DEC-0023"]},{"id":"PLN-0048","file":"PLN-0048-minimal-system-hub-pipeline.md","status":"open","created_at":"2026-05-14","updated_at":"2026-05-14","ref_decisions":["DEC-0023"]},{"id":"PLN-0049","file":"PLN-0049-system-profile-abi-gates.md","status":"open","created_at":"2026-05-14","updated_at":"2026-05-14","ref_decisions":["DEC-0023"]},{"id":"PLN-0050","file":"PLN-0050-system-pipeline-evidence-and-learning.md","status":"open","created_at":"2026-05-14","updated_at":"2026-05-14","ref_decisions":["DEC-0023"]}],"lessons":[]} +{"type":"discussion","id":"DSC-0031","status":"in_progress","ticket":"runtime-mode-separation-game-system","title":"Agenda - Runtime Mode Separation: Game and System","created_at":"2026-05-11","updated_at":"2026-05-14","tags":["runtime","firmware","hub","system-apps","game-mode","scheduler"],"agendas":[{"id":"AGD-0031","file":"AGD-0031-runtime-mode-separation-game-system.md","status":"accepted","created_at":"2026-05-11","updated_at":"2026-05-14"}],"decisions":[{"id":"DEC-0023","file":"DEC-0023-system-pipeline-separation.md","status":"accepted","created_at":"2026-05-14","updated_at":"2026-05-14"}],"plans":[{"id":"PLN-0046","file":"PLN-0046-profile-separation-specification.md","status":"done","created_at":"2026-05-14","updated_at":"2026-05-14","ref_decisions":["DEC-0023"]},{"id":"PLN-0047","file":"PLN-0047-firmware-runtime-profile-dispatch.md","status":"done","created_at":"2026-05-14","updated_at":"2026-05-14","ref_decisions":["DEC-0023"]},{"id":"PLN-0048","file":"PLN-0048-minimal-system-hub-pipeline.md","status":"open","created_at":"2026-05-14","updated_at":"2026-05-14","ref_decisions":["DEC-0023"]},{"id":"PLN-0049","file":"PLN-0049-system-profile-abi-gates.md","status":"open","created_at":"2026-05-14","updated_at":"2026-05-14","ref_decisions":["DEC-0023"]},{"id":"PLN-0050","file":"PLN-0050-system-pipeline-evidence-and-learning.md","status":"open","created_at":"2026-05-14","updated_at":"2026-05-14","ref_decisions":["DEC-0023"]}],"lessons":[]} diff --git a/discussion/workflow/plans/PLN-0047-firmware-runtime-profile-dispatch.md b/discussion/workflow/plans/PLN-0047-firmware-runtime-profile-dispatch.md index 9dcd6b56..fb366b9f 100644 --- a/discussion/workflow/plans/PLN-0047-firmware-runtime-profile-dispatch.md +++ b/discussion/workflow/plans/PLN-0047-firmware-runtime-profile-dispatch.md @@ -2,7 +2,7 @@ id: PLN-0047 ticket: runtime-mode-separation-game-system title: Firmware Runtime Profile Dispatch -status: open +status: done created: 2026-05-14 completed: ref_decisions: [DEC-0023]