Palette and Recoloring - smeagol44/MKMSZ-Randomizer GitHub Wiki

Palette and recoloring

Scope: This page owns MKMSZR's production player-outfit recoloring behavior, the stable MKMSZ palette/TLUT facts needed by that product feature, and the current palette-configuration boundaries.

Donor-fighter palette conversion and actor-specific palette compatibility are canonical in MKT fighter asset translation. Version-specific Sektor palette proofs, including v60, are canonical in Sektor takeover proof history.

Current production behavior

Sub-Zero's guarded clean-ROM palette record begins at ROM 0x0078E168; the 64 color entries begin at 0x0078E16C. The production recolor changes only the clothing range, palette indices 0x21..0x3F.

MKMSZ source colors are BGR555 halfwords. Production preserves the high control/alpha bit and transforms only the five-bit color channels for the clothing entries. Entries outside the configured clothing range remain untouched.

Supported product modes are:

  • vanilla;
  • named presets;
  • legacy red/green;
  • seed-derived hue;
  • explicit hue;
  • explicit RGB;
  • runtime rainbow.

The source-palette transformation is Runtime-confirmed across multiple modes. Unit coverage checks bounds, channel conversion, determinism, and preservation of untouched entries.

Stable palette / TLUT boundary

The clean-ROM source palette is the stable patching reference. An active runtime TLUT was observed at 0x803BD410 in one proof, but that runtime address is stage/timing dependent and must not replace the stable ROM mapping.

The production recolor is therefore a guarded source-data transformation, not a claim that one fixed runtime TLUT address is globally valid.

Donor-fighter work has established additional palette-binding rules for imported 5-bpp assets and alternate actor palettes. Those conclusions do not redefine the production recolor contract and are maintained in MKT fighter asset translation.

Configuration and determinism boundaries

Palette RNG is isolated from pickup and boot-phrase namespaces. Changing presentation/recolor options must not change item placement.

The current product feature configures the normal player outfit. The title's own 15-color art/edition ramp also follows non-vanilla outfit selections as a separate build-time presentation change; rainbow is a fixed title treatment while the clothing continues its gameplay cycle. Exact title design and acceptance status belong to Presentation and branding. This does not claim a general per-actor palette allocator, automatic conversion of arbitrary donor palettes, or coverage of every alternate/enemy palette route. Those are separate compatibility problems.

Safety constraints

  • Transform only the guarded supported-ROM source palette and the configured clothing indices.
  • Preserve the source word's high control/alpha bit.
  • Do not treat a runtime TLUT address observed in one route as a stable global patch site.
  • Do not reuse donor palette words directly without the explicit donor-to-MKMSZ channel/order conversion owned by the fighter-asset adapter.
  • Presentation RNG changes must remain isolated from gameplay/randomizer RNG namespaces.

Rainbow runtime mode

Production / Runtime-confirmed. The browser and CLI expose rainbow as a normal outfit mode. The original full-composition v01 established the 64-phase palette mechanism; the 2026-09-27 compact-tail all-stage proof then Runtime-confirmed the storage optimization across all eight safe stages, including inventory use, movement, enemy kills, and door interaction.

Disposable full-composition proof:

  • file: MKMSZR_rainbow-outfit_full-proof_v01.z64;
  • SHA-256: 4f9aff72c3f81d20e7f3d8f3e59f07cff8f7c6e5a1c0ce81d1a1bbb91ab92060;
  • CRC1/CRC2: E0AD24EF / 4993529C;
  • seed: RAINBOW64.

The original proof composed the then-current production randomizer systems while excluding Sektor and unrelated proof-only experiments. The user reported the requested manual rainbow/regression test worked successfully. The production module preserves that mechanism exactly.

The rainbow path keeps the established clothing boundary: only palette indices 0x21..0x3F vary. It precomputes 64 full BGR555 palettes distributed around the hue wheel; every non-clothing entry is preserved exactly from the stock Sub-Zero palette in every generated palette.

Unlike the production static recolor, the proof is a runtime palette feature. It hooks native fighter frame setup at 0x8001BDA0, applies only to normal Sub-Zero fighter type 4, and uses the native palette allocation/refcount path so the actor is rebound coherently before the prior palette handle is released. This deliberately avoids treating the route-specific observed TLUT address 0x803BD410 as a stable global write target.

Production composition details:

  • the established first 1 KiB MKMSZR Runtime V2 layout remains 0x801AF420..0x801AF81F inside the current 16 KiB reservation;
  • rainbow phase state uses production state offset +0x48;
  • the frame-time rainbow helper occupies the optional Runtime V2 tail 0x801AF700..0x801AF7CF;
  • stock Sub-Zero file 0x87 remains at retail ROM 0x748920..0x78E2FF and its file-table entry is not repointed;
  • all 15 stock 0x87 load paths allocate exactly +0x2000 bytes and route through an 88-byte wrapper in the already-reserved controls→Toasty gap beginning at 0x801B0880;
  • dedicated raw file 0x92 carries only the 64-palette bank at ROM 0xF20000..0xF21FFF, loaded to fighter_base + 0x459E0;
  • the effective runtime fighter allocation remains 0x479E0, identical to the prior rainbow runtime footprint, while high-ROM rainbow data falls from 0x479E0 to 0x2000, reclaiming 0x459E0 = 285,152 bytes.

The compact-tail proof ROM MKMSZR_rainbow-compact-tail_all-stage-proof_v01.z64 (SHA-256 10095f87a85dd89113817ef33eced68c8b9216fa5360ba80107329f6bd9adabb) was manually validated across all eight safe stages. Other seeds change seeded randomizer content as usual; the rainbow mechanism itself is not seed-randomized.

Related pages