XGS on the Raspberry Pi 400

About a week and half ago I became the owner of Raspberry Pi 400, a small computer built around a Raspberry Pi 4. The kit I purchased came with a USB-C power adapter and a basic USB mouse; all I needed to supply was a monitor.

Naturally, the first thing I did after setting it up was get XGS running on it:

This was not quite as simple compiling XGS and running it, so let’s go over what changed, why it changed, and how to build XGS on the Pi after the changes.

Open GL Support on the Raspberry Pi

On older Pi models (1, 2, 3, and the Zero) the OpenGL support was provided through a proprietary firmware blob, and exposed through a set of custom GL libraries in /opt/vc/lib. Since 2017 XGS supported use of these libraries by specifying -DBCMHOST=true when running cmake.

As of the Pi 4 (and, by extension, the Pi 400) this proprietary firmware driver is no longer supported. Instead, there are now open source drivers supporting the Pi 3 and 4. They are fully integrated into Mesa now, so it is no longer necessary to link against proprietary libraries.

As a result of these changes I have decided to remove the BCMHOST option in XGS. Instead, XGS relies on SDL to pick the right driver; this will be KMSDRM when running from the console, or X11 when running from the desktop.

Note that this change has probably broken support for the Pi 1 or 2. Those models are sufficiently outdated now that I don’t feel the need to continue supporting them.

Building XGS

As of this writing Raspberry Pi OS does not ship a version of SDL with the KMSDRM driver enabled. So, before building XGS, you’ll need to build and install your own build of SDL. Fortunately this is very easy:

sudo apt-get remove -y --force-yes libsdl2-dev
sudo apt-get install libgbm-dev libdrm-dev
tar -xzvf SDL2-2.0.12.tar.gz
cd SDL2-2.0.12
./configure --host=arm-raspberry-linux-gnueabihf \
--disable-pulseaudio \
--disable-esd \
--disable-video-rpi \
make -j4
sudo make install

You should also run raspi-config, navigate to Advanced Options -> GL Driver, and make sure you have the KMS driver selected. You’ll need to reboot after making this change.

With SDL built and the KMS driver enabled you can now build XGS:

cd xgs
mkdir build
cd build
cmake ..
make -j4

The resulting binary can be run from the desktop or direct from the console. It will open in a window when run from the desktop, and full-screen when run from the console.

The only problem I have noticed is that the video is a bit choppy when running from the console. It’s most noticeable when watching the sliding apple on the “Check startup device” screen. It does not happen when running from the desktop, so it is somehow related to the KMSDRM driver.

Raspberry Pi & the Future of XGS

XGS has certainly had a fragmented development history. I originally started it in 1996, but by 1997 development had already stalled. Five years later, in 2002, I briefly resumed work on it, but I also started a small business around that time and XGS ended up on a (virtual) shelf for nearly 15 years.

Fast forward to 2016, when I got the XGS itch again. I rewrote the code in C++ to make it easier to understand, removed non-SDL graphics support, and added a basic GUI.

By 2017 I had moved away from the project again despite making good progress. I briefly considered creating a retro emulated GS based around the Raspberry Pi (think of the C64 Mini) but that project never really got off of the ground, and by that point I was already spending the bulk of my time on other projects.

And so here we are in 2020. I’m currently between hardware projects (well sort of; more on that in another post) and I’m feeling the need to spend at least some of my free time on a software project. So, I am jumping back into XGS, with the intent of improving the Raspberry Pi support. My first task will be to create an ARM-optimized version of the M65816 emulation core. I’ve been wanting to learn ARM assembly, and this will be a great way to do that.

Stay tuned!

XGS Lives

Believe it or not, XGS is now 20 years old! The project was started way back in 1996, when my fastest PC was still a 66 MHz Pentium. Sadly, for various reasons, development pretty much stalled in 1997. I briefly started tinkering with it again in 2002, but I got busy, and nothing came of it. The last released version is still from 1997…but that’s about to change.

Lately I’ve found myself in need of a good personal project to sink my teeth into, and so I’ve circled back around to XGS.  I have two goals in mind for the future of XGS:

  1. Finishing what I started 20 years ago.  I want to find and fix the bugs that keep some high-profile software from running (hi Diversi-Tune!), improve the emulation (3200-color support anyone?), and apply some spit and polish in the form of an actual GUI.
  2. Create a version of XGS that is geared towards running on a Raspberry Pi to create a teeny-tiny Apple IIGS. Part of this project would involve some actual hardware hacking to create interfaces to authentic Apple hardware. I for sure would like to implement ADB, so that a real IIGS keyboard and mouse can be used. I’m also considering trying to drive an actual 3.5″ 800k drive, which would be great if there’s anyone out there with some stuff on old IIGS disks.

With those goals mind, the first decision I’ve made is that I’m no longer going to go out of my way to make the code portable beyond Linux. I certainly won’t object if anyone wants to resurrect any of the other ports, and I will try to not make things hard on anyone who wants to do so, but if I can do something cleaner and/or easier by targeting just Linux that is the way I will go. Case in point: the current code base is using the Linux timerfd interface for timing, because it just works way better for me than straight POSIX timers (I did try them!)

Next, I’ve mostly finished up some work I started back in 2002 to replace all the individual video and audio drivers with a single set. Currently that’s SDL for video and PulseAudio for audio. I wanted to use SDL for both, but I so far I’ve been unable to get SDL audio that doesn’t have lots of skips and crackles. SDL does have the benefit of being multi-platform so at least here I hopefully made things easier for any would-be port maintainers.

I’m also looking at ways to simplify the code by removing some roundabout ways of doing things that were originally implemented to make the emulator actually usable on 1996-vintage PCs. The new low-end for acceptable performance is going to be a Raspberry Pi 2.

And finally, I’m considering changing the code base from C to C++ and implementing the various hardware chips as their own classes. This isn’t fundamentally different than what is there now, but the resulting code will be much cleaner, and the interfaces between the various emulated hardware bits will be well-defined. It will also aid in my long-term Raspberry Pi goals, because I’m going to need to be able to plug in different bits cleanly (e.g remove ADB emulation and replace with an interface to my yet-to-be-designed ADB hardware).

I’m really excited about all this, and I’m hoping to start pushing out some new development snapshots this month. Stay tuned!