星期二, 3月 30, 2010

VRAM & DMA

因為有人問  所以在此就我所知的做簡單解說
如有誤   歡迎給予指教 (畢竟我也只是個中文化路人....)

又因為我只對皇騎系有興趣  所以這邊僅以SFC為例來解說
(GBA上的TOG沒用到debugger  所以不清楚......)

以SFC為例來說
通常會把字庫圖像放到RAM(7E0000~7FFFFF)裡
再用DMA一次丟到VRAM中  然後輸出畫面


ROM --解讀字庫--〉RAM --DMA--〉VRAM  --〉螢幕畫面



VRAM中每個8x8字庫圖像(tile)會對應一個tile編號
依模式不同  VRAM中可用的tile數量
與及每個tile所佔的byte數也不同(通常是8x2或8x4個bytes)
在繪製畫面前  SFC會把用到的tile編號
依畫面顯示順序存在VRAM的另一個地方
VRAM中的字庫tile   大致會以下圖所示方法顯示




















因為VRAM只有64kB  所以一次可以放進去的字不多
加上其他圖標、欄框、背景也要佔tile數量
如果只有平片假名  大概還能全部塞進VRAM
但如果是大量的漢字  通常會把畫面用到的字先存到RAM
再把這些挑出來的字存到VRAM

所以
如果遊戲因為只用到少數平片假名文字
而採用一口氣全部讀到VRAM裡的作法時
就沒辦法透過改字庫pointer等方式來擴增可用字數
因為程式無法一次讀更多字進去
只能用ASM改寫原程式  只挑出要用的字到RAM裡
用DMA把這些字送到VRAM中
並且根據這些字在畫面上該出現的位置
填寫對應的tile編號 

基本上  除了上面黃字的Case
中文化好像不太需要去動VRAM這一塊
DMA倒是比較常用到
傳輸大塊連續資料很快速方便

要修改VRAM中的資料不是很直覺
必須要去存取幾個特定位址  才能更動裡面資料
參考連結1
*參考連結2


舉例(這是國外某文章的範例  借花獻佛一下):
如果要從ROM位置$18000的地方
複製128個8x8大小的4色(2bytes)文字
到VRAM中$0000的位置時
(也就是共複製$800 bytes到VRAM中$0000的位置)
可以用下面這個函式完成

#$表示16進位數字  $表示16進位位址的值
除".w"表示處理資料為2bytes外  其餘皆為1byte 

    ldx.w #$0000    ; 設定VRAM pointer($2116)為#$0000
    stx $2116       
    lda #$01        ; 設定DMA control value($4300) 為 "normal"
    sta $4300
    lda #$18        ; 設定DMA至VRAM($2118)
    sta $4301        ; 參考上面的*連結   
    ldx.w #$8000    ; 設定DMA來源位址($18000)
    stx $4302
    lda #$01       
    sta $4304
    ldx.w #$0800    ; 設定DMA要傳的總Byte數
    stx $4305
    lda #$01        ; 經由channel 0開始DMA傳輸
    sta $420B

這邊要注意的一點是
DMA傳輸有0~7八種channel    各自有對應使用的特定位址
如果是經由channel 1做DMA傳輸  $430X要改為$431X
如果是經由channel 2做DMA傳輸  $430X要改為$432X
以此類推 $420B亦如是

雖然前述例子是ROM --DMA--〉VRAM
但當然也能RAM --DMA--〉VRAM  作法上沒啥改變
我處理OB就是把要顯示的字先從ROM挑好排到RAM中
再用DMA傳到VRAM

DMA也能用在ROM --〉RAM或RAM --〉RAM(單純移動位址)
這時就有一個專門op code處理
不用像傳到VRAM中那麼麻煩

星期日, 3月 28, 2010

結果我還是認真了.....

結果我還是認真了....
Orz

原本8x8的平片假名
目前除了戰鬥畫面以外
都改成8x12文字顯示了
(這字庫還真沒白刻....)

可用字也擴增到500字
大概勉強剛好夠用...

如果16x16文字好擴充
我想會做中文化吧





不過在那之前....
得先弄完TO才行....



在弄TO之前....
得先玩完戰神3才行
wwwww

星期二, 3月 16, 2010

Just Try

因為校對TO真的很無聊
所以我稍稍了一下OB
好換一下口味

基本上
我是能不碰ASM就不碰
一來看code流程很無聊
二來替代函式容易出包

所以可以的話
我一般偏好按原算法
重新壓縮資料回原空間
這樣幾乎不會衝突當掉


不過......
偶爾還是有不用ASM寫新函式不行的情形.....
OB的狀態畫面就是其中之一

這個畫面主要會放512個(事實上不止)8x8圖像到VRAM
再選用這些8x8圖像拼出狀態畫面
其中作為字庫的部份近200個    用來放平片假名英數字等
(其他內容是職業icon、邊框、血條等....)
用兩個8x8圖像顯示8x12中文的話   塞不到100個字就爆了

而我估計  大約要近400個8x12中文字  
才能涵蓋所有姓名、職業、攻擊名、裝備名等用字
就算VRAM切換成mode 0  讓職業icon改用4色表示(原16色)
還是無法一次讀進4倍大的中文字庫

最後只好改寫新函式 
把人名、職業等所用的圖像編號鎖死成連續編號
把當下要用的字依序排好繪至RAM裡後
一次用DMA轉進到VRAM中的對應連續編號位址  
(理論上這樣就沒有了字庫大小的限制)
只是這函式僅能用於狀態畫面    其他畫面的要再改寫一下....

OB目前看來  最麻煩的就是這4倍文字量需求的狀態畫面
其他劇情對話等雖有壓縮    但很快就被找出位址跟演算法
狀態畫面則是花了我兩天時間才初步解決
不過這不代表我會繼續做下去就是了    
目前只是為了轉換心情用而已.....
何況戰神3也要出了.....

另外關於SFC ASM debugger
我是推薦用snes9x1.43.ep9r8比較方便
只可惜VRAM資料好像不能存出?