Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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
PLATFORMS = miyoomini trimuismart rg35xx rg35xxplus my355 tg5040 zero28 rgb30 m17 my282 magicmini rk3566
endif

###########################################################
Expand Down Expand Up @@ -92,7 +92,7 @@ endif
export OPT_FLAGS
export LOG_FLAGS

.PHONY: help build test coverage lint format dev dev-run dev-run-4x3 dev-run-16x9 dev-clean all shell name clean setup special tidy stage compress package dev-deploy dev-build-deploy release release-patch release-minor release-major
.PHONY: help build test coverage lint format dev dev-run dev-run-4x3 dev-run-16x9 dev-clean all shell name clean setup lessos special tidy stage compress package dev-deploy dev-build-deploy release release-patch release-minor release-major

export MAKEFLAGS=--no-print-directory

Expand Down Expand Up @@ -313,7 +313,7 @@ setup: name
@echo "Generating emulator paks..."
@./scripts/generate-paks.sh all

# Platform-specific packaging for Miyoo/Trimui family
# Platform-specific packaging for Miyoo/Trimui/LessOS families
special:
@mkdir -p ./build/BOOT/common/install
@rsync -a ./skeleton/SYSTEM/common/log.sh ./build/BOOT/common/install/
Expand All @@ -323,9 +323,11 @@ special:
@mv ./build/BOOT/miyoo ./build/BASE/
@mv ./build/BOOT/trimui ./build/BASE/
@mv ./build/BOOT/magicx ./build/BASE/
@if [ -d ./build/BOOT/lessos ]; then mv ./build/BOOT/lessos ./build/BASE/; fi
@rsync -a ./build/BOOT/.tmp_update/ ./build/BASE/miyoo/app/.tmp_update/
@rsync -a ./build/BOOT/.tmp_update/ ./build/BASE/trimui/app/.tmp_update/
@rsync -a ./build/BOOT/.tmp_update/ ./build/BASE/magicx/.tmp_update/
@if [ -d ./build/BASE/lessos ]; then rsync -a ./build/BOOT/.tmp_update/ ./build/BASE/lessos/.tmp_update/; fi
@rsync -a ./build/BASE/miyoo/ ./build/BASE/miyoo354/
@rsync -a ./build/BASE/miyoo/ ./build/BASE/miyoo355/
@rsync -a ./build/BASE/miyoo/ ./build/BASE/miyoo285/
Expand Down Expand Up @@ -389,7 +391,7 @@ compress:
cd ./build/PAYLOAD && 7z a -t7z -mx=9 -md=16m -mmt=on LessUI.7z .system; \
fi
@mv ./build/PAYLOAD/LessUI.7z ./build/BASE
@cd ./build/BASE && 7z a -tzip -mmt=on -mx=5 ../../releases/$(RELEASE_NAME).zip Tools Bios Roms Saves bin miyoo miyoo354 trimui rg35xx rg35xxplus miyoo355 magicx miyoo285 em_ui.sh LessUI.7z README.txt
@cd ./build/BASE && 7z a -tzip -mmt=on -mx=5 ../../releases/$(RELEASE_NAME).zip Tools Bios Roms Saves bin miyoo miyoo354 trimui rg35xx rg35xxplus miyoo355 magicx miyoo285 lessos em_ui.sh LessUI.7z README.txt
@echo "$(RELEASE_NAME)" > ./build/latest.txt

# Package: full release build (stage + compress)
Expand Down
55 changes: 28 additions & 27 deletions Makefile.qa

Large diffs are not rendered by default.

67 changes: 38 additions & 29 deletions skeleton/BOOT/common/updater
Original file line number Diff line number Diff line change
Expand Up @@ -2,35 +2,44 @@

# NOTE: becomes .tmp_update/updater

INFO=`cat /proc/cpuinfo 2> /dev/null`
case $INFO in
*"sun8i"*)
if [ -d /usr/miyoo ]; then
PLATFORM="my282" # Miyoo A30
else
PLATFORM="trimuismart"
fi
;;
*"SStar"*)
PLATFORM="miyoomini"
;;
*"TG5040"*|*"TG3040"*)
PLATFORM="tg5040" # Trimui Smart Pro or Brick
;;
*"0xd03"*)
PLATFORM="zero28" # MagicX Mini Zero 28
;;
*"0xd05"*)
PLATFORM="my355" # Miyoo Flip
;;
esac
# LessOS provides platform directly via environment variable
if [ -n "$LESSOS_PLATFORM" ]; then
PLATFORM=$(echo "$LESSOS_PLATFORM" | tr '[:upper:]' '[:lower:]')
else
# Stock OS - detect platform from cpuinfo
INFO=$(cat /proc/cpuinfo 2>/dev/null)
case $INFO in
*"sun8i"*)
if [ -d /usr/miyoo ]; then
PLATFORM="my282" # Miyoo A30
else
PLATFORM="trimuismart"
fi
;;
*"SStar"*)
PLATFORM="miyoomini"
;;
*"TG5040"*|*"TG3040"*)
PLATFORM="tg5040" # Trimui Smart Pro or Brick
;;
*"0xd03"*)
PLATFORM="zero28" # MagicX Mini Zero 28
;;
*"0xd05"*)
PLATFORM="my355" # Miyoo Flip
;;
esac

