Repository navigation
Data Structures and Encodings
Scope: This page is the canonical owner for stable, version-independent record layouts, structure grammar, target codecs, and encoding constraints. Donor-fighter descriptors, palette conversion, Sektor encoder benchmarks, supplemental donor history, and fighter-resource packing belong to MKT fighter asset translation.
| Offset | Size | Meaning | Randomized? |
|---|---|---|---|
+0x00 |
4 | X position | No |
+0x04 |
4 | Y position | No |
+0x08 |
4 | Z position | No |
+0x0C |
4 | Location metadata | No |
+0x10 |
4 | Type/behavior | Yes |
+0x14 |
4 | Callback parameter/flags. Low 15 bits are passed to the callback; bit 0x8000 is a destination-record activation gate consumed by the pickup manager and masked before callback dispatch. |
Yes |
+0x18 |
4 | Native award callback | Yes |
+0x1C |
4 | Collision extent A | Yes |
+0x20 |
4 | Collision extent B | Yes |
+0x24 |
4 | Stage-local resource selector | Yes |
+0x28 |
4 | Presentation descriptor | Yes |
+0x2C |
4 | Collected flag | No; persisted separately |
The production identity is the contiguous 28-byte slice +0x10..+0x2B. Copying only callback/type is insufficient for correct art and behavior. There are exactly 84 ordinary records: Temple 4, Wind 6, Water 9, Earth 20, Prison 10, Fire 16, Bridge 10, Fortress 9.
Bit-15 ownership (Static-confirmed, 2026-10-01): pickup-manager setup reads raw +0x14 & 0x8000 before actor activation, while callback dispatch at 0x800393BC..0x800393D0 masks the parameter with 0x7FFF. Bridge stage scripts later clear this bit on dynamically activated Omega/Rings/Arrow/Health records, and Fortress boss reward activation uses the same record-level mechanism. Therefore bit 15 belongs to the physical destination record, not to the logical reward callback. A cross-stage materializer must preserve the destination's stock bit-15 state independently of the assigned reward.
Production V2 lives at 0x801AF7D0..0x801AF81F.
| Offset | Meaning |
|---|---|
+0x00 |
Magic MKSV = 0x4D4B5356
|
+0x04 |
Version 2
|
+0x08 |
Total size 0x50
|
+0x0C |
Header size 0x20
|
+0x10 |
Flags; bit 0x0001 = Temple scripted special check collected |
+0x14..+0x1F |
Lifecycle-v06 HP/reason/current-resource snapshots (specific fields/validation owned by the Persistence and Lifecycle page); no longer unused reserved storage |
+0x20 |
Temple ordinary-pickup bitset |
+0x24 |
Wind |
+0x28 |
Water |
+0x2C |
Earth |
+0x30 |
Prison |
+0x34 |
Fire |
+0x38 |
Bridge |
+0x3C |
Fortress |
+0x40 |
Progression rewards acquired, 0..9 |
+0x44 |
Persistent progression XP |
+0x48 |
Rainbow phase word; used only by the rainbow outfit mode |
+0x4C |
Reserved persistent-state word with temporary GAME SETTINGS editor use at 0x801AF81C while editing; not free storage |
Fire's 19 manager ordinals translate to catalog bits as:
[2, 5, 4, FF, FF, FF, 9, 14, 0, 1, 8, 11, 12, 3, 7, 6, 10, 13, 15]
FF ordinals 3, 4, and 5 are special type-4 records and intentionally excluded. Progression count/XP and the Temple scripted-check header flag are separate from these 84 ordinary-pickup persistence bits.
| Address | Words | Meaning |
|---|---|---|
0x800A600C |
10 | Live stock inventory window |
0x800A6048 |
10 | Box 1 backing |
0x800A6070 |
10 | Box 2 backing |
0x800A6098 |
10 | Box 3 backing |
0x800A60C0 |
10 | Box 4 backing |
0x800A60E8 |
1 | Active index bits 0..1, input latch bit 0x0100, and five durable GAME SETTINGS flags: 0x0200 TURN=LOCK, 0x0400 ATTACK=MODERN, 0x0800 SPECIALS=MODERN, 0x1000 JUMP=BUTTON, 0x2000 RUN=AUTO. Current accepted five-setting frontend replaces the old COMBOS label; see Persistence/Inventory lifecycle for prerequisite behavior. |
0x800A60EC |
1 |
MKBX magic |
Empty stock slots use 0xFFFFFFFF. Foreign-stage keys appear in the live window as item 0x08 only; the true item remains in backing storage.
| IDs | Origin stage |
|---|---|
0x0D |
Temple Map |
0x0E..0x10 |
Wind |
0x11..0x13 |
Earth |
0x14..0x16 |
Water |
0x17..0x19 |
Fire |
0x1A..0x1C |
Prison |
0x1D..0x1F |
Bridge |
0x20..0x22 |
Fortress crystals |
0x23 |
Shinnok Amulet; special pickup path |
0x24 |
Tablet; rejected as a safe mask because it is consumable |
Static-confirmed for the normal player locomotion path. These offsets are fields in reusable engine structures, so meanings below are lifecycle-qualified rather than universal labels for every process.
| Structure / offset | Locomotion meaning |
|---|---|
controller +0x638
|
Pointer to semantic input; player construction stores 0x800BF2EE here |
controller +0x68C
|
Active horizontal semantic direction: 0x8000 Left or 0x2000 Right |
controller +0x680
|
During normal walk setup, shadows the temporary 1/2 locomotion selector before +0x6E4 becomes the animation cursor |
fighter process +0x6B2
|
Signed halfword action/physics-in-progress state. Ordinary enemy 0x80071B20 zero-fills +0x638..+0x6D7 before actor construction; 0x800321D0 clears it at entry, increments it before each sleep/animation iteration, then clears it at exit. 0x80032580, 0x80033BB4, 0x800341AC, and other shared callbacks can set it to 1 for bounded loops. 0x8002B690 maps nonzero to 0x8000, zero to 0x4000; reaction transfer 0x8002E078/0x80032CD4 leaves this halfword intact. Its value is process-owned, not actor +0x98 animation-root data. Ordinary slots 0x71..0x74 normalize to process classes 2..5; the normal collision scan selects classes 2..4 as victims. A Slide reaction 0x2D reaches 0x800321D0 on such a victim and creates a nonzero interval, although a later reaction-0 overlap remains unproved. |
controller +0x6BC bit 0x0200
|
Shared fighter face-policy flag used by several host routines to conditionally face a nearest opponent; not a universal boss bit |
controller +0x6E0
|
Current actor pointer |
controller +0x6E4
|
Animation cursor; temporarily receives the forward/back selector immediately before animation selection |
controller +0x6FC
|
Normal locomotion mode written as 1 by forward setup and 2 by backward setup |
controller +0x704
|
In normal horizontal entry, direction-vs-facing mismatch: 0 means forward-compatible, 0x10 means requested direction opposes facing |
actor +0x78
|
Fighter type |
actor +0x8C bit 0x10
|
Horizontal facing bit; clear corresponds to right-facing and set to left-facing in the normal locomotion classifier |
The ordinary player classifier at 0x80029200..0x800292C8 derives +0x704 without searching for a target: Right stores the actor facing bit directly, while Left stores it XOR 0x10. This makes the field a ready-made world-direction/facing mismatch signal for control-assist work.
Streams are big-endian 32-bit words, terminated by 0x0000FFFF, and dispatched for opcodes 0..9 by table 0x800AD7A0. Common spawn opcodes 0, 1, and 9 occupy 0x1C bytes:
| Offset | Meaning |
|---|---|
+0x00 |
Opcode |
+0x04 |
Raw X; stored as -(value << 8) at process +0x714
|
+0x08 |
Raw Y; stored as -(value << 8) at process +0x718
|
+0x0C |
Raw Z; stored as value << 8 at process +0x6F4
|
+0x10 |
Low 16-bit fighter type; process +0x6FC
|
+0x14 |
Low 16-bit remaining/spawn quota |
+0x18 |
Low signed 16-bit activation/proximity mode |
Opcode 6 is 0x20 bytes: a mask at +0x04 is tested against 0x802C1140, then the same six fields occupy +0x08..+0x1C. The stream record ordinal indexes eight-byte state at 0x801AE720 + ordinal*8. Opcodes 3, 4, 7, and 8 set concurrency/count, cooldown, auxiliary +0x704, and flag +0x6F8; opcode 5 exits. Complete gameplay names for opcodes 1, 2, and 9 remain unresolved.
The stage overlay scans these at 0x801114F4, count 0x802E8228. Center/edge coordinates are at +0x00/+0x04/+0x08, extents at +0x0C/+0x10, state at +0x14, flags/opcode at +0x18, and subtype arguments from +0x1C. They are activation/script volumes, not the primary ordinary-enemy list.
The node is 22 words. Four vertex X/Y pairs occur at +0x08/+0x0A, +0x18/+0x1A, +0x28/+0x2A, and +0x38/+0x3A; per-vertex RGBA words are at +0x14, +0x24, +0x34, and +0x44. Allocation is 0x8002018C and submission is 0x8001EAE4.
N64 source colors are 16-bit BGR555 values with a preserved high control/alpha bit. Sub-Zero's 64-color source TLUT begins at ROM 0x78E16C; clothing entries are indices 0x21..0x3F. Those indices define the mapped clothing-transform range; other palettes require independent mappings.
Static-confirmed. MKMSZ image decoder 0x8000322C selects the compression type from header byte +3 (the low byte of the big-endian header word), masked with 0x3F.
- Type
0is raw and returnssrc + 4; a type-0 wrapper therefore requires the low header byte to remain zero. - Fighter type
5uses exact header0x05000000and dispatches through0x80003314 -> 0x80065E00. - Type
5is distinct from ordinary embedded-image type4.
Donor-specific source codecs and conversion pipelines are documented in MKT fighter asset translation.
Static-confirmed; generated fighter use is Runtime-confirmed on bounded Sektor proof routes. Stock Sub-Zero fighter frames in global file ID 0x87 predominantly use native image type 5.
The type-5 wrapper is:
| Offset | Meaning |
|---|---|
+0x00 |
Exact header 0x05000000
|
+0x04 |
Signed image-relative pointer to the type-5 model/dictionary table |
+0x08 |
Packed decode dimensions, high 16 bits height / low 16 bits width |
+0x0C |
Compressed bitstream |
The Type-5 switch arm at 0x80003314 (inside the decoder dispatch function, not a separate function entry) resolves the table pointer and calls 0x80065E00. The output arena reservation is align4(width) * align2(height). A fighter's visible descriptor dimensions may remain unpadded while the type-5 backing buffer uses decoder-aligned dimensions.
The table begins with u16 rows_per_block and u16 model_count, followed by 104-byte model entries. Stock Sub-Zero's main table at file-0x87 offset +0x14AC begins 0002 0004: two rows per block and four models. A model contains:
- a pattern-table relative offset;
- bits per pixel;
- 13 normal-code extra-bit counts;
- three zero-run extra-bit counts;
- 13 pattern-index bases;
- three zero-run bases.
The decoder consumes the stream MSB-first. The first 6 bits select the model. Each output unit is a rows_per_block x 4 pixel block; stock fighter data uses two rows, so ordinary blocks are 2x4 pixels. A 4-bit symbol below 13 selects a normal pattern-index class. Symbols 13..15 encode transparent-block runs. Generated streams use the zero-run relation zero_base + extra + 1 blocks. Pattern entries store the block's palette indices packed at the selected model's bit depth.
- Multiple model records may point to the same physical pattern table while retaining independent normal-class widths/bases and transparent-run classes. The model selector, not physical dictionary duplication, defines the entropy model.
- Generated fighter shapes must begin on a 4-byte boundary. Unaligned generated shape records are known unsafe.
- MKMSZR generated-fighter encoders currently require every normal-pattern class width to satisfy
normal_bits >= 1. Zero-bit normal classes are not established as native-decoder-safe; the guarded requirement is intentionally stronger than the software decoder alone requires. - For lossless generated assets, the build independently decodes every emitted stream and requires exact equality with the selected aligned indexed-pixel target buffer before writing the proof ROM.
- Decode dimensions, visible fighter dimensions, and source-row storage pitch are separate concepts and must not be conflated.
Sektor-specific encoder benchmarks, donor conversion history, palette binding, proof-version storage results, and whole-resource packing policy are owned by MKT fighter asset translation.
Static-confirmed for the fields below. Dynamic texture IDs 0x200..0x2FF index 16-byte records at 0x802E83F0 + id*0x10; backing pointers are stored separately at 0x800ED940[id].
| Offset | Meaning | Evidence |
|---|---|---|
+0x00 |
format/flags word used by 0x8001F7A8 to choose texture-load path |
Static-confirmed |
+0x04 |
backing-capacity width used by 0x8001C2B4 reuse-fit checks |
Static-confirmed |
+0x06 |
backing-capacity height used by reuse-fit checks | Static-confirmed |
+0x08 |
current DRAM source-image width; consumed by 0x8001F7A8 when emitting RDP SetTextureImage
|
Static-confirmed |
+0x0A |
image/allocation height field; exact downstream ownership beyond allocator bookkeeping is not yet fully cataloged | Static-confirmed field write; semantics bounded |
+0x0C |
reuse/lifecycle field; exact semantic name Pending | Static-confirmed as part of allocator reuse eligibility |
+0x0E |
active flag; 1 means active |
Static-confirmed |
For a new dynamic allocation, 0x8001C2B4 rounds requested width up to 32 before allocating backing storage and initially writes that aligned width to both +0x04 and +0x08. Its reuse path can return an inactive record whose +0x04/+0x06 capacity is sufficient without updating +0x08. Stock image-building callers therefore rewrite record+0x08 after allocation with the source image's actual DRAM row width. Toasty v23-v37 omitted that caller-owned initialization; see Toasty visual research.
MKMSZR current documentation · Wiki source: wiki/ · Evidence/archive: ChatGPT Library MKMSZR Research · Product source: smeagol44/MKMSZ-Randomizer
Orientation / Project
- Home
- Contributor start here
- Project status
- 1.0 requirements and roadmap
- Runtime validation status
- Architecture overview
- Research methodology and evidence
- Glossary
Core Technical Reference
- Core runtime and native payload
- Memory and allocation map
- Function registry
- Address and patch-site registry
- Data structures and encodings
- Resource and overlay system
- Address quick reference
- Testing and CI
Randomizer / Product Systems
- Stage flow and selector
- Pickups and stage-local randomization
- Global item materialization and solvability
- Persistence, inventory and lifecycle
- Lifecycle static closure / unbuilt v05
- XP and progression
- Native HUD and UI
- Presentation and branding
- Audio system
- Palette and recoloring
- Web patcher and product
Stage Reference
Gameplay / Enemy / Donor Research
- Enemy randomization
- Player actions and special moves
- MKT compatibility overview
- MKT adapter primitives
- MKT fighter asset translation
- Sub-Zero ↔ Sektor animation mapping
- Sektor takeover proof history
- Toasty audio research
- Toasty visual research
- PS1 research
- N64–PS1 comparison
- N64 -> PS1 port planning and strategy
History / Failures / Superseded Material