SNES模拟器如何从完全完善中获得一些像素

作为…的首席编码员
s
,我一直在尝试完善Super Nintendo仿真
在过去的15年中
。我们现在正处在实现这一目标的时刻,但我们面临的最后一个挑战是:SNES视频处理器的准确周期计时。获得最终的仿真精度将需要社区的努力,我希望你们中的一些人可以提供帮助。但是首先,让我回顾一下我们已经走了多远。

我们在哪里

今天,SNES仿真处于非常好的位置。除非具有耐仿真性的异常外围设备(例如,基于光传感器的高尔夫球杆,健身车或用于在日本的实时赛马上进行实物投注的拨号调制解调器),否则每个获得官方许可的SNES头衔都是完全可玩,没有游戏存在任何明显问题。

SNES仿真已经变得如此精确,以至于我甚至将仿真器分为两个版本:higan,它专注于绝对准确性和硬件文档;和bsnes,重点关注性能,功能和易用性。

最近,SNES仿真产生了一些令人惊奇的事情,包括:

  • 所有SNES协处理器的底层仿真
  • 高清模式7支持
  • 减慢速度
  • 宽屏支持
  • MSU1,用于CD音频和FMV
  • 提前运行以减少延迟
  • 动态速率控制可实现完美的音视频同步

… 以及更多

就这样,对吧?感谢您所做的一切好吗?好吧…不完全是。

今天,我们几乎对SNES的每个组件都享有周期级的准确性。唯一的例外是PPU(图像处理单元),它们用于生成发送到屏幕的视频帧。我们大多数人都知道PPU的工作原理,但是我们必须对某些功能进行猜测,而这些功能所带来的效果还不完全理想。

在总体方案中,其余问题相对较小。如果您对自己追求100%忠实的仿真完美不感兴趣,那么我将无法说服您进一步改进SNES PPU仿真的需求。与生活中的任何目标一样,我们越接近完美,回报就越小。

我可以告诉你为什么这对我很重要:这是我一生的工作,我不想说我没有完成最后一部分就已经接近完成了。我正在变老,并且我不会永远存在。我希望最终的解决方案能够解决,以便让我对退休后的工作充满信心,因为SNES已通过仿真得到了忠实和完整的保护。没有留下任何石头,没有留下任何未完成的区域。我想说已经完成了。

如果您仍然感兴趣,请继续阅读以深入了解问题的背景和我提出的解决方案。

对SNES设计建模

让我们首先看一下构成SNES的组件:

超级NES系统图。放大/超级NES系统图。

箭头指示SNES中各个处理器可以相互通信的方向,虚线表示存储芯片连接。

现在要拿走的关键是要注意,视频和音频输出是直接从PPU和DSP直接发送的。这意味着它们的功能就像“黑匣子”一样,在这里我们看不到内部发生的一切。稍后这将很重要。

正确性

想象一下,您正在仿真一个CPU的“乘法”指令,该指令需要两个寄存器(变量),然后将它们相乘,然后产生一个结果以及一些表示结果状态(例如溢出)的标志。

我们可以设计一个软件程序,将每个可能的值从0乘以255乘以乘数和被乘数。然后,我们可以输出乘法的数字结果和标志结果。这将产生两个65,536个条目表。

通过分析这些表,我们可以准确确定如何以及何时以某些方式设置CPU结果。然后,我们可以修改模拟器,以便在运行相同的测试时,在相同的时间产生完全相同的表。

现在,我们假设CPU具有16位x 16位乘法。测试每个可能的值将产生40亿个结果,这开始推动在合理的时间内进行实际测试。如果CPU具有32位x 32位乘法,那么在Cosmos热死之前测试所有输入组合都是不可行的(至少使用当前技术)。

在这种情况下,我们将不得不对测试进行更多的选择,并尝试准确确定标志何时可能更改,结果何时可能溢出等。否则,我们将无法完成测试。

乘法是相当琐碎的操作,但这是反向工程背后的一般过程,它扩展到更复杂的操作,例如SNES的水平消隐DMA(直接内存访问)传输的工作方式。我们创建测试以尝试检测边缘情况下发生的情况,然后确认我们的仿真行为与真实SNES相同。

振荡器和周期

SNES包含两个振荡器:一个运行在〜21MHz的晶体时钟,它控制CPU和PPU;陶瓷谐振器的工作频率约为24MHz,它控制着SMP和DSP。盒式协处理器有时会使用〜21MHz的CPU振荡器,有时会包括自己的以不同频率运行的振荡器。

纯粹用软件重新创建原始的Super Famicom电路板比看起来要难。纯粹通过软件来放大/重新创建原始的Super Famicom电路板比看起来要难。

时钟是任何系统的核心计时元素,SNES旨在在特定的频率和时间执行各种任务。

如果您想象一个100Hz的时钟,则它是一个具有数字引脚的设备,该引脚每秒转换为逻辑高电平(例如+5伏),然后又转换回逻辑低电平(0伏或接地)。因此,每秒钟引脚电压将总共波动200次:100个时钟上涨沿和100个时钟下跌沿。

一个时钟周期通常被视为一个完整的过渡,因此100Hz时钟每秒将产生100个时钟周期。有些系统需要区分上涨沿和下跌沿,对于这些系统,我们将其进一步细分为半个周期,以表示时钟信号的每个相位(高或低)。

真正的仿真器的主要目标是以与真实硬件完全相同的方式并在相同的时间执行任务。具体如何执行任务并不重要。重要的是,仿真器在被赋予相同的输入后,会以与真实硬件相同的时序生成相同的输出。

定时

有时,操作会随着时间而发生。以SNES CPU乘法为例。 SNES CPU无需暂停等待乘法完成,而是在八个CPU操作码周期中一次在后台计算乘法结果。这样,您的代码就可以在等待乘法完成的同时做其他事情。

任何商业发行的软件都可能要等待这八个周期,因为如果尝试在准备就绪之前先读取结果,则会得到部分计算的结果。但是,早期的SNES仿真器无需等待这些额外的周期即可立即给出正确的结果。

当业余爱好者开始通过仿真器创建和测试自制软件时,这种差异开始引起一些问题。该软件中的某些软件(例如许多早期的Super Mario World ROM黑客程序)只能在这些早期的仿真器上正确运行,而不能在实际的SNES硬件上正常运行。那是因为它们在设计时就考虑了模拟器的即时(和对真实硬件不真实的)乘法结果。

随着仿真器的改进,该旧软件出现了问题,随后我们不得不在较新的仿真器中提供兼容性选项,以免浪费时间。是的,可以这么说,这些天我们的仿真器必须模仿其他仿真器多么元

关于CPU乘法延迟的好处是,它是非常可预测的:八个计算周期在请求乘法后立即开始。通过编写代码在每个周期后读取结果,我们可以确认SNES CPU使用的是Booth算法进行乘法。

时钟同步

其他操作并不是那么简单建模,因为它们在后台异步发生。 SNES CPU的DRAM刷新就是这种情况之一。

在渲染每条扫描线的过程中,在某个点上,随着RAM芯片内容的刷新,整个SNES CPU冻结的时间很短。之所以需要这样做,是因为为了降低成本,SNES为其主CPU内存使用了动态RAM(而不是静态RAM)。动态RAM必须定期刷新,以保留其内容。

对于一个真正完美的仿真器,仅使约3500种商业发行的SNES游戏可玩是不够的。系统的每个功能也必须以完美的周期精度进行仿真。放大/对于一个真正完美的模拟器,仅使约3500个商业发行的SNES游戏可玩就不够。系统的每个功能也必须以完美的周期精度进行仿真。

