Plateforme de jeu rétro SNES multijoueur en ligne avec émulation côté serveur.
- Authentification Google OAuth - Connexion sécurisée
- Système d'amis - Invitations et confirmations sans email
- Bibliothèque de jeux - Upload et gestion de ROMs personnelles
- Rooms multijoueur - Création et partage de sessions de jeu
- Configuration manettes - Personnalisation complète des touches
- Sélection des ports - Choix dynamique du port manette (1 ou 2)
- Sauvegardes individuelles - Save states liés au joueur et au jeu
- Menu pause - Réassignation touches, save/load, arrêt
- Streaming WebRTC - Latence ultra-faible ~45ms via WebRTC peer-to-peer
- Contrôle vitesse émulation - Ralenti, accéléré, vitesse illimitée (voir docs/SPEED_CONTROLS.md)
- Node.js/TypeScript avec Express
- Socket.io pour WebSocket temps réel et signaling WebRTC
- Prisma + SQLite pour la base de données
- Redis pour sessions et rooms actives
- Passport.js pour OAuth Google
- Multer pour upload de fichiers
- SvelteKit avec TypeScript
- WebRTC pour streaming vidéo/audio basse latence (~45ms)
- Canvas API pour rendu vidéo
- Web Audio API pour le son
- Socket.io-client pour WebSocket et signaling
- snes9x-next (libretro core) - Émulation SNES réelle
- Streaming vidéo (256x224 @ 60 FPS)
- Audio PCM temps réel
- Contrôle vitesse dynamique (0.5x à illimité)
- Node.js 20+
- Docker & Docker Compose
- Compte Google Cloud (pour OAuth)
cd psnes
npm install- Aller sur Google Cloud Console
- Créer un nouveau projet
- Activer "Google+ API"
- Créer des credentials OAuth 2.0:
- Type: Web application
- Authorized redirect URIs:
http://localhost:3000/auth/google/callback
- Copier Client ID et Client Secret
cd backend
cp .env.example .envÉditer backend/.env:
NODE_ENV=development
PORT=3000
DATABASE_URL="file:./data/dev.db"
REDIS_HOST=redis
REDIS_PORT=6379
SESSION_SECRET=YOUR_RANDOM_SECRET_HERE
GOOGLE_CLIENT_ID=YOUR_GOOGLE_CLIENT_ID
GOOGLE_CLIENT_SECRET=YOUR_GOOGLE_CLIENT_SECRET
GOOGLE_CALLBACK_URL=http://localhost:3000/auth/google/callback
FRONTEND_URL=http://localhost:5173
ROMS_DIR=/app/roms
SAVES_DIR=/app/savesdocker compose upSur WSL, cela peut échouer à cause des autorisations, auquel cas essayez:
sudo docker compose upL'application sera disponible sur:
- Frontend: http://localhost:5173
- Backend API: http://localhost:3000
- Connexion - Se connecter avec Google
- Upload ROM - Ajouter un jeu à sa bibliothèque
- Créer room - Cliquer sur "Play" pour créer une session
- Inviter ami - L'ami voit le jeu actif et peut rejoindre
- Sélection ports - Choisir manette 1 ou 2
- Lancer jeu - N'importe quel joueur peut démarrer
- Jouer - Le jeu tourne sur le serveur, streaming vers les clients
- Contrôle vitesse - Tab pour vitesse illimitée, +/- pour ajuster
- Menu pause - Appuyer sur Échap pour options
psnes/
├── backend/
│ ├── src/
│ │ ├── api/ # Routes REST
│ │ │ ├── auth.ts # Google OAuth
│ │ │ ├── friends.ts # Système d'amis
│ │ │ ├── games.ts # Bibliothèque ROMs
│ │ │ └── rooms.ts # Gestion rooms
│ │ ├── auth/
│ │ │ └── passport.ts # Config Passport
│ │ ├── emulator/
│ │ │ └── manager.ts # Gestion émulateur
│ │ ├── models/ # Models Prisma
│ │ ├── websocket/
│ │ │ └── index.ts # Socket.io handlers
│ │ ├── types/
│ │ │ └── index.ts # Types TypeScript
│ │ └── index.ts # Point d'entrée
│ ├── prisma/
│ │ └── schema.prisma # Schéma DB
│ ├── roms/ # Stockage ROMs
│ ├── saves/ # Stockage saves
│ └── package.json
├── frontend/
│ ├── src/
│ │ ├── lib/
│ │ │ ├── components/ # Composants Svelte
│ │ │ ├── stores/ # Stores globaux
│ │ │ └── api/ # API client
│ │ ├── routes/ # Pages SvelteKit
│ │ │ ├── +layout.svelte
│ │ │ ├── +page.svelte # Login
│ │ │ ├── library/ # Bibliothèque
│ │ │ └── room/[id]/ # Room de jeu
│ │ └── app.html
│ └── package.json
├── docker-compose.yml
└── README.md
cd backend
npm install
npm run db:generate # Générer Prisma client
npm run db:migrate # Migrations DB
npm run dev # Mode devcd frontend
npm install
npm run devLe projet utilise snes9x-next, un core libretro compilé en WebAssembly pour une émulation SNES réelle côté serveur.
| Touche | Action |
|---|---|
Tab |
Basculer entre vitesse normale (1x) et illimitée (MAX) |
+ / = |
Augmenter la vitesse (0.5x → 1x → 2x → 3x → MAX) |
- |
Diminuer la vitesse |
Vitesses disponibles:
- 0.5x - Ralenti (30 FPS)
- 1x - Normal (60 FPS)
- 2x - Double vitesse (120 FPS)
- 3x - Triple vitesse (180 FPS)
- MAX - Vitesse illimitée (CPU max)
📖 Documentation complète: docs/SPEED_CONTROLS.md
# Installer snes9x compilé en WebAssembly
npm install snes9x-emscriptenModifier backend/src/emulator/manager.ts:
import Snes9x from 'snes9x-emscripten';
async startEmulator(roomId: string, gameId: string) {
const emulator = await Snes9x.create();
await emulator.loadROM(romPath);
// Frame loop
emulator.onFrame((videoData, audioData) => {
this.emit(`frame:${roomId}`, videoData);
this.emit(`audio:${roomId}`, audioData);
});
}Utiliser node-ffi ou napi pour bindings vers libretro native:
# Installer libretro core
apt-get install libretro-snes9x-
Domaine: Configurer DNS pour
snes.pleymor.com -
SSL: Obtenir certificat Let's Encrypt
certbot certonly --standalone -d snes.pleymor.com- Variables d'env production:
NODE_ENV=production
FRONTEND_URL=https://snes.pleymor.com
GOOGLE_CALLBACK_URL=https://snes.pleymor.com/auth/google/callback
SESSION_SECRET=<strong-random-secret>- Docker Compose production:
# Ajouter proxy nginx pour SSL
services:
nginx:
image: nginx:alpine
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
- /etc/letsencrypt:/etc/letsencrypt- Optimisations:
- Activer compression gzip
- CDN pour assets statiques
- Redis persistence (RDB/AOF)
- Monitoring (Prometheus + Grafana)
- ✅ HTTPS obligatoire en production
- ✅ CORS configuré strictement
- ✅ Helmet.js pour headers sécurisés
- ✅ Session secrets forts
- ✅ Validation des uploads ROM (taille, type)
- ✅ Rate limiting sur API
GET /auth/google- Initier OAuthGET /auth/google/callback- Callback OAuthGET /auth/me- User actuelPOST /auth/logout- Déconnexion
GET /api/friends- Liste amisGET /api/friends/requests- Demandes en attentePOST /api/friends/request- Envoyer demandePOST /api/friends/accept/:id- Accepter demandeDELETE /api/friends/:id- Supprimer ami
GET /api/games- BibliothèquePOST /api/games/upload- Upload ROMDELETE /api/games/:id- Supprimer jeuGET /api/games/:id/saves- Sauvegardes
room:create- Créer roomroom:join- Rejoindre roomroom:leave- Quitter roomroom:selectPort- Sélectionner port manetteroom:updateKeyConfig- Modifier config touchesroom:toggleReady- Basculer readygame:start- Lancer jeugame:input- Envoyer inputsgame:pause- Pausegame:resume- Reprendregame:stop- Arrêtergame:save- Sauvegardergame:load- Chargergame:setSpeed- Changer vitesse émulation
room:created- Room crééeroom:updated- Room mise à jourroom:destroyed- Room détruitegame:started- Jeu démarrégame:frame- Frame vidéogame:audio- Frame audiogame:paused- Jeu en pausegame:resumed- Jeu reprisgame:stopped- Jeu arrêtégame:speedChanged- Vitesse émulation changéefriends:online- Amis en ligne
- Vérifier que Redis est démarré
- Vérifier les CORS settings
- Vérifier taille fichier < 10MB
- Vérifier extension (.smc, .sfc, etc.)
- Vérifier permissions dossier
roms/
- Ajuster buffer size dans Web Audio API
- Vérifier latence réseau
Le streaming vidéo utilise WebRTC pour une latence minimale :
- Latence réelle : ~45ms (mesurée)
- Amélioration : ~10x plus rapide que l'architecture précédente Socket.IO (~500ms)
- Technologie : Peer-to-peer direct avec ICE/STUN pour NAT traversal
- Qualité : 60 FPS stable avec audio synchronisé
- WebRTC DataChannel : Transmission inputs en temps réel
- MediaStream : Streaming vidéo/audio optimisé
- ICE candidates : Connexion P2P directe quand possible
- Audio buffering : ~100ms buffer pour synchronisation
- Frame timing : Synchronisation précise à 60 FPS
- Latence input→display : ~45ms ✅
- FPS stable : 60 FPS ✅
- Bande passante : ~2-5 Mbps par room
- Concurrent users : 50+ rooms
- Fork le projet
- Créer feature branch (
git checkout -b feature/AmazingFeature) - Commit changes (
git commit -m 'Add AmazingFeature') - Push branch (
git push origin feature/AmazingFeature) - Ouvrir Pull Request
Projet privé - Tous droits réservés
⚠️ Legal Disclaimer - ROMs and Intellectual Property / Disclaimer Légal - ROMs et Propriété Intellectuelle
IMPORTANT - READ BEFORE USE
This platform provides only a technical emulation infrastructure. The use of video game ROMs is strictly regulated by law:
-
Ownership of original games: You must own an original physical copy of the game whose ROM you upload. Possessing a ROM without the original game is illegal in most jurisdictions.
-
Personal use only: ROMs may only be used for strictly personal purposes. Any commercial or public distribution or sharing is prohibited.
-
Copyright: SNES games and their ROMs are protected by copyright. Nintendo and game developers retain all rights to their works.
-
Personal backup: In some jurisdictions, you have the right to create a backup copy of a game you legally own. Downloading ROMs from the Internet, even for games you own, may be illegal.
- The user is solely responsible for the content they upload and its compliance with applicable laws
- The operators of this platform do not provide, host, or distribute any ROMs
- This platform is provided solely for educational purposes and preservation of video game heritage
- By using this platform, you agree to comply with all local, national, and international intellectual property laws
Copyright infringement may result in civil and criminal prosecution, including substantial fines and imprisonment.
By using this platform, you acknowledge that you have read, understood, and accepted these terms.
IMPORTANT - À LIRE AVANT UTILISATION
Cette plateforme fournit uniquement une infrastructure technique d'émulation. L'utilisation de ROMs de jeux vidéo est strictement encadrée par la loi :
-
Propriété des jeux originaux : Vous devez posséder une copie physique originale du jeu dont vous uploadez la ROM. La possession d'une ROM sans le jeu original est illégale dans la plupart des juridictions.
-
Usage personnel uniquement : Les ROMs ne peuvent être utilisées que dans un cadre strictement personnel. Toute distribution, partage commercial ou public est interdit.
-
Droits d'auteur : Les jeux SNES et leurs ROMs sont protégés par le droit d'auteur. Nintendo et les développeurs de jeux détiennent tous les droits sur leurs œuvres.
-
Backup personnel : Dans certaines juridictions, vous avez le droit de créer une copie de sauvegarde d'un jeu que vous possédez légalement. Le téléchargement de ROMs depuis Internet, même pour des jeux que vous possédez, peut être illégal.
- L'utilisateur est seul responsable du contenu qu'il upload et de sa conformité avec les lois applicables
- Les opérateurs de cette plateforme ne fournissent, n'hébergent et ne distribuent aucune ROM
- Cette plateforme est fournie uniquement à des fins éducatives et de préservation du patrimoine vidéoludique
- En utilisant cette plateforme, vous acceptez de respecter toutes les lois locales, nationales et internationales sur la propriété intellectuelle
La violation des droits d'auteur peut entraîner des poursuites civiles et pénales, incluant des amendes substantielles et des peines d'emprisonnement.
En utilisant cette plateforme, vous reconnaissez avoir lu, compris et accepté ces conditions.
- Authentification Google
- Système d'amis
- Upload ROMs
- Rooms multijoueur
- Configuration manettes
- Architecture streaming
- Intégration émulateur réel (snes9x-next)
- Contrôle vitesse émulation dynamique
- Filtres vidéo (CRT, scanlines)
- Support gamepad physique
- Chat vocal
- Spectator mode (>2 joueurs)
- Replay recording
- Achievements system
- Support autres consoles (NES, Genesis, N64)
- Tournois en ligne
- Classements
- Cloud saves sync
Pour questions ou problèmes:
- GitHub Issues: psnes/issues
- Email: support@pleymor.com
Fait avec ❤️ par Pleymor