トップ   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS

解説/イベント命令での自前関数呼び出し のバックアップ差分(No.1)


  • 追加された行はこの色です。
  • 削除された行はこの色です。
#author("2017-06-08T20:51:29+09:00","","")
イベント命令の 40 0D から始まる命令で、呼び出される、自前asm関数について解説する。


*自前関数呼び出し [#h0b1533a]
イベント命令から自前の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以降のレジスタの保存 [#tfbcd566]

r4以降のレジスタを壊す場合は pushするのが望ましい(多分?)

 @org	$08E4F680
 @thumb
 	push	{r4,r5,r6,r7, lr}
 
 	ここに好きな処理
 
 	mov	r0, #0
 	pop	{pc,r7, r6 , r5 ,r4 }


*関数引数 [#kbf75fed]

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 が取れる。


もちろん、イベントフラグにアクセスしたり、アセンブラなので全メモリ空間にアクセスできるため、情報は好きなだけ取れる。


*関数戻り値 条件式 [#we8e68f3]

イベント命令の条件式として利用するには、以下のようにする。
 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
 	mov	r0, #1		;金がある
 
 exit_result
 	ldr	r2, =$030004B0  ; + #0x30
 	str	r0, [r2, #0x30]	;条件式で取れる領域に書き込む

 	mov	r0, #0
 	pop	{pc}

イベント命令をこんな感じで作る。

 400D50C3''不明  //5万ゴールドの確認 gold_find.asm
 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]終了

なお、イベント命令の分岐の書き方は、他にもある。


*関数戻り値 会話テキスト [#aae8a73c]
会話テキストで、@0080@0005 で10進数で取ることができる。
ただし、@0080@0005 が使えるのは、吹き出しの会話のみ。システムメッセージでは取れない。


 ;r0に格納されている数字を @0080@0005で取れるように書き込む
 ;注意:@0080@0005は会話でしか取れない。システムメッセージでは読めないらしい
 mov		r0,r7
 ldr		r1,=$08008914
 mov		lr, r1
 @dcw	$F800


*関数処理 [#f8643541]
asmなので、全メモリにアクセスできる。(ただし、一部領域は例外)
ldrでデータを読み出して、 strでデータを書き込もう。
関数を呼び出したりなんでもできます。