pop↑ push↓

☆ (ゝω・)v

プログラムを改造する(2)

EU4のパッチに関する技術情報です。思い出しながらまた1からやっているので間違っている可能性あり。コードが汚いとか全部jmpでやってるとかはアセンブリ歴2ヶ月なので大目に見てください。あと画像が多いです。

前回

popush.hatenablog.com

改造用にコードセグメントを追加

概要

exeの最後にセグメントを0x1000ほど追加。こうしないと修正コードが追加できません。

修正

下記を参考。

popush.hatenablog.com

エスケープ化

概要

 エスケープ化とは下記で言っているものです。ただしSJISはやめて、UCS2にしました。これで、UTF-8->UCS2>SJISがUTF-8->UCS2にできます。

popush.hatenablog.com

その他に下記で起きた問題を解決するために、0x5Bもエスケープします。

popush.hatenablog.com

そして問題のコードは下記です。

popush.hatenablog.com

実はこのコードは、確かにlatin1以外の文字を0x3F(?)に変えてしまいますが、それで終わりではなく、その文字がプログラム内部のテーブルに定義されている特定の文字(€など)だったりすると、0x3Fを0x8x~0x9xの指定された値に置き換える処理があります。そしてそのテーブルにもない場合には破棄されて、結果として0x3Fが残るようになっています。

f:id:saito-matanki:20170929215908p:plain

よってそこの処理を変えて、MultiByteToWideCharを置けば、3Fになってしまった文字にUTF-8からUCS2にするチャンスができます。MultiByteToWideCharのアドレスはrelocする必要があります。relocの追加方法は下記を参考にします。

popush.hatenablog.com

エスケープするのは下記です。

  • 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^)/

修正

f:id:saito-matanki:20170930112354p:plain

ヒープ拡張

概要

 ビットマップフォントはデータへのアドレスが配列で置かれています。どういうことかは下記を見てください。

popush.hatenablog.com

EU4でそれ用に確保されているヒープサイズは0x400、つまり4バイトが256しか入りません。しかもlatin1以外も普通に読み込んでしまうために用意に天元突破(メモリ破壊)します。ビットマップフォントを日本語用にすげ替えて落ちたらそれです。

ここからひたすら地道な作業を続けることによって0x2820というヒープサイズ指定を見つけます。

f:id:saito-matanki:20170930003128p:plain

この領域の先頭からオフセット0xB4進んだところから0x400が上記の配列の領域になっています。

f:id:saito-matanki:20170930003351p:plain

0x400の領域を動かすのは大変なので、0x2820の後ろにヒープを拡張して、使えない領域(後述)は運用で回避しましょう。拡張するサイズはとりあえず65536*4=0x3FFFCあればいいです。

拡張したヒープを開放する箇所もあります。これも変えます。

f:id:saito-matanki:20170930004413p:plain

そして上記のコードはランチャー用のヒープ確保のコードなので、本体用のヒープ確保のコードも変える必要があります。本体はサイズがなぜか0x2850になっています。

f:id:saito-matanki:20170930005142p:plain

問題点として下記があります。

  • 0x2820 - (0xB4+0x400)の領域には何か別のものが入っているので、その部分に当たるUCS2(0x100~0x9DB)はつかえない。キリル文字、ギリシャ文字、一部のアクセント付き文字が使えない。将来的に解決したい。
  • 0x2850 - 略)

修正

pushは4バイトなので0x2820→0x42820は簡単。0x2850も同じ。 f:id:saito-matanki:20170930005631p:plain f:id:saito-matanki:20170930010201p:plain f:id:saito-matanki:20170930010243p:plain

f:id:saito-matanki:20170930010359p:plain f:id:saito-matanki:20170930010423p:plain f:id:saito-matanki:20170930010456p:plain

プログラムを改造する(3)へ続く