galgame漢化簡述

研究了一下水晶社這個引擎,簡單講下怎么漢化
聲明
由于本人能力有限,對引擎只有一個很粗略的了解,以下內(nèi)容不可避免會出現(xiàn)很多錯誤,歡迎大佬指出??
分析基于CRYSTALiA的RE:D Cherish!,不同版本可能存在差異
vm簡述
想漢化這個引擎的游戲,分析vm是必不可少的。漢化需要關(guān)心的最主要文件是data.pac中的SCRIPT.SRC和TEXT.DAT??


SCRIPT.SRC是引擎的核心邏輯腳本,除開前0xC個字節(jié),均屬于vm指令,其中開頭4字節(jié)為文件頭,另外8字節(jié)未知。
TEXT.DAT則是一些需要用到的字符串(包括文本),另外還會用到FILE.DAT等文件
所有開頭第一個字節(jié)為$(0x24)的文件都會加密,解密過程大致如下(注意解密是從文件的0x10開始的)。

下面以一些常用指令為例進(jìn)行簡略說明
1F 00 01 00 FF FF FF 0F ?
1F 00 01 00為vm的opcode,表示向棧中push一個值。FF FF FF 0F 則為push的值。??
該vm中,push的值大致可以分為常量與變量兩種。此處的0x0FFFFFFF代表null,小于0x0FFFFFFF代表push的是一個常量,0x40000000開始則代表一個變量,指令會從變量區(qū)中獲取值再進(jìn)行push(實(shí)際劃分會更細(xì))
1F 00 01 00 00 00 00 00 1F 00 01 00 49 54 00 00
1F 00 01 00 76 54 00 00 1F 00 01 00 F8 4C 00 00
17 00 01 00 02 00 02 00 00 00 00 00 ?
前0x20字節(jié)代表4次push。17 00 01 00為vm的opcode,代表call。02 00 02 00代表call的具體函數(shù),高位0x02描述了該函數(shù)的大致分類,此處為text相關(guān)函數(shù),低位0x02代表具體操作,此處為根據(jù)參數(shù)獲取字符串并渲染,同時會獲取文本需要調(diào)用的語音。最后4字節(jié)應(yīng)該是函數(shù)有返回值時需要寫入的變量區(qū)地址??
1F 00 01 00 F8 4C 00 00 為本條文本需要調(diào)用的語音。該值會作為索引從FILE.DAT中尋找要調(diào)用的具體文件。具體計(jì)算方式為(value<<5)+0x10 ?
1F 00 01 00 76 54 00 00 為本條文本需要渲染的角色名 ?
1F 00 01 00 49 54 00 00 為本條文本需要渲染的具體文本 ?
角色名與渲染文本都是一個TEXT.DAT中的直接偏移
可以看出0x100??統(tǒng)一為這個vm的opcode,另外還有如0x1000A表示if等,這里就不不多做贅述了。了解虛擬機(jī)可以方便分析出引擎的各種問題。
知道了渲染文本的函數(shù)后,我們便可以通過改指令獲取文本在TEXT.DAT中的偏移(其實(shí)還涉及到0x2000F與0xF0002等函數(shù)),當(dāng)然你也可以直接dump
提取文本翻譯后將修改的文本重新導(dǎo)入TEXT.DAT。同時修改SCRIPT.SRC中對應(yīng)指令push的偏移。不過雖然我一直在說修改TEXT.DAT和SCRIPT.SRC,可我個人還是感覺直接HOOK會比較好,畢竟TEXT.DAT的更改可能會導(dǎo)致很多問題
另外還有一點(diǎn)需要注意,vm跳轉(zhuǎn)的方式是通過獲得一個POINT.DAT中的索引來獲取需要跳轉(zhuǎn)的地址。涉及到具體的opcode索引的計(jì)算方式似乎還會有細(xì)微差異,最常用的一種應(yīng)該是[pointDatSize-(value<<2)]+0xC。想添加vm指令的話就需要將所有跳轉(zhuǎn)修正,估計(jì)不會很容易。所以要避免翻譯把一句話拆成幾句話導(dǎo)致需要插入額外的渲染指令,不然讓他自己修跳轉(zhuǎn)(霧)
邊界修改
知道如何提取文本后,替換文本后。就需要修改邊界了。游戲在exe和pal.dll中各有一次邊界校驗(yàn)
exe中的邊界如下

修改0x81,0x9F,以及0xBC至中文編碼邊界便可
pal.dll中的邊界如下

通過渲染字符的首字節(jié)查表判斷該字符的字節(jié)數(shù)
用ida打開的話可以看到其實(shí)是用的_mbsnextc

這個表是初始化得來的,并不能直接在dll里搜到,需要在dll里搜索
A6 DF 00 00 00 00 00 00?
A1 A5 00 00 00 00 00 00
81 9F E0 FC 00 00 00 00?
40 7E 80 FC 00 00 00 00
然后修改81 9F和80 FC即可
渲染模式
這個引擎有字庫和gdi兩種方式獲取字模。

字模的獲取方式會在游戲初始化時用palFontSetType設(shè)置,在此修改即可(貌似是從SYSTEM.INI里取的值,沒有試過,不太清楚)
如果采用字庫模式,游戲會從system.pac中的DEFAULT_FONT.DAT中獲取字模(其實(shí)還有一個額外字庫,不過并不怎么重要)
引擎會以字符為索引得到一個偏移,在跳轉(zhuǎn)到偏移處獲得字模數(shù)據(jù)。
具體索引計(jì)算方式為:(((highByte>>8)-0x80)*0xFF)+lowByte
使用這種方式的話,游戲還會有一個縮放因子,用于縮放字模。
或者直接修改模式使用gdi獲取字模。
之后再進(jìn)行一些處理后拿去繪制(游戲會為字模計(jì)算一個邊框)
TIPS顯示
游戲的TIPS條目信息采用csv.pac里的TIPS.CSV存儲

直接修邊編碼會導(dǎo)致tips?mode中的按鈕失效

這是因?yàn)橛螒蚩繖z測每行第二項(xiàng)(也就是注音)的字符來分類并排序tips,修改編碼后所有條目均不在游戲的檢測范圍內(nèi)
有兩種方式修改
1 用中文編碼下該注音編碼所對應(yīng)字符進(jìn)行替換,簡單快捷,就是可能會不太好看
2?修改游戲檢測范圍,exe中找到
82 A0 82 A2 82 A4 82 A6 82 A8 82 A9 82 AB 82 AD
82 AF 82 B1 82 B3 82 B5 82 B7 82 B9 82 BB 82 BD
82 BF 82 C2 82 C4 82 C6 82 C8 82 C9 82 CA 82 CB
82 CC 82 CD 82 D0 82 D3 82 D6 82 D9 82 DC 82 DD
82 DE 82 DF 82 E0 82 E2 81 40 82 E4 81 40 82 E6
82 E7 82 E8 82 E9 82 EA 82 EB 82 ED 82 EE 82 EF
82 F0
隨后替換應(yīng)該可以滿足基本需求
上面是漢化會碰到的一些麻煩,如果按我講的方式漢化還有遇到選項(xiàng),voice頭像顯示等問題。這里我就不細(xì)說了,有愛的小伙伴可以自己動手
另外這游戲黃毛的母上真是好看啊,不能推真是可惜
