I had the need to load up Flash7 swfs no script in an AS3.0+Flash9 application. Without the ability to edit the swf to say use LocalConnection as other sites suggest, as they are output from a video2swf convertor.
There was some hope of converting byteCode since the file is so simple, and the raw data is the same. I discovered AVM2Loader through ActionScript Classes, which got it from Fladdict who apparently was linking to the file on a snippets site with Trac, and that is/was down or no longer working. So I'm copying it here incase others need to find it.
Results, works but is very limited
While it helps, In testing it's very limited, which is true in general of AVM1Movie + AS3. I wanted to load relatively simple Flash7 files as output by a swf generator that contain PCM audio and no graphics for use with an AS3/Flash9 based UI. Sadly no dice. With or without AVM2Loader, the audio clip still shows up as an AVM1Movie and can be loaded/replayed 2 times before it stops working, despite all loading events being sent. This latter seems like a bug, as no matter what I try once it's loaded it won't play reliably by loading it again, trying to remove it prior gives caller must be child of Display object or something.
AVM2Loader does work with simple graphics, put a tween on stage...they appear as MovieClip in the AVM2 so can be added to the displayList and controlled with play(), stop() etc. Add audio it stops working.
Somehow audio packets throw off the AVM1 to AVM2 translation. In testing it bypasses one of the 'hackA' segment, and the byteHeader is different, but changing it to to match didn't help. I wish I knew more about the swf file format(s). Working in hex is painful for me, feels like I'm starting a tire treads when I should be driving.
Anyway you're mileage might be better, so here's the code.
AVM2Loader.as
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 compressedbytes.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;
}
}
}
}
}
TEST CODE
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();
{ 2 trackbacks }
{ 4 comments… read them below or add one }
It is great man! Thanks!
thanks a lot . what is your msn ? my msn is wenll299@hotmail.com . could you contact me by msn ?
I’m not on msn, and don’t really know more than what I posted on the blog.
great
thanks