case study18 min read$36

I Put MVC2's Hayato Into Marvel vs. Capcom. Here's v0.

Hayato's Dreamcast art, animation records, collision boxes and palettes now render inside stock Marvel vs. Capcom, driven by Hulk's character code. The v0 video, what the render probe measures, the palette rule the hardware forced, and everything that is still not there: no Hayato moves, no download.

cps2marvel-vs-capcommvc2hayatohulk
CPS-2 Reverse EngineeringPart 42 of 43
Browse all writing
On this page

Hayato's plasma sword should be the reason to play this port. That means bringing over the attacks, their full animations, and the objects that make the sword work, not just putting a new idle pose over Hulk.

The target is Hayato in Hulk's slot, with a complete six-button kit. Orange Hulk's secret route becomes Armored Dark Hayato: the same moves, damage and speed, with dark presentation and deliberate one-hit armor. Both must work inside the ordinary two-character MVC1 game, using the original ROM sizes.

This is v0: the first time Hayato is on screen in the stock engine. Every sprite, animation record, collision box and palette that the engine reaches is Hayato's, translated from the Dreamcast data into MVC1's own formats and seated in Hulk's storage. The character code underneath is still Hulk's. That is why v0 is a render probe and not a port: it proves the seat, the formats and the art pipeline on real arcade code, and it does not prove a single Hayato move. There is no playable MVC1 Hayato candidate or download.

Hayato v0 // 2:26 · scripted MAME captures of the render probe · Hulk's character code, Hayato's data · a cut, not evidenceYouTube ↗

What the evidence establishes

5 STOPS · 0 CORRECTED · 0 RETRACTIONS · 0 OPEN
  1. Cable source → shared reader
    Shared tiles = prior tile export

    Pinned Cable tile export and shared-reader regression test

    01 / 5prior artExisting conversion

    Control against Cable

    14,095Cable tiles reproduced exactly

    The shared converter reproduces the older Cable tile export byte for byte before it is used for Hayato.

    Read this section
  2. Hayato victory artwork decoded from the Dreamcast source; not an MVC1 capture

    PL12_DAT sprite controls and PL12_WIN source-art reader

    02 / 5measuredHayato source audit

    Keep the complete source

    4,989 / 4,989sprite pieces round-tripped

    Every source sprite is preserved. The 741 assembled images also match after conversion, including layering and cropped flips.

    COVERAGE 100% OF SOURCE SPRITE PIECES ROUND-TRIPPED, OUT OF 4,989 — NOT GAMEPLAY PARITY

    Read this section
  3. 16,427 exclusive tiles
    14,765 new tile writes
    1,662 tiles remaining

    Fresh canonical-base ownership census and stock packing readback

    03 / 5measuredStock allocation

    Measure the remaining fit

    1,662exclusive graphics tiles still available

    The source sprites fit the measured Hulk-family allocation. Identity art, target behavior, program ownership and sound still need their own budgets and tests.

    Read this section
  4. entry = bitrev4(stored pen)
    colour(e) = MVC2 pen 15 − bitrev4(e)
    entry 15 = transparent

    OBJ/palette RAM dumps of the probe and a stock-Hulk idle re-render control, registered as harness fact cps2_obj_pen_order

    04 / 5measuredFirst probe boot

    The object layer reads pens bit-reversed

    13 / 13probe palette cells matched at distance zero under the reversed rule

    The harness had recorded the rule as a mirror and the first boot scrambled Hayato's colours. OBJ and palette RAM dumps re-measured Cable's four-bit reversal: every visible cell matches at distance zero, and stock Hulk's idle re-renders pixel-exact only under that rule.

    Read this section
  5. Hayato's standing heavy punch rendered by stock Marvel vs. Capcom in MAME 0.287; the HUD still reads HULK

    Observer logs and snapshots from the pinned MAME 0.287 run and the headless MAME 0.264 control and probe runs

    05 / 5measuredv0 render probe

    Hayato renders on the stock engine

    2,892frames on the pinned MAME 0.287, sixteen snapshots, no reset

    Hulk's code requests animation groups and slots; every request lands on the matching Hayato chain through a measured group map. Idle, walks, crouch, jump, all six standing normals, crouching HP, air HK and hit reactions draw with source colours.

    Read this section
  • SOURCE PIXELSnot yet true
  • ON SCREENnot yet true
  • MVC1 GAMEPLAYnot yet true
