2015-12-05遊戲 知乎好玩就好玩在總有這麽有趣的問題。 比起你在其它地方能找到的資訊,我會稍微講得詳細那麽一點點,至少比各種流言更靠譜一些,但是受限於專業水平,這個答案並不完美,權當拋磚引玉好了。知乎上程式設計師多,總有能幫我補充的。 —————————— 我先從一個有點感人的故事講起吧。圖少字多,見諒。 這個故事講的是一位 「Cheat Finder」 ——也就是熱衷於研究「作弊碼」的玩家。故事有點長,但我實在希望更多玩家知道這個人。 所謂「作弊碼」你大概能猜到是什麽意思,就是透過非常規的方式修改遊戲記憶體,實作在遊戲中作弊的效果,例如角色無限生命、瞬間獲得強力武器等等。 當然,具體改哪裏、怎麽改,都是有講究的,所以才會有人專門研究這個,他們尋找能夠實作作弊的特定的「地址+值」的組合,測試,然後分享出來,以此為樂。 在這個圈子中,從1998年就致力於制作/收集/整理/分享MAME作弊碼的Pugsy應該算得上是個大拿,他經常會釋出最新版的作弊碼合集。時至今日你下載到的各種第三方打包MAME中,作弊碼部份基本都是從他的網站 「Pugsy's Cheats 」 ( http:// cheat.retrogames.com )抓來的。 然而今天的主角並不是Pugsy君,而是一名叫做 zakria 的網友,真名 Zakriya Aleem ,年齡性別國籍不詳——看名字應該是阿拉伯裔男性。 2008年6月的一天,這位zakria在Pugsy的論壇上操著半生不熟的英語發了個帖: 「求『懲罰者』作弊」 。 ( http://www. mamecheat.co.uk/forums/ viewtopic.php?t=3008 ) 『懲罰者』街機上有個秘技可以殺死全螢幕幕的敵人,誰能發一下啊? 抱歉我英語很差但是Pugsy很厲害他找到了『Eswat』無限特殊武器的作弊碼。這次我想要的作弊是在『懲罰者』中殺死螢幕上所有敵人,就像最新版作弊檔中那個『吞食天地2』清屏。( 程式碼 )誰能發一下『懲罰者』的嗎? Pugsy當時回復道: 這個作弊很難實作。我倒是做了個改版ROM能快速清屏的,但bug太多了而且還會當機。總之我有空再看看吧。 過了3個月,可能是zakria發了私信詢問研究進展,Pugsy再次回復了貼文(請註意文字的語氣態度): 我已經說過了這個作弊很麻煩, 給我發私信求我給你RAM碼也沒用 : 1.我通常不看私信。如果你想要作弊碼不如直接發貼文,得到回答的機率還高一點。 這次的話題我最後回答一遍,然後你自求多福吧 。 2.改RAM行不通,因為角色在記憶體中是動態分配的,它需要使用「相對地址」,或者在ROM中改一大堆東西。 我也說過了我試過改ROM然後發現要修改和測試的地方太多了,每一種扣血都有自己的程式碼,它們都需要被處理。我改了一點,就是之前說過特別bug的那個。 反正短期內我也不會再關註這個問題了 ,所以發給你看看,強調,特別bug。如果你想自己改的話,你最好去學學「68000組譯」和「MAME debugger」。你需要幹掉所有跟敵人血量有關的sub.w d0,(36,ax)呼叫,有80個以上地方,而且說不定還得改別的。 ( 程式碼 ) 就在這個回復的十幾天後,zakria又發了個貼文(還是半生不熟的英語): 「『懲罰者』清屏作弊」 ( http://www. mamecheat.co.uk/forums/ viewtopic.php?t=3132 ) 我找到了『懲罰者』殺死所有敵人的作弊碼。 這個碼不怎麽bug所有關卡都可以用它快速透過只有第一關不行。要幹掉第一關boss你可以用無限手槍那個作弊。 如果Pugsy你想給這個碼改名請隨意。 ( 程式碼 ) 可想而知,Pugsy驚詫了: 牛逼啊!這不光是「殺死所有敵人」,簡直就是「直接走著過關」的作弊啊,好多敵人根本連刷都不刷了。 你能堅持下來很好。 你證明了我之前說的「改RAM行不通」是錯誤的(找個台階,我當時想得是另外一種改法來著)。 zakria回復: 謝謝Pugsy他給了我們很好用的作弊搜尋器。 Miguelo( *另外一位表示驚奇的回復者 ), 這個RAM作弊很簡單 ,我以前在街機上見過( *估計就是中國盜版 )。 當年12月,zakria貢獻了另外一個作弊碼,貼文中又有了一段對話: ( http://www. mamecheat.co.uk/forums/ viewtopic.php?f=4&t=3199 ) Pugsy: 謝謝,加好了……對了在cheats.txt的貢獻者名單中你想署哪個名字?zakria還是genesis?你的真名是什麽? zakria: 謝謝Pugsy,我的名字是ZAKRIYA。 我不需要署名。 你說genesis,我完成他一兩個作弊請求我不太明白? Pugsy: 抱歉,只是你們這兩個賬號發貼文用的是相同的IP地址,在我這種小眾論壇這可不是常事。我已經在cheat.txt中加上你的名字了,如果你不希望露真名請告訴我。 zakria: 我非常非常抱歉Pugsy,Qayoom(genesis)是我的朋友, 我們去同一個網吧上的網。 所有的作弊碼都歸你。如果你願意加上我的名字,我的名字是Zakriya Aleem。 看到這裏,我鼻子有點酸。 這個非英語母語的玩家,磕磕巴巴地提了一個挺有意義的難題,卻被認為該難題無解的大V前輩甩了一通臉色、拒之門外。就這樣,憑著一點施舍性質的、微妙的線索,他竟花了不到兩星期(而且是在網吧)自己給解決了,解法還很漂亮,還絲毫不計前嫌、慷慨地分享出來,連署名都不要…… 中東那邊世道亂,希望這哥們如今過得還好,不要卷入戰火。 —————————— 故事講完了,回歸正題,說下『懲罰者』這個搖無敵是怎麽回事吧。 我就是順著zakria同誌的作弊碼開始查的,他給出的修改很簡潔: 把$FF5FA1這個字節置為FF ,所有敵人就自動全滅,道具一撿就碎,boss也不用打,和街機搖出無敵的效果一模一樣。 為什麽會有這樣的效果呢? 用MAME debugger的Watchpoint監視,可以簡單發現: 在每一關的開頭,以及擊殺boss的瞬間,這個地址都會有寫入操作; 讀取則相對非常頻繁。 結合實際現象,我推測: 擊殺boss過關的時候,如果螢幕上還有雜兵活著,它們會立刻被一起幹掉,然後出結算畫面。$FF5FA1就是觸發這個判定用的。將它鎖成FF的話,遊戲就會一直以為你是剛剛過關的狀態,因此見誰秒誰。 這是清屏的通俗原理。 那麽,搖出來的無敵,跟zakria改出來的無敵,是不是一回事呢? 我用「可以搖無敵」的改版ROM(punipic)測試了一下,在第三關搖出無敵(紅衣機槍敵人掙脫)的瞬間,執行情況如下: 什麽意思? 我試著說一下啊——雖說我也算是個程式設計師,畢竟是有陣子沒怎麽親手寫程式碼了,而且更沒怎麽弄過組譯,水平有限,如果解釋錯了你們不要噴我。 首先,發揮最關鍵作用的是 $03BF34 這句(ROM中是50EDDFA1)。DFA1反組譯顯示成-$205F,其實就是 $FF5FA1 ,程式執行到這一句就會給這個地址賦值,也就是觸發了無敵狀態,然後再往下走到檢測時就會觸發殺死敵人的效果。 換言之,大家熟知的搖無敵確實是$FF5FA1這個地址造成的。zakria改出來的無敵和你搖出來的無敵是一樣的。 然而正常遊戲中並不會出現無敵。 在 $03BF20 這一步,程式會檢查D0寄存器的值,如果不等於#$7,就會從 $03BF24 直接跳到 $03BF38 ,跳過了上述賦值。 D0寄存器的值是動態變化的,每一次執行到這裏都可能不一樣,因此 即使在盜版街機上也不是100%能搖出無敵,能搖出來的前提是敵兵掙脫瞬間D0=7 。可能是我手法差,總之這裏我暫且認為是隨機發生的。 如果第一步沒有攔住(原版也有可能透過第一步),那麽往下還會有一個檢查,在 $03BF28 (上圖示黃的內容)。它會檢查 從$000AC6起的四個字節是否等於#$0080014A ,如果相等,就跳過去,直接到 $03BF38 。 註意:000AC6是ROM中的內容,值是固定的。 繼續追查,原版遊戲ROM是這樣的: 看到 0080014A 了麽?看見了就應該明白, 原版遊戲中你怎麽搖也搖不出無敵的,程式100%會跳過觸發無敵的那一句,根本進不去。 能搖出無敵的盜版ROM,則是這樣的: 這裏被改成了 0C409180 ,因此在BEQ判斷處不能正常跳轉,於是程式接下來會按順序執行 $03BF34 ,然後就觸發無敵了。 —————————— (圖: THE PUNISHER || ENEMIES ) 總結一下, 在「中國大陸流行的盜版基板」中,觸發「無敵bug」的條件是「$03BF20語句執行時D0=#$7,從而未能跳過$03BF34」。而$03BF20會在特定敵兵「TRENCH」(即上圖的紅衣機槍手)從揪脖子狀態掙脫時執行,無論是時間到了自動掙脫,還是玩家搖出了前捲動作中止揪脖子。 之所以只有3、5、6關能無敵,是因為這個敵人只在這三關重新整理。 以上是我可以確定的內容。 另外,我個人還有一些猜測,主觀認為可能性很高,但沒有徹底確定(精力有限,懶得通讀程式碼): 1. 在「搖無敵」這個過程中,瘋狂左右晃動搖桿可能並沒有起到太大作用,只是盡量快速重復「揪脖子,掙脫」這個過程,反復碰運氣而已。 2. 「無敵bug」不像是盜版dump ROM時失誤所致——盜版ROM和原版ROM不只是一兩位數據有出入,光是上面我截圖中顯示的,從$000AB2到$000B0D都大相徑庭,其它還有很多不同之處。我認為這個bug很可能是人為手動修改導致的。『懲罰者』的基板並不是普通的CPS,而是CPS'(搭載QSound芯片),盜版基板閹掉了QSound,勢必要在程式上有些改動。 3. 「無敵bug」也並不像是盜版者故意設計的秘技。就$03BF34這一句以及其附近的程式碼而言,盜版ROM和原版ROM這裏是相同的。我傾向於認為它是盜版者修改程式時意外發生的副作用。 至於原版程式為什麽要在這個地方留一句進不去的程式碼,抱歉,我也不知道。所以我說這個答案只是一知半解、拋磚引玉,等著大牛來個徹底解析吧。 就這些。禁止轉載。 (如有不同見解,歡迎在評論區補充)
知乎好玩就好玩在總有這麽有趣的問題。 比起你在其它地方能找到的資訊,我會稍微講得詳細那麽一點點,至少比各種流言更靠譜一些,但是受限於專業水平,這個答案並不完美,權當拋磚引玉好了。知乎上程式設計師多,總有能幫我補充的。 —————————— 我先從一個有點感人的故事講起吧。圖少字多,見諒。 這個故事講的是一位 「Cheat Finder」 ——也就是熱衷於研究「作弊碼」的玩家。故事有點長,但我實在希望更多玩家知道這個人。 所謂「作弊碼」你大概能猜到是什麽意思,就是透過非常規的方式修改遊戲記憶體,實作在遊戲中作弊的效果,例如角色無限生命、瞬間獲得強力武器等等。 當然,具體改哪裏、怎麽改,都是有講究的,所以才會有人專門研究這個,他們尋找能夠實作作弊的特定的「地址+值」的組合,測試,然後分享出來,以此為樂。 在這個圈子中,從1998年就致力於制作/收集/整理/分享MAME作弊碼的Pugsy應該算得上是個大拿,他經常會釋出最新版的作弊碼合集。時至今日你下載到的各種第三方打包MAME中,作弊碼部份基本都是從他的網站 「Pugsy's Cheats 」 ( http:// cheat.retrogames.com )抓來的。 然而今天的主角並不是Pugsy君,而是一名叫做 zakria 的網友,真名 Zakriya Aleem ,年齡性別國籍不詳——看名字應該是阿拉伯裔男性。 2008年6月的一天,這位zakria在Pugsy的論壇上操著半生不熟的英語發了個帖: 「求『懲罰者』作弊」 。 ( http://www. mamecheat.co.uk/forums/ viewtopic.php?t=3008 ) 『懲罰者』街機上有個秘技可以殺死全螢幕幕的敵人,誰能發一下啊? 抱歉我英語很差但是Pugsy很厲害他找到了『Eswat』無限特殊武器的作弊碼。這次我想要的作弊是在『懲罰者』中殺死螢幕上所有敵人,就像最新版作弊檔中那個『吞食天地2』清屏。( 程式碼 )誰能發一下『懲罰者』的嗎? Pugsy當時回復道: 這個作弊很難實作。我倒是做了個改版ROM能快速清屏的,但bug太多了而且還會當機。總之我有空再看看吧。 過了3個月,可能是zakria發了私信詢問研究進展,Pugsy再次回復了貼文(請註意文字的語氣態度): 我已經說過了這個作弊很麻煩, 給我發私信求我給你RAM碼也沒用 : 1.我通常不看私信。如果你想要作弊碼不如直接發貼文,得到回答的機率還高一點。 這次的話題我最後回答一遍,然後你自求多福吧 。 2.改RAM行不通,因為角色在記憶體中是動態分配的,它需要使用「相對地址」,或者在ROM中改一大堆東西。 我也說過了我試過改ROM然後發現要修改和測試的地方太多了,每一種扣血都有自己的程式碼,它們都需要被處理。我改了一點,就是之前說過特別bug的那個。 反正短期內我也不會再關註這個問題了 ,所以發給你看看,強調,特別bug。如果你想自己改的話,你最好去學學「68000組譯」和「MAME debugger」。你需要幹掉所有跟敵人血量有關的sub.w d0,(36,ax)呼叫,有80個以上地方,而且說不定還得改別的。 ( 程式碼 ) 就在這個回復的十幾天後,zakria又發了個貼文(還是半生不熟的英語): 「『懲罰者』清屏作弊」 ( http://www. mamecheat.co.uk/forums/ viewtopic.php?t=3132 ) 我找到了『懲罰者』殺死所有敵人的作弊碼。 這個碼不怎麽bug所有關卡都可以用它快速透過只有第一關不行。要幹掉第一關boss你可以用無限手槍那個作弊。 如果Pugsy你想給這個碼改名請隨意。 ( 程式碼 ) 可想而知,Pugsy驚詫了: 牛逼啊!這不光是「殺死所有敵人」,簡直就是「直接走著過關」的作弊啊,好多敵人根本連刷都不刷了。 你能堅持下來很好。 你證明了我之前說的「改RAM行不通」是錯誤的(找個台階,我當時想得是另外一種改法來著)。 zakria回復: 謝謝Pugsy他給了我們很好用的作弊搜尋器。 Miguelo( *另外一位表示驚奇的回復者 ), 這個RAM作弊很簡單 ,我以前在街機上見過( *估計就是中國盜版 )。 當年12月,zakria貢獻了另外一個作弊碼,貼文中又有了一段對話: ( http://www. mamecheat.co.uk/forums/ viewtopic.php?f=4&t=3199 ) Pugsy: 謝謝,加好了……對了在cheats.txt的貢獻者名單中你想署哪個名字?zakria還是genesis?你的真名是什麽? zakria: 謝謝Pugsy,我的名字是ZAKRIYA。 我不需要署名。 你說genesis,我完成他一兩個作弊請求我不太明白? Pugsy: 抱歉,只是你們這兩個賬號發貼文用的是相同的IP地址,在我這種小眾論壇這可不是常事。我已經在cheat.txt中加上你的名字了,如果你不希望露真名請告訴我。 zakria: 我非常非常抱歉Pugsy,Qayoom(genesis)是我的朋友, 我們去同一個網吧上的網。 所有的作弊碼都歸你。如果你願意加上我的名字,我的名字是Zakriya Aleem。 看到這裏,我鼻子有點酸。 這個非英語母語的玩家,磕磕巴巴地提了一個挺有意義的難題,卻被認為該難題無解的大V前輩甩了一通臉色、拒之門外。就這樣,憑著一點施舍性質的、微妙的線索,他竟花了不到兩星期(而且是在網吧)自己給解決了,解法還很漂亮,還絲毫不計前嫌、慷慨地分享出來,連署名都不要…… 中東那邊世道亂,希望這哥們如今過得還好,不要卷入戰火。 —————————— 故事講完了,回歸正題,說下『懲罰者』這個搖無敵是怎麽回事吧。 我就是順著zakria同誌的作弊碼開始查的,他給出的修改很簡潔: 把$FF5FA1這個字節置為FF ,所有敵人就自動全滅,道具一撿就碎,boss也不用打,和街機搖出無敵的效果一模一樣。 為什麽會有這樣的效果呢? 用MAME debugger的Watchpoint監視,可以簡單發現: 在每一關的開頭,以及擊殺boss的瞬間,這個地址都會有寫入操作; 讀取則相對非常頻繁。 結合實際現象,我推測: 擊殺boss過關的時候,如果螢幕上還有雜兵活著,它們會立刻被一起幹掉,然後出結算畫面。$FF5FA1就是觸發這個判定用的。將它鎖成FF的話,遊戲就會一直以為你是剛剛過關的狀態,因此見誰秒誰。 這是清屏的通俗原理。 那麽,搖出來的無敵,跟zakria改出來的無敵,是不是一回事呢? 我用「可以搖無敵」的改版ROM(punipic)測試了一下,在第三關搖出無敵(紅衣機槍敵人掙脫)的瞬間,執行情況如下: 什麽意思? 我試著說一下啊——雖說我也算是個程式設計師,畢竟是有陣子沒怎麽親手寫程式碼了,而且更沒怎麽弄過組譯,水平有限,如果解釋錯了你們不要噴我。 首先,發揮最關鍵作用的是 $03BF34 這句(ROM中是50EDDFA1)。DFA1反組譯顯示成-$205F,其實就是 $FF5FA1 ,程式執行到這一句就會給這個地址賦值,也就是觸發了無敵狀態,然後再往下走到檢測時就會觸發殺死敵人的效果。 換言之,大家熟知的搖無敵確實是$FF5FA1這個地址造成的。zakria改出來的無敵和你搖出來的無敵是一樣的。 然而正常遊戲中並不會出現無敵。 在 $03BF20 這一步,程式會檢查D0寄存器的值,如果不等於#$7,就會從 $03BF24 直接跳到 $03BF38 ,跳過了上述賦值。 D0寄存器的值是動態變化的,每一次執行到這裏都可能不一樣,因此 即使在盜版街機上也不是100%能搖出無敵,能搖出來的前提是敵兵掙脫瞬間D0=7 。可能是我手法差,總之這裏我暫且認為是隨機發生的。 如果第一步沒有攔住(原版也有可能透過第一步),那麽往下還會有一個檢查,在 $03BF28 (上圖示黃的內容)。它會檢查 從$000AC6起的四個字節是否等於#$0080014A ,如果相等,就跳過去,直接到 $03BF38 。 註意:000AC6是ROM中的內容,值是固定的。 繼續追查,原版遊戲ROM是這樣的: 看到 0080014A 了麽?看見了就應該明白, 原版遊戲中你怎麽搖也搖不出無敵的,程式100%會跳過觸發無敵的那一句,根本進不去。 能搖出無敵的盜版ROM,則是這樣的: 這裏被改成了 0C409180 ,因此在BEQ判斷處不能正常跳轉,於是程式接下來會按順序執行 $03BF34 ,然後就觸發無敵了。 —————————— (圖: THE PUNISHER || ENEMIES ) 總結一下, 在「中國大陸流行的盜版基板」中,觸發「無敵bug」的條件是「$03BF20語句執行時D0=#$7,從而未能跳過$03BF34」。而$03BF20會在特定敵兵「TRENCH」(即上圖的紅衣機槍手)從揪脖子狀態掙脫時執行,無論是時間到了自動掙脫,還是玩家搖出了前捲動作中止揪脖子。 之所以只有3、5、6關能無敵,是因為這個敵人只在這三關重新整理。 以上是我可以確定的內容。 另外,我個人還有一些猜測,主觀認為可能性很高,但沒有徹底確定(精力有限,懶得通讀程式碼): 1. 在「搖無敵」這個過程中,瘋狂左右晃動搖桿可能並沒有起到太大作用,只是盡量快速重復「揪脖子,掙脫」這個過程,反復碰運氣而已。 2. 「無敵bug」不像是盜版dump ROM時失誤所致——盜版ROM和原版ROM不只是一兩位數據有出入,光是上面我截圖中顯示的,從$000AB2到$000B0D都大相徑庭,其它還有很多不同之處。我認為這個bug很可能是人為手動修改導致的。『懲罰者』的基板並不是普通的CPS,而是CPS'(搭載QSound芯片),盜版基板閹掉了QSound,勢必要在程式上有些改動。 3. 「無敵bug」也並不像是盜版者故意設計的秘技。就$03BF34這一句以及其附近的程式碼而言,盜版ROM和原版ROM這裏是相同的。我傾向於認為它是盜版者修改程式時意外發生的副作用。 至於原版程式為什麽要在這個地方留一句進不去的程式碼,抱歉,我也不知道。所以我說這個答案只是一知半解、拋磚引玉,等著大牛來個徹底解析吧。 就這些。禁止轉載。 (如有不同見解,歡迎在評論區補充)