Quake III Arena for iOS and tvOS for Apple TV

My next stop on the tour of porting id Techs to iOS and tvOS is Quake III Arena, powered by id Tech 3. In keeping with tradition, here’s the link for those who want it right away

Quake III Arena for iOS and tvOS for Apple TV:
https://github.com/tomkidd/Quake3-iOS

Those playing along at home may be wondering: “Hang on a minute, why didn’t you do Quake II next?” Well, it’s interesting…

I was looking for some information about Quake online after I posted the previous article and I stumbled across a strange image in Google Image Search of multiple iPhones playing Quake, seemingly together.

Looking into it further, I found the origin of the photo – it boiled down to this page detailing a port of Quake to the iPhone by a company called TMSoft. It appears TMSoft is a mobile app developer and consulting company that ported Quake and made its source available… back in 2008.

I was blown away. In my previous article I mentioned that I had searched high and low for existing ports of Quake to iOS and I had only found two, and only one of them would build, and it had Google Cardboard code in it. And here was an existing, working port of Quake to iOS a decade ago. Being done in 2008 meant a lot of things. It meant that this port predated the official Wolfenstein 3-D and DOOM ports by a year. It meant that the video they show of the port was running on probably an iPhone 3G, and they mention they had it going 20-30fps. It meant that it was running on iOS 2.0 (or rather iPhone OS 2.0 since they weren’t calling it iOS yet). And crazily enough, it not only featured a working console for typed commands, it featured multiplayer.

At the end of my previous article I mentioned that the whole question of multiplayer was something I was kind of struggling with. Wolfenstein 3-D never had it, DOOM did have it but the official port never did, and Quake not only had it but it was a big deal at the time, and my iOS port of it didn’t feature it at all. And besides other aspects of the game being the challenges I was most interested in, I honestly had no idea if it would even work. Like I said, OpenGL in these engines only works because OpenGL ES exists for iOS (for now anyway), but a certain amount of bridging code was necessary (as in, a file that says “when the code asks for A from OpenGL, they really mean B from OpenGL ES”). Quake‘s multiplayer was designed to work on PCs in 1996. What are the odds that it wouldn’t need some additional work fo networking on a device as locked down as the iPhone or iPad in 2018?

But seeing that video made me realize: I hadn’t actually tried it either. So then I did.

“Doctor.” “Doctor.”

Huh. It does work. In the photo above the foreground is running the Quake-iOS port, and the screen behind it is my Windows 10 PC running whatever source port the “Ultimate Fan Patch” includes for Steam. Even crazier is that the iPad instigated the game so it’s running as the “server”. Either the author of the Quake_For_OSX port had done the work necessary to handle networking, or it does work right out of the box. I haven’t investigated this to death or anything but I’m willing to bet it just works. It’s not perfect – I tried to spin up a Quakespasm instance on the Mac and it could see but not join the server, an iPhone could see the iPad server but not the other way around, etc. But the point is it’s not impossible and now I need to see what all is involved with trying to put a UI wrapper around the thing. So I have more work to do. I told you it wasn’t 100% complete.

Parallel to all of that I tried to fire up the Quake port from TMSoft and it doesn’t compile and throws errors. But the errors look eerily familiar, they’re reminiscent of errors I encountered trying to get Wolfenstein 3-D and DOOM up and running and errors I encountered in the Quake for tvOS port when I had cloned the target but not made the C compiler settings match up. So I’m pretty sure if I could work through those issues the same way I had worked on the previous ports, it would compile and run in modern Xcode like the others.

I’m still puzzled as to how I missed the TMSoft port in my initial searches but in the long run I’m glad I handled the port the way I did. The TMSoft port is using Objective-C and EAGLView and is basically the same thing that id Software would have done if they had done the port back then, the port I went with uses Swift and GLKit and is a more modern take on the process (I could probably go do the Swift/GLKit thing to the Wolfenstein 3-D and DOOM port but my design goal in those was to minimize changes).

