I took a break from Cave Story this week to work on Quake for the GameCube.
There had been a couple of long-standing bugs which halted progress on Quake. Firstly, the SD card library seemed to be reading garbage data occasionally, which would generally manifest itself as corruption when loading the second demo in Quake’s attract mode.
Thankfully, softdev released an alternative SD card library which I quickly plugged into Quake. That fixed the bug, but added a couple of limitations which weren’t there before:
- File names must now be upper case.
- File names must be in DOS 8.3 format.
- SD cards are only supported in memory card slot 1.
Thankfully there’s nothing too major, as Quake was a DOS game and SDLOAD (used to run GameCube programs from SD card) only seems to work with slot 1 on my GameCube anyway.
After that bug was gone, fixing the other was much easier. The other bug seemed to cause some variables to get corrupted, but only when starting a new game. Previously I couldn’t tell what the cause was, because the two bugs fed into each other and I couldn’t be sure where the corruption came from.
Disabling optimisation made the bug go away, so I suspected that one or more of the optimisation flags were breaking the code generation somehow. Just to make sure that it wasn’t my code that was buggy, I disabled optimisation for my code only and let Quake’s code use full optimisation.
The bug remained, so I was fairly certain that my code was fine. To be honest, there’s not much GameCube specific code in there but I wanted to be really sure it wasn’t my problem before blaming the tools. You know what they say.
GCC’s -O1 switch turns on a bunch of optimisation switches, so I systematically went through all of them, checking to see if any broke the code generation. And sure enough, one of them did (-fmerge-constants).
So with the naughty switch disabled (-fno-merge-constants), Quake now runs without crashing and with (almost) full optimisation. And boy, does it run. At 320×264 (PAL), demo 1 runs at comfortably over 70 frames per second. At 640×528, it runs at just under 30.
I implemented input and audio too, so the game is quite playable. Unfortunately, Quake uses the standard C library’s file functions for save game access, so there’s no support for loading and saving games yet. I’ll need to convert that code to use the abstract file system instead.
I also need to convert a load of code which expects the user to press “Y” or “N” into something more suitable for joypad users. I currently map the A button to “Enter” and the B button to “Escape” so they seem like good candidates.