Skip to content
PORTSNATIVE.
HomeCatalog
Web GamesEmulatorsToolsNews
PORTSNATIVE.

A catalog for discovering ports and related projects. We link to official sources and do not host original game files.

ExploreCatalogMy list
InformationAbout usSuggest a portSupportDonationsLegal notice
© 2026 PortsNative
Back to catalog
MetroidNESRecomp
PORTSNATIVE

MetroidNESRecomp

NATIVE PORTPLATFORMERWINDOWSLINUXMACOSALPHA

MetroidNESRecomp

Metroid

OriginNintendo Entertainment System

TechnologyStatic recompilation (native C/C++)

Available forWindows, Linux, macOS

View official project

About the project

Metroid es un videojuego del género acción y aventura y la primera entrega de la serie de videojuegos de Metroid. Desarrollado en cooperación por Nintendo Research & Development 1 e Intelligent Systems, y distribuido internacionalmente por Nintendo, el juego fue lanzado inicialmente en 1986 para la Family Computer Disk System en Japón y para la Nintendo Entertainment System en Norteamérica y Europa en 1987.

Official project information

Author's original READMEOpen on GitHub ↗

MetroidNESRecomp

This recompilation is a byproduct of developing nesrecomp — the games are the proving ground, the framework is the goal. These are in-development previews, not finished ports — expect rough edges, and depth will keep landing over months, not days. My time for any one title is limited, so I ask for your patience. Contributions are welcome — testing, issues, and PRs to the game or framework all help and will accelerate this game's polish. More on the why at: Recomp + AI: 5 Months Later »

A static recompilation of Metroid (NES) using nesrecomp. The original 6502 machine code is translated to C at build time, then compiled to native x64 for direct execution on modern PCs.

This is NOT an emulator. The game logic runs as native compiled code. NES hardware (PPU, APU, mapper) is simulated by the runner library.

You must supply your own Metroid ROM. No copyrighted game data is included in this repository.

Windows builds record startup diagnostics automatically. After a failed launch, send the diagnostics folder beside the executable. See collecting startup diagnostics, including the helper for Windows loader failures before the launcher appears.

Which ROM

The default cycle backend has separate USA/NTSC and Europe/PAL builds:

VariantCRC32 (headerless PRG+CHR)CRC32 (whole .nes)m1disasm target
USA / NTSC70080810A2C89CB9NES_NTSC
Europe / PAL7751588DA591CC24NES_PAL

Choose the variant at build time. Each executable accepts only its matching ROM. The builds use separate generated cycle sources and content keys; European packages are staged with the European CRC. The legacy backend retains its USA-only generated sources and hints.

Status

Experimental adaptive widescreen support (USA and Europe) is available through the bundled Metroid Widescreen mod. Enable it in the launcher's mod controls and choose Fit window, 16:9, 21:9, or 32:9. The custom renderer shows adjacent room terrain and follows live window resizing in Fit mode.

Optional mod choices add Viewport enemies and item previews, Expanded sprite capacity, and Reduced slowdown. Viewport enemies retain their original distance-based attack triggers. Widescreen is off by default, and each additional enhancement defaults to Original. These features are still experimental; enemy, projectile, and room-transition coverage remains incomplete.

Experimental 32:9 widescreen showing Samus, enemies and the Morph Ball in the expanded viewport

For the command-line options, tested behavior and remaining limitations, see WIDESCREEN.md.

The cycle migration preserves password saves, widescreen, viewport actors, expanded sprites, optional slowdown reduction and first-person voxel rendering. Stock gameplay and the tested enhancements agree between native cycle code and the cycle interpreter in both regions. See CYCLE-MIGRATION.md for build commands, validation and progress migration.

These are still development previews. The short regression route does not establish compatibility across every area, boss or ending. The function-level backend remains available for explicit legacy builds.

Experimental Voxel 3D (first person)

