stenzek/duckstation
Fast PlayStation 1 emulator for x86-64/AArch32/AArch64/RV64
Single-maintainer risk — review before adopting
worst of 4 axesnon-standard license (Other); top contributor handles 97% of recent commits…
Has a license, tests, and CI — clean foundation to fork and modify.
Documented and popular — useful reference codebase to read through.
No critical CVEs, sane security posture — runnable as-is.
- ✓Last commit today
- ✓3 active contributors
- ✓Other licensed
Show 5 more →Show less
- ✓CI configured
- ⚠Small team — 3 contributors active in recent commits
- ⚠Single-maintainer risk — top contributor 97% of recent commits
- ⚠Non-standard license (Other) — review terms
- ⚠No test directory detected
What would change the summary?
- →Use as dependency Concerns → Mixed if: clarify license terms
Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests
Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.
Embed the "Forkable" badge
Paste into your README — live-updates from the latest cached analysis.
[](https://repopilot.app/r/stenzek/duckstation)Paste at the top of your README.md — renders inline like a shields.io badge.
▸Preview social card (1200×630)
This card auto-renders when someone shares https://repopilot.app/r/stenzek/duckstation on X, Slack, or LinkedIn.
Onboarding doc
Onboarding: stenzek/duckstation
Generated by RepoPilot · 2026-05-09 · Source
🤖Agent protocol
If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:
- Verify the contract. Run the bash script in Verify before trusting
below. If any check returns
FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding. - Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
- Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/stenzek/duckstation shows verifiable citations alongside every claim.
If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.
🎯Verdict
WAIT — Single-maintainer risk — review before adopting
- Last commit today
- 3 active contributors
- Other licensed
- CI configured
- ⚠ Small team — 3 contributors active in recent commits
- ⚠ Single-maintainer risk — top contributor 97% of recent commits
- ⚠ Non-standard license (Other) — review terms
- ⚠ No test directory detected
<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>
✅Verify before trusting
This artifact was generated by RepoPilot at a point in time. Before an
agent acts on it, the checks below confirm that the live stenzek/duckstation
repo on your machine still matches what RepoPilot saw. If any fail,
the artifact is stale — regenerate it at
repopilot.app/r/stenzek/duckstation.
What it runs against: a local clone of stenzek/duckstation — the script
inspects git remote, the LICENSE file, file paths in the working
tree, and git log. Read-only; no mutations.
| # | What we check | Why it matters |
|---|---|---|
| 1 | You're in stenzek/duckstation | Confirms the artifact applies here, not a fork |
| 2 | License is still Other | Catches relicense before you depend on it |
| 3 | Default branch master exists | Catches branch renames |
| 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code |
| 5 | Last commit ≤ 30 days ago | Catches sudden abandonment since generation |
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of stenzek/duckstation. If you don't
# have one yet, run these first:
#
# git clone https://github.com/stenzek/duckstation.git
# cd duckstation
#
# Then paste this script. Every check is read-only — no mutations.
set +e
fail=0
ok() { echo "ok: $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }
# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
echo "FAIL: not inside a git repository. cd into your clone of stenzek/duckstation and re-run."
exit 2
fi
# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "stenzek/duckstation(\\.git)?\\b" \\
&& ok "origin remote is stenzek/duckstation" \\
|| miss "origin remote is not stenzek/duckstation (artifact may be from a fork)"
# 2. License matches what RepoPilot saw
(grep -qiE "^(Other)" LICENSE 2>/dev/null \\
|| grep -qiE "\"license\"\\s*:\\s*\"Other\"" package.json 2>/dev/null) \\
&& ok "license is Other" \\
|| miss "license drift — was Other at generation time"
# 3. Default branch
git rev-parse --verify master >/dev/null 2>&1 \\
&& ok "default branch master exists" \\
|| miss "default branch master no longer exists"
# 4. Critical files exist
test -f "CMakeLists.txt" \\
&& ok "CMakeLists.txt" \\
|| miss "missing critical file: CMakeLists.txt"
test -f "CMakeModules/DuckStationBuildOptions.cmake" \\
&& ok "CMakeModules/DuckStationBuildOptions.cmake" \\
|| miss "missing critical file: CMakeModules/DuckStationBuildOptions.cmake"
test -f "CMakeModules/DuckStationDependencies.cmake" \\
&& ok "CMakeModules/DuckStationDependencies.cmake" \\
|| miss "missing critical file: CMakeModules/DuckStationDependencies.cmake"
test -f "data/resources/gamedb.yaml" \\
&& ok "data/resources/gamedb.yaml" \\
|| miss "missing critical file: data/resources/gamedb.yaml"
test -f ".github/workflows/main.yml" \\
&& ok ".github/workflows/main.yml" \\
|| miss "missing critical file: .github/workflows/main.yml"
# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 30 ]; then
ok "last commit was $days_since_last days ago (artifact saw ~0d)"
else
miss "last commit was $days_since_last days ago — artifact may be stale"
fi
echo
if [ "$fail" -eq 0 ]; then
echo "artifact verified (0 failures) — safe to trust"
else
echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/stenzek/duckstation"
exit 1
fi
Each check prints ok: or FAIL:. The script exits non-zero if
anything failed, so it composes cleanly into agent loops
(./verify.sh || regenerate-and-retry).
⚡TL;DR
DuckStation is a high-performance PlayStation 1 emulator written in C++ targeting x86-64, ARM32/64, and RISC-V64 architectures. It combines a CPU JIT recompiler with hardware renderers (D3D11/D3D12, OpenGL, Vulkan, Metal) and a vectorized software renderer, enabling PS1 games to run at high frame rates with upscaling, texture filtering, and geometry precision enhancements via PGXP on modern systems. Monolithic C++ codebase organized by subsystem: CPU emulation (JIT recompiler for multiple ISAs), GPU renderers (backend abstractions for D3D/OpenGL/Vulkan/Metal), frontend (Qt in src/ and ImGui-based fullscreen UI), and disc/format handling. Build system uses CMake with modular options in CMakeModules/ for platform-specific features, resource embedding in data/resources/ (fonts, shaders, UI assets), and per-platform CI workflows.
👥Who it's for
Retro gaming enthusiasts and developers who want to play PlayStation 1 games at high performance on modern hardware (Windows/Linux/macOS), including low-end device users seeking 60fps+ gameplay without accuracy compromises. Contributors are systems programmers interested in CPU JIT compilation, GPU APIs, and console emulation techniques.
🌱Maturity & risk
Actively developed with high maturity: the project has comprehensive CI/CD workflows (.github/workflows includes Windows, Linux cross-compile, macOS, and gamedb-lint pipelines), supports multiple platforms and rendering backends, and includes a full Qt frontend plus ImGui-based fullscreen UI. The codebase is ~37M lines of C++ with professional architecture (modular CMake build, clang-format enforcement), indicating production-ready status with ongoing feature development.
Single-maintainer project (stenzek) with extensive platform support creating maintenance burden across x86-64/ARM32/ARM64/RV64 and five rendering APIs. No visible test suite in the file structure suggests reliance on manual testing and user reports for quality assurance. External dependencies include Qt, FFmpeg, and platform-specific libraries (UDEV for Linux), increasing build complexity across environments.
Active areas of work
Project is actively maintained with focus on multi-architecture JIT support (evidenced by RV64 support alongside x86-64/ARM), rendering backend optimization (Metal support, D3D12 additions), and compatibility (discdb.yaml, achievement_hashlib.yaml resources suggest RetroAchievements integration). CI/CD workflows include gamedb linting and cross-platform AppImage builds, indicating ongoing release management.
🚀Get running
Clone and build: git clone https://github.com/stenzek/duckstation.git && cd duckstation && mkdir build && cd build && cmake .. && cmake --build . (CMake required; platform-specific: Qt5/Qt6, FFmpeg development headers, graphics APIs). Requires BIOS ROM image (dumped from hardware) to run—see README for legal details.
Daily commands:
After build: ./build/bin/duckstation (or duckstation-qt for full Qt interface). Supply BIOS via Settings or auto-detection. Launch games via file browser or auto-scan directories. Fullscreen UI accessible via ImGui-based menu. See README for PlayStation disc format support (bin/cue, CHD, ECM, MDS/MDF, CCD, PBP).
🗺️Map of the codebase
CMakeLists.txt— Root build configuration that orchestrates the entire project compilation across multiple platforms; every contributor must understand the build system dependencies and targets.CMakeModules/DuckStationBuildOptions.cmake— Defines all major build-time configuration flags and feature toggles; critical for understanding which emulation features are enabled by default.CMakeModules/DuckStationDependencies.cmake— Manages all external library dependencies (FFmpeg, etc.); essential for setting up development environment and understanding runtime requirements.data/resources/gamedb.yaml— Game compatibility database that drives per-title emulation quirks and workarounds; contributors need to understand how games are profiled..github/workflows/main.yml— Primary CI/CD pipeline for all platforms; defines the automated testing and release process every PR goes through.README.md— Project charter and feature overview; sets expectations for emulation accuracy, performance targets, and scope boundaries.
🧩Components & responsibilities
- CMake Build System — Orchestrates compilation across 4+ target architectures; resolves dependencies (FFmpeg, libudev); enables/disables features
🛠️How to make changes
Add a game compatibility workaround
- Identify the game's serial in the emulator console output or use disc identification (
data/resources/discdb.yaml) - Add or update the game entry in gamedb.yaml with serial, region, and emulation settings (CPU/GPU quirks, timing fixes, etc.) (
data/resources/gamedb.yaml) - Test the game and commit with clear description of the fix (
.github/workflows/gamedb-lint.yml)
Add a new platform/architecture build target
- Update CMakeLists.txt to detect and enable the new architecture (e.g., new RISC-V variant) (
CMakeLists.txt) - Add architecture-specific compiler flags and optimizations in DuckStationBuildOptions.cmake (
CMakeModules/DuckStationBuildOptions.cmake) - Create a new GitHub Actions workflow file following the naming convention for matrix builds (
.github/workflows/main.yml) - Run the build pipeline and validate cross-architecture release artifacts (
.github/workflows/main.yml)
Add a new UI font or improve multilingual support
- Add the font file (.ttf, .otf, or .woff2) to the appropriate language folder (
data/resources/fonts) - Reference the font in the UI rendering code (typically in native frontend or fullscreen UI system) (
data/resources/fullscreenui/backgrounds/Default.glsl) - Test the font rendering across all supported languages and commit (
data/resources/fonts/NotoSansJP-VariableFont_wght.ttf)
🔧Why these technologies
- CMake — Provides cross-platform build configuration and dependency management for x86-64, ARM, RISC-V, and allows conditional feature compilation at build time.
- C++17+ — Performance-critical emulation requires low-level memory management and instruction-level optimization; modern C++ provides abstractions without overhead.
- FFmpeg (optional) — Enables multimedia codec support for cutscenes and media playback compatibility.
- SDL (implied) — Cross-platform input handling via gamecontrollerdb.txt; critical for controller mapping on Windows, Linux, macOS.
- YAML format — Readable, maintainable configuration for game database and disc identification without requiring code recompilation.
⚖️Trade-offs already made
-
Default configuration + per-game workarounds over blanket compatibility hacks
- Why: Maintains emulation accuracy as the default while allowing game-specific overrides for edge cases.
- Consequence: Requires careful game profiling and testing; complex games may need multiple settings tweaked, increasing maintenance burden.
-
Support for multiple CPU backends (interpreter + dynarec) and GPU renderers
- Why: Allows low-end devices to use interpreter while high-end systems use dynarec for speed; supports mobile and desktop.
- Consequence: Increased codebase complexity and testing surface area across backends.
-
BIOS ROM image required at runtime
- Why: Ensures hardware-accurate initialization and system call emulation; maintains legal boundaries.
- Consequence: Increased setup friction for end users; requires manual BIOS dump from hardware.
-
Fullscreen UI + native frontend modes
- Why: Fullscreen UI enables console-like experience on low-end devices; native frontend suits desktop workflows.
- Consequence: Dual code paths increase maintenance overhead and UI inconsistencies.
🚫Non-goals (don't propose these)
- Does not emulate PlayStation 2 (PS2) — focuses exclusively on PS1 accuracy.
- Does not provide BIOS ROMs — users must dump from their own hardware.
- Does not implement cheat code frameworks — game-specific workarounds only.
- Does not support real-time multiplayer networking — only local input.
- Not a cycle-accurate emulator — trading perfect accuracy for playable performance on low-end devices.
🪤Traps & gotchas
BIOS requirement: Project legally cannot distribute PS1 BIOS—must be user-dumped from hardware; emulator will not run games without valid BIOS. Platform specifics: RV64 JIT requires specific instruction set support; ARM recompiler uses AArch32/AArch64 variants with architecture detection. Shader paths: HLSL shaders for D3D, GLSL for OpenGL/Vulkan, Metal for Apple—backend selection at build time affects available renderers. Cross-compilation: Linux AppImage builds use cross-compile workflows (.github/workflows/linux-cross-appimage-build.yml) requiring multilib toolchains. Audio/Input: Platform abstraction required; SDL2 or native APIs depending on backend.
🏗️Architecture
💡Concepts to learn
- JIT Recompilation — DuckStation's performance advantage comes from translating PS1 MIPS bytecode to native x86-64/ARM/RV64 machine code at runtime; understanding instruction selection, register allocation, and code cache management is essential for CPU backend work
- PGXP (Polygon Geometry Precision) — DuckStation implements PGXP to correct PS1's fixed-point geometry precision errors and emulate per-pixel depth buffering via texture tricks; understanding affine texture mapping vs. perspective correction is key to graphics accuracy
- Memory-Mapped I/O — PS1 hardware (GPU, SPU, controllers) communication happens via memory-mapped registers; emulator must intercept CPU reads/writes to specific address ranges and route them to correct hardware modules
- GPU Backend Abstraction — DuckStation supports five rendering APIs (D3D11/D3D12, OpenGL, Vulkan, Metal) through a pluggable backend layer; understanding texture upload, command buffer recording, and shader compilation across APIs is required for graphics work
- Rasterizer Order Views / Fragment Shader Interlock — DuckStation implements accurate PS1 blending via ROV (DirectX) and FSI (Vulkan/Metal); these GPU features allow pixel-level synchronization, critical for emulating PS1's unusual transparency blend modes
- Disc Image Formats & CD-ROM Emulation — DuckStation reads bin/cue, CHD, ECM, MDS/MDF, CCD, and unencrypted PBP formats; handling sector parsing, error correction, and subchannel data is necessary for multi-disc game merging and automatic PPF patch application
- Deinterlacing & Motion Estimation — PS1 output is interlaced; DuckStation implements motion-adaptive deinterlacing to avoid blur on static content while preserving motion; understanding temporal filtering and frame blending techniques is useful for video output quality work
🔗Related repos
Commonly/pcsx-redux— Alternative PS1 emulator with focus on debugging and preservation; shares CPU/GPU emulation challenges but different architecture approachgrumpycoders/pcsx-redux— Modern PS1 emulator emphasizing code clarity and debuggability; active alternative to DuckStation with overlapping feature setdolphin-emu/dolphin— GameCube/Wii emulator by same ecosystem; demonstrates multi-architecture JIT recompiler patterns (x86-64/ARM64) and multi-backend rendering DuckStation followsPCSX2/pcsx2— PlayStation 2 emulator; natural progression for users; shares CPU recompilation and GPU backend architecture concepts with DuckStationRetroArch/RetroArch— Multi-system emulation frontend; DuckStation integrates RetroAchievements (achievement_hashlib.yaml), and RetroArch can wrap PS1 cores sharing compatibility data
🪄PR ideas
To work on one of these in Claude Code or Cursor, paste:
Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.
Add GitHub Actions workflow for translation file linting validation
The repo has .github/workflows/translation-lint.yml configured but no corresponding translation validation tooling or documentation. A new contributor could implement a Python/shell script that validates YAML translation files in data/resources/ for missing keys, encoding issues, and consistency across language files. This prevents broken translations from being merged and is critical for a multi-language emulator.
- [ ] Create
scripts/validate-translations.pyto lint all translation YAML files - [ ] Validate that all language files have identical key structures
- [ ] Check for invalid UTF-8 encoding and malformed YAML syntax
- [ ] Update
.github/workflows/translation-lint.ymlto call the validation script - [ ] Add documentation to
CONTRIBUTORS.mdon translation submission requirements
Create unit tests for CMake build option validation
The CMakeModules/DuckStationBuildOptions.cmake file defines many build flags but there's no test coverage validating that incompatible option combinations are caught (e.g., ARM32 + AVX2, or conflicting audio backends). A new contributor could add CMake-based tests or a Python validation script that catches invalid configurations before compilation.
- [ ] Create
tests/cmake_options_validation.pyto parseDuckStationBuildOptions.cmake - [ ] Define incompatible option combinations (e.g., architecture + CPU feature mismatches)
- [ ] Add test cases for valid and invalid configurations
- [ ] Integrate test into
.github/workflows/main.ymlto validate on all PRs - [ ] Document valid build option combinations in a new
BUILD_OPTIONS.mdfile
Add asset optimization workflow for image and font files in data/resources/
The repo contains numerous font files (TTF, WOFF2) and image assets (PNG, SVG) but lacks a CI workflow to detect unoptimized assets. A new contributor could implement GitHub Actions workflow that detects oversized images/fonts and suggests optimization via tools like imagemin, fonttools, or svgo, reducing distribution size for resource-constrained platforms.
- [ ] Create
.github/workflows/asset-optimization.ymlworkflow - [ ] Add Python script using
Pillowto check PNG optimization and suggest compression - [ ] Add font validation using
fonttoolsto detect unnecessary glyphs in TTF/WOFF2 files - [ ] Add SVG validation using
svgofor unnecessary DOM elements - [ ] Post PR comments with optimization suggestions and estimated size savings
- [ ] Document asset contribution guidelines in
CONTRIBUTORS.md
🌿Good first issues
- Add unit tests for the CPU recompiler (cpu_recompiler.cpp) instruction generation—currently no visible test/ directory, leaving JIT correctness validated only by game execution
- Document shader architecture in docs/: explain HLSL->GLSL translation, ReShade FX parsing flow, and Slang preset loading used in data/resources/fullscreenui/
- Expand discdb.yaml with parsing validation CI job (gamedb-lint.yml exists but could enforce per-game field schemas and catch malformed entries early)
⭐Top contributors
Click to expand
Top contributors
- @stenzek — 97 commits
- @crashGG — 2 commits
- @bilginGamer — 1 commits
📝Recent commits
Click to expand
Recent commits
2ca8307— FullscreenUI: Fix loading screen drawing with non-zero minimum (stenzek)678c2ec— FullscreenUI: Fix InputStringDialog not clearing text (stenzek)9e82d21— FullscreenUI: Fix typo in MenuImageButton() (stenzek)69b3958— FullscreenUI: Use icon in both AlertPrompt() and ConfirmPrompt() (stenzek)ccce159— FullscreenUI: Fix game grid titles drawing even when disabled (stenzek)adff8db— FullscreenUI: Improve sort operator consistency (stenzek)7120a4a— FullscreenUI: Fix possible divide by zero in achievement summary (stenzek)f685648— FullscreenUI: Fix leaderboard ID/format not caching in pause menu (stenzek)1917421— FullscreenUI: Use correct active state for timed indicator removal (stenzek)1e570ed— FullscreenUI: Fix first achievement notification not triggering run-idle (stenzek)
🔒Security observations
DuckStation is a PlayStation emulator with a generally reasonable security posture for its intended purpose. The primary security concerns are around handling user-provided binary files (BIOS ROMs) and third-party data files (YAML configurations, fonts, controller mappings). No hardcoded secrets or obvious injection vulnerabilities were detected in the visible file structure. The codebase appears to follow standard C++ development practices. Main recommendations: (1) Implement strict validation for all user-provided ROM files, (2) Use safe YAML parsing without dangerous deserialization features, (3) Verify integrity of bundled third-party resources, (4) Consider implementing sandboxing for untrusted file parsing. The moderate security score reflects that this is a complex binary-parsing application that handles user files, which inherently carries some risk.
- Medium · BIOS ROM Dependency on User-Provided Files —
Core emulator initialization and ROM loading logic. The emulator requires users to provide a PS1/PS2 BIOS ROM image to function. This creates a security risk if the emulator doesn't properly validate the ROM file before loading it. Malicious ROM files could potentially exploit vulnerabilities in the ROM parsing code. Fix: Implement strict validation and integrity checks for BIOS ROM files. Use cryptographic hashing to verify ROM authenticity. Consider implementing sandboxing for ROM file parsing operations. - Medium · Game Database YAML Files Without Validation —
data/resources/gamedb.yaml, data/resources/discdb.yaml, data/resources/discsets.yaml. The codebase includes YAML resource files (gamedb.yaml, discdb.yaml, discsets.yaml) that are loaded at runtime. If these files are parsed without proper sanitization, they could be vulnerable to YAML injection attacks or arbitrary code execution through unsafe deserialization. Fix: Use safe YAML parsing libraries with disabled dangerous features (no arbitrary object instantiation). Validate schema of loaded YAML files strictly. Consider using JSON format instead of YAML if possible. - Low · Third-Party Font Files Without Integrity Verification —
data/resources/fonts/ directory. The application bundles multiple third-party font files (.ttf, .woff2, .otf) from external sources. Compromised or malicious font files could potentially exploit font rendering vulnerabilities. Fix: Verify the integrity and authenticity of all bundled font files. Pin specific versions and use cryptographic checksums. Consider obtaining fonts from official sources only. - Low · Game Controller Database Without Source Verification —
data/resources/gamecontrollerdb.txt. The gamecontrollerdb.txt file is a third-party data file that maps game controllers. Without verification of its source and integrity, it could be tampered with. Fix: Verify the origin of gamecontrollerdb.txt (appears to be from SDL_GameControllerDB). Implement checksum verification and consider pinning to a specific upstream version. - Low · Achievement System YAML Configuration —
data/resources/achievement_hashlib.yaml. The achievement_hashlib.yaml file is used for achievement tracking. Unsafe parsing of this file could lead to injection vulnerabilities or information disclosure. Fix: Ensure the YAML parser is configured securely. Validate all content loaded from this file before use in security-sensitive operations.
LLM-derived; treat as a starting point, not a security audit.
👉Where to read next
- Open issues — current backlog
- Recent PRs — what's actively shipping
- Source on GitHub
Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.