Merge origin/master

This commit is contained in:
Jindra Petřík
2014-08-30 22:01:47 +02:00
9 changed files with 447 additions and 206 deletions

View File

@@ -16,7 +16,6 @@
*/
package com.jpexs.decompiler.flash.action;
import com.jpexs.decompiler.flash.AppResources;
import com.jpexs.decompiler.flash.DisassemblyListener;
import com.jpexs.decompiler.flash.SWFInputStream;
import com.jpexs.decompiler.flash.action.deobfuscation.ActionDeobfuscator;

View File

@@ -1262,13 +1262,13 @@ public class CommandLineArgumentParser {
} catch (NumberFormatException nfe) {
System.err.println("CharacterId should be integer");
badArguments();
System.exit(1);
}
int characterId = Integer.parseInt(args.remove());
SWF swf = new SWF(is, Configuration.parallelSpeedUp.get());
if (!swf.characters.containsKey(characterId)) {
System.err.println("CharacterId not exits");
badArguments();
System.exit(1);
}
CharacterTag characterTag = swf.characters.get(characterId);
@@ -1281,7 +1281,7 @@ public class CommandLineArgumentParser {
new ImageImporter().importImage(imageTag, data);
} else {
System.err.println("The specified tag type it not supported for import");
badArguments();
System.exit(1);
}
try {

View File

@@ -16,6 +16,7 @@
*/
package com.jpexs.decompiler.flash.gui;
import com.jpexs.decompiler.flash.gui.hexview.HexView;
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.event.ComponentEvent;

View File

@@ -1,196 +0,0 @@
/*
* Copyright (C) 2010-2014 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.gui;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Rectangle;
import javax.swing.JLabel;
import javax.swing.JTable;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableColumn;
/**
*
* @author JPEXS
*/
public class HexView extends JTable {
private final int bytesInRow = 16;
private long[] highlightStarts;
private long[] highlightEnds;
private byte[] data;
private final String[] highlightColorsStr = new String[]{/*"EEEEEE", */"29AEC2", "9AC88C", "DF5F80", "EEA32E", "FFD200", "5E9B4C", "D3E976", "A3AEC2"};
private final Color[] highlightColors;
private Color bgColor = Color.decode("#F7F7F7");
private Color bgColorAlternate = Color.decode("#EDEDED");
public class HighlightCellRenderer extends DefaultTableCellRenderer {
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int col) {
JLabel l = (JLabel) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, col);
int level = -1;
if (col > 0 && highlightStarts != null) {
if (col != bytesInRow + 1) {
int idx = row * bytesInRow + ((col > bytesInRow + 1) ? (col - bytesInRow - 2) : (col - 1));
for (int i = 0; i < highlightStarts.length; i++) {
if (highlightStarts[i] <= idx && highlightEnds[i] >= idx) {
level++;
} else {
break;
}
}
}
}
if (level > -1) {
l.setForeground(Color.white);
l.setBackground(highlightColors[level % highlightColors.length]);
} else {
l.setForeground(Color.black);
l.setBackground(row % 2 == 0 ? bgColor : bgColorAlternate);
}
return l;
}
}
public HexView() {
highlightColors = new Color[highlightColorsStr.length];
for (int i = 0; i < highlightColors.length; i++) {
highlightColors[i] = Color.decode("#" + highlightColorsStr[i]);
}
setModel(new AbstractTableModel() {
@Override
public int getRowCount() {
if (data == null) {
return 0;
}
int byteCount = data.length;
int rowCount = byteCount / bytesInRow;
if (byteCount % bytesInRow != 0) {
rowCount++;
}
return rowCount;
}
@Override
public int getColumnCount() {
return 2 * bytesInRow + 1 + 1;
}
@Override
public String getColumnName(int column) {
if (column == 0) {
return "Address";
} else if (column <= bytesInRow) {
return String.format("%01X", column - 1);
}
return "";
}
@Override
public Object getValueAt(int row, int column) {
if (column == 0) {
return String.format("%08X", (long) row * bytesInRow);
} else if (column <= bytesInRow) {
int pos = row * bytesInRow + column - 1;
if (pos < data.length) {
return String.format("%02X", data[pos]);
}
return null;
} else if (column == 1 + bytesInRow) {
return null;
} else {
int pos = row * bytesInRow + column - bytesInRow - 1 - 1;
if (pos < data.length) {
return (char) data[pos];
}
return null;
}
}
});
setBackground(Color.white);
setFont(new Font("Monospaced", Font.PLAIN, 12));
setTableHeader(new JTableHeader());
setMaximumSize(new Dimension(200, 200));
setShowHorizontalLines(false);
setShowVerticalLines(false);
setRowSelectionAllowed(false);
setColumnSelectionAllowed(false);
HighlightCellRenderer cellRenderer = new HighlightCellRenderer();
TableColumn column = columnModel.getColumn(0);
column.setMaxWidth(80);
//column.setCellRenderer(cellRenderer);
for (int i = 0; i < bytesInRow; i++) {
column = columnModel.getColumn(i + 1);
column.setMaxWidth(25);
column.setCellRenderer(cellRenderer);
}
column = columnModel.getColumn(bytesInRow + 1);
column.setMaxWidth(10);
for (int i = 0; i < bytesInRow; i++) {
column = columnModel.getColumn(i + bytesInRow + 1 + 1);
column.setMaxWidth(10);
column.setCellRenderer(cellRenderer);
}
}
public void setData(byte[] data, long[] highlightStarts, long[] highlightEnds) {
if ((highlightStarts == null) ^ (highlightEnds == null)) {
throw new Error("highlightStarts and highlightEnds should be both null or not null.");
}
if (highlightStarts != null && highlightStarts.length != highlightEnds.length) {
throw new Error("highlightStarts and highlightEnds should have the same number of elements.");
}
this.data = data;
this.highlightStarts = highlightStarts;
this.highlightEnds = highlightEnds;
}
public void scrollToByte(long byteNum) {
int row = (int) (byteNum / bytesInRow);
//final int pageSize = (int) (getParent().getSize().getHeight() / getRowHeight());
getSelectionModel().setSelectionInterval(row, row);
scrollRectToVisible(new Rectangle(getCellRect(row, 0, true)));
}
public void scrollToByte(long[] byteNumStarts, long[] byteNumEnds) {
for (int i = 0; i < byteNumStarts.length; i++) {
scrollToByte(byteNumStarts[i]);
scrollToByte(byteNumEnds[i]);
scrollToByte(byteNumStarts[i]);
}
}
}

