ARMIGA is a minimal Linux distribution based on Buildroot for the Anbernic RG40XX H and RG40XX V, with experimental support for the RG35XX H, developed by retro-gaming enthusiasts. Our goal is to craft a highly focused operating system dedicated to Commodore Amiga emulation via RetroArch and the PUAE core, creating exactly the retro experience we want while having fun developing it.
| Component | Detail |
|---|---|
| Supported devices | RG40XX H, RG40XX V, RG35XX H (experimental) |
| SoC | Allwinner H700 (ARM64, Cortex-A53 x4 @ 1.42GHz, boost to 1.512GHz on Maximum Performance) |
| GPU | Mali-G31 MP2 (Panfrost) |
| RAM | 1 GB LPDDR4 |
| WiFi/BT | RTL8821CS (SDIO) |
| Display | 640Γ480 |
| Storage | MicroSD (mmcblk0) |
- β Boot (U-Boot 2026.01 + kernel 7.3.0-armiga + DTB); with the console off, plugging in USB-C only charges the battery (AXP717 charge-only boot, the system does not start)
- β A/B partition scheme with automatic rollback (see below)
- β Rootfs on SquashFS + zstd (system/system_b, 300MB per slot, ro)
- β
RTL8821CS WiFi (
wpa_supplicant+udhcpc, config generated in/tmpβ/etcis ro) - β SSH (Dropbear, root, port 22) β enabled by default, toggleable from Settings
- β
Dynamic CPU governor:
performancein normal use,powersaveduring screensaver - β
GPU governor forced to
performance(fixed 648MHz βsimple_ondemanddidn't scale well under real load) - β
ZRAM swap (512MB, LZ4,
swappiness=100) - β
amiga_datapartition (exFAT, auto-expands to 100% of the SD card on first boot) - β
Graphics stack: SDL3 3.4.18 (kmsdrm) + Mesa 26.3.0-rc2 (GBM + Panfrost, stripped
.soin overlay) - β
Custom C/SDL3 launcher (
armiga-launcher), bilingual Spanish/English interface (toggleL1, persistent) - β
Own gamepad driver (
armiga-joypad, out-of-tree kernel module): analog sticks read through the analog multiplexer, D-pad as hat, debounced buttons, rumble - β
RetroArch 1.22.2-nightly (2242d04) + PUAE 2021 core (
puae2021_libretro.so, 2.6.1 4ffb396) - β OTA update system (GitHub Releases β download β SHA256 verification β flash inactive slot, all async without blocking the UI)
- β Automatic A/B rollback on boot failure (attempt counter + slot reversion)
- β Settings menu: wireless network, backup (create/restore/delete), analog stick RGB LEDs, timezone, screensaver, brightness, performance profiles (maximum/balanced/power saving), SSH, factory reset
- β Redesigned "Workbench" interface (beige/gold palette on black, monochrome Tabler Icons iconography)
- β
Developer mode (terminal, btop, CPU temperature graph + throttling detection) accessible with
SELECT+START+L1combo - β ARexx scripts: kickstart checker (MD5 verification, color-coded pass/fail), disk/partition integrity check with verdict (OK/WARNING/CRITICAL); script output view supports line wrapping (no truncation) and continuous D-pad/stick hold-to-scroll
- β
Global brightness shortcut (
MODE+DPAD), USB-C charging indicator, real-time telemetry dashboard (CPU temp/load, RAM), reactive RGB LEDs (screen dimming, low battery β blinks red at 25% LED intensity when battery reaches 15%), UI navigation click sound (toggleable) - β
Last played game indicator on the main menu (reads RetroArch's history playlist): shows the title above the footer,
[X]resumes it directly without going through the RetroArch menu - β
Amiga Catalog (native list of your WHDLoad
.lhagames): games are identified by CRC32 against a bundled index (games.idx), not by file name, so renaming a file doesn't matter; box art / screenshot downloaded on demand over WiFi and cached inamiga_data; per-game play time; jump by letter with D-pad left/right - β
Optional Samba share of
amiga_data(\\armiga) β seeUSER-GUIDE.md
| # | Label | FS | Size | Content | Mount |
|---|---|---|---|---|---|
| 1 | boot | FAT32 | 64 MB | Kernel, dtb.img, extlinux.conf (armiga-A/B labels) | /boot (on demand) |
| 2 | system | squashfs | 300 MB | Rootfs β slot A | / (ro) if DEFAULT=armiga-A |
| 3 | system_b | squashfs | 300 MB | Rootfs β slot B (identical copy on every build) | / (ro) if DEFAULT=armiga-B |
| 4 | amiga_data | exFAT | rest of the disk | Kickstarts, ROMs, configs, saves | /media/amiga_data |
amiga_data must always be the last physical partition, so that auto-expansion to 100% of the disk works on SD cards of any size.
On boot, S02bootcheck compares the active slot (read from /proc/cmdline) against an attempt counter persisted on p1. If the launcher doesn't confirm a successful boot (first SDL frame rendered) within 3 consecutive attempts, the system automatically reverts DEFAULT in extlinux.conf to the last known-good slot and reboots β no user intervention required.
armiga-launcher / RetroArch (PUAE)
βββ SDL3 3.4.18 (backend: kmsdrm)
βββ libgbm.so.1.0.0 (Mesa 26.3.0-rc2)
β βββ dri_gbm.so β libgallium-26.3.0-rc2.so (Panfrost)
βββ libEGL.so.1.0.0
βββ libGLESv2.so.2.0.0
βββ libdrm
βββ DRM/KMS kernel (Panfrost, Mali-G31 @ fixed 648MHz)
Mesa 25+ note:
panfrost_dri.sono longer exists. The Panfrost driver lives inlibgallium-<version>.so, loaded viadri_gbm.so. Don't look under/usr/lib/dri/.
armiga/
βββ .github/workflows/
β βββ build.yml # Main CI β full Buildroot image (manual, points to tag for release)
β βββ build-kernel.yml # Kernel CI β Image, dtbs, modules, joypad driver (manual, kernel_version input)
β βββ build-mesa.yml # Mesa CI (cross-compile GBM+Panfrost, committed .so files, manual)
β βββ build-puae.yml # PUAE2021 core CI (manual, branch input)
β βββ build-retroarch.yml # Stable RetroArch CI (manual)
β βββ build-retroarch-nightly.yml # Nightly RetroArch CI (manual)
βββ board/armiga/
β βββ bootloader/ # Precompiled kernel, DTB and U-Boot (committed)
β βββ linux/ # Kernel config, patches/, dts/ (custom DTS), build_kernel.sh; the joypad driver lives in its own repo (amigagamesplus/armiga-joypad, cloned by build-kernel.yml)
β βββ rootfs_overlay/
β β βββ usr/lib/ # Mesa .so files (stripped)
β β βββ usr/bin/ # armiga-launcher-wrapper, retroarch (wrapper)
β β βββ usr/share/armiga/ # games.idx (Amiga game index, generated by tools/build-games-idx.py)
β β βββ etc/retroarch/ # retroarch.cfg.template, armiga.cfg, autoconfig/
β β βββ etc/init.d/ # Boot scripts (S02bootcheck, S06gpu, S07zram, S40partitions, S41wifi, S43update, ...)
β β βββ media/amiga_data/ # Static mountpoint (needed: rootfs is ro)
β βββ post-build.sh # Generates /etc/armiga-release
β βββ post-image.sh # Generates extlinux.conf, amiga_data.img, invokes genimage
β βββ genimage.cfg
βββ configs/armiga_defconfig
βββ package/
β βββ armiga-launcher/ # Custom launcher (C + SDL3)
β βββ armiga-splash/
β βββ btop/
β βββ fastfetch/
β βββ kmsdrm-test/
β βββ sdl-joystick-info/
β βββ sdl3/
β βββ sdl3_image/
β βββ sdl3_ttf/
βββ tools/ # build-games-idx.py (games.idx generator), retroarch-sync.sh
βββ docs/assets/ # README images
βββ Config.in
βββ external.mk
βββ external.desc
βββ flash.sh
βββ USER-GUIDE.md
βββ RETROARCH-CONFIG.md
βββ SECURITY.md
- Ubuntu 22.04+ (or GitHub Actions)
- Packages:
build-essential wget cpio unzip rsync bc python3 libssl-dev
Manual trigger (workflow_dispatch) in Actions β Build armiga β Run workflow. Verify that the branch selected in "Use workflow from" is correct before launching.
Estimated time: 30-40 min (~1h+ if configs/armiga_defconfig is modified, which invalidates the ccache/toolchain cache).
wget https://buildroot.org/downloads/buildroot-2026.08.tar.xz
tar xf buildroot-2026.08.tar.xz
make BR2_EXTERNAL=$PWD -C buildroot-2026.08 O=$PWD/output armiga_defconfig
make -C output -j$(nproc)
- Rootfs is read-only SquashFS. Any code that writes at runtime must point to
/media/amiga_dataor tmpfs (/tmp,/var/*), never to rootfs paths. This includes generated configs (wpa_supplicant.conf), caches (Mesa shader cache), and mountpoints (must already exist in the overlay, not created withmkdirat runtime). amiga_datamust always be the last physical partition (currently p4) β required for auto-expansion to work.rootfstype=inextlinux.confmust always match the real filesystem of system/system_b. A mismatch causes a silent boot failure.- Executable bit in git: always use
git update-index --chmod=+xafter adding a new script; verify withgit ls-files -s(should show100755). Don't assume a localchmod +xis preserved in the commit. - Large
.sofiles: alwaysaarch64-linux-gnu-strip --strip-unneededbefore committing.libgalliumunstripped weighs ~110-120MB; stripped, ~23MB. ddon the device is destructive β always verify offsets (sfdisk -d, positional) before flashing.- GitHub API
/releases/latestdoesn't return prereleases β the launcher uses/releases. - BusyBox awk doesn't support
match()with array β usegrep+cutto parsesfdisk -d. - Never patch the squashfs manually on the SD (
unsquashfs/mksquashfsby hand) β doesn't reliably preserve extended attributes. Any change is rebuilt from Buildroot.
Each component retains its original license.



