Skip to content
Index / $01

Binary Forensics: What Hidden Features Exist in Compiled Binaries?

Discovering undocumented characters, secret input codes, and unused entity IDs through systematic binary forensics on MvC1's CPS-2 ROM

Date
Jan 24, 2026 · upd Jul 4, 2026
Runtime
9 min · 2,032 words
Tags
binary-forensics, pattern-analysis, state-machines
Slot
$01
Contents
tip // Evidence Strip

Goal: Document MvC1's complete secret character system: input encoding, character ID mappings, and detection logic.

Constraints: No source code. Input buffer location unknown. Code detection routines not fully traced. Must distinguish real character IDs from false positives in binary scan.

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

Result: All 6 secret characters documented with input sequences, byte patterns, and ROM locations. Character ID table fully mapped (0x02-0x2E). False positive IDs 0x30/0x32 identified (opcode 0x303C). ID 0x2E confirmed as strongest candidate for unreleased character (85 real code references).

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.

Repo / Artifacts: CHARACTER_SELECT/scripts/ (scanner scripts), CHARACTER_SELECT/docs/02_CHARACTER_ID_MAP.md.

note // Status update (July 2026)

The forensics below stand as documented. The plan for the $2E slot has changed: the Armored Spider-Man / Iron Spider line was retired, and the slot's character work pivoted to a Dark Sakura port from MSHvSF (char-id $2A in that game) -- a same-generation port whose animation/frame tables carry over byte-identical to MvC1, so the work is table porting plus tile bank remapping rather than new art.

Many compiled binaries contain hidden features, debug modes, and undocumented functionality left by developers. MvC1's CPS-2 ROM contains 6 secret characters accessible via directional input codes, plus evidence of at least one more that was never finished. This deep dive documents the complete secret character system, the input encoding scheme, and the forensic techniques used to find character ID 0x2E -- our "Armored Spider-Man" target.

Secret Character System

MvC1 features 6 secret characters accessible via directional-only input codes on the character select screen. All codes start from Zangief's portrait except where noted.

Secret Characters

Roll (ID 0x10)

PropertyValue
TypeUnique character (not a palette swap)
Starting PositionZangief
Code Length16 inputs

Input Sequence:

Left, Left, Down, Down, Right, Right, Down, Down,
Left, Left, Up, Right, Up, Up, Right, Right

Byte Pattern:

04 04 02 02 06 06 02 02 04 04 08 06 08 08 06 06

Lilith (ID 0x2C)

PropertyValue
TypeMorrigan palette swap
Base CharacterMorrigan (0x1E)
Starting PositionZangief
Code Length17 inputs

Input Sequence:

Left, Left, Down, Down, Right, Right, Down, Down,
Left, Left, Up, Up, Right, Up, Up, Right, Right

Byte Pattern:

04 04 02 02 06 06 02 02 04 04 08 08 06 08 08 06 06

Gold War Machine (ID 0x28)

PropertyValue
TypeWar Machine palette swap
Base CharacterWar Machine (0x02)
Starting PositionZangief
Code Length15 inputs

Input Sequence:

Left, Left, Down, Down, Right, Right, Down, Down,
Left, Left, Up, Up, Up, Right, Right

Byte Pattern:

04 04 02 02 06 06 02 02 04 04 08 08 08 06 06

Orange Hulk (ID 0x26)

PropertyValue
TypeHulk palette swap
Base CharacterHulk (0x06)
Starting PositionZangief
Code Length14 inputs

Input Sequence:

Left, Down, Down, Right, Right, Down, Down,
Left, Left, Up, Up, Up, Up, Right

Byte Pattern:

04 02 02 06 06 02 02 04 04 08 08 08 08 06
warning // Important Note

Orange Hulk does NOT have armor (palette swap only, no armor animations).

Shadow Lady (ID 0x2A)

PropertyValue
TypeChun-Li palette swap
Base CharacterChun-Li (0x16)
Starting PositionZangief
Code Length16 inputs

Input Sequence:

Left, Left, Down, Down, Right, Right, Down, Down,
Left, Left, Up, Up, Up, Up, Right, Down

Byte Pattern:

04 04 02 02 06 06 02 02 04 04 08 08 08 08 06 02

Red Venom (ID 0x24)

PropertyValue
TypeVenom palette swap
Base CharacterVenom (0x0C)
Starting PositionZangief
Code Length14 inputs

Input Sequence:

Left, Down, Down, Right, Right, Down, Down,
Left, Left, Up, Up, Up, Right, Right

Byte Pattern:

04 02 02 06 06 02 02 04 04 08 08 08 06 06

Target: Armored Spider-Man (ID 0x2E)

This is the primary target of the Phoenix Edition project. ROM analysis revealed 85 code references for ID 0x2E -- far more than any other unused ID -- suggesting Capcom may have planned this character.

PropertyValue
TypeSpider-Man palette swap with armor flag
Base CharacterSpider-Man (0x0E)
Starting PositionSpider-Man (different from others!)
Code Length10 inputs
ROM Evidence85 code references, 4 secret load functions verified
StatusPlan retired (July 2026) -- the $2E slot pivoted to the Dark Sakura port; the binary evidence above remains valid

Proposed Input Sequence:

Down, Down, Left, Left, Up, Up, Right, Right, Down, Down

Byte Pattern:

02 02 04 04 08 08 06 06 02 02

Design Rationale:

  • Shorter than existing codes (10 vs 14-17)
  • Forms a "box" pattern (easy to remember)
  • Starts on Spider-Man (logical for Spider-Man variant)
  • Unique pattern (no conflicts with existing 6 secret codes)

Character ID Table

Normal Characters

