2016年10月26日 星期三

Nes Rom header

特定檔案類型的標頭照理來說應該要是一個嚴謹而且有組織單位背書的標準規範,但這種事情其實也不是那麼一定,特別是從社群發展的東西有時候牽涉到各個社群的風俗習慣或是發展者的個人想法,在沒有特定單位出面嚴格處理標準化的制定問題下,就會產生標準不一樣的問題,這對開發者來說並不是好事情.

以任天堂的ROM檔來說目前最主流最主流使用的header格式稱為 INES header,標頭共16Bytes大小,緊接著後面連貫的是RPG-ROM與CHR-ROM實際內容,理論上搞定INES header就可以,但實際上這格式內容卻有些新舊衝突的問題要謹慎處理,這東西是由社群和領導制定者產生的東西.

ines header最大的公約數是開頭一定是 'N' 'E' 'S' \0x1a 這四個字元(檔案內容byte 0~3),接著是一個byte的RPG-ROM count (byte 4) , 接著是一個byte的CHR-ROM count (byte 5) , 以及擁有mapper與rom重要屬性flag的 byte 6 與 byte 7 , 接著 byte 8 ~15 是實作上比較沒那麼重要的資訊,輔助性質的一些東西,隨著 ines版本或是各dumper者習慣而有資訊多寡不同,簡單來說如果你找相關介紹資訊,會發現byte 8~15 的定義有些差異 , 通常舊的ines header byte 8~15內容都為 0x00,新版的 nes 2.0 ines header延伸規範則會有新的屬性.

撇開新版的ines 延伸規格 nes 2.0不談 , 就算是舊版只討論 byte 0 ~ 7 的內容,也還是會有些衝突問題會導致mapper解讀錯誤,最主要是早期某些rom 對 mapper的解讀定義是不會理會到 byte 7這邊,從 byte 7 ~ byte 15 會填入 DiskDude! 這幾個ASII code , 如果你拿到這種rom用新的正確規範去解讀,就會踩到地雷,從mapper 0 變成 mapper 64.


Early ROM processing tools were not aware of Flags 7 because the earliest emulators ignored it. For example, one tool put 0x44 (ASCII for 'D', the first character of "DiskDude!") here. This confuses newer emulators, which combine the nibbles from Flags 6 and Flags 7 to form an incorrect mapper number. NES 2.0 redefines the unused bits to always equal binary 10, which happens not to match any of the patterns used by these ROM processing tools:

簡單來說需要有一個判斷方式去對這種特立做解讀mapper上的修正.

流程大概是 

1.如果 byte 7 低4bits 為 0 , 進行標準ines規範maper解讀,
mapper = (byte)(((byte6 & 0xf0) >> 4) | (byte7 & 0xf0));



2.如果 byte 7 低 4bit 不為 0 ,且   byte 7 bit3為1 & byte 7 bit2為 0 ,認定此為遵守nes 2.0延伸規範的header定譯內容.

3.如果 byte 7 低 4bit 不為 0 , 且byte 7的 "bit3與bit2"不為 "1與0" , 則是早期非標準的版本.
mapper = (byte6 & 0xf0) >> 4;



以上.....社群零散發展起來的東西其實就會有這樣的狀況,就算組織單位也常常會有規範衝突的問題,但又是別種層面的狀況.

其實ines的規範標準並不是說很方便完整,也有新的規範方式出現,不過並不普及,模擬器多數實作也不一定會支援,如果我是當初的制定者,我大概會給mapper一個完整的byte,而屬性控制則獨立一個byte分開來放置,不需要把mapper硬切高低 4bits 放置到兩個 byte 跟 屬性控制bits混雜,有可能最早時候沒考慮到 mapper的數量會超過於 4bit範圍這問題.



2016年10月3日 星期一

任天堂紅白機模擬器