View File

@@ -358,7 +358,7 @@ public final class MainPanel extends JPanel implements ActionListener, TreeSelec
private JPanel createDumpPreviewCard() {
JPanel dumpViewCard = new JPanel(new BorderLayout());
dumpViewPanel = new DumpViewPanel();
dumpViewPanel = new DumpViewPanel(dumpTree);
dumpViewCard.add(new JScrollPane(dumpViewPanel), BorderLayout.CENTER);
return dumpViewCard;
@@ -2172,8 +2172,8 @@ public final class MainPanel extends JPanel implements ActionListener, TreeSelec
return;
}
dumpViewPanel.setData(DumpInfoSwfNode.getSwfNode(dumpInfo).getSwf().originalUncompressedData, dumpInfo);
dumpViewPanel.revalidate();
dumpViewPanel.setSelectedNode(dumpInfo);
showCard(CARDDUMPVIEW);
}

View File

@@ -17,7 +17,10 @@
package com.jpexs.decompiler.flash.gui.dumpview;
import com.jpexs.decompiler.flash.dumpview.DumpInfo;
import com.jpexs.decompiler.flash.gui.HexView;
import com.jpexs.decompiler.flash.dumpview.DumpInfoSwfNode;
import com.jpexs.decompiler.flash.gui.hexview.HexView;
import com.jpexs.decompiler.flash.gui.hexview.HexViewListener;
import com.jpexs.helpers.Helper;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.util.ArrayList;
@@ -25,6 +28,8 @@ import java.util.List;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreePath;
/**
*
@@ -32,21 +37,89 @@ import javax.swing.JScrollPane;
*/
public class DumpViewPanel extends JPanel {
private final JLabel selectedByteInfo;
private final JLabel dumpViewLabel;
private final HexView dumpViewHexTable;
private final DumpTree dumpTree;
private DumpInfo selectedDumpInfo;
private boolean skipNextScroll;
private boolean skipValueChange;
public DumpViewPanel() {
public DumpViewPanel(final DumpTree dumpTree) {
super(new BorderLayout());
this.dumpTree = dumpTree;
selectedByteInfo = new JLabel();
selectedByteInfo.setMinimumSize(new Dimension(100, 20));
selectedByteInfo.setText("-");
add(selectedByteInfo, BorderLayout.NORTH);
dumpViewLabel = new JLabel();
dumpViewLabel.setMinimumSize(new Dimension(100, 20));
dumpViewLabel.setText("-");
add(dumpViewLabel, BorderLayout.SOUTH);
dumpViewHexTable = new HexView();
dumpViewHexTable.addListener(new HexViewListener() {
@Override
public void byteValueChanged(int address, byte b) {
if (skipValueChange) {
return;
}
TreeModel model = dumpTree.getModel();
DumpInfo di = DumpInfoSwfNode.getSwfNode(selectedDumpInfo);
while (model.getChildCount(di) > 0) {
boolean found = false;
for (DumpInfo child : di.getChildInfos()) {
if (child.startByte > address) {
break;
}
if (child.getEndByte() >= address) {
di = child;
found = true;
}
}
if (!found) {
break;
}
}
List<Object> path = new ArrayList<>();
while (di != null) {
path.add(0, di);
di = di.parent;
}
path.add(0, model.getRoot());
TreePath tp = new TreePath(path.toArray());
skipNextScroll = true;
dumpTree.setSelectionPath(tp);
dumpTree.scrollPathToVisible(tp);
}
@Override
public void byteMouseMoved(int address, byte b) {
int b2 = b & 0xff;
selectedByteInfo.setText("Addr: " + Helper.padZeros(address, 8) +
" Hex: " + Helper.padZeros(Integer.toHexString(b2), 2) +
" Dec: " + b2 +
" Bin: " + Helper.padZeros(Integer.toBinaryString(b2), 8) +
" Ascii: " + (char) b2);
}
});
add(new JScrollPane(dumpViewHexTable), BorderLayout.CENTER);
}
public void setData(byte[] data, DumpInfo dumpInfo) {
public void setSelectedNode(DumpInfo dumpInfo) {
if (this.selectedDumpInfo == dumpInfo) {
skipNextScroll = false;
return;
}
this.selectedDumpInfo = dumpInfo;
byte[] data = DumpInfoSwfNode.getSwfNode(dumpInfo).getSwf().originalUncompressedData;
List<DumpInfo> dumpInfos = new ArrayList<>();
DumpInfo di = dumpInfo;
while (di.parent != null) {
@@ -61,12 +134,17 @@ public class DumpViewPanel extends JPanel {
highlightEnds[i] = di2.getEndByte();
}
dumpViewHexTable.setData(data, highlightStarts, highlightEnds);
dumpViewHexTable.revalidate();
if (dumpInfo.lengthBytes != 0 || dumpInfo.lengthBits != 0) {
int selectionStart = (int) dumpInfo.startByte;
int selectionEnd = (int) dumpInfo.getEndByte();
dumpViewHexTable.scrollToByte(highlightStarts, highlightEnds);
if (!skipNextScroll) {
skipValueChange = true;
dumpViewHexTable.scrollToByte(highlightStarts, highlightEnds);
skipValueChange = false;
}
setLabelText("startByte: " + dumpInfo.startByte
+ " startBit: " + dumpInfo.startBit
@@ -76,6 +154,7 @@ public class DumpViewPanel extends JPanel {
+ " selectionEnd: " + selectionEnd);
}
skipNextScroll = false;
repaint();
}

View File

@@ -0,0 +1,235 @@
/*
* Copyright (C) 2010-2014 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.gui.hexview;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import javax.swing.JLabel;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableColumn;
import javax.swing.table.TableModel;
/**
*
* @author JPEXS
*/
public class HexView extends JTable {
private static final int bytesInRow = 16;
private long[] highlightStarts;
private long[] highlightEnds;
private final String[] highlightColorsStr = new String[]{/*"EEEEEE", */"29AEC2", "9AC88C", "DF5F80", "EEA32E", "FFD200", "5E9B4C", "D3E976", "A3AEC2"};
private final Color[] highlightColors;
private final Color bgColor = Color.decode("#F7F7F7");
private final Color bgColorAlternate = Color.decode("#EDEDED");
private int itsRow = 0;
private int itsColumn = 0;
private HexViewListener listener;
private class HighlightCellRenderer extends DefaultTableCellRenderer {
public int byteIndex;
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int col) {
JLabel l = (JLabel) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, col);
int level = -1;
if (col > 0 && highlightStarts != null && col != bytesInRow + 1) {
int idx = row * bytesInRow + ((col > bytesInRow + 1) ? (col - bytesInRow - 2) : (col - 1));
byteIndex = idx;
for (int i = 0; i < highlightStarts.length; i++) {
if (highlightStarts[i] <= idx && highlightEnds[i] >= idx) {
level++;
} else {
break;
}
}
}
Color foreground;
Color background;
if (level > -1) {
foreground = Color.white;
background = highlightColors[level % highlightColors.length];
} else {
foreground = Color.black;
background = row % 2 == 0 ? bgColor : bgColorAlternate;
}
if (col == itsColumn && row == itsRow) {
foreground = new Color(255 - foreground.getRed(), 255 - foreground.getGreen(), 255 - foreground.getBlue());
background = new Color(255 - background.getRed(), 255 - background.getGreen(), 255 - background.getBlue());
}
l.setForeground(foreground);
l.setBackground(background);
return l;
}
}
private class HexViewSelectionListener implements ListSelectionListener {
private final HexView table;
public HexViewSelectionListener(HexView table) {
this.table = table;
}
@Override
public void valueChanged(ListSelectionEvent e) {
int col = table.getSelectedColumn();
int row = table.getSelectedRow();
if (col > 0 && highlightStarts != null && col != bytesInRow + 1) {
int idx = row * bytesInRow + ((col > bytesInRow + 1) ? (col - bytesInRow - 2) : (col - 1));
byte[] data = getModel().getData();
if (idx < data.length) {
if (listener != null) {
listener.byteValueChanged(idx, data[idx]);
}
}
}
}
}
private class HexViewMouseAdapter extends MouseAdapter {
@Override
public void mouseClicked(MouseEvent e) {
}
}
private class HexViewMouseMotionAdapter extends MouseMotionAdapter {
@Override
public void mouseMoved(MouseEvent e) {
HexView table = (HexView) e.getSource();
Point point = e.getPoint();
int col = table.columnAtPoint(point);
int row = table.rowAtPoint(point);
itsColumn = col;
itsRow = row;
getModel().fireTableCellUpdated(row, col);
if (listener != null) {
int idx = row * bytesInRow + ((col > bytesInRow + 1) ? (col - bytesInRow - 2) : (col - 1));
listener.byteMouseMoved(idx, getModel().getData()[idx]);
}
}
}
public HexView() {
super(new HexViewTableModel(bytesInRow));
highlightColors = new Color[highlightColorsStr.length];
for (int i = 0; i < highlightColors.length; i++) {
highlightColors[i] = Color.decode("#" + highlightColorsStr[i]);
}
setBackground(Color.white);
setFont(new Font("Monospaced", Font.PLAIN, 12));
setTableHeader(new JTableHeader());
setMaximumSize(new Dimension(200, 200));
setShowHorizontalLines(false);
setShowVerticalLines(false);
setRowSelectionAllowed(false);
setColumnSelectionAllowed(false);
HighlightCellRenderer cellRenderer = new HighlightCellRenderer();
TableColumn column = columnModel.getColumn(0);
column.setMaxWidth(80);
for (int i = 0; i < bytesInRow; i++) {
column = columnModel.getColumn(i + 1);
column.setMaxWidth(25);
column.setCellRenderer(cellRenderer);
}
column = columnModel.getColumn(bytesInRow + 1);
column.setMaxWidth(10);
for (int i = 0; i < bytesInRow; i++) {
column = columnModel.getColumn(i + bytesInRow + 1 + 1);
column.setMaxWidth(10);
column.setCellRenderer(cellRenderer);
}
addMouseListener(new HexViewMouseAdapter());
addMouseMotionListener(new HexViewMouseMotionAdapter());
ListSelectionModel rowSelModel = getSelectionModel();
ListSelectionModel colSelModel = getColumnModel().getSelectionModel();
ListSelectionListener selectionListener = new HexViewSelectionListener(this);
rowSelModel.addListSelectionListener(selectionListener);
colSelModel.addListSelectionListener(selectionListener);
}
@Override
public HexViewTableModel getModel() {
TableModel model = super.getModel();
return (HexViewTableModel) model;
}
public void setData(byte[] data, long[] highlightStarts, long[] highlightEnds) {
if ((highlightStarts == null) ^ (highlightEnds == null)) {
throw new Error("highlightStarts and highlightEnds should be both null or not null.");
}
if (highlightStarts != null && highlightStarts.length != highlightEnds.length) {
throw new Error("highlightStarts and highlightEnds should have the same number of elements.");
}
getModel().setData(data);
this.highlightStarts = highlightStarts;
this.highlightEnds = highlightEnds;
}
public void scrollToByte(long byteNum) {
int row = (int) (byteNum / bytesInRow);
//final int pageSize = (int) (getParent().getSize().getHeight() / getRowHeight());
getSelectionModel().setSelectionInterval(row, row);
scrollRectToVisible(new Rectangle(getCellRect(row, 0, true)));
}
public void scrollToByte(long[] byteNumStarts, long[] byteNumEnds) {
for (int i = 0; i < byteNumStarts.length; i++) {
scrollToByte(byteNumStarts[i]);
scrollToByte(byteNumEnds[i]);
scrollToByte(byteNumStarts[i]);
}
}
public void addListener(HexViewListener listener) {
this.listener = listener;
}
}

View File

@@ -0,0 +1,28 @@
/*
* Copyright (C) 2010-2014 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.gui.hexview;
/**
*
* @author JPEXS
*/
public interface HexViewListener {
public void byteValueChanged(int address, byte b);
public void byteMouseMoved(int address, byte b);
}

View File

@@ -0,0 +1,95 @@
/*
* Copyright (C) 2010-2014 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.gui.hexview;
import javax.swing.table.AbstractTableModel;
/**
*
* @author JPEXS
*/
public class HexViewTableModel extends AbstractTableModel {
private byte[] data;
private final int bytesInRow;
public HexViewTableModel(int bytesInRow) {
this.bytesInRow = bytesInRow;
}
@Override
public int getRowCount() {
if (data == null) {
return 0;
}
int byteCount = data.length;
int rowCount = byteCount / bytesInRow;
if (byteCount % bytesInRow != 0) {
rowCount++;
}
return rowCount;
}
@Override
public int getColumnCount() {
return 2 * bytesInRow + 1 + 1;
}
@Override
public String getColumnName(int column) {
if (column == 0) {
return "Address";
} else if (column <= bytesInRow) {
return String.format("%01X", column - 1);
}
return "";
}
@Override
public Object getValueAt(int row, int column) {
if (column == 0) {
return String.format("%08X", (long) row * bytesInRow);
} else if (column <= bytesInRow) {
int pos = row * bytesInRow + column - 1;
if (pos < data.length) {
return String.format("%02X", data[pos]);
}
return null;
} else if (column == 1 + bytesInRow) {
return null;
} else {
int pos = row * bytesInRow + column - bytesInRow - 1 - 1;
if (pos < data.length) {
return (char) (data[pos] & 0xff);
}
return null;
}
}
public byte[] getData() {
return data;
}
public void setData(byte[] data) {
this.data = data;
}
@Override
public void fireTableCellUpdated(int row, int columnd) {
super.fireTableCellUpdated(bytesInRow, bytesInRow);
}
}