Finally, I booted GC-Linux

The platinum GameCube and Pokémon Colosseum, that I had since I was a kid, and the memory card, SD gecko and microSD card that I bought for this adventure

An obsession for half of my life

When I was a very little kid, my neighbor had a PlayStation One, and I wanted one as as well. I knew almost nothing about video games, I just thought they were cool. Then the PlayStation 2 came out, and I started wanting it.

So, after many years of requests, when I was like 8 or 9, on the Saturday before Christmas, my Dad took me and my syster to a shop close to our home… and we bought a GameCube. He liked a Logitech steering wheel that was for the GC, and, influenced by a shop assistant, we bought the bundle of a platinum GameCube with Mario Kart: Double Dash!!.

So, I did not get a PlayStation - at that time, and, fun fact, I still never had one -, and actually I would have preferred the iconic indigo GameCube, to the platinum one. However, I must say I had a good time in the following years with the GC, and I do not regret having a PS.

I still remember when I used to come home from afternoons at the middle school, and then started playing Pokémon Colosseum, or my climb to the Mt. Battle.

During middle school, I also started using Linux. And, when in January 2009 I discovered the GC-Linux project, I wanted to cross the two things, and try to run Linux on my GameCube.

I followed the official guide step by step, compiled the kernel, somehow prepared a Debian image, created my ISO image and burnt it into an 8cm DVD-R… to then discover what anti-piracy protections are.

So I dismissed both the initial enthusiasm and the disappointment. Then, a few months later, we bought a Nintendo Wii, softmodded it, and finally booted GC-Linux on it. However, being the Wii an empowered GameCube, it was quite powerless when it launched in 2006, and it was even worse in 2009. So I enjoyed seeing Linux running on it, I think I even managed to start an X server and a browser, but nothing more than that.

Still, when 5 years later I had my first powerful PC, I used it to compile a Linux kernel for the Wii, and create what I called Debian Wiizi 😁. Again, it was a temporary thing, just me enjoying doing nerdy things, rather than actually using it.

PokéLoad

Four more years passed, and from August to December of 2018, I stayed in Oslo with the Erasmus+ programme. There, I attended a class about software security, and I started also watching some videos about that on YouTube. Therefore, the algorithm made me discover a channel called Modern Vintage Gamer, because he often posts video about how the security of various video game consoles was bypassed.

On May 2019, he published a video about the GC security, in which he showed also which games can be exploited to run unofficial code, and that Pokémon Colosseum is amongst them. Yep, the same Pokémon Colosseum that I enjoyed playing to relax. But once again, I dismissed the enthusiasm, or actually, I hid it, until some weeks ago 😈️.

So, here we are! The attack is called PokéLoad, and it involves a tampered save, to make the game stack overflow on the name of a Pokémon at the start of a battle.

For many years I incorrectly believed that the SD-geckos could be used as a replacement for memory cards, but they cannot. Actually, I do not even remember how I had discovered them. I always thought I saw them in the manual of GC, but it does not state anything about them, and the official ones were a Japan-exclusive (as always, lucky Japanese!).

Otherwise it would have been fantastic: just like the Wii, it would have been possible to hack the console just with a SD-card, and I was so thrilled at the idea. Turns out it is not that trivial, and you need another modded console, being it a GC or a Wii, to write on a real memory card, with GCMM. At least I was covered on that.

However, I did not want to sacrifice any of my old saves, therefore I decided to buy a new memory card. Luckily, the cheapest memory card from the EU, on eBay, was from less than 50km from where I live! Unluckily, I did not think that Pokémon Colosseum is a heavy load - 48 blocks - and Swiss also needs space, and I bought a 59 blocks card, to then realize the problem just some minutes after the purchase.

BrosExec

I did not despond, yet, and I though that I could still use a proxy loader. In other words, PokéLoad, which is very constrained, loads the proxy, which in turn, loads Swiss/Linux from the SD card. «88KB must be enough to do that!», I thought. Also, since I could not find such a loader, «Heck, I am a programmer I can do that by myself!», I thought.

