translate to english!
This commit is contained in:
parent
38ec13b248
commit
0f3105d622
72
README.md
72
README.md
@ -1,84 +1,84 @@
|
|||||||
# PROMETEU
|
# PROMETEU
|
||||||
|
|
||||||
PROMETEU é um **ecossistema educacional e experimental** inspirado em consoles clássicos, com foco em **ensinar programação, arquitetura de sistemas e conceitos de hardware através de software**.
|
PROMETEU is an **educational and experimental ecosystem** inspired by classic consoles, focusing on **teaching programming, system architecture, and hardware concepts through software**.
|
||||||
|
|
||||||
> PROMETEU é uma máquina virtual simples, explícita e didática.
|
> PROMETEU is a simple, explicit, and educational virtual machine.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 🎯 Objetivos do Projeto
|
## 🎯 Project Goals
|
||||||
|
|
||||||
- **Simular um “hardware lógico” simples**: Criar uma barreira de entrada baixa para entender como computadores funcionam.
|
- **Simulate simple "logical hardware"**: Create a low entry barrier for understanding how computers work.
|
||||||
- **Loop Determinístico**: Garantir que o mesmo código produza o mesmo resultado em qualquer plataforma.
|
- **Deterministic Loop**: Ensure the same code produces the same result on any platform.
|
||||||
- **Portabilidade Total**: O núcleo não depende de sistema operacional, permitindo rodar de computadores modernos a hardware dedicado.
|
- **Total Portability**: The core does not depend on an operating system, allowing it to run from modern computers to dedicated hardware.
|
||||||
- **Ferramentas de Primeiro Nível**: Oferecer depuração e inspeção profunda como parte central da experiência.
|
- **First-Class Tools**: Offer deep debugging and inspection as a central part of the experience.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 🧠 Filosofia de Design
|
## 🧠 Design Philosophy
|
||||||
|
|
||||||
- **Sem magia**: tudo é explícito.
|
- **No magic**: everything is explicit.
|
||||||
- **Sem heurística implícita**: o sistema não “adivinha intenções”.
|
- **No implicit heuristics**: the system doesn't "guess intentions".
|
||||||
- **Determinístico**: mesmo input → mesmo resultado.
|
- **Deterministic**: same input → same result.
|
||||||
- **Hardware-first**: APIs modelam periféricos, não frameworks modernos.
|
- **Hardware-first**: APIs model peripherals, not modern frameworks.
|
||||||
- **Portável por definição**: se não funciona em todas as plataformas, não existe.
|
- **Portable by definition**: if it doesn't work on all platforms, it doesn't exist.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 📦 Estrutura do Monorepo
|
## 📦 Monorepo Structure
|
||||||
|
|
||||||
Este repositório é organizado como um workspace Rust e contém diversos componentes:
|
This repository is organized as a Rust workspace and contains several components:
|
||||||
|
|
||||||
- **[crates/](./crates)**: Implementação do software em Rust.
|
- **[crates/](./crates)**: Software implementation in Rust.
|
||||||
- **[prometeu](./crates/prometeu)**: Interface de linha de comando (CLI) unificada.
|
- **[prometeu](./crates/prometeu)**: Unified command-line interface (CLI).
|
||||||
- **[prometeu-core](./crates/prometeu-core)**: O núcleo lógico, VM e SO interno.
|
- **[prometeu-core](./crates/prometeu-core)**: The logical core, VM, and internal OS.
|
||||||
- **[prometeu-runtime-desktop](./crates/prometeu-runtime-desktop)**: Host para execução em sistemas Desktop.
|
- **[prometeu-runtime-desktop](./crates/prometeu-runtime-desktop)**: Host for execution on Desktop systems.
|
||||||
- **[docs/](./docs)**: Documentação técnica e especificações do sistema.
|
- **[docs/](./docs)**: Technical documentation and system specifications.
|
||||||
- **[devtools-protocol/](./devtools-protocol)**: Definição do protocolo de comunicação para ferramentas de desenvolvimento.
|
- **[devtools-protocol/](./devtools-protocol)**: Definition of the communication protocol for development tools.
|
||||||
- **[test-cartridges/](./test-cartridges)**: Exemplos e suítes de teste de cartuchos.
|
- **[test-cartridges/](./test-cartridges)**: Cartridge examples and test suites.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 🛠️ Requisitos
|
## 🛠️ Requirements
|
||||||
|
|
||||||
- **Rust**: Versão definida em `rust-toolchain.toml`.
|
- **Rust**: Version defined in `rust-toolchain.toml`.
|
||||||
- **Instalação**: Use o [rustup](https://rustup.rs/) para instalar a toolchain necessária.
|
- **Installation**: Use [rustup](https://rustup.rs/) to install the required toolchain.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## ▶️ Início Rápido
|
## ▶️ Quick Start
|
||||||
|
|
||||||
Para compilar o projeto completo:
|
To compile the full project:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cargo build
|
cargo build
|
||||||
```
|
```
|
||||||
|
|
||||||
Para rodar um cartucho de exemplo:
|
To run an example cartridge:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
./target/debug/prometeu run test-cartridges/color-square
|
./target/debug/prometeu run test-cartridges/color-square
|
||||||
```
|
```
|
||||||
|
|
||||||
Para mais detalhes sobre como usar a CLI, veja o README de **[prometeu](./crates/prometeu)**.
|
For more details on how to use the CLI, see the **[prometeu](./crates/prometeu)** README.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 🚧 Status do Projeto
|
## 🚧 Project Status
|
||||||
|
|
||||||
⚠️ **Em estágio inicial (bootstrap)**
|
⚠️ **Early stage (bootstrap)**
|
||||||
|
|
||||||
Atualmente o foco é na estabilização da arquitetura do core e do protocolo de depuração. Nada aqui deve ser considerado uma API estável ainda.
|
Currently, the focus is on stabilizing the core architecture and debugging protocol. Nothing here should be considered a stable API yet.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 📜 Licença
|
## 📜 License
|
||||||
|
|
||||||
Este projeto está licenciado sob a Licença MIT - veja o arquivo [LICENSE](LICENSE) para detalhes.
|
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## ✨ Nota Final
|
## ✨ Final Note
|
||||||
|
|
||||||
PROMETEU é tanto um projeto técnico quanto pedagógico. A ideia não é esconder complexidade, mas **expor a complexidade certa**, no nível certo, para que ela possa ser entendida, estudada e explorada.
|
PROMETEU is both a technical and pedagogical project. The idea is not to hide complexity, but to **expose the right complexity**, at the right level, so it can be understood, studied, and explored.
|
||||||
|
|
||||||
|
|||||||
@ -1,14 +1,14 @@
|
|||||||
# PROMETEU Core
|
# PROMETEU Core
|
||||||
|
|
||||||
Este crate contém a biblioteca central que define o comportamento do hardware e software do PROMETEU.
|
This crate contains the core library that defines the behavior of PROMETEU's hardware and software.
|
||||||
|
|
||||||
## Responsabilidades
|
## Responsibilities
|
||||||
|
|
||||||
- **Hardware Lógico**: Definição de GFX, Input, Audio e Touch.
|
- **Logical Hardware**: Definition of GFX, Input, Audio, and Touch.
|
||||||
- **Máquina Virtual**: Execução de bytecode customizado (PBC - Prometeu Byte Code).
|
- **Virtual Machine**: Execution of custom bytecode (PBC - Prometeu Byte Code).
|
||||||
- **Virtual FS**: Gerenciamento de arquivos e acesso ao "cartucho".
|
- **Virtual FS**: File management and "cartridge" access.
|
||||||
- **Firmware/OS**: O sistema operacional interno que gerencia o ciclo de vida das aplicações, splash screens e o Hub Home.
|
- **Firmware/OS**: The internal operating system that manages the application lifecycle, splash screens, and the Hub Home.
|
||||||
|
|
||||||
## Arquitetura
|
## Architecture
|
||||||
|
|
||||||
O core é projetado para ser determinístico e portátil. Ele não faz chamadas diretas ao sistema operacional do host; em vez disso, define traços (traits) que os hosts devem implementar (ex: `FsBackend`).
|
The core is designed to be deterministic and portable. It does not make direct calls to the host operating system; instead, it defines traits that hosts must implement (e.g., `FsBackend`).
|
||||||
|
|||||||
@ -31,7 +31,7 @@ impl Firmware {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn step_frame(&mut self, signals: &InputSignals, hw: &mut dyn HardwareBridge) {
|
pub fn step_frame(&mut self, signals: &InputSignals, hw: &mut dyn HardwareBridge) {
|
||||||
// Atualiza input uma vez por frame de host
|
// Updates input once per host frame
|
||||||
hw.pad_mut().begin_frame(signals);
|
hw.pad_mut().begin_frame(signals);
|
||||||
hw.touch_mut().begin_frame(signals);
|
hw.touch_mut().begin_frame(signals);
|
||||||
|
|
||||||
@ -50,7 +50,7 @@ impl Firmware {
|
|||||||
self.state = new_state;
|
self.state = new_state;
|
||||||
self.state_initialized = false;
|
self.state_initialized = false;
|
||||||
|
|
||||||
// Entra no novo estado imediatamente
|
// Enters the new state immediately
|
||||||
self.on_enter(signals, hw);
|
self.on_enter(signals, hw);
|
||||||
self.state_initialized = true;
|
self.state_initialized = true;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -14,16 +14,16 @@ impl AppCrashesStep {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn on_update(&mut self, ctx: &mut PrometeuContext) -> Option<FirmwareState> {
|
pub fn on_update(&mut self, ctx: &mut PrometeuContext) -> Option<FirmwareState> {
|
||||||
// Atualiza periféricos para input na tela de crash
|
// Update peripherals for input on the crash screen
|
||||||
ctx.hw.pad_mut().begin_frame(ctx.signals);
|
ctx.hw.pad_mut().begin_frame(ctx.signals);
|
||||||
|
|
||||||
// Tela de erro: fundo vermelho, texto branco
|
// Error screen: red background, white text
|
||||||
ctx.hw.gfx_mut().clear(Color::RED);
|
ctx.hw.gfx_mut().clear(Color::RED);
|
||||||
// Por enquanto apenas logamos ou mostramos algo simples
|
// For now we just log or show something simple
|
||||||
// No futuro, usar draw_text
|
// In the future, use draw_text
|
||||||
ctx.hw.gfx_mut().present();
|
ctx.hw.gfx_mut().present();
|
||||||
|
|
||||||
// Se apertar START, volta pro Hub
|
// If START is pressed, return to the Hub
|
||||||
if ctx.hw.pad().start.down {
|
if ctx.hw.pad().start.down {
|
||||||
return Some(FirmwareState::LaunchHub(LaunchHubStep));
|
return Some(FirmwareState::LaunchHub(LaunchHubStep));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -13,19 +13,19 @@ impl HubHomeStep {
|
|||||||
pub fn on_update(&mut self, ctx: &mut PrometeuContext) -> Option<FirmwareState> {
|
pub fn on_update(&mut self, ctx: &mut PrometeuContext) -> Option<FirmwareState> {
|
||||||
let mut error = None;
|
let mut error = None;
|
||||||
|
|
||||||
// Sempre atualiza a GUI do Hub (limpa a tela e processa input se não houver foco)
|
// Always updates the Hub GUI (clears screen and processes input if no focus)
|
||||||
ctx.hub.gui_update(ctx.os, ctx.hw);
|
ctx.hub.gui_update(ctx.os, ctx.hw);
|
||||||
|
|
||||||
if let Some(focused_id) = ctx.hub.window_manager.focused {
|
if let Some(focused_id) = ctx.hub.window_manager.focused {
|
||||||
if ctx.hw.pad().start.down {
|
if ctx.hw.pad().start.down {
|
||||||
ctx.hub.window_manager.remove_window(focused_id);
|
ctx.hub.window_manager.remove_window(focused_id);
|
||||||
} else {
|
} else {
|
||||||
// System App roda aqui, desenhando sobre o fundo do Hub
|
// System App runs here, drawing over the Hub background
|
||||||
error = ctx.os.step_frame(ctx.vm, ctx.signals, ctx.hw);
|
error = ctx.os.step_frame(ctx.vm, ctx.signals, ctx.hw);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Renderiza as bordas das janelas do System App
|
// Renders the System App window borders
|
||||||
ctx.hub.render(ctx.os, ctx.hw);
|
ctx.hub.render(ctx.os, ctx.hw);
|
||||||
|
|
||||||
ctx.hw.gfx_mut().present();
|
ctx.hw.gfx_mut().present();
|
||||||
|
|||||||
@ -17,8 +17,8 @@ impl LaunchHubStep {
|
|||||||
if let BootTarget::Cartridge { path, .. } = ctx.boot_target {
|
if let BootTarget::Cartridge { path, .. } = ctx.boot_target {
|
||||||
match CartridgeLoader::load(path) {
|
match CartridgeLoader::load(path) {
|
||||||
Ok(cartridge) => {
|
Ok(cartridge) => {
|
||||||
// No caso de debug, aqui poderíamos pausar, mas o requisito diz
|
// In the case of debug, we could pause here, but the requirement says
|
||||||
// para o Runtime abrir o socket e aguardar.
|
// for the Runtime to open the socket and wait.
|
||||||
return Some(FirmwareState::LoadCartridge(LoadCartridgeStep { cartridge }));
|
return Some(FirmwareState::LoadCartridge(LoadCartridgeStep { cartridge }));
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
|
|||||||
@ -23,8 +23,8 @@ impl LoadCartridgeStep {
|
|||||||
);
|
);
|
||||||
ctx.hub.window_manager.set_focus(id);
|
ctx.hub.window_manager.set_focus(id);
|
||||||
|
|
||||||
// Apps de sistema não mudam o estado do firmware para GameRunning.
|
// System apps do not change the firmware state to GameRunning.
|
||||||
// Eles rodam em background ou via janelas no Hub.
|
// They run in the background or via windows in the Hub.
|
||||||
return Some(FirmwareState::HubHome(HubHomeStep));
|
return Some(FirmwareState::HubHome(HubHomeStep));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -12,23 +12,23 @@ pub struct SplashScreenStep {
|
|||||||
impl SplashScreenStep {
|
impl SplashScreenStep {
|
||||||
pub fn on_enter(&mut self, ctx: &mut PrometeuContext) {
|
pub fn on_enter(&mut self, ctx: &mut PrometeuContext) {
|
||||||
ctx.os.log(LogLevel::Info, LogSource::Pos, 0, "Showing SplashScreen".to_string());
|
ctx.os.log(LogLevel::Info, LogSource::Pos, 0, "Showing SplashScreen".to_string());
|
||||||
// Tocar som no enter
|
// Play sound on enter
|
||||||
if let Some(sample) = ctx.os.sample_square.clone() {
|
if let Some(sample) = ctx.os.sample_square.clone() {
|
||||||
ctx.hw.audio_mut().play(sample, 0, 255, 127, 1.0, 0, LoopMode::Off);
|
ctx.hw.audio_mut().play(sample, 0, 255, 127, 1.0, 0, LoopMode::Off);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn on_update(&mut self, ctx: &mut PrometeuContext) -> Option<FirmwareState> {
|
pub fn on_update(&mut self, ctx: &mut PrometeuContext) -> Option<FirmwareState> {
|
||||||
const ANIMATION_DURATION: u32 = 60; // 1 segundo a 60fps
|
const ANIMATION_DURATION: u32 = 60; // 1 second at 60fps
|
||||||
const TOTAL_DURATION: u32 = 240; // 2 segundos totais (conforme ctxuisito anterior)
|
const TOTAL_DURATION: u32 = 240; // 4 seconds total (updated from 2s based on total_duration logic)
|
||||||
|
|
||||||
// Atualiza periféricos para input
|
// Update peripherals for input
|
||||||
ctx.hw.pad_mut().begin_frame(ctx.signals);
|
ctx.hw.pad_mut().begin_frame(ctx.signals);
|
||||||
|
|
||||||
// Limpar tela
|
// Clear screen
|
||||||
ctx.hw.gfx_mut().clear(Color::BLACK);
|
ctx.hw.gfx_mut().clear(Color::BLACK);
|
||||||
|
|
||||||
// Desenhar quadrado aumentando
|
// Draw expanding square
|
||||||
let (sw, sh) = ctx.hw.gfx().size();
|
let (sw, sh) = ctx.hw.gfx().size();
|
||||||
let max_size = (sw.min(sh) as i32 / 2).max(1);
|
let max_size = (sw.min(sh) as i32 / 2).max(1);
|
||||||
|
|
||||||
@ -44,8 +44,8 @@ impl SplashScreenStep {
|
|||||||
ctx.hw.gfx_mut().fill_rect(x, y, current_size, current_size, Color::WHITE);
|
ctx.hw.gfx_mut().fill_rect(x, y, current_size, current_size, Color::WHITE);
|
||||||
ctx.hw.gfx_mut().present();
|
ctx.hw.gfx_mut().present();
|
||||||
|
|
||||||
// Lógica de transição
|
// Transition logic
|
||||||
// Caso o botão start seja pressionado a qualquer momento depois da animação terminar
|
// If any button is pressed at any time after the animation ends
|
||||||
if self.frame >= ANIMATION_DURATION && ctx.hw.pad().any() {
|
if self.frame >= ANIMATION_DURATION && ctx.hw.pad().any() {
|
||||||
return Some(FirmwareState::LaunchHub(LaunchHubStep));
|
return Some(FirmwareState::LaunchHub(LaunchHubStep));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -120,7 +120,7 @@ impl Audio {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Limpa a fila de comandos. O Host deve consumir isso a cada frame.
|
/// Clears the command queue. The Host should consume this every frame.
|
||||||
pub fn clear_commands(&mut self) {
|
pub fn clear_commands(&mut self) {
|
||||||
self.commands.clear();
|
self.commands.clear();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -32,7 +32,7 @@ pub struct Gfx {
|
|||||||
pub hud_fade_level: u8, // 0..31
|
pub hud_fade_level: u8, // 0..31
|
||||||
pub hud_fade_color: Color,
|
pub hud_fade_color: Color,
|
||||||
|
|
||||||
// Cache de prioridades para evitar alocações por frame
|
// Priority cache to avoid per-frame allocations
|
||||||
priority_buckets: [Vec<usize>; 5],
|
priority_buckets: [Vec<usize>; 5],
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -51,17 +51,19 @@ impl Gfx {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let len = w * h;
|
let len = w * h;
|
||||||
|
let mut layers = [
|
||||||
|
ScrollableTileLayer::new(64, 64, TileSize::Size16),
|
||||||
|
ScrollableTileLayer::new(64, 64, TileSize::Size16),
|
||||||
|
ScrollableTileLayer::new(64, 64, TileSize::Size16),
|
||||||
|
ScrollableTileLayer::new(64, 64, TileSize::Size16),
|
||||||
|
];
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
w,
|
w,
|
||||||
h,
|
h,
|
||||||
front: vec![0; len],
|
front: vec![0; len],
|
||||||
back: vec![0; len],
|
back: vec![0; len],
|
||||||
layers: [
|
layers,
|
||||||
ScrollableTileLayer::new(64, 64, TileSize::Size16),
|
|
||||||
ScrollableTileLayer::new(64, 64, TileSize::Size16),
|
|
||||||
ScrollableTileLayer::new(64, 64, TileSize::Size16),
|
|
||||||
ScrollableTileLayer::new(64, 64, TileSize::Size16),
|
|
||||||
],
|
|
||||||
hud: HudTileLayer::new(64, 32),
|
hud: HudTileLayer::new(64, 32),
|
||||||
banks: [EMPTY_BANK; 16],
|
banks: [EMPTY_BANK; 16],
|
||||||
sprites: [EMPTY_SPRITE; 512],
|
sprites: [EMPTY_SPRITE; 512],
|
||||||
@ -83,7 +85,7 @@ impl Gfx {
|
|||||||
(self.w, self.h)
|
(self.w, self.h)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// O buffer que o host deve exibir (RGB565).
|
/// The buffer that the host should display (RGB565).
|
||||||
pub fn front_buffer(&self) -> &[u16] {
|
pub fn front_buffer(&self) -> &[u16] {
|
||||||
&self.front
|
&self.front
|
||||||
}
|
}
|
||||||
@ -92,7 +94,7 @@ impl Gfx {
|
|||||||
self.back.fill(color.0);
|
self.back.fill(color.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Retângulo com modo de blend.
|
/// Rectangle with blend mode.
|
||||||
pub fn fill_rect_blend(
|
pub fn fill_rect_blend(
|
||||||
&mut self,
|
&mut self,
|
||||||
x: i32,
|
x: i32,
|
||||||
@ -122,21 +124,21 @@ impl Gfx {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Conveniência: retângulo normal (sem blend).
|
/// Convenience: normal rectangle (no blend).
|
||||||
pub fn fill_rect(&mut self, x: i32, y: i32, w: i32, h: i32, color: Color) {
|
pub fn fill_rect(&mut self, x: i32, y: i32, w: i32, h: i32, color: Color) {
|
||||||
self.fill_rect_blend(x, y, w, h, color, BlendMode::None);
|
self.fill_rect_blend(x, y, w, h, color, BlendMode::None);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Double buffer swap (O(1), sem cópia de pixels).
|
/// Double buffer swap (O(1), no pixel copying).
|
||||||
pub fn present(&mut self) {
|
pub fn present(&mut self) {
|
||||||
std::mem::swap(&mut self.front, &mut self.back);
|
std::mem::swap(&mut self.front, &mut self.back);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Pipeline principal de renderização do frame.
|
/// Main frame rendering pipeline.
|
||||||
/// Segue a ordem de prioridade do manual (Capítulo 4.11).
|
/// Follows the priority order from the manual (Chapter 4.11).
|
||||||
pub fn render_all(&mut self) {
|
pub fn render_all(&mut self) {
|
||||||
// 0. Fase de Preparação: Organiza quem deve ser desenhado em cada camada
|
// 0. Preparation Phase: Organizes what should be drawn in each layer
|
||||||
// Limpa os buckets sem desalocar memória
|
// Clears the buckets without deallocating memory
|
||||||
for bucket in self.priority_buckets.iter_mut() {
|
for bucket in self.priority_buckets.iter_mut() {
|
||||||
bucket.clear();
|
bucket.clear();
|
||||||
}
|
}
|
||||||
@ -147,27 +149,27 @@ impl Gfx {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 1. Sprites de prioridade 0 (Atrás da Layer 0 - o fundo do fundo)
|
// 1. Priority 0 sprites (Behind Layer 0 - the very back)
|
||||||
Self::draw_bucket_on_buffer(&mut self.back, self.w, self.h, &self.priority_buckets[0], &self.sprites, &self.banks);
|
Self::draw_bucket_on_buffer(&mut self.back, self.w, self.h, &self.priority_buckets[0], &self.sprites, &self.banks);
|
||||||
|
|
||||||
for i in 0..self.layers.len() {
|
for i in 0..self.layers.len() {
|
||||||
// 2. Layers de jogo (0 a 3)
|
// 2. Game Layers (0 to 3)
|
||||||
let bank_id = self.layers[i].bank_id as usize;
|
let bank_id = self.layers[i].bank_id as usize;
|
||||||
if let Some(Some(bank)) = self.banks.get(bank_id) {
|
if let Some(Some(bank)) = self.banks.get(bank_id) {
|
||||||
Self::draw_tile_map(&mut self.back, self.w, self.h, &self.layers[i].map, bank, self.layers[i].scroll_x, self.layers[i].scroll_y);
|
Self::draw_tile_map(&mut self.back, self.w, self.h, &self.layers[i].map, bank, self.layers[i].scroll_x, self.layers[i].scroll_y);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. Sprites de acordo com prioridade
|
// 3. Sprites according to priority
|
||||||
Self::draw_bucket_on_buffer(&mut self.back, self.w, self.h, &self.priority_buckets[i + 1], &self.sprites, &self.banks);
|
Self::draw_bucket_on_buffer(&mut self.back, self.w, self.h, &self.priority_buckets[i + 1], &self.sprites, &self.banks);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4. Aplica Scene Fade (Afeta tudo desenhado até agora)
|
// 4. Applies Scene Fade (Affects everything drawn so far)
|
||||||
Self::apply_fade_to_buffer(&mut self.back, self.scene_fade_level, self.scene_fade_color);
|
Self::apply_fade_to_buffer(&mut self.back, self.scene_fade_level, self.scene_fade_color);
|
||||||
|
|
||||||
// 5. HUD (Sempre por cima)
|
// 5. HUD (Always on top)
|
||||||
self.render_hud();
|
self.render_hud();
|
||||||
|
|
||||||
// 6. Aplica HUD Fade (Opcional, apenas para o HUD)
|
// 6. Applies HUD Fade (Optional, HUD only)
|
||||||
Self::apply_fade_to_buffer(&mut self.back, self.hud_fade_level, self.hud_fade_color);
|
Self::apply_fade_to_buffer(&mut self.back, self.hud_fade_level, self.hud_fade_color);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -186,7 +188,7 @@ impl Gfx {
|
|||||||
Self::draw_tile_map(&mut self.back, self.w, self.h, &self.layers[layer_idx].map, bank, scroll_x, scroll_y);
|
Self::draw_tile_map(&mut self.back, self.w, self.h, &self.layers[layer_idx].map, bank, scroll_x, scroll_y);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Renderiza o HUD (sem scroll).
|
/// Renders the HUD (no scroll).
|
||||||
pub fn render_hud(&mut self) {
|
pub fn render_hud(&mut self) {
|
||||||
let bank_id = self.hud.bank_id as usize;
|
let bank_id = self.hud.bank_id as usize;
|
||||||
let bank = match self.banks.get(bank_id) {
|
let bank = match self.banks.get(bank_id) {
|
||||||
@ -208,30 +210,30 @@ impl Gfx {
|
|||||||
) {
|
) {
|
||||||
let tile_size = bank.tile_size as usize;
|
let tile_size = bank.tile_size as usize;
|
||||||
|
|
||||||
// 1. Calcular quantos tiles cabem na tela (com margem de 1 para o scroll)
|
// 1. Calculate how many tiles fit on the screen (with margin of 1 for scroll)
|
||||||
let visible_tiles_x = (screen_w / tile_size) + 1;
|
let visible_tiles_x = (screen_w / tile_size) + 1;
|
||||||
let visible_tiles_y = (screen_h / tile_size) + 1;
|
let visible_tiles_y = (screen_h / tile_size) + 1;
|
||||||
|
|
||||||
// 2. Calcular o offset inicial (onde o primeiro tile começa a ser desenhado)
|
// 2. Calculate the initial offset (where the first tile starts being drawn)
|
||||||
let start_tile_x = scroll_x / tile_size as i32;
|
let start_tile_x = scroll_x / tile_size as i32;
|
||||||
let start_tile_y = scroll_y / tile_size as i32;
|
let start_tile_y = scroll_y / tile_size as i32;
|
||||||
|
|
||||||
let fine_scroll_x = scroll_x % tile_size as i32;
|
let fine_scroll_x = scroll_x % tile_size as i32;
|
||||||
let fine_scroll_y = scroll_y % tile_size as i32;
|
let fine_scroll_y = scroll_y % tile_size as i32;
|
||||||
|
|
||||||
// 3. Loop por Tile (Muito mais eficiente)
|
// 3. Loop by Tile (Much more efficient)
|
||||||
for ty in 0..visible_tiles_y {
|
for ty in 0..visible_tiles_y {
|
||||||
for tx in 0..visible_tiles_x {
|
for tx in 0..visible_tiles_x {
|
||||||
let map_x = (start_tile_x + tx as i32) as usize;
|
let map_x = (start_tile_x + tx as i32) as usize;
|
||||||
let map_y = (start_tile_y + ty as i32) as usize;
|
let map_y = (start_tile_y + ty as i32) as usize;
|
||||||
|
|
||||||
// Skip se estiver fora dos limites do mapa
|
// Skip if outside map bounds
|
||||||
if map_x >= map.width || map_y >= map.height { continue; }
|
if map_x >= map.width || map_y >= map.height { continue; }
|
||||||
|
|
||||||
let tile = map.tiles[map_y * map.width + map_x];
|
let tile = map.tiles[map_y * map.width + map_x];
|
||||||
if tile.id == 0 { continue; }
|
if tile.id == 0 { continue; }
|
||||||
|
|
||||||
// 4. Desenha o bloco do tile na tela
|
// 4. Draws the tile block on the screen
|
||||||
let screen_tile_x = (tx as i32 * tile_size as i32) - fine_scroll_x;
|
let screen_tile_x = (tx as i32 * tile_size as i32) - fine_scroll_x;
|
||||||
let screen_tile_y = (ty as i32 * tile_size as i32) - fine_scroll_y;
|
let screen_tile_y = (ty as i32 * tile_size as i32) - fine_scroll_y;
|
||||||
|
|
||||||
@ -240,7 +242,7 @@ impl Gfx {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Função auxiliar para desenhar um bloco de 8x8, 16x16 ou 32x32 pixels
|
// Helper function to draw a block of 8x8, 16x16 or 32x32 pixels
|
||||||
fn draw_tile_pixels(back: &mut [u16], screen_w: usize, screen_h: usize, x: i32, y: i32, tile: crate::model::Tile, bank: &TileBank) {
|
fn draw_tile_pixels(back: &mut [u16], screen_w: usize, screen_h: usize, x: i32, y: i32, tile: crate::model::Tile, bank: &TileBank) {
|
||||||
let size = bank.tile_size as usize;
|
let size = bank.tile_size as usize;
|
||||||
|
|
||||||
@ -255,13 +257,13 @@ impl Gfx {
|
|||||||
let fetch_x = if tile.flip_x { size - 1 - local_x } else { local_x };
|
let fetch_x = if tile.flip_x { size - 1 - local_x } else { local_x };
|
||||||
let fetch_y = if tile.flip_y { size - 1 - local_y } else { local_y };
|
let fetch_y = if tile.flip_y { size - 1 - local_y } else { local_y };
|
||||||
|
|
||||||
// 1. Pega o índice do pixel no banco
|
// 1. Gets the pixel index in the bank
|
||||||
let px_index = bank.get_pixel_index(tile.id, fetch_x, fetch_y);
|
let px_index = bank.get_pixel_index(tile.id, fetch_x, fetch_y);
|
||||||
|
|
||||||
// 2. Regra: Índice 0 é transparente
|
// 2. Rule: Index 0 is transparent
|
||||||
if px_index == 0 { continue; }
|
if px_index == 0 { continue; }
|
||||||
|
|
||||||
// 3. Resolve a cor usando a paleta do tile
|
// 3. Resolves the color using the tile's palette
|
||||||
let color = bank.resolve_color(tile.palette_id, px_index);
|
let color = bank.resolve_color(tile.palette_id, px_index);
|
||||||
|
|
||||||
back[world_y as usize * screen_w + world_x as usize] = color.raw();
|
back[world_y as usize * screen_w + world_x as usize] = color.raw();
|
||||||
@ -293,7 +295,7 @@ impl Gfx {
|
|||||||
sprite: &Sprite,
|
sprite: &Sprite,
|
||||||
bank: &TileBank
|
bank: &TileBank
|
||||||
) {
|
) {
|
||||||
// ... (mesmo cálculo de bounds/clipping que já tínhamos) ...
|
// ... (same bounds/clipping calculation we already had) ...
|
||||||
let size = bank.tile_size as usize;
|
let size = bank.tile_size as usize;
|
||||||
let start_x = sprite.x.max(0);
|
let start_x = sprite.x.max(0);
|
||||||
let start_y = sprite.y.max(0);
|
let start_y = sprite.y.max(0);
|
||||||
@ -308,13 +310,13 @@ impl Gfx {
|
|||||||
let fetch_x = if sprite.flip_x { size - 1 - local_x } else { local_x };
|
let fetch_x = if sprite.flip_x { size - 1 - local_x } else { local_x };
|
||||||
let fetch_y = if sprite.flip_y { size - 1 - local_y } else { local_y };
|
let fetch_y = if sprite.flip_y { size - 1 - local_y } else { local_y };
|
||||||
|
|
||||||
// 1. Pega o índice
|
// 1. Get index
|
||||||
let px_index = bank.get_pixel_index(sprite.tile.id, fetch_x, fetch_y);
|
let px_index = bank.get_pixel_index(sprite.tile.id, fetch_x, fetch_y);
|
||||||
|
|
||||||
// 2. Transparência
|
// 2. Transparency
|
||||||
if px_index == 0 { continue; }
|
if px_index == 0 { continue; }
|
||||||
|
|
||||||
// 3. Resolve cor via paleta (do tile dentro do sprite)
|
// 3. Resolve color via palette (from the tile inside the sprite)
|
||||||
let color = bank.resolve_color(sprite.tile.palette_id, px_index);
|
let color = bank.resolve_color(sprite.tile.palette_id, px_index);
|
||||||
|
|
||||||
back[world_y as usize * screen_w + world_x as usize] = color.raw();
|
back[world_y as usize * screen_w + world_x as usize] = color.raw();
|
||||||
@ -322,10 +324,10 @@ impl Gfx {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Aplica o efeito de fade em todo o back buffer.
|
/// Applies the fade effect to the entire back buffer.
|
||||||
/// level: 0 (cor total) até 31 (visível)
|
/// level: 0 (full color) to 31 (visible)
|
||||||
fn apply_fade_to_buffer(back: &mut [u16], level: u8, fade_color: Color) {
|
fn apply_fade_to_buffer(back: &mut [u16], level: u8, fade_color: Color) {
|
||||||
if level >= 31 { return; } // Totalmente visível, pula processamento
|
if level >= 31 { return; } // Fully visible, skip processing
|
||||||
|
|
||||||
let weight = level as u16;
|
let weight = level as u16;
|
||||||
let inv_weight = 31 - weight;
|
let inv_weight = 31 - weight;
|
||||||
@ -334,7 +336,7 @@ impl Gfx {
|
|||||||
for px in back.iter_mut() {
|
for px in back.iter_mut() {
|
||||||
let (sr, sg, sb) = Color::unpack_to_native(*px);
|
let (sr, sg, sb) = Color::unpack_to_native(*px);
|
||||||
|
|
||||||
// Fórmula: (src * weight + fade * inv_weight) / 31
|
// Formula: (src * weight + fade * inv_weight) / 31
|
||||||
let r = ((sr as u16 * weight + fr as u16 * inv_weight) / 31) as u8;
|
let r = ((sr as u16 * weight + fr as u16 * inv_weight) / 31) as u8;
|
||||||
let g = ((sg as u16 * weight + fg as u16 * inv_weight) / 31) as u8;
|
let g = ((sg as u16 * weight + fg as u16 * inv_weight) / 31) as u8;
|
||||||
let b = ((sb as u16 * weight + fb as u16 * inv_weight) / 31) as u8;
|
let b = ((sb as u16 * weight + fb as u16 * inv_weight) / 31) as u8;
|
||||||
@ -343,19 +345,19 @@ impl Gfx {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Retorna o uso real de memória das estruturas gráficas em bytes.
|
/// Returns the actual memory usage of the graphics structures in bytes.
|
||||||
/// Reflete os buffers de índices, paletas e OAM conforme Capítulo 10.8.
|
/// Reflects index buffers, palettes, and OAM as per Chapter 10.8.
|
||||||
pub fn memory_usage_bytes(&self) -> usize {
|
pub fn memory_usage_bytes(&self) -> usize {
|
||||||
let mut total = 0;
|
let mut total = 0;
|
||||||
|
|
||||||
// 1. Framebuffers (Front + Back)
|
// 1. Framebuffers (Front + Back)
|
||||||
// Cada um é Vec<u16>, ocupando 2 bytes por pixel.
|
// Each is Vec<u16>, occupying 2 bytes per pixel.
|
||||||
total += self.front.len() * 2;
|
total += self.front.len() * 2;
|
||||||
total += self.back.len() * 2;
|
total += self.back.len() * 2;
|
||||||
|
|
||||||
// 2. Tile Layers (4 Game Layers)
|
// 2. Tile Layers (4 Game Layers)
|
||||||
for layer in &self.layers {
|
for layer in &self.layers {
|
||||||
// Tamanho da struct + os dados do mapa (Vec<Tile>)
|
// Struct size + map data (Vec<Tile>)
|
||||||
total += size_of::<ScrollableTileLayer>();
|
total += size_of::<ScrollableTileLayer>();
|
||||||
total += layer.map.tiles.len() * size_of::<crate::model::Tile>();
|
total += layer.map.tiles.len() * size_of::<crate::model::Tile>();
|
||||||
}
|
}
|
||||||
@ -364,19 +366,19 @@ impl Gfx {
|
|||||||
total += size_of::<HudTileLayer>();
|
total += size_of::<HudTileLayer>();
|
||||||
total += self.hud.map.tiles.len() * size_of::<crate::model::Tile>();
|
total += self.hud.map.tiles.len() * size_of::<crate::model::Tile>();
|
||||||
|
|
||||||
// 4. Tile Banks (Assets e Paletas)
|
// 4. Tile Banks (Assets and Palettes)
|
||||||
for bank_opt in &self.banks {
|
for bank_opt in &self.banks {
|
||||||
if let Some(bank) = bank_opt {
|
if let Some(bank) = bank_opt {
|
||||||
total += size_of::<TileBank>();
|
total += size_of::<TileBank>();
|
||||||
total += bank.pixel_indices.len();
|
total += bank.pixel_indices.len();
|
||||||
|
|
||||||
// Tabela de Paletas: 256 paletas * 16 cores * tamanho da struct Color
|
// Palette Table: 256 palettes * 16 colors * Color struct size
|
||||||
total += 256 * 16 * size_of::<Color>();
|
total += 256 * 16 * size_of::<Color>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 5. Sprites (OAM)
|
// 5. Sprites (OAM)
|
||||||
// Array fixo de 512 Sprites.
|
// Fixed array of 512 Sprites.
|
||||||
total += self.sprites.len() * size_of::<Sprite>();
|
total += self.sprites.len() * size_of::<Sprite>();
|
||||||
|
|
||||||
total
|
total
|
||||||
@ -457,8 +459,8 @@ impl Gfx {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Faz blend em RGB565 por canal com saturação.
|
/// Blends in RGB565 per channel with saturation.
|
||||||
/// `dst` e `src` são pixels RGB565 (u16).
|
/// `dst` and `src` are RGB565 pixels (u16).
|
||||||
fn blend_rgb565(dst: u16, src: u16, mode: BlendMode) -> u16 {
|
fn blend_rgb565(dst: u16, src: u16, mode: BlendMode) -> u16 {
|
||||||
match mode {
|
match mode {
|
||||||
BlendMode::None => src,
|
BlendMode::None => src,
|
||||||
|
|||||||
@ -9,7 +9,7 @@ pub struct Touch {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Touch {
|
impl Touch {
|
||||||
/// Flags transitórias devem durar apenas 1 frame.
|
/// Transient flags should last only 1 frame.
|
||||||
pub fn begin_frame(&mut self, signals: &InputSignals) {
|
pub fn begin_frame(&mut self, signals: &InputSignals) {
|
||||||
self.f.begin_frame(signals.f_signal);
|
self.f.begin_frame(signals.f_signal);
|
||||||
self.x = signals.x_pos.clone();
|
self.x = signals.x_pos.clone();
|
||||||
|
|||||||
@ -85,7 +85,7 @@ mod tests {
|
|||||||
service.log(i as u64, 1, LogLevel::Info, LogSource::Pos, 0, format!("Log {}", i));
|
service.log(i as u64, 1, LogLevel::Info, LogSource::Pos, 0, format!("Log {}", i));
|
||||||
}
|
}
|
||||||
|
|
||||||
let after = service.get_after(2); // seqs são 0, 1, 2, 3, 4. Deve retornar 3 e 4.
|
let after = service.get_after(2); // seqs are 0, 1, 2, 3, 4. Should return 3 and 4.
|
||||||
assert_eq!(after.len(), 2);
|
assert_eq!(after.len(), 2);
|
||||||
assert_eq!(after[0].msg, "Log 3");
|
assert_eq!(after[0].msg, "Log 3");
|
||||||
assert_eq!(after[1].msg, "Log 4");
|
assert_eq!(after[1].msg, "Log 4");
|
||||||
|
|||||||
@ -33,7 +33,7 @@ impl DirectoryCartridgeLoader {
|
|||||||
let manifest_content = fs::read_to_string(manifest_path).map_err(|_| CartridgeError::IoError)?;
|
let manifest_content = fs::read_to_string(manifest_path).map_err(|_| CartridgeError::IoError)?;
|
||||||
let manifest: CartridgeManifest = serde_json::from_str(&manifest_content).map_err(|_| CartridgeError::InvalidManifest)?;
|
let manifest: CartridgeManifest = serde_json::from_str(&manifest_content).map_err(|_| CartridgeError::InvalidManifest)?;
|
||||||
|
|
||||||
// Validação adicional conforme requisitos
|
// Additional validation as per requirements
|
||||||
if manifest.magic != "PMTU" {
|
if manifest.magic != "PMTU" {
|
||||||
return Err(CartridgeError::InvalidManifest);
|
return Err(CartridgeError::InvalidManifest);
|
||||||
}
|
}
|
||||||
@ -73,7 +73,6 @@ pub struct PackedCartridgeLoader;
|
|||||||
|
|
||||||
impl PackedCartridgeLoader {
|
impl PackedCartridgeLoader {
|
||||||
pub fn load(_path: &Path) -> Result<Cartridge, CartridgeError> {
|
pub fn load(_path: &Path) -> Result<Cartridge, CartridgeError> {
|
||||||
// Stub inicialmente, como solicitado
|
|
||||||
Err(CartridgeError::InvalidFormat)
|
Err(CartridgeError::InvalidFormat)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,10 +1,10 @@
|
|||||||
/// Cor simples em RGB565 (0bRRRRRGGGGGGBBBBB).
|
/// Simple RGB565 color (0bRRRRRGGGGGGBBBBB).
|
||||||
/// - 5 bits Red
|
/// - 5 bits Red
|
||||||
/// - 6 bits Green
|
/// - 6 bits Green
|
||||||
/// - 5 bits Blue
|
/// - 5 bits Blue
|
||||||
///
|
///
|
||||||
/// Não há canal alpha.
|
/// There is no alpha channel.
|
||||||
/// Transparência é tratada via Color Key ou Blend Mode.
|
/// Transparency is handled via Color Key or Blend Mode.
|
||||||
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
|
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
|
||||||
pub struct Color(pub u16);
|
pub struct Color(pub u16);
|
||||||
|
|
||||||
@ -23,7 +23,7 @@ impl Color {
|
|||||||
pub const COLOR_KEY: Self = Self::MAGENTA;
|
pub const COLOR_KEY: Self = Self::MAGENTA;
|
||||||
pub const TRANSPARENT: Self = Self::MAGENTA;
|
pub const TRANSPARENT: Self = Self::MAGENTA;
|
||||||
|
|
||||||
/// Extrai canais já na faixa nativa do RGB565:
|
/// Extracts channels in the native RGB565 range:
|
||||||
/// R: 0..31, G: 0..63, B: 0..31
|
/// R: 0..31, G: 0..63, B: 0..31
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub const fn unpack_to_native(px: u16) -> (u8, u8, u8) {
|
pub const fn unpack_to_native(px: u16) -> (u8, u8, u8) {
|
||||||
@ -33,14 +33,14 @@ impl Color {
|
|||||||
(r, g, b)
|
(r, g, b)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Incorpora canais já na faixa nativa do RGB565 em um pixel:
|
/// Packs channels from the native RGB565 range into a pixel:
|
||||||
/// R: 0..31, G: 0..63, B: 0..31
|
/// R: 0..31, G: 0..63, B: 0..31
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub const fn pack_from_native(r: u8, g: u8, b: u8) -> u16 {
|
pub const fn pack_from_native(r: u8, g: u8, b: u8) -> u16 {
|
||||||
((r as u16 & 0x1F) << 11) | ((g as u16 & 0x3F) << 5) | (b as u16 & 0x1F)
|
((r as u16 & 0x1F) << 11) | ((g as u16 & 0x3F) << 5) | (b as u16 & 0x1F)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Cria uma cor RGB565 a partir de componentes 8-bit (0..255).
|
/// Creates an RGB565 color from 8-bit components (0..255).
|
||||||
pub const fn rgb(r: u8, g: u8, b: u8) -> Self {
|
pub const fn rgb(r: u8, g: u8, b: u8) -> Self {
|
||||||
let r5 = (r as u16 >> 3) & 0x1F;
|
let r5 = (r as u16 >> 3) & 0x1F;
|
||||||
let g6 = (g as u16 >> 2) & 0x3F;
|
let g6 = (g as u16 >> 2) & 0x3F;
|
||||||
|
|||||||
@ -9,13 +9,12 @@ pub enum TileSize {
|
|||||||
|
|
||||||
pub struct TileBank {
|
pub struct TileBank {
|
||||||
pub tile_size: TileSize,
|
pub tile_size: TileSize,
|
||||||
pub width: usize, // em pixels
|
pub width: usize, // in pixels
|
||||||
pub height: usize, // em pixels
|
pub height: usize, // in pixels
|
||||||
// pub pixels: Vec<Color>,
|
|
||||||
|
|
||||||
/// Agora guardamos índices de 0 a 15 (4 bits por pixel simulados em 8 bits)
|
/// Now we store indices from 0 to 15 (4 bits per pixel simulated in 8 bits)
|
||||||
pub pixel_indices: Vec<u8>,
|
pub pixel_indices: Vec<u8>,
|
||||||
/// 256 paletas, cada uma com 16 cores (RGB565 como u16)
|
/// 256 palettes, each with 16 colors (RGB565 as u16)
|
||||||
pub palettes: [[Color; 16]; 256],
|
pub palettes: [[Color; 16]; 256],
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -25,14 +24,14 @@ impl TileBank {
|
|||||||
tile_size,
|
tile_size,
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
pixel_indices: vec![0; width * height], // Índice 0 = Transparente
|
pixel_indices: vec![0; width * height], // Index 0 = Transparent
|
||||||
palettes: [[Color::BLACK; 16]; 256],
|
palettes: [[Color::BLACK; 16]; 256],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Retorna a cor de um pixel específico dentro de um tile.
|
/// Returns the color of a specific pixel inside a tile.
|
||||||
/// tile_id: o índice do tile no banco
|
/// tile_id: the tile index in the bank
|
||||||
/// local_x, local_y: a posição do pixel dentro do tile (0 até tile_size-1)
|
/// local_x, local_y: the pixel position inside the tile (0 to tile_size-1)
|
||||||
pub fn get_pixel_index(&self, tile_id: u16, local_x: usize, local_y: usize) -> u8 {
|
pub fn get_pixel_index(&self, tile_id: u16, local_x: usize, local_y: usize) -> u8 {
|
||||||
let size = self.tile_size as usize;
|
let size = self.tile_size as usize;
|
||||||
let tiles_per_row = self.width / size;
|
let tiles_per_row = self.width / size;
|
||||||
@ -45,13 +44,13 @@ impl TileBank {
|
|||||||
if pixel_x < self.width && pixel_y < self.height {
|
if pixel_x < self.width && pixel_y < self.height {
|
||||||
self.pixel_indices[pixel_y * self.width + pixel_x]
|
self.pixel_indices[pixel_y * self.width + pixel_x]
|
||||||
} else {
|
} else {
|
||||||
0 // Fora do banco = Transparente
|
0 // Outside the bank = Transparent
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Resolve um índice de pixel para uma Color real usando uma paleta.
|
/// Resolves a pixel index to a real Color using a palette.
|
||||||
pub fn resolve_color(&self, palette_id: u8, pixel_index: u8) -> Color {
|
pub fn resolve_color(&self, palette_id: u8, pixel_index: u8) -> Color {
|
||||||
// Regra: Índice 0 é sempre transparente (usamos MAGENTA/COLOR_KEY como vácuo)
|
// Rule: Index 0 is always transparent (we use MAGENTA/COLOR_KEY as vacuum)
|
||||||
if pixel_index == 0 {
|
if pixel_index == 0 {
|
||||||
return Color::COLOR_KEY;
|
return Color::COLOR_KEY;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,7 +3,7 @@ use crate::log::{LogLevel, LogSource};
|
|||||||
use crate::model::{Color, Rect, Window, WindowId};
|
use crate::model::{Color, Rect, Window, WindowId};
|
||||||
use crate::prometeu_os::PrometeuOS;
|
use crate::prometeu_os::PrometeuOS;
|
||||||
|
|
||||||
/// Gerenciador de janelas do PROMETEU.
|
/// PROMETEU Window Manager.
|
||||||
pub struct WindowManager {
|
pub struct WindowManager {
|
||||||
pub windows: Vec<Window>,
|
pub windows: Vec<Window>,
|
||||||
pub focused: Option<WindowId>,
|
pub focused: Option<WindowId>,
|
||||||
@ -50,7 +50,7 @@ impl WindowManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// PrometeuHub: Launcher e ambiente de UI do sistema.
|
/// PrometeuHub: Launcher and system UI environment.
|
||||||
pub struct PrometeuHub {
|
pub struct PrometeuHub {
|
||||||
pub window_manager: WindowManager,
|
pub window_manager: WindowManager,
|
||||||
}
|
}
|
||||||
@ -63,7 +63,7 @@ impl PrometeuHub {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn init(&mut self) {
|
pub fn init(&mut self) {
|
||||||
// Inicializa o Window System e lista apps
|
// Initializes the Window System and lists apps
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn gui_update(&mut self, os: &mut PrometeuOS, hw: &mut dyn HardwareBridge) {
|
pub fn gui_update(&mut self, os: &mut PrometeuOS, hw: &mut dyn HardwareBridge) {
|
||||||
|
|||||||
@ -9,8 +9,8 @@ use std::collections::HashMap;
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
|
|
||||||
/// PrometeuOS (POS): O firmware/base do sistema.
|
/// PrometeuOS (POS): The system firmware/base.
|
||||||
/// Autoridade máxima do boot, periféricos, execução da PVM e tratamento de falhas.
|
/// Maximum authority for boot, peripherals, PVM execution, and fault handling.
|
||||||
pub struct PrometeuOS {
|
pub struct PrometeuOS {
|
||||||
pub tick_index: u64,
|
pub tick_index: u64,
|
||||||
pub logical_frame_index: u64,
|
pub logical_frame_index: u64,
|
||||||
@ -18,7 +18,7 @@ pub struct PrometeuOS {
|
|||||||
pub logical_frame_remaining_cycles: u64,
|
pub logical_frame_remaining_cycles: u64,
|
||||||
pub last_frame_cpu_time_us: u64,
|
pub last_frame_cpu_time_us: u64,
|
||||||
|
|
||||||
// Assets de exemplo (mantidos para compatibilidade com syscalls de áudio v0)
|
// Example assets (kept for compatibility with v0 audio syscalls)
|
||||||
pub sample_square: Option<Arc<Sample>>,
|
pub sample_square: Option<Arc<Sample>>,
|
||||||
pub sample_kick: Option<Arc<Sample>>,
|
pub sample_kick: Option<Arc<Sample>>,
|
||||||
pub sample_snare: Option<Arc<Sample>>,
|
pub sample_snare: Option<Arc<Sample>>,
|
||||||
@ -37,7 +37,7 @@ pub struct PrometeuOS {
|
|||||||
pub current_cartridge_app_mode: crate::model::AppMode,
|
pub current_cartridge_app_mode: crate::model::AppMode,
|
||||||
pub logs_written_this_frame: HashMap<u32, u32>,
|
pub logs_written_this_frame: HashMap<u32, u32>,
|
||||||
|
|
||||||
// Telemetria e Certificação
|
// Telemetry and Certification
|
||||||
pub telemetry_current: TelemetryFrame,
|
pub telemetry_current: TelemetryFrame,
|
||||||
pub telemetry_last: TelemetryFrame,
|
pub telemetry_last: TelemetryFrame,
|
||||||
pub certifier: Certifier,
|
pub certifier: Certifier,
|
||||||
@ -49,7 +49,7 @@ pub struct PrometeuOS {
|
|||||||
|
|
||||||
impl PrometeuOS {
|
impl PrometeuOS {
|
||||||
pub const CYCLES_PER_LOGICAL_FRAME: u64 = 100_000;
|
pub const CYCLES_PER_LOGICAL_FRAME: u64 = 100_000;
|
||||||
pub const SLICE_PER_TICK: u64 = 100_000; // Por enquanto, o mesmo, mas permite granularidade diferente
|
pub const SLICE_PER_TICK: u64 = 100_000; // For now the same, but allows different granularity
|
||||||
|
|
||||||
pub const MAX_LOG_LEN: usize = 256;
|
pub const MAX_LOG_LEN: usize = 256;
|
||||||
pub const MAX_LOGS_PER_FRAME: u32 = 10;
|
pub const MAX_LOGS_PER_FRAME: u32 = 10;
|
||||||
@ -83,7 +83,7 @@ impl PrometeuOS {
|
|||||||
boot_time,
|
boot_time,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Inicializa samples básicos (mesma lógica do LogicalHardware)
|
// Initializes basic samples (same logic as LogicalHardware)
|
||||||
os.sample_square = Some(Arc::new(Self::create_square_sample(440.0, 0.1)));
|
os.sample_square = Some(Arc::new(Self::create_square_sample(440.0, 0.1)));
|
||||||
|
|
||||||
os.log(LogLevel::Info, LogSource::Pos, 0, "PrometeuOS starting...".to_string());
|
os.log(LogLevel::Info, LogSource::Pos, 0, "PrometeuOS starting...".to_string());
|
||||||
@ -135,18 +135,18 @@ impl PrometeuOS {
|
|||||||
self.last_frame_cpu_time_us = 0;
|
self.last_frame_cpu_time_us = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Carrega um cartucho na PVM e reseta o estado de execução.
|
/// Loads a cartridge into the PVM and resets the execution state.
|
||||||
pub fn initialize_vm(&mut self, vm: &mut VirtualMachine, cartridge: &Cartridge) {
|
pub fn initialize_vm(&mut self, vm: &mut VirtualMachine, cartridge: &Cartridge) {
|
||||||
vm.initialize(cartridge.program.clone(), &cartridge.entrypoint);
|
vm.initialize(cartridge.program.clone(), &cartridge.entrypoint);
|
||||||
|
|
||||||
// Determina o app_id numérico
|
// Determines the numeric app_id
|
||||||
self.current_app_id = cartridge.app_id;
|
self.current_app_id = cartridge.app_id;
|
||||||
self.current_cartridge_title = cartridge.title.clone();
|
self.current_cartridge_title = cartridge.title.clone();
|
||||||
self.current_cartridge_app_version = cartridge.app_version.clone();
|
self.current_cartridge_app_version = cartridge.app_version.clone();
|
||||||
self.current_cartridge_app_mode = cartridge.app_mode;
|
self.current_cartridge_app_mode = cartridge.app_mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Executa uma única instrução da VM (Debug).
|
/// Executes a single VM instruction (Debug).
|
||||||
pub fn debug_step_instruction(&mut self, vm: &mut VirtualMachine, hw: &mut dyn HardwareBridge) -> Option<String> {
|
pub fn debug_step_instruction(&mut self, vm: &mut VirtualMachine, hw: &mut dyn HardwareBridge) -> Option<String> {
|
||||||
match vm.step(self, hw) {
|
match vm.step(self, hw) {
|
||||||
Ok(_) => None,
|
Ok(_) => None,
|
||||||
@ -158,7 +158,7 @@ impl PrometeuOS {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Executa um tick do host (60Hz).
|
/// Executes a host tick (60Hz).
|
||||||
pub fn step_frame(&mut self, vm: &mut VirtualMachine, signals: &InputSignals, hw: &mut dyn HardwareBridge) -> Option<String> {
|
pub fn step_frame(&mut self, vm: &mut VirtualMachine, signals: &InputSignals, hw: &mut dyn HardwareBridge) -> Option<String> {
|
||||||
let start = std::time::Instant::now();
|
let start = std::time::Instant::now();
|
||||||
self.tick_index += 1;
|
self.tick_index += 1;
|
||||||
@ -174,25 +174,25 @@ impl PrometeuOS {
|
|||||||
self.logical_frame_remaining_cycles = Self::CYCLES_PER_LOGICAL_FRAME;
|
self.logical_frame_remaining_cycles = Self::CYCLES_PER_LOGICAL_FRAME;
|
||||||
self.begin_logical_frame(signals, hw);
|
self.begin_logical_frame(signals, hw);
|
||||||
|
|
||||||
// Início do frame: resetar acumulador da telemetria (mas manter frame_index)
|
// Beginning of frame: reset telemetry accumulator (but keep frame_index)
|
||||||
self.telemetry_current = TelemetryFrame {
|
self.telemetry_current = TelemetryFrame {
|
||||||
frame_index: self.logical_frame_index,
|
frame_index: self.logical_frame_index,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Budget para este tick: o mínimo entre a fatia do tick e o que resta no frame lógico
|
// Budget for this tick: the minimum between the tick slice and what remains in the logical frame
|
||||||
let budget = std::cmp::min(Self::SLICE_PER_TICK, self.logical_frame_remaining_cycles);
|
let budget = std::cmp::min(Self::SLICE_PER_TICK, self.logical_frame_remaining_cycles);
|
||||||
|
|
||||||
if budget > 0 {
|
if budget > 0 {
|
||||||
// Executa budget
|
// Execute budget
|
||||||
let run_result = vm.run_budget(budget, self, hw);
|
let run_result = vm.run_budget(budget, self, hw);
|
||||||
|
|
||||||
match run_result {
|
match run_result {
|
||||||
Ok(run) => {
|
Ok(run) => {
|
||||||
self.logical_frame_remaining_cycles = self.logical_frame_remaining_cycles.saturating_sub(run.cycles_used);
|
self.logical_frame_remaining_cycles = self.logical_frame_remaining_cycles.saturating_sub(run.cycles_used);
|
||||||
|
|
||||||
// Acumula métricas
|
// Accumulates metrics
|
||||||
self.telemetry_current.cycles_used += run.cycles_used;
|
self.telemetry_current.cycles_used += run.cycles_used;
|
||||||
self.telemetry_current.vm_steps += run.steps_executed;
|
self.telemetry_current.vm_steps += run.steps_executed;
|
||||||
|
|
||||||
@ -205,14 +205,14 @@ impl PrometeuOS {
|
|||||||
if run.reason == crate::virtual_machine::LogicalFrameEndingReason::FrameSync {
|
if run.reason == crate::virtual_machine::LogicalFrameEndingReason::FrameSync {
|
||||||
hw.gfx_mut().render_all();
|
hw.gfx_mut().render_all();
|
||||||
|
|
||||||
// Finaliza telemetria do frame (host_cpu_time será refinado no final do tick)
|
// Finalizes frame telemetry (host_cpu_time will be refined at the end of the tick)
|
||||||
self.telemetry_current.host_cpu_time_us = start.elapsed().as_micros() as u64;
|
self.telemetry_current.host_cpu_time_us = start.elapsed().as_micros() as u64;
|
||||||
|
|
||||||
// Certificação (CAP)
|
// Certification (CAP)
|
||||||
let ts_ms = self.boot_time.elapsed().as_millis() as u64;
|
let ts_ms = self.boot_time.elapsed().as_millis() as u64;
|
||||||
self.telemetry_current.violations = self.certifier.evaluate(&self.telemetry_current, &mut self.log_service, ts_ms) as u32;
|
self.telemetry_current.violations = self.certifier.evaluate(&self.telemetry_current, &mut self.log_service, ts_ms) as u32;
|
||||||
|
|
||||||
// Latch: o que o overlay lê
|
// Latch: what the overlay reads
|
||||||
self.telemetry_last = self.telemetry_current;
|
self.telemetry_last = self.telemetry_current;
|
||||||
|
|
||||||
self.logical_frame_index += 1;
|
self.logical_frame_index += 1;
|
||||||
@ -235,7 +235,7 @@ impl PrometeuOS {
|
|||||||
|
|
||||||
self.last_frame_cpu_time_us = start.elapsed().as_micros() as u64;
|
self.last_frame_cpu_time_us = start.elapsed().as_micros() as u64;
|
||||||
|
|
||||||
// Se o frame acabou neste tick, atualizamos o tempo real final no latch
|
// If the frame ended in this tick, we update the final real time in the latch
|
||||||
if !self.logical_frame_active && self.telemetry_last.frame_index == self.logical_frame_index.wrapping_sub(1) {
|
if !self.logical_frame_active && self.telemetry_last.frame_index == self.logical_frame_index.wrapping_sub(1) {
|
||||||
self.telemetry_last.host_cpu_time_us = self.last_frame_cpu_time_us;
|
self.telemetry_last.host_cpu_time_us = self.last_frame_cpu_time_us;
|
||||||
}
|
}
|
||||||
@ -367,16 +367,16 @@ mod tests {
|
|||||||
};
|
};
|
||||||
os.initialize_vm(&mut vm, &cartridge);
|
os.initialize_vm(&mut vm, &cartridge);
|
||||||
|
|
||||||
// Primeiro tick
|
// First tick
|
||||||
os.step_frame(&mut vm, &signals, &mut hw);
|
os.step_frame(&mut vm, &signals, &mut hw);
|
||||||
let cycles_after_tick_1 = vm.cycles;
|
let cycles_after_tick_1 = vm.cycles;
|
||||||
assert!(cycles_after_tick_1 >= PrometeuOS::CYCLES_PER_LOGICAL_FRAME);
|
assert!(cycles_after_tick_1 >= PrometeuOS::CYCLES_PER_LOGICAL_FRAME);
|
||||||
|
|
||||||
// Segundo tick - Agora ele NÃO deve ganhar mais budget
|
// Second tick - Now it SHOULD NOT gain more budget
|
||||||
os.step_frame(&mut vm, &signals, &mut hw);
|
os.step_frame(&mut vm, &signals, &mut hw);
|
||||||
let cycles_after_tick_2 = vm.cycles;
|
let cycles_after_tick_2 = vm.cycles;
|
||||||
|
|
||||||
// CORREÇÃO: Ele não deve ter consumido ciclos no segundo tick porque o budget do frame lógico acabou
|
// FIX: It should not have consumed cycles in the second tick because the logical frame budget ended
|
||||||
println!("Cycles after tick 1: {}, tick 2: {}", cycles_after_tick_1, cycles_after_tick_2);
|
println!("Cycles after tick 1: {}, tick 2: {}", cycles_after_tick_1, cycles_after_tick_2);
|
||||||
assert_eq!(cycles_after_tick_2, cycles_after_tick_1, "VM should NOT have consumed more cycles in the second tick because logical frame budget is exhausted");
|
assert_eq!(cycles_after_tick_2, cycles_after_tick_1, "VM should NOT have consumed more cycles in the second tick because logical frame budget is exhausted");
|
||||||
}
|
}
|
||||||
@ -388,7 +388,7 @@ mod tests {
|
|||||||
let mut hw = Hardware::new();
|
let mut hw = Hardware::new();
|
||||||
let signals = InputSignals::default();
|
let signals = InputSignals::default();
|
||||||
|
|
||||||
// Loop que chama FrameSync:
|
// Loop that calls FrameSync:
|
||||||
// PUSH_CONST 0 (dummy)
|
// PUSH_CONST 0 (dummy)
|
||||||
// FrameSync (0x80)
|
// FrameSync (0x80)
|
||||||
// JMP 0
|
// JMP 0
|
||||||
@ -407,15 +407,15 @@ mod tests {
|
|||||||
};
|
};
|
||||||
os.initialize_vm(&mut vm, &cartridge);
|
os.initialize_vm(&mut vm, &cartridge);
|
||||||
|
|
||||||
// Primeiro tick
|
// First tick
|
||||||
os.step_frame(&mut vm, &signals, &mut hw);
|
os.step_frame(&mut vm, &signals, &mut hw);
|
||||||
let cycles_after_tick_1 = vm.cycles;
|
let cycles_after_tick_1 = vm.cycles;
|
||||||
|
|
||||||
// Deve ter parado no FrameSync
|
// Should have stopped at FrameSync
|
||||||
assert!(cycles_after_tick_1 > 0, "VM should have consumed some cycles");
|
assert!(cycles_after_tick_1 > 0, "VM should have consumed some cycles");
|
||||||
assert!(cycles_after_tick_1 < PrometeuOS::CYCLES_PER_LOGICAL_FRAME);
|
assert!(cycles_after_tick_1 < PrometeuOS::CYCLES_PER_LOGICAL_FRAME);
|
||||||
|
|
||||||
// Segundo tick - Deve resetar o budget e rodar mais um pouco até o próximo FrameSync
|
// Second tick - Should reset the budget and run a bit more until the next FrameSync
|
||||||
os.step_frame(&mut vm, &signals, &mut hw);
|
os.step_frame(&mut vm, &signals, &mut hw);
|
||||||
let cycles_after_tick_2 = vm.cycles;
|
let cycles_after_tick_2 = vm.cycles;
|
||||||
|
|
||||||
@ -430,7 +430,7 @@ mod tests {
|
|||||||
|
|
||||||
os.current_app_id = 123;
|
os.current_app_id = 123;
|
||||||
|
|
||||||
// 1. Teste de log normal
|
// 1. Normal log test
|
||||||
vm.push(Value::Integer(2)); // Info
|
vm.push(Value::Integer(2)); // Info
|
||||||
vm.push(Value::String("Hello Log".to_string()));
|
vm.push(Value::String("Hello Log".to_string()));
|
||||||
let res = os.syscall(0x5001, &mut vm, &mut hw);
|
let res = os.syscall(0x5001, &mut vm, &mut hw);
|
||||||
@ -441,7 +441,7 @@ mod tests {
|
|||||||
assert_eq!(recent[0].level, LogLevel::Info);
|
assert_eq!(recent[0].level, LogLevel::Info);
|
||||||
assert_eq!(recent[0].source, LogSource::App { app_id: 123 });
|
assert_eq!(recent[0].source, LogSource::App { app_id: 123 });
|
||||||
|
|
||||||
// 2. Teste de truncamento
|
// 2. Truncation test
|
||||||
let long_msg = "A".repeat(300);
|
let long_msg = "A".repeat(300);
|
||||||
vm.push(Value::Integer(3)); // Warn
|
vm.push(Value::Integer(3)); // Warn
|
||||||
vm.push(Value::String(long_msg));
|
vm.push(Value::String(long_msg));
|
||||||
@ -451,27 +451,27 @@ mod tests {
|
|||||||
assert_eq!(recent[0].msg.len(), 256);
|
assert_eq!(recent[0].msg.len(), 256);
|
||||||
assert!(recent[0].msg.starts_with("AAAAA"));
|
assert!(recent[0].msg.starts_with("AAAAA"));
|
||||||
|
|
||||||
// 3. Teste de Rate Limit
|
// 3. Rate Limit Test
|
||||||
// Já fizemos 2 logs. O limite é 10.
|
// We already made 2 logs. The limit is 10.
|
||||||
for i in 0..8 {
|
for i in 0..8 {
|
||||||
vm.push(Value::Integer(2));
|
vm.push(Value::Integer(2));
|
||||||
vm.push(Value::String(format!("Log {}", i)));
|
vm.push(Value::String(format!("Log {}", i)));
|
||||||
os.syscall(0x5001, &mut vm, &mut hw).unwrap();
|
os.syscall(0x5001, &mut vm, &mut hw).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
// O 11º log deve ser ignorado (e deve gerar um aviso do sistema)
|
// The 11th log should be ignored (and generate a system warning)
|
||||||
vm.push(Value::Integer(2));
|
vm.push(Value::Integer(2));
|
||||||
vm.push(Value::String("Eleventh log".to_string()));
|
vm.push(Value::String("Eleventh log".to_string()));
|
||||||
os.syscall(0x5001, &mut vm, &mut hw).unwrap();
|
os.syscall(0x5001, &mut vm, &mut hw).unwrap();
|
||||||
|
|
||||||
let recent = os.log_service.get_recent(2);
|
let recent = os.log_service.get_recent(2);
|
||||||
// O último log deve ser o aviso de rate limit (veio depois do 10º log tentado)
|
// The last log should be the rate limit warning (came after the 10th log attempted)
|
||||||
assert_eq!(recent[1].msg, "App exceeded log limit per frame");
|
assert_eq!(recent[1].msg, "App exceeded log limit per frame");
|
||||||
assert_eq!(recent[1].level, LogLevel::Warn);
|
assert_eq!(recent[1].level, LogLevel::Warn);
|
||||||
// O log "Eleventh log" não deve estar lá
|
// The log "Eleventh log" should not be there
|
||||||
assert_ne!(recent[0].msg, "Eleventh log");
|
assert_ne!(recent[0].msg, "Eleventh log");
|
||||||
|
|
||||||
// 4. Teste de reset do rate limit no próximo frame
|
// 4. Rate limit reset test in the next frame
|
||||||
os.begin_logical_frame(&InputSignals::default(), &mut hw);
|
os.begin_logical_frame(&InputSignals::default(), &mut hw);
|
||||||
vm.push(Value::Integer(2));
|
vm.push(Value::Integer(2));
|
||||||
vm.push(Value::String("New frame log".to_string()));
|
vm.push(Value::String("New frame log".to_string()));
|
||||||
@ -480,7 +480,7 @@ mod tests {
|
|||||||
let recent = os.log_service.get_recent(1);
|
let recent = os.log_service.get_recent(1);
|
||||||
assert_eq!(recent[0].msg, "New frame log");
|
assert_eq!(recent[0].msg, "New frame log");
|
||||||
|
|
||||||
// 5. Teste de LOG_WRITE_TAG
|
// 5. LOG_WRITE_TAG test
|
||||||
vm.push(Value::Integer(2)); // Info
|
vm.push(Value::Integer(2)); // Info
|
||||||
vm.push(Value::Integer(42)); // Tag
|
vm.push(Value::Integer(42)); // Tag
|
||||||
vm.push(Value::String("Tagged Log".to_string()));
|
vm.push(Value::String("Tagged Log".to_string()));
|
||||||
@ -623,7 +623,7 @@ impl NativeInterface for PrometeuOS {
|
|||||||
};
|
};
|
||||||
match self.fs.list_dir(&path) {
|
match self.fs.list_dir(&path) {
|
||||||
Ok(entries) => {
|
Ok(entries) => {
|
||||||
// Por enquanto, retorna uma string separada por ';'
|
// For now, returns a string separated by ';'
|
||||||
let names: Vec<String> = entries.into_iter().map(|e| e.name).collect();
|
let names: Vec<String> = entries.into_iter().map(|e| e.name).collect();
|
||||||
vm.push(Value::String(names.join(";")));
|
vm.push(Value::String(names.join(";")));
|
||||||
Ok(500)
|
Ok(500)
|
||||||
|
|||||||
@ -2,25 +2,25 @@
|
|||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
#[repr(u16)]
|
#[repr(u16)]
|
||||||
pub enum OpCode {
|
pub enum OpCode {
|
||||||
// 6.1 Controle de Execução
|
// 6.1 Execution Control
|
||||||
Nop = 0x00,
|
Nop = 0x00,
|
||||||
Halt = 0x01,
|
Halt = 0x01,
|
||||||
Jmp = 0x02,
|
Jmp = 0x02,
|
||||||
JmpIfFalse = 0x03,
|
JmpIfFalse = 0x03,
|
||||||
|
|
||||||
// 6.2 Pilha
|
// 6.2 Stack
|
||||||
PushConst = 0x10,
|
PushConst = 0x10,
|
||||||
Pop = 0x11,
|
Pop = 0x11,
|
||||||
Dup = 0x12,
|
Dup = 0x12,
|
||||||
Swap = 0x13,
|
Swap = 0x13,
|
||||||
|
|
||||||
// 6.3 Aritmética
|
// 6.3 Arithmetic
|
||||||
Add = 0x20,
|
Add = 0x20,
|
||||||
Sub = 0x21,
|
Sub = 0x21,
|
||||||
Mul = 0x22,
|
Mul = 0x22,
|
||||||
Div = 0x23,
|
Div = 0x23,
|
||||||
|
|
||||||
// 6.4 Comparação e Lógica
|
// 6.4 Comparison and Logic
|
||||||
Eq = 0x30,
|
Eq = 0x30,
|
||||||
Neq = 0x31,
|
Neq = 0x31,
|
||||||
Lt = 0x32,
|
Lt = 0x32,
|
||||||
@ -29,13 +29,13 @@ pub enum OpCode {
|
|||||||
Or = 0x35,
|
Or = 0x35,
|
||||||
Not = 0x36,
|
Not = 0x36,
|
||||||
|
|
||||||
// 6.5 Variáveis
|
// 6.5 Variables
|
||||||
GetGlobal = 0x40,
|
GetGlobal = 0x40,
|
||||||
SetGlobal = 0x41,
|
SetGlobal = 0x41,
|
||||||
GetLocal = 0x42,
|
GetLocal = 0x42,
|
||||||
SetLocal = 0x43,
|
SetLocal = 0x43,
|
||||||
|
|
||||||
// 6.6 Funções
|
// 6.6 Functions
|
||||||
Call = 0x50,
|
Call = 0x50,
|
||||||
Ret = 0x51,
|
Ret = 0x51,
|
||||||
PushScope = 0x52,
|
PushScope = 0x52,
|
||||||
@ -46,7 +46,7 @@ pub enum OpCode {
|
|||||||
LoadRef = 0x61,
|
LoadRef = 0x61,
|
||||||
StoreRef = 0x62,
|
StoreRef = 0x62,
|
||||||
|
|
||||||
// 6.8 Periféricos e Sistema
|
// 6.8 Peripherals and System
|
||||||
Syscall = 0x70,
|
Syscall = 0x70,
|
||||||
FrameSync = 0x80,
|
FrameSync = 0x80,
|
||||||
}
|
}
|
||||||
@ -126,7 +126,7 @@ impl OpCode {
|
|||||||
OpCode::Alloc => 10,
|
OpCode::Alloc => 10,
|
||||||
OpCode::LoadRef => 3,
|
OpCode::LoadRef => 3,
|
||||||
OpCode::StoreRef => 3,
|
OpCode::StoreRef => 3,
|
||||||
OpCode::Syscall => 1, // Variável, mas vamos usar 1 como base ou definir via ID
|
OpCode::Syscall => 1, // Variable, but we'll use 1 as base or define via ID
|
||||||
OpCode::FrameSync => 1,
|
OpCode::FrameSync => 1,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,7 +7,7 @@ pub enum Value {
|
|||||||
Float(f64),
|
Float(f64),
|
||||||
Boolean(bool),
|
Boolean(bool),
|
||||||
String(String),
|
String(String),
|
||||||
Ref(usize), // Referência ao heap
|
Ref(usize), // Heap reference
|
||||||
Null,
|
Null,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -27,7 +27,7 @@ pub struct VirtualMachine {
|
|||||||
pub call_stack: Vec<CallFrame>,
|
pub call_stack: Vec<CallFrame>,
|
||||||
pub globals: Vec<Value>,
|
pub globals: Vec<Value>,
|
||||||
pub program: Program,
|
pub program: Program,
|
||||||
pub heap: Vec<Value>, // Simplificado para demo, futuramente RAM/Heap real
|
pub heap: Vec<Value>, // Simplified for demo, future real RAM/Heap
|
||||||
pub cycles: u64,
|
pub cycles: u64,
|
||||||
pub halted: bool,
|
pub halted: bool,
|
||||||
pub breakpoints: std::collections::HashSet<usize>,
|
pub breakpoints: std::collections::HashSet<usize>,
|
||||||
@ -56,12 +56,12 @@ impl VirtualMachine {
|
|||||||
self.program = Program::new(program_bytes, vec![]);
|
self.program = Program::new(program_bytes, vec![]);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Por enquanto, tratamos os bytes como a ROM diretamente.
|
// For now, we treat the bytes as the ROM directly.
|
||||||
self.program = Program::new(program_bytes, vec![]);
|
self.program = Program::new(program_bytes, vec![]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Se o entrypoint for numérico, podemos tentar usá-lo como PC inicial.
|
// If the entrypoint is numeric, we can try to use it as the initial PC.
|
||||||
// Se não, por enquanto ignoramos ou começamos do 0.
|
// If not, for now we ignore it or start from 0.
|
||||||
if let Ok(addr) = entrypoint.parse::<usize>() {
|
if let Ok(addr) = entrypoint.parse::<usize>() {
|
||||||
self.pc = addr;
|
self.pc = addr;
|
||||||
} else {
|
} else {
|
||||||
@ -173,7 +173,7 @@ impl VirtualMachine {
|
|||||||
let pc_before = self.pc;
|
let pc_before = self.pc;
|
||||||
let cycles_before = self.cycles;
|
let cycles_before = self.cycles;
|
||||||
|
|
||||||
// Fast-path: FRAME_SYNC encerra o frame lógico
|
// Fast-path: FRAME_SYNC ends the logical frame
|
||||||
let opcode_val = self.peek_u16()?;
|
let opcode_val = self.peek_u16()?;
|
||||||
let opcode = OpCode::try_from(opcode_val)?;
|
let opcode = OpCode::try_from(opcode_val)?;
|
||||||
if opcode == OpCode::FrameSync {
|
if opcode == OpCode::FrameSync {
|
||||||
@ -187,7 +187,7 @@ impl VirtualMachine {
|
|||||||
self.step(native, hw)?;
|
self.step(native, hw)?;
|
||||||
steps_executed += 1;
|
steps_executed += 1;
|
||||||
|
|
||||||
// garante progresso real
|
// ensures real progress
|
||||||
if self.pc == pc_before && self.cycles == cycles_before && !self.halted {
|
if self.pc == pc_before && self.cycles == cycles_before && !self.halted {
|
||||||
return Err(format!("VM stuck at PC 0x{:08X}", self.pc));
|
return Err(format!("VM stuck at PC 0x{:08X}", self.pc));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,17 +1,17 @@
|
|||||||
# PROMETEU Desktop Runtime
|
# PROMETEU Desktop Runtime
|
||||||
|
|
||||||
Esta é a implementação de host para plataformas desktop, permitindo que o PROMETEU rode em Windows, Linux e macOS.
|
This is the host implementation for desktop platforms, allowing PROMETEU to run on Windows, Linux, and macOS.
|
||||||
|
|
||||||
## Funcionalidades
|
## Features
|
||||||
|
|
||||||
- **Renderização**: Utiliza a GPU via biblioteca `pixels` para apresentar o framebuffer de baixa resolução.
|
- **Rendering**: Uses the GPU via the `pixels` library to present the low-resolution framebuffer.
|
||||||
- **Input**: Traduz eventos de teclado e controle (via `winit`) para os sinais de hardware do PROMETEU.
|
- **Input**: Translates keyboard and controller events (via `winit`) into PROMETEU hardware signals.
|
||||||
- **Áudio**: Interface com o sistema de som do host (via `cpal`).
|
- **Audio**: Interfaces with the host's sound system (via `cpal`).
|
||||||
- **Debugging**: Hospeda um servidor TCP que implementa o **DevTools Protocol**, permitindo conexões de IDEs ou debuggers externos.
|
- **Debugging**: Hosts a TCP server that implements the **DevTools Protocol**, allowing connections from external IDEs or debuggers.
|
||||||
|
|
||||||
## Como rodar
|
## How to run
|
||||||
|
|
||||||
Geralmente executado via CLI principal (`prometeu`), mas pode ser chamado diretamente para testes:
|
Generally executed via the main CLI (`prometeu`), but can be called directly for testing:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cargo run -- --run path/to/cart
|
cargo run -- --run path/to/cart
|
||||||
|
|||||||
@ -39,7 +39,7 @@ impl HostAudio {
|
|||||||
|
|
||||||
let mut mixer = AudioMixer::new();
|
let mut mixer = AudioMixer::new();
|
||||||
|
|
||||||
// Para passar dados de performance da thread de áudio para a principal
|
// To pass performance data from the audio thread to the main thread
|
||||||
let audio_perf_rb = HeapRb::<u64>::new(64);
|
let audio_perf_rb = HeapRb::<u64>::new(64);
|
||||||
let (mut perf_prod, perf_cons) = audio_perf_rb.split();
|
let (mut perf_prod, perf_cons) = audio_perf_rb.split();
|
||||||
|
|
||||||
@ -47,13 +47,13 @@ impl HostAudio {
|
|||||||
.build_output_stream(
|
.build_output_stream(
|
||||||
&config,
|
&config,
|
||||||
move |data: &mut [f32], _: &cpal::OutputCallbackInfo| {
|
move |data: &mut [f32], _: &cpal::OutputCallbackInfo| {
|
||||||
// Consome comandos da ringbuffer
|
// Consumes commands from ringbuffer
|
||||||
while let Some(cmd) = cons.try_pop() {
|
while let Some(cmd) = cons.try_pop() {
|
||||||
mixer.process_command(cmd);
|
mixer.process_command(cmd);
|
||||||
}
|
}
|
||||||
// Mixa áudio
|
// Mixes audio
|
||||||
mixer.fill_buffer(data);
|
mixer.fill_buffer(data);
|
||||||
// Envia tempo de processamento em microssegundos
|
// Sends processing time in microseconds
|
||||||
let _ = perf_prod.try_push(mixer.last_processing_time.as_micros() as u64);
|
let _ = perf_prod.try_push(mixer.last_processing_time.as_micros() as u64);
|
||||||
},
|
},
|
||||||
|err| eprintln!("audio stream error: {}", err),
|
|err| eprintln!("audio stream error: {}", err),
|
||||||
@ -144,7 +144,7 @@ impl AudioMixer {
|
|||||||
|
|
||||||
pub fn fill_buffer(&mut self, buffer: &mut [f32]) {
|
pub fn fill_buffer(&mut self, buffer: &mut [f32]) {
|
||||||
let start = std::time::Instant::now();
|
let start = std::time::Instant::now();
|
||||||
// Zera o buffer (estéreo)
|
// Zeroes the buffer (stereo)
|
||||||
for sample in buffer.iter_mut() {
|
for sample in buffer.iter_mut() {
|
||||||
*sample = 0.0;
|
*sample = 0.0;
|
||||||
}
|
}
|
||||||
@ -172,7 +172,7 @@ impl AudioMixer {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Interpolação Linear
|
// Linear Interpolation
|
||||||
let s1 = sample_data.data[pos_int] as f32 / 32768.0;
|
let s1 = sample_data.data[pos_int] as f32 / 32768.0;
|
||||||
let s2 = if pos_int + 1 < sample_data.data.len() {
|
let s2 = if pos_int + 1 < sample_data.data.len() {
|
||||||
sample_data.data[pos_int + 1] as f32 / 32768.0
|
sample_data.data[pos_int + 1] as f32 / 32768.0
|
||||||
@ -204,7 +204,7 @@ impl AudioMixer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clamp final para evitar clipping (opcional se usarmos f32, mas bom para fidelidade)
|
// Final clamp to avoid clipping (optional if using f32, but good for fidelity)
|
||||||
for sample in buffer.iter_mut() {
|
for sample in buffer.iter_mut() {
|
||||||
*sample = sample.clamp(-1.0, 1.0);
|
*sample = sample.clamp(-1.0, 1.0);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -28,7 +28,7 @@ impl HostDebugger {
|
|||||||
if let BootTarget::Cartridge { path, debug: true, debug_port } = boot_target {
|
if let BootTarget::Cartridge { path, debug: true, debug_port } = boot_target {
|
||||||
self.waiting_for_start = true;
|
self.waiting_for_start = true;
|
||||||
|
|
||||||
// Pré-carrega informações do cartucho para o handshake
|
// Pre-loads cartridge information for the handshake
|
||||||
if let Ok(cartridge) = CartridgeLoader::load(path) {
|
if let Ok(cartridge) = CartridgeLoader::load(path) {
|
||||||
firmware.os.initialize_vm(&mut firmware.vm, &cartridge);
|
firmware.os.initialize_vm(&mut firmware.vm, &cartridge);
|
||||||
}
|
}
|
||||||
@ -75,7 +75,7 @@ impl HostDebugger {
|
|||||||
|
|
||||||
self.stream = Some(stream);
|
self.stream = Some(stream);
|
||||||
|
|
||||||
// Enviar Handshake
|
// Send Handshake
|
||||||
let handshake = DebugResponse::Handshake {
|
let handshake = DebugResponse::Handshake {
|
||||||
protocol_version: DEVTOOLS_PROTOCOL_VERSION,
|
protocol_version: DEVTOOLS_PROTOCOL_VERSION,
|
||||||
runtime_version: "0.1".to_string(),
|
runtime_version: "0.1".to_string(),
|
||||||
@ -104,10 +104,10 @@ impl HostDebugger {
|
|||||||
}
|
}
|
||||||
Ok(n) => {
|
Ok(n) => {
|
||||||
let data = &buf[..n];
|
let data = &buf[..n];
|
||||||
// Processar múltiplos comandos se houver \n
|
// Process multiple commands if there's \n
|
||||||
let msg = String::from_utf8_lossy(data);
|
let msg = String::from_utf8_lossy(data);
|
||||||
|
|
||||||
self.stream = Some(stream); // Coloca de volta antes de processar comandos
|
self.stream = Some(stream); // Put it back before processing commands
|
||||||
|
|
||||||
for line in msg.lines() {
|
for line in msg.lines() {
|
||||||
let trimmed = line.trim();
|
let trimmed = line.trim();
|
||||||
@ -154,7 +154,7 @@ impl HostDebugger {
|
|||||||
}
|
}
|
||||||
DebugCommand::Step => {
|
DebugCommand::Step => {
|
||||||
firmware.os.paused = true;
|
firmware.os.paused = true;
|
||||||
// Executa uma instrução imediatamente
|
// Executes an instruction immediately
|
||||||
let _ = firmware.os.debug_step_instruction(&mut firmware.vm, hardware);
|
let _ = firmware.os.debug_step_instruction(&mut firmware.vm, hardware);
|
||||||
}
|
}
|
||||||
DebugCommand::StepFrame => {
|
DebugCommand::StepFrame => {
|
||||||
@ -192,7 +192,7 @@ impl HostDebugger {
|
|||||||
for event in new_events {
|
for event in new_events {
|
||||||
self.last_log_seq = event.seq;
|
self.last_log_seq = event.seq;
|
||||||
|
|
||||||
// Verifica se é um breakpoint hit via tag
|
// Check if it's a breakpoint hit via tag
|
||||||
if event.tag == 0xDEB1 {
|
if event.tag == 0xDEB1 {
|
||||||
self.send_event(DebugEvent::BreakpointHit {
|
self.send_event(DebugEvent::BreakpointHit {
|
||||||
pc: firmware.vm.pc,
|
pc: firmware.vm.pc,
|
||||||
@ -200,7 +200,7 @@ impl HostDebugger {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Certificação via Tags 0xCA01-0xCA03
|
// Certification via Tags 0xCA01-0xCA03
|
||||||
if event.tag >= 0xCA01 && event.tag <= 0xCA03 {
|
if event.tag >= 0xCA01 && event.tag <= 0xCA03 {
|
||||||
let rule = match event.tag {
|
let rule = match event.tag {
|
||||||
0xCA01 => "cycles_budget",
|
0xCA01 => "cycles_budget",
|
||||||
@ -211,7 +211,7 @@ impl HostDebugger {
|
|||||||
|
|
||||||
self.send_event(DebugEvent::Cert {
|
self.send_event(DebugEvent::Cert {
|
||||||
rule,
|
rule,
|
||||||
used: 0, // Simplificado, informações detalhadas estão na msg do log
|
used: 0, // Simplified, detailed information is in the log message
|
||||||
limit: 0,
|
limit: 0,
|
||||||
frame_index: firmware.os.logical_frame_index,
|
frame_index: firmware.os.logical_frame_index,
|
||||||
});
|
});
|
||||||
|
|||||||
@ -21,7 +21,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
let mut debug_mode = false;
|
let mut debug_mode = false;
|
||||||
let mut debug_port = 7777;
|
let mut debug_port = 7777;
|
||||||
|
|
||||||
let mut i = 1; // Pula o nome do executável
|
let mut i = 1; // Skip the executable name
|
||||||
while i < args.len() {
|
while i < args.len() {
|
||||||
match args[i].as_str() {
|
match args[i].as_str() {
|
||||||
"--run" => {
|
"--run" => {
|
||||||
|
|||||||
@ -95,7 +95,7 @@ impl HostRunner {
|
|||||||
fn display_dbg_overlay(&mut self) {
|
fn display_dbg_overlay(&mut self) {
|
||||||
let tel = &self.firmware.os.telemetry_last;
|
let tel = &self.firmware.os.telemetry_last;
|
||||||
let color_text = prometeu_core::model::Color::WHITE;
|
let color_text = prometeu_core::model::Color::WHITE;
|
||||||
let color_bg = prometeu_core::model::Color::INDIGO; // Azul escuro para destacar
|
let color_bg = prometeu_core::model::Color::INDIGO; // Dark blue to stand out
|
||||||
let color_warn = prometeu_core::model::Color::RED;
|
let color_warn = prometeu_core::model::Color::RED;
|
||||||
|
|
||||||
self.hardware.gfx.fill_rect(5, 5, 140, 65, color_bg);
|
self.hardware.gfx.fill_rect(5, 5, 140, 65, color_bg);
|
||||||
@ -129,7 +129,7 @@ impl ApplicationHandler for HostRunner {
|
|||||||
|
|
||||||
let window = event_loop.create_window(attrs).expect("failed to create window");
|
let window = event_loop.create_window(attrs).expect("failed to create window");
|
||||||
|
|
||||||
// 🔥 Leak: Window vira &'static Window (bootstrap)
|
// 🔥 Leak: Window becomes &'static Window (bootstrap)
|
||||||
let window: &'static Window = Box::leak(Box::new(window));
|
let window: &'static Window = Box::leak(Box::new(window));
|
||||||
self.window = Some(window);
|
self.window = Some(window);
|
||||||
|
|
||||||
@ -165,18 +165,18 @@ impl ApplicationHandler for HostRunner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
WindowEvent::RedrawRequested => {
|
WindowEvent::RedrawRequested => {
|
||||||
// Pegue o Pixels diretamente do campo (não via helper que pega &mut self inteiro)
|
// Get Pixels directly from the field (not via helper that gets the entire &mut self)
|
||||||
let pixels = self.pixels.as_mut().expect("pixels not initialized");
|
let pixels = self.pixels.as_mut().expect("pixels not initialized");
|
||||||
|
|
||||||
{
|
{
|
||||||
// Borrow mutável do frame (dura só dentro deste bloco)
|
// Mutable borrow of the frame (lasts only within this block)
|
||||||
let frame = pixels.frame_mut();
|
let frame = pixels.frame_mut();
|
||||||
|
|
||||||
// Borrow imutável do prometeu-core (campo diferente, ok)
|
// Immutable borrow of prometeu-core (different field, ok)
|
||||||
let src = self.hardware.gfx.front_buffer();
|
let src = self.hardware.gfx.front_buffer();
|
||||||
|
|
||||||
draw_rgb565_to_rgba8(src, frame);
|
draw_rgb565_to_rgba8(src, frame);
|
||||||
} // <- frame borrow termina aqui
|
} // <- frame borrow ends here
|
||||||
|
|
||||||
if pixels.render().is_err() {
|
if pixels.render().is_err() {
|
||||||
event_loop.exit();
|
event_loop.exit();
|
||||||
@ -206,7 +206,7 @@ impl ApplicationHandler for HostRunner {
|
|||||||
fn about_to_wait(&mut self, _event_loop: &ActiveEventLoop) {
|
fn about_to_wait(&mut self, _event_loop: &ActiveEventLoop) {
|
||||||
self.debugger.check_commands(&mut self.firmware, &mut self.hardware);
|
self.debugger.check_commands(&mut self.firmware, &mut self.hardware);
|
||||||
|
|
||||||
// Atualiza estado do Filesystem no OS (específico do prometeu-runtime-desktop)
|
// Updates Filesystem state in OS (specific to prometeu-runtime-desktop)
|
||||||
if let Some(root) = &self.fs_root {
|
if let Some(root) = &self.fs_root {
|
||||||
use prometeu_core::fs::FsState;
|
use prometeu_core::fs::FsState;
|
||||||
if matches!(self.firmware.os.fs_state, FsState::Unmounted | FsState::Error(_)) {
|
if matches!(self.firmware.os.fs_state, FsState::Unmounted | FsState::Error(_)) {
|
||||||
@ -220,7 +220,7 @@ impl ApplicationHandler for HostRunner {
|
|||||||
let now = Instant::now();
|
let now = Instant::now();
|
||||||
let mut frame_delta = now.duration_since(self.last_frame_time);
|
let mut frame_delta = now.duration_since(self.last_frame_time);
|
||||||
|
|
||||||
// Limitador para evitar a "espiral da morte" se o SO travar (máximo de 100ms por volta)
|
// Limiter to avoid the "death spiral" if the OS freezes (max 100ms per loop)
|
||||||
if frame_delta > Duration::from_millis(100) {
|
if frame_delta > Duration::from_millis(100) {
|
||||||
frame_delta = Duration::from_millis(100);
|
frame_delta = Duration::from_millis(100);
|
||||||
}
|
}
|
||||||
@ -228,7 +228,7 @@ impl ApplicationHandler for HostRunner {
|
|||||||
self.last_frame_time = now;
|
self.last_frame_time = now;
|
||||||
self.accumulator += frame_delta;
|
self.accumulator += frame_delta;
|
||||||
|
|
||||||
// 🔥 O coração do determinismo: consome o tempo em fatias exatas de 60Hz
|
// 🔥 The heart of determinism: consumes time in exact 60Hz slices
|
||||||
while self.accumulator >= self.frame_target_dt {
|
while self.accumulator >= self.frame_target_dt {
|
||||||
if !self.debugger.waiting_for_start {
|
if !self.debugger.waiting_for_start {
|
||||||
self.firmware.step_frame(&self.input.signals, &mut self.hardware);
|
self.firmware.step_frame(&self.input.signals, &mut self.hardware);
|
||||||
@ -242,10 +242,10 @@ impl ApplicationHandler for HostRunner {
|
|||||||
|
|
||||||
self.audio.update_stats(&mut self.stats);
|
self.audio.update_stats(&mut self.stats);
|
||||||
|
|
||||||
// Atualiza estatísticas a cada 1 segundo real
|
// Updates statistics every 1 real second
|
||||||
self.stats.update(now, self.window, &self.hardware, &self.firmware);
|
self.stats.update(now, self.window, &self.hardware, &self.firmware);
|
||||||
|
|
||||||
// Processa logs do sistema
|
// Process system logs
|
||||||
let last_seq = self.log_sink.last_seq().unwrap_or(u64::MAX);
|
let last_seq = self.log_sink.last_seq().unwrap_or(u64::MAX);
|
||||||
let new_events = if last_seq == u64::MAX {
|
let new_events = if last_seq == u64::MAX {
|
||||||
self.firmware.os.log_service.get_recent(4096)
|
self.firmware.os.log_service.get_recent(4096)
|
||||||
@ -254,11 +254,11 @@ impl ApplicationHandler for HostRunner {
|
|||||||
};
|
};
|
||||||
self.log_sink.process_events(new_events);
|
self.log_sink.process_events(new_events);
|
||||||
|
|
||||||
// Overlay de Telemetria
|
// Telemetry Overlay
|
||||||
if self.overlay_enabled {
|
if self.overlay_enabled {
|
||||||
self.hardware.gfx.present(); // Traz o front para o back para desenhar por cima
|
self.hardware.gfx.present(); // Bring front to back to draw over
|
||||||
self.display_dbg_overlay();
|
self.display_dbg_overlay();
|
||||||
self.hardware.gfx.present(); // Devolve para o front com o overlay aplicado
|
self.hardware.gfx.present(); // Return to front with overlay applied
|
||||||
}
|
}
|
||||||
|
|
||||||
self.request_redraw();
|
self.request_redraw();
|
||||||
@ -286,37 +286,37 @@ mod tests {
|
|||||||
assert!(runner.debugger.waiting_for_start);
|
assert!(runner.debugger.waiting_for_start);
|
||||||
assert!(runner.debugger.listener.is_some());
|
assert!(runner.debugger.listener.is_some());
|
||||||
|
|
||||||
// Verifica se conseguimos conectar
|
// Check if we can connect
|
||||||
{
|
{
|
||||||
let mut stream = TcpStream::connect(format!("127.0.0.1:{}", port)).expect("Deve conectar");
|
let mut stream = TcpStream::connect(format!("127.0.0.1:{}", port)).expect("Should connect");
|
||||||
// Pequeno sleep para garantir que o SO processe
|
// Short sleep to ensure the OS processes
|
||||||
std::thread::sleep(std::time::Duration::from_millis(100));
|
std::thread::sleep(std::time::Duration::from_millis(100));
|
||||||
|
|
||||||
// Simula o loop para aceitar a conexão
|
// Simulates the loop to accept the connection
|
||||||
runner.debugger.check_commands(&mut runner.firmware, &mut runner.hardware);
|
runner.debugger.check_commands(&mut runner.firmware, &mut runner.hardware);
|
||||||
assert!(runner.debugger.stream.is_some(), "Stream deve ter sido mantido aberto");
|
assert!(runner.debugger.stream.is_some(), "Stream should have been kept open");
|
||||||
|
|
||||||
// Verifica Handshake
|
// Handshake Check
|
||||||
let mut buf = [0u8; 2048];
|
let mut buf = [0u8; 2048];
|
||||||
let n = stream.read(&mut buf).expect("Deve ler handshake");
|
let n = stream.read(&mut buf).expect("Should read handshake");
|
||||||
let resp: serde_json::Value = serde_json::from_slice(&buf[..n]).expect("Handshake deve ser JSON válido");
|
let resp: serde_json::Value = serde_json::from_slice(&buf[..n]).expect("Handshake should be valid JSON");
|
||||||
assert_eq!(resp["type"], "handshake");
|
assert_eq!(resp["type"], "handshake");
|
||||||
assert_eq!(resp["protocol_version"], DEVTOOLS_PROTOCOL_VERSION);
|
assert_eq!(resp["protocol_version"], DEVTOOLS_PROTOCOL_VERSION);
|
||||||
|
|
||||||
// Envia start via JSON
|
// Send start via JSON
|
||||||
stream.write_all(b"{\"type\":\"start\"}\n").expect("Conexão deve estar aberta para escrita");
|
stream.write_all(b"{\"type\":\"start\"}\n").expect("Connection should be open for writing");
|
||||||
std::thread::sleep(std::time::Duration::from_millis(50));
|
std::thread::sleep(std::time::Duration::from_millis(50));
|
||||||
|
|
||||||
// Processa o comando recebido
|
// Process the received command
|
||||||
runner.debugger.check_commands(&mut runner.firmware, &mut runner.hardware);
|
runner.debugger.check_commands(&mut runner.firmware, &mut runner.hardware);
|
||||||
assert!(!runner.debugger.waiting_for_start, "Execução deve ter iniciado após comando start");
|
assert!(!runner.debugger.waiting_for_start, "Execution should have started after start command");
|
||||||
assert!(runner.debugger.listener.is_some(), "Listener deve permanecer aberto para reconexões");
|
assert!(runner.debugger.listener.is_some(), "Listener should remain open for reconnections");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Agora que o stream saiu do escopo do teste, o runner deve detectar o fechamento no próximo check
|
// Now that the stream is out of the test scope, the runner should detect closure on next check
|
||||||
std::thread::sleep(std::time::Duration::from_millis(50));
|
std::thread::sleep(std::time::Duration::from_millis(50));
|
||||||
runner.debugger.check_commands(&mut runner.firmware, &mut runner.hardware);
|
runner.debugger.check_commands(&mut runner.firmware, &mut runner.hardware);
|
||||||
assert!(runner.debugger.stream.is_none(), "Stream deve ter sido fechado após o cliente desconectar");
|
assert!(runner.debugger.stream.is_none(), "Stream should have been closed after client disconnected");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -329,32 +329,32 @@ mod tests {
|
|||||||
debug_port: port,
|
debug_port: port,
|
||||||
});
|
});
|
||||||
|
|
||||||
// 1. Conecta e inicia
|
// 1. Connect and start
|
||||||
{
|
{
|
||||||
let mut stream = TcpStream::connect(format!("127.0.0.1:{}", port)).expect("Deve conectar 1");
|
let mut stream = TcpStream::connect(format!("127.0.0.1:{}", port)).expect("Should connect 1");
|
||||||
std::thread::sleep(std::time::Duration::from_millis(50));
|
std::thread::sleep(std::time::Duration::from_millis(50));
|
||||||
runner.debugger.check_commands(&mut runner.firmware, &mut runner.hardware);
|
runner.debugger.check_commands(&mut runner.firmware, &mut runner.hardware);
|
||||||
assert!(runner.debugger.stream.is_some());
|
assert!(runner.debugger.stream.is_some());
|
||||||
|
|
||||||
stream.write_all(b"{\"type\":\"start\"}\n").expect("Deve escrever start");
|
stream.write_all(b"{\"type\":\"start\"}\n").expect("Should write start");
|
||||||
std::thread::sleep(std::time::Duration::from_millis(50));
|
std::thread::sleep(std::time::Duration::from_millis(50));
|
||||||
runner.debugger.check_commands(&mut runner.firmware, &mut runner.hardware);
|
runner.debugger.check_commands(&mut runner.firmware, &mut runner.hardware);
|
||||||
assert!(!runner.debugger.waiting_for_start);
|
assert!(!runner.debugger.waiting_for_start);
|
||||||
// Atualmente o listener é fechado aqui.
|
// Currently the listener is closed here.
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. Desconecta (limpa o stream no runner)
|
// 2. Disconnect (clears stream in runner)
|
||||||
std::thread::sleep(std::time::Duration::from_millis(50));
|
std::thread::sleep(std::time::Duration::from_millis(50));
|
||||||
runner.debugger.check_commands(&mut runner.firmware, &mut runner.hardware);
|
runner.debugger.check_commands(&mut runner.firmware, &mut runner.hardware);
|
||||||
assert!(runner.debugger.stream.is_none());
|
assert!(runner.debugger.stream.is_none());
|
||||||
|
|
||||||
// 3. Tenta reconectar - DEVE FALHAR atualmente, mas queremos que FUNCIONE
|
// 3. Try to reconnect - SHOULD FAIL currently, but we want it to WORK
|
||||||
let stream2 = TcpStream::connect(format!("127.0.0.1:{}", port));
|
let stream2 = TcpStream::connect(format!("127.0.0.1:{}", port));
|
||||||
assert!(stream2.is_ok(), "Deve aceitar nova conexão mesmo após o start");
|
assert!(stream2.is_ok(), "Should accept new connection even after start");
|
||||||
|
|
||||||
std::thread::sleep(std::time::Duration::from_millis(50));
|
std::thread::sleep(std::time::Duration::from_millis(50));
|
||||||
runner.debugger.check_commands(&mut runner.firmware, &mut runner.hardware);
|
runner.debugger.check_commands(&mut runner.firmware, &mut runner.hardware);
|
||||||
assert!(runner.debugger.stream.is_some(), "Stream deve ter sido aceito na reconexão");
|
assert!(runner.debugger.stream.is_some(), "Stream should have been accepted on reconnection");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -367,24 +367,24 @@ mod tests {
|
|||||||
debug_port: port,
|
debug_port: port,
|
||||||
});
|
});
|
||||||
|
|
||||||
// 1. Primeira conexão
|
// 1. First connection
|
||||||
let mut _stream1 = TcpStream::connect(format!("127.0.0.1:{}", port)).expect("Deve conectar 1");
|
let mut _stream1 = TcpStream::connect(format!("127.0.0.1:{}", port)).expect("Should connect 1");
|
||||||
std::thread::sleep(std::time::Duration::from_millis(50));
|
std::thread::sleep(std::time::Duration::from_millis(50));
|
||||||
runner.debugger.check_commands(&mut runner.firmware, &mut runner.hardware);
|
runner.debugger.check_commands(&mut runner.firmware, &mut runner.hardware);
|
||||||
assert!(runner.debugger.stream.is_some());
|
assert!(runner.debugger.stream.is_some());
|
||||||
|
|
||||||
// 2. Segunda conexão
|
// 2. Second connection
|
||||||
let mut stream2 = TcpStream::connect(format!("127.0.0.1:{}", port)).expect("Deve conectar 2 (SO aceita)");
|
let mut stream2 = TcpStream::connect(format!("127.0.0.1:{}", port)).expect("Should connect 2 (OS accepts)");
|
||||||
std::thread::sleep(std::time::Duration::from_millis(50));
|
std::thread::sleep(std::time::Duration::from_millis(50));
|
||||||
runner.debugger.check_commands(&mut runner.firmware, &mut runner.hardware); // Deve aceitar e fechar stream2
|
runner.debugger.check_commands(&mut runner.firmware, &mut runner.hardware); // Should accept and close stream2
|
||||||
|
|
||||||
// Verifica se stream2 foi fechado pelo servidor
|
// Check if stream2 was closed by the server
|
||||||
let mut buf = [0u8; 10];
|
let mut buf = [0u8; 10];
|
||||||
stream2.set_read_timeout(Some(std::time::Duration::from_millis(100))).unwrap();
|
stream2.set_read_timeout(Some(std::time::Duration::from_millis(100))).unwrap();
|
||||||
let res = stream2.read(&mut buf);
|
let res = stream2.read(&mut buf);
|
||||||
assert!(matches!(res, Ok(0)) || res.is_err(), "Segunda conexão deve ser fechada pelo servidor");
|
assert!(matches!(res, Ok(0)) || res.is_err(), "Second connection should be closed by server");
|
||||||
|
|
||||||
assert!(runner.debugger.stream.is_some(), "Primeira conexão deve continuar ativa");
|
assert!(runner.debugger.stream.is_some(), "First connection should continue active");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -397,7 +397,7 @@ mod tests {
|
|||||||
debug_port: port,
|
debug_port: port,
|
||||||
});
|
});
|
||||||
|
|
||||||
let stream = TcpStream::connect(format!("127.0.0.1:{}", port)).expect("Deve conectar");
|
let stream = TcpStream::connect(format!("127.0.0.1:{}", port)).expect("Should connect");
|
||||||
std::thread::sleep(std::time::Duration::from_millis(100));
|
std::thread::sleep(std::time::Duration::from_millis(100));
|
||||||
runner.debugger.check_commands(&mut runner.firmware, &mut runner.hardware);
|
runner.debugger.check_commands(&mut runner.firmware, &mut runner.hardware);
|
||||||
|
|
||||||
@ -405,19 +405,19 @@ mod tests {
|
|||||||
let mut reader = std::io::BufReader::new(stream);
|
let mut reader = std::io::BufReader::new(stream);
|
||||||
|
|
||||||
let mut line = String::new();
|
let mut line = String::new();
|
||||||
reader.read_line(&mut line).expect("Deve ler handshake");
|
reader.read_line(&mut line).expect("Should read handshake");
|
||||||
assert!(line.contains("handshake"));
|
assert!(line.contains("handshake"));
|
||||||
|
|
||||||
// Envia getState
|
// Send getState
|
||||||
reader.get_mut().write_all(b"{\"type\":\"getState\"}\n").expect("Deve escrever getState");
|
reader.get_mut().write_all(b"{\"type\":\"getState\"}\n").expect("Should write getState");
|
||||||
std::thread::sleep(std::time::Duration::from_millis(100));
|
std::thread::sleep(std::time::Duration::from_millis(100));
|
||||||
|
|
||||||
runner.debugger.check_commands(&mut runner.firmware, &mut runner.hardware);
|
runner.debugger.check_commands(&mut runner.firmware, &mut runner.hardware);
|
||||||
|
|
||||||
// Verifica se recebeu resposta (pode haver eventos/logs antes)
|
// Check if response received (may have events/logs before)
|
||||||
loop {
|
loop {
|
||||||
line.clear();
|
line.clear();
|
||||||
reader.read_line(&mut line).expect("Deve ler linha");
|
reader.read_line(&mut line).expect("Should read line");
|
||||||
if line.is_empty() { break; }
|
if line.is_empty() { break; }
|
||||||
|
|
||||||
if let Ok(resp) = serde_json::from_str::<serde_json::Value>(&line) {
|
if let Ok(resp) = serde_json::from_str::<serde_json::Value>(&line) {
|
||||||
@ -426,7 +426,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
panic!("Não recebeu resposta getState");
|
panic!("Did not receive getState response");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -439,24 +439,24 @@ mod tests {
|
|||||||
debug_port: port,
|
debug_port: port,
|
||||||
});
|
});
|
||||||
|
|
||||||
// 1. Conecta e pausa
|
// 1. Connect and pause
|
||||||
{
|
{
|
||||||
let mut stream = TcpStream::connect(format!("127.0.0.1:{}", port)).expect("Deve conectar");
|
let mut stream = TcpStream::connect(format!("127.0.0.1:{}", port)).expect("Should connect");
|
||||||
std::thread::sleep(std::time::Duration::from_millis(50));
|
std::thread::sleep(std::time::Duration::from_millis(50));
|
||||||
runner.debugger.check_commands(&mut runner.firmware, &mut runner.hardware);
|
runner.debugger.check_commands(&mut runner.firmware, &mut runner.hardware);
|
||||||
|
|
||||||
stream.write_all(b"{\"type\":\"pause\"}\n").expect("Deve escrever pause");
|
stream.write_all(b"{\"type\":\"pause\"}\n").expect("Should write pause");
|
||||||
std::thread::sleep(std::time::Duration::from_millis(50));
|
std::thread::sleep(std::time::Duration::from_millis(50));
|
||||||
runner.debugger.check_commands(&mut runner.firmware, &mut runner.hardware);
|
runner.debugger.check_commands(&mut runner.firmware, &mut runner.hardware);
|
||||||
assert!(runner.firmware.os.paused, "VM deve estar pausada");
|
assert!(runner.firmware.os.paused, "VM should be paused");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. Desconecta (stream sai de escopo)
|
// 2. Disconnect (stream goes out of scope)
|
||||||
std::thread::sleep(std::time::Duration::from_millis(50));
|
std::thread::sleep(std::time::Duration::from_millis(50));
|
||||||
runner.debugger.check_commands(&mut runner.firmware, &mut runner.hardware);
|
runner.debugger.check_commands(&mut runner.firmware, &mut runner.hardware);
|
||||||
|
|
||||||
// 3. Verifica se despausou
|
// 3. Check if unpaused
|
||||||
assert!(!runner.firmware.os.paused, "VM deve ter despausado após desconexão");
|
assert!(!runner.firmware.os.paused, "VM should have unpaused after disconnect");
|
||||||
assert!(!runner.debugger.waiting_for_start, "VM deve ter saído do estado waiting_for_start");
|
assert!(!runner.debugger.waiting_for_start, "VM should have left waiting_for_start state");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -39,7 +39,7 @@ impl HostStats {
|
|||||||
if let Some(window) = window {
|
if let Some(window) = window {
|
||||||
let kb = hardware.gfx.memory_usage_bytes() as f64 / 1024.0;
|
let kb = hardware.gfx.memory_usage_bytes() as f64 / 1024.0;
|
||||||
|
|
||||||
// comparação fixa sempre contra 60Hz, manter mesmo quando fazer teste de stress na CPU
|
// Fixed comparison always against 60Hz, keep even when doing CPU stress tests
|
||||||
let frame_budget_us = 16666.0;
|
let frame_budget_us = 16666.0;
|
||||||
let cpu_load_core = (firmware.os.last_frame_cpu_time_us as f64 / frame_budget_us) * 100.0;
|
let cpu_load_core = (firmware.os.last_frame_cpu_time_us as f64 / frame_budget_us) * 100.0;
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
/// Copia RGB565 (u16) -> RGBA8888 (u8[4]) para o frame do pixels.
|
/// Copies RGB565 (u16) -> RGBA8888 (u8[4]) to the pixels frame.
|
||||||
/// Formato do pixels: RGBA8.
|
/// Pixels format: RGBA8.
|
||||||
pub fn draw_rgb565_to_rgba8(src: &[u16], dst_rgba: &mut [u8]) {
|
pub fn draw_rgb565_to_rgba8(src: &[u16], dst_rgba: &mut [u8]) {
|
||||||
for (i, &px) in src.iter().enumerate() {
|
for (i, &px) in src.iter().enumerate() {
|
||||||
let (r8, g8, b8) = rgb565_to_rgb888(px);
|
let (r8, g8, b8) = rgb565_to_rgb888(px);
|
||||||
@ -11,7 +11,7 @@ pub fn draw_rgb565_to_rgba8(src: &[u16], dst_rgba: &mut [u8]) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Expande RGB565 para RGB888 (replicação de bits altos).
|
/// Expands RGB565 to RGB888 (high bit replication).
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn rgb565_to_rgb888(px: u16) -> (u8, u8, u8) {
|
pub fn rgb565_to_rgb888(px: u16) -> (u8, u8, u8) {
|
||||||
let r5 = ((px >> 11) & 0x1F) as u8;
|
let r5 = ((px >> 11) & 0x1F) as u8;
|
||||||
|
|||||||
@ -1,14 +1,14 @@
|
|||||||
# PROMETEU CLI (Dispatcher)
|
# PROMETEU CLI (Dispatcher)
|
||||||
|
|
||||||
O binário `prometeu` atua como o front-end unificado para o ecossistema. Ele não implementa a lógica de execução ou compilação, mas sabe onde encontrar os binários que as implementam.
|
The `prometeu` binary acts as the unified front-end for the ecosystem. It does not implement the execution or compilation logic but knows where to find the binaries that do.
|
||||||
|
|
||||||
## Comandos
|
## Commands
|
||||||
|
|
||||||
- `prometeu run <cart>`: Executa um cartucho usando o runtime disponível.
|
- `prometeu run <cart>`: Runs a cartridge using the available runtime.
|
||||||
- `prometeu debug <cart> [--port <p>]`: Inicia a execução em modo de depuração.
|
- `prometeu debug <cart> [--port <p>]`: Starts execution in debug mode.
|
||||||
- `prometeu build <projectDir>`: (Planejado) Chama o compilador `prometeuc`.
|
- `prometeu build <projectDir>`: (Planned) Calls the `prometeuc` compiler.
|
||||||
- `prometeu pack <cartDir>`: (Planejado) Chama o empacotador `prometeup`.
|
- `prometeu pack <cartDir>`: (Planned) Calls the `prometeup` packager.
|
||||||
|
|
||||||
## Funcionamento
|
## How it works
|
||||||
|
|
||||||
O dispatcher localiza os binários irmãos (`prometeu-runtime`, `prometeuc`, etc.) no mesmo diretório onde ele próprio está instalado. Ele herda `stdin`, `stdout` e `stderr`, e propaga o código de saída do processo chamado.
|
The dispatcher locates sibling binaries (`prometeu-runtime`, `prometeuc`, etc.) in the same directory where it is installed. It inherits `stdin`, `stdout`, and `stderr`, and propagates the exit code of the called process.
|
||||||
|
|||||||
@ -5,7 +5,7 @@ use std::process::Command;
|
|||||||
|
|
||||||
#[derive(Parser)]
|
#[derive(Parser)]
|
||||||
#[command(name = "prometeu")]
|
#[command(name = "prometeu")]
|
||||||
#[command(about = "Dispatcher para o ecossistema Prometeu", long_about = None)]
|
#[command(about = "Dispatcher for the Prometeu ecosystem", long_about = None)]
|
||||||
struct Cli {
|
struct Cli {
|
||||||
#[command(subcommand)]
|
#[command(subcommand)]
|
||||||
command: Option<Commands>,
|
command: Option<Commands>,
|
||||||
@ -13,30 +13,30 @@ struct Cli {
|
|||||||
|
|
||||||
#[derive(Subcommand)]
|
#[derive(Subcommand)]
|
||||||
enum Commands {
|
enum Commands {
|
||||||
/// Executa um cartucho
|
/// Executes a cartridge
|
||||||
Run {
|
Run {
|
||||||
/// Caminho para o cartucho
|
/// Path to the cartridge
|
||||||
cart: String,
|
cart: String,
|
||||||
},
|
},
|
||||||
/// Debuga um cartucho
|
/// Debugs a cartridge
|
||||||
Debug {
|
Debug {
|
||||||
/// Caminho para o cartucho
|
/// Path to the cartridge
|
||||||
cart: String,
|
cart: String,
|
||||||
/// Porta para o debugger (padrão: 7777)
|
/// Port for the debugger (default: 7777)
|
||||||
#[arg(long, default_value_t = 7777)]
|
#[arg(long, default_value_t = 7777)]
|
||||||
port: u16,
|
port: u16,
|
||||||
},
|
},
|
||||||
/// Compila um projeto
|
/// Builds a project
|
||||||
Build {
|
Build {
|
||||||
/// Diretório do projeto
|
/// Project directory
|
||||||
project_dir: String,
|
project_dir: String,
|
||||||
},
|
},
|
||||||
/// Empacota um cartucho
|
/// Packages a cartridge
|
||||||
Pack {
|
Pack {
|
||||||
/// Diretório do cartucho
|
/// Cartridge directory
|
||||||
cart_dir: String,
|
cart_dir: String,
|
||||||
},
|
},
|
||||||
/// Verifica integridade de um projeto ou cartucho
|
/// Verifies the integrity of a project or cartridge
|
||||||
Verify {
|
Verify {
|
||||||
#[command(subcommand)]
|
#[command(subcommand)]
|
||||||
target: VerifyCommands,
|
target: VerifyCommands,
|
||||||
@ -45,14 +45,14 @@ enum Commands {
|
|||||||
|
|
||||||
#[derive(Subcommand)]
|
#[derive(Subcommand)]
|
||||||
enum VerifyCommands {
|
enum VerifyCommands {
|
||||||
/// Verifica um projeto
|
/// Verifies a project
|
||||||
C {
|
C {
|
||||||
/// Diretório do projeto
|
/// Project directory
|
||||||
project_dir: String,
|
project_dir: String,
|
||||||
},
|
},
|
||||||
/// Verifica um cartucho ou arquivo PMC
|
/// Verifies a cartridge or PMC file
|
||||||
P {
|
P {
|
||||||
/// Caminho para o cartucho ou PMC
|
/// Path to the cartridge or PMC
|
||||||
cart_or_pmc: String,
|
cart_or_pmc: String,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -63,7 +63,7 @@ fn main() {
|
|||||||
let exe_dir = match env::current_exe() {
|
let exe_dir = match env::current_exe() {
|
||||||
Ok(exe_path) => exe_path.parent().unwrap_or_else(|| Path::new(".")).to_path_buf(),
|
Ok(exe_path) => exe_path.parent().unwrap_or_else(|| Path::new(".")).to_path_buf(),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
eprintln!("Erro ao obter o caminho do executável: {}", e);
|
eprintln!("Error obtaining executable path: {}", e);
|
||||||
std::process::exit(1);
|
std::process::exit(1);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -109,8 +109,8 @@ fn dispatch(exe_dir: &Path, bin_name: &str, args: &[&str]) {
|
|||||||
let bin_path = get_binary_path(exe_dir, bin_name);
|
let bin_path = get_binary_path(exe_dir, bin_name);
|
||||||
|
|
||||||
if !bin_path.exists() {
|
if !bin_path.exists() {
|
||||||
// Tenta encontrar o runtime com o nome exato (prometeu-runtime-desktop)
|
// Tries to find the runtime with the exact name (prometeu-runtime-desktop)
|
||||||
// caso prometeu-runtime seja apenas um alias ou link que ainda não existe
|
// in case prometeu-runtime is just an alias or link that doesn't exist yet
|
||||||
let alt_bin_name = if bin_name == "prometeu-runtime" {
|
let alt_bin_name = if bin_name == "prometeu-runtime" {
|
||||||
Some("prometeu-runtime-desktop")
|
Some("prometeu-runtime-desktop")
|
||||||
} else {
|
} else {
|
||||||
@ -130,7 +130,7 @@ fn dispatch(exe_dir: &Path, bin_name: &str, args: &[&str]) {
|
|||||||
|
|
||||||
if !final_bin_path.exists() {
|
if !final_bin_path.exists() {
|
||||||
eprintln!(
|
eprintln!(
|
||||||
"prometeu: comando '{}' ainda não está disponível nesta distribuição",
|
"prometeu: command '{}' is not yet available in this distribution",
|
||||||
match bin_name {
|
match bin_name {
|
||||||
"prometeu-runtime" => "run/debug",
|
"prometeu-runtime" => "run/debug",
|
||||||
"prometeuc" => "build/verify c",
|
"prometeuc" => "build/verify c",
|
||||||
@ -159,7 +159,7 @@ fn execute_bin(bin_path: &Path, args: &[&str]) {
|
|||||||
std::process::exit(status.code().unwrap_or(0));
|
std::process::exit(status.code().unwrap_or(0));
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
eprintln!("Erro ao executar {}: {}", bin_path.display(), e);
|
eprintln!("Error executing {}: {}", bin_path.display(), e);
|
||||||
std::process::exit(1);
|
std::process::exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -167,7 +167,7 @@ fn execute_bin(bin_path: &Path, args: &[&str]) {
|
|||||||
|
|
||||||
fn not_implemented(cmd: &str, _bin_name: &str) {
|
fn not_implemented(cmd: &str, _bin_name: &str) {
|
||||||
eprintln!(
|
eprintln!(
|
||||||
"prometeu: comando '{}' ainda não está disponível nesta distribuição",
|
"prometeu: command '{}' is not yet available in this distribution",
|
||||||
cmd
|
cmd
|
||||||
);
|
);
|
||||||
std::process::exit(1);
|
std::process::exit(1);
|
||||||
|
|||||||
@ -1,31 +1,31 @@
|
|||||||
# Prometeu DevTools Protocol
|
# Prometeu DevTools Protocol
|
||||||
|
|
||||||
Este documento descreve o protocolo de comunicação entre o Runtime do Prometeu e ferramentas de desenvolvimento (como o Prometeu Debugger).
|
This document describes the communication protocol between the Prometeu Runtime and development tools (such as the Prometeu Debugger).
|
||||||
|
|
||||||
## Visão Geral
|
## Overview
|
||||||
|
|
||||||
O protocolo é baseado em JSON, enviado via uma conexão de transporte (geralmente TCP). Cada mensagem é um objeto JSON em uma única linha (JSONL).
|
The protocol is based on JSON, sent via a transport connection (usually TCP). Each message is a JSON object on a single line (JSONL).
|
||||||
|
|
||||||
## Estrutura
|
## Structure
|
||||||
|
|
||||||
- **[protocol.json](./protocol.json)**: Definição formal do protocolo em formato JSON.
|
- **[protocol.json](./protocol.json)**: Formal definition of the protocol in JSON format.
|
||||||
- **[protocol.md](README.md)**: Documentação legível para humanos descrevendo os comandos, eventos e tipos.
|
- **[protocol.md](README.md)**: Human-readable documentation describing commands, events, and types.
|
||||||
- **[examples/](./examples)**: Exemplos de fluxos de mensagens (handshake, breakpoints, etc.) em formato JSONL.
|
- **[examples/](./examples)**: Examples of message flows (handshake, breakpoints, etc.) in JSONL format.
|
||||||
|
|
||||||
## Versionamento
|
## Versioning
|
||||||
|
|
||||||
O protocolo possui uma versão explícita definida no campo `protocol_version`.
|
The protocol has an explicit version defined in the `protocol_version` field.
|
||||||
|
|
||||||
- Mudanças incompatíveis (breaking changes) incrementam a versão principal.
|
- Incompatible changes (breaking changes) increment the major version.
|
||||||
- Novos campos em mensagens existentes devem ser opcionais sempre que possível para manter compatibilidade retroativa.
|
- New fields in existing messages should be optional whenever possible to maintain backward compatibility.
|
||||||
|
|
||||||
A versão atual do protocolo é: **1**
|
The current protocol version is: **1**
|
||||||
|
|
||||||
## Handshake
|
## Handshake
|
||||||
|
|
||||||
Ao conectar, o Runtime envia uma mensagem de handshake para o cliente.
|
Upon connecting, the Runtime sends a handshake message to the client.
|
||||||
|
|
||||||
### Runtime -> Cliente
|
### Runtime -> Client
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
@ -41,43 +41,43 @@ Ao conectar, o Runtime envia uma mensagem de handshake para o cliente.
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### Cliente -> Runtime
|
### Client -> Runtime
|
||||||
|
|
||||||
O cliente deve responder com `start` ou `ok` para iniciar a sessão.
|
The client must respond with `start` or `ok` to start the session.
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{ "type": "start" }
|
{ "type": "start" }
|
||||||
```
|
```
|
||||||
|
|
||||||
## Requisições (Requests)
|
## Requests
|
||||||
|
|
||||||
O cliente pode enviar as seguintes requisições para controlar a execução:
|
The client can send the following requests to control execution:
|
||||||
|
|
||||||
| Nome | Parâmetros | Descrição |
|
| Name | Parameters | Description |
|
||||||
|------|------------|-----------|
|
|------|------------|-----------|
|
||||||
| `pause` | `[]` | Pausa a execução da VM. |
|
| `pause` | `[]` | Pauses VM execution. |
|
||||||
| `resume` | `[]` | Retoma a execução da VM. |
|
| `resume` | `[]` | Resumes VM execution. |
|
||||||
| `step` | `[]` | Executa uma única instrução (PC). |
|
| `step` | `[]` | Executes a single instruction (PC). |
|
||||||
| `stepFrame` | `[]` | Executa até o próximo frame. |
|
| `stepFrame` | `[]` | Executes until the next frame. |
|
||||||
| `getState` | `[]` | Retorna o estado atual da VM (`pc`, `stack_top`, `frame_index`, `app_id`). |
|
| `getState` | `[]` | Returns the current VM state (`pc`, `stack_top`, `frame_index`, `app_id`). |
|
||||||
| `setBreakpoint` | `{"pc": number}` | Define um breakpoint no endereço especificado. |
|
| `setBreakpoint` | `{"pc": number}` | Sets a breakpoint at the specified address. |
|
||||||
| `clearBreakpoint` | `{"pc": number}` | Remove um breakpoint no endereço especificado. |
|
| `clearBreakpoint` | `{"pc": number}` | Removes a breakpoint at the specified address. |
|
||||||
|
|
||||||
## Respostas (Responses)
|
## Responses
|
||||||
|
|
||||||
Algumas requisições geram respostas específicas. Por exemplo, `getState` retorna o estado da VM.
|
Some requests generate specific responses. For example, `getState` returns the VM state.
|
||||||
|
|
||||||
## Eventos (Events)
|
## Events
|
||||||
|
|
||||||
O Runtime pode enviar eventos assíncronos para o cliente:
|
The Runtime can send asynchronous events to the client:
|
||||||
|
|
||||||
| Nome | Campos | Descrição |
|
| Name | Fields | Description |
|
||||||
|------|--------|-----------|
|
|------|--------|-----------|
|
||||||
| `breakpointHit` | `pc`, `frame_index` | Emitido quando a execução atinge um breakpoint. |
|
| `breakpointHit` | `pc`, `frame_index` | Emitted when execution hits a breakpoint. |
|
||||||
| `log` | `level`, `source`, `msg` | Emitido quando o código em execução gera um log. |
|
| `log` | `level`, `source`, `msg` | Emitted when the running code generates a log. |
|
||||||
| `telemetry` | `frame_index`, `vm_steps`, `syscalls`, `cycles` | Estatísticas de execução enviadas periodicamente. |
|
| `telemetry` | `frame_index`, `vm_steps`, `syscalls`, `cycles` | Execution statistics sent periodically. |
|
||||||
| `cert` | `rule`, `used`, `limit`, `frame_index` | Informações de certificação e limites de recursos. |
|
| `cert` | `rule`, `used`, `limit`, `frame_index` | Certification information and resource limits. |
|
||||||
|
|
||||||
## Exemplos
|
## Examples
|
||||||
|
|
||||||
Veja a pasta `examples/` para fluxos de mensagens completos.
|
See the `examples/` folder for complete message flows.
|
||||||
|
|||||||
@ -1,15 +1,15 @@
|
|||||||
# PROMETEU Documentation
|
# PROMETEU Documentation
|
||||||
|
|
||||||
Este diretório contém a documentação técnica e especificações do projeto PROMETEU.
|
This directory contains the technical documentation and specifications for the PROMETEU project.
|
||||||
|
|
||||||
## Conteúdo
|
## Content
|
||||||
|
|
||||||
### 📜 [Especificações (Specs)](./specs)
|
### 📜 [Specifications (Specs)](./specs)
|
||||||
Documentação detalhada sobre a arquitetura do sistema, formato de cartuchos, conjunto de instruções da VM e muito mais.
|
Detailed documentation on system architecture, cartridge format, VM instruction set, and more.
|
||||||
- [Índice de Tópicos](./specs/topics/table-of-contents.md)
|
- [Topic Index](./specs/topics/table-of-contents.md)
|
||||||
|
|
||||||
### 🐞 [Debugger](./debugger)
|
### 🐞 [Debugger](./debugger)
|
||||||
Documentação sobre as ferramentas de depuração e como integrar novas ferramentas ao ecossistema.
|
Documentation on debugging tools and how to integrate new tools into the ecosystem.
|
||||||
|
|
||||||
### 🔌 [DevTools Protocol](../devtools-protocol)
|
### 🔌 [DevTools Protocol](../devtools-protocol)
|
||||||
Definição do protocolo de comunicação utilizado para depuração e inspeção em tempo real.
|
Definition of the communication protocol used for real-time debugging and inspection.
|
||||||
|
|||||||
@ -1,113 +1,113 @@
|
|||||||
# Especificação — Ciclo de Desenvolvimento Prometeu
|
# Specification — Prometeu Development Cycle
|
||||||
**Versão:** 0.1
|
**Version:** 0.1
|
||||||
**Status:** Conceitual / Filosófico
|
**Status:** Conceptual / Philosophical
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 1. Princípio Central
|
## 1. Central Principle
|
||||||
|
|
||||||
O Prometeu é uma plataforma didática de desenvolvimento de software interativo.
|
Prometeu is a didactic platform for interactive software development.
|
||||||
Seu ciclo de desenvolvimento é projetado para separar claramente:
|
Its development cycle is designed to clearly separate:
|
||||||
|
|
||||||
- Criação de código
|
- Code creation
|
||||||
- Compilação
|
- Compilation
|
||||||
- Execução
|
- Execution
|
||||||
- Observação e explicação
|
- Observation and explanation
|
||||||
|
|
||||||
Cada etapa possui uma ferramenta própria, especializada e não sobreposta.
|
Each stage has its own specialized, non-overlapping tool.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 2. Ferramentas do Ciclo
|
## 2. Cycle Tools
|
||||||
|
|
||||||
O ciclo utiliza quatro pilares:
|
The cycle uses four pillars:
|
||||||
|
|
||||||
1. **Editor de Código**
|
1. **Code Editor**
|
||||||
Ambiente livre (ex: WebStorm) onde o desenvolvedor escreve em TypeScript.
|
Free environment (e.g., WebStorm) where the developer writes in TypeScript.
|
||||||
|
|
||||||
2. **Compilador Prometeu**
|
2. **Prometeu Compiler**
|
||||||
Converte código fonte em bytecode executável pela runtime Prometeu.
|
Converts source code into executable bytecode for the Prometeu runtime.
|
||||||
|
|
||||||
3. **Runtime Prometeu**
|
3. **Prometeu Runtime**
|
||||||
Executa jogos e aplicações em seu próprio ambiente gráfico.
|
Executes games and applications in its own graphical environment.
|
||||||
|
|
||||||
4. **Prometeu Debugger**
|
4. **Prometeu Debugger**
|
||||||
Ferramenta didática de observação, análise e explicação do comportamento interno do sistema.
|
A didactic tool for observation, analysis, and explanation of the system's internal behavior.
|
||||||
|
|
||||||
Nenhuma dessas ferramentas tenta substituir a outra.
|
None of these tools try to replace each other.
|
||||||
Elas cooperam através de contratos claros.
|
They cooperate through clear contracts.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 3. Fluxo Geral
|
## 3. General Flow
|
||||||
|
|
||||||
O ciclo segue sempre a mesma sequência conceitual:
|
The cycle always follows the same conceptual sequence:
|
||||||
|
|
||||||
1. O desenvolvedor escreve código em TypeScript.
|
1. The developer writes code in TypeScript.
|
||||||
2. O código é compilado para bytecode Prometeu.
|
2. The code is compiled to Prometeu bytecode.
|
||||||
3. O bytecode é empacotado como cartucho.
|
3. The bytecode is packaged as a cartridge.
|
||||||
4. O cartucho é executado pela runtime.
|
4. The cartridge is executed by the runtime.
|
||||||
5. O comportamento interno pode ser observado pelo Prometeu Debugger.
|
5. Internal behavior can be observed by the Prometeu Debugger.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 4. Modos de Execução
|
## 4. Execution Modes
|
||||||
|
|
||||||
O Prometeu possui dois modos conceituais de execução:
|
Prometeu has two conceptual execution modes:
|
||||||
|
|
||||||
### Execução Normal (Run)
|
### Normal Execution (Run)
|
||||||
|
|
||||||
- O cartucho é empacotado e executado.
|
- The cartridge is packaged and executed.
|
||||||
- A runtime funciona de forma autônoma.
|
- The runtime operates autonomously.
|
||||||
- O Debugger atua apenas como observador.
|
- The Debugger acts only as an observer.
|
||||||
|
|
||||||
### Execução Assistida (Debug)
|
### Assisted Execution (Debug)
|
||||||
|
|
||||||
- O cartucho é empacotado e executado.
|
- The cartridge is packaged and executed.
|
||||||
- A runtime aguarda conexão do Prometeu Debugger.
|
- The runtime waits for a connection from the Prometeu Debugger.
|
||||||
- O Debugger passa a controlar e observar a execução.
|
- The Debugger begins to control and observe the execution.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 5. Separação de Papéis
|
## 5. Separation of Roles
|
||||||
|
|
||||||
Cada parte do ciclo tem responsabilidade única:
|
Each part of the cycle has a unique responsibility:
|
||||||
|
|
||||||
| Etapa | Papel principal |
|
| Stage | Main Role |
|
||||||
|-----------|--------------------------------------|
|
|------------|------------------------------------|
|
||||||
| Editor | Criar código |
|
| Editor | Create code |
|
||||||
| Compilador| Transformar código em bytecode |
|
| Compiler | Transform code into bytecode |
|
||||||
| Runtime | Executar |
|
| Runtime | Execute |
|
||||||
| Debugger | Observar, explicar e ensinar |
|
| Debugger | Observe, explain, and teach |
|
||||||
|
|
||||||
Essa separação é intencional e parte da filosofia do Prometeu.
|
This separation is intentional and part of the Prometeu philosophy.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 6. Filosofia Didática
|
## 6. Didactic Philosophy
|
||||||
|
|
||||||
O Prometeu não é apenas uma engine.
|
Prometeu is not just an engine.
|
||||||
Ele é uma plataforma para aprender como software interativo funciona por dentro.
|
It is a platform for learning how interactive software works from the inside.
|
||||||
|
|
||||||
O ciclo de desenvolvimento é pensado para:
|
The development cycle is designed to:
|
||||||
|
|
||||||
- Tornar a execução visível
|
- Make execution visible
|
||||||
- Tornar decisões técnicas observáveis
|
- Make technical decisions observable
|
||||||
- Tornar erros explicáveis
|
- Make errors explainable
|
||||||
- Tornar desempenho mensurável
|
- Make performance measurable
|
||||||
|
|
||||||
O Debugger não é apenas uma ferramenta de correção, mas um instrumento pedagógico.
|
The Debugger is not just a fix tool, but a pedagogical instrument.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 7. Síntese
|
## 7. Synthesis
|
||||||
|
|
||||||
O Ciclo de Desenvolvimento Prometeu é:
|
The Prometeu Development Cycle is:
|
||||||
|
|
||||||
- Modular
|
- Modular
|
||||||
- Observável
|
- Observable
|
||||||
- Didático
|
- Didactic
|
||||||
- Não acoplado a uma IDE específica
|
- Not coupled to a specific IDE
|
||||||
- Orientado a aprendizado e compreensão profunda
|
- Oriented towards learning and deep understanding
|
||||||
|
|
||||||
Ele existe para que o desenvolvedor não apenas escreva programas, mas entenda como eles vivem dentro da máquina.
|
It exists so that the developer does not just write programs, but understands how they live inside the machine.
|
||||||
|
|||||||
@ -1,190 +1,190 @@
|
|||||||
# 📜 Prometeu — O Fogo e a Promessa
|
# 📜 Prometeu — The Fire and the Promise
|
||||||
|
|
||||||
**PROMETEU** é um console imaginário.
|
**PROMETEU** is an imaginary console.
|
||||||
|
|
||||||
Mas não no sentido fraco de “imaginar”.
|
But not in the weak sense of "imagining".
|
||||||
|
|
||||||
PROMETEU foi **deliberadamente projetado** para existir como um **modelo computacional completo**: simples o bastante para ser entendido, e poderoso o suficiente para criar jogos reais.
|
PROMETEU was **deliberately designed** to exist as a **complete computational model**: simple enough to be understood, and powerful enough to create real games.
|
||||||
|
|
||||||
O nome PROMETEU carrega dois significados intencionais:
|
The name PROMETEU carries two intentional meanings:
|
||||||
|
|
||||||
- **Prometeu, o titã**, que roubou o fogo dos deuses e entregou aos humanos
|
- **Prometheus, the titan**, who stole fire from the gods and gave it to humans
|
||||||
- **“Prometeu” como verbo**, uma promessa feita
|
- **“Prometeu” as a verb**, a promise made (in Portuguese)
|
||||||
|
|
||||||
Neste projeto:
|
In this project:
|
||||||
|
|
||||||
- o *fogo* é o conhecimento de como computadores realmente funcionam
|
- the *fire* is the knowledge of how computers really work
|
||||||
- a *promessa* é que nada é mágico, nada é escondido, e tudo pode ser compreendido
|
- the *promise* is that nothing is magic, nothing is hidden, and everything can be understood
|
||||||
|
|
||||||
Este manual é essa promessa escrita.
|
This manual is that written promise.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 🎯 O que é o PROMETEU
|
## 🎯 What is PROMETEU
|
||||||
|
|
||||||
PROMETEU é um **Virtual Microconsole** — um computador fictício, com regras claras, recursos limitados e comportamento determinístico.
|
PROMETEU is a **Virtual Microconsole** — a fictitious computer, with clear rules, limited resources, and deterministic behavior.
|
||||||
|
|
||||||
Ele foi projetado para:
|
It was designed to:
|
||||||
|
|
||||||
- ensinar fundamentos reais de computação
|
- teach real computing fundamentals
|
||||||
- expor tempo, memória e execução
|
- expose time, memory, and execution
|
||||||
- permitir jogos 2D completos (plataformers, metroidvanias, arcade)
|
- allow full 2D games (platformers, metroidvanias, arcade)
|
||||||
- servir como ponte entre:
|
- serve as a bridge between:
|
||||||
- microcontroladores
|
- microcontrollers
|
||||||
- consoles clássicos
|
- classic consoles
|
||||||
- máquinas virtuais
|
- virtual machines
|
||||||
- engines modernas
|
- modern engines
|
||||||
|
|
||||||
PROMETEU **não é**:
|
PROMETEU **is not**:
|
||||||
|
|
||||||
- uma engine genérica
|
- a generic engine
|
||||||
- um substituto de Unity ou Godot
|
- a substitute for Unity or Godot
|
||||||
- um console comercial real
|
- a real commercial console
|
||||||
|
|
||||||
PROMETEU **é**:
|
PROMETEU **is**:
|
||||||
|
|
||||||
- um laboratório
|
- a laboratory
|
||||||
- um instrumento didático
|
- a didactic instrument
|
||||||
- um brinquedo sério
|
- a serious toy
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 🧠 Modelo Mental Fundamental
|
## 🧠 Fundamental Mental Model
|
||||||
|
|
||||||
> PROMETEU é um microcontrolador que desenha pixels, toca som e lida com inputs do jogador.
|
> PROMETEU is a microcontroller that draws pixels, plays sound, and handles player input.
|
||||||
>
|
>
|
||||||
|
|
||||||
Tudo no sistema deriva disso.
|
Everything in the system derives from this.
|
||||||
|
|
||||||
### Equivalência conceitual
|
### Conceptual equivalence
|
||||||
|
|
||||||
| Microcontrolador real | PROMETEU |
|
| Real microcontroller | PROMETEU |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| Clock | Tick da VM |
|
| Clock | VM Tick |
|
||||||
| Flash | Cartucho PROMETEU |
|
| Flash | PROMETEU Cartridge |
|
||||||
| RAM | Heap + Stack |
|
| RAM | Heap + Stack |
|
||||||
| GPIO | Input |
|
| GPIO | Input |
|
||||||
| DMA | Transferência gráfica |
|
| DMA | Graphics transfer |
|
||||||
| ISR | Eventos do sistema |
|
| ISR | System events |
|
||||||
| Periféricos | GFX, AUDIO, INPUT, FS |
|
| Peripherals | GFX, AUDIO, INPUT, FS |
|
||||||
|
|
||||||
Se você entende um MCU, você entende PROMETEU.
|
If you understand an MCU, you understand PROMETEU.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 🧩 Filosofia de Design
|
## 🧩 Design Philosophy
|
||||||
|
|
||||||
### 1. Simplicidade visível
|
### 1. Visible Simplicity
|
||||||
|
|
||||||
- Cada operação tem custo
|
- Every operation has a cost
|
||||||
- Cada frame tem orçamento
|
- Every frame has a budget
|
||||||
- Cada erro tem causa observável
|
- Every error has an observable cause
|
||||||
|
|
||||||
Nada acontece “porque sim”.
|
Nothing happens "just because".
|
||||||
|
|
||||||
### 2. Determinismo
|
### 2. Determinism
|
||||||
|
|
||||||
- Mesmo cartucho
|
- Same cartridge
|
||||||
- Mesma entrada
|
- Same input
|
||||||
- Mesmo resultado
|
- Same result
|
||||||
|
|
||||||
Independente da plataforma.
|
Regardless of the platform.
|
||||||
|
|
||||||
### 3. Limitação como ferramenta pedagógica
|
### 3. Limitation as a pedagogical tool
|
||||||
|
|
||||||
PROMETEU impõe limites **intencionais**:
|
PROMETEU imposes **intentional** limits:
|
||||||
|
|
||||||
- memória finita
|
- finite memory
|
||||||
- tempo por frame
|
- time per frame
|
||||||
- recursos gráficos limitados
|
- limited graphics resources
|
||||||
|
|
||||||
Limites ensinam design.
|
Limits teach design.
|
||||||
|
|
||||||
### 4. Profundidade progressiva
|
### 4. Progressive depth
|
||||||
|
|
||||||
PROMETEU pode ser explorado em camadas:
|
PROMETEU can be explored in layers:
|
||||||
|
|
||||||
1. **Camada Jogo** — `update()` e `draw()`
|
1. **Game Layer** — `update()` and `draw()`
|
||||||
2. **Camada Sistema** — bytecode, stack, heap
|
2. **System Layer** — bytecode, stack, heap
|
||||||
3. **Camada Máquina** — ciclos, eventos, periféricos
|
3. **Machine Layer** — cycles, events, peripherals
|
||||||
|
|
||||||
O aluno decide até onde descer.
|
The student decides how deep to go.
|
||||||
|
|
||||||
## 🏗️ Arquitetura Geral
|
## 🏗️ General Architecture
|
||||||
|
|
||||||
```
|
```
|
||||||
+---------------------------+
|
+---------------------------+
|
||||||
| CARTUCHO |
|
| CARTRIDGE |
|
||||||
| (bytecodeX + assets) |
|
| (bytecodeX + assets) |
|
||||||
+-------------+-------------+
|
+-------------+-------------+
|
||||||
|
|
|
|
||||||
+-------------v-------------+
|
+-------------v-------------+
|
||||||
| PROMETEU VM |
|
| PROMETEU VM |
|
||||||
| (stack-based, |
|
| (stack-based, |
|
||||||
| determinística) |
|
| deterministic) |
|
||||||
+-------------+-------------+
|
+-------------+-------------+
|
||||||
|
|
|
|
||||||
+-------------v-------------+
|
+-------------v-------------+
|
||||||
| PERIFÉRICOS VIRTUAIS |
|
| VIRTUAL PERIPHERALS |
|
||||||
| GFX | AUDIO |INPUT | FS| |
|
| GFX | AUDIO |INPUT | FS| |
|
||||||
+-------------+-------------+
|
+-------------+-------------+
|
||||||
|
|
|
|
||||||
+-------------v-------------+
|
+-------------v-------------+
|
||||||
| CAMADA DE PLATAFORMA |
|
| PLATFORM LAYER |
|
||||||
| PC | SteamOS | Android |
|
| PC | SteamOS | Android |
|
||||||
| iOS | Consoles (futuro) |
|
| iOS | Consoles (future) |
|
||||||
+---------------------------+
|
+---------------------------+
|
||||||
```
|
```
|
||||||
|
|
||||||
Este manual descreve **a máquina PROMETEU**, não ferramentas externas.
|
This manual describes **the PROMETEU machine**, not external tools.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 📦 O Cartucho PROMETEU
|
## 📦 The PROMETEU Cartridge
|
||||||
|
|
||||||
Um **cartucho PROMETEU** é um pacote imutável, equivalente a firmware.
|
A **PROMETEU cartridge** is an immutable package, equivalent to firmware.
|
||||||
|
|
||||||
Conteúdo típico:
|
Typical content:
|
||||||
|
|
||||||
- `program.pbx` — bytecode PROMETEU (bytecodeX)
|
- `program.pbx` — PROMETEU bytecode (bytecodeX)
|
||||||
- `assets/` — gráficos, áudio, mapas
|
- `assets/` — graphics, audio, maps
|
||||||
- `manifest.json` — metadados e configuração
|
- `manifest.json` — metadata and configuration
|
||||||
|
|
||||||
O cartucho:
|
The cartridge:
|
||||||
|
|
||||||
- sempre pode ser executado
|
- can always be executed
|
||||||
- sempre pode ser distribuído
|
- can always be distributed
|
||||||
- nunca é bloqueado pelo sistema
|
- is never blocked by the system
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 🧪 Linguagens de Programação
|
## 🧪 Programming Languages
|
||||||
|
|
||||||
PROMETEU **não executa linguagens de alto nível diretamente**.
|
PROMETEU **does not execute high-level languages directly**.
|
||||||
|
|
||||||
As linguagens são **fontes**, compiladas para bytecode PROMETEU.
|
The languages are **sources**, compiled to PROMETEU bytecode.
|
||||||
|
|
||||||
### Linguagens planejadas
|
### Planned languages
|
||||||
|
|
||||||
- **Java (subset)** — arquitetura, ensino profundo
|
- **Java (subset)** — architecture, deep teaching
|
||||||
- **TypeScript (subset)** — acessibilidade e mercado
|
- **TypeScript (subset)** — accessibility and market
|
||||||
- **Lua (subset)** — scripting clássico e leve
|
- **Lua (subset)** — classic and lightweight scripting
|
||||||
|
|
||||||
Todas convergem para:
|
All converge to:
|
||||||
|
|
||||||
> O mesmo bytecode. A mesma VM. O mesmo comportamento.
|
> The same bytecode. The same VM. The same behavior.
|
||||||
>
|
>
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 🔄 Modelo de Execução
|
## 🔄 Execution Model
|
||||||
|
|
||||||
PROMETEU executa em um loop fixo:
|
PROMETEU executes in a fixed loop:
|
||||||
|
|
||||||
```
|
```
|
||||||
BOOT
|
BOOT
|
||||||
↓
|
↓
|
||||||
LOAD CARTUCHO
|
LOAD CARTRIDGE
|
||||||
↓
|
↓
|
||||||
INIT
|
INIT
|
||||||
↓
|
↓
|
||||||
@ -197,68 +197,68 @@ LOOP (60 Hz):
|
|||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
- Frequência padrão: **60 Hz**
|
- Default frequency: **60 Hz**
|
||||||
- Cada iteração corresponde a **um frame**
|
- Each iteration corresponds to **one frame**
|
||||||
- O tempo de execução é **mensurável**
|
- Execution time is **measurable**
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## ⏱️ CAP — Execution Cap (Orçamento de Execução)
|
## ⏱️ CAP — Execution Cap
|
||||||
|
|
||||||
### Definição
|
### Definition
|
||||||
|
|
||||||
O **CAP** define um orçamento de execução (tempo, memória e recursos) **em um contexto específico**, como uma Game Jam ou avaliação.
|
The **CAP** defines an execution budget (time, memory, and resources) **in a specific context**, such as a Game Jam or evaluation.
|
||||||
|
|
||||||
> CAP nunca bloqueia execução.
|
> CAP never blocks execution.
|
||||||
CAP nunca bloqueia empacotamento.
|
> CAP never blocks packaging.
|
||||||
CAP nunca impede o jogo de ser jogado.
|
> CAP never prevents the game from being played.
|
||||||
>
|
>
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### Quando o CAP é usado
|
### When the CAP is used
|
||||||
|
|
||||||
- Game Jams PROMETEU
|
- PROMETEU Game Jams
|
||||||
- Avaliações acadêmicas
|
- Academic evaluations
|
||||||
- Desafios técnicos
|
- Technical challenges
|
||||||
- Comparações entre soluções
|
- Comparisons between solutions
|
||||||
|
|
||||||
Fora desses contextos, PROMETEU opera em **modo livre**.
|
Outside of these contexts, PROMETEU operates in **free mode**.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### O papel do CAP
|
### The role of the CAP
|
||||||
|
|
||||||
O CAP serve para:
|
The CAP serves to:
|
||||||
|
|
||||||
- orientar decisões técnicas
|
- guide technical decisions
|
||||||
- fornecer feedback mensurável
|
- provide measurable feedback
|
||||||
- gerar **certificações técnicas**
|
- generate **technical certifications**
|
||||||
- criar critérios objetivos de avaliação
|
- create objective evaluation criteria
|
||||||
|
|
||||||
PROMETEU **ajuda durante o desenvolvimento**:
|
PROMETEU **helps during development**:
|
||||||
|
|
||||||
- indicadores visuais
|
- visual indicators
|
||||||
- alertas de custo
|
- cost alerts
|
||||||
- profiling por frame
|
- per-frame profiling
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 📄 Certificação PROMETEU
|
## 📄 PROMETEU Certification
|
||||||
|
|
||||||
### O que é
|
### What it is
|
||||||
|
|
||||||
A **Certificação PROMETEU** é um relatório técnico gerado a partir da execução do jogo sob um CAP definido.
|
The **PROMETEU Certification** is a technical report generated from the execution of the game under a defined CAP.
|
||||||
|
|
||||||
Ela:
|
It:
|
||||||
|
|
||||||
- **não impede** o jogo
|
- **does not prevent** the game from running
|
||||||
- **não invalida** a entrega
|
- **does not invalidate** the delivery
|
||||||
- **registra evidências técnicas**
|
- **records technical evidence**
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### Exemplo de relatório
|
### Report Example
|
||||||
|
|
||||||
```
|
```
|
||||||
PROMETEUCERTIFICATIONREPORT
|
PROMETEUCERTIFICATIONREPORT
|
||||||
@ -281,19 +281,19 @@ Notes:
|
|||||||
-Heappressurecausedbyper-frameallocations
|
-Heappressurecausedbyper-frameallocations
|
||||||
```
|
```
|
||||||
|
|
||||||
O relatório **acompanha o jogo**.
|
The report **accompanies the game**.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 🎓 Uso Educacional
|
## 🎓 Educational Use
|
||||||
|
|
||||||
A avaliação pode considerar:
|
Evaluation may consider:
|
||||||
|
|
||||||
- Qualidade do jogo (criatividade, design)
|
- Game quality (creativity, design)
|
||||||
- Qualidade técnica (certificação)
|
- Technical quality (certification)
|
||||||
- Decisões arquiteturais justificadas
|
- Justified architectural decisions
|
||||||
- Evolução entre versões
|
- Evolution between versions
|
||||||
|
|
||||||
PROMETEU avalia **processo**, não apenas resultado.
|
PROMETEU evaluates **process**, not just result.
|
||||||
|
|
||||||
< [Sumário](topics/table-of-contents.md) >
|
< [Summary](topics/table-of-contents.md) >
|
||||||
@ -1,45 +1,45 @@
|
|||||||
< [Sumário](table-of-contents.md) | [Adiante](chapter-2.md) >
|
< [Summary](table-of-contents.md) | [Next](chapter-2.md) >
|
||||||
|
|
||||||
# ⏱️ **Modelo de Tempo e Ciclos**
|
# ⏱️ **Time Model and Cycles**
|
||||||
|
|
||||||
# 1. Visão Geral
|
# 1. Overview
|
||||||
|
|
||||||
PROMETEU é um sistema **orientado a tempo**.
|
PROMETEU is a **time-oriented** system.
|
||||||
|
|
||||||
Nada acontece “instantaneamente”.
|
Nothing happens "instantly".
|
||||||
|
|
||||||
Toda ação consome **tempo mensurável**, expresso em **ciclos de execução**.
|
Every action consumes **measurable time**, expressed in **execution cycles**.
|
||||||
|
|
||||||
Este capítulo define:
|
This chapter defines:
|
||||||
|
|
||||||
- o **clock base** do sistema
|
- the system's **base clock**
|
||||||
- o conceito de **ciclo PROMETEU**
|
- the concept of a **PROMETEU cycle**
|
||||||
- como o tempo é distribuído ao longo dos frames
|
- how time is distributed across frames
|
||||||
- como o **CAP (Execution Cap)** se relaciona com esse modelo
|
- how the **CAP (Execution Cap)** relates to this model
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 2. Clock Base do Sistema
|
## 2. System Base Clock
|
||||||
|
|
||||||
PROMETEU opera com um **clock fixo de 60 Hz**.
|
PROMETEU operates with a **fixed clock of 60 Hz**.
|
||||||
|
|
||||||
Isso significa:
|
This means:
|
||||||
|
|
||||||
- 60 iterações do loop principal por segundo
|
- 60 iterations of the main loop per second
|
||||||
- cada iteração corresponde a **um frame**
|
- each iteration corresponds to **one frame**
|
||||||
- o clock é **determinístico e estável**, independente da plataforma
|
- the clock is **deterministic and stable**, regardless of the platform
|
||||||
|
|
||||||
> O clock define o ritmo da máquina,
|
> The clock defines the machine's rhythm,
|
||||||
não a quantidade de trabalho obrigatório por frame.
|
not the amount of mandatory work per frame.
|
||||||
>
|
>
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 3. O Frame PROMETEU
|
## 3. The PROMETEU Frame
|
||||||
|
|
||||||
Um **frame PROMETEU** representa uma unidade completa de execução.
|
A **PROMETEU frame** represents a complete unit of execution.
|
||||||
|
|
||||||
Cada frame executa, conceitualmente, as seguintes etapas:
|
Each frame conceptually executes the following stages:
|
||||||
|
|
||||||
```
|
```
|
||||||
FRAME N
|
FRAME N
|
||||||
@ -53,61 +53,61 @@ SYNC
|
|||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
O sistema garante:
|
The system guarantees:
|
||||||
|
|
||||||
- ordem fixa
|
- fixed order
|
||||||
- repetição previsível
|
- predictable repetition
|
||||||
- ausência de frames “fantasmas”
|
- absence of "ghost" frames
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 4. Ciclos PROMETEU
|
## 4. PROMETEU Cycles
|
||||||
|
|
||||||
### 4.1 Definição
|
### 4.1 Definition
|
||||||
|
|
||||||
Um **ciclo PROMETEU** é a menor unidade abstrata de tempo do sistema.
|
A **PROMETEU cycle** is the smallest abstract unit of time in the system.
|
||||||
|
|
||||||
- cada instrução da VM consome um número fixo de ciclos
|
- each VM instruction consumes a fixed number of cycles
|
||||||
- chamadas de periféricos também possuem custo
|
- peripheral calls also have a cost
|
||||||
- o custo é **documentado e estável**
|
- the cost is **documented and stable**
|
||||||
|
|
||||||
Ciclos são:
|
Cycles are:
|
||||||
|
|
||||||
- **contáveis**
|
- **countable**
|
||||||
- **comparáveis**
|
- **comparable**
|
||||||
- **independentes de hardware real**
|
- **independent of real hardware**
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### 4.2 Por que ciclos, e não milissegundos?
|
### 4.2 Why cycles, and not milliseconds?
|
||||||
|
|
||||||
PROMETEU não mede tempo em milissegundos porque:
|
PROMETEU does not measure time in milliseconds because:
|
||||||
|
|
||||||
- milissegundos variam entre plataformas
|
- milliseconds vary between platforms
|
||||||
- clocks reais diferem
|
- real clocks differ
|
||||||
- jitter e latência escondem custo real
|
- jitter and latency hide the real cost
|
||||||
|
|
||||||
Ciclos permitem afirmar:
|
Cycles allow stating:
|
||||||
|
|
||||||
> “Este programa é mais caro que aquele,
|
> "This program is more expensive than that one,
|
||||||
>
|
>
|
||||||
>
|
>
|
||||||
> independentemente de onde ele rode.”
|
> regardless of where it runs."
|
||||||
>
|
>
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 5. Orçamento por Frame
|
## 5. Per-Frame Budget
|
||||||
|
|
||||||
Cada frame possui um **orçamento máximo de ciclos**.
|
Each frame has a **maximum cycle budget**.
|
||||||
|
|
||||||
Esse orçamento:
|
This budget:
|
||||||
|
|
||||||
- é resetado a cada frame
|
- is reset every frame
|
||||||
- não acumula ciclos não utilizados
|
- does not accumulate unused cycles
|
||||||
- representa a capacidade da “CPU virtual”
|
- represents the capacity of the "virtual CPU"
|
||||||
|
|
||||||
### Exemplo conceitual
|
### Conceptual example
|
||||||
|
|
||||||
```
|
```
|
||||||
Frame Budget:10,000cycles
|
Frame Budget:10,000cycles
|
||||||
@ -124,107 +124,107 @@ Remaining:
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 6. Separação entre Clock e Trabalho
|
## 6. Separation between Clock and Work
|
||||||
|
|
||||||
PROMETEU **não exige** que toda lógica rode a cada frame.
|
PROMETEU **does not require** all logic to run every frame.
|
||||||
|
|
||||||
O programador é **explicitamente encorajado** a distribuir trabalho no tempo.
|
The programmer is **explicitly encouraged** to distribute work over time.
|
||||||
|
|
||||||
### Exemplos comuns
|
### Common examples
|
||||||
|
|
||||||
- lógica de inimigos a cada 2 frames (30 Hz)
|
- enemy logic every 2 frames (30 Hz)
|
||||||
- pathfinding a cada 4 frames (15 Hz)
|
- pathfinding every 4 frames (15 Hz)
|
||||||
- animações independentes da AI
|
- animations independent of AI
|
||||||
- timers baseados em contagem de frames
|
- timers based on frame count
|
||||||
|
|
||||||
Isso reflete práticas reais de:
|
This reflects real-world practices from:
|
||||||
|
|
||||||
- consoles clássicos
|
- classic consoles
|
||||||
- sistemas embarcados
|
- embedded systems
|
||||||
- firmware de microcontroladores
|
- microcontroller firmware
|
||||||
|
|
||||||
> Nem tudo precisa acontecer agora.
|
> Not everything needs to happen now.
|
||||||
>
|
>
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 7. Distribuição Temporal como Arquitetura
|
## 7. Temporal Distribution as Architecture
|
||||||
|
|
||||||
PROMETEU trata **distribuição de trabalho no tempo** como uma decisão arquitetural.
|
PROMETEU treats **work distribution over time** as an architectural decision.
|
||||||
|
|
||||||
Isso significa que:
|
This means that:
|
||||||
|
|
||||||
- código que roda todo frame é mais caro
|
- code that runs every frame is more expensive
|
||||||
- código distribuído é mais eficiente
|
- distributed code is more efficient
|
||||||
- otimização é, antes de tudo, **organização temporal**
|
- optimization is, first and foremost, **temporal organization**
|
||||||
|
|
||||||
PROMETEU ensina:
|
PROMETEU teaches:
|
||||||
|
|
||||||
> desempenho não vem só de “menos código”,
|
> performance doesn't just come from "less code",
|
||||||
>
|
>
|
||||||
>
|
>
|
||||||
> mas de **quando** o código roda.
|
> but from **when** the code runs.
|
||||||
>
|
>
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 8. Execution CAP (Orçamento Contextual)
|
## 8. Execution CAP (Contextual Budget)
|
||||||
|
|
||||||
### 8.1 O que é o CAP
|
### 8.1 What is the CAP
|
||||||
|
|
||||||
O **CAP** define um conjunto de limites técnicos associados a um **contexto específico**, como:
|
The **CAP** defines a set of technical limits associated with a **specific context**, such as:
|
||||||
|
|
||||||
- Game Jams
|
- Game Jams
|
||||||
- avaliações acadêmicas
|
- academic evaluations
|
||||||
- desafios técnicos
|
- technical challenges
|
||||||
|
|
||||||
O CAP pode definir:
|
The CAP can define:
|
||||||
|
|
||||||
- orçamento máximo de ciclos por frame
|
- maximum cycle budget per frame
|
||||||
- limite de memória
|
- memory limit
|
||||||
- limites de chamadas de periféricos
|
- peripheral call limits
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### 8.2 CAP não bloqueia execução
|
### 8.2 CAP does not block execution
|
||||||
|
|
||||||
Regras fundamentais:
|
Fundamental rules:
|
||||||
|
|
||||||
- o jogo **sempre roda**
|
- the game **always runs**
|
||||||
- o jogo **sempre pode ser empacotado**
|
- the game **can always be packaged**
|
||||||
- o jogo **sempre pode ser jogado**
|
- the game **can always be played**
|
||||||
|
|
||||||
O CAP **nunca impede** execução.
|
The CAP **never prevents** execution.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### 8.3 CAP gera evidência, não punição
|
### 8.3 CAP generates evidence, not punishment
|
||||||
|
|
||||||
Quando um CAP está ativo, PROMETEU:
|
When a CAP is active, PROMETEU:
|
||||||
|
|
||||||
- mede execução
|
- measures execution
|
||||||
- registra picos
|
- records peaks
|
||||||
- identifica gargalos
|
- identifies bottlenecks
|
||||||
- gera **relatório de certificação**
|
- generates a **certification report**
|
||||||
|
|
||||||
Esse relatório:
|
This report:
|
||||||
|
|
||||||
- não bloqueia o jogo
|
- does not block the game
|
||||||
- não invalida a entrega
|
- does not invalidate the delivery
|
||||||
- **documenta conformidade ou não conformidade**
|
- **documents compliance or non-compliance**
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 9. Certificação Baseada em Tempo
|
## 9. Time-Based Certification
|
||||||
|
|
||||||
A certificação PROMETEU analisa:
|
PROMETEU certification analyzes:
|
||||||
|
|
||||||
- uso médio de ciclos por frame
|
- average cycle usage per frame
|
||||||
- picos máximos
|
- maximum peaks
|
||||||
- frames problemáticos
|
- problematic frames
|
||||||
- distribuição de custo
|
- cost distribution
|
||||||
|
|
||||||
Exemplo:
|
Example:
|
||||||
|
|
||||||
```
|
```
|
||||||
Target CAP:PROMETEU-LITE
|
Target CAP:PROMETEU-LITE
|
||||||
@ -238,17 +238,17 @@ enemy.updateAI():1,012cycles
|
|||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Essa certificação acompanha o jogo como **artefato técnico**.
|
This certification accompanies the game as a **technical artifact**.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 10. Implicações Pedagógicas
|
## 10. Pedagogical Implications
|
||||||
|
|
||||||
O modelo de tempo e ciclos permite ensinar:
|
The time and cycles model allows teaching:
|
||||||
|
|
||||||
- planejamento de execução
|
- execution planning
|
||||||
- arquitetura orientada a tempo
|
- time-oriented architecture
|
||||||
- trade-offs técnicos
|
- technical trade-offs
|
||||||
- leitura de perfis reais
|
- reading real profiles
|
||||||
|
|
||||||
< [Sumário](table-of-contents.md) | [Adiante](chapter-2.md) >
|
< [Summary](table-of-contents.md) | [Next](chapter-2.md) >
|
||||||
@ -1,194 +1,194 @@
|
|||||||
< [Voltar](chapter-9.md) | [Sumário](table-of-contents.md) | [Adiante](chapter-11.md) >
|
< [Back](chapter-9.md) | [Summary](table-of-contents.md) | [Next](chapter-11.md) >
|
||||||
|
|
||||||
# 🛠️ **Debug, Inspeção e Profiling**
|
# 🛠️ **Debug, Inspection, and Profiling**
|
||||||
|
|
||||||
## 1. Visão Geral
|
## 1. Overview
|
||||||
|
|
||||||
PROMETEU foi projetado para **ser observado**.
|
PROMETEU was designed to **be observed**.
|
||||||
|
|
||||||
Debug, inspeção e profiling **não são ferramentas externas opcionais** —
|
Debug, inspection, and profiling **are not optional external tools** —
|
||||||
|
|
||||||
eles são **partes integrantes da máquina**.
|
they are **integral parts of the machine**.
|
||||||
|
|
||||||
Nada acontece sem deixar rastros.
|
Nothing happens without leaving traces.
|
||||||
|
|
||||||
Nada consome recursos sem ser medido.
|
Nothing consumes resources without being measured.
|
||||||
|
|
||||||
Nada falha sem explicação.
|
Nothing fails without explanation.
|
||||||
|
|
||||||
> PROMETEU não esconde estado.
|
> PROMETEU does not hide state.
|
||||||
PROMETEU expõe comportamento.
|
> PROMETEU exposes behavior.
|
||||||
>
|
>
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 2. Filosofia de Debug em PROMETEU
|
## 2. Debug Philosophy in PROMETEU
|
||||||
|
|
||||||
PROMETEU segue três princípios fundamentais de debug:
|
PROMETEU follows three fundamental debug principles:
|
||||||
|
|
||||||
1. **Estado antes de abstração**
|
1. **State before abstraction**
|
||||||
|
|
||||||
O programador vê a máquina antes de ver “features”.
|
The programmer sees the machine before seeing “features”.
|
||||||
|
|
||||||
2. **Tempo como primeira classe**
|
2. **Time as first class**
|
||||||
|
|
||||||
Cada ação é analisada no contexto do frame e dos ciclos.
|
Every action is analyzed in the context of the frame and cycles.
|
||||||
|
|
||||||
3. **Observação não altera execução**
|
3. **Observation does not alter execution**
|
||||||
|
|
||||||
Debug nunca muda o comportamento do sistema.
|
Debug never changes the behavior of the system.
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 3. Modos de Execução
|
## 3. Execution Modes
|
||||||
|
|
||||||
PROMETEU opera em três modos principais:
|
PROMETEU operates in three main modes:
|
||||||
|
|
||||||
### 3.1 Modo Normal
|
### 3.1 Normal Mode
|
||||||
|
|
||||||
- execução contínua
|
- continuous execution
|
||||||
- sem inspeção detalhada
|
- no detailed inspection
|
||||||
- foco em jogo e experiência
|
- focus on game and experience
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### 3.2 Modo Debug
|
### 3.2 Debug Mode
|
||||||
|
|
||||||
- execução controlada
|
- controlled execution
|
||||||
- acesso a estado interno
|
- access to internal state
|
||||||
- pausas e stepping
|
- pauses and stepping
|
||||||
|
|
||||||
Este modo é usado para:
|
This mode is used for:
|
||||||
|
|
||||||
- aprendizado
|
- learning
|
||||||
- investigação
|
- investigation
|
||||||
- correção de erros
|
- error correction
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### 3.3 Modo Certificação
|
### 3.3 Certification Mode
|
||||||
|
|
||||||
- execução determinística
|
- deterministic execution
|
||||||
- métricas coletadas
|
- collected metrics
|
||||||
- geração de relatório
|
- report generation
|
||||||
|
|
||||||
Nenhum modo altera o resultado lógico do programa.
|
No mode alters the logical result of the program.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 4. Debug de Execução
|
## 4. Execution Debug
|
||||||
|
|
||||||
### 4.1 Pausa e Continuação
|
### 4.1 Pause and Resume
|
||||||
|
|
||||||
O sistema pode ser pausado em pontos seguros:
|
The system can be paused at safe points:
|
||||||
|
|
||||||
- início do frame
|
- frame start
|
||||||
- antes de UPDATE
|
- before UPDATE
|
||||||
- após DRAW
|
- after DRAW
|
||||||
- antes do SYNC
|
- before SYNC
|
||||||
|
|
||||||
Durante pausa:
|
During pause:
|
||||||
|
|
||||||
- estado é congelado
|
- state is frozen
|
||||||
- buffers não são trocados
|
- buffers are not swapped
|
||||||
- tempo lógico não avança
|
- logical time does not advance
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### 4.2 Step-by-Step
|
### 4.2 Step-by-Step
|
||||||
|
|
||||||
PROMETEU permite stepping em diferentes níveis:
|
PROMETEU allows stepping at different levels:
|
||||||
|
|
||||||
- **por frame**
|
- **by frame**
|
||||||
- **por função**
|
- **by function**
|
||||||
- **por instrução da VM**
|
- **by VM instruction**
|
||||||
|
|
||||||
Stepping por instrução revela:
|
Stepping by instruction reveals:
|
||||||
|
|
||||||
- Program Counter (PC)
|
- Program Counter (PC)
|
||||||
- instrução atual
|
- current instruction
|
||||||
- pilha de operandos
|
- operand stack
|
||||||
- call stack
|
- call stack
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 5. Inspeção de Estado
|
## 5. State Inspection
|
||||||
|
|
||||||
### 5.1 Pilhas
|
### 5.1 Stacks
|
||||||
|
|
||||||
PROMETEU permite inspecionar:
|
PROMETEU allows inspecting:
|
||||||
|
|
||||||
- **Operand Stack**
|
- **Operand Stack**
|
||||||
- **Call Stack**
|
- **Call Stack**
|
||||||
|
|
||||||
Para cada frame:
|
For each frame:
|
||||||
|
|
||||||
- conteúdo
|
- content
|
||||||
- profundidade
|
- depth
|
||||||
- crescimento e limpeza
|
- growth and cleanup
|
||||||
|
|
||||||
Stack overflow e underflow são imediatamente visíveis.
|
Stack overflow and underflow are immediately visible.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### 5.2 Heap
|
### 5.2 Heap
|
||||||
|
|
||||||
O heap pode ser inspecionado em tempo real:
|
The heap can be inspected in real time:
|
||||||
|
|
||||||
- tamanho total
|
- total size
|
||||||
- uso atual
|
- current usage
|
||||||
- pico de uso
|
- peak usage
|
||||||
- objetos vivos
|
- live objects
|
||||||
|
|
||||||
O programador pode observar:
|
The programmer can observe:
|
||||||
|
|
||||||
- padrões de alocação
|
- allocation patterns
|
||||||
- fragmentação
|
- fragmentation
|
||||||
- pressão de GC
|
- GC pressure
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### 5.3 Espaço Global
|
### 5.3 Global Space
|
||||||
|
|
||||||
Variáveis globais:
|
Global variables:
|
||||||
|
|
||||||
- valores atuais
|
- current values
|
||||||
- referências
|
- references
|
||||||
- inicialização
|
- initialization
|
||||||
|
|
||||||
Globais são visíveis como **RAM estática**.
|
Globals are visible as **static RAM**.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 6. Debug Gráfico
|
## 6. Graphics Debug
|
||||||
|
|
||||||
PROMETEU permite inspecionar o sistema gráfico:
|
PROMETEU allows inspecting the graphics system:
|
||||||
|
|
||||||
- front buffer
|
- front buffer
|
||||||
- back buffer
|
- back buffer
|
||||||
- estado da paleta
|
- palette state
|
||||||
- sprites ativos
|
- active sprites
|
||||||
|
|
||||||
É possível:
|
It is possible to:
|
||||||
|
|
||||||
- congelar a imagem
|
- freeze the image
|
||||||
- observar buffers separadamente
|
- observe buffers separately
|
||||||
- identificar redraw excessivo
|
- identify excessive redraw
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 7. Profiling de Tempo (Ciclos)
|
## 7. Time Profiling (Cycles)
|
||||||
|
|
||||||
### 7.1 Medição por Frame
|
### 7.1 Per-Frame Measurement
|
||||||
|
|
||||||
Para cada frame, PROMETEU registra:
|
For each frame, PROMETEU records:
|
||||||
|
|
||||||
- ciclos totais usados
|
- total cycles used
|
||||||
- ciclos por subsistema
|
- cycles per subsystem
|
||||||
- picos de execução
|
- execution peaks
|
||||||
|
|
||||||
Exemplo conceitual:
|
Conceptual example:
|
||||||
|
|
||||||
```
|
```
|
||||||
Frame 18231:
|
Frame 18231:
|
||||||
@ -201,47 +201,47 @@ SYSTEM:612
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### 7.2 Profiling por Função
|
### 7.2 Per-Function Profiling
|
||||||
|
|
||||||
PROMETEU pode associar ciclos a:
|
PROMETEU can associate cycles with:
|
||||||
|
|
||||||
- funções
|
- functions
|
||||||
- métodos
|
- methods
|
||||||
- blocos lógicos
|
- logical blocks
|
||||||
|
|
||||||
Isso permite responder:
|
This allows answering:
|
||||||
|
|
||||||
> “onde o tempo está sendo gasto?”
|
> “where is the time being spent?”
|
||||||
>
|
>
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### 7.3 Profiling por Instrução
|
### 7.3 Per-Instruction Profiling
|
||||||
|
|
||||||
No nível mais baixo, o sistema pode exibir:
|
At the lowest level, the system can display:
|
||||||
|
|
||||||
- instruções executadas
|
- executed instructions
|
||||||
- custo individual
|
- individual cost
|
||||||
- frequência
|
- frequency
|
||||||
|
|
||||||
Esse nível é especialmente útil para:
|
This level is especially useful for:
|
||||||
|
|
||||||
- ensino de VM
|
- VM teaching
|
||||||
- otimização profunda
|
- deep optimization
|
||||||
- análise de bytecode
|
- bytecode analysis
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 8. Profiling de Memória
|
## 8. Memory Profiling
|
||||||
|
|
||||||
PROMETEU registra:
|
PROMETEU records:
|
||||||
|
|
||||||
- uso médio de heap
|
- average heap usage
|
||||||
- pico de heap
|
- heap peak
|
||||||
- alocações por frame
|
- allocations per frame
|
||||||
- frequência de GC
|
- GC frequency
|
||||||
|
|
||||||
Exemplo:
|
Example:
|
||||||
|
|
||||||
```
|
```
|
||||||
Heap:
|
Heap:
|
||||||
@ -250,101 +250,101 @@ Peak:34KB❌
|
|||||||
Limit:32KB
|
Limit:32KB
|
||||||
```
|
```
|
||||||
|
|
||||||
Esses dados alimentam diretamente a certificação.
|
These data directly feed the certification.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 9. Breakpoints e Watchpoints
|
## 9. Breakpoints and Watchpoints
|
||||||
|
|
||||||
### 9.1 Breakpoints
|
### 9.1 Breakpoints
|
||||||
|
|
||||||
PROMETEU suporta breakpoints em:
|
PROMETEU supports breakpoints in:
|
||||||
|
|
||||||
- frames específicos
|
- specific frames
|
||||||
- funções
|
- functions
|
||||||
- instruções da VM
|
- VM instructions
|
||||||
|
|
||||||
Breakpoints:
|
Breakpoints:
|
||||||
|
|
||||||
- pausam execução
|
- pause execution
|
||||||
- preservam estado
|
- preserve state
|
||||||
- não alteram comportamento
|
- do not change behavior
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### 9.2 Watchpoints
|
### 9.2 Watchpoints
|
||||||
|
|
||||||
Watchpoints monitoram:
|
Watchpoints monitor:
|
||||||
|
|
||||||
- variáveis
|
- variables
|
||||||
- endereços de heap
|
- heap addresses
|
||||||
- valores específicos
|
- specific values
|
||||||
|
|
||||||
A execução pode pausar quando:
|
Execution can pause when:
|
||||||
|
|
||||||
- um valor muda
|
- a value changes
|
||||||
- um limite é ultrapassado
|
- a limit is exceeded
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 10. Debug de Eventos e Interrupções
|
## 10. Event and Interrupt Debugging
|
||||||
|
|
||||||
PROMETEU permite observar:
|
PROMETEU allows observing:
|
||||||
|
|
||||||
- fila de eventos
|
- event queue
|
||||||
- timers ativos
|
- active timers
|
||||||
- interrupções ocorridas
|
- occurred interrupts
|
||||||
|
|
||||||
Cada evento possui:
|
Each event has:
|
||||||
|
|
||||||
- origem
|
- origin
|
||||||
- frame
|
- frame
|
||||||
- custo
|
- cost
|
||||||
- consequência
|
- consequence
|
||||||
|
|
||||||
Nada acontece “em silêncio”.
|
Nothing happens “silently”.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 11. Integração com CAP e Certificação
|
## 11. Integration with CAP and Certification
|
||||||
|
|
||||||
Todos os dados de debug e profiling:
|
All debug and profiling data:
|
||||||
|
|
||||||
- alimentam o relatório de certificação
|
- feed the certification report
|
||||||
- são coletados de forma determinística
|
- are collected deterministically
|
||||||
- não dependem de ferramentas externas
|
- do not depend on external tools
|
||||||
|
|
||||||
O relatório final é:
|
The final report is:
|
||||||
|
|
||||||
- reproduzível
|
- reproducible
|
||||||
- auditável
|
- auditable
|
||||||
- explicável
|
- explainable
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 12. Uso Pedagógico
|
## 12. Pedagogical Use
|
||||||
|
|
||||||
Este sistema permite ensinar:
|
This system allows teaching:
|
||||||
|
|
||||||
- como debugar sistemas reais
|
- how to debug real systems
|
||||||
- como ler métricas
|
- how to read metrics
|
||||||
- como correlacionar tempo e memória
|
- how to correlate time and memory
|
||||||
- como justificar decisões técnicas
|
- how to justify technical decisions
|
||||||
|
|
||||||
O aluno aprende:
|
The student learns:
|
||||||
|
|
||||||
> debug não é tentativa e erro,
|
> debug is not trial and error,
|
||||||
é observação informada.
|
> it is informed observation.
|
||||||
>
|
>
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 13. Resumo
|
## 13. Summary
|
||||||
|
|
||||||
- debug é parte do sistema
|
- debug is part of the system
|
||||||
- inspeção é completa
|
- inspection is complete
|
||||||
- profiling é determinístico
|
- profiling is deterministic
|
||||||
- tempo e memória são visíveis
|
- time and memory are visible
|
||||||
- certificação é baseada em evidência
|
- certification is evidence-based
|
||||||
|
|
||||||
< [Voltar](chapter-9.md) | [Sumário](table-of-contents.md) | [Adiante](chapter-11.md) >
|
< [Back](chapter-9.md) | [Summary](table-of-contents.md) | [Next](chapter-11.md) >
|
||||||
@ -1,258 +1,258 @@
|
|||||||
< [Voltar](chapter-10.md) | [Sumário](table-of-contents.md) | [Adiante](chapter-12.md) >
|
< [Back](chapter-10.md) | [Summary](table-of-contents.md) | [Next](chapter-12.md) >
|
||||||
|
|
||||||
# 🌍 **Garantias de Portabilidade e Execução Multiplataforma**
|
# 🌍 **Portability Guarantees and Cross-Platform Execution**
|
||||||
|
|
||||||
## 1. Visão Geral
|
## 1. Overview
|
||||||
|
|
||||||
PROMETEU foi projetado desde o início para ser **portável por construção**, não por adaptação posterior.
|
PROMETEU was designed from the beginning to be **portable by construction**, not by later adaptation.
|
||||||
|
|
||||||
Um cartucho PROMETEU:
|
A PROMETEU cartridge:
|
||||||
|
|
||||||
- executa da mesma forma em qualquer plataforma suportada
|
- executes the same way on any supported platform
|
||||||
- produz os mesmos resultados para as mesmas entradas
|
- produces the same results for the same inputs
|
||||||
- mantém comportamento técnico previsível
|
- maintains predictable technical behavior
|
||||||
|
|
||||||
> PROMETEU não depende da plataforma.
|
> PROMETEU does not depend on the platform.
|
||||||
A plataforma depende do PROMETEU.
|
> The platform depends on PROMETEU.
|
||||||
>
|
>
|
||||||
|
|
||||||
Este capítulo define **o contrato de portabilidade** do sistema.
|
This chapter defines the system's **portability contract**.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 2. Princípio Fundamental da Portabilidade
|
## 2. Fundamental Principle of Portability
|
||||||
|
|
||||||
A portabilidade em PROMETEU se baseia em uma regra simples:
|
Portability in PROMETEU is based on a simple rule:
|
||||||
|
|
||||||
> Somente a PROMETEU VM define o comportamento do programa.
|
> Only the PROMETEU VM defines the program's behavior.
|
||||||
>
|
>
|
||||||
|
|
||||||
Isso significa:
|
This means:
|
||||||
|
|
||||||
- linguagens-fonte não importam após compilação
|
- source languages do not matter after compilation
|
||||||
- hardware real não influencia lógica
|
- real hardware does not influence logic
|
||||||
- sistema operacional não altera semântica
|
- the operating system does not change semantics
|
||||||
|
|
||||||
Tudo que não pertence à VM é **adaptação**, não execução.
|
Everything that does not belong to the VM is **adaptation**, not execution.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 3. Separação de Responsabilidades
|
## 3. Separation of Responsibilities
|
||||||
|
|
||||||
PROMETEU separa rigorosamente três camadas:
|
PROMETEU strictly separates three layers:
|
||||||
|
|
||||||
```
|
```
|
||||||
+----------------------------+
|
+----------------------------+
|
||||||
| CARTUCHO |
|
| CARTRIDGE |
|
||||||
| (bytecode + assets) |
|
| (bytecode + assets) |
|
||||||
+-------------+--------------+
|
+-------------+--------------+
|
||||||
|
|
|
|
||||||
+-------------v--------------+
|
+-------------v--------------+
|
||||||
| PROMETEU VM |
|
| PROMETEU VM |
|
||||||
| (lógica, tempo, memória) |
|
| (logic, time, memory) |
|
||||||
+-------------+--------------+
|
+-------------+--------------+
|
||||||
|
|
|
|
||||||
+-------------v--------------+
|
+-------------v--------------+
|
||||||
| CAMADA DE PLATAFORMA |
|
| PLATFORM LAYER |
|
||||||
| janela, áudio,input, FS |
|
| window, audio, input, FS |
|
||||||
+----------------------------+
|
+----------------------------+
|
||||||
```
|
```
|
||||||
|
|
||||||
### O que a VM controla
|
### What the VM controls
|
||||||
|
|
||||||
- execução de bytecode
|
- bytecode execution
|
||||||
- tempo lógico (frames, ciclos)
|
- logical time (frames, cycles)
|
||||||
- memória (stack, heap)
|
- memory (stack, heap)
|
||||||
- determinismo
|
- determinism
|
||||||
- custos e métricas
|
- costs and metrics
|
||||||
|
|
||||||
### O que a plataforma fornece
|
### What the platform provides
|
||||||
|
|
||||||
- exibição de pixels
|
- pixel display
|
||||||
- saída de áudio
|
- audio output
|
||||||
- coleta de input físico
|
- physical input collection
|
||||||
- acesso ao sistema de arquivos sandbox
|
- access to the sandbox file system
|
||||||
|
|
||||||
A plataforma **nunca decide comportamento**.
|
The platform **never decides behavior**.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 4. Determinismo como Base da Portabilidade
|
## 4. Determinism as the Basis of Portability
|
||||||
|
|
||||||
PROMETEU garante determinismo por meio de:
|
PROMETEU guarantees determinism through:
|
||||||
|
|
||||||
- clock lógico fixo (60 Hz)
|
- fixed logical clock (60 Hz)
|
||||||
- ciclos abstratos, não tempo real
|
- abstract cycles, not real time
|
||||||
- input amostrado por frame
|
- input sampled per frame
|
||||||
- ausência de concorrência implícita
|
- absence of implicit concurrency
|
||||||
- ausência de operações dependentes de sistema
|
- absence of system-dependent operations
|
||||||
|
|
||||||
Isso permite afirmar:
|
This allows stating:
|
||||||
|
|
||||||
> “Se o cartucho é o mesmo, o jogo é o mesmo.”
|
> “If the cartridge is the same, the game is the same.”
|
||||||
>
|
>
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 5. Independência de Hardware Real
|
## 5. Independence from Real Hardware
|
||||||
|
|
||||||
PROMETEU **não utiliza**:
|
PROMETEU **does not use**:
|
||||||
|
|
||||||
- timers do sistema operacional
|
- operating system timers
|
||||||
- clocks de alta resolução
|
- high-resolution clocks
|
||||||
- instruções específicas de CPU
|
- CPU-specific instructions
|
||||||
- aceleração gráfica não controlada
|
- uncontrolled graphics acceleration
|
||||||
|
|
||||||
Todo desempenho é medido em **ciclos PROMETEU**, não em milissegundos.
|
All performance is measured in **PROMETEU cycles**, not in milliseconds.
|
||||||
|
|
||||||
O hardware real:
|
The real hardware:
|
||||||
|
|
||||||
- apenas executa a VM
|
- only executes the VM
|
||||||
- nunca interfere na semântica
|
- never interferes with semantics
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 6. Precisão de Ponto Flutuante
|
## 6. Floating Point Precision
|
||||||
|
|
||||||
Para garantir consistência numérica:
|
To guarantee numerical consistency:
|
||||||
|
|
||||||
- PROMETEU define operações matemáticas explícitas
|
- PROMETEU defines explicit mathematical operations
|
||||||
- evita dependência de FPU específica
|
- avoids dependence on specific FPUs
|
||||||
- padroniza comportamento de `number`
|
- standardizes `number` behavior
|
||||||
|
|
||||||
Isso evita:
|
This avoids:
|
||||||
|
|
||||||
- divergências entre arquiteturas
|
- divergences between architectures
|
||||||
- erros acumulativos imprevisíveis
|
- unpredictable cumulative errors
|
||||||
- diferenças sutis entre plataformas
|
- subtle differences between platforms
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 7. Input Multiplataforma
|
## 7. Cross-Platform Input
|
||||||
|
|
||||||
PROMETEU abstrai input físico em **estado lógico**.
|
PROMETEU abstracts physical input into **logical state**.
|
||||||
|
|
||||||
- teclado, gamepad e toque são mapeados externamente
|
- keyboard, gamepad, and touch are mapped externally
|
||||||
- o cartucho só enxerga botões e eixos lógicos
|
- the cartridge only sees logical buttons and axes
|
||||||
- o momento da leitura é fixo por frame
|
- the reading moment is fixed per frame
|
||||||
|
|
||||||
O mesmo cartucho:
|
The same cartridge:
|
||||||
|
|
||||||
- reage da mesma forma em PC, mobile ou console
|
- reacts the same way on PC, mobile, or console
|
||||||
- não contém lógica dependente de dispositivo
|
- does not contain device-dependent logic
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 8. Áudio Multiplataforma
|
## 8. Cross-Platform Audio
|
||||||
|
|
||||||
O sistema de áudio:
|
The audio system:
|
||||||
|
|
||||||
- define canais e mixagem logicamente
|
- defines channels and mixing logically
|
||||||
- usa APIs nativas apenas como saída
|
- uses native APIs only as output
|
||||||
- mantém sincronização por frame
|
- maintains per-frame synchronization
|
||||||
|
|
||||||
Diferenças de hardware:
|
Hardware differences:
|
||||||
|
|
||||||
- não alteram timing lógico
|
- do not change logical timing
|
||||||
- não alteram sequência sonora
|
- do not change sound sequence
|
||||||
- não afetam certificação
|
- do not affect certification
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 9. Gráficos Multiplataforma
|
## 9. Cross-Platform Graphics
|
||||||
|
|
||||||
O sistema gráfico:
|
The graphics system:
|
||||||
|
|
||||||
- opera sobre framebuffer lógico
|
- operates on a logical framebuffer
|
||||||
- usa paleta indexada
|
- uses an indexed palette
|
||||||
- não depende de GPU específica
|
- does not depend on a specific GPU
|
||||||
|
|
||||||
A camada de plataforma:
|
The platform layer:
|
||||||
|
|
||||||
- apenas exibe o framebuffer
|
- only displays the framebuffer
|
||||||
- não reinterpreta comandos gráficos
|
- does not reinterpret graphics commands
|
||||||
|
|
||||||
PROMETEU **não delega decisões gráficas ao hardware**.
|
PROMETEU **does not delegate graphics decisions to the hardware**.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 10. Sistema de Arquivos e Persistência
|
## 10. File System and Persistence
|
||||||
|
|
||||||
PROMETEU define um **filesystem lógico sandbox**:
|
PROMETEU defines a **sandbox logical filesystem**:
|
||||||
|
|
||||||
- caminhos virtuais
|
- virtual paths
|
||||||
- limites de tamanho
|
- size limits
|
||||||
- comportamento determinístico
|
- deterministic behavior
|
||||||
|
|
||||||
A plataforma mapeia esse filesystem para:
|
The platform maps this filesystem to:
|
||||||
|
|
||||||
- disco
|
- disk
|
||||||
- storage móvel
|
- mobile storage
|
||||||
- memória persistente
|
- persistent memory
|
||||||
|
|
||||||
Sem alterar semântica.
|
Without changing semantics.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 11. Certificação e Portabilidade
|
## 11. Certification and Portability
|
||||||
|
|
||||||
A **Certificação PROMETEU** é válida para todas as plataformas.
|
The **PROMETEU Certification** is valid for all platforms.
|
||||||
|
|
||||||
Se um cartucho:
|
If a cartridge:
|
||||||
|
|
||||||
- passa em uma plataforma
|
- passes on one platform
|
||||||
- com as mesmas entradas
|
- with the same inputs
|
||||||
|
|
||||||
Ele:
|
It:
|
||||||
|
|
||||||
- passará em todas
|
- will pass on all
|
||||||
- produzirá os mesmos relatórios
|
- will produce the same reports
|
||||||
|
|
||||||
Isso é possível porque:
|
This is possible because:
|
||||||
|
|
||||||
> a certificação valida a VM, não o ambiente.
|
> the certification validates the VM, not the environment.
|
||||||
>
|
>
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 12. O que PROMETEU NÃO garante
|
## 12. What PROMETEU DOES NOT guarantee
|
||||||
|
|
||||||
PROMETEU **não promete**:
|
PROMETEU **does not promise**:
|
||||||
|
|
||||||
- desempenho absoluto igual (FPS real)
|
- identical absolute performance (real FPS)
|
||||||
- latência física idêntica
|
- identical physical latency
|
||||||
- consumo energético equivalente
|
- equivalent energy consumption
|
||||||
|
|
||||||
PROMETEU promete:
|
PROMETEU promises:
|
||||||
|
|
||||||
- **comportamento lógico idêntico**
|
- **identical logical behavior**
|
||||||
- **decisões técnicas reproduzíveis**
|
- **reproducible technical decisions**
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 13. Implicações Pedagógicas
|
## 13. Pedagogical Implications
|
||||||
|
|
||||||
Este modelo permite ensinar:
|
This model allows teaching:
|
||||||
|
|
||||||
- diferença entre lógica e apresentação
|
- the difference between logic and presentation
|
||||||
- por que engines modernas quebram determinismo
|
- why modern engines break determinism
|
||||||
- como isolar sistemas
|
- how to isolate systems
|
||||||
- como projetar software portável
|
- how to design portable software
|
||||||
|
|
||||||
O aluno aprende:
|
The student learns:
|
||||||
|
|
||||||
> portabilidade não é sorte — é arquitetura.
|
> portability is not luck — it is architecture.
|
||||||
>
|
>
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 14. Resumo
|
## 14. Summary
|
||||||
|
|
||||||
- PROMETEU define comportamento na VM
|
- PROMETEU defines behavior in the VM
|
||||||
- plataformas apenas executam
|
- platforms only execute
|
||||||
- tempo é lógico, não físico
|
- time is logical, not physical
|
||||||
- input, áudio e gráficos são abstraídos
|
- input, audio, and graphics are abstracted
|
||||||
- certificação é universal
|
- certification is universal
|
||||||
- portabilidade é garantida por design
|
- portability is guaranteed by design
|
||||||
|
|
||||||
< [Voltar](chapter-10.md) | [Sumário](table-of-contents.md) | [Adiante](chapter-12.md) >
|
< [Back](chapter-10.md) | [Summary](table-of-contents.md) | [Next](chapter-12.md) >
|
||||||
@ -1,236 +1,236 @@
|
|||||||
< [Voltar](chapter-11.md) | [Sumário](table-of-contents.md) | [Adiante](chapter-13.md) >
|
< [Back](chapter-11.md) | [Summary](table-of-contents.md) | [Next](chapter-13.md) >
|
||||||
|
|
||||||
# 🧠 Firmware — PrometeuOS (POS) + PrometeuHub
|
# 🧠 Firmware — PrometeuOS (POS) + PrometeuHub
|
||||||
|
|
||||||
## 1. Visão Geral
|
## 1. Overview
|
||||||
|
|
||||||
O **Firmware do PROMETEU** é composto por duas camadas:
|
The **PROMETEU Firmware** is composed of two layers:
|
||||||
|
|
||||||
- **PrometeuOS (POS)**: o firmware/base do sistema. É a autoridade máxima do boot, periféricos, execução da PVM e tratamento de falhas.
|
- **PrometeuOS (POS)**: the system firmware/base. It is the maximum authority for boot, peripherals, PVM execution, and fault handling.
|
||||||
- **PrometeuHub**: o “launcher” e ambiente de UI do sistema, embutido no firmware, executado **sobre** o POS e usando o **PROMETEU Window System**.
|
- **PrometeuHub**: the system launcher and UI environment, embedded in the firmware, executed **over** the POS and using the **PROMETEU Window System**.
|
||||||
|
|
||||||
> **Todo cartucho é um App**.
|
> **Every cartridge is an App**.
|
||||||
> A diferença é o **modo do App** (Game ou System), informado no header do cartucho.
|
> The difference is the **App mode** (Game or System), specified in the cartridge header.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 2. Termos e Definições
|
## 2. Terms and Definitions
|
||||||
|
|
||||||
- **Host**: plataforma real (desktop, mobile, console DIY, etc.) que chama o core em 60Hz e exibe o framebuffer.
|
- **Host**: real platform (desktop, mobile, DIY console, etc.) that calls the core at 60Hz and displays the framebuffer.
|
||||||
- **POS (PrometeuOS)**: firmware (core de sistema). Controla boot, PVM, budget, latch de input, periféricos e crash.
|
- **POS (PrometeuOS)**: firmware (system core). Controls boot, PVM, budget, input latch, peripherals, and crash.
|
||||||
- **PrometeuHub**: UI do sistema/launcher rodando sobre POS.
|
- **PrometeuHub**: system UI / launcher running over POS.
|
||||||
- **PVM (PROMETEU Virtual Machine)**: VM que executa bytecode do App.
|
- **PVM (PROMETEU Virtual Machine)**: VM that executes the App's bytecode.
|
||||||
- **App / Cartucho**: pacote executável PROMETEU (ex.: `.pbc`).
|
- **App / Cartridge**: PROMETEU executable package (e.g., `.pbc`).
|
||||||
- **AppMode**: modo do App no header do cartucho:
|
- **AppMode**: App mode in the cartridge header:
|
||||||
- `GAME`: assume tela cheia, UI própria
|
- `GAME`: assumes full screen, own UI
|
||||||
- `SYSTEM`: app integrado ao sistema, deve rodar “em janela” no Hub
|
- `SYSTEM`: app integrated into the system, should run "in a window" in the Hub
|
||||||
- **Frame lógico**: unidade de atualização do App, encerrada por `FRAME_SYNC`.
|
- **Logical frame**: App update unit, terminated by `FRAME_SYNC`.
|
||||||
- **Tick do host**: chamada do host (60Hz real).
|
- **Host tick**: call from the host (real 60Hz).
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 3. Responsabilidades do POS (PrometeuOS)
|
## 3. Responsibilities of the POS (PrometeuOS)
|
||||||
|
|
||||||
O POS deve garantir:
|
The POS must guarantee:
|
||||||
|
|
||||||
### 3.1 Boot e Estados de Sistema
|
### 3.1 Boot and System States
|
||||||
- RESET determinístico (estado conhecido)
|
- Deterministic RESET (known state)
|
||||||
- SPLASH opcional (curto)
|
- Optional SPLASH (short)
|
||||||
- inicialização do PrometeuHub e do Window System
|
- initialization of the PrometeuHub and the Window System
|
||||||
- retorno ao Hub após saída/crash de app
|
- return to the Hub after app exit/crash
|
||||||
|
|
||||||
### 3.2 Controle da PVM
|
### 3.2 PVM Control
|
||||||
- carregar cartucho na PVM
|
- load cartridge into the PVM
|
||||||
- resetar PC/stack/heap ao iniciar app
|
- reset PC/stack/heap upon app start
|
||||||
- executar budget por frame lógico
|
- execute budget per logical frame
|
||||||
- respeitar `FRAME_SYNC` como boundary de frame lógico
|
- respect `FRAME_SYNC` as logical frame boundary
|
||||||
- manter input latched por frame lógico
|
- maintain input latched per logical frame
|
||||||
|
|
||||||
### 3.3 Controle de Periféricos
|
### 3.3 Peripheral Control
|
||||||
- inicialização e reset de:
|
- initialization and reset of:
|
||||||
- GFX / buffers
|
- GFX / buffers
|
||||||
- AUDIO (canais, fila de comandos)
|
- AUDIO (channels, command queue)
|
||||||
- INPUT / TOUCH
|
- INPUT / TOUCH
|
||||||
- política de “safe mode” (ignorar Hub/config se solicitado)
|
- "safe mode" policy (ignore Hub/config if requested)
|
||||||
|
|
||||||
### 3.4 Falhas e Recuperação
|
### 3.4 Failures and Recovery
|
||||||
- capturar faults fatais da PVM
|
- capture fatal PVM faults
|
||||||
- apresentar **POS_CRASH_SCREEN** (fora da PVM)
|
- present **POS_CRASH_SCREEN** (outside the PVM)
|
||||||
- permitir:
|
- allow:
|
||||||
- reiniciar app
|
- app restart
|
||||||
- voltar ao Hub
|
- return to Hub
|
||||||
- reset do sistema
|
- system reset
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 4. Responsabilidades do PrometeuHub
|
## 4. Responsibilities of the PrometeuHub
|
||||||
|
|
||||||
O PrometeuHub deve:
|
The PrometeuHub must:
|
||||||
|
|
||||||
- listar Apps disponíveis no storage
|
- list available Apps in storage
|
||||||
- ler metadata do header do cartucho (incluindo `AppMode`)
|
- read metadata from the cartridge header (including `AppMode`)
|
||||||
- permitir seleção e launch
|
- allow selection and launch
|
||||||
- aplicar tema/UI do sistema via Window System
|
- apply system theme/UI via Window System
|
||||||
- decidir o “comportamento de execução” com base no `AppMode`
|
- decide the "execution behavior" based on the `AppMode`
|
||||||
|
|
||||||
### 4.1 Decisão por `AppMode`
|
### 4.1 Decision by `AppMode`
|
||||||
Ao selecionar um App:
|
When selecting an App:
|
||||||
|
|
||||||
- Se `AppMode = GAME`:
|
- If `AppMode = GAME`:
|
||||||
- o Hub delega ao POS: **executar como jogo** (tela cheia)
|
- the Hub delegates to the POS: **execute as a game** (full screen)
|
||||||
- Se `AppMode = SYSTEM`:
|
- If `AppMode = SYSTEM`:
|
||||||
- o Hub delega ao POS: **carregar o App**
|
- the Hub delegates to the POS: **load the App**
|
||||||
- e o Hub **abre uma janela** e roda o App “integrado ao sistema”
|
- and the Hub **opens a window** and runs the App "integrated into the system"
|
||||||
|
|
||||||
> Observação: o Hub não executa bytecode diretamente; ele sempre delega ao POS.
|
> Note: the Hub does not execute bytecode directly; it always delegates to the POS.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 5. PROMETEU Window System (UI do Sistema)
|
## 5. PROMETEU Window System (System UI)
|
||||||
|
|
||||||
O Window System é parte do firmware (POS + Hub) e oferece:
|
The Window System is part of the firmware (POS + Hub) and offers:
|
||||||
|
|
||||||
- tema global (paleta, fontes, sons de UI)
|
- global theme (palette, fonts, UI sounds)
|
||||||
- sistema de janelas (pelo menos: uma janela ativa + stack de dialogs)
|
- window system (at least: one active window + dialog stack)
|
||||||
- roteamento de input:
|
- input routing:
|
||||||
- foco, navegação, confirmação/cancelamento
|
- focus, navigation, confirmation/cancellation
|
||||||
- touch como “tap” (single pointer)
|
- touch as "tap" (single pointer)
|
||||||
|
|
||||||
### 5.1 Integração de System Apps
|
### 5.1 System App Integration
|
||||||
System Apps são executados em modo “janela” e devem:
|
System Apps are executed in "window" mode and must:
|
||||||
|
|
||||||
- respeitar a área de viewport fornecida pela janela
|
- respect the viewport area provided by the window
|
||||||
- cooperar com foco/inputs do Window System
|
- cooperate with the Window System's focus/inputs
|
||||||
- aceitar ser suspensos/fechados pelo Hub
|
- accept being suspended/closed by the Hub
|
||||||
|
|
||||||
O Hub pode oferecer “chrome” de janela:
|
The Hub can offer window "chrome":
|
||||||
- título
|
- title
|
||||||
- botão voltar/fechar
|
- back/close button
|
||||||
- overlays (toast, dialogs)
|
- overlays (toast, dialogs)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 6. Header do Cartucho (requisito mínimo para o firmware)
|
## 6. Cartridge Header (minimum requirement for the firmware)
|
||||||
|
|
||||||
O firmware exige que todo cartucho forneça no header, no mínimo:
|
The firmware requires every cartridge to provide at least the following in the header:
|
||||||
|
|
||||||
- `magic` / `version`
|
- `magic` / `version`
|
||||||
- `app_id` (string curta ou hash)
|
- `app_id` (short string or hash)
|
||||||
- `title` (string)
|
- `title` (string)
|
||||||
- `entrypoint` (endereço de PC)
|
- `entrypoint` (PC address)
|
||||||
- `app_mode`: `GAME` ou `SYSTEM`
|
- `app_mode`: `GAME` or `SYSTEM`
|
||||||
- (opcional) `icon_id` / `cover_id`
|
- (optional) `icon_id` / `cover_id`
|
||||||
- (opcional) `requested_cap` / versão da VM
|
- (optional) `requested_cap` / VM version
|
||||||
|
|
||||||
O POS/HUB devem usar `app_mode` para decidir execução.
|
The POS/HUB must use `app_mode` to decide on execution.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 7. Estados Oficiais do Boot (Firmware)
|
## 7. Official Boot States (Firmware)
|
||||||
|
|
||||||
### 7.1 POS_RESET
|
### 7.1 POS_RESET
|
||||||
- inicializa periféricos
|
- initializes peripherals
|
||||||
- prepara PVM
|
- prepares PVM
|
||||||
- carrega config
|
- loads config
|
||||||
- detecta safe mode
|
- detects safe mode
|
||||||
|
|
||||||
Transição: `POS_SPLASH` ou `POS_LAUNCH_HUB`
|
Transition: `POS_SPLASH` or `POS_LAUNCH_HUB`
|
||||||
|
|
||||||
### 7.2 POS_SPLASH (opcional)
|
### 7.2 POS_SPLASH (optional)
|
||||||
- exibe logo/versão
|
- displays logo/version
|
||||||
- tempo fixo ou “skip”
|
- fixed time or "skip"
|
||||||
|
|
||||||
Transição: `POS_LAUNCH_HUB`
|
Transition: `POS_LAUNCH_HUB`
|
||||||
|
|
||||||
### 7.3 POS_LAUNCH_HUB
|
### 7.3 POS_LAUNCH_HUB
|
||||||
- inicia Window System
|
- starts Window System
|
||||||
- entra no loop do Hub
|
- enters the Hub loop
|
||||||
|
|
||||||
Transição: `HUB_HOME`
|
Transition: `HUB_HOME`
|
||||||
|
|
||||||
### 7.4 HUB_HOME
|
### 7.4 HUB_HOME
|
||||||
- lista Apps
|
- lists Apps
|
||||||
- permite seleção:
|
- allows selection:
|
||||||
- `GAME` → `POS_RUN_GAME(app)`
|
- `GAME` → `POS_RUN_GAME(app)`
|
||||||
- `SYSTEM` → `HUB_OPEN_WINDOW(app)` (que delega `POS_RUN_SYSTEM(app)`)
|
- `SYSTEM` → `HUB_OPEN_WINDOW(app)` (which delegates `POS_RUN_SYSTEM(app)`)
|
||||||
|
|
||||||
### 7.5 POS_RUN_GAME(app)
|
### 7.5 POS_RUN_GAME(app)
|
||||||
- carrega cartucho na PVM
|
- loads cartridge into the PVM
|
||||||
- executa frame lógico (budget + `FRAME_SYNC`)
|
- executes logical frame (budget + `FRAME_SYNC`)
|
||||||
- apresenta frames
|
- presents frames
|
||||||
- mantém latch por frame lógico
|
- maintains latch per logical frame
|
||||||
|
|
||||||
Saídas:
|
Exits:
|
||||||
- `APP_EXIT` → `POS_LAUNCH_HUB`
|
- `APP_EXIT` → `POS_LAUNCH_HUB`
|
||||||
- `APP_FAULT` → `POS_CRASH_SCREEN`
|
- `APP_FAULT` → `POS_CRASH_SCREEN`
|
||||||
|
|
||||||
### 7.6 POS_RUN_SYSTEM(app)
|
### 7.6 POS_RUN_SYSTEM(app)
|
||||||
- carrega cartucho na PVM (ou instância separada, se suportado no futuro)
|
- loads cartridge into the PVM (or separate instance, if supported in the future)
|
||||||
- executa sob o ciclo do Hub/Window System
|
- executes under the Hub/Window System cycle
|
||||||
- apresenta na área da janela (viewport)
|
- presents in the window area (viewport)
|
||||||
|
|
||||||
Saídas:
|
Exits:
|
||||||
- `APP_EXIT` → retorna ao Hub
|
- `APP_EXIT` → returns to the Hub
|
||||||
- `APP_FAULT` → `POS_CRASH_SCREEN` (ou crash window + fallback)
|
- `APP_FAULT` → `POS_CRASH_SCREEN` (or crash window + fallback)
|
||||||
|
|
||||||
### 7.7 POS_CRASH_SCREEN
|
### 7.7 POS_CRASH_SCREEN
|
||||||
- exibe erro (tipo, PC, stack trace)
|
- displays error (type, PC, stack trace)
|
||||||
- ações: restart app / hub / reset
|
- actions: restart app / hub / reset
|
||||||
|
|
||||||
Transição: conforme escolha.
|
Transition: as chosen.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 8. Modelo de Execução (Budget, Latch e `FRAME_SYNC`)
|
## 8. Execution Model (Budget, Latch, and `FRAME_SYNC`)
|
||||||
|
|
||||||
O POS é responsável por garantir:
|
The POS is responsible for guaranteeing:
|
||||||
|
|
||||||
- **Input latched por frame lógico**
|
- **Input latched per logical frame**
|
||||||
- execução em fatias (ticks do host) até o app alcançar `FRAME_SYNC`
|
- execution in slices (host ticks) until the app reaches `FRAME_SYNC`
|
||||||
- apenas em `FRAME_SYNC`:
|
- only at `FRAME_SYNC`:
|
||||||
- `present()` (ou compose+present)
|
- `present()` (or compose+present)
|
||||||
- avança `logical_frame_index`
|
- advances `logical_frame_index`
|
||||||
- libera latch de input
|
- releases input latch
|
||||||
- reseta budget do próximo frame lógico
|
- resets the budget for the next logical frame
|
||||||
|
|
||||||
Se o budget acabar antes do `FRAME_SYNC`:
|
If the budget runs out before `FRAME_SYNC`:
|
||||||
- não apresenta
|
- does not present
|
||||||
- mantém latch
|
- maintains latch
|
||||||
- continua a execução no próximo tick do host no mesmo frame lógico
|
- execution continues in the next host tick within the same logical frame
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 9. Regras de Retorno ao Hub
|
## 9. Rules for Returning to the Hub
|
||||||
|
|
||||||
O firmware deve oferecer um mecanismo de “voltar ao sistema”:
|
The firmware must offer a "return to system" mechanism:
|
||||||
|
|
||||||
- atalho de botão (ex.: START+SELECT por X ticks)
|
- button shortcut (e.g., START+SELECT for X ticks)
|
||||||
- ou syscall controlada (apenas System Apps)
|
- or controlled syscall (System Apps only)
|
||||||
|
|
||||||
Ao retornar ao Hub:
|
Upon returning to the Hub:
|
||||||
- o POS encerra ou suspende o App atual
|
- the POS terminates or suspends the current App
|
||||||
- retorna ao Window System com estado consistente
|
- returns to the Window System with a consistent state
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 10. Objetivos Pedagógicos
|
## 10. Pedagogical Objectives
|
||||||
|
|
||||||
Este firmware permite ensinar:
|
This firmware allows teaching:
|
||||||
|
|
||||||
- boot stages e firmware como autoridade
|
- boot stages and firmware as an authority
|
||||||
- separação entre sistema e aplicação
|
- separation between system and application
|
||||||
- execução determinística com budget e frame lógico
|
- deterministic execution with budget and logical frame
|
||||||
- diferença entre apps (Game vs System)
|
- difference between apps (Game vs System)
|
||||||
- tolerância a falhas e crash handling realista
|
- fault tolerance and realistic crash handling
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 11. Resumo
|
## 11. Summary
|
||||||
|
|
||||||
- POS é a camada base e controla PVM, budget, latch, periféricos e crash.
|
- POS is the base layer and controls the PVM, budget, latch, peripherals, and crash.
|
||||||
- PrometeuHub é o launcher/UI embutido do firmware sobre o POS.
|
- PrometeuHub is the embedded firmware launcher/UI over the POS.
|
||||||
- Todo cartucho é um App; o header define `app_mode` (GAME/SYSTEM).
|
- Every cartridge is an App; the header defines the `app_mode` (GAME/SYSTEM).
|
||||||
- `GAME` roda tela cheia; `SYSTEM` roda integrado ao Hub em janela.
|
- `GAME` runs in full screen; `SYSTEM` runs integrated into the Hub in a window.
|
||||||
- `FRAME_SYNC` é o boundary do frame lógico.
|
- `FRAME_SYNC` is the logical frame boundary.
|
||||||
|
|
||||||
< [Voltar](chapter-11.md) | [Sumário](table-of-contents.md) | [Adiante](chapter-13.md) >
|
< [Back](chapter-11.md) | [Summary](table-of-contents.md) | [Next](chapter-13.md) >
|
||||||
@ -1,35 +1,35 @@
|
|||||||
< [Voltar](chapter-12.md) | [Sumário](table-of-contents.md) | [Adiante](chapter-14.md) >
|
< [Back](chapter-12.md) | [Summary](table-of-contents.md) | [Next](chapter-14.md) >
|
||||||
|
|
||||||
# Cartuchos
|
# Cartridges
|
||||||
|
|
||||||
**Versão:** 1.0 (baseline estável)
|
**Version:** 1.0 (stable baseline)
|
||||||
**Status:** Proposta
|
**Status:** Proposal
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 1. Objetivo
|
## 1. Objective
|
||||||
|
|
||||||
Definir um contrato mínimo e estável para cartuchos Prometeu, permitindo:
|
Define a minimum and stable contract for Prometeu cartridges, allowing:
|
||||||
|
|
||||||
* Identificação do app
|
* App identification
|
||||||
* Seleção de modo (Game/System)
|
* Mode selection (Game/System)
|
||||||
* Resolução de entrypoint
|
* Entrypoint resolution
|
||||||
* Carregamento previsível pelo runtime
|
* Predictable loading by the runtime
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 2. Conceito
|
## 2. Concept
|
||||||
|
|
||||||
Um cartucho é a unidade distribuível do Prometeu. Ele pode existir como:
|
A cartridge is the distributable unit of Prometeu. It can exist as:
|
||||||
|
|
||||||
* **Diretório (dev)** — ideal para desenvolvimento e hot-reload
|
* **Directory (dev)** — ideal for development and hot-reload
|
||||||
* **Arquivo empacotado (.pmc)** — ideal para distribuição
|
* **Packaged file (.pmc)** — ideal for distribution
|
||||||
|
|
||||||
Ambos compartilham o mesmo layout lógico.
|
Both share the same logical layout.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 3. Layout Lógico
|
## 3. Logical Layout
|
||||||
|
|
||||||
```
|
```
|
||||||
<cartridge>/
|
<cartridge>/
|
||||||
@ -39,72 +39,72 @@ Ambos compartilham o mesmo layout lógico.
|
|||||||
└── ...
|
└── ...
|
||||||
```
|
```
|
||||||
|
|
||||||
Campos obrigatórios:
|
Required fields:
|
||||||
|
|
||||||
* `manifest.json`
|
* `manifest.json`
|
||||||
* `program.pbc` (bytecode Prometeu)
|
* `program.pbc` (Prometeu bytecode)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 4. manifest.json (Contrato v1)
|
## 4. manifest.json (Contract v1)
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"magic": "PMTU",
|
"magic": "PMTU",
|
||||||
"cartridge_version": 1,
|
"cartridge_version": 1,
|
||||||
"app_id": 1234,
|
"app_id": 1234,
|
||||||
"title": "Meu Jogo",
|
"title": "My Game",
|
||||||
"app_version": "1.0.0",
|
"app_version": "1.0.0",
|
||||||
"app_mode": "Game", // Game | System
|
"app_mode": "Game",
|
||||||
"entrypoint": "main"
|
"entrypoint": "main"
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### Campos
|
### Fields
|
||||||
|
|
||||||
* `magic`: string fixa `PMTU`
|
* `magic`: fixed string `PMTU`
|
||||||
* `cartridge_version`: versão do formato
|
* `cartridge_version`: format version
|
||||||
* `app_id`: identificador numérico único
|
* `app_id`: unique numerical identifier
|
||||||
* `title`: nome do app
|
* `title`: name of the app
|
||||||
* `app_version`: versão do app
|
* `app_version`: app version
|
||||||
* `app_mode`: `Game` ou `System`
|
* `app_mode`: `Game` or `System`
|
||||||
* `entrypoint`: símbolo ou índice reconhecido pela VM
|
* `entrypoint`: symbol or index recognized by the VM
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 5. Regras do Runtime
|
## 5. Runtime Rules
|
||||||
|
|
||||||
* Validar `magic` e `cartridge_version`
|
* Validate `magic` and `cartridge_version`
|
||||||
* Ler `app_mode` para decidir fluxo de execução
|
* Read `app_mode` to decide execution flow
|
||||||
* Resolver `entrypoint` no `program.pbc`
|
* Resolve `entrypoint` in `program.pbc`
|
||||||
* Ignorar `assets/` se não suportado ainda
|
* Ignore `assets/` if not supported yet
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 6. Modos de Uso
|
## 6. Usage Modes
|
||||||
|
|
||||||
### Diretório (desenvolvimento)
|
### Directory (development)
|
||||||
|
|
||||||
```
|
```
|
||||||
prometeu --run ./mycart/
|
prometeu --run ./mycart/
|
||||||
```
|
```
|
||||||
|
|
||||||
### Arquivo empacotado
|
### Packaged file
|
||||||
|
|
||||||
```
|
```
|
||||||
prometeu --run mygame.pmc
|
prometeu --run mygame.pmc
|
||||||
```
|
```
|
||||||
|
|
||||||
Ambos devem se comportar de forma idêntica no runtime.
|
Both must behave identically in the runtime.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 7. Estabilidade do Contrato
|
## 7. Contract Stability
|
||||||
|
|
||||||
A partir do v1:
|
From v1 onwards:
|
||||||
|
|
||||||
* `manifest.json` é a fonte de verdade
|
* `manifest.json` is the source of truth
|
||||||
* Campos só podem ser adicionados de forma backward-compatible
|
* Fields can only be added in a backward-compatible manner
|
||||||
* Mudanças incompatíveis exigem `cartridge_version` novo
|
* Incompatible changes require a new `cartridge_version`
|
||||||
|
|
||||||
< [Voltar](chapter-12.md) | [Sumário](table-of-contents.md) | [Adiante](chapter-14.md) >
|
< [Back](chapter-12.md) | [Summary](table-of-contents.md) | [Next](chapter-14.md) >
|
||||||
@ -1,25 +1,25 @@
|
|||||||
< [Voltar](chapter-13.md) | [Sumário](table-of-contents.md) >
|
< [Back](chapter-13.md) | [Summary](table-of-contents.md) >
|
||||||
|
|
||||||
# Boot Profiles
|
# Boot Profiles
|
||||||
|
|
||||||
**Versão:** 1.0
|
**Version:** 1.0
|
||||||
**Status:** Proposta
|
**Status:** Proposal
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 1. Objetivo
|
## 1. Objective
|
||||||
|
|
||||||
Definir como o Prometeu decide o que executar ao iniciar:
|
Define how Prometeu decides what to execute at startup:
|
||||||
|
|
||||||
* Hub
|
* Hub
|
||||||
* Cartucho automaticamente
|
* Automatic cartridge
|
||||||
* Modo debug
|
* Debug mode
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 2. Conceito de BootTarget
|
## 2. BootTarget Concept
|
||||||
|
|
||||||
No início do boot, o POS resolve um alvo:
|
At the beginning of boot, the POS resolves a target:
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
enum BootTarget {
|
enum BootTarget {
|
||||||
@ -30,106 +30,106 @@ enum BootTarget {
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 3. Regras Gerais
|
## 3. General Rules
|
||||||
|
|
||||||
### Se BootTarget == Hub
|
### If BootTarget == Hub
|
||||||
|
|
||||||
* Firmware entra em `HubHome`
|
* Firmware enters `HubHome`
|
||||||
* Nenhum cartucho é carregado automaticamente
|
* No cartridge is automatically loaded
|
||||||
|
|
||||||
### Se BootTarget == Cartridge
|
### If BootTarget == Cartridge
|
||||||
|
|
||||||
1. Carregar cartucho
|
1. Load cartridge
|
||||||
2. Ler `app_mode` no manifest
|
2. Read `app_mode` in the manifest
|
||||||
3. Aplicar regras:
|
3. Apply rules:
|
||||||
|
|
||||||
* `Game`:
|
* `Game`:
|
||||||
|
|
||||||
* Entrar em `RunningGame`
|
* Enter `RunningGame`
|
||||||
* `System`:
|
* `System`:
|
||||||
|
|
||||||
* Permanecer em `HubHome`
|
* Stay in `HubHome`
|
||||||
* Abrir o app como janela/system tool
|
* Open the app as a window/system tool
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 4. CLI do Host
|
## 4. Host CLI
|
||||||
|
|
||||||
### Boot padrão
|
### Default boot
|
||||||
|
|
||||||
```
|
```
|
||||||
prometeu
|
prometeu
|
||||||
```
|
```
|
||||||
|
|
||||||
Resultado: entra no Hub
|
Result: enters the Hub
|
||||||
|
|
||||||
### Executar cartucho
|
### Run cartridge
|
||||||
|
|
||||||
```
|
```
|
||||||
prometeu run <cartucho>
|
prometeu run <cartridge>
|
||||||
```
|
```
|
||||||
|
|
||||||
Resultado:
|
Result:
|
||||||
|
|
||||||
* Game → entra direto no jogo
|
* Game → enters directly into the game
|
||||||
* System → abre como tool no Hub
|
* System → opens as a tool in the Hub
|
||||||
|
|
||||||
### Executar com debugger
|
### Run with debugger
|
||||||
|
|
||||||
```
|
```
|
||||||
prometeu debug <cartucho>
|
prometeu debug <cartridge>
|
||||||
```
|
```
|
||||||
|
|
||||||
Resultado:
|
Result:
|
||||||
|
|
||||||
* Mesmo fluxo do `run`
|
* Same flow as `run`
|
||||||
* Runtime inicia em modo debug
|
* Runtime starts in debug mode
|
||||||
* Aguarda conexão do Debugger Java
|
* Waits for connection from the Java Debugger
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 5. Estados do Firmware
|
## 5. Firmware States
|
||||||
|
|
||||||
Firmware mantém apenas:
|
Firmware maintains only:
|
||||||
|
|
||||||
* `Boot`
|
* `Boot`
|
||||||
* `HubHome`
|
* `HubHome`
|
||||||
* `RunningGame`
|
* `RunningGame`
|
||||||
* `AppCrashed`
|
* `AppCrashed`
|
||||||
|
|
||||||
System apps nunca mudam o estado do firmware.
|
System apps never change the firmware state.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 6. Comportamento em Hardware Real (futuro)
|
## 6. Behavior on Real Hardware (future)
|
||||||
|
|
||||||
* Se miniSD/cartucho físico presente no boot:
|
* If miniSD/physical cartridge is present at boot:
|
||||||
|
|
||||||
* POS pode:
|
* POS can:
|
||||||
|
|
||||||
* sempre ir ao Hub, ou
|
* always go to the Hub, or
|
||||||
* auto-executar conforme configuração do usuário
|
* auto-execute according to user configuration
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 7. Integração com Debugger
|
## 7. Integration with Debugger
|
||||||
|
|
||||||
Quando `debug == true`:
|
When `debug == true`:
|
||||||
|
|
||||||
* Runtime:
|
* Runtime:
|
||||||
|
|
||||||
* Inicializa
|
* Initializes
|
||||||
* Abre socket DevTools
|
* Opens DevTools socket
|
||||||
* Aguarda comando `start`
|
* Waits for `start` command
|
||||||
* Somente após isso inicia execução do cartucho
|
* Only after that does it start cartridge execution
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 8. Estabilidade
|
## 8. Stability
|
||||||
|
|
||||||
* BootTarget é contrato interno do POS
|
* BootTarget is an internal POS contract
|
||||||
* CLI do host deve respeitar essas regras
|
* Host CLI must respect these rules
|
||||||
* Novos modos de boot devem ser extensões compatíveis
|
* New boot modes must be compatible extensions
|
||||||
|
|
||||||
|
|
||||||
< [Voltar](chapter-13.md) | [Sumário](table-of-contents.md) >
|
< [Back](chapter-13.md) | [Summary](table-of-contents.md) >
|
||||||
|
|||||||
@ -1,87 +1,87 @@
|
|||||||
< [Voltar](chapter-1.md) | [Sumário](table-of-contents.md) | [Adiante](chapter-3.md) >
|
< [Back](chapter-1.md) | [Summary](table-of-contents.md) | [Next](chapter-3.md) >
|
||||||
|
|
||||||
# ⚙️ ** PVM (PROMETEU VM) — Instruction Set**
|
# ⚙️ ** PVM (PROMETEU VM) — Instruction Set**
|
||||||
|
|
||||||
## 1. Visão Geral
|
## 1. Overview
|
||||||
|
|
||||||
A **PROMETEU VM** é uma máquina virtual obrigatória e sempre presente no hardware lógico:
|
The **PROMETEU VM** is a mandatory virtual machine always present in the logical hardware:
|
||||||
|
|
||||||
* **stack-based**
|
* **stack-based**
|
||||||
* determinística
|
* deterministic
|
||||||
* orientada a ciclos
|
* cycle-oriented
|
||||||
* projetada para ensino e inspeção
|
* designed for teaching and inspection
|
||||||
|
|
||||||
Ela existe para:
|
It exists to:
|
||||||
|
|
||||||
* mapear conceitos de linguagens de alto nível
|
* map high-level language concepts
|
||||||
* tornar custo computacional visível
|
* make computational cost visible
|
||||||
* permitir análise de execução
|
* allow execution analysis
|
||||||
* servir como base do cartucho PROMETEU
|
* serve as the foundation of the PROMETEU cartridge
|
||||||
|
|
||||||
> A PROMETEU VM é simples por escolha.
|
> The PROMETEU VM is simple by choice.
|
||||||
> Simplicidade é uma ferramenta pedagógica.
|
> Simplicity is a pedagogical tool.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 2. Modelo de Execução
|
## 2. Execution Model
|
||||||
|
|
||||||
### 2.1 Componentes Principais
|
### 2.1 Main Components
|
||||||
|
|
||||||
A VM possui:
|
The VM has:
|
||||||
|
|
||||||
* **PC (Program Counter)** — próxima instrução
|
* **PC (Program Counter)** — next instruction
|
||||||
* **Operand Stack** — pilha de valores
|
* **Operand Stack** — value stack
|
||||||
* **Call Stack** — pilha de frames
|
* **Call Stack** — frame stack
|
||||||
* **Heap** — memória dinâmica
|
* **Heap** — dynamic memory
|
||||||
* **Globals** — variáveis globais
|
* **Globals** — global variables
|
||||||
* **Constant Pool** — literais e referências
|
* **Constant Pool** — literals and references
|
||||||
* **ROM** — bytecode do cartucho
|
* **ROM** — cartridge bytecode
|
||||||
* **RAM** — dados mutáveis
|
* **RAM** — mutable data
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### 2.2 Ciclo de Execução
|
### 2.2 Execution Cycle
|
||||||
|
|
||||||
Cada instrução executa:
|
Each instruction executes:
|
||||||
|
|
||||||
```
|
```
|
||||||
FETCH → DECODE → EXECUTE → ADVANCE PC
|
FETCH → DECODE → EXECUTE → ADVANCE PC
|
||||||
```
|
```
|
||||||
|
|
||||||
Propriedades:
|
Properties:
|
||||||
|
|
||||||
* toda instrução tem custo fixo em ciclos
|
* every instruction has a fixed cost in cycles
|
||||||
* não há trabalho implícito invisível
|
* there is no invisible implicit work
|
||||||
* execução é totalmente determinística
|
* execution is fully deterministic
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 3. Tipos Fundamentais
|
## 3. Fundamental Types
|
||||||
|
|
||||||
| Tipo | Descrição |
|
| Type | Description |
|
||||||
| --------- | ----------------------- |
|
| --------- | ------------------------- |
|
||||||
| `integer` | inteiro 64-bit (signed) |
|
| `integer` | 64-bit signed integer |
|
||||||
| `float` | ponto flutuante 64-bit |
|
| `float` | 64-bit floating point |
|
||||||
| `boolean` | verdadeiro/falso |
|
| `boolean` | true/false |
|
||||||
| `string` | UTF-8 imutável |
|
| `string` | immutable UTF-8 |
|
||||||
| `null` | ausência de valor |
|
| `null` | absence of value |
|
||||||
| `ref` | referência ao heap |
|
| `ref` | heap reference |
|
||||||
|
|
||||||
Não existem:
|
Do not exist:
|
||||||
|
|
||||||
* coerções mágicas
|
* magic coercions
|
||||||
* casts implícitos
|
* implicit casts
|
||||||
* overflows silenciosos
|
* silent overflows
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 4. Convenções da Pilha
|
## 4. Stack Conventions
|
||||||
|
|
||||||
* Operações usam o topo da pilha
|
* Operations use the top of the stack
|
||||||
* Resultado sempre volta para a pilha
|
* Results always return to the stack
|
||||||
* Último empilhado = primeiro consumido
|
* Last pushed = first consumed
|
||||||
|
|
||||||
Exemplo:
|
Example:
|
||||||
|
|
||||||
```
|
```
|
||||||
PUSH_CONST 3
|
PUSH_CONST 3
|
||||||
@ -89,7 +89,7 @@ PUSH_CONST 4
|
|||||||
ADD
|
ADD
|
||||||
```
|
```
|
||||||
|
|
||||||
Estado:
|
State:
|
||||||
|
|
||||||
```
|
```
|
||||||
[3]
|
[3]
|
||||||
@ -99,47 +99,47 @@ Estado:
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 5. Categorias de Instruções
|
## 5. Instruction Categories
|
||||||
|
|
||||||
1. Controle de fluxo
|
1. Flow control
|
||||||
2. Pilha
|
2. Stack
|
||||||
3. Aritmética e lógica
|
3. Arithmetic and logic
|
||||||
4. Variáveis
|
4. Variables
|
||||||
5. Funções
|
5. Functions
|
||||||
6. Heap e estruturas
|
6. Heap and structures
|
||||||
7. Periféricos (syscalls)
|
7. Peripherals (syscalls)
|
||||||
8. Sistema
|
8. System
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 6. Instruções — VM Set 1
|
## 6. Instructions — VM Set 1
|
||||||
|
|
||||||
### 6.1 Controle de Execução
|
### 6.1 Execution Control
|
||||||
|
|
||||||
| Instrução | Ciclos | Descrição |
|
| Instruction | Cycles | Description |
|
||||||
| ------------------- | ------ | ----------------------- |
|
| ------------------- | ------ | ------------------------- |
|
||||||
| `NOP` | 1 | Não faz nada |
|
| `NOP` | 1 | Does nothing |
|
||||||
| `HALT` | 1 | Encerra execução |
|
| `HALT` | 1 | Terminates execution |
|
||||||
| `JMP addr` | 2 | Salto incondicional |
|
| `JMP addr` | 2 | Unconditional jump |
|
||||||
| `JMP_IF_FALSE addr` | 3 | Salta se topo for falso |
|
| `JMP_IF_FALSE addr` | 3 | Jumps if top is false |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### 6.2 Pilha
|
### 6.2 Stack
|
||||||
|
|
||||||
| Instrução | Ciclos | Descrição |
|
| Instruction | Cycles | Description |
|
||||||
| -------------- | ------ | ----------------- |
|
| -------------- | ------ | ------------------- |
|
||||||
| `PUSH_CONST k` | 2 | Empilha constante |
|
| `PUSH_CONST k` | 2 | Pushes constant |
|
||||||
| `POP` | 1 | Remove topo |
|
| `POP` | 1 | Removes top |
|
||||||
| `DUP` | 1 | Duplica topo |
|
| `DUP` | 1 | Duplicates top |
|
||||||
| `SWAP` | 1 | Troca dois topos |
|
| `SWAP` | 1 | Swaps two tops |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### 6.3 Aritmética
|
### 6.3 Arithmetic
|
||||||
|
|
||||||
| Instrução | Ciclos |
|
| Instruction | Cycles |
|
||||||
| --------- | ------ |
|
| ----------- | ------ |
|
||||||
| `ADD` | 2 |
|
| `ADD` | 2 |
|
||||||
| `SUB` | 2 |
|
| `SUB` | 2 |
|
||||||
| `MUL` | 4 |
|
| `MUL` | 4 |
|
||||||
@ -147,10 +147,10 @@ Estado:
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### 6.4 Comparação e Lógica
|
### 6.4 Comparison and Logic
|
||||||
|
|
||||||
| Instrução | Ciclos |
|
| Instruction | Cycles |
|
||||||
| --------- | ------ |
|
| ----------- | ------ |
|
||||||
| `EQ` | 2 |
|
| `EQ` | 2 |
|
||||||
| `NEQ` | 2 |
|
| `NEQ` | 2 |
|
||||||
| `LT` | 2 |
|
| `LT` | 2 |
|
||||||
@ -161,53 +161,53 @@ Estado:
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### 6.5 Variáveis
|
### 6.5 Variables
|
||||||
|
|
||||||
| Instrução | Ciclos | Descrição |
|
| Instruction | Cycles | Description |
|
||||||
| -------------- | ------ | -------------- |
|
| -------------- | ------ | ---------------- |
|
||||||
| `GET_GLOBAL i` | 3 | Lê global |
|
| `GET_GLOBAL i` | 3 | Reads global |
|
||||||
| `SET_GLOBAL i` | 3 | Escreve global |
|
| `SET_GLOBAL i` | 3 | Writes global |
|
||||||
| `GET_LOCAL i` | 2 | Lê local |
|
| `GET_LOCAL i` | 2 | Reads local |
|
||||||
| `SET_LOCAL i` | 2 | Escreve local |
|
| `SET_LOCAL i` | 2 | Writes local |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### 6.6 Funções
|
### 6.6 Functions
|
||||||
|
|
||||||
| Instrução | Ciclos | Descrição |
|
| Instruction | Cycles | Description |
|
||||||
|----------------| ------ |---------------------------------|
|
|----------------| ------ |---------------------------------|
|
||||||
| `CALL addr` | 5 | Chamada |
|
| `CALL addr` | 5 | Call |
|
||||||
| `RET` | 4 | Retorno |
|
| `RET` | 4 | Return |
|
||||||
| `PUSH_SCOPE n` | 3 | Cria escopo (frame de execução) |
|
| `PUSH_SCOPE n` | 3 | Creates scope (execution frame) |
|
||||||
| `POP_SCOPE` | 3 | Remove escopo |
|
| `POP_SCOPE` | 3 | Removes scope |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### 6.7 Heap
|
### 6.7 Heap
|
||||||
|
|
||||||
| Instrução | Ciclos | Descrição |
|
| Instruction | Cycles | Description |
|
||||||
| --------------- | ------ | ------------- |
|
| --------------- | ------ | --------------- |
|
||||||
| `ALLOC size` | 10 | Aloca no heap |
|
| `ALLOC size` | 10 | Allocates on heap |
|
||||||
| `LOAD_REF off` | 3 | Lê campo |
|
| `LOAD_REF off` | 3 | Reads field |
|
||||||
| `STORE_REF off` | 3 | Escreve campo |
|
| `STORE_REF off` | 3 | Writes field |
|
||||||
|
|
||||||
Heap é:
|
Heap is:
|
||||||
|
|
||||||
* finito
|
* finite
|
||||||
* monitorado
|
* monitored
|
||||||
* contabilizado no CAP
|
* accounted for in the CAP
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### 6.8 Periféricos (Syscalls)
|
### 6.8 Peripherals (Syscalls)
|
||||||
|
|
||||||
| Instrução | Ciclos | Descrição |
|
| Instruction | Cycles | Description |
|
||||||
|--------------| -------- | ------------------- |
|
|--------------| -------- | --------------------- |
|
||||||
| `SYSCALL id` | variável | Chamada ao hardware |
|
| `SYSCALL id` | variable | Call to hardware |
|
||||||
|
|
||||||
#### Syscalls Implementadas (v0.1)
|
#### Implemented Syscalls (v0.1)
|
||||||
|
|
||||||
| ID | Nome | Argumentos (Pilha) | Retorno |
|
| ID | Name | Arguments (Stack) | Return |
|
||||||
| ---------- | ----------------- | ---------------------------- | ------- |
|
| ---------- | ----------------- | ---------------------------- | ------- |
|
||||||
| `0x0001` | `system.has_cart` | - | `bool` |
|
| `0x0001` | `system.has_cart` | - | `bool` |
|
||||||
| `0x0002` | `system.run_cart` | - | - |
|
| `0x0002` | `system.run_cart` | - | - |
|
||||||
@ -216,7 +216,7 @@ Heap é:
|
|||||||
| `0x2001` | `input.get_pad` | `button_id` | `bool` |
|
| `0x2001` | `input.get_pad` | `button_id` | `bool` |
|
||||||
| `0x3001` | `audio.play` | `s_id, v_id, vol, pan, pitch`| - |
|
| `0x3001` | `audio.play` | `s_id, v_id, vol, pan, pitch`| - |
|
||||||
|
|
||||||
**IDs de Botões:**
|
**Button IDs:**
|
||||||
- `0`: Up, `1`: Down, `2`: Left, `3`: Right
|
- `0`: Up, `1`: Down, `2`: Left, `3`: Right
|
||||||
- `4`: A, `5`: B, `6`: X, `7`: Y
|
- `4`: A, `5`: B, `6`: X, `7`: Y
|
||||||
- `8`: L, `9`: R
|
- `8`: L, `9`: R
|
||||||
@ -224,57 +224,57 @@ Heap é:
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 7. Erros de Execução
|
## 7. Execution Errors
|
||||||
|
|
||||||
Erros são:
|
Errors are:
|
||||||
|
|
||||||
* explícitos
|
* explicit
|
||||||
* fatais
|
* fatal
|
||||||
* nunca silenciosos
|
* never silent
|
||||||
|
|
||||||
Tipos:
|
Types:
|
||||||
|
|
||||||
* stack underflow
|
* stack underflow
|
||||||
* tipo inválido
|
* invalid type
|
||||||
* heap inválido
|
* invalid heap
|
||||||
* frame inválido
|
* invalid frame
|
||||||
|
|
||||||
Geram:
|
Generate:
|
||||||
|
|
||||||
* mensagem clara
|
* clear message
|
||||||
* dump de estado
|
* state dump
|
||||||
* stack trace
|
* stack trace
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 8. Determinismo
|
## 8. Determinism
|
||||||
|
|
||||||
Garantias:
|
Guarantees:
|
||||||
|
|
||||||
* mesma entrada → mesmo resultado
|
* same input → same result
|
||||||
* mesma sequência → mesmos ciclos
|
* same sequence → same cycles
|
||||||
* sem execução especulativa
|
* no speculative execution
|
||||||
* sem otimizações invisíveis
|
* no invisible optimizations
|
||||||
|
|
||||||
> Se você vê a instrução, você paga por ela.
|
> If you see the instruction, you pay for it.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 9. Relação com Linguagens
|
## 9. Relationship with Languages
|
||||||
|
|
||||||
Java, TypeScript, Lua etc:
|
Java, TypeScript, Lua etc:
|
||||||
|
|
||||||
* são linguagens-fonte
|
* are source languages
|
||||||
* compiladas para esse bytecode
|
* compiled to this bytecode
|
||||||
* nunca executadas diretamente
|
* never executed directly
|
||||||
|
|
||||||
Todas rodam na **mesma VM**.
|
All run on the **same VM**.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 10. Exemplo
|
## 10. Example
|
||||||
|
|
||||||
Fonte:
|
Source:
|
||||||
|
|
||||||
```java
|
```java
|
||||||
x = 3 + 4;
|
x = 3 + 4;
|
||||||
@ -289,107 +289,107 @@ ADD
|
|||||||
SET_GLOBAL 0
|
SET_GLOBAL 0
|
||||||
```
|
```
|
||||||
|
|
||||||
Custo:
|
Cost:
|
||||||
|
|
||||||
```
|
```
|
||||||
2 + 2 + 2 + 3 = 9 ciclos
|
2 + 2 + 2 + 3 = 9 cycles
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 11. Execução por Tick
|
## 11. Execution per Tick
|
||||||
|
|
||||||
A VM não roda infinitamente.
|
The VM does not run infinitely.
|
||||||
|
|
||||||
Ela executa:
|
It executes:
|
||||||
|
|
||||||
* até consumir o budget do **frame lógico**
|
* until consuming the **logical frame** budget
|
||||||
* ou até `HALT`
|
* or until `HALT`
|
||||||
|
|
||||||
O budget é definido pelo hardware lógico do PROMETEU (ex.: `CYCLES_PER_FRAME`).
|
The budget is defined by the PROMETEU logical hardware (e.g., `CYCLES_PER_FRAME`).
|
||||||
|
|
||||||
Exemplo:
|
Example:
|
||||||
|
|
||||||
```
|
```
|
||||||
vm.step_budget(10_000)
|
vm.step_budget(10_000)
|
||||||
```
|
```
|
||||||
|
|
||||||
Isso alimenta:
|
This feeds:
|
||||||
|
|
||||||
* CAP
|
* CAP
|
||||||
* profiling
|
* profiling
|
||||||
* certificação
|
* certification
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 12. Frame Lógico e `FRAME_SYNC`
|
## 12. Logical Frame and `FRAME_SYNC`
|
||||||
|
|
||||||
O PROMETEU define **frame lógico** como a unidade mínima de atualização consistente do jogo.
|
PROMETEU defines **logical frame** as the minimum unit of consistent game update.
|
||||||
|
|
||||||
* **Input é latched por frame lógico** (não muda enquanto o frame lógico não for concluído).
|
* **Input is latched per logical frame** (does not change until the logical frame is completed).
|
||||||
* O **budget de ciclos** é aplicado ao frame lógico.
|
* The **cycle budget** is applied to the logical frame.
|
||||||
* Um novo frame lógico só começa quando o frame atual termina.
|
* A new logical frame only starts when the current frame ends.
|
||||||
|
|
||||||
### 12.1 Instrução de Sistema: `FRAME_SYNC`
|
### 12.1 System Instruction: `FRAME_SYNC`
|
||||||
|
|
||||||
A instrução `FRAME_SYNC` marca o **fim do frame lógico**.
|
The `FRAME_SYNC` instruction marks the **end of the logical frame**.
|
||||||
|
|
||||||
| Instrução | Ciclos | Descrição |
|
| Instruction | Cycles | Description |
|
||||||
| ------------ | ------ | ----------------------------- |
|
| ------------ | ------ | ---------------------------------- |
|
||||||
| `FRAME_SYNC` | 1 | Finaliza o frame lógico atual |
|
| `FRAME_SYNC` | 1 | Finalizes the current logical frame |
|
||||||
|
|
||||||
Propriedades:
|
Properties:
|
||||||
|
|
||||||
* `FRAME_SYNC` é uma **instrução do sistema**.
|
* `FRAME_SYNC` is a **system instruction**.
|
||||||
* Não deve ser exposta como API “manual” ao usuário.
|
* It should not be exposed as a "manual" API to the user.
|
||||||
* O tooling/compilador pode **injetar** `FRAME_SYNC` automaticamente ao final do loop principal.
|
* Tooling/compiler can **inject** `FRAME_SYNC` automatically at the end of the main loop.
|
||||||
|
|
||||||
### 12.2 Semântica (o que acontece quando executa)
|
### 12.2 Semantics (what happens when it executes)
|
||||||
|
|
||||||
Ao executar `FRAME_SYNC`, o core:
|
When executing `FRAME_SYNC`, the core:
|
||||||
|
|
||||||
1. **Finaliza** o frame lógico atual.
|
1. **Finalizes** the current logical frame.
|
||||||
2. **Apresenta** o frame (`gfx.present()` ou `gfx.compose_and_present()` conforme o modelo do GFX).
|
2. **Presents** the frame (`gfx.present()` or `gfx.compose_and_present()` depending on the GFX model).
|
||||||
3. **Libera** o latch de input.
|
3. **Releases** the input latch.
|
||||||
4. **Reseta** o budget para o próximo frame lógico.
|
4. **Resets** the budget for the next logical frame.
|
||||||
|
|
||||||
### 12.3 Overbudget (quando o frame não termina a tempo)
|
### 12.3 Overbudget (when the frame doesn't finish on time)
|
||||||
|
|
||||||
Se o budget do frame lógico acabar **antes** da VM alcançar `FRAME_SYNC`:
|
If the logical frame budget runs out **before** the VM reaches `FRAME_SYNC`:
|
||||||
|
|
||||||
* a VM **pausa** (PC e pilhas permanecem no ponto exato)
|
* the VM **pauses** (PC and stacks remain at the exact point)
|
||||||
* **não há present**
|
* there is **no present**
|
||||||
* o latch de input é **mantido**
|
* the input latch is **maintained**
|
||||||
* no próximo tick do host, a VM **continua** de onde parou, ainda no mesmo frame lógico
|
* on the next host tick, the VM **continues** from where it left off, still in the same logical frame
|
||||||
|
|
||||||
Efeito prático:
|
Practical effect:
|
||||||
|
|
||||||
* se o código precisa de 2 budgets para alcançar `FRAME_SYNC`, o jogo passa a atualizar a ~30 FPS (frame lógico leva 2 ticks)
|
* if the code needs 2 budgets to reach `FRAME_SYNC`, the game updates at ~30 FPS (logical frame takes 2 ticks)
|
||||||
* isso é determinístico e reportável no CAP
|
* this is deterministic and reportable in the CAP
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 15. Extensibilidade
|
## 15. Extensibility
|
||||||
|
|
||||||
O Instruction Set é versionado.
|
The Instruction Set is versioned.
|
||||||
|
|
||||||
Futuro:
|
Future:
|
||||||
|
|
||||||
* DMA
|
* DMA
|
||||||
* streaming
|
* streaming
|
||||||
* vetores
|
* vectors
|
||||||
* coprocessadores fictícios
|
* fictitious coprocessors
|
||||||
|
|
||||||
Nenhuma instrução existente muda de significado.
|
No existing instruction changes its meaning.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 16. Resumo
|
## 16. Summary
|
||||||
|
|
||||||
* VM stack-based
|
* stack-based VM
|
||||||
* custo explícito
|
* explicit cost
|
||||||
* execução determinística
|
* deterministic execution
|
||||||
* integrada ao CAP
|
* integrated with CAP
|
||||||
* base de todo cartucho PROMETEU
|
* foundation of every PROMETEU cartridge
|
||||||
|
|
||||||
< [Voltar](chapter-1.md) | [Sumário](table-of-contents.md) | [Adiante](chapter-3.md) >
|
< [Back](chapter-1.md) | [Summary](table-of-contents.md) | [Next](chapter-3.md) >
|
||||||
@ -1,29 +1,29 @@
|
|||||||
< [Voltar](chapter-2.md) | [Sumário](table-of-contents.md) | [Adiante](chapter-4.md) >
|
< [Back](chapter-2.md) | [Summary](table-of-contents.md) | [Next](chapter-4.md) >
|
||||||
|
|
||||||
# 🧠 **Memória: Stack, Heap e Alocação**
|
# 🧠 **Memory: Stack, Heap, and Allocation**
|
||||||
|
|
||||||
## 1. Visão Geral
|
## 1. Overview
|
||||||
|
|
||||||
PROMETEU trata **memória como um recurso explícito**.
|
PROMETEU treats **memory as an explicit resource**.
|
||||||
|
|
||||||
Nada é alocado “por conveniência”.
|
Nothing is allocated "for convenience".
|
||||||
|
|
||||||
Nada cresce “automaticamente”.
|
Nothing grows "automatically".
|
||||||
|
|
||||||
Nada é invisível.
|
Nothing is invisible.
|
||||||
|
|
||||||
Este capítulo define:
|
This chapter defines:
|
||||||
|
|
||||||
- os **espaços de memória** da PROMETEU VM
|
- the **memory spaces** of the PROMETEU VM
|
||||||
- como **Stack** e **Heap** funcionam
|
- how **Stack** and **Heap** work
|
||||||
- o custo e as consequências da **alocação dinâmica**
|
- the cost and consequences of **dynamic allocation**
|
||||||
- como a memória se relaciona com **CAP e certificação**
|
- how memory relates to **CAP and certification**
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 2. Espaços de Memória da PROMETEU VM
|
## 2. PROMETEU VM Memory Spaces
|
||||||
|
|
||||||
A memória da PROMETEU VM é dividida em regiões com responsabilidades claras:
|
The PROMETEU VM memory is divided into regions with clear responsibilities:
|
||||||
|
|
||||||
```
|
```
|
||||||
+---------------------------+
|
+---------------------------+
|
||||||
@ -41,61 +41,61 @@ A memória da PROMETEU VM é dividida em regiões com responsabilidades claras:
|
|||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Cada região:
|
Each region:
|
||||||
|
|
||||||
- tem semântica própria
|
- has its own semantics
|
||||||
- tem limites definidos
|
- has defined limits
|
||||||
- tem impacto direto no custo de execução
|
- has a direct impact on execution cost
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 3. Operand Stack
|
## 3. Operand Stack
|
||||||
|
|
||||||
### 3.1 Definição
|
### 3.1 Definition
|
||||||
|
|
||||||
A **Operand Stack** é usada para:
|
The **Operand Stack** is used for:
|
||||||
|
|
||||||
- passagem de operandos entre instruções
|
- passing operands between instructions
|
||||||
- resultados intermediários
|
- intermediate results
|
||||||
- avaliação de expressões
|
- expression evaluation
|
||||||
|
|
||||||
Ela é:
|
It is:
|
||||||
|
|
||||||
- **LIFO**
|
- **LIFO**
|
||||||
- de crescimento automático dentro do frame
|
- automatically growing within the frame
|
||||||
- **resetada** entre frames (exceto valores persistidos explicitamente)
|
- **reset** between frames (except explicitly persisted values)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### 3.2 Características
|
### 3.2 Characteristics
|
||||||
|
|
||||||
- não armazena estruturas complexas
|
- does not store complex structures
|
||||||
- armazena valores primitivos ou referências
|
- stores primitive values or references
|
||||||
- overflow ou underflow são **erros fatais**
|
- overflow or underflow are **fatal errors**
|
||||||
|
|
||||||
> A pilha de operandos é barata, rápida e temporária.
|
> The operand stack is cheap, fast, and temporary.
|
||||||
>
|
>
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 4. Call Stack (Stack de Chamadas)
|
## 4. Call Stack
|
||||||
|
|
||||||
### 4.1 Frames de Execução
|
### 4.1 Execution Frames
|
||||||
|
|
||||||
Cada chamada de função cria um **Call Frame**, contendo:
|
Each function call creates a **Call Frame**, containing:
|
||||||
|
|
||||||
- variáveis locais
|
- local variables
|
||||||
- parâmetros
|
- parameters
|
||||||
- endereço de retorno
|
- return address
|
||||||
- contexto de execução
|
- execution context
|
||||||
|
|
||||||
Frames são criados com:
|
Frames are created with:
|
||||||
|
|
||||||
```
|
```
|
||||||
PUSH_FRAME n
|
PUSH_FRAME n
|
||||||
```
|
```
|
||||||
|
|
||||||
E destruídos com:
|
And destroyed with:
|
||||||
|
|
||||||
```
|
```
|
||||||
POP_FRAME
|
POP_FRAME
|
||||||
@ -103,64 +103,64 @@ POP_FRAME
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### 4.2 Custos e Limites
|
### 4.2 Costs and Limits
|
||||||
|
|
||||||
- criação de frame tem custo explícito
|
- frame creation has an explicit cost
|
||||||
- profundidade máxima de stack é limitada
|
- maximum stack depth is limited
|
||||||
- recursão profunda é desencorajada
|
- deep recursion is discouraged
|
||||||
|
|
||||||
PROMETEU favorece:
|
PROMETEU favors:
|
||||||
|
|
||||||
- iteração
|
- iteration
|
||||||
- estado explícito
|
- explicit state
|
||||||
- controle consciente de profundidade
|
- conscious depth control
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 5. Global Space
|
## 5. Global Space
|
||||||
|
|
||||||
### 5.1 Definição
|
### 5.1 Definition
|
||||||
|
|
||||||
O **Global Space** armazena:
|
The **Global Space** stores:
|
||||||
|
|
||||||
- variáveis globais
|
- global variables
|
||||||
- estado persistente do jogo
|
- persistent game state
|
||||||
- referências de longo prazo
|
- long-term references
|
||||||
|
|
||||||
Globais:
|
Globals:
|
||||||
|
|
||||||
- sobrevivem entre frames
|
- survive between frames
|
||||||
- ocupam memória permanentemente
|
- occupy memory permanently
|
||||||
- contam para o uso total de memória
|
- count towards total memory usage
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### 5.2 Uso consciente
|
### 5.2 Conscious usage
|
||||||
|
|
||||||
PROMETEU incentiva:
|
PROMETEU encourages:
|
||||||
|
|
||||||
- poucas globais
|
- few globals
|
||||||
- estruturas compactas
|
- compact structures
|
||||||
- inicialização explícita
|
- explicit initialization
|
||||||
|
|
||||||
Globais são equivalentes a **RAM estática** em microcontroladores.
|
Globals are equivalent to **static RAM** in microcontrollers.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 6. Heap
|
## 6. Heap
|
||||||
|
|
||||||
### 6.1 Definição
|
### 6.1 Definition
|
||||||
|
|
||||||
O **Heap** é a região de memória dinâmica da PROMETEU VM.
|
The **Heap** is the dynamic memory region of the PROMETEU VM.
|
||||||
|
|
||||||
É usado para:
|
It is used for:
|
||||||
|
|
||||||
- objetos
|
- objects
|
||||||
- arrays
|
- arrays
|
||||||
- tabelas
|
- tables
|
||||||
- estruturas compostas
|
- composite structures
|
||||||
|
|
||||||
Toda alocação no heap é feita explicitamente com:
|
Every allocation on the heap is done explicitly with:
|
||||||
|
|
||||||
```
|
```
|
||||||
ALLOC size
|
ALLOC size
|
||||||
@ -168,142 +168,142 @@ ALLOC size
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### 6.2 Custos da Alocação
|
### 6.2 Allocation Costs
|
||||||
|
|
||||||
Alocar memória:
|
Allocating memory:
|
||||||
|
|
||||||
- consome **ciclos**
|
- consumes **cycles**
|
||||||
- consome **heap disponível**
|
- consumes **available heap**
|
||||||
- aumenta pressão sobre o sistema
|
- increases pressure on the system
|
||||||
|
|
||||||
PROMETEU trata alocação como uma operação **cara por definição**.
|
PROMETEU treats allocation as an **expensive operation by definition**.
|
||||||
|
|
||||||
> Alocar é uma decisão arquitetural, não um detalhe.
|
> Allocation is an architectural decision, not a detail.
|
||||||
>
|
>
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 7. Limites de Heap
|
## 7. Heap Limits
|
||||||
|
|
||||||
### 7.1 Heap Finito
|
### 7.1 Finite Heap
|
||||||
|
|
||||||
O heap:
|
The heap:
|
||||||
|
|
||||||
- tem tamanho máximo definido
|
- has a defined maximum size
|
||||||
- pode variar conforme o CAP ativo
|
- can vary according to the active CAP
|
||||||
- nunca cresce dinamicamente
|
- never grows dynamically
|
||||||
|
|
||||||
Exemplo:
|
Example:
|
||||||
|
|
||||||
```
|
```
|
||||||
Heap Limit:32KB
|
Heap Limit:32KB
|
||||||
Heap Used:28KB
|
Heap Used:28KB
|
||||||
```
|
```
|
||||||
|
|
||||||
Ultrapassar o limite:
|
Exceeding the limit:
|
||||||
|
|
||||||
- não trava o jogo
|
- does not crash the game
|
||||||
- gera erro de execução
|
- generates an execution error
|
||||||
- aparece no relatório de certificação
|
- appears in the certification report
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### 7.2 Heap e CAP
|
### 7.2 Heap and CAP
|
||||||
|
|
||||||
Durante uma JAM ou avaliação:
|
During a JAM or evaluation:
|
||||||
|
|
||||||
- o pico de heap é medido
|
- heap peak is measured
|
||||||
- o valor é comparado ao limite do CAP
|
- the value is compared to the CAP limit
|
||||||
- não conformidades são registradas
|
- non-compliances are recorded
|
||||||
|
|
||||||
O jogo **continua rodando**, mas a evidência fica registrada.
|
The game **continues running**, but the evidence is recorded.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 8. Garbage Collection (GC)
|
## 8. Garbage Collection (GC)
|
||||||
|
|
||||||
### 8.1 Existência do GC
|
### 8.1 Existence of GC
|
||||||
|
|
||||||
PROMETEU pode utilizar **Garbage Collection simples**, com as seguintes propriedades:
|
PROMETEU may use **simple Garbage Collection**, with the following properties:
|
||||||
|
|
||||||
- não incremental (v0.1)
|
- non-incremental (v0.1)
|
||||||
- custo explícito
|
- explicit cost
|
||||||
- pausas observáveis
|
- observable pauses
|
||||||
- comportamento documentado
|
- documented behavior
|
||||||
|
|
||||||
GC **não é invisível**.
|
GC **is not invisible**.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### 8.2 Custo do GC
|
### 8.2 GC Cost
|
||||||
|
|
||||||
Quando o GC ocorre:
|
When GC occurs:
|
||||||
|
|
||||||
- ciclos são consumidos
|
- cycles are consumed
|
||||||
- o frame pode sofrer impacto
|
- the frame may be impacted
|
||||||
- o evento é registrado
|
- the event is recorded
|
||||||
|
|
||||||
PROMETEU ensina:
|
PROMETEU teaches:
|
||||||
|
|
||||||
> “Criar lixo tem custo.”
|
> "Creating garbage has a cost."
|
||||||
>
|
>
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 9. Boas Práticas de Memória
|
## 9. Memory Best Practices
|
||||||
|
|
||||||
PROMETEU encoraja explicitamente:
|
PROMETEU explicitly encourages:
|
||||||
|
|
||||||
- reutilização de estruturas
|
- structure reuse
|
||||||
- alocação fora do loop principal
|
- allocation outside the main loop
|
||||||
- buffers persistentes
|
- persistent buffers
|
||||||
- pooling manual
|
- pooling manual
|
||||||
|
|
||||||
E desencoraja:
|
And discourages:
|
||||||
|
|
||||||
- alocação por frame
|
- per-frame allocation
|
||||||
- estruturas temporárias descartáveis
|
- disposable temporary structures
|
||||||
- crescimento não planejado
|
- unplanned growth
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 10. Relação com Microcontroladores
|
## 10. Relationship with Microcontrollers
|
||||||
|
|
||||||
O modelo de memória PROMETEU é intencionalmente similar a MCUs reais:
|
The PROMETEU memory model is intentionally similar to real MCUs:
|
||||||
|
|
||||||
| MCU | PROMETEU |
|
| MCU | PROMETEU |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| RAM estática | Global Space |
|
| Static RAM | Global Space |
|
||||||
| Stack | Call Stack |
|
| Stack | Call Stack |
|
||||||
| Heap | Heap |
|
| Heap | Heap |
|
||||||
| Falha de alocação | Erro explícito |
|
| Allocation failure | Explicit error |
|
||||||
| Fragmentação | Responsabilidade do dev |
|
| Fragmentation | Dev's responsibility |
|
||||||
|
|
||||||
Isso cria transferência direta de aprendizado.
|
This creates a direct transfer of learning.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 11. Implicações Pedagógicas
|
## 11. Pedagogical Implications
|
||||||
|
|
||||||
Este modelo permite ensinar:
|
This model allows teaching:
|
||||||
|
|
||||||
- diferença entre stack e heap
|
- the difference between stack and heap
|
||||||
- custo de alocação
|
- allocation cost
|
||||||
- lifetime de dados
|
- data lifetime
|
||||||
- impacto arquitetural de decisões simples
|
- architectural impact of simple decisions
|
||||||
- relação entre memória e tempo
|
- the relationship between memory and time
|
||||||
|
|
||||||
Tudo com **feedback imediato e visível**.
|
Everything with **immediate and visible feedback**.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 12. Resumo
|
## 12. Summary
|
||||||
|
|
||||||
- PROMETEU possui espaços de memória bem definidos
|
- PROMETEU has well-defined memory spaces
|
||||||
- stack é temporária e barata
|
- stack is temporary and cheap
|
||||||
- heap é finita e cara
|
- heap is finite and expensive
|
||||||
- alocação tem custo explícito
|
- allocation has an explicit cost
|
||||||
- GC é visível e mensurável
|
- GC is visible and measurable
|
||||||
- memória participa da certificação
|
- memory participates in certification
|
||||||
|
|
||||||
< [Voltar](chapter-2.md) | [Sumário](table-of-contents.md) | [Adiante](chapter-4.md) >
|
< [Back](chapter-2.md) | [Summary](table-of-contents.md) | [Next](chapter-4.md) >
|
||||||
@ -1,229 +1,229 @@
|
|||||||
< [Voltar](chapter-3.md) | [Sumário](table-of-contents.md) | [Adiante](chapter-5.md) >
|
< [Back](chapter-3.md) | [Summary](table-of-contents.md) | [Next](chapter-5.md) >
|
||||||
|
|
||||||
# 🎨 **Periférico GFX (Sistema Gráfico)**
|
# 🎨 **GFX Peripheral (Graphics System)**
|
||||||
|
|
||||||
## 1. Visão Geral
|
## 1. Overview
|
||||||
|
|
||||||
O periférico **GFX** é responsável pela geração de imagem no PROMETEU.
|
The **GFX** peripheral is responsible for generating images in PROMETEU.
|
||||||
|
|
||||||
Ele modela um **hardware gráfico simples**, inspirado em consoles clássicos
|
It models **simple graphics hardware**, inspired by classic consoles
|
||||||
(SNES, CPS-2, Neo-Geo), priorizando:
|
(SNES, CPS-2, Neo-Geo), prioritizing:
|
||||||
|
|
||||||
- determinismo
|
- determinism
|
||||||
- baixo custo computacional
|
- low computational cost
|
||||||
- didática
|
- didactics
|
||||||
- portabilidade
|
- portability
|
||||||
|
|
||||||
O GFX **não é uma GPU moderna**.
|
The GFX **is not a modern GPU**.
|
||||||
Ele é um dispositivo explícito, baseado em:
|
It is an explicit device, based on:
|
||||||
|
|
||||||
- framebuffer
|
- framebuffer
|
||||||
- tilemaps
|
- tilemaps
|
||||||
- banks de tiles
|
- tile banks
|
||||||
- sprites por prioridade
|
- priority-based sprites
|
||||||
- composição por ordem de desenho
|
- composition by drawing order
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 2. Resolução e Framebuffer
|
## 2. Resolution and Framebuffer
|
||||||
|
|
||||||
### Resolução base
|
### Base resolution
|
||||||
|
|
||||||
- **320 × 180 pixels**
|
- **320 × 180 pixels**
|
||||||
- proporção próxima de 16:9
|
- aspect ratio close to 16:9
|
||||||
- escalável pelo host (nearest-neighbor)
|
- scalable by the host (nearest-neighbor)
|
||||||
|
|
||||||
### Formato de pixel
|
### Pixel format
|
||||||
|
|
||||||
- **RGB565**
|
- **RGB565**
|
||||||
- 5 bits Red
|
- 5 bits Red
|
||||||
- 6 bits Green
|
- 6 bits Green
|
||||||
- 5 bits Blue
|
- 5 bits Blue
|
||||||
- sem canal alpha
|
- no alpha channel
|
||||||
|
|
||||||
Transparência é feita por **color key**.
|
Transparency is handled via **color key**.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 3. Double Buffering
|
## 3. Double Buffering
|
||||||
|
|
||||||
O GFX mantém dois buffers:
|
The GFX maintains two buffers:
|
||||||
|
|
||||||
- **Back Buffer** — onde o frame é construído
|
- **Back Buffer** — where the frame is built
|
||||||
- **Front Buffer** — onde o frame é exibido
|
- **Front Buffer** — where the frame is displayed
|
||||||
|
|
||||||
Fluxo por frame:
|
Per-frame flow:
|
||||||
|
|
||||||
1. O sistema desenha no back buffer
|
1. The system draws to the back buffer
|
||||||
2. Chama `present()`
|
2. Calls `present()`
|
||||||
3. Buffers são trocados
|
3. Buffers are swapped
|
||||||
4. O host exibe o front buffer
|
4. The host displays the front buffer
|
||||||
|
|
||||||
Isso garante:
|
This guarantees:
|
||||||
|
|
||||||
- ausência de tearing
|
- no tearing
|
||||||
- sincronização clara por frame
|
- clear per-frame synchronization
|
||||||
- comportamento determinístico
|
- deterministic behavior
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 4. Estrutura Gráfica do PROMETEU
|
## 4. PROMETEU Graphical Structure
|
||||||
|
|
||||||
O mundo gráfico é composto por:
|
The graphical world is composed of:
|
||||||
|
|
||||||
- Até **16 Tile Banks**
|
- Up to **16 Tile Banks**
|
||||||
- **4 Tile Layers** (scrolláveis)
|
- **4 Tile Layers** (scrollable)
|
||||||
- **1 HUD Layer** (fixa, sempre por cima)
|
- **1 HUD Layer** (fixed, always on top)
|
||||||
- Sprites com prioridade entre layers
|
- Sprites with priority between layers
|
||||||
|
|
||||||
### 4.1 Tile Banks
|
### 4.1 Tile Banks
|
||||||
|
|
||||||
- Existem até **16 banks**
|
- There are up to **16 banks**
|
||||||
- Cada bank tem tamanho fixo de tile:
|
- Each bank has a fixed tile size:
|
||||||
- 8×8, 16×16 ou 32×32
|
- 8×8, 16×16, or 32×32
|
||||||
- Um bank é uma biblioteca de gráficos:
|
- A bank is a graphics library:
|
||||||
- ambiente
|
- environment
|
||||||
- personagens
|
- characters
|
||||||
- UI
|
- UI
|
||||||
- efeitos
|
- effects
|
||||||
|
|
||||||
### 4.2 Layers
|
### 4.2 Layers
|
||||||
|
|
||||||
- Existem:
|
- There are:
|
||||||
- 4 Tile Layers
|
- 4 Tile Layers
|
||||||
- 1 HUD Layer
|
- 1 HUD Layer
|
||||||
- Cada layer aponta para **um único bank**
|
- Each layer points to **a single bank**
|
||||||
- Sprites podem usar **qualquer bank**
|
- Sprites can use **any bank**
|
||||||
- HUD:
|
- HUD:
|
||||||
- não scrolla
|
- does not scroll
|
||||||
- prioridade máxima
|
- maximum priority
|
||||||
- geralmente usa tiles 8×8
|
- generally uses 8×8 tiles
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 5. Modelo Interno de uma Tile Layer
|
## 5. Internal Model of a Tile Layer
|
||||||
|
|
||||||
Uma Tile Layer **não é um bitmap de pixels**.
|
A Tile Layer **is not a bitmap of pixels**.
|
||||||
Ela é composta por:
|
It is composed of:
|
||||||
|
|
||||||
- Um **Tilemap lógico** (índices de tiles)
|
- A **logical Tilemap** (tile indices)
|
||||||
- Um **Cache de Borda** (janela de tiles visíveis)
|
- A **Border Cache** (window of visible tiles)
|
||||||
- Um **Offset de Scroll**
|
- A **Scroll Offset**
|
||||||
|
|
||||||
### Estrutura:
|
### Structure:
|
||||||
|
|
||||||
- `bank_id`
|
- `bank_id`
|
||||||
- `tile_size`
|
- `tile_size`
|
||||||
- `tilemap` (matriz grande)
|
- `tilemap` (large matrix)
|
||||||
- `scroll_x`, `scroll_y`
|
- `scroll_x`, `scroll_y`
|
||||||
- `cache_origin_x`, `cache_origin_y`
|
- `cache_origin_x`, `cache_origin_y`
|
||||||
- `cache_tiles[w][h]`
|
- `cache_tiles[w][h]`
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 6. Tilemap Lógico
|
## 6. Logical Tilemap
|
||||||
|
|
||||||
O tilemap representa o mundo:
|
The tilemap represents the world:
|
||||||
|
|
||||||
Cada célula contém:
|
Each cell contains:
|
||||||
|
|
||||||
- `tile_id`
|
- `tile_id`
|
||||||
- `flip_x`
|
- `flip_x`
|
||||||
- `flip_y`
|
- `flip_y`
|
||||||
- `priority` (opcional)
|
- `priority` (optional)
|
||||||
- `palette_id` (opcional)
|
- `palette_id` (optional)
|
||||||
|
|
||||||
O tilemap pode ser muito maior que a tela.
|
The tilemap can be much larger than the screen.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 7. Cache de Borda (Tile Cache)
|
## 7. Border Cache (Tile Cache)
|
||||||
|
|
||||||
O cache é uma janela de tiles ao redor da câmera.
|
The cache is a window of tiles around the camera.
|
||||||
|
|
||||||
Exemplo:
|
Example:
|
||||||
|
|
||||||
- Tela: 320×180
|
- Screen: 320×180
|
||||||
- Tiles 16×16 → 20×12 visíveis
|
- 16×16 tiles → 20×12 visible
|
||||||
- Cache: 22×14 (margem de 1 tile)
|
- Cache: 22×14 (1-tile margin)
|
||||||
|
|
||||||
Ele guarda os tiles já resolvidos a partir do tilemap.
|
It stores tiles already resolved from the tilemap.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 8. Atualização do Cache
|
## 8. Cache Update
|
||||||
|
|
||||||
A cada frame:
|
Every frame:
|
||||||
|
|
||||||
1. Calcular:
|
1. Calculate:
|
||||||
- `tile_x = scroll_x / tile_size`
|
- `tile_x = scroll_x / tile_size`
|
||||||
- `tile_y = scroll_y / tile_size`
|
- `tile_y = scroll_y / tile_size`
|
||||||
- `offset_x = scroll_x % tile_size`
|
- `offset_x = scroll_x % tile_size`
|
||||||
- `offset_y = scroll_y % tile_size`
|
- `offset_y = scroll_y % tile_size`
|
||||||
|
|
||||||
2. Se `tile_x` mudou:
|
2. If `tile_x` changed:
|
||||||
- Avança `cache_origin_x`
|
- Advance `cache_origin_x`
|
||||||
- Recarrega apenas a nova coluna
|
- Reload only the new column
|
||||||
|
|
||||||
3. Se `tile_y` mudou:
|
3. If `tile_y` changed:
|
||||||
- Avança `cache_origin_y`
|
- Advance `cache_origin_y`
|
||||||
- Recarrega apenas a nova linha
|
- Reload only the new line
|
||||||
|
|
||||||
Somente **uma linha e/ou coluna** é atualizada por frame.
|
Only **one row and/or column** is updated per frame.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 9. Cache como Ring Buffer
|
## 9. Cache as Ring Buffer
|
||||||
|
|
||||||
O cache é circular:
|
The cache is circular:
|
||||||
|
|
||||||
- Não move dados fisicamente
|
- Does not physically move data
|
||||||
- Apenas move índices lógicos
|
- Only moves logical indices
|
||||||
|
|
||||||
Acesso:
|
Access:
|
||||||
- `real_x = (cache_origin_x + logical_x) % cache_width`
|
- `real_x = (cache_origin_x + logical_x) % cache_width`
|
||||||
- `real_y = (cache_origin_y + logical_y) % cache_height`
|
- `real_y = (cache_origin_y + logical_y) % cache_height`
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 10. Projeção para o Back Buffer
|
## 10. Projection to the Back Buffer
|
||||||
|
|
||||||
Para cada frame:
|
For each frame:
|
||||||
|
|
||||||
1. Para cada Tile Layer, em ordem:
|
1. For each Tile Layer, in order:
|
||||||
- Rasterizar tiles visíveis do cache
|
- Rasterize visible tiles from the cache
|
||||||
- Aplicar scroll, flip e transparência
|
- Apply scroll, flip, and transparency
|
||||||
- Escrever no back buffer
|
- Write to the back buffer
|
||||||
|
|
||||||
2. Desenhar sprites:
|
2. Draw sprites:
|
||||||
- Com prioridade entre layers
|
- With priority between layers
|
||||||
- Ordem de desenho define profundidade
|
- Drawing order defines depth
|
||||||
|
|
||||||
3. Desenhar HUD layer por último
|
3. Draw HUD layer last
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 11. Ordem de Desenho e Prioridade
|
## 11. Drawing Order and Priority
|
||||||
|
|
||||||
- Não existe Z-buffer
|
- There is no Z-buffer
|
||||||
- Não existe sorting automático
|
- There is no automatic sorting
|
||||||
- Quem desenha depois fica na frente
|
- Whoever draws later is in front
|
||||||
|
|
||||||
Ordem base:
|
Base order:
|
||||||
|
|
||||||
1. Tile Layer 0
|
1. Tile Layer 0
|
||||||
2. Tile Layer 1
|
2. Tile Layer 1
|
||||||
3. Tile Layer 2
|
3. Tile Layer 2
|
||||||
4. Tile Layer 3
|
4. Tile Layer 3
|
||||||
5. Sprites (por prioridade entre layers)
|
5. Sprites (by priority between layers)
|
||||||
6. HUD Layer
|
6. HUD Layer
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 12. Transparência (Color Key)
|
## 12. Transparency (Color Key)
|
||||||
|
|
||||||
- Um valor RGB565 é reservado como TRANSPARENT_KEY
|
- One RGB565 value is reserved as TRANSPARENT_KEY
|
||||||
- Pixels com essa cor não são desenhados
|
- Pixels with this color are not drawn
|
||||||
|
|
||||||
```
|
```
|
||||||
if src == TRANSPARENT_KEY:
|
if src == TRANSPARENT_KEY:
|
||||||
@ -235,11 +235,11 @@ else:
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 13. Color Math (Blending Discreto)
|
## 13. Color Math (Discrete Blending)
|
||||||
|
|
||||||
Inspirado no SNES.
|
Inspired by the SNES.
|
||||||
|
|
||||||
Modos oficiais:
|
Official modes:
|
||||||
|
|
||||||
- `BLEND_NONE`
|
- `BLEND_NONE`
|
||||||
- `BLEND_HALF`
|
- `BLEND_HALF`
|
||||||
@ -247,99 +247,99 @@ Modos oficiais:
|
|||||||
- `BLEND_HALF_MINUS`
|
- `BLEND_HALF_MINUS`
|
||||||
- `BLEND_FULL`
|
- `BLEND_FULL`
|
||||||
|
|
||||||
Sem alpha contínuo.
|
No continuous alpha.
|
||||||
Sem blending arbitrário.
|
No arbitrary blending.
|
||||||
|
|
||||||
Tudo é:
|
Everything is:
|
||||||
|
|
||||||
- inteiro
|
- integer
|
||||||
- barato
|
- cheap
|
||||||
- determinístico
|
- deterministic
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 14. Onde o Blend é Aplicado
|
## 14. Where Blend is Applied
|
||||||
|
|
||||||
- O blend ocorre durante o desenho
|
- Blending occurs during drawing
|
||||||
- O resultado vai direto para o back buffer
|
- The result goes directly to the back buffer
|
||||||
- Não existe composição posterior automática
|
- There is no automatic post-composition
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 15. O que o GFX NÃO suporta
|
## 15. What the GFX DOES NOT support
|
||||||
|
|
||||||
Por design:
|
By design:
|
||||||
|
|
||||||
- Alpha contínuo
|
- Continuous alpha
|
||||||
- RGBA framebuffer
|
- RGBA framebuffer
|
||||||
- Shader
|
- Shaders
|
||||||
- Pipeline moderno de GPU
|
- Modern GPU pipeline
|
||||||
- HDR
|
- HDR
|
||||||
- Gamma correction
|
- Gamma correction
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 16. Regra de Performance
|
## 16. Performance Rule
|
||||||
|
|
||||||
- Layers:
|
- Layers:
|
||||||
- só atualizam borda ao cruzar tile
|
- only update the border when crossing a tile
|
||||||
- nunca redesenham mundo inteiro
|
- never redraw the entire world
|
||||||
- Rasterização:
|
- Rasterization:
|
||||||
- sempre por frame, só área visível
|
- always per frame, only the visible area
|
||||||
- Sprites:
|
- Sprites:
|
||||||
- sempre redesenhados por frame
|
- always redrawn per frame
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 17. PostFX Especial — Fade (Scene e HUD)
|
## 17. Special PostFX — Fade (Scene and HUD)
|
||||||
|
|
||||||
O PROMETEU suporta **fade gradual** como um PostFX especial, com dois controles
|
PROMETEU supports **gradual fade** as a special PostFX, with two independent
|
||||||
independentes:
|
controls:
|
||||||
|
|
||||||
- **Scene Fade**: afeta toda a cena (Tile Layers 0–3 + Sprites)
|
- **Scene Fade**: affects the entire scene (Tile Layers 0–3 + Sprites)
|
||||||
- **HUD Fade**: afeta apenas o HUD Layer (sempre composto por último)
|
- **HUD Fade**: affects only the HUD Layer (always composed last)
|
||||||
|
|
||||||
O fade é implementado sem alpha contínuo por pixel e sem floats.
|
The fade is implemented without continuous per-pixel alpha and without floats.
|
||||||
Ele usa um **nível inteiro discreto** (0..31), que na prática produz um resultado
|
It uses a **discrete integer level** (0..31), which in practice produces an
|
||||||
visual “quase contínuo” em 320×180 pixel art.
|
"almost continuous" visual result in 320×180 pixel art.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### 17.1 Representação do Fade
|
### 17.1 Fade Representation
|
||||||
|
|
||||||
Cada fade é representado por:
|
Each fade is represented by:
|
||||||
|
|
||||||
- `fade_level: u8` no intervalo **[0..31]**
|
- `fade_level: u8` in the range **[0..31]**
|
||||||
- `0` → totalmente substituído pela cor de fade
|
- `0` → fully replaced by the fade color
|
||||||
- `31` → totalmente visível (sem fade)
|
- `31` → fully visible (no fade)
|
||||||
- `fade_color: RGB565`
|
- `fade_color: RGB565`
|
||||||
- cor para a qual a imagem será misturada
|
- color the image will be blended into
|
||||||
|
|
||||||
Registradores:
|
Registers:
|
||||||
|
|
||||||
- `SCENE_FADE_LEVEL` (0..31)
|
- `SCENE_FADE_LEVEL` (0..31)
|
||||||
- `SCENE_FADE_COLOR` (RGB565)
|
- `SCENE_FADE_COLOR` (RGB565)
|
||||||
- `HUD_FADE_LEVEL` (0..31)
|
- `HUD_FADE_LEVEL` (0..31)
|
||||||
- `HUD_FADE_COLOR` (RGB565)
|
- `HUD_FADE_COLOR` (RGB565)
|
||||||
|
|
||||||
Casos comuns:
|
Common cases:
|
||||||
|
|
||||||
- Fade-out: `fade_color = BLACK`
|
- Fade-out: `fade_color = BLACK`
|
||||||
- Flash/teleporte: `fade_color = WHITE`
|
- Flash/teleport: `fade_color = WHITE`
|
||||||
- Efeitos especiais: qualquer cor RGB565
|
- Special effects: any RGB565 color
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### 17.2 Operação de Fade (Mistura com Cor Arbitrária)
|
### 17.2 Fade Operation (Blending with Arbitrary Color)
|
||||||
|
|
||||||
Para cada pixel RGB565 `src` e cor de fade `fc`, o pixel final `dst` é calculado por canal.
|
For each RGB565 pixel `src` and fade color `fc`, the final pixel `dst` is calculated per channel.
|
||||||
|
|
||||||
1) Extrair componentes:
|
1) Extract components:
|
||||||
|
|
||||||
- `src_r5`, `src_g6`, `src_b5`
|
- `src_r5`, `src_g6`, `src_b5`
|
||||||
- `fc_r5`, `fc_g6`, `fc_b5`
|
- `fc_r5`, `fc_g6`, `fc_b5`
|
||||||
|
|
||||||
2) Aplicar mistura inteira:
|
2) Apply integer blending:
|
||||||
|
|
||||||
```
|
```
|
||||||
src_weight = fade_level // 0..31
|
src_weight = fade_level // 0..31
|
||||||
@ -352,127 +352,127 @@ b5 = (src_b5 * src_weight + fc_b5 * fc_weight) / 31
|
|||||||
- `src_r5`, `src_g6`, `src_b5`
|
- `src_r5`, `src_g6`, `src_b5`
|
||||||
- `fc_r5`, `fc_g6`, `fc_b5`
|
- `fc_r5`, `fc_g6`, `fc_b5`
|
||||||
|
|
||||||
3) Reempacotar:
|
3) Repack:
|
||||||
|
|
||||||
```
|
```
|
||||||
dst = pack_rgb565(r5, g6, b5)
|
dst = pack_rgb565(r5, g6, b5)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
Observações:
|
Notes:
|
||||||
|
|
||||||
- Operação determinística
|
- Deterministic operation
|
||||||
- Somente inteiros
|
- Integers only
|
||||||
- Pode ser otimizada via LUT
|
- Can be optimized via LUT
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### 17.3 Ordem de Aplicação no Frame
|
### 17.3 Order of Application in the Frame
|
||||||
|
|
||||||
A composição do frame segue esta ordem:
|
The frame composition follows this order:
|
||||||
|
|
||||||
1. Rasterizar **Tile Layers 0–3** → Back Buffer
|
1. Rasterize **Tile Layers 0–3** → Back Buffer
|
||||||
2. Rasterizar **Sprites** conforme prioridade
|
2. Rasterize **Sprites** according to priority
|
||||||
3. (Opcional) Pipeline extra (Emission/Light/Glow etc.)
|
3. (Optional) Extra pipeline (Emission/Light/Glow etc.)
|
||||||
4. Aplicar **Scene Fade** usando:
|
4. Apply **Scene Fade** using:
|
||||||
- `SCENE_FADE_LEVEL`
|
- `SCENE_FADE_LEVEL`
|
||||||
- `SCENE_FADE_COLOR`
|
- `SCENE_FADE_COLOR`
|
||||||
5. Rasterizar **HUD Layer**
|
5. Rasterize **HUD Layer**
|
||||||
6. Aplicar **HUD Fade** usando:
|
6. Apply **HUD Fade** using:
|
||||||
- `HUD_FADE_LEVEL`
|
- `HUD_FADE_LEVEL`
|
||||||
- `HUD_FADE_COLOR`
|
- `HUD_FADE_COLOR`
|
||||||
7. `present()`
|
7. `present()`
|
||||||
|
|
||||||
Regras:
|
Rules:
|
||||||
|
|
||||||
- Scene Fade nunca afeta HUD
|
- Scene Fade never affects the HUD
|
||||||
- HUD Fade nunca afeta a cena
|
- HUD Fade never affects the scene
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### 17.4 Casos de Uso
|
### 17.4 Use Cases
|
||||||
|
|
||||||
- Troca de HUD:
|
- HUD Switch:
|
||||||
- diminuir `HUD_FADE_LEVEL` até 0
|
- decrease `HUD_FADE_LEVEL` to 0
|
||||||
- trocar HUD/tilemap
|
- switch HUD/tilemap
|
||||||
- aumentar `HUD_FADE_LEVEL` até 31
|
- increase `HUD_FADE_LEVEL` to 31
|
||||||
|
|
||||||
- Troca de área:
|
- Area Switch:
|
||||||
- diminuir `SCENE_FADE_LEVEL` até 0
|
- decrease `SCENE_FADE_LEVEL` to 0
|
||||||
- trocar cenário
|
- switch scenery
|
||||||
- aumentar `SCENE_FADE_LEVEL` até 31
|
- increase `SCENE_FADE_LEVEL` to 31
|
||||||
|
|
||||||
- Flash / dano / teleporte:
|
- Flash / damage / teleport:
|
||||||
- usar `fade_color = WHITE` ou outra cor temática
|
- use `fade_color = WHITE` or another thematic color
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 18. Sistema de Paletas
|
## 18. Palette System
|
||||||
|
|
||||||
### 18.1. Visão Geral
|
### 18.1. Overview
|
||||||
|
|
||||||
O PROMETEU utiliza **exclusivamente** gráficos indexados por paleta.
|
PROMETEU uses **exclusively** palette-indexed graphics.
|
||||||
|
|
||||||
Não existe modo RGB direto por pixel.
|
There is no direct RGB-per-pixel mode.
|
||||||
Todo pixel gráfico é um **índice** que aponta para uma cor real em uma paleta.
|
Every graphical pixel is an **index** pointing to a real color in a palette.
|
||||||
|
|
||||||
Objetivos:
|
Objectives:
|
||||||
|
|
||||||
- reduzir uso de RAM e storage
|
- reduce RAM and storage usage
|
||||||
- permitir troca de cores sem shader
|
- allow color swapping without shaders
|
||||||
- manter identidade retrô
|
- maintain retro identity
|
||||||
- facilitar efeitos como variação, dano, dia/noite
|
- facilitate effects like variation, damage, day/night
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### 18.2. Formato de Pixel
|
### 18.2. Pixel Format
|
||||||
|
|
||||||
Cada pixel de um tile ou sprite é:
|
Each pixel of a tile or sprite is:
|
||||||
|
|
||||||
- **4 bits por pixel (4bpp)**
|
- **4 bits per pixel (4bpp)**
|
||||||
- valores: `0..15`
|
- values: `0..15`
|
||||||
|
|
||||||
Regra fixa:
|
Fixed rule:
|
||||||
|
|
||||||
- Índice `0` = TRANSPARENTE
|
- Index `0` = TRANSPARENT
|
||||||
- Índices `1..15` = cores válidas da paleta
|
- Indices `1..15` = valid palette colors
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### 18.3. Estrutura de Paletas
|
### 18.3. Palette Structure
|
||||||
|
|
||||||
Cada **Tile Bank** contém:
|
Each **Tile Bank** contains:
|
||||||
|
|
||||||
- Até **256 paletas**
|
- Up to **256 palettes**
|
||||||
- Cada paleta tem:
|
- Each palette has:
|
||||||
- **16 cores**
|
- **16 colors**
|
||||||
- cada cor em **RGB565 (u16)**
|
- each color in **RGB565 (u16)**
|
||||||
|
|
||||||
Tamanho:
|
Size:
|
||||||
|
|
||||||
- 1 paleta = 16 × 2 bytes = **32 bytes**
|
- 1 palette = 16 × 2 bytes = **32 bytes**
|
||||||
- 256 paletas = **8 KB por bank**
|
- 256 palettes = **8 KB per bank**
|
||||||
- 16 banks = **128 KB máximo de paletas**
|
- 16 banks = **128 KB maximum palettes**
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### 18.4. Associação de Paleta
|
### 18.4. Palette Association
|
||||||
|
|
||||||
#### Regra Fundamental
|
#### Fundamental Rule
|
||||||
|
|
||||||
- Cada **tile** usa **uma única paleta**
|
- Each **tile** uses **a single palette**
|
||||||
- Cada **sprite** usa **uma única paleta**
|
- Each **sprite** uses **a single palette**
|
||||||
- A paleta deve ser informada **explicitamente** em todo draw
|
- The palette must be provided **explicitly** in every draw
|
||||||
|
|
||||||
Não existe troca de paleta dentro do mesmo tile ou sprite.
|
There is no palette swap within the same tile or sprite.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### 18.5. Onde a Paleta é Definida
|
### 18.5. Where the Palette is Defined
|
||||||
|
|
||||||
#### Tilemap
|
#### Tilemap
|
||||||
|
|
||||||
Cada célula do tilemap contém:
|
Each tilemap cell contains:
|
||||||
|
|
||||||
- `tile_id`
|
- `tile_id`
|
||||||
- `palette_id (u8)`
|
- `palette_id (u8)`
|
||||||
@ -481,7 +481,7 @@ Cada célula do tilemap contém:
|
|||||||
|
|
||||||
#### Sprite
|
#### Sprite
|
||||||
|
|
||||||
Cada sprite draw contém:
|
Each sprite draw contains:
|
||||||
|
|
||||||
- `bank_id`
|
- `bank_id`
|
||||||
- `tile_id`
|
- `tile_id`
|
||||||
@ -492,20 +492,20 @@ Cada sprite draw contém:
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### 18.6. Resolução de Cor
|
### 18.6. Color Resolution
|
||||||
|
|
||||||
O pipeline funciona assim:
|
The pipeline works like this:
|
||||||
|
|
||||||
1. Ler pixel indexado do tile (valor 0..15)
|
1. Read indexed pixel from tile (value 0..15)
|
||||||
2. Se índice == 0 → pixel transparente
|
2. If index == 0 → transparent pixel
|
||||||
3. Caso contrário:
|
3. Otherwise:
|
||||||
- cor_real = paleta[palette_id][indice]
|
- real_color = palette[palette_id][index]
|
||||||
4. Aplicar:
|
4. Apply:
|
||||||
- flip
|
- flip
|
||||||
- blend discreto
|
- discrete blend
|
||||||
- escrita no back buffer
|
- writing to back buffer
|
||||||
|
|
||||||
Ou seja:
|
In other words:
|
||||||
```
|
```
|
||||||
pixel_index = tile_pixel(x,y)
|
pixel_index = tile_pixel(x,y)
|
||||||
if pixel_index == 0:
|
if pixel_index == 0:
|
||||||
@ -517,84 +517,84 @@ else:
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### 18.7. Organização dos Tile Banks
|
### 18.7. Organization of Tile Banks
|
||||||
|
|
||||||
Os Tile Banks são “assets fortes”:
|
Tile Banks are "strong assets":
|
||||||
|
|
||||||
- Tiles e paletas vivem juntos
|
- Tiles and palettes live together
|
||||||
- Exportação/importação sempre leva:
|
- Export/import always carries:
|
||||||
- tiles + paletas
|
- tiles + palettes
|
||||||
- O hardware não impõe organização semântica:
|
- The hardware does not impose semantic organization:
|
||||||
- o agrupamento é decisão do criador
|
- grouping is the creator's decision
|
||||||
- Tooling e scripts podem criar convenções:
|
- Tooling and scripts can create conventions:
|
||||||
- ex.: paletas 0..15 = inimigos
|
- e.g.: palettes 0..15 = enemies
|
||||||
- 16..31 = cenário
|
- 16..31 = scenery
|
||||||
- etc.
|
- etc.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### 18.8. Efeitos Possíveis com Paletas
|
### 18.8. Possible Effects with Palettes
|
||||||
|
|
||||||
Sem shader, é possível:
|
Without shaders, it is possible to:
|
||||||
|
|
||||||
- Palette swap:
|
- Palette swap:
|
||||||
- inimigos com variação de cor
|
- enemies with color variation
|
||||||
- Estados:
|
- States:
|
||||||
- dano, gelo, veneno, power-up
|
- damage, ice, poison, power-up
|
||||||
- Dia / noite:
|
- Day / night:
|
||||||
- trocar paletas globalmente
|
- swap palettes globally
|
||||||
- Biomas:
|
- Biomes:
|
||||||
- mesma arte, clima diferente
|
- same art, different climate
|
||||||
- UI themes
|
- UI themes
|
||||||
|
|
||||||
Tudo isso sem mudar os tiles.
|
All this without changing tiles.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### 18.9. Limitações Artísticas
|
### 18.9. Artistic Limitations
|
||||||
|
|
||||||
- Cada tile/sprite:
|
- Each tile/sprite:
|
||||||
|
|
||||||
- máximo de 16 cores
|
- maximum of 16 colors
|
||||||
|
|
||||||
- Gradientes suaves exigem:
|
- Smooth gradients require:
|
||||||
|
|
||||||
- dithering
|
- dithering
|
||||||
- blend discreto
|
- discrete blend
|
||||||
- glow/emission
|
- glow/emission
|
||||||
|
|
||||||
Essa limitação é intencional e faz parte da identidade do PROMETEU.
|
This limitation is intentional and part of the PROMETEU identity.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### 18.10. Métricas para Certificação (CAP)
|
### 18.10. Metrics for Certification (CAP)
|
||||||
|
|
||||||
O sistema pode medir:
|
The system can measure:
|
||||||
|
|
||||||
- `palettes_loaded_total`
|
- `palettes_loaded_total`
|
||||||
- `palettes_referenced_this_frame`
|
- `palettes_referenced_this_frame`
|
||||||
- `tiles_drawn_by_palette_id`
|
- `tiles_drawn_by_palette_id`
|
||||||
- `sprites_drawn_by_palette_id`
|
- `sprites_drawn_by_palette_id`
|
||||||
|
|
||||||
Isso permite:
|
This allows:
|
||||||
|
|
||||||
- analisar custo artístico
|
- analyzing artistic cost
|
||||||
- ensinar impacto de variedade excessiva
|
- teaching the impact of excessive variety
|
||||||
- sugerir boas práticas de coesão visual
|
- suggesting best practices for visual cohesion
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 19. Resumo
|
## 19. Summary
|
||||||
|
|
||||||
O GFX do PROMETEU é simples **por escolha**, não por limitação.
|
PROMETEU's GFX is simple **by choice**, not by limitation.
|
||||||
|
|
||||||
- Framebuffer RGB565 com double buffer
|
- RGB565 Framebuffer with double buffer
|
||||||
- Color key para transparência
|
- Color key for transparency
|
||||||
- Blending discreto estilo SNES
|
- SNES-style discrete blending
|
||||||
- Até 16 tile banks
|
- Up to 16 tile banks
|
||||||
- 4 Tile Layers + 1 HUD
|
- 4 Tile Layers + 1 HUD
|
||||||
- Layer = tilemap + cache + scroll
|
- Layer = tilemap + cache + scroll
|
||||||
- Projeção rasterizada por frame
|
- Rasterized projection per frame
|
||||||
- Profundidade definida por ordem de desenho
|
- Depth defined by drawing order
|
||||||
|
|
||||||
< [Voltar](chapter-3.md) | [Sumário](table-of-contents.md) | [Adiante](chapter-5.md) >
|
< [Back](chapter-3.md) | [Summary](table-of-contents.md) | [Next](chapter-5.md) >
|
||||||
@ -1,255 +1,255 @@
|
|||||||
< [Voltar](chapter-4.md) | [Sumário](table-of-contents.md) | [Adiante](chapter-6.md) >
|
< [Back](chapter-4.md) | [Summary](table-of-contents.md) | [Next](chapter-6.md) >
|
||||||
|
|
||||||
# 🔊 Periférico AUDIO (Sistema de Som)
|
# 🔊 AUDIO Peripheral (Audio System)
|
||||||
|
|
||||||
## 1. Visão Geral
|
## 1. Overview
|
||||||
|
|
||||||
O **Periférico AUDIO** é responsável pela **geração e mistura de som** no PROMETEU.
|
The **AUDIO Peripheral** is responsible for **sound generation and mixing** in PROMETEU.
|
||||||
|
|
||||||
Assim como os demais subsistemas:
|
Just like the other subsystems:
|
||||||
|
|
||||||
- não é automático
|
- it is not automatic
|
||||||
- não é gratuito
|
- it is not free
|
||||||
- não é mágico
|
- it is not magic
|
||||||
|
|
||||||
Cada som é resultado de **comandos explícitos**, executados sob **orçamento de tempo e recursos**.
|
Each sound is the result of **explicit commands**, executed under a **time and resource budget**.
|
||||||
|
|
||||||
> Som consome tempo.
|
> Sound consumes time.
|
||||||
> Som consome memória.
|
> Sound consumes memory.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 2. Filosofia
|
## 2. Philosophy
|
||||||
|
|
||||||
PROMETEU trata áudio como:
|
PROMETEU treats audio as:
|
||||||
|
|
||||||
- um **periférico ativo**
|
- an **active peripheral**
|
||||||
- com **canais limitados**
|
- with **limited channels**
|
||||||
- comportamento **determinístico**
|
- **deterministic** behavior
|
||||||
- controle **explícito**
|
- **explicit** control
|
||||||
|
|
||||||
Objetivo: clareza arquitetural e didática, não realismo absoluto.
|
Objective: architectural and didactic clarity, not absolute realism.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 3. Arquitetura Geral
|
## 3. General Architecture
|
||||||
|
|
||||||
O sistema de áudio é composto por:
|
The audio system is composed of:
|
||||||
|
|
||||||
- **Voices (canais)** — tocadores independentes
|
- **Voices (channels)** — independent players
|
||||||
- **Samples** — dados PCM
|
- **Samples** — PCM data
|
||||||
- **Mixer** — soma das voices
|
- **Mixer** — summation of voices
|
||||||
- **Saída** — buffer estéreo PCM
|
- **Output** — PCM stereo buffer
|
||||||
|
|
||||||
Separação conceitual:
|
Conceptual separation:
|
||||||
|
|
||||||
- Jogo envia **comandos a 60Hz**
|
- Game sends **commands at 60Hz**
|
||||||
- Áudio é **gerado continuamente** em 48kHz
|
- Audio is **generated continuously** at 48kHz
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 4. Formato de Saída
|
## 4. Output Format
|
||||||
|
|
||||||
- Sample rate: **48.000 Hz**
|
- Sample rate: **48,000 Hz**
|
||||||
- Formato: **PCM16 estéreo (signed i16)**
|
- Format: **PCM16 stereo (signed i16)**
|
||||||
- Clipping: saturação/clamp
|
- Clipping: saturation/clamp
|
||||||
|
|
||||||
Esse formato é compatível com:
|
This format is compatible with:
|
||||||
|
|
||||||
- DACs I2S comuns
|
- common I2S DACs
|
||||||
- HDMI áudio
|
- HDMI audio
|
||||||
- USB áudio
|
- USB audio
|
||||||
- SBCs DIY (Raspberry Pi, Orange Pi, etc.)
|
- DIY SBCs (Raspberry Pi, Orange Pi, etc.)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 5. Voices (Canais)
|
## 5. Voices (Channels)
|
||||||
|
|
||||||
### 5.1 Quantidade
|
### 5.1 Quantity
|
||||||
|
|
||||||
```
|
```
|
||||||
MAX_VOICES = 16
|
MAX_VOICES = 16
|
||||||
```
|
```
|
||||||
|
|
||||||
Cada voice:
|
Each voice:
|
||||||
|
|
||||||
- toca **1 sample por vez**
|
- plays **1 sample at a time**
|
||||||
- é independente
|
- is independent
|
||||||
- é misturada no output final
|
- is mixed into the final output
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### 5.2 Estado de uma Voice
|
### 5.2 Voice State
|
||||||
|
|
||||||
Cada voice mantém:
|
Each voice maintains:
|
||||||
|
|
||||||
- `sample_id`
|
- `sample_id`
|
||||||
- `pos` (posição fracionária no sample)
|
- `pos` (fractional position in the sample)
|
||||||
- `rate` (pitch)
|
- `rate` (pitch)
|
||||||
- `volume` (0..255)
|
- `volume` (0..255)
|
||||||
- `pan` (0..255, esquerda→direita)
|
- `pan` (0..255, left→right)
|
||||||
- `loop_mode` (off / on)
|
- `loop_mode` (off / on)
|
||||||
- `loop_start`, `loop_end`
|
- `loop_start`, `loop_end`
|
||||||
- `priority` (opcional)
|
- `priority` (optional)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### 5.3 Conflito de Voices
|
### 5.3 Voice Conflict
|
||||||
|
|
||||||
Se todas as voices estiverem ocupadas:
|
If all voices are occupied:
|
||||||
|
|
||||||
- aplica-se uma política explícita:
|
- an explicit policy is applied:
|
||||||
- `STEAL_OLDEST`
|
- `STEAL_OLDEST`
|
||||||
- `STEAL_QUIETEST`
|
- `STEAL_QUIETEST`
|
||||||
- `STEAL_LOWEST_PRIORITY`
|
- `STEAL_LOWEST_PRIORITY`
|
||||||
|
|
||||||
|
|
||||||
PROMETEU não resolve isso automaticamente sem regra definida.
|
PROMETEU does not resolve this automatically without a defined rule.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 6. Modelo Conceitual: “CPU de Áudio”
|
## 6. Conceptual Model: “Audio CPU”
|
||||||
|
|
||||||
O AUDIO do PROMETEU é concebido como um **periférico independente**, assim como consoles clássicos tinham:
|
The PROMETEU AUDIO is conceived as an **independent peripheral**, just as classic consoles had:
|
||||||
|
|
||||||
- CPU principal do jogo
|
- Main game CPU
|
||||||
- CPU dedicada ao som
|
- Dedicated sound CPU
|
||||||
|
|
||||||
No PROMETEU:
|
In PROMETEU:
|
||||||
|
|
||||||
- O **core lógico** assume essa separação conceitual
|
- The **logical core** assumes this conceptual separation
|
||||||
- O **host decide** como implementar:
|
- The **host decides** how to implement it:
|
||||||
- mesma thread
|
- same thread
|
||||||
- thread separada
|
- separate thread
|
||||||
- core separado
|
- separate core
|
||||||
|
|
||||||
### 6.1 Metáfora de Hardware
|
### 6.1 Hardware Metaphor
|
||||||
|
|
||||||
Conceitualmente:
|
Conceptually:
|
||||||
|
|
||||||
```
|
```
|
||||||
[CPU do Jogo] → envia comandos 60Hz → [Periférico AUDIO]
|
[Game CPU] → sends 60Hz commands → [AUDIO Peripheral]
|
||||||
|
|
|
|
||||||
v
|
v
|
||||||
Voices + Mixer
|
Voices + Mixer
|
||||||
|
|
|
|
||||||
v
|
v
|
||||||
Saída PCM
|
PCM Output
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
### 6.2 Implementação é Papel do Host
|
### 6.2 Implementation is the Host's Role
|
||||||
|
|
||||||
O core:
|
The core:
|
||||||
|
|
||||||
- define o **modelo**
|
- defines the **model**
|
||||||
- define os **comandos**
|
- defines the **commands**
|
||||||
- define os **limites**
|
- defines the **limits**
|
||||||
|
|
||||||
O host:
|
The host:
|
||||||
|
|
||||||
- escolhe:
|
- chooses:
|
||||||
- threads
|
- threads
|
||||||
- afinidade de CPU
|
- CPU affinity
|
||||||
- backend de áudio
|
- audio backend
|
||||||
- garante entrega contínua dos buffers
|
- guarantees continuous delivery of buffers
|
||||||
|
|
||||||
Assim:
|
Thus:
|
||||||
|
|
||||||
> PROMETEU modela o hardware.
|
> PROMETEU models the hardware.
|
||||||
> O host decide como realizá-lo fisicamente.
|
> The host decides how to physically realize it.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 7. Samples
|
## 7. Samples
|
||||||
|
|
||||||
### 7.1 Formato
|
### 7.1 Format
|
||||||
|
|
||||||
Samples do PROMETEU:
|
PROMETEU samples:
|
||||||
|
|
||||||
- **PCM16 mono**
|
- **PCM16 mono**
|
||||||
- sample_rate próprio (ex.: 22050, 44100, 48000)
|
- own sample_rate (e.g., 22050, 44100, 48000)
|
||||||
- dados imutáveis em runtime
|
- immutable data at runtime
|
||||||
|
|
||||||
Campos:
|
Fields:
|
||||||
|
|
||||||
- `sample_rate`
|
- `sample_rate`
|
||||||
- `frames_len`
|
- `frames_len`
|
||||||
- `loop_start`, `loop_end` (opcional)
|
- `loop_start`, `loop_end` (optional)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### 7.2 Uso
|
### 7.2 Usage
|
||||||
|
|
||||||
Exemplo:
|
Example:
|
||||||
|
|
||||||
```
|
```
|
||||||
audio.play(sample_id, voice_id, volume, pan, pitch, priority)
|
audio.play(sample_id, voice_id, volume, pan, pitch, priority)
|
||||||
```
|
```
|
||||||
|
|
||||||
Ou:
|
Or:
|
||||||
|
|
||||||
```
|
```
|
||||||
audio.playAuto(sample_id, volume, pan, pitch, priority)
|
audio.playAuto(sample_id, volume, pan, pitch, priority)
|
||||||
```
|
```
|
||||||
|
|
||||||
(usa política de stealing)
|
(uses stealing policy)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 8. Pitch e Interpolação
|
## 8. Pitch and Interpolation
|
||||||
|
|
||||||
- `rate = 1.0` → velocidade normal
|
- `rate = 1.0` → normal speed
|
||||||
- `rate > 1.0` → mais agudo
|
- `rate > 1.0` → higher pitch
|
||||||
- `rate < 1.0` → mais grave
|
- `rate < 1.0` → lower pitch
|
||||||
|
|
||||||
Como posição vira fracionária:
|
As position becomes fractional:
|
||||||
|
|
||||||
- usa-se **interpolação linear** entre dois samples vizinhos
|
- **linear interpolation** is used between two neighboring samples
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 9. Mixer
|
## 9. Mixer
|
||||||
|
|
||||||
Para cada frame de saída (48kHz):
|
For each output frame (48kHz):
|
||||||
|
|
||||||
1. Para cada voice ativa:
|
1. For each active voice:
|
||||||
- ler sample na posição atual
|
- read sample at current position
|
||||||
- aplicar pitch
|
- apply pitch
|
||||||
- aplicar volume
|
- apply volume
|
||||||
- aplicar pan → gera L/R
|
- apply pan → generates L/R
|
||||||
2. Somar todas as voices
|
2. Sum all voices
|
||||||
3. Aplicar clamp
|
3. Apply clamp
|
||||||
4. Escrever no buffer estéreo
|
4. Write to the stereo buffer
|
||||||
|
|
||||||
Custo depende de:
|
Cost depends on:
|
||||||
|
|
||||||
- número de voices ativas
|
- number of active voices
|
||||||
- uso de interpolação
|
- use of interpolation
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 10. Sincronização com o Jogo
|
## 10. Synchronization with the Game
|
||||||
|
|
||||||
- Jogo roda a **60Hz**
|
- Game runs at **60Hz**
|
||||||
- Áudio gera dados a **48kHz**
|
- Audio generates data at **48kHz**
|
||||||
|
|
||||||
A cada frame (60Hz):
|
Every frame (60Hz):
|
||||||
|
|
||||||
- jogo envia comandos:
|
- game sends commands:
|
||||||
- play
|
- play
|
||||||
- stop
|
- stop
|
||||||
- set_volume
|
- set_volume
|
||||||
- set_pan
|
- set_pan
|
||||||
- set_pitch
|
- set_pitch
|
||||||
|
|
||||||
O áudio aplica esses comandos e continua tocando.
|
The audio applies these commands and continues playing.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 11. Comandos Básicos
|
## 11. Basic Commands
|
||||||
|
|
||||||
Exemplos conceituais:
|
Conceptual examples:
|
||||||
|
|
||||||
```
|
```
|
||||||
audio.play(sample, voice, volume, pan, pitch, priority)
|
audio.play(sample, voice, volume, pan, pitch, priority)
|
||||||
@ -263,15 +263,15 @@ audio.isPlaying(voice)
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 12. Áudio e CAP
|
## 12. Audio and CAP
|
||||||
|
|
||||||
O áudio participa do Execution CAP:
|
Audio participates in the Execution CAP:
|
||||||
|
|
||||||
- custo de mixagem por frame
|
- mixing cost per frame
|
||||||
- custo por voice ativa
|
- cost per active voice
|
||||||
- custo de comandos
|
- command cost
|
||||||
|
|
||||||
Exemplo:
|
Example:
|
||||||
|
|
||||||
```
|
```
|
||||||
Frame 1024:
|
Frame 1024:
|
||||||
@ -283,49 +283,49 @@ audio_commands: 6
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 13. Boas Práticas
|
## 13. Best Practices
|
||||||
|
|
||||||
Recomendado:
|
Recommended:
|
||||||
|
|
||||||
- reutilizar samples
|
- reuse samples
|
||||||
- limitar voices simultâneas
|
- limit simultaneous voices
|
||||||
- tratar som como evento
|
- treat sound as an event
|
||||||
- separar música e efeitos
|
- separate music and effects
|
||||||
|
|
||||||
Evitar:
|
Avoid:
|
||||||
|
|
||||||
- tocar som todo frame
|
- playing sound every frame
|
||||||
- abusar de voices
|
- abusing voices
|
||||||
- samples gigantes para efeitos simples
|
- giant samples for simple effects
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 14. Inspiração Histórica
|
## 14. Historical Inspiration
|
||||||
|
|
||||||
O modelo PROMETEU se inspira em:
|
The PROMETEU model is inspired by:
|
||||||
|
|
||||||
- NES: canais fixos
|
- NES: fixed channels
|
||||||
- SNES: sample playback + mixagem
|
- SNES: sample playback + mixing
|
||||||
- CPS2: polifonia confortável
|
- CPS2: comfortable polyphony
|
||||||
- Neo Geo: sample pesado (não copiado integralmente)
|
- Neo Geo: heavy samples (not fully copied)
|
||||||
|
|
||||||
Mas abstraído para:
|
But abstracted for:
|
||||||
|
|
||||||
- clareza
|
- clarity
|
||||||
- simplicidade
|
- simplicity
|
||||||
- ensino
|
- teaching
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 15. Resumo
|
## 15. Summary
|
||||||
|
|
||||||
- Output: PCM16 estéreo @ 48kHz
|
- Output: stereo PCM16 @ 48kHz
|
||||||
- 16 voices
|
- 16 voices
|
||||||
- Samples PCM16 mono
|
- mono PCM16 samples
|
||||||
- Volume, pan, pitch
|
- Volume, pan, pitch
|
||||||
- Interpolação linear
|
- Linear interpolation
|
||||||
- Mixer explícito
|
- Explicit mixer
|
||||||
- Conceito de “CPU de áudio”
|
- "Audio CPU" concept
|
||||||
- Implementação é papel do host
|
- Implementation is the host's role
|
||||||
|
|
||||||
< [Voltar](chapter-4.md) | [Sumário](table-of-contents.md) | [Adiante](chapter-6.md) >
|
< [Back](chapter-4.md) | [Summary](table-of-contents.md) | [Next](chapter-6.md) >
|
||||||
@ -1,94 +1,94 @@
|
|||||||
< [Voltar](chapter-5.md) | [Sumário](table-of-contents.md) | [Adiante](chapter-7.md) >
|
< [Back](chapter-5.md) | [Summary](table-of-contents.md) | [Next](chapter-7.md) >
|
||||||
|
|
||||||
# 🎮 **Periférico INPUT (Sistema de Entrada)**
|
# 🎮 **INPUT Peripheral (Input System)**
|
||||||
|
|
||||||
## 1. Visão Geral
|
## 1. Overview
|
||||||
|
|
||||||
O **Periférico INPUT** é responsável por **coletar e disponibilizar o estado dos controles** ao programa PROMETEU.
|
The **INPUT Peripheral** is responsible for **collecting and providing the state of controls** to the PROMETEU program.
|
||||||
|
|
||||||
Em PROMETEU:
|
In PROMETEU:
|
||||||
|
|
||||||
- input é **estado**, não evento implícito
|
- input is **state**, not an implicit event
|
||||||
- input é **amostrado no tempo**, não entregue assíncronamente
|
- input is **sampled over time**, not delivered asynchronously
|
||||||
- input tem **ordem, custo e momento definidos**
|
- input has a **defined order, cost, and moment**
|
||||||
|
|
||||||
> Botões não “disparam eventos”.
|
> Buttons do not “trigger events”.
|
||||||
Eles mudam de estado.
|
> They change state.
|
||||||
>
|
>
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 2. Filosofia do Sistema de Entrada
|
## 2. Philosophy of the Input System
|
||||||
|
|
||||||
PROMETEU modela input como hardware clássico:
|
PROMETEU models input like classic hardware:
|
||||||
|
|
||||||
- o estado dos controles é lido **uma vez por frame**
|
- the state of controls is read **once per frame**
|
||||||
- o programa consulta esse estado durante `UPDATE`
|
- the program queries this state during `UPDATE`
|
||||||
- não existem callbacks assíncronos de input
|
- there are no asynchronous input callbacks
|
||||||
|
|
||||||
Esse modelo:
|
This model:
|
||||||
|
|
||||||
- é determinístico
|
- is deterministic
|
||||||
- é simples de entender
|
- is simple to understand
|
||||||
- reflete microcontroladores e consoles clássicos
|
- reflects microcontrollers and classic consoles
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 3. Dispositivos de Entrada
|
## 3. Input Devices
|
||||||
|
|
||||||
PROMETEU abstrai diferentes dispositivos em uma interface comum.
|
PROMETEU abstracts different devices into a common interface.
|
||||||
|
|
||||||
Dispositivos típicos:
|
Typical devices:
|
||||||
|
|
||||||
- controle digital (D-Pad + botões)
|
- digital control (D-Pad + botões)
|
||||||
- teclado (mapeado para botões)
|
- keyboard (mapped to buttons)
|
||||||
- gamepad
|
- gamepad
|
||||||
- toque (mobile, mapeado)
|
- touch (mobile, mapped)
|
||||||
|
|
||||||
Independentemente da origem, PROMETEU expõe **o mesmo modelo lógico**.
|
Regardless of the origin, PROMETEU exposes **the same logical model**.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 4. Modelo de Estado
|
## 4. State Model
|
||||||
|
|
||||||
### 4.1 Estado por Frame
|
### 4.1 Per-Frame State
|
||||||
|
|
||||||
Para cada frame, o sistema mantém:
|
For each frame, the system maintains:
|
||||||
|
|
||||||
- estado atual dos botões
|
- current state of buttons
|
||||||
- estado do frame anterior
|
- state from the previous frame
|
||||||
|
|
||||||
Isso permite consultar:
|
This allows querying:
|
||||||
|
|
||||||
- botão pressionado
|
- button pressed
|
||||||
- botão liberado
|
- button released
|
||||||
- botão mantido pressionado
|
- button held down
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### 4.2 Tipos de Consulta
|
### 4.2 Query Types
|
||||||
|
|
||||||
Operações típicas:
|
Typical operations:
|
||||||
|
|
||||||
```
|
```
|
||||||
input.btn(id)// botão está pressionado
|
input.btn(id)// button is pressed
|
||||||
input.btnp(id)// botão foi pressionado neste frame
|
input.btnp(id)// button was pressed this frame
|
||||||
input.btnr(id)// botão foi liberado neste frame
|
input.btnr(id)// button was released this frame
|
||||||
```
|
```
|
||||||
|
|
||||||
Essas funções:
|
These functions:
|
||||||
|
|
||||||
- são puramente consultivas
|
- are purely advisory
|
||||||
- não alteram estado
|
- do not change state
|
||||||
- têm custo explícito
|
- have an explicit cost
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 5. Momento da Amostragem
|
## 5. Sampling Moment
|
||||||
|
|
||||||
O estado do input é capturado **no início de cada frame**, antes da fase `UPDATE`.
|
The input state is captured **at the beginning of each frame**, before the `UPDATE` phase.
|
||||||
|
|
||||||
Fluxo conceitual:
|
Conceptual flow:
|
||||||
|
|
||||||
```
|
```
|
||||||
FRAME N:
|
FRAME N:
|
||||||
@ -99,162 +99,162 @@ AUDIO
|
|||||||
SYNC
|
SYNC
|
||||||
```
|
```
|
||||||
|
|
||||||
Durante todo o frame:
|
Throughout the entire frame:
|
||||||
|
|
||||||
- o estado de input é imutável
|
- the input state is immutable
|
||||||
- chamadas repetidas retornam o mesmo valor
|
- repeated calls return the same value
|
||||||
|
|
||||||
> Input não muda no meio do frame.
|
> Input does not change in the middle of the frame.
|
||||||
>
|
>
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 6. Determinismo e Reprodutibilidade
|
## 6. Determinism and Reproducibility
|
||||||
|
|
||||||
O modelo de input PROMETEU garante:
|
The PROMETEU input model guarantees:
|
||||||
|
|
||||||
- mesma sequência de inputs
|
- same sequence of inputs
|
||||||
- mesmos frames
|
- same frames
|
||||||
- mesmos resultados
|
- same results
|
||||||
|
|
||||||
Isso permite:
|
This allows:
|
||||||
|
|
||||||
- reprodução de execuções
|
- execution playback
|
||||||
- replays determinísticos
|
- deterministic replays
|
||||||
- certificação confiável
|
- reliable certification
|
||||||
|
|
||||||
Input pode ser:
|
Input can be:
|
||||||
|
|
||||||
- gravado
|
- recorded
|
||||||
- reproduzido
|
- played back
|
||||||
- injetado artificialmente
|
- artificially injected
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 7. Input e CAP
|
## 7. Input and CAP
|
||||||
|
|
||||||
Operações de input:
|
Input operations:
|
||||||
|
|
||||||
- consomem poucos ciclos
|
- consume few cycles
|
||||||
- participam do orçamento por frame
|
- participate in the per-frame budget
|
||||||
- aparecem em relatórios de certificação
|
- appear in certification reports
|
||||||
|
|
||||||
Exemplo:
|
Example:
|
||||||
|
|
||||||
```
|
```
|
||||||
Frame 18231:
|
Frame 18231:
|
||||||
input.btn():12cycles
|
input.btn():12cycles
|
||||||
```
|
```
|
||||||
|
|
||||||
Embora barato, input **não é gratuito**.
|
Although cheap, input **is not free**.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 8. Mapeamento de Botões
|
## 8. Button Mapping
|
||||||
|
|
||||||
### 8.1 Identificadores Lógicos
|
### 8.1 Logical Identifiers
|
||||||
|
|
||||||
PROMETEU define identificadores lógicos de botões:
|
PROMETEU defines logical button identifiers:
|
||||||
|
|
||||||
- `UP`, `DOWN`, `LEFT`, `RIGHT`
|
- `UP`, `DOWN`, `LEFT`, `RIGHT`
|
||||||
- `A`, `B`, `X`, `Y`
|
- `A`, `B`, `X`, `Y`
|
||||||
- `START`, `SELECT`
|
- `START`, `SELECT`
|
||||||
|
|
||||||
O mapeamento físico:
|
The physical mapping:
|
||||||
|
|
||||||
- depende da plataforma
|
- depends on the platform
|
||||||
- é resolvido fora da VM
|
- is resolved outside the VM
|
||||||
- é transparente ao programa
|
- is transparent to the program
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### 8.2 Portabilidade
|
### 8.2 Portability
|
||||||
|
|
||||||
O mesmo cartucho PROMETEU:
|
The same PROMETEU cartridge:
|
||||||
|
|
||||||
- roda em teclado
|
- runs on a keyboard
|
||||||
- roda em gamepad
|
- runs on a gamepad
|
||||||
- roda em touch
|
- runs on touch
|
||||||
|
|
||||||
Sem alteração de código.
|
Without any code changes.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 9. Input Analógico (Opcional)
|
## 9. Analog Input (Optional)
|
||||||
|
|
||||||
PROMETEU pode expor eixos analógicos de forma explícita:
|
PROMETEU can expose analog axes explicitly:
|
||||||
|
|
||||||
```
|
```
|
||||||
input.axis(id)
|
input.axis(id)
|
||||||
```
|
```
|
||||||
|
|
||||||
Características:
|
Characteristics:
|
||||||
|
|
||||||
- valor normalizado (ex.: -1.0 a 1.0)
|
- normalized value (e.g.: -1.0 to 1.0)
|
||||||
- custo explícito
|
- explicit cost
|
||||||
- atualização por frame
|
- per-frame update
|
||||||
|
|
||||||
Input analógico:
|
Analog input:
|
||||||
|
|
||||||
- não é obrigatório
|
- is not mandatory
|
||||||
- não substitui input digital
|
- does not replace digital input
|
||||||
- deve ser usado conscientemente
|
- must be used consciously
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 10. Boas Práticas de Input
|
## 10. Input Best Practices
|
||||||
|
|
||||||
PROMETEU incentiva:
|
PROMETEU encourages:
|
||||||
|
|
||||||
- tratar input como estado
|
- treating input as state
|
||||||
- consultar input apenas em `UPDATE`
|
- querying input only in `UPDATE`
|
||||||
- separar input de lógica pesada
|
- separating input from heavy logic
|
||||||
- mapear ações, não teclas
|
- mapping actions, not keys
|
||||||
|
|
||||||
E desencoraja:
|
And discourages:
|
||||||
|
|
||||||
- lógica dependente de polling excessivo
|
- logic dependent on excessive polling
|
||||||
- leitura de input em DRAW
|
- reading input in DRAW
|
||||||
- acoplamento direto a hardware físico
|
- direct coupling to physical hardware
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 11. Relação com Consoles Clássicos
|
## 11. Relationship with Classic Consoles
|
||||||
|
|
||||||
O modelo PROMETEU reflete:
|
The PROMETEU model reflects:
|
||||||
|
|
||||||
- leitura de registradores de input
|
- reading input registers
|
||||||
- polling por frame
|
- per-frame polling
|
||||||
- ausência de eventos assíncronos
|
- absence of asynchronous events
|
||||||
|
|
||||||
Esse modelo:
|
This model:
|
||||||
|
|
||||||
- simplifica raciocínio
|
- simplifies reasoning
|
||||||
- aumenta previsibilidade
|
- increases predictability
|
||||||
- facilita debugging
|
- facilitates debugging
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 12. Implicações Pedagógicas
|
## 12. Pedagogical Implications
|
||||||
|
|
||||||
O Periférico INPUT permite ensinar:
|
The INPUT Peripheral allows teaching:
|
||||||
|
|
||||||
- diferença entre evento e estado
|
- the difference between event and state
|
||||||
- amostragem temporal
|
- temporal sampling
|
||||||
- determinismo em sistemas interativos
|
- determinism in interactive systems
|
||||||
- sincronização entre input e lógica
|
- synchronization between input and logic
|
||||||
|
|
||||||
Com feedback claro e reproduzível.
|
With clear and reproducible feedback.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 13. Resumo
|
## 13. Summary
|
||||||
|
|
||||||
- input é estado, não evento
|
- input is state, not an event
|
||||||
- amostrado uma vez por frame
|
- sampled once per frame
|
||||||
- imutável durante o frame
|
- immutable during the frame
|
||||||
- consultas têm custo explícito
|
- queries have an explicit cost
|
||||||
- input participa do CAP
|
- input participates in the CAP
|
||||||
- modelo é determinístico
|
- model is deterministic
|
||||||
|
|
||||||
< [Voltar](chapter-5.md) | [Sumário](table-of-contents.md) | [Adiante](chapter-7.md) >
|
< [Back](chapter-5.md) | [Summary](table-of-contents.md) | [Next](chapter-7.md) >
|
||||||
@ -1,72 +1,72 @@
|
|||||||
< [Voltar](chapter-6.md) | [Sumário](table-of-contents.md) | [Adiante](chapter-8.md) >
|
< [Back](chapter-6.md) | [Summary](table-of-contents.md) | [Next](chapter-8.md) >
|
||||||
|
|
||||||
# 🖐️ Periférico TOUCH (Sistema de Entrada via ponteiro absoluto)
|
# 🖐️ TOUCH Peripheral (Absolute Pointer Input System)
|
||||||
|
|
||||||
## 1. Visão Geral
|
## 1. Overview
|
||||||
|
|
||||||
O periférico **TOUCH** fornece ao PROMETEU um **ponteiro absoluto**, baseado em coordenadas de tela, destinado a:
|
The **TOUCH** peripheral provides PROMETEU with an **absolute pointer**, based on screen coordinates, intended for:
|
||||||
|
|
||||||
- interação com UI
|
- UI interaction
|
||||||
- seleção direta de elementos
|
- direct element selection
|
||||||
- ações contextuais no cenário
|
- contextual actions in the scenery
|
||||||
- mecânicas baseadas em arrasto (drag, slash, trail)
|
- drag-based mechanics (drag, slash, trail)
|
||||||
|
|
||||||
O TOUCH é um **periférico de primeira classe**, tão válido quanto D-Pad e botões.
|
The TOUCH is a **first-class peripheral**, as valid as D-Pad and buttons.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 2. Princípios de Design
|
## 2. Design Principles
|
||||||
|
|
||||||
O TOUCH no PROMETEU segue princípios rígidos:
|
TOUCH in PROMETEU follows strict principles:
|
||||||
|
|
||||||
- ✅ **Single-touch universal**
|
- ✅ **Universal single-touch**
|
||||||
- ✅ **Determinístico**
|
- ✅ **Deterministic**
|
||||||
- ✅ **Estado por frame**
|
- ✅ **Per-frame state**
|
||||||
- ✅ **Sem gestos**
|
- ✅ **No gestures**
|
||||||
- ✅ **Sem aceleração**
|
- ✅ **No acceleration**
|
||||||
- ✅ **Sem heurística**
|
- ✅ **No heuristics**
|
||||||
- ✅ **Mesmo comportamento em todas as plataformas**
|
- ✅ **Same behavior on all platforms**
|
||||||
|
|
||||||
> Se um comportamento não pode ser garantido em todas as plataformas, ele não existe no PROMETEU.
|
> If a behavior cannot be guaranteed on all platforms, it does not exist in PROMETEU.
|
||||||
>
|
>
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 3. Modelo Conceitual
|
## 3. Conceptual Model
|
||||||
|
|
||||||
O PROMETEU expõe **apenas um ponteiro ativo por vez**, independentemente de quantos toques físicos o hardware reconheça.
|
PROMETEU exposes **only one active pointer at a time**, regardless of how many physical touches the hardware recognizes.
|
||||||
|
|
||||||
- Hardware pode detectar multitouch
|
- Hardware may detect multitouch
|
||||||
- Runtime seleciona **apenas um toque ativo**
|
- Runtime selects **only one active touch**
|
||||||
- A API **nunca expõe multitouch**
|
- The API **never exposes multitouch**
|
||||||
|
|
||||||
Esse modelo garante:
|
This model guarantees:
|
||||||
|
|
||||||
- portabilidade total
|
- total portability
|
||||||
- previsibilidade
|
- predictability
|
||||||
- ausência de ambiguidades
|
- absence of ambiguities
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 4. Espaço de Coordenadas
|
## 4. Coordinate Space
|
||||||
|
|
||||||
- As coordenadas do TOUCH usam **o mesmo espaço do framebuffer**
|
- TOUCH coordinates use **the same space as the framebuffer**
|
||||||
- Resolução: **320×180**
|
- Resolution: **320×180**
|
||||||
- Origem: canto superior esquerdo `(0,0)`
|
- Origin: top-left corner `(0,0)`
|
||||||
- Intervalos:
|
- Ranges:
|
||||||
- `x ∈ [0, 319]`
|
- `x ∈ [0, 319]`
|
||||||
- `y ∈ [0, 179]`
|
- `y ∈ [0, 179]`
|
||||||
|
|
||||||
O TOUCH é **absoluto**:
|
TOUCH is **absolute**:
|
||||||
|
|
||||||
> (x, y) representa a posição exata do contato, sem transformação dinâmica.
|
> (x, y) represents the exact position of contact, without dynamic transformation.
|
||||||
>
|
>
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 5. API do Periférico TOUCH
|
## 5. TOUCH Peripheral API
|
||||||
|
|
||||||
### 5.1 Estrutura Exposta
|
### 5.1 Exposed Structure
|
||||||
|
|
||||||
```
|
```
|
||||||
TOUCH:
|
TOUCH:
|
||||||
@ -81,182 +81,182 @@ TOUCH:
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### 5.2 Semântica dos Campos
|
### 5.2 Field Semantics
|
||||||
|
|
||||||
- **present**
|
- **present**
|
||||||
- `true` se o periférico TOUCH está disponível
|
- `true` if the TOUCH peripheral is available
|
||||||
- `false` se não houver touch físico (desktop, hardware sem touch)
|
- `false` if there is no physical touch (desktop, hardware without touch)
|
||||||
- **down**
|
- **down**
|
||||||
- `true` enquanto o ponteiro ativo está pressionado
|
- `true` while the active pointer is pressed
|
||||||
- **pressed**
|
- **pressed**
|
||||||
- `true` apenas no frame em que o ponteiro ativo foi capturado
|
- `true` only in the frame where the active pointer was captured
|
||||||
- **released**
|
- **released**
|
||||||
- `true` apenas no frame em que o ponteiro ativo foi liberado
|
- `true` only in the frame where the active pointer was released
|
||||||
- **x, y**
|
- **x, y**
|
||||||
- posição atual do ponteiro ativo
|
- current position of the active pointer
|
||||||
- válidas apenas quando `down == true`
|
- valid only when `down == true`
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 6. Política de Seleção do Ponteiro
|
## 6. Pointer Selection Policy
|
||||||
|
|
||||||
### *Single Pointer Capture Policy*
|
### *Single Pointer Capture Policy*
|
||||||
|
|
||||||
Quando múltiplos toques físicos ocorrem, o PROMETEU aplica a seguinte política:
|
When multiple physical touches occur, PROMETEU applies the following policy:
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### 6.1 Captura Inicial
|
### 6.1 Initial Capture
|
||||||
|
|
||||||
1. Se **nenhum ponteiro está ativo**
|
1. If **no pointer is active**
|
||||||
2. E ocorre um **novo toque físico**
|
2. And a **new physical touch** occurs
|
||||||
3. O **primeiro toque detectado** é capturado
|
3. The **first detected touch** is captured
|
||||||
4. Esse toque se torna o **ponteiro ativo**
|
4. This touch becomes the **active pointer**
|
||||||
|
|
||||||
Esse frame gera:
|
This frame generates:
|
||||||
|
|
||||||
- `pressed = true`
|
- `pressed = true`
|
||||||
- `down = true`
|
- `down = true`
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### 6.2 Manutenção da Captura
|
### 6.2 Capture Maintenance
|
||||||
|
|
||||||
Enquanto o ponteiro ativo estiver pressionado:
|
While the active pointer is pressed:
|
||||||
|
|
||||||
- Apenas ele é rastreado
|
- Only it is tracked
|
||||||
- Todos os outros toques físicos são ignorados
|
- All other physical touches are ignored
|
||||||
- `x, y` seguem apenas o ponteiro ativo
|
- `x, y` follow only the active pointer
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### 6.3 Liberação
|
### 6.3 Release
|
||||||
|
|
||||||
Quando o ponteiro ativo é solto:
|
When the active pointer is released:
|
||||||
|
|
||||||
- `released = true`
|
- `released = true`
|
||||||
- `down = false`
|
- `down = false`
|
||||||
- O sistema entra em estado **sem ponteiro ativo**
|
- The system enters a **no active pointer** state
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### 6.4 Recaptura (Regra Importante)
|
### 6.4 Recapture (Important Rule)
|
||||||
|
|
||||||
Após a liberação:
|
After release:
|
||||||
|
|
||||||
- Toques que **já estavam presentes** são ignorados
|
- Touches that **were already present** are ignored
|
||||||
- Um novo ponteiro só é capturado com um **novo evento de toque**
|
- A new pointer is only captured with a **new touch event**
|
||||||
|
|
||||||
> Isso evita saltos inesperados do ponteiro e ações acidentais.
|
> This avoids unexpected pointer jumps and accidental actions.
|
||||||
>
|
>
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 7. Comportamentos Deliberadamente NÃO Suportados
|
## 7. Deliberately NOT Supported Behaviors
|
||||||
|
|
||||||
O periférico TOUCH **não implementa**:
|
The TOUCH peripheral **does not implement**:
|
||||||
|
|
||||||
❌ Multitouch
|
❌ Multitouch
|
||||||
|
|
||||||
❌ Gestos (swipe, pinch, rotate, long-press)
|
❌ Gestures (swipe, pinch, rotate, long-press)
|
||||||
|
|
||||||
❌ Aceleração ou suavização
|
❌ Acceleration or smoothing
|
||||||
|
|
||||||
❌ Sensibilidade dinâmica
|
❌ Dynamic sensitivity
|
||||||
|
|
||||||
❌ Histórico implícito
|
❌ Implicit history
|
||||||
|
|
||||||
❌ Interpretação de intenção
|
❌ Intent interpretation
|
||||||
|
|
||||||
Se um jogo quiser qualquer um desses comportamentos, ele deve:
|
If a game wants any of these behaviors, it must:
|
||||||
|
|
||||||
- implementar explicitamente
|
- implement them explicitly
|
||||||
- usando apenas estado por frame
|
- using only per-frame state
|
||||||
- sem suporte implícito do hardware
|
- without implicit hardware support
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 8. “Sem Gesto” — Definição Formal
|
## 8. “No Gesture” — Formal Definition
|
||||||
|
|
||||||
O PROMETEU **não interpreta padrões temporais**.
|
PROMETEU **does not interpret temporal patterns**.
|
||||||
|
|
||||||
O periférico TOUCH **não classifica ações** como:
|
The TOUCH peripheral **does not classify actions** as:
|
||||||
|
|
||||||
- swipe
|
- swipe
|
||||||
- drag
|
- drag
|
||||||
- long press
|
- long press
|
||||||
- double tap
|
- double tap
|
||||||
|
|
||||||
Ele apenas informa:
|
It only reports:
|
||||||
|
|
||||||
- posição atual
|
- current position
|
||||||
- estado do contato
|
- contact state
|
||||||
|
|
||||||
Toda semântica é responsabilidade do jogo.
|
All semantics are the game's responsibility.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 9. “Sem Aceleração” — Definição Formal
|
## 9. “No Acceleration” — Formal Definition
|
||||||
|
|
||||||
O PROMETEU **não modifica** o input do TOUCH.
|
PROMETEU **does not modify** the TOUCH input.
|
||||||
|
|
||||||
- Nenhuma curva de sensibilidade
|
- No sensitivity curves
|
||||||
- Nenhuma amplificação por velocidade
|
- No speed-based amplification
|
||||||
- Nenhuma suavização
|
- No smoothing
|
||||||
|
|
||||||
A relação entre o toque físico e `(x, y)` é **1:1** após normalização.
|
The relationship between the physical touch and `(x, y)` is **1:1** after normalization.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 10. Integração com Outras Formas de Input
|
## 10. Integration with Other Input Forms
|
||||||
|
|
||||||
- Desktop:
|
- Desktop:
|
||||||
- mouse pode emular TOUCH
|
- mouse can emulate TOUCH
|
||||||
- Mobile:
|
- Mobile:
|
||||||
- touch físico direto
|
- direct physical touch
|
||||||
- Steam Deck:
|
- Steam Deck:
|
||||||
- touchscreen físico
|
- physical touchscreen
|
||||||
- Hardware PROMETEU:
|
- PROMETEU Hardware:
|
||||||
- touch opcional, mas suportado
|
- optional touch, but supported
|
||||||
|
|
||||||
Do ponto de vista do PROMETEU:
|
From PROMETEU's point of view:
|
||||||
|
|
||||||
> TOUCH é sempre TOUCH.
|
> TOUCH is always TOUCH.
|
||||||
>
|
>
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 11. Usos Esperados
|
## 11. Expected Uses
|
||||||
|
|
||||||
O periférico TOUCH é adequado para:
|
The TOUCH peripheral is suitable for:
|
||||||
|
|
||||||
- UI (menus, inventário, mapas)
|
- UI (menus, inventory, maps)
|
||||||
- drag-and-drop
|
- drag-and-drop
|
||||||
- seleção direta
|
- direct selection
|
||||||
- “clicar para investigar”
|
- “click to investigate”
|
||||||
- puzzles baseados em apontamento
|
- pointing-based puzzles
|
||||||
- mecânicas de rastro (ex.: Fruit Ninja-like)
|
- trail mechanics (e.g.: Fruit Ninja-like)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 12. Garantias de Portabilidade
|
## 12. Portability Guarantees
|
||||||
|
|
||||||
Todo jogo PROMETEU que utiliza TOUCH:
|
Every PROMETEU game that uses TOUCH:
|
||||||
|
|
||||||
- comporta-se de forma idêntica em todas as plataformas
|
- behaves identically on all platforms
|
||||||
- não depende de capacidades específicas do host
|
- does not depend on host-specific capabilities
|
||||||
- não sofre variação semântica entre desktop, mobile e hardware dedicado
|
- does not suffer semantic variation between desktop, mobile, and dedicated hardware
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 13. Resumo
|
## 13. Summary
|
||||||
|
|
||||||
O TOUCH no PROMETEU é:
|
The TOUCH in PROMETEU is:
|
||||||
|
|
||||||
- simples
|
- simple
|
||||||
- explícito
|
- explicit
|
||||||
- previsível
|
- predictable
|
||||||
- universal
|
- universal
|
||||||
- determinístico
|
- deterministic
|
||||||
|
|
||||||
< [Voltar](chapter-6.md) | [Sumário](table-of-contents.md) | [Adiante](chapter-8.md) >
|
< [Back](chapter-6.md) | [Summary](table-of-contents.md) | [Next](chapter-8.md) >
|
||||||
@ -1,80 +1,80 @@
|
|||||||
< [Voltar](chapter-7.md) | [Sumário](table-of-contents.md) | [Adiante](chapter-9.md) >
|
< [Back](chapter-7.md) | [Summary](table-of-contents.md) | [Next](chapter-9.md) >
|
||||||
|
|
||||||
# 📀 Periférico MEMCARD (Sistema de save/load)
|
# 📀 MEMCARD Peripheral (Save/Load System)
|
||||||
|
|
||||||
## 1. Visão Geral
|
## 1. Overview
|
||||||
|
|
||||||
O **MEMCARD** é o periférico responsável pela **persistência explícita de dados do jogo** no PROMETEU.
|
The **MEMCARD** is the peripheral responsible for the **explicit persistence of game data** in PROMETEU.
|
||||||
|
|
||||||
Ele simula o comportamento de *memory cards* clássicos (PS1, GameCube), fornecendo:
|
It simulates the behavior of classic *memory cards* (PS1, GameCube), providing:
|
||||||
|
|
||||||
- armazenamento limitado
|
- limited storage
|
||||||
- custo explícito de I/O
|
- explicit I/O cost
|
||||||
- controle total do jogo sobre quando salvar
|
- full game control over when to save
|
||||||
- portabilidade entre plataformas
|
- portability across platforms
|
||||||
|
|
||||||
O MEMCARD **não é um save state**.
|
The MEMCARD **is not a save state**.
|
||||||
|
|
||||||
Ele representa **dados que o próprio jogo decide persistir**.
|
It represents **data that the game itself decides to persist**.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 2. Princípios de Design
|
## 2. Design Principles
|
||||||
|
|
||||||
O periférico MEMCARD segue os seguintes princípios:
|
The MEMCARD peripheral follows these principles:
|
||||||
|
|
||||||
- ✅ **Persistência explícita** (nada automático)
|
- ✅ **Explicit persistence** (nothing automatic)
|
||||||
- ✅ **Tamanho limitado e conhecido**
|
- ✅ **Limited and known size**
|
||||||
- ✅ **Commit obrigatório**
|
- ✅ **Mandatory commit**
|
||||||
- ✅ **Custo de tempo (ciclos) mensurável**
|
- ✅ **Measurable time cost (cycles)**
|
||||||
- ✅ **Formato estável e documentado**
|
- ✅ **Stable and documented format**
|
||||||
- ✅ **Independente de plataforma**
|
- ✅ **Platform independent**
|
||||||
- ❌ Sem sistema de arquivos complexo (no v0.1)
|
- ❌ No complex file system (in v0.1)
|
||||||
- ❌ Sem múltiplos arquivos internos (no v0.1)
|
- ❌ No multiple internal files (in v0.1)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 3. Modelo Conceitual
|
## 3. Conceptual Model
|
||||||
|
|
||||||
Cada cartucho PROMETEU pode acessar **um ou mais slots de MEMCARD**, sendo o modelo padrão:
|
Each PROMETEU cartridge can access **one or more MEMCARD slots**, the default model being:
|
||||||
|
|
||||||
- **Slot A** — principal
|
- **Slot A** — main
|
||||||
- **Slot B** — opcional (futuro)
|
- **Slot B** — optional (future)
|
||||||
|
|
||||||
Cada slot corresponde a **um arquivo no host**:
|
Each slot corresponds to **a file on the host**:
|
||||||
|
|
||||||
```
|
```
|
||||||
MyGame_A.mem
|
MyGame_A.mem
|
||||||
MyGame_B.mem
|
MyGame_B.mem
|
||||||
```
|
```
|
||||||
|
|
||||||
O runtime monta esse arquivo como um **dispositivo de armazenamento persistente**.
|
The runtime mounts this file as a **persistent storage device**.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 4. Capacidade e CAP
|
## 4. Capacity and CAP
|
||||||
|
|
||||||
O tamanho do MEMCARD é **fixo**, definido pelo perfil de execução (CAP).
|
The size of the MEMCARD is **fixed**, defined by the execution profile (CAP).
|
||||||
|
|
||||||
### Tamanhos sugeridos
|
### Suggested sizes
|
||||||
|
|
||||||
| Perfil | Tamanho |
|
| Profile | Size |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| JAM | 8 KB |
|
| JAM | 8 KB |
|
||||||
| STANDARD | 32 KB |
|
| STANDARD | 32 KB |
|
||||||
| ADVANCED | 128 KB |
|
| ADVANCED | 128 KB |
|
||||||
|
|
||||||
O jogo **não pode exceder** esse tamanho.
|
The game **cannot exceed** this size.
|
||||||
|
|
||||||
Tentativas de escrita acima do limite resultam em erro.
|
Attempts to write above the limit result in an error.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 5. API do Periférico (v0.1)
|
## 5. Peripheral API (v0.1)
|
||||||
|
|
||||||
### 5.1 Interface Lógica
|
### 5.1 Logical Interface
|
||||||
|
|
||||||
O MEMCARD expõe uma API **simples de blob único**:
|
The MEMCARD exposes a **simple single-blob API**:
|
||||||
|
|
||||||
```
|
```
|
||||||
mem.read_all() -> byte[]
|
mem.read_all() -> byte[]
|
||||||
@ -86,92 +86,92 @@ mem.size() -> int
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### 5.2 Semântica das Operações
|
### 5.2 Operation Semantics
|
||||||
|
|
||||||
### `read_all()`
|
### `read_all()`
|
||||||
|
|
||||||
- Retorna todo o conteúdo persistido
|
- Returns all persisted content
|
||||||
- Se o cartão estiver vazio, retorna um buffer zerado
|
- If the card is empty, returns a zeroed buffer
|
||||||
- Custo em ciclos proporcional ao tamanho
|
- Cycle cost proportional to size
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### `write_all(bytes)`
|
### `write_all(bytes)`
|
||||||
|
|
||||||
- Escreve o buffer **em memória temporária**
|
- Writes the buffer **to temporary memory**
|
||||||
- Não persiste imediatamente
|
- Does not persist immediately
|
||||||
- Falha se `bytes.length > mem.size()`
|
- Fails if `bytes.length > mem.size()`
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### `commit()`
|
### `commit()`
|
||||||
|
|
||||||
- Persiste os dados no dispositivo
|
- Persists data to the device
|
||||||
- Operação **obrigatória**
|
- **Mandatory** operation
|
||||||
- Simula flush de hardware
|
- Simulates hardware flush
|
||||||
- Pode falhar (ex.: I/O, corrupção simulada)
|
- May fail (e.g., I/O, simulated corruption)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### `clear()`
|
### `clear()`
|
||||||
|
|
||||||
- Zera o conteúdo do cartão
|
- Zeroes the card content
|
||||||
- Requer `commit()` para persistir
|
- Requires `commit()` to persist
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### `size()`
|
### `size()`
|
||||||
|
|
||||||
- Retorna a capacidade total do cartão em bytes
|
- Returns total card capacity in bytes
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 6. Commit Explícito (Regra Fundamental)
|
## 6. Explicit Commit (Fundamental Rule)
|
||||||
|
|
||||||
O PROMETEU **não salva automaticamente**.
|
PROMETEU **does not save automatically**.
|
||||||
|
|
||||||
Sem `commit()`:
|
Without `commit()`:
|
||||||
|
|
||||||
- dados permanecem voláteis
|
- data remains volatile
|
||||||
- podem ser perdidos ao encerrar o jogo
|
- can be lost upon exiting the game
|
||||||
- simulam desligamento abrupto de hardware
|
- simulates abrupt hardware shutdown
|
||||||
|
|
||||||
👉 Isso ensina:
|
👉 This teaches:
|
||||||
|
|
||||||
- flush de dados
|
- data flushing
|
||||||
- atomicidade
|
- atomicity
|
||||||
- risco de corrupção
|
- risk of corruption
|
||||||
- custo real de persistência
|
- real cost of persistence
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 7. Custo de Execução (Ciclos)
|
## 7. Execution Cost (Cycles)
|
||||||
|
|
||||||
Todas as operações de MEMCARD têm custo explícito.
|
All MEMCARD operations have an explicit cost.
|
||||||
|
|
||||||
### Exemplo (valores ilustrativos)
|
### Example (illustrative values)
|
||||||
|
|
||||||
| Operação | Custo |
|
| Operation | Cost |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| read_all | 1 ciclo / 256 bytes |
|
| read_all | 1 cycle / 256 bytes |
|
||||||
| write_all | 1 ciclo / 256 bytes |
|
| write_all | 1 cycle / 256 bytes |
|
||||||
| commit | custo fixo + proporcional |
|
| commit | fixed + proportional cost |
|
||||||
|
|
||||||
Esses custos aparecem:
|
These costs appear:
|
||||||
|
|
||||||
- no profiler
|
- in the profiler
|
||||||
- na timeline de frame
|
- in the frame timeline
|
||||||
- no relatório de CAP
|
- in the CAP report
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 8. Formato do Arquivo `.mem`
|
## 8. `.mem` File Format
|
||||||
|
|
||||||
O arquivo de MEMCARD possui um formato simples e robusto.
|
The MEMCARD file has a simple and robust format.
|
||||||
|
|
||||||
### 8.1 Header
|
### 8.1 Header
|
||||||
|
|
||||||
| Campo | Tamanho |
|
| Field | Size |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| Magic (`PMEM`) | 4 bytes |
|
| Magic (`PMEM`) | 4 bytes |
|
||||||
| Version | 1 byte |
|
| Version | 1 byte |
|
||||||
@ -183,56 +183,56 @@ O arquivo de MEMCARD possui um formato simples e robusto.
|
|||||||
|
|
||||||
### 8.2 Payload
|
### 8.2 Payload
|
||||||
|
|
||||||
- Buffer binário definido pelo jogo
|
- Binary buffer defined by the game
|
||||||
- Tamanho fixo
|
- Fixed size
|
||||||
- Conteúdo interpretado apenas pelo jogo
|
- Content interpreted only by the game
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 9. Integridade e Segurança
|
## 9. Integrity and Security
|
||||||
|
|
||||||
- CRC valida corrupção
|
- CRC validates corruption
|
||||||
- Cart ID impede uso de save errado
|
- Cart ID prevents using wrong save
|
||||||
- Versão permite evolução futura do formato
|
- Version allows future format evolution
|
||||||
- Runtime pode:
|
- Runtime can:
|
||||||
- avisar corrupção
|
- warn of corruption
|
||||||
- permitir reset do cartão
|
- allow card reset
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 10. Integração com o Editor / GUI
|
## 10. Integration with the Editor / GUI
|
||||||
|
|
||||||
A ferramenta principal pode fornecer um **Memory Card Manager**:
|
The main tool can provide a **Memory Card Manager**:
|
||||||
|
|
||||||
- criar/resetar cartão
|
- create/reset card
|
||||||
- ver tamanho e uso
|
- see size and usage
|
||||||
- importar/exportar `.mem`
|
- import/export `.mem`
|
||||||
- visualizar últimos commits
|
- visualize last commits
|
||||||
- associar cartões a projetos
|
- associate cards with projects
|
||||||
|
|
||||||
Nenhuma dessas operações altera o runtime.
|
None of these operations change the runtime.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 11. Evoluções Planejadas (fora do v0.1)
|
## 11. Planned Evolutions (outside v0.1)
|
||||||
|
|
||||||
- API de blocos (`read_block`, `write_block`)
|
- Block API (`read_block`, `write_block`)
|
||||||
- múltiplos slots internos
|
- multiple internal slots
|
||||||
- wear simulation
|
- wear simulation
|
||||||
- versionamento de saves
|
- save versioning
|
||||||
- criptografia opcional (educacional)
|
- optional encryption (educational)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 12. Resumo
|
## 12. Summary
|
||||||
|
|
||||||
O periférico MEMCARD no PROMETEU:
|
The MEMCARD peripheral in PROMETEU:
|
||||||
|
|
||||||
- simula hardware real
|
- simulates real hardware
|
||||||
- força decisões de design
|
- forces design decisions
|
||||||
- ensina persistência corretamente
|
- teaches persistence correctly
|
||||||
- é simples de usar
|
- is simple to use
|
||||||
- é difícil de abusar
|
- is hard to abuse
|
||||||
- cresce sem quebrar compatibilidade
|
- grows without breaking compatibility
|
||||||
|
|
||||||
< [Voltar](chapter-7.md) | [Sumário](table-of-contents.md) | [Adiante](chapter-9.md) >
|
< [Back](chapter-7.md) | [Summary](table-of-contents.md) | [Next](chapter-9.md) >
|
||||||
@ -1,175 +1,175 @@
|
|||||||
< [Voltar](chapter-8.md) | [Sumário](table-of-contents.md) | [Adiante](chapter-10.md) >
|
< [Back](chapter-8.md) | [Summary](table-of-contents.md) | [Next](chapter-10.md) >
|
||||||
|
|
||||||
# ⚡ **Eventos e Interrupções**
|
# ⚡ **Events and Interrupts**
|
||||||
|
|
||||||
## 1. Visão Geral
|
## 1. Overview
|
||||||
|
|
||||||
PROMETEU distingue claramente **execução normal**, **eventos** e **interrupções**.
|
PROMETEU clearly distinguishes between **normal execution**, **events**, and **interrupts**.
|
||||||
|
|
||||||
Nada ocorre “fora do tempo”.
|
Nothing occurs "out of time".
|
||||||
|
|
||||||
Nada interrompe o sistema sem custo.
|
Nothing interrupts the system without cost.
|
||||||
|
|
||||||
Nada acontece sem um ponto bem definido no ciclo de execução.
|
Nothing happens without a well-defined point in the execution cycle.
|
||||||
|
|
||||||
> Eventos são sinais.
|
> Events are signals.
|
||||||
Interrupções são decisões da máquina.
|
> Interrupts are machine decisions.
|
||||||
>
|
>
|
||||||
|
|
||||||
Este capítulo define:
|
This chapter defines:
|
||||||
|
|
||||||
- o que PROMETEU considera um evento
|
- what PROMETEU considers an event
|
||||||
- como interrupções são modeladas
|
- how interrupts are modeled
|
||||||
- quando elas podem ocorrer
|
- when they can occur
|
||||||
- como se relacionam com ciclos, CAP e determinismo
|
- how they relate to cycles, CAP, and determinism
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 2. Filosofia de Eventos em PROMETEU
|
## 2. Event Philosophy in PROMETEU
|
||||||
|
|
||||||
PROMETEU **não utiliza callbacks assíncronos invisíveis**.
|
PROMETEU **does not use invisible asynchronous callbacks**.
|
||||||
|
|
||||||
Todo evento:
|
Every event:
|
||||||
|
|
||||||
- é registrado
|
- is registered
|
||||||
- é entregue em momento previsível
|
- is delivered at a predictable moment
|
||||||
- é tratado dentro do loop principal
|
- is handled within the main loop
|
||||||
|
|
||||||
Esse modelo evita:
|
This model avoids:
|
||||||
|
|
||||||
- concorrência implícita
|
- implicit concurrency
|
||||||
- race conditions ocultas
|
- hidden race conditions
|
||||||
- efeitos colaterais não determinísticos
|
- non-deterministic side effects
|
||||||
|
|
||||||
PROMETEU favorece:
|
PROMETEU favors:
|
||||||
|
|
||||||
> controle explícito sobre reatividade.
|
> explicit control over reactivity.
|
||||||
>
|
>
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 3. Eventos
|
## 3. Events
|
||||||
|
|
||||||
### 3.1 Definição
|
### 3.1 Definition
|
||||||
|
|
||||||
Um **evento** em PROMETEU é um **sinal lógico** gerado pelo sistema ou pelo programa, que indica que algo ocorreu.
|
An **event** in PROMETEU is a **logical signal** generated by the system or the program, indicating that something has occurred.
|
||||||
|
|
||||||
Exemplos de eventos:
|
Examples of events:
|
||||||
|
|
||||||
- fim de frame
|
- end of frame
|
||||||
- timer expirado
|
- timer expired
|
||||||
- troca de estado do sistema
|
- system state change
|
||||||
- erro de execução
|
- execution error
|
||||||
|
|
||||||
Eventos **não executam código automaticamente**.
|
Events **do not execute code automatically**.
|
||||||
|
|
||||||
Eles apenas **informam**.
|
They only **inform**.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### 3.2 Fila de Eventos
|
### 3.2 Event Queue
|
||||||
|
|
||||||
PROMETEU mantém uma **fila de eventos**:
|
PROMETEU maintains an **event queue**:
|
||||||
|
|
||||||
- eventos são enfileirados
|
- events are queued
|
||||||
- a fila é processada em ordem
|
- the queue is processed in order
|
||||||
- o processamento ocorre em pontos definidos do frame
|
- processing occurs at defined points in the frame
|
||||||
|
|
||||||
Eventos:
|
Events:
|
||||||
|
|
||||||
- não interrompem execução arbitrariamente
|
- do not interrupt execution arbitrarily
|
||||||
- não executam fora do loop
|
- do not execute outside the loop
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 4. Interrupções
|
## 4. Interrupts
|
||||||
|
|
||||||
### 4.1 Definição
|
### 4.1 Definition
|
||||||
|
|
||||||
Uma **interrupção** é um evento especial, tratado pelo sistema como **prioritário**, que pode:
|
An **interrupt** is a special event, treated by the system as **priority**, which can:
|
||||||
|
|
||||||
- alterar o fluxo normal de execução
|
- change the normal flow of execution
|
||||||
- executar código específico do sistema
|
- execute specific system code
|
||||||
- impactar ciclos e orçamento
|
- impact cycles and budget
|
||||||
|
|
||||||
Interrupções são **raras e explícitas**.
|
Interrupts are **rare and explicit**.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### 4.2 O que NÃO é uma interrupção
|
### 4.2 What is NOT an interrupt
|
||||||
|
|
||||||
Em PROMETEU, **não são interrupções**:
|
In PROMETEU, the following are **not interrupts**:
|
||||||
|
|
||||||
- input de botão
|
- button input
|
||||||
- colisões
|
- collisions
|
||||||
- timers comuns
|
- common timers
|
||||||
- lógica de jogo
|
- game logic
|
||||||
|
|
||||||
Esses são tratados como **estado ou eventos normais**.
|
These are treated as **state or normal events**.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 5. Tipos de Interrupções em PROMETEU
|
## 5. Types of Interrupts in PROMETEU
|
||||||
|
|
||||||
PROMETEU define um conjunto pequeno e bem controlado de interrupções.
|
PROMETEU defines a small and well-controlled set of interrupts.
|
||||||
|
|
||||||
### 5.1 Interrupção de Frame (VBlank Conceitual)
|
### 5.1 Frame Interrupt (Conceptual VBlank)
|
||||||
|
|
||||||
O final de cada frame gera uma **interrupção lógica de sincronização**, responsável por:
|
The end of each frame generates a **logical synchronization interrupt**, responsible for:
|
||||||
|
|
||||||
- swap de framebuffer
|
- framebuffer swap
|
||||||
- commit de áudio
|
- audio commit
|
||||||
- sincronização de estado
|
- state synchronization
|
||||||
|
|
||||||
Essa interrupção:
|
This interrupt:
|
||||||
|
|
||||||
- ocorre no SYNC
|
- occurs at SYNC
|
||||||
- tem custo fixo
|
- has a fixed cost
|
||||||
- não executa código do usuário
|
- does not execute user code
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### 5.2 Interrupção de Sistema
|
### 5.2 System Interrupt
|
||||||
|
|
||||||
Gerada por condições excepcionais:
|
Generated by exceptional conditions:
|
||||||
|
|
||||||
- erro fatal de VM
|
- fatal VM error
|
||||||
- violação de memória
|
- memory violation
|
||||||
- instrução inválida
|
- invalid instruction
|
||||||
|
|
||||||
Resultado:
|
Result:
|
||||||
|
|
||||||
- execução é interrompida
|
- execution is halted
|
||||||
- estado da VM é preservado
|
- VM state is preserved
|
||||||
- relatório detalhado é gerado
|
- detailed report is generated
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### 5.3 Interrupções Temporizadas (Timers)
|
### 5.3 Timed Interrupts (Timers)
|
||||||
|
|
||||||
PROMETEU pode oferecer **timers do sistema**, modelados como:
|
PROMETEU can offer **system timers**, modeled as:
|
||||||
|
|
||||||
- contadores baseados em frames
|
- counters based on frames
|
||||||
- sinais gerados ao atingir zero
|
- signals generated upon reaching zero
|
||||||
|
|
||||||
Timers:
|
Timers:
|
||||||
|
|
||||||
- não disparam código automaticamente
|
- do not trigger code automatically
|
||||||
- geram eventos consultáveis
|
- generate queryable events
|
||||||
|
|
||||||
Exemplo conceitual:
|
Conceptual example:
|
||||||
|
|
||||||
```
|
```
|
||||||
if (timer.expired(T1)) {
|
if (timer.expired(T1)) {
|
||||||
// tratar evento
|
// handle event
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 6. Relação entre Eventos, Interrupções e o Loop
|
## 6. Relationship between Events, Interrupts, and the Loop
|
||||||
|
|
||||||
O fluxo completo pode ser representado assim:
|
The complete flow can be represented as follows:
|
||||||
|
|
||||||
```
|
```
|
||||||
FRAME N
|
FRAME N
|
||||||
@ -184,23 +184,23 @@ SYNC
|
|||||||
──────────────
|
──────────────
|
||||||
```
|
```
|
||||||
|
|
||||||
Importante:
|
Important:
|
||||||
|
|
||||||
- eventos são processados antes da lógica principal
|
- events are processed before main logic
|
||||||
- interrupções ocorrem apenas em pontos seguros
|
- interrupts occur only at safe points
|
||||||
- nenhuma interrupção ocorre “no meio” de uma instrução
|
- no interrupt occurs "in the middle" of an instruction
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 7. Custos e Orçamento
|
## 7. Costs and Budget
|
||||||
|
|
||||||
Eventos e interrupções:
|
Events and interrupts:
|
||||||
|
|
||||||
- consomem ciclos
|
- consume cycles
|
||||||
- participam do CAP
|
- participate in the CAP
|
||||||
- aparecem na certificação
|
- appear in certification
|
||||||
|
|
||||||
Exemplo de relatório:
|
Example report:
|
||||||
|
|
||||||
```
|
```
|
||||||
Frame 18231:
|
Frame 18231:
|
||||||
@ -208,82 +208,82 @@ Event processing:120cycles
|
|||||||
VBlank interrupt:80cycles
|
VBlank interrupt:80cycles
|
||||||
```
|
```
|
||||||
|
|
||||||
Nada é gratuito.
|
Nothing is free.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 8. Determinismo e Reprodutibilidade
|
## 8. Determinism and Reproducibility
|
||||||
|
|
||||||
PROMETEU garante:
|
PROMETEU guarantees:
|
||||||
|
|
||||||
- mesma sequência de eventos → mesmo comportamento
|
- same sequence of events → same behavior
|
||||||
- interrupções sempre no mesmo ponto do frame
|
- interrupts always at the same point in the frame
|
||||||
- timers baseados em frame count, não em tempo real
|
- timers based on frame count, not real time
|
||||||
|
|
||||||
Isso permite:
|
This allows:
|
||||||
|
|
||||||
- replays confiáveis
|
- reliable replays
|
||||||
- debugging preciso
|
- precise debugging
|
||||||
- certificação justa
|
- fair certification
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 9. Boas Práticas
|
## 9. Best Practices
|
||||||
|
|
||||||
PROMETEU incentiva:
|
PROMETEU encourages:
|
||||||
|
|
||||||
- tratar eventos como dados
|
- treating events as data
|
||||||
- consultar eventos explicitamente
|
- querying events explicitly
|
||||||
- evitar lógica pesada em handlers
|
- avoiding heavy logic in handlers
|
||||||
- usar timers em vez de polling excessivo
|
- using timers instead of excessive polling
|
||||||
|
|
||||||
PROMETEU desencoraja:
|
PROMETEU discourages:
|
||||||
|
|
||||||
- simular callbacks assíncronos
|
- simulating asynchronous callbacks
|
||||||
- depender de ordem implícita
|
- depending on implicit order
|
||||||
- usar eventos como “atalho” para lógica complexa
|
- using events as a "shortcut" for complex logic
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 10. Relação com Microcontroladores
|
## 10. Relationship with Microcontrollers
|
||||||
|
|
||||||
O modelo reflete MCUs reais:
|
The model reflects real MCUs:
|
||||||
|
|
||||||
| MCU | PROMETEU |
|
| MCU | PROMETEU |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| ISR | Interrupção explícita |
|
| ISR | Explicit interrupt |
|
||||||
| Loop principal | Loop PROMETEU |
|
| Main Loop | PROMETEU Loop |
|
||||||
| Flags | Eventos |
|
| Flags | Events |
|
||||||
| Timers | Timers por frame |
|
| Timers | Per-frame timers |
|
||||||
|
|
||||||
Mas sem:
|
But without:
|
||||||
|
|
||||||
- concorrência real
|
- real concurrency
|
||||||
- interrupções imprevisíveis
|
- unpredictable interrupts
|
||||||
|
|
||||||
PROMETEU **ensina o conceito**, não o caos.
|
PROMETEU **teaches the concept**, not the chaos.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 11. Implicações Pedagógicas
|
## 11. Pedagogical Implications
|
||||||
|
|
||||||
Este modelo permite ensinar:
|
This model allows teaching:
|
||||||
|
|
||||||
- diferença entre evento e interrupção
|
- the difference between event and interrupt
|
||||||
- sincronização segura
|
- safe synchronization
|
||||||
- controle de fluxo em sistemas reativos
|
- flow control in reactive systems
|
||||||
- impacto de decisões temporais
|
- the impact of temporal decisions
|
||||||
|
|
||||||
Tudo com **ordem, clareza e mensuração**.
|
Everything with **order, clarity, and measurement**.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 12. Resumo
|
## 12. Summary
|
||||||
|
|
||||||
- eventos informam, não executam
|
- events inform, they do not execute
|
||||||
- interrupções são raras e controladas
|
- interrupts are rare and controlled
|
||||||
- nenhuma execução ocorre fora do loop
|
- no execution occurs outside the loop
|
||||||
- custos são explícitos
|
- costs are explicit
|
||||||
- comportamento é determinístico
|
- behavior is deterministic
|
||||||
|
|
||||||
< [Voltar](chapter-8.md) | [Sumário](table-of-contents.md) | [Adiante](chapter-10.md) >
|
< [Back](chapter-8.md) | [Summary](table-of-contents.md) | [Next](chapter-10.md) >
|
||||||
@ -1,19 +1,19 @@
|
|||||||
# Table of Contents
|
# Table of Contents
|
||||||
|
|
||||||
- [Capitulo 1: Modelo de Tempo e Ciclos](chapter-1.md)
|
- [Chapter 1: Time Model and Cycles](chapter-1.md)
|
||||||
- [Capitulo 2: PROMETEU VM Instruction Set](chapter-2.md)
|
- [Chapter 2: PROMETEU VM Instruction Set](chapter-2.md)
|
||||||
- [Capitulo 3: Memória: Stack, Heap e Alocação](chapter-3.md)
|
- [Chapter 3: Memory: Stack, Heap, and Allocation](chapter-3.md)
|
||||||
- [Capitulo 4: Periférico GFX (Sistema Gráfico)](chapter-4.md)
|
- [Chapter 4: GFX Peripheral (Graphics System)](chapter-4.md)
|
||||||
- [Capitulo 5: Periférico AUDIO (Sistema de Áudio)](chapter-5.md)
|
- [Chapter 5: AUDIO Peripheral (Audio System)](chapter-5.md)
|
||||||
- [Capitulo 6: Periférico INPUT (Sistema de Entrada)](chapter-6.md)
|
- [Chapter 6: INPUT Peripheral (Input System)](chapter-6.md)
|
||||||
- [Capitulo 7: Periférico TOUCH (Sistema de Entrada via ponteiro absoluto)](chapter-7.md)
|
- [Chapter 7: TOUCH Peripheral (Absolute Pointer Input System)](chapter-7.md)
|
||||||
- [Capitulo 8: Periférico MEMCARD (Sistema de save/load)](chapter-8.md)
|
- [Chapter 8: MEMCARD Peripheral (Save/Load System)](chapter-8.md)
|
||||||
- [Capitulo 9: Eventos e Interrupções](chapter-9.md)
|
- [Chapter 9: Events and Interrupts](chapter-9.md)
|
||||||
- [Capitulo 10: Debug, Inspeção e Profiling](chapter-10.md)
|
- [Chapter 10: Debug, Inspection, and Profiling](chapter-10.md)
|
||||||
- [Capitulo 11: Garantias de Portabilidade e Execução Multiplataforma](chapter-11.md)
|
- [Chapter 11: Portability Guarantees and Cross-Platform Execution](chapter-11.md)
|
||||||
- [Capitulo 12: Firmware — PrometeuOS (POS) + PrometeuHub](chapter-12.md)
|
- [Chapter 12: Firmware — PrometeuOS (POS) + PrometeuHub](chapter-12.md)
|
||||||
- [Capitulo 13: Cartucho](chapter-13.md)
|
- [Chapter 13: Cartridge](chapter-13.md)
|
||||||
- [Capitulo 14: Boot Profiles](chapter-14.md)
|
- [Chapter 14: Boot Profiles](chapter-14.md)
|
||||||
|
|
||||||
---
|
---
|
||||||
[Voltar para o README](../README.md)
|
[Back to README](../README.md)
|
||||||
@ -1,26 +1,26 @@
|
|||||||
# PROMETEU Test Cartridges
|
# PROMETEU Test Cartridges
|
||||||
|
|
||||||
Este diretório contém cartuchos de exemplo e suítes de teste para validar o comportamento do runtime e das ferramentas de desenvolvimento do PROMETEU.
|
This directory contains example cartridges and test suites to validate the behavior of the PROMETEU runtime and development tools.
|
||||||
|
|
||||||
## Cartuchos Disponíveis
|
## Available Cartridges
|
||||||
|
|
||||||
### 🟩 [color-square](./color-square)
|
### 🟩 [color-square](./color-square)
|
||||||
Um cartucho simples que demonstra:
|
A simple cartridge that demonstrates:
|
||||||
- Inicialização do sistema.
|
- System initialization.
|
||||||
- Renderização de um quadrado colorido no framebuffer.
|
- Rendering a colored square in the framebuffer.
|
||||||
- Loop básico de execução.
|
- Basic execution loop.
|
||||||
|
|
||||||
## Estrutura de um Cartucho
|
## Cartridge Structure
|
||||||
|
|
||||||
Um cartucho PROMETEU (em sua forma descompactada) geralmente consiste em:
|
A PROMETEU cartridge (in its unpacked form) generally consists of:
|
||||||
- `manifest.json`: Metadados do aplicativo (ID, título, versão, modo).
|
- `manifest.json`: Application metadata (ID, title, version, mode).
|
||||||
- `program.pbc`: O bytecode compilado para a VM do PROMETEU.
|
- `program.pbc`: Compiled bytecode for the PROMETEU VM.
|
||||||
- `assets/`: Recursos como tiles, sprites e amostras de áudio.
|
- `assets/`: Resources such as tiles, sprites, and audio samples.
|
||||||
|
|
||||||
## Como usar
|
## How to use
|
||||||
|
|
||||||
Você pode rodar qualquer um destes cartuchos usando a CLI principal:
|
You can run any of these cartridges using the main CLI:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
prometeu run test-cartridges/<nome_do_cartucho>
|
prometeu run test-cartridges/<cartridge_name>
|
||||||
```
|
```
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user