WindowsPhone-GameBoy模拟器开发四--Gameboy显示系统分析
這次說一下GB的顯示系統,先從一幅Gb的內存分布圖說起,請看圖:
圖中紅色框框起來的部分就是這篇文章關注的部分,這一部分的內存地址從8000-9Fff,共8KB,這一部分是從來存儲背景和游戲“精靈”的數據的。通常我們認為Gb只能顯示黑、白兩種顏色,但其實,Gb還能顯示明、暗灰度,總共是4種顏色。這樣,顯示出來的每個像素點需要占用兩個bit的空間。對于Gb的顯示系統來說,屏幕會緩存256*256大小的圖片,其中160*144大小的某個區域會顯示在液晶屏上,我們算一下,要緩存的圖片的大小為256*256*2=16KB。但是我們的顯存只有從8000-9Fff的8KB,顯然是放不下的。所以Gameboy使用了某種機制,使不夠16KB的顯存也能夠顯示出16KB大小的內容,這種機制就是再顯存中一部分用來存放圖片數據,一部分用來存放映射數據。圖片被劃分為每個8*8大小的塊(tile),每個塊有一個編號,而在映射數據的部分存的只是每個塊的編號,這樣子,每個塊就有可能會被重復使用,從而達到在不足16KB顯存的情況下顯示16KB數據的目的。這就解釋了為什么在上一篇文中,我直接把任天堂的logo數據加載成圖片,顯示出來的東西確怎么看都不像是一個logo,其實加載進來的數據只是一個映射數據,而不是真正的圖片數據。
好,我們繼續。知道了gameboy的顯示機制之后再重新看一下顯存中的數據分布情況,請看下表:
| 區域 | 作用 | 
| 8000-87FF | 圖塊集1: 圖塊編號0-127 | 
| 8800-8FFF | 圖塊集1: 圖塊編號128-255  | 
| 9000-97FF | 圖塊集0: 圖塊編號0-127 | 
| 9800-9BFF | 圖塊集0的映射區域 | 
| 9C00-9FFF | 圖塊集1的映射區域 | 
圖塊集1可以用來顯示背景、窗口和精靈,圖塊集0用來顯示背景和窗口。這里的窗口指的就是160*144大小的在液晶屏上顯示的區域。
精靈
Gameboy可以控制40個精靈的顯示,每個精靈的大小為8*8或者8*16的圖片塊,同時,受硬件能力限制,每個掃描線(scan line,對這個概念理解得不是很好,希望有人能幫助解釋一下)只能顯示10個精靈。每個精靈的圖片數據存放在8000-8Fff的區域中,就是上面說的圖塊集1所在的區域。而精靈自身的屬性數據(x和y坐標等數據)則存放在專門的精靈屬性表中(Sprite Attribute Table),也叫對象屬性內存OAM(Object Attribute Memory),該區域位于內存FE00-FE9F中,OAM被劃分成40個4字節的塊,每個塊代表一個精靈。
對于精靈對象,x坐標越小則它的顯示優先級越高,對于擁有同樣x坐標的精靈對象,則通過它在OAM中的順序來區分顯示優先級(FE00的最高,FE04的次之,然后依次往下)。
由于最多只能有10個精靈在同一行上顯示,所以,在一行有超過10個精靈的時候,顯示優先級低的將會被隱藏。為了避免不使用的精靈影響正常精靈的顯示,應該把這些精靈的位置設為y=0 or y>=144+16或者x=0 or x>=160+8.
下面說一下OAM中每個精靈屬性數據的含義:
Byte0: y坐標值
Byte1: x坐標值
Byte2: 精靈的圖塊編號,對于8*16模式大小的精靈,LSB(最低有效位?)被忽略
Byte3:標志位:
| ? | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | 
| 值0 | 顯示在背景和窗口的頂端 | ? | ? | 從OBJ0PAL取色 | ? | ? | ? | ? | 
| 值1 | 如果背景和窗口關的顏色為1,2,3則隱藏 | 垂直跳動 | 水平跳動 | 從OBJ1PAL取色 | ? | ? | ? | ? | 
顏色表:
| 值 | 模擬的顏色 | 
| 0 | [255, 255, 255] | 
| 1 | [192, 192, 192] | 
| 2 | [96, 96, 96] | 
| 3 | [0, 0, 0] | 
好了,再了解完gameboy的顯示機制之后接下來就要看一下在程序上是怎么來完成從內存到液晶屏上的顯示過程了:
下表列出并說明了顯示中用到的一些特殊的寄存器,特殊是因為這些寄存器是對內存中特定地址的稱呼,而不是在Cpu中的寄存器:
FF40 - LCDC – 液晶屏控制器 (R/W)
| Bit 7 – 是否開啟液晶屏顯示 (0=Off, 1=On) Bit 6 – 窗口圖塊映射范圍選擇 (0=9800-9BFF, 1=9C00-9FFF) Bit 5 – 是否開啟窗口顯示 (0=Off, 1=On) Bit 4 – 背景和窗口圖塊數據范圍選擇 (0=8800-97FF, 1=8000-8FFF) Bit 3 – 背景圖塊映射范圍選擇 (0=9800-9BFF, 1=9C00-9FFF) Bit 2 – 精靈尺寸選擇 (0=8x8, 1=8x16) Bit 1 – 是否允許顯示精靈 (0=Off, 1=On) Bit 0 – (對于黑白的GB和SGB)背景顯示開關 (0=Off, 1=On) 對于CGB在CGB模式下,0=背景和窗口會失去他們的優先級,精靈們還是會顯示在背景和窗口的頂端。 對于CGB在非CGB模式下,0=背景和窗口變白,只有精靈任能繼續顯示 | 
注:對于Bit7停止LCD操作只能在v-blank中斷中進行,否則會毀壞硬件(我們做模擬器開發的就不需要擔心這個了J)
FF41 - STAT - LCDC Status (R/W)
| Bit 6 - LYC=LY Coincidence 中斷 (1=Enable) (Read/Write) Bit 5 - 模式 2 OAM 中斷 (1=Enable) (Read/Write) Bit 4 - 模式 1 V-Blank 中斷 (1=Enable) (Read/Write) Bit 3 - 模式 0 H-Blank 中斷 (1=Enable) (Read/Write) Bit 2 - Coincidence Flag (0:LYC<>LY, 1:LYC=LY) (Read Only) Bit 1-0 - 模式標志 (模式 0-3) (Read Only) 0: 處于H-Blank中斷中,Cpu能訪問8000-9FFF和FE00-FE9F 1: 處于V-Blank中斷中,Cpu訪問同上 2: 正在搜索OAM-RAM,Cpu不能訪問8000-9FFF和FE00-FE9F 3: 正在傳輸數據到 LCD 驅動,Cpu不能訪問8000-9FFF和FE00-FE9F。CGB模式下,不能訪問調色板數據FF69,FF6B. | 
以下是一些典型的數值切換的過程中各個模式的值:
Mode 2 2_____2_____2_____2_____2_____2___________________2____
Mode 3 _33____33____33____33____33____33__________________3___
Mode 0 ___000___000___000___000___000___000________________000
Mode 1 ____________________________________11111111111111_____
模式標志每個周期的切換順序為0,2,3,一個周期的時間大約為109uS,0大約停留48.6uS,2大約19uS,3大約41uS,這由vblank中斷沒16.6ms觸發一次,模式標志被設為1的持續時間大約為1.08ms.
用時鐘周期表示的話模式0大概201-207個周期,模式2大概77-83個周期,模式3大約169-175個周期,一個完整的模式切換大約456個周期,vblank持續4560個周期,一個完整的屏幕刷新大約每70224個周期發生一次
FF42 - SCY – 滾動Y坐標 (R/W) 
FF43 - SCX – 滾動X坐標 (R/W) 
制定256*256的背景中,哪一點作為液晶屏幕的左上角原點。兩坐標的范圍為0—255. 
the video controller automatically wraps back to the upper (left) position in BG map when drawing exceeds the lower (right) border of the BG map area. 
FF44 - LY – LCDC的Y坐標 (R)
LY指示當前那一條水平線上的顯示數據被傳送給LCD驅動,LY的值可能為0—153,當值為144—153之間時,GB處于vblank中斷之中,當寫入值時,會重置計數器 
FF45 - LYC - LY 比較 (R/W)
GB不停地比較Lyc和Ly寄存器的值,當兩個值完全一樣時STAT寄存器的Coincidence Flag位會被設為1,然后如果開啟了STAT中斷的話,會請求該中斷 
FF4A - WY – 窗口Y坐標 (R/W) 
FF4B - WX – 窗口X坐標 (R/W)
指定左上角的窗口位置,當Wx=0—166,Wy=0—143時,窗口可見
下面通過一張圖來說明Scy,SCX和Wy,Wx之間的關系:
FF47 - BGP – 背景調色板數據 (R/W) – 非CGB模式,即黑白模式
該寄存器用來給背景和窗口的圖塊的顏色編號賦上灰度值
| Bit 7-6 -Color Number 3 Bit 5-4 - Color Number 2 Bit 3-2 - Color Number 1 Bit 1-0 - Color Number 0 | 
顏色值參考上面的顏色值表
FF48 - OBP0PAL – 0號對象調色板數據(R/W) -非CGB模式,即黑白模式 
FF49 - OBP1PAL - 1號對象調色板數據(R/W) -非CGB模式,即黑白模式
這兩個寄存器分別給0號和1號精靈調色板賦上灰度值,每個位代表的意思和BGP寄存器一樣,但最低的兩位是不使用的,因為00代表精靈是透明的
好,寄存器的介紹暫告一段落,現在來計算一下。不管是使用圖塊0還是圖塊1,GB的映射空間的大小都是3FFF=1024,然后GB的背景是256*256,同時背景是由8*8的圖塊拼起來的,所以總共需要32*32個圖塊。而32*32正好等于1024,由此可知通過解析圖塊映射區內的所有圖塊的編號就能夠得到要顯示的背景的像素數據了。
由今天的分析可知每個圖塊的大小是8*8個像素,占用的空間是8*8*2個bit,共16個字節。下面通過一副圖來說明:
由上圖,其實每個像素點的信息表示的是一個索引值,用來索引在調試版的顏色,調色板才是用來實際存放顏色信息的地方。
好了,今天的筆記的就到這吧,本來想先完成模擬Cpu部分的指令的代碼再來學習顯示的,不過在寫代碼的時候發現,如果沒有顯示的話都不知道實際模擬的對不對,所以就只能先學習顯示部分的知識然后再去寫代碼了,有了輸出差不多就可以判斷自己的代碼是不是正確了。
下一回將會對今天的知識用代碼來進行實現,就是模擬gameboy的顯示系統了,希望不要太難,呼,老天保佑。
轉載于:https://www.cnblogs.com/li0803/p/3283727.html
總結
以上是生活随笔為你收集整理的WindowsPhone-GameBoy模拟器开发四--Gameboy显示系统分析的全部內容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: 美股周四:热门中概股普跌,阿里跌逾5%
- 下一篇: 盒马启动上市计划:预计6-12个月内完成
