Category: Games

  • Ludum Linguarum: Aurora

    (Ludum Linguarum is an open source project that I recently started, and whose creation I’ve been documenting in a series of posts. Its purpose is to let you pull localized content from games, and make flash cards for learning another language. It can be found on GitHub.)

    In this post, I’ll talk a little bit about Ludum Linguarum’s support for some of the Aurora-engine based games that are out there. The Aurora engine was Bioware’s evolution of its earlier Infinity Engine, and was used in quite a few games overall.

    Motivation

    There are quite a few games with large amounts of text that were produced with the Aurora engine (including one that I worked on), so it seems quite natural to try and target it for extraction. The text in these games can also be categorized in some ways that I think are interesting, in the context of language learning – there are really short snippets or words (item names, spell names, skill names, etc.), as well as really lengthy bits of dialogue that might be good translation exercises. Additionally, there’s quite a bit of official and unofficial documentation out there around its file formats.

    Goals for Extraction

    The raw strings for the game are (mostly) located inside the talk table files. However, just extracting the talk tables would lose all context around how the strings are actually used in the game. For example, the spell names, feat names, creature names, dialogues, and so on, are all jumbled together in the talk table. It sounds like a small thing, but I feel that creating a taxonomy (in the form of “lessons”) would make a big difference in the usefulness of the end product. Unfortunately, it also makes a huge difference in the amount of effort needed to extract all of this data!

    How it all went

    I spent quite a bit of time writing file-format-specific code, for things like the TLK table format, the BIF and KEY packed resource formats, the ERF archive format, and the generic GFF format. On top of that, then there was code to deal with the dialogue format that gets serialized into a GFF.

    I started with the original Neverwinter Nights, and then moved on to Jade Empire. The console-based Aurora engine games used some variant file formats (binary 2DAs, RIM files, etc.) that needed a little extra work to deal with, but there was enough information about these available on the Internet that I was able to support them without too much hassle.

    Once I had the basic file parsing code in place, it was just a matter of constructing the “recipe” of how to extract the game strings. This mostly involved sifting through all of the 2DA files for each game, looking for columns that represented “string refs” (i.e. keys into the talk table database) – extracting dialogues was much simpler since they were already in their own files, and their contents were unambiguous.

    Comparison between C# and F# implementations

    I had basically written all of this file parsing code before (in the C# 2.0 era, so without LINQ), but this time around I was writing it with F#. I found it very interesting to compare the process of writing the new implementation, with what I remember from working on Neverwinter Nights 2 more than 10 years ago.

    The F# code is a lot more concise – I would estimate on the order of 5-7x. It isn’t quite an apples-to-apples comparison with what I did earlier (for example, serialization is not supported, only deserializataion), but it’s still much, much smaller. I suspect that adding serialization support wouldn’t be a huge amount of additional code, for what it’s worth.

    Record types and list comprehensions really help condense a lot of the boilerplate code involved in supporting a new file format, and match expressions are both more compact, and safer when dealing with enumerated types and other sets of conditional expressions. I also got lots of good usage out of Option types, particularly within the 2DA handling, where it very neatly encapsulated default cell functionality.

    But I think the thing that accounts for the biggest difference between my old C# implementation and the new F# implementation, is the range of functional abstract data types available – or, to put it another way, the lack of LINQ in my C# implementation. If LINQ were available at the time I was working on Neverwinter Nights 2, I think my code would have looked a lot more like the F# version, with liberal use of Select()/map() and Where()/filter(). These operations replace very verbose blocks of object construction and selective copying, often in a single line, which is an enormous savings in code size and improvement in clarity.

    I feel like there is still a lot of bespoke logic involved, for extracting the individual bits and pieces of each format, but that doesn’t seem to be avoidable – the formats are not self-describing, and it seemed like it would be overkill to try and construct a meta-definition of the GFF-based formats.

    Summary

    Overall, I was pretty pleased with how this went. While it was a decent amount of work to support each file format, once that code was all written, the process of creating the game-specific recipe to extract strings was pretty straightforward. There weren’t really any surprises in the implementation process, which was definitely not the case for the game that I’ll talk about in my next set of posts.

  • Ludum Linguarum: The Simple Stuff

    (Ludum Linguarum is an open source project that I recently started, and whose creation I’ve been documenting in a series of posts. Its purpose is to let you pull localized content from games, and make flash cards for learning another language. It can be found on GitHub.)

    When I started this project, I figured that support for individual games would fall into one of a small set of categories:

    • Low effort, where the strings are either in a simple text file or some sort of well-structured file format like XML, where many good tools already exist to pull it apart.
    • Cases where the file formats, while bespoke, are well documented, and where there may be tools and code that already exist to parse the file formats.
    • The really hard cases – ones where there isn’t a lot of (or any) extant information about how the game stores its resources, and extracting strings and metadata about them is more of a reverse-engineering exercise than anything else.

    In this post, I’ll talk very quickly about a few really simple examples of games that I was able to knock out very quickly: King of Fighters ‘98, King of Fighters 2002, Magical Drop V, and Skulls of the Shogun.

    King of Fighters ‘98 and King of Fighters 2002

    While I was working on this project, I started on some of the other supported games first. But then, I decided to take a little break, and see if there were any games out there that would be really trivial to support. I just started browsing through my Steam library, and realized that fighting games were probably a good candidate – they contain limited amounts of text, but were definitely globalized.

    Both of these games use the Xbox 360 XDK’s XUI library formats to present their UI. (I determined this by the presence of some files and directories with “xui” in their name.) All of the strings in the game are inside a file conveniently named strings.txt inside the data directory.

    This is a tab-delimited format with just four columns – a key for the string, a “category” comment field, and then columns for each supported language – “en” for English, and “jp” for Japan. (It’s interesting that the country code rather than the language code was used for Japan – I’m not sure if that was an unintentional mistake.)

    In this case, it’s super simple to extract all of the strings, because of the simple formatting, and the one place that I need to look to find them all. I simply read in the file, and directly map the key column to the per-language text for each card.

    (It’s worth noting that King of Fighters XIII doesn’t use the same format or engine, so I wasn’t able to just add support for it using the same code.)

    Magical Drop V

    Adding support for Magical Drop V just involved reading some XML files within its localization subdirectory, and massaging them slightly to remove invalid and undesirable text. For example, ampersands were not escaped in the XML files, which caused the .NET framework’s XML parser to complain. I also stripped out some obvious placeholder values (“<string placeholder>”).

    Overall, it was really quite simple to add support for this game, with the game-specific code only running to about 50 lines.

    Skulls of the Shogun

    Skulls of the Shogun is a game built on XNA and MonoGame, and actually uses the .NET framework’s globalization support to localize its strings. Thus, I was able to use the framework’s support for loading satellite assemblies to pull out both the string keys used to refer to the strings, as well as the content itself, quite easily.

    I actually spent more time determining that I had to load the assemblies using the reflection-only context, in order to keep my library and console application bit-length-independent, than writing the rest of the code to support this game!

  • Ludum Linguarum: The Tools

    (Ludum Linguarum is an open source project that I recently started, and whose creation I’ve been documenting in a series of posts. Its purpose is to let you pull localized content from games, and make flash cards for learning another language. It can be found on GitHub.)

    When I started working on Ludum Linguarum, I decided to use it as an opportunity to exercise what I had been learning about the F# language on the side. This might seem like kind of a strange decision out of context, but there were a few reasons why I felt that this made sense:

    • I already had a good bit of familiarity with the .NET stack, having spent a good chunk of my years in the gaming industry writing tools in C#.
    • Because of the frequent use of C# in games and editors, I felt that there would be a greater likelihood of me finding useful, easy-to-integrate libraries and documentation for reverse engineering games than on other stacks.
    • I write Scala at my day job, so I figured that I would be reasonably well-equipped to deal with the functional programming aspects of the language, even if I had never really touched Ocaml before.

    At the very beginning of the project, I was working on learning F# on my commute, using Mono and MonoDevelop on an old netbook that I threw Ubuntu on. This worked (in that it is totally possible and viable to write F# and .NET code on non-Windows platforms), but later on I got a proper new laptop, threw Visual Studio 2015 on it, and never looked back. The added benefit of doing this, of course, was that, running under Windows, I could easily install and run the games that I was reverse engineering.

    The benefits

    All in all, I have been very pleased with my decision to use F#. Using a functional-first language let me construct composable, easily-testable pipelines, and I feel this really saved me a bunch of time as the project grew. The language is very similar in capabilities to Scala for application code, albeit with significantly different syntax and a slight verbosity tax.

    When I think back to similar code I’ve written in the past, I feel that my F# code is more concise, easier to understand, and with less room for bugs to creep in, compared to C++ and C#. This applies both for simple parts of the code, as well as much more complex parts. In a future post, I’ll go into this in some more detail.

    I would go so far as to say that the things that slowed me down the most were when I strayed furthest from the functional style, and just used the full console application and the full game data as my testbed. (The reason I did this is that it can be a bit of a pain to construct test data that is compact, concise, and doesn’t include any actual copyrighted material.) As long as I wasn’t too eager, moved at a reasonable pace, and built up a decent test corpus, things worked out well.

    Project setup

    Initially, I used the standard .fsproj and solution setup in VS. The project was set up as a plugin-based system, where all main build outputs were copied into a single output directory, and NUnit test projects were simply run in-place. This worked OK, but as I got closer to actually releasing the first version of the project, I decided that it would be better to migrate the project to the FAKE build system and Paket dependency manager. (Using those makes it simpler to keep dependencies up-to-date, and hopefully easier for the curious or motivated to build and run the project.)

    I used the open source F# Project Scaffold, and reconstructed my old project setup. It took a little bit of experimentation, but I was able to get up and running pretty quickly. I did run into an issue where the recently-released NUnit 3 isn’t supported by FAKE, and I did have to do some legwork to get everything building with F# 4 and .NET framework 4.6.1, but it wasn’t too bad. Now I have a very simple system to build, test, and package the project for release.

    The latter is particularly important – I don’t have a lot of extra time to spend on overhead like manually making builds and uploading them, so it’s much easier for me to change the way I work, and change my project to conform to some existing conventions. One example of this is that the console program used to have no project dependencies on its plugins – they were copied as a post-build step into a separate plugins directory in the build output. This was done out of a bit of a purist mindset (and was what I had done on some other projects in the past) – but when I migrated to FAKE, this presented some problems, as it was difficult to duplicate this exact behavior. The solution was to simply abandon purity, adjust the way that I did things, and just add project dependencies to the console application against the plugins. Realistically speaking, anyone developing a plugin is probably going to have the full source handy anyway, so why get hung up on this?

    Other libraries

    So far, I’ve pulled in just a few other libraries. One is sqlite-net, a SQLite wrapper, and another is CommandLineParser, to allow me to construct verb-driven command line handling in the console application. I spent a little while wrestling with both, but now I have a couple of wrappers and things generally set up in a way that works well. (I actually switched back and forth between the old version of CommandLineParser and the new beta one, and wound up sticking with the new beta as it fixed at least one annoying crash relating to help text rendering when using verbs.) I also wound up adding the venerable SharpZipLib library for zip archive support.

    Summary

    In summary, I’m glad that I have a setup now, using FAKE and Paket via the F# project scaffold, which is good for rapid development in Visual Studio, has good testing support, and one-line release packaging and deployment. There were a few bumps along the way in arriving at this setup, but I can wholeheartedly recommend it to anyone working in this ecosystem.

  • Introducing Ludum Linguarum

    I’ve been working on a side project for some time now, and it’s gotten far enough along that it’s worth releasing it, and discussing it. It’s called Ludum Linguarum (LL) – a little awkward, yeah, but I figured that a unique name would be better in this case than spending a lot of time trying to find an available-yet-expressive one.

    What does it do?

    Well, it’s intended to be a tool for extracting localized resources from games, and then converting them into language learning resources. In other words, the end goal is that you can turn your Steam library (full of games that you bought for $0.99 in some random bundle) into material to help you learn another language.

    The current version pulls strings from games, and turns them into flash cards for use with Anki (and compatible apps). LL supports 21 games right now, and the goal is to expand that over time.

    Why write something like this?

    Well, it involves two things that have always interested me (games and languages), and as far as I know, nothing else like this exists! (subs2srs is a tool in a similar vein, but it generates flash cards from subtitled videos instead.) I figure you might be able to get a little extra motivation and drive by learning another language in the context of gaming.

    Another reason is that the vocabulary of games is often well off the beaten path of most language courses – I don’t think that Rosetta Stone or even Duolingo is going to tell you that “magic missile” is Zauberfaust in German. There aren’t that many opportunities to learn this stuff otherwise – think of it like professional vocabulary, but for a really weird job.

    I also find cultural differences interesting, and that includes the way that game content gets translated. Seeing how colloquialisms and “realistic” conversation get translated is really interesting to me – I get a huge kick out of learning that platt wie Flundern is how someone chose to translate “flat as a pancake.”

    Finally, game content in itself is an interesting treasure trove where you can often see the remnants of things that were tried and abandoned, or cut in order to get the product to the finish line. And naturally, some of the most common types of remnants are text and audio.

    Next Posts

    I’m going to spend the next few posts talking about the development of Ludum Linguarum, and writing the code to extract strings out of the first few games it supports. There were quite a few interesting problems that came up while getting to this point, and a few interesting tidbits and trivia that I can share about some of the supported games.

  • Analysis of Yakuza 5 Hack Videos

    I happen to be pretty hyped over the upcoming US release of Yakuza 5 — I’m a big fan of the series’ odd mix of ridiculous melodrama, wide variety of activities and minigames, and really satisfying combat. So naturally, after the localization was announced, I went around looking for videos of the game to watch. First off, I found this amazingly comprehensive and lovingly-assembled survey of the whole series — it’s not really related to the rest of this post, but if you’ve never seen these games it’s worth watching to get a glimpse of how unique they are, and what’s so appealing about them to me.

    Then, I found some videos of some hacks that someone apparently made to the game, to allow the player to play as Haruka and another female character (Mai — no idea what her place in the story is). During the normal story arc, there is a chapter where you play as Haruka — however, her fights are rhythm games and dance battles, not the sort of bare-knuckle brawls for which the series is famous. This hack instead allows you to play as these characters during other chapters of the game, where you engage in tons and tons of fistfights. And, somewhat surprisingly, if you watch the videos, it looks pretty good!

    So, putting on my ex-game developer hat, what do these videos tell us about the way the game is built, and why this was possible? And is adding a new playable character to the game as simple as these videos make it seem? Here are some of my observations and speculation on how this works, and its limitations.

    • The female and male characters must be animated using the same skeleton. Basically, because all of the combat animations that these characters are using are the same ones that the standard playable characters use, Haruka and Mai must be built and animated on the same basic skeletons as Kiryu, Saejima, Akiyama, and Shinada. This is a little surprising to me, but it goes a long way to explaining why the female characters in this series always seem to…uh, have a somewhat mannish feel to them. I’m guessing that, for the original PS2 games, that this was done to save memory, and then brought forward because it worked well enough and making unique skeletons would require duplicating an already-large animation set.
    • Haruka and Mai are missing a lot of animation metadata. The most obvious case is when Haruka goes to light up a relaxing cigarette after beating the tar out of countless schlubs, just like uncle Kiryu.
    • The smoke from the cigarette comes out of Haruka’s chest — or, more accurately, the origin (0, 0, 0) of the character. There’s a missing animation attachment point in Haruka’s metadata, and the game engine falls back to the origin. Interestingly, Mai seems to have this attachment point — the smoke appears in the correct place for her.

      Another example of missing metadata is this HEAT attack with a bowling ball — it pops away from Haruka’s hand and looks like it’s stuck on her nose. And if you freeze-frame a similar HEAT attack with a beer bottle, you can see that the bottle looks like it’s stuck on her lips.

      I believe there are also missing camera focus points — for example, at the end of this HEAT move, the camera seems to be focused on the origin point of Haruka, and her face is off camera. If I remember correctly, this move looks different when performed by one of the other player characters — the camera tracks the head and it’s in the frame.

    • They’re also missing a lot of animations. The easiest case to spot is that Haruka and Mai’s faces remain completely expressionless, and possibly unblinking, during fights — they don’t have any combat “barks” (voice + facial animation), and they don’t play any reaction or pain facial animations as they lay waste to their foes. While it kind of lends a comic tone to the video, this would definitely not be acceptable for an officially supported character. It just looks strange.
    • The game’s IK seems to work OK with these characters. I had kind of assumed that the engine supported IK, given that a lot of the close combat grabs in the game look pretty good. When Haruka grabs a thug by the hand, that’s a pretty strong signal to me that they’re doing some limited IK, because if they weren’t, you would probably see a gap in the throw animation as Haruka’s character is physically smaller than, say, Kiryu’s. Another example of this is Mai kicking the sign stuck on a thug’s head — it’s just too unlikely that it would look good without IK support.

      Note that there are still some cases where it looks like they don’t normally use IK, and just rely on the animations fitting the sizes of the characters — Haruka lifting up a thug looks pretty bad, as her hand is nowhere near the thug’s chest.

    • Haruka and Mai’s hair is not built to be animated during combat. In the case of Mai, her hair basically doesn’t move at all. And Haruka’s hair physics object was clearly conditioned to look good during movement animations, but not tuned at all for anything that would look like combat, with its frequent flips, tumbles, falls, and dashes. It’s all over the place constantly.
    • Both characters seem to be using Akiyama’s move set. But I can’t tell if this is just a convenience, a deliberate stylistic choice on the part of the author, or that none of the others would work. I think it would be kind of funny to see them using Saejima’s brawling moves, though.
    • Surprisingly, there was no content protection on the game assets. Presumably the author of these videos was able to simply pull out the PS3 HDD, and modify the files directly on the hard drive to point a character definition to Haruka or Mai’s models. It’s a little surprising to me that these were left unprotected, but perhaps Japan has less societal anxiety about hot coffee than the US. Maybe I should have a look at the installed data, to see if I can verify any of my conjecture here.

    In closing, I think these are really neat, fun videos to watch, and that it would be very cool if female characters in future Yakuza installments were able to fight and brawl. But there are enough rough edges and missing content in this hack, that it should be clear that making them fully playable is not just a matter of flipping a switch (or deciding to change the story) and suddenly having Haruka powerbombing fools alongside her uncle Kiryu. There’s a lot of missing content and additional polish that would need to go into making Haruka and Mai fully first-class fighting characters in the game.

    Questions or comments on my analysis are welcome!

  • Thoughts on Persona 4 Golden

    So I recently got done burning a huge chunk of time finishing Persona 4 GoldenPersona 4 Golden on the Vita (with the “true ending”). I never played Persona 4 when it was originally released, so I figured that it would be a good game to pick up for the Vita. Overall, it’s a stellar example of “better than the sum of its parts.” There’s a lot to like, but I can also level a lot of critiques at the game.

    The good

    • The story is fairly compelling. That is, for a game, it’s pretty good. It is full of well-worn character stereotypes, along with two bonus dungeons that really feel tacked on to this re-release, but the main story arc is satisfying enough. (Even if the resolution of the main story is telegraphed well in advance.) I guess the best way to describe it would be that it’s like a really, really long after school special.
    • There is a pretty solid set of interactions between the two parts of the game. The “high school time management” stuff has consequences for your equipment and powers in the dungeon crawling part of the game, and you’re motivated to do well in both parts of the game.
    • The translation and voice acting are really quite good. Humor and nuance are carried through into English, and given the amount of text in the game, this is no small feat. The dialogue fits the characters, and fits the mood of the game very well.
    • There is a ton of stuff to unlock and/or complete. You don’t need to do much of it to complete the game, but it’s enjoyable enough that you’ll be motivated to do a lot.

    The not-so-good

    • The dungeon crawling becomes incredibly tedious as the game goes on. The dungeons are nearly all just tile swaps of each other, with few gimmicks or notable differences between them except the level and type of monsters you fight. Boring…
    • The bestiary of enemies you fight is truly insane, and really feels like a huge disconnect from the story and theme. And, what’s worse is that nobody ever really comments on it! When a reanimated table is trying to kill you, you think somebody might find it at least a little funny. I realize that these enemies get carried over between games in the series, but it just seems completely out of whack. And none of the “themed” areas of the game have themed enemies, which seems like a missed opportunity.
    • The combat system gets quite boring after a while — there aren’t enough twists and sub-systems to sustain 50+ hours of gameplay. The combat basically boils down to: 1) determine elemental weaknesses, 2) spam elemental attacks of that type, 3) perform all-out-attacks, 4) rinse and repeat. It feels like they even removed a little bit of complexity from P3 since I don’t think any creatures in P4 are resilient to all-out-attacks. None of the boss fights really change things up, either — the only variation is that you might need to heal or remove ailments at some point. There are no cases where the standard battle rules are subverted, or you are forced to use unusual aspects of the battle system — there are only a couple of “trick” encounters, and you don’t even need to recognize the trick to prevail.
    • Along similar lines, there’s no real incentive or reason to mix up your party — the main character can fill in pretty much any missing powers via judicious use of Personas. I used Yosuke, Chie, and Yukiko for basically the entire game, because they were the highest level characters I had.
    • There’s a decent amount of creepitude (Teddie is the #1 offender) and/or blatant fan-service, which just makes me roll my eyes. A lot of the movies in the game fit this description, actually.
    • The social link system of the game is broad, but very limited. There aren’t really any meaningful decisions to be made when advancing someone’s social link, and once you complete it, there’s no meaningful interactivity or payoff beyond the dungeon crawling benefits (persona unlocks, battle abilities, etc.). You can’t pick between character development trees, or unlock mutually exclusive abilities, or anything like that. There was some attempt in the re-release to give some flexibility as far as respec’ing yourself and your allies, but it’s not enough (and it takes too long to do so in-game — you have to burn up a chunk of time every time you want to either get the card for a power, or respec one of your allies’ powers).
    • You are also really incentivized to be a giant man-whore, in order to unlock all of the battle benefits for each party member. (There are, I think, two points in the game where man-whoring behavior is pointed out, but there are absolutely no consequences.) All of the benefits, like follow-up attacks, ability to withstand mortal wounds, ability to take fatal damage for the main character, and especially all of Rise’s party-wide boosts are ridiculously powerful, and it would be foolish not to unlock everything that you can.
    • There are some story bits that are just kind of dropped on the floor, and left unexplored. The presence of Junes in Inaba, the fate of certain characters, Dojima’s story arc, and some of the “school life” stuff is left unresolved or ignored in the last third of the game. This is kind of disappointing, because I feel that the plot or story could be even more engaging with just a bit more effort.

    In spite of all of the negativity above, I really enjoyed playing the game. I just think that with some extra polish it could move from “pretty great niche JRPG” to “amazing game that could be recommended to any gamer.” I suppose there’s always next time.

    I’m totally done with P4G now, though. The thought of “New Game+” after playing for dozens of hours already is pretty scary…

  • My Reflections on Apple

    I’m pretty sure this will be one of a million “stories about Apple” that will be going up tonight, prompted by the death today of one of its founders, Steve Jobs. Like many of my peers, the Apple IIe was one of the first computers I ever used, and one that I spent a huge amount of time with in my childhood — mostly playing games, of course, but also some programming and doing other practical things. The Macintosh that my dad later bought, in turn, also saw a lot of usage by me, although curiously my use of it was tilted more towards the practical and less games and programming. (Games because they simply didn’t exist, for the most part, on the Mac. And programming environments were pretty rudimentary for awhile — the development situation on the Mac at the time was definitely not friendly towards, or accessible by, 9-year-old kids.)

    Of those two platforms, I would say that their influences were quite different on me. The incredible breadth and depth of games available on the Apple II platform really fanned the flames of my interest in gaming, which I would later go into as a professional career. The Mac, apart from the obvious innovations in user interfaces, introduced me to concepts like hard drives, laser printing (via PostScript), local area networking, WYSIWYG, and desktop publishing (an innovation that has become so ubiquitous that the term isn’t even used any more).

    As a game developer, and someone who did some development on pre-OS X Macs, I wound up bearing a bit of a grudge against Apple. Their development environment, lacking protected memory, was incredibly unforgiving in many ways, and killed productivity. And Apple’s haphazard, ramshackle attempts at courting game developers were for the most part insulting, incomplete, and lacked support. I generally stayed away from purchasing Apple products and MacOS for a long time, ending only recently in the iPhone (which is a pretty decent phone).

    So, in total, Apple is a company whose products have been incredibly influential not only in the world at large, but to me personally. And when one of its founders kicks the can, I feel obligated to eulogize just a little bit. In parting, I’ll relate an Apple II gaming anecdote that I haven’t written about before:

    When we were kids, my brother and I used to love playing a game called Micro League Baseball, on our Apple IIe. It was a baseball simulation game, with somewhat rudimentary graphics, but a wide roster of teams, and the ability to play head-to-head. The multi-player mode was hot-seat — for each pitch, the player whose team was batting would select an option, and then the player whose team was in the field would select an option. Since the options could include baseball trickery like stealing a base, or pitching out, the person who was not entering their option would look away from the screen and keyboard and cover their eyes. This was to prevent the gaming equivalent of stealing signs.

    Our rivalry was quite intense, and it was quite a big deal to us to triumph in these games. (We didn’t really consider the relative strengths of teams we were using, apart from the ’27 Yankees being mega-powerful.) So I wound up doing something that was both smart and dumb. The smart part: I realized that the hollow case and keyboard design of the Apple IIe was such that key presses had distinct timbres to them — ones that could be distinguished quite easily, with a little practice. I quickly learned that I could steal signs and know exactly what my brother was doing, even though my hands were covering my eyes in adherence to the “rules.” If he pressed ‘3’ to steal a base, or ‘4’ to hit-and-run, I would know about it in advance. The key noises were so distinct that there was basically zero chance of making a mistake.

    The dumb part: I took too frequent advantage of this, and he got suspicious after about the sixth time that I called for a pitchout and happened to catch him stealing bases. I had to ‘fess up to my little trick.

    I can’t remember if covering our ears, too, became part of playing the game, or if the other person had to leave the room, to ensure fairness and a level playing field.

  • Memory Card Bugs (and a note about static analysis)

    I was watching John Carmack’s QuakeCon 2011 keynote, and he mentioned that Rage was currently in the stage where they are creating cert builds, and just fixing bugs like (paraphrased) “getting a multiplayer invite and pulling your memory card out.” Memory card bugs are one of those things that tend to be a big annoyance for game programmers, because of the number of asynchronous use cases that need to be handled and the need to tie what are essentially supposed to be serial operations to a game that may be doing many other things in parallel. (Memory card support was optional on the original Xbox, due to the guaranteed presence of the internal hard drive. Accordingly, hardly any games actually support managing memory cards directly in-game.)

    Carmack’s mention of memory card bugs reminded me of a funny story from Obsidian. For the Onyx Engine, one of my coworkers was working on writing the save/load code and then fixing bugs in the system, including memory card bugs on Xbox 360. Many of these bugs were timing-specific, so he would remove and reinsert his test memory card to try and reproduce the bug. Eventually, though, the first memory card slot on his development kit broke from the repeated (and potentially forceful, because of the need to try and reproduce specific timings) insertions and removals of the memory card. He had to switch over to the second slot on the kit — which, thankfully, survived until the project was over.

    Another thing that came up in Carmack’s keynote is the use of static code analysis. He mentioned that id have drunk the proverbial Kool-Aid as far as static code analysis goes, and mentioned that turning on the “/analyze” switch for Xbox 360 builds (a flag that the XDK compiler supports — normally I think you need the Ultimate version of Visual Studio) brought to light many issues with their codebase. I can also vouch for this — I used to do this semi-regularly at Obsidian, and every time I ran it there were several subtle bugs that were sniffed out. It’s really worth using if you have it available.

  • Fallout: New Vegas has gone gold

    Here’s the official announcement on the Bethesda blog, along with pictures of an awesome Fallout: New Vegas themed cake that one of the designers at Obsidian got for his birthday.

    I pitched in for a couple of months prior to certification to help get it ready for ship. I hope everyone enjoys playing it once it’s out!

  • The Xbox (1) Live Shutdown and Secret Weapons Over Normandy

    A few months ago, Microsoft announced that it would be shutting down the Xbox Live service for the original Xbox on April 15, 2010. I haven’t played an Xbox 1 Live game in years, but this news still makes me a little wistful, because for the first time something that I’ve worked on will essentially no longer be available anywhere. I’m referring to the downloadable content for Secret Weapons Over Normandy – there were three packs, each containing a challenge mission and a new plane. According to this list, there were only 53 games on the original Xbox that even had DLC, and ours was in the earliest 20% or so of that. (Wikipedia doesn’t have a dated list for downloadable content, so I’m merely going by release date of the original game, which may not be accurate – I seem to recall that the Yavin Station DLC for KOTOR only came out after the PC version shipped, which was many months after the Xbox version.) I remember at the time that it was still a novelty for a game to support DLC – I think the only game up until that point for which I personally had downloaded DLC was MechAssault.

    At that point, publishers and developers hadn’t really figured out their DLC strategies yet – they tended to come out at odd, uncoordinated times, and since you couldn’t bill users for it, there wasn’t a direct financial motivation for producing it. (I’m guessing Microsoft probably paid LucasArts for the DLC, but I have no real knowledge about this.) In hindsight, it seems a little quaint to produce DLC for a game without Xbox Live multiplayer like SWON when there was no ability to monetize it. Then again, the time investment in producing the DLC was pretty modest – creating and setting up a new plane was a fairly simple process, and we had an awesome mission editor, SLED, that really made it fast and efficient to create new missions. Comparing that process to content generation on current-gen games makes my head spin, to be honest.

    The DLC was pretty much ready to go from the launch date – we had spent less time in certification and re-submission than we had planned, and so the DLC content was started and finished sooner than expected. I also seem to recall some feedback from Microsoft that our DLC was the first that had passed cert the first time through – I’m not 100% sure if I’m remembering that right and that we were the first, but passing on the first submission was definitely something that they highlighted and was a nice feather in our cap. Our engine design and the relatively self-contained nature of the DLC definitely helped with that. (Certification in general was actually a breeze on that game – we passed SCEA cert on our first submission, and I think we only had minor fixes for SCEE and for MS. The project schedule was built around the assumption of two resubmissions for each platform/region.) I think the DLC came out one pack at a time, a couple of weeks apart from each other, and all of the game content was out by early-to-mid December 2003.

    My involvement in the DLC was pretty peripheral – I just played it a few times and gave a little feedback. At the time, I think I was working on the Japanese localization of the game (for PC and PS2), which needed some additional code and tool work. That version, incidentally, is the “final” version of the game – there were a couple of tiny bug fixes I made that missed the US and European releases, and of course none of the Japanese text and font rendering stuff was in the earlier releases.