AS2 script import: import pcode/constants

This commit is contained in:
honfika@gmail.com
2015-07-02 09:07:55 +02:00
parent 12378f508b
commit f96fb33c4d
18 changed files with 255 additions and 73 deletions

View File

@@ -25,7 +25,7 @@ import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.executing.CallPropertyIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushStringIns;
import com.jpexs.decompiler.flash.abc.avm2.parser.AVM2ParseException;
import com.jpexs.decompiler.flash.abc.avm2.parser.script.ActionScriptParser;
import com.jpexs.decompiler.flash.abc.avm2.parser.script.ActionScript3Parser;
import com.jpexs.decompiler.flash.abc.types.ABCException;
import com.jpexs.decompiler.flash.abc.types.ClassInfo;
import com.jpexs.decompiler.flash.abc.types.InstanceInfo;
@@ -1247,7 +1247,7 @@ public class ABC {
}
List<ABC> otherAbcs = new ArrayList<>(pack.allABCs);
otherAbcs.remove(this);
ActionScriptParser.compile(as, this, otherAbcs, isDocumentClass, scriptName, newClassIndex);
ActionScript3Parser.compile(as, this, otherAbcs, isDocumentClass, scriptName, newClassIndex);
// Move newly added script to its position
script_info.set(oldIndex, script_info.get(newIndex));
script_info.remove(newIndex);

View File

