1
0
mirror of https://github.com/sethm/symon.git synced 2024-06-14 17:29:38 +00:00

Step Count and Memory Window enhancements

Introduces several changes requested by Mario Keller. The simulator now has a variable step count that can be selected by a drop-down box on the main window. This change also displays ASCII characters in the Memory window.
This commit is contained in:
Seth Morabito 2013-03-30 21:28:52 -07:00
parent 2835deb00f
commit 6a50476bfe
10 changed files with 235 additions and 110 deletions

View File

@ -1,12 +1,11 @@
SYMON - A 6502 System Simulator SYMON - A 6502 System Simulator
=============================== ===============================
**NOTE: THIS IS BETA QUALITY SOFTWARE UNDER ACTIVE DEVELOPMENT. Feedback is **NOTE: THIS SOFTWARE IS UNDER ACTIVE DEVELOPMENT. Feedback is welcome!**
welcome!**
**Version:** 0.8.4 **Version:** 0.8.5
**Last Updated:** 4 March, 2013 **Last Updated:** 30 March, 2013
Copyright (c) 2008-2013 Seth J. Morabito <web@loomcom.com> Copyright (c) 2008-2013 Seth J. Morabito <web@loomcom.com>
@ -98,7 +97,7 @@ Maven will build Symon, run unit tests, and produce a jar file in the
Symon is meant to be invoked directly from the jar file. To run with Symon is meant to be invoked directly from the jar file. To run with
Java 1.5 or greater, just type: Java 1.5 or greater, just type:
$ java -jar symon-0.8.4.jar $ java -jar symon-0.8.5.jar
When Symon is running, you should be presented with a simple graphical When Symon is running, you should be presented with a simple graphical
interface. interface.
@ -140,6 +139,9 @@ running.
## 5.0 Revision History ## 5.0 Revision History
- **0.8.5:** 30 March, 2013 - ASCII display for memory window.
Allows user to select a step count from a drop-down box.
- **0.8.4:** 4 March, 2013 - Fix for ZPX, ZPY display in the trace log - **0.8.4:** 4 March, 2013 - Fix for ZPX, ZPY display in the trace log
(change contributed by jsissom) (change contributed by jsissom)
@ -169,7 +171,7 @@ running.
- Feedback (in the form of dialogs, status bar, etc). - Feedback (in the form of dialogs, status bar, etc).
- Better debugging tools from the UI, including breakpoints - Better debugging tools from the UI, including breakpoints
and disassebly. and disassembly.
- More accurate timing. - More accurate timing.

View File

@ -4,7 +4,7 @@
<groupId>com.loomcom.symon</groupId> <groupId>com.loomcom.symon</groupId>
<artifactId>symon</artifactId> <artifactId>symon</artifactId>
<packaging>jar</packaging> <packaging>jar</packaging>
<version>0.8.4</version> <version>0.8.5</version>
<name>symon</name> <name>symon</name>
<url>http://www.loomcom.com/symon</url> <url>http://www.loomcom.com/symon</url>
<properties> <properties>
@ -38,7 +38,7 @@
<dependency> <dependency>
<groupId>junit</groupId> <groupId>junit</groupId>
<artifactId>junit</artifactId> <artifactId>junit</artifactId>
<version>4.7</version> <version>4.10</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency> <dependency>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 145 KiB

After

Width:  |  Height:  |  Size: 239 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 37 KiB

View File

