referenceUpdated Jul 21, 20268 min read$01

Every MvC1 Secret Character Code, Down to the Byte

Six directional codes, their exact byte patterns, and the character IDs behind them—including the unused number that sent the investigation sideways.

binary-forensicspattern-analysisstate-machinesreverse-engineeringinput-decoding
On this page
Where the full treatment lives

This is the input-code and ID-map reference for MvC1's secret character system: the six shipped directional codes byte for byte, the complete character ID table, and the detector's shape. It is deliberately narrow.

The system's deep dives live in two other posts and are not repeated here. The evidence that ID 0x2E was planned content -- 85 references, four BEQ-guarded load points, the false-positive filtering -- is in Binary Forensics: Recovering an Unreleased Character. The box system itself -- three table formats, the hardcoded position checks, the 13-state select machine and the interrupt hook that bypassed it -- is in Reverse-Engineering MvC1's Hidden-Character System. Read either of those for the engineering; read this one when you want the codes.

Evidence Strip

Goal: Document MvC1's secret character input encoding and character ID mappings.

Constraints: No source code. Input buffer location unknown. Must distinguish real character IDs from false positives in a raw binary scan.

Approach: Systematic byte-pattern scan of the decrypted ROM for each character ID value, cross-referenced against animation marker counts. Document all 6 secret input sequences and their byte encodings.

Result: All 6 secret codes documented with byte patterns. Character ID table mapped 0x02-0x2E. False-positive IDs 0x30/0x32 identified (opcode 0x303C).

Proof / Validation: All input sequences verified by execution in MAME. Character ID assignments confirmed via memory watch at $FF3053 (P1) and $FF3153 (P2). Animation marker counts validated via ROM scan script.

Artifacts: A pair of static ROM scanners (one for character-ID byte patterns, one for secret-code sequences), a live in-emulator slot walker that dumps the ID table from a running session, and the structured character-ID map they produce.

Status update (updated July 21, 2026)

The forensics below stand as documented. The plan for the $2E slot changed twice, and both changes shipped: the Armored Spider-Man / Iron Spider line was retired (an addition attempt -- no stock character was ever removed), the slot pivoted to a Dark Sakura port from MSHvSF (char-id $2A in that game) on a July-11 donor-chassis build ($2E force-remapped to real Ryu at state-machine dispatch) -- and the donor was then superseded by the current native ports: both Dark Sakura ($2E) and Shuma-Gorath ($30) now fight on their own relocated MSHvSF code and animation trees, no Ryu remap, hardened by a cumulative chain of live-gated fixes. Full write-up of the current state: the native port.

Many compiled binaries carry hidden features, debug modes and undocumented functionality left behind by developers. MvC1's CPS-2 ROM carries six secret characters behind directional input codes, plus one unused ID -- 0x2E -- with real code references behind it. This post is the catalog: what the codes are, how they encode, and what every character ID number means.

The Six Shipped Codes

All codes are directional-only, entered on the character select screen, and all six start from Zangief's portrait. Direction encoding: Up 0x08, Down 0x02, Left 0x04, Right 0x06.

CharacterIDTypeBaseInputsByte pattern
Roll0x10Unique character, not a palette swap--1604 04 02 02 06 06 02 02 04 04 08 06 08 08 06 06
Lilith0x2CPalette swapMorrigan 0x1E1704 04 02 02 06 06 02 02 04 04 08 08 06 08 08 06 06
Gold War Machine0x28Palette swapWar Machine 0x021504 04 02 02 06 06 02 02 04 04 08 08 08 06 06
Orange Hulk0x26Palette swapHulk 0x061404 02 02 06 06 02 02 04 04 08 08 08 08 06
Shadow Lady0x2APalette swapChun-Li 0x161604 04 02 02 06 06 02 02 04 04 08 08 08 08 06 02
Red Venom0x24Palette swapVenom 0x0C1404 02 02 06 06 02 02 04 04 08 08 08 06 06

Two things in that table are easy to skim past. Roll is not a palette swap -- she is a unique character who happens to be code-locked, which is why her ID sits inside the normal 0x02-0x22 band rather than the secret band. And Orange Hulk has no armor: it is a color change only, with no armor animations behind it, despite what the palette implies.

The Proposed Seventh: ID 0x2E

The Armored Spider-Man code was designed, not found. It deliberately breaks two conventions: it starts on Spider-Man's portrait rather than Zangief's, and it is much shorter than anything shipped.

