Talk:GMA

From Valve Developer Community
Jump to navigation Jump to search

GMA File Documention

I've been looking around for documentation related to the GMA format and found this GitHub page which has this code which reads GMA files. Below I will document how GMAs are read, which I can confirm does work with my implementation in C#. If any information below is wrong or you have thoughts, please amend the details or comment.

The file starts out with a header, describing information about the GMA itself:

struct GMAHeader
{
    int         Signature;       // File's Signature, always 'GMAD' (0x47 0x4D 0x41 0x44)
    byte        Version;         // GMAD Version, only '3' has been seen
    ulong       AuthorSteamID;   // The ID of the Steam user who authored the GMA
    ulong       TimeStamp;       // TimeStamp in Unix Time of when the GMA was authored

    byte        padding;         // Padding byte, always 0x00

    string      AddonName;       // Null-terminated string of the name of the addon
    string      JSON;            // Null-terminated string of the JSON data, indicating the addon type, tags, etc.
    uint        AddonVersion;    // The addon's version, starts at '1' (0x01)
};

Immediately trailing the header, a list of file entries begin, detailing information about each file but not storing the file data in this section:

struct GMAFileEntry
{
    string      FilePath;        // Null-terminated string of the filepath of the file. Example: "folder1/voice1.wav"
    ulong       FileLength;      // Length of the file's data
    uint        CRC32;           // Checksum of the file's data
};

Each GMA File Entry has a uint before it with a number, counting the current file. The first 4 bytes at the end of the GMAFileEntry block will always be '0', indicating the end of the block. The GMA File Entry block can be read like this:

BinaryReader reader = new BinaryReader(MemoryStreamWithGMAData);

while(reader.ReadInt32() != 0)
{
   ReadGMAFileEntry();
}

Following the GMA File Entry Block, the rest of the file is data from the files packed into the GMA. They exist in the same order as the GMA File Entry and can be read by reading the amount of bytes based on the file's length.

Note.pngNote:If you are using C#'s BinaryReader, you can only read a int's worth of data from a stream at once. GMA files support file sizes up to the Unsigned 64-bit Integer Limit.
byte[] FileData = reader.ReadBytes((int)GMAFileEntry.FileLength);


--Rmod8 (talk) 07:33, 23 April 2025 (PDT)