The coverage line measures source conversion only. No gameplay percentage has been established; the screen lamp means the stock engine draws Hayato's data, not that Hayato plays.These are engineering stages, not a release timeline.

What Cable taught us

Cable's MVC2-to-MVC1 work supplied the extraction techniques: compressed sprite pieces, palettes, assembly coordinates, animation records, and AICA voice data. Those readers were spread across character-specific tools. Hayato now uses shared readers that accept source bytes rather than assuming a Cable directory.

There is a useful control here. The shared converter reproduces Cable's established 14,095-tile binary exactly. That makes it possible to check the extraction work before introducing Hayato's larger sprite set.

The same principle applies to voice and identity art. Decoded samples and face/victory images match the earlier readers. A decoded voice is still missing its gameplay meaning: which action plays it, at what rate, and where it can safely live in MVC1's sound bank.

Keep every frame

The older census reported 33 animation groups but only listed the six normal-attack groups. Its reader also assumed the last group held one slot. Checking the boundary against the first sequence reveals 24 slots in that final table. The current structural inventory follows 341 populated group/slot references, including shared-table aliases, reaching 194 sequences and 1,418 record offsets. Fourteen require the compact eight-byte parser. Seven other starts pass both the eight-byte and twenty-byte validators. The shared effect code now establishes eight-byte consumers for those seven starts; both structural alternatives remain in the evidence.

Every parsed duration, raw event field, sprite reference, and trailer is retained. There are also 56 assemblies outside that known animation graph. They remain in the conversion because a missing reference in an incomplete inventory is not evidence that the art can be discarded.

The native compiler stores all 1,418 decoded records, with private group and slot tables and complete continuation links. Full records keep the source event fields; compact records use a separate reader. Every record and populated selection route passes a 68000 CPU playback check. Those tests use fixture event adapters, so they establish storage and playback behavior without claiming that sword effects, sound or attacks work in MVC1.

Fifteen source animation records showing Hayato's sweeping plasma-sword attack
Dreamcast source render, group 07 slot 01. Record durations come from the source; move timing in MVC1 has not been tested.

This is where Rogue's work replacing Hulk matters. A destination animation cannot be treated as a row of fixed-length placeholders. Hayato's full sequences need storage and routing of their own. Reusing only the first few Hulk records would lose attacks and effects even if a screenshot looked convincing.

The budget is more than tiles

The build starts from the canonical Euro 980123 parent, with all 21 member names, sizes, and hashes pinned. Neither a Cable ROM nor a Rogue ROM becomes Hayato's base.

The fresh ownership calculation reproduces the exact historical 16,427-tile exclusive allocation for Hulk and Orange Hulk together. Hayato needs 14,815 unique source tiles. Fifty already exist among surviving assets, so the measured placement uses 14,765 new slots and leaves 1,662.

That margin is conditional. It does not yet include the final identity surfaces or any new armor artwork. It also says nothing about how many native objects an effect can draw at once.

Lossless horizontal packing and exact sharing reduce the sprite-list and position data from 184,654 to 110,964 bytes. All 741 assemblies now compile with real stock addresses and pass a full geometry readback. That readback caught a position-encoding bug: the wider format still stores relative offsets. Checking the actual stock renderer prevented that mistake from reaching a ROM.

The compiled animation records and their directories use 35,056 bytes. All 142 collision rows and 256 rectangle definitions add 4,320 bytes. Together with the art, that leaves a provisional 94,058 bytes in historically screened program gaps, before the complete move code, translated attack properties, palettes, identity data and final ownership checks. Source voices represent 177,784 bytes at an unresampled eight-bit sample width; playback rates and safe sound allocation remain unknown.

