Skip to content
Index / $12

Byte-Identical on a CD: What the Saturn MSHvSF Port Actually Is

MSHvSF's 1998 Sega Saturn port turned out to be a source-level SH-2 recompile with mechanically-converted assets -- the character data tables are byte-identical to the arcade ROM (Shuma's MC05 frame records match 100%, 1,604 bytes), the sprites are a deterministic pen-map (pixel+1)&15 away from arcade tiles (0 of 7,680 pixels differ on a decode test), and the whole colorspace is one 128KB LUT on the disc. That makes it a plaintext second witness for the arcade RE -- and lets me cost, honestly, whether MvC content could go the other direction onto Saturn hardware.

Date
Jul 21, 2026
Runtime
8 min · 1,699 words
Tags
sega-saturn, sh-2, reverse-engineering
Slot
$12
Contents
tip // Evidence Strip

Goal: Understand MSHvSF's Sega Saturn port well enough to answer two questions with numbers: is the Saturn disc a second source of truth for the arcade data the native-character ports depend on, and could MvC content go the other direction -- onto Saturn hardware?

Constraints: No source for either side. The only inputs are the arcade CPS-2 ROM (encrypted) and the retail Saturn disc plus its 4MB RAM cartridge layout.

Approach: A byte-level audit of the disc's data files against the arcade ROM -- frame tables, sound maps, palettes, the sprite codec -- looking for mechanical, reversible transforms rather than assuming a rewrite.

Result: The Saturn port is a source-level SH-2 recompile with mechanically-converted assets. Character data tables are byte-identical to arcade; sprites are one deterministic pen-map away; the colorspace is a single precomputed LUT. That makes the disc a plaintext mirror of data I otherwise dig out of an encrypted ROM. The reverse direction -- MvC onto Saturn -- is a costed 4-phase plan: phases 0-2 demo-feasible, phases 3-4 research.

Proof / Validation: A 1,604-byte frame-record table matching the arcade ROM 100%; a decode test with 0 mismatched pixels out of 7,680; a 128KB colorspace LUT read straight off the disc.

Primary docs: SATURN_VS_CPS2 -- what the Saturn port actually is and MVC_TO_SATURN_PLAN -- the 4-phase import plan with honest effort ranges.

Why a Console Port Became Interesting

This started as a detour from a stuck problem. While the NYC stage port sat on a load hang, a side question got interesting: MSHvSF had a Sega Saturn port in 1998, famously faithful, running on the 4MB RAM cartridge. If that port's data formats were close to arcade, the Saturn version could be a second source of truth for the RE -- or even a second target.

The character-port work spends weeks locating tables inside an encrypted CPS-2 ROM. If a retail CD carried the same tables in the clear, that changes the economics of everything downstream. So I audited the disc against the arcade ROM, byte by byte. The full writeup is the SATURN_VS_CPS2 gist; here is what it turned out to be.

A Recompile, Not a Rewrite

The Saturn port is a source-level SH-2 recompile with mechanically-converted assets. Not an emulator, not a rewrite-from-scratch: Capcom compiled the game's logic for the Saturn's SH-2 CPUs and ran the arcade's data through deterministic converters. The evidence is unusually clean.

  • Character data tables are byte-identical to arcade. Shuma-Gorath's file (MC05) carries his 1,604-byte frame-record table and his 1,216-byte sound map byte-perfect against the CPS-2 ROM. The same tables I spent weeks locating in the arcade ROM for the native-character work exist on a consumer CD, unencrypted, in files named per character.
  • Sprites are a deterministic pen-map away from arcade tiles: saturn_pixel = (arcade_pixel + 1) & 15, so arcade's transparent pen 15 wraps to Saturn's 0, all wrapped in a bit-packed codec keyed by 2-bit codes. Proof standard: decoding record #694 produces 30 tiles with 0 of 7,680 pixels differing from the arcade originals under the pen-map.
  • PALET.TBL is a 128KB lookup table mapping every CPS-2 12-bit color to Saturn RGB555 -- the whole colorspace conversion is one precomputed LUT on the disc.
  • The roster index is arcade_id >> 1 -- the Saturn character list is literally the arcade's id space with the always-even ids compacted. Shuma's arcade id $0A becomes Saturn slot PL05 / MC05.
  • The one place byte-identity fully breaks: audio, re-encoded to 4-bit ADPCM with zero byte-level correspondence to the QSound data.