When I was looking up more info about this TMSoft port I found an article about it on TouchArcade, Another iPhone ‘Quake’ Port Strives for App Store Acceptance. Basically it’s just a news piece from 2008 about the port but two things about it stood out to me. First, it says that TMSoft was “looking at options for licensing the game through id and publishing it through the App Store.” Obviously that didn’t pan out for whatever reason (and wouldn’t it be weird if Quake had hit the iPhone first before Wolfenstein 3-D and DOOM?) but it sounds like at least they tried.

The second thing that jumped out at me was the word Another. The article links to and mentions a previous attempt, id’s Classic FPS ‘Quake’ Heads to App Store. The story (posted just five days earlier, 2008 was a hell of a ride for the iOS world) here was kind of nuts – basically someone else had ported Quake to the iPhone and had gone so far as to submit it to the App Store (the article doesn’t specify if it was going to be free or if he was going to charge for it). The article has an update at the end that id Software had written to inform them that this person’s port of Quake was not authorized and therefore would not be allowed to be on the App Store (the later article says the message came from then-CEO of id Software Todd Hollenshead) and that was that. But the article up to that point was extremely matter of fact about how this particular random individual had just decided to take this commercial game and put it up for free download as if that was the most natural thing on earth.

But anyway, 2008 had to be a rollercoaster for the iOS gaming world and so you can’t really fault a site like TouchArcade for getting excited and carried away with the notion of playing full games on your iPhone in an era when the thing was struggling to run dippy faux MMOs. It doesn’t help that, by accident or design, a number of people do not understand the difference between open source and public domain, like the time that some dude released a port of Abuse to the App Store and then argued with the owner about how he was in the right. Or this guy who would take open source games and put his name on them and re-release them for profit.

But the other sentence in the article that caught my eye was: “Both Quake and Quake 3: Arena have existed in the iPhone jailbreak community for some time.”

Wait, hold up – Quake III? As in id Tech 3? Ten years ago?

TouchArcade links to an article mentioning a game needing a jailbreak, but I got curious whether or not anyone had done a port to iOS and if there was source out there.

That led me to another article on TouchArcade, this time from 2014, about how to play Quake III using an app called Beben III.

Beben III actually got published to the App Store for sale, and you can actually still find it in the App Store today, however as of this writing it can’t run on iOS 11 because of the 32-bitpocalypse. It avoided the issue of legality by not providing the Quake III data files. Instead, you could either send those files to the app yourself via iTunes and iOS app document handling, or you could have the app itself download OpenArena content (OpenArena was and is an attempt to make a free game using the Quake III engine and all new open source content and levels) or the Quake III Arena demo from somewhere. And of course it avoided calling itself Quake III.

So since this was a port that actually got released to the App Store the source has to be out there, right? I went to his site where he details the process and at the bottom of the posts he says if you want the source code, send him an email. The post was from 2013.

I’ll be honest at first I thought the GPL required the source to be posted somewhere like a public website but after a little reading it turns out this is generally considered a valid interpretation of the GPL – namely if you put out a compiled version you have to make the source available to anyone who asks for it. There’s no requirement about having it be out there all the time. An even stricter interpretation says you only have to make it available if someone asks for it and they have the binaries which in the case of a commercial app could preclude anyone who wants to roll their own without purchasing your product.

Still, it was a blog post from 2013 on a blog that hasn’t been touched since 2014. What were the odds that this person hadn’t fallen off the face of the earth? Or still had the source handy five years later? Since the email address was of the firstname.lastname@gmail variety there was a decent chance it was still in use.

And parallel to all of that I had started dinking with Quake II. As far as I can tell there are no ports of it to iOS yet (though, after the searches above, I’m not completely certain of that anymore) and so I figured the first thing I’d do is get it up and running on the Mac. Which proved to be a little harder than I thought. There’s a couple of modern-ish source ports of it that have macOS ports, but they all use MAKEFILEs instead of Xcode projects, so I had started going down the rabbit hole of getting a MAKEFILE-powered project in Xcode when I found Beben III.