Open Mods in the launcher and enable Voxel 3D (first person). The bundled feature is disabled by default and targets the selected USA or European ROM. It does not patch the ROM or alter password data.

The camera follows Samus's live screen position; Right and Left directly own its horizontal heading, and holding Up smoothly raises the view toward the near-vertical shot path. The lens opens during that upward aim so overhead enemies and Samus's pellets remain visible. The room plane is reconstructed upright so horizontal movement remains forward/back instead of looking sideways. Only Samus's reserved OAM card is hidden; projectiles, enemies, doors, pickups, architecture, and shadows remain visible. The full room is voxelized behind a HUD-only overlay. The fixed Energy OAM band is excluded from world geometry and only the EN-## glyph footprint is restored in screen space, so no flat top strip or room pixels leak into the HUD.

Numpad 8/2 adjusts look pitch, 4/6 offsets yaw from Samus's facing direction, 7/9 rolls the camera, numpad or regular +/- adjusts field of view, and 1/3 changes sprite scale. Numpad 0 toggles the live view and Numpad 5 restores package defaults.

The earlier room-diorama package remains archived under mods/hidden for development reference but is intentionally not shown in release launchers.

Building

Prerequisites

  • Windows 10/11
  • Visual Studio 2022 Build Tools (or full VS 2022)
  • CMake 3.20+
  • A matching USA or European Metroid ROM; see Which ROM.

Steps

git clone https://github.com/mstan/MetroidNESRecomp.git
cd MetroidNESRecomp

# Windows
setup.bat

# Linux / macOS
chmod +x setup.sh && ./setup.sh

This initializes the pinned engine and UI submodules. Cycle code generation runs as part of the CMake build from your supplied ROM:

cmake -S . -B build-cycle-usa -G "Visual Studio 17 2022" -A x64 -DNESRECOMP_ROM=F:/ROMs/metroid.nes -DMETROID_VARIANT=usa
cmake --build build-cycle-usa --config Release

For Europe, use a separate build directory, -DMETROID_VARIANT=europe and the European ROM path. See CYCLE-MIGRATION.md for details. An explicit -DNESRECOMP_BACKEND=legacy build uses the checked-in USA function-level sources. The remaining symbol/hint instructions below describe that legacy generator workflow.

To create separate local Windows archives for both regions, run powershell -File tools/make_release.ps1 -UsaRom F:/ROMs/metroid.nes -EuropeRom F:/ROMs/metroid-eu.nes. Existing regional build caches retain their ROM paths. Use -SkipBuild to package already-built cycle executables, or -Variant usa|europe to select one region. Archives contain the selected region's mod packages and no ROM, settings or player saves. This script does not publish releases.

Symbols and hints come from the disassembly

disasm/m1disasm is a submodule of metroidret/m1disasm, an annotated WLA-DX disassembly that assembles byte-exact copies of both ROM revisions from one source tree (out/M1_NES_NTSC.nes, out/M1_NES_PAL.nes) and, via wlalink -S, a .sym file of labelled addresses for each. Two tools consume it:

  • tools/gen_symbols.py — turns one target's .sym into symbols.sym (the bank-aware symbol overlay game.toml points at, so generated functions carry their real names) and metroid_ram.h (MET_<Name> defines for every RAM/MMIO label, so extras.c and the widescreen renderer never spell an address out). Defaults to NES_NTSC; it refuses to run if the ROM body does not match the target it was asked for.
  • tools/extract_metroid_data_regions.py — walks disasm/m1disasm/SRC and emits the [[data_region]] blocks that keep the recompiler from mistaking tables for code. --target selects which .if BUILDTARGET branch applies.

Retargeting legacy hints to another ROM revision

