@tmustier/pi-nes 0.2.4 → 0.2.6
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/AGENTS.md +89 -1
- package/README.md +77 -48
- package/extensions/nes/config.ts +32 -12
- package/extensions/nes/native/nes-core/Cargo.lock +0 -2
- package/extensions/nes/native/nes-core/Cargo.toml +1 -1
- package/extensions/nes/native/nes-core/index.d.ts +5 -0
- package/extensions/nes/native/nes-core/index.node +0 -0
- package/extensions/nes/native/nes-core/native.d.ts +5 -0
- package/extensions/nes/native/nes-core/src/lib.rs +25 -0
- package/extensions/nes/native/nes-core/vendor/nes_rust/.cargo-ok +1 -0
- package/extensions/nes/native/nes-core/vendor/nes_rust/.cargo_vcs_info.json +5 -0
- package/extensions/nes/native/nes-core/vendor/nes_rust/.travis.yml +3 -0
- package/extensions/nes/native/nes-core/vendor/nes_rust/Cargo.toml +23 -0
- package/extensions/nes/native/nes-core/vendor/nes_rust/LICENSE +21 -0
- package/extensions/nes/native/nes-core/vendor/nes_rust/README.md +59 -0
- package/extensions/nes/native/nes-core/vendor/nes_rust/src/apu.rs +1114 -0
- package/extensions/nes/native/nes-core/vendor/nes_rust/src/audio.rs +6 -0
- package/extensions/nes/native/nes-core/vendor/nes_rust/src/button.rs +23 -0
- package/extensions/nes/native/nes-core/vendor/nes_rust/src/cpu.rs +2364 -0
- package/extensions/nes/native/nes-core/vendor/nes_rust/src/default_audio.rs +49 -0
- package/extensions/nes/native/nes-core/vendor/nes_rust/src/default_display.rs +47 -0
- package/extensions/nes/native/nes-core/vendor/nes_rust/src/default_input.rs +33 -0
- package/extensions/nes/native/nes-core/vendor/nes_rust/src/display.rs +10 -0
- package/extensions/nes/native/nes-core/vendor/nes_rust/src/input.rs +7 -0
- package/extensions/nes/native/nes-core/vendor/nes_rust/src/joypad.rs +86 -0
- package/extensions/nes/native/nes-core/vendor/nes_rust/src/lib.rs +168 -0
- package/extensions/nes/native/nes-core/vendor/nes_rust/src/mapper.rs +502 -0
- package/extensions/nes/native/nes-core/vendor/nes_rust/src/memory.rs +73 -0
- package/extensions/nes/native/nes-core/vendor/nes_rust/src/ppu.rs +1378 -0
- package/extensions/nes/native/nes-core/vendor/nes_rust/src/register.rs +560 -0
- package/extensions/nes/native/nes-core/vendor/nes_rust/src/rom.rs +231 -0
- package/extensions/nes/nes-core.ts +27 -4
- package/package.json +1 -1
- package/spec.md +2 -4
package/AGENTS.md
CHANGED
|
@@ -1,6 +1,94 @@
|
|
|
1
1
|
# AGENTS.md
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Technical guidance for AI agents working on this codebase.
|
|
4
|
+
|
|
5
|
+
## Architecture
|
|
6
|
+
|
|
7
|
+
pi-nes is a NES emulator extension for [pi](https://github.com/mariozechner/pi). It uses a Rust-based emulator core compiled as a Node.js native addon.
|
|
8
|
+
|
|
9
|
+
### Project Structure
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
pi-nes/
|
|
13
|
+
├── package.json # Pi package manifest (pi.extensions points to ./extensions/nes)
|
|
14
|
+
└── extensions/nes/
|
|
15
|
+
├── index.ts # Extension entry - registers /nes and /nes-config commands
|
|
16
|
+
├── nes-core.ts # TypeScript wrapper for native addon
|
|
17
|
+
├── nes-session.ts # Game session management (frame timing, SRAM saves)
|
|
18
|
+
├── nes-component.ts # TUI overlay component (input handling, render loop)
|
|
19
|
+
├── renderer.ts # Frame rendering (Kitty image protocol, PNG, ANSI)
|
|
20
|
+
├── config.ts # User config (~/.pi/nes/config.json)
|
|
21
|
+
├── paths.ts # Path resolution utilities
|
|
22
|
+
├── roms.ts # ROM directory listing
|
|
23
|
+
├── saves.ts # SRAM persistence
|
|
24
|
+
└── native/
|
|
25
|
+
├── nes-core/ # Rust NES emulator addon (required)
|
|
26
|
+
│ ├── Cargo.toml # Dependencies: nes_rust, napi
|
|
27
|
+
│ ├── src/lib.rs # Exposes NativeNes class via napi-rs
|
|
28
|
+
│ └── index.node # Compiled binary
|
|
29
|
+
└── kitty-shm/ # Rust shared memory addon (optional)
|
|
30
|
+
├── src/lib.rs # POSIX shm_open/mmap for zero-copy frames
|
|
31
|
+
└── index.node # Compiled binary
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### Native Core
|
|
35
|
+
|
|
36
|
+
The emulator uses the [`nes_rust`](https://crates.io/crates/nes_rust) crate with [napi-rs](https://napi.rs) bindings.
|
|
37
|
+
|
|
38
|
+
**API exposed to JavaScript:**
|
|
39
|
+
- `new NativeNes()` - Create emulator instance
|
|
40
|
+
- `setRom(Uint8Array)` - Load ROM data
|
|
41
|
+
- `bootup()` / `reset()` - Start/restart emulation
|
|
42
|
+
- `stepFrame()` - Advance one frame (~60fps)
|
|
43
|
+
- `pressButton(n)` / `releaseButton(n)` - Controller input (0=select, 1=start, 2=A, 3=B, 4-7=dpad)
|
|
44
|
+
- `getFramebuffer()` - Returns RGB pixel data (256×240×3 bytes, zero-copy via external buffer)
|
|
45
|
+
|
|
46
|
+
### Rendering Pipeline
|
|
47
|
+
|
|
48
|
+
```
|
|
49
|
+
NES Core → RGB framebuffer (256×240×3) → Renderer → Terminal
|
|
50
|
+
│
|
|
51
|
+
├─ Kitty shared memory (t=s) — fastest, requires kitty-shm addon
|
|
52
|
+
├─ Kitty file transport (t=f) — writes to /dev/shm or temp file
|
|
53
|
+
├─ Kitty PNG — base64-encoded PNG fallback
|
|
54
|
+
└─ ANSI half-blocks — ▀▄ characters, works everywhere
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
- Image mode (`renderer: "image"`) runs at ~30fps to keep emulation stable
|
|
58
|
+
- Text mode (`renderer: "text"`) runs at ~60fps in an overlay
|
|
59
|
+
- Image mode uses near-fullscreen (90% height) because Kitty graphics can't composite in overlays
|
|
60
|
+
|
|
61
|
+
### Session Lifecycle
|
|
62
|
+
|
|
63
|
+
1. `/nes` creates a `NesSession` that owns the core and runs the frame loop
|
|
64
|
+
2. `NesOverlayComponent` attaches to display frames and handle input
|
|
65
|
+
3. `Ctrl+Q` detaches the component but keeps the session running in background
|
|
66
|
+
4. `/nes` reattaches to existing session; `/nes <path>` starts a new one
|
|
67
|
+
5. `Q` or `session_shutdown` event stops the session and disposes the core
|
|
68
|
+
|
|
69
|
+
## Building Native Addons
|
|
70
|
+
|
|
71
|
+
Requires Rust toolchain (cargo + rustc).
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
# NES core (required)
|
|
75
|
+
cd extensions/nes/native/nes-core
|
|
76
|
+
npm install && npm run build
|
|
77
|
+
|
|
78
|
+
# Kitty shared memory (optional, faster rendering)
|
|
79
|
+
cd extensions/nes/native/kitty-shm
|
|
80
|
+
npm install && npm run build
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
The addons compile to `index.node`. The JS wrapper (`index.js`) tries to load it and exports `isAvailable: boolean`.
|
|
84
|
+
|
|
85
|
+
## Known Limitations
|
|
86
|
+
|
|
87
|
+
- **No audio** — `enableAudio` config exists but no audio backend is implemented
|
|
88
|
+
- **No save states** — Only battery-backed SRAM saves are persisted
|
|
89
|
+
- **SRAM for native core** — Tracked in issue #3
|
|
90
|
+
|
|
91
|
+
## Release and Publishing
|
|
4
92
|
|
|
5
93
|
## Version Bumps (Git + npm)
|
|
6
94
|
|
package/README.md
CHANGED
|
@@ -1,72 +1,65 @@
|
|
|
1
1
|
# pi-nes
|
|
2
2
|
|
|
3
|
-
NES
|
|
3
|
+
Play NES games in your terminal. A [pi](https://github.com/mariozechner/pi) extension that runs a full NES emulator with Kitty graphics support.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Installation
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
|
-
|
|
9
|
-
npm install
|
|
8
|
+
pi install npm:@tmustier/pi-nes
|
|
10
9
|
```
|
|
11
10
|
|
|
12
|
-
|
|
11
|
+
Or from git:
|
|
12
|
+
```bash
|
|
13
|
+
pi install git:github.com/tmustier/pi-nes
|
|
14
|
+
```
|
|
13
15
|
|
|
14
|
-
|
|
16
|
+
## Quick Start
|
|
15
17
|
|
|
16
18
|
```bash
|
|
17
|
-
#
|
|
18
|
-
|
|
19
|
-
npm install
|
|
20
|
-
npm run build
|
|
21
|
-
|
|
22
|
-
# Kitty shared-memory renderer (optional, faster)
|
|
23
|
-
cd /Users/thomasmustier/projects/pi-nes/extensions/nes/native/kitty-shm
|
|
24
|
-
npm install
|
|
25
|
-
npm run build
|
|
19
|
+
/nes # Pick a ROM from your library
|
|
20
|
+
/nes ~/roms/smb.nes # Load a specific ROM
|
|
26
21
|
```
|
|
27
22
|
|
|
28
|
-
|
|
23
|
+
On first run, you'll be prompted to set your ROM directory and display quality.
|
|
29
24
|
|
|
30
|
-
##
|
|
25
|
+
## Controls
|
|
31
26
|
|
|
32
|
-
|
|
33
|
-
# From npm
|
|
34
|
-
pi install npm:@tmustier/pi-nes
|
|
27
|
+
### Game Controls
|
|
35
28
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
29
|
+
| Action | Keys |
|
|
30
|
+
|--------|------|
|
|
31
|
+
| D-pad | Arrow keys or WASD |
|
|
32
|
+
| A button | Z |
|
|
33
|
+
| B button | X |
|
|
34
|
+
| Start | Enter or Space |
|
|
35
|
+
| Select | Tab |
|
|
39
36
|
|
|
40
|
-
|
|
37
|
+
### Emulator Controls
|
|
41
38
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
39
|
+
| Action | Key |
|
|
40
|
+
|--------|-----|
|
|
41
|
+
| Detach (keep running) | Ctrl+Q |
|
|
42
|
+
| Quit | Q |
|
|
46
43
|
|
|
47
|
-
|
|
48
|
-
- `/nes` — pick a ROM from the configured directory or reattach to a running session
|
|
49
|
-
- `/nes <path>` — load a specific ROM
|
|
50
|
-
- `/nes debug [<path>]` — enable debug overlay (FPS/memory stats)
|
|
51
|
-
- `/nes config` — guided configuration (ROM directory + quality)
|
|
52
|
-
- `/nes-config` — edit configuration (alias)
|
|
44
|
+
**Tip:** Detach with `Ctrl+Q` to return to pi, then run `/nes` to reattach to your game.
|
|
53
45
|
|
|
54
|
-
|
|
55
|
-
- `Ctrl+Q` — detach overlay (keeps the session running)
|
|
56
|
-
- `Q` — quit emulator
|
|
46
|
+
## Commands
|
|
57
47
|
|
|
58
|
-
|
|
48
|
+
| Command | Description |
|
|
49
|
+
|---------|-------------|
|
|
50
|
+
| `/nes` | Pick a ROM or reattach to running session |
|
|
51
|
+
| `/nes <path>` | Load a specific ROM file |
|
|
52
|
+
| `/nes config` | Configure ROM directory and quality |
|
|
53
|
+
| `/nes debug` | Show FPS and memory stats |
|
|
59
54
|
|
|
60
55
|
## Configuration
|
|
61
56
|
|
|
62
|
-
Config
|
|
57
|
+
Config is stored at `~/.pi/nes/config.json`. Use `/nes config` for guided setup.
|
|
63
58
|
|
|
64
|
-
Example:
|
|
65
59
|
```json
|
|
66
60
|
{
|
|
67
61
|
"romDir": "/roms/nes",
|
|
68
|
-
"saveDir": "/
|
|
69
|
-
"enableAudio": false,
|
|
62
|
+
"saveDir": "/roms/nes/saves",
|
|
70
63
|
"renderer": "image",
|
|
71
64
|
"pixelScale": 1.2,
|
|
72
65
|
"keybindings": {
|
|
@@ -82,14 +75,50 @@ Example:
|
|
|
82
75
|
}
|
|
83
76
|
```
|
|
84
77
|
|
|
85
|
-
|
|
78
|
+
### Options
|
|
86
79
|
|
|
87
|
-
|
|
80
|
+
| Option | Default | Description |
|
|
81
|
+
|--------|---------|-------------|
|
|
82
|
+
| `romDir` | `/roms/nes` | Where to look for ROM files |
|
|
83
|
+
| `saveDir` | `/roms/nes/saves` | Where to store battery saves (defaults to `<romDir>/saves`) |
|
|
84
|
+
| `renderer` | `"image"` | `"image"` (Kitty graphics) or `"text"` (ANSI) |
|
|
85
|
+
| `pixelScale` | `1.2` | Display scale (0.5–4.0) |
|
|
88
86
|
|
|
89
|
-
##
|
|
87
|
+
## Terminal Support
|
|
90
88
|
|
|
91
|
-
|
|
89
|
+
**Best experience:** [Kitty](https://sw.kovidgoyal.net/kitty/) terminal with image protocol support.
|
|
92
90
|
|
|
93
|
-
|
|
91
|
+
- **Kitty** — Full graphics via image protocol (shared memory or file transport)
|
|
92
|
+
- **Other terminals** — Falls back to ANSI half-block characters (`▀▄`)
|
|
94
93
|
|
|
95
|
-
|
|
94
|
+
Set `"renderer": "text"` if you prefer the ANSI renderer or have display issues.
|
|
95
|
+
|
|
96
|
+
## Limitations
|
|
97
|
+
|
|
98
|
+
- **No audio** — Sound is not currently supported
|
|
99
|
+
- **No save states** — Only battery-backed SRAM saves work
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
## Building from Source
|
|
104
|
+
|
|
105
|
+
Requires Rust toolchain (cargo + rustc).
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
git clone https://github.com/tmustier/pi-nes
|
|
109
|
+
cd pi-nes
|
|
110
|
+
npm install
|
|
111
|
+
|
|
112
|
+
# Build the NES core (required)
|
|
113
|
+
cd extensions/nes/native/nes-core
|
|
114
|
+
npm install && npm run build
|
|
115
|
+
|
|
116
|
+
# Build shared memory renderer (optional, faster on Kitty)
|
|
117
|
+
cd ../kitty-shm
|
|
118
|
+
npm install && npm run build
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
Run locally:
|
|
122
|
+
```bash
|
|
123
|
+
pi --extension /path/to/pi-nes
|
|
124
|
+
```
|
package/extensions/nes/config.ts
CHANGED
|
@@ -15,9 +15,15 @@ export interface NesConfig {
|
|
|
15
15
|
keybindings: InputMapping;
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
+
const DEFAULT_ROM_DIR = path.join(path.sep, "roms", "nes");
|
|
19
|
+
|
|
20
|
+
function defaultSaveDir(romDir: string): string {
|
|
21
|
+
return path.join(romDir, "saves");
|
|
22
|
+
}
|
|
23
|
+
|
|
18
24
|
export const DEFAULT_CONFIG: NesConfig = {
|
|
19
|
-
romDir:
|
|
20
|
-
saveDir:
|
|
25
|
+
romDir: DEFAULT_ROM_DIR,
|
|
26
|
+
saveDir: defaultSaveDir(DEFAULT_ROM_DIR),
|
|
21
27
|
enableAudio: false,
|
|
22
28
|
renderer: "image",
|
|
23
29
|
pixelScale: 1.2,
|
|
@@ -39,15 +45,18 @@ export function getConfigPath(): string {
|
|
|
39
45
|
|
|
40
46
|
export function normalizeConfig(raw: unknown): NesConfig {
|
|
41
47
|
const parsed = typeof raw === "object" && raw !== null ? (raw as RawConfig) : {};
|
|
48
|
+
const romDir =
|
|
49
|
+
typeof parsed.romDir === "string" && parsed.romDir.length > 0
|
|
50
|
+
? normalizePath(parsed.romDir, DEFAULT_CONFIG.romDir)
|
|
51
|
+
: DEFAULT_CONFIG.romDir;
|
|
52
|
+
const saveDirFallback = defaultSaveDir(romDir);
|
|
53
|
+
const saveDir =
|
|
54
|
+
typeof parsed.saveDir === "string" && parsed.saveDir.length > 0
|
|
55
|
+
? normalizePath(parsed.saveDir, saveDirFallback)
|
|
56
|
+
: saveDirFallback;
|
|
42
57
|
return {
|
|
43
|
-
romDir
|
|
44
|
-
|
|
45
|
-
? normalizePath(parsed.romDir, DEFAULT_CONFIG.romDir)
|
|
46
|
-
: DEFAULT_CONFIG.romDir,
|
|
47
|
-
saveDir:
|
|
48
|
-
typeof parsed.saveDir === "string" && parsed.saveDir.length > 0
|
|
49
|
-
? normalizePath(parsed.saveDir, DEFAULT_CONFIG.saveDir)
|
|
50
|
-
: DEFAULT_CONFIG.saveDir,
|
|
58
|
+
romDir,
|
|
59
|
+
saveDir,
|
|
51
60
|
enableAudio: typeof parsed.enableAudio === "boolean" ? parsed.enableAudio : DEFAULT_CONFIG.enableAudio,
|
|
52
61
|
renderer: parsed.renderer === "text" ? "text" : DEFAULT_CONFIG.renderer,
|
|
53
62
|
pixelScale: normalizePixelScale(parsed.pixelScale),
|
|
@@ -61,12 +70,15 @@ export function formatConfig(config: NesConfig): string {
|
|
|
61
70
|
|
|
62
71
|
export async function loadConfig(): Promise<NesConfig> {
|
|
63
72
|
const configPath = getConfigPath();
|
|
73
|
+
let config: NesConfig;
|
|
64
74
|
try {
|
|
65
75
|
const raw = await fs.readFile(configPath, "utf8");
|
|
66
|
-
|
|
76
|
+
config = normalizeConfig(JSON.parse(raw));
|
|
67
77
|
} catch {
|
|
68
|
-
|
|
78
|
+
config = DEFAULT_CONFIG;
|
|
69
79
|
}
|
|
80
|
+
await ensureDirectory(config.saveDir);
|
|
81
|
+
return config;
|
|
70
82
|
}
|
|
71
83
|
|
|
72
84
|
export async function configExists(): Promise<boolean> {
|
|
@@ -84,6 +96,14 @@ export async function saveConfig(config: NesConfig): Promise<void> {
|
|
|
84
96
|
await fs.writeFile(configPath, formatConfig(config));
|
|
85
97
|
}
|
|
86
98
|
|
|
99
|
+
async function ensureDirectory(dirPath: string): Promise<void> {
|
|
100
|
+
try {
|
|
101
|
+
await fs.mkdir(dirPath, { recursive: true });
|
|
102
|
+
} catch {
|
|
103
|
+
// ignore
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
87
107
|
function normalizePixelScale(raw: unknown): number {
|
|
88
108
|
if (typeof raw !== "number" || Number.isNaN(raw)) {
|
|
89
109
|
return DEFAULT_CONFIG.pixelScale;
|
|
@@ -124,8 +124,6 @@ dependencies = [
|
|
|
124
124
|
[[package]]
|
|
125
125
|
name = "nes_rust"
|
|
126
126
|
version = "0.1.2"
|
|
127
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
128
|
-
checksum = "0ee42b041b46e53bf4e4705ca0ffe66cbc7789929c3d013fa0700d7d61cf45c6"
|
|
129
127
|
|
|
130
128
|
[[package]]
|
|
131
129
|
name = "once_cell"
|
|
@@ -9,6 +9,11 @@ export class NativeNes {
|
|
|
9
9
|
reset(): void;
|
|
10
10
|
pressButton(button: number): void;
|
|
11
11
|
releaseButton(button: number): void;
|
|
12
|
+
hasBatteryBackedRam(): boolean;
|
|
13
|
+
getSram(): Uint8Array;
|
|
14
|
+
setSram(data: Uint8Array): void;
|
|
15
|
+
isSramDirty(): boolean;
|
|
16
|
+
markSramSaved(): void;
|
|
12
17
|
getFramebuffer(): Uint8Array;
|
|
13
18
|
}
|
|
14
19
|
|
|
Binary file
|
|
@@ -13,5 +13,10 @@ export declare class NativeNes {
|
|
|
13
13
|
reset(): void
|
|
14
14
|
pressButton(button: number): void
|
|
15
15
|
releaseButton(button: number): void
|
|
16
|
+
hasBatteryBackedRam(): boolean
|
|
17
|
+
getSram(): Uint8Array
|
|
18
|
+
setSram(data: Uint8Array): void
|
|
19
|
+
isSramDirty(): boolean
|
|
20
|
+
markSramSaved(): void
|
|
16
21
|
getFramebuffer(): Uint8Array
|
|
17
22
|
}
|
|
@@ -108,6 +108,31 @@ impl NativeNes {
|
|
|
108
108
|
}
|
|
109
109
|
}
|
|
110
110
|
|
|
111
|
+
#[napi]
|
|
112
|
+
pub fn has_battery_backed_ram(&self) -> bool {
|
|
113
|
+
self.nes.has_battery_backed_ram()
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
#[napi]
|
|
117
|
+
pub fn get_sram(&self) -> Uint8Array {
|
|
118
|
+
Uint8Array::from(self.nes.get_sram())
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
#[napi]
|
|
122
|
+
pub fn set_sram(&mut self, data: Uint8Array) {
|
|
123
|
+
self.nes.set_sram(data.to_vec());
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
#[napi]
|
|
127
|
+
pub fn is_sram_dirty(&self) -> bool {
|
|
128
|
+
self.nes.is_sram_dirty()
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
#[napi]
|
|
132
|
+
pub fn mark_sram_saved(&mut self) {
|
|
133
|
+
self.nes.mark_sram_saved();
|
|
134
|
+
}
|
|
135
|
+
|
|
111
136
|
#[napi]
|
|
112
137
|
pub fn get_framebuffer(&mut self) -> Uint8Array {
|
|
113
138
|
let ptr = self.framebuffer.as_mut_ptr();
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"v":1}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
|
|
2
|
+
#
|
|
3
|
+
# When uploading crates to the registry Cargo will automatically
|
|
4
|
+
# "normalize" Cargo.toml files for maximal compatibility
|
|
5
|
+
# with all versions of Cargo and also rewrite `path` dependencies
|
|
6
|
+
# to registry (e.g., crates.io) dependencies
|
|
7
|
+
#
|
|
8
|
+
# If you believe there's an error in this file please file an
|
|
9
|
+
# issue against the rust-lang/cargo repository. If you're
|
|
10
|
+
# editing this file be aware that the upstream Cargo.toml
|
|
11
|
+
# will likely look very different (and much more reasonable)
|
|
12
|
+
|
|
13
|
+
[package]
|
|
14
|
+
name = "nes_rust"
|
|
15
|
+
version = "0.1.2"
|
|
16
|
+
authors = ["Takahiro <hogehoge@gachapin.jp>"]
|
|
17
|
+
exclude = ["resources/*", "screenshots/*", "roms/*", "cli/*", "wasm/*"]
|
|
18
|
+
description = "NES emulator written in Rust"
|
|
19
|
+
homepage = "https://github.com/takahirox/nes-rust"
|
|
20
|
+
license = "MIT"
|
|
21
|
+
repository = "https://github.com/takahirox/nes-rust"
|
|
22
|
+
[badges.travis-ci]
|
|
23
|
+
repository = "takahirox/nes-rust"
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2018 Takahiro
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# nes-rust
|
|
2
|
+
|
|
3
|
+
[](https://travis-ci.com/takahirox/nes-rust)
|
|
4
|
+
[](https://crates.io/crates/nes_rust)
|
|
5
|
+
[](https://badge.fury.io/js/nes_rust_wasm)
|
|
6
|
+
|
|
7
|
+
nes-rust is a NES emulator written in Rust. It can be compiled to WebAssembly.
|
|
8
|
+
|
|
9
|
+
## Online Demos / Videos
|
|
10
|
+
|
|
11
|
+
- [Online Singleplay Demo](https://takahirox.github.io/nes-rust/wasm/web/index.html)
|
|
12
|
+
- [Online Multiplay Demo](https://takahirox.github.io/nes-rust/wasm/web/multiplay.html) / [Video](https://twitter.com/superhoge/status/1205427421010247680)
|
|
13
|
+
- [Online VR Multiplay Demo](https://takahirox.github.io/nes-rust/wasm/web/vr.html) / [Video](https://twitter.com/superhoge/status/1209685614074875906)
|
|
14
|
+
|
|
15
|
+
## Screenshots
|
|
16
|
+
|
|
17
|
+
[nestest](http://wiki.nesdev.com/w/index.php/Emulator_tests)
|
|
18
|
+
|
|
19
|
+

|
|
20
|
+
|
|
21
|
+
[Sgt. Helmet Training Day](http://www.mojontwins.com/juegos_mojonos/sgt-helmet-training-day-nes/)
|
|
22
|
+
|
|
23
|
+

|
|
24
|
+
|
|
25
|
+
## Features
|
|
26
|
+
|
|
27
|
+
- Audio support with SDL2 / WebAudio
|
|
28
|
+
- WebAssembly support
|
|
29
|
+
- Remote multiplay support with WebRTC
|
|
30
|
+
|
|
31
|
+
## How to import into your Rust project
|
|
32
|
+
|
|
33
|
+
The emulator module and document are released at [crates.io](https://crates.io/crates/nes_rust).
|
|
34
|
+
|
|
35
|
+
## How to build core library locally
|
|
36
|
+
|
|
37
|
+
```
|
|
38
|
+
$ git clone https://github.com/takahirox/nes-rust.git
|
|
39
|
+
$ cd nes-rust
|
|
40
|
+
$ cargo build --release
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## How to run as desktop application
|
|
44
|
+
|
|
45
|
+
Prerequirements
|
|
46
|
+
- Install [Rust-SDL2](https://github.com/Rust-SDL2/rust-sdl2#rust)
|
|
47
|
+
|
|
48
|
+
```
|
|
49
|
+
$ cd nes-rust/cli
|
|
50
|
+
$ cargo run --release path_to_rom_file
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## How to import and use WebAssembly NES emulator in a web browser
|
|
54
|
+
|
|
55
|
+
See [wasm/web](https://github.com/takahirox/nes-rust/tree/master/wasm/web)
|
|
56
|
+
|
|
57
|
+
## How to install and use WebAssembly NES emulator npm package
|
|
58
|
+
|
|
59
|
+
See [wasm/npm](https://github.com/takahirox/nes-rust/tree/master/wasm/npm)
|