NES 模擬器開發(fā)教程 01 - NES 系統(tǒng)結(jié)構(gòu)

NES 硬件組成

NES 有以下硬件

  1. CPU
    想必它的作用不用介紹了。它的型號(hào)是 2A03,8bit审残,工作頻率 1.7897725 MHz梭域。它有 16bit 地址總線斑举,所以它的尋址范圍為 0x0000 - 0xFFFF搅轿,即 64KB。CPU 支持三種中斷:RESET(復(fù)位)富玷,NMI(不可屏蔽中斷)璧坟,IRQ(可屏蔽中斷)

  2. APU(Audio Processing Unit)
    APU 集成在了 2A03 里面,用于聲音的產(chǎn)生和輸出赎懦,所以它沒有專門的芯片雀鹃。它有 5 個(gè)通道,可以產(chǎn)生方波励两,三角波黎茎,噪聲,PCM(你問為什么 4 種波形占了 5 個(gè)通道当悔?因?yàn)橛?2 個(gè)通道可以用于產(chǎn)生方波)傅瞻。

  3. PPU(Picture Processing Unit)
    PPU 型號(hào)為 2C02,用于產(chǎn)生圖像盲憎。NES 中圖像分兩種

    • Background(背景)
      顧名思義嗅骄,用于背景的顯示,比如游戲的天空饼疙,草地溺森,建筑
    • Sprite(精靈)
      用于前景的顯示,例如游戲里的人物窑眯,子彈等

    最終上述兩種圖像組合后屏积,輸出到屏幕

  4. Cartridge(卡帶)/ Mapper
    這是我們最熟悉的硬件了,就是這個(gè):

    image.png

    卡帶中包含了 NES 程序和圖像的信息磅甩,所以不同游戲就會(huì)生產(chǎn)不同的卡帶肾请,CPU 和 PPU 都能直接訪問卡帶讀取內(nèi)容,至于讀取的時(shí)候返回什么樣的數(shù)據(jù)更胖,這就是 Mapper 需要做的事情铛铁。有的 Mapper 擴(kuò)大了程序的容量,有的 Mapper 植入了額外的芯片提升音頻等等却妨。饵逐。。

  5. RAM(內(nèi)存)
    NES 主機(jī)中一共有 2 個(gè) 2KB RAM彪标,一個(gè)給 CPU 用倍权,另一個(gè)給 PPU 用
    NES 卡帶中可能不帶任何 RAM,也可能帶 8KB 的額外用于 CPU 的 RAM(也就是我們常見的帶了紐扣電池的卡帶),甚至還有的卡帶還帶了 2KB 的額外用于 PPU 用的 VRAM

    • 主機(jī)中 2KB RAM
      用于游戲運(yùn)行數(shù)據(jù)存儲(chǔ)
    • 主機(jī)中 2KB VRAM(Video RAM)
      看名字就知道它干嘛了薄声,該 RAM 用于顯示數(shù)據(jù)的存儲(chǔ)当船,CPU 將要顯示的數(shù)據(jù)寫入 VRAM,然后 PPU 會(huì)讀取這里面的數(shù)據(jù)解碼后輸出到屏幕
    • 卡帶上 8KB RAM
      用于游戲額外的數(shù)據(jù)存儲(chǔ)默辨,最重要的是它能夠保存游戲存檔德频。這也說明了為什么我們拔了卡帶上的電池后存檔就沒了
    • 卡帶上 2KB VRAM
      PPU 工作在 4-Screen 的時(shí)候才會(huì)用到,現(xiàn)在不需要了解它

NES 總線

這里有一張?jiān)韴D:


image.png

圖中左上為 CPU缩幸,左下為 PPU壹置,右上為卡槽
能夠觀察到圖中有兩條粗的藍(lán)色的線,一個(gè)在上方表谊,一個(gè)在下方

  • 上方的藍(lán)線
    這是 CPU 的地址總線钞护,它有 16bit,尋址范圍 0x0000 - 0xFFFF
  • 下方的藍(lán)線
    這是 PPU 的地址總線爆办,它有 14bit难咕,尋址范圍 0x0000 - 0x3FFF

總結(jié)下來,我們知道了 NES 有 CPU 和 PPU 兩類總線距辆,他們分別有自己的尋址空間余佃。由于卡帶上既有圖像數(shù)據(jù)又有程序數(shù)據(jù),所以卡帶同時(shí)接入了兩根總線

