Player Actions and Special Moves - smeagol44/MKMSZ-Randomizer GitHub Wiki
Player actions and special moves
Scope: This page owns the MKMSZ host-side action/control ABI: special-action descriptor and installer semantics, scheduler/context transfer, player movement/animation/strike primitives, callback lifetime and cleanup rules, and durable host-side findings from the Reverse Elbow proof line.
Donor choreography, donor move phases, MKT strike/reaction meanings, no-repel semantics, combo translation, and reusable donor -> MKMSZ mappings are canonical in MKT adapter primitives. The old URL is retained only as a historical supersession stub at Foreign moves and Reptile.
Low Kick descriptor and special-action path
semantic Low Kick 0x80014C60
-> event-4 handler 0x8003C94C
-> descriptor parser 0x8004A0E0
-> matcher 0x80049E60
-> transfer dispatcher 0x80049D14
-> installer 0x80032CD4
The Low Kick table is RAM 0x800B0F68 / ROM 0xB1B68. Corrected 2026-09-26 clean-ROM reconciliation: it contains one active 0x2C-byte record, followed by the zero u16 sentinel at 0x800B0F94. RAM 0x800B0F98 begins the separate High Kick table; it is not a second Low Kick record. The older two-record interpretation is superseded. Any added descriptor still requires separately owned/relocated storage rather than extending through the sentinel into the HK table.
| Offset | Type | MKMSZ host meaning |
|---|---|---|
+0x00/+0x02 |
two u16 |
Legal semantic-button masks |
+0x04 |
u32 |
Transfer selector; stock implemented values 0 and 1 |
+0x08 |
pointer | Optional no-argument condition |
+0x0C |
pointer | No-argument action/process callback |
+0x10 |
u16 |
Input-history window |
+0x12..+0x1C |
six u16 |
Facing-right tokens, zero-terminated |
+0x1E..+0x2A |
seven u16 |
Facing-left tokens, zero-terminated |
Direction tokens are 8=Left and 9=Right. The Reverse Elbow proof used the semantic command Back -> Forward + Low Kick: facing right 8,9,0, facing left 9,8,0, with window 0x10. The donor reason for that command and the donor move choreography belong to MKT adapter primitives.
Horizontal locomotion and facing
Static-confirmed. The main player process at 0x80028F3C owns normal directional locomotion. Controller +0x638 points directly to the remapping-aware semantic input word 0x800BF2EE. In its normal horizontal state, Right (0x2000) and Left (0x8000) are copied to controller +0x68C as the active direction.
The same input classification derives controller +0x704 from actor facing bit +0x8C & 0x10:
- Right stores the facing bit directly;
- Left stores the facing bit XOR
0x10.
The result is direction-independent: +0x704 == 0 means the requested horizontal direction matches current facing, while nonzero means it opposes current facing.
At 0x800293B0, stock branches on this marker:
+0x704 == 0
-> 0x8002EAFC run check
-> 0x80030178 forward locomotion setup
-> selector 1 / primary slot 0x01 walk_forward
+0x704 != 0
-> 0x80030208 backward locomotion setup
-> selector 2 / primary slot 0x02 walk_backward
Both setup helpers preserve fighter-specific speed tables and stock movement state. 0x80030178 writes the forward parameters and returns 1; 0x80030208 writes the backward parameters and returns 2. The selected value is shadowed in controller +0x680 before 0x8002FE54 installs the corresponding animation.
The stock facing-flip primitive is 0x8003188C(actor). It toggles only actor +0x8C bit 0x10 and then calls the normal frame/setup path 0x8001BDA0 with actor +0x74. Future control work should use this primitive rather than writing the facing bit directly.
Turn / facing-lock design seam
Semantic Turn/Combine is bit 0x0001. The player controller is wired to the remapping-aware semantic input word 0x800BF2EE through controller +0x638 during player construction. Inventory code at 0x8007764C separately reads that same semantic word and masks 0x0001 for Combine, so a modern-control implementation must not globally clear or remap Turn; inventory Combine behavior must remain context-local and stock.
The stock gameplay turn-action routine at 0x8003D86C selects primary animation slot 0x03, the canonical turn animation, and runs the native turn-action sequence. Because the routine operates through the current controller rather than being intrinsically player-only, a control-assist proof should suppress the standalone turn only when current controller +0x638 == 0x800BF2EE; this preserves non-player/native users while making held Turn available as the player-facing modifier.
The accepted control-assist direction is gameplay-local:
requested direction matches facing
-> vanilla forward path
requested direction opposes facing
+ Turn held
-> vanilla backward path
+ Turn not held
-> stock facing flip
-> stock forward/run path
This preserves the native backward-walk implementation as an intentional Facing Lock / Backpedal modifier instead of recreating it. The ordinary stock turn-action state is distinct from inventory handling and must be suppressed or bypassed for this mode so holding Turn can function as a modifier rather than immediately consuming the press as a standalone turn.
While a walk is already active, stock polls controller+0x68C & semantic_input. Releasing/changing the active direction exits through the normal stop/cleanup path and the next locomotion entry recomputes direction/facing. A first proof may therefore tolerate a one-tick re-entry on reversal, but release of Turn during an already-active backward walk needs an explicit check if the desired modifier semantics are to switch immediately back to auto-facing without requiring a direction repress.
Smallest proof contract
A bounded proof can stay almost entirely inside stock locomotion semantics:
after stock computes controller +0x704:
if +0x704 == 0:
leave stock forward path unchanged
else if Turn/Combine bit 0x0001 is held:
leave stock backward path unchanged
else if nearest opponent has +0x6BC & 0x0200:
leave stock forced-facing behavior unchanged
else:
0x8003188C(player_actor)
controller +0x704 = 0
resume stock forward/run selection
The same proof must player-gate the standalone 0x8003D86C turn action so a held Turn press does not itself consume control before horizontal locomotion sees it. Inventory Combine is outside that gameplay action path and remains vanilla. Earth boss behavior is an explicit manual test item because the generic 0x0200 policy is not statically universal.
Stock forced-facing exception
Shared host routines use opponent-controller +0x6BC bit 0x0200 as a gate for automatic 0x80031EF0 face-opponent behavior. The stock fighter-characteristics table sets this bit for several special/boss fighter types, including the documented Wind 0x08, Water 0x0B, Fire 0x0C, and Fortress 0x1B/0x1D encounters. This is a face-policy flag, not a proven universal "boss bit"; other special types also carry it.
Earth type 0x19 is a separate unresolved exception. Its stock characteristics-table word is zero, and the Earth custom boss constructor at overlay VA 0x802EDF50 (Earth overlay file 0x9C) bypasses the generic fighter-characteristics initialization: it manually installs type 0x19 at actor +0x78. A direct audit of the Earth overlay finds neither a +0x6BC write nor a direct call to 0x80031EF0 in that boss constructor/overlay. Therefore +0x6BC & 0x0200 is not yet proven to detect the Earth boss, and it must not be documented or implemented as a universal boss bit.
For the first modern-facing proof, the safe static rule is: defer completely to stock when the nearest opponent carries +0x6BC & 0x0200; test Earth separately. If Earth runtime behavior still auto-faces as expected, capture that route and trace its distinct mechanism before production integration instead of hard-coding a stage ID.
Direction-facing proof v01/v02
The first expansion-loaded control proof uses a proof-only file-0x1A module in the 15 KiB expansion pool and enters freshly loaded code only through uncached KSEG1 trampolines.
- v01 β Rejected / failed. Pressing the first opposite horizontal direction immediately hard-hung. The proof used current-controller global
0x802FCE20, repeating the already-rejected unsigned-low-immediate interpretation. The actual address is0x802ECE20:lui 0x802Fpaired with signed low immediate0xCE20subtracts0x31E0. - v02 β Runtime-confirmed on the tested route. Changing only that global to
0x802ECE20made the control behavior work as intended: opposite horizontal input flips Sub-Zero and proceeds through stock forward locomotion; holding Turn preserves vanilla backward walking / facing lock. The user reported the corrected behavior worked perfectly and matched the requested control model.
The proof line continued through v10/v06 and has now been promoted into the shared browser/CLI patch core. Runtime-confirmed production composition: TURN: TOGGLE preserves vanilla controls; TURN: LOCK uses the accepted v10 world-direction/facing-lock model, while v06 makes the fragile release/action-install hooks leaf-only and temporarily defers to stock semantics when the bounded controller-list scan finds opponent +0x6BC & 0x0200. The full production build passed both former Temple hang regressions and the first Scorpion forced-facing route. Earth type 0x19 remains Pending and is not generalized from Scorpion.
ATTACK: MODERN semantic input translation
Accepted control contract / proof status. The accepted user-facing setting is ATTACK: CLASSIC / MODERN. The current production frontend/code still names the same durable 0x0400 state bit COMBOS=ASSIST / COMBOS_ASSIST_STATE_MASK; that historical name remains current until production integration. The v04 common proof is Runtime-confirmed on the tested control routes and is the accepted ATTACK: MODERN gameplay baseline. No state-layout migration is required to integrate it.
ATTACK: MODERN is an input-translation layer over stock combat, not a replacement combat engine. The accepted priority is:
| Context | ATTACK: MODERN result | Stock authority preserved |
|---|---|---|
| Blocking + Attack | Low Punch; Block is cancelled directly into the stock LP state | Close LP still reaches the normal grab/throw route |
| Straight jump or somersault + Down + Attack | Air kick semantic | Stock airborne attack states, timing and presentation |
| Straight jump or somersault + Attack | Air punch semantic | Stock airborne attack state |
| Normal grounded control, currently moving backward + Run + Attack | Roundhouse semantic | Stock HK/roundhouse action |
| Normal grounded control, currently moving backward + Attack | Sweep semantic | Stock LK/sweep action |
| Active stock combo | Each Attack press satisfies the stock combo parser's current expected button while the parser retains its own timing, chaining, reaction data and conditions | Final Back requirement remains a real stock condition |
| Otherwise | High Punch | Stock neutral HP path |
Live backward predicate
Controller +0x6FC is not a live "currently walking backward" flag. Stock writes locomotion mode 1 or 2 during forward/backward setup and the value can remain after returning to idle. ATTACK v03 therefore leaked the last walk direction into later attacks: after a backward walk, idle Attack produced kicks; after a forward walk, it produced punches.
v04 instead requires all of the following at the event-0 seam:
- active player input map
0x8009F9E8(normal grounded control); - a horizontal semantic direction is currently held:
Left|Right = 0xA000; - controller
+0x704 != 0, the stock current direction-vs-facing mismatch; - Run bit
0x0004selects Roundhouse; otherwise Sweep.
This makes the predicate about current backward locomotion intent, not historical locomotion setup. It is independent of TURN: TOGGLE / LOCK.
Airborne translation
The event-0 wrapper recognizes both stock airborne control maps:
- straight-air map
0x8009FA00; - somersault map
0x8009F9A0.
With Down 0x4000 held, Attack translates to semantic event 3 and stock chooses the airborne kick path. Without Down, event 0 remains the stock airborne punch. v02 Runtime-confirmed the somersault correction and v04 preserves it.
Stock combo-parser translation
The accepted combo implementation does not synthesize a hard-coded combo or force animation states. The stock parser at 0x8004D764 remains authoritative.
At 0x8004D7A8, stock stores the current expected semantic event into controller +0x71C. The v04 proof hook at VA 0x8004D7AC / ROM 0x0004E3AC changes only the history source while ATTACK: MODERN is active:
- CLASSIC replays stock
sll v0,v0,3and reads the expected event's history; - MODERN uses event-0 / Attack history for that combo record;
- the displaced actor load is replayed;
- the parser's record chaining, windows, misses/expiry, strike/reaction data and condition callbacks remain stock-owned.
The accepted Sub-Zero sequence is therefore Attack x5, then Back+Attack. Back is not synthesized: the final stock Back condition still has to be physically satisfied.
Proof chronology v01-v04
- v01 β Rejected / unsafe composition. Artifact
MKMSZR_attack-modern_common-proof_v01.z64, SHA-256665afc2e60373ad20f009c474089ec28eae61b39d3698c8f9619fbcca6aa65ba, CRC1/CRC2CA215655 / A8146A72. Neutral HP, Block+Attack LP/grab, and ordinary airborne punch were observed; Down+Attack worked only in straight jump; Sweep, Roundhouse and combo failed. Music later accelerated, matching an earlier class of unsafe frontend/runtime corruption symptoms. The exact audio corruption writer was not isolated. The bespoke standalone bootstrap/composition is rejected and was not carried forward. - v02 β Partial Runtime-confirmed / superseded. SHA-256
b36bc02366040cd1b44b780fa5753ece0f10046dbb8629518f824dc130fcea08, CRC1/CRC25A438C7E / AA682D64. Rebuilt on the production Runtime-V2/file-0x1Alifecycle; music remained normal and somersault Down+Attack was fixed. Sweep, Roundhouse and combo still failed because the helper loaded the address0x802C1AC0but omitted the dereference needed to obtain the actual player controller. - v03 β Partial Runtime-confirmed / superseded. Artifact
MKMSZR_attack-modern_common-proof_v03.z64, SHA-256794ded0efcc1907d6899e25c5c01f81ddfbcb585d6deeb5a092342370f352ffd, CRC1/CRC25A438C7E / AA682D64. Adding the missing pointer dereference made Sweep and Roundhouse work, but exposed the sticky-+0x6FCerror: attacks after a completed backward walk kept producing kicks, and the combo still did not work. - v04 β Runtime-confirmed accepted gameplay proof. Artifact
MKMSZR_attack-modern_common-proof_v04.z64, SHA-256914905a6d880c0533fbfc7fce3223d1f248c1f1aaefc437f6b2997b8ed343abc, CRC1/CRC2A8B1BCB0 / C6D26323. v04 replaces the sticky locomotion test with the live normal-map + held-horizontal ++0x704predicate and moves combo assist into the stock parser. The user reported the complete behavior works perfectly: neutral HP, Block+Attack LP/grab, straight-air and somersault attacks, Sweep, Roundhouse, no stale last-direction behavior, and the full Attack x5 -> Back+Attack stock combo. Music remained normal. Runtime confirmation is bounded to the exercised routes; it is not exhaustive stage/enemy coverage.
v04 proof layout and production boundary
v04 extends the existing shared proof file 0x1A only through ROM 0x00F685B0 / runtime 0x801AFDD0, still below the established Toasty runtime base 0x801B0000. Its high-ROM helper layout is proof evidence, not production ownership:
- event helper: ROM
0x00F68410/ runtime0x801AFC30; - inherited Block helper: ROM
0x00F68510/ runtime0x801AFD30; - combo helper: ROM
0x00F68578/ runtime0x801AFD98; - combo trampoline: ROM
0x0009AEC0/ VA0x8009A2C0.
The combo trampoline is inside the production bootstrap-composite ownership range. Its success in the disposable proof does not make that address reusable production space.
Full-composition check v01 (2026-09-26)
Runtime-confirmed, bounded disposable composition. From main 70ac6ba6bf661e6fcbbf4417dffbf2b4881e1f20, build_attack_modern_production_check_v01.py built MKMSZR_attack-modern_full-composition-check_v01.z64 using the clean USA Rev. 0 ROM (SHA-256 9c18254abf6722b95aa782fcd310bd95f6bcf147da66beb77ce32ca90673ffc6), MKT USA Rev. 2 donor (SHA-256 30efdbe266dda8b8b12652a8d0a71b3b4bfec88bdf11ed12c219f5c4e1eaf7bb), and seed ATTACKMODERN01. Output SHA-256 is 797ed2cae81bbe99f9b2a0edd49f535945ece4f4026e12a5208c578871d1105a; CRC1/CRC2 are 4DCE4172 / 5EE0A00D. The user reported βEverything working as expectedβ after the requested manual check. That is confirmation of this artifact, not separately itemized observations for every suggested control, stage, or Toasty trigger; the assistant did not run an emulator.
The builder reuses the exact v04 event, Block, and combo helper bytes (each hash-checked against the accepted v04 proof) after the 0x404-byte production TURN prefix in shared file 0x1A. The low file extends through ROM 0x00F68600 / cached runtime 0x801AFE20; optional Toasty still begins at ROM 0x00F687E0 / runtime 0x801B0000. The event helper occupies 0x801AFC30..0x801AFD2F, Block 0x801AFD30..0x801AFD97, combo 0x801AFDA0..0x801AFDD3, and the capture/event dispatcher 0x801AFDE0..0x801AFE1F. An ordinary no-donor composition was also built and statically checked against the same low file contents; its runtime is untested.
This check does not use v04's conflicting 0x9AEC0 trampoline. It reroutes the already-owned pickup-capture trampoline at ROM [0x9AE18,0x9AE28) through a KSEG1 capture/event dispatcher that preserves the original capture caller's t0 and return address; the event-0 JAL shares that entry. Two guarded, proof-specific frontend tails route Block and combo to their KSEG1 helpers: ROM [0x77688,0x77694) and [0x775D0,0x775DC) respectively. Their hooks preload the high target word in the delay slot. The disposable frontend says ATTACK: CLASSIC / MODERN while reusing durable bit 0x0400 and the existing JUMP dependency. The builder guarded all three stock hook pairs, the production capture stub, shared file/table ownership, both frontend tails, and the label/value pointer; an independent rebuild was byte-identical and the changed-byte audit was bounded to those edits plus header CRC. These guards validate this artifact; they are not yet normal browser/CLI source tests.
Production integration plan
The production integration must preserve v04 semantics exactly; it is not an opportunity to redesign ATTACK: MODERN.
- Frontend/state: reuse durable bit
0x0400; rename the user-facing row fromCOMBOS: CLASSIC / ASSISTtoATTACK: CLASSIC / MODERN. JUMP remains enabled/editable only when ATTACK=MODERN AND SPECIALS=MODERN. An internal constant rename may follow as cleanup, but changing the bit or persistence semantics is unnecessary. - Shared expansion composition: append the ATTACK event, Block and combo helpers after the existing production TURN module through the normal
ExpansionPoolAllocator/ shared file-0x1Acomposition. Do not copy v04's literal proof offsets. The resulting low module must remain below Toasty0x801B0000, and optional Toasty must still start at its established aligned base. - Guarded hook seams: compose the accepted event-0 dispatcher hook, Block-to-LP seam, and combo-parser hook with exact expected-byte guards. CLASSIC paths must replay stock semantics byte-for-byte. The v04 combo-parser seam is ROM
0x0004E3AC/ VA0x8004D7AC; the Block seam remains VA0x80029C48; the event-0 dispatcher seam remains VA0x80014B38. - Production trampoline capacity: do not promote v04's
0x9AEC0proof trampoline. The current bootstrap composite owns that region. Either compose additional KSEG0 trampoline capacity inside an explicitly owned/refactored production region with CI bounds, or establish another production-safe entry mechanism. No zero/padding assumption is sufficient. - Implementation/CI gate: add exact hook guards, helper/classic-fallback tests, state-bit/UI tests, deterministic module packing, expansion-pool bounds, shared file-
0x1Aend checks, and explicit no-overlap assertions against Toasty. Build both ordinary and Toasty-enabled compositions statically. - Disposable production-composition proof: the Toasty-enabled check v01 has a positive user runtime report, and the ordinary no-donor composition has passed static checks. The report does not itemize each suggested manual route; retain that limit when citing it. Carry the accepted composition into the patch core with guarded tests before calling it production.
The v04 semantics and check-v01 composition are accepted runtime proof baselines. The complete ATTACK: MODERN behavior is now in the shared browser/CLI patch core; the later v02 controls/CI4 composition is the bounded full-product runtime baseline.
SPECIALS: MODERN + JUMP: BUTTON control-suite proof line (2026-09-26)
Stock-special reconciliation
A fresh clean-ROM trace reconciled the stock special parser before implementing MODERN recognition. The descriptor parser at 0x8004A0E0 advances records by exactly 0x2C; matcher 0x80049E60, transfer dispatcher 0x80049D14, and callback installer 0x80032CD4 remain the stock authority. The relevant stock commands are:
| Ability | Stock command / route | Native condition/action facts |
|---|---|---|
| Ice Blast | Down -> Forward + LP | LP record at 0x800B0F38; condition 0x8004A304; callback 0x80049C34; normal Ice root 0x8004AB84; tier >=1; cost 0x20 |
| Slide | Back + Block + LP + LK | Direct recognizer 0x8003C9F8, not a descriptor record; callback 0x8003CFAC -> action index 0x10 -> 0x80059FF0; tier >=2; no Ice-resource cost observed in the traced root |
| Directional Ice β Up | Down -> Forward + HK | HK table at 0x800B0F98; condition 0x8004A434; callback 0x80049C84, Ice mode 1; tier >=3; cost 0x20 |
| Directional Ice β Down | Down -> Back + LK | sole LK record at 0x800B0F68; condition 0x8004A4A4; callback 0x80049CB0, Ice mode 2; tier >=3; cost 0x60 |
| Air Ice Blast | Down -> Forward + LP while airborne | same LP callback 0x80049C34, selector 2 -> root 0x8004B1D0; tier >=4; cost 0x20 |
| Ice Clone | Down -> Back + LP | LP record at 0x800B0F0C; condition 0x8004A22C; callback 0x8003CF8C -> action index 4 -> 0x80059750; tier >=5; cost 0x60 |
| Ice Shatter | contextual after two Ice Blasts | Not a standalone special descriptor; qualifying stock attack/reaction paths gate it at tier >=6. MODERN must preserve this contextual behavior rather than assign a Special-button command. |
| Super Slide | Back + Block + LP + HP | Direct recognizer 0x8003CAF4; callback 0x8005A5C0; tier >=7; cost 0x60 |
| Freeze on Contact | Down -> Forward -> Forward + HP | HP record at 0x800B1080; condition 0x8005A9AC; action 0x8005A7B4; tier >=8; cost 0x80 |
| Polar Blast | Forward -> Back -> Back + HP | HP record at 0x800B1054; condition 0x8004A684; action/root 0x8004BD28; tier >=9; cost 0xA6 |
| Spine Rip | Forward -> Down -> Forward + HP | HP record at 0x800B1028; condition 0x8004A514; callback 0x80049BE8; fatality/context checks rather than progression-tier gating |
This reconciliation supersedes the earlier claim that 0x800B0F68 contained two LK records and also corrects the earlier misidentification of the first HP record as Ice Shatter: that record is Spine Rip. Native progression evaluator 0x80074FBC returns tiers 0..9; the established thresholds remain 85, 258, 834, 1410, 2323, 3315, 4503, 5911, and 7354 XP.
Accepted SPECIALS: MODERN mapping
The physical button normally mapped to LP is the Special Button. SPECIALS: CLASSIC leaves vanilla recognition intact. SPECIALS: MODERN bypasses the old directional/chord recognizers for the ordinary special family and uses the following direct mapping while preserving native condition checks, costs, callbacks, scheduler/action ownership, and contextual Ice Shatter behavior:
| Context | MODERN input | Result |
|---|---|---|
| Ground | Special | Ice Blast |
| Ground or air | Back + Special | Ice Clone |
| Ground | Forward + Special | Slide |
| Ground | Block + Forward + Special | Directional Ice β Up |
| Ground | Block + Back + Special | Directional Ice β Down |
| Ground | Action + Special | Freeze on Contact |
| Ground | Run + Forward + Special | Super Slide |
| Ground | Block + Special | Polar Blast |
| Air | Special | Air Ice Blast |
| Fatality context | Block + Run + Special | Spine Rip, only when the native fatality condition accepts |
Forward/Back are facing-relative. The proof explicitly gives airborne Back+Special priority over bare airborne Special so Clone wins instead of Air Ice Blast. The old Up+Special / Down+Special candidates are rejected as ergonomic mappings because their useful window was only the few frames before stock jump/crouch took ownership.
In SPECIALS: MODERN, the Special/LP button itself no longer performs ordinary LP. Block + Attack is the sole accepted LP macro. The temporary Run + Forward + Attack -> LP route was removed from both ATTACK and SPECIALS paths after runtime review and must not return. ATTACK: MODERN also suppresses ordinary raw LP/LK/HK gameplay attacks while leaving semantic history available where stock systems need it.
Block startup cancellation and JUMP: BUTTON
Stock Block startup at 0x80032810 plays its animation synchronously; polling only the later Block loop cannot cancel the wind-up. The earlier v05/v06 helper attempted an equivalent bounded startup loop, but post-v09 reconciliation showed its controller+0x6DC == 0x000B gate was dead on the real player path because the main dispatcher clears +0x6DC at 0x80028F94 before the normal Block call. v10 is the Runtime-confirmed correction: it identifies the exact normal-player caller 0x80029C28 -> 0x80032810 by return address 0x80029C30, retains the actual-player and MODERN-control gates, reproduces stock startup cadence with per-tick polling, and enters the same proven LP route at 0x8002A0B4. The user confirmed the Block transition can now be cancelled correctly.
JUMP: BUTTON uses both LK and HK as Jump. The accepted v05 behavior is runtime-confirmed from standing, forward movement, backward movement, and Run; ordinary D-pad Up no longer initiates those locomotion jumps while BUTTON mode is active. The moving/running route is tied to the native diagonal-jump classifier rather than only the standing Up branch.
Proof v06 extends the accepted behavior to the ledge-hanging state 0x030F: LK or HK invokes the exact native Up action used by the hanging loop. Existing contextual D-pad Up behavior in that ledge state is intentionally left stock. The same v06 state gate allows Block + Forward + Special -> Directional Ice Up while hanging, using the normal facing-relative Forward classification and the stock Directional-Ice-Up condition/cost/action route.
Control proof chronology and accepted baseline
- SPECIALS v01 β partial Runtime-confirmed / superseded.
MKMSZR_specials-modern_common-proof_v01.z64, SHA-256a29f31545fca6279aee2b5a21c762fd562074eb73ce365c57233f8256f3f9109. Core callbacks worked, but Up/Down inputs raced jump/crouch, Air Clone lost priority to Air Ice, and Attack+Special was not a usable LP macro. - SPECIALS v02 β partial Runtime-confirmed / superseded. SHA-256
bc54bc84aada41a83f44f4150a2ae66615087e1d119e2b4b8548055711bd118b. Revised chords and Air Clone worked, but facing-relative Forward/Back was wrong because the proof read the 16-bit fighter-facing field with a 32-bitlw. - SPECIALS v03 β Runtime-confirmed / superseded by later control composition.
MKMSZR_specials-modern_common-proof_v03.z64, SHA-2565511a708945b1c5188176f9afd431d76a2df17241c337ab50ec68a4e118c59fd. Correctlhufacing read fixed both facings; Run+Forward+Attack -> LP was removed, leaving Block+Attack as the sole LP macro. - Controls v04 β partial Runtime-confirmed / superseded.
MKMSZR_controls-modern_final-proof_v04.z64, SHA-256e14efaf99f8ff3a3d8638cd21f9e96ea6464b9b6bc65e59eaef152ad68a895e7. Standing BUTTON jump worked, but moving/running jump and Block-startup cancellation were incomplete. - Controls v05 β Runtime-confirmed / superseded.
MKMSZR_controls-modern_final-proof_v05.z64, SHA-256e4dd8f5caaa9b5d3289fcd3cfcc906aa02827f35b4370357a361588c1aea788f, CRC1/CRC2BF447A12 / 517A0FBC. BUTTON jump behavior was confirmed, but the later v09 retest exposed that the intended Block-startup cancellation gate had never owned the actual player startup path. - Controls v06 β Runtime-confirmed / superseded by v10.
MKMSZR_controls-modern_ledge-extension-proof_v06.z64, SHA-2567ea9cf1d606e303fe04a67bc40e76940a90a3ff6232a8f301a8a35eab809c411, CRC1/CRC28C209838 / 1D5CDE46. Adds ledge-button Jump and ledge Directional Ice Up; all non-Block-startup ATTACK/SPECIALS/JUMP behavior remains inherited by v10. - Controls v09 β Runtime-confirmed frontend baseline.
MKMSZR_controls-run-frontend_common-proof_v09.z64, SHA-256430c16973e247da5d8fd56b4ec9410c160642eed653a59cbd106efed80fa12dd, CRC1/CRC2DAE24212 / 236EC8FA. The clean one-lineTURN / ATTACK / SPECIALS / JUMP / RUN / EXITfrontend, six cursor positions, edits, persistence and existing gameplay were manually validated; RUN gameplay was intentionally absent. - Controls v10 β Runtime-confirmed accepted complete proof baseline.
MKMSZR_controls-run-gameplay_common-proof_v10.z64, SHA-2567081c1f9c4629fd88eab78d3c04d72342960ed404d7494421aa8b1f14ba8b325, CRC1/CRC2A9978A81 / CF350A67. Adds corrected Block-startup cancellation and the final RUN:HOLD/AUTO runtime path on top of v09. The user reported: βIt works perfectly!β This supersedes v06 as the accepted complete control-suite proof baseline.
The SPECIALS/JUMP research builders temporarily forced current XP to 20,000 while SPECIALS: MODERN was active so all native power tiers were immediately testable. That is strictly a proof-only diagnostic convenience and is absent from the browser/CLI product. Production uses the player's real progression state and native tier checks.
Runtime-confirmed progression regression (2026-09-26): the first 16-KiB/CI4 full-product candidate removed the XP-force helper, exposing that MODERN Slide and Super Slide still bypassed their stock progression recognizers and called their action callbacks directly. Static reconciliation confirms these are the only two MODERN progression-sensitive routes that did not already use native condition functions. The corrected v02 production composition routes Slide through stock direct recognizer 0x8003C9F8 (native tier >=2 plus contextual gates) and Super Slide through 0x8003CAF4 (native tier >=7, resource >=0x60, plus contextual gates). The user reported the corrected replacement v02 full-product ROM βWorks perfectly!β It is Runtime-confirmed for the tested progression routes. The accepted seed CONTROLSV10CI4 / MKT Rev. 2 donor build, SHA-256 b12ed90201ab754aac542b7b89458735b5a756f480fffca89c129c0ed3173147, remains the Runtime-confirmed baseline. Current builds intentionally differ only in the approved Toasty four-word TLUT purple polish.
Ice Blast -> Pickup cancel β post-1.0 Runtime-confirmed proof
A bounded 2026-10-02 Wind proof Runtime-confirms the requested normal ground Ice Blast -> Pickup cancel. The proof does not invent a pickup animation or bypass spatial/input checks. Instead, it broadens the ordinary pickup manager's action-eligibility gate at ROM 0x00039AF8 / VA 0x80038EF8: stock pickup state 0x303 remains accepted, and normal Ice is additionally accepted only when controller +0x6F0 == 0x8004AB84 and native Ice mode 0x80111F98 == 0. This excludes Directional Ice modes 1/2; Air Ice uses a different action root.
Only after the stock Pickup input/proximity/facing gates have passed does the proof hook ROM 0x00039BA4 / VA 0x80038FA4, recheck normal Ice, and clear special-action lock 0x800BF308. Stock pickup-manager code then performs the ordinary pickup transition and award path. The user reported the proof worked perfectly on the tested Wind route. This is intentionally 4Fun / Post-1.0, not a 1.0 control requirement and not yet a production allocation/composition.
Reproducer: tools/build_iceblast_pickup_cancel_proof.py. Exact artifact identity, placement-probe context, and evidence limits are in Pickup placement and Ice-Blast cancel proofs.
RUN: HOLD / AUTO β Runtime-confirmed proof semantics
The accepted behavior is now Runtime-confirmed in control-suite v10:
- HOLD: vanilla Run behavior.
- AUTO: ordinary horizontal locomotion defaults to Run; holding the configured/remapped physical Run button acts as a temporary Walk modifier.
- Pressing Run during an already-active AUTO run transitions to Walk without requiring a stop; releasing Run while movement continues returns to Run.
- The real semantic Run bit remains available for Run-based attack/special chords.
- Vanilla full-analog auto-run synthesis remains intact.
- Durable proof state uses bit
0x2000in0x800A60E8; the five-setting frontend persists it across menu exit/re-entry and box switching.
v07 β Rejected / failed. MKMSZR_controls-run-auto_common-proof_v07.z64, SHA-256 a476315ddb64250855f65f7b500597d04f094e448a42942c10af55684d1c67a9. It over-compressed the menu, overwrote ATTACK gameplay tails including Block, globally inverted merged semantic Run, failed live Run->Walk, and broke analog auto-run.
v08 β Rejected / failed. MKMSZR_controls-run-auto_common-proof_v08.z64, SHA-256 1967cbe4902d2b10ddca461714edb8e1fbe229fd61f9f55bf6bfe516d7ecfd4e. Block ownership was repaired, but GAME SETTINGS entry hard-hung because the draw helper reused caller-saved t0 after 0x8001CA88 clobbered it. Its active-run hook at 0x800296E8 was also rejected because it could bypass the accepted running-jump classifier.
v09 β Runtime-confirmed frontend. The corrected frontend rebuilds volatile bases after renderer calls, preserves the ATTACK tails, keeps type-2 cursor indices to 0..3, and maps RUN/EXIT through existing type-0 coordinates. The user confirmed the new menu works and looks correct. RUN state toggling/persistence was confirmed while locomotion intentionally remained stock.
v10 β Runtime-confirmed gameplay. The final runtime design leaves stock predicate 0x8002EAFC byte-for-byte intact. At 0x80015B4C, after remapping but before the later analog-generated Run merge, it snapshots semantic Run bit 0x0004 as the configured physical/remapped Run-button state. The four stock locomotion Run-predicate call sites are wrapped locally: HOLD returns the stock predicate result; AUTO for the actual player returns Run when the physical button is released and Walk when it is held. Active AUTO Run->Walk is interposed at the post-classifier back-edge 0x80029778 / ROM 0x0002A378, after 0x800296E8 -> 0x8002B1F8, preserving running JUMP:BUTTON priority. Walk re-entry uses 0x800293A8, whose accepted TURN decision path reconstructs the needed direction classification.
The v10 standalone no-Toasty proof originally overlapped the earlier CI8 Toasty base. The accepted v02 composition repacks Toasty to CI4 at 0x801B1000, keeps the controls below 0x801B0880, and preserves the 16 KiB arena reservation. The normal shared builder now emits that confirmed composition.
Host action primitives
| Address | Correct MKMSZ meaning |
|---|---|
0x8002B1EC |
Player velocity helper; writes player actor +0x14 and +0x58 |
0x8002B1C0 |
Stop/clear linear motion |
0x80031D00 |
Find nearest opponent controller |
0x80031EF0 |
Face opponent |
0x8002FE54 |
Select animation (table,index) |
0x800304C0 |
Advance animation |
0x8004CF3C |
Fighter strike dispatch |
0x8002BA04 |
Collision/damage/reaction core |
0x80028794 |
Process sleep |
0x800328FC |
Exit action / restore control |
0x8004AA4C |
Scheduler context-transfer shim using table 0x800A1050 |
0x8004AB84 |
Complete ice-projectile action root |
0x80030974 |
Animation token-0x0B secondary-resource actor handler |
0x80031208 |
Facing-aware actor-relative XY adjustment |
0x8004CBC4 |
Projectile child-process bridge; binds staged secondary actor into a new child controller/process |
0x8004CC50 |
Generic projectile flight/collision loop |
0x8004CE6C |
Projectile strike-record resolver |
0x800BF308 |
Special-action lock; native action roots set it |
0x8004B82C is the ice-projectile flight callback. 0x8004CC14 is projectile setup that writes a projectile actor's +0x14 and initializes projectile animation timing through 0x80031724. Neither is the player propulsion helper. The older recommendation to use 0x8004CC14 for player movement is Rejected / failed.
Projectile secondary-actor staging
The stock Zap/Ice path uses two controller fields that alias the same secondary actor at the projectile handoff but serve different lifecycle roles:
- animation token
0x0B -> 0x80030974 -> 0x80034510creates a resource-backed actor and temporarily installs it at current controller+0x6E0; 0x80030974stores that actor at+0x714, restores the owner to+0x6E0, then copies+0x714 -> +0x648;- stock straight-Ice placement at
0x8004AFF8passes+0x648to0x80031208; - the same action later uses
+0x714as the temporary current actor for animation; 0x8004CBC4gives parent+0x714to child controller+0x6E0, tags the actor0x700, and clears parent+0x648.
Therefore +0x648 is the stable secondary-actor working/staging pointer in this setup, while +0x714 is the active/transfer pointer and may be temporarily repurposed before being restored. The v71 postmortem statically rejects the hypothesis that the stock 0x80031208 call positions a different helper actor from the one handed to the projectile child.
Projectile flight callback and velocity seam
The complete v75 host transaction has three independent actors/process lifetimes. The parent 0x8004AB84 saves owner +0x6E4/+0x714, temporarily sets +0x714 to the value loaded from 0x80291C10 (file-0x87 resource base), +0x6E4 to offset 0xF88, and +0x718 to 6, and starts class-0x100 companion and tint processes. 0x8002830C copies this helper context to its child. Helper 0x80060A3C uses script resource+0xFA0 to construct a new primary and mirror actor; it allocates texture slot 0x200..0x2FF and the stock Ice palette, inserts both actors, advances the primary through 0x800304C0, and copies its body to the mirror with mirror +0xFA=0. It removes both through 0x80024B00, sleeps two ticks, releases the texture through 0x8001C424, and exits. Its traced cleanup does not release the acquired palette handle. 0x8004AB0C calls the blue screen tint and exits without creating an actor. The parent restores its saved +0x714 during its sleep. These helper actors are not the subsequently created projectile.
The initial slot-0x24 runner stops at file-0x87 +0xDB4 before the projectile token. Following the companion sleep, parent advance 0x8004AEDC consumes token +0xDB8 and operand +0xDBC, creating the projectile through 0x80030974 -> 0x80034510 -> 0x800281A0/0x80028128. The token sets +0x714=+0x648 to the new actor, gives it owner +0x98, render record +0x7C, fixed texture slot +0x9C=0x24, stock Ice palette selector +0x9E, owner position and flags, and inserts it at 0x80030AC8. The parent places +0x648 with native 0x80031208(+5,+38). On the ordinary straight branch (0x80111F98=0), 0x8004B020 invokes 0x8004B584 and 0x8004B028 jumps over the proof wrapper at 0x8004B040: the wrapper does not bind the normal v75 rocket. 0x8004B584 temporarily makes +0x714 current at +0x6E0 and runs stock 0x800304C0 at 0x8004B5A0, consuming the next Ice entry +0xDC4; then it restores the owner, checks strike, and normally hands +0x714 to class-0x700 child through 0x8004CBC4 (which clears parent +0x648). Other mode/contact branches have separate behavior.
The straight child 0x8004B82C reads file-0x87 +0xFD0 = +0xD90, sets +0x6E4 to the rocket-loop cursor, calls 0x8004CC14 once to set facing velocity and the 0x80031724 rate (+0x6A6=3, +0x6A8=1), and v75's later wrapper sets initial velocity 0x46666 and child callback +0x70C. The generic 0x8004CC50 loop sleeps one tick; 0x8003174C first consumes the countdown and then calls 0x800304C0 on +0xD90, binding the genuine rocket after the earlier Ice frame has been published. The callback changes velocity, not image or palette. This is the observed late, well-formed v75 rocket's actual path. The parent wrapper at 0x8009A210 is reachable from the nonzero-mode branch, so results from the normal straight shot cannot validate its palette store or frame transaction.
0x8001BDA0 stores actor +0x74 (entry), constructs +0x7C's image pointer, dimensions, facing and anchors from +0x98, and with +0x8C bit 0x40 set increments +0xFA to request a texture decode. It refreshes +0x68/+0x80/+0x6A/+0x6C/+0x6E/+0x70 from texture slot +0x9C and palette selector +0x9E. Constructor 0x800281A0 calls it before the token has finalized slot/selector/owner flags, so its first call is not a complete ready-to-render transaction. 0x800185B8 later consumes +0xFA, decodes record +0x7C with 0x8000322C, and queues slot-0x24 upload through 0x8001D6EC; the frame scheduler drains the queue with 0x8001D7F0. 0x80024650 links the actor into the active movement and render list sorted by +0x5C/+0x30; it neither builds the record nor uploads pixels. Both the Ice entry +0x34A58 and rocket entry +0x4E6E4 have a zero preceding descriptor word. On the +0x8C bit 0x40 path, a same-entry bind and a changed-entry bind with that zero word both increment +0xFA and use +0x9C; the earlier claim that same-shape binding skips a necessary rocket rebuild is false for these entries.
In v83 the raw pre-insertion 0x8001BDA0 changes actor +0x74 but leaves controller +0x6E4 on the Ice script, so 0x8004B5A0 replaces that early bind with Ice. v84 redirects +0x6E4 to +0xD90 and advances the rocket before insertion, but also forces selector zero. v88 repeats the early rocket descriptor/cursor advance while preserving the correct dynamic ROCKET_P selector and still shows one frame of corrupted Sektor-like texture. Therefore descriptor/cursor state alone is not enough to guarantee first-published pixel data. The render path makes the distinction explicit: 0x8001BDA0/0x800304C0 marks actor +0xFA dirty, while the active pass at 0x800185B8 later decodes +0x7C, queues the texture-slot upload through 0x8001D6EC, and only the separate queue drain commits it. v89 Runtime-confirms pre-publication texture-slot readiness as the missing seam: native synchronous 0x8001BF70 prepares finalized slot +0x9C before stock list insertion, 0x8001BDA0 refreshes the actor fields, and the user observes immediate correct rocket presentation with no one-frame corrupted Sektor. This establishes that actor descriptor/palette correctness is insufficient until the slot's pixel data is resident before publication.
Palette selection is a distinct resource transaction: token 0x80030974 calls 0x8001C528(0x800B1A24,0x100,0) and stores the returned handle minus 0x80 at actor +0x9E. The player type-4 constructor instead acquires its source via 0x800B13D0[type]: v75 file-0x87 +0x4584C (table entry +0x45848) contains the resident Sektor colors, but its runtime selector is dynamically allocated, ordinarily in 0xC0..0x1BF. Selector zero maps to handle 0x80; it does not mean βthe owner's Sektor palette.β 0x8001BDA0 resolves active +0x80 through 0x80290A02 + selector*8; render upload uses 0x802E73E0 + selector*4. Matching +0x80 to selector zero alone preserves the wrong palette source. 0x8001C64C releases an explicitly owned palette handle when called; neither the traced companion cleanup nor the normal projectile 0x8004CDF8 calls it. The exact contents of slot zero in the runtime captures, and an end-to-end per-shot palette release, are unverified.
Static-confirmed cleanup split: 0x8004CC50 calls 0x8004CDF8 for offscreen/lifetime exit; this removes the projectile actor and terminates the child process. On normal loop return, the Ice child switches scheduler callback to 0x8004BB64. Separately, the parent finishes seven postlaunch animation advances and six sleeps, calls 0x8004B524 to clear 0x800BF308, then 0x800328FC. The companion helper removes its own pair of actors; tint process exits on its own. New donor actions must model each termination path explicitly. The full donor/host map and evidence limits are in MKT adapter primitives.
0x80031394 is not a proven safe drop-in match_ani_points at this seam. Besides copying owner position, its child +0x64 branch can flip facing through 0x8003188C; its other branch dereferences child render record +0x7C and uses anchor offsets. v78 called it on the staged Ice actor before the genuine rocket first descriptor and hard-hung. The exact failing precondition or register state is unresolved, so a generic origin adapter must first establish the actor/descriptor state it requires.
Static-confirmed. The generic projectile flight loop at 0x8004CC50 provides a reusable per-tick callback seam:
loop entry:
child +0x680 = child +0x70C
each flight iteration:
sleep 1
target animation/update work
offscreen/lifetime checks
if child +0x680 != 0:
call child +0x680
resolve strike record
run projectile strike/contact path
For the stock Ice/Sektor proof actor, horizontal projectile velocity is actor +0x14. 0x8004CC14(actor, magnitude, rate) is the one-time facing-aware setup helper used by the stock path and also initializes animation timing through 0x80031724. The flight loop itself does not rewrite actor +0x14 between callback invocations. A translated per-tick acceleration callback can therefore mutate only actor +0x14 while preserving the stock lifecycle and animation-rate state.
This distinction explains the v71 failure mode: repeatedly calling 0x8004CC14 from the tick callback also reinitialized animation timing every tick. Direct per-tick +0x14 mutation is the narrower target operation for the current acceleration proof.
Projectile local-position units
0x80031208 consumes signed local whole-coordinate offsets. On the normal freshly-created projectile path (actor +0xDC == 0), it mirrors local X for actor flip, rotates vector (x,y,0) through the actor-local orientation, and adds the resulting integer components to actor world position +0x2C/+0x30/+0x34 after << 8. Target actor positions are therefore 8-fractional-bit fixed-point while this helper's placement arguments are whole local units. Its matrix normalization is unity; there is no additional target scale factor.
For the current Sektor straight-missile case, the donor's already-N64-scaled retail displacement is definitively semantic X=+5, Y=+38: MKT source multi_adjust_xy applies its second argument to oxpos and third to oypos, and retail make_rocket passes a1=5,a2=38 to the same operation. The X/Y-swap hypothesis is therefore Rejected / failed.
Those values map directly to the target helper's offset arguments (+5,+38), with facing remaining the helper's responsibility. However, complete visible spawn equivalence also depends on the projectile's position before that adjustment. MKT performs setup_proj_obj -> get_proj_obj_m -> match_ani_points(owner, projectile) before applying the offset, while the current target proof inherits stock Ice secondary-actor creation/alignment. Equivalence of those pre-adjust base origins is Pending and is the next relevant placement seam; v72 proves stable mirrored offset application, not full donor-equivalent origin setup.
Projectile velocity integration
Static-confirmed. 0x80017F80 is the actor update/integration loop used by the gameplay main loop. For a normal projectile with actor +0xDC == 0, it reads local velocity fields +0x14/+0x18, arithmetic-shifts them by 8, rotates the resulting local vector through actor orientation, and adds three times the transformed integer components into fixed8 world position +0x2C/+0x30/+0x34.
Therefore, at neutral orientation:
delta_world_x_per_actor_update =
3 * (actor_xvel >> 8) / 256
in world-coordinate units. The low eight velocity bits do not contribute to that update.
The gameplay loop invokes the actor integrator at 0x80014258 and gates the next iteration on the retrace/tick counter at 0x802FCD44; the resulting ordinary rendering/movement cadence is approximately 30 Hz. This is distinct from MKT's 16.16 oxpos += oxvel motion at nominal 60 Hz. The donor-to-target projectile adapter must therefore translate both numeric velocity units and update cadence, not merely copy MKT oxvel.pos values into target actor +0x14.
The exact Sektor resampling policy is owned by MKT adapter primitives. v73 Runtime-confirms that direct per-tick writes to +0x14 are stable, but its raw donor constants are not the final calibrated translation.
The current process/controller pointer is at effective address 0x802ECE20, not 0x802FCE20.
Function-level semantics are indexed in Function registry; this page owns how the helpers compose into the host action lifecycle.
Projectile actor/process host ABI
The v63-v70 Sektor missile work and follow-up static trace expose a target-native projectile split that should be reused by donor adapters rather than treating Ice Blast as one monolithic move.
Static-confirmed target composition:
animation token 0x0B
-> 0x80030974
-> 0x80034510
-> 0x800281A0 -> 0x80028128 ; resource-backed secondary actor
-> stage actor in controller +0x714/+0x648
-> 0x80024650 ; insert actor
0x80031208(actor, dx, dy) ; facing-aware relative placement
0x8004CBC4(callback)
-> 0x8002830C(class 0x700, callback)
-> copy parent/opponent context
-> child +0x6E0 = parent staged actor +0x714
-> tag/clear staging state
This establishes distinct host primitives for resource actor creation, relative placement, and child projectile process creation. The exact function meanings remain indexed in Function registry; donor-side semantics and the reusable adapter vocabulary remain in MKT adapter primitives.
The projectile collision/strike path is likewise separate from Ice freeze presentation: 0x8004CC50 drives the generic projectile loop, 0x8004CE6C resolves a fighter-local strike record from the supplied selector, and 0x8004CF3C -> 0x8002BA04 reaches the normal target strike/collision core. A donor strike index is still not portable numerically.
Resolved player animation cursor
The current controller/process animation cursor is +0x6E4. v69 is Runtime-confirmed for one narrow use: after the stock special helper completes, temporarily redirecting +0x6E4 to the imported chest script, advancing once through 0x800304C0, and restoring the cursor displays the genuine chest-open frame on the player without hanging.
That runtime result proves the host cursor/update mechanism only. It does not make a one-frame post-helper injection the final donor-animation runner.
Installer, scheduler, and context-transfer semantics
0x80032CD4 installs a top-level special-action callback. In the observed installed context, the callback begins with $ra equal to the callback entry. A normal jr ra therefore re-enters the callback instead of returning to an ordinary caller.
0x8004AA4C is not a generic action initializer. It transfers scheduler context according to selector table 0x800A1050. Stock selectors 0..2 are defined. The stable Reverse Elbow v6 proof used a deliberately added selector-3 bridge as a proof-specific controlled extension; that does not make selector 3 a stock ABI entry or a production allocation.
A native special action also needs the target action-lock/cleanup conventions. The successful host-side proof set 0x800BF308, kept its loops bounded, and exited through native scheduler/control restoration.
Callback lifetime and cleanup rules
These are durable host-side safety constraints:
- an installed top-level action callback must not simply return normally;
- every movement/contact wait loop must be bounded;
- action exit must transfer through the native scheduler/cleanup path or an equivalently proven target-native path;
- the native special-action lock must be established/preserved where the action path requires it;
- interruption/contact branches are lifecycle paths and must reach cleanup, not just switch animation;
- one observed state byte is not enough to prove an action is still active after interruption.
These rules come from both successful and failed bounded proofs and are applicable to later donor-adapter work regardless of the specific move choreography.
Durable Reverse Elbow host-side findings
The Reverse Elbow experiments are useful here only for what they established about MKMSZ's host action system.
| Finding | Evidence / implication |
|---|---|
| Early movement interpretation used projectile setup as propulsion | Rejected / failed. 0x8004CC14 is projectile setup; 0x8002B1EC is the player velocity helper. |
| Experimental victim callback could hard-hang on contact | Rejected / failed. Victim/contact work must not be added before its callback/lifetime semantics are understood. |
| v3 hung immediately with or without an enemy | Rejected / failed. Later analysis explains this as installed-callback jr ra self-reentry. |
v5 omitted native special lock 0x800BF308 |
Rejected / failed as a complete lifecycle model; omission is a strong host-side hang risk. |
| v6 used selector-3 bridge + lock + player velocity + bounded loops + native restore | Runtime-confirmed stable lifecycle baseline; repeatable without whole-game hang on the tested route. |
v7 added strike 0x14 and a Y-distance gate |
The Y gate behaved as intended against a jumping enemy; no abnormal jumping-enemy contact was observed on that bounded test. |
v8 attempted velocity 0xD0000, locomotion index controller+0x6E6, per-tick reapply, forced-X crossover +0x3800, and expanded diagnostics |
Not confirmed as an improvement. Runtime testing still showed slow movement/no pass-through; attacks could cancel forward motion while the displayed L 1 state stayed unchanged; expanded HUD diagnostics were absent. These parameters are preserved as failed-proof reproduction data, not accepted movement values. |
The durable conclusion is the v6 lifecycle model, not the v8 movement behavior. Direct player-velocity measurement remains the clean way to separate movement calibration from pass-through, victim-hold, and strike behavior.
The old forced-X crossover attempt is not a reusable host primitive and is not accepted donor behavior. Donor-side pass-through/no-repel semantics are documented in MKT adapter primitives.
Current host-side boundaries
Established:
- descriptor parsing/matching and special-action installation path;
- bounded scheduler sleep/context transfer primitives;
- player velocity/stop/facing helpers;
- animation select/advance helpers and the resolved controller animation cursor at
+0x6E4; - resource-backed secondary-actor construction, facing-aware relative actor placement, and projectile child-process binding;
- generic projectile collision/strike resolution path;
- strike dispatch and collision/reaction entry points;
- native action lock and exit/control restoration;
- callback self-reentry hazard and bounded cleanup requirement.
Not established here:
- a production-ready generic donor action runner;
- generic donor velocity-unit conversion;
- a generic no-repel shim;
- arbitrary donor victim-reaction translation;
- donor animation control-token translation;
- a production-ready generic wrapper that composes the identified projectile actor/process primitives with donor callback/state/effect semantics.
Those translation-layer gaps are tracked in MKT adapter primitives.
Related pages
- MKT adapter primitives β canonical donor choreography and donor -> MKMSZ semantic translation.
- MKT to MKMSZ compatibility layer β accepted genuine-port strategy and compatibility contract.
- Foreign moves and Reptile β historical supersession stub for the retired behavioral-recreation page.
- Function registry β flat canonical function semantics.
- Address and patch-site registry β exact guarded patch sites.
- Memory and allocation map β literal ownership/allocation and proof-vs-production boundaries.