Open Game Source: Battalion

by Dennis Payne

Name: Battalion
Version: 1.4b
Authors: Andy Johnson
License: Free, but with a couple of restrictions
Operating System: Several Unixes, Macintosh and Windows


"Monsters, explosions, senseless destruction. You've seen the movies, you know what to do." (Battalion web site)

Giant monster movies come alive in the virtual world of Battalion. The player takes control of a rampaging monster destroying a city. As the devastation mounts, the military launches numerous attacks against the beast. Eventually even the ferocious Googelon falters under the combined attacks.

Versioning and Patches

As noted above the Battalion version used for this article is listed as 1.4b, but the web site lists 1.5 for the Macintosh and 1.5beta2 for Windows. The site isn't clear about the differences between all the various versions. The source for any of the 1.5 versions doesn't appear to be available. A slightly reorganized web site would be beneficial. Ideally, the web site should have a changelog and a single source package of the latest version. If possible all binaries should be compiled from the original source package. I grabbed both the original 1.4 source and the Linux 1.4 version. The source for 1.5 is apparently available by request and simply hasn't been put on the web site yet. The only changes were for the Mac version.

Since I recently upgraded to a 3dfx video card, I downloaded the 3dfx patch as well. I had a shaky start with a beta Mesa version, but everything seems alright under Mesa 3.2. There is a problem with using a 3dfx card though. The monster movement can be controlled by the mouse or keyboard. For the mouse movement, if the pointer is above the center of the screen, the monster moves forward. Backward movement is caused by moving the pointer below the screen center. Being to the right or left of the center turns in the appropriate direction. Unfortunately the full screen mode of Mesa for 3dfx does not draw the mouse pointer.

I initially intended to look into this issue and discuss some of the challenges in designing a 3D game. Perhaps even add an option for drawing the pointer to solve the 3dfx problem. The Muses had a different plan in mind, however.

Sound Advice

For a long time I've derided sound in computer games. But there is a noticeably missing quality when playing a game without sound and music. A small sample of the theme music can quickly spark memories of old adventures. Even the simple beeps and gleeps of yesterday adds to the atmosphere.

The Linux version of Battalion uses the SoundIt library 0.03 by Brad Pitzel for sound support. The SoundIt library was apparently modified slightly by Sash Chukov when he added sound support to Battalion. The library only supports mono 8-bit samples, but for the simple sound effects and music of Battalion it works. In order to mix and play sounds simultaneously, the library spawns a separate process, a technique criticized on the LGDC mailing list.

There are several reasons for the criticism. The simplest to understand is that interprocess communications isn't instantaneous and may lead to some delay between firing a rocket and hearing the whoosh. Instead it has been suggested that a ProcessSound function be called in heavily trafficated areas of code. I figured implementing such a system for Battalion would make an interesting patch. Rather than reimplement a low-level library, I downloaded the latest version of SDL and SDL_mixer.

Since I hadn't heard complaints about the various Loki ports, I expected to find the technique suggested on the LGDC mailing list. Surprisingly SDL uses a multi-threaded approach, where a separate thread handles sound not an entire process. Using a thread reduces or eliminates some of the problems of a separate process but remains suboptimal on a uniprocessor machine.

So why bother implementing it? SDL works on numerous platforms. Using SDL many of the ifdefs in audio.c could be eliminated. Currently Battalion uses different audio formats, depending on the system. Since SDL can read wav files on any system there is no need to maintain raw files for Linux, au files for Solaris, etc.

Sound Architecture

Following good design principles, the sound interface is relatively simple and avoids revealing hardware implementation to the programmer. However, there is one minor kink in the system. When the program initially starts initSounds clears all the global variables relating to sound. Later, checkSound determines if the system has sound and loads the audio files if needed. Since nothing uses the sound variables between initialization and checking for sound, there is no reason to separate the two functions. In addition even before calling the initSounds function, the global noSound variable is set to false and functions to turn off the sound and music are executed. The possible incorrect setting of noSound is not modified until checkSound is called. Overall the sound initialization seem illogical and awkward.

Luckily the rest of the major audio functions are more straightforward. During the main game loop, flushSounds updates information about the currently playing sounds. At various other points the program may call doSound or soundKiller. The former starts playing the appropriate sound file. The latter stops playing a sound.

There are two other functions to be aware of when creating a new sound implementation, InitAudio and OutAudio. During sound initialization you have two steps: hardware initialization and the loading of sound files. Reading and processing each audio file requires the same steps so InitAudio packages it all up. The other function is called by doSound to actually play the sound. In theory the bookkeeping performed by doSound could then be system independent. In practice the bookkeeping didn't match up too well.

Coding the SDL implementation was relatively simple. I mainly copied the Linux SoundIt implementation and modified the functions to use the SDL_mixer equivalent. The only exception being soundKiller which does nothing in the Linux SoundIt version. Instead the type of sound playing on each channel is recorded when the sound is started. That way the appropriate channels can be halted. Since the sound may have completed, the halt may be unnecessary but may be more efficient than ensuring the playing channel information is correct. In addition to the patch, you will need the wav files from the windows binaries to use the SDL implementation.

Unfortunately I did end up referring to the source code of the SDL_mixer library during the porting. As this is my first attempt at sound programming, I was confused by the usage of the term "channel." When initializing the mixer library, one the arguments is the number of channels. One channel means mono sound and two allows stereo output. When you want to play a sound, once again channel is an argument. Channel in this case refers to the mixing channels which default to eight and are entirely separate from the audio channels. Since SDL_mixer currently lacks documentation, the only choice for new users is the source.

Remaining Can of Worms

So how is the rest of the source code? The majority of the source is found in a small number of files. Most files define numerous global variables. There are plenty of comments explaining the various sections so it is fairly easy to understand what is going on. Unfortunately battalion.c seems to have a rather haphazard placement of functions which makes finding a particular function more difficult.

While exploring the source to Battalion, I was surprised to find the monster models hard coded in the source. My initial thought was that this may have been done to simplify animation. However, Andy Johnson informed me that the restriction was due to the hardware limitations of 1995 low-end SGIs. Much of the code is still influenced by this legacy. Updating the code would be a large undertaking but would lead to much more flexible game.

Back to OGS

Copyright (c) 2000 Dennis Payne / Identical Software