6 Commits

Author SHA1 Message Date
Douglas Teles 9b55f926c0 Update README for mainline kernel and overlay architecture
Rewrite to reflect current state: kernel 6.12.61 mainline LTS, board DTB
auto-selection via SARADC, panel overlay system (20 panels), two image
variants (original + clone), Flasher app for panel selection, updated
boot flow, build pipeline, and project structure.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 17:23:15 -03:00
Douglas Teles b36a333523 Add Flasher app specification
Complete spec for the Arch R Flasher desktop app: console type selection,
panel identification wizard, image download from GitHub releases, SD card
flashing with panel overlay auto-configuration. Supports Windows/macOS/Linux.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 17:23:03 -03:00
Douglas Teles c8e7fe99e9 Add ES Tools menu scripts and gptokeyb configs (WIP)
Interactive tool scripts for EmulationStation's OPTIONS menu at /opt/system/:
system-info, wifi-setup, bluetooth-setup, performance-mode, suspend-mode,
usb-mode, factory-reset. Uses shared menu-lib.sh with fbcon rendering.

Gamepad configs: default.gptk (RetroArch), tools.gptk (menu navigation
with D-pad arrows, A=enter, B=escape).

Note: scripts need further testing on hardware — left disabled for now.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 17:22:49 -03:00
Douglas Teles 06dc2d16f3 Add system scripts, services, and boot splash
System daemons: hotkeys (volume/brightness), automount, bluetooth agent,
memory manager, sleep/suspend, USB gadget mode, save-config persistence.

Boot splash: initramfs SVG renderer (fbsplash + svg_parser) for 0.7s splash.

Panel tools: generate-panel-dtbos.sh rewrite, convert-panel.py for ROCKNIX
panel data extraction, archr-dtbo.py for runtime overlay management.

Input: archr-gptokeyb.c gamepad-to-keyboard mapper via uinput.

Launch wrappers: emulationstation.sh and retroarch-launch.sh updated for
KMS/DRM + Mesa 26 Panfrost environment.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 17:22:30 -03:00
Douglas Teles 8650d940e2 Migrate to mainline kernel 6.12.61 + board/overlay architecture
Major architecture change: move from BSP kernel 6.6 with pre-merged panel
DTBs to mainline kernel 6.12.61 LTS with separated board DTBs + panel
overlays.

- Board DTB = hardware profile (GPIOs, PMIC, joypad, audio). 16 boards.
  Auto-selected by U-Boot via SARADC ADC reading (hwrev).
- Panel overlay = display init sequence. 20 panels. Applied at boot time
  via boot.ini fdt apply.
