Nicolas Cannasse vor 19 Jahren
Ursprung
Commit
25f6cb6f2b
3 geänderte Dateien mit 313 neuen und 24 gelöschten Zeilen
  1. 31 24
      genswf8.ml
  2. 272 0
      genswf9.ml
  3. 10 0
      haxe.vcproj

+ 31 - 24
genswf8.ml

@@ -1318,8 +1318,7 @@ let convert_header ver (w,h,fps,bg) =
 let default_header ver =
 	convert_header ver (400,300,30.,0xFFFFFF)
 
-let generate file ver header infile types hres =
-	let file , codeclip = (try let f , c = ExtString.String.split file "@" in f, Some c with _ -> file , None) in
+let generate_code file ver types hres =
 	let ctx = {
 		opcodes = DynArray.create();
 		code_pos = 0;
@@ -1387,24 +1386,42 @@ let generate file ver header infile types hres =
 	let idents = AStringPool (List.map (fun ((id,_),_) -> to_utf8 id) idents) in
 	if ActionScript.action_length idents >= 1 lsl 16 then failwith "The SWF can't handle more than a total size of 64K of identifers and literal strings. Try reducing this number by using external data files loaded at runtime";
 	DynArray.set ctx.opcodes 0 idents;
+	if Plugin.defined "swf-mark" then begin
+		let ch = IO.output_channel (open_out_bin (Filename.chop_extension file ^ ".mark")) in
+		IO.write_i32 ch (List.length ctx.fun_pargs);
+		List.iter (fun (id,l) ->
+			IO.write_i32 ch id;
+			IO.write_i32 ch (List.length l);
+			List.iter (fun f -> IO.write_byte ch (if f then 1 else 0)) l;
+		) ctx.fun_pargs;
+		IO.write_i32 ch (List.length pidents);
+		List.iter (fun f -> IO.write_byte ch (if f then 1 else 0)) pidents;
+		IO.close_out ch;
+	end;
+	[TDoAction ctx.opcodes] , ctx.movieclips
+
+let generate file ver header infile types hres =
+	let file , codeclip = (try let f , c = ExtString.String.split file "@" in f, Some c with _ -> file , None) in
+	let tag_code , movieclips = (if ver = 9 then
+			Genswf9.generate types hres , []
+		else
+			generate_code file ver types hres
+	) in
 	let tag ?(ext=false) d = {
 		tid = 0;
 		textended = ext;
 		tdata = d;
 	} in
 	let base_id = ref 0x5000 in
-	let tagcode = (match codeclip with
-		| None -> [tag (TDoAction ctx.opcodes)]
+	let tag_code = (match codeclip with
+		| None -> List.map tag tag_code
 		| Some link -> 
 			incr base_id;
 			[
 				tag (TClip {
 					c_id = !base_id;
 					c_frame_count = 1;
-					c_tags = [
-						tag (TDoAction ctx.opcodes);
-						tag TShowFrame;
-					]
+					c_tags = List.map tag tag_code @ [tag TShowFrame];
 			    });
 				tag (TExport [{ exp_id = !base_id; exp_name = link }]);
 			]
@@ -1414,13 +1431,15 @@ let generate file ver header infile types hres =
 		tag ~ext:true (TClip { c_id = !base_id; c_frame_count = 1; c_tags = [] }) ::
 		tag ~ext:true (TExport [{ exp_id = !base_id; exp_name = s_type_path m }]) ::
 		acc
-	) [] ctx.movieclips in
+	) [] movieclips in
+	let movieclips = ref movieclips in
 	let swf = (match infile with
 		| None ->
 			let header , bg = (match header with None -> default_header ver | Some h -> convert_header ver h) in
 			let tagbg = tag (TSetBgColor { cr = bg lsr 16; cg = (bg lsr 8) land 0xFF; cb = bg land 0xFF }) in
+			let tagstart = (if ver >= 8 then [tag (TFlash8 "\x08\x00\x00\x00");tagbg] else [tagbg]) in
 			let tagshow = tag TShowFrame in
-			(header,tagbg :: tagclips() @ tagcode @ [tagshow])
+			(header,tagstart @ tagclips() @ tag_code @ [tagshow])
 		| Some file ->
 			let file = (try Plugin.find_file file with Not_found -> failwith ("File not found : " ^ file)) in
 			let ch = IO.input_channel (open_in_bin file) in
@@ -1448,30 +1467,18 @@ let generate file ver header infile types hres =
 					| None -> t :: loop l
 					| Some bg -> bg :: loop l)
 				| ({ tdata = TShowFrame } as t) :: l ->
-					tagclips() @ tagcode @ t :: l
+					tagclips() @ tag_code @ t :: l
 				| t :: l ->
 					(match t.tdata with
 					| TExport l ->
 						List.iter (fun e ->
-							ctx.movieclips <- List.filter (fun x -> s_type_path x <> e.exp_name) ctx.movieclips
+							movieclips := List.filter (fun x -> s_type_path x <> e.exp_name) (!movieclips)
 						) l
 					| _ -> ());
 					t :: loop l
 			in
 			(header , loop swf)
 	) in
