1. 程式人生 > >【原創】NES第一波:如何用通用型6502巨集彙編器,制用NES/FC遊戲。

【原創】NES第一波:如何用通用型6502巨集彙編器,制用NES/FC遊戲。

  在163的部落格關了呀。在這邊重新開張了。

  以後若網友有什麼要長篇解答的問題,也在這兒作答。

  作為第一波原創文章,我打算做一次小白示範。那就是一步一步的展示某個彙編編譯器的用法。

 

  一、科普

  很多人認為程式與CPU無關,那是受C語言的影響。其實,不同的CPU,它的指令集也不同。

  而彙編則是針對指令集的,可以認為彙編指令就是CPU的指令。當然還有定址不同。(當然,真正的CPU指令是機器碼。因為彙編是最緊貼CPU的,我就做理所當然了。有興趣的朋友可以學一學彙編與機器碼的編譯關係,以後當一名HACK大神。)

  還有一點要提一提的,那就是即使同是6502CPU不同巨集彙編器,其程式碼型式有微小的區別。這自然是因為沒有一個6502組合語言標準所造成的,像C語言有兩個標準,那還好一些。大家用習慣就自然瞭解。而巨集指令方面,那各個巨集彙編器有較大的不同,可以說是八仙過海 -- 各顯神通。巨集指令就是字首帶點的指令。

 

  關於NES檔案的結構,大家必須瞭解一二。NES檔案是由卡帶Dump而來的。意思是說從卡帶上的ROM讀取位元組,儲存成檔案,其間還需要解密;還要識別卡帶的電路結構(卡帶電路並非都是一個樣,恰恰相反,每家廠商都有自己獨到的設計,真是五花百門。),卡帶的一些資訊定義成iNes檔案頭。

  NES檔案結構,我們稱為iNES。它由 : 檔案頭 + PRG_ROM + CHR_ROM ,依次連線而成。

  我們這次介紹的是Mapper=0的NES製作方法。這是最基礎的,所以之後的變化都是從這兒開始的。

  Mapper又是一個新名詞,Mapper是一個8位的ID號碼,指代“卡帶的電路結構”。也就是說,當時Dump的人,簡單的將不同的電路結構定了一個序列編號,用作區分。而0號就是最初任天堂的卡帶結構,是最簡單的,最原始的,沒有變化的。也可稱之為原型。

 

  檔案頭的事,暫不細說。

  程式 (我們稱為PRG_ROM) 按16K為單位,當Mapper=0時,程式Bin可以是16K或32K。也就是說程式的長序最多也只能是32K的了,這個限制。大家不用擔心寫程式時,生成的長度不規整。後面有辦法的。不過超長的話要學學切頁,那是Mapper>0的後話了。

  圖形 (我們稱為CHR_ROM) 按8K為單位,當Mapper=0時,圖形Bin可以是0或8K。0是什麼意思,是沒有,可以不要的意思。那麼沒有圖形,是否則黑屏呢。不是的,能夠顯示圖形圖案和畫面的。那麼不要了CHR_ROM,那麼卡帶上並不是空白,而是補上一個8K的CHR_RAM。大家對ROM和RAM應該瞭解。CHR就是圖形的意思。這句話可以理解為,不要ROM了,換上RAM,圖形庫就不是固定的了,可以由程式轉移不同圖形到CHR_RAM裡面去。那麼顯示就更加靈活了。不過用上RAM就不能切頁圖形了。這話以後就明白了。

 

  二、下載

  科普結束。這次我要講解的通用型6502巨集彙編器是"6502 Macroassembler & Simulator"。中文意思是“6502巨集彙編與模擬器”,名字有點長,我們以後簡稱"6502Sim"。下載可以我的"網盤"。具體在 " NES Tool Kit " 資料夾中。

  本文下面提到的工具,還有後續博文用到的NES工具一鼓腦的塞進這一資料夾,直到塞滿,才放到同名的2號資料夾。

 

  三、介紹主角

  介紹:6502Sim,作為模擬器,可以讓程式碼在上面單步執行。從而學習6502彙編,看看CPU中各個暫存器的變化,還有棧的變化。從直觀的角度學習彙編。除錯自然要產生機器碼,這個機器碼可以儲存下來。這就是我們需要的功能了。總之是一個非常好的工具。我提供的這個是中文版。不可避免一些極簡單的英文保留下來。

  我們看看6502Sim的玉照。見圖1。

