diff --git a/crates/core/src/firmware/firmware.rs b/crates/core/src/firmware/firmware.rs index 43b50721..ac86a8f3 100644 --- a/crates/core/src/firmware/firmware.rs +++ b/crates/core/src/firmware/firmware.rs @@ -1,6 +1,6 @@ use crate::firmware::firmware_state::FirmwareState; +use crate::hardware::{HardwareBridge, InputSignals}; use crate::model::{AppMode, Cartridge, Color}; -use crate::peripherals::InputSignals; use crate::prometeu_hub::PrometeuHub; use crate::prometeu_os::PrometeuOS; @@ -19,7 +19,7 @@ impl Firmware { } } - pub fn step_frame(&mut self, signals: &InputSignals) { + pub fn step_frame(&mut self, signals: &InputSignals, hw: &mut dyn HardwareBridge) { match &mut self.state { FirmwareState::Reset => { self.os.reset(); @@ -34,33 +34,34 @@ impl Firmware { self.state = FirmwareState::HubHome; } FirmwareState::HubHome => { - // UI do Hub - self.hub.update(&mut self.os); + hw.gfx_mut().clear(Color::INDIGO); + self.hub.gui_update(&mut self.os); + hw.gfx_mut().present(); } FirmwareState::PosRunGame(_cart) => { - if let Some(error) = self.os.step_frame(signals) { + if let Some(error) = self.os.step_frame(signals, hw) { self.state = FirmwareState::PosCrashScreen(error); } } FirmwareState::PosRunSystem(_cart) => { // System Apps rodam "dentro" do Hub/Window System - if let Some(error) = self.os.step_frame(signals) { + if let Some(error) = self.os.step_frame(signals, hw) { self.state = FirmwareState::PosCrashScreen(error); } // TODO: Compor com a UI do Hub } FirmwareState::PosCrashScreen(_error) => { // Atualiza periféricos para input na tela de crash - self.os.hardware_mut().pad_mut().begin_frame(signals); + hw.pad_mut().begin_frame(signals); // Tela de erro: fundo vermelho, texto branco - self.os.hardware_mut().gfx_mut().clear(Color::RED); + hw.gfx_mut().clear(Color::RED); // Por enquanto apenas logamos ou mostramos algo simples // No futuro, usar draw_text - self.os.hardware_mut().gfx_mut().present(); + hw.gfx_mut().present(); // Se apertar START, volta pro Hub - if self.os.hardware().pad().start.down { + if hw.pad().start.down { self.state = FirmwareState::LaunchHubHome; } } diff --git a/crates/core/src/hardware.rs b/crates/core/src/hardware.rs deleted file mode 100644 index ffc738b4..00000000 --- a/crates/core/src/hardware.rs +++ /dev/null @@ -1,57 +0,0 @@ -use crate::peripherals::{Audio, Gfx, InputSignals, Pad, Touch, HardwareBridge}; -use crate::firmware::{Firmware}; - -pub struct Hardware { - pub firmware: Firmware, - pub gfx: Gfx, - pub audio: Audio, - pub pad: Pad, - pub touch: Touch, -} - -impl HardwareBridge for Hardware { - fn gfx(&self) -> &Gfx { &self.gfx } - fn gfx_mut(&mut self) -> &mut Gfx { &mut self.gfx } - - fn audio(&self) -> &Audio { &self.audio } - fn audio_mut(&mut self) -> &mut Audio { &mut self.audio } - - fn pad(&self) -> &Pad { &self.pad } - fn pad_mut(&mut self) -> &mut Pad { &mut self.pad } - - fn touch(&self) -> &Touch { &self.touch } - fn touch_mut(&mut self) -> &mut Touch { &mut self.touch } -} - -impl Hardware { - pub const W: usize = 320; - pub const H: usize = 180; - - pub fn new() -> Box { - let mut hw = Box::new(Self { - firmware: Firmware::new(), - gfx: Gfx::new(Self::W, Self::H), - audio: Audio::new(), - pad: Pad::default(), - touch: Touch::default(), - }); - - // Configura a referência circular (através do trait HardwareBridge) - let hw_ptr = hw.as_mut() as *mut dyn HardwareBridge; - hw.firmware.os.hw_ptr = Some(hw_ptr); - - hw - } - - /// Atalhos para o Runner (desktop) não quebrar tanto, - /// delegando para o PrometeuOS onde os contadores agora vivem. - pub fn tick_index(&self) -> u64 { self.firmware.os.tick_index } - pub fn logical_frame_index(&self) -> u64 { self.firmware.os.logical_frame_index } - pub fn last_frame_cpu_time_us(&self) -> u64 { self.firmware.os.last_frame_cpu_time_us } - - /// "Contrato de frame" do PROMETEU. - pub fn step_frame(&mut self, signals: &InputSignals) { - // O Host chama o hardware, que delega para o Firmware/OS. - self.firmware.step_frame(signals); - } -} diff --git a/crates/core/src/peripherals/audio.rs b/crates/core/src/hardware/audio.rs similarity index 100% rename from crates/core/src/peripherals/audio.rs rename to crates/core/src/hardware/audio.rs diff --git a/crates/core/src/peripherals/gfx.rs b/crates/core/src/hardware/gfx.rs similarity index 100% rename from crates/core/src/peripherals/gfx.rs rename to crates/core/src/hardware/gfx.rs diff --git a/crates/core/src/hardware/hardware.rs b/crates/core/src/hardware/hardware.rs new file mode 100644 index 00000000..031c8468 --- /dev/null +++ b/crates/core/src/hardware/hardware.rs @@ -0,0 +1,36 @@ +use crate::hardware::{Audio, Gfx, HardwareBridge, Pad, Touch}; + +pub struct Hardware { + pub gfx: Gfx, + pub audio: Audio, + pub pad: Pad, + pub touch: Touch, +} + +impl HardwareBridge for Hardware { + fn gfx(&self) -> &Gfx { &self.gfx } + fn gfx_mut(&mut self) -> &mut Gfx { &mut self.gfx } + + fn audio(&self) -> &Audio { &self.audio } + fn audio_mut(&mut self) -> &mut Audio { &mut self.audio } + + fn pad(&self) -> &Pad { &self.pad } + fn pad_mut(&mut self) -> &mut Pad { &mut self.pad } + + fn touch(&self) -> &Touch { &self.touch } + fn touch_mut(&mut self) -> &mut Touch { &mut self.touch } +} + +impl Hardware { + pub const W: usize = 320; + pub const H: usize = 180; + + pub fn new() -> Self { + Self { + gfx: Gfx::new(Self::W, Self::H), + audio: Audio::new(), + pad: Pad::default(), + touch: Touch::default(), + } + } +} diff --git a/crates/core/src/peripherals/input_signal.rs b/crates/core/src/hardware/input_signal.rs similarity index 100% rename from crates/core/src/peripherals/input_signal.rs rename to crates/core/src/hardware/input_signal.rs diff --git a/crates/core/src/peripherals/mod.rs b/crates/core/src/hardware/mod.rs similarity index 71% rename from crates/core/src/peripherals/mod.rs rename to crates/core/src/hardware/mod.rs index bd102bb3..e530dc0a 100644 --- a/crates/core/src/peripherals/mod.rs +++ b/crates/core/src/hardware/mod.rs @@ -3,16 +3,15 @@ mod pad; mod touch; mod input_signal; mod audio; +pub mod hardware; pub use gfx::Gfx; pub use gfx::BlendMode; pub use input_signal::InputSignals; pub use pad::Pad; pub use touch::Touch; -pub use audio::{Audio, Channel, AudioCommand, LoopMode, MAX_CHANNELS, OUTPUT_SAMPLE_RATE}; +pub use audio::{Audio, AudioCommand, Channel, LoopMode, MAX_CHANNELS, OUTPUT_SAMPLE_RATE}; -/// Interface de acesso ao hardware para o Firmware/OS. -/// Centraliza as chamadas para periféricos sem expor a estrutura interna do HardwareBridge. pub trait HardwareBridge { fn gfx(&self) -> &Gfx; fn gfx_mut(&mut self) -> &mut Gfx; diff --git a/crates/core/src/peripherals/pad.rs b/crates/core/src/hardware/pad.rs similarity index 95% rename from crates/core/src/peripherals/pad.rs rename to crates/core/src/hardware/pad.rs index 8fc58bac..473e55fd 100644 --- a/crates/core/src/peripherals/pad.rs +++ b/crates/core/src/hardware/pad.rs @@ -1,5 +1,5 @@ use crate::model::Button; -use crate::peripherals::input_signal::InputSignals; +use crate::hardware::input_signal::InputSignals; #[derive(Default, Clone, Copy, Debug)] pub struct Pad { diff --git a/crates/core/src/peripherals/touch.rs b/crates/core/src/hardware/touch.rs similarity index 88% rename from crates/core/src/peripherals/touch.rs rename to crates/core/src/hardware/touch.rs index 88f019f6..7b6fc47b 100644 --- a/crates/core/src/peripherals/touch.rs +++ b/crates/core/src/hardware/touch.rs @@ -1,5 +1,5 @@ use crate::model::Button; -use crate::peripherals::input_signal::InputSignals; +use crate::hardware::input_signal::InputSignals; #[derive(Default, Clone, Copy, Debug)] pub struct Touch { diff --git a/crates/core/src/lib.rs b/crates/core/src/lib.rs index cad9e75c..50aff840 100644 --- a/crates/core/src/lib.rs +++ b/crates/core/src/lib.rs @@ -1,9 +1,8 @@ pub mod hardware; -pub mod peripherals; pub mod vm; mod model; pub mod firmware; mod prometeu_os; mod prometeu_hub; -pub use hardware::Hardware; +pub use hardware::hardware::Hardware; diff --git a/crates/core/src/prometeu_hub/prometeu_hub.rs b/crates/core/src/prometeu_hub/prometeu_hub.rs index 5ea2b5e6..01a0c860 100644 --- a/crates/core/src/prometeu_hub/prometeu_hub.rs +++ b/crates/core/src/prometeu_hub/prometeu_hub.rs @@ -31,10 +31,7 @@ impl PrometeuHub { // Inicializa o Window System e lista apps } - pub fn update(&mut self, os: &mut PrometeuOS) { - // Renderiza a UI básica do Hub - os.hardware_mut().gfx_mut().clear(self.window_system.theme_color); - // TODO: Desenhar lista de apps - os.hardware_mut().gfx_mut().present(); + pub fn gui_update(&mut self, _os: &mut PrometeuOS) { + // Atualiza a UI do Window System } } \ No newline at end of file diff --git a/crates/core/src/prometeu_os/mod.rs b/crates/core/src/prometeu_os/mod.rs index d2c3ae9c..df032309 100644 --- a/crates/core/src/prometeu_os/mod.rs +++ b/crates/core/src/prometeu_os/mod.rs @@ -1,5 +1,4 @@ mod prometeu_os; -mod native_interface; pub use prometeu_os::PrometeuOS; -pub use native_interface::NativeInterface; \ No newline at end of file +pub use crate::vm::native_interface::NativeInterface; \ No newline at end of file diff --git a/crates/core/src/prometeu_os/native_interface.rs b/crates/core/src/prometeu_os/native_interface.rs deleted file mode 100644 index f96ce8db..00000000 --- a/crates/core/src/prometeu_os/native_interface.rs +++ /dev/null @@ -1,73 +0,0 @@ -use crate::prometeu_os::prometeu_os::PrometeuOS; -use crate::vm::{Value, VirtualMachine}; - -pub trait NativeInterface { - fn syscall(&mut self, id: u32, vm: &mut VirtualMachine) -> Result; -} - -impl NativeInterface for PrometeuOS { - fn syscall(&mut self, id: u32, vm: &mut VirtualMachine) -> Result { - match id { - // system.has_cart() -> bool - 0x0001 => { - vm.push(Value::Boolean(self.current_cartridge.is_some())); - Ok(10) - } - // system.run_cart() - 0x0002 => { - if let Some(cart) = self.current_cartridge.as_ref().cloned() { - self.load_cartridge(&cart); - } else { - return Err("No cartridge inserted".into()); - } - Ok(100) - } - // gfx.clear(color_index) - 0x1001 => { - let color_idx = vm.pop_integer()? as usize; - let color = self.get_color(color_idx); - self.hardware_mut().gfx_mut().clear(color); - Ok(100) - } - // gfx.draw_rect(x, y, w, h, color_index) - 0x1002 => { - let color_idx = vm.pop_integer()? as usize; - let h = vm.pop_integer()? as i32; - let w = vm.pop_integer()? as i32; - let y = vm.pop_integer()? as i32; - let x = vm.pop_integer()? as i32; - let color = self.get_color(color_idx); - self.hardware_mut().gfx_mut().fill_rect(x, y, w, h, color); - Ok(200) - } - // input.get_pad(button_id) -> bool - 0x2001 => { - let button_id = vm.pop_integer()? as u32; - let is_down = self.is_button_down(button_id); - vm.push(Value::Boolean(is_down)); - Ok(50) - } - // audio.play_sample(sample_id, voice_id, volume, pan, pitch) - 0x3001 => { - let pitch = vm.pop_number()?; - let pan = vm.pop_integer()? as u8; - let volume = vm.pop_integer()? as u8; - let voice_id = vm.pop_integer()? as usize; - let sample_id = vm.pop_integer()? as u32; - - let sample = match sample_id { - 0 => self.sample_square.clone(), - 1 => self.sample_kick.clone(), - 2 => self.sample_snare.clone(), - _ => None, - }; - - if let Some(s) = sample { - self.hardware_mut().audio_mut().play(s, voice_id, volume, pan, pitch, 0, crate::peripherals::LoopMode::Off); - } - Ok(300) - } - _ => Err(format!("Unknown syscall: 0x{:08X}", id)), - } - } -} \ No newline at end of file diff --git a/crates/core/src/prometeu_os/prometeu_os.rs b/crates/core/src/prometeu_os/prometeu_os.rs index d5bfba8c..e3fdc11f 100644 --- a/crates/core/src/prometeu_os/prometeu_os.rs +++ b/crates/core/src/prometeu_os/prometeu_os.rs @@ -1,7 +1,8 @@ use crate::model::{Cartridge, Color, Sample}; -use crate::peripherals::{HardwareBridge, InputSignals}; -use crate::vm::VirtualMachine; +use crate::hardware::{HardwareBridge, InputSignals}; +use crate::vm::{Value, VirtualMachine}; use std::sync::Arc; +use crate::prometeu_os::NativeInterface; /// PrometeuOS (POS): O firmware/base do sistema. /// Autoridade máxima do boot, periféricos, execução da PVM e tratamento de falhas. @@ -11,8 +12,6 @@ pub struct PrometeuOS { pub logical_frame_index: u64, pub logical_frame_open: bool, pub last_frame_cpu_time_us: u64, - pub hw_ptr: Option<*mut dyn HardwareBridge>, - pub current_cartridge: Option, // Assets de exemplo (mantidos para compatibilidade com syscalls de áudio v0) pub sample_square: Option>, @@ -26,12 +25,10 @@ impl PrometeuOS { pub fn new() -> Self { let mut os = Self { vm: VirtualMachine::default(), - hw_ptr: None, tick_index: 0, logical_frame_index: 0, logical_frame_open: false, last_frame_cpu_time_us: 0, - current_cartridge: None, sample_square: None, sample_kick: None, sample_snare: None, @@ -43,31 +40,17 @@ impl PrometeuOS { os } - /// Helper para acessar o hardware de forma segura (dentro do contexto do firmware). - #[inline] - pub fn hardware(&self) -> &dyn HardwareBridge { - unsafe { &*self.hw_ptr.expect("Hardware pointer not initialized") } - } - - /// Helper para acessar o hardware de forma mutável. - #[inline] - pub fn hardware_mut(&mut self) -> &mut dyn HardwareBridge { - unsafe { &mut *self.hw_ptr.expect("Hardware pointer not initialized") } - } - pub fn reset(&mut self) { self.vm = VirtualMachine::default(); self.tick_index = 0; self.logical_frame_index = 0; self.logical_frame_open = false; self.last_frame_cpu_time_us = 0; - self.current_cartridge = None; } /// Carrega um cartucho na PVM e reseta o estado de execução. pub fn load_cartridge(&mut self, cart: &Cartridge) { // Na spec: "resetar PC/stack/heap ao iniciar app" - self.current_cartridge = Some(cart.clone()); self.vm.program = cart.program.clone(); self.vm.pc = 0; self.vm.operand_stack.clear(); @@ -78,25 +61,25 @@ impl PrometeuOS { } /// Executa um tick do host (60Hz). - pub fn step_frame(&mut self, signals: &InputSignals) -> Option { + pub fn step_frame(&mut self, signals: &InputSignals, hw: &mut dyn HardwareBridge) -> Option { let start = std::time::Instant::now(); self.tick_index += 1; if !self.logical_frame_open { self.logical_frame_open = true; - self.begin_logical_frame(signals); + self.begin_logical_frame(signals, hw); } // Executa budget let mut vm = std::mem::take(&mut self.vm); - let run_result = vm.run_budget(Self::CYCLES_PER_FRAME, self); + let run_result = vm.run_budget(Self::CYCLES_PER_FRAME, self, hw); self.vm = vm; match run_result { Ok(run) => { if run.reason == crate::vm::LogicalFrameEndingReason::FrameSync { - self.hardware_mut().gfx_mut().render_all(); - self.end_logical_frame(); + hw.gfx_mut().render_all(); + self.end_logical_frame(hw); self.logical_frame_index += 1; self.logical_frame_open = false; } @@ -110,20 +93,18 @@ impl PrometeuOS { None } - fn begin_logical_frame(&mut self, signals: &InputSignals) { - let hw = self.hardware_mut(); + fn begin_logical_frame(&mut self, signals: &InputSignals, hw: &mut dyn HardwareBridge) { hw.audio_mut().clear_commands(); hw.touch_mut().begin_frame(signals); hw.pad_mut().begin_frame(signals); } - fn end_logical_frame(&mut self) { - self.hardware_mut().gfx_mut().present(); + fn end_logical_frame(&mut self, hw: &mut dyn HardwareBridge) { + hw.gfx_mut().present(); } // Helper para syscalls - pub fn get_color(&self, index: usize) -> Color { - let hw = self.hardware(); + pub fn get_color(&self, index: usize, hw: &mut dyn HardwareBridge) -> Color { if let Some(bank) = hw.gfx().banks[0].as_ref() { bank.palettes[0][index % 16] } else { @@ -143,8 +124,7 @@ impl PrometeuOS { } // Helper para syscalls - pub fn is_button_down(&self, id: u32) -> bool { - let hw = self.hardware(); + pub fn is_button_down(&self, id: u32, hw: &mut dyn HardwareBridge) -> bool { match id { 0 => hw.pad().up.down, 1 => hw.pad().down.down, @@ -163,7 +143,7 @@ impl PrometeuOS { } fn create_square_sample(freq: f64, duration: f64) -> Sample { - let sample_rate = crate::peripherals::OUTPUT_SAMPLE_RATE; + let sample_rate = crate::hardware::OUTPUT_SAMPLE_RATE; let num_samples = (duration * sample_rate as f64) as usize; let mut data = Vec::with_capacity(num_samples); let period = sample_rate as f64 / freq; @@ -179,4 +159,71 @@ impl PrometeuOS { Sample::new(sample_rate, data) } +} + +impl NativeInterface for PrometeuOS { + fn syscall(&mut self, id: u32, vm: &mut VirtualMachine, hw: &mut dyn HardwareBridge) -> Result { + match id { + // system.has_cart() -> bool + 0x0001 => { + // vm.push(Value::Boolean(self.current_cartridge.is_some())); + Ok(10) + } + // system.run_cart() + 0x0002 => { + // if let Some(cart) = self.current_cartridge.as_ref().cloned() { + // self.load_cartridge(&cart); + // } else { + // return Err("No cartridge inserted".into()); + // } + Ok(100) + } + // gfx.clear(color_index) + 0x1001 => { + let color_idx = vm.pop_integer()? as usize; + let color = self.get_color(color_idx, hw); + hw.gfx_mut().clear(color); + Ok(100) + } + // gfx.draw_rect(x, y, w, h, color_index) + 0x1002 => { + let color_idx = vm.pop_integer()? as usize; + let h = vm.pop_integer()? as i32; + let w = vm.pop_integer()? as i32; + let y = vm.pop_integer()? as i32; + let x = vm.pop_integer()? as i32; + let color = self.get_color(color_idx, hw); + hw.gfx_mut().fill_rect(x, y, w, h, color); + Ok(200) + } + // input.get_pad(button_id) -> bool + 0x2001 => { + let button_id = vm.pop_integer()? as u32; + let is_down = self.is_button_down(button_id, hw); + vm.push(Value::Boolean(is_down)); + Ok(50) + } + // audio.play_sample(sample_id, voice_id, volume, pan, pitch) + 0x3001 => { + let pitch = vm.pop_number()?; + let pan = vm.pop_integer()? as u8; + let volume = vm.pop_integer()? as u8; + let voice_id = vm.pop_integer()? as usize; + let sample_id = vm.pop_integer()? as u32; + + let sample = match sample_id { + 0 => self.sample_square.clone(), + 1 => self.sample_kick.clone(), + 2 => self.sample_snare.clone(), + _ => None, + }; + + if let Some(s) = sample { + hw.audio_mut().play(s, voice_id, volume, pan, pitch, 0, crate::hardware::LoopMode::Off); + } + Ok(300) + } + _ => Err(format!("Unknown syscall: 0x{:08X}", id)), + } + } } \ No newline at end of file diff --git a/crates/core/src/vm/mod.rs b/crates/core/src/vm/mod.rs index a1640c03..ac6b269f 100644 --- a/crates/core/src/vm/mod.rs +++ b/crates/core/src/vm/mod.rs @@ -3,6 +3,7 @@ mod value; mod opcode; mod call_frame; mod program; +pub mod native_interface; pub use opcode::OpCode; pub use program::Program; diff --git a/crates/core/src/vm/native_interface.rs b/crates/core/src/vm/native_interface.rs new file mode 100644 index 00000000..59839042 --- /dev/null +++ b/crates/core/src/vm/native_interface.rs @@ -0,0 +1,6 @@ +use crate::hardware::HardwareBridge; +use crate::vm::VirtualMachine; + +pub trait NativeInterface { + fn syscall(&mut self, id: u32, vm: &mut VirtualMachine, hw: &mut dyn HardwareBridge) -> Result; +} \ No newline at end of file diff --git a/crates/core/src/vm/virtual_machine.rs b/crates/core/src/vm/virtual_machine.rs index 9197d1c4..74b8d635 100644 --- a/crates/core/src/vm/virtual_machine.rs +++ b/crates/core/src/vm/virtual_machine.rs @@ -1,3 +1,4 @@ +use crate::hardware::HardwareBridge; use crate::prometeu_os::NativeInterface; use crate::vm::call_frame::CallFrame; use crate::vm::opcode::OpCode; @@ -54,7 +55,8 @@ impl VirtualMachine { pub fn run_budget( &mut self, budget: u64, - native: &mut dyn NativeInterface + native: &mut dyn NativeInterface, + hw: &mut dyn HardwareBridge, ) -> Result { let start_cycles = self.cycles; let mut ending_reason: Option = None; @@ -76,7 +78,7 @@ impl VirtualMachine { break; } - self.step(native)?; + self.step(native, hw)?; // garante progresso real if self.pc == pc_before && self.cycles == cycles_before && !self.halted { @@ -111,7 +113,7 @@ impl VirtualMachine { Ok(u16::from_le_bytes(bytes)) } - pub fn step(&mut self, native: &mut dyn NativeInterface) -> Result<(), String> { + pub fn step(&mut self, native: &mut dyn NativeInterface, hw: &mut dyn HardwareBridge) -> Result<(), String> { if self.halted || self.pc >= self.program.rom.len() { return Ok(()); } @@ -325,7 +327,7 @@ impl VirtualMachine { } OpCode::Syscall => { let id = self.read_u32()?; - let native_cycles = native.syscall(id, self).map_err(|e| format!("syscall 0x{:08X} failed: {}", id, e))?; + let native_cycles = native.syscall(id, self, hw).map_err(|e| format!("syscall 0x{:08X} failed: {}", id, e))?; self.cycles += native_cycles; } OpCode::FrameSync => { diff --git a/crates/host_desktop/src/audio_mixer.rs b/crates/host_desktop/src/audio_mixer.rs index 5eb9e3b5..9423a2d2 100644 --- a/crates/host_desktop/src/audio_mixer.rs +++ b/crates/host_desktop/src/audio_mixer.rs @@ -1,4 +1,4 @@ -use prometeu_core::peripherals::{AudioCommand, Channel, LoopMode, MAX_CHANNELS, OUTPUT_SAMPLE_RATE}; +use prometeu_core::hardware::{AudioCommand, Channel, LoopMode, MAX_CHANNELS, OUTPUT_SAMPLE_RATE}; use std::time::Duration; diff --git a/crates/host_desktop/src/prometeu_runner.rs b/crates/host_desktop/src/prometeu_runner.rs index 591a8df3..563d4106 100644 --- a/crates/host_desktop/src/prometeu_runner.rs +++ b/crates/host_desktop/src/prometeu_runner.rs @@ -1,7 +1,8 @@ use crate::audio_mixer::AudioMixer; use cpal::traits::{DeviceTrait, HostTrait, StreamTrait}; use pixels::{Pixels, SurfaceTexture}; -use prometeu_core::peripherals::{AudioCommand, InputSignals, OUTPUT_SAMPLE_RATE}; +use prometeu_core::firmware::Firmware; +use prometeu_core::hardware::{AudioCommand, InputSignals, OUTPUT_SAMPLE_RATE}; use prometeu_core::Hardware; use ringbuf::traits::{Consumer, Producer, Split}; use ringbuf::HeapRb; @@ -18,7 +19,8 @@ pub struct PrometeuRunner { window: Option<&'static Window>, pixels: Option>, - hardware_bridge: Box, + hardware: Hardware, + firmware: Firmware, input_signals: InputSignals, @@ -43,7 +45,8 @@ impl PrometeuRunner { Self { window: None, pixels: None, - hardware_bridge: Hardware::new(), + hardware: Hardware::new(), + firmware: Firmware::new(), input_signals: InputSignals::default(), frame_target_dt: Duration::from_nanos(1_000_000_000 / target_fps), last_frame_time: Instant::now(), @@ -180,7 +183,7 @@ impl ApplicationHandler for PrometeuRunner { let frame = pixels.frame_mut(); // Borrow imutável do core (campo diferente, ok) - let src = self.hardware_bridge.gfx.front_buffer(); + let src = self.hardware.gfx.front_buffer(); draw_rgb565_to_rgba8(src, frame); } // <- frame borrow termina aqui @@ -253,11 +256,11 @@ 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.hardware_bridge.step_frame(&self.input_signals); + 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 { - for cmd in self.hardware_bridge.audio.commands.drain(..) { + for cmd in self.hardware.audio.commands.drain(..) { let _ = producer.try_push(cmd); } } @@ -279,11 +282,11 @@ impl ApplicationHandler for PrometeuRunner { if stats_elapsed >= Duration::from_secs(1) { if let Some(window) = self.window { let fps = self.frames_since_last_update as f64 / stats_elapsed.as_secs_f64(); - let kb = self.hardware_bridge.gfx.memory_usage_bytes() as f64 / 1024.0; + let kb = self.hardware.gfx.memory_usage_bytes() as f64 / 1024.0; // comparação fixa sempre contra 60Hz, manter mesmo quando fazer teste de stress na CPU let frame_budget_us = 16666.0; - let cpu_load_core = (self.hardware_bridge.last_frame_cpu_time_us() as f64 / frame_budget_us) * 100.0; + let cpu_load_core = (self.firmware.os.last_frame_cpu_time_us as f64 / frame_budget_us) * 100.0; let cpu_load_audio = if self.audio_load_samples > 0 { // O load real é (tempo total processando) / (tempo total de parede). @@ -294,7 +297,7 @@ impl ApplicationHandler for PrometeuRunner { let title = format!( "PROMETEU | GFX: {:.1} KB | FPS: {:.1} | Load: {:.1}% (C) + {:.1}% (A) | Frame: tick {} logical {}", - kb, fps, cpu_load_core, cpu_load_audio, self.hardware_bridge.tick_index(), self.hardware_bridge.logical_frame_index() + kb, fps, cpu_load_core, cpu_load_audio, self.firmware.os.tick_index, self.firmware.os.logical_frame_index ); window.set_title(&title); }