add native_interface
This commit is contained in:
parent
760189929a
commit
cbb9b93ce1
@ -2,5 +2,6 @@ pub mod machine;
|
||||
pub mod peripherals;
|
||||
pub mod vm;
|
||||
mod model;
|
||||
mod native_interface;
|
||||
|
||||
pub use machine::Machine;
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
use crate::model::{Color, Sample, Cartridge};
|
||||
use crate::peripherals::{Gfx, InputSignals, Pad, Touch, Audio};
|
||||
use crate::vm::{VirtualMachine, NativeInterface, Value};
|
||||
use crate::model::{Cartridge, Color, Sample};
|
||||
use crate::peripherals::{Audio, Gfx, InputSignals, Pad, Touch};
|
||||
use crate::vm::VirtualMachine;
|
||||
use std::sync::Arc;
|
||||
|
||||
/// PROMETEU "hardware lógico" (v0).
|
||||
@ -21,123 +21,13 @@ pub struct Machine {
|
||||
pub sample_snare: Option<Arc<Sample>>,
|
||||
}
|
||||
|
||||
impl NativeInterface for Machine {
|
||||
fn call(&mut self, id: u32, vm: &mut VirtualMachine) -> Result<u64, String> {
|
||||
match id {
|
||||
// system.has_cart() -> bool
|
||||
0x0001 => {
|
||||
vm.push(Value::Boolean(self.cartridge.is_some()));
|
||||
Ok(10)
|
||||
}
|
||||
// system.run_cart()
|
||||
0x0002 => {
|
||||
if let Some(cart) = self.cartridge.as_ref() {
|
||||
vm.rom = cart.rom.clone();
|
||||
vm.constant_pool = cart.constant_pool.clone();
|
||||
vm.pc = 0;
|
||||
vm.operand_stack.clear();
|
||||
vm.call_stack.clear();
|
||||
vm.halted = false;
|
||||
} else {
|
||||
return Err("No cartridge inserted".into());
|
||||
}
|
||||
Ok(100)
|
||||
}
|
||||
// gfx.clear(color_index)
|
||||
0x1001 => {
|
||||
let color_idx = vm.pop_integer()? as usize;
|
||||
let color = self.get_color(color_idx);
|
||||
self.gfx.clear(color);
|
||||
Ok(100)
|
||||
}
|
||||
// gfx.draw_rect(x, y, w, h, color_index)
|
||||
0x1002 => {
|
||||
let color_idx = vm.pop_integer()? as usize;
|
||||
let h = vm.pop_integer()? as i32;
|
||||
let w = vm.pop_integer()? as i32;
|
||||
let y = vm.pop_integer()? as i32;
|
||||
let x = vm.pop_integer()? as i32;
|
||||
let color = self.get_color(color_idx);
|
||||
self.gfx.fill_rect(x, y, w, h, color);
|
||||
Ok(200)
|
||||
}
|
||||
// input.get_pad(button_id) -> bool
|
||||
0x2001 => {
|
||||
let button_id = vm.pop_integer()? as u32;
|
||||
let is_down = self.is_button_down(button_id);
|
||||
vm.push(Value::Boolean(is_down));
|
||||
Ok(50)
|
||||
}
|
||||
// audio.play_sample(sample_id, voice_id, volume, pan, pitch)
|
||||
// sample_id: 0=square, 1=kick, 2=snare
|
||||
0x3001 => {
|
||||
let pitch = vm.pop_number()?;
|
||||
let pan = vm.pop_integer()? as u8;
|
||||
let volume = vm.pop_integer()? as u8;
|
||||
let voice_id = vm.pop_integer()? as usize;
|
||||
let sample_id = vm.pop_integer()? as u32;
|
||||
|
||||
let sample = match sample_id {
|
||||
0 => self.sample_square.clone(),
|
||||
1 => self.sample_kick.clone(),
|
||||
2 => self.sample_snare.clone(),
|
||||
_ => None,
|
||||
};
|
||||
|
||||
if let Some(s) = sample {
|
||||
self.audio.play(s, voice_id, volume, pan, pitch, 0, crate::peripherals::LoopMode::Off);
|
||||
}
|
||||
Ok(300)
|
||||
}
|
||||
_ => Err(format!("Unknown native call: 0x{:08X}", id)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Machine {
|
||||
pub const W: usize = 320;
|
||||
pub const H: usize = 180;
|
||||
pub const CYCLES_PER_FRAME: u64 = 100_000; // Exemplo de budget
|
||||
|
||||
fn get_color(&self, index: usize) -> Color {
|
||||
// Implementação simplificada: se houver bancos, usa a paleta do banco 0
|
||||
// Caso contrário, usa cores básicas fixas
|
||||
if let Some(bank) = self.gfx.banks[0].as_ref() {
|
||||
bank.palettes[0][index % 16]
|
||||
} else {
|
||||
match index % 16 {
|
||||
0 => Color::BLACK,
|
||||
1 => Color::WHITE,
|
||||
2 => Color::RED,
|
||||
3 => Color::GREEN,
|
||||
4 => Color::BLUE,
|
||||
5 => Color::YELLOW,
|
||||
6 => Color::CYAN,
|
||||
7 => Color::INDIGO,
|
||||
8 => Color::GRAY,
|
||||
_ => Color::BLACK,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn is_button_down(&self, id: u32) -> bool {
|
||||
match id {
|
||||
0 => self.pad.up.down,
|
||||
1 => self.pad.down.down,
|
||||
2 => self.pad.left.down,
|
||||
3 => self.pad.right.down,
|
||||
4 => self.pad.a.down,
|
||||
5 => self.pad.b.down,
|
||||
6 => self.pad.x.down,
|
||||
7 => self.pad.y.down,
|
||||
8 => self.pad.l.down,
|
||||
9 => self.pad.r.down,
|
||||
10 => self.pad.start.down,
|
||||
11 => self.pad.select.down,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new() -> Self {
|
||||
let mut machine = Self {
|
||||
gfx: Gfx::new(Self::W, Self::H),
|
||||
@ -159,6 +49,45 @@ impl Machine {
|
||||
machine
|
||||
}
|
||||
|
||||
pub fn get_color(&self, index: usize) -> Color {
|
||||
// Implementação simplificada: se houver bancos, usa a paleta do banco 0
|
||||
// Caso contrário, usa cores básicas fixas
|
||||
if let Some(bank) = self.gfx.banks[0].as_ref() {
|
||||
bank.palettes[0][index % 16]
|
||||
} else {
|
||||
match index % 16 {
|
||||
0 => Color::BLACK,
|
||||
1 => Color::WHITE,
|
||||
2 => Color::RED,
|
||||
3 => Color::GREEN,
|
||||
4 => Color::BLUE,
|
||||
5 => Color::YELLOW,
|
||||
6 => Color::CYAN,
|
||||
7 => Color::INDIGO,
|
||||
8 => Color::GRAY,
|
||||
_ => Color::BLACK,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_button_down(&self, id: u32) -> bool {
|
||||
match id {
|
||||
0 => self.pad.up.down,
|
||||
1 => self.pad.down.down,
|
||||
2 => self.pad.left.down,
|
||||
3 => self.pad.right.down,
|
||||
4 => self.pad.a.down,
|
||||
5 => self.pad.b.down,
|
||||
6 => self.pad.x.down,
|
||||
7 => self.pad.y.down,
|
||||
8 => self.pad.l.down,
|
||||
9 => self.pad.r.down,
|
||||
10 => self.pad.start.down,
|
||||
11 => self.pad.select.down,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn load_cartridge(&mut self, cart: Cartridge) {
|
||||
self.cartridge = Some(cart);
|
||||
}
|
||||
|
||||
75
crates/core/src/native_interface.rs
Normal file
75
crates/core/src/native_interface.rs
Normal file
@ -0,0 +1,75 @@
|
||||
use crate::Machine;
|
||||
use crate::vm::{NativeInterface, Value, VirtualMachine};
|
||||
|
||||
impl NativeInterface for Machine {
|
||||
fn call(&mut self, id: u32, vm: &mut VirtualMachine) -> Result<u64, String> {
|
||||
match id {
|
||||
// system.has_cart() -> bool
|
||||
0x0001 => {
|
||||
vm.push(Value::Boolean(self.cartridge.is_some()));
|
||||
Ok(10)
|
||||
}
|
||||
// system.run_cart()
|
||||
0x0002 => {
|
||||
if let Some(cart) = self.cartridge.as_ref() {
|
||||
vm.rom = cart.rom.clone();
|
||||
vm.constant_pool = cart.constant_pool.clone();
|
||||
vm.pc = 0;
|
||||
vm.operand_stack.clear();
|
||||
vm.call_stack.clear();
|
||||
vm.halted = false;
|
||||
} else {
|
||||
return Err("No cartridge inserted".into());
|
||||
}
|
||||
Ok(100)
|
||||
}
|
||||
// gfx.clear(color_index)
|
||||
0x1001 => {
|
||||
let color_idx = vm.pop_integer()? as usize;
|
||||
let color = self.get_color(color_idx);
|
||||
self.gfx.clear(color);
|
||||
Ok(100)
|
||||
}
|
||||
// gfx.draw_rect(x, y, w, h, color_index)
|
||||
0x1002 => {
|
||||
let color_idx = vm.pop_integer()? as usize;
|
||||
let h = vm.pop_integer()? as i32;
|
||||
let w = vm.pop_integer()? as i32;
|
||||
let y = vm.pop_integer()? as i32;
|
||||
let x = vm.pop_integer()? as i32;
|
||||
let color = self.get_color(color_idx);
|
||||
self.gfx.fill_rect(x, y, w, h, color);
|
||||
Ok(200)
|
||||
}
|
||||
// input.get_pad(button_id) -> bool
|
||||
0x2001 => {
|
||||
let button_id = vm.pop_integer()? as u32;
|
||||
let is_down = self.is_button_down(button_id);
|
||||
vm.push(Value::Boolean(is_down));
|
||||
Ok(50)
|
||||
}
|
||||
// audio.play_sample(sample_id, voice_id, volume, pan, pitch)
|
||||
// sample_id: 0=square, 1=kick, 2=snare
|
||||
0x3001 => {
|
||||
let pitch = vm.pop_number()?;
|
||||
let pan = vm.pop_integer()? as u8;
|
||||
let volume = vm.pop_integer()? as u8;
|
||||
let voice_id = vm.pop_integer()? as usize;
|
||||
let sample_id = vm.pop_integer()? as u32;
|
||||
|
||||
let sample = match sample_id {
|
||||
0 => self.sample_square.clone(),
|
||||
1 => self.sample_kick.clone(),
|
||||
2 => self.sample_snare.clone(),
|
||||
_ => None,
|
||||
};
|
||||
|
||||
if let Some(s) = sample {
|
||||
self.audio.play(s, voice_id, volume, pan, pitch, 0, crate::peripherals::LoopMode::Off);
|
||||
}
|
||||
Ok(300)
|
||||
}
|
||||
_ => Err(format!("Unknown native call: 0x{:08X}", id)),
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user