The rectangles also pass 10,752 boundary and flip checks against MVC1's actual collision routine on a 68000 CPU. Ten rows contain special flags whose full behavior still needs mapping. Correct rectangle arithmetic does not establish damage, hit timing, throws or gameplay.

The ownership review also corrected an old scanner error around Venom's adjacent public and secret tables. Six disputed null records were traced to Chun-Li and Shadow Lady. The stock renderer skips their null sprite lists, and the revised scanner follows the subsequent records. Hulk's available tile set stayed the same. Stage, interface, effect, and sound consumers still need review beyond the character trees. Empty bytes alone do not establish safe ownership.

A controllable source reference

A pinned Flycast core now boots the local Dreamcast disc, with its executable and Hayato DAT, voice, face, and win assets checked against the source pins. Ordinary controller inputs reach Hayato and a two-player match. The source route has 45 sealed input probes covering normals, medium chains, special strengths, hypers, and Plasma Combo attempts. Earlier airborne-medium attempts failed; new input sequences reach both airborne mediums, giving all 18 normal selections source-entry observations. Complete branch, contact and recovery behavior remains under review.

Hayato's move code supplied another useful discovery. It lives in six separately linked character executables, one for each team position. Their code matches after accounting for 306 internal address relocations. All six files match the disc, and the loaded executable and dispatch table match 39 sealed captures. This separates the fighter's actual move code from its attachment and geometry data.

Hayato versus Cable in the Dreamcast MVC2 source reference
MVC2 on pinned Flycast, reached through ordinary inputs. This is the source game, not the MVC1 port.

The observations also extend Cable's property-table research: on contact, the struck fighter caches a row from the attacker's S8 table. An animation's aux18 value is not that property index. Three independent repetitions of one medium-punch chain produced identical sampled memory, input logs, and audio. That is a repeatability control for one case, not proof about every random or timing-dependent path.

These captures count emulator calls and display callbacks separately. The internal source updates and hitstop still need tracing before they can establish timing parity.

The record formats are the same lineage

Reading the stock animation reader against the source records settled a question the earlier drafts left open. MVC1's 16-byte record holds flags, a control word whose top bit terminates the chain, a sprite-list pointer, four event bytes, a word the engine copies as it is, and a hit-row index. MVC2's 20-byte record holds the same fields in the same order plus one extra word, aux12, a per-frame event id that carries sounds and spawned objects. The MVC2 collision rows are already eight words in MVC1's own layout, and its 256 box rectangles are four signed shorts each, which is exactly the 2,048-byte box slot Hulk owns.

So the probe translates at compile time: every full record becomes a stock 16-byte record with the event bytes masked the way the stock reader expects, the compact records become zero-length stops, and the tree is written with a word group directory, word slot tables and 16-bit relative offsets inside one 64 KB window, which is how the engine wants to read it. The aux12 events are the one field with no stock home. They are dropped in v0, which is why the probe is silent and spawns nothing, and they will come back through a Hayato-owned side table once Hayato has his own per-frame handler.

The other translation is the group map. Hulk's code asks for animation groups by number, so the question was which of Hayato's 33 source groups each request should reach. Measured live, MVC1 groups 0 to 6 match MVC2 groups 0 to 6, MVC1 groups 8 to 29 reach MVC2 group n − 1, and MVC1 group 7 has no counterpart. Every request the probe logged, from idle and walking through dashes, crouches, standing and crouching normals, an air kick, reactions and a throw, landed on the semantically matching Hayato chain.

The palette order had to be measured again

The first probe boot drew Hayato with his shapes and timing right and his colours scrambled. The palette rows had been written from the harness's recorded palette fact, which said entry p holds source colour 15 − p. Cable's post had measured the real rule months earlier, a four-bit reversal between the decoder's stored pen and the hardware pen at 100% over 3,390 pixels. Somewhere between that post and the shared harness the rule was written down as a mirror, and the probe followed the transcription.

