用 Go 撸了一个 NES/FC/红白机模拟器——GoNES

2019-05-28 15:05:33 +08:00
 raysonx

上个月在 V 站看到有同学发布了一个 Rust 写的 Gameboy 模拟器。当时我恰好在系统化学习 Go 语言,作为马里奥 /马力欧 /玛丽(误)的忠实粉丝,就想着自己能不能用 Go 写个模拟器玩玩。于是我瞄准了 NES 模拟器,考虑到 NES 是上个世纪 80 年代的古董硬件,可能比较容易实现。

接下来我开始在网上搜索关于 NES 硬件的信息。忽然有一个神奇的网站出现在我眼前,它就是 nesdev.com 。这个网站有一个Wiki,里面的内容包罗万象,有 NES 的硬件细节,也有 NES 游戏开发的教程。对照着文档,大概用了一天的时间完成了 INES ROM 文件(网上下到的.nes 文件都是这种格式)的读取,然后用了不到一周的业余时间就基本实现了 NES CPU ( 6502 )指令解释器。NES 的 PPU (类似显卡)是难点,大概陆陆续续写个几个星期才完成基本功能。主要因为 NES 的硬件太弱,很多游戏为了压榨机能在开发过程中用了大量的 hack,如果对 PPU 的模拟必须不够精确,游戏运行时就会出现各种奇怪的现象。用的 GUI 库是 fyne.io ,在部分操作系统上会内存泄漏,打算之后换个其他的库试试( Go 语言目前好像没有成熟的 GUI 库)。另外 APU (类似声卡)的模拟还没有实现(主要我对声学一窍不通,也暂时不想随便引用个第三方库解决,就先拖着了)。

另外一个难点是卡带的模拟。NES 原生只有 2kB 内存+2kB 显存,为了拓展内存和显存的容量,很多游戏的卡带带有一个俗称 Mapper 的芯片。配合卡带上额外的 ROM 或 RAM 芯片,Mapper 可以将卡带上 ROM 或 RAM 的一部分空间(称为 bank )映射进 NES 的内存或显存地址空间,还可以在游戏运行中动态切换。麻烦的是,不同的游戏使用的 Mapper 芯片是不同的,你必须先实现了对某种 Mapper 的模拟,才能运行使用这种 Mapper 的游戏 ROM,然而已知的 Mapper 种类就有几百种。目前我的模拟器只实现了 INES 文件格式定义的 0-3 号 Mapper,但已经可以运行不少游戏了(包括超级马力欧兄弟一代和魂斗罗)。


项目地址: https://github.com/vfreex/gones (欢迎 PR,顺便求一波赞)

目前这个项目还比较初期,只能慢慢完善了。如果很多人感兴趣的话我打算写几篇文章,做个自制 NES 模拟器的教程。

演示

演示游戏为 Nova The Squirrel,是一个仿星之卡比系列的开源山寨游戏。

5946 次点击
所在节点    分享创造
19 条回复
oovveeaarr
2019-05-28 15:11:40 +08:00
太强了,支持下 lz
hxtheone
2019-05-28 15:18:10 +08:00
强! 已 star
shansing
2019-05-28 15:19:43 +08:00
支持楼主。话说我早先接触到的模拟器是 VirtuaNES,似乎是开源的。当时我就想能不能按自己的需求修改修改(外层修改),一直没有勇气。没想到楼主竟然自己写了个模拟器。
66beta
2019-05-28 15:20:32 +08:00
瞻仰一下大佬
liuxey
2019-05-28 15:21:04 +08:00
👍
raysonx
2019-05-28 15:27:08 +08:00
@shansing NES 作为一个如此老又流行的硬件,各种开源实现还是很多的,做这个主要还是为了练手。
NES 硬件模拟(时钟不是特别精确的情况下)总体还是比较简单的,就是要处理的细节比较多,还有难以调试。
kokutou
2019-05-28 15:31:47 +08:00
nes 模拟器的 mapper 是个大坑。。。

另外精确模拟可以参考下 higan 和 mesen
AaronLiu00
2019-05-28 15:36:47 +08:00
赞一个👍
前几个月用 Go 写过 Gameboy 的模拟器,深知 debug 的艰难...
lumotian
2019-05-28 18:21:52 +08:00
太牛逼了
SurfaceView
2019-05-28 18:51:11 +08:00
我服了 太牛逼了 大佬 膝盖在这 !
abc635073826
2019-05-28 19:12:58 +08:00
牛逼!
jason94
2019-05-28 19:14:11 +08:00
大佬牛皮
dabaibai
2019-05-28 23:24:18 +08:00
马克一下 大佬厉害
zhensjoke
2019-05-29 16:46:26 +08:00
前段时间打算自己做个在线玩 FC 的网站,网上很多 JavaScript 库可以直接用。(比如 https://jsnes.org/)
到现在还在嫌麻烦没做...
liangzi
2019-06-16 18:26:59 +08:00
http://fyne.io/的库到底怎么用呢
新人看不懂 请教一下 谢谢~
raysonx
2019-06-17 13:23:29 +08:00
@liangzi pkg/nes/display.go 里面可以看一下我这里的用法,不过我打算马上把这个库替换掉
liangzi
2019-06-17 14:18:26 +08:00
@raysonx 先谢谢 gui 这块看不懂...好多库看着挺厉害的然而针对小白的资料很少都需要有一定基础才行 你这个我学习一下 谢谢
raysonx
2019-06-17 14:33:16 +08:00
@liangzi 不过注意 go 语言目前并没有一个稳定的 gui 库,我最近了尝试了好多,没有一个完善的。
liangzi
2019-06-17 18:28:49 +08:00
@raysonx 嗯 谢谢提醒

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/568410

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX