emoemu 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/settings.local.json +77 -0
- package/.node-version +1 -0
- package/CLAUDE.md +435 -0
- package/README.md +404 -0
- package/TODO.md +655 -0
- package/dist/index.cjs +25108 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +25085 -0
- package/docs/building-libretro-cores-arm-mac.md +237 -0
- package/docs/config-file-format.md +488 -0
- package/docs/cores-trd.md +425 -0
- package/docs/headless-hardware-rendering-trd.md +676 -0
- package/docs/libretro-cores-trd.md +997 -0
- package/docs/mupen64-software-rendering-trd.md +751 -0
- package/docs/n64-support-trd.md +306 -0
- package/docs/native-rendering-trd.md +540 -0
- package/docs/native-ui-rendering-trd.md +1195 -0
- package/docs/netplay-trd.md +665 -0
- package/docs/retroarch-netplay-docs.md +277 -0
- package/docs/save-state-format.md +666 -0
- package/eslint.config.js +111 -0
- package/icon/icon.png +0 -0
- package/icon/icon.pxd +0 -0
- package/package.json +63 -0
- package/pnpm-workspace.yaml +10 -0
- package/src/Emulator/consts.ts +14 -0
- package/src/Emulator/index.ts +2496 -0
- package/src/Emulator/saveState/index.ts +155 -0
- package/src/Emulator/screenshot/index.ts +160 -0
- package/src/Emulator/terminalDimensions/index.ts +79 -0
- package/src/Emulator/types.ts +83 -0
- package/src/cli/commands/consts.ts +10 -0
- package/src/cli/commands/index.ts +462 -0
- package/src/cli/parseArgs/consts.ts +17 -0
- package/src/cli/parseArgs/index.ts +457 -0
- package/src/cli/parseArgs/types.ts +61 -0
- package/src/cli/runEmulator/index.ts +406 -0
- package/src/cli/runEmulator/types.ts +7 -0
- package/src/consts.ts +19 -0
- package/src/core/button/consts.ts +35 -0
- package/src/core/button/index.ts +123 -0
- package/src/core/core.ts +300 -0
- package/src/core/index.ts +19 -0
- package/src/cores/libretro/api/index.ts +334 -0
- package/src/cores/libretro/api/types.ts +148 -0
- package/src/cores/libretro/callbacks/consts.ts +41 -0
- package/src/cores/libretro/callbacks/index.ts +456 -0
- package/src/cores/libretro/consts.ts +45 -0
- package/src/cores/libretro/coreOptions/consts.ts +36 -0
- package/src/cores/libretro/coreOptions/index.ts +222 -0
- package/src/cores/libretro/environment/consts.ts +118 -0
- package/src/cores/libretro/environment/index.ts +1095 -0
- package/src/cores/libretro/index.ts +937 -0
- package/src/cores/libretro/loader/index.ts +496 -0
- package/src/cores/libretro/pixelFormat/consts.ts +43 -0
- package/src/cores/libretro/pixelFormat/index.ts +397 -0
- package/src/cores/libretro/types.ts +339 -0
- package/src/frontend/AudioManager/index.ts +420 -0
- package/src/frontend/SettingsManager/index.ts +250 -0
- package/src/frontend/config/index.ts +608 -0
- package/src/frontend/config/tests.ts +354 -0
- package/src/frontend/config/types.ts +36 -0
- package/src/frontend/consts.ts +114 -0
- package/src/frontend/coreBuilder/index.ts +644 -0
- package/src/frontend/coreBuilder/types.ts +15 -0
- package/src/frontend/coreDownloader/index.ts +620 -0
- package/src/frontend/coreDownloader/types.ts +17 -0
- package/src/frontend/corePreferences/index.ts +69 -0
- package/src/frontend/coreRegistry/index.ts +276 -0
- package/src/frontend/directoryCache/index.ts +75 -0
- package/src/frontend/index.ts +79 -0
- package/src/frontend/notifications/consts.ts +14 -0
- package/src/frontend/notifications/index.ts +250 -0
- package/src/frontend/playlist/consts.ts +168 -0
- package/src/frontend/playlist/index.ts +899 -0
- package/src/frontend/playlist/labelFormatter/consts.ts +15 -0
- package/src/frontend/playlist/labelFormatter/index.ts +155 -0
- package/src/frontend/playlist/labelFormatter/tests.ts +153 -0
- package/src/frontend/playlist/reader/index.ts +559 -0
- package/src/frontend/playlist/sync/index.ts +511 -0
- package/src/frontend/playlist/systemLookup/index.ts +233 -0
- package/src/frontend/playlist/utils/index.ts +50 -0
- package/src/frontend/romScanner/consts.ts +348 -0
- package/src/frontend/romScanner/index.ts +1957 -0
- package/src/frontend/saveServices/consts.ts +2 -0
- package/src/frontend/saveServices/index.ts +313 -0
- package/src/frontend/serviceProvider/index.ts +108 -0
- package/src/frontend/serviceProvider/types.ts +13 -0
- package/src/index.ts +428 -0
- package/src/input/Controller/consts.ts +50 -0
- package/src/input/Controller/index.ts +81 -0
- package/src/input/GamepadManager/consts.ts +22 -0
- package/src/input/GamepadManager/index.ts +418 -0
- package/src/input/InputManager/consts.ts +86 -0
- package/src/input/InputManager/index.ts +593 -0
- package/src/input/InputMapper/consts.ts +33 -0
- package/src/input/InputMapper/index.ts +436 -0
- package/src/input/consts.ts +410 -0
- package/src/input/gamepadProfiles/index.ts +1100 -0
- package/src/input/index.ts +38 -0
- package/src/input/inputUtils/index.ts +31 -0
- package/src/netplay/FrameBuffer/consts.ts +2 -0
- package/src/netplay/FrameBuffer/index.ts +364 -0
- package/src/netplay/FrameBuffer/tests.ts +286 -0
- package/src/netplay/InputBuffer/consts.ts +7 -0
- package/src/netplay/InputBuffer/index.ts +347 -0
- package/src/netplay/InputBuffer/tests.ts +166 -0
- package/src/netplay/NetplayClient/index.ts +976 -0
- package/src/netplay/NetplayConnection/index.ts +536 -0
- package/src/netplay/NetplayDiscovery/consts.ts +41 -0
- package/src/netplay/NetplayDiscovery/index.ts +525 -0
- package/src/netplay/NetplayServer/index.ts +1407 -0
- package/src/netplay/SyncManager/index.ts +984 -0
- package/src/netplay/SyncManager/tests.ts +419 -0
- package/src/netplay/consts.ts +371 -0
- package/src/netplay/crc32/consts.ts +14 -0
- package/src/netplay/crc32/index.ts +97 -0
- package/src/netplay/crc32/tests.ts +40 -0
- package/src/netplay/index.ts +41 -0
- package/src/netplay/netplayLogger/consts.ts +30 -0
- package/src/netplay/netplayLogger/index.ts +345 -0
- package/src/netplay/protocol/consts.ts +86 -0
- package/src/netplay/protocol/index.ts +1280 -0
- package/src/netplay/protocol/tests.ts +606 -0
- package/src/netplay/protocol/types.ts +20 -0
- package/src/netplay/types.ts +395 -0
- package/src/rendering/KittyRenderer/index.ts +616 -0
- package/src/rendering/NativeRenderer/index.ts +279 -0
- package/src/rendering/NativeRenderer/tests.ts +133 -0
- package/src/rendering/TerminalRenderer/index.ts +770 -0
- package/src/rendering/consts.ts +401 -0
- package/src/rendering/fonts/CozetteVector.ttf +0 -0
- package/src/rendering/index.ts +26 -0
- package/src/rendering/nativeUi/NativeWindowManager/index.ts +158 -0
- package/src/rendering/nativeUi/NativeWindowManager/tests.ts +81 -0
- package/src/rendering/nativeUi/consts.ts +6 -0
- package/src/rendering/nativeUi/index.ts +20 -0
- package/src/rendering/postProcessing/consts.ts +38 -0
- package/src/rendering/postProcessing/index.ts +923 -0
- package/src/rendering/shared/ansi/consts.ts +12 -0
- package/src/rendering/shared/ansi/index.ts +104 -0
- package/src/rendering/shared/consts.ts +2 -0
- package/src/rendering/shared/fitToTerminal/index.ts +67 -0
- package/src/ui/AddRomsPrompt/consts.ts +13 -0
- package/src/ui/AddRomsPrompt/index.tsx +781 -0
- package/src/ui/App/consts.ts +2 -0
- package/src/ui/App/index.tsx +456 -0
- package/src/ui/AppCapabilities/index.tsx +67 -0
- package/src/ui/ConfigContext/index.tsx +56 -0
- package/src/ui/CoreManager/consts.ts +11 -0
- package/src/ui/CoreManager/index.tsx +779 -0
- package/src/ui/CoreSelector/consts.ts +2 -0
- package/src/ui/CoreSelector/index.tsx +251 -0
- package/src/ui/DialogContainer/index.tsx +42 -0
- package/src/ui/DialogOptionsList/index.tsx +61 -0
- package/src/ui/DuplicateCrcPrompt/consts.ts +5 -0
- package/src/ui/DuplicateCrcPrompt/index.tsx +146 -0
- package/src/ui/GamepadContext/consts.ts +15 -0
- package/src/ui/GamepadContext/index.tsx +295 -0
- package/src/ui/NativeDialog/index.tsx +120 -0
- package/src/ui/NetplayDisconnectedDialog/index.tsx +93 -0
- package/src/ui/NetplayPauseMenu/consts.ts +2 -0
- package/src/ui/NetplayPauseMenu/index.tsx +97 -0
- package/src/ui/RomBrowser/NetplayPanel/consts.ts +24 -0
- package/src/ui/RomBrowser/NetplayPanel/index.tsx +520 -0
- package/src/ui/RomBrowser/SettingsPanel/index.tsx +478 -0
- package/src/ui/RomBrowser/consts.ts +61 -0
- package/src/ui/RomBrowser/index.tsx +1164 -0
- package/src/ui/RomBrowser/settingsConfig/index.ts +320 -0
- package/src/ui/RomBrowser/types.ts +67 -0
- package/src/ui/SaveStateDialog/consts.ts +2 -0
- package/src/ui/SaveStateDialog/index.tsx +225 -0
- package/src/ui/WarningDialog/index.tsx +113 -0
- package/src/ui/consts.ts +27 -0
- package/src/ui/hooks/useClearTerminal/consts.ts +2 -0
- package/src/ui/hooks/useClearTerminal/index.ts +37 -0
- package/src/ui/hooks/useDialogNavigation/index.ts +99 -0
- package/src/ui/hooks/useGamepad/consts.ts +21 -0
- package/src/ui/hooks/useGamepad/index.ts +194 -0
- package/src/ui/index.ts +27 -0
- package/src/utils/buffer/consts.ts +17 -0
- package/src/utils/buffer/index.ts +129 -0
- package/src/utils/color/consts.ts +58 -0
- package/src/utils/color/index.ts +183 -0
- package/src/utils/compression/consts.ts +50 -0
- package/src/utils/compression/index.ts +101 -0
- package/src/utils/consts.ts +2 -0
- package/src/utils/crc32/consts.ts +22 -0
- package/src/utils/crc32/index.ts +83 -0
- package/src/utils/ensureDirectory/index.ts +10 -0
- package/src/utils/format/consts.ts +8 -0
- package/src/utils/format/index.ts +53 -0
- package/src/utils/getErrorMessage/index.ts +10 -0
- package/src/utils/index.ts +113 -0
- package/src/utils/ini/index.ts +200 -0
- package/src/utils/kitty/consts.ts +13 -0
- package/src/utils/kitty/index.ts +181 -0
- package/src/utils/logger/consts.ts +35 -0
- package/src/utils/logger/index.ts +217 -0
- package/src/utils/paths/consts.ts +18 -0
- package/src/utils/paths/index.ts +151 -0
- package/src/utils/png/consts.ts +34 -0
- package/src/utils/png/index.ts +131 -0
- package/src/utils/readJsonFile/index.ts +16 -0
- package/src/utils/rotateLogFile/index.ts +44 -0
- package/src/utils/safeClose/index.ts +10 -0
- package/src/utils/terminal/consts.ts +8 -0
- package/src/utils/terminal/index.ts +102 -0
- package/src/utils/thumbnailRenderer/consts.ts +2 -0
- package/src/utils/thumbnailRenderer/index.ts +147 -0
- package/src/utils/typedError/index.ts +26 -0
- package/tsconfig.json +31 -0
- package/vitest.config.ts +13 -0
package/README.md
ADDED
|
@@ -0,0 +1,404 @@
|
|
|
1
|
+
# 🎮 emoemu
|
|
2
|
+
|
|
3
|
+
<img width="100" alt="icon" src="https://github.com/user-attachments/assets/0447c490-0484-4b57-b35d-095ceaea7565" />
|
|
4
|
+
|
|
5
|
+
A terminal-based retro emulator written in TypeScript. Play classic games directly in your terminal using the Kitty graphics protocol, Unicode half-blocks, or ASCII characters. Supports **libretro cores** (RetroArch cores) to play NES, Game Boy, SNES, Sega Genesis, GBA, and more.
|
|
6
|
+
|
|
7
|
+
## ✨ Features
|
|
8
|
+
|
|
9
|
+
### General
|
|
10
|
+
|
|
11
|
+
- **Multiple render modes**: Native window (best performance), Kitty graphics protocol (best quality), Unicode half-blocks, ASCII art, or emoji
|
|
12
|
+
- **Post-processing modes**: Off, CRT preset, or Custom effects (scanlines, NTSC artifacts, bloom, vignette, gamma, etc.)
|
|
13
|
+
- **Diff-based rendering**: Optimized rendering that only updates changed pixels for better performance
|
|
14
|
+
- **Save states**: Automatic save/resume with gzip compression
|
|
15
|
+
- **Battery saves**: RetroArch-compatible `.srm` files for games with save RAM
|
|
16
|
+
- **Playlist generation**: Generate RetroArch-compatible `.lpl` playlists
|
|
17
|
+
- **Screenshots**: Capture screenshots with F8/F12, saved using RetroArch naming convention
|
|
18
|
+
- **Gamepad support**: Xbox (wired and wireless), PlayStation, Nintendo, and 8BitDo controllers via HID
|
|
19
|
+
- **Keyboard input**: Kitty keyboard protocol for accurate key detection, with legacy fallback
|
|
20
|
+
- **Dynamic scaling**: Auto-fits to terminal size with pixel aspect ratio correction
|
|
21
|
+
- **Multi-core architecture**: Extensible design for supporting additional systems
|
|
22
|
+
- **RetroArch integration**: Optionally load cores from existing RetroArch installation (`--retroarch`)
|
|
23
|
+
- **Netplay**: RetroArch-compatible multiplayer with rollback netcode
|
|
24
|
+
|
|
25
|
+
### Supported Systems
|
|
26
|
+
|
|
27
|
+
| System | Status | Extensions |
|
|
28
|
+
| -------------- | ------------------ | --------------- |
|
|
29
|
+
| NES | ✅ Via libretro | `.nes` |
|
|
30
|
+
| Game Boy / Color | ✅ Via libretro | `.gb`, `.gbc` |
|
|
31
|
+
| SNES | ✅ Via libretro | `.sfc`, `.smc` |
|
|
32
|
+
| Sega Genesis | ✅ Via libretro | `.md`, `.gen` |
|
|
33
|
+
| Game Boy Advance | ✅ Via libretro | `.gba` |
|
|
34
|
+
| Nintendo 64 | ✅ Via libretro | `.n64`, `.z64`, `.v64` |
|
|
35
|
+
| + Many more | ✅ Via libretro | Various |
|
|
36
|
+
|
|
37
|
+
> **Note:** Libretro cores must be installed separately. See [Using Libretro Cores](#-using-libretro-cores) below.
|
|
38
|
+
|
|
39
|
+
## 📋 Requirements
|
|
40
|
+
|
|
41
|
+
- Node.js 24+
|
|
42
|
+
- A terminal emulator (see below)
|
|
43
|
+
|
|
44
|
+
### Terminal Emulators
|
|
45
|
+
|
|
46
|
+
You can use any terminal emulator, but for the best experience we recommend using a terminal that supports both:
|
|
47
|
+
|
|
48
|
+
- **[Kitty Graphics Protocol](https://sw.kovidgoyal.net/kitty/graphics-protocol/)** - Enables high-quality pixel-perfect rendering directly in the terminal
|
|
49
|
+
- **[Kitty Keyboard Protocol](https://sw.kovidgoyal.net/kitty/keyboard-protocol/)** - Enables detecting multiple simultaneous key presses, which is required for many game actions (e.g., holding B to run while tapping A to jump)
|
|
50
|
+
|
|
51
|
+
#### ⭐ Recommended
|
|
52
|
+
|
|
53
|
+
These terminals support both high-quality graphics (Kitty graphics protocol) and the best keyboard experience (Kitty keyboard protocol):
|
|
54
|
+
|
|
55
|
+
- [Ghostty](https://ghostty.org/)
|
|
56
|
+
- [Kitty](https://sw.kovidgoyal.net/kitty/)
|
|
57
|
+
|
|
58
|
+
#### Other Terminals
|
|
59
|
+
|
|
60
|
+
Any other terminal will work with `--terminal` or `--ascii` mode. A gamepad is recommended since standard terminal input cannot detect multiple simultaneous key presses.
|
|
61
|
+
|
|
62
|
+
## 🚀 Quick Start
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
npx emoemu /path/to/game.nes
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## 📥 Installation
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
# Install globally
|
|
72
|
+
npm install -g emoemu
|
|
73
|
+
|
|
74
|
+
# Run
|
|
75
|
+
emoemu /path/to/game.nes
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## 📖 Usage
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
emoemu <rom> [options]
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### Core Selection
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
emoemu game.nes # Auto-detect core by file extension
|
|
88
|
+
emoemu game.nes --core fceumm # Explicitly select a core
|
|
89
|
+
emoemu --list-cores # Show available cores
|
|
90
|
+
emoemu --retroarch --list-cores # Include RetroArch cores
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
When multiple cores support the same ROM extension (e.g., `.sfc` works with both bsnes and snes9x), you'll be prompted to select which core to use. Use `--core <id>` to skip the prompt.
|
|
94
|
+
|
|
95
|
+
Use `--retroarch` to load libretro cores from RetroArch installation directories (see [Using Libretro Cores](#-using-libretro-cores)).
|
|
96
|
+
|
|
97
|
+
### Render Modes
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
emoemu game.nes --native # Native window (best performance, zero dependencies)
|
|
101
|
+
emoemu game.nes # Kitty graphics (default for most systems)
|
|
102
|
+
emoemu game.nes --terminal # Unicode half-blocks (default for N64)
|
|
103
|
+
emoemu game.nes --ascii # ASCII characters
|
|
104
|
+
emoemu game.nes --emoji # Emoji characters
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
**Render Mode:** By default, render mode is set to "Auto" which uses system-appropriate defaults: Kitty graphics for most systems (best quality) and Terminal mode for N64 (better performance with software rendering). You can override this in settings or with `--terminal`, `--kitty`, `--native`, etc.
|
|
108
|
+
|
|
109
|
+
> **Note:** The `--native` mode renders to a native window instead of the terminal, bypassing terminal I/O for the best performance. The window backend (fenster) and bitmap font are bundled — **no system dependencies to install**.
|
|
110
|
+
|
|
111
|
+
> **Tip:** When using `--terminal`, `--ascii`, or `--emoji` modes, scale your terminal font down to a small size so the characters are small enough to render graphics clearly. For example, on Ghostty or Kitty on macOS, press `Cmd+-` repeatedly. The default Kitty graphics mode renders at pixel level and doesn't require this.
|
|
112
|
+
|
|
113
|
+
### Display Options
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
emoemu game.nes --scale 2 # Fixed scale (Kitty mode, 0.25x-4x)
|
|
117
|
+
emoemu game.nes --png-level 1 # PNG compression 1-9 for Kitty mode (default: 4)
|
|
118
|
+
emoemu game.nes --width 120 # Fixed width (terminal/ASCII)
|
|
119
|
+
emoemu game.nes --height 40 # Fixed height (terminal/ASCII)
|
|
120
|
+
emoemu game.nes --no-color # Disable colors (terminal/ASCII modes)
|
|
121
|
+
emoemu game.nes --no-diff-render # Disable diff-based rendering optimization
|
|
122
|
+
emoemu game.nes --status # Show the status bar
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
**Video Scale:** By default, video scale is set to "Auto" which uses system-appropriate defaults: 2x for most systems (NES, SNES, Genesis, etc.) and 0.5x for N64. You can override this in settings or with `--scale`.
|
|
126
|
+
|
|
127
|
+
**Post-Processing Modes:**
|
|
128
|
+
|
|
129
|
+
Post-processing can be configured via the settings panel or toggled with the P key during gameplay. Three modes are available:
|
|
130
|
+
|
|
131
|
+
- **Off**: No effects applied (clean pixels)
|
|
132
|
+
- **CRT**: Preset values for an authentic retro look (gamma 1.3, scanlines 0.1, vignette 0.5, NTSC 1.0, curvature 0.1)
|
|
133
|
+
- **Custom**: User-defined effect values from config or command line
|
|
134
|
+
|
|
135
|
+
The P key cycles through: Off → Custom (if defined) → CRT → Off
|
|
136
|
+
|
|
137
|
+
**Custom Effect Settings:**
|
|
138
|
+
|
|
139
|
+
```bash
|
|
140
|
+
emoemu game.nes --gamma 1.2 # Gamma correction (default: 1.0)
|
|
141
|
+
emoemu game.nes --scanlines 0.3 # Scanline intensity (default: 0)
|
|
142
|
+
emoemu game.nes --saturation 1.2 # Color saturation (default: 1.0)
|
|
143
|
+
emoemu game.nes --brightness 1.1 # Brightness multiplier (default: 1.0)
|
|
144
|
+
emoemu game.nes --contrast 1.1 # Contrast adjustment (default: 1.0)
|
|
145
|
+
emoemu game.nes --vignette 0.5 # Vignette edge darkening (default: 0)
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
- `--gamma` adjusts display gamma. Values above 1.0 darken midtones for richer colors. Try `1.1` to `1.4`.
|
|
149
|
+
- `--scanlines` adds horizontal scanline darkening to simulate CRT phosphor gaps. Try `0.2` to `0.4` for subtle effect.
|
|
150
|
+
- `--saturation` boosts color vibrancy. Values above 1.0 increase saturation. Try `1.1` to `1.3` for CRT-like colors.
|
|
151
|
+
- `--brightness` adjusts overall brightness. Values above 1.0 brighten, below 1.0 darken.
|
|
152
|
+
- `--contrast` adjusts tonal range. Values above 1.0 increase contrast, below 1.0 flatten.
|
|
153
|
+
- `--vignette` darkens screen edges to simulate CRT electron beam falloff. Try `0.3` to `0.5`.
|
|
154
|
+
|
|
155
|
+
**Additional Effects (Kitty mode only):**
|
|
156
|
+
|
|
157
|
+
```bash
|
|
158
|
+
emoemu game.nes --crt # Start with CRT mode enabled
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
- `--crt` starts the emulator with CRT post-processing mode selected. Use P key or settings to switch to Custom mode if you want to use custom effect values.
|
|
162
|
+
- `--bloom` adds phosphor glow around bright areas. Try `0.3` to `0.6` for subtle CRT glow.
|
|
163
|
+
- `--bloom-threshold` sets brightness threshold for bloom effect. Default `0.6` (range 0-1).
|
|
164
|
+
- `--ntsc` simulates horizontal color bleeding from composite video signals. Try `0.5` to `1.0`.
|
|
165
|
+
- `--curvature` applies barrel distortion to simulate curved CRT glass. Try `0.1` to `0.3`.
|
|
166
|
+
|
|
167
|
+
### Emulation
|
|
168
|
+
|
|
169
|
+
```bash
|
|
170
|
+
emoemu game.nes --fps-limit 30 # Override FPS limit (0 = uncapped)
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
### Audio
|
|
174
|
+
|
|
175
|
+
```bash
|
|
176
|
+
emoemu game.nes # Audio enabled (default)
|
|
177
|
+
emoemu game.nes --no-audio # Disable audio
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
### Gamepad
|
|
181
|
+
|
|
182
|
+
```bash
|
|
183
|
+
emoemu --list-gamepads # Show detected controllers
|
|
184
|
+
emoemu game.nes --debug-gamepad # Debug raw HID data
|
|
185
|
+
emoemu game.nes --no-gamepad # Disable gamepad support
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
### Save Data
|
|
189
|
+
|
|
190
|
+
```bash
|
|
191
|
+
emoemu game.nes # Auto-save state and battery saves (default)
|
|
192
|
+
emoemu game.nes --no-save-state # Disable save state loading/saving
|
|
193
|
+
emoemu game.nes --no-battery-save # Disable battery save (.srm) loading/saving
|
|
194
|
+
emoemu game.nes --no-gzip-state # Save states uncompressed (for debugging)
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
Save states are saved automatically on exit. File names include the core ID (e.g., `game.libretro-fceumm.state`, `game.libretro-bsnes.state`) to prevent conflicts when using different cores for the same ROM.
|
|
198
|
+
|
|
199
|
+
Battery saves (`.srm` files) store cartridge SRAM for games with battery-backed saves (e.g., Zelda, Pokemon) and are RetroArch-compatible.
|
|
200
|
+
|
|
201
|
+
### Playlist Generation
|
|
202
|
+
|
|
203
|
+
Generate RetroArch-compatible `.lpl` playlist files from your ROM collection:
|
|
204
|
+
|
|
205
|
+
```bash
|
|
206
|
+
emoemu --generate-playlist /path/to/roms # Generate per-system playlists
|
|
207
|
+
emoemu --generate-playlist /path/to/roms --single-playlist "My Games" # Single playlist
|
|
208
|
+
emoemu --retroarch --generate-playlist /path/to/roms # Include RetroArch cores
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
| Option | Description |
|
|
212
|
+
|--------|-------------|
|
|
213
|
+
| `--generate-playlist [path]` | Scan directory for ROMs (default: current directory) |
|
|
214
|
+
| `--playlist-output <dir>` | Output directory (default: platform-specific, e.g., `~/.config/emoemu/playlists/`) |
|
|
215
|
+
| `--single-playlist <name>` | Create one playlist instead of per-system |
|
|
216
|
+
| `--windows-paths` | Use Windows backslash separators |
|
|
217
|
+
|
|
218
|
+
### Netplay
|
|
219
|
+
|
|
220
|
+
Play multiplayer games over the network using RetroArch-compatible netplay:
|
|
221
|
+
|
|
222
|
+
```bash
|
|
223
|
+
# Host a session (player 1)
|
|
224
|
+
emoemu game.sfc --netplay-host --netplay-nick "Player1"
|
|
225
|
+
|
|
226
|
+
# Join via LAN discovery (auto-finds host on local network)
|
|
227
|
+
emoemu game.sfc --netplay-connect --netplay-nick "Player2"
|
|
228
|
+
|
|
229
|
+
# Join a specific host (player 2)
|
|
230
|
+
emoemu game.sfc --netplay-connect 192.168.1.100 --netplay-nick "Player2"
|
|
231
|
+
|
|
232
|
+
# Join with password
|
|
233
|
+
emoemu game.sfc --netplay-connect host:55435 --netplay-password secret
|
|
234
|
+
|
|
235
|
+
# Spectate a session
|
|
236
|
+
emoemu game.sfc --netplay-connect 192.168.1.100 --netplay-spectate
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
| Option | Description |
|
|
240
|
+
|--------|-------------|
|
|
241
|
+
| `--netplay-host` | Host a netplay session (server mode) |
|
|
242
|
+
| `--netplay-connect [host]` | Connect to server (host or host:port). Omit host for LAN auto-discovery |
|
|
243
|
+
| `--netplay-port <n>` | Port for netplay (default: 55435) |
|
|
244
|
+
| `--netplay-password <pw>` | Password for the session |
|
|
245
|
+
| `--netplay-spectate` | Join as spectator (view only) |
|
|
246
|
+
| `--netplay-nick <name>` | Your nickname (default: Player) |
|
|
247
|
+
| `--netplay-frames <n>` | Input delay 0-16 (higher = fewer rollbacks, more latency) |
|
|
248
|
+
|
|
249
|
+
> **Note:** Netplay requires libretro cores.
|
|
250
|
+
|
|
251
|
+
## 🔌 Using Libretro Cores
|
|
252
|
+
|
|
253
|
+
emoemu can load native [libretro cores](https://www.libretro.com/) (the same cores used by RetroArch) to support additional systems without any configuration.
|
|
254
|
+
|
|
255
|
+
### Using Cores from RetroArch
|
|
256
|
+
|
|
257
|
+
If you already have RetroArch installed with cores, use the `--retroarch` flag to load them:
|
|
258
|
+
|
|
259
|
+
```bash
|
|
260
|
+
emoemu game.md --retroarch # Load RetroArch cores and play
|
|
261
|
+
emoemu --retroarch --list-cores # Show all cores including RetroArch
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
This reads your `retroarch.cfg` (read-only) to find the core directory.
|
|
265
|
+
|
|
266
|
+
### Installing Cores
|
|
267
|
+
|
|
268
|
+
#### Core Manager (Recommended)
|
|
269
|
+
|
|
270
|
+
Use the built-in Core Manager to download and manage cores:
|
|
271
|
+
|
|
272
|
+
1. Launch emoemu and open the ROM browser
|
|
273
|
+
2. Tab to the action bar and select **Manage Cores**
|
|
274
|
+
3. Switch to the **Download** tab to see recommended cores
|
|
275
|
+
4. Press Enter to download a core
|
|
276
|
+
|
|
277
|
+
The Core Manager shows recommended cores for popular systems and provides access to the full libretro buildbot catalog.
|
|
278
|
+
|
|
279
|
+
#### Manual Install
|
|
280
|
+
|
|
281
|
+
1. **Download cores** from the [RetroArch buildbot](https://buildbot.libretro.com/nightly/):
|
|
282
|
+
- macOS: Choose `apple/osx/arm64` or `apple/osx/x86_64`
|
|
283
|
+
- Linux: Choose `linux/x86_64`
|
|
284
|
+
- Windows: Choose `windows/x86_64`
|
|
285
|
+
|
|
286
|
+
2. **Place cores** in one of these directories:
|
|
287
|
+
| Platform | Directory |
|
|
288
|
+
|----------|-----------|
|
|
289
|
+
| macOS | `~/Library/Application Support/emoemu/cores/` |
|
|
290
|
+
| Linux | `~/.config/emoemu/cores/` |
|
|
291
|
+
| Windows | `%APPDATA%\emoemu\cores\` |
|
|
292
|
+
|
|
293
|
+
3. **Run your game** - cores are auto-detected by ROM extension:
|
|
294
|
+
```bash
|
|
295
|
+
emoemu game.md # Auto-detects picodrive
|
|
296
|
+
emoemu game.gba # Auto-detects mgba
|
|
297
|
+
emoemu --list-cores # Show all available cores
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
### Recommended Cores
|
|
301
|
+
|
|
302
|
+
| Core | Systems |
|
|
303
|
+
|------|---------|
|
|
304
|
+
| `bsnes` | SNES |
|
|
305
|
+
| `mgba` | Game Boy Advance |
|
|
306
|
+
| `gambatte` | Game Boy / Color |
|
|
307
|
+
| `picodrive` | Sega Genesis / Mega Drive |
|
|
308
|
+
| `mupen64plus_next` | Nintendo 64 |
|
|
309
|
+
|
|
310
|
+
### BIOS Files
|
|
311
|
+
|
|
312
|
+
Some cores require BIOS files. Place them in `./system/`:
|
|
313
|
+
```
|
|
314
|
+
./system/
|
|
315
|
+
├── gba_bios.bin # GBA BIOS (optional for mgba)
|
|
316
|
+
├── bios_CD_U.bin # Sega CD BIOS (for picodrive)
|
|
317
|
+
└── syscard3.pce # PC Engine CD BIOS
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
### Limitations
|
|
321
|
+
|
|
322
|
+
- **Software rendering only**: Cores requiring OpenGL/Vulkan won't work (e.g., PPSSPP, Dolphin)
|
|
323
|
+
- **N64 on macOS ARM64**: Requires Xcode CLI tools (`xcode-select --install`). The core is automatically built from source with software rendering since pre-built ARM64 binaries require OpenGL.
|
|
324
|
+
- **No core options UI**: Core-specific settings use defaults
|
|
325
|
+
|
|
326
|
+
## 🎮 Controls
|
|
327
|
+
|
|
328
|
+
### Keyboard
|
|
329
|
+
|
|
330
|
+
| Button | Primary | Alternate |
|
|
331
|
+
| ------ | ------- | ---------- |
|
|
332
|
+
| D-Pad | WASD | Arrow keys |
|
|
333
|
+
| A | K | Z |
|
|
334
|
+
| B | J | X |
|
|
335
|
+
| Start | Enter | |
|
|
336
|
+
| Select | Space | |
|
|
337
|
+
|
|
338
|
+
### Shortcuts
|
|
339
|
+
|
|
340
|
+
| Key | Action |
|
|
341
|
+
| ------ | ----------------------------- |
|
|
342
|
+
| F8/F12 | Take screenshot |
|
|
343
|
+
| M | Toggle audio mute |
|
|
344
|
+
| P | Cycle post-processing (Off → Custom → CRT) |
|
|
345
|
+
| R | Cycle render mode |
|
|
346
|
+
| Esc | Quit |
|
|
347
|
+
| Ctrl+C | Quit |
|
|
348
|
+
|
|
349
|
+
### Gamepad
|
|
350
|
+
|
|
351
|
+
Standard gamepad mapping is used. Controllers are auto-detected with hotplug support.
|
|
352
|
+
|
|
353
|
+
Supported controllers:
|
|
354
|
+
|
|
355
|
+
- Xbox (360, One, Series X/S)
|
|
356
|
+
- PlayStation (DS4, DualSense)
|
|
357
|
+
- Nintendo (Switch Pro, Joy-Cons)
|
|
358
|
+
- 8BitDo controllers
|
|
359
|
+
|
|
360
|
+
**Analog stick support**: For systems that require analog input (like N64), the left analog stick is mapped directly to the core's analog axes. This enables proper control in games like Super Mario 64 that need precise analog movement.
|
|
361
|
+
|
|
362
|
+
## 🔨 Building from Source
|
|
363
|
+
|
|
364
|
+
```bash
|
|
365
|
+
git clone https://github.com/tuxracer/emoemu.git
|
|
366
|
+
cd emoemu
|
|
367
|
+
pnpm install # Install dependencies
|
|
368
|
+
pnpm run build # Build the project
|
|
369
|
+
pnpm run typecheck # Type check without building
|
|
370
|
+
pnpm run test:run # Run tests
|
|
371
|
+
pnpm run check # Run typecheck, lint, and tests
|
|
372
|
+
pnpm run start /path/to/game.nes
|
|
373
|
+
```
|
|
374
|
+
|
|
375
|
+
## Project Structure
|
|
376
|
+
|
|
377
|
+
```
|
|
378
|
+
src/
|
|
379
|
+
├── index.ts # CLI entry point
|
|
380
|
+
├── cli/ # Argument parsing, commands, emulator runner
|
|
381
|
+
├── Emulator/ # Main emulation loop, renderer orchestration
|
|
382
|
+
├── core/ # Multi-core interface definitions
|
|
383
|
+
├── frontend/ # Shared frontend (audio, state, registry)
|
|
384
|
+
├── cores/
|
|
385
|
+
│ └── libretro/ # Libretro core wrapper (RetroArch cores)
|
|
386
|
+
├── input/ # Keyboard and gamepad input
|
|
387
|
+
├── rendering/ # Terminal renderers
|
|
388
|
+
├── netplay/ # RetroArch-compatible netplay (rollback, LAN discovery)
|
|
389
|
+
└── ui/ # React/Ink TUI (ROM browser, settings)
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
## Architecture
|
|
393
|
+
|
|
394
|
+
emoemu uses a **libretro-inspired** multi-core architecture:
|
|
395
|
+
|
|
396
|
+
- **Cores** (`src/cores/`): System-specific emulation (CPU, PPU, APU, memory)
|
|
397
|
+
- **Frontend** (`src/frontend/`): Shared infrastructure (audio, input, rendering, state)
|
|
398
|
+
- **Core Interface** (`src/core/`): Standard interface all cores implement
|
|
399
|
+
|
|
400
|
+
This separation allows adding new systems without modifying shared code. See [docs/cores-trd.md](docs/cores-trd.md) for the full architecture documentation.
|
|
401
|
+
|
|
402
|
+
## 📄 License
|
|
403
|
+
|
|
404
|
+
MIT
|