ActionPush の複数値指定
Flash SWF の ActionScript2 Bytecode に ActionPush(0x96) という、実行マシンスタックに値を積む命令がありまして、
IO_SWF と SWFEditor の replaceActionStrings がこの ActionPush の仕様を満たしていないので修正中です。
情報 thx > @yoshikids
勘違い
ActionPush は例えば文字列を渡す時は、↓こういうフォーマットだと思っていましたが、
Code |Length|Type| String |StringEnd| 0x96 | ??? | 0 | ??? | 0 | <------- Length ------->
仕様書を読むと。
ActionPush pushes one or more values onto the stack. The Type field specifies the type of the value to be pushed.
とありまして、複数の値を一度に Push 出来るようです。
つまり、↓こっちのイメージが正しいです。
|Length|Type| String |StringEnd|Type| something | | ??? | 0 | ??? | 0 | ? | ??? | <---------------- Length ---------------->
面倒なのは、情報要素毎に Type 指定するので、任意の型が混在した配列を表現できる事です。
1つが文字列だからといって他のデータが文字列であるとは限らないので、このバイナリを再構築するには、全 Type について処理する必要があります。
イメージを作ってみる。
a = "1"; b = "2"; c = "3";
コンパイルすると以下のような SWF バイナリが出来ます。
00000000 46 57 53 04 4b 00 00 00 70 00 09 60 00 00 96 00 |FWS.K...p..`....| 00000010 00 0a 01 00 43 02 ff ff ff 3f 03 28 00 00 00 96 |....C....?.(....| 00000020 03 00 00 61 00 96 03 00 00 31 00 1d 96 03 00 00 |...a.....1......| 00000030 62 00 96 03 00 00 32 00 1d 96 03 00 00 63 00 96 |b.....2......c..| 00000040 03 00 00 33 00 1d 00 40 00 00 00 |...3...@...|
swftools の swfdump で逆アセンブルして確認
[00c] 40 DOACTION ( 3 bytes) action: Push String:"a" ( 3 bytes) action: Push String:"1" ( 0 bytes) action: SetVariable ( 3 bytes) action: Push String:"b" ( 3 bytes) action: Push String:"2" ( 0 bytes) action: SetVariable ( 3 bytes) action: Push String:"c" ( 3 bytes) action: Push String:"3" ( 0 bytes) action: SetVariable ( 0 bytes) action: End
この中から Action Push のイメージを抜き出すと、この辺り。
00000010 96 | .| ~~ P (Push) 00000020 03 00 00 61 00 96 03 00 00 31 00 1d 96 03 00 00 |...a.....1......| ~~~~ ~~ ~~~~~ ~~ ~~~~~ ~~ ~~~~~ ~~ len type 'a' AP len type '1' SV (SetVariables)
(意味的に正しいか自信ないけど、今回はバイナリ形式しか考えないとして)
a と 1 を一緒に push するバイナリイメージに書き換えてみます。
(SWF Header の FileLength と Tag HeaderRecords の Length も書き換えます)
00000010 96 | .| ~~ P (Push) 00000020 06 00 00 61 00 00 31 00 1d 96 03 00 00 62 00 96 |...a..1......b..| ~~~~~ ~~ ~~~~~ ~~ ~~~~~ ~~ len type 'a' type '1' SV (SetVariables)
もう一度、swfdump で
[00c] 40 DOACTION ( 6 bytes) action: Push String:"a" String:"1" ( 0 bytes) action: SetVariable ( 3 bytes) action: Push String:"b" ( 3 bytes) action: Push String:"2" ( 0 bytes) action: SetVariable ( 3 bytes) action: Push String:"c" ( 3 bytes) action: Push String:"3" ( 0 bytes) action: SetVariable ( 0 bytes) action: End
テスト用サンプルの作り方が分かったので、これで実装できます。