スクリプトブロック(作成途中)

このページはlevファイルの子ページになります。
スクリプトブロックは、ステージのイベントを制御しています。

スクリプトブロックは、開始部の直後の命令文から始まります。
その後は、命令文の直後にあるオフセットアドレスの通りに、命令文を次々に実行し、
最後にブロック末尾まで到達すると、開始部にループして戻ってくる、という流れをとります。
(Basicで言えば、一つのfor文の中でif文、goto文が繰り返されているだけです)
そのため、途中のオフセットの値を間違えるなどすると、スクリプト内に無限ループが発生し、処理落ちする等の危険性も存在しています。
オフセットアドレスについては、ループ回数チェック命令の所で詳細に解説しています。

また、各項目の「もっと詳しく」と書かれた部分につきましては、ツール類を使わず手作業で解釈した結果&言語を使ったことが無いので、色々間違ってるかもしれません。
(当サイト管理人は職業プログラマーではありません)



スクリプトブロックに存在する命令文のパターンはおおよそ2パターンです。

1.分岐の存在しないもの
データ列+89E9FF+命令文(53XX)+次の命令へのオフセットアドレス
2.分岐の存在するもの
データ列+89E9FF+命令文(53XX)+分岐条件(3D+4byte+7X05)+条件不成立時のオフセット+条件成立時のオフセット

このパターンさえ見つけることが出来れば、levファイルのスクリプト部分も理解しやすいかと思います。

条件分岐については、3D+4byte+7X05のパターンです。
0x3Dが条件分岐の宣言、続く4byteが条件分岐の比較に用いる値、最後の7X05が条件判定のフラグです。
7Xの部分については、0x74:等値、0x7D:以上、0x7E:未満 という分類になります。



スクリプトブロックには以下の命令が存在しています。
このうち、開始部・末尾以外の命令文には記述される順番は存在しません。



スクリプトブロック開始部

スクリプトブロックの開始部は、全てのlevファイルで共通です。
ブロック開始の宣言、ループ処理の宣言を行っていると思われます。
+ もっと詳しく
アドレス オペコード オペコードの
パラメータ
パラメータの
解釈
命令 命令の
パラメータ
全体をもう少しだけ解説
0x00003B24 55 PUSH ebp esp-1。ebpレジスタの値を一時的にスタック(メモリ)に保存する
0x00003B25 53 PUSH ebx esp-1。ebxレジスタの値を一時的にスタック(メモリ)に保存する
0x00003B26 56 PUSH esi esp-1。esiレジスタの値を一時的にスタック(メモリ)に保存する
0x00003B27 8B /r 6C 24 10 mod01,ebp,ptr[1*(none)+esp+disp8] 0x10 MOV r32,r/m32 r/m32(esp+10hのアドレスが示すメモリ)の値をr32(ebp)に転送する
0x00003B2B 8B /r 5D 00 mod01,ebx,ptr[ebp+disp8] 0x00 MOV r32,r/m32 r/m32(ebp+0hのアドレスが示すメモリ)の値をr32(ebx)に転送する
0x00003B2E 8B /r 71 04 mod01,esi,ptr[ecx+disp8] 0x04 MOV r32,r/m32 r/m32(ecx+4hのアドレスが示すメモリ)の値をr32(esi)に転送する

※ここで設定されたレジスタebxのポインタの指し示す場所は、恐らく各種の計算ルーチンを示す配列の先頭部分。
 このスクリプト部分では、必要なデータをスタックに積むことしか行っておらず、計算の実体はサブルーチンとしてCALLされています。
※ここで設定されたレジスタesiのポインタの指し示す場所は、恐らく各種ユニット(矩形も含む)の座標の配列の先頭部分。


ループ回数チェック命令(0x2453)

この命令文は、この命令文を通った回数を保持しています。
この回数に対して条件分岐を行うことで、特定のループ回数でイベントを起こしたりすることが可能です。
具体的には、画像のように初回時のみ分岐することで、ユニットの初期配置につなげたり、
あるいは1ループ1フレームであることを利用して、あるイベントの30秒後に別のイベントを起こすこと等に利用されています。
+ もっと詳しく
アドレス オペコード オペコードの
パラメータ
パラメータの
解釈
命令 命令の
パラメータ
全体をもう少しだけ解説
0x00003B31 89 /r E9 mod11,ebp,ecx MOV r/m32,r32 r32(ecx)の値をr/m32(ebp)に転送する
0x00003B33 FF /2 53 24 mod01,2,ptr[ebx+disp8] 0x24 CALL r/m32 r/m32(ebx+24hのアドレスが示すメモリ)上に存在するサブルーチンが呼び出される
0x00003B36 3D id 00 00 00 00 0x00000000 CMP eax,imm32 imm32(0)をeaxの値と比較する。等しければレジスタのフラグZF=1
0x00003B3B 74 cb 05 0x05 JE rel8 等しい(ZF=1)場合、rel8(cb)の値分(+5h)ジャンプする。3B3Dh+5h=3B42h
0x00003B3D E9 cd 05 00 00 00 0x00000005 JMP rel32 rel32(cd)の値分(+5h)ジャンプする。3B42h+5h=3B47h
0x00003B42 E9 cd 1B 00 00 00 0x0000001B JMP rel32 rel32(cd)の値分(+1Bh)ジャンプする。3B47h+1Bh=3B62h

オフセットアドレスについて。例えば上の画像の0x3B3Eから始まるオフセットアドレスですが、
記述が終わった、address 0x3B42に0x00000005を足して、address 0x3B47に移動することになります。
なお、オフセットアドレスはsigned int32ですので、0x80000000から先はマイナスの値になります。
例えばオフセットアドレス0xFFFFFFE0なら、現在のアドレス-0x20のアドレスに移動します。



編成値チェック命令(0x2853)

支援艦隊を除いた艦隊の編成値のチェックに利用されます。
主に高編成値時の増援艦隊などの分岐に利用されています。
+ もっと詳しく
アドレス オペコード オペコードの
パラメータ
パラメータの
解釈
命令 命令の
パラメータ
全体をもう少しだけ解説
0x00004391 89 /r E9 mod11,ebp,ecx MOV r/m32,r32 r32(ecx)の値をr/m32(ebp)に転送する
0x00004393 FF /2 53 28 mod01,2,ptr[ebx+disp8] 0x28 CALL r/m32 r/m32(ebx+28hのアドレスが示すメモリ)上に存在するサブルーチンが呼び出される
0x00004396 3D id 28 00 00 00 0x00000028 CMP eax,imm32 imm32(40)をeaxの値と比較する。等しければレジスタのフラグZF=1
0x0000439B 74 cb 05 0x05 JE rel8 等しい(ZF=1)場合、rel8(cb)の値分(+5h)ジャンプする。439Dh+5h=43A2h
0x0000439D E9 cd 21 F2 FF FF 0xFFFFF221 JMP rel32 rel32(cd)の値分(FFFFF221h = -DDFh)ジャンプする。43A2h-DDFh=35C3h
0x000043A2 E9 cd 00 00 00 00 0x00000000 JMP rel32 rel32(cd)の値分(+0h)ジャンプする。43A7h+0h=43A7h


耐久力チェック命令(0x2C53)

