Skip to content

resources.assets

Klotz Van Ziegelstein edited this page Aug 25, 2018 · 10 revisions

Role

While resources.assets.resS contains the actual music tracks, resources.assets contains the corresponding metadata. For each track the following values are stored (as first discovered by Zetor):

  • Name
  • Track size
  • Offset into resources.assets.resS

When the original resources.assets.resS is replaced with a new one, these values need to be updated for each track. The following sections document how resources.assets can be parsed.

Anatomy of a track entry

Resources.assets contains lots of stuff, not just the metadata for the music. The section where the track entries begin is at a different offset for each Shadowrun game but luckily the entries themselves have a distinct pattern to them:

SomeName-MoreWords(delimiter byte sequence)(track size)(resS offset)

A picture should make this more clear:

The bytes in the blue box are the track name (in this case Seattle-Set7-Legwork). The name is then immediately followed by the delimiter sequence in the yellow box. After this come the two purple boxes we're interested in: the track size and the resS offset.

This pattern can be expressed as a Perl compatible regular expression like this:

[\w]+\x00*\x02\x00{3}\x0E\x00{7}\x02\x00{3}.{8}

Or with POSIX character classes:

[[:alnum:]-]+\x00*\x02\x00{3}\x0E\x00{7}\x02\x00{3}.{8}

The .{8} at the end bundles both the track size and the resS offset. This is possible because both of these values take up four bytes each, and they appear in succession.

Using grouping mechanisms, we can extract substrings from a successful match:

([\w]+)\x00*\x02\x00{3}\x0E\x00{7}\x02\x00{3}(.{8})

respectively:

([[:alnum:]-]+)\x00*\x02\x00{3}\x0E\x00{7}\x02\x00{3}(.{8})

If you look at the source code of Shadow-Tune, though, you'll notice that the parsing routine omits the last (.{8}). This is because the script makes use of a special Perl built-in variable to calculate the absolute file positions of those eight bytes from the "tail" of a successful match. These positions are later used during the update process to locate the track sizes and resS offsets directly.

Some might also wonder why the leading \x00* has a * quantifier. The reason for this is that the delimiter byte sequence is aligned to four-byte words. If the final letters of the preceding name string don't fill up an entire word, the rest is padded with zeroes. As a consequence, the initial \x02 of the delimiter sequence might be preceded by up to three or no null bytes.

Making sense of the byte soup

The four bytes of the track size and the resS offset have to be "interpreted" as unsigned integer values in order to get the numbers we're interested in. More importantly, for these integer values to turn out correct the bytes have to be stored in little-endian order. Most programming languages should have a mechanism in place to handle such a task with minimal headache on the coder's part (e.g. Python has an unpack routine similar to that of Perl).

Clone this wiki locally