Updated 7 November 2026

Core8Bit Lua SDK

Core8Bit games are written in Lua 5.3 against the c8b API. This reference describes the API and its behaviour on the console and in the emulator.

Contents

Getting started

-- Games/HelloWorld/main.lua
local gfx = c8b.graphics

local x, y = 240, 136

function c8b.update()
    if c8b.buttonIsPressed(c8b.kButtonLeft) then x = x - 2 end
    if c8b.buttonIsPressed(c8b.kButtonRight) then x = x + 2 end
    gfx.clear(gfx.kColorBlack)
    gfx.fillCircle(x, y, 10, 0x07E0)          -- RGB565 green
    gfx.drawText("Hello Core8Bit", 10, 10)
end

The screen is 480x272 pixels and colors are RGB565 integers (gfx.kColorBlack = 0x0000, gfx.kColorWhite = 0xFFFF, gfx.kColorClear = -1).

Game folder layout

/Games/<Name>/
    main.lua          required: the launcher only lists folders that contain main.lua
    icon.stj          optional cover art shown by the launcher (legacy: icons/icon.sti)
    icons/splash.sti  optional splash image shown while launching
    data/             written by c8b.datastore (data/<name>.json)
    ...               your own scripts (import/require) and assets
  • The launcher scans /Games and lists every directory that has main.lua. Order and "featured" games come from /System/launcher/order.txt (one name per line, * prefix = featured).
  • No manifest is read for games: a manifest.json in a game folder is ignored by the console and the launcher. The emulator only reads manifest.json under /System/* to find the auto-start system application ("auto_start": true, "entry").
  • The working directory is the game folder on both platforms, so relative paths ("images/hero", require("enemy"), import "scenes/Title") resolve inside it. Asset paths are usually given without extension (.sti, .sta, .sts are resolved by the loaders).

main.lua and the update loop

  1. The runtime loads the SDK (the class system, the graphics, sprite, timer and JSON modules, and the native bindings).
  2. It runs main.lua once. Top-level code is your initialisation.
  3. Every frame it calls c8b.update. After it returns, the runtime services streaming sound players and closes graphics contexts left open by lockFocus/pushContext.

Differences: the emulator passes the frame time in seconds as the only argument (c8b.update(dt)) and calls core8bit.init() once after main.lua if you define it; the console calls c8b.update() with no argument and never calls core8bit.init. Lifecycle callbacks (c8b.gameWillTerminate, gameWillPause, gameDidResume, deviceWillSleep, deviceDidWake) are only called on the console. Sprites and timers are not updated automatically: call gfx.sprite.update() and c8b.timer.updateTimers() from your update function.

How the runtime starts a game

  • Console (BIOS): loads the SDK once at boot, then starts the launcher. Choosing a game calls c8b.system.loadGame("/Games/<Name>/main.lua"); the console calls gameWillTerminate on the old game, cleans up, changes into the game folder, creates a fresh sandboxed environment for the game and runs it. MENU+B held for one second forces a return to the launcher.
  • Emulator: creates a fresh Lua state, registers the same native API plus the emulator modules (network, UDP, P2P, STV, time, plugins), loads the SDK (or the System/sdk folder of a mounted SD-card folder), then changes into the game folder and runs the script.

Running in the emulator

core8bit_emulator Games/MyGame/main.lua
core8bit_emulator --game MyGame            # same as Games/MyGame/main.lua
core8bit_emulator --sdcard /path/to/sdcard # console boot: runs the System app with "auto_start": true
core8bit_emulator --dev ...                # developer mode (protected calls with stack traces)

With no script argument the emulator boots like the console from an SD-card folder (a directory containing System/). In that mode c8b.launchGame/c8b.system.loadGame switch games.

Running on the console

Copy the game folder to /Games/<Name>/ on the SD card (or over the USB developer bridge) and start it from the launcher. Use c8b.system.loadGame(path) to switch games and c8b.returnToLauncher() to exit; c8b.launchGame has no effect on the console.

Namespaces

Name What it is
c8b The API table. C8B is the same table and also holds the flat native bindings (C8B.Graphics_fillRect, ...).
gfx Global alias of c8b.graphics created by the SDK.
json Global JSON module (= c8b.json).
Sprite, Image, ImageTable, Tilemap, Font, NineSlice, AnimationLoop, Animator, Timer, RealTimer, Object Global classes created by the SDK modules.
plugin Native plugin API.
core8bit / Core8Bit Legacy names (see System page).

Reference pages