2

我完成了我的 6502 仿真器的编写,并准备开始测试它。我找到了带有一些文档的嵌套ROM,但我不确定加载 ROM 的正确方法是什么。作者说,模拟器应该从0xC000开始,当我加载ROM时包含0,所以我一定做错了什么。

所以现在我的加载过程看起来像这样:

clear memory
set PC to 0x8000
open the file
skip first 16 bytes (iNES header)
load the rest of the file into RAM (starting at 0x8000)
set PC to 0xC000
4

1 回答 1

3

根据 Nick Westgate 的评论(因此是即时社区 wiki),加载过程比您可能天真的猜测的要复杂一些

现在,您可以从偏移量 0x0010 开始加载 0x4000 字节,并将其作为 ROM 映射到仿真 6502 的内存映射的 $8000-$BFFF 和 $C000-$FFFF 中。

“现在”假设您要编写一个 NES 模拟器,因此有一天会正确解析存储测试的 NES 相关文件格式,并模拟导致内容镜像的 NES 特定内存映射方案。

忽略之前帖子中的评论,您应该“在每个周期[记录]您的 PC(和寄存器)”,以及该帖子及以后的相同含义;他的意思是:

  1. 在获取第一个操作码字节之前,对程序计数器和其他寄存器进行内部记录;
  2. 读取最后一个操作数字节后,记录您在步骤 (1) 中存储的所有值以及完整指令及其反汇编。

如果您在仿真器中简化了一些事情,以原子方式读取和执行每个操作,然后按照您应该花费的工作周期数提前跳过时间,那么您可能可以省略临时存储。我怀疑生成示例日志的作者已经实现了这样的仿真。关键线索将是一个switch由操作码索引的表,它在某种程度上不是协程,和/或指令长度的查找表。

进一步的建议:

NES 实际上并没有使用 6502。它使用了一个省略十进制模式的克隆——十进制标志根本不起作用。因此,如果您正在模拟 6502,预计测试结果会有所不同。

有关其他良好的 6502 测试,请参阅:

  • AllSuiteA(测试一大堆东西,让你通过或失败);
  • Klaus Dormann 的测试(有点麻烦;如果特定测试失败,将简单地在某处进入无限循环。您需要检查源以找出您遇到的失败);和
  • Wolfgang Lorenz 的测试(一大堆单独的测试,最初用于在 C64 上单独运行,但在 6502 之外没有任何实现的情况下很容易运行,除了它会在 PETSCII 中提供状态的文本输出,所以你还需要一个快速查找表将其映射到 ASCII)。

我使用所有这三个来引导我最近的 6502 仿真器,以及一些自己编写的逐周期测试,用于诸如中断之类的事情,你不会期望位于 6502 地址空间内的代码能够处理。

后来我发现我在十进制处理上有一个非常小的偏差——小到足以通过所有这些测试,但不足以通过详尽的 6502 比较。我很方便地在 Acorn BBC 社区中找到了一个更好的测试,在这篇文章所附的档案中。我选择通过以下方式运行它:

  • 加载BCDTEST_beebat的内容0x2900
  • 写信JSR 2900h给地址0x200
  • 放一个RTSat 0xffee,但也要确保您可以捕获该地址;
  • 将程序计数器设置为0x200并继续运行,直到它位于0x203
  • 然后测试 处的值0x84是否为0。如果是其他东西,则表明失败。

为了获得更多反馈,只要 PC 进入0xffee,输出 A 寄存器中的 ASCII 字符。

于 2017-10-31T13:16:29.287 回答