Tekken 4’s stage format, and building a new stage from scratch

Geometry, floors, walls, crowds and start positions, decoded far enough to add stage 17

Each Tekken 4 (PS2) stage is four archive files, and the biggest is a 15-section container holding the geometry, textures, floor, walls, crowd and start positions. The geometry and wall formats rebuild the stock stages byte for byte, and a new stage 17, with its own geometry, textures, props and collision, loads and plays in PCSX2.

Tekken 4 has 17 fight stages, and the game reserves table space for 26. This entry describes how a stage is stored, how that was confirmed, and what it took to add a stage 17 with its own geometry rather than a retexture of an existing one. The limits of the format (how big a stage can be, how the crowd is budgeted) are covered by the experiments in How large can a Tekken 4 stage be? Bigger than predicted.

Four files per stage

Stage n is archive records 991 + 4n to 994 + 4n (see Tekken 4’s 2.57 GB archive keeps its index in the executable for the archive):

FileHoldsLoaded to
j0The stage’s sound bankSound RAM at 0x12B090 (at most 213,120 bytes)
j1Character Data for non-player figures (the crowd)A 64 KB window
j2Their motion banksA 256 KB window
j3The stage itself: a 15-section container0xB17440 in versus modes (an address hard-coded in three places), 0xAA1800 in Practice

Stages 0–16 are populated. Records for 17–25 exist with size zero.

The crowd files turned out to reuse the moveset format. All 77 Character Data files across the stock stages parse and rebuild byte-identical with the same tool used for fighters (Tekken 4’s moveset files, decoded and edited in game), so the crowd are fighters that never fight.

The j3 container

j3 starts with a count (15) and fifteen (offset, size) pairs:

SectionHolds
0, 1Crowd models and textures
2Lighting
3The camera’s collision outline (optional, empty on 12 of 17 stages)
4, 5, 6Placement lists: the crowd and locators, hittable objects, and fighter start regions
7Texture banks
8Geometry (MAPTK4)
9Fighter walls
10The floor (UNDNEW)
11A stub
12A packed motion-bank container, role unknown
13, 14Empty

Geometry

The geometry section holds two models: a sky dome (2 nodes, 394 vertices) and the stage. The street stage used as the template has 922 nodes, 9,322 triangle strips, 47,598 vertices and 28,954 triangles.

  • Coordinates. Millimetres, with Y up. The floor is at y = 0 and the fight starts at the origin.
  • Nodes (160 bytes each). A bounding sphere, a 4×4 matrix that is not applied (vertices are already in world space), and 80 bytes of flags and ids.
  • Batches. Each is a GIF register block followed by a VIF stream of colours (8-bit), texture coordinates, normals and positions.

The format was confirmed three ways:

  • The exported mesh’s counts match the header counts exactly.
  • Both models rebuild byte-identical from the parsed form.
  • An adversarial verifier re-derived the counts independently.

The rendering rules came from building, not reading:

  • One trailer entry per batch. Each chunk ends with a trailer that needs one entry per batch. A single entry for a whole node drew only its first strip.
  • Back-face culling. The renderer culls, so the first triangle of each strip must wind so that (v1 − v0) × (v2 − v0) points along the face normal.
  • Material mode at header +0x28. Mode 0 uses the vertex texture coordinates. Mode 7 is a reflection map computed from the view-space normal, which ignores texture coordinates entirely; doubling them changed no pixel. The template stage carried mode 7, which is why the first custom geometry came out wrong.
  • Lighting. Header +0x2C = 0 leaves geometry unlit, and lighting uses the vertex normals.
  • The view is mirrored. Looking north, +x is on the left of the screen.

Walls and floor

Walls (section 9) use a format the notes call MHO:

  • A 0x98-byte header and a table of 0x60-byte objects: a root, floor tiles, walls and solids.
  • Then a grid of cells, each listing the objects it touches.
  • Each face is four corners from y = −5000 to +5000 plus a horizontal normal.
  • The grid size is stored in each file. It ranges from 5×5 to 32×16 cells, with cells 2 to 7 metres across.

The project’s wall writer rebuilds all 17 stock fight-stage wall files byte-identical. Generated with a 400 mm margin, its cell lists miss none of the 7,106 cell references in Namco’s own.

One rule only showed up in game: a wall whose faces wind against their normal is ignored. That has its own entry, Tekken 4 ignores a wall whose faces wind against their normal.

The floor (section 10) is seven lists of surfaces, sorted by flag bits. Type 5 is a plain floor and works in game; the template street’s pavement sits 294 mm above the road. The roles of the other flags are inferred, not tested.

Start positions, variants and the crowd

  • Stage number. It comes from a global at 0x357D5C, not from the setup structure the first report named.
  • Variant. A variant byte (random in arcade mode) picks the stage’s select card and the fighters’ initial start region. The game then re-picks the region nearest the fighters. The first report said the variant also picked lighting or time of day; it doesn’t.
  • The limit table at 0x2B12B0 is a crowd budget: how many crowd figures are drawn, plus distance-fade limits. The first report read it as playable-area limits. The in-game test that settled it is in How large can a Tekken 4 stage be? Bigger than predicted.

Adding stage 17

A new stage needs table entries as well as files:

  • an entry in the stage table at 0x2BC390 (26 slots);
  • a select card (the card table is clamped to 17 entries);
  • an arcade-mode slot (seven round lists at 0x30F2D0);
  • a music id;
  • a crowd budget.

The select-card pictures live in one file that can’t grow: one extra picture blanks the select screen. So stage 17 reuses existing card pictures with a new label.

The stage was then built in stages, each proven in game before the next:

  1. A lift test (2026-10-20). One node of the template stage was raised 400 mm. It floated at knee height and the fighters’ legs passed through it: geometry edits load with no checksum or bounds trouble.
  2. Own geometry and textures (2026-10-21). Street, pavement, building fronts and pillars generated from scratch, rendering with seven new textures.
  3. A real layout. A small-town post office and its surroundings, with sky, lighting, and props that are wall solids, so the fighters collide with them.

Textures needed the most care. The stage’s texture section is a sequence of GS uploads, and the game rebases their addresses by 0x2668 blocks. Rebuilding the uploads in a new arrangement (“repack”) hangs the stage load: a black screen, no music, frozen fighters. Bisecting showed the new images themselves are fine. Keeping the stock upload count and sizes and writing new pictures into the existing slots (“in place”) works. Why the repack hangs is still open.

Corrections

The adversarial verification and the build overturned several readings in the first report:

  • The wall grid isn’t a fixed 16×16 of 3 m cells covering a “48 m window”. It’s set per file.
  • The longest strip isn’t 50 vertices. That was the builder’s own cap; stock strips reach 60.
  • The sound and crowd files are separate buffers, not slots inside j3.
  • The crowd list is section 4, not section 6. Section 6 is the fighter start regions.
  • “7.8 MB of headroom” after the stage file was wrong. The space right after it is live data. How big a stage can really be is the subject of How large can a Tekken 4 stage be? Bigger than predicted.
  • Stages 2 and 5 do upload textures. The original count was a script error.

↑ ↓ move, Enter open Search with filters