TO:R Data Map

How docs are written

Source
docs/templates/README.md
SHA-256
a9a1599b…d2766e2b

Every doc and schema about the game's data or code (format docs, table and file schemas, executable docs, issue reports) follows these conventions. A new format doc or issue report starts from its template here, keeping its section order (sections that don't apply yet may be left out); a new schema follows schema.md (schema.md). Table and file pages are generated, never written:

Kind Lives in Written by
One doc per file format, <format>.md docs/formats/ hand, from format.md (format.md)
One report per investigated bug or modding problem, R<n>-I<n>-<topic>.md, written to be shared with the modding community docs/issues/ hand or agent, from issue.md (issue.md)
One schema per data table, <name>.yaml: its layout and what we know of each field schemas/ hand or agent, as schema.md (schema.md) says
One schema per game file we know something about as a whole, at its path under Data/ schemas/files/ hand or agent, as schema.md (schema.md#file-schemas) says
One file per value list more than one table uses, <name>.yaml schemas/values/ hand or agent, as schema.md (schema.md#value-lists) says
One page per table schema, <name>.md docs/tables/ tor pages --data data/game --docs docs, from schemas and extracted data
One page per game file, at its path under Data/ docs/files/ tor pages --data data/game --docs docs, from its file schema and extracted data

The toolchain reads the layouts, value lists and entry names in the format docs and schemas, so their shapes below matter. A fix to a table or a file page is made in its schema, then tor pages re-run.

An issue report owns its issue's story: the symptom, reproduction, cause, fix and test results. What it finds about a field or a function also goes in that field's schema or the executable doc, and the report links there. Its For modders section is the one place a finding is simplified on purpose, for players and modders who don't read code.

Notation

Evidence and confidence

Each documented format, field or value says how it was found (tool output, hex inspection, a DuckDB query, static analysis of the executable with the function's address and the tool, in-game test, or, as a cross-check only (Reference tools), an outside source with its URL or repo path and the date checked) and how sure we are: confirmed, likely or guess, kept visibly apart. A fact found only by static analysis is at most likely until a decode or an in-game test confirms it. Prose facts mark their confidence in bold: confirmed:, likely:, guess:.

Evidence block

A two-column table right after a doc's opening line. It covers the whole doc; individual facts still carry their own confidence, and their own source where it differs. A generated page's is generated: a file page's holds the file's SHA-256, and a table page's links the file pages of every file its schema matches; another doc relying on a file that has a page links to that page instead of repeating the hash (a game patch can change a file, and the hash shows which version the findings describe; findings are then re-verified and updated in place, rule 13 (../rules.md)). A schema has no evidence block: what it would hold is in its keys (name_from, code, a field's code, text and data) or generated.

Row What goes in it Required in
SHA-256 The hash of the game file. File pages
Size on disk In bytes. File pages
Based on The game files examined, each linked to its page if there is one. For a sample, how it was chosen. Every other doc
Checked Date of the inspection, YYYY-MM-DD. All
Method Tools and techniques: decrypting, hex inspection, DuckDB queries, static analysis, in-game test. All
Name from Where the doc's name comes from (Names): the game's own name and where it is, or what the code or data shows, cited. Format docs; table pages, from the schema's name_from
Round trip How many entries the page's layout covers rebuilt byte for byte in the recorded binary verification, and the date. Table pages

Docs may add rows (a file page's Wrapping and Payload, say). Table pages add Entry path, Rows × size, Schema and Code.

A passing round trip proves that every byte is kept and that the layout fits every file it covers, not what a field means. It supports byte preservation and rebuild rules; it does not establish field boundaries, signedness or meanings. Those claims keep their own evidence and confidence.

Reference tools

The tools in reference_tools/ (Gibbed's tools, Nightmare and its modules) and the docs in legacy/ are references: consult them, check our findings against them, and, where the game and our analysis don't show what something is, use what they say to inform our own layouts and names. Whatever they contribute is cited in Source, and no name or layout is copied from them unchecked. Where a reference covers the same bytes, Source says whether it agrees or not: "agrees with Gibbed's arms_data sheet". A fact or name whose only source is a reference is guess, until our own evidence confirms or replaces it.

Names

Every name we give (a format, table, entry, field, value, function, file, command or term) follows these rules, so that a name is made once and never redone.

  1. The game's own name first, where it has one: a string or text key in its files, a file or folder name, a magic, a class or source-file name in the executable. Where the name is written down says where it is: a field's Source, a doc's Name from row, a term's row in the glossary. Where the game has two words for one thing, the word in its English text wins, since that's what players and modders read (music, not the code's bgm); the code's word (a text key, class or source file) is used only where the English text has none (clut, vfx) or is ambiguous (tribe), and the glossary lists the other word under Other names.
  2. Otherwise ours, saying what the data does: from what the code does with it (the function's address cited) or what the decoded data shows (the DuckDB query cited).
  3. References inform, they don't decide. Where the game and our analysis don't show what something is, we make our own name from what a reference calls it, marked guess and citing the reference in Source, until our own evidence confirms or replaces it. A reference's name is never copied unchecked; a name we make in our own style may end up the same as theirs, and that's fine. Where a reference names the same thing, the glossary lists that name under Other names, so it can be searched for.
  4. Only words we've checked. A word that claims a scope (local, global), a role, a unit or a direction is used only when the code, the data or a cited reference shows it. Something whose meaning isn't known from any of them is named by where it is: unk_<offset> for a field, unk_<part>_<offset> for a field after a variable-size part (unk_header_end for the one after a pakd's IDs), <file stem>_<index> for a table or entry and <file stem>_<index>_<index> for a nested one (never entry_<n>).
  5. One term per concept, the same in every doc, table, field, function, file and command, and every term in the glossary with what it means and the evidence for its name.
  6. The same kind of thing gets the same kind of name. Tables, fields and values are snake_case.
  7. A generic word is always qualified. A word that means several things (flag, kind, slot, side, version, …) is never used alone: it says where the thing lives or what it belongs to (game flag, unit flag, unwrap kind, equipment slot), and a field that packs yes/no bits is <what>_flags. The glossary lists each qualified form and where the bare word is allowed.

Tables

Types

Type Size Meaning
u8 u16 u32 u64 1/2/4/8 Unsigned integer, little-endian.
s8 s16 s32 s64 1/2/4/8 Signed integer, little-endian.
f32 4 IEEE 754 single.
bool8 1 0 or 1.
bits[a:b] 1/2/4/8 Bits a to b (inclusive, bit 0 = least significant) of the little-endian unsigned integer of Size bytes at Offset; the bits fields that share it give the same Offset and Size.
str_ofs64 8 Offset, relative to the start of the table (its xlce or txte magic), to a NUL-terminated UTF-8 string.
cstr n + 1 An ASCII string of n bytes held in place, then a NUL. Its Size is written `n` + 1, and the fields after it count from n.
T[n] n × size Array of n values of type T.
raw[n] n Bytes with no known structure.
enum8 / enum16 1/2 Integer whose values are listed in a value list: a schema's enum, or a format doc's link from Meaning.

Value lists

A value list (an enum, or the names behind an ID) used by more than one table lives in one place, and each field that uses it names it; a list used by one table stays in its schema or doc. Its names follow Names: the game's own text where it has it, otherwise ours from the code that reads the value. The toolchain names each value with it in the pages and the decoded data.

In a schema, a field names its list with enum (its own schema's enums, or <schema>.<list>), and a field whose value picks a text key names it with text_link: the value picks a row of the linked table, whose str_ofs64 field holds a text key, and that key's English text (localize/LocalizeText_en-us.dat) is the name (schema.md (schema.md#fields)). A key with no English text, or a row past the end, names nothing.

In a format doc, the link in Meaning has one of these forms:

List lives in Link Example
This doc, under a heading See [Name](#heading) See [Codecs](#codecs).
A table's value lists Names: Name (.md#heading) Names: [Comparison](/tables/pgrs#comparison).

A link to another doc without Names: is an ordinary reference, not a value list.

File pages

Each game file has one page at docs/files/<path under Data/> with its extension replaced by .md: battle/battle_data_release.dat → docs/files/battle/battle_data_release.md. docs/files/README.md (hand-written) describes Data/ as a whole.

tor pages writes the whole page on every run, and nothing in it is edited by hand: its title, a marker line saying so, then:

A file schema names a container's entries, where a name is known, in entries: one entry per row ("11", 75/3), or a range or list of them (3–10, 1, 3, … 49) that labels nothing. The generator labels a single entry with its name in the byte map and, for an entry no table schema covers, in its section heading. Each entry's kind, offset, size and row count come from the byte map.

Table pages

Each table schema has one page, docs/tables/<name>.md, that tor pages writes whole on every run from the schema and every matching entry in the complete extracted dataset, whichever file-page selectors the run was given: its description, an evidence block (entry path, row counts and size, the files it's based on with their hashes, the schema, name from, code, checked, method, round trip), Notes, Row ranges, Header, Fields (each field's layout, name, meaning and confidence from the schema, its values over every row, and its source), Value lists and Leads. A page whose schema is gone is deleted.

A file or table page is linked from docs/README.md (../README.md) only once its schema says something; every other doc is linked from there.