diff --git a/README.md b/README.md
index 8925e87d..0c22e25d 100644
--- a/README.md
+++ b/README.md
@@ -2,7 +2,7 @@
MinUI is a focused, custom launcher and libretro frontend for [a variety of retro handhelds](#supported-devices).
-
+
## Features
@@ -10,12 +10,12 @@ MinUI is a focused, custom launcher and libretro frontend for [a variety of retr
- No settings or configuration
- No boxart, themes, or distractions
- Automatically hides hidden files
- and extension and region/version
+ and extension and region/version
cruft in display names
- Consistent in-emulator menu with
quick access to save states, disc
changing, and emulator options
-- Automatically sleeps after 30 seconds
+- Automatically sleeps after 30 seconds
or press POWER to sleep (and wake)
- Automatically powers off while asleep
after two minutes or hold POWER for
@@ -23,26 +23,32 @@ MinUI is a focused, custom launcher and libretro frontend for [a variety of retr
- Automatically resumes right where
you left off if powered off while
in-game, manually or while asleep
-- Resume from manually created, last
- used save state by pressing X in
+- Resume from manually created, last
+ used save state by pressing X in
the launcher instead of A
-- Streamlined emulator frontend
+- Streamlined emulator frontend
(minarch + libretro cores)
- Single SD card compatible with
multiple devices from different
manufacturers
-You can [grab the latest version here](https://github.com/shauninman/MinUI/releases).
+**[Download the latest release](https://github.com/shauninman/MinUI/releases)**
-> Devices with a physical power switch
-> use MENU to sleep and wake instead of
-> POWER. Once asleep the device can safely
-> be powered off manually with the switch.
+## Installation
-## Supported consoles
+1. Download the latest release (base ZIP for your device)
+2. Extract to a freshly formatted FAT32 SD card
+3. Follow device-specific instructions in the included `README.txt`
+4. Insert SD card and boot your device
-Base:
+For detailed installation steps and device-specific setup, see the `README.txt` included in the base download.
+> [!TIP]
+> Devices with a physical power switch use MENU to sleep and wake instead of POWER. Once asleep, the device can be safely powered off with the switch.
+
+## Supported Consoles
+
+**Base consoles** (included with every release):
- Game Boy
- Game Boy Color
- Game Boy Advance
@@ -51,11 +57,10 @@ Base:
- Sega Genesis
- PlayStation
-Extras:
-
+**Extra consoles** (optional download):
- Neo Geo Pocket (and Color)
- Pico-8
-- Pokémon mini
+- Pokémon mini
- Sega Game Gear
- Sega Master System
- Super Game Boy
@@ -64,47 +69,42 @@ Extras:
## Supported Devices
-| Device | Added | Status |
-| -- | -- | -- |
-| Anbernic RG28xx | MinUI-20240429b-2 | Deprecated |
-| Anbernic RG34xx | MinUI-20241227-0 | Deprecated |
-| Anbernic RG34xxSP | MinUI-20250920-0 | Deprecated |
-| Anbernic RG35xx | MinUI-20230922b-2 | Deprecated |
-| Anbernic RG35xx Plus | MinUI-20240106b-0 | Deprecated |
-| Anbernic RG35xxH | MinUI-20240120b-1 | Deprecated |
-| Anbernic RG35xxSP | MinUI-20240525-0 | Deprecated |
-| Anbernic RG40xxH | MinUI-20240717-1 | Deprecated |
-| Anbernic RG40xxV | MinUI-20240831-0 | Deprecated |
-| Anbernic RG CubeXX | MinUI-202401028-0 | Deprecated |
-| GKD Pixel | MinUI-20240120b-1 | Deprecated |
-| M17 | MinUI-20231126b-2 | Deprecated |
-| MagicX XU Mini M | MinUI-20240831-0 | Deprecated |
-| MagicX Mini Zero 28 | MinUI-20250111-0 | Deprecated |
-| Miyoo A30 | MinUI-20240705-0 | Deprecated |
-| Miyoo Flip | MinUI-20250111-0 | Deprecated |
-| Miyoo Mini | MinUI-20230922b-2 | Deprecated |
-| Miyoo Mini Flip | MinUI-20251023-0 | Deprecated |
-| Miyoo Mini Plus | MinUI-20230922b-2 | Deprecated |
-| Powkiddy RGB30 | MinUI-20231014b-1 | Deprecated |
-| Trimui Brick | MinUI-20241028-0 | Deprecated |
-| Trimui Smart | MinUI-20230922b-2 | Deprecated |
-| Trimui Smart Pro | MinUI-20231111b-2 | Deprecated |
+| Manufacturer | Device | Released | Status |
+|--------------|--------|----------|--------|
+| **Anbernic** | RG35XX | December 2022 | ✓ |
+| **Anbernic** | RG35XX Plus | November 2023 | ✓ |
+| **Anbernic** | RG35XXH | January 2024 | ✓ |
+| **Anbernic** | RG28XX | April 2024 | ✓ |
+| **Anbernic** | RG35XXSP | May 2024 | ✓ |
+| **Anbernic** | RG40XXH | July 2024 | ✓ |
+| **Anbernic** | RG40XXV | August 2024 | ✓ |
+| **Anbernic** | RG CubeXX | October 2024 | ✓ |
+| **Anbernic** | RG34XX | December 2024 | ✓ |
+| **Anbernic** | RG34XXSP | May 2025 | ✓ |
+| **Miyoo** | Mini | December 2021 | ✓ |
+| **Miyoo** | Mini Plus | February 2023 | ✓ |
+| **Miyoo** | A30 | May 2024 | ✓ |
+| **Miyoo** | Mini Flip | October 2024 | ✓ |
+| **Miyoo** | Flip | January 2025 | ✓ |
+| **Trimui** | Smart | October 2022 | ✓ |
+| **Trimui** | Smart Pro | November 2023 | ✓ |
+| **Trimui** | Brick | October 2024 | ✓ |
+| **Powkiddy** | RGB30 | August 2023 | ✓ |
+| **MagicX** | Mini Zero 28 | January 2025 | ✓ |
+| **GKD** | Pixel | January 2024 | Deprecated |
+| **Generic** | M17 | October 2023 | Deprecated |
+| **MagicX** | XU Mini M | May 2024 | Deprecated |
> [!NOTE]
-> **Active** actively working on compatibility and improvements specific to this device
-> **Maintained** inheriting improvements to common functionality
-> **Deprecated** will be retired in a future update
-> **Retired** removed from repo, no longer updated or packaged with new releases
-
-## Legacy versions
-
-The original Trimui Model S version of MinUI (2021/04/03-2021/08/06) has been archived [here](https://github.com/shauninman/MinUI-Legacy-Trimui-Model-S).
+> Deprecated devices will continue to work with current MinUI releases but will not receive new features or platform-specific fixes.
-The sequel, MiniUI for the Miyoo Mini (2022/04/20-2022/10/23), has been archived [here](https://github.com/shauninman/MiniUI-Legacy-Miyoo-Mini).
+---
-The return of MinUI for the original Anbernic RG35XX (2023/02/26-2023/03/26) has been archived [here](https://github.com/shauninman/MinUI-Legacy-RG35XX).
+## For Developers
-The current MinUI which introduced support for multiple devices starting with the Trimui Smart, Miyoo Mini (and Plus), and the original Anbernic RG35XX was released on [2023/09/22][init-release] with the initial functional commit 6 months earlier on [2023/03/27][init-commit].
+Want to build MinUI, create custom paks, or understand how it works?
-[init-release]:https://github.com/shauninman/MinUI/releases/tag/v20230922b-2
-[init-commit]:https://github.com/shauninman/MinUI/commit/53e0296ea5a2794290fb5783765af6cee0063445#diff-b993e61ab6e66a19b67c88cfb98261aa9267d250de8bb56463662f67aae1a558
\ No newline at end of file
+- **[Development Guide](docs/DEVELOPMENT.md)** - Building, testing, and contributing
+- **[Architecture Guide](docs/ARCHITECTURE.md)** - How MinUI works internally
+- **[Pak Development Guide](docs/PAKS.md)** - Creating custom emulator and tool paks
+- **[Platform Documentation](workspace/)** - Technical hardware details for each device
diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md
new file mode 100644
index 00000000..f0732941
--- /dev/null
+++ b/docs/ARCHITECTURE.md
@@ -0,0 +1,404 @@
+# MinUI Architecture
+
+This document explains how MinUI is structured and how the pieces fit together.
+
+## Core Concept
+
+MinUI uses a **platform abstraction layer** to run the same code on 20+ different handheld devices. Write once, compile for each platform with hardware-specific constants.
+
+## The Three Layers
+
+### 1. Common Code (`workspace/all/`)
+
+Platform-independent C code that works everywhere:
+
+- **minui** (`minui.c`) - The launcher
+ - Browse ROMs by folder
+ - Track recently played games
+ - Launch emulator paks
+ - Display hardware status (battery, volume, brightness)
+
+- **minarch** (`minarch.c`) - The libretro frontend
+ - Load and run emulator cores
+ - Save state management (auto-save to slot 9)
+ - In-game menu (states, disc changing, options)
+ - Video scaling and audio mixing
+
+- **common utilities** (`common/`)
+ - `utils.c` - String helpers, file I/O, ROM name cleanup
+ - `api.c` - Graphics (GFX_*), Audio (SND_*), Input (PAD_*), Power (PWR_*)
+ - `scaler.c` - Optimized pixel scaling (NEON when available)
+
+### 2. Platform Definitions (`workspace//platform/`)
+
+Each device defines hardware constants in `platform.h`:
+
+```c
+#define PLATFORM "miyoomini"
+#define FIXED_WIDTH 640
+#define FIXED_HEIGHT 480
+#define FIXED_SCALE 2
+#define SDCARD_PATH "/mnt/SDCARD"
+#define BUTTON_A SDLK_SPACE
+#define BUTTON_B SDLK_LCTRL
+```
+
+The common code uses these to adapt to each device. One codebase, multiple targets.
+
+Some platforms also have `platform.c` for complex hardware-specific implementations (video initialization, HDMI switching, etc.).
+
+### 3. Platform Components (`workspace//`)
+
+Device-specific daemons and utilities:
+
+- **keymon** - Button monitoring daemon
+ - Monitors hardware buttons (volume, power, etc.)
+ - Updates settings (brightness, volume)
+ - Handles sleep/wake, shutdown
+
+- **libmsettings** - Settings library
+ - Persists volume, brightness, etc.
+ - Shared between minui, minarch, and tools
+ - Uses shared memory or files for IPC
+
+- **Other components** (platform-specific):
+ - `batmon` - Battery overlay
+ - `lumon` - Backlight control
+ - `overclock` - CPU frequency adjustment
+ - `show` - Boot splash display
+
+## How It Works
+
+### Starting Up
+
+1. Device boots → runs platform boot script (`workspace//install/boot.sh`)
+2. Boot script displays splash screen (installing/updating if needed)
+3. Launches MinUI via `.system//paks/MinUI.pak/launch.sh`
+4. MinUI reads ROM folders and displays launcher
+
+### Launching a Game
+
+1. User selects ROM in launcher
+2. MinUI calls the appropriate pak's `launch.sh` script
+3. Pak script runs `minarch.elf `
+4. Minarch loads the libretro core and starts emulation
+5. User presses MENU → in-game menu appears
+6. User saves state, changes settings, etc.
+7. User quits → returns to launcher
+8. Next launch auto-resumes from slot 9
+
+### Platform Abstraction
+
+Common code calls abstract APIs:
+```c
+GFX_init(); // Initialize display
+PAD_poll(); // Read button state
+PWR_getBatteryLevel(); // Get battery %
+```
+
+Each platform implements these differently:
+- **miyoomini**: SDL keyboard + custom battery ADC
+- **rgb30**: SDL2 joystick + sysfs battery
+- **tg5040**: SDL2 joystick + inverted ALSA volume
+
+The abstraction hides complexity. Common code doesn't care how buttons work.
+
+## Directory Layout
+
+### Source Code
+```
+workspace/
+├── all/ # Runs everywhere
+│ ├── minui/ # Launcher
+│ ├── minarch/ # Emulator frontend
+│ └── common/ # Shared API
+│
+└── miyoomini/ # Example platform
+ ├── platform/ # Hardware definitions
+ ├── keymon/ # Button daemon
+ ├── libmsettings/ # Settings library
+ ├── install/ # Boot script + splash screens
+ └── cores/ # Libretro cores (git submodules)
+```
+
+### Installation Files
+```
+skeleton/
+├── SYSTEM/
+│ └── res/ # Shared assets
+│ ├── assets@2x.png # UI sprite sheet
+│ └── BPreplayBold-unhinted.otf
+│
+├── BOOT/ # Boot scripts
+└── EXTRAS/ # Optional paks
+```
+
+### Output
+```
+build/
+├── SYSTEM/ # Core system files
+├── BOOT/ # Bootloaders
+└── EXTRAS/ # Optional components
+```
+
+## The Pak System
+
+MinUI is extended through "paks" - folders ending in `.pak` with a `launch.sh` script inside.
+
+### Emulator Paks
+
+Live in `Emus//`:
+```
+Emus/miyoomini/
+└── GB.pak/
+ ├── launch.sh # Launches core for this system
+ └── default.cfg # Default core settings
+```
+
+The launcher maps ROM folders to paks by tag:
+```
+Roms/Game Boy (GB)/ → Emus/miyoomini/GB.pak/
+```
+
+### Tool Paks
+
+Live in `Tools//`:
+```
+Tools/miyoomini/
+└── Files.pak/
+ ├── launch.sh # Launches file manager
+ └── res/ # Tool assets
+```
+
+Tools appear in the launcher as a separate category.
+
+See [PAKS.md](PAKS.md) for complete pak development guide.
+
+## Multi-Resolution Support
+
+MinUI supports devices from 320x240 to 1280x720 using a scale factor:
+
+- **1x**: 320x240 devices (trimuismart, gkdpixel)
+- **2x**: 640x480 devices (most platforms)
+- **3x**: 960x720 devices (tg5040 brick)
+- **4x**: 1280x960+ devices (future)
+
+Each platform defines `FIXED_SCALE` in `platform.h`. At startup, MinUI loads the appropriate sprite sheet:
+
+```c
+sprintf(asset_path, RES_PATH "/assets@%ix.png", FIXED_SCALE);
+```
+
+All UI coordinates use `SCALE1()`, `SCALE2()`, etc. macros:
+```c
+SDL_Rect button = {SCALE4(10, 20, 30, 40)}; // Scales all 4 values
+```
+
+This way UI code is resolution-independent.
+
+## Input Handling
+
+MinUI supports three input methods (platforms use one or more):
+
+1. **SDL Keyboard**: `BUTTON_A = SDLK_SPACE`
+2. **SDL Joystick**: `JOY_A = 0`
+3. **Evdev Codes**: `CODE_A = 57`
+
+Platforms define which buttons use which method. Some use multiple (e.g., miyoomini uses SDL keyboard for games, evdev codes for keymon).
+
+Common code reads buttons through the PAD API:
+```c
+PAD_poll();
+if (PAD_justPressed(BTN_A)) { /* ... */ }
+```
+
+The platform layer handles the actual hardware polling.
+
+## Graphics Pipeline
+
+### Display Initialization
+
+1. Platform opens framebuffer or SDL window
+2. Creates surfaces for screen and layers
+3. Sets up pixel format (usually RGB565)
+
+### Rendering
+
+MinUI uses double-buffering:
+```c
+GFX_clear(screen); // Clear back buffer
+GFX_blitText(...); // Draw UI elements
+GFX_flip(screen); // Show back buffer
+```
+
+### Asset System
+
+UI sprites live in a single sprite sheet (`assets@Nx.png`). Each sprite has a defined rectangle in `api.c`:
+
+```c
+asset_rects[ASSET_BATTERY] = (SDL_Rect){SCALE4(47, 51, 17, 10)};
+```
+
+Draw sprites with:
+```c
+GFX_blitAsset(ASSET_BATTERY, screen, x, y, width, height, rotation);
+```
+
+## Save States
+
+MinUI has 9 save state slots per game:
+- **Slots 0-8**: Manual saves (accessible in-game menu)
+- **Slot 9**: Auto-save (created on quit, loaded on resume)
+
+State files live in `.userdata/shared/-/`:
+```
+.userdata/shared/GB-gambatte/
+├── Pokemon.st0 # Manual save slot 0
+├── Pokemon.st9 # Auto-save slot 9
+└── Pokemon.srm # Save RAM (battery saves)
+```
+
+Save states are shared across all platforms (unlike per-game configs which are platform-specific). Press X in launcher to resume from last manual state instead of auto-state.
+
+## Memory Management
+
+### Stack vs Heap
+
+MinUI prefers stack allocation for speed:
+```c
+char path[MAX_PATH]; // 512 bytes on stack
+```
+
+Use heap only when necessary:
+```c
+char* data = allocFile(path); // Returns malloc'd memory
+// ... use data ...
+free(data); // Caller must free
+```
+
+### SDL Surfaces
+
+SDL surfaces are reference counted:
+```c
+SDL_Surface* img = IMG_Load(path);
+// ... use img ...
+SDL_FreeSurface(img); // Always free
+```
+
+## Configuration Files
+
+### Emulator Options
+
+Each pak can have a `default.cfg`:
+```
+upscaler = 0
+aspect = fill
+filter = nearest
+
+bind Up = UP
+bind Down = DOWN
+bind A Button = A
+```
+
+Users can override per-game in `.userdata////`.
+
+### Recent Games
+
+`/.minui/recent.txt` tracks recently played games:
+```
+/path/to/rom.gb
+/path/to/rom.nes
+```
+
+Launcher shows these first for quick access.
+
+## Boot Process
+
+1. Device hardware boots
+2. Runs boot script from device-specific location
+3. Boot script:
+ - Checks for `MinUI.zip` (update)
+ - Displays splash screen if updating
+ - Extracts update or launches MinUI
+4. MinUI launcher starts
+5. User navigates and plays games
+6. On quit, device reboots or powers off (prevents stock firmware access)
+
+## Performance Optimizations
+
+### NEON SIMD
+
+Platforms with `HAS_NEON` can use ARM SIMD instructions:
+```c
+#ifdef HAS_NEON
+ scale_neon(src, dst, width, height);
+#else
+ scale_c(src, dst, width, height);
+#endif
+```
+
+Used in `scaler.c` for fast pixel scaling.
+
+### Frame Pacing
+
+Minarch maintains 60fps by:
+- Locking to vsync when possible
+- Throttling with `SDL_Delay()` when vsync unavailable
+- Skipping frames if too slow (rare)
+
+### Memory Efficiency
+
+- Reuse surfaces where possible
+- Free immediately after use
+- Keep texture cache small
+- Avoid allocations in hot paths
+
+## Thread Safety
+
+MinUI is mostly single-threaded except:
+- Some platforms use background threads for HDMI monitoring
+- Keymon runs as separate process
+- Settings use shared memory or files for IPC
+
+No complex locking needed.
+
+## Platform-Specific Code
+
+When you need platform-specific behavior, use `#ifdef`:
+
+```c
+#ifdef PLATFORM_MIYOOMINI
+ // Special code for Miyoo Mini
+#endif
+```
+
+Or add to `platform.c` and call from common code:
+```c
+// In platform.c
+void PLAT_initSpecialHardware(void) {
+ // Platform-specific initialization
+}
+
+// In common code
+#ifdef HAS_SPECIAL_HARDWARE
+ PLAT_initSpecialHardware();
+#endif
+```
+
+## File Paths
+
+All paths use forward slashes. Platforms define base paths:
+```c
+#define SDCARD_PATH "/mnt/SDCARD"
+#define ROMS_PATH SDCARD_PATH "/Roms"
+#define SYSTEM_PATH SDCARD_PATH "/.system/" PLATFORM
+```
+
+Common code uses these macros. Never hardcode paths.
+
+## Resources
+
+- [Development Guide](DEVELOPMENT.md) - Building and testing
+- [Pak Development](PAKS.md) - Creating custom paks
+- [Platform READMEs](../workspace/) - Hardware-specific details
+- [Project Docs](../CLAUDE.md) - Comprehensive technical reference
diff --git a/docs/DEVELOPMENT.md b/docs/DEVELOPMENT.md
new file mode 100644
index 00000000..a3f22bb1
--- /dev/null
+++ b/docs/DEVELOPMENT.md
@@ -0,0 +1,295 @@
+# MinUI Development Guide
+
+This guide covers building MinUI, running tests, and contributing code.
+
+## Building MinUI
+
+MinUI uses Docker to cross-compile for ARM devices. You don't need the actual hardware to build.
+
+### Prerequisites
+
+- Docker Desktop
+- Make (pre-installed on macOS/Linux)
+- Git
+
+### Quick Start
+
+Build everything:
+```bash
+make
+```
+
+Build for one platform:
+```bash
+make PLATFORM=miyoomini
+```
+
+Available platforms: `miyoomini`, `my282`, `my355`, `trimuismart`, `rg35xx`, `rg35xxplus`, `rgb30`, `tg5040`, `m17`, `gkdpixel`, `magicmini`, `zero28`
+
+### Platform Shell (for development)
+
+Drop into a build environment for interactive development:
+```bash
+make PLATFORM=miyoomini shell
+```
+
+Inside the container you can build components individually:
+```bash
+cd /root/workspace/all/minui
+make
+```
+
+## Code Quality
+
+### Run All Checks
+
+```bash
+make test # Run unit tests
+make lint # Static analysis
+make format # Auto-format code
+```
+
+### Static Analysis
+
+Find bugs before they ship:
+```bash
+make lint # Check common code
+```
+
+This runs `cppcheck` on `workspace/all/` which contains all the platform-independent code.
+
+### Unit Tests
+
+MinUI uses Unity for testing:
+```bash
+make test
+```
+
+Tests live in `tests/unit/` and mirror the structure of `workspace/all/`. For example, `workspace/all/common/utils.c` has tests in `tests/unit/all/common/test_utils.c`.
+
+#### Writing Tests
+
+Here's an example test:
+```c
+#include "unity.h"
+#include "utils.h"
+
+void test_getDisplayName_stripsExtension(void) {
+ char result[256];
+ getDisplayName("game.gb", result);
+ TEST_ASSERT_EQUAL_STRING("game", result);
+}
+```
+
+Add your test function to the `main()` function in your test file:
+```c
+int main(void) {
+ UNITY_BEGIN();
+ RUN_TEST(test_getDisplayName_stripsExtension);
+ return UNITY_END();
+}
+```
+
+Run tests: `make test`
+
+### Code Formatting
+
+MinUI uses `clang-format` with tabs and K&R-style braces:
+```bash
+make format # Format all code
+make format-check # Check without changing
+```
+
+Settings in `.clang-format`:
+- Tabs for indentation (width: 4)
+- Opening braces on same line
+- Left-aligned pointers (`char* name`)
+- 100 character line limit
+
+### Shell Script Linting
+
+Check shell scripts with `shellcheck`:
+```bash
+make lint-shell
+```
+
+## Project Structure
+
+```
+MinUI/
+├── workspace/
+│ ├── all/ # Platform-independent code
+│ │ ├── minui/ # Launcher
+│ │ ├── minarch/ # Libretro frontend
+│ │ └── common/ # Shared utilities and API
+│ │
+│ └── / # Platform-specific code
+│ ├── platform/ # Hardware definitions
+│ ├── keymon/ # Button monitoring daemon
+│ ├── libmsettings/ # Settings library
+│ └── cores/ # Libretro cores
+│
+├── skeleton/ # Files copied to SD card
+│ ├── SYSTEM/res/ # Shared assets (fonts, sprites)
+│ └── BOOT/ # Boot scripts
+│
+├── build/ # Build output (generated)
+├── tests/ # Unit tests
+└── docs/ # Documentation
+```
+
+## Platform Architecture
+
+MinUI uses a **platform abstraction layer** so one codebase supports 20+ devices:
+
+**Common code** (`workspace/all/`) calls abstract APIs like:
+- `GFX_clear()` - Clear screen
+- `PAD_poll()` - Read buttons
+- `PWR_getBatteryLevel()` - Get battery %
+
+**Platform code** (`workspace//platform/`) implements these for specific hardware:
+- `platform.h` - Hardware constants (screen size, button codes)
+- `platform.c` - Hardware functions (if needed)
+
+Example from `platform.h`:
+```c
+#define FIXED_WIDTH 640
+#define FIXED_HEIGHT 480
+#define BUTTON_A SDLK_SPACE
+```
+
+The common code compiles once, then links with different platform definitions for each device.
+
+## Adding Features
+
+### Making Changes to Common Code
+
+1. Edit files in `workspace/all/`
+2. Write tests in `tests/unit/`
+3. Run `make test` to verify
+4. Format with `make format`
+5. Check with `make lint`
+
+### Adding Platform-Specific Features
+
+1. Edit `workspace//platform/` files
+2. Test on actual hardware (cross-compilation can't verify hardware behavior)
+3. Document in `workspace//README.md`
+
+### Testing Your Changes
+
+Build for a specific platform:
+```bash
+make PLATFORM=miyoomini build
+```
+
+Output goes to `build/` directory. Copy to SD card and test on device.
+
+## Contributing
+
+### Before You Submit
+
+1. Run all checks:
+```bash
+make test lint format
+```
+
+2. Test on at least one platform if possible
+
+3. Update documentation:
+ - Platform README if hardware-specific
+ - CLAUDE.md if changing architecture
+ - This file if changing workflows
+
+### Commit Messages
+
+Keep it simple:
+```
+Add battery percentage to status bar
+
+Show battery % next to icon when available.
+Fallback to icon-only on platforms without %.
+```
+
+First line is summary (imperative mood). Body explains why and what changed.
+
+## Common Tasks
+
+### Adding a New Libretro Core
+
+1. Add core to `workspace//cores/` as git submodule (cores are platform-specific)
+2. Add build rules to `workspace//cores/makefile`
+3. Create emulator pak with launch script
+4. Test on target hardware
+
+Note: Some platforms share cores (e.g., my282 copies cores from rg35xx due to same CPU).
+
+### Fixing a Bug
+
+1. Write a failing test first (if possible)
+2. Fix the bug
+3. Verify test passes
+4. Run `make lint` to check for issues
+
+### Updating Assets
+
+Assets live in `skeleton/SYSTEM/res/`:
+- `assets@1x.png` - UI sprites for 1x scale (320x240)
+- `assets@2x.png` - UI sprites for 2x scale (640x480)
+- `assets@3x.png` - UI sprites for 3x scale (960x720)
+- `assets@4x.png` - UI sprites for 4x scale (1280x960+)
+- `BPreplayBold-unhinted.otf` - UI font
+
+Edit with pixel editor. Keep sprites on grid defined in `workspace/all/common/api.c`.
+
+## Troubleshooting
+
+### Docker Won't Start
+
+Check Docker Desktop is running. Restart if needed.
+
+### Build Fails
+
+Try cleaning:
+```bash
+make clean
+```
+
+Then rebuild:
+```bash
+make PLATFORM=miyoomini
+```
+
+### Tests Fail
+
+Tests run in Docker. Check test output carefully. Tests are strict about memory and undefined behavior.
+
+Common issues:
+- Buffer too small
+- Uninitialized variables
+- Off-by-one errors
+
+### Platform Won't Boot
+
+Check `workspace//install/boot.sh` for errors. Boot scripts are platform-specific and finicky.
+
+Enable verbose logging by editing boot script to redirect output:
+```bash
+./minui.elf > /tmp/minui.log 2>&1
+```
+
+Then check logs on device.
+
+## Resources
+
+- [Architecture Guide](ARCHITECTURE.md) - How MinUI works internally
+- [Pak Development](PAKS.md) - Creating custom emulator paks
+- [Platform READMEs](../workspace/) - Platform-specific docs
+- [Main Project Docs](../CLAUDE.md) - Comprehensive reference
+
+## Getting Help
+
+- Check existing code for examples
+- Platform READMEs document hardware quirks
+- CLAUDE.md has detailed architecture notes
+- GitHub issues for bugs and questions
diff --git a/PAKS.md b/docs/PAKS.md
similarity index 92%
rename from PAKS.md
rename to docs/PAKS.md
index c8b47c78..2f635397 100644
--- a/PAKS.md
+++ b/docs/PAKS.md
@@ -24,6 +24,21 @@ In all cases please make clear to your users that I (@shauninman) can't support
MinUI maps roms to paks based on the tag in parentheses at the end the name of the rom's parent folder (eg. "/Roms/Game Boy (GB)/Dr. Mario (World).gb" will launch the "GB.pak"). A tag should be all uppercase. When choosing a tag, start with common abbreviations used by other emulation frontends like Retroarch or EmulationStation (eg. FC for Famicom/Nintendo or MD for MegaDrive/Genesis). If that tag is already being used by another pak, use the core name if short (eg. MGBA) or an abbreviation (eg. PKM for pokemini) or truncation (eg. SUPA for mednafen_supafaust) of the core name.
+# Environment variables
+
+MinUI sets up these variables before launching your pak:
+
+- `PLATFORM` - Platform identifier (e.g., "miyoomini", "rg35xxplus")
+- `DEVICE` - Device variant (e.g., "cube" for RG CubeXX, "wide" for RG34XX)
+- `SDCARD_PATH` - SD card root (e.g., "/mnt/SDCARD")
+- `SYSTEM_PATH` - Platform system files
+- `CORES_PATH` - Libretro cores location
+- `BIOS_PATH` - BIOS files
+- `SAVES_PATH` - Save files
+- `USERDATA_PATH` - Platform-specific user data
+- `SHARED_USERDATA_PATH` - Shared user data
+- `LOGS_PATH` - Log files
+
# Launching your core
Here's an example "launch.sh":
@@ -50,7 +65,7 @@ There's no need to edit anything below the line of hash marks. The rest is boile
That's it! Feel free to experiement with cores from the stock firmware, other compatible devices, or building your own.
-Oh, if you're creating a pak for Anbernic's RG*XX line you'll need to change the last part of the last line from ` &> "$LOGS_PATH/$EMU_TAG.txt"` to ` > "$LOGS_PATH/$EMU_TAG.txt" 2>&1` because its default shell is whack.
+Some platforms may require `nice -20` before `minarch.elf` for proper CPU priority. Check existing paks for your target platform for examples.
# Option defaults and button bindings
diff --git a/docs/QA-README.md b/docs/QA-README.md
deleted file mode 100644
index 2fd02c96..00000000
--- a/docs/QA-README.md
+++ /dev/null
@@ -1,179 +0,0 @@
-# MinUI Quality Assurance
-
-Quick reference for code quality tools.
-
-## Quick Start
-
-```bash
-# Run C static analysis
-make -f Makefile.qa lint
-
-# Run shell script linting
-make -f Makefile.qa lint-shell
-
-# Run tests
-make -f Makefile.qa test
-
-# Check code formatting (safe, no changes)
-make -f Makefile.qa format-check
-
-# Run all checks
-make -f Makefile.qa lint lint-shell test format-check
-```
-
-## What's Set Up
-
-### ✅ Static Analysis (cppcheck)
-- **Tool:** cppcheck
-- **Rules:** Forgiving (warnings only, no style checks yet)
-- **Scope:** workspace/all/ (common code)
-- **Issues Found:** 1 real issue (undefined behavior in api.c:355)
-- **Doc:** [static-analysis-setup.md](static-analysis-setup.md)
-
-### ✅ Unit Tests (Unity)
-- **Framework:** Unity (lightweight C test framework)
-- **Coverage:** 9 tests for string utilities
-- **Status:** All passing ✓
-- **Doc:** [testing-setup.md](testing-setup.md)
-
-### ✅ Code Formatting (clang-format)
-- **Tool:** clang-format
-- **Style:** Tabs, opening brace on same line, left-aligned pointers
-- **Status:** Available (use on new/modified code)
-- **Doc:** [formatting-setup.md](formatting-setup.md)
-
-### ✅ Shell Script Linting (shellcheck)
-- **Tool:** shellcheck
-- **Rules:** Forgiving (serious issues only)
-- **Scope:** 403 scripts (skeleton, workspace, root)
-- **Issues Found:** 202 scripts with warnings
-- **Doc:** [shellcheck-setup.md](shellcheck-setup.md)
-
-## Current Status
-
-| Item | Status | Next Step |
-|------|--------|-----------|
-| Static analysis | ✅ Working | Fix api.c:355 issue |
-| Test infrastructure | ✅ Working | Add more tests |
-| Test coverage | 🟡 Minimal | Test more functions |
-| CI/CD | ❌ Not set up | Add GitHub Actions (later) |
-
-## Files Added
-
-```
-.cppcheck-suppressions # What to ignore in static analysis
-Makefile.qa # QA commands (lint, test)
-tests/unity/ # Unity test framework
-tests/utils/ # Test files
-docs/static-analysis-setup.md
-docs/testing-setup.md
-docs/QA-README.md # This file
-```
-
-## Philosophy
-
-**Start gentle, tighten gradually:**
-
-1. ✅ **Phase 1 (Now):** Forgiving rules, find serious issues
-2. ⏭️ **Phase 2:** Fix found issues, add more tests
-3. ⏭️ **Phase 3:** Enable stricter rules (style, performance)
-4. ⏭️ **Phase 4:** Enforce in CI
-
-## Real Issue Found
-
-**api.c:355 - Undefined Behavior**
-```c
-uint32_t of = ((sum < c1) | (ret < sum)) << 31;
-```
-
-Shifting signed 32-bit value by 31 bits is undefined.
-
-**Impact:** May cause incorrect calculations.
-
-**Priority:** Medium (should fix)
-
-## Commands Reference
-
-```bash
-# Static analysis
-make -f Makefile.qa lint # Quick check (common code)
-make -f Makefile.qa lint-full # Full check (all code)
-make -f Makefile.qa report # Generate report file
-
-# Testing
-make -f Makefile.qa test # Run all tests
-
-# Cleanup
-make -f Makefile.qa clean-tests # Clean test artifacts
-make -f Makefile.qa clean-qa # Clean all QA artifacts
-
-# Help
-make -f Makefile.qa help # Show all commands
-```
-
-## Integration with Development
-
-### Before Committing
-```bash
-make -f Makefile.qa lint test
-```
-
-### When Refactoring
-```bash
-# 1. Write tests first
-# 2. Refactor code
-# 3. Run tests to verify
-make -f Makefile.qa test
-```
-
-### When Adding Features
-```bash
-# 1. Run lint to check new code
-make -f Makefile.qa lint
-
-# 2. Add tests for new functionality
-# 3. Verify tests pass
-make -f Makefile.qa test
-```
-
-## Next Steps
-
-### Immediate
-1. Fix api.c:355 undefined behavior
-2. Add tests for more utils functions
-3. Document safe coding patterns
-
-### Near Term (1-2 months)
-4. Add tests for config parsing
-5. Add tests for save state logic
-6. Enable style checking in cppcheck
-
-### Long Term (3-6 months)
-7. Increase test coverage to 40%+
-8. Add integration tests
-9. Set up CI/CD
-10. Make lint/test mandatory for PRs
-
-## Resources
-
-- [Static Analysis Setup](static-analysis-setup.md) - Detailed cppcheck guide
-- [Testing Setup](testing-setup.md) - Detailed testing guide
-- [Improvement Plan](improvement-plan.md) - Full quality improvement roadmap
-- [Unity Framework](https://github.com/ThrowTheSwitch/Unity) - Test framework docs
-
-## Success Metrics
-
-### Current
-- ✅ Static analysis running
-- ✅ 9 tests passing
-- ✅ 1 real issue found
-
-### 1 Month
-- ⏭️ Real issue fixed
-- ⏭️ 20+ tests
-- ⏭️ Test more modules
-
-### 3 Months
-- ⏭️ 100+ tests
-- ⏭️ CI running
-- ⏭️ Style checking enabled
diff --git a/docs/README.md b/docs/README.md
deleted file mode 100644
index c49d697d..00000000
--- a/docs/README.md
+++ /dev/null
@@ -1,56 +0,0 @@
-# MinUI Technical Documentation
-
-Welcome to the MinUI technical documentation. This documentation provides comprehensive information about MinUI's architecture, components, and development.
-
-## Documentation Structure
-
-### Getting Started
-- [Architecture Overview](architecture.md) - High-level system design and philosophy
-- [Project Structure](project-structure.md) - Directory layout and organization
-- [Build System](build-system.md) - How to build MinUI from source
-
-### Core Systems
-- [Component Guide](components.md) - Detailed breakdown of all components
-- [Platform Abstraction](platform-abstraction.md) - How platform support works
-- [Pak System](pak-system.md) - Plugin architecture for emulators and tools
-
-### Development
-- [Development Guide](development-guide.md) - How to contribute and develop
-- [Adding Platform Support](adding-platform.md) - Creating new platform ports
-- [API Reference](api-reference.md) - Core APIs and functions
-
-### Reference
-- [Supported Platforms](platforms.md) - All supported devices and their details
-- [File Formats](file-formats.md) - Configuration files and data structures
-- [Troubleshooting](troubleshooting.md) - Common issues and solutions
-
-## Quick Links
-
-- [Main README](../README.md)
-- [PAK Creation Guide](../PAKS.md)
-- [User Guide](../skeleton/BASE/README.txt)
-
-## About MinUI
-
-MinUI is a minimal frontend launcher and libretro-based retro gaming environment designed for handheld Linux devices. It prioritizes:
-
-- **Minimal resource usage** - Fast, lightweight C code
-- **Direct hardware access** - No heavy frameworks or abstractions
-- **Clean UI/UX** - Simple, intuitive navigation
-- **Portability** - Support for 12+ device families
-- **Extensibility** - Pak system for custom emulators and tools
-
-## Key Statistics
-
-- **Language**: C (C99 standard with GNU extensions)
-- **Lines of Code**: ~30,000+ lines of C
-- **Supported Platforms**: 12+ device families
-- **Supported Consoles**: 8 stock + 6 additional emulators
-- **Build System**: Docker-based cross-compilation
-- **Dependencies**: SDL, libretro cores, minimal system libraries
-
-## Development Status
-
-MinUI is currently in a **deprecated maintenance mode** for the existing codebase. All current platforms are marked as deprecated, but the system remains functional and widely used.
-
-This documentation aims to preserve knowledge about the system architecture and enable continued development and improvements.
diff --git a/docs/api-reference.md b/docs/api-reference.md
deleted file mode 100644
index 504a7539..00000000
--- a/docs/api-reference.md
+++ /dev/null
@@ -1,1103 +0,0 @@
-# MinUI API Reference
-
-Complete reference for MinUI's common APIs and platform abstraction layer.
-
-## Graphics API (GFX_*)
-
-Defined in: `/workspace/all/common/api.c`, `/workspace/all/common/api.h`
-
-### Initialization
-
-#### `void GFX_init(void)`
-
-Initializes the graphics subsystem.
-
-**Description:**
-- Sets up SDL video mode
-- Loads UI assets
-- Initializes fonts
-- Prepares rendering surfaces
-
-**Called by:** MinUI, Minarch, utilities
-**Must call:** Before any other GFX functions
-
----
-
-#### `void GFX_quit(void)`
-
-Shuts down graphics subsystem.
-
-**Description:**
-- Frees all loaded assets
-- Closes fonts
-- Releases video resources
-
-**Called by:** Application exit
-**Must call:** After all GFX operations complete
-
----
-
-### Display Management
-
-#### `void GFX_clear(void)`
-
-Clears the screen to black.
-
-**Description:**
-- Fills screen with color 0x0000 (black)
-- Typically called at start of frame
-
----
-
-#### `void GFX_flip(void)`
-
-Presents the rendered frame.
-
-**Description:**
-- Swaps front/back buffers (double-buffered mode)
-- Or copies buffer to display (single-buffered)
-- Equivalent to SDL_Flip
-
-**Frame timing:** Should be called once per frame (~60 Hz)
-
----
-
-#### `void GFX_sync(void)`
-
-Waits for vertical sync.
-
-**Description:**
-- Blocks until next v-sync
-- Prevents screen tearing
-- May delegate to `PLAT_vsync()`
-
----
-
-### Asset Loading
-
-#### `SDL_Surface* GFX_loadImage(const char* path)`
-
-Loads a PNG image.
-
-**Parameters:**
-- `path` - File path to PNG image
-
-**Returns:**
-- `SDL_Surface*` - Loaded image surface
-- `NULL` - On error
-
-**Description:**
-- Loads PNG from disk
-- Converts to screen format
-- Caches for performance
-- Caller must NOT free (managed internally)
-
-**Example:**
-```c
-SDL_Surface* icon = GFX_loadImage("icon.png");
-if (icon) {
- GFX_blitImage(icon, x, y);
-}
-```
-
----
-
-#### `void GFX_freeImage(SDL_Surface* image)`
-
-Frees a loaded image.
-
-**Parameters:**
-- `image` - Surface to free
-
-**Description:**
-- Releases image memory
-- Removes from cache
-- Safe to call with NULL
-
----
-
-#### `void GFX_blitImage(SDL_Surface* src, int x, int y)`
-
-Draws an image to screen.
-
-**Parameters:**
-- `src` - Source surface
-- `x` - X coordinate
-- `y` - Y coordinate
-
-**Description:**
-- Blits entire source surface
-- Top-left corner at (x, y)
-- Respects alpha channel
-
----
-
-### Text Rendering
-
-#### `TTF_Font* GFX_openFont(const char* path, int size)`
-
-Opens a TrueType font.
-
-**Parameters:**
-- `path` - Font file path
-- `size` - Point size (16, 20, 24, 32, 40)
-
-**Returns:**
-- `TTF_Font*` - Loaded font
-- `NULL` - On error
-
-**Description:**
-- Loads TTF/OTF font
-- Opens at specified point size
-- Caches fonts by path+size
-- Caller must NOT free
-
-**Example:**
-```c
-TTF_Font* font = GFX_openFont("font.otf", 20);
-```
-
----
-
-#### `void GFX_closeFont(TTF_Font* font)`
-
-Closes a font.
-
-**Parameters:**
-- `font` - Font to close
-
-**Description:**
-- Releases font resources
-- Removes from cache
-- Safe to call with NULL
-
----
-
-#### `void GFX_drawText(int x, int y, const char* text, TTF_Font* font, uint32_t color)`
-
-Renders text to screen.
-
-**Parameters:**
-- `x` - X coordinate
-- `y` - Y coordinate (baseline)
-- `text` - UTF-8 string
-- `font` - Font to use
-- `color` - RGB888 color (0xRRGGBB)
-
-**Description:**
-- Renders text with anti-aliasing
-- Color converted to screen format
-- Alpha blending enabled
-
-**Example:**
-```c
-GFX_drawText(10, 30, "Hello World", font, 0xFFFFFF);
-```
-
----
-
-#### `int GFX_getTextWidth(const char* text, TTF_Font* font)`
-
-Measures text width.
-
-**Parameters:**
-- `text` - String to measure
-- `font` - Font to use
-
-**Returns:**
-- `int` - Width in pixels
-
-**Description:**
-- Calculates rendered width
-- Useful for centering/alignment
-
-**Example:**
-```c
-int width = GFX_getTextWidth("Hello", font);
-int x = (FIXED_WIDTH - width) / 2; // Center
-GFX_drawText(x, y, "Hello", font, color);
-```
-
----
-
-### UI Elements
-
-#### `void GFX_drawPill(int x, int y, int w, int h, uint32_t color)`
-
-Draws a rounded rectangle (pill shape).
-
-**Parameters:**
-- `x`, `y` - Top-left corner
-- `w`, `h` - Width and height
-- `color` - RGB888 color
-
-**Description:**
-- Filled rounded rectangle
-- Used for buttons, selections
-- Corner radius automatic based on height
-
----
-
-#### `void GFX_drawButton(int x, int y, const char* text, int selected)`
-
-Draws a UI button.
-
-**Parameters:**
-- `x`, `y` - Position
-- `text` - Button label
-- `selected` - 1 if selected, 0 otherwise
-
-**Description:**
-- Draws pill background
-- Renders text centered
-- Different colors for selected/unselected
-
----
-
-#### `void GFX_drawBattery(int x, int y, int level, int charging)`
-
-Draws battery indicator.
-
-**Parameters:**
-- `x`, `y` - Position
-- `level` - Battery percentage (0-100)
-- `charging` - 1 if charging, 0 otherwise
-
-**Description:**
-- Draws battery icon
-- Fill indicates level
-- Lightning bolt if charging
-
----
-
-#### `void GFX_drawVolume(int x, int y, int level)`
-
-Draws volume indicator.
-
-**Parameters:**
-- `x`, `y` - Position
-- `level` - Volume (0-20)
-
-**Description:**
-- Draws speaker icon
-- Bars indicate level
-
----
-
-#### `void GFX_drawBrightness(int x, int y, int level)`
-
-Draws brightness indicator.
-
-**Parameters:**
-- `x`, `y` - Position
-- `level` - Brightness (0-10)
-
-**Description:**
-- Draws sun icon
-- Brightness indicates level
-
----
-
-## Sound API (SND_*)
-
-Defined in: `/workspace/all/common/api.c`, `/workspace/all/common/api.h`
-
-### Initialization
-
-#### `void SND_init(void)`
-
-Initializes audio subsystem.
-
-**Description:**
-- Opens audio device
-- Sets up ring buffer
-- Configures sample rate (44100 or 48000 Hz)
-
----
-
-#### `void SND_quit(void)`
-
-Shuts down audio.
-
-**Description:**
-- Closes audio device
-- Releases buffers
-
----
-
-### Audio Output
-
-#### `void SND_write(int16_t* samples, int count)`
-
-Writes audio samples.
-
-**Parameters:**
-- `samples` - Interleaved stereo samples (L, R, L, R, ...)
-- `count` - Number of sample *frames* (pairs)
-
-**Description:**
-- Writes to ring buffer
-- Non-blocking (drops if full)
-- Samples are 16-bit signed PCM
-
-**Example:**
-```c
-int16_t buffer[2048]; // 1024 frames
-// ... fill buffer ...
-SND_write(buffer, 1024);
-```
-
----
-
-## Input API (PAD_*)
-
-Defined in: `/workspace/all/common/api.c`, `/workspace/all/common/api.h`
-
-### Initialization
-
-#### `void PAD_init(void)`
-
-Initializes input subsystem.
-
-**Description:**
-- Calls `PLAT_initInput()`
-- Initializes button state tracking
-- Sets up auto-repeat timers
-
----
-
-#### `void PAD_quit(void)`
-
-Shuts down input.
-
-**Description:**
-- Calls `PLAT_quitInput()`
-- Releases input resources
-
----
-
-### Input Polling
-
-#### `void PAD_poll(void)`
-
-Updates button state.
-
-**Description:**
-- Calls `PLAT_pollInput()`
-- Updates button state arrays
-- Handles auto-repeat logic
-
-**Must call:** Once per frame before checking buttons
-
----
-
-#### `int PAD_justPressed(int button)`
-
-Checks if button just pressed.
-
-**Parameters:**
-- `button` - Button ID (BTN_A, BTN_B, etc.)
-
-**Returns:**
-- `1` - Button pressed this frame
-- `0` - Not pressed
-
-**Description:**
-- Edge detection (0 → 1 transition)
-- Returns true only on first frame
-
-**Example:**
-```c
-if (PAD_justPressed(BTN_A)) {
- launchGame();
-}
-```
-
----
-
-#### `int PAD_justRepeated(int button)`
-
-Checks if button auto-repeated.
-
-**Parameters:**
-- `button` - Button ID
-
-**Returns:**
-- `1` - Button repeated this frame
-- `0` - Not repeated
-
-**Description:**
-- Initial delay: 300ms
-- Repeat rate: 100ms
-- Useful for menu navigation
-
-**Example:**
-```c
-if (PAD_justPressed(BTN_UP) || PAD_justRepeated(BTN_UP)) {
- selection--;
-}
-```
-
----
-
-#### `int PAD_justReleased(int button)`
-
-Checks if button just released.
-
-**Parameters:**
-- `button` - Button ID
-
-**Returns:**
-- `1` - Button released this frame
-- `0` - Not released
-
-**Description:**
-- Edge detection (1 → 0 transition)
-
----
-
-#### `int PAD_isPressed(int button)`
-
-Checks if button currently held.
-
-**Parameters:**
-- `button` - Button ID
-
-**Returns:**
-- `1` - Button currently down
-- `0` - Button up
-
-**Description:**
-- Level detection (not edge)
-- True every frame while held
-
----
-
-### Button IDs
-
-```c
-#define BTN_UP 0
-#define BTN_DOWN 1
-#define BTN_LEFT 2
-#define BTN_RIGHT 3
-#define BTN_A 4
-#define BTN_B 5
-#define BTN_X 6
-#define BTN_Y 7
-#define BTN_L1 8
-#define BTN_R1 9
-#define BTN_L2 10
-#define BTN_R2 11
-#define BTN_SELECT 12
-#define BTN_START 13
-#define BTN_MENU 14
-#define BTN_L3 15
-#define BTN_R3 16
-```
-
-**Note:** Not all platforms have all buttons. Check `HAS_X` defines.
-
----
-
-## Power API (PWR_*)
-
-Defined in: `/workspace/all/common/api.c`, `/workspace/all/common/api.h`
-
-### Initialization
-
-#### `void PWR_init(void)`
-
-Initializes power subsystem.
-
-**Description:**
-- Sets up sleep timer
-- Initializes battery monitoring
-- Configures CPU speed
-
----
-
-#### `void PWR_quit(void)`
-
-Shuts down power management.
-
----
-
-### Update
-
-#### `void PWR_update(void)`
-
-Updates power state.
-
-**Description:**
-- Checks for idle timeout
-- Monitors battery status
-- Handles auto-sleep
-- Handles auto-poweroff
-
-**Must call:** Once per frame
-
----
-
-### Battery
-
-#### `int PWR_getBatteryLevel(void)`
-
-Gets battery percentage.
-
-**Returns:**
-- `0-100` - Battery percentage
-- `-1` - Unknown/AC powered
-
-**Description:**
-- Calls `PLAT_getBatteryStatus()`
-- Cached, updated periodically
-
----
-
-#### `int PWR_isCharging(void)`
-
-Checks if charging.
-
-**Returns:**
-- `1` - Charging
-- `0` - Not charging
-
-**Description:**
-- Calls `PLAT_getBatteryStatus()`
-
----
-
-### Sleep/Power
-
-#### `void PWR_sleep(void)`
-
-Enters sleep mode.
-
-**Description:**
-- Disables backlight
-- Reduces CPU speed
-- Waits for wake button
-
----
-
-#### `void PWR_wake(void)`
-
-Exits sleep mode.
-
-**Description:**
-- Restores backlight
-- Restores CPU speed
-- Resets idle timer
-
----
-
-#### `void PWR_powerOff(void)`
-
-Shuts down device.
-
-**Description:**
-- Saves state
-- Calls `PLAT_powerOff()`
-- Does not return
-
----
-
-### CPU Speed
-
-#### `int PWR_getCPUSpeed(void)`
-
-Gets current CPU frequency.
-
-**Returns:**
-- `int` - Frequency in MHz
-
----
-
-#### `void PWR_setCPUSpeed(int mhz)`
-
-Sets CPU frequency.
-
-**Parameters:**
-- `mhz` - Frequency in MHz
-
-**Description:**
-- Calls `PLAT_setCPUSpeed()`
-- Platform-dependent valid values
-
----
-
-## Platform Abstraction Layer (PLAT_*)
-
-Defined in: `/workspace/[platform]/platform/platform.c`, `platform.h`
-
-Each platform must implement these functions.
-
-### Video
-
-#### `void PLAT_initVideo(void)`
-
-Initializes video.
-
-**Description:**
-- Opens framebuffer or SDL window
-- Sets up display surfaces
-- Configures scaling
-
----
-
-#### `void PLAT_quitVideo(void)`
-
-Shuts down video.
-
----
-
-#### `void PLAT_clearVideo(void)`
-
-Clears video memory.
-
----
-
-#### `void PLAT_setVsync(int enabled)`
-
-Enables/disables vsync.
-
----
-
-#### `void PLAT_vsync(void)`
-
-Waits for vsync.
-
----
-
-#### `void PLAT_flip(void)`
-
-Swaps buffers.
-
----
-
-#### `SDL_Surface* PLAT_getScreen(void)`
-
-Gets screen surface.
-
-**Returns:**
-- `SDL_Surface*` - Main screen surface
-
----
-
-### Input
-
-#### `void PLAT_initInput(void)`
-
-Initializes input devices.
-
----
-
-#### `void PLAT_quitInput(void)`
-
-Shuts down input.
-
----
-
-#### `void PLAT_pollInput(void)`
-
-Polls input state.
-
-**Description:**
-- Reads all input devices
-- Updates button state arrays
-- Handles analog sticks
-
----
-
-### Power
-
-#### `int PLAT_getBatteryStatus(void)`
-
-Gets battery info.
-
-**Returns:**
-- `0-100` - Battery percentage
-- `101-200` - Charging (subtract 100 for %)
-- `-1` - Unknown
-
----
-
-#### `void PLAT_enableBacklight(int enable)`
-
-Controls backlight.
-
-**Parameters:**
-- `enable` - 1 to enable, 0 to disable
-
----
-
-#### `void PLAT_powerOff(void)`
-
-Powers off device.
-
-**Description:**
-- Hardware shutdown
-- Does not return
-
----
-
-#### `void PLAT_setCPUSpeed(int speed)`
-
-Sets CPU frequency.
-
-**Parameters:**
-- `speed` - CPU speed index (platform-specific)
-
----
-
-### Scaling (Optional)
-
-#### `void PLAT_scale(SDL_Surface* src, SDL_Rect* src_rect, SDL_Surface* dst, SDL_Rect* dst_rect, int sharp, int effect)`
-
-Hardware-accelerated scaling.
-
-**Parameters:**
-- `src` - Source surface
-- `src_rect` - Source rectangle
-- `dst` - Destination surface
-- `dst_rect` - Destination rectangle
-- `sharp` - Sharpness mode (0-2)
-- `effect` - Effect mode (0-2)
-
-**Description:**
-- Platform may provide hardware scaling
-- Falls back to software if not implemented
-
----
-
-## Settings Library (libmsettings)
-
-Defined in: `/workspace/[platform]/libmsettings/msettings.c`, `msettings.h`
-
-### Initialization
-
-#### `int InitSettings(void)`
-
-Initializes settings system.
-
-**Returns:**
-- `0` - Success
-- `-1` - Error
-
----
-
-#### `void QuitSettings(void)`
-
-Saves and closes settings.
-
----
-
-### Volume
-
-#### `int GetVolume(void)`
-
-Gets volume level.
-
-**Returns:**
-- `0-20` - Volume level
-
----
-
-#### `void SetVolume(int value)`
-
-Sets volume level.
-
-**Parameters:**
-- `value` - Volume (0-20)
-
-**Description:**
-- Adjusts hardware mixer
-- Persists to settings file
-
----
-
-### Brightness
-
-#### `int GetBrightness(void)`
-
-Gets brightness level.
-
-**Returns:**
-- `0-10` - Brightness level
-
----
-
-#### `void SetBrightness(int value)`
-
-Sets brightness level.
-
-**Parameters:**
-- `value` - Brightness (0-10)
-
-**Description:**
-- Adjusts backlight via sysfs
-- Persists to settings file
-
----
-
-### Last Play
-
-#### `char* GetLastPlay(void)`
-
-Gets last played ROM path.
-
-**Returns:**
-- `char*` - Full path to ROM
-- `NULL` - No last play
-
----
-
-#### `void SetLastPlay(char* path)`
-
-Sets last played ROM.
-
-**Parameters:**
-- `path` - Full ROM path
-
-**Description:**
-- Saves for auto-resume
-- Used by MinUI launcher
-
----
-
-## Utility Functions
-
-Defined in: `/workspace/all/common/utils.c`, `utils.h`
-
-### File Operations
-
-#### `int exists(const char* path)`
-
-Checks if file exists.
-
-**Returns:**
-- `1` - Exists
-- `0` - Does not exist
-
----
-
-#### `int isDir(const char* path)`
-
-Checks if path is directory.
-
-**Returns:**
-- `1` - Is directory
-- `0` - Not directory or doesn't exist
-
----
-
-#### `void makeDir(const char* path)`
-
-Creates directory.
-
-**Parameters:**
-- `path` - Directory path
-
-**Description:**
-- Creates if doesn't exist
-- No error if already exists
-
----
-
-### String Operations
-
-#### `int exactMatch(const char* str, const char* find)`
-
-Case-sensitive exact match.
-
-**Returns:**
-- `1` - Strings match
-- `0` - Don't match
-
----
-
-#### `int prefixMatch(const char* str, const char* prefix)`
-
-Checks if string starts with prefix.
-
-**Returns:**
-- `1` - Starts with prefix
-- `0` - Doesn't start with prefix
-
----
-
-#### `int suffixMatch(const char* str, const char* suffix)`
-
-Checks if string ends with suffix.
-
-**Returns:**
-- `1` - Ends with suffix
-- `0` - Doesn't end with suffix
-
-**Example:**
-```c
-if (suffixMatch(filename, ".gb")) {
- // It's a Game Boy ROM
-}
-```
-
----
-
-### Path Operations
-
-#### `const char* getFilename(const char* path)`
-
-Extracts filename from path.
-
-**Parameters:**
-- `path` - Full path
-
-**Returns:**
-- `const char*` - Filename portion
-
-**Example:**
-```c
-getFilename("/path/to/file.txt") // Returns "file.txt"
-```
-
----
-
-#### `const char* getExtension(const char* path)`
-
-Gets file extension.
-
-**Parameters:**
-- `path` - Filename or path
-
-**Returns:**
-- `const char*` - Extension (including dot)
-- `""` - No extension
-
-**Example:**
-```c
-getExtension("file.txt") // Returns ".txt"
-```
-
----
-
-#### `void trimExtension(char* path)`
-
-Removes file extension.
-
-**Parameters:**
-- `path` - Path to modify (in-place)
-
-**Example:**
-```c
-char name[256] = "game.gb";
-trimExtension(name);
-// name is now "game"
-```
-
----
-
-## Constants and Macros
-
-### Screen
-
-```c
-#define FIXED_WIDTH 640 // Platform-specific
-#define FIXED_HEIGHT 480 // Platform-specific
-#define FIXED_BPP 16 // Always 16-bit
-#define FIXED_SCALE 2 // UI scale factor
-```
-
-### Paths
-
-```c
-#define SDCARD_PATH "/mnt/SDCARD" // Platform-specific
-#define ROMS_PATH SDCARD_PATH "/Roms"
-#define SAVES_PATH SDCARD_PATH "/Saves"
-#define BIOS_PATH SDCARD_PATH "/Bios"
-```
-
-### Colors
-
-```c
-#define COLOR_BLACK 0x0000
-#define COLOR_WHITE 0xFFFF
-#define COLOR_RED 0xF800
-#define COLOR_GREEN 0x07E0
-#define COLOR_BLUE 0x001F
-```
-
-### Timing
-
-```c
-#define FRAME_RATE 60 // Target FPS
-#define SLEEP_TIMEOUT 30000 // 30 seconds
-#define POWEROFF_TIME 120000 // 2 minutes
-```
-
----
-
-## Usage Examples
-
-### Simple Application
-
-```c
-#include "common/api.h"
-
-int main(int argc, char* argv[]) {
- // Initialize
- GFX_init();
- PAD_init();
- PWR_init();
-
- TTF_Font* font = GFX_openFont("font.otf", 20);
-
- // Main loop
- int running = 1;
- while (running) {
- PAD_poll();
- PWR_update();
-
- if (PAD_justPressed(BTN_START)) {
- running = 0;
- }
-
- GFX_clear();
- GFX_drawText(10, 30, "Hello MinUI!", font, 0xFFFFFF);
- GFX_flip();
- }
-
- // Cleanup
- PWR_quit();
- PAD_quit();
- GFX_quit();
-
- return 0;
-}
-```
-
-### Menu System
-
-```c
-int selection = 0;
-int max_items = 10;
-
-while (running) {
- PAD_poll();
-
- if (PAD_justPressed(BTN_UP) || PAD_justRepeated(BTN_UP)) {
- selection = (selection - 1 + max_items) % max_items;
- }
- if (PAD_justPressed(BTN_DOWN) || PAD_justRepeated(BTN_DOWN)) {
- selection = (selection + 1) % max_items;
- }
- if (PAD_justPressed(BTN_A)) {
- activateItem(selection);
- }
-
- GFX_clear();
- for (int i = 0; i < max_items; i++) {
- GFX_drawButton(10, 30 + i * 40, items[i], i == selection);
- }
- GFX_flip();
-}
-```
diff --git a/docs/architecture.md b/docs/architecture.md
deleted file mode 100644
index a185f941..00000000
--- a/docs/architecture.md
+++ /dev/null
@@ -1,302 +0,0 @@
-# MinUI Architecture Overview
-
-## Design Philosophy
-
-MinUI follows a minimalist, hardware-first approach to retro gaming on handheld devices:
-
-1. **Minimal Dependencies** - Direct hardware access, no heavy frameworks
-2. **Fast Performance** - Optimized C code with NEON acceleration where applicable
-3. **Clean Abstraction** - Platform-specific code isolated from core logic
-4. **Extensible Design** - Pak system allows customization without core changes
-5. **User-Focused** - Simple UI, instant resume, automatic state management
-
-## System Architecture
-
-```
-┌─────────────────────────────────────────────────────────────┐
-│ User Layer │
-│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
-│ │ MinUI │ │ Minarch │ │ Clock │ │ Tools │ │
-│ │ Launcher │ │ Frontend │ │ Utils │ │ (Paks) │ │
-│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
-└─────────────────────────────────────────────────────────────┘
- ↓
-┌─────────────────────────────────────────────────────────────┐
-│ Common API Layer │
-│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
-│ │ GFX │ │ SND │ │ PAD │ │ PWR │ │
-│ │ Graphics │ │ Audio │ │ Input │ │ Power │ │
-│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
-│ ┌──────────┐ ┌──────────┐ │
-│ │ Scaler │ │ Utils │ │
-│ │ Renderer │ │ Helpers │ │
-│ └──────────┘ └──────────┘ │
-└─────────────────────────────────────────────────────────────┘
- ↓
-┌─────────────────────────────────────────────────────────────┐
-│ Platform Abstraction Layer │
-│ ┌──────────────────────────────────────────────────────┐ │
-│ │ platform.c / platform.h │ │
-│ │ - Video Init - Input Polling - Power Mgmt │ │
-│ │ - Display - Battery - Sleep/Wake │ │
-│ └──────────────────────────────────────────────────────┘ │
-│ ┌──────────────────────────────────────────────────────┐ │
-│ │ libmsettings (Settings Library) │ │
-│ │ - Volume - Brightness - Persistence │ │
-│ └──────────────────────────────────────────────────────┘ │
-└─────────────────────────────────────────────────────────────┘
- ↓
-┌─────────────────────────────────────────────────────────────┐
-│ Hardware Layer │
-│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
-│ │Framebuffer│ │ Audio │ │ Input │ │ Power │ │
-│ │ /dev │ │ ALSA │ │ evdev │ │ /sys │ │
-│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
-└─────────────────────────────────────────────────────────────┘
-```
-
-## Core Components
-
-### 1. MinUI (Launcher)
-**Location**: `/workspace/all/minui/minui.c`
-
-The main launcher application responsible for:
-- ROM browsing and organization
-- Collections management
-- Recent games tracking
-- Settings display
-- Launching emulator paks
-
-**Key Features**:
-- Smart ROM name display (hides tags, extensions)
-- Automatic resume from last state
-- Fast navigation with pill-style UI
-- Hardware info display (volume, brightness, battery)
-
-### 2. Minarch (Libretro Frontend)
-**Location**: `/workspace/all/minarch/minarch.c`
-
-The emulator frontend that runs libretro cores:
-- Loads and executes emulator cores
-- In-game menu system
-- Save state management (10 slots + auto-resume)
-- Video scaling and effects
-- Audio processing
-- Input remapping
-
-**Key Features**:
-- Quicksave on power-off
-- Auto-resume from slot 9
-- Per-console and per-core configuration
-- Threaded video rendering option
-- Disc changing for multi-disc games
-- Screenshot support
-
-### 3. Common API
-**Location**: `/workspace/all/common/api.c`
-
-Provides unified interfaces for:
-
-**Graphics (GFX_*)**:
-- Asset loading and sprite rendering
-- Text rendering with TTF fonts
-- UI element drawing
-- Frame timing (60 FPS)
-
-**Sound (SND_*)**:
-- Audio initialization
-- Sample buffering
-- Ring buffer management
-
-**Input (PAD_*)**:
-- Button state tracking
-- Auto-repeat logic
-- Analog stick handling
-
-**Power (PWR_*)**:
-- Sleep timer management
-- Battery monitoring
-- Brightness/volume control
-- CPU speed scaling
-
-### 4. Platform Abstraction Layer
-**Location**: `/workspace/[platform]/platform/`
-
-Each platform implements:
-- Video initialization (framebuffer or SDL)
-- Input polling (keyboard, joystick, raw devices)
-- Power management (battery, charging, sleep/wake)
-- Display rendering and scaling
-- Platform-specific features (HDMI, analog sticks, etc.)
-
-### 5. Pak System
-**Location**: `/skeleton/SYSTEM/[platform]/paks/`
-
-Plugin architecture for emulators and tools:
-- Self-contained directories with launch scripts
-- Can bundle custom cores or reuse system cores
-- Configuration system for core options
-- Support for native applications
-
-### 6. Background Services
-
-**keymon** - Input monitor daemon:
-- Monitors hardware buttons
-- Handles global shortcuts
-- Manages sleep/wake events
-
-**syncsettings** - Settings sync daemon:
-- Restores MinUI settings after third-party apps
-- Prevents interference from stock applications
-
-## Data Flow
-
-### ROM Launch Flow
-```
-1. User selects ROM in MinUI
-2. MinUI identifies console type from directory tag
-3. MinUI locates appropriate .pak directory
-4. MinUI executes launch.sh with ROM path
-5. launch.sh sets up environment and calls minarch
-6. minarch loads libretro core
-7. minarch loads ROM and any save states
-8. Core runs game loop
-9. On exit, minarch saves state and settings
-10. Control returns to MinUI
-```
-
-### Video Rendering Flow
-```
-1. Libretro core renders frame to buffer
-2. minarch receives callback with frame data
-3. Software scaler converts and scales (if needed)
-4. GFX API blits to framebuffer or SDL surface
-5. Platform layer presents to display
-6. Frame timing ensures 60 FPS
-```
-
-### Input Processing Flow
-```
-1. keymon monitors raw input devices
-2. Global shortcuts handled by keymon
-3. Platform layer polls input devices
-4. PAD API tracks button states
-5. Applications read button state via PAD_*
-6. minarch maps to libretro inputs
-7. Core receives input callbacks
-```
-
-## Build Architecture
-
-### Docker Toolchain System
-```
-Host Machine (macOS/Linux)
- ↓
-Master Makefile
- ↓
-Docker Container (per-platform toolchain)
- ↓
-Platform Builds (cross-compilation)
- ↓
-Skeleton Population (file copying)
- ↓
-Release Packaging (.zip files)
-```
-
-### Compilation Model
-- Host-driven orchestration
-- Docker containers for reproducible builds
-- Cross-compilation for ARM targets
-- Shared code compiled per-platform
-- Platform code linked into each binary
-
-## File System Layout
-
-### SD Card Structure
-```
-/
-├── BOOT/ # Bootstrap files
-├── SYSTEM/ # MinUI system files
-│ ├── res/ # Shared resources (fonts, assets)
-│ └── [platform]/ # Platform-specific files
-│ ├── bin/ # Executables (.elf)
-│ ├── lib/ # Libraries (.so)
-│ ├── cores/ # Libretro cores
-│ └── paks/ # System paks
-│ └── Emus/ # Emulator paks
-└── BASE/ # User-facing content
- ├── Roms/ # ROM directories
- ├── Saves/ # Save states/RAM
- └── Bios/ # BIOS files
-```
-
-## Key Design Patterns
-
-### 1. Hardware Abstraction Layer (HAL)
-Platform-specific code isolated in platform.c, common code uses standard API.
-
-### 2. Plugin Architecture
-Paks allow extensibility without modifying core code.
-
-### 3. Libretro Integration
-Standard interface for emulator cores enables easy addition of new consoles.
-
-### 4. Double Buffering
-Page flipping for smooth graphics without tearing.
-
-### 5. Ring Buffers
-Lock-free audio buffers for low-latency sound.
-
-### 6. State Management
-Automatic saving and resuming of game states.
-
-### 7. Daemon Pattern
-Background services (keymon, syncsettings) for system-wide functionality.
-
-## Performance Optimizations
-
-1. **NEON Intrinsics** - ARM SIMD for video scaling
-2. **Direct Hardware Access** - Bypass abstraction layers
-3. **Minimal Allocations** - Stack allocation where possible
-4. **Software Rendering** - Full control over display pipeline
-5. **Threaded Video** - Optional async rendering
-6. **Asset Caching** - Load graphics once
-7. **Ring Buffers** - Lock-free audio
-
-## Portability Strategy
-
-### Platform Independence
-- Core logic in `/workspace/all/`
-- No platform-specific code in common files
-- SDL abstraction where appropriate
-
-### Platform Specifics
-- Each platform in `/workspace/[platform]/`
-- Platform HAL implements standard interface
-- Build system selects platform at compile time
-
-### Extensibility
-- Pak system for user additions
-- Configuration files for customization
-- Launch scripts for flexibility
-
-## Security Considerations
-
-MinUI runs with full system privileges on most platforms:
-- Direct hardware access required for performance
-- No sandboxing or privilege separation
-- Trust model: user controls all content
-- Paks can execute arbitrary code
-
-This is acceptable for single-user gaming devices but would require hardening for multi-user or networked environments.
-
-## Limitations and Trade-offs
-
-1. **RGB565 Only** - No 24-bit color support (performance)
-2. **No OpenGL** - Software rendering only (portability)
-3. **SDL 1.2/2.0** - Older libraries for broader support
-4. **Single-threaded** - Mostly single-threaded (simplicity)
-5. **No Audio Resampling** - Core must match device rate
-6. **Platform Coupling** - Some platform quirks leak into common code
-
-These trade-offs prioritize performance, portability, and simplicity over flexibility and modern best practices.
diff --git a/docs/build-fixes.md b/docs/build-fixes.md
deleted file mode 100644
index b1c0c7de..00000000
--- a/docs/build-fixes.md
+++ /dev/null
@@ -1,216 +0,0 @@
-# MinUI Build Fixes
-
-This document describes fixes applied to the MinUI build system to address common issues.
-
-## Automatic Dockerfile Patching
-
-**Problem:** The external toolchain repositories use Debian Buster, which was archived in 2022 and is no longer available from standard Debian mirrors.
-
-**Error:**
-```
-Err:4 http://deb.debian.org/debian buster Release
- 404 Not Found
-E: The repository 'http://deb.debian.org/debian buster Release' does not have a Release file.
-```
-
-**Solution:** The `makefile.toolchain` now automatically patches Dockerfiles when cloning toolchain repositories.
-
-### What Gets Patched
-
-When a toolchain is cloned, the following changes are automatically applied to the Dockerfile:
-
-1. **Keeps Debian Buster** - No version change to avoid compatibility issues
-2. **Redirects apt to archive.debian.org** - Points to where Buster packages are still available
-3. **Adds all three repos**:
- - `deb http://archive.debian.org/debian buster main`
- - `deb http://archive.debian.org/debian-security buster/updates main`
- - `deb http://archive.debian.org/debian buster-updates main`
-4. **Disables apt valid-until check** - Archived repos don't get updates, so this prevents errors
-
-### Implementation
-
-The patching happens in `/makefile.toolchain`:
-
-```makefile
-$(GIT_IF_NECESSARY):
- mkdir -p toolchains
- git clone https://github.com/shauninman/union-$(PLATFORM)-toolchain/ toolchains/$(PLATFORM)-toolchain
- @echo "Patching Dockerfile for archived Debian versions..."
- @if [ -f toolchains/$(PLATFORM)-toolchain/Dockerfile ]; then \
- DOCKERFILE=toolchains/$(PLATFORM)-toolchain/Dockerfile; \
- if grep -q "^FROM debian:buster" $$DOCKERFILE; then \
- awk '/^FROM debian:buster/ {print; print "RUN echo \"deb http://archive.debian.org/debian buster main\" > /etc/apt/sources.list && \\"; print " echo \"deb http://archive.debian.org/debian-security buster/updates main\" >> /etc/apt/sources.list && \\"; print " echo \"deb http://archive.debian.org/debian buster-updates main\" >> /etc/apt/sources.list && \\"; print " echo \"Acquire::Check-Valid-Until false;\" > /etc/apt/apt.conf.d/99no-check-valid-until"; next}1' $$DOCKERFILE > $$DOCKERFILE.tmp && \
- mv $$DOCKERFILE.tmp $$DOCKERFILE; \
- echo "✓ Dockerfile patched successfully"; \
- else \
- echo "✓ No Debian Buster found, skipping patch"; \
- fi; \
- fi
-```
-
-### How It Works
-
-The script uses `awk` to:
-1. Find the `FROM debian:buster*` line
-2. Insert a new `RUN` command immediately after it that:
- - **Overwrites** `/etc/apt/sources.list` with archive.debian.org URLs
- - Adds all three Debian repos (main, security, updates)
- - Creates apt config to disable valid-until checking
-
-**Why awk instead of sed?**
-- Works identically on macOS (BSD) and Linux (GNU)
-- No need for platform-specific syntax
-- Cleaner multi-line insertion
-
-**Why overwrite sources.list?**
-- Old URLs (`deb.debian.org`) return 404 errors
-- Clean replacement = no failed connection attempts
-- Matches original repo structure (main, security, updates)
-
-### Verification
-
-After cloning a toolchain, you can verify the patch was applied:
-
-```bash
-head -10 toolchains/rg35xx-toolchain/Dockerfile
-```
-
-Should show:
-```dockerfile
-FROM debian:buster-slim
-RUN echo "deb http://archive.debian.org/debian buster main" > /etc/apt/sources.list && \
- echo "deb http://archive.debian.org/debian-security buster/updates main" >> /etc/apt/sources.list && \
- echo "deb http://archive.debian.org/debian buster-updates main" >> /etc/apt/sources.list && \
- echo "Acquire::Check-Valid-Until false;" > /etc/apt/apt.conf.d/99no-check-valid-until
-ENV DEBIAN_FRONTEND noninteractive
-```
-
-### Future-Proofing
-
-When Debian Bullseye eventually gets archived, this approach can be updated to patch to a newer version (e.g., Debian Bookworm) without modifying the external toolchain repositories.
-
-To update to a newer Debian version in the future, simply modify the sed patterns in `makefile.toolchain`.
-
-## Why This Approach?
-
-Instead of forking all 12+ toolchain repositories, this approach:
-
-1. **Avoids maintenance burden** - No need to maintain forked repos
-2. **Stays up-to-date** - Gets updates from upstream repos automatically
-3. **Transparent** - Clearly shows what's being modified
-4. **Future-proof** - Easy to update for future Debian versions
-5. **Zero friction** - Users don't need to do anything special
-
-## Resetting the Build Environment
-
-### Quick Clean (Build Artifacts Only)
-```bash
-make clean
-```
-Removes `./build/` directory but keeps toolchains and Docker images.
-
-### Full Reset (Start Fresh)
-```bash
-# Remove build artifacts
-make clean
-
-# Remove downloaded toolchains
-rm -rf toolchains/
-
-# Remove releases (optional)
-rm -rf releases/
-```
-
-### Per-Platform Reset
-```bash
-# Remove specific toolchain and rebuild
-rm -rf toolchains/miyoomini-toolchain
-make PLATFORM=miyoomini
-
-# Or clean Docker image only (keeps toolchain source)
-make -f makefile.toolchain PLATFORM=miyoomini clean
-```
-
-### Nuclear Option (Complete Wipe)
-```bash
-# Clean everything
-make clean
-rm -rf toolchains/ releases/ build/
-
-# Also remove Docker images
-docker images | grep toolchain | awk '{print $3}' | xargs docker rmi
-```
-
-## Troubleshooting
-
-### Patch didn't apply
-
-If the Dockerfile wasn't patched automatically:
-
-```bash
-# Remove and re-clone
-rm -rf toolchains/miyoomini-toolchain
-make -f makefile.toolchain PLATFORM=miyoomini toolchains/miyoomini-toolchain
-```
-
-### Manual patching
-
-If you need to manually patch a Dockerfile:
-
-```bash
-cd toolchains/miyoomini-toolchain
-sed -i 's/debian:buster/debian:bullseye/g' Dockerfile # Linux
-# or
-sed -i '' 's/debian:buster/debian:bullseye/g' Dockerfile # macOS
-```
-
-### Still getting 404 errors
-
-If you still see 404 errors after patching:
-
-1. Check if Docker has cached the old Buster image:
- ```bash
- docker images | grep buster
- docker rmi debian:buster-slim # Remove if present
- ```
-
-2. Force rebuild:
- ```bash
- cd toolchains/miyoomini-toolchain
- make clean
- make .build
- ```
-
-## Obsolete PokeMini Patch Removed
-
-**Problem:** The pokemini core build was failing with:
-```
-error: patch failed: source/PokeMini.c:489
-error: source/PokeMini.c: patch does not apply
-```
-
-**Root Cause:** The patch `workspace/all/cores/patches/pokemini/0001-fix-resume-audio.patch` was attempting to fix a bug where `"LCD-"` should have been `"AUD-"` for audio state loading. However, upstream pokemini has since fixed this bug, making the patch obsolete and causing conflicts.
-
-**Solution:** Removed the obsolete patch directory `workspace/all/cores/patches/pokemini/` since the fix is now included in the upstream libretro pokemini core.
-
-**Verification:**
-```bash
-# Check that upstream has the fix
-grep "AUD-" workspace/miyoomini/cores/src/pokemini/source/PokeMini.c
-# Should show line 407: } else if (!strcmp(PMiniStr, "AUD-")) {
-```
-
-## Related Issues
-
-This document addresses:
-- Debian Buster 404 errors (archived ~June 2022)
-- PokeMini patch conflicts (fixed upstream)
-- Affected platforms: All (miyoomini, rg35xx, trimuismart, etc.)
-
-## Contributing
-
-If you encounter other build system issues, please:
-1. Document the problem
-2. Propose a fix
-3. Test on both macOS and Linux (if possible)
-4. Add to this document
diff --git a/docs/build-system.md b/docs/build-system.md
deleted file mode 100644
index cffe9ab3..00000000
--- a/docs/build-system.md
+++ /dev/null
@@ -1,638 +0,0 @@
-# MinUI Build System
-
-This document explains how to build MinUI from source, including the build system architecture and toolchain setup.
-
-## Overview
-
-MinUI uses a Docker-based cross-compilation system that:
-- Builds for 12+ ARM platforms from a macOS/Linux host
-- Uses platform-specific toolchain containers
-- Produces ready-to-deploy SD card images
-- Creates release packages automatically
-
-## Build System Architecture
-
-```
-┌─────────────────────────────────────────────┐
-│ Host Machine (macOS/Linux) │
-│ │
-│ ┌────────────────────────────────────┐ │
-│ │ /makefile (Master Build) │ │
-│ │ - Setup skeleton │ │
-│ │ - Invoke Docker for each platform │ │
-│ │ - Package releases │ │
-│ └────────────────────────────────────┘ │
-│ ↓ │
-│ ┌────────────────────────────────────┐ │
-│ │ /makefile.toolchain │ │
-│ │ - Docker container management │ │
-│ │ - Volume mounting │ │
-│ │ - Build invocation │ │
-│ └────────────────────────────────────┘ │
-└─────────────────────────────────────────────┘
- ↓
-┌─────────────────────────────────────────────┐
-│ Docker Container (per platform) │
-│ │
-│ ┌────────────────────────────────────┐ │
-│ │ /workspace/makefile │ │
-│ │ - Build all components │ │
-│ │ - Cross-compile for target │ │
-│ └────────────────────────────────────┘ │
-│ ↓ │
-│ ┌────────────────────────────────────┐ │
-│ │ Component Makefiles │ │
-│ │ - Individual builds │ │
-│ │ - Link libraries │ │
-│ └────────────────────────────────────┘ │
-└─────────────────────────────────────────────┘
- ↓
- Compiled binaries → /build/
-```
-
-## Prerequisites
-
-### Required Software
-
-1. **Docker Desktop** - For cross-compilation containers
-2. **Make** - GNU Make (usually pre-installed on macOS/Linux)
-3. **Git** - For version control and toolchain fetching
-4. **Basic Unix Tools** - cp, rm, zip, etc.
-
-### Optional
-
-- **zip** - For creating release archives
-- **ImageMagick** - For generating asset variations (if modifying graphics)
-
-## Quick Start
-
-### Build for All Platforms
-
-```bash
-make
-```
-
-This runs the full build:
-1. Sets up build directory
-2. Compiles for all platforms
-3. Creates release packages
-
-### Build for Specific Platform
-
-```bash
-make PLATFORM=miyoomini
-```
-
-Supported platforms:
-- `miyoomini` - Miyoo Mini/Plus
-- `my282` - Miyoo Mini Flip
-- `my355` - Miyoo Flip/A30
-- `trimuismart` - Trimui Smart family
-- `rg35xx` - RG35XX original
-- `rg35xxplus` - RG35XX Plus family
-- `rgb30` - RGB30
-- `tg5040` - Trimui Smart Pro
-- `m17` - M17
-- `gkdpixel` - GKD Pixel/Mini
-- `magicmini` - MagicX XU Mini M
-- `zero28` - MagicX Mini Zero 28
-
-### Interactive Shell (Development)
-
-```bash
-make PLATFORM=miyoomini shell
-```
-
-Opens interactive shell in Docker container for debugging and development.
-
-## Build Phases
-
-### Phase 1: Setup (`make setup`)
-
-Creates build directory and prepares skeleton:
-
-```bash
-# Creates /build/ from /skeleton/
-# Removes authoring files (.meta, .keep)
-# Formats README files
-# Generates build hash
-```
-
-**What happens:**
-1. `/build/` directory created
-2. `/skeleton/` contents copied to `/build/`
-3. Placeholder files removed
-4. README files processed (wrapped/formatted)
-5. Git commit hash embedded in build
-
-**Output:**
-- `/build/SYSTEM/`
-- `/build/BASE/`
-- `/build/EXTRAS/`
-- `/build/BOOT/`
-
-### Phase 2: Platform Builds (`make [platform]`)
-
-For each platform:
-
-```bash
-make PLATFORM=[platform] build
-```
-
-This invokes the Docker toolchain:
-
-**What happens:**
-1. Toolchain image pulled from GitHub (if needed)
-2. Docker container started with workspace mounted
-3. `/workspace/makefile` executed inside container
-4. All components compiled for target platform
-5. Binaries copied to `/build/SYSTEM/[platform]/`
-
-**Build order** (inside container):
-```
-1. libmsettings.so
-2. keymon.elf
-3. minui.elf
-4. minarch.elf
-5. clock.elf, minput.elf, say.elf, syncsettings.elf
-6. Platform-specific utilities
-7. Libretro cores (optional, see cores build)
-```
-
-**Output** (per platform):
-- `/build/SYSTEM/[platform]/bin/*.elf`
-- `/build/SYSTEM/[platform]/lib/libmsettings.so`
-- `/build/SYSTEM/[platform]/cores/*.so` (if cores built)
-
-### Phase 3: Cores Build (Optional)
-
-Cores can be built separately:
-
-```bash
-cd workspace/[platform]/cores
-make
-```
-
-**What happens:**
-1. Git clones libretro core repositories
-2. Applies universal patches from `/workspace/all/cores/shared/`
-3. Applies platform patches from `patches/`
-4. Compiles core with platform-specific flags
-5. Copies `.so` to `output/`
-
-**Common cores:**
-- fceumm (NES)
-- gambatte (GB/GBC)
-- gpsp (GBA)
-- picodrive (Genesis/SMS/GG)
-- snes9x2005_plus (SNES)
-- pcsx_rearmed (PS1)
-
-**Note:** Cores build can take hours. Pre-built cores available in releases.
-
-### Phase 4: Special Platform Handling (`make special`)
-
-Handles platform-specific packaging quirks:
-
-**What happens:**
-- Creates Miyoo family variants (miyoo354, miyoo355, etc.)
-- Reorganizes boot files
-- Applies platform-specific patches
-- Creates symlinks where needed
-
-**Output:**
-- Additional platform directories in `/build/BOOT/`
-- Modified system files for variants
-
-### Phase 5: Packaging (`make package`)
-
-Creates release archives:
-
-```bash
-cd build
-zip -r ../releases/MinUI-[date]-[build]-base.zip SYSTEM/ BASE/ BOOT/
-zip -r ../releases/MinUI-[date]-[build]-extras.zip EXTRAS/
-zip -r ../releases/MinUI-[date]-[build].zip SYSTEM/
-```
-
-**Release files:**
-- `MinUI-YYYYMMDD-N-base.zip` - Full base installation
-- `MinUI-YYYYMMDD-N-extras.zip` - Extra cores and tools
-- `MinUI-YYYYMMDD-N.zip` - Update package (SYSTEM only)
-- `version.txt` - Version information
-- `commits.txt` - Commit history
-
-## Toolchain System
-
-### Toolchain Images
-
-MinUI uses pre-built Docker images containing:
-- Cross-compilation toolchain (GCC for ARM)
-- Platform-specific libraries (SDL, etc.)
-- Build tools (make, pkg-config, etc.)
-- Development headers
-
-**Toolchain sources:**
-```
-https://github.com/shauninman/union-[platform]-toolchain/
-```
-
-**Available toolchains:**
-- union-miyoomini-toolchain
-- union-rg35xx-toolchain
-- union-rg35xxplus-toolchain
-- union-trimuismart-toolchain
-- etc.
-
-### Toolchain Operations
-
-**Pull toolchain image:**
-```bash
-make PLATFORM=miyoomini toolchain
-```
-
-**Interactive shell:**
-```bash
-make PLATFORM=miyoomini shell
-```
-
-**Non-interactive build:**
-```bash
-make PLATFORM=miyoomini build
-```
-
-### Inside the Container
-
-**Mounted volumes:**
-- Host: `/Users/[user]/[repo]/workspace/`
-- Guest: `/root/workspace/`
-
-**Environment variables:**
-- `UNION_PLATFORM=[platform]` - Current platform
-- `CROSS_COMPILE=[prefix]` - Toolchain prefix
-- `CC, CXX, LD, AR, STRIP` - Compiler tools
-
-**Available tools:**
-- `arm-linux-gnueabihf-gcc` (or similar)
-- `make`
-- `pkg-config`
-- Platform-specific libraries
-
-## Workspace Build Process
-
-### `/workspace/makefile`
-
-Master makefile for workspace builds.
-
-**Targets:**
-```makefile
-all: [platform] # Build everything for platform
-[platform]: deps bin cores # Platform-specific build
-deps: libmsettings # Dependencies
-bin: minui minarch utils # Main binaries
-cores: platform-cores # Libretro cores (if enabled)
-clean: clean-all # Remove build artifacts
-```
-
-**Build sequence:**
-```bash
-make libmsettings # Settings library
-make keymon # Input monitor
-make minui # Launcher
-make minarch # Frontend
-make clock # Clock utility
-make minput # Input tester
-make say # Notification
-make syncsettings # Settings sync
-make platform-utils # Platform-specific tools
-make cores # Cores (optional, slow)
-```
-
-### Component Makefiles
-
-Each component has a standardized makefile:
-
-**Example** (`/workspace/all/minui/makefile`):
-```makefile
-PLATFORM = $(UNION_PLATFORM)
-
-ifeq ($(PLATFORM),miyoomini)
- CROSS_COMPILE = /opt/miyoomini-toolchain/bin/arm-linux-gnueabihf-
-endif
-
-CC = $(CROSS_COMPILE)gcc
-STRIP = $(CROSS_COMPILE)strip
-
-TARGET = minui.elf
-SOURCE = minui.c ../common/api.c ../common/utils.c ../../$(PLATFORM)/platform/platform.c
-
-CFLAGS = -Ofast -std=gnu99 -DPLATFORM=\"$(PLATFORM)\"
-LDFLAGS = -lmsettings -lSDL -lSDL_image -lSDL_ttf -lpthread -lm -lz
-
-all: $(TARGET)
-
-$(TARGET): $(SOURCE)
- $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS)
- $(STRIP) $@
-
-clean:
- rm -f $(TARGET)
-```
-
-**Key points:**
-- Platform detected from `UNION_PLATFORM` env var
-- Cross-compiler selected based on platform
-- All source files compiled in single invocation
-- Output stripped to reduce size
-- Links against platform libraries
-
-### Cores Makefile
-
-**Template pattern** (`/workspace/all/cores/makefile`):
-
-```makefile
-# Download core
-$(SRC_DIR)/[core]:
- git clone [repo-url] $@
- cd $@ && git checkout [commit-hash]
-
-# Apply patches
-$(SRC_DIR)/[core]/.patched: $(SRC_DIR)/[core]
- # Apply universal patches
- -patch -d $(SRC_DIR)/[core] -p1 < ../shared/generic/[core].patch
- # Apply platform patches
- -patch -d $(SRC_DIR)/[core] -p1 < patches/[core].patch
- touch $@
-
-# Build core
-$(OUTPUT_DIR)/[core]_libretro.so: $(SRC_DIR)/[core]/.patched
- $(MAKE) -C $(SRC_DIR)/[core] -f Makefile platform=$(PLATFORM)
- cp $(SRC_DIR)/[core]/[core]_libretro.so $@
-```
-
-**Customization per core:**
-- Custom git repository
-- Specific commit hash
-- Custom makefile location
-- Build flags
-- Output path
-
-## Build Configuration
-
-### Global Configuration
-
-**Platform selection** (in root `/makefile`):
-```makefile
-PLATFORMS = miyoomini trimuismart rg35xx rg35xxplus my355 \
- tg5040 zero28 rgb30 m17 gkdpixel my282 magicmini
-```
-
-**Toolchain mapping** (in `/makefile.toolchain`):
-```makefile
-DOCKER_IMAGE_miyoomini = ghcr.io/shauninman/union-miyoomini-toolchain:latest
-DOCKER_IMAGE_rg35xx = ghcr.io/shauninman/union-rg35xx-toolchain:latest
-# etc.
-```
-
-### Component Configuration
-
-**Compiler flags** (common):
-```makefile
-CFLAGS = -Ofast # Maximum optimization
- -std=gnu99 # C99 with GNU extensions
- -DPLATFORM="..." # Platform identifier
- -Wall # All warnings
- -Wno-unused # Suppress unused warnings
-```
-
-**Linker flags** (common):
-```makefile
-LDFLAGS = -lmsettings # Platform settings
- -lSDL # Simple DirectMedia Layer
- -lSDL_image # Image loading
- -lSDL_ttf # Font rendering
- -lpthread # Threading
- -lm # Math
- -lz # Compression
- -ldl # Dynamic loading
-```
-
-### Platform-Specific Flags
-
-Different platforms may have additional flags:
-
-**Miyoo Mini:**
-```makefile
-CFLAGS += -mcpu=cortex-a7 -mfpu=neon-vfpv4
-```
-
-**RG35XX:**
-```makefile
-CFLAGS += -march=armv8-a
-```
-
-## Incremental Builds
-
-### Build Only Changed Components
-
-```bash
-# After modifying minui.c:
-cd workspace/all/minui
-make PLATFORM=miyoomini
-
-# Copy to build:
-cp minui.elf /path/to/build/SYSTEM/miyoomini/bin/
-```
-
-### Rebuild Single Component
-
-```bash
-make -C workspace/all/minui clean
-make -C workspace/all/minui PLATFORM=miyoomini
-```
-
-### Skip Cores Build
-
-Cores take hours to compile. To skip:
-
-```bash
-# Modify workspace/[platform]/cores/makefile
-# Comment out core definitions
-
-# Or use pre-built cores from release
-```
-
-## Debugging Build Issues
-
-### Enable Verbose Output
-
-```bash
-make VERBOSE=1
-```
-
-### Check Toolchain
-
-```bash
-make PLATFORM=miyoomini shell
-# Inside container:
-which arm-linux-gnueabihf-gcc
-arm-linux-gnueabihf-gcc --version
-```
-
-### Manual Compilation
-
-```bash
-make PLATFORM=miyoomini shell
-cd /root/workspace/all/minui
-arm-linux-gnueabihf-gcc -v minui.c
-```
-
-### Common Issues
-
-**1. Docker not running:**
-```
-Error: Cannot connect to Docker daemon
-Solution: Start Docker Desktop
-```
-
-**2. Toolchain image not found:**
-```
-Error: Unable to find image 'ghcr.io/...'
-Solution: Check internet connection, verify image exists
-```
-
-**3. Missing libraries:**
-```
-Error: undefined reference to 'SDL_Init'
-Solution: Check toolchain has SDL installed
-```
-
-**4. Permission denied:**
-```
-Error: Permission denied writing to /build/
-Solution: Check directory permissions, run with appropriate user
-```
-
-## Build Performance
-
-### Build Times (Approximate)
-
-| Task | Duration |
-|------|----------|
-| Setup | 5-10 seconds |
-| Single platform (no cores) | 1-2 minutes |
-| Single platform (with cores) | 1-3 hours |
-| All platforms (no cores) | 15-30 minutes |
-| All platforms (with cores) | 12-36 hours |
-
-### Optimization Tips
-
-1. **Use parallel builds:**
- ```bash
- make -j$(nproc)
- ```
-
-2. **Skip cores:**
- - Use pre-built cores from releases
- - Only build cores when needed
-
-3. **Build specific platforms:**
- ```bash
- make PLATFORM=miyoomini
- ```
-
-4. **Incremental builds:**
- - Only rebuild changed components
- - Keep build directory between builds
-
-5. **Use local Docker images:**
- - Pull toolchains once, reuse
-
-## Output Structure
-
-### Build Directory
-
-After successful build:
-
-```
-build/
-├── SYSTEM/
-│ ├── res/ # Shared resources
-│ └── [platform]/ # Per-platform
-│ ├── bin/ # Executables
-│ │ ├── minui.elf
-│ │ ├── minarch.elf
-│ │ ├── keymon.elf
-│ │ └── ...
-│ ├── lib/
-│ │ └── libmsettings.so
-│ ├── cores/ # Cores (if built)
-│ │ ├── fceumm_libretro.so
-│ │ └── ...
-│ └── paks/ # System paks
-│ └── Emus/
-├── BASE/ # User files
-├── EXTRAS/ # Optional content
-└── BOOT/ # Bootstrap
-```
-
-### Release Packages
-
-```
-releases/
-├── MinUI-20250107-1-base.zip
-├── MinUI-20250107-1-extras.zip
-├── MinUI-20250107-1.zip
-├── version.txt
-└── commits.txt
-```
-
-## Clean Targets
-
-```bash
-make clean # Remove build artifacts
-make clean-all # Remove build/ and releases/
-make clean-workspace # Clean workspace builds
-make clean-cores # Remove downloaded cores
-```
-
-## Advanced: Building Without Docker
-
-For native compilation (if on ARM Linux):
-
-```bash
-cd workspace
-export UNION_PLATFORM=miyoomini
-make
-```
-
-**Requirements:**
-- ARM Linux system
-- Development libraries installed
-- Matching architecture to target platform
-
-**Not recommended** - Docker ensures reproducible builds.
-
-## CI/CD Integration
-
-MinUI can be built in GitHub Actions or similar:
-
-```yaml
-- name: Build MinUI
- run: |
- make setup
- make PLATFORM=miyoomini
- make package
-```
-
-**Considerations:**
-- Docker must be available in CI environment
-- Large Docker images (1-2 GB per toolchain)
-- Long build times for cores
-- Artifact storage for releases
-
-## Next Steps
-
-- [Development Guide](development-guide.md) - Contributing to MinUI
-- [Adding Platform Support](adding-platform.md) - Porting to new devices
-- [Components Guide](components.md) - Understanding the codebase
diff --git a/docs/components.md b/docs/components.md
deleted file mode 100644
index 31eaf5c6..00000000
--- a/docs/components.md
+++ /dev/null
@@ -1,751 +0,0 @@
-# MinUI Components Guide
-
-This document provides detailed information about each component in the MinUI system.
-
-## Core Applications
-
-### MinUI Launcher
-
-**Location**: `/workspace/all/minui/minui.c` (1,704 lines)
-
-**Purpose**: Main user interface for browsing and launching ROMs.
-
-#### Responsibilities
-
-1. **ROM Scanning**
- - Recursively scans `/Roms/` directories
- - Identifies console type from directory tags (e.g., "(GB)", "(GBA)")
- - Filters for supported file extensions
- - Generates display names by hiding extensions and tags
-
-2. **Collections Management**
- - Reads `.txt` files in collections directories
- - Displays custom ROM lists
- - Supports manual ROM curation
-
-3. **Recent Games Tracking**
- - Maintains list of last 10 played games
- - Auto-resume: returns to last game on boot
- - Quick access to frequently played titles
-
-4. **User Interface**
- - Pill-style navigation
- - Console icons
- - Battery/charging indicator
- - Volume and brightness display
- - Clean, minimal aesthetic
-
-5. **Pak Launching**
- - Identifies appropriate `.pak` directory for console
- - Executes `launch.sh` with ROM path
- - Handles return from emulators
-
-#### Key Functions
-
-```c
-main() // Entry point, main loop
-scanDirectory() // Recursive ROM scanning
-getDisplayName() // Smart name formatting
-launchGame() // Execute pak launch script
-drawUI() // Render interface
-handleInput() // Process button presses
-```
-
-#### Configuration
-
-MinUI reads settings from:
-- `/mnt/SDCARD/.minui/last.txt` - Last played ROM
-- `/mnt/SDCARD/.minui/recent.txt` - Recent games list
-- Platform settings via libmsettings
-
-#### ROM Name Processing
-
-MinUI automatically formats ROM names:
-- Hides file extensions (`.gb`, `.gba`, `.zip`)
-- Removes region tags (`(USA)`, `(Japan)`, `(Europe)`)
-- Removes version info (`(v1.1)`, `(Rev 1)`)
-- Removes extra tags (`[!]`, `[T+Eng]`)
-- Preserves hack indicators (`[Hack]`)
-
-Example: `Super Mario Bros. (USA) (Rev 1).nes` → `Super Mario Bros.`
-
----
-
-### Minarch Frontend
-
-**Location**: `/workspace/all/minarch/minarch.c` (4,830 lines)
-
-**Purpose**: Libretro frontend for running emulator cores.
-
-#### Responsibilities
-
-1. **Core Management**
- - Dynamic loading of libretro `.so` cores
- - Core initialization and shutdown
- - Implements libretro frontend callbacks
- - Handles core API versioning
-
-2. **Game Execution**
- - Loads ROM files (with .zip support)
- - Manages game state
- - Main emulation loop
- - Frame timing and synchronization
-
-3. **Save State System**
- - 10 manual save slots (0-9)
- - Auto-save slot (slot 9)
- - Quicksave on power-off
- - Auto-resume from slot 9 on boot
- - Compression with zlib
- - Save state preview (planned)
-
-4. **In-Game Menu**
- - Pause during gameplay
- - Save/Load state management
- - Disc changing (multi-disc games)
- - Options configuration
- - Screenshot capture
- - Core reset
-
-5. **Video Processing**
- - Receives frames from libretro core
- - Software scaling via scaler.c
- - Multiple scaling modes:
- - Native (1:1)
- - Aspect (maintain ratio)
- - Full (stretch)
- - Cropped (zoom)
- - Sharpness control (sharp/crisp/soft)
- - CRT effects (scanlines, grid)
- - Threaded video option
-
-6. **Audio Processing**
- - Receives samples from libretro core
- - Ring buffer for low-latency audio
- - Resampling (limited)
- - Volume control
-
-7. **Input Mapping**
- - Maps device buttons to libretro inputs
- - Per-console button configuration
- - Custom button bindings
- - Analog stick support (where available)
-
-8. **Configuration**
- - Frontend settings (`.minarch.ini`)
- - Per-console settings (`[TAG].ini`)
- - Per-core settings (`[CORE].ini`)
- - Core options (`.opt` files)
- - Persistent configuration
-
-#### Key Functions
-
-```c
-main() // Entry point
-retro_init() // Core initialization
-core_load_game() // Load ROM
-core_run() // Main loop
-video_cb() // Video frame callback
-audio_sample_batch_cb() // Audio callback
-input_poll_cb() // Input polling
-saveState() / loadState() // Save state management
-showMenu() // In-game menu
-applyVideoSettings() // Scaling/effects
-```
-
-#### Configuration Files
-
-**Frontend Config** (`.minarch.ini`):
-```ini
-volume=10
-brightness=5
-scale_mode=2
-sharpness=1
-effect=0
-threaded_video=0
-```
-
-**Console Config** (`[TAG].ini`):
-```ini
-core=gambatte_libretro.so
-aspect=1
-crop=0
-```
-
-**Core Options** (`[CORE].opt`):
-```ini
-gambatte_gb_colorization=internal
-gambatte_gb_palette=GBC - Blue
-```
-
-#### Save State Format
-
-Save states are stored in `/Saves/[Console]/`:
-```
-[ROM_NAME].sav # Save RAM (battery backup)
-[ROM_NAME].st0 # Save state slot 0
-[ROM_NAME].st1 # Save state slot 1
-...
-[ROM_NAME].st9 # Auto-save slot
-```
-
-#### Multi-Disc Games
-
-Minarch detects `.m3u` playlists:
-```
-# Final Fantasy VII.m3u
-Final Fantasy VII (Disc 1).bin
-Final Fantasy VII (Disc 2).bin
-Final Fantasy VII (Disc 3).bin
-```
-
-Disc changing available in in-game menu.
-
----
-
-## Common Libraries
-
-### Graphics API (GFX_*)
-
-**Location**: `/workspace/all/common/api.c`
-
-**Purpose**: Unified graphics interface for all applications.
-
-#### Functions
-
-```c
-GFX_init() // Initialize graphics subsystem
-GFX_quit() // Cleanup graphics
-GFX_clear() // Clear screen
-GFX_flip() // Present frame (swap buffers)
-GFX_sync() // Wait for vsync
-
-// Asset loading
-GFX_loadImage() // Load PNG asset
-GFX_freeImage() // Free image memory
-GFX_blitImage() // Draw image to screen
-
-// Text rendering
-GFX_openFont() // Load TTF font
-GFX_closeFont() // Free font
-GFX_drawText() // Render text string
-GFX_getTextWidth() // Measure text width
-
-// UI elements
-GFX_drawPill() // Rounded rectangle
-GFX_drawButton() // Button with label
-GFX_drawBattery() // Battery indicator
-GFX_drawVolume() // Volume indicator
-GFX_drawBrightness() // Brightness indicator
-```
-
-#### Features
-
-- Asset caching for performance
-- Multiple font sizes (16, 20, 24, 32, 40 pt)
-- Automatic scaling based on screen resolution
-- Alpha blending support
-- Dirty rectangle optimization
-
----
-
-### Sound API (SND_*)
-
-**Location**: `/workspace/all/common/api.c`
-
-**Purpose**: Audio initialization and buffering.
-
-#### Functions
-
-```c
-SND_init() // Initialize audio
-SND_quit() // Cleanup audio
-SND_write() // Write samples to buffer
-```
-
-#### Features
-
-- Ring buffer for low-latency
-- Configurable sample rate
-- Stereo output
-- Lock-free design
-
----
-
-### Input API (PAD_*)
-
-**Location**: `/workspace/all/common/api.c`
-
-**Purpose**: Button and analog stick input handling.
-
-#### Functions
-
-```c
-PAD_init() // Initialize input
-PAD_quit() // Cleanup input
-PAD_poll() // Read current button state
-PAD_justPressed() // Check for new press
-PAD_justRepeated() // Check for auto-repeat
-PAD_justReleased() // Check for release
-```
-
-#### Button Definitions
-
-```c
-BTN_UP // D-pad up
-BTN_DOWN // D-pad down
-BTN_LEFT // D-pad left
-BTN_RIGHT // D-pad right
-BTN_A // Face button A
-BTN_B // Face button B
-BTN_X // Face button X (if present)
-BTN_Y // Face button Y (if present)
-BTN_L1 // Left shoulder
-BTN_R1 // Right shoulder
-BTN_L2 // Left trigger (if present)
-BTN_R2 // Right trigger (if present)
-BTN_SELECT // Select/Back
-BTN_START // Start/Menu
-BTN_MENU // Menu button (if present)
-BTN_L3 // Left stick press (if present)
-BTN_R3 // Right stick press (if present)
-```
-
-#### Features
-
-- Auto-repeat with configurable delay and rate
-- Analog stick normalization
-- Dead zone handling
-- Platform-independent button IDs
-
----
-
-### Power API (PWR_*)
-
-**Location**: `/workspace/all/common/api.c`
-
-**Purpose**: Power management and system control.
-
-#### Functions
-
-```c
-PWR_init() // Initialize power subsystem
-PWR_quit() // Cleanup power
-PWR_update() // Update power state
-PWR_getBatteryLevel() // Get battery percentage
-PWR_isCharging() // Check charging status
-PWR_sleep() // Enter sleep mode
-PWR_wake() // Exit sleep mode
-PWR_powerOff() // Shutdown device
-PWR_getCPUSpeed() // Get CPU frequency
-PWR_setCPUSpeed() // Set CPU frequency
-```
-
-#### Features
-
-- Automatic sleep after 30 seconds idle
-- Auto power-off after 2 minutes asleep
-- Battery level monitoring
-- Charging detection
-- CPU frequency scaling
-- Backlight control
-
----
-
-### Video Scaler (scaler.c)
-
-**Location**: `/workspace/all/common/scaler.c` (110 KB)
-
-**Purpose**: Software video scaling and effects.
-
-#### Scaling Modes
-
-1. **Native** - 1:1 pixel mapping (no scaling)
-2. **Aspect** - Maintain aspect ratio, letterbox/pillarbox
-3. **Full** - Stretch to fill screen
-4. **Cropped** - Zoom to fill, crop edges
-
-#### Sharpness Levels
-
-1. **Sharp** - Nearest neighbor (crisp pixels)
-2. **Crisp** - Optimized nearest neighbor
-3. **Soft** - Bilinear interpolation
-
-#### Effects
-
-1. **None** - Clean output
-2. **Scanlines** - Horizontal lines (CRT effect)
-3. **Grid** - Full grid pattern (CRT effect)
-
-#### Optimizations
-
-- NEON SIMD intrinsics for ARM
-- Fast paths for common scaling ratios
-- RGB565 native format
-- Integer-only math
-- Loop unrolling
-
-#### Functions
-
-```c
-scale_bitmap() // Main scaling function
-scale_nearest() // Nearest neighbor
-scale_bilinear() // Bilinear interpolation
-apply_scanlines() // Add scanline effect
-apply_grid() // Add grid effect
-```
-
----
-
-### Utilities (utils.c)
-
-**Location**: `/workspace/all/common/utils.c`
-
-**Purpose**: Common helper functions.
-
-#### Functions
-
-```c
-exists() // Check if file exists
-isDir() // Check if path is directory
-makeDir() // Create directory
-exactMatch() // Case-sensitive string match
-prefixMatch() // Check string prefix
-suffixMatch() // Check string suffix
-getFilename() // Extract filename from path
-getExtension() // Get file extension
-trimExtension() // Remove extension
-normalizePath() // Clean up path
-```
-
----
-
-## Platform Abstraction Layer
-
-### Platform Interface (platform.h/platform.c)
-
-**Location**: `/workspace/[platform]/platform/`
-
-Each platform implements a standard interface:
-
-#### Required Functions
-
-```c
-// Video
-void PLAT_initVideo(void)
-void PLAT_quitVideo(void)
-void PLAT_clearVideo(void)
-void PLAT_clearAll(void)
-void PLAT_setVsync(int enabled)
-void PLAT_vsync(void)
-void PLAT_flip(void)
-Surface* PLAT_getScreen(void)
-
-// Input
-void PLAT_initInput(void)
-void PLAT_quitInput(void)
-void PLAT_pollInput(void)
-
-// Power
-int PLAT_getBatteryStatus(void)
-void PLAT_enableBacklight(int enable)
-void PLAT_powerOff(void)
-void PLAT_setCPUSpeed(int speed)
-
-// Scaling (optional)
-void PLAT_scale(Surface* src, SDL_Rect* src_rect,
- Surface* dst, SDL_Rect* dst_rect,
- int sharp, int effect)
-```
-
-#### Platform Constants
-
-```c
-// Screen dimensions
-#define FIXED_WIDTH 640
-#define FIXED_HEIGHT 480
-#define FIXED_BPP 16
-
-// Scaling
-#define FIXED_SCALE 2
-
-// Paths
-#define SDCARD_PATH "/mnt/SDCARD"
-#define MUTE_VOLUME_RAW 0
-
-// Capabilities
-#define HAS_HDMI 0
-#define HAS_ANALOG 0
-```
-
----
-
-### Settings Library (libmsettings)
-
-**Location**: `/workspace/[platform]/libmsettings/`
-
-**Purpose**: Persistent platform settings.
-
-#### API
-
-```c
-int InitSettings(void)
-void QuitSettings(void)
-
-int GetBrightness(void)
-void SetBrightness(int value)
-
-int GetVolume(void)
-void SetVolume(int value)
-
-char* GetLastPlay(void)
-void SetLastPlay(char* path)
-```
-
-#### Implementation
-
-Each platform implements settings using:
-- `/sys/class/backlight/` for brightness
-- ALSA or platform mixer for volume
-- Settings file for persistence (typically `/mnt/SDCARD/.minui/settings.ini`)
-
----
-
-### Input Monitor (keymon)
-
-**Location**: `/workspace/[platform]/keymon/`
-
-**Purpose**: Background daemon for global input handling.
-
-#### Responsibilities
-
-1. **Raw Input Monitoring**
- - Opens `/dev/input/event*` devices
- - Reads raw input events
- - Bypasses SDL for system-level access
-
-2. **Global Shortcuts**
- - Volume up/down (typically L1/R1 + D-pad)
- - Brightness up/down (typically L1/R1 + D-pad)
- - Sleep trigger (typically power button short press)
- - Force shutdown (power button long press)
-
-3. **Sleep Management**
- - Detects idle time
- - Triggers sleep mode
- - Handles wake events
- - Manages backlight state
-
-4. **System Protection**
- - Prevents stock OS from interfering
- - Blocks unwanted input handlers
- - Ensures MinUI has input priority
-
-#### Platform-Specific
-
-Each platform has different button codes and input devices:
-- Miyoo Mini: `/dev/input/event0`
-- RG35XX: Multiple event devices
-- Trimui: Different GPIO mapping
-
----
-
-## Utility Programs
-
-### Clock
-
-**Location**: `/workspace/all/clock/clock.c`
-
-Simple clock display showing current time and date. Uses platform settings for rendering.
-
-### Minput
-
-**Location**: `/workspace/all/minput/minput.c`
-
-Input testing tool:
-- Shows button presses in real-time
-- Displays analog stick values
-- Helps diagnose input issues
-- Useful for button remapping
-
-### Say
-
-**Location**: `/workspace/all/say/say.c`
-
-Notification system:
-- Displays text messages on screen
-- Used by system scripts
-- Splash screen alternative
-- Simple text overlay
-
-### Syncsettings
-
-**Location**: `/workspace/all/syncsettings/syncsettings.c`
-
-Settings restoration daemon:
-- Monitors for third-party app launches
-- Restores MinUI brightness/volume after exit
-- Prevents RetroArch or other apps from changing settings permanently
-- Runs in background
-
----
-
-## Libretro Cores
-
-### Core Building
-
-**Location**: `/workspace/all/cores/makefile`
-
-Template-based build system:
-
-```makefile
-# Example core definition
-$(CORE_DIR)/fceumm_libretro.so:
- git clone https://github.com/libretro/fceumm $(SRC_DIR)/fceumm
- cd $(SRC_DIR)/fceumm && git checkout [commit-hash]
- # Apply patches
- $(MAKE) -C $(SRC_DIR)/fceumm -f Makefile platform=[platform]
- cp $(SRC_DIR)/fceumm/fceumm_libretro.so $(CORE_DIR)/
-```
-
-### Stock Cores
-
-1. **FCEUmm** - NES/Famicom
- - Fast, accurate NES emulation
- - Mapper support for most games
- - Save state support
-
-2. **Gambatte** - Game Boy / Game Boy Color
- - High accuracy
- - Color palettes
- - Super Game Boy support
-
-3. **GPSP** - Game Boy Advance
- - Fast ARM-based dynarec
- - Good compatibility
- - Save state support
-
-4. **PicoDrive** - Sega Genesis/CD, Master System, Game Gear
- - Fast 68000/Z80 emulation
- - Sega CD support
- - Multiple systems in one core
-
-5. **Snes9x2005 Plus** - Super Nintendo
- - Balance of speed and accuracy
- - Enhanced version of Snes9x 1.43
- - Good compatibility
-
-6. **PCSX ReARMed** - PlayStation
- - ARM-optimized dynarec
- - Strong compatibility
- - Multi-disc support
- - Memory card emulation
-
-### Extra Cores
-
-Available in extras package:
-- MGBA - Better GBA accuracy
-- Mednafen cores - High accuracy multi-system
-- Fake08 - PICO-8 fantasy console
-- Race - Neo Geo Pocket
-- PokeMini - Pokemon Mini
-
----
-
-## Pak System
-
-**Location**: Various `.pak/` directories
-
-### Structure
-
-```
-[NAME].pak/
-├── launch.sh # Launch script
-├── config.json # Configuration (optional)
-└── [additional files] # Core, assets, etc.
-```
-
-### Launch Script
-
-```bash
-#!/bin/sh
-# Example launch.sh for emulator pak
-
-ROM="$1"
-CORE="/mnt/SDCARD/SYSTEM/[platform]/cores/[core]_libretro.so"
-
-cd "$(dirname "$0")"
-/mnt/SDCARD/SYSTEM/[platform]/bin/minarch.elf "$CORE" "$ROM"
-```
-
-### Configuration
-
-```json
-{
- "name": "Game Boy",
- "core": "gambatte_libretro.so",
- "options": {
- "gambatte_gb_colorization": "internal",
- "gambatte_gb_palette": "GBC - Blue"
- }
-}
-```
-
-### Types of Paks
-
-1. **Emulator (Reuse Core)** - Uses system core
-2. **Emulator (Custom Core)** - Bundles own core
-3. **Native Tool** - Standalone application
-4. **Script Tool** - Shell script utility
-
-See [PAKS.md](../PAKS.md) for complete pak creation guide.
-
----
-
-## Component Dependencies
-
-```
-minui.elf depends on:
- - api.c (GFX, PAD, PWR)
- - utils.c
- - platform.c
- - libmsettings.so
- - SDL, SDL_image, SDL_ttf
-
-minarch.elf depends on:
- - api.c (GFX, SND, PAD, PWR)
- - scaler.c
- - utils.c
- - platform.c
- - libmsettings.so
- - SDL, zlib, dlopen
-
-keymon.elf depends on:
- - libmsettings.so
- - raw input devices
-
-libmsettings.so depends on:
- - ALSA (audio)
- - sysfs (backlight)
- - file I/O
-```
-
-## Performance Characteristics
-
-| Component | CPU Usage | Memory | Disk I/O |
-|-----------|-----------|--------|----------|
-| minui | Very Low | ~2 MB | Low (ROM scan) |
-| minarch | Medium-High | ~20 MB | Low (save states) |
-| keymon | Very Low | <1 MB | None |
-| syncsettings | Very Low | <1 MB | Very Low |
-| scaler | High | Minimal | None |
-
-## Thread Model
-
-Most components are single-threaded:
-- minui - Single thread
-- minarch - Main thread + optional video thread
-- keymon - Single thread
-- syncsettings - Single thread
-
-Synchronization via file locking where needed.
diff --git a/docs/development-guide.md b/docs/development-guide.md
deleted file mode 100644
index c421509f..00000000
--- a/docs/development-guide.md
+++ /dev/null
@@ -1,717 +0,0 @@
-# MinUI Development Guide
-
-This guide covers how to contribute to MinUI, develop new features, and debug issues.
-
-## Getting Started
-
-### Development Environment Setup
-
-#### Required Tools
-
-1. **Git** - Version control
-2. **Docker Desktop** - Cross-compilation environment
-3. **Code Editor** - VS Code, Vim, etc.
-4. **Make** - Build system
-
-#### Recommended Tools
-
-- **VS Code Extensions:**
- - C/C++ (Microsoft)
- - Makefile Tools
- - Docker
-
-- **Command Line Tools:**
- - `ripgrep` or `grep` - Code search
- - `tree` - Directory visualization
- - `hexdump` - Binary inspection
-
-### Cloning the Repository
-
-```bash
-git clone https://github.com/shauninman/MinUI.git
-cd MinUI
-```
-
-### Understanding the Codebase
-
-1. **Read the documentation:**
- - [Architecture Overview](architecture.md)
- - [Project Structure](project-structure.md)
- - [Components Guide](components.md)
-
-2. **Explore the code:**
- ```bash
- # Main applications
- workspace/all/minui/minui.c
- workspace/all/minarch/minarch.c
-
- # Common APIs
- workspace/all/common/api.c
- workspace/all/common/api.h
-
- # Example platform
- workspace/miyoomini/platform/platform.c
- ```
-
-3. **Build the project:**
- ```bash
- make PLATFORM=miyoomini
- ```
-
-## Development Workflow
-
-### Typical Development Cycle
-
-1. **Create a branch:**
- ```bash
- git checkout -b feature/my-new-feature
- ```
-
-2. **Make changes:**
- - Edit source files
- - Test locally (if possible)
-
-3. **Build:**
- ```bash
- make PLATFORM=miyoomini
- ```
-
-4. **Test on device:**
- - Copy binaries to SD card
- - Test functionality
-
-5. **Commit:**
- ```bash
- git add .
- git commit -m "Add new feature"
- ```
-
-6. **Push and create PR:**
- ```bash
- git push origin feature/my-new-feature
- # Create pull request on GitHub
- ```
-
-### Development Practices
-
-#### Code Style
-
-MinUI follows a consistent C style:
-
-**Formatting:**
-- 4-space indentation (no tabs)
-- K&R brace style
-- 80-character line limit (soft)
-
-**Naming:**
-- Functions: `camelCase` or `snake_case` (context-dependent)
-- Structs: `CamelCase`
-- Constants: `UPPER_CASE`
-- Globals: `g_variableName`
-
-**Example:**
-```c
-typedef struct {
- int width;
- int height;
- void* pixels;
-} Surface;
-
-static Surface* g_screen = NULL;
-
-void GFX_init(void) {
- if (g_screen != NULL) {
- return; // Already initialized
- }
-
- g_screen = SDL_SetVideoMode(
- FIXED_WIDTH,
- FIXED_HEIGHT,
- FIXED_BPP,
- SDL_SWSURFACE
- );
-}
-```
-
-#### Comments
-
-- Use comments for complex logic
-- Document function purposes
-- Explain platform-specific quirks
-- Add TODO/FIXME for future work
-
-```c
-// TODO: Implement proper vsync timing
-// FIXME: Memory leak on error path
-// NOTE: Miyoo Mini requires double-buffering here
-```
-
-#### Error Handling
-
-```c
-// Check for errors
-if (file == NULL) {
- fprintf(stderr, "Failed to open %s\n", path);
- return -1;
-}
-
-// Clean up resources
-if (surface) {
- SDL_FreeSurface(surface);
- surface = NULL;
-}
-```
-
-## Common Development Tasks
-
-### Adding a New Feature to MinUI Launcher
-
-**Example: Adding a favorites system**
-
-1. **Define data structure:**
- ```c
- // In minui.c
- typedef struct {
- char path[256];
- int console;
- } Favorite;
-
- static Favorite favorites[100];
- static int favorite_count = 0;
- ```
-
-2. **Implement functionality:**
- ```c
- void addFavorite(const char* rom_path, int console) {
- if (favorite_count >= 100) return;
-
- strncpy(favorites[favorite_count].path, rom_path, 255);
- favorites[favorite_count].console = console;
- favorite_count++;
-
- saveFavorites();
- }
- ```
-
-3. **Add UI elements:**
- ```c
- void drawFavoritesMenu(void) {
- GFX_clear();
-
- for (int i = 0; i < favorite_count; i++) {
- GFX_drawText(10, 30 + i * 20, favorites[i].path);
- }
-
- GFX_flip();
- }
- ```
-
-4. **Handle input:**
- ```c
- if (PAD_justPressed(BTN_X)) {
- addFavorite(current_rom, current_console);
- }
- ```
-
-### Adding a New Option to Minarch
-
-**Example: Adding a frame skip option**
-
-1. **Add configuration field:**
- ```c
- // In minarch.c
- static int g_frame_skip = 0; // 0 = off, 1 = skip 1, etc.
- ```
-
-2. **Implement setting:**
- ```c
- void loadSettings(void) {
- // ... existing code ...
- g_frame_skip = ini_getInt("frameskip", 0);
- }
-
- void saveSettings(void) {
- // ... existing code ...
- ini_setInt("frameskip", g_frame_skip);
- }
- ```
-
-3. **Add to menu:**
- ```c
- // In menu rendering code
- sprintf(buffer, "Frame Skip: %d", g_frame_skip);
- drawMenuItem(y_pos, buffer);
- ```
-
-4. **Implement logic:**
- ```c
- static int frame_counter = 0;
-
- void runFrame(void) {
- core_run();
-
- frame_counter++;
- if (frame_counter > g_frame_skip) {
- frame_counter = 0;
- renderFrame();
- }
- }
- ```
-
-### Modifying the Common API
-
-**Example: Adding a new graphics primitive**
-
-1. **Add declaration to api.h:**
- ```c
- void GFX_drawCircle(int x, int y, int radius, uint32_t color);
- ```
-
-2. **Implement in api.c:**
- ```c
- void GFX_drawCircle(int x, int y, int radius, uint32_t color) {
- // Midpoint circle algorithm
- int x1 = 0;
- int y1 = radius;
- int d = 3 - 2 * radius;
-
- while (x1 <= y1) {
- putPixel(x + x1, y + y1, color);
- putPixel(x - x1, y + y1, color);
- // ... etc
-
- if (d < 0) {
- d = d + 4 * x1 + 6;
- } else {
- d = d + 4 * (x1 - y1) + 10;
- y1--;
- }
- x1++;
- }
- }
- ```
-
-3. **Update all applications that use it:**
- - Rebuild minui
- - Rebuild minarch
- - Test on target platform
-
-### Adding Platform-Specific Code
-
-**Example: Adding HDMI detection**
-
-1. **Check if platform supports it:**
- ```c
- // In workspace/miyoomini/platform/platform.h
- #define HAS_HDMI 1
- ```
-
-2. **Implement detection:**
- ```c
- // In workspace/miyoomini/platform/platform.c
- int PLAT_isHDMIConnected(void) {
- FILE* f = fopen("/sys/class/hdmi/status", "r");
- if (!f) return 0;
-
- char status[16];
- fgets(status, 16, f);
- fclose(f);
-
- return strncmp(status, "connected", 9) == 0;
- }
- ```
-
-3. **Add to platform abstraction:**
- ```c
- // In workspace/all/common/api.h
- #ifdef HAS_HDMI
- int PLAT_isHDMIConnected(void);
- #endif
- ```
-
-4. **Use in applications:**
- ```c
- // In minui.c
- #ifdef HAS_HDMI
- if (PLAT_isHDMIConnected()) {
- // Show HDMI-specific UI
- }
- #endif
- ```
-
-## Debugging
-
-### Logging
-
-MinUI applications can log to stdout/stderr:
-
-```c
-#define LOG(fmt, ...) fprintf(stderr, "[MinUI] " fmt "\n", ##__VA_ARGS__)
-
-LOG("Loading ROM: %s", rom_path);
-LOG("Battery: %d%%", battery_level);
-```
-
-**Viewing logs on device:**
-```bash
-# Via SSH or serial console
-tail -f /var/log/messages
-# or
-dmesg | grep MinUI
-```
-
-### Using GDB (if available on platform)
-
-```bash
-# On device
-gdbserver :1234 /mnt/SDCARD/SYSTEM/miyoomini/bin/minui.elf
-
-# On host
-arm-linux-gnueabihf-gdb minui.elf
-(gdb) target remote [device-ip]:1234
-(gdb) break main
-(gdb) continue
-```
-
-### Printf Debugging
-
-```c
-void debugFunction(void) {
- FILE* log = fopen("/mnt/SDCARD/debug.txt", "a");
- fprintf(log, "Entered debugFunction\n");
- fprintf(log, "Variable x = %d\n", x);
- fclose(log);
-}
-```
-
-### Common Debugging Scenarios
-
-**1. Crash on startup:**
-- Check for null pointer dereferences
-- Verify file paths exist
-- Check permissions
-
-**2. Graphics not displaying:**
-- Verify framebuffer initialization
-- Check surface formats match
-- Ensure flip/vsync called
-
-**3. Input not working:**
-- Check button mappings in platform.h
-- Verify input devices exist
-- Test with minput.elf utility
-
-**4. Audio issues:**
-- Check sample rate matches
-- Verify audio device initialization
-- Test buffer sizes
-
-### Testing on Device
-
-**Quick test cycle:**
-
-1. **Build binary:**
- ```bash
- make -C workspace/all/minui PLATFORM=miyoomini
- ```
-
-2. **Copy to device:**
- ```bash
- # Via network
- scp workspace/all/minui/minui.elf root@[device-ip]:/mnt/SDCARD/SYSTEM/miyoomini/bin/
-
- # Or copy to SD card via card reader
- cp workspace/all/minui/minui.elf /Volumes/SDCARD/SYSTEM/miyoomini/bin/
- ```
-
-3. **Restart MinUI:**
- - Power off device
- - Power on, test changes
-
-**Faster iteration (if SSH available):**
-```bash
-# On device
-pkill minui
-/mnt/SDCARD/SYSTEM/miyoomini/bin/minui.elf &
-```
-
-## Performance Optimization
-
-### Profiling
-
-**Manual timing:**
-```c
-#include
-
-clock_t start = clock();
-// ... code to measure ...
-clock_t end = clock();
-
-double seconds = (double)(end - start) / CLOCKS_PER_SEC;
-LOG("Operation took %.3f seconds", seconds);
-```
-
-**Frame timing:**
-```c
-static uint32_t last_frame_time = 0;
-
-void measureFrameRate(void) {
- uint32_t current = SDL_GetTicks();
- uint32_t delta = current - last_frame_time;
- last_frame_time = current;
-
- LOG("Frame time: %d ms (%.1f FPS)", delta, 1000.0 / delta);
-}
-```
-
-### Common Optimizations
-
-**1. Reduce allocations:**
-```c
-// Bad
-for (int i = 0; i < 1000; i++) {
- char* buffer = malloc(256);
- // ... use buffer ...
- free(buffer);
-}
-
-// Good
-char buffer[256];
-for (int i = 0; i < 1000; i++) {
- // ... use buffer ...
-}
-```
-
-**2. Cache frequently used values:**
-```c
-// Bad
-for (int i = 0; i < array_count; i++) {
- process(array[i], getConfigValue("setting"));
-}
-
-// Good
-int setting = getConfigValue("setting");
-for (int i = 0; i < array_count; i++) {
- process(array[i], setting);
-}
-```
-
-**3. Use platform-specific optimizations:**
-```c
-#ifdef __ARM_NEON__
-// Use NEON SIMD instructions
-#else
-// Fallback to scalar code
-#endif
-```
-
-**4. Minimize file I/O:**
-```c
-// Cache ROM list instead of rescanning every frame
-static RomList* cached_roms = NULL;
-
-if (!cached_roms) {
- cached_roms = scanRoms();
-}
-```
-
-## Platform Porting
-
-See [Adding Platform Support](adding-platform.md) for detailed guide.
-
-**Quick overview:**
-
-1. Create platform directory structure
-2. Implement platform.c/platform.h
-3. Implement libmsettings
-4. Create keymon daemon
-5. Configure cores to build
-6. Test and iterate
-
-## Creating Custom Paks
-
-See [PAKS.md](../PAKS.md) for complete guide.
-
-**Quick example:**
-
-```bash
-mkdir -p MyTool.pak
-cat > MyTool.pak/launch.sh << 'EOF'
-#!/bin/sh
-/mnt/SDCARD/SYSTEM/miyoomini/bin/mytool.elf
-EOF
-chmod +x MyTool.pak/launch.sh
-```
-
-## Contributing Guidelines
-
-### Before Submitting a PR
-
-1. **Test thoroughly:**
- - Test on at least one physical device
- - Test on multiple platforms if possible
- - Verify no regressions
-
-2. **Follow code style:**
- - Match existing style
- - Add comments for complex logic
- - Update documentation if needed
-
-3. **Keep commits clean:**
- - One logical change per commit
- - Clear commit messages
- - No merge commits (rebase)
-
-4. **Update documentation:**
- - Update relevant .md files
- - Update README if user-visible
- - Add to PAKS.md if pak-related
-
-### PR Description Template
-
-```markdown
-## Description
-Brief description of changes
-
-## Motivation
-Why is this change needed?
-
-## Testing
-- [ ] Tested on Miyoo Mini
-- [ ] Tested on RG35XX Plus
-- [ ] No regressions found
-
-## Screenshots (if UI change)
-[Add screenshots]
-
-## Checklist
-- [ ] Code follows project style
-- [ ] Documentation updated
-- [ ] No new warnings
-```
-
-## Common Pitfalls
-
-### 1. Platform Assumptions
-
-**Bad:**
-```c
-// Assumes 640x480 screen
-int x = 320; // Center of screen
-```
-
-**Good:**
-```c
-// Use platform constants
-int x = FIXED_WIDTH / 2;
-```
-
-### 2. Hardcoded Paths
-
-**Bad:**
-```c
-FILE* f = fopen("/mnt/SDCARD/roms/game.gb", "r");
-```
-
-**Good:**
-```c
-char path[256];
-snprintf(path, 256, "%s/Roms/Game Boy (GB)/game.gb", SDCARD_PATH);
-FILE* f = fopen(path, "r");
-```
-
-### 3. Memory Leaks
-
-**Bad:**
-```c
-Surface* loadImage(const char* path) {
- Surface* s = SDL_LoadBMP(path);
- return s;
- // Caller must remember to free!
-}
-```
-
-**Good:**
-```c
-// Document ownership
-Surface* loadImage(const char* path) {
- // Returns surface - caller must free with SDL_FreeSurface
- return SDL_LoadBMP(path);
-}
-```
-
-### 4. Buffer Overflows
-
-**Bad:**
-```c
-char buffer[256];
-strcpy(buffer, user_input); // Unsafe!
-```
-
-**Good:**
-```c
-char buffer[256];
-strncpy(buffer, user_input, 255);
-buffer[255] = '\0';
-```
-
-### 5. Race Conditions
-
-**Bad:**
-```c
-// Multiple threads accessing shared state
-static int counter = 0;
-counter++; // Not atomic!
-```
-
-**Good:**
-```c
-// Use mutexes
-static SDL_mutex* counter_lock;
-static int counter = 0;
-
-SDL_LockMutex(counter_lock);
-counter++;
-SDL_UnlockMutex(counter_lock);
-```
-
-## Resources
-
-### Documentation
-
-- [Architecture Overview](architecture.md)
-- [Project Structure](project-structure.md)
-- [Components Guide](components.md)
-- [Build System](build-system.md)
-- [Platform Abstraction](platform-abstraction.md)
-- [API Reference](api-reference.md)
-
-### External Resources
-
-- [Libretro API Documentation](https://docs.libretro.com/)
-- [SDL 1.2 Documentation](https://www.libsdl.org/release/SDL-1.2.15/docs/)
-- [SDL 2.0 Documentation](https://wiki.libsdl.org/)
-
-### Community
-
-- [MinUI GitHub Issues](https://github.com/shauninman/MinUI/issues)
-- [MinUI Discussions](https://github.com/shauninman/MinUI/discussions)
-
-## Getting Help
-
-If you're stuck:
-
-1. **Check existing documentation**
-2. **Search GitHub issues**
-3. **Ask in discussions**
-4. **Create a detailed issue with:**
- - What you're trying to do
- - What you've tried
- - Error messages
- - Platform and version
-
-## Next Steps
-
-- [Adding Platform Support](adding-platform.md) - Port to new devices
-- [API Reference](api-reference.md) - Detailed API documentation
-- [Troubleshooting](troubleshooting.md) - Common issues and solutions
diff --git a/docs/documentation-style-guide.md b/docs/documentation-style-guide.md
deleted file mode 100644
index d029adde..00000000
--- a/docs/documentation-style-guide.md
+++ /dev/null
@@ -1,372 +0,0 @@
-# C Code Documentation Style Guide
-
-This guide defines the documentation standards for the MinUI codebase. Following these conventions ensures consistency and helps developers understand the code quickly.
-
-## Philosophy
-
-Good documentation should:
-- **Explain WHY, not WHAT** - The code already shows what it does
-- **Be concise** - Don't over-explain obvious things
-- **Focus on non-obvious behavior** - Edge cases, platform quirks, memory ownership
-- **Help maintenance** - Future developers (including yourself) should understand intent
-
-## File-Level Documentation
-
-Every `.c` file should start with a header comment:
-
-```c
-/**
- * filename.c - Brief description of module purpose
- *
- * More detailed explanation of what this file provides,
- * its role in the system, and any important context.
- */
-```
-
-**Example:**
-```c
-/**
- * utils.c - Core utility functions for MinUI
- *
- * Provides cross-platform utilities for string manipulation, file I/O,
- * timing, and name processing. This file is shared across all platforms
- * and should not contain platform-specific code.
- */
-```
-
-## Function Documentation
-
-### Standard Format
-
-```c
-/**
- * Brief one-line description of what the function does.
- *
- * Optional longer explanation. Include:
- * - Edge cases or special behavior
- * - Performance characteristics if relevant
- * - Platform-specific notes
- * - Examples for complex transformations
- *
- * @param param_name Description of parameter and constraints
- * @param buffer Pointer to output buffer (modified in place)
- * @return Description of return value and special values
- *
- * @note Important caveats (e.g., "Not thread-safe")
- * @warning Critical issues (e.g., "Caller must free returned memory")
- */
-```
-
-### When to Document Functions
-
-| Function Type | Documentation Required |
-|---------------|------------------------|
-| Public API functions | **Always** - Full documentation |
-| Static helper functions | **If non-obvious** - Brief description |
-| Trivial getters/setters | **Optional** - Usually self-documenting |
-| Complex algorithms | **Always** - Explain the approach |
-
-### Examples
-
-**Good - Explains behavior and constraints:**
-```c
-/**
- * Reads entire file into dynamically allocated buffer.
- *
- * Allocates exactly the right amount of memory for the file.
- * Returns NULL if file cannot be opened or memory allocation fails.
- *
- * @param path Path to file
- * @return Pointer to allocated buffer, or NULL on failure
- *
- * @warning Caller must free returned pointer
- */
-char* allocFile(const char* path);
-```
-
-**Bad - Just repeats the function name:**
-```c
-/**
- * Allocates a file.
- */
-char* allocFile(const char* path);
-```
-
-## Inline Comments
-
-### When to Add Inline Comments
-
-✅ **DO comment:**
-- Non-obvious algorithms or bit manipulations
-- Platform-specific workarounds
-- Edge case handling
-- Magic numbers (or better: use named constants)
-- Buffer overlap safety (strcpy vs memmove)
-- Security-critical checks
-
-❌ **DON'T comment:**
-- Obvious operations (`i++; // increment i`)
-- Code that's already clear from variable names
-- Standard patterns everyone knows
-
-### Examples
-
-**Good - Explains WHY:**
-```c
-// Safe for overlapping buffers (source and dest may point to same memory)
-memmove(out_name, tmp, strlen(tmp) + 1);
-
-// Extended to 5 for .doom files (was 3)
-if (len > 2 && len <= 5) {
- tmp[0] = '\0';
-}
-
-// Hardware doesn't support negative brightness values
-if (brightness < 0) {
- brightness = 0;
-}
-```
-
-**Bad - States the obvious:**
-```c
-// Set i to 0
-i = 0;
-
-// Call strlen
-len = strlen(str);
-
-// Return the result
-return ret;
-```
-
-## Section Headers
-
-For files with multiple logical sections, use section headers:
-
-```c
-///////////////////////////////
-// Section Name
-///////////////////////////////
-```
-
-**Example sections:**
-- String utilities
-- File I/O utilities
-- Name processing utilities
-- Date/time utilities
-- Math utilities
-
-## Special Annotations
-
-Use these consistently throughout the codebase:
-
-### @param Tags
-```c
-@param path Path to file (input)
-@param buffer Pre-allocated buffer (modified in place)
-@param size Size of buffer in bytes
-```
-
-### @return Tags
-```c
-@return 0 on success, -1 on error
-@return Pointer to allocated memory, or NULL on failure
-@return 1 if match found, 0 otherwise
-```
-
-### @note Tags (General information)
-```c
-@note Buffer is not modified if file cannot be opened
-@note Uses memmove() for safe overlapping buffer copies
-@note Not thread-safe - uses static buffer
-```
-
-### @warning Tags (Critical information)
-```c
-@warning Caller must free returned pointer
-@warning Input string is modified in place
-@warning Only valid on 32-bit ARM platforms
-```
-
-## Platform-Specific Code
-
-When documenting code with platform-specific behavior:
-
-```c
-#if defined(__ARM_ARCH) && __ARM_ARCH >= 5 && !defined(__aarch64__)
-/**
- * Averages two RGB565 pixel values (ARM assembly version).
- *
- * This optimized assembly version is ~2x faster than C on 32-bit
- * ARM devices. Uses ARM-specific instructions for bit manipulation.
- *
- * @note Only used on 32-bit ARM (ARMv5+), not on ARM64/AArch64
- */
-uint32_t average16(uint32_t c1, uint32_t c2) {
- // Assembly implementation
-}
-#else
-/**
- * Averages two RGB565 pixel values (portable C version).
- *
- * Fallback implementation for non-ARM platforms.
- * See ARM version for algorithm explanation.
- */
-uint32_t average16(uint32_t c1, uint32_t c2) {
- // C implementation
-}
-#endif
-```
-
-## Examples and Edge Cases
-
-For complex transformations, provide examples:
-
-```c
-/**
- * Cleans a ROM path for display in the UI.
- *
- * Examples:
- * - "/mnt/SDCARD/Roms/GB/game.gb" -> "game"
- * - "Super Mario (USA) (v1.2).nes" -> "Super Mario"
- * - "Game [!].p8.png" -> "Game"
- *
- * @param in_name Input path or filename
- * @param out_name Output buffer for cleaned name (min 256 bytes)
- */
-void getDisplayName(const char* in_name, char* out_name);
-```
-
-## Memory Ownership
-
-Always document who owns allocated memory:
-
-```c
-/**
- * @return Pointer to allocated buffer
- * @warning Caller must free returned pointer
- */
-char* allocFile(const char* path);
-
-/**
- * @return Pointer to internal static buffer (do not free)
- * @note Not thread-safe - buffer reused on each call
- */
-char* getDisplayName(const char* in_name);
-```
-
-## Buffer Modification
-
-Clearly indicate when buffers are modified:
-
-```c
-/**
- * @param line String to normalize (modified in place)
- */
-void normalizeNewline(char* line);
-
-/**
- * @param buffer Pre-allocated buffer to fill
- * @note Buffer is not modified if file cannot be opened
- */
-void getFile(const char* path, char* buffer, size_t buffer_size);
-```
-
-## Common Documentation Patterns
-
-### String Manipulation Functions
-```c
-/**
- * Brief description of transformation.
- *
- * Example: "input" -> "output"
- *
- * @param str Input string (modified in place / not modified)
- * @return Success indicator or transformed value
- */
-```
-
-### File I/O Functions
-```c
-/**
- * Reads/Writes data from/to a file.
- *
- * Error behavior: Returns NULL / silently fails / etc.
- *
- * @param path Path to file
- * @return Data or status code
- *
- * @warning Memory ownership / buffer size requirements
- */
-```
-
-### Validation Functions
-```c
-/**
- * Checks if condition is met.
- *
- * Specific conditions that result in true/false.
- *
- * @param value Value to check
- * @return 1 if condition met, 0 otherwise
- */
-```
-
-## What NOT to Document
-
-Avoid documenting:
-1. Obvious standard library usage
-2. Self-explanatory variable assignments
-3. Standard design patterns
-4. Temporary debug code (remove it instead)
-5. TODO comments (use issue tracker instead, or mark with `TODO:` if temporary)
-
-## Header Files (.h)
-
-Document in headers when:
-- Function is part of public API
-- Struct members need explanation
-- Macros are non-obvious
-
-```c
-/**
- * Brief description of structure purpose.
- */
-typedef struct {
- int width; // Width in pixels
- int height; // Height in pixels
- void* pixels; // Pixel data (caller must free)
-} Surface;
-```
-
-## Updating Documentation
-
-When modifying code:
-1. **Update affected documentation** - Keep it in sync
-2. **Add new examples** if behavior changes
-3. **Document new edge cases** you discover
-4. **Remove obsolete comments** - Outdated docs are worse than none
-
-## Checklist for Code Reviews
-
-- [ ] File header describes module purpose
-- [ ] All public functions documented
-- [ ] Complex private functions documented
-- [ ] Non-obvious inline comments added
-- [ ] Memory ownership clear
-- [ ] Platform-specific code annotated
-- [ ] Examples provided for complex transformations
-- [ ] Edge cases documented
-- [ ] No redundant or obvious comments
-
-## Tools and Formatting
-
-- Use `clang-format` to maintain consistent spacing
-- Documentation comments use `/** */` style
-- Inline comments use `//` style
-- Keep line length under 100 characters (including comments)
-- Align parameter descriptions for readability
-
----
-
-**Remember:** Good documentation makes the code easier to understand, maintain, and extend. When in doubt, ask yourself: "Will I understand this code in 6 months?"
diff --git a/docs/formatting-setup.md b/docs/formatting-setup.md
deleted file mode 100644
index 761c7ee2..00000000
--- a/docs/formatting-setup.md
+++ /dev/null
@@ -1,211 +0,0 @@
-# Code Formatting Setup
-
-MinUI uses `clang-format` for consistent code formatting.
-
-## Commands
-
-### Check Formatting (Safe - No Changes)
-```bash
-make -f Makefile.qa format-check
-```
-
-Shows which files would be changed without modifying them.
-
-### Format Code (MODIFIES FILES)
-```bash
-make -f Makefile.qa format
-```
-
-**⚠️ WARNING:** This modifies files in place! Review changes with `git diff` before committing.
-
-### Format Specific File
-```bash
-clang-format -i workspace/all/minui/minui.c
-```
-
-## Configuration
-
-See `.clang-format` for formatting rules:
-
-```yaml
-# Indentation - MinUI uses tabs
-UseTab: ForIndentation
-TabWidth: 4
-
-# Braces - K&R style
-BreakBeforeBraces: Linux
-
-# Line length
-ColumnLimit: 100
-
-# Pointers
-PointerAlignment: Right
-```
-
-## Current Status
-
-**The codebase is NOT currently formatted** with clang-format.
-
-This is intentional - we're introducing formatting gradually:
-
-1. **Now:** Tool is available, can format new code
-2. **Later:** Format files as they're modified
-3. **Much Later:** Format entire codebase (requires review)
-
-## Usage Recommendations
-
-### For New Code
-```bash
-# After writing new code in file.c
-clang-format -i workspace/all/mynewfile.c
-```
-
-### For Modified Files
-```bash
-# After editing existing file
-clang-format -i workspace/all/minui/minui.c
-
-# Review changes
-git diff workspace/all/minui/minui.c
-
-# If looks good, commit
-git add workspace/all/minui/minui.c
-```
-
-### DON'T Format Everything Yet
-
-**Don't run** `make -f Makefile.qa format` **on the entire codebase** until:
-1. You've reviewed the changes it would make
-2. You're ready for a large formatting commit
-3. All team members agree
-
-## Why Not Format Everything Now?
-
-1. **Large diff** - Formatting 30,000+ lines creates huge git diff
-2. **Git blame** - Makes it harder to see real code changes vs formatting
-3. **Gentle approach** - Introduce tools gradually
-4. **Review burden** - Need to verify formatting doesn't break anything
-
-## Integration with Editor
-
-### VS Code
-Install "C/C++" extension and add to `.vscode/settings.json`:
-```json
-{
- "editor.formatOnSave": true,
- "C_Cpp.clang_format_style": "file"
-}
-```
-
-### Vim
-```vim
-" Format current file
-:!clang-format -i %
-```
-
-### Emacs
-```elisp
-(add-hook 'c-mode-hook
- (lambda () (add-hook 'before-save-hook 'clang-format-buffer nil t)))
-```
-
-## Formatting Rules Explained
-
-### Tabs vs Spaces
-```c
-// Uses tabs for indentation (existing MinUI style)
-void function(void) {
-→ int x = 1; // → is a tab
-}
-```
-
-### Pointer Alignment
-```c
-// Right-aligned (int* p, not int *p)
-int *pointer;
-char *string;
-```
-
-### Brace Style
-```c
-// Opening brace on same line (K&R/Linux style)
-if (condition) {
- doSomething();
-}
-
-// Functions
-void myFunction(void)
-{
- // Opening brace on new line for functions
-}
-```
-
-### Line Length
-```c
-// Max 100 characters per line
-// Long lines get wrapped automatically
-```
-
-## Incremental Adoption
-
-### Phase 1 (Now)
-- ✅ Tool installed and configured
-- ✅ Can format individual files
-- ✅ Documentation written
-
-### Phase 2 (Next Month)
-- Format new files as they're created
-- Format files as they're significantly modified
-- Build muscle memory
-
-### Phase 3 (Later)
-- Format entire codebase in one commit
-- Add format-check to CI
-- Require formatting for all PRs
-
-## Common Issues
-
-### "clang-format not found"
-```bash
-# macOS
-brew install llvm
-
-# Linux
-sudo apt-get install clang-format
-```
-
-### "Too many changes"
-Start with one file at a time:
-```bash
-clang-format -i workspace/all/clock/clock.c
-git diff workspace/all/clock/clock.c
-```
-
-### "Don't like the formatting"
-Edit `.clang-format` to adjust rules, then test:
-```bash
-clang-format -i test_file.c
-git diff test_file.c
-```
-
-## Quick Reference
-
-```bash
-# Check what would change (safe)
-make -f Makefile.qa format-check
-
-# Format all code (MODIFIES FILES!)
-make -f Makefile.qa format
-
-# Format one file
-clang-format -i path/to/file.c
-
-# See what would change without modifying
-clang-format path/to/file.c | diff path/to/file.c -
-```
-
-## Next Steps
-
-1. ✅ **Formatting available** - You are here
-2. ⏭️ **Use on new code** - Format files you create/edit
-3. ⏭️ **Eventually format all** - When ready for big commit
diff --git a/docs/improvement-plan.md b/docs/improvement-plan.md
deleted file mode 100644
index ed1ac7e0..00000000
--- a/docs/improvement-plan.md
+++ /dev/null
@@ -1,942 +0,0 @@
-# MinUI Code Quality Improvement Plan
-
-**Goal:** Transform MinUI from a one-person project into a maintainable, testable, community-friendly codebase while preserving its minimalist philosophy and performance.
-
-## Executive Summary
-
-MinUI has ~30,000 lines of C code across 12+ platforms. Analysis reveals:
-- **4,830-line minarch.c** with multiple responsibilities
-- **Minimal error handling** - unchecked malloc/fopen throughout
-- **No automated tests** - only manual hardware tests
-- **Heavy global state** - blocks testability
-- **Platform code duplication** - similar patterns across 12+ implementations
-
-This plan provides a **phased approach** over 6-12 months to introduce tests, improve code quality, and enable community contributions **without breaking existing functionality**.
-
----
-
-## Phase 1: Foundation (Weeks 1-4)
-
-**Goal:** Establish infrastructure for quality improvements
-
-### 1.1 Set Up Testing Infrastructure
-
-**Tasks:**
-- Add unit testing framework (Unity or MinUnit - both are minimal C frameworks)
-- Create `tests/` directory structure
-- Set up CI/CD with GitHub Actions
-- Add code coverage reporting (gcov/lcov)
-
-**Deliverables:**
-```
-tests/
-├── unity/ # Unity test framework
-├── utils/ # Tests for utils.c
-├── mocks/ # Mock implementations
-├── fixtures/ # Test data
-└── README.md # Testing guide
-```
-
-**CI Configuration:**
-```yaml
-# .github/workflows/test.yml
-name: Tests
-on: [push, pull_request]
-jobs:
- test:
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v2
- - name: Run unit tests
- run: make test
- - name: Upload coverage
- run: bash <(curl -s https://codecov.io/bash)
-```
-
-**Why:** Cannot improve what we cannot measure. Tests provide safety net for refactoring.
-
----
-
-### 1.2 Code Quality Tools
-
-**Tasks:**
-- Add static analysis (cppcheck, clang-tidy)
-- Set up formatting (clang-format with config)
-- Add linting to CI
-- Create `.editorconfig` for consistent style
-
-**Configuration:**
-```yaml
-# .clang-format
-BasedOnStyle: LLVM
-IndentWidth: 4
-ColumnLimit: 100
-AllowShortFunctionsOnASingleLine: Empty
-```
-
-**CI Integration:**
-```bash
-# Run on all PRs
-cppcheck --enable=all --suppress=missingInclude workspace/
-clang-format --dry-run -Werror workspace/**/*.c
-```
-
-**Why:** Automated checks catch issues before human review, establish consistent style.
-
----
-
-### 1.3 Documentation Standards
-
-**Tasks:**
-- Create CONTRIBUTING.md
-- Define code review checklist
-- Document coding standards
-- Create issue/PR templates
-
-**CONTRIBUTING.md outline:**
-```markdown
-# Contributing to MinUI
-
-## Code Standards
-- Functions must have docstrings
-- All malloc calls must be checked
-- All file I/O must handle errors
-- Max function length: 100 lines
-- Max file length: 500 lines (exceptions documented)
-
-## Testing Requirements
-- New features need unit tests
-- Bug fixes need regression tests
-- PRs need >80% coverage for new code
-
-## Review Process
-1. Automated checks must pass
-2. One maintainer approval required
-3. All conversations resolved
-```
-
-**Why:** Clear guidelines reduce friction for new contributors.
-
----
-
-## Phase 2: Quick Wins (Weeks 5-8)
-
-**Goal:** Fix critical safety issues and add initial tests
-
-### 2.1 Safety: Fix Unchecked Allocations
-
-**Priority:** CRITICAL
-
-**Tasks:**
-- Audit all malloc/calloc/realloc calls (~50+ instances)
-- Add error checking and cleanup
-- Create safe wrapper functions
-
-**Before:**
-```c
-static Array* Array_new(void) {
- Array* self = malloc(sizeof(Array));
- self->count = 0; // CRASH if malloc failed
- self->capacity = 8;
- self->items = malloc(sizeof(void*) * self->capacity);
- return self;
-}
-```
-
-**After:**
-```c
-static Array* Array_new(void) {
- Array* self = malloc(sizeof(Array));
- if (!self) {
- LOG_error("Failed to allocate Array\n");
- return NULL;
- }
-
- self->items = malloc(sizeof(void*) * 8);
- if (!self->items) {
- free(self);
- LOG_error("Failed to allocate Array items\n");
- return NULL;
- }
-
- self->count = 0;
- self->capacity = 8;
- return self;
-}
-
-// All callers must check:
-Array* arr = Array_new();
-if (!arr) {
- // Handle error
-}
-```
-
-**OR use safe wrappers:**
-```c
-// In new file: workspace/all/common/mem.c
-void* safe_malloc(size_t size, const char* context) {
- void* ptr = malloc(size);
- if (!ptr) {
- LOG_error("Allocation failed: %s (%zu bytes)\n", context, size);
- exit(1); // Or handle gracefully
- }
- return ptr;
-}
-
-// Usage:
-Array* self = safe_malloc(sizeof(Array), "Array_new");
-```
-
-**Impact:** Prevents crashes from allocation failures. ~50 locations to fix.
-
----
-
-### 2.2 Safety: Standardize Error Handling
-
-**Tasks:**
-- Define error code enum
-- Create error handling macros
-- Convert void functions to return status codes
-
-**Error codes:**
-```c
-// workspace/all/common/errors.h
-typedef enum {
- ERR_OK = 0,
- ERR_MALLOC,
- ERR_FILE_OPEN,
- ERR_FILE_READ,
- ERR_FILE_WRITE,
- ERR_INVALID_ARG,
- ERR_NOT_FOUND,
- ERR_PLATFORM,
-} ErrorCode;
-
-const char* ErrorCode_toString(ErrorCode err);
-```
-
-**Error handling pattern:**
-```c
-// Before:
-void SRAM_read(void) {
- FILE *sram_file = fopen(filename, "r");
- if (!sram_file) return; // Silent failure
- // ...
-}
-
-// After:
-ErrorCode SRAM_read(void) {
- FILE *sram_file = fopen(filename, "r");
- if (!sram_file) {
- LOG_warn("Failed to open SRAM file: %s\n", filename);
- return ERR_FILE_OPEN;
- }
-
- if (fread(sram, 1, size, sram_file) != size) {
- LOG_error("Failed to read SRAM data\n");
- fclose(sram_file);
- return ERR_FILE_READ;
- }
-
- fclose(sram_file);
- return ERR_OK;
-}
-
-// Caller:
-ErrorCode err = SRAM_read();
-if (err != ERR_OK) {
- // Handle or propagate
-}
-```
-
-**Impact:** Makes errors visible, propagatable, testable.
-
----
-
-### 2.3 Testing: Add Tests for utils.c
-
-**Goal:** Prove testing works, build momentum
-
-**Tasks:**
-- Test all string functions (prefixMatch, suffixMatch, etc.)
-- Test file path functions
-- Test display name parsing
-- Achieve 90%+ coverage for utils.c
-
-**Example test:**
-```c
-// tests/utils/test_string.c
-#include "unity.h"
-#include "../../workspace/all/common/utils.h"
-
-void setUp(void) {}
-void tearDown(void) {}
-
-void test_prefixMatch_exact(void) {
- TEST_ASSERT_TRUE(prefixMatch("hello", "hello"));
-}
-
-void test_prefixMatch_longer(void) {
- TEST_ASSERT_TRUE(prefixMatch("hello world", "hello"));
-}
-
-void test_prefixMatch_nomatch(void) {
- TEST_ASSERT_FALSE(prefixMatch("hello", "world"));
-}
-
-void test_suffixMatch_extension(void) {
- TEST_ASSERT_TRUE(suffixMatch("game.gb", ".gb"));
-}
-
-int main(void) {
- UNITY_BEGIN();
- RUN_TEST(test_prefixMatch_exact);
- RUN_TEST(test_prefixMatch_longer);
- RUN_TEST(test_prefixMatch_nomatch);
- RUN_TEST(test_suffixMatch_extension);
- return UNITY_END();
-}
-```
-
-**Build integration:**
-```makefile
-# Makefile
-test:
- $(CC) -o tests/utils_test tests/utils/test_string.c \
- workspace/all/common/utils.c tests/unity/unity.c
- ./tests/utils_test
-```
-
-**Impact:**
-- Demonstrates testing value
-- Prevents regressions in utility code
-- Template for future tests
-
----
-
-### 2.4 Documentation: Function-Level Docs
-
-**Tasks:**
-- Document all public API functions (GFX_*, SND_*, PAD_*, PWR_*)
-- Add docstrings to complex functions
-- Generate HTML docs (optional: Doxygen)
-
-**Format:**
-```c
-/**
- * @brief Initializes the graphics subsystem
- *
- * Sets up SDL video mode, loads UI assets, initializes fonts,
- * and prepares rendering surfaces. Must be called before any
- * other GFX_* functions.
- *
- * @return ERR_OK on success, error code on failure
- *
- * @note This function allocates resources that must be freed
- * with GFX_quit()
- */
-ErrorCode GFX_init(void);
-
-/**
- * @brief Loads a PNG image from disk
- *
- * @param path File path to PNG image (must exist)
- * @return Loaded surface on success, NULL on failure
- *
- * @note Returned surface is cached internally - do NOT free.
- * Call GFX_freeImage() to release if needed.
- *
- * @warning Path must remain valid for lifetime of image
- */
-SDL_Surface* GFX_loadImage(const char* path);
-```
-
-**Impact:** Makes codebase approachable for new contributors.
-
----
-
-## Phase 3: Modularization (Weeks 9-16)
-
-**Goal:** Break up large files, reduce coupling
-
-### 3.1 Split minarch.c (4,830 lines → ~5 files)
-
-**Target structure:**
-```
-workspace/all/minarch/
-├── minarch.c # Main entry point, game loop (500 lines)
-├── core.c/h # Libretro core loading/callbacks (800 lines)
-├── savestate.c/h # Save states, SRAM, RTC (400 lines)
-├── config.c/h # Configuration system (600 lines)
-├── video.c/h # Video pipeline, scaling (800 lines)
-├── audio.c/h # Audio buffering (300 lines)
-├── input.c/h # Input mapping, shortcuts (400 lines)
-├── menu.c/h # In-game menu (600 lines)
-├── disc.c/h # Disc swapping, M3U (200 lines)
-└── makefile # Updated build
-```
-
-**Migration strategy:**
-1. Create new files with stubs
-2. Move functions one at a time
-3. Keep minarch.c compiling after each move
-4. Update makefile
-5. Test on real hardware
-
-**Example split - core.c:**
-```c
-// minarch/core.h
-typedef struct {
- void* handle;
- struct retro_core_t {
- // Core function pointers
- } api;
-} Core;
-
-ErrorCode Core_init(void);
-ErrorCode Core_load(const char* core_path);
-ErrorCode Core_loadGame(const char* game_path);
-void Core_run(void);
-void Core_unload(void);
-void Core_quit(void);
-
-// minarch/core.c
-#include "core.h"
-
-static Core g_core = {0};
-
-ErrorCode Core_load(const char* core_path) {
- g_core.handle = dlopen(core_path, RTLD_LAZY);
- if (!g_core.handle) {
- LOG_error("Failed to load core: %s\n", dlerror());
- return ERR_FILE_OPEN;
- }
- // Load symbols...
- return ERR_OK;
-}
-```
-
-**Impact:**
-- Easier to understand (500 lines vs 4,830)
-- Easier to test (can test savestate.c independently)
-- Enables parallel development
-
----
-
-### 3.2 Extract Common Platform Code
-
-**Problem:** 12 platforms with duplicated code
-
-**Solution:** Create platform utility library
-
-**New structure:**
-```
-workspace/common/platform/
-├── platform_common.c/h # Shared platform code
-├── video_common.c/h # Common video setup
-├── input_common.c/h # Common input patterns
-├── scaler_common.c/h # Common scaling logic
-└── battery_common.c/h # Common battery reading
-```
-
-**Example - video_common.c:**
-```c
-// Before: Duplicated in 12 platforms
-SDL_Surface* PLAT_initVideo(void) {
- SDL_Init(SDL_INIT_VIDEO);
- SDL_ShowCursor(0);
- // Platform-specific parts...
-}
-
-// After: Shared code + hooks
-typedef struct {
- int width;
- int height;
- int bpp;
- void (*setup_hook)(void); // Platform-specific
-} VideoConfig;
-
-SDL_Surface* Platform_initVideoCommon(VideoConfig* config) {
- SDL_Init(SDL_INIT_VIDEO);
- SDL_ShowCursor(0);
-
- if (config->setup_hook) {
- config->setup_hook();
- }
-
- return SDL_SetVideoMode(
- config->width,
- config->height,
- config->bpp,
- SDL_SWSURFACE
- );
-}
-
-// Each platform:
-static void miyoomini_video_setup(void) {
- // Miyoo Mini specific setup
-}
-
-SDL_Surface* PLAT_initVideo(void) {
- VideoConfig config = {
- .width = 640,
- .height = 480,
- .bpp = 16,
- .setup_hook = miyoomini_video_setup
- };
- return Platform_initVideoCommon(&config);
-}
-```
-
-**Impact:**
-- Reduce duplication from ~500 lines × 12 = 6,000 lines to ~500 + (12 × 50) = 1,100 lines
-- Easier to add new platforms
-- Bugs fixed once, not 12 times
-
----
-
-### 3.3 Introduce Dependency Injection
-
-**Goal:** Make code testable by inverting dependencies
-
-**Example - File I/O abstraction:**
-```c
-// Before (in minui.c, api.c, minarch.c):
-FILE* f = fopen(path, "r");
-if (!f) return;
-fread(buffer, size, 1, f);
-fclose(f);
-
-// After: workspace/all/common/filesystem.h
-typedef struct {
- void* (*open)(const char* path, const char* mode);
- size_t (*read)(void* ptr, size_t size, size_t count, void* file);
- int (*close)(void* file);
- // ... etc
-} FileSystem;
-
-// Real implementation: workspace/all/common/filesystem_real.c
-static void* fs_real_open(const char* path, const char* mode) {
- return fopen(path, mode);
-}
-
-FileSystem* FileSystem_real(void) {
- static FileSystem fs = {
- .open = fs_real_open,
- .read = (void*)fread,
- .close = (void*)fclose,
- };
- return &fs;
-}
-
-// Test implementation: tests/mocks/filesystem_mock.c
-static void* fs_mock_open(const char* path, const char* mode) {
- // Return mock file handle
-}
-
-FileSystem* FileSystem_mock(void) {
- static FileSystem fs = {
- .open = fs_mock_open,
- // ...
- };
- return &fs;
-}
-
-// Usage in code:
-void loadConfig(FileSystem* fs) {
- void* file = fs->open("config.ini", "r");
- // ...
-}
-
-// Production:
-loadConfig(FileSystem_real());
-
-// Test:
-loadConfig(FileSystem_mock());
-```
-
-**Impact:** Enables unit testing without real files/hardware.
-
----
-
-## Phase 4: Comprehensive Testing (Weeks 17-24)
-
-**Goal:** Achieve 60%+ code coverage
-
-### 4.1 Unit Tests for Core Logic
-
-**Targets:**
-- Array/Hash operations (minui.c)
-- Config parsing (minarch.c)
-- Display name parsing (minui.c)
-- Input mapping (api.c)
-- Text wrapping/truncation (api.c)
-
-**Example - Array tests:**
-```c
-// tests/minui/test_array.c
-void test_Array_push_increases_count(void) {
- Array* arr = Array_new();
- TEST_ASSERT_EQUAL(0, arr->count);
-
- Array_push(arr, (void*)1);
- TEST_ASSERT_EQUAL(1, arr->count);
-
- Array_free(arr);
-}
-
-void test_Array_push_expands_capacity(void) {
- Array* arr = Array_new();
- // Push 100 items
- for (int i = 0; i < 100; i++) {
- Array_push(arr, (void*)(long)i);
- }
-
- TEST_ASSERT_EQUAL(100, arr->count);
- TEST_ASSERT_GREATER_OR_EQUAL(100, arr->capacity);
- Array_free(arr);
-}
-```
-
-**Coverage target:** 80% for utils.c, 60% for minui/minarch business logic.
-
----
-
-### 4.2 Integration Tests
-
-**Goal:** Test component interactions without hardware
-
-**Approach:**
-- Mock SDL, platform functions
-- Test minui navigation logic
-- Test minarch save/load states
-- Test config persistence
-
-**Example - SaveState integration test:**
-```c
-// tests/integration/test_savestate.c
-void test_savestate_roundtrip(void) {
- // Setup mock filesystem
- FileSystem* fs = FileSystem_mock();
-
- // Create fake save state
- uint8_t save_data[1024] = {1, 2, 3, 4, 5};
-
- // Save
- ErrorCode err = SaveState_write(fs, "test.st0", save_data, 1024);
- TEST_ASSERT_EQUAL(ERR_OK, err);
-
- // Load
- uint8_t load_data[1024] = {0};
- err = SaveState_read(fs, "test.st0", load_data, 1024);
- TEST_ASSERT_EQUAL(ERR_OK, err);
-
- // Verify
- TEST_ASSERT_EQUAL_MEMORY(save_data, load_data, 1024);
-}
-```
-
----
-
-### 4.3 Platform Tests
-
-**Goal:** Automated tests for each platform (where possible)
-
-**Approach:**
-- Hardware tests in CI (if runners available)
-- OR: Platform simulation (QEMU for ARM platforms)
-- OR: Mock platform functions for logic tests
-
-**Platform test structure:**
-```
-tests/platforms/
-├── miyoomini/
-│ ├── test_battery.c
-│ ├── test_brightness.c
-│ └── test_input.c
-├── rg35xx/
-│ └── ...
-└── common/
- └── test_platform_common.c
-```
-
-**Example:**
-```c
-// tests/platforms/miyoomini/test_battery.c
-void test_battery_reading_range(void) {
- int level = PLAT_getBatteryStatus();
- TEST_ASSERT_GREATER_OR_EQUAL(-1, level);
- TEST_ASSERT_LESS_OR_EQUAL(200, level); // 0-100 normal, 101-200 charging
-}
-```
-
----
-
-## Phase 5: Continuous Improvement (Weeks 25+)
-
-**Goal:** Establish sustainable practices
-
-### 5.1 CI/CD Pipeline
-
-**Full pipeline:**
-```yaml
-name: CI/CD
-
-on: [push, pull_request]
-
-jobs:
- lint:
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v2
- - name: Run clang-format
- run: make format-check
- - name: Run cppcheck
- run: make lint
-
- test:
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v2
- - name: Unit tests
- run: make test
- - name: Coverage
- run: make coverage
- - name: Upload to codecov
- uses: codecov/codecov-action@v2
-
- build:
- runs-on: ubuntu-latest
- strategy:
- matrix:
- platform: [miyoomini, rg35xx, rg35xxplus]
- steps:
- - uses: actions/checkout@v2
- - name: Build ${{ matrix.platform }}
- run: make PLATFORM=${{ matrix.platform }}
- - name: Upload artifacts
- uses: actions/upload-artifact@v2
-
- integration:
- runs-on: ubuntu-latest
- needs: build
- steps:
- - name: Integration tests
- run: make test-integration
-```
-
-**Benefits:**
-- Every PR is tested automatically
-- Catches issues before merge
-- Builds all platforms on every change
-
----
-
-### 5.2 Code Review Standards
-
-**Required for all PRs:**
-- [ ] All tests pass
-- [ ] Coverage >80% for new code
-- [ ] Lint checks pass
-- [ ] Documentation updated
-- [ ] Changelog entry added
-- [ ] One maintainer approval
-
-**Review checklist:**
-```markdown
-## Code Review Checklist
-
-### Functionality
-- [ ] Code does what it claims
-- [ ] No obvious bugs
-- [ ] Error cases handled
-
-### Quality
-- [ ] Functions <100 lines
-- [ ] No duplicated code
-- [ ] Clear variable names
-- [ ] Comments explain "why", not "what"
-
-### Testing
-- [ ] Unit tests added
-- [ ] Tests cover edge cases
-- [ ] Tests are deterministic
-
-### Safety
-- [ ] All malloc/fopen checked
-- [ ] No buffer overflows
-- [ ] No memory leaks
-```
-
----
-
-### 5.3 Refactoring Backlog
-
-**Ongoing improvements:**
-
-**Priority 1:**
-- [ ] Split minui.c into modules (1,704 → ~500 lines)
-- [ ] Extract platform common code
-- [ ] Add error codes throughout
-
-**Priority 2:**
-- [ ] Reduce global state in minarch.c
-- [ ] Create save state module
-- [ ] Separate config system
-
-**Priority 3:**
-- [ ] Optimize scaler (profile-guided)
-- [ ] Add benchmarks
-- [ ] Document platform porting guide
-
----
-
-## Success Metrics
-
-### Month 3:
-- [x] Test infrastructure in place
-- [x] CI/CD running
-- [x] 100% of allocations checked
-- [x] utils.c at 90% coverage
-- [x] CONTRIBUTING.md published
-
-### Month 6:
-- [x] minarch.c split into modules
-- [x] Platform common code extracted
-- [x] 40% overall code coverage
-- [x] 5+ community PRs merged
-
-### Month 12:
-- [x] 60% overall code coverage
-- [x] All major components tested
-- [x] Zero known crashes
-- [x] 20+ community contributors
-- [x] Monthly releases
-
----
-
-## Risk Mitigation
-
-### Risk 1: Breaking Existing Functionality
-
-**Mitigation:**
-- Comprehensive smoke tests on hardware before merging
-- Beta testing channel for early adopters
-- Easy rollback (keep old builds available)
-- Automated testing catches regressions
-
-### Risk 2: Community Resistance to Changes
-
-**Mitigation:**
-- Communicate plan publicly
-- Accept feedback and adjust
-- Maintain backward compatibility
-- Document all breaking changes
-
-### Risk 3: Testing Takes Too Long
-
-**Mitigation:**
-- Start with quick wins (utils.c)
-- Focus on high-value tests
-- Don't aim for 100% coverage
-- Prioritize new code coverage
-
-### Risk 4: Refactoring Introduces Bugs
-
-**Mitigation:**
-- Refactor in small increments
-- Keep tests passing at each step
-- Extensive testing on real hardware
-- Ship refactorings separately from features
-
----
-
-## Resource Requirements
-
-### Development Time
-
-**Assuming 1-2 people part-time:**
-- **Phase 1:** 40-60 hours (setup)
-- **Phase 2:** 80-100 hours (quick wins)
-- **Phase 3:** 120-160 hours (modularization)
-- **Phase 4:** 100-140 hours (comprehensive testing)
-- **Phase 5:** Ongoing (~20 hours/month)
-
-**Total:** ~400-500 hours over 6-12 months
-
-### Infrastructure
-
-**Free tier options:**
-- GitHub Actions (2,000 minutes/month free)
-- Codecov (free for open source)
-- GitHub (free for public repos)
-
-**Optional paid:**
-- Hardware test runners (~$200 for Raspberry Pi + devices)
-- Cloud build machines (~$50/month)
-
----
-
-## Getting Started
-
-### Week 1 Action Items
-
-1. **Set up testing framework:**
- ```bash
- cd MinUI
- mkdir -p tests/unity
- wget https://github.com/ThrowTheSwitch/Unity/releases/download/v2.5.2/unity.c
- wget https://github.com/ThrowTheSwitch/Unity/releases/download/v2.5.2/unity.h
- ```
-
-2. **Create first test:**
- ```bash
- # tests/test_utils.c
- # (see example above)
- ```
-
-3. **Add to Makefile:**
- ```makefile
- test: tests/test_utils
- ./tests/test_utils
-
- tests/test_utils: tests/test_utils.c workspace/all/common/utils.c
- $(CC) -o $@ $^ tests/unity/unity.c -I. -Iworkspace/all
- ```
-
-4. **Run:**
- ```bash
- make test
- ```
-
-5. **Set up GitHub Actions:**
- ```bash
- mkdir -p .github/workflows
- # Create test.yml (see CI example above)
- ```
-
-6. **Commit and push:**
- ```bash
- git checkout -b feature/testing-infrastructure
- git add tests/ .github/workflows/test.yml Makefile
- git commit -m "Add testing infrastructure and first tests"
- git push origin feature/testing-infrastructure
- ```
-
----
-
-## Conclusion
-
-This plan balances **immediate safety improvements** (unchecked allocations) with **long-term sustainability** (modularization, testing). By following this phased approach:
-
-1. **Foundation** - Establish tooling
-2. **Quick Wins** - Fix critical issues, prove value
-3. **Modularization** - Make code maintainable
-4. **Testing** - Comprehensive coverage
-5. **Continuous** - Sustainable practices
-
-MinUI can evolve from a solo project to a community-maintained codebase **without sacrificing its minimalist philosophy or breaking existing functionality**.
-
-The key is to **start small** (utils.c tests), **ship incrementally** (one module at a time), and **always keep the lights on** (tests prevent regressions).
-
-**Next Steps:** Review this plan, adjust priorities based on your goals, and start with Week 1 action items.
diff --git a/docs/platforms.md b/docs/platforms.md
deleted file mode 100644
index 76f59a94..00000000
--- a/docs/platforms.md
+++ /dev/null
@@ -1,554 +0,0 @@
-# MinUI Supported Platforms
-
-This document provides detailed information about all platforms supported by MinUI.
-
-## Platform Overview
-
-MinUI currently supports **12+ platform families**, each representing one or more handheld gaming devices.
-
-| Platform ID | Devices | Screen | Status |
-|-------------|---------|--------|--------|
-| miyoomini | Miyoo Mini, Mini Plus | 640x480 | Deprecated |
-| my282 | Miyoo Mini Flip | 752x560 | Deprecated |
-| my355 | Miyoo Flip, A30 | 640x480 | Deprecated |
-| trimuismart | Trimui Smart, Smart Pro, Brick | 640x480 | Deprecated |
-| rg35xx | RG35XX original | 640x480 | Deprecated |
-| rg35xxplus | RG35XX Plus, H, 2024, RG28XX, etc. | 640x480 | Deprecated |
-| rgb30 | RGB30 | 720x720 | Deprecated |
-| tg5040 | Trimui Smart Pro | 1024x768 | Deprecated |
-| m17 | M17 | 640x480 | Deprecated |
-| gkdpixel | GKD Pixel, GKD Mini | 640x480 | Deprecated |
-| magicmini | MagicX XU Mini M | 640x480 | Deprecated |
-| zero28 | MagicX Mini Zero 28 | 640x480 | Deprecated |
-
-**Note:** All platforms are marked "Deprecated" in current codebase, but remain functional.
-
----
-
-## Platform Details
-
-### Miyoo Mini Family
-
-#### miyoomini
-**Devices:** Miyoo Mini, Miyoo Mini Plus
-
-**Specifications:**
-- **Screen:** 640x480 (4:3)
-- **CPU:** ARM Cortex-A7
-- **RAM:** 128 MB
-- **Buttons:** D-pad, A, B, X, Y, L1, R1, Select, Start, Menu
-- **Features:** Battery monitoring, sleep mode
-
-**Platform Code:** `/workspace/miyoomini/`
-
-**Hardware Access:**
-- Framebuffer: `/dev/fb0`
-- Input: `/dev/input/event0`
-- Backlight: `/sys/class/pwm/pwmchip0/pwm0/`
-- Battery: `/sys/devices/gpiochip0/gpio/gpio59/value`
-
-**Special Features:**
-- Overclock support (up to 1.4 GHz)
-- Battery percentage monitoring
-- Luminance control
-- ADBD support (Android Debug Bridge daemon)
-
-**Included Utilities:**
-- `show.elf` - Splash screen
-- `overclock.elf` - CPU frequency control
-- `batmon.elf` - Battery monitor
-- `lumon.elf` - Luminance monitor
-- `blank.elf` - Screen blanking
-
----
-
-#### my282
-**Devices:** Miyoo Mini Flip
-
-**Specifications:**
-- **Screen:** 752x560 (clamshell)
-- **CPU:** ARM Cortex-A7
-- **RAM:** 128 MB
-- **Buttons:** D-pad, A, B, X, Y, L1, R1, Select, Start, Menu
-- **Features:** Lid detection, analog stick
-
-**Platform Code:** `/workspace/my282/`
-
-**Hardware Access:**
-- Framebuffer: `/dev/fb0`
-- Input: Multiple `/dev/input/event*`
-- Analog stick: Custom library
-- Lid switch: GPIO
-
-**Special Features:**
-- Lid open/close detection
-- Analog stick support (libmstick)
-- Auto-sleep on lid close
-
-**Included Utilities:**
-- `show.elf` - Splash screen
-- `libmstick.so` - Analog stick library
-
----
-
-#### my355
-**Devices:** Miyoo Flip, Miyoo A30
-
-**Specifications:**
-- **Screen:** 640x480
-- **CPU:** ARM Cortex-A7
-- **RAM:** 256 MB
-- **Buttons:** Full button set
-- **Features:** Enhanced hardware
-
-**Platform Code:** `/workspace/my355/`
-
-**Special Features:**
-- Improved performance over Mini
-- Better battery life
-
----
-
-### Trimui Family
-
-#### trimuismart
-**Devices:** Trimui Smart, Trimui Smart Pro, Trimui Brick
-
-**Specifications:**
-- **Screen:** 640x480
-- **CPU:** ARM
-- **Buttons:** D-pad, A, B, X, Y, L, R, Select, Start, Menu
-
-**Platform Code:** `/workspace/trimuismart/`
-
-**Hardware Access:**
-- Framebuffer: `/dev/fb0`
-- Input: `/dev/input/event*`
-- Backlight: `/sys/class/backlight/`
-
-**Special Features:**
-- Compact form factor
-- Good battery life
-
----
-
-#### tg5040
-**Devices:** Trimui Smart Pro (high-res variant)
-
-**Specifications:**
-- **Screen:** 1024x768
-- **CPU:** ARM
-- **RAM:** 256 MB
-- **Buttons:** Full button set
-- **Features:** Higher resolution
-
-**Platform Code:** `/workspace/tg5040/`
-
-**Special Features:**
-- High-resolution display
-- Enhanced performance
-
----
-
-### Anbernic Family
-
-#### rg35xx
-**Devices:** Anbernic RG35XX (original)
-
-**Specifications:**
-- **Screen:** 640x480
-- **CPU:** ARM Cortex-A9
-- **RAM:** 256 MB
-- **Buttons:** D-pad, A, B, X, Y, L1, R1, L2, R2, Select, Start
-
-**Platform Code:** `/workspace/rg35xx/`
-
-**Hardware Access:**
-- Framebuffer: `/dev/fb0`
-- Input: Multiple event devices
-- Backlight: `/sys/class/backlight/`
-
-**Special Features:**
-- Overclock support
-- Good build quality
-- L2/R2 triggers
-
-**Included Utilities:**
-- `overclock.elf` - CPU control
-- `show.elf` - Splash screen
-
----
-
-#### rg35xxplus
-**Devices:** RG35XX Plus, RG35XX H, RG35XX 2024, RG28XX, RG35XXSP, RG40XXH, RG40XXV, RGCubeXX, RG34XX, RG34XXSP
-
-**Specifications:**
-- **Screen:** 640x480 (varies by model)
-- **CPU:** ARM Cortex-A9
-- **RAM:** 256-512 MB
-- **Buttons:** Full button set, some with analog sticks
-- **Features:** Enhanced hardware, HDMI output (some models)
-
-**Platform Code:** `/workspace/rg35xxplus/`
-
-**Hardware Access:**
-- Multiple framebuffers
-- Enhanced input devices
-- HDMI detection (where available)
-
-**Special Features:**
-- Analog stick support (some models)
-- HDMI output (some models)
-- Better performance
-
-**Included Utilities:**
-- `init.elf` - System initialization
-- `show.elf` - Splash screen
-
----
-
-### Powkiddy
-
-#### rgb30
-**Devices:** Powkiddy RGB30
-
-**Specifications:**
-- **Screen:** 720x720 (1:1 square)
-- **CPU:** ARM
-- **RAM:** 256 MB
-- **Buttons:** Full button set, dual analog sticks
-
-**Platform Code:** `/workspace/rgb30/`
-
-**Hardware Access:**
-- Square framebuffer
-- Dual analog sticks
-- Enhanced input
-
-**Special Features:**
-- Unique square screen
-- Dual analog sticks
-- Vertical or horizontal orientation
-
----
-
-### Other Platforms
-
-#### m17
-**Devices:** M17
-
-**Specifications:**
-- **Screen:** 640x480
-- **CPU:** ARM
-- **Buttons:** Standard button set
-
-**Platform Code:** `/workspace/m17/`
-
----
-
-#### gkdpixel
-**Devices:** GKD Pixel, GKD Mini
-
-**Specifications:**
-- **Screen:** 640x480
-- **CPU:** ARM
-- **Buttons:** Standard button set
-- **Features:** Compact design
-
-**Platform Code:** `/workspace/gkdpixel/`
-
----
-
-#### magicmini
-**Devices:** MagicX XU Mini M
-
-**Specifications:**
-- **Screen:** 640x480
-- **CPU:** ARM
-- **Buttons:** Standard button set
-
-**Platform Code:** `/workspace/magicmini/`
-
----
-
-#### zero28
-**Devices:** MagicX Mini Zero 28
-
-**Specifications:**
-- **Screen:** 640x480
-- **CPU:** ARM
-- **Buttons:** Standard button set
-
-**Platform Code:** `/workspace/zero28/`
-
-**Special Features:**
-- Custom backlight control
-
-**Included Utilities:**
-- `bl.elf` - Backlight control
-- `show.elf` - Splash screen
-
----
-
-## Platform Comparison
-
-### Screen Resolutions
-
-| Resolution | Platforms |
-|------------|-----------|
-| 640x480 | miyoomini, my355, trimuismart, rg35xx, rg35xxplus, m17, gkdpixel, magicmini, zero28 |
-| 752x560 | my282 |
-| 720x720 | rgb30 |
-| 1024x768 | tg5040 |
-
-### Button Layouts
-
-**Standard Layout:**
-- D-pad (Up, Down, Left, Right)
-- Face buttons (A, B, X, Y)
-- Shoulders (L1/L, R1/R)
-- System (Select, Start, Menu)
-
-**Extended Layout (some models):**
-- Extra shoulders (L2, R2)
-- Analog sticks (L3, R3)
-- Function button
-
-### Features by Platform
-
-| Feature | Platforms |
-|---------|-----------|
-| Battery monitoring | All |
-| Sleep mode | All |
-| Brightness control | All |
-| Volume control | All |
-| Overclock support | miyoomini, rg35xx |
-| Analog sticks | my282, rgb30, some rg35xxplus |
-| HDMI output | Some rg35xxplus |
-| Lid detection | my282 |
-
----
-
-## Platform-Specific Considerations
-
-### miyoomini
-
-**Performance:**
-- Good performance for 8/16-bit systems
-- Struggles with PS1 (use frameskip)
-- Overclock recommended for demanding games
-
-**Battery:**
-- ~4-6 hours typical usage
-- Battery percentage available
-
-**Quirks:**
-- Backlight control via PWM
-- Custom battery detection
-
----
-
-### my282
-
-**Performance:**
-- Similar to miyoomini
-- Higher resolution screen
-
-**Special Handling:**
-- Lid detection requires polling
-- Analog stick needs calibration
-- Auto-sleep on lid close
-
-**Quirks:**
-- Clamshell form factor
-- Screen protector affects display
-
----
-
-### rg35xx / rg35xxplus
-
-**Performance:**
-- Better than Miyoo Mini
-- Good PS1 performance
-- Can handle more demanding cores
-
-**Special Handling:**
-- Multiple input devices
-- Some models have HDMI
-- Analog sticks (Plus models)
-
-**Quirks:**
-- Stock firmware interference
-- Need to disable stock services
-
----
-
-### rgb30
-
-**Performance:**
-- Good performance
-- Square screen unique
-
-**Special Handling:**
-- Square framebuffer (720x720)
-- Dual analog sticks
-- Can rotate display
-
-**Quirks:**
-- Aspect ratio handling for rectangular content
-- Letterboxing or pillarboxing always needed
-
----
-
-### tg5040
-
-**Performance:**
-- High resolution
-- Good performance
-
-**Special Handling:**
-- 1024x768 framebuffer
-- Higher resolution assets
-- More scaling options
-
-**Quirks:**
-- Larger display
-- Higher power consumption
-
----
-
-## Cross-Platform Development
-
-### Platform-Independent Code
-
-Most code should be platform-independent:
-- Use `FIXED_WIDTH` / `FIXED_HEIGHT` instead of hardcoded values
-- Use `SDCARD_PATH` instead of hardcoded `/mnt/SDCARD`
-- Check capability defines before using features
-
-### Platform-Specific Code
-
-When platform-specific code is needed:
-
-```c
-#if defined(PLATFORM_MIYOOMINI)
- // Miyoo Mini specific
-#elif defined(PLATFORM_RG35XX)
- // RG35XX specific
-#else
- // Default/common code
-#endif
-```
-
-### Capability Defines
-
-Check capabilities instead of platforms:
-
-```c
-#ifdef HAS_HDMI
- if (PLAT_isHDMIConnected()) {
- // HDMI-specific handling
- }
-#endif
-
-#ifdef HAS_ANALOG
- int x = PAD_getAnalogX();
-#endif
-```
-
----
-
-## Testing Recommendations
-
-### Physical Device Testing
-
-**Minimum testing:**
-- Test on at least one physical device
-- Verify basic functionality (ROM loading, save states, input)
-
-**Thorough testing:**
-- Test on multiple platform families
-- Verify platform-specific features work
-- Check performance on lower-end devices
-
-### Platform Priority
-
-**Tier 1 (Most common):**
-- miyoomini (Miyoo Mini is very popular)
-- rg35xxplus (Many Anbernic devices)
-- trimuismart (Trimui devices)
-
-**Tier 2:**
-- rg35xx (Original RG35XX)
-- my355 (Miyoo Flip/A30)
-- rgb30 (Unique screen)
-
-**Tier 3:**
-- my282, tg5040, m17, gkdpixel, magicmini, zero28
-
----
-
-## Platform Resources
-
-### Toolchains
-
-Each platform has a Docker toolchain image:
-```
-ghcr.io/shauninman/union-[platform]-toolchain:latest
-```
-
-### Documentation
-
-Platform-specific notes in:
-- `/workspace/[platform]/README.md` (if exists)
-- `/todo.txt` (platform quirks and issues)
-
-### Community
-
-- GitHub Issues for bug reports
-- GitHub Discussions for platform-specific questions
-
----
-
-## Adding New Platforms
-
-See [Adding Platform Support](adding-platform.md) for complete guide.
-
-**Quick checklist:**
-1. Create `/workspace/[platform]/` directory structure
-2. Implement platform.c/platform.h
-3. Implement libmsettings
-4. Create keymon daemon
-5. Add to build system
-6. Test thoroughly
-
----
-
-## Deprecated Platforms
-
-### macos
-**Purpose:** Development and testing on macOS
-
-**Note:** Not intended for end users, only for development without cross-compilation.
-
-**Platform Code:** `/workspace/macos/`
-
-**Usage:**
-```bash
-cd workspace
-export UNION_PLATFORM=macos
-make
-./all/minui/minui
-```
-
----
-
-## Platform Support Status
-
-All platforms are currently marked as **deprecated** in the codebase, indicating:
-- Active development has slowed
-- Platforms remain functional
-- Bug fixes may be limited
-- Community contributions welcome
-
-Despite deprecated status, MinUI remains the most popular custom firmware for many of these devices due to its speed, simplicity, and clean UI.
diff --git a/docs/project-structure.md b/docs/project-structure.md
deleted file mode 100644
index 22a2c5ba..00000000
--- a/docs/project-structure.md
+++ /dev/null
@@ -1,508 +0,0 @@
-# MinUI Project Structure
-
-This document describes the directory layout and organization of the MinUI repository.
-
-## Repository Root
-
-```
-/
-├── workspace/ # Core source code
-├── skeleton/ # SD card template structure
-├── github/ # Documentation assets
-├── releases/ # Built release packages (generated)
-├── build/ # Build output (generated)
-├── docs/ # Technical documentation
-├── makefile # Master build orchestration
-├── makefile.toolchain # Docker toolchain setup
-├── README.md # User-facing documentation
-├── PAKS.md # Pak creation guide
-├── todo.txt # Development notes
-├── commits.sh # Release history script
-└── .gitignore # Git configuration
-```
-
-## Workspace Directory
-
-The workspace contains all source code and is organized by platform and component.
-
-### `/workspace/` Structure
-
-```
-workspace/
-├── all/ # Platform-independent code
-│ ├── minui/ # Main launcher
-│ ├── minarch/ # Libretro frontend
-│ ├── common/ # Shared libraries
-│ ├── cores/ # Core build system
-│ ├── clock/ # Clock utility
-│ ├── minput/ # Input testing tool
-│ ├── say/ # Notification utility
-│ ├── syncsettings/ # Settings sync daemon
-│ └── readmes/ # README utilities
-│
-├── miyoomini/ # Miyoo Mini platform
-├── my282/ # Miyoo Mini Flip
-├── my355/ # Miyoo Flip/A30
-├── trimuismart/ # Trimui Smart family
-├── rg35xx/ # RG35XX original
-├── rg35xxplus/ # RG35XX Plus family
-├── rgb30/ # RGB30
-├── tg5040/ # Trimui Smart Pro
-├── m17/ # M17
-├── gkdpixel/ # GKD Pixel/Mini
-├── magicmini/ # MagicX XU Mini M
-├── zero28/ # MagicX Mini Zero 28
-├── macos/ # macOS testing
-│
-└── makefile # Workspace build orchestrator
-```
-
-### Platform-Independent Code (`/workspace/all/`)
-
-#### MinUI Launcher (`/workspace/all/minui/`)
-```
-minui/
-├── minui.c # Main launcher (1,704 lines)
-├── makefile # Build configuration
-└── credits.txt # Attribution
-```
-
-**Purpose**: Main UI for ROM browsing and launching
-
-**Key Files**:
-- `minui.c` - Entry point, menu system, ROM scanning, pak launching
-
-#### Minarch Frontend (`/workspace/all/minarch/`)
-```
-minarch/
-├── minarch.c # Libretro frontend (4,830 lines)
-├── makefile # Build configuration
-└── credits.txt # Attribution
-```
-
-**Purpose**: Runs libretro emulator cores
-
-**Key Files**:
-- `minarch.c` - Core loading, in-game menu, save states, video/audio
-
-#### Common Libraries (`/workspace/all/common/`)
-```
-common/
-├── api.c # Common API implementation (1,722 lines)
-├── api.h # API header (347 lines)
-├── scaler.c # Video scaling (110 KB)
-├── scaler.h # Scaler header (22 KB)
-├── utils.c # Utility functions (5 KB)
-├── utils.h # Utility header (821 bytes)
-├── defines.h # Global constants (5 KB)
-└── sdl.h # SDL version abstraction (1 KB)
-```
-
-**Purpose**: Shared functionality across all applications
-
-**Key APIs**:
-- **GFX_*** - Graphics rendering, asset loading, text display
-- **SND_*** - Audio initialization and buffering
-- **PAD_*** - Input handling with auto-repeat
-- **PWR_*** - Power management, sleep, battery
-- **LID_*** - Lid state detection
-
-#### Cores Build System (`/workspace/all/cores/`)
-```
-cores/
-├── makefile # Template-based core builder
-├── shared/ # Shared core patches
-│ └── generic/ # Universal patches
-└── README.txt # Core building documentation
-```
-
-**Purpose**: Downloads, patches, and builds libretro cores
-
-#### Utility Applications
-
-**Clock** (`/workspace/all/clock/`):
-```
-clock/
-├── clock.c # Simple clock display
-└── makefile
-```
-
-**Minput** (`/workspace/all/minput/`):
-```
-minput/
-├── minput.c # Input testing/configuration
-└── makefile
-```
-
-**Say** (`/workspace/all/say/`):
-```
-say/
-├── say.c # Notification display
-└── makefile
-```
-
-**Syncsettings** (`/workspace/all/syncsettings/`):
-```
-syncsettings/
-├── syncsettings.c # Settings restoration daemon
-└── makefile
-```
-
-**Readmes** (`/workspace/all/readmes/`):
-```
-readmes/
-└── formatreadmes.c # README formatting utility
-```
-
-### Platform-Specific Code
-
-Each platform directory follows a similar structure:
-
-```
-[platform]/
-├── platform/ # Platform abstraction layer
-│ ├── platform.c # Platform implementation
-│ └── platform.h # Platform constants
-│
-├── libmsettings/ # Settings library
-│ ├── msettings.c # Settings implementation
-│ └── msettings.h # Settings API
-│
-├── keymon/ # Input monitor daemon
-│ ├── keymon.c # Key monitoring
-│ └── makefile
-│
-├── cores/ # Platform cores configuration
-│ ├── makefile # Which cores to build
-│ ├── patches/ # Platform-specific patches
-│ ├── output/ # Built .so files (generated)
-│ └── src/ # Downloaded sources (generated)
-│
-└── [platform-specific utilities]
-```
-
-#### Platform.h/platform.c
-
-**platform.h** defines:
-- Button mappings (SDL keys, raw codes, joystick IDs)
-- Screen dimensions
-- System paths
-- Platform capabilities
-- Hardware-specific constants
-
-**platform.c** implements:
-- `PLAT_initInput()` - Input device setup
-- `PLAT_quitInput()` - Input cleanup
-- `PLAT_pollInput()` - Read button states
-- `PLAT_initVideo()` - Display initialization
-- `PLAT_quitVideo()` - Display cleanup
-- `PLAT_clearVideo()` - Screen clearing
-- `PLAT_clearAll()` - Full screen clear
-- `PLAT_setVsync()` - V-sync control
-- `PLAT_vsync()` - Wait for v-sync
-- `PLAT_flip()` - Present frame
-- `PLAT_scale()` - Software scaling
-- `PLAT_getBatteryStatus()` - Battery level
-- `PLAT_enableBacklight()` - Display on/off
-- `PLAT_powerOff()` - System shutdown
-- `PLAT_setCPUSpeed()` - CPU frequency
-
-#### libmsettings
-
-**msettings.h** API:
-- `InitSettings()` - Load settings
-- `QuitSettings()` - Save settings
-- `GetBrightness()` / `SetBrightness()` - Backlight control
-- `GetVolume()` / `SetVolume()` - Audio control
-- `GetLastPlay()` / `SetLastPlay()` - Resume tracking
-
-**msettings.c** implementation:
-- Platform-specific hardware access
-- `/sys/class/backlight/` for brightness
-- ALSA or platform mixer for volume
-- Settings file persistence
-
-#### keymon
-
-**keymon.c**:
-- Opens raw input devices (`/dev/input/eventX`)
-- Monitors for button presses
-- Handles volume up/down shortcuts
-- Handles brightness shortcuts
-- Implements sleep timer
-- Prevents system from interfering with MinUI
-
-#### Cores Configuration
-
-**cores/makefile**:
-- Lists which cores to build
-- Specifies core sources (git repos)
-- Defines patches to apply
-- Sets build flags
-
-Example platforms build these stock cores:
-- fceumm (NES)
-- gambatte (GB/GBC)
-- gpsp (GBA)
-- picodrive (Genesis/SMS/GG/SegaCD)
-- snes9x2005_plus (SNES)
-- pcsx_rearmed (PS1)
-
-#### Platform-Specific Utilities
-
-**Miyoo Mini** (`/workspace/miyoomini/`):
-- `show/` - Splash screen display
-- `overclock/` - CPU frequency control
-- `batmon/` - Battery monitor
-- `lumon/` - Luminance control
-- `blank/` - Screen blanking
-
-**MY282** (`/workspace/my282/`):
-- `libmstick/` - Analog stick library
-- `show/` - Splash screen
-
-**RG35XX Plus** (`/workspace/rg35xxplus/`):
-- `init/` - System initialization
-- `show/` - Splash screen
-
-**Zero28** (`/workspace/zero28/`):
-- `bl/` - Backlight control
-- `show/` - Splash screen
-
-## Skeleton Directory
-
-The skeleton defines the SD card structure that gets populated during the build.
-
-### `/skeleton/` Structure
-
-```
-skeleton/
-├── SYSTEM/ # System files
-│ ├── res/ # Shared resources
-│ └── [platform]/ # Platform binaries (populated at build)
-│
-├── BASE/ # User-facing structure
-│ ├── Roms/ # ROM directories
-│ ├── Saves/ # Save files
-│ ├── Bios/ # BIOS files
-│ ├── README.txt # User guide
-│ ├── miyoo/ # Miyoo boot files
-│ ├── trimui/ # Trimui boot files
-│ └── magicx/ # MagicX boot files
-│
-├── EXTRAS/ # Optional content
-│ ├── Emus/ # Extra emulator paks
-│ ├── Tools/ # Utility paks
-│ ├── Roms/ # Extra console folders
-│ ├── Saves/ # Extra saves folders
-│ ├── Bios/ # Extra BIOS folders
-│ └── README.txt # Extras guide
-│
-└── BOOT/ # Bootstrap files
- ├── common/ # Shared updater
- ├── miyoo/ # Miyoo family bootstrap
- ├── trimui/ # Trimui family bootstrap
- └── magicx/ # MagicX family bootstrap
-```
-
-### System Resources (`/skeleton/SYSTEM/res/`)
-
-```
-SYSTEM/res/
-├── BPreplayBold-unhinted.otf # Main UI font
-├── assets@1x.png # UI sprites (240p)
-├── assets@2x.png # UI sprites (480p)
-├── assets@3x.png # UI sprites (720p)
-├── assets@4x.png # UI sprites (960p+)
-├── grid-1x.png # CRT grid overlay
-├── grid-2x.png
-├── grid-3x.png
-├── grid-4x.png
-├── line-1x.png # Scanline overlay
-├── line-2x.png
-├── line-3x.png
-├── line-4x.png
-└── charging-*.png # Charging screen graphics
-```
-
-### Platform Binaries (`/skeleton/SYSTEM/[platform]/`)
-
-Populated during build from workspace:
-
-```
-SYSTEM/[platform]/
-├── bin/
-│ ├── minui.elf # Main launcher
-│ ├── minarch.elf # Libretro frontend
-│ ├── keymon.elf # Input monitor
-│ ├── syncsettings.elf # Settings sync
-│ ├── say.elf # Notifications
-│ ├── clock.elf # Clock utility
-│ ├── install.sh # Update script
-│ └── [platform utilities] # Platform-specific tools
-│
-├── lib/
-│ └── libmsettings.so # Settings library
-│
-├── cores/
-│ ├── fceumm_libretro.so # NES core
-│ ├── gambatte_libretro.so # GB/GBC core
-│ ├── gpsp_libretro.so # GBA core
-│ ├── picodrive_libretro.so # Genesis/SMS core
-│ ├── snes9x2005_plus_libretro.so # SNES core
-│ └── pcsx_rearmed_libretro.so # PS1 core
-│
-└── paks/
- ├── MinUI.pak/ # System updater
- └── Emus/ # Emulator paks
- ├── GB.pak/
- ├── GBC.pak/
- ├── GBA.pak/
- ├── FC.pak/
- ├── SFC.pak/
- ├── MD.pak/
- ├── PS.pak/
- └── PAK.pak/
-```
-
-### ROM Directories (`/skeleton/BASE/Roms/`)
-
-```
-Roms/
-├── Game Boy (GB)/
-├── Game Boy Color (GBC)/
-├── Game Boy Advance (GBA)/
-├── Nintendo Entertainment System (FC)/
-├── Super Nintendo Entertainment System (SFC)/
-├── Sega Genesis (MD)/
-├── Sony PlayStation (PS)/
-└── Native Games (PAK)/
-```
-
-Directory names follow pattern: `Console Name (TAG)`
-- Display name shown in UI
-- Tag used to identify emulator pak
-
-### Extras Structure (`/skeleton/EXTRAS/`)
-
-```
-EXTRAS/
-├── Emus/[platform]/
-│ ├── MGBA.pak/ # Better GBA emulation
-│ ├── SGB.pak/ # Super Game Boy
-│ ├── PKM.pak/ # Pokemon Mini
-│ ├── NGP.pak/ # Neo Geo Pocket
-│ ├── NGPC.pak/ # Neo Geo Pocket Color
-│ ├── PCE.pak/ # TurboGrafx-16
-│ ├── P8.pak/ # PICO-8
-│ ├── SUPA.pak/ # Better SNES emulation
-│ ├── VB.pak/ # Virtual Boy
-│ ├── GG.pak/ # Game Gear
-│ └── SMS.pak/ # Sega Master System
-│
-└── Tools/[platform]/
- ├── Clock.pak/ # Clock display
- ├── Input.pak/ # Input tester
- ├── Files.pak/ # File browser
- ├── ADBD.pak/ # ADB daemon (Miyoo Mini)
- ├── IP.pak/ # IP display (Miyoo Mini)
- ├── Bootlogo.pak/ # Boot logo changer
- └── [platform-specific]/
-```
-
-## Build Output
-
-### `/build/` Directory (Generated)
-
-Created during build process, mirrors skeleton with populated binaries:
-
-```
-build/
-├── SYSTEM/
-│ ├── res/ # Copied from skeleton
-│ └── [platform]/ # Populated with compiled files
-├── BASE/ # Copied from skeleton
-├── EXTRAS/ # Copied from skeleton
-└── BOOT/ # Copied from skeleton
-```
-
-### `/releases/` Directory (Generated)
-
-Contains final release packages:
-
-```
-releases/
-├── MinUI-YYYYMMDD-N-base.zip # Base release
-├── MinUI-YYYYMMDD-N-extras.zip # Extras package
-├── MinUI-YYYYMMDD-N.zip # Update package
-├── version.txt # Version info
-└── commits.txt # Commit history
-```
-
-## Documentation Directory
-
-### `/docs/` Structure
-
-```
-docs/
-├── README.md # Documentation index
-├── architecture.md # System design
-├── project-structure.md # This file
-├── components.md # Component details
-├── build-system.md # Build process
-├── platform-abstraction.md # Platform HAL guide
-├── pak-system.md # Pak architecture
-├── development-guide.md # Developer guide
-├── adding-platform.md # Platform porting
-├── api-reference.md # API documentation
-├── platforms.md # Platform details
-├── file-formats.md # Config file specs
-└── troubleshooting.md # Common issues
-```
-
-## Key File Locations Quick Reference
-
-| Purpose | Location |
-|---------|----------|
-| Main launcher | `/workspace/all/minui/minui.c` |
-| Libretro frontend | `/workspace/all/minarch/minarch.c` |
-| Common API | `/workspace/all/common/api.c` |
-| Video scaler | `/workspace/all/common/scaler.c` |
-| Platform HAL | `/workspace/[platform]/platform/platform.c` |
-| Settings library | `/workspace/[platform]/libmsettings/msettings.c` |
-| Input monitor | `/workspace/[platform]/keymon/keymon.c` |
-| Master makefile | `/makefile` |
-| Toolchain setup | `/makefile.toolchain` |
-| User guide | `/skeleton/BASE/README.txt` |
-| Pak guide | `/PAKS.md` |
-| UI font | `/skeleton/SYSTEM/res/BPreplayBold-unhinted.otf` |
-| UI graphics | `/skeleton/SYSTEM/res/assets@*.png` |
-
-## Build Artifacts
-
-Files and directories created during build (in `.gitignore`):
-
-- `/build/` - Build output directory
-- `/releases/` - Release packages
-- `/workspace/*/cores/src/` - Downloaded core sources
-- `/workspace/*/cores/output/` - Compiled cores
-- `*.elf` - Executable files
-- `*.so` - Shared libraries
-- `*.o` - Object files
-- `.tmp_update/` - Update system temporary files
-
-## Version Control
-
-The repository tracks:
-- All source code
-- Skeleton structure (with `.keep` files for empty dirs)
-- Documentation
-- Build scripts
-- Resource files (fonts, graphics)
-
-The repository ignores:
-- Build artifacts
-- Compiled binaries
-- Downloaded dependencies
-- Release packages
-- Platform-specific temporary files
diff --git a/docs/shellcheck-setup.md b/docs/shellcheck-setup.md
deleted file mode 100644
index ff8c2eff..00000000
--- a/docs/shellcheck-setup.md
+++ /dev/null
@@ -1,149 +0,0 @@
-# ShellCheck Setup
-
-MinUI uses `shellcheck` for shell script linting.
-
-## Running ShellCheck
-
-```bash
-make -f Makefile.qa lint-shell
-```
-
-Checks 403 shell scripts for common issues.
-
-## What Gets Checked
-
-- `commits.sh` - Release commit history script
-- `skeleton/**/*.sh` - Boot scripts, pak launchers
-- `workspace/**/*.sh` - Install scripts, platform utilities
-
-**Excluded:**
-- `workspace/*/cores/**` - Downloaded libretro cores (not our code)
-- `toolchains/**` - External toolchain scripts
-- `workspace/m17/boot/output/em_ui.sh` - Contains embedded binary data
-
-## Configuration
-
-See `.shellcheckrc` for suppression rules:
-
-```bash
-# Start forgiving - only serious issues
-disable=SC2086,SC2034,SC2164,SC2046,SC2006,SC2005,SC2003,SC1090,SC2295
-severity=warning
-```
-
-### Suppressed Warnings (For Now)
-
-Common issues suppressed to reduce noise:
-
-- **SC2086** - Unquoted variables (too common, fix gradually)
-- **SC2164** - Missing `cd ... || exit` (scripts assume cd works)
-- **SC2006** - Backticks instead of `$()` (style, not critical)
-- **SC2181** - Checking `$?` indirectly (style preference)
-- **SC3010/SC3014** - Bash-isms in POSIX sh (many scripts use these)
-
-## Current Findings
-
-**202 scripts with issues** (out of 403 checked)
-
-Common real issues found:
-- Missing shebang lines
-- POSIX incompatibilities (`[[`, `==`)
-- Unquoted `rm -rf` with variables (dangerous!)
-
-## Example Issues
-
-### Issue 1: rm -rf safety
-```bash
-# Dangerous - could delete / if var is empty
-rm -rf "$SDCARD_PATH/$MIYOO_DIR"
-
-# Better
-rm -rf "${SDCARD_PATH:?}/${MIYOO_DIR:?}"
-```
-
-### Issue 2: POSIX compatibility
-```bash
-# Bash-specific (won't work in /bin/sh)
-if [[ "$A" == "$B" ]]; then
-
-# POSIX-compatible
-if [ "$A" = "$B" ]; then
-```
-
-### Issue 3: Missing shebang
-```bash
-# Missing at top of file
-#!/bin/sh
-```
-
-## Usage Recommendations
-
-### For New Scripts
-```bash
-# Check as you write
-shellcheck mynewscript.sh
-```
-
-### For Modified Scripts
-```bash
-# Before committing
-shellcheck skeleton/SYSTEM/miyoomini/paks/MinUI.pak/launch.sh
-```
-
-## Gradually Improving
-
-**Current approach:** Forgiving rules, find serious issues
-
-**Future phases:**
-1. Enable more rules as scripts are fixed
-2. Make shellcheck pass with no suppressions
-3. Add to CI (when ready)
-
-## Integration with Editors
-
-### VS Code
-Install "ShellCheck" extension - automatic linting in editor
-
-### Vim
-```vim
-let g:syntastic_sh_shellcheck_args = "-x"
-```
-
-### Emacs
-```elisp
-(add-hook 'sh-mode-hook 'flycheck-mode)
-```
-
-## Common Fixes
-
-### Add Shebang
-```bash
-#!/bin/sh
-# or
-#!/bin/bash
-```
-
-### Quote Variables
-```bash
-# Before
-cd $SOME_PATH
-
-# After
-cd "$SOME_PATH"
-```
-
-### Use POSIX Syntax
-```bash
-# Before (bash-only)
-if [[ "$VAR" == "value" ]]; then
-
-# After (POSIX)
-if [ "$VAR" = "value" ]; then
-```
-
-## Next Steps
-
-1. ✅ **ShellCheck available** - You are here
-2. ⏭️ **Fix critical issues** - `rm -rf` with unquoted vars
-3. ⏭️ **Add shebangs** - Many scripts missing them
-4. ⏭️ **Improve over time** - Fix as scripts are modified
diff --git a/docs/static-analysis-setup.md b/docs/static-analysis-setup.md
deleted file mode 100644
index 3f7493a7..00000000
--- a/docs/static-analysis-setup.md
+++ /dev/null
@@ -1,142 +0,0 @@
-# Static Analysis Setup
-
-MinUI uses `cppcheck` for static code analysis to catch bugs early.
-
-## Installation
-
-### macOS
-```bash
-brew install cppcheck
-```
-
-### Linux
-```bash
-sudo apt-get install cppcheck
-```
-
-## Usage
-
-### Quick Check (Recommended)
-```bash
-make -f Makefile.qa lint
-```
-
-Checks `workspace/all/` (common code) for serious issues:
-- NULL pointer dereferences
-- Memory leaks
-- Buffer overflows
-- Uninitialized variables
-
-### Full Check (Verbose)
-```bash
-make -f Makefile.qa lint-full
-```
-
-Checks entire workspace including platform-specific code.
-
-### Generate Report
-```bash
-make -f Makefile.qa report
-```
-
-Creates `cppcheck-report.txt` with detailed findings.
-
-## Current Findings
-
-### Real Issue Found ✅
-
-**Undefined Behavior in api.c:355**
-```c
-uint32_t of = ((sum < c1) | (ret < sum)) << 31;
-```
-
-**Problem:** Shifting signed 32-bit value by 31 bits is undefined behavior in C.
-
-**Impact:** May cause incorrect calculations on some platforms.
-
-**Fix:** Use unsigned types:
-```c
-uint32_t of = ((uint32_t)((sum < c1) | (ret < sum))) << 31;
-```
-
-**Location:** workspace/all/common/api.c:355
-
-### Suppressed Issues
-
-The following are suppressed as they're not actual problems:
-
-1. **unknownMacro warnings** - `PLATFORM`, `PAKS_PATH`, etc. are defined during compilation
-2. **libretro-common warnings** - Third-party code we don't maintain
-3. **normalCheckLevelMaxBranches** - Informational only, not errors
-
-## Configuration
-
-### `.cppcheck-suppressions`
-
-Controls what gets ignored:
-
-```
-# Third-party code
-*:*/libretro-common/*
-
-# Platform macros (defined at compile time)
-unknownMacro:*PLATFORM*
-
-# Noise reduction
-normalCheckLevelMaxBranches
-unusedFunction
-```
-
-### `Makefile.qa`
-
-Defines check targets and flags:
-
-```makefile
-CPPCHECK_FLAGS = --enable=warning \
- --suppressions-list=.cppcheck-suppressions \
- --error-exitcode=0 \
- --quiet
-```
-
-## Adding to Workflow
-
-### Before Committing
-```bash
-make -f Makefile.qa lint
-```
-
-### Before PR
-```bash
-make -f Makefile.qa lint-full
-```
-
-## Tightening Rules Over Time
-
-Currently using **forgiving rules** to avoid overwhelming output:
-- Only `--enable=warning` (not style, performance, portability)
-- Suppressions for third-party code
-- No CI enforcement yet
-
-### Future Improvements
-
-As code quality improves, gradually enable:
-
-1. **Phase 2:** Add `--enable=style` for coding style issues
-2. **Phase 3:** Add `--enable=performance` for optimization hints
-3. **Phase 4:** Add `--enable=portability` for cross-platform issues
-4. **Phase 5:** Make lint checks mandatory in CI (fail on errors)
-
-## Next Steps
-
-1. ✅ **Static analysis set up** - You are here
-2. ⏭️ **Fix the real issue** - Fix api.c:355 undefined behavior
-3. ⏭️ **Set up tests** - Add Unity framework
-4. ⏭️ **Write first tests** - Test utils.c functions
-
-## Known Limitations
-
-- Doesn't understand platform-specific macros (PLATFORM, PAKS_PATH, etc.)
-- Can't check platform-specific code without platform definitions
-- Third-party code (libretro-common) generates many warnings
-
-These are acceptable trade-offs for a lightweight setup.
diff --git a/docs/testing-checklist.md b/docs/testing-checklist.md
deleted file mode 100644
index ee652a15..00000000
--- a/docs/testing-checklist.md
+++ /dev/null
@@ -1,257 +0,0 @@
-# MinUI Testing Checklist
-
-This document provides a prioritized checklist of files to test, ordered by importance, complexity, and dependencies.
-
-## Testing Philosophy
-
-1. **Test common utilities first** - These are used everywhere and bugs cascade
-2. **Test pure functions** - Functions with no side effects are easiest to test
-3. **Test platform-independent code** - Avoid testing platform-specific implementations
-4. **Mock external dependencies** - Use stubs for SDL, hardware, etc.
-5. **Skip third-party code** - Don't test libretro-common (maintained externally)
-
-## Priority Order
-
-### ✅ Phase 1: Foundation (COMPLETED)
-**Status:** All tests passing
-
-| File | Lines | Priority | Status | Tests | Notes |
-|------|-------|----------|--------|-------|-------|
-| `workspace/all/common/utils.c` | 219 | **CRITICAL** | ✅ DONE | 52 | String manipulation, file I/O, timing - used everywhere |
-
-**Key achievements:**
-- Found and fixed critical memory overlap bug in `getEmuName()`
-- Fixed sign comparison warning in `exactMatch()`
-- Comprehensive test coverage of all public functions
-- Established test infrastructure with Unity framework
-
----
-
-### 🎯 Phase 2: Core Utilities (NEXT)
-**Rationale:** Test remaining utility code before testing code that depends on it
-
-| File | Lines | Priority | Status | Tests | Testability |
-|------|-------|----------|--------|-------|-------------|
-| `workspace/all/common/api.c` | 1,722 | **HIGH** | ⏳ TODO | 0 | Medium - needs SDL/TTF mocks |
-| `workspace/all/clock/clock.c` | 322 | **MEDIUM** | ⏳ TODO | 0 | High - mostly pure logic |
-| `workspace/all/say/say.c` | 52 | **LOW** | ⏳ TODO | 0 | High - very simple |
-| `workspace/all/minput/minput.c` | 274 | **MEDIUM** | ⏳ TODO | 0 | Medium - input handling |
-| `workspace/all/syncsettings/syncsettings.c` | 12 | **LOW** | ⏳ TODO | 0 | High - trivial |
-
-**Recommended order:**
-1. `syncsettings.c` - Simplest, good warm-up
-2. `say.c` - Small and simple
-3. `clock.c` - Pure logic, no external dependencies
-4. `minput.c` - Input handling with some complexity
-5. `api.c` - Complex, many SDL dependencies (tackle in parts)
-
----
-
-### 🔧 Phase 3: Application Layer
-**Rationale:** Test after all utilities are tested and stable
-
-| File | Lines | Priority | Status | Tests | Testability |
-|------|-------|----------|--------|-------|-------------|
-| `workspace/all/minui/minui.c` | 1,704 | **HIGH** | ⏳ TODO | 0 | Low - heavy SDL/file dependencies |
-| `workspace/all/minarch/minarch.c` | 4,830 | **HIGH** | ⏳ TODO | 0 | Very Low - libretro integration |
-
-**Notes:**
-- These are more suitable for **integration tests** than unit tests
-- Consider testing specific helper functions in isolation
-- Mock libretro core for minarch testing
-- Mock SDL surfaces and TTF for minui testing
-
----
-
-### 🎨 Phase 4: Graphics (OPTIONAL)
-**Rationale:** Low-level pixel manipulation - consider visual/integration testing instead
-
-| File | Lines | Priority | Status | Tests | Testability |
-|------|-------|----------|--------|-------|-------------|
-| `workspace/all/common/scaler.c` | 3,072 | **MEDIUM** | ⏳ TODO | 0 | Medium - pure pixel math |
-
-**Notes:**
-- Contains NEON assembly optimizations - hard to unit test
-- Could test C fallback implementations
-- Better suited for visual regression tests
-- Low priority unless bugs are found
-
----
-
-## Detailed Test Plans
-
-### api.c - Core API Functions
-**Lines:** 1,722 | **Priority:** HIGH | **Complexity:** HIGH
-
-#### Testable Functions (grouped by subsystem)
-
-**Logging (Simple - Test First)**
-- `LOG_note()` - Basic logging with different levels
-
-**Text Utilities (Medium)**
-- `GFX_truncateText()` - Text truncation with max width
-- `GFX_wrapText()` - Text wrapping logic
-- `GFX_getButtonWidth()` - Calculate button width
-
-**Rendering Helpers (Complex - Mock SDL)**
-- `GFX_blitAsset()` - Blit assets to surface
-- `GFX_blitPill()` - Render pill-shaped UI elements
-- `GFX_blitRect()` - Render rectangles
-- `GFX_blitBattery()` - Render battery indicator
-- `GFX_blitButton()` - Render button with hint
-- `GFX_blitMessage()` - Render text message
-
-**Math/Utility (Simple)**
-- `average16()` / `average32()` - Color averaging (inline)
-- `gcd()` - Greatest common divisor (inline)
-
-**Strategy:**
-1. Start with logging and math utilities (no SDL needed)
-2. Mock TTF_Font for text utilities
-3. Mock SDL_Surface for rendering functions
-4. Test each subsystem independently
-
----
-
-### clock.c - Clock Application
-**Lines:** 322 | **Priority:** MEDIUM | **Complexity:** LOW
-
-**Expected Functions:**
-- Time/date display formatting
-- Time zone handling
-- Clock rendering logic
-
-**Strategy:**
-- Mock SDL for rendering
-- Mock time functions for deterministic testing
-- Test time formatting edge cases (midnight, DST changes)
-
----
-
-### say.c - Simple Text-to-Speech Wrapper
-**Lines:** 52 | **Priority:** LOW | **Complexity:** LOW
-
-**Strategy:**
-- Likely just wraps external TTS command
-- Test command construction
-- Mock system() calls
-
----
-
-### minput.c - Input Configuration
-**Lines:** 274 | **Priority:** MEDIUM | **Complexity:** MEDIUM
-
-**Expected Functions:**
-- Input mapping configuration
-- Button combination handling
-- Controller profile management
-
-**Strategy:**
-- Test input mapping logic
-- Test button combination detection
-- Mock SDL input events
-
----
-
-### syncsettings.c - Settings Synchronization
-**Lines:** 12 | **Priority:** LOW | **Complexity:** TRIVIAL
-
-**Strategy:**
-- With only 12 lines, likely a simple wrapper
-- Test basic functionality
-- Quick win for test coverage
-
----
-
-## Test Infrastructure Needs
-
-### Current Infrastructure ✅
-- Unity test framework
-- Platform stubs (`tests/support/platform.h`)
-- Mirror directory structure
-- Makefile.qa integration
-
-### Needed Mocks
-- [ ] SDL_Surface mock
-- [ ] TTF_Font mock
-- [ ] SDL_Rect utilities
-- [ ] File I/O mocking (for deterministic tests)
-- [ ] Time mocking (for clock tests)
-
-### Future Enhancements
-- [ ] Code coverage reporting (gcov/lcov)
-- [ ] Memory leak detection (valgrind)
-- [ ] Continuous integration tests
-- [ ] Integration test framework
-
----
-
-## Testing Metrics
-
-### Current Coverage
-```
-Total testable files: 8
-Files tested: 1 (12.5%)
-Total tests: 52
-Lines tested: ~219 / ~8,200 (2.7%)
-```
-
-### Target Coverage
-```
-Phase 1 (Foundation): 100% ✅
-Phase 2 (Core Utilities): 80% target
-Phase 3 (Application): 60% target (integration tests)
-Phase 4 (Graphics): 40% target (optional)
-```
-
----
-
-## Recommended Next Steps
-
-1. **Immediate (Week 1-2):**
- - Test `syncsettings.c` (12 lines - quick win)
- - Test `say.c` (52 lines - simple)
- - Test `clock.c` (322 lines - no complex dependencies)
-
-2. **Short-term (Week 3-4):**
- - Create SDL/TTF mocks
- - Test logging functions in `api.c`
- - Test text utilities in `api.c`
- - Test `minput.c`
-
-3. **Medium-term (Month 2):**
- - Test remaining `api.c` functions (with mocks)
- - Begin integration tests for `minui.c`
- - Begin integration tests for `minarch.c`
-
-4. **Long-term (Month 3+):**
- - Add code coverage reporting
- - Set up CI/CD pipeline
- - Consider `scaler.c` testing or visual regression tests
- - Performance testing for critical paths
-
----
-
-## Notes
-
-- **Skip libretro-common**: This is third-party code maintained externally
-- **Focus on business logic**: Test algorithms and logic, not just I/O
-- **Mock external dependencies**: Don't test SDL, test your use of SDL
-- **Integration tests matter**: Some code is better tested end-to-end
-- **Bug-driven testing**: When bugs are found, add regression tests
-
----
-
-## Questions to Answer
-
-Before testing each file, answer:
-
-1. **What does this file do?** (Read first 50 lines and skim)
-2. **What are the public functions?** (Check header file)
-3. **What are the dependencies?** (External libs, other modules)
-4. **Can we test in isolation?** (Or do we need mocks/stubs)
-5. **What are the edge cases?** (NULL, empty, overflow, underflow)
-6. **What are the critical paths?** (Most frequently called)
-7. **What could break?** (Memory, bounds, race conditions)
-
-This checklist will evolve as we learn more about each file!
diff --git a/docs/testing-setup.md b/docs/testing-setup.md
deleted file mode 100644
index b3348e62..00000000
--- a/docs/testing-setup.md
+++ /dev/null
@@ -1,160 +0,0 @@
-# Testing Setup
-
-MinUI uses the Unity test framework for unit testing.
-
-## Running Tests
-
-```bash
-make -f Makefile.qa test
-```
-
-Output:
-```
-Building utils tests...
-✓ Tests compiled
-Running tests...
-...
-9 Tests 0 Failures 0 Ignored
-OK
-✓ All tests passed
-```
-
-## What's Tested
-
-### String Utilities (9 tests)
-
-Tests for `prefixMatch()`, `suffixMatch()`, and `exactMatch()` functions:
-
-- Exact string matching
-- Prefix detection (e.g., "hello" matches "hello world")
-- Suffix detection (e.g., ".gb" matches "game.gb")
-- Edge cases (empty strings, no matches)
-- Case sensitivity
-
-## Project Structure
-
-```
-tests/
-├── unity/ # Unity test framework
-│ ├── unity.c
-│ ├── unity.h
-│ └── unity_internals.h
-└── utils/ # Utils tests
- └── test_utils_simple.c # String function tests
-```
-
-## Adding New Tests
-
-### 1. Create Test File
-
-```bash
-touch tests/mynewtest/test_mynewtest.c
-```
-
-### 2. Write Tests
-
-```c
-#include "../unity/unity.h"
-
-void setUp(void) {}
-void tearDown(void) {}
-
-void test_something(void) {
- TEST_ASSERT_EQUAL(expected, actual);
-}
-
-int main(void) {
- UNITY_BEGIN();
- RUN_TEST(test_something);
- return UNITY_END();
-}
-```
-
-### 3. Add to Makefile.qa
-
-```makefile
-tests/mynewtest_test: tests/mynewtest/test_mynewtest.c tests/unity/unity.c
- @$(CC) -o $@ $^ -I tests -std=c99
-
-test: tests/mynewtest_test
- @./tests/mynewtest_test
-```
-
-## Unity Assertions
-
-Common assertions:
-
-```c
-// Basic comparisons
-TEST_ASSERT_TRUE(condition)
-TEST_ASSERT_FALSE(condition)
-TEST_ASSERT_EQUAL(expected, actual)
-TEST_ASSERT_NOT_EQUAL(expected, actual)
-
-// Strings
-TEST_ASSERT_EQUAL_STRING("expected", actual)
-TEST_ASSERT_EQUAL_STRING_LEN("exp", actual, 3)
-
-// Numbers
-TEST_ASSERT_EQUAL_INT(42, value)
-TEST_ASSERT_EQUAL_UINT(42, value)
-
-// Pointers
-TEST_ASSERT_NULL(pointer)
-TEST_ASSERT_NOT_NULL(pointer)
-
-// Arrays/Memory
-TEST_ASSERT_EQUAL_MEMORY(expected, actual, length)
-```
-
-## Current Limitations
-
-### Platform Dependencies
-
-Many MinUI functions depend on platform-specific code:
-- `api.c` requires SDL and platform headers
-- `minui.c` requires platform definitions
-- `minarch.c` requires libretro
-
-**Solution:** Test simple, pure functions first (like string utilities).
-
-### Future Tests
-
-As code is refactored, we'll add tests for:
-
-1. **Phase 1:** More util functions (file operations with mocks)
-2. **Phase 2:** Config parsing
-3. **Phase 3:** Save state logic
-4. **Phase 4:** Input mapping
-5. **Phase 5:** Integration tests
-
-## Benefits
-
-### Current
-- ✅ Proves testing works
-- ✅ Documents expected behavior
-- ✅ Catches regressions in string utilities
-- ✅ Template for future tests
-
-### Future
-- Enables safe refactoring
-- Catches bugs before hardware testing
-- Faster development iteration
-- Confidence in changes
-
-## No CI Yet
-
-Currently tests run locally only. Future: Add to GitHub Actions.
-
-## Clean Up
-
-```bash
-make -f Makefile.qa clean-tests
-```
-
-## Next Steps
-
-1. ✅ **Tests work** - You are here
-2. ⏭️ **Fix static analysis issue** - api.c:355 undefined behavior
-3. ⏭️ **Add more tests** - As code is refactored
-4. ⏭️ **Add CI** - When ready for automation
diff --git a/makefile b/makefile
index b1157bc2..763fb1eb 100644
--- a/makefile
+++ b/makefile
@@ -115,8 +115,8 @@ setup: name
# copy readmes to workspace so we can use Linux fmt instead of host's
mkdir -p ./workspace/readmes
- cp ./skeleton/BASE/README.txt ./workspace/readmes/BASE-in.txt
- cp ./skeleton/EXTRAS/README.txt ./workspace/readmes/EXTRAS-in.txt
+ cp ./skeleton/BASE/README.md ./workspace/readmes/BASE-in.txt
+ cp ./skeleton/EXTRAS/README.md ./workspace/readmes/EXTRAS-in.txt
done:
say "done" 2>/dev/null || true
diff --git a/skeleton/BASE/README.md b/skeleton/BASE/README.md
new file mode 100644
index 00000000..42898720
--- /dev/null
+++ b/skeleton/BASE/README.md
@@ -0,0 +1,356 @@
+# MinUI
+
+MinUI is a focused, custom launcher and libretro frontend for retro handheld devices. One SD card works across 20+ different handhelds from multiple manufacturers.
+
+**Source:** https://github.com/shauninman/minui
+
+---
+
+## What's Included
+
+This package contains:
+- MinUI launcher and emulator frontend
+- Base emulator cores (GB, GBC, GBA, NES, SNES, Genesis, PlayStation)
+- Installation files for supported devices
+- Sample ROM and BIOS folders
+
+---
+
+## Installation
+
+### Before You Start
+
+**SD Card Setup:**
+- Use a reputable brand SD card
+- Format as FAT32 (MBR partition table)
+- For dual-SD devices: Install MinUI on the **second card** (TF2)
+
+**Important:** Some devices require one-time NAND or TF1 modifications. Follow your device's specific instructions below.
+
+### Anbernic RG35XX Family
+
+**Devices:** RG35XX Plus, RG35XXH, RG35XX 2024, RG28XX, RG35XXSP, RG40XXH, RG40XXV, RG CubeXX, RG34XX, RG34XXSP
+
+**Setup:**
+1. Use stock Anbernic firmware on TF1 (quality is fine, no userdata stored there)
+2. Copy `rg35xxplus/dmenu.bin` to root of TF1's "NO NAME" partition (has "anbernic" folder)
+3. Copy `MinUI.zip` to root of TF2 card
+4. Insert both cards and boot
+
+**Note:** Different stock TF1 versions for different models (Plus/H/2024/SP vs 28XX/40XXH). Don't mix them.
+
+### Anbernic RG35XX (Original)
+
+**Setup:**
+1. Use stock Anbernic firmware on TF1
+2. Copy `rg35xx/dmenu.bin` to root of MISC partition on TF1
+3. Copy `MinUI.zip` to root of TF2 card
+4. Insert both cards and boot
+
+### Miyoo Mini / Miyoo Mini Plus
+
+**Standard Mini:**
+1. Copy `miyoo` folder to SD card root
+2. Copy `MinUI.zip` to SD card root
+3. Boot device
+
+**Mini Plus:**
+1. Copy `miyoo354` folder to SD card root
+2. Copy `MinUI.zip` to SD card root
+3. Boot device
+4. Optional: Enable RTC by creating empty file `/.userdata/miyoomini/enable-rtc`
+
+### Miyoo A30
+
+**Setup:**
+1. Copy `miyoo` folder to SD card root
+2. Copy `MinUI.zip` to SD card root
+3. Boot device
+
+### Miyoo Mini Flip
+
+**Setup:**
+1. Copy `miyoo285` folder to SD card root
+2. Copy `MinUI.zip` to SD card root
+3. Boot device
+
+### Miyoo Flip
+
+**Setup:**
+1. Copy `miyoo355` folder to SD card root
+2. Copy `MinUI.zip` to SD card root
+3. Insert SD card in **right slot** (beneath power button)
+4. Boot device
+
+### Trimui Smart / Smart Pro / Brick
+
+**Setup:**
+1. Copy `trimui` folder to SD card root
+2. Copy `MinUI.zip` to SD card root
+3. Boot device
+
+### Powkiddy RGB30
+
+**Setup:**
+1. Download and flash Moss to **left slot** (TF-OS): https://github.com/shauninman/Moss/releases
+2. Copy `MinUI.zip` to root of **right slot** (TFGAME) SD card
+3. Boot device
+
+### MagicX Mini Zero 28
+
+**Setup:**
+1. Download and flash Moss to **left slot** (TF1/INT): https://github.com/shauninman/Moss-zero28/releases
+2. Copy `magicx` folder to root of **right slot** (TF2/EXT) SD card
+3. Copy `MinUI.zip` to root of TF2/EXT SD card
+4. Boot device
+
+### MagicX XU Mini M (Deprecated)
+
+**Setup:**
+1. Download and flash modified stock to **left slot** (TF1/INT): https://github.com/shauninman/Moss-magicmini/releases
+2. Copy `MinUI.zip` to root of **right slot** (TF2/EXT) SD card
+3. Boot device
+
+### M17 (Deprecated)
+
+**Setup:**
+1. Copy `em_ui.sh` to SD card root
+2. Copy `MinUI.zip` to SD card root
+3. Boot device
+
+### GKD Pixel / GKD Mini (Deprecated)
+
+**Important:** Not cross-compatible with other MinUI devices. Firmware lives on SD card.
+
+**Setup:**
+1. Backup entire stock SD card (or copy everything to "stock" folder on ROMS partition)
+2. Copy `gkdpixel` folder to root of ROMS partition
+3. Copy `MinUI.zip` to root of ROMS partition
+4. Boot stock firmware
+5. Navigate to APP folder, launch "file manager"
+6. Navigate to `/media/roms/gkdpixel`
+7. Select `install.sh` and choose "Execute"
+
+---
+
+## Updating MinUI
+
+Copy `MinUI.zip` to the root of your SD card (the one with your Roms folder). Reboot. MinUI will detect the ZIP and auto-update.
+
+---
+
+## Using MinUI
+
+### Controls
+
+**For devices without dedicated MENU button:**
+- **RGB30**: Use L3 or R3 for MENU
+- **M17**: Use + or - for MENU
+
+**Volume and Brightness:**
+
+*Modern devices* (RGB30, Miyoo Mini Plus, RG35XX Plus, Trimui Smart Pro/Brick, GKD Pixel, Miyoo A30, Miyoo Flip, Mini Zero 28):
+- **Brightness**: MENU + VOLUME UP/DOWN
+
+*Classic devices* (Miyoo Mini, Trimui Smart, M17):
+- **Volume**: SELECT + L1/R1
+- **Brightness**: START + L1/R1
+
+**Sleep and Wake:**
+
+*Power button devices* (most modern handhelds):
+- **Sleep**: Press POWER
+- **Wake**: Press POWER
+
+*Physical switch devices* (Trimui Smart, M17):
+- **Sleep**: Press MENU twice
+- **Wake**: Press MENU
+- Then flip physical power switch when asleep
+
+**Other:**
+- **Mute** (Trimui Smart Pro/Brick): FN switch (also disables rumble)
+
+### Save States and Auto-Resume
+
+**Quicksave:** MinUI automatically saves when you power off in-game. Next time you boot, it resumes exactly where you left off.
+
+**Manual Save States:** Press MENU in-game to access 9 save state slots (0-8).
+
+**Resume Options:**
+- Press **A** on a game to auto-resume (loads quicksave from slot 9)
+- Press **X** on a game to resume from your last manual save state
+
+**How It Works:**
+- Quicksave created when powering off (manually or after 30 seconds of sleep)
+- On devices without POWER button: Press MENU twice to sleep before using power switch
+- Auto-resume happens on next boot
+
+---
+
+## ROMs and Organization
+
+### ROM Folders
+
+MinUI maps ROM folders to emulators using **tags in parentheses**:
+
+```
+Roms/
+├── Game Boy (GB)/
+├── Game Boy Advance (GBA)/
+├── Nintendo (FC)/
+└── Sony PlayStation (PS)/
+```
+
+The tag (e.g., "GB", "GBA") must match an emulator pak. You can rename folders but keep the tag:
+- "Nintendo Entertainment System (FC)" → "NES (FC)" ✓
+- "Famicom (FC)" ✓
+- "Nintendo" ✗ (missing tag)
+
+### Combining Folders
+
+Multiple folders with the same display name merge into one menu:
+
+```
+Roms/
+├── Game Boy Advance (GBA)/ # Uses stock core
+└── Game Boy Advance (MGBA)/ # Uses mgba core
+```
+
+Shows as single "Game Boy Advance" entry containing ROMs from both folders.
+
+### Multi-Disc Games
+
+**Single disc with multiple files:**
+```
+Harmful Park (English v1.0)/
+├── Harmful Park (English v1.0).bin
+└── Harmful Park (English v1.0).cue
+```
+
+MinUI launches the .cue file when you select the folder.
+
+**Multi-disc games:**
+```
+Policenauts (English v1.0)/
+├── Policenauts (English v1.0).m3u
+├── Policenauts (Japan) (Disc 1).bin
+├── Policenauts (Japan) (Disc 1).cue
+├── Policenauts (Japan) (Disc 2).bin
+└── Policenauts (Japan) (Disc 2).cue
+```
+
+Create an `.m3u` file listing each disc's .cue file:
+```
+Policenauts (Japan) (Disc 1).cue
+Policenauts (Japan) (Disc 2).cue
+```
+
+**In-game disc changing:** Press MENU → Continue shows current disc. Use left/right to switch discs.
+
+**Supported formats:** .bin/.cue, .iso, .chd, .pbp (official format, <2GB only)
+
+All discs share the same memory card and save states.
+
+### Custom Display Names
+
+Override ROM display names with a `map.txt` file in the ROM folder:
+
+```
+neogeo.zip .Neo Geo Bios
+mslug.zip Metal Slug
+sf2.zip Street Fighter II
+```
+
+Format: `filename.ext` + TAB + `Display Name`
+
+Start name with `.` to hide the file (useful for BIOS files).
+
+---
+
+## BIOS Files
+
+Some emulators require official BIOS files. Place them in `Bios//`:
+
+```
+Bios/
+├── FC/disksys.rom
+├── GB/gb_bios.bin
+├── GBA/gba_bios.bin
+├── GBC/gbc_bios.bin
+├── MD/bios_CD_E.bin
+│ bios_CD_J.bin
+│ bios_CD_U.bin
+└── PS/psxonpsp660.bin
+```
+
+**Note:** Filenames are case-sensitive.
+
+---
+
+## Collections
+
+Create custom playlists with text files in the `Collections/` folder:
+
+**Example:** `Collections/Metroid series.txt`
+```
+/Roms/GBA/Metroid Zero Mission.gba
+/Roms/GB/Metroid II.gb
+/Roms/SNES (SFC)/Super Metroid.sfc
+/Roms/GBA/Metroid Fusion.gba
+```
+
+Collections appear as a separate category in the launcher.
+
+---
+
+## Simple Mode
+
+Hide the Tools folder and simplify the in-game menu (replaces Options with Reset).
+
+**Enable:** Create empty file `/.userdata/shared/enable-simple-mode`
+
+Perfect for kids or non-technical users.
+
+---
+
+## Advanced
+
+### Auto-Run Script
+
+Run custom shell scripts on boot:
+
+**Create:** `/.userdata//auto.sh`
+
+**Important:** Use Unix line endings (`\n`), not Windows (`\r\n`).
+
+---
+
+## Credits
+
+**eggs** - NEON scalers, example code, endless patience
+- RG35XX: https://www.dropbox.com/sh/3av70t99ffdgzk1/AAAKPQ4y0kBtTsO3e_Xlrhqha
+- Miyoo Mini: https://www.dropbox.com/sh/hqcsr1h1d7f8nr3/AABtSOygIX_e4mio3rkLetWTa
+- Trimui Model S: https://www.dropbox.com/sh/5e9xwvp672vt8cr/AAAkfmYQeqdAalPiTramOz9Ma
+
+**neonloop** - Trimui toolchain, picoarch inspiration
+- Repos: https://git.crowdedwood.com
+
+**muOS community** - H700 discoveries and collaboration
+- muOS: https://muos.dev
+- Knulli: https://knulli.org
+
+**JELOS/fewt** - RGB30 support, Linux kernel guidance
+- JELOS: https://github.com/JustEnoughLinuxOS/distribution
+
+**Steward** - Exhaustive device documentation
+- Website: https://steward-fu.github.io/website/
+
+**Gamma** - MagicX performance unlocking, GammaOS
+- Repos: https://github.com/TheGammaSqueeze/
+
+**BlackSeraph** - chroot expertise, GarlicOS
+- Repos: https://github.com/GarlicOS
+
+**Jim Gray** - Testing, development soundtrack
+- Music: https://ourghosts.bandcamp.com/music
+- Patreon: https://www.patreon.com/ourghosts/
diff --git a/skeleton/BASE/README.txt b/skeleton/BASE/README.txt
deleted file mode 100644
index a1af6824..00000000
--- a/skeleton/BASE/README.txt
+++ /dev/null
@@ -1,273 +0,0 @@
-MinUI is a minimal launcher for the Trimui Smart (and Pro) and Brick, the Miyoo Mini (and Plus), A30, and Flip, the Powkiddy RGB30, the M17, the MagicX XU Mini M and Mini Zero 28, and the Anbernic RG*XX family--all from the same SD card. Why? Why not?
-
-Source:
-https://github.com/shauninman/minui
-
-----------------------------------------
-Installing
-
-PREFACE
-
-MinUI has two essential parts: an installer/updater zip archive named "MinUI.zip" and a bootstrap file or folder with names that vary by platform.
-
-On devices that support two SD cards (eg. RG35XX) I will use the name "TF1" to refer to the card that goes into slot one of the device. All other instances of "SD card" or "primary card" refer to the card that goes into the second slot or to the sole SD card of devices that only support a single card. To be able to use MinUI from a single SD card on multiple devices you must install it on the second card of devices that support two SD cards.
-
-The primary card should be a reputable brand and freshly formatted as FAT32 (MBR).
-
-CAVEATS
-
-While MinUI can be updated from any device once installed, some devices require (minor) changes to NAND or TF1 (via the aforementioned bootstrap file or folder) and therefore need to be installed from the specific device before using. The same is true when trying to use an existing card in a new device of the same type. When in doubt, follow the installation instructions; if all the necessary bits are already installed, the installer will just act as an updater instead.
-
-ALL
-
-Preload the "Bios" and "Roms" folders then copy both to the root of your primary card.
-
-RGB30
-
-MinUI is meant to be used with Moss installed on the SD card that goes into the left slot (labeled TF-OS) of the RGB30. Download and flash the latest version:
-
- https://github.com/shauninman/Moss/releases
-
-Copy "MinUI.zip" (without unzipping) to the root of the SD card that goes into the right slot (labeled TFGAME) of the RGB30.
-
-MAGICX XU MINI M
-
-MinUI is meant to be used with a heavily modified stock SD card that goes into the left slot (labeled TF1/INT). Download and flash the latest version:
-
- https://github.com/shauninman/Moss-magicmini/releases
-
-Copy "MinUI.zip" (without unzipping) to the root of the SD card that goes into the right slot (labeled TF2/EXT).
-
-MAGICX MINI ZERO 28
-
-MinUI is meant to be used with Moss installed on the SD card that goes into the left slot (labeled TF1/INT). Download and flash the latest version:
-
- https://github.com/shauninman/Moss-zero28/releases
-
-Copy the "magicx" folder and "MinUI.zip" (without unzipping) to the root of the SD card that goes into the right slot (labeled TF2/EXT).
-
-TRIMUI SMART / TRIMUI SMART PRO / TRIMUI BRICK
-
-Copy the "trimui" folder and "MinUI.zip" (without unzipping) to the root of the SD card.
-
-MIYOO MINI / MIYOO A30
-
-Copy the "miyoo" folder and "MinUI.zip" (without unzipping) to the root of the SD card.
-
-MIYOO MINI PLUS
-
-Copy the "miyoo354" folder and "MinUI.zip" (without unzipping) to the root of the SD card.
-
-If you have a device with working RTC, you can enable it by creating an empty file named "enable-rtc" (no extension) in "/.userdata/miyoomini/".
-
-MIYOO FLIP
-
-Copy the "miyoo355" folder and "MinUI.zip" (without unzipping) to the root of the SD card. Put the SD card into the right slot (beneath the power button).
-
-MIYOO MINI FLIP
-
-Copy the "miyoo285" folder and "MinUI.zip" (without unzipping) to the root of the SD card.
-
-M17
-
-Copy the "em_ui.sh" file and "MinUI.zip" (without unzipping) to the root of the SD card.
-
-RG35XX PLUS / RG35XX H / RG35XX 2024 / RG28XX / RG35XXSP / RG40XXH / RGCUBEXX / RG34XX / RG34XXSP
-
-MinUI is meant to be installed over a fresh copy of the stock Anbernic firmware. You can use the stock TF1 card, reports of its poor quality are greatly exaggerated and, as long as you are using the recommended two card setup, no userdata is stored on it. (Note that the PLUS/H/2024/SP stock TF1 is not compatible with the 28XX/40XXH and vice versa.)
-
-Copy "/rg35xxplus/dmenu.bin" (just the file) to the root of the "NO NAME" partition (FAT32 with an "anbernic" folder) of the TF1 card. Copy "MinUI.zip" (without unzipping) to the root of the TF2 card.
-
-GKD PIXEL / GKD MINI
-
-An important caveat: this device is not cross-compatible with other MinUI-supported devices because its firmware lives on the SD card and its presence trips up all the other devices.
-
-Backup your stock SD card (not just the "ROMS" partition but the entire thing). If you like to live on the edge just create a folder named "stock" on the "ROMS" partition and copy everything into that folder.
-
-Copy the "gkdpixel" folder and "MinUI.zip" (without unzipping) to the root of the "ROMS" partition of the SD card. (On the GKD Mini should be TF1.)
-
-Boot stock, navigate to the "APP" folder and launch "file manager". Then use the d-pad and A button to navigate to "/media/roms/gkdpixel". Highlight the "install.sh" file and press A to open a menu and select "Execute" to install MinUI.
-
-RG35XX (original)
-
-MinUI is meant to be installed over a fresh copy of the stock Anbernic firmware. You can use the stock TF1 card, reports of its poor quality are greatly exaggerated and, as long as you are using the recommended two card setup, no userdata is stored on it.
-
-Copy "/rg35xx/dmenu.bin" (just the file) to the root of the MISC partition of the TF1 card. Copy "MinUI.zip" (without unzipping) to the root of the TF2 card.
-
-----------------------------------------
-Updating
-
-ALL
-
-Copy "MinUI.zip" (without unzipping) to the root of the SD card containing your Roms.
-
-----------------------------------------
-Shortcuts
-
-For devices without a dedicated MENU button
-
- RGB30: use L3 or R3 for MENU
- M17: use + or - for MENU
-
-RGB30 / MIYOO MINI PLUS / RG35XX (PLUS) / TRIMUI SMART PRO / TRIMUI BRICK / GKD PIXEL / MIYOO A30 / MAGICX XU MINI M / MIYOO FLIP / MAGICX MINI ZERO 28
-
- Brightness: MENU + VOLUME UP
- or VOLUME DOWN
-
-MIYOO MINI / TRIMUI SMART / M17
-
- Volume: SELECT + L or R
- Brightness: START + L or R
-
-RGB30 / MIYOO MINI (PLUS) / RG35XX (PLUS) / TRIMUI SMART PRO / TRIMUI BRICK / GKD PIXEL / MIYOO A30 / MAGICX XU MINI M / MIYOO FLIP / MAGICX MINI ZERO 28
-
- Sleep: POWER
- Wake: POWER
-
-TRIMUI SMART / M17
-
- Sleep: MENU (twice)
- Wake: MENU
-
-TRIMUI SMART PRO / TRIMUI BRICK
-
- Mute: FN switch (volume and rumble)
-
-----------------------------------------
-Quicksave & auto-resume
-
-MinUI will create a quicksave when powering off in-game. The next time you power on the device it will automatically resume from where you left off. A quicksave is created when powering off manually or automatically after a short sleep. On devices without a POWER button (eg. the Trimui Smart or M17) press the MENU button twice to put the device to sleep before flipping the POWER switch.
-
-----------------------------------------
-Roms
-
-Included in this zip is a "Roms" folder containing folders for each console MinUI currently supports. You can rename these folders but you must keep the uppercase tag name in parentheses in order to retain the mapping to the correct emulator (eg. "Nintendo Entertainment System (FC)" could be renamed to "Nintendo (FC)", "NES (FC)", or "Famicom (FC)").
-
-When one or more folder share the same display name (eg. "Game Boy Advance (GBA)" and "Game Boy Advance (MGBA)") they will be combined into a single menu item containing the roms from both folders (continuing the previous example, "Game Boy Advance"). This allows opening specific roms with an alternate pak.
-
-----------------------------------------
-Bios
-
-Some emulators require or perform much better with official bios. MinUI is strictly BYOB. Place the bios for each system in a folder that matches the tag in the corresponding "Roms" folder name (eg. bios for "Sony PlayStation (PS)" roms goes in "/Bios/PS/"),
-
-Bios file names are case-sensitive:
-
- FC: disksys.rom
- GB: gb_bios.bin
- GBA: gba_bios.bin
- GBC: gbc_bios.bin
- MD: bios_CD_E.bin
- bios_CD_J.bin
- bios_CD_U.bin
- PS: psxonpsp660.bin
-
-----------------------------------------
-Disc-based games
-
-To streamline launching multi-file disc-based games with MinUI place your bin/cue (and/or iso/wav files) in a folder with the same name as the cue file. MinUI will automatically launch the cue file instead of navigating into the folder when selected, eg.
-
- Harmful Park (English v1.0)/
- Harmful Park (English v1.0).bin
- Harmful Park (English v1.0).cue
-
-For multi-disc games, put all the files for all the discs in a single folder. Then create an m3u file in that folder (just a text file containing the relative path to each disc's cue file on a separate line) with the same name as the folder. Instead of showing the entire messy contents of the folder, MinUI will launch the appropriate cue file, eg. For a "Policenauts" folder structured like this:
-
- Policenauts (English v1.0)/
- Policenauts (English v1.0).m3u
- Policenauts (Japan) (Disc 1).bin
- Policenauts (Japan) (Disc 1).cue
- Policenauts (Japan) (Disc 2).bin
- Policenauts (Japan) (Disc 2).cue
-
-The m3u file would contain just:
-
- Policenauts (Japan) (Disc 1).cue
- Policenauts (Japan) (Disc 2).cue
-
-When a multi-disc game is detected the in-game menu's Continue item will also show the current disc. Press left or right to switch between discs.
-
-MinUI also supports chd files and official pbp files (multi-disc pbp files larger than 2GB are not supported). Regardless of the multi-disc file format used, every disc of the same game share the same memory card and save state slots.
-
-----------------------------------------
-Collections
-
-A collection is just a text file containing an ordered list of full paths to rom, cue, or m3u files. These text files live in the "Collections" folder at the root of your SD card, eg. "/Collections/Metroid series.txt" might look like this:
-
- /Roms/GBA/Metroid Zero Mission.gba
- /Roms/GB/Metroid II.gb
- /Roms/SNES (SFC)/Super Metroid.sfc
- /Roms/GBA/Metroid Fusion.gba
-
-----------------------------------------
-
-Display names
-
-Certain (unsupported arcade) cores require roms to use arcane file names. You can override the display name used throughout MinUI by creating a map.txt in the same folder as the files you want to rename. One line per file, `rom.ext` followed by a single tab followed by `Display Name`. You can hide a file by adding a `.` at the beginning of the display name. eg.
-
- neogeo.zip .Neo Geo Bios
- mslug.zip Metal Slug
- sf2.zip Street Fighter II
-
-----------------------------------------
-Simple mode
-
-Not simple enough for you (or maybe your kids)? MinUI has a simple mode that hides the Tools folder and replaces Options in the in-game menu with Reset. Perfect for handing off to littles (and olds too I guess). Just create an empty file named "enable-simple-mode" (no extension) in "/.userdata/shared/".
-
-----------------------------------------
-Advanced
-
-MinUI can automatically run a user-authored shell script on boot. Just place a file named "auto.sh" in "/.userdata//". If you're on Windows, make sure your text editor uses Unix line-endings (eg. `\n`), these devices usually choke on Windows line-endings (eg. `\r\n`).
-
-----------------------------------------
-Thanks
-
-To eggs, for his NEON scalers, years of top-notch example code, and patience in the face of my endless questions.
-
-Check out eggs' releases (includes source code):
-
- RG35XX https://www.dropbox.com/sh/3av70t99ffdgzk1/AAAKPQ4y0kBtTsO3e_Xlrhqha
- Miyoo Mini https://www.dropbox.com/sh/hqcsr1h1d7f8nr3/AABtSOygIX_e4mio3rkLetWTa
- Trimui Model S https://www.dropbox.com/sh/5e9xwvp672vt8cr/AAAkfmYQeqdAalPiTramOz9Ma
-
-To neonloop, for putting together the original Trimui toolchain from which I learned everything I know about docker and buildroot and is the basis for every toolchain I've put together since, and for picoarch, the inspiration for minarch.
-
-Check out neonloop's repos:
-
- https://git.crowdedwood.com
-
-To adixial and acmeplus and the entire muOS community, for sharing their discoveries for the h700 family of Anbernic devices.
-
-Check out muOS and Knulli:
-
- https://muos.dev
- https://knulli.org
-
-To fewt and the entire JELOS community, for JELOS (without which MinUI would not exist on the RGB30) and for sharing their knowledge with this perpetual Linux kernel novice.
-
-Check out JELOS:
-
- https://github.com/JustEnoughLinuxOS/distribution
-
-To Steward, for maintaining exhaustive documentation on a plethora of devices:
-
- https://steward-fu.github.io/website/
-
-To Gamma, for his efforts unlocking more performance on the MagicX XU Mini M (before we all realized its RG3562 was surreptitiously an RK3266).
-
-Check out his repos (including GammaOS):
-
- https://github.com/TheGammaSqueeze/
-
-To BlackSeraph, for introducing me to chroot.
-
-Check out the GarlicOS repos:
-
- https://github.com/GarlicOS
-
-To Jim Gray, for commiserating during development, for early alpha testing, and for providing the soundtrack for much of MinUI's development.
-
-Check out Jim's music:
-
- https://ourghosts.bandcamp.com/music
- https://www.patreon.com/ourghosts/
-
diff --git a/skeleton/EXTRAS/README.md b/skeleton/EXTRAS/README.md
new file mode 100644
index 00000000..d5e32c46
--- /dev/null
+++ b/skeleton/EXTRAS/README.md
@@ -0,0 +1,157 @@
+# MinUI Extras
+
+Optional emulator cores and tools for MinUI. These supplement the base installation with additional systems and utilities.
+
+**Source:** https://github.com/shauninman/minui
+
+---
+
+## What's Included
+
+**Extra Emulator Cores:**
+- Neo Geo Pocket (and Color)
+- Pico-8
+- Pokémon mini
+- Sega Game Gear
+- Sega Master System
+- Super Game Boy
+- TurboGrafx-16 (and TurboGrafx-CD)
+- Virtual Boy
+
+**Platform-Specific Tools:**
+- File managers
+- Configuration utilities
+- Platform-specific tweaks
+
+---
+
+## Installation
+
+Copy the desired folders from this archive to the corresponding locations on your MinUI SD card:
+
+- `Emus//` → `/Emus//` (emulator paks)
+- `Tools//` → `/Tools//` (tool paks)
+
+**Platform identifiers:**
+- `miyoomini` - Miyoo Mini/Plus
+- `my282` - Miyoo A30, RG28XX
+- `my355` - Miyoo Flip, Miyoo Mini Flip
+- `trimuismart` - Trimui Smart
+- `tg5040` - Trimui Smart Pro, Trimui Brick
+- `rg35xx` - RG35XX (original)
+- `rg35xxplus` - RG35XX Plus, H, SP, 2024, Cube, RG34XX, RG40XX family
+- `rgb30` - RGB30
+- `zero28` - MagicX Mini Zero 28
+- `m17` - M17 (deprecated)
+- `gkdpixel` - GKD Pixel/Mini (deprecated)
+- `magicmini` - MagicX XU Mini M (deprecated)
+
+---
+
+## Updating
+
+Check the release notes to see what changed. Only copy updated paks you want to your device's specific folders.
+
+Example: If GBA.pak was updated for miyoomini, copy just that pak to `/Emus/miyoomini/` on your SD card.
+
+---
+
+## BIOS Files
+
+Some extra cores require BIOS files. Place them in `Bios//`:
+
+**Required BIOS:**
+- **MGBA** (GBA): `gba_bios.bin`
+- **PCE** (PC Engine): `syscard3.pce`
+- **PKM** (Pokémon mini): `bios.min`
+- **SGB** (Super Game Boy): `sgb.bios`
+
+**Note:** Filenames are case-sensitive. MinUI is strictly BYOB (bring your own BIOS).
+
+---
+
+## Platform-Specific Tools
+
+### RGB30 Only
+
+#### P8-NATIVE.pak and Splore.pak
+
+Run official PICO-8 natively (faster than libretro core).
+
+**Setup:**
+1. Download PICO-8 for Raspberry Pi: https://lexaloffle.itch.io/pico-8
+2. Copy the entire ZIP (e.g., `pico-8_0.2.5g_raspi.zip`) to `/Tools/rgb30/Splore.pak/`
+3. Copy `P8-NATIVE.pak`, `Splore.pak`, and `Wi-Fi.pak` to `/Tools/rgb30/` and `/Emus/rgb30/` on SD card
+4. Place PICO-8 carts in `/Roms/Pico-8 (P8-NATIVE)/`
+
+**Controls:**
+- **Exit P8-NATIVE**: Press START → select "SHUTDOWN"
+- **Exit Splore**: Press START (in-game) → "EXIT TO SPLORE" → (in splore) START → "OPTIONS" → "SHUTDOWN PICO-8"
+
+**Limitations:** No MinUI features (in-game menu, save states, auto-resume, sleep).
+
+#### Wi-Fi.pak
+
+Enable WiFi for Splore and other network features.
+
+**Setup:**
+1. Edit `wifi.txt` with your network credentials (two lines: SSID, then password):
+ ```
+ minui
+ lessismore
+ ```
+2. Copy `Wi-Fi.pak` to `/Tools/rgb30/` on SD card
+3. Launch pak to connect (first time) or toggle WiFi on/off (subsequent launches)
+
+**Note:** WiFi drains battery. Enable only when needed.
+
+---
+
+## Device-Specific Tools
+
+### Miyoo A30
+
+#### Remove Loading.pak
+
+Removes "LOADING" text between boot logo and MinUI.
+
+**Warning:** Patches NAND memory (read-only root filesystem). Takes ~5 minutes. Stay connected to power. Do not power off during operation.
+
+### Trimui Smart Pro / Brick
+
+#### Remove Loading.pak
+
+Removes "LOADING" text. Minimally invasive compared to A30 version.
+
+### RG34XX
+
+#### Swap Menu.pak
+
+Swaps MENU and SELECT buttons system-wide (makes MENU more accessible).
+
+**Usage:**
+- Launch pak → reboot to apply
+- Launch pak again → reboot to undo
+
+---
+
+## Creating Your Own Paks
+
+Want to add more systems or tools? Check out the [Pak Development Guide](https://github.com/shauninman/minui/blob/main/docs/PAKS.md) to learn how to create custom emulator and tool paks for MinUI.
+
+**Pak types:**
+1. **Reuse existing cores** - Customize options for bundled cores
+2. **Bundle new cores** - Add new libretro cores
+3. **Standalone emulators** - Maximum performance (no MinUI integration)
+
+---
+
+## Support
+
+**Important:** Third-party paks are not officially supported. If a console or core isn't included in MinUI's base or extras, there's usually a good reason:
+- Poor libretro integration
+- Unreliable save states
+- Performance issues
+- Complexity (arcade cores with arcane ROM requirements)
+
+For help with MinUI itself, check the GitHub repository.
diff --git a/skeleton/EXTRAS/README.txt b/skeleton/EXTRAS/README.txt
deleted file mode 100644
index 3cf633a5..00000000
--- a/skeleton/EXTRAS/README.txt
+++ /dev/null
@@ -1,66 +0,0 @@
-MinUI is a minimal launcher for the RGB30, Trimui Smart (and Pro), Miyoo Mini (and Plus), M17, and RG35XX--all from the same SD card. Why? Why not?
-
-Source:
-https://github.com/shauninman/minui
-
-----------------------------------------
-Installing
-
-PREFACE
-
-On devices that support two SD cards (eg. RG35XX) I will use the name "TF1" to refer to the card that goes into slot one of the device. All other instances of "SD card" or "primary card" refer to the card that goes into the second slot or to the sole SD card of devices that only support a single card. To get the most out of MinUI on devices that support two SD cards you should install MinUI on the second card.
-
-Copy all the folders from this zip file to the root of your primary card.
-
-----------------------------------------
-Updating
-
-This extras zip file is included with every release, regardless of whether its contents has changed or not. Refer to the release notes to see what, if anything, was added or changed and copy just the desired updated pak(s) to the corresponding device folder in the Emus or Tools folders (eg. /Emus/tg5040 or /Tools/rgb30)
-
-----------------------------------------
-Bios files
-
-You'll need to BYOB for the emulator paks included in this zip file.
-
-MGBA: gba_bios.bin
- PCE: syscard3.pce
- PKM: bios.min
- SGB: sgb.bios
-
-----------------------------------------
-Native PICO-8 and Splore.pak (RGB30-only)
-
-Download the official PICO-8 fantasy console for the Raspberry Pi from https://lexaloffle.itch.io/pico-8 (If you've bought a bundle on itch.io any time in the last few years you might already have a copy in your library https://itch.io/my-collections) At the time of writing, the file is named "pico-8_0.2.5g_raspi.zip". Copy that zip file into "/Tools/rgb30/Splore.pak/". Copy "/Emus/rgb30/P8-NATIVE.pak", "/Tools/rgb30/Splore.pak", and "/Tools/rgb30/Wi-Fi.pak" to your SD card. (You need the Wi-Fi.pak to download PICO-8 games in Splore.pak.)
-
-Place carts you would like to play with native PICO-8 in "/Roms/Pico-8 (P8-NATIVE)/".
-
-To exit P8-NATIVE.pak, press start. Then select "SHUTDOWN".
-
-To exit Splore.pak, press start. In-game select "EXIT TO SPLORE". With a cart selected in splore press start, select "OPTIONS", and then "SHUTDOWN PICO-8".
-
-Please note that Splore.pak and P8-NATIVE.pak don't/can't implement MinUI's uniform features like the in-game menu (including save states), faux sleep, and quicksave/auto-resume.
-
-----------------------------------------
-Wi-Fi.pak (RGB30-only)
-
-Open "wifi.txt" in a plain text editor and enter your network name and password on two separate lines and save, eg.
-
- minui
- lessismore
-
-Copy "Wi-Fi.pak" to "/Tools/rgb30/" on your SD card. The first time you open the pak (or any time you change the contents of "wifi.txt") it will update the network name and password then connect. Subsequent launches will toggle wi-fi on and off. Wi-fi will drain the battery so it's best to only enable it when you plan to use it and disable it when you're done. Your Wi-fi state persists across reboots.
-
-----------------------------------------
-Remove Loading.pak (Miyoo A30)
-
-This pak removes the "LOADING" text that appears between the boot logo and the main interface when powering on. It requires patching nand memory to modify the otherwise read-only root file system. It takes around 5 minutes to complete. While not required it is a very good idea to be connected to power while performing this operation. Please be patient and do not power off the device before it completes.
-
-----------------------------------------
-Remove Loading.pak (Trimui Smart Pro and Brick)
-
-This pak removes the "LOADING" text that appears between the boot logo and the main interface when powering on. Compared to the A-30 this is a minimally invasive procedure. Nothing to worry about.
-
-----------------------------------------
-Swap Menu.pak (RG34XX)
-
-This pak swaps the MENU and SELECT button at a system level to make MENU more accessible. Launch the pak then reboot. Relaunch the pak and reboot to undo the change.
\ No newline at end of file
diff --git a/workspace/gkdpixel/README.md b/workspace/gkdpixel/README.md
new file mode 100644
index 00000000..177cd67b
--- /dev/null
+++ b/workspace/gkdpixel/README.md
@@ -0,0 +1,440 @@
+# GKD Pixel
+
+Platform implementation for the GKD Pixel retro handheld device.
+
+> [!WARNING]
+> **This platform is deprecated and will be removed in a future MinUI release.**
+>
+> **Reason**: Unique chipset (Ingenic X1830) with limited community support value.
+>
+> While the platform will continue to work with current MinUI releases, it will not receive new features or platform-specific bug fixes.
+
+## Hardware Specifications
+
+### Display
+- **Resolution**: 320x240 (QVGA)
+- **Color Depth**: 16-bit RGB565
+- **UI Scale**: 1x (uses `assets.png`)
+- **Video**: SDL2 with triple buffering (SDL_TRIPLEBUF)
+- **Scaling**: Custom approximate bilinear scalers optimized for device resolution
+
+### Input
+- **D-Pad**: Up, Down, Left, Right
+- **Face Buttons**: A, B, X, Y
+- **Shoulder Buttons**: L1, R1, L2, R2
+- **System Buttons**:
+ - MENU button
+ - POWER button
+ - SELECT and START buttons
+ - Dedicated PLUS/MINUS volume buttons
+
+### Input Method
+- **Primary**: Evdev/keyboard input codes (direct kernel input)
+- **No SDL Keyboard**: All SDL keyboard mappings are `BUTTON_NA`
+- **No Joystick Input**: Platform does not use SDL joystick API
+- **Event Device**: `/dev/input/event0` for all button input
+
+### CPU & Performance
+- ARM processor with support for GNU99 standard
+- LTO (Link Time Optimization) enabled in build
+- No overclocking support
+- Uses GCW0 toolchain for cross-compilation
+
+### Power Management
+- Battery monitoring via sysfs (`/sys/class/power_supply/battery/capacity`)
+- USB charging detection (`/sys/class/power_supply/usb/online`)
+- Simplified charge levels (10%, 20%, 40%, 60%, 80%, 100%)
+- Auto-sleep and power-off features
+
+### Storage
+- SD card mounted at `/media/roms`
+
+## Architecture
+
+The GKD Pixel uses a **pure evdev input architecture** with custom optimized scalers:
+
+- **Evdev-only input**: All buttons mapped via kernel input event codes (no SDL keyboard or joystick)
+- **Software scaling**: Uses custom approximate bilinear scalers optimized for common retro resolutions
+- **Stock OS integration**: Hooks into system startup via `/usr/sbin/frontend_start`
+
+## Directory Structure
+
+```
+gkdpixel/
+├── platform/ Platform-specific hardware definitions
+│ ├── platform.h Button mappings, display specs, evdev codes
+│ ├── platform.c Platform implementation (scalers, battery, etc.)
+│ ├── makefile.env Build environment settings
+│ └── makefile.copy File copy rules
+├── keymon/ Hardware button monitoring daemon
+│ ├── keymon.c Volume/brightness control daemon
+│ └── credits.txt Attribution for button monitoring code
+├── libmsettings/ Settings library (volume, brightness)
+│ ├── msettings.h Settings API header
+│ └── msettings.c Settings implementation (shared memory)
+├── boot/ Boot and update scripts
+│ ├── boot.sh Main boot handler (becomes frontend_start)
+│ ├── install.sh Installation script
+│ ├── installing.bmp Boot splash for fresh install (320x240)
+│ └── updating.bmp Boot splash for updates (320x240)
+├── install/ Installation assets
+│ └── install.sh Post-update installation script
+├── input/ Input testing utility
+│ ├── input.c Raw input and SDL input testing
+│ └── input.txt Input testing documentation
+├── test/ Platform testing utilities
+├── cores/ Libretro cores (submodules + builds)
+└── makefile Platform build orchestration
+```
+
+## Input System
+
+The GKD Pixel uses an **evdev-only input approach**:
+
+1. **Evdev Codes**: All input handled via direct kernel input codes (`CODE_*` defines)
+2. **No SDL Input**: Platform does not use SDL keyboard or joystick APIs
+3. **Single Event Device**: `/dev/input/event0` handles all button input
+4. **Kernel Space Monitoring**: keymon daemon polls input device at 60Hz
+
+### Evdev Button Mappings
+
+| Button | Evdev Code | Linux Constant |
+|--------|------------|----------------|
+| UP | 103 | KEY_UP |
+| DOWN | 108 | KEY_DOWN |
+| LEFT | 105 | KEY_LEFT |
+| RIGHT | 106 | KEY_RIGHT |
+| SELECT | 1 | KEY_ESC |
+| START | 28 | KEY_ENTER |
+| A | 29 | KEY_LEFTCTRL |
+| B | 56 | KEY_LEFTALT |
+| X | 57 | KEY_SPACE |
+| Y | 42 | KEY_LEFTSHIFT |
+| L1 | 15 | KEY_TAB |
+| R1 | 14 | KEY_BACKSPACE |
+| L2 | 104 | KEY_PAGEUP |
+| R2 | 109 | KEY_PAGEDOWN |
+| MENU | 102 | KEY_HOME |
+| MENU_ALT | 107 | KEY_END |
+| POWER | 116 | KEY_POWER |
+| POWEROFF | 68 | KEY_F10 |
+| PLUS | 78 | KEY_KPPLUS |
+| MINUS | 74 | KEY_KPMINUS |
+
+### Button Combinations
+
+| Combination | Function |
+|-------------|----------|
+| PLUS | Increase volume |
+| MINUS | Decrease volume |
+| MENU + PLUS | Increase brightness |
+| MENU + MINUS | Decrease brightness |
+| POWER | Sleep/wake device |
+| X (in launcher) | Resume from save state |
+
+### Input Characteristics
+- **Polling Rate**: 60Hz (16.666ms interval)
+- **Repeat Delay**: 300ms initial, 100ms interval
+- **Stale Input Protection**: Ignores events after 1+ second gap (prevents spurious events after sleep)
+
+## Building
+
+### Prerequisites
+Requires Docker with GCW0 cross-compilation toolchain.
+
+### Build Commands
+
+```bash
+# Enter platform build environment
+make PLATFORM=gkdpixel shell
+
+# Inside container: build all platform components
+cd /root/workspace/gkdpixel
+make
+
+# This builds:
+# - keymon (button monitoring daemon)
+# - libmsettings (settings library)
+# - All libretro cores in cores/
+# - Platform abstraction layer (platform.c)
+```
+
+### Dependencies
+- **Build Standard**: GNU99 (`-std=gnu99`)
+- **Optimization**: LTO enabled (`-flto`)
+- **Toolchain**: GCW0 (same as other OpenDingux devices)
+
+No external dependencies are cloned - platform uses stock MinUI shared code.
+
+## Installation
+
+### File System Layout
+
+MinUI installs to the SD card with the following structure:
+
+```
+/media/roms/
+├── .system/
+│ ├── gkdpixel/ Platform-specific binaries
+│ │ ├── bin/ Utilities (keymon, etc.)
+│ │ │ └── install.sh Post-update installation script
+│ │ ├── dat/ Platform data files
+│ │ │ └── boot.sh Boot handler script
+│ │ └── paks/ Applications and emulators
+│ │ └── MinUI.pak/ Main launcher
+│ └── res/ Shared UI assets
+│ ├── assets.png UI sprite sheet (1x scale)
+│ └── BPreplayBold-unhinted.otf
+├── MinUI.zip Update package (if present)
+└── log.txt Installation/update log
+```
+
+### Stock OS Integration
+
+MinUI integrates with the stock firmware through system hooks:
+
+**On system partition** (`/usr`):
+```
+/usr/
+├── sbin/
+│ ├── frontend_start MinUI's boot.sh (copied here)
+│ └── frontend_start.original Stock launcher (backed up)
+└── share/
+ └── minui/
+ ├── installing.bmp Fresh install splash (320x240)
+ └── updating.bmp Update splash (320x240)
+```
+
+The stock OS calls `/usr/sbin/frontend_start` on boot, which MinUI replaces with its own boot handler.
+
+### Boot Process
+
+1. Device boots stock OS
+2. Stock OS runs `/usr/sbin/frontend_start` (MinUI's boot script)
+3. Script performs console cleanup:
+ - Unlocks virtual terminal
+ - Resets console
+ - Deactivates console on framebuffer
+4. Script checks for `MinUI.zip` on `/media/roms`
+5. If ZIP found:
+ - Display splash to framebuffer (`installing.bmp` or `updating.bmp`)
+ - Extract ZIP to `/media/roms`
+ - Delete ZIP file
+ - Run `.system/gkdpixel/bin/install.sh` to complete setup
+6. Launch MinUI via `.system/gkdpixel/paks/MinUI.pak/launch.sh`
+7. If launcher not found, fallback to stock launcher (`frontend_start.original`)
+
+#### Boot Image Display
+
+The platform displays BMP images directly to framebuffer:
+
+```bash
+dd skip=54 if=/usr/share/minui/installing.bmp of=/dev/fb0 bs=1
+```
+
+**Format Requirements**:
+- 320x240 resolution
+- Windows BMP format
+- Header skip: 54 bytes (standard BMP header)
+- Direct framebuffer write (no SDL required)
+
+## Platform-Specific Features
+
+### Framebuffer Management
+
+The boot script performs critical framebuffer cleanup:
+- **unlockvt**: Unlocks virtual terminal for framebuffer access
+- **reset**: Resets console to clean state
+- **vtconsole unbind**: Deactivates console text overlay on framebuffer
+
+This ensures clean video output without console interference.
+
+### Custom Optimized Scalers
+
+The platform implements **custom approximate bilinear scalers** optimized for common retro resolutions:
+
+#### GBA Scaler (240x160 → 320x213)
+- **Method**: 3x3 → 4x4 pixel upscale
+- **Algorithm**: Subpixel blending with color component weighting
+- **Optimization**: Likely() branch prediction for identical pixel runs
+- **Coverage**: Full GBA native resolution support
+
+#### Game Boy Scaler (160x144 → 266x240)
+- **Method**: 3x3 → 5x5 pixel upscale
+- **Algorithm**: Subpixel blending with 2:1 and 1:2 weighting
+- **Special Case**: Handles odd column remainders gracefully
+- **Coverage**: Original Game Boy and Game Boy Color
+
+#### SNES Scaler (256x224 → 320x238)
+- **Method**: 4x16 → 5x17 pixel chunk upscale
+- **Algorithm**: Complex multi-row blending with temporal coherence
+- **Row Weighting**: 3:1 average for smooth vertical scaling
+- **Coverage**: SNES, NES, and other 256px-wide systems
+
+All scalers use:
+- **RGB565 color space** (native format)
+- **Magic constants** for fast bit manipulation (0xF7DE, 0x0821, 0xE79C, 0x1863)
+- **Weighted averaging** to preserve visual quality
+- **Branch prediction hints** (`likely()`/`unlikely()`) for identical pixel optimization
+
+### Settings Management (libmsettings)
+
+Uses **shared memory architecture** for settings:
+- **Shared Memory Key**: `/SharedSettings`
+- **Host**: keymon daemon (creates and manages settings)
+- **Clients**: MinUI, emulators (read/write shared settings)
+- **Persistence**: Binary file at `$USERDATA_PATH/msettings.bin`
+
+#### Settings Schema
+
+```c
+typedef struct Settings {
+ int version; // Currently 2
+ int brightness; // 0-10
+ int headphones; // 0-20 (volume when jack detected)
+ int speaker; // 0-20 (volume when no jack)
+ int unused[2]; // Reserved for future use
+ int jack; // 0-1 (runtime only, not persisted)
+ int hdmi; // 0-1 (runtime only, not persisted)
+} Settings;
+```
+
+#### Hardware Control
+
+**Brightness** (PWM via sysfs):
+```
+/sys/devices/platform/jz-pwm-dev.0/jz-pwm/pwm0/dutyratio
+Range: 5-100 (0 prevents screen from waking)
+Curve: Linear (value * 10), minimum 5
+```
+
+**Volume** (ALSA mixer):
+```
+amixer sset 'PCM'
+Range: 0% (mute) to 100% (max)
+Transform: val ? 60 + (val * 2) / 5 : 0
+Scale: 0-20 user scale → 0-100 raw scale
+```
+
+### Battery Monitoring
+
+Simplified battery reporting via sysfs:
+- **Capacity Path**: `/sys/class/power_supply/battery/capacity`
+- **Charging Path**: `/sys/class/power_supply/usb/online`
+- **Levels**: Reduced to 6 steps (10%, 20%, 40%, 60%, 80%, 100%)
+- **Philosophy**: "Worry less about battery and more about the game you're playing"
+
+## Included Tools
+
+The following MinUI standard tools are available:
+
+### Clock.pak
+System clock/time display
+
+### Input.pak
+Input configuration and testing utility
+
+## Known Issues / Quirks
+
+### Platform Quirks
+
+1. **No L3/R3**: Platform lacks clickable analog sticks
+2. **No Rumble**: No vibration motor support
+3. **No CPU Scaling**: CPU frequency adjustment not supported
+4. **No VSync Control**: Fixed vsync via SDL_Delay()
+5. **Small Screen**: 320x240 limits UI visibility - uses 1x assets
+6. **Graphics Jitter**: Intermittent scrolling jitter in UI (not consistently reproducible, may be related to vsync timing)
+
+### Development Notes
+
+1. **Evdev-Only Input**: Platform completely bypasses SDL input system
+ - Must poll `/dev/input/event0` directly
+ - Cannot use SDL_PollEvent() for button input
+ - Input testing utility (input/) demonstrates both methods
+
+2. **Framebuffer Initialization**: Requires console cleanup before framebuffer access
+ - Must call unlockvt, reset, and unbind vtconsole
+ - Failure causes graphical corruption
+
+3. **Settings Shared Memory**: First process to create `/SharedSettings` becomes host
+ - keymon is expected to be the host
+ - Clients must handle host process lifecycle
+
+4. **Scaler Selection**: Platform.c selects scalers based on exact source resolution
+ - 240x160: Uses optimized GBA scaler
+ - 160x144: Uses optimized GB scaler
+ - 256x224: Uses optimized SNES scaler
+ - Other resolutions: Falls back to generic scalers (scale2x2_c16, etc.)
+
+5. **MENU Button Alternative**: CODE_MENU_ALT (107 / KEY_END) provides alternate menu access
+
+### Volume Quirks
+
+- **Mute Value**: 0 (simpler than platforms using negative values)
+- **Volume Range**: 0-20 (finer granularity than typical 0-10 scale)
+- **Separate Profiles**: Headphone and speaker volumes stored independently
+- **ALSA Transform**: Non-linear mapping to optimize useful volume range
+
+## Testing
+
+### Input Testing
+
+Use the included input testing utility:
+
+```bash
+cd /root/workspace/gkdpixel/input
+make
+./input.elf
+```
+
+The utility provides two modes:
+- **raw_input()**: Tests evdev input by reading `/dev/input/event0-3`
+- **sdl_input()**: Tests SDL keyboard input (will show no events on this platform)
+
+### When Testing Changes
+
+1. Verify evdev input codes match kernel expectations
+2. Test volume/brightness controls with MENU+PLUS/MINUS
+3. Check battery monitoring displays correct charge levels
+4. Verify boot splash displays correctly during install/update
+5. Test all custom scalers with different resolution content:
+ - GBA (240x160): Pokémon, Metroid
+ - GB (160x144): Tetris, Link's Awakening
+ - SNES (256x224): Super Mario World, Final Fantasy
+6. Confirm framebuffer cleanup prevents console text overlay
+
+## Related Documentation
+
+- Main project docs: `../../README.md`
+- Platform abstraction: `../../all/common/defines.h`
+- Shared code: `../../all/minui/minui.c` (launcher), `../../all/minarch/minarch.c` (libretro frontend)
+- Build system: `../../Makefile` (host), `./makefile` (platform)
+- Platform header: `./platform/platform.h` (all hardware definitions)
+- Platform implementation: `./platform/platform.c` (scalers, battery, rendering)
+
+## Maintainer Notes
+
+This platform demonstrates several unique MinUI characteristics:
+
+### Pure Evdev Input Architecture
+- **No SDL keyboard or joystick**: All input via direct kernel event codes
+- **Single event device**: Simpler than platforms requiring multiple input sources
+- **60Hz polling**: Direct control over input latency
+
+### Optimized Software Scaling
+- **Custom bilinear scalers**: Hand-tuned for specific retro resolutions
+- **Magic constant optimization**: Fast RGB565 bit manipulation
+- **Branch prediction**: Likely()/unlikely() hints for solid color regions
+- **Temporal coherence**: SNES scaler maintains row state for efficiency
+
+### Minimal Dependencies
+- **No external repos**: Uses stock MinUI shared code only
+- **Small footprint**: Compact platform suitable for resource-constrained device
+- **GCW0 toolchain**: Leverages existing OpenDingux infrastructure
+
+### Integration Pattern
+- **Stock OS hook**: Replaces frontend_start rather than full OS replacement
+- **Fallback support**: Can return to stock launcher if MinUI not found
+- **Clean framebuffer**: Demonstrates proper console management
+
+Changes to this platform should preserve the evdev-only input architecture and maintain the custom scaler optimizations that provide high-quality output on the small 320x240 display.
diff --git a/workspace/m17/README.md b/workspace/m17/README.md
new file mode 100644
index 00000000..c87929f2
--- /dev/null
+++ b/workspace/m17/README.md
@@ -0,0 +1,410 @@
+# M17
+
+Platform implementation for the M17 retro handheld device.
+
+> [!WARNING]
+> **This platform is deprecated and will be removed in a future MinUI release.**
+>
+> **Reason**: Old/weak Cortex-A7 chipset, ultra-budget outlier with limited performance.
+>
+> While the platform will continue to work with current MinUI releases, it will not receive new features or platform-specific bug fixes.
+
+## Hardware Specifications
+
+### Display
+- **Resolution**: 480x273 (16:9 widescreen)
+- **Color Depth**: 16-bit RGB565
+- **UI Scale**: 1x (uses `assets.png`)
+- **Aspect Ratio**: 16:9 widescreen format
+
+### Input
+- **D-Pad**: Up, Down, Left, Right
+- **Face Buttons**: A, B, X, Y (labels swapped: physical A=B, physical B=A, physical X=Y, physical Y=X)
+- **Shoulder Buttons**: L1, R1, L2, R2
+- **System Buttons**:
+ - SELECT button
+ - START button
+ - Two MENU buttons (primary + alternate)
+
+### Input Method
+- **Primary**: Hybrid input (SDL keyboard + joystick)
+- **SDL Keyboard**: Face/shoulder buttons and D-pad
+- **Joystick**: All buttons duplicated as joystick indices
+- **Evdev Codes**: Not used (all CODE_* values are CODE_NA)
+
+### CPU & Performance
+- ARM processor with potential NEON SIMD support (HAS_NEON defined)
+- Supports CPU affinity pinning (taskset 8 for core 3)
+- No overclocking utilities included
+
+### Power Management
+- Headphone jack detection via sysfs (`/sys/devices/virtual/switch/h2w/state`)
+- Auto audio routing for headphones vs speakers
+- Basic sleep/wake functionality via MENU button
+
+### Storage
+- SD card mounted at `/sdcard`
+
+## Directory Structure
+
+```
+m17/
+├── platform/ Platform-specific hardware definitions
+│ └── platform.h Button mappings, display specs, paths
+├── keymon/ Hardware button monitoring daemon
+│ └── keymon.c Volume/brightness control + headphone monitoring
+├── libmsettings/ Settings library (volume, brightness, jack)
+├── boot/ Boot script and splash images
+│ ├── boot.sh Boot/update handler (becomes em_ui.sh)
+│ ├── build.sh Script to package boot assets
+│ ├── installing.bmp 32-bit BMP boot splash (480x272)
+│ ├── updating.bmp 32-bit BMP update splash (480x272)
+│ └── notes.txt Technical notes on framebuffer and boot logo
+├── install/ Installation assets
+│ └── install.sh Post-update installation script
+└── cores/ Libretro cores (submodules + builds)
+```
+
+## Input System
+
+The M17 uses a **hybrid input approach**:
+
+1. **SDL Keyboard Events**: Primary method for UI and games
+2. **SDL Joystick Events**: All buttons have duplicate joystick indices
+3. **No Evdev Codes**: Platform does not use kernel input codes
+
+### Button Combinations
+
+| Combination | Function |
+|-------------|----------|
+| START + R1 | Increase brightness |
+| START + L1 | Decrease brightness |
+| SELECT + R1 | Increase volume |
+| SELECT + L1 | Decrease volume |
+| MENU | Sleep device |
+| MENU | Wake device |
+| X (in launcher) | Resume from save state |
+
+### Button Mapping Notes
+
+The M17 has **swapped button labels** compared to typical layouts:
+- Physical A button → Maps to SDLK_B (BUTTON_A)
+- Physical B button → Maps to SDLK_A (BUTTON_B)
+- Physical X button → Maps to SDLK_Y (BUTTON_X)
+- Physical Y button → Maps to SDLK_X (BUTTON_Y)
+
+This ensures consistent behavior across different devices despite different physical labeling.
+
+### Joystick Indices
+
+All buttons are accessible via SDL joystick API with these indices:
+
+| Button | Joystick Index |
+|--------|----------------|
+| D-Pad Up | 11 |
+| D-Pad Down | 14 |
+| D-Pad Left | 12 |
+| D-Pad Right | 13 |
+| A | 9 |
+| B | 4 |
+| X | 2 |
+| Y | 7 |
+| L1 | 5 |
+| R1 | 1 |
+| L2 | 6 |
+| R2 | 8 |
+| SELECT | 10 |
+| START | 3 |
+| MENU | 15 |
+| MENU_ALT | 16 |
+
+## Building
+
+### Prerequisites
+Requires Docker with M17 cross-compilation toolchain.
+
+### Build Commands
+
+```bash
+# Enter platform build environment
+make PLATFORM=m17 shell
+
+# Inside container: build all platform components
+cd /root/workspace/m17
+make
+
+# This builds:
+# - keymon (button monitoring daemon)
+# - libmsettings (settings library)
+# - em_ui.sh (boot script with embedded splash images)
+# - All libretro cores in cores/
+```
+
+### Dependencies
+The M17 platform requires two additional shared libraries from the toolchain:
+- **libpng16.so.16**: PNG image library
+- **libSDL2_ttf-2.0.so.0**: SDL2 TrueType font library
+
+These are automatically extracted from the toolchain during the build process and packaged as `extra-libs.tar`.
+
+## Installation
+
+### File System Layout
+
+MinUI installs to the SD card with the following structure:
+
+```
+/sdcard/
+├── .system/
+│ ├── m17/ Platform-specific binaries
+│ │ ├── bin/ Utilities (keymon, etc.)
+│ │ │ └── install.sh Post-update installation script
+│ │ ├── lib/ Additional libraries (extracted from extra-libs.tar)
+│ │ ├── dat/ Data files (extra-libs.tar)
+│ │ └── paks/ Applications and emulators
+│ │ └── MinUI.pak/ Main launcher
+│ └── res/ Shared UI assets
+│ ├── assets.png UI sprite sheet (1x scale)
+│ └── BPreplayBold-unhinted.otf
+├── em_ui.sh Boot script (MinUI entry point)
+├── Roms/ ROM files organized by system
+├── MinUI.zip Update package (if present)
+└── log.txt Installation/update log (optional)
+```
+
+### Boot Process
+
+1. Device boots and runs `/sdcard/em_ui.sh` (MinUI's boot.sh)
+2. Script checks for `MinUI.zip` on SD card root
+3. If ZIP found:
+ - Initialize framebuffer (`/dev/fb0`)
+ - Extract embedded splash images from boot script using `uudecode`
+ - Display `installing` (first install) or `updating` (update) to framebuffer
+ - Extract `MinUI.zip` to `/sdcard`
+ - Delete ZIP file
+ - Run `.system/m17/bin/install.sh` to complete setup:
+ - Extract `extra-libs.tar` to `.system/m17/lib/`
+ - Copy updated boot script to `/sdcard/em_ui.sh`
+ - Clear framebuffer
+4. Launch MinUI via taskset: `taskset 8 /sdcard/.system/m17/paks/MinUI.pak/launch.sh`
+5. Loop: relaunch if launcher exits normally
+6. Poweroff if launcher script is deleted (prevents stock OS from interfering)
+
+#### Boot Script Packaging
+
+The boot script (`em_ui.sh`) is created by a build process that:
+1. Strips 54-byte headers from BMP splash images
+2. Creates ZIP file containing headerless bitmaps
+3. Encodes ZIP with `uuencode` and appends to `boot.sh`
+4. At runtime, script extracts embedded data using line offset calculation
+
+This allows splash images to be embedded directly in the boot script without requiring separate files.
+
+### Update Process
+
+To update MinUI on device:
+1. Place `MinUI.zip` in `/sdcard/` root
+2. Reboot device
+3. Boot script auto-detects ZIP and performs update
+4. ZIP is deleted after successful extraction
+5. Updated boot script replaces `/sdcard/em_ui.sh`
+
+## Platform-Specific Features
+
+### Framebuffer Display
+
+Boot splash images are displayed directly to `/dev/fb0`:
+- **Resolution**: 480x272 (matches screen exactly)
+- **Format**: 32-bit BMP (Windows format, flipped row order)
+- **Display method**: Raw write via `dd` command after header removal
+- **Initialization**: Framebuffer mode set from `/sys/class/graphics/fb0/modes`
+
+### Headphone Jack Monitoring
+
+A background thread in `keymon` continuously monitors headphone state:
+- **Detection**: Reads `/sys/devices/virtual/switch/h2w/state` (0=speaker, 2=headphones)
+- **Polling**: Checks every 1 second for state changes
+- **Audio Routing**: Automatically switches between speaker and headphone volume profiles
+
+Volume levels are maintained separately for speakers and headphones, restoring the appropriate level when switching.
+
+### Volume and Brightness Control
+
+**Volume**:
+- Range: 0-20 (user-facing scale)
+- Raw range: 0-100 (5x multiplier: `raw = value * 5`)
+- Control method: ALSA amixer via `system()` call
+- Command: `amixer cset name='Master Playback Volume' %`
+- Separate volume levels for speakers (default: 8) and headphones (default: 4)
+
+**Brightness**:
+- Range: 0-10 (user-facing scale)
+- Raw range: 0-8000 (inverted: lower values = brighter)
+- Control method: GPIO PWM device (`/dev/gpio-pwm`)
+- Mapping:
+ - 0 → 8000 (off)
+ - 5 → 5000 (mid)
+ - 10 → 0 (max brightness)
+
+### Input Event Monitoring
+
+The keymon daemon monitors **four input devices**:
+- `/dev/input/event0` through `/dev/input/event3`
+- Polls at 60Hz (16.666ms interval)
+- Handles button repeat with timing:
+ - Initial delay: 300ms
+ - Repeat interval: 100ms
+
+### CPU Affinity
+
+MinUI launcher runs pinned to CPU core 3:
+```bash
+taskset 8 /sdcard/.system/m17/paks/MinUI.pak/launch.sh
+```
+
+This may improve performance on this multi-core device by dedicating a core to the launcher.
+
+### Hardware Volume Button Workaround
+
+The platform includes a workaround for hardware volume buttons:
+```c
+case CODE_PLUS:
+case CODE_MINUS:
+ system("echo 0 > /sys/devices/platform/0gpio-keys/scaled");
+ SetVolume(GetVolume());
+ break;
+```
+
+This resets a hardware "scaled" flag and re-applies the current volume, likely to prevent conflicts between hardware volume controls and software volume management.
+
+## UI Layout Adjustments
+
+The M17's widescreen display uses optimized UI parameters:
+
+| Parameter | Value | Notes |
+|-----------|-------|-------|
+| `MAIN_ROW_COUNT` | 7 rows | Number of visible menu rows |
+| `FIXED_SCALE` | 1x | No UI scaling needed |
+| Screen ratio | 16:9 | Wider aspect ratio than 4:3 platforms |
+
+The 1x scale means the platform uses `assets.png` instead of `assets@2x.png` for UI elements.
+
+## Boot Logo Customization
+
+The M17 stores boot logos directly in the boot partition (`/dev/block/by-name/boot`). Technical details from notes.txt:
+
+### Extracting Boot Logos
+
+Different hardware revisions have different offsets:
+
+**Rev A:**
+- Horizontal logo: offset 4044800, size 31734 bytes
+- Vertical logo: offset 4087296, size 31734 bytes
+
+**Rev B:**
+- Horizontal logo: offset 4045312, size 31734 bytes
+- Vertical logo: offset 4087808, size 31734 bytes
+
+Extract command:
+```bash
+# Rev A horizontal
+dd if=/dev/block/by-name/boot of=/sdcard/logo-h.bmp bs=1 skip=4044800 count=31734
+```
+
+### Replacing Boot Logos
+
+```bash
+# Rev A horizontal (tested and working)
+dd conv=notrunc if=/sdcard/logo-h.bmp of=/dev/block/by-name/boot bs=1 seek=4044800
+```
+
+### Logo Format Requirements
+
+- **Dimensions**: 264x40 pixels (horizontal) or 40x264 (vertical, rotated)
+- **Format**: 24-bit BMP, Windows format
+- **Flipping**: DO NOT flip row order (opposite of runtime framebuffer images)
+- **Centering**: Logo appears centered in framebuffer at 1x scale
+- **Variable size**: Can use smaller dimensions (e.g., 100x100) within the size limit
+
+**Note:** The device uses the horizontal version of the logo by default.
+
+## Included Tools
+
+Standard MinUI tools are available:
+- **Clock.pak**: System clock/time display
+- **Input.pak**: Input configuration utility
+
+## Known Issues / Quirks
+
+### Hardware Quirks
+1. **Swapped Button Labels**: Physical button labels don't match logical mappings (A/B and X/Y swapped)
+2. **Dual Menu Buttons**: Two menu button indices (15 and 16) may represent different physical buttons or modes
+3. **CPU Affinity**: Launcher pinned to core 3 (taskset 8) - purpose unclear but may improve performance
+4. **Volume Button Workaround**: Hardware volume buttons require special handling to reset "scaled" flag
+5. **Cannot Disable Stock Volume Controls**: Hardware volume control (`gpio-volctrl.sh`) runs from read-only 500MB squashfs rootfs, making it impractical to patch or disable
+
+### Input System Quirks
+1. **Hybrid Input**: Platform defines both keyboard and joystick mappings for all buttons
+2. **No Evdev**: Despite evdev codes being defined in some systems, M17 doesn't use them (all CODE_NA)
+3. **Complex Joystick Indices**: Joystick button numbers are non-sequential (1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16)
+
+### Development Notes
+1. **No L3/R3**: Platform lacks clickable analog sticks
+2. **NEON Available**: May support ARM NEON SIMD (HAS_NEON defined) but uncertain
+3. **Separate Volume Profiles**: Speaker and headphone volumes are tracked independently
+4. **Embedded Boot Images**: Boot script includes base64-encoded ZIP file with splash images
+5. **Poweroff on Exit**: Boot script powers off device if launcher is removed (safety measure)
+
+### Boot Image Complexity
+- Runtime framebuffer images: 32-bit BMP, flipped row order, 480x272
+- Boot partition logos: 24-bit BMP, NOT flipped, 264x40 or smaller
+- Different header offsets between hardware revisions (Rev A vs Rev B)
+- Different display methods (dd to framebuffer vs. dd to boot partition)
+
+## Testing
+
+When testing changes:
+1. Test button combinations for volume/brightness (START+L1/R1, SELECT+L1/R1)
+2. Verify headphone jack detection and audio routing
+3. Test both keyboard and joystick input methods
+4. Check boot splash display during install/update
+5. Verify CPU affinity settings (taskset 8)
+6. Test repeat functionality for held buttons (300ms initial, 100ms repeat)
+7. Confirm poweroff behavior when launcher exits
+
+## Related Documentation
+
+- Main project docs: `../../README.md`
+- Platform abstraction: `../../all/common/defines.h`
+- Shared code: `../../all/minui/minui.c` (launcher), `../../all/minarch/minarch.c` (libretro frontend)
+- Build system: `../../Makefile` (host), `./makefile` (platform)
+- Platform header: `./platform/platform.h` (all hardware definitions)
+- Boot image notes: `./boot/notes.txt` (framebuffer and boot logo details)
+
+## Maintainer Notes
+
+The M17 platform demonstrates several unique characteristics:
+
+### Unique Features
+1. **Hybrid Input System**: One of few platforms defining both keyboard and joystick mappings
+2. **Embedded Boot Assets**: Boot script includes uuencoded ZIP of splash images
+3. **Headphone Monitoring**: Background thread for jack state detection
+4. **CPU Pinning**: Uses taskset for core affinity
+5. **16:9 Widescreen**: Unusual aspect ratio for retro handhelds
+6. **Boot Partition Access**: Direct access to boot partition for logo customization
+
+### Platform Complexity
+- Moderate input complexity (hybrid keyboard + joystick)
+- Complex boot image handling (multiple formats, embedded assets)
+- Hardware revision differences (Rev A vs Rev B offsets)
+- Advanced audio routing (separate speaker/headphone profiles)
+
+### Reference Value
+This platform is a good reference for:
+- Implementing hybrid input systems
+- Headphone jack detection and audio routing
+- Embedding assets in boot scripts
+- Direct framebuffer rendering
+- Separate volume profiles for different audio outputs
+
+Changes to this platform should account for the dual input methods and ensure both keyboard and joystick paths are tested.
diff --git a/workspace/magicmini/README.md b/workspace/magicmini/README.md
new file mode 100644
index 00000000..153757ae
--- /dev/null
+++ b/workspace/magicmini/README.md
@@ -0,0 +1,289 @@
+# Magic Mini (MagicX XU Mini M)
+
+Platform implementation for the Magic Mini retro handheld device.
+
+> [!WARNING]
+> **This platform is deprecated and will be removed in a future MinUI release.**
+>
+> **Reason**: RK3326 chipset scandal and supplier fraud issues affecting device availability and support.
+>
+> While the platform will continue to work with current MinUI releases, it will not receive new features or platform-specific bug fixes.
+
+## Hardware Specifications
+
+### Display
+- **Resolution**: 640x480 (VGA)
+- **Color Depth**: 16-bit RGB565 (runtime), 32-bit XRGB for boot images
+- **UI Scale**: 2x (uses `assets@2x.png`)
+- **Orientation**: Portrait mode (boot images rotated 90 degrees)
+
+### Input
+- **D-Pad**: Up, Down, Left, Right
+- **Face Buttons**: A, B, X, Y
+- **Shoulder Buttons**: L1, R1, L2, R2
+- **System Buttons**:
+ - MENU button
+ - POWER button
+ - Dedicated PLUS/MINUS volume buttons
+
+### Input Method
+- **Primary**: Joystick API (SDL joystick indices defined but currently unused)
+- **Active**: Evdev codes for volume/power buttons only
+- **No SDL Keyboard**: All keyboard mappings are `BUTTON_NA`
+
+### CPU & Performance
+- ARM processor with NEON SIMD support
+- No overclocking support
+
+### Power Management
+- Basic power button detection via evdev (CODE_POWER = 116)
+- No battery monitoring daemon
+
+### Storage
+- **Primary SD Card**: `/mnt/SDCARD` (internal/stock OS)
+- **Secondary SD Card**: `/storage/TF2` (MinUI installation location)
+
+## Platform Architecture
+
+The Magic Mini uses a unique dual-SD-card setup where:
+- **Internal SD** (`/mnt/SDCARD`): Contains stock OS and boot configuration
+- **External SD** (`/storage/TF2`): Contains all MinUI files, ROMs, and data
+
+This allows MinUI to coexist with the stock firmware by keeping all files on the second card.
+
+## Directory Structure
+
+```
+magicmini/
+├── platform/ Platform-specific hardware definitions
+│ └── platform.h Button mappings, display specs, paths
+├── keymon/ Hardware button monitoring daemon
+│ └── keymon.c Volume/brightness control via hardware buttons
+├── libmsettings/ Settings library (volume, brightness)
+├── install/ Installation assets and boot script
+│ ├── boot.sh Boot/update handler (becomes autostart.sh)
+│ ├── installing.bmp 32-bit BMP boot splash (640x480, rotated 90°)
+│ ├── updating.bmp 32-bit BMP update splash (640x480, rotated 90°)
+│ └── notes.txt Technical notes on BMP format
+├── cores/ Libretro cores (submodules + builds)
+└── other/ Third-party dependencies
+ └── 351files/ File manager tool (github.com/shauninman/351Files)
+```
+
+## Input System
+
+The Magic Mini has a **simplified input architecture**:
+
+1. **Joystick API**: Button indices are defined (JOY_A=0, JOY_B=1, etc.) but currently unused
+2. **Evdev Codes**: Only POWER and volume buttons (PLUS/MINUS) use evdev
+3. **No SDL Keyboard**: Platform does not use SDL keyboard events
+
+### Input Event Devices
+- **event2**: Gamepad/menu button input
+- **event3**: Volume button input (PLUS/MINUS)
+
+### Button Combinations
+
+| Combination | Function |
+|-------------|----------|
+| PLUS | Increase volume |
+| MINUS | Decrease volume |
+| MENU + PLUS | Increase brightness |
+| MENU + MINUS | Decrease brightness |
+| POWER | Sleep/wake device |
+| X (in launcher) | Resume from save state |
+
+### Hardware Button Quirks
+- **MENU button code**: 704 (in kernel space, different from standard SDL codes)
+- **Volume range**: 0-20 (MUTE_VOLUME_RAW = 0)
+- **Brightness range**: 0-10
+
+## Building
+
+### Prerequisites
+Requires Docker with Magic Mini cross-compilation toolchain.
+
+### Build Commands
+
+```bash
+# Enter platform build environment
+make PLATFORM=magicmini shell
+
+# Inside container: build all platform components
+cd /root/workspace/magicmini
+make
+
+# This builds:
+# - keymon (button monitoring daemon)
+# - libmsettings (settings library)
+# - 351Files (file manager tool)
+# - All libretro cores in cores/
+```
+
+### Dependencies
+The platform automatically clones required dependencies on first build:
+- **351Files**: `github.com/shauninman/351Files.git` (file manager)
+
+Note: Unlike most platforms, Magic Mini has no SDL dependency in its makefile.
+
+## Installation
+
+### File System Layout
+
+MinUI installs to the **secondary SD card** (`/storage/TF2`) with this structure:
+
+```
+/storage/TF2/
+├── .system/
+│ ├── magicmini/ Platform-specific binaries
+│ │ ├── bin/ Utilities (keymon, etc.)
+│ │ │ └── install.sh Post-update installation script
+│ │ └── paks/ Applications and emulators
+│ │ └── MinUI.pak/ Main launcher
+│ └── res/ Shared UI assets
+│ ├── assets@2x.png UI sprite sheet (2x scale)
+│ └── BPreplayBold-unhinted.otf
+├── Roms/ ROM files organized by system
+├── MinUI.zip Update package (if present)
+└── log.txt Installation/update log
+```
+
+### Stock OS Integration
+
+MinUI integrates with the stock firmware through boot scripts:
+
+**On internal SD** (`/mnt/SDCARD`):
+```
+SYSTEM.squashfs/
+├── usr/
+│ ├── bin/
+│ │ └── autostart.sh # Magic Mini's boot.sh gets installed here
+│ └── config/
+│ └── minui/
+│ ├── installing.bmp # Copied from install/installing.bmp
+│ └── updating.bmp # Copied from install/updating.bmp
+```
+
+The `autostart.sh` script runs on device boot and checks for MinUI updates on the secondary card.
+
+### Boot Process
+
+1. Device boots stock OS from internal SD
+2. Stock OS runs `/usr/bin/autostart.sh` (MinUI's boot.sh)
+3. Script checks for `MinUI.zip` on `/storage/TF2`
+4. If ZIP found:
+ - Display splash screen to framebuffer (`installing.bmp` or `updating.bmp`)
+ - Extract ZIP to `/storage/TF2`
+ - Delete ZIP file
+ - Run `.system/magicmini/bin/install.sh` to complete setup
+5. Launch MinUI via `.system/magicmini/paks/MinUI.pak/launch.sh`
+6. If launcher exits, shutdown device (prevents stock OS from interfering)
+
+#### Boot Image Display
+
+The platform uses a unique BMP display method:
+
+```bash
+dd if=/usr/config/minui/installing.bmp of=/dev/fb0 bs=71 skip=1
+echo 0,0 > /sys/class/graphics/fb0/pan
+```
+
+**Format Requirements**:
+- 640x480 resolution
+- 32-bit XRGB (X8 R8 G8 B8 format)
+- Rotated 90 degrees (portrait orientation)
+- Windows BMP format with flipped row order
+- Uses `bs=71 skip=1` to skip 70-byte header + 1 byte for color shift correction
+
+## Platform-Specific Features
+
+### Dual SD Card Architecture
+The Magic Mini's dual SD card setup provides:
+- **Isolation**: MinUI completely separate from stock OS
+- **Safety**: Stock firmware never touches MinUI data
+- **Flexibility**: Can remove secondary SD to boot stock OS normally
+
+### Direct Framebuffer Access
+Boot images are written directly to `/dev/fb0` using `dd` command rather than using SDL or other graphics libraries. This allows splash screens before MinUI fully initializes.
+
+### Audio Configuration
+Custom audio buffer size (`SAMPLES 400`) to reduce audio underruns in fceumm (NES emulator).
+
+### Volume Control
+- Mute value: `0` (simpler than other platforms using negative values)
+- Volume range: 0-20 (finer granularity than typical 0-10 scale)
+
+### Input Event Monitoring
+Uses **dual input devices**:
+- `/dev/input/event2`: Gamepad and MENU button
+- `/dev/input/event3`: Volume buttons (hardware dedicated buttons)
+
+This split allows the volume buttons to work independently of the main gamepad input.
+
+## Included Tools
+
+### Files.pak
+351Files-based file manager with scaled UI assets:
+- Multiple resolution support (24px, 32px, 48px, 58px, 64px icons)
+- Full file operations (copy, cut, paste, delete, rename)
+- Image preview support
+- Keyboard input for text entry
+
+### Clock.pak
+System clock/time display tool
+
+### Input.pak
+Input configuration utility
+
+## Known Issues / Quirks
+
+### Platform Quirks
+1. **Deprecated Status**: Platform marked as deprecated - newer MinUI features may not be supported
+2. **Dual SD Required**: Requires secondary SD card slot for MinUI installation
+3. **Portrait Boot Images**: Boot splash BMPs must be rotated 90 degrees
+4. **BMP Header Offset**: Uses `bs=71` instead of `bs=70` to correct color shifting issue
+5. **Joystick API Unused**: Despite having joystick indices defined, platform doesn't currently use SDL joystick input
+6. **Screen Sleep Issue**: Display doesn't fully turn off during sleep mode (backlight dims but doesn't blank)
+7. **Audio Choppy**: Audio stuttering persists in some games even with 400 sample buffer fix
+8. **Headphone Detection Unreliable**: GPIO `/sys/class/gpio/gpio86/value` always reads 1, making separate speaker/headphone volumes impractical (can only detect change events, not initial state)
+
+### Development Notes
+1. **No L3/R3**: Platform lacks clickable analog sticks
+2. **Simplified Input**: No SDL keyboard support, limited evdev codes
+3. **MENU Code Difference**: Kernel MENU button code (704) differs from typical SDL codes
+4. **Stock OS Dependency**: Requires stock firmware to handle initial boot sequence
+5. **Shutdown on Exit**: Boot script shutdowns device if MinUI exits (safety measure)
+
+### Input Limitations
+- Joystick button mappings are defined but **not currently used**
+- Most input handling may rely on stock OS or alternative methods not documented in platform.h
+- Only volume buttons and power button use evdev codes
+
+## Testing
+
+When testing changes:
+1. Verify boot splash displays correctly (check 90-degree rotation, color shift)
+2. Test on **secondary SD card** (`/storage/TF2`)
+3. Check volume control with PLUS/MINUS buttons
+4. Verify brightness control with MENU+PLUS/MINUS
+5. Confirm MinUI launches after update extraction
+6. Test shutdown behavior when launcher exits
+
+## Related Documentation
+
+- Main project docs: `../../README.md`
+- Platform abstraction: `../../all/common/defines.h`
+- Shared code: `../../all/minui/minui.c` (launcher), `../../all/minarch/minarch.c` (libretro frontend)
+- Build system: `../../Makefile` (host), `./makefile` (platform)
+- Platform header: `./platform/platform.h` (all hardware definitions)
+- Boot image notes: `./install/notes.txt` (BMP format details)
+
+## Maintainer Notes
+
+This platform represents an **alternative architecture** in MinUI:
+- Dual SD card installation (unique among MinUI platforms)
+- Direct framebuffer rendering for boot images
+- No SDL keyboard input (joystick or alternative method)
+- Integration with stock firmware rather than replacement
+
+While deprecated, it demonstrates MinUI's flexibility in adapting to different hardware constraints and installation methods. This approach may be useful reference for future platforms with similar dual-storage architectures.
diff --git a/workspace/miyoomini/README.md b/workspace/miyoomini/README.md
new file mode 100644
index 00000000..7cac93c6
--- /dev/null
+++ b/workspace/miyoomini/README.md
@@ -0,0 +1,273 @@
+# Miyoo Mini / Miyoo Mini Plus
+
+Platform implementation for the Miyoo Mini and Miyoo Mini Plus retro handheld devices.
+
+## Hardware Specifications
+
+### Display
+- **Resolution**: 640x480 (standard) or 752x560 (Plus variant with 560p screen)
+- **Color Depth**: 16-bit RGB565
+- **UI Scale**: 2x (uses `assets@2x.png`)
+- **Screen Detection**: Runtime detection via `is_560p` flag
+
+### Input
+- **D-Pad**: Up, Down, Left, Right
+- **Face Buttons**: A, B, X, Y
+- **Shoulder Buttons**: L1, R1, L2, R2
+- **System Buttons**:
+ - MENU button
+ - POWER button
+ - SELECT and START buttons
+ - **Plus only**: Dedicated PLUS/MINUS volume buttons
+
+### CPU & Performance
+- ARM processor with NEON SIMD support
+- Overclock/underclock capability via register manipulation
+- Performance governor set during boot
+
+### Power Management
+- **Standard Mini**: Battery monitoring via SAR ADC
+- **Plus**: Battery monitoring via AXP223 PMIC (I2C)
+- Charging detection support
+- Auto-sleep and power-off features
+
+### Storage
+- SD card mounted at `/mnt/SDCARD`
+
+## Platform Variants
+
+This platform supports two hardware variants detected at runtime:
+
+### Standard Miyoo Mini
+- 640x480 display
+- SAR ADC battery monitoring
+- Volume control via SELECT + L1/R1
+- Brightness control via START + L1/R1
+
+### Miyoo Mini Plus
+- Optional 752x560 display (560p)
+- AXP223 PMIC battery monitoring (`/customer/app/axp_test` present)
+- Dedicated hardware volume buttons (PLUS/MINUS)
+- Volume control also works with standalone VOLUMEUP/DOWN
+- Brightness control via MENU + VOLUMEUP/DOWN or MENU + L1/R1
+
+**Detection**: Variants are auto-detected at runtime by `keymon`. The `is_plus` and `is_560p` flags configure UI layout and input handling accordingly.
+
+## Directory Structure
+
+```
+miyoomini/
+├── platform/ Platform-specific hardware definitions
+│ └── platform.h Button mappings, display specs, variant flags
+├── keymon/ Hardware button monitoring daemon
+│ └── keymon.c Complex daemon with dual-variant support
+├── batmon/ Battery status overlay (uses AXP223 on Plus)
+├── lumon/ Screen backlight/brightness control
+├── blank/ Screen blanking utility
+├── show/ Boot splash screen display
+├── overclock/ CPU frequency adjustment via register access
+├── libmsettings/ Settings library (volume, brightness, etc.)
+├── install/ Installation assets and boot script
+│ ├── boot.sh Initial boot/update handler
+│ ├── installing.png Boot splash for fresh install (640x480)
+│ └── updating.png Boot splash for updates (640x480)
+├── cores/ Libretro cores (submodules + builds)
+└── other/ Third-party dependencies
+ ├── sdl/ Custom SDL 1.2 fork (miniui-miyoomini branch)
+ └── DinguxCommander/ File manager dependency
+```
+
+## Input System
+
+The Miyoo Mini uses a **hybrid input approach**:
+
+1. **SDL Keyboard Events**: Primary input method for most applications
+2. **Evdev Codes**: Direct kernel input codes for low-level monitoring (used by `keymon`)
+3. **No Joystick Input**: Platform does not use SDL joystick API
+
+### Button Combinations
+
+| Combination | Function | Model |
+|-------------|----------|-------|
+| SELECT + L1/R1 | Volume control | Standard only |
+| START + L1/R1 | Brightness control | Standard only |
+| VOLUMEUP/DOWN | Volume control | Plus only |
+| MENU + VOLUMEUP/DOWN | Brightness control | Plus only |
+| MENU + L1/R1 | Brightness control | Plus only |
+| MENU + POWER | System shutdown | Both |
+| X (in launcher) | Resume from save state | Both |
+| POWER | Sleep/wake device | Both |
+
+## Building
+
+### Prerequisites
+Requires Docker with Miyoo Mini cross-compilation toolchain.
+
+### Build Commands
+
+```bash
+# Enter platform build environment
+make PLATFORM=miyoomini shell
+
+# Inside container: build all platform components
+cd /root/workspace/miyoomini
+make
+
+# This builds:
+# - blank.elf (screen blanking)
+# - batmon.elf (battery monitor overlay)
+# - lumon.elf (backlight control)
+# - show.elf (boot splash display)
+# - overclock.elf (CPU frequency control)
+# - SDL library (custom fork)
+# - DinguxCommander (file manager)
+# - All libretro cores in cores/
+```
+
+### Dependencies
+The platform automatically clones required dependencies on first build:
+- **SDL 1.2**: `github.com/shauninman/SDL-1.2.git` (branch: `miniui-miyoomini`)
+- **DinguxCommander**: `github.com/shauninman/DinguxCommander.git` (branch: `miniui-miyoomini`)
+
+## Installation
+
+### File System Layout
+
+MinUI installs to the SD card with the following structure:
+
+```
+/mnt/SDCARD/
+├── .system/
+│ ├── miyoomini/ Platform-specific binaries
+│ │ ├── bin/ Utilities (batmon, lumon, overclock, etc.)
+│ │ └── paks/ Applications and emulators
+│ │ └── MinUI.pak/ Main launcher
+│ └── res/ Shared UI assets
+│ ├── assets@2x.png UI sprite sheet (2x scale)
+│ └── BPreplayBold-unhinted.otf
+├── .tmp_update/ Update staging area
+│ └── miyoomini/ Platform boot components
+│ ├── show.elf Splash screen display
+│ ├── installing.png Initial install splash
+│ └── updating.png Update splash
+├── Roms/ ROM files organized by system
+└── MinUI.zip Update package (if present)
+```
+
+### Boot Process
+
+1. Device boots and runs `miyoomini.sh` from `.tmp_update/`
+2. Script sets CPU governor to "performance"
+3. If `MinUI.zip` exists:
+ - Initialize backlight (PWM)
+ - Initialize LCD (trigger `/proc/ls`)
+ - Display `installing.png` (first install) or `updating.png` (update)
+ - Extract `MinUI.zip` to SD card
+ - Run `.system/miyoomini/bin/install.sh` to complete setup
+4. Launch MinUI via `.system/miyoomini/paks/MinUI.pak/launch.sh`
+5. If launcher exits, reboot (prevents stock firmware from accessing card)
+
+### Update Process
+
+To update MinUI on device:
+1. Place `MinUI.zip` in SD card root
+2. Reboot device
+3. Boot script auto-detects ZIP and performs update
+4. ZIP is deleted after successful extraction
+
+## Platform-Specific Features
+
+### LCD Initialization
+The platform requires a quirk to initialize the LCD:
+```bash
+cat /proc/ls # Triggers LCD initialization
+sleep 1
+export LCD_INIT=1
+```
+
+### Backlight Control
+Hardware PWM control via sysfs:
+```
+/sys/class/pwm/pwmchip0/export
+/sys/class/pwm/pwmchip0/pwm0/period = 800
+/sys/class/pwm/pwmchip0/pwm0/duty_cycle = 0-100
+```
+
+### CPU Frequency
+Direct register access to MPLL (Memory PLL):
+- Base address: `0x1F000000` (RIU register bank)
+- MPLL offset: `+0x103000*2`
+- Allows overclock/underclock adjustments
+
+### Battery Monitoring
+Two different methods based on variant:
+- **Standard**: SAR ADC readings
+- **Plus**: I2C communication with AXP223 PMIC at address `0x34` on `/dev/i2c-1`
+
+## UI Layout Adjustments
+
+The 560p variant uses different UI parameters:
+
+| Parameter | Standard (640x480) | 560p (752x560) |
+|-----------|-------------------|----------------|
+| `MAIN_ROW_COUNT` | 6 rows | 8 rows |
+| `PADDING` | 10px | 5px |
+| `PAGE_SCALE` | 3 | 2 (memory optimization) |
+
+These adjustments maximize visible content on the taller display while managing memory usage.
+
+## Included Tools
+
+### Files.pak
+DinguxCommander-based file manager with:
+- File operations (copy, cut, paste, delete, rename)
+- Directory navigation
+- Image preview support
+- Integrated with MinUI launcher
+
+### Remove Loading.pak
+Utility to disable the stock "loading" screen animation that appears before game launch.
+
+## Known Issues / Quirks
+
+### Hardware Quirks
+1. **LCD Init Required**: Must read `/proc/ls` to initialize LCD on boot
+2. **Variant Detection**: Plus model detected by presence of `/customer/app/axp_test`
+3. **Reboot on Exit**: Boot script forces reboot if launcher exits to prevent stock firmware access
+
+### Development Notes
+1. **No L3/R3**: Platform lacks clickable analog sticks
+2. **Hybrid Input**: Must handle both SDL keyboard and evdev codes for complete input coverage
+3. **Runtime Configuration**: Many constants (resolution, button mappings) are runtime-determined based on variant flags
+4. **NEON Optimizations**: Platform supports ARM NEON SIMD - use `HAS_NEON` define for optimized code paths
+
+### Volume Quirks
+- Mute volume value: `-60` (raw scale, not percentage)
+- Plus model has hardware volume buttons that work independently of button combinations
+
+## Testing
+
+When testing changes:
+1. Test on **both** standard Mini and Plus variants
+2. Verify 640x480 **and** 752x560 display modes
+3. Check battery monitoring on both SAR ADC and AXP223 PMIC
+4. Test volume/brightness controls with variant-specific button combinations
+5. Verify boot splash screens display correctly during install/update
+
+## Related Documentation
+
+- Main project docs: `../../README.md`
+- Platform abstraction: `../../all/common/defines.h`
+- Shared code: `../../all/minui/minui.c` (launcher), `../../all/minarch/minarch.c` (libretro frontend)
+- Build system: `../../Makefile` (host), `./makefile` (platform)
+- Platform header: `./platform/platform.h` (all hardware definitions)
+
+## Maintainer Notes
+
+This is one of the most popular MinUI platforms and serves as a reference implementation for:
+- Multi-variant runtime detection
+- Hybrid input handling (SDL + evdev)
+- Battery monitoring abstraction (ADC vs I2C)
+- Display resolution flexibility
+
+Changes to this platform should be thoroughly tested due to its wide user base and variant complexity.
diff --git a/workspace/my282/README.md b/workspace/my282/README.md
new file mode 100644
index 00000000..d9c9807d
--- /dev/null
+++ b/workspace/my282/README.md
@@ -0,0 +1,410 @@
+# MY282
+
+Platform implementation for the MY282 retro handheld device.
+
+## Hardware Specifications
+
+### Display
+- **Resolution**: 640x480 (VGA)
+- **Color Depth**: 16-bit RGB565
+- **UI Scale**: 2x (uses `assets@2x.png`)
+
+### Input
+- **D-Pad**: Up, Down, Left, Right
+- **Face Buttons**: A, B, X, Y
+- **Shoulder Buttons**: L1, R1, L2, R2
+- **System Buttons**:
+ - MENU button
+ - POWER button
+ - Dedicated PLUS/MINUS volume buttons
+ - SELECT and START buttons
+
+### Input Method
+- **Primary**: Joystick API (SDL joystick indices 0-18)
+- **Active**: Evdev code for POWER button only (CODE_POWER = 102)
+- **No SDL Keyboard**: All keyboard mappings are `BUTTON_NA`
+
+### CPU & Performance
+- ARM Cortex-A53 processor with NEON SIMD support
+- NEON-FP-ARMv8 floating point unit
+- Supports overclocking/underclocking via overclock utility
+- Performance governor set during boot
+
+### Power Management
+- Power button detection via evdev (CODE_POWER = 102, KEY_HOME)
+- System sleep/wake controlled by POWER button
+
+### Storage
+- SD card mounted at `/mnt/SDCARD`
+
+### Audio
+- Headphone jack support with automatic detection
+- Separate volume levels for headphones and speakers
+- Volume control via amixer
+
+## Directory Structure
+
+```
+my282/
+├── platform/ Platform-specific hardware definitions
+│ ├── platform.h Button mappings, display specs, input codes
+│ ├── makefile.env Toolchain settings (Cortex-A53)
+│ └── makefile.copy File copy rules for deployment
+├── keymon/ Hardware button monitoring daemon
+│ ├── keymon.c Volume/brightness control daemon
+│ └── credits.txt Attribution (based on TrimUI Smart implementation)
+├── libmsettings/ Settings library
+│ ├── msettings.c Volume/brightness persistence and control
+│ └── msettings.h Settings API header
+├── libmstick/ Joystick/analog stick input library
+│ └── mstick.h Analog stick API (-32768 to 32767 range)
+├── show/ Boot splash screen display utility
+│ └── show.c SDL2-based image display with rotation support
+├── overclock/ CPU frequency adjustment utility
+│ ├── makefile Build rules
+│ └── credits.txt Based on Steward-fu's A30 utils
+├── install/ Installation assets and boot script
+│ ├── boot.sh Boot/update handler
+│ ├── update.sh Post-update script (minimal/stub)
+│ ├── installing.png 640x480 PNG boot splash
+│ └── updating.png 640x480 PNG update splash
+├── cores/ Libretro cores
+│ ├── makefile Copies cores from rg35xx platform
+│ └── output/ Built libretro core binaries
+├── other/ Third-party dependencies
+│ ├── DinguxCommander-sdl2/ File manager (SDL2 version)
+│ ├── unzip60/ Unzip utility for package extraction
+│ └── squashfs/ Squashfs tools for filesystem management
+└── tests/ Platform-specific test utilities
+ ├── brightness/ Brightness control testing
+ ├── calibrate/ Input calibration
+ └── volume/ Volume control testing
+```
+
+## Input System
+
+The MY282 uses a **joystick-based input architecture**:
+
+1. **SDL Joystick API**: Primary input method with button indices 0-18
+2. **Evdev Codes**: Only POWER button uses evdev (code 102)
+3. **No SDL Keyboard**: Platform does not use SDL keyboard events
+4. **Dual Input Devices**: Monitors `/dev/input/event0` and `/dev/input/event3`
+
+### Joystick Button Mapping
+
+| Button | Index | Notes |
+|--------|-------|-------|
+| A | 0 | Primary action button |
+| B | 1 | Secondary/cancel button |
+| Y | 2 | Tertiary action |
+| X | 3 | Quaternary action |
+| L1 | 4 | Left shoulder |
+| R1 | 5 | Right shoulder |
+| SELECT | 6 | Select button |
+| START | 7 | Start/menu button |
+| MENU | 8 | System menu |
+| L2 | 9 | Left trigger |
+| R2 | 10 | Right trigger |
+| UP | 13 | D-pad up |
+| LEFT | 14 | D-pad left |
+| RIGHT | 15 | D-pad right |
+| DOWN | 16 | D-pad down |
+| MINUS | 17 | Volume down |
+| PLUS | 18 | Volume up |
+
+### Button Combinations
+
+| Combination | Function |
+|-------------|----------|
+| PLUS | Increase volume |
+| MINUS | Decrease volume |
+| MENU + PLUS | Increase brightness |
+| MENU + MINUS | Decrease brightness |
+| POWER | Sleep/wake device |
+| X (in launcher) | Resume from save state |
+
+### Input Event Quirks
+- **MENU button code**: Can be 1 or 354 in kernel space (keymon handles both)
+- **Volume range**: 0-20 (0 = muted)
+- **Brightness range**: 0-10 (non-linear mapping)
+- **Polling rate**: 60Hz (16.666ms interval)
+- **Repeat delay**: 300ms initial, 100ms subsequent
+
+## Building
+
+### Prerequisites
+Requires Docker with MY282 cross-compilation toolchain (ARM Cortex-A53).
+
+### Build Commands
+
+```bash
+# Enter platform build environment
+make PLATFORM=my282 shell
+
+# Inside container: build all platform components
+cd /root/workspace/my282
+make
+
+# This builds:
+# - keymon (button monitoring daemon)
+# - libmsettings (settings library with shared memory)
+# - libmstick (analog stick input library)
+# - show.elf (SDL2-based splash screen display)
+# - overclock.elf (CPU frequency control)
+# - DinguxCommander (file manager)
+# - unzip (package extraction)
+# - squashfs tools
+# - Copies libretro cores from rg35xx platform
+```
+
+### Toolchain Configuration
+
+The platform uses ARM Cortex-A53 toolchain settings:
+```makefile
+ARCH = -marm -mtune=cortex-a53 -mfpu=neon-fp-armv8 -mfloat-abi=hard -mcpu=cortex-a53
+LIBS = -flto -lmstick
+SDL = SDL2
+```
+
+### Dependencies
+
+The platform automatically clones required dependencies on first build:
+- **DinguxCommander-sdl2**: `github.com/shauninman/DinguxCommander-sdl2.git` (file manager)
+- **unzip60**: `github.com/shauninman/unzip60.git` (archive extraction)
+
+### Core Sharing
+
+MY282 shares libretro cores with the rg35xx platform due to similar ARM Cortex-A53 architecture. The cores makefile simply copies pre-built binaries from `../../rg35xx/cores/output/`.
+
+## Installation
+
+### File System Layout
+
+MinUI installs to the SD card with the following structure:
+
+```
+/mnt/SDCARD/
+├── .system/
+│ ├── my282/ Platform-specific binaries
+│ │ ├── bin/ Utilities (keymon, overclock, etc.)
+│ │ │ └── install.sh Post-update installation script
+│ │ └── paks/ Applications and emulators
+│ │ └── MinUI.pak/ Main launcher
+│ └── res/ Shared UI assets
+│ ├── assets@2x.png UI sprite sheet (2x scale)
+│ └── BPreplayBold-unhinted.otf
+├── .tmp_update/ Update staging area
+│ └── my282/ Platform boot components
+│ ├── show.elf Splash screen display
+│ ├── unzip Package extraction utility
+│ ├── installing.png Initial install splash
+│ └── updating.png Update splash
+├── .userdata/ Platform-specific user data
+│ └── my282/
+│ └── msettings.bin Settings persistence file
+├── Roms/ ROM files organized by system
+└── MinUI.zip Update package (if present)
+```
+
+### Boot Process
+
+1. Device boots and runs boot script from `.tmp_update/my282.sh`
+2. Script sets CPU governor to "performance" for optimal speed
+3. If `MinUI.zip` exists:
+ - Display `installing.png` (first install) or `updating.png` (update)
+ - Move old update directory to backup location
+ - Extract `MinUI.zip` to SD card using unzip utility
+ - Delete ZIP file
+ - Remove backup directory
+ - Run `.system/my282/bin/install.sh` to complete setup
+4. Launch MinUI via `.system/my282/paks/MinUI.pak/launch.sh`
+5. Keep relaunching while launcher exists (infinite loop)
+6. If launcher removed, execute `poweroff` to prevent stock firmware access
+
+### Update Process
+
+To update MinUI on device:
+1. Place `MinUI.zip` in SD card root (`/mnt/SDCARD/MinUI.zip`)
+2. Reboot device
+3. Boot script auto-detects ZIP and performs update
+4. ZIP is deleted after successful extraction
+5. MinUI launches automatically
+
+## Platform-Specific Features
+
+### Settings Persistence
+
+The platform uses a **shared memory architecture** for settings:
+- Settings stored in `/dev/shm/SharedSettings` (POSIX shared memory)
+- Keymon acts as "host" process managing settings
+- Other processes act as "clients" reading/writing shared state
+- Persisted to `/mnt/SDCARD/.userdata/my282/msettings.bin`
+
+Settings structure:
+```c
+struct Settings {
+ int version; // Version for future compatibility
+ int brightness; // 0-10 (non-linear mapping to hardware)
+ int headphones; // Headphone volume (0-20)
+ int speaker; // Speaker volume (0-20)
+ int jack; // Headphone jack detection (0/1)
+ int hdmi; // HDMI output detection (0/1, unused)
+};
+```
+
+### Brightness Control
+
+Non-linear brightness mapping via `/dev/disp` ioctl:
+
+| Level | Raw Value | Increment |
+|-------|-----------|-----------|
+| 0 | 3 | - |
+| 1 | 4 | +1 |
+| 2 | 5 | +1 |
+| 3 | 6 | +1 |
+| 4 | 8 | +2 |
+| 5 | 12 | +4 |
+| 6 | 16 | +4 |
+| 7 | 24 | +8 |
+| 8 | 72 | +48 |
+| 9 | 128 | +56 |
+| 10 | 255 | +127 |
+
+Uses `DISP_LCD_SET_BRIGHTNESS` ioctl (0x102) on `/dev/disp`.
+
+### Volume Control
+
+- **Raw range**: 0-100 (mapped from 0-20 scale)
+- **Control method**: amixer command (`amixer set 'headphone volume' N%`)
+- **Separate levels**: Headphone vs speaker (auto-switches on jack detection)
+- **Mute value**: 0
+
+### CPU Frequency Control
+
+The overclock utility (based on Steward-fu's A30 utils) provides CPU frequency adjustment. Unlike some platforms with direct register access, this platform uses a pre-built utility.
+
+### Analog Stick Support
+
+Platform includes `libmstick` library for analog stick input:
+```c
+void Stick_init(void);
+void Stick_quit(void);
+void Stick_get(int* x, int* y); // Returns -32768 to 32767
+```
+
+This is unique compared to other MinUI platforms which typically only have D-pad input.
+
+### Display Rotation Support
+
+The `show.elf` utility includes rotation detection:
+```c
+SDL_GetCurrentDisplayMode(0, &mode);
+if (mode.h > mode.w) rotate = 3; // 270 degrees if portrait
+```
+
+This allows proper splash screen display regardless of screen orientation.
+
+### Input Event Monitoring
+
+Keymon daemon monitors **two separate input devices**:
+- `/dev/input/event0`: Primary input events
+- `/dev/input/event3`: Secondary input events
+
+This dual-device approach ensures all hardware buttons are captured even if distributed across multiple kernel input nodes.
+
+### Stale Input Prevention
+
+After system sleep/resume, keymon ignores input for >1 second to prevent spurious button events:
+```c
+if (now - then > 1000) ignore = 1; // Ignore stale input
+```
+
+## Included Tools
+
+### Files.pak
+DinguxCommander-SDL2 based file manager with:
+- Full file operations (copy, cut, paste, delete, rename)
+- Directory navigation
+- SDL2 graphics rendering
+- Integrated with MinUI launcher
+
+### Clock.pak
+System clock/time display tool
+
+### Input.pak
+Input configuration utility
+
+## Known Issues / Quirks
+
+### Hardware Quirks
+1. **Dual Input Devices**: Button events split across event0 and event3
+2. **MENU Code Variance**: Keymon must handle both code 1 and 354 for MENU button
+3. **Shared Cores**: Uses rg35xx cores (same ARM Cortex-A53 architecture)
+4. **Infinite Launch Loop**: Boot script loops indefinitely to prevent stock OS access
+5. **Forced Poweroff**: Device powers off if MinUI launcher removed
+
+### Development Notes
+1. **No L3/R3**: Platform lacks clickable analog sticks
+2. **NEON Support**: HAS_NEON defined - use SIMD optimizations for performance-critical code
+3. **Joystick Input**: Unlike most MinUI platforms which use keyboard, MY282 uses joystick API
+4. **Settings Architecture**: Shared memory approach is more complex than simple file-based settings
+5. **60Hz Polling**: Keymon runs at 60Hz (16.666ms) for responsive button detection
+
+### Input Limitations
+- Power button (CODE_POWER = 102) only available via evdev, not SDL
+- MENU button has two different kernel codes requiring special handling
+- Volume buttons work through joystick indices (17/18) but also handled by keymon
+
+### Volume/Brightness Quirks
+- Brightness mapping is highly non-linear (exponential curve from level 7-10)
+- Volume controlled via shell command (amixer) not direct ioctl
+- Jack detection changes active volume setting (headphones vs speaker)
+- HDMI detection present but unused (always returns 0)
+
+## Testing
+
+When testing changes:
+1. Verify button input on both event0 and event3 devices
+2. Test volume control with PLUS/MINUS buttons
+3. Verify brightness control with MENU+PLUS/MINUS
+4. Check settings persistence across reboots
+5. Test headphone jack detection and volume switching
+6. Verify analog stick input if used by applications
+7. Confirm splash screens display correctly during install/update
+8. Test boot process with and without MinUI.zip present
+
+## Related Documentation
+
+- Main project docs: `../../README.md`
+- Platform abstraction: `../../all/common/defines.h`
+- Shared code: `../../all/minui/minui.c` (launcher), `../../all/minarch/minarch.c` (libretro frontend)
+- Build system: `../../Makefile` (host), `./makefile` (platform)
+- Platform header: `./platform/platform.h` (all hardware definitions)
+
+## Maintainer Notes
+
+The MY282 platform is notable for several unique characteristics:
+
+### Architectural Distinctions
+1. **Joystick-first input**: One of the few MinUI platforms using SDL joystick API instead of keyboard
+2. **Shared memory settings**: More sophisticated than file-only persistence
+3. **Dual input monitoring**: Keymon watches two event devices simultaneously
+4. **Analog stick support**: Unique among handheld platforms (via libmstick)
+5. **Core sharing**: Leverages rg35xx cores due to identical CPU architecture
+
+### Code Reuse
+- Toolchain settings identical to rg35xx (Cortex-A53)
+- Cores copied from rg35xx without rebuilding
+- Overclock utility derived from Miyoo A30 utils
+- Settings library similar to other platforms but with shared memory
+
+### Integration Points
+When modifying platform code, pay attention to:
+- Keymon must initialize settings as "host" process
+- All other processes are settings "clients"
+- Volume/brightness have separate headphone/speaker profiles
+- Input code differences between SDL (joystick) and kernel (evdev)
+- Non-linear brightness curve optimized for perceived brightness
+- 60Hz polling rate balances responsiveness vs CPU usage
+
+This platform demonstrates MinUI's flexibility in adapting to diverse input architectures (joystick vs keyboard) while maintaining consistent user experience across all supported devices.
diff --git a/workspace/my355/README.md b/workspace/my355/README.md
new file mode 100644
index 00000000..def971b3
--- /dev/null
+++ b/workspace/my355/README.md
@@ -0,0 +1,532 @@
+# Miyoo Flip (MY355)
+
+Platform implementation for the Miyoo Flip retro handheld device.
+
+## Hardware Specifications
+
+### Display
+- **Built-in Screen**: 640x480 (VGA resolution)
+- **HDMI Output**: 1280x720 (720p, runtime detection)
+- **Color Depth**: 16-bit RGB565
+- **UI Scale**: 2x (uses `assets@2x.png`)
+- **Rotation**: 270 degrees for built-in screen (disabled on HDMI)
+- **Dynamic Layout**: Adjusts UI parameters based on active output
+
+### Input
+- **D-Pad**: Up, Down, Left, Right
+- **Face Buttons**: A, B, X, Y
+- **Shoulder Buttons**: L1, R1, L2, R2, L3, R3
+- **Analog Sticks**: Left (X/Y) and Right (X/Y)
+- **System Buttons**:
+ - MENU button
+ - POWER button (sleep/wake)
+ - Dedicated PLUS/MINUS volume buttons
+ - SELECT and START buttons
+
+### Input Method
+- **Primary**: SDL2 Joystick API (analog sticks supported)
+- **Secondary**: Evdev codes for direct hardware access (keymon)
+- **No SDL Keyboard**: All keyboard mappings are `BUTTON_NA`
+
+### CPU & Performance
+- ARM processor (userspace CPU frequency control)
+- Performance governor with 4 speed levels:
+ - **Menu**: 600 MHz (minimal power)
+ - **Powersave**: 1104 MHz (battery-friendly)
+ - **Normal**: 1608 MHz (default)
+ - **Performance**: 1992 MHz (demanding games)
+
+### Power Management
+- Battery monitoring via sysfs (`/sys/class/power_supply/battery/capacity`)
+- AC charging detection
+- Backlight control with 11 brightness levels (0-10)
+- Auto-sleep and power-off features
+
+### Storage
+- SD card mounted at `/mnt/SDCARD`
+
+### Special Features
+- **Hall Sensor**: Lid open/close detection for auto-sleep
+- **HDMI Hotplug**: Runtime detection and automatic output switching
+- **Rumble Motor**: GPIO-controlled haptic feedback (GPIO20, disabled on HDMI)
+- **WiFi Status**: Network connectivity monitoring
+- **LED Indicator**: Work LED for sleep state indication
+- **Sharpness Modes**: Crisp (nearest-neighbor) and soft (linear) scaling
+- **Overlay Effects**: Scanlines and grid overlays with color tinting
+- **Headphone Jack**: Auto-detection with audio routing (GPIO150)
+
+## Platform Architecture
+
+The MY355 (Miyoo Flip) is unique in MinUI's platform lineup due to:
+
+1. **Clamshell Design**: Features hall sensor for lid detection, enabling automatic sleep when closed
+2. **Dual Display Support**: Seamlessly switches between built-in 640x480 screen and 720p HDMI output
+3. **Advanced Video Features**: Supports multi-pass rendering for crisp scaling, overlay effects, and dynamic rotation
+4. **Complex Settings System**: Uses shared memory for inter-process settings communication
+5. **Special Initialization**: Requires rootfs modification via init script for first-time setup
+
+## Directory Structure
+
+```
+my355/
+├── platform/ Platform-specific hardware definitions
+│ ├── platform.h Button mappings, display specs, HDMI config
+│ ├── platform.c Platform implementation (lid, HDMI, rumble, scaling)
+│ └── makefile.* Build configuration files
+├── keymon/ Hardware button monitoring daemon
+│ └── keymon.c Volume/brightness control, headphone/HDMI detection
+├── libmsettings/ Settings library (shared memory based)
+│ ├── msettings.c Volume, brightness, jack/HDMI state management
+│ └── msettings.h Settings API header
+├── show/ Boot splash screen display utility
+│ └── show.c SDL2-based PNG image display (with rotation)
+├── init/ Initial device setup (first install only)
+│ └── init.sh Rootfs modification script for MinUI integration
+├── install/ Installation assets and boot script
+│ ├── boot.sh Boot/update handler
+│ ├── installing.png Boot splash for fresh install (640x480)
+│ └── updating.png Boot splash for updates (640x480)
+├── cores/ Libretro cores (submodules + builds)
+└── other/ Third-party dependencies
+ ├── evtest/ Input event monitoring tool
+ ├── mkbootimg/ Boot image creation tool
+ ├── rsce-go/ Resource editing tool (Go)
+ ├── squashfs/ Squashfs filesystem tools
+ └── DinguxCommander-sdl2/ File manager dependency
+```
+
+## Input System
+
+The MY355 uses a **hybrid input approach**:
+
+1. **SDL2 Joystick API**: Primary input for gamepad and analog sticks
+2. **Evdev Codes**: Direct kernel input codes for low-level hardware monitoring (keymon uses HID codes)
+3. **No SDL Keyboard**: Platform does not use SDL keyboard events
+
+### Evdev Code Mappings
+
+The platform uses HID (Human Interface Device) scancodes for evdev:
+
+| Button | HID Code | Description |
+|--------|----------|-------------|
+| D-Pad Up/Down/Left/Right | 82/81/80/79 | Arrow keys |
+| SELECT | 228 | Left GUI (Windows key) |
+| START | 40 | Enter |
+| A | 44 | Space |
+| B | 224 | Left Control |
+| X | 225 | Left Shift |
+| Y | 226 | Left Alt |
+| L1 | 43 | Tab |
+| R1 | 42 | Backspace |
+| L2 | 75 | Page Up |
+| R2 | 78 | Page Down |
+| L3 | 230 | Left Alt (alt mapping) |
+| R3 | 229 | Right Shift |
+| MENU | 41 | Escape |
+| POWER | 102 | Home |
+| PLUS | 128 | Volume Up |
+| MINUS | 129 | Volume Down |
+
+### Button Combinations
+
+| Combination | Function |
+|-------------|----------|
+| PLUS | Increase volume |
+| MINUS | Decrease volume |
+| MENU + PLUS | Increase brightness |
+| MENU + MINUS | Decrease brightness |
+| POWER | Sleep/wake device |
+| X (in launcher) | Resume from save state |
+
+## Building
+
+### Prerequisites
+Requires Docker with MY355 cross-compilation toolchain and additional tools:
+- Go compiler (for rsce-go)
+- ARM cross-compiler
+- Squashfs tools
+- mkbootimg utilities
+
+### Build Commands
+
+```bash
+# Enter platform build environment
+make PLATFORM=my355 shell
+
+# Inside container: build all platform components
+cd /root/workspace/my355
+make
+
+# This builds:
+# - show.elf (boot splash display)
+# - keymon (button monitoring daemon)
+# - libmsettings.so (settings library)
+# - evtest (input event debugging tool)
+# - mkbootimg (boot image creation)
+# - rsce_tool (resource editing)
+# - squashfs tools
+# - DinguxCommander (file manager)
+# - All libretro cores in cores/
+```
+
+### Early Dependencies
+
+The platform requires several external tools built first via `make early`:
+- **evtest**: Input device event monitor
+- **mkbootimg**: Android boot image tool
+- **rsce-go**: Resource container editor (Go-based)
+- **DinguxCommander-sdl2**: File manager application
+
+These are automatically cloned and built on first run.
+
+## Installation
+
+### File System Layout
+
+MinUI installs to the SD card with the following structure:
+
+```
+/mnt/SDCARD/
+├── .system/
+│ ├── my355/ Platform-specific binaries
+│ │ ├── bin/ Utilities (keymon, etc.)
+│ │ │ └── install.sh Post-update installation script
+│ │ └── paks/ Applications and emulators
+│ │ └── MinUI.pak/ Main launcher
+│ └── res/ Shared UI assets
+│ ├── assets@2x.png UI sprite sheet (2x scale)
+│ ├── line-*.png Scanline overlay effects (various scales)
+│ ├── grid-*.png Grid overlay effects (various scales)
+│ └── BPreplayBold-unhinted.otf
+├── .tmp_update/ Update staging area
+│ └── my355/ Platform boot components
+│ ├── show.elf Splash screen display
+│ ├── installing.png Initial install splash
+│ └── updating.png Update splash
+├── Roms/ ROM files organized by system
+└── MinUI.zip Update package (if present)
+```
+
+### Initial Installation
+
+The MY355 requires a **one-time rootfs modification** to integrate MinUI with the stock system:
+
+1. Place installation files in `/miyoo355/app/355/` directory
+2. Run `init.sh` script which:
+ - Extracts current rootfs from `/dev/mtd3ro`
+ - Unpacks squashfs filesystem
+ - Backs up original `runmiyoo.sh` to `runmiyoo-original.sh`
+ - Injects MinUI launcher hook
+ - Repacks and flashes modified rootfs to `/dev/mtd3`
+ - Reboots device
+
+**Warning**: This process modifies system firmware. Backup important data first.
+
+### Boot Process
+
+After initialization, device boots as follows:
+
+1. Stock system runs modified `runmiyoo.sh` boot script
+2. Script sets CPU governor to "performance" mode
+3. If `MinUI.zip` exists on SD card:
+ - Display `installing.png` (first install) or `updating.png` (update)
+ - Extract ZIP to SD card root
+ - Delete ZIP file
+ - Run `.system/my355/bin/install.sh` to complete setup
+4. Launch MinUI via `.system/my355/paks/MinUI.pak/launch.sh`
+5. Loop: if launcher exits, relaunch (prevents stock firmware access)
+6. On critical failure: power off device
+
+### Update Process
+
+To update MinUI on device:
+1. Place `MinUI.zip` in SD card root (`/mnt/SDCARD/`)
+2. Reboot device
+3. Boot script auto-detects ZIP and performs update
+4. ZIP is deleted after successful extraction
+
+## Platform-Specific Features
+
+### Hall Sensor Lid Detection
+
+The clamshell design includes a hall sensor for automatic lid detection:
+
+```c
+#define LID_PATH "/sys/devices/platform/hall-mh248/hallvalue"
+```
+
+- **1** = Lid open (normal operation)
+- **0** = Lid closed (triggers auto-sleep)
+- Checked via `PLAT_lidChanged()` during main loop
+- Enables battery-saving auto-sleep when device is closed
+
+### HDMI Hotplug Detection
+
+HDMI connection is detected at runtime and updates video configuration:
+
+```c
+#define HDMI_STATE_PATH "/sys/class/drm/card0-HDMI-A-1/status"
+```
+
+When HDMI is connected:
+- Resolution changes from 640x480 to 1280x720
+- Screen rotation disabled (HDMI always landscape)
+- Rumble disabled (assumes external controller)
+- Volume set to maximum (external audio system)
+- UI layout adjusted: `MAIN_ROW_COUNT` increases from 6 to 8 rows
+- Brightness control disabled (HDMI backlight N/A)
+
+Detection happens on every frame flip, enabling hotplug without restart.
+
+### Headphone Jack Detection
+
+Automatic audio routing based on headphone connection:
+
+```c
+#define JACK_STATE_PATH "/sys/class/gpio/gpio150/value"
+```
+
+- **0** = Headphones plugged in (inverted logic)
+- **1** = No headphones (use speaker)
+- Monitored by keymon background thread (1 second polling)
+- Automatically switches ALSA playback path: `HP` (headphones) or `SPK` (speaker)
+- Separate volume settings for headphones vs speaker
+
+### Sharpness Modes
+
+The platform supports two scaling modes for pixel-perfect retro gaming:
+
+**SHARPNESS_SOFT** (default):
+- Linear interpolation scaling
+- Smooth appearance, good for most content
+
+**SHARPNESS_CRISP**:
+- Multi-pass rendering: nearest-neighbor upscale → linear downscale
+- Preserves pixel sharpness while avoiding harsh aliasing
+- Adjustable hard_scale factor (1x/2x/4x) based on source resolution
+- Creates intermediate texture at higher resolution for better clarity
+
+### Overlay Effects
+
+Support for scanline and grid overlays to simulate CRT displays:
+
+- **EFFECT_LINE**: Horizontal scanlines (7 different scales: 2px to 8px)
+- **EFFECT_GRID**: Pixel grid (6 different scales: 2px to 11px)
+- Color tinting support for DMG Game Boy green effect
+- Dynamic opacity adjustment based on grid size
+- Automatically scaled and positioned for aspect-correct rendering
+
+Overlay PNGs stored in `.system/res/` directory.
+
+### Settings System
+
+Uses **shared memory** (POSIX shm) for inter-process communication:
+
+```c
+#define SHM_KEY "/SharedSettings"
+```
+
+**Host Process** (keymon):
+- Creates shared memory segment
+- Loads persisted settings from `msettings.bin`
+- Monitors and updates hardware state (jack, HDMI)
+
+**Client Processes** (launcher, emulators):
+- Attach to existing shared memory
+- Read current settings (brightness, volume, jack/HDMI state)
+- Write changes which host persists
+
+Benefits:
+- No IPC overhead for reads
+- Settings survive process crashes
+- Consistent state across all applications
+
+### Brightness Scaling
+
+Non-linear brightness curve for better perceived brightness control:
+
+| Level | Raw Value | Perceived Brightness |
+|-------|-----------|----------------------|
+| 0 | 1 | Minimal (not off) |
+| 1 | 6 | Very dim |
+| 2 | 10 | Dim |
+| 3 | 16 | Low |
+| 4 | 32 | Below medium |
+| 5 | 48 | Medium-low |
+| 6 | 64 | Medium |
+| 7 | 96 | Medium-high |
+| 8 | 128 | Bright |
+| 9 | 192 | Very bright |
+| 10 | 255 | Maximum |
+
+Curve follows roughly logarithmic progression to match human perception.
+
+### Volume System
+
+Separate volume settings for different audio outputs:
+
+- **Speaker**: Default 8/20 (40%)
+- **Headphones**: Default 4/20 (20%, quieter for ear safety)
+- **HDMI**: Fixed 100/100 (maximum, delegate to external system)
+
+Volume conversion:
+```c
+int raw_volume = user_volume * 5; // 0-20 → 0-100
+```
+
+Special mute handling:
+- Mute sets ALSA playback path to `OFF` (not just volume 0)
+- Prevents white noise on speaker mute
+- Headphones still routed when muted (for cleaner audio)
+
+### WiFi Status Monitoring
+
+Piggybacks on battery status polling to check WiFi:
+
+```c
+getFile("/sys/class/net/wlan0/operstate", status, 16);
+online = prefixMatch("up", status);
+```
+
+Displayed in UI when available, enables network-based features.
+
+### Rumble Control
+
+Simple GPIO-based haptic feedback:
+
+```c
+#define RUMBLE_PATH "/sys/class/gpio/gpio20/value"
+```
+
+- Binary control: 0=off, 1=on (no strength variation)
+- Automatically disabled when HDMI active
+- Used for in-game feedback in supported cores
+
+### LED Indicator
+
+Work LED indicates sleep state:
+
+```c
+#define LED_PATH "/sys/class/leds/work/brightness"
+```
+
+- **255**: Device asleep (backlight off)
+- **0**: Device active (backlight on)
+
+Provides visual feedback when lid is closed or device sleeping.
+
+## UI Layout Adjustments
+
+Dynamic UI parameters based on active display output:
+
+| Parameter | Built-in Screen (640x480) | HDMI Output (1280x720) |
+|-----------|---------------------------|------------------------|
+| `MAIN_ROW_COUNT` | 6 rows | 8 rows |
+| `PADDING` | 10px | 40px |
+| Resolution | 640x480 | 1280x720 |
+| Rotation | 270° | None |
+
+These adjustments maximize visible content and maintain proper spacing on different displays.
+
+## Included Tools
+
+### Files.pak
+DinguxCommander-SDL2 based file manager with:
+- Full SDL2 support with rotation
+- File operations (copy, cut, paste, delete, rename)
+- Directory navigation
+- Image preview support
+- Integrated with MinUI launcher
+
+## Known Issues / Quirks
+
+### Hardware Quirks
+1. **Rootfs Modification Required**: First install requires system firmware modification (irreversible without backup)
+2. **Clamshell Design**: Hall sensor enables lid detection but requires careful handling
+3. **HDMI Hotplug**: While supported, frequent cable swapping may cause brief visual glitches
+4. **Rotation Overhead**: 270-degree rotation adds minimal overhead but is always active on built-in screen
+5. **Rumble Quality**: Vibration motor feels low quality (subjective)
+6. **HDMI Performance**: Minarch runs at 30fps over HDMI instead of 60fps; UI padding reverts to 640x480 layout after first dirty frame
+
+### Development Notes
+1. **Go Dependency**: Build system requires Go compiler for rsce-go tool
+2. **Complex Init**: Initial setup script modifies MTD flash partitions (high-risk operation)
+3. **Shared Memory**: Settings system requires proper cleanup on abnormal termination
+4. **Dual Input Devices**: keymon reads `/dev/input/event0` for hardware buttons
+5. **NEON Support**: Platform lacks NEON SIMD (`HAS_NEON` is commented out in platform.h)
+
+### Input Quirks
+- Uses HID scancodes instead of typical Linux event codes
+- Analog stick axes: LX=0, LY=1, RX=4, RY=3 (non-sequential)
+- Button code 704 for MENU in keymon vs code 41 (Escape) in evdev
+
+### Audio Quirks
+- Custom sample buffer size (`SAMPLES 400`) to reduce audio underruns in fceumm
+- Mute implemented via playback path change, not volume
+- Always sets volume to 1% before target to ensure ALSA registers change
+- **Headphone mute static**: Muting headphones produces static noise instead of silence (hardware limitation, left at 0 volume as workaround)
+
+### Video Quirks
+- Rotation applied via `SDL_RenderCopyEx` with 90-degree increments
+- Crisp mode creates large intermediate textures (memory intensive for high resolutions)
+- Effect overlays require exact pixel alignment for proper tiling
+
+## Testing
+
+When testing changes:
+1. Test on **both** built-in screen and HDMI output
+2. Verify lid detection and auto-sleep functionality
+3. Check volume/brightness controls with button combinations
+4. Test headphone jack detection and audio routing
+5. Verify rumble works and disables on HDMI
+6. Test WiFi status indicator accuracy
+7. Validate sharpness modes (soft vs crisp) at various resolutions
+8. Check overlay effects at different scale factors
+9. Verify boot splash screens display correctly during install/update
+10. Test settings persistence across reboots
+
+## Related Documentation
+
+- Main project docs: `../../README.md`
+- Platform abstraction: `../../all/common/defines.h`
+- Shared code: `../../all/minui/minui.c` (launcher), `../../all/minarch/minarch.c` (libretro frontend)
+- Build system: `../../Makefile` (host), `./makefile` (platform)
+- Platform header: `./platform/platform.h` (all hardware definitions)
+- Platform implementation: `./platform/platform.c` (advanced features)
+
+## Maintainer Notes
+
+The MY355 (Miyoo Flip) represents one of the most **feature-complete** implementations in MinUI:
+
+### Advanced Features
+- Hall sensor lid detection (unique among MinUI platforms)
+- Runtime HDMI hotplug with automatic reconfiguration
+- Multi-pass rendering for crisp pixel scaling
+- Overlay effects system (scanlines/grids)
+- Shared memory settings architecture
+- Dual analog stick support
+- Haptic feedback (rumble)
+- WiFi status monitoring
+
+### Reference Implementation For
+- Clamshell/flip device support
+- Dynamic display switching (built-in screen ↔ HDMI)
+- Advanced video scaling techniques
+- Inter-process communication via shared memory
+- Complex platform initialization (rootfs modification)
+
+### Complexity Considerations
+This platform has higher complexity than most others due to:
+- Initial rootfs modification requirement
+- Dual-display support with hotplug
+- Shared memory IPC between processes
+- Multi-pass rendering pipeline
+- Runtime feature detection (lid, HDMI, headphones, WiFi)
+
+Changes to this platform should be thoroughly tested across all feature combinations due to the complexity and interdependencies. Pay special attention to:
+- HDMI hotplug behavior
+- Settings persistence and shared memory cleanup
+- Video pipeline performance with overlay effects
+- Lid detection reliability
+
+This platform showcases MinUI's ability to support sophisticated hardware features while maintaining the project's core philosophy of simplicity and cross-platform consistency.
diff --git a/workspace/rg35xx/README.md b/workspace/rg35xx/README.md
new file mode 100644
index 00000000..35bec2c7
--- /dev/null
+++ b/workspace/rg35xx/README.md
@@ -0,0 +1,382 @@
+# Anbernic RG35XX
+
+Platform implementation for the Anbernic RG35XX retro handheld device.
+
+## Hardware Specifications
+
+### Display
+- **Resolution**: 640x480 (VGA)
+- **Color Depth**: 16-bit RGB565
+- **UI Scale**: 2x (uses `assets@2x.png`)
+- **Framebuffer**: `/dev/fb0`
+
+### Input
+- **D-Pad**: Up, Down, Left, Right
+- **Face Buttons**: A, B, X, Y
+- **Shoulder Buttons**: L1, R1, L2, R2
+- **System Buttons**:
+ - MENU button
+ - POWER button
+ - SELECT and START buttons
+ - Dedicated PLUS/MINUS volume buttons
+
+### Input Method
+- **Primary**: SDL Keyboard (Japanese input key mappings)
+- **Secondary**: Evdev codes for low-level hardware monitoring
+- **No Joystick**: Platform does not use SDL joystick API
+
+### Input Quirk: Japanese Key Mappings
+The RG35XX hardware uses **unusual Japanese input keys** for button mappings:
+- D-Pad uses: `SDLK_KATAKANA`, `SDLK_HIRAGANA`, `SDLK_HENKAN`, `SDLK_KATAKANAHIRAGANA`
+- Face buttons use: `SDLK_MUHENKAN` (A), `SDLK_KP_JPCOMMA` (B), etc.
+
+This is a hardware quirk specific to the RG35XX's button driver implementation.
+
+### CPU & Performance
+- ARM processor with NEON SIMD support
+- Overclock/underclock capability via direct register access
+- Voltage control via I2C PMIC interface
+- CMU (Clock Management Unit) base address: `0xB0160000`
+
+### CPU Frequency Profiles
+```
+1488 MHz @ 1.375V - Performance + launch (max)
+1392 MHz @ 1.325V
+1296 MHz @ 1.275V - Normal
+1200 MHz @ 1.200V
+1104 MHz @ 1.175V - Powersave
+1008 MHz @ 1.100V - Anbernic default max (overvolted)
+ 840 MHz @ 1.075V
+ 720 MHz @ 1.025V
+ 504 MHz @ 1.000V - Menu browsing
+ 240 MHz @ 0.975V - Minimum
+```
+
+All frequencies are overvolted for stability compared to stock values.
+
+### Power Management
+- Battery monitoring via msettings library
+- Headphone jack detection via sysfs (`/sys/class/switch/h2w/state`)
+- Backlight power control (`/sys/class/backlight/backlight.2/bl_power`)
+- Auto-sleep and power-off features
+
+### Storage
+- **Primary partition**: `/mnt/mmc` (ROMs partition, TF1)
+- **Secondary partition**: `/mnt/sdcard` (TF2, optional)
+- **SD Card Path**: `/mnt/sdcard` (with fallback symlink to `/mnt/mmc` if TF2 unavailable)
+
+## Platform Architecture
+
+### Dual Partition System
+The RG35XX uses a flexible dual-partition approach:
+- **TF1** (`/mnt/mmc`): Primary ROMS partition
+- **TF2** (`/mnt/sdcard`): Optional secondary partition
+
+Boot script detects which partition contains MinUI (`.system/rg35xx` or `MinUI.zip`) and creates symlinks accordingly. This allows MinUI to work with single or dual TF card setups.
+
+### Boot Firmware Integration
+MinUI runs through a custom ramdisk (`ramdisk.img`) and boot script (`dmenu.bin`) installed in the `/misc` partition:
+- Ramdisk provides chroot environment with ext2 filesystem (`rootfs.ext2`)
+- Boot script mounts SD cards and launches MinUI
+- Falls back to stock `dmenu.bin` if MinUI is not installed
+
+## Directory Structure
+
+```
+rg35xx/
+├── platform/ Platform-specific hardware definitions
+│ └── platform.h Button mappings, display specs, Japanese key codes
+├── keymon/ Hardware button monitoring daemon
+│ └── keymon.c Volume/brightness control, headphone detection
+├── libmsettings/ Settings library (volume, brightness, jack)
+│ └── msettings.c Shared memory settings with sysfs hardware access
+├── overclock/ CPU frequency/voltage adjustment utility
+│ └── overclock.c Direct CMU register access + I2C PMIC control
+├── boot/ Boot assets and initialization script
+│ ├── boot.sh Main boot script (becomes /misc/dmenu.bin)
+│ ├── build.sh Packages boot assets into boot.sh
+│ ├── boot_logo.png Boot splash (2.5KB PNG)
+│ ├── installing.bmp Fresh install splash (640x480, 32-bit BMP)
+│ └── updating.bmp Update splash (640x480, 32-bit BMP)
+├── install/ Post-update installation handler
+│ └── install.sh Updates /misc partition with new ramdisk/boot files
+├── ramdisk/ Custom ramdisk assets
+│ ├── patched-ramdisk.img Modified ramdisk with custom charging screen
+│ ├── charging.png Custom charging graphic (uses /misc/charging.png)
+│ └── readme.txt Ramdisk modification instructions
+├── cores/ Libretro cores (submodules + builds)
+└── other/ Third-party dependencies
+ └── DinguxCommander/ File manager (minui-rg35xx branch)
+```
+
+## Input System
+
+The RG35XX uses a **hybrid dual-input approach**:
+
+1. **SDL Keyboard Events**: Primary input method with Japanese key quirk
+2. **Evdev Codes**: Direct kernel input codes for `keymon` hardware monitoring
+3. **No Joystick Input**: Platform does not use SDL joystick API
+
+### Button Combinations
+
+| Combination | Function |
+|-------------|----------|
+| PLUS | Increase volume |
+| MINUS | Decrease volume |
+| MENU + PLUS | Increase brightness |
+| MENU + MINUS | Decrease brightness |
+| MENU + POWER | System shutdown |
+| X (in launcher) | Resume from save state |
+| POWER | Sleep/wake device |
+
+### Input Event Devices
+Keymon monitors multiple input devices:
+- `/dev/input/event0`: Gamepad input
+- `/dev/input/event1`: Additional input device
+
+## Building
+
+### Prerequisites
+Requires Docker with RG35XX cross-compilation toolchain.
+
+### Build Commands
+
+```bash
+# Enter platform build environment
+make PLATFORM=rg35xx shell
+
+# Inside container: build all platform components
+cd /root/workspace/rg35xx
+make
+
+# This builds:
+# - keymon (button monitoring daemon)
+# - overclock (CPU frequency utility)
+# - libmsettings (settings library)
+# - boot.sh with embedded assets (via build.sh)
+# - DinguxCommander (file manager)
+# - All libretro cores in cores/
+```
+
+### Dependencies
+The platform automatically clones required dependencies on first build:
+- **DinguxCommander**: `github.com/shauninman/DinguxCommander.git` (branch: `minui-rg35xx`)
+
+## Installation
+
+### File System Layout
+
+MinUI installs to the SD card with the following structure:
+
+```
+/mnt/sdcard/ (or /mnt/mmc if single partition)
+├── .system/
+│ ├── rg35xx/ Platform-specific binaries
+│ │ ├── bin/ Utilities (keymon, overclock, install.sh)
+│ │ ├── paks/ Applications and emulators
+│ │ │ └── MinUI.pak/ Main launcher
+│ │ ├── dat/ Boot partition files (ramdisk.img, dmenu.bin)
+│ │ └── rootfs.ext2 Chroot filesystem image
+│ └── res/ Shared UI assets
+│ ├── assets@2x.png UI sprite sheet (2x scale)
+│ └── BPreplayBold-unhinted.otf
+├── Roms/ ROM files organized by system
+└── MinUI.zip Update package (if present)
+```
+
+### Boot Partition Layout (`/misc`)
+
+MinUI modifies the `/misc` partition during installation:
+
+```
+/misc/
+├── dmenu.bin MinUI boot script (boot.sh)
+├── ramdisk.img Custom ramdisk with MinUI environment
+├── boot_logo.bmp.gz Boot splash (only installed, never updated)
+├── charging.png Custom charging graphic (only installed, never updated)
+└── .minstalled Flag file indicating MinUI is installed
+```
+
+### Boot Process
+
+1. Stock firmware boots and runs `/misc/dmenu.bin` (MinUI's boot.sh)
+2. Script mounts SD card partitions (TF1 at `/mnt/mmc`, TF2 at `/mnt/sdcard`)
+3. Detects which partition contains MinUI by checking for `.system/rg35xx` or `MinUI.zip`
+4. Creates symlink if needed to unify partition access
+5. If `MinUI.zip` exists:
+ - Display splash screen based on install state (installing.bmp or updating.bmp)
+ - Set framebuffer to 640x480x16
+ - Extract splash images from uuencoded data in boot script
+ - Display appropriate splash to `/dev/fb0`
+ - Extract `MinUI.zip` to SD card
+ - Delete ZIP file
+ - Run `.system/rg35xx/bin/install.sh` to update `/misc` partition
+ - Reboot device
+6. Check for `rootfs.ext2` (required for MinUI)
+7. If missing, fall back to stock `dmenu.bin`
+8. Setup loopback device and mount rootfs as chroot environment
+9. Bind mount system directories (`/dev`, `/proc`, `/sys`, etc.)
+10. `chroot` into rootfs and launch MinUI via `launch.sh`
+11. On exit: unmount, detach loopback, reboot device
+
+### Update Process
+
+To update MinUI on device:
+1. Place `MinUI.zip` in SD card root
+2. Reboot device
+3. Boot script auto-detects ZIP and performs update
+4. Install script checks MD5 checksums of `/misc` files
+5. Only updates `/misc` if files have changed (preserves custom boot logo)
+6. Device automatically reboots after update
+
+### Install Script Behavior
+
+The `install.sh` script is intelligent about updates:
+- **First install**: Backs up original files to `/mnt/mmc/bak/`, installs all files
+- **Updates**: Compares MD5 checksums before updating
+- **Never overwrites**: `boot_logo.bmp.gz` or `charging.png` (user customization preserved)
+- **Always updates**: `dmenu.bin` and `ramdisk.img` if changed
+
+## Platform-Specific Features
+
+### Brightness Control
+Hardware PWM control via sysfs with 11 brightness levels (0-10):
+
+| Level | Raw Value | Increment |
+|-------|-----------|-----------|
+| 0 | 16 | - |
+| 1 | 24 | 8 |
+| 2 | 40 | 16 |
+| 3 | 64 | 24 |
+| 4 | 128 | 64 |
+| 5 | 192 | 64 |
+| 6 | 256 | 64 |
+| 7 | 384 | 128 |
+| 8 | 512 | 128 |
+| 9 | 768 | 256 |
+| 10 | 1024 | 256 |
+
+Path: `/sys/class/backlight/backlight.2/brightness`
+
+### Volume Control
+Volume range: 0-20 (finer granularity than typical 0-10 scale)
+- Raw range: 0-40 (multiplied by 2)
+- Separate settings for speaker and headphones
+- Automatic switching based on jack state
+- Path: `/sys/class/volume/value`
+
+### Headphone Jack Detection
+Background thread in `keymon` polls jack state every second:
+- Path: `/sys/class/switch/h2w/state`
+- Automatically switches volume profile when headphones are plugged/unplugged
+
+### CPU Frequency Control
+The overclock utility provides direct CMU register manipulation:
+- Register access via `/dev/mem` at `0xB0160000`
+- Voltage control via I2C device `/sys/class/i2c-adapter/i2c-1/1-0065/reg_dbg`
+- Always sets voltage to maximum before changing frequency (safety)
+- Then adjusts to target voltage for stability
+
+Voltage formula: `((volts - 700000) / 25000) << 7 | 0xe04e`
+
+### Chroot Environment
+MinUI runs in a chroot environment from `rootfs.ext2`:
+- Loopback mounted at `/cfw` via `/dev/block/loop7`
+- Provides isolated userspace with necessary libraries
+- System directories bind-mounted from host (`/dev`, `/proc`, `/sys`)
+- Allows MinUI to use different library versions than stock OS
+
+### Custom Charging Screen
+The ramdisk is patched to use a custom charging graphic:
+- Stock charger binary modified via `sed` to always use `/misc/charging.png`
+- User can replace `charging.png` for custom charging screen
+- Change persists across updates (install script doesn't overwrite)
+
+## Included Tools
+
+### Files.pak
+DinguxCommander-based file manager with:
+- File operations (copy, cut, paste, delete, rename)
+- Directory navigation
+- Image preview support
+- Integrated with MinUI launcher
+
+## Known Issues / Quirks
+
+### Hardware Quirks
+1. **Japanese Key Mappings**: SDL buttons use unusual Japanese input key codes (Katakana, Hiragana, etc.)
+2. **Dual Partition Detection**: Complex boot logic to support single or dual TF card configurations
+3. **Chroot Requirement**: MinUI requires `rootfs.ext2` and cannot run directly on stock firmware
+4. **Reboot on Exit**: Boot script forces reboot if MinUI exits to prevent system instability
+
+### Development Notes
+1. **No L3/R3**: Platform lacks clickable analog sticks
+2. **Evdev + SDL**: Must handle both SDL keyboard and evdev codes for complete functionality
+3. **Register Access**: Overclock requires `/dev/mem` access and `mmap()` for CMU registers
+4. **I2C Voltage Control**: PMIC voltage adjustment uses I2C sysfs interface (device `1-0065`)
+5. **UUencoded Boot Images**: Boot script embeds splash images as uuencoded binary data
+6. **Custom Ramdisk**: Ramdisk modification requires `u-boot-tools` for CRC recalculation
+
+### Volume Quirks
+- Raw volume scale (0-40) is different from user-facing scale (0-20)
+- Separate volume settings for headphones vs speaker
+- Mute value: 0 (raw scale)
+
+### Boot Image Format
+- Installing/updating BMPs are 640x480, 32-bit XRGB format
+- Embedded in boot.sh via `uuencode` to avoid separate file dependencies
+- Extracted to `/tmp` during boot and displayed directly to framebuffer
+
+### Ramdisk Patching
+Custom ramdisk cannot be created by simple hex editing due to CRC checksum:
+1. Strip 64-byte header from stock ramdisk
+2. Unpack with `cpio`
+3. Modify `charger` binary with `sed`
+4. Repack with `cpio` and `mkimage` (recreates header with correct CRC)
+
+## Testing
+
+When testing changes:
+1. Test with **both single and dual partition** SD card configurations
+2. Verify boot splash displays correctly during install and update
+3. Check volume control with PLUS/MINUS buttons
+4. Verify brightness control with MENU + PLUS/MINUS
+5. Test headphone jack detection and automatic volume switching
+6. Verify overclock utility doesn't cause instability
+7. Confirm `/misc` partition updates work correctly
+8. Test fallback to stock `dmenu.bin` when `rootfs.ext2` is missing
+
+## Related Documentation
+
+- Main project docs: `../../README.md`
+- Platform abstraction: `../../all/common/defines.h`
+- Shared code: `../../all/minui/minui.c` (launcher), `../../all/minarch/minarch.c` (libretro frontend)
+- Build system: `../../Makefile` (host), `./makefile` (platform)
+- Platform header: `./platform/platform.h` (all hardware definitions)
+- Ramdisk notes: `./ramdisk/readme.txt` (modification instructions)
+
+## Maintainer Notes
+
+This platform demonstrates several **unique architectural patterns** in MinUI:
+
+1. **Chroot-based execution**: Only platform that runs entirely in a chrooted environment
+2. **Boot partition modification**: Directly modifies `/misc` partition for firmware integration
+3. **Japanese key mappings**: Hardware quirk requiring unusual SDL key codes
+4. **Direct register access**: Low-level CMU and PMIC manipulation for overclocking
+5. **Flexible partition detection**: Sophisticated logic for single/dual TF card support
+6. **Embedded boot assets**: UUencoded images in shell script to minimize dependencies
+
+The RG35XX is a popular and actively used platform. Changes should be thoroughly tested, especially:
+- Boot script logic (affects system stability)
+- Overclock values (can cause hardware instability)
+- `/misc` partition updates (incorrect updates can brick the device)
+
+### Performance Considerations
+
+- Default frequency: 1008 MHz (Anbernic stock max)
+- Menu browsing: 504 MHz (power savings)
+- Normal gaming: 1296 MHz
+- Performance gaming: 1488 MHz
+- All frequencies are **overvolted** compared to manufacturer specs for stability
+
+The overclock utility is conservative and has been tested across many devices, but users should be warned that overclocking can reduce hardware lifespan.
diff --git a/workspace/rg35xxplus/README.md b/workspace/rg35xxplus/README.md
new file mode 100644
index 00000000..52ff51b2
--- /dev/null
+++ b/workspace/rg35xxplus/README.md
@@ -0,0 +1,449 @@
+# Anbernic RG35XX Plus / H / SP
+
+Platform implementation for the Anbernic RG35XX Plus series retro handheld devices.
+
+## Hardware Specifications
+
+### Display
+- **Resolution**: Variable by model (runtime-detected)
+ - RG35XX Plus: 640x480 (VGA)
+ - RG35XX H (CubeXX): 720x720 (square)
+ - RG35XX SP (RG34XX): 720x480 (widescreen)
+- **HDMI Output**: 1280x720 (720p) - all variants
+- **Color Depth**: 16-bit RGB565
+- **UI Scale**: 2x (uses `assets@2x.png`)
+- **Orientation**: Supports rotated framebuffer (480x640) on some variants
+
+### Input
+- **D-Pad**: Up, Down, Left, Right
+- **Face Buttons**: A, B, X, Y
+- **Shoulder Buttons**: L1, R1, L2, R2
+- **System Buttons**:
+ - MENU button
+ - POWER button (hardware code 102, KEY_HOME)
+ - SELECT and START buttons
+ - Dedicated PLUS/MINUS volume buttons
+
+### Input Method
+- **Primary**: Joystick API (SDL joystick indices)
+- **Hardware codes**: Evdev codes for power button only (CODE_POWER = 102)
+- **No SDL Keyboard**: All keyboard mappings are `BUTTON_NA`
+
+### CPU & Performance
+- ARM Cortex-A53 processor
+- ARM NEON SIMD support
+- Compiler optimizations: `-march=armv8-a+crc -mtune=cortex-a53 -mcpu=cortex-a53`
+- Fast math and tree vectorization enabled
+
+### Power Management
+- Power button via evdev (KEY_HOME)
+- Sleep/wake functionality
+- Auto-sleep support
+
+### Storage
+- **TF1 (Internal)**: `/mnt/mmc` - Boot partition and stock OS
+- **TF2 (External)**: `/mnt/sdcard` - MinUI and ROMs
+- Automatic fallback: If TF2 is missing or empty, symlink to TF1
+
+## Platform Variants
+
+This platform supports **three hardware variants** detected at runtime:
+
+### RG35XX Plus (Standard)
+- 640x480 display
+- Standard aspect ratio
+- Base variant (`RGXX_MODEL` detection)
+- Framebuffer: Standard or rotated (480x640)
+
+### RG35XX H (CubeXX)
+- 720x720 square display
+- Unique aspect ratio for arcade/vertical games
+- Detected via `RGcubexx` model string
+- UI adjustments: 8 rows, 40px padding
+
+### RG35XX SP (RG34XX)
+- 720x480 widescreen display
+- 3:2 aspect ratio
+- Detected via `RG34xx*` model string (wildcard for variants)
+- UI adjustments: Standard rows (6), standard padding (10px)
+
+### HDMI Output Mode
+- 1280x720 resolution (720p)
+- Runtime detection via `/sys/class/extcon/hdmi/cable.0/state`
+- UI adjustments when active: 8 rows, 40px padding
+- Volume forced to 100% when HDMI connected
+- Brightness control disabled during HDMI output
+
+**Detection**: Variants are auto-detected at boot by reading `/mnt/vendor/bin/dmenu.bin` for model string. The `is_cubexx`, `is_rg34xx`, and `on_hdmi` flags configure display resolution, UI layout, and input handling accordingly.
+
+## Directory Structure
+
+```
+rg35xxplus/
+├── platform/ Platform-specific hardware definitions
+│ └── platform.h Runtime-configurable specs, variant detection flags
+├── keymon/ Hardware button monitoring daemon
+│ └── keymon.c Volume/brightness control + HDMI monitoring
+├── libmsettings/ Settings library (volume, brightness, HDMI)
+│ └── msettings.c Shared memory settings with variant support
+├── boot/ Boot assets and scripts
+│ ├── boot.sh Main boot/update handler
+│ ├── build.sh Boot asset packaging script
+│ ├── bootlogo.bmp (640x480 - RG35XX Plus)
+│ ├── bootlogo-r.bmp (480x640 - Rotated framebuffer)
+│ ├── bootlogo-s.bmp (720x720 - RG35XX H/CubeXX)
+│ ├── bootlogo-w.bmp (720x480 - RG35XX SP)
+│ ├── installing.bmp (640x480)
+│ ├── installing-r.bmp (480x640 rotated)
+│ ├── installing-s.bmp (720x720 square)
+│ ├── installing-w.bmp (720x480 widescreen)
+│ ├── updating.bmp (640x480)
+│ ├── updating-r.bmp (480x640 rotated)
+│ ├── updating-s.bmp (720x720 square)
+│ └── updating-w.bmp (720x480 widescreen)
+├── init/ Minimal SDL initialization utility
+│ └── init.c Early SDL setup (VideoMode initialization)
+├── show/ Boot splash screen display
+│ └── show.c SDL2-based image display with rotation support
+├── install/ Installation assets and scripts
+│ └── install.sh Post-update system configuration
+├── cores/ Libretro cores (submodules + builds)
+└── other/ Third-party dependencies
+ ├── sdl2/ Custom SDL2 fork (Mali framebuffer rotation)
+ ├── unzip60/ Unzip utility for update extraction
+ ├── dtc/ Device Tree Compiler (for boot customization)
+ └── fbset/ Framebuffer configuration utility
+```
+
+## Input System
+
+The RG35XX Plus series uses **joystick input exclusively**:
+
+1. **SDL Joystick API**: Primary input method for all game controls
+2. **Evdev Codes**: Only power button (CODE_POWER = 102) uses direct kernel input
+3. **No SDL Keyboard**: Platform does not use SDL keyboard events
+
+### Joystick Button Mappings
+
+| Button | Index |
+|--------|-------|
+| A | 0 |
+| B | 1 |
+| X | 3 |
+| Y | 2 |
+| L1 | 4 |
+| R1 | 5 |
+| L2 | 9 |
+| R2 | 10 |
+| SELECT | 6 |
+| START | 7 |
+| MENU | 8 |
+| PLUS (Volume Up) | 18 |
+| MINUS (Volume Down) | 17 |
+| D-Pad Up | 13 |
+| D-Pad Down | 16 |
+| D-Pad Left | 14 |
+| D-Pad Right | 15 |
+
+### Button Combinations
+
+| Combination | Function |
+|-------------|----------|
+| PLUS | Increase volume |
+| MINUS | Decrease volume |
+| MENU + PLUS | Increase brightness |
+| MENU + MINUS | Decrease brightness |
+| POWER | Sleep/wake device |
+| X (in launcher) | Resume from save state |
+
+### Hardware Button Quirks
+- **MENU button code**: 312 (in kernel space, also responds to 354)
+- **Volume range**: 0-20
+- **Brightness range**: 0-10
+- **Brightness disabled**: When HDMI is active
+- **Volume behavior**: Maxed to 100% when HDMI connected
+
+## Building
+
+### Prerequisites
+Requires Docker with ARM cross-compilation toolchain (buildroot with GCC).
+
+### Build Commands
+
+```bash
+# Enter platform build environment
+make PLATFORM=rg35xxplus shell
+
+# Inside container: build all platform components
+cd /root/workspace/rg35xxplus
+make
+
+# This builds:
+# - init (early SDL initialization)
+# - show.elf (boot splash display utility)
+# - keymon (button monitoring daemon)
+# - libmsettings (settings library)
+# - Boot assets (bootlogo variants packaged into boot.sh)
+# - SDL2 library (Mali framebuffer with rotation support)
+# - unzip60 (update extraction)
+# - dtc (device tree compiler)
+# - fbset (framebuffer configuration)
+# - All libretro cores in cores/
+```
+
+### Dependencies
+The platform automatically clones required dependencies on first build:
+- **SDL2**: `github.com/JohnnyonFlame/SDL-malifbdev-rot` (Mali framebuffer with rotation)
+- **unzip60**: `github.com/shauninman/unzip60.git`
+- **dtc**: `github.com/dgibson/dtc` (Device Tree Compiler)
+- **fbset**: `github.com/shauninman/union-fbset`
+
+## Installation
+
+### File System Layout
+
+MinUI installs across two SD cards:
+
+**TF1 (Internal) - `/mnt/mmc`**:
+```
+/mnt/mmc/
+├── dmenu.bin Updated from MinUI (stock menu binary)
+├── .minstalled Flag file (prevents bootlogo reinstall)
+└── log.txt Installation/boot log
+```
+
+**TF2 (External) - `/mnt/sdcard`**:
+```
+/mnt/sdcard/
+├── .system/
+│ ├── rg35xxplus/ Platform-specific binaries
+│ │ ├── bin/ Utilities (keymon, init, show, etc.)
+│ │ │ └── install.sh Post-update installation script
+│ │ ├── dat/
+│ │ │ └── dmenu.bin Updated stock menu binary
+│ │ └── paks/ Applications and emulators
+│ │ └── MinUI.pak/ Main launcher
+│ └── res/ Shared UI assets
+│ ├── assets@2x.png UI sprite sheet (2x scale)
+│ └── BPreplayBold-unhinted.otf
+├── .userdata/
+│ └── rg35xxplus/ User settings and saves
+├── Roms/ ROM files organized by system
+└── MinUI.zip Update package (if present)
+```
+
+### Boot Process
+
+1. Stock firmware boots from TF1 (`/mnt/mmc`)
+2. Custom boot script runs (`boot.sh` embedded in bootloader)
+3. Script mounts TF2 (`/mnt/sdcard`) at `/dev/mmcblk1p1`
+4. If TF2 mount fails or doesn't contain MinUI: symlink `/mnt/sdcard` → `/mnt/mmc`
+5. Check for `MinUI.zip` on TF2:
+ - Detect device variant by reading `/mnt/vendor/bin/dmenu.bin`
+ - Detect framebuffer orientation from `/sys/class/graphics/fb0/modes`
+ - Select appropriate boot image suffix:
+ - `-r`: Rotated framebuffer (480x640)
+ - `-s`: Square display (RGcubexx)
+ - `-w`: Widescreen display (RG34xx)
+ - (none): Standard 640x480
+ - Display `installing.bmp` (first install) or `updating.bmp` (update)
+ - Extract `MinUI.zip` to `/mnt/sdcard`
+ - Delete ZIP file
+ - On first install: Replace stock bootlogo.bmp on boot partition (TF1)
+ - Run `.system/rg35xxplus/bin/install.sh` to complete setup
+6. Launch MinUI via `.system/rg35xxplus/paks/MinUI.pak/launch.sh`
+7. If launcher exits, shutdown device (prevents stock firmware from accessing card)
+
+### Update Process
+
+To update MinUI on device:
+1. Place `MinUI.zip` in TF2 root (`/mnt/sdcard/`)
+2. Reboot device
+3. Boot script auto-detects ZIP, determines variant, and performs update
+4. ZIP is deleted after successful extraction
+5. `install.sh` finalizes update (copies dmenu.bin, migrates old configs)
+
+### Migration from RG40XXCUBE
+
+The install script handles automatic migration from the deprecated `rg40xxcube` platform:
+
+1. Detects old `.system/rg40xxcube` directory
+2. Deletes old system folder
+3. Migrates user configs from `.userdata/rg40xxcube` to `.userdata/rg35xxplus`
+4. Renames config files with `-cube.cfg` suffix to preserve variant-specific settings
+5. Deletes old userdata folder
+6. Reboots to apply changes
+
+This ensures users can seamlessly upgrade from the older platform naming.
+
+## Platform-Specific Features
+
+### Runtime Variant Detection
+
+The platform uses **runtime configuration** based on detected hardware:
+
+```c
+// Runtime flags set during initialization
+extern int is_cubexx; // RG35XX H (720x720 square)
+extern int is_rg34xx; // RG35XX SP (720x480 widescreen)
+extern int on_hdmi; // HDMI output active
+
+// Display resolution adapts to variant
+#define FIXED_WIDTH (is_cubexx?720:(is_rg34xx?720:640))
+#define FIXED_HEIGHT (is_cubexx?720:480)
+
+// UI layout adapts to variant/HDMI
+#define MAIN_ROW_COUNT (is_cubexx||on_hdmi?8:6)
+#define PADDING (is_cubexx||on_hdmi?40:10)
+```
+
+This single binary supports all three hardware variants without recompilation.
+
+### HDMI Monitoring
+
+The `keymon` daemon runs a background thread that monitors HDMI state:
+
+```c
+// Polls /sys/class/extcon/hdmi/cable.0/state every second
+// When HDMI state changes:
+// - Updates on_hdmi flag
+// - Switches video routing
+// - Maximizes volume (100%)
+// - Disables brightness control
+```
+
+HDMI detection is automatic and handles hot-plugging during runtime.
+
+### Multi-Resolution Boot Images
+
+The boot process supports four image variants:
+
+| Suffix | Resolution | Variant |
+|--------|-----------|---------|
+| (none) | 640x480 | RG35XX Plus (standard) |
+| `-r` | 480x640 | Rotated framebuffer |
+| `-s` | 720x720 | RG35XX H (CubeXX) |
+| `-w` | 720x480 | RG35XX SP |
+
+Boot script auto-detects the correct variant and displays the appropriate image.
+
+### Framebuffer Configuration
+
+Custom SDL2 fork supports Mali framebuffer with rotation:
+- Enables ARM NEON SIMD optimizations
+- Mali framebuffer driver support (`--enable-video-mali`)
+- Rotation handling for portrait-mode screens
+- Optimized blitting for 16-bit RGB565
+
+### Audio Configuration
+
+Custom audio buffer size (`SAMPLES 400`) reduces audio underruns in fceumm (NES emulator).
+
+Volume control via ALSA:
+```bash
+amixer sset 'lineout volume'
+```
+
+### Brightness Control
+
+Direct `/dev/disp` ioctl control:
+```c
+#define DISP_LCD_SET_BRIGHTNESS 0x102
+// Raw brightness: 0-255
+// User levels: 0-10 (mapped to exponential curve)
+```
+
+### Device Tree Customization
+
+Platform includes Device Tree Compiler (dtc) for boot-time hardware customization. This allows modification of device tree binaries for hardware configuration.
+
+## UI Layout Adjustments
+
+Different variants use optimized UI parameters:
+
+| Parameter | Plus (640x480) | H/HDMI (720x720/1280x720) | SP (720x480) |
+|-----------|----------------|---------------------------|--------------|
+| `FIXED_WIDTH` | 640 | 720 | 720 |
+| `FIXED_HEIGHT` | 480 | 720 | 480 |
+| `MAIN_ROW_COUNT` | 6 rows | 8 rows | 6 rows |
+| `PADDING` | 10px | 40px | 10px |
+| `FIXED_SCALE` | 2x | 2x | 2x |
+
+These adjustments maximize visible content while maintaining consistent UI appearance.
+
+## Included Tools
+
+Tools are provided via the shared MinUI .pak system:
+- **Clock.pak**: System clock/time display
+- **Input.pak**: Input configuration utility
+- **Files.pak**: File manager (if included in build)
+
+## Known Issues / Quirks
+
+### Hardware Quirks
+1. **Dual SD Card Complexity**: Requires careful TF1/TF2 management and symlink fallback
+2. **Runtime Configuration**: All display parameters are runtime-calculated based on flags
+3. **HDMI Audio Override**: Volume forced to 100% when HDMI connected (system limitation)
+4. **Model String Detection**: Relies on stock `dmenu.bin` containing `RGcubexx` or `RG34xx` string
+5. **Framebuffer Rotation**: Some units ship with rotated framebuffer (480x640) requiring special handling
+
+### Development Notes
+1. **No L3/R3**: Platform lacks clickable analog sticks
+2. **Joystick-Only Input**: No SDL keyboard support - must use joystick API exclusively
+3. **MENU Button Duality**: Kernel reports code 312 AND 354 for MENU button
+4. **Platform Consolidation**: Replaces older `rg40xxcube` platform (migration handled automatically)
+5. **NEON Optimizations**: Platform supports ARM NEON SIMD - use `HAS_NEON` define for optimized code paths
+
+### Volume/Brightness Quirks
+- Brightness control uses non-linear exponential curve for better perceptual response
+- Volume muted at raw value 0 (simpler than other platforms)
+- Both volume and brightness disabled during HDMI output
+- Headphone jack monitoring defined but jack_state always returns 0 (unused feature)
+
+### Boot Process Quirks
+1. **dmenu.bin Update**: Install script copies updated `dmenu.bin` to TF1 for stock menu compatibility
+2. **Bootlogo One-Time Install**: `.minstalled` flag prevents bootlogo from being reinstalled on updates
+3. **Shutdown on Exit**: Boot script shutdowns device if MinUI exits (safety measure)
+4. **Automatic Symlink**: If TF2 is missing/empty, automatically symlinks to TF1 for single-card operation
+
+## Testing
+
+When testing changes:
+1. Test on **all three variants** (Plus, H/CubeXX, SP)
+2. Verify each resolution: 640x480, 720x720, 720x480
+3. Test rotated framebuffer variant (480x640)
+4. Check HDMI output (1280x720) with hot-plug detection
+5. Verify volume/brightness controls with variant-specific behavior
+6. Test boot splash screens for all variants (standard, -r, -s, -w)
+7. Confirm TF1/TF2 symlink fallback works when TF2 is removed
+8. Test migration from `rg40xxcube` platform (if applicable)
+9. Verify `dmenu.bin` update mechanism
+
+## Related Documentation
+
+- Main project docs: `../../README.md`
+- Platform abstraction: `../../all/common/defines.h`
+- Shared code: `../../all/minui/minui.c` (launcher), `../../all/minarch/minarch.c` (libretro frontend)
+- Build system: `../../Makefile` (host), `./makefile` (platform)
+- Platform header: `./platform/platform.h` (runtime-configurable definitions)
+
+## Maintainer Notes
+
+This platform demonstrates MinUI's **advanced runtime adaptation**:
+- Single binary supporting three distinct hardware variants
+- Runtime display resolution and UI layout configuration
+- Hot-plug HDMI detection with automatic routing
+- Multi-resolution boot asset selection
+- Automatic migration from deprecated platforms
+- Dual SD card architecture with intelligent fallback
+
+The consolidation of RG35XX Plus, H, and SP into a single platform (replacing the older separate `rg40xxcube` platform) significantly reduces code duplication and simplifies maintenance.
+
+**Key Design Patterns**:
+- Use of `extern int` flags for runtime configuration
+- Macro definitions with ternary operators for variant-specific values
+- Background thread for HDMI monitoring
+- Boot-time model string detection from vendor binaries
+- Shared memory settings architecture for cross-process communication
+
+Changes to this platform should preserve runtime compatibility across all three variants and maintain HDMI hot-plug functionality.
diff --git a/workspace/rgb30/README.md b/workspace/rgb30/README.md
new file mode 100644
index 00000000..f3d4f6b2
--- /dev/null
+++ b/workspace/rgb30/README.md
@@ -0,0 +1,349 @@
+# Anbernic RGB30
+
+Platform implementation for the Anbernic RGB30 retro handheld device.
+
+## Hardware Specifications
+
+### Display
+- **Resolution**: 720x720 (square display, 1:1 aspect ratio)
+- **Color Depth**: 16-bit RGB565
+- **UI Scale**: 2x (uses `assets@2x.png`)
+- **HDMI Output**: 1280x720 (720p) with automatic switching
+
+### Input
+- **D-Pad**: Up, Down, Left, Right
+- **Face Buttons**: A, B, X, Y
+- **Shoulder Buttons**: L1, R1, L2, R2
+- **Analog Sticks**: L3, R3 (clickable, used as menu modifiers)
+- **System Buttons**:
+ - Two MENU buttons (primary and alternate via L3/R3)
+ - POWER button
+ - Dedicated PLUS/MINUS volume buttons
+ - SELECT and START buttons
+
+### Input Method
+- **Primary**: SDL Joystick API (gamepad input)
+- **Secondary**: Evdev codes for volume, power, and menu modifier buttons
+- **Hybrid Design**: Minimal SDL keyboard (power button only), most input via joystick
+
+### CPU & Performance
+- ARM processor with NEON SIMD support
+- No overclocking support
+
+### Power Management
+- Power button detection via SDL keyboard (SDLK_POWER)
+- Sleep/wake functionality
+
+### Audio/Video
+- **Headphone Jack**: Automatic detection and audio routing
+- **HDMI Output**: Automatic detection with video/audio switching
+- **Volume Range**: 0-20 (raw: 0-100 via amixer)
+- **Brightness Range**: 0-10 (raw: 0-255)
+
+### Storage
+- SD card mounted at `/storage/roms`
+
+## Platform Architecture
+
+The RGB30 uses a **hybrid input system** that combines:
+- SDL2 joystick for gamepad buttons (D-Pad, face buttons, shoulders)
+- Minimal SDL keyboard for power button
+- Evdev codes for volume control and L3/R3 menu modifiers
+
+This approach allows hardware volume buttons to work independently while maintaining standard gamepad compatibility.
+
+## Directory Structure
+
+```
+rgb30/
+├── platform/ Platform-specific hardware definitions
+│ └── platform.h Button mappings, display specs, HDMI support
+├── keymon/ Hardware button monitoring daemon
+│ └── keymon.c Volume/brightness + headphone/HDMI detection
+├── libmsettings/ Settings library with audio/video routing
+│ ├── msettings.c Shared memory settings management
+│ └── msettings.h Settings API (volume, brightness, jack, HDMI)
+├── show/ Boot splash screen utility
+│ ├── show.c SDL2-based image display (supports HDMI)
+│ └── makefile Build configuration
+├── cores/ Libretro cores (submodules + builds)
+└── other/ Third-party dependencies
+ ├── DinguxCommander/ File manager (branch: minui-rgb30)
+ └── sdl12-compat/ SDL 1.2 compatibility layer (branch: minui-rgb30)
+```
+
+## Input System
+
+The RGB30 uses a **joystick-first input architecture**:
+
+1. **SDL Joystick API**: Primary gamepad input (D-Pad, face buttons, shoulders, Start/Select)
+2. **SDL Keyboard**: Power button only (SDLK_POWER)
+3. **Evdev Codes**: Volume buttons (114/115) and L3/R3 menu modifiers (317/318)
+
+### Joystick Button Mappings
+
+| Physical Button | Joystick Index |
+|----------------|----------------|
+| D-Pad Up/Down/Left/Right | 13/14/15/16 |
+| A, B, X, Y | 1, 0, 2, 3 |
+| L1, R1 | 4, 5 |
+| L2, R2 | 6, 7 |
+| SELECT, START | 8, 9 |
+| MENU (primary) | 11 |
+| MENU ALT (secondary) | 12 |
+
+### Input Event Devices
+
+The keymon daemon monitors multiple input devices:
+- **event0-4**: Gamepad and button input
+- **js0**: Joystick device
+
+### Button Combinations
+
+| Combination | Function |
+|-------------|----------|
+| PLUS | Increase volume |
+| MINUS | Decrease volume |
+| L3/R3 + PLUS | Increase brightness |
+| L3/R3 + MINUS | Decrease brightness |
+| POWER | Sleep/wake device |
+| X (in launcher) | Resume from save state |
+
+### Hardware Monitoring
+
+The keymon daemon runs a background thread to monitor:
+- **Headphone jack state**: `/sys/bus/platform/devices/singleadc-joypad/hp`
+- **HDMI connection state**: `/sys/class/extcon/hdmi/cable.0/state`
+
+Audio and video routing automatically switches when headphones or HDMI are connected/disconnected.
+
+## Building
+
+### Prerequisites
+Requires Docker with RGB30 cross-compilation toolchain.
+
+### Build Commands
+
+```bash
+# Enter platform build environment
+make PLATFORM=rgb30 shell
+
+# Inside container: build all platform components
+cd /root/workspace/rgb30
+make
+
+# This builds (in early target):
+# - DinguxCommander (file manager)
+# - sdl12-compat (SDL 1.2 compatibility layer)
+#
+# And (in all target):
+# - show.elf (boot splash display)
+# - All libretro cores in cores/
+```
+
+### Dependencies
+
+The platform automatically clones required dependencies on first build:
+- **DinguxCommander**: `github.com/shauninman/DinguxCommander.git` (branch: `minui-rgb30`)
+- **sdl12-compat**: `github.com/shauninman/sdl12-compat.git` (branch: `minui-rgb30`)
+
+Both dependencies use custom toolchain configurations for the RGB30 hardware.
+
+## Installation
+
+### File System Layout
+
+MinUI installs to the SD card with the following structure:
+
+```
+/storage/roms/
+├── .system/
+│ ├── rgb30/ Platform-specific binaries
+│ │ ├── bin/ Utilities (keymon, show, etc.)
+│ │ └── paks/ Applications and emulators
+│ │ └── MinUI.pak/ Main launcher
+│ └── res/ Shared UI assets
+│ ├── assets@2x.png UI sprite sheet (2x scale)
+│ └── BPreplayBold-unhinted.otf
+├── .userdata/ User settings and save data
+│ └── rgb30/ Platform-specific settings
+│ └── msettings.bin Volume/brightness preferences
+├── Roms/ ROM files organized by system
+└── MinUI.zip Update package (if present)
+```
+
+### Settings Management
+
+The RGB30 uses shared memory for settings synchronization between processes:
+
+**Settings Stored**:
+- Brightness level (0-10)
+- Speaker volume (0-20)
+- Headphone volume (0-20, separate from speaker)
+- Jack state (headphones connected/disconnected)
+- HDMI state (HDMI connected/disconnected)
+
+**Persistence**: Settings are saved to `$USERDATA_PATH/msettings.bin` and persist across reboots.
+
+## Platform-Specific Features
+
+### Square Display
+
+The 720x720 square display (1:1 aspect ratio) requires UI adjustments:
+
+| Parameter | Value | Notes |
+|-----------|-------|-------|
+| `MAIN_ROW_COUNT` | 8 rows | More rows visible than standard 640x480 |
+| `PADDING` | 40px | Larger padding for square layout |
+
+These settings maximize content visibility while maintaining comfortable spacing.
+
+### HDMI Output Support
+
+The platform includes full HDMI support:
+
+**Output Resolution**: 1280x720 (720p)
+
+**Automatic Behavior**:
+- Video output switches to HDMI when connected
+- Audio routing changes to HDMI audio
+- Volume locked at 100% on HDMI (brightness control disabled)
+- Automatically reverts to internal display/speaker when disconnected
+
+**Implementation**: Background thread in keymon polls HDMI state every second.
+
+### Audio Routing
+
+Smart audio routing based on connected devices:
+
+1. **Internal Speaker**: Default audio output
+2. **Headphones**: Auto-detected, switches to headphone output, uses separate volume level
+3. **HDMI**: Auto-detected, switches to HDMI audio, locks volume at 100%
+
+**amixer Commands**:
+- Playback path: `amixer cset name='Playback Path' 'SPK'|'HP'`
+- Volume: `amixer sset -M 'Master' N%`
+
+### Brightness Control
+
+Hardware brightness via sysfs:
+- **Path**: `/sys/class/backlight/backlight/brightness`
+- **Range**: 0-255 (raw), mapped from 0-10 user scale
+- **Disabled on HDMI**: Brightness adjustments ignored when HDMI connected
+
+**Brightness Curve** (non-linear for better low-end visibility):
+```
+Level 0: 4 Level 1: 6 Level 2: 10 Level 3: 16
+Level 4: 32 Level 5: 48 Level 6: 64 Level 7: 96
+Level 8: 128 Level 9: 192 Level 10: 255
+```
+
+### Volume Button Quirks
+
+The platform has hardware volume buttons with evdev codes:
+- **CODE_PLUS**: 129 (Volume up) - **swapped from kernel default**
+- **CODE_MINUS**: 128 (Volume down) - **swapped from kernel default**
+
+These codes are swapped in platform.h to correct the hardware mapping.
+
+### Repeat Functionality
+
+Volume and brightness buttons support repeat:
+- **Initial delay**: 300ms before repeat starts
+- **Repeat interval**: 100ms between repeats
+- **Ignores stale input**: After system sleep (>1 second gap), input ignored to prevent spurious events
+
+## Supported Emulator Cores
+
+The RGB30 platform includes these libretro cores:
+
+| Core | Systems | Notes |
+|------|---------|-------|
+| **fceumm** | NES, Famicom | Nintendo Entertainment System |
+| **gambatte** | Game Boy, Game Boy Color | Accuracy-focused |
+| **gpsp** | Game Boy Advance | Fast, requires BIOS |
+| **pcsx_rearmed** | PlayStation | Optimized ARM port |
+| **picodrive** | Genesis, Mega Drive, 32X, Sega CD | Multi-system |
+| **snes9x2005_plus** | SNES | Lightweight, Blargg APU |
+| **pokemini** | Pokemon Mini | Niche handheld |
+| **fake-08** | PICO-8 | Fantasy console |
+| **mednafen_pce_fast** | PC Engine, TurboGrafx-16 | Fast variant |
+| **mednafen_vb** | Virtual Boy | Nintendo VR handheld |
+| **mednafen_supafaust** | SNES | High accuracy |
+| **mgba** | Game Boy Advance | High accuracy |
+| **race** | Neo Geo Pocket, Neo Geo Pocket Color | SNK handheld |
+
+## Included Tools
+
+### Files.pak
+DinguxCommander-based file manager (custom RGB30 build):
+- Full file operations (copy, cut, paste, delete, rename)
+- Directory navigation
+- Image preview support
+- Integrated with MinUI launcher
+
+## Known Issues / Quirks
+
+### Hardware Quirks
+1. **Joystick-first input**: Unlike keyboard-based platforms, uses SDL joystick API primarily
+2. **Dual menu buttons**: L3/R3 analog stick clicks act as menu modifiers (codes 317/318)
+3. **Volume code swap**: Hardware volume button codes swapped in software to correct mapping
+4. **HDMI volume lock**: Volume/brightness controls disabled when HDMI connected
+5. **Audio crackling**: Light crackling reported in some cores (fceumm, snes9x2005_plus) - likely SDL2 audio pipeline issue
+
+### Development Notes
+1. **SDL2**: Platform uses SDL2 (not SDL 1.2), requiring sdl12-compat for legacy cores
+2. **Shared memory settings**: libmsettings uses `/SharedSettings` SHM for IPC
+3. **Settings host**: keymon is always the settings "host" (first to create SHM)
+4. **HDMI polling**: Background thread polls HDMI state at 1Hz (every second)
+5. **60Hz input polling**: Main keymon loop runs at 60Hz (16.6ms sleep)
+
+### Input Limitations
+- **No L3/R3 for games**: L3/R3 reserved for system menu modifier, not available to cores
+- **Evdev overhead**: Volume buttons require evdev monitoring (can't use SDL alone)
+
+### Audio Buffer Size
+Default audio buffer: `SAMPLES 400` (balanced latency vs stability)
+
+## Testing
+
+When testing changes:
+1. Verify joystick input works correctly (D-Pad, face buttons, shoulders)
+2. Test HDMI detection and automatic video/audio switching
+3. Check headphone jack detection and audio routing
+4. Verify volume control with PLUS/MINUS buttons
+5. Test brightness control with L3/R3 + PLUS/MINUS
+6. Confirm settings persist across reboots (msettings.bin)
+7. Test on both internal display and HDMI output
+8. Verify square display UI layout (720x720)
+
+## Related Documentation
+
+- Main project docs: `../../README.md`
+- Platform abstraction: `../../all/common/defines.h`
+- Shared code: `../../all/minui/minui.c` (launcher), `../../all/minarch/minarch.c` (libretro frontend)
+- Build system: `../../Makefile` (host), `./makefile` (platform)
+- Platform header: `./platform/platform.h` (all hardware definitions)
+
+## Maintainer Notes
+
+This platform demonstrates several advanced MinUI features:
+
+**Unique Characteristics**:
+- Square display (720x720) - unique aspect ratio among MinUI platforms
+- HDMI output support with automatic switching
+- Dual menu modifier buttons (L3/R3)
+- Hybrid input system (joystick + keyboard + evdev)
+- Background hardware monitoring threads
+- Shared memory settings management
+- Separate volume levels for speaker vs headphones
+
+**Reference Implementation For**:
+- HDMI output detection and switching
+- Headphone jack detection
+- Multi-device audio routing
+- Non-standard display aspect ratios
+- SDL2-based platforms
+- Joystick-first input handling
+
+Changes to this platform should be tested with HDMI output and headphone jack to ensure automatic switching continues to work correctly.
diff --git a/workspace/tg5040/README.md b/workspace/tg5040/README.md
new file mode 100644
index 00000000..1069470f
--- /dev/null
+++ b/workspace/tg5040/README.md
@@ -0,0 +1,484 @@
+# TG5040 (Trimui Smart Pro / Brick)
+
+Platform implementation for the TG5040 handheld devices, supporting both the standard Trimui Smart Pro and the Brick variant.
+
+## Hardware Specifications
+
+### Display
+- **Standard Resolution**: 1280x720 (HD widescreen)
+- **Brick Resolution**: 1024x768 (XGA, 4:3 aspect ratio)
+- **Color Depth**: 16-bit RGB565
+- **UI Scale**: 2x standard, 3x Brick (uses `assets@2x.png` or `assets@3x.png`)
+- **Variant Detection**: Runtime detection via `is_brick` flag
+
+### Input
+- **D-Pad**: Up, Down, Left, Right (via HAT)
+- **Face Buttons**: A, B, X, Y
+- **Shoulder Buttons**: L1, R1
+- **Analog Triggers**: L2, R2 (axis-based)
+- **Analog Sticks**: Left stick (LX/LY) and Right stick (RX/RY)
+- **L3/R3 Buttons**: Brick variant only (clickable analog sticks)
+- **System Buttons**:
+ - SELECT and START buttons
+ - MENU button
+ - POWER button (HOME key, code 102)
+ - PLUS/MINUS volume buttons (hardware buttons on Brick, evdev codes on standard)
+
+### Input Method
+- **Primary**: SDL Joystick API (not keyboard events)
+- **D-Pad**: Implemented via joystick HAT
+- **Analog**: 6 analog axes (left/right sticks, L2/R2 triggers)
+- **Evdev Codes**: Volume/power buttons only
+
+### CPU & Performance
+- ARM processor with NEON SIMD support
+- CPU frequency: 2.0 GHz (userspace governor)
+- Performance mode set during boot
+
+### Power Management
+- Hardware mute switch (GPIO243)
+- Headphone jack detection via EV_SW events
+- Auto-sleep and power-off features
+- Battery monitoring (platform-specific)
+
+### Storage
+- SD card mounted at `/mnt/SDCARD`
+- Brick variant also mounts `/mnt/UDISK`
+
+### Audio
+- ALSA mixer controls via `amixer`
+- DAC channel swap correction (fixes L/R channels)
+- Hardware mute switch with GPIO monitoring
+- Headphone jack detection with automatic volume switching
+- Volume range: 0-20 (raw: 0-100)
+- Mute volume: 0
+
+## Platform Variants
+
+This platform supports two hardware variants detected at runtime:
+
+### Standard Trimui Smart Pro
+- **Display**: 1280x720 (16:9 widescreen)
+- **Scale**: 2x
+- **Main Rows**: 8
+- **Padding**: 40px
+- **Volume Buttons**: Evdev codes 128 (PLUS) and 129 (MINUS)
+- **No L3/R3**: Clickable stick buttons not available
+
+### Trimui Brick
+- **Display**: 1024x768 (4:3 aspect ratio)
+- **Scale**: 3x
+- **Main Rows**: 7
+- **Padding**: 5px
+- **Volume Buttons**: Joystick buttons 14 (PLUS) and 13 (MINUS)
+- **L3/R3**: Buttons 9 and 10 respectively
+- **LED Control**: Additional LED strips (max_scale_lr, max_scale_f1f2)
+
+**Detection**: The boot script checks for "Trimui Brick" string in `/usr/trimui/bin/MainUI`. The `is_brick` flag is set via `DEVICE` environment variable and propagates to all platform code.
+
+## Directory Structure
+
+```
+tg5040/
+├── platform/ Platform-specific hardware definitions
+│ └── platform.h Button mappings, display specs, variant detection
+├── keymon/ Hardware button monitoring daemon
+│ └── keymon.c Volume/brightness control, mute/jack monitoring
+├── libmsettings/ Settings library (volume, brightness, jack state)
+│ └── msettings.c Dual-variant brightness/volume tables
+├── show/ Boot splash screen display (SDL2)
+│ └── show.c PNG image loader for install/update screens
+├── install/ Installation assets and boot scripts
+│ ├── boot.sh Variant detection and boot/update handler
+│ ├── update.sh Migration script (tg3040 to tg5040)
+│ ├── installing.png Standard boot splash (1280x720)
+│ ├── updating.png Standard update splash (1280x720)
+│ └── brick/ Brick-specific assets
+│ ├── installing.png Brick boot splash (1024x768)
+│ └── updating.png Brick update splash (1024x768)
+├── cores/ Libretro cores (submodules + builds)
+└── other/ Third-party dependencies
+ ├── DinguxCommander-sdl2/ File manager (SDL2)
+ ├── evtest/ Input device testing tool
+ ├── jstest/ Joystick testing tool
+ └── unzip60/ ZIP extraction utility
+```
+
+## Input System
+
+The TG5040 uses **joystick-based input**:
+
+1. **Joystick API**: Primary input method (D-pad via HAT, buttons via indices)
+2. **Analog Axes**: 6 axes for sticks and triggers
+3. **Evdev Codes**: Only for POWER (102), PLUS/MINUS volume buttons
+4. **No SDL Keyboard**: All keyboard mappings are `BUTTON_NA`
+
+### Button Mappings
+
+| Physical Button | Standard Mapping | Brick Mapping |
+|----------------|------------------|---------------|
+| D-Pad | HAT (no button index) | HAT (no button index) |
+| A | JOY 1 | JOY 1 |
+| B | JOY 0 | JOY 0 |
+| X | JOY 3 | JOY 3 |
+| Y | JOY 2 | JOY 2 |
+| L1 | JOY 4 | JOY 4 |
+| R1 | JOY 5 | JOY 5 |
+| L2 | Axis 2 (ABSZ) | Axis 2 (ABSZ) |
+| R2 | Axis 5 (RABSZ) | Axis 5 (RABSZ) |
+| L3 | N/A | JOY 9 |
+| R3 | N/A | JOY 10 |
+| SELECT | JOY 6 | JOY 6 |
+| START | JOY 7 | JOY 7 |
+| MENU | JOY 8 | JOY 8 |
+| PLUS | Code 128 | JOY 14 |
+| MINUS | Code 129 | JOY 13 |
+| POWER | Code 102 | Code 102 |
+
+### Analog Axes
+
+| Axis | Control | Range |
+|------|---------|-------|
+| 0 (ABS_X) | Left stick X | -32k to +32k |
+| 1 (ABS_Y) | Left stick Y | -32k to +32k |
+| 2 (ABSZ) | L2 trigger | 0 to max |
+| 3 (ABS_RX) | Right stick X | -32k to +32k |
+| 4 (ABS_RY) | Right stick Y | -32k to +32k |
+| 5 (RABSZ) | R2 trigger | 0 to max |
+
+### Button Combinations
+
+| Combination | Function |
+|-------------|----------|
+| PLUS | Increase volume |
+| MINUS | Decrease volume |
+| MENU + PLUS | Increase brightness |
+| MENU + MINUS | Decrease brightness |
+| POWER | Sleep/wake device |
+| X (in launcher) | Resume from save state |
+
+### Input Quirks
+- **A/B Swap**: Button mappings were swapped in first public stock release
+- **HAT D-Pad**: D-pad uses joystick HAT instead of individual buttons
+- **Analog Triggers**: L2/R2 are analog axes, not digital buttons
+- **Variant Buttons**: L3/R3 and volume buttons differ between variants
+
+## Building
+
+### Prerequisites
+Requires Docker with TG5040 cross-compilation toolchain.
+
+### Build Commands
+
+```bash
+# Enter platform build environment
+make PLATFORM=tg5040 shell
+
+# Inside container: build all platform components
+cd /root/workspace/tg5040
+make
+
+# This builds:
+# - keymon (button monitoring daemon)
+# - libmsettings (settings library with variant support)
+# - show.elf (SDL2 boot splash display)
+# - DinguxCommander (file manager)
+# - evtest (input testing tool)
+# - jstest (joystick testing tool)
+# - unzip (ZIP extraction)
+# - All libretro cores in cores/
+```
+
+### Dependencies
+The platform automatically clones required dependencies on first build:
+- **DinguxCommander-sdl2**: `github.com/shauninman/DinguxCommander-sdl2.git`
+- **evtest**: `github.com/freedesktop-unofficial-mirror/evtest.git`
+- **jstest**: `github.com/datrh/joyutils.git`
+- **unzip60**: `github.com/shauninman/unzip60.git`
+
+### Supported Libretro Cores
+- **NES**: fceumm
+- **Game Boy / GBC**: gambatte
+- **GBA**: gpsp, mgba
+- **SNES**: snes9x2005_plus (with Blargg APU)
+- **Genesis/Mega Drive**: picodrive
+- **PC Engine/TurboGrafx-16**: mednafen_pce_fast
+- **PlayStation**: pcsx_rearmed
+- **Virtual Boy**: mednafen_vb
+- **SNES (enhanced)**: mednafen_supafaust
+- **PICO-8**: fake-08
+- **Pokemon Mini**: pokemini
+- **Neo Geo Pocket**: race
+
+## Installation
+
+### File System Layout
+
+MinUI installs to the SD card with the following structure:
+
+```
+/mnt/SDCARD/
+├── .system/
+│ ├── tg5040/ Platform-specific binaries
+│ │ ├── bin/ Utilities (keymon, etc.)
+│ │ │ └── install.sh Post-update script
+│ │ ├── dat/ Data files (runtrimui.sh)
+│ │ └── paks/ Applications and emulators
+│ │ └── MinUI.pak/ Main launcher
+│ └── res/ Shared UI assets
+│ ├── assets@2x.png UI sprite sheet (2x scale - standard)
+│ ├── assets@3x.png UI sprite sheet (3x scale - Brick)
+│ └── BPreplayBold-unhinted.otf
+├── .tmp_update/ Update staging area
+│ └── tg5040/ Platform boot components
+│ ├── show.elf Splash screen display
+│ ├── unzip ZIP extraction utility
+│ ├── installing.png Standard install splash (1280x720)
+│ ├── updating.png Standard update splash (1280x720)
+│ └── brick/ Brick variant assets
+│ ├── installing.png Brick install splash (1024x768)
+│ └── updating.png Brick update splash (1024x768)
+├── .userdata/ User settings and saves
+│ └── tg5040/ Platform-specific settings
+├── Roms/ ROM files organized by system
+└── MinUI.zip Update package (if present)
+```
+
+### Boot Process
+
+1. Device boots and runs `.tmp_update/tg5040.sh` (boot.sh)
+2. Script remounts SD cards as read-write (Brick has `/mnt/UDISK` too)
+3. Sets CPU governor to "userspace" and frequency to 2.0 GHz
+4. Detects variant by checking MainUI binary for "Trimui Brick" string
+5. If `MinUI.zip` exists:
+ - Disables LED animations (standard + Brick-specific LEDs if applicable)
+ - Displays variant-appropriate splash screen:
+ - Standard: `installing.png` or `updating.png` (1280x720)
+ - Brick: `brick/installing.png` or `brick/updating.png` (1024x768)
+ - Extracts `MinUI.zip` to SD card
+ - Deletes ZIP file
+ - Runs `.system/tg5040/bin/install.sh` to complete setup
+ - Reboots if fresh install
+6. Launches MinUI via `.system/tg5040/paks/MinUI.pak/launch.sh`
+
+### Update Process
+
+To update MinUI on device:
+1. Place `MinUI.zip` in SD card root (`/mnt/SDCARD/`)
+2. Reboot device
+3. Boot script auto-detects ZIP and performs update
+4. Displays variant-appropriate update splash
+5. ZIP is deleted after successful extraction
+
+### Migration from TG3040
+
+The update script (`update.sh`) handles migration from the old Brick platform identifier:
+
+1. Checks for `/mnt/SDCARD/.system/tg3040` (old Brick folder)
+2. If found:
+ - Copies all `.cfg` files from `.userdata/tg3040/*/*.cfg` to `.userdata/tg5040/*/NAME-brick.cfg`
+ - Deletes old system folder and userdata
+ - Removes old update staging area
+ - Reboots to complete migration
+3. Updates `runtrimui.sh` if outdated version detected
+
+## Platform-Specific Features
+
+### Variant Detection
+
+Runtime detection is performed in multiple layers:
+
+1. **Boot Script** (`boot.sh`):
+ - Reads `/usr/trimui/bin/MainUI` binary
+ - Searches for "Trimui Brick" string
+ - Sets `DEVICE=brick` environment variable
+ - Loads variant-specific splash screens
+
+2. **Settings Library** (`libmsettings`):
+ - Reads `DEVICE` environment variable
+ - Sets `is_brick` flag
+ - Uses variant-specific brightness tables
+
+3. **Platform Header** (`platform.h`):
+ - Declares `extern int is_brick`
+ - Uses ternary operators for runtime configuration:
+ - `FIXED_SCALE = is_brick ? 3 : 2`
+ - `FIXED_WIDTH = is_brick ? 1024 : 1280`
+ - `JOY_L3 = is_brick ? 9 : JOY_NA`
+
+### Audio Configuration
+
+The platform performs extensive ALSA mixer initialization:
+
+```bash
+amixer sset 'Headphone' 0 # 100% headphone volume
+amixer sset 'digital volume' 0 # 100% digital volume
+amixer sset 'DAC Swap' Off # Fix L/R channel swap
+```
+
+Volume control uses inverted digital volume mapping:
+- User volume 0-20 maps to raw 0-100
+- `digital volume` is set to `100 - raw_value` (reversed mapping)
+- At mute: Both `digital volume` and `DAC volume` set to 0
+- Otherwise: `DAC volume` fixed at 160 (0dB)
+
+### Brightness Control
+
+Variant-specific brightness tables provide non-linear scaling:
+
+| Level | Standard Raw | Brick Raw | Description |
+|-------|-------------|-----------|-------------|
+| 0 | 4 | 1 | Minimum (not off) |
+| 1 | 6 | 8 | Very dim |
+| 2 | 10 | 16 | Dim |
+| 3 | 16 | 32 | Low |
+| 4 | 32 | 48 | Medium-low |
+| 5 | 48 | 72 | Medium |
+| 6 | 64 | 96 | Medium-high |
+| 7 | 96 | 128 | High |
+| 8 | 128 | 160 | Higher |
+| 9 | 192 | 192 | Very high |
+| 10 | 255 | 255 | Maximum |
+
+Brightness is set via `/dev/disp` ioctl (`DISP_LCD_SET_BRIGHTNESS = 0x102`).
+
+### Hardware Monitoring
+
+The keymon daemon monitors multiple hardware states:
+
+1. **Mute Switch** (background thread):
+ - Polls GPIO243 (`/sys/class/gpio/gpio243/value`) every 200ms
+ - Updates mute state when switch changes
+ - Runs in separate pthread until quit signal
+
+2. **Headphone Jack** (EV_SW events):
+ - Monitors switch event code 2 (CODE_JACK)
+ - Automatically switches between headphone/speaker volume
+ - Maintains separate volume settings for each output
+
+3. **Button Events** (EV_KEY):
+ - 60Hz polling of event0-3 input devices
+ - Implements repeat functionality (300ms initial delay, 100ms interval)
+ - Ignores stale input after >1 second gap (prevents spurious events after sleep)
+
+### LED Control
+
+Brick variant has additional LED strips controlled via sysfs:
+- `/sys/class/led_anim/max_scale` - Main LED brightness
+- `/sys/class/led_anim/max_scale_lr` - L/R shoulder LEDs (Brick only)
+- `/sys/class/led_anim/max_scale_f1f2` - Front LEDs (Brick only)
+
+LEDs are disabled during boot/update process (set to 0).
+
+### Boot Splash Display
+
+The `show.elf` utility uses SDL2 to display PNG images:
+- Loads variant-appropriate PNG from boot script
+- Centers image on screen
+- Default 2-second display time (configurable)
+- Handles any resolution (screen dimensions auto-detected)
+
+## UI Layout Adjustments
+
+The Brick variant uses different UI parameters to optimize for its display:
+
+| Parameter | Standard (1280x720) | Brick (1024x768) |
+|-----------|-------------------|------------------|
+| `FIXED_SCALE` | 2x | 3x |
+| `FIXED_WIDTH` | 1280px | 1024px |
+| `FIXED_HEIGHT` | 720px | 768px |
+| `MAIN_ROW_COUNT` | 8 rows | 7 rows |
+| `PADDING` | 40px | 5px |
+
+These adjustments account for the aspect ratio difference (16:9 vs 4:3) and different UI scaling.
+
+## Included Tools
+
+### Files.pak
+DinguxCommander-sdl2 file manager with:
+- SDL2 graphics (hardware accelerated)
+- Full file operations (copy, cut, paste, delete, rename)
+- Directory navigation
+- Image preview support
+- Integrated with MinUI launcher
+
+### evtest
+Hardware input testing utility:
+- Displays raw input events from kernel
+- Useful for debugging button/axis mappings
+- Shows switch events (jack, mute)
+
+### jstest
+Joystick testing utility:
+- Tests joystick buttons and axes
+- Calibration support
+- Useful for verifying analog stick behavior
+
+## Known Issues / Quirks
+
+### Hardware Quirks
+1. **Button Label Swap**: A/B and X/Y physical labels don't match software mappings (first stock firmware had them swapped)
+2. **Inverted Volume**: ALSA `digital volume` control is reversed (100 = silent, 0 = loud)
+3. **Dual Mute Control**: Muting requires setting both `digital volume` and `DAC volume` to prevent audio leakage
+4. **Variant Detection**: Relies on binary string search in MainUI (fragile)
+5. **GPIO Polling**: Mute switch requires constant GPIO polling (no interrupt support)
+6. **Headphone Boot State**: Cannot detect headphone jack state at boot, only detects change events (separate speaker/headphone volumes less useful)
+7. **WiFi Limitations**: Stock `wget` lacks SSL support; Splore.pak cannot download carts from BBS (workaround: use `curl` instead)
+8. **PSP/NDS Setup**: Requires copying assets from stock firmware (not included with MinUI)
+
+### Platform Differences
+- **L3/R3 Support**: Only Brick variant has clickable analog sticks
+- **Volume Buttons**: Different implementation (evdev codes vs joystick buttons)
+- **LED Strips**: Brick has additional LED controllers
+- **Display Ratio**: 16:9 (standard) vs 4:3 (Brick) affects UI layout
+- **Mount Points**: Brick has additional `/mnt/UDISK` mount
+
+### Development Notes
+1. **HAT D-Pad**: D-pad input uses HAT, not individual button indices
+2. **Analog Triggers**: L2/R2 are axes (ABSZ/RABSZ), not digital buttons
+3. **Runtime Configuration**: Many constants use ternary operators based on `is_brick`
+4. **Multiple Input Devices**: Must monitor event0-3 for complete input coverage
+5. **Stale Input Prevention**: 1-second gap detection prevents phantom button presses after sleep
+6. **NEON Optimizations**: Platform supports ARM NEON SIMD - use `HAS_NEON` define
+
+### Input Quirks
+- **No Keyboard Input**: Platform exclusively uses joystick API
+- **MENU Button Codes**: Multiple evdev codes (314, 315, 316) all map to MENU
+- **Button Repeat**: Only PLUS/MINUS buttons have repeat behavior (300ms delay, 100ms interval)
+- **Analog Range**: Sticks use full 16-bit signed range (-32k to +32k)
+
+## Testing
+
+When testing changes:
+1. Test on **both** standard and Brick variants
+2. Verify resolution-specific assets load correctly (720p vs 768p)
+3. Check variant-specific button mappings (L3/R3, volume buttons)
+4. Test brightness tables (different raw values per variant)
+5. Verify boot splash screens display at correct resolution
+6. Test headphone jack switching between speaker/headphone volumes
+7. Verify mute switch GPIO monitoring works
+8. Check LED control (especially Brick-specific LEDs)
+9. Test analog stick and trigger functionality
+10. Verify HAT-based D-pad input works correctly
+
+## Related Documentation
+
+- Main project docs: `../../README.md`
+- Platform abstraction: `../../all/common/defines.h`
+- Shared code: `../../all/minui/minui.c` (launcher), `../../all/minarch/minarch.c` (libretro frontend)
+- Build system: `../../Makefile` (host), `./makefile` (platform)
+- Platform header: `./platform/platform.h` (all hardware definitions)
+
+## Maintainer Notes
+
+This platform is notable for:
+- **Dual-variant support**: Runtime detection of two different hardware configurations
+- **Joystick-exclusive input**: No SDL keyboard events, uses HAT for D-pad
+- **Analog controls**: Full analog stick and trigger support
+- **Complex audio**: Inverted volume mapping, dual mute controls, jack detection
+- **Hardware monitoring**: GPIO polling, switch events, multi-device input
+- **Migration support**: Handles upgrade from old tg3040 platform identifier
+
+The variant detection mechanism is somewhat fragile (depends on binary string search), but allows a single build to support both devices. Future improvements might include more robust hardware detection.
+
+Changes to input handling should be tested with analog controllers and HAT-based D-pad input, as this differs significantly from keyboard-based platforms.
diff --git a/workspace/trimuismart/README.md b/workspace/trimuismart/README.md
new file mode 100644
index 00000000..83e1f779
--- /dev/null
+++ b/workspace/trimuismart/README.md
@@ -0,0 +1,422 @@
+# Trimui Smart
+
+Platform implementation for the Trimui Smart retro handheld device.
+
+## Hardware Specifications
+
+### Display
+- **Resolution**: 320x240 (QVGA)
+- **Color Depth**: 16-bit RGB565
+- **UI Scale**: 1x (uses `assets.png`)
+- **Display Engine**: Allwinner Display Engine 2.0 (DE2) with hardware layer composition
+- **Rotation**: Software 90-degree rotation for portrait-to-landscape conversion
+- **Orientation**: Physical screen is landscape, MinUI renders portrait (then rotates)
+
+### SoC & Architecture
+- **SoC**: Allwinner F1C100s
+- **CPU**: ARM926EJ-S (single core)
+- **Memory Allocator**: ION (In-kernel Out-of-Nexus) for contiguous DMA buffers
+- **Display Layers**: Multi-channel composition (video scaling + UI overlay)
+- **NEON**: Supported (ARM NEON SIMD optimizations available)
+
+### Input
+- **D-Pad**: Up, Down, Left, Right
+- **Face Buttons**: A, B, X, Y
+- **Shoulder Buttons**: L1, R1 only (no L2/R2)
+- **System Buttons**:
+ - MENU button
+ - SELECT and START buttons
+ - No dedicated POWER button accessible in platform.h
+ - No PLUS/MINUS volume buttons
+
+### Input Method
+- **Primary**: SDL Keyboard events (SDLK_* codes)
+- **Secondary**: Evdev codes for low-level monitoring (used by keymon)
+- **No Joystick**: Platform does not use SDL joystick API
+
+### Power Management
+- **Battery Monitoring**: LRADC (Low Resolution ADC)
+- **No Battery Daemon**: Unlike other platforms, Trimui Smart lacks a dedicated battery monitor overlay
+- **Power Button**: Not defined in platform.h (may be handled by stock firmware)
+
+### Storage
+- SD card mounted at `/mnt/SDCARD`
+
+## Platform Architecture
+
+The Trimui Smart uses the Allwinner Display Engine 2.0, which provides advanced features:
+- **Multi-layer composition**: Separate channels for video and UI
+- **Hardware scaling**: Channel 1 supports video upscaling
+- **Hardware rotation**: Used for portrait-to-landscape display conversion
+- **ION memory**: Physically contiguous buffers for DMA operations
+- **Zero-copy flipping**: Direct register mapping for page flips
+
+This architecture is more complex than simple framebuffer-based platforms but enables efficient scaling and composition.
+
+## Directory Structure
+
+```
+trimuismart/
+├── platform/ Platform-specific hardware definitions
+│ ├── platform.h Button mappings, display specs
+│ ├── platform.c DE2 layer management, ION allocation (1,057 lines)
+│ ├── sunxi_display2.h Allwinner DE2 ioctl definitions
+│ ├── ion.h ION memory allocator interface
+│ ├── ion_sunxi.h Allwinner-specific ION extensions
+│ ├── makefile.env Environment variables for build
+│ └── makefile.copy File installation rules
+├── keymon/ Hardware button monitoring daemon
+│ └── keymon.c Volume/brightness control via button combos
+├── libmsettings/ Settings library (volume, brightness, jack detection)
+│ ├── msettings.c Shared memory settings with DE2 brightness control
+│ ├── msettings.h Settings API
+│ └── sunxi_display2.h DE2 header for brightness ioctl
+├── show/ Boot splash screen display
+│ └── show.c SDL-based PNG image display (rotates screen)
+├── install/ Installation assets and boot script
+│ ├── boot.sh Boot/update handler (becomes trimuismart.sh)
+│ ├── installing.png Boot splash for fresh install (320x240)
+│ └── updating.png Boot splash for updates (320x240)
+├── cores/ Libretro cores (submodules + builds)
+│ └── makefile 12 cores: NES, GB/GBC, GBA, PSX, Genesis, SNES, etc.
+└── other/ Third-party dependencies
+ ├── DinguxCommander/ File manager (trimui-smart branch)
+ └── unzip60/ Unzip utility for update extraction
+```
+
+## Input System
+
+The Trimui Smart uses a **hybrid input approach** similar to Miyoo Mini:
+
+1. **SDL Keyboard Events**: Primary input method for applications
+2. **Evdev Codes**: Direct kernel input codes for low-level monitoring (used by keymon)
+3. **No Joystick Input**: Platform does not use SDL joystick API
+
+### Hardware Button Layout
+
+| Button | SDL Keyboard Code | Evdev Code | Notes |
+|--------|------------------|------------|-------|
+| D-Pad Up | SDLK_UP | 103 (KEY_UP) | |
+| D-Pad Down | SDLK_DOWN | 108 (KEY_DOWN) | |
+| D-Pad Left | SDLK_LEFT | 105 (KEY_LEFT) | |
+| D-Pad Right | SDLK_RIGHT | 106 (KEY_RIGHT) | |
+| A | SDLK_SPACE | 57 (KEY_SPACE) | |
+| B | SDLK_LCTRL | 29 (KEY_LEFTCTRL) | |
+| X | SDLK_LSHIFT | 42 (KEY_LEFTSHIFT) | |
+| Y | SDLK_LALT | 56 (KEY_LEFTALT) | |
+| L1 | SDLK_TAB | 15 (KEY_TAB) | |
+| R1 | SDLK_BACKSPACE | 14 (KEY_BACKSPACE) | |
+| SELECT | SDLK_RCTRL | 97 (KEY_RIGHTCTRL) | |
+| START | SDLK_RETURN | 28 (KEY_ENTER) | |
+| MENU | SDLK_ESCAPE | 1 (KEY_ESC) | |
+
+### Button Combinations
+
+| Combination | Function |
+|-------------|----------|
+| SELECT + R1 | Increase volume |
+| SELECT + L1 | Decrease volume |
+| START + R1 | Increase brightness |
+| START + L1 | Decrease brightness |
+| X (in launcher) | Resume from save state |
+
+### Input Device
+- **Event Device**: `/dev/input/event0`
+- **Polling Rate**: 60Hz (16.666ms sleep in keymon)
+- **Repeat Behavior**: 300ms initial delay, then 100ms repeat interval
+
+## Building
+
+### Prerequisites
+Requires Docker with Trimui Smart cross-compilation toolchain (Allwinner F1C100s).
+
+### Build Commands
+
+```bash
+# Enter platform build environment
+make PLATFORM=trimuismart shell
+
+# Inside container: build all platform components
+cd /root/workspace/trimuismart
+make
+
+# This builds:
+# - show.elf (boot splash display using SDL)
+# - keymon (button monitoring daemon)
+# - libmsettings (settings library with DE2 brightness control)
+# - DinguxCommander (file manager)
+# - unzip60 (update extraction utility)
+# - All libretro cores in cores/
+```
+
+### Dependencies
+The platform automatically clones required dependencies on first build:
+- **DinguxCommander**: `github.com/shauninman/DinguxCommander.git` (branch: `trimui-smart`)
+- **unzip60**: `github.com/shauninman/unzip60.git` (custom makefile for Trimui Smart)
+
+Note: Unlike most platforms, Trimui Smart has no SDL dependency in its platform makefile (SDL is pre-installed in stock firmware).
+
+## Installation
+
+### File System Layout
+
+MinUI installs to the SD card with the following structure:
+
+```
+/mnt/SDCARD/
+├── .system/
+│ ├── trimuismart/ Platform-specific binaries
+│ │ ├── bin/ Utilities (keymon, etc.)
+│ │ │ └── install.sh Post-update installation script
+│ │ └── paks/ Applications and emulators
+│ │ └── MinUI.pak/ Main launcher
+│ └── res/ Shared UI assets
+│ ├── assets.png UI sprite sheet (1x scale, 320x240)
+│ └── BPreplayBold-unhinted.otf
+├── .tmp_update/ Update staging area
+│ └── trimuismart/ Platform boot components
+│ ├── show.elf Splash screen display
+│ ├── installing.png Initial install splash
+│ ├── updating.png Update splash
+│ ├── unzip Update extraction utility
+│ └── leds_off LED control utility
+├── Roms/ ROM files organized by system
+└── MinUI.zip Update package (if present)
+```
+
+### Boot Process
+
+1. Device boots and runs `trimuismart.sh` from `.tmp_update/`
+2. Script sets CPU governor to "performance" mode
+3. If `MinUI.zip` exists:
+ - Turn off LEDs (`leds_off`)
+ - Display `installing.png` (first install) or `updating.png` (update)
+ - Extract `MinUI.zip` to SD card using custom `unzip` utility
+ - Delete `MinUI.zip` after successful extraction
+ - Run `.system/trimuismart/bin/install.sh` to complete setup
+4. Launch MinUI via `.system/trimuismart/paks/MinUI.pak/launch.sh`
+5. If launcher exits, poweroff device (prevents stock firmware from accessing card)
+
+### Update Process
+
+To update MinUI on device:
+1. Place `MinUI.zip` in SD card root
+2. Reboot device
+3. Boot script auto-detects ZIP and performs update
+4. ZIP is deleted after successful extraction
+
+## Platform-Specific Features
+
+### Display Engine 2.0 Architecture
+
+The Trimui Smart uses Allwinner's advanced Display Engine 2.0 with multi-layer composition:
+
+**Hardware Layers**:
+- **Channel 0 (FB_CH)**: Stock framebuffer layer (disabled by MinUI)
+- **Channel 1 (SCALER_CH)**: Main game display with rotation and scaling
+- **Channel 2 (OVERLAY_CH)**: UI overlay with alpha blending (currently unused)
+
+**Benefits**:
+- Hardware scaling for different game resolutions
+- Zero-copy page flipping via direct register access
+- Independent z-ordering and blending per layer
+- 90-degree rotation in hardware pipeline
+
+### ION Memory Allocation
+
+Uses Linux ION allocator for display buffers:
+```c
+// Request physically contiguous memory for DMA
+ion_alloc_data.heap_id_mask = ION_HEAP_TYPE_DMA_MASK;
+ion_alloc_data.flags = 0;
+ion_alloc_data.len = buffer_size;
+ioctl(ion_fd, ION_IOC_ALLOC, &ion_alloc_data);
+```
+
+This provides both physical addresses (for hardware DMA) and virtual addresses (for CPU access).
+
+### Display Rotation
+
+Software performs 90-degree rotation before hardware scaling:
+```c
+rotate_16bpp(src_buffer, dst_buffer, width, height);
+```
+
+**Reason**: MinUI renders in portrait orientation for UI consistency across devices, but the Trimui Smart physical screen is landscape. Rotation happens in the render pipeline.
+
+### CPU Performance
+
+Boot script sets CPU governor to "performance" for maximum clock speed:
+```bash
+echo performance > /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
+```
+
+### Settings Persistence
+
+Uses shared memory (`/SharedSettings`) for inter-process communication:
+- **Host**: keymon daemon creates and manages settings
+- **Clients**: Applications map read/write access
+- **Persistence**: Settings saved to `$USERDATA_PATH/msettings.bin`
+
+Default settings:
+- Brightness: 3 (0-10 scale)
+- Volume (speaker): 8 (0-20 scale)
+- Volume (headphones): 4 (0-20 scale)
+
+### Brightness Control
+
+Brightness uses Allwinner DE2 display ioctl:
+```c
+u32 args[4] = {0};
+args[1] = brightness_value; // 0-256
+ioctl(disp_fd, DISP_LCD_SET_BRIGHTNESS, args);
+```
+
+**Brightness Scale Mapping**:
+| Level | Raw Value |
+|-------|-----------|
+| 0 | 8 |
+| 1 | 12 |
+| 2 | 16 |
+| 3 | 24 (default) |
+| 4 | 32 |
+| 5 | 48 |
+| 6 | 64 |
+| 7 | 96 |
+| 8 | 128 |
+| 9 | 192 |
+| 10 | 256 |
+
+### Volume Control
+
+Volume controlled via ALSA amixer:
+```bash
+amixer sset 'Lineout volume' # 0-31 (converted from 0-20 scale)
+```
+
+**Volume Features**:
+- Separate levels for headphones and speakers
+- Automatic jack detection support (SetJack/GetJack)
+- Switches volume level when headphones plugged/unplugged
+- Mute value: 0 (raw scale)
+
+### SDL Configuration
+
+Boot splash display uses SDL with rotation:
+```c
+putenv("SDL_VIDEO_FBCON_ROTATION=CCW"); // Counter-clockwise rotation
+SDL_Surface *screen = SDL_SetVideoMode(320, 240, 16, SDL_SWSURFACE);
+```
+
+This rotates the framebuffer output to match the physical screen orientation.
+
+## Included Tools
+
+### Files.pak
+DinguxCommander-based file manager:
+- Full file operations (copy, cut, paste, delete, rename)
+- Directory navigation
+- Image preview support
+- Trimui Smart specific branch with optimizations
+
+### LED Control
+`leds_off` utility to disable device LEDs during boot/update process.
+
+## Supported Libretro Cores
+
+The Trimui Smart supports 12 libretro cores:
+
+| Core | System | Notes |
+|------|--------|-------|
+| fceumm | NES/Famicom | Nintendo Entertainment System |
+| gambatte | GB/GBC | Game Boy and Game Boy Color |
+| gpsp | GBA | Game Boy Advance |
+| pcsx_rearmed | PSX | PlayStation 1 |
+| picodrive | Genesis/MD | Sega Genesis/Mega Drive, 32X, Sega CD |
+| snes9x2005_plus | SNES | Super Nintendo (Blargg APU enabled) |
+| mednafen_pce_fast | PC Engine | TurboGrafx-16 / PC Engine |
+| mednafen_vb | Virtual Boy | Nintendo Virtual Boy |
+| mednafen_supafaust | SNES | Accuracy-focused SNES core |
+| mgba | GBA | Game Boy Advance (alternative core) |
+| pokemini | Pokemon Mini | Pokemon Mini handheld |
+| race | Neo Geo Pocket | Neo Geo Pocket / Pocket Color |
+
+**Note**: fake-08 (PICO-8) is commented out in the cores makefile.
+
+## Known Issues / Quirks
+
+### Hardware Quirks
+1. **No L2/R2 Buttons**: Hardware only has L1 and R1 shoulder buttons
+2. **Compact Screen**: 320x240 is the smallest resolution among MinUI platforms
+3. **1x UI Scale**: No scaling applied to UI assets (uses base `assets.png`)
+4. **No Dedicated Power Button**: POWER button not accessible in platform.h
+5. **No Battery Monitor**: Unlike other platforms, no battery overlay daemon
+6. **Portrait-to-Landscape**: Requires software rotation before display
+
+### Display Engine Complexity
+1. **ION Memory Required**: Must use physically contiguous memory for DMA
+2. **Multi-layer Management**: Complex channel/layer configuration compared to simple framebuffer
+3. **Register Mapping**: Direct memory-mapped I/O to display registers
+4. **Rotation Overhead**: Software 90-degree rotation adds processing cost
+
+### Development Notes
+1. **No L3/R3**: Platform lacks clickable analog sticks
+2. **NEON Optimizations**: Platform supports ARM NEON SIMD - use `HAS_NEON` define
+3. **Simple Keymon**: Simpler than other platforms (no jack detection, no HDMI, no power monitoring)
+4. **Shutdown on Exit**: Boot script forces poweroff if MinUI exits (prevents stock firmware access)
+5. **SDL Pre-installed**: Stock firmware provides SDL libraries (no SDL build needed)
+
+### Input Limitations
+- No L2/R2 buttons (marked as BUTTON_NA and CODE_NA)
+- No analog sticks (L3/R3 not available)
+- Power button not exposed in platform.h
+- No dedicated volume buttons (use button combinations)
+
+### Volume and Brightness
+- Volume range: 0-20 (mapped to 0-31 for ALSA)
+- Brightness range: 0-10 (mapped to 8-256 for DE2)
+- Mute volume: 0 (simpler than platforms using negative values)
+- No separate headphone volume control in keymon (handled by msettings library)
+
+## Testing
+
+When testing changes:
+1. Verify boot splash displays correctly (check SDL rotation)
+2. Test volume/brightness controls with button combinations
+3. Verify display output on physical 320x240 screen
+4. Check ION memory allocation and cleanup (no leaks)
+5. Confirm 1x UI scaling displays properly (no assets@2x)
+6. Test update process (ZIP extraction, install.sh execution)
+7. Verify poweroff behavior when launcher exits
+
+## Related Documentation
+
+- Main project docs: `../../README.md`
+- Platform abstraction: `../../all/common/defines.h`
+- Shared code: `../../all/minui/minui.c` (launcher), `../../all/minarch/minarch.c` (libretro frontend)
+- Build system: `../../Makefile` (host), `./makefile` (platform)
+- Platform header: `./platform/platform.h` (all hardware definitions)
+- Display engine: `./platform/platform.c` (DE2 implementation details)
+- Allwinner DE2: `./platform/sunxi_display2.h` (ioctl definitions)
+
+## Maintainer Notes
+
+This platform represents a **compact, low-resolution** implementation in MinUI:
+- Smallest screen resolution (320x240) among active platforms
+- 1x UI scaling (no @2x assets)
+- Advanced display architecture (Allwinner DE2) vs simple framebuffer
+- ION memory allocation for DMA operations
+- Software rotation for portrait-to-landscape conversion
+- Simpler keymon implementation (fewer hardware features to monitor)
+
+The Trimui Smart's Display Engine 2.0 architecture is more complex than framebuffer-based platforms but enables efficient hardware scaling and composition. This serves as a reference implementation for Allwinner SoC-based devices.
+
+**Key Technical Characteristics**:
+- F1C100s SoC (ARM926EJ-S single core)
+- Multi-layer display composition
+- ION memory allocator
+- 90-degree software rotation
+- No battery monitoring overlay
+- Minimal keymon functionality
+
+Changes to display code should account for the DE2 layer management complexity and ION memory allocation requirements.
diff --git a/workspace/zero28/README.md b/workspace/zero28/README.md
new file mode 100644
index 00000000..4674bc83
--- /dev/null
+++ b/workspace/zero28/README.md
@@ -0,0 +1,369 @@
+# Mini Zero 28 (MagicX Mini Zero 28)
+
+Platform implementation for the Mini Zero 28 retro handheld device.
+
+## Hardware Specifications
+
+### Display
+- **Resolution**: 640x480 (VGA)
+- **Color Depth**: 16-bit RGB565
+- **UI Scale**: 2x (uses `assets@2x.png`)
+- **Orientation**: Auto-detects portrait mode and applies 90-degree rotation when height > width
+- **Hardware**: `/dev/disp` ioctl-based backlight and brightness control
+
+### Input
+- **D-Pad**: Up, Down, Left, Right (via joystick HAT)
+- **Face Buttons**: A, B, X, Y
+- **Shoulder Buttons**: L1, R1, L2, R2
+- **Analog Sticks**: Left (L3 clickable) and Right (R3 clickable)
+- **System Buttons**:
+ - MENU button
+ - POWER button (code 102 - KEY_HOME)
+ - Dedicated PLUS/MINUS volume buttons
+
+**Note**: A/B and X/Y button mappings were swapped in the first public stock release.
+
+### Input Method
+- **Primary**: SDL Joystick API (joystick index 0)
+- **HAT Input**: D-pad uses HAT events (indices 13-16)
+- **Evdev**: Volume/brightness keys monitored via `/dev/input/event2` and `/dev/input/event3`
+- **No SDL Keyboard**: All keyboard mappings are `BUTTON_NA`
+
+### CPU & Performance
+- ARM processor with NEON SIMD support
+- Four CPU speed profiles:
+ - **MENU**: 600 MHz (UI navigation)
+ - **POWERSAVE**: 816 MHz (low-demand games)
+ - **NORMAL**: 1416 MHz (most games)
+ - **PERFORMANCE**: 1800 MHz (demanding games)
+- Governor control via `/sys/devices/system/cpu/cpu0/cpufreq/scaling_setspeed`
+
+### Power Management
+- **Battery**: AXP2202 power management IC
+- **Battery path**: `/sys/class/power_supply/axp2202-battery/capacity`
+- **Charging detection**: `/sys/class/power_supply/axp2202-usb/online`
+- **WiFi monitoring**: `/sys/class/net/wlan0/operstate` (polled during battery checks)
+
+### Storage
+- SD card mounted at `/mnt/SDCARD`
+
+### Audio
+- **Volume Scale**: Inverted (63 = mute, 0 = max volume)
+- **Sample Rate**: 400 samples (buffer size tuned for fceumm compatibility)
+- **Mixer Controls**:
+ - "Headphone" - set to 0 (100%)
+ - "digital volume" - set to 0 (100%)
+ - "Soft Volume Master" - set to 255 (100%)
+ - "DAC volume" - active volume control (0 or 96-160)
+- **Headphone jack detection**: Via EV_SW switch events (CODE_JACK = 2)
+- **Separate volume levels**: Maintains independent speaker/headphone volume settings
+
+## Platform Architecture
+
+The Zero 28 platform uses several unique features:
+
+### SDL2 Joystick Input
+Unlike many MinUI platforms that use SDL keyboard events, the Zero28 uses SDL_Joystick API for all gamepad input. The D-pad uses joystick HAT events rather than discrete button events.
+
+### Hardware-Accelerated Rendering
+The platform leverages SDL2's hardware-accelerated renderer with support for:
+- **Crisp rendering**: Nearest neighbor upscale + bilinear downscale
+- **Soft rendering**: Pure bilinear scaling
+- **Visual effects**: Grid and line overlays for CRT simulation
+- **Display rotation**: Automatic 90-degree rotation for portrait displays
+
+### Backlight Control
+Uses external `bl_enable` and `bl_disable` binaries that communicate with `/dev/disp` via ioctl commands (`DISP_LCD_BACKLIGHT_ENABLE` / `DISP_LCD_BACKLIGHT_DISABLE`).
+
+## Directory Structure
+
+```
+zero28/
+├── platform/ Platform-specific hardware definitions
+│ ├── platform.h Button mappings, display specs, paths
+│ └── platform.c Platform implementation (883 lines)
+├── keymon/ Hardware button monitoring daemon
+│ └── keymon.c Volume/brightness via MENU+PLUS/MINUS
+├── libmsettings/ Settings library (volume, brightness, jack)
+│ ├── msettings.h Settings API header
+│ └── msettings.c Shared memory settings implementation
+├── bl/ Backlight enable/disable utilities
+│ ├── bl_enable.c Enable backlight via ioctl
+│ └── bl_disable.c Disable backlight via ioctl
+├── show/ Boot splash screen display
+│ └── show.c SDL2-based PNG display with rotation support
+├── install/ Installation assets and boot script
+│ ├── boot.sh Boot/update handler (becomes zero28.sh)
+│ ├── installing.png Boot splash for fresh install (640x480)
+│ └── updating.png Boot splash for updates (640x480)
+├── cores/ Libretro cores (submodules + builds)
+└── other/ Third-party dependencies
+ └── DinguxCommander-sdl2/ File manager (SDL2 fork)
+```
+
+## Input System
+
+The Zero28 uses a **joystick-centric input architecture**:
+
+1. **SDL Joystick API**: All gamepad input via `SDL_JoystickOpen(0)`
+2. **HAT D-Pad**: D-pad uses joystick HAT (indices 13-16, not discrete buttons)
+3. **Evdev Monitoring**: `keymon` watches `/dev/input/event2` and `/dev/input/event3` for volume/brightness keys
+4. **No SDL Keyboard**: Platform does not use SDL keyboard events (`BUTTON_NA` for all keyboard mappings)
+
+### Button Combinations
+
+| Combination | Function |
+|-------------|----------|
+| PLUS | Increase volume |
+| MINUS | Decrease volume |
+| MENU + PLUS | Increase brightness |
+| MENU + MINUS | Decrease brightness |
+| POWER | Sleep/wake device |
+| X (in launcher) | Resume from save state |
+
+### Input Event Devices
+- **event2**: Gamepad input (face buttons, shoulders, menu)
+- **event3**: Volume buttons (PLUS/MINUS)
+
+### Hardware Button Details
+- **MENU button code**: 158 (CODE_MENU in keymon)
+- **Volume up code**: 115 (CODE_PLUS in keymon)
+- **Volume down code**: 114 (CODE_MINUS in keymon)
+- **Headphone jack switch**: 2 (CODE_JACK, generates EV_SW events)
+- **Volume range**: 0-20 (separate speaker/headphone settings)
+- **Brightness range**: 0-10 (non-linear mapping to 1-255 raw values)
+
+## Building
+
+### Prerequisites
+Requires Docker with Zero28 cross-compilation toolchain.
+
+### Build Commands
+
+```bash
+# Enter platform build environment
+make PLATFORM=zero28 shell
+
+# Inside container: build all platform components
+cd /root/workspace/zero28
+make
+
+# This builds:
+# - bl_enable (backlight enable utility)
+# - bl_disable (backlight disable utility)
+# - show.elf (boot splash display)
+# - keymon (button monitoring daemon)
+# - libmsettings.so (settings library)
+# - DinguxCommander-sdl2 (file manager)
+# - All libretro cores in cores/
+```
+
+### Dependencies
+The platform automatically clones required dependencies on first build:
+- **DinguxCommander-sdl2**: `github.com/shauninman/DinguxCommander-sdl2.git` (SDL2 fork of file manager)
+
+Note: The Zero28 uses SDL2 (unlike many MinUI platforms that use SDL 1.2).
+
+## Installation
+
+### File System Layout
+
+MinUI installs to the SD card with the following structure:
+
+```
+/mnt/SDCARD/
+├── .system/
+│ ├── zero28/ Platform-specific binaries
+│ │ ├── bin/ Utilities (keymon, bl_enable, bl_disable, etc.)
+│ │ │ └── install.sh Post-update installation script (no-op)
+│ │ └── paks/ Applications and emulators
+│ │ └── MinUI.pak/ Main launcher
+│ └── res/ Shared UI assets
+│ ├── assets@2x.png UI sprite sheet (2x scale)
+│ ├── line-*.png Line effect overlays (2-8px)
+│ ├── grid-*.png Grid effect overlays (2-11px)
+│ └── BPreplayBold-unhinted.otf
+├── .tmp_update/ Update staging area
+│ └── zero28/ Platform boot components
+│ ├── show.elf Splash screen display
+│ ├── installing.png Initial install splash
+│ └── updating.png Update splash
+├── Roms/ ROM files organized by system
+└── MinUI.zip Update package (if present)
+```
+
+### Boot Process
+
+1. Device boots and runs `zero28.sh` (from `.tmp_update/`)
+2. Script sets CPU governor to "performance" (600 MHz)
+3. If `MinUI.zip` exists:
+ - Display `installing.png` (first install) or `updating.png` (update)
+ - Rename `.tmp_update` to `.tmp_update-old`
+ - Extract `MinUI.zip` to SD card
+ - Delete ZIP and old update directory
+ - Run `.system/zero28/bin/install.sh` to complete setup
+4. Launch MinUI via `.system/zero28/paks/MinUI.pak/launch.sh`
+5. If launcher exits, power off device (prevents stock firmware from accessing card)
+
+### Update Process
+
+To update MinUI on device:
+1. Place `MinUI.zip` in SD card root
+2. Reboot device
+3. Boot script auto-detects ZIP and performs update
+4. ZIP is deleted after successful extraction
+
+## Platform-Specific Features
+
+### Visual Effects System
+The Zero28 has sophisticated support for retro display effects:
+
+**Line Effects** (scanlines):
+- Simulates CRT horizontal scanlines
+- Available scales: 2px, 3px, 4px, 5px, 6px, 8px
+- Opacity: 50% (alpha 128)
+
+**Grid Effects** (pixel grids):
+- Simulates LCD/CRT pixel structure
+- Available scales: 2px, 3px, 4px, 5px, 6px, 8px, 11px
+- Variable opacity based on scale (25-64%)
+- Supports color tinting (e.g., DMG Game Boy green)
+
+Effects are automatically scaled based on game resolution and applied as SDL texture overlays.
+
+### Crisp Rendering Mode
+Two rendering quality modes:
+- **SHARPNESS_SOFT**: Bilinear scaling (smooth)
+- **SHARPNESS_CRISP**: Nearest neighbor upscale (4x for small resolutions) + bilinear downscale
+
+The crisp mode provides pixel-perfect scaling for low-resolution systems (Game Boy, GBC, NES) while maintaining smooth output at native resolution.
+
+### Display Rotation
+Automatically detects portrait displays (height > width) and applies 90-degree rotation to all rendering:
+```c
+SDL_GetCurrentDisplayMode(0, &mode);
+if (mode.h > mode.w) rotate = 1;
+```
+
+### Brightness Control
+Non-linear brightness mapping for better perceptual uniformity:
+```
+Level 0: 1 (near-off)
+Level 1: 8
+Level 2: 16
+Level 3: 32
+Level 4: 48
+Level 5: 72
+Level 6: 96
+Level 7: 128
+Level 8: 160
+Level 9: 192
+Level 10: 255 (max)
+```
+
+Applied via `/dev/disp` ioctl (`DISP_LCD_SET_BRIGHTNESS`).
+
+### Volume Control
+Complex volume system with multiple mixer controls:
+1. One-time setup: Set base levels for "Headphone", "digital volume", and "Soft Volume Master"
+2. Active control: Adjust "DAC volume" (0 = mute, 96-160 = audible range)
+3. Separate settings: Speaker and headphone volumes stored independently
+4. Auto-switch: Headphone jack detection switches between settings automatically
+
+Volume scale: 0-20 (user) → 0 or 96-160 (raw DAC)
+
+### WiFi Integration
+WiFi status is monitored during battery polling (avoid separate daemon):
+```c
+char status[16];
+getFile("/sys/class/net/wlan0/operstate", status, 16);
+online = prefixMatch("up", status);
+```
+
+Accessible via `PLAT_isOnline()` for UI indicators.
+
+## Included Tools
+
+### Files.pak
+DinguxCommander-based file manager (SDL2 fork) with:
+- File operations (copy, cut, paste, delete, rename)
+- Directory navigation
+- Image preview support
+- Integrated with MinUI launcher
+
+### Clock.pak
+System clock/time display tool
+
+### Input.pak
+Input configuration utility
+
+## Known Issues / Quirks
+
+### Platform Quirks
+1. **Button Swap**: A/B and X/Y mappings were swapped in first stock firmware release
+2. **Inverted Volume**: Volume scale is inverted (63 = mute, 0 = max) unlike most platforms
+3. **Joystick-Only**: No SDL keyboard support - all input via joystick API
+4. **HAT D-Pad**: D-pad uses HAT events instead of discrete button events
+6. **Power-Off on Exit**: Boot script powers off if MinUI exits (prevents stock firmware access)
+
+### Development Notes
+1. **SDL2 Platform**: Uses SDL2 (not SDL 1.2 like many MinUI platforms)
+2. **Hardware Rendering**: Leverages SDL2 hardware-accelerated renderer with texture targets
+3. **Effect System**: Sophisticated overlay system with multiple effect types and scales
+4. **Dual Input Devices**: Monitors two separate `/dev/input/event*` devices for complete input
+5. **Rotation Support**: Auto-detects and handles portrait displays transparently
+6. **AXP2202 PMIC**: Battery monitoring via AXP2202-specific sysfs paths
+
+### Input Limitations
+- HAT D-Pad means different input handling than button-based D-pads
+- Joystick API required - cannot use simpler keyboard-based input
+- Button swap issue may cause confusion for users familiar with stock firmware
+
+### Volume Quirks
+- Inverted raw scale (0 = max, 63 = mute) is opposite of most platforms
+- Complex mixer setup requires multiple controls configured at startup
+- Uses `amixer` system calls instead of direct ALSA API (easier but less efficient)
+
+### Backlight Quirks
+- External utilities (`bl_enable`/`bl_disable`) required for backlight control
+- Must use ioctl to `/dev/disp` device (not standard sysfs backlight interface)
+- Separate brightness control via different ioctl command
+
+## Testing
+
+When testing changes:
+1. Verify boot splash displays correctly (check rotation if using portrait display)
+2. Test volume control with PLUS/MINUS buttons
+3. Verify brightness control with MENU+PLUS/MINUS
+4. Check headphone jack detection and volume switching
+5. Test visual effects (grid/line overlays) with different games
+6. Verify crisp vs soft rendering modes
+7. Test both portrait and landscape display orientations
+8. Confirm battery and WiFi status indicators work
+
+## Related Documentation
+
+- Main project docs: `../../README.md`
+- Platform abstraction: `../../all/common/defines.h`
+- Shared code: `../../all/minui/minui.c` (launcher), `../../all/minarch/minarch.c` (libretro frontend)
+- Build system: `../../Makefile` (host), `./makefile` (platform)
+- Platform header: `./platform/platform.h` (all hardware definitions)
+- Platform implementation: `./platform/platform.c` (883 lines of SDL2 rendering and effects)
+
+## Maintainer Notes
+
+This platform represents several **unique characteristics** in MinUI:
+- **SDL2 adoption**: One of few platforms using SDL2 instead of SDL 1.2
+- **Hardware rendering**: Leverages GPU-accelerated rendering with texture targets
+- **Effects system**: Most sophisticated visual effects implementation in MinUI
+- **Joystick-centric**: Pure joystick input (no keyboard fallback)
+- **AXP2202 PMIC**: Different battery monitoring IC than most platforms
+- **Display rotation**: Automatic portrait mode detection and rotation
+
+This platform demonstrates MinUI's flexibility in adapting to:
+- Modern SDL2 graphics stack
+- Joystick-based input systems
+- Advanced rendering features (effects, crisp mode, rotation)
+- Alternative PMIC hardware
+
+This platform may serve as reference for future SDL2-based platforms or devices requiring display rotation support.