/// FIELD NOTES FROM A SELF-AWARE GAME SITE
RetroArch Cores 2026: 200+ in 12 Steps, 40 Min
You installed RetroArch. You opened Load Core. It was empty. Nothing is broken — this is the design.
RetroArch is not an emulator. It is a frontend: a chassis, a shell, a universal remote for other people's emulators. Those emulators are separate modules called cores, and they load at runtime through a thin C API named libretro. A clean install ships the chassis and none of the engines. Newcomers read this as a bait-and-switch. Anyone who has looked at the licensing — dozens of emulators, each under its own license, several of them one cease-and-desist away from a bad afternoon — reads it as the only defensible way to ship the thing.
The payoff of that architecture is absurd reach: one interface, one shader pipeline, one save-state format, one netplay stack, running everything from an Atari 2600 to a PlayStation 2, on Windows, Linux, macOS, Android, iOS, a jailbroken PlayStation, or a $60 handheld from a company you have never heard of. The cost is that you decide which of the twelve PlayStation cores you actually want, and RetroArch will not decide for you.
This tutorial takes you from an empty Load Core menu to a working, updatable, per-game-tunable library — twelve steps, roughly forty minutes, on RetroArch 1.22.2. We cover the update order everyone gets wrong, the cores worth arguing about, the override hierarchy nobody reads, and the BIOS files the project legally cannot hand you.
What a Core Actually Is (and Why RetroArch Ships None)
Before you download anything, understand what you are downloading. Half the support threads on the libretro forums are people who thought a core was a plugin, a theme, or a ROM. It is none of those.
Libretro is the API nobody sees
libretro is a small, boring C interface. On one side sits the frontend — RetroArch — which owns the window, the audio device, the input, the configuration, the menu, the shaders, netplay, and save states. On the other side sits the core, which owns exactly one thing: emulating a machine. The core exposes a handful of functions (the frontend calls retro_run() once per frame), hands back a framebuffer and an audio buffer, and receives input. That is the entire contract.
That clean split is why a single save-state format and a single CRT shader work identically across a Game Boy core and a PlayStation core. Neither core knows what a shader is; RetroArch does the post-processing after the core hands over its pixels. RetroArch itself is GPLv3, with a GitHub repository sitting north of 13,200 stars; the cores carry whatever licenses their upstream emulators carry, which is exactly why they are not bundled. Physically, a core is a shared library: snes9x_libretro.so on Linux and Android, .dll on Windows, .dylib on macOS. Alongside each one lives a matching .info file — the manifest that tells RetroArch what the core is called, what systems it plays, and which BIOS files it expects.
"200+ cores" is a catalogue, not a promise
You will see the number 200+ everywhere, including the official site. It is real, and it is also misleading. That figure is the entire libretro catalogue across every platform and CPU architecture the buildbot compiles for. Your Core Downloader shows only the builds compiled for your exact operating system and instruction set. A Windows x64 desktop sees a long list. An armv7 webOS television sees a much shorter one — the webosbrew/retroarch-cores project rebuilt its set in December 2025 and lists roughly 170 armv7 cores plus an experimental aarch64 tier. Some cores are desktop-only by nature and will never appear on a phone at all. So treat 200+ as the size of the warehouse, not the size of your shelf.
The Steam exception: 10 cores, no downloader
If you got RetroArch from Steam, everything above changes. The Steam build ships ten cores in the base install — Mupen64Plus-Next, Kronos, PCSX ReARMed, Stella, SameBoy, mGBA, Mesen, Mesen-S, Genesis Plus GX, and Final Burn Neo — and it removes the Core Downloader entirely. Every other core is distributed as free DLC on the store page: the same binaries the buildbot produces, delivered by Valve instead. Cores cost nothing, exactly like RetroArch itself. So if you are on Steam hunting for an "Update Cores" button that does not exist, stop hunting — open the DLC tab on the store page and install the cores you want from there. This is the single most common "where did my Online Updater go" question, and the answer is: Valve took it.
Prerequisites: Versions, Hardware, and BIOS
Three things gate a successful core install: the right frontend version, silicon that can actually run the core you pick, and BIOS files you must supply yourself. Skip any of them and you will spend your forty minutes reading logs instead of playing games.
Software: RetroArch 1.22.2, and the version to avoid
The current stable line is 1.22.2, released November 20, 2025. Get it from retroarch.com or the GitHub releases page. One caveat that matters: 1.22.0 shipped with a shader black-screen bug on certain content, fixed in 1.22.1 and 1.22.2 — do not run .0. The 1.21.0 release earlier in 2025 was the milestone that repaired Apple Vulkan, CoreMIDI, and 3DS support; 1.22.2 later added a dual-core-mode toggle directly inside the Dolphin (GameCube/Wii) core, which is worth a real framerate on multi-core CPUs. Update the frontend first, before you touch a single core: cores are compiled against the current libretro API and the current core-info version, and a stale frontend loading fresh cores is a reliable way to manufacture "failed to load" errors that have nothing to do with the core.
Hardware: the CPU tax nobody warns you about
Cores are wildly unequal in cost, and no configuration flag repeals physics. Cycle-accurate cores burn clock cycles by design: bsnes in its accuracy profile wants roughly a 4 GHz core to hold full-speed SNES. Beetle PSX HW at 4x internal resolution with the Vulkan renderer is a genuine GPU-and-CPU load. LRPS2, the PlayStation 2 core, is a PCSX2 fork and expects a modern x86_64. At the other end, PCSX ReARMed emulates a PlayStation on a phone SoC without breaking a sweat. Match the core to the machine. A Raspberry Pi or a budget ARM handheld will not run bsnes accuracy or LRPS2, and it never will — if that is your hardware, read our RetroPie-on-PC breakdown for where the Pi actually tops out, or our Retroid Pocket 6 versus 5 comparison for what a modern Snapdragon handheld can and cannot brute-force.
BIOS files: the legal gray you supply yourself
Many systems refuse to boot without a BIOS or firmware dump. PlayStation needs an scph image; PlayStation 2 under LRPS2 needs a real PS2 BIOS; Sega CD, Neo Geo, and several others have their own requirements; Game Boy Advance takes an optional gba_bios.bin for accuracy. RetroArch and libretro do not distribute any of these — they are copyrighted, and shipping them is precisely the legal exposure the whole core-separation architecture exists to avoid. You dump them from hardware you own. They live in the system directory, and the filename must match exactly what the core expects — the right file under the wrong name is, to the core, no file at all. The per-core BIOS names and MD5 checksums are documented in the libretro core documentation; check them before you assume the dump is bad.
Installing Cores: 12 Steps, About 40 Minutes
Here is the whole procedure, start to finish. It is ordered deliberately — the first four steps are the ones people skip, and skipping them is why the other eight fail. Each step carries its rationale, because a step you understand is a step you can debug.
- Update RetroArch to 1.22.2. Cores and their info files are built against the current API; an outdated frontend is the most common invisible cause of load failures. On Windows use
winget upgrade Libretro.RetroArch; on Steam Deck or Linux Flatpak useflatpak update org.libretro.RetroArch; elsewhere grab the installer from the releases page. - Online Updater → Update Core Info Files. This is the step everyone gets wrong. The core-info manifest tells RetroArch what cores exist, what systems they play, and what BIOS each needs. Run it before downloading anything. Skip it and the Core Downloader is empty or your freshly downloaded cores report themselves as "unrecognized" and refuse to load.
- Update Assets, Databases, Overlays, Cheats, and Shaders. Optional but recommended in the same pass. Playlists, thumbnails, and content scanning depend on the databases; overlays and shaders are referenced by cores and per-game configs. Doing it now saves a second trip later.
- Open Load Core → Download a Core (equivalently, Online Updater → Core Downloader). If the entry is missing, the menu item is hidden: Settings → User Interface → Menu Item Visibility → Show Core Downloader. Remember this list is filtered to your platform and architecture — it is your shelf, not the whole warehouse.
- Find your system and pick the recommended core. Cores are named
System (Core), e.g.Nintendo - SNES/SFC (Snes9x)orSony - PlayStation (Beetle PSX HW). You can type a system name to filter. Pick by the guidance in the next section, not by whichever name you recognize. - Download the core and confirm it appears in Load Core. The binary lands in your cores directory next to its
.infofile. Verifying it shows up in Load Core now — before you have a game riding on it — turns a silent failure into a visible one. - Place BIOS files in the system directory with exact filenames. PlayStation, PS2, Sega CD, Neo Geo and friends will boot to a black screen or a "cannot find BIOS" error without them. The project cannot ship these; you supply them, named exactly as the docs specify.
- Set the video driver. On desktop and on Android, prefer Vulkan where the core supports it — hardware renderers like Beetle PSX HW (Vulkan) and the ParaLLEl RDP need it. Settings → Drivers → Video. Keep
glas a fallback for cores or GPUs that misbehave under Vulkan. - Load content with the core and confirm it runs. Load Content, point it at a ROM or disc image, pick the core, and watch it boot. If it stalls, the log (below) tells you why — usually a missing BIOS or a driver mismatch, rarely the core itself.
- Associate a core with the content or playlist. Set a default core so a scanned playlist launches the right emulator on a double-click, and different systems map to different cores automatically. This is what turns a pile of cores into a usable library.
- Update Installed Cores periodically. Online Updater → Update Installed Cores refreshes every downloaded core in a single pass — the fastest way to stay current. Always run Update Core Info Files first so the manifest matches the binaries.
- Back up your
config/andplaylists/directories. Your overrides, input remaps, per-game options, and playlists live here, and they represent more accumulated tuning than the cores themselves. A bad update or a reinstall that wipes them is an afternoon you do not get back.
Why the update order is not optional
Steps 1 through 4 exist in that sequence for a mechanical reason. RetroArch decides what a core is from its info file. If the info files are older than the cores, RetroArch sees a binary it has no manifest for and marks it unrecognized — the core is physically present and still "fails to load." Updating the frontend, then the info files, then the cores, keeps all three layers in lockstep. Reverse it and you get a downloader that looks empty and cores that appear broken, and you will blame the core when the fault is ordering.
Expected output: what a working install looks like
After steps 6 and 9, your cores directory and a successful load should look roughly like this. The exact core list depends on what you downloaded; the shape is the point.
$ ls ~/.config/retroarch/cores/
beetle_psx_hw_libretro.so genesis_plus_gx_libretro.so
mesen_libretro.so mgba_libretro.so
mupen64plus_next_libretro.so snes9x_libretro.so
beetle_psx_hw_libretro.info genesis_plus_gx_libretro.info
...
$ ls ~/.config/retroarch/cores/*.so | wc -l
14And a clean boot in the log (Settings → Logging, or run with a verbose flag) reads like this — note the API version line and the pixel-format line, both signs the handshake between frontend and core succeeded:
[INFO] [Core]: Loading dynamic libretro core from:
"~/.config/retroarch/cores/beetle_psx_hw_libretro.so"
[INFO] [Core]: Version of libretro API: 1, Compiled against API: 1
[INFO] [Environ]: SET_PIXEL_FORMAT: RGB565.
[INFO] [Content]: Loading content file:
"~/roms/psx/Gran Turismo 2 (USA).chd".
[INFO] [Core]: Content ran for 1 frames.Associating a core with content and playlists
Step 10 deserves a note, because it is what people mean when they say RetroArch "just works" for someone else and not for them. Once a core is installed, open a playlist entry or Load Content result, go to the Quick Menu, and set it as the default core for that content or that whole playlist. From then on, launching a PlayStation disc uses your chosen PS1 core and a SNES ROM uses your chosen SNES core, with no per-launch prompt. You can also override this per single game — the same content can point at Beetle PSX HW for the game you care about accuracy on and PCSX ReARMed for the one you just want to boot fast. That per-title flexibility is the entire reason to keep multiple cores for one system installed.
Choosing the Right Core, System by System
This is where RetroArch's refusal to choose for you actually costs you time. For some systems the answer is obvious and boring. For three of them, asking the question in public will start a fight. Here is the deadpan version.
The systems with one obvious answer
Do not overthink these. NES: Mesen — PPU-accurate, supports every mapper anyone has documented, and ships a built-in debugger for the curious. Game Boy / Color: Gambatte or mGBA, either is fine. Game Boy Advance: mGBA — accurate, light, the sane default; keep the optional BIOS for the correct boot logo and a handful of edge cases. Sega 8/16-bit: Genesis Plus GX, which is 100% compatible across Mega Drive, Mega CD, Master System, Game Gear, SG-1000, and the Pico, and carries a pedigree from the Wii homebrew scene. One trap: Genesis Plus GX does not emulate the 32X — that is PicoDrive's job. Arcade: Final Burn Neo, a curated romset reaching back to 1970s hardware, documented in the core list. SNES: bsnes in its accuracy profile if you have the ~4 GHz to spare; Snes9x for everything else and for every handheld, where it is both fast and faithful enough that you will not notice the difference in motion.
The systems that start fights: N64, PS1, PS2
Nintendo 64 is the swamp it has always been. The mainline core is mupen64plus-next, which bundles GLideN64 for HLE plus angrylion and the ParaLLEl-RDP/RSP plugins for accuracy — see the mupen64plus core page. Be warned: it regressed in early 2025, and specific titles — Stunt Racer 64, World Driver Championship — stopped loading; the community response was to pin a January nightly. For low-level accuracy there is Parallel N64 (Vulkan LLE), with narrower compatibility. There is no clean winner here; there never has been.
PlayStation is a three-way choice with an actual right answer per context. Beetle PSX HW (Mednafen lineage, hardware renderer) is the most accurate and the heaviest — the desktop pick, with upscaling, PGXP geometry correction, and true-color dithering. SwanStation (a DuckStation libretro port) is the pragmatic middle ground. PCSX ReARMed is the ARM-optimized featherweight that powers the budget-handheld world — muOS, ROCKNIX, and the OnionOS firmware you will meet in our Miyoo Mini Plus versus RG35XX writeup, where the firmware, not the silicon, decides the experience.
PlayStation 2 finally arrived in the downloader with the 1.22 line in November 2025, as LRPS2 — a hard fork of PCSX2. Read the constraint carefully: it is x86_64 only. Windows, Linux, and macOS-under-Rosetta, full stop — no Android, no iOS, no ARM Linux. Its new ParaLLEl-GS renderer, by Themaister, offers Vulkan/GL/D3D compute paths plus a software-accuracy fallback. It needs a real PS2 BIOS; the GameIndex database is now embedded in the core itself. The libretro announcement has the full technical story.
The 3DS problem: Citra is dead, Azahar lives
Citra was taken down — collateral damage from the Yuzu litigation — and for a while the libretro ecosystem had no viable 3DS option at all. The successor is Azahar, a merge of the strongest Citra forks (PabloMK7's build and Lime3DS). Its first official libretro core shipped in 2125.0 Alpha 4, built for six operating systems — Linux, Windows, macOS, Android, iOS, and tvOS — and the line has since advanced to 2126.0 (release-candidate as of mid-2026). Note two deliberate omissions: it dropped support for encrypted games and for the Nintendo CDN (you now use the Artic Setup Tool), and the libretro binaries are stripped for a smaller Android core. Track releases on the Azahar GitHub. The full stable 2125.0 will surface the core in RetroArch's built-in downloader; until then it is a manual install.
Overrides: Per-Game, Per-Core, Per-Directory
The reason to keep a single global config and still get different behavior per game is the override system. It is powerful, it is documented, and it is misunderstood by nearly everyone, because "override" refers to three separate mechanisms that live in three separate files.
The hierarchy: game beats directory beats core beats global
RetroArch resolves configuration from least to most specific. It loads the global retroarch.cfg, then applies a core override, then a content-directory override, then a game override — and the most specific one wins any conflict. The precedence, top to bottom, is game > content-directory > core > global. The files live under config/<Core Name>/: <Core Name>.cfg for the core scope, <dir>.cfg for the content directory, and <game>.cfg for a single title. For any of these to auto-apply on load, keep auto_overrides_enable set to true. The full behavior is in the libretro overrides guide.
Three different things people call "overrides"
Here is the distinction that ends most confusion. First, config overrides are RetroArch settings — video, audio, input driver, aspect ratio — saved per scope as .cfg files. Second, core options are the emulator's own knobs — renderer, internal resolution, PGXP mode — stored globally in retroarch-core-options.cfg or per game in config/<core>/<game>.opt; per-game core options require game_specific_options = true. Third, input remaps are button maps stored in config/remaps/<core>/<game>.rmp, gated by auto_remaps_enable. Three mechanisms, three file types, three toggles. Treating a core option like a config override — or expecting one file to hold all three — is the single most common override mistake.
Saving without nuking your global config
Do this from the menu, not by hand-editing while the game runs. Quick Menu → Overrides → Save Core Override / Content Directory Override / Game Override writes only the delta from global — not a full copy of your config. For core options specifically: Quick Menu → Core Options → Manage → Create game-options file. What you must not do is flip config_save_on_exit and expect scoping — that writes your live settings straight into the global config and quietly poisons every other game. A minimal core override for Beetle PSX HW looks like this:
# config/Beetle PSX HW/Beetle PSX HW.cfg
video_fullscreen = "true"
video_scale_integer = "false"
aspect_ratio_index = "21"
video_shader_enable = "true"The core's own options — the renderer, the upscale factor, the geometry correction — live separately. These are the real Beetle PSX HW option keys, set globally:
# retroarch-core-options.cfg (global core options)
beetle_psx_hw_renderer = "hardware_vk"
beetle_psx_hw_internal_resolution = "4x"
beetle_psx_hw_pgxp_mode = "memory only"
beetle_psx_hw_dither_mode = "internal resolution"
beetle_psx_hw_widescreen_hack = "disabled"And when one specific title wants different treatment — say, a game that tolerates the widescreen hack and full PGXP where others glitch — you write a per-game options file that overrides just those keys:
# config/Beetle PSX HW/Gran Turismo 2 (USA).opt
beetle_psx_hw_widescreen_hack = "enabled"
beetle_psx_hw_pgxp_mode = "memory + CPU"Run-Ahead, Second Instance, and the Latency Question
Once your cores run, the next thing worth tuning is input latency — the gap between pressing a button and the game reacting. RetroArch can make emulated games feel faster than the original hardware, which sounds like marketing until you understand the mechanism.
What Run-Ahead actually does (1 to 3 frames)
Under Settings → Latency → Run-Ahead, RetroArch runs the core forward by 1 to 3 frames, keeps the newest frame, and internally rolls back. Because most emulated games buffer input for a frame or two before acting on it, skipping ahead past that internal buffer removes the emulator's inherent lag — sometimes dropping below what the real console did. One frame is the safe, universal setting. Two or three helps cores with heavier internal latency. The cost is straightforward: run-ahead re-runs the frame, so it multiplies the core's CPU load by the number of look-ahead frames.
Second Instance and the audio-glitch tax
Single-instance run-ahead re-simulates the whole frame, audio included, which on some cores produces crackle. The fix is Second Instance: RetroArch spins up a second copy of the core purely to do the look-ahead, leaving the primary instance's audio untouched. It roughly doubles the core's CPU and RAM footprint, which is trivial on a desktop and a real consideration on a thermally limited handheld. Enable it and the config reads:
# retroarch.cfg (latency section)
run_ahead_enabled = "true"
run_ahead_frames = "1"
run_ahead_secondary_instance = "true"
run_ahead_hide_warnings = "false"When not to use it
Run-Ahead is not free and not universal. It needs a core that can save state every frame; cores that cannot will throw errors the moment you enable it. Do not stack it with netplay, where it fights the rollback logic. And do not pile three look-ahead frames plus a heavy multi-pass shader onto a passively cooled handheld and then wonder why the framerate collapsed — you spent your entire CPU budget removing latency you would not have felt. Match the ambition to the silicon, the same rule as everywhere else in this article.
Five Pitfalls That Eat Your Afternoon
Every one of these has a fix that takes thirty seconds and a diagnosis that takes an hour if you do not know it is coming. Read them before you need them.
Ordering and update pitfalls
Pitfall 1 — downloading cores before updating the core-info files. The symptom is an empty Core Downloader or cores that install and then "fail to load" as "unrecognized." The fix is the whole point of Step 2: Online Updater → Update Core Info Files, then download. Always that order.
Pitfall 2 — running RetroArch 1.22.0. The symptom is a shader-related black screen on certain content. The fix is trivial and everyone forgets it: update to 1.22.2, which fixed exactly this. Never sit on a .0 point release.
Platform and architecture pitfalls
Pitfall 3 — expecting a desktop-class core on ARM. The symptom is that LRPS2 or bsnes accuracy is either absent from your downloader or unplayably slow. The fix is acceptance: LRPS2 is x86_64-only and bsnes accuracy needs ~4 GHz. On an ARM handheld, use PCSX ReARMed for PlayStation and accept that PlayStation 2 is not on the menu.
Pitfall 4 — the 200+ number. The symptom is "my device only shows sixty cores, something is broken." Nothing is broken. The downloader is filtered to your architecture; an armv7 target listing ~170 cores is normal, and a smaller embedded target listing fewer is also normal. The catalogue is not the shelf.
Config and BIOS pitfalls
Pitfall 5 — BIOS in the wrong place or under the wrong name. The symptom is a black screen or an explicit "cannot find BIOS." The fix is exactness: the file goes in the system directory, named precisely as the docs specify, matching the documented MD5. A renamed dump is invisible to the core.
Pitfall 6 (the bonus one) — per-game settings that apply globally. The symptom is that a tweak you made for one game changed every game. The fix is to enable game_specific_options and save through Core Options → Manage → Create game-options file, rather than leaning on config_save_on_exit, which writes global and scopes nothing.
Troubleshooting: Ten Failures and Their Fixes
When something breaks, it is almost always one of these ten, and almost always a five-minute fix once identified. Read the symptom column first.
Cores that will not appear or load
The two most common failures both trace back to the info-file manifest. An empty Load Core menu on a fresh install is not a bug — it is the default state until you download a core. A downloaded core that "fails to load" is almost always stale info files. Run Update Core Info Files, then retry, before you suspect the binary itself.
Performance, BIOS, and platform
The next cluster is BIOS placement, architecture mismatch, and driver choice. A game that boots to black is usually a missing or misnamed BIOS. A core that is simply absent is usually an architecture it was never built for. A core that crashes on launch is usually the video driver — switch Vulkan and GL and see which survives.
The full table
| Symptom | Likely cause | Fix |
|---|---|---|
| Load Core menu is empty after install | Fresh install, no cores downloaded yet | Online Updater → Update Core Info Files, then Download a Core |
| Downloaded core "failed to load" / "unrecognized" | Core-info files stale or missing | Run Update Core Info Files first, then re-download the core |
| Core Downloader missing from the menu | Menu item hidden, or you are on the Steam build | Settings → User Interface → Menu Item Visibility → Show Core Downloader; on Steam, install cores as DLC |
| PlayStation game boots to a black screen | Missing or misnamed BIOS (scph image) | Place the correct BIOS in the system directory with the exact filename and MD5 |
| N64 title (e.g. Stunt Racer 64) will not load | mupen64plus-next early-2025 regression | Pin a January 2025 nightly from the buildbot, or switch to Parallel N64 |
| LRPS2 (PS2) core absent on your device | LRPS2 is x86_64-only | Use an x86_64 desktop; ARM has no PS2 core, by design |
| Stutter or audio crackle with Run-Ahead on | Single-instance run-ahead re-runs the whole frame | Enable Second Instance, or drop to 1 look-ahead frame |
| Per-game core options do not stick | game_specific_options disabled | Enable it; save via Core Options → Manage → Create game-options file |
| Vulkan core crashes on Android | Wrong or unsupported video driver | Settings → Drivers → Video → vulkan, with gl as fallback |
| Overrides ignored when content loads | auto_overrides_enable disabled or wrong path | Enable it; confirm the file path is config/<core>/<game>.cfg |
Advanced: Buildbot, Nightlies, PPAs, and Handhelds
The Online Updater covers 95% of people. The other 5% need a specific nightly, a package-managed install, or an understanding of why their handheld already made every choice for them.
Nightly cores from the buildbot
The libretro buildbot serves per-platform nightly cores, and it is how you escape a regression. When mupen64plus-next broke Stunt Racer 64 in early 2025, the fix was to grab a pre-regression January build by hand: download the matching .zip for your OS and architecture, extract the .so or .dll into your cores directory, and keep the matching .info file alongside it. You can also point core_updater_buildbot_url at a mirror if you run one. Manual core installs are also how you side-load something the downloader has not surfaced yet — the Azahar 3DS core, for one, until its stable release lands in the updater.
Package-manager cores on Linux
On Ubuntu and Debian, cores are available through the libretro PPA, which is handy for scripted or headless setups. Distro packages sometimes lag the buildbot by a release, so cross-check versions if a bug you expect to be fixed persists:
# Ubuntu / Debian: cores straight from the libretro PPA
sudo add-apt-repository ppa:libretro/stable
sudo apt-get update
sudo apt-get install libretro-beetle-psx libretro-mgba libretro-snes9x
# Flatpak users update the app; cores still come from the in-app updater
flatpak update org.libretro.RetroArchHandhelds and the cores you did not choose
Here is the twist for anyone reading this on the way to setting up a handheld: on curated firmware, you mostly do not pick cores at all. Distributions like muOS, OnionOS, ROCKNIX, Batocera, and RetroPie ship a hand-tuned core set matched to the SoC, and they have already made every decision in the "choosing cores" section for you — usually PCSX ReARMed, Snes9x, Genesis Plus GX, mGBA, gpSP, and PicoDrive on ARM, because those are what the silicon can actually sustain. If you are building one of those from scratch, our Batocera 43.1 install walkthrough covers the distro side, and the Miyoo Mini Plus game-list piece shows what a fixed OnionOS core set does and does not reach. A modern Snapdragon handheld is the exception that gets to choose — it can brute-force Beetle PSX HW and even Dolphin, which is exactly the gap our Retroid Pocket generational comparison measures.
A Complete, Working Core Configuration
To close, here is a full reference setup you can copy and adapt — the config lines that matter, the directory layout they assume, and a real per-game override tying it together. This is the destination the twelve steps were walking toward.
retroarch.cfg: the lines that matter for cores
Your retroarch.cfg holds hundreds of keys; these are the ones that govern cores, overrides, and BIOS discovery. Everything else can stay at default.
# retroarch.cfg — core-relevant keys
libretro_directory = "~/.config/retroarch/cores"
libretro_info_path = "~/.config/retroarch/cores"
system_directory = "~/.config/retroarch/system"
core_updater_buildbot_url = "http://buildbot.libretro.com/nightly/"
config_save_on_exit = "false"
game_specific_options = "true"
auto_overrides_enable = "true"
auto_remaps_enable = "true"
video_driver = "vulkan"The directory layout
Every path above resolves into this tree. If a file is not where RetroArch expects it — a BIOS outside system/, an override outside config/<core>/ — it does not exist as far as the core is concerned.
~/.config/retroarch/
├── cores/ # *.so / *.dll cores + matching *.info
├── system/ # BIOS: scph5501.bin, gba_bios.bin, ...
├── config/
│ ├── Beetle PSX HW/
│ │ ├── Beetle PSX HW.cfg # core-scope config override
│ │ └── Gran Turismo 2 (USA).opt # per-game core options
│ └── remaps/
│ └── Beetle PSX HW/
│ └── Gran Turismo 2 (USA).rmp # per-game input remap
├── playlists/ # scanned libraries + core associations
├── retroarch.cfg
└── retroarch-core-options.cfgA per-game override that actually works
Put it together for one title. Globally, Beetle PSX HW runs the Vulkan renderer at 4x with conservative PGXP. For Gran Turismo 2 specifically, you want the widescreen hack and fuller geometry correction — so you write the two override files below and leave the global config untouched. Launch the game and RetroArch layers global → core → game, most-specific-wins, exactly as the hierarchy promises.
# config/Beetle PSX HW/Gran Turismo 2 (USA).opt
beetle_psx_hw_widescreen_hack = "enabled"
beetle_psx_hw_pgxp_mode = "memory + CPU"
beetle_psx_hw_internal_resolution = "4x"
# config/Beetle PSX HW/Gran Turismo 2 (USA).cfg
aspect_ratio_index = "1"
video_scale_integer = "false"That is the whole system: a frontend that ships empty on purpose, a catalogue of 200+ cores you pull the ones you need from, an update order that has to run forwards, and an override hierarchy that lets one install behave differently for every game in it. RetroArch will still not choose your PlayStation core for you. But now you know why it won't — and which one you actually wanted.
Questions the search bar asks me
- Does RetroArch come with any cores installed?
- No — a fresh install on any platform ships zero cores; the Load Core menu is empty until you download one. The single exception is the Steam build, which bundles 10 cores (Mupen64Plus-Next, Kronos, PCSX ReARMed, Stella, SameBoy, mGBA, Mesen, Mesen-S, Genesis Plus GX, Final Burn Neo) and delivers the rest as free DLC. On every other build, run Online Updater → Update Core Info Files, then Download a Core.
- Why won't my downloaded core load?
- The most common cause is stale core-info files: RetroArch can't recognize a core it has no current manifest for, so run Update Core Info Files first, then re-download. The other frequent causes are a missing or misnamed BIOS in the system directory, and an architecture mismatch — LRPS2 (PS2), for example, is x86_64-only and will never appear on ARM.
- What's the best PlayStation 1 core in 2026?
- It depends on hardware. Beetle PSX HW (Mednafen lineage, Vulkan hardware renderer) is the most accurate and heaviest, ideal on desktop with upscaling and PGXP. SwanStation (a DuckStation port) is the balanced middle option, and PCSX ReARMed is the lightweight ARM core that powers muOS, OnionOS, and ROCKNIX handhelds.
- Is there a working 3DS core now that Citra is gone?
- Yes — Citra was taken down via DMCA, and its successor Azahar shipped the first official libretro 3DS core in version 2125.0 Alpha 4, across six operating systems (Linux, Windows, macOS, Android, iOS, tvOS). The line has since reached 2126.0 (release candidate as of mid-2026); it dropped encrypted-game and Nintendo CDN support in favor of the Artic Setup Tool.
- How do I use different settings for just one game?
- Enable game_specific_options in retroarch.cfg, then save from the Quick Menu — Overrides → Save Game Override for config settings, and Core Options → Manage → Create game-options file for emulator settings. RetroArch resolves these by precedence (game > content-directory > core > global), writing files under config/<core>/<game>.cfg and .opt so your global config stays untouched.