← 1.20 ReplayEntropic Dev

REPLAY 1.20 · RESEARCH NOTES

The asset brain

A linked map of loading, rendering, and collision evidence.

34 notes · Latest source update
SOURCE NOTE · Updated 2026-09-28 02:58:19 UTC
On this page

XModel Fastfile to DObj Flow

Asset brain · XModels and Surfaces · Engine Integration

Scope and status

This page traces the best-supported fastfile path into XModel surface data and the source/runtime surface-consumer path. The Replay loader chain is directly inspectable. The Replay cross-reference from loaded XModelSurfs into DObj render submission is not closed: source PDB consumer names and calls are known, but no exact Replay rows or independently resolved target bodies for those consumers are currently recorded. Keep these as two linked investigations, not one proven cross-build call chain.

Replay 1.20 asset and loader path

XModel root

Replay XAssetHeader phase dispatch case 0x9 reaches Load_XModelPtr, Preload_XModelPtr, and Postload_XModelPtr, each of which calls its corresponding XModel root. Current Replay root labels are q_Load_XModel ID 20329/RVA 0xE29820, q_Preload_XModel ID 20368/RVA 0xE2E9C0, and q_Postload_XModel ID 20357/RVA 0xE2CEA0. The source PDB has matching exact phase roots and case 0x9 dispatch. The Replay Load/Preload/Postload root code uses 0x2B0 bytes; the Game-Test XModel PDB UDT is 0x2A8. The eight-byte difference prevents treating the source UDT as Replay ABI.

XModelSurfs pointer and child asset

The separate model-surfaces pointer family is dispatched from XAssetHeader case 0x8 in the source and Replay observations. The source PDB names Load_XModelSurfsPtr at RVA 0x8B35C0, and the source union member XAssetHeader::modelSurfs is an eight-byte pointer at union offset zero. Replay ID 20337/RVA 0xE2A970 is currently named Load_XModelSurfsPtr, size 239. Its Replay callgraph has the Load_XAssetHeader caller and direct nested calls to Load_XModelSurfs ID 20336/RVA 0xE2A7D0 and Load_XModelSurfsAsset ID 24789/RVA 0xF62300. The pointer-state report independently records those two nested roles and the candidate pointer-state global. The source symbol extent is 246 bytes; the Replay row extent is 239 bytes. The prior review kept the semantic cross-build mapping at q-candidate confidence; the current spelling alone does not remove that caveat.

Replay Load and Preload processing of the pointer slot uses eight bytes, and the Postload path advances by eight bytes. The Postload pointer helper observed in the current Replay callgraph is generic ID 20364/RVA 0xE2DDA0 (18 bytes), called from Postload_XAssetHeader; its exact type identity is still unresolved. Replay Preload surface-pointer target ID 20375/RVA 0xE2F7A0 is also generic, but its callgraph includes Load_XModelSurfs and Load_XModelSurfsAsset. These edges support a pointer/asset route, not complete pointer sentinel semantics or pointee layout.

A second explicit route is q_Load_AlwaysloadedFlagSet ID 20385/RVA 0xE2F9B0. It loads Load_XModelPtr, then calls q_AllocLoad_XModelSurfsPtr ID 20319 followed by q_Load_XModelSurfsPtrArray ID 20338. The source PDB has the corresponding named allocator and array loader. Replay's recovered array CFG reaches its epilogue at 0xE2AB9B, but the SQLite size is only 78 bytes; keep the recorded size and prototype and use the resolved CFG/chain evidence for the boundary. The AlwaysloadedFlagSet root and allocator labels remain q-prefixed because caller coverage differs by build.

Surface child processing

Replay ID 20336 Load_XModelSurfs calls Load_XSurfaceSharedData ID 20340, a helper at 0xE2ABA0 with an unresolved name, plus additional stream, asset, and shared-data helpers. The Replay caller graph directly connects it back to Load_XModelSurfsPtr and the Preload pointer route. This gives a loader-level route from the pointer wrapper into the surface parser. It does not establish the exact XSurface child layout or show which runtime draw consumer later dereferences it.

Runtime consumer evidence

Game-Test source PDB / Atlas

