Merge pull request #67 from jindrapetrik/dev

merge 11.1.0
This commit is contained in:
Jindra Petřík
2018-05-24 15:10:52 +02:00
committed by GitHub
231 changed files with 8436 additions and 1531 deletions
+25
View File
@@ -1,6 +1,30 @@
# Change Log
All notable changes to this project will be documented in this file.
## [Unreleased]
### Added
- [#1449] Turkish translation by Osman ÖZ
- AS2 classes: maintain order of variables, and methods (place variables before methods)
- AS1/2: displaying script path in the error log when jump to invalid address
- AS1/2: Try..catch with Error types - decompilation and direct editation
- AS1/2: Properly handling of Flash7 scripts exported to Flash5/6 - ActionDefineFunction local registers
### Changed
- AS1/2 direct editation - generated constantpool is sorted according to ActionPush position
### Fixed
- Accessing font list on demand - prevents loading X11 on systems without UI
- Better AS2 class detection
- AS1/2 break statement decompilation in for..in loops
- AS2 direct editation - not generating Pop in class header ifs
- AS1/2 deobfuscation - ActionRandom fixed for nonpositive numbers
- AS1/2 switch statement detection - fixes of default section position
- AS1/2: break on the end of for..in loop
- AS1/2: Export selection dialog did not allow to select script export formats and/or export script at all
- AS3 P-code - HAS_OPTIONAL flag in AVM2 code displayed twice
- Turkish locale toLowerCase I problem fix - causing not loading main window at all
- [#1456] jsyntaxpane (code display/editor) fixed for Java 9/10
## [11.0.0] - 2018-01-17
### Added
- [#1240] AS search using multiple threads when parallel speedup is enabled
@@ -2341,3 +2365,4 @@ All notable changes to this project will be documented in this file.
[#1320]: https://www.free-decompiler.com/flash/issues/1320
[#1323]: https://www.free-decompiler.com/flash/issues/1323
[#27]: https://www.free-decompiler.com/flash/issues/27
[#1449]: https://www.free-decompiler.com/flash/issues/1449
+1
View File
@@ -123,6 +123,7 @@ The application was made in Czech republic.
* **Laurent LOUVET** - french translation
* **MaGiC** - portugese translation
* **martinkoza** - polish translation
* **Osman ÖZ** - turkish translation
* **pepka** - ukrainian and dutch translation
* **poxyran** - spanish translation
* **realmaster42** - portugese-brasil translation
+1
View File
@@ -17,6 +17,7 @@
- Russian
- Spanish
- Swedish
- Turkish
- Ukrainian
## New translation
+1
View File
@@ -368,6 +368,7 @@ var SMDir
!insertmacro LANG_LOAD "Russian"
!insertmacro LANG_LOAD "Spanish"
!insertmacro LANG_LOAD "Swedish"
!insertmacro LANG_LOAD "Turkish"
!insertmacro LANG_LOAD "Ukrainian"
!insertmacro LANG_LOAD "Italian"
Binary file not shown.
@@ -12,10 +12,13 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. */
* License along with this library.
*/
package com.jpexs.decompiler.flash;
import com.jpexs.decompiler.graph.Loop;
import java.util.HashSet;
import java.util.List;
/**
*
@@ -24,8 +27,10 @@ import java.util.HashSet;
public class FinalProcessLocalData {
public final HashSet<Integer> temporaryRegisters;
public final List<Loop> loops;
public FinalProcessLocalData() {
public FinalProcessLocalData(List<Loop> loops) {
temporaryRegisters = new HashSet<>();
this.loops = loops;
}
}
@@ -12,7 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. */
* License along with this library.
*/
package com.jpexs.decompiler.flash;
import SevenZip.Compression.LZMA.Decoder;
@@ -348,6 +349,8 @@ public final class SWF implements SWFContainerItem, Timelined {
private static final DecompilerPool decompilerPool = new DecompilerPool();
public static final String AS2_PKG_PREFIX = "__Packages.";
public static List<String> swfSignatures = Arrays.asList(
"FWS", // Uncompressed Flash
"CWS", // ZLib compressed Flash
@@ -1708,8 +1711,9 @@ public final class SWF implements SWFContainerItem, Timelined {
}
private void getASMs(boolean exportFileNames, TreeItem treeItem, List<TreeItem> nodesToExport, boolean exportAll, Map<String, ASMSource> asmsToExport, String path) {
boolean exportNode = nodesToExport.contains(treeItem);
TreeItem realItem = treeItem instanceof TagScript ? ((TagScript) treeItem).getTag() : treeItem;
boolean exportNode = nodesToExport.contains(treeItem) || nodesToExport.contains(realItem);
if (realItem instanceof ASMSource && (exportAll || exportNode)) {
String npath = path;
String exPath = path;
@@ -1965,6 +1969,7 @@ public final class SWF implements SWFContainerItem, Timelined {
}
private static void getVariables(ConstantPool constantPool, BaseLocalData localData, TranslateStack stack, List<GraphTargetItem> output, ActionGraphSource code, int ip, List<MyEntry<DirectValueActionItem, ConstantPool>> variables, List<GraphSourceItem> functions, HashMap<DirectValueActionItem, ConstantPool> strings, List<Integer> visited, HashMap<DirectValueActionItem, String> usageTypes, String path) throws InterruptedException {
ActionLocalData aLocalData = (ActionLocalData) localData;
boolean debugMode = false;
while ((ip > -1) && ip < code.size()) {
if (visited.contains(ip)) {
@@ -2031,7 +2036,7 @@ public final class SWF implements SWFContainerItem, Timelined {
ip = code.adr2pos(addr);
addr += size;
int nextip = code.adr2pos(addr);
getVariables(variables, functions, strings, usageTypes, new ActionGraphSource(code.getActions().subList(ip, nextip), code.version, new HashMap<>(), new HashMap<>(), new HashMap<>()), 0, path + (cntName == null ? "" : "/" + cntName));
getVariables(aLocalData.insideDoInitAction, variables, functions, strings, usageTypes, new ActionGraphSource(path, aLocalData.insideDoInitAction, code.getActions().subList(ip, nextip), code.version, new HashMap<>(), new HashMap<>(), new HashMap<>()), 0, path + (cntName == null ? "" : "/" + cntName));
ip = nextip;
}
List<List<GraphTargetItem>> r = new ArrayList<>();
@@ -2122,39 +2127,40 @@ public final class SWF implements SWFContainerItem, Timelined {
}
}
private static void getVariables(List<MyEntry<DirectValueActionItem, ConstantPool>> variables, List<GraphSourceItem> functions, HashMap<DirectValueActionItem, ConstantPool> strings, HashMap<DirectValueActionItem, String> usageTypes, ActionGraphSource code, int addr, String path) throws InterruptedException {
ActionLocalData localData = new ActionLocalData();
private static void getVariables(boolean insideDoInitAction, List<MyEntry<DirectValueActionItem, ConstantPool>> variables, List<GraphSourceItem> functions, HashMap<DirectValueActionItem, ConstantPool> strings, HashMap<DirectValueActionItem, String> usageTypes, ActionGraphSource code, int addr, String path) throws InterruptedException {
ActionLocalData localData = new ActionLocalData(insideDoInitAction);
getVariables(null, localData, new TranslateStack(path), new ArrayList<>(), code, code.adr2pos(addr), variables, functions, strings, new ArrayList<>(), usageTypes, path);
}
private List<MyEntry<DirectValueActionItem, ConstantPool>> getVariables(List<MyEntry<DirectValueActionItem, ConstantPool>> variables, HashMap<ASMSource, ActionList> actionsMap, List<GraphSourceItem> functions, HashMap<DirectValueActionItem, ConstantPool> strings, HashMap<DirectValueActionItem, String> usageTypes, ASMSource src, String path) throws InterruptedException {
private List<MyEntry<DirectValueActionItem, ConstantPool>> getVariables(boolean insideDefineFunction1, List<MyEntry<DirectValueActionItem, ConstantPool>> variables, HashMap<ASMSource, ActionList> actionsMap, List<GraphSourceItem> functions, HashMap<DirectValueActionItem, ConstantPool> strings, HashMap<DirectValueActionItem, String> usageTypes, ASMSource src, String path) throws InterruptedException {
List<MyEntry<DirectValueActionItem, ConstantPool>> ret = new ArrayList<>();
ActionList actions = src.getActions();
actionsMap.put(src, actions);
getVariables(variables, functions, strings, usageTypes, new ActionGraphSource(actions, version, new HashMap<>(), new HashMap<>(), new HashMap<>()), 0, path);
boolean insideDoInitAction = src instanceof DoInitActionTag;
getVariables(insideDoInitAction, variables, functions, strings, usageTypes, new ActionGraphSource(path, insideDoInitAction, actions, version, new HashMap<>(), new HashMap<>(), new HashMap<>()), 0, path);
return ret;
}
private void getVariables(Iterable<Tag> tags, String path, List<MyEntry<DirectValueActionItem, ConstantPool>> variables, HashMap<ASMSource, ActionList> actionsMap, List<GraphSourceItem> functions, HashMap<DirectValueActionItem, ConstantPool> strings, HashMap<DirectValueActionItem, String> usageTypes) throws InterruptedException {
private void getVariables(boolean insideDefineFunction1, Iterable<Tag> tags, String path, List<MyEntry<DirectValueActionItem, ConstantPool>> variables, HashMap<ASMSource, ActionList> actionsMap, List<GraphSourceItem> functions, HashMap<DirectValueActionItem, ConstantPool> strings, HashMap<DirectValueActionItem, String> usageTypes) throws InterruptedException {
List<String> processed = new ArrayList<>();
for (Tag t : tags) {
String subPath = path + "/" + t.toString();
if (t instanceof ASMSource) {
addVariable((ASMSource) t, subPath, processed, variables, actionsMap, functions, strings, usageTypes);
addVariable(insideDefineFunction1, (ASMSource) t, subPath, processed, variables, actionsMap, functions, strings, usageTypes);
}
if (t instanceof ASMSourceContainer) {
List<String> processed2 = new ArrayList<>();
for (ASMSource asm : ((ASMSourceContainer) t).getSubItems()) {
addVariable(asm, subPath + "/" + asm.toString(), processed2, variables, actionsMap, functions, strings, usageTypes);
addVariable(insideDefineFunction1, asm, subPath + "/" + asm.toString(), processed2, variables, actionsMap, functions, strings, usageTypes);
}
}
if (t instanceof DefineSpriteTag) {
getVariables(((DefineSpriteTag) t).getTags(), path + "/" + t.toString(), variables, actionsMap, functions, strings, usageTypes);
getVariables(insideDefineFunction1, ((DefineSpriteTag) t).getTags(), path + "/" + t.toString(), variables, actionsMap, functions, strings, usageTypes);
}
}
}
private void addVariable(ASMSource asm, String path, List<String> processed, List<MyEntry<DirectValueActionItem, ConstantPool>> variables, HashMap<ASMSource, ActionList> actionsMap, List<GraphSourceItem> functions, HashMap<DirectValueActionItem, ConstantPool> strings, HashMap<DirectValueActionItem, String> usageTypes) throws InterruptedException {
private void addVariable(boolean insideDefineFunction1, ASMSource asm, String path, List<String> processed, List<MyEntry<DirectValueActionItem, ConstantPool>> variables, HashMap<ASMSource, ActionList> actionsMap, List<GraphSourceItem> functions, HashMap<DirectValueActionItem, ConstantPool> strings, HashMap<DirectValueActionItem, String> usageTypes) throws InterruptedException {
int pos = 1;
String infPath2 = path;
while (processed.contains(infPath2)) {
@@ -2163,7 +2169,7 @@ public final class SWF implements SWFContainerItem, Timelined {
}
processed.add(infPath2);
informListeners("getVariables", infPath2);
getVariables(variables, actionsMap, functions, strings, usageTypes, asm, path);
getVariables(insideDefineFunction1, variables, actionsMap, functions, strings, usageTypes, asm, path);
}
public boolean as3StringConstantExists(String str) {
@@ -2252,7 +2258,7 @@ public final class SWF implements SWFContainerItem, Timelined {
HashMap<DirectValueActionItem, String> usageTypes = new HashMap<>();
int ret = 0;
getVariables(getTags(), "", allVariableNames, actionsMap, allFunctions, allStrings, usageTypes);
getVariables(false, getTags(), "", allVariableNames, actionsMap, allFunctions, allStrings, usageTypes);
informListeners("rename", "");
int fc = 0;
for (MyEntry<DirectValueActionItem, ConstantPool> it : allVariableNames) {
@@ -2275,10 +2281,9 @@ public final class SWF implements SWFContainerItem, Timelined {
DoInitActionTag dia = (DoInitActionTag) t;
String exportName = getExportName(dia.spriteId);
exportName = exportName != null ? exportName : "_unk_";
final String pkgPrefix = "__Packages.";
String[] classNameParts = null;
if (exportName.startsWith(pkgPrefix)) {
String className = exportName.substring(pkgPrefix.length());
if (exportName.startsWith(AS2_PKG_PREFIX)) {
String className = exportName.substring(AS2_PKG_PREFIX.length());
if (className.contains(".")) {
classNameParts = className.split("\\.");
} else {
@@ -2288,7 +2293,7 @@ public final class SWF implements SWFContainerItem, Timelined {
int staticOperation = Graph.SOP_USE_STATIC; //(Boolean) Configuration.getConfig("autoDeobfuscate", true) ? Graph.SOP_SKIP_STATIC : Graph.SOP_USE_STATIC;
List<GraphTargetItem> dec;
try {
dec = Action.actionsToTree(dia.getActions(), version, staticOperation, ""/*FIXME*/);
dec = Action.actionsToTree(true /*Yes, inside doInitAction*/, dia.getActions(), version, staticOperation, ""/*FIXME*/);
} catch (EmptyStackException ex) {
continue;
}
@@ -2297,9 +2302,15 @@ public final class SWF implements SWFContainerItem, Timelined {
if (it instanceof ClassActionItem) {
ClassActionItem cti = (ClassActionItem) it;
List<GraphTargetItem> methods = new ArrayList<>();
methods.addAll(cti.functions);
methods.addAll(cti.staticFunctions);
List<GraphTargetItem> vars = new ArrayList<>();
for (MyEntry<GraphTargetItem, GraphTargetItem> trait : cti.traits) {
if (trait.getValue() instanceof FunctionActionItem) {
methods.add(trait.getValue());
} else {
vars.add(trait.getValue());
}
}
for (GraphTargetItem gti : methods) {
if (gti instanceof FunctionActionItem) {
FunctionActionItem fun = (FunctionActionItem) gti;
@@ -2314,13 +2325,6 @@ public final class SWF implements SWFContainerItem, Timelined {
}
}
List<GraphTargetItem> vars = new ArrayList<>();
for (MyEntry<GraphTargetItem, GraphTargetItem> item : cti.vars) {
vars.add(item.getKey());
}
for (MyEntry<GraphTargetItem, GraphTargetItem> item : cti.staticVars) {
vars.add(item.getKey());
}
for (GraphTargetItem gti : vars) {
if (gti instanceof DirectValueActionItem) {
DirectValueActionItem dvf = (DirectValueActionItem) gti;
@@ -12,7 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. */
* License along with this library.
*/
package com.jpexs.decompiler.flash.abc.avm2;
import com.jpexs.decompiler.flash.EndOfStreamException;
@@ -264,7 +265,7 @@ import com.jpexs.decompiler.flash.abc.avm2.model.clauses.DeclarationAVM2Item;
import com.jpexs.decompiler.flash.abc.avm2.model.clauses.ForEachInAVM2Item;
import com.jpexs.decompiler.flash.abc.avm2.model.clauses.ForInAVM2Item;
import com.jpexs.decompiler.flash.abc.avm2.parser.script.PropertyAVM2Item;
import com.jpexs.decompiler.flash.abc.avm2.parser.script.Reference;
import com.jpexs.helpers.Reference;
import com.jpexs.decompiler.flash.abc.types.ABCException;
import com.jpexs.decompiler.flash.abc.types.AssignedValue;
import com.jpexs.decompiler.flash.abc.types.ConvertData;
@@ -1175,7 +1176,6 @@ public class AVM2Code implements Cloneable {
writer.appendNoHilight("flag ");
writer.hilightSpecial("HAS_OPTIONAL", HighlightSpecialType.FLAG_HAS_OPTIONAL);
writer.newLine();
writer.appendNoHilight("flag HAS_OPTIONAL").newLine();
}
if (info.flagHas_paramnames()) {
writer.appendNoHilight("flag ");
@@ -2172,8 +2172,7 @@ public class AVM2Code implements Cloneable {
ins.operands[j] = updater.updateOperandOffset(target, ins.operands[j]);
}
}*/ //Faster, but not so universal
{
if (ins.definition instanceof IfTypeIns) {
if (ins.definition instanceof IfTypeIns) {
long target = ins.getTargetAddress();
try {
ins.operands[0] = updater.updateOperandOffset(ins.getAddress(), target, ins.operands[0]);
@@ -2181,7 +2180,6 @@ public class AVM2Code implements Cloneable {
throw new ConvertException("Invalid offset (" + ins + ")", i);
}
}
}
ins.setAddress(updater.updateInstructionOffset(ins.getAddress()));
//Note: changing operands here does not change instruction byte length as offsets are always S24 (not variable length)
}
@@ -12,7 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. */
* License along with this library.
*/
package com.jpexs.decompiler.flash.abc.avm2.deobfuscation;
import com.jpexs.decompiler.flash.BaseLocalData;
@@ -32,7 +33,7 @@ import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.SetLocalTypeIn
import com.jpexs.decompiler.flash.abc.avm2.instructions.other.ReturnValueIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.other.ReturnVoidIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.other.ThrowIns;
import com.jpexs.decompiler.flash.abc.avm2.parser.script.Reference;
import com.jpexs.helpers.Reference;
import com.jpexs.decompiler.flash.abc.types.MethodBody;
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
import com.jpexs.decompiler.flash.abc.types.traits.Trait;
@@ -12,7 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. */
* License along with this library.
*/
package com.jpexs.decompiler.flash.abc.avm2.deobfuscation;
import com.jpexs.decompiler.flash.BaseLocalData;
@@ -30,7 +31,7 @@ import com.jpexs.decompiler.flash.abc.avm2.instructions.other.ReturnValueIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.other.ReturnVoidIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.other.ThrowIns;
import com.jpexs.decompiler.flash.abc.avm2.model.NullAVM2Item;
import com.jpexs.decompiler.flash.abc.avm2.parser.script.Reference;
import com.jpexs.helpers.Reference;
import com.jpexs.decompiler.flash.abc.types.MethodBody;
import com.jpexs.decompiler.flash.abc.types.traits.Trait;
import com.jpexs.decompiler.graph.Graph;
@@ -12,7 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. */
* License along with this library.
*/
package com.jpexs.decompiler.flash.abc.avm2.graph;
import com.jpexs.decompiler.flash.BaseLocalData;
@@ -571,8 +572,8 @@ public class AVM2Graph extends Graph {
}
@Override
protected void finalProcessAfter(List<GraphTargetItem> list, int level, FinalProcessLocalData localData) {
super.finalProcessAfter(list, level, localData);
protected void finalProcessAfter(List<GraphTargetItem> list, int level, FinalProcessLocalData localData, String path) {
super.finalProcessAfter(list, level, localData, path);
for (int i = 0; i < list.size(); i++) {
if (list.get(i) instanceof SetLocalAVM2Item) {
SetLocalAVM2Item ri = (SetLocalAVM2Item) list.get(i);
@@ -585,7 +586,7 @@ public class AVM2Graph extends Graph {
}
@Override
protected void finalProcess(List<GraphTargetItem> list, int level, FinalProcessLocalData localData) throws InterruptedException {
protected void finalProcess(List<GraphTargetItem> list, int level, FinalProcessLocalData localData, String path) throws InterruptedException {
if (level == 0) {
if (!list.isEmpty()) {
@@ -702,7 +703,7 @@ public class AVM2Graph extends Graph {
}
}
//Handle for loops at the end:
super.finalProcess(list, level, localData);
super.finalProcess(list, level, localData, path);
}
@Override
@@ -12,7 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. */
* License along with this library.
*/
package com.jpexs.decompiler.flash.abc.avm2.graph;
import com.jpexs.decompiler.flash.BaseLocalData;
@@ -21,7 +22,7 @@ import com.jpexs.decompiler.flash.abc.AVM2LocalData;
import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
import com.jpexs.decompiler.flash.abc.avm2.ConvertOutput;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.parser.script.Reference;
import com.jpexs.helpers.Reference;
import com.jpexs.decompiler.flash.abc.types.MethodBody;
import com.jpexs.decompiler.graph.DottedChain;
import com.jpexs.decompiler.graph.GraphPart;
@@ -12,7 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. */
* License along with this library.
*/
package com.jpexs.decompiler.flash.abc.avm2.instructions;
import com.jpexs.decompiler.flash.abc.ABC;
@@ -29,7 +30,7 @@ import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.IncLocalIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.SetLocalTypeIns;
import com.jpexs.decompiler.flash.abc.avm2.model.AVM2Item;
import com.jpexs.decompiler.flash.abc.avm2.model.FullMultinameAVM2Item;
import com.jpexs.decompiler.flash.abc.avm2.parser.script.Reference;
import com.jpexs.helpers.Reference;
import com.jpexs.decompiler.flash.abc.types.MethodBody;
import com.jpexs.decompiler.flash.abc.types.Multiname;
import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
@@ -12,9 +12,11 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. */
* License along with this library.
*/
package com.jpexs.decompiler.flash.abc.avm2.parser.script;
import com.jpexs.helpers.Reference;
import com.jpexs.decompiler.flash.SWFInputStream;
import com.jpexs.decompiler.flash.SourceGeneratorLocalData;
import com.jpexs.decompiler.flash.abc.ABC;
@@ -12,9 +12,11 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. */
* License along with this library.
*/
package com.jpexs.decompiler.flash.abc.avm2.parser.script;
import com.jpexs.helpers.Reference;
import com.jpexs.decompiler.flash.SWC;
import com.jpexs.decompiler.flash.SWF;
import com.jpexs.decompiler.flash.SourceGeneratorLocalData;
@@ -12,9 +12,11 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. */
* License along with this library.
*/
package com.jpexs.decompiler.flash.abc.avm2.parser.script;
import com.jpexs.helpers.Reference;
import com.jpexs.decompiler.flash.SourceGeneratorLocalData;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instructions;
@@ -12,9 +12,11 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. */
* License along with this library.
*/
package com.jpexs.decompiler.flash.abc.avm2.parser.script;
import com.jpexs.helpers.Reference;
import com.jpexs.decompiler.flash.SourceGeneratorLocalData;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
@@ -12,9 +12,11 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. */
* License along with this library.
*/
package com.jpexs.decompiler.flash.abc.avm2.parser.script;
import com.jpexs.helpers.Reference;
import com.jpexs.decompiler.flash.SourceGeneratorLocalData;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instructions;
import com.jpexs.decompiler.flash.abc.types.Multiname;
@@ -12,9 +12,11 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. */
* License along with this library.
*/
package com.jpexs.decompiler.flash.abc.avm2.parser.script;
import com.jpexs.helpers.Reference;
import com.jpexs.decompiler.flash.SourceGeneratorLocalData;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instructions;
@@ -12,9 +12,11 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. */
* License along with this library.
*/
package com.jpexs.decompiler.flash.abc.avm2.parser.script;
import com.jpexs.helpers.Reference;
import com.jpexs.decompiler.flash.SourceGeneratorLocalData;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.types.Namespace;
@@ -12,9 +12,11 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. */
* License along with this library.
*/
package com.jpexs.decompiler.flash.abc.avm2.parser.script;
import com.jpexs.helpers.Reference;
import com.jpexs.decompiler.flash.SourceGeneratorLocalData;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool;
@@ -12,9 +12,11 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. */
* License along with this library.
*/
package com.jpexs.decompiler.flash.abc.avm2.parser.script;
import com.jpexs.helpers.Reference;
import com.jpexs.decompiler.flash.SourceGeneratorLocalData;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool;
@@ -12,7 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. */
* License along with this library.
*/
package com.jpexs.decompiler.flash.action;
import com.jpexs.decompiler.flash.AppResources;
@@ -20,9 +21,10 @@ import com.jpexs.decompiler.flash.BaseLocalData;
import com.jpexs.decompiler.flash.DisassemblyListener;
import com.jpexs.decompiler.flash.SWF;
import com.jpexs.decompiler.flash.SWFOutputStream;
import com.jpexs.decompiler.flash.abc.avm2.parser.script.Reference;
import com.jpexs.helpers.Reference;
import com.jpexs.decompiler.flash.action.deobfuscation.ActionDeobfuscator;
import com.jpexs.decompiler.flash.action.model.ActionItem;
import com.jpexs.decompiler.flash.action.model.CallMethodActionItem;
import com.jpexs.decompiler.flash.action.model.ConstantPool;
import com.jpexs.decompiler.flash.action.model.DirectValueActionItem;
import com.jpexs.decompiler.flash.action.model.ExtendsActionItem;
@@ -65,6 +67,7 @@ import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
import com.jpexs.decompiler.flash.helpers.NulWriter;
import com.jpexs.decompiler.flash.helpers.SWFDecompilerPlugin;
import com.jpexs.decompiler.flash.helpers.collections.MyEntry;
import com.jpexs.decompiler.flash.tags.DoInitActionTag;
import com.jpexs.decompiler.flash.tags.base.ASMSource;
import com.jpexs.decompiler.graph.Graph;
import com.jpexs.decompiler.graph.GraphSource;
@@ -78,6 +81,7 @@ import com.jpexs.decompiler.graph.model.IfItem;
import com.jpexs.decompiler.graph.model.LocalData;
import com.jpexs.decompiler.graph.model.NotItem;
import com.jpexs.decompiler.graph.model.PopItem;
import com.jpexs.decompiler.graph.model.PushItem;
import com.jpexs.decompiler.graph.model.ScriptEndItem;
import com.jpexs.helpers.ByteArrayRange;
import com.jpexs.helpers.CancellableWorker;
@@ -756,7 +760,7 @@ public abstract class Action implements GraphSourceItem {
* @param path the value of path
* @throws java.lang.InterruptedException
*/
public void translate(GraphSourceItem lineStartIns, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) throws InterruptedException {
public void translate(boolean insideDoInitAction, GraphSourceItem lineStartIns, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) throws InterruptedException {
}
@Override
@@ -832,8 +836,8 @@ public abstract class Action implements GraphSourceItem {
return -1;
}
public static List<GraphTargetItem> actionsToTree(List<Action> actions, int version, int staticOperation, String path) throws InterruptedException {
return actionsToTree(new HashMap<>(), new HashMap<>(), new HashMap<>(), actions, version, staticOperation, path);
public static List<GraphTargetItem> actionsToTree(boolean insideDoInitAction, List<Action> actions, int version, int staticOperation, String path) throws InterruptedException {
return actionsToTree(insideDoInitAction, new HashMap<>(), new HashMap<>(), new HashMap<>(), actions, version, staticOperation, path);
}
/**
@@ -858,7 +862,8 @@ public abstract class Action implements GraphSourceItem {
@Override
public List<GraphTargetItem> call() throws Exception {
int staticOperation = Graph.SOP_USE_STATIC; //(Boolean) Configuration.getConfig("autoDeobfuscate", true) ? Graph.SOP_SKIP_STATIC : Graph.SOP_USE_STATIC;
List<GraphTargetItem> tree = actionsToTree(new HashMap<>(), new HashMap<>(), new HashMap<>(), actions, version, staticOperation, path);
boolean insideDoInitAction = (asm instanceof DoInitActionTag);
List<GraphTargetItem> tree = actionsToTree(insideDoInitAction, new HashMap<>(), new HashMap<>(), new HashMap<>(), actions, version, staticOperation, path);
SWFDecompilerPlugin.fireActionTreeCreated(tree, swf);
if (Configuration.autoDeobfuscate.get()) {
new ActionDeobfuscator().actionTreeCreated(tree, swf);
@@ -916,8 +921,8 @@ public abstract class Action implements GraphSourceItem {
* @return List of treeItems
* @throws java.lang.InterruptedException
*/
public static List<GraphTargetItem> actionsToTree(HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, List<Action> actions, int version, int staticOperation, String path) throws InterruptedException {
return ActionGraph.translateViaGraph(regNames, variables, functions, actions, version, staticOperation, path);
public static List<GraphTargetItem> actionsToTree(boolean insideDoInitAction, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, List<Action> actions, int version, int staticOperation, String path) throws InterruptedException {
return ActionGraph.translateViaGraph(insideDoInitAction, regNames, variables, functions, actions, version, staticOperation, path);
}
@Override
@@ -929,7 +934,7 @@ public abstract class Action implements GraphSourceItem {
}
expectedSize += getStackPushCount(localData, stack);*/
translate(aLocalData.lineStartAction, stack, output, aLocalData.regNames, aLocalData.variables, aLocalData.functions, staticOperation, path);
translate(aLocalData.insideDoInitAction, aLocalData.lineStartAction, stack, output, aLocalData.regNames, aLocalData.variables, aLocalData.functions, staticOperation, path);
/*if (stack.size() != expectedSize && !(this instanceof ActionPushDuplicate)) {
throw new Error("HONFIKA stack size mismatch");
}*/
@@ -965,11 +970,11 @@ public abstract class Action implements GraphSourceItem {
this.ignored = ignored;
}
public static List<GraphTargetItem> actionsPartToTree(Reference<GraphSourceItem> fi, HashMap<Integer, String> registerNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, TranslateStack stack, List<Action> actions, int start, int end, int version, int staticOperation, String path) throws InterruptedException {
public static List<GraphTargetItem> actionsPartToTree(boolean insideDoInitAction, Reference<GraphSourceItem> fi, HashMap<Integer, String> registerNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, TranslateStack stack, List<Action> actions, int start, int end, int version, int staticOperation, String path) throws InterruptedException {
if (start < actions.size() && (end > 0) && (start > 0)) {
logger.log(Level.FINE, "Entering {0}-{1}{2}", new Object[]{start, end, actions.size() > 0 ? (" (" + actions.get(start).toString() + " - " + actions.get(end == actions.size() ? end - 1 : end) + ")") : ""});
}
ActionLocalData localData = new ActionLocalData(registerNames, variables, functions);
ActionLocalData localData = new ActionLocalData(insideDoInitAction, registerNames, variables, functions);
localData.lineStartAction = fi.getVal();
List<GraphTargetItem> output = new ArrayList<>();
int ip = start;
@@ -1039,7 +1044,7 @@ public abstract class Action implements GraphSourceItem {
}
}
}
out = ActionGraph.translateViaGraph(regNames, variables2, functions, actions.subList(adr2ip(actions, endAddr), adr2ip(actions, endAddr + size)), version, staticOperation, path + (cntName == null ? "" : "/" + cntName));
out = ActionGraph.translateViaGraph(insideDoInitAction, regNames, variables2, functions, actions.subList(adr2ip(actions, endAddr), adr2ip(actions, endAddr + size)), version, staticOperation, path + (cntName == null ? "" : "/" + cntName));
} catch (OutOfMemoryError | TranslateException | StackOverflowError ex) {
logger.log(Level.SEVERE, "Decompilation error in: " + path, ex);
if (ex instanceof OutOfMemoryError) {
@@ -1072,7 +1077,7 @@ public abstract class Action implements GraphSourceItem {
if (actions.get(ip + 2) instanceof ActionNot) {
if (actions.get(ip + 3) instanceof ActionIf) {
ActionIf aif = (ActionIf) actions.get(ip + 3);
if (adr2ip(actions, ip2adr(actions, ip + 4) + aif.getJumpOffset()) == ip) {
if (adr2ip(actions, ip2adr(actions, ip + 3) + 5 + aif.getJumpOffset()) == ip) {
ip += 4;
continue;
}
@@ -1082,103 +1087,16 @@ public abstract class Action implements GraphSourceItem {
}
}
/*ActionJump && ActionIf removed*/
/*if ((action instanceof ActionEnumerate2) || (action instanceof ActionEnumerate)) {
loopStart = ip + 1;
isForIn = true;
ip += 4;
action.translate(localData, stack, output);
EnumerateActionItem en = (EnumerateActionItem) stack.peek();
inItem = en.object;
continue;
} else*/ /*if (action instanceof ActionTry) {
ActionTry atry = (ActionTry) action;
List<GraphTargetItem> tryCommands = ActionGraph.translateViaGraph(registerNames, variables, functions, atry.tryBody, version);
ActionItem catchName;
if (atry.catchInRegisterFlag) {
catchName = new DirectValueActionItem(atry, -1, new RegisterNumber(atry.catchRegister), new ArrayList<>());
} else {
catchName = new DirectValueActionItem(atry, -1, atry.catchName, new ArrayList<>());
}
List<GraphTargetItem> catchExceptions = new ArrayList<GraphTargetItem>();
catchExceptions.add(catchName);
List<List<GraphTargetItem>> catchCommands = new ArrayList<List<GraphTargetItem>>();
catchCommands.add(ActionGraph.translateViaGraph(registerNames, variables, functions, atry.catchBody, version));
List<GraphTargetItem> finallyCommands = ActionGraph.translateViaGraph(registerNames, variables, functions, atry.finallyBody, version);
output.add(new TryActionItem(tryCommands, catchExceptions, catchCommands, finallyCommands));
} else if (action instanceof ActionWith) {
ActionWith awith = (ActionWith) action;
List<GraphTargetItem> withCommands = ActionGraph.translateViaGraph(registerNames, variables, functions,new ArrayList<Action>() , version); //TODO:parse with actions
output.add(new WithActionItem(action, stack.pop(), withCommands));
} else */ if (false) {
} /*if (action instanceof ActionStoreRegister) {
if ((ip + 1 <= end) && (actions.get(ip + 1) instanceof ActionPop)) {
action.translate(localData, stack, output);
stack.pop();
ip++;
} else {
try {
action.translate(localData, stack, output);
} catch (Exception ex) {
// ignore
}
}
} */ /*else if (action instanceof ActionStrictEquals) {
if ((ip + 1 < actions.size()) && (actions.get(ip + 1) instanceof ActionIf)) {
List<ActionItem> caseValues = new ArrayList<ActionItem>();
List<List<ActionItem>> caseCommands = new ArrayList<List<ActionItem>>();
caseValues.add(stack.pop());
ActionItem switchedObject = stack.pop();
if (output.size() > 0) {
if (output.get(output.size() - 1) instanceof StoreRegisterActionItem) {
output.remove(output.size() - 1);
}
}
int caseStart = ip + 2;
List<Integer> caseBodyIps = new ArrayList<Integer>();
long defaultAddr = 0;
caseBodyIps.add(adr2ip(actions, ((ActionIf) actions.get(ip + 1)).getRef(version), version));
ip++;
do {
ip++;
if ((actions.get(ip - 1) instanceof ActionStrictEquals) && (actions.get(ip) instanceof ActionIf)) {
caseValues.add(actionsToStackTree(registerNames, jumpsOrIfs, actions, constants, caseStart, ip - 2, version).pop());
caseStart = ip + 1;
caseBodyIps.add(adr2ip(actions, ((ActionIf) actions.get(ip)).getRef(version), version));
if (actions.get(ip + 1) instanceof ActionJump) {
defaultAddr = ((ActionJump) actions.get(ip + 1)).getRef(version);
ip = adr2ip(actions, defaultAddr, version);
break;
}
}
} while (ip < end);
for (int i = 0; i < caseBodyIps.size(); i++) {
int caseEnd = ip - 1;
if (i < caseBodyIps.size() - 1) {
caseEnd = caseBodyIps.get(i + 1) - 1;
}
caseCommands.add(actionsToTree(registerNames, unknownJumps, loopList, jumpsOrIfs, stack, constants, actions, caseBodyIps.get(i), caseEnd, version));
}
output.add(new SwitchActionItem(action, defaultAddr, switchedObject, caseValues, caseCommands, null));
continue;
} else {
action.translate(stack, constants, output, registerNames);
}
} */ else {
if (action instanceof ActionStore) {
ActionStore store = (ActionStore) action;
store.setStore(actions.subList(ip + 1, ip + 1 + store.getStoreSize()));
ip = ip + 1 + store.getStoreSize() - 1/*ip++ will be next*/;
}
action.translate(localData, stack, output, staticOperation, path);
if (action instanceof ActionStore) {
ActionStore store = (ActionStore) action;
store.setStore(actions.subList(ip + 1, ip + 1 + store.getStoreSize()));
ip = ip + 1 + store.getStoreSize() - 1/*ip++ will be next*/;
}
action.translate(localData, stack, output, staticOperation, path);
ip++;
}
//output = checkClass(output);
logger.log(Level.FINE, "Leaving {0}-{1}", new Object[]{start, end});
return output;
}
@@ -1211,155 +1129,6 @@ public abstract class Action implements GraphSourceItem {
return ti;
}
public static List<GraphTargetItem> checkClass(List<GraphTargetItem> output) {
if (true) {
//return output;
}
List<GraphTargetItem> ret = new ArrayList<>();
List<GraphTargetItem> functions = new ArrayList<>();
List<GraphTargetItem> staticFunctions = new ArrayList<>();
List<MyEntry<GraphTargetItem, GraphTargetItem>> vars = new ArrayList<>();
List<MyEntry<GraphTargetItem, GraphTargetItem>> staticVars = new ArrayList<>();
GraphTargetItem className;
GraphTargetItem extendsOp = null;
List<GraphTargetItem> implementsOp = new ArrayList<>();
boolean ok = true;
int prevCount = 0;
for (GraphTargetItem t : output) {
if (t instanceof IfItem) {
IfItem it = (IfItem) t;
if (it.expression instanceof NotItem) {
NotItem nti = (NotItem) it.expression;
if ((nti.value instanceof GetMemberActionItem) || (nti.value instanceof GetVariableActionItem)) {
if (true) { //it.onFalse.isEmpty()){ //||(it.onFalse.get(0) instanceof UnsupportedActionItem)) {
if ((it.onTrue.size() == 1) && (it.onTrue.get(0) instanceof SetMemberActionItem) && (((SetMemberActionItem) it.onTrue.get(0)).value instanceof NewObjectActionItem)) {
// ignore
} else {
List<GraphTargetItem> parts = it.onTrue;
className = getWithoutGlobal(nti.value);
if (parts.size() >= 1) {
int ipos = 0;
while ((parts.get(ipos) instanceof PopItem) || ((parts.get(ipos) instanceof IfItem) && ((((IfItem) parts.get(ipos)).onTrue.size() == 1) && (((IfItem) parts.get(ipos)).onTrue.get(0) instanceof SetMemberActionItem) && (((SetMemberActionItem) ((IfItem) parts.get(ipos)).onTrue.get(0)).value instanceof NewObjectActionItem)))) {
ipos++;
}
if (parts.get(ipos) instanceof ExtendsActionItem) {
ExtendsActionItem et = (ExtendsActionItem) parts.get(ipos);
extendsOp = getWithoutGlobal(et.superclass);
ipos++;
}
if (parts.get(ipos) instanceof StoreRegisterActionItem) {
StoreRegisterActionItem sr = (StoreRegisterActionItem) parts.get(ipos);
int instanceReg = sr.register.number;
if (sr.value instanceof GetMemberActionItem) {
GetMemberActionItem gm = (GetMemberActionItem) sr.value;
//gm.memberName should be "prototype"
if (gm.object instanceof TemporaryRegister) {
TemporaryRegister tm = (TemporaryRegister) gm.object;
int classReg = tm.getRegId();
if (tm.value instanceof SetMemberActionItem) {
SetMemberActionItem sm = (SetMemberActionItem) tm.value;
if (sm.value instanceof StoreRegisterActionItem) {
sr = (StoreRegisterActionItem) sm.value;
if (sr.value instanceof FunctionActionItem) {
((FunctionActionItem) (sr.value)).calculatedFunctionName = (className instanceof GetMemberActionItem) ? ((GetMemberActionItem) className).memberName : className;
functions.add((FunctionActionItem) sr.value);
for (; ipos < parts.size(); ipos++) {
if (parts.get(ipos) instanceof ImplementsOpActionItem) {
ImplementsOpActionItem io = (ImplementsOpActionItem) parts.get(ipos);
implementsOp = io.superclasses;
continue;
}
if (parts.get(ipos) instanceof SetMemberActionItem) {
sm = (SetMemberActionItem) parts.get(ipos);
int rnum = -1;
if (sm.object instanceof DirectValueActionItem) {
DirectValueActionItem dv = (DirectValueActionItem) sm.object;
if (dv.value instanceof RegisterNumber) {
RegisterNumber rn = (RegisterNumber) dv.value;
rnum = rn.number;
}
}
if (sm.object instanceof TemporaryRegister) {
rnum = ((TemporaryRegister) sm.object).getRegId();
}
if (rnum == instanceReg) {
if (sm.value instanceof FunctionActionItem) {
((FunctionActionItem) sm.value).calculatedFunctionName = sm.objectName;
functions.add((FunctionActionItem) sm.value);
} else {
vars.add(new MyEntry<>(sm.objectName, sm.value));
}
} else if (rnum == classReg) {
if (sm.value instanceof FunctionActionItem) {
((FunctionActionItem) sm.value).calculatedFunctionName = sm.objectName;
staticFunctions.add((FunctionActionItem) sm.value);
} else {
staticVars.add(new MyEntry<>(sm.objectName, sm.value));
}
}
}
}
}
}
}
List<GraphTargetItem> output2 = new ArrayList<>();
for (int i = 0; i < prevCount; i++) {
output2.add(output.get(i));
}
output2.add(new ClassActionItem(className, extendsOp, implementsOp, null/*FIXME*/, functions, vars, staticFunctions, staticVars));
return output2;
}
}
} else if (parts.get(ipos) instanceof SetMemberActionItem) {
SetMemberActionItem sm = (SetMemberActionItem) parts.get(0);
if (sm.value instanceof FunctionActionItem) {
FunctionActionItem f = (FunctionActionItem) sm.value;
if (f.actions.isEmpty()) {
if (parts.size() == 2) {
if (parts.get(1) instanceof ImplementsOpActionItem) {
ImplementsOpActionItem iot = (ImplementsOpActionItem) parts.get(1);
implementsOp = iot.superclasses;
} else {
//ok = false;
break;
}
}
List<GraphTargetItem> output2 = new ArrayList<>();
for (int i = 0; i < prevCount; i++) {
output2.add(output.get(i));
}
output2.add(new InterfaceActionItem(sm.objectName, implementsOp));
return output2;
}
}
}
}
}
} else {
//ok = false;
}
} else {
ok = false;
}
} else {
ok = false;
}
} else if (!(t instanceof PopItem)) {
prevCount++;
//ok = false;
}
if (!ok) {
break;
}
}
return output;
}
@Override
public boolean ignoredLoops() {
return false;
@@ -0,0 +1,291 @@
/*
* Copyright (C) 2010-2018 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.action;
import com.jpexs.decompiler.flash.SWF;
import com.jpexs.decompiler.flash.action.swf4.ActionJump;
import com.jpexs.decompiler.flash.action.swf4.ActionPop;
import com.jpexs.decompiler.flash.action.swf4.ActionPush;
import com.jpexs.decompiler.flash.action.swf4.RegisterNumber;
import com.jpexs.decompiler.flash.action.swf5.ActionDefineFunction;
import com.jpexs.decompiler.flash.action.swf5.ActionReturn;
import com.jpexs.decompiler.flash.action.swf5.ActionStoreRegister;
import com.jpexs.decompiler.flash.ecma.Undefined;
import com.jpexs.decompiler.flash.helpers.SWFDecompilerAdapter;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
/**
* Cleaner for ActionDefineFunction push registers. From Flash 7 onwards,
* functions are stored as ActionDefineFunction2 with use up to 255 local
* registers. When exporting SWF to lower formats Flash5-Flash6 in Flash IDE
* (for example MX 2004), all ActionDefineFunction2 are replaced with
* ActionDefineFunction, and it also use local registers (4 of them are
* available). The code of ActionDefineFunction is also modified that it pushes
* all previous values of registers on the code start and pops them back on code
* exit or when return action shows up. All returns are replaced with jump to
* popping part. This makes code flow tangled and the decompiler cannot properly
* handle it. The cleaner will fix this mess.
*
* @author JPEXS
*/
public class ActionDefineFunctionPushRegistersCleaner extends SWFDecompilerAdapter {
@Override
public void actionListParsed(ActionList actions, SWF swf) throws InterruptedException {
cleanActionDefineFunctions(actions);
}
private void cleanActionDefineFunctions(ActionList actions) {
for (int i = actions.size() - 1; i >= 0; i--) {
Action action = actions.get(i);
if (action instanceof ActionDefineFunction) {
ActionDefineFunction def = (ActionDefineFunction) action;
List<Long> sizes = def.getContainerSizes();
long endAddress = action.getAddress() + def.getHeaderSize() + sizes.get(0);
int lastIndex = actions.getIndexByAddress(endAddress);
int startIndex = i + 1;
int count = lastIndex - startIndex;
cleanPushRegisters(actions, startIndex, count);
}
}
}
/**
*
* @param code
* @param startIndex Index of first Action in DefineFunction body
* @param count Count of actions in DefineFunction
* @return
*/
private boolean cleanPushRegisters(ActionList code, int startIndex, int count) {
if (count == 0) {
return false;
}
/*
ON BEGINNING:
Push register1 register2 normalval
*/
List<Integer> pushedRegisters = new ArrayList<>();
int pos = startIndex;
loopregs:
while (code.get(pos) instanceof ActionPush) {
ActionPush ap = (ActionPush) code.get(pos);
for (int i = 0; i < ap.values.size(); i++) {
if (ap.values.get(i) instanceof RegisterNumber) {
RegisterNumber rn = (RegisterNumber) ap.values.get(i);
pushedRegisters.add(rn.number);
} else {
break loopregs;
}
}
pos++;
if (pos >= code.size()) {
return false;
}
}
if (pushedRegisters.isEmpty()) {
return false;
}
/*
ON FINISH:
when function returns something:
StoreRegister 0 ;return value
Pop
StoreRegister 2
Pop
StoreRegister 1
Pop
Push register0
Return
when function does not return anything:
StoreRegister 2
Pop
StoreRegister 1
Pop
when original function has some returns, but no return at the end of function:
Push undefined
locjump: StoreRegister 0
Pop
...
*/
int returnReg = -1;
pos = startIndex + count - 1;
if (code.get(pos) instanceof ActionReturn) {
pos--;
if (pos < startIndex) {
return false;
}
if (!(code.get(pos) instanceof ActionPush)) {
return false;
}
ActionPush pu = (ActionPush) code.get(pos);
if (pu.values.size() != 1) {
return false;
}
if (!(pu.values.get(0) instanceof RegisterNumber)) {
return false;
}
RegisterNumber rn = (RegisterNumber) pu.values.get(0);
returnReg = rn.number;
pos--;
if (pos < startIndex) {
return false;
}
}
for (int i = 0; i < pushedRegisters.size(); i++) {
if (!(code.get(pos) instanceof ActionPop)) {
return false;
}
pos--;
if (pos < startIndex) {
return false;
}
if (!(code.get(pos) instanceof ActionStoreRegister)) {
return false;
}
ActionStoreRegister asr = (ActionStoreRegister) code.get(pos);
int expectedReg = pushedRegisters.get(i);
if (asr.registerNumber != expectedReg) {
return false;
}
pos--;
if (pos < startIndex) {
return false;
}
}
Set<Integer> jumpsToReturnPositions = new TreeSet<>(new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o2 - o1; //biggest first
}
});
int posBeforeFinishPart;
Action actionBeforeFinishPart = null;
if (returnReg > -1) {
if (!(code.get(pos) instanceof ActionPop)) {
return false;
}
pos--;
if (pos < startIndex) {
return false;
}
if (!(code.get(pos) instanceof ActionStoreRegister)) {
return false;
}
ActionStoreRegister asr = (ActionStoreRegister) code.get(pos);
int expectedReg = returnReg;
if (asr.registerNumber != expectedReg) {
return false;
}
Iterator<Action> ait = code.getReferencesFor(asr);
while (ait.hasNext()) {
Action a = ait.next();
if (!(a instanceof ActionJump)) {
return false;
}
jumpsToReturnPositions.add(code.indexOf(a));
}
pos--;
if (!(code.get(pos) instanceof ActionJump)) {
actionBeforeFinishPart = code.get(pos);
}
posBeforeFinishPart = pos;
} else {
posBeforeFinishPart = pos;
}
//process code...
//replace jumps to return with returns
for (Integer jp : jumpsToReturnPositions) {
int index = jp;
code.removeAction(index);
code.addAction(index, new ActionReturn());
}
//previous action (not jump) also leads to finishpart, we might add return there aswell
if (returnReg > -1 && actionBeforeFinishPart != null) {
if ((actionBeforeFinishPart instanceof ActionPush) && ((ActionPush) actionBeforeFinishPart).values.size() == 1 && ((ActionPush) actionBeforeFinishPart).values.get(0) == Undefined.INSTANCE) {
//its return undefined, which is same as no return
code.removeAction(posBeforeFinishPart);
posBeforeFinishPart--;
count--;
} else if (actionBeforeFinishPart instanceof ActionReturn) {
//it was a jump that was replaced with Return
} else if (actionBeforeFinishPart instanceof ActionJump) {
//its jump to another location, we will not add return there
} else { //might be another returned value
posBeforeFinishPart++;
code.addAction(posBeforeFinishPart, new ActionReturn());
count++; //action added, but not removed, we increase total count
}
}
//remove finishPart
int removeStartIndex = posBeforeFinishPart + 1;
int removeCount = startIndex + count - removeStartIndex;
code.removeAction(removeStartIndex, removeCount);
//remove pushes from beginning part
pos = startIndex;
int registersLeft = pushedRegisters.size();
loopregs2:
while (code.get(pos) instanceof ActionPush) {
ActionPush currentPush = (ActionPush) code.get(pos);
List<Object> currentPushedValues = currentPush.values;
List<Object> newPushedValues = new ArrayList<>();
for (int i = 0; i < currentPushedValues.size(); i++) {
if (registersLeft > 0 && currentPushedValues.get(i) instanceof RegisterNumber) {
registersLeft--;
} else {
newPushedValues.add(currentPushedValues.get(i));
}
}
if (newPushedValues.size() != currentPushedValues.size()) {
code.removeAction(pos); //remove that push
if (!newPushedValues.isEmpty()) {
ActionPush newPush = new ActionPush(newPushedValues.toArray());
newPush.constantPool = currentPush.constantPool;
code.addAction(pos, newPush); //replace with different push
} else {
pos--; //action removed, but not added
}
}
if (registersLeft == 0) { //we removed all unwanted registers
break;
}
pos++;
}
return true;
}
}
@@ -12,7 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. */
* License along with this library.
*/
package com.jpexs.decompiler.flash.action;
import com.jpexs.decompiler.flash.BaseLocalData;
@@ -48,6 +49,7 @@ import com.jpexs.decompiler.graph.TranslateStack;
import com.jpexs.decompiler.graph.model.BreakItem;
import com.jpexs.decompiler.graph.model.ContinueItem;
import com.jpexs.decompiler.graph.model.DefaultItem;
import com.jpexs.decompiler.graph.model.IfItem;
import com.jpexs.decompiler.graph.model.SwitchItem;
import com.jpexs.decompiler.graph.model.WhileItem;
import java.util.ArrayList;
@@ -62,26 +64,31 @@ import java.util.Set;
*/
public class ActionGraph extends Graph {
public ActionGraph(List<Action> code, HashMap<Integer, String> registerNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int version) {
super(new ActionGraphSource(code, version, registerNames, variables, functions), new ArrayList<>());
//this.version = version;
/*heads = makeGraph(code, new ArrayList<GraphPart>());
for (GraphPart head : heads) {
fixGraph(head);
makeMulti(head, new ArrayList<GraphPart>());
}*/
private boolean insideDoInitAction;
public ActionGraph(String path, boolean insideDoInitAction, List<Action> code, HashMap<Integer, String> registerNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int version) {
super(new ActionGraphSource(path, insideDoInitAction, code, version, registerNames, variables, functions), new ArrayList<>());
this.insideDoInitAction = insideDoInitAction;
}
public static List<GraphTargetItem> translateViaGraph(HashMap<Integer, String> registerNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, List<Action> code, int version, int staticOperation, String path) throws InterruptedException {
public boolean isInsideDoInitAction() {
return insideDoInitAction;
}
ActionGraph g = new ActionGraph(code, registerNames, variables, functions, version);
ActionLocalData localData = new ActionLocalData(registerNames);
@Override
protected void afterPopupateAllParts(Set<GraphPart> allParts) {
}
public static List<GraphTargetItem> translateViaGraph(boolean insideDoInitAction, HashMap<Integer, String> registerNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, List<Action> code, int version, int staticOperation, String path) throws InterruptedException {
ActionGraph g = new ActionGraph(path, insideDoInitAction, code, registerNames, variables, functions, version);
ActionLocalData localData = new ActionLocalData(insideDoInitAction, registerNames);
g.init(localData);
return g.translate(localData, staticOperation, path);
}
@Override
public void finalProcessStack(TranslateStack stack, List<GraphTargetItem> output) {
public void finalProcessStack(TranslateStack stack, List<GraphTargetItem> output, String path) {
if (stack.size() > 0) {
for (int i = stack.size() - 1; i >= 0; i--) {
//System.err.println(stack.get(i));
@@ -96,11 +103,11 @@ public class ActionGraph extends Graph {
}
@Override
protected void finalProcess(List<GraphTargetItem> list, int level, FinalProcessLocalData localData) throws InterruptedException {
List<GraphTargetItem> ret = Action.checkClass(list);
if (ret != list) {
list.clear();
list.addAll(ret);
protected void finalProcess(List<GraphTargetItem> list, int level, FinalProcessLocalData localData, String path) throws InterruptedException {
if (insideDoInitAction) {
ActionScript2ClassDetector detector = new ActionScript2ClassDetector();
detector.checkClass(list, path);
}
int targetStart;
int targetEnd;
@@ -161,34 +168,51 @@ public class ActionGraph extends Graph {
} while (again);
for (int t = 1/*not first*/; t < list.size(); t++) {
GraphTargetItem it = list.get(t);
List<GraphTargetItem> checkedBody = null;
GraphTargetItem checkedCondition = null;
Loop checkedLoop = null;
if (it instanceof WhileItem) {
WhileItem wi = (WhileItem) it;
if ((!wi.commands.isEmpty()) && (wi.commands.get(0) instanceof SetTypeActionItem)) {
SetTypeActionItem sti = (SetTypeActionItem) wi.commands.get(0);
if (wi.expression.get(wi.expression.size() - 1) instanceof NeqActionItem) {
NeqActionItem ne = (NeqActionItem) wi.expression.get(wi.expression.size() - 1);
if (ne.rightSide instanceof DirectValueActionItem) {
DirectValueActionItem dv = (DirectValueActionItem) ne.rightSide;
if (dv.value == Null.INSTANCE) {
GraphTargetItem en = list.get(t - 1);
if (en instanceof EnumerateActionItem) {
EnumerateActionItem eti = (EnumerateActionItem) en;
list.remove(t);
wi.commands.remove(0);
list.add(t, new ForInActionItem(null, null, wi.loop, sti.getObject(), eti.object, wi.commands));
list.remove(t - 1);
t--;
checkedBody = wi.commands;
checkedCondition = wi.expression.get(wi.expression.size() - 1);
checkedLoop = wi.loop;
} else if (it instanceof IfItem) {
IfItem ifi = (IfItem) it;
if (ifi.onFalse.isEmpty()) {
checkedBody = ifi.onTrue;
checkedCondition = ifi.expression;
checkedLoop = null;
}
}
if (checkedBody != null && (!checkedBody.isEmpty()) && (checkedBody.get(0) instanceof SetTypeActionItem)) {
SetTypeActionItem sti = (SetTypeActionItem) checkedBody.get(0);
if (checkedCondition instanceof NeqActionItem) {
NeqActionItem ne = (NeqActionItem) checkedCondition;
if (ne.rightSide instanceof DirectValueActionItem) {
DirectValueActionItem dv = (DirectValueActionItem) ne.rightSide;
if (dv.value == Null.INSTANCE) {
GraphTargetItem en = list.get(t - 1);
if (en instanceof EnumerateActionItem) {
EnumerateActionItem eti = (EnumerateActionItem) en;
list.remove(t);
checkedBody.remove(0);
if (checkedLoop == null) {
checkedLoop = new Loop(localData.loops.size(), null, null);
checkedBody.add(new BreakItem(null, null, checkedLoop.id));
}
list.add(t, new ForInActionItem(null, null, checkedLoop, sti.getObject(), eti.object, checkedBody));
list.remove(t - 1);
t--;
}
}
}
}
}
}
//Handle for loops at the end:
super.finalProcess(list, level, localData);
super.finalProcess(list, level, localData, path);
}
@@ -300,59 +324,102 @@ public class ActionGraph extends Graph {
stack.push(set);
} else {
part = part.nextParts.get(1);
//caseBodyParts.add(part);
GraphPart defaultPart = part;
if (code.size() > defaultPart.start && code.get(defaultPart.start) instanceof ActionJump) {
defaultPart = defaultPart.nextParts.get(0);
}
GraphPart breakPart = getMostCommonPart(localData, caseBodyParts, loops);
List<GraphTargetItem> caseValues = new ArrayList<>();
boolean hasDefault = false;
for (int i = 0; i < caseBodyParts.size(); i++) {
caseValues.add(caseValuesMap.get(i));
/*
case 4:
case 5:
default:
trace("5 & def");
...
case 6:
*/
//must go backwards to hit case 5, not case 4
for (int i = caseBodyParts.size() - 1; i >= 0; i--) {
if (caseBodyParts.get(i) == defaultPart) {
i++;
caseValuesMap.add(i, new DefaultItem());
caseBodyParts.add(i, defaultPart);
caseValues.add(caseValuesMap.get(i));
DefaultItem di = new DefaultItem();
caseValuesMap.add(i + 1, di);
caseBodyParts.add(i + 1, defaultPart);
hasDefault = true;
break;
}
}
if (!hasDefault) {
//List<GraphPart> stops = new ArrayList<>();
//stops.addAll(caseBodyParts);
for (int i = 0; i < caseBodyParts.size(); i++) {
if (defaultPart.leadsTo(localData, this, code, caseBodyParts.get(i), loops)) {
caseValuesMap.add(i, new DefaultItem());
caseBodyParts.add(i, defaultPart);
caseValues.add(i, caseValuesMap.get(i));
/*
case 1:
trace("1");
case 2:
trace("2"); //no break
default:
trace("def");
...
case 3:
*/
//must go backwards to hit case 2, not case 1
for (int i = caseBodyParts.size() - 1; i >= 0; i--) {
if (caseBodyParts.get(i).leadsTo(localData, this, code, defaultPart, loops)) {
DefaultItem di = new DefaultItem();
caseValuesMap.add(i + 1, di);
caseBodyParts.add(i + 1, defaultPart);
hasDefault = true;
break;
}
}
}
if (!hasDefault) {
caseValuesMap.add(new DefaultItem());
caseBodyParts.add(defaultPart);
caseValues.add(caseValuesMap.get(caseValuesMap.size() - 1));
/*
case 1:
trace("1");
break;
default:
trace("def"); //no break
case 2:
trace("2");
*/
for (int i = 0; i < caseBodyParts.size(); i++) {
if (defaultPart.leadsTo(localData, this, code, caseBodyParts.get(i), loops)) {
DefaultItem di = new DefaultItem();
caseValuesMap.add(i, di);
caseBodyParts.add(i, defaultPart);
hasDefault = true;
break;
}
}
}
List<List<GraphTargetItem>> caseCommands = new ArrayList<>();
GraphPart next;
if (!hasDefault) {
/*
case 1:
...
case 2:
...
default:
trace("def");
*/
caseValuesMap.add(new DefaultItem());
caseBodyParts.add(defaultPart);
}
next = breakPart;
GraphPart breakPart = getMostCommonPart(localData, caseBodyParts, loops);
List<List<GraphTargetItem>> caseCommands = new ArrayList<>();
GraphPart next = breakPart;
GraphTargetItem ti = checkLoop(next, stopPart, loops);
//create switch as new loop break command detection to work
currentLoop = new Loop(loops.size(), null, next);
currentLoop.phase = 1;
loops.add(currentLoop);
//switchLoc.getNextPartPath(new ArrayList<GraphPart>());
List<Integer> valuesMapping = new ArrayList<>();
List<GraphPart> caseBodies = new ArrayList<>();
for (int i = 0; i < caseValues.size(); i++) {
for (int i = 0; i < caseValuesMap.size(); i++) {
GraphPart cur = caseBodyParts.get(i);
if (!caseBodies.contains(cur)) {
caseBodies.add(cur);
@@ -360,45 +427,36 @@ public class ActionGraph extends Graph {
valuesMapping.add(caseBodies.indexOf(cur));
}
/*List<GraphPart> ignored = new ArrayList<>();
for (Loop l : loops) {
ignored.add(l.loopContinue);
}*/
for (int i = 0; i < caseBodies.size(); i++) {
List<GraphTargetItem> cc = new ArrayList<>();
GraphPart nextCase = null;
nextCase = next;
List<GraphTargetItem> currentCaseCommands = new ArrayList<>();
GraphPart nextCase = next;
if (next != null) {
if (i < caseBodies.size() - 1) {
if (!caseBodies.get(i).leadsTo(localData, this, code, caseBodies.get(i + 1), loops)) {
cc.add(new BreakItem(null, localData.lineStartInstruction, currentLoop.id));
currentCaseCommands.add(new BreakItem(null, localData.lineStartInstruction, currentLoop.id));
} else {
nextCase = caseBodies.get(i + 1);
}
}
}
List<GraphPart> stopPart2x = new ArrayList<>(stopPart);
//stopPart2.add(nextCase);
for (GraphPart b : caseBodies) {
if (b != caseBodies.get(i)) {
stopPart2x.add(b);
}
}
/*if (defaultPart != null) {
stopPart2x.add(defaultPart);
}*/
if (breakPart != null) {
stopPart2x.add(breakPart);
}
cc.addAll(0, printGraph(partCodes, partCodePos, localData, stack, allParts, null, caseBodies.get(i), stopPart2x, loops, staticOperation, path));
if (cc.size() >= 2) {
if (cc.get(cc.size() - 1) instanceof BreakItem) {
if ((cc.get(cc.size() - 2) instanceof ContinueItem) || (cc.get(cc.size() - 2) instanceof BreakItem)) {
cc.remove(cc.size() - 1);
currentCaseCommands.addAll(0, printGraph(partCodes, partCodePos, localData, stack, allParts, null, caseBodies.get(i), stopPart2x, loops, staticOperation, path));
if (currentCaseCommands.size() >= 2) {
if (currentCaseCommands.get(currentCaseCommands.size() - 1) instanceof BreakItem) {
if ((currentCaseCommands.get(currentCaseCommands.size() - 2) instanceof ContinueItem) || (currentCaseCommands.get(currentCaseCommands.size() - 2) instanceof BreakItem)) {
currentCaseCommands.remove(currentCaseCommands.size() - 1);
}
}
}
caseCommands.add(cc);
caseCommands.add(currentCaseCommands);
}
//If the lastone is default empty and alone, remove it
@@ -410,15 +468,16 @@ public class ActionGraph extends Graph {
}
if (lastc.isEmpty()) {
int cnt2 = 0;
if (caseValues.get(caseValues.size() - 1) instanceof DefaultItem) {
if (caseValuesMap.get(caseValuesMap.size() - 1) instanceof DefaultItem) {
for (int i = valuesMapping.size() - 1; i >= 0; i--) {
if (valuesMapping.get(i) == caseCommands.size() - 1) {
cnt2++;
}
}
caseValuesMap.remove(caseValuesMap.size() - 1);
valuesMapping.remove(valuesMapping.size() - 1);
if (cnt2 == 1) {
caseValues.remove(caseValues.size() - 1);
valuesMapping.remove(valuesMapping.size() - 1);
caseCommands.remove(lastc);
}
}
@@ -430,13 +489,12 @@ public class ActionGraph extends Graph {
if (!lastc.isEmpty() && (lastc.get(lastc.size() - 1) instanceof BreakItem)) {
BreakItem bi = (BreakItem) lastc.get(lastc.size() - 1);
lastc.remove(lastc.size() - 1);
}
}
ret = new ArrayList<>();
ret.addAll(output);
SwitchItem sti = new SwitchItem(null, switchStartItem, currentLoop, switchedObject, caseValues, caseCommands, valuesMapping);
SwitchItem sti = new SwitchItem(null, switchStartItem, currentLoop, switchedObject, caseValuesMap, caseCommands, valuesMapping);
ret.add(sti);
currentLoop.phase = 2;
if (next != null) {
@@ -454,15 +512,15 @@ public class ActionGraph extends Graph {
@Override
protected int checkIp(int ip) {
int oldIp = ip;
//return in for..in
//return/break in for..in
GraphSourceItem action = code.get(ip);
if ((action instanceof ActionPush) && (((ActionPush) action).values.size() == 1) && (((ActionPush) action).values.get(0) == Null.INSTANCE)) {
if (ip + 4 < code.size()) {
if (ip + 3 <= code.size()) {
if ((code.get(ip + 1) instanceof ActionEquals) || (code.get(ip + 1) instanceof ActionEquals2)) {
if (code.get(ip + 2) instanceof ActionNot) {
if (code.get(ip + 3) instanceof ActionIf) {
ActionIf aif = (ActionIf) code.get(ip + 3);
if (code.adr2pos(code.pos2adr(ip + 4) + aif.getJumpOffset()) == ip) {
if (code.adr2pos(code.pos2adr(ip + 3) + 5 /*IF numbytes*/ + aif.getJumpOffset()) == ip) {
ip += 4;
}
}
@@ -471,6 +529,9 @@ public class ActionGraph extends Graph {
}
}
if (oldIp != ip) {
if (ip == code.size()) { //no next checkIp call since its after code size
return ip;
}
return checkIp(ip);
}
return ip;
@@ -12,11 +12,12 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. */
* License along with this library.
*/
package com.jpexs.decompiler.flash.action;
import com.jpexs.decompiler.flash.BaseLocalData;
import com.jpexs.decompiler.flash.abc.avm2.parser.script.Reference;
import com.jpexs.helpers.Reference;
import com.jpexs.decompiler.graph.GraphPart;
import com.jpexs.decompiler.graph.GraphSource;
import com.jpexs.decompiler.graph.GraphSourceItem;
@@ -45,16 +46,22 @@ public class ActionGraphSource extends GraphSource {
private final HashMap<String, GraphTargetItem> functions;
private final boolean insideDoInitAction;
private final String path;
public List<Action> getActions() {
return actions;
}
public ActionGraphSource(List<Action> actions, int version, HashMap<Integer, String> registerNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions) {
public ActionGraphSource(String path, boolean insideDoInitAction, List<Action> actions, int version, HashMap<Integer, String> registerNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions) {
this.actions = actions;
this.version = version;
this.registerNames = registerNames;
this.variables = variables;
this.functions = functions;
this.insideDoInitAction = insideDoInitAction;
this.path = path;
}
@Override
@@ -80,7 +87,7 @@ public class ActionGraphSource extends GraphSource {
public List<GraphTargetItem> translatePart(GraphPart part, BaseLocalData localData, TranslateStack stack, int start, int end, int staticOperation, String path) throws InterruptedException {
Reference<GraphSourceItem> fi = new Reference<>(localData.lineStartInstruction);
List<GraphTargetItem> r = Action.actionsPartToTree(fi, registerNames, variables, functions, stack, actions, start, end, version, staticOperation, path);
List<GraphTargetItem> r = Action.actionsPartToTree(this.insideDoInitAction, fi, registerNames, variables, functions, stack, actions, start, end, version, staticOperation, path);
localData.lineStartInstruction = fi.getVal();
return r;
}
@@ -135,7 +142,7 @@ public class ActionGraphSource extends GraphSource {
}
//ret = adr2posInside(adr);
if (ret == -1) {
Logger.getLogger(ActionGraphSource.class.getName()).log(Level.SEVERE, "Address loc" + Helper.formatAddress(adr) + " not found");
Logger.getLogger(ActionGraphSource.class.getName()).log(Level.SEVERE, "{0} - address loc{1} not found", new Object[]{path, Helper.formatAddress(adr)});
/*System.err.println("Addr loc"+Helper.formatAddress(adr)+" not found");
int pos=0;
for(long l:posCache){
@@ -12,7 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. */
* License along with this library.
*/
package com.jpexs.decompiler.flash.action;
import com.jpexs.decompiler.flash.DisassemblyListener;
@@ -31,7 +32,11 @@ import com.jpexs.decompiler.flash.configuration.Configuration;
import com.jpexs.decompiler.flash.helpers.SWFDecompilerPlugin;
import com.jpexs.decompiler.graph.GraphSourceItemContainer;
import com.jpexs.helpers.CancellableWorker;
import com.jpexs.helpers.Helper;
import com.jpexs.helpers.stat.Statistics;
import com.jpexs.helpers.utf8.Utf8Helper;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
@@ -163,6 +168,15 @@ public class ActionListReader {
}
}
//TODO: This cleaner needs to be executed only before actual decompilation, not when disassembly only
try {
new ActionDefineFunctionPushRegistersCleaner().actionListParsed(actions, sis.getSwf());
} catch (ThreadDeath | InterruptedException ex) {
throw ex;
} catch (Throwable ex) {
logger.log(Level.SEVERE, "Cleaning push registers in ActionDefineFunction failed: " + path, ex);
}
return actions;
}
@@ -12,7 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. */
* License along with this library.
*/
package com.jpexs.decompiler.flash.action;
import com.jpexs.decompiler.flash.BaseLocalData;
@@ -34,21 +35,26 @@ public class ActionLocalData extends BaseLocalData {
public GraphSourceItem lineStartAction;
public ActionLocalData() {
public boolean insideDoInitAction;
public ActionLocalData(boolean insideDoInitAction) {
regNames = new HashMap<>();
variables = new HashMap<>();
functions = new HashMap<>();
this.insideDoInitAction = insideDoInitAction;
}
public ActionLocalData(HashMap<Integer, String> regNames) {
public ActionLocalData(boolean insideDoInitAction, HashMap<Integer, String> regNames) {
this.regNames = regNames;
variables = new HashMap<>();
functions = new HashMap<>();
this.insideDoInitAction = insideDoInitAction;
}
public ActionLocalData(HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions) {
public ActionLocalData(boolean insideDoInitAction, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions) {
this.regNames = regNames;
this.variables = variables;
this.functions = functions;
this.insideDoInitAction = insideDoInitAction;
}
}
@@ -0,0 +1,738 @@
/*
* Copyright (C) 2010-2018 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.action;
import com.jpexs.decompiler.flash.action.model.CallFunctionActionItem;
import com.jpexs.helpers.Reference;
import com.jpexs.decompiler.flash.action.model.CallMethodActionItem;
import com.jpexs.decompiler.flash.action.model.DirectValueActionItem;
import com.jpexs.decompiler.flash.action.model.ExtendsActionItem;
import com.jpexs.decompiler.flash.action.model.FunctionActionItem;
import com.jpexs.decompiler.flash.action.model.GetMemberActionItem;
import com.jpexs.decompiler.flash.action.model.GetVariableActionItem;
import com.jpexs.decompiler.flash.action.model.ImplementsOpActionItem;
import com.jpexs.decompiler.flash.action.model.NewMethodActionItem;
import com.jpexs.decompiler.flash.action.model.NewObjectActionItem;
import com.jpexs.decompiler.flash.action.model.SetMemberActionItem;
import com.jpexs.decompiler.flash.action.model.SetVariableActionItem;
import com.jpexs.decompiler.flash.action.model.StoreRegisterActionItem;
import com.jpexs.decompiler.flash.action.model.TemporaryRegister;
import com.jpexs.decompiler.flash.action.model.clauses.ClassActionItem;
import com.jpexs.decompiler.flash.action.model.clauses.InterfaceActionItem;
import com.jpexs.decompiler.flash.action.swf4.RegisterNumber;
import com.jpexs.decompiler.flash.ecma.Null;
import com.jpexs.decompiler.flash.helpers.collections.MyEntry;
import com.jpexs.decompiler.graph.GraphTargetItem;
import com.jpexs.decompiler.graph.model.IfItem;
import com.jpexs.decompiler.graph.model.NotItem;
import com.jpexs.decompiler.graph.model.PopItem;
import com.jpexs.decompiler.graph.model.PushItem;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
*
* @author JPEXS
*/
public class ActionScript2ClassDetector {
private static final Logger logger = Logger.getLogger(ActionScript2ClassDetector.class.getName());
private class AssertException extends Exception {
private final String condition;
public AssertException(String condition) {
super(condition);
this.condition = condition;
}
public String getCondition() {
return condition;
}
}
/**
* Checks whether an item is direct submember of path. a.b.c.d is submember
* of a.b.c, x.y.z is not submember of x,
*
* @param item
* @param objectPath
* @param newPathItem New submember name
* @return
*/
private boolean isMemberOfPath(GraphTargetItem item, List<String> objectPath, Reference<String> newPathItem) {
List<String> path = getMembersPath(item);
if (path == null) {
return false;
}
if (path.size() != objectPath.size() + 1) {
return false;
}
for (int i = 0; i < objectPath.size(); i++) {
if (!path.get(i).equals(objectPath.get(i))) {
return false;
}
}
newPathItem.setVal(path.get(path.size() - 1));
return true;
}
/**
* Gets path of variable and its getMembers: a.b.c.d => [a,b,c,d]
*
* @param item
* @return List of path or null if not members path
*/
private List<String> getMembersPath(GraphTargetItem item) {
List<String> ret = new ArrayList<>();
while (item instanceof GetMemberActionItem) {
GetMemberActionItem mem = (GetMemberActionItem) item;
if (!(mem.memberName instanceof DirectValueActionItem)) {
return null;
}
DirectValueActionItem dv = ((DirectValueActionItem) mem.memberName);
if (!dv.isString()) {
return null;
}
ret.add(0, dv.getAsString());
item = mem.object;
}
if (!(item instanceof GetVariableActionItem)) {
return null;
}
GetVariableActionItem gv = (GetVariableActionItem) item;
if (!(gv.name instanceof DirectValueActionItem)) {
return null;
}
DirectValueActionItem dv = ((DirectValueActionItem) gv.name);
if (!dv.isString()) {
return null;
}
String varName = dv.getAsString();
ret.add(0, varName);
return ret;
}
private GraphTargetItem setMemberToGetMember(GraphTargetItem item) {
if (item instanceof SetMemberActionItem) {
return new GetMemberActionItem(null, null, ((SetMemberActionItem) item).object, ((SetMemberActionItem) item).objectName);
} else if (item instanceof SetVariableActionItem) {
return new GetVariableActionItem(null, null, ((SetVariableActionItem) item).name);
}
return null;
}
private GraphTargetItem newToGetMember(GraphTargetItem nobj) throws AssertException {
if (nobj instanceof NewMethodActionItem) {
NewMethodActionItem nm = (NewMethodActionItem) nobj;
return new GetMemberActionItem(nobj.getSrc(), nobj.getLineStartItem(), nm.scriptObject, nm.methodName);
} else if (nobj instanceof NewObjectActionItem) {
NewObjectActionItem no = (NewObjectActionItem) nobj;
return new GetVariableActionItem(nobj.getSrc(), nobj.getLineStartItem(), no.objectName);
}
throw new AssertException("NewMethod or NewObject expected");
}
private List<String> getSetMembersPath(GraphTargetItem item) {
if (item instanceof SetVariableActionItem) {
SetVariableActionItem sv = (SetVariableActionItem) item;
if (!(sv.name instanceof DirectValueActionItem)) {
return null;
}
DirectValueActionItem nDv = (DirectValueActionItem) sv.name;
if (!nDv.isString()) {
return null;
}
List<String> ret = new ArrayList<>();
ret.add(nDv.getAsString());
return ret;
} else if (item instanceof SetMemberActionItem) {
SetMemberActionItem sm = (SetMemberActionItem) item;
if (!(sm.objectName instanceof DirectValueActionItem)) {
return null;
}
DirectValueActionItem onDv = (DirectValueActionItem) sm.objectName;
if (!onDv.isString()) {
return null;
}
String currentMemberName = onDv.getAsString();
List<String> path = getMembersPath(sm.object);
if (path == null) {
return null;
}
path.add(currentMemberName);
return path;
} else {
return null;
}
}
/**
* Get register id or -1 if not found
*
* @param item
* @return
*/
private int getAsRegisterNum(GraphTargetItem item, String assertName) throws AssertException {
if (item instanceof DirectValueActionItem) {
DirectValueActionItem dv = (DirectValueActionItem) item;
if (dv.value instanceof RegisterNumber) {
RegisterNumber rn = (RegisterNumber) dv.value;
return rn.number;
}
}
if (item instanceof TemporaryRegister) {
TemporaryRegister tr = (TemporaryRegister) item;
return tr.getRegId();
}
throw new AssertException("not a register - " + assertName);
}
/*private boolean isInstanceRegister(GraphTargetItem item, Reference<Integer> instanceReg, Reference<Integer> classReg,Reference<GraphTargetItem> extracted, String assertName) throws AssertException {
if (item instanceof DirectValueActionItem) {
DirectValueActionItem dv = (DirectValueActionItem) item;
if (dv.value instanceof RegisterNumber) {
RegisterNumber rn = (RegisterNumber) dv.value;
if (rn.number == instanceReg.getVal()) {
return true;
} else if (rn.number == classReg.getVal()) {
return false;
}else{
throw new AssertException(assertName + " - unknown register");
}
}
}
if (item instanceof TemporaryRegister) {
TemporaryRegister tr = (TemporaryRegister) item;
if (!"prototype".equals(getAsString(gm.memberName, "memberName"))) {
throw new AssertException("memberName not \"prototype\"");
}
return tr.getRegId();
}
}
*/
private static GraphTargetItem getWithoutGlobal(GraphTargetItem ti) {
GraphTargetItem t = ti;
if (!(t instanceof GetMemberActionItem)) {
return ti;
}
GetMemberActionItem lastMember = null;
while (((GetMemberActionItem) t).object instanceof GetMemberActionItem) {
lastMember = (GetMemberActionItem) t;
t = ((GetMemberActionItem) t).object;
}
if (((GetMemberActionItem) t).object instanceof GetVariableActionItem) {
GetVariableActionItem v = (GetVariableActionItem) ((GetMemberActionItem) t).object;
if (v.name instanceof DirectValueActionItem) {
if (((DirectValueActionItem) v.name).value instanceof String) {
if (((DirectValueActionItem) v.name).value.equals("_global")) {
GetVariableActionItem gvt = new GetVariableActionItem(null, null, ((GetMemberActionItem) t).memberName);
if (lastMember == null) {
return gvt;
} else {
lastMember.object = gvt;
}
}
}
}
}
return ti;
}
private String getAsString(GraphTargetItem item, String itemName) throws AssertException {
if (!(item instanceof DirectValueActionItem)) {
throw new AssertException(itemName + " not DirectValue");
}
DirectValueActionItem mnDv = (DirectValueActionItem) item;
if (!mnDv.isString()) {
throw new AssertException(itemName + " not string");
}
return mnDv.getAsString();
}
private boolean checkClassContent(List<GraphTargetItem> parts, int partsPos, int commandsStartPos, int commandsEndPos, List<GraphTargetItem> commands, List<String> classNamePath, String scriptPath) {
try {
GraphTargetItem item = parts.get(partsPos);
GraphTargetItem extendsOp = null;
List<GraphTargetItem> implementsOp = new ArrayList<>();
if (item instanceof ExtendsActionItem) {
ExtendsActionItem et = (ExtendsActionItem) parts.get(partsPos);
extendsOp = getWithoutGlobal(et.superclass);
partsPos++;
item = parts.get(partsPos);
}
int instanceReg = -1;
int classReg = -1;
GraphTargetItem classNameTargetPath = null;
GraphTargetItem constructor = null;
if (item instanceof StoreRegisterActionItem) {
StoreRegisterActionItem sr = (StoreRegisterActionItem) item;
instanceReg = sr.register.number;
if (sr.value instanceof GetMemberActionItem) {
GetMemberActionItem gm = (GetMemberActionItem) sr.value;
if (gm.object instanceof TemporaryRegister) {
TemporaryRegister treg = (TemporaryRegister) gm.object;
classReg = treg.getRegId();
if (!"prototype".equals(getAsString(gm.memberName, "memberName"))) {
throw new AssertException("memberName not \"prototype\"");
}
if ((treg.value instanceof SetMemberActionItem) || (treg.value instanceof SetVariableActionItem)) {
List<String> path = getSetMembersPath(treg.value);
if (path == null || path.isEmpty()) {
throw new AssertException("Cannot detect class - tempreg value is not a path");
}
//remove _global if it's there - happens for classes in global package
if ("_global".equals(path.get(0))) {
path.remove(0);
}
if (classNamePath.equals(path)) {
//can start with _global for classes on top level
classNameTargetPath = getWithoutGlobal(setMemberToGetMember(treg.value));
//treg.value.value is the value being set - treg.value is setmember ot setvariable
if (!(treg.value.value instanceof StoreRegisterActionItem)) {
throw new AssertException("Constructor expected to be in storeregister");
}
if (!(treg.value.value.value instanceof FunctionActionItem)) {
throw new AssertException("Constructor expected as functionitem");
}
constructor = treg.value.value.value;
} else {
throw new AssertException("temporaryreg value does not match class path");
}
} else {
throw new AssertException("temporaryreg value not setmember/setvariable");
}
} else {
throw new AssertException("Getmember does not have TemporaryRegister as object");
}
} else {
throw new AssertException("Not Getmember in StoreRegister");
}
partsPos++;
}
List<MyEntry<GraphTargetItem, GraphTargetItem>> traits = new ArrayList<>();
List<Boolean> traitsStatic = new ArrayList<>();
loopsetmembers:
for (; partsPos < parts.size(); partsPos++) {
item = parts.get(partsPos);
if (item instanceof PushItem) { //push is optional
PushItem pi = (PushItem) item;
item = pi.value;
}
if (item instanceof SetMemberActionItem) {
SetMemberActionItem sm = (SetMemberActionItem) item;
GraphTargetItem regValue;
int currentRegId = -1;
if (sm.object instanceof TemporaryRegister) {
TemporaryRegister tempReg = (TemporaryRegister) sm.object;
currentRegId = tempReg.getRegId();
regValue = tempReg.value;
} else if ((sm.object instanceof DirectValueActionItem) && (((DirectValueActionItem) sm.object).value instanceof RegisterNumber)) {
DirectValueActionItem dv = (DirectValueActionItem) sm.object;
RegisterNumber rn = ((RegisterNumber) dv.value);
currentRegId = rn.number;
regValue = dv.computedRegValue;
} else {
//might be an interface
List<String> path = getSetMembersPath(item);
if (path == null || path.isEmpty()) {
throw new AssertException("invalid setmember");
}
//remove _global if it's there - happens for classes in global package
if ("_global".equals(path.get(0))) {
path.remove(0);
}
if (!path.equals(classNamePath)) {
throw new AssertException("wrong path in setmember");
}
GraphTargetItem interfaceClass = getWithoutGlobal(setMemberToGetMember(item));
if (!(sm.value instanceof FunctionActionItem)) {
throw new AssertException("not a function in setmember");
}
FunctionActionItem f = (FunctionActionItem) sm.value;
if (!"".equals(f.functionName)) {
throw new AssertException("not unnamed func in setmember");
}
if (!f.actions.isEmpty()) {
throw new AssertException("not empty function in setmember");
}
if (!f.paramNames.isEmpty()) {
throw new AssertException("not empty params for function in setmember");
}
partsPos++;
for (; partsPos < parts.size(); partsPos++) {
item = parts.get(partsPos);
if (item instanceof ImplementsOpActionItem) {
if (!implementsOp.isEmpty()) {
throw new AssertException("multiple implementsAction");
}
ImplementsOpActionItem io = (ImplementsOpActionItem) item;
implementsOp = io.superclasses;
} else {
throw new AssertException("unknown iface item: " + item.getClass().getSimpleName());
}
}
InterfaceActionItem ifsItem = new InterfaceActionItem(interfaceClass, implementsOp);
for (int k = commandsStartPos; k <= commandsEndPos; k++) {
commands.remove(commandsStartPos);
}
commands.add(commandsStartPos, ifsItem);
//remove §§pop after, if it's there
if (commandsStartPos + 1 < commands.size()) {
if (commands.get(commandsStartPos + 1) instanceof PopItem) {
commands.remove(commandsStartPos + 1);
}
}
// goto next line and check next classes
return true;
}
//it was register .. continue class detection
if (currentRegId != instanceReg && currentRegId != classReg) {
if (!(regValue instanceof SetMemberActionItem)) {
throw new AssertException("temp register do not contain setmember");
}
SetMemberActionItem sm2 = (SetMemberActionItem) regValue;
GraphTargetItem pathSource;
boolean isPrototype;
if ("prototype".equals(getAsString(sm2.objectName, "objectName"))) {
pathSource = sm2.object;
isPrototype = true;
} else {
pathSource = setMemberToGetMember(sm2);
isPrototype = false;
}
List<String> memPath = getMembersPath(pathSource);
if (memPath == null) {
throw new AssertException("Invalid pathsource");
}
if (!classNamePath.equals(memPath)) {
throw new AssertException("Invalid path of setmember:" + String.join(".", memPath));
}
classNameTargetPath = pathSource;
if (!(sm2.value instanceof StoreRegisterActionItem)) {
throw new AssertException("Not storeregister");
}
StoreRegisterActionItem sr = (StoreRegisterActionItem) sm2.value;
if (sr.register.number != currentRegId) {
throw new AssertException("Invalid storeregister");
}
if (isPrototype && ((sr.value instanceof NewMethodActionItem) || (sr.value instanceof NewObjectActionItem))) {
extendsOp = newToGetMember(sr.value);
instanceReg = currentRegId;
} else if (!isPrototype && (sr.value instanceof FunctionActionItem)) { //constructor
constructor = sr.value;
classReg = currentRegId;
} else {
throw new AssertException("invalid storeregister value: " + sr.value.getClass().getSimpleName());
}
}
MyEntry<GraphTargetItem, GraphTargetItem> trait = new MyEntry<>(sm.objectName, sm.value);
if (sm.value instanceof FunctionActionItem) {
FunctionActionItem f = (FunctionActionItem) sm.value;
f.calculatedFunctionName = sm.objectName;
}
traits.add(trait);
if (currentRegId == instanceReg) {
traitsStatic.add(false);
} else if (currentRegId == classReg) {
traitsStatic.add(true);
}
} else if (item instanceof ImplementsOpActionItem) {
ImplementsOpActionItem iot = (ImplementsOpActionItem) item;
implementsOp = iot.superclasses;
} else if (item instanceof CallMethodActionItem) {
CallMethodActionItem cm = (CallMethodActionItem) item;
String pushMethodName = getAsString(cm.methodName, "push methodName");
if ("addProperty".equals(pushMethodName)) {
int rnumObject = getAsRegisterNum(cm.scriptObject, "addProperty not on register");
if ((rnumObject != instanceReg) && (rnumObject != classReg)) {
throw new AssertException("unexpected addProperty object register " + rnumObject);
}
if (cm.arguments.size() != 3) {
throw new AssertException("invalid number of arguments to addProperty: " + cm.arguments.size());
}
GraphTargetItem propertyName = cm.arguments.get(0);
GraphTargetItem propertyGetter = cm.arguments.get(1);
GraphTargetItem propertySetter = cm.arguments.get(2);
String propertyNameStr = getAsString(propertyName, "propertyName");
if (propertyGetter instanceof GetMemberActionItem) {
int regId = getAsRegisterNum(((GetMemberActionItem) propertyGetter).object, "getter member not register");
if (rnumObject != regId) {
throw new AssertException("getter register does not match property register " + regId + " <=> " + rnumObject);
}
String getterNameStr = getAsString(((GetMemberActionItem) propertyGetter).memberName, "getter memberName");
if (!(getterNameStr.equals("__get__" + propertyNameStr))) {
throw new AssertException("getter does not match property name");
}
//TODO: handle getter HERE
} else if (propertyGetter instanceof FunctionActionItem) {
FunctionActionItem getterFunc = (FunctionActionItem) propertyGetter;
if (!(getterFunc.actions.isEmpty() && getterFunc.functionName.isEmpty() && ((FunctionActionItem) propertyGetter).paramNames.isEmpty())) {
throw new AssertException("unexpected getter value for property " + propertyNameStr);
}
//we got empty getter
} else {
throw new AssertException("unexpected getter value for property " + propertyNameStr + ": " + propertyGetter.getClass().getSimpleName());
}
if (propertySetter instanceof GetMemberActionItem) {
int regId = getAsRegisterNum(((GetMemberActionItem) propertySetter).object, "setter member");
if (rnumObject != regId) {
throw new AssertException("setter register does not match property register " + regId + " <=> " + rnumObject);
}
String setterNameStr = getAsString(((GetMemberActionItem) propertySetter).memberName, "setter memberNAme");
if (!(setterNameStr.equals("__set__" + propertyNameStr))) {
throw new AssertException("setter does not match property name");
}
//TODO: handle setter HERE
} else if (propertySetter instanceof FunctionActionItem) {
FunctionActionItem setterFunc = (FunctionActionItem) propertySetter;
if (!(setterFunc.actions.isEmpty() && setterFunc.functionName.isEmpty() && ((FunctionActionItem) propertySetter).paramNames.isEmpty())) {
throw new AssertException("unexpected getter value for property " + propertyNameStr);
}
//we got empty setter
} else {
throw new AssertException("unexpected setter value for property " + propertyNameStr + ": " + propertySetter.getClass().getSimpleName());
}
} else {
throw new AssertException("unknown push method name: " + pushMethodName);
}
} else if (item instanceof CallFunctionActionItem) {
CallFunctionActionItem cf = (CallFunctionActionItem) item;
String funName = getAsString(cf.functionName, "pushitem function name");
if (funName.equals("ASSetPropFlags")) {
//it should be ASSetPropFlags(a.b.c.D.prototype,null,1) as it sets prototype to hidden
//see http://www.ryanjuckett.com/programming/how-to-use-assetpropflags-in-actionscript-2-0/
if (cf.arguments.size() != 3) {
throw new AssertException("Invalid number of arguments to ASSetPropFlags:" + cf.arguments.size() + ", 3 expected");
}
GraphTargetItem obj = cf.arguments.get(0);
GraphTargetItem props = cf.arguments.get(1);
GraphTargetItem flags = cf.arguments.get(2);
if ((obj instanceof DirectValueActionItem) && (((DirectValueActionItem) obj).value instanceof RegisterNumber)) {
RegisterNumber rn = (RegisterNumber) ((DirectValueActionItem) obj).value;
if (rn.number != instanceReg) {
throw new AssertException("ASSetPropFlags not on instanceReg");
}
} else {
List<String> path = getMembersPath(obj);
if (path != null && !path.isEmpty() && "_global".equals(path.get(0))) { //For classes in toplevel package, there's _global in path
path.remove(0); //remove that _global
}
List<String> classPathWithPrototype = new ArrayList<>();
classPathWithPrototype.addAll(classNamePath);
classPathWithPrototype.add("prototype");
if (!classPathWithPrototype.equals(path)) {
throw new AssertException("ASSetPropFlags not on prototype");
}
}
if (!((props instanceof DirectValueActionItem) && (((DirectValueActionItem) props).value == Null.INSTANCE))) {
throw new AssertException("ASSetPropFlags properties param not null");
}
if (!((flags instanceof DirectValueActionItem) && (((DirectValueActionItem) flags).value == (Long) 1L))) {
throw new AssertException("ASSetPropFlags flags not set to 1");
}
} else {
throw new AssertException("unknown pushitem function call " + funName);
}
} else {
throw new AssertException("unknown item - " + item.getClass().getSimpleName());
}
}
if (constructor != null) { //constructor should be there always, but just in calse
//add constructor as trait
traitsStatic.add(0, false);
DirectValueActionItem classBaseName = new DirectValueActionItem(classNamePath.get(classNamePath.size() - 1));
((FunctionActionItem) constructor).calculatedFunctionName = classBaseName;
traits.add(0, new MyEntry<>(classBaseName, constructor));
} else {
throw new AssertException("No constructor found");
}
ClassActionItem clsItem = new ClassActionItem(classNameTargetPath, extendsOp, implementsOp, traits, traitsStatic);
for (int k = commandsStartPos; k <= commandsEndPos; k++) {
commands.remove(commandsStartPos);
}
commands.add(commandsStartPos, clsItem);
//remove §§pop after, if it's there
if (commandsStartPos + 1 < commands.size()) {
if (commands.get(commandsStartPos + 1) instanceof PopItem) {
commands.remove(commandsStartPos + 1);
}
}
// goto next line and check next classes
return true;
} catch (AssertException ex) {
logger.log(Level.WARNING, "{0}: Cannot detect class - {1}", new Object[]{scriptPath, ex.getCondition()});
}
return false;
}
private boolean checkIfVariants(List<GraphTargetItem> commands, int pos, String scriptPath) {
/*
Variant 1:
if(!_global.a)
{
_global.a = new Object();
}
§§pop();
if(!_global.a.b)
{
_global.a.b = new Object();
}
§§pop();
if(!_global.a.b.c)
{
_global.a.b.c = new Object();
}
§§pop();
if(!_global.a.b.c.D)
{
..class_content...
}
§§pop();
*/
List<String> pathToSearchVariant1 = new ArrayList<>();
pathToSearchVariant1.add("_global");
check_variant1:
for (int checkPos = pos; checkPos < commands.size(); checkPos++) {
GraphTargetItem t = commands.get(checkPos);
if (t instanceof IfItem) {
IfItem ifItem = (IfItem) t;
if (ifItem.expression instanceof NotItem) {
NotItem nti = (NotItem) ifItem.expression;
GraphTargetItem condType = nti.value;
Reference<String> newMemberNameRef = new Reference<>("");
if (isMemberOfPath(condType, pathToSearchVariant1, newMemberNameRef)) {
pathToSearchVariant1.add(newMemberNameRef.getVal());
//_global.a.b.c = new Object();
if ((ifItem.onTrue.size() == 1) && (ifItem.onTrue.get(0) instanceof SetMemberActionItem) && (((SetMemberActionItem) ifItem.onTrue.get(0)).value instanceof NewObjectActionItem)) {
//skip §§pop item if its there right after if
if (checkPos + 1 < commands.size()) {
GraphTargetItem tnext = commands.get(checkPos + 1);
if (tnext instanceof PopItem) {
checkPos++;
}
}
continue check_variant1;
}
List<String> classPath = pathToSearchVariant1;
classPath.remove(0); //remove _global
if (this.checkClassContent(ifItem.onTrue, 0, pos, checkPos, commands, classPath, scriptPath)) {
return true;
} else {
break check_variant1;
}
} else {
break check_variant1;
}
} else {
break check_variant1; //not an if !
}
} else {
break check_variant1; //not an if
}
} //check_variant1
/*
Variant 2:
if(!a.b.c.D)
{
if(!a)
{
_global.a = new Object();
}
if(!a.b)
{
_global.a.b = new Object();
}
if(!a.b.c)
{
_global.a.b.c = new Object();
}
..class_content..
}
*/
List<String> variant2CurrentPath = new ArrayList<>();
check_variant2:
if (commands.get(pos) instanceof IfItem) {
IfItem ifItem = (IfItem) commands.get(pos);
if (ifItem.expression instanceof NotItem) {
NotItem nti = (NotItem) ifItem.expression;
List<String> memPath = getMembersPath(nti.value);
if (memPath == null) {
break check_variant2;
}
if (ifItem.onTrue.size() < memPath.size()) {
break check_variant2;
}
variant2CurrentPath.clear();
List<GraphTargetItem> parts = ifItem.onTrue;
int checkPos = 0;
for (; checkPos < memPath.size() - 1; checkPos++) {
variant2CurrentPath.add(memPath.get(checkPos));
if (!(parts.get(checkPos) instanceof IfItem)) {
break check_variant2;
}
IfItem ifItem2 = (IfItem) parts.get(checkPos);
if (ifItem2.expression instanceof NotItem) {
NotItem nti2 = (NotItem) ifItem2.expression;
List<String> if2Path = getMembersPath(nti2.value);
if (!variant2CurrentPath.equals(if2Path)) {
break check_variant2;
}
}
}
if (checkClassContent(parts, checkPos, pos, pos, commands, memPath, scriptPath)) {
return true;
}
}
}//check_variant2
return false;
}
public void checkClass(List<GraphTargetItem> commands, String scriptPath) {
for (int pos = 0; pos < commands.size(); pos++) {
checkIfVariants(commands, pos, scriptPath);
}
}
}
@@ -12,9 +12,11 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. */
* License along with this library.
*/
package com.jpexs.decompiler.flash.action;
import com.jpexs.decompiler.flash.ecma.Null;
import com.jpexs.decompiler.flash.ecma.Undefined;
import java.util.ArrayList;
import java.util.HashMap;
@@ -181,6 +183,6 @@ public class ActionScriptObject implements Cloneable {
}
}
}
return null;
return Undefined.INSTANCE;
}
}
@@ -12,7 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. */
* License along with this library.
*/
package com.jpexs.decompiler.flash.action.deobfuscation;
import com.jpexs.decompiler.flash.IdentifiersDeobfuscation;
@@ -12,7 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. */
* License along with this library.
*/
package com.jpexs.decompiler.flash.action.flashlite;
import com.jpexs.decompiler.flash.BaseLocalData;
@@ -42,7 +43,7 @@ public class ActionFSCommand2 extends Action {
}
@Override
public void translate(GraphSourceItem lineStartItem, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
public void translate(boolean insideDoInitAction, GraphSourceItem lineStartItem, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
long numArgs = popLong(stack);
GraphTargetItem command = stack.pop();
List<GraphTargetItem> args = new ArrayList<>();
@@ -12,7 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. */
* License along with this library.
*/
package com.jpexs.decompiler.flash.action.flashlite;
import com.jpexs.decompiler.flash.SWFInputStream;
@@ -73,7 +74,7 @@ public class ActionStrictMode extends Action {
}
@Override
public void translate(GraphSourceItem lineStartItem, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
public void translate(boolean insideDoInitAction, GraphSourceItem lineStartItem, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
output.add(new StrictModeActionItem(this, lineStartItem, mode));
}
}
@@ -12,7 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. */
* License along with this library.
*/
package com.jpexs.decompiler.flash.action.model;
import com.jpexs.decompiler.flash.IdentifiersDeobfuscation;
@@ -303,7 +304,7 @@ public class FunctionActionItem extends ActionItem {
needsFun2 = true;
}
if (localData.inMethod) {
needsFun2 = true;
//needsFun2 = true;
}
if (localData.inFunction > 1) {
needsFun2 = true;
@@ -12,7 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. */
* License along with this library.
*/
package com.jpexs.decompiler.flash.action.model;
import com.jpexs.decompiler.flash.SourceGeneratorLocalData;
@@ -41,7 +42,11 @@ public class RandomNumberActionItem extends ActionItem {
}
public static Integer getResult(Object maximum) {
return rnd.nextInt(EcmaScript.toInt32(maximum));
int maximumInt = EcmaScript.toInt32(maximum);
if (maximumInt <= 0) {
return 0;
}
return rnd.nextInt(maximumInt);
}
@Override
@@ -12,7 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. */
* License along with this library.
*/
package com.jpexs.decompiler.flash.action.model.clauses;
import com.jpexs.decompiler.flash.SourceGeneratorLocalData;
@@ -44,56 +45,39 @@ import java.util.Set;
*/
public class ClassActionItem extends ActionItem implements Block {
public List<GraphTargetItem> functions;
public List<GraphTargetItem> staticFunctions;
public GraphTargetItem extendsOp;
public List<GraphTargetItem> implementsOp;
public GraphTargetItem className;
public GraphTargetItem constructor;
public List<MyEntry<GraphTargetItem, GraphTargetItem>> vars;
public List<MyEntry<GraphTargetItem, GraphTargetItem>> staticVars;
//public GraphTargetItem constructor;
public List<MyEntry<GraphTargetItem, GraphTargetItem>> traits;
public List<Boolean> traitsStatic;
public Set<String> uninitializedVars;
@Override
public List<List<GraphTargetItem>> getSubs() {
List<List<GraphTargetItem>> ret = new ArrayList<>();
if (functions != null) {
ret.add(functions);
}
if (staticFunctions != null) {
ret.add(staticFunctions);
}
//? is this needed for traits ?
return ret;
}
public ClassActionItem(GraphTargetItem className, GraphTargetItem extendsOp, List<GraphTargetItem> implementsOp, GraphTargetItem constructor, List<GraphTargetItem> functions, List<MyEntry<GraphTargetItem, GraphTargetItem>> vars, List<GraphTargetItem> staticFunctions, List<MyEntry<GraphTargetItem, GraphTargetItem>> staticVars) {
public ClassActionItem(GraphTargetItem className, GraphTargetItem extendsOp, List<GraphTargetItem> implementsOp, List<MyEntry<GraphTargetItem, GraphTargetItem>> traits, List<Boolean> traitsStatic) {
super(null, null, NOPRECEDENCE);
this.className = className;
this.functions = functions;
this.vars = vars;
this.traits = traits;
this.traitsStatic = traitsStatic;
this.extendsOp = extendsOp;
this.implementsOp = implementsOp;
this.staticFunctions = staticFunctions;
this.staticVars = staticVars;
this.constructor = constructor;
//this.constructor = constructor;
List<GraphTargetItem> allFunc = new ArrayList<>(functions);
if (constructor != null) {
allFunc.add(constructor);
}
this.uninitializedVars = new HashSet<>();
List<GraphTargetItem> allUsages = new ArrayList<>();
for (GraphTargetItem it : allFunc) {
if (it instanceof FunctionActionItem) {
FunctionActionItem f = (FunctionActionItem) it;
for (MyEntry<GraphTargetItem, GraphTargetItem> it : traits) {
if (it.getValue() instanceof FunctionActionItem) {
FunctionActionItem f = (FunctionActionItem) it.getValue();
detectUnitializedVars(f.actions, allUsages);
}
}
@@ -102,7 +86,7 @@ public class ClassActionItem extends ActionItem implements Block {
allMembers.add(it.toStringNoQuotes(LocalData.empty));
}
uninitializedVars.addAll(allMembers);
for (MyEntry<GraphTargetItem, GraphTargetItem> v : vars) {
for (MyEntry<GraphTargetItem, GraphTargetItem> v : traits) {
String s = v.getKey().toStringNoQuotes(LocalData.empty);
if (uninitializedVars.contains(s)) {
uninitializedVars.remove(s);
@@ -176,38 +160,49 @@ public class ClassActionItem extends ActionItem implements Block {
}
writer.startBlock();
if (constructor != null) {
/*if (constructor != null) {
constructor.toString(writer, localData).newLine();
}
}*/
for (int pass = 1; pass <= 2; pass++) {
looptraits:
for (int i = 0; i < traits.size(); i++) {
MyEntry<GraphTargetItem, GraphTargetItem> item = traits.get(i);
for (MyEntry<GraphTargetItem, GraphTargetItem> item : vars) {
writer.append("var ");
item.getKey().toStringNoQuotes(writer, localData);
writer.append(" = ");
item.getValue().toString(writer, localData);
writer.append(";").newLine();
switch (pass) {
//pass 1: add variables
case 1:
if (item.getValue() instanceof FunctionActionItem) { //ignore methods
continue looptraits;
}
break;
//pass 2: add methods
case 2:
if (!(item.getValue() instanceof FunctionActionItem)) { //ignore nonmethods
continue looptraits;
}
break;
}
if (traitsStatic.get(i)) {
writer.append("static ");
}
if (item.getValue() instanceof FunctionActionItem) {
item.getValue().toString(writer, localData).newLine();
} else {
writer.append("var ");
item.getKey().toStringNoQuotes(writer, localData);
writer.append(" = ");
item.getValue().toString(writer, localData);
writer.append(";").newLine();
}
}
}
for (String v : uninitializedVars) {
writer.append("var ");
writer.append(v);
writer.append(";").newLine();
}
for (MyEntry<GraphTargetItem, GraphTargetItem> item : staticVars) {
writer.append("static var ");
item.getKey().toStringNoQuotes(writer, localData);
writer.append(" = ");
item.getValue().toString(writer, localData);
writer.append(";").newLine();
}
for (GraphTargetItem f : functions) {
f.toString(writer, localData).newLine();
}
for (GraphTargetItem f : staticFunctions) {
writer.append("static ");
f.toString(writer, localData).newLine();
}
writer.endBlock();
writer.endClass();
return writer;
@@ -230,7 +225,7 @@ public class ClassActionItem extends ActionItem implements Block {
ActionSourceGenerator asGenerator = (ActionSourceGenerator) generator;
SourceGeneratorLocalData localData2 = Helper.deepCopy(localData);
asGenerator.setInMethod(localData2, true);
ret.addAll(asGenerator.generateTraits(localData2, false, className, extendsOp, implementsOp, constructor, functions, vars, staticFunctions, staticVars));
ret.addAll(asGenerator.generateTraits(localData2, false, className, extendsOp, implementsOp, traits, traitsStatic));
return ret;
}
@@ -12,7 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. */
* License along with this library.
*/
package com.jpexs.decompiler.flash.action.model.clauses;
import com.jpexs.decompiler.flash.SWF;
@@ -12,7 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. */
* License along with this library.
*/
package com.jpexs.decompiler.flash.action.model.clauses;
import com.jpexs.decompiler.flash.SourceGeneratorLocalData;
@@ -20,6 +21,7 @@ import com.jpexs.decompiler.flash.action.Action;
import com.jpexs.decompiler.flash.action.model.ActionItem;
import com.jpexs.decompiler.flash.action.parser.script.ActionSourceGenerator;
import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
import com.jpexs.decompiler.flash.helpers.collections.MyEntry;
import com.jpexs.decompiler.graph.CompilationException;
import com.jpexs.decompiler.graph.GraphSourceItem;
import com.jpexs.decompiler.graph.GraphTargetItem;
@@ -72,7 +74,7 @@ public class InterfaceActionItem extends ActionItem {
public List<GraphSourceItem> toSource(SourceGeneratorLocalData localData, SourceGenerator generator) throws CompilationException {
List<GraphSourceItem> ret = new ArrayList<>();
ActionSourceGenerator asGenerator = (ActionSourceGenerator) generator;
ret.addAll(asGenerator.generateTraits(localData, true, name, null, superInterfaces, null, null, null, null, null));
ret.addAll(asGenerator.generateTraits(localData, true, name, null, superInterfaces, new ArrayList<MyEntry<GraphTargetItem, GraphTargetItem>>(), new ArrayList<>()));
return ret;
}
@@ -12,7 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. */
* License along with this library.
*/
package com.jpexs.decompiler.flash.action.model.clauses;
import com.jpexs.decompiler.flash.SWF;
@@ -20,9 +21,21 @@ import com.jpexs.decompiler.flash.SourceGeneratorLocalData;
import com.jpexs.decompiler.flash.action.Action;
import com.jpexs.decompiler.flash.action.model.ActionItem;
import com.jpexs.decompiler.flash.action.model.ConstantPool;
import com.jpexs.decompiler.flash.action.model.DirectValueActionItem;
import com.jpexs.decompiler.flash.action.parser.script.ActionSourceGenerator;
import com.jpexs.decompiler.flash.action.swf4.ActionIf;
import com.jpexs.decompiler.flash.action.swf4.ActionJump;
import com.jpexs.decompiler.flash.action.swf4.ActionPop;
import com.jpexs.decompiler.flash.action.swf4.ActionPush;
import com.jpexs.decompiler.flash.action.swf4.RegisterNumber;
import com.jpexs.decompiler.flash.action.swf5.ActionDefineLocal;
import com.jpexs.decompiler.flash.action.swf5.ActionEquals2;
import com.jpexs.decompiler.flash.action.swf5.ActionPushDuplicate;
import com.jpexs.decompiler.flash.action.swf5.ActionStackSwap;
import com.jpexs.decompiler.flash.action.swf7.ActionCastOp;
import com.jpexs.decompiler.flash.action.swf7.ActionThrow;
import com.jpexs.decompiler.flash.action.swf7.ActionTry;
import com.jpexs.decompiler.flash.ecma.Null;
import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
import com.jpexs.decompiler.graph.Block;
import com.jpexs.decompiler.graph.CompilationException;
@@ -33,6 +46,8 @@ import com.jpexs.decompiler.graph.model.ContinueItem;
import com.jpexs.decompiler.graph.model.LocalData;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
*
@@ -42,7 +57,9 @@ public class TryActionItem extends ActionItem implements Block {
public List<GraphTargetItem> tryCommands;
public List<GraphTargetItem> catchExceptions;
public List<GraphTargetItem> catchExceptionNames;
public List<GraphTargetItem> catchExceptionTypes;
public List<List<GraphTargetItem>> catchCommands;
@@ -61,10 +78,11 @@ public class TryActionItem extends ActionItem implements Block {
return ret;
}
public TryActionItem(List<GraphTargetItem> tryCommands, List<GraphTargetItem> catchExceptions, List<List<GraphTargetItem>> catchCommands, List<GraphTargetItem> finallyCommands) {
public TryActionItem(List<GraphTargetItem> tryCommands, List<GraphTargetItem> catchExceptionNames, List<GraphTargetItem> catchExceptionTypes, List<List<GraphTargetItem>> catchCommands, List<GraphTargetItem> finallyCommands) {
super(null, null, NOPRECEDENCE);
this.tryCommands = tryCommands;
this.catchExceptions = catchExceptions;
this.catchExceptionNames = catchExceptionNames;
this.catchExceptionTypes = catchExceptionTypes;
this.catchCommands = catchCommands;
this.finallyCommands = finallyCommands;
}
@@ -73,19 +91,23 @@ public class TryActionItem extends ActionItem implements Block {
public GraphTextWriter appendTo(GraphTextWriter writer, LocalData localData) throws InterruptedException {
writer.append("try");
appendBlock(null, writer, localData, tryCommands);
for (int e = 0; e < catchExceptions.size(); e++) {
for (int e = 0; e < catchExceptionNames.size(); e++) {
writer.newLine();
writer.append("catch");
if (writer.getFormatting().spaceBeforeParenthesesCatchParentheses) {
writer.append(" ");
}
writer.append("(");
catchExceptions.get(e).toStringNoQuotes(writer, localData);
catchExceptionNames.get(e).toStringNoQuotes(writer, localData);
if (catchExceptionTypes.get(e) != null) {
writer.append(":");
catchExceptionTypes.get(e).toStringNoQuotes(writer, localData);
}
writer.append(")");
List<GraphTargetItem> commands = catchCommands.get(e);
appendBlock(null, writer, localData, commands);
}
if (catchExceptions.isEmpty() || finallyCommands.size() > 0) {
if (catchExceptionNames.isEmpty() || finallyCommands.size() > 0) {
writer.newLine();
writer.append("finally");
appendBlock(null, writer, localData, finallyCommands);
@@ -140,15 +162,82 @@ public class TryActionItem extends ActionItem implements Block {
List<Action> finallyCommandsA = finallyCommands == null ? null : asGenerator.toActionList(asGenerator.generate(localData, finallyCommands));
List<Action> catchCommandsA = null;
String catchName = null;
if (catchExceptions != null) {
if (!catchExceptions.isEmpty()) {
catchName = catchExceptions.get(0).toStringNoQuotes(LocalData.create(new ConstantPool(asGenerator.getConstantPool())));
}
}
int catchSize = 0;
int catchRegister = 0;
boolean catchInRegisterFlag = false;
if (catchCommands != null && !catchCommands.isEmpty()) {
catchCommandsA = asGenerator.toActionList(asGenerator.generate(localData, catchCommands.get(0)));
List<GraphSourceItem> fullCatchBody = new ArrayList<>();
if (catchExceptionNames.size() == 1 && catchExceptionTypes.get(0) == null) { //catch everything without any type
GraphTargetItem ename = catchExceptionNames.get(0);
if (ename instanceof DirectValueActionItem) {
catchName = ((DirectValueActionItem) ename).getAsString();
} else {
Logger.getLogger(TryActionItem.class.getName()).log(Level.SEVERE, "Invalid catchName, string expected");
}
catchInRegisterFlag = false;
fullCatchBody = GraphTargetItem.toSourceMerge(localData, generator, catchCommands.get(0));
} else {
catchInRegisterFlag = true;
catchRegister = asGenerator.getTempRegister(localData);
boolean allCatched = false;
for (int i = catchExceptionNames.size() - 1; i >= 0; i--) {
GraphTargetItem etype = catchExceptionTypes.get(i);
if (etype == null) {
allCatched = true;
break;
}
}
if (!allCatched) {
fullCatchBody.addAll(0, GraphTargetItem.toSourceMerge(localData, generator,
new ActionPush(new RegisterNumber(catchRegister)),
new ActionThrow()
));
}
for (int i = catchExceptionNames.size() - 1; i >= 0; i--) {
GraphTargetItem ename = catchExceptionNames.get(i);
GraphTargetItem etype = catchExceptionTypes.get(i);
List<GraphTargetItem> ebody = catchCommands.get(i);
if (etype == null) {
fullCatchBody.addAll(0, GraphTargetItem.toSourceMerge(localData, generator,
new DirectValueActionItem(new RegisterNumber(catchRegister)),
ename,
new ActionStackSwap(),
new ActionDefineLocal(),
ebody
));
} else {
List<GraphSourceItem> ifBody = GraphTargetItem.toSourceMerge(localData, generator,
ename,
new ActionStackSwap(),
new ActionDefineLocal(),
ebody);
fullCatchBody.add(0, new ActionPop());
int toFinishSize = Action.actionsToBytes(asGenerator.toActionList(fullCatchBody), false, SWF.DEFAULT_VERSION).length;
ActionJump finishJump = new ActionJump(toFinishSize);
ifBody.add(finishJump);
List<Action> ifBodyA = asGenerator.toActionList(ifBody);
int ifBodySize = Action.actionsToBytes(ifBodyA, false, SWF.DEFAULT_VERSION).length;
fullCatchBody.addAll(0, ifBody);
fullCatchBody.addAll(0,
GraphTargetItem.toSourceMerge(localData, generator,
etype,
new ActionPush(new RegisterNumber(catchRegister)),
new ActionCastOp(),
new ActionPushDuplicate(),
new ActionPush(Null.INSTANCE),
new ActionEquals2(),
new ActionIf(ifBodySize)
));
}
}
asGenerator.releaseTempRegister(localData, catchRegister);
}
catchCommandsA = asGenerator.toActionList(fullCatchBody);
catchSize = Action.actionsToBytes(catchCommandsA, false, SWF.DEFAULT_VERSION).length;
tryCommandsA.add(new ActionJump(catchSize));
}
@@ -157,7 +246,7 @@ public class TryActionItem extends ActionItem implements Block {
finallySize = Action.actionsToBytes(finallyCommandsA, false, SWF.DEFAULT_VERSION).length;
}
int trySize = Action.actionsToBytes(tryCommandsA, false, SWF.DEFAULT_VERSION).length;
ret.add(new ActionTry(false, finallyCommands != null, catchCommands != null, catchName, 0, trySize, catchSize, finallySize, SWF.DEFAULT_VERSION));
ret.add(new ActionTry(catchInRegisterFlag, finallyCommands != null, catchCommands != null, catchName, catchRegister, trySize, catchSize, finallySize, SWF.DEFAULT_VERSION));
ret.addAll(tryCommandsA);
if (catchCommandsA != null) {
ret.addAll(catchCommandsA);
@@ -12,7 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. */
* License along with this library.
*/
package com.jpexs.decompiler.flash.action.parser.script;
import com.jpexs.decompiler.flash.SourceGeneratorLocalData;
@@ -119,6 +120,7 @@ import com.jpexs.decompiler.flash.action.model.operations.SubtractActionItem;
import com.jpexs.decompiler.flash.action.model.operations.URShiftActionItem;
import com.jpexs.decompiler.flash.action.parser.ActionParseException;
import com.jpexs.decompiler.flash.action.swf4.ActionIf;
import com.jpexs.decompiler.flash.action.swf4.ActionPush;
import com.jpexs.decompiler.flash.action.swf4.ConstantIndex;
import com.jpexs.decompiler.flash.action.swf5.ActionConstantPool;
import com.jpexs.decompiler.flash.ecma.Null;
@@ -338,11 +340,8 @@ public class ActionScript2Parser {
globalClassTypeStr.addAll(nameStr);*/
ParsedSymbol s;
FunctionActionItem constr = null;
List<GraphTargetItem> staticFunctions = new ArrayList<>();
List<MyEntry<GraphTargetItem, GraphTargetItem>> staticVars = new ArrayList<>();
List<GraphTargetItem> instanceFunctions = new ArrayList<>();
List<MyEntry<GraphTargetItem, GraphTargetItem>> vars = new ArrayList<>();
List<MyEntry<GraphTargetItem, GraphTargetItem>> traits = new ArrayList<>();
List<Boolean> traitsStatic = new ArrayList<>();
String classNameStr = "";
if (nameStr instanceof GetMemberActionItem) {
@@ -373,16 +372,21 @@ public class ActionScript2Parser {
expected(s, lexer.yyline(), SymbolType.IDENTIFIER, SymbolGroup.GLOBALFUNC);
String fname = s.value.toString();
if (fname.equals(classNameStr)) { //constructor
constr = (function(!isInterface, "", true, variables, functions));
} else if (!isInterface) {
//actually there's no difference, it's instance trait
}
if (!isInterface) {
if (isStatic) {
FunctionActionItem ft = function(!isInterface, "", true, variables, functions);
ft.calculatedFunctionName = pushConst(fname);
staticFunctions.add(ft);
//staticFunctions.add(ft);
traits.add(new MyEntry<>(ft.calculatedFunctionName, ft));
traitsStatic.add(true);
} else {
FunctionActionItem ft = function(!isInterface, "", true, variables, functions);
ft.calculatedFunctionName = pushConst(fname);
instanceFunctions.add(ft);
//instanceFunctions.add(ft);
traits.add(new MyEntry<>(ft.calculatedFunctionName, ft));
traitsStatic.add(false);
}
}
break;
@@ -396,11 +400,8 @@ public class ActionScript2Parser {
s = lex();
}
if (s.type == SymbolType.ASSIGN) {
if (isStatic) {
staticVars.add(new MyEntry<>(pushConst(ident), expression(false, false, true, variables, functions)));
} else {
vars.add(new MyEntry<>(pushConst(ident), expression(false, false, true, variables, functions)));
}
traits.add(new MyEntry<>(pushConst(ident), expression(false, false, true, variables, functions)));
traitsStatic.add(isStatic);
s = lex();
}
if (s.type != SymbolType.SEMICOLON) {
@@ -417,7 +418,7 @@ public class ActionScript2Parser {
if (isInterface) {
return new InterfaceActionItem(nameStr, implementsStr);
} else {
return new ClassActionItem(nameStr, extendsStr, implementsStr, constr, instanceFunctions, vars, staticFunctions, staticVars);
return new ClassActionItem(nameStr, extendsStr, implementsStr, traits, traitsStatic);
}
}
@@ -1151,14 +1152,25 @@ public class ActionScript2Parser {
s = lex();
boolean found = false;
List<List<GraphTargetItem>> catchCommands = null;
List<GraphTargetItem> catchExceptions = new ArrayList<>();
if (s.type == SymbolType.CATCH) {
List<GraphTargetItem> catchExceptionNames = new ArrayList<>();
List<GraphTargetItem> catchExceptionTypes = new ArrayList<>();
while (s.type == SymbolType.CATCH) {
expectedType(SymbolType.PARENT_OPEN);
s = lex();
expected(s, lexer.yyline(), SymbolType.IDENTIFIER, SymbolType.STRING);
catchExceptions.add(pushConst((String) s.value));
catchExceptionNames.add(pushConst((String) s.value));
s = lex();
if (s.type == SymbolType.COLON) {
catchExceptionTypes.add(type(variables));
} else {
catchExceptionTypes.add(null);
lexer.pushback(s);
}
expectedType(SymbolType.PARENT_CLOSE);
catchCommands = new ArrayList<>();
if (catchCommands == null) {
catchCommands = new ArrayList<>();
}
List<GraphTargetItem> cc = new ArrayList<>();
cc.add(command(inFunction, inMethod, forinlevel, true, variables, functions));
catchCommands.add(cc);
@@ -1176,7 +1188,7 @@ public class ActionScript2Parser {
expected(s, lexer.yyline(), SymbolType.CATCH, SymbolType.FINALLY);
}
lexer.pushback(s);
ret = new TryActionItem(tryCommands, catchExceptions, catchCommands, finallyCommands);
ret = new TryActionItem(tryCommands, catchExceptionNames, catchExceptionTypes, catchCommands, finallyCommands);
break;
case THROW:
ret = new ThrowActionItem(null, null, expression(inFunction, inMethod, true, variables, functions));
@@ -1872,12 +1884,58 @@ public class ActionScript2Parser {
return retTree;
}
public List<Action> actionsFromTree(List<GraphTargetItem> tree, List<String> constantPool) throws CompilationException {
private List<GraphSourceItem> generateActionList(List<GraphTargetItem> tree, List<String> constantPool) throws CompilationException {
ActionSourceGenerator gen = new ActionSourceGenerator(swfVersion, constantPool);
SourceGeneratorLocalData localData = new SourceGeneratorLocalData(new HashMap<>(), 0, Boolean.FALSE, 0);
return gen.generate(localData, tree);
}
private List<Action> actionsFromTree(List<GraphTargetItem> tree, List<String> constantPool, boolean doOrder) throws CompilationException, NeedsGenerateAgainException {
List<Action> ret = new ArrayList<>();
SourceGeneratorLocalData localData = new SourceGeneratorLocalData(
new HashMap<>(), 0, Boolean.FALSE, 0);
List<GraphSourceItem> srcList = gen.generate(localData, tree);
List<GraphSourceItem> srcList = generateActionList(tree, constantPool);
if (doOrder) {
List<String> orderedConstantPool = new ArrayList<>();
boolean canChangeInPlace;
int lastIndex = constantPool.size() - 1;
if (lastIndex <= ActionPush.MAX_CONSTANT_INDEX_TYPE8) {
//can change constant indices as ActionPush contains always 1 byte per constant
canChangeInPlace = true;
} else {
//variable number bytes per ActionPush constant,
//must generate again to make relative offsets in jumps work
canChangeInPlace = false;
}
//create ordered constant pool, update constantindices when we can changeinplace
for (GraphSourceItem src : srcList) {
if (src instanceof ActionPush) {
ActionPush ap = (ActionPush) src;
for (int i = 0; i < ap.values.size(); i++) {
Object val = ap.values.get(i);
if (val instanceof ConstantIndex) {
ConstantIndex ci = (ConstantIndex) val;
String cval = constantPool.get(ci.index);
int orderedIndex = orderedConstantPool.indexOf(cval);
if (orderedIndex == -1) {
orderedIndex = orderedConstantPool.size();
orderedConstantPool.add(cval);
}
if (canChangeInPlace) {
//Do NOT change ci.index directly - it may be cloned from other location
ap.values.set(i, new ConstantIndex(orderedIndex));
}
}
}
}
}
if (!canChangeInPlace) {
//generate again, as number of bytes per ActionPush can change
throw new NeedsGenerateAgainException(orderedConstantPool);
}
constantPool = orderedConstantPool;
}
for (GraphSourceItem s : srcList) {
if (s instanceof Action) {
ret.add((Action) s);
@@ -1888,9 +1946,21 @@ public class ActionScript2Parser {
}
public List<Action> actionsFromString(String s) throws ActionParseException, IOException, CompilationException {
List<String> constantPool = new ArrayList<>();
List<GraphTargetItem> tree = treeFromString(s, constantPool);
return actionsFromTree(tree, constantPool);
try {
List<String> constantPool = new ArrayList<>();
List<GraphTargetItem> tree = treeFromString(s, constantPool);
return actionsFromTree(tree, constantPool, true);
} catch (NeedsGenerateAgainException nga) {
//Can happen when constantpool needs reordering and number of constants > 256
try {
List<String> newConstantPool = nga.getNewConstantPool();
List<GraphTargetItem> tree = treeFromString(s, newConstantPool);
return actionsFromTree(tree, newConstantPool, false /*do not order again*/);
} catch (NeedsGenerateAgainException ex) {
//should not happen as doOrder parameter is set to false
return new ArrayList<>();
}
}
}
private void versionRequired(ParsedSymbol s, int min) throws ActionParseException {
@@ -12,7 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. */
* License along with this library.
*/
package com.jpexs.decompiler.flash.action.parser.script;
import com.jpexs.decompiler.flash.SWF;
@@ -655,7 +656,7 @@ public class ActionSourceGenerator implements SourceGenerator {
return new ActionPush(new ConstantIndex(index));
}
public List<GraphSourceItem> generateTraits(SourceGeneratorLocalData localData, boolean isInterface, GraphTargetItem name, GraphTargetItem extendsVal, List<GraphTargetItem> implementsStr, GraphTargetItem constructor, List<GraphTargetItem> functions, List<MyEntry<GraphTargetItem, GraphTargetItem>> vars, List<GraphTargetItem> staticFunctions, List<MyEntry<GraphTargetItem, GraphTargetItem>> staticVars) throws CompilationException {
public List<GraphSourceItem> generateTraits(SourceGeneratorLocalData localData, boolean isInterface, GraphTargetItem name, GraphTargetItem extendsVal, List<GraphTargetItem> implementsStr, List<MyEntry<GraphTargetItem, GraphTargetItem>> traits, List<Boolean> traitsStatic) throws CompilationException {
List<String> extendsStr = getVarParts(extendsVal);
List<GraphSourceItem> ret = new ArrayList<>();
List<String> nameStr = getVarParts(name);
@@ -668,7 +669,7 @@ public class ActionSourceGenerator implements SourceGenerator {
}
List<Action> val = new ArrayList<>();
val.add(new ActionPush((Long) 0L));
val.add(new ActionPush((Double) 0.0));
val.add(pushConst("Object"));
val.add(new ActionNewObject());
notBody.addAll(typeToActions(globalClassTypeStr, val));
@@ -677,12 +678,26 @@ public class ActionSourceGenerator implements SourceGenerator {
ret.add(new ActionNot());
ret.add(new ActionIf(Action.actionsToBytes(notBody, false, SWF.DEFAULT_VERSION).length));
ret.addAll(notBody);
ret.add(new ActionPop());
}
List<Action> ifbody = new ArrayList<>();
List<String> globalClassTypeStr = new ArrayList<>();
globalClassTypeStr.add("_global");
globalClassTypeStr.addAll(nameStr);
String constructorName = nameStr.get(nameStr.size() - 1); //com.jpexs.MyClass => MyClass
GraphTargetItem constructor = null;
int constructorIndex = -1;
for (int t = 0; t < traits.size(); t++) {
MyEntry<GraphTargetItem, GraphTargetItem> en = traits.get(t);
if (en.getValue() instanceof FunctionActionItem) {
if (constructorName.equals(getName(en.getKey()))) {
constructorIndex = t;
constructor = en.getValue();
break;
}
}
}
ParsedSymbol s = null;
List<Action> constr = new ArrayList<>();
@@ -692,45 +707,40 @@ public class ActionSourceGenerator implements SourceGenerator {
if (!isInterface) {
val.add(new ActionStoreRegister(1));
}
constr.addAll(typeToActions(globalClassTypeStr, val));
constr.addAll(typeToActions(nameStr, val));
} else {
constr.addAll(toActionList(((FunctionActionItem) constructor).toSource(localData, this)));
constr.add(new ActionStoreRegister(1));
constr = (typeToActions(globalClassTypeStr, constr));
constr = (typeToActions(nameStr, constr));
}
if (!isInterface) {
for (GraphTargetItem f : staticFunctions) {
FunctionActionItem fi = (FunctionActionItem) f;
ifbody.add(new ActionPush(new RegisterNumber(1/*static*/)));
ifbody.add(new ActionPush(getName(fi.calculatedFunctionName)));
ifbody.addAll(toActionList(fi.toSource(localData, this)));
ifbody.add(new ActionSetMember());
}
for (GraphTargetItem f : functions) {
FunctionActionItem fi = (FunctionActionItem) f;
ifbody.add(new ActionPush(new RegisterNumber(2/*instance*/)));
ifbody.add(new ActionPush(getName(fi.calculatedFunctionName)));
ifbody.addAll(toActionList(fi.toSource(localData, this)));
ifbody.add(new ActionSetMember());
}
for (MyEntry<GraphTargetItem, GraphTargetItem> en : staticVars) {
ifbody.add(new ActionPush(new RegisterNumber(1/*static*/)));
ifbody.add(new ActionPush(getName(en.getKey())));
ifbody.addAll(toActionList(en.getValue().toSource(localData, this)));
ifbody.add(new ActionSetMember());
}
for (MyEntry<GraphTargetItem, GraphTargetItem> en : vars) {
ifbody.add(new ActionPush(new RegisterNumber(2/*instance*/)));
ifbody.add(new ActionPush(getName(en.getKey())));
ifbody.addAll(toActionList(en.getValue().toSource(localData, this)));
ifbody.add(new ActionSetMember());
for (int pass = 1; pass <= 2; pass++) { //two passes, methods first, then variables
for (int t = 0; t < traits.size(); t++) {
if (constructorIndex == t) { //constructor already handled
continue;
}
MyEntry<GraphTargetItem, GraphTargetItem> en = traits.get(t);
boolean isFunc = (en.getValue() instanceof FunctionActionItem);
if (pass == 1 && isFunc) { //Add methods in first pass
FunctionActionItem fi = (FunctionActionItem) en.getValue();
ifbody.add(new ActionPush(new RegisterNumber(traitsStatic.get(t) ? 1 : 2)));
ifbody.add(pushConst(getName(en.getKey())));
ifbody.addAll(toActionList(fi.toSource(localData, this)));
ifbody.add(new ActionSetMember());
} else if (pass == 2 && !isFunc) { //add variables in second pass
ifbody.add(new ActionPush(new RegisterNumber(traitsStatic.get(t) ? 1 : 2)));
ifbody.add(pushConst(getName(en.getKey())));
ifbody.addAll(toActionList(en.getValue().toSource(localData, this)));
ifbody.add(new ActionSetMember());
}
}
}
}
if (!isInterface) {
ifbody.add(new ActionPush((Long) 1L));
ifbody.add(new ActionPush(Null.INSTANCE));
ifbody.addAll(typeToActions(globalClassTypeStr, null));
ifbody.addAll(typeToActions(nameStr, null));
ifbody.add(pushConst("prototype"));
ifbody.add(new ActionGetMember());
ifbody.add(new ActionPush((Long) 3L));
@@ -0,0 +1,37 @@
/*
* Copyright (C) 2010-2018 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.action.parser.script;
import java.util.List;
/**
*
* @author JPEXS
*/
public class NeedsGenerateAgainException extends Exception {
private List<String> newConstantPool;
public NeedsGenerateAgainException(List<String> newConstantPool) {
this.newConstantPool = newConstantPool;
}
public List<String> getNewConstantPool() {
return newConstantPool;
}
}
@@ -12,7 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. */
* License along with this library.
*/
package com.jpexs.decompiler.flash.action.special;
import com.jpexs.decompiler.flash.action.Action;
@@ -52,7 +53,7 @@ public class ActionEnd extends Action {
}
@Override
public void translate(GraphSourceItem lineStartItem, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
public void translate(boolean insideDoInitAction, GraphSourceItem lineStartItem, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
//output.add(new SimpleActionTreeItem(this, "end()"));
}
}
@@ -12,7 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. */
* License along with this library.
*/
package com.jpexs.decompiler.flash.action.special;
import com.jpexs.decompiler.flash.action.Action;
@@ -48,7 +49,7 @@ public class ActionNop extends Action {
}
@Override
public void translate(GraphSourceItem lineStartItem, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
public void translate(boolean insideDoInitAction, GraphSourceItem lineStartItem, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
//output.add(new SimpleActionTreeItem(this, "nop();"));
}
}
@@ -12,7 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. */
* License along with this library.
*/
package com.jpexs.decompiler.flash.action.special;
import com.jpexs.decompiler.flash.action.LocalDataArea;
@@ -45,6 +46,6 @@ public class ActionUnknown extends ActionNop {
}
@Override
public void translate(GraphSourceItem lineStartItem, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
public void translate(boolean insideDoInitAction, GraphSourceItem lineStartItem, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
}
}
@@ -97,7 +97,7 @@ public class ActionGetURL extends Action {
}
@Override
public void translate(GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
public void translate(boolean insideDoInitAction, GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
String fsCommandPrefix = "FSCommand:";
if (urlString.startsWith(fsCommandPrefix) && targetString.isEmpty()) {
String command = urlString.substring(fsCommandPrefix.length());
@@ -86,7 +86,7 @@ public class ActionGoToLabel extends Action {
}
@Override
public void translate(GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
public void translate(boolean insideDoInitAction, GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
output.add(new GotoLabelActionItem(this, lineStartAction, label));
}
}
@@ -82,7 +82,7 @@ public class ActionGotoFrame extends Action {
}
@Override
public void translate(GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
public void translate(boolean insideDoInitAction, GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
output.add(new GotoFrameActionItem(this, lineStartAction, frame));
}
}
@@ -53,7 +53,7 @@ public class ActionNextFrame extends Action {
}
@Override
public void translate(GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
public void translate(boolean insideDoInitAction, GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
output.add(new NextFrameActionItem(this, lineStartAction));
}
}
@@ -52,7 +52,7 @@ public class ActionPlay extends Action {
}
@Override
public void translate(GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
public void translate(boolean insideDoInitAction, GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
if (!output.isEmpty() && (output.get(output.size() - 1) instanceof GotoFrameActionItem)) {
GotoFrameActionItem gta = (GotoFrameActionItem) output.remove(output.size() - 1);
output.add(new GotoFrame2ActionItem(this, lineStartAction, new DirectValueActionItem(gta.frame + 1), false, true, 0));
@@ -53,7 +53,7 @@ public class ActionPrevFrame extends Action {
}
@Override
public void translate(GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
public void translate(boolean insideDoInitAction, GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
output.add(new PrevFrameActionItem(this, lineStartAction));
}
}
@@ -90,7 +90,7 @@ public class ActionSetTarget extends Action {
}
@Override
public void translate(GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
public void translate(boolean insideDoInitAction, GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
output.add(new SetTargetActionItem(this, lineStartAction, targetName));
}
}
@@ -49,7 +49,7 @@ public class ActionStop extends Action {
}
@Override
public void translate(GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
public void translate(boolean insideDoInitAction, GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
output.add(new StopActionItem(this, lineStartAction));
}
}
@@ -48,7 +48,7 @@ public class ActionStopSounds extends Action {
}
@Override
public void translate(GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
public void translate(boolean insideDoInitAction, GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
output.add(new StopAllSoundsActionItem(this, lineStartAction));
}
}
@@ -48,7 +48,7 @@ public class ActionToggleQuality extends Action {
}
@Override
public void translate(GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
public void translate(boolean insideDoInitAction, GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
output.add(new ToggleHighQualityActionItem(this, lineStartAction));
}
}
@@ -12,7 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. */
* License along with this library.
*/
package com.jpexs.decompiler.flash.action.swf3;
import com.jpexs.decompiler.flash.SWF;
@@ -99,9 +100,9 @@ public class ActionWaitForFrame extends Action implements ActionStore {
}
@Override
public void translate(GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) throws InterruptedException {
public void translate(boolean insideDoInitAction, GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) throws InterruptedException {
GraphTargetItem frameTi = new DirectValueActionItem(null, null, 0, new Long(frame), new ArrayList<>());
List<GraphTargetItem> body = ActionGraph.translateViaGraph(regNames, variables, functions, skipped, SWF.DEFAULT_VERSION, staticOperation, path);
List<GraphTargetItem> body = ActionGraph.translateViaGraph(insideDoInitAction, regNames, variables, functions, skipped, SWF.DEFAULT_VERSION, staticOperation, path);
output.add(new IfFrameLoadedActionItem(frameTi, body, this, lineStartAction));
}
@@ -12,7 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. */
* License along with this library.
*/
package com.jpexs.decompiler.flash.action.swf4;
import com.jpexs.decompiler.flash.BaseLocalData;
@@ -53,7 +54,7 @@ public class ActionAdd extends Action {
}
@Override
public void translate(GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
public void translate(boolean insideDoInitAction, GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
GraphTargetItem a = stack.pop();
GraphTargetItem b = stack.pop();
stack.push(new AddActionItem(this, lineStartAction, b, a, false));
@@ -53,7 +53,7 @@ public class ActionAnd extends Action {
}
@Override
public void translate(GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
public void translate(boolean insideDoInitAction, GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
GraphTargetItem a = stack.pop();
GraphTargetItem b = stack.pop();
stack.push(new AndActionItem(this, lineStartAction, b, a));
@@ -53,7 +53,7 @@ public class ActionAsciiToChar extends Action {
}
@Override
public void translate(GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
public void translate(boolean insideDoInitAction, GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
GraphTargetItem a = stack.pop();
stack.push(new AsciiToCharActionItem(this, lineStartAction, a));
}
@@ -58,7 +58,7 @@ public class ActionCall extends Action {
}
@Override
public void translate(GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
public void translate(boolean insideDoInitAction, GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
output.add(new CallActionItem(this, lineStartAction, stack.pop()));
}
@@ -53,7 +53,7 @@ public class ActionCharToAscii extends Action {
}
@Override
public void translate(GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
public void translate(boolean insideDoInitAction, GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
GraphTargetItem a = stack.pop();
stack.push(new CharToAsciiActionItem(this, lineStartAction, a));
}
@@ -12,7 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. */
* License along with this library.
*/
package com.jpexs.decompiler.flash.action.swf4;
import com.jpexs.decompiler.flash.BaseLocalData;
@@ -21,6 +22,7 @@ import com.jpexs.decompiler.flash.action.ActionScriptObject;
import com.jpexs.decompiler.flash.action.LocalDataArea;
import com.jpexs.decompiler.flash.action.model.CloneSpriteActionItem;
import com.jpexs.decompiler.flash.ecma.EcmaScript;
import com.jpexs.decompiler.flash.ecma.Undefined;
import com.jpexs.decompiler.flash.types.annotations.SWFVersion;
import com.jpexs.decompiler.graph.GraphSourceItem;
import com.jpexs.decompiler.graph.GraphTargetItem;
@@ -53,13 +55,16 @@ public class ActionCloneSprite extends Action {
int depth = EcmaScript.toInt32(lda.stack.pop());
String source = EcmaScript.toString(lda.stack.pop());
String target = EcmaScript.toString(lda.stack.pop());
lda.stage.setMember(target, ((ActionScriptObject) lda.stage.getMember(source)).clone());
lda.stage.addToDisplayList(depth, lda.stage.getMember(target));
Object clonedMember = lda.stage.getMember(source);
if (clonedMember != Undefined.INSTANCE) {
lda.stage.setMember(target, ((ActionScriptObject) clonedMember).clone());
lda.stage.addToDisplayList(depth, lda.stage.getMember(target));
}
return true;
}
@Override
public void translate(GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
public void translate(boolean insideDoInitAction, GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
GraphTargetItem depth = stack.pop();
GraphTargetItem source = stack.pop();
GraphTargetItem target = stack.pop();
@@ -53,7 +53,7 @@ public class ActionDivide extends Action {
}
@Override
public void translate(GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
public void translate(boolean insideDoInitAction, GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
GraphTargetItem a = stack.pop();
GraphTargetItem b = stack.pop();
stack.push(new DivideActionItem(this, lineStartAction, b, a));
@@ -52,7 +52,7 @@ public class ActionEndDrag extends Action {
}
@Override
public void translate(GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
public void translate(boolean insideDoInitAction, GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
output.add(new StopDragActionItem(this, lineStartAction));
}
}
@@ -53,7 +53,7 @@ public class ActionEquals extends Action {
}
@Override
public void translate(GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
public void translate(boolean insideDoInitAction, GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
GraphTargetItem a = stack.pop();
GraphTargetItem b = stack.pop();
stack.push(new EqActionItem(this, lineStartAction, b, a, false));
@@ -64,7 +64,7 @@ public class ActionGetProperty extends Action {
}
@Override
public void translate(GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
public void translate(boolean insideDoInitAction, GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
GraphTargetItem index = stack.pop();
GraphTargetItem target = stack.pop();
int indexInt = 0;
@@ -49,7 +49,7 @@ public class ActionGetTime extends Action {
}
@Override
public void translate(GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
public void translate(boolean insideDoInitAction, GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
stack.push(new GetTimeActionItem(this, lineStartAction));
}
@@ -124,7 +124,7 @@ public class ActionGetURL2 extends Action {
}
@Override
public void translate(GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
public void translate(boolean insideDoInitAction, GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
GraphTargetItem targetString = stack.pop();
GraphTargetItem urlString = stack.pop();
Integer num = null;
@@ -64,7 +64,7 @@ public class ActionGetVariable extends Action {
}
@Override
public void translate(GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
public void translate(boolean insideDoInitAction, GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
GraphTargetItem name = stack.pop();
String nameStr;
if (name instanceof DirectValueActionItem) {
@@ -143,7 +143,7 @@ public class ActionGotoFrame2 extends Action {
}
@Override
public void translate(GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
public void translate(boolean insideDoInitAction, GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
GraphTargetItem frame = stack.pop();
output.add(new GotoFrame2ActionItem(this, lineStartAction, frame, sceneBiasFlag, playFlag, sceneBias));
}
@@ -53,7 +53,7 @@ public class ActionLess extends Action {
}
@Override
public void translate(GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
public void translate(boolean insideDoInitAction, GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
GraphTargetItem a = stack.pop();
GraphTargetItem b = stack.pop();
stack.push(new LtActionItem(this, lineStartAction, b, a, false));
@@ -53,7 +53,7 @@ public class ActionMBAsciiToChar extends Action {
}
@Override
public void translate(GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
public void translate(boolean insideDoInitAction, GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
GraphTargetItem a = stack.pop();
stack.push(new MBAsciiToCharActionItem(this, lineStartAction, a));
}
@@ -53,7 +53,7 @@ public class ActionMBCharToAscii extends Action {
}
@Override
public void translate(GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
public void translate(boolean insideDoInitAction, GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
GraphTargetItem a = stack.pop();
stack.push(new MBCharToAsciiActionItem(this, lineStartAction, a));
}
@@ -53,7 +53,7 @@ public class ActionMBStringExtract extends Action {
}
@Override
public void translate(GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
public void translate(boolean insideDoInitAction, GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
GraphTargetItem count = stack.pop();
GraphTargetItem index = stack.pop();
GraphTargetItem value = stack.pop();
@@ -53,7 +53,7 @@ public class ActionMBStringLength extends Action {
}
@Override
public void translate(GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
public void translate(boolean insideDoInitAction, GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
GraphTargetItem a = stack.pop();
stack.push(new MBStringLengthActionItem(this, lineStartAction, a));
}
@@ -53,7 +53,7 @@ public class ActionMultiply extends Action {
}
@Override
public void translate(GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
public void translate(boolean insideDoInitAction, GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
GraphTargetItem a = stack.pop();
GraphTargetItem b = stack.pop();
stack.push(new MultiplyActionItem(this, lineStartAction, b, a));
@@ -53,7 +53,7 @@ public class ActionNot extends Action {
}
@Override
public void translate(GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
public void translate(boolean insideDoInitAction, GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
GraphTargetItem a = stack.pop();
stack.push(a.invert(this));
}
@@ -53,7 +53,7 @@ public class ActionOr extends Action {
}
@Override
public void translate(GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
public void translate(boolean insideDoInitAction, GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
GraphTargetItem a = stack.pop();
GraphTargetItem b = stack.pop();
stack.push(new OrActionItem(this, lineStartAction, b, a));
@@ -52,7 +52,7 @@ public class ActionPop extends Action {
}
@Override
public void translate(GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
public void translate(boolean insideDoInitAction, GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
GraphTargetItem val = stack.pop();
output.add(val);
}
@@ -12,7 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. */
* License along with this library.
*/
package com.jpexs.decompiler.flash.action.swf4;
import com.jpexs.decompiler.flash.BaseLocalData;
@@ -62,6 +63,12 @@ public class ActionPush extends Action {
public List<String> constantPool;
/**
* Maximum constant index for storing in type 8, greater indices must be
* stored in type 9
*/
public static final int MAX_CONSTANT_INDEX_TYPE8 = 255;
public ActionPush(int actionLength, SWFInputStream sis, int version) throws IOException {
super(0x96, actionLength);
int type;
@@ -151,7 +158,7 @@ public class ActionPush extends Action {
}
} else if (o instanceof ConstantIndex) {
int cIndex = ((ConstantIndex) o).index;
if (cIndex < 256) {
if (cIndex <= MAX_CONSTANT_INDEX_TYPE8) {
sos.writeUI8(8);
sos.writeUI8(cIndex);
} else {
@@ -382,7 +389,7 @@ public class ActionPush extends Action {
}
@Override
public void translate(GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
public void translate(boolean insideDoInitAction, GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
int pos = 0;
for (Object o : values) {
if (o instanceof ConstantIndex) {
@@ -53,7 +53,7 @@ public class ActionRandomNumber extends Action {
}
@Override
public void translate(GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
public void translate(boolean insideDoInitAction, GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
GraphTargetItem maximum = stack.pop();
stack.push(new RandomNumberActionItem(this, lineStartAction, maximum));
}
@@ -55,7 +55,7 @@ public class ActionRemoveSprite extends Action {
}
@Override
public void translate(GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
public void translate(boolean insideDoInitAction, GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
GraphTargetItem target = stack.pop();
output.add(new RemoveSpriteActionItem(this, lineStartAction, target));
}
@@ -70,7 +70,7 @@ public class ActionSetProperty extends Action {
}
@Override
public void translate(GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
public void translate(boolean insideDoInitAction, GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
GraphTargetItem value = stack.pop().getThroughDuplicate();
GraphTargetItem index = stack.pop().getThroughDuplicate();
GraphTargetItem target = stack.pop().getThroughDuplicate();
@@ -54,7 +54,7 @@ public class ActionSetTarget2 extends Action {
}
@Override
public void translate(GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
public void translate(boolean insideDoInitAction, GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
GraphTargetItem target = stack.pop();
output.add(new SetTarget2ActionItem(this, lineStartAction, target));
}
@@ -68,7 +68,7 @@ public class ActionSetVariable extends Action implements StoreTypeAction {
}
@Override
public void translate(GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
public void translate(boolean insideDoInitAction, GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
GraphTargetItem value = stack.pop().getThroughDuplicate();
GraphTargetItem name = stack.pop();
String nameStr;
@@ -54,7 +54,7 @@ public class ActionStartDrag extends Action {
}
@Override
public void translate(GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
public void translate(boolean insideDoInitAction, GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
GraphTargetItem target = stack.pop();
GraphTargetItem lockCenter = stack.pop();
GraphTargetItem constrain = stack.pop();
@@ -53,7 +53,7 @@ public class ActionStringAdd extends Action {
}
@Override
public void translate(GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
public void translate(boolean insideDoInitAction, GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
GraphTargetItem a = stack.pop();
GraphTargetItem b = stack.pop();
stack.push(new StringAddActionItem(this, lineStartAction, b, a));
@@ -53,7 +53,7 @@ public class ActionStringEquals extends Action {
}
@Override
public void translate(GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
public void translate(boolean insideDoInitAction, GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
GraphTargetItem a = stack.pop();
GraphTargetItem b = stack.pop();
stack.push(new StringEqActionItem(this, lineStartAction, b, a));
@@ -53,7 +53,7 @@ public class ActionStringExtract extends Action {
}
@Override
public void translate(GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
public void translate(boolean insideDoInitAction, GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
GraphTargetItem count = stack.pop();
GraphTargetItem index = stack.pop();
GraphTargetItem value = stack.pop();
@@ -53,7 +53,7 @@ public class ActionStringLength extends Action {
}
@Override
public void translate(GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
public void translate(boolean insideDoInitAction, GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
GraphTargetItem a = stack.pop();
stack.push(new StringLengthActionItem(this, lineStartAction, a));
}
@@ -53,7 +53,7 @@ public class ActionStringLess extends Action {
}
@Override
public void translate(GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
public void translate(boolean insideDoInitAction, GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
GraphTargetItem a = stack.pop();
GraphTargetItem b = stack.pop();
stack.push(new StringLtActionItem(this, lineStartAction, b, a));
@@ -53,7 +53,7 @@ public class ActionSubtract extends Action {
}
@Override
public void translate(GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
public void translate(boolean insideDoInitAction, GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
GraphTargetItem a = stack.pop();
GraphTargetItem b = stack.pop();
stack.push(new SubtractActionItem(this, lineStartAction, b, a));
@@ -53,7 +53,7 @@ public class ActionToInteger extends Action {
}
@Override
public void translate(GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
public void translate(boolean insideDoInitAction, GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
GraphTargetItem a = stack.pop();
stack.push(new ToIntegerActionItem(this, lineStartAction, a));
}
@@ -53,7 +53,7 @@ public class ActionTrace extends Action {
}
@Override
public void translate(GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
public void translate(boolean insideDoInitAction, GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
GraphTargetItem value = stack.pop();
output.add(new TraceActionItem(this, lineStartAction, value));
}
@@ -12,7 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. */
* License along with this library.
*/
package com.jpexs.decompiler.flash.action.swf4;
import com.jpexs.decompiler.flash.BaseLocalData;
@@ -145,9 +146,9 @@ public class ActionWaitForFrame2 extends Action implements ActionStore {
}
@Override
public void translate(GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) throws InterruptedException {
public void translate(boolean insideDoInitAction, GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) throws InterruptedException {
GraphTargetItem frame = stack.pop();
List<GraphTargetItem> body = ActionGraph.translateViaGraph(regNames, variables, functions, skipped, SWF.DEFAULT_VERSION, staticOperation, path);
List<GraphTargetItem> body = ActionGraph.translateViaGraph(insideDoInitAction, regNames, variables, functions, skipped, SWF.DEFAULT_VERSION, staticOperation, path);
output.add(new IfFrameLoadedActionItem(frame, body, this, lineStartAction));
}
@@ -53,7 +53,7 @@ public class ActionAdd2 extends Action {
}
@Override
public void translate(GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
public void translate(boolean insideDoInitAction, GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
GraphTargetItem a = stack.pop();
GraphTargetItem b = stack.pop();
stack.push(new AddActionItem(this, lineStartAction, b, a, true));
@@ -53,7 +53,7 @@ public class ActionBitAnd extends Action {
}
@Override
public void translate(GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
public void translate(boolean insideDoInitAction, GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
GraphTargetItem a = stack.pop();
GraphTargetItem b = stack.pop();
stack.push(new BitAndActionItem(this, lineStartAction, b, a));
@@ -53,7 +53,7 @@ public class ActionBitLShift extends Action {
}
@Override
public void translate(GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
public void translate(boolean insideDoInitAction, GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
GraphTargetItem a = stack.pop();
GraphTargetItem b = stack.pop();
stack.push(new LShiftActionItem(this, lineStartAction, b, a));
@@ -53,7 +53,7 @@ public class ActionBitOr extends Action {
}
@Override
public void translate(GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
public void translate(boolean insideDoInitAction, GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
GraphTargetItem a = stack.pop();
GraphTargetItem b = stack.pop();
stack.push(new BitOrActionItem(this, lineStartAction, b, a));
@@ -53,7 +53,7 @@ public class ActionBitRShift extends Action {
}
@Override
public void translate(GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
public void translate(boolean insideDoInitAction, GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
GraphTargetItem a = stack.pop();
GraphTargetItem b = stack.pop();
stack.push(new RShiftActionItem(this, lineStartAction, b, a));

Some files were not shown because too many files have changed in this diff Show More