/// <summary> /// Initializes a new instance of a SWF with the same defaults as the /// Flash IDE. /// </summary> /// <param name="ctx">An optional object intended solely to give error messages /// some context.</param> /// <param name="generateScripts">True if you want to generate the default /// timeline scripts.</param> public SWF(SWFContext ctx, bool generateScripts) { this.Context = ctx; this.FrameWidth = DefaultFrameWidth; this.FrameHeight = DefaultFrameHeight; this.Fps = DefaultFPS; this.dictionary = new Dictionary <string, ICharacter>(); this.scripts = new List <DoABC>(); this.fonts = new List <SWFFont>(); this.BackgroundColor = defaultBGColour; /* ISSUE 30: This list is read when the swf is written, but we never * add to it. We should add to it on instruction from swiffotron xml * attributes, and also when we infer that a read sprite should be * exported based on its position in the source SWF relative to its first * use. */ this.exportOnFirstFrame = new List <Sprite>(); this.clipClassMap = new Dictionary <AS3ClassDef, Timeline>(); if (generateScripts) { this.GenerateTimelineScripts(); } }
/// <summary> /// Initializes a new instance of a SWF with the same defaults as the /// Flash IDE. /// </summary> /// <param name="ctx">An optional object intended solely to give error messages /// some context.</param> /// <param name="generateScripts">True if you want to generate the default /// timeline scripts.</param> public SWF(SWFContext ctx, bool generateScripts) { this.Context = ctx; this.FrameWidth = DefaultFrameWidth; this.FrameHeight = DefaultFrameHeight; this.Fps = DefaultFPS; this.dictionary = new Dictionary<string, ICharacter>(); this.scripts = new List<DoABC>(); this.fonts = new List<SWFFont>(); this.BackgroundColor = defaultBGColour; /* ISSUE 30: This list is read when the swf is written, but we never * add to it. We should add to it on instruction from swiffotron xml * attributes, and also when we infer that a read sprite should be * exported based on its position in the source SWF relative to its first * use. */ this.exportOnFirstFrame = new List<Sprite>(); this.clipClassMap = new Dictionary<AS3ClassDef, Timeline>(); if (generateScripts) { this.GenerateTimelineScripts(); } }
public void OnLoadAbc(bool lazyInit, SWFContext ctx, string abcName, int doAbcCount, byte[] bytecode) { string abcDir = TestDir + @"\abc\"; Directory.CreateDirectory(abcDir); string name = ctx.Name + "." + abcName + doAbcCount + abcName + ".abc"; using (FileStream fs = new FileStream(abcDir + name, FileMode.Create)) { fs.Write(bytecode, 0, bytecode.Length); } StringBuilder abcReadLog = new StringBuilder(); AbcCode code = new AbcReader().Read(bytecode, abcReadLog); StringBuilder abcd = new StringBuilder(); code.ToStringModelView(0, abcd); byte[] dasmBytes = new ASCIIEncoding().GetBytes(abcd.ToString()); using (FileStream fs = new FileStream(abcDir + name + ".txt", FileMode.Create)) { fs.Write(dasmBytes, 0, dasmBytes.Length); } byte[] abcReadLogBytes = new ASCIIEncoding().GetBytes(abcReadLog.ToString()); using (FileStream fs = new FileStream(abcDir + name + ".abcread.txt", FileMode.Create)) { fs.Write(abcReadLogBytes, 0, abcReadLogBytes.Length); } }
public void OnLoadAbc(bool lazyInit, SWFContext ctx, string abcName, int doAbcCount, byte[] bytecode) { StringBuilder readLog = new StringBuilder(); new AbcReader().Read(bytecode, readLog); using (FileStream modelOut = new FileStream(ctx.Name + ".ABCREAD" + "." + doAbcCount + ".txt", FileMode.Create)) { byte[] ascii = new ASCIIEncoding().GetBytes(readLog.ToString()); modelOut.Write(ascii, 0, ascii.Length); } }
public void OnLoadAbc(bool lazyInit, SWFContext ctx, string abcName, int doAbcCount, byte[] bytecode) { string abcDir = this.TestDir + @"\abc\"; Directory.CreateDirectory(abcDir); string name = ctx.Name + "." + abcName + doAbcCount + abcName + ".abc"; using (FileStream fs = new FileStream(abcDir + name, FileMode.Create)) { fs.Write(bytecode, 0, bytecode.Length); } StringBuilder readLog = new StringBuilder(); AbcCode code = null; try { code = new AbcReader().Read(bytecode, readLog); } catch (Exception e) { readLog.Append(e.Message); throw; } finally { using (FileStream fs = new FileStream(abcDir + name + ".readlog.txt", FileMode.Create)) { byte[] readLogBytes = new ASCIIEncoding().GetBytes(readLog.ToString()); fs.Write(readLogBytes, 0, readLogBytes.Length); } } StringBuilder abcd = new StringBuilder(); code.ToStringModelView(0, abcd); byte[] dasmBytes = new ASCIIEncoding().GetBytes(abcd.ToString()); using (FileStream fs = new FileStream(abcDir + name + ".txt", FileMode.Create)) { fs.Write(dasmBytes, 0, dasmBytes.Length); } }
private void ReadHeader(SWFContext ctx) { int sig = this.sdtr.ReadUI24(); if (sig != SIG_COMPRESSED && sig != SIG_UNCOMPRESSED) { throw new SWFModellerException( SWFModellerError.SWFParsing, @"Not a SWF file", ctx); } bool compressed = sig == SIG_COMPRESSED; this.version = this.sdtr.ReadUI8(); if (this.version < 9) { throw new SWFModellerException( SWFModellerError.SWFParsing, @"Only SWF 9+ is supported (Found " + this.version + ")", ctx); } #if DEBUG this.Log("SWF version = " + this.version); #endif this.fileLen = this.sdtr.ReadUI32(); if (compressed) { this.sdtr.SwitchToDeflateMode(this.fileLen); } this.frameSize = this.sdtr.ReadRect(); this.fps = this.sdtr.ReadFIXED8(); this.frameCount = this.sdtr.ReadUI16(); }
/// <summary> /// Merges some code into this code. /// </summary> /// <param name="abc">The code to merge into this object. Once merged, you should /// discard 'abc'.</param> internal void Merge(DoABC abc, SWFContext ctx) { /* Because we want everything to be object references... */ AbcCode abcCode = abc.Code; /* This is a kludge to force initial parsing of the abc data, if not done already */ AbcCode thisCode = this.Code; abc.Disassemble(); /* This ensures that the code is disassembled into mergable form */ this.Disassemble(); foreach (AS3ClassDef clazz in abc.Code.Classes) { AS3ClassDef classCollision = thisCode.GetClassByQName(clazz.Name.QualifiedName); if (classCollision != null) { throw new SWFModellerException( SWFModellerError.CodeMerge, "Class name collision on " + clazz.Name, ctx.Sentinel("ClassNameCollision")); } thisCode.AddClass(clazz); } }
/// <summary> /// Initializes a new instance of an exception without an error message /// </summary> /// <param name="error">The error code.</param> public SWFModellerException(SWFModellerError error, SWFContext ctx) : base(error.ToString() + "; " + ctx.ToString()) { this.Error = error; this.Sentinel = ctx.ToString(); }
/// <summary> /// Factory method for a new timeline class. /// </summary> /// <param name="abc">The abc code to create the class within.</param> /// <param name="packageName">Name of the fla. You can make this up, since you probably don't have /// a fla.</param> /// <param name="className">Name of the class.</param> /// <returns>A bew timeline class.</returns> private static AS3ClassDef GenerateTimelineClass(AbcCode abc, string qClassName, SWFContext ctx) { int splitPos = qClassName.LastIndexOf('.'); if (splitPos < 0) { throw new SWFModellerException(SWFModellerError.CodeMerge, "A generated timeline class must have a package name.", ctx.Sentinel("TimelineDefaultPackage")); } string packageName = qClassName.Substring(0, splitPos); string className = qClassName.Substring(splitPos + 1); /* Class name: */ Namespace flaNS = abc.CreateNamespace(Namespace.NamespaceKind.Package, packageName); Multiname classMultinameName = abc.CreateMultiname(Multiname.MultinameKind.QName, className, flaNS, null); /* Superclass: */ Namespace nsFlashDisplay = abc.CreateNamespace(Namespace.NamespaceKind.Package, "flash.display"); Multiname mnMovieClip = abc.CreateMultiname(Multiname.MultinameKind.QName, "MovieClip", nsFlashDisplay, null); AS3ClassDef newClass = abc.CreateClass(); newClass.Name = classMultinameName; newClass.Supername = mnMovieClip; Namespace protectedNS = abc.CreateNamespace(Namespace.NamespaceKind.Protected, packageName + ":" + className); newClass.ProtectedNS = protectedNS; newClass.Cinit = abc.CreateMethod(className + "Constructor.abc", 1, 1, 9, 10, /* The above magic numbers come from the numbers generated by IDE versions of this function. * I have no real ideal about how I'd work them out for myself, which would obviously be * more ideal. */ /* AFAICT, this is always generated by the IDE because the abc file format * doesn't allow for classes with no static initialiser. It doesn't seem * to actually do anything. */ abc.Op(Opcode.Mnemonics.GetLocal0), abc.Op(Opcode.Mnemonics.PushScope), abc.Op(Opcode.Mnemonics.ReturnVoid)); newClass.Iinit = abc.CreateMethod(className + "ClassInit.abc", 1, 1, 10, 11, /* The above magic numbers come from the numbers generated by IDE versions of this function. * I have no real ideal about how I'd work them out for myself, which would obviously be * more ideal. */ abc.Op(Opcode.Mnemonics.GetLocal0), abc.Op(Opcode.Mnemonics.PushScope), abc.Op(Opcode.Mnemonics.GetLocal0), abc.Op(Opcode.Mnemonics.ConstructSuper, 0U), abc.Op(Opcode.Mnemonics.ReturnVoid)); return(newClass); }
/// <summary> /// Factory method for a new timeline class. /// </summary> /// <param name="abc">The abc code to create the class within.</param> /// <param name="packageName">Name of the fla. You can make this up, since you probably don't have /// a fla.</param> /// <param name="className">Name of the class.</param> /// <returns>A bew timeline class.</returns> private static AS3ClassDef GenerateTimelineClass(AbcCode abc, string qClassName, SWFContext ctx) { int splitPos = qClassName.LastIndexOf('.'); if (splitPos < 0) { throw new SWFModellerException(SWFModellerError.CodeMerge, "A generated timeline class must have a package name.", ctx.Sentinel("TimelineDefaultPackage")); } string packageName = qClassName.Substring(0, splitPos); string className = qClassName.Substring(splitPos + 1); /* Class name: */ Namespace flaNS = abc.CreateNamespace(Namespace.NamespaceKind.Package, packageName); Multiname classMultinameName = abc.CreateMultiname(Multiname.MultinameKind.QName, className, flaNS, null); /* Superclass: */ Namespace nsFlashDisplay = abc.CreateNamespace(Namespace.NamespaceKind.Package, "flash.display"); Multiname mnMovieClip = abc.CreateMultiname(Multiname.MultinameKind.QName, "MovieClip", nsFlashDisplay, null); AS3ClassDef newClass = abc.CreateClass(); newClass.Name = classMultinameName; newClass.Supername = mnMovieClip; Namespace protectedNS = abc.CreateNamespace(Namespace.NamespaceKind.Protected, packageName + ":" + className); newClass.ProtectedNS = protectedNS; newClass.Cinit = abc.CreateMethod(className + "Constructor.abc", 1, 1, 9, 10, /* The above magic numbers come from the numbers generated by IDE versions of this function. * I have no real ideal about how I'd work them out for myself, which would obviously be * more ideal. */ /* AFAICT, this is always generated by the IDE because the abc file format * doesn't allow for classes with no static initialiser. It doesn't seem * to actually do anything. */ abc.Op(Opcode.Mnemonics.GetLocal0), abc.Op(Opcode.Mnemonics.PushScope), abc.Op(Opcode.Mnemonics.ReturnVoid)); newClass.Iinit = abc.CreateMethod(className + "ClassInit.abc", 1, 1, 10, 11, /* The above magic numbers come from the numbers generated by IDE versions of this function. * I have no real ideal about how I'd work them out for myself, which would obviously be * more ideal. */ abc.Op(Opcode.Mnemonics.GetLocal0), abc.Op(Opcode.Mnemonics.PushScope), abc.Op(Opcode.Mnemonics.GetLocal0), abc.Op(Opcode.Mnemonics.ConstructSuper, 0U), abc.Op(Opcode.Mnemonics.ReturnVoid)); return newClass; }
/// <summary> /// Reads a SWF from the stream. /// </summary> /// <returns>A parsed SWF object</returns> public SWF ReadSWF(SWFContext ctx) { #if DEBUG this.MarkDumpOffset("Start of file"); #endif this.jpegTable = null; this.sceneNotes = new List<FrameNote>(); this.frameLabelNotes = new List<FrameNote>(); this.ReadHeader(ctx); this.fontDict = new Dictionary<int, SWFFont>(); this.frameCursor = 1; bool as3 = false; if (this.version >= 8) { #if DEBUG this.MarkDumpOffset("Start of file attributes tag"); #endif this.ReadFileAttributesTag(out as3); } if (!as3) { throw new SWFModellerException( SWFModellerError.SWFParsing, @"AS2 and under is not supported.", ctx); } this.swf = new SWF(ctx, false); this.swf.FrameWidth = this.frameSize.Width; this.swf.FrameHeight = this.frameSize.Height; this.swf.Fps = this.fps; this.swf.FrameCount = this.frameCount; this.currentTimeline = this.swf; bool hasMore = true; do { hasMore = this.ReadTag(); } while (hasMore); foreach (FrameNote note in this.sceneNotes) { this.swf.GetFrame((int)note.frame).SceneName = note.note; } foreach (FrameNote note in this.frameLabelNotes) { this.swf.GetFrame((int)note.frame).Label = note.note; } foreach (string className in this.LateClassResolutions.Keys) { swf.MapClassnameToClip(className, this.LateClassResolutions[className]); } return this.swf; }
private void ReadHeader(SWFContext ctx) { int sig = this.sdtr.ReadUI24(); if (sig != SIG_COMPRESSED && sig != SIG_UNCOMPRESSED) { throw new SWFModellerException( SWFModellerError.SWFParsing, @"Not a SWF file", ctx); } bool compressed = sig == SIG_COMPRESSED; this.version = this.sdtr.ReadUI8(); if (this.version < 9) { throw new SWFModellerException( SWFModellerError.SWFParsing, @"Only SWF 9+ is supported (Found " + this.version +")", ctx); } #if DEBUG this.Log("SWF version = " + this.version); #endif this.fileLen = this.sdtr.ReadUI32(); if (compressed) { this.sdtr.SwitchToDeflateMode(this.fileLen); } this.frameSize = this.sdtr.ReadRect(); this.fps = this.sdtr.ReadFIXED8(); this.frameCount = this.sdtr.ReadUI16(); }
/// <summary> /// Reads a SWF from the stream. /// </summary> /// <returns>A parsed SWF object</returns> public SWF ReadSWF(SWFContext ctx) { #if DEBUG this.MarkDumpOffset("Start of file"); #endif this.jpegTable = null; this.sceneNotes = new List <FrameNote>(); this.frameLabelNotes = new List <FrameNote>(); this.ReadHeader(ctx); this.fontDict = new Dictionary <int, SWFFont>(); this.frameCursor = 1; bool as3 = false; if (this.version >= 8) { #if DEBUG this.MarkDumpOffset("Start of file attributes tag"); #endif this.ReadFileAttributesTag(out as3); } if (!as3) { throw new SWFModellerException( SWFModellerError.SWFParsing, @"AS2 and under is not supported.", ctx); } this.swf = new SWF(ctx, false); this.swf.FrameWidth = this.frameSize.Width; this.swf.FrameHeight = this.frameSize.Height; this.swf.Fps = this.fps; this.swf.FrameCount = this.frameCount; this.currentTimeline = this.swf; bool hasMore = true; do { hasMore = this.ReadTag(); }while (hasMore); foreach (FrameNote note in this.sceneNotes) { this.swf.GetFrame((int)note.frame).SceneName = note.note; } foreach (FrameNote note in this.frameLabelNotes) { this.swf.GetFrame((int)note.frame).Label = note.note; } foreach (string className in this.LateClassResolutions.Keys) { swf.MapClassnameToClip(className, this.LateClassResolutions[className]); } return(this.swf); }