IDCharacterSlot
0x02War MachineNormal
0x04Captain AmericaNormal
0x06HulkNormal
0x08WolverineNormal
0x0AGambitNormal
0x0CVenomNormal
0x0ESpider-ManNormal
0x10RollSecret
0x12RyuNormal
0x14Captain CommandoNormal
0x16Chun-LiNormal
0x18JinNormal
0x1AZangiefNormal
0x1CStriderNormal
0x1EMorriganNormal
0x20MegamanNormal
0x22OnslaughtBoss

Secret Character IDs

IDCharacterBase IDBase Character
0x10Roll0x10Roll (unique)
0x24Red Venom0x0CVenom
0x26Orange Hulk0x06Hulk
0x28Gold War Machine0x02War Machine
0x2AShadow Lady0x16Chun-Li
0x2CLilith0x1EMorrigan
0x2EArmored Spider-Man0x0ESpider-Man

Hidden/Unused IDs

IDNameStatusNotes
0x22OnslaughtBossFinal boss, not selectable by players
0x2EArmored Spider-ManTarget85 real code references, 4 conditional load points ($06DC76, $096B86, $0A8A9E, $0BAD8E), 3/4 near Shadow Lady code
0x30Empty SlotUnused0 animation markers (80 opcode refs are false positives from MOVE.W #imm encoding 0x303C)
0x32Empty SlotUnused0 animation markers (81 opcode refs are false positives)
0x34-0x3EEmpty SlotsUnused8 total unused ID slots available for new characters
warning // 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 -- completely empty slots.

Input System

Directional Input Encoding

DirectionByte Value
Up0x08
Down0x02
Left0x04
Right0x06

Input Buffer

PropertyValue
LocationTBD (requires MAME debugger analysis)
StructureCircular buffer storing last N inputs
TimeoutInputs expire after ~60 frames (1 second) of inactivity

Code Detection System

Detection Logic (Estimated)

1. Monitor input buffer
2. On each new input:
   a. Check if cursor is on correct starting position
   b. Compare input buffer against all secret code patterns
   c. If match found:
      - Set character ID to secret character
      - Load secret palette
      - Play confirmation sound/effect
   d. If timeout or wrong input:
      - Reset code detection state

ROM Locations (TBD)

ComponentLocation
Input bufferTBD
Code check routineTBD
Code pattern dataTBD
Character ID assignmentTBD

Character Select Screen Layout

Loading diagram...

Palette Swap System

How Palette Swaps Work

  1. Graphics Reuse: Secret character uses base character's sprite data
  2. Palette Override: Different palette applied to same sprites
  3. Moveset Identical: Same animations, hitboxes, properties
  4. ID Different: Separate character ID for tracking

Palette Swap Relationships

Loading diagram...

Implementation Guide

Adding a New Secret Character

  1. Choose Character ID

    • Use unused ID (0x2E, 0x30, 0x32)
    • Follow pattern: base_id + 0x20 for secret variant
  2. Create Palette

    • Design 16-color palette (RGB444 format)
    • Write to palette ROM (mvc.06a)
    • Document offset
  3. Update Character Table

    • Location: 0x065CCA in mvc.05a
    • Entry size: 32 bytes
    • Copy base character entry
    • Update ID and palette pointer
  4. Design Selection Code

    • Choose starting position
    • Create unique input sequence
    • Test for conflicts with existing codes
  5. Implement Code Detection

    • Find code check routine in ROM
    • Add new code pattern
    • Link to character ID
  6. Test

    • Verify code works
    • Check palette displays correctly
    • Ensure no conflicts with other characters

Tooling Model

For building detection and training tools:

from dataclasses import dataclass
 
@dataclass(frozen=True)
class SecretCode:
    name: str
    char_id: int
    start: str
    pattern: bytes
 
ROLL = SecretCode(
    name="Roll",
    char_id=0x10,
    start="Zangief",
    pattern=bytes([0x04,0x04,0x02,0x02,0x06,0x06,0x02,0x02,
                   0x04,0x04,0x08,0x06,0x08,0x08,0x06,0x06]),
)
 
LILITH = SecretCode(
    name="Lilith",
    char_id=0x2C,
    start="Zangief",
    pattern=bytes([0x04,0x04,0x02,0x02,0x06,0x06,0x02,0x02,
                   0x04,0x04,0x08,0x08,0x06,0x08,0x08,0x06,0x06]),
)
 
ARMORED_SPIDERMAN = SecretCode(
    name="Armored Spider-Man",
    char_id=0x2E,
    start="Spider-Man",
    pattern=bytes([0x02,0x02,0x04,0x04,0x08,0x08,0x06,0x06,0x02,0x02]),
)

Testing Scripts

Character ID Scanner

Script: scripts/char_id_scanner.lua

Scans all character slots and builds comprehensive ID table.

mame mvsc -autoboot_script scripts/char_id_scanner.lua

ID 0x2E Tester

Script: scripts/test_char_id_0x2e.lua

Forces character ID to 0x2E to test behavior.

mame mvsc -autoboot_script scripts/test_char_id_0x2e.lua

Secret Code Analyzer

Script: scripts/secret_code_analyzer.py

Analyzes ROM for secret code patterns.

python3 scripts/secret_code_analyzer.py

Next Steps

With deterministic replays, you can:

  • Detect when a code is entered
  • Label training data with "secret character chosen"
  • Correlate to downstream outcomes (team comp, win rate, etc.)

References

  • Code Discovery: Community findings, MAME debugger traces
  • Character IDs: PalMod source, ROM analysis
  • Input System: CPS-2 hardware documentation
EOF · $01 · 2,032 words · Daniel Plas Rivera
Share[X][LinkedIn]