Compare commits

...
13 Commits
Author SHA1 Message Date
Seth Morabito 5f8f743f7d Update for 1.3.2 2022-03-08 14:36:59 -08:00
Seth Morabito 4ce8bc86de Update pom.xml
- Switched from maven-assembly-plugin to maven-shade-plugin
  for final packaging
- Updated maven-jar-plugin to 3.2.0
2021-09-25 10:46:36 -07:00
Seth Morabito 4644fe9b55 Update junit and mockito
- JUnit has been bumped to 4.13.2.
- Mockito has gone from 1.10.19 to 3.12.4, and now compiles correctly
  on OpenJDK 16 using Maven 3.8.
2021-09-24 09:39:00 -07:00
Seth Morabito 655bbb3ab0 Merge pull request #26 from sethm/dependabot/maven/junit-junit-4.13.1
Bump junit from 4.12 to 4.13.1
2020-10-13 14:45:47 -07:00
dependabot[bot] e2d31fd39c Bump junit from 4.12 to 4.13.1
Bumps [junit](https://github.com/junit-team/junit4) from 4.12 to 4.13.1.
- [Release notes](https://github.com/junit-team/junit4/releases)
- [Changelog](https://github.com/junit-team/junit4/blob/main/doc/ReleaseNotes4.12.md)
- [Commits](https://github.com/junit-team/junit4/compare/r4.12...r4.13.1)

Signed-off-by: dependabot[bot] <support@github.com>
2020-10-13 09:09:28 +00:00
Seth Morabito 087ba28b82 Force metal look-and-feel
* On Linux GTK+, the small text fields in the Status Panel displayed a
  large inner margin, cutting off text. This change forces Java to use the
  Metal look-and-feel for these fields, which forces no default inner
  margin.
2020-09-01 10:48:17 -07:00
Seth Morabito 8edca5d595 Update link in README 2020-05-21 15:01:34 -07:00
Seth Morabito 105a09067f Fix README for 1.3.1 2019-10-12 14:58:16 -07:00
Seth Morabito 08efd81be3 Merge branch 'master' into 1.3.branch 2019-10-12 14:55:43 -07:00
Seth Morabito 0aeb97bb56 Add new options -cpu and -rom 2019-10-12 14:54:05 -07:00
Seth Morabito d466a21b3e Fix README screenshots (again) 2018-07-09 14:00:32 -07:00
Seth Morabito 31d1f7c5e1 Update screenshots 2018-03-01 19:21:56 -08:00
Seth Morabito 247f2ba2fc Update screenshots 2018-03-01 19:21:21 -08:00
9 changed files with 194 additions and 96 deletions

No files matched your search

+1
View File
@@ -4,3 +4,4 @@ target
.DS_Store
.idea
symon.iml
/dependency-reduced-pom.xml
+28 -12
View File
@@ -1,13 +1,13 @@
SYMON - A 6502 System Simulator
===============================
**Version:** 1.3.0
**Version:** 1.3.2
**Last Updated:** 25 February, 2018
**Last Updated:** 08 March, 2021
See the file COPYING for license.
![Symon Simulator in Action](http://www.loomcom.com/symon/screenshots/full.jpg)
![Symon Simulator in Action](https://github.com/sethm/symon/raw/master/screenshots/full.jpg)
## 1.0 About
@@ -66,7 +66,7 @@ memory.
### 3.2 Serial Console and CPU Status
![Serial Console](http://www.loomcom.com/symon/screenshots/console.png)
![Serial Console](https://github.com/sethm/symon/raw/master/screenshots/console.png)
The main window of the simulator acts as the primary Input/Output
system through a virtual serial terminal. The terminal is attached to
@@ -78,13 +78,13 @@ It also provides CPU status. Contents of the accumulator, index
registers, processor status flags, disassembly of the instruction
register, and stack pointer are all displayed.
![Font Selection](http://www.loomcom.com/symon/screenshots/font_selection.png)
![Font Selection](https://github.com/sethm/symon/raw/master/screenshots/font_selection.png)
The console supports font sizes from 10 to 20 points.
### 3.3 ROM Loading
![ROM Loading](http://www.loomcom.com/symon/screenshots/load_rom.png)
![ROM Loading](https://github.com/sethm/symon/raw/master/screenshots/load_rom.png)
Symon can load any appropriately sized ROM image. The Symon
architecture expects as 16KB (16384 byte) ROM image, while the
@@ -95,32 +95,32 @@ address.
### 3.4 Memory Window
![Memory Window](http://www.loomcom.com/symon/screenshots/memory_window.png)
![Memory Window](https://github.com/sethm/symon/raw/master/screenshots/memory_window.png)
Memory contents can be viewed (and edited) one page at a time through the Memory Window.
### 3.5 Trace Log
![Trace Log](http://www.loomcom.com/symon/screenshots/trace_log.png)
![Trace Log](https://github.com/sethm/symon/raw/master/screenshots/trace_log.png)
The last 20,000 execution steps are disassembled and logged to the Trace Log
Window.
### 3.6 Simulator Speeds
![Speeds](http://www.loomcom.com/symon/screenshots/simulator_menu.png)
![Speeds](https://github.com/sethm/symon/raw/master/screenshots/simulator_menu.png)
Simulated speeds may be set from 1MHz to 8MHz.
### 3.7 Breakpoints
![Breakpoints](http://www.loomcom.com/symon/screenshots/breakpoints.png)
![Breakpoints](https://github.com/sethm/symon/raw/master/screenshots/breakpoints.png)
Breakpoints can be set and removed through the Breakpoints window.
### 3.8 Experimental 6545 CRTC Video
![Composite Video](http://www.loomcom.com/symon/screenshots/video_window.png)
![Composite Video](https://github.com/sethm/symon/raw/master/screenshots/video_window.png)
This feature is highly experimental. It's possible to open a video window
from the "View" menu. This window simulates the output of a MOS 6545 CRT
@@ -193,6 +193,18 @@ Java 1.8 or greater, just type:
When Symon is running, you should be presented with a simple graphical
interface.
#### 4.1.1 Command Line Options
Two command line options may be passed to the JAR file on startup,
to specify machine type and CPU type. The options are:
- `-cpu 6502`: Use the NMOS 6502 CPU type by default.
- `-cpu 65c02`: Use the CMOS 65C02 CPU type by default.
- `-machine symon`: Use the **Symon** machine type by default.
- `-machine multicomp`: Use the **Multicomp** machine type by default.
- `-machine simple`: Use the **Simple** machine type by default.
- `-rom <file>`: Use the specified file as the ROM image.
### 4.2 ROM images
The simulator requires a ROM image loaded into memory to work
@@ -235,6 +247,10 @@ running.
## 5.0 Revision History
- **1.3.1:** 12 October, 2019 - Add support for new command line
option `-cpu <type>` to specify one of `6502` or `65c02` on startup,
and new option `-rom <file>` to specify a ROM file to load.
- **1.3.0:** 24 February, 2018 - Adds support for 65C02 opcodes.
- **1.2.1:** 8 January, 2016 - Remove dependency on Java 8. Now
@@ -340,7 +356,7 @@ Additional components used in this project are copyright their respective owners
This project would not have been possible without the following resources:
- [Andrew Jacobs' 6502 Pages](http://www.obelisk.demon.co.uk/6502/), for
- [Andrew Jacobs' 6502 Pages](http://obelisk.me.uk/6502/), for
wonderfully detailed information about the 6502
- [Neil Parker's "The 6502/65C02/65C816 Instruction Set Decoded"](http://www.llx.com/~nparker/a2/opcodes.html),
+28 -16
View File
@@ -4,7 +4,7 @@
<groupId>com.loomcom.symon</groupId>
<artifactId>symon</artifactId>
<packaging>jar</packaging>
<version>1.3.0</version>
<version>1.3.2</version>
<name>symon</name>
<url>http://www.loomcom.com/symon</url>
<properties>
@@ -24,39 +24,51 @@
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<version>1.10.19</version>
<artifactId>mockito-core</artifactId>
<version>3.12.4</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>commons-cli</groupId>
<artifactId>commons-cli</artifactId>
<version>1.4</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.6</version>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.0</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<appendAssemblyId>false</appendAssemblyId>
<archive>
<manifest>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>com.loomcom.symon.Main</mainClass>
</manifest>
</archive>
</transformer>
</transformers>
<filters>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/*.SF</exclude>
<exclude>META-INF/*.DSA</exclude>
<exclude>META-INF/*.RSA</exclude>
</excludes>
</filter>
</filters>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
<goal>shade</goal>
</goals>
</execution>
</executions>
@@ -76,7 +88,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.6</version>
<version>3.2.0</version>
<configuration>
<archive>
<manifest>
+93 -47
View File
@@ -28,6 +28,8 @@ package com.loomcom.symon;
import com.loomcom.symon.machines.MulticompMachine;
import com.loomcom.symon.machines.SimpleMachine;
import com.loomcom.symon.machines.SymonMachine;
import org.apache.commons.cli.*;
import java.util.Locale;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;
@@ -41,71 +43,115 @@ public class Main {
*
* @param args Program arguments
*/
public static void main(String args[]) throws Exception {
public static void main(String[] args) throws Exception {
Class machineClass = SymonMachine.class;
for(int i = 0; i < args.length; ++i) {
String arg = args[i].toLowerCase(Locale.ENGLISH);
if(arg.equals("-machine") && (i+1) < args.length) {
String machine = args[i+1].trim().toLowerCase(Locale.ENGLISH);
Options options = new Options();
options.addOption(new Option("m", "machine", true, "Specify machine type."));
options.addOption(new Option("c", "cpu", true, "Specify CPU type."));
options.addOption(new Option("r", "rom", true, "Specify ROM file."));
CommandLineParser parser = new DefaultParser();
try {
CommandLine line = parser.parse(options, args);
InstructionTable.CpuBehavior cpuBehavior = null;
String romFile = null;
if (line.hasOption("machine")) {
String machine = line.getOptionValue("machine").toLowerCase(Locale.ENGLISH);
switch (machine) {
case "symon":
machineClass = SymonMachine.class;
break;
case "multicomp":
machineClass = MulticompMachine.class;
break;
case "simple":
machineClass = SimpleMachine.class;
break;
}
}
}
while (true) {
if (machineClass == null) {
Object[] possibilities = {"Symon", "Multicomp", "Simple"};
String s = (String)JOptionPane.showInputDialog(
null,
"Please choose the machine type to be emulated:",
"Machine selection",
JOptionPane.PLAIN_MESSAGE,
null,
possibilities,
"Symon");
if (s != null && s.equals("Multicomp")) {
machineClass = MulticompMachine.class;
} else if (s != null && s.equals("Simple")) {
machineClass = SimpleMachine.class;
} else {
machineClass = SymonMachine.class;
case "symon":
machineClass = SymonMachine.class;
break;
default:
System.err.println("Could not start Symon. Unknown machine type " + machine);
return;
}
}
final Simulator simulator = new Simulator(machineClass);
if (line.hasOption("cpu")) {
String cpu = line.getOptionValue("cpu").toLowerCase(Locale.ENGLISH);
switch (cpu) {
case "6502":
cpuBehavior = InstructionTable.CpuBehavior.NMOS_6502;
break;
case "65c02":
cpuBehavior = InstructionTable.CpuBehavior.CMOS_6502;
break;
case "65c816":
cpuBehavior = InstructionTable.CpuBehavior.CMOS_65816;
break;
default:
System.err.println("Could not start Symon. Unknown cpu type " + cpu);
return;
}
}
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();
if (line.hasOption("rom")) {
romFile = line.getOptionValue("rom");
}
while (true) {
if (machineClass == null) {
Object[] possibilities = {"Symon", "Multicomp", "Simple"};
String s = (String)JOptionPane.showInputDialog(
null,
"Please choose the machine type to be emulated:",
"Machine selection",
JOptionPane.PLAIN_MESSAGE,
null,
possibilities,
"Symon");
if (s != null && s.equals("Multicomp")) {
machineClass = MulticompMachine.class;
} else if (s != null && s.equals("Simple")) {
machineClass = SimpleMachine.class;
} else {
machineClass = SymonMachine.class;
}
}
});
if (cpuBehavior == null) {
cpuBehavior = InstructionTable.CpuBehavior.NMOS_6502;
}
final Simulator simulator = new Simulator(machineClass, cpuBehavior, romFile);
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();
}
}
});
Simulator.MainCommand cmd = simulator.waitForCommand();
if (cmd.equals(Simulator.MainCommand.SELECTMACHINE)) {
machineClass = null;
} else {
break;
Simulator.MainCommand cmd = simulator.waitForCommand();
if (cmd.equals(Simulator.MainCommand.SELECTMACHINE)) {
machineClass = null;
} else {
break;
}
}
} catch (ParseException ex) {
System.err.println("Could not start Symon. Reason: " + ex.getMessage());
}
}
}
+11 -3
View File
@@ -31,6 +31,7 @@ import com.loomcom.symon.ui.Console;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.management.monitor.CounterMonitor;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import java.awt.*;
@@ -136,9 +137,15 @@ public class Simulator {
private static final String[] STEPS = {"1", "5", "10", "20", "50", "100"};
public Simulator(Class machineClass) throws Exception {
this(machineClass, InstructionTable.CpuBehavior.NMOS_6502, null);
}
public Simulator(Class machineClass, InstructionTable.CpuBehavior cpuType, String romFile) throws Exception {
this.breakpoints = new Breakpoints(this);
this.machine = (Machine) machineClass.getConstructors()[0].newInstance();
this.machine = (Machine) machineClass.getConstructors()[0].newInstance(romFile);
this.machine.getCpu().setBehavior(cpuType);
// Initialize final fields in the constructor.
this.traceLog = new TraceLog();
@@ -887,8 +894,9 @@ public class Simulator {
JMenu cpuTypeMenu = new JMenu("CPU");
ButtonGroup cpuGroup = new ButtonGroup();
makeCpuMenuItem("NMOS 6502", Cpu.CpuBehavior.NMOS_6502, cpuTypeMenu, cpuGroup);
makeCpuMenuItem("CMOS 65C02", Cpu.CpuBehavior.CMOS_6502, cpuTypeMenu, cpuGroup);
makeCpuMenuItem("6502", Cpu.CpuBehavior.NMOS_6502, cpuTypeMenu, cpuGroup);
makeCpuMenuItem("65C02", Cpu.CpuBehavior.CMOS_6502, cpuTypeMenu, cpuGroup);
makeCpuMenuItem("65C816", Cpu.CpuBehavior.CMOS_65816, cpuTypeMenu, cpuGroup);
// "Clock Speed" sub-menu
JMenu speedSubMenu = new JMenu("Clock Speed");
@@ -68,7 +68,7 @@ public class MulticompMachine implements Machine {
private Memory rom;
public MulticompMachine() throws Exception {
public MulticompMachine(String romFile) throws Exception {
this.bus = new Bus(BUS_BOTTOM, BUS_TOP);
this.cpu = new Cpu();
this.ram = new Memory(MEMORY_BASE, MEMORY_BASE + MEMORY_SIZE - 1, false);
@@ -80,19 +80,22 @@ public class MulticompMachine implements Machine {
bus.addDevice(acia, 1);
bus.addDevice(new SdController(SD_BASE), 1);
// TODO: Make this configurable, of course.
File romImage = new File("rom.bin");
if (romImage.canRead()) {
logger.info("Loading ROM image from file " + romImage);
this.rom = Memory.makeROM(ROM_BASE, ROM_BASE + ROM_SIZE - 1, romImage);
} else {
logger.info("Default ROM file " + romImage +
if (romFile != null) {
File romImage = new File("rom.bin");
if (romImage.canRead()) {
logger.info("Loading ROM image from file " + romImage);
this.rom = Memory.makeROM(ROM_BASE, ROM_BASE + ROM_SIZE - 1, romImage);
} else {
logger.info("Default ROM file " + romImage +
" not found, loading empty R/W memory image.");
this.rom = Memory.makeRAM(ROM_BASE, ROM_BASE + ROM_SIZE - 1);
}
} else {
logger.info("No ROM file specified, loading empty R/W memory image.");
this.rom = Memory.makeRAM(ROM_BASE, ROM_BASE + ROM_SIZE - 1);
}
bus.addDevice(rom);
}
@Override
@@ -46,7 +46,7 @@ public class SimpleMachine implements Machine {
private final Memory ram;
private final Cpu cpu;
public SimpleMachine() throws MemoryRangeException {
public SimpleMachine(String romFile) throws MemoryRangeException {
this.bus = new Bus(BUS_BOTTOM, BUS_TOP);
this.ram = new Memory(BUS_BOTTOM, BUS_TOP, false);
this.cpu = new Cpu();
@@ -70,7 +70,7 @@ public class SymonMachine implements Machine {
private Memory rom;
public SymonMachine() throws Exception {
public SymonMachine(String romFile) throws Exception {
this.bus = new Bus(BUS_BOTTOM, BUS_TOP);
this.cpu = new Cpu();
this.ram = new Memory(MEMORY_BASE, MEMORY_BASE + MEMORY_SIZE - 1, false);
@@ -84,13 +84,17 @@ public class SymonMachine implements Machine {
bus.addDevice(acia);
bus.addDevice(crtc);
// TODO: Make this configurable, of course.
File romImage = new File("rom.bin");
if (romImage.canRead()) {
logger.info("Loading ROM image from file {}", romImage);
this.rom = Memory.makeROM(ROM_BASE, ROM_BASE + ROM_SIZE - 1, romImage);
if (romFile != null) {
File romImage = new File(romFile);
if (romImage.canRead()) {
logger.info("Loading ROM image from file {}", romImage);
this.rom = Memory.makeROM(ROM_BASE, ROM_BASE + ROM_SIZE - 1, romImage);
} else {
logger.info("Default ROM file {} not found, loading empty R/W memory image.", romImage);
this.rom = Memory.makeRAM(ROM_BASE, ROM_BASE + ROM_SIZE - 1);
}
} else {
logger.info("Default ROM file {} not found, loading empty R/W memory image.", romImage);
logger.info("No ROM file specified, loading empty R/W memory image.");
this.rom = Memory.makeRAM(ROM_BASE, ROM_BASE + ROM_SIZE - 1);
}
@@ -30,6 +30,7 @@ import com.loomcom.symon.machines.Machine;
import javax.swing.*;
import javax.swing.border.Border;
import javax.swing.border.EtchedBorder;
import javax.swing.plaf.metal.MetalTextFieldUI;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
@@ -69,7 +70,7 @@ public class StatusPanel extends JPanel {
private JTextField xField;
private JTextField yField;
private Machine machine;
private final Machine machine;
private static final int EMPTY_BORDER = 10;
private static final Border LABEL_BORDER = BorderFactory.createEmptyBorder(0, 5, 0, 0);
@@ -392,6 +393,13 @@ public class StatusPanel extends JPanel {
textField.setMaximumSize(size);
textField.setPreferredSize(size);
textField.setBackground(Color.WHITE);
// Although we usually defer to the system look-and-feel, for
// these small text fields in particular, we use a Metal
// look-and-feel because native look-and-feel breaks very small
// text fields under GTK+ (they are drawn with an inner margin
// even if the margin is set to 0)
textField.setUI(new MetalTextFieldUI());
return textField;
}