Well, I installed devkitPPC, and discovered that a homebrew with an empty main, takes about 90KB (or 58KB compressed), just because it ships also additional code from libogc. A “Hello World” takes more than 200KB uncompressed, and 106KB compressed. The proxy loader did not seem a viable solution anymore. I even started thinking about making libogc lighter or doing something at low level, e.g. even reading from the raw SD without any partition, to avoid using libfat.

But luckily for me, I decided to look again on the Internet, and I found BrosExec. Its author had the same idas as me, but they also claimed that it can fit 11 blocks, just what I needed!

But I did not believe that, I looked at the code and there was no way for it to fit 88KB. Indeed there was a trick: BrosExec could fit 11 blocks in 2015. So I downloaded devkitPPC 27, released in 2014, and checked out an old commit on the git repository of libogc. In this way, I obtained a .dol of 149,5KB, that with dolxz (a .dol compressor from the same author of PokéLoad) arrived to 87016 bytes! YES!

Actually, I did not notice that the GitHub repo of BrosExec contains a release page, otherwise I would not have compiled it 😅. Anyway, that was it, I could continue with my experiments.

So, after two weeks, the SD Gecko arrived (I had to order it from the UK), and I finally could try to get Swiss running… but nothing happened and my GC reset instead. Well, this was quite easy to fix: I was using a new SD card, that I just bought so I could do everything I wanted without having to backup, and it was formatted in exFAT. That makes sense, since today’s SDs are quite big, but this filesystem is not compatible with libfat; I also think that the partition table should be msdos, not GPT, but I did not test the latter. Anyway, I formatted the SD in fat32 and then everything worked 🤩️.

Booting GC-Linux

Naturally, trying to boot the DVD I created when I was young was the first thing I did. To my little surprise, it did not work: although I can run any code on the GC (’s CPU), the optical drive has its own firmware, which bans DVD-R.

So I tried to copy the DVD into the SD, and it was a bit better: I could load the kernel and its initial ramdisk, which in turn tried to load Debian from the optical drive, which indeed was not possible once again.

Therefore I decided to recompile the kernel, to customize the embedded initrd, and to be sure it supported SDHC. I relied again on DeltaResero’s repository of GC-Linux kernels. Though he supported GC, he worked mainly on the Wii, so, when I tried to compile the latest kernel he offered (based on version 3.15) using the GC configuration, I encountered compilation problems. Eventually after having fixed them and produced an image, it booted, but went to kernel panic.

Thus, I decided to use an older kernel, in particular one from the 2.6.32 series, as the kernel that I compiled in 2009 - and worked in 2020 - was from that series.

But these kernels had some checks on the used GCC version, and they worked until version 4. I really wanted to carry this out quickly, because there could be a lot of additional problems, so I decided to create a Debian Jessie PowerPC chroot, since Jessie shipped GCC 4. Luckily, the Debian folks are very good at archiving stuff, so it is still possible to create chroots with very old versions of debian with debootstrap:

debootstrap --foreign --arch=powerpc --include debian-archive-keyring,build-essential,ccache,git,ca-certificates jessie jessieppc/ http://archive-klecker.debian.org/debian-archive/debian/
chroot jessieppc
debootstrap/debootstrap --second-stage
adduser piero # Of course, you can use the username you want, or even continue as root (although not suggested)
su -l piero
git clone -b GC-Wii-Linux-Kernel-2.6.32.y-STABLE --single-branch https://github.com/DeltaResero/GC-Wii-Linux-Kernels.git
cd GC-Wii-Linux-Kernel
cp arch/powerpc/configs/gamecube_defconfig .config

We are almost ready to compile the kernel, but first we need to modify the boot params, which are stored in the file arch/powerpc/boot/dts/gamecube.dts:

[...]
		bootargs = "root=/dev/gcnsdb2 video=gcn-vifb:tv=auto force_keyboard_port=4";
