BLANCO

Developer · blancodagoat.dev

← All parts

DLC PACKS

GTA V / RAGE file formats › Part 4

How an add-on DLC pack is shaped: folder structure, content.xml and setup2.xml field by field, fileType values, singleplayer registration, and the eight-build failure cycle that proved the working pack template in-game.

How to read the evidence markers on this page: no marker — verified from source or a primary spec, trust it. 🟡 — community reverse-engineering, widely used but never confirmed by Rockstar. 🔴 — folklore: repeated in tutorials, plausible, untested — verify before relying on it. ✅ — confirmed in-game on a real working pack. Full legend and corrections log.

4. DLC packs

Folder structure

mods/update/x64/dlcpacks/mypack/
└─ dlc.rpf
   ├─ setup2.xml
   ├─ content.xml
   ├─ common/data/          # handling.meta, carcols.meta, …
   ├─ data/                 # alternative meta location
   └─ x64/
      ├─ levels/gta5/
      │  ├─ mypack.rpf              # ydr/ydd/ybn/ytd
      │  └─ mypack_metadata.rpf     # ymap/ytyp/ymf
      ├─ vehicles.rpf
      └─ vehiclemods/foo_mods.rpf

Convention (Rockstar's):

  • _metadata.rpf.ymap, .ytyp, _manifest.ymf
  • .rpf (main) → .ydr, .ydd, .yft, .ybn, .ytd

Pack-verified variant (Dekurwinator template1 / eastsidetrailers): the .ytyp travels with the models, not the metadata:

  • map_props.rpf (no <contents> tag) → .ydr .ydd .yft .ytd + .ytyp
  • map_meta.rpf (<contents>CONTENTS_DLC_MAP_DATA</contents>) → .ymap .ybn _manifest.ymf

✅ Putting models+ytyp inside the CONTENTS_DLC_MAP_DATA rpf (or everything in one rpf) mounts fine but the props silently never load, a verified failure mode, twice (v4/v5).

Splitting metadata out is not inherently fatal: the pack-verified template (§4) puts ymap/ybn/_manifest.ymf in map_meta.rpf, separate from the models, and loads fine in SP. The crash reports (documented as a caveat on the gta5-mods DLC Pack Creator tool page) trace to a specific broken arrangement, usually a missing manifest ityp dependency or a DLC_ITYP_REQUEST aimed at the wrong rpf. Fix the dependency, not the split.

✅ Counterpoint from the working pack: the split is what made props load. If a split pack misbehaves, check first: models/ytyp misplaced into the map-data rpf, missing CONTENTS_DLC_MAP_DATA, or resources imported as binary entries (§11). Don't merge the rpfs as a first resort.

setup2.xml

<?xml version="1.0" encoding="UTF-8"?>
<SSetupData>
  <deviceName>dlc_mypack</deviceName>
  <datFile>content.xml</datFile>
  <timeStamp>05/06/2026 00:00:00</timeStamp>
  <nameHash>mypack</nameHash>
  <contentChangeSets/>
  <contentChangeSetGroups>
    <Item>
      <NameHash>GROUP_STARTUP</NameHash>
      <ContentChangeSets>
        <Item>mypack_AUTOGEN</Item>
      </ContentChangeSets>
    </Item>
  </contentChangeSetGroups>
  <startupScript/>
  <scriptCallstackSize value="0"/>
  <type>EXTRACONTENT_COMPAT_PACK</type>
  <order value="80"/>
  <minorOrder value="0"/>
  <isLevelPack value="false"/>
  <dependencyPackHash/>
  <requiredVersion/>
  <subPackCount value="0"/>
</SSetupData>
Field Meaning
deviceName Virtual mount point. dlc_mypack:/ is how content.xml refers to files. Must be unique.
nameHash Pack identity used by changesets. Usually matches folder name.
type EXTRACONTENT_COMPAT_PACK (safe default) or EXTRACONTENT_LEVEL_PACK. ✅ LEVEL_PACK is the proven choice for map/props add-ons (template1, BLSM, eastsidetrailers)
order Mount priority: higher = later = overrides earlier. Order comes from this value and the dlclist.xml entry sequence, not from any number in the folder name. Numbering mod packs 80+ is just a filing habit; the engine parses no digit from the folder.
isLevelPack true on every working map add-on pack examined (template1, BLSM, eastsidetrailers, order 2). The "full new levels only, fragile" claim didn't hold up
startupScript / scriptCallstackSize Only if you ship a .ysc
subPackCount ✅ How many extra archives the pack ships beyond dlc.rpf. The loader mounts dlc1.rpf, dlc2.rpf … up to this count, so files on disk = subPackCount + 1. This is the supported way past the 4 GB per-archive ceiling. Verified against all 45 packs in a retail install: mpheist4 declares 2 and ships three archives, mpbattle and mpsecurity declare 1 and ship two, everything else declares 0. Sub-packs carry no setup2.xml or content.xml of their own and mount into the same deviceName, so content.xml addresses every file the same way regardless of which archive holds it. Two early packs (mpchristmas2, mpheist) omit the field; absent reads as 0

content.xml

<?xml version="1.0" encoding="UTF-8"?>
<CDataFileMgr__ContentsOfDataFileXml>
  <disabledFiles/>
  <includedXmlFiles/>
  <includedDataFiles/>
  <dataFiles>
    <Item>
      <filename>dlc_mypack:/%PLATFORM%/levels/gta5/mypack_metadata.rpf</filename>
      <fileType>RPF_FILE</fileType>
      <overlay value="false"/>
      <disabled value="true"/>
      <persistent value="true"/>
    </Item>
    <Item>
      <filename>dlc_mypack:/%PLATFORM%/levels/gta5/mypack.rpf</filename>
      <fileType>RPF_FILE</fileType>
      <overlay value="false"/>
      <disabled value="true"/>
      <persistent value="true"/>
    </Item>
    <Item>
      <filename>dlc_mypack:/%PLATFORM%/levels/gta5/mypack_metadata.rpf/mypack.ytyp</filename>
      <fileType>DLC_ITYP_REQUEST</fileType>
      <overlay value="false"/>
      <disabled value="true"/>
      <persistent value="false"/>
    </Item>
    <Item>
      <filename>dlc_mypack:/common/data/handling.meta</filename>
      <fileType>HANDLING_FILE</fileType>
      <overlay value="true"/>
      <disabled value="true"/>
    </Item>
  </dataFiles>
  <contentChangeSets>
    <Item>
      <changeSetName>mypack_AUTOGEN</changeSetName>
      <filesToInvalidate/>
      <filesToDisable/>
      <filesToEnable>
        <Item>dlc_mypack:/%PLATFORM%/levels/gta5/mypack_metadata.rpf</Item>
        <Item>dlc_mypack:/%PLATFORM%/levels/gta5/mypack.rpf</Item>
        <Item>dlc_mypack:/%PLATFORM%/levels/gta5/mypack_metadata.rpf/mypack.ytyp</Item>
        <Item>dlc_mypack:/common/data/handling.meta</Item>
      </filesToEnable>
      <txdToLoad/>
      <txdToUnload/>
      <residentResources/>
      <unregisterResources/>
      <executionConditions/>
    </Item>
  </contentChangeSets>
  <patchFiles/>
</CDataFileMgr__ContentsOfDataFileXml>

Rules of thumb:

  • %PLATFORM% expands to x64 on PC. Don't hardcode.
  • Anything with <disabled value="true"/> must appear in a changeset's filesToEnable, or it never loads.
  • overlay="true" = merge into the existing global list (metas). overlay="false" = plain mount (rpfs).
  • persistent="true" = never unloaded once mounted.
  • Every .ytyp needs its own DLC_ITYP_REQUEST entry, path pointing inside the rpf. ✅ Nuance: with correct _manifest.ymf imap→ityp deps, map-streamed ytyps work with no request at all (template1 ships none); keeping one is harmless belt-and-braces. Valid forms: full in-rpf path to the physical .ytyp (✅ working pack), or device-root with .ityp extension (R/gtawprops style). 💥 Device-root with .ytyp = CTD at startup* (verified).
  • Ordering inside dataFiles matters for metas: later overlays win.

✅ Map DLC content.xml: the pack-verified pattern

The generic example above (GROUP_STARTUP changeset, disabled=true/persistent=true) is the props-pack pattern (gtawprops etc.), which loads ityps for object spawners but does not stream ymaps (verified failure v1). A map DLC needs the streaming changeset with a level condition:

<dataFiles>
  <Item>
    <filename>dlc_mypack:/%PLATFORM%/levels/gta5/props/map_props.rpf</filename>
    <fileType>RPF_FILE</fileType>
    <overlay value="false"/> <disabled value="false"/> <persistent value="false"/>
  </Item>
  <Item>
    <filename>dlc_mypack:/%PLATFORM%/levels/gta5/props/map_meta.rpf</filename>
    <fileType>RPF_FILE</fileType>
    <overlay value="false"/> <disabled value="false"/> <persistent value="false"/>
    <contents>CONTENTS_DLC_MAP_DATA</contents>
  </Item>
  <Item>
    <filename>dlc_mypack:/%PLATFORM%/levels/gta5/props/map_props.rpf/mypack.ytyp</filename>
    <fileType>DLC_ITYP_REQUEST</fileType>
    <overlay value="false"/> <disabled value="true"/> <persistent value="true"/>
  </Item>
</dataFiles>
<contentChangeSets>
  <Item>
    <changeSetName>CCS_MYPACK_NG_STREAMING_MAP</changeSetName>
    <filesToEnable>
      <Item>dlc_mypack:/%PLATFORM%/levels/gta5/props/map_props.rpf</Item>
      <Item>dlc_mypack:/%PLATFORM%/levels/gta5/props/map_meta.rpf</Item>
      <Item>dlc_mypack:/%PLATFORM%/levels/gta5/props/map_props.rpf/mypack.ytyp</Item>
    </filesToEnable>
    <executionConditions>
      <activeChangesetConditions>
      </activeChangesetConditions>
      <genericConditions>$level=MO_JIM_L11</genericConditions>
    </executionConditions>
  </Item>
</contentChangeSets>
  • $level=MO_JIM_L11 = GTA V's main SP map level; the changeset fires when it loads.
  • Pair with setup2: changeset under GROUP_UPDATE_STREAMING, EXTRACONTENT_LEVEL_PACK, isLevelPack=true, order 2 (template1 verbatim).

fileType values (the common ones)

Archives / map RPF_FILE, RPF_FILE_PRE_INSTALL, RPF_FILE_PRE_INSTALL_ONLY, PERMANENT_ITYP_FILE, DLC_ITYP_REQUEST, IPL_FILE, IDE_FILE, DELAYED_IDE_FILE, EXTRA_FOLDER_MOUNT_DATA, ZONED_ASSET_FILE

Vehicles VEHICLE_METADATA_FILE, HANDLING_FILE, CARCOLS_FILE, CARGRP_FILE, VEHICLE_VARIATION_FILE, VEHICLE_LAYOUTS_FILE, VEHICLE_POPULATION_FILE, VEHICLE_CAMERA_OFFSETS_FILE, VEHICLEEXTRAS_FILE, VFXVEHICLEINFO_FILE

Peds PEDSTREAM_FILE, PEDGRP_FILE, PED_METADATA_FILE, PED_PERSONALITY_FILE, PED_VARS_FILE, PED_BOUNDS_FILE, PED_HEALTH_FILE, PED_COMPONENT_SETS_FILE, PED_OVERLAY_FILE, PED_TASK_DATA_FILE, PED_BRAWLING_STYLE_FILE, PED_FIRST_PERSON_ASSET_DATA

Weapons WEAPONINFO_FILE, WEAPONINFO_FILE_PATCH, WEAPON_METADATA_FILE, WEAPONCOMPONENTSINFO_FILE, LOADOUTS_FILE, PICKUPS_FILE, EXPLOSION_INFO_FILE

World / population POPGROUP_FILE, DLC_POP_GROUPS, SCENARIO_INFO_FILE, SCENARIO_POINTS_FILE, AMBIENT_ZONE_FILE, TRAFFIC_LIGHT_FILE, POPSCHED_FILE

Audio AUDIO_SOUNDDATA, AUDIO_WAVEPACK, AUDIO_GAMEDATA, AUDIO_SYNTHDATA, AUDIO_DYNAMIXDATA, AUDIO_SPEECHDATA

Text / misc TEXTFILE_METAFILE, GXT2_FILE, SCALEFORM_PREALLOC_FILE, SCALEFORM_VALID_METHODS_FILE, CONDITIONAL_ANIMS_FILE, CLIP_SETS_FILE, EXPRESSION_DLC_FILE, SHOP_PED_APPAREL_META_FILE, TATTOO_SHOP_DLC_FILE

(Full enumeration: github.com/gtasnail/gta5-meta-fileTypes)

Registration (SP)

mods/update/update.rpf/common/data/dlclist.xml:

<Item>dlcpacks:/mypack/</Item>

mods/update/update.rpf/common/data/extratitleupdatedata.meta, required if your DLC needs a device mount:

<Item>
  <deviceName>dlc_mypack</deviceName>
  <datFile>dlcpacks:/mypack/dlc.rpf</datFile>
</Item>

Also: mods/update/update.rpf/common/data/gameconfig.xml, bump pool sizes when you add lots of archetypes/props (ConfigArchetypeManager, MaxNoOfVisibleEntities, fwStaticBoundsStore). Separately, the "worked fine until my Nth DLC" crash is ERR_FIL_PACK_1: the exe has a fixed cap on how many packfiles (RPFs) it will mount, and enough dlcpacks exhausts it. Raise it with the Packfile Limit Adjuster. The count that trips it varies with how many RPFs each pack ships, so there is no fixed "40".


15. Appendix: the pack-verified test cycle

The ✅ claims in this document come from building a real standalone SP add-on (eastsidetrailers, two ymaps + six custom trailer props extracted from a larger map pack into a self-contained dlc.rpf). It took eight builds to get a working pack; every failure and its root cause:

Build Loader / structure Symptom Root cause
v1 props-pack pattern (GROUP_STARTUP enable, device-root .ytyp ityp request) loads, maps never appear props loaders don't stream ymaps
v2 + overlay=true + GROUP_MAP mapChangeSetData enabling the same rpf again CTD at startup double-enable; .ytyp device-root ityp request
v3 ityp request .ityp; empty cache-loader map changesets CTD wrong changeset combo (latent: binary-entry ydrs)
v4 single rpf, CONTENTS_DLC_MAP_DATA, $level changeset, LEVEL_PACK no CTD, nothing loads models+ytyp inside the map-data rpf
v5 full map-overhaul clone (overlay + GROUP_MAP + useCacheLoader) no CTD, nothing loads same split violation
v6 template1: map_props.rpf + map_meta.rpf split, one $level changeset streams! CTD on approach: ERR_SYS_INVALIDRESOURCE_5 the .ydrs were binary entries, extracted headerless, mis-imported
v7 + in-rpf ityp request, re-saved ymaps same CTD same binary ydrs
v8 proper RSC7 export (Compress + AddResourceHeader), byte-original ytyp/ymaps works N/A

The validation gates that would have caught all of it before launch:

  1. Every .y* file in the built rpf is a resource entry, never a binary entry.
  2. RSC7 magic + version per type (ydr 165, yft 162, ytd 13, ybn 43, ymap/ytyp 2).
  3. Every ymap entity archetype resolves against bundled ytyps ∪ the vanilla game.
  4. Manifest imap names match bundled ymaps; ityp deps match bundled ytyps; both dep forms present.
  5. Every disabled=true content.xml entry appears in a changeset's filesToEnable.
  6. No models/ytyps inside the CONTENTS_DLC_MAP_DATA rpf, no ymaps outside it.
  7. Extraction fidelity: re-extracted bytes equal the source (compared through the same API form).
  8. Total rpf size below 4 GB.

In-game triage, once it's installed:

  • Crash at startup → content.xml / setup2.xml (changesets, ityp requests, double-enables).
  • Loads, nothing appears → streaming pattern, props/meta split, or manifest deps.
  • Loads, crash on approach → a streamed resource is invalid (entry type, header, version).
  • Appears untextured → txd reference; no collision → physicsDictionary / ybn list.