第十九章 破解6502密碼(中)
一天后,橫井俊平終于看到了讓他牽掛了一晚上的答案。看到這個(gè)答案的時(shí)候,他差點(diǎn)要給自己一拳,因?yàn)檫@個(gè)答案點(diǎn)居然是最基礎(chǔ)的理論。
“堆棧???”
不錯(cuò),王秋陽(yáng)給出的答案就是堆棧。
所謂堆棧,就是在單片機(jī)應(yīng)用中,有一個(gè)特殊的存儲(chǔ)區(qū)。它的主要功能是暫時(shí)存放數(shù)據(jù)和地址,通常用來(lái)保護(hù)斷點(diǎn)和現(xiàn)場(chǎng)。這個(gè)存儲(chǔ)區(qū),就是堆棧。
但堆和棧,又有些許的不同。
堆,是隊(duì)列優(yōu)先,先進(jìn)先出(FIFO—first in first out)。
棧,是先進(jìn)后出(FILO—First-In/Last-Out)。
6502堆棧$100--$1FF最多只能存放127個(gè)雙字節(jié),所以JSR最大連續(xù)的轉(zhuǎn)入深度為127層。如果還有其它數(shù)據(jù)入棧,子程序轉(zhuǎn)入深度還要減少。所以在設(shè)計(jì)復(fù)雜的程序時(shí),堆棧是會(huì)出現(xiàn)溢出的。堆棧溢出,意味著主機(jī)會(huì)死機(jī)。
死機(jī)代表什么?
橫井俊平終于意識(shí)到了關(guān)鍵,因?yàn)樗罊C(jī)不代表結(jié)束。對(duì)普通人來(lái)說(shuō)死機(jī)意味著重啟,而在黑客的手上死機(jī)意味著B(niǎo)UG就要出來(lái)了。
果然,王秋陽(yáng)的回復(fù)中,依據(jù)堆和棧的特點(diǎn),做出了不一樣的文章。
堆,因?yàn)槭窍冗M(jìn)先出,理論上是由電腦自行運(yùn)算。
棧,由于是先進(jìn)后出,因此可以人為控制其運(yùn)算。
說(shuō)形象一點(diǎn),堆就像地鐵,乘客只要買票,上車后可以萬(wàn)事不管,輕輕松松的坐車到站。但是地鐵只管到站,不會(huì)送你到家門口。
而棧,則更像私家車。私家車需要自己駕駛,不像乘地鐵那樣輕松。但是它的自由度更大,想去哪兒就去哪兒,想什么時(shí)候出發(fā)隨心所欲。
一個(gè)棧,在沒(méi)有數(shù)據(jù)進(jìn)棧時(shí)堆棧指針S=$FF。
每當(dāng)有一個(gè)數(shù)據(jù)進(jìn)棧S-1→S。
每當(dāng)有一個(gè)數(shù)據(jù)出時(shí)棧S+1→S。
當(dāng)執(zhí)行JSR指令時(shí),CPU把下一條指令地址-1,也就是兩個(gè)字節(jié)自動(dòng)入棧,即是程序的返回地址-1自動(dòng)入棧,然后轉(zhuǎn)入到子程序中執(zhí)行。
當(dāng)遇到RTS時(shí)彈出棧頂2個(gè)字節(jié),作為程序的返回地址,并轉(zhuǎn)到下一條指令中執(zhí)行。而這次執(zhí)行,是可以人為控制的。
也就是說(shuō)讓堆自主運(yùn)算,然后人為的控制棧的數(shù)據(jù)流動(dòng),這就能夠讓6502芯片自發(fā)的完成定時(shí)器的效果,造成和留白一樣的假死機(jī),也就是花屏。
而且這個(gè)花屏的顏色,將不再是黑色,因?yàn)樗呀?jīng)BUG過(guò)了。加之?,F(xiàn)在避開(kāi)的電腦的自主操作,可以這次花屏可以人為的“默認(rèn)”它顯示灰階。
“還有這種操作?”
看到這里,橫井俊平直感慨,為什么自己的思維總跟不上節(jié)奏?再看之前的同顯五十二色匯編語(yǔ)言,他甚至懷疑這篇稿件是未來(lái)的某個(gè)人寫(xiě)出來(lái)的才對(duì)。
思路被打通之后,后面的內(nèi)容,橫井俊平看得就輕松了許多,但同樣很扣人心弦。
因?yàn)楹竺娣治龅?,就是如何利用PPU增加發(fā)色數(shù)。
現(xiàn)行PPU和6502.7芯片一樣,是由理光設(shè)計(jì),十六進(jìn)制支持既定4x16色號(hào)調(diào)色版的型號(hào)。
電腦的畫(huà)面制作,是由PPU擬定原始色號(hào),也就是物理運(yùn)算芯片。之后由GPU負(fù)責(zé)運(yùn)算,顯示,最后CPU負(fù)責(zé)全程調(diào)控??梢哉f(shuō)PPU是發(fā)色的基礎(chǔ),它的發(fā)色原理來(lái)源于芯片上的寄存器。
寄存器本身分為兩個(gè)概念,一個(gè)是物理概念,也就是寄存真實(shí)的顏色,比如紅,綠,藍(lán)這樣的顏色。另一個(gè)概念,就是運(yùn)算概念,PPU把這些顏色以數(shù)據(jù)的形式傳送給電腦,再由GPU通過(guò)顯卡把數(shù)據(jù)傳送到屏幕上。當(dāng)然,F(xiàn)C沒(méi)有單獨(dú)顯卡,GPU是集成于主板上的。
其中的物理概念,重點(diǎn)就在于寄存器對(duì)發(fā)色的選定。
電腦的三源色是紅,綠,藍(lán)。6502的發(fā)色原理是構(gòu)建兩條垂直伸展的軸線,分別是X和Y,從左上角向右方和下方延展。原色紅居于正上方,藍(lán)居于左下角方,綠居于右下方。
由于6502認(rèn)定屏幕的上和下,左和右是互通的,因此發(fā)色的區(qū)域左邊自形成的白色起始,漸進(jìn)到灰色,然后是從紫到紅,向右漸變?yōu)榍嗌?,再到綠色,最后是黑色。
自上而下,則是從紅色漸變到橙色,再到黃色為止。而座標(biāo)的斜方向,就是漸變的一些靠近主色的近色。PPU寄存器要做的,就是選定一個(gè)發(fā)色范圍,同時(shí)將需要的顏色以數(shù)據(jù)的形式貯存下來(lái)。
如果以后需要某種顏色,PPU就能夠提交數(shù)據(jù),迅速以相應(yīng)的座標(biāo)記憶將三原色搭配出的色彩毫無(wú)差錯(cuò)的構(gòu)建出來(lái)。這也是電腦讓人類無(wú)法企及的超強(qiáng)運(yùn)算能力,哪怕只是八位處理性能的6502。
試問(wèn),就是一位畫(huà)家,他能夠保證自己每次調(diào)配出來(lái)的色號(hào)完全一樣嗎?肯定不能,但是電腦就可以。
和6502協(xié)同運(yùn)算的PPU,座標(biāo)記憶就是達(dá)到四乘以十六的一個(gè)區(qū)間,在寄存器中貯存下來(lái)。這些數(shù)據(jù),就是電腦的調(diào)色板,即物理運(yùn)算;而這些能夠隨時(shí)轉(zhuǎn)化為顏色的座標(biāo)數(shù)據(jù),就是色號(hào),即數(shù)據(jù)運(yùn)算。
6502要增加PPU上的游戲色號(hào),這個(gè)堆棧就要聯(lián)系到卡帶上的臨時(shí)貯存器。
任天堂的卡帶上有四個(gè)重要的組成部分,分別是ROM-chr,ROM-prg,MMC芯片,還有RAM。當(dāng)然還有電池,密碼鎖等和程序關(guān)系不大的配件。
其中,ROM-chr用來(lái)貯存游戲的圖文,ROM-prg貯存程序。
而在游戲過(guò)程中,運(yùn)算都是在RAM中進(jìn)行的。RAM全稱為Random-Access Memory,代表游戲內(nèi)存。它的功能是暫時(shí)存儲(chǔ)數(shù)據(jù)供CPU調(diào)取。
由于卡帶的讀取速度跟不上6502的處理速度,因此所有的程序運(yùn)行都是先從卡帶讀取數(shù)據(jù)并加載到內(nèi)存中,再寫(xiě)入CPU內(nèi)部的高速緩存進(jìn)行處理。
人為增加發(fā)色數(shù)的過(guò)程,將在這里完成最后的步驟。
RAM在待機(jī)狀態(tài)下為空,也就是說(shuō),RAM負(fù)責(zé)在游戲運(yùn)行時(shí)貯存臨時(shí)數(shù)據(jù)。從某種意義上來(lái)說(shuō),RAM和堆棧的作用很相似,只是它的容量非常之小,一般只有20Kb(1Kb等于8字節(jié))。
這個(gè)就是臨時(shí)貯存器。在“定時(shí)器”的原理下,色號(hào)能存在兩個(gè)。它能夠把灰階20像黑色那樣,指定為花屏底色,強(qiáng)制電腦顯示出來(lái),使它成為可用色號(hào)。
因?yàn)镃PU顯示出默認(rèn)灰階,成為了同顯發(fā)色色號(hào)。因此人為的再使用灰階30,就能夠在黑色之外再增加一款發(fā)色數(shù),而且本身并不占用到任何內(nèi)存。
如此一來(lái),即便在沒(méi)有MMC芯片的支持下,發(fā)色數(shù)也增加到了十四種。即黑色,灰階,以及十二種彩色!
看到這里,橫井俊平忍不住感慨道:“科樂(lè)美為了研發(fā)MMC芯片,花了兩年時(shí)間,增加了一款發(fā)色數(shù)。而這套匯編才用了兩天,真是讓人難以置信!”