# fallback for tg5040 20240413 recovery firmware
# TODO: doublecheck interaction with tg3040
# might need/want to strings /usr/trimui/bin/MainUI during install/update
# and store platform in a text file
if [ -z "$PLATFORM" ] && [ -f /usr/trimui/bin/runtrimui.sh ]; then
PLATFORM="tg5040"
# fallback for tg5040 20240413 recovery firmware
# TODO: doublecheck interaction with tg3040
# might need/want to strings /usr/trimui/bin/MainUI during install/update
# and store platform in a text file
if [ -z "$PLATFORM" ] && [ -f /usr/trimui/bin/runtrimui.sh ]; then
PLATFORM="tg5040"
fi
fi

exec "/mnt/SDCARD/.tmp_update/$PLATFORM.sh" # &> /mnt/SDCARD/boot.txt
# Use LessOS storage path if set, otherwise default to stock path
SDCARD_PATH="${LESSOS_STORAGE:-/mnt/SDCARD}"

exec "$SDCARD_PATH/.tmp_update/$PLATFORM.sh" # &> $SDCARD_PATH/boot.txt
24 changes: 24 additions & 0 deletions skeleton/BOOT/lessos/init.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#!/bin/sh
# LessOS Bootstrap for LessUI
# Mirrors stock platform hijack scripts (miyoomini.sh, etc.)
#
# LessOS provides these environment variables before calling this script:
# LESSOS_PLATFORM - SoC/platform family (e.g., "RK3566")
# LESSOS_DEVICE - Specific device model (e.g., "Powkiddy RGB30")
# LESSOS_STORAGE - Writable storage path (e.g., "/storage")

SDCARD_PATH="${LESSOS_STORAGE:-/storage}"
SCRIPT_DIR="$(dirname "$0")"

# Copy .tmp_update to SD card (like miyoomini.sh does)
# This ensures the updater and platform boot scripts are in place
if [ -d "$SCRIPT_DIR/.tmp_update" ]; then
cp -rf "$SCRIPT_DIR/.tmp_update" "$SDCARD_PATH/"
sync
fi

# Run the updater (handles platform detection, updates, and launching)
"$SDCARD_PATH/.tmp_update/updater"

# Fallback if updater exits unexpectedly
reboot
12 changes: 12 additions & 0 deletions skeleton/SYSTEM/rk3566/bin/shutdown
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#!/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
Empty file.
Empty file.
Empty file.
2 changes: 2 additions & 0 deletions skeleton/SYSTEM/rk3566/system.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
-player_screen_sharpness = Crisp

36 changes: 36 additions & 0 deletions tests/support/paths_stub.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/**
* paths_stub.c - Test stub for runtime paths
*
* Provides initialized path globals for unit testing.
* Uses values from tests/support/platform.h (SDCARD_PATH="/tmp/test")
*/

#include "paths.h"

#include <string.h>

// Initialize paths with test values
char g_sdcard_path[PATHS_MAX_LEN] = "/tmp/test";
char g_roms_path[PATHS_MAX_LEN] = "/tmp/test/Roms";
char g_root_system_path[PATHS_MAX_LEN] = "/tmp/test/.system";
char g_system_path[PATHS_MAX_LEN] = "/tmp/test/.system/test";
char g_res_path[PATHS_MAX_LEN] = "/tmp/test/.system/res";
char g_font_path[PATHS_MAX_LEN] = "/tmp/test/.system/res/font.ttf";
char g_userdata_path[PATHS_MAX_LEN] = "/tmp/test/.userdata/test";
char g_shared_userdata_path[PATHS_MAX_LEN] = "/tmp/test/.userdata/shared";
char g_paks_path[PATHS_MAX_LEN] = "/tmp/test/.system/test/paks";
char g_recent_path[PATHS_MAX_LEN] = "/tmp/test/.userdata/shared/.launcher/recent.txt";
char g_simple_mode_path[PATHS_MAX_LEN] = "/tmp/test/.userdata/test/.simple_mode";
char g_auto_resume_path[PATHS_MAX_LEN] = "/tmp/test/.userdata/test/.auto_resume";
char g_faux_recent_path[PATHS_MAX_LEN] = "/tmp/test/Recently Played";
char g_collections_path[PATHS_MAX_LEN] = "/tmp/test/Collections";

