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

用 Typescript 写了个 NES 模拟器

  •  4
     
  •   esw · 2020-04-06 13:48:21 +08:00 · 7430 次点击
    这是一个创建于 1687 天前的主题,其中的信息可能已经有所发展或是发生改变。

    假期无聊想着搞一个 NES 模拟器玩玩,目标在浏览器中运行,断断续续搞了一个月之后基本五脏俱全了,声音和图像都没啥大问题

    github 地址:tsnes

    在线演示地址:tsnes-demo

    当初做模拟器的时候网上也找不到完整的入门教程,所以干脆就自己抽空慢慢更新教程了:NES 模拟器开发教程

    模拟器效果图:

    重装机兵 p1

    Mario1 p2

    我的 18 款 MBP i7 CPU,在 Chrome 中运行 CPU 占用大概 70%,所以理论上 i5 应该也可以全速模拟。

    另外由于音频和绘图也会占用不少 CPU,所以如果采用 Web worker 将模拟器的线程分离出去,理论上在手机中应该也能全速模拟

    由于我是以库的形式进行开发的,所以没有花心思美化页面(~~主要还是懒~~)

    55 条回复    2020-04-11 12:20:23 +08:00
    zhuawadao
        1
    zhuawadao  
       2020-04-06 13:57:30 +08:00
    别让楼主灰心,支持一下~
    Mohanson
        2
    Mohanson  
       2020-04-06 13:59:58 +08:00   ❤️ 1
    lzdyes
        3
    lzdyes  
       2020-04-06 14:20:05 +08:00
    厉害了!
    yuuko
        4
    yuuko  
       2020-04-06 14:24:32 +08:00
    厉害了
    anUglyDog
        5
    anUglyDog  
       2020-04-06 14:39:33 +08:00
    anUglyDog
        6
    anUglyDog  
       2020-04-06 14:40:49 +08:00
    你这做好看点可以引流啊,太有情怀了
    idealhs
        7
    idealhs  
       2020-04-06 14:47:00 +08:00
    挺好奇,为什么如此低性能的一个机器,浏览器的模拟器跑起来这么吃资源啊
    GPLer
        8
    GPLer  
       2020-04-06 14:50:56 +08:00
    @idealhs 模拟本身就有性能损失,更不用说用的是脚本语言,执行效率本身就不高,原始的机器性能虽然低,但好歹利用率高,性能浪费的少。
    LukeChien
        9
    LukeChien  
       2020-04-06 15:09:45 +08:00 via Android
    好像见过 WebAssembly 做的,那个性能会好一些,楼主同样🐮🍺
    zj
        10
    zj  
       2020-04-06 15:25:43 +08:00
    这个要支持下。
    across
        11
    across  
       2020-04-06 15:25:46 +08:00
    看了文档还没写到显示部分,是用 webgl 画?
    across
        12
    across  
       2020-04-06 15:27:58 +08:00
    @across 看了下 ppu 代码是纯手动画的啊,怪不得····
    renmu
        13
    renmu  
       2020-04-06 15:37:49 +08:00 via Android
    我不当勇士了,我要回家修战车
    esw
        14
    esw  
    OP
       2020-04-06 15:47:56 +08:00
    @zhuawadao 谢谢!
    esw
        15
    esw  
    OP
       2020-04-06 15:51:30 +08:00
    @idealhs NES PPU 时钟 5MHZ 以上,也就是说模拟的时候每秒要执行 500w 以上次运算,而且每次运算需要很多逻辑来完成,再加上 JS 性能损耗,所以比较费 CPU
    esw
        16
    esw  
    OP
       2020-04-06 15:53:11 +08:00
    @across 目前是 PPU 生成 RGB 点阵数据直接扔给 canvas 画图和缩放,只不过都在一个线程完成了
    firefox12
        17
    firefox12  
       2020-04-06 15:57:39 +08:00
    很牛逼 我想问是不是要把 cpu ppu 系统本身全模拟出来 再做?
    esw
        18
    esw  
    OP
       2020-04-06 16:03:21 +08:00
    @firefox12 我是找一些简单的或者自己写的测试程序,然后一点一点开发,不需要一下子全模拟好,在不熟悉所有硬件行为的情况下也不现实
    firefox12
        19
    firefox12  
       2020-04-06 16:08:20 +08:00
    @esw 但是 没有模拟 cpu 和 ppu 你怎么让卡带里的内容跑起来? 我的看法 是读卡带文件 ,然后让模拟 cpu 开始运行里面的二进制,然后让结果显示出来吧。
    zwxharry
        20
    zwxharry  
       2020-04-06 16:13:30 +08:00
    重装机兵回忆杀,红狼,尼娜
    esw
        21
    esw  
    OP
       2020-04-06 16:24:02 +08:00
    @firefox12 对,首先开发 CPU,使用 http://nickmass.com/images/nestest.nes 来开发,它有 log 可以对照: http://www.qmtpro.com/~nes/misc/nestest.log ,这样就可以一条指令一条指令地开发,同时用 log 来检测错误,最终整个文件正常运行完就说明 CPU 大部分工作开发完了,然后使用同样的方法,一点一点开发 PPU
    Arrowing
        22
    Arrowing  
       2020-04-06 17:10:24 +08:00
    重装机兵好评,upupup
    Warder
        23
    Warder  
       2020-04-06 17:22:01 +08:00
    很强,一个月就做好了啊
    mengkun
        24
    mengkun  
       2020-04-06 18:15:26 +08:00
    太强了……
    lbyo
        25
    lbyo  
       2020-04-06 19:46:00 +08:00
    收下我的膝盖
    superliwei
        26
    superliwei  
       2020-04-06 20:05:57 +08:00
    很强。。。
    esw
        27
    esw  
    OP
       2020-04-06 22:14:49 +08:00
    @Warder 不算完全做好,nes mapper 太多了,简直就是无底洞,目前只完成了一些常用 mapper
    esw
        28
    esw  
    OP
       2020-04-06 22:15:21 +08:00
    @Mohanson 学习了!
    Mohanson
        29
    Mohanson  
       2020-04-06 22:21:59 +08:00
    @esw 哈哈, 我还写过雅达利街机的模拟器: https://github.com/mohanson/space-invaders, 这些游戏机因为没有操作系统所以模拟起来比较容易, 到 PS 时代后的机器就不好模拟了, 去年想过做 switch emu, 调研了一下就立马放弃了.
    Meltdown
        30
    Meltdown  
       2020-04-06 22:23:50 +08:00 via Android
    膜拜
    zhw2590582
        31
    zhw2590582  
       2020-04-06 22:34:08 +08:00
    可以大概说说怎么个原理吗
    luny
        32
    luny  
       2020-04-06 23:45:37 +08:00
    学习了!
    Archeb
        33
    Archeb  
       2020-04-07 08:02:09 +08:00 via iPhone
    楼主🐮🍺!
    happy8109
        34
    happy8109  
       2020-04-07 09:37:09 +08:00
    实现个实时存盘吧
    esw
        35
    esw  
    OP
       2020-04-07 09:47:28 +08:00
    @Mohanson 是啊,资料太少,其他主机基本都没有 nesdev 这样全的网站了
    esw
        36
    esw  
    OP
       2020-04-07 09:48:19 +08:00
    @zhw2590582 其实就是软件模拟 NES 里面芯片的逻辑,然后电信号变成函数调用
    esw
        37
    esw  
    OP
       2020-04-07 09:48:54 +08:00
    @happy8109 存盘已经实现了,现在每 3 秒保存在 localstorage 里面
    esw
        38
    esw  
    OP
       2020-04-07 09:49:40 +08:00
    @happy8109 刚看错了,才反应过来你说的是实时存档,这个确实还没搞
    augustheart
        39
    augustheart  
       2020-04-07 10:35:49 +08:00
    @esw gba 啊,唯一一台主机发售前就让人给模拟了的游戏机……
    UnknownR
        40
    UnknownR  
       2020-04-07 10:55:50 +08:00
    卧槽🐂🍺,star 一个学习一下
    eivs
        41
    eivs  
       2020-04-07 11:32:55 +08:00
    这个感觉更流程一些

    https://github.com/bfirsh/jsnes
    wanguorui123
        42
    wanguorui123  
       2020-04-07 14:16:26 +08:00
    666
    baxtergu
        43
    baxtergu  
       2020-04-07 16:50:46 +08:00
    在 github 发现了这个仓库看了下代码,一开始以为是对 jsnes 的 ts 实现,后来发现好像不是。不过楼主厉害 一个月能做成这样,666
    sivacohan
        44
    sivacohan  
       2020-04-07 16:54:16 +08:00
    @Mohanson 我支持了一个小额赞助~
    yun77op
        45
    yun77op  
       2020-04-07 17:07:43 +08:00
    厉害,可以尝试下用 assemblyscript 把 ts 转成 WebAssembly
    Mohanson
        46
    Mohanson  
       2020-04-07 17:13:38 +08:00
    @sivacohan 天啦噜, 这是我收到过最大的一笔赞助费! 谢谢老板(认真
    exceptionplayer1
        47
    exceptionplayer1  
       2020-04-07 17:37:06 +08:00
    真厉害,大佬
    lneoi
        48
    lneoi  
       2020-04-07 17:56:27 +08:00
    厉害厉害
    boks
        49
    boks  
       2020-04-07 18:04:23 +08:00
    牛逼,我最近刚好也想搞这个。
    lights
        50
    lights  
       2020-04-07 18:10:13 +08:00
    重装机兵在国内真的好有名啊
    esw
        51
    esw  
    OP
       2020-04-07 19:37:35 +08:00
    @eivs jsnes 之前看过源码,不过 es5 看得脑阔疼
    esw
        52
    esw  
    OP
       2020-04-07 19:37:54 +08:00
    @yun77op js 的动态特性不一定能转把?
    nazhenhuiyi294
        53
    nazhenhuiyi294  
       2020-04-08 09:55:18 +08:00
    有点流批
    uestcfei
        54
    uestcfei  
       2020-04-09 11:26:08 +08:00
    这个是没有支持所有的 nes 格式的吗?我下载的有一些 nes 的游戏,运行提示:Unsupported mapper: 150,file 看了一下,没啥区别啊。和好奇这个 nes 文件的格式。
    esw
        55
    esw  
    OP
       2020-04-11 12:20:23 +08:00   ❤️ 2
    @uestcfei 没有,nes 有几百种 mapper,大部分 mapper 逻辑都是不同的,所以要全支持的话相当于要实现上百颗芯片的逻辑,这是非常耗时耗力的,所以目前只支持了任天堂官方几个常用的 mapper 和重装机兵的 mapper:mapper 0-4,mapper 74
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3262 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 12:21 · PVG 20:21 · LAX 04:21 · JFK 07:21
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.