Warning
BETA & EXPERIMENTAL NOTICE:
The Flashiibo Executable Binary (.feb) format, C SDK (feb.h), build tooling, and runtime environment are currently in Beta & Experimental status.
APIs, header specifications, and runtime behavior are under active development and breaking changes might happen without warning.
Document Version: 1.0 (Beta)
Target Platform: Flashiibo Pro Gen3 (Firmware >= 26.10.6)
Host Applet: FEB Runner
Runtime Environment: Flashiibo Executable Binary (.feb) Virtual Machine
Flashiibo Pro Gen3 features a sandboxed virtual runtime for user-installable applications and games called FEB Runner (.feb, requires firmware >= 26.10.6). With the Flashiibo C SDK, developers can write applications in idiomatic C, compile them into self-contained .feb binary packages, and distribute them without modifying or reflashing the MCU firmware.
| Resource | Specification | Notes |
|---|---|---|
| Target Platform | Flashiibo Pro Gen3 | Requires firmware >= 26.10.6 (Sandboxed VM) |
| Language | C (C99 / C11) / Assembly | Standard types from <stdint.h> and <stdbool.h> |
| Display | 128×64 (default Super-CHIP) or 64×32 (legacy) Monochrome OLED | 1-bit per pixel (XOR sprite drawing) |
| Frame Rate | 60 Hz | Hardware timer-driven execution cycle |
| Memory Limit | 4,096 Bytes total address space | Sandboxed from system radio and kernel |
| Input Controls | 4 Physical buttons | UP, DOWN, BACK (Left), OK (Right) |
| Container Format | .feb (Flashiibo Executable Binary) |
100-byte metadata header + binary bytecode |
| Distribution | VFS /feb/*.feb on SPI NOR Flash |
Loaded using Flashiibo Pro Tools on Web or Mobile |
Flashiibo devices feature four physical buttons on the device body. In FEB Runner, these map to deterministic virtual key constants:
┌──────────────┐
│ [ UP ] │
│ (FEB_KEY_UP) │
│ Key: 0x2 │
┌───────────────┴──────────────┴───────────────┐
│ [ BACK ] [ OK ] │
│ (FEB_KEY_LEFT) (FEB_KEY_RIGHT)│
│ Key: 0x4 Key: 0x6 │
└───────────────┬──────────────┬───────────────┘
│ [ DOWN ] │
│(FEB_KEY_DOWN)│
│ Key: 0x8 │
└──────────────┘
| Physical Button | C Constant | Hex Code | Primary App Role |
|---|---|---|---|
| UP | FEB_KEY_UP |
0x2 |
Move cursor up / Jump / Rotate |
| DOWN | FEB_KEY_DOWN |
0x8 |
Move cursor down / Crouch / Soft drop |
| BACK | FEB_KEY_LEFT / FEB_KEY_BACK |
0x4 |
Move cursor left / Navigate back |
| OK | FEB_KEY_RIGHT / FEB_KEY_OK |
0x6 |
Move cursor right / Select / Action |
Important
Pressing UP and DOWN simultaneously is intercepted at both the OS and virtual machine engine level to guarantee an immediate, safe exit back to the "FEB Runner" main menu.
Long press on BACK is deliberately not an exit trigger, ensuring that BACK (Key 0x4 / Left) is completely safe to hold down for continuous gameplay movement or action charging without accidental termination.
Include the C SDK header in your application:
#include "feb.h"Clears the entire display buffer (turns off all pixels).
Sets the active drawing mode for all subsequent graphics operations:
FEB_DRAW_MODE_XOR(0): Inverts existing pixels (standard CHIP-8 blitting).FEB_DRAW_MODE_SET(1): Solid write (turns pixels ON).FEB_DRAW_MODE_CLEAR(2): Eraser (turns pixels OFF).FEB_DRAW_MODE_OPAQUE(3): Sets pixels ON with a solid black background bounding box (erases whatever is behind glyphs/shapes).FEB_DRAW_MODE_INVERTED_OPAQUE(4): Clears pixels OFF inside a solid white bounding box.
Draws an 8-pixel wide bitmap sprite of height height (1 to 15 rows) at coordinate (x, y).
- Sprites use XOR blitting. If a pixel is drawn where a pixel is already turned on, it will invert (turn off).
- Erase a sprite: Call
feb_draw_spritea second time with the exact same coordinates and data. - Return value: Returns
trueif any drawn pixel collided with an already active pixel on screen.
Draws a 16×16 pixel sprite in 128×64 mode (32 bytes). Returns true if collision occurred.
Renders a built-in single-digit hexadecimal glyph (0x0 through 0xF, 5 pixels high by 4 pixels wide) at (x, y).
Flashiibo firmware >= 26.10.6 includes hardware-accelerated drawing primitives executed directly by the VM:
void feb_draw_pixel(uint8_t x, uint8_t y);: Plots single pixel using active draw mode.void feb_draw_line(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1);: Draws line between endpoints using Bresenham's algorithm.void feb_draw_hline(uint8_t x, uint8_t y, uint8_t len);: Draws fast horizontal line.void feb_draw_vline(uint8_t x, uint8_t y, uint8_t len);: Draws fast vertical line.void feb_draw_rect(uint8_t x, uint8_t y, uint8_t w, uint8_t h);: Draws unfilled outline rectangle.void feb_fill_rect(uint8_t x, uint8_t y, uint8_t w, uint8_t h);: Draws filled solid rectangle.void feb_draw_rrect(uint8_t x, uint8_t y, uint8_t w, uint8_t h);: Draws unfilled outline rounded rectangle with 1px corner radius.void feb_fill_rrect(uint8_t x, uint8_t y, uint8_t w, uint8_t h);: Draws filled solid rounded rectangle with 1px corner radius.void feb_draw_triangle(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2);: Draws unfilled outline triangle connecting 3 vertices.void feb_draw_circle(uint8_t x, uint8_t y, uint8_t r);: Draws unfilled circle outline centered at(x, y).void feb_fill_circle(uint8_t x, uint8_t y, uint8_t r);: Draws filled solid circle centered at(x, y).
Inspects whether the pixel at (x, y) is currently lit without modifying the display buffer or requiring shadow collision arrays in memory. Returns true if lit, false otherwise.
Built-in typography functions render text using high-legibility u8g2 bitmap fonts:
FEB_FONT_4X6(0): Compact 4×6 numeric & ASCII font.FEB_FONT_6X10(1): Standard UI 6×10 font.FEB_FONT_RETRO_8X8(2): Blocky 8×8 retro arcade font.
Functions:
uint8_t feb_draw_string(uint8_t x, uint8_t y, const char *str, uint8_t font_id);: Renders null-terminated ASCII string; returns advanced X coordinate.uint8_t feb_draw_char(uint8_t x, uint8_t y, char ch, uint8_t font_id);: Renders single ASCII character; returns advanced X coordinate.uint8_t feb_string_width(const char *str, uint8_t font_id);: Calculates pixel width of string without drawing.uint8_t feb_draw_number(uint8_t x, uint8_t y, uint16_t num, uint8_t font_id);: Formats and renders 16-bit unsigned integer (0..65535) directly from registerI; returns advanced X coordinate.
Non-blocking poll of the instantaneous 4-button hardware bitmask:
- Bit 0 (
0x01):FEB_BTN_UP - Bit 1 (
0x02):FEB_BTN_DOWN - Bit 2 (
0x04):FEB_BTN_LEFT(FEB_BTN_BACK) - Bit 3 (
0x08):FEB_BTN_RIGHT(FEB_BTN_OK)
Allows detecting multi-button simultaneous presses and chord combinations with zero latency.
Blocks execution until a physical button is pressed, and returns the key code (0x2, 0x8, 0x4, or 0x6).
Non-blocking check to determine if the specified key code is currently held down.
Returns an 8-bit pseudo-random integer masked with mask (e.g., feb_rand(0x07) produces 0..7).
Sets the 60 Hz delay timer register. It automatically decrements by 1 every 16.6 ms until it reaches 0.
Returns the current value of the 60 Hz delay timer register.
Blocks execution for frames screen frames (~16.6 ms per frame).
Executable .feb files are strictly read-only. User save data, high scores, and settings are automatically persisted to /feb/saves/<app_name>.sav upon exit.
Saves up to 16 bytes of persistent application state (mapped to Super-CHIP RPL user flags). Flushed to the companion .sav file when the app closes.
Loads up to 16 bytes of persistent application state previously saved by feb_save_flags.
Immediately halts execution of the FEB application, flushes any dirty RPL persistent flags, and returns cleanly to the device's "FEB Runner" menu.
- Alias:
feb_quit() - Bytecode: Emits standard Super-CHIP
00FDopcode.
For smooth, flicker-free movement in single-buffered CHIP-8, use non-blocking feb_get_keys() and XOR in-place erasing rather than clearing the whole screen every frame:
#include "feb.h"
int main(void) {
uint8_t x = 60, y = 30;
feb_set_high_res(true);
feb_clear_screen();
/* Render static background once */
feb_draw_string(4, 2, "ACTION DEMO", FEB_FONT_6X10);
feb_draw_rect(x, y, 6, 6);
while (1) {
/* Poll instantaneous input */
uint8_t keys = feb_get_keys();
if (keys != 0) {
feb_draw_rect(x, y, 6, 6); /* XOR erase old position */
if (keys & FEB_BTN_UP) y--;
if (keys & FEB_BTN_DOWN) y++;
if (keys & FEB_BTN_LEFT) x--;
if (keys & FEB_BTN_RIGHT) x++;
feb_draw_rect(x, y, 6, 6); /* XOR draw new position */
}
}
return 0;
}A minimal moving sprite demo using 4-button directional keys:
#include "../../include/feb.h"
static const uint8_t player_sprite[8] = {
0x3C, 0x7E, 0xDB, 0xFF, 0xFF, 0xDB, 0x7E, 0x3C
};
int main(void) {
uint8_t x = 60, y = 28;
feb_set_high_res(true);
feb_clear_screen();
feb_draw_sprite(x, y, player_sprite, 8);
while (1) {
uint8_t key = feb_wait_key();
feb_draw_sprite(x, y, player_sprite, 8); /* XOR erase */
if (key == FEB_KEY_UP && y >= 2) y -= 2;
else if (key == FEB_KEY_DOWN && y <= 54) y += 2;
else if (key == FEB_KEY_LEFT && x >= 2) x -= 2;
else if (key == FEB_KEY_RIGHT && x <= 118) x += 2;
feb_draw_sprite(x, y, player_sprite, 8); /* redraw */
}
return 0;
}The repository includes a complete, fully playable 2048 game in examples/2048/main.c.
feb-sdk/
├── include/
│ └── feb.h <-- Flashiibo SDK header
├── tools/
│ ├── feb_build.py <-- Build orchestrator
│ ├── make_feb.py <-- .feb container packager
│ └── assemble_chip8.py <-- Bytecode assembler
└── examples/
└── my_app/
├── Makefile <-- App build script
└── main.c <-- Your C application
Compile your C application into a distributable .feb container:
python3 tools/feb_build.py examples/my_app/main.c -o examples/my_app/my_app.feb \
--title "My App" \
--author "Developer" \
--ver "1.0.0"PYTHON ?= python3
BUILD_TOOL = ../../tools/feb_build.py
APP_TITLE = My App
APP_AUTHOR = Developer
APP_VER = 1.0.0
TARGET = my_app.feb
all: $(TARGET)
$(TARGET): main.c ../../include/feb.h
$(PYTHON) $(BUILD_TOOL) main.c -o $(TARGET) \
--title "$(APP_TITLE)" \
--author "$(APP_AUTHOR)" \
--ver "$(APP_VER)"
clean:
rm -f $(TARGET)Note
Running .feb applications requires Flashiibo Pro Gen3 firmware >= 26.10.6.
- Connect your Flashiibo Pro Gen3 to your computer or phone via USB or Web Bluetooth.
- In the Flashiibo companion application or Web Tool, open the File Manager.
- Upload your
.febfile into the/feb/folder on the device flash storage. - On your Flashiibo device, enter FEB Runner from the main menu, select your game, and press OK to launch!