#!/usr/bin/env bash ############################################################################### # GEEKCADE MANAGEMENT MENU # Cabinet Boot/Admin Console # Version: v2.0 (build 38) # # Boot behavior: # - tty1 auto-login runs this script via .bash_profile # - Boot gate: 5s countdown; any key -> menu, otherwise -> AM+ # - When AM+ exits, getty@tty1 is restarted to clear stuck KMSDRM # keyboard grabs from MAME's SDL2 backend. # - On the next login, .bash_profile runs this script again, but the # boot gate is suppressed (via /tmp/.geekcade_skip_gate) so we land # directly in the menu instead of relaunching AM+. # # Assumptions: # - Ubuntu is already installed # - User "geekcade" exists # - GeekCade installer has created: # /home/geekcade/mame # /home/geekcade/attractplus # /home/geekcade/mame.sh # /home/geekcade/attractplus.sh ############################################################################### # ============================== # [0] CONFIG & PATHS # ============================== BASE_DIR="$HOME" INSTALL_SCRIPT_PATH="$BASE_DIR/geekcade_install.sh" MENU_SCRIPT_PATH="$BASE_DIR/geekcade_menu.sh" # All GeekCade-hosted files live at this base URL. Override with: # GEEKCADE_BASE_URL=http://other.host/path ./geekcade_menu.sh GEEKCADE_BASE_URL="${GEEKCADE_BASE_URL:-https://install.geekcade.com/deploy}" INSTALL_SCRIPT_URL="${GEEKCADE_BASE_URL}/geekcade_install.sh" MENU_SCRIPT_URL="${GEEKCADE_BASE_URL}/geekcade_menu.sh" MAME_DIR="$BASE_DIR/mame" ATTRACT_DIR="$BASE_DIR/attractplus" LOG_DIR="$BASE_DIR/logs" MAME_LAUNCHER="$BASE_DIR/mame.sh" ATTRACT_LAUNCHER="$BASE_DIR/attractplus.sh" SUCCESS_FLAG_FILE="$BASE_DIR/.geekcade_install_success" # Used to signal "skip the boot gate, go straight to the menu" - set # right before we restart getty@tty1, so the next login lands in the # menu instead of bouncing right back into AM+. SKIP_GATE_FLAG="/tmp/.geekcade_skip_gate" # Boot admin-gate timeout in seconds AUTO_MENU_TIMEOUT="${AUTO_MENU_TIMEOUT:-5}" # Stable PATH export PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games" # Scrollable logs export LESS='-R' # ============================== # [1] COLORS # ============================== GREEN=$'\033[0;32m' RED=$'\033[0;31m' YELLOW=$'\033[1;33m' CYAN=$'\033[0;36m' NC=$'\033[0m' # ============================== # [2] UI HELPERS # ============================== display_banner() { clear echo -e "${GREEN}" cat << "EOF" ____ _ ____ _ / ___| ___ ___| | __/ ___|__ _ __| | ___ | | _ / _ \/ _ \ |/ / | / _` |/ _` |/ _ \ | |_| | __/ __/ <| |__| (_| | (_| | __/ \____|\___|\___|_|\_\\____\__,_|\__,_|\___| EOF echo -e " Cabinet Menu v2.0 (build 38)${NC}" echo } pause_menu() { echo read -n 1 -s -r -p "Press any key to continue..." echo } display_stats() { local mame_version="Not Installed" local attract_version="Not Installed" local rom_count="0" local install_status="${YELLOW}Incomplete${NC}" local layout_name="Unknown" # MAME version - call binary directly to avoid any launcher side effects if command -v /usr/games/mame >/dev/null 2>&1; then mame_version="$(/usr/games/mame -version 2>&1 | head -n1 | sed 's/ ([^)]*)//')" elif command -v mame >/dev/null 2>&1; then mame_version="$(command mame -version 2>&1 | head -n1 | sed 's/ ([^)]*)//')" else mame_version="${RED}Not Installed${NC}" fi # Attract-Mode Plus version - call binary directly (NOT through launcher # or alias) so we just print version and exit if command -v attractplus >/dev/null 2>&1; then attract_version="$(command attractplus --version 2>/dev/null | head -n1 || true)" [ -z "$attract_version" ] && attract_version="${GREEN}Installed${NC}" elif command -v attract >/dev/null 2>&1; then attract_version="$(command attract --version 2>/dev/null | head -n1 || true)" [ -z "$attract_version" ] && attract_version="${GREEN}Installed${NC}" else attract_version="${RED}Not Installed${NC}" fi # ROM count if [ -d "$MAME_DIR/roms" ]; then rom_count="$(find "$MAME_DIR/roms" -type f 2>/dev/null | wc -l | xargs)" fi # Install status if [ -f "$SUCCESS_FLAG_FILE" ]; then install_status="${GREEN}Complete${NC}" fi # Layout if [ -f "$ATTRACT_DIR/attract.cfg" ]; then layout_name="$(grep -E '^[[:space:]]*layout[[:space:]]+' "$ATTRACT_DIR/attract.cfg" | awk '{print $2}' | head -n1)" [ -z "$layout_name" ] && layout_name="Not set" fi echo -e "${CYAN}----------------------------------------------------${NC}" echo -e " ${YELLOW}System Status${NC}" echo -e "${CYAN}----------------------------------------------------${NC}" printf " %-16s %b\n" "MAME Version:" "$mame_version" printf " %-16s %b\n" "Attract-Mode:" "$attract_version" printf " %-16s %s\n" "MAME ROMs:" "$rom_count" printf " %-16s %b\n" "Setup Status:" "$install_status" printf " %-16s %s\n" "Layout:" "$layout_name" printf " %-16s %s\n" "MAME Dir:" "$MAME_DIR" printf " %-16s %s\n" "Attract Dir:" "$ATTRACT_DIR" echo -e "${CYAN}----------------------------------------------------${NC}" echo } display_menu() { echo -e "${YELLOW}Please choose an option:${NC}" echo " 1) Launch Attract-Mode" echo " 2) Sync Assets from USB" echo " 3) Rebuild Attract-Mode MAME Romlist" echo " 4) View Latest Installer Log" echo " 5) Check for System Updates (apt)" echo " 6) Download Latest GeekCade Installer" echo " 7) Download Latest GeekCade Menu" echo " 8) Run Installer - COMPILE Attract-Mode Plus" echo " 9) Run Installer - RELEASE Attract-Mode Plus" echo " 10) Run Installer - SKIP Attract-Mode Plus" echo " 11) Reboot System" echo " 12) Shutdown System" echo echo " q) Exit to Shell" echo } # ============================== # [3] CABINET INPUT RECOVERY # ============================== # After AM+ (or anything that ran MAME) exits, SDL2's KMSDRM backend can # leave systemd-logind holding /dev/input/event* exclusively, freezing # keyboard input on tty1. The reliable cure is to restart getty@tty1 # which kills our shell session and respawns a clean login. The next # login will hit .bash_profile -> this script again, and we want it to # land directly in the menu (not bounce back into AM+), so we touch a # flag first that the boot gate honors. recover_tty_and_relaunch_menu() { touch "$SKIP_GATE_FLAG" echo echo -e "${YELLOW}Resetting tty1 input (returning to menu)...${NC}" sleep 1 sudo /bin/systemctl restart getty@tty1 # systemctl will kill this shell; if for some reason it returns, # fall through and exit so .bash_profile reruns naturally. exit 0 } # ============================== # [4] ACTIONS # ============================== # Shared download helper. Args: