Metric Panda Games

One pixel at a time.

Unpacking and Caching Game Assets At Runtime

Rival Fortress Update #33

I modified the asset subsystem for Rival Fortress to support unpacking of compressed assets at runtime. Things like PNG images and TTF fonts will be converted to “game digestible” formats at runtime instead of having them preprocessed offline and shipped with the game.

The reason for this is that I want game content to be easily inspectable and moddable by players without too much trouble.

Game and user mod content will still be distributed in the MPAK format I talked about a few weeks ago, but the game will come with an packer/unpacker executable capable of extracting .MPAK files and re-compressing them in order to facilitate modding.

Caching at runtime

The first time the game encounters an .MPAK file, it parses the header looking for assets that need further preprocessing. Assets that are processed are packed into a new .MPAK file that is saved in the .cache folder located in the user’s “pref dir” (i.e. the OS specific folder where applications are meant to write user specific files, like save games, preferences, etc.).

The new .MPAK file has an internal reference to the parent .MPAK (there is a 1-to-1 relationship between .MPAK files) with each entry referencing the original entry. The game keeps an in memory B-tree containing asset IDs as keys and a pointer to the following data structure as values:

struct MPEPakInMemoryEntry
{
  MPEPakFile* File;
  void* Data;
  u64 Offset;
  u32 Size;
  MPEPakEntryType Type;
  u16 Flags;
};

The memory representation of the file is updated after the asset has been processed.

On demand processing

Not all assets that require processing are processed on load. By default assets are flagged as on-demand (using the u16 Flags above) and are lazily processed when they are required in a separate processing thread.

This means that the game treats all asset requests as asynchronous, and falls back to a default object if the asset is not found or not ready.