The Format of Music

December 3rd, 2011

Note: You will need to have your speakers turned up to fully appreciate this entry.

I’m going to depart from the normal technical focus of my blog and talk about something more people can relate to: music.

That is, the format of music, as used in the context of computers. Most people can clearly see how enormous an influence technology has exerted on music in the last few decades. In the case of computers, there have been two main revolutions in the musical realm:

1) The ability to synthesize and create music by means not limited to the classical methods, performing and rehearsal.
2) The ability to script playback of digitized music in an automated fashion.

The first revolution came in the form of the synthesizer-loving 1980s, as well as in the various hardware and software that facilitated note-by-note recording and playback of wired instruments. The second revolution occurred at the roughly the same time, perhaps a bit later, in the form of video games, CD-ROM players, and MP3 players.

Both of these revolutions needed digital storage formats to keep track of the musical data. Without them, you’d have no way to “store” the music for playback beyond straight analog recordings.

The foremost and most well-known digital music format is Musical Instrument Data Interface, or MIDI. I originally created the 14 musical tracks of Cruz as MIDI files. A MIDI file stores notes and instruments as metadata–C key octave 4 note down, E key octave 3 note down, C key octave 4 note up, etc. The sequence of “command” and “data” bytes in a MIDI file, when interpreted by software and hardware, can be used to play back a composition that a musician is working with.

In this respect, MIDI has immeasurably helped in the composition process. The ability to listen to how your music sounds, when not being performed, is critical when deciding which music is good and which music still needs work.

Take the “Cruz Puzzle Theme” track’s music, composed in Anvil Studio. The metadata exists as command and data bytes, but it can be rendered on the computer screen as a musical staff customarily seen in sheet music:

Anvil Studio lets the composer add effects and notations to the staff. I didn’t in this case, because I was more concerned with how the music sounded than how it would look printed.

MIDI sequencers like Anvil Studio are invaluable assets to people like me–I absolutely need to hear the music while composing it to determine if I’m on the right path or not. This is very much unlike programming, where so much of a program must be written before compiling it to see if the entire thing works at once.

With only a few tweaks, a composer can move notes, change the tempo, change keys, change instruments, and make other changes that might have required countless hours if hand corrections were used on paper!

So MIDI is great. But it’s not enough.

Anyone who appreciates good musical performances knows that music, as performed, is a lot more nuanced than what simply appears on a staff. Many effects are instrument-specific, and the need for custom instruments is very important. MIDI locks the composer into a relatively limited number of instruments.

But it gets worse. Each MIDI playback device has its own wavetable “soundfont” for the instrument set! This means that the instruments for a MIDI song composed in one MIDI context might sound very different for some instruments when played back in a different MIDI context. If a composer works hard on making a song sound a certain way, he or she will not want to see it “ruined” by the wrong soundfont.

Compare the two songs, and tell if they sound the same:

Cruz Puzzle Theme – MP3
Cruz Puzzle Theme – MIDI

If the MIDI theme sounds different (and probably worse), it’s because the SoundMAX default soundfont is not the MIDI playback device on your computer. I converted the MIDI format to MP3, which is purely digital waveform, in order to head off the problem of inconsistent playback.

Which leads me to the next part of this topic: tracker software.

An early alternative to MIDI that allowed for direct wavetable configuration is MOD. The idea behind MOD, UMX, and other “tracker” formats is that both the note-by-note metadata and the wavetable samples used in playback are stored in the same file, resulting in consistent-sounding music regardless of playback device.

There are many brands of “tracker” software, but the idea behind them is essentially the same: you edit note metadata, applying effects, etc. This is much like Anvil Studio, although the editing display is often different from the “sheet music” view seen in Anvil Studio.

Above is a screenshot from FamiTracker, a utility that makes tracks compatible with the sound-generating capabilities from the 8-bit NES. I used it to make the “chiptune” variant of the Cruz Puzzle Theme. Have a listen:

Cruz Chiptune Puzzle Theme – MP3

The differences between MIDI and FamiTracker formats required some time to port over, but because I had already composed the original, it came together in only a single evening.

It certainly demonstrates the utility of FamiTracker to have allowed me to customize the note sampling periods. If you’re sharp, you noted from the Anvil Studio staff screenshot that I’ve hit you over the head with a very unusual feature in music: the 5/4 time signature!

The 5-count time signature is extremely rare. The vast majority of songs (and musicians, it would appear) never leave the comfortable realm of 4/4. But well-made software will accommodate nearly any “trick” the composer might have up his sleeve.

I made a 5-count song for two reasons: influence from Jesus Christ Superstar, which has 5-count and 7-count songs, and because I really wanted to challenge myself to make a quality 5-count song.

Of course, composing also requires audio editing, which is challenging no matter how difficult the source material was to create. This leads me to the final part of this topic: purely digital formats.

To represent digital waveform data, no matter what the source is (voice included), you must use a format like WAV or MP3. The WAV format contains lots (and I do mean lots) of individual sample points of the audio waveform for any one second of playback. For CD-quality audio, that’s 44,100 sample points per second!

Obviously, the large storage size required for waveform audio has created a need for compressed formats. The most common compression format is MP3, which sacrifices a bit of quality for reduced file size. There are a few others, such as OGG.

After music is composed, one must translate it to digital waveform data. But just one direct-translation operation is rarely adequate–filtering operations, volume control, fade-in and fade-out, making stereo tracks from mono, and a whole lot of other clipping, segueing, and tweaking operations must occur to make a song ready for use in the world of computing.

Several waveform-editing applications exist, such as Audacity. The screenshot below is of the waveform of the Cruz Puzzle Theme, as seen in Audacity.

In conclusion, I hope I haven’t blown anyone’s brains out. I’ve just summarized a huge topic, leaving out countless details, in the hopes of giving people a general idea of the “world” of musical composition that computer-minded composers live in.

The skill required to master all of these tools and formats? Hard to say. It definitely makes a difference how musically inclined you are in the first place, as well as how computer-savvy you already are.

Take me, for instance. I’ve used audio editing software for years, but I never composed anything (in Anvil Studio, OR FamiTracker, OR anything else) before 2011!

Only one thing is required for sure: you must love music.

Anatomy of a Web App

October 4th, 2011

Hello! Time to dissect the application I’ve mentioned several times already: Cruz.

Long before starting Cruz, I had built many, many software applications. Some used sophisticated requirements, design, and configuration management techniques. Others, not so much. This one falls into the “not so much” camp.

But Cruz, like many other applications I have built, has very sophisticated programming. With me, that’s just the way I do things. I take pride in my programming skills, and I will go the extra mile to develop to a high level the engine of any game I create.

Cruz is a Flash game. Many Flash games are rich in graphical and sound content, but they lack programming sophistication. Inability to program forces many designers to act at the mercy of whatever tools or engines others have built, which further limits the types of games they can create. Could a graphical designer who knows little about programming create something like Cruz? Well, read on, and see for yourself.

System Components

There are six main components of the Flash application:

  1. Flash file (Cruz.swf)
  2. Graphical content (embedded in Flash file in this case)
  3. Audio content (MP3s loaded at run time)
  4. Level design data (XML files in “Cruz” format)
  5. Server-side scripts and storage (PHP and text files)
  6. Client-side savegame, progress, and config info (Shared objects)

The Flash file is loaded first, usually as an embedded object in a web browser, with graphical content loaded automatically. The audio content is loaded in two contexts: the sound effects at the beginning (a preloader precedes the title screen), and the musical tracks on an as-needed basis.

The level design data is loaded on an as-needed basis per episode, which is only when the user starts a game for a particular episode. The server-side scripts are used when handling high score update and retrieval operations. The savegame, progress, and config info are periodically updated and saved by the Flash environment on the client side.

If you’re building a Flash application, there’s a good chance you won’t need to touch the XML API, or write server-side scripts, or use shared objects. You might not even need a preloader, choosing to embed everything in the SWF. This keeps everything simple, but it limits what you can do, programming-wise.

If you’re building a game designed to give the user a full experience of rich content, savegames, and high scores with competition from everyone in the world, the “web application” way to do it is substantially different from the “home PC” way to do it or the “game system” way to do it. Different APIs, different components, different implementations of components.

But the underlying programming effectively does the same stuff, no matter what the platform is. You have load operations, save operations, ins, outs, etc. Business logic is business logic in any language.

Classes and Programming

What about the programming for Cruz? Well, as managed applications go, there is little to the imagination. Let’s look at what Cruz implements for unique classes:

  • utils: Low-level utility functions, such as sign, absolute value, random chance, etc.
  • IPoint: Coordinate pair of integers (x and y).
  • Dir8: Eight-directional calculation functions and lookups; useful for 2-D gridded games.
  • FxCont: Field effect container class (a rectangular region with specific game properties).
  • objid: Enumerated constant and name lookup container for game object types.
  • fxid: Field effect and level feature lookups.
  • SF: Special flags-per-grid-cell storage and lookup.
  • SaveGame: Represents savegame data.
  • CruzOptions: Represents configurable options for the game.
  • Game_Characters: Storage and functionality for ASCII-noir characters used in background text.
  • RandInfoArray: Grid randomization functions.
  • CruzMedal: Storage and functionality for medals (unlockable achievements found in various parts of the game).
  • Sounds: Storage and functionality for sound effects and music.
  • PathCalc: Mouse click-to-move path calculation functions.
  • MsgParser: Special object message parsing class; used with tablets and special items.
  • GPlayer: The main character’s object (the player).
  • iobj: Individual game objects, capable of interaction. A single GPlayer individual is always present as the first individual.
  • rtobj: Real-time object, representing a short-lived, animated object in the game that does not interact with anything.
  • cruzparse: XML parsing functions for translating level design content into game data.
  • game: The main gameplay class. This covers most general gameplay business logic and functions.
  • cruz: The main interfacial class, controlling Flash-specific API operations and API callbacks, such as user input, timer, load complete, etc.

If I were writing in C# for a PC game, the class layout would look the same. If I were writing in C++ for a game console, the class layout would look the same.

With three exceptions, that is: enumerated constants, polymorphism, and server-side handling.

Enumerated constant definitions will look a bit different across languages. The differences across C++ and Java alone are pretty substantial. Enumerated constants are not directly supported in ActionScript, not even in AS3. If you want to make a constant, you must declare it as a named static constant in a class. I ended up doing this for fxid, objid, and SF classes, to name a few.

ActionScript does not support virtual functions. Even if you derive from a base class, you must cascade functions manually at every level of function implementation. This is annoying. For this reason, some objects, like iobj, were not broken into individual subclasses.

Server-side scripts are necessary for Flash applications that want to maintain a central data repository; there is no dedicated client-side API for handling server-side data. The PHP scripts are very simple. All that the scripts do is take HTTP requests from the Flash application and fire back resources at the application. Just a little text file cooking, that’s it.

Special considerations

As far as the class implementation is concerned…well, it’s here where software engineers earn their pay. I have been programming for well over a decade. It takes skill to know how to properly use arrays, vectors, integers, floating point numbers, and strings. A surgeon can show off the anatomy of a rat, but he can’t tell the lay observer how to sew the rat up so that he instantly knows how to make it live and breathe again.

So I won’t go into the detailed design and cover every function in Cruz. Not today, at least. But I will discuss a very important aspect of programming for web applications: respecting the fact that what you are creating is a web application.

Decades ago, we never would have dreamed that so many of these web applications would conduct advanced calculations in the background. That’s what a client-side web application usually is: a background application. It can be an advertisement, or a game, or a slideshow, or a fundamental user interface needed to enter data into a form. Regardless of what the application is used for, it should be expected that the user’s computer will be doing other things than paying every bit of attention to running your web application.

This means that slack needs to be built into timing routines that might have demanded precision otherwise. Synchronization of animation frames and timer ticks is not guaranteed. CPU performance could be drained by a computer function not even remotely related to the web browser or its applications. The user might destroy your application’s operating environment at any time by closing the window, forcing you to update shared objects or call server-side scripts at key moments to avoid data loss.

Oh, and one final hiccup: the gargantuan task of making Cruz, a cutting-edge netted AS3 application, resemble the gameplay and timing mechanisms of Kroz, a non-netted Pascal application, written over 20 years earlier without any event-driven programming.

Now you know what went into Cruz. Web applications aren’t necessarily easier or harder to program than general-purpose applications–they’re just different.

But in some ways, they’re the same as ever.

That Smoooooth User Interface

July 22nd, 2011

Haven’t you ever gotten annoyed when you want to do something on a computer or handheld device, but you can’t? The user interface is the one thing stopping you from doing “that one obvious thing” that you want?

I have just identified one of the most common sources of “feature creep” in software. When people test an application’s user interface, the feedback is often one of extraordinary inconvenience to the developers of the user interface. No matter how easy or hard it is to give the user what he or she wants, it has to be done. Because people are only human.

But computers are not. Computers are dumb, and a programmer often has to reinvent in code what a human has already thought of and has no trouble executing in reality. The subject of today deals with a difficult, and yet necessary, user interface improvement to a video game.

Remember Diablo? You click the mouse on a spot, and you move to it. If there is an item, you pick it up. Or if there is an enemy, you attack it. If you have a long-distance weapon, you attack it from far away. Why did this system work so well?

Because it reflects what people want. If a person wants to do something in a user interface, the most intuitive thing to do is to interact with the object or location where the action must occur. For this reason, a top-menu is good, but context menus are better, since the action and options are localized. Keyboard shortcuts are good, but allowing a more intuitive (if longer) mechanism is better. Drag-and-drop for directory files, as well as inventory item screens, is reflective of the pick-up and let-go motions that a person will perform when carrying a real, physical object.

Once a popular game uses click-to-move controls, people start to expect, and then demand, click-to-move controls in similar games. Kroz, a game of the late 1980s and early 1990s, got by with keyboard-only controls because mice did not play a big role in the games market back then. But this is 2011, so keyboard-only controls are not acceptable for many people today.

When I developed Cruz, which modernizes Kroz, I realized I was dealing with a serious user interface problem: now that people like to use their mice in dungeon-crawler-type games, how should I allow the user to employ the mouse for a game that was never designed to work with one?

I decided that click-to-move would work best for Cruz. Some games featuring ASCII characters use mice in a different fashion. ZZT, for example, had analog mouse movements move the player, instead. This was clunky and unreliable, and for Kroz, where precise movements are very important, a click-to-move scheme is much more desirable.

But click-to-move is not straightforward to implement at all. The click-to-move system in Diablo is quite sophisticated, because so many implicit desires of the user need to be taken into consideration, all without the user ever telling the computer anything! These advanced, not-so-obvious features are all part of Diablo’s click-to-move system:

1) Moving around obstacles. The system must reconcile how the player can get to the destination, even if no direct line of progress exists. This is easy for a human who can see, but for a computer, it’s only as easy as for a human who is blind. The heuristics require probing objects to “feel around corners” in order to find the ideal path to the destination.Normal destination for click-to-move

2) Give-up factor given impassible terrain. The user might click a location that cannot be reached, no matter how close the player is physically to the spot clicked. The “feelers” will never find an impassible spot, so the heuristics need to “know” when to give up and flag the movement as impossible.Impossible destination for click-to-move

3) Target tracking. If the user clicks on a moving target, the path to the destination must be constantly recalculated as the target moves. It’s even possible that the destination will become impassible mid-way through the player’s path traversal.

4) Target prioritization. Is there always one possible target in Diablo? Nope. More typical is a horde of 10 or more foes, all charging at once. If the player clicks on a spot at the end of the pack, or beyond it (if he or she wants to run away), what happens when the remaining foes block the destination? Well, the effects may vary, but the rational assumption that most people have is that a recalculated “flight” response is appropriate if no foe is the target, but a “fight” response, with the nearest foe, should be chosen if a foe is the target, or if a “flight” response is no longer an option.

People want simple. But simple is not simple to implement. Clearly, one would run into the same issues faced by the Diablo development team while developing a click-to-move system. I could forgo movement around obstacles, but that would annoy people. At the very least, handling obstacles was an absolute necessity for Cruz.

But a game’s user interface must be shaped around the game. A direct copy of another game’s methods never works. Cruz does not require things like target tracking, but it does require something similar to target prioritization. There are a lot of object types in this game, and many of these objects have both positive and negative consequences when touched.

I had to develop a set of “navigation rules” based on the types themselves and where the user had explicitly clicked. These are the rules:

1) Commit to movement to a position if the user directly clicks on a spot, regardless of consequences.

2) If user had clicked once on a spot, the path taken is a careful one. Only visible items that are worth getting and don’t hurt the player are picked up automatically. For objects that hurt the player, the path avoids them completely, even if it is possible to move into them. Single-click (avoids hazards)

3) If user had double-clicked a spot, the path taken is a hasty one. Passage over objects, even those that hurt, is possible, as long as the object isn’t a path dealbreaker. A path dealbreaker is something that would never allow access to the destination if crossed, such as a teleport trap or a bottomless pit.Double-click (cuts through hazards)

Some objects are only reachable by click-to-move if clicked on directly: solid walls, doors, lava, pits, etc. Since Kroz games require careful movement, recklessness in the form of clicking explicitly on the wrong spot is punished the same as with an errant key press. But implicit movement into danger should not happen simply because the user didn’t spoon-feed the computer an exact path. Why should the computer err on the side of a fundamentally nonsensical decision?

The click-to-move system would be great even if just left with the above rule set. This is pretty much the way it works now, if you want to try it out at http://www.chriskallen.com/cruz/cruz.html.

Alas, Cruz is a more complex game than that! What about boulder pushing? Puzzles must be solved by pushing boulders in eight directions. When should click-to-move push objects? Also, several levels in Cruz have gravity. How should “feelers” work if the player must climb and jump in order to reach certain destinations?

Diablo offers no guidance, since neither pushables nor gravity effects factored into that game’s navigation system. Cruz does implement rules for these special cases, but more work is still needed. What is intuitive movement for dungeon-crawler combat is not intuitive for puzzle-solving or side-scrolling action.

Now you have an idea of some of the user interface issues that a software engineer has to deal with! So the next time you find the need to complain about not being able to do that…

Remember, “that” is often a really tough challenge behind the scenes.

A Game Resurrected!

June 8th, 2011

Hello; it’s been a while. There hasn’t been much to say on the formatting blog, since I’ve been busy working at GD and making the game engine Cruz in my spare time.

This is the subject today: Cruz, and its level design format. Pictured below is a screenshot of “Return to Kroz” played in the Cruz engine. As you can see, the game turned out rather well.

Cruz

Others seem to really like this game. You can play it at one of these locations:

http://www.chriskallen.com/cruz/
http://www.newgrounds.com/portal/view/569388

Moving beyond “amateur-experiment” games into “pro” games is something I’ve wanted to do for a long time, and it appears I’ve met success with the Cruz demo: I have successfully resurrected the Kroz series from the annals of DOS history.

CruzEditor, the subject of my last post, has not changed much. The game itself just reads the XML content created with CruzEditor. The devil, of course, is in the details of the XML content.

ActionScript 3 provides a robust API for parsing XML. You can reference individual branches of the XML “tree” via dynamic properties. For example, if XML has encapsulated an attribute of an element called “stuff,” you can access it from the top-level XML object by writing in the code “outer.inner.element.@stuff” without having to wade through string parsing routines or numerous “get” API functions.

Okay, but how does one store the level design content for Cruz, let alone all the Kroz games?

Of the eight Kroz games made by Apogee, each one was its own executable. Having a single application take on the level set-up responsibilities for all the games, each with its own subtle variations on format, was a big challenge. I have written a whole technical article about all the Kroz/Cruz differences here:

http://www.chriskallen.com/cruz/differences.html#differences

I decided that a hybrid of the original level design formats for Kroz and my own additions would be suitable. The character encodings for ordered levels would stay the same (with the exception of text), the unordered levels would be encoded as individual named assignments (not the hard-to-read DF assignments in the original Pascal), and level/episode features would have their own containers to allow for basic design tweaks, such as gravity, terrain growth, quake drop type, whether level was sideways, etc.

The advantage of the format is that it is way more manageable than before–as human-readable XML, it allows for no misunderstanding of what is represented.

The disadvantage is that the content is a lot larger than the original Kroz binary-encoded data. This might have been an issue 10 years ago, but with people streaming video to their computers, a few hundred kilobytes no longer matters as much.

Load times are reasonable for Cruz. Oddly enough, the John Wilson “Hidden Caves of Kroz” episode, which I had nothing to do with, has very long load times for some levels. I suspect that game’s metadata is handled much less effectively.

That there was no modding community for Kroz was disappointing. With CruzEditor, we can develop such a community–one in which anyone can write their own Kroz adventures. Finally!

Popularizing the series once again will be easy, too. Before Cruz, basic attempts at porting Kingdom of Kroz II had been done, but not the entire series. Now, at last, gamers can play the entire series online, including the mother lode of Kroz adventures, Lost Adventures of Kroz!

Of course, you can’t build a modding community if the moddable game isn’t good. Generally speaking, people don’t mod stuff that sucks, because it doesn’t become popular. So, I didn’t just simply recreate Kroz when I made Cruz–I gave it a big overhaul in terms of engine.

ASCII characters have been replaced with actual sprite models. Animation is now much better. Sound effects are mostly the same due to nostalgia, but there are a few new ones as well. Timing is controlled and reasonable, which was a big problem with Kroz games as CPU speed increased. And most important of all–I wrote an entire musical score for the game, something Kroz didn’t have originally.

There is one thing missing from this whole enterprise–the author’s blessing. You might wonder why I’d do all this without consulting him?

First of all, I didn’t think I needed any sort of official go-or-no-go from 3dRealms. The source code was released as Freeware, and I picked it up and ran with it–my own way.

The other reason is that they probably don’t care much about the Kroz franchise anymore. At this time, it seems like they’re actually going to release Duke Nukem Forever, after a decade of anticipation. Who cares about some stupid, outdated text-mode game that has aged terribly and means almost nothing to modern gamers?

Answer: I do!!

That Was Random

August 20th, 2010

Here’s something new. Or rather, something very old. I introduce to you CruzEditor, my new Flash editor for the classic Kroz series of games.

CruzEditor - New Level Editor For Kroz

Over a year ago, I made a BAR implementation file for characterizing Kroz level designs from the source code files released by Apogee in 2009. But I never really did anything with the results–until now. Pictured here is the opening scene from Lost Adventures of Kroz.

Well, the original Kroz graphics weren’t that good. The editor is still under development, and the game engine for the remake is still a ways off. I intend to re-release a modernized version of all seven original episodes, eight if you include Kingdom of Kroz II. I also want to develop some more adventures of my own and enable others to do so.

As of this point, all of the Kroz source code files now work with CruzEditor, including all ordered and all unordered levels. See the unordered levels below:

Unordered Level 1
Unordered Level 2

These are unordered levels, created after pushing the “Test Generate” button. If you keep pushing the button, a new random level will be generated.

Scott Miller’s original random-level generation routine was very simple. It just involved selecting a random pair of coordinates for each item that needed to be placed on the grid.

But this was problematic for those levels, like the ones shown here, that were filled wall-to-wall with enemies, walls, or other items.

Whenever a spot on the grid was not empty, the coordinates had to be rejected, and a new pair picked instead. This made the level generation process very slow for levels that ended up rejecting lots and lots of coordinates.

I decided to employ a better level generation process: the random list algorithm. With this, you treat each grid square as a list item, and have a probability (in this case, about 1 in 1,500) that any one square will be picked next for placement. Then, after placement occurs, you remove that square from the available squares, and then run a reduced probability on the rest of them. The next placement would be 1 in 1,499, the next 1 in 1,498, then 1 in 1,497, etc. all the way down to 1 in 2 and 1 in 1, if the grid needs to be completely filled up.

A smaller list like this ten-item one can help to visualize:

ABCDEFGHIJ : Pick C
ABJDEFGHI : Pick A
IBJDEFGH : Pick G
IBJDEFH : Pick E
IBJDHF : Pick F
IBJDH : Pick B
IHJD : Pick J
IHD : Pick I
DH : Pick D
H : Pick H

The algorithm is fastest if the last item in the list is moved to fill the “gap” made by removing the item selected. You could also perform a slower memory block transfer to preserve the original order, but this is moot because the list will ultimately end up shuffled.

With no rejected coordinates, it runs pretty fast.

Do you like the look and feel of this editor? I will make it available to everyone eventually. That we never had an editor for Kroz in the first place was a disappointment–a problem which I intend to remedy.

Patchmaker International

June 14th, 2010

Hi folks. Since I started at GD, I’ve been away from the blog, but here’s a format I’ve been working on for a while: IPS, or International Patching Specification.

My last entry about ROM hacking only discussed what a person does to make a hack. But with a mind for distribution, no hack would ever legally pass muster without some sort of patching scheme. This involves a format that facilitates patching, and software applications that can make and apply such patches.

A patch file contains only changes to a file. Suppose you have version A and version B of a file: the patch, once applied to A, will “transform” A into B, provided you have version A to begin with.

The most common type of patch file used in ROM hacks is IPS, and for good reason:

1) It’s common.
2) It’s simple.
3) It works well with small binaries.

A number of utilities exist to apply patches, such as IPSWin.exe. It applies patch files with IPS extensions to whole ROMs or other files. Generally speaking, you cannot distribute the whole ROMs legally to another person, but you can distribute the patch, which contains only changes you’ve made personally.

There is a lot of legal gray area here. But I’m not concerned with that–and neither should you. What concerned me was that I never found many utilities that could make IPS files in the way I wanted.

I went to work on BARfly and made a new I.F. called IPS.BAR. This file actually has three functions rolled into one:

1) It characterizes patch records of an existing IPS file.
2) It allows you to patch a file using version A of a file and an IPS file.
3) It allows you to make an IPS from version A and version B of a file.

It’s #3 that is most useful to me. I had to give it some thought, because there are some nuances to making a patch have a small size. Run-length encoding is supported in IPS, so I took advantage of that whenever possible.

When testing it out, I was shocked to discover that in some cases, IPS.BAR generated patch files nearly half the size of some of the originals I’ve found online!

Anyway, I’m satisfied with the utility, and I encourage anyone who wants to learn about IPS to check out the new file on my website. Download it here: http://www.chriskallen.com/barfly/IPS_Patch_File.bar.

I will note that the instructions are not that straightforward because they involve some copying, pasting, and deleting. This is because BARfly’s original charter was to characterize data formats. Its utility in performing more complex file operations is limited as a result. I will be changing this soon, of course. Having a schema have diverse file inputs and file outputs raises the “BAR” significantly–pun intended.

Reverse Engineering with Style

April 13th, 2010

Folks, it was only a matter of time before I would talk about this subject. I’ve covered many different types of data formats, including secondary storage, network communications, and representation in RAM. But what about executable files?

If you’ve evaluated BARfly, you’ll know that the software is merciless. It doesn’t know when it’s being pushed too far. If you want to represent machine code instruction sets with it, you’re perfectly welcome to do so. Machine language is just another data format.

I won’t go into all the ethics of (or reasons for) reverse engineering. I will say this, though: most of the time, license agreements you sign when you purchase software or hardware have a clause forbidding the reverse engineering of your newly acquired property. Please obey those.

Now that I’ve said that, let’s talk about reverse engineering with style.

When a program’s source code is compiled and linked, it becomes machine language, a series of bytes that, when interpreted, tell a processor what to do. A machine language “instruction,” as it is known, generally has the form of an operational code (often known as an “opcode“), followed by one or more optional “mod bytes” that influence the performance of the opcode.

Most programmers nowadays don’t know about machine language. This is because compilers and linkers are so good anymore, and optimization so reliable, that everyone just thinks, “I’ll just create the source code and have the compiler handle the tough translation tasks.” Unless you’re tasked with making or modifying the compiler itself, you normally don’t need to know about the target instruction set.

But if you are performing reverse engineering, you’ll need to know about every instruction set you want to work with. Each computer manufacturer uses its own instruction set and has its own interface for programming the hardware, which isn’t necessarily linked to the instruction set.

Why do you need to know this info? Because once machine language is generated, it can’t be immediately molded back into source code. Machine language instructions tend to be simple operations. The equation A = B + C * D / E would require at least 5 different instructions.

As you can imagine, reverse engineering requires both a significant knowledge base and a whole lot of patience. The quality of the tools used in the process can make a huge difference in overall effectiveness.

A short list of tools you have:

  1. DEBUG: A very elementary disassembler and debugger, present since the early days of DOS.
  2. IDA Pro: A sophisticated, platform-independent graphical disassembly suite.
  3. Various off-the-shelf tools: Varying functionality and usefulness.
  4. Emulators: Programs designed to run a simulated version of the actual machine in a “box,” whose input and output can be easily manipulated.

DEBUG and similar disassemblers operate on the principle that any portion of memory can be reverse-engineered, as long as you know (a) the starting address, and (b) the range over which the code needs to be reverse-engineered. This is the “forward only” principle.

IDA Pro and similar tools operate on a “follow the path only” principle. Instead of linearly (and blindly) stepping through instructions in a memory buffer, IDA Pro allows you to keep track of the stack frame, the call tree of the program, the references to local and global variables, jump labels, etc. Generally, output from applications like IDA Pro are more useful than the “forward and blind” applications like DEBUG.

Programmers have made custom disassemblers that try to get around some of the limitations of DEBUG and/or IDA Pro. These tools have varying strengths and weaknesses, which I will discuss shortly. Finding the right tool can make a world of difference.

Emulation is the last resort of reverse engineering. With an emulator, you can get a realistic state of the processor and its memory at all times. DosBox is a common emulator for 16-bit DOS applications. Emulators are also commonly used to play classic games built for antiquated hardware; MAME is the best-known example.

The biggest strength of the “forward-only” principle in reverse engineering is that you cover all bases–you reach all portions of code, regardless of how they are actually covered. The weaknesses include possibly disassembling non-code (resulting in gibberish), straddling valid opcodes (resulting in incorrect disassembly), and limited ability to interpret the results.

The core strength of the “follow the path only” principle is that only the paths actually discovered through natural flow from points of entry will be disassembled. This yields much more useful and valid output than forward-only, and allows applications like IDA Pro to display all sorts of useful diagrams and relationships. The weakness of path-following is that it is restricted to just known points of entry and deterministic paths (not all code is deterministic).

I’m going to provide a case study in reverse engineering, using my own experience. I’ve already done a ROM hack total conversion with Metroid Master, but I wanted to do the next ROM hack without relying so much on others’ tools. This time, I decided to reverse engineer the code by building my own disassembler.

(NOTE: I feel I can safely talk about reverse engineering 8-bit Metroid because it’s been 25 years since it was popular. If I were talking about hacking Wii games, Nintendo might not like what I’m doing.)

There are many quality 6502 disassemblers out there. I’m mostly used to Intel’s x86 family of instruction sets. But the 6502 processor was once widely used, so learning it was something I absolutely had to do.

The rationale behind creating my own disassembler is that I wanted to circumvent the weaknesses of the existing disassemblers. My disassembler performs limited emulation, and can generate multiple types of readable assembly from machine language.

While 6502 disassembly output usually looks like this…

0001FFB0: sei
0001FFB1: cld
0001FFB2: ldx #$00
0001FFB4: stx $2000
0001FFB7: stx $2001
0001FFBA: lda $2002
0001FFBD: bpl $0001FFBA
0001FFBF: lda $2002
0001FFC2: bpl $0001FFBF
0001FFC4: ora #$FF
0001FFC6: sta $8000
0001FFC9: sta $A000
0001FFCC: sta $C000
0001FFCF: sta $E000
0001FFD2: jmp $C01A

…my disassembler, NESDis, can display it like this:

label_07_FFB0:
07/FFB0: 78 P |= F_INTERRUPT_DISABLE;
07/FFB1: D8 P &= ~F_DECIMAL_MODE;
07/FFB2: A2 00 X = 0×00;
07/FFB4: 8E 00 20 m[0x2000] = X; // PPU Command
07/FFB7: 8E 01 20 m[0x2001] = X; // PPU Command
label_07_FFBA:
07/FFBA: AD 02 20 A = m[0x2002]; // PPU Read
07/FFBD: 10 FB if (!(P & F_SIGN)) goto label_FFBA;
label_07_FFBF:
07/FFBF: AD 02 20 A = m[0x2002]; // PPU Read
07/FFC2: 10 FB if (!(P & F_SIGN)) goto label_FFBF;
label_07_FFC4:
07/FFC4: 09 FF A |= 0xFF;
07/FFC6: 8D 00 80 m[0x8000] = A; // MMC1 Control
07/FFC9: 8D 00 A0 m[0xA000] = A; // MMC1 CHR-ROM 1
07/FFCC: 8D 00 C0 m[0xC000] = A; // MMC1 CHR-ROM 2
07/FFCF: 8D 00 E0 m[0xE000] = A; // MMC1 PRG-ROM
07/FFD2: 4C 1A C0 goto label_0xC01A

Same machine language, but the assembly output looks COMPLETELY different. I think opcodes are much more readable if put into C-language equivalents. Wouldn’t you agree?

Critical hardware port programming is revealed. Original machine language and readable assembly are displayed concurrently. Addresses and bank numbers are known. More importantly, paths are followed in a similar way as IDA Pro, meaning that they need not be dumped in a linear order (they can be dumped hierarchically).

BUT…determinism is always an issue. Most instruction sets, including both x86 and 6502, have indirect jump opcodes. This constitutes a serious problem because the path to which to jump or call is determined at run-time. Emulation can help find the valid addresses, but it’s almost impossible to know all the valid addresses unless you watch every path being followed at run-time, which is usually not worth it.

Fortunately, programmers rarely get fancy with such opcodes for just any reason. A programmer will generally implement an indirect jump or call for one of the following reasons:

  1. Callback or “hook” procedure. Equivalent to a C-language pointer to a function.
  2. Switch control block. C-language “switch” statements can use a “jump table” to quickly direct program control to a wide variety of locations based on a scalar input. This is most economical when there are many scalar input choices that are numerically close to each other (e.g. 5, 6, 7, 8, and 9).

These are very specific circumstances. Therefore, the number of indirect jump opcodes in a program tends to be very few. When confronted with an indirect jump opcode, I had to perform manual inspection to figure out what the processor was trying to do:

label_07_C510:
07/C510: 0A A <<= 1;
07/C511: A8 Y = A;
07/C512: B9 1F C5 A = m[0xC51F + Y];
07/C515: 85 0A m[0x0A] = A;
07/C517: B9 20 C5 A = m[0xC520 + Y];
07/C51A: 85 0B m[0x0B] = A;
07/C51C: 6C 0A 00 indirect_jump(ia(0x000A));

What does this mean? Well, roughly translated, it means “use the value of Y as an index into a jump table.” Fortunately, the jump table is located immediately after the indirect jump opcode. I’ve found that the jump addresses, also co-located, evaluate to the following:

{ 0xC531, 0xC552, 0xC583, 0xC590, 0xC5B6, 0xC5C3, 0xC45C, 0xC45C, 0xC45C }

NESDis stops when it encounters an indirect jump opcode, because of lack of determinism. But you can pick any point of entry with NESDis. The next time I ran NESDis, I chose the point of entry as the first entry in the jump table, 0xC531. And lo! An entirely new set of paths was revealed:

label_07_C531:
07/C531: A0 00 Y = 0×00;
07/C533: 84 31 m[0x31] = Y;
07/C535: C8 Y++;
07/C536: 84 1D m[0x1D] = Y;
07/C538: 20 5D C4 funccall_0xC45D();
label_07_C53B:
07/C53B: 20 3E A9 funccall_0xA93E();
label_07_C53E:
07/C53E: 20 58 C1 funccall_0xC158();

By combining the results of individual NESDis outputs, we can eventually build a complete picture of the Metroid source code.

Individuals who are interested in reverse engineering now have an idea of where to begin. Of course, there are many other advanced tricks, but they have to be discovered on one’s own time.

I strongly suggest you check out emulation central, http://www.zophar.net, for more information.

Programming Made Easier with the Right Formats

March 26th, 2010

We’re going to go WAY back in my programming career this time. I’m almost embarrassed, in fact, to be mentioning this. My first real attempt at action game programming was making a game out of a silly paper drawing that my friends and I had worked on, called a “Torture Course.” Screenshot is below.

Torture Course

It looks like your typical “get through a dungeon full of traps without dying” type of game. More or less, it’s true. ASCII characters plopped on the screen, leaving much (okay, just about everything) to one’s imagination.

Incredibly, a game this early in my programming career (circa 1991) had sound programming, mostly in the form of creative effects when your character gets zapped, stabbed, burnt, cut up, etc.

But how was the level information stored? How did I edit it? How to test it?

Heh heh…well, folks, I hadn’t yet learned that you can actually call API functions to save and load information. What’s that, you say? You can SAVE your designed data and LOAD it later?

If you don’t believe that the level was generated ENTIRELY by code, just look at a sampling of how the BASIC code was constructed:

