ARC: the engine's named archive (bl::archive)
- Source
docs/formats/arc.md- SHA-256
a16150f3…52676d08
Where it appears · Header · Records · Data blocks · Layout rules · Record types · How the game reads it · The shader package · BMAR models · Rebuilding · Leads
The Blade engine's archive: a header, an offset table, a list of named, typed records, and the data blocks they point to. It holds the menu layouts and their textures (menu/), the text presets and the font set, every menu texture pack, the shader package (Shaders/Shader.dat) and the one world-map model (worldmap/Worldmap.dat#28, behind a BMAR104 prefix). An ARC sits whole in a pakd entry or a ZIP member (containers.md), and a data block can hold another ARC, nested up to four deep. Textures inside are btx (another doc); layouts, presets and models are only named here (Leads).
| Based on | Every ARC in the game's Data/: a C# scan of all 10,016 files that unwrap as RotXor + ZIP found 220 top-level ARCs (a payload or a pakd entry starting ARC\0, or BMAR104\0 + ARC\0) and 254 more nested inside them, 474 in all, with 5,959 records. They are all in Shaders/Shader.dat (SHA-256 65f799f68dd1ed7392854bbf352bde8aa8f60a3ae179596b54c513c834ef9a77, 27,572 bytes), the 81 .dat files under menu/ that hold ARCs (among them menu/menu_layout.dat, SHA-256 c4ea277d468d02adbc7e74d866645f79f5fbfa11161d99bb2219d4437f77ce3c; menu/menu_parts.dat, b403e5d7eb07c486c5c69aeaad895af6df875cb5b4f1cfb214f50c046aa8f1e2; menu/fontset/fontset.dat, ca3e8380762155ebafad3093ce7923a5b5888c120e57c7b8027fbb0dc35c715f) and worldmap/Worldmap.dat (3c3c2577a0c0c79259117336594254dd0771da252678e2310507733f3496a698). No file pages yet. The unpacked executable, SHA-256 7b0230a11498f40396c9048345e7cfe0ef442cb7ca8faffc6f197920d2669599. Gibbed's ArcFile.cs and ArcDataHeader.cs (reference_tools/Gibbed.LetUsClingTogether/projects/Gibbed.Reborn.FileFormats/, read-only, no writer) and Gibbed.Reborn.UnpackPAC/Program.cs, checked 2026-10-11. |
| Checked | 2026-10-11 |
| Method | Single-file C# exploration programs in the session scratchpad, over the game files unwrapped with the toolchain's Containers project: arcscan.cs tallies every header, record and block field of every ARC, nested ones included; arcrebuild.cs parses each ARC into a tree and writes it back from the parsed fields with the layout rules, comparing byte for byte; shaderscan.cs decodes the shader package; arclist.cs lists records per file. Static analysis of the executable with Ghidra 12.1.4 through the decompiled code in local/exe/decomp/, and a C# reader for its data (va.cs). No in-game tests. |
Where it appears
| Files | Archive name (header) | Record tags | Nested |
|---|---|---|---|
Shaders/Shader.dat (ZIP member sh_tacos.pac, not a pakd) |
sh_tacos.pac |
21 × bin |
each bin is an ARC <shader>.pac of 2 × bin, each an ARC BlShaderArchive of 1 × SHG, each an ARC BlShaderGroup: see The shader package |
menu/menu_layout.dat (69 entries), menu/menu_parts.dat (70 entries) |
CrowleyArchiveDatas |
1 × lyt, then 0–69 × tex |
— |
menu/fontset/fontset.dat (1 entry) |
CrowleyArchiveDatas |
1 × lpj named fontset |
— |
menu/text/textPreset_ea.dat, textPreset_asia.dat (1 entry each) |
ea_text_preset.pac, asia_text_preset.pac |
75 / 74 × bin named font_*.lpja |
each bin is an ARC CrowleyArchiveDatas of 1 × lpj |
menu/texture_x4/*.dat and its 8 <lang>/ folders (1 entry each) |
<stem>.pac, e.g. com_icon.pac, common_x4.pac |
tex only (0 to 439); tex_common_x4.dat's ARC is empty |
— |
worldmap/Worldmap.dat#28 |
BladeModelPac, after the 8 bytes BMAR104\0 |
BML, BMD, BMA, BMT, all named worldModel00 |
— (contents are chunk chains, BMAR) |
confirmed: these are the only ARCs in the 10,016 unwrapped files, and no other blob has the 6-byte signature ARC\0 00 01 anywhere inside it except Worldmap.dat#28 at +8. Source: arcrebuild.cs over Data/, all files.
Header
Offsets are from the start of the ARC.
| Offset | Size | Type | Name | Meaning | Confidence | Source |
|---|---|---|---|---|---|---|
| 0x00 | 4 | raw[4] | magic |
ARC\0. Every reader checks it. |
confirmed | C# scan, all 474 ARCs (fields tallied by arcscan.cs for the 473 in Shaders/ and menu/, and the BMAR one by its byte-identical rebuild); checked in 0x14005bfa0, 0x14005c0c0 and every inlined walk. |
| 0x04 | 2 | u16 | version |
0x0100 (bytes 00 01). Every reader checks it and ignores an ARC with any other value. |
confirmed | C# scan, all 474; 0x14005c0c0; Gibbed ArcFile (rejects other versions). |
| 0x06 | 2 | u16 | record_count |
Number of records. Equals offset_count in every ARC. |
confirmed | C# scan, all 474; 0x14005bfa0 loops this many times. |
| 0x08 | 2 | u16 | offset_count |
Number of data blocks (entries of the offset table). The records start at align32(0x30 + 4 × offset_count), which the game computes as (4 × offset_count + 0x4F) & ~0x1F. |
confirmed | C# scan, all 474; 0x14005bfa0. |
| 0x0A | 2 | u16 | unk_0x0A |
0 in every ARC. Not read. | confirmed | C# scan, all 474; no reader reads it. |
| 0x0C | 4 | u32 | unk_0x0C |
0 in every ARC. Not read. | confirmed | C# scan, all 474; no reader reads it. |
| 0x10 | 32 | raw[32] | archive_name |
The archive's name, NUL-terminated and zero-padded (sh_tacos.pac, CrowleyArchiveDatas, BlShaderGroup, …). Not read by the game. |
confirmed | C# scan, all 474 (NUL inside the 32 bytes, zeros after it); no reader reads it. |
| 0x30 | 4 × offset_count |
u32[offset_count] |
offsets |
Start of each data block, from the start of the ARC. | confirmed | C# scan, all 474; 0x14005bfa0 (ARC + offsets[data_index]). |
| next | to align32 |
raw[n] | padding |
Zeros up to the first record. | confirmed | C# scan, all 474. |
Byte-swapped ARCs (Gibbed reads CRA\0 as big-endian) don't occur, and this executable's walkers have no byte-swap path for them. Source: C# scan; 0x14005bfa0.
Records
One per data block, back to back from align32(0x30 + 4 × offset_count). Each is align32(0x14 + filename_length) bytes, and the game steps to the next one as (filename_length + 0x33) & ~0x1F. The game's own word for a record's name is "filename" (classes Traverser_filename, Traverser_type_filename). Offsets are from the start of the record.
| Offset | Size | Type | Name | Meaning | Confidence | Source |
|---|---|---|---|---|---|---|
| 0x00 | 4 | raw[4] | type |
The record's kind, as 3 or 4 ASCII bytes, NUL-padded: see Record types. Every lookup matches it. | confirmed | C# scan, all 5,959 records; every traverser in How the game reads it. |
| 0x04 | 2 | u16 | id_u16 |
The record's ID when uses_id_u32 is 0. 0 in every record (all use id_u32). |
confirmed | C# scan, all records; 0x14005bc00, 0x14005bfa0. |
| 0x06 | 2 | u16 | offset_index |
Index into offsets of the record's data block. Equals the record's own index in every record. |
confirmed | C# scan, all records; 0x14005bfa0 (ARC[0x30 + 4 × offset_index]). |
| 0x08 | 4 | u32 | filename_hash |
Hash of filename, as in Filename hash. Correct in every record. Compared only by name lookups that ask for an exact match (the font set's). |
confirmed | C# scan, all records; 0x14005bc30, 0x14008b740. |
| 0x0C | 1 | u8 | unk_0x0C |
0 in every record. Every lookup matches it against a value the caller passes, always 0 in the calls read so far: a sub-kind or group. Gibbed rejects non-zero. | likely | C# scan, all records; 0x14005bc00, 0x14005bc30, 0x14005bed0, 0x14005bef0. |
| 0x0D | 1 | bool8 | uses_id_u32 |
1 in every record: the ID is id_u32. With 0 the game would take id_u16. |
confirmed | C# scan, all records; 0x14005bc00, 0x14005bfa0. |
| 0x0E | 1 | u8 | filename_length |
Length of filename with its NUL. Sets the record's size, so it must be right. |
confirmed | C# scan, all records (strlen + 1); 0x14005bfa0 and every walk. |
| 0x0F | 1 | u8 | unk_0x0F |
0 in every record. Not read. Gibbed rejects non-zero. | confirmed | C# scan, all records. |
| 0x10 | 4 | u32 | id_u32 |
The record's ID, matched by ID lookups. The record's index within its archive in most; 0 for every tex record of a layout archive (CrowleyArchiveDatas) and the 4 BladeModelPac records; for SHP records, the index among the SHPs (the SARC is ID 0). |
confirmed | C# scan, all records; 0x14005bc00. |
| 0x14 | filename_length |
raw[filename_length] |
filename |
ASCII, NUL-terminated. Some carry an extension (font_battle_name_s.lpja); SARC and SHP records have an empty one. |
confirmed | C# scan, all records; the name lookups 0x14005bc30 (Traverser_filename) and 0x14005bd70 (Traverser_type_filename) match on it. |
| next | to align32 |
raw[n] | padding |
Zeros to the record's end. | confirmed | C# scan, all records. |
Filename hash
h = 0; for each byte c of the filename: h = h × 33 + c (32-bit); hash = h + (h >> 5). Source: 0x14008b740 (hashes fontset), 0x1400bc530, 0x1400640b0, 0x140073d70; confirmed against every record's filename_hash (C# scan).
Data blocks
Each offsets entry points to a block: an 8-byte header, zeros, then the content. Offsets are from the start of the block.
| Offset | Size | Type | Name | Meaning | Confidence | Source |
|---|---|---|---|---|---|---|
| 0x0 | 4 | u32 | size |
Size of the content. The game passes it on as the content's length. For a nested ARC it includes that ARC's trailing padding. | confirmed | C# scan; 0x14005bfa0 (result's size). |
| 0x4 | 2 | u16 | alignment |
16, 32 or 128. The content starts at align(8, alignment) from the block, which for these values is alignment itself (Gibbed reads the field as that offset). The block itself starts at a multiple of it from the ARC's start. |
confirmed | C# scan, all 5,959 blocks (16: the 4 in BladeModelPac; 32: bin and tex in *.pac archives; 128: the rest, tex in layout archives included); 0x14005bfa0, 0x140037f40-style (a − 1 + 8) & −a. |
| 0x6 | 1 | u8 | unk_0x06 |
0 in every block. Read into the lookup result (offset 0x1C) and handed to the caller; no use seen. Gibbed rejects non-zero. | likely | C# scan, all blocks; 0x14005bfa0. |
| 0x7 | 1 | u8 | unk_0x07 |
0 in every block. Not read. | confirmed | C# scan, all blocks. |
| 0x8 | to alignment |
raw[n] | padding |
Zeros. | confirmed | C# scan, all blocks. |
alignment |
size |
raw[size] |
content |
The record's data, read in place: see Record types. | confirmed | C# scan; 0x14005bfa0. |
Layout rules
arcrebuild.cs writes each ARC from its parsed fields with these rules, nested ARCs first, and the result is confirmed byte-identical for all 220 top-level ARCs (474 in all, every nested one included), with the zero padding as described:
- Header (0x30 bytes),
offsets, zeros to a multiple of 32. - The records in order, each padded to a multiple of 32, with
filename_hashandfilename_lengthcomputed from the name. - The data blocks in
offsetsorder (the same as record order). Each starts at the end of the previous content (for the first, the end of the records) rounded up to the block'salignment, measured from the ARC's start. - The ARC ends at the last content's end rounded up to the largest
alignmentamong its blocks (32 when it has none: the emptycommon_x4.pacis 0x40 bytes). A nested ARC's blocksizeis this padded length. - Outside: a
pakdentry holding an ARC adds its usual 16 zero bytes, and theBMAR104\0prefix 8 (containers.md).
likely: the game needs only rules 1–3's offsets to be right, not the padding: it reads offsets, filename_length and each block's alignment, never an ARC's length. Alignment above 16 is relative to the ARC's start, and a pakd entry is only 16-aligned (menu_layout.dat's first entry is at 0x130), so nothing in memory relies on more. Source: How the game reads it.
Record types
| Tag | In | Content | Read by | Confidence |
|---|---|---|---|---|
bin |
sh_tacos.pac, <shader>.pac, the text-preset archives |
A nested ARC (all 212). | Shader package: 0x1400b1240, 0x1400b13b0, 0x1400b14c0 (only bin records). Text presets: 0x14008b680. |
confirmed (content); likely (reader) |
SHG |
BlShaderArchive |
A nested ARC BlShaderGroup. |
0x1400b0b80 (counts and walks SHG records by type index). |
confirmed (content); likely (reader) |
SARC |
BlShaderGroup (record 0) |
The shader group's description, 0x10C bytes (below). | 0x140072f40, 0x1400730e0 (find SARC ID 0). |
confirmed (content); likely (reader) |
SAEX |
BlShaderGroup |
Not in the game's files; optional, looked up after SARC. |
0x1400730e0. |
likely |
SHP |
BlShaderGroup |
One compiled shader variant: a key, a size and a DXBC blob (below). | 0x140073380 (every SHP). |
confirmed (content); likely (reader) |
lyt |
layout archives (CrowleyArchiveDatas in menu_layout.dat, menu_parts.dat), always record 0 |
A bl::lyt layout: starts 01 03 0D 00 (a version the game compares to 0x140caa70c), the layout from +0x10. |
0x1400bc530 (by index or by name), 0x14008ad70, 0x1402725d0. |
confirmed (bytes); likely (reader) |
tex |
layout archives and texture packs | A btx texture (all 5,313). |
0x1400640b0 (by tex + name, extension ignored). |
confirmed (content); likely (reader) |
lpj |
fontset.dat's archive (fontset), and each text preset's inner archive |
Font set: starts 01 00 00 00 (compared to 0x140caa71c), data from +0x10, font names per language. Text presets: a binary preset. |
0x14008b740 (font set, by name fontset); 0x14008bba0 (presets). |
confirmed (bytes); likely (reader) |
BML, BMD, BMA, BMT |
BladeModelPac |
Chunk chains starting BML, mad, ANHD, BMT (BMAR). |
Model code, not traced. BMT (and pac) records are also searched for textures by 0x1400642a0. |
confirmed (bytes); guess (meaning) |
MDL |
(none in the game's files) | A model. | 0x140038570 checks for one. |
likely |
cmp\0 content (compressed, below) never occurs. Source for every "content" claim: arcrebuild.cs, all files.
How the game reads it
Static analysis only, so every fact is at most likely; functions are in the names list.
-
likely: every ARC is read in place from the buffer it was loaded in; nothing is copied or relocated. A reader checks
magicandversion, takes the records fromalign32(0x30 + 4 × offset_count), steps throughrecord_countof them byfilename_length, and for a match returns the block's content (ARC + offsets[offset_index] + align(8, alignment)), itssize, its ID, its name andunk_0x06. Source:0x14005bfa0, with0x14005c0c0(magic and version) and0x14005bf30(record_count). -
likely: a record is found by a "traverser" that tests each record in order and stops at the first match:
Traverser Matches Source type + ID type,unk_0x0C, and the ID (id_u32whenuses_id_u32, elseid_u16)0x14005bc00type + index typeandunk_0x0C; the n-th such record0x14005bef0(counting:0x14005bed0)name unk_0x0C; with the exact flag alsofilename_hash; then the first two characters; then, with the exact flag, the whole name, and without it the name up to its extension (.), sofontsetwould also findfontset.lpj0x14005bc30type + name type, then as name0x14005bd70 -
likely: no reader checks
record_countagainstoffset_count, an offset or size against the buffer,archive_name, the padding, orunk_0x0A,unk_0x0C,unk_0x0F,unk_0x07. A wrong offset orfilename_lengthreads out of bounds. Source: the functions above. -
likely: a block whose content starts
cmp\0is decompressed before use when a caller asks for it (Compressed content). Source:0x14005c210,0x14005c0f0,0x1400b1240.
The menu files
- likely: at startup
0x140271250loads, all throughFileTable_OpenById(group 500) and unwrap kind 1, every entry of eachpakd, the entry's length taken as the next offset minus its own: the text presets0x2815–0x2816(menu/text/), the font set0x2817(looked up by namefontset, exact, through0x14008b740), the texture packs0x2814,0x2818–0x2829and the language folders'0x282A + language,0x2832 + …etc. (0x140272450, each entry to the common-texture list),menu_parts.dat0x2811(each entry'slytrecord registered by name,0x14008ad70, which returns after the firstlytrecord it finds),menu_layout.dat0x2802(0x1402725d0) andtex_common_x4.dat0x2813. Source: decompiled0x140271250; file IDs fromFileTable.bin(filetable.md). - likely:
menu_layout.dat's entries 0–18 are taken by position as the 19 layouts the game names in its table at0x140c98fd0:mn_common,mn_commonwin,mn_itemicon,mn_event,mn_bt_main,mn_status,mn_organize,mn_at_organize,mn_shop2,mn_warrenreport,mn_datainstall,mn_title,mn_option,mn_input,mn_world,mn_bt_result,mn_network,mn_birthday,mn_key_layout. Each later entry is named by its archive's firstlytrecord. confirmed: entries 0–18'slytrecords carry exactly these names, in this order, and entries 19–68 each hold onelyt(mn_advertise…test_command_data). Source:0x1402725d0;arclist.cs. - likely: a layout's textures are found by name in its own archive (
texrecords) and then in the loaded texture packs, bytex+ name with the extension ignored; recordspacorBMTwhose content is an ARC are searched too. Source:0x1400640b0,0x1400642a0.
So the names are what binds things: a modder can add, remove or reorder tex records and resize their btx content freely, as long as the names the layout uses still resolve, and must keep menu_layout.dat's first 19 entries in order.
Compressed content
- likely: content starting
cmp\0is compressed: a u32 compressor tag at +4 (zliborlzma, matched by the two registered decompressors), the uncompressed size at +0xC, and the compressed data from +0x10 to the end of the block.zlibis inflated with zlib 1.2.11 (window bits 31 if it starts1F 8B 08, a gzip header, else 15: a zlib header);lzmareads 5 bytes of LZMA properties, then the stream. The output is allocated 128-aligned. Source:0x14005c0f0,0x140087190,0x140087550,0x140087480,0x1400876d0,0x140087530. - confirmed: no ARC in the game's files has compressed content. Source:
arcrebuild.cs, all files.
The shader package
Shaders/Shader.dat is RotXor + ZIP like the other .dat files, but it is not in FileTable.bin (confirmed: its path isn't in the file) and the game reads it by path.
- likely:
BladeGraphicsManager(0x140163d10) runs0x1401646f0, which readsData/Shaders/Shader.datwhole with0x1401973b0(its size from the file system), deobfuscates it in place with the three RotXor steps, inflates the ZIP member from the local header (raw DEFLATE,method0 copies), and hands the result to0x1400b1240(Ghidra:ShaderLibUtil::constructCustomShaders' traverser). The length it passes is the file's size, not the member's; nothing reads it unless the package iscmp. Source: decompiled0x1401646f0. - likely:
0x1400b1240walks everybinrecord ofsh_tacos.pac; each must hold an ARC (<shader>.pac), whosebinrecords each hold aBlShaderArchive;0x1400b0b80counts that archive'sSHGrecords and registers eachBlShaderGroupthrough0x140072f40, which finds theSARC(type + ID 0) and files the group under theSARC's name in the shader database slot for itskind;0x1400730e0then adds everySHPunder itsvariant_key. Record names and IDs above theSARClevel aren't used. Source: the functions named. - likely: the game asks for shaders by name (
0x1401646f0creates aShaderBladefor each of its names; the names are hashed at startup, overview). 19 of the 21 names in the package are in that list;color_adjustandmodelare looked up elsewhere, and the list'scopyisn't in the package (probably built in: the executable carries its ownBlShaderArchives, e.g.text_*.pac). Source:0x1401646f0;shaderscan.cs.
Every shader has two <shader>.pac records: ID 0 holds the pixel-shader group (SARC kind 2) and ID 1 the vertex-shader group (kind 0). confirmed for all 21. Source: shaderscan.cs.
SARC
The 0x10C-byte content of a SARC record.
| Offset | Size | Type | Name | Meaning | Confidence | Source |
|---|---|---|---|---|---|---|
| 0x000 | 256 | raw[256] | name |
The shader's name (bg, unit_outline_2d, …), NUL-terminated, zero-padded. The group is registered under it. Equals the enclosing <shader>.pac record's name in all 42. |
confirmed (values); likely (use) | shaderscan.cs, all 42; 0x140072f40, 0x140073ec0. |
| 0x100 | 4 | u32 | variant_count |
Number of SHP records in the group: 1, 2 or 8. |
confirmed | shaderscan.cs, all 42 (equals the SHP count); 0x1400730e0. |
| 0x104 | 4 | u32 | variant_mask |
0, 0x1, 0x100 or 0x800101: the OR of the group's SHP variant_keys. Copied into the group (+0x2C). |
confirmed (values); guess (meaning) | shaderscan.cs, all 42; 0x1400730e0. |
| 0x108 | 4 | u32 | kind |
Shader stage: 0 vertex, 2 pixel (1 is probably geometry; unused). Its low byte picks the shader-database slot. | confirmed (values match the DXBC types); likely (use) | shaderscan.cs; 0x140072f40 (byte at +0x108). |
SHP
| Offset | Size | Type | Name | Meaning | Confidence | Source |
|---|---|---|---|---|---|---|
| 0x0 | 4 | u32 | variant_key |
Which variant this is: 0, 1, 0x100, 0x101, 0x800000, 0x800001, 0x800100, 0x800101 (the last four only in model). |
confirmed (values); likely (use) | shaderscan.cs, all 57; 0x140073380 (FUN_1400504a0(group, key, …)). |
| 0x4 | 4 | u32 | dxbc_size |
Size of dxbc. The block's size is dxbc_size + 8 and the DXBC's own total-size field equals it in all 57. |
confirmed | shaderscan.cs, all 57. |
| 0x8 | dxbc_size |
raw[dxbc_size] |
dxbc |
A compiled Direct3D 11 shader (DXBC container, shader model 5.0, SHEX chunk): pixel shaders in kind 2 groups, vertex shaders in kind 0. Read as a CompressibleData (could be cmp). |
confirmed (format); likely (use) | shaderscan.cs (container header and SHEX version token); 0x140073380. |
guess: a replaced shader must be a valid DXBC blob from Microsoft's compiler (fxc or D3DCompile, target vs_5_0 / ps_5_0), with its constant buffers and input layout compatible with what the game binds; a hand-edited blob would need its DXBC checksum recomputed (vkd3d's DXBC parser rejects a bad one unless told to ignore it: vkd3d MR 582, checked 2026-10-11). Whether Direct3D 11 itself rejects a bad checksum is untested.
BMAR models
worldmap/Worldmap.dat#28 is BMAR + 104\0 + an ARC BladeModelPac with four records, all named worldModel00: BML, BMD, BMA, BMT, in 16-aligned blocks. Their contents are chains of chunks: a u32 tag, a u32 size, a byte, a flags byte (bit 0: byte-swapped), a u16 alignment, the content at the next multiple of the alignment, and the next chunk at the content's end rounded up to 4; a chunk with tag 0 and size 0 ends the chain (NODE, DATA, … inside BML). Pointer fixups are applied from a POF0 chunk. likely, from 0x140037f40 (next chunk), 0x14005ba90 (POF0 fixups) and 0x140038570 (the model check: version 104\0, then either MDL\0 or BMAR with an ARC holding an MDL record). confirmed: the ARC part rebuilds byte for byte with the layout rules. The model formats are Leads.
Rebuilding
Rebuild an ARC from its records and contents with the layout rules; unchanged data comes back byte for byte (confirmed, 220/220). For an edited ARC (a changed layout, an added or resized texture) the game needs, likely:
magicARC\0andversion0x0100;record_count,offsets, and each record'sfilename_lengthandoffset_indexconsistent;- each block's
alignmentandsizeright (nested ARCs andbtxare read through them); - the record
types, names and IDs the game looks up:bin/SHG/SARC(ID 0)/SHPin the shader package, the first recordlytin a layout archive,lpjnamedfontset,texnames a layout uses; filename_hashright wherever a lookup asks for an exact name (the font set); the rebuild always computes it.
It need not be byte-identical: the padding, archive_name, unk_0x0A and unk_0x0C aren't read. A changed ARC changes its pakd entry and so its .dat's size, which needs the FileTable.bin entry updated (filetable.md), except Shaders/Shader.dat, which is read by path.
Leads
- The
lytlayout format (version01 03 0D 00), thelpjfont-set and text-preset formats:bl::lyt(0x14008a230,0x1400bc530,0x14008af00,0x14008bba0). Needed to edit menu layouts beyond swapping textures. - The
BML/BMD/BMA/BMTchunk formats and what readsWorldmap.dat#28(model and animation tagsMTXP,TXTR,MESH,MATE,INFO,ANMS,ANSK,ANMT,ANVS,NODE,DATAin0x140038c90and0x14004b1a0). - What
unk_0x0C(the lookup sub-kind) andunk_0x06(handed to callers) are for when non-zero, and the meaning ofvariant_keybits inSHP. - Test in game that a rebuilt
menu_layout.datwith a resized texture, and aShader.datwith a recompiled shader, load. - Walkers: the record walkers take an object whose first field is the ARC pointer, and the traversers derive from
bl::archive::ArchiveAccessor::Traverser, so they are probablyArchiveAccessormethods; nothing ties the method names yet, so the names list keepsArchive_*. - The executable's own
BlShaderArchives (text_*.pac,tonemapping*.pac, …, near0x1406b10f0and0x140808000): built-in engine shaders, not game files.