九龍妖魔學園紀

キーワード
ベース
レジスタ
ルーチン
論理積、排他的論理和
テーブル
符号拡張


内容
感情値変動すると指定値へ変更
プリクラなくてもバディ選択可能
アイテム全種x個
感情値表示


アイテム全種x個

このソフトは持ち歩けるアイテムは数個。自室で全てのアイテムを収納できる様になっています。
ですから、調べるのは自室のアイテムの処理です。
ラベルのSt_GetRoomItemNumが自室のアイテムの個数をロードしているのではないかと推測できます。

00133ce0 andi  v0, a0, $ffff             St_GetRoomItemNum(ラベル)
00133ce4 sll   v1, v0, 2               
00133ce8 lui   v0, $0078        v0=$00780000
00133cec addiu  v0, v0, $9376      v0=$00779376
00133cf0 addu  v0, v0, v1
00133cf4 lhu   v0, $0000(v0)             
00133cf8 jr   ra

注目すべき点はsllのシフト命令とlhuのロード命令です。
ここではシフト命令でアドレスをずらしながら全種類のアイテムの個数を処理しています。
0個の場合は$0000。99個の場合は$0063がロード命令のv0レジスタに格納されています。
という事はv0レジスタに任意の数を入れる事で全種類の個数を変えられるかもしれません。

00133ce0 andi  v0, a0, $ffff             St_GetRoomItemNum(ラベル)
00133ce4 sll   v1, v0, 2
00133ce8 lui   v0, $0078        v0=$00780000
00133cec addiu  v0, v0, $9376      v0=$00779376
00133cf0 addu  v0, v0, v1
00133cf4 addiu  v0, zero, $003c     v0=$0000003c 
00133cf8 jr   ra

今回は$003c、10進数での60を入れてみます。
すると自室アイテムを見ると全種類のアイテムが60個になりました。
しかしこのままではセーブデータに残りません。
原因はロードしているだけでストアしていない為ですので、ストア命令を追加します。

00133ce0 andi  v0, a0, $ffff             St_GetRoomItemNum
00133ce4 sll   v1, v0, 2
00133ce8 lui   v0, $0078        v0=$00780000
00133cec addiu  v0, v0, $9376      v0=$00779376
00133cf0 addu  t7, v0, v1              
00133cf4 addiu  v0, zero, $003c     v0=$0000003c
00133cf8 jr   ra
00133cfc sh   v0, $0000(t7)

幸いな事にjr raの復帰の次の行が1行空いていました。
ストア命令を書きますが問題点が1つあります。
それはベースとなるレジスタとロードした数値を格納するレジスタが共にv0である為、
このままだと$003cがベースとなってしまいます。ですのでどちらかを変更します。
この処理はロードを処理している為ロードした数値をv0ではない物に変える事は
後の処理に影響が出る可能性が高い為、問題外。
するとベースとなるレジスタを変更するのですが、
ロード命令の直前にv0とv1を加算した物をv0に格納するという命令があります。
この格納するレジスタとベースとなるレジスタを同じにする事で問題なく処理が進みます。
例としてt7レジスタを入れてあります。
このコードを使用しセーブしてみるとセーブに反映されています。
これでアイテム全種x個のコードが出来ました。

感情値表示

このコードは各バディの成績表にゲーム中では確認が出来ない感情値を表示させる。というコードです
手間が一番かかる上に需要があるコードではなく、作った理由はただの自己満足(ry
しかし今後にいかせるかもしれないので無駄ではないでしょう。多分…

まずは各バディの能力値がどの様にして表示されているのかを説明します。
ではこちらを見て下さい

しかしこのままでは少し見づらい為ハーフワード表示に切り換えます。

プラスの場合は見た目そのままで、マイナスの数値は符号拡張です。
符号拡張についてはキーワードを参照して下さい。
-10,+10,-5,-1,+10,0,+40…となっており、白岐の能力値のテーブルだと分かります。
以下皆守、八千穂と続いていました。

この様に命令ではなくデータが並んで書かれているものをテーブルと呼びます。
テーブルはLVUPまでの経験値などで使われる場合が多く、現在のLV分シフトし、
その数値が書かれている箇所のデータをロード命令でロード、比較してLVUPするのかを判定する。
という流れになることが多いです。ちなみにこのソフトもLVUPはテーブルを使っています。

ではこの数値をどの処理からロードしているのかを調べます。
_BuddyDataTblには参照箇所がないのでそのすぐ上のアドレス$0048e58cから見ていきます。
St_GetRealParamPreparationという処理の参照箇所があります。

001331a0 andi  v1, a0, $ffff             St_GetRealParamPreparation(ラベル)
001331a4 ori   v0, zero, $8000     v0=$00008000
001331a8 bne   v1, v0, $001331c0
001331ac nop
001331b0 lui   at, $0077        at=$00770000
001331b4 lb   v0, $7f20(at)      v0=$00777f20
001331b8 beq   zero, zero, $00133208
001331bc nop
001331c0 ori   v0, zero, $ffff     v0=$0000ffff
001331c4 bne   v1, v0, $001331d8
001331c8 nop
001331cc daddu  v0, zero, zero
001331d0 beq   zero, zero, $00133208
001331d4 nop
001331d8 andi  v0, v1, $8000
001331dc beq   v0, zero, $00133204
001331e0 nop
001331e4 andi  v0, v1, $7fff
001331e8 sll   v1, v0, 5
001331ec lui   v0, $0049        v0=$00490000
001331f0 addiu  v0, v0, $e58c      v0=$0048e58c
001331f4 addu  v0, v0, v1
001331f8 lb   v0, $0000(v0)             
001331fc beq   zero, zero, $00133208
00133200 nop
00133204 daddu  v0, zero, zero
00133208 jr   ra

Preparation。何だか分かりませんが辞書で調べると生活が一番近いので生活と仮定して進めていきます。

試しに青くマークしてあるロードのデータを$000aに変えてみます。するとバディ全員の生活が+10になりました。
St_GetRealParam以外のものは変えても数値が変化しなかったのでこの表示用処理を使います。
つまりこのv0レジスタに感情値のアドレスを読込んだデータを格納する事でバディの感情値を確認する事が可能に
なります。しかし、ここはバイトデータで処理してある為ハーフワードデータを入れた場合、前後の科目の数値に
影響が出てしまいます。
ですから科目ではなく生命などの能力値を書き換える方法をとりました。
アドレス$0048e58cの更に上$0048e588の参照箇所を調べると英語の数値です。

この様に参照が並んでいて

それぞれこの能力値の処理の参照である様です。

では身体の処理を書き換えるのですが

0012ff10 andi  v1, a0, $ffff             St_GetRealParamPower(ラベル)
0012ff14 ori   v0, zero, $8000     v0=$00008000
0012ff18 bne   v1, v0, $0012ff30
0012ff1c nop
0012ff20 lui   at, $0077        at=$00770000
0012ff24 lh   v0, $7f04(at)      v0=$00777f04
0012ff28 beq   zero, zero, $0012ff78
0012ff2c nop
0012ff30 ori   v0, zero, $ffff     v0=$0000ffff
0012ff34 bne   v1, v0, $0012ff48
0012ff38 nop
0012ff3c daddu  v0, zero, zero
0012ff40 beq   zero, zero, $0012ff78
0012ff44 nop
0012ff48 andi  v0, v1, $8000
0012ff4c beq   v0, zero, $0012ff74
0012ff50 nop
0012ff54 andi  v0, v1, $7fff
0012ff58 sll   v1, v0, 5               
0012ff5c lui   v0, $0049        v0=$00490000
0012ff60 addiu  v0, v0, $e570      v0=身体
0012ff64 addu  v0, v0, v1              
0012ff68 lh   v0, $0000(v0)
0012ff6c beq   zero, zero, $0012ff78
0012ff70 nop
0012ff74 daddu  v0, zero, zero
0012ff78 jr   ra

注目すべき点は灰色のマーク箇所でシフトした分を青いマーク箇所で加算しています。
ということはこのシフトのv0=キャラそれぞれのナンバーということになります。
これを利用し、キャラごとのアドレス差を加算していくことでキャラ詳細画面での感情値を表示させることが出来る。

1カ所の項目で全て処理しなかった理由は例え身体の表示処理で書き換えても他の処理で再びロードされてしまえば
上書きされることが予測できる為です。
ではロードさせるアドレスを書き換えていくのですが身体・知性などそれぞれの処理のみでやっていくと効率が
悪くなる為共通の処理は空きメモリへとばしてしまいます。
どこから飛ばせるのか色々あるかと思いますが、今回は処理が復帰するjr raの箇所から飛ばします。

しかしその前に上であげたキャラのナンバーとなるレジスタに入っている数値を確かめる必要があります。
それによって基となるアドレスの値が変わってきます。
どうやって確かめるのかは先ほどのロードした値となるレジスタを変えた方法と同じですが、
シフトのv0レジスタはその後使われている為、
シフトする前の処理を見ていきますするとこの処理の始めにあるandiのa0レジスタを
ロードのv0レジスタに変えることで数値を見ることが出来ます。

$0012ff68をaddu v0, zero, a0に変える事で身体の項目に表示される値がa0レジスタの値です。

確認しますと
白岐-32767、皆守が-32766、八千穂-32765以下同様調べたのがかなり前ですので少しあやふやです

16進数に直すと$8001,$8002,$8003となっていますのでこれを1,2,3へ変えるには

andi a0,a0,$7fffかori a0,a0,$8000

なのですが出来れば前者の方がいいです。
理由は入っている値が常にマイナスの場合は後者でもいいのですが、
プラスの値になった際には後者の場合はマイナスになってしまう為です。
コードのページに載っているものはoriを使っていますので危ないかもしれません。
動作確認中フリーズした為危険だという注意書きは一応しています。
andi a0,a0,$7fffに修正しました。04.12.26

andiで変換した数値は
白岐1,皆守2,八千穂3

これを感情値のキャラごとの差$000Cに乗算、加算することでアドレスを変えていくことが可能になります。

今までの点を踏まえ、出来たコードはこちら
コードのページに掲載しているものと少し変えています。
行数を短くすることを考えずに書き直した為乗算命令ではなくシフト命令を使っています。

各バディの成績表(プリクラの詳細)に感情値表示
0CE4F466 1456320C
1C9AF398 1456E7C6
0CE4F466 1456C20C
1C9AF398 15F6E79D
1C9AF39C 2052E794
1C9AF3A0 13CB47C6
1C9AF3A4 24DA300C
1C9AF3A8 145A3F65
1C9AF3AC 13BA3FC6
1C9AF3B0 14513F25
1C9AF3B4 13B23FC6
1C9AF3B8 15F6E79D
1C9AF3BC 97B4E7A5
身体に友情
1C8580A0 0C5393A9
1C8580A4 384B4527
知性に愛情
1C8682E0 0C5393A9
1C8682E4 384B4521
R2+□でON
R2+△でOFF

この様に書き換えています。

000f7070 addu  zero, zero, zero            
000f7074 lui   t4, $0077        t4=$00770000
000f7078 addu  t4, t4, t3
000f707c andi  a0, a0, $7fff
000f7080 sll   t5, a1, 1
000f7084 addu  t5, t5, a0
000f7088 sll   t5, t5, 2
000f708c addu  t5, t5, t4
000f7090 jr   ra
000f7094 lh   v0, $0000(t5)

最初の行はjr raにパッドコードで切り換えが可能。

0012ff54 andi  v0, v1, $7fff
0012ff58 sll   v1, v0, 5
0012ff5c lui   v0, $0049        v0=$00490000
0012ff60 addiu  v0, v0, $e570      v0=身体
0012ff64 addu  v0, v0, v1
0012ff68 lh   v0, $0000(v0)
0012ff6c beq   zero, zero, $0012ff78
0012ff70 nop
0012ff74 daddu  v0, zero, zero
0012ff78 j    $000f7070               

1ページ目へ 雑記へ戻る