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
|
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.
|
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
|
Symon is meant to be invoked directly from the jar file. To run with
|
||||||
Java 1.8 or greater, just type:
|
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
|
When Symon is running, you should be presented with a simple graphical
|
||||||
interface.
|
interface.
|
||||||
@@ -235,6 +235,12 @@ running.
|
|||||||
|
|
||||||
## 5.0 Revision History
|
## 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
|
- **1.1.1:** 2 January, 2016 - Minor enhancement: Allows breakpoints
|
||||||
to be added with the Enter key.
|
to be added with the Enter key.
|
||||||
|
|
||||||
@@ -286,7 +292,15 @@ running.
|
|||||||
|
|
||||||
- **0.1:** 20 January, 2010
|
- **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).
|
- Feedback (in the form of dialogs, status bar, etc).
|
||||||
|
|
||||||
@@ -310,7 +324,7 @@ running.
|
|||||||
|
|
||||||
- Symbolic debugging.
|
- Symbolic debugging.
|
||||||
|
|
||||||
## 7.0 Copyright and Acknowledgements
|
## 8.0 Copyright and Acknowledgements
|
||||||
|
|
||||||
**Copyright (c) 2014 Seth J. Morabito <web@loomcom.com>**
|
**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),
|
- [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
|
for information about how instructions are coded
|
||||||
|
|
||||||
## 8.0 Licensing
|
## 9.0 Licensing
|
||||||
|
|
||||||
Symon is free software. It is distributed under the MIT License.
|
Symon is free software. It is distributed under the MIT License.
|
||||||
Please see the file 'COPYING' for full details of the license.
|
Please see the file 'COPYING' for full details of the license.
|
||||||
@@ -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>1.1.1</version>
|
<version>1.3.0-SNAPSHOT</version>
|
||||||
<name>symon</name>
|
<name>symon</name>
|
||||||
<url>http://www.loomcom.com/symon</url>
|
<url>http://www.loomcom.com/symon</url>
|
||||||
<properties>
|
<properties>
|
||||||
@@ -91,8 +91,8 @@
|
|||||||
<version>3.1</version>
|
<version>3.1</version>
|
||||||
<configuration>
|
<configuration>
|
||||||
<compilerArgument>-Xlint:unchecked</compilerArgument>
|
<compilerArgument>-Xlint:unchecked</compilerArgument>
|
||||||
<source>1.8</source>
|
<source>1.7</source>
|
||||||
<target>1.8</target>
|
<target>1.7</target>
|
||||||
</configuration>
|
</configuration>
|
||||||
</plugin>
|
</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
|
$(LD) -C symon.config -vm -m echo_irq.map -o echo_irq.rom echo_irq.o
|
||||||
|
|
||||||
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:
|
clean:
|
||||||
rm -f *.o *.rom *.map *.lst
|
rm -f *.o *.rom *.map *.lst
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
MEMORY {
|
MEMORY {
|
||||||
RAM1: start = $0000, size = $8000;
|
RAM1: start = $0000, size = $8000 - __STACKSIZE__;
|
||||||
ROM1: start = $C000, size = $3FFA, fill = yes;
|
ROM1: start = $C000, size = $3FFA, fill = yes;
|
||||||
ROMV: start = $FFFA, size = $6, file = %O, fill = yes;
|
ROMV: start = $FFFA, size = $6, file = %O, fill = yes;
|
||||||
}
|
}
|
||||||
@@ -11,6 +11,6 @@ VECTORS: load = ROMV, type = ro;
|
|||||||
}
|
}
|
||||||
|
|
||||||
SYMBOLS {
|
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
|
$(LD) -C symon.config -vm -m ehbasic.map -o ehbasic.rom ehbasic.o
|
||||||
|
|
||||||
ehbasic.o:
|
ehbasic.o:
|
||||||
$(CA) --listing -o ehbasic.o min_mon.asm
|
$(CA) --listing ehbasic.lst -o ehbasic.o min_mon.asm
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f *.o *.rom *.map *.lst
|
rm -f *.o *.rom *.map *.lst
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
MEMORY {
|
MEMORY {
|
||||||
RAM1: start = $0000, size = $8000;
|
RAM1: start = $0000, size = $8000 - __STACKSIZE__;
|
||||||
ROM1: start = $C000, size = $3F00, fill = yes;
|
ROM1: start = $C000, size = $3F00, fill = yes;
|
||||||
MONITOR: start = $FF00, size = $FA, fill = yes;
|
MONITOR: start = $FF00, size = $FA, fill = yes;
|
||||||
ROMV: start = $FFFA, size = $6, file = %O, fill = yes;
|
ROMV: start = $FFFA, size = $6, file = %O, fill = yes;
|
||||||
@@ -13,6 +13,6 @@ VECTORS: load = ROMV, type = ro;
|
|||||||
}
|
}
|
||||||
|
|
||||||
SYMBOLS {
|
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
|
$(LD) -C symon.config -vm -m ehbasic.map -o ehbasic.rom ehbasic.o
|
||||||
|
|
||||||
ehbasic.o:
|
ehbasic.o:
|
||||||
$(CA) --listing -o ehbasic.o min_mon.asm
|
$(CA) --listing ehbasic.lst -o ehbasic.o min_mon.asm
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f *.o *.rom *.map *.lst
|
rm -f *.o *.rom *.map *.lst
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
MEMORY {
|
MEMORY {
|
||||||
RAM1: start = $0000, size = $8000;
|
RAM1: start = $0000, size = $8000 - __STACKSIZE__;
|
||||||
ROM1: start = $C000, size = $3C00, fill = yes;
|
ROM1: start = $C000, size = $3C00, fill = yes;
|
||||||
MONITOR: start = $FC00, size = $3FA, fill = yes;
|
MONITOR: start = $FC00, size = $3FA, fill = yes;
|
||||||
ROMV: start = $FFFA, size = $6, file = %O, fill = yes;
|
ROMV: start = $FFFA, size = $6, file = %O, fill = yes;
|
||||||
@@ -13,6 +13,6 @@ VECTORS: load = ROMV, type = ro;
|
|||||||
}
|
}
|
||||||
|
|
||||||
SYMBOLS {
|
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.SortedSet;
|
||||||
import java.util.TreeSet;
|
import java.util.TreeSet;
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Bus ties the whole thing together, man.
|
* The Bus ties the whole thing together, man.
|
||||||
@@ -222,9 +221,11 @@ public class Bus {
|
|||||||
List<Integer> priorities = new ArrayList<>(deviceMap.keySet());
|
List<Integer> priorities = new ArrayList<>(deviceMap.keySet());
|
||||||
Collections.sort(priorities);
|
Collections.sort(priorities);
|
||||||
|
|
||||||
for(int priority : priorities) {
|
for (int priority : priorities) {
|
||||||
SortedSet<Device> deviceSet = deviceMap.get(priority);
|
SortedSet<Device> deviceSet = deviceMap.get(priority);
|
||||||
devices.addAll(deviceSet.stream().collect(Collectors.toList()));
|
for (Device device : deviceSet) {
|
||||||
|
devices.add(device);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return devices;
|
return devices;
|
||||||
|
|||||||
@@ -86,13 +86,16 @@ public class Main {
|
|||||||
|
|
||||||
final Simulator simulator = new Simulator(machineClass);
|
final Simulator simulator = new Simulator(machineClass);
|
||||||
|
|
||||||
SwingUtilities.invokeLater(() -> {
|
SwingUtilities.invokeLater(new Runnable() {
|
||||||
try {
|
@Override
|
||||||
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
|
public void run() {
|
||||||
// Create the main UI window
|
try {
|
||||||
simulator.createAndShowUi();
|
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
|
||||||
} catch (Exception e) {
|
// Create the main UI window
|
||||||
e.printStackTrace();
|
simulator.createAndShowUi();
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -185,13 +185,16 @@ public class Simulator {
|
|||||||
JButton hardResetButton = new JButton("Hard Reset");
|
JButton hardResetButton = new JButton("Hard Reset");
|
||||||
|
|
||||||
stepCountBox = new JComboBox<>(STEPS);
|
stepCountBox = new JComboBox<>(STEPS);
|
||||||
stepCountBox.addActionListener(actionEvent -> {
|
stepCountBox.addActionListener(new ActionListener() {
|
||||||
try {
|
@Override
|
||||||
JComboBox cb = (JComboBox) actionEvent.getSource();
|
public void actionPerformed(ActionEvent actionEvent) {
|
||||||
stepsPerClick = Integer.parseInt((String) cb.getSelectedItem());
|
try {
|
||||||
} catch (NumberFormatException ex) {
|
JComboBox cb = (JComboBox) actionEvent.getSource();
|
||||||
stepsPerClick = 1;
|
stepsPerClick = Integer.parseInt((String) cb.getSelectedItem());
|
||||||
stepCountBox.setSelectedIndex(0);
|
} catch (NumberFormatException ex) {
|
||||||
|
stepsPerClick = 1;
|
||||||
|
stepCountBox.setSelectedIndex(0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -211,24 +214,38 @@ public class Simulator {
|
|||||||
// Bottom - buttons.
|
// Bottom - buttons.
|
||||||
mainWindow.getContentPane().add(buttonContainer, BorderLayout.PAGE_END);
|
mainWindow.getContentPane().add(buttonContainer, BorderLayout.PAGE_END);
|
||||||
|
|
||||||
runStopButton.addActionListener(actionEvent -> {
|
runStopButton.addActionListener(new ActionListener() {
|
||||||
if (runLoop != null && runLoop.isRunning()) {
|
@Override
|
||||||
handleStop();
|
public void actionPerformed(ActionEvent actionEvent) {
|
||||||
} else {
|
if (runLoop != null && runLoop.isRunning()) {
|
||||||
handleStart();
|
Simulator.this.handleStop();
|
||||||
|
} else {
|
||||||
|
Simulator.this.handleStart();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
stepButton.addActionListener(actionEvent -> handleStep(stepsPerClick));
|
stepButton.addActionListener(new ActionListener() {
|
||||||
|
@Override
|
||||||
softResetButton.addActionListener(actionEvent -> {
|
public void actionPerformed(ActionEvent actionEvent) {
|
||||||
// If this was a CTRL-click, do a hard reset.
|
Simulator.this.handleStep(stepsPerClick);
|
||||||
handleReset(false);
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
hardResetButton.addActionListener(actionEvent -> {
|
softResetButton.addActionListener(new ActionListener() {
|
||||||
// If this was a CTRL-click, do a hard reset.
|
@Override
|
||||||
handleReset(true);
|
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);
|
mainWindow.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
|
||||||
@@ -400,13 +417,16 @@ public class Simulator {
|
|||||||
logger.debug("Starting main run loop.");
|
logger.debug("Starting main run loop.");
|
||||||
isRunning = true;
|
isRunning = true;
|
||||||
|
|
||||||
SwingUtilities.invokeLater(() -> {
|
SwingUtilities.invokeLater(new Runnable() {
|
||||||
// Don't allow step while the simulator is running
|
@Override
|
||||||
stepButton.setEnabled(false);
|
public void run() {
|
||||||
stepCountBox.setEnabled(false);
|
// Don't allow step while the simulator is running
|
||||||
menuBar.simulatorDidStart();
|
stepButton.setEnabled(false);
|
||||||
// Toggle the state of the run button
|
stepCountBox.setEnabled(false);
|
||||||
runStopButton.setText("Stop");
|
menuBar.simulatorDidStart();
|
||||||
|
// Toggle the state of the run button
|
||||||
|
runStopButton.setText("Stop");
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -417,17 +437,20 @@ public class Simulator {
|
|||||||
logger.error("Exception in main simulator run thread. Exiting run.", ex);
|
logger.error("Exception in main simulator run thread. Exiting run.", ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
SwingUtilities.invokeLater(() -> {
|
SwingUtilities.invokeLater(new Runnable() {
|
||||||
statusPane.updateState();
|
@Override
|
||||||
memoryWindow.updateState();
|
public void run() {
|
||||||
runStopButton.setText("Run");
|
statusPane.updateState();
|
||||||
stepButton.setEnabled(true);
|
memoryWindow.updateState();
|
||||||
stepCountBox.setEnabled(true);
|
runStopButton.setText("Run");
|
||||||
if (traceLog.isVisible()) {
|
stepButton.setEnabled(true);
|
||||||
traceLog.refresh();
|
stepCountBox.setEnabled(true);
|
||||||
|
if (traceLog.isVisible()) {
|
||||||
|
traceLog.refresh();
|
||||||
|
}
|
||||||
|
menuBar.simulatorDidStop();
|
||||||
|
traceLog.simulatorDidStop();
|
||||||
}
|
}
|
||||||
menuBar.simulatorDidStop();
|
|
||||||
traceLog.simulatorDidStop();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
isRunning = false;
|
isRunning = false;
|
||||||
@@ -480,9 +503,12 @@ public class Simulator {
|
|||||||
// Now load the program at the starting address.
|
// Now load the program at the starting address.
|
||||||
loadProgram(program, preferences.getProgramStartAddress());
|
loadProgram(program, preferences.getProgramStartAddress());
|
||||||
|
|
||||||
SwingUtilities.invokeLater(() -> {
|
SwingUtilities.invokeLater(new Runnable() {
|
||||||
console.reset();
|
@Override
|
||||||
breakpoints.refresh();
|
public void run() {
|
||||||
|
console.reset();
|
||||||
|
breakpoints.refresh();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// TODO: "Don't Show Again" checkbox
|
// TODO: "Don't Show Again" checkbox
|
||||||
@@ -623,9 +649,12 @@ public class Simulator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void actionPerformed(ActionEvent actionEvent) {
|
public void actionPerformed(ActionEvent actionEvent) {
|
||||||
SwingUtilities.invokeLater(() -> {
|
SwingUtilities.invokeLater(new Runnable() {
|
||||||
console.setFont(new Font("Monospaced", Font.PLAIN, size));
|
@Override
|
||||||
mainWindow.pack();
|
public void run() {
|
||||||
|
console.setFont(new Font("Monospaced", Font.PLAIN, size));
|
||||||
|
mainWindow.pack();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -889,12 +918,15 @@ public class Simulator {
|
|||||||
|
|
||||||
private void updateVisibleState() {
|
private void updateVisibleState() {
|
||||||
// Immediately update the UI.
|
// Immediately update the UI.
|
||||||
SwingUtilities.invokeLater(() -> {
|
SwingUtilities.invokeLater(new Runnable() {
|
||||||
// Now update the state
|
@Override
|
||||||
statusPane.updateState();
|
public void run() {
|
||||||
memoryWindow.updateState();
|
// Now update the state
|
||||||
if (traceLog.shouldUpdate()) {
|
statusPane.updateState();
|
||||||
traceLog.refresh();
|
memoryWindow.updateState();
|
||||||
|
if (traceLog.shouldUpdate()) {
|
||||||
|
traceLog.refresh();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -115,7 +115,9 @@ public abstract class Device implements Comparable<Device> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void notifyListeners() {
|
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.MemoryAccessException;
|
||||||
import com.loomcom.symon.exceptions.MemoryRangeException;
|
import com.loomcom.symon.exceptions.MemoryRangeException;
|
||||||
import jdk.nashorn.internal.ir.annotations.Ignore;
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
|
|||||||
@@ -30,7 +30,10 @@ import org.slf4j.LoggerFactory;
|
|||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
import javax.swing.border.EmptyBorder;
|
import javax.swing.border.EmptyBorder;
|
||||||
|
import javax.swing.event.ListSelectionEvent;
|
||||||
|
import javax.swing.event.ListSelectionListener;
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
|
import java.awt.event.ActionEvent;
|
||||||
import java.awt.event.ActionListener;
|
import java.awt.event.ActionListener;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -62,21 +65,24 @@ public class BreakpointsWindow extends JFrame {
|
|||||||
breakpointsPanel.setLayout(new BorderLayout());
|
breakpointsPanel.setLayout(new BorderLayout());
|
||||||
breakpointsPanel.setBorder(new EmptyBorder(10, 10, 10, 10));
|
breakpointsPanel.setBorder(new EmptyBorder(10, 10, 10, 10));
|
||||||
|
|
||||||
JButton addButton = new JButton("Add");
|
final JButton addButton = new JButton("Add");
|
||||||
JButton removeButton = new JButton("Del");
|
final JButton removeButton = new JButton("Del");
|
||||||
removeButton.setEnabled(false);
|
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.setShowGrid(true);
|
||||||
breakpointsTable.setGridColor(Color.LIGHT_GRAY);
|
breakpointsTable.setGridColor(Color.LIGHT_GRAY);
|
||||||
breakpointsTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
|
breakpointsTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
|
||||||
breakpointsTable.getSelectionModel().addListSelectionListener(e -> {
|
breakpointsTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
|
||||||
if (e.getFirstIndex() > -1) {
|
@Override
|
||||||
removeButton.setEnabled(true);
|
public void valueChanged(ListSelectionEvent e) {
|
||||||
} else {
|
if (e.getFirstIndex() > -1) {
|
||||||
removeButton.setEnabled(false);
|
removeButton.setEnabled(true);
|
||||||
|
} else {
|
||||||
|
removeButton.setEnabled(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -86,37 +92,45 @@ public class BreakpointsWindow extends JFrame {
|
|||||||
|
|
||||||
breakpointsPanel.add(scrollPane, BorderLayout.CENTER);
|
breakpointsPanel.add(scrollPane, BorderLayout.CENTER);
|
||||||
|
|
||||||
ActionListener addBreakpointListener = e -> {
|
ActionListener addBreakpointListener = new ActionListener() {
|
||||||
int value = -1;
|
@Override
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
int value;
|
||||||
|
|
||||||
String newBreakpoint = addTextField.getText();
|
String newBreakpoint = addTextField.getText();
|
||||||
|
|
||||||
if (newBreakpoint == null || newBreakpoint.isEmpty()) {
|
if (newBreakpoint == null || newBreakpoint.isEmpty()) {
|
||||||
return;
|
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);
|
addButton.addActionListener(addBreakpointListener);
|
||||||
addTextField.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(addTextField);
|
||||||
controlPanel.add(addButton);
|
controlPanel.add(addButton);
|
||||||
|
|||||||
@@ -97,19 +97,25 @@ public class PreferencesDialog extends Observable implements Preferences {
|
|||||||
JButton applyButton = new JButton("Apply");
|
JButton applyButton = new JButton("Apply");
|
||||||
JButton cancelButton = new JButton("Cancel");
|
JButton cancelButton = new JButton("Cancel");
|
||||||
|
|
||||||
cancelButton.addActionListener(actionEvent -> {
|
cancelButton.addActionListener(new ActionListener() {
|
||||||
updateUi();
|
@Override
|
||||||
dialog.setVisible(false);
|
public void actionPerformed(ActionEvent actionEvent) {
|
||||||
|
PreferencesDialog.this.updateUi();
|
||||||
|
dialog.setVisible(false);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
applyButton.addActionListener(actionEvent -> {
|
applyButton.addActionListener(new ActionListener() {
|
||||||
haltOnBreak = haltOnBreakCheckBox.isSelected();
|
@Override
|
||||||
programLoadAddress = hexToInt(programLoadAddressField.getText());
|
public void actionPerformed(ActionEvent actionEvent) {
|
||||||
updateUi();
|
haltOnBreak = haltOnBreakCheckBox.isSelected();
|
||||||
// TODO: Actually check to see if values have changed, don't assume.
|
programLoadAddress = PreferencesDialog.this.hexToInt(programLoadAddressField.getText());
|
||||||
setChanged();
|
PreferencesDialog.this.updateUi();
|
||||||
PreferencesDialog.this.notifyObservers();
|
// TODO: Actually check to see if values have changed, don't assume.
|
||||||
dialog.setVisible(false);
|
PreferencesDialog.this.setChanged();
|
||||||
|
PreferencesDialog.this.notifyObservers();
|
||||||
|
dialog.setVisible(false);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
buttonsContainer.add(applyButton);
|
buttonsContainer.add(applyButton);
|
||||||
|
|||||||
@@ -31,6 +31,8 @@ import javax.swing.*;
|
|||||||
import javax.swing.border.Border;
|
import javax.swing.border.Border;
|
||||||
import javax.swing.border.EtchedBorder;
|
import javax.swing.border.EtchedBorder;
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
|
import java.awt.event.ActionEvent;
|
||||||
|
import java.awt.event.ActionListener;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* UI component that displays the current state of the simulated CPU.
|
* 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);
|
yField = makeTextField(SMALL_TEXT_FIELD_SIZE, true);
|
||||||
|
|
||||||
// Make fields editable
|
// Make fields editable
|
||||||
pcField.addActionListener(e -> {
|
pcField.addActionListener(new ActionListener() {
|
||||||
try {
|
@Override
|
||||||
int newVal = getHexVal(pcField) & 0xffff;
|
public void actionPerformed(ActionEvent e) {
|
||||||
machine.getCpu().setProgramCounter(newVal);
|
try {
|
||||||
} catch (Exception ex) {
|
int newVal = StatusPanel.this.getHexVal(pcField) & 0xffff;
|
||||||
// Swallow exception
|
machine.getCpu().setProgramCounter(newVal);
|
||||||
}
|
} catch (Exception ex) {
|
||||||
|
// Swallow exception
|
||||||
|
}
|
||||||
|
|
||||||
updateState();
|
StatusPanel.this.updateState();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
spField.addActionListener(e -> {
|
spField.addActionListener(new ActionListener() {
|
||||||
try {
|
@Override
|
||||||
int newVal = getHexVal(spField) & 0xff;
|
public void actionPerformed(ActionEvent e) {
|
||||||
machine.getCpu().setStackPointer(newVal);
|
try {
|
||||||
} catch (Exception ex) {
|
int newVal = StatusPanel.this.getHexVal(spField) & 0xff;
|
||||||
// Swallow exception
|
machine.getCpu().setStackPointer(newVal);
|
||||||
}
|
} catch (Exception ex) {
|
||||||
|
// Swallow exception
|
||||||
|
}
|
||||||
|
|
||||||
updateState();
|
StatusPanel.this.updateState();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
aField.addActionListener(e -> {
|
aField.addActionListener(new ActionListener() {
|
||||||
try {
|
@Override
|
||||||
int newVal = getHexVal(aField) & 0xff;
|
public void actionPerformed(ActionEvent e) {
|
||||||
machine.getCpu().setAccumulator(newVal);
|
try {
|
||||||
} catch (Exception ex) {
|
int newVal = StatusPanel.this.getHexVal(aField) & 0xff;
|
||||||
// Swallow exception
|
machine.getCpu().setAccumulator(newVal);
|
||||||
}
|
} catch (Exception ex) {
|
||||||
|
// Swallow exception
|
||||||
|
}
|
||||||
|
|
||||||
updateState();
|
StatusPanel.this.updateState();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
xField.addActionListener(e -> {
|
xField.addActionListener(new ActionListener() {
|
||||||
try {
|
@Override
|
||||||
int newVal = getHexVal(xField) & 0xff;
|
public void actionPerformed(ActionEvent e) {
|
||||||
machine.getCpu().setXRegister(newVal);
|
try {
|
||||||
} catch (Exception ex) {
|
int newVal = StatusPanel.this.getHexVal(xField) & 0xff;
|
||||||
// Swallow exception
|
machine.getCpu().setXRegister(newVal);
|
||||||
}
|
} catch (Exception ex) {
|
||||||
|
// Swallow exception
|
||||||
|
}
|
||||||
|
|
||||||
updateState();
|
StatusPanel.this.updateState();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
yField.addActionListener(e -> {
|
yField.addActionListener(new ActionListener() {
|
||||||
try {
|
@Override
|
||||||
int newVal = getHexVal(yField) & 0xff;
|
public void actionPerformed(ActionEvent e) {
|
||||||
machine.getCpu().setYRegister(newVal);
|
try {
|
||||||
} catch (Exception ex) {
|
int newVal = StatusPanel.this.getHexVal(yField) & 0xff;
|
||||||
// Swallow exception
|
machine.getCpu().setYRegister(newVal);
|
||||||
}
|
} catch (Exception ex) {
|
||||||
|
// Swallow exception
|
||||||
|
}
|
||||||
|
|
||||||
updateState();
|
StatusPanel.this.updateState();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
constraints.anchor = GridBagConstraints.LINE_START;
|
constraints.anchor = GridBagConstraints.LINE_START;
|
||||||
|
|||||||
@@ -122,10 +122,13 @@ public class VideoWindow extends JFrame implements DeviceChangeListener {
|
|||||||
*/
|
*/
|
||||||
private class CursorBlinker implements Runnable {
|
private class CursorBlinker implements Runnable {
|
||||||
public void run() {
|
public void run() {
|
||||||
SwingUtilities.invokeLater(() -> {
|
SwingUtilities.invokeLater(new Runnable() {
|
||||||
if (cursorBlinkRate > 0) {
|
@Override
|
||||||
hideCursor = !hideCursor;
|
public void run() {
|
||||||
repaint();
|
if (cursorBlinkRate > 0) {
|
||||||
|
hideCursor = !hideCursor;
|
||||||
|
VideoWindow.this.repaint();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||