diff --git a/crates/core/src/c_button.rs b/crates/core/src/c_button.rs new file mode 100644 index 00000000..edb89c03 --- /dev/null +++ b/crates/core/src/c_button.rs @@ -0,0 +1,25 @@ +#[derive(Default, Clone, Copy, Debug)] +pub struct CButton { + pub pressed: bool, + pub released: bool, + pub down: bool, + pub hold_frames: u32, +} + +impl CButton { + pub fn begin_frame(&mut self, is_down_now: bool) { + let was_down = self.down; + self.down = is_down_now; + + // Detecta transições + self.pressed = !was_down && self.down; + self.released = was_down && !self.down; + + // Atualiza contador de frames + if self.down { + self.hold_frames = self.hold_frames.saturating_add(1); + } else { + self.hold_frames = 0; + } + } +} \ No newline at end of file diff --git a/crates/core/src/lib.rs b/crates/core/src/lib.rs index 9fa88ef4..e3050d0d 100644 --- a/crates/core/src/lib.rs +++ b/crates/core/src/lib.rs @@ -1,6 +1,7 @@ pub mod machine; pub mod peripherals; mod color; +mod c_button; pub use machine::Machine; pub use color::Color; diff --git a/crates/core/src/machine.rs b/crates/core/src/machine.rs index f8dc2603..83e95ffd 100644 --- a/crates/core/src/machine.rs +++ b/crates/core/src/machine.rs @@ -1,11 +1,11 @@ -use crate::peripherals::{Gfx, Input, Touch}; +use crate::peripherals::{Gfx, InputSignals, Pad, Touch}; use crate::Color; /// PROMETEU "hardware lógico" (v0). /// O Host alimenta INPUT/TOUCH e chama `step_frame()` em 60Hz. pub struct Machine { pub gfx: Gfx, - pub input: Input, + pub pad: Pad, pub touch: Touch, pub frame_index: u64, } @@ -17,7 +17,7 @@ impl Machine { pub fn new() -> Self { Self { gfx: Gfx::new(Self::W, Self::H), - input: Input::default(), + pad: Pad::default(), touch: Touch::default(), frame_index: 0, } @@ -25,21 +25,21 @@ impl Machine { /// "Contrato de frame" do PROMETEU (Template Method sem loop). /// O Host controla tempo/event loop; o Core define a sequência do frame. - pub fn step_frame(&mut self) { - self.begin_frame(); + pub fn step_frame(&mut self, signals: &InputSignals) { + self.begin_frame(signals); self.tick(); // futuro: executa cartucho/VM self.end_frame(); // present/housekeeping } /// Início do frame: zera flags transitórias. - pub fn begin_frame(&mut self) { + pub fn begin_frame(&mut self, signals: &InputSignals) { self.frame_index += 1; // Flags transitórias do TOUCH devem durar 1 frame. - self.touch.begin_frame(); + self.touch.begin_frame(signals); // Se você quiser input com pressed/released depois: - // self.input.begin_frame(); + self.pad.begin_frame(signals); } /// Lógica do frame (demo hardcoded por enquanto). @@ -48,7 +48,7 @@ impl Machine { let (x, y) = self.demo_pos(); - let color = if self.input.a_down || self.touch.down { + let color = if self.pad.a.down || self.touch.f.down { Color::rgb(0x00, 0xFF, 0x00) } else { Color::rgb(0xFF, 0x40, 0x40) diff --git a/crates/core/src/peripherals/input.rs b/crates/core/src/peripherals/input.rs deleted file mode 100644 index 15b0d7f2..00000000 --- a/crates/core/src/peripherals/input.rs +++ /dev/null @@ -1,20 +0,0 @@ -#[derive(Default, Clone, Copy, Debug)] -pub struct Input { - pub up: bool, - pub down: bool, - pub left: bool, - pub right: bool, - - pub a_down: bool, - pub b_down: bool, - - pub start: bool, - pub select: bool, -} - -impl Input { - pub fn begin_frame(&mut self) { - // No v0, nada a fazer. - // No futuro: a_pressed/a_released, etc. - } -} diff --git a/crates/core/src/peripherals/input_signal.rs b/crates/core/src/peripherals/input_signal.rs new file mode 100644 index 00000000..97feea76 --- /dev/null +++ b/crates/core/src/peripherals/input_signal.rs @@ -0,0 +1,26 @@ +#[derive(Default, Clone, Copy, Debug)] +pub struct InputSignals { + // PAD + pub up_signal: bool, + pub down_signal: bool, + pub left_signal: bool, + pub right_signal: bool, + + pub a_signal: bool, + pub d_signal: bool, + pub w_signal: bool, + pub s_signal: bool, + pub q_signal: bool, + pub e_signal: bool, + + pub start_signal: bool, + pub select_signal: bool, + + // TOUCH + pub t_signal: bool, + pub x_pos: i32, + pub y_pos: i32, +} + +impl InputSignals { +} \ No newline at end of file diff --git a/crates/core/src/peripherals/mod.rs b/crates/core/src/peripherals/mod.rs index 3f7225d7..d319df4a 100644 --- a/crates/core/src/peripherals/mod.rs +++ b/crates/core/src/peripherals/mod.rs @@ -1,7 +1,9 @@ mod gfx; -mod input; +mod pad; mod touch; +mod input_signal; pub use gfx::Gfx; -pub use input::Input; +pub use input_signal::InputSignals; +pub use pad::Pad; pub use touch::Touch; diff --git a/crates/core/src/peripherals/pad.rs b/crates/core/src/peripherals/pad.rs new file mode 100644 index 00000000..a2d297ee --- /dev/null +++ b/crates/core/src/peripherals/pad.rs @@ -0,0 +1,41 @@ +use crate::c_button::CButton; +use crate::peripherals::input_signal::InputSignals; + +#[derive(Default, Clone, Copy, Debug)] +pub struct Pad { + pub up: CButton, + pub down: CButton, + pub left: CButton, + pub right: CButton, + + pub a: CButton, // ps: square + pub d: CButton, // ps: circle + pub w: CButton, // ps: triangle + pub s: CButton, // ps: cross + pub q: CButton, // ps: R + pub e: CButton, // ps: L + + pub start: CButton, + pub select: CButton, +} + +impl Pad { + pub fn begin_frame(&mut self, signals: &InputSignals) { + self.up.begin_frame(signals.up_signal); + self.down.begin_frame(signals.down_signal); + self.left.begin_frame(signals.left_signal); + self.right.begin_frame(signals.right_signal); + + self.a.begin_frame(signals.a_signal); + self.d.begin_frame(signals.d_signal); + self.w.begin_frame(signals.w_signal); + self.s.begin_frame(signals.s_signal); + self.q.begin_frame(signals.q_signal); + self.e.begin_frame(signals.e_signal); + + self.start.begin_frame(signals.start_signal); + self.select.begin_frame(signals.select_signal); + } +} + + diff --git a/crates/core/src/peripherals/touch.rs b/crates/core/src/peripherals/touch.rs index e7fea20c..54c1678f 100644 --- a/crates/core/src/peripherals/touch.rs +++ b/crates/core/src/peripherals/touch.rs @@ -1,17 +1,18 @@ +use crate::c_button::CButton; +use crate::peripherals::input_signal::InputSignals; + #[derive(Default, Clone, Copy, Debug)] pub struct Touch { - pub present: bool, - pub down: bool, - pub pressed: bool, - pub released: bool, + pub f: CButton, pub x: i32, pub y: i32, } impl Touch { /// Flags transitórias devem durar apenas 1 frame. - pub fn begin_frame(&mut self) { - self.pressed = false; - self.released = false; + pub fn begin_frame(&mut self, signals: &InputSignals) { + self.f.begin_frame(signals.t_signal); + self.x = signals.x_pos; + self.y = signals.y_pos; } } diff --git a/crates/host_desktop/src/main.rs b/crates/host_desktop/src/main.rs index fe573f53..77c72f47 100644 --- a/crates/host_desktop/src/main.rs +++ b/crates/host_desktop/src/main.rs @@ -1,6 +1,7 @@ use std::time::{Duration, Instant}; use pixels::{Pixels, SurfaceTexture}; +use prometeu_core::peripherals::InputSignals; use prometeu_core::Machine; use winit::{ application::ApplicationHandler, @@ -23,15 +24,13 @@ fn main() -> Result<(), Box> { struct PrometeuApp { window: Option<&'static Window>, pixels: Option>, + machine: Machine, + input_signals: InputSignals, + frame_dt: Duration, next_frame: Instant, - - mouse_down: bool, - mouse_just_pressed: bool, - mouse_just_released: bool, - mouse_pos_fb: (i32, i32), } impl PrometeuApp { @@ -39,15 +38,11 @@ impl PrometeuApp { Self { window: None, pixels: None, + input_signals: InputSignals::default(), machine: Machine::new(), frame_dt: Duration::from_nanos(1_000_000_000 / 60), next_frame: Instant::now(), - - mouse_down: false, - mouse_just_pressed: false, - mouse_just_released: false, - mouse_pos_fb: (0, 0), } } @@ -70,39 +65,6 @@ impl PrometeuApp { w.request_redraw(); } } - - fn map_key(&mut self, code: KeyCode, is_down: bool) { - match code { - KeyCode::ArrowUp => self.machine.input.up = is_down, - KeyCode::ArrowDown => self.machine.input.down = is_down, - KeyCode::ArrowLeft => self.machine.input.left = is_down, - KeyCode::ArrowRight => self.machine.input.right = is_down, - - // A/B (troque depois como quiser) - KeyCode::KeyZ => self.machine.input.a_down = is_down, - KeyCode::KeyX => self.machine.input.b_down = is_down, - - KeyCode::Enter => self.machine.input.start = is_down, - KeyCode::ShiftLeft | KeyCode::ShiftRight => self.machine.input.select = is_down, - - _ => {} - } - } - - fn update_touch_in_core(&mut self) { - // no desktop, mouse emula touch - self.machine.touch.present = true; - self.machine.touch.x = self.mouse_pos_fb.0; - self.machine.touch.y = self.mouse_pos_fb.1; - - // pressed/released devem durar 1 frame (o core limpa em begin_frame) - self.machine.touch.pressed = self.mouse_just_pressed; - self.machine.touch.released = self.mouse_just_released; - self.machine.touch.down = self.mouse_down; - - self.mouse_just_pressed = false; - self.mouse_just_released = false; - } } impl ApplicationHandler for PrometeuApp { @@ -169,28 +131,42 @@ impl ApplicationHandler for PrometeuApp { WindowEvent::KeyboardInput { event, .. } => { if let PhysicalKey::Code(code) = event.physical_key { let is_down = event.state == ElementState::Pressed; - self.map_key(code, is_down); + match code { + KeyCode::ArrowUp => self.input_signals.up_signal = is_down, + KeyCode::ArrowDown => self.input_signals.down_signal = is_down, + KeyCode::ArrowLeft => self.input_signals.left_signal = is_down, + KeyCode::ArrowRight => self.input_signals.right_signal = is_down, + + // A/B (troque depois como quiser) + KeyCode::KeyA => self.input_signals.a_signal = is_down, + KeyCode::KeyD => self.input_signals.d_signal = is_down, + KeyCode::KeyW => self.input_signals.w_signal = is_down, + KeyCode::KeyS => self.input_signals.s_signal = is_down, + KeyCode::KeyQ => self.input_signals.q_signal = is_down, + KeyCode::KeyE => self.input_signals.e_signal = is_down, + + KeyCode::KeyZ => self.input_signals.start_signal = is_down, + KeyCode::ShiftLeft | KeyCode::ShiftRight => self.input_signals.select_signal = is_down, + + _ => {} + } } } WindowEvent::CursorMoved { position, .. } => { - self.mouse_pos_fb = window_to_fb(position.x as f32, position.y as f32, self.window()); + let v = window_to_fb(position.x as f32, position.y as f32, self.window()); + self.input_signals.x_pos = v.0; + self.input_signals.y_pos = v.1; } WindowEvent::MouseInput { state, button, .. } => { if button == MouseButton::Left { match state { ElementState::Pressed => { - if !self.mouse_down { - self.mouse_down = true; - self.mouse_just_pressed = true; - } + self.input_signals.t_signal = true; } ElementState::Released => { - if self.mouse_down { - self.mouse_down = false; - self.mouse_just_released = true; - } + self.input_signals.t_signal = false; } } } @@ -207,11 +183,8 @@ impl ApplicationHandler for PrometeuApp { if now >= self.next_frame { self.next_frame += self.frame_dt; - // atualiza touch/input no core - self.update_touch_in_core(); - // executa 1 frame do PROMETEU - self.machine.step_frame(); + self.machine.step_frame(&self.input_signals); // pede redraw self.request_redraw();