19 I$ = INKEY$: IF I$ = “y” OR I$ = “Y” THEN SYSTEM ELSE IF I$ = “n” OR I$ = “N” THEN 0 ELSE GOTO 19
20 I$ = INKEY$: IF VAL(I$) > 6 OR VAL(I$) < 1 THEN 20 ELSE TYPEVAL = 0: CHAIN "intermis.bas"
49 L = 40: FL$ = CHR$(15)
50 A = 2: B = 1: C = 102: SQ = 6: F1 = 26: F2 = 26: F3 = 30: F4 = 30: UP = 1: LEFT = 1: F$ = "M": T1 = 3: T2 = 6: WP1 = 10: WP2 = 25: JUMP = 2: H = 3: LF = 1
60 LA$ = CHR$(175): W$ = CHR$(219): U$ = CHR$(24): D$ = CHR$(25): R$ = CHR$(17): L$ = CHR$(16): LS$ = CHR$(176): WP$ = CHR$(254): V$ = CHR$(179): LN$ = CHR$(196)
61 CLS : COLOR 8: LOCATE 1, 1: PRINT STRING$(45, W$); : LOCATE 8, 1: PRINT STRING$(45, W$); : LOCATE 8, 40: PRINT " "; W$; " "; W$; " "
62 FOR X = 2 TO 7: LOCATE X, 1: PRINT W$; : LOCATE X, 9: PRINT W$; : LOCATE X, 16: PRINT W$; : LOCATE X, 24: PRINT W$; : LOCATE X, 45: PRINT W$: NEXT
63 LOCATE 2, 2: COLOR 10: PRINT V$; " "; V$; " "; V$; " "; V$; " "; : COLOR 6: PRINT WP$; SPC(13); : COLOR 8: PRINT W$; : COLOR 6: PRINT WP$; : COLOR 8: PRINT " "; W$; " "; : COLOR 10: PRINT V$; : COLOR 8: PRINT "oooooo "; LS$; " "; LS$
64 LOCATE 3, 2: COLOR 10: PRINT V$; " "; V$; " "; V$; " ": LOCATE 3, 16: PRINT " ": LOCATE 3, 32: PRINT V$: LOCATE 4, 2: PRINT V$; " "; V$: LOCATE 4, 27: COLOR 8: PRINT W$; W$; " "; : COLOR 10: PRINT V$
65 LOCATE 5, 2: PRINT V$: LOCATE 5, 28: COLOR 8: PRINT LS$; " "; : COLOR 10: PRINT V$; : LOCATE 6, 28: COLOR 8: PRINT W$; " "; : COLOR 10: PRINT V$: LOCATE 7, 2: COLOR 12: PRINT U$; U$; U$; U$; U$; U$; U$; : COLOR 8: PRINT W$; : COLOR 14
66 PRINT LS$; LA$; LA$; LA$; LA$; LS$: LOCATE 7, 24: COLOR 8: PRINT " "; LS$; " "; : COLOR 10: PRINT V$;

Ha ha ha ha he he ha ha ha–oh, whoops. I gotta continue this entry. You can continue laughing if you want. If a software engineer in his right mind would ever code like this, he would have to be under one intense deadline. Obviously, coding discipline and coding standards are very important, neither which I had even heard of back then.

If only I had thought ahead of time how to put the program’s architecture together. But when you have only your own resourcefulness, every line of code you write is a proof of concept in some fashion. I will note that programming courses on the level of what I was trying to do were NOT offered at my schools. So I improvised.

Walls and movers were drawn on the screen with for…next loops. If…then statements were used to check for collisions. And I mean a LOT of If…then statements. One for each wall segment or obstacle. The Torture Course bears a striking resemblance to a game known as “Escape from Epsilon,” which at the time, I had never seen. But the creators of THAT game had it together. I clearly did not.

It would have been far better if I had designed the levels in a text editor, with various symbols representing the walls and obstacles. It would have been much better if I had simply chosen an intra-code gridded format, like what Scott Miller did with Kroz. Making my own independent level editor would have been excessive, though. Especially when you consider that I’d have to create an entirely new format.

Speaking of which, there are a LOT of game design formats out there. Since every game is its own beast (and often its own programming masterpiece), it’s reasonable to assume that just about every game has its own custom formats, specific to JUST that game. Well, sort of. The resources used to create games are now a lot more standardized than before: GIF, BMP, JPEG, PNG for images, MPEG, MOV, and AVI for video, WAV, AIFF, and MP3 for audio.

But the level designs for games are all over the place. I’ve got several of my own: NIB, NGR. There are FR files, UNR files, MAP files, and the list goes on. Savegame formats? Once again, all over the place. What do these mean? Should we care?

Granted, there are somewhat standardized level design formats. A software engineer must decide on the ease of implementation when figuring out how to store the formats. I’ve mentioned how BARfly can transform text into binary with the formats used in Brian’s Journey. But really, a designer needs to start out with concepts, and not so much formats.

What is the designer trying to represent? If it’s a static 3-D map, try using an off-the-shelf editor. If it’s a standard 2-D grid, try using an off-the-shelf editor. If you need to start adding game-specific features that no off-the-shelf formats support, think about XML or other text-based formats. There should be no shame in starting out a level design with multiple formats per level. After all, many maps are designed in such a fashion: static elements on one layer, and actors and dynamic elements in additional layers, which are placed at pre-map based on a specific context.

Software engineers are supposed to be resourceful. Use text when you want to edit quickly and experiment. Use off-the-shelf editors to generate static designs.

But whatever you do, DO NOT create your own level editor unless you think it’s value-added in terms of time. It can save loads of time if the editor and the game app are the same program, but remember, the cost of developing the editor is something you can’t get back. Try to figure it out:

Is (Cost of Editor Creation) + [(Less Time Editing) * (Total Number of Levels)]

less than or greater than [(More Time Editing with COTS editor and text files) * (Total Number of Levels)] ?

In my case with the Torture Course, and in Scott Miller’s case with Kroz, a single change to a single level feature required a recompile of the ENTIRE program. And back in the day, compile times were not fast. That adds to your development and testing time!

In the case of Nibbler, an intra-game level editor allowed much more rapid development and testing of levels, even though it’s just a compressed gridded format.

I guy I know named Josh uses text files to script when enemy ship formations appear in his side-scrolling shooter. Is that wrong? He has claimed it could be viewed as lazy, but I think, what’s a more straightforward way to fine-tune level features than to modify a text file?

There is no consistent answer to how you should use formats to make your development job easier. But if you ask the right questions, you’ll be in good shape.

But one thing is clear: good riddance to “FOR X = 2 TO 7: LOCATE X, 1: PRINT W$;” !!!!

Local File Manipulation with Flash

March 1st, 2010

For the last several months, I’ve brought myself up to speed on the Flash platform. This a very common environment for the creation of animation, movie clips, and games that are designed to play in an embedded application. This usually means a web browser.

I find Flash useful for game programming, because it’s cross-platform and doesn’t require a separate download. Give someone a link, and -BAM- they’re playing the game. That’s all you need.

But (and there’s always a “but”)…

What about loading and saving of data files to secondary storage?

The general trend for language runtime development is to add more features, give more flexibility, run on more target platforms, etc. Basically you start small and conquer more territory over time. For Flash, it’s no different: it used to be just a sandboxed environment with arcane scripting, focusing mostly on the animation side of things. Then animation expectations got bigger, with a third dimension. Then people wanted more high-level language features; AS3 is now a lot more akin to Java than ever before. Then people wanted full control over files, local and remote. And control over cookies. And the ability to network remotely. And the ability to–

Whoa, whoa, whoa, whoa! Slow down! Are we talking about a sandboxed environment anymore? It seems like you can do anything from Flash now, including program viruses that infect the moment the animation plays! That’s a risk that Adobe has realized and tried to mitigate.

The Flash security settings are actually designed with a lot of foresight. The Adobe AIR platform, created to act as a Flash-based runtime on the server, can do just about anything with files, much like Java, .NET, Perl, or PHP. If your web server supports AIR, the sky is the limit.

But an SWF in your web browser is another story. The sky is NOT the limit–you can only climb a few feet up the mountain if you’re not using AIR. If a Flash SWF file is run as an embedded control in the browser, you don’t have as much control over networks or files. Mainly:

1) Accessing client data, like cookies, is much harder.
2) Network-based communications face many restrictions (can’t “bot” users who run SWF files).
3) Files can be read with URLRequest, URLLoad, etc. But writing to them is nearly IMPOSSIBLE.

Point #3 has been the biggest disappointment to me in terms of game programming. Writing back data to the web server, even if it’s just a dopey high score list, is WAY harder than I think it should be. But it’s also understandable. Flash is an animation platform–Adobe wants to keep it that way. Would-be virus programmers be damned.

But…what if I just want to make an online level editor and save my work that way? You mean I can’t even do something as simple as fopen, fwrite, and fclose in the same freaking directory as the SWF?

I’m a resourceful sort of person. I didn’t want to believe Flash was so restrictive. And it turns out, it’s not.

There are roundabout ways to save data. The Flash security settings, by default, let you access HTML pages and data files in the same directory as the SWF. You just need to be tricky about how you “read” a file.

In the case of http://www.chriskallen.com, the answer lies in PHP. The following Flash code uses sendToURL to “load” a PHP file. But notice that we’re putting a GET variable, text1field.text, into the URL:

function xferClick(e:MouseEvent):void
{
//Compose URL.
var urlstring:String = text2field.text;
var varstring:String =
"?parameter=" + text1field.text;

//Send request (don't check result).
var myrequest:URLRequest = new URLRequest(urlstring + varstring);
sendToURL(myrequest);
}

This means that we’re loading a dynamic web page–a PHP web page–by virtue of a custom input in a GET variable. Unlike non-AIR Flash, PHP can manipulate files locally. As part of the web page “load,” the server-side PHP script gets executed, causing the GET variable to be “saved.”

The SWF can read the data back by invoking URLRequest. No problem!

What does the user see when sendToURL is invoked? Depends on the browser. Since HTTP is stateless, the user might notice that the status bar indicates web traffic. Nearly invisible web traffic, but to be sure, it’s there.

I’ve got my strategy for loading and saving files. Yours can be the same, or it can be much different. You could use Perl instead of PHP. You could install the AIR runtime on the web server, if you have that ability (I don’t). You could use ASP or JSP. The list goes on and on.

Did someone say something about a sandbox?

Getting that image file to your screen

January 28th, 2010

Something we take for granted: image files.

What are image files? How do we get to look at them? We use them all the time, for a variety of reasons, but how do you get from point A, a data file in storage, to point B, the pixels on your computer screen?

When people think of images, they normally think that the computer will just do whatever it takes to display the image, leaving us full control over what we do with the picture once it is rendered. They look at a file on the disk, click on it, and see an image thumbnail pop up. “Good and well,” a person will tell himself, “Because I know that this filename is associated with this picture. End of story.”

It’s unfortunate that image formatting is taken for granted so much. Computers have to do a LOT of things in order to go from an image file to a picture on the screen. Formats are very important to displaying an image, and the inability to display the image, even if only the thumbnail can’t be seen in an explorer window, will frustrate users immensely.

What happens when an image is processed, even when displaying just a thumbnail, is this:

1) File format must be identified. Tags and headers in the file identify the file as a BMP, a JPEG, a PNG, a TIFF, etc.
2) Dimensions (width and height), pixel depth (8-bit, 32-bit, etc.), palettes, and other information must be collected and stored in a format that best promotes the display of the image data on the computer screen.
3) The pixel data itself must be unpacked. There might be compression, or not, meaning a variety of algorithms could be used to get the unpacked pixel data.
4) The unpacked pixel data must be translated into the computer screen’s target format. Pixel depth conversions are the most common types of translation, for example, 8-bit to 16-bit. Re-ordering of the pixels within the bitmap (flipping or rotation) is also common.
5) The computer blits the pixels to the screen. This step is itself a complex process, because it might be a raw transfer of bytes, or the image might be scaled up or down in size to fit into a specific window, or it might be dithered or anti-aliased, or it might require transparency or alpha-blending.

And these steps apply only to raster formats. Vector formats also require the CPU to effectively “draw” the image from scratch, using a series of internal commands stored within the file. For example, SVG, CGM, or WMF.

That’s a lot of work behind the scenes! And the worst part of it is that if any part of these steps break down for a particular file format (for example, TIFF), you can forget about “seeing” the image. That’s it. Over. No room for error.

Obviously, the above problem I have outlined provides a strong incentive to standardize image formats. There’s nothing wrong with that, of course. But software developers are still their own worst enemies here: they continue to develop more formats, and enhance old formats, over time.

The massively disparate mechanisms used to read, draw, and render so many types of image formats has made it difficult for developers to support so many types of formats. Core formats like GIF, JPEG, and BMP are widely supported, but each format has its own unique applications, strengths, and weaknesses. So you can’t ever have a “master” format. If you WANTED to have a “master” format, you would end up creating another format…which means–you guessed it–you’re contributing to the problem.

The fundamental issue here is not that developers are bad people, or that operating systems have flaws in them that prevent all image formats from being viewed and used. The issue is knowledge, and lack of education. To make a decent image reader or writer, you need lots of programming code, usually optimized code, which accomplishes a specific task. And who has the ability to write or understand this code? Just the hardest-core of the already hard-core software developers, who also contribute to the problem.

BARfly confers an advantage to developers and other technical folks: it exposes the “guts” of an image file. It lets you know what’s “really” in it, letting you dissect or even edit the contents that paint programs will not touch. The long-planned “ImageMaker” protocol is not yet available in the software, but once it is, you will have, for the first time ever, a development platform capable of supporting every type of image file ever made, or ever could be made.

Until then, we’ll just have to be content with an elite group of uber-nerds who mercilessly change formatting rules with no prior notice and hold massive contempt for everyone else. Okay, I made that last part up. But the problem is known–we just need to finally start getting around to fixing it!