Halo and the Battle With the Past

Working on this project was a dream come true! One of the most legendary titles of all time! The mighty Halo! As powerhouse a game as AAA games come. I was thrilled to work on this. I’ve loved all the Halo games as they’ve come out and have spent many, many hours playing through the campaigns and attempting to raise my rank in multiplayer.

There was tons of miscellaneous work I did for this project, but as far as super important tasks went I mostly had one critical duty on this project. That job was to carve out a way to add incremental content (like fun party hats) in small patches in the aged 1998 codebase through any means possible. A battle against the past. And, indeed, many days on this project often felt similar to what I imagine a day in the trenches would be like. The predominant enemy? Macros.

This codebase was almost entirely written with macros. To do anything, you passed macro results into macros that passed those values into other macros that sent those values directly into other macros. This is not even exaggerating for effect. This is the reality of that codebase. It would often take 20 minutes to understand a few lines of code because you had to follow a massive trail of macros to even uncover what was happening. I was stoked to be on the project, but I have never worked on anything more exhausting. Day after day of intense macro analysis.

The code was broken up into three areas I had to manipulate to get this content in. The first stage took the raw assets and converted them into this platform-independent generic asset type known as TAGs. The second stage then took that generic asset type and converted it into the platform-specific data the game would actually load in. Then, of course, the third phase was loading that data into the game at runtime and using it. All three phases were macro heavy.

There was no documentation on these systems and no one to ask about them. The code was written by Bungie employees that no longer had any connection to Microsoft. No one at Microsoft knew how this code worked. That’s what they hired us for. After nosediving headfirst into the macro Hell every day for a few weeks, I was provided with resources from the original engine team. There was not much there, but included amongst it was a video of a presentation they gave on the engine system. This sounded interesting and I figured it might help me navigate the codebase some, so I put it on while I was looking at more code.

My ears perked up when I suddenly heard the presenter mention the word macro. I immediately gave the video my full attention. What could they possibly have to say about this?

“Many people in the industry today discourage the use of macros.”

Okay, but I guess they have some excuse?

“Don’t get me wrong, macros are problematic. They can obfuscate code, hide implementation details, and make it difficult to understand what the code is actually doing.”

Well, that sure is a lot of negatives…what could they possibly say to follow up that list of problems?

“This is all true, but none of it matters in our codebase. Look at this complicated macro.”

He shows one on the powerpoint slide that looks fairly confusing.

“Now look at this!”

He shows a function using a different macro with a single argument that looks nicer and calls the initial one with the many arguments internally.

“Our macro usage isn’t complicated at all, because we can hide those implementation details beneath other macros that make it user friendly.”

I nearly spat the water I was drinking all over my keyboard. I watched a few more minutes to see if it was a joke. It wasn’t. I took a few moments to reflect on the legendary magnitude of what I just heard. Indeed, I would be hard pressed to say anything more ridiculous if I were trying to make a joke. They really thought the issues with macro overuse were fixed by hiding them behind more macros. Simply amazing. The fact that Halo, one of the greatest games of all time, was produced under such conditions is a testament to the human spirit.

Here’s a short blog post about macros from Raymond Chen, also known as the Chuck Norris of Microsoft. I’ll probably post something about them and the evil abominations known as exceptions in a later post myself, but the gist is they just truly make things harder to understand and harder to debug as well.

But let’s get back to that task. Adding incremental content to the game. Now, the problem was that Halo was designed with these monolithic level files in mind. Every asset used in the level was contained within the individual massive level file. Adding a single hat to the game would require touching every single level file across every Halo game, as of course we’d want the hat to be wearable across all of them. Even for just the Halo 1-3 levels, that would mean an ~100 GB patch each time a hat is added. So, you can see the need for an enhancement to the system.

I won’t go into too many details, but this was a very rigid system built specifically for the sole purpose of cramming all the data for a level into individual files to put on the DVDs and loaded all at once on the initial loading screen. And to make sure it was all valid and secure. There were checks upon checks upon checks I had to hook the new system up with to verify the size of a level, the size of the assets, the size of the group of the assets, etc. Redundancy at every stage of the pipeline to fail if anything looked even slightly off. There were security measures put in place to not allow any data to be injected on top of that.

I was really glad to be working on Halo, yes. Would I choose to do it again? I would. But pouring through all those macros and systems to get these new assets to work, staring at barely readable code for the better part of every day for weeks and weeks and determining why cryptic checks were failing…was an exhausting period of work. But since I was the only one looking at a lot of the code in the asset areas initially, I was able to help out the rest of the team a lot later on. I gave some presentations to explain the fundamentals of the systems to bring people up to speed and got things rolling for some other tasks more quickly. The reason I mention this is for a bit of background on the meeting I am about to detail. It will sound like a delusional narcissistic fantasy, but I assure you it really happened.

For the end of the milestone, each team member was asked to list something positive and negative about the project. Notes were taken to refer back to when analyzing project methodologies in the studio. One team member said something positive was that I really helped out a lot with his task and he doubts he could have finished it by the deadline without me pointing him in the right direction. The production assistant looks at the lead and asks him what to put, so he says “teamwork”. The next team member says he guesses the best thing was that I did all his tasks because he was on vacation the whole milestone. The lead says to put a checkmark next to teamwork. It gets to a third team member, and he says he has to say the best thing was me telling him what his task actually was because he had no clue before I did so. The production assistant asks the lead “another question mark?” and he smiles, shakes his head, and says “just erase teamwork and write down Rio”.

I don’t like to toot my own horn, but I found this story too humorous to leave out. Truth be told, I was only doing what I feel most engineers should be doing regularly anyway. A lot of programmers have a lone wolf attitude, and this can and does often serve them well…but there are benefits to taking some time to help the rest of the team, especially in a codebase as confusing as this one was.

Anyway, I finished a working prototype for adding some assets in a good bit ahead of schedule. I was glad. All the work had paid off after what had been the longest task I’d ever had without solid results. Being a generalist engine programmer in an understaffed work for hire company, we didn’t have a lot of time to get things done. My turnaround on most tasks was 1-2 days…not months. But at least there was light at the end of the tunnel as great progress was finally shown after all of it.

And as soon as I test my working prototype, literally minutes after I see the new assets in the game, before I can tell anyone…I am called into a meeting. “Microsoft is pulling the contract.” Well, at least I worked out the flow to get new assets in to hand over to them. “Oh, I’ll just shelve the prototype I got working and write up a little more documentation to…” I was cut off. “You are on another project as of now. We aren’t giving them anything we haven’t already.”

Well then. One would hope we could have spent a little bit of time out of professional courtesy, but I suppose not. They had 95% of the work already, so I’m sure it didn’t take them too long to figure out the rest.