2017-07-25 111 views
1

我正在用C编写我的第一个NES仿真器。目标是让它易于理解并且循环准确(不一定必须是代码效率),以便在正常的“硬件'的速度。在深入挖掘6502的技术参考资料时,看起来指令消耗的CPU周期不止一个 - 并且根据给定的条件(如分支)也有不同的周期。我的计划是创建读写功能,并通过使用switch寻址模式对操作码进行分组。6502每个指令的周期时间

的问题是:当我有一个多周期指令,如BRK,我需要效仿在每个周期中究竟发生了什么:

#Method 1 

cycle - action 

1 - read BRK opcode 
2 - read padding byte (ignored) 
3 - store high byte of PC 
4 - store low byte of PC 
5 - store status flags with B flag set 
6 - low byte of target address 
7 - high byte of target address 

...或者我能不能执行在一个“周期”(一个switchcase)中的所有必需操作,并在剩余的周期中不做任何事情?

#Method 2 

1 - read BRK opcode, 
read padding byte (ignored), 
store high byte of PC, 
store low byte of PC, 
store status flags with B flag set, 
low byte of target address, 
high byte of target address 
2 - do nothing 
3 - do nothing 
4 - do nothing 
5 - do nothing 
6 - do nothing 
7 - do nothing 

由于两种方法都消耗了所需的7个周期,两者之间是否没有差异? (精度明智)

我个人认为方法1的方式是对去解决,但是我想不出来实现它......一个适当的,简单的方法(请帮助!)

+1

它不会有所作为,当你只** **模拟CPU。但考虑一下外设访问与“STA”指令相同的内存 - 当存储单元正好改变时,这可能很重要。所以,去选项1. –

+1

至于如何,你将需要一个状态机 –

+0

你知道任何好的C实例或来源,实现方法1吗?我所能找到的都是非C模拟器,有些在当前级别上太复杂:( –

回答

4

你'需要?这取决于软件。想象一下最简单的例子:

STA ($56), Y 

......碰巧碰到一个硬件寄存器。如果您至少没有按照正确的周期进行写入,那么您已经引入了时序不足。您正在写入的寄存器将在错误的时间写入。如果它像一个调色板寄存器,并且程序员正在运行栅格效果呢?然后,你刚搬到颜色发生变化的地方。你已经改变了图形输出。

实际上,聪明的程序员做的事情比那更聪明 - 例如,人们可以使用读 - 修改 - 写操作在一个确切的周期读取硬件值,修改它,然后在其他确切的周期写回。

所以我的答案是:

  1. 大多数软件不写,这样的区别(1)和(2)会产生什么影响;但是
  2. 有些肯定是,因为作者很聪明;和
  3. 一些肯定是,只是因为作者试验,直到他们发现一个很酷的效果,无论他们是否认识到原因;和
  4. 无论如何,当您发现某些在您的模拟器上无法正常工作时,您希望花费多少时间考虑所有潜在原因的排列和组合?每一个你可以分解的是一个较少考虑。

大多数仿真器都使用你的方法(2)。通常发生的事情是他们使用90%的软件。然后有几个不起作用的情况,模拟器作者在这里将特例放在这里,这是一个特例。那些通常最终互动不佳,模拟器的余生在支持可用软件的不同95%组合之间摇摆,直到有人写出更好的软件为止。

所以只需要使用方法(1)。它会导致一些本来不会被破坏的软件。它还会教你更多,并且它肯定会消除特殊情况下的任何潜在动机,从而使代码更清晰。它会稍微慢一些,但我认为你的电脑可以处理它。

其他提示:6502只有少数寻址模式,和寻址模式完全决定了定时。 This document是您需要了解完美时机的一切。如果你想要完美的清洁度,你的开关表可以选择一种寻址模式和一个中央操作,然后退出,你可以在寻址模式上分支来执行主要操作。

如果你打算使用香草readwrite方法,这是一个6502智能为每一个周期是读或写操作,这样,它几乎所有你需要说的,只是要小心的方法签名。例如,6502有一个SYNC引脚,它允许观察者将普通读取与操作码读取进行区分。检查NES是否将这种情况暴露给磁带盒,因为它经常在系统上使用,将其暴露给隐式寻呼,并且NES的主要识别特征是有数百个寻呼方案。

编辑:次要更新:

  • 它实际上不是完全真实地说,一个6502始终读取或写入;它也有一个RDY输入。如果RDY输入有效并且6502有意读取,它将停止,同时保持预期的读取地址。在实践中很少使用,因为它不足以执行一些常见的任务,比如允许其他人占有内存 - 6502将会写入,无论RDY输入如何,它的确意味着帮助单步执行 - 而且看起来不包含在NES cartridge pinout中,您无需为该机器实施它。
  • 每个相同的引脚,同步信号也似乎没有暴露在该系统的墨盒。
+0

好一个汤米。你说我确实太累了,无法打字。很长一段时间,我想编写一个微代码6502. @ H.J Jang:天真的方式是交换机(操作码)中每个操作码的开关(循环)语句。另一种方法是写一个微码表(你的方法#1)。正如Tommy所说,除了实际的操作码操作外,每种寻址模式都有相同的顺序。 –

+0

@NickWestgate我现在的6502仿真是微码! Microcode发明的时候虽然没有事先做好准备,但并不理想。我已经对Z80进行了微码编码,而且我的系统更加系统化。自90年代以来,我的6502模拟的演变:(1)函数指针表,不循环准确; (2)一个大的开关语句,接通指令,周期准确但只能运行一整个指令,所以必须是时间主站; (3)一个大的开关语句,接通指令,分离线程,必要时阻塞运行任意数量的周期; (4)微码。 – Tommy

+0

这个答案提供了一个很好的解释,我试图在我的评论中表达出来,+1从我:) –