diff --git a/spruce/scripts/docs/DOCUMENTATION_INDEX.md b/spruce/scripts/docs/DOCUMENTATION_INDEX.md new file mode 100644 index 000000000..559d2adca --- /dev/null +++ b/spruce/scripts/docs/DOCUMENTATION_INDEX.md @@ -0,0 +1,503 @@ +# SpruceOS Scripts Documentation Index + +## Quick Start + +Welcome to the SpruceOS scripts documentation! This is a comprehensive guide to understanding and working with the SpruceOS runtime system. + +### For First Time Users + +1. Start with [README.md](README.md) for an overview of the directory structure and key concepts +2. Review [PLATFORM_ABSTRACTION.md](PLATFORM_ABSTRACTION.md) to understand how scripts work across devices +3. Consult [ENVIRONMENT_VARIABLES.md](ENVIRONMENT_VARIABLES.md) when scripts need device-specific data + +### For Developers + +1. [FUNCTIONS.md](FUNCTIONS.md) - Complete function reference for all available functions +2. [EMULATOR_SYSTEM.md](EMULATOR_SYSTEM.md) - Understanding how games are launched and routed to emulators +3. [NETWORK_SERVICES.md](NETWORK_SERVICES.md) - Reference for network functionality + +## Documentation Files + +### 1. **README.md** - Complete System Overview + +**Best for:** Understanding the big picture + +Contents: + +- Directory structure and organization +- Script categories and purposes +- Critical process flows (game launch, shutdown, sleep) +- Configuration and settings management +- Cross-script communication patterns +- Related directories + +**Read this when:** You want to understand what each script does and how they interact + +--- + +### 2. **ENVIRONMENT_VARIABLES.md** - Environment Variable Reference + +**Best for:** Understanding hardware abstraction and configuration + +Contents: + +- System configuration variables ($PLATFORM, $SYSTEM_JSON) +- Hardware path variables (input devices, display, LED) +- Button mapping variables +- Directory and path variables +- State and flag variables +- Cross-script usage patterns +- Platform-specific variable sets + +**Read this when:** You need to know what variables are available or how to access settings + +--- + +### 3. **FUNCTIONS.md** - Function Reference + +**Best for:** Learning about available functions + +Contents: + +- Helper functions (device detection, configuration, logging) +- Device control functions (CPU, display, LED, vibration) +- Emulator control functions +- Network service functions +- Watchdog functions +- System management functions +- Configuration functions + +**Read this when:** You want to know what a function does or how to call it + +--- + +### 4. **PLATFORM_ABSTRACTION.md** - Platform Layer Documentation + +**Best for:** Understanding device abstraction and cross-device compatibility + +Contents: + +- Platform detection mechanism +- Three-layer abstraction model +- Platform configuration files +- Device-specific function implementations +- Implementation examples +- Adding support for new devices +- Platform capability matrix + +**Read this when:** You want to understand how to write device-agnostic code + +--- + +### 5. **EMULATOR_SYSTEM.md** - Emulator Launch System + +**Best for:** Understanding game launching and emulator routing + +Contents: + +- System overview and design philosophy +- Architecture and directory structure +- Step-by-step launch flow +- Emulator-specific handlers +- Configuration system +- Core mappings +- Adding new emulators +- Troubleshooting guide + +**Read this when:** You need to understand how games are launched or add new emulator support + +--- + +### 6. **NETWORK_SERVICES.md** - Network Services Reference + +**Best for:** Setting up and troubleshooting network features + +Contents: + +- Network system overview +- Service architecture +- SSH (Dropbear) configuration and usage +- Samba (SMB) file sharing +- Syncthing sync setup +- SFTPGo SFTP server +- Darkhttpd HTTP server +- Configuration management +- Common tasks and troubleshooting + +**Read this when:** You want to set up network services or troubleshoot connection issues + +--- + +## Topic Guide + +### I want to... + +#### Understand How The System Works + +1. [README.md](README.md#directory-structure) - Overview of structure +2. [README.md](README.md#script-categories) - What each script does +3. [README.md](README.md#critical-process-flows) - How games launch and shutdown + +#### Write a New Script + +1. [PLATFORM_ABSTRACTION.md](PLATFORM_ABSTRACTION.md) - Understand device abstraction +2. [ENVIRONMENT_VARIABLES.md](ENVIRONMENT_VARIABLES.md) - Know what variables are available +3. [FUNCTIONS.md](FUNCTIONS.md) - See reusable functions +4. [README.md](README.md#key-dependencies--sourcing-chains) - Understand sourcing patterns + +#### Add Support for a New Device + +1. [PLATFORM_ABSTRACTION.md](PLATFORM_ABSTRACTION.md#adding-support-for-new-devices) - Step-by-step guide +2. platform configuration files as references +3. [ENVIRONMENT_VARIABLES.md](ENVIRONMENT_VARIABLES.md#platform-specific-variable-sets) - Variable templates + +#### Add a New Emulator + +1. [EMULATOR_SYSTEM.md](EMULATOR_SYSTEM.md#adding-new-emulators) - Step-by-step guide +2. [EMULATOR_SYSTEM.md](EMULATOR_SYSTEM.md#emulator-specific-handlers) - Handler examples +3. Existing emulator handler files as templates + +#### Set Up Network Services + +1. [NETWORK_SERVICES.md](NETWORK_SERVICES.md) - Start here +2. [NETWORK_SERVICES.md](NETWORK_SERVICES.md#common-tasks) - Task reference +3. [NETWORK_SERVICES.md](NETWORK_SERVICES.md#troubleshooting) - Debugging + +#### Debug a Script + +1. [ENVIRONMENT_VARIABLES.md](ENVIRONMENT_VARIABLES.md#accessing-variables-in-scripts) - Check variable access +2. [FUNCTIONS.md](FUNCTIONS.md#logging-functions) - Use logging functions +3. Check `/mnt/SDCARD/Saves/spruce/spruce.log` for logs + +#### Understand CPU/Performance + +1. [PLATFORM_ABSTRACTION.md](PLATFORM_ABSTRACTION.md#device-specific-functions) - CPU control functions +2. [FUNCTIONS.md](FUNCTIONS.md#cpugovernor-functions-generic) - Generic CPU functions +3. [PLATFORM_ABSTRACTION.md](PLATFORM_ABSTRACTION.md#performance-implications) - Frequency table + +#### Troubleshoot Boot Issues + +1. [README.md](README.md#critical-process-flows) - Understand startup sequence +2. Check system logs: `/var/log/messages` +3. Check SpruceOS logs: `/mnt/SDCARD/Saves/spruce/spruce.log` + +#### Troubleshoot Game Launch Issues + +1. [EMULATOR_SYSTEM.md](EMULATOR_SYSTEM.md#troubleshooting) - Emulator debugging guide +2. Check game ROM path and format +3. Verify emulator core is installed + +--- + +## Script Organization Summary + +### By Function Category + +| Category | Key Files | Purpose | +| -------------------- | ------------------------------------------------ | ------------------------------------ | +| **System Startup** | runtime.sh, firstboot.sh, runtimeHelper.sh | Initialize system and load services | +| **Main Menu Loop** | principal.sh, archiveUnpacker.sh | Game selection and launching | +| **Game Launch** | emu/standard_launch.sh, emu/lib/\*.sh | Route to emulator and launch | +| **Watchdogs** | \*\_watchdog.sh | Monitor hardware events continuously | +| **Power Management** | save*poweroff.sh, sleep_helper.sh, idlemon*\*.sh | Shutdown and idle handling | +| **Device Control** | platform/device_functions/\*.sh | Hardware abstraction layer | +| **Network Services** | network/\*Functions.sh, networkservices.sh | Connectivity and file sharing | +| **Utilities** | tasks/\*.sh | System maintenance and repair | + +### By Device Support + +| Device | Architecture | Config File | Device File | +| -------------------- | -------------- | ------------- | ------------ | +| **Miyoo A30** | 32-bit (ARMv7) | A30.cfg | A30.sh | +| **Miyoo Mini** | 32-bit (ARMv7) | MiyooMini.cfg | MiyooMini.sh | +| **Miyoo Flip** | 64-bit (ARMv8) | Flip.cfg | Flip.sh | +| **TrimUI SmartPro** | 64-bit (ARMv8) | SmartPro.cfg | SmartPro.sh | +| **TrimUI SmartProS** | 64-bit (ARMv8) | SmartProS.cfg | SmartProS.sh | +| **Miyoo Pixel2** | 64-bit (ARMv8) | Pixel2.cfg | Pixel2.sh | +| **TrimUI Brick** | 64-bit (ARMv8) | Brick.cfg | Brick.sh | + +--- + +## Key Concepts + +### Abstraction Layers + +**Layer 1: Application Scripts** + +- High-level logic (game launching, settings) +- Device-agnostic code + +**Layer 2: Platform Abstraction (helperFunctions.sh)** + +- Generic helper functions +- Configuration access +- Device detection + +**Layer 3: Device-Specific Implementation** + +- Hardware control (CPU, display, LED) +- Platform configuration files +- Architecture-specific code + +### Configuration System + +**Main Config File:** `/mnt/SDCARD/spruce/-system.json` + +**Configuration Hierarchy:** + +1. User's device-specific override +2. User's system-specific preference +3. User's global preference +4. System default (hardcoded) + +**Access:** `get_config_value '.path.to.setting.selected'` + +### Flag System + +**Purpose:** Inter-process communication + +**Types:** + +- Persistent: `/mnt/SDCARD/spruce/flags/` +- Temporary: `/tmp/` + +**Usage:** `flag_add`, `flag_check`, `flag_remove` + +### Sourcing Pattern + +Most scripts follow this pattern: + +```bash +#!/bin/bash +source /mnt/SDCARD/spruce/scripts/helperFunctions.sh # Load core +source /mnt/SDCARD/spruce/scripts/platform/device_functions/${PLATFORM}.sh # Load device-specific + +# Now use unified interface - automatically routed! +set_performance # Works on all devices +vibrate # Works on all devices +``` + +--- + +## Common Patterns + +### Reading Configuration + +```bash +SWAP_SIZE=$(get_config_value '.menuOptions.System.swapfileSize.selected') +``` + +### Detecting Device + +```bash +source /mnt/SDCARD/spruce/scripts/helperFunctions.sh +echo "Device: $PLATFORM" +``` + +### Device-Specific Code + +```bash +case "$PLATFORM" in + A30|MiyooMini) + # 32-bit specific code + ;; + Flip|SmartPro) + # 64-bit specific code + ;; +esac +``` + +### Controlling CPU + +```bash +set_performance # Gaming mode +set_smart # Balanced mode +set_powersave # Power saving mode +set_overclock # Maximum performance (A30 only) +``` + +### Launching Games + +```bash +# Games are launched via: /Emu//launch.sh +/Emu/GB/launch.sh "/mnt/SDCARD/Roms/GB/Tetris.gb" +``` + +--- + +## File Locations Reference + +| Path | Contents | +| ------------------------------------------- | ----------------------------- | +| `/mnt/SDCARD/spruce/scripts/` | All scripts (this directory) | +| `/mnt/SDCARD/spruce/-system.json` | Configuration settings | +| `/mnt/SDCARD/Emu/` | Emulator installations | +| `/mnt/SDCARD/Roms/` | Game ROMs organized by system | +| `/mnt/SDCARD/Saves/` | Game saves and configurations | +| `/mnt/SDCARD/Themes/` | UI themes | +| `/var/log/messages` | System kernel log | +| `/mnt/SDCARD/Saves/spruce/spruce.log` | SpruceOS application log | + +--- + +## Getting Help + +### Check Script Comments + +Most scripts have comments at the top explaining their purpose: + +```bash +head -50 /mnt/SDCARD/spruce/scripts/script.sh +``` + +### View Script Source + +To understand a function, look at its implementation: + +```bash +grep -A 20 "function_name()" /mnt/SDCARD/spruce/scripts/script.sh +``` + +### Check Logs + +```bash +# System events +tail -f /var/log/messages + +# SpruceOS events +tail -f /mnt/SDCARD/Saves/spruce/spruce.log +``` + +### Common Debug Commands + +```bash +# Check device type +source helperFunctions.sh && echo $PLATFORM + +# Check if service is running +ps aux | grep servicename + +# Check configuration +jq '.menuOptions' /mnt/SDCARD/spruce/-system.json | head -50 + +# Test function +source helperFunctions.sh && get_config_value '.theme' +``` + +--- + +## Version Information + +This documentation corresponds to SpruceOS with: + +- **Supported Devices:** 7 handheld devices +- **Script Count:** 60+ shell scripts +- **Emulator Support:** 40+ systems via RetroArch + specialized emulators +- **Network Services:** 5 (SSH, Samba, Syncthing, SFTPGo, Darkhttpd) +- **Architecture Support:** 32-bit and 64-bit ARM + +--- + +## Document Navigation + +``` +README.md +├── Overview of all scripts +├── Directory structure +├── Process flows +└── Cross-script communication + +ENVIRONMENT_VARIABLES.md +├── All variable types +├── Hardware paths +├── Button mappings +└── Usage patterns + +FUNCTIONS.md +├── Helper functions +├── Device control +├── Emulator functions +├── Network functions +└── All function signatures + +PLATFORM_ABSTRACTION.md +├── Device detection +├── Architecture overview +├── Creating new platform support +└── Hardware capability matrix + +EMULATOR_SYSTEM.md +├── Game launch flow +├── Emulator-specific handlers +├── Configuration system +└── Adding new emulators + +NETWORK_SERVICES.md +├── Service descriptions +├── Configuration +├── Usage examples +└── Troubleshooting +``` + +--- + +## Tips & Tricks + +### Quick Device Detection + +```bash +source /mnt/SDCARD/spruce/scripts/helperFunctions.sh +echo "I'm running on: $PLATFORM ($BRAND)" +``` + +### List All Available Functions + +```bash +grep -h "^[a-z_]*() {" /mnt/SDCARD/spruce/scripts/*.sh +``` + +### Find Function Definition + +```bash +grep -r "function_name()" /mnt/SDCARD/spruce/scripts/ +``` + +### Check if Function Exists + +```bash +declare -f function_name >/dev/null && echo "Function exists" +``` + +### Debug Script Execution + +```bash +bash -x /path/to/script.sh # Trace execution +bash -x -e /path/to/script.sh # Exit on error +``` + +--- + +## Contributing & Maintenance + +### Before Modifying Scripts + +1. Read relevant documentation +2. Understand the abstraction layers +3. Test on multiple devices if possible +4. Update documentation if behavior changes + +### Best Practices + +1. Source `helperFunctions.sh` first +2. Use `$PLATFORM` and `$SYSTEM_JSON` variables +3. Leverage existing functions instead of duplicating code +4. Log important events using logging functions +5. Use flag system for inter-process communication +6. Handle cleanup on exit + +### Adding New Documentation + +1. Keep sections focused and organized +2. Provide examples for each concept +3. Reference other documentation files +4. Update this index if adding new files diff --git a/spruce/scripts/docs/EMULATOR_SYSTEM.md b/spruce/scripts/docs/EMULATOR_SYSTEM.md new file mode 100644 index 000000000..7429448f3 --- /dev/null +++ b/spruce/scripts/docs/EMULATOR_SYSTEM.md @@ -0,0 +1,630 @@ +# Emulator System Documentation + +This document describes the universal emulator launching system in SpruceOS, which routes game launches to appropriate emulators using a flexible, configuration-driven architecture. + +## Table of Contents + +1. [System Overview](#system-overview) +2. [Architecture](#architecture) +3. [Emulator Launch Flow](#emulator-launch-flow) +4. [Emulator-Specific Handlers](#emulator-specific-handlers) +5. [Configuration System](#configuration-system) +6. [Core Mappings](#core-mappings) +7. [Adding New Emulators](#adding-new-emulators) +8. [Configuration Reference](#configuration-reference) + +## System Overview + +The emulator system provides: + +1. **Universal Launcher** - Single entry point for all game launches +2. **Configuration-Driven Core Selection** - Cores selected from system JSON +3. **Platform Abstraction** - Works across all device types and architectures +4. **Modular Emulator Support** - Add new emulators without modifying core code +5. **Pre-Game and Post-Game Hooks** - Setup and cleanup around emulation + +### Design Philosophy + +Instead of having separate launch scripts for each emulator/system combination, SpruceOS uses a single `standard_launch.sh` that: + +1. Detects which emulator is needed (from script filename) +2. Loads emulator-specific configuration from JSON +3. Routes to appropriate emulator handler +4. Cleans up after game session + +This reduces code duplication and makes maintenance easier. + +## Architecture + +### Directory Structure + +``` +spruce/scripts/emu/ +├── standard_launch.sh # Universal launcher (entry point) +└── lib/ + ├── core_mappings.sh # RetroArch core lookup table + ├── general_functions.sh # Universal emulator functions + ├── ra_functions.sh # RetroArch-specific + ├── drastic_functions.sh # NDS (DraStic) emulator + ├── ppsspp_functions.sh # PSP (PPSSPP) emulator + ├── media_functions.sh # Media playback (FFmpeg) + ├── scummvm_functions.sh # ScummVM adventure games + ├── flycast_functions.sh # DC/Naomi (Flycast) + ├── mupen_functions.sh # N64 (Mupen64plus) + ├── pico8_functions.sh # PICO-8 fantasy console + ├── ports_functions.sh # Game Ports (custom) + ├── yaba_functions.sh # Saturn (Yabasanshiro) + ├── openbor_functions.sh # Beat-em-up engine + ├── led_functions.sh # LED effects + ├── network_functions.sh # In-game network services + └── gtt_functions.sh # Game Time Tracking +``` + +### How Games Are Launched + +1. **User selects game** in PyUI/MainUI +2. **Menu creates task** `/tmp/cmd_to_run.sh` with ROM path +3. **principal.sh detects file** and executes it +4. **Script path encodes system** (e.g., `/Emu/GB/launch.sh → GB system) +5. **standard_launch.sh sources** emulator-specific handler library +6. **Handler detects core** from system JSON configuration +7. **Handler launches game** with appropriate emulator +8. **On exit:** Cleanup and return to menu + +### Game ROM Location Mapping + +``` +/Emu//launch.sh + ↓ +standard_launch.sh determines EMU_NAME = + ↓ +Looks up core in: Emu/.emu_setup//config.json + ↓ +Routes to appropriate emulator function + ↓ +Emulator reads ROM from: /mnt/SDCARD/Roms// +``` + +## Emulator Launch Flow + +### Step-by-Step Execution + +``` +1. User selects game in menu + ↓ +2. Menu writes: /tmp/cmd_to_run.sh with ROM path + Example: /Emu/GB/launch.sh "/mnt/SDCARD/Roms/GB/Tetris.gb" + ↓ +3. principal.sh detects /tmp/cmd_to_run.sh and executes it + ↓ +4. /Emu/GB/launch.sh is actually symlink to standard_launch.sh + standard_launch.sh "${@}" + ↓ +5. standard_launch.sh: + a) Source helperFunctions.sh (load platform detection) + b) Detect EMU_NAME from $0 path → EMU_NAME="GB" + c) Source general_functions.sh + d) Set CPU to performance mode + e) Check network needs - stop services if required + f) Source emulator-specific library (ra_functions.sh for GB) + g) Load configuration from system JSON + h) Get core preference: RetroArch or specific emulator + i) Trigger LED effect (gaming profile) + j) Call handler function: launch_gb_game() with ROM path + ↓ +6. Emulator-specific handler (e.g., launch_gb_game()): + a) Load emulator configuration for system/platform + b) Apply overlays if enabled (Perfect Overlays for GB) + c) Launch emulator with game ROM + d) Wait for emulator to exit + ↓ +7. Post-execution cleanup: + a) Restore CPU mode to default + b) Sync filesystem + c) Restore display/audio settings + d) Return to principal.sh → back to menu +``` + +### Configuration Access During Launch + +```bash +# Example: GB system launch + +# 1. Get core preference +CORE=$(get_config_value '.menuOptions.Emulator_GB.selected') +# Returns: "snes9x" or "mgba" (user setting in UI) + +# 2. Get platform-specific override (if exists) +CORE=$(get_config_value ".menuOptions.Emulator_GB_${PLATFORM}.selected") +# Returns: platform override or empty string + +# 3. Fall back to system default +if [ -z "$CORE" ]; then + CORE=$(get_emu_core_for_system "GB") + # Returns: "mgba" (default for GB) +fi + +# 4. Get system-specific config +SYSTEM_CONFIG="/Emu/GB/config.json" +RA_CONFIG="/Saves/GB/config/retroarch-${PLATFORM}.cfg" + +# 5. Apply configuration +launch_game_with_core "$ROM_PATH" "$CORE" +``` + +## Emulator-Specific Handlers + +### RetroArch Systems (Most Systems) + +RetroArch is used for the majority of systems via `ra_functions.sh`: + +**Supported Systems:** NES, SNES, Genesis, GB, GBC, GBA, N64, PSX, and 20+ others + +**Core Selection:** + +```bash +# From system JSON configuration +jq '.menuOptions.Emulator_GB.selected' /mnt/SDCARD/spruce/-system.json +# Returns: User's selected core (e.g., "mgba", "snes9x") + +# Core-to-ROM mapping (core_mappings.sh) +get_ra_core_for_system "GB" +# Returns: "mgba" (sensible default if user hasn't configured) +``` + +**Launch Code Pattern:** + +```bash +launch_ra_game() { + local rom_path="$1" + local system="$2" + local core="$3" + + # Set up RetroArch + $RETROARCH \ + --config "$RA_CONFIG" \ + -L "/mnt/SDCARD/RetroArch/cores/${core}_libretro.so" \ + "$rom_path" +} +``` + +### DraStic Handler (NDS Emulator) + +Nintendo DS games use DraStic exclusively (superior performance on handheld): + +**Handler File:** `emu/lib/drastic_functions.sh` + +**Launch Flow:** + +```bash +launch_nds_game() { + rom_path="$1" + + # Load platform-specific launcher + case "$PLATFORM_ARCHITECTURE" in + armhf) + /mnt/SDCARD/Emu/NDS/drastic32 "$rom_path" + ;; + aarch64) + /mnt/SDCARD/Emu/NDS/drastic64 "$rom_path" + ;; + esac +} +``` + +**Configuration:** Uses platform-specific `.cfg` files in `/Saves/NDS/`. + +### PPSSPP Handler (PSP Emulator) + +PlayStation Portable games use PPSSPP specifically: + +**Handler File:** `emu/lib/ppsspp_functions.sh` + +**Launch Flow:** + +```bash +launch_psp_game() { + rom_path="$1" + + # Platform-specific config + case "$PLATFORM" in + A30) + PPSSPP_CONFIG="/Saves/PSP/A30_PPSSPPConfig.ini" + ;; + Flip) + PPSSPP_CONFIG="/Saves/PSP/Flip_PPSSPPConfig.ini" + ;; + esac + + PPSSPP_CONFIG_DIR="$(dirname "$PPSSPP_CONFIG")" + + /mnt/SDCARD/Emu/PSP/PPSSPP_Core \ + --config-dir="$PPSSPP_CONFIG_DIR" \ + "$rom_path" +} +``` + +### ScummVM Handler (Adventure Games) + +Point-and-click adventure games use ScummVM: + +**Handler File:** `emu/lib/scummvm_functions.sh` + +**Game Discovery:** + +```bash +scan_scummvm_library() { + /mnt/SDCARD/Emu/SCUMMVM/scummvm --list-games | \ + awk '{print $1}' | \ + head -n -1 +} +``` + +**Launch Flow:** + +```bash +launch_scummvm_game() { + game_id="$1" + + /mnt/SDCARD/Emu/SCUMMVM/scummvm \ + --config=/etc/scummvmrc \ + --savepath=/mnt/SDCARD/Saves/SCUMMVM \ + "$game_id" +} +``` + +### Media Handler (FFmpeg) + +Video and media files use FFmpeg for playback: + +**Handler File:** `emu/lib/media_functions.sh` + +**Launch Flow:** + +```bash +launch_media_file() { + media_path="$1" + + ffplay -fs "$media_path" # Full-screen playback +} +``` + +### Custom Ports Handler + +Game ports use platform-specific launchers: + +**Handler File:** `emu/lib/ports_functions.sh` + +**Launch Flow:** + +```bash +launch_port_game() { + port_name="$1" + + case "$port_name" in + doom) + /mnt/SDCARD/App/A30PORTS/doom/doom.elf + ;; + quake) + /mnt/SDCARD/App/A30PORTS/quake/quake + ;; + esac +} +``` + +### Special System Routing + +**A30PORTS System:** + +- Routes to appropriate port launcher +- Auto-detects port type +- May require platform-specific binary + +**MEDIA/MOVIES System:** + +- Routes to FFmpeg +- Handles video, audio, images +- Scales to display resolution + +**DC/NAOMI Systems:** + +- Uses Flycast emulator preferentially +- Falls back to RetroArch if Flycast unavailable + +**PICO8 System:** + +- Uses PICO-8 fantasy console binary +- Runs `.p8` cartridge files + +## Configuration System + +### System Configuration Files + +Each system has its own configuration: + +``` +/Emu/GB/config.json # User settings for Game Boy +/Emu/.emu_setup/GB/config.json # Factory defaults for GB +/Saves/GB/config/ # Runtime-specific configs +/Saves/GB/.*.cfg # Platform-specific backups +``` + +### Configuration Structure + +```json +{ + "menuOptions": { + "Emulator": { + "selected": "mgba", // Global default core + "options": ["snes9x", "mgba"] // Available cores + }, + "Emulator_GB": { + "selected": "mgba", // GB-specific override + "options": ["snes9x", "mgba", "gb"] // GB available cores + }, + "Emulator_GB_A30": { + "selected": "gb", // A30-specific override for GB + "options": ["gb"] // Limited to this on 32-bit + }, + "GB_Settings": { + "renderer": "software", + "saveType": "automatic", + "bootBIOS": false + } + } +} +``` + +### Configuration Precedence (For Core Selection) + +``` +1. User's platform-specific override: + .menuOptions.Emulator__.selected + +2. User's system-specific preference: + .menuOptions.Emulator_.selected + +3. User's global emulator preference: + .menuOptions.Emulator.selected + +4. System default (hardcoded in core_mappings.sh): + Default core for system +``` + +### Configuration Reading Functions + +```bash +# Generic configuration reader +CORE=$(get_config_value '.menuOptions.Emulator_GB.selected') + +# With jq directly +CORE=$(jq '.menuOptions.Emulator_GB.selected' "$SYSTEM_JSON") + +# Emulator-specific reader (general_functions.sh) +set_emu_core_from_emu_json "GB" +echo "Using core: $CORE" +``` + +## Core Mappings + +The `core_mappings.sh` file provides default core selections for each system: + +```bash +# core_mappings.sh - Default RetroArch cores + +get_ra_core_for_system() { + local system="$1" + + case "$system" in + # Nintendo Systems + NES|FC) echo "fceumm" ;; + SNES|SFC) echo "snes9x" ;; + N64) echo "mupen64plus" ;; # Via ra_functions + GBA) echo "mgba" ;; + GB|GBC) echo "mgba" ;; + + # Sega Systems + MD|GEN|GENESIS) echo "genesis_plus_gx" ;; + GG) echo "genesis_plus_gx" ;; + MS|MASTERSYSTEM) echo "genesis_plus_gx" ;; + + # Sony Systems + PS) echo "pcsx_rearmed" ;; + + # Atari Systems + ATARI) echo "stella" ;; + + # Arcade Systems + ARCADE|CPS1|CPS2|NEOGEO) echo "fbneo" ;; + + # Other Systems + PCECD|PCE) echo "mednafen_pce" ;; + SUPERGRAFX) echo "mednafen_supergrafx" ;; + + *) echo "snes9x" ;; # Safe default + esac +} +``` + +### Core Availability by System + +``` +NES/FC: fceumm, nestopia, fceux +SNES/SFC: snes9x, bsnes, mednafen_snes +Genesis/MD: genesis_plus_gx, picodrive +N64: mupen64plus (via emu binary) +ARCADE: fbneo, mame2003plus, fbalpha2012 +PS1: pcsx_rearmed +PSX: mednafen_psx +GB/GBC: mgba, gambatte +GBA: mgba, visualboyadvance +NDS: drastic (not RetroArch) +PSP: PPSSPP (not RetroArch) +DC/NAOMI: Flycast (preferred) or fbneo +``` + +## Adding New Emulators + +### Step 1: Create Emulator Function Library + +Create `emu/lib/newemu_functions.sh`: + +```bash +#!/bin/bash +# emu/lib/newemu_functions.sh +# NewEmulator-specific functions + +# Required: main launch function +launch_newemu_game() { + local rom_path="$1" + + # Load configuration + source "${SCRIPT_DIR}/emu/lib/general_functions.sh" + + # Get core/renderer preference + local emulator_config="/Saves/SYSTEM/config.json" + local renderer=$(jq '.settings.renderer.selected' "$emulator_config") + + # Launch emulator + /path/to/newemu \ + --config=/etc/newemu.conf \ + --renderer="$renderer" \ + "$rom_path" +} + +# Optional: cleanup function +cleanup_newemu() { + # Kill any remaining processes + pkill -f newemu || true +} + +# Optional: save state function +save_newemu_state() { + # Save game state for autoresume +} +``` + +### Step 2: Update standard_launch.sh Router + +Edit in `emu/standard_launch.sh`: + +```bash +# Add to emulator detection switch +case "$EMU_NAME" in + NewSystem) + source "${SCRIPT_DIR}/emu/lib/newemu_functions.sh" + launch_newemu_game "$ROM_PATH" + ;; + # ... existing cases +esac +``` + +### Step 3: Create System Directory + +```bash +mkdir -p /Emu/NEWSYSTEM +mkdir -p /Emu/.emu_setup/NEWSYSTEM +mkdir -p /Saves/NEWSYSTEM/config +``` + +### Step 4: Create Symbolic Link + +```bash +ln -s /mnt/SDCARD/spruce/scripts/emu/standard_launch.sh \ + /mnt/SDCARD/Emu/NEWSYSTEM/launch.sh +``` + +### Step 5: Add Configuration Files + +Create `/Emu/.emu_setup/NEWSYSTEM/config.json`: + +```json +{ + "menuOptions": { + "Emulator_NEWSYSTEM": { + "selected": "newemu_core", + "options": ["newemu_core", "other_core"] + } + } +} +``` + +### Step 6: Test + +```bash +# Test rom launching +/Emu/NEWSYSTEM/launch.sh "/mnt/SDCARD/Roms/NEWSYSTEM/game.rom" +``` + +## Configuration Reference + +### Standard Launch Options + +```bash +# Via command line +/Emu/GB/launch.sh "/mnt/SDCARD/Roms/GB/game.gb" + +# Via configuration file +CONFIG="/Saves/GB/config.json" +jq '.menuOptions.Emulator_GB.selected' "$CONFIG" +``` + +### Environment Variables Used During Launch + +| Variable | Set By | Purpose | +| ------------------ | -------------------- | --------------------------- | +| `$PLATFORM` | helperFunctions.sh | Device model | +| `$EMU_NAME` | standard_launch.sh | Detected system | +| `$CORE` | general_functions.sh | Selected core/emulator | +| `$ROM_PATH` | (argument) | Game file path | +| `$RETROARCH` | (detected) | RetroArch binary path | +| `$LD_LIBRARY_PATH` | (set per emu) | Emulator-specific libraries | + +### Pre-Launch Setup + +These functions run before emulator launch: + +```bash +set_performance # Set CPU to max +led_effect_gaming # LED gaming mode +stop_network_services # Free up resources (optional) +start_network_services # Resume services on exit +``` + +### Post-Launch Cleanup + +These functions run after emulator exit: + +```bash +set_smart # Return to balanced CPU +led_effect_off # Turn off LED effects +log_game_end # Record playtime +start_network_services # Resume services +``` + +## Troubleshooting + +### Game Won't Launch + +1. Check ROM path exists: `/mnt/SDCARD/Roms//` +2. Verify system JSON has core setting: `jq '.menuOptions.Emulator_.selected' "$SYSTEM_JSON"` +3. Check emulator binary exists: `ls /mnt/SDCARD/Emu//` +4. Check library exists: `ls /mnt/SDCARD/RetroArch/cores/_libretro.so` + +### Wrong Emulator Launched + +1. Check system JSON preference: `get_config_value '.menuOptions.Emulator_.selected'` +2. Verify core exists for platform +3. Check core_mappings.sh has entry for system + +### Game Runs But Controls Don't Work + +1. Check button mapping in platform-specific retroarch.cfg +2. Verify RetroArch port of launch has input overlay enabled +3. Check device button codes in platform/\*.cfg + +### Game Crashes on Exit + +1. Check emulator cleanup code in handler +2. Verify no orphan processes: `ps aux | grep emu` +3. Check filesystem sync: `sync` before exit diff --git a/spruce/scripts/docs/ENVIRONMENT_VARIABLES.md b/spruce/scripts/docs/ENVIRONMENT_VARIABLES.md new file mode 100644 index 000000000..79fd2ba67 --- /dev/null +++ b/spruce/scripts/docs/ENVIRONMENT_VARIABLES.md @@ -0,0 +1,522 @@ +# Environment Variables Reference + +This document describes all environment variables used across SpruceOS scripts. These variables are set during system initialization and used throughout the script ecosystem for device abstraction, configuration, and runtime state management. + +## Table of Contents + +1. [System Configuration Variables](#system-configuration-variables) +2. [Hardware Path Variables](#hardware-path-variables) +3. [Button Mapping Variables](#button-mapping-variables) +4. [Directory and Path Variables](#directory-and-path-variables) +5. [Configuration Variables](#configuration-variables) +6. [State and Flags](#state-and-flags) +7. [Cross-Script Usage Patterns](#cross-script-usage-patterns) + +## System Configuration Variables + +### Core Platform Detection + +| Variable | Set By | Values | Usage | +| ------------------------ | ------------------------------ | -------------------------------------------------------- | ---------------------------------- | +| `$PLATFORM` | `helperFunctions.sh` | A30, MiyooMini, Flip, SmartPro, SmartProS, Pixel2, Brick | Device model identification | +| `$PLATFORM_ARCHITECTURE` | `helperFunctions.sh` (derived) | armhf, aarch64 | 32-bit vs 64-bit architecture | +| `$BRAND` | `platform/device.sh` | Miyoo, TrimUI | Device manufacturer | +| `$DISPLAY_ASPECT_RATIO` | Device functions | 16:9, 4:3 | Screen aspect ratio for UI scaling | + +### System JSON Configuration + +| Variable | Set By | Path | Usage | +| ---------------------- | -------------------- | ------------------------------------------- | ----------------------------------------- | +| `$SYSTEM_JSON` | `helperFunctions.sh` | `/mnt/SDCARD/spruce/-system.json` | Main settings file (all configs via `jq`) | +| `$SYSTEM_SETTINGS_DIR` | (derived) | `/mnt/SDCARD/spruce/` | Settings directory root | +| `$CONFIG_DIR` | (derived) | `/mnt/SDCARD/spruce/config/` | Persistent configuration storage | + +### Example: Reading Settings + +```bash +# From helperFunctions.sh +get_config_value '.menuOptions.System.swapfileSize.selected' +# Returns: "256MB" + +# Direct jq access +jq '.theme' "$SYSTEM_JSON" +# Returns: "SPRUCE" + +# WiFi state +jq '.wifi' "$SYSTEM_JSON" +# Returns: 0 or 1 +``` + +## Hardware Path Variables + +### Input Device Paths + +Button and input device paths are platform-specific and defined in platform configuration files (`platform/*.cfg`): + +| Variable | Example Value | Purpose | +| ------------------------ | ------------------- | -------------------------- | +| `$EVENT_PATH_POWER` | `/dev/input/event0` | Power button input event | +| `$EVENT_PATH_BUTTONS` | `/dev/input/event1` | Main button inputs | +| `$EVENT_PATH_JOYSTICK` | `/dev/input/event2` | Analog stick/D-pad inputs | +| `$EVENT_PATH_TOUCHPAD` | `/dev/input/event3` | Touchpad (if device has) | +| `$EVENT_PATH_LID` | `/dev/input/event4` | Lid sensor (if device has) | +| `$EVENT_PATH_BRIGHTNESS` | `/dev/input/event5` | Brightness button inputs | + +### Display and Backlight + +| Variable | Example Value | Purpose | +| ------------------------- | ----------------------------------- | ------------------------ | +| `$DEVICE_BRIGHTNESS_PATH` | `/sys/class/backlight/*/brightness` | Backlight device control | +| `$BRIGHTNESS_MAX` | 255 | Maximum brightness value | +| `$BRIGHTNESS_MIN` | 0 | Minimum brightness value | +| `$DISPLAY_DEVICE` | `/dev/fb0` | Framebuffer device | + +### LED Control (TrimUI only) + +| Variable | Example Value | Purpose | +| ------------- | --------------------------------------- | --------------------- | +| `$LED_PATH` | `/sys/class/leds/` | LED device base path | +| `$LED_LEFT` | `/sys/class/leds/led_left/brightness` | Left LED (RGB zone) | +| `$LED_RIGHT` | `/sys/class/leds/led_right/brightness` | Right LED (RGB zone) | +| `$LED_MIDDLE` | `/sys/class/leds/led_middle/brightness` | Middle LED (RGB zone) | +| `$LED_1` | `/sys/class/leds/led1/brightness` | Zone 1 LED | +| `$LED_2` | `/sys/class/leds/led2/brightness` | Zone 2 LED | + +### Audio Devices + +| Variable | Example Value | Purpose | +| ----------------------- | ------------------------------------- | --------------------- | +| `$DEVICE_AUDIO_OUTPUT` | `/dev/snd/pcmC*D0p` | Main audio output PCM | +| `$DEVICE_AUDIO_CONTROL` | `/dev/snd/controlC*` | Audio mixer control | +| `$ASOUND_RC_PATH` | `/etc/asound.rc` or `$HOME/.asoundrc` | ALSA configuration | + +### CPU and Thermal + +| Variable | Example Value | Purpose | +| --------------- | ------------------------------------------------------- | --------------------- | +| `$CPUFREQ_PATH` | `/sys/devices/system/cpu/cpu*/cpufreq/` | CPU frequency scaling | +| `$CPUGOV_PATH` | `/sys/devices/system/cpu/cpu*/cpufreq/scaling_governor` | CPU governor control | +| `$THERMAL_ZONE` | `/sys/class/thermal/thermal_zone0/temp` | Temperature sensor | + +### Battery and Power + +| Variable | Example Value | Purpose | +| ------------------- | --------------------------------------------- | -------------------------- | +| `$BATTERY_PATH` | `/sys/class/power_supply/battery/` | Battery status directory | +| `$BATTERY_CAPACITY` | `/sys/class/power_supply/battery/capacity` | Current battery percentage | +| `$BATTERY_VOLTAGE` | `/sys/class/power_supply/battery/voltage_now` | Battery voltage | +| `$POWER_STATUS` | `/sys/class/power_supply/battery/status` | Charging/Discharging state | + +## Button Mapping Variables + +All button mappings are defined in `platform/*.cfg` files. They contain key codes from Linux input subsystem: + +### Standard Button Keys + +```bash +$B_A # A/Cross button +$B_B # B/Circle button +$B_X # X/Square button +$B_Y # Y/Triangle button + +$B_L1 # Left shoulder 1 (L1) +$B_L2 # Left shoulder 2 (L2) +$B_R1 # Right shoulder 1 (R1) +$B_R2 # Right shoulder 2 (R2) + +$B_UP # D-Pad up +$B_DOWN # D-Pad down +$B_LEFT # D-Pad left +$B_RIGHT # D-Pad right + +$B_START # Start button +$B_SELECT # Select button +$B_MENU # Menu/Home button +$B_POWER # Power button +``` + +### Extended Button Keys + +```bash +$B_L3 # Left analog stick press +$B_R3 # Right analog stick press +$B_VOLUP # Volume up +$B_VOLDOWN # Volume down +$B_LID # Lid open/close event +``` + +### Example Usage in watchdogs + +```bash +# From buttons_watchdog.sh +getevent "$EVENT_PATH_BRIGHTNESS" | grep "EV_KEY" | \ + while IFS= read -r line; do + if echo "$line" | grep -q "$B_VOLUP"; then + increase_brightness + elif echo "$line" | grep -q "$B_VOLDOWN"; then + decrease_brightness + fi + done +``` + +## Directory and Path Variables + +### System Directories + +| Variable | Path | Purpose | +| ----------------- | ----------------------------- | ----------------------- | +| `$SPRUCE_HOME` | `/mnt/SDCARD/spruce/` | SpruceOS root directory | +| `$SPRUCE_SCRIPTS` | `/mnt/SDCARD/spruce/scripts/` | Scripts directory | +| `$SPRUCE_FLAGS` | `/mnt/SDCARD/spruce/flags/` | Runtime flag markers | +| `$SPRUCE_CACHE` | `/mnt/SDCARD/spruce/cache/` | Temporary cache files | +| `$THEMES_DIR` | `/mnt/SDCARD/Themes/` | UI theme files | +| `$ICONS_DIR` | `/mnt/SDCARD/Icons/` | Icon collections | + +### Emulator Directories + +| Variable | Path | Purpose | +| ------------ | -------------------- | ----------------------------- | +| `$EMUS_DIR` | `/mnt/SDCARD/Emu/` | Emulator installations | +| `$ROMS_DIR` | `/mnt/SDCARD/Roms/` | ROM files organized by system | +| `$SAVES_DIR` | `/mnt/SDCARD/Saves/` | Game saves and screenshots | +| `$BIOS_DIR` | `/mnt/SDCARD/BIOS/` | System BIOS files | + +### RetroArch Directories + +| Variable | Path | Purpose | +| --------------------- | --------------------------------- | ------------------------- | +| `$RA_CONFIG_DIR` | `/mnt/SDCARD/RetroArch/` | RetroArch main config | +| `$RA_PLATFORM_CONFIG` | `/mnt/SDCARD/RetroArch/platform/` | Platform-specific configs | +| `$RA_CORES_DIR` | `/mnt/SDCARD/RetroArch/cores/` | Libretro cores | +| `$RA_OVERLAYS` | `/mnt/SDCARD/RetroArch/overlays/` | Screen overlays | + +### Application Directories + +| Variable | Path | Purpose | +| ----------------- | ----------------------------- | -------------------- | +| `$APP_DIR` | `/mnt/SDCARD/App/` | Utility applications | +| `$PORTMASTER_DIR` | `/mnt/SDCARD/App/PortMaster/` | GamePorts collection | +| `$SCUMMVM_DIR` | `/mnt/SDCARD/App/ScummVM/` | ScummVM games | + +### Log Directories + +| Variable | Path | Purpose | +| ------------- | ------------------------------------- | -------------------- | +| `$LOG_DIR` | `/mnt/SDCARD/Saves/spruce/` | Main log directory | +| `$SYSTEM_LOG` | `/var/log/messages` | System kernel log | +| `$SPRUCE_LOG` | `/mnt/SDCARD/Saves/spruce/spruce.log` | Main application log | + +## Configuration Variables + +### Emulator Configuration Paths + +| Variable | Path | Purpose | +| --------------------- | --------------------------- | -------------------------- | +| `$EMU_CONFIG_FILE` | `/Emu//config.json` | Per-system user config | +| `$EMU_SETUP_DIR` | `/Emu/.emu_setup//` | Factory defaults | +| `$EMU_RUNTIME_CONFIG` | `/tmp/_runtime.cfg` | Runtime-specific overrides | + +### Specific Emulator Configs + +| Variable | Example | Purpose | +| ------------------ | --------------------------------------------------------- | --------------------------- | +| `$RA_CONFIG_FILE` | `/mnt/SDCARD/RetroArch/retroarch.cfg` | Main RetroArch config | +| `$RA_PLATFORM_CFG` | `/mnt/SDCARD/RetroArch/platform/retroarch-.cfg` | Platform-specific RA config | +| `$NDS_CONFIG_DIR` | `/Saves/NDS/` | DraStic configuration | +| `$PSP_CONFIG_DIR` | `/Saves/PSP/` | PPSSPP configuration | +| `$SCUMMVM_CONFIG` | `/Saves/SCUMMVM/scummvm.ini` | ScummVM configuration | + +### Network Configuration Files + +| Variable | Path | Purpose | +| ------------------- | ------------------------------- | -------------------- | +| `$SSH_KEY_DIR` | `/etc/dropbear/` | SSH host keys | +| `$SAMBA_CONFIG` | `/etc/samba/smb.conf` | Samba configuration | +| `$SYNCTHING_CONFIG` | `/home/root/.config/syncthing/` | Syncthing setup | +| `$SFTPGO_CONFIG` | `/etc/sftpgo/` | SFTPGo configuration | + +## State and Flags + +### Runtime State Variables + +| Variable | Scope | Set By | Usage | +| ------------------ | ------------- | ------------------ | ---------------------------------- | +| `$HOME` | Process-local | OS/Script | Working directory | +| `$PATH` | Process-local | OS/Platform files | Executable search path | +| `$LD_LIBRARY_PATH` | Process-local | Emulator launchers | Shared library paths | +| `$LD_PRELOAD` | Process-local | Audio setup | Library preloading for audio fixes | + +### Flag Files (in `/mnt/SDCARD/spruce/flags/`) + +Flag files serve as temporary markers for inter-process communication: + +| Flag | Set By | Checked By | Meaning | +| ---------------------- | ------------------------------ | ------------------ | -------------------------------- | +| `silentUnpacker` | archiveUnpacker.sh | principal.sh | Archive unpacking in progress | +| `first_boot_$PLATFORM` | firstboot.sh | runtime.sh | First boot detected for platform | +| `in_menu` | principal.sh | watchdogs | Currently in menu mode | +| `lastgame.lock` | principal.sh | runtimeHelper.sh | Last game for autoresume | +| `low_battery` | low_power_warning.sh | watchdogs | Battery critically low | +| `perfectOverlays` | applySetting/applyPerfectOs.sh | emulator launchers | Perfect overlays enabled | +| `log_verbose` | (user config) | Logging functions | Verbose logging mode | +| `pb.longpress` | power_button_watchdog_v2.sh | principal.sh | Power button long press detected | +| `sleep_helper_started` | sleep_helper.sh | idlemon scripts | Sleep mode active | +| `ota_completed` | runtimeHelper.sh | firstboot.sh | OTA update completed | + +### Temporary State (in `/tmp/`) + +| File | Set By | Checked By | Purpose | +| --------------------------- | --------------------------- | --------------- | ------------------------- | +| `/tmp/cmd_to_run.sh` | PyUI/MainUI | principal.sh | Command to execute next | +| `/tmp/powerbtn` | power_button_watchdog_v2.sh | sleep_helper.sh | Power button state | +| `/tmp/sleep_helper_started` | sleep_helper.sh | watchdogs | Sleep mode marker | +| `/tmp/host_msg` | networkservices.sh | (network apps) | Network message broadcast | +| `/tmp/miyoo_inputd/` | (input daemon) | watchdogs | Input event sockets | + +## Cross-Script Usage Patterns + +### Configuration Reading Pattern + +Most scripts follow this pattern for reading settings: + +```bash +#!/bin/bash + +# Source helper functions (loads $SYSTEM_JSON) +source /mnt/SDCARD/spruce/scripts/helperFunctions.sh + +# Read setting using helper function +SETTING_VALUE=$(get_config_value '.menuOptions.System.swapfileSize.selected') + +# Or direct jq access +WIFI_STATE=$(jq '.wifi' "$SYSTEM_JSON") + +# Read platform-specific value +CPU_MODE=$(jq ".menuOptions.Governor_${PLATFORM}.selected" "$SYSTEM_JSON") +``` + +### Device Detection Pattern + +```bash +#!/bin/bash + +source /mnt/SDCARD/spruce/scripts/helperFunctions.sh + +# $PLATFORM is now set to detected device +case "$PLATFORM" in + A30|MiyooMini) + # 32-bit device handling + source platform/device_functions/common32bit.sh + ;; + Flip|SmartPro|SmartProS|Pixel2) + # 64-bit device handling + source platform/device_functions/common64bit.sh + ;; +esac + +# Load platform-specific functions +source platform/device_functions/${PLATFORM}.sh +``` + +### Setting Values with jq + +```bash +#!/bin/bash + +# Update a setting +NEW_SWAP_SIZE="512MB" +jq ".menuOptions.System.swapfileSize.selected = \"$NEW_SWAP_SIZE\"" "$SYSTEM_JSON" > /tmp/system.json.tmp +mv /tmp/system.json.tmp "$SYSTEM_JSON" + +# Multi-value update +jq '.menuOptions.Governor.selected = "performance" | .menuOptions.System.swapfileSize.selected = "512MB"' \ + "$SYSTEM_JSON" > /tmp/system.json.tmp +mv /tmp/system.json.tmp "$SYSTEM_JSON" +``` + +### Flag Management Pattern + +```bash +#!/bin/bash + +source /mnt/SDCARD/spruce/scripts/helperFunctions.sh + +# Add a flag (persistent in /mnt/SDCARD/spruce/flags/) +flag_add "myProcessRunning" + +# Check if flag exists +if flag_check "myProcessRunning"; then + echo "Process is running" +fi + +# Check with temporary flag (in /tmp) +flag_add "tmpMarker" --tmp + +# Remove flag +flag_remove "myProcessRunning" +``` + +## Platform-Specific Variable Sets + +### Miyoo A30 (32-bit) + +```bash +$PLATFORM="A30" +$PLATFORM_ARCHITECTURE="armhf" +$BRAND="Miyoo" +# Plus A30-specific button mappings and paths from platform/A30.cfg +``` + +### Miyoo Mini (32-bit) + +```bash +$PLATFORM="MiyooMini" +$PLATFORM_ARCHITECTURE="armhf" +$BRAND="Miyoo" +# Plus MiyooMini-specific button mappings and paths from platform/MiyooMini.cfg +``` + +### Miyoo Flip (64-bit) + +```bash +$PLATFORM="Flip" +$PLATFORM_ARCHITECTURE="aarch64" +$BRAND="Miyoo" +# Plus Flip-specific button mappings and paths from platform/Flip.cfg +``` + +### TrimUI SmartPro (64-bit) + +```bash +$PLATFORM="SmartPro" +$PLATFORM_ARCHITECTURE="aarch64" +$BRAND="TrimUI" +# Plus SmartPro-specific RGB LED paths and button mappings from platform/SmartPro.cfg +``` + +### TrimUI Brick (64-bit) + +```bash +$PLATFORM="Brick" +$PLATFORM_ARCHITECTURE="aarch64" +$BRAND="TrimUI" +# Plus Brick-specific button mappings from platform/Brick.cfg +``` + +### TrimUI SmartProS (64-bit) + +```bash +$PLATFORM="SmartProS" +$PLATFORM_ARCHITECTURE="aarch64" +$BRAND="TrimUI" +# Plus SmartProS-specific button mappings from platform/SmartProS.cfg +``` + +## Accessing Variables in Scripts + +### Best Practice: Always Source helperFunctions.sh First + +```bash +#!/bin/bash +# This ensures all base variables are loaded + +source /mnt/SDCARD/spruce/scripts/helperFunctions.sh + +# Now $PLATFORM, $SYSTEM_JSON, and other core variables are available +echo "Running on $PLATFORM with system config: $SYSTEM_JSON" + +# Load platform-specific functions +source /mnt/SDCARD/spruce/scripts/platform/device_functions/${PLATFORM}.sh + +# Use platform-specific variables and functions +set_performance_mode +``` + +### For Scripts That Need Minimal Output + +```bash +#!/bin/bash +# Minimal initialization for background watchdogs + +source /mnt/SDCARD/spruce/scripts/helperFunctions.sh 2>/dev/null + +# Use variables but suppress helper function logs +PLATFORM_ARCH="$PLATFORM_ARCHITECTURE" +``` + +## Common Variable Combinations + +### For Emulator Configuration + +```bash +# System-specific config file +$SAVES_DIR/$SYSTEM_NAME/config.json + +# Platform override config +$SAVES_DIR/$SYSTEM_NAME/${PLATFORM}_config.json + +# Global emulator config +$RA_PLATFORM_CONFIG/retroarch-${PLATFORM}.cfg +``` + +### For Device Control + +```bash +# Device hardware paths +read -r CURRENT_BRIGHTNESS < "$DEVICE_BRIGHTNESS_PATH" + +# Button input +getevent "$EVENT_PATH_BUTTONS" | grep "$B_A" + +# LED control +echo 255 > "$LED_LEFT" +``` + +### For Configuration Access + +```bash +# Read single value +SETTING=$(get_config_value '.menuOptions.path.to.setting.selected') + +# Read with jq +VALUE=$(jq '.menuOptions.System.swapfileSize.selected' "$SYSTEM_JSON") + +# Update setting +jq ".menuOptions.System.key = \"value\"" "$SYSTEM_JSON" > /tmp/system.json.tmp && \ + mv /tmp/system.json.tmp "$SYSTEM_JSON" +``` + +## Logging and Verbosity + +### Log Verbosity Control + +```bash +# Check if verbose logging is enabled +if flag_check "log_verbose"; then + echo "[VERBOSE] Debug information" | tee -a "$SPRUCE_LOG" +else + # Normal logging without debug + echo "[INFO] Message" >> "$SPRUCE_LOG" +fi +``` + +### Audit and History + +```bash +# Battery history +echo "$(date): Battery at $(cat $BATTERY_CAPACITY)%" >> /mnt/SDCARD/Saves/spruce/battery_log.txt + +# Activity logging +echo "$(date): Game launched: $GAME_NAME" >> "$SPRUCE_LOG" +``` + +## Notes and Best Practices + +1. **Always source `helperFunctions.sh` before using `$PLATFORM` or `$SYSTEM_JSON`** +2. **Use `get_config_value()` function** rather than direct `jq` when available +3. **Device paths are platform-specific** - always reference variables instead of hardcoding paths +4. **Flag files should be used** for inter-script communication instead of temporary files +5. **Log files use append mode** (`>>`) to preserve history; use `tee -a` for console + file output +6. **JSON updates should write to temporary file first**, then `mv` to ensure atomicity +7. **Button mappings vary by device** - never hardcode key codes, always use `$B_*` variables +8. **CPU frequency paths** are architecture-specific; use platform abstraction functions instead diff --git a/spruce/scripts/docs/FUNCTIONS.md b/spruce/scripts/docs/FUNCTIONS.md new file mode 100644 index 000000000..cfce960e6 --- /dev/null +++ b/spruce/scripts/docs/FUNCTIONS.md @@ -0,0 +1,1298 @@ +# Functions Reference + +This document provides a comprehensive reference of all functions defined across SpruceOS scripts, organized by category and subsystem. + +## Table of Contents + +1. [Helper Functions](#helper-functions) +2. [Device Control Functions](#device-control-functions) +3. [Emulator Control Functions](#emulator-control-functions) +4. [Network Service Functions](#network-service-functions) +5. [Watchdog Functions](#watchdog-functions) +6. [System Management Functions](#system-management-functions) +7. [Configuration Functions](#configuration-functions) + +## Helper Functions + +Helper functions are core utilities defined in `helperFunctions.sh`, sourced by most scripts. + +### Device Detection and Initialization + +#### `detect_device()` + +**Purpose:** Detect the current device platform by reading `/proc/cpuinfo` + +**Usage:** + +```bash +detect_device +``` + +**Sets:** + +- `$PLATFORM` - Device model (A30, MiyooMini, Flip, SmartPro, SmartProS, Pixel2, Brick) +- `$PLATFORM_ARCHITECTURE` - Architecture (armhf or aarch64) + +**Example:** + +```bash +source helperFunctions.sh +# Platform variables are automatically set during sourcing +echo "Running on: $PLATFORM ($PLATFORM_ARCHITECTURE)" +``` + +### Configuration Functions + +#### `get_config_value(path)` + +**Purpose:** Retrieve a configuration value from the system JSON file using jq path + +**Parameters:** + +- `path` - jq path to the configuration key (e.g., `.menuOptions.System.swapfileSize.selected`) + +**Returns:** Configuration value or empty string if not found + +**Usage:** + +```bash +SWAP_SIZE=$(get_config_value '.menuOptions.System.swapfileSize.selected') +echo "Swap size: $SWAP_SIZE" # Output: "256MB" +``` + +**Common Paths:** + +```bash +# System settings +get_config_value '.menuOptions.System.swapfileSize.selected' +get_config_value '.menuOptions.System.useZRAM.selected' +get_config_value '.menuOptions.System.overclockSpeedA30.selected' +get_config_value '.menuOptions.System.rumbleIntensity.selected' +get_config_value '.menuOptions.System.enableLidSensor.selected' + +# Network settings +get_config_value '.menuOptions.Network.enableSamba.selected' +get_config_value '.menuOptions.Network.enableSSH.selected' +get_config_value '.menuOptions.Network.enableSFTPGo.selected' +get_config_value '.menuOptions.Network.enableSyncthing.selected' + +# Emulator settings +get_config_value '.menuOptions.Emulator.raAutoSave.selected' +get_config_value '.menuOptions.Emulator.raAutoLoad.selected' +get_config_value '.menuOptions.Emulator.perfectOverlays.selected' + +# Device-specific +get_config_value ".menuOptions.Governor_${PLATFORM}.selected" +get_config_value ".menuOptions.Governor.selected" + +# Theme and general +get_config_value '.theme' +get_config_value '.wifi' +``` + +#### `set_config_value(path, value)` + +**Purpose:** Update a configuration value in the system JSON file + +**Parameters:** + +- `path` - jq path to the configuration key +- `value` - New value to set + +**usage:** + +```bash +set_config_value '.menuOptions.System.swapfileSize.selected' '512MB' +set_config_value '.menuOptions.Network.enableSSH.selected' 'True' +``` + +**Important:** Uses atomic write with temporary file to prevent corruption: + +```bash +jq ".$key = $value" "$SYSTEM_JSON" > /tmp/system.json.tmp && \ + mv /tmp/system.json.tmp "$SYSTEM_JSON" +``` + +### Flag Management Functions + +#### `flag_add(name [--tmp])` + +**Purpose:** Create a flag file marker for inter-process communication + +**Parameters:** + +- `name` - Flag file name (no extension) +- `--tmp` - Optional: create in `/tmp` instead of `/mnt/SDCARD/spruce/flags/` + +**Usage:** + +```bash +# Persistent flag (survives reboot) +flag_add "myprocess_running" + +# Temporary flag (cleared on reboot) +flag_add "process_temp" --tmp +``` + +**Stored In:** + +- Without `--tmp`: `/mnt/SDCARD/spruce/flags/` +- With `--tmp`: `/tmp/` + +#### `flag_check(name [--tmp])` + +**Purpose:** Check if a flag file exists + +**Parameters:** + +- `name` - Flag file name to check +- `--tmp` - Optional: check in `/tmp` instead of persistent directory + +**Returns:** 0 (success) if flag exists, 1 if not + +**Usage:** + +```bash +if flag_check "process_running"; then + echo "Process is currently running" +else + echo "Process is not running" +fi +``` + +#### `flag_remove(name [--tmp])` + +**Purpose:** Delete a flag file + +**Parameters:** + +- `name` - Flag file name to remove +- `--tmp` - Optional: remove from `/tmp` instead of persistent directory + +**Usage:** + +```bash +# When process completes +flag_remove "process_running" +flag_remove "temp_marker" --tmp +``` + +### Logging Functions + +#### `log_message(message)` + +**Purpose:** Log a timestamped message to the main log file + +**Parameters:** + +- `message` - Text to log + +**Usage:** + +```bash +log_message "Game launched: Pac-Man" +log_message "Syncthing sync completed" +``` + +**Output:** `[TIMESTAMP] message` appended to `/mnt/SDCARD/Saves/spruce/spruce.log` + +#### `log_error(message)` + +**Purpose:** Log an error message with ERROR prefix + +**Parameters:** + +- `message` - Error description + +**Usage:** + +```bash +log_error "Failed to mount SD card" +log_error "RetroArch exited with code: $?" +``` + +### Directory Functions + +#### `ensure_directory(path)` + +**Purpose:** Create a directory tree if it doesn't exist + +**Parameters:** + +- `path` - Full directory path + +**Usage:** + +```bash +ensure_directory "/mnt/SDCARD/Saves/GB/config" +ensure_directory "$SAVES_DIR/NDS/Backup" +``` + +### CPU/Governor Functions (Generic) + +#### `set_cpu_governor(governor_name)` + +**Purpose:** Change CPU governor (generic implementation, platform-specific in device files) + +**Parameters:** + +- `governor_name` - Governor mode: "powersave", "performance", "smart", "overclock" + +**Usage:** + +```bash +set_cpu_governor "performance" # Gaming mode +set_cpu_governor "powersave" # Power saving mode +set_cpu_governor "smart" # Smart CPU management +set_cpu_governor "overclock" # Maximum performance (A30 only) +``` + +## Device Control Functions + +Device control functions provide a unified interface across all platforms. These are implemented in `platform/device_functions/*.sh` files. + +### Required Device Functions (All Platforms) + +Each platform file (`A30.sh`, `MiyooMini.sh`, `Flip.sh`, `SmartPro.sh`, etc.) implements these core functions: + +#### `get_python_path()` + +**Purpose:** Return the path to the Python executable for this platform + +**Returns:** Absolute path to Python binary + +**Usage:** + +```bash +source platform/device_functions/${PLATFORM}.sh +PYTHON=$(get_python_path) +$PYTHON /path/to/script.py +``` + +**Platform Examples:** + +```bash +# Miyoo A30 +get_python_path # Returns: /usr/bin/python3 + +# TrimUI SmartPro +get_python_path # Returns: /usr/bin/python3.9 +``` + +#### `get_config_path()` + +**Purpose:** Return the base path for platform-specific configuration + +**Returns:** Configuration base directory path + +**Usage:** + +```bash +CONFIG_PATH=$(get_config_path) +cp "$CONFIG_PATH/retroarch.cfg" /tmp/retroarch_backup.cfg +``` + +#### `cores_online()` + +**Purpose:** Get number of CPU cores available online + +**Returns:** Integer count of active cores + +**Usage:** + +```bash +CORES=$(cores_online) +echo "CPU cores available: $CORES" +``` + +#### `set_smart()` + +**Purpose:** Set CPU governor to smart/balanced mode + +**Usage:** + +```bash +set_smart # Balanced performance and power consumption +``` + +#### `set_performance()` + +**Purpose:** Set CPU governor to performance mode (maximum CPU frequency) + +**Usage:** + +```bash +set_performance # Before launching game +``` + +#### `set_overclock()` + +**Purpose:** Set CPU to overclocked frequency (if supported) + +**Note:** Available only on A30. Other platforms will log "not supported" + +**Usage:** + +```bash +if [ "$PLATFORM" = "A30" ]; then + set_overclock # 1344 MHz on A30 +fi +``` + +#### `set_powersave()` + +**Purpose:** Set CPU governor to power saving mode (reduced frequency) + +**Usage:** + +```bash +set_powersave # Extended battery life +``` + +#### `vibrate([force] [duration])` + +**Purpose:** Trigger device vibration/rumble + +**Parameters:** + +- `force` - Optional: vibration intensity (0-100, default: based on config) +- `duration` - Optional: milliseconds (default: 100ms) + +**Usage:** + +```bash +vibrate # Default rumble +vibrate 50 # 50% intensity +vibrate 100 200 # Full intensity for 200ms +``` + +**Supported Platforms:** + +- A30, MiyooMini, Flip, SmartPro, SmartProS (via GPIO) +- Brick (limited support) +- Pixel2 (limited support) + +#### `display_kill()` + +**Purpose:** Terminate all display-related processes (SDL, framebuffer, X11) + +**Usage:** + +```bash +display_kill # Before emulator launch with custom display settings +``` + +#### `display(text [x] [y] [duration])` + +**Purpose:** Display on-screen text or image + +**Parameters:** + +- `text` - Text message or image file path +- `x` - Optional: X coordinate (default: center) +- `y` - Optional: Y coordinate (default: center) +- `duration` - Optional: display time in seconds (default: 2) + +**Usage:** + +```bash +display "Loading game..." +display "Game saved" 50 50 3 # 3 seconds at position (50, 50) +display "/path/to/image.png" # Display image +``` + +#### `rgb_led(color [zone])` + +**Purpose:** Control RGB LED (TrimUI devices only) + +**Parameters:** + +- `color` - Color name: "red", "green", "blue", "yellow", "cyan", "magenta", "white", "off" +- `zone` - Optional: LED zone (left, right, middle, 1, 2) - default: all zones + +**Usage (TrimUI only):** + +```bash +rgb_led "red" # All red +rgb_led "green" "left" # Left LED green +rgb_led "blue" "middle" # Middle LED blue +rgb_led "off" "right" # Turn right LED off +``` + +**Note:** On Miyoo devices, this function will log "not supported" + +#### `enable_or_disable_rgb([state])` + +**Purpose:** Toggle RGB LED on/off (TrimUI only) + +**Parameters:** + +- `state` - Optional: "on" or "off" (default: toggle) + +**Usage:** + +```bash +enable_or_disable_rgb "on" # Enable all LEDs +enable_or_disable_rgb "off" # Disable all LEDs +enable_or_disable_rgb # Toggle current state +``` + +#### `device_init()` + +**Purpose:** Initialize device hardware (run once at boot) + +**Usage:** + +```bash +# Called by runtime.sh during system startup +device_init +``` + +**Performs:** + +- GPIO setup +- Brightness initialization +- LED initialization +- Audio paths setup +- Thermal management initialization + +### Platform-Specific Advanced Functions + +#### `set_brightness(level)` (A30, Flip, SmartPro, SmartProS) + +**Purpose:** Set display brightness to specific level + +**Parameters:** + +- `level` - Brightness level: 0-10 (10 = maximum) + +**Usage:** + +```bash +set_brightness 5 # 50% brightness +set_brightness 10 # Maximum brightness +set_brightness 1 # Minimum brightness +``` + +#### `get_brightness()` (All platforms) + +**Purpose:** Get current display brightness level + +**Returns:** Current brightness level (0-10 or percentage) + +**Usage:** + +```bash +CURRENT=$(get_brightness) +echo "Current brightness: $CURRENT" +``` + +#### `get_battery_percentage()` (All platforms) + +**Purpose:** Read current battery percentage + +**Returns:** Battery percentage (0-100) + +**Usage:** + +```bash +BATTERY=$(get_battery_percentage) +if [ "$BATTERY" -lt 10 ]; then + echo "Battery low!" +fi +``` + +#### `get_temperature()` (Thermal sensors) + +**Purpose:** Read CPU temperature + +**Returns:** Temperature in Celsius + +**Usage:** + +```bash +TEMP=$(get_temperature) +if [ "$TEMP" -gt 80 ]; then + log_error "Overheating: ${TEMP}°C" +fi +``` + +#### `headphone_connected()` (Flip only) + +**Purpose:** Check if headphones are plugged in + +**Returns:** 0 if connected, 1 if not + +**Usage:** + +```bash +if headphone_connected; then + echo "Using headphones" +fi +``` + +#### `lid_open()` (Devices with lid sensor) + +**Purpose:** Check if device lid is open + +**Returns:** 0 if open, 1 if closed + +**Usage:** + +```bash +if lid_open; then + echo "Lid is open - device active" +else + echo "Lid is closed - device may sleep" +fi +``` + +## Emulator Control Functions + +Emulator functions are located in `emu/lib/*.sh` and handle emulator-specific launching and configuration. + +### General Emulator Functions (general_functions.sh) + +#### `set_emu_core_from_emu_json(system_name)` + +**Purpose:** Read emulator core preference from system JSON and set `$CORE` variable + +**Parameters:** + +- `system_name` - System name (e.g., "GB", "GBA", "N64") + +**Usage:** + +```bash +set_emu_core_from_emu_json "GBA" # Sets $CORE based on JSON preference +echo "Using core: $CORE" +``` + +**Logic:** + +1. Check system-specific override: `.menuOptions.Emulator_$SYSTEM.selected` +2. Check platform override: `.menuOptions.Emulator_${SYSTEM}_${PLATFORM}.selected` +3. Fall back to default core for system + +#### `get_emu_startup_path(emu_name game_path)` + +**Purpose:** Build the complete startup command for an emulator + +**Parameters:** + +- `emu_name` - Emulator name (e.g., "retroarch", "drastic", "ppsspp") +- `game_path` - Full path to game ROM/file + +**Returns:** Executable command string + +**Usage:** + +```bash +CMD=$(get_emu_startup_path "retroarch" "/mnt/SDCARD/Roms/GB/Game.gb") +eval "$CMD" # Execute the command +``` + +### RetroArch Functions (ra_functions.sh) + +#### `load_ra_config_for_system(system_name)` + +**Purpose:** Load RetroArch configuration for specific system + +**Parameters:** + +- `system_name` - System name + +**Usage:** + +```bash +load_ra_config_for_system "GB" +# Sets up RetroArch with Game Boy-specific config +``` + +#### `save_ra_screenshot(game_name)` + +**Purpose:** Save a screenshot from RetroArch + +**Parameters:** + +- `game_name` - Name of the game that was running + +**Usage:** + +```bash +save_ra_screenshot "Super Mario Bros 3" +# Screenshot saved to /mnt/SDCARD/Saves/screenshots/ +``` + +#### `get_ra_core_for_system(system_name)` + +**Purpose:** Get the default RetroArch core for a system + +**Parameters:** + +- `system_name` - System name + +**Returns:** Core name (e.g., "genesis_plus_gx", "snes9x") + +**Usage:** + +```bash +CORE=$(get_ra_core_for_system "MD") # Returns "genesis_plus_gx" +``` + +### DraStic Function (drastic_functions.sh) + +#### `launch_drastic_nds(game_path)` + +**Purpose:** Launch Nintendo DS game using DraStic emulator + +**Parameters:** + +- `game_path` - Full path to NDS ROM file + +**Usage:** + +```bash +launch_drastic_nds "/mnt/SDCARD/Roms/NDS/Pokemon Diamond.nds" +``` + +**Features:** + +- Platform-specific launcher (32-bit vs 64-bit) +- Configuration loading +- Overlay setup (optional) +- Save state management + +### PPSSPP Functions (ppsspp_functions.sh) + +#### `launch_ppsspp_psp(game_path)` + +**Purpose:** Launch PlayStation Portable game using PPSSPP + +**Parameters:** + +- `game_path` - Full path to PSP ROM file (.iso or .cso) + +**Usage:** + +```bash +launch_ppsspp_psp "/mnt/SDCARD/Roms/PSP/Final Fantasy.iso" +``` + +**Features:** + +- Per-platform configuration +- PSP-specific overlay support +- Controller mapping per device + +### ScummVM Functions (scummvm_functions.sh) + +#### `launch_scummvm_game(game_id)` + +**Purpose:** Launch adventure game using ScummVM + +**Parameters:** + +- `game_id` - ScummVM game identifier + +**Usage:** + +```bash +launch_scummvm_game "monkey" # Monkey Island +launch_scummvm_game "simon1" # Simon the Sorcerer +``` + +#### `scan_scummvm_library()` + +**Purpose:** Discover installed ScummVM games + +**Returns:** List of available game IDs + +**Usage:** + +```bash +GAMES=$(scan_scummvm_library) +for GAME in $GAMES; do + echo "Found ScummVM game: $GAME" +done +``` + +### LED Control Functions (led_functions.sh) + +#### `led_effect_startup()` + +**Purpose:** Show LED startup effect + +**Usage:** + +```bash +led_effect_startup # Boot animation +``` + +#### `led_effect_gaming()` + +**Purpose:** Set LED to gaming profile + +**Usage:** + +```bash +led_effect_gaming # Subtle LEDs during gameplay +``` + +#### `led_effect_charging()` + +**Purpose:** Set LED to charging indicator + +**Usage:** + +```bash +led_effect_charging # Pulsing LED while charging +``` + +#### `led_effect_low_battery()` + +**Purpose:** Set LED to low battery warning + +**Usage:** + +```bash +led_effect_low_battery # Rapid flashing LED +``` + +#### `led_effect_off()` + +**Purpose:** Turn off all LED effects + +**Usage:** + +```bash +led_effect_off # Disable LEDs +``` + +### Game Time Tracking Functions (gtt_functions.sh) + +#### `log_game_start(game_name system_name)` + +**Purpose:** Record when a game is started + +**Parameters:** + +- `game_name` - Display name of the game +- `system_name` - System/emulator name + +**Usage:** + +```bash +log_game_start "Super Mario Bros" "NES" +``` + +#### `log_game_end(game_name)` + +**Purpose:** Record when a game is ended and calculate play time + +**Parameters:** + +- `game_name` - Display name of the game + +**Usage:** + +```bash +log_game_end "Super Mario Bros" +# Output: "Played for 1 hour 23 minutes" +``` + +### Network Functions (network_functions.sh) + +#### `stop_network_services()` + +**Purpose:** Gracefully stop all network services + +**Usage:** + +```bash +stop_network_services # Called before emulator launch +``` + +**Stops:** + +- Syncthing daemon +- SSH server +- SMB/Samba +- SFTPGo +- Web server + +#### `start_network_services()` + +**Purpose:** Restart network services after emulator + +**Usage:** + +```bash +start_network_services # Called after emulator exit +``` + +## Network Service Functions + +Network service functions are located in `network/*.sh` files. + +### SSH Functions (sshFunctions.sh) + +#### `dropbear_generate_keys()` + +**Purpose:** Generate SSH host keys for Dropbear + +**Usage:** + +```bash +source network/sshFunctions.sh +dropbear_generate_keys +``` + +#### `start_ssh_process()` + +**Purpose:** Start SSH server (Dropbear) + +**Usage:** + +```bash +start_ssh_process +# SSH now available on port 22 +``` + +#### `stop_ssh_process()` + +**Purpose:** Stop SSH server + +**Usage:** + +```bash +stop_ssh_process +``` + +### Samba Functions (sambaFunctions.sh) + +#### `start_samba_process()` + +**Purpose:** Start Samba (SMB file sharing) + +**Usage:** + +```bash +source network/sambaFunctions.sh +start_samba_process +# Samba shares now available +``` + +#### `stop_samba_process()` + +**Purpose:** Stop Samba service + +**Usage:** + +```bash +stop_samba_process +``` + +### Syncthing Functions (syncthingFunctions.sh) + +#### `generate_syncthing_config()` + +**Purpose:** Generate initial Syncthing configuration + +**Usage:** + +```bash +source network/syncthingFunctions.sh +generate_syncthing_config +``` + +#### `repair_syncthing_config()` + +**Purpose:** Fix corrupted Syncthing configuration + +**Usage:** + +```bash +repair_syncthing_config +``` + +#### `start_syncthing_process()` + +**Purpose:** Start Syncthing sync daemon + +**Usage:** + +```bash +start_syncthing_process +# Syncthing daemon running on port 8384 +``` + +#### `run_syncthing()` + +**Purpose:** Run Syncthing in foreground (main run mode) + +**Usage:** + +```bash +run_syncthing +``` + +### SFTPGo Functions (sftpgoFunctions.sh) + +#### `start_sftpgo_process()` + +**Purpose:** Start SFTPGo SFTP server + +**Usage:** + +```bash +source network/sftpgoFunctions.sh +start_sftpgo_process +``` + +#### `stop_sftpgo_process()` + +**Purpose:** Stop SFTPGo service + +**Usage:** + +```bash +stop_sftpgo_process +``` + +### Darkhttpd Functions (darkhttpdFunctions.sh) + +#### `start_darkhttpd_process()` + +**Purpose:** Start Darkhttpd web server + +**Usage:** + +```bash +source network/darkhttpdFunctions.sh +start_darkhttpd_process +``` + +#### `stop_darkhttpd_process()` + +**Purpose:** Stop Darkhttpd server + +**Usage:** + +```bash +stop_darkhttpd_process +``` + +## Watchdog Functions + +Watchdog functions run continuously to monitor hardware events. + +### Power Button Watchdog (power_button_watchdog_v2.sh) + +#### `detect_power_button_event()` + +**Purpose:** Monitor and detect power button press/release events + +**Detects:** + +- Short press: Sleep/wake toggle +- Long press (2s): Poweroff + +**Usage:** + +```bash +while true; do + detect_power_button_event + sleep 0.1 +done +``` + +### Home Button Watchdog (homebutton_watchdog.sh) + +#### `detect_home_button()` + +**Purpose:** Monitor home button and trigger appropriate action + +**Actions:** + +- Pause/Resume DraStic (if running NDS) +- Terminate port if running game port +- Take screenshot if in compatible app + +**Usage:** + +```bash +detect_home_button +``` + +### Lid Watchdog (lid_watchdog_v2.sh) + +#### `detect_lid_state()` + +**Purpose:** Monitor lid sensor for open/close events + +**Usage:** + +```bash +while true; do + detect_lid_state + sleep 1 +done +``` + +### Brightness Button Watchdog (buttons_watchdog.sh) + +#### `handle_brightness_button()` + +**Purpose:** Monitor brightness buttons and adjust display + +**Usage:** + +```bash +handle_brightness_button +``` + +## System Management Functions + +### Power Management Functions (save_poweroff.sh) + +#### `graceful_shutdown()` + +**Purpose:** Perform graceful system shutdown with cleanup + +**Actions:** + +1. Log shutdown event +2. Stop all services +3. Kill running emulators +4. Sync Syncthing +5. Unmount USB storage +6. Trigger stage2 poweroff + +**Usage:** + +```bash +graceful_shutdown +``` + +### Archive Unpacking Functions (archiveUnpacker.sh) + +#### `finish_unpacking()` + +**Purpose:** Unpack pre-queued archive files + +**Usage:** + +```bash +finish_unpacking +# Processes any pending .zip or .7z files before menu launch +``` + +### First Boot Functions (firstboot.sh) + +#### `run_first_boot_setup()` + +**Purpose:** Initialize system on first boot + +**Tasks:** + +- Generate SSH keys +- Extract PortMaster bundle +- Extract ScummVM games +- Set initial configuration +- Create necessary directories + +**Usage:** + +```bash +run_first_boot_setup +``` + +### Swap Management Functions (set_up_swap.sh) + +#### `create_swapfile(size)` + +**Purpose:** Create swapfile with specified size + +**Parameters:** + +- `size` - Size in MB (128, 256, 512) + +**Usage:** + +```bash +create_swapfile 256 # Create 256MB swapfile +``` + +#### `enable_swapfile()` + +**Purpose:** Enable the swapfile + +**Usage:** + +```bash +enable_swapfile +``` + +#### `disable_swapfile()` + +**Purpose:** Disable and remove swapfile + +**Usage:** + +```bash +disable_swapfile +``` + +### ZRAM Management Functions (enable_zram.sh, disable_zram.sh) + +#### `enable_zram_compression(algorithm)` + +**Purpose:** Enable ZRAM memory compression + +**Parameters:** + +- `algorithm` - Compression method: "lz4" or "lzo" + +**Usage:** + +```bash +enable_zram_compression "lz4" +# Memory compression now active +``` + +#### `disable_zram_compression()` + +**Purpose:** Disable ZRAM compression + +**Usage:** + +```bash +disable_zram_compression +``` + +## Configuration Functions + +### RetroArch Configuration (retroarch_utils.sh) + +#### `update_ra_config_file_with_new_setting(config_file setting value)` + +**Purpose:** Update a RetroArch configuration setting + +**Parameters:** + +- `config_file` - Path to RetroArch .cfg file +- `setting` - Configuration key name +- `value` - New value + +**Usage:** + +```bash +update_ra_config_file_with_new_setting \ + "/mnt/SDCARD/RetroArch/retroarch.cfg" \ + "video_scale_integer" \ + "true" +``` + +### Settings Application Functions (applySetting/\*.sh) + +#### `apply_perfect_overlays()` + +**Purpose:** Apply Perfect Overlays to Game Boy systems + +**Usage:** + +```bash +apply_perfect_overlays +# GB, GBC, GBA now have enhanced overlays +``` + +#### `apply_cpu_settings()` + +**Purpose:** Apply CPU governor settings from configuration + +**Usage:** + +```bash +apply_cpu_settings +``` + +#### `apply_display_settings()` + +**Purpose:** Apply display brightness and resolution settings + +**Usage:** + +```bash +apply_display_settings +``` + +## Function Naming Conventions + +### Device Functions + +All device-specific files implement this pattern: + +```bash +# In: platform/device_functions/.sh +get_() # Retrieve/read operation +set_() # Change/write operation +``` + +### Emulator Functions + +```bash +# In: emu/lib/_functions.sh +launch__() # Start emulator +load__configs() # Load configuration +save__configs() # Save state +get__core_for_() # Retrieve core mapping +``` + +### Network Functions + +```bash +# In: network/Functions.sh +start__process() # Start service daemon +stop__process() # Stop service daemon +generate__config() # Create initial config (Syncthing) +repair__config() # Fix corrupted config (Syncthing) +``` + +### Watchdog Functions + +```bash +# In: *_watchdog.sh +detect_() # Monitor and detect event +handle_() # React to detected event +``` + +## Best Practices for Function Usage + +1. **Always source helper functions first**: Most scripts depend on `helperFunctions.sh` +2. **Use consistent error handling**: Check return codes and log errors +3. **Avoid hardcoded paths**: Use provided `$*_DIR` variables +4. **Use functions instead of duplicating code**: Reduces maintenance burden +5. **Document function purpose and parameters**: Add header comments to new functions +6. **Return appropriate exit codes**: 0 for success, non-zero for failure +7. **Use `local` keyword** in functions to avoid global variable pollution +8. **Test on all supported platforms** before deploying new functions + +## Function Dependency Graph + +``` +helperFunctions.sh (base - sourced by most) +├── device_functions.sh +│ └── platform/device_functions/*.sh +├── emu/lib/general_functions.sh +│ ├── emu/lib/core_mappings.sh +│ └── emu/lib/*_functions.sh +├── network/*Functions.sh +├── applySetting/*.sh +└── tasks/*.sh +``` + +For any function requiring device-specific behavior, ensure both: + +1. Generic implementation in helper functions +2. Platform-specific override in platform-specific files diff --git a/spruce/scripts/docs/NETWORK_SERVICES.md b/spruce/scripts/docs/NETWORK_SERVICES.md new file mode 100644 index 000000000..6512dddf5 --- /dev/null +++ b/spruce/scripts/docs/NETWORK_SERVICES.md @@ -0,0 +1,895 @@ +# Network Services Documentation + +This document describes the network service architecture in SpruceOS, including SSH, Samba (SMB), Syncthing, SFTPGo, and Darkhttpd services. The network system allows wireless file sharing, remote access, and game synchronization. + +## Table of Contents + +1. [Network System Overview](#network-system-overview) +2. [Architecture](#architecture) +3. [SSH (Dropbear)](#ssh-dropbear) +4. [Samba (SMB/CIFS)](#samba-smbcifs) +5. [Syncthing](#syncthing) +6. [SFTPGo](#sftpgo) +7. [Darkhttpd](#darkhttpd) +8. [Configuration Management](#configuration-management) +9. [Common Tasks](#common-tasks) +10. [Troubleshooting](#troubleshooting) + +## Network System Overview + +### Purpose + +The network services provide: + +1. **SSH Access** - Remote command execution and login +2. **File Sharing** - Samba/SMB for Windows-compatible network shares +3. **Game/Data Sync** - Syncthing for automatic backup and synchronization +4. **Secure File Transfer** - SFTPGo for SFTP server +5. **Web Access** - Darkhttpd for simple HTTP file serving + +### Service Architecture + +``` +networkservices.sh (main orchestrator) + ├── Check WiFi connection + ├── Check each service setting in system JSON + ├── Start/stop services based on user preference + └── Manage status and logging + +Network Function Libraries: + ├── network/sshFunctions.sh (SSH/Dropbear) + ├── network/sambaFunctions.sh (SMB/Samba) + ├── network/syncthingFunctions.sh (Syncthing sync) + ├── network/sftpgoFunctions.sh (SFTP server) + └── network/darkhttpdFunctions.sh (HTTP server) +``` + +### Design Philosophy + +- **Configuration-Driven** - User enables/disables via system JSON +- **Modular** - Each service is independent +- **Non-Intrusive** - Services don't interfere with emulation +- **Safe** - Stop services before game launch to maximize resources +- **Automatic** - Services auto-start on system boot if enabled + +## Architecture + +### Initialization Flow + +``` +runtime.sh + ↓ +helperFunctions.sh (device detection) + ↓ +runtimeHelper.sh + ↓ +networkservices.sh (main service manager) + ├── While WiFi available: + │ ├── Check: get_config_value '.menuOptions.Network.enableSSH.selected' + │ ├── Check: get_config_value '.menuOptions.Network.enableSamba.selected' + │ ├── Check: get_config_value '.menuOptions.Network.enableSyncthing.selected' + │ ├── Check: get_config_value '.menuOptions.Network.enableSFTPGo.selected' + │ └── Start/stop services accordingly + └── Loop every 60 seconds +``` + +### Service Status Management + +Services maintain state via flag files: + +- `/mnt/SDCARD/spruce/flags/ssh_running` - SSH active +- `/mnt/SDCARD/spruce/flags/samba_running` - Samba active +- `/mnt/SDCARD/spruce/flags/syncthing_running` - Syncthing active +- `/mnt/SDCARD/spruce/flags/sftpgo_running` - SFTPGo active +- `/mnt/SDCARD/spruce/flags/darkhttpd_running` - Darkhttpd active + +### Service Control + +All services are managed as background daemons: + +```bash +# Start service +start_ssh_process # Runs as background daemon +flag_add "ssh_running" # Mark as running + +# Stop service +stop_ssh_process # Gracefully stop daemon +flag_remove "ssh_running" # Clear running flag + +# Check status +if flag_check "ssh_running"; then + echo "SSH is running" +fi +``` + +## SSH (Dropbear) + +### Overview + +Dropbear is a lightweight SSH server that provides secure remote command execution and file transfer. + +**Default Port:** 22 + +**Features:** + +- Secure command execution +- Secure file transfer (SCP/SFTP) +- Key-based authentication +- Password authentication (configurable) + +### Configuration + +#### Enable/Disable SSH + +```bash +# Via system JSON +jq '.menuOptions.Network.enableSSH.selected' "$SYSTEM_JSON" +# Returns: "True" or "False" + +# Set via config function +set_config_value '.menuOptions.Network.enableSSH.selected' 'True' +``` + +#### SSH Key Management + +```bash +# Generate SSH host keys on first boot +dropbear_generate_keys +# Creates: +# /etc/dropbear/dropbear_rsa_host_key +# /etc/dropbear/dropbear_ed25519_host_key +``` + +### Functions + +#### `dropbear_generate_keys()` + +**Purpose:** Generate SSH host keys for secure connections + +**When called:** First boot only (if keys don't exist) + +**Generated Keys:** + +- RSA host key (2048-bit) +- ED25519 host key (modern, smaller) + +**Usage:** + +```bash +source /mnt/SDCARD/spruce/scripts/network/sshFunctions.sh +dropbear_generate_keys +``` + +#### `start_ssh_process()` + +**Purpose:** Start Dropbear SSH server daemon + +**Port:** 22 (standard SSH) + +**Configuration Files:** + +- SSH keys: `/etc/dropbear/` +- Config: `/etc/dropbear/dropbear.conf` (if exists) + +**Usage:** + +```bash +source /mnt/SDCARD/spruce/scripts/network/sshFunctions.sh +start_ssh_process +# SSH now available: ssh root@ +``` + +**Command:** + +```bash +/usr/sbin/dropbear -p 22 -B +# -p 22 = port 22 +# -B = background mode +``` + +#### `stop_ssh_process()` + +**Purpose:** Stop Dropbear SSH server + +**Usage:** + +```bash +stop_ssh_process +# SSH server stopped +``` + +**Command:** + +```bash +pkill -f dropbear || true +``` + +### Usage Examples + +#### Connect to Device via SSH + +From a computer on the same network: + +```bash +# Get device IP +# (visible in network settings or router) + +# Connect via SSH +ssh root@192.168.1.50 + +# Once connected, you can: +ls /mnt/SDCARD/Roms/ # List ROMs +cp game.gba /mnt/SDCARD/Roms/GBA/ # Copy files +cat /var/log/messages # View system logs +``` + +#### Copy Files via SCP + +```bash +# From computer to device +scp game.gb root@192.168.1.50:/mnt/SDCARD/Roms/GB/ + +# From device to computer +scp root@192.168.1.50:/mnt/SDCARD/Saves/GB/savegame.sav ./ +``` + +#### SSH Keys (Advanced) + +```bash +# Generate SSH keypair on your computer +ssh-keygen -t ed25519 -f ~/.ssh/sprucedevice + +# Copy public key to device +ssh-copy-id -i ~/.ssh/sprucedevice.pub root@192.168.1.50 + +# Or manually copy to device +scp ~/.ssh/sprucedevice.pub root@192.168.1.50:/root/.ssh/authorized_keys + +# Now login without password +ssh -i ~/.ssh/sprucedevice root@192.168.1.50 +``` + +### Default Credentials + +- **User:** root +- **Password:** (none or configured in system) +- **Authentication:** Key-based or password (if enabled) + +## Samba (SMB/CIFS) + +### Overview + +Samba provides SMB/CIFS file sharing, allowing Windows/Mac computers to access device files as network shares. + +**Default Port:** 445 (Windows SMB) + +**Features:** + +- Browse device files in Windows File Explorer +- Network drive mapping +- Drag-and-drop file transfer +- Username/password protection +- File permissions + +### Configuration + +#### Enable/Disable Samba + +```bash +# Via system JSON +jq '.menuOptions.Network.enableSamba.selected' "$SYSTEM_JSON" +# Returns: "True" or "False" +``` + +#### Configuration Files + +- **Samba config:** `/etc/samba/smb.conf` +- **Shares directory:** `/mnt/SDCARD/` (shared as "Roms", "Saves", etc.) + +### Functions + +#### `start_samba_process()` + +**Purpose:** Start Samba daemon (smbd and nmbd) + +**Usage:** + +```bash +source /mnt/SDCARD/spruce/scripts/network/sambaFunctions.sh +start_samba_process +``` + +**Daemons Started:** + +- `smbd` - Main SMB protocol handler +- `nmbd` - NetBIOS name service (helps device discovery) + +#### `stop_samba_process()` + +**Purpose:** Stop Samba daemon + +**Usage:** + +```bash +stop_samba_process +``` + +### Usage Examples + +#### Connect from Windows + +1. Open File Explorer +2. Right-click and select "Map network drive" +3. Enter: `\\192.168.1.50\Roms` +4. Enter credentials (root / password) +5. Files appear as network drive + +#### Connect from Mac + +1. Finder → Go → Connect to Server +2. Enter: `smb://192.168.1.50/Roms` +3. Enter credentials +4. Share mounts on desktop + +#### Available Shares + +The Samba configuration typically exposes: + +``` +\\192.168.1.50\Roms → /mnt/SDCARD/Roms/ +\\192.168.1.50\Saves → /mnt/SDCARD/Saves/ +\\192.168.1.50\BIOS → /mnt/SDCARD/BIOS/ +\\192.168.1.50\App → /mnt/SDCARD/App/ +\\192.168.1.50\Themes → /mnt/SDCARD/Themes/ +``` + +### Default Credentials + +- **User:** root +- **Password:** (configured in smb.conf) + +## Syncthing + +### Overview + +Syncthing provides automatic, bidirectional synchronization of files between the device and computers. + +**Default Port:** 8384 (web UI), 22000 (sync) + +**Features:** + +- Automatic backup of game saves +- Sync across multiple computers +- Versioning (recover old file versions) +- Selective folder sync +- End-to-end encrypted (optional) +- Web UI for management + +### Configuration + +#### Enable/Disable Syncthing + +```bash +# Via system JSON +jq '.menuOptions.Network.enableSyncthing.selected' "$SYSTEM_JSON" +# Returns: "True" or "False" +``` + +#### Configuration Files + +- **Config:** `/home/root/.config/syncthing/config.xml` +- **Data:** `/home/root/.local/share/syncthing/` +- **Certificate:** `/home/root/.config/syncthing/cert.pem` + +### Functions + +#### `generate_syncthing_config()` + +**Purpose:** Create initial Syncthing configuration + +**Usage:** + +```bash +source /mnt/SDCARD/spruce/scripts/network/syncthingFunctions.sh +generate_syncthing_config +``` + +**Creates:** + +- Device ID (unique identifier) +- API key +- Configuration files +- Default folder syncs + +#### `repair_syncthing_config()` + +**Purpose:** Fix corrupted Syncthing configuration + +**Usage:** + +```bash +repair_syncthing_config +# Validates and repairs config.xml +# Restores default settings if needed +``` + +#### `start_syncthing_process()` + +**Purpose:** Start Syncthing daemon (background) + +**Usage:** + +```bash +start_syncthing_process +# Syncthing running in background +# Web UI available at: http://192.168.1.50:8384 +``` + +#### `run_syncthing()` + +**Purpose:** Run Syncthing in foreground (main mode) + +**Usage (rarely used directly):** + +```bash +run_syncthing +# Syncthing runs in foreground with logs to console +``` + +### Usage Examples + +#### Access Syncthing Web UI + +1. On computer, open web browser +2. Navigate to: `http://192.168.1.50:8384` +3. Log in with credentials +4. Add folders to sync +5. Add other devices to share with + +#### Add Another Device + +1. Open Syncthing web UI +2. Click "Add Remote Device" +3. Enter device ID from other device +4. Confirm on remote device +5. Select folders to share + +#### Sync Game Saves + +1. Create shared folder: `/mnt/SDCARD/Saves/` +2. Add to Syncthing via web UI +3. Add device (e.g., laptop) to share +4. Game saves automatically sync + +### Device ID Discovery + +```bash +# Get Syncthing device ID +curl http://localhost:8384/rest/system/status | jq '.deviceID' +``` + +## SFTPGo + +### Overview + +SFTPGo provides a dedicated SFTP (SSH File Transfer Protocol) server with web administration interface. + +**Default Ports:** + +- 2022 (SFTP) +- 8080 (Web UI admin) + +**Features:** + +- Dedicated SFTP server (not SSH) +- Web UI for user/permission management +- Virtual filesystem paths +- Per-user quotas +- Audit logging + +### Configuration + +#### Enable/Disable SFTPGo + +```bash +# Via system JSON +jq '.menuOptions.Network.enableSFTPGo.selected' "$SYSTEM_JSON" +# Returns: "True" or "False" +``` + +#### Configuration Files + +- **Config:** `/etc/sftpgo/sftpgo.conf` +- **Users DB:** `/etc/sftpgo/users.db` + +### Functions + +#### `start_sftpgo_process()` + +**Purpose:** Start SFTPGo server daemon + +**Usage:** + +```bash +source /mnt/SDCARD/spruce/scripts/network/sftpgoFunctions.sh +start_sftpgo_process +# SFTP available on port 2022 +# Web UI available at: http://192.168.1.50:8080 +``` + +#### `stop_sftpgo_process()` + +**Purpose:** Stop SFTPGo server + +**Usage:** + +```bash +stop_sftpgo_process +``` + +### Usage Examples + +#### Connect via SFTP Client + +```bash +# Using command line +sftp -P 2022 root@192.168.1.50 + +# Using SFTP client (WinSCP, Cyberduck, etc.) +Host: 192.168.1.50 +Port: 2022 +User: (configured) +Password: (configured) + +# Once connected +ls # List files +cd Roms/GB # Change directory +put game.gb # Upload file +get savegame.sav # Download file +quit # Exit +``` + +#### Web Administration + +1. Open browser: `http://192.168.1.50:8080` +2. Login with SFTPGo admin credentials +3. Manage users and permissions +4. Monitor connections +5. Set upload/download limits + +## Darkhttpd + +### Overview + +Darkhttpd is a lightweight HTTP server for serving static files and directories. + +**Default Port:** 8008 + +**Features:** + +- Zero configuration needed +- Serves entire SD card directory tree +- CGI script support (optional) +- Directory listings +- Range requests (resume downloads) + +### Configuration + +Darkhttpd is auto-configured to serve `/mnt/SDCARD/` on port 8008. + +### Functions + +#### `start_darkhttpd_process()` + +**Purpose:** Start Darkhttpd server daemon + +**Usage:** + +```bash +source /mnt/SDCARD/spruce/scripts/network/darkhttpdFunctions.sh +start_darkhttpd_process +# Web server available at: http://192.168.1.50:8008 +``` + +#### `stop_darkhttpd_process()` + +**Purpose:** Stop Darkhttpd server + +**Usage:** + +```bash +stop_darkhttpd_process +``` + +### Usage Examples + +#### Access Files via Browser + +1. Open web browser: `http://192.168.1.50:8008` +2. Navigate directory structure +3. Download ROMs, saves, etc. +4. Browse themes and screenshots + +#### Download Game Saves + +``` +http://192.168.1.50:8008/Saves/GB/ # Browse saves +http://192.168.1.50:8008/Saves/GB/game.sav # Download directly +``` + +#### Directory Listing + +``` +http://192.168.1.50:8008/Roms/ # Browse ROMs +http://192.168.1.50:8008/Roms/GB/ # Browse by system +http://192.168.1.50:8008/Roms/GB/game.gb # Direct file link +``` + +## Configuration Management + +### System JSON Settings + +All network services are configured via the `menuOptions.Network` section: + +```json +{ + "menuOptions": { + "Network Settings": { + "enableSSH": { + "selected": "True", + "options": ["True", "False"] + }, + "enableSamba": { + "selected": "False", + "options": ["True", "False"] + }, + "enableSFTPGo": { + "selected": "False", + "options": ["True", "False"] + }, + "enableSyncthing": { + "selected": "False", + "options": ["True", "False"] + }, + "darkhttpdEnabled": { + "selected": "Auto", + "options": ["Auto", "On", "Off"] + } + } + } +} +``` + +### Service Detection + +```bash +# Check if service should be running +SSH_ENABLED=$(get_config_value '.menuOptions.Network.enableSSH.selected') + +if [ "$SSH_ENABLED" = "True" ]; then + start_ssh_process +else + stop_ssh_process +fi +``` + +### Configuration Updates + +```bash +# Enable SSH +set_config_value '.menuOptions.Network.enableSSH.selected' 'True' + +# Disable Samba +set_config_value '.menuOptions.Network.enableSamba.selected' 'False' + +# These changes take effect next time networkservices.sh checks (max 60 seconds) +``` + +## Common Tasks + +### Check Network Service Status + +```bash +# Check individual services +ps aux | grep -E "dropbear|smbd|syncthing|sftpgo|darkhttpd" + +# Or via flag system +flag_check "ssh_running" +flag_check "samba_running" +flag_check "syncthing_running" +``` + +### View Service Logs + +```bash +# System log messages +tail -f /var/log/messages | grep -i network + +# Application-specific logs +tail -f /mnt/SDCARD/Saves/spruce/spruce.log +``` + +### Stop All Services + +```bash +# Via system JSON +set_config_value '.menuOptions.Network.enableSSH.selected' 'False' +set_config_value '.menuOptions.Network.enableSamba.selected' 'False' +set_config_value '.menuOptions.Network.enableSyncthing.selected' 'False' +set_config_value '.menuOptions.Network.enableSFTPGo.selected' 'False' + +# Manual stop +pkill -f dropbear +pkill -f smbd +pkill -f nmbd +pkill -f syncthing +pkill -f sftpgo +pkill -f darkhttpd +``` + +### Get Device Network Information + +```bash +# IP address +hostname -I + +# Network interfaces +ifconfig + +# Connected WiFi network +iw dev wlan0 link + +# Route information +ip route show +``` + +### Network Troubleshooting + +```bash +# Check WiFi connectivity +ping -c 3 8.8.8.8 + +# Check DNS resolution +nslookup google.com + +# Device discovery (mDNS) +avahi-resolve-address + +# Open ports +netstat -tulpn | grep LISTEN +``` + +## Troubleshooting + +### SSH Won't Start + +```bash +# Check if port 22 is available +netstat -tulpn | grep 22 + +# Check SSH keys exist +ls -la /etc/dropbear/ + +# If missing, regenerate +dropbear_generate_keys + +# Try starting with debug output +dropbear -p 22 -F -v +``` + +### Samba Share Not Visible + +```bash +# Check Samba is running +ps aux | grep smbd + +# Test SMB connectivity +smbclient -L //192.168.1.50 -U root + +# Check configuration +cat /etc/samba/smb.conf +``` + +### Syncthing Folder Not Syncing + +```bash +# Check Syncthing is running +ps aux | grep syncthing + +# Access web UI +curl http://localhost:8384/rest/system/connections + +# Check folder permissions +ls -la /mnt/SDCARD/Saves/ + +# Repair config if corrupted +repair_syncthing_config +``` + +### Can't Connect to Device Over WiFi + +```bash +# Check device IP +hostname -I + +# Check WiFi is enabled +ifconfig wlan0 + +# Check signal quality +iw dev wlan0 link + +# Restart DHCP +killall dhclient +dhclient wlan0 + +# Test ping from computer +ping +``` + +### Services Stop After Game Launch + +This is expected behavior: + +```bash +# Services are stopped before game to free resources +# They restart after game exits (configurable delay) + +# Game launch process: +1. Stop all network services +2. Set CPU to performance +3. Launch emulator/game +4. On exit: Restart network services +``` + +### High CPU Usage from Syncthing + +Syncthing can be CPU-intensive during initial sync: + +```bash +# Monitor CPU usage +top -p $(pgrep syncthing) + +# Disable temporarily +stop_syncthing_process + +# Check what's syncing +# (via web UI at http://192.168.1.50:8384) +``` + +## Network Security Notes + +### Recommendations + +1. **Change Default Passwords** - If using password auth +2. **Use SSH Keys** - More secure than password authentication +3. **Restrict Access** - Use firewall rules if available +4. **Keep Services Updated** - Regular updates recommended +5. **Monitor Logs** - Check for unauthorized access attempts +6. **Enable Service Selectively** - Keep only needed services running + +### Default Network Ports + +| Service | Port | Protocol | +| -------------- | -------- | -------- | +| SSH (Dropbear) | 22 | TCP | +| Samba | 445, 139 | TCP | +| Syncthing | 22000 | TCP/UDP | +| Syncthing UI | 8384 | HTTP | +| SFTPGo | 2022 | TCP | +| SFTPGo UI | 8080 | HTTP | +| Darkhttpd | 8008 | HTTP | + +### Firewall Recommendations + +If device has firewall: + +```bash +# Allow SSH from LAN +ufw allow from 192.168.1.0/24 to any port 22 + +# Allow Samba from LAN +ufw allow from 192.168.1.0/24 to any port 445 + +# Block SFTP from WAN +ufw deny from any to any port 2022/tcp +``` diff --git a/spruce/scripts/docs/PLATFORM_ABSTRACTION.md b/spruce/scripts/docs/PLATFORM_ABSTRACTION.md new file mode 100644 index 000000000..ce474b3db --- /dev/null +++ b/spruce/scripts/docs/PLATFORM_ABSTRACTION.md @@ -0,0 +1,653 @@ +# Platform Abstraction Layer Documentation + +This document describes how SpruceOS achieves device-agnostic script design through hardware abstraction, allowing the same scripts to run on all supported handheld devices with minimal changes. + +## Table of Contents + +1. [Platform Detection](#platform-detection) +2. [Architecture Overview](#architecture-overview) +3. [Platform Configuration Files](#platform-configuration-files) +4. [Device-Specific Functions](#device-specific-functions) +5. [Implementation Examples](#implementation-examples) +6. [Adding Support for New Devices](#adding-support-for-new-devices) + +## Platform Detection + +### Device Identification + +Device detection happens automatically when `helperFunctions.sh` is sourced. The detection reads `/proc/cpuinfo` and classifies devices based on CPU model: + +```bash +# Device Detection Logic (in helperFunctions.sh) + +if grep -q "sun8i" /proc/cpuinfo; then + PLATFORM="A30" + BRAND="Miyoo" +elif grep -q "TG5040" /proc/cpuinfo; then + PLATFORM="SmartPro" + BRAND="TrimUI" +elif grep -q "TG3040" /proc/cpuinfo; then + PLATFORM="Brick" + BRAND="TrimUI" +elif grep -q "TG5050" /proc/cpuinfo; then + PLATFORM="SmartProS" + BRAND="TrimUI" +elif grep -q "0xd05" /proc/cpuinfo; then + PLATFORM="Flip" + BRAND="Miyoo" +elif grep -q "0xd04" /proc/cpuinfo; then + PLATFORM="Pixel2" + BRAND="Miyoo" +else + PLATFORM="MiyooMini" # Default + BRAND="Miyoo" +fi +``` + +### Architecture Detection + +After device identification, architecture is determined: + +```bash +if [ -n "$(file /bin/bash | grep 'ARM')" ]; then + if [ -n "$(file /bin/bash | grep '32-bit')" ]; then + PLATFORM_ARCHITECTURE="armhf" # 32-bit + else + PLATFORM_ARCHITECTURE="aarch64" # 64-bit + fi +fi +``` + +**Architecture Grouping:** + +- **32-bit (armhf):** A30, MiyooMini +- **64-bit (aarch64):** Flip, SmartPro, SmartProS, Pixel2, Brick + +## Architecture Overview + +### Three-Layer Abstraction Model + +``` +┌─────────────────────────────────────────────────────┐ +│ Application Scripts (runtime.sh, principal.sh, etc) │ +│ - Device-agnostic application logic │ +└────────────────────────┬────────────────────────────┘ + │ +┌────────────────────────▼────────────────────────────┐ +│ Platform Abstraction Layer (helperFunctions) │ +│ - Generic helper functions │ +│ - Device detection logic │ +│ - Configuration access via get_config_value() │ +└────────────────────────┬────────────────────────────┘ + │ +┌────────────────────────▼────────────────────────────┐ +│ Device-Specific Implementation Layer │ +│ (platform/device_functions/*.sh) │ +│ - CPU control (set_performance, set_powersave) │ +│ - Display/brightness control │ +│ - LED control (TrimUI only) │ +│ - Hardware initialization │ +│ - Vibration/rumble control │ +└────────────────────────┬────────────────────────────┘ + │ +┌────────────────────────▼────────────────────────────┐ +│ Hardware/OS Layer │ +│ - Linux sysfs (/sys/class/*) │ +│ - Device nodes (/dev/input/*) │ +│ - ALSA audio (/dev/snd/*) │ +└─────────────────────────────────────────────────────┘ +``` + +### Sourcing Pattern + +Most scripts follow this sourcing pattern to leverage abstraction: + +```bash +#!/bin/bash + +# 1. Source core helpers (loads device detection) +source /mnt/SDCARD/spruce/scripts/helperFunctions.sh +# Now $PLATFORM and $SYSTEM_JSON are available + +# 2. Load platform-specific device functions +source /mnt/SDCARD/spruce/scripts/platform/device_functions/${PLATFORM}.sh + +# 3. Use unified interface (automatically routed) +set_performance # Calls A30-specific or Flip-specific code +vibrate # Route-dependent implementation +rgb_led "red" # Works on TrimUI, logged as unsupported on Miyoo + +# 4. Use generic helpers +get_config_value '.menuOptions.System.swapfileSize.selected' +``` + +## Platform Configuration Files + +### Configuration File Location and Structure + +``` +platform/ +├── A30.cfg # Miyoo A30 (32-bit) +├── MiyooMini.cfg # Miyoo Mini (32-bit) +├── Flip.cfg # Miyoo Flip (64-bit) +├── SmartPro.cfg # TrimUI SmartPro (64-bit) +├── SmartProS.cfg # TrimUI SmartProS (64-bit) +├── Pixel2.cfg # Miyoo Pixel2 (64-bit) +├── Brick.cfg # TrimUI Brick (64-bit) +└── device.sh # Device detection helper +``` + +### Configuration File Format + +Each `.cfg` file defines hardware-specific paths and button mappings in shell variable format: + +```bash +# platform/A30.cfg +# Miyoo A30 Hardware Configuration +# CPU: Allwinner H2+ (sun8i), 1.2GHz quad-core ARM Cortex-A7, 32-bit +# Display: 3.5" 320×240, IPS LCD +# RAM: 512MB + +# Input Event Paths +export EVENT_PATH_BUTTONS="/dev/input/event3" +export EVENT_PATH_POWER="/dev/input/event0" +export EVENT_PATH_JOYSTICK="/dev/input/event4" +export EVENT_PATH_BRIGHTNESS="/dev/input/event5" + +# Button Key Codes +export B_A=305 +export B_B=304 +export B_X=308 +export B_Y=307 +export B_L1=310 +export B_L2=312 +export B_R1=311 +export B_R2=313 +export B_UP=103 +export B_DOWN=108 +export B_LEFT=105 +export B_RIGHT=106 +export B_START=28 +export B_SELECT=1 +export B_MENU=274 +export B_POWER=116 + +# Display Paths +export DEVICE_BRIGHTNESS_PATH="/sys/class/backlight/*/brightness" +export BRIGHTNESS_MAX=255 +export BRIGHTNESS_MIN=0 + +# System Brightness Levels (11 levels for UI) +export SYSTEM_BRIGHTNESS_0=0 +export SYSTEM_BRIGHTNESS_1=23 +export SYSTEM_BRIGHTNESS_2=46 +export SYSTEM_BRIGHTNESS_3=69 +export SYSTEM_BRIGHTNESS_4=92 +export SYSTEM_BRIGHTNESS_5=115 +export SYSTEM_BRIGHTNESS_6=138 +export SYSTEM_BRIGHTNESS_7=161 +export SYSTEM_BRIGHTNESS_8=184 +export SYSTEM_BRIGHTNESS_9=207 +export SYSTEM_BRIGHTNESS_10=255 + +# CPU Paths +export CPUFREQ_PATH="/sys/devices/system/cpu/cpu0/cpufreq/" +export CPUGOV_PATH="/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor" + +# Battery Paths +export BATTERY_PATH="/sys/class/power_supply/battery/" +export BATTERY_CAPACITY="${BATTERY_PATH}capacity" + +# Audio +export DEVICE_AUDIO_OUTPUT="/dev/snd/pcmC1D0p" +export DEVICE_AUDIO_CONTROL="/dev/snd/controlC1" + +# Vibration (GPIO-based) +export VIBRATION_PATH="/sys/class/gpio/gpio48" + +# Display Aspect Ratio +export DISPLAY_ASPECT_RATIO="16:9" +``` + +### Configuration for TrimUI SmartPro (with RGB LEDs) + +```bash +# platform/SmartPro.cfg +# RGB LED paths (TrimUI-specific) +export LED_PATH="/sys/class/leds/" +export LED_LEFT="${LED_PATH}led_left/brightness" +export LED_RIGHT="${LED_PATH}led_right/brightness" +export LED_MIDDLE="${LED_PATH}led_middle/brightness" +export LED_1="${LED_PATH}led1/brightness" +export LED_2="${LED_PATH}led2/brightness" + +# TrimUI-specific CPU/GPU +export GPU_FREQ_PATH="/sys/class/devfreq/ff9a0000.gpu/" +export THERMAL_CORE="/sys/class/thermal/thermal_zone0/" +``` + +## Device-Specific Functions + +### File Organization + +``` +platform/device_functions/ +├── A30.sh # A30-specific implementations +├── MiyooMini.sh # MiyooMini-specific implementations +├── Flip.sh # Flip-specific implementations +├── SmartPro.sh # SmartPro-specific implementations +├── SmartProS.sh # SmartProS-specific implementations +├── Pixel2.sh # Pixel2-specific implementations +├── Brick.sh # Brick-specific implementations +├── common32bit.sh # Shared 32-bit abstractions +├── common64bit.sh # Shared 64-bit abstractions +└── utils/ + ├── cpu_control_functions.sh # CPU frequency/governor control + ├── watchdog_launcher.sh # Launch background watchdogs + ├── legacy_display.sh # Display abstraction + ├── rumble.sh # GPIO vibration control + ├── sleep_functions.sh # Sleep/suspend state handlers + ├── flip_a30_brightness.sh # Device-specific brightness + ├── miyoomini/mm_set_volume.py # MiyooMini volume control + └── smartpros/adaptive_fan.py # TrimUI fan management +``` + +### Device File Structure + +Each device file defines platform-specific functions. Example from `A30.sh`: + +```bash +#!/bin/bash +# platform/device_functions/A30.sh +# Miyoo A30 specific implementations + +# Required functions +get_python_path() { + echo "/usr/bin/python3" +} + +get_config_path() { + echo "/mnt/SDCARD" +} + +cores_online() { + cat /proc/cpuinfo | grep -c "processor" +} + +set_performance() { + # A30-specific performance mode + echo "performance" > "${CPUGOV_PATH}" + echo 1200000 > "${CPUFREQ_PATH}scaling_max_freq" +} + +set_powersave() { + echo "powersave" > "${CPUGOV_PATH}" + echo 600000 > "${CPUFREQ_PATH}scaling_max_freq" +} + +set_overclock() { + # A30 supports 1344MHz overclocking + echo 1344000 > "${CPUFREQ_PATH}scaling_max_freq" + echo "performance" > "${CPUGOV_PATH}" +} + +vibrate() { + force=${1:-50} + duration=${2:-100} + + # A30 vibration via GPIO48 + if [ -d "${VIBRATION_PATH}" ]; then + echo 1 > "${VIBRATION_PATH}/value" + sleep 0.${duration} + echo 0 > "${VIBRATION_PATH}/value" + fi +} + +get_brightness() { + read -r value < "${DEVICE_BRIGHTNESS_PATH}" + # Convert raw value (0-255) to level (0-10) + echo $((value * 10 / 255)) +} + +set_brightness() { + level=$1 + # Convert level (0-10) to raw value (0-255) + raw_value=$((level * 255 / 10)) + echo "$raw_value" > "${DEVICE_BRIGHTNESS_PATH}" +} + +rgb_led() { + # A30 doesn't support RGB LEDs + log_message "RGB LED not supported on A30" +} + +enable_or_disable_rgb() { + # A30 doesn't support RGB LEDs + log_message "RGB LED not supported on A30" +} + +device_init() { + # Initialize A30 hardware + set_smart # Default to balanced mode + get_brightness # Initialize brightness +} +``` + +### Shared Architecture Functions + +#### common32bit.sh (32-bit Devices) + +Used by A30 and MiyooMini for shared 32-bit abstractions: + +```bash +# Shared CPU control for 32-bit systems +set_smart() { + echo "ondemand" > "${CPUGOV_PATH}" +} + +# Shared 32-bit memory management +setup_32bit_ld_path() { + export LD_LIBRARY_PATH="/lib:/usr/lib:/mnt/SDCARD/App/MiyooMini/lib" +} +``` + +#### common64bit.sh (64-bit Devices) + +Used by Flip, SmartPro, SmartProS, Pixel2, Brick for shared 64-bit abstractions: + +```bash +# Shared CPU control for 64-bit systems +set_smart() { + echo "schedutil" > "${CPUGOV_PATH}" +} + +# Shared 64-bit memory management +setup_64bit_ld_path() { + export LD_LIBRARY_PATH="/lib64:/usr/lib64:/mnt/SDCARD/App/Platform/lib64" +} + +# 64-bit brightness control +set_brightness() { + level=$1 + # 64-bit systems use different brightness scale + raw_value=$((level * 100)) + echo "$raw_value" > "${DEVICE_BRIGHTNESS_PATH}" +} +``` + +### Platform-Specific Utils + +#### cpu_control_functions.sh + +```bash +# Generic CPU control functions used by all platforms + +set_cpu_frequency() { + cpu=$1 + frequency=$2 + + if [ -f "/sys/devices/system/cpu/cpu${cpu}/cpufreq/scaling_max_freq" ]; then + echo "$frequency" > "/sys/devices/system/cpu/cpu${cpu}/cpufreq/scaling_max_freq" + fi +} + +set_cpu_governor() { + governor=$1 + for cpu in /sys/devices/system/cpu/cpu*/cpufreq/; do + echo "$governor" > "${cpu}/scaling_governor" + done +} + +get_cpu_frequency() { + cat /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_cur_freq +} +``` + +#### rumble.sh + +GPIO-based vibration control (works on all Miyoo and TrimUI devices): + +```bash +vibrate() { + gpio_pin=$1 + duration=${2:-100} + intensity=${3:-50} + + if [ ! -d "/sys/class/gpio/gpio${gpio_pin}" ]; then + echo "$gpio_pin" > /sys/class/gpio/export + fi + + # Simulate intensity with pulse-width modulation + on_time=$((duration * intensity / 100)) + off_time=$((duration - on_time)) + + echo 1 > "/sys/class/gpio/gpio${gpio_pin}/value" + sleep 0.$(printf "%03d" "$on_time") + echo 0 > "/sys/class/gpio/gpio${gpio_pin}/value" +} +``` + +## Implementation Examples + +### Example 1: CPU Governor Setting (Cross-Platform) + +**Goal:** Change CPU mode to performance without device-specific knowledge + +```bash +#!/bin/bash + +source /mnt/SDCARD/spruce/scripts/helperFunctions.sh +source /mnt/SDCARD/spruce/scripts/platform/device_functions/${PLATFORM}.sh + +# This works the same on all devices! +set_performance + +# On A30: Sets frequency to 1.2GHz, governor to "performance" +# On MiyooMini: Sets frequency to 1.0GHz, governor adapted for ARMv7 +# On Flip: Sets frequency to 2.0GHz, governor to "performance" +# On SmartPro: Sets frequency to 2.4GHz, governor with GPU coordination +``` + +**How it works:** + +1. `set_performance()` is defined in device-specific files +2. Automatically routes to correct implementation +3. Each device adjusts frequencies and governors appropriately + +### Example 2: Display Brightness Control + +```bash +#!/bin/bash +source /mnt/SDCARD/spruce/scripts/helperFunctions.sh +source /mnt/SDCARD/spruce/scripts/platform/device_functions/${PLATFORM}.sh + +# Get current brightness (0-10 scale, works on all devices) +CURRENT=$(get_brightness) + +# Increase brightness by 1 level (hardware-agnostic) +NEW_LEVEL=$((CURRENT + 1)) +[ "$NEW_LEVEL" -gt 10 ] && NEW_LEVEL=10 + +set_brightness "$NEW_LEVEL" +``` + +**Platform Handling:** + +- **A30:** Converts level (0-10) → raw value (0-255) for `/sys/class/backlight/*/brightness` +- **MiyooMini:** Converts level (0-10) → raw value (0-255) for `/sys/class/backlight/*/brightness` +- **Flip:** Uses platform-specific scaling via `flip_a30_brightness.sh` +- **SmartPro:** Uses 64-bit brightness scaling with different hardware path + +### Example 3: LED Control (TrimUI only) + +```bash +#!/bin/bash +source /mnt/SDCARD/spruce/scripts/helperFunctions.sh +source /mnt/SDCARD/spruce/scripts/platform/device_functions/${PLATFORM}.sh + +# This code works on all platforms - TrimUI logs success, Miyoo logs unsupported +rgb_led "blue" # SmartPro turns blue, MiyooMini logs "not supported" +enable_or_disable_rgb "on" # SmartPro enables, MiyooMini is no-op +``` + +**Device Behavior:** + +- **TrimUI (SmartPro, SmartProS, Brick):** Genuine RGB LED control via sysfs +- **Miyoo (A30, MiyooMini, Flip, Pixel2):** Function silently logs unsupported, continues execution + +## Adding Support for New Devices + +### Step 1: Create Platform Configuration File + +Create `platform/NewDevice.cfg`: + +```bash +#!/bin/bash +# platform/NewDevice.cfg +# NewDevice Hardware Configuration +# CPU: [Processor details] + +# Input Event Paths (find with: cat /proc/bus/input/devices) +export EVENT_PATH_BUTTONS="/dev/input/event[X]" +export EVENT_PATH_POWER="/dev/input/event[Y]" +# ... other event paths + +# Button Key Codes (find with: evtest) +export B_A=305 +export B_B=304 +# ... other button codes + +# Display Paths +export DEVICE_BRIGHTNESS_PATH="/sys/class/backlight/[device]/brightness" +export BRIGHTNESS_MAX=255 + +# ... other hardware paths +``` + +### Step 2: Create Device Function File + +Create `platform/device_functions/NewDevice.sh`: + +```bash +#!/bin/bash +# platform/device_functions/NewDevice.sh +# NewDevice specific implementations + +# Required functions (all must be implemented) +get_python_path() { + echo "/usr/bin/python3" +} + +get_config_path() { + echo "/mnt/SDCARD" +} + +cores_online() { + cat /proc/cpuinfo | grep -c "processor" +} + +set_smart() { + # Device-specific balanced mode + echo "schedutil" > "${CPUGOV_PATH}" +} + +set_performance() { + # Device-specific performance mode + echo "performance" > "${CPUGOV_PATH}" +} + +# ... implement other required functions +``` + +### Step 3: Update Device Detection + +Edit `helperFunctions.sh` device detection section: + +```bash +elif grep -q "newdevice_cpu_signature" /proc/cpuinfo; then + PLATFORM="NewDevice" + BRAND="Manufacturer" +fi +``` + +### Step 4: Update Architecture Detection (if needed) + +If NewDevice uses new architecture, update common32bit.sh or common64bit.sh accordingly. + +### Step 5: Test on All Code Paths + +1. **System Management:** `runtime.sh` → device initialization +2. **Emulator Launch:** Game launching → CPU mode switching +3. **Watchdog Monitoring:** Button/lid input handling +4. **Network Services:** Service starting/stopping +5. **Power Management:** Shutdown and sleep sequences + +## Platform Capability Matrix + +| Feature | A30 | MiyooMini | Flip | SmartPro | SmartProS | Pixel2 | Brick | +| -------------- | --- | --------- | ---- | -------- | --------- | ------ | ----- | +| CPU Governor | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | +| Overclock | ✓ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | +| Vibration | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | +| RGB LED | ✗ | ✗ | ✗ | ✓ | ✓ | ✗ | ✓ | +| Headphone Jack | ✗ | ✗ | ✓ | ✓ | ✓ | ✗ | ✗ | +| Lid Sensor | ✗ | ✗ | ✓ | ✓ | ✓ | ✗ | ✓ | +| Fan Control | ✗ | ✗ | ✗ | ✓ | ✓ | ✗ | ✓ | + +## Performance Implications + +### CPU Frequency Per Platform + +| Device | Idle | Smart | Performance | Overclock | +| --------- | ------- | -------- | ----------- | --------- | +| A30 | 600 MHz | 1000 MHz | 1200 MHz | 1344 MHz | +| MiyooMini | 600 MHz | 1000 MHz | 1200 MHz | - | +| Flip | 800 MHz | 1500 MHz | 2000 MHz | - | +| SmartPro | 800 MHz | 1800 MHz | 2400 MHz | - | +| SmartProS | 800 MHz | 1800 MHz | 2400 MHz | - | +| Pixel2 | 800 MHz | 1500 MHz | 2000 MHz | - | +| Brick | 800 MHz | 1600 MHz | 2200 MHz | - | + +These frequencies are tuned per device for optimal balance between performance and power consumption. + +## Debugging Platform Issues + +### To determine which platform is detected: + +```bash +source /mnt/SDCARD/spruce/scripts/helperFunctions.sh +echo "Platform: $PLATFORM" +echo "Architecture: $PLATFORM_ARCHITECTURE" +echo "Brand: $BRAND" +``` + +### To test device functions: + +```bash +source /mnt/SDCARD/spruce/scripts/helperFunctions.sh +source /mnt/SDCARD/spruce/scripts/platform/device_functions/${PLATFORM}.sh + +# Test a function +get_brightness +set_brightness 5 +vibrate 100 200 +``` + +### To check hardware paths: + +```bash +# Input devices +cat /proc/bus/input/devices + +# Display paths +ls -la /sys/class/backlight/ + +# CPU frequency paths +ls -la /sys/devices/system/cpu/cpu0/cpufreq/ + +# Battery +ls -la /sys/class/power_supply/battery/ + +# LEDs (TrimUI) +ls -la /sys/class/leds/ +``` diff --git a/spruce/scripts/docs/README.md b/spruce/scripts/docs/README.md new file mode 100644 index 000000000..25d6ec76d --- /dev/null +++ b/spruce/scripts/docs/README.md @@ -0,0 +1,465 @@ +# SpruceOS Scripts Documentation + +## Overview + +The `scripts` directory contains a comprehensive collection of shell scripts that power SpruceOS functionality across all supported devices (Miyoo A30, Miyoo Mini, Miyoo Flip, TrimUI SmartPro, TrimUI Brick, and TrimUI SmartProS). These scripts handle system initialization, emulator launching, device hardware abstraction, power management, network services, and user interface control. + +## Directory Structure + +``` +spruce/scripts/ +├── System Management +│ ├── runtime.sh # System startup initialization +│ ├── runtimeHelper.sh # Runtime helper utilities +│ ├── principal.sh # Main control loop and game switching +│ ├── firstboot.sh # First-boot setup +│ ├── archiveUnpacker.sh # Archive unpacking service +│ ├── enable_zram.sh # Enable ZRAM compression +│ ├── disable_zram.sh # Disable ZRAM +│ ├── set_up_swap.sh # Swapfile management +│ └── enforceSmartCPU.sh # CPU governor locking +│ +├── Watchdog & Monitoring +│ ├── powerbutton_watchdog.sh # Power button monitoring (v1) +│ ├── power_button_watchdog_v2.sh # Power button handling (v2) +│ ├── buttons_watchdog.sh # Brightness and button mapping +│ ├── homebutton_watchdog.sh # Home button actions +│ ├── lid_watchdog_v2.sh # Lid sensor monitoring +│ ├── bluetooth_watchdog.sh # Bluetooth monitoring +│ └── mixer_watchdog.sh # Audio mixer watchdog +│ +├── Power Management +│ ├── idlemon_chargingAction.sh # Idle charging action +│ ├── idlemon_poweroffAction.sh # Idle poweroff wrapper +│ ├── sleep_helper.sh # Sleep/suspend handler +│ ├── low_power_warning.sh # Battery warning system +│ ├── save_poweroff.sh # Graceful shutdown +│ └── save_poweroff_stage2.sh # Final unmounting +│ +├── Audio & Display +│ ├── asound-setup.sh # Bluetooth audio configuration +│ ├── audioFunctions.sh # Audio control (deprecated) +│ ├── autoIconRefresh.sh # Theme change watcher +│ ├── iconfresh.sh # Icon/theme refresh +│ └── retroarch_utils.sh # RetroArch configuration updates +│ +├── Network Services +│ ├── networkservices.sh # Main network orchestrator +│ └── (Network function libraries - see below) +│ +├── Emulator Control +│ ├── emu/ +│ │ └── standard_launch.sh # Universal emulator launcher +│ └── emu/lib/ +│ ├── (Emulator-specific functions - see below) +│ +├── Platform Abstraction +│ ├── platform/ +│ │ ├── *.cfg # Platform configuration files +│ │ ├── device.sh # Device detection script +│ │ └── device_functions/ +│ │ ├── *.sh # Platform-specific device functions +│ │ └── utils/ # Device utility scripts +│ └── applySetting/ +│ ├── *.sh # Settings application scripts +│ +└── Tasks & Utilities + ├── tasks/ + │ ├── bugReport.sh # Bug report generator + │ ├── clearwifi.sh # WiFi clearing utility + │ ├── deleteMacFiles.sh # macOS artifact removal + │ ├── repairSD.sh # SD card repair + │ ├── resetNDS.sh # Reset NDS configuration + │ ├── resetPPSSPP.sh # Reset PSP configuration + │ ├── resetRA.sh # Reset RetroArch + │ ├── resetRAHotkeys.sh # Reset RetroArch hotkeys + │ └── scanScummVM.sh # ScummVM game discovery + │ + └── Support Libraries + ├── helperFunctions.sh # Core helper functions + ├── device_functions.sh # Device abstraction layer + └── network/ + ├── sshFunctions.sh + ├── sambaFunctions.sh + ├── syncthingFunctions.sh + ├── sftpgoFunctions.sh + └── darkhttpdFunctions.sh +``` + +## Script Categories + +### 1. **System Management & Runtime** (9 scripts) + +| Script | Purpose | Main Functionality | +| -------------------- | ----------------------------- | -------------------------------------------------------------- | +| `runtime.sh` | System startup initialization | Logging setup, WiFi, swap, firmware checks, watchdog launching | +| `runtimeHelper.sh` | Runtime utilities | SD card fixes, firmware app visibility, OTA checks | +| `principal.sh` | Main control loop | Game switching, PyUI launch, emulator execution manager | +| `firstboot.sh` | First-boot setup | SSH setup, PortMaster/ScummVM extraction, version detection | +| `archiveUnpacker.sh` | Archive unpacking | Pre-menu and pre-command archive unpacking | +| `enable_zram.sh` | Memory compression | ZRAM device setup with lz4/lzo compression | +| `disable_zram.sh` | Disable ZRAM | Swap disable and device reset | +| `set_up_swap.sh` | Swap file management | Create/manage swapfile (128-512MB) | +| `enforceSmartCPU.sh` | CPU governor locking | Prevent CPU mode changes during execution | + +### 2. **Watchdog & Monitoring Processes** (7 scripts) + +Continuous background processes that monitor hardware events and system state: + +| Script | Event Triggers | Actions | +| ---------------------------------- | ------------------- | -------------------------------------------------- | +| `powerbutton_watchdog.sh` (v1) | Power button press | Wake alarm configuration, emulator detection | +| `power_button_watchdog_v2.sh` (v2) | Power press/release | Sleep trigger on press, poweroff on 2s hold | +| `buttons_watchdog.sh` | Button combinations | System brightness mapping (10 levels) | +| `homebutton_watchdog.sh` | Home button press | DraStic pause/resume, port termination, screenshot | +| `lid_watchdog_v2.sh` | Lid open/close | Sleep on close (with charging state checks) | +| `bluetooth_watchdog.sh` | Config changes | Enable Bluetooth/bluealsa | +| `mixer_watchdog.sh` | Audio events | Call audio control routines | + +### 3. **Power Management** (6 scripts) + +| Script | Purpose | Triggers | +| --------------------------- | ------------------- | ----------------------------------------------- | +| `idlemon_chargingAction.sh` | Idle while charging | Screen off when charging, wake on input | +| `idlemon_poweroffAction.sh` | Idle poweroff | Route to save_poweroff.sh for inactive apps | +| `sleep_helper.sh` | Sleep/suspend | Manage lid/power button, wakeup timers | +| `low_power_warning.sh` | Battery warning | Morse code SOS LED/vibration, battery logging | +| `save_poweroff.sh` | Graceful shutdown | Syncthing sync, process cleanup, stage2 trigger | +| `save_poweroff_stage2.sh` | Final cleanup | Minimal unmounting with reduced binaries | + +### 4. **Network Services** (1 main + 5 function libraries) + +The network subsystem uses a modular architecture: + +``` +networkservices.sh (main orchestrator) +├── sshFunctions.sh (SSH/Dropbear) +├── sambaFunctions.sh (SMB/Samba) +├── syncthingFunctions.sh (Syncthing sync) +├── sftpgoFunctions.sh (SFTP server) +└── darkhttpdFunctions.sh (HTTP server) +``` + +**Startup Flow:** + +1. Wait for WiFi connection +2. Check Samba config → start/stop +3. Check SSH config → start/stop +4. Check SFTPGo config → start/stop +5. Check Syncthing config → start/stop +6. Auto-setup Darkhttpd + +### 5. **Emulator Launch System** (1 main + 16 function libraries) + +The emulator system uses a universal launcher that routes to emulator-specific handlers: + +**Main Coordinator:** + +- `emu/standard_launch.sh` - Universal emulator launcher + +**Emulator-Specific Libraries:** + +``` +emu/lib/ +├── core_mappings.sh # RetroArch core-to-folder mapping +├── general_functions.sh # Universal emulator functions +├── ra_functions.sh # RetroArch-specific +├── drastic_functions.sh # NDS (DraStic) emulator +├── ppsspp_functions.sh # PSP (PPSSPP) emulator +├── media_functions.sh # Media playback (FFmpeg) +├── scummvm_functions.sh # ScummVM adventure games +├── flycast_functions.sh # Dreamcast/Naomi (Flycast) +├── mupen_functions.sh # N64 (Mupen64plus) +├── pico8_functions.sh # PICO-8 fantasy console +├── ports_functions.sh # Custom game ports +├── yaba_functions.sh # Sega Saturn (Yabasanshiro) +├── openbor_functions.sh # Beat-em-up engine (OpenBOR) +├── led_functions.sh # LED effects during gameplay +├── network_functions.sh # In-game network services +└── gtt_functions.sh # Game Time Tracking +``` + +**Emulator Launch Flow:** + +1. Source helper functions and platform-specific code +2. Detect emulator from script path (EMU_NAME) +3. Load CPU mode from configuration +4. Set CPU mode via platform-specific handler +5. Initialize network services if needed +6. Trigger LED effects +7. Route to appropriate emulator: + - A30PORTS → A30 port launcher + - DC/NAOMI → Flycast or RetroArch + - GB/GBC/GBA → Perfect Overlays + RetroArch + - MEDIA → FFplay or RetroArch + - NDS → DraStic + - PSP → PPSSPP + - SCUMMVM → ScummVM Menu/Play + - Other systems → RetroArch +8. Post-execution cleanup and settings restoration + +### 6. **Platform Abstraction Layer** + +The platform layer ensures device-agnostic script design through hardware abstraction: + +**Device Detection (via `/proc/cpuinfo`):** + +- `sun8i` → Miyoo A30 (32-bit) +- `TG5040` → TrimUI SmartPro +- `TG3040` → TrimUI Brick +- `TG5050` → TrimUI SmartProS +- `0xd05` → Miyoo Flip +- `0xd04` → Miyoo Pixel2 +- Default → Miyoo Mini + +**Platform-Specific Functions:** + +``` +platform/device_functions/ +├── A30.sh # Miyoo A30 (32-bit) +├── MiyooMini.sh # Miyoo Mini (32-bit) +├── Flip.sh # Miyoo Flip (64-bit) +├── SmartPro.sh # TrimUI SmartPro (64-bit) +├── SmartProS.sh # TrimUI SmartProS (64-bit) +├── Pixel2.sh # Miyoo Pixel2 (64-bit) +├── Brick.sh # TrimUI Brick (64-bit) +├── common32bit.sh # Shared 32-bit code +├── common64bit.sh # Shared 64-bit code +└── utils/ + ├── cpu_control_functions.sh # CPU frequency scaling + ├── watchdog_launcher.sh # Watchdog spawning + ├── legacy_display.sh # Display wrappers + ├── rumble.sh # GPIO vibration + ├── sleep_functions.sh # Sleep handlers + ├── flip_a30_brightness.sh # Brightness control + ├── miyoomini/mm_set_volume.py # Volume control (Python) + └── smartpros/adaptive_fan.py # Fan control (TrimUI) +``` + +### 7. **Task & Utility Scripts** (9 scripts) + +Located in `tasks/` directory: + +| Script | Purpose | +| ------------------- | -------------------------------------------- | +| `bugReport.sh` | Collect logs and configs into 7z archive | +| `clearwifi.sh` | Remove all WiFi networks | +| `deleteMacFiles.sh` | Remove macOS artifacts (.DS_Store, .Trashes) | +| `repairSD.sh` | SD card repair utility with fsck | +| `resetNDS.sh` | Restore NDS configuration from backups | +| `resetPPSSPP.sh` | Restore PSP emulator configuration | +| `resetRA.sh` | Restore RetroArch to baseline config | +| `resetRAHotkeys.sh` | Reset RetroArch hotkeys to defaults | +| `scanScummVM.sh` | Discover ScummVM games automatically | + +## Critical Process Flows + +### Game Launch Sequence + +``` +1. User selects game in MainUI +2. MainUI writes: /tmp/cmd_to_run.sh +3. MainUI exits → principal.sh detects file +4. principal.sh: + - Sets performance CPU mode + - Saves command to /mnt/SDCARD/spruce/flags/lastgame.lock (autoresume) + - Executes /tmp/cmd_to_run.sh (symlink to /Emu//launch.sh) +5. standard_launch.sh router calls appropriate emulator +6. Emulator runs with saved configurations +7. On exit: + - Restores CPU mode + - Syncs filesystem + - Returns to principal.sh loop +``` + +### Shutdown Sequence + +``` +save_poweroff.sh: + 1. Logs activity event + 2. Stops all background services + 3. Kills running emulators/MainUI + 4. Saves Syncthing data + 5. Unmounts USB storage if mounted + 6. Copies stage2 to /tmp/ + 7. Executes stage2 with minimal PATH + ↓ +save_poweroff_stage2.sh: + 1. Uses only: /usr/bin, /usr/sbin, /bin, /sbin + 2. Finds all processes with open SD files + 3. Kills them (SIGKILL) + 4. Waits for kernel cleanup + 5. Unmounts SD card + 6. Poweroff or reboot +``` + +### Sleep/Lid Sensor Sequence + +``` +lid_watchdog_v2.sh (continuous): + 1. Monitor lid state via device_lid_open() + 2. Check setting: True/False/"Only when unplugged" + 3. On close + condition met: + ↓ +sleep_helper.sh: + 1. Logs current app activity STOP + 2. Creates sleep_helper_started marker + 3. Monitors power button via getevent + 4. Waits for shutdown timer (config-driven: 2m-60m) + 5. On timeout: + → save_poweroff.sh + 6. On power press before timeout: + → Resume game/app +``` + +## Configuration & Settings Management + +### Settings JSON Structure + +The main configuration file (`/mnt/SDCARD/spruce/-system.json`) contains: + +```json +{ + "menuOptions": { + "System Settings": { + "swapfileSize": { "selected": "256MB" }, + "useZRAM": { "selected": "False" }, + "overclockSpeedA30": { "selected": "1344" }, + "rumbleIntensity": { "selected": "Medium" }, + "enableLidSensor": { "selected": "True" }, + "checkForUpdates": { "selected": "True" } + }, + "Network Settings": { + "enableSamba": { "selected": "False" }, + "enableSSH": { "selected": "False" }, + "enableSFTPGo": { "selected": "False" }, + "enableSyncthing": { "selected": "False" } + }, + "Emulator Settings": { + "raAutoSave": { "selected": "Custom" }, + "raAutoLoad": { "selected": "Custom" }, + "perfectOverlays": { "selected": "False" } + }, + "Battery Settings": { + "shutdownFromSleep": { "selected": "5m" } + } + }, + "theme": "SPRUCE", + "wifi": 0 +} +``` + +### Configuration Hierarchy (Emulators) + +``` +/Emu//config.json → User settings per system +/Emu/.emu_setup/ → Factory defaults +/Emu//config/ → Runtime configs (platform-specific) +/Saves//config/ → User-modified configs +/Saves//.*.cfg → Platform-specific backups +``` + +## Key Dependencies & Sourcing Chains + +### Initialization Chain (Runtime Startup) + +``` +runtime.sh + ├── helperFunctions.sh + │ ├── platform/$PLATFORM.cfg (hardware definitions) + │ └── device_functions.sh + │ └── platform/$PLATFORM.sh + │ └── platform/device_functions/utils/*.sh + └── runtimeHelper.sh + ├── sambaFunctions.sh + └── sshFunctions.sh +``` + +### Emulator Launch Chain + +``` +/Emu//launch.sh → standard_launch.sh + ├── helperFunctions.sh + ├── emu/lib/general_functions.sh + │ ├── core_mappings.sh + │ └── emu/lib/_functions.sh + ├── emu/lib/led_functions.sh + ├── emu/lib/network_functions.sh + └── emu/lib/gtt_functions.sh +``` + +### Main Menu Cycle Chain + +``` +principal.sh + ├── helperFunctions.sh + ├── archiveUnpacker.sh → finish_unpacking() + ├── firstboot.sh (conditional) + └── /tmp/cmd_to_run.sh → emulator launch chain +``` + +## Cross-Script Communication + +### Flag System + +Temporary state markers stored in `/mnt/SDCARD/spruce/flags/`: + +```bash +flag_add "name" [--tmp] # Create flag file (--tmp = /tmp) +flag_check "name" # Test flag existence +flag_remove "name" # Delete flag + +# Common flags: +silentUnpacker, first_boot_$PLATFORM, in_menu, lastgame.lock, +low_battery, perfectOverlays, log_verbose, pb.longpress +``` + +### Temporary Files (Inter-Process Communication) + +| File | Purpose | +| --------------------------- | ------------------------------------ | +| `/tmp/cmd_to_run.sh` | Command passed from menu to launcher | +| `/tmp/powerbtn` | Power button state marker | +| `/tmp/sleep_helper_started` | Sleep mode active marker | +| `/tmp/host_msg` | Network broadcast message | + +### Log Files + +| Path | Purpose | +| ------------------------------------------ | ---------------------- | +| `/var/log/messages` | System event log | +| `/mnt/SDCARD/Saves/spruce/spruce.log` | Main application log | +| `/mnt/SDCARD/Saves/spruce/*.log` | Emulator-specific logs | +| `/mnt/SDCARD/Saves/spruce/battery_log.txt` | Battery history | + +## Documentation Reference + +For detailed information about specific topics, see: + +- **[FUNCTIONS.md](FUNCTIONS.md)** - Complete function reference for all scripts +- **[ENVIRONMENT_VARIABLES.md](ENVIRONMENT_VARIABLES.md)** - Environment variables used across scripts +- **[PLATFORM_ABSTRACTION.md](PLATFORM_ABSTRACTION.md)** - Platform-specific implementations +- **[EMULATOR_SYSTEM.md](EMULATOR_SYSTEM.md)** - Emulator launch and configuration system +- **[NETWORK_SERVICES.md](NETWORK_SERVICES.md)** - Network service configuration and management + +## Related Directories + +- **`/Emu/`** - Emulator installations and per-system configurations +- **`/Roms/`** - Game ROM storage organized by system +- **`/Saves/`** - Game saves, configurations, and screenshots +- **`/RetroArch/`** - RetroArch persistent configurations +- **`/Themes/`** - UI theme files and resources +- **`/App/`** - Utility applications + +## Notes for Developers + +1. **Always source `helperFunctions.sh` first** in scripts that need device detection or platform-specific code +2. **Use the flag system** for inter-process communication instead of temporary files when possible +3. **Platform-specific code** should be isolated in `platform/device_functions/` files +4. **Configuration values** are accessed via `get_config_value '.path.to.setting'` helper function +5. **Logging** should use the established log rotation and verbosity system +6. **Emulator setup** is handled by `standard_launch.sh`; don't replicate emulator-specific code in individual scripts + +## Support + +For issues or questions about specific script functionality, refer to the detailed documentation files listed above or examine the script source code with comments.