So in the middle of trying to get Quake II to work I found this existing Quake III port so I figured – couldn’t hurt to email, right? No idea if it would go anywhere. I basically asked if he had the source handy anymore because I was going through the id Techs and it would be nice to add to my collection, followed by a listing of the three GitHub URLs. I wasn’t sure if the “hey I want to take your work and screw with it and put it back out” angle was the right one but I added them anyway.

Five hours later I got a response, basically saying “Sure, I’ll add you to the BitBucket repo”, followed by an email from BitBucket to be added to the repo.

Holy shit.

I quickly dashed back to my desk at work, fired up my personal MacBook Pro, connected to my personal hotspot on my iPad, raced through the steps to create a BitBucket account (turns out I already had an Altassian account), then accepted the invite and cloned the repo. The whole time my thought process was: quick, get this cloned before he changes his mind!

And in the middle of cloning I got another email granting me write access to the repo.

In the initial email he asked if I did anything with it to please not include the graphics because he didn’t have the rights to redistribute them, which is the origin of not putting the repo public in the first place. In my mind I’m remembering how I use id Software graphics without permission in Quake-iOS and hope they don’t mind. We emailed a couple more times and I said I’d let him know if I got anywhere with it.

BitBucket’s site showed the source hadn’t been touched since 2014. I opened up the Xcode project and it had hundreds of warnings, but only about four errors. One of them was about “moarfonts” which was apparently an old method of getting custom fonts to render in Interface Builder that had been rendered unnecessary in Xcode 6, so I just axed it. One error was on how the storyboards were targeting too low of an iOS version so that was easy to fix. And two errors were about missing symbols which were contained in C files not included in the project, which seemed odd, but I included them and hit build. And it ran. Holy crap. I struggled with those other ports for weeks but this one was building in less than an hour.

From there I made some tweaks so that I could see the menu that presented the options, and a hack to deal with getting the Quake III files onto the simulator (since the iTunes thing would definitely not apply) and at some point I was up and running with the orientation issues naturally expected in any game that hasn’t seen loving past iOS 8. But a quick fix to that and the Quake III menu was running in the simulator.

I was dreamin’ when I wrote this, forgive me if it goes astray

It’s fascinating, I’m torn between being blown away that Quake III Arena runs on iOS and thinking… of course it runs on iOS. The game was designed for PCs in 1999, of course it runs on your $1,000 phone from 2017.

Beben III, like the Quake port I worked with that had Google Cardboard, was aiming to mostly be a literal port of the old game, warts and all. As in, with the Quake port you hit a button on the controller that was effectively the Escape key, which brought up the menu, and then the options from the original game were available there. Not all of them worked, and “exiting” the game generally screwed everything up because there’s no real concept of “exiting” an app in iOS, but it did alleviate the concerns of making a menu system. Beben III features a menu to choose Quake III‘s pk3 files or the OpenArena stuff but outside of that it’s pretty much the same game that shipped in 1999, for better or worse. The code to maneuver the mouse pointer has to be kludged in a bit since the original Quake III engine’s UI wasn’t designed to handle absolute mouse positioning, it was designed to handle relative ones (makes sense, your mouse moves down the pointer moves down). The approach I’ve been taking in my id Tech iOS ports is to have a Cocoa Touch-based series of screens before dumping you into the real game, bypassing those menus.

I contributed my changes back to the Beben III project, as well as MFI controller support (there was the beginnings of this in the code already, I tweaked/finished it). There’s a chance it will come back out at some point, but that’s up to the original author.

