隨筆 · 東方遊戲重建

逆向工程的工業革命。

作者 N0zoM1z0 · 2026 年 10 月 10 日

要點

  • 讓程式設計助手自主開展調查。明確目標和驗收標準,再讓它決定下一步嘗試什麼。
  • 把程式碼儲存庫和 Git 當作工作記憶。推理過程和程式碼一起儲存。用 Git 留下檢查點,下一次會話就能在對話結束後接著做。
  • 結論要由證據決定。說得再肯定,也需要驗證。證據不足時,“尚不清楚”是合理的答案。
  • 驗證基準本身也要測試。故意給它應當拒絕的錯誤案例。如果它漏掉了 bug,就重新檢查依賴這套基準的早期結果。
  • 我們正處於逆向工程工業革命的早期。方法還在成形,還有很多值得探索的地方。

經驗如何產生複利

人來定方向 · 目標和驗收標準

自主探索

程式設計助手

選擇實驗。
提出假設。

驗證

驗證基準

對照
具體的基準驗證。

程式碼儲存庫

工作記憶

程式碼、證據、
檢查和經驗。

不匹配
修正假設

更好的
起點

複用

透過 · 保留結果及其證據

每個專案都為下一個專案留下更好的起點。發現檢查有漏洞時,也要把檢查修好。

2026年8月發生了什麼變化

在這之前,我做過很多手工逆向。我會反覆檢視一個函式,直到能解釋它,再對照程式驗證這個解釋。想推進專案,就得親自花更多時間研究下一個函式,腦子裡也要記住越來越多的整體關係。

我的逆向工作主要圍繞遊戲。我希望透過重建弄清遊戲的行為,最終做出移植版或 mod。這篇文章來自這些經歷。方法可以遷移到其他領域,但每個領域都需要先明確:什麼可以用可靠的基準來驗證。

2026 年 8 月,我開始認真探索讓程式設計助手做逆向。有了程式本身和常用開發工具,它究竟能走多遠?東方遊戲重建給了我一個足夠完整的專案來尋找答案。

早期的進展讓我吃驚。我不再需要為每一步作選擇,調查也能持續推進。對比失敗後,助手可能轉去檢視另一個呼叫方,寫一段診斷程式,再根據結果決定下一步。這種自主性改變了我的工作:我可以更多關注專案方向,以及檢查是否可靠。

速度先引起了我的注意。隨後我開始想:當前專案結束後,什麼會留下來?下一個遊戲能不能用上我們剛學到的經驗?

TH08:接續前人的工作

TH08,也就是《東方永夜抄》,從接續GensokyoClub 的重建工作開始。他們的公開原始碼提供了紮實的基礎,也留下了構建經驗和貢獻歷史。我在後續工作中保留了這些歷史。

匯入的歷史截至 8 月 10 日的公開檢查點。我的獨立續作從 8 月 13 日開始。到 8 月 19 日,進度臺賬中已識別的 1,107 個遊戲函式都有了原始碼。

8 月 24 日,我們提交了可玩的 Linux 重建移植版,距離開始續作約十一天。隨後做出了 Web 版。8 月 30 日,原生 Linux 64 位版釋出。

最打動我的是,這些工作最終變成了大家能執行的程式。為此必須解決單個函式以外的問題。即使兩個函式分別看起來都對,也可能各自使用一份本應共享的狀態。

這讓對照檢查成為工作的核心。我把這些基準稱為驗證基準(oracle)。程式碼對比可以檢查重建函式是否復現原始指令;執行時檢查可以確認已走過的路徑是否到達預期狀態。助手提出解釋,再驗證它。發現不匹配,就有了具體的調查方向。

常量錯了,卻仍然“精確匹配”

校驗工具也是人寫的軟體。TH08 讓我清楚地看到,多少結論都依賴著它。

9 月,下游 Switch 移植版報告了一個 bug,最後追溯到道具自動收集。重建原始碼把玩家火力與 0.0 比較,而原版用的是 128.0,即滿火力的閾值。

正常火力不會小於零,所以重建版的火力條件幾乎總是滿足。玩家到了收集線上方,不用滿火力也會吸取道具。條件裡的其他例外沒有問題,但這一個常量就改變了行為。

可這個函式之前已經透過了精確對比。

