From 0b7b0ce2332cb04fc1e82011695fda12b218a7e2 Mon Sep 17 00:00:00 2001 From: Nick Chapman Date: Wed, 31 Dec 2025 13:21:25 -0800 Subject: [PATCH 1/6] Rename rk3566 platform to rgb30. LessUI platforms represent device families, not chipsets. The rk3566 platform was specific to RGB30's 720x720 display and input layout. Renamed to match device identity and avoid confusion with other RK3566 devices (RG353P/V/VS, RG503) which have different displays/features. Also updated updater to detect RGB30 via LESSOS_DEVICE instead of LESSOS_PLATFORM, enabling device-specific detection on LessOS. --- Makefile | 2 +- skeleton/BOOT/common/updater | 20 +- skeleton/SYSTEM/rgb30/bin/shutdown | 12 - skeleton/SYSTEM/rgb30/cores/.keep | 0 skeleton/SYSTEM/rgb30/dat/.keep | 0 skeleton/SYSTEM/rgb30/lib/.keep | 0 skeleton/SYSTEM/rgb30/system.cfg | 2 - toolchains.json | 2 +- .../all/paks/LessUI/platforms/rgb30/init.sh | 21 +- .../all/paks/LessUI/platforms/rk3566/init.sh | 26 -- .../all/paks/Tools/System Report/pak.json | 1 - workspace/all/paks/config/platforms.json | 9 +- workspace/rgb30/Makefile | 22 +- workspace/rgb30/README.md | 56 +-- workspace/{rk3566 => rgb30}/install/boot.sh | 4 +- workspace/rgb30/platform/Makefile.copy | 10 +- workspace/rgb30/platform/Makefile.env | 4 +- workspace/rgb30/platform/platform.c | 30 +- workspace/rgb30/platform/platform.h | 20 +- workspace/rgb30/show/Makefile | 2 +- workspace/rgb30/show/show.c | 83 +++- workspace/rk3566/Makefile | 28 -- workspace/rk3566/README.md | 330 -------------- workspace/rk3566/libmsettings/Makefile | 32 -- workspace/rk3566/libmsettings/msettings.c | 203 --------- workspace/rk3566/libmsettings/msettings.h | 25 -- workspace/rk3566/other/.keep | 0 workspace/rk3566/platform/Makefile.copy | 13 - workspace/rk3566/platform/Makefile.env | 4 - workspace/rk3566/platform/platform.c | 406 ------------------ workspace/rk3566/platform/platform.h | 222 ---------- workspace/rk3566/show/Makefile | 14 - workspace/rk3566/show/show.c | 83 ---- 33 files changed, 165 insertions(+), 1521 deletions(-) delete mode 100755 skeleton/SYSTEM/rgb30/bin/shutdown delete mode 100644 skeleton/SYSTEM/rgb30/cores/.keep delete mode 100644 skeleton/SYSTEM/rgb30/dat/.keep delete mode 100644 skeleton/SYSTEM/rgb30/lib/.keep delete mode 100644 skeleton/SYSTEM/rgb30/system.cfg delete mode 100644 workspace/all/paks/LessUI/platforms/rk3566/init.sh rename workspace/{rk3566 => rgb30}/install/boot.sh (97%) delete mode 100644 workspace/rk3566/Makefile delete mode 100644 workspace/rk3566/README.md delete mode 100644 workspace/rk3566/libmsettings/Makefile delete mode 100644 workspace/rk3566/libmsettings/msettings.c delete mode 100644 workspace/rk3566/libmsettings/msettings.h delete mode 100644 workspace/rk3566/other/.keep delete mode 100644 workspace/rk3566/platform/Makefile.copy delete mode 100644 workspace/rk3566/platform/Makefile.env delete mode 100644 workspace/rk3566/platform/platform.c delete mode 100644 workspace/rk3566/platform/platform.h delete mode 100755 workspace/rk3566/show/Makefile delete mode 100644 workspace/rk3566/show/show.c diff --git a/Makefile b/Makefile index c8f08f5d..1f734d67 100644 --- a/Makefile +++ b/Makefile @@ -29,7 +29,7 @@ endif # Default platforms to build (can be overridden with PLATFORMS=...) ifeq (,$(PLATFORMS)) -PLATFORMS = miyoomini trimuismart rg35xx rg35xxplus my355 tg5040 zero28 rgb30 m17 my282 magicmini rk3566 +PLATFORMS = miyoomini trimuismart rg35xx rg35xxplus my355 tg5040 zero28 rgb30 m17 my282 magicmini endif ########################################################### diff --git a/skeleton/BOOT/common/updater b/skeleton/BOOT/common/updater index 8977f93c..3795b744 100755 --- a/skeleton/BOOT/common/updater +++ b/skeleton/BOOT/common/updater @@ -2,9 +2,23 @@ # NOTE: becomes .tmp_update/updater -# LessOS provides platform directly via environment variable -if [ -n "$LESSOS_PLATFORM" ]; then - PLATFORM=$(echo "$LESSOS_PLATFORM" | tr '[:upper:]' '[:lower:]') +# LessOS provides device name - map to LessUI platform +if [ -n "$LESSOS_DEVICE" ]; then + case "$LESSOS_DEVICE" in + *"RGB30"*) + PLATFORM="rgb30" + ;; + *"RG353P"*|*"RG353V"*|*"RG353M"*|*"RG353"*) + # Future: map to rg353 platform if/when we add it + # For now, unsupported + echo "LessUI: Device $LESSOS_DEVICE not yet supported" + PLATFORM="" + ;; + *) + echo "LessUI: Unknown LessOS device: $LESSOS_DEVICE" + PLATFORM="" + ;; + esac else # Stock OS - detect platform from cpuinfo INFO=$(cat /proc/cpuinfo 2>/dev/null) diff --git a/skeleton/SYSTEM/rgb30/bin/shutdown b/skeleton/SYSTEM/rgb30/bin/shutdown deleted file mode 100755 index 46ebe7c2..00000000 --- a/skeleton/SYSTEM/rgb30/bin/shutdown +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/sh - -if [ -n "$DATETIME_PATH" ]; then - echo `date +'%F %T'` > "$DATETIME_PATH" - sync -fi - -cat /dev/zero > /dev/fb0 -poweroff -# echo s > /proc/sysrq-trigger -# echo u > /proc/sysrq-trigger -# echo o > /proc/sysrq-trigger diff --git a/skeleton/SYSTEM/rgb30/cores/.keep b/skeleton/SYSTEM/rgb30/cores/.keep deleted file mode 100644 index e69de29b..00000000 diff --git a/skeleton/SYSTEM/rgb30/dat/.keep b/skeleton/SYSTEM/rgb30/dat/.keep deleted file mode 100644 index e69de29b..00000000 diff --git a/skeleton/SYSTEM/rgb30/lib/.keep b/skeleton/SYSTEM/rgb30/lib/.keep deleted file mode 100644 index e69de29b..00000000 diff --git a/skeleton/SYSTEM/rgb30/system.cfg b/skeleton/SYSTEM/rgb30/system.cfg deleted file mode 100644 index f2e1550f..00000000 --- a/skeleton/SYSTEM/rgb30/system.cfg +++ /dev/null @@ -1,2 +0,0 @@ --player_screen_sharpness = Crisp - diff --git a/toolchains.json b/toolchains.json index d1795ee3..f3d1e94b 100644 --- a/toolchains.json +++ b/toolchains.json @@ -6,7 +6,7 @@ "tg5040": { "platform": "linux/amd64" }, - "rk3566": { + "rgb30": { "platform": "linux/amd64" } } diff --git a/workspace/all/paks/LessUI/platforms/rgb30/init.sh b/workspace/all/paks/LessUI/platforms/rgb30/init.sh index 9ab19c27..7108267f 100644 --- a/workspace/all/paks/LessUI/platforms/rgb30/init.sh +++ b/workspace/all/paks/LessUI/platforms/rgb30/init.sh @@ -1,22 +1,27 @@ #!/bin/sh -# rgb30 initialization +# RGB30 platform initialization (LessOS) +# Device: PowKiddy RGB30 (Rockchip RK3566) +# OS: LessOS (ROCKNIX-based) + +type log_info >/dev/null 2>&1 && log_info "RGB30 platform init starting" # CPU setup -echo userspace >/sys/devices/system/cpu/cpufreq/policy0/scaling_governor +echo userspace >/sys/devices/system/cpu/cpufreq/policy0/scaling_governor 2>/dev/null CPU_PATH=/sys/devices/system/cpu/cpufreq/policy0/scaling_setspeed CPU_SPEED_PERF=1992000 cpu_restore() { - echo $CPU_SPEED_PERF >$CPU_PATH + echo "$CPU_SPEED_PERF" >"$CPU_PATH" 2>/dev/null } cpu_restore +type log_info >/dev/null 2>&1 && log_info "CPU governor set to userspace" -# Clean up JELOS filesystem check litter -rm -f "$SDCARD_PATH"/FSCK*.REC - -# SDL environment for sdl12-compat -export SDL_VIDEODRIVER=kmsdrm +# SDL environment export SDL_AUDIODRIVER=alsa +type log_info >/dev/null 2>&1 && log_info "SDL_AUDIODRIVER=$SDL_AUDIODRIVER" # Start keymon +type log_info >/dev/null 2>&1 && log_info "Starting keymon..." LOG_FILE="$LOGS_PATH/keymon.log" keymon.elf & +KEYMON_PID=$! +type log_info >/dev/null 2>&1 && log_info "keymon started (PID: $KEYMON_PID)" diff --git a/workspace/all/paks/LessUI/platforms/rk3566/init.sh b/workspace/all/paks/LessUI/platforms/rk3566/init.sh deleted file mode 100644 index 2573b940..00000000 --- a/workspace/all/paks/LessUI/platforms/rk3566/init.sh +++ /dev/null @@ -1,26 +0,0 @@ -#!/bin/sh -# RK3566 platform initialization (LessOS) -# Supports: RGB30, RG353P/M/V/VS, and other RK3566 devices - -type log_info >/dev/null 2>&1 && log_info "RK3566 platform init starting" - -# CPU setup -echo userspace >/sys/devices/system/cpu/cpufreq/policy0/scaling_governor 2>/dev/null -CPU_PATH=/sys/devices/system/cpu/cpufreq/policy0/scaling_setspeed -CPU_SPEED_PERF=1992000 - -cpu_restore() { - echo "$CPU_SPEED_PERF" >"$CPU_PATH" 2>/dev/null -} -cpu_restore -type log_info >/dev/null 2>&1 && log_info "CPU governor set to userspace" - -# SDL environment -export SDL_AUDIODRIVER=alsa -type log_info >/dev/null 2>&1 && log_info "SDL_AUDIODRIVER=$SDL_AUDIODRIVER" - -# Start keymon -type log_info >/dev/null 2>&1 && log_info "Starting keymon..." -LOG_FILE="$LOGS_PATH/keymon.log" keymon.elf & -KEYMON_PID=$! -type log_info >/dev/null 2>&1 && log_info "keymon started (PID: $KEYMON_PID)" diff --git a/workspace/all/paks/Tools/System Report/pak.json b/workspace/all/paks/Tools/System Report/pak.json index 67d724ec..8667f0e3 100644 --- a/workspace/all/paks/Tools/System Report/pak.json +++ b/workspace/all/paks/Tools/System Report/pak.json @@ -13,7 +13,6 @@ "tg5040", "zero28", "rgb30", - "rk3566", "m17", "my282", "magicmini" diff --git a/workspace/all/paks/config/platforms.json b/workspace/all/paks/config/platforms.json index cad1c7d6..6e514c66 100644 --- a/workspace/all/paks/config/platforms.json +++ b/workspace/all/paks/config/platforms.json @@ -50,14 +50,7 @@ "nice_prefix": "" }, "rgb30": { - "description": "Powkiddy RGB30", - "arch": "arm64", - "sdcard_path": "/storage/roms", - "shutdown_cmd": "shutdown", - "nice_prefix": "" - }, - "rk3566": { - "description": "Rockchip RK3566 devices (LessOS)", + "description": "Powkiddy RGB30 (LessOS)", "arch": "arm64", "sdcard_path": "/storage", "shutdown_cmd": "poweroff", diff --git a/workspace/rgb30/Makefile b/workspace/rgb30/Makefile index 6b6cd31b..524b002c 100644 --- a/workspace/rgb30/Makefile +++ b/workspace/rgb30/Makefile @@ -10,33 +10,19 @@ endif ########################################################### -REQUIRES_COMMANDER = other/DinguxCommander -REQUIRES_SDLCOMPAT = other/sdl12-compat +# LessOS provides SDL2 natively - no sdl12-compat needed # keymon.elf is now built in workspace/all/utils +# LessOS doesn't need DinguxCommander (file manager for stock firmware) all: readmes show .PHONY: show show: @$(MAKE) -C show -early: $(REQUIRES_COMMANDER) $(REQUIRES_SDLCOMPAT)/build - @cd $(REQUIRES_COMMANDER) && $(MAKE) -s - @cd $(REQUIRES_SDLCOMPAT) && cmake --build build >/dev/null +# No early dependencies for rgb30 +early: clean: - @cd $(REQUIRES_COMMANDER) && $(MAKE) -s clean - @cd $(REQUIRES_SDLCOMPAT) && rm -rf build - -########################################################### - -$(REQUIRES_COMMANDER): - git clone --depth 1 --branch minui-rgb30 https://github.com/shauninman/DinguxCommander.git $(REQUIRES_COMMANDER) - -$(REQUIRES_SDLCOMPAT): - git clone --depth 1 --branch minui-rgb30 https://github.com/shauninman/sdl12-compat.git $(REQUIRES_SDLCOMPAT) - -$(REQUIRES_SDLCOMPAT)/build: $(REQUIRES_SDLCOMPAT) - cd $(REQUIRES_SDLCOMPAT) && cmake --toolchain ./toolchain.cmake -Bbuild -DCMAKE_BUILD_TYPE=Release . include ../all/readmes/Makefile \ No newline at end of file diff --git a/workspace/rgb30/README.md b/workspace/rgb30/README.md index e5343c0a..468877bd 100644 --- a/workspace/rgb30/README.md +++ b/workspace/rgb30/README.md @@ -1,6 +1,9 @@ -# Anbernic RGB30 +# RGB30 Platform -Platform implementation for the Anbernic RGB30 retro handheld device. +Platform implementation for the PowKiddy RGB30 handheld (LessOS). + +## Device +- **PowKiddy RGB30** - Rockchip RK3566 (Cortex-A55), 720x720 display ## Hardware Specifications @@ -41,11 +44,11 @@ Platform implementation for the Anbernic RGB30 retro handheld device. - **Brightness Range**: 0-10 (raw: 0-255) ### Storage -- SD card mounted at `/storage/roms` +- SD card mounted at `/storage` (LessOS) ## Platform Architecture -The RGB30 uses a **hybrid input system** that combines: +RGB30 use 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 @@ -66,15 +69,12 @@ rgb30/ ├── 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: launcher-rgb30) - └── sdl12-compat/ SDL 1.2 compatibility layer (branch: launcher-rgb30) +└── cores/ Libretro cores (submodules + builds) ``` ## Input System -The RGB30 uses a **joystick-first input architecture**: +RGB30 use 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) @@ -120,7 +120,7 @@ Audio and video routing automatically switches when headphones or HDMI are conne ## Building ### Prerequisites -Requires Docker with RGB30 cross-compilation toolchain. +Requires Docker with rgb30 cross-compilation toolchain. ### Build Commands @@ -132,23 +132,10 @@ make PLATFORM=rgb30 shell cd /root/workspace/rgb30 make -# This builds (in early target): -# - DinguxCommander (file manager) -# - sdl12-compat (SDL 1.2 compatibility layer) -# -# And (in all target): +# This builds: # - 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: `launcher-rgb30`) -- **sdl12-compat**: `github.com/shauninman/sdl12-compat.git` (branch: `launcher-rgb30`) - -Both dependencies use custom toolchain configurations for the RGB30 hardware. - ## Installation ### File System Layout @@ -156,9 +143,11 @@ Both dependencies use custom toolchain configurations for the RGB30 hardware. LessUI installs to the SD card with the following structure: ``` -/storage/roms/ +/storage/ +├── lessos/ LessOS bootstrap +│ └── init.sh Entry point ├── .system/ -│ ├── rgb30/ Platform-specific binaries +│ ├── rgb30/ Platform-specific binaries │ │ ├── bin/ Utilities (keymon, show, etc.) │ │ └── paks/ Applications and emulators │ │ └── LessUI.pak/ Main launcher @@ -166,7 +155,7 @@ LessUI installs to the SD card with the following structure: │ ├── assets@2x.png UI sprite sheet (2x scale) │ └── InterTight-Bold.ttf ├── .userdata/ User settings and save data -│ └── rgb30/ Platform-specific settings +│ └── rgb30/ Platform-specific settings │ └── msettings.bin Volume/brightness preferences ├── Roms/ ROM files organized by system └── LessUI.7z Update package (if present) @@ -174,7 +163,7 @@ LessUI installs to the SD card with the following structure: ### Settings Management -The RGB30 uses shared memory for settings synchronization between processes: +RGB30 use shared memory for settings synchronization between processes: **Settings Stored**: - Brightness level (0-10) @@ -273,15 +262,6 @@ The RGB30 platform includes these libretro cores: | **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 LessUI launcher - ## Known Issues / Quirks ### Hardware Quirks @@ -292,7 +272,7 @@ DinguxCommander-based file manager (custom RGB30 build): 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 +1. **SDL2**: Platform uses SDL2 natively (LessOS provides SDL2) 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) diff --git a/workspace/rk3566/install/boot.sh b/workspace/rgb30/install/boot.sh similarity index 97% rename from workspace/rk3566/install/boot.sh rename to workspace/rgb30/install/boot.sh index 15adc2b8..a4fc0eb1 100755 --- a/workspace/rk3566/install/boot.sh +++ b/workspace/rgb30/install/boot.sh @@ -1,7 +1,7 @@ #!/bin/sh -# NOTE: becomes .tmp_update/rk3566.sh +# NOTE: becomes .tmp_update/rgb30.sh -PLATFORM="rk3566" +PLATFORM="rgb30" # Use LessOS storage path if set, otherwise default SDCARD_PATH="${LESSOS_STORAGE:-/storage}" UPDATE_PATH="$SDCARD_PATH/LessUI.7z" diff --git a/workspace/rgb30/platform/Makefile.copy b/workspace/rgb30/platform/Makefile.copy index 812731e9..76da13e3 100644 --- a/workspace/rgb30/platform/Makefile.copy +++ b/workspace/rgb30/platform/Makefile.copy @@ -1,5 +1,13 @@ $(PLATFORM): # $@ + cp ./workspace/$@/keymon/keymon.elf ./build/SYSTEM/$@/bin/ # show.elf (platform-specific build) cp ./workspace/$@/show/show.elf ./build/SYSTEM/$@/bin/ - rsync -a ./workspace/$@/other/sdl12-compat/build/libSDL-1.2.so.1.2.69 ./build/SYSTEM/$@/lib/libSDL-1.2.so.0 \ No newline at end of file + # LessOS provides SDL2 natively - no sdl12-compat needed + # installer + rsync -a ./workspace/$@/install/boot.sh ./build/BOOT/common/$@.sh + mkdir -p ./build/BOOT/common/$@/ + cp ./workspace/$@/show/show.elf ./build/BOOT/common/$@/ + # boot assets + rsync -a ./skeleton/SYSTEM/res/installing@3x.png ./build/BOOT/common/$@/installing.png + rsync -a ./skeleton/SYSTEM/res/updating@3x.png ./build/BOOT/common/$@/updating.png \ No newline at end of file diff --git a/workspace/rgb30/platform/Makefile.env b/workspace/rgb30/platform/Makefile.env index b5d3e2b3..70ba8f64 100644 --- a/workspace/rgb30/platform/Makefile.env +++ b/workspace/rgb30/platform/Makefile.env @@ -1,4 +1,4 @@ -# rgb30 +# rgb30 - LessOS toolchain ARCH = -mtune=cortex-a55 -march=armv8.2-a -O3 -LIBS = -flto -lrga +LIBS = -flto -lrga -ldrm -lstdc++ -lasound -lfreetype -ljpeg -lpng16 -lbz2 SDL = SDL2 \ No newline at end of file diff --git a/workspace/rgb30/platform/platform.c b/workspace/rgb30/platform/platform.c index 8203f6fc..d05a2dcf 100644 --- a/workspace/rgb30/platform/platform.c +++ b/workspace/rgb30/platform/platform.c @@ -1,19 +1,22 @@ /** - * platform.c - Powkiddy RGB30 platform implementation + * platform.c - PowKiddy RGB30 platform implementation * * REFACTORED VERSION - Uses shared render_sdl2 backend * - * Platform-specific code for the Powkiddy RGB30 handheld device. + * Platform-specific code for PowKiddy RGB30 handheld. + * Device: PowKiddy RGB30 (Rockchip RK3566, Cortex-A55) + * OS: LessOS (ROCKNIX-based) + * * Key features: + * - 720x720 square display * - Dual analog sticks with swapped right stick axes (X/Y reversed) * - WiFi support with status monitoring * - Grid and line visual effects for retro aesthetics - * - Rotation support for display output - * - Dynamic device model detection from device tree + * - HDMI output with rotation support + * - Uses rocknix-singleadc-joypad kernel driver * - Overscan support (PLAT_supportsOverscan returns 1) * - * The RGB30 uses the Rockchip RK3566 SoC with 720x720 display. - * Input events are read directly from /dev/input/event* devices. + * Input is read directly from /dev/input/event* devices via evdev. */ #include @@ -33,6 +36,7 @@ #include "platform.h" #include "utils.h" +#include "gl_video.h" #include "render_sdl2.h" #include "scaler.h" @@ -80,11 +84,13 @@ void PLAT_setSharpness(int sharpness) { } void PLAT_setEffect(int effect) { - SDL2_setEffect(&vid_ctx, effect); + // Only GL path is used on GLES platforms (SDL2 effect state is unused) + GLVideo_setEffect(effect); } void PLAT_setEffectColor(int color) { - SDL2_setEffectColor(&vid_ctx, color); + // Only GL path is used on GLES platforms (SDL2 effect state is unused) + GLVideo_setEffectColor(color); } void PLAT_vsync(int remaining) { @@ -99,6 +105,14 @@ void PLAT_present(GFX_Renderer* renderer) { SDL2_present(&vid_ctx, renderer); } +SDL_Window* PLAT_getWindow(void) { + return SDL2_getWindow(&vid_ctx); +} + +int PLAT_getRotation(void) { + return SDL2_getRotation(&vid_ctx); +} + int PLAT_supportsOverscan(void) { return 1; } diff --git a/workspace/rgb30/platform/platform.h b/workspace/rgb30/platform/platform.h index a2ce5587..b909b60f 100644 --- a/workspace/rgb30/platform/platform.h +++ b/workspace/rgb30/platform/platform.h @@ -1,19 +1,18 @@ /** * rgb30/platform/platform.h - Platform definitions for PowKiddy RGB30 * - * Supported devices (Rockchip RK3566, Cortex-A55): - * - PowKiddy RGB30: 4.0" 720x720 display + * Device: PowKiddy RGB30 (Rockchip RK3566, Cortex-A55) + * OS: LessOS (ROCKNIX-based) * * Hardware features: * - 720x720 square display (1:1 aspect ratio) * - 1280x720 HDMI output support * - D-pad and face buttons (A/B/X/Y) * - Shoulder buttons (L1/R1/L2/R2) - * - Menu buttons (primary and alternate) - * - Uses hybrid input (minimal SDL keyboard + joystick) - * - Larger UI with increased row count and padding + * - Dual analog sticks with L3/R3 clicks + * - Uses rocknix-singleadc-joypad kernel driver * - * @note Power button uses SDL keyboard mapping, volume controls use evdev codes + * @note Input handled via LessOS's standardized joypad driver */ #ifndef PLATFORM_H @@ -25,6 +24,12 @@ #define PLATFORM "rgb30" +/////////////////////////////// +// Hardware Capabilities +/////////////////////////////// + +#define HAS_OPENGLES 1 // Mali-G52 GPU supports OpenGL ES 2.0 + /////////////////////////////// // Audio Configuration /////////////////////////////// @@ -182,7 +187,8 @@ // Platform-Specific Paths and Settings /////////////////////////////// -#define SDCARD_PATH "/storage/roms" // Path to SD card mount point +#define SDCARD_PATH \ + "/storage" // Path to SD card mount point (LessOS default, overridden by LESSOS_STORAGE) #define MUTE_VOLUME_RAW 0 // Raw value for muted volume /////////////////////////////// diff --git a/workspace/rgb30/show/Makefile b/workspace/rgb30/show/Makefile index ce34deef..03195e74 100755 --- a/workspace/rgb30/show/Makefile +++ b/workspace/rgb30/show/Makefile @@ -6,7 +6,7 @@ TARGET = show PRODUCT = $(TARGET).elf CC = $(CROSS_COMPILE)gcc -FLAGS = -Os -lSDL2 -lSDL2_image -lrt -ldl -Wl,--gc-sections -s +FLAGS = -Os $(CFLAGS) $(LDFLAGS) -lSDL2 -lSDL2_image -lrt -ldl -Wl,--gc-sections -s all: $(CC) $(TARGET).c -o $(PRODUCT) $(FLAGS) diff --git a/workspace/rgb30/show/show.c b/workspace/rgb30/show/show.c index 0f512752..debbecd8 100644 --- a/workspace/rgb30/show/show.c +++ b/workspace/rgb30/show/show.c @@ -9,36 +9,75 @@ SDL_Window* window; SDL_Surface* screen; -int main(int argc , char* argv[]) { - if (argc<2) { - puts("Usage: show.elf image.png delay"); - return 0; +int main(int argc, char* argv[]) { + if (argc < 2) { + fprintf(stderr, "Usage: show.elf image.png [delay]\n"); + return 1; } - + char path[256]; snprintf(path, sizeof(path), "%s", argv[1]); - if (access(path, F_OK)!=0) return 0; // nothing to show :( - - int delay = argc>2 ? atoi(argv[2]) : 2; - - SDL_Init(SDL_INIT_VIDEO); + if (access(path, F_OK) != 0) { + fprintf(stderr, "show.elf: Image not found: %s\n", path); + return 1; + } + + int delay = argc > 2 ? atoi(argv[2]) : 2; + + fprintf(stderr, "show.elf: Initializing SDL2...\n"); + if (SDL_Init(SDL_INIT_VIDEO) < 0) { + fprintf(stderr, "show.elf: SDL_Init failed: %s\n", SDL_GetError()); + return 1; + } + SDL_ShowCursor(0); - - int w = 720; - int h = 720; - window = SDL_CreateWindow("", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, w,h, SDL_WINDOW_SHOWN); - - screen = SDL_GetWindowSurface(window); + + // Use 0,0 to let SDL auto-detect display size (like tg5040) + fprintf(stderr, "show.elf: Creating window...\n"); + window = SDL_CreateWindow("", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 0, 0, SDL_WINDOW_SHOWN); + if (!window) { + fprintf(stderr, "show.elf: SDL_CreateWindow failed: %s\n", SDL_GetError()); + SDL_Quit(); + return 1; + } + + screen = SDL_GetWindowSurface(window); + if (!screen) { + fprintf(stderr, "show.elf: SDL_GetWindowSurface failed: %s\n", SDL_GetError()); + SDL_DestroyWindow(window); + SDL_Quit(); + return 1; + } + + fprintf(stderr, "show.elf: Window size: %dx%d\n", screen->w, screen->h); SDL_FillRect(screen, NULL, 0); - - SDL_Surface* img = IMG_Load(path); - SDL_BlitSurface(img, NULL, screen, &(SDL_Rect){(screen->w-img->w)/2,(screen->h-img->h)/2}); - - SDL_UpdateWindowSurface(window); + + fprintf(stderr, "show.elf: Loading image: %s\n", path); + SDL_Surface* img = IMG_Load(path); + if (!img) { + fprintf(stderr, "show.elf: IMG_Load failed: %s\n", IMG_GetError()); + SDL_DestroyWindow(window); + SDL_Quit(); + return 1; + } + + fprintf(stderr, "show.elf: Image size: %dx%d\n", img->w, img->h); + + // Center the image on screen + SDL_Rect dst = {(screen->w - img->w) / 2, (screen->h - img->h) / 2, img->w, img->h}; + SDL_BlitSurface(img, NULL, screen, &dst); + + if (SDL_UpdateWindowSurface(window) < 0) { + fprintf(stderr, "show.elf: SDL_UpdateWindowSurface failed: %s\n", SDL_GetError()); + } + + fprintf(stderr, "show.elf: Displaying for %d seconds...\n", delay); sleep(delay); - + SDL_FreeSurface(img); SDL_DestroyWindow(window); SDL_Quit(); + + fprintf(stderr, "show.elf: Done\n"); return 0; } diff --git a/workspace/rk3566/Makefile b/workspace/rk3566/Makefile deleted file mode 100644 index 9274d056..00000000 --- a/workspace/rk3566/Makefile +++ /dev/null @@ -1,28 +0,0 @@ -########################################################### - -ifeq (,$(PLATFORM)) -PLATFORM = $(UNION_PLATFORM) -endif - -ifeq (,$(PLATFORM)) -$(error please specify PLATFORM, eg. PLATFORM=rk3566 make) -endif - -########################################################### - -# LessOS provides SDL2 natively - no sdl12-compat needed - -# keymon.elf is now built in workspace/all/utils -# LessOS doesn't need DinguxCommander (file manager for stock firmware) -all: readmes show - -.PHONY: show -show: - @$(MAKE) -C show - -# No early dependencies for rk3566 -early: - -clean: - -include ../all/readmes/Makefile \ No newline at end of file diff --git a/workspace/rk3566/README.md b/workspace/rk3566/README.md deleted file mode 100644 index fbadd354..00000000 --- a/workspace/rk3566/README.md +++ /dev/null @@ -1,330 +0,0 @@ -# Rockchip RK3566 Platform - -Platform implementation for Rockchip RK3566-based retro handheld devices (LessOS). - -## Supported Devices -- PowKiddy RGB30 -- Anbernic RG353P/M/V/VS (future) - -## 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**: Evdev input events (direct reading from `/dev/input/event*`) -- **Implementation**: Reads raw `input_event` structures for all input -- **Notable**: Bypasses SDL input APIs entirely - -### 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` (LessOS) - -## Platform Architecture - -RK3566 devices use 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 - -``` -RK3566/ -├── 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) -``` - -## Input System - -RK3566 devices use 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 RK3566 cross-compilation toolchain. - -### Build Commands - -```bash -# Enter platform build environment -make PLATFORM=rk3566 shell - -# Inside container: build all platform components -cd /root/workspace/rk3566 -make - -# This builds: -# - show.elf (boot splash display) -``` - -## Installation - -### File System Layout - -LessUI installs to the SD card with the following structure: - -``` -/storage/ -├── lessos/ LessOS bootstrap -│ └── init.sh Entry point -├── .system/ -│ ├── RK3566/ Platform-specific binaries -│ │ ├── bin/ Utilities (keymon, show, etc.) -│ │ └── paks/ Applications and emulators -│ │ └── LessUI.pak/ Main launcher -│ └── res/ Shared UI assets -│ ├── assets@2x.png UI sprite sheet (2x scale) -│ └── InterTight-Bold.ttf -├── .userdata/ User settings and save data -│ └── RK3566/ Platform-specific settings -│ └── msettings.bin Volume/brightness preferences -├── Roms/ ROM files organized by system -└── LessUI.7z Update package (if present) -``` - -### Settings Management - -RK3566 devices use 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 RK3566 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 | - -## 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 natively (LessOS provides SDL2) -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/launcher/launcher.c` (launcher), `../../all/player/player.c` (libretro frontend) -- Build system: `../../Makefile` (host), `./makefile` (platform) -- Platform header: `./platform/platform.h` (all hardware definitions) - -## Maintainer Notes - -This platform demonstrates several advanced LessUI features: - -**Unique Characteristics**: -- Square display (720x720) - unique aspect ratio among LessUI 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/rk3566/libmsettings/Makefile b/workspace/rk3566/libmsettings/Makefile deleted file mode 100644 index bc879d7b..00000000 --- a/workspace/rk3566/libmsettings/Makefile +++ /dev/null @@ -1,32 +0,0 @@ -ifeq (,$(CROSS_COMPILE)) -$(error missing CROSS_COMPILE for this toolchain) -endif -ifeq (,$(PREFIX)) -$(error missing PREFIX for this toolchain) -endif - -TARGET = msettings - -.PHONY: build -.PHONY: clean - -CC = $(CROSS_COMPILE)gcc - -SYSROOT := $(shell $(CC) --print-sysroot) - -INCLUDEDIR = $(SYSROOT)/usr/include -# OPT_FLAGS from parent makefile (-O3 for release, -O0 -g for debug) -OPT_FLAGS ?= -O3 -CFLAGS = -I$(INCLUDEDIR) $(OPT_FLAGS) -LDFLAGS = -ldl -lrt -s - -build: - @$(CC) -c -Werror -fpic "$(TARGET).c" -Wl,--no-as-needed $(CFLAGS) - @$(CC) -shared -o "lib$(TARGET).so" "$(TARGET).o" $(LDFLAGS) - @cp "$(TARGET).h" "$(PREFIX)/include" - @cp "lib$(TARGET).so" "$(PREFIX)/lib" -clean: - rm -f *.o - rm -f "lib$(TARGET).so" - rm -f $(PREFIX)/include/$(TARGET).h - rm -f $(PREFIX)/lib/lib$(TARGET).so \ No newline at end of file diff --git a/workspace/rk3566/libmsettings/msettings.c b/workspace/rk3566/libmsettings/msettings.c deleted file mode 100644 index ab87f4b1..00000000 --- a/workspace/rk3566/libmsettings/msettings.c +++ /dev/null @@ -1,203 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "msettings.h" - -/////////////////////////////////////// - -#define SETTINGS_VERSION 2 -typedef struct Settings { - int version; // future proofing - int brightness; - int headphones; - int speaker; - int unused[2]; // for future use - // NOTE: doesn't really need to be persisted but still needs to be shared - int jack; - int hdmi; -} Settings; -static Settings DefaultSettings = { - .version = SETTINGS_VERSION, - .brightness = 2, - .headphones = 4, - .speaker = 8, - .jack = 0, - .hdmi = 0, -}; -static Settings* settings; - -#define SHM_KEY "/SharedSettings" -static char SettingsPath[256]; -static int shm_fd = -1; -static int is_host = 0; -static int shm_size = sizeof(Settings); - -#define BACKLIGHT_PATH "/sys/class/backlight/backlight/bl_power" -#define BRIGHTNESS_PATH "/sys/class/backlight/backlight/brightness" -#define JACK_STATE_PATH "/sys/bus/platform/devices/singleadc-joypad/hp" -#define HDMI_STATE_PATH "/sys/class/extcon/hdmi/cable.0/state" - -int getInt(char* path) { - int i = 0; - FILE *file = fopen(path, "r"); - if (file!=NULL) { - fscanf(file, "%i", &i); - fclose(file); - } - return i; -} - - -void InitSettings(void) { - sprintf(SettingsPath, "%s/msettings.bin", getenv("USERDATA_PATH")); - - shm_fd = shm_open(SHM_KEY, O_RDWR | O_CREAT | O_EXCL, 0644); // see if it exists - if (shm_fd==-1 && errno==EEXIST) { // already exists - puts("Settings client"); - shm_fd = shm_open(SHM_KEY, O_RDWR, 0644); - settings = mmap(NULL, shm_size, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0); - } - else { // host - puts("Settings host"); // should always be keymon - is_host = 1; - // we created it so set initial size and populate - ftruncate(shm_fd, shm_size); - settings = mmap(NULL, shm_size, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0); - - int fd = open(SettingsPath, O_RDONLY); - if (fd>=0) { - read(fd, settings, shm_size); - // TODO: use settings->version for future proofing? - close(fd); - } - else { - // load defaults - memcpy(settings, &DefaultSettings, shm_size); - } - - // these shouldn't be persisted - // settings->jack = 0; - // settings->hdmi = 0; - } - - int jack = getInt(JACK_STATE_PATH); - int hdmi = getInt(HDMI_STATE_PATH); - printf("brightness: %i (hdmi: %i)\nspeaker: %i (jack: %i)\n", settings->brightness, hdmi, settings->speaker, jack); fflush(stdout); - - // both of these set volume - SetJack(jack); - SetHDMI(hdmi); - - SetBrightness(GetBrightness()); - // system("echo $(< " BRIGHTNESS_PATH ")"); -} -void QuitSettings(void) { - munmap(settings, shm_size); - if (is_host) shm_unlink(SHM_KEY); -} -static inline void SaveSettings(void) { - int fd = open(SettingsPath, O_CREAT|O_WRONLY, 0644); - if (fd>=0) { - write(fd, settings, shm_size); - close(fd); - sync(); - } -} - -int GetBrightness(void) { // 0-10 - return settings->brightness; -} -void SetBrightness(int value) { - if (settings->hdmi) return; - - int raw; - switch (value) { - // TODO: redo, range is 0-255 - case 0: raw=4; break; // 0 - case 1: raw=6; break; // 2 - case 2: raw=10; break; // 4 - case 3: raw=16; break; // 6 - case 4: raw=32; break; // 16 - case 5: raw=48; break; // 16 - case 6: raw=64; break; // 16 - case 7: raw=96; break; // 32 - case 8: raw=128; break; // 32 - case 9: raw=192; break; // 64 - case 10: raw=255; break; // 64 - } - SetRawBrightness(raw); - settings->brightness = value; - SaveSettings(); -} - -int GetVolume(void) { // 0-20 - return settings->jack ? settings->headphones : settings->speaker; -} -void SetVolume(int value) { - if (settings->hdmi) return; - - if (settings->jack) settings->headphones = value; - else settings->speaker = value; - - int raw = value * 5; - SetRawVolume(raw); - SaveSettings(); -} - -void SetRawBrightness(int val) { // 0 - 255 - if (settings->hdmi) return; - - // printf("SetRawBrightness(%i)\n", val); fflush(stdout); - int fd = open(BRIGHTNESS_PATH, O_WRONLY); - if (fd>=0) { - dprintf(fd,"%d",val); - close(fd); - } -} -void SetRawVolume(int val) { // 0 - 100 - // printf("SetRawVolume(%i)\n", val); fflush(stdout); - char cmd[256]; - sprintf(cmd, "amixer sset -M 'Master' %i%% &> /dev/null", val); - // puts(cmd); fflush(stdout); - system(cmd); -} - -// monitored and set by thread in keymon -int GetJack(void) { - return settings->jack; -} -void SetJack(int value) { - // printf("SetJack(%i)\n", value); fflush(stdout); - - char cmd[256]; - sprintf(cmd, "amixer cset name='Playback Path' '%s' &> /dev/null", value?"HP":"SPK"); - system(cmd); - - settings->jack = value; - SetVolume(GetVolume()); -} - -int GetHDMI(void) { - // printf("GetHDMI() %i\n", settings->hdmi); fflush(stdout); - return settings->hdmi; -} -void SetHDMI(int value) { - // printf("SetHDMI(%i)\n", value); fflush(stdout); - - // if (settings->hdmi!=value) system("/usr/lib/autostart/common/055-hdmi-check"); - - settings->hdmi = value; - if (value) SetRawVolume(100); // max - else SetVolume(GetVolume()); // restore -} - -int GetMute(void) { return 0; } -void SetMute(int value) { } \ No newline at end of file diff --git a/workspace/rk3566/libmsettings/msettings.h b/workspace/rk3566/libmsettings/msettings.h deleted file mode 100644 index 47e5fb00..00000000 --- a/workspace/rk3566/libmsettings/msettings.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef __msettings_h__ -#define __msettings_h__ - -void InitSettings(void); -void QuitSettings(void); - -int GetBrightness(void); -int GetVolume(void); - -void SetRawBrightness(int value); // 0-1024 -void SetRawVolume(int value); // 0-40 - -void SetBrightness(int value); // 0-10 -void SetVolume(int value); // 0-20 - -int GetJack(void); -void SetJack(int value); // 0-1 - -int GetHDMI(void); -void SetHDMI(int value); // 0-1 - -int GetMute(void); -void SetMute(int value); // 0-1 - -#endif // __msettings_h__ diff --git a/workspace/rk3566/other/.keep b/workspace/rk3566/other/.keep deleted file mode 100644 index e69de29b..00000000 diff --git a/workspace/rk3566/platform/Makefile.copy b/workspace/rk3566/platform/Makefile.copy deleted file mode 100644 index 76da13e3..00000000 --- a/workspace/rk3566/platform/Makefile.copy +++ /dev/null @@ -1,13 +0,0 @@ -$(PLATFORM): - # $@ - cp ./workspace/$@/keymon/keymon.elf ./build/SYSTEM/$@/bin/ - # show.elf (platform-specific build) - cp ./workspace/$@/show/show.elf ./build/SYSTEM/$@/bin/ - # LessOS provides SDL2 natively - no sdl12-compat needed - # installer - rsync -a ./workspace/$@/install/boot.sh ./build/BOOT/common/$@.sh - mkdir -p ./build/BOOT/common/$@/ - cp ./workspace/$@/show/show.elf ./build/BOOT/common/$@/ - # boot assets - rsync -a ./skeleton/SYSTEM/res/installing@3x.png ./build/BOOT/common/$@/installing.png - rsync -a ./skeleton/SYSTEM/res/updating@3x.png ./build/BOOT/common/$@/updating.png \ No newline at end of file diff --git a/workspace/rk3566/platform/Makefile.env b/workspace/rk3566/platform/Makefile.env deleted file mode 100644 index 32bd0932..00000000 --- a/workspace/rk3566/platform/Makefile.env +++ /dev/null @@ -1,4 +0,0 @@ -# rk3566 - LessOS toolchain -ARCH = -mtune=cortex-a55 -march=armv8.2-a -O3 -LIBS = -flto -lrga -ldrm -lstdc++ -lasound -lfreetype -ljpeg -lpng16 -lbz2 -SDL = SDL2 \ No newline at end of file diff --git a/workspace/rk3566/platform/platform.c b/workspace/rk3566/platform/platform.c deleted file mode 100644 index 435b454f..00000000 --- a/workspace/rk3566/platform/platform.c +++ /dev/null @@ -1,406 +0,0 @@ -/** - * platform.c - Rockchip RK3566 platform implementation - * - * REFACTORED VERSION - Uses shared render_sdl2 backend - * - * Platform-specific code for Rockchip RK3566-based handheld devices. - * Supported devices: PowKiddy RGB30, Anbernic RG353P/M/V/VS - * - * Key features: - * - Dual analog sticks with swapped right stick axes (X/Y reversed) - * - WiFi support with status monitoring - * - Grid and line visual effects for retro aesthetics - * - Rotation support for display output - * - Dynamic device model detection from device tree - * - Overscan support (PLAT_supportsOverscan returns 1) - * - * RK3566 devices use 720x720 displays and read input events directly - * from /dev/input/event* devices. - */ - -#include -#include -#include -#include -#include - -#include -#include -#include - -#include - -#include "api.h" -#include "defines.h" -#include "platform.h" -#include "utils.h" - -#include "gl_video.h" -#include "render_sdl2.h" -#include "scaler.h" - -/////////////////////////////// -// Video - Using shared SDL2 backend -/////////////////////////////// - -static SDL2_RenderContext vid_ctx; - -static const SDL2_Config vid_config = { - // No rotation needed (square 720x720 display) - .auto_rotate = 0, - .rotate_cw = 0, - .rotate_null_center = 0, - // Display features - .has_hdmi = 1, - .default_sharpness = SHARPNESS_SOFT, -}; - -SDL_Surface* PLAT_initVideo(void) { - return SDL2_initVideo(&vid_ctx, FIXED_WIDTH, FIXED_HEIGHT, &vid_config); -} - -void PLAT_quitVideo(void) { - SDL2_quitVideo(&vid_ctx); -} - -void PLAT_clearVideo(SDL_Surface* screen) { - SDL2_clearVideo(&vid_ctx); -} - -void PLAT_clearAll(void) { - SDL2_clearAll(&vid_ctx); -} - -SDL_Surface* PLAT_resizeVideo(int w, int h, int p) { - return SDL2_resizeVideo(&vid_ctx, w, h, p); -} - -void PLAT_setVideoScaleClip(int x, int y, int width, int height) {} -void PLAT_setNearestNeighbor(int enabled) {} - -void PLAT_setSharpness(int sharpness) { - SDL2_setSharpness(&vid_ctx, sharpness); -} - -void PLAT_setEffect(int effect) { - // Only GL path is used on GLES platforms (SDL2 effect state is unused) - GLVideo_setEffect(effect); -} - -void PLAT_setEffectColor(int color) { - // Only GL path is used on GLES platforms (SDL2 effect state is unused) - GLVideo_setEffectColor(color); -} - -void PLAT_vsync(int remaining) { - SDL2_vsync(remaining); -} - -scaler_t PLAT_getScaler(GFX_Renderer* renderer) { - return SDL2_getScaler(&vid_ctx, renderer); -} - -void PLAT_present(GFX_Renderer* renderer) { - SDL2_present(&vid_ctx, renderer); -} - -SDL_Window* PLAT_getWindow(void) { - return SDL2_getWindow(&vid_ctx); -} - -int PLAT_getRotation(void) { - return SDL2_getRotation(&vid_ctx); -} - -int PLAT_supportsOverscan(void) { - return 1; -} - -/////////////////////////////// -// Input Handling -/////////////////////////////// - -#define RAW_UP 544 -#define RAW_DOWN 545 -#define RAW_LEFT 546 -#define RAW_RIGHT 547 -#define RAW_A 305 -#define RAW_B 304 -#define RAW_X 307 -#define RAW_Y 308 -#define RAW_START 315 -#define RAW_SELECT 314 -#define RAW_MENU 139 -#define RAW_L1 310 -#define RAW_L2 312 -#define RAW_L3 317 -#define RAW_R1 311 -#define RAW_R2 313 -#define RAW_R3 318 -#define RAW_PLUS 115 -#define RAW_MINUS 114 -#define RAW_POWER 116 -#define RAW_HATY 17 -#define RAW_HATX 16 -#define RAW_LSY 1 -#define RAW_LSX 0 -#define RAW_RSY 3 -#define RAW_RSX 4 - -#define RAW_MENU1 RAW_L3 -#define RAW_MENU2 RAW_R3 - -#define INPUT_COUNT 4 -static int inputs[INPUT_COUNT]; - -void PLAT_initInput(void) { - inputs[0] = open("/dev/input/event0", O_RDONLY | O_NONBLOCK | O_CLOEXEC); - inputs[1] = open("/dev/input/event1", O_RDONLY | O_NONBLOCK | O_CLOEXEC); - inputs[2] = open("/dev/input/event2", O_RDONLY | O_NONBLOCK | O_CLOEXEC); - inputs[3] = open("/dev/input/event3", O_RDONLY | O_NONBLOCK | O_CLOEXEC); - - for (int i = 0; i < INPUT_COUNT; i++) { - if (inputs[i] < 0) - LOG_warn("Failed to open /dev/input/event%d\n", i); - } -} - -void PLAT_quitInput(void) { - for (int i = 0; i < INPUT_COUNT; i++) { - close(inputs[i]); - } -} - -struct input_event { - struct timeval time; - __u16 type; - __u16 code; - __s32 value; -}; -#define EV_KEY 0x01 -#define EV_ABS 0x03 - -void PLAT_pollInput(void) { - uint32_t tick = SDL_GetTicks(); - PAD_beginPolling(); - PAD_handleRepeat(tick); - - int input; - static struct input_event event; - for (int i = 0; i < INPUT_COUNT; i++) { - input = inputs[i]; - while (read(input, &event, sizeof(event)) == sizeof(event)) { - if (event.type != EV_KEY && event.type != EV_ABS) - continue; - - int btn = BTN_NONE; - int pressed = 0; - int type = event.type; - int code = event.code; - int value = event.value; - - if (type == EV_KEY) { - if (value > 1) - continue; - pressed = value; - if (code == RAW_UP) { - btn = BTN_DPAD_UP; - } else if (code == RAW_DOWN) { - btn = BTN_DPAD_DOWN; - } else if (code == RAW_LEFT) { - btn = BTN_DPAD_LEFT; - } else if (code == RAW_RIGHT) { - btn = BTN_DPAD_RIGHT; - } else if (code == RAW_A) { - btn = BTN_A; - } else if (code == RAW_B) { - btn = BTN_B; - } else if (code == RAW_X) { - btn = BTN_X; - } else if (code == RAW_Y) { - btn = BTN_Y; - } else if (code == RAW_START) { - btn = BTN_START; - } else if (code == RAW_SELECT) { - btn = BTN_SELECT; - } else if (code == RAW_MENU) { - btn = BTN_MENU; - } else if (code == RAW_MENU1) { - btn = BTN_MENU; - } else if (code == RAW_MENU2) { - btn = BTN_MENU; - } else if (code == RAW_L1) { - btn = BTN_L1; - } else if (code == RAW_L2) { - btn = BTN_L2; - } else if (code == RAW_L3) { - btn = BTN_L3; - } else if (code == RAW_R1) { - btn = BTN_R1; - } else if (code == RAW_R2) { - btn = BTN_R2; - } else if (code == RAW_R3) { - btn = BTN_R3; - } else if (code == RAW_PLUS) { - btn = BTN_PLUS; - } else if (code == RAW_MINUS) { - btn = BTN_MINUS; - } else if (code == RAW_POWER) { - btn = BTN_POWER; - } - } else if (type == EV_ABS) { - if (code == RAW_LSX) { - pad.laxis.x = (value * 32767) / 1800; - PAD_setAnalog(BTN_ID_ANALOG_LEFT, BTN_ID_ANALOG_RIGHT, pad.laxis.x, - tick + PAD_REPEAT_DELAY); - } else if (code == RAW_LSY) { - pad.laxis.y = (value * 32767) / 1800; - PAD_setAnalog(BTN_ID_ANALOG_UP, BTN_ID_ANALOG_DOWN, pad.laxis.y, - tick + PAD_REPEAT_DELAY); - // Right stick axes are swapped in hardware - } else if (code == RAW_RSX) { - pad.raxis.y = (value * 32767) / 1800; - } else if (code == RAW_RSY) { - pad.raxis.x = (value * 32767) / 1800; - } - btn = BTN_NONE; - } - - PAD_updateButton(btn, pressed, tick); - } - } -} - -int PLAT_shouldWake(void) { - int input; - static struct input_event event; - for (int i = 0; i < INPUT_COUNT; i++) { - input = inputs[i]; - while (read(input, &event, sizeof(event)) == sizeof(event)) { - if (event.type == EV_KEY && event.code == RAW_POWER && event.value == 0) - return 1; - } - } - return 0; -} - -/////////////////////////////// -// Power Management -/////////////////////////////// - -static int online = 0; - -void PLAT_getBatteryStatus(int* is_charging, int* charge) { - *is_charging = getInt("/sys/class/power_supply/ac/online"); - - int i = getInt("/sys/class/power_supply/battery/capacity"); - if (i > 80) - *charge = 100; - else if (i > 60) - *charge = 80; - else if (i > 40) - *charge = 60; - else if (i > 20) - *charge = 40; - else if (i > 10) - *charge = 20; - else - *charge = 10; - - char status[16]; - getFile("/sys/class/net/wlan0/operstate", status, 16); - online = prefixMatch("up", status); -} - -void PLAT_enableBacklight(int enable) { - putInt("/sys/class/backlight/backlight/bl_power", - enable ? FB_BLANK_UNBLANK : FB_BLANK_POWERDOWN); -} - -void PLAT_powerOff(void) { - sleep(2); - SetRawVolume(MUTE_VOLUME_RAW); - PLAT_enableBacklight(0); - SND_quit(); - VIB_quit(); - PWR_quit(); - GFX_quit(); - system("shutdown"); - while (1) - pause(); -} - -double PLAT_getDisplayHz(void) { - return SDL2_getDisplayHz(); -} - -uint32_t PLAT_measureVsyncInterval(void) { - return SDL2_measureVsyncInterval(&vid_ctx); -} - -#define GOVERNOR_PATH "/sys/devices/system/cpu/cpufreq/policy0/scaling_setspeed" - -void PLAT_setCPUSpeed(int speed) { - int freq = 0; - switch (speed) { - case CPU_SPEED_IDLE: - freq = 408000; // 20% of max (408 MHz) - break; - case CPU_SPEED_POWERSAVE: - freq = 1104000; // 55% of max (1104 MHz) - break; - case CPU_SPEED_NORMAL: - freq = 1608000; // 80% of max (1608 MHz) - break; - case CPU_SPEED_PERFORMANCE: - freq = 1992000; // 100% (1992 MHz) - break; - } - putInt(GOVERNOR_PATH, freq); -} - -/** - * Gets available CPU frequencies from sysfs. - * - * @param frequencies Output array to fill with frequencies (in kHz) - * @param max_count Maximum number of frequencies to return - * @return Number of frequencies found - */ -int PLAT_getAvailableCPUFrequencies(int* frequencies, int max_count) { - return PWR_getAvailableCPUFrequencies_sysfs(frequencies, max_count); -} - -/** - * Sets CPU frequency directly via sysfs. - * - * @param freq_khz Target frequency in kHz - * @return 0 on success, -1 on failure - */ -int PLAT_setCPUFrequency(int freq_khz) { - return PWR_setCPUFrequency_sysfs(freq_khz); -} - -void PLAT_setRumble(int strength) {} - -int PLAT_pickSampleRate(int requested, int max) { - return MIN(requested, max); -} - -static char model[256]; -char* PLAT_getModel(void) { - char buffer[256]; - getFile("/proc/device-tree/model", buffer, 256); - char* tmp = strrchr(buffer, ' '); - if (tmp) { - strncpy(model, tmp + 1, sizeof(model) - 1); - model[sizeof(model) - 1] = '\0'; - } else { - strncpy(model, "RGB30", sizeof(model) - 1); - model[sizeof(model) - 1] = '\0'; - } - return model; -} - -int PLAT_isOnline(void) { - return online; -} diff --git a/workspace/rk3566/platform/platform.h b/workspace/rk3566/platform/platform.h deleted file mode 100644 index 443c1403..00000000 --- a/workspace/rk3566/platform/platform.h +++ /dev/null @@ -1,222 +0,0 @@ -/** - * RK3566/platform/platform.h - Platform definitions for Rockchip RK3566 devices - * - * Supported devices (Rockchip RK3566, Cortex-A55): - * - PowKiddy RGB30: 4.0" 720x720 display - * - Anbernic RG353P/M/V/VS: Various display configurations - * - * Hardware features: - * - 720x720 square display (1:1 aspect ratio) - * - 1280x720 HDMI output support - * - D-pad and face buttons (A/B/X/Y) - * - Shoulder buttons (L1/R1/L2/R2) - * - Menu buttons (primary and alternate) - * - Uses hybrid input (minimal SDL keyboard + joystick) - * - Larger UI with increased row count and padding - * - * @note Power button uses SDL keyboard mapping, volume controls use evdev codes - */ - -#ifndef PLATFORM_H -#define PLATFORM_H - -/////////////////////////////// -// Platform Identification -/////////////////////////////// - -#define PLATFORM "rk3566" - -/////////////////////////////// -// Hardware Capabilities -/////////////////////////////// - -#define HAS_OPENGLES 1 // Mali-G52 GPU supports OpenGL ES 2.0 - -/////////////////////////////// -// Audio Configuration -/////////////////////////////// - -// Uses default SND_RATE_CONTROL_D (0.012f) for standard timing - -/////////////////////////////// -// Video Buffer Scaling -/////////////////////////////// - -// Uses default BUFFER_SCALE_FACTOR (1.0f) - GPU hardware scaler handles all scaling - -/////////////////////////////// -// UI Scaling -/////////////////////////////// - -// Uses default SCALE_MODIFIER (1.0f) and EDGE_PADDING (10) for standard layout - -/////////////////////////////// -// Dependencies -/////////////////////////////// - -#include "sdl.h" - -/////////////////////////////// -// Platform Variant Detection -/////////////////////////////// - -// No device variants (single hardware configuration) - -/////////////////////////////// -// SDL Keyboard Button Mappings -// RK3566 devices use minimal SDL keyboard input (power button only) -/////////////////////////////// - -#define BUTTON_UP BUTTON_NA -#define BUTTON_DOWN BUTTON_NA -#define BUTTON_LEFT BUTTON_NA -#define BUTTON_RIGHT BUTTON_NA - -#define BUTTON_SELECT BUTTON_NA -#define BUTTON_START BUTTON_NA - -#define BUTTON_A BUTTON_NA -#define BUTTON_B BUTTON_NA -#define BUTTON_X BUTTON_NA -#define BUTTON_Y BUTTON_NA - -#define BUTTON_L1 BUTTON_NA -#define BUTTON_R1 BUTTON_NA -#define BUTTON_L2 BUTTON_NA -#define BUTTON_R2 BUTTON_NA -#define BUTTON_L3 BUTTON_NA -#define BUTTON_R3 BUTTON_NA - -#define BUTTON_MENU BUTTON_NA -#define BUTTON_MENU_ALT BUTTON_NA -#define BUTTON_POWER SDLK_POWER // Power key mapped to SDL -#define BUTTON_PLUS BUTTON_NA // Available but not used (commented: SDLK_RSUPER) -#define BUTTON_MINUS BUTTON_NA // Available but not used (commented: SDLK_LSUPER) - -/////////////////////////////// -// Evdev/Keyboard Input Codes -// Hardware keycodes from kernel input subsystem -/////////////////////////////// - -#define CODE_UP CODE_NA -#define CODE_DOWN CODE_NA -#define CODE_LEFT CODE_NA -#define CODE_RIGHT CODE_NA - -#define CODE_SELECT CODE_NA -#define CODE_START CODE_NA - -#define CODE_A CODE_NA -#define CODE_B CODE_NA -#define CODE_X CODE_NA -#define CODE_Y CODE_NA - -#define CODE_L1 CODE_NA -#define CODE_R1 CODE_NA -#define CODE_L2 CODE_NA -#define CODE_R2 CODE_NA -#define CODE_L3 CODE_NA -#define CODE_R3 CODE_NA - -#define CODE_MENU CODE_NA -#define CODE_MENU_ALT CODE_NA -#define CODE_POWER 102 // KEY_HOME - -#define CODE_PLUS 129 // Volume up (swapped from keymon) -#define CODE_MINUS 128 // Volume down (swapped from keymon) - -/////////////////////////////// -// Joystick Button Mappings -// Hardware joystick indices -/////////////////////////////// - -#define JOY_UP 13 -#define JOY_DOWN 14 -#define JOY_LEFT 15 -#define JOY_RIGHT 16 - -#define JOY_SELECT 8 -#define JOY_START 9 - -#define JOY_A 1 -#define JOY_B 0 -#define JOY_X 2 -#define JOY_Y 3 - -#define JOY_L1 4 -#define JOY_R1 5 -#define JOY_L2 6 -#define JOY_R2 7 -#define JOY_L3 JOY_NA -#define JOY_R3 JOY_NA - -#define JOY_MENU 11 -#define JOY_MENU_ALT 12 // Secondary menu button -#define JOY_POWER JOY_NA -#define JOY_PLUS JOY_NA -#define JOY_MINUS JOY_NA - -/////////////////////////////// -// Function Button Mappings -// System-level button combinations -/////////////////////////////// - -#define BTN_RESUME BTN_X // Button to resume from save state -#define BTN_SLEEP BTN_POWER // Button to enter sleep mode -#define BTN_WAKE BTN_POWER // Button to wake from sleep -#define BTN_MOD_VOLUME BTN_NONE // Modifier for volume control (none - direct buttons) -#define BTN_MOD_BRIGHTNESS BTN_MENU // Hold MENU for brightness control -#define BTN_MOD_PLUS BTN_PLUS // Increase with PLUS -#define BTN_MOD_MINUS BTN_MINUS // Decrease with MINUS - -/////////////////////////////// -// Display Specifications -/////////////////////////////// - -#define SCREEN_DIAGONAL 4.0f // Physical screen diagonal in inches -#define FIXED_WIDTH 720 // Screen width in pixels (square display) -#define FIXED_HEIGHT 720 // Screen height in pixels (1:1 aspect ratio) - -/////////////////////////////// -// HDMI Output Specifications -/////////////////////////////// - -#define HAS_HDMI 1 // HDMI output supported -#define HDMI_WIDTH 1280 // HDMI width in pixels -#define HDMI_HEIGHT 720 // HDMI height in pixels (720p) - -/////////////////////////////// -// Platform-Specific Paths and Settings -/////////////////////////////// - -#define SDCARD_PATH \ - "/storage" // Path to SD card mount point (LessOS default, overridden by LESSOS_STORAGE) -#define MUTE_VOLUME_RAW 0 // Raw value for muted volume - -/////////////////////////////// -// Keymon Configuration -/////////////////////////////// - -#define KEYMON_BUTTON_MENU 317 -#define KEYMON_BUTTON_MENU_ALT 318 -#define KEYMON_BUTTON_PLUS 114 -#define KEYMON_BUTTON_MINUS 115 - -#define KEYMON_HAS_HDMI 1 -#define KEYMON_HDMI_STATE_PATH "/sys/class/extcon/hdmi/cable.0/state" - -#define KEYMON_HAS_JACK 1 -#define KEYMON_JACK_STATE_PATH "/sys/bus/platform/devices/singleadc-joypad/hp" - -// Uses event0-4 plus js0 (joystick) for menu button detection -#define KEYMON_INPUT_COUNT 6 -#define KEYMON_INPUT_DEVICE_0 "/dev/input/event0" -#define KEYMON_INPUT_DEVICE_1 "/dev/input/event1" -#define KEYMON_INPUT_DEVICE_2 "/dev/input/event2" -#define KEYMON_INPUT_DEVICE_3 "/dev/input/event3" -#define KEYMON_INPUT_DEVICE_4 "/dev/input/event4" -#define KEYMON_INPUT_DEVICE_5 "/dev/input/js0" - -/////////////////////////////// - -#endif diff --git a/workspace/rk3566/show/Makefile b/workspace/rk3566/show/Makefile deleted file mode 100755 index 03195e74..00000000 --- a/workspace/rk3566/show/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -ifeq (,$(CROSS_COMPILE)) -$(error missing CROSS_COMPILE for this toolchain) -endif - -TARGET = show -PRODUCT = $(TARGET).elf - -CC = $(CROSS_COMPILE)gcc -FLAGS = -Os $(CFLAGS) $(LDFLAGS) -lSDL2 -lSDL2_image -lrt -ldl -Wl,--gc-sections -s - -all: - $(CC) $(TARGET).c -o $(PRODUCT) $(FLAGS) -clean: - rm -rf $(PRODUCT) \ No newline at end of file diff --git a/workspace/rk3566/show/show.c b/workspace/rk3566/show/show.c deleted file mode 100644 index d095d569..00000000 --- a/workspace/rk3566/show/show.c +++ /dev/null @@ -1,83 +0,0 @@ -// rk3566 - Display an image on screen during boot/install/update -#include -#include -#include -#include -#include -#include - -SDL_Window* window; -SDL_Surface* screen; - -int main(int argc, char* argv[]) { - if (argc < 2) { - fprintf(stderr, "Usage: show.elf image.png [delay]\n"); - return 1; - } - - char path[256]; - snprintf(path, sizeof(path), "%s", argv[1]); - if (access(path, F_OK) != 0) { - fprintf(stderr, "show.elf: Image not found: %s\n", path); - return 1; - } - - int delay = argc > 2 ? atoi(argv[2]) : 2; - - fprintf(stderr, "show.elf: Initializing SDL2...\n"); - if (SDL_Init(SDL_INIT_VIDEO) < 0) { - fprintf(stderr, "show.elf: SDL_Init failed: %s\n", SDL_GetError()); - return 1; - } - - SDL_ShowCursor(0); - - // Use 0,0 to let SDL auto-detect display size (like tg5040) - fprintf(stderr, "show.elf: Creating window...\n"); - window = SDL_CreateWindow("", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 0, 0, SDL_WINDOW_SHOWN); - if (!window) { - fprintf(stderr, "show.elf: SDL_CreateWindow failed: %s\n", SDL_GetError()); - SDL_Quit(); - return 1; - } - - screen = SDL_GetWindowSurface(window); - if (!screen) { - fprintf(stderr, "show.elf: SDL_GetWindowSurface failed: %s\n", SDL_GetError()); - SDL_DestroyWindow(window); - SDL_Quit(); - return 1; - } - - fprintf(stderr, "show.elf: Window size: %dx%d\n", screen->w, screen->h); - SDL_FillRect(screen, NULL, 0); - - fprintf(stderr, "show.elf: Loading image: %s\n", path); - SDL_Surface* img = IMG_Load(path); - if (!img) { - fprintf(stderr, "show.elf: IMG_Load failed: %s\n", IMG_GetError()); - SDL_DestroyWindow(window); - SDL_Quit(); - return 1; - } - - fprintf(stderr, "show.elf: Image size: %dx%d\n", img->w, img->h); - - // Center the image on screen - SDL_Rect dst = {(screen->w - img->w) / 2, (screen->h - img->h) / 2, img->w, img->h}; - SDL_BlitSurface(img, NULL, screen, &dst); - - if (SDL_UpdateWindowSurface(window) < 0) { - fprintf(stderr, "show.elf: SDL_UpdateWindowSurface failed: %s\n", SDL_GetError()); - } - - fprintf(stderr, "show.elf: Displaying for %d seconds...\n", delay); - sleep(delay); - - SDL_FreeSurface(img); - SDL_DestroyWindow(window); - SDL_Quit(); - - fprintf(stderr, "show.elf: Done\n"); - return 0; -} From d2c86e4c322132fe98607180cc81d1f4c7e4af37 Mon Sep 17 00:00:00 2001 From: Nick Chapman Date: Wed, 31 Dec 2025 15:55:03 -0800 Subject: [PATCH 2/6] Use rk3566 toolchain for rgb30. --- Makefile.toolchain | 32 +++++++++++++------ .../SYSTEM/{rk3566 => rgb30}/bin/shutdown | 0 skeleton/SYSTEM/{rk3566 => rgb30}/cores/.keep | 0 skeleton/SYSTEM/{rk3566 => rgb30}/dat/.keep | 0 skeleton/SYSTEM/{rk3566 => rgb30}/lib/.keep | 0 skeleton/SYSTEM/{rk3566 => rgb30}/system.cfg | 0 toolchains.json | 3 +- 7 files changed, 25 insertions(+), 10 deletions(-) rename skeleton/SYSTEM/{rk3566 => rgb30}/bin/shutdown (100%) rename skeleton/SYSTEM/{rk3566 => rgb30}/cores/.keep (100%) rename skeleton/SYSTEM/{rk3566 => rgb30}/dat/.keep (100%) rename skeleton/SYSTEM/{rk3566 => rgb30}/lib/.keep (100%) rename skeleton/SYSTEM/{rk3566 => rgb30}/system.cfg (100%) diff --git a/Makefile.toolchain b/Makefile.toolchain index 11b81b85..04f509ac 100644 --- a/Makefile.toolchain +++ b/Makefile.toolchain @@ -16,10 +16,14 @@ # specific architectures (e.g., trimuismart and tg5040 need amd64). # # Adding a new platform: -# 1. Fork the union--toolchain repo to lessui-hq org -# 2. Add .github/workflows/build-container.yml to the fork -# 3. Trigger the workflow to build and publish container -# 4. Add platform entry to toolchains.json with appropriate architecture +# 1. Choose approach: +# a) Reuse existing toolchain: Add to toolchains.json with "toolchain" field +# (e.g., rgb30 reuses rk3566 toolchain) +# b) New toolchain: Fork union--toolchain repo to lessui-hq org +# 2. If creating new toolchain: +# - Add .github/workflows/build-container.yml to the fork +# - Trigger workflow to build and publish container +# 3. Add platform entry to toolchains.json with appropriate architecture # # DO NOT call this makefile directly unless debugging toolchain issues. # Use the main makefile's 'shell' and 'build' targets instead. @@ -43,7 +47,11 @@ GUEST_WORKSPACE = /root/workspace # Pre-built container registry CONTAINER_REGISTRY = ghcr.io CONTAINER_ORG = lessui-hq -CONTAINER_NAME = union-$(PLATFORM)-toolchain + +# Read toolchain name from toolchains.json (defaults to platform name) +# Allows platforms to share toolchains (e.g., rgb30 uses rk3566 toolchain) +TOOLCHAIN_NAME = $(shell jq -r --arg p "$(PLATFORM)" '.toolchains[$$p].toolchain // $$p' toolchains.json 2>/dev/null || echo "$(PLATFORM)") +CONTAINER_NAME = union-$(TOOLCHAIN_NAME)-toolchain CONTAINER_TAG = latest CONTAINER_IMAGE = $(CONTAINER_REGISTRY)/$(CONTAINER_ORG)/$(CONTAINER_NAME):$(CONTAINER_TAG) @@ -52,7 +60,7 @@ CONTAINER_IMAGE = $(CONTAINER_REGISTRY)/$(CONTAINER_ORG)/$(CONTAINER_NAME):$(CON DOCKER_PLATFORM = $(shell jq -r --arg p "$(PLATFORM)" '.toolchains[$$p].platform // "linux/arm64"' toolchains.json 2>/dev/null || echo "linux/arm64") # Common docker run options -DOCKER_RUN = docker run --rm --platform=$(DOCKER_PLATFORM) -e LOG_FLAGS="$(LOG_FLAGS)" -e OPT_FLAGS="$(OPT_FLAGS)" -e BUILD_HASH="$(BUILD_HASH)" -v $(HOST_WORKSPACE):$(GUEST_WORKSPACE) +DOCKER_RUN = docker run --rm --platform=$(DOCKER_PLATFORM) -e PLATFORM="$(PLATFORM)" -e LOG_FLAGS="$(LOG_FLAGS)" -e OPT_FLAGS="$(OPT_FLAGS)" -e BUILD_HASH="$(BUILD_HASH)" -v $(HOST_WORKSPACE):$(GUEST_WORKSPACE) # Default target: launch interactive shell (pulls image if missing) all: @@ -71,9 +79,15 @@ pull: echo "❌ Container not found: $(CONTAINER_IMAGE)" && \ echo "" && \ echo "To add support for $(PLATFORM):" && \ - echo " 1. Fork the union-$(PLATFORM)-toolchain to lessui-hq org" && \ - echo " 2. Add .github/workflows/build-container.yml" && \ - echo " 3. Trigger workflow to build and publish container" && \ + echo " Option A: Reuse existing toolchain" && \ + echo " 1. Add \"toolchain\": \"\" to toolchains.json" && \ + echo " 2. Specify platform architecture (linux/amd64 or linux/arm64)" && \ + echo "" && \ + echo " Option B: Create new toolchain" && \ + echo " 1. Fork union--toolchain to lessui-hq org" && \ + echo " 2. Add .github/workflows/build-container.yml" && \ + echo " 3. Trigger workflow to build and publish container" && \ + echo " 4. Add platform entry to toolchains.json" && \ echo "" && \ exit 1) @echo "✓ Updated to latest" diff --git a/skeleton/SYSTEM/rk3566/bin/shutdown b/skeleton/SYSTEM/rgb30/bin/shutdown similarity index 100% rename from skeleton/SYSTEM/rk3566/bin/shutdown rename to skeleton/SYSTEM/rgb30/bin/shutdown diff --git a/skeleton/SYSTEM/rk3566/cores/.keep b/skeleton/SYSTEM/rgb30/cores/.keep similarity index 100% rename from skeleton/SYSTEM/rk3566/cores/.keep rename to skeleton/SYSTEM/rgb30/cores/.keep diff --git a/skeleton/SYSTEM/rk3566/dat/.keep b/skeleton/SYSTEM/rgb30/dat/.keep similarity index 100% rename from skeleton/SYSTEM/rk3566/dat/.keep rename to skeleton/SYSTEM/rgb30/dat/.keep diff --git a/skeleton/SYSTEM/rk3566/lib/.keep b/skeleton/SYSTEM/rgb30/lib/.keep similarity index 100% rename from skeleton/SYSTEM/rk3566/lib/.keep rename to skeleton/SYSTEM/rgb30/lib/.keep diff --git a/skeleton/SYSTEM/rk3566/system.cfg b/skeleton/SYSTEM/rgb30/system.cfg similarity index 100% rename from skeleton/SYSTEM/rk3566/system.cfg rename to skeleton/SYSTEM/rgb30/system.cfg diff --git a/toolchains.json b/toolchains.json index f3d1e94b..be87624d 100644 --- a/toolchains.json +++ b/toolchains.json @@ -7,7 +7,8 @@ "platform": "linux/amd64" }, "rgb30": { - "platform": "linux/amd64" + "platform": "linux/amd64", + "toolchain": "rk3566" } } } From 19dcb047f15e9cf0e32edf4558965d5ec051eb71 Mon Sep 17 00:00:00 2001 From: Nick Chapman Date: Wed, 31 Dec 2025 18:56:17 -0800 Subject: [PATCH 3/6] Make dev-deploy target configurable. --- Makefile | 25 +++++++++++++++++-------- scripts/dev-deploy.sh | 13 +++++++++++-- 2 files changed, 28 insertions(+), 10 deletions(-) diff --git a/Makefile b/Makefile index 1f734d67..1530ee87 100644 --- a/Makefile +++ b/Makefile @@ -208,26 +208,35 @@ dev-run-16x9: # Usage: make dev-deploy - Deploy all platforms # make dev-deploy PLATFORM=X - Deploy single platform dev-deploy: - @if [ -n "$(PLATFORM)" ]; then \ - ./scripts/dev-deploy.sh --platform $(PLATFORM); \ + @DEPLOY_ARGS=""; \ + if [ -n "$(DEPLOY_PATH)" ]; then \ + DEPLOY_ARGS="--path $(DEPLOY_PATH)"; \ + fi; \ + if [ -n "$(PLATFORM)" ]; then \ + ./scripts/dev-deploy.sh --platform $(PLATFORM) $$DEPLOY_ARGS; \ else \ - ./scripts/dev-deploy.sh; \ + ./scripts/dev-deploy.sh $$DEPLOY_ARGS; \ fi # Build and deploy in one shot for dev iteration (always debug build) # Uses 'stage' to prepare files without compression (faster than full 'all') -# Usage: make dev-build-deploy - Build all platforms and deploy -# make dev-build-deploy PLATFORM=miyoomini - Build and deploy single platform +# Usage: make dev-build-deploy - Build all platforms and deploy +# make dev-build-deploy PLATFORM=miyoomini - Build and deploy single platform +# make dev-build-deploy DEPLOY_PATH=/Volumes/LESSUI - Override SD card path # Note: Single-platform requires 'make setup' to have been run first dev-build-deploy: - @if [ -n "$(PLATFORM)" ]; then \ + @DEPLOY_ARGS=""; \ + if [ -n "$(DEPLOY_PATH)" ]; then \ + DEPLOY_ARGS="--path $(DEPLOY_PATH)"; \ + fi; \ + if [ -n "$(PLATFORM)" ]; then \ if [ ! -d ./build/SYSTEM ]; then \ echo "Error: build/SYSTEM not found. Run 'make setup' first."; \ exit 1; \ fi; \ - $(MAKE) common PLATFORM=$(PLATFORM) DEBUG=1 && $(MAKE) stage && ./scripts/dev-deploy.sh --platform $(PLATFORM); \ + $(MAKE) common PLATFORM=$(PLATFORM) DEBUG=1 && $(MAKE) stage && ./scripts/dev-deploy.sh --platform $(PLATFORM) $$DEPLOY_ARGS; \ else \ - $(MAKE) setup DEBUG=1 && $(MAKE) $(PLATFORMS) DEBUG=1 && $(MAKE) special && $(MAKE) stage && ./scripts/dev-deploy.sh; \ + $(MAKE) setup DEBUG=1 && $(MAKE) $(PLATFORMS) DEBUG=1 && $(MAKE) special && $(MAKE) stage && ./scripts/dev-deploy.sh $$DEPLOY_ARGS; \ fi # Build all components for a specific platform (in Docker) diff --git a/scripts/dev-deploy.sh b/scripts/dev-deploy.sh index ace93913..0f91322b 100755 --- a/scripts/dev-deploy.sh +++ b/scripts/dev-deploy.sh @@ -4,6 +4,7 @@ # Usage: ./scripts/dev-deploy.sh [options] # # Options: +# --path PATH Override SD card path (default: /Volumes/LESSUI_DEV) # --no-update Skip .tmp_update (won't trigger update on device boot) # --platform X Only sync specific platform (e.g., miyoomini) # --no-eject Don't eject the SD card after sync @@ -20,7 +21,7 @@ set -e SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" -SD_CARD="/Volumes/LESSUI_DEV" +SD_CARD="/Volumes/LESSUI_DEV" # Default, can be overridden PAYLOAD_DIR="$PROJECT_ROOT/build/PAYLOAD" BASE_DIR="$PROJECT_ROOT/build/BASE" @@ -31,6 +32,14 @@ DO_EJECT=true while [[ $# -gt 0 ]]; do case $1 in + --path) + if [[ -z "${2:-}" || "$2" == --* ]]; then + echo "Error: --path requires a value" + exit 1 + fi + SD_CARD="$2" + shift 2 + ;; --no-update) SYNC_UPDATE=false shift @@ -54,7 +63,7 @@ while [[ $# -gt 0 ]]; do ;; *) echo "Error: Unknown option: $1" - echo "Usage: $0 [--no-update] [--platform ] [--no-eject]" + echo "Usage: $0 [--path ] [--no-update] [--platform ] [--no-eject]" exit 1 ;; esac From 1d990649dcef712bd6a99300c78109a3e0d16c77 Mon Sep 17 00:00:00 2001 From: Nick Chapman Date: Wed, 31 Dec 2025 20:19:48 -0800 Subject: [PATCH 4/6] Clean up debug logs and fix volume up and down buttons. --- workspace/all/common/gl_video.c | 20 -------------------- workspace/all/player/player.c | 6 +++--- workspace/all/player/player_loop_vsync.inc | 7 ------- workspace/all/player/player_menu.c | 4 ---- workspace/rgb30/platform/platform.h | 4 ++-- 5 files changed, 5 insertions(+), 36 deletions(-) diff --git a/workspace/all/common/gl_video.c b/workspace/all/common/gl_video.c index e7dc64e1..38518e49 100644 --- a/workspace/all/common/gl_video.c +++ b/workspace/all/common/gl_video.c @@ -1872,10 +1872,7 @@ void GLVideo_uploadFrame(const void* data, unsigned width, unsigned height, size } void GLVideo_presentSurface(SDL_Surface* surface) { - LOG_debug("presentSurface: enter"); - if (!gl_state.context_ready || gl_state.shutdown_prepared) { - LOG_debug("presentSurface: context not ready, returning"); return; } @@ -1884,28 +1881,21 @@ void GLVideo_presentSurface(SDL_Surface* surface) { return; } - LOG_debug("presentSurface: surface %dx%d", surface->w, surface->h); - SDL_Window* window = PLAT_getWindow(); if (!window) { LOG_error("GL video: no window for surface presentation"); return; } - LOG_debug("presentSurface: calling makeCurrent"); GLVideo_makeCurrent(); - LOG_debug("presentSurface: makeCurrent done"); // Bind backbuffer - LOG_debug("presentSurface: binding FBO 0"); glBindFramebuffer(GL_FRAMEBUFFER, 0); - LOG_debug("presentSurface: FBO 0 bound"); // Get screen dimensions int screen_w = 0; int screen_h = 0; SDL_GetWindowSize(window, &screen_w, &screen_h); - LOG_debug("presentSurface: screen %dx%d", screen_w, screen_h); if (screen_w <= 0 || screen_h <= 0) { LOG_error("GL video: invalid window size %dx%d", screen_w, screen_h); return; @@ -1917,8 +1907,6 @@ void GLVideo_presentSurface(SDL_Surface* surface) { if (!gl_state.ui_texture || gl_state.ui_texture_width != surf_w || gl_state.ui_texture_height != surf_h) { - LOG_debug("presentSurface: creating UI texture %ux%u", surf_w, surf_h); - if (gl_state.ui_texture) { glDeleteTextures(1, &gl_state.ui_texture); } @@ -1934,21 +1922,16 @@ void GLVideo_presentSurface(SDL_Surface* surface) { gl_state.ui_texture_width = surf_w; gl_state.ui_texture_height = surf_h; - - LOG_debug("presentSurface: UI texture created (id=%u)", gl_state.ui_texture); } - LOG_debug("presentSurface: uploading pixels"); glBindTexture(GL_TEXTURE_2D, gl_state.ui_texture); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, surf_w, surf_h, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, surface->pixels); - LOG_debug("presentSurface: setting viewport and clearing"); glViewport(0, 0, screen_w, screen_h); glClearColor(0.0f, 0.0f, 0.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); - LOG_debug("presentSurface: using shader program"); glUseProgram(gl_state.present_program); glActiveTexture(GL_TEXTURE0); @@ -1973,13 +1956,10 @@ void GLVideo_presentSurface(SDL_Surface* surface) { glVertexAttribPointer(gl_state.loc_position, 2, GL_FLOAT, GL_FALSE, 0, verts); glVertexAttribPointer(gl_state.loc_texcoord, 2, GL_FLOAT, GL_FALSE, 0, texco); - LOG_debug("presentSurface: drawing quad"); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); glDisableVertexAttribArray(gl_state.loc_position); glDisableVertexAttribArray(gl_state.loc_texcoord); - - LOG_debug("presentSurface: done"); } void GLVideo_swapBuffers(void) { diff --git a/workspace/all/player/player.c b/workspace/all/player/player.c index 09c463af..66914eb8 100644 --- a/workspace/all/player/player.c +++ b/workspace/all/player/player.c @@ -2446,12 +2446,12 @@ static void retro_log_callback(enum retro_log_level level, const char* fmt, ...) va_end(args); // Map libretro levels to our levels and log + // Note: Core DEBUG/INFO logs are demoted to LOG_debug to avoid huge log files + // in release builds. Only WARN/ERROR from cores are shown in release logs. switch (level) { case RETRO_LOG_DEBUG: - LOG_debug("%s", msg_buffer); - break; case RETRO_LOG_INFO: - LOG_info("%s", msg_buffer); + LOG_debug("%s", msg_buffer); break; case RETRO_LOG_WARN: LOG_warn("%s", msg_buffer); diff --git a/workspace/all/player/player_loop_vsync.inc b/workspace/all/player/player_loop_vsync.inc index 0d1a880e..743bef4f 100644 --- a/workspace/all/player/player_loop_vsync.inc +++ b/workspace/all/player/player_loop_vsync.inc @@ -98,9 +98,7 @@ static void run_main_loop(void) { // Measure frame execution time for auto CPU scaling uint64_t frame_start = getMicroseconds(); GLVideo_bindFBO(); - LOG_debug("Main loop: calling core.run()"); core.run(); - LOG_debug("Main loop: core.run() returned"); uint64_t frame_time = getMicroseconds() - frame_start; // Store frame time for auto CPU scaling analysis @@ -130,19 +128,14 @@ static void run_main_loop(void) { input_poll_callback(); if (show_menu) { - LOG_debug("Main loop: show_menu=1, entering Menu_loop"); Menu_loop(); - LOG_debug("Main loop: returned from Menu_loop, show_menu=%d", show_menu); // Rebind FBO for HW cores after menu (menu uses FBO 0) if (GLVideo_isEnabled()) { - LOG_debug("Main loop: re-binding FBO after menu exit"); GLVideo_bindFBO(); } } - LOG_debug("Main loop: about to call hdmimon"); hdmimon(); - LOG_debug("Main loop: hdmimon returned, continuing loop"); } } diff --git a/workspace/all/player/player_menu.c b/workspace/all/player/player_menu.c index 7ed02001..add91bca 100644 --- a/workspace/all/player/player_menu.c +++ b/workspace/all/player/player_menu.c @@ -467,8 +467,6 @@ static void Menu_afterSleep(void) { } static void Menu_loop_ctx(PlayerContext* ctx) { - LOG_debug("Menu_loop_ctx: enter, HW=%d", GLVideo_isEnabled()); - PlayerMenuState* m = ctx->menu; GFX_Renderer* r = (GFX_Renderer*)ctx->renderer; struct Game* g = ctx->game; @@ -786,10 +784,8 @@ static void Menu_loop_ctx(PlayerContext* ctx) { // Use GL presentation when HW rendering is active to avoid SDL/GL conflicts if (GLVideo_isEnabled()) { - LOG_debug("Menu: about to call GLVideo_presentSurface"); GLVideo_presentSurface(*scr); GLVideo_swapBuffers(); - LOG_debug("Menu: returned from GLVideo_presentSurface"); } else { GFX_present(NULL); } diff --git a/workspace/rgb30/platform/platform.h b/workspace/rgb30/platform/platform.h index b909b60f..189df017 100644 --- a/workspace/rgb30/platform/platform.h +++ b/workspace/rgb30/platform/platform.h @@ -197,8 +197,8 @@ #define KEYMON_BUTTON_MENU 317 #define KEYMON_BUTTON_MENU_ALT 318 -#define KEYMON_BUTTON_PLUS 114 -#define KEYMON_BUTTON_MINUS 115 +#define KEYMON_BUTTON_PLUS 115 // KEY_VOLUMEUP +#define KEYMON_BUTTON_MINUS 114 // KEY_VOLUMEDOWN #define KEYMON_HAS_HDMI 1 #define KEYMON_HDMI_STATE_PATH "/sys/class/extcon/hdmi/cable.0/state" From 06ba856bb84996b0955cd1e8e284d7adc7cb0e3e Mon Sep 17 00:00:00 2001 From: Nick Chapman Date: Wed, 31 Dec 2025 20:43:06 -0800 Subject: [PATCH 5/6] Remove redundant CPU speed setup from platform init scripts. --- .../paks/LessUI/platforms/magicmini/init.sh | 13 ++----------- .../paks/LessUI/platforms/miyoomini/init.sh | 12 +----------- .../all/paks/LessUI/platforms/my282/init.sh | 7 ++----- .../all/paks/LessUI/platforms/my355/init.sh | 9 +-------- .../all/paks/LessUI/platforms/rg35xx/init.sh | 11 +---------- .../all/paks/LessUI/platforms/rgb30/init.sh | 19 +------------------ .../all/paks/LessUI/platforms/tg5040/init.sh | 9 +-------- .../paks/LessUI/platforms/trimuismart/init.sh | 8 +------- .../all/paks/LessUI/platforms/zero28/init.sh | 9 +-------- 9 files changed, 11 insertions(+), 86 deletions(-) diff --git a/workspace/all/paks/LessUI/platforms/magicmini/init.sh b/workspace/all/paks/LessUI/platforms/magicmini/init.sh index c5381ecb..aae2e5bc 100644 --- a/workspace/all/paks/LessUI/platforms/magicmini/init.sh +++ b/workspace/all/paks/LessUI/platforms/magicmini/init.sh @@ -1,21 +1,12 @@ #!/bin/sh # magicmini initialization -# CPU/GPU/DMC governors +# CPU/GPU/DMC governors (CPU speed controlled by frontend) echo userspace >/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor echo performance >/sys/devices/platform/ff400000.gpu/devfreq/ff400000.gpu/governor echo performance >/sys/devices/platform/dmc/devfreq/dmc/governor -CPU_PATH=/sys/devices/system/cpu/cpufreq/policy0/scaling_setspeed -CPU_SPEED_PERF=1608000 - -cpu_restore() { - echo $CPU_SPEED_PERF >$CPU_PATH -} -cpu_restore - -# SDL audio -export SDL_AUDIODRIVER=alsa +# Audio setup amixer cset name='Playback Path' SPK # Clear framebuffer diff --git a/workspace/all/paks/LessUI/platforms/miyoomini/init.sh b/workspace/all/paks/LessUI/platforms/miyoomini/init.sh index 99b53c53..74ae831e 100644 --- a/workspace/all/paks/LessUI/platforms/miyoomini/init.sh +++ b/workspace/all/paks/LessUI/platforms/miyoomini/init.sh @@ -1,19 +1,9 @@ #!/bin/sh # miyoomini initialization -# CPU governor +# CPU governor (speed controlled by frontend) echo userspace >/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor -# CPU speeds for player -export CPU_SPEED_MENU=504000 -export CPU_SPEED_GAME=1296000 -export CPU_SPEED_PERF=1488000 - -cpu_restore() { - overclock.elf $CPU_SPEED_PERF -} -cpu_restore - # Detect Mini Plus if [ -f /customer/app/axp_test ]; then IS_PLUS=true diff --git a/workspace/all/paks/LessUI/platforms/my282/init.sh b/workspace/all/paks/LessUI/platforms/my282/init.sh index d168b75a..e02e8131 100644 --- a/workspace/all/paks/LessUI/platforms/my282/init.sh +++ b/workspace/all/paks/LessUI/platforms/my282/init.sh @@ -4,11 +4,8 @@ # LED off echo 0 >/sys/class/leds/led1/brightness -# CPU speed control via reclock -cpu_restore() { - overclock.elf userspace 2 1344 384 1080 0 -} -cpu_restore +# CPU governor (speed controlled by frontend) +overclock.elf userspace 2 1344 384 1080 0 # Clean up tee and update log killall -9 tee diff --git a/workspace/all/paks/LessUI/platforms/my355/init.sh b/workspace/all/paks/LessUI/platforms/my355/init.sh index 82552802..a34c27e8 100644 --- a/workspace/all/paks/LessUI/platforms/my355/init.sh +++ b/workspace/all/paks/LessUI/platforms/my355/init.sh @@ -5,15 +5,8 @@ export PATH="$PATH:/usr/miyoo/bin:/usr/miyoo/sbin" export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/usr/miyoo/lib" -# CPU setup +# CPU governor (speed controlled by frontend) echo userspace >/sys/devices/system/cpu/cpufreq/policy0/scaling_governor -CPU_PATH=/sys/devices/system/cpu/cpufreq/policy0/scaling_setspeed -CPU_SPEED_PERF=1992000 - -cpu_restore() { - echo $CPU_SPEED_PERF >$CPU_PATH -} -cpu_restore # Headphone jack GPIO echo 150 >/sys/class/gpio/export diff --git a/workspace/all/paks/LessUI/platforms/rg35xx/init.sh b/workspace/all/paks/LessUI/platforms/rg35xx/init.sh index be7ab22a..619fb0a8 100644 --- a/workspace/all/paks/LessUI/platforms/rg35xx/init.sh +++ b/workspace/all/paks/LessUI/platforms/rg35xx/init.sh @@ -1,18 +1,9 @@ #!/bin/sh # rg35xx initialization -# CPU setup +# CPU governor (speed controlled by frontend) echo userspace >/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor -export CPU_SPEED_MENU=504000 -export CPU_SPEED_GAME=1296000 -export CPU_SPEED_PERF=1488000 - -cpu_restore() { - overclock.elf $CPU_SPEED_PERF -} -cpu_restore - # Storage scheduler optimization echo noop >/sys/devices/b0238000.mmc/mmc_host/mmc0/emmc_boot_card/block/mmcblk0/queue/scheduler echo noop >/sys/devices/b0230000.mmc/mmc_host/mmc1/sd_card/block/mmcblk1/queue/scheduler diff --git a/workspace/all/paks/LessUI/platforms/rgb30/init.sh b/workspace/all/paks/LessUI/platforms/rgb30/init.sh index 7108267f..39f10d9a 100644 --- a/workspace/all/paks/LessUI/platforms/rgb30/init.sh +++ b/workspace/all/paks/LessUI/platforms/rgb30/init.sh @@ -3,25 +3,8 @@ # Device: PowKiddy RGB30 (Rockchip RK3566) # OS: LessOS (ROCKNIX-based) -type log_info >/dev/null 2>&1 && log_info "RGB30 platform init starting" - -# CPU setup +# CPU governor (speed controlled by frontend) echo userspace >/sys/devices/system/cpu/cpufreq/policy0/scaling_governor 2>/dev/null -CPU_PATH=/sys/devices/system/cpu/cpufreq/policy0/scaling_setspeed -CPU_SPEED_PERF=1992000 - -cpu_restore() { - echo "$CPU_SPEED_PERF" >"$CPU_PATH" 2>/dev/null -} -cpu_restore -type log_info >/dev/null 2>&1 && log_info "CPU governor set to userspace" - -# SDL environment -export SDL_AUDIODRIVER=alsa -type log_info >/dev/null 2>&1 && log_info "SDL_AUDIODRIVER=$SDL_AUDIODRIVER" # Start keymon -type log_info >/dev/null 2>&1 && log_info "Starting keymon..." LOG_FILE="$LOGS_PATH/keymon.log" keymon.elf & -KEYMON_PID=$! -type log_info >/dev/null 2>&1 && log_info "keymon started (PID: $KEYMON_PID)" diff --git a/workspace/all/paks/LessUI/platforms/tg5040/init.sh b/workspace/all/paks/LessUI/platforms/tg5040/init.sh index cf1b50c8..11b4ba39 100644 --- a/workspace/all/paks/LessUI/platforms/tg5040/init.sh +++ b/workspace/all/paks/LessUI/platforms/tg5040/init.sh @@ -68,15 +68,8 @@ trimui_inputd & # Start stock hardware daemon hardwareservice & -# CPU setup +# CPU governor (speed controlled by frontend) echo userspace >/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor -CPU_PATH=/sys/devices/system/cpu/cpu0/cpufreq/scaling_setspeed -CPU_SPEED_PERF=2000000 - -cpu_restore() { - echo $CPU_SPEED_PERF >$CPU_PATH -} -cpu_restore # Disable network killall MtpDaemon diff --git a/workspace/all/paks/LessUI/platforms/trimuismart/init.sh b/workspace/all/paks/LessUI/platforms/trimuismart/init.sh index a02ff520..2036a6f2 100644 --- a/workspace/all/paks/LessUI/platforms/trimuismart/init.sh +++ b/workspace/all/paks/LessUI/platforms/trimuismart/init.sh @@ -8,15 +8,9 @@ export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/usr/trimui/lib" # Button configuration echo A,B,X,Y,L,R >/sys/module/gpio_keys_polled/parameters/button_config -# CPU setup +# CPU governor (speed controlled by frontend) echo userspace >/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor CPU_PATH=/sys/devices/system/cpu/cpu0/cpufreq/scaling_setspeed -CPU_SPEED_PERF=1536000 - -cpu_restore() { - echo $CPU_SPEED_PERF >$CPU_PATH -} -cpu_restore # LED off leds_off diff --git a/workspace/all/paks/LessUI/platforms/zero28/init.sh b/workspace/all/paks/LessUI/platforms/zero28/init.sh index 811b488e..d23b34af 100644 --- a/workspace/all/paks/LessUI/platforms/zero28/init.sh +++ b/workspace/all/paks/LessUI/platforms/zero28/init.sh @@ -6,15 +6,8 @@ mkdir -p "$BIOS_PATH" mkdir -p "$SDCARD_PATH/Roms" mkdir -p "$SAVES_PATH" -# CPU setup +# CPU governor (speed controlled by frontend) echo userspace >/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor -CPU_PATH=/sys/devices/system/cpu/cpu0/cpufreq/scaling_setspeed -CPU_SPEED_PERF=1800000 - -cpu_restore() { - echo $CPU_SPEED_PERF >$CPU_PATH -} -cpu_restore # Backlight fix bl_disable && bl_enable From 567b892684d511c57c004fb0409c159bd9be5e8a Mon Sep 17 00:00:00 2001 From: Nick Chapman Date: Wed, 31 Dec 2025 21:13:43 -0800 Subject: [PATCH 6/6] Clean up RGB30 README. --- workspace/rgb30/README.md | 332 +++++--------------------------------- 1 file changed, 38 insertions(+), 294 deletions(-) diff --git a/workspace/rgb30/README.md b/workspace/rgb30/README.md index 468877bd..5a143e5f 100644 --- a/workspace/rgb30/README.md +++ b/workspace/rgb30/README.md @@ -1,329 +1,73 @@ # RGB30 Platform -Platform implementation for the PowKiddy RGB30 handheld (LessOS). +Platform implementation for the PowKiddy RGB30 running LessOS. ## Device -- **PowKiddy RGB30** - Rockchip RK3566 (Cortex-A55), 720x720 display -## Hardware Specifications +- **PowKiddy RGB30** - Rockchip RK3566 (Cortex-A55), 720x720 square display +- **OS**: LessOS (ROCKNIX-based) -### 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 +## Hardware -### 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 +| Feature | Specification | +|---------|---------------| +| Display | 720x720 (1:1 square), 16-bit RGB565, 2x UI scale | +| GPU | Mali-G52 (OpenGL ES 2.0) | +| HDMI | 1280x720 output with auto-detection | +| Input | D-pad, A/B/X/Y, L1/R1/L2/R2, dual analog sticks (L3/R3) | +| Audio | ALSA, headphone jack detection, HDMI audio | +| Storage | `/storage` (LessOS default) | -### Input Method -- **Primary**: Evdev input events (direct reading from `/dev/input/event*`) -- **Implementation**: Reads raw `input_event` structures for all input -- **Notable**: Bypasses SDL input APIs entirely +## Input -### CPU & Performance -- ARM processor with NEON SIMD support -- No overclocking support +Uses `rocknix-singleadc-joypad` kernel driver via evdev. -### 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` (LessOS) - -## Platform Architecture - -RGB30 use 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. +| Combination | Function | +|-------------|----------| +| PLUS/MINUS | Volume | +| MENU + PLUS/MINUS | Brightness | +| POWER | Sleep/wake | ## 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) +├── platform/ Platform definitions and render backend +├── keymon/ Button monitoring daemon (prebuilt) +├── libmsettings/ Settings library (volume, brightness, HDMI) +├── show/ Boot splash display +└── install/ Boot script ``` -## Input System - -RGB30 use 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: -# - show.elf (boot splash display) ``` -## Installation +Uses the `rk3566` toolchain (shared via `toolchains.json`). -### File System Layout +## Installation -LessUI installs to the SD card with the following structure: +LessOS handles boot via `/storage/lessos/init.sh`. LessUI installs to: ``` /storage/ -├── lessos/ LessOS bootstrap -│ └── init.sh Entry point -├── .system/ -│ ├── rgb30/ Platform-specific binaries -│ │ ├── bin/ Utilities (keymon, show, etc.) -│ │ └── paks/ Applications and emulators -│ │ └── LessUI.pak/ Main launcher -│ └── res/ Shared UI assets -│ ├── assets@2x.png UI sprite sheet (2x scale) -│ └── InterTight-Bold.ttf -├── .userdata/ User settings and save data -│ └── rgb30/ Platform-specific settings -│ └── msettings.bin Volume/brightness preferences -├── Roms/ ROM files organized by system -└── LessUI.7z Update package (if present) -``` - -### Settings Management - -RGB30 use 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): +├── .system/rgb30/ Platform binaries and paks +├── .userdata/rgb30/ User settings +└── Roms/ ROM files ``` -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 | - -## 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 natively (LessOS provides SDL2) -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/launcher/launcher.c` (launcher), `../../all/player/player.c` (libretro frontend) -- Build system: `../../Makefile` (host), `./makefile` (platform) -- Platform header: `./platform/platform.h` (all hardware definitions) - -## Maintainer Notes -This platform demonstrates several advanced LessUI features: +## Platform Features -**Unique Characteristics**: -- Square display (720x720) - unique aspect ratio among LessUI 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 +- **OpenGL ES**: Hardware-accelerated rendering (`HAS_OPENGLES 1`) +- **HDMI**: Auto-detection with video/audio routing +- **Overscan**: Supported (`PLAT_supportsOverscan`) +- **Effects**: Grid/line overlays via OpenGL -**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 +## Related -Changes to this platform should be tested with HDMI output and headphone jack to ensure automatic switching continues to work correctly. +- Platform header: `platform/platform.h` +- Shared code: `../all/launcher/`, `../all/player/`