NES 模擬器開發(fā)教程 06 - CPU BUS

API

之前講過 NES 有 CPU 和 PPU 兩條總線,總線使 CPU 或 PPU 具備了與其他模塊通信的能力,所以設(shè)計 CPU 之前首先需要設(shè)計 CPU 總線,好在它并不復(fù)雜,不管是 CPU 還是 PPU 總線,只需要 兩個接口

export interface IBus {
  writeByte(address: uint16, data: uint8): void;
  writeWord(address: uint16, data: uint16): void;
  readByte(address: uint16): uint8;
  readWord(address: uint16): uint16;
}

這里設(shè)計區(qū)分了 byte 和 word 主要是為了調(diào)用的時候方便,其實 word 的 api 完全可以用 byte 的 api 進行封裝,比如:

public readWord(address: uint16): uint16 {
  return (this.readByte(address + 1) << 8 | this.readByte(address)) & 0xFFFF;
}

實現(xiàn)

NES 模擬器開發(fā)教程 01 - NES 系統(tǒng)結(jié)構(gòu) 中,已經(jīng)介紹過了 CPU 內(nèi)存映射。CPU BUS 的實現(xiàn),就是根據(jù)內(nèi)存映射去讀寫不同的硬件

export class CPUBus implements IBus {
  public cartridge: ICartridge;

  private readonly ram = new Uint8Array(2048);

  public writeByte(address: uint16, data: uint8): void {
    if (address < 0x2000) {
      // RAM
      this.ram[address & 0x07FF] = data;
    } else if (address < 0x6000) {
      // IO Registers, 暫時不實現(xiàn)
    } else {
      // Cartridge
      this.cartridge.mapper.write(address, data);
    }
  }

  public writeWord(address: uint16, data: uint16): void {
    this.writeByte(address, data & 0xFF);
    this.writeByte(address + 1, (data >> 8) & 0xFF)
  }

  public readByte(address: uint16): uint8 {
    if (address < 0x2000) {
      // RAM
      return this.ram[address & 0x07FF];
    } else if (address < 0x6000) {
      // IO Registers, 暫時不實現(xiàn)
      return 0;
    } else {
      // ROM
      return this.cartridge.mapper.read(address);
    }
  }

  public readWord(address: uint16): uint16 {
    return (this.readByte(address + 1) << 8 | this.readByte(address)) & 0xFFFF;
  }
}

初始化

Cartridge 和 CPU BUS 都實現(xiàn)后,需要在 Emulator 構(gòu)造函數(shù)中初始化:

const cartridge = new Cartridge(nesData, new Uint8Array(8192));
const cpuBus = new CPUBus();

cpuBus.cartridge = cartridge; // 將 Cartridge 和 CPU BUS 關(guān)聯(lián)起來

這樣初始化之后,就可以通過 CPU BUS 讀取總線上的任意數(shù)據(jù)了,例如讀取 RESET 中斷向量指向的地址:

const resetAddress = cpuBus.readWord(0xFFFA);
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容