V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
爱意满满的作品展示区。
raysonx
V2EX  ›  分享创造

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

  •  1
     
  •   raysonx ·
    vfreex · 2019-05-28 15:05:33 +08:00 · 5950 次点击
    这是一个创建于 2036 天前的主题,其中的信息可能已经有所发展或是发生改变。

    上个月在 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 模拟器的教程。

    演示

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

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

    另外精确模拟可以参考下 higan 和 mesen
    AaronLiu00
        8
    AaronLiu00  
       2019-05-28 15:36:47 +08:00 via Android
    赞一个👍
    前几个月用 Go 写过 Gameboy 的模拟器,深知 debug 的艰难...
    lumotian
        9
    lumotian  
       2019-05-28 18:21:52 +08:00
    太牛逼了
    SurfaceView
        10
    SurfaceView  
       2019-05-28 18:51:11 +08:00
    我服了 太牛逼了 大佬 膝盖在这 !
    abc635073826
        11
    abc635073826  
       2019-05-28 19:12:58 +08:00
    牛逼!
    jason94
        12
    jason94  
       2019-05-28 19:14:11 +08:00
    大佬牛皮
    dabaibai
        13
    dabaibai  
       2019-05-28 23:24:18 +08:00 via iPhone
    马克一下 大佬厉害
    zhensjoke
        14
    zhensjoke  
       2019-05-29 16:46:26 +08:00
    前段时间打算自己做个在线玩 FC 的网站,网上很多 JavaScript 库可以直接用。(比如 https://jsnes.org/)
    到现在还在嫌麻烦没做...
    liangzi
        15
    liangzi  
       2019-06-16 18:26:59 +08:00
    http://fyne.io/的库到底怎么用呢
    新人看不懂 请教一下 谢谢~
    raysonx
        16
    raysonx  
    OP
       2019-06-17 13:23:29 +08:00 via Android   ❤️ 1
    @liangzi pkg/nes/display.go 里面可以看一下我这里的用法,不过我打算马上把这个库替换掉
    liangzi
        17
    liangzi  
       2019-06-17 14:18:26 +08:00
    @raysonx 先谢谢 gui 这块看不懂...好多库看着挺厉害的然而针对小白的资料很少都需要有一定基础才行 你这个我学习一下 谢谢
    raysonx
        18
    raysonx  
    OP
       2019-06-17 14:33:16 +08:00 via Android
    @liangzi 不过注意 go 语言目前并没有一个稳定的 gui 库,我最近了尝试了好多,没有一个完善的。
    liangzi
        19
    liangzi  
       2019-06-17 18:28:49 +08:00 via Android
    @raysonx 嗯 谢谢提醒
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2589 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 15:34 · PVG 23:34 · LAX 07:34 · JFK 10:34
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.