PalmOS 5.x Hack開発講座 第5回 「メニューの文字化けを直す」

1.題材

 今回は、海外製のアプリケーションでたまに見られる「メニューの文字化け」を直してみましょう

 前回同様に、一番新しいCodeWarrior、バージョン9.3を使ってお話してゆきます CodeWarriorをお持ちでない方でも役に立つ情報があるはずですので一通り目を通してみてください

 えー、改めて僕の環境を...

 [CodeWarrior Development Studio for Palm OS Platform, Version 9.3, Professional Edition]の英語版と[WindowsXP-SP2-RC2]の英語版でございます

 今回は、僕が用意したプロジェクトをベースに解説して行くことにいたしますので、ここからアーカイブをダウンロードして、まずは眺めてみてください

2.作成したHackの概要

 何をするHackかわからないと話が進みませんね 今回作成したHackの概要をざっと...

 まず、YAHMと解凍したアーカイブの中の[To-f-Hack-ARM-CW.prc]をインストールしてください

 とりあえずYAHMを起動して、メニューを開いてみると...

 

 見事に化けていますよね では、今回作成したHack(うまく名前を書けないのでTo-f-Hackとしましょうか)を有効にしてから同じようにメニューを開くと...

  

 どうでしょう 三個の文字化けを見つけたよというメッセージの後に、きちんと修正されたメニューが表示されました

 今回は、設定パネルとHackの情報に関する部分もきちんと書いていますので、 をタップすると...

 

というパネルが表示されます ごくごく簡単なHackですが、Hack作成に必要な情報は全て盛り込んであります

2.1.トラップするAPI

 今回も二つのAPIをトラップしています

 まず、一番目

メニューリソースをアプリケーションから読み出してきてダイナミックヒープに書き出す[ResLoadMenu]
このAPIが実行されると、メニューリソースがダイナミックヒープ上に配置されるので、配置されたデータをスキャンして文字化けがあればをちょこちょこっと修正

※あとで触れますが、メニューに関する構造体はOS5.xで変更されていますので注意 

 もうひとつ、

動的にメニューに項目を追加する[MenuAddItem]です
こっちは単純、第四引数で渡される文字列をスキャンして文字化けがあればこれも修正

 他にも[WinDrawChars]をトラップするという方法も取れますが、「可能な限り上流側をトラップする」のがHackの定石ですので、今回はこの二つをトラップすることにしました

 概要はこのくらいにして、今回のプロジェクトを眺めてみましょう

3.プロジェクトを眺めてみよう

 今回のプロジェクトは、Hack作成に必要になるエッセンスを全て盛り込んであるので、かなり盛りだくさんです

3.1.プロジェクトの構成

 まずは、[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]ターゲット

3.2.1.[HACKRes.rcp]

 ここは簡単、前回までと一緒です

 アプリケーション名[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]と記述しています

3.2.2.[CnfFrmHandler.cpp]

 拡張子が[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;
}

3.2.3.[68kRes.rcp]

 ここでは、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

3.2.4.[ARMRes.rcp]

 ここでは、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へ

T-Pilot sekino