イベント命令の 40 0D から始まる命令で、呼び出される、自前asm関数について解説する。 ====== 自前関数呼び出し ====== イベント命令から自前のasm関数呼ぶには、以下のようにする。 40 0D 00 00 アドレス+1 例: 40 0D 00 00 81 F6 E4 08 これで、 0x08E4F680 に設置した関数を呼び出すことができる。 これで↓が呼べる @org $08E4F680 @thumb push {lr} ここに好きな処理 mov r0, #0 pop {pc} ====== r4以降のレジスタの保存 ====== r4以降のレジスタを壊す場合は pushするのが望ましい(多分?) @org $08E4F680 @thumb push {r4,r5,r6,r7, lr} ここに好きな処理 mov r0, #0 pop {pc,r7, r6 , r5 ,r4 } ====== 関数引数 ====== UCHAR2つ(USHORT値)の引数を取ることができる。\\ \\ r0 or r3 or r4 = 0x02025018 + 0x38 offset = 2025050 (アドレスは進捗状況によるかも) ここに、実行しているイベント命令へのポインタがある。\\ ldr r0, [r0, #0x38] %%//%%イベント命令にアクセスらしい [r3,#0x38] でイベント命令が書いてあるアドレスの場所へ\\ ldrb r1, [r0, #0x2] %%//%%引数1 40 0D [引数1] [引数2] [プログラム場所 XX XX XX 08]\\ ldrb r2, [r0, #0x3] %%//%%引数2 40 0D [引数1] [引数2] [プログラム場所 XX XX XX 08]\\ \\ 例: 40 0D 11 22 81 F6 E4 08 @org $08E4F680 @thumb push {lr} ldr r0, [r0, #0x38] //イベント命令にアクセスらしい [r3,#0x38] でイベント命令が書いてあるアドレスの場所へ ldrb r1, [r0, #0x2] //引数1 40 0D [引数1] [引数2] [プログラム場所 XX XX XX 08] ldrb r2, [r0, #0x3] //引数2 40 0D [引数1] [引数2] [プログラム場所 XX XX XX 08] ;以下のようになる ;r1 = 11 ;r2 = 22 ここに好きな処理 mov r0, #0 pop {pc} ldrh を使えば、 unsigned short で取れる。 ldr r0, [r0, #0x38] //イベント命令にアクセスらしい [r3,#0x38] でイベント命令が書いてあるアドレスの場所へ ldrh r2, [r0, #0x2] ;引数1 40 0D [11] [22] [プログラム場所 XX XX XX 08] ;→リトルエンディアンなので、 0x2211 が取れる。 イベントフラグにアクセスしたり、アセンブラなので全メモリ空間にアクセスできるため、情報は好きなだけ取れる。 ==== 注意事項 ==== 一部関数(魔王出現エフェクト 08081bb6)などで、 r0 == 0 のチェックをしている箇所がある。\\ 今のところ確認できていないが、関数呼び出しがされた結果、 r0 == 0 になることがあるのかもしれない。 もし、見かけたら教えてほしい。 ====== 関数戻り値 条件式 ====== イベント命令の条件式として利用するには、以下のようにする。 ldr r2, =$030004B0 ; + #0x30 str r0, [r2, #0x30] ;条件式で取れる領域に書き込む 例: 所持金で分岐する場合とか。 ;所持金チェック 所持金が指定ゴールド以上かどうか ;gold_find.asm ; ;40 0D [11] [22] E1 F6 E4 08 ; ;-> 0x2211ゴールド(8721ゴールド) @org $08E4F6E0 @thumb push {lr} ldr r0, [r0, #0x38] ;イベント命令にアクセスらしい [r3,#0x38] でイベント命令が書いてあるアドレスの場所へ ldrh r2, [r0, #0x2] ;引数1 40 0D [引数1] [引数2] [プログラム場所 XX XX XX 08] ;所持金 ldr r3, =$0202BCF4 ;所持金を取得 ldr r1, [r3,#0x0] mov r0, #0x0 cmp r1,r2 ;お金の比較 BLT exit_result ;お金がなければ、 exit_result へ mov r0, #1 ;金があるなら・・・ exit_result ldr r2, =$030004B0 ; + #0x30 str r0, [r2, #0x30] ;条件式で取れる領域に書き込む mov r0, #0 pop {pc} イベント命令をこんな感じで作る。 400D50C3''不明 //5万ゴールドの確認 gold_find.asm 0x50C3=>50000 E1F6E408''不明 4005050001000000''[05]条件作成終わり??? 410C05000C000500''条件成立時にイベントID[0005]で以下を実行[05]2??? 2016B900''[B9]効果音 //5万ゴールドぽんとくれたぜ 201A0000''会話開始 //あざーす 201B5D05201D0000''[055D]背景無会話表示 20090400''不成立時に条件イベントID[0004]で以下を実行 20080500''条件イベントID[0005]終了 201A0000''会話開始 //カネがないのかよ 201B5E05201D0000''[055E]背景無会話表示 20080400''条件イベントID[0004]終了 なお、イベント命令の分岐の書き方は、他にもある。 ====== 関数戻り値 会話テキスト ====== 会話テキストで、@0080@0005 で10進数で取ることができる。\\ ただし、@0080@0005 が使えるのは、吹き出しの会話のみ。システムメッセージでは取れない。\\ 例 ;r0に格納されている数字を @0080@0005で取れるように書き込む ;注意:@0080@0005は会話でしか取れない。システムメッセージでは読めないらしい mov r0,r7 ldr r1,=$08008914 mov lr, r1 @dcw $F800 ↓こういうふうに使います。 @0080@0005ゴールドもっているかい?@0003 ====== 関数処理 ====== asmなので、全メモリにアクセスできる。(ただし、一部領域は例外)\\ ldrでデータを読み出して、 strでデータを書き込もう。\\ 関数を呼び出したりなんでもできます。\\