RingOut README

The project's README from github.com/jackpoison-prog/RingOut. As one markdown file: README.md.

Ring Out

A native PC port of a GameCube fighting game (disc ID GRSEAF), produced by static recompilation rather than emulation: the disc's PowerPC executable is translated ahead of time into C, compiled for x86-64, and run as native code inside a Dolphin-derived runtime that provides the graphics, audio, input and hardware emulation around it.

No game data and no game code are distributed here. You supply a disc image you already own; setup extracts it and recompiles it on your machine.

This is still early. Expect rough edges: the game is playable start to finish, but features arrive before their polish does, and something that worked last release can break in the next one. Polish is planned throughout rather than saved up for a 1.0 — and bug reports genuinely help, because most of what gets fixed here was found by someone hitting it.


Status

Fully playable — boots to menu and through gameplay. Every block of the game's own executable runs as native code; the recompiler translates 535,368 instructions with 0 unknown opcodes and no interpreter fallback inside them.

What the interpreter does still cover is the PowerPC exception vectors — 0x500 (external interrupt), 0xC00 (system call), 0x800 (FP unavailable). Those handlers are written into low RAM by the OS at boot rather than living in the disc's executable, so there is no recompiled code to dispatch to and the interpreter runs them until control returns. They account for about 0.7% of executed steps, steadily, because interrupts fire for the life of the session — but only 0.2% of cycles, so there is nothing to win by recompiling them. An earlier version of this page claimed "zero interpreter fallback", which the runtime's own shutdown line has always contradicted.

Rendering is Vulkan on the GPU, with the CPU emulation and the runtime on separate cores.

Steam Deck: supported, with its own package — no toolchain needed, since the module is built on a desktop and copied over. Runs in both Desktop and Game Mode at 45–49 fps in a match. It can also build on the device: install a toolchain and SteamOS compiles its own module, needing no bundled libraries at all — tested end to end on SteamOS 3.8.25, and the way to get the full PGO win there (clang 20 cannot read the shipped profiles). See dist/RingOut-1.0-deck/BUILD-ON-THE-DECK.md.

Netplay: working. Rollback over a deterministic dual-core setup, with a lobby showing live ping and per-player game status; two peers stayed byte-identical over 6,470 frames.


Getting it

Two packages, from the Releases page:

for needs a toolchain?
RingOut-1.4-linux-x86_64.zip desktop Linux yes — compiles on your machine
RingOut-1.4-steamdeck-x86_64.zip Steam Deck / SteamOS only to build a module

The Deck package ships no module: build one on a desktop with the package below, then copy game/ and bin/gGRSEAF_recomp.so across. Add RingOut to Steam as a non-Steam game to launch it from Game Mode.

For desktop, unzip and run:

./RingOut

On first run it asks for your disc image (.iso / .gcm / .nkit.iso / .rvz), then extracts and recompiles it — several minutes, once. Every run after that starts straight away. You can also pass the image directly:

./RingOut /path/to/disc.iso     # or: ./setup.sh /path/to/disc.iso

Requirements

The release binary is built in a Debian 12 container and needs glibc 2.36, which every current distro clears — so the bundled glibc in libc-fallback/ is a fallback almost nobody takes. (This page previously said 2.44, which was the glibc of the machine the runtime used to be built on. The launcher believed the same number and sent every host between 2.36 and 2.44 down the bundled path for no reason, where the Vulkan loader then finds no driver. Both are fixed, and packaging now fails if the two disagree.)


Features

Controls

Key Action
Escape settings menu
Arrow keys navigate; Left/Right change a value or switch tab
Space confirm / activate
Alt+W toggle widescreen
Alt+Enter fullscreen
F1–F8 / Shift+F1–F8 load / save state
Shift+Escape quit

Free camera (enable in the Video tab): Shift+WASD move, Shift+Q/E down/up, Shift+arrows look, Shift+Z/C roll, Shift+1/2 speed, Shift+R reset.


Performance work

Everything below is measured on a fixed-work gameplay benchmark — the same emulated frames, driven by a frame-keyed input script, counted in retired CPU cycles rather than wall time. That harness exists because the earlier one did not measure the right thing: it ran boot and an idle menu, which carry ~0.1% of a real session's paired-single traffic, so a change could look free there and cost 3% in a match. Earlier figures in this README were taken that way and have been removed rather than restated. How the harness works, and the checks that stop a run from measuring the wrong thing, are in docs/measuring.md.

