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

テスト用サンプルの作り方が分かったので、これで実装できます。