使用 C 和 Allegro 实现的 NES 模拟器

in cn •  6 years ago  (edited)

NES (Nintendo Entertainment System, Wikipedia) 是历史上一款著名的游戏机,由任天堂于 1983 年推出,又被称做 FC (Family Computer) 或红白机。在国内,或许大家对「小霸王学习机」这个名字更加熟悉,应该有不少人就是在这台学习机上第一次接触了电子游戏。其实,「小霸王学习机」就是 NES 的山寨版,兼容 NES 游戏,在硬件上与 NES 基本相同。

即使对游戏不感兴趣的人,听到「超级马里奥」(超级玛丽)等,也应该不会陌生。而这些游戏角色,正是由于 NES 的普及,才变得更加知名。

在 NES 推出的时候,计算机多媒体技术并不是十分发达。而且不论是 NES,还是当时流行的 Apple II,其内存只有几 KB 到几百 KB. 为了能够流畅地显示游戏画面、播放游戏声音,NES 采用了不少巧妙的技术。

(html comment removed: more)

我的 NES 模拟器

由于 NES 已经是上个世纪的硬件,目前已经存在许多 NES 模拟器,可以运行在电脑、手机、游戏机甚至 STM32 之类的单片机上。而我只做这一 NES 模拟器,只是是为了让自己能够更加清晰地理解计算机底层的工作原理(-顺便做为毕设的一部分-)。如果需要在自己的程序中使用 NES 模拟器,建议参考更加成熟的项目。

目前,该模拟器具有下列功能:

  1. 运行基本的 NES 程序
  2. 使用 Allegro 显示游戏画面
  3. 反汇编
  4. 显示 NES ROM 的相关信息
  5. 在模拟器运行的过程中,显示 CPU 和 PPU 寄存器上的数值

一些较为复杂的游戏,在其卡带中,除了 ROM 和 RAM 之外,还内置有内存控制器等芯片,或者使用了未在 NES CPU (6502) 文档中公开的特殊指令。这些游戏在本模拟器中无法运行。

模拟器的源代码、使用方法、编译方法已经放在 GitHub: https://github.com/blanboom/bEMU

资料整理

这个模拟器中的代码并非全部由本人编写,而是参考了 LiteNES, nesemu2, mwillsey’s NES 等项目。在此对作者表示感谢。

另外,在完成这一模拟器中,发现了许多有用的资料和链接。现在整理在此处,希望能够对更多对 NES 感兴趣的人带来帮助。

调试与优化

NES 测试程序

完成 NES 模拟器后,需要对 CPU 的各个指令、PPU 的各项功能进行测试,确定模拟器是否运行正常。这时候,通过测试程序,能够更方便地完成这些功能。

在调试模拟器的过程中,我使用了 NEStress 和 nestest 两个测试程序。其中,NEStress 可以对 CPU、PPU、APU、IO 等进行测试,而 nestest 仅仅用于对 CPU 的测试,但比 NEStress 覆盖更多的指令。

这些测试程序的下载地址可从这里找到:http://wiki.nesdev.com/w/index.php/Emulator_tests

通过 SIGINFO 显示调试信息

在本模拟器中,还增加了显示 CPU、PPU 状态信息的功能。模拟器运行过程中,可通过 Ctrl+T,发送 SIGINFO,随时查看相关信息。

相关程序如下:

static void sig_info() {
    /* 显示时间 */
    static time_t timer;
    static struct tm * timeinfo;
    time(&timer);
    timeinfo = localtime(&timer);
    printf("%s\n", asctime(timeinfo));
 
    cpu_debugger();
    ppu_debugger();
    printf("--------------------------------------------\n\n");
 }

CPU 模拟器的优化技巧

这篇文章介绍了作者在对 6502 模拟器的一些优化技巧,可供参考:http://www.slack.net/~ant/nes-emu/6502.html

其他想法

关于这个模拟器的更多打算。如果以后有时间,可能会考虑将其实现。

多线程

将 CPU 与 PPU 通过两个线程实现,两者并行执行,有可能能提高效率。不过需要面临两者之间的同步问题。

通过 FPGA 制作「片上 NES」

通过 FPGA,以硬件的方式实现 CPU 和 PPU,加深对 CPU 硬件结构的理解。

扩展至 32 位

尝试将 CPU 扩展至 32 位,扩充指令集,并兼容 6502 原有的指令集。

移植到 3DS

将模拟器移植到 3DS 上。

Authors get paid when people like you upvote their post.
If you enjoyed what you read here, create your account today and start earning FREE STEEM!