圖1 6502Sim

 

  可以看見只要游標點到某個指令上,就會顯示對應的指令解析。只要在選單”幫助“上,點”動態指令幫助“即可。很貼心的功能。我喜歡。幫助為什麼是英文?哈哈沒有漢化吧,反正不是我漢化的,所以大家要適當學一些英文。或者用機翻,自己解決吧。

  可惜沒有行號列,若有編譯報錯,那要看右下角的座標資訊去找了。Ln是行,Col是列。

  注意:6502Sim規定指令必須縮排一格或一個Tab。我也不知為什麼,這可能就是作者的格式,幫助上沒有任何提示。我初學時常犯這個錯誤。報錯也沒有說清楚的,要問人才知道。坑!

 

  四、示例

  苦水吐完。我們來看一看還需要一些什麼鬼。

  這次我提供完整的示例程式碼,和一個用來填補的圖形檔案,其實本示例為了簡單起見,不打算顯示圖形。不過為了後面的學習,還是打包一起。反正批指令裡面用到了。

 

  這次的示例是葉楓的初期作品"生日快樂”音樂演奏。

  程式碼相對簡單,便於示例。(葉楓沒有給我們原碼,要我們自己去反彙編。淚奔呀。)這個程式碼由“不是女孩”提供。我小改了一下。我改檔案頭部分的型式,也是為了便於學習。我打包整套檔案,大家去我的網盤下載就可以(前文有連結)。也是在“NES Tool Kit”。

  工具和檔案,我是一起打包的。因為我的網盤有檔案數量限制。又是坑。下在是必須的工具和檔案清單。

 

 表1 清單

序號 型別 名稱
1 工具 6502Sim
2 工具 NesInfo
3 檔案 生日快樂.65s
4 檔案 ascii_2.chr
5 檔案 make.bat

 

  其它的檔案就是自己造出來的了。其實make.bat也能自己寫,不過相對有點複雜。我還是留著,還有一個檔案頭記錄我也保留了。等下會說到。

 

  五、步驟

  這是大家最關心的事情了。

  5.1 程式碼的編輯工具。

  編輯工具用6502Sim就行,也可以用npp,記事本等等。有一點記好了,編碼格式要求是"ANSI"。這一點非常重要。小白就用6502Sim,預設就是ansi格式。若用其它工具編輯,那麼儲存字尾名改為" .65s ",再用6502Sim開啟。

  為什麼要是65s字尾名?這只是為了區別彙編程式碼的格式。上面說過了,不同巨集彙編器,對應的格式有區別,為了不混淆。若是像txt字尾名,用6502Sim也能開啟,只要檔案型別選“ *.* ”就行了。

  5.2 程式碼編譯和生成。

  開啟檔案後,點選單“模擬”-“編譯”。記好這個圖示(三張紙一個下箭頭),在快捷欄直接點選也行。沒錯的話,只會閃一下,也沒有什麼別的提示。唯有快捷欄上編譯按扭旁邊的Debuger按扭(一個甲蟲的樣子)亮了。

  以後除錯就用這個甲蟲按扭,這次不提。

  接下來要生成bin檔案,即65b檔案。點選單"檔案"-“儲存程式碼”。這次的例子,程式碼是從$C000開始的,那麼直到$FFFF。(這就是16K了,那麼這些程式碼自然不是剛好16K,完全是少於16K的,其中的空白部分編譯時自動補全了。)

  填好檔名,檔名不要有空格,為了後面的方便,否則在make.bat裡面給檔名加引號。我不建議給自己添麻煩。本例用的檔名是 BinaryCode 配合後面的make.bat。

  選好型別是“*.65b”,這一個不能錯。

  還有還有,還要點“選項”。非常重要。不能漏。選項中,填“開始地址” 0xC000,結束地址“0xFFFF”,程式碼長度會自己算好。

  最後,點確定,再點儲存。OK,這樣程式Bin就生成了。(若是切頁的話,眾多的程式Bin,按次序連線就成了PRG_ROM。現在只有一個Bin,那它就是PRG_ROM。)

  5.3 圖形Bin檔案

  即作為CHR_ROM。這已經有現成的了(ascii_2.chr,有4K),再說這次示例不作圖形顯示,所以這個圖形Bin也就是充數的。為了簡單起見,下次重點再說說圖形顯示的事情。圖形Bin的字尾名是chr,因為我是用一個叫YYCHR的軟體生成的。

  這檔案只有4K,為了補足8K,後面連線2次。下面詳說。

  5.4 檔案頭的製作

  我們用的軟體是我自己開發的。我們來看看樣子。開啟NesInfo程式,見圖2。