NES 內(nèi)存映射

了解了 NES 有兩條總線之后挑格,我們需要關(guān)注 NES 的內(nèi)存映射咙冗,也就是總線上哪些地址對(duì)應(yīng)了哪些數(shù)據(jù)

1. CPU 內(nèi)存映射

image.png
  • 0x0000 - 0x0800 ( RAM )
    這是主機(jī)中 2KB RAM 的數(shù)據(jù),分成了 3 塊

    • 0x0000 - 0x00FF ( Zero page )
      前 256 字節(jié)劃分為 Zero page漂彤,這塊內(nèi)存相比其他區(qū)域不同點(diǎn)在于能讓 CPU 以更快的速度訪問雾消,所以需要頻繁讀寫的數(shù)據(jù)會(huì)優(yōu)先放入此區(qū)域
    • 0x0100 - 0x01FF ( Stack )
      這一塊區(qū)域用于棧數(shù)據(jù)的存儲(chǔ),SP(棧指針) 從 0x1FF 處向下增長(zhǎng)
    • 0x0200 - 0x07FF ( 剩余 RAM )
      這是 2KB 被 Zero page 和 Sack 瓜分后剩余的區(qū)域
  • 0x0800 - 0x2000 ( Mirrors )
    你可能會(huì)感覺到奇怪這個(gè) Mirror 到底是干什么的挫望。實(shí)際上它是 0x0000 - 0x07FF 數(shù)據(jù)的鏡像立润,總共重復(fù) 3 次
    例如:0x0001, 0x0801, 0x1001, 0x1801 都指向了同樣的數(shù)據(jù),用程序來解釋的話媳板,就是:
    address &= 0x07FF
    對(duì)應(yīng)到硬件上的話桑腮,就是 bit11 - 13 的線不接
    至于為什么任天堂要這樣設(shè)計(jì)?我猜可能是考慮到成本原因蛉幸,2KB RAM 夠用了破讨,不需要更大的 RAM,但是地址空間得用完啊奕纫,所以才有了 Mirror 效果

  • 0x2000 - 0x401F ( IO Registers )
    這里包含了部分外設(shè)的數(shù)據(jù)提陶,包括 PPU,APU匹层,輸入設(shè)備的寄存器隙笆。比如 CPU 如果想讀寫 VRAM 的數(shù)據(jù),就得靠 PPU 寄存器作為中介

  • 0x4020 - 0x5FFF ( Expansion ROM )
    Nesdev 的論壇上有篇解釋這塊區(qū)域的帖子,簡(jiǎn)單來講撑柔,該區(qū)域用于一些 Mapper 擴(kuò)展用瘸爽,大部分情況用不到

  • 0x6000 - 0x7FFF ( SRAM )
    這就是之前說過的帶電池的 RAM 了,該區(qū)域位于卡帶上

  • 0x8000 - 0xFFFF ( Program ROM )
    這里對(duì)應(yīng)了程序的數(shù)據(jù)铅忿,一般 CPU 就在這塊區(qū)域中執(zhí)行指令剪决,該區(qū)域位于卡帶上

2. PPU 內(nèi)存映射

image.png

這個(gè)圖簡(jiǎn)單看看就好了,后面介紹 PPU 的時(shí)候再詳細(xì)看看

  • 0x0000 - 0x1FFF ( Pattern Tables )
    這里存放了 8KB 的圖像數(shù)據(jù)辆沦,該區(qū)域位于卡帶上昼捍,由 Mapper 管理著识虚。它的作用是用來 PPU 渲染圖像的時(shí)候作為參考肢扯。有的游戲里面這塊區(qū)域是 RAM,由 CPU 寫入圖像數(shù)據(jù)

  • 0x2000 - 0x2FFF ( Name Tables )
    這里一共 4KB 數(shù)據(jù)担锤,其中 2KB 為主機(jī) VRAM蔚晨,另外 2KB 根據(jù)游戲配置為前 2KB 的 Mirror 或者卡帶上的 VRAM。這里面存放著 Pattern Table 的偏移量肛循,以此控制屏幕顯示的內(nèi)容铭腕,具體在后面的 PPU 章節(jié)討論

  • 0x3000 - 0x3EFF ( Mirrors )
    同 CPU 的 Mirror 一樣

  • 0x3F00 - 0x3F1F ( Palettes )
    這里是 NES 調(diào)色板數(shù)據(jù),用于控制圖像上每個(gè)像素的顏色多糠,具體在后面的 PPU 章節(jié)討論

  • 0x3F20 - 0x3FFF ( Mirrors )
    同 CPU 的 Mirror 一樣

