jace/src/main/java/jace/cheat/MemorySpy.java

396 lines
19 KiB
Java

/*
* Copyright (C) 2012 Brendan Robert (BLuRry) brendan.robert@gmail.com.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
package jace.cheat;
import jace.core.Utility;
import static jace.core.Utility.gripe;
/**
* This represents the window of the memory spy module. The memory view itself
* is implemented in MemorySpyGrid.
*
* @author Brendan Robert (BLuRry) brendan.robert@gmail.com
*/
public class MemorySpy extends javax.swing.JFrame {
static MemorySpy singleton = null;
/**
* Creates new form MemorySpy
*/
public MemorySpy() {
initComponents();
setDefaultCloseOperation(HIDE_ON_CLOSE);
singleton = this;
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
mapType = new javax.swing.ButtonGroup();
viewScroll = new javax.swing.JScrollPane();
memorySpyGrid = new jace.cheat.MemorySpyGrid();
controlPanel = new javax.swing.JPanel();
showLabel = new javax.swing.JLabel();
zoomAmount = new javax.swing.JSlider();
mapActivityMode = new javax.swing.JRadioButton();
mapValueMode = new javax.swing.JRadioButton();
zoomLabel = new javax.swing.JLabel();
startAddress = new javax.swing.JTextField();
startLabel = new javax.swing.JLabel();
endAddress = new javax.swing.JTextField();
statusLabel = new javax.swing.JLabel();
endLabel = new javax.swing.JLabel();
updateAddressButton = new javax.swing.JButton();
useColorCheckbox = new javax.swing.JCheckBox();
fastFadeCheckbox = new javax.swing.JCheckBox();
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
addComponentListener(new java.awt.event.ComponentAdapter() {
public void componentResized(java.awt.event.ComponentEvent evt) {
formComponentResized(evt);
}
public void componentShown(java.awt.event.ComponentEvent evt) {
formComponentShown(evt);
}
public void componentHidden(java.awt.event.ComponentEvent evt) {
formComponentHidden(evt);
}
});
addHierarchyBoundsListener(new java.awt.event.HierarchyBoundsListener() {
public void ancestorMoved(java.awt.event.HierarchyEvent evt) {
}
public void ancestorResized(java.awt.event.HierarchyEvent evt) {
formAncestorResized(evt);
}
});
viewScroll.setPreferredSize(new java.awt.Dimension(640, 480));
memorySpyGrid.setPreferredSize(new java.awt.Dimension(580, 480));
javax.swing.GroupLayout memorySpyGridLayout = new javax.swing.GroupLayout(memorySpyGrid);
memorySpyGrid.setLayout(memorySpyGridLayout);
memorySpyGridLayout.setHorizontalGroup(
memorySpyGridLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 631, Short.MAX_VALUE)
);
memorySpyGridLayout.setVerticalGroup(
memorySpyGridLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 490, Short.MAX_VALUE)
);
viewScroll.setViewportView(memorySpyGrid);
controlPanel.setBorder(new javax.swing.border.LineBorder(new java.awt.Color(0, 0, 0), 1, true));
showLabel.setText("Show");
zoomAmount.setMaximum(15);
zoomAmount.setMinimum(1);
zoomAmount.setPaintTicks(true);
zoomAmount.setSnapToTicks(true);
zoomAmount.setValue(5);
zoomAmount.addChangeListener(new javax.swing.event.ChangeListener() {
public void stateChanged(javax.swing.event.ChangeEvent evt) {
zoomAmountStateChanged(evt);
}
});
mapType.add(mapActivityMode);
mapActivityMode.setSelected(true);
mapActivityMode.setText("Activity");
mapActivityMode.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
mapActivityModeActionPerformed(evt);
}
});
mapType.add(mapValueMode);
mapValueMode.setText("Value");
mapValueMode.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
mapValueModeActionPerformed(evt);
}
});
zoomLabel.setText("Zoom");
startAddress.setText("$0000");
startLabel.setText("Start");
endAddress.setText("$FFFF");
statusLabel.setFont(new java.awt.Font("Courier New", 0, 14)); // NOI18N
statusLabel.setText(" ");
statusLabel.setBorder(javax.swing.BorderFactory.createEtchedBorder(javax.swing.border.EtchedBorder.RAISED));
endLabel.setText("End");
updateAddressButton.setText("Update");
updateAddressButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
updateAddressButtonActionPerformed(evt);
}
});
useColorCheckbox.setText("Color Gradient");
useColorCheckbox.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
useColorCheckboxActionPerformed(evt);
}
});
fastFadeCheckbox.setText("Fast Fade");
fastFadeCheckbox.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
fastFadeCheckboxActionPerformed(evt);
}
});
javax.swing.GroupLayout controlPanelLayout = new javax.swing.GroupLayout(controlPanel);
controlPanel.setLayout(controlPanelLayout);
controlPanelLayout.setHorizontalGroup(
controlPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(controlPanelLayout.createSequentialGroup()
.addGap(19, 19, 19)
.addComponent(showLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(controlPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(mapActivityMode)
.addComponent(fastFadeCheckbox))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(controlPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
.addGroup(controlPanelLayout.createSequentialGroup()
.addComponent(mapValueMode)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(zoomLabel))
.addComponent(useColorCheckbox))
.addGroup(controlPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
.addGroup(controlPanelLayout.createSequentialGroup()
.addGap(144, 144, 144)
.addComponent(endLabel))
.addGroup(controlPanelLayout.createSequentialGroup()
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(zoomAmount, javax.swing.GroupLayout.PREFERRED_SIZE, 107, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(startLabel)))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(controlPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
.addComponent(endAddress, javax.swing.GroupLayout.DEFAULT_SIZE, 60, Short.MAX_VALUE)
.addComponent(startAddress))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(updateAddressButton)
.addContainerGap(28, Short.MAX_VALUE))
.addGroup(controlPanelLayout.createSequentialGroup()
.addContainerGap()
.addComponent(statusLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addContainerGap())
);
controlPanelLayout.setVerticalGroup(
controlPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(controlPanelLayout.createSequentialGroup()
.addGroup(controlPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(controlPanelLayout.createSequentialGroup()
.addGroup(controlPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(zoomAmount, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)
.addGroup(controlPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(startLabel)
.addComponent(startAddress, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(controlPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(endAddress, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(endLabel)
.addComponent(updateAddressButton)
.addComponent(useColorCheckbox)
.addComponent(fastFadeCheckbox)))
.addGroup(controlPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
.addGroup(controlPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(mapActivityMode, javax.swing.GroupLayout.PREFERRED_SIZE, 22, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(showLabel))
.addGroup(javax.swing.GroupLayout.Alignment.LEADING, controlPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(zoomLabel)
.addComponent(mapValueMode))))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(statusLabel)
.addContainerGap())
);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(viewScroll, javax.swing.GroupLayout.DEFAULT_SIZE, 633, Short.MAX_VALUE)
.addComponent(controlPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addContainerGap())
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addComponent(viewScroll, javax.swing.GroupLayout.DEFAULT_SIZE, 492, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(controlPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap())
);
pack();
}// </editor-fold>//GEN-END:initComponents
private void mapActivityModeActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_mapActivityModeActionPerformed
memorySpyGrid.setDisplayMode(MemorySpyGrid.Modes.ACTIVITY);
}//GEN-LAST:event_mapActivityModeActionPerformed
private void mapValueModeActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_mapValueModeActionPerformed
memorySpyGrid.setDisplayMode(MemorySpyGrid.Modes.VALUE);
}//GEN-LAST:event_mapValueModeActionPerformed
private void zoomAmountStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_zoomAmountStateChanged
if (!zoomAmount.getValueIsAdjusting()) {
memorySpyGrid.setZoomAmount(zoomAmount.getValue());
}
}//GEN-LAST:event_zoomAmountStateChanged
private void updateAddressButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_updateAddressButtonActionPerformed
int startAddr = Utility.parseHexInt(startAddress.getText());
int endAddr = Utility.parseHexInt(endAddress.getText());
if (startAddr < 0 || startAddr > 0x0ffff) {
gripe("Start address is out of range!");
return;
}
if (endAddr < 0 || endAddr > 0x0ffff) {
gripe("End address is out of range!");
return;
}
if (startAddr > endAddr) {
gripe("Start address must be smaller than end address");
return;
}
memorySpyGrid.updateRange(startAddr, endAddr);
}//GEN-LAST:event_updateAddressButtonActionPerformed
@Override
public void validate() {
super.validate();
memorySpyGrid.adjustSize();
}
private void formComponentHidden(java.awt.event.ComponentEvent evt) {//GEN-FIRST:event_formComponentHidden
memorySpyGrid.stopDisplay();
}//GEN-LAST:event_formComponentHidden
private void formComponentShown(java.awt.event.ComponentEvent evt) {//GEN-FIRST:event_formComponentShown
memorySpyGrid.startDisplay();
}//GEN-LAST:event_formComponentShown
long lastRefresh = -1L;
long refreshDelay = 1000L;
private void formComponentResized(java.awt.event.ComponentEvent evt) {//GEN-FIRST:event_formComponentResized
}//GEN-LAST:event_formComponentResized
private void formAncestorResized(java.awt.event.HierarchyEvent evt) {//GEN-FIRST:event_formAncestorResized
// java.awt.EventQueue.invokeLater(new Runnable() {
// @Override
// public void run() {
// lastRefresh = System.currentTimeMillis() + refreshDelay + 10;
// try {
// Thread.sleep(refreshDelay);
// } catch (InterruptedException ex) {
// Logger.getLogger(MemorySpy.class.getName()).log(Level.SEVERE, null, ex);
// }
// if (System.currentTimeMillis() >= lastRefresh) {
// int newWidth = getParent().getWidth();
// }
// }
// });
// memorySpyGrid.adjustSize();
}//GEN-LAST:event_formAncestorResized
private void useColorCheckboxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_useColorCheckboxActionPerformed
memorySpyGrid.setColorGradient(useColorCheckbox.isSelected());
}//GEN-LAST:event_useColorCheckboxActionPerformed
private void fastFadeCheckboxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_fastFadeCheckboxActionPerformed
memorySpyGrid.setFastFade(fastFadeCheckbox.isSelected());
}//GEN-LAST:event_fastFadeCheckboxActionPerformed
/**
* @param args the command line arguments
*/
public static void main(String args[]) {
/* Set the Nimbus look and feel */
//<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
/* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
* For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html
*/
try {
for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
if ("Nimbus".equals(info.getName())) {
javax.swing.UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (ClassNotFoundException ex) {
java.util.logging.Logger.getLogger(MemorySpy.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (InstantiationException ex) {
java.util.logging.Logger.getLogger(MemorySpy.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (IllegalAccessException ex) {
java.util.logging.Logger.getLogger(MemorySpy.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (javax.swing.UnsupportedLookAndFeelException ex) {
java.util.logging.Logger.getLogger(MemorySpy.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
}
//</editor-fold>
/* Create and display the form */
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new MemorySpy().setVisible(true);
}
});
}
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JPanel controlPanel;
private javax.swing.JTextField endAddress;
private javax.swing.JLabel endLabel;
private javax.swing.JCheckBox fastFadeCheckbox;
private javax.swing.JRadioButton mapActivityMode;
private javax.swing.ButtonGroup mapType;
private javax.swing.JRadioButton mapValueMode;
private jace.cheat.MemorySpyGrid memorySpyGrid;
private javax.swing.JLabel showLabel;
private javax.swing.JTextField startAddress;
private javax.swing.JLabel startLabel;
public javax.swing.JLabel statusLabel;
private javax.swing.JButton updateAddressButton;
private javax.swing.JCheckBox useColorCheckbox;
private javax.swing.JScrollPane viewScroll;
private javax.swing.JSlider zoomAmount;
private javax.swing.JLabel zoomLabel;
// End of variables declaration//GEN-END:variables
}