diff --git a/trunk/src/com/jpexs/decompiler/flash/Main.java b/trunk/src/com/jpexs/decompiler/flash/Main.java index 60dd4cede..47674ff57 100644 --- a/trunk/src/com/jpexs/decompiler/flash/Main.java +++ b/trunk/src/com/jpexs/decompiler/flash/Main.java @@ -411,8 +411,8 @@ public class Main { System.out.println(" ...opens SWF file with the decompiler GUI"); System.out.println(" 3) -proxy (-PXXX)"); System.out.println(" ...auto start proxy in the tray. Optional parameter -P specifies port for proxy. Defaults to 55555. "); - System.out.println(" 4) -export (as|pcode|image|shape|movie|sound) outdirectory infile [-selectas3class class1 class2 ...]"); - System.out.println(" ...export infile sources to outdirectory as AsctionScript code (\"as\" argument) or as PCode (\"pcode\" argument), images, shapes or movies"); + System.out.println(" 4) -export (as|pcode|image|shape|movie|sound|binaryData) outdirectory infile [-selectas3class class1 class2 ...]"); + System.out.println(" ...export infile sources to outdirectory as AsctionScript code (\"as\" argument) or as PCode (\"pcode\" argument), images, shapes, movies or binaryData"); System.out.println(" When \"as\" or \"pcode\" type specified, optional \"-selectas3class\" parameter can be passed to export only selected classes (ActionScript 3 only)"); System.out.println(" 5) -dumpSWF infile"); System.out.println(" ...dumps list of SWF tags to console"); @@ -422,15 +422,15 @@ public class Main { System.out.println(" ...Decompress infile and save it to outfile"); System.out.println(); System.out.println("Examples:"); - System.out.println("java -jar FFDec.jar myfile.swf"); - System.out.println("java -jar FFDec.jar -proxy"); - System.out.println("java -jar FFDec.jar -proxy -P1234"); - System.out.println("java -jar FFDec.jar -export as \"C:\\decompiled\\\" myfile.swf"); - System.out.println("java -jar FFDec.jar -export as \"C:\\decompiled\\\" myfile.swf -selectas3class com.example.MyClass com.example.SecondClass"); - System.out.println("java -jar FFDec.jar -export pcode \"C:\\decompiled\\\" myfile.swf"); - System.out.println("java -jar FFDec.jar -dumpSWF myfile.swf"); - System.out.println("java -jar FFDec.jar -compress myfile.swf myfiledec.swf"); - System.out.println("java -jar FFDec.jar -decompress myfiledec.swf myfile.swf"); + System.out.println("java -jar ffdec.jar myfile.swf"); + System.out.println("java -jar ffdec.jar -proxy"); + System.out.println("java -jar ffdec.jar -proxy -P1234"); + System.out.println("java -jar ffdec.jar -export as \"C:\\decompiled\\\" myfile.swf"); + System.out.println("java -jar ffdec.jar -export as \"C:\\decompiled\\\" myfile.swf -selectas3class com.example.MyClass com.example.SecondClass"); + System.out.println("java -jar ffdec.jar -export pcode \"C:\\decompiled\\\" myfile.swf"); + System.out.println("java -jar ffdec.jar -dumpSWF myfile.swf"); + System.out.println("java -jar ffdec.jar -compress myfile.swf myfiledec.swf"); + System.out.println("java -jar ffdec.jar -decompress myfiledec.swf myfile.swf"); } private static void copyFile(String from, String to) throws IOException { @@ -492,8 +492,10 @@ public class Main { if (!exportFormat.toLowerCase().equals("shape")) { if (!exportFormat.toLowerCase().equals("movie")) { if (!exportFormat.toLowerCase().equals("sound")) { - System.err.println("Invalid export format:" + exportFormat); - badArguments(); + if (!exportFormat.toLowerCase().equals("binaryData")) { + System.err.println("Invalid export format:" + exportFormat); + badArguments(); + } } } } @@ -540,6 +542,9 @@ public class Main { } else if (exportFormat.equals("sound")) { exfile.exportSounds(outDir.getAbsolutePath(), true); exportOK = true; + } else if (exportFormat.equals("binaryData")) { + exfile.exportBinaryData(outDir.getAbsolutePath()); + exportOK = true; } else { exportOK = false; } diff --git a/trunk/src/com/jpexs/decompiler/flash/SWF.java b/trunk/src/com/jpexs/decompiler/flash/SWF.java index ea3ade984..8960a708e 100644 --- a/trunk/src/com/jpexs/decompiler/flash/SWF.java +++ b/trunk/src/com/jpexs/decompiler/flash/SWF.java @@ -51,6 +51,7 @@ import com.jpexs.decompiler.flash.gui.FrameNode; import com.jpexs.decompiler.flash.gui.TagNode; import com.jpexs.decompiler.flash.helpers.Helper; import com.jpexs.decompiler.flash.tags.ABCContainerTag; +import com.jpexs.decompiler.flash.tags.DefineBinaryDataTag; import com.jpexs.decompiler.flash.tags.DefineBitsJPEG2Tag; import com.jpexs.decompiler.flash.tags.DefineBitsJPEG3Tag; import com.jpexs.decompiler.flash.tags.DefineBitsJPEG4Tag; @@ -68,6 +69,7 @@ import com.jpexs.decompiler.flash.tags.JPEGTablesTag; import com.jpexs.decompiler.flash.tags.ShowFrameTag; import com.jpexs.decompiler.flash.tags.SoundStreamBlockTag; import com.jpexs.decompiler.flash.tags.SoundStreamHeadTypeTag; +import com.jpexs.decompiler.flash.tags.SymbolClassTag; import com.jpexs.decompiler.flash.tags.Tag; import com.jpexs.decompiler.flash.tags.VideoFrameTag; import com.jpexs.decompiler.flash.tags.base.ASMSource; @@ -286,6 +288,29 @@ public class SWF { frameRate = sis.readUI8(); frameCount = sis.readUI16(); tags = sis.readTagList(0); + assignClassesToSymbols(); + } + + public void assignClassesToSymbols() { + HashMap classes = new HashMap(); + for (Tag t : tags) { + if (t instanceof SymbolClassTag) { + SymbolClassTag sct = (SymbolClassTag) t; + for (int i = 0; i < sct.tagIDs.length; i++) { + if ((!classes.containsKey(sct.tagIDs[i])) && (!classes.containsValue(sct.classNames[i]))) { + classes.put(sct.tagIDs[i], sct.classNames[i]); + } + } + } + } + for (Tag t : tags) { + if (t instanceof CharacterTag) { + CharacterTag ct = (CharacterTag) t; + if (classes.containsKey(ct.getCharacterID())) { + ct.setClassName(classes.get(ct.getCharacterID())); + } + } + } } /** @@ -774,6 +799,36 @@ public class SWF { } } + public static void exportBinaryData(String outdir, List tags) throws IOException { + if (tags.isEmpty()) { + return; + } + if (!(new File(outdir)).exists()) { + (new File(outdir)).mkdirs(); + } + for (Tag t : tags) { + if (t instanceof DefineBinaryDataTag) { + int characterID = 0; + if (t instanceof CharacterTag) { + characterID = ((CharacterTag) t).getCharacterID(); + } + FileOutputStream fos = null; + try { + fos = new FileOutputStream(outdir + File.separator + characterID + ".bin"); + fos.write(((DefineBinaryDataTag) t).binaryData); + } finally { + if (fos != null) { + try { + fos.close(); + } catch (Exception ex) { + //ignore + } + } + } + } + } + } + public static void exportImages(String outdir, List tags, JPEGTablesTag jtt) throws IOException { if (tags.isEmpty()) { return; @@ -857,6 +912,10 @@ public class SWF { public void exportShapes(String outdir) throws IOException { exportShapes(outdir, tags); } + + public void exportBinaryData(String outdir) throws IOException { + exportBinaryData(outdir, tags); + } public static final String[] reservedWords = { "as", "break", "case", "catch", "class", "const", "continue", "default", "delete", "do", "each", "else", "extends", "false", "finally", "for", "function", "get", "if", "implements", "import", "in", "instanceof", diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/ABC.java b/trunk/src/com/jpexs/decompiler/flash/abc/ABC.java index f3cd9d909..a84fc1d03 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/ABC.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/ABC.java @@ -872,6 +872,7 @@ public class ABC { } return -1; } + public int findScriptByPath(String name) { for (int c = 0; c < script_info.length; c++) { String s = script_info[c].getPath(this); diff --git a/trunk/src/com/jpexs/decompiler/flash/action/Action.java b/trunk/src/com/jpexs/decompiler/flash/action/Action.java index cfe2f23bc..1184fd3c2 100644 --- a/trunk/src/com/jpexs/decompiler/flash/action/Action.java +++ b/trunk/src/com/jpexs/decompiler/flash/action/Action.java @@ -977,7 +977,7 @@ public class Action implements GraphSourceItem { if (parts.get(0) instanceof StoreRegisterTreeItem) { StoreRegisterTreeItem str1 = (StoreRegisterTreeItem) parts.get(0); int classReg = str1.register.number; - int instanceReg = -1; + int instanceReg = -1; if ((parts.size() >= 2) && (parts.get(1) instanceof SetMemberTreeItem)) { GraphTargetItem ti1 = ((SetMemberTreeItem) parts.get(1)).value; @@ -1006,7 +1006,7 @@ public class Action implements GraphSourceItem { output2.add(new ClassTreeItem(className, extendsOp, implementsOp, functions, vars, staticFunctions, staticVars)); return output2; } - + if (parts.get(pos) instanceof SetMemberTreeItem) { SetMemberTreeItem smt = (SetMemberTreeItem) parts.get(pos); if (smt.value instanceof StoreRegisterTreeItem) { diff --git a/trunk/src/com/jpexs/decompiler/flash/action/swf4/ActionPush.java b/trunk/src/com/jpexs/decompiler/flash/action/swf4/ActionPush.java index 3fa218f1c..c2ede71d7 100644 --- a/trunk/src/com/jpexs/decompiler/flash/action/swf4/ActionPush.java +++ b/trunk/src/com/jpexs/decompiler/flash/action/swf4/ActionPush.java @@ -316,8 +316,8 @@ public class ActionPush extends Action { stack.push(dvt); if (o instanceof RegisterNumber) { dvt.computedRegValue = variables.get("__register" + ((RegisterNumber) o).number); - if (regNames.containsKey(((RegisterNumber)o).number)) { - ((RegisterNumber)o).name = regNames.get(((RegisterNumber)o).number); + if (regNames.containsKey(((RegisterNumber) o).number)) { + ((RegisterNumber) o).name = regNames.get(((RegisterNumber) o).number); } } pos++; diff --git a/trunk/src/com/jpexs/decompiler/flash/graph/Graph.java b/trunk/src/com/jpexs/decompiler/flash/graph/Graph.java index 33db9edd8..3c4fbcb83 100644 --- a/trunk/src/com/jpexs/decompiler/flash/graph/Graph.java +++ b/trunk/src/com/jpexs/decompiler/flash/graph/Graph.java @@ -1019,7 +1019,7 @@ public class Graph { checkContinueAtTheEnd(retw, whileTrueLoop); List finalCommands = forFinalCommands.get(whileTrueLoop); IfItem ifi = null; - if ((finalCommands!=null) && !finalCommands.isEmpty()) { + if ((finalCommands != null) && !finalCommands.isEmpty()) { if (finalCommands.get(finalCommands.size() - 1) instanceof IfItem) { ifi = (IfItem) finalCommands.get(finalCommands.size() - 1); finalCommands.remove(finalCommands.size() - 1); diff --git a/trunk/src/com/jpexs/decompiler/flash/gui/MainFrame.java b/trunk/src/com/jpexs/decompiler/flash/gui/MainFrame.java index 0e67de670..567e482be 100644 --- a/trunk/src/com/jpexs/decompiler/flash/gui/MainFrame.java +++ b/trunk/src/com/jpexs/decompiler/flash/gui/MainFrame.java @@ -31,6 +31,7 @@ import com.jpexs.decompiler.flash.action.gui.ActionPanel; import com.jpexs.decompiler.flash.gui.player.FlashPlayerPanel; import com.jpexs.decompiler.flash.helpers.Helper; import com.jpexs.decompiler.flash.tags.ABCContainerTag; +import com.jpexs.decompiler.flash.tags.DefineBinaryDataTag; import com.jpexs.decompiler.flash.tags.DefineBitsJPEG2Tag; import com.jpexs.decompiler.flash.tags.DefineBitsJPEG3Tag; import com.jpexs.decompiler.flash.tags.DefineBitsJPEG4Tag; @@ -753,6 +754,11 @@ public class MainFrame extends JFrame implements ActionListener, TreeSelectionLi if ((t instanceof DefineSoundTag) || (t instanceof SoundStreamHeadTag) || (t instanceof SoundStreamHead2Tag)) { return "sound"; } + + if (t instanceof DefineBinaryDataTag) { + return "binaryData"; + } + return "folder"; } @@ -838,6 +844,7 @@ public class MainFrame extends JFrame implements ActionListener, TreeSelectionLi List texts = getTagNodesWithType(list, "text", parent, true); List movies = getTagNodesWithType(list, "movie", parent, true); List sounds = getTagNodesWithType(list, "sound", parent, true); + List binaryData = getTagNodesWithType(list, "binaryData", parent, true); List actionScript = new ArrayList(); for (int i = 0; i < sounds.size(); i++) { @@ -888,6 +895,9 @@ public class MainFrame extends JFrame implements ActionListener, TreeSelectionLi soundsNode.subItems.addAll(sounds); + TagNode binaryDataNode = new TagNode("binaryData"); + binaryDataNode.subItems.addAll(binaryData); + TagNode fontsNode = new TagNode("fonts"); fontsNode.subItems.addAll(fonts); @@ -937,6 +947,9 @@ public class MainFrame extends JFrame implements ActionListener, TreeSelectionLi if (!fontsNode.subItems.isEmpty()) { ret.add(fontsNode); } + if (!binaryDataNode.subItems.isEmpty()) { + ret.add(binaryDataNode); + } if (!framesNode.subItems.isEmpty()) { ret.add(framesNode); } @@ -1052,6 +1065,7 @@ public class MainFrame extends JFrame implements ActionListener, TreeSelectionLi List movies = new ArrayList(); List sounds = new ArrayList(); List actionNodes = new ArrayList(); + List binaryData = new ArrayList(); for (Object d : sel) { if (d instanceof TagNode) { TagNode n = (TagNode) d; @@ -1070,6 +1084,9 @@ public class MainFrame extends JFrame implements ActionListener, TreeSelectionLi if ("sound".equals(getTagType(n.tag))) { sounds.add((Tag) n.tag); } + if ("binaryData".equals(getTagType(n.tag))) { + binaryData.add((Tag) n.tag); + } } if (d instanceof TreeElement) { if (((TreeElement) d).isLeaf()) { @@ -1081,6 +1098,7 @@ public class MainFrame extends JFrame implements ActionListener, TreeSelectionLi SWF.exportShapes(selFile + File.separator + "shapes", shapes); swf.exportMovies(selFile + File.separator + "movies", movies); swf.exportSounds(selFile + File.separator + "sounds", sounds, isMp3); + swf.exportBinaryData(selFile + File.separator + "binaryData", binaryData); if (abcPanel != null) { for (int i = 0; i < tlsList.size(); i++) { TreeLeafScript tls = tlsList.get(i); @@ -1102,6 +1120,7 @@ public class MainFrame extends JFrame implements ActionListener, TreeSelectionLi swf.exportShapes(selFile + File.separator + "shapes"); swf.exportMovies(selFile + File.separator + "movies"); swf.exportSounds(selFile + File.separator + "sounds", isMp3); + swf.exportBinaryData(selFile + File.separator + "binaryData"); swf.exportActionScript(selFile, isPcode); } } catch (Exception ex) { @@ -1408,6 +1427,8 @@ public class MainFrame extends JFrame implements ActionListener, TreeSelectionLi showCard(CARDEMPTYPANEL); } else if ((tagObj instanceof DefineSoundTag) || (tagObj instanceof SoundStreamHeadTag) || (tagObj instanceof SoundStreamHead2Tag)) { showCard(CARDEMPTYPANEL); + } else if (tagObj instanceof DefineBinaryDataTag) { + showCard(CARDEMPTYPANEL); } else if (tagObj instanceof ASMSource) { showCard(CARDACTIONSCRIPTPANEL); actionPanel.setSource((ASMSource) tagObj); diff --git a/trunk/src/com/jpexs/decompiler/flash/gui/graphics/binaryData16.png b/trunk/src/com/jpexs/decompiler/flash/gui/graphics/binaryData16.png new file mode 100644 index 000000000..3d09261a2 Binary files /dev/null and b/trunk/src/com/jpexs/decompiler/flash/gui/graphics/binaryData16.png differ diff --git a/trunk/src/com/jpexs/decompiler/flash/tags/DefineBinaryDataTag.java b/trunk/src/com/jpexs/decompiler/flash/tags/DefineBinaryDataTag.java index 5420063b5..3fb76e45d 100644 --- a/trunk/src/com/jpexs/decompiler/flash/tags/DefineBinaryDataTag.java +++ b/trunk/src/com/jpexs/decompiler/flash/tags/DefineBinaryDataTag.java @@ -18,15 +18,17 @@ package com.jpexs.decompiler.flash.tags; import com.jpexs.decompiler.flash.SWFInputStream; import com.jpexs.decompiler.flash.SWFOutputStream; +import com.jpexs.decompiler.flash.tags.base.CharacterTag; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; -public class DefineBinaryDataTag extends Tag { +public class DefineBinaryDataTag extends CharacterTag { public int tag; public byte binaryData[]; + public long reserved; /** * Gets data bytes @@ -41,6 +43,7 @@ public class DefineBinaryDataTag extends Tag { SWFOutputStream sos = new SWFOutputStream(os, version); try { sos.writeUI16(tag); + sos.writeUI32(reserved); sos.write(binaryData); } catch (IOException e) { } @@ -51,6 +54,12 @@ public class DefineBinaryDataTag extends Tag { super(87, "DefineBinaryData", data, pos); SWFInputStream sis = new SWFInputStream(new ByteArrayInputStream(data), version); tag = sis.readUI16(); + reserved = sis.readUI32(); binaryData = sis.readBytes(sis.available()); } + + @Override + public int getCharacterID() { + return tag; + } } diff --git a/trunk/src/com/jpexs/decompiler/flash/tags/base/CharacterTag.java b/trunk/src/com/jpexs/decompiler/flash/tags/base/CharacterTag.java index 2a8cff06f..501994246 100644 --- a/trunk/src/com/jpexs/decompiler/flash/tags/base/CharacterTag.java +++ b/trunk/src/com/jpexs/decompiler/flash/tags/base/CharacterTag.java @@ -36,6 +36,15 @@ public abstract class CharacterTag extends Tag { * List of ExportAssetsTag used for converting to String */ public List exportAssetsTags = new ArrayList(); + private String className; + + public void setClassName(String className) { + this.className = className; + } + + public String getClassName() { + return className; + } @Override public String getName() { @@ -46,6 +55,9 @@ public abstract class CharacterTag extends Tag { nameAppend = ": " + eat.names.get(pos); } } + if (className != null) { + nameAppend = ": " + className; + } return super.getName() + " (" + getCharacterID() + nameAppend + ")"; }