use crate::firmware::firmware_state::{FirmwareState, LaunchHubStep}; use crate::firmware::prometeu_context::PrometeuContext; use prometeu_hal::color::Color; use prometeu_hal::log::{LogLevel, LogSource}; use prometeu_hal::{FrameId, GfxUiCommand, RenderSubmission, ShellUiFramePacket}; use prometeu_system::CrashReport; #[derive(Debug, Clone)] pub struct AppCrashesStep { pub report: CrashReport, } impl AppCrashesStep { pub fn log_message(&self) -> String { format!("App Crashed: {}", self.report) } pub fn on_enter(&mut self, ctx: &mut PrometeuContext) { ctx.os.log(LogLevel::Error, LogSource::Pos, self.report.log_tag(), self.log_message()); } pub fn on_update(&mut self, ctx: &mut PrometeuContext) -> Option { // Update peripherals for input on the crash screen ctx.hw.pad_mut().begin_frame(ctx.signals); let packet = ShellUiFramePacket::new(vec![GfxUiCommand::Clear { color: Color::RED }]); ctx.hw.publish_render_submission(&RenderSubmission::shell_ui(FrameId::ZERO, packet)); // If START is pressed, return to the Hub if ctx.hw.pad().start().down { return Some(FirmwareState::LaunchHub(LaunchHubStep)); } None } pub fn on_exit(&mut self, _ctx: &mut PrometeuContext) {} } #[cfg(test)] mod tests { use super::*; use prometeu_bytecode::TrapInfo; #[test] fn crash_step_formats_trap_from_structured_report() { let step = AppCrashesStep { report: CrashReport::VmTrap { trap: TrapInfo { code: 0xAB, opcode: 0x22, message: "type mismatch".into(), pc: 0x44, span: None, }, }, }; let msg = step.log_message(); assert!(msg.contains("PVM Trap 0x000000AB")); assert!(msg.contains("PC 0x44")); assert!(msg.contains("opcode 0x0022")); assert!(msg.contains("type mismatch")); } }