At some point I finally tried to get it running on an actual device and I was halted by compile-time errors. I was a bit confused, but I realized at some point that the errors were from those files that I thought were “missing” and not included earlier. Basically what I figured out is that those files were C-based reimplementations of assembly code. Back when Quake III was released, part of the magic that made it be able to run on 1999-era computers is that parts of it were written in assembly. I believe this meant that portions of the original Quake III had to be compiled using an assembler and linked in with the rest of the C code. As time as gone on and computers became more powerful the need to have this part be in assembly has waned, to the point where a C reimplementation of it is sufficient. Modern source ports of Quake III have gone so far as to have code that says “hey, can you handle x86 assembly? If so then use this, otherwise we’ll just do it the hard way.” When compiling an app for use in the Simulator, you’re not actually compiling them for the iPhone or iPad, they’re running on the Mac, just in a tiny window that’s pretending to be an iPhone or iPad. That’s why the use of the term “Simulator” is not an accidental one.

I’m far from a genius on this so I may have parts of this wrong but I believe that, either because the the simulator shows up as an x86_64 processor or possibly an i386 processor, the code that says “hey, can you handle this x86 assembly” says “yes” and as a result the compile fails if I don’t have those two files included. However, that same “hey, can you handle” code says “no” when running on an ARM processor like the ones in the iPad and iPhone, and the code in those two files also fails to build for that same reason. One way to get around this would be to short circuit the code’s need for these C files in even x86 mode, but I wanted to avoid modifying the base engine code any more than necessary (more on that below). However, there’s valid reasons I would need to compile and check something quickly in the Simulator, so my solution for this problem was to have two targets – one named “Quake 3” and one named “Quake 3 Simulator”, the latter of which has the files included. Once I got this sorted out I had an actual Quake III running on my iPhone. And I have to think some of the above shenanigans are responsible for the fact that while it plays damn near perfectly on a real device, it’s a different story on the simulator – not that we need it to look right in the simulator

Not pictured: the guys in helmets about to take me out with a wrench.

Ahh… much better. Take that, Fortnite!

I have to say, it may be the nostalgia talking but to me Quake III is still a beautiful game. A few years back I was playing some Quake Live at QuakeCon when a friend of a friend asked “what game is that?” (I know, someone at a QuakeCon who didn’t know what Quake III looked like – weird, right?). When I told him what it was he said “that’s hideous looking!” I said what do you expect from a game from 1999 but it occurs to me that maybe the main reason I still like how Quake III looks is because I never really stopped playing it. When you go back to a game like the first Unreal it can be hard to look at because you’ve seen much better looking games since then but something about Quake III is just timeless to me.

It’s interesting, the code from the Beben III drop has several different names in it attached to various files exclusive to the iOS port and I’m seeing some more stories talking about various jailbreak versions being released over the years so I’m wondering the extent to which the code I’m messing with has been dinked with for close to a decade now. As far as I can tell the code as it stands now is based on a version of ioquake3 from around 2013, with some #if IOS stuff sprinkled in here and there as little as possible. I figure at some point I’ll do the work to graft in the most recent ioquake3 source with the iOS-specific changes in place, assuming I can’t find a better way to do it. Depending on how well this goes over, iOS might be a supported platform of ioquake3 some day but we’ll see.

The short history lesson on Quake III is that while Quake shipped with a software renderer and hardware renderers were released as add-ons later, and Quake II shipped with both a software and hardware renderer, Quake III was unique in that it originally shipped with just a hardware renderer. While Quake shipped with co-op and deathmatch modes, with other play modes created by mod authors, and Quake II featured official versions of some popular modes like CTF in later patches, Quake III eschewed a single player campaign entirely in favor of a multiplayer focus with modes like CTF shipping out of the box, with the then-relatively recent notion that a FPS game’s multiplayer mode would benefit greatly from not having to split development efforts with a single-player mode (the game was actually announced as a regular sequel called Quake 3 and then a few months later announced to be changed to Quake Arena, and then later the Quake III: Arena name was settled upon). The game shipped in 1999 more or less simultaneously on Windows, Mac and Linux in separate boxes and SKUs because they wanted to see how the sales breakdown panned out (the Linux port got delayed because Activision passed on it and the lone Linux publisher, Loki, wasn’t ready for it). I believe the final tally was Windows 95%, Mac was a little over 4% and Linux was less than one percent (exacerbated by the Loki delay plus the tendency of Linux gamers to dual boot into Windows)

