# Nesium
[![Rust](https://github.com/mikai233/nesium/actions/workflows/rust.yml/badge.svg)](https://github.com/mikai233/nesium/actions/workflows/rust.yml) [![Flutter](https://github.com/mikai233/nesium/actions/workflows/flutter.yml/badge.svg)](https://github.com/mikai233/nesium/actions/workflows/flutter.yml) [![Web Demo](https://img.shields.io/website?label=play%20online&url=https%3A%2F%2Fmikai233.github.io%2Fnesium%2F)](https://mikai233.github.io/nesium/) [![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)](LICENSE.md)

Rust Flutter Wasm

[**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` 构建的轻量级桌面前端。它占用资源少,提供**快速调试和开发**所需的基本功能。 - ![](https://img.shields.io/badge/Windows-x86_64/arm64-blue?logo=windows) ![](https://img.shields.io/badge/macOS-Universal-black?logo=apple) ![](https://img.shields.io/badge/Linux-x86_64/arm64-orange?logo=linux) - **`nesium-flutter`** (`apps/nesium_flutter`) — 一个基于 **Flutter** 构建的现代化前端。相比 `egui` 应用,它旨在提供更精美的 UI 和更广泛的跨平台支持。 - ![](https://img.shields.io/badge/Windows-x86_64-blue?logo=windows) ![](https://img.shields.io/badge/macOS-Universal-black?logo=apple) ![](https://img.shields.io/badge/Linux-x86_64/arm64-orange?logo=linux) ![](https://img.shields.io/badge/Android-Multi--arch-green?logo=android) ![](https://img.shields.io/badge/iOS-Supported-lightgrey?logo=apple) - **Web 版本 (在线试玩)** — https://mikai233.github.io/nesium/ (通过高性能 **Flutter WASM (dart2wasm)** + Web Worker + Rust WASM 在浏览器中运行)。 - ![](https://img.shields.io/badge/Web-WasmGC-purple?logo=webassembly) (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 生态系统集成。