NES 游戲運(yùn)行大致流程

了解了各個(gè)硬件作用和內(nèi)存映射后累舷,下面可以來探討 NES 游戲運(yùn)行時(shí)的流程了,其實(shí)只是很簡(jiǎn)單的循環(huán):
首先系統(tǒng)上電或者 RESET 按鈕按下后夹孔,會(huì)觸發(fā) RESET 中斷被盈,CPU 從 0xFFFA 和 0xFFFB 存儲(chǔ)的地址處(2byte)開始取指令運(yùn)行(具體在 CPU 章節(jié)討論),之后 CPU 會(huì)一直運(yùn)行 0x8000 - 0xFFF9 區(qū)間的指令搭伤。在每一幀渲染之前只怎,CPU 會(huì)讀取輸入設(shè)備,然后通過 PPU 寄存器往 PPU 總線上的 VRAM 寫數(shù)據(jù)怜俐,同時(shí)往 APU 寫數(shù)據(jù)身堡,最終反饋到了屏幕和聲音上

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市拍鲤,隨后出現(xiàn)的幾起案子贴谎,更是在濱河造成了極大的恐慌,老刑警劉巖季稳,帶你破解...
    沈念sama閱讀 218,204評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件擅这,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡绞幌,警方通過查閱死者的電腦和手機(jī)蕾哟,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,091評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人谭确,你說我怎么就攤上這事帘营。” “怎么了逐哈?”我有些...
    開封第一講書人閱讀 164,548評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵芬迄,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我昂秃,道長(zhǎng)禀梳,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,657評(píng)論 1 293
  • 正文 為了忘掉前任肠骆,我火速辦了婚禮算途,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘蚀腿。我一直安慰自己嘴瓤,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,689評(píng)論 6 392
  • 文/花漫 我一把揭開白布莉钙。 她就那樣靜靜地躺著廓脆,像睡著了一般。 火紅的嫁衣襯著肌膚如雪磁玉。 梳的紋絲不亂的頭發(fā)上停忿,一...
    開封第一講書人閱讀 51,554評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音蚊伞,去河邊找鬼席赂。 笑死,一個(gè)胖子當(dāng)著我的面吹牛厚柳,可吹牛的內(nèi)容都是我干的氧枣。 我是一名探鬼主播,決...
    沈念sama閱讀 40,302評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼别垮,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼便监!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起碳想,我...
    開封第一講書人閱讀 39,216評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤烧董,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后胧奔,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體逊移,經(jīng)...
    沈念sama閱讀 45,661評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,851評(píng)論 3 336
  • 正文 我和宋清朗相戀三年龙填,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了胳泉。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片拐叉。...
    茶點(diǎn)故事閱讀 39,977評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖扇商,靈堂內(nèi)的尸體忽然破棺而出凤瘦,到底是詐尸還是另有隱情,我是刑警寧澤案铺,帶...
    沈念sama閱讀 35,697評(píng)論 5 347
  • 正文 年R本政府宣布蔬芥,位于F島的核電站,受9級(jí)特大地震影響控汉,放射性物質(zhì)發(fā)生泄漏笔诵。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,306評(píng)論 3 330
  • 文/蒙蒙 一姑子、第九天 我趴在偏房一處隱蔽的房頂上張望乎婿。 院中可真熱鬧,春花似錦壁酬、人聲如沸次酌。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,898評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至剂公,卻和暖如春希俩,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背纲辽。 一陣腳步聲響...
    開封第一講書人閱讀 33,019評(píng)論 1 270
  • 我被黑心中介騙來泰國(guó)打工颜武, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人拖吼。 一個(gè)月前我還...
    沈念sama閱讀 48,138評(píng)論 3 370
  • 正文 我出身青樓鳞上,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親吊档。 傳聞我的和親對(duì)象是個(gè)殘疾皇子篙议,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,927評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容