プログラムを改造する(2)
EU4のパッチに関する技術情報です。思い出しながらまた1からやっているので間違っている可能性あり。コードが汚いとか全部jmpでやってるとかはアセンブリ歴2ヶ月なので大目に見てください。あと画像が多いです。
前回
改造用にコードセグメントを追加
概要
exeの最後にセグメントを0x1000ほど追加。こうしないと修正コードが追加できません。
修正
下記を参考。
エスケープ化
概要
エスケープ化とは下記で言っているものです。ただしSJISはやめて、UCS2にしました。これで、UTF-8->UCS2>SJISがUTF-8->UCS2にできます。
その他に下記で起きた問題を解決するために、0x5Bもエスケープします。
そして問題のコードは下記です。
実はこのコードは、確かにlatin1以外の文字を0x3F(?)に変えてしまいますが、それで終わりではなく、その文字がプログラム内部のテーブルに定義されている特定の文字(€など)だったりすると、0x3Fを0x8x~0x9xの指定された値に置き換える処理があります。そしてそのテーブルにもない場合には破棄されて、結果として0x3Fが残るようになっています。
よってそこの処理を変えて、MultiByteToWideCharを置けば、3Fになってしまった文字にUTF-8からUCS2にするチャンスができます。MultiByteToWideCharのアドレスはrelocする必要があります。relocの追加方法は下記を参考にします。
エスケープするのは下記です。
- 1バイト目が0x00 -> 頭に0x11 1を足したUCS2
- 1バイト目が0x5B -> 頭に0x11 1を足したUCS2
- 2バイト目が0x5B -> 頭に0x12 0x100を足したUCS2
- それ以外 -> 頭に0x10 UCS2
問題点として下記があります。
- 1文字づつ変換することになるので遅い。
- 3バイト以上の文字(BMP外)が来るとバグる。
- 0x5B 0x5B → 知らない子ですね。
- 0x5B 0x00 → 知らなry)
- 他にエスケープする必要がある文字があった → 作り直し\(^o^)/
修正
ヒープ拡張
概要
ビットマップフォントはデータへのアドレスが配列で置かれています。どういうことかは下記を見てください。
EU4でそれ用に確保されているヒープサイズは0x400、つまり4バイトが256しか入りません。しかもlatin1以外も普通に読み込んでしまうために用意に天元突破(メモリ破壊)します。ビットマップフォントを日本語用にすげ替えて落ちたらそれです。
ここからひたすら地道な作業を続けることによって0x2820というヒープサイズ指定を見つけます。
この領域の先頭からオフセット0xB4進んだところから0x400が上記の配列の領域になっています。
0x400の領域を動かすのは大変なので、0x2820の後ろにヒープを拡張して、使えない領域(後述)は運用で回避しましょう。拡張するサイズはとりあえず65536*4=0x3FFFCあればいいです。
拡張したヒープを開放する箇所もあります。これも変えます。
そして上記のコードはランチャー用のヒープ確保のコードなので、本体用のヒープ確保のコードも変える必要があります。本体はサイズがなぜか0x2850になっています。
問題点として下記があります。
- 0x2820 - (0xB4+0x400)の領域には何か別のものが入っているので、その部分に当たるUCS2(0x100~0x9DB)はつかえない。キリル文字、ギリシャ文字、一部のアクセント付き文字が使えない。将来的に解決したい。
- 0x2850 - 略)
修正
pushは4バイトなので0x2820→0x42820は簡単。0x2850も同じ。
プログラムを改造する(3)へ続く