重新編譯後,常量可能出現在不同地址。比較工具會先調整編譯後指令中的地址,再和原版比較,以處理這種差異。問題是,它從未檢查被引用地址中實際存放的浮點值。

漏洞就在這裡:工具可以把重建指令的引用地址調整為原版的 128.0,而原始碼裡寫的仍然是 0.0。指令位元組匹配了,原始碼含義卻不同。

9 月 2 日的修復糾正了原始碼,並讓比較工具檢查被引用常量的實際位元組。隨後進行的全面審計檢查了 1,548 處浮點常量引用,又在五個已透過驗收的函式中發現十二處錯誤引用。

現在工具會檢查每一處這樣的浮點常量。測試還會故意使用錯誤值,確保工具能夠拒絕它們。我們也重新檢查了曾經透過舊版檢查的結果。

驗證基準本身也需要重建。修復它,就是修復遊戲的一部分。

當團隊幾乎就是一個人加一群程式設計助手時,這一點尤其重要。我無法逐行檢查它們寫出的所有程式碼,很多信心都來自檢查結果。共享驗證基準中的盲點,可能在我發現之前就影響許多調查。我必須弄清工具到底驗證了什麼,再用應當失敗的案例測試它。

隨著專案推進,檢查程式進入了程式碼儲存庫。原始碼修改的理由也儲存在裡面,還有讓下一次會話能夠接著做的記錄。程式碼儲存庫正在成為專案的工作記憶。

每完成一批工作,我們既得到了還原的程式碼,也改善了下一批工作的環境。

兩種不同的重建理念

GensokyoClub 的公開 README明確表達了對這種工作的異議。公告說,專案完成前,後續開發將在私下進行。其中有這樣一段話:

“這個領域裡出現了利用我們成果的投機者(AI 反編譯和移植專案),給未來的反編譯工作留下了不好的印象……”

公告也提到了維護者承受的心理壓力。他們的貢獻政策不接受主要由 AI 生成的 PR。他們用業餘時間投入了艱難的工作,這些成果讓我的續作成為可能。我尊重他們付出的努力。我想討論的分歧,是重建應當如何推進,以及貢獻應當如何評價。

在我熟悉的手工流程中,理解一個函式和重建它,通常由同一個人完成。專案非常依賴這個人的專業能力。很多推理發生在工作過程中,所以對貢獻者本人的信任很重要。

已有專案本就會在原始碼和構建工具中儲存知識。對我而言,變化在於:程式設計助手能利用這些知識,自主推進下一次調查。

在我的續作中,我來確定目標和驗收標準,助手有充分的調查自由。它提出的重建方案必須透過相應檢查。我希望其他人能夠看懂我們為什麼選擇這個實現,即使大部分工作由助手完成。

這可能是一個艱難的轉變。多年的細緻工作,可能成為一個推進得更快的續作的基礎。這會帶來真實的歸屬與署名問題,也改變維護者在接受貢獻前需要了解的事情。

工業化的比喻有助於理解這一點。手工作業的過程往往依賴操作者的技藝。機器改變了這些技藝發揮作用的位置,但仍然需要人設計流程、識別錯誤產出。不同社群可以選擇接受多少這樣的變化。

我的選擇是公開繼續,註明繼承的工作並保留其歷史。我希望新工作可以被審查。這樣,我們才能探索這種方法能走多遠,也從沿途的問題中學習。

來源:GensokyoClub 的README 公告(於 2026 年 10 月 10 日核對)及其貢獻政策。上面的引文為節選譯文。TH08 的貢獻署名與來源記錄說明了獨立續作的起點。

TH095:經驗開始產生複利

TH095,也就是《東方文花帖》,讓這些經驗的價值更容易看清。儲存庫於 8 月 29 日建立,當時臺賬中確認的遊戲函式數量為零。我們仍需研究遊戲本身,但已經更清楚如何開始重建,以及怎樣持續推進。

到 9 月 7 日,全部 697 個已識別遊戲函式都有了原始碼。9 月 8 日,其中 696 個透過了精確對比。9 月 9 日,整個程式完成連結。9 月 10 日,Windows i386 重建版被記錄為可玩,距離初始化約十二天。

這比第一個專案的速度更讓我興奮。新目標能受益於另一個遊戲的工作。經驗已經進入工具,也進入了專案的組織方式。

