OpenKh

This is a centralized place for the documentation and other discoveries about the internal working of Kingdom Hearts games.

View on GitHub

Kingdom Hearts II - IDX (Index file table)

Every game file is packed into an IMG file, a big chunk of data that contains everything. The file that contains information on how the files are stored is the IDX.

Whenever the game wants to load a specific file, the engine uses the IDX as a look-up table to search and retrieve the file needed.

NOTE: This document applies on Playstation 2 version only.

Multiple IDXs

The game does not contain every file in the IMG into a single IDX. Instead the game loads specific IDX based on the situation. This is done in order to improve the table look-up speed and group data files in the disc to improve the seeking time.

KH2.IDX is the common index table, where all the common files are located. This is where all the core content is located.

000{WorldId}.idx is the table for a specific world. Since the gameplay nature of Kingdom Hearts II, every world-specific file can be isolated in their own IDX.

File structure

The entries are stored ordered by the Hash32, so the game can use a binary-search algorithm to improve the table look-up speed even more.

When block is mentioned, it means a ISO9660 block, which is 2048 bytes. Every file in the IMG is block-aligned. The reason for that is because the CD-Drive reads the content using a 2048 length buffer.

When a file is streamed, it means that the engine should progressively load the file chunk by chunk instead of storing it entirely in the memory data. This is true for VAG and video files, since their content is never replayed. As far is known, a streamed file cannot be flagged as compressed.

NOTE: While seems to be logical leaving a file uncompressed to improve performance speed, in PS2-era compressed files loads faster from a disc.

IDX header

Offset Type Description
0 int32 Entry count in the IDX
4 Entry[0..N] Each entry represent a file in the IMG

IDX Entry

Offset Type Description
0 uint32 32-bit hash of the original file name
4 uint16 16-bit hash of the original file name, probably used to avoid hash collision
8 uint16 : 0-13 Number of physical blocks that the file takes. A value of 0 means that it takes 1 block.
8 bool : 14 Positive if the file is compressed.
8 bool : 15 Positive if the file is streamed.
12 int Uncompressed length of the file in bytes.

Kaitai file structure

meta:
  id: kh2_idx
  endian: le
seq:
  - id: num_files
    type: u4
  - id: files
    type: file_entry
    repeat: expr
    repeat-expr: num_files
types:
  file_entry:
    seq:
      - id: main_hash
        type: u4
      - id: second_hash
        type: u2
      - id: flags
        type: u2
        doc: |
            & 0x8000: Verify secondary hash
            & 0x4000: Is compressed
            & 0x3FFF: Compressed size = (flags + 1) * 2048
      - id: offset
        type: s4
        doc: offset in the IMG
      - id: size
        type: s4