- Two image variants: original (a_boot.ini) and clone (b_boot.ini)
- Kernel cross-compiles from x86 host (no ARM chroot needed)
- Initramfs boot splash with SVG rendering at 0.7s
- Out-of-tree joypad driver (singleadc-joypad) for clone boards
- Panel generic-dsi driver with archr,generic-dsi compatible

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 17:20:09 -03:00
Douglas Teles 70342ca457 ROADMAP: detail beta1.2 system changes and update last-updated
Input merger, RetroArch tuning, panel ordering, no-panel variant,
mirror list, boot.ini autodetect.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 02:24:00 -03:00
138 changed files with 66311 additions and 1889 deletions
+14
View File
@@ -3,6 +3,20 @@ output/
# Kernel and bootloader source (cloned during build)
kernel/src/
# Kernel module build artifacts (compiled .ko/.o are not source)
kernel/drivers/**/*.o
kernel/drivers/**/*.ko
kernel/drivers/**/*.mod
kernel/drivers/**/*.mod.c
kernel/drivers/**/*.mod.o
kernel/drivers/**/*.cmd
kernel/drivers/**/Module.symvers
kernel/drivers/**/modules.order
kernel/drivers/**/.module-common.o
# Compiled DTBs in source tree (use output/boot/dtbs/ instead)
kernel/dts/*.dtb
bootloader/src/
# Build cache
+610
View File
File diff suppressed because it is too large Load Diff
+146 -135
View File
@@ -8,22 +8,32 @@
>
> Leve como uma pluma.
Arch R is a custom Linux distribution built from scratch for the R36S handheld gaming console (RK3326 SoC, Mali-G31 GPU, 640x480 MIPI DSI display). It supports all R36S variants and clones with 18 different display panels.
Arch R is a custom Linux distribution built from scratch for the R36S handheld gaming console (RK3326 SoC, Mali-G31 GPU, 640x480 MIPI DSI display). It supports all R36S variants and clones — 16 board profiles and 20 display panels.
## Features
- **Kernel 6.6.89** (Rockchip BSP) — custom DTS with joypad, panel init sequences, audio, USB OTG
- **Kernel 6.12.61** (Mainline LTS) — board auto-detection via SARADC, 16 board DTBs, panel overlays
- **Mesa 26 Panfrost** — open-source GPU driver, GLES 1.0/2.0/3.1, no proprietary blobs
- **EmulationStation** (fcamod fork) — 78fps stable, GLES 1.0 native rendering
- **RetroArch 1.22.2** — KMS/DRM + EGL, 18+ cores pre-installed
- **19-second boot** — U-Boot logo → kernel → systemd EmulationStation
- **Full audio** — ALSA, speaker + headphone auto-switch, volume hotkeys
- **Battery monitoring** — LED warning, capacity/voltage/temp reporting
- **Multi-panel support** — 18 panel DTBOs (6 original R36S + 12 clones)
- **19-second boot** — initramfs splash at 0.7s, systemd to EmulationStation
- **Full audio** — ALSA, speaker + headphone auto-switch, volume/brightness hotkeys
- **Battery monitoring** — capacity/voltage reporting, LED warning
- **Multi-panel support** — 20 panel overlays (7 original + 13 clone variants)
- **Two images** — Original R36S and Clone boards, both auto-detect hardware
## Quick Start — Flash a Pre-built Image
## Quick Start
Download the latest image from [Releases](../../releases), then:
Download the latest images from [Releases](../../releases):
- **`ArchR-R36S-*.img.xz`** — for genuine R36S, OGA, OGS, RG351V/M, Chi, R33S
- **`ArchR-R36S-clone-*.img.xz`** — for K36 clones, RGB20S, RGB10X, XU-Mini-M, R36Max
### Using Arch R Flasher (recommended)
Download the [Arch R Flasher](https://github.com/archr-linux/archr-flasher) app, select your console type and display panel, and flash directly. The Flasher handles image download, panel overlay selection, and SD card writing.
### Manual Flash
```bash
xz -d ArchR-R36S-*.img.xz
@@ -31,7 +41,16 @@ sudo dd if=ArchR-R36S-*.img of=/dev/sdX bs=4M status=progress
sync
```
Insert the SD card into your R36S and power on. First boot creates a ROMS partition automatically.
After flashing, mount the BOOT partition and copy your panel overlay:
```bash
sudo mount /dev/sdX1 /mnt
sudo cp /mnt/overlays/panel4-v22.dtbo /mnt/overlays/mipi-panel.dtbo
sudo umount /mnt
sync
```
Insert the SD card and power on. The correct board DTB is selected automatically.
## Building from Source
@@ -40,7 +59,6 @@ Insert the SD card into your R36S and power on. First boot creates a ROMS partit
- **OS:** Ubuntu 22.04+ (or any Linux with QEMU user-static support)
- **Disk:** 30GB+ free space
- **RAM:** 4GB+ recommended
- **Time:** ~3-4 hours (first build), ~1 hour (incremental)
### Install Dependencies
@@ -66,21 +84,22 @@ sudo apt install -y \
### Build Everything
```bash
git clone --recurse-submodules https://github.com/user/Arch-R.git
git clone --recurse-submodules https://github.com/archr-linux/Arch-R.git
cd Arch-R
# Full build (kernel + rootfs + mesa + ES + retroarch + panels + image)
# Full build: kernel + rootfs + mesa + ES + retroarch + panels + both images
sudo ./build-all.sh
```
The flashable image will be at `output/images/ArchR-R36S-YYYYMMDD.img.xz` (~860MB compressed).
Output: `output/images/ArchR-R36S-YYYYMMDD.img.xz` and `ArchR-R36S-clone-YYYYMMDD.img.xz`
### Build Individual Components
```bash
sudo ./build-all.sh --kernel # Kernel only (~10 min)
sudo ./build-all.sh --rootfs # Rootfs + Mesa + ES + RetroArch (~3 hours)
sudo ./build-all.sh --image # Image assembly only (~2 min)
sudo ./build-all.sh --kernel # Kernel + initramfs (~10 min, cross-compile)
sudo ./build-all.sh --rootfs # Rootfs + Mesa + ES + RetroArch (~3 hours, QEMU chroot)
sudo ./build-all.sh --uboot # U-Boot (~2 min)
sudo ./build-all.sh --image # Image assembly only (~2 min per variant)
sudo ./build-all.sh --clean # Remove all build artifacts
```
@@ -88,53 +107,63 @@ sudo ./build-all.sh --clean # Remove all build artifacts
```
build-all.sh
├── build-kernel.sh # Cross-compile kernel 6.6.89 (~10 min)
├── build-rootfs.sh # Arch Linux ARM rootfs in QEMU chroot (~45 min)
├── build-mesa.sh # Mesa 26 with Panfrost + GLES 1.0 (~30 min)
├── build-emulationstation.sh # ES-fcamod with 21 patches (~20 min)
├── build-retroarch.sh # RetroArch + cores (~40 min)
├── generate-panel-dtbos.sh # 18 panel DTBO overlays (~10 sec)
── build-image.sh # Assemble SD card image (~2 min)
├── build-initramfs.sh # Boot splash (SVG rendering, ~648KB)
├── build-kernel.sh # Cross-compile kernel 6.12.61 (~10 min)
├── build-rootfs.sh # Arch Linux ARM in QEMU chroot (~45 min)
├── build-mesa.sh # Mesa 26 Panfrost + GLES 1.0 (~30 min)
├── build-emulationstation.sh # ES-fcamod with patches (~20 min)
├── build-retroarch.sh # RetroArch + cores (~40 min)
── generate-panel-dtbos.sh # 20 panel overlays (~10 sec)
├── build-uboot.sh # BSP U-Boot for original boards
├── build-uboot-clone.sh # Mainline U-Boot for clone boards
└── build-image.sh # SD card image (×2 variants)
```
All builds happen inside a QEMU aarch64 chroot — no cross-compilation issues.
## Project Structure
```
Arch-R/
├── build-all.sh # Master build orchestrator
├── build-kernel.sh # Kernel compilation
├── build-rootfs.sh # Root filesystem (Arch Linux ARM + services)
├── build-mesa.sh # Mesa 26 GPU driver
├── build-emulationstation.sh # EmulationStation frontend
├── build-retroarch.sh # RetroArch + cores
├── build-image.sh # SD card image assembly
├── build-all.sh # Master build orchestrator
├── build-kernel.sh # Kernel 6.12.61 cross-compilation
├── build-initramfs.sh # Initramfs with boot splash
├── build-rootfs.sh # Root filesystem (Arch Linux ARM)
├── build-mesa.sh # Mesa 26 GPU driver
├── build-emulationstation.sh # EmulationStation frontend
├── build-retroarch.sh # RetroArch + cores
├── build-uboot.sh # BSP U-Boot (original boards)
├── build-uboot-clone.sh # Mainline U-Boot (clone boards)
├── build-image.sh # SD card image assembly
├── config/
│ ├── archr-6.6-r36s.config # Kernel config fragment (393 options)
│ ├── boot.ini # U-Boot fallback boot script
│ ├── es_systems.cfg # EmulationStation system definitions
│ ├── retroarch.cfg # RetroArch base configuration
│ ├── asound.conf # ALSA audio configuration
── autoconfig/ # RetroArch controller autoconfig
│ ├── linux-archr-base.config # Kernel config (mainline 6.12)
│ ├── a_boot.ini # Boot script — original variant
│ ├── b_boot.ini # Boot script — clone variant
│ ├── es_systems.cfg # EmulationStation systems
│ ├── retroarch.cfg # RetroArch base config
── asound.conf # ALSA audio config
│ ├── gptokeyb/ # Gamepad-to-keyboard mappings
│ ├── udev/ # udev rules (automount, USB gadget)
│ └── autoconfig/ # RetroArch controller autoconfig
├── kernel/
── dts/
├── rk3326-gameconsole-r36s.dts # Custom R36S device tree
│ └── R36S-DTB/ # Reference panel DTBs
── dts/archr/ # Board device trees (16 boards)
└── drivers/ # Out-of-tree joypad driver
├── patches/ # Kernel patches (mainline + device)
├── scripts/
│ ├── emulationstation.sh # ES launch wrapper
│ ├── retroarch-launch.sh # RetroArch launch wrapper
│ ├── archr-hotkeys.py # Volume/brightness hotkey daemon
│ ├── first-boot.sh # First boot setup (ROMS partition)
│ ├── generate-panel-dtbos.sh # Panel overlay generator
│ ├── pmic-poweroff # PMIC shutdown handler
── vlc-stub.c # VLC stub library for ES build
│ ├── emulationstation.sh # ES launch wrapper
│ ├── retroarch-launch.sh # RetroArch launch wrapper
│ ├── archr-hotkeys.py # Volume/brightness hotkey daemon
│ ├── archr-init.c # Initramfs splash (static binary)
│ ├── archr-gptokeyb.c # Gamepad-to-keyboard mapper
│ ├── panel-detect.py # Panel detection
── generate-panel-dtbos.sh # Panel overlay generator
│ ├── pmic-poweroff # PMIC shutdown handler
│ └── opt-system/ # ES Tools menu scripts
├── bootloader/
│ └── u-boot-r36s-working/ # Pre-built U-Boot binaries
│ └── u-boot-rk3326/ # U-Boot source (submodule)
├── prebuilt/
│ └── cores/ # Pre-built RetroArch cores (FBNeo, MAME, N64, PSP)
├── ArchR.png # Boot logo source
── ROADMAP.md # Development diary
│ └── cores/ # Pre-built RetroArch cores
├── ArchR.png # Boot logo
── ROADMAP.md # Development diary
└── FLASHER.md # Flasher app specification
```
## Hardware
@@ -144,122 +173,104 @@ Arch-R/
| SoC | Rockchip RK3326 (4x Cortex-A35 @ 1.5GHz) |
| GPU | Mali-G31 Bifrost (Mesa Panfrost, 600MHz) |
| RAM | 1GB DDR3L (786MHz) |
| Display | 640x480 MIPI DSI (18 panel variants) |
| Display | 640x480 MIPI DSI (20 panel variants) |
| Audio | RK817 codec, speaker + headphone jack |
| Storage | MicroSD (boot + rootfs + ROMS) |
| Storage | MicroSD (BOOT + rootfs + ROMS) |
| Controls | D-pad, ABXY, L1/L2/R1/R2, dual analog sticks |
| Battery | 3200mAh Li-Po (RK817 charger) |
| USB | OTG with host mode (VBUS power on GPIO0_B7) |
| USB | OTG with host/gadget mode switching |
## Supported Panels
## Architecture
Arch R supports 18 display panels via pre-merged DTBs. Each panel variant has its own DTB file with the correct init sequence and timings applied at build-time.
Arch R separates **board configuration** from **panel configuration**:
There are two separate images: **Original** (for genuine R36S) and **Clone** (for R36S clones like G80CA, K36, etc.). Each image has its own panel list.
- **Board DTB** = hardware profile (GPIOs, PMIC, joypad, audio codec). One per board variant. Selected automatically by U-Boot via SARADC ADC reading.
- **Panel overlay** = display init sequence and timings. One per panel type. Applied on top of the board DTB at boot time.
> **Note:** The numerical panel ordering below is available starting from **beta1.2**. Earlier versions may have a different order.
This means the same image works on all boards of a variant — only the panel overlay needs to match your specific display.
### Panel Auto-Detection
### Supported Boards
On first boot, Arch R runs a **panel detection wizard** that guides you through selecting your display panel:
| Board | DTB | Image |
|-------|-----|-------|
| R36S (original) | rk3326-gameconsole-r36s | Original |
| Odroid Go Advance | rk3326-odroid-go2 | Original |
| Odroid Go Advance v1.1 | rk3326-odroid-go2-v11 | Original |
| Odroid Go Super | rk3326-odroid-go3 | Original |
| Anbernic RG351V | rk3326-anbernic-rg351v | Original |
| Anbernic RG351M | rk3326-anbernic-rg351m | Original |
| GameForce Chi | rk3326-gameforce-chi | Original |
| R33S | rk3326-gameconsole-r33s | Original |
| MagicX XU10 | rk3326-magicx-xu10 | Original |
| K36 / R36S clone | rk3326-gameconsole-r36max | Clone |
| EE clone | rk3326-gameconsole-eeclone | Clone |
| Powkiddy RGB10 | rk3326-powkiddy-rgb10 | Clone |
| Powkiddy RGB10X | rk3326-powkiddy-rgb10x | Clone |
| Powkiddy RGB20S | rk3326-powkiddy-rgb20s | Clone |
| MagicX XU-Mini-M | rk3326-magicx-xu-mini-m | Clone |
| BatLexp G350 | rk3326-batlexp-g350 | Clone |
1. **If your screen works** (you see text on screen): press **A** to confirm the current panel
2. **If your screen is black** (wrong panel): listen for audio beeps and use buttons to navigate:
- Each panel plays a different number of beeps (Panel 0 = 1 beep, Panel 1 = 2 beeps, etc.)
- Press **B** to skip to the next panel
- Press **A** to confirm (you'll hear 3 rapid beeps)
- The system reboots with the correct panel applied
### Supported Panels
Your selection is saved permanently. To reset it later, **hold X during boot**.
#### Original R36S (7 panels)
### R36S Original (6 panels)
| Panel | Overlay file | Controller | Notes |
|-------|-------------|------------|-------|
| Panel 0 | panel0.dtbo | ST7703 | Early R36S units |
| Panel 1 | panel1.dtbo | ST7703 | V10 board |
| Panel 2 | panel2.dtbo | ST7703 | V12 board |
| Panel 3 | panel3.dtbo | ST7703 | V20 board |
| Panel 4 | panel4.dtbo | ST7703 | V22 board |
| Panel 4-V22 | panel4-v22.dtbo | ST7703 | Most common (~60%) |
| Panel 5 | panel5.dtbo | ST7703 | V22 Q8 variant |
Default: **Panel 4-V22** (~60% of units)
R46H (1024x768): `r46h.dtbo`
| Beeps | Panel | DTB | Notes |
|-------|-------|-----|-------|
| 1 | Panel 0 | kernel-panel0.dtb | Early R36S units |
| 2 | Panel 1-V10 | kernel-panel1.dtb | V10 board marking |
| 3 | Panel 2-V12 | kernel-panel2.dtb | V12 board marking |
| 4 | Panel 3-V20 | kernel-panel3.dtb | V20 board marking |
| 5 | **Panel 4-V22** *(default)* | kernel.dtb | Most common |
| 6 | Panel 5-V22 Q8 | kernel-panel5.dtb | V22 Q8 variant |
#### Clone R36S (13 panels)
### R36S Clone (12 panels)
Default: **Clone 8 ST7703 G80CA**
| Beeps | Panel | DTB | Notes |
|-------|-------|-----|-------|
| 1 | Clone 1 | kernel-clone1.dtb | ST7703 |
| 2 | Clone 2 | kernel-clone2.dtb | ST7703 |
| 3 | Clone 3 | kernel-clone3.dtb | NV3051D |
| 4 | Clone 4 | kernel-clone4.dtb | NV3051D |
| 5 | Clone 5 | kernel-clone5.dtb | ST7703 |
| 6 | Clone 6 | kernel-clone6.dtb | NV3051D |
| 7 | Clone 7 | kernel-clone7.dtb | JD9365DA |
| 8 | **Clone 8** *(default)* | kernel.dtb | ST7703 (G80CA-MB) |
| 9 | Clone 9 | kernel-clone9.dtb | NV3051D |
| 10 | Clone 10 | kernel-clone10.dtb | ST7703 variant |
| 11 | R36 Max | kernel-r36max.dtb | 720x720 ST7703 |
| 12 | RX6S | kernel-rx6s.dtb | NV3051D variant |
| Panel | Overlay file | Controller | Notes |
|-------|-------------|------------|-------|
| Clone 1 | clone_panel_1.dtbo | ST7703 | |
| Clone 2 | clone_panel_2.dtbo | ST7703 | |
| Clone 3 | clone_panel_3.dtbo | NV3051D | |
| Clone 4 | clone_panel_4.dtbo | NV3051D | |
| Clone 5 | clone_panel_5.dtbo | ST7703 | |
| Clone 6 | clone_panel_6.dtbo | NV3051D | |
| Clone 7 | clone_panel_7.dtbo | JD9365DA | |
| Clone 8 | clone_panel_8.dtbo | ST7703 | G80CA — most common |
| Clone 9 | clone_panel_9.dtbo | NV3051D | |
| Clone 10 | clone_panel_10.dtbo | ST7703 | |
| R36 Max | r36_max.dtbo | ST7703 | 720x720 |
| RX6S | rx6s.dtbo | NV3051D | |
### Manual Panel Selection
If you prefer to set the panel manually (e.g., you know which panel you have from ArkOS/dArkOS):
**Step 1 -- Mount the BOOT partition on your PC**
Mount the BOOT partition and copy the correct overlay as `mipi-panel.dtbo`:
```bash
lsblk
sudo mount /dev/sdX1 /mnt
```
**Step 2 -- Create panel.txt**
# Example: set Panel 4-V22 (most common original R36S panel)
sudo cp /mnt/overlays/panel4-v22.dtbo /mnt/overlays/mipi-panel.dtbo
```bash
# Example: Panel 3-V20 (original R36S)
echo 'PanelNum=3
PanelDTB=kernel-panel3.dtb' | sudo tee /mnt/panel.txt
# Example: set Clone 8 (most common clone panel)
sudo cp /mnt/overlays/clone_panel_8.dtbo /mnt/overlays/mipi-panel.dtbo
# Mark as confirmed (skip wizard on next boot)
echo 'confirmed' | sudo tee /mnt/panel-confirmed
```
For default panels (no custom DTB needed):
```bash
# Original R36S: Panel 4-V22 (default)
echo 'PanelNum=4
PanelDTB=' | sudo tee /mnt/panel.txt
# Clone R36S: Clone 8 G80CA (default)
echo 'PanelNum=C8
PanelDTB=' | sudo tee /mnt/panel.txt
echo 'confirmed' | sudo tee /mnt/panel-confirmed
```
**Step 3 -- Unmount and boot**
```bash
sudo umount /mnt
sync
```
**To reset panel selection:** hold **X** during boot, or delete `panel-confirmed` from the BOOT partition.
## Boot Flow
```
Power On
→ U-Boot (idbloader → trust → uboot.img)
logo.bmp displayed on screen
→ boot.ini: load panel.txt → load pre-merged DTB (kernel-panelN.dtb)
→ Kernel 6.6.89 + initramfs splash (0.7s)
→ systemd → panel-detect.service (first boot only)
→ archr-boot-setup (GPU + governors)
→ U-Boot loads (idbloader → trust → uboot.img)
boot.ini: read SARADC hwrev → select board DTB
→ boot.ini: apply overlays/mipi-panel.dtbo (panel init sequence)
→ Kernel 6.12.61 + initramfs splash (0.7s)
→ systemd → archr-boot-setup (GPU + governors)
→ emulationstation.service → EmulationStation UI
≈ 19 seconds total (+ wizard on first boot)
≈ 19 seconds total
```
## Contributing
+29 -4
View File
@@ -1961,10 +1961,35 @@ The Flasher lives at `archr-linux/archr-flasher` on GitHub. Still ironing out th
(first build caught a Tauri 2 schema issue with `app.title` and 16-bit icon PNGs), but the
code is feature-complete.
**beta1.2 image changes:**
**beta1.2 system changes — a lot more than "just polish":**
Published new images with accumulated fixes since beta1.1. Nothing dramatic — mostly polish
and small fixes that came out of Flasher development and continued testing.
The biggest under-the-hood change was the **input merger daemon**. RetroArch sees multiple input
devices (gpio-keys for buttons, adc-joystick for analog sticks) as separate controllers. With
`max_users=1`, it would bind to gpio-keys and ignore the joystick entirely. The fix: a small
C daemon (`input-merge`) that reads both evdev devices and outputs a single virtual "Arch R
Gamepad" via uinput. Now RetroArch sees one unified controller with buttons + analog sticks.
`retroarch-launch.sh` starts the merger before RA and kills it after.
RetroArch itself got a proper config tuning pass, borrowed heavily from ROCKNIX's RK3326
profiles. Audio at 48kHz (native DAC rate), triple buffer, late input polling for reduced
latency, per-core options for mupen64plus, pcsx_rearmed, flycast, mame2003-plus, melonds,
and others. Auto-save enabled, core options path set.
**Panel wizard rework:** Panels now show in numerical order — the beep count matches the panel
position in the list (Panel 1 = 1 beep, Panel 2 = 2 beeps, etc.). Default panel detection
uses `dtb_name` matching instead of always falling back to `panels[0]`.
**Third image variant: no-panel.** For the Flasher app — includes all 18 pre-merged panel DTBs
for both original and clone hardware. The Flasher picks the right DTB at write time. Also added
`variant-sync` systemd service that copies `/boot/variant` to `/etc/archr/variant` on first
boot (necessary because the Flasher writes the variant marker to the FAT32 BOOT partition,
not directly into ext4).
**Mirror list updated:** The old EU mirror was returning 403 errors. Reshuffled to Americas-first
ordering (better for Brazil) and added new mirrors (de4, gr, tw, tw2, ca.us).
**boot.ini fix:** Root device now auto-detected from `mmcdev` variable instead of the hardcoded
`__ROOTDEV__` placeholder — one less thing that could break on different boot configurations.
---
@@ -2077,4 +2102,4 @@ and small fixes that came out of Flasher development and continued testing.
---
*Last updated: 2026-02-25 (build pipeline fixes, boot.scr mystery solved, splash positioning)*
*Last updated: 2026-03-01 (beta1.2 release — Flasher app, input merger, RetroArch tuning, no-panel variant)*
Submodule bootloader/u-boot-rk3326 updated: 5606e804ff...2492a3e467
+9 -7
View File
@@ -129,6 +129,14 @@ log "✓ Prerequisites OK"
START_TIME=$(date +%s)
if [ "$BUILD_KERNEL" = true ]; then
# Initramfs must be built BEFORE kernel — kernel embeds it at compile time
log ""
log "═══════════════════════════════════════════════════════════════"
log " BUILDING INITRAMFS"
log "═══════════════════════════════════════════════════════════════"
chmod +x "$SCRIPT_DIR/build-initramfs.sh"
"$SCRIPT_DIR/build-initramfs.sh"
log ""
log "═══════════════════════════════════════════════════════════════"
log " BUILDING KERNEL"
@@ -184,7 +192,7 @@ log "═════════════════════════
chmod +x "$SCRIPT_DIR/scripts/generate-panel-dtbos.sh"
"$SCRIPT_DIR/scripts/generate-panel-dtbos.sh"
# Build custom U-Boot (optional — requires arm-linux-gnueabihf toolchain)
# Build U-Boot BSP (requires aarch64 cross-compiler)
if [ "$BUILD_UBOOT" = true ] && [ -f "$SCRIPT_DIR/build-uboot.sh" ]; then
if command -v aarch64-linux-gnu-gcc &>/dev/null; then
log ""
@@ -213,12 +221,6 @@ if [ "$BUILD_IMAGE" = true ]; then
log " BUILDING IMAGE (clone)"
log "═══════════════════════════════════════════════════════════════"
"$SCRIPT_DIR/build-image.sh" --variant clone
log ""
log "═══════════════════════════════════════════════════════════════"
log " BUILDING IMAGE (no-panel)"
log "═══════════════════════════════════════════════════════════════"
"$SCRIPT_DIR/build-image.sh" --variant no-panel
fi
#------------------------------------------------------------------------------
+102 -298
View File
File diff suppressed because it is too large Load Diff
+102
View File
@@ -0,0 +1,102 @@
#!/bin/bash
#==============================================================================
# Arch R - Initramfs Builder
#==============================================================================
# Generates the initramfs directory for kernel embedding (CONFIG_INITRAMFS_SOURCE).
# Must run BEFORE build-kernel.sh — the kernel embeds this at compile time.
#
# Pipeline:
# 1. Compile archr-init.c + SVG splash library (static aarch64 binary)
# 2. Create initramfs directory tree (init + dev + proc + newroot)
#
# Logo is rendered from SVG paths at runtime (no ImageMagick needed).
#
# Output: $OUTPUT_DIR/initramfs/ (directory tree, not cpio)
#==============================================================================
set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# Colors
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
RED='\033[0;31m'
NC='\033[0m'
log() { echo -e "${GREEN}[$(date '+%H:%M:%S')]${NC} $1"; }
warn() { echo -e "${YELLOW}[$(date '+%H:%M:%S')] WARNING:${NC} $1"; }
error() { echo -e "${RED}[$(date '+%H:%M:%S')] ERROR:${NC} $1"; exit 1; }
#------------------------------------------------------------------------------
# Configuration
#------------------------------------------------------------------------------
OUTPUT_DIR="$SCRIPT_DIR/output"
INITRAMFS_DIR="$OUTPUT_DIR/initramfs"
SPLASH_DIR="$SCRIPT_DIR/scripts/splash"
log "================================================================"
log " Arch R - Initramfs Builder (SVG splash)"
log "================================================================"
#------------------------------------------------------------------------------
# Prerequisites
#------------------------------------------------------------------------------
if ! command -v aarch64-linux-gnu-gcc &>/dev/null; then
error "Cross-compiler not found. Install: sudo apt install gcc-aarch64-linux-gnu"
fi
# Verify splash library files exist
for f in fbsplash.c svg_parser.c svg_renderer.c archr-logo.h; do
if [ ! -f "$SPLASH_DIR/$f" ]; then
error "Missing splash file: $SPLASH_DIR/$f"
fi
done
#------------------------------------------------------------------------------
# Step 1: Compile archr-init (static aarch64 binary with SVG splash)
#------------------------------------------------------------------------------
log ""
log "Step 1: Compiling archr-init (SVG splash)..."
TMPDIR=$(mktemp -d)
aarch64-linux-gnu-gcc -static -O2 \
-I"$SPLASH_DIR" \
-o "$TMPDIR/archr-init" \
"$SCRIPT_DIR/scripts/archr-init.c" \
"$SPLASH_DIR/fbsplash.c" \
"$SPLASH_DIR/svg_parser.c" \
"$SPLASH_DIR/svg_renderer.c" \
-lm
log " archr-init compiled ($(du -h "$TMPDIR/archr-init" | cut -f1))"
#------------------------------------------------------------------------------
# Step 2: Create initramfs directory tree
#------------------------------------------------------------------------------
log ""
log "Step 2: Creating initramfs directory..."
rm -rf "$INITRAMFS_DIR"
mkdir -p "$INITRAMFS_DIR"/{dev,proc,newroot}
cp "$TMPDIR/archr-init" "$INITRAMFS_DIR/init"
chmod 755 "$INITRAMFS_DIR/init"
#------------------------------------------------------------------------------
# Cleanup
#------------------------------------------------------------------------------
rm -rf "$TMPDIR"
INIT_SIZE=$(du -h "$INITRAMFS_DIR/init" | cut -f1)
log ""
log "================================================================"
log " Initramfs Ready"
log "================================================================"
log ""
log " Directory: $INITRAMFS_DIR"
log " /init: $INIT_SIZE (static aarch64 + SVG splash)"
log ""
log " Kernel will embed this via CONFIG_INITRAMFS_SOURCE"
+217 -139
View File
@@ -1,9 +1,11 @@
#!/bin/bash
#==============================================================================
# Arch R - Kernel 6.6 Build Script for R36S
# Arch R - Kernel Build Script
#==============================================================================
# Builds Linux kernel 6.6.89 (Rockchip BSP) with R36S DTS + systemd support
# Builds mainline Linux 6.12.x with Arch R patches for RK3326 R36S
# Applies: device patches, 6.12-LTS patches, mainline patches
# Builds: kernel Image + ALL DTBs + modules + out-of-tree joypad driver
#==============================================================================
set -e
@@ -14,7 +16,6 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
CYAN='\033[0;36m'
NC='\033[0m'
log() { echo -e "${GREEN}[$(date '+%H:%M:%S')]${NC} $1"; }
@@ -22,21 +23,18 @@ warn() { echo -e "${YELLOW}[$(date '+%H:%M:%S')] WARNING:${NC} $1"; }
error() { echo -e "${RED}[$(date '+%H:%M:%S')] ERROR:${NC} $1"; exit 1; }
#------------------------------------------------------------------------------
# Configuration - Kernel 6.6 Rockchip BSP
# Configuration
#------------------------------------------------------------------------------
KERNEL_VERSION="6.6.89"
KERNEL_BRANCH="develop-6.6"
KERNEL_REPO="https://github.com/rockchip-linux/kernel.git"
DEFCONFIG="rockchip_linux_defconfig"
CONFIG_FRAGMENT="$SCRIPT_DIR/config/archr-6.6-r36s.config"
# DTS targets
R36S_DTB="rk3326-gameconsole-r36s"
CLONE_DTB="rk3326-gameconsole-r36s-clone-type5"
KERNEL_VERSION="6.12.61"
KERNEL_URL="https://www.kernel.org/pub/linux/kernel/v6.x/linux-${KERNEL_VERSION}.tar.xz"
# Paths
KERNEL_SRC="${KERNEL_SRC:-/home/dgateles/Documentos/Projetos/kernel}"
KERNEL_SRC="$SCRIPT_DIR/kernel/src/linux-${KERNEL_VERSION}"
PATCHES_DIR="$SCRIPT_DIR/patches/linux"
DTS_DIR="$SCRIPT_DIR/kernel/dts/archr"
JOYPAD_DIR="$SCRIPT_DIR/kernel/drivers/archr-joypad"
CONFIG_BASE="$SCRIPT_DIR/config/linux-archr-base.config"
# Output
OUTPUT_DIR="$SCRIPT_DIR/output"
@@ -50,13 +48,17 @@ export CROSS_COMPILE=aarch64-linux-gnu-
# Build parallelism
JOBS=$(nproc)
# DTS target directory inside kernel
KERNEL_DTS_DIR="$KERNEL_SRC/arch/arm64/boot/dts/rockchip"
log "================================================================"
log " Arch R - Kernel $KERNEL_VERSION (Rockchip BSP for R36S)"
log " Arch R - Kernel $KERNEL_VERSION (Mainline + Arch R patches)"
log "================================================================"
log ""
log "Source: $KERNEL_SRC"
log "Branch: $KERNEL_BRANCH"
log "DTB: $R36S_DTB"
log "Patches: $PATCHES_DIR"
log "DTS: $DTS_DIR"
log "Config: $CONFIG_BASE"
log "Jobs: $JOBS"
#------------------------------------------------------------------------------
@@ -66,11 +68,13 @@ log ""
log "Step 1: Checking kernel source..."
if [ ! -d "$KERNEL_SRC" ]; then
log " Cloning kernel 6.6 (rockchip-linux/kernel)..."
log " Branch: $KERNEL_BRANCH"
git clone --depth 1 --branch "$KERNEL_BRANCH" \
"$KERNEL_REPO" "$KERNEL_SRC"
log " Kernel cloned"
TARBALL="$SCRIPT_DIR/kernel/src/linux-${KERNEL_VERSION}.tar.xz"
if [ ! -f "$TARBALL" ]; then
log " Downloading kernel $KERNEL_VERSION..."
wget -c "$KERNEL_URL" -O "$TARBALL"
fi
log " Extracting..."
tar -xf "$TARBALL" -C "$SCRIPT_DIR/kernel/src/"
fi
if [ ! -f "$KERNEL_SRC/Makefile" ]; then
@@ -80,76 +84,130 @@ fi
ACTUAL_VERSION=$(make -C "$KERNEL_SRC" -s kernelversion 2>/dev/null)
log " Kernel: $ACTUAL_VERSION"
# Copy R36S DTS from Arch-R repo into kernel source tree
DTS_SRC="$SCRIPT_DIR/kernel/dts/rk3326-gameconsole-r36s.dts"
DTS_DEST="$KERNEL_SRC/arch/arm64/boot/dts/rockchip/rk3326-gameconsole-r36s.dts"
if [ -f "$DTS_SRC" ]; then
cp "$DTS_SRC" "$DTS_DEST"
log " DTS: copied from repo"
else
if [ -f "$DTS_DEST" ]; then
warn "DTS not in Arch-R repo — using existing kernel source copy"
else
error "DTS not found! Expected at: $DTS_SRC"
fi
fi
# Copy clone DTS (if available)
CLONE_DTS_SRC="$SCRIPT_DIR/kernel/dts/${CLONE_DTB}.dts"
CLONE_DTS_DEST="$KERNEL_SRC/arch/arm64/boot/dts/rockchip/${CLONE_DTB}.dts"
if [ -f "$CLONE_DTS_SRC" ]; then
cp "$CLONE_DTS_SRC" "$CLONE_DTS_DEST"
log " DTS (clone): copied from repo"
fi
#------------------------------------------------------------------------------
# Step 2: Configure Kernel
# Step 2: Apply Patches (idempotent — skip already applied)
#------------------------------------------------------------------------------
log ""
log "Step 2: Configuring kernel..."
log "Step 2: Applying patches..."
# Apply base defconfig
make -C "$KERNEL_SRC" ARCH=$ARCH CROSS_COMPILE=$CROSS_COMPILE $DEFCONFIG
log " Base: $DEFCONFIG"
PATCH_MARKER="$KERNEL_SRC/.archr-patches-applied"
# Merge R36S-specific config fragment
# IMPORTANT: merge_config.sh writes output to .config in the CURRENT directory,
# NOT to the base config path. Must run from kernel source dir.
if [ -f "$CONFIG_FRAGMENT" ]; then
pushd "$KERNEL_SRC" > /dev/null
MERGE_LOG=$(scripts/kconfig/merge_config.sh \
-m .config "$CONFIG_FRAGMENT" 2>&1) || true
echo "$MERGE_LOG" | grep -E "(^#|Value)" | tail -20 || true
popd > /dev/null
make -C "$KERNEL_SRC" ARCH=$ARCH CROSS_COMPILE=$CROSS_COMPILE olddefconfig
# Verify critical GPU config was applied
if grep -q "CONFIG_DRM_PANFROST=y" "$KERNEL_SRC/.config"; then
log " Panfrost GPU: ENABLED (built-in)"
elif grep -q "CONFIG_DRM_PANFROST=m" "$KERNEL_SRC/.config"; then
log " Panfrost GPU: ENABLED (module)"
else
warn " Panfrost GPU: NOT ENABLED — check config fragment!"
fi
if grep -q "CONFIG_MALI_MIDGARD=y" "$KERNEL_SRC/.config"; then
warn " Mali Midgard: STILL ENABLED (conflict with Panfrost!)"
else
log " Mali Midgard: disabled (good)"
fi
log " Merged: $(basename "$CONFIG_FRAGMENT")"
if [ -f "$PATCH_MARKER" ]; then
log " Patches already applied (marker exists). Skipping."
else
warn "Config fragment not found: $CONFIG_FRAGMENT"
PATCH_COUNT=0
# Order: mainline first (GPIO API, input-polldev), then 6.12-LTS, then device-specific
for PATCH_SUBDIR in mainline 6.12-lts device; do
PDIR="$PATCHES_DIR/$PATCH_SUBDIR"
if [ ! -d "$PDIR" ]; then
warn " Patch dir not found: $PDIR"
continue
fi
for PATCH in $(ls "$PDIR"/*.patch 2>/dev/null | sort); do
PNAME=$(basename "$PATCH")
log " Applying [$PATCH_SUBDIR] $PNAME..."
if ! patch -d "$KERNEL_SRC" -p1 --forward --batch < "$PATCH" 2>&1 | tail -3; then
warn " Patch may have failed or already applied: $PNAME"
fi
PATCH_COUNT=$((PATCH_COUNT + 1))
done
done
touch "$PATCH_MARKER"
log " Applied $PATCH_COUNT patches"
fi
#------------------------------------------------------------------------------
# Step 3: Copy DTS files
#------------------------------------------------------------------------------
log ""
log "Step 3: Copying DTS files..."
if [ ! -d "$DTS_DIR" ]; then
error "DTS directory not found: $DTS_DIR"
fi
DTS_COUNT=0
for DTS_FILE in "$DTS_DIR"/*.dts "$DTS_DIR"/*.dtsi; do
[ -f "$DTS_FILE" ] || continue
DEST="$KERNEL_DTS_DIR/$(basename "$DTS_FILE")"
cp "$DTS_FILE" "$DEST"
DTS_COUNT=$((DTS_COUNT + 1))
done
# Add DTS entries to Makefile (for each .dts, ensure dtb- line exists)
ROCKCHIP_MAKEFILE="$KERNEL_DTS_DIR/Makefile"
for DTS_FILE in "$DTS_DIR"/*.dts; do
[ -f "$DTS_FILE" ] || continue
DTB_NAME=$(basename "$DTS_FILE" .dts)
if ! grep -q "${DTB_NAME}.dtb" "$ROCKCHIP_MAKEFILE"; then
# Add before the first empty line or at the end of the dtb list
echo "dtb-\$(CONFIG_ARCH_ROCKCHIP) += ${DTB_NAME}.dtb" >> "$ROCKCHIP_MAKEFILE"
log " Added to Makefile: ${DTB_NAME}.dtb"
fi
done
log " Copied $DTS_COUNT DTS files"
#------------------------------------------------------------------------------
# Step 4: Configure Kernel
#------------------------------------------------------------------------------
log ""
log "Step 4: Configuring kernel..."
if [ ! -f "$CONFIG_BASE" ]; then
error "Config base not found: $CONFIG_BASE"
fi
# Copy Arch R base config
cp "$CONFIG_BASE" "$KERNEL_SRC/.config"
# Replace placeholder for initramfs
INITRAMFS_DIR="$OUTPUT_DIR/initramfs"
if [ -d "$INITRAMFS_DIR" ] && [ -x "$INITRAMFS_DIR/init" ]; then
log " Embedding initramfs from: $INITRAMFS_DIR"
sed -i "s|@INITRAMFS_SOURCE@|${INITRAMFS_DIR}|" "$KERNEL_SRC/.config"
else
warn " Initramfs not found at $INITRAMFS_DIR"
warn " Run build-initramfs.sh first! Disabling embedded initramfs."
sed -i 's|CONFIG_INITRAMFS_SOURCE=.*|CONFIG_INITRAMFS_SOURCE=""|' "$KERNEL_SRC/.config"
fi
# Finalize config
make -C "$KERNEL_SRC" ARCH=$ARCH CROSS_COMPILE=$CROSS_COMPILE olddefconfig
# Verify critical settings
log " Verifying config..."
check_config() {
local key="$1" expected="$2" desc="$3"
local val=$(grep "^${key}=" "$KERNEL_SRC/.config" 2>/dev/null | head -1)
if [ -z "$val" ]; then
val=$(grep "^# ${key} is not set" "$KERNEL_SRC/.config" 2>/dev/null | head -1)
fi
if echo "$val" | grep -q "$expected"; then
log " $desc: OK"
else
warn " $desc: UNEXPECTED ($val)"
fi
}
check_config "CONFIG_DRM_PANFROST" "=m" "Panfrost GPU"
check_config "CONFIG_DRM_PANEL_SITRONIX_ST7703" "=y" "ST7703 panel"
check_config "CONFIG_FRAMEBUFFER_CONSOLE" "=y" "fbcon"
check_config "CONFIG_FRAMEBUFFER_CONSOLE_DEFERRED_TAKEOVER" "is not set" "No deferred takeover"
check_config "CONFIG_EXT4_FS" "=y" "ext4"
check_config "CONFIG_DEVTMPFS" "=y" "devtmpfs"
log " Kernel configured"
#------------------------------------------------------------------------------
# Step 3: Build Kernel Image
# Step 5: Build Kernel Image
#------------------------------------------------------------------------------
log ""
log "Step 3: Building kernel Image..."
log "Step 5: Building kernel Image..."
make -C "$KERNEL_SRC" -j$JOBS ARCH=$ARCH CROSS_COMPILE=$CROSS_COMPILE Image 2>&1 | \
tail -5
make -C "$KERNEL_SRC" -j$JOBS ARCH=$ARCH CROSS_COMPILE=$CROSS_COMPILE Image 2>&1 | tail -5
if [ ! -f "$KERNEL_SRC/arch/arm64/boot/Image" ]; then
error "Kernel Image build failed!"
@@ -159,85 +217,104 @@ IMAGE_SIZE=$(du -h "$KERNEL_SRC/arch/arm64/boot/Image" | cut -f1)
log " Kernel Image built ($IMAGE_SIZE)"
#------------------------------------------------------------------------------
# Step 4: Build Device Tree
# Step 6: Build ALL Device Trees
#------------------------------------------------------------------------------
log ""
log "Step 4: Building Device Tree ($R36S_DTB)..."
log "Step 6: Building Device Trees..."
make -C "$KERNEL_SRC" -j$JOBS ARCH=$ARCH CROSS_COMPILE=$CROSS_COMPILE \
"rockchip/${R36S_DTB}.dtb" 2>&1 | tail -5
# Build dtbs target (compiles all DTBs referenced in Makefile)
make -C "$KERNEL_SRC" -j$JOBS ARCH=$ARCH CROSS_COMPILE=$CROSS_COMPILE DTC_FLAGS=-@ dtbs 2>&1 | tail -10
if [ ! -f "$KERNEL_SRC/arch/arm64/boot/dts/rockchip/${R36S_DTB}.dtb" ]; then
error "DTB build failed: ${R36S_DTB}.dtb"
# Verify R36S DTB was built
if [ ! -f "$KERNEL_DTS_DIR/rk3326-gameconsole-r36s.dtb" ]; then
error "R36S DTB not built!"
fi
log " DTB built: ${R36S_DTB}.dtb"
# Build clone DTB (if DTS was copied)
if [ -f "$CLONE_DTS_DEST" ]; then
make -C "$KERNEL_SRC" -j$JOBS ARCH=$ARCH CROSS_COMPILE=$CROSS_COMPILE \
"rockchip/${CLONE_DTB}.dtb" 2>&1 | tail -5
if [ -f "$KERNEL_SRC/arch/arm64/boot/dts/rockchip/${CLONE_DTB}.dtb" ]; then
log " DTB built (clone): ${CLONE_DTB}.dtb"
else
warn "Clone DTB build failed: ${CLONE_DTB}.dtb"
fi
fi
DTB_COUNT=$(find "$KERNEL_DTS_DIR" -name "rk3326-*.dtb" | wc -l)
log " Built $DTB_COUNT RK3326 DTBs"
#------------------------------------------------------------------------------
# Step 5: Build Kernel Modules
# Step 7: Build Kernel Modules
#------------------------------------------------------------------------------
log ""
log "Step 5: Building kernel modules..."
log "Step 7: Building kernel modules..."
make -C "$KERNEL_SRC" -j$JOBS ARCH=$ARCH CROSS_COMPILE=$CROSS_COMPILE modules 2>&1 | \
tail -5
make -C "$KERNEL_SRC" -j$JOBS ARCH=$ARCH CROSS_COMPILE=$CROSS_COMPILE modules 2>&1 | tail -5
log " Kernel modules built"
#------------------------------------------------------------------------------
# Step 6: Install to Output Directory
# Step 8: Build Out-of-Tree Drivers
#------------------------------------------------------------------------------
log ""
log "Step 6: Installing artifacts..."
log "Step 8: Building out-of-tree drivers..."
if [ -d "$JOYPAD_DIR" ] && [ -f "$JOYPAD_DIR/Makefile" ]; then
log " Building archr-joypad..."
make -C "$KERNEL_SRC" ARCH=$ARCH CROSS_COMPILE=$CROSS_COMPILE \
M="$JOYPAD_DIR" modules 2>&1 | tail -5
if find "$JOYPAD_DIR" -name "*.ko" | grep -q .; then
log " archr-joypad: OK"
else
warn " archr-joypad: no .ko files produced"
fi
else
warn " Joypad driver not found at: $JOYPAD_DIR"
fi
#------------------------------------------------------------------------------
# Step 9: Install to Output Directory
#------------------------------------------------------------------------------
log ""
log "Step 9: Installing artifacts..."
mkdir -p "$BOOT_DIR"
mkdir -p "$MODULES_DIR"
# Copy kernel image
cp "$KERNEL_SRC/arch/arm64/boot/Image" "$BOOT_DIR/"
log " Copied: Image"
# Copy kernel image as KERNEL (Arch R naming convention)
cp "$KERNEL_SRC/arch/arm64/boot/Image" "$BOOT_DIR/KERNEL"
log " Copied: KERNEL"
# Copy R36S DTB
cp "$KERNEL_SRC/arch/arm64/boot/dts/rockchip/${R36S_DTB}.dtb" "$BOOT_DIR/"
log " Copied: ${R36S_DTB}.dtb"
# Copy ALL RK3326 DTBs to dtbs/ subdirectory
mkdir -p "$BOOT_DIR/dtbs"
for DTB in "$KERNEL_DTS_DIR"/rk3326-*.dtb; do
[ -f "$DTB" ] || continue
cp "$DTB" "$BOOT_DIR/dtbs/"
done
log " Copied: $(ls "$BOOT_DIR/dtbs"/rk3326-*.dtb 2>/dev/null | wc -l) DTBs to dtbs/"
# Copy clone DTB (if built)
if [ -f "$KERNEL_SRC/arch/arm64/boot/dts/rockchip/${CLONE_DTB}.dtb" ]; then
cp "$KERNEL_SRC/arch/arm64/boot/dts/rockchip/${CLONE_DTB}.dtb" "$BOOT_DIR/"
log " Copied: ${CLONE_DTB}.dtb"
fi
# Install modules (use pipefail to catch errors masked by tail)
# Install kernel modules
set -o pipefail
make -C "$KERNEL_SRC" ARCH=$ARCH CROSS_COMPILE=$CROSS_COMPILE \
INSTALL_MOD_PATH="$MODULES_DIR" \
modules_install 2>&1 | tail -5
set +o pipefail
# Remove symlinks (save space)
# Install joypad driver module
if find "$JOYPAD_DIR" -name "*.ko" | grep -q .; then
KREL=$(cat "$KERNEL_SRC/include/config/kernel.release" 2>/dev/null)
JOYPAD_DEST="$MODULES_DIR/lib/modules/$KREL/extra/archr-joypad"
mkdir -p "$JOYPAD_DEST"
cp "$JOYPAD_DIR"/*.ko "$JOYPAD_DEST/"
log " Installed joypad modules to: extra/archr-joypad/"
# Regenerate modules.dep
depmod -b "$MODULES_DIR" "$KREL"
fi
# Remove build/source symlinks (save space on target)
rm -f "$MODULES_DIR/lib/modules/"*/source 2>/dev/null || true
rm -f "$MODULES_DIR/lib/modules/"*/build 2>/dev/null || true
# Verify critical module was installed
KERNEL_FULL=$(make -C "$KERNEL_SRC" -s kernelversion 2>/dev/null)
KREL=$(cat "$KERNEL_SRC/include/config/kernel.release" 2>/dev/null || echo "$KERNEL_FULL")
if find "$MODULES_DIR/lib/modules/$KREL" -name 'panfrost.ko*' 2>/dev/null | grep -q .; then
log " Panfrost module: INSTALLED"
else
warn " Panfrost module: NOT FOUND in $MODULES_DIR/lib/modules/$KREL/"
warn " Check directory permissions (must be writable by build user)"
fi
# Verify critical modules
KREL=$(cat "$KERNEL_SRC/include/config/kernel.release" 2>/dev/null)
for MOD in panfrost; do
if find "$MODULES_DIR/lib/modules/$KREL" -name "${MOD}.ko*" 2>/dev/null | grep -q .; then
log " Module OK: $MOD"
else
warn " Module MISSING: $MOD"
fi
done
# Note: rockchipdrm is CONFIG_DRM_ROCKCHIP=y (built-in, not a module) — no .ko to check
log " Modules installed"
@@ -250,20 +327,21 @@ log " BUILD COMPLETE"
log "================================================================"
log ""
KERNEL_FULL=$(make -C "$KERNEL_SRC" -s kernelversion 2>/dev/null || echo "$KERNEL_VERSION")
IMAGE_SIZE=$(du -h "$BOOT_DIR/Image" | cut -f1)
DTB_SIZE=$(du -h "$BOOT_DIR/${R36S_DTB}.dtb" | cut -f1)
MODULES_SIZE=$(du -sh "$MODULES_DIR" 2>/dev/null | cut -f1 || echo "N/A")
KERNEL_FULL=$(make -C "$KERNEL_SRC" -s kernelversion 2>/dev/null)
KERNEL_SIZE=$(du -h "$BOOT_DIR/KERNEL" | cut -f1)
MODULES_SIZE=$(du -sh "$MODULES_DIR" 2>/dev/null | cut -f1)
DTB_COUNT=$(ls "$BOOT_DIR/dtbs"/rk3326-*.dtb 2>/dev/null | wc -l)
log "Kernel: $KERNEL_FULL"
log "Kernel: $KERNEL_FULL (mainline + Arch R patches)"
log "KERNEL: $BOOT_DIR/KERNEL ($KERNEL_SIZE)"
log "DTBs: $DTB_COUNT files in $BOOT_DIR/dtbs/"
log "Modules: $MODULES_DIR/ ($MODULES_SIZE)"
log ""
CLONE_DTB_SIZE="N/A"
[ -f "$BOOT_DIR/${CLONE_DTB}.dtb" ] && CLONE_DTB_SIZE=$(du -h "$BOOT_DIR/${CLONE_DTB}.dtb" | cut -f1)
log "Artifacts:"
log " Image: $BOOT_DIR/Image ($IMAGE_SIZE)"
log " DTB: $BOOT_DIR/${R36S_DTB}.dtb ($DTB_SIZE)"
log " DTB clone: $BOOT_DIR/${CLONE_DTB}.dtb ($CLONE_DTB_SIZE)"
log " Modules: $MODULES_DIR/ ($MODULES_SIZE)"
log "Key DTBs:"
for DTB in rk3326-gameconsole-r36s rk3326-odroid-go2 rk3326-gameconsole-r33s; do
if [ -f "$BOOT_DIR/dtbs/${DTB}.dtb" ]; then
log " ${DTB}.dtb ($(du -h "$BOOT_DIR/dtbs/${DTB}.dtb" | cut -f1))"
fi
done
log ""
log "Kernel 6.6 ready for R36S (original + clone)!"
log "Ready for deployment to SD card!"
+208 -53
View File
@@ -123,10 +123,11 @@ log " ✓ Pacman CheckSpace disabled (QEMU chroot compatibility)"
# Add multiple fallback mirrors (default mirror often has stale/404 packages)
cat > "$ROOTFS_DIR/etc/pacman.d/mirrorlist" << 'MIRRORS_EOF'
# Arch Linux ARM mirrors - all official mirrors, Americas first
# Arch Linux ARM mirrors - all official, Americas first
Server = http://fl.us.mirror.archlinuxarm.org/$arch/$repo
Server = http://nj.us.mirror.archlinuxarm.org/$arch/$repo
Server = http://ca.us.mirror.archlinuxarm.org/$arch/$repo
Server = http://eu.mirror.archlinuxarm.org/$arch/$repo
Server = http://de.mirror.archlinuxarm.org/$arch/$repo
Server = http://de4.mirror.archlinuxarm.org/$arch/$repo
Server = http://dk.mirror.archlinuxarm.org/$arch/$repo
@@ -294,34 +295,33 @@ kernel.sched_latency_ns=1000000
kernel.sched_min_granularity_ns=500000
SYSCTL_EOF
# ZRAM swap — via timer, NOT in multi-user.target!
# Type=oneshot + WantedBy=multi-user.target means systemd WAITS for mkswap to finish
# before reaching multi-user.target. This adds 2.4s to boot critical path.
# Fix: use a timer that fires at boot+15s (ES is already running by then).
cat > /etc/systemd/system/zram-swap.service << 'ZRAM_EOF'
# Memory manager — ZRAM swap with delayed start (15s after boot)
# Timer avoids blocking multi-user.target (ES is already running by then)
cat > /etc/systemd/system/archr-memory-manager.service << 'MEM_SVC'
[Unit]
Description=ZRAM Swap
Description=Arch R Memory Manager
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/bin/bash -c 'modprobe zram num_devices=1 2>/dev/null; echo lzo > /sys/block/zram0/comp_algorithm; echo 134217728 > /sys/block/zram0/disksize && mkswap /dev/zram0 && swapon -p 100 /dev/zram0'
ExecStop=/bin/bash -c 'swapoff /dev/zram0 2>/dev/null; echo 1 > /sys/block/zram0/reset 2>/dev/null'
ZRAM_EOF
ExecStart=/usr/local/bin/archr-memory-manager setup
ExecStop=/usr/local/bin/archr-memory-manager stop
ExecReload=/usr/local/bin/archr-memory-manager reload
MEM_SVC
cat > /etc/systemd/system/zram-swap.timer << 'ZRAM_TIMER'
cat > /etc/systemd/system/archr-memory-manager.timer << 'MEM_TIMER'
[Unit]
Description=Delayed ZRAM Swap Setup
Description=Delayed Memory Manager Setup
[Timer]
OnBootSec=15s
Unit=zram-swap.service
Unit=archr-memory-manager.service
[Install]
WantedBy=timers.target
ZRAM_TIMER
MEM_TIMER
systemctl enable zram-swap.timer
systemctl enable archr-memory-manager.timer
# Create directories
mkdir -p /home/archr/.config/retroarch/cores
@@ -378,7 +378,6 @@ cat > /etc/systemd/system/archr-variant-sync.service << 'VARSYNC_EOF'
[Unit]
Description=Sync variant from BOOT partition
After=local-fs.target
Before=panel-detect.service
RequiresMountsFor=/boot
ConditionPathExists=!/etc/archr/variant
@@ -393,25 +392,6 @@ VARSYNC_EOF
systemctl enable archr-variant-sync
# Panel auto-detect wizard (first boot / X-button reset)
cat > /etc/systemd/system/panel-detect.service << 'PANELDET_EOF'
[Unit]
Description=Arch R Panel Detection Wizard
After=local-fs.target
Before=emulationstation.service
RequiresMountsFor=/boot
[Service]
Type=oneshot
ExecStart=/usr/local/bin/panel-detect.py
TimeoutStartSec=600
[Install]
WantedBy=multi-user.target
PANELDET_EOF
systemctl enable panel-detect
# EmulationStation launch — PRIMARY: systemd service (created by build-emulationstation.sh)
# FALLBACK: autologin + .bash_profile (if ES service not installed)
# The emulationstation.service Conflicts with getty@tty1, so only one runs.
@@ -531,6 +511,127 @@ TIMING_EOF
systemctl enable boot-timing
# Debug dump: comprehensive system info to /boot/debug.log (readable from PC)
cat > /etc/systemd/system/archr-debug-dump.service << 'DEBUG_EOF'
[Unit]
Description=Arch R Debug Dump
After=emulationstation.service
After=multi-user.target
[Service]
Type=oneshot
ExecStart=/bin/bash -c '\
sleep 20; \
{ \
echo "=== Arch R Debug Dump ($(date)) ==="; \
echo ""; \
echo "--- Kernel ---"; \
uname -a; \
echo ""; \
echo "--- Input Devices ---"; \
for d in /dev/input/event*; do \
name=$(cat /sys/class/input/$(basename $d)/device/name 2>/dev/null); \
echo " $d: $name"; \
done; \
echo ""; \
echo "--- DRM ---"; \
for c in /sys/class/drm/card*/status; do \
echo " $c: $(cat $c 2>/dev/null)"; \
done; \
cat /sys/class/drm/card*/modes 2>/dev/null | head -5; \
echo ""; \
echo "--- Backlight ---"; \
for bl in /sys/class/backlight/*/; do \
echo " $(basename $bl): cur=$(cat ${bl}brightness 2>/dev/null) max=$(cat ${bl}max_brightness 2>/dev/null)"; \
done; \
echo ""; \
echo "--- ALSA Controls ---"; \
amixer scontrols 2>/dev/null || echo " (no ALSA)"; \
echo ""; \
echo "--- CPU/GPU ---"; \
echo " CPU: $(cat /sys/devices/system/cpu/cpufreq/policy0/scaling_cur_freq 2>/dev/null)kHz ($(cat /sys/devices/system/cpu/cpufreq/policy0/scaling_governor 2>/dev/null))"; \
echo " GPU: $(cat /sys/devices/platform/ff400000.gpu/devfreq/ff400000.gpu/cur_freq 2>/dev/null)Hz"; \
echo " Temp: $(cat /sys/class/thermal/thermal_zone0/temp 2>/dev/null)"; \
echo ""; \
echo "--- Memory ---"; \
free -h; \
echo ""; \
echo "--- Loaded Modules ---"; \
lsmod 2>/dev/null | head -30; \
echo ""; \
echo "--- Failed Services ---"; \
systemctl --failed --no-pager 2>/dev/null; \
echo ""; \
echo "--- dmesg errors ---"; \
dmesg -l err,warn 2>/dev/null | tail -30; \
} > /boot/debug.log 2>&1; \
chmod 644 /boot/debug.log'
[Install]
WantedBy=multi-user.target
DEBUG_EOF
systemctl enable archr-debug-dump
# USB auto-mount service (triggered by udev on device insertion)
cat > /etc/systemd/system/archr-automount.service << 'AUTOMOUNT_SVC'
[Unit]
Description=Arch R USB Auto-Mount
[Service]
Type=oneshot
ExecStart=/usr/local/bin/archr-automount mount
AUTOMOUNT_SVC
# Save config on shutdown (backs up ALSA state, brightness, WiFi to /boot)
cat > /etc/systemd/system/archr-save-config.service << 'SAVECONF_SVC'
[Unit]
Description=Arch R Save Config
DefaultDependencies=no
Before=shutdown.target
[Service]
Type=oneshot
ExecStart=/usr/local/bin/archr-save-config backup
[Install]
WantedBy=shutdown.target
SAVECONF_SVC
systemctl enable archr-save-config
# Bluetooth auto-pairing agent (runs alongside bluetoothd)
cat > /etc/systemd/system/archr-bluetooth-agent.service << 'BTAGENT_SVC'
[Unit]
Description=Arch R Bluetooth Agent
After=bluetooth.service
PartOf=bluetooth.service
[Service]
Type=simple
ExecStart=/usr/local/bin/archr-bluetooth-agent
Restart=on-failure
RestartSec=10
[Install]
WantedBy=bluetooth.target
BTAGENT_SVC
systemctl enable archr-bluetooth-agent
# Sleep configuration (suspend disabled by default, user enables via archr-suspend-mode)
mkdir -p /etc/systemd/sleep.conf.d
cat > /etc/systemd/sleep.conf.d/archr.conf << 'SLEEP_CONF'
[Sleep]
AllowSuspend=yes
SuspendState=mem
AllowHibernation=no
SLEEP_CONF
# Modules blacklist for sleep (unloaded before suspend by archr-sleep hook)
mkdir -p /etc/archr
install -m 644 /tmp/modules.bad /etc/archr/modules.bad 2>/dev/null || true
# Delete stock ALARM initramfs and kernel (we use our own kernel + initramfs)
# Our initramfs.img is built by build-image.sh and placed on BOOT partition
rm -f /boot/initramfs-linux.img /boot/Image /boot/Image.gz 2>/dev/null
@@ -546,7 +647,7 @@ dd if=/dev/urandom of=/var/lib/systemd/random-seed bs=512 count=1 2>/dev/null
chmod 600 /var/lib/systemd/random-seed
# Sudoers for perfmax/perfnorm/pmic-poweroff (allow archr to run without password)
echo "archr ALL=(ALL) NOPASSWD: /usr/local/bin/perfmax, /usr/local/bin/perfnorm, /usr/local/bin/pmic-poweroff, /usr/local/bin/input-merge, /usr/bin/kill, /usr/bin/ln, /usr/bin/dmesg, /usr/bin/chvt, /usr/bin/cp, /usr/bin/chmod, /bin/bash" > /etc/sudoers.d/archr-perf
echo "archr ALL=(ALL) NOPASSWD: /usr/local/bin/perfmax, /usr/local/bin/perfnorm, /usr/local/bin/pmic-poweroff, /usr/local/bin/input-merge, /usr/local/bin/archr-gptokeyb, /usr/local/bin/archr-factory-reset, /usr/local/bin/archr-suspend-mode, /usr/local/bin/archr-usbgadget, /usr/bin/kill, /usr/bin/ln, /usr/bin/dmesg, /usr/bin/chvt, /usr/bin/cp, /usr/bin/chmod, /usr/bin/tee, /usr/bin/systemctl, /bin/bash" > /etc/sudoers.d/archr-perf
chmod 440 /etc/sudoers.d/archr-perf
# Allow archr to use negative nice values (needed for nice -n -19 in ES launch commands)
@@ -597,8 +698,8 @@ cat > /etc/systemd/logind.conf.d/fast.conf << 'LOGIND_EOF'
[Login]
NAutoVTs=1
ReserveVT=0
HandlePowerKey=ignore
HandleSuspendKey=ignore
HandlePowerKey=suspend
HandleSuspendKey=suspend
HandleHibernateKey=ignore
HandleLidSwitch=ignore
KillUserProcesses=no
@@ -694,6 +795,7 @@ for sock in \
systemd-mute-console.socket systemd-bootctl.socket \
systemd-creds.socket systemd-repart.socket \
systemd-importd.socket systemd-machined.socket \
systemd-hostnamed.socket \
systemd-rfkill.socket dm-event.socket \
systemd-coredump.socket systemd-sysext.socket \
systemd-ask-password-wall.socket \
@@ -721,6 +823,9 @@ for rule in 60-cdrom_id 60-dmi-id 60-fido-id 60-infiniband \
ln -sf /dev/null "/etc/udev/rules.d/${rule}.rules"
done
# Allow input group to use /dev/uinput (needed by archr-gptokeyb and input-merge)
echo 'KERNEL=="uinput", GROUP="input", MODE="0660"' > /etc/udev/rules.d/99-archr-uinput.rules
# Pre-build caches NOW (inside chroot) so masks are safe
ldconfig 2>/dev/null || true
journalctl --update-catalog 2>/dev/null || true
@@ -960,6 +1065,9 @@ chmod +x "$ROOTFS_DIR/tmp/setup.sh"
# Copy libvlc stub into chroot (needed by bloat cleanup — ES links against libvlc.so.5)
cp "$SCRIPT_DIR/scripts/libvlc-stub-aarch64.so" "$ROOTFS_DIR/tmp/libvlc-stub.so"
# Copy modules.bad into chroot (installed by setup.sh to /etc/archr/)
cp "$SCRIPT_DIR/config/modules.bad" "$ROOTFS_DIR/tmp/modules.bad"
# Run setup inside chroot
log " Running setup inside chroot..."
chroot "$ROOTFS_DIR" /tmp/setup.sh
@@ -977,7 +1085,7 @@ install -m 755 "$SCRIPT_DIR/scripts/perfmax" "$ROOTFS_DIR/usr/local/bin/perfmax"
install -m 755 "$SCRIPT_DIR/scripts/perfnorm" "$ROOTFS_DIR/usr/local/bin/perfnorm"
install -m 755 "$SCRIPT_DIR/scripts/pmic-poweroff" "$ROOTFS_DIR/usr/local/bin/pmic-poweroff"
install -m 755 "$SCRIPT_DIR/scripts/retroarch-launch.sh" "$ROOTFS_DIR/usr/local/bin/retroarch-launch"
# RetroArch core options (per-core tuning for RK3326, from ROCKNIX)
# RetroArch core options (per-core tuning for RK3326)
install -m 644 "$SCRIPT_DIR/config/retroarch-core-options.cfg" "$ROOTFS_DIR/home/archr/.config/retroarch/retroarch-core-options.cfg"
log " ✓ RetroArch core options installed"
# Input merger daemon: combines gpio-keys + adc-joystick into single virtual device
@@ -987,9 +1095,19 @@ if command -v aarch64-linux-gnu-gcc &>/dev/null; then
"$SCRIPT_DIR/scripts/input-merge.c"
chmod 755 "$ROOTFS_DIR/usr/local/bin/input-merge"
log " ✓ input-merge compiled and installed"
# Gamepad-to-keyboard mapper for Linux ports (compatible with ROCKNIX .gptk configs)
aarch64-linux-gnu-gcc -static -O2 -o "$ROOTFS_DIR/usr/local/bin/archr-gptokeyb" \
"$SCRIPT_DIR/scripts/archr-gptokeyb.c"
chmod 755 "$ROOTFS_DIR/usr/local/bin/archr-gptokeyb"
log " ✓ archr-gptokeyb compiled and installed"
else
warn "aarch64-linux-gnu-gcc not found — input-merge not compiled"
warn "aarch64-linux-gnu-gcc not found — input-merge/gptokeyb not compiled"
fi
# gptokeyb config files
mkdir -p "$ROOTFS_DIR/etc/archr/gptokeyb"
install -m 644 "$SCRIPT_DIR/config/gptokeyb/default.gptk" "$ROOTFS_DIR/etc/archr/gptokeyb/default.gptk"
install -m 644 "$SCRIPT_DIR/config/gptokeyb/tools.gptk" "$ROOTFS_DIR/etc/archr/gptokeyb/tools.gptk"
log " ✓ gptokeyb configs installed (default + tools)"
# RetroArch joypad autoconfig (merged device + individual fallbacks)
mkdir -p "$ROOTFS_DIR/usr/share/retroarch/autoconfig/udev"
install -m 644 "$SCRIPT_DIR/config/autoconfig/udev/archr-gamepad.cfg" "$ROOTFS_DIR/usr/share/retroarch/autoconfig/udev/"
@@ -1011,6 +1129,40 @@ install -m 755 "$SCRIPT_DIR/scripts/timezones" "$ROOTFS_DIR/usr/local/bin/timezo
install -m 755 "$SCRIPT_DIR/scripts/auto_suspend_update.sh" "$ROOTFS_DIR/usr/local/bin/auto_suspend_update.sh"
log " ✓ ES compatibility scripts installed (timezones, auto_suspend_update.sh)"
# System management scripts
install -m 755 "$SCRIPT_DIR/scripts/archr-automount" "$ROOTFS_DIR/usr/local/bin/archr-automount"
install -m 755 "$SCRIPT_DIR/scripts/archr-usbgadget" "$ROOTFS_DIR/usr/local/bin/archr-usbgadget"
install -m 755 "$SCRIPT_DIR/scripts/archr-bluetooth-agent" "$ROOTFS_DIR/usr/local/bin/archr-bluetooth-agent"
install -m 755 "$SCRIPT_DIR/scripts/archr-factory-reset" "$ROOTFS_DIR/usr/local/bin/archr-factory-reset"
install -m 755 "$SCRIPT_DIR/scripts/archr-suspend-mode" "$ROOTFS_DIR/usr/local/bin/archr-suspend-mode"
install -m 755 "$SCRIPT_DIR/scripts/archr-save-config" "$ROOTFS_DIR/usr/local/bin/archr-save-config"
install -m 755 "$SCRIPT_DIR/scripts/archr-memory-manager" "$ROOTFS_DIR/usr/local/bin/archr-memory-manager"
log " ✓ System management scripts installed"
# System sleep hook (called by systemd on suspend/resume)
mkdir -p "$ROOTFS_DIR/usr/lib/systemd/system-sleep"
install -m 755 "$SCRIPT_DIR/scripts/archr-sleep" "$ROOTFS_DIR/usr/lib/systemd/system-sleep/archr-sleep"
log " ✓ Sleep hook installed"
# ES Tools shared menu library (sourced by tool scripts)
mkdir -p "$ROOTFS_DIR/usr/lib/archr"
install -m 644 "$SCRIPT_DIR/scripts/opt-system/menu-lib.sh" "$ROOTFS_DIR/usr/lib/archr/menu-lib.sh"
# ES Tools menu scripts (shown in ES OPTIONS menu via GuiTools)
mkdir -p "$ROOTFS_DIR/opt/system"
for script in "$SCRIPT_DIR/scripts/opt-system/"*.sh; do
[ -f "$script" ] || continue
[ "$(basename "$script")" = "menu-lib.sh" ] && continue
install -m 755 "$script" "$ROOTFS_DIR/opt/system/$(basename "$script")"
done
log " ✓ ES Tools menu scripts installed (/opt/system/)"
# Udev rules
mkdir -p "$ROOTFS_DIR/etc/udev/rules.d"
install -m 644 "$SCRIPT_DIR/config/udev/99-archr-automount.rules" "$ROOTFS_DIR/etc/udev/rules.d/99-archr-automount.rules"
install -m 644 "$SCRIPT_DIR/config/udev/80-archr-usbgadget.rules" "$ROOTFS_DIR/etc/udev/rules.d/80-archr-usbgadget.rules"
log " ✓ Udev rules installed (automount, usbgadget)"
# Install prebuilt libretro cores (not available in ALARM repos)
PREBUILT_CORES="$SCRIPT_DIR/prebuilt/cores"
if [ -d "$PREBUILT_CORES" ]; then
@@ -1034,10 +1186,6 @@ log " ✓ First boot script installed"
# Boot splash: no binary needed in rootfs — splash is embedded in initramfs /init
# (built by build-image.sh: archr-init.c + embedded splash BMP → initramfs.img)
# Panel detection wizard
install -m 755 "$SCRIPT_DIR/scripts/panel-detect.py" "$ROOTFS_DIR/usr/local/bin/panel-detect.py"
log " ✓ Panel detection wizard installed"
# RetroArch config (install to user's config dir where retroarch expects it)
mkdir -p "$ROOTFS_DIR/home/archr/.config/retroarch"
cp "$SCRIPT_DIR/config/retroarch.cfg" "$ROOTFS_DIR/home/archr/.config/retroarch/retroarch.cfg"
@@ -1069,6 +1217,9 @@ log " ✓ Battery LED script installed"
install -m 755 "$SCRIPT_DIR/scripts/archr-hotkeys.py" "$ROOTFS_DIR/usr/local/bin/archr-hotkeys.py"
log " ✓ Hotkey daemon installed"
# Screenshots directory (used by MODE+B hotkey)
mkdir -p "$ROOTFS_DIR/home/archr/screenshots"
# Fix ownership of archr home directory (files installed by root in Step 5)
chown -R 1001:1001 "$ROOTFS_DIR/home/archr"
log " ✓ archr home ownership fixed (UID 1001)"
@@ -1082,18 +1233,22 @@ log "Step 6: Installing kernel and modules..."
KERNEL_BOOT="$OUTPUT_DIR/boot"
KERNEL_MODULES="$OUTPUT_DIR/modules/lib/modules"
if [ -f "$KERNEL_BOOT/Image" ]; then
if [ -f "$KERNEL_BOOT/KERNEL" ]; then
mkdir -p "$ROOTFS_DIR/boot"
cp "$KERNEL_BOOT/Image" "$ROOTFS_DIR/boot/"
log " ✓ Kernel Image installed"
cp "$KERNEL_BOOT/KERNEL" "$ROOTFS_DIR/boot/"
log " ✓ Kernel installed to rootfs/boot/"
# Copy R36S DTB
for dtb in "$KERNEL_BOOT"/*.dtb; do
[ -f "$dtb" ] && cp "$dtb" "$ROOTFS_DIR/boot/" && \
log " ✓ DTB installed: $(basename "$dtb")"
done
# Copy board DTBs (build-image.sh handles BOOT partition separately)
if [ -d "$KERNEL_BOOT/dtbs" ]; then
mkdir -p "$ROOTFS_DIR/boot/dtbs"
for dtb in "$KERNEL_BOOT/dtbs"/rk3326-*.dtb; do
[ -f "$dtb" ] && cp "$dtb" "$ROOTFS_DIR/boot/dtbs/"
done
dtb_count=$(ls "$ROOTFS_DIR/boot/dtbs"/rk3326-*.dtb 2>/dev/null | wc -l)
log "$dtb_count DTBs installed to rootfs/boot/dtbs/"
fi
else
warn "Kernel Image not found. Run build-kernel.sh first!"
warn "Kernel not found at $KERNEL_BOOT/KERNEL. Run build-kernel.sh first!"
fi
if [ -d "$KERNEL_MODULES" ]; then
+1 -1
View File
@@ -2,7 +2,7 @@
#==============================================================================
# Arch R - Build Mainline U-Boot for R36S Clones
#==============================================================================
# Uses mainline U-Boot v2025.10 + ROCKNIX patches
# Uses mainline U-Boot v2025.10 + RK3326 handheld patches
# Produces: idbloader.img, uboot.img, trust.img (Rockchip format)
#
# Usage:
+125 -79
View File
@@ -1,121 +1,163 @@
#!/bin/bash
#==============================================================================
# Arch R - U-Boot Build Script for R36S
# Arch R - Build U-Boot BSP for RK3326
#==============================================================================
# Builds custom U-Boot with R36S original/clone auto-detection via eMMC probe.
# Cross-compiles for aarch64 (CONFIG_ARM64=y in defconfig).
# Builds U-Boot v2017.09 BSP for all RK3326 handhelds.
# Same binary works for both original and clone boards — hwrev.c detects
# board variant via SARADC ch0, boot.ini overrides DTB as needed.
#
# Custom modifications:
# - cmd/hwrev.c: R36S detection via eMMC probe (original vs clone)
# - r36s-uboot.dts: U-Boot display DTB for original (Panel 4-V22 NV3052C)
# - r36s-clone-uboot.dts: U-Boot display DTB for clone (Type5 NV3052C)
# Output: bootloader/u-boot-rk3326/sd_fuse/
# idbloader.img — DDR init + miniloader
# uboot.img — U-Boot proper
# trust.img — ARM Trusted Firmware (BL31 + BL32)
#
# Prerequisites:
# sudo apt install gcc-aarch64-linux-gnu
# Usage:
# ./build-uboot.sh # build for SD card
# ./build-uboot.sh --clean # clean build artifacts first
#==============================================================================
set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
UBOOT_DIR="$SCRIPT_DIR/bootloader/u-boot-rk3326"
RKBIN_DIR="$SCRIPT_DIR/bootloader/rkbin"
OUTPUT_DIR="$UBOOT_DIR/sd_fuse"
# Firmware versions (from rkbin)
DDR_BIN="$RKBIN_DIR/bin/rk33/rk3326_ddr_333MHz_v2.11.bin"
MINILOADER_BIN="$RKBIN_DIR/bin/rk33/rk3326_miniloader_v1.40.bin"
BL31_ELF="$RKBIN_DIR/bin/rk33/rk3326_bl31_v1.34.elf"
BL32_BIN="$RKBIN_DIR/bin/rk33/rk3326_bl32_v2.19.bin"
# Colors
RED='\033[0;31m'
GREEN='\033[0;32m'
RED='\033[0;31m'
YELLOW='\033[1;33m'
NC='\033[0m'
log() { echo -e "${GREEN}[$(date '+%H:%M:%S')]${NC} $1"; }
warn() { echo -e "${YELLOW}[$(date '+%H:%M:%S')] WARNING:${NC} $1"; }
error() { echo -e "${RED}[$(date '+%H:%M:%S')] ERROR:${NC} $1"; exit 1; }
log() { echo -e "${GREEN}[U-BOOT]${NC} $1"; }
warn() { echo -e "${YELLOW}[U-BOOT] WARNING:${NC} $1"; }
error() { echo -e "${RED}[U-BOOT] ERROR:${NC} $1"; exit 1; }
#------------------------------------------------------------------------------
# Configuration
# Parse arguments
#------------------------------------------------------------------------------
UBOOT_DIR="$SCRIPT_DIR/bootloader"
UBOOT_REPO="https://github.com/christianhaitian/RG351MP-u-boot"
UBOOT_SRC="$UBOOT_DIR/u-boot-rk3326"
OUTPUT_DIR="$SCRIPT_DIR/output/bootloader"
# U-Boot for RK3326 is aarch64 (CONFIG_ARM64=y in defconfig)
CROSS_COMPILE="aarch64-linux-gnu-"
log "=== Arch R - U-Boot Builder (Custom R36S) ==="
CLEAN=false
while [[ $# -gt 0 ]]; do
case $1 in
--clean) CLEAN=true; shift ;;
*) error "Unknown option: $1\nUsage: $0 [--clean]" ;;
esac
done
#------------------------------------------------------------------------------
# Step 1: Clone U-Boot
# Prerequisites
#------------------------------------------------------------------------------
log ""
log "Step 1: Checking U-Boot source..."
log "=== Arch R U-Boot Builder ==="
mkdir -p "$UBOOT_DIR"
if ! command -v aarch64-linux-gnu-gcc &>/dev/null; then
error "Cross-compiler not found. Install with: sudo apt install gcc-aarch64-linux-gnu"
fi
if [ ! -d "$UBOOT_SRC" ]; then
log " Cloning U-Boot for RK3326..."
git clone --depth 1 "$UBOOT_REPO" "$UBOOT_SRC"
log " Cloned"
else
log " Source exists"
if [ ! -d "$UBOOT_DIR" ]; then
error "U-Boot source not found at: $UBOOT_DIR"
fi
if [ ! -f "$DDR_BIN" ]; then
error "rkbin firmware not found at: $RKBIN_DIR\nExpected: $DDR_BIN"
fi
GCC_VER=$(aarch64-linux-gnu-gcc -dumpversion)
log "Compiler: aarch64-linux-gnu-gcc $GCC_VER"
#------------------------------------------------------------------------------
# Clean (optional)
#------------------------------------------------------------------------------
if [ "$CLEAN" = true ]; then
log "Cleaning previous build..."
make -C "$UBOOT_DIR" distclean 2>/dev/null || true
rm -rf "$OUTPUT_DIR"
fi
#------------------------------------------------------------------------------
# Step 2: Verify toolchain
# Build U-Boot
#------------------------------------------------------------------------------
log ""
log "Step 2: Checking toolchain..."
log "Step 1: Configuring (odroidgoa_defconfig)..."
if ! command -v ${CROSS_COMPILE}gcc &>/dev/null; then
error "aarch64 toolchain not found!\n Install: sudo apt install gcc-aarch64-linux-gnu"
cd "$UBOOT_DIR"
# GCC 13+ needs these warnings suppressed for 2017.09 codebase
export KCFLAGS="-Wno-error=array-bounds -Wno-error=enum-int-mismatch -Wno-error=implicit-function-declaration -Wno-error=format-overflow"
make odroidgoa_defconfig 2>&1 | tail -3
log "Step 2: Building U-Boot..."
NCPUS=$(nproc 2>/dev/null || echo 4)
make CROSS_COMPILE=aarch64-linux-gnu- all --jobs=$NCPUS 2>&1 | tail -5
if [ ! -f "u-boot.bin" ]; then
error "Build failed — u-boot.bin not found"
fi
log " $(${CROSS_COMPILE}gcc --version | head -1)"
log " u-boot.bin built OK"
#------------------------------------------------------------------------------
# Step 3: Build U-Boot
# Pack images
#------------------------------------------------------------------------------
log ""
log "Step 3: Building U-Boot..."
cd "$UBOOT_SRC"
# GCC 13+ adds stricter warnings that U-Boot 2017.09 doesn't pass.
# Disable specific -Werror flags that break with modern GCC:
# address-of-packed-member: disk/part_efi.c (packed struct pointer)
# enum-int-mismatch: common/command.c (enum command_ret_t vs int)
# maybe-uninitialized: common/edid.c (hdmi_len variable)
GCC_COMPAT_FLAGS="-Wno-error=address-of-packed-member -Wno-error=enum-int-mismatch -Wno-error=maybe-uninitialized"
make CROSS_COMPILE=$CROSS_COMPILE odroidgoa_defconfig
make CROSS_COMPILE=$CROSS_COMPILE KCFLAGS="$GCC_COMPAT_FLAGS" -j$(nproc)
log " Built"
#------------------------------------------------------------------------------
# Step 4: Copy artifacts
#------------------------------------------------------------------------------
log ""
log "Step 4: Copying bootloader files..."
log "Step 3: Packing images..."
mkdir -p "$OUTPUT_DIR"
if [ -d "sd_fuse" ] && [ -f "sd_fuse/idbloader.img" ]; then
cp sd_fuse/idbloader.img "$OUTPUT_DIR/"
cp sd_fuse/uboot.img "$OUTPUT_DIR/"
cp sd_fuse/trust.img "$OUTPUT_DIR/"
log " Bootloader binaries copied"
else
error "sd_fuse directory not found — U-Boot build may have failed"
fi
# idbloader.img = DDR init + miniloader
"$UBOOT_DIR/tools/mkimage" -n px30 -T rksd -d "$DDR_BIN" "$OUTPUT_DIR/idbloader.img"
cat "$MINILOADER_BIN" >> "$OUTPUT_DIR/idbloader.img"
log " idbloader.img (DDR v2.11 + miniloader v1.40)"
# Copy R36S U-Boot DTBs
for dtb in r36s-uboot.dtb r36s-clone-uboot.dtb; do
if [ -f "arch/arm/dts/$dtb" ]; then
cp "arch/arm/dts/$dtb" "$OUTPUT_DIR/"
log " DTB copied: $dtb"
else
warn "DTB not found: $dtb"
# uboot.img = packed U-Boot binary
UBOOT_LOAD_ADDR=$(grep -r "CONFIG_SYS_TEXT_BASE" include/autoconf.mk 2>/dev/null | cut -d= -f2 || echo "0x00200000")
"$RKBIN_DIR/tools/loaderimage" --pack --uboot u-boot.bin "$OUTPUT_DIR/uboot.img" "$UBOOT_LOAD_ADDR" 2>&1 | tail -1
log " uboot.img (load addr: $UBOOT_LOAD_ADDR)"
# trust.img = BL31 + BL32
cat > /tmp/archr-trust.ini << TRUST_EOF
[VERSION]
MAJOR=1
MINOR=0
[BL30_OPTION]
SEC=0
[BL31_OPTION]
SEC=1
PATH=$BL31_ELF
ADDR=0x00010000
[BL32_OPTION]
SEC=1
PATH=$BL32_BIN
ADDR=0x08400000
[BL33_OPTION]
SEC=0
[OUTPUT]
PATH=$OUTPUT_DIR/trust.img
TRUST_EOF
"$RKBIN_DIR/tools/trust_merger" --rsa 3 /tmp/archr-trust.ini 2>&1 | tail -1
rm -f /tmp/archr-trust.ini
log " trust.img (BL31 v1.34 + BL32 v2.19)"
#------------------------------------------------------------------------------
# Verify
#------------------------------------------------------------------------------
log ""
log "Step 4: Verifying..."
for img in idbloader.img uboot.img trust.img; do
if [ ! -f "$OUTPUT_DIR/$img" ]; then
error "Missing: $OUTPUT_DIR/$img"
fi
SIZE=$(du -h "$OUTPUT_DIR/$img" | cut -f1)
log " $img ($SIZE)"
done
#------------------------------------------------------------------------------
@@ -124,7 +166,11 @@ done
log ""
log "=== U-Boot Build Complete ==="
log ""
log "Bootloader: $OUTPUT_DIR/"
ls -lh "$OUTPUT_DIR/"
log "Output: $OUTPUT_DIR/"
log " idbloader.img — DDR v2.11 + miniloader v1.40"
log " uboot.img — U-Boot v2017.09 BSP"
log " trust.img — BL31 v1.34 + BL32 v2.19"
log ""
log "These will be installed by build-image.sh"
log "Same binary for both original and clone images."
log "Board detection: hwrev.c (SARADC ch0)"
log "DTB selection: boot.ini (variant A or B)"
+61
View File
@@ -0,0 +1,61 @@
odroidgoa-uboot-config
########################################################################
# Arch R Boot Configuration — Variant A (BSP U-Boot)
#
# For: Original R36S, OGA, OGA v1.1, OGS, R33S, RG351V, RG351M,
# GameForce Chi, MagicX XU10
#
# BSP U-Boot reads this file directly.
# hwrev is set by BSP's hwrev.c from SARADC ch0 before this runs.
#
# We ALWAYS load our DTB from partition (not U-Boot embedded) because
# our DTBs have archr-* compatible strings for joypad/panel drivers.
########################################################################
# Memory addresses
setenv loadaddr "0x02000000"
setenv dtb_loadaddr "0x01f00000"
setenv dtbo_loadaddr "0x01e00000"
# Load kernel
load mmc 1:1 ${loadaddr} KERNEL
# Map hwrev to board DTB (always load from partition)
if test ${hwrev} = 'v10-go3'; then
load mmc 1:1 ${dtb_loadaddr} dtbs/rk3326-odroid-go3.dtb
elif test ${hwrev} = 'r33s'; then
load mmc 1:1 ${dtb_loadaddr} dtbs/rk3326-gameconsole-r33s.dtb
elif test ${hwrev} = 'chi'; then
load mmc 1:1 ${dtb_loadaddr} dtbs/rk3326-gameforce-chi.dtb
elif test ${hwrev} = 'rg351v'; then
gpio input b6
if test $? -eq 0; then
load mmc 1:1 ${dtb_loadaddr} dtbs/rk3326-anbernic-rg351v.dtb
else
load mmc 1:1 ${dtb_loadaddr} dtbs/rk3326-gameconsole-r36s.dtb
fi
elif test ${hwrev} = 'v11'; then
load mmc 1:1 ${dtb_loadaddr} dtbs/rk3326-odroid-go2-v11.dtb
elif test ${hwrev} = 'v10'; then
load mmc 1:1 ${dtb_loadaddr} dtbs/rk3326-odroid-go2.dtb
elif test ${hwrev} = 'xu10'; then
load mmc 1:1 ${dtb_loadaddr} dtbs/rk3326-magicx-xu10.dtb
else
load mmc 1:1 ${dtb_loadaddr} dtbs/rk3326-odroid-go2.dtb
fi
# Apply panel overlay
if load mmc 1:1 ${dtbo_loadaddr} overlays/mipi-panel.dtbo; then
fdt addr ${dtb_loadaddr}
fdt resize 8192
fdt apply ${dtbo_loadaddr}
fi
# Boot
setenv bootargs "boot=LABEL=BOOT disk=LABEL=STORAGE rw console=ttyS2,115200 console=tty0 quiet loglevel=0 vt.global_cursor_default=0 consoleblank=0 fsck.mode=skip"
booti ${loadaddr} - ${dtb_loadaddr}
# Power off if boot fails
sleep 15
poweroff
+12 -4
View File
@@ -67,16 +67,19 @@ CONFIG_DRM_PANFROST=m
# ============================================================
# Framebuffer: fb0 via DRM emulation + fbcon
# DEFERRED_TAKEOVER=y: fbcon waits for text output before clearing
# screen. With quiet+ttyFIQ0, U-Boot logo persists until Plymouth
# takes DRM master. Plymouth handles splash via KMS/DRM natively.
# DEFERRED_TAKEOVER DISABLED: With deferred takeover, fbcon does
# NOT trigger DRM modeset until text is written to console.
# On clone R36S (mainline U-Boot, no BSP display init), this
# means display stays BLACK. ROCKNIX explicitly disables this.
# FRAMEBUFFER_CONSOLE_ROTATION: Display rotation support.
# ============================================================
CONFIG_DRM_FBDEV_EMULATION=y
CONFIG_DRM_FBDEV_OVERALLOC=200
CONFIG_FB=y
CONFIG_FRAMEBUFFER_CONSOLE=y
CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
CONFIG_FRAMEBUFFER_CONSOLE_DEFERRED_TAKEOVER=y
CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
# CONFIG_FRAMEBUFFER_CONSOLE_DEFERRED_TAKEOVER is not set
# CONFIG_LOGO is not set
# ============================================================
@@ -209,6 +212,11 @@ CONFIG_DEBUG_INFO_NONE=y
# CONFIG_MEDIA_TEST_SUPPORT is not set
# CONFIG_DVB_CORE is not set
# ============================================================
# Panel driver: Arch R Generic DSI (panel_description strings)
# ============================================================
CONFIG_DRM_PANEL_ARCHR_DSI=y
# ============================================================
# SIZE TRIM: Display drivers — R36S uses ONLY MIPI DSI (~500KB-1MB)
# ============================================================
+10
View File
@@ -0,0 +1,10 @@
# Arch R fragment — applied on top of ROCKNIX base config
# Only contains overrides specific to Arch Linux
# Initramfs: embedded in kernel (path set by build-kernel.sh)
# CONFIG_INITRAMFS_SOURCE is set dynamically
# Compression
CONFIG_INITRAMFS_COMPRESSION_GZIP=y
CONFIG_INITRAMFS_ROOT_UID=0
CONFIG_INITRAMFS_ROOT_GID=0
+48
View File
@@ -0,0 +1,48 @@
odroidgoa-uboot-config
########################################################################
# Arch R Boot Configuration — Variant B (Clone boards)
#
# For: K36 clones, Powkiddy RGB20S, Powkiddy RGB10X, MagicX XU-Mini-M
#
# hwrev is set by U-Boot's board file from SARADC ch0 before this runs.
# This script overrides the kernel DTB for boards that need a different
# DTB than what U-Boot loaded internally.
#
# hwrev mappings (clone boards):
# r33s = Powkiddy RGB10X (shares ADC range with R33S)
# xu10 = MagicX XU-Mini-M (shares ADC range with XU10)
# rg351v = K36 clone / R36Max / EE clone boards
########################################################################
# Memory addresses
setenv loadaddr "0x02000000"
setenv dtb_loadaddr "0x01f00000"
setenv dtbo_loadaddr "0x01e00000"
# Load kernel
load mmc 1:1 ${loadaddr} KERNEL
# Override DTB for clone boards
if test ${hwrev} = 'r33s'; then
load mmc 1:1 ${dtb_loadaddr} dtbs/rk3326-powkiddy-rgb10x.dtb
elif test ${hwrev} = 'xu10'; then
load mmc 1:1 ${dtb_loadaddr} dtbs/rk3326-magicx-xu-mini-m.dtb
elif test ${hwrev} = 'rg351v'; then
load mmc 1:1 ${dtb_loadaddr} dtbs/rk3326-gameconsole-r36max.dtb
fi
# Apply panel overlay
if load mmc 1:1 ${dtbo_loadaddr} overlays/mipi-panel.dtbo; then
fdt addr ${dtb_loadaddr}
fdt resize 8192
fdt apply ${dtbo_loadaddr}
fi
# Boot
setenv bootargs "boot=LABEL=BOOT disk=LABEL=STORAGE rw console=ttyS2,115200 console=tty0 quiet loglevel=0 vt.global_cursor_default=0 consoleblank=0 fsck.mode=skip"
booti ${loadaddr} - ${dtb_loadaddr}
# Power off if boot fails
sleep 15
poweroff
-74
View File
@@ -1,74 +0,0 @@
odroidgoa-uboot-config
########################################################################
# Arch R Boot Configuration
#
# Auto-detects SD card MMC device AND root partition:
# Original R36S: eMMC=mmc0, SD=mmc1 → root=/dev/mmcblk1p2
# Clone (no eMMC): SD=mmc0 → root=/dev/mmcblk0p2
#
# Panel config from panel.txt (managed by panel-detect.py).
# Panel reset handled in Linux (panel-detect.py) -- no GPIO check here
# because X button GPIO differs between boards (modular!).
########################################################################
# --- Turn on LED immediately (feedback: device is booting) ---
gpio set b5
setenv tmp_loadaddr "0x01e00000"
setenv dtb_loadaddr "0x01f00000"
setenv loadaddr "0x02000000"
# --- Auto-detect MMC device (loads kernel Image into memory) ---
setenv mmcdev 1
if load mmc 1:1 ${loadaddr} Image; then
setenv mmcdev 1
elif load mmc 0:1 ${loadaddr} Image; then
setenv mmcdev 0
else
sleep 15
poweroff
fi
# --- Panel DTB selection (read panel.txt written by panel-detect.py) ---
# Pre-merged DTBs: overlay already applied at build-time (no fdt apply needed).
# panel.txt contains PanelDTB=kernel-panelN.dtb (or empty for default).
setenv PanelDTB ""
mw.b ${tmp_loadaddr} 0x00 0x400
if load mmc ${mmcdev}:1 ${tmp_loadaddr} panel.txt; then
env import -t ${tmp_loadaddr} ${filesize}
fi
# Select DTB: pre-merged panel DTB if set, otherwise default kernel.dtb
if test -n "${PanelDTB}"; then
setenv dtb_name "${PanelDTB}"
echo "Panel DTB: ${PanelDTB}"
else
setenv dtb_name "kernel.dtb"
fi
# --- Auto-detect root device (SD card partition 2) ---
# mmcdev already detected above: 1 = original (eMMC+SD), 0 = clone (SD only)
if test "${mmcdev}" = "1"; then
setenv rootdev "/dev/mmcblk1p2"
else
setenv rootdev "/dev/mmcblk0p2"
fi
# --- Load DTB and boot (Image already loaded above) ---
if load mmc ${mmcdev}:1 ${dtb_loadaddr} ${dtb_name}; then
setenv bootargs "root=${rootdev} rootwait rw console=ttyFIQ0 loglevel=0 quiet vt.global_cursor_default=0 consoleblank=0 printk.devkmsg=off fsck.mode=skip"
# Load initramfs (splash appears immediately after kernel boot, before systemd)
setenv initrd_loadaddr "0x04000000"
if load mmc ${mmcdev}:1 ${initrd_loadaddr} initramfs.img; then
booti ${loadaddr} ${initrd_loadaddr}:${filesize} ${dtb_loadaddr}
else
booti ${loadaddr} - ${dtb_loadaddr}
fi
fi
# Power off if boot fails
sleep 15
poweroff
+36
View File
@@ -0,0 +1,36 @@
# Arch R — Default gamepad-to-keyboard mapping
# Used by archr-gptokeyb for Linux ports that need keyboard input.
# Per-game overrides: /etc/archr/gptokeyb/<game>.gptk
# Format: button_name = key_name (compatible with ROCKNIX .gptk)
# Action buttons
a = space
b = backspace
x = c
y = v
# Shoulder buttons
l1 = a
r1 = s
l2 = q
r2 = e
# Menu
back = esc
start = enter
guide = f1
# D-pad
up = up
down = down
left = left
right = right
# Left analog → mouse movement
left_analog_as_mouse = true
# Right analog → arrow keys
right_analog_up = up
right_analog_down = down
right_analog_left = left
right_analog_right = right
+20
View File
@@ -0,0 +1,20 @@
# Arch R — Gamepad mapping for system tools (menus)
# D-pad navigates, A=select, B=back, Start=select, Back=back
# D-pad → arrow keys for menu navigation
up = up
down = down
left = left
right = right
# A button → Enter (select/confirm)
a = enter
# B button → Escape (back/cancel)
b = escape
# Start → Enter (alternate confirm)
start = enter
# Back/Select → Escape (alternate back)
back = escape
File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More