case studyUpdated Sep 18, 202615 min read$37

I Put MVC2's Sentinel Into Marvel vs. Capcom 1. It Worked on the First Boot.

Sentinel's render probe still runs on Hulk's code. A later pinned audibility run was blocked: 24 source clips decoded, 11 mapped and seated across 42 aux12 events, but no audio was heard and no candidate exists.

Help shape what comes next ↓
cps2marvel-vs-capcommvc2sentinelhulk
CPS-2 Reverse EngineeringPart 43 of 54
Browse all writing
On this page
Pinned audibility run blocked — September 18, 2026

The pinned run happened; it did not produce an audibility pass. The source inventory contains 24 decoded clips. Sentinel's animation data contains 42 aux12 event occurrences, which collapse to 11 distinct low-byte ids, 11 mapped source clips, and 11 seated QSound row slots. The pinned diagnostic reached live $06, but no clip crossed the detection threshold (maximum correlation 0.1532 against 0.45) and no audio was heard.

The rebuilt 11-clip package also differs from the earlier shipped pin, and its boot-checksum calibration remains unverified. The decision is AUDIBILITY_DEFERRED; candidate remains null. This is static reconciliation plus a blocked diagnostic run, not sound, gameplay, or release evidence.

Sentinel is the character MVC2 players either love or refuse to play against: a mutant-hunting robot the height of the screen, with flight, drones and a Hyper Sentinel Force that fills the stage. He is also, on paper, the worst possible candidate for a CPS-2 port. He is the biggest sprite set in the game, he was never in a CPS-2 title, and his sounds only ever existed on the Dreamcast.

He is on screen in the original arcade Marvel vs. Capcom now. In Hulk's slot, on Hulk's character code, with his own art, animation records, collision boxes and palettes, and he came up with the right colours on the first boot. That last part is not luck, and it is the real story of this post: the port pipeline that took weeks to get right for Hayato is now a harness, and Sentinel was its first run.

This is v0, a render probe, not a port. Hulk's code chooses every state and Sentinel's data is what it draws. He has no moves of his own yet, no flight, no drones, and he makes no sound. There is no playable MVC1 Sentinel candidate or download.

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

What the evidence establishes

5 STOPS · 0 CORRECTED · 0 RETRACTIONS · 0 OPEN
  1. render probe(PL12) = pinned zip
    render probe(PL34) = new zip

    Pinned Hayato probe hash and the container rebuild through MVC_HARNESS/lib/port

    01 / 5prior artHarness generalization

    Control against Hayato

    b73f8b5b…Hayato's pinned probe zip, reproduced byte for byte

    Before the harness read a single Sentinel byte, the generalized modules had to rebuild Hayato's pinned render probe and match its hash exactly. They did. Only then did the same code run on Sentinel.

    Read this section
  2. group directory @ 0x200 (Hayato 0x100)
    13,608 unique tiles
    boxes = 2,048 bytes = Hulk's slot

    PL34_DAT census through the shared readers

    02 / 5measuredSentinel source audit

    Census the giant

    3,004 / 3,004source sprites round-tripped

    3,004 sprites, 392 sprite lists, 74 palettes, 27 animation groups, 170 sequences and 1,016 records, with the box table at exactly the 2,048 bytes of Hulk's stock slot. His animation directory sits at a different offset than Hayato's and Cable's, which the harness now detects instead of assuming.

    COVERAGE 100% OF UNIQUE SOURCE TILES SEATED, OUT OF 13,608 — NOT GAMEPLAY PARITY

    Read this section
  3. 16,427 exclusive tiles
    13,608 seated
    2,819 remaining (Hayato: 1,662)

    Canonical-base ownership census and stock packing readback

    03 / 5measuredStock allocation

    The giant fits

    2,819exclusive graphics tiles still available

    Sentinel's 13,608 unique tiles fit the measured 16,427-tile Hulk-family allocation with more room to spare than Hayato left. Identity art, his own code and his sounds still need their own budgets.

    Read this section
  4. Sentinel's standing heavy punch landing on Ryu in stock Marvel vs. Capcom, the HUD reading HULK

    Observer logs and snapshots from the headless MAME 0.264 control and probe runs; diagnostic tier

    04 / 5measuredv0 render probe

    Right colours, first boot

    5,589duel frames in a headless MAME 0.264, no reset

    The palette rule Hayato's first boot got wrong is a registered harness fact now, so Sentinel inherited it. He rendered with source colours on the first attempt, and in the scripted duel he KO'd both Ryus in 48 seconds on Hulk's move logic.

    Read this section
  5. AICA 4-bit ADPCM → PCM16 → 8-bit QSound
    24 decoded inventory clips
    42 aux12 events → 11 ids → 11 seats

    MVC_HARNESS audio readers plus Sentinel's September 18 audibility-decision receipt

    05 / 5measuredAudio transcode

    Why the Dreamcast characters are silent

    24 / 11 / 42decoded clips / mapped and seated clips / aux12 occurrences

    Every MVC2 port with working sound copied QSound bytes out of a CPS-2 game the character also appeared in. Cable, Sentinel and Hayato never did. The conversion exists and the 42 event occurrences map to 11 seated clips, but the pinned run did not establish audibility.

    Read this section
  • SOURCE PIXELSnot yet true
  • ON SCREENnot yet true
  • HIS OWN SOUNDSnot yet true
  • MVC1 GAMEPLAYnot yet true
