Tuesday, September 2, 2014

Abiathar Confidential: The Strange and Unusual GalaxyGraphicsChunkSettings

I'm away from all electronic communications this week. Enjoy automatically posted issues of Abiathar Confidential!

This isn't about Abiathar itself, but FleexCore2/FMod, which is an important part of Abiathar.

If you poke around in FMod.dll, specifically the GalaxyGraphicsChunkSettings class or the GalaxyGraphics class that makes heavy use of it, you will find that the structure is a giant mess of strangely-named fields and flags, controlling a huge mess of control flow in GalaxyGraphics.FromFiles that has a cyclomatic complexity of almost 100.

GalaxyGraphicsChunkSettings is a class that determines the chunk layout of the EGA files. You must pass one to GalaxyGraphics.FromFiles so it can know how to interpret the byte streams it's getting. You could make one yourself, or use GetDefaultChunkSettings. Abiathar makes its own, for reasons that will be explained shortly.

Originally, GalaxyGraphicsChunkSettings was a simple and clean bunch of fields. It told FromFiles where to start interpreting things as a certain type of resource and where to stop. (If you set the table chunks to occur after the chunks containing the resources they define, FromFiles will die horribly because it assumes that tables always come first, which they do in all iD Software games.) For example, it had a SpriteTable entry to give the ID of the chunk containing the sprite table, a MaskTileStart entry to give the ID of the first masked 16x16 tile, a matching MaskTileEnd entry to give the ID of the last masked 16x16 tile, and of course a whole bunch of others.

But what are these strange entries with underscores before them? The most used one is _HeaderEntryLength: it tells FromFiles (and ToFiles actually, making it the only reason GalaxyGraphics saves the GalaxyGraphicsChunkSettings you give it) how many bytes should be used for each entry in the EGA header. This and all the underscored options were added while I was genericizing GalaxyGraphics to support Dreams as well. Why are they named with ugly underscores before them? Because I wanted them to be obviously not a chunk setting, and for a long time there was just _HeaderEntryLength.

Enter Abiathar version whatever-it-was-as-of-February. I had just shoved a whole bunch of EGA resources into the executable to use as default graphics. I noticed that the entire EGA file was loaded, decompressed, and rearranged, but only the tiles and masked tiles were used by Abiathar. To save load time, I added _LevelTilesOnly and _TilesOnly. (Why both? It seemed like it might be useful to somebody.) That saved the bit-twiddling to convert the chunks into the various resource types, but decompressing, especially in the default resources, still took quite a while. So, _DecompStart and _DecompEnd were added to ensure that only used chunks would be decompressed when loading the EGAGRAPH resource. You don't actually have to set these; FromFiles will assume you want to decompress all the things if _DecompEnd is 0.

In fact, the _LevelTilesOnly and _TilesOnly options are kind of redundant now because FromFiles has lots of null checks everywhere to make sure it doesn't load non-decompressed chunks as resources. You could, say, set only the range belonging to sprites to be decompressed - only the Sprites list will be populated.

Fortunately, the audio version of this structure (GalaxyAudioChunkSettings, which actually hasn't been published yet because it's part of the unreleased Abiathar v2.2) is a lot less of a mess; it contains no table chunks or _underscored options. Additionally, GalaxyAudio.FromFiles delegates the loading and saving of audio chunks to their classes instead of having a 500-line loader of everything. There are no fancy exclusion options for GalaxyAudio because it takes barely any time at all to do its work.

No comments:

Post a Comment