我的红白机模拟器
我又来了,致力于把计算机底层“玩”明白系列又添一笔。实现一个红白机模拟器,跑跑童年的回忆——超级玛丽。
起因是这样的:偶然刷知乎,看到一个问答GitHub 或者其他的开源平台中是否有一些适合初学者的 C++ 项目?,底下有答主[1]推荐Github上的一个项目SimpleNES。我一细看,这不是实践计算机组成原理的最佳项目吗?
这是用软件实现一个指令集级别的CPU模拟器、PPU(图形处理单元)模拟器、计算机体系结构中的总线、内存分配的项目,做完这个项目可以理解整个硬件系统是如何工作的。
此外,红白机模拟器还很有趣,你成功实现它之后就可以愉快地在自己的 PC 玩超级玛丽了。你可以在享受自己学习到新知识和带着满满地成就感愉快地“浪费“一下午在玩游戏上。效果如下图:
这个项目并不难,会 C++ 更好,只会 C 的话也可以用 C with Class来实现,在调用C++的基本STL就可(不要问我怎么知道的~)。
这个项目的代码很少,20几个文件,条理清晰,每个文件就百行代码,粗粗看一遍也就小半天。而且每个模块的独立性强,可以有选择的深入研究。这个项目使用到的有C++11的基本语法和STL库,非常适合刚读完教材的初学者阅读。[1]
如果你还担心自己不会,没关系。我为了自己更加理解,我从初学者的角度自己简化并实现了一遍SimpleNES。我只保留了运行超级玛丽游戏的最关键的代码(代码量更少),并将SimpleNES分割成一个个小块,每天实现一个功能,每个功能都是可以单独验证的(功能划分更明确)。如下:
- Day1:模拟CPU6502、总线和内存RAM,实现CPU可从内存中读写数据和取指令
- Day2:参考6502 CPU 的datasheet,实现了CPU对指令的解码执行
- Day3:解析卡带(Cartidge 游戏卡)的文件格式,编写简单的.nes程序(加法运算),测试 CPU 能否正常执行程序。
- Day4:实现 Mapper,预留给游戏卡的地址空间是有限的,游戏卡的程序内存(Program Memory)被限制在 32 KB,角色内存(Character Memory)被限制在 8 KB。为了突破这种限制,人们发明了内存映射器(Mapper)。 内存映射器是游戏卡中的一个硬件,具有存储体空间切换(Bank Switching)的功能,以将新的程序或角色内存引入到可寻址的内存空间。
- Day5:多媒体库(SFML 简单快速多媒体库)的配置和使用,并构建PPU总线(Picture Bus)以及虚拟屏幕(Virtual Screen)的实现
- Day6: 实现 PPU 的各个回调函数,显示游戏画面
- Day7:增加按键控制,愉快游戏!
我的实现开源在 Github 上了,我称它为 MyNES 。你可以通过选择不同的 git 分支查看每个功能实现的迭代,还担心自己不知道从何入手吗?
PS:因为设计到具体的CPU(6502),同时对计组不太熟悉的同学,可以观看红白机模拟器实现的相关视频,B站和油管上都有(推荐油管的英文视频)。
zmzty
有意思。有个网站专门怀旧。https://www.yikm.net/