The coverage line measures source conversion and seating only. No gameplay percentage has been established; the screen lamp means the stock engine draws Sentinel's data, not that Sentinel plays. The sound lamp stays off: 11 clips are statically mapped and seated, but the pinned run did not detect or hear them.These are engineering stages, not a release timeline.

The harness built it

Hayato's v0 was the first time MVC2 data rendered on the MVC1 engine, and most of that post is about the things that had to be measured before it would: the record formats, the group map, the palette order the hardware forced. Those measurements are now facts in a registry that every port reads first, and the readers, compilers and the render probe that used them are shared modules rather than Hayato's scripts.

The rule for touching them was simple. Generalizing a module that has a pinned, working output is only allowed if the pinned output does not change. So before the harness read a Sentinel byte, it rebuilt Hayato's render probe through the generalized code and compared the zip hash to the pinned one. It matched, byte for byte. Then the same code ran on Sentinel's data, and the only Sentinel-specific thing it needed was the number 34.

Two things did have to give. Sentinel's animation-group directory lives at a different offset inside his animation section than Hayato's and Cable's, because more frame records precede it; the reader used to assume the offset, and now it finds the first aligned table of forward pointers instead. And Sentinel has twenty-six animation sequences whose record stride is ambiguous between two valid readings. Hayato resolved his with evidence from the game's own SH-4 code. Sentinel does not have that evidence yet, so the probe uses the full-record reading for all twenty-six and says so in its manifest. That is a documented default, not a proof, and it is on the list.

The census and the fit

The numbers are the reason a Sentinel port is even plausible on this hardware. His source has 3,004 sprite pieces in 392 sprite lists, 74 palettes, and an animation tree of 27 groups, 170 sequences and 1,016 records. Every sprite round-trips through conversion. His collision rows and rectangles come out at exactly 2,048 bytes, which is the size of the box slot Hulk already owns, so they drop in without a relocation.

Tiles are the budget that matters. The fresh ownership census of the canonical Euro 980123 parent again gives Hulk and Orange Hulk together 16,427 exclusive tiles. Sentinel needs 13,608 unique tiles, and the measured packing leaves 2,819. Hayato, a much smaller character with far more frames, left 1,662. The giant is, in tile terms, the easier fit.

That margin is still conditional in the same ways Hayato's was: no identity surfaces yet, no Sentinel-owned code, no sound allocation, and nothing about how many objects the drones would need to draw at once.

Right colours on the first boot

The render probe is built the same way Hayato's was: the pinned parent, the recomputed tile seating, the compiled art, animation and collision, the translated record tree in the largest free program run, the boxes in Hulk's box slot, the $06 and $26 directory rows pointed at Sentinel's tree, and Hulk's private code untouched.

Hayato's first boot came up with scrambled colours because the harness had transcribed the object layer's pen order wrong, and it took an OBJ and palette RAM dump to fix. That fix was registered as a harness fact, so Sentinel's palette writer inherited the measured rule. He came up right the first time. It is a small thing to write down and a large thing to have happen: a measurement made once, for one character, that the next character got for free.

The evidence again starts with a stock-Hulk control in a headless MAME 0.264, then the probe on the same observer: boot, coin, land on $06, a fixed schedule of ordinary inputs. Sentinel animates with source colours through idle, walks, crouch, jump, the six standing normals, crouching normals, air attacks, guard and hit reactions, and a throw, with no watchdog reset. In the scripted duel he beat both Ryus in 48 seconds. That reel remains an unpinned cloud diagnostic. A later pinned MAME 0.287 audibility run reached live $06 but detected no qualifying clip; it did not promote the render probe or establish sound.

Sentinel's standing heavy punch landing on Ryu in the render probe; the HUD reads HULK
Headless MAME 0.264, the fight chapter: Hulk's standing HP logic, Sentinel's fist. The name plate reads HULK because the HUD is an identity surface v0 does not touch.
Sentinel towering over Ryu in the render probe
The duel chapter, second Ryu. Every sprite, box and colour is Sentinel's; every decision is Hulk's.

The video is a cut of longer scripted captures, in the same shape as Hayato's: Sentinel on player one, a scripted Ryu on the human player-two seat reached by joining as the challenger, and a one-player game against the CPU for the reactions chapter. Every input goes through MAME's ordinary input ports, every capture keeps its observer log, and the observer's frame counter is the capture's frame index. The rails, captions and cards ride outside the gameplay window. One new thing: under the captured QSound there is a music bed, an original instrumental generated for the video, mixed twelve decibels below the game audio. The game audio itself is untouched.

Frame 120 after the fixed input schedule begins on the stock ROM (Hulk, left) and on the render probe (Sentinel, right)
Same inputs, same frame // one input schedule on the stock ROM and on the probe, side by side at the same frame index. When the fights diverge, it is the data doing something, not the code.

Why every Dreamcast-only character has been silent

