swflib 3 Hello World
さて、何にもでない物作ってても面白くないので今日は一つ、
Hello Worldと画面に出力するActionScript入りのswfファイルを出力してみようと思います。
ActionScriptで書くと、
createTextField("tf", 1, 0, 0, 640, 480); tf.text = "hello world";
をやりたいということです。
まずは、parafla!でさらっと作ってlistswfしてみます。
Offset: 26 (0x00001a) Block type: 12 (DoAction) Block length: 95 0 Declare Dictionary: tf, createTextField, text, Hello World 41 Push 480 Push 640 Push 0 Push 0 Push 0 Push "tf" Push 6 Push "createTextField" 78 Call Function 79 Pop 80 Push "tf" 85 Get Variable 86 Push "text" Push "Hello World" 93 Set Member 94
Push,Pop以外に4つの命令が実行されています。
Declare Dictionary
Call Function
Get Variable
Set Member
です。
0 Declare Dictionary: tf, createTextField, text, Hello World
これは、使う文字列をプールに保存ってことですね。
次が、 createTextField("tf", 0, 0, 0, 640, 480);
に対応するところです。
ActionCallFunctionの定義をswfの仕様書で見てみると以下のようになっています。
1.ファンクション名をPop
2.引数の数をPop
3.引数をPop
4.関数を実行
5.関数の戻り値をPush
これを見ると、
41 Push 480 <- 引数6
Push 640 <- 引数5
Push 0 <- 引数4
Push 0 <- 引数3
Push 0 <- 引数2
Push "tf" <- 引数1
Push 6 <- 引数の数
Push "createTextField" <-関数名
78 Call Function <- 関数呼び出し
79 Pop <- 戻り値を捨てる
ってことがわかります。
tf.text = "Hello World";はGetVariableとSetMemberを使ってます。
ActionGetVariable
1.名前をPop
2.値をスタックにPush
ActionSetMember
1新しい値をPop
2オブジェクトの名前をPop
3オブジェクトをPop
80 Push "tf" <- 名前をPush
85 Get Variable <- tfをPopして、値(オブジェクト)をPush
86 Push "text" <- 名前をPush
Push "Hello World" <- 新しい値をPush
93 Set Member <- 新しい値"Hello World"をPop, オブジェクトの名前"text"をPop,オブジェクト"tf"をPopして、tf.textに"Hello World"を入れる。
ってことになってます。
mlに落とすと以下のようになります。
open Swf open SwfParser open SwfZip (* タグ生成 *) let tag ?(ext=false) d = { tid = 0; textended = ext; tdata = d; } (* 領域データ生成 *) let bounds x y w h = { rect_nbits = if (max w h) >= 820 then 16 else 15; left = x; top = y; right = w * 20; bottom = h * 20; } let w = 640 let h = 480 let fps = 40.0 let out = "out.swf" let bgcolor = ref 0xffffff let header = { h_version = 8; h_size = bounds 0 0 w h; h_frame_count = 1; h_fps = to_float16 fps; h_compressed = false; } ;; let ass : Swf.action DynArray.t = DynArray.create();; DynArray.add ass (AStringPool ["tf"; "createTextField"; "text"; "Hello World"]);; DynArray.add ass (APush [ (PInt (Int32.of_int 480)); (PInt (Int32.of_int 640)); (PInt (Int32.of_int 0)); (PInt (Int32.of_int 0)); (PInt (Int32.of_int 0)); (PStack 0); (* tf *) (PInt (Int32.of_int 6)); (PStack 1); (* createTextField *) ]);; DynArray.add ass (ACall);; DynArray.add ass (APop);; DynArray.add ass (APush [ (PStack 0); (* tf *) ]);; DynArray.add ass (AEval);; DynArray.add ass (APush [ (PStack 2); (* text *) (PStack 3); (* text *) ]);; DynArray.add ass (AObjSet);; let data = [ tag (TSetBgColor { cr = 0xFF; cg = 0xFF; cb = 0xFF }); tag (TDoAction ass); tag (TShowFrame)];; SwfParser.init SwfZip.inflate SwfZip.deflate;; Swf.warnings := true;; let ch = IO.output_channel (open_out_bin out);; Swf.write ch (header, data);; IO.close_out ch;;
実行して出来たout.swfを実際に見てみると、、、ちゃんとHello Worldと出ました。
ocamlでアクションスクリプトでテキストを出力するswfを生成する。
わけわからん話しですけど、こんな感じでできます。