What shipped

Change Effect
Inline the paired-single helper chain psq cost per unit of work −43%
Compile loop back-edges as native goto dispatches −66%, CPU −11.5%
Defer FPRF classification until FPSCR is observable −2.14% cycles (Deck)
-flto=auto module relink 22 min → 6
Profile-guided optimisation −10.3% desktop, −14.1% Steam Deck
Per-region profiles −12.33% for a JP module vs the US profile
On-device profile training (setup.sh --pgo) recovers the full win on any clang

The FPRF one is the shape most of these take: the FP condition register is written 3.07 billion times per run and read 15,885 times — mandatory by architecture, dead in practice — so it is now computed only where something can observe it, with frame hashes proving guest state is unchanged.

What was measured and rejected

Kept here because the negative results cost as much to establish as the wins, and each one looks plausible enough to be retried:

Idea Result
BOLT post-link layout 8.1% slower
-O2 instead of -O3 9.1% slower, despite 12.5% less code
LLVM object backend 4% slower, even removing 43% of dispatches
Leaders-only entry labels 81% of execution fell out to the interpreter
Block-local register allocation tied; no cross-iteration residency to exploit
CR / XER[CA] elision ceiling ~0.05% and ~0.2% respectively
Optical-flow frame generation needs 120Hz+; halves speed with V-Sync on, +8.3ms latency

PGO was itself in the rejected table for a long time — "does not build, SIGBUS before the first frame". That was true when it was written and is not any more. It is now the largest single win here, and the details, including the several ways it silently does nothing, are in docs/profile-guided-optimisation.md.

Frame generation is the odd one out: it works, and the shader does what it says. It is rejected on physics rather than on codegen. Presenting a synthesised midpoint costs a second present, which on a 60Hz panel means a second vblank and therefore emulation at 30 FPS; turning V-Sync off restores 60 but tears. It also adds ~8.3ms of input latency, because a midpoint cannot exist until both of its endpoints do — a poor trade in a fighting game. It would need a 120Hz+ display to have a spare refresh to live in, and every panel this project runs on is 60Hz. Kept on the framegen branch rather than deleted.

The pattern among the rest: BOLT, -O2 and the LLVM backend all bought instruction locality or fewer dispatches, and all three lost by retiring more instructions at lower IPC. PMU attribution explains why — front-end starvation is 2.4% of cycles and the back end is saturated at IPC 1.92. The workload is not inefficient, just large: 86.4 million host instructions per emulated frame.


What's next

Ordered by how much they would help, not by effort. Nothing here is promised.

1. Make it easier to get running. This is the biggest thing between the project and anyone using it. Today setup wants cmake, ninja, clang and python3 on your machine and takes several minutes before you see the game.

The compile itself cannot go away: the module is your disc's own executable translated to native code, so it is game data and cannot be distributed — that constraint is the whole design, not an oversight. What can go is everything around it:

2. Mods, further than they go now. Texture packs and texture mods work, and character skins install from the menu when their data is exactly the size of the entry they replace. Two gaps are known and neither is hidden by the UI:

Beyond closing those:

3. Whether any performance is left. The stage-by-stage figures behind this page's numbers predate the Steam Deck training its own PGO profile, which was worth 14%. If the slow stages now hold full speed, the performance work is finished and several remaining ideas die with it — which is worth knowing either way.

4. A Windows build — coming. No date yet. The scaffolding from the earlier Windows work is still in the tree, so this is a revival rather than a fresh start — but it is unbuilt and untested today, and nothing currently on the Releases page will run there.

5. Staying current with upstream. The recompiler and the Dolphin-derived runtime both have upstreams that keep moving. Most of the delta is work this fork has measured and rejected, but not all of it.


Known issues

Fixed since the last revision of this page


Building from source

cmake -S ModernGekko -B ModernGekko/build -G Ninja -DCMAKE_BUILD_TYPE=Release
ninja -C ModernGekko/build

Then build the recompiled module for your disc with dist/RingOut-1.0-dist/setup.sh, which drives dolrecomp and compiles the generated C.

Releases are assembled by script, never by zipping a working directory — those hold the extracted disc, saves and build output. Each stage is built from an allowlist and then checked: no disc-derived files, no personal data, and for the desktop package, that the prebuilt runtime can actually load a module built from the sources shipped beside it.

.github/scripts/package-deck.sh     # Steam Deck zip
.github/scripts/package-dist.sh     # desktop Linux zip
.github/scripts/regen-source.sh     # refresh the GPL source shipment

Repository layout

Path What it is
ModernGekko/ the runtime fork — chassis, settings overlay, StaticRecomp core
ModernGekko/vendor/dolphin/ the vendored Dolphin tree the runtime is built from
DolRecomp/ the static recompiler fork (PowerPC → C)
dist/RingOut-1.0-dist/ the desktop redistributable: launcher, setup.sh, module build recipe
dist/RingOut-1.0-deck/ the Steam Deck package scaffolding
dist/shared/gc-art.py extracts the game's banner and icon on the player's machine
.github/scripts/ packaging, the privacy scan, the GPL source shipment, benchmarks
.github/deck-notes/ the toolchain notes kept on the test Deck's desktop
docs/measuring.md how performance is measured, and the checks that keep it honest
docs/profile-guided-optimisation.md PGO: what it is worth, and how it silently does nothing
work/mg_userdir/GameSettings/ the cheat lists this project authored (US, JP)

Everything is vendored as plain files — clone and build, no submodule init needed.


Credits

Almost none of the heavy lifting here is original. This is a thin layer on other people's work:

RingOut (jackpoison-prog/RingOut)

clang
Searching Database…

What is this?RingOut is a native PC port of a GameCube fighting game (disc ID GRSEAF), made by static recompilation rather than emulation: the original PowerPC executable is translated ahead of time into C, compiled for x86-64, and run as native code inside a Dolphin-derived runtime that handles graphics, audio, input and hardware emulation around it.
Is this basically an emulator, or something different?It is not a traditional emulator — every block of the game's own executable (535,368 instructions) is recompiled ahead of time into real native code, with 0 unknown opcodes and no interpreter fallback inside them. Only the OS exception vectors, about 0.2% of cycles, still run through an interpreter.
How do I get it running?Download either the desktop Linux or Steam Deck package from the Releases page, unzip it, and run it. On first launch it asks for your GameCube disc image (.iso/.gcm/.nkit.iso/.rvz), then extracts and recompiles it, which takes a few minutes and only happens once.
What do I need besides my own game disc?You need a GameCube disc image you already own, plus cmake, ninja, python3 and clang (or gcc) on your machine to compile the recompiled code, and a working Vulkan driver. setup.sh detects your distro and tells you the exact install command if something's missing.
Does it actually play start to finish, or is it still rough?It's fully playable start to finish and boots through the menu and into gameplay, but the project calls itself early: features sometimes land before they're polished, and something that worked in one release can break in the next.
Can I run it on Steam Deck as well as desktop Linux?Yes. Steam Deck gets its own package that needs no toolchain (the module is pre-built on a desktop and just copied over), running in both Desktop and Game Mode at 45–49 fps in a match; it can also build its own module directly on the device if you install a toolchain.
Does the download include the actual game?No. No game code or data is distributed with this project; you must supply a disc image of the game you already own, and setup extracts and recompiles it on your own machine.
Does netplay work, and how is it synced?Yes, two players can connect directly (LAN, VPN, or a forwarded port) with a lobby showing live ping and status. It's delay-based rather than rollback: both peers run the same inputs on the same frame, with an adjustable input buffer (1-20 frames, 5 by default), and this determinism has been validated byte-identical over 6,470 frames.
Can I install mods and HD texture packs?Yes. Drop an HD texture pack into userdata/Load/Textures/GRS/, or drop a downloaded mod archive into userdata/Load/Mods/ and it's automatically unpacked and listed in the in-game MODS tab; character skins get written directly into the game data.
What kind of performance work went into this?The project built a dedicated cycle-accurate benchmark and shipped real wins like profile-guided optimisation (-10.3% desktop, -14.1% Steam Deck) and inlining the paired-single helper chain (-43%), while documenting ideas it tried and rejected, like BOLT post-link layout and frame generation, because they measured worse in practice.
Size
87.7 MB
Stars
164
Age
1mo
Commits · 90 Days