Padme core

Pixel As Dot-Matrix Emulator

padme-core is a Gameboy emulator engine. It itself doesn't rely on libstd or on dynamic memory, which makes it easier to use in any embedded platforms or web assembly.

Tests

For fast unit / integration / doc tests:

cargo test

For more expensive tests, you can use:

cargo test -- --ignored

or run all tests with:

cargo test -- --include-ignored

Examples

  1. Create your hardware components: a screen, a speaker and a serial output

These components should be specific to your platform.

```rust 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 } } ```

Alternatively, if you don't need / want some of these components, it's possible to use empty versions:

rust use padme::default::{NoScreen, NoSerial, NoSpeaker};

  1. Load a rom

```rust use padme_core::Rom;

let bin: Vec = std::fs::read("some_game.gb").expect("could not find game"); let mut rom = Rom::load(bin).unwrap(); ```

  1. Create your emulator and run it

```rust 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.setframerate(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.updateframe(); // Deal with button inputs emulator.setbutton(Button::A, apressed); emulator.setbutton(Button::B, bpressed); emulator.setbutton(Button::Start, startpressed); emulator.setbutton(Button::Select, selectpressed); emulator.setbutton(Button::Up, uppressed); emulator.setbutton(Button::Down, downpressed); emulator.setbutton(Button::Left, leftpressed); emulator.setbutton(Button::Right, rightpressed); // Now we just need to wait the remaining time before the next frame // This is because we need to keep ~60 frames / second let frametime = t0.elapsed(); let minframetime = emulator.minframetime(); if frametime < minframetime { sleep(minframetime - frametime); } } ```

Alternatively, you may want to execute the steps yourself:

```rust use padmecore::{CLOCKSPEED};

let cyclesperframe = CLOCKSPEED / 60; let mut cycles = 0u32; while cycles < cyclesper_frame { cycles += emulator.step() as u32; } emulator.screen().update(); ```

To see some implementations, check out padme-demo, a desktop demo or padme-browser, a web assembly version.

Features

Todo