| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258 | (* *  This file is part of SwfLib *  Copyright (c)2004 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA *)open Swfopen ActionScriptopen IO(* ************************************************************************ *)(* TOOLS *)let full_parsing = ref truelet force_as3_parsing = ref falselet swf_version = ref 0let id_count = ref 0let tag_end = { tid = 0; textended = false; tdata = TEnd }let sum f l =	List.fold_left (fun acc x -> acc + f x) 0 llet gen_id() =	incr id_count;	!id_countlet const n = fun _ -> nlet opt_len f = function	| None -> 0	| Some x -> f xlet opt_flag flags fid f fparam =	if (flags land fid) = 0 then		None	else		Some (f fparam)let opt f = function	| None -> ()	| Some x -> f xlet flag = function	| None -> false	| Some _ -> truelet rec make_flags = function	| [] -> 0	| true :: l -> 1 lor ((make_flags l) lsl 1)	| false :: l -> (make_flags l) lsl 1let f16_value (a,b) =	let k = int_of_char a lor (int_of_char b lsl 8) in	float_of_int k /. float_of_int (1 lsl 8)let rec read_count n f arg =	if n = 0 then		[]	else		let v = f arg in		v :: read_count (n - 1) f arg(* ************************************************************************ *)(* LENGTH *)let _nbits x =	if x < 0 then error "Negative nbits";	if x = 0 then		0	else		let x = ref x in		let nbits = ref 0 in		while !x > 0 do			x := !x lsr 1;			incr nbits;		done;		!nbitslet rect_nbits r =	r.rect_nbitslet bigrect_nbits r =	r.brect_nbitslet rgba_nbits c =	max		(max (_nbits c.r) (_nbits c.g))		(max (_nbits c.b) (_nbits c.a))let cxa_nbits c =	c.cxa_nbitslet matrix_part_nbits m =	m.m_nbitslet rgb_length = 3let rgba_length = 4let string_length s = String.length s + 1let color_length = function	| ColorRGB _ -> rgb_length	| ColorRGBA _ -> rgba_lengthlet rect_length r =	let nbits = rect_nbits r in	let nbits = nbits * 4 + 5 in	(nbits + 7) / 8let big_rect_length r =	let nbits = bigrect_nbits r in	let nbits = nbits * 4 + 5 in	(nbits + 7) / 8let gradient_length = function	| GradientRGB (l,_) -> 1 + (1 + rgb_length) * List.length l	| GradientRGBA (l,_) -> 1 + (1 + rgba_length) * List.length llet matrix_length m =	let matrix_part_len m = 5 + matrix_part_nbits m * 2 in	let nbits = 2 + opt_len matrix_part_len m.scale + opt_len matrix_part_len m.rotate + matrix_part_len m.trans in	(nbits + 7) / 8let cxa_length c =	let nbits = cxa_nbits c in	let nbits = 6 + opt_len (const (nbits * 4)) c.cxa_add + opt_len (const (nbits * 4)) c.cxa_mult in	(nbits + 7) / 8let clip_event_length c =	(if !swf_version >= 6 then 4 else 2) + 4 + (opt_len (const 1) c.cle_key) + actions_length c.cle_actionslet clip_events_length l =	(if !swf_version >= 6 then 10 else 6) + sum clip_event_length llet export_length e =	2 + string_length e.exp_namelet import_length i =	2 + string_length i.imp_namelet sound_length s =	2 + 1 + 4 + String.length s.so_datalet shape_fill_style_length s =	1 + match s with	| SFSSolid _ -> rgb_length	| SFSSolid3 _ -> rgba_length	| SFSLinearGradient (m,g)	| SFSRadialGradient (m,g,None) -> matrix_length m + gradient_length g	| SFSRadialGradient (m,g,Some _) -> matrix_length m + gradient_length g + 2	| SFSBitmap b -> 2 + matrix_length b.sfb_mposlet shape_line_style_length s =	2 + match s.sls_flags with		| None -> color_length s.sls_color		| Some _ ->			2 + (match s.sls_fill with None -> color_length s.sls_color | Some f -> shape_fill_style_length f)			  + opt_len (const 2) s.sls_miterlet shape_array_length f s =	let n = List.length s in	(if n < 0xFF then 1 else 3) + sum f slet shape_new_styles_length s =	shape_array_length shape_fill_style_length s.sns_fill_styles +	shape_array_length shape_line_style_length s.sns_line_styles +	1let font_shape_records_length records =	let nbits = ref 8 in	let nfbits = ref records.srs_nfbits in	let nlbits = ref records.srs_nlbits in	List.iter (fun r ->		nbits := !nbits + 6;		match r with		| SRStyleChange s ->			nbits := !nbits +				opt_len (fun (n,_,_) -> 5 + n * 2) s.scsr_move +				opt_len (const !nfbits) s.scsr_fs0 +				opt_len (const !nfbits) s.scsr_fs1 +				opt_len (const !nlbits) s.scsr_ls;		| SRCurvedEdge s ->			nbits := !nbits + s.scer_nbits * 4		| SRStraightEdge s ->			nbits := !nbits + 1 + (match s.sser_line with								| None , None -> assert false								| Some _ , None								| None, Some _ -> 1 + s.sser_nbits								| Some _ , Some _ -> 2 * s.sser_nbits)	) records.srs_records;	(* nbits := !nbits + 6; *)	(!nbits + 7) / 8let shape_records_length records =	let nbits = ref 8 in	let nfbits = ref records.srs_nfbits in	let nlbits = ref records.srs_nlbits in	List.iter (fun r ->		nbits := !nbits + 6;		match r with		| SRStyleChange s ->			nbits := !nbits +				opt_len (fun (n,_,_) -> 5 + n * 2) s.scsr_move +				opt_len (const !nfbits) s.scsr_fs0 +				opt_len (const !nfbits) s.scsr_fs1 +				opt_len (const !nlbits) s.scsr_ls;			(match s.scsr_new_styles with			| None -> ()			| Some s ->				nbits := (((!nbits + 7) / 8) + shape_new_styles_length s) * 8;				nfbits := s.sns_nfbits;				nlbits := s.sns_nlbits)		| SRCurvedEdge s ->			nbits := !nbits + s.scer_nbits * 4		| SRStraightEdge s ->			nbits := !nbits + 1 + (match s.sser_line with								| None , None -> assert false								| Some _ , None								| None, Some _ -> 1 + s.sser_nbits								| Some _ , Some _ -> 2 * s.sser_nbits)	) records.srs_records;	nbits := !nbits + 6;	(!nbits + 7) / 8let shape_with_style_length s =	shape_array_length shape_fill_style_length s.sws_fill_styles +	shape_array_length shape_line_style_length s.sws_line_styles +	shape_records_length s.sws_recordslet shape_length s =	2 + rect_length s.sh_bounds + opt_len (fun (r,_) -> rect_length r + 1) s.sh_bounds2 + shape_with_style_length s.sh_stylelet bitmap_lossless_length b =	2 + 1 + 2 + 2 + String.length b.bll_datalet morph_shape_length s =	2 + rect_length s.msh_start_bounds + rect_length s.msh_end_bounds + String.length s.msh_datalet text_record_length t r =	1 + opt_len (const 4) r.txr_font +		opt_len color_length r.txr_color +		opt_len (const 2) r.txr_dx +		opt_len (const 2) r.txr_dy +		1 + ((((t.txt_ngbits + t.txt_nabits) * List.length r.txr_glyphs) + 7) / 8)let text_length t =	2 + big_rect_length t.txt_bounds + matrix_length t.txt_matrix + 2 + sum (text_record_length t) t.txt_records + 1let filters_length l =	1 + sum (fun f ->		1 + match f with		| FDropShadow s		| FBlur s		| FGlow s		| FBevel s		| FAdjustColor s ->			String.length s		| FGradientGlow fg		| FGradientBevel fg ->			1 + ((rgba_length + 1) * List.length fg.fgr_colors) + String.length fg.fgr_data	) llet button_record_length r =	1 + 2 + 2 + matrix_length r.btr_mpos + (match r.btr_color with None -> 0 | Some c -> cxa_length c)	+ opt_len filters_length r.btr_filters	+ (match r.btr_blendmode with None -> 0 | Some c -> 1)let button_action_length r =	2 + 2 + actions_length r.bta_actionslet button2_length b =	2 + 1 + 2 +		1 + sum button_record_length b.bt2_records +		sum button_action_length b.bt2_actionslet cid_data_length c =	2 + String.length c.cd_datalet edit_text_layout_length = 9let header_length h =	3 + 1 + rect_length h.h_size + 2 + 4let edit_text_length t =	2 + rect_length t.edt_bounds + 2 +		opt_len (const 4) t.edt_font +		opt_len (const rgba_length) t.edt_color +		opt_len (const 2) t.edt_maxlen +		opt_len (const edit_text_layout_length) t.edt_layout +		string_length t.edt_variable +		opt_len string_length t.edt_textlet place_object_length p v3 =	3	+ (if v3 then 1 else 0)	+ 0 (* po_move *)	+ opt_len (const 2) p.po_cid	+ opt_len matrix_length p.po_matrix	+ opt_len cxa_length p.po_color	+ opt_len (const 2) p.po_ratio	+ opt_len string_length p.po_inst_name	+ opt_len (const 2) p.po_clip_depth	+ opt_len clip_events_length p.po_events	+ (if v3 then		opt_len filters_length p.po_filters		+ opt_len (const 1) p.po_blend		+ opt_len (const 1) p.po_bcache	else		0)let rec tag_data_length = function	| TEnd ->		0	| TShowFrame ->		0	| TShape s ->		shape_length s	| TRemoveObject _ ->		4	| TBitsJPEG b ->		2 + String.length b.jpg_data	| TJPEGTables tab ->		String.length tab	| TSetBgColor _ ->		rgb_length	| TFont c ->		cid_data_length c	| TText t ->		text_length t	| TDoAction acts ->		actions_length acts	| TFontInfo c ->		cid_data_length c	| TSound s ->		sound_length s	| TStartSound s ->		2 + String.length s.sts_data	| TBitsLossless b ->		bitmap_lossless_length b	| TBitsJPEG2 b ->		2 + opt_len String.length b.bd_table + String.length b.bd_data	| TShape2 s ->		shape_length s	| TProtect ->		0	| TPlaceObject2 p ->		place_object_length p false	| TRemoveObject2 _ ->		2	| TShape3 s ->		shape_length s	| TText2 t ->		text_length t	| TButton2 b ->		button2_length b	| TBitsJPEG3 b ->		2 + 4 + opt_len String.length b.bd_table + String.length b.bd_data + opt_len String.length b.bd_alpha	| TBitsLossless2 b ->		bitmap_lossless_length b	| TEditText t ->		edit_text_length t	| TClip c ->		4 + sum tag_length (tag_end :: c.c_tags)	| TProductInfo s ->		String.length s	| TFrameLabel (label,id) ->		string_length label + (match id with None -> 0 | Some _ -> 1)	| TSoundStreamHead2 data ->		String.length data	| TMorphShape s | TMorphShape2 s ->		morph_shape_length s	| TFont2 c | TFont3 c | TFontAlignZones c ->		cid_data_length c	| TExport el ->		2 + sum export_length el	| TImport (url,il) ->		string_length url + 2 + sum import_length il	| TDoInitAction i ->		2 + actions_length i.dia_actions	| TVideoStream c ->		cid_data_length c	| TVideoFrame c ->		cid_data_length c	| TFontInfo2 c ->		cid_data_length c	| TDebugID s ->		String.length s	| TEnableDebugger2 (_,pass) ->		2 + string_length pass	| TScriptLimits _ ->		4	| TFilesAttributes _ ->		4	| TPlaceObject3 p ->		place_object_length p true	| TImport2 (url,il) ->		string_length url + 1 + 1 + 2 + sum import_length il	| TCSMSettings c ->		cid_data_length c	| TF9Classes l ->		2 + sum (fun c -> string_length c.f9_classname + 2) l	| TMetaData meta ->		string_length meta	| TScale9 (_,r) ->		2 + rect_length r	| TActionScript3 (id,a) ->		(match id with None -> 0 | Some (id,f) -> 4 + string_length f) + As3parse.as3_length a	| TShape4 s ->		shape_length s	| TScenes (sl,fl) ->		As3parse.int_length (List.length sl) + sum (fun(n,s) -> As3parse.int_length n + string_length s) sl +		As3parse.int_length (List.length fl) + sum (fun(n,s) -> As3parse.int_length n + string_length s) fl	| TBinaryData (_,data) ->		2 + 4 + String.length data	| TBigBinaryData (_,data) ->		2 + 4 + (List.fold_left (fun acc s -> acc + String.length s) 0 data)	| TFontName c ->		cid_data_length c	| TBitsJPEG4 b ->		2 + 2 + 4 + opt_len String.length b.bd_table + String.length b.bd_data + opt_len String.length b.bd_alpha	| TFont4 c ->		cid_data_length c	| TUnknown (_,data) ->		String.length dataand tag_length t =	let dlen = tag_data_length t.tdata in	dlen + 2 + (if t.textended || dlen >= 63 then 4 else 0)(* ************************************************************************ *)(* READ PRIMS *)let skip ch n =	seek_in ch ((Stdlib.pos_in ch) + n)let read_rgba ch =	let r = read_byte ch in	let g = read_byte ch in	let b = read_byte ch in	let a = read_byte ch in	{		r = r;		g = g;		b = b;		a = a;	}let read_rgb ch =	let r = read_byte ch in	let g = read_byte ch in	let b = read_byte ch in	{		cr = r;		cg = g;		cb = b;	}let read_gradient ch is_rgba =	let grad_rgb() =		let r = read_byte ch in		let c = read_rgb ch in		(r, c)	in	let grad_rgba() =		let r = read_byte ch in		let c = read_rgba ch in		(r, c)	in	let n = read_byte ch in	let n , flags = n land 0xF , n lsr 4 in	if is_rgba then		GradientRGBA (read_count n grad_rgba (),flags)	else		GradientRGB (read_count n grad_rgb (),flags)let read_rect ch =	let b = input_bits ch in	let nbits = read_bits b 5 in	let left = read_bits b nbits in	let right = read_bits b nbits in	let top = read_bits b nbits in	let bottom = read_bits b nbits in	{		rect_nbits = nbits;		left = left;		right = right;		top = top;		bottom = bottom;	}let rec read_multi_bits b n =	if n <= 30 then		[read_bits b n]	else		let d = read_bits b 30 in		d :: read_multi_bits b (n - 30)let read_big_rect ch =	let b = input_bits ch in	let nbits = read_bits b 5 in	let left = read_multi_bits b nbits in	let right = read_multi_bits b nbits in	let top = read_multi_bits b nbits in	let bottom = read_multi_bits b nbits in	{		brect_nbits = nbits;		bleft = left;		bright = right;		btop = top;		bbottom = bottom;	}let read_matrix ch =	let b = input_bits ch in	let read_matrix_part() =		let nbits = read_bits b 5 in		let x = read_bits b nbits in		let y = read_bits b nbits in		{			m_nbits = nbits;			mx = x;			my = y;		}	in	let has_scale = (read_bits b 1 = 1) in	let scale = (if has_scale then Some (read_matrix_part()) else None) in	let has_rotate = (read_bits b 1 = 1) in	let rotate = (if has_rotate then Some (read_matrix_part()) else None) in	let trans = read_matrix_part() in	{		scale = scale;		rotate = rotate;		trans = trans;	}let read_cxa ch =	let b = input_bits ch in	let has_add = (read_bits b 1 = 1) in	let has_mult = (read_bits b 1 = 1) in	let nbits = read_bits b 4 in	let read_cxa_color() =		let r = read_bits b nbits in		let g = read_bits b nbits in		let bl = read_bits b nbits in		let a = read_bits b nbits in		{			r = r;			g = g;			b = bl;			a = a;		}	in	let mult = (if has_mult then Some (read_cxa_color()) else None) in	let add = (if has_add then Some (read_cxa_color()) else None) in	{		cxa_nbits = nbits;		cxa_add = add;		cxa_mult = mult;	}let read_event ch =	(if !swf_version >= 6 then read_i32 else read_ui16) ch(* ************************************************************************ *)(* WRITE PRIMS *)let write_rgb ch c =	write_byte ch c.cr;	write_byte ch c.cg;	write_byte ch c.cblet write_rgba ch c =	write_byte ch c.r;	write_byte ch c.g;	write_byte ch c.b;	write_byte ch c.alet write_color ch = function	| ColorRGB c -> write_rgb ch c	| ColorRGBA c -> write_rgba ch clet write_gradient ch = function	| GradientRGB (l,flags) ->		let n = List.length l in		write_byte ch (n lor (flags lsl 4));		List.iter (fun (ratio,c) -> write_byte ch ratio; write_rgb ch c) l	| GradientRGBA (l,flags) ->		let n = List.length l in		write_byte ch (n lor (flags lsl 4));		List.iter (fun (ratio,c) -> write_byte ch ratio; write_rgba ch c) llet write_rect ch r =	let b = output_bits ch in	let nbits = rect_nbits r in	write_bits b 5 nbits;	write_bits b nbits r.left;	write_bits b nbits r.right;	write_bits b nbits r.top;	write_bits b nbits r.bottom;	flush_bits blet rec write_multi_bits b n l =	if n <= 30 then		match l with		| [] -> write_bits b n 0		| [x] -> write_bits b n x		| _ -> assert false	else		match l with		| [] -> write_bits b 30 0; write_multi_bits b (n - 30) []		| x :: l -> write_bits b 30 x; write_multi_bits b (n - 30) llet write_big_rect ch r =	let b = output_bits ch in	let nbits = bigrect_nbits r in	write_bits b 5 nbits;	write_multi_bits b nbits r.bleft;	write_multi_bits b nbits r.bright;	write_multi_bits b nbits r.btop;	write_multi_bits b nbits r.bbottom;	flush_bits blet write_matrix ch m =	let b = output_bits ch in	let write_matrix_part m =		let nbits = matrix_part_nbits m in		write_bits b 5 nbits;		write_bits b nbits m.mx;		write_bits b nbits m.my;	in	(match m.scale with	| None ->		write_bits b 1 0	| Some s ->		write_bits b 1 1;		write_matrix_part s	);	(match m.rotate with	| None ->		write_bits b 1 0	| Some r ->		write_bits b 1 1;		write_matrix_part r);	write_matrix_part m.trans;	flush_bits blet write_cxa ch c =	let b = output_bits ch in	let nbits = cxa_nbits c in	(match c.cxa_add , c.cxa_mult with	| None , None ->		write_bits b 2 0;		write_bits b 4 1; (* some strange MM thing... *)	| Some c , None ->		write_bits b 2 2;		write_bits b 4 nbits;		List.iter (write_bits b ~nbits) [c.r;c.g;c.b;c.a];	| None , Some c ->		write_bits b 2 1;		write_bits b 4 nbits;		List.iter (write_bits b ~nbits) [c.r;c.g;c.b;c.a];	| Some c1 , Some c2 ->		write_bits b 2 3;		write_bits b 4 nbits;		List.iter (write_bits b ~nbits) [c2.r;c2.g;c2.b;c2.a;c1.r;c1.g;c1.b;c1.a]	);	flush_bits blet write_event ch evt =	(if !swf_version >= 6 then write_i32 else write_ui16) ch evt(* ************************************************************************ *)(* PARSING *)let parse_clip_events ch =	ignore(read_ui16 ch); (* reserved *)	ignore(read_event ch); (* all_events *)	let rec loop() =		let events = read_event ch in		if events = 0 then			[]		else begin			ignore(read_i32 ch); (* len *)			let key = (if events land (1 lsl 17) <> 0 then Some (read ch) else None) in			let e = {				cle_events = events;				cle_key = key;				cle_actions = parse_actions ch			} in			e :: (loop())		end;	in	loop()let parse_shape_fill_style ch vshape =	let t = read_byte ch in	match t with	| 0x00 when vshape >= 3 -> SFSSolid3 (read_rgba ch)	| 0x00 -> SFSSolid (read_rgb ch)	| 0x10 ->		let m = read_matrix ch in		let g = read_gradient ch (vshape >= 3) in		SFSLinearGradient (m,g)	| 0x12 ->		let m = read_matrix ch in		let g = read_gradient ch (vshape >= 3) in		SFSRadialGradient (m,g,None)	| 0x13 ->		let m = read_matrix ch in		let g = read_gradient ch (vshape >= 3) in		let i = read_i16 ch in		SFSRadialGradient (m,g,Some i)	| 0x40	| 0x41	| 0x42	| 0x43 ->		let id = read_ui16 ch in		let m = read_matrix ch in		SFSBitmap {			sfb_repeat = (t = 0x40 || t = 0x42);			sfb_smooth = (t = 0x42 || t = 0x43);			sfb_cid = id;			sfb_mpos = m;		}	| _ ->		assert falselet parse_shape_line_style ch vshape =	let width = read_ui16 ch in	if vshape >= 4 then begin		let flags = read_ui16 ch in		let fill = (flags land 8 <> 0) in		let miterjoin = (flags land 0x20 <> 0) in		let miter = (if miterjoin then Some (IO.read_ui16 ch) else None) in		let color = (if fill then { r = 0; g = 0; b = 0; a = 0 } else read_rgba ch) in		(*			let noVscale = (flags land 0x02 <> 0) in			let noHscale = (flags land 0x04 <> 0) in			let beveljoin = (flags land 0x10 <> 0) in			let nocap = (flags land 0x40 <> 0) in			let squarecap = (flags land 0x80 <> 0) in		*)		{			sls_width = width;			sls_color = ColorRGBA color;			sls_fill = if fill then Some (parse_shape_fill_style ch vshape) else None;			sls_flags = Some flags;			sls_miter = miter;		}	end else		{			sls_width = width;			sls_color = if vshape = 3 then ColorRGBA (read_rgba ch) else ColorRGB (read_rgb ch);			sls_fill = None;			sls_flags = None;			sls_miter = None;		}let parse_shape_array f ch vshape =	let n = (match read_byte ch with 0xFF -> read_ui16 ch | n -> n) in	read_count n (f ch) vshapelet parse_shape_style_change_record ch b flags nlbits nfbits vshape =	let move = (if flags land 1 <> 0 then begin		let mbits = read_bits b 5 in		let dx = read_bits b mbits in		let dy = read_bits b mbits in		Some (mbits,dx,dy)	end else		None)	in	let fs0 = (if flags land 2 <> 0 then Some (read_bits b !nfbits) else None) in	let fs1 = (if flags land 4 <> 0 then Some (read_bits b !nfbits) else None) in	let ls = (if flags land 8 <> 0 then Some (read_bits b !nlbits) else None) in	let styles = (if flags land 16 <> 0 then begin		IO.drop_bits b;		let fstyles = parse_shape_array parse_shape_fill_style ch vshape in		let lstyles = parse_shape_array parse_shape_line_style ch vshape in		let bits = read_byte ch in		nlbits := bits land 15;		nfbits := bits lsr 4;		Some {			sns_fill_styles = fstyles;			sns_line_styles = lstyles;			sns_nlbits = !nlbits;			sns_nfbits = !nfbits;		}	end else		None	) in	{		scsr_move = move;		scsr_fs0 = fs0;		scsr_fs1 = fs1;		scsr_ls = ls;		scsr_new_styles = styles;	}let parse_shape_curved_edge_record b flags =	let nbits = (flags land 15) + 2 in	let cx = read_bits b nbits in	let cy = read_bits b nbits in	let ax = read_bits b nbits in	let ay = read_bits b nbits in	{		scer_nbits = nbits;		scer_cx = cx;		scer_cy = cy;		scer_ax = ax;		scer_ay = ay;	}let parse_shape_straight_edge_record b flags =	let nbits = (flags land 15) + 2 in	let is_general = (read_bits b 1 = 1) in	let l = (if is_general then		let dx = read_bits b nbits in		let dy = read_bits b nbits in		Some dx, Some dy	else		let is_vertical = (read_bits b 1 = 1) in		let p = read_bits b nbits in		if is_vertical then			None, Some p		else			Some p, None)	in	{		sser_nbits = nbits;		sser_line = l;	}let parse_shape_records ch nlbits nfbits vshape =	let b = input_bits ch in	let nlbits = ref nlbits in	let nfbits = ref nfbits in	let rec loop() =		let flags = read_bits b 6 in		if flags = 0 then			[]		else			let r =				(if (flags land 32) = 0 then					SRStyleChange (parse_shape_style_change_record ch b flags nlbits nfbits vshape)				else if (flags land 48) = 32 then					SRCurvedEdge (parse_shape_curved_edge_record b flags)				else					SRStraightEdge (parse_shape_straight_edge_record b flags))			in			r :: loop()	in	loop()let parse_shape_with_style ch vshape =	let fstyles = parse_shape_array parse_shape_fill_style ch vshape in	let lstyles = parse_shape_array parse_shape_line_style ch vshape in	let bits = read_byte ch in	let nlbits = bits land 15 in	let nfbits = bits lsr 4 in	let records = parse_shape_records ch nlbits nfbits vshape in	{		sws_fill_styles = fstyles;		sws_line_styles = lstyles;		sws_records = {			srs_nlbits = nlbits;			srs_nfbits = nfbits;			srs_records = records;		}	}let parse_shape ch len vshape =	let id = read_ui16 ch in	let bounds = read_rect ch in	let bounds2 = (if vshape = 4 then		let r = read_rect ch in		let b = read_byte ch in		Some (r, b)	else		None	) in	let style = parse_shape_with_style ch vshape in	{		sh_id = id;		sh_bounds = bounds;		sh_bounds2 = bounds2;		sh_style = style;	}let extract_jpg_table data =	match data.[0], data.[1] with	| '\xFF', '\xD8' ->		let ch = IO.input_string data in		let b = Buffer.create 0 in		let rec loop flag =			let c = IO.read ch in			Buffer.add_char b c;			match int_of_char c with			| 0xFF -> loop true			| 0xD9 when flag -> ()			| _ -> loop false		in		loop false;		let t = Buffer.contents b in		let l = String.length t in		String.sub data l (String.length data - l), Some t	| _ ->		data, Nonelet parse_bitmap_lossless ch len =	let id = read_ui16 ch in	let format = read_byte ch in	let width = read_ui16 ch in	let height = read_ui16 ch in	let data = nread_string ch (len - 7) in	{		bll_id = id;		bll_format = format;		bll_width = width;		bll_height = height;		bll_data = data;	}let parse_text ch is_txt2 =	let id = read_ui16 ch in	let bounds = read_big_rect ch in	let matrix = read_matrix ch in	let ngbits = read_byte ch in	let nabits = read_byte ch in	let read_glyph bits =		let indx = read_bits bits ngbits in		let adv = read_bits bits nabits in		{			txg_index = indx;			txg_advanced = adv;		}	in	let rec loop() =		let flags = read_byte ch in		if flags = 0 then			[]		else			let font_id = (if flags land 8 <> 0 then read_ui16 ch else 0) in			let color = (if flags land 4 <> 0 then Some (if is_txt2 then ColorRGBA (read_rgba ch) else ColorRGB (read_rgb ch)) else None) in			let dx = (if flags land 1 <> 0 then Some (read_i16 ch) else None) in			let dy = (if flags land 2 <> 0 then Some (read_i16 ch) else None) in			let font = (if flags land 8 <> 0 then Some (font_id,read_ui16 ch) else None) in			let nglyphs = read_byte ch in			let r = {				txr_font = font;				txr_color = color;				txr_dx = dx;				txr_dy = dy;				txr_glyphs = read_count nglyphs read_glyph (input_bits ch);			} in			r :: loop()	in	{		txt_id = id;		txt_bounds = bounds;		txt_matrix = matrix;		txt_ngbits = ngbits;		txt_nabits = nabits;		txt_records = loop();	}let parse_edit_text_layout ch =	let align = read_byte ch in	let ml = read_ui16 ch in	let rl = read_ui16 ch in	let ident = read_ui16 ch in	let lead = read_ui16 ch in	{		edtl_align = align;		edtl_left_margin = ml;		edtl_right_margin = rl;		edtl_indent = ident;		edtl_leading = lead;	}let parse_edit_text ch =	let id = read_ui16 ch in	let bounds = read_rect ch in	let flags = read_ui16 ch in	let font = (if flags land 1 <> 0 then			let fid = read_ui16 ch in			let height = read_ui16 ch in			Some (fid, height)		else			None) in	let color = (if flags land 4 <> 0 then Some (read_rgba ch) else None) in	let maxlen = (if flags land 2 <> 0 then Some (read_ui16 ch) else None) in	let layout = (if flags land (1 lsl 13) <> 0 then Some (parse_edit_text_layout ch) else None) in	let variable = read_string ch in	let text = (if flags land 128 <> 0 then Some (read_string ch) else None) in	{		edt_id = id;		edt_bounds = bounds;		edt_font = font;		edt_color = color;		edt_maxlen = maxlen;		edt_layout = layout;		edt_variable = variable;		edt_text = text;		edt_wordwrap = (flags land 64) <> 0;		edt_multiline = (flags land 32) <> 0;		edt_password = (flags land 16) <> 0;		edt_readonly = (flags land 8) <> 0;		edt_autosize = (flags land (1 lsl 14)) <> 0;		edt_noselect = (flags land 4096) <> 0;		edt_border = (flags land 2048) <> 0;		edt_html = (flags land 512) <> 0;		edt_outlines = (flags land 256) <> 0;	}let parse_cid_data ch len =	let id = read_ui16 ch in	let data = nread_string ch (len - 2) in	{		cd_id = id;		cd_data = data;	}let parse_morph_shape ch len =	let id = read_ui16 ch in	let sbounds = read_rect ch in	let ebounds = read_rect ch in	let data = nread_string ch (len - 2 - rect_length sbounds - rect_length ebounds) in	{		msh_id = id;		msh_start_bounds = sbounds;		msh_end_bounds = ebounds;		msh_data = data;	}let parse_filter_gradient ch =	let ncolors = read_byte ch in	let colors = read_count ncolors read_rgba ch in	let cvals = read_count ncolors read_byte ch in	let data = nread_string ch 19 in	{		fgr_colors = List.combine colors cvals;		fgr_data = data;	}let parse_filter ch =	match read_byte ch with	| 0 -> FDropShadow (nread_string ch 23)	| 1 -> FBlur (nread_string ch 9)	| 2 -> FGlow (nread_string ch 15)	| 3 -> FBevel (nread_string ch 27)	| 4 -> FGradientGlow (parse_filter_gradient ch)	| 6 -> FAdjustColor (nread_string ch 80)	| 7 -> FGradientBevel (parse_filter_gradient ch)	| _ -> assert falselet parse_filters ch =	let nf = read_byte ch in	read_count nf parse_filter chlet rec parse_button_records ch color =	let flags = read_byte ch in	if flags = 0 then		[]	else		let cid = read_ui16 ch in		let depth = read_ui16 ch in		let mpos = read_matrix ch in		let cxa = (if color then Some (read_cxa ch) else None) in		let filters = (if flags land 16 = 0 then None else Some (parse_filters ch)) in		let blendmode = (if flags land 32 = 0 then None else Some (read_byte ch)) in		let r = {			btr_flags = flags;			btr_cid = cid;			btr_depth = depth;			btr_mpos = mpos;			btr_color = cxa;			btr_filters = filters;			btr_blendmode = blendmode;		} in		r :: parse_button_records ch colorlet rec parse_button_actions ch =	let size = read_ui16 ch in	let flags = read_ui16 ch in	let actions = parse_actions ch in	let bta = {		bta_flags = flags;		bta_actions = actions;	} in	if size = 0 then		[bta]	else		bta :: parse_button_actions chlet parse_button2 ch len =	let id = read_ui16 ch in	let flags = read_byte ch in	let track = (match flags with 0 -> false | 1 -> true | _ -> assert false) in	let offset = read_ui16 ch in	let records = parse_button_records ch true in	let actions = (if offset = 0 then [] else parse_button_actions ch) in	{		bt2_id = id;		bt2_track_as_menu = track;		bt2_records = records;		bt2_actions = actions;	}let parse_place_object ch v3 =	let f = read_byte ch in	let fext = (if v3 then read_byte ch else 0) in	let depth = read_ui16 ch in	let move = (f land 1) <> 0 in	let cid = opt_flag f 2 read_ui16 ch in	let matrix = opt_flag f 4 read_matrix ch in	let color = opt_flag f 8 read_cxa ch in	let ratio = opt_flag f 16 read_ui16 ch in	let name = opt_flag f 32 read_string ch in	let clip_depth = opt_flag f 64 read_ui16 ch in	let clip_events = opt_flag f 128 parse_clip_events ch in	let filters = opt_flag fext 1 parse_filters ch in	let blend = opt_flag fext 2 read_byte ch in	let bcache = opt_flag fext 4 read_byte ch in	{		po_depth = depth;		po_move = move;		po_cid = cid;		po_matrix = matrix;		po_color = color;		po_ratio = ratio;		po_inst_name = name;		po_clip_depth = clip_depth;		po_events = clip_events;		po_filters = filters;		po_blend = blend;		po_bcache = bcache;	}let parse_import ch =	let cid = read_ui16 ch in	let name = read_string ch in	{		imp_id = cid;		imp_name = name	}let rec parse_tag ch h =	let id = h lsr 6 in	let len = h land 63 in	let len , extended = (		if len = 63 then			let len = read_i32 ch in			len , len < 63		else			len , false	) in	let t = (		match id with		| 0x00 ->			TEnd		| 0x01 ->			TShowFrame		| 0x02 when !full_parsing ->			TShape (parse_shape ch len 1)		(* 0x03 invalid *)		(*//0x04 TPlaceObject *)		| 0x05 ->			let cid = read_ui16 ch in			let depth = read_ui16 ch in			TRemoveObject {				rmo_id = cid;				rmo_depth = depth;			}		| 0x06 ->			let id = read_ui16 ch in			let data = nread_string ch (len - 2) in			TBitsJPEG {				jpg_id = id;				jpg_data = data;			}		(*//0x07 TButton *)		| 0x08 ->			TJPEGTables (nread_string ch len)		| 0x09 ->			TSetBgColor (read_rgb ch)		| 0x0A ->			TFont (parse_cid_data ch len)		| 0x0B when !full_parsing ->			TText (parse_text ch false)		| 0x0C ->			TDoAction (parse_actions ch)		| 0x0D ->			TFontInfo (parse_cid_data ch len)		| 0x0E ->			let sid = read_ui16 ch in			let flags = read_byte ch in			let samples = read_i32 ch in			let data = nread_string ch (len - 7) in			TSound {				so_id = sid;				so_flags = flags;				so_samples = samples;				so_data = data;			}		| 0x0F ->			let sid = read_ui16 ch in			let data = nread_string ch (len - 2) in			TStartSound {				sts_id = sid;				sts_data = data;			}		(* 0x10 invalid *)		(*//0x11 TButtonSound *)		(*//0x12 TSoundStreamHead *)		(*//0x13 TSoundStreamBlock *)		| 0x14 ->			TBitsLossless (parse_bitmap_lossless ch len)		| 0x15 ->			let id = read_ui16 ch in			let data = nread_string ch (len - 2) in			let data, table = extract_jpg_table data in			TBitsJPEG2 {				bd_id = id;				bd_table = table;				bd_data = data;				bd_alpha = None;				bd_deblock = None;			}		| 0x16 when !full_parsing ->			TShape2 (parse_shape ch len 2)		(*//0x17 TButtonCXForm *)		| 0x18 ->			TProtect		(* 0x19 invalid *)		| 0x1A when !full_parsing ->			TPlaceObject2 (parse_place_object ch false)		(* 0x1B invalid *)		| 0x1C ->			let depth = read_ui16 ch in			TRemoveObject2 depth		(* 0x1D-1F invalid *)		| 0x20 when !full_parsing ->			TShape3 (parse_shape ch len 3)		| 0x21 when !full_parsing ->			TText2 (parse_text ch true)		| 0x22 when !full_parsing ->			TButton2 (parse_button2 ch len)		| 0x23 ->			let id = read_ui16 ch in			let size = read_i32 ch in			let data = nread_string ch size in			let data, table = extract_jpg_table data in			let alpha = nread_string ch (len - 6 - size) in			TBitsJPEG3 {				bd_id = id;				bd_table = table;				bd_data = data;				bd_alpha = Some alpha;				bd_deblock = None;			}		| 0x24 ->			TBitsLossless2 (parse_bitmap_lossless ch len)		| 0x25 when !full_parsing ->			TEditText (parse_edit_text ch)		(* 0x26 invalid *)		| 0x27 ->			let cid = read_ui16 ch in			let fcount = read_ui16 ch in			let tags = parse_tag_list ch in			TClip {				c_id = cid;				c_frame_count = fcount;				c_tags = tags;			}		(* 0x28 invalid *)		| 0x29 ->			(* undocumented ? *)			TProductInfo (nread_string ch len)		(* 0x2A invalid *)		| 0x2B ->			let label = read_string ch in			let id = (if len = String.length label + 2 then Some (read ch) else None) in			TFrameLabel (label,id)		(* 0x2C invalid *)		| 0x2D ->			TSoundStreamHead2 (nread_string ch len)		| 0x2E when !full_parsing ->			TMorphShape (parse_morph_shape ch len)		(* 0x2F invalid *)		| 0x30 when !full_parsing ->			TFont2 (parse_cid_data ch len)		(* 0x31-37 invalid *)		| 0x38 ->			let read_export() =				let cid = read_ui16 ch in				let name = read_string ch in				{					exp_id = cid;					exp_name = name				}			in			TExport (read_count (read_ui16 ch) read_export ())		| 0x39 ->			let url = read_string ch in			TImport (url, read_count (read_ui16 ch) parse_import ch)		(*// 0x3A TEnableDebugger *)		| 0x3B ->			let cid = read_ui16 ch in			let actions = parse_actions ch in			TDoInitAction {				dia_id = cid;				dia_actions = actions;			}		| 0x3C ->			TVideoStream (parse_cid_data ch len)		| 0x3D ->			TVideoFrame (parse_cid_data ch len)		| 0x3E ->			TFontInfo2 (parse_cid_data ch len)		| 0x3F ->			(* undocumented ? *)			TDebugID (nread_string ch len)		| 0x40 ->			let tag = read_ui16 ch in			(* 0 in general, 6517 for some swfs *)			let pass_md5 = read_string ch in			TEnableDebugger2 (tag,pass_md5)		| 0x41 ->			let recursion_depth = read_ui16 ch in			let script_timeout = read_ui16 ch in			TScriptLimits (recursion_depth, script_timeout)		(*// 0x42 TSetTabIndex *)		(* 0x43-0x44 invalid *)		| 0x45 ->			let flags = IO.read_i32 ch in			let mask = 1 lor 8 lor 16 lor 32 lor 64 in			if (flags lor mask) <> mask then failwith ("Invalid file attributes " ^ string_of_int flags);			TFilesAttributes {				fa_network = (flags land 1) <> 0;				(* flags 2,4 : reserved *)				fa_as3 = (flags land 8) <> 0;				fa_metadata = (flags land 16) <> 0;				fa_gpu = (flags land 32) <> 0;				fa_direct_blt = (flags land 64) <> 0;			}		| 0x46 when !full_parsing ->			TPlaceObject3 (parse_place_object ch true)		| 0x47 ->			let url = read_string ch in			if IO.read_byte ch <> 1 then assert false;			if IO.read_byte ch <> 0 then assert false;			TImport2 (url, read_count (read_ui16 ch) parse_import ch)		| 0x48 when !full_parsing || !force_as3_parsing ->			TActionScript3 (None , As3parse.parse ch len)		| 0x49 when !full_parsing ->			TFontAlignZones (parse_cid_data ch len)		| 0x4A ->			TCSMSettings (parse_cid_data ch len)		| 0x4B when !full_parsing ->			TFont3 (parse_cid_data ch len)		| 0x4C ->			let i = read_ui16 ch in			let rec loop i =				if i = 0 then					[]				else					let a = read_ui16 ch in					let s = read_string ch in					{						f9_cid = if a = 0 then None else Some a;						f9_classname = s;					} :: loop (i - 1)			in			TF9Classes (loop i)		| 0x4D ->			TMetaData (read_string ch)		| 0x4E ->			let cid = read_ui16 ch in			let rect = read_rect ch in			TScale9 (cid,rect)		(* 0x4F-0x51 invalid *)		| 0x52 when !full_parsing || !force_as3_parsing ->			let id = read_i32 ch in			let frame = read_string ch in			let len = len - (4 + String.length frame + 1) in			TActionScript3 (Some (id,frame), As3parse.parse ch len)		| 0x53 when !full_parsing ->			TShape4 (parse_shape ch len 4)		| 0x54 when !full_parsing ->			TMorphShape2 (parse_morph_shape ch len)		(* 0x55 invalid *)		| 0x56 ->			let scenes = read_count (As3parse.read_int ch) (fun() ->				let offset = As3parse.read_int ch in				let name = read_string ch in				(offset, name)			) () in			let frames = read_count (As3parse.read_int ch) (fun() ->				let f = As3parse.read_int ch in				let name = read_string ch in				(f, name)			) () in			TScenes (scenes,frames)		| 0x57 ->			let cid = read_ui16 ch in			if read_i32 ch <> 0 then assert false;			let rec loop len =				if len > Sys.max_string_length then					let s = nread_string ch Sys.max_string_length in					s :: loop (len - Sys.max_string_length)				else					[nread_string ch len]			in			(match loop (len - 6) with			| [data] -> TBinaryData (cid,data)			| data -> TBigBinaryData (cid,data))		| 0x58 ->			TFontName (parse_cid_data ch len)		(* // 0x59 TStartSound2 *)		| 0x5A ->			let id = read_ui16 ch in			let size = read_i32 ch in			let deblock = read_ui16 ch in			let data = nread_string ch size in			let data, table = extract_jpg_table data in			let alpha = nread_string ch (len - 6 - size) in			TBitsJPEG4 {				bd_id = id;				bd_table = table;				bd_data = data;				bd_alpha = Some alpha;				bd_deblock = Some deblock;			}		| 0x5B ->			TFont4 (parse_cid_data ch len)		| _ ->			(*if !Swf.warnings then Printf.printf "Unknown tag 0x%.2X\n" id;*)			TUnknown (id,nread_string ch len)	) in(*	let len2 = tag_data_length t in	if len <> len2 then error (Printf.sprintf "Datalen mismatch for tag 0x%.2X (%d != %d)" id len len2);*)	{		tid = gen_id();		tdata = t;		textended = extended;	}and parse_tag_list ch =	let rec loop acc =		let h = (try read_ui16 ch with IO.No_more_input -> 0) in		match parse_tag ch h with		| { tdata = TEnd } -> List.rev acc		| t -> loop (t :: acc)	in	loop []let parse ch =	let sign = nread_string ch 3 in	if sign <> "FWS" && sign <> "CWS" then error "Invalid SWF signature";	let ver = read_byte ch in	swf_version := ver;	ignore(read_i32 ch); (* file length *)	let compressed, ch = (if sign = "CWS" then true , inflate ch else false, ch) in	let size = read_rect ch in	let fps = read_ui16 ch in	let frame_count = read_ui16 ch in	let h = {		h_version = ver;		h_size = size;		h_fps = fps;		h_frame_count = frame_count;		h_compressed = compressed;	} in	let data = h , parse_tag_list ch in	if compressed then IO.close_in ch;	data(* ************************************************************************ *)(* WRITING *)let rec tag_id = function	| TEnd -> 0x00	| TShowFrame -> 0x01	| TShape _ -> 0x02	| TRemoveObject _ -> 0x05	| TBitsJPEG _ -> 0x06	| TJPEGTables _ -> 0x08	| TSetBgColor _ -> 0x09	| TFont _ -> 0x0A	| TText _ -> 0x0B	| TDoAction _ -> 0x0C	| TFontInfo _ -> 0x0D	| TSound _ -> 0x0E	| TStartSound _ -> 0x0F	| TBitsLossless _ -> 0x14	| TBitsJPEG2 _ -> 0x15	| TShape2 _ -> 0x16	| TProtect -> 0x18	| TPlaceObject2 _ -> 0x1A	| TRemoveObject2 _ -> 0x1C	| TShape3 _ -> 0x20	| TText2 _ -> 0x21	| TButton2 _ -> 0x22	| TBitsJPEG3 _ -> 0x23	| TBitsLossless2 _ -> 0x24	| TEditText _ -> 0x25	| TClip _ -> 0x27	| TProductInfo _ -> 0x29	| TFrameLabel _ -> 0x2B	| TSoundStreamHead2 _ -> 0x2D	| TMorphShape _ -> 0x2E	| TFont2 _ -> 0x30	| TExport _ -> 0x38	| TImport _ -> 0x39	| TDoInitAction _ -> 0x3B	| TVideoStream _ -> 0x3C	| TVideoFrame _ -> 0x3D	| TFontInfo2 _ -> 0x3E	| TDebugID _ -> 0x3F	| TEnableDebugger2 _ -> 0x40	| TScriptLimits _ -> 0x41	| TFilesAttributes _ -> 0x45	| TPlaceObject3 _ -> 0x46	| TImport2 _ -> 0x47	| TFontAlignZones _ -> 0x49	| TCSMSettings _ -> 0x4A	| TFont3 _ -> 0x4B	| TF9Classes _ -> 0x4C	| TMetaData _ -> 0x4D	| TScale9 _ -> 0x4E	| TActionScript3 (None,_) -> 0x48	| TActionScript3 _ -> 0x52	| TShape4 _ -> 0x53	| TMorphShape2 _ -> 0x54	| TScenes _ -> 0x56	| TBinaryData _ | TBigBinaryData _ -> 0x57	| TFontName _ -> 0x58	| TBitsJPEG4 _ -> 0x5A	| TFont4 _ -> 0x5B	| TUnknown (id,_) -> idlet write_clip_event ch c =	write_event ch c.cle_events;	write_i32 ch (actions_length c.cle_actions + opt_len (const 1) c.cle_key);	opt (write ch) c.cle_key;	write_actions ch c.cle_actionslet write_clip_events ch event_list = 	write_ui16 ch 0;	let all_events = List.fold_left (fun acc c -> acc lor c.cle_events) 0 event_list in	write_event ch all_events;	List.iter (write_clip_event ch) event_list;	write_event ch 0let write_shape_fill_style ch s =	match s with	| SFSSolid c ->		write_byte ch 0x00;		write_rgb ch c	| SFSSolid3 c ->		write_byte ch 0x00;		write_rgba ch c	| SFSLinearGradient (m,g) ->		write_byte ch 0x10;		write_matrix ch m;		write_gradient ch g	| SFSRadialGradient (m,g,None) ->		write_byte ch 0x12;		write_matrix ch m;		write_gradient ch g	| SFSRadialGradient (m,g,Some i) ->		write_byte ch 0x13;		write_matrix ch m;		write_gradient ch g;		write_i16 ch i;	| SFSBitmap b ->		write_byte ch (match b.sfb_repeat , b.sfb_smooth with			| true, false -> 0x40			| false , false -> 0x41			| true , true -> 0x42			| false, true -> 0x43);		write_ui16 ch b.sfb_cid;		write_matrix ch b.sfb_mposlet write_shape_line_style ch l =	write_ui16 ch l.sls_width;	opt (write_ui16 ch) l.sls_flags;	opt (write_ui16 ch) l.sls_miter;	match l.sls_fill with	| None ->		write_color ch l.sls_color;	| Some fill ->		write_shape_fill_style ch filllet write_shape_array ch f sl =	let n = List.length sl in	if n >= 0xFF then begin		write_byte ch 0xFF;		write_ui16 ch n;	end else		write_byte ch n;	List.iter (f ch) sllet write_shape_style_change_record ch b nlbits nfbits s =	let flags = make_flags [flag s.scsr_move; flag s.scsr_fs0; flag s.scsr_fs1; flag s.scsr_ls; flag s.scsr_new_styles] in	write_bits b 6 flags;	opt (fun (n,dx,dy) ->		write_bits b 5 n;		write_bits b n dx;		write_bits b n dy;	) s.scsr_move;	opt (write_bits b ~nbits:!nfbits) s.scsr_fs0;	opt (write_bits b ~nbits:!nfbits) s.scsr_fs1;	opt (write_bits b ~nbits:!nlbits) s.scsr_ls;	match s.scsr_new_styles with	| None -> ()	| Some s ->		flush_bits b;		write_shape_array ch write_shape_fill_style s.sns_fill_styles;		write_shape_array ch write_shape_line_style s.sns_line_styles;		nfbits := s.sns_nfbits;		nlbits := s.sns_nlbits;		write_bits b 4 !nfbits;		write_bits b 4 !nlbitslet write_shape_record ch b nlbits nfbits = function	| SRStyleChange s ->		write_shape_style_change_record ch b nlbits nfbits s	| SRCurvedEdge s ->		write_bits b 2 2;		write_bits b 4 (s.scer_nbits - 2);		write_bits b s.scer_nbits s.scer_cx;		write_bits b s.scer_nbits s.scer_cy;		write_bits b s.scer_nbits s.scer_ax;		write_bits b s.scer_nbits s.scer_ay;	| SRStraightEdge s ->		write_bits b 2 3;		write_bits b 4 (s.sser_nbits - 2);		match s.sser_line with		| None , None -> assert false		| None , Some p		| Some p , None ->			write_bits b 1 0;			write_bits b 1 (if (fst s.sser_line) = None then 1 else 0);			write_bits b s.sser_nbits p;		| Some dx, Some dy ->			write_bits b 1 1;			write_bits b s.sser_nbits dx;			write_bits b s.sser_nbits dylet write_shape_without_style ch s =	(* write_shape_array ch write_shape_fill_style s.sws_fill_styles; *)	(* write_shape_array ch write_shape_line_style s.sws_line_styles; *)	let r = s in (* s.sws_records in *)	let b = output_bits ch in	write_bits b 4 r.srs_nfbits;	write_bits b 4 r.srs_nlbits;	let nlbits = ref r.srs_nlbits in	let nfbits = ref r.srs_nfbits in	List.iter (write_shape_record ch b nlbits nfbits) r.srs_records;	(* write_bits b 6 0; *)	flush_bits blet write_shape_with_style ch s =	write_shape_array ch write_shape_fill_style s.sws_fill_styles;	write_shape_array ch write_shape_line_style s.sws_line_styles;	let r = s.sws_records in	let b = output_bits ch in	write_bits b 4 r.srs_nfbits;	write_bits b 4 r.srs_nlbits;	let nlbits = ref r.srs_nlbits in	let nfbits = ref r.srs_nfbits in	List.iter (write_shape_record ch b nlbits nfbits) r.srs_records;	write_bits b 6 0;	flush_bits blet write_shape ch s =	write_ui16 ch s.sh_id;	write_rect ch s.sh_bounds;	(match s.sh_bounds2 with	| None -> ()	| Some (r,b) ->		write_rect ch r;		write_byte ch b);	write_shape_with_style ch s.sh_stylelet write_bitmap_lossless ch b =	write_ui16 ch b.bll_id;	write_byte ch b.bll_format;	write_ui16 ch b.bll_width;	write_ui16 ch b.bll_height;	nwrite_string ch b.bll_datalet write_morph_shape ch s =	write_ui16 ch s.msh_id;	write_rect ch s.msh_start_bounds;	write_rect ch s.msh_end_bounds;	nwrite_string ch s.msh_datalet write_text_record ch t r =	write_byte ch (make_flags [flag r.txr_dx; flag r.txr_dy; flag r.txr_color; flag r.txr_font; false; false; false; true]);	opt (fun (id,_) -> write_ui16 ch id) r.txr_font;	opt (write_color ch) r.txr_color;	opt (write_i16 ch) r.txr_dx;	opt (write_i16 ch) r.txr_dy;	opt (fun (_,id) -> write_ui16 ch id) r.txr_font;	write_byte ch (List.length r.txr_glyphs);	let bits = output_bits ch in	List.iter (fun g ->		write_bits bits t.txt_ngbits g.txg_index;		write_bits bits t.txt_nabits g.txg_advanced;	) r.txr_glyphs;	flush_bits bitslet write_text ch t =	write_ui16 ch t.txt_id;	write_big_rect ch t.txt_bounds;	write_matrix ch t.txt_matrix;	write_byte ch t.txt_ngbits;	write_byte ch t.txt_nabits;	List.iter (write_text_record ch t) t.txt_records;	write_byte ch 0let write_edit_text_layout ch l =	write_byte ch l.edtl_align;	write_ui16 ch l.edtl_left_margin;	write_ui16 ch l.edtl_right_margin;	write_ui16 ch l.edtl_indent;	write_ui16 ch l.edtl_leadinglet write_edit_text ch t =	write_ui16 ch t.edt_id;	write_rect ch t.edt_bounds;	write_ui16 ch (make_flags [		flag t.edt_font; flag t.edt_maxlen; flag t.edt_color; t.edt_readonly;		t.edt_password; t.edt_multiline; t.edt_wordwrap; flag t.edt_text;		t.edt_outlines; t.edt_html; false; t.edt_border;		t.edt_noselect; flag t.edt_layout; t.edt_autosize; false	]);	opt (fun (id,h) -> write_ui16 ch id; write_ui16 ch h) t.edt_font;	opt (write_rgba ch) t.edt_color;	opt (write_ui16 ch) t.edt_maxlen;	opt (write_edit_text_layout ch) t.edt_layout;	write_string ch t.edt_variable;	opt (write_string ch) t.edt_textlet write_cid_data ch c =	write_ui16 ch c.cd_id;	nwrite_string ch c.cd_datalet write_filter_gradient ch fg =	write_byte ch (List.length fg.fgr_colors);	List.iter (fun (c,_) -> write_rgba ch c) fg.fgr_colors;	List.iter (fun (_,n) -> write_byte ch n) fg.fgr_colors;	nwrite_string ch fg.fgr_datalet write_filter ch = function	| FDropShadow s ->		write_byte ch 0;		nwrite_string ch s	| FBlur s ->		write_byte ch 1;		nwrite_string ch s	| FGlow s ->		write_byte ch 2;		nwrite_string ch s	| FBevel s ->		write_byte ch 3;		nwrite_string ch s	| FGradientGlow fg ->		write_byte ch 4;		write_filter_gradient ch fg	| FAdjustColor s ->		write_byte ch 6;		nwrite_string ch s	| FGradientBevel fg ->		write_byte ch 7;		write_filter_gradient ch fglet write_button_record ch r =	write_byte ch r.btr_flags;	write_ui16 ch r.btr_cid;	write_ui16 ch r.btr_depth;	write_matrix ch r.btr_mpos;	(match r.btr_color with	| None -> ()	| Some c ->		write_cxa ch c);	opt (fun l ->		write_byte ch (List.length l);		List.iter (write_filter ch) l	) r.btr_filters;	(match r.btr_blendmode with	| None -> ()	| Some c ->		write_byte ch c)let rec write_button_actions ch = function	| [] -> assert false	| [a] ->		write_ui16 ch 0;		write_ui16 ch a.bta_flags;		write_actions ch a.bta_actions	| a :: l ->		let size = button_action_length a in		write_ui16 ch size;		write_ui16 ch a.bta_flags;		write_actions ch a.bta_actions;		write_button_actions ch llet write_button2 ch b =	write_ui16 ch b.bt2_id;	write_byte ch (if b.bt2_track_as_menu then 1 else 0);	if b.bt2_actions <> [] then write_ui16 ch (3 + sum button_record_length b.bt2_records) else write_ui16 ch 0;	List.iter (write_button_record ch) b.bt2_records;	write_byte ch 0;	if b.bt2_actions <> [] then write_button_actions ch b.bt2_actionslet write_place_object ch p v3 =	write_byte ch (make_flags [		p.po_move;		flag p.po_cid;		flag p.po_matrix;		flag p.po_color;		flag p.po_ratio;		flag p.po_inst_name;		flag p.po_clip_depth;		flag p.po_events	]);	if v3 then write_byte ch (make_flags [flag p.po_filters; flag p.po_blend; flag p.po_bcache]);	write_ui16 ch p.po_depth;	opt (write_ui16 ch) p.po_cid;	opt (write_matrix ch) p.po_matrix;	opt (write_cxa ch) p.po_color;	opt (write_ui16 ch) p.po_ratio;	opt (write_string ch) p.po_inst_name;	opt (write_ui16 ch) p.po_clip_depth;	opt (write_clip_events ch) p.po_events;	if v3 then begin		opt (fun l ->			write_byte ch (List.length l);			List.iter (write_filter ch) l		) p.po_filters;		opt (write_byte ch) p.po_blend;		opt (write_byte ch) p.po_bcache;	endlet rec write_tag_data ch = function	| TEnd ->		()	| TShowFrame ->		()	| TShape s ->		write_shape ch s	| TRemoveObject r ->		write_ui16 ch r.rmo_id;		write_ui16 ch r.rmo_depth;	| TBitsJPEG b ->		write_ui16 ch b.jpg_id;		nwrite_string ch b.jpg_data	| TJPEGTables tab ->		nwrite_string ch tab	| TSetBgColor c ->		write_rgb ch c	| TFont c ->		write_cid_data ch c	| TText t ->		write_text ch t	| TDoAction acts ->		write_actions ch acts	| TFontInfo c ->		write_cid_data ch c	| TSound s ->		write_ui16 ch s.so_id;		write_byte ch s.so_flags;		write_i32 ch s.so_samples;		nwrite_string ch s.so_data	| TStartSound s ->		write_ui16 ch s.sts_id;		nwrite_string ch s.sts_data	| TBitsLossless b ->		write_bitmap_lossless ch b	| TBitsJPEG2 b ->		write_ui16 ch b.bd_id;		opt (nwrite_string ch) b.bd_table;		nwrite_string ch b.bd_data;	| TShape2 s ->		write_shape ch s	| TProtect ->		()	| TPlaceObject2 p ->		write_place_object ch p false;	| TRemoveObject2 depth ->		write_ui16 ch depth;	| TShape3 s ->		write_shape ch s	| TText2 t ->		write_text ch t	| TButton2 b ->		write_button2 ch b	| TBitsJPEG3 b ->		write_ui16 ch b.bd_id;		write_i32 ch (String.length b.bd_data + opt_len String.length b.bd_table);		opt (nwrite_string ch) b.bd_table;		nwrite_string ch b.bd_data;		opt (nwrite_string ch) b.bd_alpha;	| TBitsLossless2 b ->		write_bitmap_lossless ch b	| TEditText t ->		write_edit_text ch t	| TClip c ->		write_ui16 ch c.c_id;		write_ui16 ch c.c_frame_count;		List.iter (write_tag ch) c.c_tags;		write_tag ch tag_end;	| TProductInfo s ->		nwrite_string ch s	| TFrameLabel (label,id) ->		write_string ch label;		opt (write ch) id;	| TSoundStreamHead2 data ->		nwrite_string ch data	| TMorphShape s ->		write_morph_shape ch s	| TFont2 c ->		write_cid_data ch c	| TExport el ->		write_ui16 ch (List.length el);		List.iter (fun e ->			write_ui16 ch e.exp_id;			write_string ch e.exp_name		) el	| TImport (url,il) ->		write_string ch url;		write_ui16 ch (List.length il);		List.iter (fun i ->			write_ui16 ch i.imp_id;			write_string ch i.imp_name		) il	| TDoInitAction i ->		write_ui16 ch i.dia_id;		write_actions ch i.dia_actions;	| TVideoStream c ->		write_cid_data ch c	| TVideoFrame c ->		write_cid_data ch c	| TFontInfo2 c ->		write_cid_data ch c	| TDebugID s ->		nwrite_string ch s	| TEnableDebugger2 (tag,pass) ->		write_ui16 ch tag;		write_string ch pass	| TScriptLimits (recursion_depth, script_timeout) ->		write_ui16 ch recursion_depth;		write_ui16 ch script_timeout;	| TFilesAttributes f ->		let flags = make_flags [f.fa_network;false;false;f.fa_as3;f.fa_metadata;f.fa_gpu;f.fa_direct_blt] in		write_i32 ch flags	| TPlaceObject3 p ->		write_place_object ch p true;	| TImport2 (url,il) ->		write_string ch url;		write_byte ch 1;		write_byte ch 0;		write_ui16 ch (List.length il);		List.iter (fun i ->			write_ui16 ch i.imp_id;			write_string ch i.imp_name		) il	| TFontAlignZones c ->		write_cid_data ch c	| TCSMSettings c ->		write_cid_data ch c	| TFont3 c ->		write_cid_data ch c	| TF9Classes l ->		write_ui16 ch (List.length l);		List.iter (fun c ->			write_ui16 ch (match c.f9_cid with None -> 0 | Some id -> id);			write_string ch c.f9_classname		) l	| TMetaData meta ->		write_string ch meta	| TScale9 (cid,r) ->		write_ui16 ch cid;		write_rect ch r;	| TActionScript3 (id,a) ->		(match id with		| None -> ()		| Some (id,frame) ->			write_i32 ch id;			write_string ch frame;		);		As3parse.write ch a	| TShape4 s ->		write_shape ch s	| TMorphShape2 m ->		write_morph_shape ch m	| TScenes (sl,fl) ->		As3parse.write_int ch (List.length sl);		List.iter (fun (n,s) ->			As3parse.write_int ch n;			write_string ch s;		) sl;		As3parse.write_int ch (List.length fl);		List.iter (fun (n,s) ->			As3parse.write_int ch n;			write_string ch s;		) fl;	| TBinaryData (id,data) ->		write_ui16 ch id;		write_i32 ch 0;		nwrite_string ch data	| TBigBinaryData (id,data) ->		write_ui16 ch id;		write_i32 ch 0;		List.iter (nwrite_string ch) data	| TFontName c ->		write_cid_data ch c	| TBitsJPEG4 b ->		write_ui16 ch b.bd_id;		write_i32 ch (String.length b.bd_data + opt_len String.length b.bd_table);		opt (write_ui16 ch) b.bd_deblock;		opt (nwrite_string ch) b.bd_table;		nwrite_string ch b.bd_data;		opt (nwrite_string ch) b.bd_alpha;	| TFont4 c ->		write_cid_data ch c	| TUnknown (_,data) ->		nwrite_string ch dataand write_tag ch t =	let id = tag_id t.tdata in	let dlen = tag_data_length t.tdata in	if t.textended || dlen >= 63 then begin		write_ui16 ch ((id lsl 6) lor 63);		write_i32 ch dlen;	end else begin		write_ui16 ch ((id lsl 6) lor dlen);	end;	write_tag_data ch t.tdatalet write ch (h,tags) =	swf_version := h.h_version;	nwrite_string ch (if h.h_compressed then "CWS" else "FWS");	write ch (char_of_int h.h_version);	let rec calc_len = function		| [] -> tag_length tag_end		| t :: l ->			tag_length t + calc_len l	in	let len = calc_len tags in	let len = len + 4 + 4 + rect_length h.h_size + 2 + 2 in	write_i32 ch len;	let ch = (if h.h_compressed then deflate ch else ch) in	write_rect ch h.h_size;	write_ui16 ch h.h_fps;	write_ui16 ch h.h_frame_count;	List.iter (write_tag ch) tags;	write_tag ch tag_end;	if h.h_compressed then IO.close_out ch(* ************************************************************************ *)(* EXTRA *)let scan fid f t =	match t.tdata with	| TEnd	| TShowFrame	| TJPEGTables _	| TSetBgColor _	| TDoAction _	| TActionScript3 _	| TProtect	| TRemoveObject2 _	| TFrameLabel _	| TSoundStreamHead2 _	| TScenes _	| TEnableDebugger2 _	| TMetaData _	| TScriptLimits _	| TDebugID _	| TFilesAttributes _	| TProductInfo _		-> ()	| TF9Classes l ->		List.iter (fun c ->			match c.f9_cid with			| None -> ()			| Some id -> c.f9_cid <- Some (f id)		) l	| TShape s	| TShape2 s	| TShape3 s	| TShape4 s ->		s.sh_id <- fid s.sh_id;		let loop fs =			List.iter (fun s -> match s with				| SFSBitmap b ->					if b.sfb_cid <> 0xFFFF then b.sfb_cid <- f b.sfb_cid;				| _ ->					()			) fs		in		loop s.sh_style.sws_fill_styles;		List.iter (fun s -> match s with			| SRStyleChange { scsr_new_styles = Some s } ->				loop s.sns_fill_styles			| _ ->				()		) s.sh_style.sws_records.srs_records;	| TRemoveObject r ->		r.rmo_id <- f r.rmo_id	| TBitsJPEG b ->		b.jpg_id <- fid b.jpg_id	| TBitsJPEG2 b ->		b.bd_id <- fid b.bd_id	| TText t	| TText2 t ->		t.txt_id <- fid t.txt_id;		List.iter (fun r -> match r.txr_font with None -> () | Some (id,id2) -> r.txr_font <- Some (f id,id2)) t.txt_records	| TEditText t ->		t.edt_id <- fid t.edt_id;		(match t.edt_font with None -> () | Some (id,h) -> t.edt_font <- Some (f id,h))	| TSound s ->		s.so_id <- fid s.so_id	| TStartSound s ->		s.sts_id <- f s.sts_id	| TBitsLossless b	| TBitsLossless2 b ->		b.bll_id <- fid b.bll_id	| TPlaceObject2 p ->		p.po_cid <- (match p.po_cid with None -> None | Some id -> Some (f id))	| TButton2 b ->		b.bt2_id <- fid b.bt2_id;		List.iter (fun r ->			r.btr_cid <- f r.btr_cid		) b.bt2_records;	| TBitsJPEG3 j ->		j.bd_id <- fid j.bd_id	| TClip c ->		c.c_id <- fid c.c_id	| TMorphShape s | TMorphShape2 s ->		s.msh_id <- fid s.msh_id	| TFont c | TFont2 c | TFont3 c | TFont4 c ->		c.cd_id <- fid c.cd_id	| TExport el ->		List.iter (fun e -> e.exp_id <- f e.exp_id) el	| TImport (_,il) | TImport2 (_,il) ->		List.iter (fun i -> i.imp_id <- fid i.imp_id) il	| TDoInitAction a ->		a.dia_id <- f a.dia_id	| TVideoStream c ->		c.cd_id <- fid c.cd_id	| TVideoFrame c ->		c.cd_id <- f c.cd_id	| TPlaceObject3 p ->		p.po_cid <- (match p.po_cid with None -> None | Some id -> Some (f id))	| TCSMSettings c ->		c.cd_id <- f c.cd_id	| TBinaryData (id,data) ->		t.tdata <- TBinaryData (fid id,data)	| TBigBinaryData (id,data) ->		t.tdata <- TBigBinaryData (fid id,data)	| TFontAlignZones c | TFontInfo c | TFontInfo2 c | TFontName c ->		c.cd_id <- f c.cd_id	| TScale9 (id,r) ->		t.tdata <- TScale9 (f id,r)	| TBitsJPEG4 j ->		j.bd_id <- fid j.bd_id	| TUnknown _ ->		()let tag_name = function	| TEnd -> "End"	| TShowFrame -> "ShowFrame"	| TShape _ -> "Shape"	| TRemoveObject _ -> "RemoveObject"	| TBitsJPEG _ -> "BitsJPEG"	| TJPEGTables _ -> "JPGETables"	| TSetBgColor _ -> "SetBgColor"	| TFont _ -> "Font"	| TText _ -> "Text"	| TDoAction _ -> "DoAction"	| TFontInfo _ -> "FontInfo"	| TSound _ -> "Sound"	| TStartSound _ -> "StartSound"	| TBitsLossless _ -> "BitsLossless"	| TBitsJPEG2 _ -> "BitsJPEG2"	| TShape2 _ -> "Shape2"	| TProtect -> "Protect"	| TPlaceObject2 _ -> "PlaceObject2"	| TRemoveObject2 _ -> "RemoveObject2"	| TShape3 _ -> "Shape3"	| TText2 _ -> "Text2"	| TButton2 _ -> "Button2"	| TBitsJPEG3 _ -> "BitsJPEG3"	| TBitsLossless2 _ -> "Lossless2"	| TEditText _ -> "EditText"	| TClip _ -> "Clip"	| TProductInfo _ -> "ProductInfo"	| TFrameLabel _ -> "FrameLabel"	| TSoundStreamHead2 _ -> "SoundStreamHead2"	| TMorphShape _ -> "MorphShape"	| TFont2 _ -> "Font2"	| TExport _ -> "Export"	| TImport _ -> "Import"	| TDoInitAction _ -> "DoInitAction"	| TVideoStream _ -> "VideoStream"	| TVideoFrame _ -> "VideoFrame"	| TFontInfo2 _ -> "FontInfo2"	| TDebugID _ -> "DebugID"	| TEnableDebugger2 _ -> "EnableDebugger2"	| TScriptLimits _ -> "ScriptLimits"	| TFilesAttributes _ -> "FilesAttributes"	| TPlaceObject3 _ -> "PlaceObject3"	| TImport2 _ -> "Import2"	| TFontAlignZones _ -> "FontAlignZones"	| TCSMSettings _ -> "TCSMSettings"	| TFont3 _ -> "Font3"	| TF9Classes _ -> "F9Classes"	| TMetaData _ -> "MetaData"	| TScale9 _ -> "Scale9"	| TActionScript3 _ -> "ActionScript3"	| TShape4 _ -> "Shape4"	| TMorphShape2 _ -> "MorphShape2"	| TScenes _ -> "Scenes"	| TBinaryData _ -> "BinaryData"	| TBigBinaryData _ -> "BigBinaryData"	| TFontName _ -> "FontName"	| TBitsJPEG4 _ -> "BitsJPEG4"	| TFont4 _ -> "Font4"	| TUnknown (n,_) -> Printf.sprintf "Unknown 0x%.2X" nlet init inflate deflate =	Swf.__parser := parse;	Swf.__printer := write;	Swf.__inflate := inflate;	Swf.__deflate := deflate;;;Swf.__parser := parse;Swf.__printer := write
 |