Sequence (10 inputs): Down, Down, Left, Left, Up, Up, Right, Right, Down, Down Byte pattern: 02 02 04 04 08 08 06 06 02 02

The design rationale was a "box" shape that is easy to remember, thematically anchored on the base character's own portrait, and pattern-unique against all six shipped codes. Plotting every code's length makes the choice explicit -- the shipped codes cluster at 14-17 inputs:

How long each secret code is, in directional inputs
  • Armored Spider-Man10inputs

    the shortest of them, and the one that was never meant to be reachable

  • Red Venom14inputs
  • Orange Hulk14inputs
  • Gold War Machine15inputs
  • Roll16inputs
  • Shadow Lady16inputs
  • Lilith17inputs

The evidence that made 0x2E worth designing a code for -- 85 real code references and four disabled load points -- is documented in full here. That plan was later retired: the slot went to Dark Sakura, first on a donor chassis and now as a native port.

Character ID Table

IDs are even numbers. The normal roster occupies 0x02-0x22; secret variants occupy 0x24-0x2E, one step of +0x18 or +0x20 above their base.

IDCharacterSlot
0x02War MachineNormal
0x04Captain AmericaNormal
0x06HulkNormal
0x08WolverineNormal
0x0AGambitNormal
0x0CVenomNormal
0x0ESpider-ManNormal
0x10RollSecret (unique character)
0x12RyuNormal
0x14Captain CommandoNormal
0x16Chun-LiNormal
0x18JinNormal
0x1AZangiefNormal
0x1CStriderNormal
0x1EMorriganNormal
0x20MegamanNormal
0x22OnslaughtBoss, not player-selectable
0x24Red VenomSecret
0x26Orange HulkSecret
0x28Gold War MachineSecret
0x2AShadow LadySecret
0x2CLilithSecret
0x2E(unused -- the target)85 real code references, 4 conditional load points
0x30, 0x32No data80/81 opcode refs are false positives; 0 animation markers
0x34-0x3ENo data8 further ID values with nothing behind them
False Positive Alert

IDs 0x30 and 0x32 appear to have many ROM references, but analysis revealed these are the 68000 instruction MOVE.W #imm,D0 (opcode 0x303C) being misidentified as character ID references. The animation marker count for both is zero -- no character data behind either.

Later correction: 'unused ID' does not mean 'available slot'

This table originally described the unused IDs as "empty slots available for new characters." The character-port work that followed disproved that reading. Every per-character table in the engine holds exactly 23 entries, ids 0x00-0x2C, packed with zero slack -- so 0x30 physically aliases the next table's rows rather than sitting in a reserved gap, and 0x2E resolves only by borrowing Spider-Man's 0x0E entry. Capcom did not leave provisioned slots waiting to be finished; an unused ID is just a number the engine has no row for. That is why every fix in the later ports had to be a reader-side clamp and never a table rewrite.

How the Detector Works

The code checker is a single accumulate-or-reset loop over a circular buffer of recent directional inputs, guarded by two conditions: the cursor must be on the correct starting cell, and inputs expire after roughly 60 frames (one second) of inactivity.

How it works
Drawing the diagram…

Two things about that diagram are honest limits rather than findings. The input buffer's address was never located -- it stayed TBD through the whole project, because the interrupt-hook approach that eventually shipped sidestepped the detector entirely rather than extending it. And the "load palette, play confirm" step is inferred from behavior, not read out of disassembly.

The Three Scanners

ScannerWhat it does
Live slot walkerAn emulator-side script that walks every character slot in a running session and builds the ID table from live memory
Forced-ID probeWrites 0x2E into the character-ID field mid-select and records what the engine reads instead
Static code scannerSweeps the decrypted program ROM for the secret-code byte patterns and cross-references each hit against animation-marker counts to drop false positives

The live scanners run as autoboot scripts against the emulator, so a single command boots the game, attaches the probe, and dumps a table -- no manual debugger stepping.

The forced-ID probe is the cheapest experiment in the set: write the ID the engine has no row for, then watch what it reads instead.

References

  • Code Discovery: Community findings, MAME debugger traces
  • Character IDs: PalMod source, ROM analysis
  • Input System: CPS-2 hardware documentation

Written by Daniel Plas Rivera · 1,724 words · $01

ShareXLinkedIn