[](https://github.com/mikai233/nesium/actions/workflows/rust.yml)
[](https://github.com/mikai233/nesium/actions/workflows/flutter.yml)
[](https://mikai233.github.io/nesium/)
[](LICENSE.md)
[**English**](./README.md)
这是一个用 Rust 编写的周期精确 (cycle-accurate) NES 模拟器,旨在忠实还原任天堂娱乐系统 (NES) 的硬件行为。本项目致力于精确模拟 CPU、PPU、APU 等关键组件,确保每款游戏都能像在原始硬件上一样运行。
本模拟器的设计和实现深受优秀的 [Mesen2](https://github.com/SourMesen/Mesen2) 项目启发。Mesen2 的文档、代码结构以及许多实现思路(特别是在时序、Open-bus 行为和音频混合方面)都极具参考价值。非常感谢 Mesen2 的作者和贡献者们开发并开源了如此高质量的模拟器。
## 关键特性
- **周期精确模拟**:每一个时钟周期都经过精确模拟,以确保准确的游戏行为。
- **CPU (6502) 模拟**:完整模拟 6502 处理器,支持所有指令。
- **PPU 模拟**:精确的图形渲染,支持调色板、精灵和背景层。
- **APU 模拟**:重现声音处理,支持 NES 各个声道。
- **兼容性**:支持多种 NES 游戏,并持续改进兼容性和性能。
## UI 前端
本仓库目前提供 **两个** 前端实现:
- **`nesium-egui`** (`apps/nesium-egui`) — 一个基于 `egui` 构建的轻量级桌面前端。它占用资源少,提供**快速调试和开发**所需的基本功能。
-   
- **`nesium-flutter`** (`apps/nesium_flutter`) — 一个基于 **Flutter** 构建的现代化前端。相比 `egui` 应用,它旨在提供更精美的 UI 和更广泛的跨平台支持。
-     
- **Web 版本 (在线试玩)** — https://mikai233.github.io/nesium/ (通过高性能 **Flutter WASM (dart2wasm)** + Web Worker + Rust WASM 在浏览器中运行)。
-  (Chrome/Edge 119+, Firefox 120+)
## 当前状态
- 处于活跃开发阶段,持续改进准确性、性能和兼容性。
- 仍处于早期阶段,但几个关键组件已经可以使用。
## 路线图
Nesium 的长期愿景专注于精确度、工具链和可扩展性:
- [ ] **精确的 NES 模拟**:
实现 CPU、PPU 和 APU 组件的周期级精确度。目标是通过所有标准合规性测试套件(包括 `blargg` 测试和 `nes-test-roms` 中的棘手边缘情况),并正确支持“无授权”或依赖硬件缺陷的游戏。
- [ ] **高级调试套件**:
在前端实现一个全面的调试器。计划的功能包括:
- 实时反汇编和单步执行。
- 内存检查/编辑(RAM, VRAM, OAM)。
- 命名表(Nametable)、图案表(Pattern Table)和调色板查看器。
- 断点管理(执行、读/写、IRQ)。
- [ ] **Lua 脚本集成**:
嵌入 Lua 运行时以支持强大的自动化和分析功能。这将支持:
- 工具辅助竞速(TAS)工作流。
- 用于训练或直播的自定义 HUD 和覆盖层。
- 自动化回归测试脚本。
- [ ] **联机游戏 (Netplay)**:
实现互联网两名玩家的网络多人游戏支持。
## Mapper 支持
### Plane 0 (iNES 1.0 mappers 0-255)
| Row | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F |
|---------|------|------|------|------|------|------|------|------|------|------|------|------|-----|------|------|-----|
| 000-015 | ☑000 | ☑001 | ☑002 | ☑003 | ☑004 | ☑005 | ☑006 | ☑007 | ☑008 | ☑009 | ☑010 | ☑011 | 012 | ☑013 | 014 | 015 |
| 016-031 | 016 | 017 | 018 | ☑019 | 020 | ☑021 | 022 | ☑023 | 024 | ☑025 | ☑026 | 027 | 028 | 029 | 030 | 031 |
| 032-047 | 032 | 033 | ☑034 | 035 | 036 | 037 | 038 | 039 | 040 | 041 | 042 | 043 | 044 | 045 | 046 | 047 |
| 048-063 | 048 | 049 | 050 | 051 | 052 | 053 | 054 | 055 | 056 | 057 | 058 | 059 | 060 | 061 | 062 | 063 |
| 064-079 | 064 | 065 | ☑066 | 067 | 068 | ☑069 | 070 | ☑071 | 072 | 073 | 074 | 075 | 076 | 077 | ☑078 | 079 |
| 080-095 | 080 | 081 | 082 | 083 | 084 | ☑085 | 086 | 087 | 088 | 089 | ☑090 | 091 | 092 | 093 | 094 | 095 |
| 096-111 | 096 | 097 | 098 | 099 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 |
| 112-127 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | ☑119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 |
| 128-143 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 |
| 144-159 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 |
| 160-175 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 |
| 176-191 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 |
| 192-207 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 |
| 208-223 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 |
| 224-239 | 224 | 225 | 226 | 227 | ☑228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 |
| 240-255 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 |
### Plane 1 (NES 2.0 mappers 256-511)
| Row | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F |
|---------|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|
| 256-271 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 |
| 272-287 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 |
| 288-303 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 |
| 304-319 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 |
| 320-335 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 |
| 336-351 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 |
| 352-367 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 |
| 368-383 | 368 | 369 | 370 | 371 | 372 | 373 | 374 | 375 | 376 | 377 | 378 | 379 | 380 | 381 | 382 | 383 |
| 384-399 | 384 | 385 | 386 | 387 | 388 | 389 | 390 | 391 | 392 | 393 | 394 | 395 | 396 | 397 | 398 | 399 |
| 400-415 | 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 |
| 416-431 | 416 | 417 | 418 | 419 | 420 | 421 | 422 | 423 | 424 | 425 | 426 | 427 | 428 | 429 | 430 | 431 |
| 432-447 | 432 | 433 | 434 | 435 | 436 | 437 | 438 | 439 | 440 | 441 | 442 | 443 | 444 | 445 | 446 | 447 |
| 448-463 | 448 | 449 | 450 | 451 | 452 | 453 | 454 | 455 | 456 | 457 | 458 | 459 | 460 | 461 | 462 | 463 |
| 464-479 | 464 | 465 | 466 | 467 | 468 | 469 | 470 | 471 | 472 | 473 | 474 | 475 | 476 | 477 | 478 | 479 |
| 480-495 | 480 | 481 | 482 | 483 | 484 | 485 | 486 | 487 | 488 | 489 | 490 | 491 | 492 | 493 | 494 | 495 |
| 496-511 | 496 | 497 | 498 | 499 | 500 | 501 | 502 | 503 | 504 | 505 | 506 | 507 | 508 | 509 | 510 | 511 |
### Plane 2 (NES 2.0 mappers 512-767)
| Row | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F |
|---------|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|
| 512-527 | 512 | 513 | 514 | 515 | 516 | 517 | 518 | 519 | 520 | 521 | 522 | 523 | 524 | 525 | 526 | 527 |
| 528-543 | 528 | 529 | 530 | 531 | 532 | 533 | 534 | 535 | 536 | 537 | 538 | 539 | 540 | 541 | 542 | 543 |
| 544-559 | 544 | 545 | 546 | 547 | 548 | 549 | 550 | 551 | 552 | 553 | 554 | 555 | 556 | 557 | 558 | 559 |
| 560-575 | 560 | 561 | 562 | 563 | 564 | 565 | 566 | 567 | 568 | 569 | 570 | 571 | 572 | 573 | 574 | 575 |
| 576-591 | 576 | 577 | 578 | 579 | 580 | 581 | 582 | 583 | 584 | 585 | 586 | 587 | 588 | 589 | 590 | 591 |
| 592-607 | 592 | 593 | 594 | 595 | 596 | 597 | 598 | 599 | 600 | 601 | 602 | 603 | 604 | 605 | 606 | 607 |
| 608-623 | 608 | 609 | 610 | 611 | 612 | 613 | 614 | 615 | 616 | 617 | 618 | 619 | 620 | 621 | 622 | 623 |
| 624-639 | 624 | 625 | 626 | 627 | 628 | 629 | 630 | 631 | 632 | 633 | 634 | 635 | 636 | 637 | 638 | 639 |
| 640-655 | 640 | 641 | 642 | 643 | 644 | 645 | 646 | 647 | 648 | 649 | 650 | 651 | 652 | 653 | 654 | 655 |
| 656-671 | 656 | 657 | 658 | 659 | 660 | 661 | 662 | 663 | 664 | 665 | 666 | 667 | 668 | 669 | 670 | 671 |
| 672-687 | 672 | 673 | 674 | 675 | 676 | 677 | 678 | 679 | 680 | 681 | 682 | 683 | 684 | 685 | 686 | 687 |
| 688-703 | 688 | 689 | 690 | 691 | 692 | 693 | 694 | 695 | 696 | 697 | 698 | 699 | 700 | 701 | 702 | 703 |
| 704-719 | 704 | 705 | 706 | 707 | 708 | 709 | 710 | 711 | 712 | 713 | 714 | 715 | 716 | 717 | 718 | 719 |
| 720-735 | 720 | 721 | 722 | 723 | 724 | 725 | 726 | 727 | 728 | 729 | 730 | 731 | 732 | 733 | 734 | 735 |
| 736-751 | 736 | 737 | 738 | 739 | 740 | 741 | 742 | 743 | 744 | 745 | 746 | 747 | 748 | 749 | 750 | 751 |
| 752-767 | 752 | 753 | 754 | 755 | 756 | 757 | 758 | 759 | 760 | 761 | 762 | 763 | 764 | 765 | 766 | 767 |
### Mapper 支持详情 / 已知问题
- **MMC5 (mapper 5)**: ExRAM 作为 nametable 的模式和扩展属性/填充特性尚未实现;扩展音频未实现。
- **J.Y. Company 90**: 已在抽样 mapper 90 商业 ROM 上验证音视频对齐;较少见的高级 nametable 边缘行为仍缺少专项覆盖。
- **TQROM (mapper 119)**: 围绕 CHR ROM/RAM 位切换的边缘情况仍需验证。
- **Action 52 / Cheetahmen II (mapper 228)**: Mapper RAM 窗口行为实现非常基础;需针对所有卡带进行验证。
- **通用**: 针对某些离散板(如部分 UNROM/CNROM 变体)的总线冲突处理尚未完全建模。
## 测试 ROM 状态
Nesium 集成了大量的 NES 测试 ROM 套件(通过 `rom_suites.rs`)来验证 CPU、PPU、APU 和 Mapper 的行为。下表总结了目前自动通过的套件、需交互/手动测试的套件,以及目前标记为失败/忽略仍需工作的套件。
图例:
- ✅: 启用的自动化测试(无 `#[ignore]`)且当前通过
- ❌: 标记为 `#[ignore = "this test fails and needs investigation"]` 的测试
- 🔶: 交互式/手动 ROM(例如控制器/视觉测试)
- ℹ️: 出于基线跟踪/诊断目的保留 `#[ignore]` 的测试
### 自动通过的 ROM 套件 (✅)
| 套件名称 | 说明 | TASVideos 精度要求 |
|--------------------------------------|---------------------------------------------|----------------|
| `_240pee_suite` | TV 颜色多样性 / 时序测试 | 否 |
| `mmc1_a12_suite` | MMC1 A12 线行为 | 否 |
| `apu_mixer_suite` | APU 混音器 / TASVideos 测试集 | 是 |
| `apu_reset_suite` | APU 复位行为 | 是 |
| `apu_test_suite` | APU 精度测试(包括 `rom_singles`) | 是 |
| `blargg_apu_2005_07_30_suite` | 早期 Blargg APU 测试 | 是 |
| `blargg_nes_cpu_test5_suite` | CPU 精度测试 | 是 |
| `blargg_ppu_tests_2005_09_15b_suite` | PPU 调色板/显存/滚动行为 | 是 |
| `branch_timing_tests_suite` | 分支指令时序(零页结果) | 是 |
| `cpu_dummy_reads_suite` | CPU 伪读行为 | 是 |
| `cpu_dummy_writes_suite` | CPU 伪写行为 | 是 |
| `cpu_exec_space_suite` | CPU 执行空间测试 (APU/PPU I/O) | 是 |
| `cpu_interrupts_v2_suite` | NMI/IRQ/BRK/DMA 中断时序 | 是 |
| `cpu_reset_suite` | 复位后 RAM/寄存器状态 | 是 |
| `cpu_timing_test6_suite` | TASVideos CPU 时序 (TV SHA1) | 是 |
| `dmc_dma_during_read4_suite` | DMC DMA 与 CPU 读取周期的交互 | 是 |
| `dmc_tests_suite` | DMC 缓冲/延迟/IRQ 行为 | 是 |
| `full_palette_suite` | 全调色板渲染与 Emphasis 测试(Mesen2 RGB24 基线) | 否 |
| `scanline_suite` | 扫描线时序(Mesen2 RGB24 多帧基线) | 是 |
| `scanline_a1_suite` | 替代扫描线时序(Mesen2 RGB24 多帧基线) | 是 |
| `instr_misc_suite` | 杂项指令行为 | 是 |
| `instr_test_v3_suite` | Blargg 指令测试 v3 | 是 |
| `instr_test_v5_suite` | Blargg 指令测试 v5 | 是 |
| `instr_timing_suite` | 指令时序 | 是 |
| `mmc3_irq_tests_suite` | MMC3 IRQ 测试集(必测项通过 + revision 变体至少通过一个) | 是 |
| `mmc3_test_suite` | MMC3 功能测试集(必测项通过 + MMC3/MMC6 变体至少通过一个) | 是 |
| `mmc3_test_2_suite` | MMC3 第二组测试集(必测项通过 + MMC3/MMC3_alt 变体至少通过一个) | 是 |
| `nes_instr_test_suite` | 额外指令行为测试 | 是 |
| `ny2011_suite` | 视觉多样性 / 时序 | 否 |
| `oam_read_suite` | OAM 读取行为 | 是 |
| `oam_stress_suite` | OAM 压力 / 溢出条件 | 是 |
| `ppu_open_bus_suite` | PPU open-bus 行为 | 是 |
| `ppu_read_buffer_suite` | PPU 读取缓冲行为 | 是 |
| `ppu_vbl_nmi_suite` | PPU VBL/NMI 时序 | 是 |
| `sprite_hit_tests_2005_10_05_suite` | 精灵 0 命中时序和边缘情况 | 是 |
| `sprite_overflow_tests_suite` | 精灵溢出行为 | 是 |
| `spritecans_2011_suite` | 视觉多样性 / 精灵压力 | 否 |
| `sprdma_and_dmc_dma_suite` | Sprite DMA 和 DMC DMA 交互 | 是 |
| `stomper_suite` | 视觉多样性 / 时序 | 否 |
| `tutor_suite` | 视觉多样性 / 参考演示 | 否 |
| `vbl_nmi_timing_suite` | VBL/NMI 时序(零页结果) | 是 |
| `window5_suite` | 颜色窗口测试 (NTSC/PAL) | 否 |
### 交互式 / 手动 ROM (🔶)
这些 ROM 设计用于交互式/手动验证,并未暴露简单的 $6000 状态字节或 TV 哈希协议。它们被连接到测试工具中,但保持 `#[ignore]` 状态,应手动检查。
| 套件名称 | 说明 | TASVideos 精度要求 |
|-----------------------|---------------------------------------------------|----------------|
| `dpcmletterbox_suite` | 可视化 DPCM 演示 ROM;按 `dpcmletterbox/README.txt` 手动验证 | 是 |
| `nmi_sync_manual` | 可视化 NMI 同步演示 ROM;按 `nmi_sync/readme.txt` 手动验证 | 是 |
| `paddletest3_manual` | 旋钮/模拟控制器测试;遵循 ROM `Info.txt` 指示 | 否 |
| `tvpassfail_manual` | TV 特性(NTSC 色度/亮度,伪影);视觉验证 | 否 |
| `vaus_test_manual` | Arkanoid Vaus 控制器测试(交互式) | 否 |
### 失败 / 忽略的 ROM 套件 (❌)
以下套件目前标记为 `#[ignore = "this test fails and needs investigation"]`。这突出了 Nesium 的行为仍与参考模拟器和硬件有偏差的地方。
| 套件名称 | 说明 | TASVideos 精度要求 |
|---------------------------|--------------------------|----------------|
| `blargg_litewall_suite` | Litewall / 时序相关测试 | 否 |
| `exram_suite` | MMC5 ExRAM 行为(当前失败) | 否 |
| `m22chrbankingtest_suite` | Mapper 22 CHR banking 行为 | 否 |
| `mmc5test_suite` | MMC5 功能测试 | 是 |
| `mmc5test_v2_suite` | MMC5 测试集 v2 | 是 |
| `nes15_1_0_0_suite` | `nes15` 系列测试 (NTSC/PAL) | 是 |
| `nrom368_suite` | NROM-368 映射测试 | 否 |
| `other_suite` | nes-test-roms 绑定的杂项演示/测试 | 否 |
| `pal_apu_tests_suite` | PAL APU 行为 | 是 |
| `read_joy3_suite` | 控制器读取时序 | 是 |
| `scrolltest_suite` | 滚动行为 | 是 |
| `volume_tests_suite` | 音量/混音行为 | 是 |
### 跟踪 / 诊断类测试 (ℹ️)
以下套件用于和参考输出做基线跟踪,本身不应直接视为“功能失败”。
| 套件名称 | 说明 | TASVideos 精度要求 |
|--------------------------------|-------------------------------------|----------------|
| `nmi_sync_ntsc_mesen_baseline` | 与 Mesen2 输出进行 NTSC 帧哈希基线跟踪(默认测试已启用) | 是 |
## 免责声明
本项目是一个由粉丝制作的非商业模拟器,旨在用于教育和保存目的。本项目与任天堂或其他权利方无关,亦未获得其认可或赞助。您需自行承担遵守当地法律的责任,并确保您在此模拟器中使用的任何 ROM 或其他受版权保护的内容均是通过合法途径获得和使用的(例如,来自您个人拥有的卡带)。
## 贡献
欢迎 Fork 本项目,提交 Issue 和 Pull Request。我们欢迎任何有助于提高模拟器准确性和扩展功能集的贡献。
## 许可证
Nesium 基于 GNU 通用公共许可证第 3 版或(由您选择)任何更高版本 (GPL-3.0-or-later) 发布。有关全文,请参阅 `LICENSE.md`。
本项目还包含 Shay Green 的 `blip_buf` 库(通过 `nesium-blip` crate 使用),该库根据 GNU 宽通用公共许可证 v2.1 授权。相关的许可证文本包含在 `crates/nesium-blip/csrc/license.md` 中的导入源码旁边。
## Libretro 绑定
本工作区包含 `libretro-bridge` crate,它通过 `bindgen` 自动为上游 `libretro.h`头文件生成 Rust 绑定。构建脚本会在编译时获取最新的头文件(对于离线构建有内置的回退),以便 Nesium——以及任何其他 Rust 项目——可以在 API 变更在上游发布后立即与 Libretro 生态系统集成。