Skip to content

Instantly share code, notes, and snippets.

@etheling
Last active Apr 18, 2021
Embed
What would you like to do?
Installation 'recipe' for RetroPie on Ubuntu to run in KMS/DRM mode
#!/bin/bash
##
## Configure RetroPie to run under Linux KMS/DRM mode on Ubuntu 20.04 LTS.
## Supports only Intel (and virtual) framebuffers. Specifically nVidia and
## Radeon based systems are not properly set up by this script.
##
## Optional post-install setup-script (set __has_kms to enable) for
## https://github.com/MizterB/RetroPie-Setup-Ubuntu/blob/master/retropie_setup_ubuntu.sh
## and install this script to ~/optional_scripts/post_install before running ./retropie_setup_ubuntu.sh
## Control behaviour of script
__XRES="1920" # target X & Y resolution (1080p)
__YRES="1080"
#__FB_DEV="/dev/fb0" # set to skip i915 detection
#__KOPT_VIDEO=... # set to skip resolution probing
#__KEEP_SPLASH=1 # set to keep plymouth/splash
__SLEEP=2 # delay between tasks
## TODO:
## - Enable early KMS start (https://wiki.archlinux.org/index.php/Kernel_mode_setting#Early_KMS_start)
## - Support radeon, maybe nvidia
## - Consider https://wiki.archlinux.org/index.php/intel_graphics#Enable_GuC_/_HuC_firmware_loading
## - Warn nvidia or radeon cards are found
##
USER="$SUDO_USER"
USER_HOME="/home/$USER"
if [ -z $SCRIPT_DIR ]; then
SCRIPT_DIR=$(dirname $(realpath $0))
fi
# Backup system config file(s) before modifications (Eth)
function backupFile() {
if [ ! -f "$1" ] ; then
echo "-> backupFile: $1 does not exist. Not creating $1.orig"
return
fi
if [ ! -f "$1.orig" ]; then
echo "-> Backing up $1 -> $1.orig"
cp $1 $1.orig
else
echo "-> backupFile: $1.orig already exists (and cowardly refusing to overwrite)"
fi
}
##
function install_kmsdrm_depends() {
echo "--------------------------------------------------------------------------------"
echo "| install_kmsdrm_depends: TBD"
echo "--------------------------------------------------------------------------------"
apt-get install -y fbset
echo -e "FINISHED install_kmsdrm_depends \n\n"
sleep $__SLEEP
}
## Set FB_DEV, and set FB_i915 if i915 found
function is_it_i915_fb() {
echo "--------------------------------------------------------------------------------"
echo "| find_i915_fb: TBD"
echo "--------------------------------------------------------------------------------"
## TODO: early exit if FB_DEV is set
local __fb="null"
local __tmp_fb="/dev/fb0"
## Assumes single display setup; one display ought to be enough for anybody...
if [ ! $(cat /proc/fb | wc -l) -eq 1 ]; then
echo "WARNING: More than one framebuffer found. This may produce unexpected results."
fi
## https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/6/html/deployment_guide/s2-proc-fb
echo "-> Probe /proc/fb to find if we have intel i915 framebuffer"
__fb=$(cat /proc/fb | grep i915drmfb)
if [ ! $? -eq 0 ]; then
echo "-> Cannot find i915 framebuffer. Available framebuffers / displays are:"
ls -l /dev/fb*
cat /proc/fb
lshw -c display -short
FB_DEV=$__tmp_fb
echo "-> Using /dev/fb0 for configuration"
else
export FB_DEV="/dev/fb$(echo $__fb | cut -d' ' -f1)"
FB_i915=1
echo "-> Found i915drmfb. Framebuffer device is $FB_DEV ($__fb)"
fi
## Test that ($FB_DEV) is FB that we're (propably) looking at...
fbset -fb $FB_DEV > /dev/null 2>&1
if [ ! $? -eq 0 ]; then
echo "ERROR: cannot verify that $FB_DEV is usable. Reverting back to $__tmp_fb"
unset FB_i915
export FB_DEV=$__tmp_fb
fi
echo -e "FINISHED is_it_i915_fb \n\n"
sleep $__SLEEP
}
# Useful for getting systems with max resolution less than 1080p configured
function find_fb_max_resolution() {
echo "--------------------------------------------------------------------------------"
echo "| Detect if framebuffer supports ${__XRES}x${__YRES}, if not try to determine"
echo "| usable resolution (using $FB_DEV)"
echo "--------------------------------------------------------------------------------"
local __fb=$FB_DEV
local __x=$__XRES
local __y=$__YRES
echo "/proc/fb: "
cat /proc/fb
fbset -fb $__fb -s
## Test if we can set 1080p
echo "-> Testing if we can set framebuffer $__fb to $__XRES x $__YRES resolution"
fbset --test -fb $__fb -xres $__XRES -yres $__YRES -match
if [ ! $? -eq 0 ]; then
## Note: on VMs we might get lower then max, but on real hw, expectation is max supported (assuming kernel supports hw)
echo "-> 1080p does not appear to be supported by $__fb. Getting current resolution."
local __tempres=`sudo fbset -fb $__fb -s | sed -n -e 's/^.*geometry //p'`
__XRES=`echo $__tempres | cut -d' ' -f1`
__YRES=`echo $__tempres | cut -d' ' -f2`
## double check that what we got can be set
fbset --test -fb $__fb -xres $__XRES -yres $__YRES -match
if [ ! $? -eq 0 ]; then
echo "ERROR: cannot determine appropriate resolution. Falling back to 1920x1080."
echo " It is likely you will experience resolution issues"
__XRES=$__x
__YRES=$__y
fi
## TODO: test if we ended up with larger than 1080p for some reason
fi
echo "-> Using $__XRES x $__YRES for X and framebuffer default resolutions"
echo -e "FINISHED find_fb_max_resolution \n\n"
sleep $__SLEEP
}
## Build video= kernel boot option string. Assumes only one connected display; falls back
## to generic form if multiple connected displays
function build_kernel_video_option() {
echo "--------------------------------------------------------------------------------"
echo "| Construct video= kernel boot option from /sys/class/drm/card*"
echo "--------------------------------------------------------------------------------"
local __card="null"
# determine video= parameter(s)
echo "-> List of output ports under /sys/class/drm/*:"
for p in /sys/class/drm/*/status; do con=${p%/status}; echo -n "${con#*/card?-}: "; cat $p; done
if [ ! $(cat /sys/class/drm/*/status | grep -w "connected" | wc -l) -eq 1 ]; then
__KOPT_VIDEO="video=${__XRES}x${__YRES}"
echo "WARNING: multiple (or zero) connected displays found. This is untested setup."
echo " Falling back to generic $__KOPT_VIDEO kernel parameter."
return
fi
for i in /sys/class/drm/*/status ; do
cat $i | grep -w 'connected' > /dev/null
if [ $? -eq 0 ]; then
__card=$i
break
fi
done
#echo $CARD | cut -d'/' -f5 | cut -d'-' -f2-
__KOPT_VIDEO="video=$(echo $__card | cut -d'/' -f5 | cut -d'-' -f2-):${__XRES}x${__YRES}"
echo "-> Kernel video boot option: ${__KOPT_VIDEO}"
echo -e "FINISHED build_kernel_video_option \n\n"
sleep $__SLEEP
}
# Sets the GRUB graphics mode
# URL: https://www.gnu.org/software/grub/manual/grub/html_node/gfxmode.html
function update_grub_resolution() {
if [[ -z "$1" ]]; then
MODES="auto"
else
MODES="$1,auto"
fi
echo "--------------------------------------------------------------------------------"
echo "| Changing the GRUB graphics mode to '$MODES' and adds"
echo "| GRUB_GFXPAYLOAD_LINUX=\"keep\" to minimize display mode switching"
echo "--------------------------------------------------------------------------------"
local __ggpl=""
grep GRUB_GFXPAYLOAD_LINUX /etc/default/grub > /dev/null 2>&1
if [ ! $? -eq 0 ]; then
__ggpl="\\nGRUB_GFXPAYLOAD_LINUX=\"keep\""
fi
sed -i "s/GRUB_GFXMODE=.*/GRUB_GFXMODE=${MODES}${__ggpl}/g" "/etc/default/grub"
update-grub
egrep "(GRUB_GFXMODE|GRUB_GFXPAYLOAD)" /etc/default/grub
echo -e "FINISHED update_grub_resolution \n\n"
sleep $__SLEEP
}
# Eth:
# Sets FB resolution using video= kernel boot parameter
function set_kernel_fb_resolution() {
echo "--------------------------------------------------------------------------------"
echo "| Adding video=${__XRES}x${__YRES} kernel parameter to /etc/default/grub"
echo "--------------------------------------------------------------------------------"
backupFile /etc/default/grub
if [ -z $__KOPT_VIDEO ]; then
build_kernel_video_option
fi
local __KOPT_MS=""
if [ ! -z $FB_i915 ]; then
## https://wiki.archlinux.org/index.php/Intel_graphics
__KOPT_MS="i915.modeset=1 "
echo "-> FB_i915 set. Adding option $__KOPT_MS"
fi
## https://retropie.org.uk/forum/topic/18810/retropie-installation-on-ubuntu-server-x64-18-04-1/161
sed -i "s/GRUB_CMDLINE_LINUX_DEFAULT=\"[^\"]*/& ${__KOPT_MS}${__KOPT_VIDEO}/" /etc/default/grub
update-grub
grep "GRUB_CMDLINE_LINUX_DEFAULT" /etc/default/grub
echo -e "FINISHED set_kernel_fb_resolution \n\n"
sleep $__SLEEP
}
# Eth:
function install_xorgconf() {
XORGCONF="/etc/X11/xorg.conf"
echo " "
echo "+-------------------------------------------------------------------------------"
echo "| Install $XORGCONF to set default X11 resolution to match"
echo "| console resoluton (${__XRES}x${__YRES}) to avoid mode switches during boot"
echo "+-------------------------------------------------------------------------------"
backupFile $XORGCONF
cat << EOF > $XORGCONF
## Sets X startup resolution to $__XRES x $__YRES as to avoid modeswitch
## https://wiki.ubuntu.com/X/Config/Resolution
Section "Monitor"
Identifier "Configured Monitor"
EndSection
Section "Screen"
Identifier "Default Screen"
Monitor "Configured Monitor"
Device "Configured Video Device"
SubSection "Display"
Virtual $__XRES $__YRES
EndSubSection
EndSection
Section "Device"
Identifier "Configured Video Device"
EndSection
EOF
chown root:root $XORGCONF
#rw-r--r--
chmod 644 $XORGCONF
echo -e "FINISHED xorg_conf \n\n"
sleep $__SLEEP
}
## .xsession that supports launching openbox, or a port; resolution set via /etc/X11/...
function rewrite_xsession() {
echo "--------------------------------------------------------------------------------"
echo "| FIXME: Update .xsession"
echo "--------------------------------------------------------------------------------"
backupFile $USER_HOME/.xsession
cat << EOF > $USER_HOME/.xsession
## Support launching openbox and full screen games via RetroPie ports
## document xrandr output \$XRANDR_LOG
XRANDR_LOG=/dev/shm/xrand_modes.log
xrandr --version >> \$XRANDR_LOG 2>&1
xrandr >> \$XRANDR_LOG 2>&1
# Disable screen blanking (only happens outside of EmulationStation)
# This prevents the display from doing any ‘screen blanking’ due to inactivity
xset s off && xset -dpms
if [ ! -f /dev/shm/portruncommand.sh ] ; then
exec openbox-session
else
## don't exec; we want to return & exit
/dev/shm/portruncommand.sh
fi
EOF
echo -e "FINISHED rewrite_xsession \n\n"
sleep $__SLEEP
}
## Eth: Start emulationstation as soon as user is logged in
function enable_autostart_emulationstation() {
echo "--------------------------------------------------------------------------------"
echo "| Enabling autostart of EmulationStation in KMS/DRM mode via .bash_profile"
echo "--------------------------------------------------------------------------------"
backupFile $USER_HOME/.bash_profile
sed -i '/startx/a\ emulationstation' $USER_HOME/.bash_profile
sed -i '/startx/a\ # dont exec emulationstation: otherwise ES gets restarted on exit (F4)' $USER_HOME/.bash_profile
sed -i 's/.*startx/#&/' $USER_HOME/.bash_profile
chown $USER:$USER $USER_HOME/.bash_profile
echo -e "FINISHED enable_autostart_emulationstation \n\n"
sleep $__SLEEP
}
function disable_plymouth_splash() {
echo "--------------------------------------------------------------------------------"
echo "| Disable Plymouth theme by removing splash from /etc/default/grub"
echo "--------------------------------------------------------------------------------"
backupFile /etc/default/grub
## TODO: purge plymouth?
## TODO: etc/default/grub *should* not have other lines with 'splash'....but
sed -i 's/\<splash\>//g' /etc/default/grub
update-grub
echo -n "-> Updated /etc/default/grub:GRUB_CMDLINE_LINUX_DEFAULT:"
grep "GRUB_CMDLINE_LINUX_DEFAULT" /etc/default/grub
echo -e "FINISHED disable_plymouth_splash \n\n"
sleep $__SLEEP
}
function fix_quirks_kmsdrm() {
echo "--------------------------------------------------------------------------------"
echo "| Fixing any known quirks for KMS/DRM mode"
echo "--------------------------------------------------------------------------------"
echo " "
echo "+-------------------------------------------------------------------------------"
echo "| Add rpie user to the input group to allow /dev/input/* access"
echo "| (needed for KSM/DRM mode with linxuraw/udev access"
echo "+-------------------------------------------------------------------------------"
## https://github.com/libretro/RetroArch/issues/5033
## done already in helpers.sh: echo 'SUBSYSTEM=="input", GROUP="input", MODE="0660"' > /etc/udev/rules.d/99-input.rules
usermod -a -G input $USER
FBSET=`which fbset`
echo " "
echo "+-------------------------------------------------------------------------------"
echo "| Allow $FBSET to be executed by non-root users"
echo "| (used by /opt/retropie/supplementary/runcommand/runcommand.sh)"
echo "+-------------------------------------------------------------------------------"
## https://stackoverflow.com/questions/53052294/managing-linux-framebufferfb0-permission-in-low-level-c-graphics-code
usermod -a -G video $USER
chgrp video /usr/bin/fbset
chmod g+s $FBSET
echo " "
echo "+-------------------------------------------------------------------------------"
echo "| Update /opt/retropie/config/all/retroarch.cfg to use audio_driver = alsa"
echo "| (needed by KMS/DRM)"
echo "+-------------------------------------------------------------------------------"
cp -fv /opt/retropie/configs/all/retroarch.cfg /opt/retropie/configs/all/retroarch.cfg.orig
sed -i '/# audio_driver =/c\audio_driver = \"alsa\"' /opt/retropie/configs/all/retroarch.cfg
echo -e "FINISHED fix_quirks_kmsdrm \n\n"
sleep $__SLEEP
}
# Install latest stock libsdl2
function install_local_libsdl2_with_kmsdrm() {
echo "--------------------------------------------------------------------------------"
echo "| Install local libsdl2 with KMS/DRM enabled"
echo "--------------------------------------------------------------------------------"
echo "-> Remove (possible) hold on libsdl2-dev package"
dpkg --list | grep sdl2
## unhold all packages. But because this is fresh install, onluy libsdl2-dev should be on hold if installed by retropie
## https://askubuntu.com/questions/164587/how-can-you-unhold-remove-a-hold-on-a-package
apt-mark unhold $(apt-mark showhold)
echo "-> Install depends. Most/all should be installed already."
apt-get install -y libasound2-dev libudev-dev libibus-1.0-dev libdbus-1-dev fcitx-libs-dev libsndio-dev libsamplerate0-dev libpulse-dev libwayland-dev libdrm-dev libgbm-dev
#git clone https://github.com/RetroPie/SDL-mirror "retropie-2.0.10"
#cd retropie-2.0.10
# for some reason git clone https://github.com/RetroPie/SDL-mirror "retropie-2.0.10" version doesn't work
echo "-> Get latest version of libsdl2"
cd $USER_HOME
## sha1sum of SDL2-2.0.12.tar.gz from libsdl.org on 20201015 - do at least minimal effort
## to check that we're getting what we're expecting (https://www.gnupg.org/download/integrity_check.html)
#local __SHA1SUM="e8ba91bf5eb438dbcf1fedf0530a1bcbe30d3bb6"
#wget https://www.libsdl.org/release/SDL2-2.0.12.tar.gz
local __LIBSDL2="SDL2-2.0.14"
local __SDL2VER=$(echo ${__LIBSDL2} | cut -d- -f2)
local __SHA1SUM="212b17d988c417a1a905ab09c50d1845cc48ddb7"
wget https://www.libsdl.org/release/${__LIBSDL2}.tar.gz
local __SHA1SUMNEW=`sha1sum ./${__LIBSDL2}.tar.gz | cut -d' ' -f1`
if [ "$__SHA1SUM" != "$__SHA1SUMNEW" ]; then
echo "ERROR: sha1sum of downloaded file doesn't match with previously recorded value."
echo "ERROR: make sure ${__LIBSDL2}.tar.gz has not been tampered with. Aborting."
exit 1
fi
tar zxf ${__LIBSDL2}.tar.gz
cd ${__LIBSDL2}
./configure --enable-video-kmsdrm --prefix=/usr/local/lib/libsdl2-${__SDL2VER}
make -j`grep -c ^processor /proc/cpuinfo`
make install
echo "-> Add local libsdl2 to ld.so.cache. Current versions of SDL2 are:"
ldconfig -p | grep SDL
echo "-> cat /etc/ld.so.conf.d/x86_64-linux-gnu.conf for library paths/search order"
cat /etc/ld.so.conf.d/x86_64-linux-gnu.conf
## FIXME: read in first uncommented line and use that (should be /usr/local/lib/x86_64-linux-gnu on 20.04)
mkdir -p /usr/local/lib/x86_64-linux-gnu
echo "-> symlink to installed .so and rebuild ld.so.cache"
ln -s /usr/local/lib/libsdl2-${__SDL2VER}/lib/libSDL2-2.0.so.0 /usr/local/lib/x86_64-linux-gnu
ldconfig
echo "-> ld.so.cache entries for libsdl2:"
ldconfig -p | grep SDL
echo "-> test that retroarch uses this copy"
ldd /opt/retropie/emulators/retroarch/bin/retroarch | grep libSDL2
cd $USER_HOME
mv -v ${__LIBSDL2} RetroPie-Setup/
mv -v ${__LIBSDL2}.tar.gz RetroPie-Setup/
echo -e "FINISHED install_local_libsdl2_with_kmsdrm \n\n"
sleep $__SLEEP
}
function disable_es_openbox_autostart() {
echo "--------------------------------------------------------------------------------"
echo "| disable ES start from ~/.config/openbox/autostart as it is now laucnhed"
echo "| from ~/.bash_profile"
echo "--------------------------------------------------------------------------------"
backupFile $USER_HOME/.config/openbox/autostart
sed -i 's/.*autostart/#&/' $USER_HOME/.config/openbox/autostart
## TODO: maybe don't disable unclutter
sed -i 's/.*unclutter/#&/' $USER_HOME/.config/openbox/autostart
echo -e "FINISHED disable_es_openbox_autostart \n\n"
sleep $__SLEEP
}
function normalize_gnome_terminal() {
echo "--------------------------------------------------------------------------------"
echo "| Comment out gnome terminal modifications from ~/.bash_profile"
echo "--------------------------------------------------------------------------------"
backupFile $USER_HOME/.bash_profile
sed -i 's/.*gsettings/#&/' $USER_HOME/.bash_profile
mv -v $USER_HOME/.config/openbox/rc.xml $USER_HOME/.config/openbox/rc.xml.retropie
echo -e "FINISHED normalize_gnome_terminal \n\n"
sleep $__SLEEP
}
function are_we_root() {
# Make sure the user is running the script via sudo
if [ -z "$SUDO_USER" ]; then
echo "This script requires sudo privileges. Please run with: sudo $0"
exit 1
fi
# Don't allow the user to run this script from the root account. RetroPie doesn't like this.
if [[ "$SUDO_USER" == root ]]; then
echo "This script cannot be run by the root user. Please run as normal user using sudo."
exit 1
fi
}
### 1,2,3,...
if [ ! -z $__has_kms ]; then
are_we_root
echo "KMS/DRM setup activated."
echo ""
echo "Configure RetroPie to run under Linux KMS/DRM mode on Ubuntu 20.04 LTS."
echo "Supports only Intel (and virtual) framebuffers. Specifically nVidia and"
echo "Radeon based systems are not properly set up by this script."
install_kmsdrm_depends
is_it_i915_fb # Find if we have i915 FB
find_fb_max_resolution # Find if FB can support 1080p; if not try to find lower working resolution
update_grub_resolution "${__XRES}x${__YRES}x32,1920x1440x32"
set_kernel_fb_resolution # Sets kernel video=
install_xorgconf # create /etc/X11/xorg.conf (match FB resolution)
fix_quirks_kmsdrm
install_local_libsdl2_with_kmsdrm
## Roll back / modify changes
enable_autostart_emulationstation
rewrite_xsession
disable_es_openbox_autostart
normalize_gnome_terminal
if [ -z $__KEEP_SPLASH]; then
disable_plymouth_splash
fi
else
echo "-> __has_kms is not set. Skipping KMS/DRM setup."
fi
#! /bin/bash
# https://github.com/MizterB/RetroPie-Setup-Ubuntu/blob/master/retropie_setup_ubuntu.sh
## Optional features (Eth:)
export __has_kms=1 # if set, setup to run in KMS mode (Intel only)
# Computed variables
USER="$SUDO_USER"
USER_HOME="/home/$USER"
SCRIPT_PATH="$(realpath $0)"
SCRIPT_DIR="$(dirname $SCRIPT_PATH)"
SCRIPT_FILE="$(basename $SCRIPT_PATH)"
LOG_FILE="$SCRIPT_DIR/$(basename $0 .sh)-$(date +"%Y%m%d_%H%M%S").log"
OPTIONAL_SCRIPT_DIR="$SCRIPT_DIR/optional_scripts"
# Global setting for APT recommended packages - leave blank for now.
# It's a little more bloated, but we can't get a clean boot without it.
#APT_RECOMMENDS="–no-install-recommends"
APT_RECOMMENDS=
# Minimal depedencies to install RetroPie on Ubuntu
RETROPIE_DEPENDS=(
xorg openbox pulseaudio alsa-utils menu libglib2.0-bin python3-xdg
at-spi2-core libglib2.0-bin dbus-x11 git dialog unzip xmlstarlet joystick
triggerhappy
# Eth: needed if building retroarch with __has_kms set (ideally should be in
# in retroarch.sh, but maybe it's more robust to add it here)
libdrm-dev
)
# Helpful packages to improve usability
#--------------------------------------------------------------------------------
# openssh-server Remote administration, copy/paste
# xdg-utils Eliminates 'xdg-screensaver not found' error
# unclutter Hides mouse cursor when not being used
# inxi Queries video driver information
#--------------------------------------------------------------------------------
EXTRA_TOOLS=(
openssh-server xdg-utils unclutter inxi
)
# Output to both console and log file
function enable_logging() {
echo "--------------------------------------------------------------------------------"
echo "| Saving console output to '$LOG_FILE'"
echo "--------------------------------------------------------------------------------"
touch $LOG_FILE
exec > >(tee $LOG_FILE) 2>&1
sleep 2
}
# Install RetroPie dependencies
function install_retropie_dependencies() {
echo "--------------------------------------------------------------------------------"
echo "| Updating OS packages and installing RetroPie dependencies"
echo "--------------------------------------------------------------------------------"
apt-get update && apt-get -y upgrade
apt-get install -y $APT_RECOMMENDS ${RETROPIE_DEPENDS[@]}
echo -e "FINISHED install_retropie_dependencies \n\n"
sleep 2
}
## Eth:
function patch_systemsh_kmsdrm() {
# https://retropie.org.uk/forum/topic/28159/update-retroarch-sh-to-enable-kms-drm-on-x11-platform/4
echo "-> __has_kms= set. Enabling KMS/DRM support in RetroPie."
echo "-> patch RetroPie-Setup/scriptmodules/system.sh to enable both x11 and kms on x86"
SYSTEMSH="$USER_HOME/RetroPie-Setup/scriptmodules/system.sh"
cat << EOF >> $SYSTEMSH.patch
518c518,519
< __platform_flags+=(kms)
---
> ## modify non-default path to contain x11 (and kms)
> __platform_flags+=(x11 kms)
EOF
cp -v $SYSTEMSH $SYSTEMSH.orig
patch $SYSTEMSH $SYSTEMSH.patch
}
# Install RetroPie
function install_retropie() {
echo "--------------------------------------------------------------------------------"
echo "| Installing RetroPie"
echo "--------------------------------------------------------------------------------"
# Get Retropie Setup script and perform an install of same packages
# used in the RetroPie image (as applicable)
# See https://github.com/RetroPie/RetroPie-Setup/blob/master/scriptmodules/admin/image.sh
cd $USER_HOME
git clone --depth=1 https://github.com/RetroPie/RetroPie-Setup.git
## Eth:
if [ ! -z $__has_kms ]; then
# https://retropie.org.uk/forum/topic/28159/update-retroarch-sh-to-enable-kms-drm-on-x11-platform/4
patch_systemsh_kmsdrm
fi
$USER_HOME/RetroPie-Setup/retropie_packages.sh setup basic_install
$USER_HOME/RetroPie-Setup/retropie_packages.sh bluetooth depends
$USER_HOME/RetroPie-Setup/retropie_packages.sh usbromservice
$USER_HOME/RetroPie-Setup/retropie_packages.sh samba depends
$USER_HOME/RetroPie-Setup/retropie_packages.sh samba install_shares
$USER_HOME/RetroPie-Setup/retropie_packages.sh splashscreen default
$USER_HOME/RetroPie-Setup/retropie_packages.sh splashscreen enable
$USER_HOME/RetroPie-Setup/retropie_packages.sh xpad
chown -R $USER:$USER $USER_HOME/RetroPie-Setup
echo -e "FINISHED install_retropie \n\n"
sleep 2
}
# Install RetroArch shaders from official repository
function install_retroarch_shaders() {
echo "--------------------------------------------------------------------------------"
echo "| Remove the RPi shaders installed by RetroPie-Setup and replace with"
echo "| RetroArch (merge of common & GLSL, and new Slang) shaders from Libretro"
echo "--------------------------------------------------------------------------------"
# Cleanup pi shaders installed by RetroPie-Setup
rm -rf /opt/retropie/configs/all/retroarch/shaders
mkdir -p /opt/retropie/configs/all/retroarch/shaders
# Install common shaders from Libretro repository
git clone --depth=1 https://github.com/libretro/common-shaders.git /tmp/common-shaders
cp -r /tmp/common-shaders/* /opt/retropie/configs/all/retroarch/shaders/
rm -rf /tmp/common-shaders
# Install GLSL shaders from Libretro repository
git clone --depth=1 https://github.com/libretro/glsl-shaders.git /tmp/glsl-shaders
cp -r /tmp/glsl-shaders/* /opt/retropie/configs/all/retroarch/shaders/
rm -rf /tmp/glsl-shaders
# Install Slang shaders from Libretro repository (for use with Vulkan, glcore, ..)
# https://www.libretro.com/index.php/category/slang/
git clone --depth=1 https://github.com/libretro/slang-shaders.git /tmp/slang-shaders
##mkdir -vp /opt/retropie/configs/all/retroarch/shaders-slang ; # MERGE INSTEAD
cp -r /tmp/slang-shaders/* /opt/retropie/configs/all/retroarch/shaders/
rm -rf /tmp/slang-shaders
# Remove git repository from shader dir
rm -rf /opt/retropie/configs/all/retroarch/shaders/.git
##rm -rf /opt/retropie/configs/all/retroarch/slang-shaders/.git
chown -R $USER:$USER /opt/retropie/configs
echo -e "FINISHED install_retroarch_shaders \n\n"
sleep 2
}
# Create file in sudoers.d directory and disable password prompt
function disable_sudo_password() {
echo "--------------------------------------------------------------------------------"
echo "| Disabling the sudo password prompt"
echo "--------------------------------------------------------------------------------"
echo "$USER ALL=(ALL) NOPASSWD:ALL" | sudo tee /etc/sudoers.d/$USER-no-password-prompt
chmod 0440 /etc/sudoers.d/$USER-no-password-prompt
echo -e "FINISHED disable_sudo_password \n\n"
sleep 2
}
# Install latest Intel video drivers
function install_latest_intel_drivers() {
echo "--------------------------------------------------------------------------------"
echo "| Installing the latest Intel video drivers from 'ppa:ubuntu-x-swat/updates'"
echo "| This may throw errors on a new release if this PPA does not supportit yet (OK)."
echo "--------------------------------------------------------------------------------"
add-apt-repository -y ppa:ubuntu-x-swat/updates
apt-get update && apt-get -y upgrade
echo -e "FINISHED install_latest_intel_drivers \n\n"
sleep 2
}
# Install the latest Nvidia video drivers
function install_latest_nvidia_drivers() {
echo "--------------------------------------------------------------------------------"
echo "- Installing the latest Nvidia video drivers"
echo "--------------------------------------------------------------------------------"
apt-get install -y $APT_RECOMMENDS ubuntu-drivers-common
add-apt-repository -y ppa:graphics-drivers/ppa
ubuntu-drivers autoinstall
echo -e "FINISHED install_latest_nvidia_drivers \n\n"
sleep 2
}
# Install MESA Vulkan drivers
function install_vulkan() {
echo "--------------------------------------------------------------------------------"
echo "| Installing Vulkan video drivers"
echo "--------------------------------------------------------------------------------"
apt-get install -y $APT_RECOMMENDS mesa-vulkan-drivers
echo -e "FINISHED install_vulkan \n\n"
sleep 2
}
# Enable Plymouth Splash Screen
function enable_plymouth_theme() {
if [[ -z "$1" ]]; then
echo "--------------------------------------------------------------------------------"
echo "| Skipping Plymouth boot splash because no theme name was provided"
echo "--------------------------------------------------------------------------------"
echo -e "Skipped\n\n"
return 255
fi
PLYMOUTH_THEME=$1
echo "--------------------------------------------------------------------------------"
echo "| Installing Plymouth boot splash and enabling theme '$PLYMOUTH_THEME'"
echo "--------------------------------------------------------------------------------"
apt-get install -y $APT_RECOMMENDS plymouth plymouth-themes plymouth-x11
rm -rf /tmp/plymouth-themes
git clone --depth=1 https://github.com/HerbFargus/plymouth-themes.git /tmp/plymouth-themes
mv /tmp/plymouth-themes/* /usr/share/plymouth/themes/
update-alternatives --install /usr/share/plymouth/themes/default.plymouth default.plymouth /usr/share/plymouth/themes/$PLYMOUTH_THEME/$PLYMOUTH_THEME.plymouth 10
update-alternatives --set default.plymouth /usr/share/plymouth/themes/$PLYMOUTH_THEME/$PLYMOUTH_THEME.plymouth
update-initramfs -u
echo -e "FINISHED enable_plymouth_theme \n\n"
sleep 2
}
# Hide Boot Messages
function hide_boot_messages() {
echo "--------------------------------------------------------------------------------"
echo "| Hiding boot messages"
echo "--------------------------------------------------------------------------------"
# Hide kernel messages and blinking cursor via GRUB
sed -i 's/GRUB_CMDLINE_LINUX_DEFAULT=".*"/GRUB_CMDLINE_LINUX_DEFAULT="quiet splash vt.global_cursor_default=0"/g' /etc/default/grub
update-grub
# Hide fsck messages after Plymouth splash
echo 'FRAMEBUFFER=y' > /etc/initramfs-tools/conf.d/splash
update-initramfs -u
# Remove cloud-init to suppress its boot messages
apt-get purge cloud-init -y
rm -rf /etc/cloud/ /var/lib/cloud/
# Disable motd
touch $USER_HOME/.hushlogin
chown $USER:$USER $USER_HOME/.hushlogin
echo -e "FINISHED hide_boot_messages \n\n"
sleep 2
}
# Change the default runlevel to multi-user
# This disables GDM from loading at boot (new for 20.04)
function enable_runlevel_multiuser () {
echo "--------------------------------------------------------------------------------"
echo "| Enabling the 'multi-user' runlevel"
echo "--------------------------------------------------------------------------------"
systemctl set-default multi-user
echo -e "FINISHED enable_runlevel_multiuser \n\n"
sleep 2
}
# Configure user to autologin at the terminal
function enable_autologin_tty() {
echo "--------------------------------------------------------------------------------"
echo "| Enabling autologin to terminal"
echo "--------------------------------------------------------------------------------"
mkdir -p /etc/systemd/system/getty@tty1.service.d
cat << EOF >> /etc/systemd/system/getty@tty1.service.d/override.conf
[Service]
ExecStart=
ExecStart=-/sbin/agetty --skip-login --noissue --autologin $USER %I \$TERM
Type=idle
EOF
echo -e "FINISHED enable_autologin_tty \n\n"
sleep 2
}
# Start X as soon as autologin is complete
function enable_autostart_xwindows() {
echo "--------------------------------------------------------------------------------"
echo "| Enabling autostart of X Windows"
echo "--------------------------------------------------------------------------------"
# Create a .xsession file to launch OpenBox when startx is called
echo 'exec openbox-session' >> $USER_HOME/.xsession
chown $USER:$USER $USER_HOME/.xsession
# Add startx to .bash_profile
cat << EOF >> $USER_HOME/.bash_profile
if [[ -z \$DISPLAY ]] && [[ \$(tty) = /dev/tty1 ]]; then
exec startx -- >/dev/null 2>&1
fi
EOF
chown $USER:$USER $USER_HOME/.bash_profile
echo -e "FINISHED enable_autostart_xwindows \n\n"
sleep 2
}
# Hide Openbox Windows and reduce visibility of terminal
function hide_openbox_windows() {
echo "--------------------------------------------------------------------------------"
echo "| Hiding window decorations in OpenBox"
echo "--------------------------------------------------------------------------------"
# Reduce the visibility of the gnome terminal by prepending these settings in the bash profile
GNOME_TERMINAL_SETTINGS='dbus-launch gsettings set org.gnome.Terminal.Legacy.Profile:/org/gnome/terminal/legacy/profiles:/:b1dcc9dd-5262-4d8d-a863-c897e6d979b9/'
cat << EOF >> $USER_HOME/.bash_profile
$GNOME_TERMINAL_SETTINGS use-theme-colors false
$GNOME_TERMINAL_SETTINGS use-theme-transparency false
$GNOME_TERMINAL_SETTINGS foreground-color '#FFFFFF'
$GNOME_TERMINAL_SETTINGS background-color '#000000'
$GNOME_TERMINAL_SETTINGS cursor-blink-mode 'off'
$GNOME_TERMINAL_SETTINGS scrollbar-policy 'never'
$GNOME_TERMINAL_SETTINGS audible-bell 'false'
gsettings set org.gnome.Terminal.Legacy.Settings default-show-menubar false
EOF
chown $USER:$USER $USER_HOME/.bash_profile
# Further reduce the visibility of windows (terminal) by modifying the OpenBox config
mkdir -p $USER_HOME/.config/openbox
cp /etc/xdg/openbox/rc.xml $USER_HOME/.config/openbox/rc.xml
cat << EOF > /tmp/rc.xml.applications
<application class="*">
<fullscreen>yes</fullscreen>
<iconic>no</iconic>
<layer>below</layer>
<decor>no</decor>
<maximized>true</maximized>
</application>
EOF
sed -i '/<applications>/r /tmp/rc.xml.applications' $USER_HOME/.config/openbox/rc.xml
rm /tmp/rc.xml.applications
sed -e 's/<keepBorder>yes<\/keepBorder>/<keepBorder>no<\/keepBorder>/g' -i $USER_HOME/.config/openbox/rc.xml
chown -R $USER:$USER $USER_HOME/.config
echo -e "FINISHED hide_openbox_xwindows \n\n"
sleep 2
}
# Autostart OpenBox Applications
function autostart_openbox_apps() {
echo "--------------------------------------------------------------------------------"
echo "| Enabling OpenBox autostart applications and RetroPie autostart.sh"
echo "--------------------------------------------------------------------------------"
# OpenBox autostarts unclutter, then passes off to the RetroPie autostart
mkdir -p $USER_HOME/.config/openbox
echo 'unclutter -idle 0.01 -root' >> $USER_HOME/.config/openbox/autostart
echo '/opt/retropie/configs/all/autostart.sh' >> $USER_HOME/.config/openbox/autostart
chown -R $USER:$USER $USER_HOME/.config
# Create RetroPie autostart
mkdir -p /opt/retropie/configs/all
touch /opt/retropie/configs/all/autostart.sh
chmod +x /opt/retropie/configs/all/autostart.sh
chown -R $USER:$USER /opt/retropie/configs
cat << EOF > /opt/retropie/configs/all/autostart.sh
#! /bin/bash
gnome-terminal --full-screen --hide-menubar -- emulationstation --no-splash # RPSU_End autostart_openbox_apps
EOF
echo -e "FINISHED autostart_openbox_apps \n\n"
sleep 2
}
# Install and configure extra tools
function install_extra_tools() {
echo "--------------------------------------------------------------------------------"
echo "| Installing the following tools to improve usability:"
echo "| ${EXTRA_TOOLS[@]}"
echo "--------------------------------------------------------------------------------"
apt-get update
apt-get install -y $APT_RECOMMENDS ${EXTRA_TOOLS[@]}
# Configure 'inxi' if it was installed
if [[ -x "$(command -v inxi)" ]]; then
echo "--------------------------------------------------------------------------------"
echo "| Enabling updates on the 'inxi' package", which is
echo "| used for checking hardware and system information"
echo "| Command 'inxi -G' is useful for querying video card driver versions"
echo "--------------------------------------------------------------------------------"
sed -i 's/B_ALLOW_UPDATE=false/B_ALLOW_UPDATE=true/g' /etc/inxi.conf
inxi -U
fi
echo -e "FINISHED install_extra_tools \n\n"
sleep 2
}
# Install and configure extra tools
function fix_quirks() {
echo "--------------------------------------------------------------------------------"
echo "| Fixing any known quirks"
echo "--------------------------------------------------------------------------------"
# XDG_RUNTIME_DIR
echo "--------------------------------------------------------------------------------"
echo "| Remove 'error: XDG_RUNTIME_DIR not set in the environment' CLI error"
echo "| when exiting Retroarch from the RetroPie Setup screen within ES"
echo "| by creating a file in sudoers.d directory to keep environment variable"
echo "--------------------------------------------------------------------------------"
echo 'Defaults env_keep +="XDG_RUNTIME_DIR"' | sudo tee /etc/sudoers.d/keep-xdg-environment-variable
chmod 0440 /etc/sudoers.d/keep-xdg-environment-variable
echo -e "\n"
# Screen blanking
echo "--------------------------------------------------------------------------------"
echo "| Disable screen blanking (only happens outside of EmulationStation)"
echo "| This prevents the display from doing any ‘screen blanking’ due to inactivity"
echo "--------------------------------------------------------------------------------"
sed -i '1 i\xset s off && xset -dpms' $USER_HOME/.xsession
echo -e "\n"
echo -e "FINISHED fix_quirks \n\n"
sleep 2
}
# Add the ability to change screen resolution in autostart.sh
function set_resolution_xwindows() {
echo "--------------------------------------------------------------------------------"
echo "| Adding the ability to override the default display resolution"
echo "| from the '/opt/retropie/config/all/autostart.sh' script."
echo "| Update the PREFERRED_RESOLUTION variable inside the script to change this value."
echo "| If not valid, it will gracefully revert to the display's preferred resolution."
echo "| This is typically helpful for improving performance by lowering resolution on 4K displays"
echo "--------------------------------------------------------------------------------"
cat << EOF >> /tmp/set_resolution_xwindows
# RPSU_START set_resolution_xwindows
# Update the next line to customize the display resolution
# If will fall back to the display's preferred resolution, if the custom value is invalid
PREFERRED_RESOLUTION=1920x1080
if [[ ! -z \$PREFERRED_RESOLUTION ]]; then
current_resolution=\$(xrandr --display :0 | awk 'FNR==1{split(\$0,a,", "); print a[2]}' | awk '{gsub("current ","");gsub(" x ", "x");print}')
connected_display=\$(xrandr --display :0 | grep " connected " | awk '{ print \$1 }')
if \$(xrandr --display :0 | grep -q \$PREFERRED_RESOLUTION); then
xrandr --display :0 --output \$connected_display --mode \$PREFERRED_RESOLUTION &
else
echo "\$PREFERRED_RESOLUTION is not available on \$connected_display. Remaining at default resolution of \$current_resolution."
fi
fi
# RPSU_END set_resolution_xwindows
EOF
# Insert into autostart.sh after the 1st line (after shebang)
sed -i '1r /tmp/set_resolution_xwindows' "/opt/retropie/configs/all/autostart.sh"
rm /tmp/set_resolution_xwindows
echo -e "FINISHED set_resolution_xwindows \n\n"
sleep 2
}
# Sets the GRUB graphics mode
# Takes a valid mode string as a argument, such as "1920x1080x32"
# If none is provided, a default of 'auto' will be used
function set_resolution_grub() {
if [[ -z "$1" ]]; then
MODES="auto"
else
MODES="$1,auto"
fi
echo "--------------------------------------------------------------------------------"
echo "| Changing the GRUB graphics mode to '$MODE'"
echo "| If this mode is incompatible with your system, GRUB will fall back to 'auto' mode"
echo "| Run 'vbeinfo' (legacy, pre-18.04) or 'videoinfo' (UEFI) from the GRUB command line"
echo "| to see the supported modes"
echo "| This value, 'GRUB_GFXMODE', can be edited in /etc/default/grub"
echo "--------------------------------------------------------------------------------"
sed -i "s/#GRUB_GFXMODE=.*/GRUB_GFXMODE=$MODES/g" "/etc/default/grub"
update-grub
echo -e "Done\n\n"
sleep 2
echo -e "FINISHED set_resolution_grub \n\n"
}
# Run any optional scripts that the user has provided
function run_optional_scripts() {
SCRIPT_PATH=$1
# If a specific file is provided, just run that
if [[ -f $SCRIPT_PATH ]]; then
SCRIPT_FILE_PATH=$SCRIPT_PATH
echo "--------------------------------------------------------------------------------"
echo "| Running optional script at $SCRIPT_FILE_PATH"
echo "--------------------------------------------------------------------------------"
echo -e "\n"
source "$SCRIPT_FILE_PATH"
sleep 2
# Otherwise, run all scripts in the provided directory
else
echo "--------------------------------------------------------------------------------"
echo "| Running any optional scripts found in $SCRIPT_PATH"
echo "--------------------------------------------------------------------------------"
ls "$SCRIPT_PATH" | sort -n | while read SCRIPT_FILE; do
SCRIPT_FILE_PATH="$SCRIPT_PATH/$SCRIPT_FILE"
if [[ -f $SCRIPT_FILE_PATH ]] && [[ $SCRIPT_FILE_PATH != *README* ]]; then
echo -e "\n"
source "$SCRIPT_FILE_PATH"
sleep 2
fi
done
fi
echo -e "\n\n"
echo -e "FINISHED run_optional_scripts \n\n"
}
# Repair any permissions that might have been incorrectly set
function repair_permissions() {
echo "--------------------------------------------------------------------------------"
echo "| Repairing file & folder permissions underneath $USER_HOME"
echo "| by changing owner to $USER on all files and directories under $USER_HOME"
echo "--------------------------------------------------------------------------------"
chown -R $USER:$USER $USER_HOME/
echo -e "FINISHED repair_permissions \n\n"
sleep 2
}
# Remove unneeded packages
function remove_unneeded_packages() {
echo "--------------------------------------------------------------------------------"
echo "| Autoremoving any unneeded packages"
echo "--------------------------------------------------------------------------------"
apt-get update && apt-get -y upgrade
apt-get -y autoremove
echo -e "FINISHED remove_unneeded_packages \n\n"
sleep 2
}
# Prompt user for reboot
function prompt_for_reboot() {
read -p "Reboot the system now? (y/n) " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
reboot
fi
}
# Final message to user
function complete_install() {
RUNTIME=$SECONDS
echo "--------------------------------------------------------------------------------"
echo "| Installation complete"
echo "| Runtime: $(($RUNTIME / 60)) minutes and $(($RUNTIME % 60)) seconds"
echo "| Output has been logged to '$LOG_FILE'"
echo "--------------------------------------------------------------------------------"
## Eth:
#prompt_for_reboot
}
# Make sure the user is running the script via sudo
if [ -z "$SUDO_USER" ]; then
echo "This script requires sudo privileges. Please run with: sudo $0"
exit 1
fi
# Don't allow the user to run this script from the root account. RetroPie doesn't like this.
if [[ "$SUDO_USER" == root ]]; then
echo "This script cannot be run by the root user. Please run as normal user using sudo."
exit 1
fi
#--------------------------------------------------------------------------------
#| INSTALLATION SCRIPT
#--------------------------------------------------------------------------------
# If no arguments are provided
if [[ -z "$1" ]]; then
#-- Log this script's output
enable_logging
run_optional_scripts "$OPTIONAL_SCRIPT_DIR/pre_install"
#-- Basic RetroPie install
install_retropie_dependencies
install_retropie
install_retroarch_shaders
disable_sudo_password
#-- Common video drivers
install_latest_intel_drivers
install_latest_nvidia_drivers
install_vulkan
#-- Hide text and boot directly into EmulationStation
enable_plymouth_theme "retropie-pacman" # See https://github.com/HerbFargus/plymouth-themes.git for other theme names
hide_boot_messages
enable_runlevel_multiuser
enable_autologin_tty
enable_autostart_xwindows
hide_openbox_windows
autostart_openbox_apps
#-- Additional customizations
install_extra_tools
fix_quirks
#-- OPTIONAL STEPS (comment/change as needed)
# These are helpful for improving 4k performance and user experience
set_resolution_xwindows "1920x1080" # Run 'xrandr --display :0' when a X Windows session is running to the supported resolutions
set_resolution_grub "1920x1080x32" # Run 'vbeinfo' (legacy, pre 18.04) or 'videoinfo' (UEFI) from the GRUB command line to see the supported modes
run_optional_scripts "$OPTIONAL_SCRIPT_DIR/post_install"
#-- Final cleanup
repair_permissions
remove_unneeded_packages
complete_install
# If function names are provided as arguments, just run those functions
# (then restore perms and clean up)
else
enable_logging
for call_function in "$@"; do
$call_function
done
repair_permissions
complete_install
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment