From fa9623bf9f6cca9b824625ad2232d8c08db006a5 Mon Sep 17 00:00:00 2001 From: "honfika@gmail.com" Date: Sun, 6 Mar 2016 15:35:46 +0100 Subject: [PATCH] mulptiple xlf export fix (separate output directory for each swf), show definebuttontag(1) actions in tree, image export fix (sometimes throws ArrumentOutOfBounds exception) --- .../decompiler/flash/helpers/ImageHelper.java | 2 +- .../flash/tags/DefineButtonTag.java | 119 +---------- .../flash/tags/base/ButtonAction.java | 188 ++++++++++++++++++ .../decompiler/flash/xfl/XFLConverter.java | 13 +- .../decompiler/graph/model/DefaultItem.java | 1 - .../console/CommandLineArgumentParser.java | 17 +- .../flash/gui/AdvancedSettingsDialog.java | 5 +- 7 files changed, 218 insertions(+), 127 deletions(-) create mode 100644 libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/ButtonAction.java diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/helpers/ImageHelper.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/helpers/ImageHelper.java index 187f87b7b..bf5dec726 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/helpers/ImageHelper.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/helpers/ImageHelper.java @@ -58,7 +58,7 @@ public class ImageHelper { CMYKJPEGImageReader r = new CMYKJPEGImageReader(new CMYKJPEGImageReaderSpi()); r.setInput(iis); in = r.read(0); - } catch (IOException ex) { + } catch (IOException | ArrayIndexOutOfBoundsException ex) { try { in = ImageIO.read(ImageIO.createImageInputStream(new ByteArrayInputStream(data))); } catch (IOException ex1) { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineButtonTag.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineButtonTag.java index ea3776639..8903f8d45 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineButtonTag.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineButtonTag.java @@ -16,17 +16,13 @@ */ package com.jpexs.decompiler.flash.tags; -import com.jpexs.decompiler.flash.DisassemblyListener; import com.jpexs.decompiler.flash.SWF; 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.ConstantPoolTooBigException; -import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode; -import com.jpexs.decompiler.flash.helpers.GraphTextWriter; -import com.jpexs.decompiler.flash.tags.base.ASMSource; +import com.jpexs.decompiler.flash.tags.base.ASMSourceContainer; import com.jpexs.decompiler.flash.tags.base.BoundedTag; +import com.jpexs.decompiler.flash.tags.base.ButtonAction; import com.jpexs.decompiler.flash.tags.base.ButtonTag; import com.jpexs.decompiler.flash.tags.base.CharacterTag; import com.jpexs.decompiler.flash.timeline.DepthState; @@ -42,9 +38,9 @@ import com.jpexs.decompiler.flash.types.annotations.SWFType; import com.jpexs.decompiler.flash.types.annotations.SWFVersion; import com.jpexs.helpers.ByteArrayRange; import com.jpexs.helpers.Cache; -import com.jpexs.helpers.Helper; import java.io.IOException; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.Set; @@ -54,7 +50,7 @@ import java.util.Set; * @author JPEXS */ @SWFVersion(from = 1) -public class DefineButtonTag extends ButtonTag implements ASMSource { +public class DefineButtonTag extends ButtonTag implements ASMSourceContainer { public static final int ID = 7; @@ -77,13 +73,6 @@ public class DefineButtonTag extends ButtonTag implements ASMSource { @HideInRawEdit public ByteArrayRange actionBytes; - private String scriptName = "-"; - - @Override - public String getScriptName() { - return scriptName; - } - /** * Constructor * @@ -108,11 +97,6 @@ public class DefineButtonTag extends ButtonTag implements ASMSource { readData(sis, data, 0, false, false, false); } - @Override - public void setScriptName(String scriptName) { - this.scriptName = scriptName; - } - @Override public final void readData(SWFInputStream sis, ByteArrayRange data, int level, boolean parallel, boolean skipUnusualTags, boolean lazy) throws IOException { buttonId = sis.readUI16("buttonId"); @@ -131,7 +115,6 @@ public class DefineButtonTag extends ButtonTag implements ASMSource { sos.writeUI16(buttonId); sos.writeBUTTONRECORDList(characters, false); sos.write(getActionBytes()); - //sos.write(Action.actionsToBytes(actions, true, version)); } @Override @@ -149,75 +132,27 @@ public class DefineButtonTag extends ButtonTag implements ASMSource { return characters; } - /** - * Converts actions to ASM source - * - * @param exportMode PCode or hex? - * @param writer - * @param actions - * @return ASM source - * @throws java.lang.InterruptedException - */ @Override - public GraphTextWriter getASMSource(ScriptExportMode exportMode, GraphTextWriter writer, ActionList actions) throws InterruptedException { - if (actions == null) { - actions = getActions(); - } - return Action.actionsToString(listeners, 0, actions, swf.version, exportMode, writer); + public List getSubItems() { + return Arrays.asList(new ButtonAction(this)); } - /** - * Whether or not this object contains ASM source - * - * @return True when contains - */ - @Override - public boolean containsSource() { - return true; - } - - /** - * Returns actions associated with this object - * - * @return List of actions - * @throws java.lang.InterruptedException - */ - @Override - public ActionList getActions() throws InterruptedException { - return SWF.getCachedActionList(this, listeners); - } - - @Override public void setActions(List actions) { actionBytes = Action.actionsToByteArrayRange(actions, true, swf.version); } - @Override public ByteArrayRange getActionBytes() { return actionBytes; } - @Override public void setActionBytes(byte[] actionBytes) { this.actionBytes = new ByteArrayRange(actionBytes); - SWF.uncache(this); } - @Override - public void setConstantPools(List> constantPools) throws ConstantPoolTooBigException { - Action.setConstantPools(this, constantPools, false); - } - - @Override public void setModified() { setModified(true); } - @Override - public GraphTextWriter getActionBytesAsHex(GraphTextWriter writer) { - return Helper.byteArrayToHexWithHeader(writer, actionBytes.getRangeData()); - } - @Override public boolean replaceCharacter(int oldCharacterId, int newCharacterId) { boolean modified = false; @@ -286,18 +221,6 @@ public class DefineButtonTag extends ButtonTag implements ASMSource { return rect; } - List listeners = new ArrayList<>(); - - @Override - public void addDisassemblyListener(DisassemblyListener listener) { - listeners.add(listener); - } - - @Override - public void removeDisassemblyListener(DisassemblyListener listener) { - listeners.remove(listener); - } - @Override public boolean trackAsMenu() { return false; @@ -308,26 +231,6 @@ public class DefineButtonTag extends ButtonTag implements ASMSource { return 1; } - @Override - public GraphTextWriter getActionSourcePrefix(GraphTextWriter writer) { - return writer; - } - - @Override - public GraphTextWriter getActionSourceSuffix(GraphTextWriter writer) { - return writer; - } - - @Override - public int getPrefixLineCount() { - return 0; - } - - @Override - public String removePrefixAndSuffix(String source) { - return source; - } - @Override protected void initTimeline(Timeline timeline) { ColorTransform clrTrans = null; @@ -389,14 +292,4 @@ public class DefineButtonTag extends ButtonTag implements ASMSource { timeline.addFrame(frameHit); } - - @Override - public Tag getSourceTag() { - return this; - } - - @Override - public void setSourceTag(Tag t) { - //nothing - } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/ButtonAction.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/ButtonAction.java new file mode 100644 index 000000000..65c4e2f8b --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/ButtonAction.java @@ -0,0 +1,188 @@ +/* + * Copyright (C) 2010-2016 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash.tags.base; + +import com.jpexs.decompiler.flash.DisassemblyListener; +import com.jpexs.decompiler.flash.SWF; +import com.jpexs.decompiler.flash.action.Action; +import com.jpexs.decompiler.flash.action.ActionList; +import com.jpexs.decompiler.flash.action.ConstantPoolTooBigException; +import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode; +import com.jpexs.decompiler.flash.helpers.GraphTextWriter; +import com.jpexs.decompiler.flash.tags.DefineButtonTag; +import com.jpexs.decompiler.flash.tags.Tag; +import com.jpexs.helpers.ByteArrayRange; +import com.jpexs.helpers.Helper; +import java.util.ArrayList; +import java.util.List; + +/** + * Object containing ASM source + * + * @author JPEXS + */ +public class ButtonAction implements ASMSource { + + List listeners = new ArrayList<>(); + + private String scriptName = "-"; + + private final DefineButtonTag buttonTag; + + public ButtonAction(DefineButtonTag buttonTag) { + this.buttonTag = buttonTag; + } + + /** + * Converts actions to ASM source + * + * @param exportMode PCode or hex? + * @param writer + * @param actions + * @return ASM source + * @throws java.lang.InterruptedException + */ + @Override + public GraphTextWriter getASMSource(ScriptExportMode exportMode, GraphTextWriter writer, ActionList actions) throws InterruptedException { + if (actions == null) { + actions = getActions(); + } + + return Action.actionsToString(listeners, 0, actions, getSwf().version, exportMode, writer); + } + + /** + * Whether or not this object contains ASM source + * + * @return True when contains + */ + @Override + public boolean containsSource() { + return true; + } + + /** + * Returns actions associated with this object + * + * @return List of actions + * @throws java.lang.InterruptedException + */ + @Override + public ActionList getActions() throws InterruptedException { + return SWF.getCachedActionList(this, listeners); + } + + @Override + public void setActions(List actions) { + buttonTag.setActions(actions); + } + + @Override + public void setModified() { + buttonTag.setModified(); + } + + @Override + public ByteArrayRange getActionBytes() { + return buttonTag.getActionBytes(); + } + + @Override + public void setActionBytes(byte[] actionBytes) { + buttonTag.setActionBytes(actionBytes); + SWF.uncache(this); + } + + @Override + public void setConstantPools(List> constantPools) throws ConstantPoolTooBigException { + Action.setConstantPools(this, constantPools, false); + } + + @Override + public GraphTextWriter getActionBytesAsHex(GraphTextWriter writer) { + return Helper.byteArrayToHexWithHeader(writer, buttonTag.getActionBytes().getRangeData()); + } + + @Override + public void addDisassemblyListener(DisassemblyListener listener) { + listeners.add(listener); + } + + @Override + public void removeDisassemblyListener(DisassemblyListener listener) { + listeners.remove(listener); + } + + @Override + public GraphTextWriter getActionSourcePrefix(GraphTextWriter writer) { + return writer; + } + + @Override + public GraphTextWriter getActionSourceSuffix(GraphTextWriter writer) { + return writer; + } + + @Override + public int getPrefixLineCount() { + return 0; + } + + @Override + public String removePrefixAndSuffix(String source) { + return source; + } + + @Override + public Tag getSourceTag() { + return buttonTag; + } + + @Override + public void setSourceTag(Tag t) { + } + + @Override + public String getScriptName() { + return scriptName; + } + + @Override + public void setScriptName(String scriptName) { + this.scriptName = scriptName; + } + + @Override + public String getExportFileName() { + return buttonTag.getExportFileName(); + } + + @Override + public SWF getSwf() { + return buttonTag.getSwf(); + } + + @Override + public boolean isModified() { + return buttonTag.isModified(); + } + + @Override + public String toString() { + return buttonTag.toString(); + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/xfl/XFLConverter.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/xfl/XFLConverter.java index 092d3806d..6554c80bf 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/xfl/XFLConverter.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/xfl/XFLConverter.java @@ -56,6 +56,7 @@ import com.jpexs.decompiler.flash.tags.StartSoundTag; import com.jpexs.decompiler.flash.tags.SymbolClassTag; import com.jpexs.decompiler.flash.tags.Tag; import com.jpexs.decompiler.flash.tags.base.ASMSource; +import com.jpexs.decompiler.flash.tags.base.ButtonAction; import com.jpexs.decompiler.flash.tags.base.ButtonTag; import com.jpexs.decompiler.flash.tags.base.CharacterTag; import com.jpexs.decompiler.flash.tags.base.FontTag; @@ -247,13 +248,7 @@ public class XFLConverter { if (ls.width == 1) { params.append(" solidStyle=\"hairline\""); } - if ((!ls.noHScaleFlag) && (!ls.noVScaleFlag)) { - params.append(" scaleMode=\"normal\""); - } else if ((!ls.noHScaleFlag) && ls.noVScaleFlag) { - params.append(" scaleMode=\"horizontal\""); - } else if (ls.noHScaleFlag && (!ls.noVScaleFlag)) { - params.append(" scaleMode=\"vertical\""); - } + params.append(" scaleMode=\"").append(getScaleMode(ls)).append("\""); switch (ls.endCapStyle) { //What about endCapStyle? case LINESTYLE2.NO_CAP: @@ -276,7 +271,7 @@ public class XFLConverter { break; } - ret.append(""); ret.append(""); @@ -1148,7 +1143,7 @@ public class XFLConverter { if (tag instanceof DefineButtonTag) { ret.append(""); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/DefaultItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/DefaultItem.java index a26420034..3629ebd0d 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/DefaultItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/DefaultItem.java @@ -20,5 +20,4 @@ public class DefaultItem extends GraphTargetItem { public GraphTargetItem returnType() { return TypeItem.UNBOUNDED; } - } diff --git a/src/com/jpexs/decompiler/flash/console/CommandLineArgumentParser.java b/src/com/jpexs/decompiler/flash/console/CommandLineArgumentParser.java index ca8ccab00..29b673719 100644 --- a/src/com/jpexs/decompiler/flash/console/CommandLineArgumentParser.java +++ b/src/com/jpexs/decompiler/flash/console/CommandLineArgumentParser.java @@ -1523,7 +1523,13 @@ public class CommandLineArgumentParser { if (flaVersion == null) { flaVersion = FLAVersion.CS6; //Defaults to CS6 } - swf.exportFla(handler, outDir + (multipleExportTypes ? File.separator + "fla" : ""), inFile.getName(), ApplicationInfo.APPLICATION_NAME, ApplicationInfo.applicationVerName, ApplicationInfo.version, Configuration.parallelSpeedUp.get(), flaVersion); + String outFile = outDir; + if (multipleExportTypes) { + outFile = Path.combine(outFile, "fla"); + }; + + outFile = Path.combine(outFile, inFile.getName()); + swf.exportFla(handler, outFile, inFile.getName(), ApplicationInfo.APPLICATION_NAME, ApplicationInfo.applicationVerName, ApplicationInfo.version, Configuration.parallelSpeedUp.get(), flaVersion); } if (exportFormats.contains("xfl")) { @@ -1532,7 +1538,14 @@ public class CommandLineArgumentParser { if (xflVersion == null) { xflVersion = FLAVersion.CS6; //Defaults to CS6 } - swf.exportXfl(handler, outDir + (multipleExportTypes ? File.separator + "xfl" : ""), inFile.getName(), ApplicationInfo.APPLICATION_NAME, ApplicationInfo.applicationVerName, ApplicationInfo.version, Configuration.parallelSpeedUp.get(), xflVersion); + + String outFile = outDir; + if (multipleExportTypes) { + outFile = Path.combine(outFile, "xfl"); + }; + + outFile = Path.combine(outFile, inFile.getName()); + swf.exportXfl(handler, outFile, inFile.getName(), ApplicationInfo.APPLICATION_NAME, ApplicationInfo.applicationVerName, ApplicationInfo.version, Configuration.parallelSpeedUp.get(), xflVersion); } if (!singleFile) { diff --git a/src/com/jpexs/decompiler/flash/gui/AdvancedSettingsDialog.java b/src/com/jpexs/decompiler/flash/gui/AdvancedSettingsDialog.java index dce648f8d..d639549cc 100644 --- a/src/com/jpexs/decompiler/flash/gui/AdvancedSettingsDialog.java +++ b/src/com/jpexs/decompiler/flash/gui/AdvancedSettingsDialog.java @@ -334,7 +334,7 @@ public class AdvancedSettingsDialog extends AppDialog { final Map locNames = new HashMap<>(); for (String name : names) { - String locName = "(Internal) " + name; + String locName; if (resourceBundle.containsKey("config.name." + name)) { locName = resourceBundle.getString("config.name." + name); @@ -344,7 +344,10 @@ public class AdvancedSettingsDialog extends AppDialog { if (cint == null) { throw new RuntimeException("Missing configuration name: " + name); } + + locName = "(Internal) " + name; } + locNames.put(name, locName); }