Appendix J.3 - SRM-D Snapshot Mechanics

<< Click to Display Table of Contents >>

Navigation:  ASA-EMulatR Reference Guide > Introduction > Appendix > Appendix J - SRM Firmware Topic Hive >

Appendix J.3 - SRM-D Snapshot Mechanics

This section is the authoritative reference for the SRM-D snapshot file format, memory region capture policy, integrity field semantics, and validation failure handling. All information here applies equally to saveSnapshot() and loadSnapshot().

 


 

J.3.1 File Format (.axpsnap)

 

The snapshot file is a binary stream written by QDataStream in little-endian byte order. It is self-describing and self-validating: the header contains all information needed to verify snapshot compatibility with the current ROM and emulator build before any state is restored. The format is versioned to support forward evolution.

 

+-------------------------------------------------------------+

| HEADER |

| magic quint64 0x415850534E415001 "AXPSNAPv1" |

| version quint32 1 |

| romHash quint64 FNV-1a hash of ROM payload |

| emulatorBuild quint64 Build ID (__DATE__+__TIME__ hash) |

| finalPC quint64 Boot handoff PC (with PAL bit) |

| finalPalBase quint64 PAL_BASE at handoff |

| cyclesExecuted quint64 Total decompressor cycles |

| elapsedMs double Wall-clock decompression time |

+-------------------------------------------------------------+

| MEMORY REGIONS |

| regionCount quint32 Number of regions |

| [ per region: |

| basePA quint64 Physical base address |

| size quint64 Region byte count |

| data raw bytes Region content |

| ] |

+-------------------------------------------------------------+

| INTEGER REGISTERS |

| intRegs[32] quint64 R0-R31 at boot handoff |

+-------------------------------------------------------------+

| FLOATING-POINT REGISTERS |

| fpRegs[32] quint64 F0-F31 at boot handoff |

+-------------------------------------------------------------+

| IPRs (Internal Processor Registers) |

| iprCount quint32 Number of IPR entries |

| [ per IPR: |

| id quint32 IPR identifier |

| value quint64 IPR value at handoff |

| ] |

+-------------------------------------------------------------+

| FOOTER |

| checksum quint64 FNV-1a over all preceding bytes |

+-------------------------------------------------------------+

 

All multi-byte integers are in little-endian order. The QDataStream version is fixed at Qt_6_0 and is not stored in the file -- it is an implicit contract of the format version field. If the Qt serialization format changes in a future release, the snapshot version field must be incremented.

 

J.3.2 Memory Regions

 

The snapshot captures all physical memory regions live at boot handoff. For the ES40 V6.2 decompressor path, two regions are saved:

 

Region

PA Range

Size

Content

Firmware

0x000000 -- 0x3FFFFF

4.0 MB

Decompressed SRM firmware (copy loop destination)

PALcode space

0x900000 -- 0xBAB7FF

2.7 MB

EXE decompressor image (PAL_BASE home)

 

Total uncompressed snapshot size is approximately 6.7 MB. The snapshot is stored uncompressed. Deterministic execution correctness takes precedence over disk space savings -- a compressed format would introduce a decompression step with potential platform-specific behavior differences.

 

The full 4 MB firmware region is saved regardless of how much was actually written by the copy loop. This enforces address-space determinism: every execution loading from a given snapshot sees identical physical memory at every address, including bytes zero-initialized before the copy loop ran.

 

J.3.3 ROM Hash and Emulator Build ID

 

Two independent integrity fields provide deterministic execution guarantees.

 

ROM Hash -- a 64-bit FNV-1a hash of the ROM payload bytes (excluding any file header before the decompressor signature). Detects any change to the ROM binary: different firmware version, bit flip, or wrong image. Computed at save time. At load time the current ROM payload hash is recomputed and compared. A mismatch is a hard fail triggering automatic rebuild.

 

Emulator Build ID -- a 64-bit hash derived from the compiler's __DATE__ and __TIME__ macros, or a CMake-injected version string. Detects any rebuild of the emulator binary. If IPR layout, register file structure, or PALbox state changes between builds, a snapshot from the old build is incompatible. The build ID catches this before any incorrect state is restored.

 

Both fields are checked on every snapshot load. Either mismatch is a hard fail -- the snapshot is deleted and the full decompression path runs.

 

J.3.4 Footer Checksum

 

The footer contains a 64-bit FNV-1a checksum computed over all bytes from offset 0 through the last byte of the IPR section. Appended as the final 8 bytes of the file. On load the file is read to the footer position, the checksum recomputed, and compared to the stored value. A mismatch indicates corruption or truncation -- the snapshot is deleted and decompression reruns.

 

FNV-1a was selected for simplicity, speed, and absence of external dependencies. It is not a cryptographic hash -- its purpose is corruption detection, not tamper resistance.

 

J.3.5 Validation Failure Handling

 

On any snapshot validation failure the following sequence executes unconditionally:

 

1. Log the specific failure with WARN_LOG:

 "Snapshot magic mismatch -- not an .axpsnap file"

 "Snapshot version mismatch (file=N, expected=M) -- rebuild required"

 "Snapshot ROM hash mismatch -- ROM image has changed -- rebuilding"

 "Snapshot build ID mismatch -- emulator rebuilt -- rebuilding"

 "Snapshot checksum mismatch -- file corrupt or truncated -- rebuilding"

2. Delete the stale/corrupt snapshot file (QFile::remove)

3. Log rebuild notice:

 "[INFO] Running full SRM decompression -- this will take approximately

 16 minutes in a debug build"

 "[INFO] Snapshot will be saved to <path> on completion"

4. Execute decompress() -- full pipeline traversal

5. On success: saveSnapshot() -- write fresh snapshot

6. Log completion:

 "[INFO] Snapshot rebuilt from ES40_V6_2.EXE -- saved to <path>"

 

The user is never required to manually delete, regenerate, or manage snapshot files. The system is fully self-healing. The only required action is patience on the rebuild run -- approximately 16 minutes in a debug build with full trace I/O, under 10 seconds in a release build.

 

See Also: J.2 - SRM-D Configuration and Initialization ; J.5 - SRM-D Full Cycle Execution ; J.1 - ROM Loader: Descriptor Derivation and Snapshot Validation (TC-SNAP-001 through TC-SNAP-004 test results);memoryLib/SrmRomLoader.h; memoryLib/SrmRomLoader.cpp;memoryLib/GuestPhysicalRegionRegistry.cpp (includeInSnapshot flag).