🚀 Blazing-fast Stable Retro fork with native vectorization and preprocessing 🚀
env-StableRetro-turbo is a Python library for reinforcement-learning developers who need faster batched rollouts from classic console games. It keeps Stable Retro's game integrations and single-environment API, and adds RetroVecEnv, a Gymnasium vector environment that steps many libretro emulators and preprocesses observations in native code.
Install the package, import your legally obtained ROMs, and use the upstream-compatible stable_retro import. The native path is useful for parallel training workloads that would otherwise spend substantial time crossing between Python wrappers and individual emulator instances.
Install
Release wheels require Python 3.14 and support macOS on Apple Silicon and Linux on x86-64.
uv venv --python 3.14
source .venv/bin/activate
uv pip install env-stableretro-turbo
python -m stable_retro.import /path/to/your/roms
ROMs are not included. The importer matches supported ROMs to Stable Retro's game integrations.
Check the games available on your machine, then open one in the interactive player:
stable-retro-turbo play --list
stable-retro-turbo play nes
stable-retro-turbo play SuperMarioBros-Nes-v0 --press START
stable-retro-turbo play Breakout-Atari2600-v0 --mode 32 --difficulty A
Pass a full game ID such as SuperMarioBros-Nes-v0, or use all to open one imported game per platform. Add --show-obs to display the raw game beside its PPO-style preprocessed observation.
--press BUTTON[:COUNT] applies repeatable startup inputs using the selected
game's own button names. Atari games additionally accept --mode N, which
pulses the console SELECT switch N times before RESET, and --difficulty A
or --difficulty B, which sets both console difficulty switches. For example,
Breakout mode values 0, 4, 8, …, 44 select its twelve one-player
cartridge variants. Use --state none to launch a game from its power-on state.
Use
import gymnasium as gym
import numpy as np
env = gym.make_vec(
"stable_retro:StableRetro-Turbo-v0",
game="SuperMarioBros-Nes-v0",
state="Level1-1",
num_envs=32,
num_threads=16,
render_mode="rgb_array",
obs_crop=(32, 0, 0, 0),
obs_crop_mode="mask",
obs_resize=(84, 84),
obs_resize_algorithm="area",
obs_grayscale=True,
obs_layout="chw",
frame_skip=4,
frame_stack=4,
maxpool_last_two=True,
info_filter="terminal",
)
obs, infos = env.reset(seed=123)
obs, rewards, terminations, truncations, infos = env.step(
env.action_space.sample()
)
done = terminations | truncations
if done.any():
obs, reset_infos = env.reset(options={"reset_mask": done})
The module-qualified ID imports the package and registers the factory. This ID
is vector-only and requires an explicit game; RetroVecEnv remains available
for direct use. Stable Retro's existing scalar stable_retro.make() and
RetroEnv APIs are unchanged and are not registered under the Turbo ID.
RetroVecEnv uses Gymnasium's disabled-autoreset semantics. A finished lane keeps its terminal observation and cannot be stepped again until it is selected by a masked reset; unselected lanes keep their emulator state, RNG stream, frame stack, and sticky-action history.
Turbo Vector API v2
RetroVecEnv implements the strict Turbo Vector API v2:
metadata["turbo_api_version"]is2,metadata["transition_transport"]is"numpy", andmetadata["render_modes"]advertisesrgb_array.- Immutable
capabilitiesandsignal_schemadeclarations describe supported features and the dtype, shape, and reset/step availability of every signal. buttons,action_mode,action_preset,action_table,action_meanings, andaction_table_hashexpose the resolved action semantics without provider-specific probing.state_catalogis an immutable ordered tuple. Callers select reset states with anint32state_indicesarray and inspect the read-only active indices withactive_state_indices(); state sampling and lane routing remain caller-owned.observation_ownershipandobservation_buffer_depthdeclare the exact lifetime of returned observations. Rendering is opt-in: withrender_mode="rgb_array",render_lane(index)renders one lane,get_images()renders all lanes, andrender()renders lane zero. With the defaultrender_mode=None, the first two methods returnNoneandget_images()returns oneNoneentry per lane.
When env.supports_live_snapshots is true, live positions can be captured
without advancing emulation and restored into any lane of the same environment:
capture_mask = np.zeros(env.num_envs, dtype=np.bool_)
capture_mask[0] = True
captured = env.capture_snapshots(capture_mask)
restore_mask = np.zeros(env.num_envs, dtype=np.bool_)
restore_mask[3] = True
starts = [None] * env.num_envs
starts[3] = captured[0]
obs, infos = env.reset(
options={"reset_mask": restore_mask, "snapshots": starts},
)
env.close()
Handles are reusable, session-local, and intentionally not pickleable. A
single masked reset can mix snapshot starts with ordinary state_indices;
infos["start_source"] is int8: 0 means an environment state and 1
means a snapshot.
Scripted scenarios and cores that cannot serialize exact state report the
capability as unavailable.
The fast path also supports:
- native crop, mask, resize, grayscale, layout conversion, frame skip, frame stack, and two-frame max-pooling;
- ordered reset-state catalogs (including power-on as index zero when no saved
state exists) with explicit per-lane
state_indices; state sampling and curriculum routing stay with the caller; - copy-safe, safe-view, and benchmark-only unsafe-view observation ownership;
- sticky actions, random no-op starts, reward clipping, and native info filtering;
- Atari through the packaged Stella core, using the same
RetroEnvandRetroVecEnvAPIs.
The inherited RetroEnv API remains available for single-environment use. RetroVecEnv supports one player, image observations, and no movie recording.
Develop
git clone https://github.com/tsilva/env-StableRetro-turbo.git
cd env-StableRetro-turbo
uv sync --frozen
Source builds require Python 3.14, CMake, a C/C++ compiler, and the platform dependencies needed by the selected emulator cores.
Commands
Run these commands from the repository root:
uv run --frozen stable-retro-turbo play --list # list imported games by platform
uv run --frozen --with pytest pytest tests/test_python/test_cli.py # run quick tests
uv run --frozen --with build python -m build # build source and wheel artifacts
Core and semantic changes additionally use a pinned original-Stable-Retro
oracle for Super Mario Bros. and Breakout. The compared fields, reproducible
commands, and release receipt gate are documented in
docs/semantic_oracle.md.
Benchmark
In an official correctness-gated
TurboBench 1.0.0 comparison on
the matched supermario/canonical-v1 workload,
stable-retro-turbo==1.0.1.post37 measured
2.1248x to 2.2465x the throughput of original stable-retro==1.0.1 at 1, 16,
and 32 environments. This is a workload-specific result, not a claim across all
games or emulator cores. See BENCHMARKS.md for exact SPS,
paired confidence intervals, protocol, host details, provenance, and the
reproduction command. Install the benchmark CLI with:
uv tool install \
--exclude-newer-package turbobench-cli=2026-08-12T00:00:00Z \
turbobench-cli==1.0.0
Notes
- The distribution is
env-stableretro-turbo; the Python package isstable_retro. The upstream-compatibleretroimport remains available for scalar integrations, while new code should importstable_retro. RetroVecEnvimplements Gymnasium's vector API directly. It is not a Stable-Baselines3VecEnv, and Stable-Baselines3 is not a runtime dependency.- A scalar reset seed expands to
seed + lane_index. Seed sequences must contain one integer orNoneper lane. state_catalogpreloads an ordered saved-state catalog. Select reset lanes withreset_maskand their exact catalog entries withstate_indices; Turbo does not sample states.capture_snapshots(mask)returns lane-aligned live handles for exact same-instance continuation. The caller owns archive selection, eviction, and curriculum policy;handle.nbytesexposes approximate payload size.active_state_indices()returns a read-only NumPy view. Copy it when you need a stable snapshot.- Stable Retro remains the source for inherited game, integration, and emulator documentation.
- Bundled emulator cores have their own licenses; see
LICENSES.md.
Local credentials
Private local values declared in .keyenv.toml live in macOS Keychain. Run
keyenv doctor to verify them and launch credential-dependent commands with
keyenv run -- <command>. Python, Node, and their child processes receive the
values through their normal environment APIs. Keep only public or non-secret
configuration in dotenv files.
Architecture
License
Metadata
Release files for env-stableretro-turbo 1.0.1.post44
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| env_stableretro_turbo-1.0.1.post44.tar.gz | 96.2 MB | With provenance | Details for env_stableretro_turbo-1.0.1.post44.tar.gz |
Built distributions (wheels)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| env_stableretro_turbo-1.0.1.post44-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl | CPython 3.14 | CPython 3.14 | Linux glibc 2.28+ x86-64, Linux glibc 2.27+ x86-64 | Details for env_stableretro_turbo-1.0.1.post44-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl |
| env_stableretro_turbo-1.0.1.post44-cp314-cp314-macosx_14_0_arm64.whl | CPython 3.14 | CPython 3.14 | macOS 14.0+ ARM64 | Details for env_stableretro_turbo-1.0.1.post44-cp314-cp314-macosx_14_0_arm64.whl |
Total release size: 273.6 MB
Release files / env_stableretro_turbo-1.0.1.post44.tar.gz
| Download URL | env_stableretro_turbo-1.0.1.post44.tar.gz |
|---|---|
| Size | 96.2 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
39270faa21c3523aa6528dc1763b13208dfea66d799761172ba8cd5ff78e72cb
|
|
BLAKE2b-256 checksum How to use checksums |
3a7a394f308bc7dda55f5974fee28ece6a74fcae06fe682db233d3f998bcaa69
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 20, 2026.
Transparency logRelease files / env_stableretro_turbo-1.0.1.post44-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
| Download URL | env_stableretro_turbo-1.0.1.post44-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl |
|---|---|
| Size | 91.6 MB |
| Tags | CPython 3.14 Linux glibc 2.27+ x86-64 Linux glibc 2.28+ x86-64 |
|
SHA-256 checksum How to use checksums |
bbc59d33fa51b6f92005d34e3b4da4f3d3ef6e4019f9d432da8467333952e918
|
|
BLAKE2b-256 checksum How to use checksums |
790e9e34e4fda94e5eac98d140ed158547639128c918beb21c5d8002d58e15b4
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 20, 2026.
Transparency logRelease files / env_stableretro_turbo-1.0.1.post44-cp314-cp314-macosx_14_0_arm64.whl
| Download URL | env_stableretro_turbo-1.0.1.post44-cp314-cp314-macosx_14_0_arm64.whl |
|---|---|
| Size | 85.9 MB |
| Tags | CPython 3.14 macOS 14.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
70fe4c4aab83c025c85a2d03d3efe16b2a377531dae2e784a5bb9c9adb14dbbf
|
|
BLAKE2b-256 checksum How to use checksums |
6cf44e2d0cb8be5329d0b7194bf2a14b8c100d0ce564398fbb3d5e8592b1035c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 20, 2026.
Transparency logSecurity for env-stableretro-turbo 1.0.1.post44
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 3 files in this release have been uploaded with provenance metadata.
Attestation for env_stableretro_turbo-1.0.1.post44.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 20, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.