Skip to content

Repository files navigation

MidwayRecomp

A MIPS static recompilation toolkit for Midway Seattle and Midway Vegas arcade hardware. Converts MIPS-IV R5000 game binaries into portable C code that compiles natively on modern platforms -- no emulator required.

Built on top of N64Recomp by Mr-Wiseguy, which pioneered this approach for N64 titles like Zelda 64: Recompiled. MidwayRecomp extends it with the instruction set and platform support needed for Midway's arcade boards.

What's Different From N64Recomp

N64Recomp targets the Nintendo 64 (MIPS III, R4300i, big-endian). Midway Seattle/Vegas boards use the MIPS R5000 (MIPS IV, little-endian) with different hardware. MidwayRecomp adds:

Feature N64Recomp MidwayRecomp
Endianness Big-endian only Big-endian + little-endian (little_endian = true)
ISA MIPS III (R4300i) MIPS III + MIPS IV extensions
Conditional moves -- movn, movz
Prefetch -- pref (stubbed as NOP)
FP multiply-add -- madd.s/d, msub.s/d, nmadd.s/d, nmsub.s/d
Indexed FP load/store -- lwxc1, ldxc1, swxc1, sdxc1
Atomic load/store -- ll, lld, sc, scd (treated as plain lw/sw; sc/scd always succeed on single-core)
COP2 load/store -- lwc2, ldc2, swc2 (NOP stubs -- Seattle has no COP2)
Exception handlers Stack analysis fails on negative SP offsets Negative SP offsets allowed
Entrypoint Must be at ROM offset 0x1000 Any ROM offset accepted
Output filename prefix Always funcs_N.c Configurable output_func_prefix (avoids obj-file collisions when consumer builds multiple recompiled targets in one project)
Unsupported-instruction handling Bails mid-function, leaves unclosed brace in .c output Emits a stub return + closes the function so the build can still link
External-branch fallback Emits goto L_XXXX; to an undefined label, breaks consumer's build If branch target isn't a known function, emits return; instead of an unresolvable goto
Split-entry fall-through Alternate entry points that fall through into the next function become an implicit return, silently dropping the rest of the routine If a function runs off its end (last two instructions aren't a branch/jump/return) into a known function, emits a tail call + return so control continues

Without the atomic and COP2 patches, roughly half of CarnEvil's 2,047 game functions recompile to empty stubs because they hit ll/sc/lwc2 instructions the upstream recompiler bails on. With them, all functions generate full code (~472K lines of C).

Everything else -- the core recompilation engine, ELF parsing, symbol file format, overlay support, mod tools, live recompilation -- is inherited from N64Recomp and works identically.

Target Hardware

MidwayRecomp is designed for the following Midway arcade platforms:

Midway Seattle (1996-1999)

Component Spec
CPU MIPS R5000LE @ 150 MHz (MIPS-IV ISA)
System Galileo GT64010
GPU 3DFX Voodoo 1 (2MB framebuffer + 4MB texture)
Sound DCS2 (ADSP-2115)
I/O Midway IOASIC

Titles: CarnEvil, NFL Blitz, NFL Blitz '99, California Speed, Hyperdrive, Wayne Gretzky's 3D Hockey, Mace: The Dark Age, War Gods, San Francisco Rush, Vapor TRX, BioFreaks

Midway Vegas (1998-2002)

Component Spec
CPU MIPS R5000LE @ 200-250 MHz (MIPS-IV ISA)
System VRC5074 Nile 4
GPU 3DFX Voodoo 2/Banshee
Sound DCS2 (ADSP-2115)
I/O Midway IOASIC

Titles: Gauntlet Legends, Gauntlet Dark Legacy, NBA Showtime, NBA on NBC, NFL Blitz 2000/2001, San Francisco Rush 2049, Tenth Degree, Road Burners, Invasion

Quick Start

# Clone with submodules
git clone --recurse-submodules https://github.com/sp00nznet/MidwayRecomp.git
cd MidwayRecomp

# Build
cmake -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build --config Release

# Run
./build/Release/MidwayRecomp your_config.toml

Configuration

MidwayRecomp uses the same TOML config format as N64Recomp. For Midway Seattle/Vegas binaries, set little_endian = true:

[input]
symbols_file_path = "symbols.toml"
rom_file_path = "game.bin"
entrypoint = 0x800C4000
output_func_path = "recomp_out/funcs"
output_func_prefix = "funcs_"  # default; set distinctly per target to avoid obj-file collisions
little_endian = true
uses_mips3_float_mode = true

[patches]
stubs = ["exception_handler_func"]

If you have a project that needs to recompile multiple binaries (e.g. a game and its RTOS), give each one a different output_func_prefix so the emitted source files have distinct basenames (funcs_0.c vs rtos_funcs_0.c). Otherwise both produce funcs_N.obj and the linker only sees one set.

The symbol file format is unchanged from N64Recomp. For flat binaries without ELF headers, provide a symbol TOML listing all functions:

[[section]]
name = ".text"
rom = 0x1000
vram = 0x800C4000
size = 0xDF504

  [[section.functions]]
  name = "entry_point"
  vram = 0x800C4000
  size = 0xA4

See the N64Recomp documentation for the full config reference -- everything there applies here too.

How It Works

Same approach as N64Recomp: each MIPS instruction is translated one-to-one into a C statement. The output compiles with any C/C++ compiler and runs with a platform-specific runtime that provides memory access macros and hardware shims.

MIPS:  addiu $r4, $r4, 0x20
  C:   ctx->r4 = ADD32(ctx->r4, 0X20);

MIPS:  jal 0x80143A10
  C:   func_80143A10(rdram, ctx);

MIPS:  movn $rd, $rs, $rt        (MIPS IV -- new in MidwayRecomp)
  C:   if (ctx->r3 != 0) ctx->r2 = ctx->r4;

MIPS:  madd.s $fd, $fr, $fs, $ft (MIPS IV COP1X -- new in MidwayRecomp)
  C:   ctx->f6.fl = ctx->f8.fl * ctx->f10.fl + ctx->f4.fl;

Tooling

tools/ contains a project-agnostic, Ghidra-assisted function naming pipeline. It exports a Ghidra analysis to JSON, derives meaningful names from the binary's own debug strings (many self-name the function that prints them, e.g. coin_volume_proc():, sst1InitSli) plus an optional hand-verified seed list, and merges them into a symbols TOML so generated code reads main_init_sound_800C5E30(...) instead of func_800C5E30(...). See tools/README.md.

Credits

MidwayRecomp is a fork of N64Recomp by Mr-Wiseguy and contributors. The core recompilation engine, instruction processing pipeline, ELF parser, symbol file format, overlay/relocation support, mod tools, live recompilation framework, and the overall architecture are all their work. Without N64Recomp, this project would not exist.

The Midway-specific extensions (MIPS IV instructions, little-endian support, exception handler handling) were added by sp00nznet.

Libraries Used

  • rabbitizer for MIPS instruction decoding (by Decompollaborate)
  • ELFIO for ELF parsing
  • toml++ for TOML parsing
  • fmtlib for string formatting
  • sljit for live recompilation JIT

License

MIT (same as upstream N64Recomp)

About

MIPS-IV static recompiler for Midway Seattle/Vegas arcade hardware (CarnEvil, Blitz, California Speed, etc). Fork of N64Recomp with R5000 extensions.

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages