Stable-Retro: gym-retro's Maintained Fork, and the Emulator Cores It Actually Ships
A fork of gym-retro with additional games, emulators and supported platforms
At a glance
- What is it?
- Stable-Retro turns classic console games into Gymnasium environments for reinforcement learning. The interesting part is not the game list, it is which emulator cores build on which platform, and what that costs you in setup work.
- Who is it for?
- Adopt Stable-Retro if you need a Gymnasium-compatible retro environment and you accept that ROMs and, for Sega Saturn or Dreamcast, BIOS files are your responsibility to obtain and import with python3 -m retro.import .
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository received new commits within the last day.
- What is it written in?
- Mainly C++, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
The gap Stable-Retro fills, and who is standing in it
OpenAI's gym-retro is described in the Stable-Retro README as being in maintenance, and the fork exists so that new games and features have somewhere to land. That is the whole premise: the interface did not change, the intake did. The README states that gym-retro "lets you turn classic video games into Gymnasium environments for reinforcement learning", and Stable-Retro keeps that contract while adding games, emulators and platforms.
The audience is narrow and specific. If your research depends on a console title that gym-retro never integrated, and that title runs on one of the systems in the table (Atari 2600, NES, SNES, Nintendo 64, Nintendo DS, Gameboy/Color, Gameboy Advance, Sega Genesis, Master System, CD, 32X, Saturn, Dreamcast, PC Engine, arcade machines), Stable-Retro is the shortest path to a Gymnasium env. If your work is Atari 2600 or NES, the calculus is different, and the alternatives section below explains why.
Two things about the framing are worth noticing. First, the project claims over 1000 integrated games, including platformers, fighters, sports, puzzle, shmups, beat-em-ups, racing and a set of RPGs the README itself labels experimental. Second, the documentation site is described in the README as "work in progress". That is an honest label and it matters: the repository, not the site, is the source of truth for installation detail.
Emulator cores are the real feature matrix, not the game count
The supported-systems table is where adoption decisions actually get made, because a missing core means a game you cannot run regardless of how many integrations exist. Three footnotes in that table are load-bearing.
Nintendo 64 is marked with a dagger on Linux and Windows and a dash on Apple. The footnote says the core is built by default when BUILD_N64=ON and OpenGL headers are available, and that the build skips the N64 core if the headers are missing. So an N64 environment can fail to exist on a machine that installed the package successfully. You find out at import or build time, not at pip time.
Gameboy and Gameboy Color carry an asterisk for Apple: on Apple Silicon (arm64), Gambatte is skipped by default in the CMake build. That is a default, not a hard block, but it means the Apple Silicon path is not equivalent to the Intel path out of the box.
Dreamcast is the most constrained: a double dagger means it is only available when hardware rendering is enabled (ENABLE_HW_RENDER=ON), and the README states hardware rendering support is currently Linux-only. Dreamcast on Windows or Apple is not a configuration problem you can solve with a flag. The core is not there.
Read together, the table describes a project where Linux is the reference platform, Windows works through WSL2, and macOS is supported with two named exceptions. That is a reasonable shape for a research tool, and it is also the first thing to check against your own hardware before you plan an experiment.
What an integration actually contains
The README is explicit that a game integration is not just a ROM slot. Each integration has files listing memory locations for in-game variables, reward functions built on those variables, episode end conditions, savestates at the beginning of levels, and a file containing hashes of ROMs that work with those files.
That layout tells you where the research surface is. The reward function is not a generic score signal; it is derived from named memory addresses in a specific ROM revision, which is why the hash file exists. If your ROM's SHA-1 does not match, the integration's memory map may point at the wrong bytes and your reward will be meaningless rather than obviously broken. The README says most ROM hashes are sourced from their respective No-Intro SHA-1 sums.
It also explains why adding a game is real work rather than a config edit, and why the project ships an integration tool with a video playlist covering its use. The savestates at level beginnings are the other half of the design: they give you deterministic episode starts without replaying an intro, which is the difference between a usable benchmark and a slow one.
Getting it running: install, import, train
The README gives two installation paths. The simple one is pip3 install stable-retro, with a fallback of pip3 install git+https://github.com/Farama-Foundation/stable-retro.git for platforms where the wheel does not work. If you intend to integrate new ROMs, states or emulator cores, or edit an existing env, the README says to clone the repository and run pip3 install -e . from inside it.
ROMs are not included. You obtain them yourself, put them in a folder, and run python3 -m retro.import . from that folder. The README says the import checks the checksum and, on a match, moves the ROM into the related game folder inside stable-retro. Sega Saturn and Dreamcast additionally need a BIOS, with a documented list of BIOS names and checksums in docs/core_bios.md. The one ROM shipped for testing is Airstriker, a non-commercial Sega Genesis title by Electrokinesis, which is why the example environment is Airstriker-Genesis-v0.
The training example is short. Install system packages (the README lists python3, python3-pip, git, zlib1g-dev, libopenmpi-dev and ffmpeg for the Debian/Ubuntu path), then pip3 install stable_baselines3[extra] with a note that you need a Stable Baselines 3 version that supports Gymnasium, then cd retro/examples and python3 ppo.py --game='Airstriker-Genesis-v0'. Platform-specific detail lives in docs/linux_installation.md and docs/macos_installation.md, covering Ubuntu/Debian dependencies, N64 and Dreamcast core setup, a WSL2 guide and Homebrew dependencies for Apple Silicon.
Stated specs: Python 3.10 through 3.14, Windows 10 and 11 via WSL2, macOS 10.13 and 10.14, Linux manylinux1 with Ubuntu 24.04 recommended, and a CPU with SSE3 or better.
Where the design bites back
The most consequential limitation is not a bug, it is the ROM pipeline. Stable-Retro cannot ship the games most people want to train on, so every serious use begins with you sourcing ROMs and matching SHA-1 hashes against the integration's expectations. Get the hash wrong and, as noted above, the failure mode is a silently wrong reward rather than an error.
The second is the core matrix. A pip install that succeeds tells you nothing about whether the N64, Dreamcast or Apple Silicon Gameboy cores are present. Those are build-time decisions driven by BUILD_N64, ENABLE_HW_RENDER and the CMake defaults documented in the README footnotes.
The third is the RPG category, which the README marks experimental. Games like Pokemon Red, Legend Of Zelda, Final Fantasy and Dragon Warrior have long horizons and sparse reward signals, and the integration quality for them is not presented as equivalent to the platformers and fighters. Treating an experimental integration as a benchmark is a mistake the README does not make for you.
Finally, the documentation site is a work in progress. Installation answers are more reliable in the repository's docs directory and in the README than on the site, and the README itself points to GitHub Issues and the Farama Foundation Discord for support rather than a formal support channel.
Airstriker-Genesis-v0 versus gymnasium's built-in Atari
The honest alternative depends on what you are training on. If your target is Atari 2600, gymnasium already ships Atari environments built on the Arcade Learning Environment, and the practical difference is the ROM pipeline: ALE packages its own ROM set, while Stable-Retro requires you to supply ROMs and run python3 -m retro.import . before anything runs. For Atari work, Stable-Retro adds a step and a hash-matching failure mode without adding games you cannot already get.
The comparison flips for everything else in the table. NES, SNES, Genesis, Saturn, Dreamcast, PC Engine and the rest are not covered by gymnasium's built-in environments, and that is precisely the space Stable-Retro occupies. Within that space the closest comparison is gym-retro itself, and the README's stated difference is maintenance: gym-retro no longer takes new games or features, while Stable-Retro invites PRs for both. If you are already running gym-retro and your games exist there, migration buys you Gymnasium compatibility and future additions; if your games do not exist there, there is no migration question, only whether the core for your system builds on your machine.
Licence and the cost of staying current
The repository is MIT, and the README points to LICENSES.md for the licences of the individual cores. Those are two different things. The MIT grant covers the project's own code; the emulator cores it bundles carry their own terms, and the README's instruction to consult LICENSES.md is the operative one. Nothing here constitutes legal advice, and if you plan to redistribute a build or ship a trained agent commercially, the core licences are the file to read rather than the repository's top-level licence.
On maintenance cost, the material supports a few concrete observations. Release cadence in the supplied list runs v0.9.9 in February 2026, v1.0.0 in April 2026 and v1.0.1 in June 2026, with the last push to the repository in September 2026. The Python support window is 3.10 through 3.14, which is wide but not open-ended; a Python version bump is a real upgrade event because the package builds C++ cores. The platform docs distinguish Ubuntu/Debian, Apple Silicon and WSL2 paths, so an environment that works on one developer's machine is not automatically reproducible on another's. Pinning your Python version and recording which cores built successfully is cheaper than rediscovering the N64 or Dreamcast footnotes after a fresh install.
Editorial conclusion
Adopt Stable-Retro if you need a Gymnasium-compatible retro environment and you accept that ROMs and, for Sega Saturn or Dreamcast, BIOS files are your responsibility to obtain and import with python3 -m retro.import . Do not adopt it if you need Atari 2600 or NES specifically: ALE and gymnasium's own built-in Atari environments cover that ground without a separate ROM pipeline, and stable-retro's MIT licence does not extend to the individual emulator cores listed in LICENSES.md. Before you commit to a training run, verify three things on your own machine: that the core for your target system actually built (Nintendo 64 is skipped when BUILD_N64 is off or OpenGL headers are missing, Gambatte is skipped by default on Apple Silicon, and Dreamcast needs ENABLE_HW_RENDER=ON plus Linux), that your ROM hashes match the No-Intro SHA-1 sums the integrations expect, and that the reward and episode-end variables defined in your chosen game's data files line up with the behaviour you want to learn.
Community notes