Version 1.0 is a clean-room, native x64 Windows reimplementation of the offline 1995 FMV game Ms. Metaverse. It preserves the original two-disc game flow and media without emulation, installation, physical-CD checks, or non-system runtime DLLs.
Original game data is not included. You must supply a lawfully obtained copy of both original discs. This repository and its releases contain no original video, audio, bitmap, data, installer, disc image, icon, or cursor content.
The source written for this port is MIT-licensed. FFmpeg retains its LGPL license. The original game and all of its content remain the property of their respective rights holders. This is an unofficial preservation project and is not endorsed by or affiliated with the original creators or rights holders.
- Download and extract
ms-metaverse-native-v1.0.1-windows-x64.zipfrom the GitHub Releases page. - Run
ms_metaverse_native.exe.
The EXE contains its media decoders and compiler runtime. It does not require FFmpeg DLLs, Visual C++ redistributables, the original installer, a mounted CD, or administrator access.
See CREDITS.md, CHANGELOG.md, and THIRD_PARTY_NOTICES.md for attribution and release details.
This repository also inventories the original media, extracts its data reproducibly, documents the recovered executable behavior, and builds the native replacement.
The original BIN/CUE and optional VHD are treated as read-only inputs. Generated images, extracted files, hashes, and analysis reports live under ignored workspace directories so they cannot be mistaken for source code.
Expected inputs:
METAVERSE1.bin: raw Mode-1/2352 CD trackMETAVERSE1.cue: track layoutMETAVERSE2.bin: raw Mode-1/2352 second CD trackMETAVERSE2.cue: second-disc track layoutmsmetaverse.vhd: fixed VHD containing a FAT16 installation
python tools/extract_mode1.py <METAVERSE1.bin> work/METAVERSE1.iso
python tools/extract_iso9660.py work/METAVERSE1.iso extracted/iso
python tools/extract_hfs_resources.py work/METAVERSE1.iso extracted/hfs
python tools/extract_mode1.py <METAVERSE2.bin> work/METAVERSE2.iso
python tools/extract_iso9660.py work/METAVERSE2.iso extracted/iso2
python tools/extract_hfs_resources.py work/METAVERSE2.iso extracted/hfs2
python tools/extract_fat16_vhd.py <msmetaverse.vhd> extracted/vhd
python tools/inventory_assets.py extracted/iso artifacts/inventory
python tools/inventory_assets.py extracted/iso2 artifacts/inventory2
python tools/extract_pe_resources.py extracted/iso/SETUP32/DATA/MM.EXE artifacts/pe/MMBoth tools write JSON manifests containing source and output hashes. They do not modify the input images.
extract_iso9660.py keeps ISO associated files (used by this hybrid CD for
Macintosh resource forks) in a sibling __associated__ directory so a fork and
its ordinary data file cannot overwrite one another.
The HFS resource-fork exporter requires hfsutils inside WSL (on Ubuntu:
sudo apt-get install hfsutils). It inventories the entire HFS catalog and
exports every non-empty resource fork as MacBinary II plus split .data and
.rsrc files.
The x64 Win32 target renders the original 8-bit bitmaps and plays PCM WAV files
directly. Its media layer streams the original Cinepak, Microsoft Video 1, and
RLE8 AVI frames through a minimal FFmpeg 8.1.2 build linked statically into the
EXE, decodes embedded AVI audio to native waveOut PCM playback, and loops both
without converting the assets. This avoids generation loss, retains the
odd-sized sprite frames, and requires no FFmpeg or compiler-runtime DLLs.
The executable currently provides a playable native offline flow through the
intro, the ordinary-profile entry-13 Hall, Cryo sponsorship, category weights,
the original Comments/ORDER board,
Brains, Looks, and Talent performances, all seven recovered navigation graphs,
slots, both Crossroads scenes, winner/tally movies, the credit movie, and tally.
The intro, winner, and credit movies retain their shared centered modal's blank
100 ms pre-play timer; pavilion and Penalty movies use their separate
immediate-start handlers. The shared player doubles each 320×240 movie to the
original 640×480 surface. After the centered movie child appears, a left click
uses its original stop/result-zero skip path; winner teardown clears that movie
before the replay prompt or finale sound, so its last frame cannot leak behind
the next step.
Profile selection runs before MMINTRO.AVI, matching the recovered top-level
controller rather than prompting after the opening movie. Profile selection
now uses the original 640×480 PASSWORD.BMP, exact two edit rectangles, and
painted OK.BMP press/release target in a borderless popup. Both fields retain
the original uppercase styles. Its vtable makes default Enter, Escape, and
window-close inert; only releasing the painted OK target submits the fields.
Cryo's C11 entry and first-sponsorship C12 use the recovered shared host
boundary: legacy audio stops, the mode-6 host clip runs modally, its wrapper is
destroyed, and CRYO.WAV restarts even when host media cannot open. C11 then
constructs ROTATE followed by hidden INFO in the retained Cryo dialog.
The original modal validation loop is
restored for guest, demo, returning, and newly created profiles. The original
GUEST and DEMO sessions remain non-persistent; only an authenticated or new
ordinary named profile is written to MM.DAT.
Legacy record loading is deliberately tolerant like MM.EXE: unrelated malformed
records and arbitrary IEEE-754 credit payloads do not reject the whole file,
and an authenticated return balance uses the recovered signed raw-bit $400
floor rather than a floating-point maximum.
After the intro, an ordinary or guest session now opens HALL.DAT at entry 13
and reaches first-round Cryo only through its Ms. Metaverse action. That branch
does not run the later replay reset or consume its extra judge-cadet RNG draws.
Before the intro, the original top orchestrator installs IDs 3,4,5,8,10, raw
weights 5,5,5, and an ascending host-comment table for every profile. Ordinary
play replaces them through Cryo, Weight, and ORDER; DEMO retains them, so its
Judge-O-Matic reactions now select the correct Disc II comment audio.
Navigation scenes obtain their video paths and object counts from the original
DAT files and seek/play the recovered transition frame ranges. Crossroads AVI
audio is likewise range-gated: a loaded/paused scene and a single-frame seek
remain silent, while bounded playback starts and stops the matching PCM span.
The three 0x1200 cross-scene nodes stop that range before reproducing the
original 199-pass palette-brightening recurrence; physical-CD remapping remains
disabled because both asset trees are packaged together.
Flagged
navigation nodes composite the original blue-screen T0–T10 AVI sprites at
the SPR runtime's top-left coordinates, cumulative relative paths, and state transitions
from D0–D10.MMS,
including the recovered one-second trigger, voice clips, strict four-edge DLL
hit test, and 5–15%-of-sponsorship awards represented by the MMS $50/$100
success sentinels. Misses play the original RICOCHET.WAV without dismissing the modal
encounter. Judging uses the original performance movies,
custom host-comment ordering, sponsorship/surcharge economy, Gong and Penalty
Box rules, and exact tally behavior. Talent/Brains affordability and all three
wrong-accusation debits retain MM.EXE's single unrounded x87 multiply-add,
including its -0.001f tolerance and stored-float negative clamp. The C host interstitials and all 38 active
motion-scripted X score reactions play at their traced state transitions before
the flow advances. Meter selection speaks the ordered comment asynchronously;
pressed judging controls commit on release, and accepted/gonged portraits change
before their host response is shown. Every C-clip click ends that clip; an
opaque sprite hit additionally plays the original synchronous OUCH.WAV from
the completion routine. Named profiles persist in the legacy
28-byte format; host reaction rotation persists in the original 180-byte
hnrd.dat layout. The install-global Brains/Talent rotation state uses the
exact 130-byte nrfPav.dat format. Both rotation files update immediately for
guest, DEMO, and ordinary named rounds; profile records are omitted for both
GUEST and DEMO.
nrfPav.dat is reopened when each round's media variants are prepared and its
two affected lines are updated in place per contestant; hnrd.dat is reopened
for every score reaction, matching the install-global timing instead of using a
process-start snapshot.
Cryo uses all eleven original highlighted control/detail bitmaps and places the
five sponsored contestant portraits at the traced 60×60 bottom-strip slots.
Those highlights are pressed states, not hover effects: an action runs only
when mouse-up remains inside the same recovered rectangle. The original hidden
Ctrl-click on the money panel also grants exactly $100.
C11 runs after the original 500 ms delay inside that retained Cryo dialog;
ROTATE and hidden INFO are constructed only after it returns. Browse ordering,
all forty quarter-turns and ten wrap cases, all 60 INFO ranges, per-selection
portrait loading, and every reachable sponsorship cash boundary are tested.
On the fifth selection, ROTATE closes before INFO, active INFO audio stops, the
legacy Cryo channel and owned artwork are released, and only then are the ten
Pavilion variants drawn and written.
The post-Cryo sequence matches MM.EXE: category Weight first, then ORDER.
Weight starts at 5/5/5 and uses the exact gauges, arrows, asynchronous spoken
values, and release-to-confirm OK state. ORDER uses its exact thermometer, hand,
phrase rows, red rank labels, and release-to-assign ACCEPT state.
Judging pavilions wait for a click on any unfinished bottom portrait before
charging or loading media, then return to that chooser after each result; they
no longer force contestant order 1→5. Talent/Brains keep that chooser and its
current rating gauge wrapper alive in place through ACCEPT, Gong, correct
Penalty, and NOCASH2. A successful next surcharge resets the numeric value and
loads the visible 0.BMP gauge. Looks likewise clears its visible gauge and
numeric value whenever a different contestant becomes active.
All three pavilion painters also restore the original live green balance at
(465,25) and white portrait frames. Talent/Brains add the active pending
slot's red frame only on the one painter pass armed by selection, and the exact
name-strip repaint shows the green contestant name while a bottom portrait is
hovered.
Talent/Brains preserve the original shared press flag: mouse-up on any of their
three action rectangles dispatches that release target after a press began on
one of them. Looks retains its separate per-button release code.
All three pavilion visits keep their 500 ms entry callback after C21/C31/C41 has
already been consumed. In Looks this means ROTATE construction, automatic
contestant selection/seek, and LOOKS.WAV remain delayed on re-entry too.
Navigation audio is destination-driven: each DAT node WAV plays once after
arrival, before any automatic follow-on hop. XR1.DAT positional nodes render
the original N1-N4 overlay bitmaps at their stored 640x480 coordinates, and
directional hover uses the embedded original Up/Right/Left cursor resources.
Neutral areas alternate the ripped 165/161 sparkling-hand frames every 500 ms.
XR1 also preserves its one-time sound-muted long transition and its later
held-frame shortcut; the five 0x0020 arrivals restore the original frame-25
background state before playing their destination cue.
The 320×240 navigation movies are stretched into the original 640×480 logical
canvas before DAT overlays and MMS sprites are drawn, so visual and mouse
coordinates now share the executable's coordinate space.
Valid manual departures also play the original ZPR.WAV effect on an
independent audio channel. The recovered 0x0900 mask suppresses it for
automatic and 0x0800 sound-bearing source nodes; slot Up/self retains it.
Right-click now opens the original six-item navigation popup in its recovered
order. Pavilion shortcuts dispatch directly, Slots selects the original XR1/XR2
variant-8 entry for the current asset tree, Exit uses the original confirmation,
and Skip Ahead is enabled only while a navigation range is active. During a
Slots wait, using Skip aborts the notified range and reveals the result
immediately; a second popup correctly shows Skip gray. Hall action
13 starts the game, actions 6/16 exit, and the retired external-game actions
return to the Hall without any physical-media prompt.
If a transition finishes while its already-open popup is still tracking, the
formerly enabled Skip command preserves the original stale-menu quirk and
forces that node's middle DAT transition.
Slots now runs as the original in-place navigation-node action rather than a
standalone approximation. Up on XR1/XR2 object 15 plays its exact self-range and
SLOTSPIN.WAV for 4,500 ms measured after range playback has started, then draws the three native-size ripped symbols at
their recovered coordinates, updates the balance, and plays the matching win or
loss sound. Zero credit immediately draws NO CREDIT without starting the reel
movie. Its recovered wait loop continues pumping queued Windows messages; this
is deliberately distinct from the blocking pavilion MCI-Wait calls. No original
disc is queried for any of these assets.
The packaged executable is self-contained: its import table contains only
Windows system DLLs. The build and packaging scripts fail if a third-party DLL
dependency reappears, and the package contains no runtime DLL files or original
installer executables. Game data remains in the ordinary data-only assets and
assets2 directories (BMP, DAT, MOV, and WAV). The runtime
resolves those directories beside the EXE before considering the caller's
working directory, so Explorer and shortcut launches remain portable. It
performs no physical-CD, drive, volume-label, or copy-protection check.
The two disc roots remain separate because five shared paths have intentionally
different bytes on each original volume. The app resolves Disk-I scenes from
assets and Talent/Crossroads-II/tally content from assets2, preserving those
disc-specific variants instead of flattening them into a lossy merged tree.
The AVI trigger audit accounts for all 266
installed movies and their playback boundaries. MOV/HOST/X11DB.AVI is the
sole movie-only inactive artifact; it has no script, audio, or executable
reference and is intentionally not dispatched.
./scripts/build-native.ps1
./build/native/ms_metaverse_native.exe --assets ./extracted/iso --assets2 ./extracted/iso2The required minimal static codec archives and headers are stored under
third_party/ffmpeg-static; no separately installed FFmpeg SDK is used.
scripts/verify-self-contained.ps1 inspects the PE import table after every
native build and again during packaging. FFmpeg's LGPL notices are included in
that directory and copied into packaged builds. Exact build provenance is in
third_party/ffmpeg-static/PROVENANCE.md, and the corresponding upstream source
archive accompanies public binary releases.
Original gameplay cursors and the application icon are optional local fidelity
resources. They are never committed or published. With a lawfully owned
MM.EXE, run ./scripts/prepare-original-resources.ps1; ordinary local builds
then embed the reconstructed resources. Public builds use Windows fallbacks.
Main controls:
- Press
Alt+Enterto toggle borderless fullscreen on the current monitor. The original 640×480 canvas remains aspect-correct with black letterboxing, and mouse/cursor hit testing is translated back into original coordinates. - Press
Ctrl+Alt+F1to set the current player's live balance to exactly$999999.00. Named-player balances retain that value through the ordinary profile save on exit; Guest sessions remain intentionally non-persistent. - Intro advances when its movie ends; after the initial 100 ms delay, a left click on it uses the original centered-movie skip path. The same applies to winner and credit movies. Pavilions and Crossroads use the original clickable DAT links; there is no generic stage-skip control.
- Cryo uses its five original on-screen browse/rotate/info/sponsor controls and
all six information labels. The fifth valid sponsorship advances
automatically; selections cannot be undone or bypassed. Each information label
plays its original
TT0–TT5spoken prompt before the matching contestant-specificINFO.AVIsegment. The 60 authored segment ranges are taken directly from MM.EXE and every start/end frame is package-validated. - Weights and ORDER use their painted arrow/ACCEPT/OK controls with original mouse-down and mouse-up-inside commit behavior. The original ORDER dialog also continues into navigation on a right double-click, retaining a partial ranking table if the board was not finished. Its confirmed Escape/close path has the same surprising continuation despite asking whether to quit the game.
- Navigation: after a one-second dwell on an encounter-enabled node, click the wandering Simm to tag it and earn the scripted reward. A miss plays the original ricochet effect and leaves the Simm active. Exact sprite-border pixels are misses, matching SPR.dll before its color-key test. The original target crosshair remains active for this mode-3 encounter; host introductions and score reactions retain the hand cursor.
- Judging uses the painted Judge-O-Matic, ACCEPT, GONG, PENALTY, and Looks ROTATE controls. Click the Looks contestant's head, torso, legs, or back to cycle the exact magnifier images. The left 60-pixel exit region returns to navigation whenever no synchronous Looks turn or Penalty response is active. Those authored movies cannot be truncated with Escape, close, or another pavilion click. After the fifth Talent/Brains result, the completed portrait strip is an additional close path; Brains plays C81 there first. Completed pavilions can be revisited as in the original; a completed Brains strip click plays C81 for that visit before returning to navigation.
- Slots: move Up at the slot-machine node. Its reel movie runs in place for the original 4.5 seconds, then leaves the exact symbols and result visible on that same node until you spin again or depart. Skip Ahead ends the range and shows that result immediately; any left click during the active reel follows the same original stop/notify path. Left clicks likewise skip other active navigation ranges before running their normal arrival handling and repainting the resolved destination immediately.
- Tally: Disk II
TALLY.DATobject 3 action 5 is the sole trigger. It calculates automatically, plays the winner/judge-cadet finale media in order, and presents the original replay decision at the $400 threshold. Below $400, Disk IIEND2.WAVprecedes the credit movie; a No answer at or above $400 goes directly to credits. Replay returns to Cryo without an original-CD check.
MM.EXE contains no accelerator resource. Accordingly, aside from the explicit
native Alt+Enter display toggle and Ctrl+Alt+F1 credit cheat, the game exposes no port-only
arrow/Enter/Space/R/I/G/X/P shortcuts that bypass those painted control paths.
Default dialog commands still follow the original
vtables: Enter exits an active navigation hub without confirmation, Escape asks
to quit most gameplay dialogs, profile and centered movies ignore Cancel, and
ORDER's confirmed Cancel continues into navigation.
Alt-Tab/reactivation also follows the recovered handlers: active ORDER and
Weight artwork is reloaded, and an existing Looks rotation child is shown again.
Run extraction/unit checks, the native build, static dependency inspection, complete two-disc media/trigger probe, and real Win32 UI-route audit with:
./scripts/test.ps1