/* This file is part of jpcsp. Jpcsp 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. Jpcsp 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 Jpcsp. If not, see <http://www.gnu.org/licenses/>. */ package jpcsp.Debugger; import java.awt.event.KeyEvent; import java.io.BufferedWriter; import java.io.File; import java.io.FileWriter; import java.io.IOException; import javax.swing.JOptionPane; import javax.swing.SwingUtilities; import jpcsp.Emulator; import jpcsp.Memory; import jpcsp.WindowPropSaver; import jpcsp.util.Utilities; /** * * @author George */ public class MemoryViewer extends javax.swing.JFrame { private static final long serialVersionUID = 1L; private int visiblelines = 0; private int startaddress; public MemoryViewer() { //this.cpu = c; startaddress = Emulator.getProcessor().cpu.pc; initComponents(); RefreshMemory(); WindowPropSaver.loadWindowProperties(this); } public static char converttochar(int character) { if (character < 0x020 || character >= 0x07f && character <= 0x0a0 || character == 0x0ad) { return '.'; } return (char) (character & 0x0ff); } private static byte safeRead8(Memory mem, int address) { byte value = 0; if (Memory.isAddressGood(address)) { value = (byte) mem.read8(address); } return value; } public static String getMemoryView(int addr) { byte[] line = new byte[16]; Memory mem = Memory.getInstance(); for (int i = 0; i < line.length; i++) { line[i] = safeRead8(mem, addr + i); } return String.format("%08X : %02X %02X %02X %02X %02X %02X " + "%02X %02X %02X %02X %02X %02X %02X %02X " + "%02X %02X %c %c %c %c %c %c %c %c %c %c %c %c %c %c %c %c", addr, line[0], line[1], line[2], line[3], line[4], line[5], line[6], line[7], line[8], line[9], line[10], line[11], line[12], line[13], line[14], line[15], converttochar(line[0]), converttochar(line[1]), converttochar(line[2]), converttochar(line[3]), converttochar(line[4]), converttochar(line[5]), converttochar(line[6]), converttochar(line[7]), converttochar(line[8]), converttochar(line[9]), converttochar(line[10]), converttochar(line[11]), converttochar(line[12]), converttochar(line[13]), converttochar(line[14]), converttochar(line[15])); } public void SafeRefreshMemory() { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { RefreshMemory(); } }); } public void RefreshMemory() { int addr = startaddress; taMemoryView.setText(""); visiblelines = taMemoryView.getHeight() / taMemoryView.getFontMetrics(taMemoryView.getFont()).getHeight(); for (int y = 0; y < visiblelines; y++) { if (y > 0) { taMemoryView.append("\n"); } taMemoryView.append(getMemoryView(addr)); addr += 16; } } /** * 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. */ // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents private void initComponents() { AddressField = new javax.swing.JTextField(); btnGoToAddress = new javax.swing.JButton(); btnGoToSP = new javax.swing.JButton(); btnDumpRawRam = new javax.swing.JButton(); btnGoToVRAM = new javax.swing.JButton(); jPanel1 = new javax.swing.JPanel(); taMemoryView = new javax.swing.JTextArea(); java.util.ResourceBundle bundle = java.util.ResourceBundle.getBundle("jpcsp/languages/jpcsp"); // NOI18N setTitle(bundle.getString("MemoryViewer.title")); // NOI18N setMinimumSize(new java.awt.Dimension(800, 380)); setPreferredSize(new java.awt.Dimension(800, 380)); AddressField.setFont(new java.awt.Font("Courier New", 0, 12)); // NOI18N AddressField.setHorizontalAlignment(javax.swing.JTextField.CENTER); AddressField.setText("0x00000000"); // NOI18N AddressField.addKeyListener(new java.awt.event.KeyAdapter() { public void keyPressed(java.awt.event.KeyEvent evt) { onKeyPressed(evt); } }); btnGoToAddress.setText(bundle.getString("MemoryViewer.btnGoToAddress.text")); // NOI18N btnGoToAddress.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { btnGoToAddressActionPerformed(evt); } }); btnGoToSP.setText(bundle.getString("MemoryViewer.btnGoToSP.text")); // NOI18N btnGoToSP.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { btnGoToSPActionPerformed(evt); } }); btnDumpRawRam.setText(bundle.getString("MemoryViewer.btnDumpRawRam.text")); // NOI18N btnDumpRawRam.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { btnDumpRawRamActionPerformed(evt); } }); btnGoToVRAM.setText(bundle.getString("MemoryViewer.btnGoToVRAM.text")); // NOI18N btnGoToVRAM.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { btnGoToVRAMActionPerformed(evt); } }); jPanel1.addComponentListener(new java.awt.event.ComponentAdapter() { public void componentResized(java.awt.event.ComponentEvent evt) { jPanel1ComponentResized(evt); } }); taMemoryView.setEditable(false); taMemoryView.setFont(new java.awt.Font("Courier New", 0, 12)); // NOI18N taMemoryView.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(0, 0, 0))); taMemoryView.addMouseWheelListener(new java.awt.event.MouseWheelListener() { public void mouseWheelMoved(java.awt.event.MouseWheelEvent evt) { taMemoryViewMouseWheelMoved(evt); } }); taMemoryView.addKeyListener(new java.awt.event.KeyAdapter() { public void keyPressed(java.awt.event.KeyEvent evt) { taMemoryViewKeyPressed(evt); } }); javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1); jPanel1.setLayout(jPanel1Layout); jPanel1Layout.setHorizontalGroup( jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(taMemoryView) ); jPanel1Layout.setVerticalGroup( jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(taMemoryView, javax.swing.GroupLayout.DEFAULT_SIZE, 295, Short.MAX_VALUE) ); 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) .addGroup(layout.createSequentialGroup() .addComponent(AddressField, javax.swing.GroupLayout.PREFERRED_SIZE, 100, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(btnGoToAddress, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(btnGoToVRAM, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(btnGoToSP, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(btnDumpRawRam, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) .addComponent(jPanel1, 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() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(btnDumpRawRam) .addComponent(AddressField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(btnGoToAddress) .addComponent(btnGoToSP) .addComponent(btnGoToVRAM)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addContainerGap()) ); pack(); }// </editor-fold>//GEN-END:initComponents private void taMemoryViewKeyPressed(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_taMemoryViewKeyPressed if (evt.getKeyCode() == java.awt.event.KeyEvent.VK_DOWN) { startaddress += 16; evt.consume(); RefreshMemory(); } else if (evt.getKeyCode() == java.awt.event.KeyEvent.VK_UP) { startaddress -= 16; evt.consume(); RefreshMemory(); } else if (evt.getKeyCode() == java.awt.event.KeyEvent.VK_PAGE_UP) { startaddress -= 16 * visiblelines; evt.consume(); RefreshMemory(); } else if (evt.getKeyCode() == java.awt.event.KeyEvent.VK_PAGE_DOWN) { startaddress += 16 * visiblelines; evt.consume(); RefreshMemory(); } }//GEN-LAST:event_taMemoryViewKeyPressed private void btnGoToAddressActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnGoToAddressActionPerformed GoToAddress(); }//GEN-LAST:event_btnGoToAddressActionPerformed private void GoToAddress() { String gettext = AddressField.getText(); int value; try { value = Utilities.parseAddressExpression(gettext); } catch (Exception e) { JOptionPane.showMessageDialog(this, java.util.ResourceBundle.getBundle("jpcsp/languages/jpcsp").getString("MemoryViewer.strInvalidAddress.text")); return; } startaddress = value; AddressField.setText(String.format("0x%08X", value)); RefreshMemory(); } private void taMemoryViewMouseWheelMoved(java.awt.event.MouseWheelEvent evt) {//GEN-FIRST:event_taMemoryViewMouseWheelMoved if (evt.getWheelRotation() > 0) { startaddress += 16; evt.consume(); RefreshMemory(); } else { startaddress -= 16; evt.consume(); RefreshMemory(); } }//GEN-LAST:event_taMemoryViewMouseWheelMoved private void btnGoToSPActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnGoToSPActionPerformed startaddress = Emulator.getProcessor().cpu._sp; RefreshMemory(); }//GEN-LAST:event_btnGoToSPActionPerformed private void btnDumpRawRamActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnDumpRawRamActionPerformed File f = new File("ramdump.bin"); BufferedWriter out = null; try { out = new BufferedWriter(new FileWriter(f)); Memory mem = Memory.getInstance(); for (int i = 0x08000000; i <= 0x09ffffff; i++) { out.write(safeRead8(mem, i)); } } catch (IOException e) { // do nothing } finally { Utilities.close(out); } }//GEN-LAST:event_btnDumpRawRamActionPerformed private void onKeyPressed(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_onKeyPressed if (evt.getKeyCode() == KeyEvent.VK_ENTER) { GoToAddress(); } }//GEN-LAST:event_onKeyPressed private void btnGoToVRAMActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnGoToVRAMActionPerformed startaddress = 0x04000000; RefreshMemory(); }//GEN-LAST:event_btnGoToVRAMActionPerformed private void jPanel1ComponentResized(java.awt.event.ComponentEvent evt) {//GEN-FIRST:event_jPanel1ComponentResized // this is needed to override the size of the TextArea with text already present taMemoryView.setMinimumSize(jPanel1.getMinimumSize()); taMemoryView.setMaximumSize(jPanel1.getMaximumSize()); RefreshMemory(); }//GEN-LAST:event_jPanel1ComponentResized @Override public void dispose() { Emulator.getMainGUI().endWindowDialog(); super.dispose(); } // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JTextField AddressField; private javax.swing.JButton btnDumpRawRam; private javax.swing.JButton btnGoToAddress; private javax.swing.JButton btnGoToSP; private javax.swing.JButton btnGoToVRAM; private javax.swing.JPanel jPanel1; private javax.swing.JTextArea taMemoryView; // End of variables declaration//GEN-END:variables }