二十年前,它是无数人电脑上的第一款红白机模拟器;
二十年后,我们把它从 DirectX 老古董堆里捞出来,
换上 Web 新装,重新打包成 0.9 MB 的单文件 exe------
而复活路上最大的拦路虎,居然是一只手柄。
为什么是 VirtuaNES
VirtuaNES 是红白机(FC/NES)模拟器里的元老级存在:Mapper 支持全、
扩展音源齐、手感地道,承载了一代人的童年存档。
但它太老了。基于 DirectX + MFC 的架构,意味着:
- 编译环境难搭,定制门槛高
- 界面是 Win32 对话框,想改个样式都得动 C++
- 依赖一堆系统组件,打包分发自带负担
老程序没有错,错的是它活在了二十年前的技术栈里。
所以,换一种方式让它活下去。
重生的方式:模拟核心不动,外壳全换
我们的做法是「外科手术式」改造:
-
src/nes模拟核心(PPU / APU / CPU / 148 个 Mapper)零改动保留 -
用一套
src/compat兼容层,把 DirectX、MFC 的调用全部翻译成现代实现 -
界面交给 Web(HTML/CSS/JS),用 TauriCPP(Win32 + WebView2)桥接
画面 → Canvas 2D ← PPU 8bpp 索引位图 + 调色板
声音 → Web Audio ← APU 16bit 单声道 PCM
输入 → KeyboardEvent ← DIK 扫描码
于是 VirtuaNES.exe 长出了新面孔:无边框窗口、自绘标题栏、F12 打开 DevTools,
前端开发者改样式刷新即见。而模拟内核,还是那套让老玩家放心的原汁原味。
重生路上最大的拦路虎:手柄
新装是换上了,但想用手柄玩红白机时,麻烦接踵而至。
第一关:插上手柄,系统提示「未知 USB 设备(设备描述符请求失败)」
这是 USB 枚举失败------系统根本没和手柄握手成功,程序再努力也白搭。
排查顺序(按命中率):
- 换数据线------很多原装线是纯充电线,没有数据线
- 换 USB 口------插机箱背面直连口,避开集线器/扩展坞
- 设备管理器卸载设备 → 重新插拔
- 切换 X/D 模式------部分国产手柄默认模式会触发此问题
- 换电脑验证------缩小故障范围
标准:设备管理器里能看到手柄具体名称,才算真正连上。
第二关:连上了,按键却怎么按都没反应
手柄能被检测到,点「设置」后狂按按钮,界面纹丝不动。
真相是时序问题 :按下瞬间正处于点击「设置」的手势里,按键被当成了初始状态;
或者手柄被判定为「一直按着」,捕获直接作废。
修复:改用帧间边沿检测 ------点完设置直接按键即可绑定,
若按键恰好处于按住状态,会提示「请先松开手柄按键」,松开再按一次就好;
再加 8 秒超时,界面永远不会卡在「请操作手柄...」。
顺手加的两个贴心功能
- 实时输入测试 :面板上实时显示
按钮 [0 8]、轴0=1.00,
按了没反应还是绑不上,一眼定位问题在采样链路还是绑定逻辑 - 恢复手柄默认绑定:一键按 Xbox 标准布局填好键位,插上直接开玩
后端也下了功夫:XInput 动态加载(兼容 xinput1_4/1_3/9_1_0),
DirectInput8 兜底非 Xbox 手柄并自动去重,16 按钮 + 4 轴带死区归一化,
支持按键与摇杆轴自由绑定。
重生之后
现在的 VirtuaNES.exe:
- Mapper 0--255 全支持,FDS / NSF 不在话下
- VRC6 / VRC7 / MMC5 / N106 / FME7 扩展音源全开
- 即时存档、光枪、整数倍缩放,一样不少
- 画面走 Canvas,声音走 Web Audio,前端主动拉帧天然背压,低延迟
- 前端资源全部打进 exe,单文件 0.9 MB 直接分发
老内核,新外壳,能用手柄重温童年------这就是 VirtuaNES.exe 的重生。