game.toml's hints are raw addresses, so they are revision-specific. tools/migrate_hints.py moves them by label name rather than by hand: it reads the old and new .sym, rewrites [functions], [[data_region]], [[inline_dispatch]], [[stack_bail_func]], [[cond_bail_func]], [[merge_range]] and [[mod_function_hook]], and drops anything it cannot resolve (reporting each one). An address with no label of its own is recovered only when the move can be proven: the span between the two surrounding matched labels must be the same length in both builds, and — given --old-rom/--new-rom — must also hold the same bytes, the same relocated operands, or the same 6502 opcode stream. To retarget this repo at the European ROM:

python tools/gen_symbols.py --target NES_PAL --rom metroid-eu.nes
python tools/extract_metroid_data_regions.py --target NES_PAL   # replaces [[data_region]]
python tools/migrate_hints.py --toml game.toml \
    --old-sym disasm/m1disasm/out/M1_NES_NTSC.sym \
    --new-sym disasm/m1disasm/out/M1_NES_PAL.sym \
    --old-rom metroid.nes --new-rom metroid-eu.nes \
    --skip data_region --out game.toml --report migration_report.txt

then update the CRC32 in extras.c, CMakeLists.txt and the mod manifests, and regenerate. The tool is game-agnostic — any nesrecomp title with per-revision .sym files can use it.

Project Structure

FilePurpose
game.tomlRecompiler configuration (dispatch hints, data regions, extra functions) — NTSC/USA addresses
extras.cGame-specific runner hooks (frame callbacks, password save system, ROM CRC gate)
symbols.symBank-aware symbol overlay, generated from the disassembly (do not edit)
metroid_ram.hMET_<Name> RAM/MMIO defines, generated from the disassembly (do not edit)
metroid_ws*.c/hOpt-in widescreen mod: gating, function hooks, compositor, room decoder
mods/Declarative mod packages + their trusted plugin registration
recomp_stack.h/cRecompiled function call stack tracking
watchdog.h/cFrame timeout detection
generated/metroid_full*.cAuto-generated recompiled game code (do not edit)
generated/metroid_dispatch.cAuto-generated dispatch table (do not edit)
disasm/m1disasm/Annotated WLA-DX disassembly (git submodule) — source of symbols and data regions
tools/gen_symbols.py.sym → symbols.sym + metroid_ram.h
tools/extract_metroid_data_regions.pydisassembly → [[data_region]] blocks
tools/migrate_hints.pymove game.toml addresses between ROM revisions by label name
nesrecomp/Recompiler + runner framework (git submodule)

How It Works

The nesrecomp recompiler statically analyzes the ROM, discovers functions via BFS from the NMI/RESET/IRQ vectors, and translates each 6502 instruction to equivalent C code. JSR becomes a direct C function call, branches become gotos, and the 6502 stack is maintained as real RAM at g_ram[0x100+S].

Metroid uses the MMC1 mapper with 8 PRG banks. Bank 7 is fixed (always mapped at $C000-$FFFF) and contains the main game loop, NMI handler, and core routines. Banks 0-6 are switchable and contain area-specific code. The recompiler handles bank switching via call_by_address() runtime dispatch.

License

PolyForm Noncommercial 1.0.0 — see LICENSE. The nesrecomp framework submodule and any other third-party components are licensed separately in their own repositories.

No game ROM data is included. You must supply your own legally obtained copy of Metroid (USA).


<p align="center"> <sub><b>R.A.I.D. — Retro AI Development</b> · a Discord for AI-assisted retro reverse-engineering, decomp &amp; recomp</sub> </p> <p align="center"> <a href="https://discord.gg/Ad9BwSzctP"><img src=".github/raid-discord.png" alt="Join the Retro AI Development (R.A.I.D.) Discord" width="200"></a> </p>
View official project
CALIFICACIÓN
—
Loading votes…
Advertisement

PROJECT FILE

Project type
NATIVE PORT
Genre
Platformer
Status
alpha
Original platform
Nintendo Entertainment System
Technology
Static recompilation (native C/C++)
Version
—
Updated
—

Target platforms 3

Windows
Linux
macOS
View on GitHub
Advertisement