圖2 NesInfo

  

  填上這次,我們要的數值:

  這次我們只談Mapper=0,那麼填0就可以。

  這次程式從C000到FFFF,共16K,那麼PRG ROM填1就可以,1x16K的意思呀。

  這次圖形定為8K,當然,沒有也行,不過為了完整演示,還是加一個補足。CHR ROM填1就好了。

  映象,S-RAM,4螢幕,TRAINER用不上,預設好了。

  這裡簡單解釋一下,大家暫時不用追求深入瞭解。

 

表2  名詞

  釋義
映象 背景影象的左右或垂直映象,滾屏用的。
S-RAM 帶電池的SRAM,記錄遊戲資料
4螢幕 4屏聯動,廢掉映象的作用。
TRAINER 教練,就是增加512位元組的ROM,外加一些遊戲示例等。實質是多了一點空間。電路設計麻煩了一點兒。

 

  填好之後,為了以後方便,先儲存一下。點選“高階”。見圖3。

圖3 NesInfo 高階

  按下“另存資訊”,就儲存一個ini檔案。

  (本示例包中,保留了head.ini。可以直接按這個“開啟”,載入之前定義好的檔案頭。)

  最後要生成bin檔案才行。我沒有設計生成彙編.db形式的,否則生成數值,直觀一些。我這個程式功能有點多,好像能夠用行指令,那麼就能寫進make.bat,不細說。

  生成Bin,就是按“儲存Bin",就行,他會以開啟的檔名,按同名儲存成bin,生成後沒有太多的反應,就給你一上提勾圖示就算了。

  那麼,你開啟我的head.ini,就會生成一個head.bin。否則沒有名字,它會要求你寫一個的。本例中名字是head.bin,這要配合後面的make.bat。

 

  5.5 Make批檔案

  用批檔案的原因是,因為要用到COPY指令。開啟win附件記事本。填寫如下

copy /b head.bin+BinaryCode.65b+ascii_2.chr+ascii_2.chr Day.nes
pause

  head.bin是我們生成檔案頭,

  BinaryCode.65b是我們生成的程式,

  ascii_2.chr是圖形,本示例用於充數,

  Day.nes是生成的nes檔名。

  記得要寫+號,我不曉得檔名出現空格會什麼情況,也不知加引號頂不頂用。反正我的檔名不加空格,那就對了。

  後面一個暫停指令,讓你看看過程出沒出問題。

  儲存成檔案make.bat。檔案型別選*.*,編碼選ANSI。選錯了出問題,不過ANSI是預設的。不用操心。只是你有可能檔案型別忙記選了,儲存的還是txt。變成make.bat.txt。

  那麼儲存後再重新命名了,哈哈。

  那麼讓我們來雙擊make.bat

  

  正常的如下。見圖4。

圖4 正常的結果

  按任意鍵,就結束。nes就生成好了。可以用模擬器開啟。就能聽到生日快樂音樂。

&n