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 4062f60d7..1b7283dda 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 @@ -1059,6 +1059,42 @@ public class ABC { } } + + public void addClass(ClassInfo ci, InstanceInfo ii,int index){ + for (MethodBody b : bodies) { + for (AVM2Instruction ins : b.getCode().code) { + for (int i = 0; i < ins.definition.operands.length; i++) { + if (ins.definition.operands[i] == AVM2Code.DAT_CLASS_INDEX) { + if (ins.operands[i] >= index) { + ins.operands[i]++; + } + } + } + } + } + for (ScriptInfo si : script_info) { + addClassInTraits(si.traits, index); + } + for (MethodBody b : bodies) { + addClassInTraits(b.traits, index); + } + instance_info.add(index,ii); + class_info.add(index,ci); + } + + private void addClassInTraits(Traits traits, int index) { + for (Trait t : traits.traits) { + if (t instanceof TraitClass) { + TraitClass tc = (TraitClass) t; + addClassInTraits(instance_info.get(tc.class_info).instance_traits, index); + addClassInTraits(class_info.get(tc.class_info).static_traits, index); + if (tc.class_info >= index) { + tc.class_info++; + } + } + } + } + public void removeClass(int index) { for (MethodBody b : bodies) { for (AVM2Instruction ins : b.getCode().code) { @@ -1179,8 +1215,17 @@ public class ABC { } boolean isDocumentClass = documentClass.equals(pack.getPath().toString()); - script_info.get(oldIndex).delete(this, true); - ActionScriptParser.compile(as, this, new ArrayList(), isDocumentClass, scriptName); + + ScriptInfo si=script_info.get(oldIndex); + si.delete(this, true); + int newClassIndex = instance_info.size(); + for(Trait t:si.traits.traits){ + if(t instanceof TraitClass){ + TraitClass tc=(TraitClass)t; + newClassIndex = tc.class_info+1; + } + } + ActionScriptParser.compile(as, this, new ArrayList(), isDocumentClass, scriptName,newClassIndex); //Move newly added script to its position script_info.set(oldIndex, script_info.get(newIndex)); script_info.remove(newIndex); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/AVM2SourceGenerator.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/AVM2SourceGenerator.java index 1f716fc3a..200b005a4 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/AVM2SourceGenerator.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/AVM2SourceGenerator.java @@ -1169,7 +1169,7 @@ public class AVM2SourceGenerator implements SourceGenerator { return abc; } - public void generateClass(List importedClasses, List sinitVariables, boolean staticNeedsActivation, List staticInit, List openedNamespaces, int namespace, int initScope, String pkg, ClassInfo classInfo, InstanceInfo instanceInfo, SourceGeneratorLocalData localData, boolean isInterface, String name, String superName, GraphTargetItem extendsVal, List implementsStr, GraphTargetItem constructor, List traitItems) throws AVM2ParseException, CompilationException { + public void generateClass(List importedClasses, List sinitVariables, boolean staticNeedsActivation, List staticInit, List openedNamespaces, int namespace, int initScope, String pkg, ClassInfo classInfo, InstanceInfo instanceInfo, SourceGeneratorLocalData localData, boolean isInterface, String name, String superName, GraphTargetItem extendsVal, List implementsStr, GraphTargetItem constructor, List traitItems,Reference class_index) throws AVM2ParseException, CompilationException { localData.currentClass = name; localData.pkg = pkg; List ret = new ArrayList<>(); @@ -1180,12 +1180,12 @@ public class AVM2SourceGenerator implements SourceGenerator { instanceInfo.name_index = traitName(namespace, name); - Trait[] it = generateTraitsPhase1(name, superName, false, localData, traitItems, instanceInfo.instance_traits); - Trait[] st = generateTraitsPhase1(name, superName, true, localData, traitItems, classInfo.static_traits); + Trait[] it = generateTraitsPhase1(name, superName, false, localData, traitItems, instanceInfo.instance_traits,class_index); + Trait[] st = generateTraitsPhase1(name, superName, true, localData, traitItems, classInfo.static_traits,class_index); generateTraitsPhase2(importedClasses, pkg, traitItems, it, openedNamespaces, localData); generateTraitsPhase2(importedClasses, pkg, traitItems, st, openedNamespaces, localData); - generateTraitsPhase3(initScope, isInterface, name, superName, false, localData, traitItems, instanceInfo.instance_traits, it, new HashMap()); - generateTraitsPhase3(initScope, isInterface, name, superName, true, localData, traitItems, classInfo.static_traits, st, new HashMap()); + generateTraitsPhase3(initScope, isInterface, name, superName, false, localData, traitItems, instanceInfo.instance_traits, it, new HashMap(),class_index); + generateTraitsPhase3(initScope, isInterface, name, superName, true, localData, traitItems, classInfo.static_traits, st, new HashMap(),class_index); int init = 0; if (constructor == null || isInterface) { instanceInfo.iinit_index = init = method(isInterface, new ArrayList(), pkg, false, new ArrayList(), initScope + 1, false, 0, isInterface ? null : name, extendsVal != null ? extendsVal.toString() : null, true, localData, new ArrayList(), new ArrayList(), new ArrayList(), new ArrayList(), TypeItem.UNBOUNDED/*?? FIXME*/); @@ -1272,7 +1272,7 @@ public class AVM2SourceGenerator implements SourceGenerator { return ret; } - public int generateClass(int namespace, ClassInfo ci, InstanceInfo ii, int initScope, String pkg, SourceGeneratorLocalData localData, AVM2Item cls) throws AVM2ParseException, CompilationException { + public int generateClass(int namespace, ClassInfo ci, InstanceInfo ii, int initScope, String pkg, SourceGeneratorLocalData localData, AVM2Item cls, Reference class_index) throws AVM2ParseException, CompilationException { /*ClassInfo ci = new ClassInfo(); InstanceInfo ii = new InstanceInfo(); abc.class_info.add(ci); @@ -1280,7 +1280,7 @@ public class AVM2SourceGenerator implements SourceGenerator { */ if (cls instanceof ClassAVM2Item) { ClassAVM2Item cai = (ClassAVM2Item) cls; - generateClass(cai.importedClasses, cai.sinitVariables, cai.staticInitActivation, cai.staticInit, cai.openedNamespaces, namespace, initScope, pkg, ci, ii, localData, false, cai.className, cai.extendsOp == null ? "Object" : cai.extendsOp.toString(), cai.extendsOp, cai.implementsOp, cai.constructor, cai.traits); + generateClass(cai.importedClasses, cai.sinitVariables, cai.staticInitActivation, cai.staticInit, cai.openedNamespaces, namespace, initScope, pkg, ci, ii, localData, false, cai.className, cai.extendsOp == null ? "Object" : cai.extendsOp.toString(), cai.extendsOp, cai.implementsOp, cai.constructor, cai.traits,class_index); if (!cai.isDynamic) { ii.flags |= InstanceInfo.CLASS_SEALED; } @@ -1294,7 +1294,7 @@ public class AVM2SourceGenerator implements SourceGenerator { InterfaceAVM2Item iai = (InterfaceAVM2Item) cls; ii.flags |= InstanceInfo.CLASS_INTERFACE; ii.flags |= InstanceInfo.CLASS_SEALED; - generateClass(iai.importedClasses, new ArrayList(), false, new ArrayList(), iai.openedNamespaces, namespace, initScope, pkg, ci, ii, localData, true, iai.name, null, null, iai.superInterfaces, null, iai.methods); + generateClass(iai.importedClasses, new ArrayList(), false, new ArrayList(), iai.openedNamespaces, namespace, initScope, pkg, ci, ii, localData, true, iai.name, null, null, iai.superInterfaces, null, iai.methods,class_index); } return abc.instance_info.size() - 1; @@ -1907,7 +1907,7 @@ public class AVM2SourceGenerator implements SourceGenerator { } - public void generateTraitsPhase3(int methodInitScope, boolean isInterface, String className, String superName, boolean generateStatic, SourceGeneratorLocalData localData, List items, Traits ts, Trait[] traits, Map initScopes) throws AVM2ParseException, CompilationException { + public void generateTraitsPhase3(int methodInitScope, boolean isInterface, String className, String superName, boolean generateStatic, SourceGeneratorLocalData localData, List items, Traits ts, Trait[] traits, Map initScopes,Reference class_index) throws AVM2ParseException, CompilationException { //Note: Names must be generated first before accesed in inner subs for (int k = 0; k < items.size(); k++) { GraphTargetItem item = items.get(k); @@ -1915,11 +1915,11 @@ public class AVM2SourceGenerator implements SourceGenerator { continue; } if (item instanceof InterfaceAVM2Item) { - generateClass(((InterfaceAVM2Item) item).namespace, abc.class_info.get(((TraitClass) traits[k]).class_info), abc.instance_info.get(((TraitClass) traits[k]).class_info), initScopes.get(traits[k]), ((InterfaceAVM2Item) item).pkg, localData, (InterfaceAVM2Item) item); + generateClass(((InterfaceAVM2Item) item).namespace, abc.class_info.get(((TraitClass) traits[k]).class_info), abc.instance_info.get(((TraitClass) traits[k]).class_info), initScopes.get(traits[k]), ((InterfaceAVM2Item) item).pkg, localData, (InterfaceAVM2Item) item,class_index); } if (item instanceof ClassAVM2Item) { - generateClass(((ClassAVM2Item) item).namespace, abc.class_info.get(((TraitClass) traits[k]).class_info), abc.instance_info.get(((TraitClass) traits[k]).class_info), initScopes.get(traits[k]), ((ClassAVM2Item) item).pkg, localData, (ClassAVM2Item) item); + generateClass(((ClassAVM2Item) item).namespace, abc.class_info.get(((TraitClass) traits[k]).class_info), abc.instance_info.get(((TraitClass) traits[k]).class_info), initScopes.get(traits[k]), ((ClassAVM2Item) item).pkg, localData, (ClassAVM2Item) item,class_index); } if ((item instanceof MethodAVM2Item) || (item instanceof GetterAVM2Item) || (item instanceof SetterAVM2Item)) { MethodAVM2Item mai = (MethodAVM2Item) item; @@ -1934,7 +1934,7 @@ public class AVM2SourceGenerator implements SourceGenerator { } } - public Trait[] generateTraitsPhase1(String className, String superName, boolean generateStatic, SourceGeneratorLocalData localData, List items, Traits ts) throws AVM2ParseException, CompilationException { + public Trait[] generateTraitsPhase1(String className, String superName, boolean generateStatic, SourceGeneratorLocalData localData, List items, Traits ts, Reference classIndex) throws AVM2ParseException, CompilationException { Trait[] traits = new Trait[items.size()]; int slot_id = 1; int disp_id = 3; //1 and 2 are for constructor @@ -1944,10 +1944,13 @@ public class AVM2SourceGenerator implements SourceGenerator { TraitClass tc = new TraitClass(); ClassInfo ci = new ClassInfo(); InstanceInfo ii = new InstanceInfo(); - abc.class_info.add(ci); - abc.instance_info.add(ii); + /*abc.class_info.add(ci); + abc.instance_info.add(ii);*/ + tc.class_info = classIndex.getVal(); + abc.addClass(ci, ii, classIndex.getVal()); + classIndex.setVal(classIndex.getVal()+1); ii.flags |= InstanceInfo.CLASS_INTERFACE; - tc.class_info = abc.instance_info.size() - 1; + //tc.class_info = abc.instance_info.size() - 1; tc.kindType = Trait.TRAIT_CLASS; //tc.name_index = traitName(((InterfaceAVM2Item) item).namespace, ((InterfaceAVM2Item) item).name); tc.slot_id = 0; //? @@ -1958,10 +1961,13 @@ public class AVM2SourceGenerator implements SourceGenerator { if (item instanceof ClassAVM2Item) { TraitClass tc = new TraitClass(); ClassInfo ci = new ClassInfo(); - InstanceInfo instanceInfo = new InstanceInfo(); - abc.class_info.add(ci); - abc.instance_info.add(instanceInfo); - tc.class_info = abc.instance_info.size() - 1; + InstanceInfo ii = new InstanceInfo(); + /*abc.class_info.add(ci); + abc.instance_info.add(instanceInfo);*/ + tc.class_info = classIndex.getVal(); + abc.addClass(ci, ii, classIndex.getVal()); + classIndex.setVal(classIndex.getVal()+1); + //tc.class_info = abc.instance_info.size() - 1; /*instanceInfo.name_index = abc.constants.addMultiname(new Multiname(Multiname.QNAME, abc.constants.getStringId(((ClassAVM2Item) item).className, true), abc.constants.getNamespaceId(new Namespace(Namespace.KIND_PACKAGE, abc.constants.getStringId(pkg.packageName, true)), 0, true), 0, 0, new ArrayList())); @@ -2058,10 +2064,11 @@ public class AVM2SourceGenerator implements SourceGenerator { return traits; } - public ScriptInfo generateScriptInfo(SourceGeneratorLocalData localData, List commands) throws AVM2ParseException, CompilationException { + public ScriptInfo generateScriptInfo(SourceGeneratorLocalData localData, List commands, int classPos) throws AVM2ParseException, CompilationException { + Reference class_index = new Reference<>(classPos); ScriptInfo si = new ScriptInfo(); localData.currentScript = si; - Trait[] traitArr = generateTraitsPhase1(null, null, false, localData, commands, si.traits); + Trait[] traitArr = generateTraitsPhase1(null, null, false, localData, commands, si.traits,class_index); generateTraitsPhase2(new ArrayList(), null/*FIXME*/, commands, traitArr, new ArrayList(), localData); MethodInfo mi = new MethodInfo(new int[0], 0, 0, 0, new ValueKind[0], new int[0]); MethodBody mb = new MethodBody(); @@ -2115,7 +2122,7 @@ public class AVM2SourceGenerator implements SourceGenerator { abc.addMethodBody(mb); si.init_index = mb.method_info; localData.pkg = null; //FIXME: pkg.packageName; - generateTraitsPhase3(1/*??*/, false, null, null, false, localData, commands, si.traits, traitArr, initScopes); + generateTraitsPhase3(1/*??*/, false, null, null, false, localData, commands, si.traits, traitArr, initScopes,class_index); return si; } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ActionScriptParser.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ActionScriptParser.java index 3501fd95b..a50ef5a15 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ActionScriptParser.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ActionScriptParser.java @@ -2317,18 +2317,18 @@ public class ActionScriptParser { return ret; } - public void addScriptFromTree(List items, boolean documentClass) throws AVM2ParseException, CompilationException { + public void addScriptFromTree(List items, boolean documentClass, int classPos) throws AVM2ParseException, CompilationException { AVM2SourceGenerator gen = new AVM2SourceGenerator(abc, otherABCs); List ret = new ArrayList<>(); SourceGeneratorLocalData localData = new SourceGeneratorLocalData( new HashMap(), 0, Boolean.FALSE, 0); localData.documentClass = documentClass; - abc.script_info.add(gen.generateScriptInfo(localData, items)); + abc.script_info.add(gen.generateScriptInfo(localData, items,classPos)); } - public void addScript(String s, boolean documentClass, String fileName) throws AVM2ParseException, IOException, CompilationException { + public void addScript(String s, boolean documentClass, String fileName, int classPos) throws AVM2ParseException, IOException, CompilationException { List traits = scriptTraitsFromString(s, fileName); - addScriptFromTree(traits, documentClass); + addScriptFromTree(traits, documentClass,classPos); } public ActionScriptParser(ABC abc, List otherABCs) { @@ -2348,22 +2348,22 @@ public class ActionScriptParser { } } - public static void compile(String src, ABC abc, List otherABCs, boolean documentClass, String fileName) throws AVM2ParseException, IOException, InterruptedException, CompilationException { + public static void compile(String src, ABC abc, List otherABCs, boolean documentClass, String fileName, int classPos) throws AVM2ParseException, IOException, InterruptedException, CompilationException { List parABCs = new ArrayList<>(); initPlayer(); parABCs.addAll(playerABCs); parABCs.addAll(otherABCs); ActionScriptParser parser = new ActionScriptParser(abc, parABCs); - parser.addScript(src, documentClass, fileName); + parser.addScript(src, documentClass, fileName,classPos); } - public static void compile(SWF swf, String src, String dst) { + public static void compile(SWF swf, String src, String dst, int classPos) { System.err.println("WARNING: AS3 compiler is not finished yet. This is only used for debuggging!"); try { initPlayer(); ABC abc = new ABC(swf); ActionScriptParser parser = new ActionScriptParser(abc, playerABCs); - parser.addScript(new String(Helper.readFile(src), "UTF-8"), true, src); + parser.addScript(new String(Helper.readFile(src), "UTF-8"), true, src,classPos); abc.saveToStream(new FileOutputStream(new File(dst))); } catch (Exception ex) { Logger.getLogger(ActionScriptParser.class.getName()).log(Level.SEVERE, null, ex); diff --git a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/RecompileTest.java b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/RecompileTest.java index f8a896456..91a8213d9 100644 --- a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/RecompileTest.java +++ b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/RecompileTest.java @@ -147,7 +147,7 @@ public class RecompileTest { en.getValue().toSource(htw, swf.abcList, abc.script_info.get(s).traits.traits, ScriptExportMode.AS, false); String original = htw.toString(); ABC nabc = new ABC(swf); - com.jpexs.decompiler.flash.abc.avm2.parser.script.ActionScriptParser.compile(original, nabc, allAbcs, false, en.getKey().className + ".as"); + com.jpexs.decompiler.flash.abc.avm2.parser.script.ActionScriptParser.compile(original, nabc, allAbcs, false, en.getKey().className + ".as",abc.instance_info.size()); } } } else {