1 个不稳定版本
0.0.1 | 2022年5月16日 |
---|
#54 in #gameboy
765KB
5K SLoC
Padme 核心库
像素点阵模拟器
padme-core 是一个 Gameboy 模拟器引擎。它本身不依赖于 libstd 或动态内存,这使得它在任何嵌入式平台或 [https://github.com/alexlren/padme-browser web assembly](https://github.com/alexlren/padme-browser) 中更容易使用。
测试
用于快速单元/集成/文档测试
cargo test
对于更昂贵的测试,你可以使用
cargo test -- --ignored
或运行所有测试
cargo test -- --include-ignored
示例
- 创建你的硬件组件:一个屏幕、一个扬声器和串行输出
这些组件应针对您的平台特定。
use padme_core::{AudioSpeaker, Button, Pixel, Rom, Screen, SerialOutput, System};
struct MyScreen {
// ... your framebuffer implementation
}
impl Screen for MyScreen {
fn set_pixel(&mut self, pixel: &Pixel, x: u8, y: u8) {
// add pixel to your framebuffer
}
}
struct MySpeaker {
// ... your audio buffer implementation
}
impl AudioSpeaker for MySpeaker {
fn set_samples(&mut self, left: f32, right: f32) {
// add samples for left and right channels
}
}
struct MySerialConsole {
}
impl SerialOutput for MySerialConsole {
fn putchar(&mut self, ch: u8) {
// add char to
}
}
或者,如果您不需要/想要这些组件中的一些,则可以使用空版本
use padme::default::{NoScreen, NoSerial, NoSpeaker};
- 加载一个 rom
use padme_core::Rom;
let bin: Vec<u8> = std::fs::read("some_game.gb").expect("could not find game");
let mut rom = Rom::load(bin).unwrap();
- 创建您的模拟器并运行它
use std::time::Instant;
use std::thread::sleep;
let mut emulator = System::new(rom, MyScreen, MySerialConsole, MySpeaker);
// Set the number of frame per seconds
// This also sets the number of cycles needed per frame given the fixed CPU clock frequency
emulator.set_frame_rate(60);
while running {
// We need to know how much time it took to display a frame
let t0 = Instant::now();
// This executes all the cycles needed to display one frame
emulator.update_frame();
// Deal with button inputs
emulator.set_button(Button::A, a_pressed);
emulator.set_button(Button::B, b_pressed);
emulator.set_button(Button::Start, start_pressed);
emulator.set_button(Button::Select, select_pressed);
emulator.set_button(Button::Up, up_pressed);
emulator.set_button(Button::Down, down_pressed);
emulator.set_button(Button::Left, left_pressed);
emulator.set_button(Button::Right, right_pressed);
// Now we just need to wait the remaining time before the next frame
// This is because we need to keep ~60 frames / second
let frame_time = t0.elapsed();
let min_frame_time = emulator.min_frame_time();
if frame_time < min_frame_time {
sleep(min_frame_time - frame_time);
}
}
或者,您可能希望自行执行这些步骤
use padme_core::{CLOCK_SPEED};
let cycles_per_frame = CLOCK_SPEED / 60;
let mut cycles = 0u32;
while cycles < cycles_per_frame {
cycles += emulator.step() as u32;
}
emulator.screen().update();
要查看一些实现,请查看 [https://github.com/alexlren/padme-demo padme-demo](https://github.com/alexlren/padme-demo),一个桌面演示或 [https://github.com/alexlren/padme-browser padme-browser](https://github.com/alexlren/padme-browser),一个 web assembly 版本。
功能
- no_std
- 定时器
- DMA
- CPU 汇编器
- 带 fifo 的像素处理器单元
- 外部屏幕
- 外部串行端口
- 手柄
- ROM、MBC1、MBC3
- 集成测试
- 音频处理单元
待办事项
- 添加对 MBC2、MBC4、MBC5、MBC6、MBC7 的支持
- 为每个模块添加单元测试