PalmOS 5.x Hack開発講座 第2回 「m68kHackの組みたて」

1.題材

 前回は、「テキスト入力フィールドの下線を点線ではなくて実線にしてしまう」Hackを組んでみようというところまでお話しました

 どのAPIをトラップすればよいか、二つ見つけることができましたか?

2.まずはm68kHackから

 m68kHackであれば、PalmOSEmulatorを使ったデバッグができますので、まずはm68kHackを書いてみましょうね

 まず、トラップするAPIの選定です

 [Palm OS Programmer's API Reference]を参照して、まずフィールドリソースがどのようになっているか見てみます [FieldType Struct]の部分と、[FieldAttrType Struct]の部分です

 今回トラップしようとしているフィールドの下線に関する設定は、FieldType構造体の中の3番目、[FieldAttrType attr]、日本語で言うと「属性」の中の、9番目[underlined]をどのようにするかで行っているようで、設定できる値は、noUnderline、grayUnderline、solidUnderline、colorUnderlineの四つだそうです

 さて、今回の目的を達成するには、この[underlined]を常に[solidUnderline]となるようにしてあげれば良いだろうということになります

 次は、この[FieldAttrType attr]に絡むAPIを探してみましょう

 まず、一番目

フィールドを描画するAPIである[FldDrawField]
ここでは、引数として渡される[FieldType *fldP]の中に、「属性」の情報が含まれてきますので、この「属性」をちょいちょいと修正

 もう一つ、

フィールドの「属性」を設定する[FldSetAttributes]です
このAPIは「属性」の設定そのものです 第二引数として渡される[const FieldAttrType *attrP]の中身をちょいちょいと...

 さて、下準備は整いました Hackを書いてゆきましょう

 そうそう、フォルダの構成を揃えておきましょうね 今回はcドライブのルートに[m68kHack]というフォルダを作成し、さらに[solidLineHack]というサブフォルダを作成して、これから記述するファイルを置くことにします [c:\m68kHack\solidLineHack] ついでにこのフォルダをマウントしておきましょう [mount -tf "c:\m68kHack" /m68kHack] こうしておくと、[cd /m68kHack]とタイプするだけで[m68kHack]ディレクトリに移動できます

2.1.リソース定義ファイル[*.rcp]の記述

 PilRCに渡すリソース定義ファイル[*.rcp]を記述します [solidLineHack.rcp]としましょう

 アプリケーション名[tAIN]とバージョン[tver]の記述


APPLICATIONICONNAME ID 3000 "solidLineHack-m68k"
VERSION ID 1 "m68k"

 まあ、こんなものだと思ってください

 次、どのAPIをトラップするつもりであるかをHackマネージャに教えてあげるための[TRAP]リソースの記述
 今回は、一番目に
[FldDrawField]を、二番目に[FldSetAttributes]をトラップすることとして、この順番で記述します

CoreTraps.hを参照して、上記二つのAPIのTrapNo.を調べてください
 #define sysTrapFldDrawField 0xA135
 #define sysTrapFldSetAttributes 0xA150
 と書かれていますね メモメモ...と

 では、書いてみましょう


HEX "TRAP" ID 1000
0xA1 0x35
HEX "TRAP" ID 1001
0xA1 0x50

 リソース定義ファイルはこれだけ 簡単ですね

2.2.置き換え実行コード(APIの代わりに呼び出される実行コード)の記述

2.2.1.[FldDrawField]置き換えコードの記述

 まずは一番目の[FldDrawField]の代わりに呼ばれるコードを書いてみましょう 先ほど記述した[TRAP]リソースのIDにあわせて[code 1000]リソースとして作成しますので、[code03e8.c]とします(03e8は16進数表記で、10進数に直すと1000)

 では、書いていきます

 必要なヘッダファイルをインクルードします


#include <Standalone.h> 
#include <PalmOS.h> 

 ここは特にコメントはありません 次


#define RESID 1000
STANDALONE_CODE_RESOURCE_TYPESTR_ID("code", RESID); 

 これは、「今書いているコードは[code 1000]リソースにするつもりですよ」ということを書いています

 一つ目のdefine文はコード中で使用する定数の記述、二つ目の[STANDALONE...]は[Standalone.h]で定義されているマクロで、「コンパイラに[code 1000]としてコードを作成してくださいね」とお願いするための記述です 次


typedef void (*osApiFldDrawField)(FieldType *fldP);

 もともとのAPIを利用する場合に必要な一文です

 Hackマネージャは、もともとのAPIのアドレスを参照できる仕組みを用意してくれていますが、このAPIのアドレスだけ分かっても、そのアドレスに対してどのように引数を渡せばよいのか、またどんな値が戻ってくるのかはコンパイラは知りません そこで、この一文を書くことで、コンパイラに対してもともとのAPIがどういうものかを教えてあげることが必要になります (以下、「もともとのAPI」を「osAPI」と書きますよ)

 [Field.h]を参照して[FldDrawField]がどのように定義されているか見てみましょう


extern void FldDrawField (FieldType *fldP)
	SYS_TRAP(sysTrapFldDrawField);

 戻り値は[void]、引数は[FieldType *fldP] 戻り値と引数の型を合わせていることがお解りですね

 さて、ようやく心臓部にたどり着きました


void myApiFldDrawField(FieldType *fldP)
{
	osApiFldDrawField osApiTrap;
	FieldAttrType attr;

	FldGetAttributes(fldP, &attr);
	FldSetAttributes(fldP, &attr);

	FtrGet(CRID, RESID, (UInt32 *)&osApiTrap);
		osApiTrap(fldP);
} 

 まず[void myApiFld...] これは[置き換え実行コード](関数)の宣言です ここも、戻り値と引数の型を[FldDrawField]に合わせておきましょう

 次、[osApiFldDrawField osApiTrap;] さっき定義した型がでてきましたね ここで宣言する変数[osApiTrap]は、osAPIのアドレスを格納して、osAPIを呼び出すために使います

 次の[FieldAttrTyp...]からは簡単 一時的にフィールドのアトリビュートを格納する変数を宣言して、[FldGetAttributes]でフィールドのアトリビュートを取得 そのまま[FldSetAttributes]でフィールドのアトリビュートをセット

 そして、osAPI(ここでは[FldDrawField]ですね)のアドレスを取得して、osAPIを呼び出して... 戻る

※osAPIのアドレスは、Hackマネージャが自分のクリエータIDとリソースIDでアクセスできるフィーチャに格納してくれています

 どうでしょうか 「何もしていないのと同じじゃないか」と思われる方もいらっしゃると思いますが、その理由は後でお解りになるはずです

2.2.2.[FldSetAttributes]置き換えコードの記述

 ここでは、二番目の[FldSetAttributes]の代わりに呼ばれるコードを書いてゆきます 先ほど記述した[TRAP]リソースのIDにあわせて、今度は[code 1001]リソースとして作成しますので、[code03e9.c]とします(03e9は16進数表記で、10進数に直すと1001)

 では、書いていきますが、特に説明は必要ない部分は飛ばして


FieldAttrType attr;
MemMove(&attr, attrP, sizeof(FieldAttrType));

if(attr.underlined == grayUnderline)
	attr.underlined = solidUnderline;

 ここが、今回のHackの一番のポイントでしょうか

 セットされようとしているフィールドのアトリビュートをコピーして、その中のメンバである[underlined]の値を調べ、[grayUnderline]だったら[solidUnderline]に直しています

 あとはosAPIに[修正を加えたアトリビュート]を渡しておしまい

 どうでしょうか 難しくないですよね

 そうそう、先ほど書いた[FldDrawField]の置き換え関数の中で、[FldSetAttributes]をコールしていました つまり、[FldDrawField]が呼ばれたときは必ず[FldSetAttributes]も呼ばれるように仕組んだわけです この[FldSetAttributes]はすでに置き換えていますので、ここで書いた[FldSetAttributes]の置き換え関数が呼ばれて、フィールドの下線は実線にされてしまう訳

 あとはコンパイルを残すのみ もう一息です

3.shellコマンドリストの作成

 Cygwinのshellコマンドリストを作成しましょう コンパイルするたびに、いちいちタイプしていては面倒ですからね (shellコマンドリストというのはDOSのバッチファイルのようなものと捉えてください)

 ここでは、[compile.sh]として作成します このshellコマンドリストを実行するときは[sh compile.sh]とタイプすればOK

 まず一行目


pilrc -q -ro solidLineHack.rcp

 ここは、[solidLineHack.rcp]で記述した[tAIN]、[tver]および二つの[TRAP]リソースをPilRCにお願いして作ってもらうところです

 次 ちょっと長いですが[code03e8.c][code03e9.c]をコンパイルして[code 1000]および[code 1001]リソースを作ってくださいとコンパイラにお願いする部分です


m68k-palmos-gcc -Wall -Wno-multichar -fshort-enums -fpack-struct -O1 -DCRID=\'SolL\' -nostartfiles -D_m68k_HACK_ -c -o code03e8.o code03e8.c

m68k-palmos-gcc -nostartfiles -o code03e8 code03e8.o

m68k-palmos-gcc -Wall -Wno-multichar -fshort-enums -fpack-struct -O1 -DCRID=\'SolL\' -nostartfiles -D_m68k_HACK_ -c -o code03e9.o code03e9.c

m68k-palmos-gcc -nostartfiles -o code03e9 code03e9.o

 よくよく眺めればなんとなく分かると思うので説明は省きます というよりも、僕もよく解らないままなのですが...

 ちょっと注意していただきたいのは[-DCRID=\'SolL\']の部分です さきほど作成した[code03e8.c][code03e9.c]のなかで、[CRID]を定義しないまま使っていましたよね お気づきになりました? じつは、ここで定義するつもりだったのです (もちろんコード中に記述することもできますよ)

 そうそう、今回は[SolL]とします [solidLineHack]という意図で、きちんとレジストしてありますのでこれを使ってください

 さて、お次は全てをまとめてひとつのリソースデータベースにまとめる作業です


build-prc --no-check-resources -o solidLineHack-m68k.prc -n "solidLineHack" -c SolL -t 'HACK' solidLineHack.ro code03e8 code03e9

 [-o solidLineHack-m68k.prc]の部分は、作成するファイル名の指定ですね

 [-n "solidLineHack"]は、Palm上でのデータベース名

 [-c SolL -t 'HACK']はクリエータIDとリソースタイプの指定

 あとの[solidLineHack.ro code03e8 code03e9]のところは、まとめて欲しいデータを並べるだけ

 さあ、ビルドしてみましょう

4.ビルドしてみよう

 Cygwinを起動して、[cd /m68kHack/solidLineHack]とタイプしてディレクトリを移動します

 あとは何も考えず[sh compile.sh]

 ごそごそと何かやっているようだけど... あれ、何も起こらない?

 はて、ファイルの一覧を見てみましょう [ls]とタイプして...

 おぉ、無事に[solidLineHack-m68k.prc]がいましたね うまくいっているようです

5.試してみる

 いきなり実機でも良いのですが、ここはエミュレータを利用してみます

 エミュレータを起動して、[YAHM]と[solidLineHack-m68k.prc]をインストールして...と

 そうそう、[Alt+\]で[Debug Options]を開いて、全てのチェックを外しておいてください (ちょっと五月蝿いので)

 さて、[YAHM]を起動して、[solidLineHack-m68k]にチェックを入れて、すかさず[Memo]を起動

  

 はは、結構いいものです これはぼくごのみ(へへ)

 うまく行ったので、これ以上細かい話はやめてm68kHackのお話はここまで

 次回はいよいよARMHackに進みます 第3回「ARMHackの組みたて」

質問、感想などはPalmHackersSalonのBBSへ

T-Pilot sekino