Open-source arcade netplay — a clean-room, community-owned alternative for low-latency rollback matchmaking and emulation.
OpenCade is a monorepo for a modern arcade netplay platform: Rust server (Axum + PostgreSQL), Tauri + React + TypeScript desktop client, and a pluggable emulator adapter SDK. The repository contains an executable Proof of Match control plane, deterministic mock-adapter data plane, an original no-ROM libretro Proof-of-Play fixture, safe local FBNeo launch, direct UDP/STUN/hole-punching, authenticated readiness-probe relay fallback, and an experimental native-process RetroArch adapter. Standalone FBNeo netplay, physical cross-NAT results, behavior classification, and real two-machine RetroArch play remain explicitly unproven.
OpenCade exists to build a completely open-source, self-hostable, and clean-room alternative to proprietary platforms like Fightcade. We believe rollback matchmaking, lobby coordination, and emulator netplay should belong to the community—not locked behind closed binaries, tracking, or paywalls.
Building low-latency distributed netplay across diverse real-world networks requires dedicated resources:
- Physical Multi-Node Test Hardware: Continuous two-machine cross-NAT and cross-ISP testing across varying network topologies (Symmetric NAT, Carrier-Grade NAT, firewall edge cases).
- Dedicated Relay & STUN Infrastructure: Running public fallback relays and high-availability STUN nodes so players behind strict routers can always connect.
- CI & Artifact Matrix: Automated multi-platform builds, integration test runners, and binary integrity scans on every PR.
- Emulator Adapter & Protocol R&D: Clean-room protocol reverse-engineering, deterministic frame-sync research, and pluggable adapter development.
OpenCade is 100% free software (Apache-2.0): no paywalled features, no artificial queue priorities, no ads, and no premium tiers. Ever.
👉 Buy Me a Coffee — https://buymeacoffee.com/zendevve
Every single contribution directly funds the infrastructure, hardware test benches, and continuous engineering needed to make independent netplay rock solid.
- Docker + Docker Compose (server + Postgres)
- Rust stable +
sqlx-cli(server) - Node.js 24+ + pnpm 11+ (client)
- Rust + Tauri prerequisites (tauri.app/start/prerequisites)
# from repo root
cp .env.example .env
# replace SESSION_SECRET in .env, then:
docker compose up -d
# verify
curl http://localhost:8080/health
docker compose logs -f opencade-serverThis starts PostgreSQL, runs committed SQLx migrations as a one-shot job, then starts opencade-server and the authenticated readiness-probe relay. See the production runbook for backup, restore, deployment, and rollback procedures.
# stop
docker compose down
# reset DB (destructive)
docker compose down -v# install JS dependencies
pnpm install
# run desktop app in dev mode (Vite + Tauri)
pnpm -C apps/client tauri dev
# or run web-only frontend
pnpm --filter @opencade/client dev
# production bundle
pnpm -C apps/client tauri buildPorts (default): server
8080, PostgreSQL5432, client dev1420.
OpenCade/
├── apps/
│ ├── client/ # Tauri + React + TypeScript desktop client
│ │ ├── src/ # Auth, games, lobby, challenge, and match views
│ │ ├── src-tauri/ # Rust native layer (process / fs / logging / diagnostics)
│ │ └── package.json
│ └── server/ # Rust + Axum + PostgreSQL API + WebSocket signaling
│ ├── src/
│ ├── migrations/
│ └── Dockerfile
├── packages/
│ ├── protocol/ # Versioned signaling + REST contract (shared types)
│ ├── emulator-sdk/ # Adapter trait: detect / validate / getVersion / launch / stop / configure
│ ├── game-definitions/ # Declarative TOML (id, name, emulator, launch args, validation)
│ ├── networking/ # Bounded input frames, deterministic in-memory + direct UDP transports
│ └── shared/ # Cross-cutting utils, logging, config
├── adapters/
│ ├── fbneo/ # Standalone FBNeo local-play adapter
│ └── retroarch/ # Experimental native-process netplay adapter
├── services/ # Authenticated bounded readiness-probe relay
├── scripts/alpha/ # Windows alpha-kit packager, verifier, doctor, and launcher
├── research/ # OBSERVATIONS ONLY — never shipped (see Clean-Room Notice)
│ ├── observations/ # Dated, factual notes from black-box behavior
│ ├── protocol/ # Captured message field notes (no replay)
│ ├── binaries/ # Inventory only — no binaries checked in
│ ├── network/ # RTT / NAT / firewall observations
│ ├── behavior/ # UX flows, state transitions
│ └── notes/ # Working scratch (not source of truth)
├── docs/
│ ├── ARCHITECTURE.md # System architecture & subsystem map (authoritative)
│ ├── adr/ # Architecture decision records
│ ├── alpha/ # LAN test and match-report procedures
│ ├── IMPLEMENTATION_STATUS.md # Verified scope and explicit non-claims
│ ├── OPPORTUNITIES_2026-08-28.md # 20 screened bets + one recommended keystone
│ └── reference-fightcade-install.md # D:/Fightcade read-only notes (never copied)
├── docker/
│ └── (compose at root: `docker-compose.yml` — see also `docker/` if present)
├── .github/
│ └── workflows/ # CI (fmt, clippy, test, build)
└── tests/ # Cross-package integration tests
See docs/ARCHITECTURE.md for the full system design, subsystem boundaries, data model, and adapter contract.
D:/Fightcade is a read-only reference. No proprietary binaries, ROMs, or credentials are shipped in this repository.
OpenCade is built under a strict clean-room process:
- Observation — black-box study of behavior and protocols against
D:/Fightcadeas an installed reference. Notes go toresearch/only. - Documentation — observations are distilled into specs (
docs/,packages/protocol). - Design — new interfaces are designed from the spec, not from decompiled or copied code.
- Implementation — original code only.
Forbidden (never committed): proprietary binaries, ROMs/assets, credentials/tokens, decompiled or copy-pasted code, packet dumps with user data.
Allowed: original source under Apache-2.0, documentation, licensed dependencies, public specifications.
The research/ directory is workspace-only and is not shipped in any release artifact or the server container image. The process and prohibited material are documented in research/GUARDRAILS.md and docs/ARCHITECTURE.md §18. CI enforces the guardrail (research/ is excluded from builds and binary scans block proprietary artifacts).
High-level: Client (Tauri) ↔ Server (Axum REST + authenticated WebSocket) for the control plane; direct UDP or the deterministic in-memory transport carries OpenCade input frames; the adapter boundary owns safe local emulator execution.
- Server: auth (Argon2id), hashed sessions, games, server hints, lobbies, durable challenges,
rooms/matches, and authenticated WebSocket signaling (
offer/answer/candidate). - Networking: deterministic in-memory, direct UDP, RFC 8489 discovery, nonce-bound hole punching, and a short-lived room-member-ticket WebSocket relay are implemented. Physical cross-NAT evidence and cone/symmetric behavior classification remain pending.
- Client: login/register, games, lobby challenges, match state, local availability scan, diagnostics, and redacted report export; Rust core owns process spawn, filesystem validation, and diagnostics.
- Emulator SDK: explicit OpenCade/native/blocked netplay modes, safe process launch, ROM validation, game-definition TOML, and an experimental user-supplied RetroArch + FBNeo-core adapter.
Full reference: docs/ARCHITECTURE.md.
| Phase | Milestone | Focus | Exit Criteria |
|---|---|---|---|
| M0 | Scaffolding | Monorepo, CI, Docker Compose, lint/fmt, clean-room guardrails | pnpm install && docker compose up -d works from clean clone |
| M1 | Server Core | Axum + PostgreSQL, auth (register/login/logout, Argon2id), users/sessions, health/observability | REST auth + health passes integration tests |
| M2 | Realtime & Networking | WebSocket signaling, room state machine (WAITING→PLAYING→ENDED/CANCELLED), challenge flow |
Signaling versioned protocol + presence/chat e2e |
| M3 | Client Shell | Tauri + React shell, routing (Games/Lobbies/Friends/Servers/Settings), Rust fs/process/logging | Client launches, talks to server, diagnostics panel |
| M4 | Emulator SDK | Adapter trait (detect/validate/getVersion/launch/stop/configure/getSupportedGames), FBNeo adapter, TOML game definitions |
Local ROM scan + safe launch for one title |
| M5 | Matchmaking | Lobbies, game versions, server browser, matchmaking & room lifecycle | Create/join/spectate room e2e with two peers |
| M6 | NAT & Relay | STUN, hole-punching, authenticated opencade-relay WebSocket fallback, RTT/loss/jitter, Network Test |
Direct + relayed matches measured; relay Docker image |
| M7 | MVP Release | Hardening, bans/reports, replay hooks, packaging, docs | Tagged MVP, signed artifacts, no proprietary content |
Discord — where we discuss OpenCade and everything around it (not only OpenCade): https://discord.gg/Y4rDyTScPe
General dev chat, architecture questions, emulator adapter ideas, and matchmaking talk — all in one place.
👉 Support OpenCade on Buy Me a Coffee — https://buymeacoffee.com/zendevve
See CONTRIBUTING.md. If you can't contribute code, you can still keep the project moving — every coffee funds test hardware, CI minutes, and public relay capacity. ☕ https://buymeacoffee.com/zendevve
Do not open public issues for sensitive vulnerabilities. See SECURITY.md for disclosure.
Apache License 2.0 — see LICENSE. Copyright 2026 OpenCade Contributors.