Memory接口
我们都已经知道,程序必须加载到内存中才能被CPU执行。内存按照读写方式大致可以分为两种:ROM是只读的,RAM可以读也可以写。不过在真正的计算机中,CPU并不关心自己读写的是RAM还是ROM,因为CPU是通过总线(BUS)和内存间接沟通的。正是因为这样,6502只需要知道自己能够通过一个16比特的地址总线读写64K大小的内存就够了。至于这些内存到底是RAM还是ROM,是嵌在游戏机内部还是游戏卡上,都不重要。下面是Memory接口的代码:
public interface Memory { // Read one byte. public short read(int address); // Write one byte. public void write(int address, short value); }
6502是8比特CPU,也就是说,每一条指令只能够操作一个8比特整数,所以用一个byte[]就可以模拟内存了。但是考虑到大部分时候6502操作的都是无符号整数,而Java语言的byte表示的则是有符号整数,用byte会带来诸多不便,所以就使用了short来表示无符号8比特整数。
MOS6502
下面是6502模拟器的部分代码,emulate()方法执行一条指令,暂时还没实现,其他细节稍后介绍:
public class MOS6502 { private final Registers registers = new Registers(); private final Flags flags = new Flags(); private Memory memory; public Registers getRegisters() { return registers; } public Flags getFlags() { return flags; } public Memory getMemory() { return memory; } public void setMemory(Memory memory) { this.memory = memory; } // Execute one instruction. public void emulate() { // TODO } }
内存读写
为了方便起见,MOS6502实现了一对儿内存读写方法,这样可以省去每次内存读写操作前的getMemory()方法调用:
public class MOS6502 { ... // Read one byte from memory public short read(int address) { return memory.read(address); } // Write one byte into memory public void write(int address, short value) { memory.write(address, value); } ... }
栈操作
前面的文章提到过,6502可以操作一个256字节大小的栈,这个栈位于内存的$0100到$01FF之间。下面是push()和pull()方法的实现:
public class MOS6502 { ... // Push one byte into stack public void push(int value) { int oldSp = registers.getSP(); write(oldSp, (short) value); int newSp = oldSp - 1; registers.setSP(newSp); } // Pull one byte from stack public short pull() { int newSp = registers.getSP() + 1; registers.setSP(newSp); return read(newSp); } ... }