去年年初撰寫了任天堂紅白主機的模擬器雛型,大概如上圖,好像有一回事,但其實相當不完善,任天堂紅白機跟GameBoy初代兩台主機相比,若是以初學來說,我會建議學習選擇gameboy做為起步入門的嘗試,因為即使到現在我都還沒辦法將紅白機給摸透 (悟性不夠阿... orz....) , 在整個系統的 timing 模擬設計與記憶體mapping.register與vram address相互影響要摸熟都有一定的複雜度,能實做擁有正確畫面 scroll 效果需要不少功夫的, 這也就是為何我 demo 的遊戲畫面只選擇定格於同一背景的類型.

總覺得這東西沒有好好完成很可惜,想繼續完整實做,這次也放棄單靠閱讀文件來做全部理解 ,應該會參考別的project來輔助理解,甚至部分改採移植的動作,再慢慢理解.

8086模擬器專案目前在io周邊裝置實作上遇到一些瓶頸,也覺得有點疲備,先換個口味吧....如果沒又荒廢掉的話,希望能夠在今年年底或是明年初推出正式的版本.

2016年9月17日 星期六

Apr8086 雛形Demo

https://dl.dropboxusercontent.com/u/61164954/project/Apr8086/index.htm


趁著連假這幾天趕了一下進度,開始檢查和修正之前寫好的8086 cpu code指令模擬的bug,利用fakePC這個project加以修改,匯出執行每一個步驟的各暫存器的log,用來檢查自己的專案正確性,持續修正到將BIOS畫面輸出,由於尚未時做控制周邊IO,目前會讀到IO的回傳部分是依賴fakePC記錄輸出(建立步驟與io回應的關係),記錄了步驟從從1~1100000 其中會回傳io read的部分,順利到達系統記憶體checking階段,然後就暫時先停止運作,等待日後更完整實作.

目前撰寫起來,雖然8086 cpu模擬也還稱不上困難(相對於arm解碼, 8086已經算是很好處理了),但這顆16bits的cpu相較前身8008來說整體運作已經付雜很多,主要是x86的節區運作觀念,幾個節區暫存器怎樣的狀況下使用哪個,又記憶址分成 effective address (EA) 與 physical address (PA),每種狀況下換算用的方式又盡不同,以及所謂的prefix指令,最後就是雜七雜八的定址法,跟8bits cpu時代相比完全不可一概而喻了,但CPU要用軟體模擬只要規則搞懂,flag沒搞錯,基本上也就是規格書怎麼描述,你就依樣畫葫就是,所以錯得再怎麼多,只要有耐性,跟別人的的steps log比對,看看問題出在哪還節哪個指令,慢慢修正下去,都還可以處理.

比較麻煩的,對於像我這種悟性比較不足.硬體接觸經驗又相對不足的人來說,幾個周邊裝置io的了解與模擬,我認為才是後面階段的大重點.

由於這並非是我我的工作,只是我的興趣與休閒,因此之後進度也沒很刻意要求,一切隨意.

2016年8月17日 星期三

8086 指令集模擬完成後

單只有CPU不能稱上是一部電腦,若只是把指令集模擬完成,還是沒有任何作用,於是開始進入相關電腦周邊控制模擬的階段,簡單來說cpu可以透過 IN OUT 兩個指令對 IO port 做溝通,在8086中這個 IO port 很相似於一個獨立的記憶體介面位址(只是讀寫的是裝置) , port 位址從 0x0 ~ 0xffff  (不確定 8086之後是不是也是這樣) , 鍵盤.滑鼠.軟碟片.顯示卡...有的沒的基本周邊都要透過 IO port去溝通存取控制, 而且各自的控制器都有各自的規則特性 , 需要去了解 , 完成了cpu的指令模擬真的才完成整個專案的一小塊部分,所以還有一段路得走.

列出參考  http://wiki.osdev.org/I/O_Ports

每一個裝置控制器要了解又得花不少功夫(至少對我這種平凡的人來說)......

其實後來看別人的project sources做法,有些似乎沒有真正完整實做這些周邊的功能特性(控制器規則等等),只是把DOS跟BIOS用到的中斷服務最後結果給做出來,簡單來這算是一種取巧的做法,這種作法有利有弊,優點大概就是程式較為簡略些,我只要管呼叫這個中斷要得到什麼正確的結果,更底層 IN OUT對周邊的動作控制細節不用真的處理到,速度理論上也比較快.缺點大概是相容性有限,如果是別的作業系統中斷功能定義跟DOS不同,當然就有問題 ,這種差異大概就像是 Dosbox 和  Bochs 兩種實做的差異 , dosbox官翻網站所言

