rename Machine -> LogicalHardware

This commit is contained in:
bQUARKz 2026-01-16 05:41:51 +00:00 committed by Nilton Constantino
parent f26245c8fc
commit f9d90b3cd6
No known key found for this signature in database
5 changed files with 38 additions and 37 deletions

View File

@ -1,8 +1,8 @@
pub mod machine;
pub mod logical_hardware;
pub mod peripherals;
pub mod vm;
mod model;
mod native_interface;
mod utilz;
pub use machine::Machine;
pub use logical_hardware::LogicalHardware;

View File

@ -5,7 +5,7 @@ use std::sync::Arc;
/// PROMETEU "hardware lógico" (v0).
/// O Host alimenta INPUT SIGNALS e chama `step_frame()` em 60Hz.
pub struct Machine {
pub struct LogicalHardware {
pub gfx: Gfx,
pub audio: Audio,
pub pad: Pad,
@ -23,13 +23,13 @@ pub struct Machine {
impl Machine {
impl LogicalHardware {
pub const W: usize = 320;
pub const H: usize = 180;
pub const CYCLES_PER_FRAME: u64 = 100_000; // Exemplo de budget
pub fn new() -> Self {
let mut machine = Self {
let mut logical_hardware = Self {
gfx: Gfx::new(Self::W, Self::H),
audio: Audio::new(),
pad: Pad::default(),
@ -44,9 +44,9 @@ impl Machine {
};
// Inicializa samples básicos
machine.sample_square = Some(Arc::new(Self::create_square_sample(440.0, 0.1)));
logical_hardware.sample_square = Some(Arc::new(Self::create_square_sample(440.0, 0.1)));
machine
logical_hardware
}
pub fn get_color(&self, index: usize) -> Color {
@ -116,7 +116,7 @@ impl Machine {
let start = std::time::Instant::now();
self.begin_frame(signals);
// Retira a VM temporariamente para executar run_budget passando self (Machine) como NativeInterface.
// Retira a VM temporariamente para executar run_budget passando self (Logical Hardware) como NativeInterface.
// Como VirtualMachine implementa Default, usamos std::mem::take.
let mut vm = std::mem::take(&mut self.vm);
let _result = vm.run_budget(Self::CYCLES_PER_FRAME, self);

View File

@ -1,11 +1,11 @@
use crate::vm::{Value, VirtualMachine};
use crate::Machine;
use crate::LogicalHardware;
pub trait NativeInterface {
fn syscall(&mut self, id: u32, vm: &mut VirtualMachine) -> Result<u64, String>;
}
impl NativeInterface for Machine {
impl NativeInterface for LogicalHardware {
fn syscall(&mut self, id: u32, vm: &mut VirtualMachine) -> Result<u64, String> {
match id {
// system.has_cart() -> bool

View File

@ -726,10 +726,10 @@ mod tests {
#[test]
fn test_system_run_cart() {
use crate::Machine;
use crate::LogicalHardware;
use crate::model::Cartridge;
let mut machine = Machine::new();
let mut logical_hardware = LogicalHardware::new();
// 1. Verifica que não tem cartucho inicialmente
let mut rom = Vec::new();
@ -738,12 +738,12 @@ mod tests {
utilz::emit_u32(&mut rom, 0x0001);
utilz::emit_op(&mut rom, OpCode::Halt);
machine.vm = VirtualMachine::new(rom, vec![]);
let mut vm = std::mem::take(&mut machine.vm);
vm.run_budget(100, &mut machine).unwrap();
machine.vm = vm;
logical_hardware.vm = VirtualMachine::new(rom, vec![]);
let mut vm = std::mem::take(&mut logical_hardware.vm);
vm.run_budget(100, &mut logical_hardware).unwrap();
logical_hardware.vm = vm;
assert_eq!(machine.vm.pop().unwrap(), Value::Boolean(false));
assert_eq!(logical_hardware.vm.pop().unwrap(), Value::Boolean(false));
// 2. Adiciona um cartucho e roda
let mut cart_rom = Vec::new();
@ -754,7 +754,7 @@ mod tests {
let cart_pool = vec![Value::Integer(42)];
let cart = Cartridge::new(Program::new(cart_rom, cart_pool));
machine.load_cartridge(cart);
logical_hardware.load_cartridge(cart);
// Código para rodar o cartucho
let mut boot_rom = Vec::new();
@ -762,14 +762,14 @@ mod tests {
utilz::emit_op(&mut boot_rom, OpCode::Syscall);
utilz::emit_u32(&mut boot_rom, 0x0002);
machine.vm = VirtualMachine::new(boot_rom, vec![]);
let mut vm = std::mem::take(&mut machine.vm);
vm.run_budget(1000, &mut machine).unwrap();
machine.vm = vm;
logical_hardware.vm = VirtualMachine::new(boot_rom, vec![]);
let mut vm = std::mem::take(&mut logical_hardware.vm);
vm.run_budget(1000, &mut logical_hardware).unwrap();
logical_hardware.vm = vm;
// Após o run_budget, a VM deve ter executado o cartucho
assert_eq!(machine.vm.operand_stack.last(), Some(&Value::Integer(42)));
assert!(machine.vm.halted);
assert_eq!(logical_hardware.vm.operand_stack.last(), Some(&Value::Integer(42)));
assert!(logical_hardware.vm.halted);
}
#[test]

View File

@ -6,7 +6,7 @@ mod audio_mixer;
use audio_mixer::AudioMixer;
use cpal::traits::{DeviceTrait, HostTrait, StreamTrait};
use prometeu_core::peripherals::{AudioCommand, InputSignals, OUTPUT_SAMPLE_RATE};
use prometeu_core::Machine;
use prometeu_core::LogicalHardware;
use ringbuf::traits::{Consumer, Producer, Split};
use ringbuf::HeapRb;
use std::sync::Arc;
@ -32,7 +32,7 @@ struct PrometeuApp {
window: Option<&'static Window>,
pixels: Option<Pixels<'static>>,
machine: Machine,
logical_hardware: LogicalHardware,
input_signals: InputSignals,
@ -58,7 +58,7 @@ impl PrometeuApp {
window: None,
pixels: None,
machine: Machine::new(),
logical_hardware: LogicalHardware::new(),
input_signals: InputSignals::default(),
@ -160,7 +160,7 @@ impl ApplicationHandler for PrometeuApp {
let size = window.inner_size();
let surface_texture = SurfaceTexture::new(size.width, size.height, window);
let mut pixels = Pixels::new(Machine::W as u32, Machine::H as u32, surface_texture)
let mut pixels = Pixels::new(LogicalHardware::W as u32, LogicalHardware::H as u32, surface_texture)
.expect("failed to create Pixels");
pixels.frame_mut().fill(0);
@ -195,7 +195,7 @@ impl ApplicationHandler for PrometeuApp {
let frame = pixels.frame_mut();
// Borrow imutável do core (campo diferente, ok)
let src = self.machine.gfx.front_buffer();
let src = self.logical_hardware.gfx.front_buffer();
draw_rgb565_to_rgba8(src, frame);
} // <- frame borrow termina aqui
@ -268,11 +268,11 @@ impl ApplicationHandler for PrometeuApp {
// 🔥 O coração do determinismo: consome o tempo em fatias exatas de 60Hz
while self.accumulator >= self.frame_target_dt {
self.machine.step_frame(&self.input_signals);
self.logical_hardware.step_frame(&self.input_signals);
// Envia comandos de áudio gerados neste frame para a thread de áudio
if let Some(producer) = &mut self.audio_producer {
for cmd in self.machine.audio.commands.drain(..) {
for cmd in self.logical_hardware.audio.commands.drain(..) {
let _ = producer.try_push(cmd);
}
}
@ -294,10 +294,11 @@ impl ApplicationHandler for PrometeuApp {
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.machine.gfx.memory_usage_bytes() as f64 / 1024.0;
let kb = self.logical_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.machine.last_frame_cpu_time_us as f64 / frame_budget_us) * 100.0;
let cpu_load_core = (self.logical_hardware.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).
@ -308,7 +309,7 @@ impl ApplicationHandler for PrometeuApp {
let title = format!(
"PROMETEU | GFX: {:.1} KB | FPS: {:.1} | Load: {:.1}% (C) + {:.1}% (A) | Frame: {}",
kb, fps, cpu_load_core, cpu_load_audio, self.machine.frame_index
kb, fps, cpu_load_core, cpu_load_audio, self.logical_hardware.frame_index
);
window.set_title(&title);
}
@ -327,13 +328,13 @@ impl ApplicationHandler for PrometeuApp {
/// Depois podemos fazer letterbox/aspect-ratio correto.
fn window_to_fb(wx: f32, wy: f32, window: &Window) -> (i32, i32) {
let size = window.inner_size();
let fb_w = Machine::W as f32;
let fb_h = Machine::H as f32;
let fb_w = LogicalHardware::W as f32;
let fb_h = LogicalHardware::H as f32;
let x = (wx * fb_w / size.width as f32).floor() as i32;
let y = (wy * fb_h / size.height as f32).floor() as i32;
(x.clamp(0, Machine::W as i32 - 1), y.clamp(0, Machine::H as i32 - 1))
(x.clamp(0, LogicalHardware::W as i32 - 1), y.clamp(0, LogicalHardware::H as i32 - 1))
}
/// Copia RGB565 (u16) -> RGBA8888 (u8[4]) para o frame do pixels.