Skip to content

Binary Wire Format v1 ​

Aegis Save uses a custom, bit-exact binary wire format designed for durability, forward/backward compatibility, and zero-copy bundle reuse.

This guide details the physical byte layout of .aegis save files and explains how the format guarantees perpetual compatibility across engine upgrades.


1. Physical Container Layout ​

An .aegis save container is organized into four distinct sections:

text
┌─────────────────────────────────────────────────────────────┐
│ 1. Container Header (Fixed 64-byte uncompressed header)     │
│    - Magic Identifier ("AEGIS\0\0\0")                       │
│    - Format Version (Frozen at 1)                           │
│    - Engine Version & Custom Version GUID Table             │
├─────────────────────────────────────────────────────────────┤
│ 2. Metadata Section (Fast Slot Browser Index)               │
│    - Slot Display Name, UTC Timestamp, Playtime Seconds     │
│    - Game Schema Version & Record Count                     │
├─────────────────────────────────────────────────────────────┤
│ 3. Bundle Index & Hash Table                                │
│    - Table of Bundle Offsets, Sizes, & CRC32 Checksums      │
│    - Spatial Morton Z-Order Locality Tags                   │
├─────────────────────────────────────────────────────────────┤
│ 4. Payload Data Bundles (Oodle Kraken Compressed)           │
│    - Bundle 0: [Records 0..N]                               │
│    - Bundle 1: [Records N+1..M]                             │
│    - ...                                                    │
├─────────────────────────────────────────────────────────────┤
│ 5. Container Trailer                                        │
│    - Overall Payload CRC32 Checksum                         │
└─────────────────────────────────────────────────────────────┘

Key Architectural Strengths ​

  • Fast Metadata Reads: Reading slot info (Get Slot Info / Get All Slot Info) reads only the first few hundred bytes of Header and Metadata. It never decompresses the record bundles, enabling ultra-fast save browser menus even with hundreds of slots.
  • Verbatim Bundle Reuse (F-3): Bundles that contain no modified records are copied directly byte-for-byte from the old file to the new file, skipping CPU-intensive re-compression.
  • Atomic Integrity Validation: Every bundle and the container trailer carry CRC32 checksums. If a power cut or write interruption occurs, corruption is caught immediately.

2. Tagged Property Encoding (G-3) ​

Unlike brittle raw memory dumps, Aegis Save uses Schema-Tagged Property Serialization:

  • Each property written to the bundle carries its name, property type tag, and byte size.
  • If you add a new variable to your character Blueprint in a patch, existing player saves load seamlessly (the new variable adopts its default value).
  • If you remove a variable, Aegis cleanly skips the tagged property bytes without corrupting adjacent variables.
  • If you reorder variables, tagged lookup matches fields by name rather than binary byte offset.

3. Perpetual Compatibility & Golden Save Corpus (G-1, E-1) ​

Aegis Save 1.0 establishes a perpetual backwards compatibility guarantee (G-1):

Every save file written by Aegis 1.0 on any supported engine version will load bit-exact in every future version of Aegis Save.

The Golden Save Corpus ​

To mathematically prove this guarantee rather than merely claim it, the repository contains a committed Golden Save Corpus (Plugins/AegisSave/Corpus/):

  • v1_5.5.aegis (Captured on UE 5.5.4)
  • v1_5.6.aegis (Captured on UE 5.6.1)
  • v1_5.7.aegis (Captured on UE 5.7.4)
  • v1_5.8.aegis (Captured on UE 5.8.1)
  • Manifest.json (Bit-exact property expectations)

The automated test Aegis.Corpus.LoadsAndVerifiesAllEntries executes across all 16 cross-engine permutations ($4 \times 4$) on every engine release gate.


4. Custom Binary Serializers (G-14, FO-20) ​

If your C++ actors implement custom binary serialization via Serialize(FArchive& Ar) instead of standard reflected UPROPERTYs, follow this mandatory rule:

Branch on Meaning, Never on Width (FO-20)

When implementing custom serialization, always branch on engine custom versions or semantic format flags. Never assume fixed byte widths or pack raw C++ structs directly without version tags!

cpp
// Correct: Version-branched custom serialization
void AMyComplexActor::Serialize(FArchive& Ar)
{
    Super::Serialize(Ar);

    Ar.UsingCustomVersion(FMyGameCustomVersion::GUID);
    const int32 CustomVer = Ar.CustomVer(FMyGameCustomVersion::GUID);

    if (Ar.IsSaving())
    {
        Ar << MyCoreValue;
        Ar << MyNewPatchValue; // Added in Version 2
    }
    else if (Ar.IsLoading())
    {
        Ar << MyCoreValue;
        if (CustomVer >= FMyGameCustomVersion::AddedNewPatchValue)
        {
            Ar << MyNewPatchValue;
        }
        else
        {
            MyNewPatchValue = DefaultValue; // Safe fallback for older saves
        }
    }
}

Next Steps ​

Aegis Save — Enterprise World Persistence for Unreal Engine 5.