指定艦艇の耐久力(%)により条件分岐を行えます。
画像ではCPU艦艇の指定を行っていますが、おそらく自艦艇の耐久力もチェック可能です。
具体的には 8B86XXXXXXXX50 → 8B0650 で自艦を対象に出来ますが、
シナリオ内ではこのようなパターンが存在しないので、ちゃんと働くかどうかは不明です。
+ もっと詳しく
アドレス オペコード オペコードの
パラメータ
パラメータの
解釈
命令 命令の
パラメータ
全体をもう少しだけ解説
0x00004249 8B /r 86 54 02 00 00 mod10,eax,ptr[esi+disp32] 0x0254 MOV r32,r/m32 r/m32(esi+254hのアドレスが示すメモリ)の値をr32(eax)に転送する
0x0000424F 50 PUSH eax esp-1。eaxレジスタの値を一時的にスタック(メモリ)に保存する
0x00004250 89 /r E9 mod11,ebp,ecx MOV r/m32,r32 r32(ecx)の値をr/m32(ebp)に転送する
0x00004252 FF /2 53 2C mod01,2,ptr[ebx+disp8] 0x2C CALL r/m32 r/m32(ebx+2Chのアドレスが示すメモリ)上に存在するサブルーチンが呼び出される
0x00004255 3D id 32 00 00 00 0x00000032 CMP eax,imm32 imm32(50)をeaxの値と比較する。等しければZF=1,eax<imm32ならSF=1,eax-imm32がオーバーフローしたらOF=1
0x0000425A 7E cb 05 0x05 JLE rel8 より小さいか等しい(ZF=1またはSF=OFではない)場合、rel8(cb)の値分(+5h)ジャンプする。425Ch+5h=4261h
0x0000425C E9 cd BB FF FF FF 0xFFFFFFBB JMP rel32 rel32(cd)の値分(FFFFFFBBh = -45h)ジャンプする。4261h-45h=421Ch
0x00004261 E9 cd 00 00 00 00 0x00000000 JMP rel32 rel32(cd)の値分(+0h)ジャンプする。4266h+0h=4266h


距離チェック命令(0x3053)

主に自艦が敵艦、特定領域に接近しているかどうかの判定に利用されています。
画像では示していませんが、NPC艦が特定領域に接近したかどうかの判定にも利用されています。
+ もっと詳しく
1つ目の画像について
アドレス オペコード オペコードの
パラメータ
パラメータの
解釈
命令 命令の
パラメータ
全体をもう少しだけ解説
0x00003F85 8B /r 06 mod00,eax,ptr[esi] MOV r32,r/m32 r/m32(esiのアドレスが示すメモリ)の値をr32(eax)に転送する
0x00003F87 50 PUSH eax esp-1。eaxレジスタの値を一時的にスタック(メモリ)に保存する
0x00003F88 8B /r 86 10 02 00 00 mod10,eax,ptr[esi+disp32] 0x0210 MOV r32,r/m32 r/m32(esi+210hのアドレスが示すメモリ)上の値をr32(eax)に転送する
0x00003F8E 50 PUSH eax esp-1。eaxレジスタの値を一時的にスタック(メモリ)に保存する
0x00003F8F 89 /r E9 mod11,ebp,ecx MOV r/m32,r32 r32(ecx)の値をr/m32(ebp)に転送する
0x00003F91 FF /2 53 30 mod01,2,ptr[ebx+disp8] 0x30 CALL r/m32 r/m32(ebx+30hのアドレスが示すメモリ)上に存在するサブルーチンが呼び出される
0x00003F94 3D id 20 03 00 00 0x00000320 CMP eax,imm32 imm32(800)をeaxの値と比較する。等しければZF=1,eax<imm32ならSF=1,eax-imm32がオーバーフローしたらOF=1
0x00003F99 7E cb 05 0x05 JLE rel8 より小さいか等しい(ZF=1またはSF=OFではない)場合、rel8(cb)の値分(+5h)ジャンプする。3F9Bh+5h=3FA0h
0x00003F9B E9 cd 55 01 00 00 0x00000155 JMP rel32 rel32(cd)の値分(+155h)ジャンプする。3FA0h+155h=40F5h
0x00003FA0 E9 cd 00 00 00 00 0x00000000 JMP rel32 rel32(cd)の値分(+0h)ジャンプする。3FA5h+0h=3FA5h
2つめの画像について
アドレス オペコード オペコードの
パラメータ
パラメータの
解釈
命令 命令の
パラメータ
全体をもう少しだけ解説
0x000044C6 8B /r 06 mod00,eax,ptr[esi] MOV r32,r/m32 r/m32(esiのアドレスが示すメモリ)の値をr32(eax)に転送する
0x000044C8 50 PUSH eax esp-1。eaxレジスタの値を一時的にスタック(メモリ)に保存する
0x000044C9 8B /r 46 14 mod01,eax,ptr[esi+disp8] 0x14 MOV r32,r/m32 r/m32(esi+14hのアドレスが示すメモリ)の値をr32(eax)に転送する
0x000044CC 50 PUSH eax esp-1。eaxレジスタの値を一時的にスタック(メモリ)に保存する
0x000044CD 89 /r E9 mod11,ebp,ecx MOV r/m32,r32 r32(ecx)の値をr/m32(ebp)に転送する
0x000044CF FF /2 53 30 mod01,ptr[ebx+disp8] 0x30 CALL r/m32 r/m32(ebx+30hのアドレスが示すメモリ)上に存在するサブルーチンが呼び出される
0x000044D2 3D id 1E 00 00 00 0x0000001E CMP eax,imm32 imm32(30)をeaxの値と比較する。等しければZF=1,eax<imm32ならSF=1,eax-imm32がオーバーフローしたらOF=1
0x000044D7 7D cb 05 0x05 JGE rel8 より大きいか等しい(ZF=1、またはSF=OF)場合、cbの値分(+5h)ジャンプする。44D9h+5h=44DEh
0x000044D9 E9 cd 2D 00 00 00 0x0000002D JMP rel32 rel32(cd)の値分(+2Dh)ジャンプする。44DEh+2Dh=450Bh
0x000044DE E9 cd DB 05 00 00 0x000005DB JMP rel32 rel32(cd)の値分(+5DBh)ジャンプする。44F3h+5DBh=4ACEh


