Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fcc57d9be4 | ||
|
|
88eba2cdcb | ||
|
|
0e49b197b3 | ||
|
|
b59fa63b63 | ||
|
|
eff98118d5 | ||
|
|
c599df1cfb | ||
|
|
66c52c8826 | ||
|
|
f3a5dd93ad | ||
|
|
4044458baa | ||
|
|
9ab94b3050 | ||
|
|
9a504adc58 | ||
|
|
57cbff42e7 | ||
|
|
0ca30291cb | ||
|
|
95f85b71b1 | ||
|
|
7a9f9bfd55 | ||
|
|
1e04a52d1b |
No files matched your search
@@ -1,9 +1,9 @@
|
||||
SYMON - A 6502 System Simulator
|
||||
===============================
|
||||
|
||||
**Version:** 1.1.1
|
||||
**Version:** 1.2.1
|
||||
|
||||
**Last Updated:** 2 January, 2016
|
||||
**Last Updated:** 8 January, 2016
|
||||
|
||||
See the file COPYING for license.
|
||||
|
||||
@@ -188,7 +188,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
|
||||
Java 1.8 or greater, just type:
|
||||
|
||||
$ java -jar symon-1.1.1.jar
|
||||
$ java -jar symon-1.2.0.jar
|
||||
|
||||
When Symon is running, you should be presented with a simple graphical
|
||||
interface.
|
||||
@@ -235,6 +235,12 @@ 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.
|
||||
|
||||
- **1.1.1:** 2 January, 2016 - Minor enhancement: Allows breakpoints
|
||||
to be added with the Enter key.
|
||||
|
||||
@@ -286,7 +292,15 @@ running.
|
||||
|
||||
- **0.1:** 20 January, 2010
|
||||
|
||||
## 6.0 To Do
|
||||
## 6.0 Roadmap
|
||||
|
||||
- **1.2:** Better breakpoint support. Symbolic debugging of breakpoints.
|
||||
|
||||
- **2.0:** Complete rewrite of the UI in JavaFX instead of Swing. Complete
|
||||
assembler and disassembler built in. Ability to attach source code for
|
||||
symbolic debugging.
|
||||
|
||||
## 7.0 To Do
|
||||
|
||||
- Feedback (in the form of dialogs, status bar, etc).
|
||||
|
||||
@@ -310,7 +324,7 @@ running.
|
||||
|
||||
- Symbolic debugging.
|
||||
|
||||
## 7.0 Copyright and Acknowledgements
|
||||
## 8.0 Copyright and Acknowledgements
|
||||
|
||||
**Copyright (c) 2014 Seth J. Morabito <web@loomcom.com>**
|
||||
|
||||
@@ -330,7 +344,7 @@ This project would not have been possible without the following resources:
|
||||
- [Neil Parker's "The 6502/65C02/65C816 Instruction Set Decoded"] (http://www.llx.com/~nparker/a2/opcodes.html),
|
||||
for information about how instructions are coded
|
||||
|
||||
## 8.0 Licensing
|
||||
## 9.0 Licensing
|
||||
|
||||
Symon is free software. It is distributed under the MIT License.
|
||||
Please see the file 'COPYING' for full details of the license.
|
||||
@@ -4,7 +4,7 @@
|
||||
<groupId>com.loomcom.symon</groupId>
|
||||
<artifactId>symon</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<version>1.1.1</version>
|
||||
<version>1.3.0-SNAPSHOT</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>
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ echo_irq: echo_irq.o
|
||||
$(LD) -C symon.config -vm -m echo_irq.map -o echo_irq.rom echo_irq.o
|
||||
|
||||
echo_irq.o:
|
||||
$(CA) --listing -o echo_irq.o echo_irq.asm
|
||||
$(CA) --listing echo_irq.lst -o echo_irq.o echo_irq.asm
|
||||
|
||||
clean:
|
||||
rm -f *.o *.rom *.map *.lst
|
||||
@@ -1,5 +1,5 @@
|
||||
MEMORY {
|
||||
RAM1: start = $0000, size = $8000;
|
||||
RAM1: start = $0000, size = $8000 - __STACKSIZE__;
|
||||
ROM1: start = $C000, size = $3FFA, fill = yes;
|
||||
ROMV: start = $FFFA, size = $6, file = %O, fill = yes;
|
||||
}
|
||||
@@ -11,6 +11,6 @@ VECTORS: load = ROMV, type = ro;
|
||||
}
|
||||
|
||||
SYMBOLS {
|
||||
__STACKSIZE__ = $0300;
|
||||
__STACKSIZE__: type = weak, value = $0300;
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ ehbasic: ehbasic.o
|
||||
$(LD) -C symon.config -vm -m ehbasic.map -o ehbasic.rom ehbasic.o
|
||||
|
||||
ehbasic.o:
|
||||
$(CA) --listing -o ehbasic.o min_mon.asm
|
||||
$(CA) --listing ehbasic.lst -o ehbasic.o min_mon.asm
|
||||
|
||||
clean:
|
||||
rm -f *.o *.rom *.map *.lst
|
||||
@@ -1,5 +1,5 @@
|
||||
MEMORY {
|
||||
RAM1: start = $0000, size = $8000;
|
||||
RAM1: start = $0000, size = $8000 - __STACKSIZE__;
|
||||
ROM1: start = $C000, size = $3F00, fill = yes;
|
||||
MONITOR: start = $FF00, size = $FA, fill = yes;
|
||||
ROMV: start = $FFFA, size = $6, file = %O, fill = yes;
|
||||
@@ -13,6 +13,6 @@ VECTORS: load = ROMV, type = ro;
|
||||
}
|
||||
|
||||
SYMBOLS {
|
||||
__STACKSIZE__ = $0300;
|
||||
__STACKSIZE__: type = weak, value = $0300;
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ ehbasic: ehbasic.o
|
||||
$(LD) -C symon.config -vm -m ehbasic.map -o ehbasic.rom ehbasic.o
|
||||
|
||||
ehbasic.o:
|
||||
$(CA) --listing -o ehbasic.o min_mon.asm
|
||||
$(CA) --listing ehbasic.lst -o ehbasic.o min_mon.asm
|
||||
|
||||
clean:
|
||||
rm -f *.o *.rom *.map *.lst
|
||||
@@ -1,5 +1,5 @@
|
||||
MEMORY {
|
||||
RAM1: start = $0000, size = $8000;
|
||||
RAM1: start = $0000, size = $8000 - __STACKSIZE__;
|
||||
ROM1: start = $C000, size = $3C00, fill = yes;
|
||||
MONITOR: start = $FC00, size = $3FA, fill = yes;
|
||||
ROMV: start = $FFFA, size = $6, file = %O, fill = yes;
|
||||
@@ -13,6 +13,6 @@ VECTORS: load = ROMV, type = ro;
|
||||
}
|
||||
|
||||
SYMBOLS {
|
||||
__STACKSIZE__ = $0300;
|
||||
__STACKSIZE__: type = weak, value = $0300;
|
||||
}
|
||||
|
||||
|
Before Width: | Height: | Size: 50 KiB After Width: | Height: | Size: 27 KiB |
|
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 48 KiB |
|
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 38 KiB |
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 35 KiB |
@@ -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();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||