The source PDB identifies these separate DObj/render functions:

  • DObjGetSurfaceData at RVA 0x18C1930, 625 bytes; the exported source signatures agree on a DObj *, vector, two fixed 254-entry output arrays, and MaterialLodSettings *, but disagree on the first array type: the PDB signature inventory says unsigned int[254], while the Atlas signature says unsigned char[254]. Treat that type as unresolved. Atlas xrefs show a direct call from R_InitSceneEntity.
  • DObjGetNumSurfaces at RVA 0x18C0D30, 196 bytes; signature takes DObj const * and a 254-entry byte array. Atlas xrefs show a direct call from CG_ModPrvLoadModel.
  • DObjGetSurfacesInternal at RVA 0x18CFCF0, 477 bytes; its exact source caller DObjGetSurfaces tail-jumps to it.
  • R_AddDObjSurfaces at RVA 0xB09ED0, 2923 bytes; Atlas xrefs show calls from sun-shadow and spot-shadow scene-surface submission functions.
  • R_AddDObjSurfacesCamera at RVA 0xB0AD20, 4617 bytes; Atlas xrefs show a call from R_AddAllSceneEntSurfacesCameraCmd.

These PDB signatures and source callsites establish source-side consumer roles. They do not identify Replay counterparts.

Replay runtime anchors and unresolved edge

Replay has exact DObjNumBones at ID 40700/RVA 0x149C1F0, whose five-byte body reads a byte at [rcx+0x10] and returns it. Its direct callers include DObjIsValidBoneIndex; the wider callgraph contains 21 callers. This verifies a DObj bone-count helper, not an XModelSurfs/render-surface consumer.

Replay also has exact Stream_UsedMesh at ID 57281/RVA 0x1BCF850, size 29, cross-referenced from the source PDB at RVA 0x17BCB30; the source signature takes XModelSurfs *. The Replay prototype is a generic __int64 argument, so retain the source type as source-only metadata. Its one indexed Replay caller is generic ID 57273/RVA 0x1BCEDD0. This is a verified mesh-streaming endpoint, but the recorded evidence does not join it to DObj scene submission.

A read-only exact-name query of the current Replay function table has no exact DObjGetSurfaceData, DObjGetNumSurfaces, DObjGetSurfacesInternal, R_AddDObjSurfaces, or R_AddDObjSurfacesCamera rows. No matching Replay bodies/callers are established by the linked evidence. Keep this as an actionable hold rather than assigning candidate generic rows based on the source names alone.

Safe integration reading

The evidence supports the following partial graph:

XAssetHeader phase dispatch
  ├─ case 0x9 -> XModelPtr -> q_Load / q_Preload / q_Postload_XModel
  └─ case 0x8 -> XModelSurfsPtr -> Load_XModelSurfs -> XSurface/shared-data helpers
                                      └─ Load_XModelSurfsAsset registration handler

Game-Test source runtime path:
DObj setup/query -> DObjGetSurfaceData / DObjGetNumSurfaces
                 -> R_AddDObjSurfaces / R_AddDObjSurfacesCamera

Replay runtime evidence:
Load_XModelSurfs -> Stream_UsedMesh (mesh streaming)
DObjNumBones -> DObjIsValidBoneIndex (bone validation)

Cross-build XModelSurfs-to-DObj render-submission edge: unresolved

Do not turn the visual grouping above into a serialized-data order or direct runtime call chain. To close the gap, locate Replay candidates for the five source consumer functions, compare their body/callsite boundaries, then verify that a Replay scene submission route consumes the relevant model/surface pointers.

Evidence

  • XModel asset-root crosswalk
  • XModelSurfs pointer-state and nested-call report
  • XModelSurfsPtr switch-family candidate
  • XModelSurfsPtrArray Replay boundary report
  • AlwaysloadedFlagSet and surface allocator report
  • AlwaysloadedFlagSet/surface allocator application readback
  • DObjNumBones Replay report
  • Game-Test PDB function signatures
  • Game-Test PDB function symbol inventory
  • Replay cross-reference register

The paired Load_GfxWorldSurfaces parent also uses q_AllocLoad_GfxDrawSurf followed by q_Load_GfxDrawSurfArray; see GfxWorld and Brush Models. These helpers parse GfxWorld draw-surface data. Their name and stream wrapper do not prove that the data is the same as XModelSurfs, nor do they close the unresolved Replay DObj render-submission edge.