知乎日報:FC 遊戲機的工作原理是怎樣的?
扼要的寫一下顯示部分的技術原理,尤其是設計緣由和精妙之處,儘量使外行人也能看懂:
(一開始是預備知識,我至少假設讀者理解二進位制,二進位制位 bit,位元組 byte,十六進位制表示等)
顯示的基本單元是畫素(Pixel),我們看到的幾乎所有顯示器顯示的東西都是許多畫素組成的,可以把它們想象成一個個小方格,整齊的排列在顯示器上:
比如這幅 Lena 區域性經過放大後,可以看出每個畫素就是顯示一個色彩的方塊。當今我們常見的顯示調色有 256 色,或者真彩(True color)24 位色。 所謂 256 色就是一個位元組儲存 256 種顏色,而真彩色是三個通道從暗到明各 256 色,然後三原色組合在一起。我們需要 3x8 個二進位制位來表示。三原色共 3*8 bit
FC/NES 的主要硬體包括一顆 MOS Technology 6502 晶片,以及被稱作 PPU (Picture Processing Unit) 的圖形處理晶片 RP2C02/RP2C07。PPU 有 2KB 的外部 RAM 來儲存顯示影象和其它輔助資訊,256 位元組的內部 DRAM 儲存 sprite*,32 位元組的內部 SRAM 儲存調色盤 *。
* Sprite,常譯作精靈。。。 指包含於場景中的二維影象或動畫,NES 裡基本就是會動的各種角色了,比如 Super Mario 裡瑪里奧自己,各種怪什麼的。
* 調色盤 Palette , 通俗的講就是顏色編碼表。NES 的 Palette 見下圖(中文維基上說 48 種彩色+5 種灰階是錯的。。。只有 4 種灰階,整個右邊三列的色彩 RGB 表示都是 [0,0,0],編碼 20 和 30 的都是 [255,255,255]):
按照今天的顯示技術來看,FC 的彩色技術簡直就是奇技淫巧大集合。只有 2KB 的視訊記憶體和 2KB 的主存,基本完全無可能裝下彩色影象。
(NES PPU)
做一個簡單計算:
解析度 256x240 = 61440,即畫面上有這麼多個畫素點。(忽略 NTSC 系統損失的 16 行,PAL 系統上是 256x240)
我們如果只顯示黑白,即每個畫素非黑即白,那麼單畫素一個 bit 就可以了,這麼大的解析度下,一共需要 1 * 61440 / 8 / 1024 = 7.5KB,要是直接這麼幹黑白點都裝不下主機視訊記憶體,當時好點的電腦勉強差不多。
假設我們用現在非常普通的 256 色,即 8 個二進位制位,一個位元組儲存,整個畫面 61440 / 1024 = 60KB,這在 FC 時代是任何普通機器都不能直接做到的。
為了顯示彩色,當時的不同機器有各種技術手段,可以說八仙過海各顯神通。FC 用的第一種手段叫做 Color Cell,具體來說:
將整個影象分割成許多 8x8 的小 cell (或者叫 tile)
每個 cell 內至多有 4 種顏色
這樣,每個畫素只用 2bit 來儲存色彩,然後對一共 32x30 = 960 個 cell 再分配色彩編碼,指示有哪幾種顏色。
舉個栗子,我們熟悉的惡魔城 (Castlevania, 1986) 開場:(圖片來自[dustmop.io blog])
圖中最小的格子(所有明暗線分割出的)即一個 cell 或 tile,四個 tile 組成一個 block(僅亮線分割出的)。圖中一共用了 10 種顏色。你絕對找不出用了超過 4 種顏色的 cell。
再看一個我頂我頂:
編碼後的 cell 表將儲存在視訊記憶體所謂 name table 區域中,剛才的惡魔城開場的區域編碼成形如下圖所示:
FC 第二個高明的地方在於領先時代的滾屏技術,由於 PPU 內部有兩個(映象後是四個)name table 來儲存 cell 表資訊,我們可以一直預先儲存著超過顯示部分的內容,在玩家或者程式觸發滾屏操作後,透過向兩個暫存器 PPUSCROLL 和 PPUCTRL 寫相關資訊,即可移動遊戲鏡頭。
在 FC 之前的主機,滾屏操作幾乎都要覆寫整塊螢幕,代價高昂。FC 的出現同時使得動作、射擊型遊戲得到極大發展。
最後一個部分是遊戲中運動的 Sprite,儲存於顯示卡的特定內建儲存區域,通常單個大小為 8x8 或 8x16,我們看到的主角們大都是多個 Sprite 拼到一起的,比如 Mario 實際上是 4 個 Sprite 拼出來的,只是在程式中保證不會散架。
Sprite 的顯示是覆蓋背景的,無論背景如何設定,在 PPU 進行 Sprite 探測後都會將對應位設定成 Sprite 的色彩。
最後,btw,基本上所有的 FC/NES 開發資料都能在NES dev和其附屬 wiki 上找到,只是沒有相關專業知識可能比較難啃。
國人的《任天堂遊戲程式設計探秘》一書總的來說還是比較詳細的,然而很多關鍵之處卻語焉不詳,且花了很多篇幅教怎麼寫程式碼。對於外行來說還好,對於專業人士就基本無用了。更重要的是,這本書幾乎沒有講任何 Rationale 的東西,對於真正的學習是災難性的。