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.
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.
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.
| Character | ID | Type | Base | Inputs | Byte pattern |
|---|---|---|---|---|---|
| Roll | 0x10 | Unique character, not a palette swap | -- | 16 | 04 04 02 02 06 06 02 02 04 04 08 06 08 08 06 06 |
| Lilith | 0x2C | Palette swap | Morrigan 0x1E | 17 | 04 04 02 02 06 06 02 02 04 04 08 08 06 08 08 06 06 |
| Gold War Machine | 0x28 | Palette swap | War Machine 0x02 | 15 | 04 04 02 02 06 06 02 02 04 04 08 08 08 06 06 |
| Orange Hulk | 0x26 | Palette swap | Hulk 0x06 | 14 | 04 02 02 06 06 02 02 04 04 08 08 08 08 06 |
| Shadow Lady | 0x2A | Palette swap | Chun-Li 0x16 | 16 | 04 04 02 02 06 06 02 02 04 04 08 08 08 08 06 02 |
| Red Venom | 0x24 | Palette swap | Venom 0x0C | 14 | 04 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:
- 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.
| ID | Character | Slot |
|---|---|---|
| 0x02 | War Machine | Normal |
| 0x04 | Captain America | Normal |
| 0x06 | Hulk | Normal |
| 0x08 | Wolverine | Normal |
| 0x0A | Gambit | Normal |
| 0x0C | Venom | Normal |
| 0x0E | Spider-Man | Normal |
| 0x10 | Roll | Secret (unique character) |
| 0x12 | Ryu | Normal |
| 0x14 | Captain Commando | Normal |
| 0x16 | Chun-Li | Normal |
| 0x18 | Jin | Normal |
| 0x1A | Zangief | Normal |
| 0x1C | Strider | Normal |
| 0x1E | Morrigan | Normal |
| 0x20 | Megaman | Normal |
| 0x22 | Onslaught | Boss, not player-selectable |
| 0x24 | Red Venom | Secret |
| 0x26 | Orange Hulk | Secret |
| 0x28 | Gold War Machine | Secret |
| 0x2A | Shadow Lady | Secret |
| 0x2C | Lilith | Secret |
| 0x2E | (unused -- the target) | 85 real code references, 4 conditional load points |
| 0x30, 0x32 | No data | 80/81 opcode refs are false positives; 0 animation markers |
| 0x34-0x3E | No data | 8 further ID values with nothing behind them |
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.
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.
stateDiagram-v2
[*] --> Idle
Idle --> Buffering: directional input
Buffering --> Buffering: append byte to circular buffer
Buffering --> Match: buffer equals a secret pattern and cursor on start cell
Buffering --> Idle: wrong input or 60 frame timeout
Match --> Activated: set secret id, load palette, play confirm
Activated --> [*]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
| Scanner | What it does |
|---|---|
| Live slot walker | An emulator-side script that walks every character slot in a running session and builds the ID table from live memory |
| Forced-ID probe | Writes 0x2E into the character-ID field mid-select and records what the engine reads instead |
| Static code scanner | Sweeps 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