弄清楚这些操作的准确时间的关键见解是利用SNES PPU的水平和垂直计数器。这些计数器前进,并在每个水平和垂直消隐周期后重置。但是,它们的精度仅为SNES CPU振荡器频率的四分之一。也就是说,水平计数器每四个时钟周期仅增加一次。

通过多次读取计数器,我能够确定计数器与时钟周期的哪四分之一对齐。通过将这种洞察力与特制的功能相结合,可以按用户指定的精确时钟周期数步进,可以将SNES CPU完美地对准我想要的任何精确时钟周期位置。

通过循环遍历一系列时钟周期,我可以确切确定何时进行某些操作(例如DRAM刷新,HDMA传输,中断轮询等),并且我能够在仿真下精确地重现该操作。

SNES SMP芯片也具有自己的计时器,并且针对该处理器的类似逆向工程也很成功。我可能会花费整整篇文章单独讨论SMP TEST寄存器,它使编码人员可以控制SMP的时钟分频器及其计时器,以及其他可怕的事情。可以说,尽管这不是一个简单或快速的过程,但我们最终取得了胜利。

收集协处理器

SuperFX芯片只是SNES模拟器必须正确处理的众多盒式协处理器之一。放大/ SuperFX芯片只是SNES模拟器必须正确处理的众多盒式协处理器之一。在各种游戏盒中也需要使用大量SNES协处理器。从SuperFX和SA-1等专用通用CPU,到DSP-1和Cx4等数字信号处理器,再到S-DD1和SPC7110等解压加速器,再到Sharp和Epson的实时时钟等等。 ..

这意味着SNES仿真器需要能够处理SuperFX的指令和像素缓存。 SA-1的内存总线冲突Arbitrum器(允许SNES CPU和SA-1同时共享相同的ROM和RAM芯片); DSP-1和Cx4的嵌入式固件; S-DD1和SPC7110的基于预测的算术编码器;以及实时时钟的奇数BCD(二进制编码的十进制)边缘情况。但是,通过应用上述技术确定正确性和时序,我们可以缓慢但可靠地几乎完美地仿真所有这些芯片。

实际上,从各种游戏中使用的数字信号处理器中提取并提取编程固件需要花费大量的精力和数千美元。在一个实例中,NEC uPD772x的仿真导致higan的代码被用来保存已故教授Stephen Hawking的声音

在另一种情况下,我们必须对Hitachi HG51B架构的整个指令集进行反向工程,因为从未公开记录过该架构。在另一款游戏中(Hayazashi Nidan Morita Shougi 2)最终包含了成熟的32位,21MHz ARM6 CPU,以加速其日本象棋引擎

仅保留所有SNES协处理器是一个充满挑战和惊喜的多年旅程。

处理数字信号

不要与DSP-1盒式协处理器混淆,索尼S-DSP(数字信号处理器)芯片可以从SNES产生独特的声音。该芯片将八个语音通道与4位ADPCM编码结合在一起,以产生16位立体声信号。

从表面上看,按照之前的系统框图,DSP最初看起来像一个黑匣子:您配置语音通道和混币器设置,然后坐下来,它会生成声音以发送给扬声器。

但是一个主要功能允许名为blargg的开发人员对该芯片进行完全反向工程:回声缓冲区。 SNES DSP具有将先前样本的输出混合在一起以产生回声效果的功能。这发生在音频生成过程的最后(除了最后一个最终静音标志(可用于使所有音频输出静音)之外)。

通过精心编写周期定时代码并监视这些回声结果,就可以发现SNES DSP生成每个样本并产生周期精确,比特完美的音频所需的确切操作顺序。

资讯来源:由0x资讯编译自ARSTECHNICA,版权归作者Ars Staff所有,未经许可,不得转载
提示:投资有风险,入市需谨慎,本资讯不作为投资理财建议。请理性投资,切实提高风险防范意识;如有发现的违法犯罪线索,可积极向有关部门举报反映。
你可能还喜欢