ターゲット設定命令(0x3453)

指定されたターゲットが何隻残っているかどうかを判定します。
この命令だけではマーカーなどが表示されないので、一般に0x7053のターゲット表示設定と一緒に運用されます。
但し、隠し要素として目標表示せずにイベントを起こす場合は、この命令だけで運用されています。



変数の条件判定(0x3853)

変数の値の条件判定を行います。
なお、ステージ間で保持される変数と、そうでない変数があるようですが、未調査です。



ユニット出現命令(0x3C53)

設定ブロックで設定したユニットを出現させます。
艦艇だけでなく、建物の出現命令もこの命令で行います。(建物、艦艇をまとめて扱える)



現在未解明の命令(0x4053)

現在のところ、全く分かっていません。



光源変化命令(0x4453)

設定ブロックで設定した光源を呼び出す命令です。
初期配置の光源は0フレームで呼び出されています。



メッセージ表示命令(0x4853)

画面上部のメッセージの他、ダイアログボックスのメッセージも表示する命令です。
文字列の先頭に#が存在するとダイアログボックスになります。



SE演奏命令(0x4C53)




Music演奏命令(0x5053)




現在未解明の命令(0x5453)

不明ですが、超兵器の出現するステージでのみ見られる命令文です。


編成値獲得命令(0x5C53)




作戦成功命令(0x6053)

この命令が読み込まれると作戦成功になります。


変数への代入命令(0x6453)

変数への代入処理を行う命令です。
主にフラグ立てに利用されています。



変数への加算命令(0x6853)




目標表示命令(0x7053、0x7453)

目標の表示、目標進捗状況の表示、ターゲットマーカーの設定を行う命令群です。
このうち0x7053の目標表示命令については、単独で記述されることもあります。
(進捗状況が必要無い目標の場合:操舵訓練等)



現在未解明の命令(0x8C53)

未解明ですが、ステージ開始直後の1回だけ呼び出されるので、
何らかのステージ初期化に関わっていると考えられます。



現在未解明の命令(0x9053)

未解明ですが、ステージ開始直後の1回だけ呼び出されるので、
何らかのステージ初期化に関わっていると考えられます。



スクリプトブロック末尾

スクリプトブロック末尾は全てのlevファイルで共通です。
おそらく、ループ処理に関わっていると思われます。




タグ:

+ タグ編集
  • タグ:
最終更新:2015年12月17日 18:37