The decode pipeline, exactly

The sprite transform is small enough to be a diagram and mechanical enough to be reversible -- which is the entire reason the reverse-direction plan (below) is even costable.

Loading diagram...
Saturn audit, receipts
1,604B
Shuma frame-record table
byte-perfect vs. the arcade ROM (file MC05)
1,216B
his sound map
also byte-perfect on the disc
(p+1)&15
the whole sprite pixel transform
arcade pen 15 (transparent) becomes 0
0/7,680
pixel mismatches, decode test
record #694, 30 tiles round-tripped
128KB
PALET.TBL colorspace LUT
CPS-2 12-bit to RGB555, precomputed
id >> 1
roster index formula
arcade id space, compacted
5 x 668,448B
RAM-cart streaming slots
the 4MB cart is mandatory, and it is full
0%
audio byte-identity
re-encoded 4-bit ADPCM -- the one clean break

Boot Chain and the 4MB Cart

The disc boots through a fixed chain -- IP.BIN -> 00LOAD.BIN -> SYS.BIN -> MM.BIN -- and the whole thing refuses to run without the 4MB RAM cartridge: the cart check validates ID byte 0x5C at 0x24FFFFFF before proceeding. Once up, characters and stages stream from CD into the cart, and the SH-2 feeds decompressed tiles to the VDP1 sprite hardware per frame; sprites stay compressed in the cart and are decoded per-tile on the way to VDP1.

Loading diagram...

The cart's streaming region is five equal slots of 668,448 bytes (0xA3320) starting at 0x02486BC0, slot k at base + k * 0xA3320. That is the memory choreography the shipped roster is tuned against -- and it is essentially full, which becomes the load-bearing constraint on any reverse-direction plan.

Loading diagram...

For the arcade project this audit was an immediate, practical win: the Saturn disc is a plaintext mirror of data I otherwise dig out of an encrypted ROM. Byte-identical frame tables on a CD mean a second, independent witness for every table the native-character ports depend on.

Going the Other Direction: MvC on a Saturn?

Once you know the asset pipeline is deterministic and the data tables are arcade-identical, the tempting question writes itself: could MvC1 content -- a character, eventually the game -- go to the Saturn port's engine? I costed it properly rather than vibing it; the full plan is the MVC_TO_SATURN_PLAN gist. It's a phased plan with honest effort ranges, and the ranges are wide because they should be.

Loading diagram...

The verdict I stand behind: Phases 0-2 are demo-feasible and low-risk -- the pen-map and codec are proven reversible, so building the toolchain, swapping an asset, and getting one MvC sprite rendering in Saturn MSHvSF is a bounded project with a great screenshot at the end. Phases 3-4 are research projects, and I label them that way deliberately. Three walls stand between a rendered sprite and a playable character:

  1. The animation stream format is undecoded. Frame tables are byte-identical; the runtime stream that sequences them on Saturn is not yet understood.
  2. Character logic means hand-authored SH-2. The recompile is Capcom's source through Capcom's compiler; we don't have the source. New character behavior means writing it, per character, in SH-2 assembly against a partially-understood engine.
  3. The 4MB cart is saturated. Five slots of 668,448 bytes, already streaming-tight for the shipped roster. MvC's bigger cast and effects don't fit the existing memory choreography without redesigning it.

So the recommendation in the plan is the one this whole series already lives by: CPS-2-native porting is the right road for gameplay work, and the Saturn is a superb data source and a fun bounded demo target -- not the venue for new characters. Knowing precisely why, with hour ranges attached, is worth more than the fantasy.

Open Items

Stated plainly, because the project rule is no false success claims:

  • Nothing MvC-related runs on a Saturn today. Phases 0-2 are a plan, not an artifact.
  • The animation stream format is undecoded -- frame tables are byte-identical, the sequencer that plays them on Saturn is not yet understood.
  • Audio has zero byte-identity with the arcade -- the Saturn's 4-bit ADPCM is a separate encoding, not a witness for the QSound data.
info // Where this connects

The byte-identical frame tables here are the same tables the native Dark Sakura / Shuma-Gorath ports locate the hard way inside an encrypted CPS-2 ROM -- the Saturn disc is the plaintext cross-check. And the stuck-problem that sent me here in the first place is the NYC two-tier stage port, whose load hang is still open.

EOF · $12 · 1,699 words · Daniel Plas Rivera
Share[X][LinkedIn]