PalmOS 5.x Hack開発講座 第5回 「メニューの文字化けを直す」
今回は、海外製のアプリケーションでたまに見られる「メニューの文字化け」を直してみましょう
前回同様に、一番新しいCodeWarrior、バージョン9.3を使ってお話してゆきます CodeWarriorをお持ちでない方でも役に立つ情報があるはずですので一通り目を通してみてください
えー、改めて僕の環境を...
[CodeWarrior Development Studio for Palm OS Platform, Version 9.3, Professional Edition]の英語版と[WindowsXP-SP2-RC2]の英語版でございます
今回は、僕が用意したプロジェクトをベースに解説して行くことにいたしますので、ここからアーカイブをダウンロードして、まずは眺めてみてください
何をするHackかわからないと話が進みませんね 今回作成したHackの概要をざっと...
まず、YAHMと解凍したアーカイブの中の[To-f-Hack-ARM-CW.prc]をインストールしてください
とりあえずYAHMを起動して、メニューを開いてみると...
見事に化けていますよね では、今回作成したHack(うまく名前を書けないのでTo-f-Hackとしましょうか)を有効にしてから同じようにメニューを開くと...
どうでしょう 三個の文字化けを見つけたよというメッセージの後に、きちんと修正されたメニューが表示されました
今回は、設定パネルとHackの情報に関する部分もきちんと書いていますので、 と をタップすると...
というパネルが表示されます ごくごく簡単なHackですが、Hack作成に必要な情報は全て盛り込んであります
今回も二つのAPIをトラップしています
まず、一番目
メニューリソースをアプリケーションから読み出してきてダイナミックヒープに書き出す[ResLoadMenu]
このAPIが実行されると、メニューリソースがダイナミックヒープ上に配置されるので、配置されたデータをスキャンして文字化けがあればをちょこちょこっと修正※あとで触れますが、メニューに関する構造体はOS5.xで変更されていますので注意
もうひとつ、
動的にメニューに項目を追加する[MenuAddItem]です
こっちは単純、第四引数で渡される文字列をスキャンして文字化けがあればこれも修正
他にも[WinDrawChars]をトラップするという方法も取れますが、「可能な限り上流側をトラップする」のがHackの定石ですので、今回はこの二つをトラップすることにしました
概要はこのくらいにして、今回のプロジェクトを眺めてみましょう
今回のプロジェクトは、Hack作成に必要になるエッセンスを全て盛り込んであるので、かなり盛りだくさんです
まずは、[To-f-Hack-ARM-CW.mcp]を開いてみてください このプロジェクトは次のような構成になっています
左側がファイルの構成、右側がターゲットの構成です いや、いっぱいありますが、全部で五つのターゲットに分かれていますので下流側から順番に、
まず、五番目
[MenuAddItem-03e9]ターゲット
二番目にトラップするAPIを置き換えるHackコードですね このターゲットで[armc03e9.bin]リソースを生成します
四番目
[ResLoadMenu-03e8]ターゲット
一番目にトラップするするAPIを置き換えるHackコード ここでは[armc03e8.bin]リソースの生成ですね
三番目
[ARMRes]ターゲット
Hackコードの中で使用するリソースです ここでは[aalt9000]リソースを含むダミーのリソースデータベース[ARMResTmp.prc]が生成されます
PilRCでリソースをコンパイルするときに[-LE32]という引数をつけてあげて、OS5ネイティブのリソースを生成してもらいます 「x個文字化けを見つけたよ」というダイアログはここで記述しています
OS5ネイティブであるリソースは、今回作成した「アラート」のほかに「フォーム」、「メニュー」、「ビットマップ」などがありますので、これらのリソースを使用する場合はOS5ネイティブで作成してあげることに気をつけてください
もう少しです、二番目
[68kRes]ターゲット
こちらは、設定パネル、情報表示に関するリソースを生成する部分で、普通に68kコードから呼ばれるので、ごく普通に作ってあげればOKです ここでは[tFRM2000]および[tFRM3000]リソースを含むダミーのリソースデータベース[68kResTmp.prc]を生成します
わざわざ分けるのが面倒なときは、先の[ARMRes]ターゲットに含めてしまっても良いでしょう 68kコードからはレガシーなリソースでも、OS5ネイティブなリソースでも、どちらでも気にせずに呼んでしまっても大丈夫ですので...
では、最後の一番目
[Application]ターゲット
一番最後に全てのターゲットをまとめあげます 設定パネルに関するコードとHackに関するリソース[HackRes.rcp]をコンパイルして、[68kResTmp.prc]、[ARMResTmp.prc]、[armc03e8.bin]および[armc03e9.bin]をくっつけて、最終的な[To-f-Hack-ARM-CW.prc]を生成します
どうですか? では、順番に解説を入れていきましょう
さて、簡単なところから攻めて行きましょうか
3.2.ARMに関係の無いところから... [Application]、[68kRes]、[ARMRes]ターゲット
ここは簡単、前回までと一緒です
アプリケーション名[tAIN]とバージョン[tver]の記述
// HACKRes.rcp APPLICATIONICONNAME ID 3000 "\x85 to \x18 Hack" VERSION ID 1 "phs sample"
次、どのAPIをトラップするつもりであるかをHackマネージャに教えてあげるための[TRAP]リソースならぬ[TRA5]リソースの記述
// ResLoadMenu armc 0x03e8 // UITable 0x408 ResLoadMenu HEX "TRA5" ID 0x03e8 00 00 00 12 00 00 0x04 0x08 00 00 00 00 // <- ARM 00 00 00 00 00 00 00 00 // MenuAddItem armc 0x03e9 // UITable 0x3A8 MenuAddItem HEX "TRA5" ID 0x03e9 00 00 00 12 00 00 0x03 0xa8 00 00 00 00 // <- ARM 00 00 00 00 00 00 00 00
リソース定義ファイルはこれだけ 簡単ですね
※頭の片隅においておいて欲しいことがひとつあります この[TRA5]リソースの3行目、コメントに[<-ARM]と書いてある部分ですが、[00 00 00 00]とするとARMインストラクションセット(以下ARMコード)、[00 00 00 01]とするとThumbインストラクションセット(以下Thumbコード)でコンパイルされたコードですよというようにYAHMが扱ってくれる決まりになっていますし、YAHMのドキュメントにもそのように書かれています
実は、この記述は間違いではないのですが、より厳密に表現すると、「コードのエントリーポイントがARMコード、もしくはThumbコードですよ」ということになります(ThumbコードというのはARMコードの縮小インストラクションセットで、ひとつのオペランドは基本的に2バイトで表現されます、うまく利用するとコードサイズをかなり小さくできるという利点がありますが、利用できるレジスタに制限があるため、場合によってはコードサイズが大きくなってしまうこともあります 実行速度はARMコードに比べて若干遅くなることが多いのですが、メモリアクセスのバス幅が16ビットの場合はかえって早くなったりして、うまく使うとコードサイズを節約しつつ早いアプリケーションが書けたりします ひとつのコード中にARMコードとThumbコードは混在可能ですので、そのうち使い分けのTipsなんてお話できるといいですね)
後で述べますが、APIを置き換える関数はARMコードではなくThumbコードでコンパイルしています ただし、エントリーポイントだけはARMコードとしているので、ここでは[00 00 00 00]と記述しています
拡張子が[cpp]なのですが、中身はcでございます ここでは、Hackの設定に関する処理を記述しています
この辺のお話はレガシーなHackと同様ですので説明は省きましょう ソースを載せておくだけにします (英語環境なのでコメントをほとんど入れていませんが勘弁くださいね)
// CnfFrmHandler.cpp #include <PalmOS.h> #include "68kRes.h" #define CRID 'To-f' #define ConfigFormEntry __Startup__ extern "C" Boolean ConfigFormEntry(EventType *eventP); static Boolean ConfigFormHandler(EventType *eventP) { Boolean result = false; switch(eventP->eType) { case ctlSelectEvent: switch(eventP->data.ctlSelect.controlID) { case DoneBtn: FormPtr frmP = FrmGetActiveForm(); UInt16 objIndex = FrmGetControlGroupSelection(frmP, 1); UInt32 which = FrmGetObjectId(frmP, objIndex) - ellipsPb; FtrSet(CRID, 0, which); FrmGotoForm(9000); // return to YAHM result = true; break; } } return result; } Boolean ConfigFormEntry(EventType *eventP) { if(eventP->eType == frmOpenEvent) { UInt32 which = 0; FtrGet(CRID, 0, &which); FormPtr frmP = FrmGetActiveForm(); FrmSetControlGroupSelection(frmP, 1, ellipsPb + which); FrmDrawForm(frmP); FrmSetEventHandler(frmP, &ConfigFormHandler); return true; } return false; }
ここでは、Hackの設定に関するリソースと情報表示のためのリソースを記述しています
ここもソースを載せておくだけにします
// 68kRes.rcp GENERATEHEADER "68kRes.h" RESETAUTOID 7999 FORM 3000 AT (2 80 156 78) MODAL USABLE BEGIN TITLE "\x85 to \x18 Hack" LABEL "\x85 to \x18 Hack" AUTOID AT (CENTER 20) USABLE FONT 1 LABEL "Freeware" AUTOID AT (CENTER 40) USABLE BUTTON "Done" 1 AT (8 59 AUTO AUTO) USABLE END FORM ID 2000 AT ( 2 2 156 156 ) MODAL BEGIN TITLE "\x85 to \x18 Hack" BUTTON "Done" ID DoneBtn AT (8 137 36 AUTO) LABEL "Simple Configuration Form" AUTOID AT (12 27) PUSHBUTTON "\x18" ID ellipsPb AT (38 99 26 23) GROUP 1 FONT 7 PUSHBUTTON "_" ID usPb AT (65 99 26 23) GROUP 1 FONT 7 PUSHBUTTON "-" ID minusPb AT (92 99 26 23) GROUP 1 FONT 7 END
ここでは、Hackコードから呼び出すリソースを記述しています PilRCのオプションに[-LE32]をくっつけるのを忘れずに
// ARMRes.rcp GENERATEHEADER "ARMRes.h" RESETAUTOID 8999 ALERT ID FoundMessage CONFIRMATION BEGIN TITLE "\x85 to \x18 Hack" MESSAGE "Found ^1 \x85 ." BUTTONS "OK" END
ここはこれだけ 特に説明はいらないでしょう
あ、「PilRCのオプションに[-LE32]をくっつけるのを忘れずに」といっても、どこで付けたら良いのかわかりますか? ここです
さて、外堀は埋まりました ちょっと長くなったので、肝心要のHackコードに関するお話は次回にもちこしましょう
第6回「メニューの文字化けを直す」その2へ
質問、感想などはPalmHackersSalonのBBSへ