There was one expansion pack, Quake III: Team Arena, which added more maps and modes, and then id switched gears to start working on what would become DOOM 3. In 2005, they released the Quake III engine as open source like they had done with all their engines to that point. Something that’s interesting to me is that while the DOOM source port scene was a bizarre wild west of various ports and efforts with some merging here and there, and the Quake source port scene whittled down to a handful of options, for the most part the Quake III source port scene has largely coalesced around a single effort: ioquake3, the name coined by Ryan “icculus” Gordon.

ioquake3 was started shortly after the original open source release and has been active ever since. It’s wild to think that this project has been improving and maintaining Quake III for thirteen years. Most game engines see a few years of development at most. Large massive projects like Microsoft Word wind up with a lumbering codebase that shambles on for decades. It’s not unheard of for a game to release its source code in some form or fashion but it’s unusual for one to see so much active development for so long after its release. It’s weird to see that such and such thing was removed from the code back in 2011 and think that that was seven years ago.

And when I originally postulated on the concept of maybe trying to get Quake III up and running like I had done for the other id Software engines, I did wonder whether or not it was worthwhile seeing as how it’s more or less an entirely multiplayer game. I thought maybe the benefit would be less to Quake III itself and more for an id Tech 3 powered game like Return to Castle Wolfenstein, which also has its source code out there (and an ioquake3 derived project as well).

But then I was able to finagle the menus and figured out – this damn thing running on my phone can connect to live Quake III servers.

This is the part where I become a little out of my depth. Quake III featured an optional anti-cheating component called Punkbuster, which I believe was Windows only but it definitely wasn’t on iOS or included in ioquake3. I’m not sure how they prevent a hacker client from connecting, seeing as how the source code is out there, but presumably there’s some mechanism for enforcement, even if it’s that the cheaters just don’t care to bother anymore.

Quake III is also interesting in that it still has a player base and a following today. I’m sure there are many games like this to some extent but I have to think that Quake III‘s sheet popularity in 1999, coupled with the community around ioquake3, has helped it stay afloat all this time.

It’s even more impressive when you consider the player base split that occurred a while back. id decided to get into the F2P FPS genre with an entry called Quake Live. Basically the premise was a free version of Quake III that ran in a web browser and used the web for matchmaking. The game itself ran “in” the browser via an ActiveX or NPAPI plugin so it was the real thing, not some HTML5 bullshit.

It launched as being ad supported but that monetization model failed for the most part so then there was a subscription model. Then two subscription models. I think they were called Premium and Pro. I had a subscription at one point and I honestly have no idea which one. Or what the differences were. Then the game was ported to Mac and Linux. Then when the web browser technologies got deprecated it became a standalone game and then un-ported to Mac and Linux. Then it came to Steam and reset all the achievements. Then it made tons of rule changes but I don’t know what became of those because every server I play on just has the old rules in place. Then it became a $10 game, no more subscriptions but no longer F2P either.

And that’s on top of things like the initial delay of the original game because it turns out web development is harder than game engine coders thought it was. And the original name Quake Zero being ruined by domain squatters. And the rumor that Quake Live is pretty much what id Software used to train new developers on how to work with their company’s workflow/pipeline before moving them to other projects. Quake Live is the game industry equivalent of a television show that keeps changing formats because they can’t figure out what it wants to be.

And yet despite that there’s still hundreds of Quake III servers online. It’s just hung on after all these years.

So, given that the multiplayer worked I figured it would be appropriate for my Quake III port to iOS would have it as well, so I needed to include a server browser.

