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 146 additions and 48 deletions

No files matched your search

+1
View File
@@ -4,3 +4,4 @@ target
.DS_Store .DS_Store
.idea .idea
symon.iml symon.iml
/dependency-reduced-pom.xml
+28 -12
View File
@@ -1,13 +1,13 @@
SYMON - A 6502 System Simulator 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. 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 ## 1.0 About
@@ -66,7 +66,7 @@ memory.
### 3.2 Serial Console and CPU Status ### 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 The main window of the simulator acts as the primary Input/Output
system through a virtual serial terminal. The terminal is attached to 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 registers, processor status flags, disassembly of the instruction
register, and stack pointer are all displayed. 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. The console supports font sizes from 10 to 20 points.
### 3.3 ROM Loading ### 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 Symon can load any appropriately sized ROM image. The Symon
architecture expects as 16KB (16384 byte) ROM image, while the architecture expects as 16KB (16384 byte) ROM image, while the
@@ -95,32 +95,32 @@ address.
### 3.4 Memory Window ### 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. Memory contents can be viewed (and edited) one page at a time through the Memory Window.
### 3.5 Trace Log ### 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 The last 20,000 execution steps are disassembled and logged to the Trace Log
Window. Window.
### 3.6 Simulator Speeds ### 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. Simulated speeds may be set from 1MHz to 8MHz.
### 3.7 Breakpoints ### 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. Breakpoints can be set and removed through the Breakpoints window.
### 3.8 Experimental 6545 CRTC Video ### 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 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 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 When Symon is running, you should be presented with a simple graphical
interface. 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 ### 4.2 ROM images
The simulator requires a ROM image loaded into memory to work The simulator requires a ROM image loaded into memory to work
@@ -235,6 +247,10 @@ running.
## 5.0 Revision History ## 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.3.0:** 24 February, 2018 - Adds support for 65C02 opcodes.
- **1.2.1:** 8 January, 2016 - Remove dependency on Java 8. Now - **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: 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 wonderfully detailed information about the 6502
- [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),
+28 -16
View File
@@ -4,7 +4,7 @@
<groupId>com.loomcom.symon</groupId> <groupId>com.loomcom.symon</groupId>
<artifactId>symon</artifactId> <artifactId>symon</artifactId>
<packaging>jar</packaging> <packaging>jar</packaging>
<version>1.3.0</version> <version>1.3.2</version>
<name>symon</name> <name>symon</name>
<url>http://www.loomcom.com/symon</url> <url>http://www.loomcom.com/symon</url>
<properties> <properties>
@@ -24,39 +24,51 @@
<dependency> <dependency>
<groupId>junit</groupId> <groupId>junit</groupId>
<artifactId>junit</artifactId> <artifactId>junit</artifactId>
<version>4.12</version> <version>4.13.2</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.mockito</groupId> <groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId> <artifactId>mockito-core</artifactId>
<version>1.10.19</version> <version>3.12.4</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>commons-cli</groupId>
<artifactId>commons-cli</artifactId>
<version>1.4</version>
</dependency>
</dependencies> </dependencies>
<build> <build>
<plugins> <plugins>
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId> <artifactId>maven-shade-plugin</artifactId>
<version>2.6</version> <version>3.2.0</version>
<configuration> <configuration>
<descriptorRefs> <transformers>
<descriptorRef>jar-with-dependencies</descriptorRef> <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
</descriptorRefs>
<appendAssemblyId>false</appendAssemblyId>
<archive>
<manifest>
<mainClass>com.loomcom.symon.Main</mainClass> <mainClass>com.loomcom.symon.Main</mainClass>
</manifest> </transformer>
</archive> </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> </configuration>
<executions> <executions>
<execution> <execution>
<id>make-assembly</id>
<phase>package</phase> <phase>package</phase>
<goals> <goals>
<goal>single</goal> <goal>shade</goal>
</goals> </goals>
</execution> </execution>
</executions> </executions>
@@ -76,7 +88,7 @@
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId> <artifactId>maven-jar-plugin</artifactId>
<version>2.6</version> <version>3.2.0</version>
<configuration> <configuration>
<archive> <archive>
<manifest> <manifest>
+55 -9
View File
@@ -28,6 +28,8 @@ package com.loomcom.symon;
import com.loomcom.symon.machines.MulticompMachine; import com.loomcom.symon.machines.MulticompMachine;
import com.loomcom.symon.machines.SimpleMachine; import com.loomcom.symon.machines.SimpleMachine;
import com.loomcom.symon.machines.SymonMachine; import com.loomcom.symon.machines.SymonMachine;
import org.apache.commons.cli.*;
import java.util.Locale; import java.util.Locale;
import javax.swing.JOptionPane; import javax.swing.JOptionPane;
import javax.swing.SwingUtilities; import javax.swing.SwingUtilities;
@@ -41,25 +43,61 @@ public class Main {
* *
* @param args Program arguments * @param args Program arguments
*/ */
public static void main(String args[]) throws Exception { public static void main(String[] args) throws Exception {
Class machineClass = SymonMachine.class; Class machineClass = SymonMachine.class;
for(int i = 0; i < args.length; ++i) {
String arg = args[i].toLowerCase(Locale.ENGLISH); Options options = new Options();
if(arg.equals("-machine") && (i+1) < args.length) {
String machine = args[i+1].trim().toLowerCase(Locale.ENGLISH); 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) { switch (machine) {
case "symon":
machineClass = SymonMachine.class;
break;
case "multicomp": case "multicomp":
machineClass = MulticompMachine.class; machineClass = MulticompMachine.class;
break; break;
case "simple": case "simple":
machineClass = SimpleMachine.class; machineClass = SimpleMachine.class;
break; break;
case "symon":
machineClass = SymonMachine.class;
break;
default:
System.err.println("Could not start Symon. Unknown machine type " + machine);
return;
} }
} }
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;
}
}
if (line.hasOption("rom")) {
romFile = line.getOptionValue("rom");
} }
while (true) { while (true) {
@@ -84,7 +122,11 @@ public class Main {
} }
} }
final Simulator simulator = new Simulator(machineClass); if (cpuBehavior == null) {
cpuBehavior = InstructionTable.CpuBehavior.NMOS_6502;
}
final Simulator simulator = new Simulator(machineClass, cpuBehavior, romFile);
SwingUtilities.invokeLater(new Runnable() { SwingUtilities.invokeLater(new Runnable() {
@Override @Override
@@ -101,11 +143,15 @@ public class Main {
Simulator.MainCommand cmd = simulator.waitForCommand(); Simulator.MainCommand cmd = simulator.waitForCommand();
if (cmd.equals(Simulator.MainCommand.SELECTMACHINE)) { if (cmd.equals(Simulator.MainCommand.SELECTMACHINE)) {
machineClass = null; machineClass = null;
} else { } else {
break; 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.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import javax.management.monitor.CounterMonitor;
import javax.swing.*; import javax.swing.*;
import javax.swing.border.EmptyBorder; import javax.swing.border.EmptyBorder;
import java.awt.*; import java.awt.*;
@@ -136,9 +137,15 @@ public class Simulator {
private static final String[] STEPS = {"1", "5", "10", "20", "50", "100"}; private static final String[] STEPS = {"1", "5", "10", "20", "50", "100"};
public Simulator(Class machineClass) throws Exception { 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.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. // Initialize final fields in the constructor.
this.traceLog = new TraceLog(); this.traceLog = new TraceLog();
@@ -887,8 +894,9 @@ public class Simulator {
JMenu cpuTypeMenu = new JMenu("CPU"); JMenu cpuTypeMenu = new JMenu("CPU");
ButtonGroup cpuGroup = new ButtonGroup(); ButtonGroup cpuGroup = new ButtonGroup();
makeCpuMenuItem("NMOS 6502", Cpu.CpuBehavior.NMOS_6502, cpuTypeMenu, cpuGroup); makeCpuMenuItem("6502", Cpu.CpuBehavior.NMOS_6502, cpuTypeMenu, cpuGroup);
makeCpuMenuItem("CMOS 65C02", Cpu.CpuBehavior.CMOS_6502, cpuTypeMenu, cpuGroup); makeCpuMenuItem("65C02", Cpu.CpuBehavior.CMOS_6502, cpuTypeMenu, cpuGroup);
makeCpuMenuItem("65C816", Cpu.CpuBehavior.CMOS_65816, cpuTypeMenu, cpuGroup);
// "Clock Speed" sub-menu // "Clock Speed" sub-menu
JMenu speedSubMenu = new JMenu("Clock Speed"); JMenu speedSubMenu = new JMenu("Clock Speed");
@@ -68,7 +68,7 @@ public class MulticompMachine implements Machine {
private Memory rom; private Memory rom;
public MulticompMachine() throws Exception { public MulticompMachine(String romFile) throws Exception {
this.bus = new Bus(BUS_BOTTOM, BUS_TOP); this.bus = new Bus(BUS_BOTTOM, BUS_TOP);
this.cpu = new Cpu(); this.cpu = new Cpu();
this.ram = new Memory(MEMORY_BASE, MEMORY_BASE + MEMORY_SIZE - 1, false); this.ram = new Memory(MEMORY_BASE, MEMORY_BASE + MEMORY_SIZE - 1, false);
@@ -80,7 +80,7 @@ public class MulticompMachine implements Machine {
bus.addDevice(acia, 1); bus.addDevice(acia, 1);
bus.addDevice(new SdController(SD_BASE), 1); bus.addDevice(new SdController(SD_BASE), 1);
// TODO: Make this configurable, of course. if (romFile != null) {
File romImage = new File("rom.bin"); File romImage = new File("rom.bin");
if (romImage.canRead()) { if (romImage.canRead()) {
logger.info("Loading ROM image from file " + romImage); logger.info("Loading ROM image from file " + romImage);
@@ -90,9 +90,12 @@ public class MulticompMachine implements Machine {
" not found, loading empty R/W memory image."); " not found, loading empty R/W memory image.");
this.rom = Memory.makeRAM(ROM_BASE, ROM_BASE + ROM_SIZE - 1); 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); bus.addDevice(rom);
} }
@Override @Override
@@ -46,7 +46,7 @@ public class SimpleMachine implements Machine {
private final Memory ram; private final Memory ram;
private final Cpu cpu; private final Cpu cpu;
public SimpleMachine() throws MemoryRangeException { public SimpleMachine(String romFile) throws MemoryRangeException {
this.bus = new Bus(BUS_BOTTOM, BUS_TOP); this.bus = new Bus(BUS_BOTTOM, BUS_TOP);
this.ram = new Memory(BUS_BOTTOM, BUS_TOP, false); this.ram = new Memory(BUS_BOTTOM, BUS_TOP, false);
this.cpu = new Cpu(); this.cpu = new Cpu();
@@ -70,7 +70,7 @@ public class SymonMachine implements Machine {
private Memory rom; private Memory rom;
public SymonMachine() throws Exception { public SymonMachine(String romFile) throws Exception {
this.bus = new Bus(BUS_BOTTOM, BUS_TOP); this.bus = new Bus(BUS_BOTTOM, BUS_TOP);
this.cpu = new Cpu(); this.cpu = new Cpu();
this.ram = new Memory(MEMORY_BASE, MEMORY_BASE + MEMORY_SIZE - 1, false); this.ram = new Memory(MEMORY_BASE, MEMORY_BASE + MEMORY_SIZE - 1, false);
@@ -84,8 +84,8 @@ public class SymonMachine implements Machine {
bus.addDevice(acia); bus.addDevice(acia);
bus.addDevice(crtc); bus.addDevice(crtc);
// TODO: Make this configurable, of course. if (romFile != null) {
File romImage = new File("rom.bin"); File romImage = new File(romFile);
if (romImage.canRead()) { if (romImage.canRead()) {
logger.info("Loading ROM image from file {}", romImage); logger.info("Loading ROM image from file {}", romImage);
this.rom = Memory.makeROM(ROM_BASE, ROM_BASE + ROM_SIZE - 1, romImage); this.rom = Memory.makeROM(ROM_BASE, ROM_BASE + ROM_SIZE - 1, romImage);
@@ -93,6 +93,10 @@ public class SymonMachine implements Machine {
logger.info("Default ROM file {} not found, loading empty R/W memory image.", romImage); 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); 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); bus.addDevice(rom);
@@ -30,6 +30,7 @@ import com.loomcom.symon.machines.Machine;
import javax.swing.*; import javax.swing.*;
import javax.swing.border.Border; import javax.swing.border.Border;
import javax.swing.border.EtchedBorder; import javax.swing.border.EtchedBorder;
import javax.swing.plaf.metal.MetalTextFieldUI;
import java.awt.*; import java.awt.*;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;
import java.awt.event.ActionListener; import java.awt.event.ActionListener;
@@ -69,7 +70,7 @@ public class StatusPanel extends JPanel {
private JTextField xField; private JTextField xField;
private JTextField yField; private JTextField yField;
private Machine machine; private final Machine machine;
private static final int EMPTY_BORDER = 10; private static final int EMPTY_BORDER = 10;
private static final Border LABEL_BORDER = BorderFactory.createEmptyBorder(0, 5, 0, 0); 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.setMaximumSize(size);
textField.setPreferredSize(size); textField.setPreferredSize(size);
textField.setBackground(Color.WHITE); 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; return textField;
} }