Home > スポンサー広告 > TempAR - 0xC1 コードタイプ さんぷる?

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

コメント: -

Home > スポンサー広告 > TempAR - 0xC1 コードタイプ さんぷる?

Home > TempAR Usage > TempAR - 0xC1 コードタイプ さんぷる?

TempAR - 0xC1 コードタイプ さんぷる?


まだTH2DTをやってます。

ウィッチというクラスはNukerのはずなのにダメージがいまいちで、
属性魔法で敵の弱点属性を突いても割合でダメージが増えるだけ。
何より詠唱時間が非常に長く、詠唱速度装備を揃える頃には
ゲームが終わってしまいます。

他のクラスと比較しても利点が無く、無属性全体攻撃無詠唱の鳳凰と
FF11よろしく弱体が付属してる忍術が使える「くノ一」だけいれば
いいんじゃね?と思ってしまいます。

「世界樹の迷宮3」の特異点定理スキルを再現してみようかと思う今日この頃。
おおよそ形は出来てますが、弱点をどうするか悩み中。
もともと弱点という属性が無いのでこちらで弱点を設定しなくてはなりません。
弱点が1つなら簡単なのですが、複数弱点だと管理が面倒くさい。
流れとしてはこんな感じ?

01.敵1の属性値ロード。
02.比較して最小値を検出。
03.最小値と同じ値が入っているアドレスをどこかにアレイでストア。
04.アドレスから属性を割り出してどこかにアレイでストア。
05.プレイヤーが使用した魔法と魔法リストを照合し属性を特定する。
06.プレイヤーの魔法属性と敵弱点属性をチェック。
07.弱点属性ならダメージなど操作。
08.敵2へループ。

耐性が均一の敵の場合、全属性が弱点ということに。
もう改造コードというか


本題に移ります。
TempARの0xC1コードタイプを使ってコードを作ってみました。
例のごとくTH2DTなのですが。


0xCコードタイプを2重に使ってループをネストしようとしたが
ネストには対応してなかったので、アセンブラで書いてみた。

動作としては、次のような形です。

1.1F全マス分を繰り返し書き込み
2.2F先頭アドレスまで移動
3.2F全マス分を繰り返し書き込み
4.3F先頭アドレスまで移動
5.以下繰り返し


_S ULJM-05873
_G ToHeart2 DUNGEON TRAVELERS

_C0 @ Map Init Base
data:
_N 0x08801880 0x3C08FFFF # lui $t0,0xFFFF
_N 0x08801884 0x3508FFFF # ori $t0,$t0,0xFFFF
_N 0x08801888 0x00046025 # or $t4,$zero,$a0
_N 0x0880188C 0x00005024 # and $t2,$zero,$zero
counter_reset:
_N 0x08801890 0x00004824 # and $t1,$zero,$zero
loop_tile:
_N 0x08801894 0xAD880000 # sw $t0,0x0000($t4)
_N 0x08801898 0x258C0004 # addiu $t4,$t4,0x0004
_N 0x0880189C 0x0125582B # sltu $t3,$t1,$a1
_N 0x088018A0 0x1560FFFC # bne $t3,$zero,loop_tile
_N 0x088018A4 0x25290001 # addiu $t1,$t1,0x0001
loop_floor:
_N 0x088018A8 0x01876021 # addu $t4,$t4,$a3
_N 0x088018AC 0x0146582B # sltu $t3,$t2,$a2
_N 0x088018B0 0x1560FFF7 # bne $t3,$zero,counter_reset
_N 0x088018B4 0x254A0001 # addiu $t2,$t2,0x0001
exit:
_N 0x088018B8 0x03E00008 # jr $ra


_C0 = Map Tower
_N 0xC1000004 0x08801880 # 4 registers start=0x08801880
_N 0x09CDB2F8 0x0000000F # a0=0x09CDB2F8 a1=0x0000000F
_N 0x0000001D 0x000000FC # a2=0x0000001D a3=0x000000FC
■0xC1のコードの説明

効果:三十重の塔のマップを全踏破/初期化


▼*=0xC1000004

4はレジスタを何個使うか?という意味です。
a0,a1,a2,a3の4つを使うので4です。



▼*=0x08801880

このアドレスからプログラムを実施せよという命令です。



▼a0=0x09CDB2F8

a0に書き込みの開始アドレスをセットします。

1F左上の場所を踏破すると下のようになります。
0x09CDB2F8 0x00000001
右隣に1歩移動
0x09CDB2F8 0x00000003

2進数を見慣れている人ならこれですぐに分かりますが、
orでビットを立てていく、フラグではおなじみのパターンです
1=0b01
2=0b10
3=0b11



▼a1=0x0000000F

4byte書き込みを何回繰り返せば良いか計算します。


1F右下のアドレスは
0x09CDB334

(末尾アドレス-先頭アドレス)/4byte=繰り返し回数
(0x09CDB334-0x09CDB2F8)=0x0F



▼a2=0x0000001D

何フロアあるか数値を入れます。
三十重の塔は30Fありますが、このプログラムの場合初期化でループカウンタ0
0の時に1回書き込み、残り29回ループするのでn-1で29(0x1D)になっています。



▼a3=0x000000FC

