CONNECTING...

Getting Started

Create games for Emberware hardware

Making games for Emberware hardware means working within the constraints of real (if obscure) hardware. This guide covers ZX development. Support for Chroma and z is coming.

Prerequisites

Before you start, make sure you have:

  • Rust installed (rustup.rs)
  • A code editor (VS Code, Sublime, Vim, whatever you prefer)
  • Basic programming knowledge (any language is fine)
  • An Emberware account for uploading games
1

Install the Emberware SDK

Clone the Emberware repository and build the development tools:

git clone https://github.com/emberware-io/emberware.git
cd emberware
cargo build --release

This gives you the player, dev tools, and example games to learn from.

2

Create Your First Game

Create a new Rust library project:

cargo new --lib my-game
cd my-game

Update Cargo.toml:

[package]
name = "my-game"
version = "0.1.0"
edition = "2021"

[lib]
crate-type = ["cdylib"]

[profile.release]
opt-level = "s"
lto = true
3

Understanding the Game Loop

Every Emberware game exports three functions. Replace src/lib.rs with:

#![no_std]
#![no_main]

use core::panic::PanicInfo;

#[panic_handler]
fn panic(_: &PanicInfo) -> ! { core::arch::wasm32::unreachable() }

// Import runtime functions
#[link(wasm_import_module = "env")]
extern "C" {
    fn set_clear_color(color: u32);
    fn draw_rect(x: f32, y: f32, w: f32, h: f32, color: u32);
    fn button_pressed(player: u32, button: u32) -> u32;
}

static mut Y: f32 = 200.0;

#[no_mangle]
pub extern "C" fn init() {
    unsafe { set_clear_color(0x1a1a2eFF); }
}

#[no_mangle]
pub extern "C" fn update() {
    unsafe {
        if button_pressed(0, 0) != 0 { Y -= 10.0; } // Up
        if button_pressed(0, 1) != 0 { Y += 10.0; } // Down
    }
}

#[no_mangle]
pub extern "C" fn render() {
    unsafe { draw_rect(200.0, Y, 80.0, 80.0, 0xFF6B6BFF); }
}

All game state lives in static mut variables — this enables automatic rollback netcode for online multiplayer!

4

Drawing Graphics

Emberware provides 2D and 3D drawing APIs:

2D Drawing

// Draw rectangles and text
draw_rect(x, y, width, height, 0xFF0000FF); // Red
draw_text(b"Hello!".as_ptr(), 6, x, y, 24.0, 0xFFFFFFFF);

3D Graphics

// Set up camera
camera_set(0.0, 5.0, 10.0, 0.0, 0.0, 0.0);

// Create and draw a cube
let cube_handle = cube(1.0, 1.0, 1.0);
push_identity();
push_translate(0.0, 1.0, 0.0);
push_rotate_y(45.0);
draw_mesh(cube_handle);
5

Handling Input

Check button states with the input API:

// Button constants
const BUTTON_A: u32 = 4;
const BUTTON_LEFT: u32 = 2;

// Check if A was just pressed this frame
if button_pressed(0, BUTTON_A) != 0 {
    jump();
}

// Check if button is held down
if button_held(0, BUTTON_LEFT) != 0 {
    player_x -= 5.0;
}

// Analog stick input (-1.0 to 1.0)
let stick_x = left_stick_x(0);
player_x += stick_x * 5.0;
6

Adding Sound

Play sounds with simple procedural audio or loaded samples:

// Load PCM samples (22050 Hz, mono, i16)
let samples = generate_beep(); // Your audio data
let sfx = load_sound(samples.as_ptr(), (samples.len() * 2) as u32);

// Play with volume and stereo pan
play_sound(sfx, 0.8, 0.0); // volume=0.8, pan=center

// Or load from ROM assets
let jump = rom_sound(b"jump".as_ptr(), 4);
play_sound(jump, 1.0, -0.5); // pan left
7

Build & Test

Compile your game to WebAssembly:

cargo build --target wasm32-unknown-unknown --release

Run in the Emberware player:

ember run target/wasm32-unknown-unknown/release/my_game.wasm
8

Package for Release

Create an ember.toml manifest and package your game:

[game]
id = "my-game"
title = "My Game"
author = "Your Name"
version = "1.0.0"

Build and pack:

ember build && ember pack
9

Submit to the Archive

  1. Sign in to your account
  2. Go to your Dashboard
  3. Click "Upload New Game"
  4. Fill in the details (title, description, category)
  5. Upload your .emb ROM file
  6. Add an icon (64x64 PNG) and screenshots (optional)
  7. Click "Publish"

Your game is now part of the Emberware Archive — playable by anyone with the emulator.

Next Steps

📚

Read the Docs

Learn to build a complete game with our Paddle tutorial, then explore the full API reference, render modes, and advanced features.

Developer Docs
🎮

Study Examples

Learn from complete example games in the Emberware repository. See how platformers, shooters, and puzzle games are built.

View Examples
💬

Join the Community

Get help, share your games, and collaborate with other developers on GitHub and Discord. Open issues, start discussions, and contribute.

Common Patterns

How do I implement game states (menu, playing, game over)?
enum GameState { Menu, Playing, GameOver }
static mut STATE: GameState = GameState::Menu;

pub extern "C" fn update() {
    unsafe {
        match STATE {
            GameState::Menu => update_menu(),
            GameState::Playing => update_game(),
            GameState::GameOver => update_game_over(),
        }
    }
}
How do I handle collision detection?
fn aabb_collision(a: &Rect, b: &Rect) -> bool {
    a.x < b.x + b.width &&
    a.x + a.width > b.x &&
    a.y < b.y + b.height &&
    a.y + a.height > b.y
}

if aabb_collision(&player.bounds(), &enemy.bounds()) {
    player.take_damage();
}
How do I save player progress?
// 8 save slots available, up to 64KB each
const SLOT: u32 = 0;

// Save bytes
let data: [u8; 8] = [level, score, /* ... */];
save_write(SLOT, data.as_ptr(), data.len() as u32);

// Load bytes
let mut data = [0u8; 8];
let size = save_read(SLOT, data.as_mut_ptr(), 8);
if size > 0 { /* data loaded */ }
How does online multiplayer work?
// Multiplayer is AUTOMATIC! Just write rollback-safe code:

// 1. All state in static variables
static mut PLAYER1_X: f32 = 0.0;
static mut PLAYER2_X: f32 = 0.0;

// 2. Read inputs for each player
let p1_input = left_stick_x(0);
let p2_input = left_stick_x(1);  // Works online!

// 3. Deterministic update (no random system calls)
PLAYER1_X += p1_input * SPEED;
PLAYER2_X += p2_input * SPEED;

// The runtime handles networking, rollback, and prediction!

Ready to Build?

You now have everything you need to create your first game for Emberware hardware.