add boot loader
This commit is contained in:
parent
4a6def6aa0
commit
990e3ead2a
@ -4,6 +4,6 @@
|
||||
"app_id": 1234,
|
||||
"title": "Cart de Teste",
|
||||
"app_version": "1.0.0",
|
||||
"app_mode": "Invalid",
|
||||
"app_mode": "Game",
|
||||
"entrypoint": "0"
|
||||
}
|
||||
|
||||
@ -5,6 +5,7 @@ mod log_sink;
|
||||
|
||||
use crate::prometeu_runner::PrometeuRunner;
|
||||
use winit::event_loop::EventLoop;
|
||||
use prometeu_core::firmware::BootTarget;
|
||||
use prometeu_core::telemetry::CertificationConfig;
|
||||
|
||||
fn load_cap_config(path: &str) -> Option<CertificationConfig> {
|
||||
@ -37,14 +38,26 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let args: Vec<String> = std::env::args().collect();
|
||||
let mut fs_root = None;
|
||||
let mut cap_config = None;
|
||||
let mut cartridge_path = None;
|
||||
let mut boot_target = BootTarget::Hub;
|
||||
|
||||
let mut i = 1; // Pula o nome do executável
|
||||
while i < args.len() {
|
||||
match args[i].as_str() {
|
||||
"run" => {
|
||||
"--run" => {
|
||||
if i + 1 < args.len() {
|
||||
cartridge_path = Some(args[i + 1].clone());
|
||||
boot_target = BootTarget::Cartridge {
|
||||
path: args[i + 1].clone(),
|
||||
debug: false,
|
||||
};
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
"--debug" => {
|
||||
if i + 1 < args.len() {
|
||||
boot_target = BootTarget::Cartridge {
|
||||
path: args[i + 1].clone(),
|
||||
debug: true,
|
||||
};
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
@ -68,16 +81,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let event_loop = EventLoop::new()?;
|
||||
|
||||
let mut runner = PrometeuRunner::new(fs_root, cap_config);
|
||||
|
||||
if let Some(path) = cartridge_path {
|
||||
match runner.load_cartridge(&path) {
|
||||
Ok(_) => println!("Cartridge loaded: {}", path),
|
||||
Err(e) => {
|
||||
eprintln!("Failed to load cartridge: {:?}", e);
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
}
|
||||
runner.set_boot_target(boot_target);
|
||||
|
||||
event_loop.run_app(&mut runner)?;
|
||||
|
||||
|
||||
@ -3,7 +3,7 @@ use crate::fs_desktop_backend::HostDirBackend;
|
||||
use crate::log_sink::HostConsoleSink;
|
||||
use cpal::traits::{DeviceTrait, HostTrait, StreamTrait};
|
||||
use pixels::{Pixels, SurfaceTexture};
|
||||
use prometeu_core::firmware::Firmware;
|
||||
use prometeu_core::firmware::{BootTarget, Firmware};
|
||||
use prometeu_core::hardware::{AudioCommand, InputSignals, OUTPUT_SAMPLE_RATE};
|
||||
use prometeu_core::Hardware;
|
||||
use ringbuf::traits::{Consumer, Producer, Split};
|
||||
@ -42,6 +42,8 @@ pub struct PrometeuRunner {
|
||||
|
||||
overlay_enabled: bool,
|
||||
|
||||
debug_waiting_for_start: bool,
|
||||
|
||||
audio_load_accum_us: u64,
|
||||
audio_load_samples: u64,
|
||||
audio_perf_consumer: Option<ringbuf::wrap::CachingCons<Arc<HeapRb<u64>>>>,
|
||||
@ -51,6 +53,15 @@ pub struct PrometeuRunner {
|
||||
}
|
||||
|
||||
impl PrometeuRunner {
|
||||
pub(crate) fn set_boot_target(&mut self, boot_target: BootTarget) {
|
||||
self.firmware.boot_target = boot_target.clone();
|
||||
if let BootTarget::Cartridge { debug: true, .. } = boot_target {
|
||||
self.debug_waiting_for_start = true;
|
||||
println!("[Debugger] Waiting for start command...");
|
||||
println!("[Debugger] (Stub: press D to start execution)");
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn load_cartridge(&mut self, path: &str) -> Result<(), CartridgeError> {
|
||||
let cartridge = CartridgeLoader::load(path)?;
|
||||
self.firmware.load_cartridge(cartridge);
|
||||
@ -82,6 +93,7 @@ impl PrometeuRunner {
|
||||
frames_since_last_update: 0,
|
||||
current_fps: 0.0,
|
||||
overlay_enabled: false,
|
||||
debug_waiting_for_start: false,
|
||||
audio_load_accum_us: 0,
|
||||
audio_load_samples: 0,
|
||||
audio_perf_consumer: None,
|
||||
@ -225,6 +237,12 @@ impl ApplicationHandler for PrometeuRunner {
|
||||
WindowEvent::KeyboardInput { event, .. } => {
|
||||
if let PhysicalKey::Code(code) = event.physical_key {
|
||||
let is_down = event.state == ElementState::Pressed;
|
||||
|
||||
if is_down && code == KeyCode::KeyD && self.debug_waiting_for_start {
|
||||
self.debug_waiting_for_start = false;
|
||||
println!("[Debugger] Execution started!");
|
||||
}
|
||||
|
||||
match code {
|
||||
KeyCode::ArrowUp => self.input_signals.up_signal = is_down,
|
||||
KeyCode::ArrowDown => self.input_signals.down_signal = is_down,
|
||||
@ -301,7 +319,9 @@ impl ApplicationHandler for PrometeuRunner {
|
||||
|
||||
// 🔥 O coração do determinismo: consome o tempo em fatias exatas de 60Hz
|
||||
while self.accumulator >= self.frame_target_dt {
|
||||
self.firmware.step_frame(&self.input_signals, &mut self.hardware);
|
||||
if !self.debug_waiting_for_start {
|
||||
self.firmware.step_frame(&self.input_signals, &mut self.hardware);
|
||||
}
|
||||
|
||||
// Envia comandos de áudio gerados neste frame para a thread de áudio
|
||||
if let Some(producer) = &mut self.audio_producer {
|
||||
|
||||
11
crates/prometeu-core/src/firmware/boot_target.rs
Normal file
11
crates/prometeu-core/src/firmware/boot_target.rs
Normal file
@ -0,0 +1,11 @@
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum BootTarget {
|
||||
Hub,
|
||||
Cartridge { path: String, debug: bool },
|
||||
}
|
||||
|
||||
impl Default for BootTarget {
|
||||
fn default() -> Self {
|
||||
Self::Hub
|
||||
}
|
||||
}
|
||||
@ -1,3 +1,4 @@
|
||||
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};
|
||||
@ -13,6 +14,7 @@ pub struct Firmware {
|
||||
pub os: PrometeuOS,
|
||||
pub hub: PrometeuHub,
|
||||
pub state: FirmwareState,
|
||||
pub boot_target: BootTarget,
|
||||
state_initialized: bool,
|
||||
}
|
||||
|
||||
@ -23,6 +25,7 @@ impl Firmware {
|
||||
os: PrometeuOS::new(cap_config),
|
||||
hub: PrometeuHub::new(),
|
||||
state: FirmwareState::Reset(ResetStep),
|
||||
boot_target: BootTarget::Hub,
|
||||
state_initialized: false,
|
||||
}
|
||||
}
|
||||
@ -57,6 +60,7 @@ impl Firmware {
|
||||
vm: &mut self.vm,
|
||||
os: &mut self.os,
|
||||
hub: &mut self.hub,
|
||||
boot_target: &self.boot_target,
|
||||
signals,
|
||||
hw,
|
||||
};
|
||||
@ -76,6 +80,7 @@ impl Firmware {
|
||||
vm: &mut self.vm,
|
||||
os: &mut self.os,
|
||||
hub: &mut self.hub,
|
||||
boot_target: &self.boot_target,
|
||||
signals,
|
||||
hw,
|
||||
};
|
||||
@ -95,6 +100,7 @@ impl Firmware {
|
||||
vm: &mut self.vm,
|
||||
os: &mut self.os,
|
||||
hub: &mut self.hub,
|
||||
boot_target: &self.boot_target,
|
||||
signals,
|
||||
hw,
|
||||
};
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
use crate::firmware::firmware_state::{FirmwareState, HubHomeStep};
|
||||
use crate::firmware::boot_target::BootTarget;
|
||||
use crate::firmware::firmware_state::{FirmwareState, HubHomeStep, LoadCartridgeStep};
|
||||
use crate::firmware::prometeu_context::PrometeuContext;
|
||||
use crate::model::CartridgeLoader;
|
||||
use crate::log::{LogLevel, LogSource};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
@ -11,7 +13,19 @@ impl LaunchHubStep {
|
||||
ctx.hub.init();
|
||||
}
|
||||
|
||||
pub fn on_update(&mut self, _ctx: &mut PrometeuContext) -> Option<FirmwareState> {
|
||||
pub fn on_update(&mut self, ctx: &mut PrometeuContext) -> Option<FirmwareState> {
|
||||
if let BootTarget::Cartridge { path, debug } = ctx.boot_target {
|
||||
match CartridgeLoader::load(path) {
|
||||
Ok(cartridge) => {
|
||||
// No caso de debug, aqui poderíamos pausar, mas o requisito diz
|
||||
// para o Runtime abrir o socket e aguardar.
|
||||
return Some(FirmwareState::LoadCartridge(LoadCartridgeStep { cartridge }));
|
||||
}
|
||||
Err(e) => {
|
||||
ctx.os.log(LogLevel::Error, LogSource::Pos, 0, format!("Failed to auto-load cartridge: {:?}", e));
|
||||
}
|
||||
}
|
||||
}
|
||||
Some(FirmwareState::HubHome(HubHomeStep))
|
||||
}
|
||||
|
||||
|
||||
@ -22,6 +22,9 @@ impl LoadCartridgeStep {
|
||||
Color::WHITE
|
||||
);
|
||||
ctx.hub.window_manager.set_focus(id);
|
||||
|
||||
// Apps de sistema não mudam o estado do firmware para GameRunning.
|
||||
// Eles rodam em background ou via janelas no Hub.
|
||||
return Some(FirmwareState::HubHome(HubHomeStep));
|
||||
}
|
||||
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
use crate::firmware::firmware_state::{FirmwareState, SplashScreenStep};
|
||||
use crate::firmware::boot_target::BootTarget;
|
||||
use crate::firmware::firmware_state::{FirmwareState, LaunchHubStep, SplashScreenStep};
|
||||
use crate::firmware::prometeu_context::PrometeuContext;
|
||||
use crate::log::{LogLevel, LogSource};
|
||||
|
||||
@ -11,8 +12,11 @@ impl ResetStep {
|
||||
ctx.os.reset(ctx.vm);
|
||||
}
|
||||
|
||||
pub fn on_update(&mut self, _ctx: &mut PrometeuContext) -> Option<FirmwareState> {
|
||||
Some(FirmwareState::SplashScreen(SplashScreenStep { frame: 0 }))
|
||||
pub fn on_update(&mut self, ctx: &mut PrometeuContext) -> Option<FirmwareState> {
|
||||
match ctx.boot_target {
|
||||
BootTarget::Hub => Some(FirmwareState::SplashScreen(SplashScreenStep { frame: 0 })),
|
||||
BootTarget::Cartridge { .. } => Some(FirmwareState::LaunchHub(LaunchHubStep)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn on_exit(&mut self, _ctx: &mut PrometeuContext) {}
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
mod firmware;
|
||||
pub mod firmware_state;
|
||||
mod boot_target;
|
||||
|
||||
pub(crate) mod firmware_step_reset;
|
||||
pub(crate) mod firmware_step_splash_screen;
|
||||
@ -13,3 +14,4 @@ mod prometeu_context;
|
||||
pub use firmware::Firmware;
|
||||
pub use firmware_state::FirmwareState;
|
||||
pub use prometeu_context::PrometeuContext;
|
||||
pub use boot_target::BootTarget;
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
use crate::firmware::boot_target::BootTarget;
|
||||
use crate::hardware::{HardwareBridge, InputSignals};
|
||||
use crate::prometeu_hub::PrometeuHub;
|
||||
use crate::prometeu_os::PrometeuOS;
|
||||
@ -7,6 +8,7 @@ pub struct PrometeuContext<'a> {
|
||||
pub vm: &'a mut VirtualMachine,
|
||||
pub os: &'a mut PrometeuOS,
|
||||
pub hub: &'a mut PrometeuHub,
|
||||
pub boot_target: &'a BootTarget,
|
||||
pub signals: &'a InputSignals,
|
||||
pub hw: &'a mut dyn HardwareBridge,
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user