スクリプトブロック(作成途中)
このページは
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