@@ -104,6 +104,15 @@ public class ScriptPack extends AS3ClassTreeItem {
return scriptName;
}
public File getExportFile(String directory, ScriptExportSettings exportSettings) throws IOException {
String scriptName = getPathScriptName();
String packageName = getPathPackage();
File outDir = new File(directory + File.separatorChar + makeDirPath(packageName));
Path.createDirectorySafe(outDir);
String fileName = outDir.toString() + File.separator + Helper.makeFileName(scriptName) + exportSettings.getFileExtension();
return new File(fileName);
}
/*public String getPath() {
String packageName = "";
String scriptName = "";
@@ -197,12 +206,7 @@ public class ScriptPack extends AS3ClassTreeItem {
File file = null;
if (!exportSettings.singleFile) {
String scriptName = getPathScriptName();
String packageName = getPathPackage();
File outDir = new File(directory + File.separatorChar + makeDirPath(packageName));
Path.createDirectorySafe(outDir);
String fileName = outDir.toString() + File.separator + Helper.makeFileName(scriptName) + exportSettings.getFileExtension();
file = new File(fileName);
file = getExportFile(directory, exportSettings);
}
try (FileTextWriter writer = exportSettings.singleFile ? null : new FileTextWriter(Configuration.getCodeFormatting(), new FileOutputStream(file))) {

View File

@@ -903,6 +903,7 @@ public class AVM2Code implements Cloneable {
writer.newLine();
}
}
if (info != null) {
writer.appendNoHilight("method").newLine();
writer.appendNoHilight("name ");
@@ -1049,7 +1050,7 @@ public class AVM2Code implements Cloneable {
if (exportMode == ScriptExportMode.HEX) {
Helper.byteArrayToHexWithHeader(writer, getBytes());
} else {
} else if (exportMode == ScriptExportMode.PCODE || exportMode == ScriptExportMode.PCODE_HEX) {
for (AVM2Instruction ins : code) {
long ofs = ins.offset;
if (exportMode == ScriptExportMode.PCODE_HEX) {
@@ -1124,7 +1125,10 @@ public class AVM2Code implements Cloneable {
}
ip++;
}
} else if (exportMode == ScriptExportMode.CONSTANTS) {
writer.appendNoHilight("Constant export mode is not supported.").newLine();
}
return writer;
}

View File

@@ -125,7 +125,7 @@ import java.util.logging.Logger;
*
* @author JPEXS
*/
public class ActionScriptParser {
public class ActionScript3Parser {
private long uniqLast = 0;
@@ -2376,7 +2376,7 @@ public class ActionScriptParser {
addScriptFromTree(traits, documentClass, classPos);
}
public ActionScriptParser(ABC abc, List<ABC> otherABCs) {
public ActionScript3Parser(ABC abc, List<ABC> otherABCs) {
this.abc = abc;
this.otherABCs = otherABCs;
}
@@ -2401,7 +2401,7 @@ public class ActionScriptParser {
initPlayer();
parABCs.addAll(playerABCs);
parABCs.addAll(otherABCs);
ActionScriptParser parser = new ActionScriptParser(abc, parABCs);
ActionScript3Parser parser = new ActionScript3Parser(abc, parABCs);
parser.addScript(src, documentClass, fileName, classPos);
}
@@ -2410,13 +2410,13 @@ public class ActionScriptParser {
try {
initPlayer();
ABC abc = new ABC(null);
ActionScriptParser parser = new ActionScriptParser(abc, playerABCs);
ActionScript3Parser parser = new ActionScript3Parser(abc, playerABCs);
parser.addScript(new String(Helper.readFile(src), Utf8Helper.charset), true, src, classPos);
try (OutputStream fos = new BufferedOutputStream(new FileOutputStream(new File(dst)))) {
abc.saveToStream(fos);
}
} catch (Exception ex) {
Logger.getLogger(ActionScriptParser.class.getName()).log(Level.SEVERE, null, ex);
Logger.getLogger(ActionScript3Parser.class.getName()).log(Level.SEVERE, null, ex);
}
System.exit(0);
}

View File

@@ -75,6 +75,7 @@ import com.jpexs.decompiler.graph.model.IfItem;
import com.jpexs.decompiler.graph.model.LocalData;
import com.jpexs.decompiler.graph.model.NotItem;
import com.jpexs.decompiler.graph.model.ScriptEndItem;
import com.jpexs.helpers.ByteArrayRange;
import com.jpexs.helpers.CancellableWorker;
import com.jpexs.helpers.Helper;
import java.io.ByteArrayOutputStream;
@@ -370,6 +371,34 @@ public abstract class Action implements GraphSourceItem {
return baos.toByteArray();
}
public static ByteArrayRange actionsToByteArrayRange(List<Action> list, boolean addZero, int version) {
byte[] bytes = Action.actionsToBytes(list, addZero, version);
return new ByteArrayRange(bytes);
}
public static void setConstantPools(ASMSource src, List<List<String>> constantPools) {
try {
ActionList actions = src.getActions();
int poolIdx = 0;
for (Action action : actions) {
if (action instanceof ActionConstantPool) {
ActionConstantPool cPool = (ActionConstantPool) action;
List<String> constantPool = constantPools.get(poolIdx);
cPool.constantPool = constantPool;
poolIdx++;
if (constantPools.size() <= poolIdx) {
break;
}
}
}
src.setActions(actions);
} catch (InterruptedException ex) {
logger.log(Level.SEVERE, null, ex);
}
}
/**
* Set addresses of actions in the list
*

View File

@@ -155,11 +155,11 @@ import java.util.List;
*
* @author JPEXS
*/
public class ActionScriptParser {
public class ActionScript2Parser {
private final int swfVersion;
public ActionScriptParser(int swfVersion) {
public ActionScript2Parser(int swfVersion) {
this.swfVersion = swfVersion;
}

View File

@@ -47,6 +47,8 @@ public class ScriptExportSettings {
return ".pcode";
case HEX:
return ".hex";
case CONSTANTS:
return ".txt";
default:
throw new Error("Unsupported script export mode: " + mode);
}

View File

@@ -17,6 +17,8 @@
package com.jpexs.decompiler.flash.importers;
import com.jpexs.decompiler.flash.action.parser.ActionParseException;
import com.jpexs.decompiler.flash.action.parser.pcode.ASMParser;
import com.jpexs.decompiler.flash.action.parser.script.ActionScript2Parser;
import com.jpexs.decompiler.flash.tags.base.ASMSource;
import com.jpexs.decompiler.graph.CompilationException;
import com.jpexs.helpers.Helper;
@@ -34,9 +36,9 @@ import java.util.logging.Logger;
*
* @author JPEXS
*/
public class ScriptImporter {
public class AS2ScriptImporter {
private static final Logger logger = Logger.getLogger(ScriptImporter.class.getName());
private static final Logger logger = Logger.getLogger(AS2ScriptImporter.class.getName());
public int importScripts(String scriptsFolder, Map<String, ASMSource> asms) {
if (!scriptsFolder.endsWith(File.separator)) {
@@ -68,11 +70,11 @@ public class ScriptImporter {
String fileName = Path.combine(currentOutDir, name) + ".as";
if (new File(fileName).exists()) {
String as = Helper.readTextFile(fileName);
String txt = Helper.readTextFile(fileName);
com.jpexs.decompiler.flash.action.parser.script.ActionScriptParser par = new com.jpexs.decompiler.flash.action.parser.script.ActionScriptParser(asm.getSwf().version);
ActionScript2Parser par = new ActionScript2Parser(asm.getSwf().version);
try {
asm.setActions(par.actionsFromString(as));
asm.setActions(par.actionsFromString(txt));
} catch (ActionParseException ex) {
logger.log(Level.SEVERE, "%error% on line %line%, file: %file%".replace("%error%", ex.text).replace("%line%", Long.toString(ex.line)).replace("%file%", fileName), ex);
} catch (CompilationException ex) {
@@ -84,6 +86,40 @@ public class ScriptImporter {
asm.setModified();
importCount++;
}
fileName = Path.combine(currentOutDir, name) + ".pcode";
if (new File(fileName).exists()) {
String txt = Helper.readTextFile(fileName);
try {
asm.setActions(ASMParser.parse(0, true, txt, asm.getSwf().version, false));
} catch (IOException ex) {
logger.log(Level.SEVERE, "error during script import, file: %file%".replace("%file%", fileName), ex);
} catch (ActionParseException ex) {
logger.log(Level.SEVERE, "%error% on line %line%, file: %file%".replace("%error%", ex.text).replace("%line%", Long.toString(ex.line)).replace("%file%", fileName), ex);
}
asm.setModified();
importCount++;
}
fileName = Path.combine(currentOutDir, name) + ".hex";
if (new File(fileName).exists()) {
String txt = Helper.readTextFile(fileName);
asm.setActionBytes(Helper.getBytesFromHexaText(txt));
asm.setModified();
importCount++;
}
fileName = Path.combine(currentOutDir, name) + ".txt";
if (new File(fileName).exists()) {
String txt = Helper.readTextFile(fileName);
asm.setConstantPools(Helper.getConstantPoolsFromText(txt));
asm.setModified();
importCount++;
}
}
return importCount;

View File

@@ -0,0 +1,44 @@
/*
* Copyright (C) 2010-2015 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.importers;
import com.jpexs.decompiler.flash.abc.ScriptPack;
import java.io.File;
import java.util.List;
import java.util.logging.Logger;
/**
*
* @author JPEXS
*/
public class AS3ScriptImporter {
private static final Logger logger = Logger.getLogger(AS3ScriptImporter.class.getName());
public int importScripts(String scriptsFolder, List<ScriptPack> packs) {
if (!scriptsFolder.endsWith(File.separator)) {
scriptsFolder += File.separator;
}
int importCount = 0;
for (ScriptPack pack : packs) {
// todo honfika
}
return importCount;
}
}

View File

@@ -200,8 +200,7 @@ public class DefineButtonTag extends ButtonTag implements ASMSource {
@Override
public void setActions(List<Action> actions) {
byte[] bytes = Action.actionsToBytes(actions, true, swf.version);
actionBytes = new ByteArrayRange(bytes, 0, bytes.length);
actionBytes = Action.actionsToByteArrayRange(actions, true, swf.version);
}
@Override
@@ -214,6 +213,11 @@ public class DefineButtonTag extends ButtonTag implements ASMSource {
this.actionBytes = new ByteArrayRange(actionBytes);
}
@Override
public void setConstantPools(List<List<String>> constantPools) {
Action.setConstantPools(this, constantPools);
}
@Override
public void setModified() {
setModified(true);
@@ -437,5 +441,4 @@ public class DefineButtonTag extends ButtonTag implements ASMSource {
public void setSourceTag(Tag t) {
//nothing
}
}

View File

@@ -151,8 +151,7 @@ public class DoActionTag extends Tag implements ASMSource {
@Override
public void setActions(List<Action> actions) {
byte[] bytes = Action.actionsToBytes(actions, true, swf.version);
actionBytes = new ByteArrayRange(bytes);
actionBytes = Action.actionsToByteArrayRange(actions, true, swf.version);
}
@Override
@@ -165,6 +164,11 @@ public class DoActionTag extends Tag implements ASMSource {
this.actionBytes = new ByteArrayRange(actionBytes);
}
@Override
public void setConstantPools(List<List<String>> constantPools) {
Action.setConstantPools(this, constantPools);
}
@Override
public void setModified() {
setModified(true);

View File

@@ -149,8 +149,7 @@ public class DoInitActionTag extends Tag implements CharacterIdTag, ASMSource {
@Override
public void setActions(List<Action> actions) {
byte[] bytes = Action.actionsToBytes(actions, true, swf.version);
actionBytes = new ByteArrayRange(bytes);
actionBytes = Action.actionsToByteArrayRange(actions, true, swf.version);
}
@Override
@@ -163,6 +162,11 @@ public class DoInitActionTag extends Tag implements CharacterIdTag, ASMSource {
this.actionBytes = new ByteArrayRange(actionBytes);
}
@Override
public void setConstantPools(List<List<String>> constantPools) {
Action.setConstantPools(this, constantPools);
}
@Override
public void setModified() {
setModified(true);

View File

@@ -1,23 +1,22 @@
/*
* Copyright (C) 2010-2015 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.exporters.modes.ScriptExportMode;
@@ -71,6 +70,8 @@ public interface ASMSource extends Exportable {
public void setActionBytes(byte[] actionBytes);
public void setConstantPools(List<List<String>> constantPools);
public GraphTextWriter getActionBytesAsHex(GraphTextWriter writer);
public void addDisassemblyListener(DisassemblyListener listener);
@@ -88,5 +89,4 @@ public interface ASMSource extends Exportable {
public Tag getSourceTag();
public void setSourceTag(Tag t);
}

View File

@@ -226,8 +226,7 @@ public class BUTTONCONDACTION implements ASMSource, Serializable {
@Override
public void setActions(List<Action> actions) {
byte[] bytes = Action.actionsToBytes(actions, true, swf.version);
actionBytes = new ByteArrayRange(bytes);
actionBytes = Action.actionsToByteArrayRange(actions, true, swf.version);
}
@Override
@@ -240,6 +239,11 @@ public class BUTTONCONDACTION implements ASMSource, Serializable {
this.actionBytes = new ByteArrayRange(actionBytes);
}
@Override
public void setConstantPools(List<List<String>> constantPools) {
Action.setConstantPools(this, constantPools);
}
@Override
public void setModified() {
if (tag != null) {

View File

@@ -212,8 +212,7 @@ public class CLIPACTIONRECORD implements ASMSource, Serializable {
@Override
public void setActions(List<Action> actions) {
byte[] bytes = Action.actionsToBytes(actions, true, swf.version);
actionBytes = new ByteArrayRange(bytes);
actionBytes = Action.actionsToByteArrayRange(actions, true, swf.version);
}
@Override
@@ -226,6 +225,11 @@ public class CLIPACTIONRECORD implements ASMSource, Serializable {
this.actionBytes = new ByteArrayRange(actionBytes);
}
@Override
public void setConstantPools(List<List<String>> constantPools) {
Action.setConstantPools(this, constantPools);
}
@Override
public void setModified() {
if (tag != null) {