The first road I went down was thinking that since the game itself features a server browser, then surely somewhere in there is code that basically says “query the servers and hand this string to the browser” and if I could intercept that I could just put them in a UITableViewController or something. This turned out to be trickier than I thought, especially since it basically has to have the “game” running to use it, but more to the point I didn’t have any luck in this area.

I thought maybe somewhere someone had made like a REST API or something but I couldn’t find one of those either. The best way to do this would be to tinker with and maybe reverse engineer the protocols the server browser uses but that sounded like a giant pain in the ass, and way beyond my ability or time constraints.

So I Googled “Quake 3 Server Browser Mac” and the first or second result that showed up was Q3ServerBrowser, a Mac server browser whose source was in GitHub. I clicked the little bar on the GitHub page that shows what language the project is written in… and it’s 100% Swift. I was elated. Even better is the project kept the UI and querying code in separate targets so I could just import the querying code wholesale.

It did have a dependency on something called CocoaAsyncSocket but fortunately that project is cross platform across macOS/iOS/tvOS so we’re good there too. However, I wasn’t sure how to best include it. Up until now I’ve been avoiding putting any sort of package management in these ports because I wanted people to be able to just fire up the code with as little hassle as possible, but for a project that touches the Internet and might be susceptible to security holes and the like, it made sense to start using one. I included it via Carthage, the package manager of choice at the moment. I’ve included the builds and checkouts it does so you don’t actually have to do the Carthage update unless you want to.

So with that, I set off to write a server browser to include in the app. Which, I would later realize, is like saying I went off to write a word processor. Not so much in so far as the two being comparable in scope, but more that it’s like saying you’re going to go casually write something that a number of people have spent lots of time and energy doing. You get to rediscover all the things they had to discover. People used to write these things as commercial applications. I was going to dash one off in a few hours of work.

Anyway I got a serviceable one in place. It could be more elaborate but I’ve reached the limit of what I’ll do before knowing if anyone’s actually going to use this thing.

That… sounds uncomfortable

It’s odd that people still name servers like companies trying to get to the beginning of the phone book when most people probably sort by ping. It’s also odd that this thumbnail looks like shit for some reason.

So with all that fun accomplished, what I really wanted was to add more features to it before I told people about it. I also really wanted to get Quake II up and running on iOS and release them at the same time, and in that vein I went on a trip for a few days getting a Mac source port working in Xcode, but I hit a wall there. And I really wanted to get the Quake III port out before QuakeCon 2018 for no other reason than I thought it would be cool to play Quake III in line waiting for the BYOC so this is pretty much what the initial version is going to be. If we say the initial Quake offering was about 85-90% done, I’d say this one is about 75% done since things like custom bot matches or the ability to change your user model.

And heck right as I was writing this paragraph I realized I hadn’t added an Options screen to change your name. I just went and put that in otherwise we’d all be Schnapple.

And parallel to all of this I got it running on tvOS as well. Since the ioquake3 code is parted out and very little of the Swift code needed to be platform specific, the tvOS port was mostly uneventful and just sort of came along for the ride with one exception – the Beben III code’s audio initialization code was old enough that it was deprecated back in iOS 7 and it still worked, except it meant that those methods never existed in tvOS to begin with since tvOS started out at version 9 in rough feature parity with iOS 9. I could find Objective-C code that did what I wanted but I couldn’t figure out how to get it to call in C. But then the damndest thing happened that worked – I renamed the .c file to a .m file, changing it from a C file to an Objective-C file, and it still built and compiled. Everything it did in C was valid Objective-C. I could then make the Objective-C calls with no problems.

So anyways, this crazy 1999 computer game that people still play and maintain the source for is running on a modern iPhone and can still play with the PC servers. It’s not perfect, it has an occasional sound glitch, and it needs more options, but it’s apparently built on the works of people hacking on it a decade or so back.

Here are some videos of the ports in action, and how it plays with a SteelSeries Nimbus controller

If anyone wants to contact me I can be reached at tomkidd@gmail.com.

Thanks.

Categories: