diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java index 9fc648d7b..9d6942d0e 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java @@ -1034,6 +1034,14 @@ public class AVM2Code implements Cloneable { return bos.toByteArray(); } + public void markOffsets() { + long offset = 0; + for (int i = 0; i < code.size(); i++) { + code.get(i).offset = offset; + offset += code.get(i).getBytesLength(); + } + } + @Override public String toString() { StringBuilder s = new StringBuilder(); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2ConstantPool.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2ConstantPool.java index 9d8b74c0e..79ca4d1dc 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2ConstantPool.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2ConstantPool.java @@ -122,6 +122,7 @@ public class AVM2ConstantPool implements Cloneable { public synchronized int addInt(long value) { ensureDefault(constant_int); + value = (int) value; constant_int.add(value); return constant_int.size() - 1; } @@ -150,6 +151,7 @@ public class AVM2ConstantPool implements Cloneable { public synchronized int addUInt(long value) { ensureDefault(constant_uint); + value &= 0xffffffffl; constant_uint.add(value); return constant_uint.size() - 1; } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/stack/PushByteIns.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/stack/PushByteIns.java index ea564c20c..9c5ad51f0 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/stack/PushByteIns.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/stack/PushByteIns.java @@ -36,13 +36,13 @@ public class PushByteIns extends InstructionDefinition implements PushIntegerTyp @Override public boolean execute(LocalDataArea lda, AVM2ConstantPool constants, AVM2Instruction ins) { - lda.operandStack.push(ins.getParam(constants, 0)); + lda.operandStack.push((long) (byte) ins.operands[0]); return true; } @Override public void translate(AVM2LocalData localData, TranslateStack stack, AVM2Instruction ins, List output, String path) { - stack.push(new IntegerValueAVM2Item(ins, localData.lineStartInstruction, (long) ins.operands[0])); + stack.push(new IntegerValueAVM2Item(ins, localData.lineStartInstruction, (long) (byte) ins.operands[0])); } @Override diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/fastactionlist/FastActionList.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/fastactionlist/FastActionList.java index 734f1c128..4f0b3aacd 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/fastactionlist/FastActionList.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/fastactionlist/FastActionList.java @@ -57,12 +57,12 @@ public class FastActionList implements Collection { getJumps(actions, actionItemMap); } - final ActionItem insertItemAfter(ActionItem item, Action action) { + public final ActionItem insertItemAfter(ActionItem item, Action action) { ActionItem newItem = new ActionItem(action); return insertItemAfter(item, newItem); } - final ActionItem insertItemBefore(ActionItem item, ActionItem newItem) { + public final ActionItem insertItemBefore(ActionItem item, ActionItem newItem) { insertItemAfter(item.prev, newItem); if (item == firstItem) { firstItem = newItem; @@ -71,7 +71,7 @@ public class FastActionList implements Collection { return newItem; } - final ActionItem insertItemAfter(ActionItem item, ActionItem newItem) { + public final ActionItem insertItemAfter(ActionItem item, ActionItem newItem) { if (item == null && firstItem == null) { firstItem = newItem; newItem.next = newItem; @@ -95,7 +95,7 @@ public class FastActionList implements Collection { return newItem; } - ActionItem removeItem(ActionItem item) { + public ActionItem removeItem(ActionItem item) { ActionItem next = null; if (item == firstItem) { if (item.next == item) { @@ -135,6 +135,19 @@ public class FastActionList implements Collection { return next; } + public void removeItem(int index, int count) { + FastActionListIterator iterator = new FastActionListIterator(this, index); + for (int i = 0; i < count; i++) { + iterator.next(); + iterator.remove(); + } + } + + public ActionItem get(int index) { + FastActionListIterator iterator = new FastActionListIterator(this, index); + return iterator.next(); + } + public void replaceJumpTargets(ActionItem target, ActionItem newTarget) { if (target.jumpsHere != null) { for (ActionItem item : new ArrayList<>(target.jumpsHere)) { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/fastactionlist/FastActionListIterator.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/fastactionlist/FastActionListIterator.java index 8fac86e05..f8f05aaae 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/fastactionlist/FastActionListIterator.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/fastactionlist/FastActionListIterator.java @@ -23,7 +23,7 @@ import java.util.Iterator; * * @author JPEXS */ -public class FastActionListIterator implements Iterator { +public final class FastActionListIterator implements Iterator { private ActionItem item; @@ -36,6 +36,18 @@ public class FastActionListIterator implements Iterator { this.list = list; } + FastActionListIterator(FastActionList list, int index) { + item = list.first(); + this.list = list; + for (int i = 0; i < index; i++) { + if (!hasNext()) { + throw new Error("Invalid index"); + } + + next(); + } + } + @Override public boolean hasNext() { return item != null && (!started || item != list.first()); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/ecma/EcmaScript.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/ecma/EcmaScript.java index 8482ecb5a..d8c8b48af 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/ecma/EcmaScript.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/ecma/EcmaScript.java @@ -48,8 +48,13 @@ public class EcmaScript { return (double) (int) (Integer) o; } if (o instanceof String) { + String str = (String) o; + if (str.isEmpty()) { + return 0.0; + } + try { - return Double.parseDouble((String) o); + return Double.parseDouble(str); } catch (NumberFormatException nfe) { return Double.NaN; } diff --git a/test/com/jpexs/decompiler/flash/gui/AS2ExecuteTask.java b/test/com/jpexs/decompiler/flash/gui/AS2ExecuteTask.java new file mode 100644 index 000000000..c0cff956d --- /dev/null +++ b/test/com/jpexs/decompiler/flash/gui/AS2ExecuteTask.java @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2010-2015 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 . + */ +package com.jpexs.decompiler.flash.gui; + +import com.jpexs.decompiler.flash.action.Action; +import java.util.List; + +/** + * + * @author JPEXS + */ +public class AS2ExecuteTask { + + public String description; + + public List actions; + + public String flashResult; + + public String ffdecTranslateResult; + + public String ffdecResult; +} diff --git a/test/com/jpexs/decompiler/flash/gui/AdobeFlashExecutor.java b/test/com/jpexs/decompiler/flash/gui/AdobeFlashExecutor.java index a0543e673..ae47514c0 100644 --- a/test/com/jpexs/decompiler/flash/gui/AdobeFlashExecutor.java +++ b/test/com/jpexs/decompiler/flash/gui/AdobeFlashExecutor.java @@ -28,7 +28,14 @@ import com.jpexs.decompiler.flash.abc.types.Namespace; import com.jpexs.decompiler.flash.abc.types.traits.TraitMethodGetterSetter; import com.jpexs.decompiler.flash.action.Action; import com.jpexs.decompiler.flash.action.ActionList; +import com.jpexs.decompiler.flash.action.fastactionlist.ActionItem; +import com.jpexs.decompiler.flash.action.fastactionlist.FastActionList; +import com.jpexs.decompiler.flash.action.swf4.ActionPush; +import com.jpexs.decompiler.flash.action.swf5.ActionCallFunction; +import com.jpexs.decompiler.flash.action.swf5.ActionDefineFunction; +import com.jpexs.decompiler.flash.action.swf5.ActionReturn; import com.jpexs.decompiler.flash.tags.DoABC2Tag; +import com.jpexs.decompiler.flash.tags.DoActionTag; import com.jpexs.decompiler.flash.tags.Tag; import com.jpexs.decompiler.flash.tags.base.ASMSource; import com.jpexs.javactivex.ActiveX; @@ -133,6 +140,73 @@ public class AdobeFlashExecutor { return null; } + public void executeActionLists(List tasks) { + try { + File f2 = new File("run_test_" + new Date().getTime() + "_" + id.getAndIncrement() + ".swf"); + f2.deleteOnExit(); + + SWF swf; + try (InputStream is = new BufferedInputStream(new FileInputStream(runFileAs2))) { + swf = new SWF(is, false); + } + + Map asms = swf.getASMs(true); + ASMSource asm = asms.get("\\frame_1\\DoAction"); + int asmIndex = swf.tags.indexOf(asm); + + ActionList actionsList = asm.getActions(); + FastActionList actions = new FastActionList(actionsList); + actions.removeItem(2, 4); + + int i = 0; + ActionItem item = actions.get(1); + for (AS2ExecuteTask task : tasks) { + DoActionTag doaTag = new DoActionTag(swf); + List actions2 = new ArrayList<>(); + int codeSize = 1; // 1 == size of return action + for (Action actionsToExecute : task.actions) { + codeSize += actionsToExecute.getBytesLength(); + } + + actions2.add(new ActionDefineFunction("testRun" + i, new ArrayList<>(), codeSize, swf.version)); + actions2.addAll(task.actions); + actions2.add(new ActionReturn()); + + doaTag.setActions(actions2); + swf.tags.add(asmIndex, doaTag); + + i++; + } + + item = actions.insertItemAfter(item, new ActionPush(new Object[]{tasks.size(), 1, "runTests"})); + actions.insertItemAfter(item, new ActionCallFunction()); + asm.setActions(actions.toActionList()); + asm.setModified(); + try (OutputStream fos = new BufferedOutputStream(new FileOutputStream(f2))) { + swf.saveTo(fos); + } + + flash.setMovie(f2.getAbsolutePath()); + + synchronized (lockObj) { + lockObj.wait(); + } + + //String str = flash.GetVariable("myText.text"); + f2.delete(); + + String flashResult = resultRef.getVal(); + String[] lines = flashResult.split("(\r\n|\r|\n)"); + if (lines.length == tasks.size()) { + for (int j = 0; j < tasks.size(); j++) { + tasks.get(j).flashResult = lines[j]; + } + } + } catch (IOException | InterruptedException ex) { + Logger.getLogger(AdobeFlashExecutor.class.getName()).log(Level.SEVERE, null, ex); + } + } + public void loadTestSwf() throws IOException, InterruptedException { SWF swf = new SWF(new BufferedInputStream(new FileInputStream(runFileAs3)), false); swf.version = SWF.MAX_VERSION; @@ -163,7 +237,6 @@ public class AdobeFlashExecutor { body.max_regs = 10; body.setCode(code); - body.markOffsets(); abcTag.setModified(true); @@ -247,8 +320,8 @@ public class AdobeFlashExecutor { } code.add(new AVM2Instruction(0, AVM2Instructions.ReturnValue, null)); + ccode.markOffsets(); body.setCode(ccode); - body.markOffsets(); abcTag.setModified(true); @@ -292,7 +365,6 @@ public class AdobeFlashExecutor { methodBody.max_scope_depth = 10; methodBody.setCode(code); - methodBody.markOffsets(); return methodTrait.name_index; }