mirror of
https://codeberg.org/sethm/symon.git
synced 2026-11-07 19:12:23 +00:00
Compare commits
3
Commits
v1.2.0
..
1.2.branch
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0e49b197b3 | ||
|
|
eff98118d5 | ||
|
|
66c52c8826 |
No files matched your search
@@ -1,9 +1,9 @@
|
||||
SYMON - A 6502 System Simulator
|
||||
===============================
|
||||
|
||||
**Version:** 1.2.0
|
||||
**Version:** 1.2.1
|
||||
|
||||
**Last Updated:** 3 January, 2016
|
||||
**Last Updated:** 8 January, 2016
|
||||
|
||||
See the file COPYING for license.
|
||||
|
||||
@@ -235,6 +235,9 @@ running.
|
||||
|
||||
## 5.0 Revision History
|
||||
|
||||
- **1.2.1:** 8 January, 2016 - Remove dependency on Java 8. Now
|
||||
supports compiling and running under Java 1.7.
|
||||
|
||||
- **1.2.0:** 3 January, 2016 - Add symbolic disassembly to breakpoints
|
||||
window.
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<groupId>com.loomcom.symon</groupId>
|
||||
<artifactId>symon</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<version>1.2.0</version>
|
||||
<version>1.2.1</version>
|
||||
<name>symon</name>
|
||||
<url>http://www.loomcom.com/symon</url>
|
||||
<properties>
|
||||
@@ -91,8 +91,8 @@
|
||||
<version>3.1</version>
|
||||
<configuration>
|
||||
<compilerArgument>-Xlint:unchecked</compilerArgument>
|
||||
<source>1.8</source>
|
||||
<target>1.8</target>
|
||||
<source>1.7</source>
|
||||
<target>1.7</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
|
||||
@@ -34,7 +34,6 @@ import java.util.Map;
|
||||
|
||||
import java.util.SortedSet;
|
||||
import java.util.TreeSet;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* The Bus ties the whole thing together, man.
|
||||
@@ -222,9 +221,11 @@ public class Bus {
|
||||
List<Integer> priorities = new ArrayList<>(deviceMap.keySet());
|
||||
Collections.sort(priorities);
|
||||
|
||||
for(int priority : priorities) {
|
||||
for (int priority : priorities) {
|
||||
SortedSet<Device> deviceSet = deviceMap.get(priority);
|
||||
devices.addAll(deviceSet.stream().collect(Collectors.toList()));
|
||||
for (Device device : deviceSet) {
|
||||
devices.add(device);
|
||||
}
|
||||
}
|
||||
|
||||
return devices;
|
||||
|
||||
@@ -86,13 +86,16 @@ public class Main {
|
||||
|
||||
final Simulator simulator = new Simulator(machineClass);
|
||||
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
try {
|
||||
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
|
||||
// Create the main UI window
|
||||
simulator.createAndShowUi();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
|
||||
// Create the main UI window
|
||||
simulator.createAndShowUi();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -185,13 +185,16 @@ public class Simulator {
|
||||
JButton hardResetButton = new JButton("Hard Reset");
|
||||
|
||||
stepCountBox = new JComboBox<>(STEPS);
|
||||
stepCountBox.addActionListener(actionEvent -> {
|
||||
try {
|
||||
JComboBox cb = (JComboBox) actionEvent.getSource();
|
||||
stepsPerClick = Integer.parseInt((String) cb.getSelectedItem());
|
||||
} catch (NumberFormatException ex) {
|
||||
stepsPerClick = 1;
|
||||
stepCountBox.setSelectedIndex(0);
|
||||
stepCountBox.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
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);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -211,24 +214,38 @@ public class Simulator {
|
||||
// Bottom - buttons.
|
||||
mainWindow.getContentPane().add(buttonContainer, BorderLayout.PAGE_END);
|
||||
|
||||
runStopButton.addActionListener(actionEvent -> {
|
||||
if (runLoop != null && runLoop.isRunning()) {
|
||||
handleStop();
|
||||
} else {
|
||||
handleStart();
|
||||
runStopButton.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent actionEvent) {
|
||||
if (runLoop != null && runLoop.isRunning()) {
|
||||
Simulator.this.handleStop();
|
||||
} else {
|
||||
Simulator.this.handleStart();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
stepButton.addActionListener(actionEvent -> handleStep(stepsPerClick));
|
||||
|
||||
softResetButton.addActionListener(actionEvent -> {
|
||||
// If this was a CTRL-click, do a hard reset.
|
||||
handleReset(false);
|
||||
stepButton.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent actionEvent) {
|
||||
Simulator.this.handleStep(stepsPerClick);
|
||||
}
|
||||
});
|
||||
|
||||
hardResetButton.addActionListener(actionEvent -> {
|
||||
// If this was a CTRL-click, do a hard reset.
|
||||
handleReset(true);
|
||||
softResetButton.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent actionEvent) {
|
||||
// If this was a CTRL-click, do a hard reset.
|
||||
Simulator.this.handleReset(false);
|
||||
}
|
||||
});
|
||||
|
||||
hardResetButton.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent actionEvent) {
|
||||
// If this was a CTRL-click, do a hard reset.
|
||||
Simulator.this.handleReset(true);
|
||||
}
|
||||
});
|
||||
|
||||
mainWindow.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
|
||||
@@ -400,13 +417,16 @@ public class Simulator {
|
||||
logger.debug("Starting main run loop.");
|
||||
isRunning = true;
|
||||
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
// Don't allow step while the simulator is running
|
||||
stepButton.setEnabled(false);
|
||||
stepCountBox.setEnabled(false);
|
||||
menuBar.simulatorDidStart();
|
||||
// Toggle the state of the run button
|
||||
runStopButton.setText("Stop");
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
// Don't allow step while the simulator is running
|
||||
stepButton.setEnabled(false);
|
||||
stepCountBox.setEnabled(false);
|
||||
menuBar.simulatorDidStart();
|
||||
// Toggle the state of the run button
|
||||
runStopButton.setText("Stop");
|
||||
}
|
||||
});
|
||||
|
||||
try {
|
||||
@@ -417,17 +437,20 @@ public class Simulator {
|
||||
logger.error("Exception in main simulator run thread. Exiting run.", ex);
|
||||
}
|
||||
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
statusPane.updateState();
|
||||
memoryWindow.updateState();
|
||||
runStopButton.setText("Run");
|
||||
stepButton.setEnabled(true);
|
||||
stepCountBox.setEnabled(true);
|
||||
if (traceLog.isVisible()) {
|
||||
traceLog.refresh();
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
statusPane.updateState();
|
||||
memoryWindow.updateState();
|
||||
runStopButton.setText("Run");
|
||||
stepButton.setEnabled(true);
|
||||
stepCountBox.setEnabled(true);
|
||||
if (traceLog.isVisible()) {
|
||||
traceLog.refresh();
|
||||
}
|
||||
menuBar.simulatorDidStop();
|
||||
traceLog.simulatorDidStop();
|
||||
}
|
||||
menuBar.simulatorDidStop();
|
||||
traceLog.simulatorDidStop();
|
||||
});
|
||||
|
||||
isRunning = false;
|
||||
@@ -480,9 +503,12 @@ public class Simulator {
|
||||
// Now load the program at the starting address.
|
||||
loadProgram(program, preferences.getProgramStartAddress());
|
||||
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
console.reset();
|
||||
breakpoints.refresh();
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
console.reset();
|
||||
breakpoints.refresh();
|
||||
}
|
||||
});
|
||||
|
||||
// TODO: "Don't Show Again" checkbox
|
||||
@@ -623,9 +649,12 @@ public class Simulator {
|
||||
}
|
||||
|
||||
public void actionPerformed(ActionEvent actionEvent) {
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
console.setFont(new Font("Monospaced", Font.PLAIN, size));
|
||||
mainWindow.pack();
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
console.setFont(new Font("Monospaced", Font.PLAIN, size));
|
||||
mainWindow.pack();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -889,12 +918,15 @@ public class Simulator {
|
||||
|
||||
private void updateVisibleState() {
|
||||
// Immediately update the UI.
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
// Now update the state
|
||||
statusPane.updateState();
|
||||
memoryWindow.updateState();
|
||||
if (traceLog.shouldUpdate()) {
|
||||
traceLog.refresh();
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
// Now update the state
|
||||
statusPane.updateState();
|
||||
memoryWindow.updateState();
|
||||
if (traceLog.shouldUpdate()) {
|
||||
traceLog.refresh();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -115,7 +115,9 @@ public abstract class Device implements Comparable<Device> {
|
||||
}
|
||||
|
||||
public void notifyListeners() {
|
||||
deviceChangeListeners.forEach(DeviceChangeListener::deviceStateChanged);
|
||||
for (DeviceChangeListener listener : deviceChangeListeners) {
|
||||
listener.deviceStateChanged();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -27,7 +27,6 @@ package com.loomcom.symon.devices;
|
||||
|
||||
import com.loomcom.symon.exceptions.MemoryAccessException;
|
||||
import com.loomcom.symon.exceptions.MemoryRangeException;
|
||||
import jdk.nashorn.internal.ir.annotations.Ignore;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
|
||||
@@ -30,7 +30,10 @@ import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.border.EmptyBorder;
|
||||
import javax.swing.event.ListSelectionEvent;
|
||||
import javax.swing.event.ListSelectionListener;
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
|
||||
/**
|
||||
@@ -62,21 +65,24 @@ public class BreakpointsWindow extends JFrame {
|
||||
breakpointsPanel.setLayout(new BorderLayout());
|
||||
breakpointsPanel.setBorder(new EmptyBorder(10, 10, 10, 10));
|
||||
|
||||
JButton addButton = new JButton("Add");
|
||||
JButton removeButton = new JButton("Del");
|
||||
final JButton addButton = new JButton("Add");
|
||||
final JButton removeButton = new JButton("Del");
|
||||
removeButton.setEnabled(false);
|
||||
|
||||
JTextField addTextField = new JTextField(4);
|
||||
final JTextField addTextField = new JTextField(4);
|
||||
|
||||
JTable breakpointsTable = new JTable(breakpoints);
|
||||
final JTable breakpointsTable = new JTable(breakpoints);
|
||||
breakpointsTable.setShowGrid(true);
|
||||
breakpointsTable.setGridColor(Color.LIGHT_GRAY);
|
||||
breakpointsTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
|
||||
breakpointsTable.getSelectionModel().addListSelectionListener(e -> {
|
||||
if (e.getFirstIndex() > -1) {
|
||||
removeButton.setEnabled(true);
|
||||
} else {
|
||||
removeButton.setEnabled(false);
|
||||
breakpointsTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
|
||||
@Override
|
||||
public void valueChanged(ListSelectionEvent e) {
|
||||
if (e.getFirstIndex() > -1) {
|
||||
removeButton.setEnabled(true);
|
||||
} else {
|
||||
removeButton.setEnabled(false);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -86,37 +92,45 @@ public class BreakpointsWindow extends JFrame {
|
||||
|
||||
breakpointsPanel.add(scrollPane, BorderLayout.CENTER);
|
||||
|
||||
ActionListener addBreakpointListener = e -> {
|
||||
int value = -1;
|
||||
ActionListener addBreakpointListener = new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
int value;
|
||||
|
||||
String newBreakpoint = addTextField.getText();
|
||||
String newBreakpoint = addTextField.getText();
|
||||
|
||||
if (newBreakpoint == null || newBreakpoint.isEmpty()) {
|
||||
return;
|
||||
if (newBreakpoint == null || newBreakpoint.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
value = (Integer.parseInt(addTextField.getText(), 16) & 0xffff);
|
||||
} catch (NumberFormatException ex) {
|
||||
logger.warn("Can't parse page number {}", newBreakpoint);
|
||||
return;
|
||||
}
|
||||
|
||||
if (value < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
breakpoints.addBreakpoint(value);
|
||||
|
||||
logger.debug("Added breakpoint ${}", Utils.wordToHex(value));
|
||||
|
||||
addTextField.setText(EMPTY_STRING);
|
||||
}
|
||||
|
||||
try {
|
||||
value = (Integer.parseInt(addTextField.getText(), 16) & 0xffff);
|
||||
} catch (NumberFormatException ex) {
|
||||
logger.warn("Can't parse page number {}", newBreakpoint);
|
||||
return;
|
||||
}
|
||||
|
||||
if (value < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
breakpoints.addBreakpoint(value);
|
||||
|
||||
logger.debug("Added breakpoint ${}", Utils.wordToHex(value));
|
||||
|
||||
addTextField.setText(EMPTY_STRING);
|
||||
};
|
||||
|
||||
addButton.addActionListener(addBreakpointListener);
|
||||
addTextField.addActionListener(addBreakpointListener);
|
||||
|
||||
removeButton.addActionListener(e -> breakpoints.removeBreakpointAtIndex(breakpointsTable.getSelectedRow()));
|
||||
removeButton.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
breakpoints.removeBreakpointAtIndex(breakpointsTable.getSelectedRow());
|
||||
}
|
||||
});
|
||||
|
||||
controlPanel.add(addTextField);
|
||||
controlPanel.add(addButton);
|
||||
|
||||
@@ -97,19 +97,25 @@ public class PreferencesDialog extends Observable implements Preferences {
|
||||
JButton applyButton = new JButton("Apply");
|
||||
JButton cancelButton = new JButton("Cancel");
|
||||
|
||||
cancelButton.addActionListener(actionEvent -> {
|
||||
updateUi();
|
||||
dialog.setVisible(false);
|
||||
cancelButton.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent actionEvent) {
|
||||
PreferencesDialog.this.updateUi();
|
||||
dialog.setVisible(false);
|
||||
}
|
||||
});
|
||||
|
||||
applyButton.addActionListener(actionEvent -> {
|
||||
haltOnBreak = haltOnBreakCheckBox.isSelected();
|
||||
programLoadAddress = hexToInt(programLoadAddressField.getText());
|
||||
updateUi();
|
||||
// TODO: Actually check to see if values have changed, don't assume.
|
||||
setChanged();
|
||||
PreferencesDialog.this.notifyObservers();
|
||||
dialog.setVisible(false);
|
||||
applyButton.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent actionEvent) {
|
||||
haltOnBreak = haltOnBreakCheckBox.isSelected();
|
||||
programLoadAddress = PreferencesDialog.this.hexToInt(programLoadAddressField.getText());
|
||||
PreferencesDialog.this.updateUi();
|
||||
// TODO: Actually check to see if values have changed, don't assume.
|
||||
PreferencesDialog.this.setChanged();
|
||||
PreferencesDialog.this.notifyObservers();
|
||||
dialog.setVisible(false);
|
||||
}
|
||||
});
|
||||
|
||||
buttonsContainer.add(applyButton);
|
||||
|
||||
@@ -31,6 +31,8 @@ import javax.swing.*;
|
||||
import javax.swing.border.Border;
|
||||
import javax.swing.border.EtchedBorder;
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
|
||||
/**
|
||||
* UI component that displays the current state of the simulated CPU.
|
||||
@@ -162,59 +164,74 @@ public class StatusPanel extends JPanel {
|
||||
yField = makeTextField(SMALL_TEXT_FIELD_SIZE, true);
|
||||
|
||||
// Make fields editable
|
||||
pcField.addActionListener(e -> {
|
||||
try {
|
||||
int newVal = getHexVal(pcField) & 0xffff;
|
||||
machine.getCpu().setProgramCounter(newVal);
|
||||
} catch (Exception ex) {
|
||||
// Swallow exception
|
||||
}
|
||||
pcField.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
try {
|
||||
int newVal = StatusPanel.this.getHexVal(pcField) & 0xffff;
|
||||
machine.getCpu().setProgramCounter(newVal);
|
||||
} catch (Exception ex) {
|
||||
// Swallow exception
|
||||
}
|
||||
|
||||
updateState();
|
||||
StatusPanel.this.updateState();
|
||||
}
|
||||
});
|
||||
|
||||
spField.addActionListener(e -> {
|
||||
try {
|
||||
int newVal = getHexVal(spField) & 0xff;
|
||||
machine.getCpu().setStackPointer(newVal);
|
||||
} catch (Exception ex) {
|
||||
// Swallow exception
|
||||
}
|
||||
spField.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
try {
|
||||
int newVal = StatusPanel.this.getHexVal(spField) & 0xff;
|
||||
machine.getCpu().setStackPointer(newVal);
|
||||
} catch (Exception ex) {
|
||||
// Swallow exception
|
||||
}
|
||||
|
||||
updateState();
|
||||
StatusPanel.this.updateState();
|
||||
}
|
||||
});
|
||||
|
||||
aField.addActionListener(e -> {
|
||||
try {
|
||||
int newVal = getHexVal(aField) & 0xff;
|
||||
machine.getCpu().setAccumulator(newVal);
|
||||
} catch (Exception ex) {
|
||||
// Swallow exception
|
||||
}
|
||||
aField.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
try {
|
||||
int newVal = StatusPanel.this.getHexVal(aField) & 0xff;
|
||||
machine.getCpu().setAccumulator(newVal);
|
||||
} catch (Exception ex) {
|
||||
// Swallow exception
|
||||
}
|
||||
|
||||
updateState();
|
||||
StatusPanel.this.updateState();
|
||||
}
|
||||
});
|
||||
|
||||
xField.addActionListener(e -> {
|
||||
try {
|
||||
int newVal = getHexVal(xField) & 0xff;
|
||||
machine.getCpu().setXRegister(newVal);
|
||||
} catch (Exception ex) {
|
||||
// Swallow exception
|
||||
}
|
||||
xField.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
try {
|
||||
int newVal = StatusPanel.this.getHexVal(xField) & 0xff;
|
||||
machine.getCpu().setXRegister(newVal);
|
||||
} catch (Exception ex) {
|
||||
// Swallow exception
|
||||
}
|
||||
|
||||
updateState();
|
||||
StatusPanel.this.updateState();
|
||||
}
|
||||
});
|
||||
|
||||
yField.addActionListener(e -> {
|
||||
try {
|
||||
int newVal = getHexVal(yField) & 0xff;
|
||||
machine.getCpu().setYRegister(newVal);
|
||||
} catch (Exception ex) {
|
||||
// Swallow exception
|
||||
}
|
||||
yField.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
try {
|
||||
int newVal = StatusPanel.this.getHexVal(yField) & 0xff;
|
||||
machine.getCpu().setYRegister(newVal);
|
||||
} catch (Exception ex) {
|
||||
// Swallow exception
|
||||
}
|
||||
|
||||
updateState();
|
||||
StatusPanel.this.updateState();
|
||||
}
|
||||
});
|
||||
|
||||
constraints.anchor = GridBagConstraints.LINE_START;
|
||||
|
||||
@@ -122,10 +122,13 @@ public class VideoWindow extends JFrame implements DeviceChangeListener {
|
||||
*/
|
||||
private class CursorBlinker implements Runnable {
|
||||
public void run() {
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
if (cursorBlinkRate > 0) {
|
||||
hideCursor = !hideCursor;
|
||||
repaint();
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (cursorBlinkRate > 0) {
|
||||
hideCursor = !hideCursor;
|
||||
VideoWindow.this.repaint();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user