# kiln, a launcher for the TrimUI Brick

> A replacement home screen for a retro handheld, as one static C binary that draws straight to the framebuffer. It runs on the stock firmware, and the launcher lives entirely on the SD card.

Canonical: https://mark-web.com/projects/kiln
Author: Mark Sulleza
Stack: C (static, musl, aarch64), Docker, adb
Source: https://github.com/mSulleza/kiln

## Why

The TrimUI Brick is a small handheld with a 1024×768 screen, an Allwinner A133 and 1 GB of RAM. The long-term goal is my own OS on it. The first step was my own launcher, without flashing anything: the stock firmware gives a root shell over USB, and the SD card boots before the internal storage, so there is always a way back.

kiln is one static binary, about 1,800 lines of C. It draws straight to `/dev/fb0`, double-buffered by panning, reads the handheld’s buttons from evdev, and starts games with the stock launch scripts. It needs no device libraries, and the stock launcher doesn’t have to be running.

## What it does

- **Games**: every emulator the SD card is set up for, read from the stock config files, with folders to browse.
- **Search** (Y): an on-screen keyboard with live results. Inside one system it filters that list; from the top it searches every system. Each typed word has to start a word in the title.
- **Emulator picker** (X): choose which emulator a system uses. The choice goes into the same config field the stock UI reads, through a temp file and a rename, and nothing else in the file changes.
- **Apps and Ports**, including ports installed by PortMaster.
- **System info**, a way back to the stock UI, reboot and power off.

[Screenshot: kiln's System screen: kernel, uptime, CPU, temperatures, memory, battery, SD card space, Wi-Fi, display and the last button pressed.] The System screen. The last line shows the most recent button event, which helped while mapping the buttons.

## It starts at boot, and you can always get out

`./dev.sh install` copies kiln to the SD card and adds a hook to a folder the stock boot already runs. Stock boot carries on as normal, so USB, Wi-Fi and audio come up as usual; then kiln pauses the stock launcher and takes the screen. When kiln exits for any reason, the stock launcher comes back.

Hold B while booting to skip kiln for that boot. Nothing outside the SD card changes, apart from one `bash` link that PortMaster needs.

## Testing without touching the handheld

Most of kiln was checked without anyone pressing a button. Writing input events to the handheld’s button device injects presses that kiln and the emulators both see, and dumping the visible framebuffer page gives a screenshot. `./dev.sh press down down a` and `./dev.sh shot` are the whole test loop, so an agent can drive the UI and look at the result.

A few things only showed up on the real device:

- Killing kiln while a game still held the framebuffer wedged the display driver until a reboot. Games now run in their own process group, and kiln stops the group first.
- Presses sent faster than about 60 ms apart overflow the input buffer while kiln is drawing, and the kernel drops the rest.
- The handheld goes to sleep after a few minutes and drops the USB connection, unless the stock keep-awake flags are set during development.

## PortMaster on stock firmware

PortMaster treats stock TrimUI as unsupported, and the firmware lacks what it and its ports assume: `bash`, Python 3, a busybox `tr` that understands character classes, and newer libraries. `./dev.sh portmaster` puts static builds of each on the SD card, and kiln adds them to the environment only for apps and ports, so emulators see exactly the stock setup. Without the newer `tr`, PortMaster took the Brick for a model with analog sticks and ports ignored the d-pad.

## Build it

```bash
git clone https://github.com/mSulleza/kiln.git && cd kiln
./dev.sh build     # static aarch64 binary, built in an Alpine container
./dev.sh run       # push it, pause the stock UI, start kiln
./dev.sh restore   # stop kiln and hand the screen back
```

It needs Docker, Python 3 with Pillow for the font, and `adb`. The font is Fira Code, rasterised into a C header at build time.
