究極綠寶石5.3——科普向,什么是金手指(三)
說在前面:
????回顧一下上一期的內(nèi)容,三個有關(guān)“金手指”的問題,作者回答了第一個問題:我們想要改的數(shù)字在哪里——變量地址查詢。并在最后給出了一個可以提前看黃半仙的蛋會孵出什么精靈的彩蛋。這一期專欄,將會回答第二個問題:
????我們要改的數(shù)字是什么含義,或者說我們想改的東西對應(yīng)了什么數(shù)字——變量與實體的映射表。

映射與映射表
????映射是計算機(jī)編程領(lǐng)域的一個術(shù)語,含義是兩個概念之間的對應(yīng)關(guān)系。這么說有些抽象,舉幾個例子就好理解了。第一個例子是交通信號燈,我們常說的“紅燈停,綠燈行”就是在燈的顏色和過馬路的動作之間建立了一組映射:“紅燈”映射到“停”,“綠燈”映射到“行”。第二個例子是我們的身份證號碼,一個18位的身份證號碼映射到一個公民。第三個例子是上下課的鈴聲,如果上下課鈴聲不同的話,那么上課鈴就可以映射到“上課”這個消息,下課鈴就可以映射到“下課”這個消息。
????映射只是對“對應(yīng)關(guān)系”進(jìn)行了描述,它并不是“等價”。交通信號燈的紅燈讓人聯(lián)想到過馬路需要停,但是充電器上的紅燈就不會,“紅燈”和“停下來”并不等價;18位的身份證號只是一串?dāng)?shù)字,它并不是某個公民,它只能說對應(yīng)到某個公民,數(shù)字和人不能等價;上下課的鈴聲如果不是在學(xué)校響起的,它代表的含義可能就不再是上課下課,上下課鈴聲這段音樂和上下課的消息也不是等價的,只能說是在一個具體的環(huán)境中,兩者存在對應(yīng)關(guān)系。
????回到游戲中來,以上篇專欄最后給出的彩蛋為例,我們可以做出這樣的映射:
????變量地址0202450c,映射到:首位精靈的種族
????變量取值02b0,映射到:三首惡龍
????這就是變量到游戲?qū)嶓w的映射。我們看到的金手指,有相當(dāng)大的一部分是通過這種映射來實現(xiàn)的,變量地址映射到某個想要改的東西,變量取值映射到我們想要它改成的東西。
????上面只有兩條映射,如果我們把映射一一列舉出來,比如下面這個片段:
????這個列舉出來、一條一條展示映射的表格就稱為映射表。這還只是變量取值的映射表,變量地址同樣也有映射表,比如下面這個片段:
????什么變量地址映射到游戲中的什么含義,什么變量取值映射到什么精靈或者物品,都是設(shè)計游戲的人在編寫程序時確定的。需要注意的是,變量地址的映射表,對于究極綠寶石5來說只有一張表,因為變量的門牌號(地址的取值范圍)限定在了00000000(16)~ffffffff(16)這一條“大街”上,沒有另一條“大街”。但是變量取值的映射表卻有好多張,比如說精靈種族對應(yīng)著一張映射表,攜帶物品也對應(yīng)著一張映射表,游戲為常用漢字也做了一張映射表,例如02b0在精靈種族的映射表中對應(yīng)到三首惡龍,在攜帶物品的映射表中卻對應(yīng)到銀色王冠,在常用漢字的映射表中,它又對應(yīng)到“大蔥鴨”里的“蔥”這個字??梢哉f,游戲界面中給你展示出來的一切,都是按照這些大大小小的映射表,從一個個的數(shù)字對應(yīng)到游戲?qū)嶓w的。

變量到實體,究竟是怎么對應(yīng)的?
????上面一小節(jié)拋出了很多讓人莫名其妙的事實:為什么0202450e就對應(yīng)到“隊伍中首位精靈的攜帶物品”了?為什么02b0一會兒代表著“三首惡龍”,一會兒又成了“銀色王冠”,一會兒又代表著單個漢字?這有什么道理嗎?為了解釋清楚這些,我們又要請出VBA模擬器,這次要用到的是查找金手指這個功能。
????VBA模擬器中,點擊“金手指——查找金手指”,可以打開“查找金手指”的界面。