-	if Plugin.defined "swf-mark" then begin
-		let ch = IO.output_channel (open_out_bin (Filename.chop_extension file ^ ".mark")) in
-		IO.write_i32 ch (List.length ctx.fun_pargs);
-		List.iter (fun (id,l) ->
-			IO.write_i32 ch id;
-			IO.write_i32 ch (List.length l);
-			List.iter (fun f -> IO.write_byte ch (if f then 1 else 0)) l;
-		) ctx.fun_pargs;
-		IO.write_i32 ch (List.length pidents);
-		List.iter (fun f -> IO.write_byte ch (if f then 1 else 0)) pidents;
-		IO.close_out ch;
-	end;
 	let ch = IO.output_channel (open_out_bin file) in
 	Swf.write ch swf;
 	IO.close_out ch

+ 272 - 0
genswf9.ml

@@ -0,0 +1,272 @@
+(*
+ *  Haxe Compiler
+ *  Copyright (c)2006 Nicolas Cannasse
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *)
+open As3
+open Type
+
+type ('a,'b) gen_lookup = {
+	h : ('a,'b) Hashtbl.t;
+	a : 'a DynArray.t;
+	c : int -> 'b;
+}
+
+type 'a lookup = ('a,'a index) gen_lookup
+type 'a lookup_nz = ('a,'a index_nz) gen_lookup
+
+type context = {
+	(* globals *)
+	idents : string lookup;
+	ints : int32 lookup;
+	floats : float lookup;
+	brights : as3_base_right lookup;
+	rights : as3_rights lookup;
+	types : as3_type lookup;
+	mtypes : as3_method_type lookup_nz;
+	mutable classes : as3_class list;
+	mutable statics : as3_static list;
+	mutable inits : as3_static list;
+	functions : as3_function lookup;
+	rpublic : as3_base_right index;
+
+	(* per-function *)
+	mutable locals : (string,int) PMap.t;
+	mutable code : as3_opcode DynArray.t;
+	mutable pos : int;
+}
+
+let public = A3RPublic None
+let mt0 = {
+	mt3_ret = None;
+	mt3_args = [];
+	mt3_native = false;
+	mt3_var_args = false;
+	mt3_debug_name = None;
+	mt3_dparams = None;
+	mt3_pnames = None;
+	mt3_unk_flags = (false,false,false,false);
+}
+
+let index_int (x : int) : 'a index = Obj.magic (x + 1)
+let index_nz_int (x : int) : 'a index_nz = Obj.magic x
+let tid (x : 'a index) : int = Obj.magic x
+
+let new_lookup() = { h = Hashtbl.create 0; a = DynArray.create(); c = index_int }
+let new_lookup_nz() = { h = Hashtbl.create 0; a = DynArray.create(); c = index_nz_int }
+
+let lookup i w =
+	try
+		Hashtbl.find w.h i
+	with
+		Not_found ->
+			let id = w.c (DynArray.length w.a) in
+			Hashtbl.add w.h i id;
+			DynArray.add w.a i;
+			id
+
+let add i w =
+	let id = w.c (DynArray.length w.a) in
+	DynArray.add w.a i;
+	id
+
+let lookup_array w = DynArray.to_array w.a
+
+let ident ctx i = lookup i ctx.idents
+
+let write ctx op =
+	DynArray.add ctx.code op;
+	ctx.pos <- As3code.length op + ctx.pos
+
+let acc_ident ctx i =
+	try
+		write ctx (A3Reg (PMap.find i ctx.locals))
+	with
+		Not_found -> assert false
+
+let type_path ctx ?(getclass=false) (pack,name) =
+	let pid = ident ctx (String.concat "." pack) in
+	let nameid = ident ctx name in
+	let pid = lookup (A3RPublic (Some pid)) ctx.brights in
+	let tid = lookup (if getclass then A3TClassInterface (Some nameid,pid) else A3TMethodVar (nameid,pid)) ctx.types in
+	tid
+
+let begin_fun ctx args =
+	let mt = {
+		mt3_ret = None;
+		mt3_args = List.map (fun _ -> None) args;
+		mt3_native = false;
+		mt3_var_args = false;
+		mt3_debug_name = None;
+		mt3_dparams = None;
+		mt3_pnames = None;
+		mt3_unk_flags = (false,false,false,false);
+	} in
+	let old_locals = ctx.locals in
+	let old_code = ctx.code in
+	let old_pos = ctx.pos in
+	let count = ref 0 in
+	ctx.locals <- List.fold_left (fun acc name -> incr count; PMap.add name (!count) acc) PMap.empty args;
+	ctx.code <- DynArray.create();
+	ctx.pos <- 0;
+	(fun () ->
+		let f = {
+			fun3_id = add mt ctx.mtypes;
+			fun3_unk1 = 2;
+			fun3_unk2 = 1;
+			fun3_unk3 = 1;
+			fun3_unk4 = 3;
+			fun3_code = DynArray.to_list ctx.code;
+			fun3_trys = [||];
+			fun3_locals = [||];
+		} in
+		ignore(add f ctx.functions);
+		ctx.locals <- old_locals;
+		ctx.code <- old_code;
+		ctx.pos <- old_pos;
+		f.fun3_id
+	)
+
+let generate_construct ctx args =
+	let f = begin_fun ctx args in
+	write ctx A3This;
+	write ctx A3Context;
+	write ctx A3This;
+	List.iter (acc_ident ctx) args;
+	write ctx (A3SuperConstr (List.length args));
+	write ctx A3RetVoid;
+	f()
+
+let generate_class_init ctx c =
+	let f = begin_fun ctx [] in
+	write ctx A3This;
+	write ctx A3Context;
+	write ctx (A3LoadBlock 0);
+	write ctx (A3GetProp (tid (type_path ctx ([],"Object"))));
+	write ctx A3Context;
+	write ctx (A3GetProp (tid (type_path ~getclass:true ctx ([],"Object"))));
+	write ctx (A3ClassDef (List.length ctx.classes));
+	write ctx A3PopContext;
+	write ctx (A3Set (tid (type_path ctx c.cl_path)));
+	write ctx A3RetVoid;
+	f()
+
+let generate_class_static ctx c =
+	let f = begin_fun ctx [] in
+	write ctx A3RetVoid;
+	f()
+
+let generate_class ctx c =
+	let name_id = type_path ctx c.cl_path in
+	let st_id = generate_class_static ctx c in
+	let cid = (match c.cl_constructor with
+		| None ->
+			let rec loop c =
+				match c.cl_super with
+				| None ->
+					generate_construct ctx []
+				| Some (csup,_) ->
+					match csup.cl_constructor with
+					| None -> loop csup
+					| Some co -> generate_construct ctx (match follow co.cf_type with TFun (l,_) -> List.map (fun (name,_,_) -> name) l | _ -> assert false)
+			in
+			loop c
+		| Some f -> assert false
+	) in
+	let fields = [||] in
+	let sc = {
+		cl3_name = name_id;
+		cl3_super = (match c.cl_super with None -> Some (type_path ctx ([],"Object")) | Some _ -> assert false);
+		cl3_sealed = true;
+		cl3_final = false;
+		cl3_interface = false;
+		cl3_rights = None;
+		cl3_implements = [||];
+		cl3_construct = cid;
+		cl3_fields = fields;
+	} in
+	let st = {
+		st3_method = st_id;
+		st3_fields = [||];
+	} in
+	let ic = {
+		st3_method = generate_class_init ctx c;
+		st3_fields = [|
+			{
+				f3_name = sc.cl3_name;
+				f3_slot = 1;
+				f3_kind = A3FClass (index_nz_int (List.length ctx.classes));
+				f3_metas = None;
+			}
+		|];
+	} in	
+	ctx.classes <- sc :: ctx.classes;
+	ctx.statics <- st :: ctx.statics;
+	ctx.inits <- ic :: ctx.inits;
+	()
+
+let generate_type ctx t =
+	match t with
+	| TClassDecl c -> if not c.cl_extern then generate_class ctx c
+	| TTypeDecl _ -> ()
+	| TEnumDecl e ->
+		match e.e_path with
+		| [] , "Void" | [] , "Bool" | [] , "Dynamic" -> ()
+		| _ ->
+			failwith (Ast.s_type_path e.e_path)
+
+let generate types hres =
+	let brights = new_lookup() in
+	let idents = new_lookup() in
+	let empty_id = lookup "" idents in
+	let rpublic = lookup (A3RPublic (Some empty_id)) brights in
+	let ctx = {
+		idents = idents;
+		ints = new_lookup();
+		floats = new_lookup();
+		brights = brights;
+		rights = new_lookup();
+		types = new_lookup();
+		mtypes = new_lookup_nz();
+		rpublic = rpublic;
+		classes = [];
+		statics = [];
+		inits = [];
+		functions = new_lookup();
+
+		code = DynArray.create();
+		locals = PMap.empty;
+		pos = 0;
+	} in
+	ignore(lookup [ctx.rpublic] ctx.rights);
+	List.iter (generate_type ctx) types;
+	Hashtbl.iter (fun _ _ -> assert false) hres;
+	let a = {
+		as3_ints = lookup_array ctx.ints;
+		as3_floats = lookup_array ctx.floats;
+		as3_idents = lookup_array ctx.idents;
+		as3_base_rights = lookup_array ctx.brights;
+		as3_rights = lookup_array ctx.rights;
+		as3_types = lookup_array ctx.types;
+		as3_method_types = lookup_array ctx.mtypes;
+		as3_metadatas = [||];
+		as3_classes = Array.of_list (List.rev ctx.classes);
+		as3_statics = Array.of_list (List.rev ctx.statics);
+		as3_inits = Array.of_list (List.rev ctx.inits);
+		as3_functions = lookup_array ctx.functions;
+		as3_unknown = "";
+	} in
+	[Swf.TActionScript3 (None,a); Swf.TSwf9Name [0,"Test"]]

+ 10 - 0
haxe.vcproj

@@ -51,6 +51,13 @@
 				RelativePath="..\neko\libs\include\ocaml\nxml.ml">
 			</File>
 		</Filter>
+		<Filter
+			Name="AS3"
+			Filter="">
+			<File
+				RelativePath="..\..\mtcvs\swflib\as3.mli">
+			</File>
+		</Filter>
 		<File
 			RelativePath=".\ast.ml">
 		</File>
@@ -60,6 +67,9 @@
 		<File
 			RelativePath=".\genswf.ml">
 		</File>
+		<File
+			RelativePath=".\genswf9.ml">
+		</File>
 		<File
 			RelativePath=".\genxml.ml">
 		</File>