例如,TH08 教會我們儘早關注整個程式。如果幾個還原函式依賴同一份狀態,分別對比它們仍然會留下一個關鍵問題:它們能否一起正常工作?這條經驗影響了 TH095 的整程式構建方式。

經驗只記在我腦子裡,我在場時它才有用。變成其他會話能執行的檢查後,即使我離開,它仍能幫助專案。下一個助手可以利用檢查結果,不用重複當初得出這條經驗的調查。

浮點常量的 bug 也屬於這份記憶。它說明,檢查引用時,還要檢查引用背後的資料。把修正儲存在程式碼旁邊,可以幫助後續專案避免繼承舊工具的盲點。

方法本身成了下一個遊戲的起始材料。我們可以把更多精力放在新目標真正不同的地方。

後來加入的人也能受益。他們可以檢視某個決定,重新執行檢查,再繼續工作。不用先重走整個專案的歷史,才能理解原始碼為何這樣寫。

TH04:換了架構,工作方式仍然適用

TH04,也就是《東方幻想鄉》,把這套工作帶到了 PC-98 DOS 時代。這次是一個由四個程式協作的 16 位環境。理解硬體行為,需要和 Windows 遊戲不同的證據。已有的ReC98 工作同樣提供了寶貴的知識與原始碼材料。

DOS 重建版現在已經能執行。我手工打完了完整的 Normal 路線,看到結局,並檢查了存檔。目前正在做原生 64 位移植。先得到一個正常工作的 DOS 版,就為移植提供了參照。

架構改變了要調查的問題,也改變了用來驗證的編譯器和執行時。但助手依然能沿著問題找到結果,再用結果指導下一次實驗。

比如從遊戲過程切換到結局:哪些狀態需要跨越這個邊界?哪個程式負責它們?我們可以對照 DOS 原版調查。只要證據和檢查可用,助手就能像研究 Windows 遊戲一樣推進這個問題。

這就是 TH04 對這篇文章的意義。大幅的平臺變化,並沒有迫使我們重新發明一套工作方式。架構決定了問題,工作流程仍然提供瞭解決問題的方法。

做 64 位移植時,我們可以把新實現與 DOS 上已經還原的行為對照。重建得到的知識為移植提供了基礎。

截至 2026 年 10 月 10 日:DOS 重建與手工測試 · 64 位移植。移植仍在開發中。

從精確還原到可讀原始碼

重建版能執行之後,我還希望別人能讀懂它。

對我而言,彙編和原始偏移就像老朋友。我知道,這種“可讀”的定義有點特別。多數人更希望直接看懂遊戲邏輯,而不用在腦中記住可執行檔案的記憶體佈局。

這就需要語義重建。一個還原欄位可能仍然只有偏移作為標識。我們追蹤遊戲如何使用它,直到能解釋其作用,再依據證據賦予合適的名稱和型別。推理過程和原始碼一起儲存,後來的人就能知道這個解釋從何而來。

移植時,語義尤其重要。絕對地址能告訴我資料在舊程式中的位置,卻很難幫助 64 位實現決定哪個物件應當持有這份狀態。要正確遷移行為,就得還原舊記憶體訪問背後的關係。

我現在採用這樣的順序:

  1. 先建立精確還原的基線。用當年的編譯器編譯重建程式碼,與原始可執行檔案對比相關程式碼和資料。記錄尚未解決的差異,讓下一階段有明確的起點。
  2. 在原平臺上構建,並實際遊玩。用原架構和編譯器把各部分連結為真正的程式,走過重要的遊戲路徑。這能發現單函式對比漏掉的共享狀態或初始化問題。
  3. 對照兩套基準做語義重建。每次處理遊戲中一個完整、連貫的部分,明確還原原始碼的含義。改善程式碼表達,同時保留精確對比和可玩的原平臺構建。
  4. 再做現代平臺移植。把已經確定的行為帶入新環境,例如原生 64 位構建。原平臺重建版繼續作為比較移植行為的參照。

第二階段的可玩構建,在第三階段成為第二套驗證基準。第一套檢查修改後的原始碼是否仍然復現原版相關程式碼和資料;第二套檢查重建程式是否能構建,並在實際測試的路徑上保持正確行為。

