Project renamed to Free Flash Decompiler.

Code moved to new dir.
Version changed to 1.3
This commit is contained in:
Jindra Pet��k
2013-02-17 18:13:01 +01:00
parent 561c12426e
commit 6ca95c8e34
792 changed files with 4004 additions and 4021 deletions
@@ -0,0 +1,159 @@
/*
* Copyright (C) 2010-2013 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash;
import com.jpexs.proxy.Replacement;
import java.io.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.logging.Logger;
import javax.swing.JOptionPane;
public class Configuration {
private static final String CONFIG_NAME = "asdec.cfg";
private static final String REPLACEMENTS_NAME = "replacements.ini";
private static HashMap<String, Object> config = new HashMap<String, Object>();
public static String getASDecHome() {
String dir = ".";//System.getProperty("user.home");
if (!dir.endsWith(File.separator)) {
dir += File.separator;
}
dir += "config" + File.separator;
return dir;
}
private static String getReplacementsFile() {
return getASDecHome() + REPLACEMENTS_NAME;
}
private static String getConfigFile() {
return getASDecHome() + CONFIG_NAME;
}
/**
* List of replacements
*/
public static java.util.List<Replacement> replacements = new ArrayList<Replacement>();
/**
* Saves replacements to file for future use
*/
private static void saveReplacements() {
try {
if (replacements.isEmpty()) {
File rf = new File(getReplacementsFile());
if (rf.exists()) {
rf.delete();
}
} else {
File f = new File(getASDecHome());
if (!f.exists()) {
f.mkdir();
}
PrintWriter pw = new PrintWriter(new FileWriter(getReplacementsFile()));
for (Replacement r : replacements) {
pw.println(r.urlPattern);
pw.println(r.targetFile);
}
pw.close();
}
} catch (IOException e) {
}
}
/**
* Load replacements from file
*/
private static void loadReplacements() {
replacements = new ArrayList<Replacement>();
try {
BufferedReader br = new BufferedReader(new FileReader(getReplacementsFile()));
String s;
while ((s = br.readLine()) != null) {
Replacement r = new Replacement(s, br.readLine());
replacements.add(r);
}
br.close();
} catch (IOException e) {
}
}
public static Object getConfig(String cfg) {
return getConfig(cfg, null);
}
public static Object getConfig(String cfg, Object defaultValue) {
if (!config.containsKey(cfg)) {
return defaultValue;
}
return config.get(cfg);
}
public static Object setConfig(String cfg, Object value) {
return config.put(cfg, value);
}
public static void load() {
ObjectInputStream ois = null;
try {
ois = new ObjectInputStream(new FileInputStream(getConfigFile()));
config = (HashMap<String, Object>) ois.readObject();
} catch (FileNotFoundException ex) {
} catch (ClassNotFoundException cnf) {
} catch (IOException ex) {
} finally {
if (ois != null) {
try {
ois.close();
} catch (IOException ex1) {
//ignore
}
}
}
loadReplacements();
}
public static void save() {
File f = new File(getASDecHome());
if (!f.exists()) {
f.mkdir();
}
ObjectOutputStream oos = null;
try {
oos = new ObjectOutputStream(new FileOutputStream(getConfigFile()));
oos.writeObject(config);
} catch (IOException ex) {
JOptionPane.showMessageDialog(null, "Cannot save configuration.\nPlease make application directory writable.", "Error", JOptionPane.ERROR_MESSAGE);
Logger.getLogger(SWFInputStream.class.getName()).severe("Configuration directory is read only.");
} finally {
if (oos != null) {
try {
oos.close();
} catch (IOException ex1) {
//ignore
}
}
}
saveReplacements();
}
public static List<Replacement> getReplacements() {
return replacements;
}
}
@@ -0,0 +1,26 @@
/*
* Copyright (C) 2010-2013 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash;
/**
*
* @author JPEXS
*/
public interface EventListener {
public void handleEvent(String event, Object data);
}
@@ -0,0 +1,830 @@
/*
* Copyright (C) 2010-2013 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash;
import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
import com.jpexs.decompiler.flash.abc.types.MethodBody;
import com.jpexs.decompiler.flash.gui.AboutDialog;
import com.jpexs.decompiler.flash.gui.LoadingDialog;
import com.jpexs.decompiler.flash.gui.MainFrame;
import com.jpexs.decompiler.flash.gui.ModeFrame;
import com.jpexs.decompiler.flash.gui.View;
import com.jpexs.decompiler.flash.gui.proxy.ProxyFrame;
import com.jpexs.decompiler.flash.helpers.Highlighting;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.*;
import java.lang.management.ManagementFactory;
import java.net.Socket;
import java.util.Calendar;
import java.util.logging.ConsoleHandler;
import java.util.logging.FileHandler;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.logging.SimpleFormatter;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.SwingWorker;
import javax.swing.filechooser.FileFilter;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
/**
* Main executable class
*
* @author JPEXS
*/
public class Main {
public static ProxyFrame proxyFrame;
public static String file;
public static String maskURL;
public static SWF swf;
public static final String version = "1.3";
public static final String applicationName = "JPEXS Free Flash Decompiler v." + version;
public static final String shortApplicationName = "FFDec";
public static final String shortApplicationVerName = shortApplicationName + " v." + version;
public static final String projectPage = "http://www.free-decompiler.com/flash";
public static LoadingDialog loadingDialog;
public static ModeFrame modeFrame;
private static boolean working = false;
private static TrayIcon trayIcon;
private static MenuItem stopMenuItem;
private static boolean commandLineMode = false;
public static MainFrame mainFrame;
public static boolean isCommandLineMode() {
return commandLineMode;
}
public static boolean DEBUG_COPY = false;
/**
* Debug mode = throwing an error when comparing original file and recompiled
*/
public static boolean debugMode = false;
/**
* Turn off reading unsafe tags (tags which can cause problems with
* recompiling)
*/
public static boolean DISABLE_DANGEROUS = false;
/**
* Turn off resolving constants in ActionScript 2
*/
public static final boolean RESOLVE_CONSTANTS = true;
/**
* Turn off decompiling if needed
*/
public static final boolean DO_DECOMPILE = true;
/**
* Find latest constant pool in the code
*/
public static final boolean LATEST_CONSTANTPOOL_HACK = false;
/**
* Dump tags to stdout
*/
public static boolean dump_tags = false;
/**
* Limit of code subs (for obfuscated code)
*/
public static final int SUBLIMITER = 500;
//using parameter names in decompiling may cause problems because oficial programs like Flash CS 5.5 inserts wrong parameter names indices
public static final boolean PARAM_NAMES_ENABLE = false;
public static String getFileTitle() {
if (maskURL != null) {
return maskURL;
}
return file;
}
public static void setSubLimiter(boolean value) {
if (value) {
AVM2Code.toSourceLimit = Main.SUBLIMITER;
} else {
AVM2Code.toSourceLimit = -1;
}
}
public static boolean isWorking() {
return working;
}
public static void showProxy() {
if (proxyFrame == null) {
proxyFrame = new ProxyFrame();
}
proxyFrame.setVisible(true);
proxyFrame.setState(Frame.NORMAL);
}
public static void startWork(String name) {
startWork(name, -1);
}
public static void startWork(String name, int percent) {
working = true;
if (mainFrame != null) {
mainFrame.setWorkStatus(name);
if (percent == -1) {
mainFrame.hidePercent();
} else {
mainFrame.setPercent(percent);
}
}
if (loadingDialog != null) {
loadingDialog.setDetail(name);
if (percent == -1) {
loadingDialog.hidePercent();
} else {
loadingDialog.setPercent(percent);
}
}
if (Main.isCommandLineMode()) {
System.out.println(name);
}
}
public static void stopWork() {
working = false;
if (mainFrame != null) {
mainFrame.setWorkStatus("");
}
if (loadingDialog != null) {
loadingDialog.setDetail("");
}
}
public static SWF parseSWF(String file) throws Exception {
FileInputStream fis = new FileInputStream(file);
InputStream bis = new BufferedInputStream(fis);
SWF locswf = new SWF(bis, new PercentListener() {
@Override
public void percent(int p) {
startWork("Reading SWF", p);
}
});
locswf.addEventListener(new EventListener() {
public void handleEvent(String event, Object data) {
if (event.equals("export")) {
startWork((String) data);
}
}
});
return locswf;
}
public static void saveFile(String outfile) throws IOException {
file = outfile;
swf.saveTo(new FileOutputStream(outfile));
}
private static class OpenFileWorker extends SwingWorker {
@Override
protected Object doInBackground() throws Exception {
try {
Main.startWork("Reading SWF...");
swf = parseSWF(Main.file);
FileInputStream fis = new FileInputStream(file);
DEBUG_COPY = true;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
/*try {
swf.saveTo(baos);
} catch (NotSameException nse) {
Logger.getLogger(Main.class.getName()).log(Level.FINE, null, nse);
JOptionPane.showMessageDialog(null, "WARNING: The SWF decompiler may have problems saving this file. Recommended usage is READ ONLY.");
}*/
DEBUG_COPY = false;
//DEBUG_COPY=true;
} catch (Exception ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
JOptionPane.showMessageDialog(null, "Cannot load SWF file.");
loadingDialog.setVisible(false);
return false;
}
try {
mainFrame = new MainFrame(swf);
loadingDialog.setVisible(false);
mainFrame.setVisible(true);
} catch (Exception ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
}
return true;
}
}
public static boolean openFile(String swfFile) {
if (mainFrame != null) {
mainFrame.setVisible(false);
}
Main.file = swfFile;
if (Main.loadingDialog == null) {
Main.loadingDialog = new LoadingDialog();
}
Main.loadingDialog.setVisible(true);
(new OpenFileWorker()).execute();
return true;
}
public static boolean saveFileDialog() {
JFileChooser fc = new JFileChooser();
fc.setCurrentDirectory(new File((String) Configuration.getConfig("lastSaveDir", ".")));
JFrame f = new JFrame();
View.setWindowIcon(f);
int returnVal = fc.showSaveDialog(f);
if (returnVal == JFileChooser.APPROVE_OPTION) {
File file = fc.getSelectedFile();
try {
Main.saveFile(file.getAbsolutePath());
Configuration.setConfig("lastSaveDir", file.getParentFile().getAbsolutePath());
maskURL = null;
return true;
} catch (IOException ex) {
JOptionPane.showMessageDialog(null, "Cannot write to the file");
}
}
return false;
}
public static boolean openFileDialog() {
maskURL = null;
JFileChooser fc = new JFileChooser();
fc.setCurrentDirectory(new File((String) Configuration.getConfig("lastOpenDir", ".")));
fc.setFileFilter(new FileFilter() {
@Override
public boolean accept(File f) {
return (f.getName().endsWith(".swf")) || (f.isDirectory());
}
@Override
public String getDescription() {
return "SWF files (*.swf)";
}
});
JFrame f = new JFrame();
View.setWindowIcon(f);
int returnVal = fc.showOpenDialog(f);
if (returnVal == JFileChooser.APPROVE_OPTION) {
Configuration.setConfig("lastOpenDir", fc.getSelectedFile().getParentFile().getAbsolutePath());
File selfile = fc.getSelectedFile();
Main.openFile(selfile.getAbsolutePath());
return true;
} else {
return false;
}
}
public static void showModeFrame() {
if (modeFrame == null) {
modeFrame = new ModeFrame();
}
modeFrame.setVisible(true);
}
public static void updateLicense() {
updateLicenseInDir(new File(".\\src\\"));
}
/**
* Script for updating license header in java files :-)
*
* @param dir Star directory (e.g. "src/")
*/
public static void updateLicenseInDir(File dir) {
int defaultStartYear = 2010;
int defaultFinalYear = 2013;
String defaultAuthor = "JPEXS";
String defaultYearStr = "" + defaultStartYear;
if (defaultFinalYear != defaultStartYear) {
defaultYearStr += "-" + defaultFinalYear;
}
String license = "/*\r\n * Copyright (C) {year} {author}\r\n * \r\n * This program is free software: you can redistribute it and/or modify\r\n * it under the terms of the GNU General Public License as published by\r\n * the Free Software Foundation, either version 3 of the License, or\r\n * (at your option) any later version.\r\n * \r\n * This program is distributed in the hope that it will be useful,\r\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r\n * GNU General Public License for more details.\r\n * \r\n * You should have received a copy of the GNU General Public License\r\n * along with this program. If not, see <http://www.gnu.org/licenses/>.\r\n */";
File files[] = dir.listFiles();
for (File f : files) {
if (f.isDirectory()) {
updateLicenseInDir(f);
} else {
if (f.getName().endsWith(".java")) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
PrintWriter pw = null;
try {
pw = new PrintWriter(new OutputStreamWriter(baos, "utf8"));
} catch (UnsupportedEncodingException ex) {
}
try {
BufferedReader br = new BufferedReader(new FileReader(f));
String s;
boolean packageFound = false;
String author = defaultAuthor;
String yearStr = defaultYearStr;
while ((s = br.readLine()) != null) {
if (!packageFound) {
if (s.trim().startsWith("package")) {
packageFound = true;
pw.println(license.replace("{year}", yearStr).replace("{author}", author));
} else {
Matcher mAuthor = Pattern.compile("^.*Copyright \\(C\\) ([0-9]+)(-[0-9]+)? (.*)$").matcher(s);
if (mAuthor.matches()) {
author = mAuthor.group(3).trim();
int startYear = Integer.parseInt(mAuthor.group(1).trim());
if (startYear == defaultFinalYear) {
yearStr = "" + startYear;
} else {
yearStr = "" + startYear + "-" + defaultFinalYear;
}
if (!author.equals(defaultAuthor)) {
System.out.println("Detected nodefault author:" + author + " in " + f.getAbsolutePath());
}
}
}
}
if (packageFound) {
pw.println(s);
}
}
br.close();
pw.close();
} catch (IOException ex) {
}
FileOutputStream fos;
try {
fos = new FileOutputStream(f);
fos.write(baos.toByteArray());
fos.close();
} catch (IOException ex) {
}
}
}
}
}
public static void badArguments() {
System.err.println("Error: Bad Commandline Arguments!");
printCmdLineUsage();
System.exit(1);
}
public static void printHeader() {
System.out.println(applicationName);
for (int i = 0; i < applicationName.length(); i++) {
System.out.print("-");
}
System.out.println();
}
public static void printCmdLineUsage() {
System.out.println("Commandline arguments:");
System.out.println(" 1) -help | --help | /?");
System.out.println(" ...shows commandline arguments (this help)");
System.out.println(" 2) infile");
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) outdirectory infile");
System.out.println(" ...export infile sources to outdirectory as AsctionScript code (\"as\" argument) or as PCode (\"pcode\" argument) or images");
System.out.println(" 5) -dumpSWF infile");
System.out.println(" ...dumps list of SWF tags to console");
System.out.println(" 6) -compress infile outfile");
System.out.println(" ...Compress SWF infile and save it to outfile");
System.out.println(" 7) -decompress infile outfile");
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 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 {
FileInputStream fis = new FileInputStream(from);
FileOutputStream fos = new FileOutputStream(to);
byte buf[] = new byte[4096];
int cnt = 0;
while ((cnt = fis.read(buf)) > 0) {
fos.write(buf, 0, cnt);
}
fis.close();
fos.close();
}
public static void restartApplication(String[] args) {
StringBuilder cmd = new StringBuilder();
cmd.append(System.getProperty("java.home") + File.separator + "bin" + File.separator + "java ");
for (String jvmArg : ManagementFactory.getRuntimeMXBean().getInputArguments()) {
cmd.append(jvmArg + " ");
}
cmd.append("-cp ").append(ManagementFactory.getRuntimeMXBean().getClassPath()).append(" ");
cmd.append(Main.class.getName()).append(" ");
for (String arg : args) {
cmd.append(arg).append(" ");
}
try {
Runtime.getRuntime().exec(cmd.toString());
} catch (IOException ex) {
}
System.exit(0);
}
public static void checkSWT(String[] args) {
if (System.getProperty("os.name").toLowerCase().indexOf("win") == -1) {
return;
}
String lastBits = (String) Configuration.getConfig("bits", "-");
if ((!System.getProperty("sun.arch.data.model").equals(lastBits)) || (!(new File("lib/swt.jar")).exists())) {
try {
if (System.getProperty("sun.arch.data.model").equals("32")) {
copyFile("lib/swt32.jar", "lib/swt.jar");
} else if (System.getProperty("sun.arch.data.model").equals("64")) {
copyFile("lib/swt64.jar", "lib/swt.jar");
}
} catch (IOException ex) {
JOptionPane.showMessageDialog(null, "Cannot copy SWT library.\nPlease make application directory writeable.\n(Placing outside of Program files may help)", "Error", JOptionPane.ERROR_MESSAGE);
Logger.getLogger(SWFInputStream.class.getName()).severe("Cannot copy SWT library");
System.exit(1);
}
Configuration.setConfig("bits", System.getProperty("sun.arch.data.model"));
Configuration.save();
restartApplication(args);
}
}
public static final void printASM(AVM2Code code) {
String s = Highlighting.stripHilights(code.toASMSource(null, new MethodBody()));
String ss[] = s.split("\n");
for (int i = 0; i < ss.length; i++) {
System.out.println("" + i + ":" + ss[i]);
}
}
/**
* @param args the command line arguments
*/
public static void main(String[] args) throws IOException {
View.setLookAndFeel();
Configuration.load();
checkSWT(args);
int pos = 0;
if (args.length > 0) {
if (args[0].equals("-debug")) {
debugMode = true;
pos++;
}
}
initLogging(debugMode);
if (args.length < pos + 1) {
autoCheckForUpdates();
showModeFrame();
} else {
if (args[pos].equals("-proxy")) {
int port = 55555;
for (int i = pos; i < args.length; i++) {
if (args[i].startsWith("-P")) {
try {
port = Integer.parseInt(args[pos].substring(2));
} catch (NumberFormatException nex) {
System.err.println("Bad port number");
}
}
}
if (proxyFrame == null) {
proxyFrame = new ProxyFrame();
}
proxyFrame.setPort(port);
addTrayIcon();
switchProxy();
} else if (args[pos].equals("-export")) {
if (args.length < pos + 4) {
badArguments();
}
String exportFormat = args[pos + 1];
if (!exportFormat.toLowerCase().equals("as")) {
if (!exportFormat.toLowerCase().equals("pcode")) {
if (!exportFormat.toLowerCase().equals("image")) {
System.err.println("Invalid export format:" + exportFormat);
badArguments();
}
}
}
File outDir = new File(args[pos + 2]);
File inFile = new File(args[pos + 3]);
if (!inFile.exists()) {
System.err.println("Input SWF file does not exist!");
badArguments();
}
commandLineMode = true;
boolean exportOK;
try {
printHeader();
dump_tags = true;
SWF exfile = new SWF(new FileInputStream(inFile));
exfile.addEventListener(new EventListener() {
public void handleEvent(String event, Object data) {
if (event.equals("export")) {
System.out.println((String) data);
}
}
});
if (exportFormat.equals("image")) {
exfile.exportImages(outDir.getAbsolutePath());
exportOK = true;
} else if (exportFormat.equals("as") || exportFormat.equals("pcode")) {
exportOK = exfile.exportActionScript(outDir.getAbsolutePath(), exportFormat.equals("pcode"));
} else {
exportOK = false;
}
} catch (Exception ex) {
exportOK = false;
System.err.print("FAIL: Exporting Failed on Exception - ");
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
System.exit(1);
}
if (exportOK) {
System.out.println("OK");
System.exit(0);
} else {
System.err.println("FAIL");
System.exit(1);
}
} else if (args[pos].equals("-compress")) {
if (args.length < pos + 3) {
badArguments();
}
if (SWF.fws2cws(new FileInputStream(args[pos + 1]), new FileOutputStream(args[pos + 2]))) {
System.out.println("OK");
} else {
System.err.println("FAIL");
}
} else if (args[pos].equals("-decompress")) {
if (args.length < pos + 3) {
badArguments();
}
if (SWF.cws2fws(new FileInputStream(args[pos + 1]), new FileOutputStream(args[pos + 2]))) {
System.out.println("OK");
System.exit(0);
} else {
System.err.println("FAIL");
System.exit(1);
}
} else if (args[pos].equals("-dumpSWF")) {
if (args.length < pos + 2) {
badArguments();
}
try {
dump_tags = true;
SWF swf = parseSWF(args[pos + 1]);
} catch (Exception ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
System.exit(1);
}
System.exit(0);
} else if (args[pos].equals("-help") || args[pos].equals("--help") || args[pos].equals("/?")) {
printHeader();
printCmdLineUsage();
System.exit(0);
} else if (args.length == pos + 1) {
autoCheckForUpdates();
openFile(args[pos]);
} else {
badArguments();
}
}
}
public static String tempFile(String url) {
File f = new File(Configuration.getASDecHome() + "saved" + File.separator);
if (!f.exists()) {
f.mkdirs();
}
return Configuration.getASDecHome() + "saved" + File.separator + "asdec_" + Integer.toHexString(url.hashCode()) + ".tmp";
}
public static void removeTrayIcon() {
if (SystemTray.isSupported()) {
SystemTray tray = SystemTray.getSystemTray();
if (trayIcon != null) {
tray.remove(trayIcon);
trayIcon = null;
}
}
}
public static void switchProxy() {
proxyFrame.switchState();
if (stopMenuItem != null) {
if (proxyFrame.isRunning()) {
stopMenuItem.setLabel("Stop proxy");
} else {
stopMenuItem.setLabel("Start proxy");
}
}
}
public static void addTrayIcon() {
if (trayIcon != null) {
return;
}
if (SystemTray.isSupported()) {
SystemTray tray = SystemTray.getSystemTray();
trayIcon = new TrayIcon(View.loadImage("com/jpexs/decompiler/flash/gui/graphics/proxy16.png"), "JP ASDec Proxy");
trayIcon.setImageAutoSize(true);
PopupMenu trayPopup = new PopupMenu();
ActionListener trayListener = new ActionListener() {
/**
* Invoked when an action occurs.
*/
public void actionPerformed(ActionEvent e) {
if (e.getActionCommand().equals("EXIT")) {
Main.exit();
}
if (e.getActionCommand().equals("SHOW")) {
Main.showProxy();
}
if (e.getActionCommand().equals("SWITCH")) {
Main.switchProxy();
}
}
};
MenuItem showMenuItem = new MenuItem("Show proxy");
showMenuItem.setActionCommand("SHOW");
showMenuItem.addActionListener(trayListener);
trayPopup.add(showMenuItem);
stopMenuItem = new MenuItem("Start proxy");
stopMenuItem.setActionCommand("SWITCH");
stopMenuItem.addActionListener(trayListener);
trayPopup.add(stopMenuItem);
trayPopup.addSeparator();
MenuItem exitMenuItem = new MenuItem("Exit");
exitMenuItem.setActionCommand("EXIT");
exitMenuItem.addActionListener(trayListener);
trayPopup.add(exitMenuItem);
trayIcon.setPopupMenu(trayPopup);
trayIcon.addMouseListener(new MouseAdapter() {
/**
* {@inheritDoc}
*/
@Override
public void mouseClicked(MouseEvent e) {
if (e.getButton() == MouseEvent.BUTTON1) {
Main.showProxy();
}
}
});
try {
tray.add(trayIcon);
} catch (AWTException ex) {
}
}
}
public static void exit() {
Configuration.save();
System.exit(0);
}
public static void about() {
(new AboutDialog()).setVisible(true);
}
public static void autoCheckForUpdates() {
Calendar lastUpdatesCheckDate = (Calendar) Configuration.getConfig("lastUpdatesCheckDate", null);
if ((lastUpdatesCheckDate == null) || (lastUpdatesCheckDate.getTime().getTime() < Calendar.getInstance().getTime().getTime() - 1000 * 60 * 60 * 24)) {
checkForUpdates();
}
}
public static boolean checkForUpdates() {
try {
Socket sock = new Socket("code.google.com", 80);
OutputStream os = sock.getOutputStream();
os.write("GET /feeds/p/asdec/downloads/basic HTTP/1.1\r\nHost: code.google.com\r\nConnection: close\r\n\r\n".getBytes());
BufferedReader br = new BufferedReader(new InputStreamReader(sock.getInputStream()));
String s;
String response = "";
boolean start = false;
while ((s = br.readLine()) != null) {
if (start) {
response += s + "\r\n";
}
if (s.equals("")) {
start = true;
}
}
DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document doc = builder.parse(new ByteArrayInputStream(response.getBytes()));
NodeList contents = doc.getElementsByTagName("content");
for (int i = 0; i < contents.getLength(); i++) {
Node nod = contents.item(i);
String cont = nod.getTextContent().trim();
String parts[] = cont.split("\n");
boolean isUpdate = false;
for (String part : parts) {
if (part.trim().equals("Update")) {
isUpdate = true;
break;
}
}
if ((parts.length > 4) && (isUpdate)) {
String downloadName = parts[1];
String link = parts[parts.length - 2];
if (isUpdate) {
String downVersion = "NEW";
if (downloadName.startsWith(shortApplicationName + " version ")) {
downVersion = downloadName.substring((shortApplicationName + " version ").length());
}
if (link.startsWith("<a href=\"")) {
link = link.substring(link.indexOf("\"") + 1);
link = link.substring(0, link.indexOf("\""));
if (!downVersion.equals(version)) {
java.awt.Desktop desktop = null;
if (java.awt.Desktop.isDesktopSupported()) {
desktop = java.awt.Desktop.getDesktop();
if (desktop.isSupported(java.awt.Desktop.Action.BROWSE)) {
if (JOptionPane.showConfirmDialog(null, "New version of " + shortApplicationName + " is available: " + downloadName + ".\r\nDo you want to go to project web page to download it?", "New version", JOptionPane.YES_NO_OPTION, JOptionPane.INFORMATION_MESSAGE) == JOptionPane.YES_OPTION) {
java.net.URI uri = new java.net.URI(projectPage);
desktop.browse(uri);
}
} else {
desktop = null;
}
}
if (desktop == null) {
JOptionPane.showMessageDialog(null, "New version of " + shortApplicationName + " is available: " + downloadName + ".\r\nPlease go to " + projectPage + " to download it.", "New version", JOptionPane.INFORMATION_MESSAGE);
}
Configuration.setConfig("lastUpdatesCheckDate", Calendar.getInstance());
return true;
}
}
}
}
}
} catch (Exception ex) {
return false;
}
Configuration.setConfig("lastUpdatesCheckDate", Calendar.getInstance());
return false;
}
public static void initLogging(boolean debug) {
try {
Logger logger = Logger.getLogger("");
logger.setLevel(debug ? Level.CONFIG : Level.WARNING);
FileHandler fileTxt = new FileHandler("log.txt");
SimpleFormatter formatterTxt = new SimpleFormatter();
fileTxt.setFormatter(formatterTxt);
logger.addHandler(fileTxt);
if (debug) {
ConsoleHandler conHan = new ConsoleHandler();
conHan.setFormatter(formatterTxt);
logger.addHandler(conHan);
}
} catch (Exception ex) {
throw new RuntimeException("Problems with creating the log files");
}
}
}
@@ -0,0 +1,26 @@
/*
* Copyright (C) 2010-2013 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash;
/**
*
* @author JPEXS
*/
public interface PercentListener {
public void percent(int p);
}
@@ -0,0 +1,76 @@
/*
* Copyright (C) 2010-2013 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
/**
*
* @author JPEXS
*/
public class ReReadableInputStream extends InputStream {
InputStream is;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] converted;
int pos = 0;
int count = 0;
public byte[] getAllRead() {
return baos.toByteArray();
}
public int getPos() {
return pos;
}
public ReReadableInputStream(InputStream is) {
this.is = is;
}
public void setPos(int pos) throws IOException {
if (pos > count) {
skip(pos - count);
}
this.pos = pos;
}
@Override
public int read() throws IOException {
if (pos < count) {
if (converted == null) {
converted = baos.toByteArray();
}
int ret = converted[pos] & 0xff;
pos++;
return ret;
}
int i = is.read();
baos.write(i);
count++;
pos++;
converted = null;
return i;
}
@Override
public int available() throws IOException {
return (pos < count ? count - pos : 0) + is.available();
}
}
@@ -0,0 +1,509 @@
/*
* Copyright (C) 2010-2013 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash;
import SevenZip.Compression.LZMA.Encoder;
import com.jpexs.decompiler.flash.action.TagNode;
import com.jpexs.decompiler.flash.tags.DefineBitsJPEG2Tag;
import com.jpexs.decompiler.flash.tags.DefineBitsJPEG3Tag;
import com.jpexs.decompiler.flash.tags.DefineBitsJPEG4Tag;
import com.jpexs.decompiler.flash.tags.DefineBitsLossless2Tag;
import com.jpexs.decompiler.flash.tags.DefineBitsLosslessTag;
import com.jpexs.decompiler.flash.tags.DefineBitsTag;
import com.jpexs.decompiler.flash.tags.DoABCTag;
import com.jpexs.decompiler.flash.tags.JPEGTablesTag;
import com.jpexs.decompiler.flash.tags.Tag;
import com.jpexs.decompiler.flash.types.RECT;
import java.io.*;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.zip.DeflaterOutputStream;
import java.util.zip.InflaterInputStream;
import javax.imageio.ImageIO;
/**
* Class representing SWF file
*
* @author JPEXS
*/
public class SWF {
/**
* Default version of SWF file format
*/
public static final int DEFAULT_VERSION = 10;
/**
* Tags inside of file
*/
public List<Tag> tags = new ArrayList<Tag>();
/**
* Rectangle for the display
*/
public RECT displayRect;
/**
* Movie frame rate
*/
public int frameRate;
/**
* Number of frames in movie
*/
public int frameCount;
/**
* Version of SWF
*/
public int version;
/**
* Size of the file
*/
public long fileSize;
/**
* Use compression
*/
public boolean compressed = false;
/**
* Use LZMA compression
*/
public boolean lzma = false;
/**
* Compressed size of the file (LZMA)
*/
public long compressedSize;
/**
* LZMA Properties
*/
public byte lzmaProperties[];
/**
* Gets all tags with specified id
*
* @param tagId Identificator of tag type
* @return List of tags
*/
public List<Tag> getTagData(int tagId) {
List<Tag> ret = new ArrayList<Tag>();
for (Tag tag : tags) {
if (tag.getId() == tagId) {
ret.add(tag);
}
}
return ret;
}
/**
* Saves this SWF into new file
*
* @param os OutputStream to save SWF in
* @throws IOException
*/
public void saveTo(OutputStream os) throws IOException {
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
SWFOutputStream sos = new SWFOutputStream(baos, version);
sos.writeRECT(displayRect);
sos.writeUI8(0);
sos.writeUI8(frameRate);
sos.writeUI16(frameCount);
sos.writeTags(tags);
sos.writeUI16(0);
sos.close();
if (compressed && lzma) {
os.write('Z');
} else if (compressed) {
os.write('C');
} else {
os.write('F');
}
os.write('W');
os.write('S');
os.write(version);
byte data[] = baos.toByteArray();
sos = new SWFOutputStream(os, version);
sos.writeUI32(data.length + 8);
if (compressed) {
if (lzma) {
Encoder enc = new Encoder();
int val = lzmaProperties[0] & 0xFF;
int lc = val % 9;
int remainder = val / 9;
int lp = remainder % 5;
int pb = remainder / 5;
int dictionarySize = 0;
for (int i = 0; i < 4; i++) {
dictionarySize += ((int) (lzmaProperties[1 + i]) & 0xFF) << (i * 8);
}
enc.SetDictionarySize(dictionarySize);
enc.SetLcLpPb(lc, lp, pb);
baos = new ByteArrayOutputStream();
enc.SetEndMarkerMode(true);
enc.Code(new ByteArrayInputStream(data), baos, -1, -1, null);
data = baos.toByteArray();
byte udata[] = new byte[4];
udata[0] = (byte) (data.length & 0xFF);
udata[1] = (byte) ((data.length >> 8) & 0xFF);
udata[2] = (byte) ((data.length >> 16) & 0xFF);
udata[3] = (byte) ((data.length >> 24) & 0xFF);
os.write(udata);
os.write(lzmaProperties);
} else {
os = new DeflaterOutputStream(os);
}
}
os.write(data);
} finally {
if (os != null) {
os.close();
}
}
}
public SWF(InputStream is) throws IOException {
this(is, null);
}
/**
* Construct SWF from stream
*
* @param is Stream to read SWF from
* @throws IOException
*/
public SWF(InputStream is, PercentListener listener) throws IOException {
byte hdr[] = new byte[3];
is.read(hdr);
String shdr = new String(hdr);
if ((!shdr.equals("FWS")) && (!shdr.equals("CWS")) && (!shdr.equals("ZWS"))) {
throw new IOException("Invalid SWF file");
}
version = is.read();
SWFInputStream sis = new SWFInputStream(is, version, 4);
fileSize = sis.readUI32();
if (hdr[0] == 'C') {
sis = new SWFInputStream(new InflaterInputStream(is), version, 8);
compressed = true;
}
if (hdr[0] == 'Z') {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
long outSize = sis.readUI32();
int propertiesSize = 5;
lzmaProperties = new byte[propertiesSize];
if (sis.read(lzmaProperties, 0, propertiesSize) != propertiesSize) {
throw new IOException("LZMA:input .lzma file is too short");
}
SevenZip.Compression.LZMA.Decoder decoder = new SevenZip.Compression.LZMA.Decoder();
if (!decoder.SetDecoderProperties(lzmaProperties)) {
throw new IOException("LZMA:Incorrect stream properties");
}
if (!decoder.Code(sis, baos, fileSize - 8)) {
throw new IOException("LZMA:Error in data stream");
}
sis = new SWFInputStream(new ByteArrayInputStream(baos.toByteArray()), version, 8);
compressed = true;
lzma = true;
}
if (listener != null) {
sis.addPercentListener(listener);
}
sis.setPercentMax(fileSize);
displayRect = sis.readRECT();
// FIXED8 (16 bit fixed point) frameRate
int tmpFirstByetOfFrameRate = sis.readUI8();
frameRate = sis.readUI8();
frameCount = sis.readUI16();
tags = sis.readTagList(0);
}
/**
* Compress SWF file
*
* @param fis Input stream
* @param fos Output stream
*/
public static boolean fws2cws(InputStream fis, OutputStream fos) {
try {
byte swfHead[] = new byte[8];
fis.read(swfHead);
if (swfHead[0] != 'F') {
fis.close();
return false;
}
swfHead[0] = 'C';
fos.write(swfHead);
fos = new DeflaterOutputStream(fos);
int i;
while ((i = fis.read()) != -1) {
fos.write(i);
}
fis.close();
fos.close();
} catch (FileNotFoundException ex) {
return false;
} catch (IOException ex) {
return false;
}
return true;
}
/**
* Decompress SWF file
*
* @param fis Input stream
* @param fos Output stream
*/
public static boolean cws2fws(InputStream fis, OutputStream fos) {
try {
byte swfHead[] = new byte[8];
fis.read(swfHead);
InflaterInputStream iis = new InflaterInputStream(fis);
if (swfHead[0] != 'C') {
fis.close();
return false;
}
swfHead[0] = 'F';
fos.write(swfHead);
int i;
while ((i = iis.read()) != -1) {
fos.write(i);
}
fis.close();
fos.close();
} catch (FileNotFoundException ex) {
return false;
} catch (IOException ex) {
return false;
}
return true;
}
/**
* Decompress LZMA compressed SWF file
*
* @param fis Input stream
* @param fos Output stream
*/
public static boolean zws2fws(InputStream fis, OutputStream fos) {
try {
byte hdr[] = new byte[3];
fis.read(hdr);
String shdr = new String(hdr);
if (!shdr.equals("ZWS")) {
return false;
}
int version = fis.read();
SWFInputStream sis = new SWFInputStream(fis, version, 4);
long fileSize = sis.readUI32();
if (hdr[0] == 'Z') {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
long outSize = sis.readUI32();
int propertiesSize = 5;
byte lzmaProperties[] = new byte[propertiesSize];
if (sis.read(lzmaProperties, 0, propertiesSize) != propertiesSize) {
throw new IOException("LZMA:input .lzma file is too short");
}
SevenZip.Compression.LZMA.Decoder decoder = new SevenZip.Compression.LZMA.Decoder();
if (!decoder.SetDecoderProperties(lzmaProperties)) {
throw new IOException("LZMA:Incorrect stream properties");
}
if (!decoder.Code(sis, baos, fileSize - 8)) {
throw new IOException("LZMA:Error in data stream");
}
SWFOutputStream sos = new SWFOutputStream(fos, version);
sos.write("FWS".getBytes());
sos.write(version);
sos.writeUI32(fileSize);
sos.write(baos.toByteArray());
sos.close();
} else {
return false;
}
} catch (FileNotFoundException ex) {
return false;
} catch (IOException ex) {
return false;
}
return true;
}
public boolean exportActionScript(String outdir, boolean isPcode) throws Exception {
boolean asV3Found = false;
final EventListener evl = new EventListener() {
public void handleEvent(String event, Object data) {
if (event.equals("export")) {
informListeners(event, data);
}
}
};
List<DoABCTag> abcTags = new ArrayList<DoABCTag>();
for (Tag t : tags) {
if (t instanceof DoABCTag) {
abcTags.add((DoABCTag) t);
asV3Found = true;
}
}
for (int i = 0; i < abcTags.size(); i++) {
DoABCTag t = abcTags.get(i);
t.abc.addEventListener(evl);
t.abc.export(outdir, isPcode, abcTags, "tag " + (i + 1) + "/" + abcTags.size() + " ");
}
for (DoABCTag t : abcTags) {
}
if (!asV3Found) {
List<Object> list2 = new ArrayList<Object>();
list2.addAll(tags);
List<TagNode> list = TagNode.createTagList(list2);
TagNode.setExport(list, true);
return TagNode.exportNode(list, outdir, isPcode);
}
return asV3Found;
}
protected HashSet<EventListener> listeners = new HashSet<EventListener>();
public void addEventListener(EventListener listener) {
listeners.add(listener);
}
public void removeEventListener(EventListener listener) {
listeners.remove(listener);
}
protected void informListeners(String event, Object data) {
for (EventListener listener : listeners) {
listener.handleEvent(event, data);
}
}
private static String getImageFormat(byte data[]) {
if (hasErrorHeader(data)) {
return "jpg";
}
if (data.length > 2 && ((data[0] & 0xff) == 0xff) && ((data[1] & 0xff) == 0xd8)) {
return "jpg";
}
if (data.length > 6 && ((data[0] & 0xff) == 0x47) && ((data[1] & 0xff) == 0x49) && ((data[2] & 0xff) == 0x46) && ((data[3] & 0xff) == 0x38) && ((data[4] & 0xff) == 0x39) && ((data[5] & 0xff) == 0x61)) {
return "gif";
}
if (data.length > 8 && ((data[0] & 0xff) == 0x89) && ((data[1] & 0xff) == 0x50) && ((data[2] & 0xff) == 0x4e) && ((data[3] & 0xff) == 0x47) && ((data[4] & 0xff) == 0x0d) && ((data[5] & 0xff) == 0x0a) && ((data[6] & 0xff) == 0x1a) && ((data[7] & 0xff) == 0x0a)) {
return "png";
}
return "unk";
}
public static boolean hasErrorHeader(byte data[]) {
if (data.length > 4) {
if ((data[0] & 0xff) == 0xff) {
if ((data[1] & 0xff) == 0xd9) {
if ((data[2] & 0xff) == 0xff) {
if ((data[3] & 0xff) == 0xd8) {
return true;
}
}
}
}
}
return false;
}
public static void exportImages(String outdir, List<Tag> tags, JPEGTablesTag jtt) throws IOException {
for (Tag t : tags) {
if ((t instanceof DefineBitsJPEG2Tag) || (t instanceof DefineBitsJPEG3Tag) || (t instanceof DefineBitsJPEG4Tag)) {
byte imageData[] = null;
int characterID = 0;
if (t instanceof DefineBitsJPEG2Tag) {
imageData = ((DefineBitsJPEG2Tag) t).imageData;
characterID = ((DefineBitsJPEG2Tag) t).characterID;
}
if (t instanceof DefineBitsJPEG3Tag) {
imageData = ((DefineBitsJPEG3Tag) t).imageData;
characterID = ((DefineBitsJPEG3Tag) t).characterID;
}
if (t instanceof DefineBitsJPEG4Tag) {
imageData = ((DefineBitsJPEG4Tag) t).imageData;
characterID = ((DefineBitsJPEG4Tag) t).characterID;
}
FileOutputStream fos = null;
try {
fos = new FileOutputStream(outdir + File.separator + characterID + "." + getImageFormat(imageData));
if (hasErrorHeader(imageData)) {
fos.write(imageData, 4, imageData.length - 4);
} else {
fos.write(imageData);
}
} finally {
if (fos != null) {
try {
fos.close();
} catch (Exception ex) {
//ignore
}
}
}
}
if (t instanceof DefineBitsLosslessTag) {
DefineBitsLosslessTag dbl = (DefineBitsLosslessTag) t;
ImageIO.write(dbl.getImage(), "PNG", new File(outdir + File.separator + dbl.characterID + ".png"));
}
if (t instanceof DefineBitsLossless2Tag) {
DefineBitsLossless2Tag dbl = (DefineBitsLossless2Tag) t;
ImageIO.write(dbl.getImage(), "PNG", new File(outdir + File.separator + dbl.characterID + ".png"));
}
if ((jtt != null) && (t instanceof DefineBitsTag)) {
DefineBitsTag dbt = (DefineBitsTag) t;
FileOutputStream fos = null;
try {
fos = new FileOutputStream(outdir + File.separator + dbt.characterID + ".jpg");
fos.write(dbt.getFullImageData(jtt));
} finally {
if (fos != null) {
try {
fos.close();
} catch (Exception ex) {
//ignore
}
}
}
}
}
}
public void exportImages(String outdir) throws IOException {
JPEGTablesTag jtt = null;
for (Tag t : tags) {
if (t instanceof JPEGTablesTag) {
jtt = (JPEGTablesTag) t;
}
}
exportImages(outdir, tags, jtt);
}
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,865 @@
/*
* Copyright (C) 2010-2013 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc;
import com.jpexs.decompiler.flash.EventListener;
import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
import com.jpexs.decompiler.flash.abc.avm2.ConstantPool;
import com.jpexs.decompiler.flash.abc.avm2.UnknownInstructionCode;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.types.*;
import com.jpexs.decompiler.flash.abc.types.traits.Trait;
import com.jpexs.decompiler.flash.abc.types.traits.TraitMethodGetterSetter;
import com.jpexs.decompiler.flash.abc.types.traits.TraitSlotConst;
import com.jpexs.decompiler.flash.abc.types.traits.Traits;
import com.jpexs.decompiler.flash.abc.usages.*;
import com.jpexs.decompiler.flash.tags.DoABCTag;
import java.io.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Random;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Pattern;
public class ABC {
public int major_version = 0;
public int minor_version = 0;
public ConstantPool constants;
public MethodInfo method_info[];
public MetadataInfo metadata_info[];
public InstanceInfo instance_info[];
public ClassInfo class_info[];
public ScriptInfo script_info[];
public MethodBody bodies[];
private int bodyIdxFromMethodIdx[];
public long stringOffsets[];
public static String IDENT_STRING = " ";
public static final int MINORwithDECIMAL = 17;
protected HashSet<EventListener> listeners = new HashSet<EventListener>();
private static Logger logger = Logger.getLogger(ABC.class.getName());
public void addEventListener(EventListener listener) {
listeners.add(listener);
}
public void removeEventListener(EventListener listener) {
listeners.remove(listener);
}
protected void informListeners(String event, Object data) {
for (EventListener listener : listeners) {
listener.handleEvent(event, data);
}
}
public int removeTraps() {
int rem = 0;
for (MethodBody body : bodies) {
rem += body.removeTraps(constants);
}
return rem;
}
public int removeDeadCode() {
int rem = 0;
for (MethodBody body : bodies) {
rem += body.removeDeadCode(constants);
}
return rem;
}
public void restoreControlFlow() {
for (MethodBody body : bodies) {
body.restoreControlFlow(constants);
}
}
public int deobfuscateIdentifiers(HashMap<String, String> namesMap) {
int ret = 0;
for (int i = 1; i < instance_info.length; i++) {
if (instance_info[i].name_index != 0) {
if (deobfuscateName(namesMap, constants.constant_multiname[instance_info[i].name_index].name_index, true)) {
ret++;
}
}
if (instance_info[i].super_index != 0) {
if (deobfuscateName(namesMap, constants.constant_multiname[instance_info[i].super_index].name_index, true)) {
ret++;
}
}
}
for (int i = 1; i < constants.constant_multiname.length; i++) {
if (deobfuscateName(namesMap, constants.constant_multiname[i].name_index, false)) {
ret++;
}
}
for (int i = 1; i < constants.constant_namespace.length; i++) {
if (deobfuscateNameSpace(namesMap, constants.constant_namespace[i].name_index)) {
ret++;
}
}
return ret;
}
public ABC(InputStream is) throws IOException {
ABCInputStream ais = new ABCInputStream(is);
minor_version = ais.readU16();
major_version = ais.readU16();
logger.log(Level.FINE, "ABC minor_version: {0}, major_version: {1}", new Object[]{minor_version, major_version});
constants = new ConstantPool();
//constant integers
int constant_int_pool_count = ais.readU30();
constants.constant_int = new long[constant_int_pool_count];
for (int i = 1; i < constant_int_pool_count; i++) { //index 0 not used. Values 1..n-1
constants.constant_int[i] = ais.readS32();
}
//constant unsigned integers
int constant_uint_pool_count = ais.readU30();
constants.constant_uint = new long[constant_uint_pool_count];
for (int i = 1; i < constant_uint_pool_count; i++) { //index 0 not used. Values 1..n-1
constants.constant_uint[i] = ais.readU32();
}
//constant double
int constant_double_pool_count = ais.readU30();
constants.constant_double = new double[constant_double_pool_count];
for (int i = 1; i < constant_double_pool_count; i++) { //index 0 not used. Values 1..n-1
constants.constant_double[i] = ais.readDouble();
}
//constant decimal
if (minor_version >= MINORwithDECIMAL) {
int constant_decimal_pool_count = ais.readU30();
constants.constant_decimal = new Decimal[constant_decimal_pool_count];
for (int i = 1; i < constant_decimal_pool_count; i++) { //index 0 not used. Values 1..n-1
constants.constant_decimal[i] = ais.readDecimal();
}
} else {
constants.constant_decimal = new Decimal[0];
}
//constant string
int constant_string_pool_count = ais.readU30();
constants.constant_string = new String[constant_string_pool_count];
stringOffsets = new long[constant_string_pool_count];
constants.constant_string[0] = "";
for (int i = 1; i < constant_string_pool_count; i++) { //index 0 not used. Values 1..n-1
long pos = ais.getPosition();
constants.constant_string[i] = ais.readString();
stringOffsets[i] = pos;
}
//constant namespace
int constant_namespace_pool_count = ais.readU30();
constants.constant_namespace = new Namespace[constant_namespace_pool_count];
for (int i = 1; i < constant_namespace_pool_count; i++) { //index 0 not used. Values 1..n-1
constants.constant_namespace[i] = ais.readNamespace();
}
//constant namespace set
int constant_namespace_set_pool_count = ais.readU30();
constants.constant_namespace_set = new NamespaceSet[constant_namespace_set_pool_count];
for (int i = 1; i < constant_namespace_set_pool_count; i++) { //index 0 not used. Values 1..n-1
constants.constant_namespace_set[i] = new NamespaceSet();
int namespace_count = ais.readU30();
constants.constant_namespace_set[i].namespaces = new int[namespace_count];
for (int j = 0; j < namespace_count; j++) {
constants.constant_namespace_set[i].namespaces[j] = ais.readU30();
}
}
//constant multiname
int constant_multiname_pool_count = ais.readU30();
constants.constant_multiname = new Multiname[constant_multiname_pool_count];
for (int i = 1; i < constant_multiname_pool_count; i++) { //index 0 not used. Values 1..n-1
constants.constant_multiname[i] = ais.readMultiname();
}
//method info
int methods_count = ais.readU30();
method_info = new MethodInfo[methods_count];
bodyIdxFromMethodIdx = new int[methods_count];
for (int i = 0; i < methods_count; i++) {
method_info[i] = ais.readMethodInfo();
bodyIdxFromMethodIdx[i] = -1;
}
//metadata info
int metadata_count = ais.readU30();
metadata_info = new MetadataInfo[metadata_count];
for (int i = 0; i < metadata_count; i++) {
int name_index = ais.readU30();
int values_count = ais.readU30();
int keys[] = new int[values_count];
for (int v = 0; v < values_count; v++) {
keys[v] = ais.readU30();
}
int values[] = new int[values_count];
for (int v = 0; v < values_count; v++) {
values[v] = ais.readU30();
}
metadata_info[i] = new MetadataInfo(name_index, keys, values);
}
int class_count = ais.readU30();
instance_info = new InstanceInfo[class_count];
for (int i = 0; i < class_count; i++) {
instance_info[i] = ais.readInstanceInfo();
}
class_info = new ClassInfo[class_count];
for (int i = 0; i < class_count; i++) {
ClassInfo ci = new ClassInfo();
ci.cinit_index = ais.readU30();
ci.static_traits = ais.readTraits();
class_info[i] = ci;
}
int script_count = ais.readU30();
script_info = new ScriptInfo[script_count];
for (int i = 0; i < script_count; i++) {
ScriptInfo si = new ScriptInfo();
si.init_index = ais.readU30();
si.traits = ais.readTraits();
script_info[i] = si;
}
int bodies_count = ais.readU30();
bodies = new MethodBody[bodies_count];
for (int i = 0; i < bodies_count; i++) {
MethodBody mb = new MethodBody();
mb.method_info = ais.readU30();
mb.max_stack = ais.readU30();
mb.max_regs = ais.readU30();
mb.init_scope_depth = ais.readU30();
mb.max_scope_depth = ais.readU30();
int code_length = ais.readU30();
mb.codeBytes = new byte[code_length];
ais.read(mb.codeBytes);
try {
mb.code = new AVM2Code(new ByteArrayInputStream(mb.codeBytes));
} catch (UnknownInstructionCode re) {
mb.code = new AVM2Code();
Logger.getLogger(ABC.class.getName()).log(Level.SEVERE, null, re);
}
mb.code.compact();
int ex_count = ais.readU30();
mb.exceptions = new ABCException[ex_count];
for (int j = 0; j < ex_count; j++) {
ABCException abce = new ABCException();
abce.start = ais.readU30();
abce.end = ais.readU30();
abce.target = ais.readU30();
abce.type_index = ais.readU30();
abce.name_index = ais.readU30();
mb.exceptions[j] = abce;
}
mb.traits = ais.readTraits();
bodies[i] = mb;
method_info[mb.method_info].setBody(mb);
bodyIdxFromMethodIdx[mb.method_info] = i;
}
loadNamespaceMap();
/* for(ScriptInfo si:script_info){
System.out.println("--------------------------------------------");
System.out.println(findBody(si.init_index).toString(true, false, -1, this, constants, method_info,new Stack<TreeItem>(),false,false));
System.out.println("sitrait:"+si.traits.toString(this));
}*/
/*try {
MethodBody body=new MethodBody();
AVM2Code code=ASM3Parser.parse(new FileInputStream("D:\\tst2.txt"), constants, body);
//code.removeTraps(constants, body);
code.restoreControlFlow(constants, body);
FileOutputStream fos=new FileOutputStream("D:\\tst3.txt");
fos.write(Highlighting.stripHilights(code.toASMSource(constants, body)).getBytes());
fos.close();
System.out.println(code.toSource(false, 0, this, constants, method_info, body, new HashMap<Integer,String>(), new Stack<TreeItem>(), false, null, null));
System.exit(0);
} catch (Exception ex) {
Logger.getLogger(ABC.class.getName()).log(Level.SEVERE, null, ex);
}*/
}
public void saveToStream(OutputStream os) throws IOException {
ABCOutputStream aos = new ABCOutputStream(os);
aos.writeU16(minor_version);
aos.writeU16(major_version);
aos.writeU30(constants.constant_int.length);
for (int i = 1; i < constants.constant_int.length; i++) {
aos.writeS32(constants.constant_int[i]);
}
aos.writeU30(constants.constant_uint.length);
for (int i = 1; i < constants.constant_uint.length; i++) {
aos.writeU32(constants.constant_uint[i]);
}
aos.writeU30(constants.constant_double.length);
for (int i = 1; i < constants.constant_double.length; i++) {
aos.writeDouble(constants.constant_double[i]);
}
if (minor_version >= MINORwithDECIMAL) {
aos.writeU30(constants.constant_decimal.length);
for (int i = 1; i < constants.constant_decimal.length; i++) {
aos.writeDecimal(constants.constant_decimal[i]);
}
}
aos.writeU30(constants.constant_string.length);
for (int i = 1; i < constants.constant_string.length; i++) {
aos.writeString(constants.constant_string[i]);
}
aos.writeU30(constants.constant_namespace.length);
for (int i = 1; i < constants.constant_namespace.length; i++) {
aos.writeNamespace(constants.constant_namespace[i]);
}
aos.writeU30(constants.constant_namespace_set.length);
for (int i = 1; i < constants.constant_namespace_set.length; i++) {
aos.writeU30(constants.constant_namespace_set[i].namespaces.length);
for (int j = 0; j < constants.constant_namespace_set[i].namespaces.length; j++) {
aos.writeU30(constants.constant_namespace_set[i].namespaces[j]);
}
}
aos.writeU30(constants.constant_multiname.length);
for (int i = 1; i < constants.constant_multiname.length; i++) {
aos.writeMultiname(constants.constant_multiname[i]);
}
aos.writeU30(method_info.length);
for (int i = 0; i < method_info.length; i++) {
aos.writeMethodInfo(method_info[i]);
}
aos.writeU30(metadata_info.length);
for (int i = 0; i < metadata_info.length; i++) {
aos.writeU30(metadata_info[i].name_index);
aos.writeU30(metadata_info[i].values.length);
for (int j = 0; j < metadata_info[i].values.length; j++) {
aos.writeU30(metadata_info[i].keys[j]);
}
for (int j = 0; j < metadata_info[i].values.length; j++) {
aos.writeU30(metadata_info[i].values[j]);
}
}
aos.writeU30(class_info.length);
for (int i = 0; i < instance_info.length; i++) {
aos.writeInstanceInfo(instance_info[i]);
}
for (int i = 0; i < class_info.length; i++) {
aos.writeU30(class_info[i].cinit_index);
aos.writeTraits(class_info[i].static_traits);
}
aos.writeU30(script_info.length);
for (int i = 0; i < script_info.length; i++) {
aos.writeU30(script_info[i].init_index);
aos.writeTraits(script_info[i].traits);
}
aos.writeU30(bodies.length);
for (int i = 0; i < bodies.length; i++) {
aos.writeU30(bodies[i].method_info);
aos.writeU30(bodies[i].max_stack);
aos.writeU30(bodies[i].max_regs);
aos.writeU30(bodies[i].init_scope_depth);
aos.writeU30(bodies[i].max_scope_depth);
byte codeBytes[] = bodies[i].code.getBytes();
aos.writeU30(codeBytes.length);
try {
aos.write(codeBytes);
} catch (NotSameException ex) {
System.out.println(bodies[i].code.toString(constants));
System.exit(0);
return;
}
aos.writeU30(bodies[i].exceptions.length);
for (int j = 0; j < bodies[i].exceptions.length; j++) {
aos.writeU30(bodies[i].exceptions[j].start);
aos.writeU30(bodies[i].exceptions[j].end);
aos.writeU30(bodies[i].exceptions[j].target);
aos.writeU30(bodies[i].exceptions[j].type_index);
aos.writeU30(bodies[i].exceptions[j].name_index);
}
aos.writeTraits(bodies[i].traits);
}
}
public MethodBody findBody(int methodInfo) {
if (methodInfo < 0) {
return null;
}
return method_info[methodInfo].getBody();
}
public int findBodyIndex(int methodInfo) {
if (methodInfo == -1) {
return -1;
}
return bodyIdxFromMethodIdx[methodInfo];
}
public MethodBody findBodyByClassAndName(String className, String methodName) {
for (int i = 0; i < instance_info.length; i++) {
if (className.equals(constants.constant_multiname[instance_info[i].name_index].getName(constants, new ArrayList<String>()))) {
for (Trait t : instance_info[i].instance_traits.traits) {
if (t instanceof TraitMethodGetterSetter) {
TraitMethodGetterSetter t2 = (TraitMethodGetterSetter) t;
if (methodName.equals(t2.getName(this).getName(constants, new ArrayList<String>()))) {
for (MethodBody body : bodies) {
if (body.method_info == t2.method_info) {
return body;
}
}
}
}
}
//break;
}
}
for (int i = 0; i < class_info.length; i++) {
if (className.equals(constants.constant_multiname[instance_info[i].name_index].getName(constants, new ArrayList<String>()))) {
for (Trait t : class_info[i].static_traits.traits) {
if (t instanceof TraitMethodGetterSetter) {
TraitMethodGetterSetter t2 = (TraitMethodGetterSetter) t;
if (methodName.equals(t2.getName(this).getName(constants, new ArrayList<String>()))) {
for (MethodBody body : bodies) {
if (body.method_info == t2.method_info) {
return body;
}
}
}
}
}
//break;
}
}
return null;
}
public static String addTabs(String s, int tabs) {
String parts[] = s.split("\r\n");
if (!s.contains("\r\n")) {
parts = s.split("\n");
}
StringBuilder ret = new StringBuilder();
for (int i = 0; i < parts.length; i++) {
for (int t = 0; t < tabs; t++) {
ret.append(IDENT_STRING);
}
ret.append(parts[i]);
if (i < parts.length - 1) {
ret.append("\r\n");
}
}
return ret.toString();
}
public Trait findTraitByTraitId(int classIndex, int traitId) {
if (traitId < class_info[classIndex].static_traits.traits.length) {
return class_info[classIndex].static_traits.traits[traitId];
} else if (traitId < class_info[classIndex].static_traits.traits.length + instance_info[classIndex].instance_traits.traits.length) {
traitId -= class_info[classIndex].static_traits.traits.length;
return instance_info[classIndex].instance_traits.traits[traitId];
} else {
return null; //Can be class or instance initializer
}
}
public int findMethodIdByTraitId(int classIndex, int traitId) {
if (traitId < class_info[classIndex].static_traits.traits.length) {
if (class_info[classIndex].static_traits.traits[traitId] instanceof TraitMethodGetterSetter) {
return ((TraitMethodGetterSetter) class_info[classIndex].static_traits.traits[traitId]).method_info;
} else {
return -1;
}
} else if (traitId < class_info[classIndex].static_traits.traits.length + instance_info[classIndex].instance_traits.traits.length) {
traitId -= class_info[classIndex].static_traits.traits.length;
if (instance_info[classIndex].instance_traits.traits[traitId] instanceof TraitMethodGetterSetter) {
return ((TraitMethodGetterSetter) instance_info[classIndex].instance_traits.traits[traitId]).method_info;
} else {
return -1;
}
} else {
traitId -= class_info[classIndex].static_traits.traits.length + instance_info[classIndex].instance_traits.traits.length;
if (traitId == 0) {
return instance_info[classIndex].iinit_index;
} else if (traitId == 1) {
return class_info[classIndex].cinit_index;
} else {
return -1;
}
}
}
/* Map from multiname index of namespace value to namespace name**/
private HashMap<String, String> namespaceMap;
private void loadNamespaceMap() {
namespaceMap = new HashMap<String, String>();
for (ScriptInfo si : script_info) {
for (Trait t : si.traits.traits) {
if (t instanceof TraitSlotConst) {
TraitSlotConst s = ((TraitSlotConst) t);
if (s.isNamespace()) {
String key = constants.constant_namespace[s.value_index].getName(constants);
String val = constants.constant_multiname[s.name_index].getNameWithNamespace(constants);
namespaceMap.put(key, val);
}
}
}
}
}
public String builtInNs(String ns) {
if (ns.equals("http://www.adobe.com/2006/actionscript/flash/proxy")) {
return "flash.utils.flash_proxy";
}
if (ns.equals("http://adobe.com/AS3/2006/builtin")) {
return "-";
}
return null;
}
public String nsValueToName(String value) {
if (namespaceMap.containsKey(value)) {
return namespaceMap.get(value);
} else {
String ns = builtInNs(value);
if (ns == null) {
return "";
} else {
return ns;
}
}
}
public void export(String directory, boolean pcode, List<DoABCTag> abcList) throws IOException {
export(directory, pcode, abcList, "");
}
public void export(String directory, boolean pcode, List<DoABCTag> abcList, String abcStr) throws IOException {
for (int i = 0; i < script_info.length; i++) {
String path = script_info[i].getPath(this);
String packageName = path.substring(0, path.lastIndexOf("."));
if (packageName.equals("")) {
path = path.substring(1);
}
String cnt = "";
if (script_info.length > 1) {
cnt = "script " + (i + 1) + "/" + script_info.length + " ";
}
String exStr = "Exporting " + abcStr + cnt + path + " ...";
informListeners("export", exStr);
script_info[i].export(this, abcList, directory, pcode);
}
}
public void dump(OutputStream os) {
PrintStream output = new PrintStream(os);
constants.dump(output);
for (int i = 0; i < method_info.length; i++) {
output.println("MethodInfo[" + i + "]:" + method_info[i].toString(constants, new ArrayList<String>()));
}
for (int i = 0; i < metadata_info.length; i++) {
output.println("MetadataInfo[" + i + "]:" + metadata_info[i].toString(constants));
}
for (int i = 0; i < instance_info.length; i++) {
output.println("InstanceInfo[" + i + "]:" + instance_info[i].toString(this, new ArrayList<String>()));
}
for (int i = 0; i < class_info.length; i++) {
output.println("ClassInfo[" + i + "]:" + class_info[i].toString(this, new ArrayList<String>()));
}
for (int i = 0; i < script_info.length; i++) {
output.println("ScriptInfo[" + i + "]:" + script_info[i].toString(this, new ArrayList<String>()));
}
for (int i = 0; i < bodies.length; i++) {
output.println("MethodBody[" + i + "]:"); //+ bodies[i].toString(this, constants, method_info));
}
}
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",
"interface", "internal", "is", "native", "new", "null", "override", "package", "private", "protected", "public",
"return", "set", "super", "switch", "this", "throw", "true", "try", "typeof", "use", "var", /*"void",*/ "while",
"with", "dynamic", "default", "final", "in"};
public static final String validFirstCharacters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_";
public static final String validNextCharacters = validFirstCharacters + "0123456789";
public static final String validNsCharacters = ".:$";
public static final String fooCharacters = "bcdfghjklmnpqrstvwz";
public static final String fooJoinCharacters = "aeiouy";
private HashMap<String, String> deobfuscated = new HashMap<String, String>();
private Random rnd = new Random();
private final int DEFAULT_FOO_SIZE = 10;
private String fooString(String orig, boolean firstUppercase, int rndSize) {
boolean exists;
String ret;
loopfoo:
do {
exists = false;
int len = 3 + rnd.nextInt(rndSize - 3);
ret = "";
for (int i = 0; i < len; i++) {
String c = "";
if ((i % 2) == 0) {
c = "" + fooCharacters.charAt(rnd.nextInt(fooCharacters.length()));
} else {
c = "" + fooJoinCharacters.charAt(rnd.nextInt(fooJoinCharacters.length()));
}
if (i == 0 && firstUppercase) {
c = c.toUpperCase();
}
ret += c;
}
for (int i = 1; i < constants.constant_string.length; i++) {
if (constants.constant_string[i].equals(ret)) {
exists = true;
rndSize = rndSize + 1;
continue loopfoo;
}
}
if (isReserved(ret)) {
exists = true;
rndSize = rndSize + 1;
continue;
}
if (deobfuscated.containsValue(ret)) {
exists = true;
rndSize = rndSize + 1;
continue;
}
} while (exists);
deobfuscated.put(orig, ret);
return ret;
}
private boolean isReserved(String s) {
for (String rw : reservedWords) {
if (rw.equals(s.trim())) {
return true;
}
}
return false;
}
private boolean isValidNSPart(String s) {
boolean isValid = true;
if (isReserved(s)) {
isValid = false;
}
if (isValid) {
for (int i = 0; i < s.length(); i++) {
if (s.charAt(i) > 127) {
isValid = false;
break;
}
}
}
if (isValid) {
Pattern pat = Pattern.compile("^([" + Pattern.quote(validFirstCharacters) + "]" + "[" + Pattern.quote(validFirstCharacters + validNextCharacters + validNsCharacters) + "]*)*$");
if (!pat.matcher(s).matches()) {
isValid = false;
}
}
return isValid;
}
public boolean deobfuscateNameSpace(HashMap<String, String> namesMap, int strIndex) {
if (strIndex <= 0) {
return false;
}
String s = constants.constant_string[strIndex];
boolean isValid = isValidNSPart(s);
if (!isValid) {
if (namesMap.containsKey(s)) {
constants.constant_string[strIndex] = namesMap.get(s);
} else {
String parts[] = null;
if (s.contains(".")) {
parts = s.split("\\.");
} else {
parts = new String[]{s};
}
String ret = "";
for (int p = 0; p < parts.length; p++) {
if (p > 0) {
ret += ".";
}
if (!isValidNSPart(parts[p])) {
ret += fooString(constants.constant_string[strIndex], false, DEFAULT_FOO_SIZE);
} else {
ret += parts[p];
}
}
constants.constant_string[strIndex] = ret;
namesMap.put(s, constants.constant_string[strIndex]);
}
}
return !isValid;
}
public boolean deobfuscateName(HashMap<String, String> namesMap, int strIndex, boolean firstUppercase) {
if (strIndex <= 0) {
return false;
}
String s = constants.constant_string[strIndex];
boolean isValid = true;
if (isReserved(s)) {
isValid = false;
}
if (isValid) {
for (int i = 0; i < s.length(); i++) {
if (s.charAt(i) > 127) {
isValid = false;
break;
}
}
}
if (isValid) {
Pattern pat = Pattern.compile("^[" + Pattern.quote(validFirstCharacters) + "]" + "[" + Pattern.quote(validFirstCharacters + validNextCharacters) + "]*$");
if (!pat.matcher(s).matches()) {
isValid = false;
}
}
if (!isValid) {
if (namesMap.containsKey(s)) {
constants.constant_string[strIndex] = namesMap.get(s);
} else {
constants.constant_string[strIndex] = fooString(constants.constant_string[strIndex], firstUppercase, DEFAULT_FOO_SIZE);
namesMap.put(s, constants.constant_string[strIndex]);
}
}
return !isValid;
}
private void checkMultinameUsedInMethod(int multinameIndex, int methodInfo, List<MultinameUsage> ret, int classIndex, int traitIndex, boolean isStatic, boolean isInitializer, Traits traits, int parentTraitIndex) {
for (int p = 0; p < method_info[methodInfo].param_types.length; p++) {
if (method_info[methodInfo].param_types[p] == multinameIndex) {
ret.add(new MethodParamsMultinameUsage(multinameIndex, classIndex, traitIndex, isStatic, isInitializer, traits, parentTraitIndex));
break;
}
}
if (method_info[methodInfo].ret_type == multinameIndex) {
ret.add(new MethodReturnTypeMultinameUsage(multinameIndex, classIndex, traitIndex, isStatic, isInitializer, traits, parentTraitIndex));
}
MethodBody body = findBody(methodInfo);
if (body != null) {
findMultinameUsageInTraits(body.traits, multinameIndex, isStatic, classIndex, ret, traitIndex);
for (ABCException e : body.exceptions) {
if ((e.name_index == multinameIndex) || (e.type_index == multinameIndex)) {
ret.add(new MethodBodyMultinameUsage(multinameIndex, classIndex, traitIndex, isStatic, isInitializer, traits, parentTraitIndex));
return;
}
}
for (AVM2Instruction ins : body.code.code) {
for (int o = 0; o < ins.definition.operands.length; o++) {
if (ins.definition.operands[o] == AVM2Code.DAT_MULTINAME_INDEX) {
if (ins.operands[o] == multinameIndex) {
ret.add(new MethodBodyMultinameUsage(multinameIndex, classIndex, traitIndex, isStatic, isInitializer, traits, parentTraitIndex));
return;
}
}
}
}
}
}
private void findMultinameUsageInTraits(Traits traits, int multinameIndex, boolean isStatic, int classIndex, List<MultinameUsage> ret, int parentTraitIndex) {
for (int t = 0; t < traits.traits.length; t++) {
if (traits.traits[t] instanceof TraitSlotConst) {
TraitSlotConst tsc = (TraitSlotConst) traits.traits[t];
if (tsc.name_index == multinameIndex) {
ret.add(new ConstVarNameMultinameUsage(multinameIndex, classIndex, t, isStatic, traits, parentTraitIndex));
}
if (tsc.type_index == multinameIndex) {
ret.add(new ConstVarTypeMultinameUsage(multinameIndex, classIndex, t, isStatic, traits, parentTraitIndex));
}
}
if (traits.traits[t] instanceof TraitMethodGetterSetter) {
TraitMethodGetterSetter tmgs = (TraitMethodGetterSetter) traits.traits[t];
if (tmgs.name_index == multinameIndex) {
ret.add(new MethodNameMultinameUsage(multinameIndex, classIndex, t, isStatic, false, traits, parentTraitIndex));
}
checkMultinameUsedInMethod(multinameIndex, tmgs.method_info, ret, classIndex, t, isStatic, false, traits, parentTraitIndex);
}
}
}
public List<MultinameUsage> findMultinameUsage(int multinameIndex) {
List<MultinameUsage> ret = new ArrayList<MultinameUsage>();
if (multinameIndex == 0) {
return ret;
}
for (int c = 0; c < instance_info.length; c++) {
if (instance_info[c].name_index == multinameIndex) {
ret.add(new ClassNameMultinameUsage(multinameIndex, c));
}
if (instance_info[c].super_index == multinameIndex) {
ret.add(new ExtendsMultinameUsage(multinameIndex, c));
}
for (int i = 0; i < instance_info[c].interfaces.length; i++) {
if (instance_info[c].interfaces[i] == multinameIndex) {
ret.add(new ImplementsMultinameUsage(multinameIndex, c));
}
}
checkMultinameUsedInMethod(multinameIndex, instance_info[c].iinit_index, ret, c, 0, false, true, null, -1);
checkMultinameUsedInMethod(multinameIndex, class_info[c].cinit_index, ret, c, 0, true, true, null, -1);
findMultinameUsageInTraits(instance_info[c].instance_traits, multinameIndex, false, c, ret, -1);
findMultinameUsageInTraits(class_info[c].static_traits, multinameIndex, true, c, ret, -1);
}
loopm:
for (int m = 1; m < constants.constant_multiname.length; m++) {
if (constants.constant_multiname[m].kind == Multiname.TYPENAME) {
if (constants.constant_multiname[m].qname_index == multinameIndex) {
ret.add(new TypeNameMultinameUsage(m));
continue;
}
for (int mp : constants.constant_multiname[m].params) {
if (mp == multinameIndex) {
ret.add(new TypeNameMultinameUsage(m));
continue loopm;
}
}
}
}
return ret;
}
public void autoFillAllBodyParams() {
for (int i = 0; i < bodies.length; i++) {
bodies[i].autoFillStats(this);
}
}
}
@@ -0,0 +1,377 @@
/*
* Copyright (C) 2010-2013 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc;
import com.jpexs.decompiler.flash.abc.types.*;
import com.jpexs.decompiler.flash.abc.types.traits.*;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
public class ABCInputStream extends InputStream {
private static final int CLASS_PROTECTED_NS = 8;
private static final int ATTR_METADATA = 4;
private InputStream is;
private long bytesRead = 0;
private ByteArrayOutputStream bufferOs = null;
public static boolean DEBUG_READ = false;
public void startBuffer() {
bufferOs = new ByteArrayOutputStream();
}
public byte[] stopBuffer() {
if (bufferOs == null) {
return new byte[0];
}
byte ret[] = bufferOs.toByteArray();
bufferOs = null;
return ret;
}
public ABCInputStream(InputStream is) {
this.is = is;
}
@Override
public int read() throws IOException {
bytesRead++;
int i = is.read();
if (DEBUG_READ) {
System.out.println("Read:0x" + Integer.toHexString(i));
}
if (bufferOs != null) {
if (i != -1) {
bufferOs.write(i);
}
}
return i;
}
@Override
public int read(byte[] b) throws IOException {
int currBytesRead = is.read(b);
bytesRead += currBytesRead;
if (DEBUG_READ) {
StringBuilder sb = new StringBuilder("Read[");
sb.append(currBytesRead);
sb.append('/');
sb.append(b.length);
sb.append("]: ");
for (int jj = 0; jj < currBytesRead; jj++) {
sb.append("0x");
sb.append(Integer.toHexString(b[jj]));
sb.append(' ');
}
System.out.println(sb.toString());
}
if (bufferOs != null) {
if (currBytesRead > 0) {
bufferOs.write(b, 0, currBytesRead);
}
}
return currBytesRead;
}
;
public int readU8() throws IOException {
return read();
}
public int readU32() throws IOException {
int i;
int ret = 0;
int bytePos = 0;
int byteCount = 0;
boolean nextByte;
do {
i = read();
nextByte = (i >> 7) == 1;
i = i & 0x7f;
ret = ret + (i << bytePos);
byteCount++;
bytePos += 7;
} while (nextByte);
return ret;
}
public int readU30() throws IOException {
return readU32();
}
public int readS24() throws IOException {
int ret = (read()) + (read() << 8) + (read() << 16);
if ((ret >> 23) == 1) {
ret = ret | 0xff000000;
}
return ret;
}
public int readU16() throws IOException {
return (read()) + (read() << 8);
}
public long readS32() throws IOException {
int i;
long ret = 0;
int bytePos = 0;
int byteCount = 0;
boolean nextByte;
do {
i = read();
nextByte = (i >> 7) == 1;
i = i & 0x7f;
ret = ret + (i << bytePos);
byteCount++;
bytePos += 7;
if (bytePos == 35) {
if ((ret >> 31) == 1) {
ret = -(ret & 0x7fffffff);
}
break;
}
} while (nextByte);
return ret;
}
@Override
public int available() throws IOException {
return is.available();
}
public final long readLong() throws IOException {
byte readBuffer[] = safeRead(8);
return (((long) readBuffer[7] << 56)
+ ((long) (readBuffer[6] & 255) << 48)
+ ((long) (readBuffer[5] & 255) << 40)
+ ((long) (readBuffer[4] & 255) << 32)
+ ((long) (readBuffer[3] & 255) << 24)
+ ((readBuffer[2] & 255) << 16)
+ ((readBuffer[1] & 255) << 8)
+ ((readBuffer[0] & 255)));
}
public double readDouble() throws IOException {
long el = readLong();
double ret = Double.longBitsToDouble(el);
return ret;
}
private byte[] safeRead(int count) throws IOException {
byte ret[] = new byte[count];
for (int i = 0; i < count; i++) {
ret[i] = (byte) read();
}
return ret;
}
public Namespace readNamespace() throws IOException {
int kind = read();
int name_index = 0;
for (int k = 0; k < Namespace.nameSpaceKinds.length; k++) {
if (Namespace.nameSpaceKinds[k] == kind) {
name_index = readU30();
break;
}
}
return new Namespace(kind, name_index);
}
public Multiname readMultiname() throws IOException {
int kind = readU8();
int namespace_index = -1;
int name_index = -1;
int namespace_set_index = -1;
int qname_index = -1;
List<Integer> params = new ArrayList<Integer>();
if ((kind == 7) || (kind == 0xd)) { // CONSTANT_QName and CONSTANT_QNameA.
namespace_index = readU30();
name_index = readU30();
} else if ((kind == 0xf) || (kind == 0x10)) { //CONSTANT_RTQName and CONSTANT_RTQNameA
name_index = readU30();
} else if ((kind == 0x11) || (kind == 0x12))//kind==0x11,0x12 nothing CONSTANT_RTQNameL and CONSTANT_RTQNameLA.
{
} else if ((kind == 9) || (kind == 0xe)) { // CONSTANT_Multiname and CONSTANT_MultinameA.
name_index = readU30();
namespace_set_index = readU30();
} else if ((kind == 0x1B) || (kind == 0x1C)) { //CONSTANT_MultinameL and CONSTANT_MultinameLA
namespace_set_index = readU30();
} else if (kind == 0x1D) {
//Constant_TypeName
qname_index = readU30(); //Multiname index!!!
int paramsLength = readU30();
for (int i = 0; i < paramsLength; i++) {
params.add(readU30()); //multiname indices!
}
} else {
System.err.println("Unknown kind of Multiname:0x" + Integer.toHexString(kind));
System.exit(1);
}
return new Multiname(kind, name_index, namespace_index, namespace_set_index, qname_index, params);
}
public MethodInfo readMethodInfo() throws IOException {
int param_count = readU30();
int ret_type = readU30();
int param_types[] = new int[param_count];
for (int i = 0; i < param_count; i++) {
param_types[i] = readU30();
}
int name_index = readU30();
int flags = read();
//// 1=need_arguments, 2=need_activation, 4=need_rest 8=has_optional (16=ignore_rest, 32=explicit,) 64=setsdxns, 128=has_paramnames
ValueKind optional[] = new ValueKind[0];
if ((flags & 8) == 8) { //if has_optional
int optional_count = readU30();
optional = new ValueKind[optional_count];
for (int i = 0; i < optional_count; i++) {
optional[i] = new ValueKind(readU30(), read());
}
}
int param_names[] = new int[param_count];
if ((flags & 128) == 128) { //if has_paramnames
for (int i = 0; i < param_count; i++) {
param_names[i] = readU30();
}
}
return new MethodInfo(param_types, ret_type, name_index, flags, optional, param_names);
}
public Trait readTrait() throws IOException {
long pos = getPosition();
startBuffer();
int name_index = readU30();
int kind = read();
int kindType = 0xf & kind;
int kindFlags = kind >> 4;
Trait trait;
switch (kindType) {
case 0: //slot
case 6: //const
TraitSlotConst t1 = new TraitSlotConst();
t1.slot_id = readU30();
t1.type_index = readU30();
t1.value_index = readU30();
if (t1.value_index != 0) {
t1.value_kind = read();
}
trait = t1;
break;
case 1: //method
case 2: //getter
case 3: //setter
TraitMethodGetterSetter t2 = new TraitMethodGetterSetter();
t2.disp_id = readU30();
t2.method_info = readU30();
trait = t2;
break;
case 4: //class
TraitClass t3 = new TraitClass();
t3.slot_id = readU30();
t3.class_info = readU30();
trait = t3;
break;
case 5: //function
TraitFunction t4 = new TraitFunction();
t4.slot_index = readU30();
t4.method_info = readU30();
trait = t4;
break;
default:
throw new IOException("Unknown trait kind:" + kind);
}
trait.fileOffset = pos;
trait.kindType = kindType;
trait.kindFlags = kindFlags;
trait.name_index = name_index;
if ((kindFlags & ATTR_METADATA) != 0) {
int metadata_count = readU30();
trait.metadata = new int[metadata_count];
for (int i = 0; i < metadata_count; i++) {
trait.metadata[i] = readU30();
}
}
trait.bytes = stopBuffer();
return trait;
}
public Traits readTraits() throws IOException {
int count = readU30();
Traits traits = new Traits();
traits.traits = new Trait[count];
for (int i = 0; i < count; i++) {
traits.traits[i] = readTrait();
}
return traits;
}
public byte[] readBytes(int count) throws IOException {
byte ret[] = new byte[count];
for (int i = 0; i < count; i++) {
ret[i] = (byte) read();
}
return ret;
}
public Decimal readDecimal() throws IOException {
byte data[] = readBytes(16);
return new Decimal(data);
}
public InstanceInfo readInstanceInfo() throws IOException {
InstanceInfo ret = new InstanceInfo();
ret.name_index = readU30();
ret.super_index = readU30();
ret.flags = read();
if ((ret.flags & CLASS_PROTECTED_NS) != 0) {
ret.protectedNS = readU30();
}
int interfaces_count = readU30();
ret.interfaces = new int[interfaces_count];
for (int i = 0; i < interfaces_count; i++) {
ret.interfaces[i] = readU30();
}
ret.iinit_index = readU30();
ret.instance_traits = readTraits();
return ret;
}
public String readString() throws IOException {
int length = readU30();
return new String(safeRead(length), "utf8");
}
/*public void markStart(){
bytesRead=0;
}*/
public long getPosition() {
return bytesRead;
}
}
@@ -0,0 +1,271 @@
/*
* Copyright (C) 2010-2013 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc;
import com.jpexs.decompiler.flash.abc.types.*;
import com.jpexs.decompiler.flash.abc.types.traits.*;
import java.io.IOException;
import java.io.OutputStream;
public class ABCOutputStream extends OutputStream {
private OutputStream os;
public ABCOutputStream(OutputStream os) {
this.os = os;
}
@Override
public void write(int b) throws IOException {
os.write(b);
}
public void writeU30(long value) throws IOException {
writeS32(value);
/*boolean loop = true;
boolean underZero=value<0;
if(underZero){
value = value & 0xFFFFFFFF;
}else{
value = value & 0x7FFFFFFF;
}
do {
int ret = (int) (value & 0x7F);
if (value < 0x80) {
loop = false;
}
if (value > 0x7F) {
ret += 0x80;
}
write(ret);
value = value >> 7;
} while (loop);
*/
}
public void writeU32(long value) throws IOException {
boolean loop = true;
value = value & 0xFFFFFFFF;
do {
int ret = (int) (value & 0x7F);
if (value < 0x80) {
loop = false;
}
if (value > 0x7F) {
ret += 0x80;
}
write(ret);
value = value >> 7;
} while (loop);
}
public void writeS24(long value) throws IOException {
int ret = (int) (value & 0xff);
write(ret);
value = value >> 8;
ret = (int) (value & 0xff);
write(ret);
value = value >> 8;
ret = (int) (value & 0xff);
write(ret);
}
public void writeS32(long value) throws IOException {
boolean belowZero = value < 0;
/*if (belowZero) {
value = -value;
}*/
int bitcount = 0;
boolean loop = true;
//value = value & 0xFFFFFFFF;
do {
bitcount += 7;
int ret = (int) (value & 0x7F);
if (value < 0x80) {
if (belowZero) { //&& bitcount < 35
ret += 0x80;
} else {
loop = false;
}
} else {
ret += 0x80;
}
if (bitcount == 35) {
ret = ret & 0xf;
}
write(ret);
if (bitcount == 35) {
break;
}
value = value >> 7;
} while (loop);
}
public void writeLong(long value) throws IOException {
byte writeBuffer[] = new byte[8];
writeBuffer[7] = (byte) (value >>> 56);
writeBuffer[6] = (byte) (value >>> 48);
writeBuffer[5] = (byte) (value >>> 40);
writeBuffer[4] = (byte) (value >>> 32);
writeBuffer[3] = (byte) (value >>> 24);
writeBuffer[2] = (byte) (value >>> 16);
writeBuffer[1] = (byte) (value >>> 8);
writeBuffer[0] = (byte) (value);
write(writeBuffer);
}
public void writeDouble(double value) throws IOException {
writeLong(Double.doubleToLongBits(value));
}
public void writeU8(int value) throws IOException {
write(value);
}
public void writeU16(int value) throws IOException {
write(value & 0xff);
write((value >> 8) & 0xff);
}
public void writeString(String s) throws IOException {
byte sbytes[] = s.getBytes("utf8");
writeU30(sbytes.length);
write(sbytes);
}
public void writeNamespace(Namespace ns) throws IOException {
write(ns.kind);
for (int k = 0; k < Namespace.nameSpaceKinds.length; k++) {
if (Namespace.nameSpaceKinds[k] == ns.kind) {
writeU30(ns.name_index);
break;
}
}
}
public void writeMultiname(Multiname m) throws IOException {
writeU8(m.kind);
if ((m.kind == 7) || (m.kind == 0xd)) { // CONSTANT_QName and CONSTANT_QNameA.
writeU30(m.namespace_index);
writeU30(m.name_index);
}
if ((m.kind == 9) || (m.kind == 0xe)) { // CONSTANT_Multiname and CONSTANT_MultinameA.
writeU30(m.name_index);
writeU30(m.namespace_set_index);
}
if ((m.kind == 0xf) || (m.kind == 0x10)) { //CONSTANT_RTQName and CONSTANT_RTQNameA
writeU30(m.name_index);
}
if ((m.kind == 0x1B) || (m.kind == 0x1C)) { //CONSTANT_MultinameL and CONSTANT_MultinameLA
writeU30(m.namespace_set_index);
}
if (m.kind == 0x1D) {
writeU30(m.qname_index);
writeU30(m.params.size());
for (int i = 0; i < m.params.size(); i++) {
writeU30(m.params.get(i));
}
}
//kind==0x11,0x12 nothing CONSTANT_RTQNameL and CONSTANT_RTQNameLA.
}
public void writeMethodInfo(MethodInfo mi) throws IOException {
writeU30(mi.param_types.length);
writeU30(mi.ret_type);
for (int i = 0; i < mi.param_types.length; i++) {
writeU30(mi.param_types[i]);
}
writeU30(mi.name_index);
write(mi.flags);
if ((mi.flags & 8) == 8) {
writeU30(mi.optional.length);
for (int i = 0; i < mi.optional.length; i++) {
writeU30(mi.optional[i].value_index);
write(mi.optional[i].value_kind);
}
}
if ((mi.flags & 128) == 128) { //if has_paramnames
for (int i = 0; i < mi.paramNames.length; i++) {
writeU30(mi.paramNames[i]);
}
}
}
public void writeTrait(Trait t) throws IOException {
writeU30(t.name_index);
write((t.kindFlags << 4) + t.kindType);
if (t instanceof TraitSlotConst) {
TraitSlotConst t1 = (TraitSlotConst) t;
writeU30(t1.slot_id);
writeU30(t1.type_index);
writeU30(t1.value_index);
if (t1.value_index != 0) {
write(t1.value_kind);
}
}
if (t instanceof TraitMethodGetterSetter) {
TraitMethodGetterSetter t2 = (TraitMethodGetterSetter) t;
writeU30(t2.disp_id);
writeU30(t2.method_info);
}
if (t instanceof TraitClass) {
TraitClass t3 = (TraitClass) t;
writeU30(t3.slot_id);
writeU30(t3.class_info);
}
if (t instanceof TraitFunction) {
TraitFunction t4 = (TraitFunction) t;
writeU30(t4.slot_index);
writeU30(t4.method_info);
}
if ((t.kindFlags & 4) == 4) {
writeU30(t.metadata.length);
for (int i = 0; i < t.metadata.length; i++) {
writeU30(t.metadata[i]);
}
}
}
public void writeTraits(Traits t) throws IOException {
writeU30(t.traits.length);
for (int i = 0; i < t.traits.length; i++) {
writeTrait(t.traits[i]);
}
}
public void writeInstanceInfo(InstanceInfo ii) throws IOException {
writeU30(ii.name_index);
writeU30(ii.super_index);
write(ii.flags);
if ((ii.flags & 8) == 8) {
writeU30(ii.protectedNS);
}
writeU30(ii.interfaces.length);
for (int i = 0; i < ii.interfaces.length; i++) {
writeU30(ii.interfaces[i]);
}
writeU30(ii.iinit_index);
writeTraits(ii.instance_traits);
}
public void writeDecimal(Decimal value) throws IOException {
write(value.data);
}
}
@@ -0,0 +1,72 @@
/*
* Copyright (C) 2010-2013 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
public class CopyOutputStream extends OutputStream {
private OutputStream os;
private InputStream is;
private long pos = 0;
private int TEMPSIZE = 5;
private int temp[] = new int[TEMPSIZE];
private int tempPos = 0;
public int ignoreFirst = 0;
public CopyOutputStream(OutputStream os, InputStream is) {
this.os = os;
this.is = is;
}
@Override
public void write(int b) throws IOException {
temp[tempPos] = b;
tempPos = (tempPos + 1) % TEMPSIZE;
pos++;
int r = is.read();
if ((b & 0xff) != r) {
if (ignoreFirst <= 0) {
os.flush();
boolean output = true;
if (output) {
System.out.print("Last written:");
for (int i = 0; i < TEMPSIZE; i++) {
System.out.print("" + Integer.toHexString(temp[(tempPos + i) % TEMPSIZE]) + " ");
}
System.out.println("");
System.out.println("More expected:");
for (int i = 0; i < TEMPSIZE; i++) {
System.out.println("" + Integer.toHexString(is.read()));
}
System.out.println("");
System.out.println(Integer.toHexString(r) + " expected but " + Integer.toHexString(b) + " found");
}
throw new NotSameException(pos);
} else {
ignoreFirst--;
}
}
os.write(b);
}
}
@@ -0,0 +1,26 @@
/*
* Copyright (C) 2010-2013 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc;
import com.jpexs.decompiler.flash.helpers.Helper;
public class NotSameException extends RuntimeException {
public NotSameException(long pos) {
super("Streams are not the same at pos " + Helper.formatHex((int) pos, 8));
}
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,56 @@
/*
* Copyright (C) 2011-2013 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2;
import com.jpexs.decompiler.flash.abc.ABC;
import java.util.List;
/**
*
* @author JPEXS
*/
public class CodeStats {
public int maxstack = 0;
public int maxscope = 0;
public int maxlocal = 0;
public boolean has_set_dxns = false;
public boolean has_activation = false;
public InstructionStats instructionStats[];
public String toString(ABC abc, List<String> fullyQualifiedNames) {
String ret = "Stats: maxstack=" + maxstack + ", maxscope=" + maxscope + ", maxlocal=" + maxlocal + "\r\n";
int i = 0;
int ms = 0;
for (InstructionStats stats : instructionStats) {
int deltastack = stats.ins.definition.getStackDelta(stats.ins, abc);
if (stats.stackpos > ms) {
ms = stats.stackpos;
}
ret += "" + i + ":" + stats.stackpos + (deltastack >= 0 ? "+" + deltastack : deltastack) + "," + stats.scopepos + " " + stats.ins.toString(abc.constants, fullyQualifiedNames) + "\r\n";
i++;
}
return ret;
}
public CodeStats(AVM2Code code) {
instructionStats = new InstructionStats[code.code.size()];
for (int i = 0; i < code.code.size(); i++) {
instructionStats[i] = new InstructionStats(code.code.get(i));
}
}
}
@@ -0,0 +1,158 @@
/*
* Copyright (C) 2010-2013 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2;
import com.jpexs.decompiler.flash.abc.types.Decimal;
import com.jpexs.decompiler.flash.abc.types.Multiname;
import com.jpexs.decompiler.flash.abc.types.Namespace;
import com.jpexs.decompiler.flash.abc.types.NamespaceSet;
import java.io.OutputStream;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Arrays;
public class ConstantPool {
public long constant_int[];
public long constant_uint[];
public double constant_double[];
/* Only for some minor versions */
public Decimal constant_decimal[];
public String constant_string[];
public Namespace constant_namespace[];
public NamespaceSet constant_namespace_set[];
public Multiname constant_multiname[];
public int addInt(long value) {
constant_int = Arrays.copyOf(constant_int, constant_int.length + 1);
constant_int[constant_int.length - 1] = value;
return constant_int.length - 1;
}
public int addUInt(long value) {
constant_uint = Arrays.copyOf(constant_uint, constant_uint.length + 1);
constant_uint[constant_uint.length - 1] = value;
return constant_uint.length - 1;
}
public int addDouble(double value) {
constant_double = Arrays.copyOf(constant_double, constant_double.length + 1);
constant_double[constant_double.length - 1] = value;
return constant_double.length - 1;
}
public int addString(String value) {
constant_string = Arrays.copyOf(constant_string, constant_string.length + 1);
constant_string[constant_string.length - 1] = value;
return constant_string.length - 1;
}
public int getIntId(long value) {
for (int i = 1; i < constant_int.length; i++) {
if (constant_int[i] == value) {
return i;
}
}
return 0;
}
public int getUIntId(long value) {
for (int i = 1; i < constant_uint.length; i++) {
if (constant_uint[i] == value) {
return i;
}
}
return 0;
}
public int getDoubleId(double value) {
for (int i = 1; i < constant_double.length; i++) {
if (constant_double[i] == value) {
return i;
}
}
return 0;
}
public int getStringId(String s) {
for (int i = 1; i < constant_string.length; i++) {
if (constant_string[i].equals(s)) {
return i;
}
}
return 0;
}
public int forceGetStringId(String val) {
int id = getStringId(val);
if (id == 0) {
id = addString(val);
}
return id;
}
public int forceGetIntId(long val) {
int id = getIntId(val);
if (id == 0) {
id = addInt(val);
}
return id;
}
public int forceGetUIntId(long val) {
int id = getUIntId(val);
if (id == 0) {
id = addUInt(val);
}
return id;
}
public int forceGetDoubleId(double val) {
int id = getDoubleId(val);
if (id == 0) {
id = addDouble(val);
}
return id;
}
public void dump(OutputStream os) {
PrintStream output = new PrintStream(os);
String s = "";
for (int i = 1; i < constant_int.length; i++) {
output.println("INT[" + i + "]=" + constant_int[i]);
}
for (int i = 1; i < constant_uint.length; i++) {
output.println("UINT[" + i + "]=" + constant_uint[i]);
}
for (int i = 1; i < constant_double.length; i++) {
output.println("Double[" + i + "]=" + constant_double[i]);
}
for (int i = 1; i < constant_string.length; i++) {
output.println("String[" + i + "]=" + constant_string[i]);
}
for (int i = 1; i < constant_namespace.length; i++) {
output.println("Namespace[" + i + "]=" + constant_namespace[i].toString(this));
}
for (int i = 1; i < constant_namespace_set.length; i++) {
output.println("NamespaceSet[" + i + "]=" + constant_namespace_set[i].toString(this));
}
for (int i = 1; i < constant_multiname.length; i++) {
output.println("Multiname[" + i + "]=" + constant_multiname[i].toString(this, new ArrayList<String>()));
}
}
}
@@ -0,0 +1,27 @@
/*
* Copyright (C) 2010-2013 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2;
public class ConvertException extends RuntimeException {
public int line;
public ConvertException(String s, int line) {
super(s + " on line " + line);
this.line = line;
}
}
@@ -0,0 +1,36 @@
/*
* Copyright (C) 2010-2013 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.TreeItem;
import java.util.List;
import java.util.Stack;
/**
*
* @author JPEXS
*/
public class ConvertOutput {
public Stack<TreeItem> stack;
public List<TreeItem> output;
public ConvertOutput(Stack<TreeItem> stack, List<TreeItem> output) {
this.stack = stack;
this.output = output;
}
}
@@ -0,0 +1,35 @@
/*
* Copyright (C) 2011-2013 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
/**
*
* @author JPEXS
*/
public class InstructionStats {
public boolean seen = false;
public int stackpos = 0;
public int scopepos = 0;
public AVM2Instruction ins;
public InstructionStats(AVM2Instruction ins) {
this.ins = ins;
}
}
@@ -0,0 +1,24 @@
/*
* Copyright (C) 2010-2013 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2;
public class InvalidInstructionArguments extends RuntimeException {
public InvalidInstructionArguments() {
super("Invalid method arguments");
}
}
@@ -0,0 +1,27 @@
/*
* Copyright (C) 2010-2013 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2;
import java.util.HashMap;
import java.util.Stack;
public class LocalDataArea {
public Stack operandStack = new Stack();
public Stack scopeStack = new Stack();
public HashMap localRegisters = new HashMap<Integer, Object>();
}
@@ -0,0 +1,27 @@
/*
* Copyright (C) 2010-2013 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2;
public class UnknownInstructionCode extends RuntimeException {
public int code;
public UnknownInstructionCode(int code) {
super("Unknown instruction code: 0x" + Integer.toHexString(code));
this.code = code;
}
}
@@ -0,0 +1,39 @@
/*
* Copyright (C) 2010-2013 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.TreeItem;
import java.util.List;
import java.util.Stack;
public class UnknownJumpException extends RuntimeException {
public Stack stack;
public int ip;
public List<TreeItem> output;
public UnknownJumpException(Stack stack, int ip, List<TreeItem> output) {
this.stack = stack;
this.ip = ip;
this.output = output;
}
@Override
public String toString() {
return "Unknown jump to " + ip;
}
}
@@ -0,0 +1,996 @@
/*
* Copyright (C) 2010-2013 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2.graph;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
import com.jpexs.decompiler.flash.abc.avm2.ConvertException;
import com.jpexs.decompiler.flash.abc.avm2.ConvertOutput;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.IfTypeIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.IfFalseIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.IfStrictEqIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.IfStrictNeIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.IfTrueIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.JumpIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.LookupSwitchIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.GetLocalTypeIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.KillIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.other.LabelIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.other.ReturnValueIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.other.ReturnVoidIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.other.ThrowIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.*;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.BooleanTreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.BreakTreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.CommentTreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.ContinueTreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.FilteredCheckTreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.HasNextTreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.InTreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.IntegerValueTreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.LocalRegTreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.NextNameTreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.NextValueTreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.NullTreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.ReturnValueTreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.ReturnVoidTreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.SetLocalTreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.SetPropertyTreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.SetTypeTreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.TreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.WithTreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.clauses.DoWhileTreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.clauses.ExceptionTreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.clauses.FilterTreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.clauses.ForEachInTreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.clauses.ForInTreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.clauses.ForTreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.clauses.IfTreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.clauses.SwitchTreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.clauses.TernarOpTreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.clauses.TryTreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.clauses.WhileTreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.operations.AndTreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.operations.LogicalOp;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.operations.OrTreeItem;
import com.jpexs.decompiler.flash.abc.types.ABCException;
import com.jpexs.decompiler.flash.abc.types.MethodBody;
import com.jpexs.decompiler.flash.graph.Graph;
import com.jpexs.decompiler.flash.graph.GraphPart;
import com.jpexs.decompiler.flash.graph.GraphPartMulti;
import com.jpexs.decompiler.flash.graph.Loop;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
*
* @author JPEXS
*/
public class AVM2Graph extends Graph {
private AVM2Code code;
private ABC abc;
private MethodBody body;
public AVM2Graph(AVM2Code code, ABC abc, MethodBody body) {
heads = makeGraph(code, new ArrayList<GraphPart>(), body);
this.code = code;
this.abc = abc;
this.body = body;
for (GraphPart head : heads) {
fixGraph(head);
makeMulti(head, new ArrayList<GraphPart>());
}
}
public GraphPart getNextNoJump(GraphPart part) {
while (code.code.get(part.start).definition instanceof JumpIns) {
part = part.getSubParts().get(0).nextParts.get(0);
}
return part;
}
public static List<TreeItem> translateViaGraph(String path, AVM2Code code, ABC abc, MethodBody body) {
AVM2Graph g = new AVM2Graph(code, abc, body);
List<GraphPart> allParts = new ArrayList<GraphPart>();
for (GraphPart head : g.heads) {
populateParts(head, allParts);
}
return g.printGraph(path, new Stack<TreeItem>(), new Stack<TreeItem>(), allParts, new ArrayList<ABCException>(), new ArrayList<Integer>(), 0, null, g.heads.get(0), null, new ArrayList<Loop>(), new HashMap<Integer, TreeItem>(), body, new ArrayList<Integer>());
}
private List<GraphPart> getLoopsContinues(List<Loop> loops) {
List<GraphPart> ret = new ArrayList<GraphPart>();
for (Loop l : loops) {
if (l.loopContinue != null) {
ret.add(l.loopContinue);
}
}
return ret;
}
private TreeItem checkLoop(GraphPart part, GraphPart stopPart, List<Loop> loops) {
if (part == stopPart) {
return null;
}
for (Loop l : loops) {
if (l.loopContinue == part) {
return (new ContinueTreeItem(null, l.loopBreak == null ? -1 : l.loopBreak.start));
}
if (l.loopBreak == part) {
return (new BreakTreeItem(null, part.start));
}
}
return null;
}
private boolean doDecompile = true;
private List<TreeItem> printGraph(String methodPath, Stack<TreeItem> stack, Stack<TreeItem> scopeStack, List<GraphPart> allParts, List<ABCException> parsedExceptions, List<Integer> finallyJumps, int level, GraphPart parent, GraphPart part, GraphPart stopPart, List<Loop> loops, HashMap<Integer, TreeItem> localRegs, MethodBody body, List<Integer> ignoredSwitches) {
List<TreeItem> ret = new ArrayList<TreeItem>();
if (level > 50) {
//System.err.println(methodPath+": Level>50 :"+part);
//new Exception().printStackTrace();
//return ret;
}
boolean debugMode = false;
try {
if (!doDecompile) {
ret.add(new CommentTreeItem(null, "not decompiled"));
return ret;
}
if (debugMode) {
System.err.println("PART " + part);
}
if (part == stopPart) {
return ret;
}
if (part.ignored) {
return ret;
}
List<String> fqn = new ArrayList<String>();
HashMap<Integer, String> lrn = new HashMap<Integer, String>();
List<TreeItem> output = new ArrayList<TreeItem>();
boolean isSwitch = false;
try {
code.initToSource();
List<GraphPart> parts = new ArrayList<GraphPart>();
if (part instanceof GraphPartMulti) {
parts = ((GraphPartMulti) part).parts;
} else {
parts.add(part);
}
boolean isIf = false;
int end = part.end;
for (GraphPart p : parts) {
end = p.end;
int start = p.start;
isIf = false;
if (code.code.get(end).definition instanceof JumpIns) {
end--;
} else if (code.code.get(end).definition instanceof IfTypeIns) {
end--;
isIf = true;
} else if (code.code.get(end).definition instanceof LookupSwitchIns) {
isSwitch = true;
end--;
}
ConvertOutput co = code.toSourceOutput(false, false, 0, localRegs, stack, scopeStack, abc, abc.constants, abc.method_info, body, start, end, lrn, fqn, new boolean[code.code.size()]);
output.addAll(co.output);
}
if (isIf) {
AVM2Instruction ins = code.code.get(end + 1);
if ((stack.size() >= 2) && (ins.definition instanceof IfFalseIns) && (stack.get(stack.size() - 1) == stack.get(stack.size() - 2))) {
ret.addAll(output);
GraphPart sp0 = getNextNoJump(part.nextParts.get(0));
GraphPart sp1 = getNextNoJump(part.nextParts.get(1));
boolean reversed = false;
List<GraphPart> loopContinues = getLoopsContinues(loops);
loopContinues.add(part);
if (sp1.leadsTo(sp0, loopContinues)) {
} 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));
} else {
stack.push(new AndTreeItem(ins, first, second));
}
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);
GraphPart sp0 = getNextNoJump(part.nextParts.get(0));
GraphPart sp1 = getNextNoJump(part.nextParts.get(1));
boolean reversed = false;
List<GraphPart> loopContinues = getLoopsContinues(loops);
loopContinues.add(part);
if (sp1.leadsTo(sp0, loopContinues)) {
} 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));
} else {
stack.push(new OrTreeItem(ins, first, second));
}
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)))) {
ret.addAll(output);
boolean reversed = false;
if (ins.definition instanceof IfStrictEqIns) {
reversed = true;
}
TreeItem switchedObject = null;
if (!output.isEmpty()) {
if (output.get(output.size() - 1) instanceof SetLocalTreeItem) {
switchedObject = ((SetLocalTreeItem) output.get(output.size() - 1)).value;
}
}
if (switchedObject == null) {
switchedObject = new NullTreeItem(null);
}
HashMap<Integer, TreeItem> caseValuesMap = new HashMap<Integer, TreeItem>();
stack.pop();
caseValuesMap.put(code.code.get(part.nextParts.get(reversed ? 0 : 1).start).operands[0], stack.pop());
GraphPart switchLoc = part.nextParts.get(reversed ? 0 : 1).nextParts.get(0);
while ((code.code.get(part.nextParts.get(reversed ? 1 : 0).end).definition instanceof IfStrictNeIns)
|| (code.code.get(part.nextParts.get(reversed ? 1 : 0).end).definition instanceof IfStrictEqIns)) {
part = part.nextParts.get(reversed ? 1 : 0);
List<GraphPart> ps = part.getSubParts();
for (GraphPart p : ps) {
code.toSourceOutput(false, false, 0, localRegs, stack, scopeStack, abc, abc.constants, abc.method_info, body, p.start, p.end - 1, lrn, fqn, new boolean[code.code.size()]);
}
stack.pop();
if (code.code.get(part.end).definition instanceof IfStrictNeIns) {
reversed = false;
} else {
reversed = true;
}
caseValuesMap.put(code.code.get(part.nextParts.get(reversed ? 0 : 1).start).operands[0], stack.pop());
}
boolean hasDefault = false;
GraphPart dp = part.nextParts.get(reversed ? 1 : 0);
while (code.code.get(dp.start).definition instanceof JumpIns) {
if (dp instanceof GraphPartMulti) {
dp = ((GraphPartMulti) dp).parts.get(0);
}
dp = dp.nextParts.get(0);
}
if (code.code.get(dp.start).definition instanceof PushByteIns) {
hasDefault = true;
}
List<TreeItem> caseValues = new ArrayList<TreeItem>();
for (int i = 0; i < switchLoc.nextParts.size() - 1; i++) {
if (caseValuesMap.containsKey(i)) {
caseValues.add(caseValuesMap.get(i));
} else {
continue;
}
}
List<List<TreeItem>> caseCommands = new ArrayList<List<TreeItem>>();
GraphPart next = null;
List<GraphPart> loopContinues = getLoopsContinues(loops);
next = switchLoc.getNextPartPath(loopContinues);
if (next == null) {
next = switchLoc.getNextSuperPartPath(loopContinues);
}
/*for (GraphPart p : allParts) {
if (p.start == switchLoc.end + 1) {
next = p;
break;
}
}*/
TreeItem ti = checkLoop(next, stopPart, loops);
Loop currentLoop = new Loop(null, next);
loops.add(currentLoop);
//switchLoc.getNextPartPath(new ArrayList<GraphPart>());
List<Integer> valuesMapping = new ArrayList<Integer>();
List<GraphPart> caseBodies = new ArrayList<GraphPart>();
for (int i = 0; i < caseValues.size(); i++) {
GraphPart cur = switchLoc.nextParts.get(1 + i);
if (!caseBodies.contains(cur)) {
caseBodies.add(cur);
}
valuesMapping.add(caseBodies.indexOf(cur));
}
List<TreeItem> defaultCommands = new ArrayList<TreeItem>();
GraphPart defaultPart = null;
if (hasDefault) {
defaultPart = switchLoc.nextParts.get(switchLoc.nextParts.size() - 1);
defaultCommands = printGraph(methodPath, stack, scopeStack, allParts, parsedExceptions, finallyJumps, level + 1, switchLoc, defaultPart, next, loops, localRegs, body, ignoredSwitches);
}
List<GraphPart> ignored = new ArrayList<GraphPart>();
for (Loop l : loops) {
ignored.add(l.loopContinue);
}
for (int i = 0; i < caseBodies.size(); i++) {
List<TreeItem> cc = new ArrayList<TreeItem>();
GraphPart nextCase = null;
nextCase = next;
if (next != null) {
if (i < caseBodies.size() - 1) {
if (!caseBodies.get(i).leadsTo(caseBodies.get(i + 1), ignored)) {
cc.add(new BreakTreeItem(null, next.start));
} else {
nextCase = caseBodies.get(i + 1);
}
} else if (hasDefault) {
if (!caseBodies.get(i).leadsTo(defaultPart, ignored)) {
cc.add(new BreakTreeItem(null, next.start));
} else {
nextCase = defaultPart;
}
}
}
cc.addAll(0, printGraph(methodPath, stack, scopeStack, allParts, parsedExceptions, finallyJumps, level + 1, switchLoc, caseBodies.get(i), nextCase, loops, localRegs, body, ignoredSwitches));
caseCommands.add(cc);
}
SwitchTreeItem sti = new SwitchTreeItem(null, next == null ? -1 : next.start, switchedObject, caseValues, caseCommands, defaultCommands, valuesMapping);
ret.add(sti);
loops.remove(currentLoop);
if (next != null) {
if (ti != null) {
ret.add(ti);
} else {
ret.addAll(printGraph(methodPath, stack, scopeStack, allParts, parsedExceptions, finallyJumps, level + 1, null, next, stopPart, loops, localRegs, body, ignoredSwitches));
}
}
return ret;
} else {
try {
ins.definition.translate(false, 0, new HashMap<Integer, TreeItem>(), stack, new Stack<TreeItem>(), abc.constants, ins, abc.method_info, output, body, abc, lrn, fqn);
} catch (Exception ex) {
System.err.println("ip:" + (end + 1));
ex.printStackTrace();
}
}
//((IfTypeIns)ins.definition).translateInverted(new HashMap<Integer,TreeItem>(), co.stack, ins);
}
} catch (ConvertException ex) {
Logger.getLogger(AVM2Graph.class.getName()).log(Level.SEVERE, null, ex);
}
int ip = part.start;
int addr = code.fixAddrAfterDebugLine(code.pos2adr(part.start));
int maxend = -1;
List<ABCException> catchedExceptions = new ArrayList<ABCException>();
for (int e = 0; e < body.exceptions.length; e++) {
if (addr == code.fixAddrAfterDebugLine(body.exceptions[e].start)) {
if (!body.exceptions[e].isFinally()) {
if (((body.exceptions[e].end) > maxend) && (!parsedExceptions.contains(body.exceptions[e]))) {
catchedExceptions.clear();
maxend = code.fixAddrAfterDebugLine(body.exceptions[e].end);
catchedExceptions.add(body.exceptions[e]);
} else if (code.fixAddrAfterDebugLine(body.exceptions[e].end) == maxend) {
catchedExceptions.add(body.exceptions[e]);
}
}
}
}
if (catchedExceptions.size() > 0) {
parsedExceptions.addAll(catchedExceptions);
int endpos = code.adr2pos(code.fixAddrAfterDebugLine(catchedExceptions.get(0).end));
int endposStartBlock = code.adr2pos(catchedExceptions.get(0).end);
List<List<TreeItem>> catchedCommands = new ArrayList<List<TreeItem>>();
if (code.code.get(endpos).definition instanceof JumpIns) {
int afterCatchAddr = code.pos2adr(endpos + 1) + code.code.get(endpos).operands[0];
int afterCatchPos = code.adr2pos(afterCatchAddr);
Collections.sort(catchedExceptions, new Comparator<ABCException>() {
public int compare(ABCException o1, ABCException o2) {
try {
return code.fixAddrAfterDebugLine(o1.target) - code.fixAddrAfterDebugLine(o2.target);
} catch (ConvertException ex) {
return 0;
}
}
});
List<TreeItem> finallyCommands = new ArrayList<TreeItem>();
int returnPos = afterCatchPos;
for (int e = 0; e < body.exceptions.length; e++) {
if (body.exceptions[e].isFinally()) {
if (addr == code.fixAddrAfterDebugLine(body.exceptions[e].start)) {
if (afterCatchPos + 1 == code.adr2pos(code.fixAddrAfterDebugLine(body.exceptions[e].end))) {
AVM2Instruction jmpIns = code.code.get(code.adr2pos(code.fixAddrAfterDebugLine(body.exceptions[e].end)));
if (jmpIns.definition instanceof JumpIns) {
int finStart = code.adr2pos(code.fixAddrAfterDebugLine(body.exceptions[e].end) + jmpIns.getBytes().length + jmpIns.operands[0]);
finallyJumps.add(finStart);
/*if (unknownJumps.contains(finStart)) {
unknownJumps.remove((Integer) finStart);
}*/
for (int f = finStart; f < code.code.size(); f++) {
if (code.code.get(f).definition instanceof LookupSwitchIns) {
AVM2Instruction swins = code.code.get(f);
if (swins.operands.length >= 3) {
if (swins.operands[0] == swins.getBytes().length) {
if (code.adr2pos(code.pos2adr(f) + swins.operands[2]) < finStart) {
GraphPart fpart = null;
for (GraphPart p : allParts) {
if (p.start == finStart) {
fpart = p;
break;
}
}
stack.push(new ExceptionTreeItem(body.exceptions[e]));
GraphPart fepart = null;
for (GraphPart p : allParts) {
if (p.start == f + 1) {
fepart = p;
break;
}
}
//code.code.get(f).ignored = true;
ignoredSwitches.add(f);
finallyCommands = printGraph(methodPath, stack, scopeStack, allParts, parsedExceptions, finallyJumps, level + 1, parent, fpart, fepart, loops, localRegs, body, ignoredSwitches);
returnPos = f + 1;
break;
}
}
}
}
}
break;
}
}
}
}
}
for (int e = 0; e < catchedExceptions.size(); e++) {
int eendpos;
if (e < catchedExceptions.size() - 1) {
eendpos = code.adr2pos(code.fixAddrAfterDebugLine(catchedExceptions.get(e + 1).target)) - 2;
} else {
eendpos = afterCatchPos - 1;
}
Stack<TreeItem> substack = new Stack<TreeItem>();
substack.add(new ExceptionTreeItem(catchedExceptions.get(e)));
GraphPart npart = null;
int findpos = code.adr2pos(code.fixAddrAfterDebugLine(catchedExceptions.get(e).target));
for (GraphPart p : allParts) {
if (p.start == findpos) {
npart = p;
break;
}
}
GraphPart nepart = null;
for (GraphPart p : allParts) {
if (p.start == eendpos + 1) {
nepart = p;
break;
}
}
stack.add(new ExceptionTreeItem(catchedExceptions.get(e)));
catchedCommands.add(printGraph(methodPath, stack, scopeStack, allParts, parsedExceptions, finallyJumps, level + 1, parent, npart, nepart, loops, localRegs, body, ignoredSwitches));
}
GraphPart nepart = null;
for (GraphPart p : allParts) {
if (p.start == endposStartBlock) {
nepart = p;
break;
}
}
List<TreeItem> tryCommands = printGraph(methodPath, stack, scopeStack, allParts, parsedExceptions, finallyJumps, level + 1, parent, part, nepart, loops, localRegs, body, ignoredSwitches);
output.clear();
output.add(new TryTreeItem(tryCommands, catchedExceptions, catchedCommands, finallyCommands));
ip = returnPos;
addr = code.pos2adr(ip);
}
}
if (ip != part.start) {
part = null;
for (GraphPart p : allParts) {
List<GraphPart> ps = p.getSubParts();
for (GraphPart p2 : ps) {
if (p2.start == ip) {
part = p2;
break;
}
}
}
ret.addAll(output);
TreeItem lop = checkLoop(part, stopPart, loops);
if (lop == null) {
ret.addAll(printGraph(methodPath, stack, scopeStack, allParts, parsedExceptions, finallyJumps, level + 1, null, part, stopPart, loops, localRegs, body, ignoredSwitches));
} else {
ret.add(lop);
}
return ret;
}
List<GraphPart> loopContinues = new ArrayList<GraphPart>();
for (Loop l : loops) {
if (l.loopContinue != null) {
loopContinues.add(l.loopContinue);
}
}
boolean loop = false;
boolean reversed = false;
if ((!part.nextParts.isEmpty()) && part.nextParts.get(0).leadsTo(part, loopContinues)) {
loop = true;
} else if ((part.nextParts.size() > 1) && part.nextParts.get(1).leadsTo(part, loopContinues)) {
loop = true;
reversed = true;
}
if (((part.nextParts.size() == 2) || ((part.nextParts.size() == 1) && loop)) && (!isSwitch)) {
boolean doWhile = loop;
if (loop && output.isEmpty()) {
doWhile = false;
}
Loop currentLoop = new Loop(part, null);
if (loop) {
loops.add(currentLoop);
}
loopContinues = new ArrayList<GraphPart>();
for (Loop l : loops) {
if (l.loopContinue != null) {
loopContinues.add(l.loopContinue);
}
}
if (part.nextParts.size() > 1) {
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()) {
}
expr = stack.pop();
}
if (doWhile) {
ret.add(new DoWhileTreeItem(null, breakIp, part.start, output, expr));
} else {
ret.addAll(output);
}
GraphPart next = part.getNextPartPath(loopContinues);
if (expr instanceof LogicalOp) {
expr = ((LogicalOp) expr).invert();
}
if (loop && (!doWhile)) {
List<TreeItem> loopBody = null;
List<TreeItem> 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;
}
}
}
if (isFor) {
ret.add(new ForTreeItem(null, breakIp, finalPart.start, new ArrayList<TreeItem>(), 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<TreeItem> trueStack = (Stack<TreeItem>) stack.clone();
Stack<TreeItem> falseStack = (Stack<TreeItem>) stack.clone();
TreeItem lopTrue = checkLoop(part.nextParts.get(1), stopPart, loops);
TreeItem lopFalse = null;
if (next != part.nextParts.get(0)) {
lopFalse = checkLoop(part.nextParts.get(0), stopPart, loops);
}
List<TreeItem> onTrue = new ArrayList<TreeItem>();
if (lopTrue != null) {
onTrue.add(lopTrue);
} else {
if (debugMode) {
System.err.println("ONTRUE: (inside " + part + ")");
}
onTrue = printGraph(methodPath, trueStack, scopeStack, allParts, parsedExceptions, finallyJumps, level + 1, part, part.nextParts.get(1), next == null ? stopPart : next, loops, localRegs, body, ignoredSwitches);
if (debugMode) {
System.err.println("/ONTRUE (inside " + part + ")");
}
}
List<TreeItem> onFalse = new ArrayList<TreeItem>();
if (lopFalse != null) {
onFalse.add(lopFalse);
} else {
if (debugMode) {
System.err.println("ONFALSE: (inside " + part + ")");
}
onFalse = (((next == part.nextParts.get(0)) || (part.nextParts.get(0).path.equals(part.path) || part.nextParts.get(0).path.length() < part.path.length())) ? new ArrayList<TreeItem>() : printGraph(methodPath, falseStack, scopeStack, allParts, parsedExceptions, finallyJumps, level + 1, part, part.nextParts.get(0), next == null ? stopPart : next, loops, localRegs, body, ignoredSwitches));
if (debugMode) {
System.err.println("/ONFALSE (inside " + part + ")");
}
}
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));
//Same continues in onTrue and onFalse gets continue on parent level
if ((!onTrue.isEmpty()) && (!onFalse.isEmpty())) {
if (onTrue.get(onTrue.size() - 1) instanceof ContinueTreeItem) {
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));
}
}
}
}
}
}
if (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 (next != null) {
boolean finallyJump = false;
for (int f : finallyJumps) {
if (next.start == f) {
finallyJump = true;
break;
}
}
if (!finallyJump) {
TreeItem ti = checkLoop(next, stopPart, loops);
if (ti != null) {
ret.add(ti);
} else {
if (debugMode) {
System.err.println("NEXT: (inside " + part + ")");
}
ret.addAll(printGraph(methodPath, stack, scopeStack, allParts, parsedExceptions, finallyJumps, level, part, next, stopPart, loops, localRegs, body, ignoredSwitches));
if (debugMode) {
System.err.println("/NEXT: (inside " + part + ")");
}
}
}
}
} else {
ret.addAll(output);
}
onepart:
if (part.nextParts.size() == 1 && (!loop)) {
if (part.end - part.start > 4) {
if (code.code.get(part.end).definition instanceof PopIns) {
if (code.code.get(part.end - 1).definition instanceof LabelIns) {
if (code.code.get(part.end - 2).definition instanceof PushByteIns) {
//if (code.code.get(part.end - 3).definition instanceof SetLocalTypeIns) {
if (part.nextParts.size() == 1) {
GraphPart sec = part.nextParts.get(0);
if (code.code.get(sec.end).definition instanceof ReturnValueIns) {
if (sec.end - sec.start >= 3) {
if (code.code.get(sec.end - 1).definition instanceof KillIns) {
if (code.code.get(sec.end - 2).definition instanceof GetLocalTypeIns) {
if (!output.isEmpty()) {
if (output.get(output.size() - 1) instanceof SetLocalTreeItem) {
sec.ignored = true;
ret.add(new ReturnValueTreeItem(code.code.get(sec.end), ((SetLocalTreeItem) output.get(output.size() - 1)).value));
break onepart;
}
}
}
}
}
} else if (code.code.get(sec.end).definition instanceof ReturnVoidIns) {
ret.add(new ReturnVoidTreeItem(code.code.get(sec.end)));
break onepart;
}
//}
}
}
}
}
}
for (int f : finallyJumps) {
if (part.nextParts.get(0).start == f) {
if ((!output.isEmpty()) && (output.get(output.size() - 1) instanceof SetLocalTreeItem)) {
ret.add(new ReturnValueTreeItem(null, ((SetLocalTreeItem) output.get(output.size() - 1)).value));
} else {
ret.add(new ReturnVoidTreeItem(null));
}
break onepart;
}
}
GraphPart p = part.nextParts.get(0);
TreeItem lop = checkLoop(p, stopPart, loops);
if (lop == null) {
if (p.path.length() == part.path.length()) {
ret.addAll(printGraph(methodPath, stack, scopeStack, allParts, parsedExceptions, finallyJumps, level + 1, part, p, stopPart, loops, localRegs, body, ignoredSwitches));
} else {
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(cti);
}
}
} else {
ret.add(lop);
}
//}
//ret += (strOfChars(level, TAB) + "continue;\r\n");
//}
}
if (isSwitch && (!ignoredSwitches.contains(part.end))) {
//ret.add(new CommentTreeItem(code.code.get(part.end), "Switch not supported"));
TreeItem switchedObject = stack.pop();
List<TreeItem> caseValues = new ArrayList<TreeItem>();
List<Integer> valueMappings = new ArrayList<Integer>();
List<List<TreeItem>> caseCommands = new ArrayList<List<TreeItem>>();
GraphPart next = part.getNextPartPath(loopContinues);
int breakPos = -1;
if (next != null) {
breakPos = next.start;
}
List<TreeItem> defaultCommands = printGraph(methodPath, stack, scopeStack, allParts, parsedExceptions, finallyJumps, level + 1, part, part.nextParts.get(0), stopPart, loops, localRegs, body, ignoredSwitches);
for (int i = 0; i < part.nextParts.size() - 1; i++) {
caseValues.add(new IntegerValueTreeItem(null, (Long) (long) i));
valueMappings.add(i);
GraphPart nextCase = next;
List<TreeItem> caseBody = new ArrayList<TreeItem>();
if (i < part.nextParts.size() - 1 - 1) {
if (!part.nextParts.get(1 + i).leadsTo(part.nextParts.get(1 + i + 1), new ArrayList<GraphPart>())) {
caseBody.add(new BreakTreeItem(null, breakPos));
} else {
nextCase = part.nextParts.get(1 + i + 1);
}
} else if (!part.nextParts.get(1 + i).leadsTo(part.nextParts.get(0), new ArrayList<GraphPart>())) {
caseBody.add(new BreakTreeItem(null, breakPos));
} else {
nextCase = part.nextParts.get(0);
}
caseBody.addAll(0, printGraph(methodPath, stack, scopeStack, allParts, parsedExceptions, finallyJumps, level + 1, part, part.nextParts.get(1 + i), nextCase, loops, localRegs, body, ignoredSwitches));
caseCommands.add(caseBody);
}
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));
}
}
} catch (ForException fex) {
ret.addAll(fex.output);
fex.output = ret;
throw fex;
}
code.clearTemporaryRegisters(ret);
if (!part.forContinues.isEmpty()) {
throw new ForException(new ArrayList<TreeItem>(), ret, part);
}
return ret;
}
private List<GraphPart> makeGraph(AVM2Code code, List<GraphPart> allBlocks, MethodBody body) {
HashMap<Integer, List<Integer>> refs = code.visitCode(body);
List<GraphPart> ret = new ArrayList<GraphPart>();
boolean visited[] = new boolean[code.code.size()];
ret.add(makeGraph(null, "0", code, 0, 0, allBlocks, refs, visited));
for (ABCException ex : body.exceptions) {
GraphPart e1 = new GraphPart(-1, -1);
e1.path = "e";
GraphPart e2 = new GraphPart(-1, -1);
e2.path = "e";
GraphPart e3 = new GraphPart(-1, -1);
e3.path = "e";
makeGraph(e1, "e", code, code.adr2pos(ex.start), code.adr2pos(ex.start), allBlocks, refs, visited);
makeGraph(e2, "e", code, code.adr2pos(ex.end), code.adr2pos(ex.end), allBlocks, refs, visited);
ret.add(makeGraph(e3, "e", code, code.adr2pos(ex.target), code.adr2pos(ex.target), allBlocks, refs, visited));
}
return ret;
}
private GraphPart makeGraph(GraphPart parent, String path, AVM2Code code, int startip, int lastIp, List<GraphPart> allBlocks, HashMap<Integer, List<Integer>> refs, boolean visited2[]) {
int ip = startip;
for (GraphPart p : allBlocks) {
if (p.start == ip) {
p.refs.add(parent);
return p;
}
}
GraphPart g;
GraphPart ret = new GraphPart(ip, -1);
ret.path = path;
GraphPart part = ret;
while (ip < code.code.size()) {
if (visited2[ip] || ((ip != startip) && (refs.get(ip).size() > 1))) {
part.end = lastIp;
GraphPart found = null;
for (GraphPart p : allBlocks) {
if (p.start == ip) {
found = p;
break;
}
}
allBlocks.add(part);
if (found != null) {
part.nextParts.add(found);
found.refs.add(part);
break;
} else {
GraphPart gp = new GraphPart(ip, -1);
gp.path = path;
part.nextParts.add(gp);
gp.refs.add(part);
part = gp;
}
}
lastIp = ip;
AVM2Instruction ins = code.code.get(ip);
if ((ins.definition instanceof ThrowIns) || (ins.definition instanceof ReturnValueIns) || (ins.definition instanceof ReturnVoidIns)) {
part.end = ip;
allBlocks.add(part);
break;
}
if (ins.definition instanceof LookupSwitchIns) {
part.end = ip;
allBlocks.add(part);
try {
part.nextParts.add(g = makeGraph(part, path + "0", code, code.adr2pos(code.pos2adr(ip) + ins.operands[0]), ip, allBlocks, refs, visited2));
g.refs.add(part);
for (int i = 2; i < ins.operands.length; i++) {
part.nextParts.add(g = makeGraph(part, path + (i - 1), code, code.adr2pos(code.pos2adr(ip) + ins.operands[i]), ip, allBlocks, refs, visited2));
g.refs.add(part);
}
break;
} catch (ConvertException ex) {
}
}
if (ins.definition instanceof JumpIns) {
try {
part.end = ip;
allBlocks.add(part);
ip = code.adr2pos(code.pos2adr(ip) + ins.getBytes().length + ins.operands[0]);
part.nextParts.add(g = makeGraph(part, path, code, ip, lastIp, allBlocks, refs, visited2));
g.refs.add(part);
break;
} catch (ConvertException ex) {
Logger.getLogger(AVM2Code.class.getName()).log(Level.FINE, null, ex);
}
} else if (ins.definition instanceof IfTypeIns) {
part.end = ip;
allBlocks.add(part);
try {
part.nextParts.add(g = makeGraph(part, path + "0", code, code.adr2pos(code.pos2adr(ip) + ins.getBytes().length + ins.operands[0]), ip, allBlocks, refs, visited2));
g.refs.add(part);
part.nextParts.add(g = makeGraph(part, path + "1", code, ip + 1, ip, allBlocks, refs, visited2));
g.refs.add(part);
} catch (ConvertException ex) {
Logger.getLogger(AVM2Code.class.getName()).log(Level.FINE, null, ex);
}
break;
}
ip++;
};
return ret;
}
}
@@ -0,0 +1,38 @@
/*
* Copyright (C) 2010-2013 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2.graph;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.TreeItem;
import com.jpexs.decompiler.flash.graph.GraphPart;
import java.util.List;
/**
*
* @author JPEXS
*/
public class ForException extends RuntimeException {
public List<TreeItem> output;
public List<TreeItem> finalOutput;
public GraphPart continuePart;
public ForException(List<TreeItem> output, List<TreeItem> finalOutput, GraphPart continuePart) {
this.output = output;
this.finalOutput = finalOutput;
this.continuePart = continuePart;
}
}
@@ -0,0 +1,230 @@
/*
* Copyright (C) 2010-2013 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2.instructions;
import com.jpexs.decompiler.flash.abc.ABCOutputStream;
import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
import com.jpexs.decompiler.flash.abc.avm2.ConstantPool;
import com.jpexs.decompiler.flash.helpers.Helper;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
public class AVM2Instruction implements Serializable {
public InstructionDefinition definition;
public int operands[];
public long offset;
public byte bytes[];
public String comment;
public boolean ignored = false;
public String labelname;
public long mappedOffset = -1;
public int changeJumpTo = -1;
public AVM2Instruction(long offset, InstructionDefinition definition, int[] operands, byte bytes[]) {
this.definition = definition;
this.operands = operands;
this.offset = offset;
this.bytes = bytes;
}
public byte[] getBytes() {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try {
ABCOutputStream aos = new ABCOutputStream(bos);
aos.write(definition.instructionCode);
for (int i = 0; i < definition.operands.length; i++) {
int opt = definition.operands[i] & 0xff00;
switch (opt) {
case AVM2Code.OPT_S24:
aos.writeS24(operands[i]);
break;
case AVM2Code.OPT_U30:
aos.writeU30(operands[i]);
break;
case AVM2Code.OPT_U8:
aos.writeU8(operands[i]);
break;
case AVM2Code.OPT_BYTE:
aos.writeU8(0xff & operands[i]);
break;
case AVM2Code.OPT_CASE_OFFSETS:
aos.writeU30(operands[i]); //case count
for (int j = i + 1; j < operands.length; j++) {
aos.writeS24(operands[j]);
}
break;
}
}
} catch (IOException ex) {
//ignored
}
return bos.toByteArray();
}
@Override
public String toString() {
String s = definition.instructionName;
for (int i = 0; i < operands.length; i++) {
s += " " + operands[i];
}
return s;
}
public List<Long> getOffsets() {
List<Long> ret = new ArrayList<Long>();
String s = "";
for (int i = 0; i < definition.operands.length; i++) {
switch (definition.operands[i]) {
case AVM2Code.DAT_OFFSET:
ret.add(offset + operands[i] + getBytes().length);
break;
case AVM2Code.DAT_CASE_BASEOFFSET:
ret.add(offset + operands[i]);
break;
case AVM2Code.OPT_CASE_OFFSETS:
for (int j = i + 1; j < operands.length; j++) {
ret.add(offset + operands[j]);
}
break;
}
}
return ret;
}
public List getParamsAsList(ConstantPool constants) {
List s = new ArrayList();
for (int i = 0; i < definition.operands.length; i++) {
switch (definition.operands[i]) {
case AVM2Code.DAT_MULTINAME_INDEX:
s.add(constants.constant_multiname[operands[i]]);
break;
case AVM2Code.DAT_STRING_INDEX:
s.add(constants.constant_string[operands[i]]);
break;
case AVM2Code.DAT_INT_INDEX:
s.add(new Long(constants.constant_int[operands[i]]));
break;
case AVM2Code.DAT_UINT_INDEX:
s.add(new Long(constants.constant_uint[operands[i]]));
break;
case AVM2Code.DAT_DOUBLE_INDEX:
s.add(new Double(constants.constant_double[operands[i]]));
break;
case AVM2Code.DAT_OFFSET:
s.add(new Long(offset + operands[i] + getBytes().length));
break;
case AVM2Code.DAT_CASE_BASEOFFSET:
s.add(new Long(offset + operands[i]));
break;
case AVM2Code.OPT_CASE_OFFSETS:
s.add(new Long(operands[i]));
for (int j = i + 1; j < operands.length; j++) {
s.add(new Long(offset + operands[j]));
}
break;
default:
s.add(new Long(operands[i]));
}
}
return s;
}
public String getParams(ConstantPool constants, List<String> fullyQualifiedNames) {
String s = "";
for (int i = 0; i < definition.operands.length; i++) {
switch (definition.operands[i]) {
case AVM2Code.DAT_MULTINAME_INDEX:
s += " m[" + operands[i] + "]\"" + Helper.escapeString(constants.constant_multiname[operands[i]].toString(constants, fullyQualifiedNames)) + "\"";
break;
case AVM2Code.DAT_STRING_INDEX:
s += " \"" + Helper.escapeString(constants.constant_string[operands[i]]) + "\"";
break;
case AVM2Code.DAT_INT_INDEX:
s += " " + constants.constant_int[operands[i]] + "";
break;
case AVM2Code.DAT_UINT_INDEX:
s += " " + constants.constant_uint[operands[i]] + "";
break;
case AVM2Code.DAT_DOUBLE_INDEX:
s += " " + constants.constant_double[operands[i]] + "";
break;
case AVM2Code.DAT_OFFSET:
s += " ";
if (operands[i] > 0) {
//s += "+";
}//operands[i]
s += "ofs" + Helper.formatAddress(offset + operands[i] + getBytes().length) + "";
break;
case AVM2Code.DAT_CASE_BASEOFFSET:
s += " ";
if (operands[i] > 0) {
//s += "+";
}//operands[i]
s += "ofs" + Helper.formatAddress(offset + operands[i]) + "";
break;
case AVM2Code.OPT_CASE_OFFSETS:
s += " " + operands[i];
for (int j = i + 1; j < operands.length; j++) {
s += " ";
if (operands[j] > 0) {
//s += "+";
}//operands[j]
s += "ofs" + Helper.formatAddress(offset + operands[j]) + "";
}
break;
default:
s += " " + operands[i];
}
}
return s;
}
public String getComment() {
if (ignored) {
return " ;ignored";
}
if ((comment == null) || comment.equals("")) {
return "";
}
return " ;" + comment;
}
public boolean isIgnored() {
return ignored;
}
public String toString(ConstantPool constants, List<String> fullyQualifiedNames) {
String s = Helper.formatAddress(offset) + " " + Helper.padSpaceRight(Helper.byteArrToString(getBytes()), 30) + definition.instructionName;
s += getParams(constants, fullyQualifiedNames) + getComment();
return s;
}
public String toStringNoAddress(ConstantPool constants, List<String> fullyQualifiedNames) {
String s = definition.instructionName;
s += getParams(constants, fullyQualifiedNames) + getComment();
return s;
}
public List replaceWith;
}
@@ -0,0 +1,25 @@
/*
* Copyright (C) 2010-2013 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2.instructions;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.TreeItem;
import java.util.Stack;
public interface IfTypeIns {
public abstract void translateInverted(java.util.HashMap<Integer, TreeItem> localRegs, Stack<TreeItem> stack, AVM2Instruction ins);
}
@@ -0,0 +1,123 @@
/*
* Copyright (C) 2010-2013 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2.instructions;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
import com.jpexs.decompiler.flash.abc.avm2.ConstantPool;
import com.jpexs.decompiler.flash.abc.avm2.LocalDataArea;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.FullMultinameTreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.TreeItem;
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
import com.jpexs.decompiler.flash.helpers.Highlighting;
import java.io.Serializable;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
public class InstructionDefinition implements Serializable {
protected String hilighOffset(String text, long offset) {
return Highlighting.hilighOffset(text, offset);
}
public int operands[];
public String instructionName = "";
public int instructionCode = 0;
public InstructionDefinition(int instructionCode, String instructionName, int operands[]) {
this.instructionCode = instructionCode;
this.instructionName = instructionName;
this.operands = operands;
}
@Override
public String toString() {
String s = instructionName;
for (int i = 0; i < operands.length; i++) {
if ((operands[i] & 0xff00) == AVM2Code.OPT_U30) {
s += " U30";
}
if ((operands[i] & 0xff00) == AVM2Code.OPT_U8) {
s += " U8";
}
if ((operands[i] & 0xff00) == AVM2Code.OPT_BYTE) {
s += " BYTE";
}
if ((operands[i] & 0xff00) == AVM2Code.OPT_S24) {
s += " S24";
}
if ((operands[i] & 0xff00) == AVM2Code.OPT_CASE_OFFSETS) {
s += " U30 S24,[S24]...";
}
}
return s;
}
public void execute(LocalDataArea lda, ConstantPool constants, List arguments) {
throw new UnsupportedOperationException("Instruction " + instructionName + " not implemented");
}
public void translate(boolean isStatic, int classIndex, java.util.HashMap<Integer, TreeItem> localRegs, Stack<TreeItem> stack, java.util.Stack<TreeItem> scopeStack, ConstantPool constants, AVM2Instruction ins, MethodInfo[] method_info, List<TreeItem> output, com.jpexs.decompiler.flash.abc.types.MethodBody body, com.jpexs.decompiler.flash.abc.ABC abc, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames) {
}
protected FullMultinameTreeItem resolveMultiname(Stack<TreeItem> stack, ConstantPool constants, int multinameIndex, AVM2Instruction ins) {
TreeItem ns = null;
TreeItem name = null;
if (constants.constant_multiname[multinameIndex].needsName()) {
name = (TreeItem) stack.pop();
}
if (constants.constant_multiname[multinameIndex].needsNs()) {
ns = (TreeItem) stack.pop();
}
return new FullMultinameTreeItem(ins, multinameIndex, name, ns);
}
protected int resolvedCount(ConstantPool constants, int multinameIndex) {
int pos = 0;
if (constants.constant_multiname[multinameIndex].needsNs()) {
pos++;
}
if (constants.constant_multiname[multinameIndex].needsName()) {
pos++;
}
return pos;
}
protected String resolveMultinameNoPop(int pos, Stack<TreeItem> stack, ConstantPool constants, int multinameIndex, AVM2Instruction ins, List<String> fullyQualifiedNames) {
String ns = "";
String name;
if (constants.constant_multiname[multinameIndex].needsNs()) {
ns = "[" + stack.get(pos) + "]";
pos++;
}
if (constants.constant_multiname[multinameIndex].needsName()) {
name = stack.get(pos).toString();
} else {
name = hilighOffset(constants.constant_multiname[multinameIndex].getName(constants, fullyQualifiedNames), ins.offset);
}
return name + ns;
}
public int getStackDelta(AVM2Instruction ins, ABC abc) {
return 0;
}
public int getScopeStackDelta(AVM2Instruction ins, ABC abc) {
return 0;
}
}
@@ -0,0 +1,28 @@
/*
* Copyright (C) 2010-2013 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2.instructions;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.TreeItem;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
public interface SetTypeIns {
public abstract String getObject(Stack<TreeItem> stack, ABC abc, AVM2Instruction ins, List<TreeItem> output, com.jpexs.decompiler.flash.abc.types.MethodBody body, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames);
}
@@ -0,0 +1,28 @@
/*
* Copyright (C) 2010-2013 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2.instructions;
/**
*
* @author JPEXS
*/
public class TagInstruction extends InstructionDefinition {
public TagInstruction(String tagName) {
super(-1, tagName, new int[0]);
}
}
@@ -0,0 +1,47 @@
/*
* Copyright (C) 2010-2013 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.avm2.ConstantPool;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.TreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.operations.AddTreeItem;
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
public class AddIIns extends AddIns {
public AddIIns() {
instructionName = "add_i";
instructionCode = 0xc5;
}
@Override
public void translate(boolean isStatic, int classIndex, java.util.HashMap<Integer, TreeItem> localRegs, Stack<TreeItem> stack, java.util.Stack<TreeItem> scopeStack, ConstantPool constants, AVM2Instruction ins, MethodInfo[] method_info, List<TreeItem> output, com.jpexs.decompiler.flash.abc.types.MethodBody body, com.jpexs.decompiler.flash.abc.ABC abc, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames) {
TreeItem v2 = (TreeItem) stack.pop();
TreeItem v1 = (TreeItem) stack.pop();
stack.push(new AddTreeItem(ins, v1, v2));
}
@Override
public int getStackDelta(AVM2Instruction ins, ABC abc) {
return -2 + 1;
}
}
@@ -0,0 +1,70 @@
/*
* Copyright (C) 2010-2013 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.avm2.ConstantPool;
import com.jpexs.decompiler.flash.abc.avm2.LocalDataArea;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.TreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.operations.AddTreeItem;
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
public class AddIns extends InstructionDefinition {
public AddIns() {
super(0xa0, "add", new int[]{});
}
@Override
public void execute(LocalDataArea lda, ConstantPool constants, List arguments) {
Object o1 = lda.operandStack.pop();
Object o2 = lda.operandStack.pop();
if ((o1 instanceof Long) && ((o2 instanceof Long))) {
Long ret = new Long(((Long) o1).longValue() + ((Long) o2).longValue());
lda.operandStack.push(ret);
} else if ((o1 instanceof Double) && ((o2 instanceof Double))) {
Double ret = new Double(((Double) o1).doubleValue() + ((Double) o2).doubleValue());
lda.operandStack.push(ret);
} else if ((o1 instanceof Long) && ((o2 instanceof Double))) {
Double ret = new Double(((Long) o1).longValue() + ((Double) o2).doubleValue());
lda.operandStack.push(ret);
} else if ((o1 instanceof Double) && ((o2 instanceof Long))) {
Double ret = new Double(((Double) o1).doubleValue() + ((Long) o2).longValue());
lda.operandStack.push(ret);
} else {
String s = o1.toString() + o2.toString();
lda.operandStack.push(s);
}
}
@Override
public void translate(boolean isStatic, int classIndex, java.util.HashMap<Integer, TreeItem> localRegs, Stack<TreeItem> stack, java.util.Stack<TreeItem> scopeStack, ConstantPool constants, AVM2Instruction ins, MethodInfo[] method_info, List<TreeItem> output, com.jpexs.decompiler.flash.abc.types.MethodBody body, com.jpexs.decompiler.flash.abc.ABC abc, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames) {
TreeItem v2 = (TreeItem) stack.pop();
TreeItem v1 = (TreeItem) stack.pop();
stack.push(new AddTreeItem(ins, v1, v2));
}
@Override
public int getStackDelta(AVM2Instruction ins, ABC abc) {
return -2 + 1;
}
}
@@ -0,0 +1,64 @@
/*
* Copyright (C) 2010-2013 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.avm2.ConstantPool;
import com.jpexs.decompiler.flash.abc.avm2.LocalDataArea;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.DecrementTreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.TreeItem;
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
public class DecrementIIns extends InstructionDefinition {
public DecrementIIns() {
super(0xc1, "decrement_i", new int[]{});
}
@Override
public void execute(LocalDataArea lda, ConstantPool constants, List arguments) {
Object obj = lda.operandStack.pop();
if (obj instanceof Long) {
Long obj2 = ((Long) obj).longValue() - 1;
lda.operandStack.push(obj2);
} else if (obj instanceof Double) {
Double obj2 = ((Double) obj).doubleValue() - 1;
lda.operandStack.push(obj2);
}
if (obj instanceof String) {
Double obj2 = Double.parseDouble((String) obj) - 1;
lda.operandStack.push(obj2);
} else {
throw new RuntimeException("Cannot decrement local register");
}
}
@Override
public void translate(boolean isStatic, int classIndex, java.util.HashMap<Integer, TreeItem> localRegs, Stack<TreeItem> stack, java.util.Stack<TreeItem> scopeStack, ConstantPool constants, AVM2Instruction ins, MethodInfo[] method_info, List<TreeItem> output, com.jpexs.decompiler.flash.abc.types.MethodBody body, com.jpexs.decompiler.flash.abc.ABC abc, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames) {
stack.push(new DecrementTreeItem(ins, (TreeItem) stack.pop()));
}
@Override
public int getStackDelta(AVM2Instruction ins, ABC abc) {
return -1 + 1;
}
}
@@ -0,0 +1,64 @@
/*
* Copyright (C) 2010-2013 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.avm2.ConstantPool;
import com.jpexs.decompiler.flash.abc.avm2.LocalDataArea;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.DecrementTreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.TreeItem;
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
public class DecrementIns extends InstructionDefinition {
public DecrementIns() {
super(0x93, "decrement", new int[]{});
}
@Override
public void execute(LocalDataArea lda, ConstantPool constants, List arguments) {
Object obj = lda.operandStack.pop();
if (obj instanceof Long) {
Long obj2 = ((Long) obj).longValue() - 1;
lda.operandStack.push(obj2);
} else if (obj instanceof Double) {
Double obj2 = ((Double) obj).doubleValue() - 1;
lda.operandStack.push(obj2);
}
if (obj instanceof String) {
Double obj2 = Double.parseDouble((String) obj) - 1;
lda.operandStack.push(obj2);
} else {
throw new RuntimeException("Cannot decrement local register");
}
}
@Override
public void translate(boolean isStatic, int classIndex, java.util.HashMap<Integer, TreeItem> localRegs, Stack<TreeItem> stack, java.util.Stack<TreeItem> scopeStack, ConstantPool constants, AVM2Instruction ins, MethodInfo[] method_info, List<TreeItem> output, com.jpexs.decompiler.flash.abc.types.MethodBody body, com.jpexs.decompiler.flash.abc.ABC abc, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames) {
stack.push(new DecrementTreeItem(ins, (TreeItem) stack.pop()));
}
@Override
public int getStackDelta(AVM2Instruction ins, ABC abc) {
return -1 + 1;
}
}
@@ -0,0 +1,69 @@
/*
* Copyright (C) 2010-2013 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.avm2.ConstantPool;
import com.jpexs.decompiler.flash.abc.avm2.LocalDataArea;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.TreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.operations.DivideTreeItem;
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
public class DivideIns extends InstructionDefinition {
public DivideIns() {
super(0xa3, "divide", new int[]{});
}
@Override
public void execute(LocalDataArea lda, ConstantPool constants, List arguments) {
Object o2 = lda.operandStack.pop();
Object o1 = lda.operandStack.pop();
if ((o1 instanceof Long) && ((o2 instanceof Long))) {
Long ret = new Long(((Long) o1).longValue() / ((Long) o2).longValue());
lda.operandStack.push(ret);
} else if ((o1 instanceof Double) && ((o2 instanceof Double))) {
Double ret = new Double(((Double) o1).doubleValue() / ((Double) o2).doubleValue());
lda.operandStack.push(ret);
} else if ((o1 instanceof Long) && ((o2 instanceof Double))) {
Double ret = new Double(((Long) o1).longValue() / ((Double) o2).doubleValue());
lda.operandStack.push(ret);
} else if ((o1 instanceof Double) && ((o2 instanceof Long))) {
Double ret = new Double(((Double) o1).doubleValue() / ((Long) o2).longValue());
lda.operandStack.push(ret);
} else {
throw new RuntimeException("Cannot divide");
}
}
@Override
public void translate(boolean isStatic, int classIndex, java.util.HashMap<Integer, TreeItem> localRegs, Stack<TreeItem> stack, java.util.Stack<TreeItem> scopeStack, ConstantPool constants, AVM2Instruction ins, MethodInfo[] method_info, List<TreeItem> output, com.jpexs.decompiler.flash.abc.types.MethodBody body, com.jpexs.decompiler.flash.abc.ABC abc, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames) {
TreeItem v2 = (TreeItem) stack.pop();
TreeItem v1 = (TreeItem) stack.pop();
stack.push(new DivideTreeItem(ins, v1, v2));
}
@Override
public int getStackDelta(AVM2Instruction ins, ABC abc) {
return -2 + 1;
}
}
@@ -0,0 +1,45 @@
/*
* Copyright (C) 2010-2013 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.avm2.ConstantPool;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.IncrementTreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.TreeItem;
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
public class IncrementIIns extends InstructionDefinition {
public IncrementIIns() {
super(0xc0, "increment_i", new int[]{});
}
@Override
public void translate(boolean isStatic, int classIndex, java.util.HashMap<Integer, TreeItem> localRegs, Stack<TreeItem> stack, java.util.Stack<TreeItem> scopeStack, ConstantPool constants, AVM2Instruction ins, MethodInfo[] method_info, List<TreeItem> output, com.jpexs.decompiler.flash.abc.types.MethodBody body, com.jpexs.decompiler.flash.abc.ABC abc, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames) {
stack.push(new IncrementTreeItem(ins, (TreeItem) stack.pop()));
}
@Override
public int getStackDelta(AVM2Instruction ins, ABC abc) {
return -1 + 1;
}
}
@@ -0,0 +1,45 @@
/*
* Copyright (C) 2010-2013 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.avm2.ConstantPool;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.IncrementTreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.TreeItem;
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
public class IncrementIns extends InstructionDefinition {
public IncrementIns() {
super(0x91, "increment", new int[]{});
}
@Override
public void translate(boolean isStatic, int classIndex, java.util.HashMap<Integer, TreeItem> localRegs, Stack<TreeItem> stack, java.util.Stack<TreeItem> scopeStack, ConstantPool constants, AVM2Instruction ins, MethodInfo[] method_info, List<TreeItem> output, com.jpexs.decompiler.flash.abc.types.MethodBody body, com.jpexs.decompiler.flash.abc.ABC abc, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames) {
stack.push(new IncrementTreeItem(ins, (TreeItem) stack.pop()));
}
@Override
public int getStackDelta(AVM2Instruction ins, ABC abc) {
return -1 + 1;
}
}
@@ -0,0 +1,61 @@
/*
* Copyright (C) 2010-2013 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.avm2.ConstantPool;
import com.jpexs.decompiler.flash.abc.avm2.LocalDataArea;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.TreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.operations.ModuloTreeItem;
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
public class ModuloIns extends InstructionDefinition {
public ModuloIns() {
super(0xa4, "modulo", new int[]{});
}
@Override
public void execute(LocalDataArea lda, ConstantPool constants, List arguments) {
Object o1 = lda.operandStack.pop();
Object o2 = lda.operandStack.pop();
if ((o1 instanceof Long) && ((o2 instanceof Long))) {
Long ret = new Long(((Long) o2).longValue() % ((Long) o1).longValue());
lda.operandStack.push(ret);
} else {
throw new RuntimeException("Cannot modulo");
}
}
@Override
public void translate(boolean isStatic, int classIndex, java.util.HashMap<Integer, TreeItem> localRegs, Stack<TreeItem> stack, java.util.Stack<TreeItem> scopeStack, ConstantPool constants, AVM2Instruction ins, MethodInfo[] method_info, List<TreeItem> output, com.jpexs.decompiler.flash.abc.types.MethodBody body, com.jpexs.decompiler.flash.abc.ABC abc, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames) {
TreeItem v2 = (TreeItem) stack.pop();
TreeItem v1 = (TreeItem) stack.pop();
stack.push(new ModuloTreeItem(ins, v1, v2));
}
@Override
public int getStackDelta(AVM2Instruction ins, ABC abc) {
return -2 + 1;
}
}
@@ -0,0 +1,47 @@
/*
* Copyright (C) 2010-2013 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.avm2.ConstantPool;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.TreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.operations.MultiplyTreeItem;
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
public class MultiplyIIns extends InstructionDefinition {
public MultiplyIIns() {
super(0xc7, "multiply_i", new int[]{});
}
@Override
public void translate(boolean isStatic, int classIndex, java.util.HashMap<Integer, TreeItem> localRegs, Stack<TreeItem> stack, java.util.Stack<TreeItem> scopeStack, ConstantPool constants, AVM2Instruction ins, MethodInfo[] method_info, List<TreeItem> output, com.jpexs.decompiler.flash.abc.types.MethodBody body, com.jpexs.decompiler.flash.abc.ABC abc, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames) {
TreeItem v2 = (TreeItem) stack.pop();
TreeItem v1 = (TreeItem) stack.pop();
stack.push(new MultiplyTreeItem(ins, v1, v2));
}
@Override
public int getStackDelta(AVM2Instruction ins, ABC abc) {
return -2 + 1;
}
}
@@ -0,0 +1,69 @@
/*
* Copyright (C) 2010-2013 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.avm2.ConstantPool;
import com.jpexs.decompiler.flash.abc.avm2.LocalDataArea;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.TreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.operations.MultiplyTreeItem;
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
public class MultiplyIns extends InstructionDefinition {
public MultiplyIns() {
super(0xa2, "multiply", new int[]{});
}
@Override
public void execute(LocalDataArea lda, ConstantPool constants, List arguments) {
Object o1 = lda.operandStack.pop();
Object o2 = lda.operandStack.pop();
if ((o1 instanceof Long) && ((o2 instanceof Long))) {
Long ret = new Long(((Long) o1).longValue() * ((Long) o2).longValue());
lda.operandStack.push(ret);
} else if ((o1 instanceof Double) && ((o2 instanceof Double))) {
Double ret = new Double(((Double) o1).doubleValue() * ((Double) o2).doubleValue());
lda.operandStack.push(ret);
} else if ((o1 instanceof Long) && ((o2 instanceof Double))) {
Double ret = new Double(((Long) o1).longValue() * ((Double) o2).doubleValue());
lda.operandStack.push(ret);
} else if ((o1 instanceof Double) && ((o2 instanceof Long))) {
Double ret = new Double(((Double) o1).doubleValue() * ((Long) o2).longValue());
lda.operandStack.push(ret);
} else {
throw new RuntimeException("Cannot multiply");
}
}
@Override
public void translate(boolean isStatic, int classIndex, java.util.HashMap<Integer, TreeItem> localRegs, Stack<TreeItem> stack, java.util.Stack<TreeItem> scopeStack, ConstantPool constants, AVM2Instruction ins, MethodInfo[] method_info, List<TreeItem> output, com.jpexs.decompiler.flash.abc.types.MethodBody body, com.jpexs.decompiler.flash.abc.ABC abc, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames) {
TreeItem v2 = (TreeItem) stack.pop();
TreeItem v1 = (TreeItem) stack.pop();
stack.push(new MultiplyTreeItem(ins, v1, v2));
}
@Override
public int getStackDelta(AVM2Instruction ins, ABC abc) {
return -2 + 1;
}
}
@@ -0,0 +1,46 @@
/*
* Copyright (C) 2010-2013 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.avm2.ConstantPool;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.TreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.operations.NegTreeItem;
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
public class NegateIIns extends InstructionDefinition {
public NegateIIns() {
super(0xc4, "negate_i", new int[]{});
}
@Override
public void translate(boolean isStatic, int classIndex, java.util.HashMap<Integer, TreeItem> localRegs, Stack<TreeItem> stack, java.util.Stack<TreeItem> scopeStack, ConstantPool constants, AVM2Instruction ins, MethodInfo[] method_info, List<TreeItem> output, com.jpexs.decompiler.flash.abc.types.MethodBody body, com.jpexs.decompiler.flash.abc.ABC abc, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames) {
TreeItem v = (TreeItem) stack.pop();
stack.push(new NegTreeItem(ins, v));
}
@Override
public int getStackDelta(AVM2Instruction ins, ABC abc) {
return -1 + 1;
}
}
@@ -0,0 +1,46 @@
/*
* Copyright (C) 2010-2013 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.avm2.ConstantPool;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.TreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.operations.NegTreeItem;
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
public class NegateIns extends InstructionDefinition {
public NegateIns() {
super(0x90, "negate", new int[]{});
}
@Override
public void translate(boolean isStatic, int classIndex, java.util.HashMap<Integer, TreeItem> localRegs, Stack<TreeItem> stack, java.util.Stack<TreeItem> scopeStack, ConstantPool constants, AVM2Instruction ins, MethodInfo[] method_info, List<TreeItem> output, com.jpexs.decompiler.flash.abc.types.MethodBody body, com.jpexs.decompiler.flash.abc.ABC abc, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames) {
TreeItem v = (TreeItem) stack.pop();
stack.push(new NegTreeItem(ins, v));
}
@Override
public int getStackDelta(AVM2Instruction ins, ABC abc) {
return -1 + 1;
}
}
@@ -0,0 +1,46 @@
/*
* Copyright (C) 2010-2013 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.avm2.ConstantPool;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.TreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.operations.NotTreeItem;
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
public class NotIns extends InstructionDefinition {
public NotIns() {
super(0x96, "not", new int[]{});
}
@Override
public void translate(boolean isStatic, int classIndex, java.util.HashMap<Integer, TreeItem> localRegs, Stack<TreeItem> stack, java.util.Stack<TreeItem> scopeStack, ConstantPool constants, AVM2Instruction ins, MethodInfo[] method_info, List<TreeItem> output, com.jpexs.decompiler.flash.abc.types.MethodBody body, com.jpexs.decompiler.flash.abc.ABC abc, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames) {
TreeItem v = (TreeItem) stack.pop();
stack.push(new NotTreeItem(ins, v));
}
@Override
public int getStackDelta(AVM2Instruction ins, ABC abc) {
return -1 + 1;
}
}
@@ -0,0 +1,47 @@
/*
* Copyright (C) 2010-2013 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.avm2.ConstantPool;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.TreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.operations.SubtractTreeItem;
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
public class SubtractIIns extends InstructionDefinition {
public SubtractIIns() {
super(0xc6, "subtract_i", new int[]{});
}
@Override
public void translate(boolean isStatic, int classIndex, java.util.HashMap<Integer, TreeItem> localRegs, Stack<TreeItem> stack, java.util.Stack<TreeItem> scopeStack, ConstantPool constants, AVM2Instruction ins, MethodInfo[] method_info, List<TreeItem> output, com.jpexs.decompiler.flash.abc.types.MethodBody body, com.jpexs.decompiler.flash.abc.ABC abc, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames) {
TreeItem v2 = (TreeItem) stack.pop();
TreeItem v1 = (TreeItem) stack.pop();
stack.push(new SubtractTreeItem(ins, v1, v2));
}
@Override
public int getStackDelta(AVM2Instruction ins, ABC abc) {
return -2 + 1;
}
}
@@ -0,0 +1,47 @@
/*
* Copyright (C) 2010-2013 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.avm2.ConstantPool;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.TreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.operations.SubtractTreeItem;
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
public class SubtractIns extends InstructionDefinition {
public SubtractIns() {
super(0xa1, "subtract", new int[]{});
}
@Override
public void translate(boolean isStatic, int classIndex, java.util.HashMap<Integer, TreeItem> localRegs, Stack<TreeItem> stack, java.util.Stack<TreeItem> scopeStack, ConstantPool constants, AVM2Instruction ins, MethodInfo[] method_info, List<TreeItem> output, com.jpexs.decompiler.flash.abc.types.MethodBody body, com.jpexs.decompiler.flash.abc.ABC abc, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames) {
TreeItem v2 = (TreeItem) stack.pop();
TreeItem v1 = (TreeItem) stack.pop();
stack.push(new SubtractTreeItem(ins, v1, v2));
}
@Override
public int getStackDelta(AVM2Instruction ins, ABC abc) {
return -2 + 1;
}
}
@@ -0,0 +1,56 @@
/*
* Copyright (C) 2010-2013 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2.instructions.bitwise;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.avm2.ConstantPool;
import com.jpexs.decompiler.flash.abc.avm2.LocalDataArea;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.TreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.operations.BitAndTreeItem;
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
public class BitAndIns extends InstructionDefinition {
public BitAndIns() {
super(0xa8, "bitand", new int[]{});
}
@Override
public void execute(LocalDataArea lda, ConstantPool constants, List arguments) {
Long value2 = (Long) lda.operandStack.pop();
Long value1 = (Long) lda.operandStack.pop();
Long value3 = value1 & value2;
lda.operandStack.push(value3);
}
@Override
public void translate(boolean isStatic, int classIndex, java.util.HashMap<Integer, TreeItem> localRegs, Stack<TreeItem> stack, java.util.Stack<TreeItem> scopeStack, ConstantPool constants, AVM2Instruction ins, MethodInfo[] method_info, List<TreeItem> output, com.jpexs.decompiler.flash.abc.types.MethodBody body, com.jpexs.decompiler.flash.abc.ABC abc, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames) {
TreeItem v2 = (TreeItem) stack.pop();
TreeItem v1 = (TreeItem) stack.pop();
stack.push(new BitAndTreeItem(ins, v1, v2));
}
@Override
public int getStackDelta(AVM2Instruction ins, ABC abc) {
return -2 + 1;
}
}
@@ -0,0 +1,54 @@
/*
* Copyright (C) 2010-2013 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2.instructions.bitwise;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.avm2.ConstantPool;
import com.jpexs.decompiler.flash.abc.avm2.LocalDataArea;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.TreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.operations.BitNotTreeItem;
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
public class BitNotIns extends InstructionDefinition {
public BitNotIns() {
super(0x97, "bitnot", new int[]{});
}
@Override
public void execute(LocalDataArea lda, ConstantPool constants, List arguments) {
Long value = (Long) lda.operandStack.pop();
Long ret = new Long(-value.longValue());
lda.operandStack.push(ret);
}
@Override
public void translate(boolean isStatic, int classIndex, java.util.HashMap<Integer, TreeItem> localRegs, Stack<TreeItem> stack, java.util.Stack<TreeItem> scopeStack, ConstantPool constants, AVM2Instruction ins, MethodInfo[] method_info, List<TreeItem> output, com.jpexs.decompiler.flash.abc.types.MethodBody body, com.jpexs.decompiler.flash.abc.ABC abc, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames) {
TreeItem v = (TreeItem) stack.pop();
stack.push(new BitNotTreeItem(ins, v));
}
@Override
public int getStackDelta(AVM2Instruction ins, ABC abc) {
return -1 + 1;
}
}
@@ -0,0 +1,56 @@
/*
* Copyright (C) 2010-2013 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2.instructions.bitwise;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.avm2.ConstantPool;
import com.jpexs.decompiler.flash.abc.avm2.LocalDataArea;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.TreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.operations.BitOrTreeItem;
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
public class BitOrIns extends InstructionDefinition {
public BitOrIns() {
super(0xa9, "bitor", new int[]{});
}
@Override
public void execute(LocalDataArea lda, ConstantPool constants, List arguments) {
Long value2 = (Long) lda.operandStack.pop();
Long value1 = (Long) lda.operandStack.pop();
Long value3 = value1 | value2;
lda.operandStack.push(value3);
}
@Override
public void translate(boolean isStatic, int classIndex, java.util.HashMap<Integer, TreeItem> localRegs, Stack<TreeItem> stack, java.util.Stack<TreeItem> scopeStack, ConstantPool constants, AVM2Instruction ins, MethodInfo[] method_info, List<TreeItem> output, com.jpexs.decompiler.flash.abc.types.MethodBody body, com.jpexs.decompiler.flash.abc.ABC abc, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames) {
TreeItem v2 = (TreeItem) stack.pop();
TreeItem v1 = (TreeItem) stack.pop();
stack.push(new BitOrTreeItem(ins, v1, v2));
}
@Override
public int getStackDelta(AVM2Instruction ins, ABC abc) {
return -2 + 1;
}
}
@@ -0,0 +1,56 @@
/*
* Copyright (C) 2010-2013 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2.instructions.bitwise;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.avm2.ConstantPool;
import com.jpexs.decompiler.flash.abc.avm2.LocalDataArea;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.TreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.operations.BitXorTreeItem;
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
public class BitXorIns extends InstructionDefinition {
public BitXorIns() {
super(0xaa, "bitxor", new int[]{});
}
@Override
public void execute(LocalDataArea lda, ConstantPool constants, List arguments) {
Long value2 = (Long) lda.operandStack.pop();
Long value1 = (Long) lda.operandStack.pop();
Long value3 = value1 ^ value2;
lda.operandStack.push(value3);
}
@Override
public void translate(boolean isStatic, int classIndex, java.util.HashMap<Integer, TreeItem> localRegs, Stack<TreeItem> stack, java.util.Stack<TreeItem> scopeStack, ConstantPool constants, AVM2Instruction ins, MethodInfo[] method_info, List<TreeItem> output, com.jpexs.decompiler.flash.abc.types.MethodBody body, com.jpexs.decompiler.flash.abc.ABC abc, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames) {
TreeItem v2 = (TreeItem) stack.pop();
TreeItem v1 = (TreeItem) stack.pop();
stack.push(new BitXorTreeItem(ins, v1, v2));
}
@Override
public int getStackDelta(AVM2Instruction ins, ABC abc) {
return -2 + 1;
}
}
@@ -0,0 +1,47 @@
/*
* Copyright (C) 2010-2013 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2.instructions.bitwise;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.avm2.ConstantPool;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.TreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.operations.LShiftTreeItem;
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
public class LShiftIns extends InstructionDefinition {
public LShiftIns() {
super(0xa5, "lshift", new int[]{});
}
@Override
public void translate(boolean isStatic, int classIndex, java.util.HashMap<Integer, TreeItem> localRegs, Stack<TreeItem> stack, java.util.Stack<TreeItem> scopeStack, ConstantPool constants, AVM2Instruction ins, MethodInfo[] method_info, List<TreeItem> output, com.jpexs.decompiler.flash.abc.types.MethodBody body, com.jpexs.decompiler.flash.abc.ABC abc, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames) {
TreeItem v2 = (TreeItem) stack.pop();
TreeItem v1 = (TreeItem) stack.pop();
stack.push(new LShiftTreeItem(ins, v1, v2));
}
@Override
public int getStackDelta(AVM2Instruction ins, ABC abc) {
return -2 + 1;
}
}
@@ -0,0 +1,47 @@
/*
* Copyright (C) 2010-2013 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2.instructions.bitwise;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.avm2.ConstantPool;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.TreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.operations.RShiftTreeItem;
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
public class RShiftIns extends InstructionDefinition {
public RShiftIns() {
super(0xa6, "rshift", new int[]{});
}
@Override
public void translate(boolean isStatic, int classIndex, java.util.HashMap<Integer, TreeItem> localRegs, Stack<TreeItem> stack, java.util.Stack<TreeItem> scopeStack, ConstantPool constants, AVM2Instruction ins, MethodInfo[] method_info, List<TreeItem> output, com.jpexs.decompiler.flash.abc.types.MethodBody body, com.jpexs.decompiler.flash.abc.ABC abc, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames) {
TreeItem v2 = (TreeItem) stack.pop();
TreeItem v1 = (TreeItem) stack.pop();
stack.push(new RShiftTreeItem(ins, v1, v2));
}
@Override
public int getStackDelta(AVM2Instruction ins, ABC abc) {
return -2 + 1;
}
}
@@ -0,0 +1,47 @@
/*
* Copyright (C) 2010-2013 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2.instructions.bitwise;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.avm2.ConstantPool;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.TreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.operations.URShiftTreeItem;
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
public class URShiftIns extends InstructionDefinition {
public URShiftIns() {
super(0xa7, "urshift", new int[]{});
}
@Override
public void translate(boolean isStatic, int classIndex, java.util.HashMap<Integer, TreeItem> localRegs, Stack<TreeItem> stack, java.util.Stack<TreeItem> scopeStack, ConstantPool constants, AVM2Instruction ins, MethodInfo[] method_info, List<TreeItem> output, com.jpexs.decompiler.flash.abc.types.MethodBody body, com.jpexs.decompiler.flash.abc.ABC abc, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames) {
TreeItem v2 = (TreeItem) stack.pop();
TreeItem v1 = (TreeItem) stack.pop();
stack.push(new URShiftTreeItem(ins, v1, v2));
}
@Override
public int getStackDelta(AVM2Instruction ins, ABC abc) {
return -2 + 1;
}
}
@@ -0,0 +1,56 @@
/*
* Copyright (C) 2010-2013 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2.instructions.comparsion;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.avm2.ConstantPool;
import com.jpexs.decompiler.flash.abc.avm2.LocalDataArea;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.TreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.operations.EqTreeItem;
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
public class EqualsIns extends InstructionDefinition {
public EqualsIns() {
super(0xab, "equals", new int[]{});
}
@Override
public void execute(LocalDataArea lda, ConstantPool constants, List arguments) {
Object obj1 = lda.operandStack.pop();
Object obj2 = lda.operandStack.pop();
Boolean res = obj1.equals(obj2);
lda.operandStack.push(res);
}
@Override
public void translate(boolean isStatic, int classIndex, java.util.HashMap<Integer, TreeItem> localRegs, Stack<TreeItem> stack, java.util.Stack<TreeItem> scopeStack, ConstantPool constants, AVM2Instruction ins, MethodInfo[] method_info, List<TreeItem> output, com.jpexs.decompiler.flash.abc.types.MethodBody body, com.jpexs.decompiler.flash.abc.ABC abc, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames) {
TreeItem v2 = (TreeItem) stack.pop();
TreeItem v1 = (TreeItem) stack.pop();
stack.push(new EqTreeItem(ins, v1, v2));
}
@Override
public int getStackDelta(AVM2Instruction ins, ABC abc) {
return -2 + 1;
}
}
@@ -0,0 +1,47 @@
/*
* Copyright (C) 2010-2013 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2.instructions.comparsion;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.avm2.ConstantPool;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.TreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.operations.GeTreeItem;
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
public class GreaterEqualsIns extends InstructionDefinition {
public GreaterEqualsIns() {
super(0xb0, "greaterequals", new int[]{});
}
@Override
public void translate(boolean isStatic, int classIndex, java.util.HashMap<Integer, TreeItem> localRegs, Stack<TreeItem> stack, java.util.Stack<TreeItem> scopeStack, ConstantPool constants, AVM2Instruction ins, MethodInfo[] method_info, List<TreeItem> output, com.jpexs.decompiler.flash.abc.types.MethodBody body, com.jpexs.decompiler.flash.abc.ABC abc, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames) {
TreeItem v2 = (TreeItem) stack.pop();
TreeItem v1 = (TreeItem) stack.pop();
stack.push(new GeTreeItem(ins, v1, v2));
}
@Override
public int getStackDelta(AVM2Instruction ins, ABC abc) {
return -2 + 1;
}
}
@@ -0,0 +1,47 @@
/*
* Copyright (C) 2010-2013 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2.instructions.comparsion;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.avm2.ConstantPool;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.TreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.operations.LtTreeItem;
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
public class GreaterThanIns extends InstructionDefinition {
public GreaterThanIns() {
super(0xaf, "greaterthan", new int[]{});
}
@Override
public void translate(boolean isStatic, int classIndex, java.util.HashMap<Integer, TreeItem> localRegs, Stack<TreeItem> stack, java.util.Stack<TreeItem> scopeStack, ConstantPool constants, AVM2Instruction ins, MethodInfo[] method_info, List<TreeItem> output, com.jpexs.decompiler.flash.abc.types.MethodBody body, com.jpexs.decompiler.flash.abc.ABC abc, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames) {
TreeItem v2 = (TreeItem) stack.pop();
TreeItem v1 = (TreeItem) stack.pop();
stack.push(new LtTreeItem(ins, v1, v2));
}
@Override
public int getStackDelta(AVM2Instruction ins, ABC abc) {
return -2 + 1;
}
}
@@ -0,0 +1,47 @@
/*
* Copyright (C) 2010-2013 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2.instructions.comparsion;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.avm2.ConstantPool;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.TreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.operations.LeTreeItem;
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
public class LessEqualsIns extends InstructionDefinition {
public LessEqualsIns() {
super(0xae, "lessequals", new int[]{});
}
@Override
public void translate(boolean isStatic, int classIndex, java.util.HashMap<Integer, TreeItem> localRegs, Stack<TreeItem> stack, java.util.Stack<TreeItem> scopeStack, ConstantPool constants, AVM2Instruction ins, MethodInfo[] method_info, List<TreeItem> output, com.jpexs.decompiler.flash.abc.types.MethodBody body, com.jpexs.decompiler.flash.abc.ABC abc, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames) {
TreeItem v2 = (TreeItem) stack.pop();
TreeItem v1 = (TreeItem) stack.pop();
stack.push(new LeTreeItem(ins, v1, v2));
}
@Override
public int getStackDelta(AVM2Instruction ins, ABC abc) {
return -2 + 1;
}
}
@@ -0,0 +1,47 @@
/*
* Copyright (C) 2010-2013 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2.instructions.comparsion;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.avm2.ConstantPool;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.TreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.operations.GtTreeItem;
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
public class LessThanIns extends InstructionDefinition {
public LessThanIns() {
super(0xad, "lessthan", new int[]{});
}
@Override
public void translate(boolean isStatic, int classIndex, java.util.HashMap<Integer, TreeItem> localRegs, Stack<TreeItem> stack, java.util.Stack<TreeItem> scopeStack, ConstantPool constants, AVM2Instruction ins, MethodInfo[] method_info, List<TreeItem> output, com.jpexs.decompiler.flash.abc.types.MethodBody body, com.jpexs.decompiler.flash.abc.ABC abc, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames) {
TreeItem v2 = (TreeItem) stack.pop();
TreeItem v1 = (TreeItem) stack.pop();
stack.push(new GtTreeItem(ins, v1, v2));
}
@Override
public int getStackDelta(AVM2Instruction ins, ABC abc) {
return -2 + 1;
}
}
@@ -0,0 +1,47 @@
/*
* Copyright (C) 2010-2013 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2.instructions.comparsion;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.avm2.ConstantPool;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.TreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.operations.StrictEqTreeItem;
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
public class StrictEqualsIns extends InstructionDefinition {
public StrictEqualsIns() {
super(0xac, "strictequals", new int[]{});
}
@Override
public void translate(boolean isStatic, int classIndex, java.util.HashMap<Integer, TreeItem> localRegs, Stack<TreeItem> stack, java.util.Stack<TreeItem> scopeStack, ConstantPool constants, AVM2Instruction ins, MethodInfo[] method_info, List<TreeItem> output, com.jpexs.decompiler.flash.abc.types.MethodBody body, com.jpexs.decompiler.flash.abc.ABC abc, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames) {
TreeItem v2 = (TreeItem) stack.pop();
TreeItem v1 = (TreeItem) stack.pop();
stack.push(new StrictEqTreeItem(ins, v1, v2));
}
@Override
public int getStackDelta(AVM2Instruction ins, ABC abc) {
return -2 + 1;
}
}
@@ -0,0 +1,118 @@
/*
* Copyright (C) 2010-2013 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2.instructions.construction;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
import com.jpexs.decompiler.flash.abc.avm2.ConstantPool;
import com.jpexs.decompiler.flash.abc.avm2.LocalDataArea;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.ConstructTreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.EscapeXAttrTreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.EscapeXElemTreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.FindPropertyTreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.FullMultinameTreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.GetLexTreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.GetPropertyTreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.StringTreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.TreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.XMLTreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.operations.AddTreeItem;
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
public class ConstructIns extends InstructionDefinition {
public ConstructIns() {
super(0x42, "construct", new int[]{AVM2Code.DAT_ARG_COUNT});
}
@Override
public void execute(LocalDataArea lda, ConstantPool constants, List arguments) {
/*int argCount = (int) ((Long) arguments.get(0)).longValue();
List passArguments = new ArrayList();
for (int i = argCount - 1; i >= 0; i--) {
passArguments.set(i, lda.operandStack.pop());
}
Object obj = lda.operandStack.pop();*/
throw new RuntimeException("Cannot call constructor");
//call construct property of obj
//push new instance
}
public static boolean walkXML(TreeItem item, List<TreeItem> list) {
boolean ret = true;
if (item instanceof StringTreeItem) {
list.add(item);
} else if (item instanceof AddTreeItem) {
ret = ret && walkXML(((AddTreeItem) item).leftSide, list);
ret = ret && walkXML(((AddTreeItem) item).rightSide, list);
} else if ((item instanceof EscapeXElemTreeItem) || (item instanceof EscapeXAttrTreeItem)) {
list.add(item);
} else {
return false;
}
return ret;
}
@Override
public void translate(boolean isStatic, int classIndex, java.util.HashMap<Integer, TreeItem> localRegs, Stack<TreeItem> stack, java.util.Stack<TreeItem> scopeStack, ConstantPool constants, AVM2Instruction ins, MethodInfo[] method_info, List<TreeItem> output, com.jpexs.decompiler.flash.abc.types.MethodBody body, com.jpexs.decompiler.flash.abc.ABC abc, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames) {
int argCount = ins.operands[0];
List<TreeItem> args = new ArrayList<TreeItem>();
for (int a = 0; a < argCount; a++) {
args.add(0, (TreeItem) stack.pop());
}
TreeItem obj = (TreeItem) stack.pop();
FullMultinameTreeItem xmlMult = null;
boolean isXML = false;
if (obj instanceof GetPropertyTreeItem) {
GetPropertyTreeItem gpt = (GetPropertyTreeItem) obj;
if (gpt.object instanceof FindPropertyTreeItem) {
FindPropertyTreeItem fpt = (FindPropertyTreeItem) gpt.object;
xmlMult = fpt.propertyName;
isXML = xmlMult.isXML(constants, localRegNames, fullyQualifiedNames) && xmlMult.isXML(constants, localRegNames, fullyQualifiedNames);
}
}
if (obj instanceof GetLexTreeItem) {
GetLexTreeItem glt = (GetLexTreeItem) obj;
isXML = glt.propertyName.getName(constants, fullyQualifiedNames).equals("XML");
}
if (isXML) {
if (args.size() == 1) {
TreeItem arg = args.get(0);
List<TreeItem> xmlLines = new ArrayList<TreeItem>();
if (walkXML(arg, xmlLines)) {
stack.push(new XMLTreeItem(ins, xmlLines));
return;
}
}
}
stack.push(new ConstructTreeItem(ins, obj, args));
}
@Override
public int getStackDelta(AVM2Instruction ins, ABC abc) {
return -ins.operands[0] - 1 + 1;
}
}
@@ -0,0 +1,93 @@
/*
* Copyright (C) 2010-2013 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2.instructions.construction;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
import com.jpexs.decompiler.flash.abc.avm2.ConstantPool;
import com.jpexs.decompiler.flash.abc.avm2.LocalDataArea;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.ConstructPropTreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.FullMultinameTreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.TreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.XMLTreeItem;
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
public class ConstructPropIns extends InstructionDefinition {
public ConstructPropIns() {
super(0x4a, "constructprop", new int[]{AVM2Code.DAT_MULTINAME_INDEX, AVM2Code.DAT_ARG_COUNT});
}
@Override
public void execute(LocalDataArea lda, ConstantPool constants, List arguments) {
/*int multinameIndex = (int) ((Long) arguments.get(0)).longValue();
int argCount = (int) ((Long) arguments.get(1)).longValue();
List passArguments = new ArrayList();
for (int i = argCount - 1; i >= 0; i--) {
passArguments.set(i, lda.operandStack.pop());
}*/
//if multiname[multinameIndex] is runtime
//pop(name) pop(ns)
throw new RuntimeException("Cannot construct property");
//create property
//push new instance
}
@Override
public void translate(boolean isStatic, int classIndex, java.util.HashMap<Integer, TreeItem> localRegs, Stack<TreeItem> stack, java.util.Stack<TreeItem> scopeStack, ConstantPool constants, AVM2Instruction ins, MethodInfo[] method_info, List<TreeItem> output, com.jpexs.decompiler.flash.abc.types.MethodBody body, com.jpexs.decompiler.flash.abc.ABC abc, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames) {
int multinameIndex = ins.operands[0];
int argCount = ins.operands[1];
List<TreeItem> args = new ArrayList<TreeItem>();
for (int a = 0; a < argCount; a++) {
args.add(0, (TreeItem) stack.pop());
}
FullMultinameTreeItem multiname = resolveMultiname(stack, constants, multinameIndex, ins);
TreeItem obj = (TreeItem) stack.pop();
if (multiname.isXML(constants, localRegNames, fullyQualifiedNames)) {
if (args.size() == 1) {
TreeItem arg = args.get(0);
List<TreeItem> xmlLines = new ArrayList<TreeItem>();
if (ConstructIns.walkXML(arg, xmlLines)) {
stack.push(new XMLTreeItem(ins, xmlLines));
return;
}
}
}
stack.push(new ConstructPropTreeItem(ins, obj, multiname, args));
}
@Override
public int getStackDelta(AVM2Instruction ins, ABC abc) {
int ret = -ins.operands[1] - 1 + 1;
int multinameIndex = ins.operands[0];
if (abc.constants.constant_multiname[multinameIndex].needsName()) {
ret--;
}
if (abc.constants.constant_multiname[multinameIndex].needsNs()) {
ret--;
}
return ret;
}
}
@@ -0,0 +1,67 @@
/*
* Copyright (C) 2010-2013 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2.instructions.construction;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
import com.jpexs.decompiler.flash.abc.avm2.ConstantPool;
import com.jpexs.decompiler.flash.abc.avm2.LocalDataArea;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.ConstructSuperTreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.TreeItem;
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
public class ConstructSuperIns extends InstructionDefinition {
public ConstructSuperIns() {
super(0x49, "constructsuper", new int[]{AVM2Code.DAT_ARG_COUNT});
}
@Override
public void execute(LocalDataArea lda, ConstantPool constants, List arguments) {
/*int argCount = (int) ((Long) arguments.get(0)).longValue();
List passArguments = new ArrayList();
for (int i = argCount - 1; i >= 0; i--) {
passArguments.set(i, lda.operandStack.pop());
}
Object obj = lda.operandStack.pop();*/
throw new RuntimeException("Cannot call super constructor");
//call construct property of obj
//do not push anything
}
@Override
public void translate(boolean isStatic, int classIndex, java.util.HashMap<Integer, TreeItem> localRegs, Stack<TreeItem> stack, java.util.Stack<TreeItem> scopeStack, ConstantPool constants, AVM2Instruction ins, MethodInfo[] method_info, List<TreeItem> output, com.jpexs.decompiler.flash.abc.types.MethodBody body, com.jpexs.decompiler.flash.abc.ABC abc, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames) {
int argCount = ins.operands[0];
List<TreeItem> args = new ArrayList<TreeItem>();
for (int a = 0; a < argCount; a++) {
args.add(0, (TreeItem) stack.pop());
}
TreeItem obj = (TreeItem) stack.pop();
output.add(new ConstructSuperTreeItem(ins, obj, args));
}
@Override
public int getStackDelta(AVM2Instruction ins, ABC abc) {
return -ins.operands[0] - 1;
}
}
@@ -0,0 +1,45 @@
/*
* Copyright (C) 2010-2013 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2.instructions.construction;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.avm2.ConstantPool;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.NewActivationTreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.TreeItem;
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
public class NewActivationIns extends InstructionDefinition {
public NewActivationIns() {
super(0x57, "newactivation", new int[]{});
}
@Override
public void translate(boolean isStatic, int classIndex, java.util.HashMap<Integer, TreeItem> localRegs, Stack<TreeItem> stack, java.util.Stack<TreeItem> scopeStack, ConstantPool constants, AVM2Instruction ins, MethodInfo[] method_info, List<TreeItem> output, com.jpexs.decompiler.flash.abc.types.MethodBody body, com.jpexs.decompiler.flash.abc.ABC abc, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames) {
stack.push(new NewActivationTreeItem(ins));
}
@Override
public int getStackDelta(AVM2Instruction ins, ABC abc) {
return 1;
}
}
@@ -0,0 +1,52 @@
/*
* Copyright (C) 2010-2013 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2.instructions.construction;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
import com.jpexs.decompiler.flash.abc.avm2.ConstantPool;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.NewArrayTreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.TreeItem;
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
public class NewArrayIns extends InstructionDefinition {
public NewArrayIns() {
super(0x56, "newarray", new int[]{AVM2Code.DAT_ARG_COUNT});
}
@Override
public void translate(boolean isStatic, int classIndex, java.util.HashMap<Integer, TreeItem> localRegs, Stack<TreeItem> stack, java.util.Stack<TreeItem> scopeStack, ConstantPool constants, AVM2Instruction ins, MethodInfo[] method_info, List<TreeItem> output, com.jpexs.decompiler.flash.abc.types.MethodBody body, com.jpexs.decompiler.flash.abc.ABC abc, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames) {
int argCount = ins.operands[0];
List<TreeItem> args = new ArrayList<TreeItem>();
for (int a = 0; a < argCount; a++) {
args.add(0, (TreeItem) stack.pop());
}
stack.push(new NewArrayTreeItem(ins, args));
}
@Override
public int getStackDelta(AVM2Instruction ins, ABC abc) {
return -ins.operands[0] + 1;
}
}
@@ -0,0 +1,47 @@
/*
* Copyright (C) 2010-2013 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2.instructions.construction;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
import com.jpexs.decompiler.flash.abc.avm2.ConstantPool;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.TreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.clauses.ExceptionTreeItem;
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
public class NewCatchIns extends InstructionDefinition {
public NewCatchIns() {
super(0x5a, "newcatch", new int[]{AVM2Code.DAT_EXCEPTION_INDEX});
}
@Override
public void translate(boolean isStatic, int classIndex, java.util.HashMap<Integer, TreeItem> localRegs, Stack<TreeItem> stack, java.util.Stack<TreeItem> scopeStack, ConstantPool constants, AVM2Instruction ins, MethodInfo[] method_info, List<TreeItem> output, com.jpexs.decompiler.flash.abc.types.MethodBody body, com.jpexs.decompiler.flash.abc.ABC abc, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames) {
int exInfo = ins.operands[0];
stack.push(new ExceptionTreeItem(body.exceptions[exInfo]));
}
@Override
public int getStackDelta(AVM2Instruction ins, ABC abc) {
return 1;
}
}
@@ -0,0 +1,48 @@
/*
* Copyright (C) 2010-2013 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2.instructions.construction;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
import com.jpexs.decompiler.flash.abc.avm2.ConstantPool;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.TreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.UnparsedTreeItem;
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
public class NewClassIns extends InstructionDefinition {
public NewClassIns() {
super(0x58, "newclass", new int[]{AVM2Code.DAT_CLASS_INDEX});
}
@Override
public void translate(boolean isStatic, int classIndex, java.util.HashMap<Integer, TreeItem> localRegs, Stack<TreeItem> stack, java.util.Stack<TreeItem> scopeStack, ConstantPool constants, AVM2Instruction ins, MethodInfo[] method_info, List<TreeItem> output, com.jpexs.decompiler.flash.abc.types.MethodBody body, com.jpexs.decompiler.flash.abc.ABC abc, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames) {
int clsIndex = ins.operands[0];
String baseType = stack.pop().toString(constants, localRegNames, fullyQualifiedNames);
stack.push(new UnparsedTreeItem(ins, "new " + abc.constants.constant_multiname[abc.instance_info[clsIndex].name_index].getName(constants, fullyQualifiedNames) + ".class extends " + baseType));
}
@Override
public int getStackDelta(AVM2Instruction ins, ABC abc) {
return -1 + 1;
}
}
@@ -0,0 +1,57 @@
/*
* Copyright (C) 2010-2013 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2.instructions.construction;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
import com.jpexs.decompiler.flash.abc.avm2.ConstantPool;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.NewFunctionTreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.TreeItem;
import com.jpexs.decompiler.flash.abc.types.MethodBody;
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
import com.jpexs.decompiler.flash.helpers.Highlighting;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
public class NewFunctionIns extends InstructionDefinition {
public NewFunctionIns() {
super(0x40, "newfunction", new int[]{AVM2Code.DAT_METHOD_INDEX});
}
@Override
public void translate(boolean isStatic, int classIndex, java.util.HashMap<Integer, TreeItem> localRegs, Stack<TreeItem> stack, java.util.Stack<TreeItem> scopeStack, ConstantPool constants, AVM2Instruction ins, MethodInfo[] method_info, List<TreeItem> output, com.jpexs.decompiler.flash.abc.types.MethodBody body, com.jpexs.decompiler.flash.abc.ABC abc, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames) {
int methodIndex = ins.operands[0];
MethodBody mybody = abc.findBody(methodIndex);
String bodyStr = "";
String paramStr = "";
if (mybody != null) {
bodyStr = Highlighting.hilighMethodEnd() + mybody.toString("", false, isStatic, classIndex, abc, constants, method_info, new Stack<TreeItem>()/*scopeStack*/, false, true, fullyQualifiedNames, null) + Highlighting.hilighMethodBegin(body.method_info);
paramStr = method_info[methodIndex].getParamStr(constants, mybody, abc, fullyQualifiedNames);
}
stack.push(new NewFunctionTreeItem(ins, "", paramStr, method_info[methodIndex].getReturnTypeStr(constants, fullyQualifiedNames), bodyStr));
}
@Override
public int getStackDelta(AVM2Instruction ins, ABC abc) {
return 1;
}
}
@@ -0,0 +1,55 @@
/*
* Copyright (C) 2010-2013 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2.instructions.construction;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
import com.jpexs.decompiler.flash.abc.avm2.ConstantPool;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.NameValuePair;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.NewObjectTreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.TreeItem;
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
public class NewObjectIns extends InstructionDefinition {
public NewObjectIns() {
super(0x55, "newobject", new int[]{AVM2Code.DAT_ARG_COUNT});
}
@Override
public void translate(boolean isStatic, int classIndex, java.util.HashMap<Integer, TreeItem> localRegs, Stack<TreeItem> stack, java.util.Stack<TreeItem> scopeStack, ConstantPool constants, AVM2Instruction ins, MethodInfo[] method_info, List<TreeItem> output, com.jpexs.decompiler.flash.abc.types.MethodBody body, com.jpexs.decompiler.flash.abc.ABC abc, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames) {
int argCount = ins.operands[0];
List<NameValuePair> args = new ArrayList<NameValuePair>();
for (int a = 0; a < argCount; a++) {
TreeItem value = (TreeItem) stack.pop();
TreeItem name = (TreeItem) stack.pop();
args.add(0, new NameValuePair(name, value));
}
stack.push(new NewObjectTreeItem(ins, args));
}
@Override
public int getStackDelta(AVM2Instruction ins, ABC abc) {
return -ins.operands[0] * 2 + 1;
}
}
@@ -0,0 +1,27 @@
/*
* Copyright (C) 2010-2013 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2.instructions.debug;
import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
public class DebugFileIns extends InstructionDefinition {
public DebugFileIns() {
super(0xf1, "debugfile", new int[]{AVM2Code.DAT_STRING_INDEX});
}
}
@@ -0,0 +1,27 @@
/*
* Copyright (C) 2010-2013 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2.instructions.debug;
import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
public class DebugIns extends InstructionDefinition {
public DebugIns() {
super(0xef, "debug", new int[]{AVM2Code.DAT_DEBUG_TYPE, AVM2Code.DAT_STRING_INDEX, AVM2Code.DAT_REGISTER_INDEX, AVM2Code.OPT_U30});
}
}
@@ -0,0 +1,27 @@
/*
* Copyright (C) 2010-2013 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2.instructions.debug;
import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
public class DebugLineIns extends InstructionDefinition {
public DebugLineIns() {
super(0xf0, "debugline", new int[]{AVM2Code.DAT_LINENUM});
}
}
@@ -0,0 +1,68 @@
/*
* Copyright (C) 2010-2013 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2.instructions.executing;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
import com.jpexs.decompiler.flash.abc.avm2.ConstantPool;
import com.jpexs.decompiler.flash.abc.avm2.LocalDataArea;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.CallTreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.TreeItem;
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
public class CallIns extends InstructionDefinition {
public CallIns() {
super(0x41, "call", new int[]{AVM2Code.DAT_ARG_COUNT});
}
@Override
public void execute(LocalDataArea lda, ConstantPool constants, List arguments) {
/*int argCount = (int) ((Long) arguments.get(0)).longValue();
List passArguments = new ArrayList();
for (int i = argCount - 1; i >= 0; i--) {
passArguments.set(i, lda.operandStack.pop());
}
Object receiver = lda.operandStack.pop();
Object function = lda.operandStack.pop();*/
throw new RuntimeException("Call to unknown function");
//push(result)
}
@Override
public void translate(boolean isStatic, int classIndex, java.util.HashMap<Integer, TreeItem> localRegs, Stack<TreeItem> stack, java.util.Stack<TreeItem> scopeStack, ConstantPool constants, AVM2Instruction ins, MethodInfo[] method_info, List<TreeItem> output, com.jpexs.decompiler.flash.abc.types.MethodBody body, com.jpexs.decompiler.flash.abc.ABC abc, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames) {
int argCount = ins.operands[0];
List<TreeItem> args = new ArrayList<TreeItem>();
for (int a = 0; a < argCount; a++) {
args.add(0, (TreeItem) stack.pop());
}
TreeItem receiver = (TreeItem) stack.pop();
TreeItem function = (TreeItem) stack.pop();
stack.push(new CallTreeItem(ins, receiver, function, args));
}
@Override
public int getStackDelta(AVM2Instruction ins, ABC abc) {
return -2 + 1 - ins.operands[0];
}
}
@@ -0,0 +1,69 @@
/*
* Copyright (C) 2010-2013 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2.instructions.executing;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
import com.jpexs.decompiler.flash.abc.avm2.ConstantPool;
import com.jpexs.decompiler.flash.abc.avm2.LocalDataArea;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.CallMethodTreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.TreeItem;
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
public class CallMethodIns extends InstructionDefinition {
public CallMethodIns() {
super(0x43, "callmethod", new int[]{AVM2Code.DAT_METHOD_INDEX, AVM2Code.DAT_ARG_COUNT});
}
@Override
public void execute(LocalDataArea lda, ConstantPool constants, List arguments) {
/*int methodIndex = (int) ((Long) arguments.get(0)).longValue(); //index of object's method
int argCount = (int) ((Long) arguments.get(1)).longValue();
List passArguments = new ArrayList();
for (int i = argCount - 1; i >= 0; i--) {
passArguments.set(i, lda.operandStack.pop());
}
Object receiver = lda.operandStack.pop();*/
throw new RuntimeException("Call to unknown method");
//push(result)
}
@Override
public void translate(boolean isStatic, int classIndex, java.util.HashMap<Integer, TreeItem> localRegs, Stack<TreeItem> stack, java.util.Stack<TreeItem> scopeStack, ConstantPool constants, AVM2Instruction ins, MethodInfo[] method_info, List<TreeItem> output, com.jpexs.decompiler.flash.abc.types.MethodBody body, com.jpexs.decompiler.flash.abc.ABC abc, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames) {
int methodIndex = ins.operands[0];
int argCount = ins.operands[1];
List<TreeItem> args = new ArrayList<TreeItem>();
for (int a = 0; a < argCount; a++) {
args.add(0, (TreeItem) stack.pop());
}
TreeItem receiver = (TreeItem) stack.pop();
String methodName = method_info[methodIndex].getName(constants);
stack.push(new CallMethodTreeItem(ins, receiver, methodName, args));
}
@Override
public int getStackDelta(AVM2Instruction ins, ABC abc) {
return -1 + 1 - ins.operands[1];
}
}
@@ -0,0 +1,64 @@
/*
* Copyright (C) 2010-2013 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2.instructions.executing;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.avm2.ConstantPool;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.CallPropertyTreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.FullMultinameTreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.TreeItem;
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
public class CallPropLexIns extends CallPropertyIns {
public CallPropLexIns() {
instructionName = "callproplex";
instructionCode = 0x4c;
}
@Override
public void translate(boolean isStatic, int classIndex, java.util.HashMap<Integer, TreeItem> localRegs, Stack<TreeItem> stack, java.util.Stack<TreeItem> scopeStack, ConstantPool constants, AVM2Instruction ins, MethodInfo[] method_info, List<TreeItem> output, com.jpexs.decompiler.flash.abc.types.MethodBody body, com.jpexs.decompiler.flash.abc.ABC abc, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames) {
int multinameIndex = ins.operands[0];
int argCount = ins.operands[1];
List<TreeItem> args = new ArrayList<TreeItem>();
for (int a = 0; a < argCount; a++) {
args.add(0, (TreeItem) stack.pop());
}
FullMultinameTreeItem multiname = resolveMultiname(stack, constants, multinameIndex, ins);
TreeItem receiver = (TreeItem) stack.pop();
stack.push(new CallPropertyTreeItem(ins, false, receiver, multiname, args));
}
@Override
public int getStackDelta(AVM2Instruction ins, ABC abc) {
int ret = -ins.operands[1] - 1 + 1;
int multinameIndex = ins.operands[0];
if (abc.constants.constant_multiname[multinameIndex].needsName()) {
ret--;
}
if (abc.constants.constant_multiname[multinameIndex].needsNs()) {
ret--;
}
return ret;
}
}
@@ -0,0 +1,84 @@
/*
* Copyright (C) 2010-2013 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2.instructions.executing;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
import com.jpexs.decompiler.flash.abc.avm2.ConstantPool;
import com.jpexs.decompiler.flash.abc.avm2.LocalDataArea;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.CallPropertyTreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.FullMultinameTreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.TreeItem;
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
public class CallPropVoidIns extends InstructionDefinition {
public CallPropVoidIns() {
super(0x4f, "callpropvoid", new int[]{AVM2Code.DAT_MULTINAME_INDEX, AVM2Code.DAT_ARG_COUNT});
}
@Override
public void execute(LocalDataArea lda, ConstantPool constants, List arguments) {
//same as callproperty
/*
int multinameIndex = (int) ((Long) arguments.get(0)).longValue();
int argCount = (int) ((Long) arguments.get(1)).longValue();
List passArguments = new ArrayList();
for (int i = argCount - 1; i >= 0; i--) {
passArguments.set(i, lda.operandStack.pop());
}
//if multiname[multinameIndex] is runtime
//pop(name) pop(ns)
Object obj = lda.operandStack.pop();*/
throw new RuntimeException("Call to unknown property");
//do not push anything
}
@Override
public void translate(boolean isStatic, int classIndex, java.util.HashMap<Integer, TreeItem> localRegs, Stack<TreeItem> stack, java.util.Stack<TreeItem> scopeStack, ConstantPool constants, AVM2Instruction ins, MethodInfo[] method_info, List<TreeItem> output, com.jpexs.decompiler.flash.abc.types.MethodBody body, com.jpexs.decompiler.flash.abc.ABC abc, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames) {
int multinameIndex = ins.operands[0];
int argCount = ins.operands[1];
List<TreeItem> args = new ArrayList<TreeItem>();
for (int a = 0; a < argCount; a++) {
args.add(0, (TreeItem) stack.pop());
}
FullMultinameTreeItem multiname = resolveMultiname(stack, constants, multinameIndex, ins);
TreeItem receiver = (TreeItem) stack.pop();
output.add(new CallPropertyTreeItem(ins, true, receiver, multiname, args));
}
@Override
public int getStackDelta(AVM2Instruction ins, ABC abc) {
int ret = -ins.operands[1] - 1;
int multinameIndex = ins.operands[0];
if (abc.constants.constant_multiname[multinameIndex].needsName()) {
ret--;
}
if (abc.constants.constant_multiname[multinameIndex].needsNs()) {
ret--;
}
return ret;
}
}
@@ -0,0 +1,82 @@
/*
* Copyright (C) 2010-2013 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2.instructions.executing;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
import com.jpexs.decompiler.flash.abc.avm2.ConstantPool;
import com.jpexs.decompiler.flash.abc.avm2.LocalDataArea;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.CallPropertyTreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.FullMultinameTreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.TreeItem;
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
public class CallPropertyIns extends InstructionDefinition {
public CallPropertyIns() {
super(0x46, "callproperty", new int[]{AVM2Code.DAT_MULTINAME_INDEX, AVM2Code.DAT_ARG_COUNT});
}
@Override
public void execute(LocalDataArea lda, ConstantPool constants, List arguments) {
/*int multinameIndex = (int) ((Long) arguments.get(0)).longValue();
int argCount = (int) ((Long) arguments.get(1)).longValue();
List passArguments = new ArrayList();
for (int i = argCount - 1; i >= 0; i--) {
passArguments.set(i, lda.operandStack.pop());
}
//if multiname[multinameIndex] is runtime
//pop(name) pop(ns)
Object obj = lda.operandStack.pop();*/
throw new RuntimeException("Call to unknown property");
//push(result)
}
@Override
public void translate(boolean isStatic, int classIndex, java.util.HashMap<Integer, TreeItem> localRegs, Stack<TreeItem> stack, java.util.Stack<TreeItem> scopeStack, ConstantPool constants, AVM2Instruction ins, MethodInfo[] method_info, List<TreeItem> output, com.jpexs.decompiler.flash.abc.types.MethodBody body, com.jpexs.decompiler.flash.abc.ABC abc, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames) {
int multinameIndex = ins.operands[0];
int argCount = ins.operands[1];
List<TreeItem> args = new ArrayList<TreeItem>();
for (int a = 0; a < argCount; a++) {
args.add(0, (TreeItem) stack.pop());
}
FullMultinameTreeItem multiname = resolveMultiname(stack, constants, multinameIndex, ins);
TreeItem receiver = (TreeItem) stack.pop();
stack.push(new CallPropertyTreeItem(ins, false, receiver, multiname, args));
}
@Override
public int getStackDelta(AVM2Instruction ins, ABC abc) {
int ret = -ins.operands[1] - 1 + 1;
int multinameIndex = ins.operands[0];
if (abc.constants.constant_multiname[multinameIndex].needsName()) {
ret--;
}
if (abc.constants.constant_multiname[multinameIndex].needsNs()) {
ret--;
}
return ret;
}
}
@@ -0,0 +1,69 @@
/*
* Copyright (C) 2010-2013 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2.instructions.executing;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
import com.jpexs.decompiler.flash.abc.avm2.ConstantPool;
import com.jpexs.decompiler.flash.abc.avm2.LocalDataArea;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.CallStaticTreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.TreeItem;
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
public class CallStaticIns extends InstructionDefinition {
public CallStaticIns() {
super(0x44, "callstatic", new int[]{AVM2Code.DAT_METHOD_INDEX, AVM2Code.DAT_ARG_COUNT});
}
@Override
public void execute(LocalDataArea lda, ConstantPool constants, List arguments) {
/*int methodIndex = (int) ((Long) arguments.get(0)).longValue(); //index of method_info
int argCount = (int) ((Long) arguments.get(1)).longValue();
List passArguments = new ArrayList();
for (int i = argCount - 1; i >= 0; i--) {
passArguments.set(i, lda.operandStack.pop());
}
Object receiver = lda.operandStack.pop();*/
throw new RuntimeException("Call to unknown static method");
//push(result)
}
@Override
public void translate(boolean isStatic, int classIndex, java.util.HashMap<Integer, TreeItem> localRegs, Stack<TreeItem> stack, java.util.Stack<TreeItem> scopeStack, ConstantPool constants, AVM2Instruction ins, MethodInfo[] method_info, List<TreeItem> output, com.jpexs.decompiler.flash.abc.types.MethodBody body, com.jpexs.decompiler.flash.abc.ABC abc, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames) {
int methodIndex = ins.operands[0];
int argCount = ins.operands[1];
List<TreeItem> args = new ArrayList<TreeItem>();
for (int a = 0; a < argCount; a++) {
args.add(0, (TreeItem) stack.pop());
}
TreeItem receiver = (TreeItem) stack.pop();
String methodName = method_info[methodIndex].getName(constants);
stack.push(new CallStaticTreeItem(ins, receiver, methodName, args));
}
@Override
public int getStackDelta(AVM2Instruction ins, ABC abc) {
return -1 + 1 - ins.operands[1];
}
}
@@ -0,0 +1,81 @@
/*
* Copyright (C) 2010-2013 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2.instructions.executing;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
import com.jpexs.decompiler.flash.abc.avm2.ConstantPool;
import com.jpexs.decompiler.flash.abc.avm2.LocalDataArea;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.CallSuperTreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.FullMultinameTreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.TreeItem;
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
public class CallSuperIns extends InstructionDefinition {
public CallSuperIns() {
super(0x45, "callsuper", new int[]{AVM2Code.DAT_MULTINAME_INDEX, AVM2Code.DAT_ARG_COUNT});
}
@Override
public void execute(LocalDataArea lda, ConstantPool constants, List arguments) {
/*int multinameIndex = (int) ((Long) arguments.get(0)).longValue();
int argCount = (int) ((Long) arguments.get(1)).longValue();
List passArguments = new ArrayList();
for (int i = argCount - 1; i >= 0; i--) {
passArguments.set(i, lda.operandStack.pop());
}
//if multiname[multinameIndex] is runtime
//pop(name) pop(ns)
Object receiver = lda.operandStack.pop();*/
throw new RuntimeException("Call to unknown super method");
//push(result)
}
@Override
public void translate(boolean isStatic, int classIndex, java.util.HashMap<Integer, TreeItem> localRegs, Stack<TreeItem> stack, java.util.Stack<TreeItem> scopeStack, ConstantPool constants, AVM2Instruction ins, MethodInfo[] method_info, List<TreeItem> output, com.jpexs.decompiler.flash.abc.types.MethodBody body, com.jpexs.decompiler.flash.abc.ABC abc, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames) {
int multinameIndex = ins.operands[0];
int argCount = ins.operands[1];
List<TreeItem> args = new ArrayList<TreeItem>();
for (int a = 0; a < argCount; a++) {
args.add(0, (TreeItem) stack.pop());
}
FullMultinameTreeItem multiname = resolveMultiname(stack, constants, multinameIndex, ins);
TreeItem receiver = (TreeItem) stack.pop();
stack.push(new CallSuperTreeItem(ins, false, receiver, multiname, args));
}
@Override
public int getStackDelta(AVM2Instruction ins, ABC abc) {
int ret = -ins.operands[1] - 1 + 1;
int multinameIndex = ins.operands[0];
if (abc.constants.constant_multiname[multinameIndex].needsName()) {
ret--;
}
if (abc.constants.constant_multiname[multinameIndex].needsNs()) {
ret--;
}
return ret;
}
}
@@ -0,0 +1,82 @@
/*
* Copyright (C) 2010-2013 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2.instructions.executing;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
import com.jpexs.decompiler.flash.abc.avm2.ConstantPool;
import com.jpexs.decompiler.flash.abc.avm2.LocalDataArea;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.CallSuperTreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.FullMultinameTreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.TreeItem;
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
public class CallSuperVoidIns extends InstructionDefinition {
public CallSuperVoidIns() {
super(0x4e, "callsupervoid", new int[]{AVM2Code.DAT_MULTINAME_INDEX, AVM2Code.DAT_ARG_COUNT});
}
@Override
public void execute(LocalDataArea lda, ConstantPool constants, List arguments) {
/*int multinameIndex = (int) ((Long) arguments.get(0)).longValue();
int argCount = (int) ((Long) arguments.get(1)).longValue();
List passArguments = new ArrayList();
for (int i = argCount - 1; i >= 0; i--) {
passArguments.set(i, lda.operandStack.pop());
}
//if multiname[multinameIndex] is runtime
//pop(name) pop(ns)
Object receiver = lda.operandStack.pop();*/
throw new RuntimeException("Call to unknown super method");
//do not push anything
}
@Override
public void translate(boolean isStatic, int classIndex, java.util.HashMap<Integer, TreeItem> localRegs, Stack<TreeItem> stack, java.util.Stack<TreeItem> scopeStack, ConstantPool constants, AVM2Instruction ins, MethodInfo[] method_info, List<TreeItem> output, com.jpexs.decompiler.flash.abc.types.MethodBody body, com.jpexs.decompiler.flash.abc.ABC abc, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames) {
int multinameIndex = ins.operands[0];
int argCount = ins.operands[1];
List<TreeItem> args = new ArrayList<TreeItem>();
for (int a = 0; a < argCount; a++) {
args.add(0, (TreeItem) stack.pop());
}
FullMultinameTreeItem multiname = resolveMultiname(stack, constants, multinameIndex, ins);
TreeItem receiver = (TreeItem) stack.pop();
output.add(new CallSuperTreeItem(ins, true, receiver, multiname, args));
}
@Override
public int getStackDelta(AVM2Instruction ins, ABC abc) {
int ret = -ins.operands[1] - 1;
int multinameIndex = ins.operands[0];
if (abc.constants.constant_multiname[multinameIndex].needsName()) {
ret--;
}
if (abc.constants.constant_multiname[multinameIndex].needsNs()) {
ret--;
}
return ret;
}
}
@@ -0,0 +1,56 @@
/*
* Copyright (C) 2010-2013 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2.instructions.jumps;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
import com.jpexs.decompiler.flash.abc.avm2.ConstantPool;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.IfTypeIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.TreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.operations.EqTreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.operations.NeqTreeItem;
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
public class IfEqIns extends InstructionDefinition implements IfTypeIns {
public IfEqIns() {
super(0x13, "ifeq", new int[]{AVM2Code.DAT_OFFSET});
}
@Override
public void translate(boolean isStatic, int classIndex, java.util.HashMap<Integer, TreeItem> localRegs, Stack<TreeItem> stack, java.util.Stack<TreeItem> scopeStack, ConstantPool constants, AVM2Instruction ins, MethodInfo[] method_info, List<TreeItem> output, com.jpexs.decompiler.flash.abc.types.MethodBody body, com.jpexs.decompiler.flash.abc.ABC abc, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames) {
TreeItem v2 = (TreeItem) stack.pop();
TreeItem v1 = (TreeItem) stack.pop();
stack.push(new EqTreeItem(ins, v1, v2));
}
public void translateInverted(java.util.HashMap<Integer, TreeItem> localRegs, Stack<TreeItem> stack, AVM2Instruction ins) {
TreeItem v2 = (TreeItem) stack.pop();
TreeItem v1 = (TreeItem) stack.pop();
stack.push(new NeqTreeItem(ins, v1, v2));
}
@Override
public int getStackDelta(AVM2Instruction ins, ABC abc) {
return -2;
}
}
@@ -0,0 +1,53 @@
/*
* Copyright (C) 2010-2013 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2.instructions.jumps;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
import com.jpexs.decompiler.flash.abc.avm2.ConstantPool;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.IfTypeIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.TreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.operations.NotTreeItem;
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
public class IfFalseIns extends InstructionDefinition implements IfTypeIns {
public IfFalseIns() {
super(0x12, "iffalse", new int[]{AVM2Code.DAT_OFFSET});
}
@Override
public void translate(boolean isStatic, int classIndex, java.util.HashMap<Integer, TreeItem> localRegs, Stack<TreeItem> stack, java.util.Stack<TreeItem> scopeStack, ConstantPool constants, AVM2Instruction ins, MethodInfo[] method_info, List<TreeItem> output, com.jpexs.decompiler.flash.abc.types.MethodBody body, com.jpexs.decompiler.flash.abc.ABC abc, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames) {
TreeItem v1 = (TreeItem) stack.pop();
stack.push(new NotTreeItem(ins, v1));
}
public void translateInverted(java.util.HashMap<Integer, TreeItem> localRegs, Stack<TreeItem> stack, AVM2Instruction ins) {
//String v1 = stack.pop().toString();
//stack.push("(" + v1 + ")");
}
@Override
public int getStackDelta(AVM2Instruction ins, ABC abc) {
return -1;
}
}
@@ -0,0 +1,56 @@
/*
* Copyright (C) 2010-2013 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2.instructions.jumps;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
import com.jpexs.decompiler.flash.abc.avm2.ConstantPool;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.IfTypeIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.TreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.operations.GeTreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.operations.LtTreeItem;
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
public class IfGeIns extends InstructionDefinition implements IfTypeIns {
public IfGeIns() {
super(0x18, "ifge", new int[]{AVM2Code.DAT_OFFSET});
}
@Override
public void translate(boolean isStatic, int classIndex, java.util.HashMap<Integer, TreeItem> localRegs, Stack<TreeItem> stack, java.util.Stack<TreeItem> scopeStack, ConstantPool constants, AVM2Instruction ins, MethodInfo[] method_info, List<TreeItem> output, com.jpexs.decompiler.flash.abc.types.MethodBody body, com.jpexs.decompiler.flash.abc.ABC abc, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames) {
TreeItem v2 = (TreeItem) stack.pop();
TreeItem v1 = (TreeItem) stack.pop();
stack.push(new GeTreeItem(ins, v1, v2));
}
public void translateInverted(java.util.HashMap<Integer, TreeItem> localRegs, Stack<TreeItem> stack, AVM2Instruction ins) {
TreeItem v2 = (TreeItem) stack.pop();
TreeItem v1 = (TreeItem) stack.pop();
stack.push(new LtTreeItem(ins, v1, v2));
}
@Override
public int getStackDelta(AVM2Instruction ins, ABC abc) {
return -2;
}
}
@@ -0,0 +1,56 @@
/*
* Copyright (C) 2010-2013 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2.instructions.jumps;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
import com.jpexs.decompiler.flash.abc.avm2.ConstantPool;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.IfTypeIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.TreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.operations.GtTreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.operations.LeTreeItem;
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
public class IfGtIns extends InstructionDefinition implements IfTypeIns {
public IfGtIns() {
super(0x17, "ifgt", new int[]{AVM2Code.DAT_OFFSET});
}
@Override
public void translate(boolean isStatic, int classIndex, java.util.HashMap<Integer, TreeItem> localRegs, Stack<TreeItem> stack, java.util.Stack<TreeItem> scopeStack, ConstantPool constants, AVM2Instruction ins, MethodInfo[] method_info, List<TreeItem> output, com.jpexs.decompiler.flash.abc.types.MethodBody body, com.jpexs.decompiler.flash.abc.ABC abc, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames) {
TreeItem v2 = (TreeItem) stack.pop();
TreeItem v1 = (TreeItem) stack.pop();
stack.push(new GtTreeItem(ins, v1, v2));
}
public void translateInverted(java.util.HashMap<Integer, TreeItem> localRegs, Stack<TreeItem> stack, AVM2Instruction ins) {
TreeItem v2 = (TreeItem) stack.pop();
TreeItem v1 = (TreeItem) stack.pop();
stack.push(new LeTreeItem(ins, v1, v2));
}
@Override
public int getStackDelta(AVM2Instruction ins, ABC abc) {
return -2;
}
}
@@ -0,0 +1,56 @@
/*
* Copyright (C) 2010-2013 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2.instructions.jumps;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
import com.jpexs.decompiler.flash.abc.avm2.ConstantPool;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.IfTypeIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.TreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.operations.GtTreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.operations.LeTreeItem;
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
public class IfLeIns extends InstructionDefinition implements IfTypeIns {
public IfLeIns() {
super(0x16, "ifle", new int[]{AVM2Code.DAT_OFFSET});
}
@Override
public void translate(boolean isStatic, int classIndex, java.util.HashMap<Integer, TreeItem> localRegs, Stack<TreeItem> stack, java.util.Stack<TreeItem> scopeStack, ConstantPool constants, AVM2Instruction ins, MethodInfo[] method_info, List<TreeItem> output, com.jpexs.decompiler.flash.abc.types.MethodBody body, com.jpexs.decompiler.flash.abc.ABC abc, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames) {
TreeItem v2 = (TreeItem) stack.pop();
TreeItem v1 = (TreeItem) stack.pop();
stack.push(new LeTreeItem(ins, v1, v2));
}
public void translateInverted(java.util.HashMap<Integer, TreeItem> localRegs, Stack<TreeItem> stack, AVM2Instruction ins) {
TreeItem v2 = (TreeItem) stack.pop();
TreeItem v1 = (TreeItem) stack.pop();
stack.push(new GtTreeItem(ins, v1, v2));
}
@Override
public int getStackDelta(AVM2Instruction ins, ABC abc) {
return -2;
}
}
@@ -0,0 +1,56 @@
/*
* Copyright (C) 2010-2013 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2.instructions.jumps;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
import com.jpexs.decompiler.flash.abc.avm2.ConstantPool;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.IfTypeIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.TreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.operations.GeTreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.operations.LtTreeItem;
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
public class IfLtIns extends InstructionDefinition implements IfTypeIns {
public IfLtIns() {
super(0x15, "iflt", new int[]{AVM2Code.DAT_OFFSET});
}
@Override
public void translate(boolean isStatic, int classIndex, java.util.HashMap<Integer, TreeItem> localRegs, Stack<TreeItem> stack, java.util.Stack<TreeItem> scopeStack, ConstantPool constants, AVM2Instruction ins, MethodInfo[] method_info, List<TreeItem> output, com.jpexs.decompiler.flash.abc.types.MethodBody body, com.jpexs.decompiler.flash.abc.ABC abc, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames) {
TreeItem v2 = (TreeItem) stack.pop();
TreeItem v1 = (TreeItem) stack.pop();
stack.push(new LtTreeItem(ins, v1, v2));
}
public void translateInverted(java.util.HashMap<Integer, TreeItem> localRegs, Stack<TreeItem> stack, AVM2Instruction ins) {
TreeItem v2 = (TreeItem) stack.pop();
TreeItem v1 = (TreeItem) stack.pop();
stack.push(new GeTreeItem(ins, v1, v2));
}
@Override
public int getStackDelta(AVM2Instruction ins, ABC abc) {
return -2;
}
}
@@ -0,0 +1,56 @@
/*
* Copyright (C) 2010-2013 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2.instructions.jumps;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
import com.jpexs.decompiler.flash.abc.avm2.ConstantPool;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.IfTypeIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.TreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.operations.GeTreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.operations.LtTreeItem;
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
public class IfNGeIns extends InstructionDefinition implements IfTypeIns {
public IfNGeIns() {
super(0x0f, "ifnge", new int[]{AVM2Code.DAT_OFFSET});
}
@Override
public void translate(boolean isStatic, int classIndex, java.util.HashMap<Integer, TreeItem> localRegs, Stack<TreeItem> stack, java.util.Stack<TreeItem> scopeStack, ConstantPool constants, AVM2Instruction ins, MethodInfo[] method_info, List<TreeItem> output, com.jpexs.decompiler.flash.abc.types.MethodBody body, com.jpexs.decompiler.flash.abc.ABC abc, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames) {
TreeItem v2 = (TreeItem) stack.pop();
TreeItem v1 = (TreeItem) stack.pop();
stack.push(new LtTreeItem(ins, v1, v2));
}
public void translateInverted(java.util.HashMap<Integer, TreeItem> localRegs, Stack<TreeItem> stack, AVM2Instruction ins) {
TreeItem v2 = (TreeItem) stack.pop();
TreeItem v1 = (TreeItem) stack.pop();
stack.push(new GeTreeItem(ins, v1, v2));
}
@Override
public int getStackDelta(AVM2Instruction ins, ABC abc) {
return -2;
}
}
@@ -0,0 +1,56 @@
/*
* Copyright (C) 2010-2013 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2.instructions.jumps;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
import com.jpexs.decompiler.flash.abc.avm2.ConstantPool;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.IfTypeIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.TreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.operations.GtTreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.operations.LeTreeItem;
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
public class IfNGtIns extends InstructionDefinition implements IfTypeIns {
public IfNGtIns() {
super(0x0e, "ifngt", new int[]{AVM2Code.DAT_OFFSET});
}
@Override
public void translate(boolean isStatic, int classIndex, java.util.HashMap<Integer, TreeItem> localRegs, Stack<TreeItem> stack, java.util.Stack<TreeItem> scopeStack, ConstantPool constants, AVM2Instruction ins, MethodInfo[] method_info, List<TreeItem> output, com.jpexs.decompiler.flash.abc.types.MethodBody body, com.jpexs.decompiler.flash.abc.ABC abc, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames) {
TreeItem v2 = (TreeItem) stack.pop();
TreeItem v1 = (TreeItem) stack.pop();
stack.push(new LeTreeItem(ins, v1, v2));
}
public void translateInverted(java.util.HashMap<Integer, TreeItem> localRegs, Stack<TreeItem> stack, AVM2Instruction ins) {
TreeItem v2 = (TreeItem) stack.pop();
TreeItem v1 = (TreeItem) stack.pop();
stack.push(new GtTreeItem(ins, v1, v2));
}
@Override
public int getStackDelta(AVM2Instruction ins, ABC abc) {
return -2;
}
}
@@ -0,0 +1,56 @@
/*
* Copyright (C) 2010-2013 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2.instructions.jumps;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
import com.jpexs.decompiler.flash.abc.avm2.ConstantPool;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.IfTypeIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.TreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.operations.GtTreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.operations.LeTreeItem;
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
public class IfNLeIns extends InstructionDefinition implements IfTypeIns {
public IfNLeIns() {
super(0x0d, "ifnle", new int[]{AVM2Code.DAT_OFFSET});
}
@Override
public void translate(boolean isStatic, int classIndex, java.util.HashMap<Integer, TreeItem> localRegs, Stack<TreeItem> stack, java.util.Stack<TreeItem> scopeStack, ConstantPool constants, AVM2Instruction ins, MethodInfo[] method_info, List<TreeItem> output, com.jpexs.decompiler.flash.abc.types.MethodBody body, com.jpexs.decompiler.flash.abc.ABC abc, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames) {
TreeItem v2 = (TreeItem) stack.pop();
TreeItem v1 = (TreeItem) stack.pop();
stack.push(new GtTreeItem(ins, v1, v2));
}
public void translateInverted(java.util.HashMap<Integer, TreeItem> localRegs, Stack<TreeItem> stack, AVM2Instruction ins) {
TreeItem v2 = (TreeItem) stack.pop();
TreeItem v1 = (TreeItem) stack.pop();
stack.push(new LeTreeItem(ins, v1, v2));
}
@Override
public int getStackDelta(AVM2Instruction ins, ABC abc) {
return -2;
}
}
@@ -0,0 +1,56 @@
/*
* Copyright (C) 2010-2013 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2.instructions.jumps;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
import com.jpexs.decompiler.flash.abc.avm2.ConstantPool;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.IfTypeIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.TreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.operations.GeTreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.operations.LtTreeItem;
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
public class IfNLtIns extends InstructionDefinition implements IfTypeIns {
public IfNLtIns() {
super(0x0c, "ifnlt", new int[]{AVM2Code.DAT_OFFSET});
}
@Override
public void translate(boolean isStatic, int classIndex, java.util.HashMap<Integer, TreeItem> localRegs, Stack<TreeItem> stack, java.util.Stack<TreeItem> scopeStack, ConstantPool constants, AVM2Instruction ins, MethodInfo[] method_info, List<TreeItem> output, com.jpexs.decompiler.flash.abc.types.MethodBody body, com.jpexs.decompiler.flash.abc.ABC abc, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames) {
TreeItem v2 = (TreeItem) stack.pop();
TreeItem v1 = (TreeItem) stack.pop();
stack.push(new GeTreeItem(ins, v1, v2));
}
public void translateInverted(java.util.HashMap<Integer, TreeItem> localRegs, Stack<TreeItem> stack, AVM2Instruction ins) {
TreeItem v2 = (TreeItem) stack.pop();
TreeItem v1 = (TreeItem) stack.pop();
stack.push(new LtTreeItem(ins, v1, v2));
}
@Override
public int getStackDelta(AVM2Instruction ins, ABC abc) {
return -2;
}
}
@@ -0,0 +1,56 @@
/*
* Copyright (C) 2010-2013 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2.instructions.jumps;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
import com.jpexs.decompiler.flash.abc.avm2.ConstantPool;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.IfTypeIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.TreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.operations.EqTreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.operations.NeqTreeItem;
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
public class IfNeIns extends InstructionDefinition implements IfTypeIns {
public IfNeIns() {
super(0x14, "ifne", new int[]{AVM2Code.DAT_OFFSET});
}
@Override
public void translate(boolean isStatic, int classIndex, java.util.HashMap<Integer, TreeItem> localRegs, Stack<TreeItem> stack, java.util.Stack<TreeItem> scopeStack, ConstantPool constants, AVM2Instruction ins, MethodInfo[] method_info, List<TreeItem> output, com.jpexs.decompiler.flash.abc.types.MethodBody body, com.jpexs.decompiler.flash.abc.ABC abc, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames) {
TreeItem v2 = (TreeItem) stack.pop();
TreeItem v1 = (TreeItem) stack.pop();
stack.push(new NeqTreeItem(ins, v1, v2));
}
public void translateInverted(java.util.HashMap<Integer, TreeItem> localRegs, Stack<TreeItem> stack, AVM2Instruction ins) {
TreeItem v2 = (TreeItem) stack.pop();
TreeItem v1 = (TreeItem) stack.pop();
stack.push(new EqTreeItem(ins, v1, v2));
}
@Override
public int getStackDelta(AVM2Instruction ins, ABC abc) {
return -2;
}
}
@@ -0,0 +1,56 @@
/*
* Copyright (C) 2010-2013 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2.instructions.jumps;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
import com.jpexs.decompiler.flash.abc.avm2.ConstantPool;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.IfTypeIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.TreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.operations.StrictEqTreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.operations.StrictNeqTreeItem;
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
public class IfStrictEqIns extends InstructionDefinition implements IfTypeIns {
public IfStrictEqIns() {
super(0x19, "ifstricteq", new int[]{AVM2Code.DAT_OFFSET});
}
@Override
public void translate(boolean isStatic, int classIndex, java.util.HashMap<Integer, TreeItem> localRegs, Stack<TreeItem> stack, java.util.Stack<TreeItem> scopeStack, ConstantPool constants, AVM2Instruction ins, MethodInfo[] method_info, List<TreeItem> output, com.jpexs.decompiler.flash.abc.types.MethodBody body, com.jpexs.decompiler.flash.abc.ABC abc, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames) {
TreeItem v2 = (TreeItem) stack.pop();
TreeItem v1 = (TreeItem) stack.pop();
stack.push(new StrictEqTreeItem(ins, v1, v2));
}
public void translateInverted(java.util.HashMap<Integer, TreeItem> localRegs, Stack<TreeItem> stack, AVM2Instruction ins) {
TreeItem v2 = (TreeItem) stack.pop();
TreeItem v1 = (TreeItem) stack.pop();
stack.push(new StrictNeqTreeItem(ins, v1, v2));
}
@Override
public int getStackDelta(AVM2Instruction ins, ABC abc) {
return -2;
}
}
@@ -0,0 +1,56 @@
/*
* Copyright (C) 2010-2013 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2.instructions.jumps;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
import com.jpexs.decompiler.flash.abc.avm2.ConstantPool;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.IfTypeIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.TreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.operations.StrictEqTreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.operations.StrictNeqTreeItem;
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
public class IfStrictNeIns extends InstructionDefinition implements IfTypeIns {
public IfStrictNeIns() {
super(0x1A, "ifstrictne", new int[]{AVM2Code.DAT_OFFSET});
}
@Override
public void translate(boolean isStatic, int classIndex, java.util.HashMap<Integer, TreeItem> localRegs, Stack<TreeItem> stack, java.util.Stack<TreeItem> scopeStack, ConstantPool constants, AVM2Instruction ins, MethodInfo[] method_info, List<TreeItem> output, com.jpexs.decompiler.flash.abc.types.MethodBody body, com.jpexs.decompiler.flash.abc.ABC abc, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames) {
TreeItem v2 = (TreeItem) stack.pop();
TreeItem v1 = (TreeItem) stack.pop();
stack.push(new StrictNeqTreeItem(ins, v1, v2));
}
public void translateInverted(java.util.HashMap<Integer, TreeItem> localRegs, Stack<TreeItem> stack, AVM2Instruction ins) {
TreeItem v2 = (TreeItem) stack.pop();
TreeItem v1 = (TreeItem) stack.pop();
stack.push(new StrictEqTreeItem(ins, v1, v2));
}
@Override
public int getStackDelta(AVM2Instruction ins, ABC abc) {
return -2;
}
}
@@ -0,0 +1,53 @@
/*
* Copyright (C) 2010-2013 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2.instructions.jumps;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
import com.jpexs.decompiler.flash.abc.avm2.ConstantPool;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.IfTypeIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.TreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.operations.NotTreeItem;
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
public class IfTrueIns extends InstructionDefinition implements IfTypeIns {
public IfTrueIns() {
super(0x11, "iftrue", new int[]{AVM2Code.DAT_OFFSET});
}
@Override
public void translate(boolean isStatic, int classIndex, java.util.HashMap<Integer, TreeItem> localRegs, Stack<TreeItem> stack, java.util.Stack<TreeItem> scopeStack, ConstantPool constants, AVM2Instruction ins, MethodInfo[] method_info, List<TreeItem> output, com.jpexs.decompiler.flash.abc.types.MethodBody body, com.jpexs.decompiler.flash.abc.ABC abc, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames) {
//String v1 = stack.pop().toString();
//stack.push("(" + v1 + ")");
}
public void translateInverted(java.util.HashMap<Integer, TreeItem> localRegs, Stack<TreeItem> stack, AVM2Instruction ins) {
TreeItem v1 = (TreeItem) stack.pop();
stack.push(new NotTreeItem(ins, v1));
}
@Override
public int getStackDelta(AVM2Instruction ins, ABC abc) {
return -1;
}
}
@@ -0,0 +1,44 @@
/*
* Copyright (C) 2010-2013 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2.instructions.jumps;
import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
import com.jpexs.decompiler.flash.abc.avm2.ConstantPool;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.IfTypeIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.BooleanTreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.TreeItem;
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
public class JumpIns extends InstructionDefinition implements IfTypeIns {
public JumpIns() {
super(0x10, "jump", new int[]{AVM2Code.DAT_OFFSET});
}
@Override
public void translate(boolean isStatic, int classIndex, java.util.HashMap<Integer, TreeItem> localRegs, Stack<TreeItem> stack, java.util.Stack<TreeItem> scopeStack, ConstantPool constants, AVM2Instruction ins, MethodInfo[] method_info, List<TreeItem> output, com.jpexs.decompiler.flash.abc.types.MethodBody body, com.jpexs.decompiler.flash.abc.ABC abc, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames) {
stack.push(new BooleanTreeItem(ins, Boolean.TRUE));// + ins.operands[0]);
}
public void translateInverted(java.util.HashMap<Integer, TreeItem> localRegs, Stack<TreeItem> stack, AVM2Instruction ins) {
}
}
@@ -0,0 +1,47 @@
/*
* Copyright (C) 2010-2013 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2.instructions.jumps;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
import com.jpexs.decompiler.flash.abc.avm2.ConstantPool;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.TreeItem;
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
public class LookupSwitchIns extends InstructionDefinition {
public LookupSwitchIns() {
super(0x1b, "lookupswitch", new int[]{AVM2Code.DAT_CASE_BASEOFFSET, AVM2Code.OPT_CASE_OFFSETS});
}
@Override
public void translate(boolean isStatic, int classIndex, java.util.HashMap<Integer, TreeItem> localRegs, Stack<TreeItem> stack, java.util.Stack<TreeItem> scopeStack, ConstantPool constants, AVM2Instruction ins, MethodInfo[] method_info, List<TreeItem> output, com.jpexs.decompiler.flash.abc.types.MethodBody body, com.jpexs.decompiler.flash.abc.ABC abc, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames) {
int defaultOffset = ins.operands[0];
int caseCount = ins.operands[1];
//stack.push("switch(...)");
}
@Override
public int getStackDelta(AVM2Instruction ins, ABC abc) {
return -1;
}
}
@@ -0,0 +1,61 @@
/*
* Copyright (C) 2010-2013 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2.instructions.localregs;
import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
import com.jpexs.decompiler.flash.abc.avm2.ConstantPool;
import com.jpexs.decompiler.flash.abc.avm2.LocalDataArea;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.DecLocalTreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.TreeItem;
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
public class DecLocalIIns extends InstructionDefinition {
public DecLocalIIns() {
super(0xc3, "declocal_i", new int[]{AVM2Code.DAT_LOCAL_REG_INDEX});
}
@Override
public void execute(LocalDataArea lda, ConstantPool constants, List arguments) {
int locRegIndex = (int) ((Long) arguments.get(0)).longValue();
Object obj = lda.localRegisters.get(locRegIndex);
if (obj instanceof Long) {
Long obj2 = ((Long) obj).longValue() - 1;
lda.localRegisters.put(locRegIndex, obj2);
} else if (obj instanceof Double) {
Double obj2 = ((Double) obj).doubleValue() - 1;
lda.localRegisters.put(locRegIndex, obj2);
}
if (obj instanceof String) {
Double obj2 = Double.parseDouble((String) obj) - 1;
lda.localRegisters.put(locRegIndex, obj2);
} else {
throw new RuntimeException("Cannot decrement local register");
}
}
@Override
public void translate(boolean isStatic, int classIndex, java.util.HashMap<Integer, TreeItem> localRegs, Stack<TreeItem> stack, java.util.Stack<TreeItem> scopeStack, ConstantPool constants, AVM2Instruction ins, MethodInfo[] method_info, List<TreeItem> output, com.jpexs.decompiler.flash.abc.types.MethodBody body, com.jpexs.decompiler.flash.abc.ABC abc, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames) {
int regIndex = ins.operands[0];
output.add(new DecLocalTreeItem(ins, regIndex));
}
}
@@ -0,0 +1,61 @@
/*
* Copyright (C) 2010-2013 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2.instructions.localregs;
import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
import com.jpexs.decompiler.flash.abc.avm2.ConstantPool;
import com.jpexs.decompiler.flash.abc.avm2.LocalDataArea;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.DecLocalTreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.TreeItem;
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
public class DecLocalIns extends InstructionDefinition {
public DecLocalIns() {
super(0x94, "declocal", new int[]{AVM2Code.DAT_LOCAL_REG_INDEX});
}
@Override
public void execute(LocalDataArea lda, ConstantPool constants, List arguments) {
int locRegIndex = (int) ((Long) arguments.get(0)).longValue();
Object obj = lda.localRegisters.get(locRegIndex);
if (obj instanceof Long) {
Long obj2 = ((Long) obj).longValue() - 1;
lda.localRegisters.put(locRegIndex, obj2);
} else if (obj instanceof Double) {
Double obj2 = ((Double) obj).doubleValue() - 1;
lda.localRegisters.put(locRegIndex, obj2);
}
if (obj instanceof String) {
Double obj2 = Double.parseDouble((String) obj) - 1;
lda.localRegisters.put(locRegIndex, obj2);
} else {
throw new RuntimeException("Cannot decrement local register");
}
}
@Override
public void translate(boolean isStatic, int classIndex, java.util.HashMap<Integer, TreeItem> localRegs, Stack<TreeItem> stack, java.util.Stack<TreeItem> scopeStack, ConstantPool constants, AVM2Instruction ins, MethodInfo[] method_info, List<TreeItem> output, com.jpexs.decompiler.flash.abc.types.MethodBody body, com.jpexs.decompiler.flash.abc.ABC abc, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames) {
int regIndex = ins.operands[0];
output.add(new DecLocalTreeItem(ins, regIndex));
}
}
@@ -0,0 +1,60 @@
/*
* Copyright (C) 2010-2013 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2.instructions.localregs;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.avm2.ConstantPool;
import com.jpexs.decompiler.flash.abc.avm2.LocalDataArea;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.ClassTreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.ThisTreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.TreeItem;
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
public class GetLocal0Ins extends InstructionDefinition implements GetLocalTypeIns {
public GetLocal0Ins() {
super(0xd0, "getlocal_0", new int[]{});
}
@Override
public void execute(LocalDataArea lda, ConstantPool constants, List arguments) {
lda.operandStack.push(lda.localRegisters.get(0));
}
@Override
public void translate(boolean isStatic, int classIndex, java.util.HashMap<Integer, TreeItem> localRegs, Stack<TreeItem> stack, java.util.Stack<TreeItem> scopeStack, ConstantPool constants, AVM2Instruction ins, MethodInfo[] method_info, List<TreeItem> output, com.jpexs.decompiler.flash.abc.types.MethodBody body, com.jpexs.decompiler.flash.abc.ABC abc, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames) {
if (isStatic) {
stack.push(new ClassTreeItem(abc.instance_info[classIndex].getName(constants)));
} else {
stack.push(new ThisTreeItem(abc.instance_info[classIndex].getName(constants)));
}
}
public int getRegisterId(AVM2Instruction par0) {
return 0;
}
@Override
public int getStackDelta(AVM2Instruction ins, ABC abc) {
return 1;
}
}
@@ -0,0 +1,55 @@
/*
* Copyright (C) 2010-2013 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2.instructions.localregs;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.avm2.ConstantPool;
import com.jpexs.decompiler.flash.abc.avm2.LocalDataArea;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.LocalRegTreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.TreeItem;
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
public class GetLocal1Ins extends InstructionDefinition implements GetLocalTypeIns {
public GetLocal1Ins() {
super(0xd1, "getlocal_1", new int[]{});
}
@Override
public void execute(LocalDataArea lda, ConstantPool constants, List arguments) {
lda.operandStack.push(lda.localRegisters.get(1));
}
@Override
public void translate(boolean isStatic, int classIndex, java.util.HashMap<Integer, TreeItem> localRegs, Stack<TreeItem> stack, java.util.Stack<TreeItem> scopeStack, ConstantPool constants, AVM2Instruction ins, MethodInfo[] method_info, List<TreeItem> output, com.jpexs.decompiler.flash.abc.types.MethodBody body, com.jpexs.decompiler.flash.abc.ABC abc, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames) {
stack.push(new LocalRegTreeItem(ins, 1, localRegs.get(1)));
}
public int getRegisterId(AVM2Instruction par0) {
return 1;
}
@Override
public int getStackDelta(AVM2Instruction ins, ABC abc) {
return 1;
}
}
@@ -0,0 +1,55 @@
/*
* Copyright (C) 2010-2013 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2.instructions.localregs;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.avm2.ConstantPool;
import com.jpexs.decompiler.flash.abc.avm2.LocalDataArea;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.LocalRegTreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.TreeItem;
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
public class GetLocal2Ins extends InstructionDefinition implements GetLocalTypeIns {
public GetLocal2Ins() {
super(0xd2, "getlocal_2", new int[]{});
}
@Override
public void execute(LocalDataArea lda, ConstantPool constants, List arguments) {
lda.operandStack.push(lda.localRegisters.get(2));
}
@Override
public void translate(boolean isStatic, int classIndex, java.util.HashMap<Integer, TreeItem> localRegs, Stack<TreeItem> stack, java.util.Stack<TreeItem> scopeStack, ConstantPool constants, AVM2Instruction ins, MethodInfo[] method_info, List<TreeItem> output, com.jpexs.decompiler.flash.abc.types.MethodBody body, com.jpexs.decompiler.flash.abc.ABC abc, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames) {
stack.push(new LocalRegTreeItem(ins, 2, localRegs.get(2)));
}
public int getRegisterId(AVM2Instruction par0) {
return 2;
}
@Override
public int getStackDelta(AVM2Instruction ins, ABC abc) {
return 1;
}
}
@@ -0,0 +1,55 @@
/*
* Copyright (C) 2010-2013 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2.instructions.localregs;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.avm2.ConstantPool;
import com.jpexs.decompiler.flash.abc.avm2.LocalDataArea;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.LocalRegTreeItem;
import com.jpexs.decompiler.flash.abc.avm2.treemodel.TreeItem;
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
public class GetLocal3Ins extends InstructionDefinition implements GetLocalTypeIns {
public GetLocal3Ins() {
super(0xd3, "getlocal_3", new int[]{});
}
@Override
public void execute(LocalDataArea lda, ConstantPool constants, List arguments) {
lda.operandStack.push(lda.localRegisters.get(3));
}
@Override
public void translate(boolean isStatic, int classIndex, java.util.HashMap<Integer, TreeItem> localRegs, Stack<TreeItem> stack, java.util.Stack<TreeItem> scopeStack, ConstantPool constants, AVM2Instruction ins, MethodInfo[] method_info, List<TreeItem> output, com.jpexs.decompiler.flash.abc.types.MethodBody body, com.jpexs.decompiler.flash.abc.ABC abc, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames) {
stack.push(new LocalRegTreeItem(ins, 3, localRegs.get(3)));
}
public int getRegisterId(AVM2Instruction par0) {
return 3;
}
@Override
public int getStackDelta(AVM2Instruction ins, ABC abc) {
return 1;
}
}

Some files were not shown because too many files have changed in this diff Show More