added minimal machine structure£
This commit is contained in:
parent
6782c54354
commit
ba673b4547
4
Cargo.lock
generated
4
Cargo.lock
generated
@ -7,9 +7,9 @@ name = "cart_demo"
|
||||
version = "0.1.0"
|
||||
|
||||
[[package]]
|
||||
name = "core"
|
||||
name = "host_desktop"
|
||||
version = "0.1.0"
|
||||
|
||||
[[package]]
|
||||
name = "host_desktop"
|
||||
name = "prometeu-core"
|
||||
version = "0.1.0"
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "core"
|
||||
name = "prometeu-core"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
@ -1,14 +1,4 @@
|
||||
pub fn add(left: u64, right: u64) -> u64 {
|
||||
left + right
|
||||
}
|
||||
pub mod machine;
|
||||
pub mod peripherals;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn it_works() {
|
||||
let result = add(2, 2);
|
||||
assert_eq!(result, 4);
|
||||
}
|
||||
}
|
||||
pub use machine::Machine;
|
||||
|
||||
65
crates/core/src/machine.rs
Normal file
65
crates/core/src/machine.rs
Normal file
@ -0,0 +1,65 @@
|
||||
use crate::peripherals::{Gfx, Input, Touch};
|
||||
|
||||
/// PROMETEU "hardware lógico" (v0).
|
||||
/// O host alimenta INPUT/TOUCH e chama `tick()` em 60Hz.
|
||||
pub struct Machine {
|
||||
pub gfx: Gfx,
|
||||
pub input: Input,
|
||||
pub touch: Touch,
|
||||
pub frame_index: u64,
|
||||
}
|
||||
|
||||
impl Machine {
|
||||
pub const W: usize = 320;
|
||||
pub const H: usize = 180;
|
||||
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
gfx: Gfx::new(Self::W, Self::H),
|
||||
input: Input::default(),
|
||||
touch: Touch::default(),
|
||||
frame_index: 0,
|
||||
}
|
||||
}
|
||||
|
||||
/// Um frame lógico do PROMETEU.
|
||||
/// (Depois isso chamará um "cartucho"; por enquanto é demo hardcoded.)
|
||||
pub fn tick(&mut self) {
|
||||
self.frame_index += 1;
|
||||
|
||||
// Limpa
|
||||
self.gfx.clear(Color::rgb(0x10, 0x10, 0x10));
|
||||
|
||||
// Demo: quadrado que muda de cor se A ou touch estiver pressionado
|
||||
let (x, y) = self.demo_pos();
|
||||
let color = if self.input.a_down || self.touch.down {
|
||||
Color::rgb(0x00, 0xFF, 0x00)
|
||||
} else {
|
||||
Color::rgb(0xFF, 0x40, 0x40)
|
||||
};
|
||||
self.gfx.fill_rect(x, y, 24, 24, color);
|
||||
|
||||
// Present (double buffer)
|
||||
self.gfx.present();
|
||||
}
|
||||
|
||||
fn demo_pos(&self) -> (i32, i32) {
|
||||
// Só para mostrar movimento sem input por enquanto.
|
||||
let t = (self.frame_index % 280) as i32;
|
||||
(20 + t, 80)
|
||||
}
|
||||
}
|
||||
|
||||
/// Cor simples em RGBA8888 (0xRRGGBBAA).
|
||||
/// (Mais tarde, para hardware barato, você pode mudar o formato para RGB565.)
|
||||
#[derive(Clone, Copy, Debug, Default)]
|
||||
pub struct Color(pub u32);
|
||||
|
||||
impl Color {
|
||||
pub const fn rgba(r: u8, g: u8, b: u8, a: u8) -> Self {
|
||||
Self(((r as u32) << 24) | ((g as u32) << 16) | ((b as u32) << 8) | (a as u32))
|
||||
}
|
||||
pub const fn rgb(r: u8, g: u8, b: u8) -> Self {
|
||||
Self::rgba(r, g, b, 0xFF)
|
||||
}
|
||||
}
|
||||
55
crates/core/src/peripherals/gfx.rs
Normal file
55
crates/core/src/peripherals/gfx.rs
Normal file
@ -0,0 +1,55 @@
|
||||
use crate::machine::Color;
|
||||
|
||||
pub struct Gfx {
|
||||
w: usize,
|
||||
h: usize,
|
||||
front: Vec<u32>,
|
||||
back: Vec<u32>,
|
||||
}
|
||||
|
||||
impl Gfx {
|
||||
pub fn new(w: usize, h: usize) -> Self {
|
||||
let len = w * h;
|
||||
Self {
|
||||
w,
|
||||
h,
|
||||
front: vec![0; len],
|
||||
back: vec![0; len],
|
||||
}
|
||||
}
|
||||
|
||||
pub fn size(&self) -> (usize, usize) {
|
||||
(self.w, self.h)
|
||||
}
|
||||
|
||||
/// O buffer que o host deve exibir.
|
||||
pub fn front_buffer(&self) -> &[u32] {
|
||||
&self.front
|
||||
}
|
||||
|
||||
pub fn clear(&mut self, color: Color) {
|
||||
self.back.fill(color.0);
|
||||
}
|
||||
|
||||
pub fn fill_rect(&mut self, x: i32, y: i32, w: i32, h: i32, color: Color) {
|
||||
let fw = self.w as i32;
|
||||
let fh = self.h as i32;
|
||||
|
||||
let x0 = x.clamp(0, fw);
|
||||
let y0 = y.clamp(0, fh);
|
||||
let x1 = (x + w).clamp(0, fw);
|
||||
let y1 = (y + h).clamp(0, fh);
|
||||
|
||||
for yy in y0..y1 {
|
||||
let row = (yy as usize) * self.w;
|
||||
for xx in x0..x1 {
|
||||
self.back[row + (xx as usize)] = color.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Double buffer swap.
|
||||
pub fn present(&mut self) {
|
||||
std::mem::swap(&mut self.front, &mut self.back);
|
||||
}
|
||||
}
|
||||
13
crates/core/src/peripherals/input.rs
Normal file
13
crates/core/src/peripherals/input.rs
Normal file
@ -0,0 +1,13 @@
|
||||
#[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,
|
||||
}
|
||||
7
crates/core/src/peripherals/mod.rs
Normal file
7
crates/core/src/peripherals/mod.rs
Normal file
@ -0,0 +1,7 @@
|
||||
mod gfx;
|
||||
mod input;
|
||||
mod touch;
|
||||
|
||||
pub use gfx::Gfx;
|
||||
pub use input::Input;
|
||||
pub use touch::Touch;
|
||||
9
crates/core/src/peripherals/touch.rs
Normal file
9
crates/core/src/peripherals/touch.rs
Normal file
@ -0,0 +1,9 @@
|
||||
#[derive(Default, Clone, Copy, Debug)]
|
||||
pub struct Touch {
|
||||
pub present: bool,
|
||||
pub down: bool,
|
||||
pub pressed: bool,
|
||||
pub released: bool,
|
||||
pub x: i32,
|
||||
pub y: i32,
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user