diff --git a/trunk/src/com/jpexs/decompiler/flash/ReReadableInputStream.java b/trunk/src/com/jpexs/decompiler/flash/ReReadableInputStream.java index 2c0259ac1..c904790aa 100644 --- a/trunk/src/com/jpexs/decompiler/flash/ReReadableInputStream.java +++ b/trunk/src/com/jpexs/decompiler/flash/ReReadableInputStream.java @@ -62,13 +62,13 @@ public class ReReadableInputStream extends InputStream { return ret; } int i = is.read(); - if(i>-1){ + if (i > -1) { baos.write(i); - count++; + count++; } pos++; converted = null; - + return i; } diff --git a/trunk/src/com/jpexs/decompiler/flash/SWFInputStream.java b/trunk/src/com/jpexs/decompiler/flash/SWFInputStream.java index 0bff7fdcf..6df6435d7 100644 --- a/trunk/src/com/jpexs/decompiler/flash/SWFInputStream.java +++ b/trunk/src/com/jpexs/decompiler/flash/SWFInputStream.java @@ -2414,7 +2414,7 @@ public class SWFInputStream extends InputStream { COLORMAPDATA ret = new COLORMAPDATA(); ret.colorTableRGB = new RGB[colorTableSize + 1]; for (int i = 0; i < colorTableSize + 1; i++) { - ret.colorTableRGB[i] = readRGB(); + ret.colorTableRGB[i] = readRGB(); } int dataLen = 0; for (int y = 0; y < bitmapHeight; y++) { diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/graph/AVM2Graph.java b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/graph/AVM2Graph.java index 8e053186c..da1cef3d7 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/graph/AVM2Graph.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/graph/AVM2Graph.java @@ -137,23 +137,28 @@ public class AVM2Graph extends Graph { } for (Loop l : loops) { if (l.loopContinue == part) { - return (new ContinueTreeItem(null, l.loopBreak == null ? -1 : l.loopBreak.start)); + return (new ContinueTreeItem(null, l.id)); } if (l.loopBreak == part) { - return (new BreakTreeItem(null, part.start)); + return (new BreakTreeItem(null, l.id)); } } return null; } private boolean doDecompile = true; + private void checkContinueAtTheEnd(List commands, Loop loop) { + if (!commands.isEmpty()) { + if (commands.get(commands.size() - 1) instanceof ContinueTreeItem) { + if (((ContinueTreeItem) commands.get(commands.size() - 1)).loopPos == loop.id) { + commands.remove(commands.size() - 1); + } + } + } + } + private List printGraph(String methodPath, Stack stack, Stack scopeStack, List allParts, List parsedExceptions, List finallyJumps, int level, GraphPart parent, GraphPart part, GraphPart stopPart, List loops, HashMap localRegs, MethodBody body, List ignoredSwitches) { List ret = new ArrayList(); - if (level > 50) { - //System.err.println(methodPath+": Level>50 :"+part); - //new Exception().printStackTrace(); - //return ret; - } boolean debugMode = false; try { @@ -217,17 +222,42 @@ public class AVM2Graph extends Graph { } else if (sp0.leadsTo(sp1, loopContinues)) { reversed = true; } - - printGraph(methodPath, stack, scopeStack, allParts, parsedExceptions, finallyJumps, level + 1, parent, reversed ? sp0 : sp1, reversed ? sp1 : sp0, loops, localRegs, body, ignoredSwitches); - TreeItem second = stack.pop(); - TreeItem first = stack.pop(); - if (reversed) { - stack.push(new OrTreeItem(ins, first, second)); + GraphPart next = reversed ? sp0 : sp1; + TreeItem ti; + if ((ti = checkLoop(next, stopPart, loops)) != null) { + ret.add(ti); } else { - stack.push(new AndTreeItem(ins, first, second)); + printGraph(methodPath, stack, scopeStack, allParts, parsedExceptions, finallyJumps, level + 1, parent, next, reversed ? sp1 : sp0, loops, localRegs, body, ignoredSwitches); + TreeItem second = stack.pop(); + TreeItem first = stack.pop(); + if (!reversed) { + AndTreeItem a = new AndTreeItem(ins, first, second); + stack.push(a); + a.firstPart = part; + if (second instanceof AndTreeItem) { + a.firstPart = ((AndTreeItem) second).firstPart; + } + if (second instanceof OrTreeItem) { + a.firstPart = ((AndTreeItem) second).firstPart; + } + } else { + OrTreeItem o = new OrTreeItem(ins, first, second); + stack.push(o); + o.firstPart = part; + if (second instanceof OrTreeItem) { + o.firstPart = ((OrTreeItem) second).firstPart; + } + if (second instanceof OrTreeItem) { + o.firstPart = ((OrTreeItem) second).firstPart; + } + } + next = reversed ? sp1 : sp0; + if ((ti = checkLoop(next, stopPart, loops)) != null) { + ret.add(ti); + } else { + ret.addAll(printGraph(methodPath, stack, scopeStack, allParts, parsedExceptions, finallyJumps, level + 1, parent, next, stopPart, loops, localRegs, body, ignoredSwitches)); + } } - - ret.addAll(printGraph(methodPath, stack, scopeStack, allParts, parsedExceptions, finallyJumps, level + 1, parent, reversed ? sp1 : sp0, stopPart, loops, localRegs, body, ignoredSwitches)); return ret; } else if ((stack.size() >= 2) && (ins.definition instanceof IfTrueIns) && (stack.get(stack.size() - 1) == stack.get(stack.size() - 2))) { ret.addAll(output); @@ -240,16 +270,44 @@ public class AVM2Graph extends Graph { } else if (sp0.leadsTo(sp1, loopContinues)) { reversed = true; } - - printGraph(methodPath, stack, scopeStack, allParts, parsedExceptions, finallyJumps, level + 1, parent, reversed ? sp0 : sp1, reversed ? sp1 : sp0, loops, localRegs, body, ignoredSwitches); - TreeItem second = stack.pop(); - TreeItem first = stack.pop(); - if (reversed) { - stack.push(new AndTreeItem(ins, first, second)); + GraphPart next = reversed ? sp0 : sp1; + TreeItem ti; + if ((ti = checkLoop(next, stopPart, loops)) != null) { + ret.add(ti); } else { - stack.push(new OrTreeItem(ins, first, second)); + printGraph(methodPath, stack, scopeStack, allParts, parsedExceptions, finallyJumps, level + 1, parent, next, reversed ? sp1 : sp0, loops, localRegs, body, ignoredSwitches); + TreeItem second = stack.pop(); + TreeItem first = stack.pop(); + if (reversed) { + AndTreeItem a = new AndTreeItem(ins, first, second); + stack.push(a); + a.firstPart = part; + if (second instanceof AndTreeItem) { + a.firstPart = ((AndTreeItem) second).firstPart; + } + if (second instanceof OrTreeItem) { + a.firstPart = ((AndTreeItem) second).firstPart; + } + } else { + OrTreeItem o = new OrTreeItem(ins, first, second); + stack.push(o); + o.firstPart = part; + if (second instanceof OrTreeItem) { + o.firstPart = ((OrTreeItem) second).firstPart; + } + if (second instanceof OrTreeItem) { + o.firstPart = ((OrTreeItem) second).firstPart; + } + } + + next = reversed ? sp1 : sp0; + if ((ti = checkLoop(next, stopPart, loops)) != null) { + ret.add(ti); + } else { + ret.addAll(printGraph(methodPath, stack, scopeStack, allParts, parsedExceptions, finallyJumps, level + 1, parent, next, stopPart, loops, localRegs, body, ignoredSwitches)); + } } - ret.addAll(printGraph(methodPath, stack, scopeStack, allParts, parsedExceptions, finallyJumps, level + 1, parent, reversed ? sp1 : sp0, stopPart, loops, localRegs, body, ignoredSwitches)); + return ret; } else if ((((ins.definition instanceof IfStrictNeIns)) && ((part.nextParts.get(1).getHeight() == 2) && (code.code.get(part.nextParts.get(1).start).definition instanceof PushByteIns) && (code.code.get(part.nextParts.get(1).nextParts.get(0).end).definition instanceof LookupSwitchIns))) || (((ins.definition instanceof IfStrictEqIns)) && ((part.nextParts.get(0).getHeight() == 2) && (code.code.get(part.nextParts.get(0).start).definition instanceof PushByteIns) && (code.code.get(part.nextParts.get(0).nextParts.get(0).end).definition instanceof LookupSwitchIns)))) { @@ -568,8 +626,21 @@ public class AVM2Graph extends Graph { } boolean loop = false; boolean reversed = false; + boolean whileTrue = false; + Loop whileTrueLoop = null; if ((!part.nextParts.isEmpty()) && part.nextParts.get(0).leadsTo(part, loopContinues)) { - loop = true; + if ((part.nextParts.size() > 1) && part.nextParts.get(1).leadsTo(part, loopContinues)) { + if (output.isEmpty()) { + whileTrueLoop = new Loop(part, null); + loops.add(whileTrueLoop); + whileTrue = true; + } else { + loop = true;//doWhile + } + + } else { + loop = true; + } } else if ((part.nextParts.size() > 1) && part.nextParts.get(1).leadsTo(part, loopContinues)) { loop = true; reversed = true; @@ -592,90 +663,43 @@ public class AVM2Graph extends Graph { } } - if (part.nextParts.size() > 1) { + if ((part.nextParts.size() > 1) && (!doWhile)) { currentLoop.loopBreak = part.nextParts.get(reversed ? 0 : 1); } - int breakIp = -1; - if (currentLoop.loopBreak != null) { - breakIp = currentLoop.loopBreak.start; - } TreeItem expr = null; if ((code.code.get(part.end).definition instanceof JumpIns) || (!(code.code.get(part.end).definition instanceof IfTypeIns))) { expr = new BooleanTreeItem(null, true); } else { - if (stack.isEmpty()) { + if (!stack.isEmpty()) { + expr = stack.pop(); } - expr = stack.pop(); } + if (loop) { + if (expr instanceof AndTreeItem) { + currentLoop.loopContinue = ((AndTreeItem) expr).firstPart; + } + if (expr instanceof OrTreeItem) { + currentLoop.loopContinue = ((OrTreeItem) expr).firstPart; + } + } + if (doWhile) { - ret.add(new DoWhileTreeItem(null, breakIp, part.start, output, expr)); + //ret.add(new DoWhileTreeItem(null, currentLoop.id, part.start, output, expr)); } else { ret.addAll(output); } - + GraphPart loopBodyStart = null; GraphPart next = part.getNextPartPath(loopContinues); - if (expr instanceof LogicalOp) { + if (reversed && (expr instanceof LogicalOp)) { expr = ((LogicalOp) expr).invert(); } - if (loop && (!doWhile)) { - List loopBody = null; - List finalCommands = null; - GraphPart finalPart = null; - boolean isFor = false; - try { - loopBody = printGraph(methodPath, stack, scopeStack, allParts, parsedExceptions, finallyJumps, level + 1, part, part.nextParts.get(reversed ? 1 : 0), stopPart, loops, localRegs, body, ignoredSwitches); - } catch (ForException fex) { - loopBody = fex.output; - finalCommands = fex.finalOutput; - if (!finalCommands.isEmpty()) { - finalCommands.remove(finalCommands.size() - 1); //remove continue - } - finalPart = fex.continuePart; - isFor = true; - for (Object o : finalPart.forContinues) { - if (o instanceof ContinueTreeItem) { - ((ContinueTreeItem) o).loopPos = breakIp; - } - } + List retx = ret; + if ((!loop) || (doWhile && (part.nextParts.size() > 1))) { + if (doWhile) { + retx = output; + } - if (isFor) { - ret.add(new ForTreeItem(null, breakIp, finalPart.start, new ArrayList(), expr, finalCommands, loopBody)); - } else if ((expr instanceof HasNextTreeItem) && ((HasNextTreeItem) expr).collection.getNotCoerced().getThroughRegister() instanceof FilteredCheckTreeItem) { - TreeItem gti = ((HasNextTreeItem) expr).collection.getNotCoerced().getThroughRegister(); - boolean found = false; - if ((loopBody.size() == 3) || (loopBody.size() == 4)) { - TreeItem ft = loopBody.get(0); - if (ft instanceof WithTreeItem) { - ft = loopBody.get(1); - if (ft instanceof IfTreeItem) { - IfTreeItem ift = (IfTreeItem) ft; - if (ift.onTrue.size() > 0) { - ft = ift.onTrue.get(0); - if (ft instanceof SetPropertyTreeItem) { - SetPropertyTreeItem spt = (SetPropertyTreeItem) ft; - if (spt.object instanceof LocalRegTreeItem) { - int regIndex = ((LocalRegTreeItem) spt.object).regIndex; - HasNextTreeItem iti = (HasNextTreeItem) expr; - localRegs.put(regIndex, new FilterTreeItem(null, iti.collection.getThroughRegister(), ift.expression)); - } - } - } - } - } - } - } else if ((expr instanceof HasNextTreeItem) && (!loopBody.isEmpty()) && (loopBody.get(0) instanceof SetTypeTreeItem) && (((SetTypeTreeItem) loopBody.get(0)).getValue().getNotCoerced() instanceof NextValueTreeItem)) { - TreeItem obj = ((SetTypeTreeItem) loopBody.get(0)).getObject(); - loopBody.remove(0); - ret.add(new ForEachInTreeItem(null, breakIp, part.start, new InTreeItem(expr.instruction, obj, ((HasNextTreeItem) expr).collection), loopBody)); - } else if ((expr instanceof HasNextTreeItem) && (!loopBody.isEmpty()) && (loopBody.get(0) instanceof SetTypeTreeItem) && (((SetTypeTreeItem) loopBody.get(0)).getValue().getNotCoerced() instanceof NextNameTreeItem)) { - TreeItem obj = ((SetTypeTreeItem) loopBody.get(0)).getObject(); - loopBody.remove(0); - ret.add(new ForInTreeItem(null, breakIp, part.start, new InTreeItem(expr.instruction, obj, ((HasNextTreeItem) expr).collection), loopBody)); - } else { - ret.add(new WhileTreeItem(null, breakIp, part.start, expr, loopBody)); - } - } else if (!loop) { int stackSizeBefore = stack.size(); Stack trueStack = (Stack) stack.clone(); Stack falseStack = (Stack) stack.clone(); @@ -712,7 +736,14 @@ public class AVM2Graph extends Graph { if (onTrue.isEmpty() && onFalse.isEmpty() && (trueStack.size() > stackSizeBefore) && (falseStack.size() > stackSizeBefore)) { stack.push(new TernarOpTreeItem(null, expr, trueStack.pop(), falseStack.pop())); } else { - ret.add(new IfTreeItem(null, expr, onTrue, onFalse)); + List retw = retx; + if (whileTrue) { + retw = new ArrayList(); + retw.add(new IfTreeItem(null, expr, onTrue, onFalse)); + retx.add(new WhileTreeItem(null, whileTrueLoop.id, whileTrueLoop.loopContinue.start, new BooleanTreeItem(null, true), retw)); + } else { + retx.add(new IfTreeItem(null, expr, onTrue, onFalse)); + } //Same continues in onTrue and onFalse gets continue on parent level if ((!onTrue.isEmpty()) && (!onFalse.isEmpty())) { @@ -720,19 +751,125 @@ public class AVM2Graph extends Graph { if (onFalse.get(onFalse.size() - 1) instanceof ContinueTreeItem) { if (((ContinueTreeItem) onTrue.get(onTrue.size() - 1)).loopPos == ((ContinueTreeItem) onFalse.get(onFalse.size() - 1)).loopPos) { onTrue.remove(onTrue.size() - 1); - ret.add(onFalse.remove(onFalse.size() - 1)); + retw.add(onFalse.remove(onFalse.size() - 1)); } } } } + + if ((!onTrue.isEmpty()) && (!onFalse.isEmpty())) { + if (onTrue.get(onTrue.size() - 1) instanceof ReturnValueTreeItem || onTrue.get(onTrue.size() - 1) instanceof ReturnVoidTreeItem) { + if (onFalse.get(onFalse.size() - 1) instanceof ContinueTreeItem) { + retw.add(onFalse.remove(onFalse.size() - 1)); + } + } + } + + if ((!onTrue.isEmpty()) && (!onFalse.isEmpty())) { + if (onFalse.get(onFalse.size() - 1) instanceof ReturnValueTreeItem || onFalse.get(onFalse.size() - 1) instanceof ReturnVoidTreeItem) { + if (onTrue.get(onTrue.size() - 1) instanceof ContinueTreeItem) { + retw.add(onTrue.remove(onTrue.size() - 1)); + } + } + } + if (whileTrue) { + checkContinueAtTheEnd(retw, whileTrueLoop); + } + } + if (doWhile) { + loopBodyStart = next; } } - if (loop && (part.nextParts.size() > 1)) { + if (loop) { // && (!doWhile)) { + List loopBody = null; + List finalCommands = null; + GraphPart finalPart = null; + boolean isFor = false; + try { + loopBody = printGraph(methodPath, stack, scopeStack, allParts, parsedExceptions, finallyJumps, level + 1, part, loopBodyStart != null ? loopBodyStart : part.nextParts.get(reversed ? 1 : 0), stopPart, loops, localRegs, body, ignoredSwitches); + checkContinueAtTheEnd(loopBody, currentLoop); + } catch (ForException fex) { + loopBody = fex.output; + finalCommands = fex.finalOutput; + if (!finalCommands.isEmpty()) { + finalCommands.remove(finalCommands.size() - 1); //remove continue + } + finalPart = fex.continuePart; + isFor = true; + for (Object o : finalPart.forContinues) { + if (o instanceof ContinueTreeItem) { + ((ContinueTreeItem) o).loopPos = currentLoop.id; + } + } + } + if (isFor) { + ret.add(new ForTreeItem(null, currentLoop.id, finalPart.start, new ArrayList(), expr, finalCommands, loopBody)); + } else if ((expr instanceof HasNextTreeItem) && ((HasNextTreeItem) expr).collection.getNotCoerced().getThroughRegister() instanceof FilteredCheckTreeItem) { + TreeItem gti = ((HasNextTreeItem) expr).collection.getNotCoerced().getThroughRegister(); + boolean found = false; + if ((loopBody.size() == 3) || (loopBody.size() == 4)) { + TreeItem ft = loopBody.get(0); + if (ft instanceof WithTreeItem) { + ft = loopBody.get(1); + if (ft instanceof IfTreeItem) { + IfTreeItem ift = (IfTreeItem) ft; + if (ift.onTrue.size() > 0) { + ft = ift.onTrue.get(0); + if (ft instanceof SetPropertyTreeItem) { + SetPropertyTreeItem spt = (SetPropertyTreeItem) ft; + if (spt.object instanceof LocalRegTreeItem) { + int regIndex = ((LocalRegTreeItem) spt.object).regIndex; + HasNextTreeItem iti = (HasNextTreeItem) expr; + localRegs.put(regIndex, new FilterTreeItem(null, iti.collection.getThroughRegister(), ift.expression)); + } + } + } + } + } + } + } else if ((expr instanceof HasNextTreeItem) && (!loopBody.isEmpty()) && (loopBody.get(0) instanceof SetTypeTreeItem) && (((SetTypeTreeItem) loopBody.get(0)).getValue().getNotCoerced() instanceof NextValueTreeItem)) { + TreeItem obj = ((SetTypeTreeItem) loopBody.get(0)).getObject(); + loopBody.remove(0); + ret.add(new ForEachInTreeItem(null, currentLoop.id, part.start, new InTreeItem(expr.instruction, obj, ((HasNextTreeItem) expr).collection), loopBody)); + } else if ((expr instanceof HasNextTreeItem) && (!loopBody.isEmpty()) && (loopBody.get(0) instanceof SetTypeTreeItem) && (((SetTypeTreeItem) loopBody.get(0)).getValue().getNotCoerced() instanceof NextNameTreeItem)) { + TreeItem obj = ((SetTypeTreeItem) loopBody.get(0)).getObject(); + loopBody.remove(0); + ret.add(new ForInTreeItem(null, currentLoop.id, part.start, new InTreeItem(expr.instruction, obj, ((HasNextTreeItem) expr).collection), loopBody)); + } else { + if (doWhile) { + if (stack.isEmpty()) { + expr = new BooleanTreeItem(null, true); + } else { + expr = stack.pop(); + } + loopBody.addAll(0, output); + checkContinueAtTheEnd(loopBody, currentLoop); + + List addIf = new ArrayList(); + if ((!loopBody.isEmpty()) && (loopBody.get(loopBody.size() - 1) instanceof IfTreeItem)) { + IfTreeItem ift = (IfTreeItem) loopBody.get(loopBody.size() - 1); + if (ift.onFalse.isEmpty()) { + expr = ift.expression; + addIf = ift.onTrue; + loopBody.remove(loopBody.size() - 1); + } + } + ret.add(new DoWhileTreeItem(null, currentLoop.id, part.start, loopBody, expr)); + ret.addAll(addIf); + + } else { + ret.add(new WhileTreeItem(null, currentLoop.id, part.start, expr, loopBody)); + } + } + } + if ((!doWhile) && (!whileTrue) && loop && (part.nextParts.size() > 1)) { loops.remove(currentLoop); //remove loop so no break shows up //ret.addAll(printGraph(methodPath, stack, scopeStack, allParts, parsedExceptions, finallyJumps, level, part, part.nextParts.get(reversed ? 0 : 1), stopPart, loops, localRegs, body, ignoredSwitches)); next = part.nextParts.get(reversed ? 0 : 1); } - + if (doWhile) { + next = null; + } if (next != null) { boolean finallyJump = false; for (int f : finallyJumps) { @@ -817,7 +954,7 @@ public class AVM2Graph extends Graph { if ((p != stopPart) && (p.refs.size() > 1)) { ContinueTreeItem cti = new ContinueTreeItem(null, -1); //p.forContinues.add(cti); - ret.add(new CommentTreeItem(null, "Unknown jump")); + ret.add(new CommentTreeItem(null, "Unknown jump to part " + p)); ret.add(cti); } } @@ -865,11 +1002,13 @@ public class AVM2Graph extends Graph { SwitchTreeItem swt = new SwitchTreeItem(null, breakPos, switchedObject, caseValues, caseCommands, defaultCommands, valueMappings); ret.add(swt); - TreeItem lopNext = checkLoop(next, stopPart, loops); - if (lopNext != null) { - ret.add(lopNext); - } else { - ret.addAll(printGraph(methodPath, stack, scopeStack, allParts, parsedExceptions, finallyJumps, level + 1, part, next, stopPart, loops, localRegs, body, ignoredSwitches)); + if (next != null) { + TreeItem lopNext = checkLoop(next, stopPart, loops); + if (lopNext != null) { + ret.add(lopNext); + } else { + ret.addAll(printGraph(methodPath, stack, scopeStack, allParts, parsedExceptions, finallyJumps, level + 1, part, next, stopPart, loops, localRegs, body, ignoredSwitches)); + } } } diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/treemodel/BreakTreeItem.java b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/treemodel/BreakTreeItem.java index 431975f7b..9aeb88725 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/treemodel/BreakTreeItem.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/treemodel/BreakTreeItem.java @@ -23,14 +23,14 @@ import java.util.List; public class BreakTreeItem extends TreeItem { - public int loopPos; + public long loopPos; public boolean isKnown; - public BreakTreeItem(AVM2Instruction instruction, int loopPos) { + public BreakTreeItem(AVM2Instruction instruction, long loopPos) { this(instruction, loopPos, true); } - public BreakTreeItem(AVM2Instruction instruction, int loopPos, boolean isKnown) { + public BreakTreeItem(AVM2Instruction instruction, long loopPos, boolean isKnown) { super(instruction, NOPRECEDENCE); this.loopPos = loopPos; this.isKnown = isKnown; diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/treemodel/ContinueTreeItem.java b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/treemodel/ContinueTreeItem.java index fa2805500..d11415bf0 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/treemodel/ContinueTreeItem.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/treemodel/ContinueTreeItem.java @@ -23,14 +23,14 @@ import java.util.List; public class ContinueTreeItem extends TreeItem { - public int loopPos; + public long loopPos; public boolean isKnown; - public ContinueTreeItem(AVM2Instruction instruction, int loopPos) { + public ContinueTreeItem(AVM2Instruction instruction, long loopPos) { this(instruction, loopPos, true); } - public ContinueTreeItem(AVM2Instruction instruction, int loopPos, boolean isKnown) { + public ContinueTreeItem(AVM2Instruction instruction, long loopPos, boolean isKnown) { super(instruction, NOPRECEDENCE); this.loopPos = loopPos; this.isKnown = isKnown; diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/treemodel/clauses/DoWhileTreeItem.java b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/treemodel/clauses/DoWhileTreeItem.java index 2e20c22df..a9a579641 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/treemodel/clauses/DoWhileTreeItem.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/treemodel/clauses/DoWhileTreeItem.java @@ -34,27 +34,22 @@ public class DoWhileTreeItem extends LoopTreeItem implements Block { return false; } - public DoWhileTreeItem(AVM2Instruction instruction, int loopBreak, int loopContinue, List commands, TreeItem expression) { - super(instruction, loopBreak, loopContinue); + public DoWhileTreeItem(AVM2Instruction instruction, long loopId, int loopContinue, List commands, TreeItem expression) { + super(instruction, loopId, loopContinue); this.expression = expression; this.commands = commands; - if ((!commands.isEmpty()) && (commands.get(commands.size() - 1) instanceof ContinueTreeItem)) { - if (((ContinueTreeItem) commands.get(commands.size() - 1)).loopPos == loopBreak) { - commands.remove(commands.size() - 1); - } - } } @Override public String toString(ConstantPool constants, HashMap localRegNames, List fullyQualifiedNames) { String ret = ""; - ret += "loop" + loopBreak + ":\r\n"; + ret += "loop" + loopId + ":\r\n"; ret += hilight("do\r\n{") + "\r\n"; for (TreeItem ti : commands) { ret += ti.toStringSemicoloned(constants, localRegNames, fullyQualifiedNames) + "\r\n"; } ret += hilight("}\r\nwhile(") + expression.toString(constants, localRegNames, fullyQualifiedNames) + hilight(");") + "\r\n"; - ret += ":loop" + loopBreak; + ret += ":loop" + loopId; return ret; } diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/treemodel/clauses/ForEachInTreeItem.java b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/treemodel/clauses/ForEachInTreeItem.java index 311266e4d..3a068ec4f 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/treemodel/clauses/ForEachInTreeItem.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/treemodel/clauses/ForEachInTreeItem.java @@ -28,8 +28,8 @@ public class ForEachInTreeItem extends LoopTreeItem implements Block { public InTreeItem expression; public List commands; - public ForEachInTreeItem(AVM2Instruction instruction, int loopBreak, int loopContinue, InTreeItem expression, List commands) { - super(instruction, loopBreak, loopContinue); + public ForEachInTreeItem(AVM2Instruction instruction, long loopId, int loopContinue, InTreeItem expression, List commands) { + super(instruction, loopId, loopContinue); if (!commands.isEmpty()) { TreeItem firstAssign = commands.get(0); if (firstAssign instanceof SetTypeTreeItem) { @@ -47,11 +47,6 @@ public class ForEachInTreeItem extends LoopTreeItem implements Block { } this.expression = expression; this.commands = commands; - if ((!commands.isEmpty()) && (commands.get(commands.size() - 1) instanceof ContinueTreeItem)) { - if (((ContinueTreeItem) commands.get(commands.size() - 1)).loopPos == loopBreak) { - commands.remove(commands.size() - 1); - } - } } @Override @@ -62,13 +57,13 @@ public class ForEachInTreeItem extends LoopTreeItem implements Block { @Override public String toString(ConstantPool constants, HashMap localRegNames, List fullyQualifiedNames) { String ret = ""; - ret += "loop" + loopBreak + ":\r\n"; + ret += "loop" + loopId + ":\r\n"; ret += hilight("for each (") + expression.toString(constants, localRegNames, fullyQualifiedNames) + ")\r\n{\r\n"; for (TreeItem ti : commands) { ret += ti.toStringSemicoloned(constants, localRegNames, fullyQualifiedNames) + "\r\n"; } ret += hilight("}") + "\r\n"; - ret += ":loop" + loopBreak; + ret += ":loop" + loopId; return ret; } diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/treemodel/clauses/ForInTreeItem.java b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/treemodel/clauses/ForInTreeItem.java index 904046057..eca78ce01 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/treemodel/clauses/ForInTreeItem.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/treemodel/clauses/ForInTreeItem.java @@ -28,8 +28,8 @@ public class ForInTreeItem extends LoopTreeItem implements Block { public InTreeItem expression; public List commands; - public ForInTreeItem(AVM2Instruction instruction, int loopBreak, int loopContinue, InTreeItem expression, List commands) { - super(instruction, loopBreak, loopContinue); + public ForInTreeItem(AVM2Instruction instruction, long loopId, int loopContinue, InTreeItem expression, List commands) { + super(instruction, loopId, loopContinue); if (!commands.isEmpty()) { TreeItem firstAssign = commands.get(0); if (firstAssign instanceof SetTypeTreeItem) { @@ -47,12 +47,6 @@ public class ForInTreeItem extends LoopTreeItem implements Block { } this.expression = expression; this.commands = commands; - - if ((!commands.isEmpty()) && (commands.get(commands.size() - 1) instanceof ContinueTreeItem)) { - if (((ContinueTreeItem) commands.get(commands.size() - 1)).loopPos == loopBreak) { - commands.remove(commands.size() - 1); - } - } } @Override @@ -63,13 +57,13 @@ public class ForInTreeItem extends LoopTreeItem implements Block { @Override public String toString(ConstantPool constants, HashMap localRegNames, List fullyQualifiedNames) { String ret = ""; - ret += "loop" + loopBreak + ":\r\n"; + ret += "loop" + loopId + ":\r\n"; ret += hilight("for (") + expression.toString(constants, localRegNames, fullyQualifiedNames) + hilight(")") + "\r\n{\r\n"; for (TreeItem ti : commands) { ret += ti.toStringSemicoloned(constants, localRegNames, fullyQualifiedNames) + "\r\n"; } ret += hilight("}") + "\r\n"; - ret += ":loop" + loopBreak; + ret += ":loop" + loopId; return ret; } diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/treemodel/clauses/ForTreeItem.java b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/treemodel/clauses/ForTreeItem.java index f15546da0..442553c46 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/treemodel/clauses/ForTreeItem.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/treemodel/clauses/ForTreeItem.java @@ -31,18 +31,12 @@ public class ForTreeItem extends LoopTreeItem implements Block { public List finalCommands; public List commands; - public ForTreeItem(AVM2Instruction instruction, int loopBreak, int loopContinue, List firstCommands, TreeItem expression, List finalCommands, List commands) { + public ForTreeItem(AVM2Instruction instruction, long loopBreak, int loopContinue, List firstCommands, TreeItem expression, List finalCommands, List commands) { super(instruction, loopBreak, loopContinue); this.firstCommands = firstCommands; this.expression = expression; this.finalCommands = finalCommands; this.commands = commands; - - if ((!commands.isEmpty()) && (commands.get(commands.size() - 1) instanceof ContinueTreeItem)) { - if (((ContinueTreeItem) commands.get(commands.size() - 1)).loopPos == loopBreak) { - commands.remove(commands.size() - 1); - } - } } private String stripSemicolon(String s) { @@ -55,7 +49,7 @@ public class ForTreeItem extends LoopTreeItem implements Block { @Override public String toString(ConstantPool constants, HashMap localRegNames, List fullyQualifiedNames) { String ret = ""; - ret += "loop" + loopBreak + ":\r\n"; + ret += "loop" + loopId + ":\r\n"; ret += hilight("for("); for (int i = 0; i < firstCommands.size(); i++) { if (i > 0) { @@ -77,7 +71,7 @@ public class ForTreeItem extends LoopTreeItem implements Block { ret += ti.toStringSemicoloned(constants, localRegNames, fullyQualifiedNames) + "\r\n"; } ret += hilight("}") + "\r\n"; - ret += ":loop" + loopBreak; + ret += ":loop" + loopId; return ret; } diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/treemodel/clauses/LoopTreeItem.java b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/treemodel/clauses/LoopTreeItem.java index 76b8b7f54..94bb93f03 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/treemodel/clauses/LoopTreeItem.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/treemodel/clauses/LoopTreeItem.java @@ -21,12 +21,12 @@ import com.jpexs.decompiler.flash.abc.avm2.treemodel.TreeItem; public abstract class LoopTreeItem extends TreeItem { - public int loopBreak; + public long loopId; public int loopContinue; - public LoopTreeItem(AVM2Instruction instruction, int loopBreak, int loopContinue) { + public LoopTreeItem(AVM2Instruction instruction, long loopId, int loopContinue) { super(instruction, NOPRECEDENCE); - this.loopBreak = loopBreak; + this.loopId = loopId; this.loopContinue = loopContinue; } diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/treemodel/clauses/SwitchTreeItem.java b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/treemodel/clauses/SwitchTreeItem.java index e08808a7c..01a67042b 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/treemodel/clauses/SwitchTreeItem.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/treemodel/clauses/SwitchTreeItem.java @@ -46,7 +46,7 @@ public class SwitchTreeItem extends LoopTreeItem implements Block { @Override public String toString(ConstantPool constants, HashMap localRegNames, List fullyQualifiedNames) { String ret = ""; - ret += "loop" + loopBreak + ":\r\n"; + ret += "loop" + loopId + ":\r\n"; ret += hilight("switch(") + switchedObject.toString(constants, localRegNames, fullyQualifiedNames) + hilight(")") + "\r\n{\r\n"; for (int i = 0; i < caseCommands.size(); i++) { for (int k = 0; k < valuesMapping.size(); k++) { @@ -61,7 +61,7 @@ public class SwitchTreeItem extends LoopTreeItem implements Block { ret += AVM2Code.IDENTCLOSE + "\r\n"; } if (defaultCommands.size() > 0) { - if (!((defaultCommands.size() == 1) && (defaultCommands.get(0) instanceof BreakTreeItem) && (((BreakTreeItem) defaultCommands.get(0)).loopPos == loopBreak))) { + if (!((defaultCommands.size() == 1) && (defaultCommands.get(0) instanceof BreakTreeItem) && (((BreakTreeItem) defaultCommands.get(0)).loopPos == loopId))) { ret += hilight("default") + ":\r\n"; ret += AVM2Code.IDENTOPEN + "\r\n"; for (int j = 0; j < defaultCommands.size(); j++) { @@ -72,7 +72,7 @@ public class SwitchTreeItem extends LoopTreeItem implements Block { } ret += hilight("}") + "\r\n"; - ret += ":loop" + loopBreak; + ret += ":loop" + loopId; return ret; } diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/treemodel/clauses/WhileTreeItem.java b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/treemodel/clauses/WhileTreeItem.java index f5c73d890..ea9e7ca51 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/treemodel/clauses/WhileTreeItem.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/treemodel/clauses/WhileTreeItem.java @@ -29,28 +29,22 @@ public class WhileTreeItem extends LoopTreeItem implements Block { public TreeItem expression; public List commands; - public WhileTreeItem(AVM2Instruction instruction, int loopBreak, int loopContinue, TreeItem expression, List commands) { - super(instruction, loopBreak, loopContinue); + public WhileTreeItem(AVM2Instruction instruction, long loopId, int loopContinue, TreeItem expression, List commands) { + super(instruction, loopId, loopContinue); this.expression = expression; this.commands = commands; - - if ((!commands.isEmpty()) && (commands.get(commands.size() - 1) instanceof ContinueTreeItem)) { - if (((ContinueTreeItem) commands.get(commands.size() - 1)).loopPos == loopBreak) { - commands.remove(commands.size() - 1); - } - } } @Override public String toString(ConstantPool constants, HashMap localRegNames, List fullyQualifiedNames) { String ret = ""; - ret += "loop" + loopBreak + ":\r\n"; + ret += "loop" + loopId + ":\r\n"; ret += hilight("while(") + expression.toString(constants, localRegNames, fullyQualifiedNames) + hilight(")") + "\r\n{\r\n"; for (TreeItem ti : commands) { ret += ti.toStringSemicoloned(constants, localRegNames, fullyQualifiedNames) + "\r\n"; } ret += hilight("}") + "\r\n"; - ret += ":loop" + loopBreak; + ret += ":loop" + loopId; return ret; } diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/treemodel/operations/AndTreeItem.java b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/treemodel/operations/AndTreeItem.java index e3b2a49fd..6c2117bc5 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/treemodel/operations/AndTreeItem.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/treemodel/operations/AndTreeItem.java @@ -18,9 +18,12 @@ package com.jpexs.decompiler.flash.abc.avm2.treemodel.operations; import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; import com.jpexs.decompiler.flash.abc.avm2.treemodel.TreeItem; +import com.jpexs.decompiler.flash.graph.GraphPart; public class AndTreeItem extends BinaryOpTreeItem { + public GraphPart firstPart; + public AndTreeItem(AVM2Instruction instruction, TreeItem leftSide, TreeItem rightSide) { super(instruction, PRECEDENCE_LOGICALAND, leftSide, rightSide, "&&"); } diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/treemodel/operations/OrTreeItem.java b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/treemodel/operations/OrTreeItem.java index 76cb3a55b..e32b6069c 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/treemodel/operations/OrTreeItem.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/treemodel/operations/OrTreeItem.java @@ -18,9 +18,12 @@ package com.jpexs.decompiler.flash.abc.avm2.treemodel.operations; import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; import com.jpexs.decompiler.flash.abc.avm2.treemodel.TreeItem; +import com.jpexs.decompiler.flash.graph.GraphPart; public class OrTreeItem extends BinaryOpTreeItem { + public GraphPart firstPart; + public OrTreeItem(AVM2Instruction instruction, TreeItem leftSide, TreeItem rightSide) { super(instruction, PRECEDENCE_LOGICALOR, leftSide, rightSide, "||"); } diff --git a/trunk/src/com/jpexs/decompiler/flash/graph/GraphPart.java b/trunk/src/com/jpexs/decompiler/flash/graph/GraphPart.java index 58d7496f4..b09f518f7 100644 --- a/trunk/src/com/jpexs/decompiler/flash/graph/GraphPart.java +++ b/trunk/src/com/jpexs/decompiler/flash/graph/GraphPart.java @@ -67,7 +67,7 @@ public class GraphPart { } private GraphPart getNextPartPath(GraphPart original, String path, List visited) { - if (visited.contains(this)) { + if (visited.contains(this) && (this != original)) { return null; } visited.add(this); diff --git a/trunk/src/com/jpexs/decompiler/flash/graph/Loop.java b/trunk/src/com/jpexs/decompiler/flash/graph/Loop.java index 1c3603d66..daa9014bc 100644 --- a/trunk/src/com/jpexs/decompiler/flash/graph/Loop.java +++ b/trunk/src/com/jpexs/decompiler/flash/graph/Loop.java @@ -24,9 +24,13 @@ public class Loop { public GraphPart loopContinue; public GraphPart loopBreak; + public long id; + static long maxLoopId = 0; public Loop(GraphPart loopContinue, GraphPart loopBreak) { this.loopContinue = loopContinue; this.loopBreak = loopBreak; + id = maxLoopId; + maxLoopId++; } } diff --git a/trunk/src/com/jpexs/decompiler/flash/tags/DefineBitsLossless2Tag.java b/trunk/src/com/jpexs/decompiler/flash/tags/DefineBitsLossless2Tag.java index 632472014..05814834d 100644 --- a/trunk/src/com/jpexs/decompiler/flash/tags/DefineBitsLossless2Tag.java +++ b/trunk/src/com/jpexs/decompiler/flash/tags/DefineBitsLossless2Tag.java @@ -134,7 +134,7 @@ public class DefineBitsLossless2Tag extends CharacterTag implements AloneTag { for (int y = 0; y < bitmapHeight; y++) { for (int x = 0; x < bitmapWidth; x++) { if ((bitmapFormat == DefineBitsLossless2Tag.FORMAT_8BIT_COLORMAPPED)) { - RGBA color = colorMapData.colorTableRGB[colorMapData.colorMapPixelData[pos32aligned]&0xff]; + RGBA color = colorMapData.colorTableRGB[colorMapData.colorMapPixelData[pos32aligned] & 0xff]; g.setColor(new Color(color.red, color.green, color.blue, color.alpha)); } if ((bitmapFormat == DefineBitsLossless2Tag.FORMAT_15BIT_RGB) || (bitmapFormat == DefineBitsLossless2Tag.FORMAT_24BIT_RGB)) { diff --git a/trunk/src/com/jpexs/decompiler/flash/tags/DefineBitsLosslessTag.java b/trunk/src/com/jpexs/decompiler/flash/tags/DefineBitsLosslessTag.java index 03926709b..53b7ab781 100644 --- a/trunk/src/com/jpexs/decompiler/flash/tags/DefineBitsLosslessTag.java +++ b/trunk/src/com/jpexs/decompiler/flash/tags/DefineBitsLosslessTag.java @@ -62,8 +62,8 @@ public class DefineBitsLosslessTag extends CharacterTag implements AloneTag { int pos = 0; for (int y = 0; y < bitmapHeight; y++) { for (int x = 0; x < bitmapWidth; x++) { - if (bitmapFormat == DefineBitsLosslessTag.FORMAT_8BIT_COLORMAPPED) { - RGB color = colorMapData.colorTableRGB[colorMapData.colorMapPixelData[pos32aligned]&0xff]; + if (bitmapFormat == DefineBitsLosslessTag.FORMAT_8BIT_COLORMAPPED) { + RGB color = colorMapData.colorTableRGB[colorMapData.colorMapPixelData[pos32aligned] & 0xff]; g.setColor(new Color(color.red, color.green, color.blue)); } if (bitmapFormat == DefineBitsLosslessTag.FORMAT_15BIT_RGB) {