A Look at Aleph One (Part 1)
Thursday, December 26th, 2002, 1:47 PM
If you never even heard the word "Bungie" before you bought an Xbox, you might have occasionally wondered why Bungie fans occasionally throw around unfamiliar and downright arcane terms like Jjaro and W'rkncacnter. You might have stumbled over the occasional reference to "Waldo World" or "5-D Space" and been completely befuddled. Maybe you asked around and found out that those names come from the Marathon trilogy, a series of games created by Bungie in the mid-90s. Maybe you wanted to check out these games and learn more about Bungie's roots but found yourself frustrated because the games are hard to find (hint: look up the Mac Action Sack in the Bungie Store) or won't run on your computer. What's a Bungiephile-in-training to do?
Enter Aleph One.
A few years ago, Bungie released the source code for the second game in the Marathon trilogy, Marathon 2: Durandal. Ever since then, a dedicated group of developers and Marathon fans have built on the foundations Bungie laid years ago, adding new features the Marathon community had dreamed of for years and porting the code to work on new operating systems that had never been able to play Marathon before.
Ever since the first Marathon game was released in 1994, internet multiplayer has been something of a holy grail for fans of the game - but because Bungie was always working on some new project, we never had time to do the complete overhaul of Marathon's networking code that was needed for internet support. Recently the Aleph One team added support for TCP/IP networking, making Marathon over the internet a reality. I thought this milestone would be a good opportunity to interview some of the people who made this possible, with the dual aim of learning more about the future of Aleph One and introducing their work to those of you who still haven't played what is (in my not-at-all-humble opinion) one of the best games Bungie has ever made - now even better than it used to be.
In this first installment, you'll meet three members of the Aleph One team - Loren Petrich, Jesse Simko, Alexander Strange and Woody Zenfell - and find out more about the origins of the Marathon Open Source project.
What first drew you to work with the Marathon source code?
Alexander Strange: I had played some Marathon back when Marathon 2 was new, and I forgot about it for a few years. Then I looked around, saw that the source had been released, and decided it might be fun to play with.
Jesse Simko: I was working on a big Marathon scenario back in 1999, and I thought of all kinds of things that the source code could do to improve my game. Two days after the code was released I pitched the idea of a Marathon Open Source web site to the guys at bungie.org, and shortly afterwards source.bungie.org was launched. I figured that maintaining a web site devoted to the cause of improving the code was the best way for me, a non-coder, to encourage the development of the engine. In the back of my head, I was greedily anticapating new engine features that would benefit my own scenario. But I also imagined a how fantastic it would be for an already tight-knit gaming community to have something new to rally around.
Loren Petrich: I wanted to fix some of the annoying bugs in the Marathon engine, like various geometry-complexity limits. And I also wanted the graphics to look better. MUCH better. No more horrid blockiness and no more being stuck at 640x480.
Woody Zenfell: I was excited by the features (Windows compatibility, OpenGL rendering) that had already been added, and felt that I had the particular knowledge and experience to help fill a gap (networking on non-Mac versions, via IP). Also, netplay had been a particularly important component of the Marathon games for me years ago, and I was unhappy to see that it wasn't working when I found the project.
I was more excited by Aleph One than by projects that, say, try to simulate Marathon under Unreal Tournament, because Aleph One was "really" Marathon - the graphics were the Marathon graphics, the sounds were the Marathon sounds, and the weapon behaviors and alien behaviors and Bob behaviors were all Marathon behaviors - not just somebody else's differently-styled impression of Marathon.
Marathon-style netplay is something I didn't see in other networked run-and-shoot games, which is a good part of the reason I thought it was important to make it available to people. The pacing and weapons balance in Marathon 1 is superb, and is simply not found in games like the Quake series. I've lost touch with the latest crop of such games, due to a lack of players and a lack of up-to-the-second hardware, so maybe they've gotten better... but at my last count, Unreal Tournament was the closest in terms of weapons variety and balance. You still had to crank the overall game speed down significantly though, there was still no motion sensor, and most levels still had health packs and armor all over the place.
What previous development experience did you have at the time?
AS: Not very much. I've got a lot more recently (with Fink and iThink Software).
JS: I had a little experience with REALbasic, a language that I have since written about 100000 lines of code in; C always was and still remains completely alien to me. I wish I knew it, but I don't have the drive to learn it, especially after having done so much stuff with REALbasic.
LP: I've been doing programming for the last 20 years. Much of my earlier programming had been numerical work for solving some arcane physical problems, and much of my more recent programming has been for data and image compression, data analysis and the like.
In the world of real-time-3D game programming, I've written some data viewers/extractors for the Marathon and Tomb Raider series, and a bit for the Quake series. In fact, I got my start in OpenGL with a Tomb Raider level viewer that someone had written -- it helped me get experience for a Marathon-series level viewer.
WZ: Hmm, well I have a BS and MS (1999) in computer science from a prestigious midwestern university. I guess I've been working with games in some capacity for about 17 years, but that extends back to hacking around inside Commodore 64 BASIC programs typed in from Compute!'s Gazette and operating a Color 64 BBS [Editor's Note: YES!], which was basically my platform for showing off my weird modified versions of the standard Color 64 online games. Although I thought I had learned a lot from my own playing around like that, I didn't really start to understand computing until I was a couple years into my first degree.
For one course at University, we had to write something in 68k assembly for a final project. Most of the students wrote things like Tic-Tac-Toe or Mastermind, with crudely-drawn little Mac OS Toolbox circles or filled rectangles, and where the only interface was by clicking things with the mouse. I wrote a two-player Mac "shoot-the-other-ship" action game, with a big dialog box to configure things like shot speed, shot damage, turning rate, acceleration, whether there was a sun you could crash into, whether that sun produced gravity, whether the walls were bouncy or wrap-around, etc. Players controlled the ships at the keyboard, and graphics (stolen from, umm, a well-known Mac asteroids clone - but the game was never released of course) were rendered offscreen using those little techniques that made CopyBits blitting fast.
I then wrote a version of the MS-DOS action game "Pizza Worm" for the Power Macintosh. Pizza Worm is like "Snake" in one-player mode or "Tron" in two-player mode, but the action is smooth - no 90-degree turns or chunky square-by-square movements. It was in what I'd now call 'pidgin C++'. I thought I really knew what I was doing and was building a nice, clean, efficient object-oriented design. Ha! I guess when you look back, you're always a little amused by how clueless you were. I'm sure I'll look back on some of the stuff I'm doing now similarly. Anyway, the game worked, and since it had some things like measuring the display's refresh rate to adjust the game speed so it would be the same on different displays (but always with the frame rate at the display rate) and rendering the worms and pizzas with different sizes depending on the screen size (so the game would play the same at 1024x768 as at 640x480, but would have smoother-looking worms etc.), and used palette animation, I talked my graphics professor into accepting it as his course's final project. So there it was, among two dozen lame clones of AppleWorks's "draw" mode running under Win32. Poor guy had no idea what to make of it, but passed me anyway. :)
Then, enamored of the Mac game "Mortal Pongbat" but annoyed by its choppy frame-rate, even on decent hardware, I decided to make a version of that for Windows using DirectX. It would have to be smooth and pretty and sound good etc. I wanted it to have, kind of, a 16-bit console feeling, with the smooth 2D action, but I rendered all the sprites in POV-Ray so it wouldn't get that cartoony look. (Besides, I can't draw.) I'd consider that game to be still under development, though it's far along.
Oh, and meanwhile for my master's degree I was writing little UNIX applications and casting about inside the scheduling system of the BSD kernel trying to find bugs - err, I mean 'easter eggs' - my predecessors on the project had strategically planted for me. Yeah that was a nightmare. But, it's not as interesting as the other stuff right? :) So I'll omit the details.
What were the biggest challenges you faced when you first started working on the project?
AS: Lack of skill and lack of time. Plus, that code is skanky :)
JS: Right from the start I was totally gung-ho about establishing the source.bungie.org web site. Since I don't contribute code to the project, I've been trying to maintain the site, and that was never much of a challenge, since I've done plenty of web work before. The site was once a huge all-consuming obsession, but is now more like a fun chore for me to do in my free time.
LP: I think my biggest challenge was OpenGL support, because:
1. I had to get the coordinate transformations exactly right; I ended up devising a coordinate system for the sprites, one for the walls, one for the models, etc..
2. OpenGL's preferred data formats are very different from the Marathon engine's, though they are relatively generic ones. The graphics had to be converted into RGBA 8888 color and painted onto power-of-2-sized textures, and the geometry required transformations too lengthy to be described here.
3. Working out how to do sprite texturing; I had to use a separate texture for each monster flavor, an additional texture for the glowing parts, and yet another texture for invisible and static-effect objects.
4. A bug in Apple's OpenGL support had caused some sprites to look squashed, with other textures next to them. After some lengthy debugging, I worked around that problem by using textures at least 128 pixels in size for the sprites.
An indicator of the difficulty of adding this support was that I went through a long period of using placeholder graphics in the form of flat-color polygons.
Also a challenge was understanding and learning my way around the code. In fact, I was unable to proceed until someone had reverse-engineered the absent "cseries" library.
By comparison, MML support has been fairly straightforward, though tedious.
WZ: Well, aside from the work inside the BSD kernel, where I had pretty clear guidance as to which sections were relevant, this was the first time I'd worked with a sizeable source-code base. So it took a while to sort of learn my way around. Also, a different set of techniques come into play when programming something big than when whipping up something small, and this was the first time I'd actually experienced that.
Aside from that, in my area the trickiest bit was understanding the ring protocol, particularly with respect to scheduling behavior and various misbehaviors. It probably took longer to reproduce the scheduling components of network play than the actual network communication components. (OTOH, Christian Bauer gave me a head-start on the actual network code port.) Of course, it took even longer than that to build the supporting dialog boxes (including my spiffy carnage report dialog that hardly anybody's ever seen) with the little UI-widget system that Christian put together for the SDL version. Not that Christian's code had any problems - but I needed to put in a lot of extensions to make my dialogs behave the way I wanted them to.
Was there anything in Bungie's code that surprised you?
AS: I was suprised at how hard it was to read :) And I was suprised that it used CopyBits() in the software renderer.
JS: Jason Jones seems to have expressed his rage through the occasional obscene comment. But that's understandable, considering he was apparently stuck using MPW (Macintosh Programmer's Workshop) to write all his code back then. Aside from that, the oft-asked question "Wouldn't it be easier to write a new engine from scratch?" leads me to believe that sorting through the code is like untangling a bunch of spaghetti after someone let it sit out so long that it re-hardened.
LP: It is very short on comments; it could have used some documentation explaining which each data item and each function does. The code has been worked on for several years by several programmers; one might expect those contributors to try to help out their colleagues in this fashion.
As a result, I've often had to use CodeWarrior's search function to find out what something does.
And though the complexity of the visibility code, for example, is somewhat understandable, I find the input-event code needlessly convoluted.
Also, for some reason, its variable names are all small letters; I tend to use lots of capital letters in variable names.
WZ: I was always amused to read the comments. Things like the listing of weapons, or snide comments about other programmers, or Jason's prediction of how the new sound code would make Pathways into Darkness's sound code look.
I guess - this has got to be because this was my first experience looking at real game code for a real, non-trivial game - once I learned my way around a little, the code seemed cleaner and more structured than I had, for some reason, expected game code to be. I gained a better sense of how various bits of code ought to interface with one another - how chunks of code within a subsystem may have a fairly 'wide' interface to one another, but the interfaces between subsystems should be as narrow as is practical. I also understood the importance of 'assert()'. :) On small projects, the code can be written just for the machine. When a project's size crosses some threshhold, though, the focus has to be more on the people - making sure the code authors can do what they need to do, but keeping them from making the dumb mistakes that humans inevitably make. I mean, if you screw up, but the compiler or linker or a runtime assert() points it out almost immediately, then you end up with fewer weird little bugs seeping into the code base and messing with everybody. And that reduces debugging time not just for you but for everyone involved. So, going a little bit out of your way to encourage these 'early catches' is ultimately extremely valuable.
Be sure to come back for our next installment of this interview, which will feature more in-depth discussion of the features and future of Aleph One.