#!/bin/bash #============================================================================== # Arch R - EmulationStation Launch Script (boot-optimized) # Critical path: exports → audio init → ES start (~200ms overhead) # Everything else runs in background parallel with ES SDL init #============================================================================== # Boot timeline: log uptime at each key point _bt() { echo "[TIMELINE $(cut -d' ' -f1 /proc/uptime)s] $1" >> /home/archr/es-timeline.txt; } : > /home/archr/es-timeline.txt _bt "script_start (uid=$(id -u))" # Root guard: ES must run as archr, never as root if [ "$(id -u)" = "0" ]; then exec su -l archr -c "$(printf '%q ' "$0" "$@")" fi _bt "after_root_guard" # Blank screen immediately (hide login text) printf '\033[2J\033[H\033[?25l\033[30;40m' > /dev/tty1 2>/dev/null export HOME=/home/archr export SDL_ASSERT="always_ignore" export TERM=linux export XDG_RUNTIME_DIR="/run/user/$(id -u)" export SDL_VIDEODRIVER=KMSDRM export SDL_VIDEO_DRIVER=KMSDRM export SDL_GAMECONTROLLERCONFIG_FILE="/etc/archr/gamecontrollerdb.txt" export SDL_AUDIODRIVER=alsa export SDL_LOG_PRIORITY=error export SDL_LOGGING="*=error" export MESA_NO_ERROR=1 export MESA_SHADER_CACHE_DIR="$HOME/.cache/mesa_shader_cache" export MESA_SHADER_CACHE_MAX_SIZE=128M export MESA_DISK_CACHE_SINGLE_FILE=1 # === SYNCHRONOUS: Audio + brightness init === _bt "before_amixer" # Auto-detect ALSA control names (BSP: DAC/Playback Path, Mainline: Master/Playback Mux) if amixer sget 'Master' &>/dev/null; then ALSA_VOL=Master ALSA_PATH="Playback Mux" else ALSA_VOL=DAC ALSA_PATH="Playback Path" fi amixer -q sset "$ALSA_PATH" SPK 2>/dev/null # Restore saved volume (default 80% on first boot) VOL_SAVE="$HOME/.config/archr/volume" if [ -f "$VOL_SAVE" ]; then amixer -q sset "$ALSA_VOL" "$(cat "$VOL_SAVE")%" 2>/dev/null else amixer -q sset "$ALSA_VOL" 80% 2>/dev/null fi _bt "after_amixer" # === BACKGROUND: Everything else runs parallel with ES SDL init (~2s window) === ( # NOTE: fb0 blank removed — archr-splash.service writes splash to fb0, # which persists until ES takes DRM master via KMSDRM. # Permissions + governors (single sudo) sudo sh -c '/usr/local/bin/perfmax; chmod 666 /dev/tty1 /dev/dri/* /sys/class/backlight/backlight/brightness' 2>/dev/null # Brightness restore BRIGHT_SAVE="$HOME/.config/archr/brightness" if [ -f "$BRIGHT_SAVE" ]; then brightnessctl -q s "$(cat "$BRIGHT_SAVE")" 2>/dev/null else brightnessctl -q s 60% 2>/dev/null fi # Shader cache dir mkdir -p "$MESA_SHADER_CACHE_DIR" 2>/dev/null mkdir -p "$XDG_RUNTIME_DIR" # drirc [ ! -f "$HOME/.drirc" ] && echo '' > "$HOME/.drirc" 2>/dev/null # ES config setup mkdir -p "$HOME/.emulationstation" for cfg in es_systems.cfg es_input.cfg; do [ ! -f "$HOME/.emulationstation/$cfg" ] && [ -f "/etc/emulationstation/$cfg" ] && \ ln -sf "/etc/emulationstation/$cfg" "$HOME/.emulationstation/$cfg" done # Settings fix (single sed pass) CFG="$HOME/.emulationstation/es_settings.cfg" if [ -f "$CFG" ]; then sed -i \ -e 's|||; s|||' \ -e 's|"LogLevel" value="[^"]*"|"LogLevel" value="error"|' \ -e "s|\"AudioDevice\" value=\"[^\"]*\"|\"AudioDevice\" value=\"$ALSA_VOL\"|" \ "$CFG" C=$(< "$CFG") ADDS="" [[ "$C" == *'"HideWindow"'* ]] || ADDS="${ADDS}\n " [[ "$C" == *'"AudioDevice"'* ]] || ADDS="${ADDS}\n " [[ "$C" == *'"AudioCard"'* ]] || ADDS="${ADDS}\n " [[ "$C" == *'"EnableSounds"'* ]] || ADDS="${ADDS}\n " [ -n "$ADDS" ] && sed -i "s||$ADDS|" "$CFG" fi # Theme music symlinks (only if empty) MUSIC_DIR="$HOME/.emulationstation/music" mkdir -p "$MUSIC_DIR" if [ -z "$(ls -A "$MUSIC_DIR" 2>/dev/null)" ] && [ -f "$CFG" ]; then ACTIVE_THEME=$(grep -oP 'name="ThemeSet" value="\K[^"]+' "$CFG" 2>/dev/null) if [ -n "$ACTIVE_THEME" ] && [ -d "$HOME/.emulationstation/themes/$ACTIVE_THEME" ]; then find "$HOME/.emulationstation/themes/$ACTIVE_THEME" -maxdepth 4 \( -name '*.ogg' -o -name '*.mp3' \) 2>/dev/null | while read snd; do ln -sf "$snd" "$MUSIC_DIR/$(basename "$snd")" 2>/dev/null done fi fi # Battery SVG placeholders if [ -d "$HOME/.emulationstation/themes" ]; then for theme in "$HOME/.emulationstation/themes"/*/; do [ -d "$theme/_art" ] || continue BATT_DIR="$theme/_art/battery" [ ! -f "$BATT_DIR/full.svg" ] || continue mkdir -p "$BATT_DIR" for icon in incharge full 75 50 25 empty; do echo '' > "$BATT_DIR/$icon.svg" done done fi # Panfrost module check [ ! -d /sys/module/panfrost ] && sudo modprobe panfrost 2>/dev/null ) & # === Default ES settings (first boot only) === if [ ! -f "$HOME/.emulationstation/es_settings.cfg" ]; then mkdir -p "$HOME/.emulationstation" cat > "$HOME/.emulationstation/es_settings.cfg" << 'SETTINGS_EOF' SETTINGS_EOF fi # ES directory esdir="$(dirname "$0")" DEBUGLOG="$HOME/es-debug.log" [ -f "$DEBUGLOG" ] && mv -f "$DEBUGLOG" "${DEBUGLOG}.prev" 2>/dev/null # === MAIN LOOP === CRASH_COUNT=0 while true; do rm -f /tmp/es-restart /tmp/es-sysrestart /tmp/es-shutdown _bt "before_es_binary" "$esdir/emulationstation" "$@" >> "$DEBUGLOG" 2>&1 ret=$? if [ -f /tmp/es-restart ]; then CRASH_COUNT=0 continue fi if [ -f /tmp/es-sysrestart ]; then rm -f /tmp/es-sysrestart systemctl reboot break fi if [ -f /tmp/es-shutdown ]; then rm -f /tmp/es-shutdown sudo /usr/local/bin/pmic-poweroff 2>/dev/null systemctl poweroff break fi if [ $ret -ne 0 ]; then CRASH_COUNT=$((CRASH_COUNT + 1)) [ $CRASH_COUNT -ge 5 ] && break printf '\033[2J\033[H\033[?25l\033[30;40m' > /dev/tty1 2>/dev/null sleep 0.5 continue fi break done sudo /usr/local/bin/perfnorm 2>/dev/null exit $ret