????有很多使用VBA的讀者在看到“查找金手指”的功能時,可能難免激動一番,原來模擬器早就做好了找金手指的功能!可是打開一看,根本不知所云,這東西怎么用啊?跟想象的不一樣,想象中的“查找金手指”,應(yīng)該是有一個類似“搜索”的按鈕,點擊后出現(xiàn)一個進(jìn)度條,搜索完之后,把一些代碼和對應(yīng)的含義列在一張表格中任你使用。白日夢該醒醒了,“查找金手指”的功能遠(yuǎn)沒有那么智能,這個功能的實質(zhì),需要和第二期專欄里面那個“反匯編——變量地址查看器”結(jié)合起來才能解釋清楚。

????作者在第二期的專欄中介紹過,“工具——反匯編”這個菜單打開的界面其實是一個“變量地址查看器”,有個功能是在“轉(zhuǎn)到”按鈕前的那個輸入框內(nèi)輸入一個8位十六進(jìn)制數(shù),它就會跳到對應(yīng)的地址,你就可以看到這個地址處變量的取值。簡而言之,就是給定地址,找到取值,前半句是條件,后半句是結(jié)果?!安檎医鹗种浮钡墓δ芮『门c此相反,它是給定取值,找到地址,條件和結(jié)果對調(diào)了一下。給定一個取值,“查找金手指”會找到取值是給定數(shù)字的所有變量的地址,也就是說它給的結(jié)果可能不止一個,恰好有多個變量取值是一樣的,它會把這些變量的地址都列出來。
????下面會介紹幾個具體的例子,來解釋“查找金手指”的使用方法。

查找金手指例1——游戲金幣數(shù)量在哪里?
????下面以游戲金幣數(shù)量為例,來解釋“查找金手指”功能應(yīng)該如何使用。在這里,我們希望找到代表游戲金幣數(shù)量的變量地址,而變量取值自然就是金幣數(shù)量。
????以作者一次測試的圖為例,下圖中主角擁有的金幣數(shù)是1381241

????然后我們打開“金手指——查找金手指”,界面里出現(xiàn)了一系列選項,其中“查找類型”中的“精確查找”、“比較類型”中的“相等”和右下角那個打了對勾的“刷新數(shù)值列表”,通常情況下是不需要更改的?!坝?無正負(fù)之分”那里也有三個選項:分正負(fù)、不分正負(fù)和十六進(jìn)制,這里一般采用的是“不分正負(fù)”這個選項?,F(xiàn)在就剩下“數(shù)據(jù)尺寸”這個選項了,需要詳細(xì)說明一下。
????“數(shù)據(jù)尺寸”中有三個選項:8位,16位和32位,指的是變量取值的二進(jìn)制位長度,閱讀過第二期專欄的讀者們應(yīng)該都理解是什么意思。這里我們需要多長的數(shù)據(jù)呢?這就要用到第二期專欄介紹的一個工具:win10自帶的計算器,程序員模式。將1381241輸入到十進(jìn)制的欄內(nèi),得到如下結(jié)果:

????在DEC(十進(jìn)制)下輸入數(shù)字后,上面的HEX(十六進(jìn)制)和下面的BIN(二進(jìn)制)自動進(jìn)行了轉(zhuǎn)換。看二進(jìn)制那一行,共有24位,超出了16位的范圍,因此我們需要選擇“查找金手指——數(shù)據(jù)尺寸”中的32位選項。都設(shè)置好了之后,在“精確查找的目標(biāo)值”輸入框內(nèi)輸入金幣數(shù)1381241,然后點擊左下角的“開始”按鈕,如下圖:

????點擊“開始”后,原本灰色的“查找”按鈕現(xiàn)在變得可以點擊了。這里,“開始”按鈕的含義是重新開始一輪變量取值的搜索,將之前的搜索記錄全部忘記。下一步,我們點擊“查找”,結(jié)果就會顯示出來:

????我們比較幸運,只通過一次查找,就找到了游戲內(nèi)金幣數(shù)的變量地址,是02025e90,這就是我們通過“查找金手指”功能自己找到的一條映射。怎么驗證這個地址找的對不對呢?我們先關(guān)閉當(dāng)前頁面,在游戲中買一個高級球(1200元),然后再次打開這個頁面,如下圖所示:

????上圖中,02025e90地址處對應(yīng)的“舊值”還是我們之前的數(shù)字1381241,但后面的“新值”變成了1380041,恰好是減去1200元購買高級球的剩余金幣數(shù)。這是因為我們勾選了右下角的“刷新數(shù)值列表”,所以在“查找金手指”的頁面中會隨游戲進(jìn)度更新數(shù)值。還有另一個驗證方法,是用第二期專欄介紹過的方式,從“工具——反匯編”中打開“變量地址查看器”,輸入02025e90查詢:

????02025e90處的變量取值是0ec9,這個數(shù)字只有16位二進(jìn)制,我們要的是32位(別忘了在“查找金手指”中我們的設(shè)置),剩下的16位在哪里呢?對第二期專欄還有印象的讀者,會記得變量的取值是隨地址連續(xù)的,因此剩下的16位在02025e92處,是0015,而小端序則確定了這兩個16位二進(jìn)制數(shù)(也就是4位十六進(jìn)制數(shù))該怎么拼接:高位放在高地址,低位放在低地址。因此拼接之后的32位二進(jìn)制數(shù)就是00150ec9,這個數(shù)的十進(jìn)制是多少呢?再次用到我們的win10程序員計算器,這次選擇HEX一欄進(jìn)行輸入,可以看到:

????在DEC一欄的數(shù)字是1380041,恰好是主角剩下的金幣數(shù)。這樣,我們就用了兩種方式驗證了:角色的金幣數(shù)這個實體概念,可以映射到的變量地址是02025e90。
????這次我們比較幸運,在“查找金手指”中,只用了一次查找就找到了變量地址,下面再舉一個例子,需要多次查找。

查找金手指例2——隊伍首位精靈的級別在哪里?
????作者拿一個存檔進(jìn)行如下測試:隊伍中有三只精靈,級別分別為4級、15級和22級,隊首精靈級別為4:

????我們打開“金手指——查找金手指”,其他設(shè)置和上一個例子沒有變化,只有“數(shù)據(jù)尺寸”這一條需要仔細(xì)考慮。由于精靈等級最高100級,對應(yīng)的十六進(jìn)制數(shù)是64(16),(還不知道十進(jìn)制怎么轉(zhuǎn)換成十六進(jìn)制?win10程序員計算器!),說明精靈等級的二進(jìn)制不會超過8位(2位的十六進(jìn)制數(shù)就是8位二進(jìn)制數(shù)),因此這里的“數(shù)據(jù)尺寸”需要選擇“8位”。然后在“精確查找的目標(biāo)值”輸入框內(nèi)輸入4,先點擊“開始”,再點擊“查找”,結(jié)果如下圖:

????和上個例子不同,這里變量取值是4的變量有很多,到底哪個才是隊伍首位精靈的等級呢?這就需要介紹查找金手指的進(jìn)階功能:追蹤式變量取值查找。
????注:有的讀者可能會在這一步搜索彈出一個對話框“錯誤,搜索到……條結(jié)果,請選擇最適合的”,這種情況并不是說搜索失敗了,搜索還是成功的,接下來的步驟仍然可以進(jìn)行下去,詳細(xì)的解釋可以看第八期專欄究極綠寶石5.3——科普向,什么是金手指(八)。
????追蹤式變量取值查找:在點擊了一次“查找”按鈕之后,我們可以先回到游戲進(jìn)行一些操作,然后再進(jìn)入“查找金手指”的界面,修改“精確查找的目標(biāo)值”后面輸入框內(nèi)的數(shù)值,然后再次點擊“查找”,這樣挑選出來的變量就是這樣的變量:在第一次查找時符合第一次條件,并且在第二次查找時符合第二次條件的變量。
????為了演示,我們先點擊右下角的“確定”按鈕退出“查找金手指”的頁面,返回游戲,然后將首位精靈和第二位精靈換位一下:

????此時首位精靈的等級變成了15級,我們再次打開“查找金手指”的界面,發(fā)現(xiàn)有些原來取值是4的變量,現(xiàn)在發(fā)生了變化:

????可以看到,目前顯示出來的變量,有的還保持著4這個取值,有的變成了0,它們都不是我們要找的變量,我們要找的變量現(xiàn)在應(yīng)該變成了15才對,因此在“精確查找的目標(biāo)值”后面輸入15,然后點擊下面的“查找”(此時不能點擊“開始”!因為我們需要“追蹤式變量取值查找”,點了“開始”,之前的查找記錄就沒了),查找的結(jié)果如下:

????現(xiàn)在我們就剩下了2個地址,目標(biāo)范圍大大縮小。再次聲明一下“追蹤式變量取值查找”的結(jié)果,以上圖為例,就是第一次查找時取值是4,且第二次查找時取值是15的變量。只滿足兩個條件中的一條的變量可能很多,但同時滿足的就只有這兩個地址處的變量。
????結(jié)果還是不唯一,到底是哪個呢?我們通過換精靈的方式改變了首位精靈的級別,下面我們再用一個操作改變一下:喂給首位精靈一個神奇糖果,等級+1(需要先點“確定”按鈕退出“查找金手指”的界面):

????此時我們再次打開“查找金手指”,也不用再查找了,一眼就能看出來哪個地址是我們的目標(biāo):

????答案是02024540,這個地址處的變量映射到的實體就是首位精靈的等級。通過以上的“追蹤式變量取值查找”過程,我們可以發(fā)現(xiàn),這個過程像極了用篩子去篩選粗沙子中的細(xì)沙,每一遍篩選都能去掉一些不符合條件的變量,最后剩下的就是我們的目標(biāo)。(注:另一個地址02024532也有它的含義,是隊伍首位精靈被捕捉時的等級)
????這個過程和網(wǎng)上一個修改程序內(nèi)存的工具——Cheat Engine(也被稱作CE修改器)——的修改原理是完全相同的,可以認(rèn)為VBA模擬器把Cheat Engine的功能整合在了里面。
????怎么驗證這個地址映射正不正確呢?可以仿照上一個例子,用兩種方法——“查找金手指”和“變量地址查看器”——來驗證,相信跟著例子操作的讀者們應(yīng)該不會有問題的!

難度稍微大一點的金手指查找
????上面舉的兩個例子有個共同的特點:我們想要找的變量都是游戲中的數(shù)字??墒怯螒蛑胁粌H僅有數(shù)字,還有各種各樣的東西,精靈種族、道具、文字,等等。盡管閱讀過第一期專欄的讀者們知道,它們本質(zhì)上都是數(shù)字,但是怎么從這些實體映射到數(shù)字,我們還不知道。此時,我們就需要借助網(wǎng)絡(luò)的力量,從前人的經(jīng)驗中找到線索。
????搜索“究極綠寶石金手指”,網(wǎng)上有多種渠道告訴你各式各樣的金手指代碼,其中有一類“原始代碼”(英文名raw code),指的就是直接修改變量地址處的取值。這些代碼有個共同的特點,就是前面是8位帶有數(shù)字和字母的東西,后面用空格或者冒號隔開,然后再跟一個東西,這個東西長度可就不一定了,有時候是8位,有時候是4位,有時候又是2位。抽象總結(jié)一下,原始代碼的金手指大概長成這個樣子(冒號分隔):
或者(空格分隔)
????我們暫且不管這些金手指怎么使用,只需要知道,冒號/空格前面的那8位(現(xiàn)在大家知道了這些夾雜著字母和數(shù)字的東西是十六進(jìn)制數(shù))就是我們在本次專欄中提到的變量地址,而冒號/空格后面的那些2位或4位或8位的十六進(jìn)制數(shù),就是變量取值。
????上次專欄的彩蛋——“黃半仙送的蛋里面是什么?”——里面,留下來兩個問題,也就是
????為什么:變量地址0202450c映射到首位精靈的種族?
????為什么:變量取值02b0映射到三首惡龍?
????第一個問題,是因為網(wǎng)上的金手指中,有這么一條說是“任意修改隊伍首位精靈種族”,代碼是“0202450c:YYYY”,類型是“原始代碼”。且不管這條金手指管不管用,也且不管這條金手指用了之后有沒有副作用,起碼作者了解到了,存在這么一個變量到實體的映射,是地址0202450c到隊伍首位精靈種族的映射。
????第二個問題,它涉及到精靈種族的映射表,這個映射表可以自己去構(gòu)造,接下來說一下構(gòu)造的方法。
????按照第二期專欄的“變量地址查看器”使用方法,首先把自己想要找到映射的精靈放在隊伍首位,比如現(xiàn)在作者放了一個烈空坐在隊伍首位:

????然后打開“工具——反匯編”(也就是作者說的“變量地址查看器”),在“轉(zhuǎn)到”之前的輸入框輸入0202450c,點擊“轉(zhuǎn)到”按鈕,查看結(jié)果:

????發(fā)現(xiàn)結(jié)果是0196,這是一個十六進(jìn)制數(shù),并不是“一百九十六”,這樣我們就建立了烈空坐到數(shù)字0196(16)的映射。如果把首位精靈換成別的,就可以建立其他映射,這樣一個精靈種族的映射表就建立起來了。
????可能讀者還有一個疑問,為什么精靈種族對應(yīng)的十六進(jìn)制數(shù)是4位的,而不是2位的或者8位的?(比如之前金幣的那個例子,金幣數(shù)就是個8位十六進(jìn)制的變量,而精靈等級就是個2位十六進(jìn)制的變量)這得從游戲中總共有多少精靈種族說起。按照百度貼吧中制作組的官方說明,究極綠寶石5共收錄了第一到第八代共898只精靈,但實際上,各種mega、地區(qū)形態(tài),或者銀伴戰(zhàn)獸和阿爾宙斯的形態(tài)等等也是單獨的映射。這些精靈種族全算到一起,也不會超過4位十六進(jìn)制數(shù)能表示的范圍(65536=2^16),但卻超出了2位十六進(jìn)制數(shù)的范圍(256=2^8),因此表示精靈種族的變量是4位十六進(jìn)制數(shù),2位不夠,8位的話會浪費空間,編寫游戲的程序員不會這么做的。至于為什么不能是3位5位,第二期專欄說過,變量的長度必須是字節(jié)的整數(shù)倍,一個字節(jié)是8位二進(jìn)制,2位十六進(jìn)制。

自己動手來嘗試
????通過閱讀本專欄,或者從網(wǎng)上找的金手指,讀者可以找到隊伍首位精靈攜帶物品可以映射到哪個變量地址,然后通過在游戲中變換首位精靈攜帶的道具,又可以制造一張攜帶物品映射到變量取值的映射表,完全理解本篇專欄內(nèi)容的讀者,不妨自己動手試一試。
????注:用這種方式制作映射表是非常費時費力的,因此僅建議讀者在嘗試過程中了解其原理即可,制作映射表有利用程序處理、非常高效的辦法,在作者的另一個系列的專欄中(口袋妖怪綠寶石——數(shù)據(jù)提取與代碼分析)有所介紹。

????下一期專欄作者還是繼續(xù)介紹變量與實體的映射表。內(nèi)容涉及到一些難度更大的金手指查找,例如個體值、努力值、性格、對戰(zhàn)開拓區(qū)的印記等等。例如:6項個體值全滿(6V)映射到什么變量取值?速度0,其他5V的個體值又會映射到什么變量取值?對戰(zhàn)開拓區(qū)里,要對戰(zhàn)塔、對戰(zhàn)巨蛋是金色印記,對戰(zhàn)水管、對戰(zhàn)競技場是銀色印記,其他對戰(zhàn)設(shè)施沒有印記,這又會映射到什么變量取值?
????內(nèi)容難度肯定是有的,各位讀者能讀到此處實屬不易,不過前方還有更高的山峰等著我們?nèi)ヅ实?。大家有問題歡迎在討論區(qū)交流,謝謝大家的支持!