muOS

Custom Firmware

User Tools

Site Tools


tech:retroarch

How to compile RetroArch for muOS

Overview

This is a “guide” for people who want to compile RetroArch as complete beginners to embedded linux. I hope it would help the next person when they want to cross-compile RetroArch for muOS

Terminology

Name Description
cross-compile Compile binary to target a different architecture/operating system, for example compiling linux binaries on windows is also cross compile, in my case I'm compiling an ARM binary in WSL2(Linux)
toolchain All sorts of binaries libraries you need to compile the project
buildroot/Batocera Lite SDK Toolchain Exported toolchain instead of image to cross-compile
buildroot A tool which can create an image for you to cross-compile, I didn't use it this time

General Idea

  1. Use the installed toolchain to compile RetroArch
  2. Copy the new built binary to RG35XX(PLUSH)
  3. Run and test

Steps

0 Preparation

Let's clone RetroArch

cd ~
git clone https://github.com/libretro/RetroArch.git

1 Install buildroot/Batocera Lite SDK Toolchain

buildroot/Batocera Lite SDK Toolchain

# this would download arm-buildroot-linux-gnueabihf_sdk-buildroot.tar.gz to current directory
wget https://github.com/rg35xx-cfw/rg35xx-cfw.github.io/releases/download/rg35xx_plus_h_sdk_20240207/arm-buildroot-linux-gnueabihf_sdk-buildroot.tar.gz
 
# unzip and rename folder
tar zxvf arm-buildroot-linux-gnueabihf_sdk-buildroot.tar.gz
mv arm-buildroot-linux-gnueabihf_sdk-buildroot toolchain
 
# run relocate-sdk.sh
cd toolchain
./relocate-sdk.sh

2 Use the installed toolchain to compile RetroArch

Now we have the toolchain on our machine, but to compile RetroArch you need to let it know that you are using this toolchain instead of the one that your system has by default. To do that we would need to setup some environment variables

The following is from Adixal with some modifications

2.1 Config environment variables for toolchain

Create a file with the following contents and call it cc-plus.sh (the name doesn't matter I'm just using the same name that Adixal uses)

#!/bin/bash
 
export DEVICE=RG35XXPLUS
 
export XTOOL=$HOME/x-tools
export XHOST=arm-buildroot-linux-gnueabihf
export XBIN=$XTOOL/$XHOST/bin
 
export PATH="${PATH}:$XBIN"
 
export SYSROOT=$XTOOL/$XHOST/$XHOST/sysroot
export DESTDIR=$SYSROOT
 
export CC=$XBIN/$XHOST-gcc
export CXX=$XBIN/$XHOST-g++
export AR=$XBIN/$XHOST-ar
export LD=$XBIN/$XHOST-ld
export STRIP=$XBIN/$XHOST-strip
 
export LD_LIBRARY_PATH="$SYSROOT/usr/lib"
 
export CPP_FLAGS="--sysroot=$SYSROOT -I$SYSROOT/usr/include"
export LD_FLAGS="-L$SYSROOT -L$SYSROOT/lib -L$SYSROOT/usr/lib -L$SYSROOT/usr/local/lib -L$SYSROOT/usr/include/sound"
 
export CPPFLAGS=$CPP_FLAGS
export LDFLAGS=$LD_FLAGS
 
export CFLAGS="-marm -mfpu=neon -mfloat-abi=hard $CPP_FLAGS"
export CCFLAGS=$CPP_FLAGS
export CXXFLAGS=$CPP_FLAGS
 
export INC_DIR=$CPP_FLAGS
export LIB_DIR=$LD_FLAGS
 
export ARMABI=$XHOST
export TOOLCHAIN_DIR=$XTOOL/$XHOST
 
export PKG_CONFIG_PATH=$SYSROOT/usr/lib/pkgconfig
export PKG_CONF_PATH=$XBIN/pkgconf
 
export CROSS_COMPILE=$XBIN/$XHOST-
 
export SDL_CONFIG=$SYSROOT/usr/bin/sdl-config
export FREETYPE_CONFIG=$SYSROOT/usr/bin/freetype-config

Run the following to have the environment variables in your shell

. ./cc-plus.sh

At this point you should have all the environment variables in your current shell, you can check with env

2.2 Run ./configure in RetroArch aka Automake

We cloned RetroArch in Step 0, let's go into that directory and run ./configure with a lot of options

cd RetroArch
 
./configure --disable-nvda --disable-materialui --disable-systemd --disable-x11 --disable-xrandr --disable-xinerama --disable-wayland --enable-sunxi --disable-cdrom --enable-libshake --disable-crtswitchres --enable-hid --enable-screenshots --disable-vulkan --disable-qt --disable-online_updater --disable-update_cores --disable-update_core_info --disable-update_assets --enable-neon --disable-pulse --disable-oss --enable-alsa --enable-mali_fbdev --enable-command --enable-threads --enable-bluetooth --disable-parport --enable-opengles

