Skip to content

Latest commit

 

History

History
235 lines (166 loc) · 7.53 KB

File metadata and controls

235 lines (166 loc) · 7.53 KB

E16

E16 is a small toolchain for the Ember-16 virtual machine and assembly language. The repository contains a C++ assembler, emulator, disassembler, image and tilemap converters, sample programs, and a Neovim plugin for editing .e16 files.

What is included

  • assembler/: builds e16asm, which compiles .e16 assembly into binary programs.
  • emulator/: builds e16emu, an SDL3-based emulator for running compiled programs.
  • disassembler/: builds e16dis, a terminal disassembler for E16 binaries.
  • converter/: builds e16img, e16spritepack, and e16tilemap PNG asset converters.
  • musicMaker/: builds e16musicmaker, a six-channel APU tracker with live SDL3 preview, wavetable design, PCM recording, and callable .e16 music export.
  • tests/: example .e16 programs and assets.
  • nvim/e16.nvim/: Neovim filetype, syntax highlighting, and LSP support.

Requirements

  • CMake 3.10 or newer
  • A C++20 compiler
  • SDL3 for the emulator and music maker
  • zlib for the image converter
  • Python 3 for the Neovim LSP server

On macOS with Homebrew:

brew install cmake sdl3 zlib

On Ubuntu:

sudo apt-get update
sudo apt-get install -y build-essential cmake pkg-config libsdl3-dev zlib1g-dev python3

Build

Each tool is currently its own CMake project.

cmake -S assembler -B assembler/build
cmake --build assembler/build

cmake -S emulator -B emulator/build
cmake --build emulator/build

cmake -S musicMaker -B musicMaker/build
cmake --build musicMaker/build

cmake -S disassembler -B disassembler/build
cmake --build disassembler/build

cmake -S converter -B converter/build
cmake --build converter/build

The binaries are written to each build directory:

  • assembler/build/e16asm
  • emulator/build/e16emu
  • musicMaker/build/e16musicmaker
  • disassembler/build/e16dis
  • converter/build/e16img
  • converter/build/e16spritepack
  • converter/build/e16tilemap

Usage

Assemble a program:

assembler/build/e16asm tests/solid/main.e16 -o tests/solid/main.bin

Run it in the emulator:

emulator/build/e16emu tests/solid/main.bin

Run with debugger mode enabled:

emulator/build/e16emu -s tests/solid/main.bin

Compose and export E16 music:

musicMaker/build/e16musicmaker

The exported assembly module provides music_play, music_update, and music_stop. Call music_update once per game frame after music_play so the song advances without blocking the game loop.

Disassemble a binary:

disassembler/build/e16dis --plain tests/solid/main.bin

Convert a small PNG sprite or tile image:

converter/build/e16img sprite.png -o sprite.e16img

The image converter accepts 8x8, 16x16, and 32x32 PNG files with up to 16 RGB555 colors.

Combine palette-compatible sprite variants:

converter/build/e16spritepack red.png blue.png -o actors.e16spr --inc actors.e16

Create a background asset from a PNG tilemap:

converter/build/e16tilemap background.png -o level1.e16bg --inc level1.e16 --wrap

e16spritepack writes one padded 16-color palette page followed by every packed sprite. It checks that all sprites are the same size and share the same opaque shape unless --force is passed.

e16tilemap splits a PNG into 8x8 tiles, builds one padded 16-color palette page, deduplicates tiles with flip-aware tilemap entries, and writes constants for palette, tile, and map offsets.

Tool options

e16asm

Usage: e16asm [--base address] [-o output.bin] [--print-ast] file.e16
  • -o, --output: choose the output binary path.
  • -b, --base: set the base address. Defaults to 0x200000.
  • --print-ast: print parsed expressions before compiling.

e16emu

usage: e16emu [-s] [-w] [-m] [--headless] [--load-address addr] [--scale n] program.bin
  • -s: enable debugger mode.
  • -w: run in a window and leave the cursor visible.
  • --headless: run without creating a window, including on Linux systems without a desktop environment.
  • -m: disable audio playback.
  • --load-address: choose where the binary is loaded.
  • --scale: set the initial emulator display scale.
  • The emulator opens fullscreen by default and letterboxes the 320x180 display.
  • If SDL cannot initialize graphical output, the emulator reports the SDL error and exits.
  • If a Mesa OpenGL version override is inherited, the emulator uses SDL's software renderer to avoid incompatible OpenGL contexts.
  • When DISPLAY is available, the emulator prefers SDL3's x11 backend. Otherwise it lets SDL select the native video backend for the current environment.
  • Every launch writes a fresh diagnostic log to the platform temporary directory (/tmp/e16.log on Linux), including the SDL version, display environment, selected video and render drivers, fallback decisions, runtime faults, fatal exceptions, signals, and the final exit code.
  • Gamepad and audio initialization failures do not prevent graphical execution. Failed accelerated renderers, unavailable fullscreen modes, and presentation failures automatically use safe fallbacks where possible.
  • The graphical emulator uses nearest-neighbor presentation, hides the cursor, and never opens modal SDL message boxes.
  • Gamepads are supported for up to two players. D-pads and left sticks map to directions; South/East/West/North map to A/B/X/Y; Start maps to Start; Back maps to Select.
  • Escape or Back+Start / Minus+Plus exits the emulator.

e16dis

Usage: e16dis [--base address] [--plain] [--no-color] [--no-pager] [--no-labels] [--no-bytes] file.bin
  • -b, --base: set the base address. Defaults to 0x200000.
  • --plain: disable color and pager output.
  • --no-color: disable ANSI color output.
  • --no-pager: print directly instead of using a pager.
  • --no-labels: hide generated labels.
  • --no-bytes: hide instruction bytes.

e16img

Usage: e16img <image.png> [-o output.e16img]
  • -o, --output: choose the converted image output path.

e16spritepack

Usage: e16spritepack [--yes] [--force] [-o output.e16spr] [--inc output.e16] <sprite.png>...
  • -o, --output: choose the combined binary output path.
  • --inc, --include: choose the generated .e16 constants path.
  • -y, --yes: skip the confirmation prompt.
  • --force: combine sprites even when their opaque shapes differ.

e16tilemap

Usage: e16tilemap <background.png> [-o output.e16bg] [--inc output.e16] [--symbol NAME] [--palette n] [--wrap] [--no-flips]
  • -o, --output: choose the background binary output path.
  • --inc, --include: choose the generated .e16 constants path.
  • --symbol: choose the constant prefix.
  • --palette: set the tilemap entry palette number from 0 to 15.
  • --wrap: emit a layer control value with horizontal and vertical wrapping.
  • --no-flips: disable flipped tile deduplication.

Neovim plugin

The Neovim plugin lives in nvim/e16.nvim and provides:

  • *.e16 filetype detection
  • syntax highlighting
  • completions, hover, go-to-definition, document symbols, semantic tokens, and diagnostics through the included Python LSP server

With lazy.nvim:

{
  dir = "/path/to/E16/nvim/e16.nvim",
  ft = "e16",
  config = function()
    require("e16").setup()
  end,
}

See nvim/e16.nvim/README.md for more editor setup details.

GitHub Actions

This repository includes workflows for:

  • Building all CMake tools on Ubuntu.
  • Checking the Neovim plugin's Python LSP server with py_compile.

Repository status

This is an experimental toolchain. Interfaces and binary formats may change while the emulator, assembler, and editor tooling evolve together.