mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/jpexs-decompiler.git
synced 2026-05-31 03:15:11 +00:00
do not use getBytesLength because it "generates" the action bytes to get the length (slow)
use instead getTotalActionLength
This commit is contained in:
@@ -26,6 +26,7 @@ import com.jpexs.decompiler.flash.abc.ScriptPack;
|
||||
import com.jpexs.decompiler.flash.action.Action;
|
||||
import com.jpexs.decompiler.flash.action.ActionDeobfuscation;
|
||||
import com.jpexs.decompiler.flash.action.ActionGraphSource;
|
||||
import com.jpexs.decompiler.flash.action.ActionList;
|
||||
import com.jpexs.decompiler.flash.action.ActionLocalData;
|
||||
import com.jpexs.decompiler.flash.action.model.ConstantPool;
|
||||
import com.jpexs.decompiler.flash.action.model.DirectValueActionItem;
|
||||
@@ -1682,7 +1683,7 @@ public final class SWF implements TreeItem, Timelined {
|
||||
GraphSourceItem ins = code.get(ip);
|
||||
|
||||
if (debugMode) {
|
||||
System.err.println("Visit " + ip + ": ofs" + Helper.formatAddress(((Action) ins).getAddress()) + ":" + ((Action) ins).getASMSource(new ArrayList<GraphSourceItem>(), new ArrayList<Long>(), new ArrayList<String>(), code.version, ScriptExportMode.PCODE) + " stack:" + Helper.stackToString(stack, LocalData.create(new ConstantPool())));
|
||||
System.err.println("Visit " + ip + ": ofs" + Helper.formatAddress(((Action) ins).getAddress()) + ":" + ((Action) ins).getASMSource(new ArrayList<GraphSourceItem>(), new ArrayList<Long>(), new ArrayList<String>(), ScriptExportMode.PCODE) + " stack:" + Helper.stackToString(stack, LocalData.create(new ConstantPool())));
|
||||
}
|
||||
if (ins.isExit()) {
|
||||
break;
|
||||
@@ -1844,12 +1845,12 @@ public final class SWF implements TreeItem, Timelined {
|
||||
|
||||
private List<MyEntry<DirectValueActionItem, ConstantPool>> getVariables(List<MyEntry<DirectValueActionItem, ConstantPool>> variables, List<GraphSourceItem> functions, HashMap<DirectValueActionItem, ConstantPool> strings, HashMap<DirectValueActionItem, String> usageType, ASMSource src, String path) throws InterruptedException {
|
||||
List<MyEntry<DirectValueActionItem, ConstantPool>> ret = new ArrayList<>();
|
||||
List<Action> actions = src.getActions();
|
||||
ActionList actions = src.getActions();
|
||||
actionsMap.put(src, actions);
|
||||
getVariables(variables, functions, strings, usageType, new ActionGraphSource(actions, version, new HashMap<Integer, String>(), new HashMap<String, GraphTargetItem>(), new HashMap<String, GraphTargetItem>()), 0, path);
|
||||
return ret;
|
||||
}
|
||||
private HashMap<ASMSource, List<Action>> actionsMap = new HashMap<>();
|
||||
private HashMap<ASMSource, ActionList> actionsMap = new HashMap<>();
|
||||
|
||||
private void getVariables(List<ContainerItem> objs, String path) throws InterruptedException {
|
||||
List<String> processed = new ArrayList<>();
|
||||
@@ -2155,7 +2156,7 @@ public final class SWF implements TreeItem, Timelined {
|
||||
}
|
||||
}
|
||||
for (ASMSource src : actionsMap.keySet()) {
|
||||
actionsMap.put(src, Action.removeNops(0, actionsMap.get(src), version, ""/*FIXME path*/));
|
||||
actionsMap.get(src).removeNops();
|
||||
src.setActions(actionsMap.get(src));
|
||||
src.setModified();
|
||||
}
|
||||
|
||||
@@ -323,6 +323,16 @@ public class Action implements GraphSourceItem {
|
||||
return getBytes(version).length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Uptates the action length to the length calculated from action bytes
|
||||
*
|
||||
* @param version SWF version
|
||||
*/
|
||||
public void updateLength(int version) {
|
||||
int length = getBytes(version).length;
|
||||
actionLength = length - 1 - ((actionCode >= 0x80) ? 2 : 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Surrounds byte array with Action header
|
||||
*
|
||||
@@ -374,13 +384,12 @@ public class Action implements GraphSourceItem {
|
||||
*
|
||||
* @param list List of actions
|
||||
* @param baseAddress Address of first action in the list
|
||||
* @param version SWF version
|
||||
*/
|
||||
public static void setActionsAddresses(List<Action> list, long baseAddress, int version) {
|
||||
public static void setActionsAddresses(List<Action> list, long baseAddress) {
|
||||
long offset = baseAddress;
|
||||
for (Action a : list) {
|
||||
a.setAddress(offset);
|
||||
offset += a.getBytesLength(version);
|
||||
offset += a.getTotalActionLength();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -493,7 +502,7 @@ public class Action implements GraphSourceItem {
|
||||
if (pos + 1 < list.size()) {
|
||||
len = (int) (((Action) (list.get(pos + 1))).getAddress() - a.getAddress());
|
||||
} else {
|
||||
len = a.getBytesLength(version);
|
||||
len = a.getTotalActionLength();
|
||||
}
|
||||
if (!(a instanceof ActionEnd)) {
|
||||
for (int i = 0; i < len; i++) {
|
||||
@@ -538,12 +547,12 @@ public class Action implements GraphSourceItem {
|
||||
writer.appendNoHilight("FFDec_DeobfuscatePop").newLine();
|
||||
if (fixBranch == 0) { //jump
|
||||
writer.appendNoHilight("Jump loc");
|
||||
writer.appendNoHilight(Helper.formatAddress(a.getAddress() + a.getBytesLength(version) + ((ActionIf) a).getJumpOffset()));
|
||||
writer.appendNoHilight(Helper.formatAddress(a.getAddress() + a.getTotalActionLength() + ((ActionIf) a).getJumpOffset()));
|
||||
} else {
|
||||
//nojump, ignore
|
||||
}
|
||||
} else {
|
||||
a.getASMSourceReplaced(list, importantOffsets, constantPool, version, exportMode, writer);
|
||||
a.getASMSourceReplaced(list, importantOffsets, constantPool, exportMode, writer);
|
||||
}
|
||||
writer.appendNoHilight(a.isIgnored() ? "; ignored" : "");
|
||||
writer.appendNoHilight(add);
|
||||
@@ -593,7 +602,7 @@ public class Action implements GraphSourceItem {
|
||||
* @param exportMode PCode or hex?
|
||||
* @return String of P-code source
|
||||
*/
|
||||
public String getASMSource(List<? extends GraphSourceItem> container, List<Long> knownAddreses, List<String> constantPool, int version, ScriptExportMode exportMode) {
|
||||
public String getASMSource(List<? extends GraphSourceItem> container, List<Long> knownAddreses, List<String> constantPool, ScriptExportMode exportMode) {
|
||||
return toString();
|
||||
}
|
||||
|
||||
@@ -633,10 +642,9 @@ public class Action implements GraphSourceItem {
|
||||
*
|
||||
* @param actions List of actions
|
||||
* @param ip Action index
|
||||
* @param version SWF version
|
||||
* @return address
|
||||
*/
|
||||
public static long ip2adr(List<Action> actions, int ip, int version) {
|
||||
public static long ip2adr(List<Action> actions, int ip) {
|
||||
/* List<Action> actions=new ArrayList<Action>();
|
||||
for(GraphSourceItem s:sources){
|
||||
if(s instanceof Action){
|
||||
@@ -647,7 +655,7 @@ public class Action implements GraphSourceItem {
|
||||
if (actions.isEmpty()) {
|
||||
return 0;
|
||||
}
|
||||
return actions.get(actions.size() - 1).getAddress() + actions.get(actions.size() - 1).getBytesLength(version);
|
||||
return actions.get(actions.size() - 1).getAddress() + actions.get(actions.size() - 1).getTotalActionLength();
|
||||
}
|
||||
if (ip == -1) {
|
||||
return 0;
|
||||
@@ -660,17 +668,16 @@ public class Action implements GraphSourceItem {
|
||||
*
|
||||
* @param actions List of actions
|
||||
* @param addr Address
|
||||
* @param version SWF version
|
||||
* @return action index
|
||||
*/
|
||||
public static int adr2ip(List<Action> actions, long addr, int version) {
|
||||
public static int adr2ip(List<Action> actions, long addr) {
|
||||
for (int ip = 0; ip < actions.size(); ip++) {
|
||||
if (actions.get(ip).getAddress() == addr) {
|
||||
return ip;
|
||||
}
|
||||
}
|
||||
if (actions.size() > 0) {
|
||||
long outpos = actions.get(actions.size() - 1).getAddress() + actions.get(actions.size() - 1).getBytesLength(version);
|
||||
long outpos = actions.get(actions.size() - 1).getAddress() + actions.get(actions.size() - 1).getTotalActionLength();
|
||||
if (addr == outpos) {
|
||||
return actions.size();
|
||||
}
|
||||
@@ -824,7 +831,7 @@ public class Action implements GraphSourceItem {
|
||||
loopip:
|
||||
while (ip <= end) {
|
||||
|
||||
long addr = ip2adr(actions, ip, version);
|
||||
long addr = ip2adr(actions, ip);
|
||||
if (ip > end) {
|
||||
break;
|
||||
}
|
||||
@@ -858,7 +865,7 @@ public class Action implements GraphSourceItem {
|
||||
}
|
||||
List<GraphTargetItem> out;
|
||||
try {
|
||||
out = ActionGraph.translateViaGraph(cnt.getRegNames(), variables2, functions, actions.subList(adr2ip(actions, endAddr, version), adr2ip(actions, endAddr + size, version)), version, staticOperation, path + (cntName == null ? "" : "/" + cntName));
|
||||
out = ActionGraph.translateViaGraph(cnt.getRegNames(), variables2, functions, actions.subList(adr2ip(actions, endAddr), adr2ip(actions, endAddr + size)), version, staticOperation, path + (cntName == null ? "" : "/" + cntName));
|
||||
} catch (OutOfMemoryError | TranslateException | StackOverflowError ex2) {
|
||||
Logger.getLogger(Action.class.getName()).log(Level.SEVERE, "Decompilation error in: " + path, ex2);
|
||||
if (ex2 instanceof OutOfMemoryError) {
|
||||
@@ -877,7 +884,7 @@ public class Action implements GraphSourceItem {
|
||||
endAddr += size;
|
||||
}
|
||||
((GraphSourceItemContainer) action).translateContainer(outs, stack, output, registerNames, variables, functions);
|
||||
ip = adr2ip(actions, endAddr, version);
|
||||
ip = adr2ip(actions, endAddr);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -888,7 +895,7 @@ public 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, version) + aif.getJumpOffset(), version) == ip) {
|
||||
if (adr2ip(actions, ip2adr(actions, ip + 4) + aif.getJumpOffset()) == ip) {
|
||||
ip += 4;
|
||||
continue;
|
||||
}
|
||||
@@ -1188,19 +1195,6 @@ public class Action implements GraphSourceItem {
|
||||
return false;
|
||||
}
|
||||
|
||||
public static List<Action> removeNops(long address, List<Action> actions, int version, String path) {
|
||||
List<Action> ret = actions;
|
||||
try {
|
||||
HilightedTextWriter writer = new HilightedTextWriter(Configuration.getCodeFormatting(), false);
|
||||
Action.actionsToString(new ArrayList<DisassemblyListener>(), address, ret, version, ScriptExportMode.PCODE, writer, path);
|
||||
String s = writer.toString();
|
||||
ret = ASMParser.parse(address, true, s, SWF.DEFAULT_VERSION, false);
|
||||
} catch (IOException | ParseException ex) {
|
||||
Logger.getLogger(SWFInputStream.class.getName()).log(Level.SEVERE, "parsing error. path: " + path, ex);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static void setConstantPool(List<? extends GraphSourceItem> actions, ConstantPool cpool) {
|
||||
for (GraphSourceItem a : actions) {
|
||||
if (a instanceof ActionPush) {
|
||||
@@ -1221,8 +1215,8 @@ public class Action implements GraphSourceItem {
|
||||
}
|
||||
}
|
||||
|
||||
public GraphTextWriter getASMSourceReplaced(List<? extends GraphSourceItem> container, List<Long> knownAddreses, List<String> constantPool, int version, ScriptExportMode exportMode, GraphTextWriter writer) {
|
||||
writer.appendNoHilight(getASMSource(container, knownAddreses, constantPool, version, exportMode));
|
||||
public GraphTextWriter getASMSourceReplaced(List<? extends GraphSourceItem> container, List<Long> knownAddreses, List<String> constantPool, ScriptExportMode exportMode, GraphTextWriter writer) {
|
||||
writer.appendNoHilight(getASMSource(container, knownAddreses, constantPool, exportMode));
|
||||
return writer;
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package com.jpexs.decompiler.flash.action;
|
||||
|
||||
import com.jpexs.decompiler.flash.SWF;
|
||||
import com.jpexs.decompiler.flash.action.special.ActionNop;
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
@@ -29,6 +30,29 @@ public class ActionList extends ArrayList<Action> {
|
||||
ActionListReader.removeAction(this, index, SWF.DEFAULT_VERSION, true);
|
||||
}
|
||||
|
||||
public void removeAction(int index, int count) {
|
||||
if (size() <= index + count - 1) {
|
||||
// Can't remove count elements, only size - index is available
|
||||
count = size() - index;
|
||||
}
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
ActionListReader.removeAction(this, index, SWF.DEFAULT_VERSION, true);
|
||||
}
|
||||
}
|
||||
|
||||
public void addAction(int index, Action action) {
|
||||
ActionListReader.removeAction(this, index, SWF.DEFAULT_VERSION, true);
|
||||
}
|
||||
|
||||
public void removeNops() {
|
||||
for (int i = 0; i < size(); i++) {
|
||||
if (get(i) instanceof ActionNop) {
|
||||
removeAction(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Action getByAddress(long address) {
|
||||
for (Action action : this) {
|
||||
if (action.getAddress() == address) {
|
||||
|
||||
@@ -90,7 +90,7 @@ public class ActionListReader {
|
||||
* @throws java.lang.InterruptedException
|
||||
* @throws java.util.concurrent.TimeoutException
|
||||
*/
|
||||
public static List<Action> readActionListTimeout(final List<DisassemblyListener> listeners, final SWFInputStream sis, final int version, final int ip, final int endIp, final String path) throws IOException, InterruptedException, TimeoutException {
|
||||
public static ActionList readActionListTimeout(final List<DisassemblyListener> listeners, final SWFInputStream sis, final int version, final int ip, final int endIp, final String path) throws IOException, InterruptedException, TimeoutException {
|
||||
try {
|
||||
ActionList actions = CancellableWorker.call(new Callable<ActionList>() {
|
||||
|
||||
@@ -111,7 +111,7 @@ public class ActionListReader {
|
||||
Logger.getLogger(ActionListReader.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
}
|
||||
return new ArrayList<>();
|
||||
return new ActionList();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -180,7 +180,8 @@ public class ActionListReader {
|
||||
Map<Action, Action> jumps = new HashMap<>();
|
||||
getJumps(actions, jumps);
|
||||
|
||||
long endAddress = updateAddresses(actions, 0, version);
|
||||
updateActionLengths(actions, version);
|
||||
long endAddress = updateAddresses(actions, 0);
|
||||
|
||||
// add end action
|
||||
Action lastAction = actions.get(actions.size() - 1);
|
||||
@@ -194,17 +195,16 @@ public class ActionListReader {
|
||||
|
||||
updateJumps(actions, jumps, containerLastActions, endAddress);
|
||||
updateActionStores(actions, jumps);
|
||||
updateActionLengths(actions, version);
|
||||
updateContainerSizes(actions, containerLastActions);
|
||||
|
||||
if (SWFDecompilerPlugin.listener != null) {
|
||||
try {
|
||||
SWFDecompilerPlugin.listener.actionListParsed(actions);
|
||||
|
||||
updateAddresses(actions, 0, version);
|
||||
updateActionLengths(actions, version);
|
||||
updateAddresses(actions, 0);
|
||||
updateJumps(actions, jumps, containerLastActions, endAddress);
|
||||
updateActionStores(actions, jumps);
|
||||
updateActionLengths(actions, version);
|
||||
updateContainerSizes(actions, containerLastActions);
|
||||
} catch (Throwable e) {
|
||||
View.showMessageDialog(null, "Failed to call plugin method actionListParsed. Exception: " + e.getMessage());
|
||||
@@ -297,7 +297,7 @@ public class ActionListReader {
|
||||
new HashMap<Integer, HashMap<String, GraphTargetItem>>(),
|
||||
version, 0, maxRecursionLevel);
|
||||
|
||||
List<Action> ret = new ArrayList<>();
|
||||
ActionList ret = new ActionList();
|
||||
Action last = null;
|
||||
for (Action a : retdups) {
|
||||
if (a != last) {
|
||||
@@ -305,7 +305,7 @@ public class ActionListReader {
|
||||
}
|
||||
last = a;
|
||||
}
|
||||
ret = Action.removeNops(0, ret, version, path);
|
||||
ret.removeNops();
|
||||
ActionList reta = new ActionList();
|
||||
for (Object o : ret) {
|
||||
if (o instanceof Action) {
|
||||
@@ -403,11 +403,11 @@ public class ActionListReader {
|
||||
}
|
||||
}
|
||||
|
||||
private static long updateAddresses(List<Action> actions, long address, int version) {
|
||||
private static long updateAddresses(List<Action> actions, long address) {
|
||||
for (int i = 0; i < actions.size(); i++) {
|
||||
Action a = actions.get(i);
|
||||
a.setAddress(address);
|
||||
int length = a.getBytesLength(version);
|
||||
int length = a.getTotalActionLength();
|
||||
if ((i != actions.size() - 1) && (a instanceof ActionEnd)) {
|
||||
// placeholder for jump action
|
||||
length = new ActionDeobfuscateJump(0).getTotalActionLength();
|
||||
@@ -419,9 +419,7 @@ public class ActionListReader {
|
||||
|
||||
private static void updateActionLengths(List<Action> actions, int version) {
|
||||
for (int i = 0; i < actions.size(); i++) {
|
||||
Action a = actions.get(i);
|
||||
int length = a.getBytesLength(version);
|
||||
a.actionLength = length - 1 - ((a.actionCode >= 0x80) ? 2 : 0);
|
||||
actions.get(i).updateLength(version);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -538,6 +536,7 @@ public class ActionListReader {
|
||||
|
||||
/**
|
||||
* Removes an action from the action list, and updates all references
|
||||
* This method will keep the inner actions of the container when you remove the container
|
||||
*
|
||||
* @param actions
|
||||
* @param index
|
||||
@@ -596,10 +595,10 @@ public class ActionListReader {
|
||||
|
||||
actions.remove(index);
|
||||
|
||||
updateAddresses(actions, startIp, version);
|
||||
updateActionLengths(actions, version);
|
||||
updateAddresses(actions, startIp);
|
||||
updateJumps(actions, jumps, containerLastActions, endAddress);
|
||||
updateActionStores(actions, jumps);
|
||||
updateActionLengths(actions, version);
|
||||
updateContainerSizes(actions, containerLastActions);
|
||||
|
||||
return true;
|
||||
@@ -745,7 +744,7 @@ public class ActionListReader {
|
||||
}
|
||||
|
||||
if (debugMode) {
|
||||
String atos = a.getASMSource(new ArrayList<GraphSourceItem>(), new ArrayList<Long>(), cpool.constants, version, ScriptExportMode.PCODE);
|
||||
String atos = a.getASMSource(new ArrayList<GraphSourceItem>(), new ArrayList<Long>(), cpool.constants, ScriptExportMode.PCODE);
|
||||
if (a instanceof GraphSourceItemContainer) {
|
||||
atos = a.toString();
|
||||
}
|
||||
|
||||
@@ -141,7 +141,7 @@ public class ASMParser {
|
||||
|
||||
ActionConstantPool cpool = new ActionConstantPool(constantPool);
|
||||
cpool.setAddress(address);
|
||||
address += cpool.getBytesLength(version);
|
||||
address += cpool.getTotalActionLength();
|
||||
list.add(cpool);
|
||||
|
||||
while (true) {
|
||||
@@ -185,7 +185,7 @@ public class ASMParser {
|
||||
address += 1;
|
||||
} else if (a != null) {
|
||||
a.setAddress(address);
|
||||
address += a.getBytesLength(version);
|
||||
address += a.getTotalActionLength();
|
||||
}
|
||||
if (a instanceof GraphSourceItemContainer) {
|
||||
containers.push((GraphSourceItemContainer) a);
|
||||
@@ -415,6 +415,8 @@ public class ASMParser {
|
||||
} else {
|
||||
throw new ParseException("Unknown instruction name :" + instructionName, lexer.yyline());
|
||||
}
|
||||
|
||||
a.updateLength(version);
|
||||
return a;
|
||||
}
|
||||
|
||||
@@ -473,19 +475,21 @@ public class ASMParser {
|
||||
identifier = ((ActionJump) link).identifier;
|
||||
|
||||
for (Label label : labels) {
|
||||
ActionJump actionJump = (ActionJump) link;
|
||||
|
||||
if (((ActionJump) link).identifier.equals(label.name)) {
|
||||
((ActionJump) link).setJumpOffset((int) (label.address - (((ActionJump) link).getAddress() + ((ActionJump) link).getBytesLength(version))));
|
||||
if (actionJump.identifier.equals(label.name)) {
|
||||
actionJump.setJumpOffset((int) (label.address - (actionJump.getAddress() + actionJump.getTotalActionLength())));
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (link instanceof ActionIf) {
|
||||
identifier = ((ActionIf) link).identifier;
|
||||
ActionIf actionIf = (ActionIf) link;
|
||||
identifier = actionIf.identifier;
|
||||
|
||||
for (Label label : labels) {
|
||||
if (((ActionIf) link).identifier.equals(label.name)) {
|
||||
((ActionIf) link).setJumpOffset((int) (label.address - (((ActionIf) link).getAddress() + ((ActionIf) link).getBytesLength(version))));
|
||||
if (actionIf.identifier.equals(label.name)) {
|
||||
actionIf.setJumpOffset((int) (label.address - (actionIf.getAddress() + actionIf.getTotalActionLength())));
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -157,7 +157,7 @@ public class ActionSourceGenerator implements SourceGenerator {
|
||||
|| (((ActionJump) onTrue.get(onTrue.size() - 1)).isBreak)))) {
|
||||
ajmp = new ActionJump(0);
|
||||
ret.add(ajmp);
|
||||
onTrueLen += ajmp.getBytesLength(SWF.DEFAULT_VERSION);
|
||||
onTrueLen += ajmp.getTotalActionLength();
|
||||
}
|
||||
ifaif.setJumpOffset(onTrueLen);
|
||||
byte[] onFalseBytes = Action.actionsToBytes(onFalse, false, SWF.DEFAULT_VERSION);
|
||||
@@ -182,7 +182,7 @@ public class ActionSourceGenerator implements SourceGenerator {
|
||||
private void fixLoop(List<Action> code, int breakOffset, int continueOffset) {
|
||||
int pos = 0;
|
||||
for (Action a : code) {
|
||||
pos += a.getBytesLength(SWF.DEFAULT_VERSION);
|
||||
pos += a.getTotalActionLength();
|
||||
if (a instanceof ActionJump) {
|
||||
ActionJump aj = (ActionJump) a;
|
||||
if (aj.isContinue && (continueOffset != Integer.MAX_VALUE)) {
|
||||
@@ -248,7 +248,7 @@ public class ActionSourceGenerator implements SourceGenerator {
|
||||
ret.addAll(doExpr);
|
||||
ActionIf doif = new ActionIf(0);
|
||||
ret.add(doif);
|
||||
int offset = doBodyLen + doExprLen + doif.getBytesLength(SWF.DEFAULT_VERSION);
|
||||
int offset = doBodyLen + doExprLen + doif.getTotalActionLength();
|
||||
doif.setJumpOffset(-offset);
|
||||
fixLoop(doBody, offset, doBodyLen);
|
||||
return ret;
|
||||
@@ -265,7 +265,7 @@ public class ActionSourceGenerator implements SourceGenerator {
|
||||
ActionIf foraif = new ActionIf(0);
|
||||
forExpr.add(foraif);
|
||||
ActionJump forajmp = new ActionJump(0);
|
||||
int forajmpLen = forajmp.getBytesLength(SWF.DEFAULT_VERSION);
|
||||
int forajmpLen = forajmp.getTotalActionLength();
|
||||
int forExprLen = Action.actionsToBytes(forExpr, false, SWF.DEFAULT_VERSION).length;
|
||||
int forBodyLen = Action.actionsToBytes(forBody, false, SWF.DEFAULT_VERSION).length;
|
||||
int forFinalLen = Action.actionsToBytes(forFinalCommands, false, SWF.DEFAULT_VERSION).length;
|
||||
@@ -373,7 +373,7 @@ public class ActionSourceGenerator implements SourceGenerator {
|
||||
jmpPos += exprLengths.get(k).get(m);
|
||||
}
|
||||
}
|
||||
jmpPos += defJump.getBytesLength(SWF.DEFAULT_VERSION);
|
||||
jmpPos += defJump.getTotalActionLength();
|
||||
for (int n = 0; n < i; n++) {
|
||||
jmpPos += caseLengths.get(n);
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ public class ActionWaitForFrame extends Action implements ActionStore {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getASMSource(List<? extends GraphSourceItem> container, List<Long> knownAddreses, List<String> constantPool, int version, ScriptExportMode exportMode) {
|
||||
public String getASMSource(List<? extends GraphSourceItem> container, List<Long> knownAddreses, List<String> constantPool, ScriptExportMode exportMode) {
|
||||
String ret = "WaitForFrame " + frame + " " + skipCount;
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -75,8 +75,8 @@ public class ActionIf extends Action {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getASMSource(List<? extends GraphSourceItem> container, List<Long> knownAddreses, List<String> constantPool, int version, ScriptExportMode exportMode) {
|
||||
String ofsStr = Helper.formatAddress(getAddress() + getBytesLength(version) + offset);
|
||||
public String getASMSource(List<? extends GraphSourceItem> container, List<Long> knownAddreses, List<String> constantPool, ScriptExportMode exportMode) {
|
||||
String ofsStr = Helper.formatAddress(getAddress() + getTotalActionLength() + offset);
|
||||
return "If loc" + ofsStr + (!jumpUsed ? " ;compileTimeIgnore" : (!ignoreUsed ? " ;compileTimeJump" : ""));
|
||||
}
|
||||
|
||||
@@ -98,8 +98,7 @@ public class ActionIf extends Action {
|
||||
@Override
|
||||
public List<Integer> getBranches(GraphSource code) {
|
||||
List<Integer> ret = super.getBranches(code);
|
||||
int version = ((ActionGraphSource) code).version;
|
||||
int length = getBytesLength(version);
|
||||
int length = getTotalActionLength();
|
||||
int jmp = code.adr2pos(getAddress() + length + offset);
|
||||
int after = code.adr2pos(getAddress() + length);
|
||||
if (jmp == -1) {
|
||||
|
||||
@@ -75,8 +75,8 @@ public class ActionJump extends Action {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getASMSource(List<? extends GraphSourceItem> container, List<Long> knownAddreses, List<String> constantPool, int version, ScriptExportMode exportMode) {
|
||||
String ofsStr = Helper.formatAddress(getAddress() + getBytesLength(version) + offset);
|
||||
public String getASMSource(List<? extends GraphSourceItem> container, List<Long> knownAddreses, List<String> constantPool, ScriptExportMode exportMode) {
|
||||
String ofsStr = Helper.formatAddress(getAddress() + getTotalActionLength() + offset);
|
||||
return "Jump loc" + ofsStr;
|
||||
}
|
||||
|
||||
|
||||
@@ -231,7 +231,7 @@ public class ActionPush extends Action {
|
||||
}
|
||||
|
||||
@Override
|
||||
public GraphTextWriter getASMSourceReplaced(List<? extends GraphSourceItem> container, List<Long> knownAddreses, List<String> constantPool, int version, ScriptExportMode exportMode, GraphTextWriter writer) {
|
||||
public GraphTextWriter getASMSourceReplaced(List<? extends GraphSourceItem> container, List<Long> knownAddreses, List<String> constantPool, ScriptExportMode exportMode, GraphTextWriter writer) {
|
||||
if (replacement == null || replacement.size() < values.size()) {
|
||||
return toString(writer);
|
||||
}
|
||||
|
||||
@@ -116,7 +116,7 @@ public class ActionWaitForFrame2 extends Action implements ActionStore {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getASMSource(List<? extends GraphSourceItem> container, List<Long> knownAddreses, List<String> constantPool, int version, ScriptExportMode exportMode) {
|
||||
public String getASMSource(List<? extends GraphSourceItem> container, List<Long> knownAddreses, List<String> constantPool, ScriptExportMode exportMode) {
|
||||
String ret = "WaitForFrame2 " + skipCount;
|
||||
/*for (int i = 0; i < skipped.size(); i++) {
|
||||
if (skipped.get(i) instanceof ActionEnd) {
|
||||
|
||||
@@ -146,7 +146,7 @@ public class ActionDefineFunction extends Action implements GraphSourceItemConta
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getASMSource(List<? extends GraphSourceItem> container, List<Long> knownAddreses, List<String> constantPool, int version, ScriptExportMode exportMode) {
|
||||
public String getASMSource(List<? extends GraphSourceItem> container, List<Long> knownAddreses, List<String> constantPool, ScriptExportMode exportMode) {
|
||||
StringBuilder paramStr = new StringBuilder();
|
||||
for (int i = 0; i < paramNames.size(); i++) {
|
||||
paramStr.append("\"").append(Helper.escapeString(paramNames.get(i))).append("\" ");
|
||||
@@ -156,7 +156,7 @@ public class ActionDefineFunction extends Action implements GraphSourceItemConta
|
||||
}
|
||||
|
||||
@Override
|
||||
public GraphTextWriter getASMSourceReplaced(List<? extends GraphSourceItem> container, List<Long> knownAddreses, List<String> constantPool, int version, ScriptExportMode exportMode, GraphTextWriter writer) {
|
||||
public GraphTextWriter getASMSourceReplaced(List<? extends GraphSourceItem> container, List<Long> knownAddreses, List<String> constantPool, ScriptExportMode exportMode, GraphTextWriter writer) {
|
||||
List<String> oldParamNames = paramNames;
|
||||
if (replacedParamNames != null) {
|
||||
paramNames = replacedParamNames;
|
||||
@@ -165,7 +165,7 @@ public class ActionDefineFunction extends Action implements GraphSourceItemConta
|
||||
if (replacedFunctionName != null) {
|
||||
functionName = replacedFunctionName;
|
||||
}
|
||||
String ret = getASMSource(container, knownAddreses, constantPool, version, exportMode);
|
||||
String ret = getASMSource(container, knownAddreses, constantPool, exportMode);
|
||||
paramNames = oldParamNames;
|
||||
functionName = oldFunctionName;
|
||||
writer.appendNoHilight(ret);
|
||||
|
||||
@@ -75,7 +75,7 @@ public class ActionWith extends Action implements GraphSourceItemContainer {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getASMSource(List<? extends GraphSourceItem> container, List<Long> knownAddreses, List<String> constantPool, int version, ScriptExportMode exportMode) {
|
||||
public String getASMSource(List<? extends GraphSourceItem> container, List<Long> knownAddreses, List<String> constantPool, ScriptExportMode exportMode) {
|
||||
return "With {";
|
||||
}
|
||||
|
||||
|
||||
@@ -226,7 +226,7 @@ public class ActionDefineFunction2 extends Action implements GraphSourceItemCont
|
||||
}
|
||||
|
||||
@Override
|
||||
public GraphTextWriter getASMSourceReplaced(List<? extends GraphSourceItem> container, List<Long> knownAddreses, List<String> constantPool, int version, ScriptExportMode exportMode, GraphTextWriter writer) {
|
||||
public GraphTextWriter getASMSourceReplaced(List<? extends GraphSourceItem> container, List<Long> knownAddreses, List<String> constantPool, ScriptExportMode exportMode, GraphTextWriter writer) {
|
||||
List<String> oldParamNames = paramNames;
|
||||
if (replacedParamNames != null) {
|
||||
paramNames = replacedParamNames;
|
||||
@@ -235,7 +235,7 @@ public class ActionDefineFunction2 extends Action implements GraphSourceItemCont
|
||||
if (replacedFunctionName != null) {
|
||||
functionName = replacedFunctionName;
|
||||
}
|
||||
String ret = getASMSource(container, knownAddreses, constantPool, version, exportMode);
|
||||
String ret = getASMSource(container, knownAddreses, constantPool, exportMode);
|
||||
paramNames = oldParamNames;
|
||||
functionName = oldFunctionName;
|
||||
writer.appendNoHilight(ret);
|
||||
@@ -244,7 +244,7 @@ public class ActionDefineFunction2 extends Action implements GraphSourceItemCont
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getASMSource(List<? extends GraphSourceItem> container, List<Long> knownAddreses, List<String> constantPool, int version, ScriptExportMode exportMode) {
|
||||
public String getASMSource(List<? extends GraphSourceItem> container, List<Long> knownAddreses, List<String> constantPool, ScriptExportMode exportMode) {
|
||||
StringBuilder paramStr = new StringBuilder();
|
||||
for (int i = 0; i < paramNames.size(); i++) {
|
||||
paramStr.append(paramRegisters.get(i)).append(" \"").append(Helper.escapeString(paramNames.get(i))).append("\" ");
|
||||
|
||||
@@ -148,7 +148,7 @@ public class ActionTry extends Action implements GraphSourceItemContainer {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getASMSource(List<? extends GraphSourceItem> container, List<Long> knownAddreses, List<String> constantPool, int version, ScriptExportMode exportMode) {
|
||||
public String getASMSource(List<? extends GraphSourceItem> container, List<Long> knownAddreses, List<String> constantPool, ScriptExportMode exportMode) {
|
||||
String ret = "";
|
||||
ret += "Try ";
|
||||
if (catchBlockFlag) {
|
||||
|
||||
@@ -21,6 +21,7 @@ import com.jpexs.decompiler.flash.SWFInputStream;
|
||||
import com.jpexs.decompiler.flash.SWFOutputStream;
|
||||
import com.jpexs.decompiler.flash.abc.CopyOutputStream;
|
||||
import com.jpexs.decompiler.flash.action.Action;
|
||||
import com.jpexs.decompiler.flash.action.ActionList;
|
||||
import com.jpexs.decompiler.flash.action.ActionListReader;
|
||||
import com.jpexs.decompiler.flash.configuration.Configuration;
|
||||
import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode;
|
||||
@@ -165,20 +166,20 @@ public class DefineButtonTag extends ButtonTag implements ASMSource {
|
||||
* @throws java.lang.InterruptedException
|
||||
*/
|
||||
@Override
|
||||
public List<Action> getActions() throws InterruptedException {
|
||||
public ActionList getActions() throws InterruptedException {
|
||||
try {
|
||||
int prevLength = actionBytes.pos;
|
||||
SWFInputStream rri = new SWFInputStream(swf, actionBytes.array);
|
||||
if (prevLength != 0) {
|
||||
rri.seek(prevLength);
|
||||
}
|
||||
List<Action> list = ActionListReader.readActionListTimeout(listeners, rri, getVersion(), prevLength, prevLength + actionBytes.length, toString()/*FIXME?*/);
|
||||
ActionList list = ActionListReader.readActionListTimeout(listeners, rri, getVersion(), prevLength, prevLength + actionBytes.length, toString()/*FIXME?*/);
|
||||
return list;
|
||||
} catch (InterruptedException ex) {
|
||||
throw ex;
|
||||
} catch (Exception ex) {
|
||||
Logger.getLogger(DoActionTag.class.getName()).log(Level.SEVERE, null, ex);
|
||||
return new ArrayList<>();
|
||||
return new ActionList();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ import com.jpexs.decompiler.flash.DisassemblyListener;
|
||||
import com.jpexs.decompiler.flash.SWF;
|
||||
import com.jpexs.decompiler.flash.SWFInputStream;
|
||||
import com.jpexs.decompiler.flash.action.Action;
|
||||
import com.jpexs.decompiler.flash.action.ActionList;
|
||||
import com.jpexs.decompiler.flash.action.ActionListReader;
|
||||
import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode;
|
||||
import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
|
||||
@@ -119,20 +120,20 @@ public class DoActionTag extends Tag implements ASMSource {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Action> getActions() throws InterruptedException {
|
||||
public ActionList getActions() throws InterruptedException {
|
||||
try {
|
||||
int prevLength = actionBytes.pos;
|
||||
SWFInputStream rri = new SWFInputStream(swf, actionBytes.array);
|
||||
if (prevLength != 0) {
|
||||
rri.seek(prevLength);
|
||||
}
|
||||
List<Action> list = ActionListReader.readActionListTimeout(listeners, rri, getVersion(), prevLength, prevLength + actionBytes.length, toString()/*FIXME?*/);
|
||||
ActionList list = ActionListReader.readActionListTimeout(listeners, rri, getVersion(), prevLength, prevLength + actionBytes.length, toString()/*FIXME?*/);
|
||||
return list;
|
||||
} catch (InterruptedException ex) {
|
||||
throw ex;
|
||||
} catch (Exception ex) {
|
||||
Logger.getLogger(DoActionTag.class.getName()).log(Level.SEVERE, null, ex);
|
||||
return new ArrayList<>();
|
||||
return new ActionList();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ import com.jpexs.decompiler.flash.DisassemblyListener;
|
||||
import com.jpexs.decompiler.flash.SWFInputStream;
|
||||
import com.jpexs.decompiler.flash.SWFOutputStream;
|
||||
import com.jpexs.decompiler.flash.action.Action;
|
||||
import com.jpexs.decompiler.flash.action.ActionList;
|
||||
import com.jpexs.decompiler.flash.action.ActionListReader;
|
||||
import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode;
|
||||
import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
|
||||
@@ -113,20 +114,20 @@ public class DoInitActionTag extends CharacterIdTag implements ASMSource {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Action> getActions() throws InterruptedException {
|
||||
public ActionList getActions() throws InterruptedException {
|
||||
try {
|
||||
int prevLength = actionBytes.pos;
|
||||
SWFInputStream rri = new SWFInputStream(swf, actionBytes.array);
|
||||
if (prevLength != 0) {
|
||||
rri.seek(prevLength);
|
||||
}
|
||||
List<Action> list = ActionListReader.readActionListTimeout(listeners, rri, getVersion(), prevLength, prevLength + actionBytes.length, toString()/*FIXME?*/);
|
||||
ActionList list = ActionListReader.readActionListTimeout(listeners, rri, getVersion(), prevLength, prevLength + actionBytes.length, toString()/*FIXME?*/);
|
||||
return list;
|
||||
} catch (InterruptedException ex) {
|
||||
throw ex;
|
||||
} catch (Exception ex) {
|
||||
Logger.getLogger(DoActionTag.class.getName()).log(Level.SEVERE, null, ex);
|
||||
return new ArrayList<>();
|
||||
return new ActionList();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.jpexs.decompiler.flash.tags.base;
|
||||
|
||||
import com.jpexs.decompiler.flash.DisassemblyListener;
|
||||
import com.jpexs.decompiler.flash.action.Action;
|
||||
import com.jpexs.decompiler.flash.action.ActionList;
|
||||
import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode;
|
||||
import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
|
||||
import com.jpexs.decompiler.flash.tags.Tag;
|
||||
@@ -55,7 +56,7 @@ public interface ASMSource extends TreeItem {
|
||||
* @return List of actions
|
||||
* @throws java.lang.InterruptedException
|
||||
*/
|
||||
public List<Action> getActions() throws InterruptedException;
|
||||
public ActionList getActions() throws InterruptedException;
|
||||
|
||||
/**
|
||||
* Sets actions associated with this object
|
||||
|
||||
@@ -1,192 +1,192 @@
|
||||
/*
|
||||
* Copyright (C) 2010-2014 JPEXS
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.treenodes;
|
||||
|
||||
import com.jpexs.decompiler.flash.AbortRetryIgnoreHandler;
|
||||
import com.jpexs.decompiler.flash.EventListener;
|
||||
import com.jpexs.decompiler.flash.action.Action;
|
||||
import com.jpexs.decompiler.flash.configuration.Configuration;
|
||||
import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode;
|
||||
import com.jpexs.decompiler.flash.helpers.FileTextWriter;
|
||||
import com.jpexs.decompiler.flash.tags.Tag;
|
||||
import com.jpexs.decompiler.flash.tags.base.ASMSource;
|
||||
import com.jpexs.decompiler.flash.tags.base.Exportable;
|
||||
import com.jpexs.decompiler.graph.TranslateException;
|
||||
import com.jpexs.helpers.CancellableWorker;
|
||||
import com.jpexs.helpers.Helper;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public class TagNode extends ContainerNode {
|
||||
|
||||
public TagNode(Tag tag) {
|
||||
super(tag);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Tag getItem() {
|
||||
return (Tag) item;
|
||||
}
|
||||
|
||||
public static void setExport(List<TreeNode> nodeList, boolean export) {
|
||||
for (TreeNode node : nodeList) {
|
||||
node.export = export;
|
||||
setExport(node.subNodes, export);
|
||||
}
|
||||
}
|
||||
|
||||
public static int getTagCountRecursive(List<TreeNode> nodeList) {
|
||||
int count = 0;
|
||||
|
||||
for (TreeNode node : nodeList) {
|
||||
if (node.subNodes.isEmpty()) {
|
||||
if ((node.item instanceof ASMSource) && (node.export)) {
|
||||
count += 1;
|
||||
}
|
||||
} else {
|
||||
count += getTagCountRecursive(node.subNodes);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
public static List<File> exportNodeAS(final AbortRetryIgnoreHandler handler, final List<TreeNode> nodeList, final String outdir, final ScriptExportMode exportMode, final EventListener ev) throws IOException {
|
||||
try {
|
||||
List<File> result = CancellableWorker.call(new Callable<List<File>>() {
|
||||
|
||||
@Override
|
||||
public List<File> call() throws Exception {
|
||||
AtomicInteger cnt = new AtomicInteger(1);
|
||||
int totalCount = TagNode.getTagCountRecursive(nodeList);
|
||||
return exportNodeAS(handler, nodeList, outdir, exportMode, cnt, totalCount, ev);
|
||||
}
|
||||
}, Configuration.exportTimeout.get(), TimeUnit.SECONDS);
|
||||
return result;
|
||||
} catch (ExecutionException | InterruptedException | TimeoutException ex) {
|
||||
}
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
private static List<File> exportNodeAS(AbortRetryIgnoreHandler handler, List<TreeNode> nodeList, String outdir, ScriptExportMode exportMode, AtomicInteger index, int count, EventListener ev) throws IOException {
|
||||
File dir = new File(outdir);
|
||||
List<File> ret = new ArrayList<>();
|
||||
if (!outdir.endsWith(File.separator)) {
|
||||
outdir += File.separator;
|
||||
}
|
||||
List<String> existingNames = new ArrayList<>();
|
||||
for (TreeNode node : nodeList) {
|
||||
String name = "";
|
||||
if (node.item instanceof Exportable) {
|
||||
name = Helper.makeFileName(((Exportable) node.item).getExportFileName());
|
||||
} else {
|
||||
name = Helper.makeFileName(node.item.toString());
|
||||
}
|
||||
int i = 1;
|
||||
String baseName = name;
|
||||
while (existingNames.contains(name)) {
|
||||
i++;
|
||||
name = baseName + "_" + i;
|
||||
}
|
||||
existingNames.add(name);
|
||||
if (node.subNodes.isEmpty()) {
|
||||
if ((node.item instanceof ASMSource) && (node.export)) {
|
||||
boolean retry;
|
||||
do {
|
||||
retry = false;
|
||||
try {
|
||||
int currentIndex = index.getAndIncrement();
|
||||
|
||||
if (!dir.exists()) {
|
||||
if (!dir.mkdirs()) {
|
||||
if (!dir.exists()) {
|
||||
throw new IOException("Cannot create directory " + outdir);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
String f = outdir + name + ".as";
|
||||
if (ev != null) {
|
||||
ev.handleEvent("exporting", "Exporting " + currentIndex + "/" + count + " " + f);
|
||||
}
|
||||
|
||||
long startTime = System.currentTimeMillis();
|
||||
|
||||
File file = new File(f);
|
||||
ASMSource asm = ((ASMSource) node.item);
|
||||
try (FileTextWriter writer = new FileTextWriter(Configuration.getCodeFormatting(), new FileOutputStream(f))) {
|
||||
if (exportMode == ScriptExportMode.HEX) {
|
||||
asm.getActionSourcePrefix(writer);
|
||||
asm.getActionBytesAsHex(writer);
|
||||
asm.getActionSourceSuffix(writer);
|
||||
} else if (exportMode != ScriptExportMode.AS) {
|
||||
asm.getActionSourcePrefix(writer);
|
||||
asm.getASMSource(exportMode, writer, null);
|
||||
asm.getActionSourceSuffix(writer);
|
||||
} else {
|
||||
List<Action> as = asm.getActions();
|
||||
Action.setActionsAddresses(as, 0, asm.getSwf().version);
|
||||
Action.actionsToSource(asm, as, ""/*FIXME*/, writer);
|
||||
}
|
||||
}
|
||||
|
||||
long stopTime = System.currentTimeMillis();
|
||||
|
||||
if (ev != null) {
|
||||
long time = stopTime - startTime;
|
||||
ev.handleEvent("exported", "Exported " + currentIndex + "/" + count + " " + f + ", " + Helper.formatTimeSec(time));
|
||||
}
|
||||
|
||||
ret.add(file);
|
||||
} catch (InterruptedException ex) {
|
||||
} catch (IOException | OutOfMemoryError | TranslateException | StackOverflowError ex) {
|
||||
Logger.getLogger(TagNode.class.getName()).log(Level.SEVERE, "Decompilation error in file: " + name + ".as", ex);
|
||||
if (handler != null) {
|
||||
int action = handler.getNewInstance().handle(ex);
|
||||
switch (action) {
|
||||
case AbortRetryIgnoreHandler.ABORT:
|
||||
throw ex;
|
||||
case AbortRetryIgnoreHandler.RETRY:
|
||||
retry = true;
|
||||
break;
|
||||
case AbortRetryIgnoreHandler.IGNORE:
|
||||
retry = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} while (retry);
|
||||
}
|
||||
} else {
|
||||
ret.addAll(exportNodeAS(handler, node.subNodes, outdir + name, exportMode, index, count, ev));
|
||||
}
|
||||
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Copyright (C) 2010-2014 JPEXS
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.treenodes;
|
||||
|
||||
import com.jpexs.decompiler.flash.AbortRetryIgnoreHandler;
|
||||
import com.jpexs.decompiler.flash.EventListener;
|
||||
import com.jpexs.decompiler.flash.action.Action;
|
||||
import com.jpexs.decompiler.flash.configuration.Configuration;
|
||||
import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode;
|
||||
import com.jpexs.decompiler.flash.helpers.FileTextWriter;
|
||||
import com.jpexs.decompiler.flash.tags.Tag;
|
||||
import com.jpexs.decompiler.flash.tags.base.ASMSource;
|
||||
import com.jpexs.decompiler.flash.tags.base.Exportable;
|
||||
import com.jpexs.decompiler.graph.TranslateException;
|
||||
import com.jpexs.helpers.CancellableWorker;
|
||||
import com.jpexs.helpers.Helper;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public class TagNode extends ContainerNode {
|
||||
|
||||
public TagNode(Tag tag) {
|
||||
super(tag);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Tag getItem() {
|
||||
return (Tag) item;
|
||||
}
|
||||
|
||||
public static void setExport(List<TreeNode> nodeList, boolean export) {
|
||||
for (TreeNode node : nodeList) {
|
||||
node.export = export;
|
||||
setExport(node.subNodes, export);
|
||||
}
|
||||
}
|
||||
|
||||
public static int getTagCountRecursive(List<TreeNode> nodeList) {
|
||||
int count = 0;
|
||||
|
||||
for (TreeNode node : nodeList) {
|
||||
if (node.subNodes.isEmpty()) {
|
||||
if ((node.item instanceof ASMSource) && (node.export)) {
|
||||
count += 1;
|
||||
}
|
||||
} else {
|
||||
count += getTagCountRecursive(node.subNodes);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
public static List<File> exportNodeAS(final AbortRetryIgnoreHandler handler, final List<TreeNode> nodeList, final String outdir, final ScriptExportMode exportMode, final EventListener ev) throws IOException {
|
||||
try {
|
||||
List<File> result = CancellableWorker.call(new Callable<List<File>>() {
|
||||
|
||||
@Override
|
||||
public List<File> call() throws Exception {
|
||||
AtomicInteger cnt = new AtomicInteger(1);
|
||||
int totalCount = TagNode.getTagCountRecursive(nodeList);
|
||||
return exportNodeAS(handler, nodeList, outdir, exportMode, cnt, totalCount, ev);
|
||||
}
|
||||
}, Configuration.exportTimeout.get(), TimeUnit.SECONDS);
|
||||
return result;
|
||||
} catch (ExecutionException | InterruptedException | TimeoutException ex) {
|
||||
}
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
private static List<File> exportNodeAS(AbortRetryIgnoreHandler handler, List<TreeNode> nodeList, String outdir, ScriptExportMode exportMode, AtomicInteger index, int count, EventListener ev) throws IOException {
|
||||
File dir = new File(outdir);
|
||||
List<File> ret = new ArrayList<>();
|
||||
if (!outdir.endsWith(File.separator)) {
|
||||
outdir += File.separator;
|
||||
}
|
||||
List<String> existingNames = new ArrayList<>();
|
||||
for (TreeNode node : nodeList) {
|
||||
String name = "";
|
||||
if (node.item instanceof Exportable) {
|
||||
name = Helper.makeFileName(((Exportable) node.item).getExportFileName());
|
||||
} else {
|
||||
name = Helper.makeFileName(node.item.toString());
|
||||
}
|
||||
int i = 1;
|
||||
String baseName = name;
|
||||
while (existingNames.contains(name)) {
|
||||
i++;
|
||||
name = baseName + "_" + i;
|
||||
}
|
||||
existingNames.add(name);
|
||||
if (node.subNodes.isEmpty()) {
|
||||
if ((node.item instanceof ASMSource) && (node.export)) {
|
||||
boolean retry;
|
||||
do {
|
||||
retry = false;
|
||||
try {
|
||||
int currentIndex = index.getAndIncrement();
|
||||
|
||||
if (!dir.exists()) {
|
||||
if (!dir.mkdirs()) {
|
||||
if (!dir.exists()) {
|
||||
throw new IOException("Cannot create directory " + outdir);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
String f = outdir + name + ".as";
|
||||
if (ev != null) {
|
||||
ev.handleEvent("exporting", "Exporting " + currentIndex + "/" + count + " " + f);
|
||||
}
|
||||
|
||||
long startTime = System.currentTimeMillis();
|
||||
|
||||
File file = new File(f);
|
||||
ASMSource asm = ((ASMSource) node.item);
|
||||
try (FileTextWriter writer = new FileTextWriter(Configuration.getCodeFormatting(), new FileOutputStream(f))) {
|
||||
if (exportMode == ScriptExportMode.HEX) {
|
||||
asm.getActionSourcePrefix(writer);
|
||||
asm.getActionBytesAsHex(writer);
|
||||
asm.getActionSourceSuffix(writer);
|
||||
} else if (exportMode != ScriptExportMode.AS) {
|
||||
asm.getActionSourcePrefix(writer);
|
||||
asm.getASMSource(exportMode, writer, null);
|
||||
asm.getActionSourceSuffix(writer);
|
||||
} else {
|
||||
List<Action> as = asm.getActions();
|
||||
Action.setActionsAddresses(as, 0);
|
||||
Action.actionsToSource(asm, as, ""/*FIXME*/, writer);
|
||||
}
|
||||
}
|
||||
|
||||
long stopTime = System.currentTimeMillis();
|
||||
|
||||
if (ev != null) {
|
||||
long time = stopTime - startTime;
|
||||
ev.handleEvent("exported", "Exported " + currentIndex + "/" + count + " " + f + ", " + Helper.formatTimeSec(time));
|
||||
}
|
||||
|
||||
ret.add(file);
|
||||
} catch (InterruptedException ex) {
|
||||
} catch (IOException | OutOfMemoryError | TranslateException | StackOverflowError ex) {
|
||||
Logger.getLogger(TagNode.class.getName()).log(Level.SEVERE, "Decompilation error in file: " + name + ".as", ex);
|
||||
if (handler != null) {
|
||||
int action = handler.getNewInstance().handle(ex);
|
||||
switch (action) {
|
||||
case AbortRetryIgnoreHandler.ABORT:
|
||||
throw ex;
|
||||
case AbortRetryIgnoreHandler.RETRY:
|
||||
retry = true;
|
||||
break;
|
||||
case AbortRetryIgnoreHandler.IGNORE:
|
||||
retry = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} while (retry);
|
||||
}
|
||||
} else {
|
||||
ret.addAll(exportNodeAS(handler, node.subNodes, outdir + name, exportMode, index, count, ev));
|
||||
}
|
||||
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ import com.jpexs.decompiler.flash.DisassemblyListener;
|
||||
import com.jpexs.decompiler.flash.SWF;
|
||||
import com.jpexs.decompiler.flash.SWFInputStream;
|
||||
import com.jpexs.decompiler.flash.action.Action;
|
||||
import com.jpexs.decompiler.flash.action.ActionList;
|
||||
import com.jpexs.decompiler.flash.action.ActionListReader;
|
||||
import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode;
|
||||
import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
|
||||
@@ -184,16 +185,16 @@ public class BUTTONCONDACTION implements ASMSource, Exportable, ContainerItem, S
|
||||
* @throws java.lang.InterruptedException
|
||||
*/
|
||||
@Override
|
||||
public List<Action> getActions() throws InterruptedException {
|
||||
public ActionList getActions() throws InterruptedException {
|
||||
try {
|
||||
List<Action> list = ActionListReader.readActionListTimeout(listeners, new SWFInputStream(swf, actionBytes), swf.version, 0, -1, toString()/*FIXME?*/);
|
||||
ActionList list = ActionListReader.readActionListTimeout(listeners, new SWFInputStream(swf, actionBytes), swf.version, 0, -1, toString()/*FIXME?*/);
|
||||
return list;
|
||||
|
||||
} catch (InterruptedException ex) {
|
||||
throw ex;
|
||||
} catch (Exception ex) {
|
||||
Logger.getLogger(BUTTONCONDACTION.class.getName()).log(Level.SEVERE, null, ex);
|
||||
return new ArrayList<>();
|
||||
return new ActionList();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ import com.jpexs.decompiler.flash.DisassemblyListener;
|
||||
import com.jpexs.decompiler.flash.SWF;
|
||||
import com.jpexs.decompiler.flash.SWFInputStream;
|
||||
import com.jpexs.decompiler.flash.action.Action;
|
||||
import com.jpexs.decompiler.flash.action.ActionList;
|
||||
import com.jpexs.decompiler.flash.action.ActionListReader;
|
||||
import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode;
|
||||
import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
|
||||
@@ -194,15 +195,15 @@ public class CLIPACTIONRECORD implements ASMSource, Exportable, ContainerItem, S
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Action> getActions() throws InterruptedException {
|
||||
public ActionList getActions() throws InterruptedException {
|
||||
try {
|
||||
List<Action> list = ActionListReader.readActionListTimeout(listeners, new SWFInputStream(swf, actionBytes), swf.version, 0, -1, toString()/*FIXME?*/);
|
||||
ActionList list = ActionListReader.readActionListTimeout(listeners, new SWFInputStream(swf, actionBytes), swf.version, 0, -1, toString()/*FIXME?*/);
|
||||
return list;
|
||||
} catch (InterruptedException ex) {
|
||||
throw ex;
|
||||
} catch (Exception ex) {
|
||||
Logger.getLogger(BUTTONCONDACTION.class.getName()).log(Level.SEVERE, null, ex);
|
||||
return new ArrayList<>();
|
||||
return new ActionList();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user