As promised @Atari for all his support in this process, I would write about the two main obstacles that I encountered when trying to get MakeCode Arcade games to run on Batocera 34 for Raspberry Pi 4, since they are loosely related to two somewhat similar issues that others have struggled with, and they might also be of help to others.
1. Batocera 34 for RPi4 is 64-bit(arm64) with no included 32-bit armhf runtime
I will not join in the choir of nagging about lacking 32-bit support, but this was my main obstacle, since I have no control over the MakeCode Arcade compiled 32-bit armhf .elf executable game files. They are “as-is” in 32-bit armhf.
This also turned out to be related to missing audio and cryptic error messages from the pipewire audio driver.
My solution was inspired by two freedesktop.org issues, where one coincidentally was about running 32-bit Wine on Batocera 64-bit:
https://gitlab.freedesktop.org/pipewire/pipewire/-/issues/1520
https://gitlab.freedesktop.org/pipewire/pipewire/-/issues/1239
Solution:
1. Download the needed libraries from e.g. Debian package archives(Bullseye version, but should maybe have chosen newer ones) and distribute a package with all needed 32-bit shared libraries with my solution and save these under a new /lib32 library folder; https://github.com/Vegz78/McAirpos/blob/master/McAirpos/Batocera34/batocera_re.tar.gz
Other executables might require additional 32-bit libraries to function, but this package at least contains everything needed for pipewire and many basic executables without the need for too many special external libraries.
If a library is missing, one normally gets an easily identifiable error message about which file is missing.
2. Before execution of your 32-bit binaries, set the following environmental variables in the same tty session that calls your executable 32-bit game(For Batocera, this normally means inside the <command> tag of your es_systems.cfg configuration):
export LD_LIBRARY_PATH=/lib32/arm-linux-gnueabihf
export SPA_PLUGIN_DIR="/lib32/arm-linux-gnueabihf/spa-0.2"
export PIPEWIRE_MODULE
DIR="/lib32/arm-linux-gnueabihf/pipewire-0.3"
Remember to unset these, or check and set back to original values(e.g. export LD_LIBRARY_PATH=)
on exit, in case they make problems for all the regular 64-bit executables on the system.
As a final note, maybe we can understand “yet” here to mean that multiple environment variables separated by : might be supported in the future, so that the 32-bit and 64-bit runtime environments can live happily side-by-side?:
https://gitlab.freedesktop.org/pipewire/pipewire/-/issues/1520/#:\~:text=Multiple%20paths%20separated
2. Batocera did not change the active tty session on game launch and exit
If I understand correctly, Batocera is configured to boot with EmulationStation in an X/Wayland session on tty2, while MakeCode Arcade games display their graphics directly to the framebuffer on tty1.
To further complicate things, EmulationStation calls a service, AIGLX: Suspending AIGLX clients for VT switch, to prevent switching between virtual terminals during game play, so that it was impossible to change back to tty2 on game exit in either my game launcher’s executable or the es_systems.cfg <command> entry with e.g. chvt 2
, since the system()/sh –c command inside EmulationStation would not close this service and allow switching until it was totally finished and had returned.
This led to the infamous VT_WAITACTIVE race condition for VT framebuffer screens in ioctl modes “KDSETMODE, KD_GRAPHICS” and “VT_SETMODE, VT_AUTO”, making both chvt
and the whole system hang/freeze.
To check whether a process, e.g. chvt, hangs on VT_WAITACTIVE, https://bugs.launchpad.net/oem-priority/+bug/1817738, has a solution that does not require installation of external tools like strace etc.:
$ cat /proc/$(pidof chvt)/stack
Output:
[<0>] __vt_event_wait.isra.2.part.3+0×40/0×90
[<0>] vt_waitactive+0×80/0xd0
…
My solution was inspired by this blog post:
https://forum.odroid.com/viewtopic.php?p=251333&sid=601885d49335e48b35e37ee5d73c8484#p251333
this GitHub commit:
https://github.com/batocera-linux/batocera.linux/commit/dfcbb92eee4c3b27a6496645ca51e11b8731f02b
and the amazing tool, ttyecho, found on Pratik Sinha’s blog:
https://www.humbug.in/2010/utility-to-send-commands-or-data-to-other-terminals-ttypts
Solution:
1. Use ttyecho to launch a bash script as a process group leader directly on the logging console on tty3, which is already logged in as root:
In the es_systems.cfg <command> tag:
<command>ttyecho -n /dev/tty3 /home/pi/McAirpos/McAirpos/Batocera34/batocera_launCharc.sh %ROM%</command>
(For brevity, I have omitted the need to also set the above environment variables for ttyecho, which in my solution also is 32-bit(but could be compiled as 64-bit) and omitted the need to unset them afterwards. Full details here.)
2. Inside the above mentioned bash script, use chvt 1
to switch display active to the tty1 session, launch the executable, and on return from the executable, use chvt 2
to return to EmulationStation. Full details here.
;-)
Perhaps something similar would work for x86 32-bit on x64 64-bit Linux PC as well, I would not know.
I hope this can help others in the same situation and maybe spare them from both the time and frustration these two issues caused me!