use crate::firmware::boot_target::BootTarget; use crate::firmware::firmware_state::{FirmwareState, LoadCartridgeStep, ResetStep}; use crate::firmware::prometeu_context::PrometeuContext; use crate::hardware::{HardwareBridge, InputSignals}; use crate::model::Cartridge; use crate::prometeu_hub::PrometeuHub; use crate::prometeu_os::PrometeuOS; use crate::virtual_machine::VirtualMachine; use crate::telemetry::CertificationConfig; /// PROMETEU Firmware. /// /// The central orchestrator of the system. It manages the high-level state machine, /// transitioning between system states like booting, the Hub launcher, and /// actual application execution. pub struct Firmware { /// The Virtual Machine instance. pub vm: VirtualMachine, /// The System Operating logic (syscalls, telemetry, logs). pub os: PrometeuOS, /// The System UI / Launcher environment. pub hub: PrometeuHub, /// Current high-level state of the system. pub state: FirmwareState, /// Desired execution target resolved at boot. pub boot_target: BootTarget, /// Tracking flag to ensure `on_enter` is called exactly once per state transition. state_initialized: bool, } impl Firmware { /// Initializes the firmware in the `Reset` state. pub fn new(cap_config: Option) -> Self { Self { vm: VirtualMachine::default(), os: PrometeuOS::new(cap_config), hub: PrometeuHub::new(), state: FirmwareState::Reset(ResetStep), boot_target: BootTarget::Hub, state_initialized: false, } } /// The main entry point for the Host to advance the system logic. /// /// This method is called exactly once per Host frame (60Hz). /// It updates peripheral signals and delegates the logic to the current state. pub fn step_frame(&mut self, signals: &InputSignals, hw: &mut dyn HardwareBridge) { // 0. Process asset commits at the beginning of the frame boundary. hw.assets_mut().apply_commits(); // 1. Update peripheral state using the latest signals from the Host. // This ensures input is consistent throughout the entire update. hw.pad_mut().begin_frame(signals); hw.touch_mut().begin_frame(signals); // 2. State machine lifecycle management. if !self.state_initialized { self.on_enter(signals, hw); self.state_initialized = true; } // 3. Update the current state and check for transitions. if let Some(next_state) = self.on_update(signals, hw) { self.change_state(next_state, signals, hw); } } /// Transitions the system to a new state, handling lifecycle hooks. pub fn change_state(&mut self, new_state: FirmwareState, signals: &InputSignals, hw: &mut dyn HardwareBridge) { self.on_exit(signals, hw); self.state = new_state; self.state_initialized = false; // Enter the new state immediately to avoid "empty" frames during transitions. self.on_enter(signals, hw); self.state_initialized = true; } /// Dispatches the `on_enter` event to the current state implementation. fn on_enter(&mut self, signals: &InputSignals, hw: &mut dyn HardwareBridge) { let mut req = PrometeuContext { vm: &mut self.vm, os: &mut self.os, hub: &mut self.hub, boot_target: &self.boot_target, signals, hw, }; match &mut self.state { FirmwareState::Reset(s) => s.on_enter(&mut req), FirmwareState::SplashScreen(s) => s.on_enter(&mut req), FirmwareState::LaunchHub(s) => s.on_enter(&mut req), 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::AppCrashes(s) => s.on_enter(&mut req), } } /// Dispatches the `on_update` event to the current state implementation. /// Returns an optional `FirmwareState` if a transition is requested. fn on_update(&mut self, signals: &InputSignals, hw: &mut dyn HardwareBridge) -> Option { let mut req = PrometeuContext { vm: &mut self.vm, os: &mut self.os, hub: &mut self.hub, boot_target: &self.boot_target, signals, hw, }; match &mut self.state { FirmwareState::Reset(s) => s.on_update(&mut req), FirmwareState::SplashScreen(s) => s.on_update(&mut req), FirmwareState::LaunchHub(s) => s.on_update(&mut req), 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::AppCrashes(s) => s.on_update(&mut req), } } /// Dispatches the `on_exit` event to the current state implementation. fn on_exit(&mut self, signals: &InputSignals, hw: &mut dyn HardwareBridge) { let mut req = PrometeuContext { vm: &mut self.vm, os: &mut self.os, hub: &mut self.hub, boot_target: &self.boot_target, signals, hw, }; match &mut self.state { FirmwareState::Reset(s) => s.on_exit(&mut req), FirmwareState::SplashScreen(s) => s.on_exit(&mut req), FirmwareState::LaunchHub(s) => s.on_exit(&mut req), 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::AppCrashes(s) => s.on_exit(&mut req), } } pub fn load_cartridge(&mut self, cartridge: Cartridge) { self.state = FirmwareState::LoadCartridge(LoadCartridgeStep { cartridge }); self.state_initialized = false; } }