Because we are passing –enable-mali_fbdev we would need to also pass in –enable-opengles per this README

To enable mali_fbdev you must configure RetroArch with –enable-opengles and –enable-mali_fbdev.

Important Note the previous ./configure would generate config.mk in ~/RetroArch, for some reason the config.mk I generated had -I/usr/include and -L/usr/lib flags

# INCORRECT
ALSA_CFLAGS = -I/usr/include
ALSA_LIBS = -L/usr/lib -lasound

When I compile with this the toolchain is complaining

$ make
CC input/drivers/linuxraw_input.c
arm-buildroot-linux-gnueabihf-gcc: ERROR: unsafe header/library path used in cross-compilation: '-I/usr/include'
make: *** [Makefile:209: obj-unix/release/input/drivers/linuxraw_input.o] Error 1

I don't know how to let ./configure generate the correct flags but I ended up replacing -I/usr/include with -I/home/shengy/toolchain/arm-buildroot-linux-gnueabihf/sysroot/usr/include. You would probably change to your username

If you want to do it by sed

sed -i s#/usr/include#"$SYSROOT"/usr/include#g config.mk
sed -i s#/usr/lib#"$SYSROOT"/usr/lib#g config.mk

2.3 Compile RetroArch

Assume that we are in RetroArch's directory, all we need now is

make -j`nproc`

After a while it would complete and you would have retroarch in RetroArch/, to confirm it was a cross compile you can do

readelf -h retroarch

and it should show something like the following (note that Machine is ARM)

ELF Header:
  Magic:   7f 45 4c 46 01 01 01 03 00 00 00 00 00 00 00 00
  Class:                             ELF32
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - GNU
  ABI Version:                       0
  Type:                              DYN (Position-Independent Executable file)
  Machine:                           ARM
  Version:                           0x1
  Entry point address:               0x362f0
  Start of program headers:          52 (bytes into file)
  Start of section headers:          16538188 (bytes into file)
  Flags:                             0x5000400, Version5 EABI, hard-float ABI
  Size of this header:               52 (bytes)
  Size of program headers:           32 (bytes)
  Number of program headers:         9
  Size of section headers:           40 (bytes)
  Number of section headers:         31
  Section header string table index: 30

3 Copy the new built binary to RG35XX(PLUSH)

The idea is to replace the binary that came with muOS with the one we compiled and run it, you could plug the SD card to your computer or access it via ssh/scp, I would be access it via ssh/scp

3.1 Connect to WIFI

On your device

muOS MAIN MENU → Configuration → WI-FI NETWORK

Then connect there, you can verify it by running ping <ip-showed-up>

3.2 ssh into your RG35XX(PLUSH)

Assume that the IP of your RG35XX(PLUSH) is 192.168.1.217, run the following to ssh into it

ssh root@192.168.1.217

You would be prompted to enter a password, the password is root.

Note that when you type the password nothing is going to show, just type and hit enter when done

If you see the shell prompt similar to the following then you are in

$ ssh root@192.168.1.217
root@192.168.1.217's password:
[~]#

3.3 Backup the current retroarch just in case

It's always a good idea to backup the current binary just in case yours are not working, when doing my testing I noticed if my retroarch binary isn't functioning I lose WI-FI connectivity, so I had to plug the SD card to my computer to restore from backup to regain the ability to use WI-FI

Assuming we are in ssh

cd /mnt/mmc/MUOS/
cp retroarch retroarch.bak

You can also copy the config if you want to

cd /mnt/mmc/MUOS/
cp .retroarch/retroarch.cfg .retroarch/retroarch.cfg.bak

3.4 Upload current binary

We already have the backup so now we can replace retroarch in /mnt/mmc/MUOS. Again this could be done by pluging in the SD card and copy/paste from your file explorer. But I am doing it via scp. The following example assumes that your RG35XX(PLUSH)'s IP is 192.168.1.217

On your machine's shell, cd into RetroArch (where the binary is)

cd ~/RetroArch
scp retroarch root@192.168.1.217:/mnt/mmc/MUOS/retroarch

The output looks something like

$ scp retroarch root@192.168.1.217:/mnt/mmc/MUOS/retroarch
root@192.168.1.217's password:
retroarch                                       100%   16MB   2.9MB/s   00:05

4 Run and test

On your device

muOS MAIN MENU → RetroArch

Here if your binary crashes you would see a flash screen, and at that point you have to figure out what went wrong during compile. If your binary crashes you can try to run it in ssh and see if there are any error messages.

I got into another situation where RetroArch started but all the button configs are messed up so I can't exit, instead of restarting the handheld, you could run the following to kill it

[~]# pkill retroarch

The End

If you made it this far then congratulations :) you just learned how to cross-compile RetroArch for muOS

TODOs

- Instead of using the SDK, use buildroot to compile - Insetad of using the real device to test, use qemu