Guessing is cheap and wrong, so the rig repeated the measurement instead of trying colours. It dumped the object layer and palette RAM while the probe stood still and matched every visible Hayato cell against the palette it was drawn from. All thirteen cells matched at distance zero under the reversal and under nothing else: pen 1 reads entry 8, pen 2 reads entry 4, and entry 15 stays transparent. The control that made it a fact rather than a fit was stock Hulk: his idle frame re-renders pixel-exact from the stock tiles under the reversed rule and fails under both alternatives. The palette writer now stores MVC2 colour 15 − bitrev4(e) at entry e, the harness fact is corrected and pinned so the next port inherits the measured rule, and Hayato's colours came out right on the next boot.

Hayato is on screen, on Hulk's code

The render probe is a 21-member ROM set built from the pinned parent by the same builder that compiles the art, with one stage added. It seats the tiles (recomputed and checked against the pinned chip hashes), applies the compiled art, animation and collision bundles, writes the translated record tree into the largest free program run, puts the 256 boxes in Hulk's box slot, points the $06 and $26 directory rows at the Hayato tree and hit rows, and leaves Hulk's private code untouched. Two things run when you pick Hulk: Hulk's brain, and Hayato's body.

The first evidence came from a headless MAME in a cloud container, which is an unpinned emulator and therefore diagnostic only. A stock-Hulk control ran first, with the same observer script, to prove the rig: boot, coin, land on $06, then a fixed schedule of ordinary inputs and sixteen snapshots. The probe then ran the same schedule: 2,715 frames without a watchdog reset, Hayato animating with source colours through idle, walks, crouch, jump, all six standing normals, crouching HP, air HK and hit reactions. I then ran the same observer with the same ROM on my pinned MAME 0.287: 2,892 frames, sixteen snapshots, no reset, the same states, the same colours.

Hayato's standing heavy punch in stock Marvel vs. Capcom on MAME 0.287, the HUD reading HULK
Pinned MAME 0.287, snapshot 8 of 16: standing HP. The name plate still reads HULK because the HUD is one of the identity surfaces v0 does not touch.
Hayato jumping over Ryu's Hadouken in the render probe
The v0 reel: Hayato clears a Hadouken. Hulk's jump code, Hayato's jump frames, Ryu's stock fireball.

The video is a cut of longer scripted captures. An observer script drives every input through MAME's ordinary input ports: Hayato on player one, and on the human player-two seat, which the script reaches by joining as the challenger during a warm-up fight, a scripted Ryu who walks, blocks, sweeps and throws Hadoukens. The reactions chapter is a one-player game against the CPU. Each capture keeps its observer log, and the observer's frame counter is the capture's frame index, checked by taking a snapshot at a known frame and finding it in the recording with zero pixel difference. The rails, captions and cards ride outside the gameplay window; the receipt for the cut records that no overlay pixel lands inside it.

The most useful chapter is the comparison. One input schedule, identical at every frame, runs on the stock ROM and on the probe, and the two recordings sit side by side at the same frame index.

Frame 120 after the round starts on the stock ROM (Hulk, left) and on the render probe (Hayato, right) under the identical input schedule; both heavy punches connect
Same inputs, same frame // stock Hulk's standing HP connects on the left; on the right, Hayato's sword connects from the same input at the same frame. Hulk's timing, Hayato's frames.

That is the honest shape of v0. When the sword lands on the same frame as Hulk's fist, it is because Hulk's attack logic fired and Hayato's frames and boxes were what it drew and tested. When Hayato's reach differs from Hulk's, the fights diverge from that frame on, and the divergence is the data doing something, not the code.

What v0 is not

The video ends on the HULK RYU WIN screen for a reason: it is the clearest single frame of what is missing.