1F右下のアドレスから2F左上のアドレスまでの距離を求めます。

2F左上のアドレスは
0x09CDB434

(2F左上のアドレス-1F右下のアドレス)=
(0x09CDB434-0x09CDB334)=0x0100

ただし、プログラムの都合で1つのフロアの最後でループを抜ける際も
アドレス+4しているので実際には0x0100-4=0xFCになります。
■プログラム

見た目は難しそうですがやってることは単純です。
下の例は動かないコードなので使えませんが、
このようなことをやってるだけです。


_C0 not working 0xC Nest
_M 0xD5000000 0xFFFFFFFF # 0xFFFFFFFF 書き込む値をセット
_M 0xC0000000 0x0000001D # ループA : 1+29階層

_M 0xC0000000 0x0000000F # ループB : 0x0F*4byte書き込み
_M 0xD6000000 0x09CDB2F8 # 0x09CDB2F8に0xFFFFFFFFを書き込み+オフセット+4
_M 0xD1000000 0x00000000  # ループBブロック終端

_M 0xDC000000 0x000000FC # 1階層分書き込んだら、次の階層先頭へオフセット加算
_M 0xD2000000 0x00000000 # ループAブロック終端
■プログラム本体

data:
_N 0x08801880 0x3C08FFFF # lui $t0,0xFFFF
★t0=0xFFFF0000


_N 0x08801884 0x3508FFFF # ori $t0,$t0,0xFFFF
★t0=0xFFFF0000 OR 0x0000FFFF

この2行でt0=0xFFFFFFFFを生成します。


_N 0x08801888 0x00046025 # or $t4,$zero,$a0
★アドレスの値を他のレジスタへ転送

t4=0x00000000 OR a0
0xC1コードタイプでは、a0-a3レジスタは常に同じ値を取り、
addiu a0,a0,0x0001
のように加算してもa0は変化しない為、他のレジスタに入れる。
move t4,a0と同じ。


_N 0x0880188C 0x00005024 # and $t2,$zero,$zero
★全フロア分繰り返し用カウンタ初期化
t2=0x00000000 AND 0x00000000=0x00000000


counter_reset:
_N 0x08801890 0x00004824 # and $t1,$zero,$zero
★1フロア分全マス繰り返し用カウンタ初期化
t1=0x00000000 AND 0x00000000=0x00000000


loop_tile:
_N 0x08801894 0xAD880000 # sw $t0,0x0000($t4)
★アドレスt4+0x0000にt0を書き込む。
t4=0x09CDB2F8+オフセット
t0=0xFFFFFFFF


_N 0x08801898 0x258C0004 # addiu $t4,$t4,0x0004
★アドレスt4=0x09CDB2F8+オフセット加算。
t4=t4+4


_N 0x0880189C 0x0125582B # sltu $t3,$t1,$a1
★ループ回数判定
t1=1フロア全マスカウンタ
a1=1フロアで書き込むべき回数

t1 < a1 then t3 =1
t1 >= a1 then t3 =0


_N 0x088018A0 0x1560FFFC # bne $t3,$zero,loop_tile
★条件分岐
t3=0 1フロア分全マス分ループしていないならloop_tileへ戻る。


_N 0x088018A4 0x25290001 # addiu $t1,$t1,0x0001
★ループ回数+1
t1=t1+1
ディレイスロット


loop_floor:
_N 0x088018A8 0x01876021 # addu $t4,$t4,$a3
★次のフロア先頭までオフセット加算
t4=t4+a3


_N 0x088018AC 0x0146582B # sltu $t3,$t2,$a2
★ループ回数判定
t2=フロア数カウンタ
a2=全フロア数-1

t2 < a2 then t3=1
t2 >= a2 then t3=0


_N 0x088018B0 0x1560FFF7 # bne $t3,$zero,counter_reset
★条件分岐
t3=0 全フロア分ループしていなければcounter_resetへ戻る。


_N 0x088018B4 0x254A0001 # addiu $t2,$t2,0x0001
★ループ回数+1
t2=t2+1
ディレイスロット


exit:
_N 0x088018B8 0x03E00008 # jr $ra
★サブルーチンを抜ける。



0xC1コードタイプの特徴

その1 プログラム本体を書き換えること無く、a0-a3を数値変更出来る。
その2 プログラムはあらかじめ書き込んでおく必要がある。
その3 a0-a3に手を加えても元の値に書き換えられてしまうことに注意する。


その1が0xC1の利点で、0xC2だと数値変更したい場合に
プログラムに手を加えないといけませんが、0xC1の場合には
引数だけを書き換えられるので、同じプログラムを流用しつつ
引数だけを変更したい場合に、コードを短く出来ます。


具体例を挙げます。
「ダンジョン」の30階層分の踏破情報を操作する場合
引数部分の次のたった3行のコードで実現できます。
(ベースプログラムは共通コード。)


_C0 = Map Dungeon
_N 0xC1000004 0x08801880
_N 0x09CD8CB4 0x0000001E
_N 0x00000013 0x000000C0




関連記事
スポンサーサイト

コメント: -

Home > TempAR Usage > TempAR - 0xC1 コードタイプ さんぷる?

Return to page top

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。