Sentinel's sounds were part of the brief from the start, and the audio work turned out to matter beyond him.

Every MVC2 character port in this series that has correct sound got it the same way: Shuma, Storm, Magneto and Rogue all appeared in a CPS-2 game, so their QSound samples, sequences and descriptors were copied out of that game in the format MVC1 already speaks. No conversion, a byte copy with new addresses. Cable, Sentinel and Hayato were never in a CPS-2 game. Their only audio is the Dreamcast bank, which is Yamaha AICA four-bit ADPCM in a different container with a different sample map. There was no donor to copy, and the conversion that would replace the copy had never been written. Cable's port shipped with his voice row left empty and a handful of other characters' sound ids borrowed to fill the gaps, which is exactly why his sounds play through the wrong descriptor and come out high-pitched and too fast. It is a playback-rate fault, not damaged samples, and the fix is to give him his own descriptors.

So the harness now has the conversion. The decoder turns the ADPCM into 16-bit PCM, resamples if asked, and requantizes to the 8-bit signed samples QSound plays; rendered back to WAV, Sentinel's 24 clips and Cable's 26 come out with well under one percent of requantization error. The other half is the QSound authoring itself, and that was ported, not reinvented, from the toolkit that shipped Storm: the descriptor and sequence chain, the instrument note records, the free-space scanners. Its control is the reader: run against the stock ROM, it reproduces the proven toolkit's reads of all 818 stock descriptors and every keyed note, with zero mismatches.

Two things the control caught are worth recording. The QSound program, the sample ROMs and the 68000 program that holds each character's sound row are three different byte orders, and the first version of the reader swapped the wrong one; the driver's own header, which only reads as its documented bases in the right orientation, exposed it. And an address in our notes that was supposed to be a table of sound-row offsets was not: it was noise, the rows were where the two shipped ports said they were, and the scanner that depended on it was thrown out. A scanner that finds none of the shape it expects is a bug until proven otherwise.

The allocation is measured too. Sentinel's clips come to 237 KB of 8-bit samples at 22,050 Hz, and Cable's to 232 KB, against 148 KB of free space in the stock sample ROMs. The descriptor table, the action ids and the sequence space all fit in stock with room to spare; only the samples do not. The three working ports all solved that by expanding the sample ROM, which the descriptor addressing reaches directly, and that is the plan here; a fallback at 11,025 Hz would fit stock at a cost in fidelity.

What the container cannot settle is pitch. On QSound the playback rate is set by a rate byte in the descriptor together with the note the sequence keys, a relationship the sound chip resolves and a static read cannot. A pinned run has now been attempted, but it did not detect a qualifying clip and the rebuilt 11-clip package does not match the earlier shipped pin. Until package lineage, boot-checksum calibration, and heard output agree, the sound lamp stays off.

What v0 is not

The end of a round in the render probe: the game announces HULK RYU WIN while Sentinel's sprite performs the win pose
Hulk's win logic, Sentinel'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 Sentinel chain the group map reaches. There is no flight, no drones and no Sentinel Force, because those are Sentinel's code and none of his code is in the ROM. The scripted captures deliberately never input a motion for him.
  • The v0 probe makes no sound and spawns nothing. Its per-frame aux12 events are dropped. A later, separate diagnostic package maps the 42 event occurrences to 11 seated clips, but no audio was heard and that package does not replace v0.
  • Contact uses Hulk's attack properties. Sentinel's collision rows are in place, but damage and hit timing come from Hulk's property table.
  • Twenty-six animation strides are a default, not a measurement, until Sentinel's SH-4 consumers are read the way Hayato's were.
  • Palette roles beyond the stock costume window are undesigned.
  • The reel is the cloud rig. A later pinned MAME 0.287 audibility run happened and blocked; it did not turn the reel into accepted gameplay evidence.
  • No download. There is no installer, no release entry and nothing to mistake for a completed port.

What must happen before release

The order is the same as Hayato's, with one addition that his post did not have to make. Sentinel-owned dispatch first: Hulk's handler-table entries and private code span become Sentinel's, so that normals, specials, hypers, flight, reactions and lifecycle calls reach his own routines, with the aux12 events delivered from a side table. Then the drones and Sentinel Force through the engine's own object and input machinery, the identity surfaces, and the palette roles.

The addition is sound. The transcode and authoring kit are built, and a static 11-clip seat now exists. What remains is stronger than another write: reconcile the divergent package hashes, reproduce the boot-checksum rule, then hear and detect the expected clips at their mapped frames on the pinned rig. Only that can lift AUDIBILITY_DEFERRED; the current seat stays zero-credit.

The final checks are unchanged: both identities, both players and facings, hit, block and whiff, corners, airborne opponents, throws, interruptions, KO, tag and consecutive rounds; two independent builds with identical hashes; ordinary-input MAME runs and sustained standard-FBNeo play; and the surviving roster. Until those exist there is no release catalog entry and no download, and the v0 video is a video of a render probe.

Community input · This article

What should I work on next?

Choose up to 3 priorities. No account needed.

Written by Daniel Plas Rivera · 3,250 words · $37

ShareXLinkedIn