static int s_initialized = 1; // Pre-initialized for tests

void Paths_init(void) {
// No-op for tests - already initialized with test values
}

int Paths_isInitialized(void) {
return s_initialized;
}
3 changes: 3 additions & 0 deletions toolchains.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
},
"tg5040": {
"platform": "linux/amd64"
},
"rk3566": {
"platform": "linux/amd64"
}
}
}
18 changes: 10 additions & 8 deletions workspace/all/common/api.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
#include "defines.h"
#include "gfx_text.h"
#include "pad.h"
#include "paths.h"
#include "utils.h"

///////////////////////////////
Expand Down Expand Up @@ -364,7 +365,7 @@ SDL_Surface* GFX_init(int mode) {

// Load asset sprite sheet at selected tier
char asset_path[MAX_PATH];
(void)snprintf(asset_path, sizeof(asset_path), RES_PATH "/assets@%ix.png", asset_scale);
(void)snprintf(asset_path, sizeof(asset_path), "%s/assets@%ix.png", g_res_path, asset_scale);
LOG_debug("GFX_init: Loading assets from: %s", asset_path);
if (!exists(asset_path))
LOG_error("GFX_init: Missing assets at %s, about to segfault!", asset_path);
Expand Down Expand Up @@ -582,17 +583,17 @@ SDL_Surface* GFX_init(int mode) {
LOG_error("GFX_init: TTF_Init failed: %s", SDL_GetError());
return NULL;
}
LOG_debug("GFX_init: Loading fonts from %s", FONT_PATH);
font.large = TTF_OpenFont(FONT_PATH, DP(FONT_LARGE));
LOG_debug("GFX_init: Loading fonts from %s", g_font_path);
font.large = TTF_OpenFont(g_font_path, DP(FONT_LARGE));
if (!font.large)
LOG_error("GFX_init: Failed to load large font: %s", SDL_GetError());
font.medium = TTF_OpenFont(FONT_PATH, DP(FONT_MEDIUM));
font.medium = TTF_OpenFont(g_font_path, DP(FONT_MEDIUM));
if (!font.medium)
LOG_error("GFX_init: Failed to load medium font: %s", SDL_GetError());
font.small = TTF_OpenFont(FONT_PATH, DP(FONT_SMALL));
font.small = TTF_OpenFont(g_font_path, DP(FONT_SMALL));
if (!font.small)
LOG_error("GFX_init: Failed to load small font: %s", SDL_GetError());
font.tiny = TTF_OpenFont(FONT_PATH, DP(FONT_TINY));
font.tiny = TTF_OpenFont(g_font_path, DP(FONT_TINY));
if (!font.tiny)
LOG_error("GFX_init: Failed to load tiny font: %s", SDL_GetError());
LOG_debug("GFX_init: Fonts loaded successfully");
Expand Down Expand Up @@ -3029,9 +3030,10 @@ void PWR_powerOff(void) {

char* msg;
if (HAS_POWER_BUTTON || HAS_POWEROFF_BUTTON)
msg = exists(AUTO_RESUME_PATH) ? "Quicksave created,\npowering off" : "Powering off";
msg = exists(g_auto_resume_path) ? "Quicksave created,\npowering off" : "Powering off";
else
msg = exists(AUTO_RESUME_PATH) ? "Quicksave created,\npower off now" : "Power off now";
msg =
exists(g_auto_resume_path) ? "Quicksave created,\npower off now" : "Power off now";

// LOG_info("PWR_powerOff %s (%ix%i)\n", gfx.screen, gfx.screen->w, gfx.screen->h);

Expand Down
1 change: 1 addition & 0 deletions workspace/all/common/build.mk
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ COMMON_SOURCE = \
$(COMMON_DIR)/gfx_text.c \
$(COMMON_DIR)/scaler.c \
$(COMMON_DIR)/platform_variant.c \
$(COMMON_DIR)/paths.c \
$(PLATFORM_DIR)/platform.c

# Add shared rendering modules
Expand Down
77 changes: 77 additions & 0 deletions workspace/all/common/paths.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
/**
* paths.c - Runtime path resolution for dynamic storage locations
*
* Initializes all runtime paths based on environment variables or defaults.
*/

#include "paths.h"
#include "log.h"
#include "platform.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// Runtime path storage
char g_sdcard_path[PATHS_MAX_LEN];
char g_roms_path[PATHS_MAX_LEN];
char g_root_system_path[PATHS_MAX_LEN];
char g_system_path[PATHS_MAX_LEN];
char g_res_path[PATHS_MAX_LEN];
char g_font_path[PATHS_MAX_LEN];
char g_userdata_path[PATHS_MAX_LEN];
char g_shared_userdata_path[PATHS_MAX_LEN];
char g_paks_path[PATHS_MAX_LEN];
char g_recent_path[PATHS_MAX_LEN];
char g_simple_mode_path[PATHS_MAX_LEN];
char g_auto_resume_path[PATHS_MAX_LEN];
char g_faux_recent_path[PATHS_MAX_LEN];
char g_collections_path[PATHS_MAX_LEN];

static int s_initialized = 0;

void Paths_init(void) {
if (s_initialized) {
return;
}

// Check for LessOS storage environment variable
const char* env_storage = getenv("LESSOS_STORAGE");
if (env_storage && env_storage[0] != '\0') {
strncpy(g_sdcard_path, env_storage, PATHS_MAX_LEN - 1);
g_sdcard_path[PATHS_MAX_LEN - 1] = '\0';
LOG_info("Paths_init: Using LESSOS_STORAGE=%s", g_sdcard_path);
} else {
// Fall back to compile-time default
strncpy(g_sdcard_path, SDCARD_PATH, PATHS_MAX_LEN - 1);
g_sdcard_path[PATHS_MAX_LEN - 1] = '\0';
LOG_info("Paths_init: Using default SDCARD_PATH=%s", g_sdcard_path);
}

// Build all derived paths
(void)snprintf(g_roms_path, PATHS_MAX_LEN, "%s/Roms", g_sdcard_path);
(void)snprintf(g_root_system_path, PATHS_MAX_LEN, "%s/.system/", g_sdcard_path);

Copilot AI Dec 31, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The g_root_system_path includes a trailing slash in line 52 ("%s/.system/"), but other paths don't consistently use trailing slashes. This inconsistency could lead to malformed paths if code elsewhere doesn't expect the trailing slash. Consider removing it for consistency, or document why it's needed here.

Suggested change
(void)snprintf(g_root_system_path, PATHS_MAX_LEN, "%s/.system/", g_sdcard_path);
(void)snprintf(g_root_system_path, PATHS_MAX_LEN, "%s/.system", g_sdcard_path);

Copilot uses AI. Check for mistakes.
(void)snprintf(g_system_path, PATHS_MAX_LEN, "%s/.system/%s", g_sdcard_path, PLATFORM);
(void)snprintf(g_res_path, PATHS_MAX_LEN, "%s/.system/res", g_sdcard_path);
(void)snprintf(g_font_path, PATHS_MAX_LEN, "%s/.system/res/InterTight-Bold.ttf", g_sdcard_path);
(void)snprintf(g_userdata_path, PATHS_MAX_LEN, "%s/.userdata/%s", g_sdcard_path, PLATFORM);
(void)snprintf(g_shared_userdata_path, PATHS_MAX_LEN, "%s/.userdata/shared", g_sdcard_path);
(void)snprintf(g_paks_path, PATHS_MAX_LEN, "%s/paks", g_system_path);
(void)snprintf(g_recent_path, PATHS_MAX_LEN, "%s/.launcher/recent.txt", g_shared_userdata_path);
(void)snprintf(g_simple_mode_path, PATHS_MAX_LEN, "%s/enable-simple-mode",
g_shared_userdata_path);
(void)snprintf(g_auto_resume_path, PATHS_MAX_LEN, "%s/.launcher/auto_resume.txt",
g_shared_userdata_path);
(void)snprintf(g_faux_recent_path, PATHS_MAX_LEN, "%s/Recently Played", g_sdcard_path);
(void)snprintf(g_collections_path, PATHS_MAX_LEN, "%s/Collections", g_sdcard_path);

LOG_debug("Paths_init: g_roms_path=%s", g_roms_path);
LOG_debug("Paths_init: g_system_path=%s", g_system_path);
LOG_debug("Paths_init: g_res_path=%s", g_res_path);
LOG_debug("Paths_init: g_paks_path=%s", g_paks_path);

s_initialized = 1;
}

int Paths_isInitialized(void) {
return s_initialized;
}
Loading