它們能發現不同型別的錯誤。型別修改可能改變生成的指令。狀態歸屬的修改,可能讓遊戲的兩部分各自使用一份狀態。保留兩套檢查,助手就能在繼續重構之前,針對具體的失敗展開調查。

命名也需要自己的證據。精確對比不能證明某欄位一定是“無敵時間”。我們必須從遊戲如何寫入和使用它來確認。如果含義仍不明確,中性名稱比自信的猜測更有利於下一位讀者。

這個順序來自專案中的教訓。TH08 在後來的一些原平臺審計之前,就已經有了可玩的移植版,一些缺陷因此更難察覺。Factory 目前的工作流程把原平臺構建放在前面,讓語義重建先有參照,再開始移植。

精確重建提供基準,語義重建讓還原的知識可用。移植隨後建立在兩者之上。

為什麼這是工業化的轉變

這些專案改變了我投入注意力的地方。助手能自主推進大部分調查之後,改善它們的工作環境,就成了我最值得做的事情之一。一項工具的改進,可以幫助之後所有需要它的函式。

自主性在這裡很重要。下一步該怎麼做,常常在實驗失敗後才清楚。助手需要足夠的自由,沿著結果探索意料之外的方向。如果每一步都要等我指定,大部分工作仍然綁在我的注意力上。

我預期助手會提出錯誤假設。關鍵是我們能否驗證它們,並從結果中學習。失敗的檢查應該幫助它理解錯誤,再次嘗試。我仍要判斷:累積的證據是否足以支援某個專案里程碑。

REA 讓助手能夠使用分析工具。調查某函式的呼叫方時,它可以直接繼續檢查那個呼叫方。重建專案提供編譯器和自己的對照檢查。助手用它們驗證提出的原始碼,看看解釋在哪些地方成立。

TH08 的 bug 說明,檢查工具本身也值得認真工程化。相同的比較用於數百個函式時,一個漏洞的影響可能遠大於某個實現中的錯誤。測試檢查器,能改善所有後續工作得到的反饋。

工業史中有一個合適的例子:博爾頓和瓦特在1796 年引入蒸汽機示功器,幫助調節閥門。記錄式示功器能繪出活塞行程中的壓力變化,讓人看到機器內部的執行情況。我們的比較工具也有類似作用:改進機器時,能看清它究竟做了什麼。

我們正處於這場工業化轉變的早期。許多基礎設施還不成熟。助手推進工作的速度,可能超過原有檢查的承受能力,所以流程也要一起發展。共享工具出現缺陷時,要修好它,並重查受影響的結果。下一個專案才能繼承更可靠的工具。

任何一段對話都有實際的長度限制。大型重建完成之前,對話就會結束。程式碼儲存庫必須讓下一次會話能繼續工作,而不丟失上一次決定背後的理由。

Touhou Reconstruction Factory正是為此而建立。它提供一種共用方式,讓專案把檢查和經驗傳遞下去。一個遊戲的工作,可以改善另一個遊戲的起點。

這就是工業化比喻對我的意義:經驗開始進入別人也能使用的工具。改善工具,就能改變下一個人或下一個助手能完成多少工作。

現在值得嘗試的專案

速度的意義在於,它改變了是否開始一個專案的決定。某個遊戲也許很值得逆向,卻需要我投入遠超現實所能承受的精力。很多專案因此一直停留在想法裡。

現在,我看到了透過一次次調查持續推進它們的可能。得到能執行的重建版,讓移植更可行;還原可讀的語義,讓別人更容易探索 mod。理解遊戲的投入,可以在第一版執行之後繼續帶來回報。

現在看到一個陌生程式,我會問:怎樣的工具訪問、反饋和知識積累,能讓助手可靠地推進這個專案?

這個問題讓我考慮以前會放棄的專案。每個專案都能改善下一個專案的工作方式。我想繼續探索,這能帶我們走多遠。

專案里程碑與來源

這些日期是已記錄的專案檢查點,於 2026 年 10 月 10 日對照公開 GitHub 歷史核實。耗時是提交之間經過的日曆時間。“有原始碼”“透過精確對比”“完成構建”和“得到執行結果”是不同的里程碑。

更多文章 · 檢視 TH04 逆向案例

頂部