@ -29,16 +29,12 @@ public interface Preferences {
public static final int DEFAULT_PROGRAM_LOAD_ADDRESS = 0x0300; public static final int DEFAULT_PROGRAM_LOAD_ADDRESS = 0x0300;
public static final int DEFAULT_BORDER_WIDTH = 10;
public static final boolean DEFAULT_HALT_ON_BREAK = true; public static final boolean DEFAULT_HALT_ON_BREAK = true;
public JDialog getDialog(); public JDialog getDialog();
public int getProgramStartAddress(); public int getProgramStartAddress();
public int getBorderWidth();
public boolean getHaltOnBreak(); public boolean getHaltOnBreak();
public void updateUi(); public void updateUi();

View File

@ -37,6 +37,8 @@ import javax.swing.*;
import javax.swing.border.EmptyBorder; import javax.swing.border.EmptyBorder;
import java.awt.*; import java.awt.*;
import java.awt.event.*; import java.awt.event.*;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.*; import java.io.*;
import java.util.Observable; import java.util.Observable;
import java.util.Observer; import java.util.Observer;
@ -51,7 +53,7 @@ import java.util.logging.Logger;
* and a simulated ACIA for serial I/O. The ACIA is attached to a dumb terminal * and a simulated ACIA for serial I/O. The ACIA is attached to a dumb terminal
* with a basic 80x25 character display. * with a basic 80x25 character display.
*/ */
public class Simulator implements Observer { public class Simulator {
// Constants used by the simulated system. These define the memory map. // Constants used by the simulated system. These define the memory map.
private static final int BUS_BOTTOM = 0x0000; private static final int BUS_BOTTOM = 0x0000;
@ -71,8 +73,10 @@ public class Simulator implements Observer {
private static final int ROM_BASE = 0xC000; private static final int ROM_BASE = 0xC000;
private static final int ROM_SIZE = 0x4000; private static final int ROM_SIZE = 0x4000;
private static final int DEFAULT_FONT_SIZE = 12; // UI constants
private static final Font DEFAULT_FONT = new Font(Font.MONOSPACED, Font.PLAIN, DEFAULT_FONT_SIZE); private static final int DEFAULT_FONT_SIZE = 12;
private static final Font DEFAULT_FONT = new Font(Font.MONOSPACED, Font.PLAIN, DEFAULT_FONT_SIZE);
private static final int CONSOLE_BORDER_WIDTH = 10;
// Since it is very expensive to update the UI with Swing's Event Dispatch Thread, we can't afford // Since it is very expensive to update the UI with Swing's Event Dispatch Thread, we can't afford
// to refresh the status view on every simulated clock cycle. Instead, we will only refresh the status view // to refresh the status view on every simulated clock cycle. Instead, we will only refresh the status view
@ -99,6 +103,9 @@ public class Simulator implements Observer {
// requested // requested
private int stepsSinceLastUpdate = 0; private int stepsSinceLastUpdate = 0;
// The number of steps to run per click of the "Step" button
private int stepsPerClick = 1;
/** /**
* The Main Window is the primary control point for the simulator. * The Main Window is the primary control point for the simulator.
* It is in charge of the menu, and sub-windows. It also shows the * It is in charge of the menu, and sub-windows. It also shows the
@ -130,10 +137,16 @@ public class Simulator implements Observer {
private JButton runStopButton; private JButton runStopButton;
private JButton stepButton; private JButton stepButton;
private JButton resetButton; private JButton resetButton;
private JComboBox stepCountBox;
private JFileChooser fileChooser; private JFileChooser fileChooser;
private PreferencesDialog preferences; private PreferencesDialog preferences;
/**
* The list of step counts that will appear in the "Step" drop-down.
*/
private static final String[] STEPS = {"1", "5", "10", "20", "50", "100"};
public Simulator() throws MemoryRangeException, IOException { public Simulator() throws MemoryRangeException, IOException {
this.acia = new Acia(ACIA_BASE); this.acia = new Acia(ACIA_BASE);
this.via = new Via(VIA_BASE); this.via = new Via(VIA_BASE);
@ -172,10 +185,11 @@ public class Simulator implements Observer {
this.console = new com.loomcom.symon.ui.Console(80, 25, DEFAULT_FONT); this.console = new com.loomcom.symon.ui.Console(80, 25, DEFAULT_FONT);
this.statusPane = new StatusPanel(); this.statusPane = new StatusPanel();
console.setBorderWidth(CONSOLE_BORDER_WIDTH);
// File Chooser // File Chooser
fileChooser = new JFileChooser(System.getProperty("user.dir")); fileChooser = new JFileChooser(System.getProperty("user.dir"));
preferences = new PreferencesDialog(mainWindow, true); preferences = new PreferencesDialog(mainWindow, true);
preferences.addObserver(this);
// Panel for Console and Buttons // Panel for Console and Buttons
JPanel consoleContainer = new JPanel(); JPanel consoleContainer = new JPanel();
@ -189,8 +203,22 @@ public class Simulator implements Observer {
stepButton = new JButton("Step"); stepButton = new JButton("Step");
resetButton = new JButton("Reset"); resetButton = new JButton("Reset");
stepCountBox = new JComboBox(STEPS);
stepCountBox.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent actionEvent) {
try {
JComboBox cb = (JComboBox) actionEvent.getSource();
stepsPerClick = Integer.parseInt((String) cb.getSelectedItem());
} catch (NumberFormatException ex) {
stepsPerClick = 1;
stepCountBox.setSelectedIndex(0);
}
}
});
buttonContainer.add(runStopButton); buttonContainer.add(runStopButton);
buttonContainer.add(stepButton); buttonContainer.add(stepButton);
buttonContainer.add(stepCountBox);
buttonContainer.add(resetButton); buttonContainer.add(resetButton);
// Left side - console // Left side - console
@ -215,7 +243,7 @@ public class Simulator implements Observer {
stepButton.addActionListener(new ActionListener() { stepButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent actionEvent) { public void actionPerformed(ActionEvent actionEvent) {
handleStep(); handleStep(stepsPerClick);
} }
}); });
@ -290,11 +318,13 @@ public class Simulator implements Observer {
} }
/** /**
* Step once, and immediately refresh the UI. * Step the requested number of times, and immediately refresh the UI.
*/ */
private void handleStep() { private void handleStep(int numSteps) {
try { try {
step(); for (int i = 0; i < numSteps; i++) {
step();
}
SwingUtilities.invokeLater(new Runnable() { SwingUtilities.invokeLater(new Runnable() {
public void run() { public void run() {
if (traceLog.isVisible()) { if (traceLog.isVisible()) {
@ -378,24 +408,6 @@ public class Simulator implements Observer {
}); });
} }
/**
* The configuration has changed. Re-load.
*
* @param observable
* @param o
*/
public void update(Observable observable, Object o) {
// Instance equality should work here, there is only one instance.
if (observable == preferences) {
int oldBorderWidth = console.getBorderWidth();
if (oldBorderWidth != preferences.getBorderWidth()) {
// Resize the main window if the border width has changed.
console.setBorderWidth(preferences.getBorderWidth());
mainWindow.pack();
}
}
}
/** /**
* Main entry point to the simulator. Creates a simulator and shows the main * Main entry point to the simulator. Creates a simulator and shows the main
* window. * window.
@ -441,6 +453,7 @@ public class Simulator implements Observer {
public void run() { public void run() {
// Don't allow step while the simulator is running // Don't allow step while the simulator is running
stepButton.setEnabled(false); stepButton.setEnabled(false);
stepCountBox.setEnabled(false);
menuBar.simulatorDidStart(); menuBar.simulatorDidStart();
// Toggle the state of the run button // Toggle the state of the run button
runStopButton.setText("Stop"); runStopButton.setText("Stop");
@ -461,6 +474,7 @@ public class Simulator implements Observer {
statusPane.updateState(cpu); statusPane.updateState(cpu);
runStopButton.setText("Run"); runStopButton.setText("Run");
stepButton.setEnabled(true); stepButton.setEnabled(true);
stepCountBox.setEnabled(true);
if (traceLog.isVisible()) { if (traceLog.isVisible()) {
traceLog.refresh(); traceLog.refresh();
} }

View File

@ -28,11 +28,19 @@ import com.loomcom.symon.exceptions.MemoryAccessException;
import com.loomcom.symon.util.HexUtil; import com.loomcom.symon.util.HexUtil;
import javax.swing.*; import javax.swing.*;
import javax.swing.border.Border;
import javax.swing.border.CompoundBorder;
import javax.swing.border.EmptyBorder; import javax.swing.border.EmptyBorder;
import javax.swing.border.MatteBorder;
import javax.swing.table.AbstractTableModel; import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableModel;
import javax.swing.text.JTextComponent;
import java.awt.*; import java.awt.*;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;
import java.awt.event.ActionListener; import java.awt.event.ActionListener;
import java.util.EventObject;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
@ -45,8 +53,22 @@ public class MemoryWindow extends JFrame implements ActionListener {
private MemoryTableModel memoryTableModel; private MemoryTableModel memoryTableModel;
private JTable memoryTable; private JTable memoryTable;
private JTextField pageNumberTextField; private JTextField pageNumberTextField;
private JButton previousPageButton;
private JButton nextPageButton;
private static final Dimension MINIMUM_SIZE = new Dimension(380, 400); private static final Dimension MINIMUM_SIZE = new Dimension(320, 600);
// The width of column 0 (address), in pixels
private static final int ADDR_COL_WIDTH = 48;
private static final int HEX_COL_WIDTH = 32;
// The width of the ASCII cells, in pixels
private static final int ASCII_COL_WIDTH = 8;
// The start/end columns of the ASCII view
private static final int ASCII_COL_START = 9;
private static final int ASCII_COL_END = 16;
/** /**
* Initialize a new MemoryWindow frame with the specified Bus. * Initialize a new MemoryWindow frame with the specified Bus.
@ -81,8 +103,12 @@ public class MemoryWindow extends JFrame implements ActionListener {
* Set the contents of the page number text field with the current * Set the contents of the page number text field with the current
* page number, in hex. * page number, in hex.
*/ */
private void updatePageNumberTextField() { private void updateControls() {
pageNumberTextField.setText(HexUtil.byteToHex(getPageNumber())); int pageNumber = getPageNumber();
previousPageButton.setEnabled(pageNumber > 0x00);
nextPageButton.setEnabled(pageNumber < 0xff);
pageNumberTextField.setText(HexUtil.byteToHex(pageNumber));
} }
/** /**
@ -90,35 +116,54 @@ public class MemoryWindow extends JFrame implements ActionListener {
*/ */
private void createUi() { private void createUi() {
setTitle("Memory Contents"); setTitle("Memory Contents");
this.memoryTable = new JTable(memoryTableModel); this.memoryTable = new MemoryTable(memoryTableModel);
memoryTable.setDragEnabled(false); memoryTable.setDragEnabled(false);
memoryTable.setCellSelectionEnabled(false); memoryTable.setCellSelectionEnabled(false);
memoryTable.setShowGrid(true); memoryTable.setIntercellSpacing(new Dimension(0, 0));
memoryTable.setShowHorizontalLines(true);
memoryTable.setShowVerticalLines(true);
memoryTable.setGridColor(Color.LIGHT_GRAY);
memoryTable.getTableHeader().setReorderingAllowed(false); memoryTable.getTableHeader().setReorderingAllowed(false);
memoryTable.getTableHeader().setResizingAllowed(false); memoryTable.getTableHeader().setResizingAllowed(false);
memoryTable.getTableHeader().setVisible(false); memoryTable.getTableHeader().setVisible(false);
memoryTable.getColumnModel().getColumn(0).setMaxWidth(ADDR_COL_WIDTH);
for (int i = 1; i < ASCII_COL_START; i++) {
memoryTable.getColumnModel().getColumn(i).setMaxWidth(HEX_COL_WIDTH);
}
for (int i = ASCII_COL_START; i <= ASCII_COL_END; i++) {
memoryTable.getColumnModel().getColumn(i).setMaxWidth(ASCII_COL_WIDTH);
}
MemoryTableCellRenderer memoryTableCellRenderer = new MemoryTableCellRenderer();
memoryTableCellRenderer.setHorizontalAlignment(JLabel.CENTER);
memoryTable.setDefaultRenderer(String.class, memoryTableCellRenderer);
// Turn off tool-tips for the table. // Turn off tool-tips for the table.
ToolTipManager.sharedInstance().unregisterComponent(memoryTable); ToolTipManager.sharedInstance().unregisterComponent(memoryTable);
ToolTipManager.sharedInstance().unregisterComponent(memoryTable.getTableHeader()); ToolTipManager.sharedInstance().unregisterComponent(memoryTable.getTableHeader());
JLabel pageNumberLabel = new JLabel("Page Number"); JLabel pageNumberLabel = new JLabel("Page");
pageNumberTextField = new JTextField(8); pageNumberTextField = new JTextField(8);
pageNumberTextField.addActionListener(this); pageNumberTextField.addActionListener(this);
updatePageNumberTextField(); nextPageButton = new JButton("Next >>");
previousPageButton = new JButton("<< Prev");
nextPageButton.addActionListener(this);
previousPageButton.addActionListener(this);
updateControls();
JPanel controlPanel = new JPanel(); JPanel controlPanel = new JPanel();
JPanel memoryPanel = new JPanel(); JPanel memoryPanel = new JPanel();
memoryPanel.setLayout(new BorderLayout()); memoryPanel.setLayout(new BorderLayout());
memoryPanel.setBorder(new EmptyBorder(10, 10, 10, 10)); memoryPanel.setBorder(new EmptyBorder(10, 10, 10, 10));
controlPanel.add(previousPageButton);
controlPanel.add(pageNumberLabel); controlPanel.add(pageNumberLabel);
controlPanel.add(pageNumberTextField); controlPanel.add(pageNumberTextField);
controlPanel.add(nextPageButton);
JScrollPane scrollPane = new JScrollPane(memoryTable); JScrollPane scrollPane = new JScrollPane(memoryTable);
scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED); scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
@ -131,7 +176,8 @@ public class MemoryWindow extends JFrame implements ActionListener {
getContentPane().add(memoryPanel, BorderLayout.CENTER); getContentPane().add(memoryPanel, BorderLayout.CENTER);
setMinimumSize(MINIMUM_SIZE); setMinimumSize(MINIMUM_SIZE);
setPreferredSize(MINIMUM_SIZE); memoryPanel.setPreferredSize(memoryTable.getPreferredSize());
setPreferredSize(memoryPanel.getPreferredSize());
pack(); pack();
} }
@ -142,8 +188,21 @@ public class MemoryWindow extends JFrame implements ActionListener {
* @param e The action event * @param e The action event
*/ */
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
if (e.getSource() == pageNumberTextField) { if (e.getSource() == previousPageButton) {
int currentPage = getPageNumber();
if (currentPage > 0x00) {
setPageNumber(currentPage - 1);
updateControls();
memoryTable.updateUI();
}
} else if (e.getSource() == nextPageButton) {
int currentPage = getPageNumber();
if (currentPage < 0xff) {
setPageNumber(currentPage + 1);
updateControls();
memoryTable.updateUI();
}
} else if (e.getSource() == pageNumberTextField) {
String pageNumberInput = pageNumberTextField.getText(); String pageNumberInput = pageNumberTextField.getText();
try { try {
// Try to parse a hex value out of the pageNumber. // Try to parse a hex value out of the pageNumber.
@ -156,7 +215,50 @@ public class MemoryWindow extends JFrame implements ActionListener {
Logger.getLogger(this.getClass().getName()).log(Level.WARNING, "Can't parse page number " + Logger.getLogger(this.getClass().getName()).log(Level.WARNING, "Can't parse page number " +
pageNumberInput); pageNumberInput);
} }
updatePageNumberTextField(); updateControls();
}
}
/**
* A JTable that will automatically select all text in a cell
* being edited.
*/
private class MemoryTable extends JTable {
public MemoryTable(TableModel tableModel) {
super(tableModel);
}
@Override
public boolean editCellAt(int row, int col, EventObject e) {
boolean result = super.editCellAt(row, col, e);
final Component editor = getEditorComponent();
if (editor != null && editor instanceof JTextComponent) {
((JTextComponent) editor).selectAll();
}
return result;
}
}
private class MemoryTableCellRenderer extends DefaultTableCellRenderer {
@Override
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus,
int row, int col) {
final Component cell = super.getTableCellRendererComponent(table, value,
isSelected, hasFocus,
row, col);
if (isSelected) {
cell.setBackground(Color.LIGHT_GRAY);
cell.setForeground(Color.BLACK);
}
return cell;
} }
} }
@ -168,7 +270,7 @@ public class MemoryWindow extends JFrame implements ActionListener {
private Bus bus; private Bus bus;
private int pageNumber; private int pageNumber;
private static final int COLUMN_COUNT = 9; private static final int COLUMN_COUNT = 17;
private static final int ROW_COUNT = 32; private static final int ROW_COUNT = 32;
public MemoryTableModel(Bus bus) { public MemoryTableModel(Bus bus) {
@ -213,15 +315,19 @@ public class MemoryWindow extends JFrame implements ActionListener {
@Override @Override
public boolean isCellEditable(int row, int column) { public boolean isCellEditable(int row, int column) {
return column > 0; return (column > 0 && column < ASCII_COL_START);
} }
public Object getValueAt(int row, int column) { public Object getValueAt(int row, int column) {
try { try {
if (column == 0) { if (column == 0) {
return HexUtil.wordToHex(fullAddress(row, 1)); return HexUtil.wordToHex(fullAddress(row, 1));
} else { } else if (column < 9) {
// Display hex value of the data
return HexUtil.byteToHex(bus.read(fullAddress(row, column))); return HexUtil.byteToHex(bus.read(fullAddress(row, column)));
} else {
// Display the ASCII equivalent (if printable)
return HexUtil.byteToAscii(bus.read(fullAddress(row, column - 8)));
} }
} catch (MemoryAccessException ex) { } catch (MemoryAccessException ex) {
return "??"; return "??";
@ -234,7 +340,7 @@ public class MemoryWindow extends JFrame implements ActionListener {
try { try {
String hexValue = (String)o; String hexValue = (String)o;
int fullAddress = fullAddress(row, column); int fullAddress = fullAddress(row, column);
int newValue = Integer.parseInt(hexValue, 16); int newValue = Integer.parseInt(hexValue, 16) & 0xff;
bus.write(fullAddress, newValue); bus.write(fullAddress, newValue);
} catch (MemoryAccessException ex) { } catch (MemoryAccessException ex) {
; ;

View File

@ -40,10 +40,8 @@ public class PreferencesDialog extends Observable implements Preferences {
private JCheckBox haltOnBreakCheckBox; private JCheckBox haltOnBreakCheckBox;
private JTextField programLoadAddressField; private JTextField programLoadAddressField;
private JTextField borderWidthField;
private int programLoadAddress = DEFAULT_PROGRAM_LOAD_ADDRESS; private int programLoadAddress = DEFAULT_PROGRAM_LOAD_ADDRESS;
private int borderWidth = DEFAULT_BORDER_WIDTH;
private boolean haltOnBreak = DEFAULT_HALT_ON_BREAK; private boolean haltOnBreak = DEFAULT_HALT_ON_BREAK;
public PreferencesDialog(Frame parent, boolean modal) { public PreferencesDialog(Frame parent, boolean modal) {
@ -72,14 +70,11 @@ public class PreferencesDialog extends Observable implements Preferences {
final JLabel haltOnBreakLabel = new JLabel("Halt on BRK"); final JLabel haltOnBreakLabel = new JLabel("Halt on BRK");
final JLabel programLoadAddressLabel = new JLabel("Program Load Address"); final JLabel programLoadAddressLabel = new JLabel("Program Load Address");
final JLabel borderWidthLabel = new JLabel("Console Border Width");
haltOnBreakCheckBox = new JCheckBox(); haltOnBreakCheckBox = new JCheckBox();
programLoadAddressField = new JTextField(8); programLoadAddressField = new JTextField(8);
borderWidthField = new JTextField(8);
programLoadAddressLabel.setLabelFor(programLoadAddressField); programLoadAddressLabel.setLabelFor(programLoadAddressField);
borderWidthLabel.setLabelFor(borderWidthField);
GridBagConstraints constraints = new GridBagConstraints(); GridBagConstraints constraints = new GridBagConstraints();
@ -99,17 +94,9 @@ public class PreferencesDialog extends Observable implements Preferences {
constraints.gridx = 1; constraints.gridx = 1;
settingsContainer.add(programLoadAddressField, constraints); settingsContainer.add(programLoadAddressField, constraints);
constraints.gridy = 2;
constraints.gridx = 0;
settingsContainer.add(borderWidthLabel, constraints);
constraints.gridx = 1;
settingsContainer.add(borderWidthField, constraints);
JButton applyButton = new JButton("Apply"); JButton applyButton = new JButton("Apply");
JButton cancelButton = new JButton("Cancel"); JButton cancelButton = new JButton("Cancel");
cancelButton.addActionListener(new ActionListener() { cancelButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent actionEvent) { public void actionPerformed(ActionEvent actionEvent) {
updateUi(); updateUi();
@ -121,7 +108,6 @@ public class PreferencesDialog extends Observable implements Preferences {
public void actionPerformed(ActionEvent actionEvent) { public void actionPerformed(ActionEvent actionEvent) {
haltOnBreak = haltOnBreakCheckBox.isSelected(); haltOnBreak = haltOnBreakCheckBox.isSelected();
programLoadAddress = hexToInt(programLoadAddressField.getText()); programLoadAddress = hexToInt(programLoadAddressField.getText());
borderWidth = Integer.parseInt(borderWidthField.getText());
updateUi(); updateUi();
// TODO: Actually check to see if values have changed, don't assume. // TODO: Actually check to see if values have changed, don't assume.
setChanged(); setChanged();
@ -143,13 +129,6 @@ public class PreferencesDialog extends Observable implements Preferences {
return programLoadAddress; return programLoadAddress;
} }
/**
* @return The width of the console border, in pixels.
*/
public int getBorderWidth() {
return borderWidth;
}
/** /**
* @return True if 'halt on break' is desired, false otherwise. * @return True if 'halt on break' is desired, false otherwise.
*/ */
@ -160,7 +139,6 @@ public class PreferencesDialog extends Observable implements Preferences {
public void updateUi() { public void updateUi() {
haltOnBreakCheckBox.setSelected(haltOnBreak); haltOnBreakCheckBox.setSelected(haltOnBreak);
programLoadAddressField.setText(intToHex(programLoadAddress)); programLoadAddressField.setText(intToHex(programLoadAddress));
borderWidthField.setText(Integer.toString(borderWidth));
} }
private String intToHex(int i) { private String intToHex(int i) {

View File

@ -42,38 +42,67 @@ package com.loomcom.symon.util;
* *
*/ */
public class HexUtil { public class HexUtil {
private static final String[] HEX_CONSTANTS = {"00", "01", "02", "03", "04", "05", "06", "07",
"08", "09", "0A", "0B", "0C", "0D", "0E", "0F", static final String NON_PRINTABLE = ".";
"10", "11", "12", "13", "14", "15", "16", "17",
"18", "19", "1A", "1B", "1C", "1D", "1E", "1F", static final String[] ASCII_CONSTANTS = {" ", "!", "\"", "#", "$", "%", "&", "'",
"20", "21", "22", "23", "24", "25", "26", "27", "(", ")", "*", "+", ",", "-", ".", "/",
"28", "29", "2A", "2B", "2C", "2D", "2E", "2F", "0", "1", "2", "3", "4", "5", "6", "7",
"30", "31", "32", "33", "34", "35", "36", "37", "8", "9", ":", ";", "<", "=", ">", "?",
"38", "39", "3A", "3B", "3C", "3D", "3E", "3F", "@", "A", "B", "C", "D", "E", "F", "G",
"40", "41", "42", "43", "44", "45", "46", "47", "H", "I", "J", "K", "L", "M", "N", "O",
"48", "49", "4A", "4B", "4C", "4D", "4E", "4F", "P", "Q", "R", "S", "T", "U", "V", "W",
"50", "51", "52", "53", "54", "55", "56", "57", "X", "Y", "Z", "[", "\\", "]", "^", "_",
"58", "59", "5A", "5B", "5C", "5D", "5E", "5F", "`", "a", "b", "c", "d", "e", "f", "g",
"60", "61", "62", "63", "64", "65", "66", "67", "h", "i", "j", "k", "l", "m", "n", "o",
"68", "69", "6A", "6B", "6C", "6D", "6E", "6F", "p", "q", "r", "s", "t", "u", "v", "w",
"70", "71", "72", "73", "74", "75", "76", "77", "x", "y", "z", "{", "|", "}", "~"};
"78", "79", "7A", "7B", "7C", "7D", "7E", "7F",
"80", "81", "82", "83", "84", "85", "86", "87", static final String[] HEX_CONSTANTS = {"00", "01", "02", "03", "04", "05", "06", "07",
"88", "89", "8A", "8B", "8C", "8D", "8E", "8F", "08", "09", "0A", "0B", "0C", "0D", "0E", "0F",
"90", "91", "92", "93", "94", "95", "96", "97", "10", "11", "12", "13", "14", "15", "16", "17",
"98", "99", "9A", "9B", "9C", "9D", "9E", "9F", "18", "19", "1A", "1B", "1C", "1D", "1E", "1F",
"A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7", "20", "21", "22", "23", "24", "25", "26", "27",
"A8", "A9", "AA", "AB", "AC", "AD", "AE", "AF", "28", "29", "2A", "2B", "2C", "2D", "2E", "2F",
"B0", "B1", "B2", "B3", "B4", "B5", "B6", "B7", "30", "31", "32", "33", "34", "35", "36", "37",
"B8", "B9", "BA", "BB", "BC", "BD", "BE", "BF", "38", "39", "3A", "3B", "3C", "3D", "3E", "3F",
"C0", "C1", "C2", "C3", "C4", "C5", "C6", "C7", "40", "41", "42", "43", "44", "45", "46", "47",
"C8", "C9", "CA", "CB", "CC", "CD", "CE", "CF", "48", "49", "4A", "4B", "4C", "4D", "4E", "4F",
"D0", "D1", "D2", "D3", "D4", "D5", "D6", "D7", "50", "51", "52", "53", "54", "55", "56", "57",
"D8", "D9", "DA", "DB", "DC", "DD", "DE", "DF", "58", "59", "5A", "5B", "5C", "5D", "5E", "5F",
"E0", "E1", "E2", "E3", "E4", "E5", "E6", "E7", "60", "61", "62", "63", "64", "65", "66", "67",
"E8", "E9", "EA", "EB", "EC", "ED", "EE", "EF", "68", "69", "6A", "6B", "6C", "6D", "6E", "6F",
"F0", "F1", "F2", "F3", "F4", "F5", "F6", "F7", "70", "71", "72", "73", "74", "75", "76", "77",
"F8", "F9", "FA", "FB", "FC", "FD", "FE", "FF"}; "78", "79", "7A", "7B", "7C", "7D", "7E", "7F",
"80", "81", "82", "83", "84", "85", "86", "87",
"88", "89", "8A", "8B", "8C", "8D", "8E", "8F",
"90", "91", "92", "93", "94", "95", "96", "97",
"98", "99", "9A", "9B", "9C", "9D", "9E", "9F",
"A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7",
"A8", "A9", "AA", "AB", "AC", "AD", "AE", "AF",
"B0", "B1", "B2", "B3", "B4", "B5", "B6", "B7",
"B8", "B9", "BA", "BB", "BC", "BD", "BE", "BF",
"C0", "C1", "C2", "C3", "C4", "C5", "C6", "C7",
"C8", "C9", "CA", "CB", "CC", "CD", "CE", "CF",
"D0", "D1", "D2", "D3", "D4", "D5", "D6", "D7",
"D8", "D9", "DA", "DB", "DC", "DD", "DE", "DF",
"E0", "E1", "E2", "E3", "E4", "E5", "E6", "E7",
"E8", "E9", "EA", "EB", "EC", "ED", "EE", "EF",
"F0", "F1", "F2", "F3", "F4", "F5", "F6", "F7",
"F8", "F9", "FA", "FB", "FC", "FD", "FE", "FF"};
/**
* Very fast 8-bit int to ASCII conversion.
* @param val The value of an ASCII character.
* @return A string representing the ASCII character.
*/
public static String byteToAscii(int val) {
if (val >= 32 && val <= 126) {
return ASCII_CONSTANTS[val - 32];
} else {
return NON_PRINTABLE;
}
}
/** /**
* Very fast 8-bit int to hex conversion, with zero-padded output. * Very fast 8-bit int to hex conversion, with zero-padded output.