/* 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.FileLogger; import java.awt.Color; import java.awt.Component; import java.awt.event.ActionEvent; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import javax.swing.JFileChooser; import javax.swing.JMenuItem; import javax.swing.JOptionPane; import javax.swing.JPopupMenu; import javax.swing.JTable; import javax.swing.SwingUtilities; import javax.swing.table.AbstractTableModel; import javax.swing.table.DefaultTableCellRenderer; import javax.swing.table.TableColumnModel; import jpcsp.Emulator; import jpcsp.HLE.Modules; import jpcsp.HLE.VFS.IVirtualFile; import jpcsp.HLE.modules.IoFileMgrForUser.IIoListener; import jpcsp.State; import jpcsp.WindowPropSaver; import jpcsp.filesystems.SeekableDataInput; import jpcsp.filesystems.umdiso.UmdIsoReader; import jpcsp.settings.Settings; import jpcsp.util.Constants; /** * * @author fiveofhearts */ public class FileLoggerFrame extends javax.swing.JFrame implements Runnable, IIoListener { private static final long serialVersionUID = 8455039521164613143L; private FileHandleModel fileHandleModel; private FileCommandModel fileCommandModel; private Thread refreshThread; private volatile boolean dirty; private volatile boolean sortRequired; /** * Creates new form FileLoggerFrame */ public FileLoggerFrame() { fileHandleModel = new FileHandleModel(); fileCommandModel = new FileCommandModel(); initComponents(); postInit(); refreshThread = new Thread(this, "FileLogger"); refreshThread.start(); if (Settings.getInstance().readBool("emu.debug.enablefilelogger")) { cbFileTrace.setSelected(true); Modules.IoFileMgrForUserModule.registerIoListener(this); } WindowPropSaver.loadWindowProperties(this); } @Override public void setVisible(boolean visible) { super.setVisible(visible); synchronized (getInstance()) { if (!dirty) { dirty = true; getInstance().notify(); } } } /** * 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() { jPopupMenu1 = new javax.swing.JPopupMenu(); copyItem = new javax.swing.JMenuItem(); saveAsItem = new javax.swing.JMenuItem(); jSplitPane1 = new javax.swing.JSplitPane(); jScrollPane1 = new javax.swing.JScrollPane(); commandLogTable = new javax.swing.JTable(); jScrollPane2 = new javax.swing.JScrollPane(); fileHandleTable = new javax.swing.JTable(); cbFileTrace = new javax.swing.JCheckBox(); copyItem.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_C, java.awt.event.InputEvent.CTRL_MASK)); java.util.ResourceBundle bundle = java.util.ResourceBundle.getBundle("jpcsp/languages/jpcsp"); // NOI18N copyItem.setText(bundle.getString("FileLoggerFrame.copyItem.text")); // NOI18N copyItem.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { copyItemActionPerformed(evt); } }); jPopupMenu1.add(copyItem); saveAsItem.setText(bundle.getString("FileLoggerFrame.saveAsItem.text")); // NOI18N saveAsItem.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { saveAsItemActionPerformed(evt); } }); jPopupMenu1.add(saveAsItem); setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); setTitle(bundle.getString("FileLoggerFrame.title")); // NOI18N setMinimumSize(new java.awt.Dimension(400, 200)); jSplitPane1.setDividerLocation(100); jSplitPane1.setOrientation(javax.swing.JSplitPane.VERTICAL_SPLIT); jSplitPane1.setMinimumSize(new java.awt.Dimension(179, 100)); commandLogTable.setModel(fileCommandModel); commandLogTable.setInheritsPopupMenu(true); commandLogTable.setMinimumSize(new java.awt.Dimension(200, 100)); commandLogTable.setName(bundle.getString("FileLoggerFrame.commandLogTable.name")); // NOI18N commandLogTable.addMouseListener(new java.awt.event.MouseAdapter() { public void mousePressed(java.awt.event.MouseEvent evt) { tableMousePressed(evt); } public void mouseReleased(java.awt.event.MouseEvent evt) { tableMouseReleased(evt); } }); jScrollPane1.setViewportView(commandLogTable); jSplitPane1.setBottomComponent(jScrollPane1); fileHandleTable.setModel(fileHandleModel); fileHandleTable.setInheritsPopupMenu(true); fileHandleTable.setMinimumSize(new java.awt.Dimension(200, 100)); fileHandleTable.setName(bundle.getString("FileLoggerFrame.fileHandleTable.name")); // NOI18N fileHandleTable.addMouseListener(new java.awt.event.MouseAdapter() { public void mousePressed(java.awt.event.MouseEvent evt) { tableMousePressed(evt); } public void mouseReleased(java.awt.event.MouseEvent evt) { tableMouseReleased(evt); } }); jScrollPane2.setViewportView(fileHandleTable); jSplitPane1.setTopComponent(jScrollPane2); cbFileTrace.setText(bundle.getString("FileLoggerFrame.cbFileTrace.text")); // NOI18N cbFileTrace.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { cbFileTraceActionPerformed(evt); } }); 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(cbFileTrace) .addGap(0, 0, Short.MAX_VALUE)) .addComponent(jSplitPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 628, Short.MAX_VALUE)) .addContainerGap()) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() .addContainerGap() .addComponent(cbFileTrace) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jSplitPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 257, Short.MAX_VALUE) .addContainerGap()) ); pack(); }// </editor-fold>//GEN-END:initComponents private void tableMousePressed(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_tableMousePressed if (evt.isPopupTrigger()) { jPopupMenu1.show(evt.getComponent(), evt.getX(), evt.getY()); } }//GEN-LAST:event_tableMousePressed private void tableMouseReleased(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_tableMouseReleased if (evt.isPopupTrigger()) { jPopupMenu1.show(evt.getComponent(), evt.getX(), evt.getY()); } }//GEN-LAST:event_tableMouseReleased private void copyItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_copyItemActionPerformed JTable source = (JTable) ((JPopupMenu) ((JMenuItem) evt.getSource()).getParent()).getInvoker(); ActionEvent ae = new ActionEvent(source, ActionEvent.ACTION_PERFORMED, ""); source.getActionMap().get("copy").actionPerformed(ae); }//GEN-LAST:event_copyItemActionPerformed private void saveAsItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_saveAsItemActionPerformed java.util.ResourceBundle bundle = java.util.ResourceBundle.getBundle("jpcsp/languages/jpcsp"); final JFileChooser fc = new JFileChooser(); fc.setDialogTitle(bundle.getString("FileLoggerFrame.strSaveTable.text")); fc.setSelectedFile(new File(State.discId + "_fileio.txt")); fc.setCurrentDirectory(new java.io.File(".")); fc.addChoosableFileFilter(Constants.fltTextFiles); fc.setFileFilter(Constants.fltTextFiles); if (fc.showSaveDialog(this) == JFileChooser.APPROVE_OPTION) { File f = fc.getSelectedFile(); if (f.exists()) { int rc = JOptionPane.showConfirmDialog( this, bundle.getString("ConsoleWindow.strFileExists.text"), bundle.getString("ConsoleWindow.strFileExistsTitle.text"), JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE); if (rc != JOptionPane.YES_OPTION) { return; } } try { JTable source = (JTable) ((JPopupMenu) ((JMenuItem) evt.getSource()).getParent()).getInvoker(); String data = ""; // list column headers for (int j = 0; j < source.getColumnCount(); j++) { data += source.getColumnName(j) + ";"; } // strip last semicolon and put a newline there instead data = data.substring(0, data.length() - 1) + System.getProperty("line.separator"); // list table content for (int i = 0; i < source.getRowCount(); i++) { for (int j = 0; j < source.getColumnCount(); j++) { data += source.getModel().getValueAt(i, j) + ";"; } // strip last semicolon and put a newline there instead data = data.substring(0, data.length() - 1) + System.getProperty("line.separator"); } FileWriter os = new FileWriter(f); os.write(data); os.close(); } catch (IOException ioe) { JOptionPane.showMessageDialog( this, bundle.getString("FileLoggerFrame.strSaveFailed.text") + ioe.getLocalizedMessage()); } } }//GEN-LAST:event_saveAsItemActionPerformed private FileLoggerFrame getInstance() { return this; } private void cbFileTraceActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cbFileTraceActionPerformed if (cbFileTrace.isSelected()) { Modules.IoFileMgrForUserModule.registerIoListener(this); Settings.getInstance().writeBool("emu.debug.enablefilelogger", true); } else { Modules.IoFileMgrForUserModule.unregisterIoListener(this); Settings.getInstance().writeBool("emu.debug.enablefilelogger", false); } }//GEN-LAST:event_cbFileTraceActionPerformed // TODO does fireTableDataChanged need to be in the swing thread? // if not we could just call fireTableDataChanged(); from the logging functions @Override public void run() { Runnable refresher = new Runnable() { @Override public void run() { if (sortRequired) { sortRequired = false; sortLists(); } // Scroll to bottom of the tables int max = jScrollPane1.getVerticalScrollBar().getMaximum(); jScrollPane1.getVerticalScrollBar().setValue(max); max = jScrollPane2.getVerticalScrollBar().getMaximum(); jScrollPane2.getVerticalScrollBar().setValue(max); // Tell the tables to redraw fileHandleModel.fireTableDataChanged(); fileCommandModel.fireTableDataChanged(); } }; while (true) { try { synchronized (this) { while (!dirty) { wait(); } dirty = false; } if (getInstance().isVisible()) { SwingUtilities.invokeAndWait(refresher); } // Cap update frequency Thread.sleep(200); } catch (Exception e) { e.printStackTrace(); } } } /** * Renders closed files in gray. */ public class FileHandleRenderer extends DefaultTableCellRenderer { private static final long serialVersionUID = -792377736132676194L; @Override public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { Component c = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); c.setForeground(Color.black); if (fileHandleList != null) { FileHandleInfo info = fileHandleList.get(row); if (!info.isOpen()) { c.setForeground(Color.gray); } } return c; } } private class FileHandleModel extends AbstractTableModel { private static final long serialVersionUID = -109193689444035593L; @Override public int getColumnCount() { return 4; } @Override public int getRowCount() { if (fileHandleList != null) { return fileHandleList.size(); } return 0; } @Override public String getColumnName(int columnIndex) { java.util.ResourceBundle bundle = java.util.ResourceBundle.getBundle("jpcsp/languages/jpcsp"); switch (columnIndex) { case 0: return bundle.getString("FileLoggerFrame.strFileID.text"); case 1: return bundle.getString("FileLoggerFrame.strFileName.text"); case 2: return bundle.getString("FileLoggerFrame.strRead.text"); case 3: return bundle.getString("FileLoggerFrame.strWrite.text"); default: throw new IllegalArgumentException("invalid column index"); } } @Override public Object getValueAt(int row, int col) { FileHandleInfo info = fileHandleList.get(row); if (info != null) { switch (col) { case 0: return String.format("0x%04X", info.fd); case 1: return info.filename; case 2: return info.bytesRead; case 3: return info.bytesWritten; } } return null; } }; private class FileCommandModel extends AbstractTableModel { private static final long serialVersionUID = -5088674695489235024L; @Override public int getColumnCount() { return 6; } @Override public int getRowCount() { if (fileCommandList != null) { return fileCommandList.size(); } return 0; } @Override public String getColumnName(int columnIndex) { java.util.ResourceBundle bundle = java.util.ResourceBundle.getBundle("jpcsp/languages/jpcsp"); switch (columnIndex) { case 0: return bundle.getString("FileLoggerFrame.strThreadID.text"); case 1: return bundle.getString("FileLoggerFrame.strThreadName.text"); case 2: return bundle.getString("FileLoggerFrame.strFileID.text"); case 3: return bundle.getString("FileLoggerFrame.strCommand.text"); case 4: return bundle.getString("FileLoggerFrame.strResult.text"); case 5: return bundle.getString("FileLoggerFrame.strParameters.text"); default: throw new IllegalArgumentException("invalid column index"); } } @Override public Object getValueAt(int row, int col) { FileCommandInfo info = fileCommandList.get(row); if (info != null) { switch (col) { case 0: return String.format("0x%08X", info.threadId); case 1: return info.threadName; case 2: return (info.hasFd) ? String.format("0x%04X", info.fd) : ""; case 3: return (info.occurences == 1) ? info.command : info.command + " " + info.occurences + "x"; case 4: return String.format("0x%08X", info.result); case 5: return info.parameters; } } return null; } }; final public void postInit() { TableColumnModel columns; // We want the middle column to be the widest columns = fileHandleTable.getColumnModel(); columns.getColumn(0).setPreferredWidth(75); columns.getColumn(1).setPreferredWidth(500); columns.getColumn(2).setPreferredWidth(75); columns.getColumn(3).setPreferredWidth(75); fileHandleTable.setDefaultRenderer(Object.class, new FileHandleRenderer()); columns = commandLogTable.getColumnModel(); columns.getColumn(0).setPreferredWidth(75); columns.getColumn(1).setPreferredWidth(90); columns.getColumn(2).setPreferredWidth(50); columns.getColumn(4).setPreferredWidth(75); columns.getColumn(5).setPreferredWidth(275); resetLogging(); // uncomment this for testing purposes // test(); } public void test() { System.err.println("test start"); resetLogging(); // file handle table sceIoOpen(1, 0x08800000, "test1.txt", 0xFF, 0xFF, "rw"); sceIoOpen(2, 0x08800000, "test2.txt", 0xFF, 0xFF, "rw"); sceIoOpen(3, 0x08800000, System.currentTimeMillis() + ".txt", 0xFF, 0xFF, "rw"); sceIoClose(0, 1); sceIoClose(0, 2); sceIoOpen(1, 0x08800000, "test1.txt", 0xFF, 0xFF, "rw"); // file command table sceIoRead(0x0, 1, 0x08800000, 0x400, 0x0, 0, null, null); System.err.println("test done"); } private class FileCommandInfo { public final boolean hasFd; public final int threadId; public final String threadName; public final int fd; public final String command; public final int result; public final String parameters; public int occurences; private FileCommandInfo(boolean hasFd, int fd, String command, int result, String parameters) { this.hasFd = hasFd; threadId = Modules.ThreadManForUserModule.getCurrentThreadID(); threadName = Modules.ThreadManForUserModule.getThreadName(threadId); this.fd = fd; this.command = command; this.result = result; this.parameters = parameters; occurences = 1; synchronized (getInstance()) { if (!dirty) { dirty = true; getInstance().notify(); } } } /** * Example: 0x1001, "close", 0x0, "" */ public FileCommandInfo(int fd, String command, int result, String parameters) { this(true, fd, command, result, parameters); } /** * Example: "open", 0x1001, "path='test.txt' flags=0xFF perm=0777" */ public FileCommandInfo(String command, int result, String parameters) { this(false, -2, command, result, parameters); } @Override public boolean equals(Object _obj) { if (_obj instanceof FileCommandInfo) { FileCommandInfo obj = (FileCommandInfo) _obj; return threadId == obj.threadId && fd == obj.fd && command.equals(obj.command) && result == obj.result && parameters.equals(obj.parameters); } return false; } @Override public int hashCode() { int hash = 7; hash = 43 * hash + threadId; hash = 43 * hash + fd; hash = 43 * hash + (command != null ? command.hashCode() : 0); hash = 43 * hash + result; hash = 43 * hash + (parameters != null ? parameters.hashCode() : 0); return hash; } } // Emu interface private HashMap<Integer, FileHandleInfo> fileHandleIdMap; private List<FileHandleInfo> fileHandleList; // Cached sorted version of fileHandleIdMap private List<FileCommandInfo> fileCommandList; public synchronized void resetLogging() { fileHandleIdMap = new HashMap<Integer, FileHandleInfo>(); fileHandleList = new LinkedList<FileHandleInfo>(); fileCommandList = new LinkedList<FileCommandInfo>(); if (!dirty) { dirty = true; getInstance().notify(); } } private void sortLists() { // File handles Collection<FileHandleInfo> c = fileHandleIdMap.values(); fileHandleList = new LinkedList<FileHandleInfo>(c); Collections.sort(fileHandleList); } /** * Handles repeated commands */ private FileCommandInfo lastFileCommand; private void logFileCommand(FileCommandInfo info) { if (lastFileCommand != null && info.equals(lastFileCommand)) { lastFileCommand.occurences++; } else { fileCommandList.add(info); lastFileCommand = info; } } @Override public void sceIoSync(int result, int device_addr, String device, int unknown) { logFileCommand(new FileCommandInfo( "sync", result, String.format("device=0x%08X('%s') unknown=0x%08X", device_addr, device, unknown))); } @Override public void sceIoPollAsync(int result, int uid, int res_addr) { logFileCommand(new FileCommandInfo( uid, "poll async", result, String.format("result=0x%08X", res_addr))); } @Override public void sceIoWaitAsync(int result, int uid, int res_addr) { logFileCommand(new FileCommandInfo( uid, "wait async", result, String.format("result=0x%08X", res_addr))); } @Override public void sceIoOpen(int result, int filename_addr, String filename, int flags, int permissions, String mode) { // File handle list if (result >= 0) { FileHandleInfo info = new FileHandleInfo(result, filename); fileHandleIdMap.put(result, info); sortRequired = true; } String filelog = String.format("path=0x%08X('%s')", filename_addr, filename); if (filename.startsWith("disc0:/sce_lbn")) { // try to resolve LBA addressing if possible UmdIsoReader iso = Modules.IoFileMgrForUserModule.getIsoReader(); if (iso != null) { String filePath = filename; filePath = filePath.substring(14); // length of "disc0:/sce_lba" int sep = filePath.indexOf("_size"); int fileStart = Integer.decode(filePath.substring(0, sep)); String resolved = iso.getFileName(fileStart); if (resolved != null) { filelog = String.format("path=0x%08X('%s', '%s')", filename_addr, filename, resolved); } } } filelog += String.format(" flags=0x%04X, permissions=0x%04X(%s)", flags, permissions, mode); // File Command list logFileCommand(new FileCommandInfo("open", result, filelog)); } @Override public void sceIoClose(int result, int uid) { // File handle list if (result >= 0) { FileHandleInfo info = fileHandleIdMap.get(uid); if (info != null) { info.isOpen(false); } } // File Command list logFileCommand(new FileCommandInfo(uid, "close", result, "")); } @Override public void sceIoWrite(int result, int uid, int data_addr, int size, int bytesWritten) { FileHandleInfo info = fileHandleIdMap.get(uid); if (result >= 0 && info != null) { info.bytesWritten += bytesWritten; } logFileCommand(new FileCommandInfo( uid, "write", result, String.format("data=0x%08X size=0x%08X", data_addr, size))); } @Override public void sceIoRead(int result, int uid, int data_addr, int size, int bytesRead, long position, SeekableDataInput dataInput, IVirtualFile vFile) { FileHandleInfo info = fileHandleIdMap.get(uid); if (result >= 0 && info != null) { info.bytesRead += bytesRead; } logFileCommand(new FileCommandInfo( uid, "read", result, String.format("data=0x%08X size=0x%08X", data_addr, size))); } @Override public void sceIoCancel(int result, int uid) { logFileCommand(new FileCommandInfo(uid, "cancel", result, "")); } private String getWhenceName(int whence) { switch (whence) { case jpcsp.HLE.modules.IoFileMgrForUser.PSP_SEEK_SET: return whence + "(set)"; case jpcsp.HLE.modules.IoFileMgrForUser.PSP_SEEK_CUR: return whence + "(cur)"; case jpcsp.HLE.modules.IoFileMgrForUser.PSP_SEEK_END: return whence + "(end)"; default: return "" + whence; } } @Override public void sceIoSeek32(int result, int uid, int offset, int whence) { logFileCommand(new FileCommandInfo( uid, "seek32", result, String.format("offset=0x%08X whence=%s", offset, getWhenceName(whence)))); } @Override public void sceIoSeek64(long result, int uid, long offset, int whence) { logFileCommand(new FileCommandInfo( uid, "seek64", (int) result, // HACK back to 32bit result String.format("offset=0x%08X whence=%s", offset, getWhenceName(whence)))); } @Override public void sceIoMkdir(int result, int path_addr, String path, int permissions) { logFileCommand(new FileCommandInfo( "mkdir", result, String.format("path=0x%08X('%s') permissions=%04X", path_addr, path, permissions))); } @Override public void sceIoRmdir(int result, int path_addr, String path) { logFileCommand(new FileCommandInfo( "rmdir", result, String.format("path=0x%08X('%s')", path_addr, path))); } @Override public void sceIoChdir(int result, int path_addr, String path) { logFileCommand(new FileCommandInfo( "chdir", result, String.format("path=0x%08X('%s')", path_addr, path))); } @Override public void sceIoDopen(int result, int path_addr, String path) { logFileCommand(new FileCommandInfo( "dopen", result, String.format("path=0x%08X('%s')", path_addr, path))); } @Override public void sceIoDread(int result, int uid, int dirent_addr) { logFileCommand(new FileCommandInfo(uid, "dread", result, String.format("dirent=0x%08X", dirent_addr))); } @Override public void sceIoDclose(int result, int uid) { logFileCommand(new FileCommandInfo(uid, "dclose", result, "")); } @Override public void sceIoDevctl(int result, int device_addr, String device, int cmd, int indata_addr, int inlen, int outdata_addr, int outlen) { logFileCommand(new FileCommandInfo( "devctl", result, String.format("device=0x%08X('%s') cmd=0x%08X indata=0x%08X inlen=0x%08X outdata=0x%08X outlen=0x%08X", device_addr, device, cmd, indata_addr, inlen, outdata_addr, outlen))); } @Override public void sceIoIoctl(int result, int uid, int cmd, int indata_addr, int inlen, int outdata_addr, int outlen) { logFileCommand(new FileCommandInfo( uid, "ioctl", result, String.format("cmd=0x%08X indata=0x%08X inlen=0x%08X outdata=0x%08X outlen=0x%08X", cmd, indata_addr, inlen, outdata_addr, outlen))); } @Override public void sceIoAssign(int result, int dev1_addr, String dev1, int dev2_addr, String dev2, int dev3_addr, String dev3, int mode, int unk1, int unk2) { logFileCommand(new FileCommandInfo( "assign", result, String.format("dev1=0x%08X('%s') dev2=0x%08X('%s') dev3=0x%08X('%s') mode=0x%08X unk1=0x%08X unk2=0x%08X", dev1_addr, dev1, dev2_addr, dev2, dev3_addr, dev3, mode, unk1, unk2))); } @Override public void sceIoGetStat(int result, int path_addr, String path, int stat_addr) { logFileCommand(new FileCommandInfo( "stat", result, String.format("path=0x%08X('%s') stat=0x%08X", path_addr, path, stat_addr))); } @Override public void sceIoRemove(int result, int path_addr, String path) { logFileCommand(new FileCommandInfo( "remove", result, String.format("path=0x%08X('%s')", path_addr, path))); } @Override public void sceIoChstat(int result, int path_addr, String path, int stat_addr, int bits) { logFileCommand(new FileCommandInfo( "chstat", result, String.format("path=0x%08X('%s') stat=0x%08X bits=0x%08X", path_addr, path, stat_addr, bits))); } @Override public void sceIoRename(int result, int path_addr, String path, int new_path_addr, String newpath) { logFileCommand(new FileCommandInfo( "rename", result, String.format("path=0x%08X('%s') newpath=0x%08X('%s')", path_addr, path, new_path_addr, newpath))); } @Override public void dispose() { Emulator.getMainGUI().endWindowDialog(); super.dispose(); } // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JCheckBox cbFileTrace; private javax.swing.JTable commandLogTable; private javax.swing.JMenuItem copyItem; private javax.swing.JTable fileHandleTable; private javax.swing.JPopupMenu jPopupMenu1; private javax.swing.JScrollPane jScrollPane1; private javax.swing.JScrollPane jScrollPane2; private javax.swing.JSplitPane jSplitPane1; private javax.swing.JMenuItem saveAsItem; // End of variables declaration//GEN-END:variables }