https://www.dosbox.com/links.php

 Bochs emulates a full x86 based pc. Unlike DOSBox that tries to mainly emulate dos programs.

至於現在,因為這專案偏於學習使用,剛好趁這機會也多了解一些東西,姑且先以 full x86 base pc為開發目的,若以後有別想法或是難以實現,視情況再修改做法.

2016年7月12日 星期二

GNU lightning jit 應用例子

對模擬器的喜好來自於對遊戲主機童年時期的熱愛(約佔70%),以及本身是資訊人,多少對技術方面的東西會更有興趣些,所以偶而會找找相關資訊看看.

其中剛好看到了一個利用JIT加入效能的範例如下

http://jeffq.com/blog/nds4droid-release-35-beta/

用的是 GNU lightning 這套JIT加速library

https://www.gnu.org/software/lightning

相當有趣.

隨著資訊技術這幾年的發展,很多新的技術都慢慢被應用在模擬器的開發上.

8086 指令解碼

x86 模擬器裝案的進展荒廢許久,最近把顯示卡的部分K一K了解一下,打算重新再來過,反正姑且一試,第一個步驟還是習慣先從CPU本身的核心開始撰寫起,當然16Bit的CPU指令複雜度已經沒像8bit CPU那麼容易了,但我個人覺得比起ARM,x86的8086這顆cpu指令解碼複雜程度相對來說還是簡單許多.

8086這顆cpu的指令已經無法使用拿指令的第一個byte用窮舉法搭配 switch case的方式來做完全的剖析,一定會有重覆的衝突,不過無所謂,只有少數幾個指令需要用第二個byte的 bit 5~3 這三個bits再做一次分析,還是可以用窮舉法,只是某幾個地方需要用到兩層.

最聰明的decode策略應該是完全了解指令的格式規則,然後用樹狀關係圖去分層出解碼的步驟,但這種方法未必會比較快,最笨的窮舉法直接靠table查詢,理論上應該是最快,但就是怕缺漏掉一些項目.

8086 格式
http://aturing.umcs.maine.edu/~meadow/courses/cos335/8086-instformat.pdf

datasheet
http://www.ece.cmu.edu/~ece740/f11/lib/exe/fetch.php?media=wiki:8086-datasheet.pdf

286開始有保護模式,386第一顆32bit cpu,486直接附帶浮點函數計算能力與相關指令,一越新的硬體越複雜,先從簡單開始,至少8086已經可以跑win 3.0了 ( 3.1需要跑在最低286上).

最後不得提醒一下,不要以為官方出版的資料或是規格書之類的東西就100%不會有錯誤,實際上就還是會有可能遇到,而且我在兩分資料中各遇到了兩次....

舉個例子來說


2016年7月7日 星期四

x86 電腦研究心得

看 8086tiny 這專案剛看會給人誤會,以為要模擬PC X86模擬器不會是太複雜的事情,再追究下去,會發現這專案用了很多相當聰明的方式簡化了所包含的CODE數量,但簡化的道理卻因為對硬體沒有夠詳細的了解,也不知所以然來,於是放棄了以這專案為學習的開始,改以 V86 https://github.com/copy/v86 這款js pc的模擬器為學習對象,完整度可以執行到win98不是問題,重點是很紮實地去跑了system bios跟vga bios,追著這專案跑,一跑到VGA那塊馬上發現自己的無知,原來電腦VGA顯卡還是有很多學問,很多對應port的Register各自有各自的功能,然後記憶體排列的原理和規則等等,要搞懂也不是那麼簡單,像這種東西在早期有很多相關的書或是資料,但現在可以找到的說明越來越少,能找到的多數是英文,但解釋的也未必很清楚

http://wiki.osdev.org/VGA_Hardware
這篇有很多vga卡 port的作用和記憶體屬性規則在各種顯示模式下的說明

很多東西還得再細看和實際demo測試....不是說那麼好懂.