Files
Arch-R/scripts/emulationstation.sh
Douglas Teles 06dc2d16f3 Add system scripts, services, and boot splash
System daemons: hotkeys (volume/brightness), automount, bluetooth agent,
memory manager, sleep/suspend, USB gadget mode, save-config persistence.

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

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

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

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

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 17:22:30 -03:00

199 lines
7.0 KiB
Bash

#!/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 '<?xml version="1.0"?><driconf/>' > "$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|<settings>|<config>|; s|</settings>|</config>|' \
-e 's|"LogLevel" value="[^"]*"|"LogLevel" value="error"|' \
-e "s|\"AudioDevice\" value=\"[^\"]*\"|\"AudioDevice\" value=\"$ALSA_VOL\"|" \
"$CFG"
C=$(< "$CFG")
ADDS=""
[[ "$C" == *'"HideWindow"'* ]] || ADDS="${ADDS}\n <bool name=\"HideWindow\" value=\"true\" />"
[[ "$C" == *'"AudioDevice"'* ]] || ADDS="${ADDS}\n <string name=\"AudioDevice\" value=\"$ALSA_VOL\" />"
[[ "$C" == *'"AudioCard"'* ]] || ADDS="${ADDS}\n <string name=\"AudioCard\" value=\"default\" />"
[[ "$C" == *'"EnableSounds"'* ]] || ADDS="${ADDS}\n <bool name=\"EnableSounds\" value=\"true\" />"
[ -n "$ADDS" ] && sed -i "s|<config>|<config>$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 '<svg xmlns="http://www.w3.org/2000/svg" width="1" height="1"/>' > "$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'
<?xml version="1.0"?>
<config>
<int name="MaxVRAM" value="150" />
<bool name="HideWindow" value="true" />
<string name="LogLevel" value="error" />
<string name="AudioCard" value="default" />
<string name="AudioDevice" value="Master" />
<bool name="EnableSounds" value="true" />
<string name="ScreenSaverBehavior" value="black" />
<string name="TransitionStyle" value="instant" />
<string name="SaveGamelistsMode" value="on exit" />
<bool name="DrawClock" value="false" />
<bool name="QuickSystemSelect" value="false" />
<string name="CollectionSystemsAuto" value="favorites,recent" />
<string name="FolderViewMode" value="always" />
</config>
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