所持金増減度操作

所持金の最大値チェックを探し当てて
周辺を見た所いい場所が見つかりました

00201F24と00201F28で所持金アドレスを求め
00201F2Cで現在値に何か(s1レジスタ)加算して
00201F30で最大値チェック
最大値より現在値が多ければ分岐はせずに
00201F3Cで修正されます。

この「00201F2Cで現在値に何か加算して」
ここのs1レジスタは増える金額のようです
この加算命令をnopにすれば所持金が増えなくなります
増えないだけでなく、減らなくもなっています。

なぜ増えない&減らないかというと
マイナス値を加算すれば減算にもなる為です
加算減算両方をここで扱っています
この所持金増減の命令を通過する前に
s1レジスタの数値を変えれば結果が変わります

s1を簡単に変える方法として挙げられるのが
空きメモリでs1の値を操作して元のプログラムへ戻す
という方法があります

遅延スロットと元のプログラムの書き直しを考慮して
作成した必須コードが以下のコードです
00201F24 0803C000 j $000F0000
00201F28 00442021 addu a0,v0,a0
000F0000 8C830000 lw v1,$0000(a0)
000F0030 080807CB j $00201F2C
これで000F0004〜000F002Cまでのアドレスに
s1の値を変えるプログラムが入れられます


実際に作った2つのプログラムの説明をします
マイナス無し
000F0004 5A200001 blezl s1,$000F000C
000F0008 70008E88 pextlb s1,zero,zero
000F0004でs1の数値が正の値だった場合
遅延スロットのpextlb命令を無効化し
分岐せずにプログラムが進みます
逆に数値が負の値だった場合は
pextlb命令を実行して000F000Cへ分岐します

pextlbは、2,3番目のレジスタの値を
複雑に組み合わせて1番目のレジスタに格納する
という動作をしています。
(細かい処理は説明が長くなるのでカットします)
つまり、s1レジスタの値を全て0にするという物です
daddu s1,zero,zero
prot3w s1,zeroでも代用出来ます
加算値が負の値ならばs1に0を格納するので
所持金が減らなくなります


プラスxx倍
000F000C 1A200002 blez s1,$000F0018
000F0010 241000xx addiu s0,zero,$00xx
000F0014 02308819 multu s1,s1,s0
マイナス無しで使ったような
「s1が負の値ならば分岐する」
を利用しプラスの場合のみ
このxx倍が有効になるようにしています
遅延スロットは無効化する必要もないので
ここではblezの方を使用しています。
もしs1が正の値の場合
000F0010でs0にxx倍したい値を格納し
000F0014でs1×s0を実行しs1に格納します

PSのR3000で同じ処理をしたい場合は
multu命令が2オペランドまでしか使えず
乗算後にhiやloレジスタから
計算結果を取得する必要がありますが
PS2のR5900ではloに格納されるのと同じ数値を
いきなりs1に格納する事が出来ます
もちろんhiも取得するにはmfhiが必要ですが・・・


ちょっと改造に慣れてない人には難しいと思いますが
同じように「加減両方を処理」しているソフトがあれば
これを応用すれば同じような事が出来るので
今後発売されるソフトでチャレンジして見て下さい。