The end of a round in the render probe: the game announces HULK RYU WIN while Hayato's sprite performs the win pose
Hulk's win logic, Hayato's frames, Hulk's name. Identity surfaces, sounds and every special are still Hulk's.
  • The HUD says HULK. Select-screen, life-bar and win-screen names are identity surfaces that v0 does not touch.
  • Every special, hyper, taunt and win pose is still Hulk's move, drawn with whatever Hayato chain the group map reaches. The scripted captures deliberately never input a motion for Hayato, because Gamma Charge wearing Hayato's frames is not a Hayato move.
  • Nothing makes a sound and nothing spawns. The per-frame aux12 events that carry Hayato's sounds and sword objects have no stock field; they wait for Hayato's own handler.
  • Contact uses Hulk's attack properties. Hayato's collision rows are in place, but the property row the struck fighter caches on contact still comes from Hulk's table, so damage and hit timing are Hulk's.
  • Palette roles 3 to 6 are undesigned. Some source cells reference palettes outside the stock three-palette costume window; the dark palette and six selectable colours are not designed.
  • Dark Hayato's armor is lab-tested only. The earlier fifty-update timer is gone. The policy is now a transition latch: one charge per active round, consumed by the first eligible hit, restored only when an attack, jump, dash, block or hit recovery or tag-in finishes and control returns to neutral; cancels, walking, crouching, turning, time and idling never recharge it, and KO, tag-out and round cleanup clear it. Nine CPU tests cover the state machine, the stock eligibility exclusions, the public identity never arming, and the routines leaving damage, speed and every register alone. None of it is bound into the game yet.
  • No download. There is no installer, no release entry and nothing to mistake for a completed port.

The kit and Dark Hayato

The intended controls include standing, crouching, and airborne light, medium, and heavy punches and kicks, command normals, the launcher, air combos, and every Plasma Combo branch. When a special has only established light and heavy source versions, the medium button will use the light version unless the source proves a distinct version.

The named move scope includes Shiden, Guren, Byakko Hou, Rasetsu Zan, Engetsu, Plasma Field, and Black Hayato. The old plan confused two of those: Plasma Field is the temporary power-up; Black Hayato is the level-three attack. The custom Armored Dark Hayato character is separate from that attack.

Input windows, branching, collision, meter behavior, cleanup, and team interactions need completed source mapping and corresponding MVC1 tests. The earlier substituted-I/O NAOMI attract observations remain diagnostic only. Byakko Hou's two-punch command has no established light/heavy split. No final control chart or accepted move count is published here.

Stock MVC1's armor check explicitly selects Hulk, while Orange Hulk skips that path. The Dark Hayato policy described above passes its CPU tests for absorbing one eligible hit, rejecting subsequent hits until a qualifying completion, and leaving damage and speed fields untouched. It still needs its game bindings at the end-of-action return to neutral and the reaction-commit entries, Hayato-owned feedback and complete lifecycle tests; Dark Hayato is not yet playable.

What must happen before release

The next stage is the one v0 was built to make honest: Hayato-owned dispatch. Hulk's nineteen handler-table entries and his private code span become Hayato's, so that the engine's normals, specials, hypers, reactions and lifecycle calls reach Hayato's own routines, with the group map compiled in and the aux12 events delivered from a side table. Then the specials and hypers through the engine's own input-pattern matcher, the sounds, the identity surfaces, the palette roles, and Dark Hayato's bindings.

The final checks cover both identities, both players and facings, hit/block/whiff, corners, airborne opponents, throws, armor break, interruptions, KO, tag, and consecutive rounds. They include two independent builds with identical hashes, ordinary-input MAME runs, sustained standard-FBNeo play for each identity, actual rendered frames and audio, and the surviving roster.

The release version of this article will add verified gameplay captures, source/target comparisons, tested controls, the reproducible installer, exact output hashes, and the results of that review. Until those exist, there is no release catalog entry or installation download, and the v0 video is a video of a render probe.

Written by Daniel Plas Rivera · 3,901 words · $36

ShareXLinkedIn