PalmOS 5.x Hack開発講座 第2回 「m68kHackの組みたて」
前回は、「テキスト入力フィールドの下線を点線ではなくて実線にしてしまう」Hackを組んでみようというところまでお話しました
どのAPIをトラップすればよいか、二つ見つけることができましたか?
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]ディレクトリに移動できます
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]の置き換え関数が呼ばれて、フィールドの下線は実線にされてしまう訳
あとはコンパイルを残すのみ もう一息です
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]のところは、まとめて欲しいデータを並べるだけ
さあ、ビルドしてみましょう
Cygwinを起動して、[cd /m68kHack/solidLineHack]とタイプしてディレクトリを移動します
あとは何も考えず[sh compile.sh]
ごそごそと何かやっているようだけど... あれ、何も起こらない?
はて、ファイルの一覧を見てみましょう [ls]とタイプして...
おぉ、無事に[solidLineHack-m68k.prc]がいましたね うまくいっているようです
いきなり実機でも良いのですが、ここはエミュレータを利用してみます
エミュレータを起動して、[YAHM]と[solidLineHack-m68k.prc]をインストールして...と
そうそう、[Alt+\]で[Debug Options]を開いて、全てのチェックを外しておいてください (ちょっと五月蝿いので)
さて、[YAHM]を起動して、[solidLineHack-m68k]にチェックを入れて、すかさず[Memo]を起動
はは、結構いいものです これはぼくごのみ(へへ)
うまく行ったので、これ以上細かい話はやめてm68kHackのお話はここまで
次回はいよいよARMHackに進みます 第3回「ARMHackの組みたて」へ
質問、感想などはPalmHackersSalonのBBSへ