Tekken 4’s 2.57 GB archive keeps its index in the executable

How DATA.BIN is laid out, why the index was hard to find, and how files are added to it

Tekken 4 (PS2) stores almost everything in one 2.57 GB file, DATA.BIN, with no index inside it. The index is a 1,121-entry table in the game’s executable, and the archive’s only protection is a reversible flip of each file’s first 4 KB. Both are decoded, every checksum passes, and a modified disc that appends new files to the archive boots and plays.

Tekken 4’s disc holds a 1.9 MB executable and a single 2,695,536,640-byte file, TEKKEN/DATA.BIN. Models, movesets, stages, textures, sound and video are all inside it. There is no file table at the start of it, no recognisable headers, and its first bytes look like noise. For two months the working theory was that it was compressed or encrypted. It’s neither.

Wrong turns first

The early notes record a reasonable but wrong picture:

  • “Compressed, so no index.” Zero padding between high-entropy blocks suggested compression.
  • Image signatures that don’t parse. A scan of the first 128 MB found 29 TIM2 image signatures, and none of them parsed. They were coincidences inside data that is compressed internally, not real images.

The project’s notes kept the lesson: raw signature hits inside packed data are not evidence of anything.

Finding the index

The breakthrough came from the running game rather than the disc. PCSX2 savestates hold the console’s entire 32 MB of main memory. A tool (ramsearch) took 8-byte samples from a savestate’s memory and streamed the whole archive looking for them. Files the game had loaded without changing showed up at known offsets in DATA.BIN, which gave sector positions to look for in the executable.

That found it on 2026-10-20: a table of 1,121 records of 16 bytes at 0x313390 in the executable, preceded by a sentinel record.

FieldTypeMeaning
lbau32First sector, counted from the start of DATA.BIN (sector 401 of the disc)
sizeu32Size in bytes
checku3232-bit sum of the decoded file’s words
id_lou16Record number + 1
id_hiu16Record number + 1, or 0xFFFF for a file stored raw

The records are contiguous and sector-aligned, and the last one ends at sector 1,316,180, which is DATA.BIN’s exact size. 663 records hold data and 458 are empty.

The “encryption”

For a normal record, the first min(size/4, 1024) 32-bit words are stored as w' = (id_hi − 1) − w. Everything after the first 4 KB is plain. Records marked 0xFFFF are stored raw throughout. The transform is its own inverse, so the same function encodes a file for writing back.

The decode routine is at 0x215008–0x215050.

The checksum is the plain 32-bit sum of the decoded file’s whole words. A mismatch fails the load (status −4). Only three load types decode and checksum their data at all. Files the game sends to the sound processor (sound banks, music streams, video) are stored raw and never checked, so a custom sound bank needs neither the flip nor a checksum.

There’s no compression at the archive level. Some files compress their own contents: each fighter’s moveset uses an LZSS codec, described in Tekken 4’s moveset files, decoded and edited in game.

Proving it

Each claim was checked by something that could have contradicted it:

  • Against memory. Record 19, decoded, equals the copy in a savestate’s RAM byte for byte: 480,392 of 480,392 bytes.
  • Against the checksums. Every non-empty record’s decoded words sum to its check value. An independent verifier, writing its own decoder without reusing the project’s scripts, got the same result on all 663.
  • Against the loader. The game never uses record numbers directly. It asks a resolver at 0x196F98 for “file N of kind K”, using a 71-entry table at 0x309760. The verifier wrote its own resolver and matched 2,457 of 2,457 loaded files across 57 savestates, each checked against that savestate’s own copy of the index.

Writing a modified disc

The game reads archive files by absolute sector (401 + lba) through the I/O processor, with no file-system lookup. So a file that grows doesn’t need room in place: it’s appended past the end of the disc image and its index entry is repointed. The project’s mod disc is 13,012,992 bytes longer than the original, and 16 of its 23 changed index entries point past the old end. It boots, and savestates show the appended files resident in memory.

PCSX2 identifies a game by a CRC that is the XOR of every 32-bit word of the executable, and cheats, settings and texture packs are filed under that CRC. Editing the index changes it, so the disc writer XORs the difference into one unused word (0x1D9000, in the debug section, outside the loaded segments). The modified disc keeps the original CRC, 833FE0A4, and with it every existing cheat and patch.

The executable itself can’t grow, so code changes are same-size word edits. No free space for new code has been mapped yet. An 88-byte padding area was already used for the new fighter’s strings.

What’s in the archive

  • 482 distinct contents among the 663 non-empty records. 99 groups are stored more than once, 96.7 MB in all, probably once per game mode’s load set.
  • The 28 video records (47–74) take 78 % of the archive, about 2.1 GB.
  • No gaps and no overlaps between records.

Corrections

The adversarial verification refuted several claims in the first report:

  • Not every record is reached by the game. Records 0, 47–102 (the movie player owns 47–74) and 276–278 are never loaded directly.
  • Video is not loaded purely by the sound processor. Main-processor code at 0x215390/0x2153B0 requests it by index entry (record = 47 + movie number).
  • The mod disc is 13.0 MB longer than stock, not 18.5 MB. 18.5 MB was a test build.
  • The rule that picks player 2’s memory layout is the reverse of what the report said. All fights observed use the large layout.

↑ ↓ move, Enter open Search with filters