[...]

With this setting, we tell Linux that the root is on the second partition of the SD/SDHC/SDXC on the SD Gecko in the slot B. You might want to change that. After that, we can compile the kernel: make -j16 zImage (I have a 16 thread CPU, you can change that number).

Please notice that I used zImage as a target for make, rather than zImage.initrd, because the root is a partition of the SD and is specified in a way that the kernel recognizes and can access, without either running scripts, nor loading modules. Again, that’s something you might want to do differently.

In all the cases, Swiss cannot boot standard kernel images/standard ELF files: we need to convert them to DOL files, first. But they do not play nice with the elf2dol program available in devkitPPC, so, following this guide, we need to use the old doltool.

Sadly, the folks of devkitPPC decided to remove all their history from SourceForge, to switch the system they use now (a series of repositories distributed thorugh Pacman - the Arch Linux package manager) and many things are not available on GitHub, either, including the Dol Tool. However I found a copy of its source in this GitHub repo. I do not know which license applies to that code; it may be GPLv2, as it was included devkitPro. However I think that its original authors did not really care about that - you can see on their original site (which they stopped renewing in February/March 2006) and in the original readme that they just wanted to share it for the good of the community. In this spirit, I decided to reupload a copy that automatically checks for endianness at compile time.

So, you can download, extract and compile my version of the doltool in the chroot, and then run the script from the GC-Linux wiki, which basically consists in running these commands:

objcopy -O binary -R .comment -R .shstrtab -R .symtab -R .strtab -R .gnu.attributes arch/powerpc/boot/zImage zImage.bin # change with zImage.initrd if you need the initrd
doltool -c zImage.initrd.bin 80600000 80600000

In all my tests, the arguments were both 80600000; if they do not work, try to use the GC-Linux script, which automatically extracts the correct arguments. The just-created .dol file will be read by Swiss.

Now we need a system, to put on the SD card. I just copied my old system, but I am not sharing it here because it has some problems 😅.

Finally, I booted the Debian image I prepared nearly 12 years ago, and this is what appeared on the screen

My explanation is that I just downloaded one of the Debian roots available in the GC-Linux SourceForge page, and then added manually lots of packages, like fluxbox and so on, but they were just too recent to work on that very very old system (ca. 2004, I estimate, i.e. 5 years earlier than my attempt). But it booted, and for now, I am okay with reaching this point, I still consider it a victory.

There are some alternatives to get a system for the Gamecube: either downloading the Mplayer frontend distro, or downloading a GC Debian image (both available in the GC-Linux SourceForge page), or creating something new, e.g. with debootstrap. In the former case, if you add the memory card to the /etc/fstab file, you should also add the related device nodes to the image. In the latter case, you should consider that the GameCube has only 24MB of RAM, therefore, the latest Debian running on ppc may not be usable at all.

Ideas for the future

I am stopping here, for now. The main reason is that I have only controllers, as input devices. An idea would be using the GameCube SDL 1.2 port to create a virtual terminal emulator on the framebuffer and with a virtual keyboard controllable with the joystick.

But what I really would like to do is to bring the GameCube online. Unluckily, today Broadband Adapters are sold for more than 100€, which is just too much for my intentions. I wonder how spread they were in my country during the GC days, since in the early 2000s most of the people who had Internet access in Italy used the dial-up, and only companies and some school had local area networks.

In any case, I realized that I do not really need an official GameCube adapter: although I have one of the only 8 games that support the functionality, I am not really interested in it, I just want networking on Linux. Moreover, the EXI buffer is electrically compatible with SPI devices, and there are a lot of cheap SPI-Ethernet converters based on the Microchip ENC28J60 IC, which are commonly used with Arduino.

So I ordered one from China, and it will take quite some time to arrive to me, then my plan is to connect it to the GC through the Serial Port 2, and to adapt the existing Linux driver to use EXI. At that point I will be completely satisfied.