ActionScript 2.0 기반으로 만들어진 swf는 AVM1이며 ActionScript 3.0기반에서 작성된 것 swf는 AVM2이다. AVM2와 AVM1 간에 스크립트 통신이 직접적으로 진행되지 않고 LocalConnection만으로만 가능하다.

 

여기서 소개하는 AVM2Loader는 AVM1, AVM2 기반의 SWF를 모두 AVM2의 형태로 로드시켜 줌으로써 해당 SWF간 스크립트 통신이 가능하게 하는데 목적이 있다. 구현방법은 flash.display.Loader 클래스를 확장해 로드된 컨텐츠가 AVM1인 경우는 AVM2로 변경해준다. 정확한 의미는 본인도 잘 모른다. 시간이 허락한다면 분석해보려고 한다.

 

소개하는 자료는 TroyWorks Blog에 나온 자료임을 밝혀둔다. 직접 테스트는 안해봤다. ^^ 아래코드는 AVM2Loader이다.

package
{
	import flash.display.Loader;
	import flash.events.*;
	import flash.net.*;
	import flash.system.LoaderContext;
	import flash.utils.ByteArray;
	import flash.utils.Endian;

	/**
	 * Loads both of AVM1 and AVM2 swf as AVM2.
	 */
	public class AVM2Loader extends Loader
	{
		private var _urlLoader:URLLoader;
		private var _context:LoaderContext;

		/**
		 * loads both of AVM1 and AVM2 movie as AVM2 movie.
		 */
		override public function load(request:URLRequest,context:LoaderContext=null):void
		{
			_context=context;

			_urlLoader=new URLLoader ;
			_urlLoader.dataFormat=URLLoaderDataFormat.BINARY;
			_urlLoader.addEventListener(Event.COMPLETE,_binaryLoaded,false,0,true);
			_urlLoader.addEventListener(IOErrorEvent.IO_ERROR,_transferEvent,false,0,true);
			_urlLoader.addEventListener(ProgressEvent.PROGRESS,_transferEvent,false,0,true);
			_urlLoader.addEventListener(Event.OPEN,_transferEvent,false,0,true);
			_urlLoader.addEventListener(HTTPStatusEvent.HTTP_STATUS,_transferEvent,false,0,true);
			_urlLoader.addEventListener(SecurityErrorEvent.SECURITY_ERROR,_transferEvent,false,0,true);
			_urlLoader.load(request);
		}

		private function _binaryLoaded(e:Event):void
		{
			loadBytes(ByteArray(_urlLoader.data),_context);
			_urlLoader=null;
		}

		private function _transferEvent(e:Event):void
		{
			dispatchEvent(e);
		}

		/**
		 * loads both of AVM1 and AVM2 movie as AVM2 movie.
		 */
		override public function loadBytes(bytes:ByteArray,context:LoaderContext=null):void
		{
			//uncompress if compressed
			bytes.endian=Endian.LITTLE_ENDIAN;
			trace("loadBytes" + bytes[0] );
			if (bytes[0] == 0x43) {
				//trace(" hackA");
				//many thanks for be-interactive.org
				var compressedBytes:ByteArray=new ByteArray() ;
				compressedBytes.writeBytes(bytes,8);
				compressedBytes.uncompress();

				bytes.length=8;
				bytes.position=8;
				bytes.writeBytes(compressedBytes);
				compressedBytes.length=0;

				//flag uncompressed
				bytes[0]=0x46;
			}
			hackBytes(bytes);
			super.loadBytes(bytes,context);
		}

		/**
		 * if bytes are AVM1 movie, hack it!
		 */
		private function hackBytes(bytes:ByteArray):void
		{
			//trace(" hackB");
			if (bytes[4] < 0x09)
			{
				trace("hack 9");
				bytes[4]=0x09;
			}

			//trace(" hackC");
			//dirty dirty
			var imax:int=Math.min(bytes.length,100);
			for (var i:int=23; i < imax; i++)
			{
				if (bytes[i - 2] == 0x44 && bytes[i - 1] == 0x11)
				{
					bytes[i]=bytes[i] | 0x08;
					return;
				}
			}
		}
	}
}
아래는 AVM2Loader 테스트 소스이다.
import flash.display.DisplayObject;
import flash.display.Loader;
import flash.display.LoaderInfo;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.net.URLLoader;
import flash.net.URLLoaderDataFormat;
import flash.net.URLRequest;
import flash.utils.ByteArray;
import flash.display.SimpleButton;
import AVM2Loader;

var avm1:AVM1Movie;

function testAudio(e:Event = null):void
{
	trace("testAudio");

	//var request:URLRequest = new URLRequest("video.swf");
	var request:URLRequest = new URLRequest("Flash8Movie.swf");
	var ldr:Loader;
	if (true)
	{
		trace("start AVM2Loader");
		ldr = new AVM2Loader();
	}
	else
	{
		ldr = new Loader();
	}

	ldr.contentLoaderInfo.addEventListener(Event.COMPLETE, _onLoaderComplete);
	ldr.load(request);
}

function _onLoaderComplete(event:Event):void
{
	trace(" _onLoaderComplete");
	var info:LoaderInfo = event.target as LoaderInfo;
	trace(" _onLoaderComplete " + info.content);

	if (info.content is AVM1Movie)
	{
		avm1 = AVM1Movie(info.content);
	}
	else
	{
		addChild(info.content);
		MovieClip(info.content).stop();
		var dO:DisplayObject = DisplayObject(info.content);
	}
}

stage.addEventListener(MouseEvent.CLICK, testAudio);
testAudio();
 
관련글

 

+ Recent posts