From c317544e7be2564118dbcbec4119cc18ceee5889 Mon Sep 17 00:00:00 2001 From: Seth Morabito Date: Thu, 13 Feb 2025 16:05:42 -0800 Subject: [PATCH] Address IntelliJ warnings This commit addresses a large number of IntelliJ warnings that have been left hanging around for far too long. --- .../java/com/loomcom/symon/Breakpoints.java | 9 +- src/main/java/com/loomcom/symon/Bus.java | 27 +-- src/main/java/com/loomcom/symon/Cpu.java | 6 +- .../com/loomcom/symon/InstructionTable.java | 6 - src/main/java/com/loomcom/symon/Main.java | 38 ++-- .../java/com/loomcom/symon/MemoryRange.java | 2 +- .../java/com/loomcom/symon/Simulator.java | 177 +++++++----------- .../java/com/loomcom/symon/devices/Acia.java | 2 +- .../com/loomcom/symon/devices/Acia6551.java | 5 +- .../com/loomcom/symon/devices/Acia6850.java | 2 +- .../java/com/loomcom/symon/devices/Crtc.java | 28 ++- .../com/loomcom/symon/devices/Device.java | 4 +- .../com/loomcom/symon/devices/Memory.java | 4 +- .../loomcom/symon/devices/SdController.java | 5 +- .../com/loomcom/symon/devices/Via6522.java | 66 +------ .../loomcom/symon/jterminal/JTerminal.java | 28 +-- .../symon/jterminal/TerminalModel.java | 42 ++--- .../symon/jterminal/bell/BellStrategy.java | 2 +- .../jterminal/vt100/AnsiControlSequence.java | 2 +- .../vt100/AnsiControlSequenceListener.java | 4 +- .../vt100/AnsiControlSequenceParser.java | 17 +- .../jterminal/vt100/Vt100TerminalModel.java | 14 +- .../loomcom/symon/machines/SimpleMachine.java | 2 +- .../loomcom/symon/ui/BreakpointsWindow.java | 68 +++---- .../java/com/loomcom/symon/ui/Console.java | 4 +- .../com/loomcom/symon/ui/MemoryWindow.java | 14 +- .../com/loomcom/symon/ui/VideoWindow.java | 48 +++-- .../loomcom/symon/util/FifoRingBuffer.java | 4 +- 28 files changed, 222 insertions(+), 408 deletions(-) diff --git a/src/main/java/com/loomcom/symon/Breakpoints.java b/src/main/java/com/loomcom/symon/Breakpoints.java index 65616f0..1ca0f1d 100644 --- a/src/main/java/com/loomcom/symon/Breakpoints.java +++ b/src/main/java/com/loomcom/symon/Breakpoints.java @@ -9,8 +9,8 @@ import java.util.TreeSet; public class Breakpoints extends AbstractTableModel { - private TreeSet breakpoints; - private Simulator simulator; + private final TreeSet breakpoints; + private final Simulator simulator; public Breakpoints(Simulator simulator) { this.breakpoints = new TreeSet<>(); @@ -26,11 +26,6 @@ public class Breakpoints extends AbstractTableModel { fireTableDataChanged(); } - public void removeBreakpoint(int address) { - this.breakpoints.remove(address); - fireTableDataChanged(); - } - public void removeBreakpointAtIndex(int index) { if (index < 0) { return; diff --git a/src/main/java/com/loomcom/symon/Bus.java b/src/main/java/com/loomcom/symon/Bus.java index 4aae7d0..ed70c21 100644 --- a/src/main/java/com/loomcom/symon/Bus.java +++ b/src/main/java/com/loomcom/symon/Bus.java @@ -42,19 +42,19 @@ import java.util.TreeSet; public class Bus { // The default address at which to load programs - public static int DEFAULT_LOAD_ADDRESS = 0x0200; + public static final int DEFAULT_LOAD_ADDRESS = 0x0200; // By default, our bus starts at 0, and goes up to 64K - private int startAddress = 0x0000; - private int endAddress = 0xffff; + private final int startAddress; + private final int endAddress; // The CPU private Cpu cpu; // Ordered sets of IO devices, associated with their priority - private Map> deviceMap; + private final Map> deviceMap; - // an array for quick lookup of adresses, brute-force style + // an array for quick lookup of addresses, brute-force style private Device[] deviceAddressArray; @@ -94,8 +94,8 @@ public class Bus { * Add a device to the bus. * * @param device Device to add - * @param priority Bus prioirity. - * @throws MemoryRangeException + * @param priority Bus priority. + * @throws MemoryRangeException Invalid device address range. */ public void addDevice(Device device, int priority) throws MemoryRangeException { @@ -109,12 +109,7 @@ public class Bus { throw new MemoryRangeException("end address of device " + device.getName() + " does not fall within the address range of the bus"); } - SortedSet deviceSet = deviceMap.get(priority); - - if (deviceSet == null) { - deviceSet = new TreeSet<>(); - deviceMap.put(priority, deviceSet); - } + SortedSet deviceSet = deviceMap.computeIfAbsent(priority, k -> new TreeSet<>()); device.setBus(this); deviceSet.add(device); @@ -125,7 +120,7 @@ public class Bus { * Add a device to the bus. Throws a MemoryRangeException if the device overlaps with any others. * * @param device Device to add - * @throws MemoryRangeException + * @throws MemoryRangeException Invalid device memory range. */ public void addDevice(Device device) throws MemoryRangeException { addDevice(device, 0); @@ -224,9 +219,7 @@ public class Bus { for (int priority : priorities) { SortedSet deviceSet = deviceMap.get(priority); - for (Device device : deviceSet) { - devices.add(device); - } + devices.addAll(deviceSet); } return devices; diff --git a/src/main/java/com/loomcom/symon/Cpu.java b/src/main/java/com/loomcom/symon/Cpu.java index 8a1d714..6928426 100644 --- a/src/main/java/com/loomcom/symon/Cpu.java +++ b/src/main/java/com/loomcom/symon/Cpu.java @@ -158,6 +158,8 @@ public class Cpu implements InstructionTable { * Performs an individual instruction cycle. */ public void step() throws MemoryAccessException { + int hi, lo; // Address calculation + opBeginTime = System.nanoTime(); // Store the address from which the IR was read, for debugging @@ -317,8 +319,8 @@ public class Cpu implements InstructionTable { break; case 0x40: // RTI - Return from Interrupt - Implied setProcessorStatus(stackPop()); - int lo = stackPop(); - int hi = stackPop(); + lo = stackPop(); + hi = stackPop(); setProgramCounter(Utils.address(lo, hi)); break; case 0x48: // PHA - Push Accumulator - Implied diff --git a/src/main/java/com/loomcom/symon/InstructionTable.java b/src/main/java/com/loomcom/symon/InstructionTable.java index 0a5495f..67de7dd 100644 --- a/src/main/java/com/loomcom/symon/InstructionTable.java +++ b/src/main/java/com/loomcom/symon/InstructionTable.java @@ -28,23 +28,17 @@ public interface InstructionTable { /** * Enumeration of valid CPU behaviors. These determine what behavior and instruction * set will be simulated, depending on desired version of 6502. - * - * TODO: As of version 0.6, this is still not used! All CPUs are "idealized" NMOS 6502 only. */ enum CpuBehavior { /** * The earliest NMOS 6502 includes a bug that causes the ROR instruction * to behave like an ASL that does not affect the carry bit. This version * is very rare in the wild. - * - * NB: Does NOT implement "unimplemented" NMOS instructions. */ NMOS_WITH_ROR_BUG, /** * All NMOS 6502's have a bug with the indirect JMP instruction. If the - * - * NB: Does NOT implement "unimplemented" NMOS instructions. */ NMOS_6502, diff --git a/src/main/java/com/loomcom/symon/Main.java b/src/main/java/com/loomcom/symon/Main.java index 54478f0..4641224 100644 --- a/src/main/java/com/loomcom/symon/Main.java +++ b/src/main/java/com/loomcom/symon/Main.java @@ -25,11 +25,10 @@ package com.loomcom.symon; -import com.loomcom.symon.machines.MulticompMachine; -import com.loomcom.symon.machines.SimpleMachine; -import com.loomcom.symon.machines.SymonMachine; -import com.loomcom.symon.machines.BenEaterMachine; +import com.loomcom.symon.machines.*; import org.apache.commons.cli.*; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.util.Locale; import javax.swing.JOptionPane; @@ -37,7 +36,8 @@ import javax.swing.SwingUtilities; import javax.swing.UIManager; public class Main { - + private final static Logger logger = LoggerFactory.getLogger(Main.class.getName()); + /** * Main entry point to the simulator. Creates a simulator and shows the main * window. @@ -45,8 +45,8 @@ public class Main { * @param args Program arguments */ public static void main(String[] args) throws Exception { - - Class machineClass = SymonMachine.class; + + Class machineClass = null; Options options = new Options(); @@ -79,7 +79,7 @@ public class Main { machineClass = BenEaterMachine.class; break; default: - System.err.println("Could not start Symon. Unknown machine type " + machine); + logger.error("Could not start Symon. Unknown machine type {}", machine); return; } } @@ -97,7 +97,7 @@ public class Main { cpuBehavior = InstructionTable.CpuBehavior.CMOS_65816; break; default: - System.err.println("Could not start Symon. Unknown cpu type " + cpu); + logger.error("Could not start Symon. Unknown cpu type {}", cpu); return; } } @@ -140,16 +140,14 @@ public class Main { final Simulator simulator = new Simulator(machineClass, cpuBehavior, romFile, haltOnBreak); - 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(); - } + SwingUtilities.invokeLater(() -> { + try { + UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); + // Create the main UI window + simulator.createAndShowUi(); + } catch (Exception e) { + logger.error("Error during Symon UI initialization: {}", e.getMessage()); + System.exit(-1); } }); @@ -163,7 +161,7 @@ public class Main { } } } catch (ParseException ex) { - System.err.println("Could not start Symon. Reason: " + ex.getMessage()); + logger.error("Could not start Symon. Reason: {}", ex.getMessage()); } } } diff --git a/src/main/java/com/loomcom/symon/MemoryRange.java b/src/main/java/com/loomcom/symon/MemoryRange.java index 97f2d72..9c4a098 100644 --- a/src/main/java/com/loomcom/symon/MemoryRange.java +++ b/src/main/java/com/loomcom/symon/MemoryRange.java @@ -27,7 +27,7 @@ import com.loomcom.symon.exceptions.*; /** * MemoryRange is a simple container class representing a literal - * range of memory, with a staraddress, and an end address. It has + * range of memory, with a start address, and an end address. It has * guards against creating impossible memory ranges, and implements * some useful methods for checking address inclusion and range * overlaps. diff --git a/src/main/java/com/loomcom/symon/Simulator.java b/src/main/java/com/loomcom/symon/Simulator.java index 6bacb6d..eaa9a16 100644 --- a/src/main/java/com/loomcom/symon/Simulator.java +++ b/src/main/java/com/loomcom/symon/Simulator.java @@ -31,14 +31,11 @@ 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.*; import java.awt.event.*; import java.io.*; -import java.util.SortedSet; -import java.util.TreeSet; /** * Symon Simulator Interface and Control. @@ -72,7 +69,7 @@ public class Simulator { private static final int MAX_STEPS_BETWEEN_UPDATES = 20000; // The simulated machine - private Machine machine; + private final Machine machine; // Number of CPU steps between CRT repaints. // TODO: Dynamically refresh the value at runtime based on performance figures to reach ~ 30fps. @@ -120,13 +117,13 @@ public class Simulator { private JFileChooser fileChooser; private PreferencesDialog preferences; - private Breakpoints breakpoints; + private final Breakpoints breakpoints; private final Object commandMonitorObject = new Object(); private MainCommand command = MainCommand.NONE; - private boolean haltOnBreak; + private final boolean haltOnBreak; public enum MainCommand { NONE, @@ -138,11 +135,11 @@ public class Simulator { */ 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, false); } - public Simulator(Class machineClass, InstructionTable.CpuBehavior cpuType, + public Simulator(Class machineClass, InstructionTable.CpuBehavior cpuType, String romFile, boolean haltOnBreak) throws Exception { this.haltOnBreak = haltOnBreak; this.breakpoints = new Breakpoints(this); @@ -165,7 +162,7 @@ public class Simulator { /** * Display the main simulator UI. */ - public void createAndShowUi() throws IOException { + public void createAndShowUi() { mainWindow = new JFrame(); mainWindow.setTitle("6502 Simulator - " + machine.getName()); mainWindow.setResizable(false); @@ -195,14 +192,16 @@ public class Simulator { JButton hardResetButton = new JButton("Hard Reset"); stepCountBox = new JComboBox<>(STEPS); - stepCountBox.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent actionEvent) { + stepCountBox.addActionListener(actionEvent -> { + JComboBox cb = (JComboBox) actionEvent.getSource(); + String cbStepsPerClick = (String) cb.getSelectedItem(); + + stepsPerClick = 1; // Default in case of error + + if (cbStepsPerClick != null) { try { - JComboBox cb = (JComboBox) actionEvent.getSource(); - stepsPerClick = Integer.parseInt((String) cb.getSelectedItem()); + stepsPerClick = Integer.parseInt(cbStepsPerClick); } catch (NumberFormatException ex) { - stepsPerClick = 1; stepCountBox.setSelectedIndex(0); } } @@ -224,38 +223,24 @@ public class Simulator { // Bottom - buttons. mainWindow.getContentPane().add(buttonContainer, BorderLayout.PAGE_END); - runStopButton.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent actionEvent) { - if (runLoop != null && runLoop.isRunning()) { - Simulator.this.handleStop(); - } else { - Simulator.this.handleStart(); - } + runStopButton.addActionListener(actionEvent -> { + if (runLoop != null && runLoop.isRunning()) { + Simulator.this.handleStop(); + } else { + Simulator.this.handleStart(); } }); - stepButton.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent actionEvent) { - Simulator.this.handleStep(stepsPerClick); - } + stepButton.addActionListener(actionEvent -> Simulator.this.handleStep(stepsPerClick)); + + softResetButton.addActionListener(actionEvent -> { + // If this was a CTRL-click, do a hard reset. + Simulator.this.handleReset(false); }); - 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); - } + hardResetButton.addActionListener(actionEvent -> { + // If this was a CTRL-click, do a hard reset. + Simulator.this.handleReset(true); }); mainWindow.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); @@ -277,7 +262,7 @@ public class Simulator { try { commandMonitorObject.wait(); } catch (InterruptedException ex) { - ex.printStackTrace(); + logger.error("Interrupted during wait on command monitor."); } } return command; @@ -342,7 +327,6 @@ public class Simulator { updateVisibleState(); } catch (SymonException ex) { logger.error("Exception during simulator step", ex); - ex.printStackTrace(); } } @@ -365,7 +349,7 @@ public class Simulator { // If a key has been pressed, fill the ACIA. try { if (machine.getAcia() != null && console.hasInput()) { - machine.getAcia().rxWrite((int) console.readInputChar()); + machine.getAcia().rxWrite(console.readInputChar()); } } catch (FifoUnderrunException ex) { logger.error("Console type-ahead buffer underrun!"); @@ -427,16 +411,13 @@ public class Simulator { logger.debug("Starting main run loop."); isRunning = true; - 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"); - } + 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"); }); try { @@ -447,20 +428,17 @@ public class Simulator { logger.error("Exception in main simulator run thread. Exiting run.", ex); } - 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(); + SwingUtilities.invokeLater(() -> { + statusPane.updateState(); + memoryWindow.updateState(); + runStopButton.setText("Run"); + stepButton.setEnabled(true); + stepCountBox.setEnabled(true); + if (traceLog.isVisible()) { + traceLog.refresh(); } + menuBar.simulatorDidStop(); + traceLog.simulatorDidStop(); }); isRunning = false; @@ -513,12 +491,9 @@ public class Simulator { // Now load the program at the starting address. loadProgram(program, preferences.getProgramStartAddress()); - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - console.reset(); - breakpoints.refresh(); - } + SwingUtilities.invokeLater(() -> { + console.reset(); + breakpoints.refresh(); }); // TODO: "Don't Show Again" checkbox @@ -556,7 +531,7 @@ public class Simulator { long fileSize = romFile.length(); if (fileSize != machine.getRomSize()) { - throw new IOException("ROM file must be exactly " + String.valueOf(machine.getRomSize()) + " bytes."); + throw new IOException("ROM file must be exactly " + machine.getRomSize() + " bytes."); } // Load the new ROM image @@ -650,30 +625,27 @@ public class Simulator { } class SetFontAction extends AbstractAction { - private int size; + private final int size; public SetFontAction(int size) { - super(Integer.toString(size) + " pt", null); + super(size + " pt", null); this.size = size; putValue(SHORT_DESCRIPTION, "Set font to " + size + "pt."); } public void actionPerformed(ActionEvent actionEvent) { - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - console.setFont(new Font("Monospaced", Font.PLAIN, size)); - mainWindow.pack(); - } + SwingUtilities.invokeLater(() -> { + console.setFont(new Font("Monospaced", Font.PLAIN, size)); + mainWindow.pack(); }); } } class SetSpeedAction extends AbstractAction { - private int speed; + private final int speed; public SetSpeedAction(int speed) { - super(Integer.toString(speed) + " MHz", null); + super(speed + " MHz", null); this.speed = speed; putValue(SHORT_DESCRIPTION, "Set simulated speed to " + speed + " MHz."); } @@ -689,7 +661,7 @@ public class Simulator { } class SetCpuAction extends AbstractAction { - private Cpu.CpuBehavior behavior; + private final Cpu.CpuBehavior behavior; public SetCpuAction(String cpu, Cpu.CpuBehavior behavior) { super(cpu, null); @@ -729,11 +701,7 @@ public class Simulator { public void actionPerformed(ActionEvent actionEvent) { synchronized (memoryWindow) { - if (memoryWindow.isVisible()) { - memoryWindow.setVisible(false); - } else { - memoryWindow.setVisible(true); - } + memoryWindow.setVisible(!memoryWindow.isVisible()); } } } @@ -746,11 +714,7 @@ public class Simulator { public void actionPerformed(ActionEvent actionEvent) { synchronized (videoWindow) { - if (videoWindow.isVisible()) { - videoWindow.setVisible(false); - } else { - videoWindow.setVisible(true); - } + videoWindow.setVisible(!videoWindow.isVisible()); } } } @@ -763,11 +727,7 @@ public class Simulator { public void actionPerformed(ActionEvent actionEvent) { synchronized (breakpointsWindow) { - if (breakpointsWindow.isVisible()) { - breakpointsWindow.setVisible(false); - } else { - breakpointsWindow.setVisible(true); - } + breakpointsWindow.setVisible(!breakpointsWindow.isVisible()); } } } @@ -963,15 +923,12 @@ public class Simulator { private void updateVisibleState() { // Immediately update the UI. - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - // Now update the state - statusPane.updateState(); - memoryWindow.updateState(); - if (traceLog.shouldUpdate()) { - traceLog.refresh(); - } + SwingUtilities.invokeLater(() -> { + // Now update the state + statusPane.updateState(); + memoryWindow.updateState(); + if (traceLog.shouldUpdate()) { + traceLog.refresh(); } }); } diff --git a/src/main/java/com/loomcom/symon/devices/Acia.java b/src/main/java/com/loomcom/symon/devices/Acia.java index 02fe0ea..12fb3d2 100644 --- a/src/main/java/com/loomcom/symon/devices/Acia.java +++ b/src/main/java/com/loomcom/symon/devices/Acia.java @@ -32,7 +32,7 @@ import com.loomcom.symon.exceptions.MemoryRangeException; public abstract class Acia extends Device { - private String name; + private final String name; /** * Register addresses diff --git a/src/main/java/com/loomcom/symon/devices/Acia6551.java b/src/main/java/com/loomcom/symon/devices/Acia6551.java index b9270a3..3401daa 100644 --- a/src/main/java/com/loomcom/symon/devices/Acia6551.java +++ b/src/main/java/com/loomcom/symon/devices/Acia6551.java @@ -121,9 +121,6 @@ public class Acia6551 extends Acia { // Mask the lower four bits to get the baud rate. int baudSelector = data & 0x0f; switch (baudSelector) { - case 0: - rate = 0; - break; case 1: rate = 50; break; @@ -169,6 +166,8 @@ public class Acia6551 extends Acia { case 15: rate = 19200; break; + default: + break; } setBaudRate(rate); diff --git a/src/main/java/com/loomcom/symon/devices/Acia6850.java b/src/main/java/com/loomcom/symon/devices/Acia6850.java index e957bb4..d3b1c93 100644 --- a/src/main/java/com/loomcom/symon/devices/Acia6850.java +++ b/src/main/java/com/loomcom/symon/devices/Acia6850.java @@ -31,7 +31,7 @@ import com.loomcom.symon.exceptions.MemoryRangeException; /** * This is a simulation of the Motorola 6850 ACIA, with limited * functionality. - * + *

* Unlike a 16550 UART, the 6850 ACIA has only one-byte transmit and * receive buffers. It is the programmer's responsibility to check the * status (full or empty) for transmit and receive buffers before diff --git a/src/main/java/com/loomcom/symon/devices/Crtc.java b/src/main/java/com/loomcom/symon/devices/Crtc.java index ecf5117..464da5f 100644 --- a/src/main/java/com/loomcom/symon/devices/Crtc.java +++ b/src/main/java/com/loomcom/symon/devices/Crtc.java @@ -26,8 +26,6 @@ package com.loomcom.symon.devices; import com.loomcom.symon.exceptions.MemoryAccessException; import com.loomcom.symon.exceptions.MemoryRangeException; -import java.io.IOException; - /** * Simulation of a 6545 CRTC and virtual CRT output. */ @@ -87,9 +85,9 @@ public class Crtc extends Device { private boolean displayEnableSkew = false; private boolean cursorSkew = false; - private Memory memory; + private final Memory memory; - public Crtc(int deviceAddress, Memory memory) throws MemoryRangeException, IOException { + public Crtc(int deviceAddress, Memory memory) throws MemoryRangeException { super(deviceAddress, deviceAddress + 2, "CRTC"); this.memory = memory; @@ -120,19 +118,17 @@ public class Crtc extends Device { @Override public int read(int address, boolean cpuAccess) throws MemoryAccessException { - switch (address) { - case REGISTER_RW: - switch (currentRegister) { - case CURSOR_POSITION_LOW: - return cursorPosition & 0xff; - case CURSOR_POSITION_HIGH: - return cursorPosition >> 8; - default: - return 0; - } - default: - return 0; + if (address == REGISTER_RW) { + switch (currentRegister) { + case CURSOR_POSITION_LOW: + return cursorPosition & 0xff; + case CURSOR_POSITION_HIGH: + return cursorPosition >> 8; + default: + return 0; + } } + return 0; } @Override diff --git a/src/main/java/com/loomcom/symon/devices/Device.java b/src/main/java/com/loomcom/symon/devices/Device.java index 3956ea5..f7b9386 100644 --- a/src/main/java/com/loomcom/symon/devices/Device.java +++ b/src/main/java/com/loomcom/symon/devices/Device.java @@ -45,7 +45,7 @@ public abstract class Device implements Comparable { /** * The memory range for this device. */ - private MemoryRange memoryRange; + private final MemoryRange memoryRange; /** * The name of the device. @@ -60,7 +60,7 @@ public abstract class Device implements Comparable { /** * Listeners to notify on update. */ - private Set deviceChangeListeners; + private final Set deviceChangeListeners; public Device(int startAddress, int endAddress, String name) throws MemoryRangeException { this.memoryRange = new MemoryRange(startAddress, endAddress); diff --git a/src/main/java/com/loomcom/symon/devices/Memory.java b/src/main/java/com/loomcom/symon/devices/Memory.java index 3fa5ff4..62dee95 100644 --- a/src/main/java/com/loomcom/symon/devices/Memory.java +++ b/src/main/java/com/loomcom/symon/devices/Memory.java @@ -30,8 +30,8 @@ import com.loomcom.symon.exceptions.*; public class Memory extends Device { - private boolean readOnly; - private int[] mem; + private final boolean readOnly; + private final int[] mem; /* Initialize all locations to 0x00 (BRK) */ private static final int DEFAULT_FILL = 0x00; diff --git a/src/main/java/com/loomcom/symon/devices/SdController.java b/src/main/java/com/loomcom/symon/devices/SdController.java index cbdd757..0663272 100644 --- a/src/main/java/com/loomcom/symon/devices/SdController.java +++ b/src/main/java/com/loomcom/symon/devices/SdController.java @@ -119,7 +119,10 @@ public class SdController extends Device { if (sdImageFile != null) { try { FileInputStream fis = new FileInputStream(sdImageFile); - fis.skip(this.position); + long bytesSkipped = fis.skip(this.position); + if (bytesSkipped < this.position) { + logger.log(Level.WARNING, "Failed to seek to position " + this.position); + } int read = fis.read(readBuffer); if (read < SECTOR_SIZE) { logger.log(Level.WARNING, "not enough data to fill read buffer from SD image file"); diff --git a/src/main/java/com/loomcom/symon/devices/Via6522.java b/src/main/java/com/loomcom/symon/devices/Via6522.java index c50a6f7..6b00007 100644 --- a/src/main/java/com/loomcom/symon/devices/Via6522.java +++ b/src/main/java/com/loomcom/symon/devices/Via6522.java @@ -27,83 +27,23 @@ import com.loomcom.symon.exceptions.MemoryAccessException; import com.loomcom.symon.exceptions.MemoryRangeException; /** - * Very basic implementation of a MOS 6522 VIA. - * - * TODO: Implement timers as threads. + * Skeleton for future implementation of a MOS 6522 VIA. */ public class Via6522 extends Pia { public static final int VIA_SIZE = 16; - enum Register { - ORB, ORA, DDRB, DDRA, T1C_L, T1C_H, T1L_L, T1L_H, - T2C_L, T2C_H, SR, ACR, PCR, IFR, IER, ORA_H - } - public Via6522(int address) throws MemoryRangeException { super(address, address + VIA_SIZE - 1, "MOS 6522 VIA"); } @Override public void write(int address, int data) throws MemoryAccessException { - Register[] registers = Register.values(); - - if (address >= registers.length) { - throw new MemoryAccessException("Unknown register: " + address); - } - - Register r = registers[address]; - - switch (r) { - case ORA: - case ORB: - case DDRA: - case DDRB: - case T1C_L: - case T1C_H: - case T1L_L: - case T1L_H: - case T2C_L: - case T2C_H: - case SR: - case ACR: - case PCR: - case IFR: - case IER: - case ORA_H: - default: - } + // TODO: Implement write. } @Override public int read(int address, boolean cpuAccess) throws MemoryAccessException { - Register[] registers = Register.values(); - - if (address >= registers.length) { - throw new MemoryAccessException("Unknown register: " + address); - } - - Register r = registers[address]; - - switch (r) { - case ORA: - case ORB: - case DDRA: - case DDRB: - case T1C_L: - case T1C_H: - case T1L_L: - case T1L_H: - case T2C_L: - case T2C_H: - case SR: - case ACR: - case PCR: - case IFR: - case IER: - case ORA_H: - default: - } - + // TODO: Implement read. return 0; } } diff --git a/src/main/java/com/loomcom/symon/jterminal/JTerminal.java b/src/main/java/com/loomcom/symon/jterminal/JTerminal.java index b3b519c..0a2a9e2 100644 --- a/src/main/java/com/loomcom/symon/jterminal/JTerminal.java +++ b/src/main/java/com/loomcom/symon/jterminal/JTerminal.java @@ -25,13 +25,8 @@ package com.loomcom.symon.jterminal; import com.loomcom.symon.jterminal.vt100.Vt100TerminalModel; -import java.awt.BorderLayout; -import java.awt.Dimension; -import java.awt.Font; -import java.awt.FontMetrics; -import java.awt.Graphics; -import java.awt.event.AdjustmentEvent; -import java.awt.event.AdjustmentListener; + +import java.awt.*; import javax.swing.JComponent; import javax.swing.JScrollBar; @@ -88,10 +83,6 @@ public class JTerminal extends JComponent { revalidate(); } - public int getBorderWidth() { - return borderWidth; - } - public void setFont(Font font) { this.font = font; setCellWidthAndHeight(font); @@ -113,13 +104,6 @@ public class JTerminal extends JComponent { return model; } - public void println(String str) { - if (str == null) { - throw new NullPointerException("str"); - } - print(str.concat("\r\n")); - } - public void print(String str) { model.print(str); } @@ -177,12 +161,8 @@ public class JTerminal extends JComponent { int bufferSize = model.getBufferSize(); if (bufferSize > rows) { - scrollBar = new JScrollBar(1, 0, rows, 0, bufferSize + 1); - scrollBar.addAdjustmentListener(new AdjustmentListener() { - public void adjustmentValueChanged(AdjustmentEvent evt) { - repaint(); - } - }); + scrollBar = new JScrollBar(Adjustable.VERTICAL, 0, rows, 0, bufferSize + 1); + scrollBar.addAdjustmentListener(evt -> repaint()); add("After", scrollBar); } diff --git a/src/main/java/com/loomcom/symon/jterminal/TerminalModel.java b/src/main/java/com/loomcom/symon/jterminal/TerminalModel.java index 7e83a2d..ae25569 100644 --- a/src/main/java/com/loomcom/symon/jterminal/TerminalModel.java +++ b/src/main/java/com/loomcom/symon/jterminal/TerminalModel.java @@ -32,51 +32,45 @@ import com.loomcom.symon.jterminal.bell.BellStrategy; */ public interface TerminalModel { - /** - * Gets the bell strategy. - * @return The bell strategy. - */ - public BellStrategy getBellStrategy(); - /** * Sets the bell strategy. * @param strategy The bell strategy. * @throws NullPointerException if the strategy is {@code null}. */ - public void setBellStrategy(BellStrategy strategy); + void setBellStrategy(BellStrategy strategy); /** * Clears the terminal. */ - public void clear(); + void clear(); /** * Moves the cursor back n characters. * @param n The number of characters. * @throws IllegalArgumentException if n is not positive. */ - public void moveCursorBack(int n); + void moveCursorBack(int n); /** * Moves the cursor forward n characters. * @param n The number of characters. * @throws IllegalArgumentException if n is not positive. */ - public void moveCursorForward(int n); + void moveCursorForward(int n); /** * Moves the cursor down n characters. * @param n The number of characters. * @throws IllegalArgumentException if n is not positive. */ - public void moveCursorDown(int n); + void moveCursorDown(int n); /** * Moves the cursor up n characters. * @param n The number of characters. * @throws IllegalArgumentException if n is not positive. */ - public void moveCursorUp(int n); + void moveCursorUp(int n); /** * Sets a cell. @@ -86,7 +80,7 @@ public interface TerminalModel { * @throws IndexOutOfBoundsException if the column and/or row number(s) are * out of bounds. */ - public void setCell(int column, int row, TerminalCell cell); + void setCell(int column, int row, TerminalCell cell); /** * Gets a cell. @@ -96,7 +90,7 @@ public interface TerminalModel { * @throws IndexOutOfBoundsException if the column and/or row number(s) are * out of bounds. */ - public TerminalCell getCell(int column, int row); + TerminalCell getCell(int column, int row); /** * Prints the specified string to the terminal at the cursor position, @@ -105,63 +99,63 @@ public interface TerminalModel { * @param str The string to print. * @throws NullPointerException if the string is {@code null}. */ - public void print(String str); + void print(String str); /** * Gets the number of columns. * @return The number of columns. */ - public int getColumns(); + int getColumns(); /** * Gets the number of rows. * @return The number of rows. */ - public int getRows(); + int getRows(); /** * Gets the buffer size. * @return The buffer size. */ - public int getBufferSize(); + int getBufferSize(); /** * Gets the cursor row. * @return The cursor row. */ - public int getCursorRow(); + int getCursorRow(); /** * Sets the cursor row. * @param row The cursor row. * @throws IllegalArgumentException if the row is out of the valid range. */ - public void setCursorRow(int row); + void setCursorRow(int row); /** * Gets the cursor column. * @return The cursor column. */ - public int getCursorColumn(); + int getCursorColumn(); /** * Sets the cursor column. * @param column The cursor column. * @throws IllegalArgumentException if the column is out of the valid range. */ - public void setCursorColumn(int column); + void setCursorColumn(int column); /** * Gets the default background color. * @return The default background color. */ - public Color getDefaultBackgroundColor(); + Color getDefaultBackgroundColor(); /** * Gets the default foreground color. * @return The default foreground color. */ - public Color getDefaultForegroundColor(); + Color getDefaultForegroundColor(); } diff --git a/src/main/java/com/loomcom/symon/jterminal/bell/BellStrategy.java b/src/main/java/com/loomcom/symon/jterminal/bell/BellStrategy.java index 57a4fb9..b477a7d 100644 --- a/src/main/java/com/loomcom/symon/jterminal/bell/BellStrategy.java +++ b/src/main/java/com/loomcom/symon/jterminal/bell/BellStrategy.java @@ -31,7 +31,7 @@ public interface BellStrategy { /** * Sounds the bell. */ - public void soundBell(); + void soundBell(); } diff --git a/src/main/java/com/loomcom/symon/jterminal/vt100/AnsiControlSequence.java b/src/main/java/com/loomcom/symon/jterminal/vt100/AnsiControlSequence.java index c752cbf..a306afd 100644 --- a/src/main/java/com/loomcom/symon/jterminal/vt100/AnsiControlSequence.java +++ b/src/main/java/com/loomcom/symon/jterminal/vt100/AnsiControlSequence.java @@ -50,7 +50,7 @@ public class AnsiControlSequence { throw new NullPointerException("parameters"); } this.command = command; - if (parameters.length == 1 && parameters[0].equals("")) { + if (parameters.length == 1 && parameters[0].isEmpty()) { this.parameters = new String[0]; } else { this.parameters = parameters.clone(); diff --git a/src/main/java/com/loomcom/symon/jterminal/vt100/AnsiControlSequenceListener.java b/src/main/java/com/loomcom/symon/jterminal/vt100/AnsiControlSequenceListener.java index c5b20a2..f92212b 100644 --- a/src/main/java/com/loomcom/symon/jterminal/vt100/AnsiControlSequenceListener.java +++ b/src/main/java/com/loomcom/symon/jterminal/vt100/AnsiControlSequenceListener.java @@ -32,13 +32,13 @@ public interface AnsiControlSequenceListener { * Called when a control sequence has been parsed. * @param seq The control sequence. */ - public void parsedControlSequence(AnsiControlSequence seq); + void parsedControlSequence(AnsiControlSequence seq); /** * Called when a string has been parsed. * @param str The string. */ - public void parsedString(String str); + void parsedString(String str); } diff --git a/src/main/java/com/loomcom/symon/jterminal/vt100/AnsiControlSequenceParser.java b/src/main/java/com/loomcom/symon/jterminal/vt100/AnsiControlSequenceParser.java index cf1a9d9..7d31a75 100644 --- a/src/main/java/com/loomcom/symon/jterminal/vt100/AnsiControlSequenceParser.java +++ b/src/main/java/com/loomcom/symon/jterminal/vt100/AnsiControlSequenceParser.java @@ -33,7 +33,7 @@ import java.io.StringReader; public class AnsiControlSequenceParser { /** - * The multi-byte control sequence introducer. + * The multibyte control sequence introducer. */ private static final char[] MULTI_CSI = new char[] { 27, '[' }; @@ -43,7 +43,7 @@ public class AnsiControlSequenceParser { private static final char SINGLE_CSI = 155; /** - * The buffer of data from the last call to {@link #parse()}. This is + * The buffer of data from the last call to "parse()". This is * populated with data if an escape sequence is not complete. */ private StringBuilder buffer = new StringBuilder(); @@ -70,13 +70,10 @@ public class AnsiControlSequenceParser { str = buffer.toString().concat(str); buffer = new StringBuilder(); } - Reader reader = new StringReader(str); - try { - try { - parse(reader); - } finally { - reader.close(); - } + try { + try (Reader reader = new StringReader(str)) { + parse(reader); + } } catch (IOException ex) { /* ignore */ } @@ -147,7 +144,7 @@ public class AnsiControlSequenceParser { if (!finishedSequence) { // not an ideal solution if they used the two byte CSI, but it's // easier and cleaner than keeping track of it - buffer.append((char) SINGLE_CSI); + buffer.append(SINGLE_CSI); buffer.append(parameters); } } diff --git a/src/main/java/com/loomcom/symon/jterminal/vt100/Vt100TerminalModel.java b/src/main/java/com/loomcom/symon/jterminal/vt100/Vt100TerminalModel.java index a3d9c28..1c00da6 100644 --- a/src/main/java/com/loomcom/symon/jterminal/vt100/Vt100TerminalModel.java +++ b/src/main/java/com/loomcom/symon/jterminal/vt100/Vt100TerminalModel.java @@ -56,6 +56,7 @@ public class Vt100TerminalModel extends AbstractTerminalModel { @Override public void parsedControlSequence(AnsiControlSequence seq) { char command = seq.getCommand(); + int n; String[] parameters = seq.getParameters(); switch (command) { @@ -63,7 +64,7 @@ public class Vt100TerminalModel extends AbstractTerminalModel { case 'B': case 'C': case 'D': - int n = 1; + n = 1; if (parameters.length == 1) { n = Integer.parseInt(parameters[0]); } @@ -73,7 +74,7 @@ public class Vt100TerminalModel extends AbstractTerminalModel { moveCursorDown(n); } else if (command == 'C') { moveCursorForward(n); - } else if (command == 'D') { + } else { moveCursorBack(n); } break; @@ -85,7 +86,7 @@ public class Vt100TerminalModel extends AbstractTerminalModel { } if (command == 'E') { moveCursorDown(n); - } else if (command == 'F') { + } else { moveCursorUp(n); } setCursorColumn(0); @@ -465,12 +466,7 @@ public class Vt100TerminalModel extends AbstractTerminalModel { return bufferSize; } - @Override - public BellStrategy getBellStrategy() { - return bellStrategy; - } - - @Override + @Override public void setBellStrategy(BellStrategy strategy) { if (strategy == null) { throw new NullPointerException("strategy"); diff --git a/src/main/java/com/loomcom/symon/machines/SimpleMachine.java b/src/main/java/com/loomcom/symon/machines/SimpleMachine.java index fc49ec4..a46b0e6 100644 --- a/src/main/java/com/loomcom/symon/machines/SimpleMachine.java +++ b/src/main/java/com/loomcom/symon/machines/SimpleMachine.java @@ -91,7 +91,7 @@ public class SimpleMachine implements Machine { } @Override - public void setRom(Memory rom) throws MemoryRangeException { + public void setRom(Memory rom) { // No-op } diff --git a/src/main/java/com/loomcom/symon/ui/BreakpointsWindow.java b/src/main/java/com/loomcom/symon/ui/BreakpointsWindow.java index 3f7bf1c..211cac2 100644 --- a/src/main/java/com/loomcom/symon/ui/BreakpointsWindow.java +++ b/src/main/java/com/loomcom/symon/ui/BreakpointsWindow.java @@ -30,10 +30,7 @@ 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; /** @@ -46,8 +43,8 @@ public class BreakpointsWindow extends JFrame { private static final Dimension FRAME_SIZE = new Dimension(240, 280); private static final String EMPTY_STRING = ""; - private JFrame mainWindow; - private Breakpoints breakpoints; + private final JFrame mainWindow; + private final Breakpoints breakpoints; public BreakpointsWindow(Breakpoints breakpoints, JFrame mainWindow) { @@ -75,16 +72,7 @@ public class BreakpointsWindow extends JFrame { breakpointsTable.setShowGrid(true); breakpointsTable.setGridColor(Color.LIGHT_GRAY); breakpointsTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); - breakpointsTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() { - @Override - public void valueChanged(ListSelectionEvent e) { - if (e.getFirstIndex() > -1) { - removeButton.setEnabled(true); - } else { - removeButton.setEnabled(false); - } - } - }); + breakpointsTable.getSelectionModel().addListSelectionListener(e -> removeButton.setEnabled(e.getFirstIndex() > -1)); JScrollPane scrollPane = new JScrollPane(breakpointsTable); scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); @@ -92,45 +80,33 @@ public class BreakpointsWindow extends JFrame { breakpointsPanel.add(scrollPane, BorderLayout.CENTER); - ActionListener addBreakpointListener = new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - int value; + ActionListener addBreakpointListener = e -> { + int value; - String newBreakpoint = addTextField.getText(); + String newBreakpoint = addTextField.getText(); - 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); + 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; + } + + breakpoints.addBreakpoint(value); + + logger.debug("Added breakpoint ${}", Utils.wordToHex(value)); + + addTextField.setText(EMPTY_STRING); }; addButton.addActionListener(addBreakpointListener); addTextField.addActionListener(addBreakpointListener); - removeButton.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - breakpoints.removeBreakpointAtIndex(breakpointsTable.getSelectedRow()); - } - }); + removeButton.addActionListener(e -> breakpoints.removeBreakpointAtIndex(breakpointsTable.getSelectedRow())); controlPanel.add(addTextField); controlPanel.add(addButton); diff --git a/src/main/java/com/loomcom/symon/ui/Console.java b/src/main/java/com/loomcom/symon/ui/Console.java index b9fafe9..6bca639 100644 --- a/src/main/java/com/loomcom/symon/ui/Console.java +++ b/src/main/java/com/loomcom/symon/ui/Console.java @@ -51,8 +51,8 @@ public class Console extends JTerminal implements KeyListener, MouseListener { private static final boolean SWAP_CR_AND_LF = true; // If true, send CRLF (0x0d 0x0a) whenever CR is typed - private boolean sendCrForLf; - private FifoRingBuffer typeAheadBuffer; + private final boolean sendCrForLf; + private final FifoRingBuffer typeAheadBuffer; public Console(int columns, int rows, Font font, boolean sendCrForLf) { super(new Vt100TerminalModel(columns, rows), font); diff --git a/src/main/java/com/loomcom/symon/ui/MemoryWindow.java b/src/main/java/com/loomcom/symon/ui/MemoryWindow.java index ed9104c..7494e3e 100644 --- a/src/main/java/com/loomcom/symon/ui/MemoryWindow.java +++ b/src/main/java/com/loomcom/symon/ui/MemoryWindow.java @@ -49,7 +49,7 @@ public class MemoryWindow extends JFrame implements ActionListener { private static final Logger logger = LoggerFactory.getLogger(MemoryWindow.class); - private MemoryTableModel memoryTableModel; + private final MemoryTableModel memoryTableModel; private JTable memoryTable; private JTextField pageNumberTextField; private JButton previousPageButton; @@ -111,7 +111,7 @@ public class MemoryWindow extends JFrame implements ActionListener { } /** - * Set-up the UI. + * Set up the UI. */ private void createUi() { setTitle("Memory Contents"); @@ -230,7 +230,7 @@ public class MemoryWindow extends JFrame implements ActionListener { * A JTable that will automatically select all text in a cell * being edited. */ - private class MemoryTable extends JTable { + private static class MemoryTable extends JTable { public MemoryTable(TableModel tableModel) { super(tableModel); @@ -242,7 +242,7 @@ public class MemoryWindow extends JFrame implements ActionListener { final Component editor = getEditorComponent(); - if (editor != null && editor instanceof JTextComponent) { + if (editor instanceof JTextComponent) { ((JTextComponent) editor).selectAll(); } @@ -250,7 +250,7 @@ public class MemoryWindow extends JFrame implements ActionListener { } } - private class MemoryTableCellRenderer extends DefaultTableCellRenderer { + private static class MemoryTableCellRenderer extends DefaultTableCellRenderer { @Override public Component getTableCellRendererComponent(JTable table, Object value, @@ -272,9 +272,9 @@ public class MemoryWindow extends JFrame implements ActionListener { /** * The model that backs the Memory Table. */ - private class MemoryTableModel extends AbstractTableModel { + private static class MemoryTableModel extends AbstractTableModel { - private Bus bus; + private final Bus bus; private int pageNumber; private static final int COLUMN_COUNT = 17; diff --git a/src/main/java/com/loomcom/symon/ui/VideoWindow.java b/src/main/java/com/loomcom/symon/ui/VideoWindow.java index ac7130e..e0a15d2 100644 --- a/src/main/java/com/loomcom/symon/ui/VideoWindow.java +++ b/src/main/java/com/loomcom/symon/ui/VideoWindow.java @@ -64,12 +64,13 @@ public class VideoWindow extends JFrame implements DeviceChangeListener { private static final long WINDOW_REPAINT_INTERVAL = 66; // 30fps rate private static final int CHAR_WIDTH = 8; private static final int CHAR_HEIGHT = 8; + private static final String ASCII_ROM = "/ascii.rom"; private final int scaleX, scaleY; private final boolean shouldScale; private BufferedImage image; - private int[] charRom; + private final int[] charRom; private int horizontalDisplayed; private int verticalDisplayed; @@ -78,9 +79,9 @@ public class VideoWindow extends JFrame implements DeviceChangeListener { private boolean hideCursor; private Dimension dimensions; - private Crtc crtc; + private final Crtc crtc; - private ScheduledExecutorService scheduler; + private final ScheduledExecutorService scheduler; private ScheduledFuture cursorBlinker; /** @@ -123,12 +124,9 @@ public class VideoWindow extends JFrame implements DeviceChangeListener { */ private class CursorBlinker implements Runnable { public void run() { - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - if (cursorBlinkRate > 0) { - hideCursor = !hideCursor; - } + SwingUtilities.invokeLater(() -> { + if (cursorBlinkRate > 0) { + hideCursor = !hideCursor; } }); } @@ -136,12 +134,9 @@ public class VideoWindow extends JFrame implements DeviceChangeListener { private class WindowPainter implements Runnable { public void run() { - SwingUtilities.invokeLater(new Runnable () { - @Override - public void run() { - if (VideoWindow.this.isVisible()) { - VideoWindow.this.repaint(); - } + SwingUtilities.invokeLater(() -> { + if (VideoWindow.this.isVisible()) { + VideoWindow.this.repaint(); } }); } @@ -152,7 +147,7 @@ public class VideoWindow extends JFrame implements DeviceChangeListener { this.scheduler = Executors.newSingleThreadScheduledExecutor(); this.crtc = crtc; - this.charRom = loadCharRom("/ascii.rom"); + this.charRom = loadCharRom(); this.scaleX = scaleX; this.scaleY = scaleY; this.shouldScale = (scaleX > 1 || scaleY > 1); @@ -292,14 +287,17 @@ public class VideoWindow extends JFrame implements DeviceChangeListener { * Since the BufferedImage is a TYPE_BYTE_BINARY, the data must be converted * into a single byte per pixel, 0 for black and 255 for white. - * @param resource The ROM file resource to load. * @return An array of glyphs, each ready for insertion. - * @throws IOException + * @throws IOException Failure to load character ROM. */ - private int[] loadCharRom(String resource) throws IOException { - BufferedInputStream bis = null; - try { - bis = new BufferedInputStream(this.getClass().getResourceAsStream(resource)); + private int[] loadCharRom() throws IOException { + var resource = this.getClass().getResourceAsStream(ASCII_ROM); + + if (resource == null) { + throw new IOException("Resource " + ASCII_ROM + " not found"); + } + + try (BufferedInputStream bis = new BufferedInputStream(resource)) { ByteArrayOutputStream bos = new ByteArrayOutputStream(); while (bis.available() > 0) { bos.write(bis.read()); @@ -314,7 +312,7 @@ public class VideoWindow extends JFrame implements DeviceChangeListener { int[] converted = new int[raw.length * CHAR_WIDTH]; int romIndex = 0; - for (int i = 0; i < converted.length;) { + for (int i = 0; i < converted.length; ) { byte charRow = raw[romIndex++]; for (int j = 7; j >= 0; j--) { @@ -322,10 +320,6 @@ public class VideoWindow extends JFrame implements DeviceChangeListener { } } return converted; - } finally { - if (bis != null) { - bis.close(); - } } } } diff --git a/src/main/java/com/loomcom/symon/util/FifoRingBuffer.java b/src/main/java/com/loomcom/symon/util/FifoRingBuffer.java index b561e81..a7ec0ca 100644 --- a/src/main/java/com/loomcom/symon/util/FifoRingBuffer.java +++ b/src/main/java/com/loomcom/symon/util/FifoRingBuffer.java @@ -34,8 +34,8 @@ import java.util.Queue; */ public class FifoRingBuffer implements Iterable { - private Queue fifoBuffer; - private int maxLength; + private final Queue fifoBuffer; + private final int maxLength; public FifoRingBuffer(int maxLength) { this.fifoBuffer = new LinkedList<>();