From c8951d9522c33b16711b2275b34c757ba5388ac2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=C5=99=C3=ADk?= Date: Sun, 31 Jul 2016 15:15:36 +0200 Subject: [PATCH 01/23] Import/Usage parsing separated to one class Class for generating linker reports from SWF files (similar to -link-report option in Flex) Generating linker report from commandline --- .../flash/abc/types/traits/Trait.java | 172 +------------- .../flash/abc/types/traits/TraitClass.java | 11 +- .../flash/abc/types/traits/TraitFunction.java | 3 +- .../types/traits/TraitMethodGetterSetter.java | 3 +- .../abc/types/traits/TraitSlotConst.java | 3 +- .../exporters/script/ImportsUsagesParser.java | 211 ++++++++++++++++++ .../exporters/script/LinkReportExporter.java | 206 +++++++++++++++++ .../console/CommandLineArgumentParser.java | 56 ++++- 8 files changed, 486 insertions(+), 179 deletions(-) create mode 100644 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/script/ImportsUsagesParser.java create mode 100644 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/script/LinkReportExporter.java diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/Trait.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/Trait.java index c161303b6..35b66c090 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/Trait.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/Trait.java @@ -42,6 +42,7 @@ import com.jpexs.decompiler.flash.abc.types.NamespaceSet; import com.jpexs.decompiler.flash.abc.types.ScriptInfo; import com.jpexs.decompiler.flash.configuration.Configuration; import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode; +import com.jpexs.decompiler.flash.exporters.script.ImportsUsagesParser; import com.jpexs.decompiler.flash.helpers.GraphTextWriter; import com.jpexs.decompiler.flash.helpers.NulWriter; import com.jpexs.decompiler.flash.tags.ABCContainerTag; @@ -169,117 +170,6 @@ public abstract class Trait implements Cloneable, Serializable { return ret; } - protected void parseImportsUsagesFromMultiname(String ignoredCustom, ABC abc, List imports, List uses, Multiname m, DottedChain ignorePackage, List fullyQualifiedNames) { - if (m != null) { - if (m.kind == Multiname.TYPENAME) { - if (m.qname_index != 0) { - parseImportsUsagesFromMultiname(ignoredCustom, abc, imports, uses, abc.constants.getMultiname(m.qname_index), ignorePackage, fullyQualifiedNames); - } - for (Integer i : m.params) { - if (i != 0) { - parseImportsUsagesFromMultiname(ignoredCustom, abc, imports, uses, abc.constants.getMultiname(i), ignorePackage, fullyQualifiedNames); - } - } - return; - } - Namespace ns = m.getNamespace(abc.constants); - String name = m.getName(abc.constants, fullyQualifiedNames, true); - NamespaceSet nss = m.getNamespaceSet(abc.constants); - if (ns != null) { - parseImportsUsagesFromNS(ignoredCustom, abc, imports, uses, m.namespace_index, ignorePackage, name); - } - if (nss != null) { - for (int n : nss.namespaces) { - parseImportsUsagesFromNS(ignoredCustom, abc, imports, uses, n, ignorePackage, nss.namespaces.length > 1 ? "" : name); - } - } - } - } - - private boolean parseUsagesFromNS(String ignoredCustom, ABC abc, List imports, List uses, int namespace_index, DottedChain ignorePackage, String name) { - Namespace ns = abc.constants.getNamespace(namespace_index); - - if (ns.kind == Namespace.KIND_NAMESPACE) { - String nsVal = ns.getName(abc.constants).toRawString(); - for (ABCContainerTag abcTag : abc.getAbcTags()) { - DottedChain nsimport = abcTag.getABC().nsValueToName(nsVal); - if (nsimport.equals(AVM2Deobfuscation.BUILTIN)) { - return true; //handled, but import/use not added - } - if (!nsimport.isEmpty()) { - - if (!nsimport.getWithoutLast().equals(ignorePackage) && !imports.contains(nsimport)) { - imports.add(nsimport); - } - if (ignoredCustom != null && nsVal.equals(ignoredCustom)) { - return true; - } - if (!uses.contains(nsimport.getLast())) { - uses.add(nsimport.getLast()); - } - return true; - } - } - } - return false; - } - - protected void parseImportsUsagesFromNS(String ignoredCustom, ABC abc, List imports, List uses, int namespace_index, DottedChain ignorePackage, String name) { - Namespace ns = abc.constants.getNamespace(namespace_index); - if (name.isEmpty()) { - name = "*"; - } - DottedChain newimport = ns.getName(abc.constants); - - if (parseUsagesFromNS(ignoredCustom, abc, imports, uses, namespace_index, ignorePackage, name)) { - return; - } else if ((ns.kind != Namespace.KIND_PACKAGE) && (ns.kind != Namespace.KIND_PACKAGE_INTERNAL)) { - return; - } - newimport = newimport.add(name); - if (!imports.contains(newimport)) { - DottedChain pkg = newimport.getWithoutLast(); //.substring(0, newimport.lastIndexOf('.')); - if (pkg.equals(InitVectorAVM2Item.VECTOR_PACKAGE)) { //special case - is imported always - return; - } - if (!pkg.equals(ignorePackage)) { - imports.add(newimport); - } - } - //} - } - - protected void parseUsagesFromMultiname(String ignoredCustom, ABC abc, List imports, List uses, Multiname m, DottedChain ignorePackage, List fullyQualifiedNames) { - if (m != null) { - if (m.kind == Multiname.TYPENAME) { - if (m.qname_index != 0) { - parseUsagesFromMultiname(ignoredCustom, abc, imports, uses, abc.constants.getMultiname(m.qname_index), ignorePackage, fullyQualifiedNames); - } - for (Integer i : m.params) { - if (i != 0) { - parseUsagesFromMultiname(ignoredCustom, abc, imports, uses, abc.constants.getMultiname(i), ignorePackage, fullyQualifiedNames); - } - } - return; - } - Namespace ns = m.getNamespace(abc.constants); - String name = m.getName(abc.constants, fullyQualifiedNames, false); - NamespaceSet nss = m.getNamespaceSet(abc.constants); - if (ns != null) { - parseUsagesFromNS(ignoredCustom, abc, imports, uses, m.namespace_index, ignorePackage, name); - } - if (nss != null) { - if (nss.namespaces.length == 1) { - parseUsagesFromNS(ignoredCustom, abc, imports, uses, nss.namespaces[0], ignorePackage, name); - } else { - for (int n : nss.namespaces) { - parseUsagesFromNS(ignoredCustom, abc, imports, uses, n, ignorePackage, ""); - } - } - } - } - } - protected DottedChain getPackage(ABC abc) { return getName(abc).getNamespace(abc.constants).getName(abc.constants); } @@ -291,7 +181,7 @@ public abstract class Trait implements Cloneable, Serializable { ignoredCustom = n.getName(abc.constants).toRawString(); } } - parseUsagesFromMultiname(ignoredCustom, abc, imports, uses, getName(abc), ignorePackage, fullyQualifiedNames); + ImportsUsagesParser.parseUsagesFromMultiname(ignoredCustom, abc, imports, uses, getName(abc), ignorePackage, fullyQualifiedNames); } private static final String[] builtInClasses = {"ArgumentError", "arguments", "Array", "Boolean", "Class", "Date", "DefinitionError", "Error", "EvalError", "Function", "int", "JSON", "Math", "Namespace", "Number", "Object", "QName", "RangeError", "ReferenceError", "RegExp", "SecurityError", "String", "SyntaxError", "TypeError", "uint", "URIError", "VerifyError", "XML", "XMLList"}; @@ -375,64 +265,6 @@ public abstract class Trait implements Cloneable, Serializable { } } - protected void parseImportsUsagesFromMethodInfo(String ignoredCustom, ABC abc, int method_index, List imports, List uses, DottedChain ignorePackage, List fullyQualifiedNames, List visitedMethods) { - if ((method_index < 0) || (method_index >= abc.method_info.size())) { - return; - } - visitedMethods.add(method_index); - if (abc.method_info.get(method_index).ret_type != 0) { - parseImportsUsagesFromMultiname(ignoredCustom, abc, imports, uses, abc.constants.getMultiname(abc.method_info.get(method_index).ret_type), ignorePackage, fullyQualifiedNames); - } - for (int t : abc.method_info.get(method_index).param_types) { - if (t != 0) { - parseImportsUsagesFromMultiname(ignoredCustom, abc, imports, uses, abc.constants.getMultiname(t), ignorePackage, fullyQualifiedNames); - } - } - MethodBody body = abc.findBody(method_index); - if (body != null) { - body.traits.getImportsUsages(ignoredCustom, abc, imports, uses, ignorePackage, fullyQualifiedNames); - for (ABCException ex : body.exceptions) { - parseImportsUsagesFromMultiname(ignoredCustom, abc, imports, uses, abc.constants.getMultiname(ex.type_index), ignorePackage, fullyQualifiedNames); - } - for (AVM2Instruction ins : body.getCode().code) { - if (ins.definition instanceof AlchemyTypeIns) { - DottedChain nimport = AlchemyTypeIns.ALCHEMY_PACKAGE.add(ins.definition.instructionName); - if (!imports.contains(nimport)) { - imports.add(nimport); - } - } - if (ins.definition instanceof NewFunctionIns) { - if (ins.operands[0] != method_index) { - if (!visitedMethods.contains(ins.operands[0])) { - parseImportsUsagesFromMethodInfo(ignoredCustom, abc, ins.operands[0], imports, uses, ignorePackage, fullyQualifiedNames, visitedMethods); - } - } - } - if ((ins.definition instanceof FindPropertyStrictIns) - || (ins.definition instanceof FindPropertyIns) - || (ins.definition instanceof GetLexIns) - || (ins.definition instanceof CoerceIns) - || (ins.definition instanceof AsTypeIns)) { - int m = ins.operands[0]; - if (m != 0) { - if (m < abc.constants.getMultinameCount()) { - parseImportsUsagesFromMultiname(ignoredCustom, abc, imports, uses, abc.constants.getMultiname(m), ignorePackage, fullyQualifiedNames); - } - } - } else { - for (int k = 0; k < ins.definition.operands.length; k++) { - if (ins.definition.operands[k] == AVM2Code.DAT_MULTINAME_INDEX) { - int multinameIndex = ins.operands[k]; - if (multinameIndex < abc.constants.getMultinameCount()) { - parseUsagesFromMultiname(ignoredCustom, abc, imports, uses, abc.constants.getMultiname(multinameIndex), ignorePackage, fullyQualifiedNames); - } - } - } - } - } - } - } - public final GraphTextWriter getMetaData(Trait parent, ConvertData convertData, ABC abc, GraphTextWriter writer) { List>> md = getMetaDataTable(parent, convertData, abc); for (Entry> en : md) { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitClass.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitClass.java index d21b8a12d..d92552773 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitClass.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitClass.java @@ -25,6 +25,7 @@ import com.jpexs.decompiler.flash.abc.types.MethodBody; import com.jpexs.decompiler.flash.abc.types.Multiname; import com.jpexs.decompiler.flash.abc.types.Namespace; import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode; +import com.jpexs.decompiler.flash.exporters.script.ImportsUsagesParser; import com.jpexs.decompiler.flash.helpers.GraphTextWriter; import com.jpexs.decompiler.flash.helpers.NulWriter; import com.jpexs.decompiler.graph.DottedChain; @@ -84,26 +85,26 @@ public class TraitClass extends Trait implements TraitWithSlot { InstanceInfo instanceInfo = abc.instance_info.get(class_info); DottedChain packageName = instanceInfo.getName(abc.constants).getNamespace(abc.constants).getName(abc.constants); //assume not null name - parseImportsUsagesFromMultiname(customNs, abc, imports, uses, abc.constants.getMultiname(instanceInfo.name_index), packageName, fullyQualifiedNames); + ImportsUsagesParser.parseImportsUsagesFromMultiname(customNs, abc, imports, uses, abc.constants.getMultiname(instanceInfo.name_index), packageName, fullyQualifiedNames); if (instanceInfo.super_index > 0) { - parseImportsUsagesFromMultiname(customNs, abc, imports, uses, abc.constants.getMultiname(instanceInfo.super_index), packageName, fullyQualifiedNames); + ImportsUsagesParser.parseImportsUsagesFromMultiname(customNs, abc, imports, uses, abc.constants.getMultiname(instanceInfo.super_index), packageName, fullyQualifiedNames); } for (int i : instanceInfo.interfaces) { - parseImportsUsagesFromMultiname(customNs, abc, imports, uses, abc.constants.getMultiname(i), packageName, fullyQualifiedNames); + ImportsUsagesParser.parseImportsUsagesFromMultiname(customNs, abc, imports, uses, abc.constants.getMultiname(i), packageName, fullyQualifiedNames); } //static classInfo.static_traits.getImportsUsages(customNs, abc, imports, uses, packageName, fullyQualifiedNames); //static initializer - parseImportsUsagesFromMethodInfo(customNs, abc, classInfo.cinit_index, imports, uses, packageName, fullyQualifiedNames, new ArrayList<>()); + ImportsUsagesParser.parseImportsUsagesFromMethodInfo(customNs, abc, classInfo.cinit_index, imports, uses, packageName, fullyQualifiedNames, new ArrayList<>()); //instance instanceInfo.instance_traits.getImportsUsages(customNs, abc, imports, uses, packageName, fullyQualifiedNames); //instance initializer - parseImportsUsagesFromMethodInfo(customNs, abc, instanceInfo.iinit_index, imports, uses, packageName, fullyQualifiedNames, new ArrayList<>()); + ImportsUsagesParser.parseImportsUsagesFromMethodInfo(customNs, abc, instanceInfo.iinit_index, imports, uses, packageName, fullyQualifiedNames, new ArrayList<>()); } @Override diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitFunction.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitFunction.java index 887971236..b18f5f1f1 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitFunction.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitFunction.java @@ -20,6 +20,7 @@ import com.jpexs.decompiler.flash.abc.ABC; import com.jpexs.decompiler.flash.abc.types.ConvertData; import com.jpexs.decompiler.flash.abc.types.MethodBody; import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode; +import com.jpexs.decompiler.flash.exporters.script.ImportsUsagesParser; import com.jpexs.decompiler.flash.helpers.GraphTextWriter; import com.jpexs.decompiler.flash.helpers.NulWriter; import com.jpexs.decompiler.flash.helpers.hilight.HighlightSpecialType; @@ -130,7 +131,7 @@ public class TraitFunction extends Trait implements TraitWithSlot { super.getImportsUsages(customNs, abc, imports, uses, ignorePackage, fullyQualifiedNames); //if (method_info != 0) { - parseImportsUsagesFromMethodInfo(customNs, abc, method_info, imports, uses, ignorePackage, fullyQualifiedNames, new ArrayList<>()); + ImportsUsagesParser.parseImportsUsagesFromMethodInfo(customNs, abc, method_info, imports, uses, ignorePackage, fullyQualifiedNames, new ArrayList<>()); } } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitMethodGetterSetter.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitMethodGetterSetter.java index cc836a0ae..7487d22f2 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitMethodGetterSetter.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitMethodGetterSetter.java @@ -23,6 +23,7 @@ import com.jpexs.decompiler.flash.abc.types.MethodInfo; import com.jpexs.decompiler.flash.abc.types.Namespace; import com.jpexs.decompiler.flash.configuration.Configuration; import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode; +import com.jpexs.decompiler.flash.exporters.script.ImportsUsagesParser; import com.jpexs.decompiler.flash.helpers.GraphTextWriter; import com.jpexs.decompiler.flash.helpers.NulWriter; import com.jpexs.decompiler.flash.helpers.hilight.HighlightSpecialType; @@ -72,7 +73,7 @@ public class TraitMethodGetterSetter extends Trait { } //if (method_info != 0) { - parseImportsUsagesFromMethodInfo(customNs, abc, method_info, imports, uses, ignorePackage, fullyQualifiedNames, new ArrayList<>()); + ImportsUsagesParser.parseImportsUsagesFromMethodInfo(customNs, abc, method_info, imports, uses, ignorePackage, fullyQualifiedNames, new ArrayList<>()); } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitSlotConst.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitSlotConst.java index 6971590a8..d46ec1c8b 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitSlotConst.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitSlotConst.java @@ -26,6 +26,7 @@ import com.jpexs.decompiler.flash.abc.types.Namespace; import com.jpexs.decompiler.flash.abc.types.ValueKind; import com.jpexs.decompiler.flash.configuration.Configuration; import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode; +import com.jpexs.decompiler.flash.exporters.script.ImportsUsagesParser; import com.jpexs.decompiler.flash.helpers.GraphTextWriter; import com.jpexs.decompiler.flash.helpers.NulWriter; import com.jpexs.decompiler.flash.helpers.hilight.HighlightSpecialType; @@ -201,7 +202,7 @@ public class TraitSlotConst extends Trait implements TraitWithSlot { ignorePackage = getPackage(abc); } super.getImportsUsages(customNs, abc, imports, uses, ignorePackage, fullyQualifiedNames); - parseImportsUsagesFromMultiname(customNs, abc, imports, uses, abc.constants.getMultiname(type_index), getPackage(abc), fullyQualifiedNames); + ImportsUsagesParser.parseImportsUsagesFromMultiname(customNs, abc, imports, uses, abc.constants.getMultiname(type_index), getPackage(abc), fullyQualifiedNames); } @Override diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/script/ImportsUsagesParser.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/script/ImportsUsagesParser.java new file mode 100644 index 000000000..79637ff6d --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/script/ImportsUsagesParser.java @@ -0,0 +1,211 @@ +/* + * Copyright (C) 2010-2016 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash.exporters.script; + +import com.jpexs.decompiler.flash.abc.ABC; +import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; +import com.jpexs.decompiler.flash.abc.avm2.AVM2Deobfuscation; +import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; +import com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy.AlchemyTypeIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.construction.NewFunctionIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.other.FindPropertyIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.other.FindPropertyStrictIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.other.GetLexIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.types.AsTypeIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.types.CoerceIns; +import com.jpexs.decompiler.flash.abc.avm2.model.InitVectorAVM2Item; +import com.jpexs.decompiler.flash.abc.types.ABCException; +import com.jpexs.decompiler.flash.abc.types.MethodBody; +import com.jpexs.decompiler.flash.abc.types.Multiname; +import com.jpexs.decompiler.flash.abc.types.Namespace; +import com.jpexs.decompiler.flash.abc.types.NamespaceSet; +import com.jpexs.decompiler.flash.tags.ABCContainerTag; +import com.jpexs.decompiler.graph.DottedChain; +import java.util.List; + +public class ImportsUsagesParser { + + public static void parseImportsUsagesFromNS(String ignoredCustom, ABC abc, List imports, List uses, int namespace_index, DottedChain ignorePackage, String name) { + Namespace ns = abc.constants.getNamespace(namespace_index); + if (name.isEmpty()) { + name = "*"; + } + DottedChain newimport = ns.getName(abc.constants); + + if (parseUsagesFromNS(ignoredCustom, abc, imports, uses, namespace_index, ignorePackage, name)) { + return; + } else if ((ns.kind != Namespace.KIND_PACKAGE) && (ns.kind != Namespace.KIND_PACKAGE_INTERNAL)) { + return; + } + newimport = newimport.add(name); + if (!imports.contains(newimport)) { + DottedChain pkg = newimport.getWithoutLast(); //.substring(0, newimport.lastIndexOf('.')); + if (pkg.equals(InitVectorAVM2Item.VECTOR_PACKAGE)) { //special case - is imported always + return; + } + if (!pkg.equals(ignorePackage)) { + imports.add(newimport); + } + } + //} + } + + public static void parseImportsUsagesFromMultiname(String ignoredCustom, ABC abc, List imports, List uses, Multiname m, DottedChain ignorePackage, List fullyQualifiedNames) { + if (m != null) { + if (m.kind == Multiname.TYPENAME) { + if (m.qname_index != 0) { + parseImportsUsagesFromMultiname(ignoredCustom, abc, imports, uses, abc.constants.getMultiname(m.qname_index), ignorePackage, fullyQualifiedNames); + } + for (Integer i : m.params) { + if (i != 0) { + parseImportsUsagesFromMultiname(ignoredCustom, abc, imports, uses, abc.constants.getMultiname(i), ignorePackage, fullyQualifiedNames); + } + } + return; + } + Namespace ns = m.getNamespace(abc.constants); + String name = m.getName(abc.constants, fullyQualifiedNames, true); + NamespaceSet nss = m.getNamespaceSet(abc.constants); + if (ns != null) { + parseImportsUsagesFromNS(ignoredCustom, abc, imports, uses, m.namespace_index, ignorePackage, name); + } + if (nss != null) { + for (int n : nss.namespaces) { + parseImportsUsagesFromNS(ignoredCustom, abc, imports, uses, n, ignorePackage, nss.namespaces.length > 1 ? "" : name); + } + } + } + } + + public static void parseImportsUsagesFromMethodInfo(String ignoredCustom, ABC abc, int method_index, List imports, List uses, DottedChain ignorePackage, List fullyQualifiedNames, List visitedMethods) { + if ((method_index < 0) || (method_index >= abc.method_info.size())) { + return; + } + visitedMethods.add(method_index); + if (abc.method_info.get(method_index).ret_type != 0) { + parseImportsUsagesFromMultiname(ignoredCustom, abc, imports, uses, abc.constants.getMultiname(abc.method_info.get(method_index).ret_type), ignorePackage, fullyQualifiedNames); + } + for (int t : abc.method_info.get(method_index).param_types) { + if (t != 0) { + parseImportsUsagesFromMultiname(ignoredCustom, abc, imports, uses, abc.constants.getMultiname(t), ignorePackage, fullyQualifiedNames); + } + } + MethodBody body = abc.findBody(method_index); + if (body != null) { + body.traits.getImportsUsages(ignoredCustom, abc, imports, uses, ignorePackage, fullyQualifiedNames); + for (ABCException ex : body.exceptions) { + parseImportsUsagesFromMultiname(ignoredCustom, abc, imports, uses, abc.constants.getMultiname(ex.type_index), ignorePackage, fullyQualifiedNames); + } + for (AVM2Instruction ins : body.getCode().code) { + if (ins.definition instanceof AlchemyTypeIns) { + DottedChain nimport = AlchemyTypeIns.ALCHEMY_PACKAGE.add(ins.definition.instructionName); + if (!imports.contains(nimport)) { + imports.add(nimport); + } + } + if (ins.definition instanceof NewFunctionIns) { + if (ins.operands[0] != method_index) { + if (!visitedMethods.contains(ins.operands[0])) { + parseImportsUsagesFromMethodInfo(ignoredCustom, abc, ins.operands[0], imports, uses, ignorePackage, fullyQualifiedNames, visitedMethods); + } + } + } + if ((ins.definition instanceof FindPropertyStrictIns) + || (ins.definition instanceof FindPropertyIns) + || (ins.definition instanceof GetLexIns) + || (ins.definition instanceof CoerceIns) + || (ins.definition instanceof AsTypeIns)) { + int m = ins.operands[0]; + if (m != 0) { + if (m < abc.constants.getMultinameCount()) { + parseImportsUsagesFromMultiname(ignoredCustom, abc, imports, uses, abc.constants.getMultiname(m), ignorePackage, fullyQualifiedNames); + } + } + } else { + for (int k = 0; k < ins.definition.operands.length; k++) { + if (ins.definition.operands[k] == AVM2Code.DAT_MULTINAME_INDEX) { + int multinameIndex = ins.operands[k]; + if (multinameIndex < abc.constants.getMultinameCount()) { + parseUsagesFromMultiname(ignoredCustom, abc, imports, uses, abc.constants.getMultiname(multinameIndex), ignorePackage, fullyQualifiedNames); + } + } + } + } + } + } + } + + public static void parseUsagesFromMultiname(String ignoredCustom, ABC abc, List imports, List uses, Multiname m, DottedChain ignorePackage, List fullyQualifiedNames) { + if (m != null) { + if (m.kind == Multiname.TYPENAME) { + if (m.qname_index != 0) { + parseUsagesFromMultiname(ignoredCustom, abc, imports, uses, abc.constants.getMultiname(m.qname_index), ignorePackage, fullyQualifiedNames); + } + for (Integer i : m.params) { + if (i != 0) { + parseUsagesFromMultiname(ignoredCustom, abc, imports, uses, abc.constants.getMultiname(i), ignorePackage, fullyQualifiedNames); + } + } + return; + } + Namespace ns = m.getNamespace(abc.constants); + String name = m.getName(abc.constants, fullyQualifiedNames, false); + NamespaceSet nss = m.getNamespaceSet(abc.constants); + if (ns != null) { + parseUsagesFromNS(ignoredCustom, abc, imports, uses, m.namespace_index, ignorePackage, name); + } + if (nss != null) { + if (nss.namespaces.length == 1) { + parseUsagesFromNS(ignoredCustom, abc, imports, uses, nss.namespaces[0], ignorePackage, name); + } else { + for (int n : nss.namespaces) { + parseUsagesFromNS(ignoredCustom, abc, imports, uses, n, ignorePackage, ""); + } + } + } + } + } + + private static boolean parseUsagesFromNS(String ignoredCustom, ABC abc, List imports, List uses, int namespace_index, DottedChain ignorePackage, String name) { + Namespace ns = abc.constants.getNamespace(namespace_index); + + if (ns.kind == Namespace.KIND_NAMESPACE) { + String nsVal = ns.getName(abc.constants).toRawString(); + for (ABCContainerTag abcTag : abc.getAbcTags()) { + DottedChain nsimport = abcTag.getABC().nsValueToName(nsVal); + if (nsimport.equals(AVM2Deobfuscation.BUILTIN)) { + return true; //handled, but import/use not added + } + if (!nsimport.isEmpty()) { + + if (!nsimport.getWithoutLast().equals(ignorePackage) && !imports.contains(nsimport)) { + imports.add(nsimport); + } + if (ignoredCustom != null && nsVal.equals(ignoredCustom)) { + return true; + } + if (!uses.contains(nsimport.getLast())) { + uses.add(nsimport.getLast()); + } + return true; + } + } + } + return false; + } + +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/script/LinkReportExporter.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/script/LinkReportExporter.java new file mode 100644 index 000000000..b59db7d8a --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/script/LinkReportExporter.java @@ -0,0 +1,206 @@ +/* + * Copyright (C) 2010-2016 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash.exporters.script; + +import com.jpexs.decompiler.flash.EventListener; +import com.jpexs.decompiler.flash.SWF; +import com.jpexs.decompiler.flash.abc.ABC; +import com.jpexs.decompiler.flash.abc.ScriptPack; +import com.jpexs.decompiler.flash.abc.types.ClassInfo; +import com.jpexs.decompiler.flash.abc.types.InstanceInfo; +import com.jpexs.decompiler.flash.abc.types.Multiname; +import com.jpexs.decompiler.flash.abc.types.Namespace; +import com.jpexs.decompiler.flash.abc.types.NamespaceSet; +import com.jpexs.decompiler.flash.abc.types.ScriptInfo; +import com.jpexs.decompiler.flash.abc.types.traits.Trait; +import com.jpexs.decompiler.flash.abc.types.traits.TraitClass; +import com.jpexs.decompiler.graph.DottedChain; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +/** + * Class LinkReportExporter - generates Linker reports similar to Flex + * -link-report, but for SWF files + * + * @author JPEXS + */ +public class LinkReportExporter { + + private String newLineChar = "\n"; + private String indentStr = " "; + + /** + * Constructs reporter with LF as newline, two spaces as indent + */ + public LinkReportExporter() { + + } + + /** + * Constructs reporter with custom newline char, two spaces as indent + * + * @param newLineChar + */ + public LinkReportExporter(String newLineChar) { + this.newLineChar = newLineChar; + } + + /** + * Constructs reporter with custom newline char and indent string + * + * @param newLineChar + * @param indentStr + */ + public LinkReportExporter(String newLineChar, String indentStr) { + this.newLineChar = newLineChar; + this.indentStr = indentStr; + + } + + private String indent(int cnt) { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < cnt; i++) { + sb.append(indentStr); + } + return sb.toString(); + } + + public String generateReport(SWF swf, List as3scripts, EventListener evl) { + StringBuilder sb = new StringBuilder(); + Set extDeps = new HashSet<>(); + sb.append("").append(newLineChar); + sb.append(indent(1)).append("").append(newLineChar); + List revList = new ArrayList<>(as3scripts); + Collections.reverse(revList); + + List existingObjects = new ArrayList<>(); + for (ScriptPack sp : as3scripts) { + existingObjects.add(sp.getClassPath().packageStr.add(sp.getClassPath().className)); + } + + for (ScriptPack sp : revList) { + String scriptName = "script" + sp.scriptIndex; + sb.append(indent(2)).append("").append(newLineChar); + } + sb.append(indent(1)).append("").append(newLineChar); + sb.append("").append(newLineChar); + return sb.toString(); + } + + private String multiNameToId(ABC abc, Multiname multiName) { + Namespace ns = multiName.getNamespace(abc.constants); + NamespaceSet nss = multiName.getNamespaceSet(abc.constants); + if (nss != null && nss.namespaces.length == 1) { + ns = abc.constants.getNamespace(nss.namespaces[0]); + } + String pkgName = ns == null ? "" : ns.getName(abc.constants).toRawString(); + String clsName = multiName.getName(abc.constants, new ArrayList<>(), true); + return pkgName.isEmpty() ? clsName : pkgName + ":" + clsName; + } + + private String dottedChainToId(DottedChain dc) { + if (dc.getWithoutLast().isEmpty()) { + return dc.getLast(); + } + return dc.getWithoutLast().toRawString() + ":" + dc.getLast(); + } + + private String reportTrait(Set externalDefs, List existingObjects, SWF swf, ABC abc, Trait t) { + //TODO: handle externalDefs - + StringBuilder sb = new StringBuilder(); + if (t instanceof TraitClass) { + TraitClass tc = (TraitClass) t; + sb.append(indent(3)).append("").append(newLineChar); + ClassInfo ci = abc.class_info.get(tc.class_info); + InstanceInfo ii = abc.instance_info.get(tc.class_info); + + Set allDeps = new HashSet<>(); + + String superPre; + if (ii.super_index != 0) { + superPre = multiNameToId(abc, abc.constants.getMultiname(ii.super_index)); + } else { + superPre = "Object"; + } + allDeps.add(superPre); + sb.append(indent(3)).append("
").append(newLineChar);
+
+            for (int iface : ii.interfaces) {
+                String ifacePre = multiNameToId(abc, abc.constants.getMultiname(iface));
+                allDeps.add(ifacePre);
+                sb.append(indent(3)).append("
").append(newLineChar);
+            }
+
+            for (Trait ct : ci.static_traits.traits) {
+                reportTrait(externalDefs, existingObjects, swf, abc, ct);
+            }
+            for (Trait it : ii.instance_traits.traits) {
+                reportTrait(externalDefs, existingObjects, swf, abc, it);
+            }
+            List imports = new ArrayList<>();
+            List uses = new ArrayList<>();
+
+            sb.append(indent(3)).append("").append(newLineChar); //Automatic
+
+            getImportsUsagesFromClass(tc.class_info, null, abc, imports, uses, new DottedChain("FAKE!PACKAGE") /*do not skip any package*/, new ArrayList<>());
+            for (DottedChain dc : imports) {
+                if (!"*".equals(dc.getLast())) {
+                    //some toplevel "imports" can be only method calls
+                    if (dc.getWithoutLast().isEmpty() && !existingObjects.contains(dc)) {
+                        continue;
+                    }
+                    String dep = dottedChainToId(dc);
+                    if (!allDeps.contains(dep)) {
+                        sb.append(indent(3)).append("").append(newLineChar);
+                        allDeps.add(dep);
+                    }
+                }
+            }
+        }
+        return sb.toString();
+    }
+
+    private void getImportsUsagesFromClass(int class_info, String customNs, ABC abc, List imports, List uses, DottedChain ignoredPackage, List fullyQualifiedNames) {
+        ClassInfo classInfo = abc.class_info.get(class_info);
+        InstanceInfo instanceInfo = abc.instance_info.get(class_info);
+
+        //static initializer
+        ImportsUsagesParser.parseImportsUsagesFromMethodInfo(customNs, abc, classInfo.cinit_index, imports, uses, ignoredPackage, fullyQualifiedNames, new ArrayList<>());
+
+        //instance initializer
+        ImportsUsagesParser.parseImportsUsagesFromMethodInfo(customNs, abc, instanceInfo.iinit_index, imports, uses, ignoredPackage, fullyQualifiedNames, new ArrayList<>());
+
+        //static
+        classInfo.static_traits.getImportsUsages(customNs, abc, imports, uses, ignoredPackage, fullyQualifiedNames);
+
+        //instance
+        instanceInfo.instance_traits.getImportsUsages(customNs, abc, imports, uses, ignoredPackage, fullyQualifiedNames);
+
+    }
+
+}
diff --git a/src/com/jpexs/decompiler/flash/console/CommandLineArgumentParser.java b/src/com/jpexs/decompiler/flash/console/CommandLineArgumentParser.java
index 906c93de2..b1abaff39 100644
--- a/src/com/jpexs/decompiler/flash/console/CommandLineArgumentParser.java
+++ b/src/com/jpexs/decompiler/flash/console/CommandLineArgumentParser.java
@@ -75,6 +75,7 @@ import com.jpexs.decompiler.flash.exporters.modes.ShapeExportMode;
 import com.jpexs.decompiler.flash.exporters.modes.SoundExportMode;
 import com.jpexs.decompiler.flash.exporters.modes.SpriteExportMode;
 import com.jpexs.decompiler.flash.exporters.modes.TextExportMode;
+import com.jpexs.decompiler.flash.exporters.script.LinkReportExporter;
 import com.jpexs.decompiler.flash.exporters.settings.BinaryDataExportSettings;
 import com.jpexs.decompiler.flash.exporters.settings.ButtonExportSettings;
 import com.jpexs.decompiler.flash.exporters.settings.FontExportSettings;
@@ -577,6 +578,13 @@ public class CommandLineArgumentParser {
             out.println("  ...: SWF file to search instance in");
         }
 
+        if (filter == null || filter.equals("linkreport")) {
+            out.println(" " + (cnt++) + ") -linkReport [-outfile ] ");
+            out.println("  ...generates linker report for the swffile");
+            out.println("  ...-outfile  (optional): Saves XML report to . When ommited, the report is printed to stdout.");
+            out.println("  ...: SWF file to search instance in");
+        }
+
         printCmdLineUsageExamples(out, filter);
     }
 
@@ -792,7 +800,9 @@ public class CommandLineArgumentParser {
             command = nextParam.substring(1);
         }
 
-        if (command.equals("getinstancemetadata")) {
+        if (command.equals("linkreport")) {
+            parseLinkReport(selectionClasses, args);
+        } else if (command.equals("getinstancemetadata")) {
             parseGetInstanceMetadata(args);
         } else if (command.equals("setinstancemetadata")) {
             parseSetInstanceMetadata(args);
@@ -987,6 +997,50 @@ public class CommandLineArgumentParser {
         setConfigurations(args.pop());
     }
 
+    private static void parseLinkReport(List selectionClasses, Stack args) {
+        if (args.isEmpty()) {
+            badArguments("linkreport");
+        }
+        File stdOutFile = null;
+        File swfFile = null;
+        while (!args.isEmpty()) {
+            String paramName = args.pop().toLowerCase();
+            switch (paramName) {
+                case "-outfile":
+                    if (args.empty()) {
+                        System.err.println("Missing output file");
+                        badArguments("linkreport");
+                    }
+                    stdOutFile = new File(args.pop());
+                    break;
+                default:
+                    if (!args.isEmpty()) {
+                        badArguments("linkreport");
+                    }
+                    swfFile = new File(paramName);
+            }
+        }
+        if (swfFile == null) {
+            System.err.println("No SWF file specified");
+            badArguments("getinstancemetadata");
+        }
+        processReadSWF(swfFile, stdOutFile, (SWF swf, OutputStream stdout) -> {
+            LinkReportExporter lre = new LinkReportExporter();
+
+            List reportPacks;
+            try {
+                reportPacks = selectionClasses != null ? swf.getScriptPacksByClassNames(selectionClasses) : swf.getAS3Packs();
+            } catch (Exception ex) {
+                System.err.println("Error while getting packs");
+                System.exit(1);
+                return;
+            }
+
+            String reportStr = lre.generateReport(swf, reportPacks, null);
+            stdout.write(reportStr.getBytes("UTF-8"));
+        });
+    }
+
     private static void parseGetInstanceMetadata(Stack args) {
         if (args.size() < 3) {
             badArguments("getinstancemetadata");

From 8c5345cfd86f8f7546db4d49c3f5b84fa03d1b51 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jindra=20Pet=C5=99=C3=ADk?= 
Date: Sat, 6 Aug 2016 07:19:52 +0200
Subject: [PATCH 02/23] AS3 editation with flex - not really working yet:  -
 needs fixing circular references, etc. (eg. editing class which references
 classes which references this class)  - needs better errors displaying with
 jump to error line, etc.

---
 .../src/com/jpexs/decompiler/flash/SWF.java   |  10 +-
 .../com/jpexs/decompiler/flash/abc/ABC.java   | 136 ++++++---
 .../flash/abc/types/traits/Trait.java         |  19 +-
 .../flash/abc/types/traits/TraitClass.java    |  40 +--
 .../flash/abc/types/traits/TraitFunction.java |   9 +-
 .../types/traits/TraitMethodGetterSetter.java |   9 +-
 .../abc/types/traits/TraitSlotConst.java      |  10 +-
 .../flash/abc/types/traits/Traits.java        |   5 +-
 .../flash/configuration/Configuration.java    |   5 +
 .../flash/exporters/script/Dependency.java    |  58 ++++
 ...sagesParser.java => DependencyParser.java} |  62 +++--
 .../exporters/script/DependencyType.java      |   5 +
 .../exporters/script/LinkReportExporter.java  |  33 +--
 .../flash/exporters/swf/SwfToSwcExporter.java | 261 ++++++++++++++++++
 .../flash/exporters/swf/swc_main_abctag.xml   | 216 +++++++++++++++
 .../flash/flexsdk/As3ScriptReplacer.java      | 152 ++++++++++
 .../flash/flexsdk/MxmlcException.java         |  15 +
 .../decompiler/flash/flexsdk/MxmlcRunner.java |  54 ++++
 .../flash/importers/SwfXmlImporter.java       |  14 +-
 .../flash/flexsdk/As3ScriptReplacerTest.java  |  50 ++++
 .../console/CommandLineArgumentParser.java    |  33 ++-
 .../jpexs/decompiler/flash/gui/MainPanel.java |   8 +
 .../decompiler/flash/gui/abc/ABCPanel.java    |  11 +-
 .../locales/AdvancedSettingsDialog.properties |   3 +
 .../flash/gui/locales/MainFrame.properties    |   3 +-
 25 files changed, 1067 insertions(+), 154 deletions(-)
 create mode 100644 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/script/Dependency.java
 rename libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/script/{ImportsUsagesParser.java => DependencyParser.java} (64%)
 create mode 100644 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/script/DependencyType.java
 create mode 100644 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/swf/SwfToSwcExporter.java
 create mode 100644 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/swf/swc_main_abctag.xml
 create mode 100644 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/flexsdk/As3ScriptReplacer.java
 create mode 100644 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/flexsdk/MxmlcException.java
 create mode 100644 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/flexsdk/MxmlcRunner.java
 create mode 100644 libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/flexsdk/As3ScriptReplacerTest.java

diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java
index f17f66ae3..664af0e18 100644
--- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java
+++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java
@@ -2535,10 +2535,14 @@ public final class SWF implements SWFContainerItem, Timelined {
         System.gc();
     }
 
+    public void clearAbcListCache() {
+        abcList = null;
+    }
+
     public void clearAllCache() {
         characters = null;
         characterIdTags = null;
-        abcList = null;
+        clearAbcListCache();
         timeline = null;
         clearReadOnlyListCache();
         clearImageCache();
@@ -2890,7 +2894,8 @@ public final class SWF implements SWFContainerItem, Timelined {
             timelined.setModified(true);
             timelined.resetTimeline();
         } else // timeline should be always the swf here
-         if (removeDependencies) {
+        {
+            if (removeDependencies) {
                 removeTagWithDependenciesFromTimeline(tag, timelined.getTimeline());
                 timelined.setModified(true);
             } else {
@@ -2899,6 +2904,7 @@ public final class SWF implements SWFContainerItem, Timelined {
                     timelined.setModified(true);
                 }
             }
+        }
     }
 
     @Override
diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ABC.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ABC.java
index 3c3a87945..29f090534 100644
--- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ABC.java
+++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ABC.java
@@ -55,7 +55,11 @@ import com.jpexs.decompiler.flash.abc.usages.MethodParamsMultinameUsage;
 import com.jpexs.decompiler.flash.abc.usages.MethodReturnTypeMultinameUsage;
 import com.jpexs.decompiler.flash.abc.usages.MultinameUsage;
 import com.jpexs.decompiler.flash.abc.usages.TypeNameMultinameUsage;
+import com.jpexs.decompiler.flash.configuration.Configuration;
 import com.jpexs.decompiler.flash.dumpview.DumpInfo;
+import com.jpexs.decompiler.flash.exporters.script.LinkReportExporter;
+import com.jpexs.decompiler.flash.flexsdk.As3ScriptReplacer;
+import com.jpexs.decompiler.flash.flexsdk.MxmlcException;
 import com.jpexs.decompiler.flash.helpers.SWFDecompilerPlugin;
 import com.jpexs.decompiler.flash.tags.ABCContainerTag;
 import com.jpexs.decompiler.flash.tags.Tag;
@@ -137,6 +141,25 @@ public class ABC {
         return method_info.size() - 1;
     }
 
+    public void deleteClass(int class_info, boolean d) {
+        ABC abc = this;
+        ClassInfo classInfo = abc.class_info.get(class_info);
+        classInfo.deleted = d;
+        InstanceInfo instanceInfo = abc.instance_info.get(class_info);
+        instanceInfo.deleted = d;
+
+        classInfo.static_traits.delete(abc, d);
+        abc.method_info.get(classInfo.cinit_index).delete(abc, d);
+
+        instanceInfo.instance_traits.delete(abc, d);
+        abc.method_info.get(instanceInfo.iinit_index).delete(abc, d);
+
+        int protectedNS = instanceInfo.protectedNS;
+        if (protectedNS != 0) {
+            abc.constants.getNamespace(protectedNS).deleted = d;
+        }
+    }
+
     public TraitMethodGetterSetter addMethod(int classId, String name, boolean isStatic) {
         Multiname multiname = new Multiname();
         multiname.kind = Multiname.QNAME;
@@ -743,10 +766,19 @@ public class ABC {
             aos.writeU30(ci.cinit_index);
             aos.writeTraits(ci.static_traits);
         }
-        aos.writeU30(script_info.size());
+        int numScripts = script_info.size();
         for (ScriptInfo si : script_info) {
-            aos.writeU30(si.init_index);
-            aos.writeTraits(si.traits);
+            if (si.deleted) {
+                numScripts--;
+            }
+        }
+
+        aos.writeU30(numScripts);
+        for (ScriptInfo si : script_info) {
+            if (!si.deleted) {
+                aos.writeU30(si.init_index);
+                aos.writeTraits(si.traits);
+            }
         }
 
         aos.writeU30(bodies.size());
@@ -964,7 +996,9 @@ public class ABC {
     public List getScriptPacks(String packagePrefix, List allAbcs) {
         List ret = new ArrayList<>();
         for (int i = 0; i < script_info.size(); i++) {
-            ret.addAll(script_info.get(i).getPacks(this, i, packagePrefix, allAbcs));
+            if (!script_info.get(i).deleted) {
+                ret.addAll(script_info.get(i).getPacks(this, i, packagePrefix, allAbcs));
+            }
         }
         return ret;
     }
@@ -1328,67 +1362,81 @@ public class ABC {
     }
 
     public boolean replaceScriptPack(ScriptPack pack, String as) throws AVM2ParseException, CompilationException, IOException, InterruptedException {
-        String scriptName = pack.getPathScriptName() + ".as";
-        int oldIndex = pack.scriptIndex;
-        int newIndex = script_info.size();
-        String documentClass = getSwf().getDocumentClass();
-        boolean isDocumentClass = documentClass != null && documentClass.equals(pack.getClassPath().toString());
+
+        final boolean USE_FLEX = true;
 
         boolean isSimple = pack.isSimple;
 
-        ScriptInfo si = script_info.get(oldIndex);
-        if (isSimple) {
-            si.delete(this, true);
+        if (USE_FLEX) {
+            if (!pack.isSimple) {
+                return false;
+            }
+            As3ScriptReplacer asr = new As3ScriptReplacer(Configuration.flexSdkLocation.get(), new LinkReportExporter());
+            try {
+                asr.replaceScript(pack.getSwf(), pack, as);
+            } catch (MxmlcException ex) {
+                throw new AVM2ParseException(ex.getMxmlcErrorOutput(), 0);
+            }
         } else {
+            String scriptName = pack.getPathScriptName() + ".as";
+            int oldIndex = pack.scriptIndex;
+            int newIndex = script_info.size();
+            String documentClass = getSwf().getDocumentClass();
+            boolean isDocumentClass = documentClass != null && documentClass.equals(pack.getClassPath().toString());
+
+            ScriptInfo si = script_info.get(oldIndex);
+            if (isSimple) {
+                si.delete(this, true);
+            } else {
+                for (int t : pack.traitIndices) {
+                    si.traits.traits.get(t).delete(this, true);
+                }
+            }
+
+            int newClassIndex = instance_info.size();
             for (int t : pack.traitIndices) {
-                si.traits.traits.get(t).delete(this, true);
+                if (si.traits.traits.get(t) instanceof TraitClass) {
+                    TraitClass tc = (TraitClass) si.traits.traits.get(t);
+                    newClassIndex = tc.class_info + 1;
+                }
+
             }
-        }
+            List otherAbcs = new ArrayList<>(pack.allABCs);
+            otherAbcs.remove(this);
+            ActionScript3Parser.compile(as, this, otherAbcs, isDocumentClass, scriptName, newClassIndex, oldIndex);
 
-        int newClassIndex = instance_info.size();
-        for (int t : pack.traitIndices) {
-            if (si.traits.traits.get(t) instanceof TraitClass) {
-                TraitClass tc = (TraitClass) si.traits.traits.get(t);
-                newClassIndex = tc.class_info + 1;
+            if (isSimple) {
+                // Move newly added script to its position
+                script_info.set(oldIndex, script_info.get(newIndex));
+                script_info.remove(newIndex);
+            } else {
+                script_info.get(newIndex).setModified(true);
+                //Note: Is deleting traits safe?
+                List todel = new ArrayList<>(new TreeSet<>(pack.traitIndices));
+                for (int i = todel.size() - 1; i >= 0; i--) {
+                    si.traits.traits.remove((int) todel.get(i));
+                }
             }
-
+            script_info.get(oldIndex).setModified(true);
         }
-        List otherAbcs = new ArrayList<>(pack.allABCs);
-        otherAbcs.remove(this);
-        ActionScript3Parser.compile(as, this, otherAbcs, isDocumentClass, scriptName, newClassIndex, oldIndex);
-
-        if (isSimple) {
-            // Move newly added script to its position
-            script_info.set(oldIndex, script_info.get(newIndex));
-            script_info.remove(newIndex);
-        } else {
-            script_info.get(newIndex).setModified(true);
-            //Note: Is deleting traits safe?
-            List todel = new ArrayList<>(new TreeSet<>(pack.traitIndices));
-            for (int i = todel.size() - 1; i >= 0; i--) {
-                si.traits.traits.remove((int) todel.get(i));
-            }
-        }
-
-        script_info.get(oldIndex).setModified(true);
         pack(); // removes old classes/methods
         ((Tag) parentTag).setModified(true);
         return !isSimple;
     }
 
     public void pack() {
-        for (int c = 0; c < instance_info.size(); c++) {
-            if (instance_info.get(c).deleted) {
-                removeClass(c);
-                c--;
-            }
-        }
         for (int m = 0; m < method_info.size(); m++) {
             if (method_info.get(m).deleted) {
                 removeMethod(m);
                 m--;
             }
         }
+        for (int c = 0; c < instance_info.size(); c++) {
+            if (instance_info.get(c).deleted) {
+                removeClass(c);
+                c--;
+            }
+        }
 
         getMethodIndexing();
     }
diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/Trait.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/Trait.java
index 35b66c090..0c1446dc4 100644
--- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/Trait.java
+++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/Trait.java
@@ -42,7 +42,9 @@ import com.jpexs.decompiler.flash.abc.types.NamespaceSet;
 import com.jpexs.decompiler.flash.abc.types.ScriptInfo;
 import com.jpexs.decompiler.flash.configuration.Configuration;
 import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode;
-import com.jpexs.decompiler.flash.exporters.script.ImportsUsagesParser;
+import com.jpexs.decompiler.flash.exporters.script.Dependency;
+import com.jpexs.decompiler.flash.exporters.script.DependencyParser;
+import com.jpexs.decompiler.flash.exporters.script.DependencyType;
 import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
 import com.jpexs.decompiler.flash.helpers.NulWriter;
 import com.jpexs.decompiler.flash.tags.ABCContainerTag;
@@ -174,14 +176,14 @@ public abstract class Trait implements Cloneable, Serializable {
         return getName(abc).getNamespace(abc.constants).getName(abc.constants);
     }
 
-    public void getImportsUsages(String ignoredCustom, ABC abc, List imports, List uses, DottedChain ignorePackage, List fullyQualifiedNames) {
+    public void getDependencies(String ignoredCustom, ABC abc, List dependencies, List uses, DottedChain ignorePackage, List fullyQualifiedNames) {
         if (ignoredCustom == null) {
             Namespace n = getName(abc).getNamespace(abc.constants);
             if (n.kind == Namespace.KIND_NAMESPACE) {
                 ignoredCustom = n.getName(abc.constants).toRawString();
             }
         }
-        ImportsUsagesParser.parseUsagesFromMultiname(ignoredCustom, abc, imports, uses, getName(abc), ignorePackage, fullyQualifiedNames);
+        DependencyParser.parseUsagesFromMultiname(ignoredCustom, abc, dependencies, uses, getName(abc), ignorePackage, fullyQualifiedNames, DependencyType.NAMESPACE);
     }
 
     private static final String[] builtInClasses = {"ArgumentError", "arguments", "Array", "Boolean", "Class", "Date", "DefinitionError", "Error", "EvalError", "Function", "int", "JSON", "Math", "Namespace", "Number", "Object", "QName", "RangeError", "ReferenceError", "RegExp", "SecurityError", "String", "SyntaxError", "TypeError", "uint", "URIError", "VerifyError", "XML", "XMLList"};
@@ -210,14 +212,21 @@ public abstract class Trait implements Cloneable, Serializable {
         }
 
         //imports
-        List imports = new ArrayList<>();
+        List dependencies = new ArrayList<>();
         List uses = new ArrayList<>();
         String customNs = null;
         Namespace ns = getName(abc).getNamespace(abc.constants);
         if (ns.kind == Namespace.KIND_NAMESPACE) {
             customNs = ns.getName(abc.constants).toRawString();
         }
-        getImportsUsages(customNs, abc, imports, uses, ignorePackage, new ArrayList<>());
+        getDependencies(customNs, abc, dependencies, uses, ignorePackage, new ArrayList<>());
+
+        List imports = new ArrayList<>();
+        for (Dependency d : dependencies) {
+            if (!imports.contains(d.getId())) {
+                imports.add(d.getId());
+            }
+        }
 
         List importnames = new ArrayList<>();
         importnames.addAll(namesInThisPackage);
diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitClass.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitClass.java
index d92552773..2eea9627c 100644
--- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitClass.java
+++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitClass.java
@@ -25,7 +25,9 @@ import com.jpexs.decompiler.flash.abc.types.MethodBody;
 import com.jpexs.decompiler.flash.abc.types.Multiname;
 import com.jpexs.decompiler.flash.abc.types.Namespace;
 import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode;
-import com.jpexs.decompiler.flash.exporters.script.ImportsUsagesParser;
+import com.jpexs.decompiler.flash.exporters.script.Dependency;
+import com.jpexs.decompiler.flash.exporters.script.DependencyParser;
+import com.jpexs.decompiler.flash.exporters.script.DependencyType;
 import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
 import com.jpexs.decompiler.flash.helpers.NulWriter;
 import com.jpexs.decompiler.graph.DottedChain;
@@ -49,22 +51,7 @@ public class TraitClass extends Trait implements TraitWithSlot {
 
     @Override
     public void delete(ABC abc, boolean d) {
-        ClassInfo classInfo = abc.class_info.get(class_info);
-        classInfo.deleted = d;
-        InstanceInfo instanceInfo = abc.instance_info.get(class_info);
-        instanceInfo.deleted = d;
-
-        classInfo.static_traits.delete(abc, d);
-        abc.method_info.get(classInfo.cinit_index).delete(abc, d);
-
-        instanceInfo.instance_traits.delete(abc, d);
-        abc.method_info.get(instanceInfo.iinit_index).delete(abc, d);
-
-        int protectedNS = instanceInfo.protectedNS;
-        if (protectedNS != 0) {
-            abc.constants.getNamespace(protectedNS).deleted = d;
-        }
-
+        abc.deleteClass(class_info, d);
         abc.constants.getMultiname(name_index).deleted = d;
     }
 
@@ -79,32 +66,31 @@ public class TraitClass extends Trait implements TraitWithSlot {
     }
 
     @Override
-    public void getImportsUsages(String customNs, ABC abc, List imports, List uses, DottedChain ignorePackage, List fullyQualifiedNames) {
-        super.getImportsUsages(customNs, abc, imports, uses, ignorePackage == null ? getPackage(abc) : ignorePackage, fullyQualifiedNames);
+    public void getDependencies(String customNs, ABC abc, List dependencies, List uses, DottedChain ignorePackage, List fullyQualifiedNames) {
+        super.getDependencies(customNs, abc, dependencies, uses, ignorePackage == null ? getPackage(abc) : ignorePackage, fullyQualifiedNames);
         ClassInfo classInfo = abc.class_info.get(class_info);
         InstanceInfo instanceInfo = abc.instance_info.get(class_info);
         DottedChain packageName = instanceInfo.getName(abc.constants).getNamespace(abc.constants).getName(abc.constants); //assume not null name
 
-        ImportsUsagesParser.parseImportsUsagesFromMultiname(customNs, abc, imports, uses, abc.constants.getMultiname(instanceInfo.name_index), packageName, fullyQualifiedNames);
-
+        //DependencyParser.parseDependenciesFromMultiname(customNs, abc, dependencies, uses, abc.constants.getMultiname(instanceInfo.name_index), packageName, fullyQualifiedNames);
         if (instanceInfo.super_index > 0) {
-            ImportsUsagesParser.parseImportsUsagesFromMultiname(customNs, abc, imports, uses, abc.constants.getMultiname(instanceInfo.super_index), packageName, fullyQualifiedNames);
+            DependencyParser.parseDependenciesFromMultiname(customNs, abc, dependencies, uses, abc.constants.getMultiname(instanceInfo.super_index), packageName, fullyQualifiedNames, DependencyType.INHERITANCE);
         }
         for (int i : instanceInfo.interfaces) {
-            ImportsUsagesParser.parseImportsUsagesFromMultiname(customNs, abc, imports, uses, abc.constants.getMultiname(i), packageName, fullyQualifiedNames);
+            DependencyParser.parseDependenciesFromMultiname(customNs, abc, dependencies, uses, abc.constants.getMultiname(i), packageName, fullyQualifiedNames, DependencyType.INHERITANCE);
         }
 
         //static
-        classInfo.static_traits.getImportsUsages(customNs, abc, imports, uses, packageName, fullyQualifiedNames);
+        classInfo.static_traits.getDependencies(customNs, abc, dependencies, uses, packageName, fullyQualifiedNames);
 
         //static initializer
-        ImportsUsagesParser.parseImportsUsagesFromMethodInfo(customNs, abc, classInfo.cinit_index, imports, uses, packageName, fullyQualifiedNames, new ArrayList<>());
+        DependencyParser.parseDependenciesFromMethodInfo(customNs, abc, classInfo.cinit_index, dependencies, uses, packageName, fullyQualifiedNames, new ArrayList<>());
 
         //instance
-        instanceInfo.instance_traits.getImportsUsages(customNs, abc, imports, uses, packageName, fullyQualifiedNames);
+        instanceInfo.instance_traits.getDependencies(customNs, abc, dependencies, uses, packageName, fullyQualifiedNames);
 
         //instance initializer
-        ImportsUsagesParser.parseImportsUsagesFromMethodInfo(customNs, abc, instanceInfo.iinit_index, imports, uses, packageName, fullyQualifiedNames, new ArrayList<>());
+        DependencyParser.parseDependenciesFromMethodInfo(customNs, abc, instanceInfo.iinit_index, dependencies, uses, packageName, fullyQualifiedNames, new ArrayList<>());
     }
 
     @Override
diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitFunction.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitFunction.java
index b18f5f1f1..b02f88e61 100644
--- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitFunction.java
+++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitFunction.java
@@ -20,7 +20,8 @@ import com.jpexs.decompiler.flash.abc.ABC;
 import com.jpexs.decompiler.flash.abc.types.ConvertData;
 import com.jpexs.decompiler.flash.abc.types.MethodBody;
 import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode;
-import com.jpexs.decompiler.flash.exporters.script.ImportsUsagesParser;
+import com.jpexs.decompiler.flash.exporters.script.Dependency;
+import com.jpexs.decompiler.flash.exporters.script.DependencyParser;
 import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
 import com.jpexs.decompiler.flash.helpers.NulWriter;
 import com.jpexs.decompiler.flash.helpers.hilight.HighlightSpecialType;
@@ -124,14 +125,14 @@ public class TraitFunction extends Trait implements TraitWithSlot {
     }
 
     @Override
-    public void getImportsUsages(String customNs, ABC abc, List imports, List uses, DottedChain ignorePackage, List fullyQualifiedNames) {
+    public void getDependencies(String customNs, ABC abc, List dependencies, List uses, DottedChain ignorePackage, List fullyQualifiedNames) {
         if (ignorePackage == null) {
             ignorePackage = getPackage(abc);
         }
-        super.getImportsUsages(customNs, abc, imports, uses, ignorePackage, fullyQualifiedNames);
+        super.getDependencies(customNs, abc, dependencies, uses, ignorePackage, fullyQualifiedNames);
         //if (method_info != 0)
         {
-            ImportsUsagesParser.parseImportsUsagesFromMethodInfo(customNs, abc, method_info, imports, uses, ignorePackage, fullyQualifiedNames, new ArrayList<>());
+            DependencyParser.parseDependenciesFromMethodInfo(customNs, abc, method_info, dependencies, uses, ignorePackage, fullyQualifiedNames, new ArrayList<>());
         }
     }
 }
diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitMethodGetterSetter.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitMethodGetterSetter.java
index 7487d22f2..8b24560a3 100644
--- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitMethodGetterSetter.java
+++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitMethodGetterSetter.java
@@ -23,7 +23,8 @@ import com.jpexs.decompiler.flash.abc.types.MethodInfo;
 import com.jpexs.decompiler.flash.abc.types.Namespace;
 import com.jpexs.decompiler.flash.configuration.Configuration;
 import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode;
-import com.jpexs.decompiler.flash.exporters.script.ImportsUsagesParser;
+import com.jpexs.decompiler.flash.exporters.script.Dependency;
+import com.jpexs.decompiler.flash.exporters.script.DependencyParser;
 import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
 import com.jpexs.decompiler.flash.helpers.NulWriter;
 import com.jpexs.decompiler.flash.helpers.hilight.HighlightSpecialType;
@@ -59,11 +60,11 @@ public class TraitMethodGetterSetter extends Trait {
     }
 
     @Override
-    public void getImportsUsages(String customNs, ABC abc, List imports, List uses, DottedChain ignorePackage, List fullyQualifiedNames) {
+    public void getDependencies(String customNs, ABC abc, List dependencies, List uses, DottedChain ignorePackage, List fullyQualifiedNames) {
         if (ignorePackage == null) {
             ignorePackage = getPackage(abc);
         }
-        super.getImportsUsages(customNs, abc, imports, uses, ignorePackage, fullyQualifiedNames);
+        super.getDependencies(customNs, abc, dependencies, uses, ignorePackage, fullyQualifiedNames);
 
         if (customNs == null) {
             Namespace n = getName(abc).getNamespace(abc.constants);
@@ -73,7 +74,7 @@ public class TraitMethodGetterSetter extends Trait {
         }
         //if (method_info != 0)
         {
-            ImportsUsagesParser.parseImportsUsagesFromMethodInfo(customNs, abc, method_info, imports, uses, ignorePackage, fullyQualifiedNames, new ArrayList<>());
+            DependencyParser.parseDependenciesFromMethodInfo(customNs, abc, method_info, dependencies, uses, ignorePackage, fullyQualifiedNames, new ArrayList<>());
         }
     }
 
diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitSlotConst.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitSlotConst.java
index d46ec1c8b..2ee16f80f 100644
--- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitSlotConst.java
+++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitSlotConst.java
@@ -26,7 +26,9 @@ import com.jpexs.decompiler.flash.abc.types.Namespace;
 import com.jpexs.decompiler.flash.abc.types.ValueKind;
 import com.jpexs.decompiler.flash.configuration.Configuration;
 import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode;
-import com.jpexs.decompiler.flash.exporters.script.ImportsUsagesParser;
+import com.jpexs.decompiler.flash.exporters.script.Dependency;
+import com.jpexs.decompiler.flash.exporters.script.DependencyParser;
+import com.jpexs.decompiler.flash.exporters.script.DependencyType;
 import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
 import com.jpexs.decompiler.flash.helpers.NulWriter;
 import com.jpexs.decompiler.flash.helpers.hilight.HighlightSpecialType;
@@ -197,12 +199,12 @@ public class TraitSlotConst extends Trait implements TraitWithSlot {
     }
 
     @Override
-    public void getImportsUsages(String customNs, ABC abc, List imports, List uses, DottedChain ignorePackage, List fullyQualifiedNames) {
+    public void getDependencies(String customNs, ABC abc, List dependencies, List uses, DottedChain ignorePackage, List fullyQualifiedNames) {
         if (ignorePackage == null) {
             ignorePackage = getPackage(abc);
         }
-        super.getImportsUsages(customNs, abc, imports, uses, ignorePackage, fullyQualifiedNames);
-        ImportsUsagesParser.parseImportsUsagesFromMultiname(customNs, abc, imports, uses, abc.constants.getMultiname(type_index), getPackage(abc), fullyQualifiedNames);
+        super.getDependencies(customNs, abc, dependencies, uses, ignorePackage, fullyQualifiedNames);
+        DependencyParser.parseDependenciesFromMultiname(customNs, abc, dependencies, uses, abc.constants.getMultiname(type_index), getPackage(abc), fullyQualifiedNames, DependencyType.SIGNATURE);
     }
 
     @Override
diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/Traits.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/Traits.java
index ad3ed16dc..b863ed879 100644
--- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/Traits.java
+++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/Traits.java
@@ -20,6 +20,7 @@ import com.jpexs.decompiler.flash.abc.ABC;
 import com.jpexs.decompiler.flash.abc.types.ConvertData;
 import com.jpexs.decompiler.flash.configuration.Configuration;
 import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode;
+import com.jpexs.decompiler.flash.exporters.script.Dependency;
 import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
 import com.jpexs.decompiler.flash.helpers.NulWriter;
 import com.jpexs.decompiler.graph.DottedChain;
@@ -244,9 +245,9 @@ public class Traits implements Cloneable, Serializable {
         }
     }
 
-    public void getImportsUsages(String customNs, ABC abc, List imports, List uses, DottedChain ignorePackage, List fullyQualifiedNames) {
+    public void getDependencies(String customNs, ABC abc, List dependencies, List uses, DottedChain ignorePackage, List fullyQualifiedNames) {
         for (Trait t : traits) {
-            t.getImportsUsages(customNs, abc, imports, uses, ignorePackage, fullyQualifiedNames);
+            t.getDependencies(customNs, abc, dependencies, uses, ignorePackage, fullyQualifiedNames);
         }
     }
 }
diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/configuration/Configuration.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/configuration/Configuration.java
index 36cd7e4bb..069800f3c 100644
--- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/configuration/Configuration.java
+++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/configuration/Configuration.java
@@ -539,6 +539,11 @@ public class Configuration {
     @ConfigurationFile(".*\\.swc$")
     public static final ConfigurationItem playerLibLocation = null;
 
+    @ConfigurationDefaultString("")
+    @ConfigurationCategory("paths")
+    @ConfigurationDirectory
+    public static final ConfigurationItem flexSdkLocation = null;
+
     @ConfigurationDefaultDouble(0.7)
     @ConfigurationName("gui.avm2.splitPane.vars.dividerLocationPercent")
     @ConfigurationInternal
diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/script/Dependency.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/script/Dependency.java
new file mode 100644
index 000000000..69a082735
--- /dev/null
+++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/script/Dependency.java
@@ -0,0 +1,58 @@
+package com.jpexs.decompiler.flash.exporters.script;
+
+import com.jpexs.decompiler.graph.DottedChain;
+import java.util.Objects;
+
+public class Dependency {
+
+    private DottedChain id;
+    private DependencyType type;
+
+    public Dependency(DottedChain id, DependencyType type) {
+        this.id = id;
+        this.type = type;
+    }
+
+    public DottedChain getId() {
+        return id;
+    }
+
+    public DependencyType getType() {
+        return type;
+    }
+
+    @Override
+    public String toString() {
+        return id.toString() + " (" + type + ")";
+    }
+
+    @Override
+    public int hashCode() {
+        int hash = 5;
+        hash = 79 * hash + Objects.hashCode(this.id);
+        hash = 79 * hash + Objects.hashCode(this.type);
+        return hash;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (getClass() != obj.getClass()) {
+            return false;
+        }
+        final Dependency other = (Dependency) obj;
+        if (!Objects.equals(this.id, other.id)) {
+            return false;
+        }
+        if (this.type != other.type) {
+            return false;
+        }
+        return true;
+    }
+
+}
diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/script/ImportsUsagesParser.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/script/DependencyParser.java
similarity index 64%
rename from libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/script/ImportsUsagesParser.java
rename to libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/script/DependencyParser.java
index 79637ff6d..a779c35d2 100644
--- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/script/ImportsUsagesParser.java
+++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/script/DependencyParser.java
@@ -37,42 +37,44 @@ import com.jpexs.decompiler.flash.tags.ABCContainerTag;
 import com.jpexs.decompiler.graph.DottedChain;
 import java.util.List;
 
-public class ImportsUsagesParser {
+public class DependencyParser {
 
-    public static void parseImportsUsagesFromNS(String ignoredCustom, ABC abc, List imports, List uses, int namespace_index, DottedChain ignorePackage, String name) {
+    public static void parseDependenciesFromNS(String ignoredCustom, ABC abc, List dependencies, List uses, int namespace_index, DottedChain ignorePackage, String name, DependencyType dependencyType) {
         Namespace ns = abc.constants.getNamespace(namespace_index);
         if (name.isEmpty()) {
             name = "*";
         }
         DottedChain newimport = ns.getName(abc.constants);
 
-        if (parseUsagesFromNS(ignoredCustom, abc, imports, uses, namespace_index, ignorePackage, name)) {
+        if (parseUsagesFromNS(ignoredCustom, abc, dependencies, uses, namespace_index, ignorePackage, name)) {
             return;
         } else if ((ns.kind != Namespace.KIND_PACKAGE) && (ns.kind != Namespace.KIND_PACKAGE_INTERNAL)) {
             return;
         }
         newimport = newimport.add(name);
-        if (!imports.contains(newimport)) {
+        Dependency dep = new Dependency(newimport, dependencyType);
+
+        if (!dependencies.contains(dep)) {
             DottedChain pkg = newimport.getWithoutLast(); //.substring(0, newimport.lastIndexOf('.'));
             if (pkg.equals(InitVectorAVM2Item.VECTOR_PACKAGE)) { //special case - is imported always
                 return;
             }
             if (!pkg.equals(ignorePackage)) {
-                imports.add(newimport);
+                dependencies.add(dep);
             }
         }
         //}
     }
 
-    public static void parseImportsUsagesFromMultiname(String ignoredCustom, ABC abc, List imports, List uses, Multiname m, DottedChain ignorePackage, List fullyQualifiedNames) {
+    public static void parseDependenciesFromMultiname(String ignoredCustom, ABC abc, List dependencies, List uses, Multiname m, DottedChain ignorePackage, List fullyQualifiedNames, DependencyType dependencyType) {
         if (m != null) {
             if (m.kind == Multiname.TYPENAME) {
                 if (m.qname_index != 0) {
-                    parseImportsUsagesFromMultiname(ignoredCustom, abc, imports, uses, abc.constants.getMultiname(m.qname_index), ignorePackage, fullyQualifiedNames);
+                    parseDependenciesFromMultiname(ignoredCustom, abc, dependencies, uses, abc.constants.getMultiname(m.qname_index), ignorePackage, fullyQualifiedNames, dependencyType);
                 }
                 for (Integer i : m.params) {
                     if (i != 0) {
-                        parseImportsUsagesFromMultiname(ignoredCustom, abc, imports, uses, abc.constants.getMultiname(i), ignorePackage, fullyQualifiedNames);
+                        parseDependenciesFromMultiname(ignoredCustom, abc, dependencies, uses, abc.constants.getMultiname(i), ignorePackage, fullyQualifiedNames, dependencyType);
                     }
                 }
                 return;
@@ -81,46 +83,47 @@ public class ImportsUsagesParser {
             String name = m.getName(abc.constants, fullyQualifiedNames, true);
             NamespaceSet nss = m.getNamespaceSet(abc.constants);
             if (ns != null) {
-                parseImportsUsagesFromNS(ignoredCustom, abc, imports, uses, m.namespace_index, ignorePackage, name);
+                parseDependenciesFromNS(ignoredCustom, abc, dependencies, uses, m.namespace_index, ignorePackage, name, dependencyType);
             }
             if (nss != null) {
                 for (int n : nss.namespaces) {
-                    parseImportsUsagesFromNS(ignoredCustom, abc, imports, uses, n, ignorePackage, nss.namespaces.length > 1 ? "" : name);
+                    parseDependenciesFromNS(ignoredCustom, abc, dependencies, uses, n, ignorePackage, nss.namespaces.length > 1 ? "" : name, dependencyType);
                 }
             }
         }
     }
 
-    public static void parseImportsUsagesFromMethodInfo(String ignoredCustom, ABC abc, int method_index, List imports, List uses, DottedChain ignorePackage, List fullyQualifiedNames, List visitedMethods) {
+    public static void parseDependenciesFromMethodInfo(String ignoredCustom, ABC abc, int method_index, List dependencies, List uses, DottedChain ignorePackage, List fullyQualifiedNames, List visitedMethods) {
         if ((method_index < 0) || (method_index >= abc.method_info.size())) {
             return;
         }
         visitedMethods.add(method_index);
         if (abc.method_info.get(method_index).ret_type != 0) {
-            parseImportsUsagesFromMultiname(ignoredCustom, abc, imports, uses, abc.constants.getMultiname(abc.method_info.get(method_index).ret_type), ignorePackage, fullyQualifiedNames);
+            parseDependenciesFromMultiname(ignoredCustom, abc, dependencies, uses, abc.constants.getMultiname(abc.method_info.get(method_index).ret_type), ignorePackage, fullyQualifiedNames, DependencyType.SIGNATURE);
         }
         for (int t : abc.method_info.get(method_index).param_types) {
             if (t != 0) {
-                parseImportsUsagesFromMultiname(ignoredCustom, abc, imports, uses, abc.constants.getMultiname(t), ignorePackage, fullyQualifiedNames);
+                parseDependenciesFromMultiname(ignoredCustom, abc, dependencies, uses, abc.constants.getMultiname(t), ignorePackage, fullyQualifiedNames, DependencyType.SIGNATURE);
             }
         }
         MethodBody body = abc.findBody(method_index);
         if (body != null) {
-            body.traits.getImportsUsages(ignoredCustom, abc, imports, uses, ignorePackage, fullyQualifiedNames);
+            body.traits.getDependencies(ignoredCustom, abc, dependencies, uses, ignorePackage, fullyQualifiedNames);
             for (ABCException ex : body.exceptions) {
-                parseImportsUsagesFromMultiname(ignoredCustom, abc, imports, uses, abc.constants.getMultiname(ex.type_index), ignorePackage, fullyQualifiedNames);
+                parseDependenciesFromMultiname(ignoredCustom, abc, dependencies, uses, abc.constants.getMultiname(ex.type_index), ignorePackage, fullyQualifiedNames, DependencyType.EXPRESSION /* or signature?*/);
             }
             for (AVM2Instruction ins : body.getCode().code) {
                 if (ins.definition instanceof AlchemyTypeIns) {
                     DottedChain nimport = AlchemyTypeIns.ALCHEMY_PACKAGE.add(ins.definition.instructionName);
-                    if (!imports.contains(nimport)) {
-                        imports.add(nimport);
+                    Dependency depExp = new Dependency(nimport, DependencyType.EXPRESSION);
+                    if (!dependencies.contains(depExp)) {
+                        dependencies.add(depExp);
                     }
                 }
                 if (ins.definition instanceof NewFunctionIns) {
                     if (ins.operands[0] != method_index) {
                         if (!visitedMethods.contains(ins.operands[0])) {
-                            parseImportsUsagesFromMethodInfo(ignoredCustom, abc, ins.operands[0], imports, uses, ignorePackage, fullyQualifiedNames, visitedMethods);
+                            parseDependenciesFromMethodInfo(ignoredCustom, abc, ins.operands[0], dependencies, uses, ignorePackage, fullyQualifiedNames, visitedMethods);
                         }
                     }
                 }
@@ -132,7 +135,7 @@ public class ImportsUsagesParser {
                     int m = ins.operands[0];
                     if (m != 0) {
                         if (m < abc.constants.getMultinameCount()) {
-                            parseImportsUsagesFromMultiname(ignoredCustom, abc, imports, uses, abc.constants.getMultiname(m), ignorePackage, fullyQualifiedNames);
+                            parseDependenciesFromMultiname(ignoredCustom, abc, dependencies, uses, abc.constants.getMultiname(m), ignorePackage, fullyQualifiedNames, DependencyType.EXPRESSION);
                         }
                     }
                 } else {
@@ -140,7 +143,7 @@ public class ImportsUsagesParser {
                         if (ins.definition.operands[k] == AVM2Code.DAT_MULTINAME_INDEX) {
                             int multinameIndex = ins.operands[k];
                             if (multinameIndex < abc.constants.getMultinameCount()) {
-                                parseUsagesFromMultiname(ignoredCustom, abc, imports, uses, abc.constants.getMultiname(multinameIndex), ignorePackage, fullyQualifiedNames);
+                                parseUsagesFromMultiname(ignoredCustom, abc, dependencies, uses, abc.constants.getMultiname(multinameIndex), ignorePackage, fullyQualifiedNames, DependencyType.EXPRESSION);
                             }
                         }
                     }
@@ -149,15 +152,15 @@ public class ImportsUsagesParser {
         }
     }
 
-    public static void parseUsagesFromMultiname(String ignoredCustom, ABC abc, List imports, List uses, Multiname m, DottedChain ignorePackage, List fullyQualifiedNames) {
+    public static void parseUsagesFromMultiname(String ignoredCustom, ABC abc, List dependencies, List uses, Multiname m, DottedChain ignorePackage, List fullyQualifiedNames, DependencyType dependencyType) {
         if (m != null) {
             if (m.kind == Multiname.TYPENAME) {
                 if (m.qname_index != 0) {
-                    parseUsagesFromMultiname(ignoredCustom, abc, imports, uses, abc.constants.getMultiname(m.qname_index), ignorePackage, fullyQualifiedNames);
+                    parseUsagesFromMultiname(ignoredCustom, abc, dependencies, uses, abc.constants.getMultiname(m.qname_index), ignorePackage, fullyQualifiedNames, dependencyType);
                 }
                 for (Integer i : m.params) {
                     if (i != 0) {
-                        parseUsagesFromMultiname(ignoredCustom, abc, imports, uses, abc.constants.getMultiname(i), ignorePackage, fullyQualifiedNames);
+                        parseUsagesFromMultiname(ignoredCustom, abc, dependencies, uses, abc.constants.getMultiname(i), ignorePackage, fullyQualifiedNames, dependencyType);
                     }
                 }
                 return;
@@ -166,21 +169,21 @@ public class ImportsUsagesParser {
             String name = m.getName(abc.constants, fullyQualifiedNames, false);
             NamespaceSet nss = m.getNamespaceSet(abc.constants);
             if (ns != null) {
-                parseUsagesFromNS(ignoredCustom, abc, imports, uses, m.namespace_index, ignorePackage, name);
+                parseUsagesFromNS(ignoredCustom, abc, dependencies, uses, m.namespace_index, ignorePackage, name);
             }
             if (nss != null) {
                 if (nss.namespaces.length == 1) {
-                    parseUsagesFromNS(ignoredCustom, abc, imports, uses, nss.namespaces[0], ignorePackage, name);
+                    parseUsagesFromNS(ignoredCustom, abc, dependencies, uses, nss.namespaces[0], ignorePackage, name);
                 } else {
                     for (int n : nss.namespaces) {
-                        parseUsagesFromNS(ignoredCustom, abc, imports, uses, n, ignorePackage, "");
+                        parseUsagesFromNS(ignoredCustom, abc, dependencies, uses, n, ignorePackage, "");
                     }
                 }
             }
         }
     }
 
-    private static boolean parseUsagesFromNS(String ignoredCustom, ABC abc, List imports, List uses, int namespace_index, DottedChain ignorePackage, String name) {
+    private static boolean parseUsagesFromNS(String ignoredCustom, ABC abc, List dependencies, List uses, int namespace_index, DottedChain ignorePackage, String name) {
         Namespace ns = abc.constants.getNamespace(namespace_index);
 
         if (ns.kind == Namespace.KIND_NAMESPACE) {
@@ -192,8 +195,9 @@ public class ImportsUsagesParser {
                 }
                 if (!nsimport.isEmpty()) {
 
-                    if (!nsimport.getWithoutLast().equals(ignorePackage) && !imports.contains(nsimport)) {
-                        imports.add(nsimport);
+                    Dependency depNs = new Dependency(nsimport, DependencyType.NAMESPACE);
+                    if (!nsimport.getWithoutLast().equals(ignorePackage) && !dependencies.contains(depNs)) {
+                        dependencies.add(depNs);
                     }
                     if (ignoredCustom != null && nsVal.equals(ignoredCustom)) {
                         return true;
diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/script/DependencyType.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/script/DependencyType.java
new file mode 100644
index 000000000..a3c3d468e
--- /dev/null
+++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/script/DependencyType.java
@@ -0,0 +1,5 @@
+package com.jpexs.decompiler.flash.exporters.script;
+
+public enum DependencyType {
+    INHERITANCE, NAMESPACE, SIGNATURE, EXPRESSION
+}
diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/script/LinkReportExporter.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/script/LinkReportExporter.java
index b59db7d8a..222a8fd0d 100644
--- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/script/LinkReportExporter.java
+++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/script/LinkReportExporter.java
@@ -162,22 +162,23 @@ public class LinkReportExporter {
             for (Trait it : ii.instance_traits.traits) {
                 reportTrait(externalDefs, existingObjects, swf, abc, it);
             }
-            List imports = new ArrayList<>();
+            List dependencies = new ArrayList<>();
             List uses = new ArrayList<>();
 
             sb.append(indent(3)).append("").append(newLineChar); //Automatic
 
-            getImportsUsagesFromClass(tc.class_info, null, abc, imports, uses, new DottedChain("FAKE!PACKAGE") /*do not skip any package*/, new ArrayList<>());
-            for (DottedChain dc : imports) {
+            tc.getDependencies(null, abc, dependencies, uses, new DottedChain("FAKE!PACKAGE"), new ArrayList<>());
+            for (Dependency dependency : dependencies) {
+                DottedChain dc = dependency.getId();
                 if (!"*".equals(dc.getLast())) {
                     //some toplevel "imports" can be only method calls
                     if (dc.getWithoutLast().isEmpty() && !existingObjects.contains(dc)) {
                         continue;
                     }
-                    String dep = dottedChainToId(dc);
-                    if (!allDeps.contains(dep)) {
-                        sb.append(indent(3)).append("").append(newLineChar);
-                        allDeps.add(dep);
+                    String reportDepId = dottedChainToId(dc);
+                    if (!allDeps.contains(reportDepId)) {
+                        sb.append(indent(3)).append("").append(newLineChar);
+                        allDeps.add(reportDepId);
                     }
                 }
             }
@@ -185,22 +186,4 @@ public class LinkReportExporter {
         return sb.toString();
     }
 
-    private void getImportsUsagesFromClass(int class_info, String customNs, ABC abc, List imports, List uses, DottedChain ignoredPackage, List fullyQualifiedNames) {
-        ClassInfo classInfo = abc.class_info.get(class_info);
-        InstanceInfo instanceInfo = abc.instance_info.get(class_info);
-
-        //static initializer
-        ImportsUsagesParser.parseImportsUsagesFromMethodInfo(customNs, abc, classInfo.cinit_index, imports, uses, ignoredPackage, fullyQualifiedNames, new ArrayList<>());
-
-        //instance initializer
-        ImportsUsagesParser.parseImportsUsagesFromMethodInfo(customNs, abc, instanceInfo.iinit_index, imports, uses, ignoredPackage, fullyQualifiedNames, new ArrayList<>());
-
-        //static
-        classInfo.static_traits.getImportsUsages(customNs, abc, imports, uses, ignoredPackage, fullyQualifiedNames);
-
-        //instance
-        instanceInfo.instance_traits.getImportsUsages(customNs, abc, imports, uses, ignoredPackage, fullyQualifiedNames);
-
-    }
-
 }
diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/swf/SwfToSwcExporter.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/swf/SwfToSwcExporter.java
new file mode 100644
index 000000000..039748896
--- /dev/null
+++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/swf/SwfToSwcExporter.java
@@ -0,0 +1,261 @@
+package com.jpexs.decompiler.flash.exporters.swf;
+
+import com.jpexs.decompiler.flash.ReadOnlyTagList;
+import com.jpexs.decompiler.flash.SWC;
+import com.jpexs.decompiler.flash.SWF;
+import com.jpexs.decompiler.flash.abc.ABC;
+import com.jpexs.decompiler.flash.abc.ClassPath;
+import com.jpexs.decompiler.flash.abc.ScriptPack;
+import com.jpexs.decompiler.flash.exporters.script.Dependency;
+import com.jpexs.decompiler.flash.exporters.script.DependencyType;
+import com.jpexs.decompiler.flash.importers.SwfXmlImporter;
+import com.jpexs.decompiler.flash.tags.ABCContainerTag;
+import com.jpexs.decompiler.flash.tags.DoABC2Tag;
+import com.jpexs.decompiler.flash.tags.SymbolClassTag;
+import com.jpexs.decompiler.graph.DottedChain;
+import com.jpexs.helpers.Helper;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.math.BigInteger;
+import java.security.MessageDigest;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipOutputStream;
+
+public class SwfToSwcExporter {
+
+    private static final String DEPENDENCY_NAMESPACE = "n";
+    private static final String DEPENDENCY_INHERITANCE = "i";
+    private static final String DEPENDENCY_EXPRESSION = "e";
+    private static final String DEPENDENCY_SIGNATURE = "s";
+
+    private static String sha256(InputStream is) {
+        String output;
+        int read;
+        byte[] buffer = new byte[8192];
+
+        try {
+            MessageDigest digest = MessageDigest.getInstance("SHA-256");
+            while ((read = is.read(buffer)) > 0) {
+                digest.update(buffer, 0, read);
+            }
+            byte[] hash = digest.digest();
+            BigInteger bigInt = new BigInteger(1, hash);
+            output = bigInt.toString(16);
+            while (output.length() < 32) {
+                output = "0" + output;
+            }
+        } catch (Exception e) {
+            return null;
+        }
+
+        return output;
+    }
+
+    public SwfToSwcExporter() {
+
+    }
+
+    private String dottedChainToId(DottedChain dc) {
+        if (dc.getWithoutLast().isEmpty()) {
+            return dc.getLast();
+        }
+        return dc.getWithoutLast().toRawString() + ":" + dc.getLast();
+    }
+
+    private String generateCatalog(SWF swf, byte[] swfBytes, boolean skipDependencies) {
+        StringBuilder sb = new StringBuilder();
+
+        final String libraryFileName = "library.swf";
+
+        final String SWC_VERSION = "1.2";
+        final String FLEX_VERSION = "4.6.0";
+        final String FLEX_BUILD = "23201";
+        final String MINIMUM_SUPPORTED_VERSION = "3.0.0";
+
+        sb.append("\n")
+                .append("\n")
+                .append("  \n")
+                .append("    \n")
+                .append("    \n")
+                .append("  \n")
+                .append("  \n")
+                .append("    \n")
+                .append("    \n")
+                .append("  \n")
+                .append("  \n")
+                .append("    \n");
+
+        final long TIME_NOW = new Date().getTime();
+
+        Set definedObjects = new HashSet<>();
+
+        List abcTagList = swf.getAbcList();
+
+        List packs = swf.getAS3Packs();
+
+        for (ScriptPack pack : packs) {
+            ClassPath cp = pack.getClassPath();
+            definedObjects.add(cp.packageStr.add(cp.className));
+        }
+
+        List allAbcList = new ArrayList<>();
+        for (int i = 0; i < abcTagList.size(); i++) {
+            allAbcList.add(abcTagList.get(i).getABC());
+        }
+
+        for (ABCContainerTag abcContainer : abcTagList) {
+            if (!(abcContainer instanceof DoABC2Tag)) {
+                continue; //DoABCTag 1 does not have name
+            }
+            DoABC2Tag abcTag = (DoABC2Tag) abcContainer;
+            String scriptName = abcTag.name;
+            sb.append("      \n");
+        }
+        String sha256Hash = sha256(new ByteArrayInputStream(swfBytes));
+        sb.append("      \n")
+                .append("        \n")
+                .append("      \n")
+                .append("    \n")
+                .append("  \n")
+                .append("  \n")
+                .append("  \n")
+                .append("\n");
+        return sb.toString();
+    }
+
+    private static String getDependencyStr(DependencyType depType) {
+        switch (depType) {
+            case EXPRESSION:
+                return DEPENDENCY_EXPRESSION;
+            case INHERITANCE:
+                return DEPENDENCY_INHERITANCE;
+            case SIGNATURE:
+                return DEPENDENCY_SIGNATURE;
+            case NAMESPACE:
+                return DEPENDENCY_NAMESPACE;
+            default:
+                return null;
+        }
+    }
+
+    private SWF recompileSWF(SWF swf) throws IOException, InterruptedException {
+        ByteArrayOutputStream swfOrigBaos = new ByteArrayOutputStream();
+        swf.saveTo(swfOrigBaos);
+        return new SWF(new ByteArrayInputStream(swfOrigBaos.toByteArray()), false, false);
+    }
+
+    public void exportSwf(SWF swf, File outSwcFile, boolean skipDependencies) throws IOException {
+
+        //Make local copy of SWF so we do not modify original
+        try {
+            swf = recompileSWF(swf);
+            final String HASH = "myhash";
+            String abcTagXml = new String(Helper.readStream(SwfToSwcExporter.class.getResourceAsStream("/com/jpexs/decompiler/flash/exporters/swf/swc_main_abctag.xml")), "UTF-8");
+            abcTagXml = abcTagXml.replace("%hash%", HASH);
+            SwfXmlImporter xmlImporter = new SwfXmlImporter();
+            DoABC2Tag mainAbcTag = (DoABC2Tag) xmlImporter.importObject(abcTagXml, DoABC2Tag.class, swf);
+            ReadOnlyTagList list = swf.getTags();
+            final String documentClassStub = "_%hash%_flash_display_Sprite";
+            String documentClass = documentClassStub.replace("%hash%", HASH);
+            boolean documentClassSet = false;
+            for (int i = 0; i < list.size(); i++) {
+                if (list.get(i) instanceof ABCContainerTag) {
+                    swf.addTag(i, mainAbcTag);
+                    break;
+                }
+            }
+            for (int i = 0; i < list.size(); i++) {
+                if (list.get(i) instanceof SymbolClassTag) {
+                    SymbolClassTag sct = (SymbolClassTag) list.get(i);
+                    for (int j = 0; j < sct.tags.size(); j++) {
+                        if (sct.tags.get(j) == 0) {
+                            sct.names.set(j, documentClass);
+                            documentClassSet = true;
+                            break;
+                        }
+                    }
+                }
+            }
+            if (!documentClassSet) {
+                throw new IOException("Original document class not found!");
+            }
+            swf = recompileSWF(swf);
+
+        } catch (Exception ex) {
+            throw new RuntimeException(ex);
+        }
+
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        swf.saveTo(baos);
+        byte[] swfBytes = baos.toByteArray();
+        String catalogStr = generateCatalog(swf, swfBytes, skipDependencies);
+
+        File tempFile = new File((outSwcFile.getAbsolutePath()) + ".tmp");
+        try (FileOutputStream fos = new FileOutputStream(tempFile);
+                ZipOutputStream zos = new ZipOutputStream(fos)) {
+
+            ZipEntry libraryEntry = new ZipEntry("library.swf");
+            zos.putNextEntry(libraryEntry);
+            zos.write(swfBytes);
+            zos.closeEntry();
+
+            ZipEntry catalogEntry = new ZipEntry("catalog.xml");
+            zos.putNextEntry(catalogEntry);
+            zos.write(catalogStr.getBytes("UTF-8"));
+            zos.closeEntry();
+
+            zos.close();
+            outSwcFile.delete();
+            tempFile.renameTo(outSwcFile);
+        } finally {
+            if (tempFile.exists()) {
+                tempFile.delete();
+            }
+        }
+
+    }
+}
diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/swf/swc_main_abctag.xml b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/swf/swc_main_abctag.xml
new file mode 100644
index 000000000..f5dcc83f0
--- /dev/null
+++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/swf/swc_main_abctag.xml
@@ -0,0 +1,216 @@
+
+
+
+    
+        
+        
+            
+            
+            
+            
+            
+            
+            
+                
+                _%hash%_flash_display_Sprite
+                
+                _%hash%_flash_display_Sprite/_%hash%_flash_display_Sprite
+                Security
+                flash.system
+                allowDomain
+                apply
+                http://adobe.com/AS3/2006/builtin
+                _%hash%_flash_display_Sprite/allowDomainInRSL
+                void
+                domains
+                allowInsecureDomain
+                _%hash%_flash_display_Sprite/allowInsecureDomainInRSL
+                allowDomainInRSL
+                __go_to_definition_help
+                pos
+                602
+                allowInsecureDomainInRSL
+                922
+                flash.display
+                Sprite
+                Object
+                EventDispatcher
+                flash.events
+                DisplayObject
+                InteractiveObject
+                DisplayObjectContainer
+                ExcludeClass
+                __go_to_ctor_definition_help
+                275
+                130
+            
+            
+                
+                
+                
+                
+                
+                
+                
+                
+                
+            
+            
+            
+                
+                
+                
+                
+                
+                
+                
+                
+                
+                
+                
+                
+                
+                
+                
+            
+        
+        
+            
+                
+                
+                
+            
+            
+                
+                
+                
+            
+            
+                
+                
+                
+            
+            
+                
+                
+                
+            
+            
+                
+                
+                
+            
+        
+        
+            
+                
+                    16
+                
+                
+                    17
+                
+            
+            
+                
+                    16
+                
+                
+                    19
+                
+            
+            
+                
+                
+            
+            
+                
+                    16
+                
+                
+                    30
+                
+            
+            
+                
+                    16
+                
+                
+                    31
+                
+            
+        
+        
+            
+                
+                
+                    
+                        
+                            
+                                0
+                            
+                        
+                        
+                            
+                                1
+                            
+                        
+                    
+                
+            
+        
+        
+            
+                
+                    
+                
+            
+        
+        
+            
+                
+                    
+                        
+                            
+                                2
+                                3
+                                4
+                            
+                        
+                    
+                
+            
+        
+        
+            
+                
+                
+                    
+                
+            
+            
+                
+                
+                    
+                
+            
+            
+                
+                
+                    
+                
+            
+            
+                
+                
+                    
+                
+            
+            
+                
+                
+                    
+                
+            
+        
+    
+
\ No newline at end of file
diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/flexsdk/As3ScriptReplacer.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/flexsdk/As3ScriptReplacer.java
new file mode 100644
index 000000000..bbdedd249
--- /dev/null
+++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/flexsdk/As3ScriptReplacer.java
@@ -0,0 +1,152 @@
+package com.jpexs.decompiler.flash.flexsdk;
+
+import com.jpexs.decompiler.flash.SWF;
+import com.jpexs.decompiler.flash.abc.ABC;
+import com.jpexs.decompiler.flash.abc.ScriptPack;
+import com.jpexs.decompiler.flash.abc.types.InstanceInfo;
+import com.jpexs.decompiler.flash.abc.types.ScriptInfo;
+import com.jpexs.decompiler.flash.configuration.Configuration;
+import com.jpexs.decompiler.flash.exporters.script.LinkReportExporter;
+import com.jpexs.decompiler.flash.exporters.swf.SwfToSwcExporter;
+import com.jpexs.decompiler.flash.tags.ABCContainerTag;
+import com.jpexs.decompiler.flash.tags.Tag;
+import com.jpexs.decompiler.graph.DottedChain;
+import com.jpexs.helpers.Helper;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.util.List;
+
+public class As3ScriptReplacer extends MxmlcRunner {
+
+    private LinkReportExporter linkReporter;
+
+    public As3ScriptReplacer(String flexSdkPath, LinkReportExporter linkReporter) {
+        super(flexSdkPath);
+        this.linkReporter = linkReporter;
+    }
+
+    private static void deleteFolder(File folder) {
+        File[] files = folder.listFiles();
+        if (files != null) { //some JVMs return null for empty dirs
+            for (File f : files) {
+                if (f.isDirectory()) {
+                    deleteFolder(f);
+                } else {
+                    f.delete();
+                }
+            }
+        }
+        folder.delete();
+    }
+
+    private SWF recompileSWF(SWF swf) throws IOException, InterruptedException {
+        ByteArrayOutputStream swfOrigBaos = new ByteArrayOutputStream();
+        swf.saveTo(swfOrigBaos);
+        return new SWF(new ByteArrayInputStream(swfOrigBaos.toByteArray()), false, false);
+    }
+
+    private boolean isParentDeleted(ABC abc, List allAbcs, DottedChain className) {
+        int class_index = abc.findClassByName(className);
+        if (class_index == -1) {
+            for (ABC a : allAbcs) {
+                class_index = abc.findClassByName(className);
+                if (class_index != -1) {
+                    abc = a;
+                    break;
+                }
+            }
+            if (class_index == -1) {
+                return false;
+            }
+        }
+        InstanceInfo ii = abc.instance_info.get(class_index);
+        if (ii.deleted) {
+            return true;
+        }
+        if (ii.super_index != 0 && isParentDeleted(abc, allAbcs, abc.constants.getMultiname(ii.super_index).getNameWithNamespace(abc.constants))) {
+            return true;
+        }
+        for (int iface : ii.interfaces) {
+            if (isParentDeleted(abc, allAbcs, abc.constants.getMultiname(iface).getNameWithNamespace(abc.constants))) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public void replaceScript(SWF swf, ScriptPack oldPack, String txt) throws IOException, MxmlcException, InterruptedException {
+        if (!oldPack.isSimple) {
+            throw new IOException("Cannot compile such file"); //Alchemy, etc.
+        }
+
+        File tempDir = null;
+        try {
+            tempDir = Files.createTempDirectory("ffdec-mxmlc-replace").toFile();
+            File pkgDir = tempDir;
+            for (String pkgPart : oldPack.getClassPath().packageStr.toList()) {
+                if (!pkgPart.isEmpty()) {
+                    pkgDir = new File(pkgDir, pkgPart);
+                }
+            }
+            pkgDir.mkdirs();
+            File scriptFileToCompile = new File(pkgDir, oldPack.getClassPath().className + ".as");
+            File compiledSwfFile = new File(pkgDir, "out.swf");
+            File swcFile = new File(pkgDir, "out.swc");
+
+            //Make copy without the old script
+            SWF swfCopy = recompileSWF(swf);
+            List copyPacks = swfCopy.getAS3Packs();
+            for (ScriptPack sp : copyPacks) {
+                if (sp.getClassPath().equals(oldPack.getClassPath())) {
+                    sp.abc.script_info.get(sp.scriptIndex).delete(sp.abc, true);
+                    ((Tag) sp.abc.parentTag).setModified(true);
+                    break;
+                }
+            }
+            //remove all subclasses
+            for (ScriptPack sp : copyPacks) {
+                DottedChain dc = sp.getPathPackage().add(sp.getPathScriptName());
+                if (isParentDeleted(sp.abc, sp.allABCs, dc)) {
+                    sp.abc.script_info.get(sp.scriptIndex).delete(sp.abc, true);
+                }
+            }
+            SwfToSwcExporter swcExport = new SwfToSwcExporter();
+            swcExport.exportSwf(swfCopy, swcFile, true);
+
+            Helper.writeFile(scriptFileToCompile.getAbsolutePath(), txt.getBytes("UTF-8"));
+            mxmlc("-include-inheritance-dependencies-only", "-warnings=false", "-library-path", swcFile.getAbsolutePath(), "-source-path", tempDir.getAbsolutePath(), "-output", compiledSwfFile.getAbsolutePath(), "-debug=true", scriptFileToCompile.getAbsolutePath());
+
+            try (FileInputStream fis = new FileInputStream(compiledSwfFile)) {
+                SWF newSWF = new SWF(fis, false, false);
+                List newTags = newSWF.getAbcList();
+                ScriptInfo oldScriptInfo = oldPack.abc.script_info.get(oldPack.scriptIndex);
+                if (oldPack.isSimple) {
+                    oldScriptInfo.delete(oldPack.abc, true);
+                } else {
+                    //NOO
+                }
+                int oldTagIndex = swf.getTags().indexOf((Tag) oldPack.abc.parentTag);
+                if (oldPack.abc.script_info.size() == 1) {
+                    swf.removeTag(oldTagIndex);
+                }
+
+                for (ABCContainerTag act : newTags) {
+                    ((Tag) act).setSwf(swf);
+                    swf.addTag(oldTagIndex + 1, (Tag) act);
+                    ((Tag) act).setModified(true);
+                }
+                ((Tag) oldPack.abc.parentTag).setModified(true);
+                swf.clearAbcListCache();
+                swf.clearScriptCache();
+            }
+        } finally {
+            if (tempDir != null && tempDir.exists()) {
+                //deleteFolder(tempDir);
+            }
+        }
+    }
+}
diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/flexsdk/MxmlcException.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/flexsdk/MxmlcException.java
new file mode 100644
index 000000000..ab8b2187e
--- /dev/null
+++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/flexsdk/MxmlcException.java
@@ -0,0 +1,15 @@
+package com.jpexs.decompiler.flash.flexsdk;
+
+public class MxmlcException extends Exception {
+
+    private String mxmlcErrorOutput;
+
+    public MxmlcException(String mxmlcErrorOutput) {
+        this.mxmlcErrorOutput = mxmlcErrorOutput;
+    }
+
+    public String getMxmlcErrorOutput() {
+        return mxmlcErrorOutput;
+    }
+
+}
diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/flexsdk/MxmlcRunner.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/flexsdk/MxmlcRunner.java
new file mode 100644
index 000000000..63a709e74
--- /dev/null
+++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/flexsdk/MxmlcRunner.java
@@ -0,0 +1,54 @@
+package com.jpexs.decompiler.flash.flexsdk;
+
+import com.jpexs.helpers.Helper;
+import java.io.File;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+public class MxmlcRunner {
+
+    private String flexSdkPath;
+
+    public MxmlcRunner(String flexSdkPath) {
+        this.flexSdkPath = flexSdkPath;
+    }
+
+    public String getMxmlcPath() {
+        boolean isWin = System.getProperty("os.name").toLowerCase().contains("win");
+        return flexSdkPath + File.separator + "bin" + File.separator + "mxmlc" + (isWin ? ".exe" : "");
+    }
+
+    public void mxmlc(String... arguments) throws MxmlcException, InterruptedException, IOException {
+        String runArgs[] = new String[arguments.length + 1];
+        runArgs[0] = getMxmlcPath();
+        System.arraycopy(arguments, 0, runArgs, 1, arguments.length);
+        System.out.println("" + String.join(" ", runArgs));
+        Process proc = null;
+        try {
+            proc = Runtime.getRuntime().exec(runArgs);
+            Helper.readStream(proc.getInputStream());
+            String errstring = "";
+            try {
+                errstring = new String(Helper.readStream(proc.getErrorStream()), "UTF-8");
+            } catch (UnsupportedEncodingException ex) {
+                //should not happen
+            }
+            proc.waitFor();
+            int exitValue = proc.exitValue();
+            if (exitValue > 0) {
+                throw new MxmlcException(errstring);
+            }
+        } finally {
+            if (proc != null) {
+                try {
+                    proc.destroy();
+                } catch (Exception ex2) {
+                    //ignore
+                }
+            }
+        }
+    }
+
+}
diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/importers/SwfXmlImporter.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/importers/SwfXmlImporter.java
index 691ef5c7a..59cb5113a 100644
--- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/importers/SwfXmlImporter.java
+++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/importers/SwfXmlImporter.java
@@ -151,6 +151,18 @@ public class SwfXmlImporter {
         }
     }
 
+    public Object importObject(String xml, Class requiredType, SWF swf) throws IOException {
+        DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
+        try {
+            DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
+            Document doc = docBuilder.parse(new InputSource(new StringReader(xml)));
+            return processObject(doc.getDocumentElement(), requiredType, swf, null);
+        } catch (ParserConfigurationException | SAXException | IllegalArgumentException | IllegalAccessException | NoSuchMethodException | InstantiationException | InvocationTargetException ex) {
+            Logger.getLogger(SwfXmlImporter.class.getName()).log(Level.SEVERE, null, ex);
+        }
+        return null;
+    }
+
     private Field getField(Class cls, String name) throws NoSuchFieldException {
         Field field;
         try {
@@ -243,7 +255,7 @@ public class SwfXmlImporter {
                         setFieldValue(field, obj, childObj);
                     }
                 } catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException | NoSuchMethodException | InstantiationException | InvocationTargetException ex) {
-                    logger.log(Level.SEVERE, null, ex);
+                    logger.log(Level.SEVERE, "Error while getting val from class " + cls + " field: " + name, ex);
                 }
             }
         }
diff --git a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/flexsdk/As3ScriptReplacerTest.java b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/flexsdk/As3ScriptReplacerTest.java
new file mode 100644
index 000000000..40dcb7677
--- /dev/null
+++ b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/flexsdk/As3ScriptReplacerTest.java
@@ -0,0 +1,50 @@
+package com.jpexs.decompiler.flash.flexsdk;
+
+import com.jpexs.decompiler.flash.SWF;
+import com.jpexs.decompiler.flash.abc.ScriptPack;
+import com.jpexs.decompiler.flash.configuration.Configuration;
+import com.jpexs.decompiler.flash.exporters.script.LinkReportExporter;
+import java.io.BufferedInputStream;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import org.testng.annotations.Test;
+
+public class As3ScriptReplacerTest {
+
+    @Test
+    public void testReplace() throws IOException, InterruptedException, Exception {
+        As3ScriptReplacer replacer = new As3ScriptReplacer(Configuration.flexSdkLocation.get(), new LinkReportExporter());
+        SWF swf = new SWF(new BufferedInputStream(new FileInputStream("testdata/as3/as3.swf")), false);
+        String replacement = "package classes\n"
+                + "{\n"
+                + "\n"
+                + "	public dynamic class TestClass1\n"
+                + "	{\n"
+                + "		public var attrib:int = 5;\n"
+                + "		public var sons:Array;\n"
+                + "\n"
+                + "		public function testHello()\n"
+                + "		{\n"
+                + "			trace(\"helloA\");\n"
+                + "		}\n"
+                + "\n"
+                + "		public function method(i:int):int\n"
+                + "		{\n"
+                + "			trace(\"methodB\");\n"
+                + "			return 7;\n"
+                + "		}\n"
+                + "	}\n"
+                + "}";
+        List classNames = new ArrayList<>();
+        classNames.add("classes.TestClass1");
+        List packs = swf.getScriptPacksByClassNames(classNames);
+        for (ScriptPack sp : packs) {
+            replacer.replaceScript(swf, sp, replacement);
+            return;
+        }
+    }
+}
diff --git a/src/com/jpexs/decompiler/flash/console/CommandLineArgumentParser.java b/src/com/jpexs/decompiler/flash/console/CommandLineArgumentParser.java
index b1abaff39..d0c5261e4 100644
--- a/src/com/jpexs/decompiler/flash/console/CommandLineArgumentParser.java
+++ b/src/com/jpexs/decompiler/flash/console/CommandLineArgumentParser.java
@@ -88,12 +88,14 @@ import com.jpexs.decompiler.flash.exporters.settings.ShapeExportSettings;
 import com.jpexs.decompiler.flash.exporters.settings.SoundExportSettings;
 import com.jpexs.decompiler.flash.exporters.settings.SpriteExportSettings;
 import com.jpexs.decompiler.flash.exporters.settings.TextExportSettings;
+import com.jpexs.decompiler.flash.exporters.swf.SwfToSwcExporter;
 import com.jpexs.decompiler.flash.exporters.swf.SwfXmlExporter;
 import com.jpexs.decompiler.flash.gui.AppStrings;
 import com.jpexs.decompiler.flash.gui.Main;
 import com.jpexs.decompiler.flash.gui.SearchInMemory;
 import com.jpexs.decompiler.flash.gui.SearchInMemoryListener;
 import com.jpexs.decompiler.flash.gui.SwfInMemory;
+import com.jpexs.decompiler.flash.gui.View;
 import com.jpexs.decompiler.flash.gui.helpers.CheckResources;
 import com.jpexs.decompiler.flash.helpers.FileTextWriter;
 import com.jpexs.decompiler.flash.helpers.SWFDecompilerPlugin;
@@ -193,6 +195,7 @@ import java.util.concurrent.ExecutionException;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.logging.Level;
 import java.util.logging.Logger;
+import javax.swing.JOptionPane;
 
 /**
  *
@@ -585,6 +588,13 @@ public class CommandLineArgumentParser {
             out.println("  ...: SWF file to search instance in");
         }
 
+        if (filter == null || filter.equals("swf2swc")) {
+            out.println(" " + (cnt++) + ") -swf2swc  ");
+            out.println("  ...generates SWC file from SWF");
+            out.println("  ...: Where to save SWC file");
+            out.println("  ...: Input SWF file");
+        }
+
         printCmdLineUsageExamples(out, filter);
     }
 
@@ -800,7 +810,9 @@ public class CommandLineArgumentParser {
             command = nextParam.substring(1);
         }
 
-        if (command.equals("linkreport")) {
+        if (command.equals("swf2swc")) {
+            parseSwf2Swc(args);
+        } else if (command.equals("linkreport")) {
             parseLinkReport(selectionClasses, args);
         } else if (command.equals("getinstancemetadata")) {
             parseGetInstanceMetadata(args);
@@ -997,6 +1009,18 @@ public class CommandLineArgumentParser {
         setConfigurations(args.pop());
     }
 
+    private static void parseSwf2Swc(Stack args) {
+        if (args.size() < 2) {
+            badArguments("swf2swc");
+        }
+        final File outFile = new File(args.pop());
+        final File swfFile = new File(args.pop());
+        processReadSWF(swfFile, null, (SWF swf, OutputStream stdout) -> {
+            SwfToSwcExporter exporter = new SwfToSwcExporter();
+            exporter.exportSwf(swf, outFile, false);
+        });
+    }
+
     private static void parseLinkReport(List selectionClasses, Stack args) {
         if (args.isEmpty()) {
             badArguments("linkreport");
@@ -3348,6 +3372,13 @@ public class CommandLineArgumentParser {
     }
 
     private static void parseImportScript(Stack args) {
+
+        String flexLocation = Configuration.flexSdkLocation.get();
+        if (flexLocation.isEmpty() || (!new File(flexLocation).exists())) {
+            System.err.println("Flex SDK path not set");
+            System.exit(1);
+        }
+
         if (args.size() < 3) {
             badArguments("importscript");
         }
diff --git a/src/com/jpexs/decompiler/flash/gui/MainPanel.java b/src/com/jpexs/decompiler/flash/gui/MainPanel.java
index ce5577f9e..79265b496 100644
--- a/src/com/jpexs/decompiler/flash/gui/MainPanel.java
+++ b/src/com/jpexs/decompiler/flash/gui/MainPanel.java
@@ -2146,6 +2146,14 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
     }
 
     public void importScript(final SWF swf) {
+
+        String flexLocation = Configuration.flexSdkLocation.get();
+        if (flexLocation.isEmpty() || (!new File(flexLocation).exists())) {
+            View.showMessageDialog(null, AppStrings.translate("message.flexpath.notset"), AppStrings.translate("error"), JOptionPane.ERROR_MESSAGE);
+            Main.advancedSettings("paths");
+            return;
+        }
+
         JFileChooser chooser = new JFileChooser();
         chooser.setCurrentDirectory(new File(Configuration.lastExportDir.get()));
         chooser.setDialogTitle(translate("import.select.directory"));
diff --git a/src/com/jpexs/decompiler/flash/gui/abc/ABCPanel.java b/src/com/jpexs/decompiler/flash/gui/abc/ABCPanel.java
index b4014e147..2c24e0deb 100644
--- a/src/com/jpexs/decompiler/flash/gui/abc/ABCPanel.java
+++ b/src/com/jpexs/decompiler/flash/gui/abc/ABCPanel.java
@@ -1157,6 +1157,12 @@ public class ABCPanel extends JPanel implements ItemListener, SearchListener packs = abc.script_info.get(oldIndex).getPacks(abc, oldIndex, null, pack.allABCs);
-             if (!packs.isEmpty()) {
-
-             }*/
-
             String as = decompiledTextArea.getText();
             abc.replaceScriptPack(pack, as);
             lastDecompiled = as;
diff --git a/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog.properties b/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog.properties
index 97539d86e..08d2a876c 100644
--- a/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog.properties
+++ b/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog.properties
@@ -432,3 +432,6 @@ config.description.simplifyExpressions = Evaluate and simplify expressions to ma
 
 config.name.resetLetterSpacingOnTextImport = Reset Letter Spacing on text import
 config.description.resetLetterSpacingOnTextImport = Useful for cyrillic fonts, because they are wider
+
+config.name.flexSdkLocation = 4) Flex SDK directory path
+config.description.flexSdkLocation = Location of Adobe Flex SDK. It is used mostly for AS3 compilation.
diff --git a/src/com/jpexs/decompiler/flash/gui/locales/MainFrame.properties b/src/com/jpexs/decompiler/flash/gui/locales/MainFrame.properties
index 677619e94..126e31f6f 100644
--- a/src/com/jpexs/decompiler/flash/gui/locales/MainFrame.properties
+++ b/src/com/jpexs/decompiler/flash/gui/locales/MainFrame.properties
@@ -734,4 +734,5 @@ generic.editor.amf3.help = AMF3 value syntax:\n\
                            \ * Nonscalar datatypes can be referenced by previously declared "id" attributes with # syntax:\n\
                            %reference_sample%\n\
                            \ * Keys in Dictionary entries can be any type\n
-                            
\ No newline at end of file
+
+message.flexpath.notset = Flex SDK not found. Please configure its path in Advanced Settings / Paths (4).
\ No newline at end of file

From 6781d86a6c70026c4946ddf8887a8ec25171634e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jindra=20Pet=C5=99=C3=ADk?= 
Date: Sat, 6 Aug 2016 07:21:58 +0200
Subject: [PATCH 03/23] Reformat and organize imports

---
 .../decompiler/flash/abc/avm2/AVM2Code.java   |    2 +-
 .../AVM2DeobfuscatorRegisters.java            |    2 +-
 .../AVM2DeobfuscatorSimpleOld.java            |    7 +-
 .../flash/abc/avm2/model/AVM2Item.java        |    3 +-
 .../avm2/model/clauses/ForEachInAVM2Item.java |    2 +-
 .../abc/avm2/parser/pcode/Flasm3Lexer.java    |  103 +-
 .../avm2/parser/script/ActionScriptLexer.java |  107 +-
 .../abc/avm2/parser/script/NameAVM2Item.java  |    6 +-
 .../parser/script/NamespacedAVM2Item.java     |   44 +-
 .../parser/script/UnresolvedAVM2Item.java     |    2 +-
 .../methodinfo_parser/MethodInfoLexer.java    |  103 +-
 .../jpexs/decompiler/flash/action/Action.java |    4 +-
 .../action/model/FunctionActionItem.java      |   14 +-
 .../flash/action/parser/pcode/FlasmLexer.java |  103 +-
 .../parser/script/ActionScriptLexer.java      |  107 +-
 .../com/jpexs/decompiler/flash/docs/docs.js   |  190 +-
 .../flash/ecma/EcmaFloatingDecimal.java       |  116 +-
 .../flash/exporters/ShapeExporter.java        |    2 +-
 .../decompiler/flash/helpers/BMPFile.java     |   14 +-
 .../flash/helpers/GraphTextWriter.java        |    6 +-
 .../decompiler/flash/helpers/ImageHelper.java |   20 +-
 .../flash/importers/TextImporter.java         |   14 +-
 .../flash/importers/amf/amf3/Amf3Lexer.java   | 1895 +++++++++--------
 .../decompiler/flash/tags/DefineFont2Tag.java |    4 +-
 .../decompiler/flash/tags/DefineFont3Tag.java |    6 +-
 .../decompiler/flash/tags/DefineFontTag.java  |    6 +-
 .../jpexs/decompiler/flash/tags/DoABCTag.java |    2 +-
 .../flash/tags/gfx/DefineCompactedFont.java   |    4 +-
 .../decompiler/flash/tags/text/TextLexer.java |  101 +-
 .../annotations/parser/ConditionLexer.java    |  101 +-
 .../decompiler/flash/xfl/FLAVersion.java      |   10 +-
 .../com/jpexs/decompiler/graph/GraphPart.java |   12 +-
 .../src/com/jpexs/helpers/resource/canvas.js  |    3 +-
 .../flash/ActionScript2ModificationTest.java  |    3 +-
 .../decompiler/flash/gui/LicenseUpdater.java  |   72 +-
 .../decompiler/flash/gui/LoadingDialog.java   |    6 +-
 .../MyRibbonApplicationMenuPopupPanelUI.java  |   84 +-
 .../decompiler/flash/gui/OceanicSkin.java     |   26 +-
 .../decompiler/flash/gui/abc/DetailPanel.java |    6 +-
 .../flash/gui/editor/UndoFixedEditorPane.java |    8 +-
 .../process/win32/Win32ProcessTools.java      |   12 +-
 src/com/sun/jna/platform/win32/User32.java    |   21 +-
 src/com/sun/jna/platform/win32/WinBase.java   |    2 +-
 src/com/sun/jna/platform/win32/WinUser.java   |   16 +-
 .../flash/gui/AdobeFlashExecutor.java         |    2 +-
 .../decompiler/flash/gui/FlashPlayerTest.java |    2 +-
 46 files changed, 1738 insertions(+), 1637 deletions(-)

diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java
index e4189d543..87f49c4ac 100644
--- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java
+++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java
@@ -1638,7 +1638,7 @@ public class AVM2Code implements Cloneable {
              }
              }//*/
 
-            /*if ((ip + 2 < code.size()) && (ins.definition instanceof NewCatchIns)) { // Filling local register in catch clause
+ /*if ((ip + 2 < code.size()) && (ins.definition instanceof NewCatchIns)) { // Filling local register in catch clause
              if (code.get(ip + 1).definition instanceof DupIns) {
              if (code.get(ip + 2).definition instanceof SetLocalTypeIns) {
              ins.definition.translate(isStatic, classIndex, localRegs, stack, scopeStack, constants, ins, method_info, output, body, abc, localRegNames, fullyQualifiedNames);
diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/AVM2DeobfuscatorRegisters.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/AVM2DeobfuscatorRegisters.java
index 0063e899e..48ad09650 100644
--- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/AVM2DeobfuscatorRegisters.java
+++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/AVM2DeobfuscatorRegisters.java
@@ -220,7 +220,7 @@ public class AVM2DeobfuscatorRegisters extends AVM2DeobfuscatorSimple {
 
                 AVM2Instruction ins = code.code.get(idx);
                 InstructionDefinition def = ins.definition;
-                    //System.err.println("" + idx + ": " + ins + " stack:" + stack.size());
+                //System.err.println("" + idx + ": " + ins + " stack:" + stack.size());
 
                 // do not throw EmptyStackException, much faster
                 int requiredStackSize = def.getStackPopCount(ins, abc);
diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/AVM2DeobfuscatorSimpleOld.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/AVM2DeobfuscatorSimpleOld.java
index 5fadb3a3d..11ded804a 100644
--- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/AVM2DeobfuscatorSimpleOld.java
+++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/AVM2DeobfuscatorSimpleOld.java
@@ -161,7 +161,7 @@ public class AVM2DeobfuscatorSimpleOld extends SWFDecompilerAdapter {
             AVM2Instruction ins = code.code.get(i);
             if (ins.definition instanceof JumpIns) {
                 long address = ins.getTargetAddress();
-                jumpTargets.add( code.adr2pos(address) );
+                jumpTargets.add(code.adr2pos(address));
             }
         }
 
@@ -294,9 +294,8 @@ public class AVM2DeobfuscatorSimpleOld extends SWFDecompilerAdapter {
 
             if (inlineIns.contains(ins)) {
                 if (def instanceof SetLocalTypeIns) {
-                    InstructionDefinition prevDef = code.code.get(idx-1).definition;
-                    if ((prevDef instanceof DupIns && !jumpTargets.contains(idx-2)) || !jumpTargets.contains(idx-1))
-                    {
+                    InstructionDefinition prevDef = code.code.get(idx - 1).definition;
+                    if ((prevDef instanceof DupIns && !jumpTargets.contains(idx - 2)) || !jumpTargets.contains(idx - 1)) {
                         int regId = ((SetLocalTypeIns) def).getRegisterId(ins);
                         staticRegs.put(regId, localData.localRegs.get(regId).getNotCoerced());
                         code.replaceInstruction(idx, new AVM2Instruction(0, DeobfuscatePopIns.getInstance(), null), body);
diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/AVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/AVM2Item.java
index 3d1159eaf..9ed4806b3 100644
--- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/AVM2Item.java
+++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/AVM2Item.java
@@ -108,8 +108,9 @@ public abstract class AVM2Item extends GraphTargetItem {
         }
         if (propertyName instanceof FullMultinameAVM2Item) {
             if (((FullMultinameAVM2Item) propertyName).name != null) {
-                if (((FullMultinameAVM2Item) propertyName).namespace != null)
+                if (((FullMultinameAVM2Item) propertyName).namespace != null) {
                     writer.append(".");
+                }
                 return propertyName.toString(writer, localData);
             } else {
                 writer.append(".");
diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/clauses/ForEachInAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/clauses/ForEachInAVM2Item.java
index 433285894..0ba0873f0 100644
--- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/clauses/ForEachInAVM2Item.java
+++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/clauses/ForEachInAVM2Item.java
@@ -77,7 +77,7 @@ public class ForEachInAVM2Item extends LoopItem implements Block {
 
 
          */
-        /*
+ /*
          if (!commands.isEmpty()) {
          GraphTargetItem firstAssign = commands.get(0);
          if (firstAssign instanceof SetTypeAVM2Item) {
diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/pcode/Flasm3Lexer.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/pcode/Flasm3Lexer.java
index 5b57f3efe..bff9f84dd 100644
--- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/pcode/Flasm3Lexer.java
+++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/pcode/Flasm3Lexer.java
@@ -1,6 +1,6 @@
 /* The following code was generated by JFlex 1.6.0 */
 
-/*
+ /*
  *  Copyright (C) 2010-2016 JPEXS, All rights reserved.
  *
  * This library is free software; you can redistribute it and/or
@@ -16,7 +16,7 @@
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library.
  */
-/* Flash assembler language lexer specification */
+ /* Flash assembler language lexer specification */
 package com.jpexs.decompiler.flash.abc.avm2.parser.pcode;
 
 import com.jpexs.decompiler.flash.abc.avm2.parser.AVM2ParseException;
@@ -24,8 +24,7 @@ import java.util.Stack;
 
 /**
  * This class is a scanner generated by
- * JFlex 1.6.0
- * from the specification file
+ * JFlex 1.6.0 from the specification file
  * C:/FFDec/jpexs-decompiler/libsrc/ffdec_lib/lexers/actionscript3_pcode.flex
  */
 public final class Flasm3Lexer {
@@ -51,9 +50,8 @@ public final class Flasm3Lexer {
 
     /**
      * ZZ_LEXSTATE[l] is the state in the DFA for the lexical state l
-     * ZZ_LEXSTATE[l+1] is the state in the DFA for the lexical state l
-     * at the beginning of a line
-     * l is of the form l = 2*k, k a non negative integer
+     * ZZ_LEXSTATE[l+1] is the state in the DFA for the lexical state l at the
+     * beginning of a line l is of the form l = 2*k, k a non negative integer
      */
     private static final int ZZ_LEXSTATE[] = {
         0, 0, 1, 1, 2, 2
@@ -272,9 +270,11 @@ public final class Flasm3Lexer {
     }
 
     private static int zzUnpackAction(String packed, int offset, int[] result) {
-        int i = 0;       /* index in packed string  */
+        int i = 0;
+        /* index in packed string  */
 
-        int j = offset;  /* index in unpacked array */
+        int j = offset;
+        /* index in unpacked array */
 
         int l = packed.length();
         while (i < l) {
@@ -380,9 +380,11 @@ public final class Flasm3Lexer {
     }
 
     private static int zzUnpackRowMap(String packed, int offset, int[] result) {
-        int i = 0;  /* index in packed string  */
+        int i = 0;
+        /* index in packed string  */
 
-        int j = offset;  /* index in unpacked array */
+        int j = offset;
+        /* index in unpacked array */
 
         int l = packed.length();
         while (i < l) {
@@ -2479,9 +2481,11 @@ public final class Flasm3Lexer {
     }
 
     private static int zzUnpackTrans(String packed, int offset, int[] result) {
-        int i = 0;       /* index in packed string  */
+        int i = 0;
+        /* index in packed string  */
 
-        int j = offset;  /* index in unpacked array */
+        int j = offset;
+        /* index in unpacked array */
 
         int l = packed.length();
         while (i < l) {
@@ -2550,9 +2554,11 @@ public final class Flasm3Lexer {
     }
 
     private static int zzUnpackAttribute(String packed, int offset, int[] result) {
-        int i = 0;       /* index in packed string  */
+        int i = 0;
+        /* index in packed string  */
 
-        int j = offset;  /* index in unpacked array */
+        int j = offset;
+        /* index in unpacked array */
 
         int l = packed.length();
         while (i < l) {
@@ -2581,8 +2587,8 @@ public final class Flasm3Lexer {
     private int zzLexicalState = YYINITIAL;
 
     /**
-     * this buffer contains the current text to be matched and is
-     * the source of the yytext() string
+     * this buffer contains the current text to be matched and is the source of
+     * the yytext() string
      */
     private char zzBuffer[] = new char[ZZ_BUFFERSIZE];
 
@@ -2602,8 +2608,8 @@ public final class Flasm3Lexer {
     private int zzStartRead;
 
     /**
-     * endRead marks the last character in the buffer, that has been read
-     * from input
+     * endRead marks the last character in the buffer, that has been read from
+     * input
      */
     private int zzEndRead;
 
@@ -2639,10 +2645,10 @@ public final class Flasm3Lexer {
     private boolean zzEOFDone;
 
     /**
-     * The number of occupied positions in zzBuffer beyond zzEndRead.
-     * When a lead/high surrogate has been read from the input stream
-     * into the final zzBuffer position, this will have a value of 1;
-     * otherwise, it will have a value of 0.
+     * The number of occupied positions in zzBuffer beyond zzEndRead. When a
+     * lead/high surrogate has been read from the input stream into the final
+     * zzBuffer position, this will have a value of 1; otherwise, it will have a
+     * value of 0.
      */
     private int zzFinalHighSurrogate = 0;
 
@@ -2705,9 +2711,11 @@ public final class Flasm3Lexer {
      */
     private static char[] zzUnpackCMap(String packed) {
         char[] map = new char[0x110000];
-        int i = 0;  /* index in packed string  */
+        int i = 0;
+        /* index in packed string  */
 
-        int j = 0;  /* index in unpacked array */
+        int j = 0;
+        /* index in unpacked array */
 
         while (i < 2916) {
             int count = packed.charAt(i++);
@@ -2766,7 +2774,8 @@ public final class Flasm3Lexer {
 
         if (totalRead > 0) {
             zzEndRead += totalRead;
-            if (totalRead == requested) { /* possibly more input available */
+            if (totalRead == requested) {
+                /* possibly more input available */
 
                 if (Character.isHighSurrogate(zzBuffer[zzEndRead - 1])) {
                     --zzEndRead;
@@ -2784,9 +2793,11 @@ public final class Flasm3Lexer {
      * Closes the input stream.
      */
     public final void yyclose() throws java.io.IOException {
-        zzAtEOF = true;            /* indicate end of file */
+        zzAtEOF = true;
+        /* indicate end of file */
 
-        zzEndRead = zzStartRead;  /* invalidate buffer    */
+        zzEndRead = zzStartRead;
+        /* invalidate buffer    */
 
         if (zzReader != null) {
             zzReader.close();
@@ -2794,12 +2805,12 @@ public final class Flasm3Lexer {
     }
 
     /**
-     * Resets the scanner to read from a new input stream.
-     * Does not close the old reader.
+     * Resets the scanner to read from a new input stream. Does not close the
+     * old reader.
      *
      * All internal variables are reset, the old input stream
-     * cannot be reused (internal buffer is discarded and lost).
-     * Lexical state is set to ZZ_INITIAL.
+     * cannot be reused (internal buffer is discarded and lost). Lexical
+     * state is set to ZZ_INITIAL.
      *
      * Internal scan buffer is resized down to its initial length, if it has
      * grown.
@@ -2845,13 +2856,12 @@ public final class Flasm3Lexer {
     }
 
     /**
-     * Returns the character at position pos from the
-     * matched text.
+     * Returns the character at position pos from the matched text.
      *
      * It is equivalent to yytext().charAt(pos), but faster
      *
-     * @param pos the position of the character to fetch.
-     * A value from 0 to yylength()-1.
+     * @param pos the position of the character to fetch. A value from 0 to
+     * yylength()-1.
      *
      * @return the character at position pos
      */
@@ -2869,14 +2879,13 @@ public final class Flasm3Lexer {
     /**
      * Reports an error that occured while scanning.
      *
-     * In a wellformed scanner (no or only correct usage of
-     * yypushback(int) and a match-all fallback rule) this method
-     * will only be called with things that "Can't Possibly Happen".
-     * If this method is called, something is seriously wrong
-     * (e.g. a JFlex bug producing a faulty scanner etc.).
+     * In a wellformed scanner (no or only correct usage of yypushback(int) and
+     * a match-all fallback rule) this method will only be called with things
+     * that "Can't Possibly Happen". If this method is called, something is
+     * seriously wrong (e.g. a JFlex bug producing a faulty scanner etc.).
      *
-     * Usual syntax/scanner level error handling should be done
-     * in error fallback rules.
+     * Usual syntax/scanner level error handling should be done in error
+     * fallback rules.
      *
      * @param errorCode the code of the errormessage to display
      */
@@ -2896,8 +2905,8 @@ public final class Flasm3Lexer {
      *
      * They will be read again by then next call of the scanning method
      *
-     * @param number the number of characters to be read again.
-     * This number must not be greater than yylength()!
+     * @param number the number of characters to be read again. This number must
+     * not be greater than yylength()!
      */
     public void yypushback(int number) {
         if (number > yylength()) {
@@ -2908,8 +2917,8 @@ public final class Flasm3Lexer {
     }
 
     /**
-     * Resumes scanning until the next regular expression is matched,
-     * the end of input is encountered or an I/O-Error occurs.
+     * Resumes scanning until the next regular expression is matched, the end of
+     * input is encountered or an I/O-Error occurs.
      *
      * @return the next token
      * @exception java.io.IOException if any I/O-Error occurs
diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ActionScriptLexer.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ActionScriptLexer.java
index 6edf3e8a3..4bd05fca1 100644
--- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ActionScriptLexer.java
+++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ActionScriptLexer.java
@@ -1,6 +1,6 @@
 /* The following code was generated by JFlex 1.6.0 */
 
-/*
+ /*
  *  Copyright (C) 2010-2016 JPEXS, All rights reserved.
  *
  * This library is free software; you can redistribute it and/or
@@ -26,8 +26,7 @@ import java.util.Stack;
 
 /**
  * This class is a scanner generated by
- * JFlex 1.6.0
- * from the specification file
+ * JFlex 1.6.0 from the specification file
  * C:/FFDec/jpexs-decompiler/libsrc/ffdec_lib/lexers/actionscript3_script.flex
  */
 public final class ActionScriptLexer {
@@ -69,9 +68,8 @@ public final class ActionScriptLexer {
 
     /**
      * ZZ_LEXSTATE[l] is the state in the DFA for the lexical state l
-     * ZZ_LEXSTATE[l+1] is the state in the DFA for the lexical state l
-     * at the beginning of a line
-     * l is of the form l = 2*k, k a non negative integer
+     * ZZ_LEXSTATE[l+1] is the state in the DFA for the lexical state l at the
+     * beginning of a line l is of the form l = 2*k, k a non negative integer
      */
     private static final int ZZ_LEXSTATE[] = {
         0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7,
@@ -295,9 +293,11 @@ public final class ActionScriptLexer {
     }
 
     private static int zzUnpackAction(String packed, int offset, int[] result) {
-        int i = 0;       /* index in packed string  */
+        int i = 0;
+        /* index in packed string  */
 
-        int j = offset;  /* index in unpacked array */
+        int j = offset;
+        /* index in unpacked array */
 
         int l = packed.length();
         while (i < l) {
@@ -383,9 +383,11 @@ public final class ActionScriptLexer {
     }
 
     private static int zzUnpackRowMap(String packed, int offset, int[] result) {
-        int i = 0;  /* index in packed string  */
+        int i = 0;
+        /* index in packed string  */
 
-        int j = offset;  /* index in unpacked array */
+        int j = offset;
+        /* index in unpacked array */
 
         int l = packed.length();
         while (i < l) {
@@ -833,9 +835,11 @@ public final class ActionScriptLexer {
     }
 
     private static int zzUnpackTrans(String packed, int offset, int[] result) {
-        int i = 0;       /* index in packed string  */
+        int i = 0;
+        /* index in packed string  */
 
-        int j = offset;  /* index in unpacked array */
+        int j = offset;
+        /* index in unpacked array */
 
         int l = packed.length();
         while (i < l) {
@@ -894,9 +898,11 @@ public final class ActionScriptLexer {
     }
 
     private static int zzUnpackAttribute(String packed, int offset, int[] result) {
-        int i = 0;       /* index in packed string  */
+        int i = 0;
+        /* index in packed string  */
 
-        int j = offset;  /* index in unpacked array */
+        int j = offset;
+        /* index in unpacked array */
 
         int l = packed.length();
         while (i < l) {
@@ -925,8 +931,8 @@ public final class ActionScriptLexer {
     private int zzLexicalState = YYINITIAL;
 
     /**
-     * this buffer contains the current text to be matched and is
-     * the source of the yytext() string
+     * this buffer contains the current text to be matched and is the source of
+     * the yytext() string
      */
     private char zzBuffer[] = new char[ZZ_BUFFERSIZE];
 
@@ -946,8 +952,8 @@ public final class ActionScriptLexer {
     private int zzStartRead;
 
     /**
-     * endRead marks the last character in the buffer, that has been read
-     * from input
+     * endRead marks the last character in the buffer, that has been read from
+     * input
      */
     private int zzEndRead;
 
@@ -983,10 +989,10 @@ public final class ActionScriptLexer {
     private boolean zzEOFDone;
 
     /**
-     * The number of occupied positions in zzBuffer beyond zzEndRead.
-     * When a lead/high surrogate has been read from the input stream
-     * into the final zzBuffer position, this will have a value of 1;
-     * otherwise, it will have a value of 0.
+     * The number of occupied positions in zzBuffer beyond zzEndRead. When a
+     * lead/high surrogate has been read from the input stream into the final
+     * zzBuffer position, this will have a value of 1; otherwise, it will have a
+     * value of 0.
      */
     private int zzFinalHighSurrogate = 0;
 
@@ -1080,9 +1086,11 @@ public final class ActionScriptLexer {
      */
     private static char[] zzUnpackCMap(String packed) {
         char[] map = new char[0x110000];
-        int i = 0;  /* index in packed string  */
+        int i = 0;
+        /* index in packed string  */
 
-        int j = 0;  /* index in unpacked array */
+        int j = 0;
+        /* index in unpacked array */
 
         while (i < 3136) {
             int count = packed.charAt(i++);
@@ -1141,7 +1149,8 @@ public final class ActionScriptLexer {
 
         if (totalRead > 0) {
             zzEndRead += totalRead;
-            if (totalRead == requested) { /* possibly more input available */
+            if (totalRead == requested) {
+                /* possibly more input available */
 
                 if (Character.isHighSurrogate(zzBuffer[zzEndRead - 1])) {
                     --zzEndRead;
@@ -1159,9 +1168,11 @@ public final class ActionScriptLexer {
      * Closes the input stream.
      */
     public final void yyclose() throws java.io.IOException {
-        zzAtEOF = true;            /* indicate end of file */
+        zzAtEOF = true;
+        /* indicate end of file */
 
-        zzEndRead = zzStartRead;  /* invalidate buffer    */
+        zzEndRead = zzStartRead;
+        /* invalidate buffer    */
 
         if (zzReader != null) {
             zzReader.close();
@@ -1169,12 +1180,12 @@ public final class ActionScriptLexer {
     }
 
     /**
-     * Resets the scanner to read from a new input stream.
-     * Does not close the old reader.
+     * Resets the scanner to read from a new input stream. Does not close the
+     * old reader.
      *
      * All internal variables are reset, the old input stream
-     * cannot be reused (internal buffer is discarded and lost).
-     * Lexical state is set to ZZ_INITIAL.
+     * cannot be reused (internal buffer is discarded and lost). Lexical
+     * state is set to ZZ_INITIAL.
      *
      * Internal scan buffer is resized down to its initial length, if it has
      * grown.
@@ -1220,13 +1231,12 @@ public final class ActionScriptLexer {
     }
 
     /**
-     * Returns the character at position pos from the
-     * matched text.
+     * Returns the character at position pos from the matched text.
      *
      * It is equivalent to yytext().charAt(pos), but faster
      *
-     * @param pos the position of the character to fetch.
-     * A value from 0 to yylength()-1.
+     * @param pos the position of the character to fetch. A value from 0 to
+     * yylength()-1.
      *
      * @return the character at position pos
      */
@@ -1244,14 +1254,13 @@ public final class ActionScriptLexer {
     /**
      * Reports an error that occured while scanning.
      *
-     * In a wellformed scanner (no or only correct usage of
-     * yypushback(int) and a match-all fallback rule) this method
-     * will only be called with things that "Can't Possibly Happen".
-     * If this method is called, something is seriously wrong
-     * (e.g. a JFlex bug producing a faulty scanner etc.).
+     * In a wellformed scanner (no or only correct usage of yypushback(int) and
+     * a match-all fallback rule) this method will only be called with things
+     * that "Can't Possibly Happen". If this method is called, something is
+     * seriously wrong (e.g. a JFlex bug producing a faulty scanner etc.).
      *
-     * Usual syntax/scanner level error handling should be done
-     * in error fallback rules.
+     * Usual syntax/scanner level error handling should be done in error
+     * fallback rules.
      *
      * @param errorCode the code of the errormessage to display
      */
@@ -1271,8 +1280,8 @@ public final class ActionScriptLexer {
      *
      * They will be read again by then next call of the scanning method
      *
-     * @param number the number of characters to be read again.
-     * This number must not be greater than yylength()!
+     * @param number the number of characters to be read again. This number must
+     * not be greater than yylength()!
      */
     public void yypushback(int number) {
         if (number > yylength()) {
@@ -1283,8 +1292,8 @@ public final class ActionScriptLexer {
     }
 
     /**
-     * Resumes scanning until the next regular expression is matched,
-     * the end of input is encountered or an I/O-Error occurs.
+     * Resumes scanning until the next regular expression is matched, the end of
+     * input is encountered or an I/O-Error occurs.
      *
      * @return the next token
      * @exception java.io.IOException if any I/O-Error occurs
@@ -1380,7 +1389,8 @@ public final class ActionScriptLexer {
                 }
                 case 167:
                     break;
-                case 3: { /*ignore*/
+                case 3: {
+                    /*ignore*/
 
                 }
                 case 168:
@@ -1794,7 +1804,8 @@ public final class ActionScriptLexer {
                 }
                 case 242:
                     break;
-                case 78: { /* ignore illegal character escape */
+                case 78: {
+                    /* ignore illegal character escape */
 
                 }
                 case 243:
diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/NameAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/NameAVM2Item.java
index fe36c4106..e59836843 100644
--- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/NameAVM2Item.java
+++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/NameAVM2Item.java
@@ -220,9 +220,9 @@ public class NameAVM2Item extends AssignableAVM2Item {
                 return toSourceMerge(localData, generator,
                         ins(AVM2Instructions.GetScopeObject, slotScope),
                         assignedValue, !(("" + assignedValue.returnType()).equals("" + type) && (basicTypes.contains("" + type))) ? generateCoerce(localData, generator, type) : null, needsReturn
-                                ? dupSetTemp(localData, generator, ret_temp) : null, generateSetLoc(regNumber), slotNumber > -1
-                                ? ins(AVM2Instructions.SetSlot, slotNumber)
-                                : null,
+                        ? dupSetTemp(localData, generator, ret_temp) : null, generateSetLoc(regNumber), slotNumber > -1
+                        ? ins(AVM2Instructions.SetSlot, slotNumber)
+                        : null,
                         needsReturn ? getTemp(localData, generator, ret_temp) : null,
                         killTemp(localData, generator, Arrays.asList(ret_temp)));
             } else {
diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/NamespacedAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/NamespacedAVM2Item.java
index c2db4f69e..8b0f08214 100644
--- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/NamespacedAVM2Item.java
+++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/NamespacedAVM2Item.java
@@ -180,30 +180,28 @@ public class NamespacedAVM2Item extends AssignableAVM2Item {
                         killTemp(localData, generator, Arrays.asList(obj_temp))
                 );
             }
+        } else if (assignedValue != null) {
+            return toSourceMerge(localData, generator,
+                    obj == null ? ns : null, obj == null ? NameAVM2Item.generateCoerce(localData, generator, new TypeItem(DottedChain.NAMESPACE)) : null, obj != null ? obj : ins(AVM2Instructions.FindPropertyStrict, constants.getMultinameId(Multiname.createRTQName(attr, constants.getStringId(name, true)), true)),
+                    ns, NameAVM2Item.generateCoerce(localData, generator, new TypeItem(DottedChain.NAMESPACE)), assignedValue,
+                    needsReturn ? dupSetTemp(localData, generator, ret_temp) : null,
+                    ins(AVM2Instructions.SetProperty, constants.getMultinameId(Multiname.createRTQName(attr, constants.getStringId(name, true)), true)),
+                    needsReturn ? getTemp(localData, generator, ret_temp) : null,
+                    killTemp(localData, generator, Arrays.asList(ns_temp, index_temp, ret_temp))
+            );
         } else {
-            if (assignedValue != null) {
-                return toSourceMerge(localData, generator,
-                        obj == null ? ns : null, obj == null ? NameAVM2Item.generateCoerce(localData, generator, new TypeItem(DottedChain.NAMESPACE)) : null, obj != null ? obj : ins(AVM2Instructions.FindPropertyStrict, constants.getMultinameId(Multiname.createRTQName(attr, constants.getStringId(name, true)), true)),
-                        ns, NameAVM2Item.generateCoerce(localData, generator, new TypeItem(DottedChain.NAMESPACE)), assignedValue,
-                        needsReturn ? dupSetTemp(localData, generator, ret_temp) : null,
-                        ins(AVM2Instructions.SetProperty, constants.getMultinameId(Multiname.createRTQName(attr, constants.getStringId(name, true)), true)),
-                        needsReturn ? getTemp(localData, generator, ret_temp) : null,
-                        killTemp(localData, generator, Arrays.asList(ns_temp, index_temp, ret_temp))
-                );
-            } else {
-                return toSourceMerge(localData, generator,
-                        obj == null ? ns : null, obj == null ? NameAVM2Item.generateCoerce(localData, generator, new TypeItem(DottedChain.NAMESPACE)) : null, obj != null ? obj : ins(AVM2Instructions.FindPropertyStrict, constants.getMultinameId(Multiname.createRTQName(attr, constants.getStringId(name, true)), true)),
-                        call ? dupSetTemp(localData, generator, obj_temp) : null,
-                        ns, NameAVM2Item.generateCoerce(localData, generator, new TypeItem(DottedChain.NAMESPACE)),
-                        construct ? callargs : null,
-                        ins(construct ? AVM2Instructions.ConstructProp : delete ? AVM2Instructions.DeleteProperty : AVM2Instructions.GetProperty, constants.getMultinameId(Multiname.createRTQName(attr, constants.getStringId(name, true)), true), construct ? callargs.size() : null),
-                        call ? getTemp(localData, generator, obj_temp) : null,
-                        call ? callargs : null,
-                        call ? ins(AVM2Instructions.Call, callargs.size()) : null,
-                        needsReturn ? null : ins(AVM2Instructions.Pop),
-                        killTemp(localData, generator, Arrays.asList(obj_temp))
-                );
-            }
+            return toSourceMerge(localData, generator,
+                    obj == null ? ns : null, obj == null ? NameAVM2Item.generateCoerce(localData, generator, new TypeItem(DottedChain.NAMESPACE)) : null, obj != null ? obj : ins(AVM2Instructions.FindPropertyStrict, constants.getMultinameId(Multiname.createRTQName(attr, constants.getStringId(name, true)), true)),
+                    call ? dupSetTemp(localData, generator, obj_temp) : null,
+                    ns, NameAVM2Item.generateCoerce(localData, generator, new TypeItem(DottedChain.NAMESPACE)),
+                    construct ? callargs : null,
+                    ins(construct ? AVM2Instructions.ConstructProp : delete ? AVM2Instructions.DeleteProperty : AVM2Instructions.GetProperty, constants.getMultinameId(Multiname.createRTQName(attr, constants.getStringId(name, true)), true), construct ? callargs.size() : null),
+                    call ? getTemp(localData, generator, obj_temp) : null,
+                    call ? callargs : null,
+                    call ? ins(AVM2Instructions.Call, callargs.size()) : null,
+                    needsReturn ? null : ins(AVM2Instructions.Pop),
+                    killTemp(localData, generator, Arrays.asList(obj_temp))
+            );
         }
     }
 
diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/UnresolvedAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/UnresolvedAVM2Item.java
index c40c93260..83ee345a5 100644
--- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/UnresolvedAVM2Item.java
+++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/UnresolvedAVM2Item.java
@@ -116,12 +116,12 @@ public class UnresolvedAVM2Item extends AssignableAVM2Item {
         }
         return -1;
     }
+
     /*
      public GraphTargetItem getNs() {
      return ns;
      }
      */
-
     public void appendName(String name) {
         this.name = this.name.add(name);
     }
diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/methodinfo_parser/MethodInfoLexer.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/methodinfo_parser/MethodInfoLexer.java
index 540e9d239..0531753b8 100644
--- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/methodinfo_parser/MethodInfoLexer.java
+++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/methodinfo_parser/MethodInfoLexer.java
@@ -1,6 +1,6 @@
 /* The following code was generated by JFlex 1.6.0 */
 
-/*
+ /*
  *  Copyright (C) 2010-2016 JPEXS, All rights reserved.
  *
  * This library is free software; you can redistribute it and/or
@@ -16,13 +16,12 @@
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library.
  */
-/* Method info lexer specification */
+ /* Method info lexer specification */
 package com.jpexs.decompiler.flash.abc.methodinfo_parser;
 
 /**
  * This class is a scanner generated by
- * JFlex 1.6.0
- * from the specification file
+ * JFlex 1.6.0 from the specification file
  * C:/FFDec/jpexs-decompiler/libsrc/ffdec_lib/lexers/actionscript3_methodinfo.flex
  */
 public final class MethodInfoLexer {
@@ -46,9 +45,8 @@ public final class MethodInfoLexer {
 
     /**
      * ZZ_LEXSTATE[l] is the state in the DFA for the lexical state l
-     * ZZ_LEXSTATE[l+1] is the state in the DFA for the lexical state l
-     * at the beginning of a line
-     * l is of the form l = 2*k, k a non negative integer
+     * ZZ_LEXSTATE[l+1] is the state in the DFA for the lexical state l at the
+     * beginning of a line l is of the form l = 2*k, k a non negative integer
      */
     private static final int ZZ_LEXSTATE[] = {
         0, 0, 1, 1
@@ -231,9 +229,11 @@ public final class MethodInfoLexer {
     }
 
     private static int zzUnpackAction(String packed, int offset, int[] result) {
-        int i = 0;       /* index in packed string  */
+        int i = 0;
+        /* index in packed string  */
 
-        int j = offset;  /* index in unpacked array */
+        int j = offset;
+        /* index in unpacked array */
 
         int l = packed.length();
         while (i < l) {
@@ -279,9 +279,11 @@ public final class MethodInfoLexer {
     }
 
     private static int zzUnpackRowMap(String packed, int offset, int[] result) {
-        int i = 0;  /* index in packed string  */
+        int i = 0;
+        /* index in packed string  */
 
-        int j = offset;  /* index in unpacked array */
+        int j = offset;
+        /* index in unpacked array */
 
         int l = packed.length();
         while (i < l) {
@@ -466,9 +468,11 @@ public final class MethodInfoLexer {
     }
 
     private static int zzUnpackTrans(String packed, int offset, int[] result) {
-        int i = 0;       /* index in packed string  */
+        int i = 0;
+        /* index in packed string  */
 
-        int j = offset;  /* index in unpacked array */
+        int j = offset;
+        /* index in unpacked array */
 
         int l = packed.length();
         while (i < l) {
@@ -518,9 +522,11 @@ public final class MethodInfoLexer {
     }
 
     private static int zzUnpackAttribute(String packed, int offset, int[] result) {
-        int i = 0;       /* index in packed string  */
+        int i = 0;
+        /* index in packed string  */
 
-        int j = offset;  /* index in unpacked array */
+        int j = offset;
+        /* index in unpacked array */
 
         int l = packed.length();
         while (i < l) {
@@ -549,8 +555,8 @@ public final class MethodInfoLexer {
     private int zzLexicalState = YYINITIAL;
 
     /**
-     * this buffer contains the current text to be matched and is
-     * the source of the yytext() string
+     * this buffer contains the current text to be matched and is the source of
+     * the yytext() string
      */
     private char zzBuffer[] = new char[ZZ_BUFFERSIZE];
 
@@ -570,8 +576,8 @@ public final class MethodInfoLexer {
     private int zzStartRead;
 
     /**
-     * endRead marks the last character in the buffer, that has been read
-     * from input
+     * endRead marks the last character in the buffer, that has been read from
+     * input
      */
     private int zzEndRead;
 
@@ -607,10 +613,10 @@ public final class MethodInfoLexer {
     private boolean zzEOFDone;
 
     /**
-     * The number of occupied positions in zzBuffer beyond zzEndRead.
-     * When a lead/high surrogate has been read from the input stream
-     * into the final zzBuffer position, this will have a value of 1;
-     * otherwise, it will have a value of 0.
+     * The number of occupied positions in zzBuffer beyond zzEndRead. When a
+     * lead/high surrogate has been read from the input stream into the final
+     * zzBuffer position, this will have a value of 1; otherwise, it will have a
+     * value of 0.
      */
     private int zzFinalHighSurrogate = 0;
 
@@ -654,9 +660,11 @@ public final class MethodInfoLexer {
      */
     private static char[] zzUnpackCMap(String packed) {
         char[] map = new char[0x110000];
-        int i = 0;  /* index in packed string  */
+        int i = 0;
+        /* index in packed string  */
 
-        int j = 0;  /* index in unpacked array */
+        int j = 0;
+        /* index in unpacked array */
 
         while (i < 2868) {
             int count = packed.charAt(i++);
@@ -715,7 +723,8 @@ public final class MethodInfoLexer {
 
         if (totalRead > 0) {
             zzEndRead += totalRead;
-            if (totalRead == requested) { /* possibly more input available */
+            if (totalRead == requested) {
+                /* possibly more input available */
 
                 if (Character.isHighSurrogate(zzBuffer[zzEndRead - 1])) {
                     --zzEndRead;
@@ -733,9 +742,11 @@ public final class MethodInfoLexer {
      * Closes the input stream.
      */
     public final void yyclose() throws java.io.IOException {
-        zzAtEOF = true;            /* indicate end of file */
+        zzAtEOF = true;
+        /* indicate end of file */
 
-        zzEndRead = zzStartRead;  /* invalidate buffer    */
+        zzEndRead = zzStartRead;
+        /* invalidate buffer    */
 
         if (zzReader != null) {
             zzReader.close();
@@ -743,12 +754,12 @@ public final class MethodInfoLexer {
     }
 
     /**
-     * Resets the scanner to read from a new input stream.
-     * Does not close the old reader.
+     * Resets the scanner to read from a new input stream. Does not close the
+     * old reader.
      *
      * All internal variables are reset, the old input stream
-     * cannot be reused (internal buffer is discarded and lost).
-     * Lexical state is set to ZZ_INITIAL.
+     * cannot be reused (internal buffer is discarded and lost). Lexical
+     * state is set to ZZ_INITIAL.
      *
      * Internal scan buffer is resized down to its initial length, if it has
      * grown.
@@ -794,13 +805,12 @@ public final class MethodInfoLexer {
     }
 
     /**
-     * Returns the character at position pos from the
-     * matched text.
+     * Returns the character at position pos from the matched text.
      *
      * It is equivalent to yytext().charAt(pos), but faster
      *
-     * @param pos the position of the character to fetch.
-     * A value from 0 to yylength()-1.
+     * @param pos the position of the character to fetch. A value from 0 to
+     * yylength()-1.
      *
      * @return the character at position pos
      */
@@ -818,14 +828,13 @@ public final class MethodInfoLexer {
     /**
      * Reports an error that occured while scanning.
      *
-     * In a wellformed scanner (no or only correct usage of
-     * yypushback(int) and a match-all fallback rule) this method
-     * will only be called with things that "Can't Possibly Happen".
-     * If this method is called, something is seriously wrong
-     * (e.g. a JFlex bug producing a faulty scanner etc.).
+     * In a wellformed scanner (no or only correct usage of yypushback(int) and
+     * a match-all fallback rule) this method will only be called with things
+     * that "Can't Possibly Happen". If this method is called, something is
+     * seriously wrong (e.g. a JFlex bug producing a faulty scanner etc.).
      *
-     * Usual syntax/scanner level error handling should be done
-     * in error fallback rules.
+     * Usual syntax/scanner level error handling should be done in error
+     * fallback rules.
      *
      * @param errorCode the code of the errormessage to display
      */
@@ -845,8 +854,8 @@ public final class MethodInfoLexer {
      *
      * They will be read again by then next call of the scanning method
      *
-     * @param number the number of characters to be read again.
-     * This number must not be greater than yylength()!
+     * @param number the number of characters to be read again. This number must
+     * not be greater than yylength()!
      */
     public void yypushback(int number) {
         if (number > yylength()) {
@@ -857,8 +866,8 @@ public final class MethodInfoLexer {
     }
 
     /**
-     * Resumes scanning until the next regular expression is matched,
-     * the end of input is encountered or an I/O-Error occurs.
+     * Resumes scanning until the next regular expression is matched, the end of
+     * input is encountered or an I/O-Error occurs.
      *
      * @return the next token
      * @exception java.io.IOException if any I/O-Error occurs
diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/Action.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/Action.java
index 89a9cefc8..53b0bc1bc 100644
--- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/Action.java
+++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/Action.java
@@ -568,7 +568,7 @@ public abstract class Action implements GraphSourceItem {
 
                                 writer.appendNoHilight(Helper.byteToHex(fileData[(int) (fileOffset + i)]));
                             }
-                            
+
                             writer.appendNoHilight(")");
                         }
 
@@ -1114,7 +1114,7 @@ public abstract class Action implements GraphSourceItem {
             }
 
             /*ActionJump && ActionIf removed*/
-            /*if ((action instanceof ActionEnumerate2) || (action instanceof ActionEnumerate)) {
+ /*if ((action instanceof ActionEnumerate2) || (action instanceof ActionEnumerate)) {
              loopStart = ip + 1;
              isForIn = true;
              ip += 4;
diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/FunctionActionItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/FunctionActionItem.java
index b970960e7..93cb192c3 100644
--- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/FunctionActionItem.java
+++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/FunctionActionItem.java
@@ -308,16 +308,12 @@ public class FunctionActionItem extends ActionItem {
                     } else {
                         v.setBoxedValue(new DirectValueActionItem(new RegisterNumber(registerNames.indexOf(varName), varName)));
                     }
+                } else if (v.isDefinition()) {
+                    v.setBoxedValue(new DefineLocalActionItem(null, null, ((ActionSourceGenerator) generator).pushConstTargetItem(varName), stored));
+                } else if (stored != null) {
+                    v.setBoxedValue(new SetVariableActionItem(null, null, ((ActionSourceGenerator) generator).pushConstTargetItem(varName), stored));
                 } else {
-                    if (v.isDefinition()) {
-                        v.setBoxedValue(new DefineLocalActionItem(null, null, ((ActionSourceGenerator) generator).pushConstTargetItem(varName), stored));
-                    } else {
-                        if (stored != null) {
-                            v.setBoxedValue(new SetVariableActionItem(null, null, ((ActionSourceGenerator) generator).pushConstTargetItem(varName), stored));
-                        } else {
-                            v.setBoxedValue(new GetVariableActionItem(null, null, ((ActionSourceGenerator) generator).pushConstTargetItem(varName)));
-                        }
-                    }
+                    v.setBoxedValue(new GetVariableActionItem(null, null, ((ActionSourceGenerator) generator).pushConstTargetItem(varName)));
                 }
 
             }
diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/pcode/FlasmLexer.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/pcode/FlasmLexer.java
index b9e8ba77d..81b68d4e9 100644
--- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/pcode/FlasmLexer.java
+++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/pcode/FlasmLexer.java
@@ -1,6 +1,6 @@
 /* The following code was generated by JFlex 1.6.0 */
 
-/*
+ /*
  *  Copyright (C) 2010-2016 JPEXS, All rights reserved.
  *
  * This library is free software; you can redistribute it and/or
@@ -16,7 +16,7 @@
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library.
  */
-/* Flash assembler language lexer specification */
+ /* Flash assembler language lexer specification */
 package com.jpexs.decompiler.flash.action.parser.pcode;
 
 import com.jpexs.decompiler.flash.action.parser.ActionParseException;
@@ -27,8 +27,7 @@ import com.jpexs.decompiler.flash.ecma.Undefined;
 
 /**
  * This class is a scanner generated by
- * JFlex 1.6.0
- * from the specification file
+ * JFlex 1.6.0 from the specification file
  * C:/Dropbox/Programovani/JavaSE/FFDec/libsrc/ffdec_lib/lexers/actionscript_pcode.flex
  */
 public final class FlasmLexer {
@@ -54,9 +53,8 @@ public final class FlasmLexer {
 
     /**
      * ZZ_LEXSTATE[l] is the state in the DFA for the lexical state l
-     * ZZ_LEXSTATE[l+1] is the state in the DFA for the lexical state l
-     * at the beginning of a line
-     * l is of the form l = 2*k, k a non negative integer
+     * ZZ_LEXSTATE[l+1] is the state in the DFA for the lexical state l at the
+     * beginning of a line l is of the form l = 2*k, k a non negative integer
      */
     private static final int ZZ_LEXSTATE[] = {
         0, 0, 1, 1, 2, 2
@@ -238,9 +236,11 @@ public final class FlasmLexer {
     }
 
     private static int zzUnpackAction(String packed, int offset, int[] result) {
-        int i = 0;       /* index in packed string  */
+        int i = 0;
+        /* index in packed string  */
 
-        int j = offset;  /* index in unpacked array */
+        int j = offset;
+        /* index in unpacked array */
 
         int l = packed.length();
         while (i < l) {
@@ -282,9 +282,11 @@ public final class FlasmLexer {
     }
 
     private static int zzUnpackRowMap(String packed, int offset, int[] result) {
-        int i = 0;  /* index in packed string  */
+        int i = 0;
+        /* index in packed string  */
 
-        int j = offset;  /* index in unpacked array */
+        int j = offset;
+        /* index in unpacked array */
 
         int l = packed.length();
         while (i < l) {
@@ -458,9 +460,11 @@ public final class FlasmLexer {
     }
 
     private static int zzUnpackTrans(String packed, int offset, int[] result) {
-        int i = 0;       /* index in packed string  */
+        int i = 0;
+        /* index in packed string  */
 
-        int j = offset;  /* index in unpacked array */
+        int j = offset;
+        /* index in unpacked array */
 
         int l = packed.length();
         while (i < l) {
@@ -510,9 +514,11 @@ public final class FlasmLexer {
     }
 
     private static int zzUnpackAttribute(String packed, int offset, int[] result) {
-        int i = 0;       /* index in packed string  */
+        int i = 0;
+        /* index in packed string  */
 
-        int j = offset;  /* index in unpacked array */
+        int j = offset;
+        /* index in unpacked array */
 
         int l = packed.length();
         while (i < l) {
@@ -541,8 +547,8 @@ public final class FlasmLexer {
     private int zzLexicalState = YYINITIAL;
 
     /**
-     * this buffer contains the current text to be matched and is
-     * the source of the yytext() string
+     * this buffer contains the current text to be matched and is the source of
+     * the yytext() string
      */
     private char zzBuffer[] = new char[ZZ_BUFFERSIZE];
 
@@ -562,8 +568,8 @@ public final class FlasmLexer {
     private int zzStartRead;
 
     /**
-     * endRead marks the last character in the buffer, that has been read
-     * from input
+     * endRead marks the last character in the buffer, that has been read from
+     * input
      */
     private int zzEndRead;
 
@@ -599,10 +605,10 @@ public final class FlasmLexer {
     private boolean zzEOFDone;
 
     /**
-     * The number of occupied positions in zzBuffer beyond zzEndRead.
-     * When a lead/high surrogate has been read from the input stream
-     * into the final zzBuffer position, this will have a value of 1;
-     * otherwise, it will have a value of 0.
+     * The number of occupied positions in zzBuffer beyond zzEndRead. When a
+     * lead/high surrogate has been read from the input stream into the final
+     * zzBuffer position, this will have a value of 1; otherwise, it will have a
+     * value of 0.
      */
     private int zzFinalHighSurrogate = 0;
 
@@ -642,9 +648,11 @@ public final class FlasmLexer {
      */
     private static char[] zzUnpackCMap(String packed) {
         char[] map = new char[0x110000];
-        int i = 0;  /* index in packed string  */
+        int i = 0;
+        /* index in packed string  */
 
-        int j = 0;  /* index in unpacked array */
+        int j = 0;
+        /* index in unpacked array */
 
         while (i < 2854) {
             int count = packed.charAt(i++);
@@ -703,7 +711,8 @@ public final class FlasmLexer {
 
         if (totalRead > 0) {
             zzEndRead += totalRead;
-            if (totalRead == requested) { /* possibly more input available */
+            if (totalRead == requested) {
+                /* possibly more input available */
 
                 if (Character.isHighSurrogate(zzBuffer[zzEndRead - 1])) {
                     --zzEndRead;
@@ -721,9 +730,11 @@ public final class FlasmLexer {
      * Closes the input stream.
      */
     public final void yyclose() throws java.io.IOException {
-        zzAtEOF = true;            /* indicate end of file */
+        zzAtEOF = true;
+        /* indicate end of file */
 
-        zzEndRead = zzStartRead;  /* invalidate buffer    */
+        zzEndRead = zzStartRead;
+        /* invalidate buffer    */
 
         if (zzReader != null) {
             zzReader.close();
@@ -731,12 +742,12 @@ public final class FlasmLexer {
     }
 
     /**
-     * Resets the scanner to read from a new input stream.
-     * Does not close the old reader.
+     * Resets the scanner to read from a new input stream. Does not close the
+     * old reader.
      *
      * All internal variables are reset, the old input stream
-     * cannot be reused (internal buffer is discarded and lost).
-     * Lexical state is set to ZZ_INITIAL.
+     * cannot be reused (internal buffer is discarded and lost). Lexical
+     * state is set to ZZ_INITIAL.
      *
      * Internal scan buffer is resized down to its initial length, if it has
      * grown.
@@ -782,13 +793,12 @@ public final class FlasmLexer {
     }
 
     /**
-     * Returns the character at position pos from the
-     * matched text.
+     * Returns the character at position pos from the matched text.
      *
      * It is equivalent to yytext().charAt(pos), but faster
      *
-     * @param pos the position of the character to fetch.
-     * A value from 0 to yylength()-1.
+     * @param pos the position of the character to fetch. A value from 0 to
+     * yylength()-1.
      *
      * @return the character at position pos
      */
@@ -806,14 +816,13 @@ public final class FlasmLexer {
     /**
      * Reports an error that occured while scanning.
      *
-     * In a wellformed scanner (no or only correct usage of
-     * yypushback(int) and a match-all fallback rule) this method
-     * will only be called with things that "Can't Possibly Happen".
-     * If this method is called, something is seriously wrong
-     * (e.g. a JFlex bug producing a faulty scanner etc.).
+     * In a wellformed scanner (no or only correct usage of yypushback(int) and
+     * a match-all fallback rule) this method will only be called with things
+     * that "Can't Possibly Happen". If this method is called, something is
+     * seriously wrong (e.g. a JFlex bug producing a faulty scanner etc.).
      *
-     * Usual syntax/scanner level error handling should be done
-     * in error fallback rules.
+     * Usual syntax/scanner level error handling should be done in error
+     * fallback rules.
      *
      * @param errorCode the code of the errormessage to display
      */
@@ -833,8 +842,8 @@ public final class FlasmLexer {
      *
      * They will be read again by then next call of the scanning method
      *
-     * @param number the number of characters to be read again.
-     * This number must not be greater than yylength()!
+     * @param number the number of characters to be read again. This number must
+     * not be greater than yylength()!
      */
     public void yypushback(int number) {
         if (number > yylength()) {
@@ -845,8 +854,8 @@ public final class FlasmLexer {
     }
 
     /**
-     * Resumes scanning until the next regular expression is matched,
-     * the end of input is encountered or an I/O-Error occurs.
+     * Resumes scanning until the next regular expression is matched, the end of
+     * input is encountered or an I/O-Error occurs.
      *
      * @return the next token
      * @exception java.io.IOException if any I/O-Error occurs
diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/script/ActionScriptLexer.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/script/ActionScriptLexer.java
index 29d96d52e..21ebb8b7b 100644
--- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/script/ActionScriptLexer.java
+++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/script/ActionScriptLexer.java
@@ -1,6 +1,6 @@
 /* The following code was generated by JFlex 1.6.0 */
 
-/*
+ /*
  *  Copyright (C) 2010-2016 JPEXS, All rights reserved.
  *
  * This library is free software; you can redistribute it and/or
@@ -25,8 +25,7 @@ import java.util.Stack;
 
 /**
  * This class is a scanner generated by
- * JFlex 1.6.0
- * from the specification file
+ * JFlex 1.6.0 from the specification file
  * D:/Dropbox/Programovani/JavaSE/FFDec/libsrc/ffdec_lib/lexers/actionscript_script.flex
  */
 public final class ActionScriptLexer {
@@ -58,9 +57,8 @@ public final class ActionScriptLexer {
 
     /**
      * ZZ_LEXSTATE[l] is the state in the DFA for the lexical state l
-     * ZZ_LEXSTATE[l+1] is the state in the DFA for the lexical state l
-     * at the beginning of a line
-     * l is of the form l = 2*k, k a non negative integer
+     * ZZ_LEXSTATE[l+1] is the state in the DFA for the lexical state l at the
+     * beginning of a line l is of the form l = 2*k, k a non negative integer
      */
     private static final int ZZ_LEXSTATE[] = {
         0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5
@@ -278,9 +276,11 @@ public final class ActionScriptLexer {
     }
 
     private static int zzUnpackAction(String packed, int offset, int[] result) {
-        int i = 0;       /* index in packed string  */
+        int i = 0;
+        /* index in packed string  */
 
-        int j = offset;  /* index in unpacked array */
+        int j = offset;
+        /* index in unpacked array */
 
         int l = packed.length();
         while (i < l) {
@@ -395,9 +395,11 @@ public final class ActionScriptLexer {
     }
 
     private static int zzUnpackRowMap(String packed, int offset, int[] result) {
-        int i = 0;  /* index in packed string  */
+        int i = 0;
+        /* index in packed string  */
 
-        int j = offset;  /* index in unpacked array */
+        int j = offset;
+        /* index in unpacked array */
 
         int l = packed.length();
         while (i < l) {
@@ -1100,9 +1102,11 @@ public final class ActionScriptLexer {
     }
 
     private static int zzUnpackTrans(String packed, int offset, int[] result) {
-        int i = 0;       /* index in packed string  */
+        int i = 0;
+        /* index in packed string  */
 
-        int j = offset;  /* index in unpacked array */
+        int j = offset;
+        /* index in unpacked array */
 
         int l = packed.length();
         while (i < l) {
@@ -1157,9 +1161,11 @@ public final class ActionScriptLexer {
     }
 
     private static int zzUnpackAttribute(String packed, int offset, int[] result) {
-        int i = 0;       /* index in packed string  */
+        int i = 0;
+        /* index in packed string  */
 
-        int j = offset;  /* index in unpacked array */
+        int j = offset;
+        /* index in unpacked array */
 
         int l = packed.length();
         while (i < l) {
@@ -1188,8 +1194,8 @@ public final class ActionScriptLexer {
     private int zzLexicalState = YYINITIAL;
 
     /**
-     * this buffer contains the current text to be matched and is
-     * the source of the yytext() string
+     * this buffer contains the current text to be matched and is the source of
+     * the yytext() string
      */
     private char zzBuffer[] = new char[ZZ_BUFFERSIZE];
 
@@ -1209,8 +1215,8 @@ public final class ActionScriptLexer {
     private int zzStartRead;
 
     /**
-     * endRead marks the last character in the buffer, that has been read
-     * from input
+     * endRead marks the last character in the buffer, that has been read from
+     * input
      */
     private int zzEndRead;
 
@@ -1246,10 +1252,10 @@ public final class ActionScriptLexer {
     private boolean zzEOFDone;
 
     /**
-     * The number of occupied positions in zzBuffer beyond zzEndRead.
-     * When a lead/high surrogate has been read from the input stream
-     * into the final zzBuffer position, this will have a value of 1;
-     * otherwise, it will have a value of 0.
+     * The number of occupied positions in zzBuffer beyond zzEndRead. When a
+     * lead/high surrogate has been read from the input stream into the final
+     * zzBuffer position, this will have a value of 1; otherwise, it will have a
+     * value of 0.
      */
     private int zzFinalHighSurrogate = 0;
 
@@ -1326,9 +1332,11 @@ public final class ActionScriptLexer {
      */
     private static char[] zzUnpackCMap(String packed) {
         char[] map = new char[0x110000];
-        int i = 0;  /* index in packed string  */
+        int i = 0;
+        /* index in packed string  */
 
-        int j = 0;  /* index in unpacked array */
+        int j = 0;
+        /* index in unpacked array */
 
         while (i < 2916) {
             int count = packed.charAt(i++);
@@ -1387,7 +1395,8 @@ public final class ActionScriptLexer {
 
         if (totalRead > 0) {
             zzEndRead += totalRead;
-            if (totalRead == requested) { /* possibly more input available */
+            if (totalRead == requested) {
+                /* possibly more input available */
 
                 if (Character.isHighSurrogate(zzBuffer[zzEndRead - 1])) {
                     --zzEndRead;
@@ -1405,9 +1414,11 @@ public final class ActionScriptLexer {
      * Closes the input stream.
      */
     public final void yyclose() throws java.io.IOException {
-        zzAtEOF = true;            /* indicate end of file */
+        zzAtEOF = true;
+        /* indicate end of file */
 
-        zzEndRead = zzStartRead;  /* invalidate buffer    */
+        zzEndRead = zzStartRead;
+        /* invalidate buffer    */
 
         if (zzReader != null) {
             zzReader.close();
@@ -1415,12 +1426,12 @@ public final class ActionScriptLexer {
     }
 
     /**
-     * Resets the scanner to read from a new input stream.
-     * Does not close the old reader.
+     * Resets the scanner to read from a new input stream. Does not close the
+     * old reader.
      *
      * All internal variables are reset, the old input stream
-     * cannot be reused (internal buffer is discarded and lost).
-     * Lexical state is set to ZZ_INITIAL.
+     * cannot be reused (internal buffer is discarded and lost). Lexical
+     * state is set to ZZ_INITIAL.
      *
      * Internal scan buffer is resized down to its initial length, if it has
      * grown.
@@ -1466,13 +1477,12 @@ public final class ActionScriptLexer {
     }
 
     /**
-     * Returns the character at position pos from the
-     * matched text.
+     * Returns the character at position pos from the matched text.
      *
      * It is equivalent to yytext().charAt(pos), but faster
      *
-     * @param pos the position of the character to fetch.
-     * A value from 0 to yylength()-1.
+     * @param pos the position of the character to fetch. A value from 0 to
+     * yylength()-1.
      *
      * @return the character at position pos
      */
@@ -1490,14 +1500,13 @@ public final class ActionScriptLexer {
     /**
      * Reports an error that occured while scanning.
      *
-     * In a wellformed scanner (no or only correct usage of
-     * yypushback(int) and a match-all fallback rule) this method
-     * will only be called with things that "Can't Possibly Happen".
-     * If this method is called, something is seriously wrong
-     * (e.g. a JFlex bug producing a faulty scanner etc.).
+     * In a wellformed scanner (no or only correct usage of yypushback(int) and
+     * a match-all fallback rule) this method will only be called with things
+     * that "Can't Possibly Happen". If this method is called, something is
+     * seriously wrong (e.g. a JFlex bug producing a faulty scanner etc.).
      *
-     * Usual syntax/scanner level error handling should be done
-     * in error fallback rules.
+     * Usual syntax/scanner level error handling should be done in error
+     * fallback rules.
      *
      * @param errorCode the code of the errormessage to display
      */
@@ -1517,8 +1526,8 @@ public final class ActionScriptLexer {
      *
      * They will be read again by then next call of the scanning method
      *
-     * @param number the number of characters to be read again.
-     * This number must not be greater than yylength()!
+     * @param number the number of characters to be read again. This number must
+     * not be greater than yylength()!
      */
     public void yypushback(int number) {
         if (number > yylength()) {
@@ -1529,8 +1538,8 @@ public final class ActionScriptLexer {
     }
 
     /**
-     * Resumes scanning until the next regular expression is matched,
-     * the end of input is encountered or an I/O-Error occurs.
+     * Resumes scanning until the next regular expression is matched, the end of
+     * input is encountered or an I/O-Error occurs.
      *
      * @return the next token
      * @exception java.io.IOException if any I/O-Error occurs
@@ -1626,7 +1635,8 @@ public final class ActionScriptLexer {
                 }
                 case 185:
                     break;
-                case 3: { /*ignore*/
+                case 3: {
+                    /*ignore*/
 
                 }
                 case 186:
@@ -1963,7 +1973,8 @@ public final class ActionScriptLexer {
                 case 250:
                     break;
                 case 68: {
-                    string.append('\\'); /*illegal escape sequence*/
+                    string.append('\\');
+                    /*illegal escape sequence*/
 
                 }
                 case 251:
diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/docs/docs.js b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/docs/docs.js
index beeac0b56..d0f438957 100644
--- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/docs/docs.js
+++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/docs/docs.js
@@ -1,152 +1,152 @@
 function bind(el, evt, func) {
-    if (el.addEventListener){
+    if (el.addEventListener) {
         el.addEventListener(evt, func, false);
     } else if (el.attachEvent) {
         el.attachEvent('on' + evt, func);
     }
 }
 
-function showhide(e,show){
-    var cls = " "+e.className+" ";
-      if(show && cls.indexOf(" hidden ") > -1){
-            cls = cls.replace(" hidden "," ");
-        }else if(!show && cls.indexOf(" hidden ") == -1 ){
-            cls = cls + "hidden ";
-        }
-        cls = cls.trim();
-        e.className = cls;
-}
-
-function hideNoName(name){
-   var lis = document.getElementsByTagName("li");
-    loopi:for(var i=0;i