diff --git a/src/main/java/jace/ConvertDiskImage.java b/src/main/java/jace/ConvertDiskImage.java index 1360838..2b9f165 100644 --- a/src/main/java/jace/ConvertDiskImage.java +++ b/src/main/java/jace/ConvertDiskImage.java @@ -71,10 +71,9 @@ public class ConvertDiskImage { // First read in the disk image, this decodes the disk as necessary FloppyDisk theDisk = null; try { - theDisk = new FloppyDisk(in); + theDisk = new FloppyDisk(in, null); } catch (IOException ex) { System.out.println("Couldn't read disk image"); - ex.printStackTrace(); return; } if (!writeNibblized) { diff --git a/src/main/java/jace/Emulator.java b/src/main/java/jace/Emulator.java index 1b6fc79..ddff938 100644 --- a/src/main/java/jace/Emulator.java +++ b/src/main/java/jace/Emulator.java @@ -20,7 +20,6 @@ package jace; import jace.apple2e.Apple2e; import jace.config.Configuration; -import jace.core.Computer; import jace.ui.AbstractEmulatorFrame; import jace.ui.EmulatorFrame; import java.awt.Component; @@ -57,7 +56,7 @@ public class Emulator { return null; } } - public Apple2e computer; + public static Apple2e computer; public AbstractEmulatorFrame theApp; /** @@ -91,7 +90,7 @@ public class Emulator { Configuration.applySettings(settings); // theApp = new MainFrame(); - theApp = new EmulatorFrame(); + theApp = new EmulatorFrame(computer); try { theApp.setIconImage(ImageIO.read(Emulator.class.getClassLoader().getResourceAsStream("jace/data/woz_figure.gif"))); } catch (IOException ex) { @@ -139,12 +138,12 @@ public class Emulator { @Override public void windowIconified(WindowEvent e) { - Computer.getComputer().getVideo().suspend(); + computer.getVideo().suspend(); } @Override public void windowDeiconified(WindowEvent e) { - Computer.getComputer().getVideo().resume(); + computer.getVideo().resume(); resizeVideo(); } diff --git a/src/main/java/jace/EmulatorUILogic.java b/src/main/java/jace/EmulatorUILogic.java index dea2892..4df837d 100644 --- a/src/main/java/jace/EmulatorUILogic.java +++ b/src/main/java/jace/EmulatorUILogic.java @@ -24,7 +24,6 @@ import jace.apple2e.SoftSwitches; import jace.config.ConfigurationPanel; import jace.config.InvokableAction; import jace.core.CPU; -import jace.core.Computer; import jace.core.Debugger; import jace.core.RAM; import jace.core.RAMEvent; @@ -69,7 +68,7 @@ public class EmulatorUILogic { @Override public void updateStatus() { enableDebug(true); - MOS65C02 cpu = (MOS65C02) Computer.getComputer().getCpu(); + MOS65C02 cpu = (MOS65C02) Emulator.computer.getCpu(); updateCPURegisters(cpu); } }; @@ -95,7 +94,7 @@ public class EmulatorUILogic { } public static void enableTrace(boolean b) { - Computer.getComputer().getCpu().setTraceEnabled(b); + Emulator.computer.getCpu().setTraceEnabled(b); } public static void stepForward() { @@ -103,7 +102,7 @@ public class EmulatorUILogic { } static void registerDebugger() { - Computer.getComputer().getCpu().setDebug(debugger); + Emulator.computer.getCpu().setDebug(debugger); } public static Integer getValidAddress(String s) { @@ -122,7 +121,7 @@ public class EmulatorUILogic { public static void updateWatchList(final DebuggerPanel panel) { java.awt.EventQueue.invokeLater(() -> { watches.stream().forEach((oldWatch) -> { - Computer.getComputer().getMemory().removeListener(oldWatch); + Emulator.computer.getMemory().removeListener(oldWatch); }); if (panel == null) { return; @@ -149,10 +148,10 @@ public class EmulatorUILogic { watchValue.setText(Integer.toHexString(e.getNewValue() & 0x0FF)); } }; - Computer.getComputer().getMemory().addListener(newListener); + Emulator.computer.getMemory().addListener(newListener); watches.add(newListener); // Print out the current value right away - byte b = Computer.getComputer().getMemory().readRaw(address); + byte b = Emulator.computer.getMemory().readRaw(address); watchValue.setText(Integer.toString(b & 0x0ff, 16)); } else { watchValue.setText("00"); @@ -192,12 +191,12 @@ public class EmulatorUILogic { description = "Loads a binary file in memory and executes it. File should end with #06xxxx, where xxxx is the start address in hex", alternatives = "Execute program;Load binary;Load program;Load rom;Play single-load game") public static void runFile() { - Computer.pause(); + Emulator.computer.pause(); JFileChooser select = new JFileChooser(); select.showDialog(Emulator.getFrame(), "Execute binary file"); File binary = select.getSelectedFile(); if (binary == null) { - Computer.resume(); + Emulator.computer.resume(); return; } runFile(binary); @@ -215,7 +214,7 @@ public class EmulatorUILogic { } } catch (NumberFormatException | IOException ex) { } - Computer.getComputer().getCpu().resume(); + Emulator.computer.getCpu().resume(); } public static void brun(File binary, int address) throws FileNotFoundException, IOException { @@ -223,17 +222,17 @@ public class EmulatorUILogic { // If it was not yet halted, then it is the case that the CPU is processing another opcode // So if that is the case, the program counter will need to be decremented here to compensate // TODO: Find a better mousetrap for this one -- it's an ugly hack - Computer.pause(); + Emulator.computer.pause(); FileInputStream in = new FileInputStream(binary); byte[] data = new byte[in.available()]; in.read(data); - RAM ram = Computer.getComputer().getMemory(); + RAM ram = Emulator.computer.getMemory(); for (int i = 0; i < data.length; i++) { ram.write(address + i, data[i], false, true); } - CPU cpu = Computer.getComputer().getCpu(); - Computer.getComputer().getCpu().setProgramCounter(address); - Computer.resume(); + CPU cpu = Emulator.computer.getCpu(); + Emulator.computer.getCpu().setProgramCounter(address); + Emulator.computer.resume(); } @InvokableAction( @@ -246,9 +245,9 @@ public class EmulatorUILogic { if (frame == null) { return; } - Computer.pause(); + Emulator.computer.pause(); frame.enforceIntegerRatio(); - Computer.resume(); + Emulator.computer.resume(); } @InvokableAction( @@ -271,9 +270,9 @@ public class EmulatorUILogic { if (frame == null) { return; } - Computer.pause(); + Emulator.computer.pause(); frame.toggleFullscreen(); - Computer.resume(); + Emulator.computer.resume(); } @InvokableAction( @@ -285,7 +284,7 @@ public class EmulatorUILogic { SimpleDateFormat df = new SimpleDateFormat("yyyy.MM.dd.HH.mm.ss"); String timestamp = df.format(new Date()); String type; - int start = Computer.getComputer().getVideo().getCurrentWriter().actualWriter().getYOffset(0); + int start = Emulator.computer.getVideo().getCurrentWriter().actualWriter().getYOffset(0); int len; if (start < 0x02000) { // Lo-res or double-lores @@ -302,8 +301,8 @@ public class EmulatorUILogic { } File outFile = new File("screen_" + type + "_a" + Integer.toHexString(start) + "_" + timestamp); try (FileOutputStream out = new FileOutputStream(outFile)) { - RAM128k ram = (RAM128k) Computer.getComputer().memory; - Computer.pause(); + RAM128k ram = (RAM128k) Emulator.computer.memory; + Emulator.computer.pause(); if (dres) { for (int i = 0; i < len; i++) { out.write(ram.getAuxVideoMemory().readByte(start + i)); @@ -323,8 +322,8 @@ public class EmulatorUILogic { alternatives = "Save image,save framebuffer,screenshot") public static void saveScreenshot() throws HeadlessException, IOException { JFileChooser select = new JFileChooser(); - Computer.pause(); - BufferedImage i = Computer.getComputer().getVideo().getFrameBuffer(); + Emulator.computer.pause(); + BufferedImage i = Emulator.computer.getVideo().getFrameBuffer(); BufferedImage j = new BufferedImage(i.getWidth(), i.getHeight(), i.getType()); j.getGraphics().drawImage(i, 0, 0, null); select.showSaveDialog(Emulator.getFrame()); diff --git a/src/main/java/jace/apple2e/Apple2e.java b/src/main/java/jace/apple2e/Apple2e.java index be234ab..f0f4e68 100644 --- a/src/main/java/jace/apple2e/Apple2e.java +++ b/src/main/java/jace/apple2e/Apple2e.java @@ -37,6 +37,7 @@ import jace.hardware.Joystick; import jace.hardware.massStorage.CardMassStorage; import java.awt.Graphics; import java.io.IOException; +import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.List; import java.util.logging.Level; @@ -49,13 +50,12 @@ import java.util.logging.Logger; * overall configuration of the computer, but the actual operation of the * computer and its timing characteristics are managed in the Motherboard class. * - * @author Brendan Robert (BLuRry) brendan.robert@gmail.com + * @author Brendan Robert (BLuRry) brendan.robert@gmail.com */ @Stateful public class Apple2e extends Computer { static int IRQ_VECTOR = 0x003F2; - public Motherboard motherboard; @ConfigurableField(name = "Slot 1", shortName = "s1card") public ClassSelection card1 = new ClassSelection(Card.class, null); @ConfigurableField(name = "Slot 2", shortName = "s2card") @@ -96,9 +96,9 @@ public class Apple2e extends Computer { try { reconfigure(); // Setup core resources - joystick1 = new Joystick(0); - joystick2 = new Joystick(1); - setCpu(new MOS65C02()); + joystick1 = new Joystick(0, this); + joystick2 = new Joystick(1, this); + setCpu(new MOS65C02(this)); reinitMotherboard(); } catch (Throwable t) { System.err.println("Unable to initalize virtual machine"); @@ -115,7 +115,7 @@ public class Apple2e extends Computer { if (motherboard != null && motherboard.isRunning()) { motherboard.suspend(); } - motherboard = new Motherboard(); + motherboard = new Motherboard(this); motherboard.reconfigure(); Motherboard.miscDevices.add(joystick1); Motherboard.miscDevices.add(joystick2); @@ -123,7 +123,7 @@ public class Apple2e extends Computer { @Override public void coldStart() { - Computer.pause(); + pause(); reinitMotherboard(); reboot(); //getMemory().dump(); @@ -139,7 +139,7 @@ public class Apple2e extends Computer { } } - Computer.resume(); + resume(); /* getCpu().resume(); getVideo().resume(); @@ -156,7 +156,7 @@ public class Apple2e extends Computer { @Override public void warmStart() { - boolean restart = Computer.pause(); + boolean restart = pause(); for (SoftSwitches s : SoftSwitches.values()) { s.getSwitch().reset(); } @@ -169,10 +169,10 @@ public class Apple2e extends Computer { } } getCpu().resume(); - Computer.resume(); + resume(); } - private void insertCard(Class type, int slot) { + private void insertCard(Class type, int slot) throws NoSuchMethodException, IllegalArgumentException, InvocationTargetException { if (getMemory().getCard(slot) != null) { if (getMemory().getCard(slot).getClass().equals(type)) { return; @@ -181,7 +181,8 @@ public class Apple2e extends Computer { } if (type != null) { try { - getMemory().addCard(type.newInstance(), slot); + Card card = type.getConstructor(Computer.class).newInstance(this); + getMemory().addCard(card, slot); } catch (InstantiationException | IllegalAccessException ex) { Logger.getLogger(Apple2e.class.getName()).log(Level.SEVERE, null, ex); } @@ -190,10 +191,10 @@ public class Apple2e extends Computer { @Override public final void reconfigure() { - boolean restart = Computer.pause(); + boolean restart = pause(); super.reconfigure(); - + RAM128k currentMemory = (RAM128k) getMemory(); if (currentMemory != null && !(currentMemory.getClass().equals(ramCard.getValue()))) { try { @@ -212,7 +213,7 @@ public class Apple2e extends Computer { try { setMemory(currentMemory); for (SoftSwitches s : SoftSwitches.values()) { - s.getSwitch().register(); + s.getSwitch().register(this); } } catch (Throwable ex) { } @@ -250,14 +251,18 @@ public class Apple2e extends Computer { } } - // Add all new cards - insertCard(card1.getValue(), 1); - insertCard(card2.getValue(), 2); - insertCard(card3.getValue(), 3); - insertCard(card4.getValue(), 4); - insertCard(card5.getValue(), 5); - insertCard(card6.getValue(), 6); - insertCard(card7.getValue(), 7); + try { + // Add all new cards + insertCard(card1.getValue(), 1); + insertCard(card2.getValue(), 2); + insertCard(card3.getValue(), 3); + insertCard(card4.getValue(), 4); + insertCard(card5.getValue(), 5); + insertCard(card6.getValue(), 6); + insertCard(card7.getValue(), 7); + } catch (NoSuchMethodException | IllegalArgumentException | InvocationTargetException ex) { + Logger.getLogger(Apple2e.class.getName()).log(Level.SEVERE, null, ex); + } if (enableHints) { enableHints(); } else { @@ -293,7 +298,7 @@ public class Apple2e extends Computer { Logger.getLogger(Apple2e.class.getName()).log(Level.SEVERE, null, ex); } if (restart) { - Computer.resume(); + resume(); } } @@ -342,7 +347,7 @@ public class Apple2e extends Computer { if (getCpu().getProgramCounter() >> 8 != 0x0c6) { return; } - + int row = 2; for (String s : new String[]{ " Welcome to", diff --git a/src/main/java/jace/apple2e/MOS65C02.java b/src/main/java/jace/apple2e/MOS65C02.java index a51fbf4..d3f8688 100644 --- a/src/main/java/jace/apple2e/MOS65C02.java +++ b/src/main/java/jace/apple2e/MOS65C02.java @@ -68,8 +68,12 @@ public class MOS65C02 extends CPU { @ConfigurableField(name = "Ext. opcode warnings", description = "If on, uses of 65c02 extended opcodes (or undocumented 6502 opcodes -- which will fail) will be logged to stdout for debugging purposes") public boolean warnAboutExtendedOpcodes = false; - private static RAM getMemory() { - return Computer.getComputer().getMemory(); + private RAM getMemory() { + return computer.getMemory(); + } + + public MOS65C02(Computer computer) { + super(computer); } @Override @@ -344,7 +348,7 @@ public class MOS65C02 extends CPU { default int getValue(boolean isRead, MOS65C02 cpu) { int address = calculateAddress(cpu); - return (address > -1) ? (0x0ff & getMemory().read(address, TYPE.READ_DATA, isRead, false)) : 0; + return (address > -1) ? (0x0ff & cpu.getMemory().read(address, TYPE.READ_DATA, isRead, false)) : 0; } } @@ -354,42 +358,42 @@ public class MOS65C02 extends CPU { // RELATIVE(2, "#$~1 ($R)"), RELATIVE(2, "$R", (cpu) -> { int pc = cpu.getProgramCounter(); - int address = pc + 2 + getMemory().read(pc + 1, TYPE.READ_OPERAND, cpu.readAddressTriggersEvent, false); + int address = pc + 2 + cpu.getMemory().read(pc + 1, TYPE.READ_OPERAND, cpu.readAddressTriggersEvent, false); // The wait cycles are not added unless the branch actually happens! cpu.setPageBoundaryPenalty((address & 0x00ff00) != (pc & 0x00ff00)); return address; }), IMMEDIATE(2, "#$~1", (cpu) -> cpu.getProgramCounter() + 1), - ZEROPAGE(2, "$~1", (cpu) -> getMemory().read(cpu.getProgramCounter() + 1, TYPE.READ_OPERAND, cpu.readAddressTriggersEvent, false) & 0x00FF), - ZEROPAGE_X(2, "$~1,X", (cpu) -> 0x0FF & (getMemory().read(cpu.getProgramCounter() + 1, TYPE.READ_OPERAND, cpu.readAddressTriggersEvent, false) + cpu.X)), - ZEROPAGE_Y(2, "$~1,Y", (cpu) -> 0x0FF & (getMemory().read(cpu.getProgramCounter() + 1, TYPE.READ_OPERAND, cpu.readAddressTriggersEvent, false) + cpu.Y)), + ZEROPAGE(2, "$~1", (cpu) -> cpu.getMemory().read(cpu.getProgramCounter() + 1, TYPE.READ_OPERAND, cpu.readAddressTriggersEvent, false) & 0x00FF), + ZEROPAGE_X(2, "$~1,X", (cpu) -> 0x0FF & (cpu.getMemory().read(cpu.getProgramCounter() + 1, TYPE.READ_OPERAND, cpu.readAddressTriggersEvent, false) + cpu.X)), + ZEROPAGE_Y(2, "$~1,Y", (cpu) -> 0x0FF & (cpu.getMemory().read(cpu.getProgramCounter() + 1, TYPE.READ_OPERAND, cpu.readAddressTriggersEvent, false) + cpu.Y)), INDIRECT(3, "$(~2~1)", (cpu) -> { - int address = getMemory().readWord(cpu.getProgramCounter() + 1, TYPE.READ_OPERAND, cpu.readAddressTriggersEvent, false); - return getMemory().readWord(address, TYPE.READ_DATA, true, false); + int address = cpu.getMemory().readWord(cpu.getProgramCounter() + 1, TYPE.READ_OPERAND, cpu.readAddressTriggersEvent, false); + return cpu.getMemory().readWord(address, TYPE.READ_DATA, true, false); }), INDIRECT_X(3, "$(~2~1,X)", (cpu) -> { - int address = getMemory().readWord(cpu.getProgramCounter() + 1, TYPE.READ_OPERAND, cpu.readAddressTriggersEvent, false) + cpu.X; - return getMemory().readWord(address & 0x0FFFF, TYPE.READ_DATA, true, false); + int address = cpu.getMemory().readWord(cpu.getProgramCounter() + 1, TYPE.READ_OPERAND, cpu.readAddressTriggersEvent, false) + cpu.X; + return cpu.getMemory().readWord(address & 0x0FFFF, TYPE.READ_DATA, true, false); }), INDIRECT_ZP(2, "$(~1)", (cpu) -> { - int address = getMemory().read(cpu.getProgramCounter() + 1, TYPE.READ_OPERAND, cpu.readAddressTriggersEvent, false); - return getMemory().readWord(address & 0x0FF, TYPE.READ_DATA, true, false); + int address = cpu.getMemory().read(cpu.getProgramCounter() + 1, TYPE.READ_OPERAND, cpu.readAddressTriggersEvent, false); + return cpu.getMemory().readWord(address & 0x0FF, TYPE.READ_DATA, true, false); }), INDIRECT_ZP_X(2, "$(~1,X)", (cpu) -> { - int address = getMemory().read(cpu.getProgramCounter() + 1, TYPE.READ_OPERAND, cpu.readAddressTriggersEvent, false) + cpu.X; - return getMemory().readWord(address & 0x0FF, TYPE.READ_DATA, true, false); + int address = cpu.getMemory().read(cpu.getProgramCounter() + 1, TYPE.READ_OPERAND, cpu.readAddressTriggersEvent, false) + cpu.X; + return cpu.getMemory().readWord(address & 0x0FF, TYPE.READ_DATA, true, false); }), INDIRECT_ZP_Y(2, "$(~1),Y", (cpu) -> { - int address = 0x00FF & getMemory().read(cpu.getProgramCounter() + 1, TYPE.READ_OPERAND, cpu.readAddressTriggersEvent, false); - address = getMemory().readWord(address, TYPE.READ_DATA, true, false) + cpu.Y; + int address = 0x00FF & cpu.getMemory().read(cpu.getProgramCounter() + 1, TYPE.READ_OPERAND, cpu.readAddressTriggersEvent, false); + address = cpu.getMemory().readWord(address, TYPE.READ_DATA, true, false) + cpu.Y; if ((address & 0x00ff00) > 0) { cpu.addWaitCycles(1); } return address; }), - ABSOLUTE(3, "$~2~1", (cpu) -> getMemory().readWord(cpu.getProgramCounter() + 1, TYPE.READ_OPERAND, cpu.readAddressTriggersEvent, false)), + ABSOLUTE(3, "$~2~1", (cpu) -> cpu.getMemory().readWord(cpu.getProgramCounter() + 1, TYPE.READ_OPERAND, cpu.readAddressTriggersEvent, false)), ABSOLUTE_X(3, "$~2~1,X", (cpu) -> { - int address2 = getMemory().readWord(cpu.getProgramCounter() + 1, TYPE.READ_OPERAND, cpu.readAddressTriggersEvent, false); + int address2 = cpu.getMemory().readWord(cpu.getProgramCounter() + 1, TYPE.READ_OPERAND, cpu.readAddressTriggersEvent, false); int address = 0x0FFFF & (address2 + cpu.X); if ((address & 0x00FF00) != (address2 & 0x00FF00)) { cpu.addWaitCycles(1); @@ -397,7 +401,7 @@ public class MOS65C02 extends CPU { return address; }), ABSOLUTE_Y(3, "$~2~1,Y", (cpu) -> { - int address2 = getMemory().readWord(cpu.getProgramCounter() + 1, TYPE.READ_OPERAND, cpu.readAddressTriggersEvent, false); + int address2 = cpu.getMemory().readWord(cpu.getProgramCounter() + 1, TYPE.READ_OPERAND, cpu.readAddressTriggersEvent, false); int address = 0x0FFFF & (address2 + cpu.Y); if ((address & 0x00FF00) != (address2 & 0x00FF00)) { cpu.addWaitCycles(1); @@ -407,9 +411,9 @@ public class MOS65C02 extends CPU { ZP_REL(2, "$~1,$R", new AddressCalculator() { @Override public int calculateAddress(MOS65C02 cpu) { - // Note: This is two's compliment addition and the getMemory().read() returns a signed 8-bit value + // Note: This is two's compliment addition and the cpu.getMemory().read() returns a signed 8-bit value int pc = cpu.getProgramCounter(); - int address = pc + 2 + getMemory().read(pc + 2, TYPE.READ_OPERAND, cpu.readAddressTriggersEvent, false); + int address = pc + 2 + cpu.getMemory().read(pc + 2, TYPE.READ_OPERAND, cpu.readAddressTriggersEvent, false); // The wait cycles are not added unless the branch actually happens! cpu.setPageBoundaryPenalty((address & 0x00ff00) != (pc & 0x00ff00)); return address; @@ -418,8 +422,8 @@ public class MOS65C02 extends CPU { @Override public int getValue(boolean isRead, MOS65C02 cpu) { int pc = cpu.getProgramCounter(); - int address = getMemory().read(pc + 1, TYPE.READ_OPERAND, cpu.readAddressTriggersEvent, false); - return getMemory().read(address, TYPE.READ_DATA, true, false); + int address = cpu.getMemory().read(pc + 1, TYPE.READ_OPERAND, cpu.readAddressTriggersEvent, false); + return cpu.getMemory().read(address, TYPE.READ_DATA, true, false); } }); private int size; @@ -473,16 +477,16 @@ public class MOS65C02 extends CPU { return calculator; } - public String formatMode(int pc) { + public String formatMode(int pc, MOS65C02 cpu) { if (implied) { return ""; } else { - int b1 = 0x00ff & getMemory().readRaw((pc + 1) & 0x0FFFF); + int b1 = 0x00ff & cpu.getMemory().readRaw((pc + 1) & 0x0FFFF); if (relative) { String R = wordString(pc + 2 + (byte) b1); return f1 + R; } else if (twoByte) { - int b2 = 0x00ff & getMemory().readRaw((pc + 2) & 0x0FFFF); + int b2 = 0x00ff & cpu.getMemory().readRaw((pc + 2) & 0x0FFFF); return f1 + byte2(b2) + byte2(b1) + f2; } else { return f1 + byte2(b1) + f2; @@ -548,7 +552,7 @@ public class MOS65C02 extends CPU { public void processCommand(int address, int value, MODE addressMode, MOS65C02 cpu) { int mask = 0x0ff ^ (1 << bit); value &= mask; - getMemory().write(address, (byte) value, true, false); + cpu.getMemory().write(address, (byte) value, true, false); } } @@ -564,7 +568,7 @@ public class MOS65C02 extends CPU { public void processCommand(int address, int value, MODE addressMode, MOS65C02 cpu) { int mask = 1 << bit; value |= mask; - getMemory().write(address, (byte) value, true, false); + cpu.getMemory().write(address, (byte) value, true, false); } } @@ -620,8 +624,8 @@ public class MOS65C02 extends CPU { cpu.setNZ(value); // Emulate correct behavior of fetch-store-modify // http://forum.6502.org/viewtopic.php?f=4&t=1617&view=previous - getMemory().write(address, (byte) value, true, false); - getMemory().write(address, (byte) value, true, false); + cpu.getMemory().write(address, (byte) value, true, false); + cpu.getMemory().write(address, (byte) value, true, false); }), ASL_A((address, value, addressMode, cpu) -> { cpu.C = cpu.A >> 7; @@ -738,8 +742,8 @@ public class MOS65C02 extends CPU { }), DEC((address, value, addressMode, cpu) -> { value = 0x0FF & (value - 1); - getMemory().write(address, (byte) value, true, false); - getMemory().write(address, (byte) value, true, false); + cpu.getMemory().write(address, (byte) value, true, false); + cpu.getMemory().write(address, (byte) value, true, false); cpu.setNZ(value); }), DEA((address, value, addressMode, cpu) -> { @@ -761,8 +765,8 @@ public class MOS65C02 extends CPU { INC((address, value, addressMode, cpu) -> { value = 0x0ff & (value + 1); // emulator correct fetch-modify-store behavior - getMemory().write(address, (byte) value, true, false); - getMemory().write(address, (byte) value, true, false); + cpu.getMemory().write(address, (byte) value, true, false); + cpu.getMemory().write(address, (byte) value, true, false); cpu.setNZ(value); }), INA((address, value, addressMode, cpu) -> { @@ -801,8 +805,8 @@ public class MOS65C02 extends CPU { value = (value >> 1) & 0x07F; cpu.setNZ(value); // emulator correct fetch-modify-store behavior - getMemory().write(address, (byte) value, true, false); - getMemory().write(address, (byte) value, true, false); + cpu.getMemory().write(address, (byte) value, true, false); + cpu.getMemory().write(address, (byte) value, true, false); }), LSR_A((address, value, addressMode, cpu) -> { cpu.C = cpu.A & 1; @@ -856,8 +860,8 @@ public class MOS65C02 extends CPU { value = 0x0ff & ((value << 1) | oldC); cpu.setNZ(value); // emulator correct fetch-modify-store behavior - getMemory().write(address, (byte) value, true, false); - getMemory().write(address, (byte) value, true, false); + cpu.getMemory().write(address, (byte) value, true, false); + cpu.getMemory().write(address, (byte) value, true, false); }), ROL_A((address, value, addressMode, cpu) -> { int oldC = cpu.C; @@ -871,8 +875,8 @@ public class MOS65C02 extends CPU { value = 0x0ff & ((value >> 1) | oldC); cpu.setNZ(value); // emulator correct fetch-modify-store behavior - getMemory().write(address, (byte) value, true, false); - getMemory().write(address, (byte) value, true, false); + cpu.getMemory().write(address, (byte) value, true, false); + cpu.getMemory().write(address, (byte) value, true, false); }), ROR_A((address, value, addressMode, cpu) -> { int oldC = cpu.C << 7; @@ -947,19 +951,19 @@ public class MOS65C02 extends CPU { SMB6(new SMBCommand(6)), SMB7(new SMBCommand(7)), STA(true, (address, value, addressMode, cpu) -> { - getMemory().write(address, (byte) cpu.A, true, false); + cpu.getMemory().write(address, (byte) cpu.A, true, false); }), STP((address, value, addressMode, cpu) -> { cpu.suspend(); }), STX(true, (address, value, addressMode, cpu) -> { - getMemory().write(address, (byte) cpu.X, true, false); + cpu.getMemory().write(address, (byte) cpu.X, true, false); }), STY(true, (address, value, addressMode, cpu) -> { - getMemory().write(address, (byte) cpu.Y, true, false); + cpu.getMemory().write(address, (byte) cpu.Y, true, false); }), STZ(true, (address, value, addressMode, cpu) -> { - getMemory().write(address, (byte) 0, true, false); + cpu.getMemory().write(address, (byte) 0, true, false); }), TAX((address, value, addressMode, cpu) -> { cpu.X = cpu.A; @@ -972,12 +976,12 @@ public class MOS65C02 extends CPU { TRB((address, value, addressMode, cpu) -> { cpu.C = (value & cpu.A) != 0 ? 1 : 0; value &= ~cpu.A; - getMemory().write(address, (byte) value, true, false); + cpu.getMemory().write(address, (byte) value, true, false); }), TSB((address, value, addressMode, cpu) -> { cpu.C = (value & cpu.A) != 0 ? 1 : 0; value |= cpu.A; - getMemory().write(address, (byte) value, true, false); + cpu.getMemory().write(address, (byte) value, true, false); }), TSX((address, value, addressMode, cpu) -> { cpu.X = cpu.STACK; @@ -1033,8 +1037,8 @@ public class MOS65C02 extends CPU { } int pc = getProgramCounter(); -// RAM ram = getMemory(); -// int op = 0x00ff & getMemory().read(pc, false); +// RAM ram = cpu.getMemory(); +// int op = 0x00ff & cpu.getMemory().read(pc, false); // This makes it possible to trap the memory read of an opcode, when PC == Address, you know it is executing that opcode. int op = 0x00ff & getMemory().read(pc, TYPE.EXECUTE, true, false); OPCODE opcode = opcodes[op]; @@ -1203,7 +1207,7 @@ public class MOS65C02 extends CPU { // Cold/Warm boot procedure @Override public void reset() { - boolean restart = Computer.pause(); + boolean restart = computer.pause(); pushWord(getProgramCounter()); push(getStatus()); // STACK = 0x0ff; @@ -1219,7 +1223,7 @@ public class MOS65C02 extends CPU { System.out.println("Reset called, setting PC to (" + Integer.toString(RESET_VECTOR, 16) + ") = " + Integer.toString(newPC, 16)); setProgramCounter(newPC); if (restart) { - Computer.resume(); + computer.resume(); } } @@ -1276,13 +1280,13 @@ public class MOS65C02 extends CPU { public String disassemble() { int pc = getProgramCounter(); -// RAM ram = getMemory(); +// RAM ram = cpu.getMemory(); int op = getMemory().readRaw(pc); OPCODE o = opcodes[op & 0x0ff]; if (o == null) { return "???"; } - String format = o.getMode().formatMode(pc); + String format = o.getMode().formatMode(pc, this); // format = format.replaceAll("~1", byte2(b1)); // format = format.replaceAll("~2", byte2(b2)); // format = format.replaceAll("R", R); diff --git a/src/main/java/jace/apple2e/RAM128k.java b/src/main/java/jace/apple2e/RAM128k.java index 1860d9c..441671a 100644 --- a/src/main/java/jace/apple2e/RAM128k.java +++ b/src/main/java/jace/apple2e/RAM128k.java @@ -18,6 +18,7 @@ */ package jace.apple2e; +import jace.core.CPU; import jace.core.Card; import jace.core.Computer; import jace.core.PagedMemory; @@ -44,16 +45,16 @@ abstract public class RAM128k extends RAM { public PagedMemory rom; public PagedMemory blank; - public RAM128k() { - super(); - mainMemory = new PagedMemory(0xc000, PagedMemory.Type.ram); - rom = new PagedMemory(0x3000, PagedMemory.Type.firmwareMain); - cPageRom = new PagedMemory(0x1000, PagedMemory.Type.slotRom); - languageCard = new PagedMemory(0x3000, PagedMemory.Type.languageCard); - languageCard2 = new PagedMemory(0x1000, PagedMemory.Type.languageCard); - activeRead = new PagedMemory(0x10000, PagedMemory.Type.ram); - activeWrite = new PagedMemory(0x10000, PagedMemory.Type.ram); - blank = new PagedMemory(0x100, PagedMemory.Type.ram); + public RAM128k(Computer computer) { + super(computer); + mainMemory = new PagedMemory(0xc000, PagedMemory.Type.ram, computer); + rom = new PagedMemory(0x3000, PagedMemory.Type.firmwareMain, computer); + cPageRom = new PagedMemory(0x1000, PagedMemory.Type.slotRom, computer); + languageCard = new PagedMemory(0x3000, PagedMemory.Type.languageCard, computer); + languageCard2 = new PagedMemory(0x1000, PagedMemory.Type.languageCard, computer); + activeRead = new PagedMemory(0x10000, PagedMemory.Type.ram, computer); + activeWrite = new PagedMemory(0x10000, PagedMemory.Type.ram, computer); + blank = new PagedMemory(0x100, PagedMemory.Type.ram, computer); // Format memory with FF FF 00 00 pattern for (int i = 0; i < 0x0100; i++) { @@ -191,13 +192,14 @@ abstract public class RAM128k extends RAM { } public void log(String message) { - if (Computer.getComputer().cpu != null && Computer.getComputer().cpu.isLogEnabled()) { + CPU cpu = computer.getCpu(); + if (cpu != null && cpu.isLogEnabled()) { String stack = ""; for (StackTraceElement e : Thread.currentThread().getStackTrace()) { stack += e.getClassName() + "." + e.getMethodName() + "(" + e.getLineNumber() + ");"; } - Computer.getComputer().cpu.log(stack); - Computer.getComputer().cpu.log(message + ";" + SoftSwitches.RAMRD + ";" + SoftSwitches.RAMWRT + ";" + SoftSwitches.AUXZP + ";" + SoftSwitches._80STORE + ";" + SoftSwitches.HIRES + ";" + SoftSwitches.PAGE2 + ";" + SoftSwitches.LCBANK1 + ";" + SoftSwitches.LCRAM + ";" + SoftSwitches.LCWRITE); + cpu.log(stack); + cpu.log(message + ";" + SoftSwitches.RAMRD + ";" + SoftSwitches.RAMWRT + ";" + SoftSwitches.AUXZP + ";" + SoftSwitches._80STORE + ";" + SoftSwitches.HIRES + ";" + SoftSwitches.PAGE2 + ";" + SoftSwitches.LCBANK1 + ";" + SoftSwitches.LCRAM + ";" + SoftSwitches.LCWRITE); } } diff --git a/src/main/java/jace/apple2e/SoftSwitches.java b/src/main/java/jace/apple2e/SoftSwitches.java index 1497863..4da0de1 100644 --- a/src/main/java/jace/apple2e/SoftSwitches.java +++ b/src/main/java/jace/apple2e/SoftSwitches.java @@ -65,21 +65,21 @@ public enum SoftSwitches { PAGE2(new VideoSoftSwitch("Page2", 0x0c054, 0x0c055, 0x0c01c, RAMEvent.TYPE.ANY, false) { @Override public void stateChanged() { -// if (Computer.getComputer() == null) { +// if (computer == null) { // return; // } -// if (Computer.getComputer() == null && Computer.getComputer().getMemory() == null) { +// if (computer == null && computer.getMemory() == null) { // return; // } -// if (Computer.getComputer() == null && Computer.getComputer().getVideo() == null) { +// if (computer == null && computer.getVideo() == null) { // return; // } // PAGE2 is a hybrid switch; 80STORE ? memory : video if (_80STORE.isOn()) { - Computer.getComputer().getMemory().configureActiveMemory(); + computer.getMemory().configureActiveMemory(); } else { - Computer.getComputer().getVideo().configureVideoMode(); + computer.getVideo().configureVideoMode(); } } }), @@ -127,10 +127,10 @@ public enum SoftSwitches { FLOATING_BUS(new SoftSwitch("FloatingBus", null, null, new int[]{0x0C050, 0x0C051, 0x0C052, 0x0C053, 0x0C054}, RAMEvent.TYPE.READ, null) { @Override protected byte readSwitch() { - if (Computer.getComputer().getVideo() == null) { + if (computer.getVideo() == null) { return 0; } - return Computer.getComputer().getVideo().getFloatingBus(); + return computer.getVideo().getFloatingBus(); } @Override diff --git a/src/main/java/jace/apple2e/Speaker.java b/src/main/java/jace/apple2e/Speaker.java index 9d481a8..f170709 100644 --- a/src/main/java/jace/apple2e/Speaker.java +++ b/src/main/java/jace/apple2e/Speaker.java @@ -163,7 +163,8 @@ public class Speaker extends Device { /** * Creates a new instance of Speaker */ - public Speaker() { + public Speaker(Computer computer) { + super(computer); configureListener(); reconfigure(); } @@ -189,7 +190,7 @@ public class Speaker extends Device { public void resume() { sdl = null; try { - sdl = Motherboard.mixer.getLine(this); + sdl = computer.getMotherboard().mixer.getLine(this); } catch (LineUnavailableException ex) { System.out.println("ERROR: Could not output sound: " + ex.getMessage()); } @@ -233,8 +234,9 @@ public class Speaker extends Device { } } } - Motherboard.cancelSpeedRequest(this); - Motherboard.mixer.returnLine(this); + + computer.getMotherboard().cancelSpeedRequest(this); + computer.getMotherboard().mixer.returnLine(this); } }); @@ -280,9 +282,9 @@ public class Speaker extends Device { int wait = 0; while (bufferPos >= BUFFER_SIZE) { if (wait++ > 1000) { - Computer.pause(); + computer.pause(); detach(); - Computer.resume(); + computer.resume(); Motherboard.enableSpeaker = false; gripe("Sound playback is not working properly. Check your configuration and sound system to ensure they are set up properly."); return; @@ -322,11 +324,11 @@ public class Speaker extends Device { * Add a memory event listener for C03x for capturing speaker events */ private void configureListener() { - Computer.getComputer().getMemory().addListener(listener); + computer.getMemory().addListener(listener); } private void removeListener() { - Computer.getComputer().getMemory().removeListener(listener); + computer.getMemory().removeListener(listener); } /** diff --git a/src/main/java/jace/apple2e/VideoDHGR.java b/src/main/java/jace/apple2e/VideoDHGR.java index 0e5b09d..a0c3ea4 100644 --- a/src/main/java/jace/apple2e/VideoDHGR.java +++ b/src/main/java/jace/apple2e/VideoDHGR.java @@ -70,7 +70,8 @@ public class VideoDHGR extends Video { /** * Creates a new instance of VideoDHGR */ - public VideoDHGR() { + public VideoDHGR(Computer computer) { + super(computer); hiresPage1 = new VideoWriter() { @Override public int getYOffset(int y) { @@ -292,10 +293,10 @@ public class VideoDHGR extends Video { if ((xOffset & 0x01) == 1) { return; } - int b1 = ((RAM128k) Computer.getComputer().getMemory()).getAuxVideoMemory().readByte(rowAddress + xOffset); - int b2 = ((RAM128k) Computer.getComputer().getMemory()).getMainMemory().readByte(rowAddress + xOffset); - int b3 = ((RAM128k) Computer.getComputer().getMemory()).getAuxVideoMemory().readByte(rowAddress + xOffset + 1); - int b4 = ((RAM128k) Computer.getComputer().getMemory()).getMainMemory().readByte(rowAddress + xOffset + 1); + int b1 = ((RAM128k) computer.getMemory()).getAuxVideoMemory().readByte(rowAddress + xOffset); + int b2 = ((RAM128k) computer.getMemory()).getMainMemory().readByte(rowAddress + xOffset); + int b3 = ((RAM128k) computer.getMemory()).getAuxVideoMemory().readByte(rowAddress + xOffset + 1); + int b4 = ((RAM128k) computer.getMemory()).getMainMemory().readByte(rowAddress + xOffset + 1); int useColOffset = xOffset << 1; // This shouldn't be necessary but prevents an index bounds exception when graphics modes are flipped (Race condition?) if (useColOffset >= 77) { @@ -318,8 +319,8 @@ public class VideoDHGR extends Video { if ((xOffset & 0x01) == 1) { return; } - int b1 = 0x0ff & ((RAM128k) Computer.getComputer().getMemory()).getMainMemory().readByte(rowAddress + xOffset); - int b2 = 0x0ff & ((RAM128k) Computer.getComputer().getMemory()).getMainMemory().readByte(rowAddress + xOffset + 1); + int b1 = 0x0ff & ((RAM128k) computer.getMemory()).getMainMemory().readByte(rowAddress + xOffset); + int b2 = 0x0ff & ((RAM128k) computer.getMemory()).getMainMemory().readByte(rowAddress + xOffset + 1); int dhgrWord = hgrToDhgr[(extraHalfBit && xOffset > 0) ? b1 | 0x0100 : b1][b2]; extraHalfBit = (dhgrWord & 0x10000000) != 0; showDhgr(screen, times14[xOffset], y, dhgrWord & 0xfffffff); @@ -375,7 +376,7 @@ public class VideoDHGR extends Video { } protected void displayLores(BufferedImage screen, int xOffset, int y, int rowAddress) { - int c1 = ((RAM128k) Computer.getComputer().getMemory()).getMainMemory().readByte(rowAddress + xOffset) & 0x0FF; + int c1 = ((RAM128k) computer.getMemory()).getMainMemory().readByte(rowAddress + xOffset) & 0x0FF; if ((y & 7) < 4) { c1 &= 15; } else { @@ -402,8 +403,8 @@ public class VideoDHGR extends Video { } private void displayDoubleLores(BufferedImage screen, int xOffset, int y, int rowAddress) { - int c1 = ((RAM128k) Computer.getComputer().getMemory()).getAuxVideoMemory().readByte(rowAddress + xOffset) & 0x0FF; - int c2 = ((RAM128k) Computer.getComputer().getMemory()).getMainMemory().readByte(rowAddress + xOffset) & 0x0FF; + int c1 = ((RAM128k) computer.getMemory()).getAuxVideoMemory().readByte(rowAddress + xOffset) & 0x0FF; + int c2 = ((RAM128k) computer.getMemory()).getMainMemory().readByte(rowAddress + xOffset) & 0x0FF; if ((y & 7) < 4) { c1 &= 15; c2 &= 15; @@ -549,8 +550,8 @@ public class VideoDHGR extends Video { return; } int yOffset = y & 7; - byte byte2 = ((RAM128k) Computer.getComputer().getMemory()).getMainMemory().readByte(rowAddress + xOffset + 1); - int c1 = getFontChar(((RAM128k) Computer.getComputer().getMemory()).getMainMemory().readByte(rowAddress + xOffset)); + byte byte2 = ((RAM128k) computer.getMemory()).getMainMemory().readByte(rowAddress + xOffset + 1); + int c1 = getFontChar(((RAM128k) computer.getMemory()).getMainMemory().readByte(rowAddress + xOffset)); int c2 = getFontChar(byte2); int b1 = Font.getByte(c1, yOffset); int b2 = Font.getByte(c2, yOffset); @@ -566,10 +567,10 @@ public class VideoDHGR extends Video { return; } int yOffset = y & 7; - int c1 = getFontChar(((RAM128k) Computer.getComputer().getMemory()).getAuxVideoMemory().readByte(rowAddress + xOffset)); - int c2 = getFontChar(((RAM128k) Computer.getComputer().getMemory()).getMainMemory().readByte(rowAddress + xOffset)); - int c3 = getFontChar(((RAM128k) Computer.getComputer().getMemory()).getAuxVideoMemory().readByte(rowAddress + xOffset + 1)); - int c4 = getFontChar(((RAM128k) Computer.getComputer().getMemory()).getMainMemory().readByte(rowAddress + xOffset + 1)); + int c1 = getFontChar(((RAM128k) computer.getMemory()).getAuxVideoMemory().readByte(rowAddress + xOffset)); + int c2 = getFontChar(((RAM128k) computer.getMemory()).getMainMemory().readByte(rowAddress + xOffset)); + int c3 = getFontChar(((RAM128k) computer.getMemory()).getAuxVideoMemory().readByte(rowAddress + xOffset + 1)); + int c4 = getFontChar(((RAM128k) computer.getMemory()).getMainMemory().readByte(rowAddress + xOffset + 1)); int bits = Font.getByte(c1, yOffset) | (Font.getByte(c2, yOffset) << 7) | (Font.getByte(c3, yOffset) << 14) | (Font.getByte(c4, yOffset) << 21); showBW(screen, times14[xOffset], y, bits); @@ -683,7 +684,7 @@ public class VideoDHGR extends Video { } private void registerDirtyFlagChecks() { - ((RAM128k) Computer.getComputer().getMemory()).addListener(new RAMListener(RAMEvent.TYPE.WRITE, RAMEvent.SCOPE.RANGE, RAMEvent.VALUE.ANY) { + ((RAM128k) computer.getMemory()).addListener(new RAMListener(RAMEvent.TYPE.WRITE, RAMEvent.SCOPE.RANGE, RAMEvent.VALUE.ANY) { @Override protected void doConfig() { setScopeStart(0x0400); @@ -705,7 +706,7 @@ public class VideoDHGR extends Video { } } }); - ((RAM128k) Computer.getComputer().getMemory()).addListener(new RAMListener(RAMEvent.TYPE.WRITE, RAMEvent.SCOPE.RANGE, RAMEvent.VALUE.ANY) { + ((RAM128k) computer.getMemory()).addListener(new RAMListener(RAMEvent.TYPE.WRITE, RAMEvent.SCOPE.RANGE, RAMEvent.VALUE.ANY) { @Override protected void doConfig() { setScopeStart(0x2000); diff --git a/src/main/java/jace/apple2e/VideoNTSC.java b/src/main/java/jace/apple2e/VideoNTSC.java index db5ae35..db73211 100644 --- a/src/main/java/jace/apple2e/VideoNTSC.java +++ b/src/main/java/jace/apple2e/VideoNTSC.java @@ -63,6 +63,11 @@ public class VideoNTSC extends VideoDHGR { boolean colorActive = false; int rowStart = 0; + public VideoNTSC(Computer computer) { + super(computer); + createStateListeners(); + } + @Override protected void showBW(BufferedImage screen, int xOffset, int y, int dhgrWord) { if (lastKnownY != y) { @@ -97,13 +102,13 @@ public class VideoNTSC extends VideoDHGR { pos = rowStart = divBy28[xOffset]; colorActive = true; } - int c1 = ((RAM128k) Computer.getComputer().getMemory()).getMainMemory().readByte(rowAddress + xOffset) & 0x0FF; + int c1 = ((RAM128k) computer.getMemory()).getMainMemory().readByte(rowAddress + xOffset) & 0x0FF; if ((y & 7) < 4) { c1 &= 15; } else { c1 >>= 4; } - int c2 = ((RAM128k) Computer.getComputer().getMemory()).getMainMemory().readByte(rowAddress + xOffset + 1) & 0x0FF; + int c2 = ((RAM128k) computer.getMemory()).getMainMemory().readByte(rowAddress + xOffset + 1) & 0x0FF; if ((y & 7) < 4) { c2 &= 15; } else { @@ -346,9 +351,9 @@ public class VideoNTSC extends VideoDHGR { // System.out.println(state + ": "+ graphicsMode); } // These catch changes to the RGB mode to toggle between color, BW and mixed - static final Set rgbStateListeners = new HashSet<>(); + Set rgbStateListeners = new HashSet<>(); - static { + private void createStateListeners() { rgbStateListeners.add(new RAMListener(RAMEvent.TYPE.ANY, RAMEvent.SCOPE.ADDRESS, RAMEvent.VALUE.ANY) { @Override protected void doConfig() { @@ -357,7 +362,7 @@ public class VideoNTSC extends VideoDHGR { @Override protected void doEvent(RAMEvent e) { - Video v = Computer.getComputer().getVideo(); + Video v = computer.getVideo(); if (v instanceof VideoNTSC) { ((VideoNTSC) v).rgbStateChange(ModeStateChanges.CLEAR_AN3); } @@ -371,7 +376,7 @@ public class VideoNTSC extends VideoDHGR { @Override protected void doEvent(RAMEvent e) { - Video v = Computer.getComputer().getVideo(); + Video v = computer.getVideo(); if (v instanceof VideoNTSC) { ((VideoNTSC) v).rgbStateChange(ModeStateChanges.SET_AN3); } @@ -385,7 +390,7 @@ public class VideoNTSC extends VideoDHGR { @Override protected void doEvent(RAMEvent e) { - Video v = Computer.getComputer().getVideo(); + Video v = computer.getVideo(); if (v instanceof VideoNTSC) { // When reset hook is called, reset the graphics mode // This is useful in case a program is running that @@ -405,21 +410,19 @@ public class VideoNTSC extends VideoDHGR { @Override protected void doEvent(RAMEvent e) { - Video v = Computer.getComputer().getVideo(); + Video v = computer.getVideo(); if (v instanceof VideoNTSC) { ((VideoNTSC) v).rgbStateChange(ModeStateChanges.SET_80); } } }); - - } @Override public void detach() { super.detach(); rgbStateListeners.stream().forEach((l) -> { - Computer.getComputer().getMemory().removeListener(l); + computer.getMemory().removeListener(l); }); } @@ -427,7 +430,7 @@ public class VideoNTSC extends VideoDHGR { public void attach() { super.attach(); rgbStateListeners.stream().forEach((l) -> { - Computer.getComputer().getMemory().addListener(l); + computer.getMemory().addListener(l); }); } } diff --git a/src/main/java/jace/apple2e/softswitch/IntC8SoftSwitch.java b/src/main/java/jace/apple2e/softswitch/IntC8SoftSwitch.java index 950dfd2..58e11cb 100644 --- a/src/main/java/jace/apple2e/softswitch/IntC8SoftSwitch.java +++ b/src/main/java/jace/apple2e/softswitch/IntC8SoftSwitch.java @@ -76,8 +76,8 @@ public class IntC8SoftSwitch extends SoftSwitch { @Override public void stateChanged() { - if (Computer.getComputer().getMemory() != null) { - Computer.getComputer().getMemory().configureActiveMemory(); + if (computer.getMemory() != null) { + computer.getMemory().configureActiveMemory(); } } } \ No newline at end of file diff --git a/src/main/java/jace/apple2e/softswitch/MemorySoftSwitch.java b/src/main/java/jace/apple2e/softswitch/MemorySoftSwitch.java index 16a95f7..81bad9e 100644 --- a/src/main/java/jace/apple2e/softswitch/MemorySoftSwitch.java +++ b/src/main/java/jace/apple2e/softswitch/MemorySoftSwitch.java @@ -40,8 +40,8 @@ public class MemorySoftSwitch extends SoftSwitch { public void stateChanged() { // System.out.println(getName()+ " was switched to "+getState()); - if (Computer.getComputer().getMemory() != null) { - Computer.getComputer().getMemory().configureActiveMemory(); + if (computer.getMemory() != null) { + computer.getMemory().configureActiveMemory(); } } diff --git a/src/main/java/jace/apple2e/softswitch/VideoSoftSwitch.java b/src/main/java/jace/apple2e/softswitch/VideoSoftSwitch.java index 36c81e2..924be07 100644 --- a/src/main/java/jace/apple2e/softswitch/VideoSoftSwitch.java +++ b/src/main/java/jace/apple2e/softswitch/VideoSoftSwitch.java @@ -40,8 +40,8 @@ public class VideoSoftSwitch extends SoftSwitch { public void stateChanged() { // System.out.println("Set "+getName()+" -> "+getState()); - if (Computer.getComputer().getVideo() != null) { - Computer.getComputer().getVideo().configureVideoMode(); + if (computer.getVideo() != null) { + computer.getVideo().configureVideoMode(); } } diff --git a/src/main/java/jace/cheat/Cheats.java b/src/main/java/jace/cheat/Cheats.java index 4e0a970..c922d66 100644 --- a/src/main/java/jace/cheat/Cheats.java +++ b/src/main/java/jace/cheat/Cheats.java @@ -30,18 +30,22 @@ import java.util.Set; * @author Brendan Robert (BLuRry) brendan.robert@gmail.com */ public abstract class Cheats extends Device { - Set listeners = new HashSet(); + Set listeners = new HashSet<>(); + + public Cheats(Computer computer) { + super(computer); + } public void addCheat(RAMListener l) { listeners.add(l); - Computer.getComputer().getMemory().addListener(l); + computer.getMemory().addListener(l); } @Override public void detach() { - for (RAMListener l : listeners) { - Computer.getComputer().getMemory().removeListener(l); - } + listeners.stream().forEach((l) -> { + computer.getMemory().removeListener(l); + }); listeners.clear(); } @@ -51,6 +55,7 @@ public abstract class Cheats extends Device { attach(); } + @Override public String getShortName() { return "cheat"; } diff --git a/src/main/java/jace/cheat/MemorySpyGrid.java b/src/main/java/jace/cheat/MemorySpyGrid.java index 74ea72f..2a1049d 100644 --- a/src/main/java/jace/cheat/MemorySpyGrid.java +++ b/src/main/java/jace/cheat/MemorySpyGrid.java @@ -18,7 +18,7 @@ */ package jace.cheat; -import jace.core.Computer; +import jace.Emulator; import jace.core.RAM; import jace.core.RAMEvent; import jace.core.RAMEvent.TYPE; @@ -56,17 +56,14 @@ public class MemorySpyGrid extends javax.swing.JPanel { gradient = bwGradient; } // This is used primarily during scroll events to repaint the whole area - ChangeListener viewportChangeListener = new ChangeListener() { - @Override - public void stateChanged(ChangeEvent e) { - repaint(); - } + ChangeListener viewportChangeListener = (ChangeEvent e) -> { + repaint(); }; @Override public void validate() { super.validate(); - if (Computer.getComputer() != null) { + if (Emulator.computer != null) { adjustSize(); } if (getParent() != null) { @@ -92,7 +89,7 @@ public class MemorySpyGrid extends javax.swing.JPanel { } } } else { - RAM ram = Computer.getComputer().getMemory(); + RAM ram = Emulator.computer.getMemory(); for (int a = startAddress; a <= endAddress; a++) { drawValue(a, ram.readRaw(a) & 0x0ff, (Graphics2D) g); } @@ -198,35 +195,31 @@ public class MemorySpyGrid extends javax.swing.JPanel { if (mousePresent) { final int addr = convertXYtoAddr(mouseX, mouseY); if (addr >= 0) { - final int value = Computer.getComputer().getMemory().readRaw(addr) & 0x0ff; - java.awt.EventQueue.invokeLater(new Runnable() { - public void run() { - Integer lastChange = setBy.get(addr); - Integer lastRead = readBy.get(addr); - char c1 = (char) Math.max(32, value & 0x07f); - char c2 = (char) (64 + (value % 32)); - char c3 = (char) (32 + (value % 96)); - - status.setText("$" - + spaceFill(Integer.toHexString(addr), 4) + ": " - + spaceFill(String.valueOf(value), 3) + " ($" - + spaceFill(Integer.toHexString(value), 2) + ") " + c1 + " " + c2 + " " + c3 - + (lastChange != null - ? " Written by $" - + spaceFill(Integer.toHexString(lastChange), 4) - : "") - + (lastRead != null - ? " Read by $" - + spaceFill(Integer.toHexString(lastRead), 4) - : "")); - } + final int value = Emulator.computer.getMemory().readRaw(addr) & 0x0ff; + java.awt.EventQueue.invokeLater(() -> { + Integer lastChange = setBy.get(addr); + Integer lastRead = readBy.get(addr); + char c1 = (char) Math.max(32, value & 0x07f); + char c2 = (char) (64 + (value % 32)); + char c3 = (char) (32 + (value % 96)); + + status.setText("$" + + spaceFill(Integer.toHexString(addr), 4) + ": " + + spaceFill(String.valueOf(value), 3) + " ($" + + spaceFill(Integer.toHexString(value), 2) + ") " + c1 + " " + c2 + " " + c3 + + (lastChange != null + ? " Written by $" + + spaceFill(Integer.toHexString(lastChange), 4) + : "") + + (lastRead != null + ? " Read by $" + + spaceFill(Integer.toHexString(lastRead), 4) + : "")); }); } } else { - java.awt.EventQueue.invokeLater(new Runnable() { - public void run() { - status.setText("Nothing selected"); - } + java.awt.EventQueue.invokeLater(() -> { + status.setText("Nothing selected"); }); } } @@ -274,20 +267,17 @@ public class MemorySpyGrid extends javax.swing.JPanel { } public void recalibrate() { - java.awt.EventQueue.invokeLater(new Runnable() { - @Override - public void run() { - stopDisplay(); - int size = endAddress - startAddress + 1; - int width = getParent().getWidth(); - columns = ((width / zoomAmount) / 16) * 16; - int height = ((size / columns) + 1) * zoomAmount; - setSize(width, height); - setPreferredSize(new Dimension(width, height)); - getParent().validate(); - repaint(); - startDisplay(); - } + java.awt.EventQueue.invokeLater(() -> { + stopDisplay(); + int size = endAddress - startAddress + 1; + int width1 = getParent().getWidth(); + columns = ((width1 / zoomAmount) / 16) * 16; + int height1 = ((size / columns) + 1) * zoomAmount; + setSize(width1, height1); + setPreferredSize(new Dimension(width1, height1)); + getParent().validate(); + repaint(); + startDisplay(); }); } @@ -322,17 +312,17 @@ public class MemorySpyGrid extends javax.swing.JPanel { static int ACTIVITY_DECREMENT = 5; static int ACTIVITY_MAX = 255; RAMListener memoryListener = null; - Map readActivity = new ConcurrentHashMap(); - Map writeActivity = new ConcurrentHashMap(); - Map pcActivity = new ConcurrentHashMap(); - Set activeRam = new ConcurrentSkipListSet(); - Map valueActivity = new ConcurrentHashMap(); - Map setBy = new ConcurrentHashMap(); - Map readBy = new ConcurrentHashMap(); + Map readActivity = new ConcurrentHashMap<>(); + Map writeActivity = new ConcurrentHashMap<>(); + Map pcActivity = new ConcurrentHashMap<>(); + Set activeRam = new ConcurrentSkipListSet<>(); + Map valueActivity = new ConcurrentHashMap<>(); + Map setBy = new ConcurrentHashMap<>(); + Map readBy = new ConcurrentHashMap<>(); void startDisplay() { if (memoryListener != null) { - Computer.getComputer().getMemory().removeListener(memoryListener); + Emulator.computer.getMemory().removeListener(memoryListener); memoryListener = null; } isDisplayActive = true; @@ -349,7 +339,7 @@ public class MemorySpyGrid extends javax.swing.JPanel { if (addr < startAddress || addr > endAddress) { return; } - int pc = Computer.getComputer().getCpu().programCounter; + int pc = Emulator.computer.getCpu().programCounter; if (e.getType() == TYPE.EXECUTE || e.getType() == TYPE.READ_OPERAND) { if (pcActivity.containsKey(addr)) { pcActivity.put(addr, Math.min(ACTIVITY_MAX, getInt(pcActivity.get(addr)) + ACTIVITY_INCREMENT)); @@ -375,73 +365,70 @@ public class MemorySpyGrid extends javax.swing.JPanel { activeRam.add(addr); } }; - Computer.getComputer().getMemory().addListener(memoryListener); - redrawThread = new Thread(new Runnable() { - @Override - public void run() { - if (mode == Modes.ACTIVITY) { - // Activity heatmap mode - while (isDisplayActive) { - updateDetails(); - Graphics2D g = (Graphics2D) getGraphics(); - for (Iterator i = activeRam.iterator(); i.hasNext();) { - boolean remove = true; - int addr = i.next(); - int read = getInt(readActivity.get(addr)); - if (read <= 0) { - read = 0; - } else { - remove = false; - readActivity.put(addr, read - ACTIVITY_DECREMENT); - } - int write = getInt(writeActivity.get(addr)); - if (write <= 0) { - write = 0; - } else { - remove = false; - writeActivity.put(addr, write - ACTIVITY_DECREMENT); - } - int pc = getInt(pcActivity.get(addr)); - if (pc <= 0) { - pc = 0; - } else { - remove = false; - pcActivity.put(addr, pc - ACTIVITY_DECREMENT); - } - - if (remove) { - i.remove(); - pcActivity.remove(addr); - writeActivity.remove(addr); - readActivity.remove(addr); - } - - drawActivity(addr, write, read, pc, g); + Emulator.computer.getMemory().addListener(memoryListener); + redrawThread = new Thread(() -> { + if (mode == Modes.ACTIVITY) { + // Activity heatmap mode + while (isDisplayActive) { + updateDetails(); + Graphics2D g = (Graphics2D) getGraphics(); + for (Iterator i = activeRam.iterator(); i.hasNext();) { + boolean remove = true; + int addr = i.next(); + int read = getInt(readActivity.get(addr)); + if (read <= 0) { + read = 0; + } else { + remove = false; + readActivity.put(addr, read - ACTIVITY_DECREMENT); } - g.dispose(); - try { - Thread.sleep(UPDATE_INTERVAL); - } catch (InterruptedException ex) { - Logger.getLogger(MemorySpyGrid.class.getName()).log(Level.SEVERE, null, ex); + int write = getInt(writeActivity.get(addr)); + if (write <= 0) { + write = 0; + } else { + remove = false; + writeActivity.put(addr, write - ACTIVITY_DECREMENT); } - } - } else { - // Redraw value, no activity counts needed - while (isDisplayActive) { - updateDetails(); - Graphics2D g = (Graphics2D) getGraphics(); - for (Iterator i = valueActivity.keySet().iterator(); i.hasNext();) { - int addr = i.next(); - int value = getInt(valueActivity.get(addr)); + int pc = getInt(pcActivity.get(addr)); + if (pc <= 0) { + pc = 0; + } else { + remove = false; + pcActivity.put(addr, pc - ACTIVITY_DECREMENT); + } + + if (remove) { i.remove(); - drawValue(addr, value, g); - } - g.dispose(); - try { - Thread.sleep(UPDATE_INTERVAL); - } catch (InterruptedException ex) { - Logger.getLogger(MemorySpyGrid.class.getName()).log(Level.SEVERE, null, ex); + pcActivity.remove(addr); + writeActivity.remove(addr); + readActivity.remove(addr); } + + drawActivity(addr, write, read, pc, g); + } + g.dispose(); + try { + Thread.sleep(UPDATE_INTERVAL); + } catch (InterruptedException ex) { + Logger.getLogger(MemorySpyGrid.class.getName()).log(Level.SEVERE, null, ex); + } + } + } else { + // Redraw value, no activity counts needed + while (isDisplayActive) { + updateDetails(); + Graphics2D g = (Graphics2D) getGraphics(); + for (Iterator i = valueActivity.keySet().iterator(); i.hasNext();) { + int addr = i.next(); + int value = getInt(valueActivity.get(addr)); + i.remove(); + drawValue(addr, value, g); + } + g.dispose(); + try { + Thread.sleep(UPDATE_INTERVAL); + } catch (InterruptedException ex) { + Logger.getLogger(MemorySpyGrid.class.getName()).log(Level.SEVERE, null, ex); } } } @@ -453,7 +440,7 @@ public class MemorySpyGrid extends javax.swing.JPanel { void stopDisplay() { isDisplayActive = false; if (memoryListener != null) { - Computer.getComputer().getMemory().removeListener(memoryListener); + Emulator.computer.getMemory().removeListener(memoryListener); memoryListener = null; } if (redrawThread != null && redrawThread.isAlive()) { diff --git a/src/main/java/jace/cheat/MetaCheats.java b/src/main/java/jace/cheat/MetaCheats.java index 592a24f..7221cf7 100644 --- a/src/main/java/jace/cheat/MetaCheats.java +++ b/src/main/java/jace/cheat/MetaCheats.java @@ -44,16 +44,16 @@ public class MetaCheats extends Cheats { // This is used to help the handler exit faster when there is nothing to do boolean noCheats = true; - public MetaCheats() { - super(); + public MetaCheats(Computer computer) { + super(computer); singleton = this; } - Map holdBytes = new TreeMap(); - Map holdWords = new TreeMap(); - Set disabled = new HashSet(); - Map results = new TreeMap(); + Map holdBytes = new TreeMap<>(); + Map holdWords = new TreeMap<>(); + Set disabled = new HashSet<>(); + Map results = new TreeMap<>(); @Override protected String getDeviceName() { return "Meta-cheat engine"; @@ -80,7 +80,7 @@ public class MetaCheats extends Cheats { Logger.getLogger(MetaCheats.class.getName()).log(Level.SEVERE, null, ex); } - RAM128k ram = (RAM128k) Computer.getComputer().getMemory(); + RAM128k ram = (RAM128k) computer.getMemory(); DefaultTableModel model = (DefaultTableModel) form.resultsTable.getModel(); if (results.size() > MAX_RESULTS_SHOWN) { model.setRowCount(0); @@ -90,8 +90,8 @@ public class MetaCheats extends Cheats { boolean useWord = form.searchForWord.isSelected(); if (model.getRowCount() != results.size()) { model.setRowCount(0); - List iter = new ArrayList(results.keySet()); - for (Integer i : iter) { + List iter = new ArrayList<>(results.keySet()); + iter.stream().forEach((i) -> { int val = results.get(i); if (useWord) { int current = ram.readWordRaw(i) & 0x0ffff; @@ -100,9 +100,9 @@ public class MetaCheats extends Cheats { int current = ram.readRaw(i) & 0x0ff; model.addRow(new Object[]{hex(i, 4), val + " ("+hex(val,2)+")", current + " ("+hex(current,2)+")"}); } - } + }); } else { - List iter = new ArrayList(results.keySet()); + List iter = new ArrayList<>(results.keySet()); for (int i=0; i < iter.size(); i++) { int val = results.get(iter.get(i)); if (useWord) { @@ -131,18 +131,18 @@ public class MetaCheats extends Cheats { noCheats = holdBytes.isEmpty() && holdWords.isEmpty() && disabled.isEmpty(); DefaultTableModel model = (DefaultTableModel) form.activeCheatsTable.getModel(); model.setRowCount(0); - for (Integer i : holdBytes.keySet()) { + holdBytes.keySet().stream().forEach((i) -> { String loc = hex(i, 4); if (disabled.contains(i)) loc += " (off)"; int val = holdBytes.get(i); model.addRow(new Object[]{loc, val + " ("+hex(val,2)+")"}); - } - for (Integer i : holdWords.keySet()) { + }); + holdWords.keySet().stream().forEach((i) -> { String loc = hex(i, 4); if (disabled.contains(i)) loc += " (off)"; int val = holdWords.get(i); model.addRow(new Object[]{loc, val + " ("+hex(val,4)+")"}); - } + }); } public void showCheatForm() { if (form == null) { @@ -191,11 +191,8 @@ public class MetaCheats extends Cheats { if (results.isEmpty()) return; if (results.size() > MAX_RESULTS_SHOWN || isDrawing) return; if (results.containsKey(e.getAddress()) || results.containsKey(e.getAddress()-1)) { - Thread t = new Thread(new Runnable() { - @Override - public void run() { - redrawResults(); - } + Thread t = new Thread(() -> { + redrawResults(); }); t.setName("Metacheat results updater"); t.start(); @@ -258,7 +255,7 @@ public class MetaCheats extends Cheats { } void performSearch(boolean useDeltaSearch, boolean searchForByteValues, int val) { - RAM128k ram = (RAM128k) Computer.getComputer().getMemory(); + RAM128k ram = (RAM128k) computer.getMemory(); if (results.isEmpty()) { int max = 0x010000; if (!searchForByteValues) max--; @@ -272,8 +269,8 @@ public class MetaCheats extends Cheats { } } } else { - Set remove = new HashSet(); - for (Integer i : results.keySet()) { + Set remove = new HashSet<>(); + results.keySet().stream().forEach((i) -> { int v = searchForByteValues ? ram.readRaw(i) & 0x0ff : ram.readWordRaw(i) & 0x0ffff; if (useDeltaSearch) { if (v - results.get(i) != val) { @@ -288,10 +285,10 @@ public class MetaCheats extends Cheats { results.put(i,v); } } - } - for (Integer i : remove) { + }); + remove.stream().forEach((i) -> { results.remove(i); - } + }); } form.resultsStatusLabel.setText("Search found "+results.size()+" result(s)."); redrawResults(); @@ -308,7 +305,7 @@ public class MetaCheats extends Cheats { } void addWatches(int addrStart, int addrEnd) { - RAM128k ram = (RAM128k) Computer.getComputer().getMemory(); + RAM128k ram = (RAM128k) computer.getMemory(); if (form == null) return; boolean searchForByteValues = form.searchForByte.isSelected(); for (int i = addrStart; i <= addrEnd; i = i + (searchForByteValues ? 1 : 2)) { diff --git a/src/main/java/jace/cheat/PrinceOfPersiaCheats.java b/src/main/java/jace/cheat/PrinceOfPersiaCheats.java index ab2eece..639e37f 100644 --- a/src/main/java/jace/cheat/PrinceOfPersiaCheats.java +++ b/src/main/java/jace/cheat/PrinceOfPersiaCheats.java @@ -109,11 +109,11 @@ public class PrinceOfPersiaCheats extends Cheats implements MouseListener { public static int LinkMap = 0x0bda0; public static int Map = 0x0bea0; public static int MapInfo = 0x0bf00; - public static int RedBufs = 0x05e00; - public static int RedBuf = RedBufs + 90; + public static final int RedBufs = 0x05e00; + public static final int RedBuf = RedBufs + 90; // Source: https://github.com/jmechner/Prince-of-Persia-Apple-II/blob/master/01%20POP%20Source/Source/EQ.S - public static int WipeBuf = RedBuf + 90; - public static int MoveBuf = WipeBuf + 30; + public static final int WipeBuf = RedBuf + 90; + public static final int MoveBuf = WipeBuf + 30; // Object types // Source: https://github.com/jmechner/Prince-of-Persia-Apple-II/blob/master/01%20POP%20Source/Source/MOVEDATA.S public static int space = 0; @@ -149,6 +149,10 @@ public class PrinceOfPersiaCheats extends Cheats implements MouseListener { // This is the correct value for an open exit door. public static int ExitOpen = 172; + public PrinceOfPersiaCheats(Computer computer) { + super(computer); + } + @Override protected String getDeviceName() { return ("Prince of Persia"); @@ -317,7 +321,7 @@ public class PrinceOfPersiaCheats extends Cheats implements MouseListener { // and 198-255 offscreen to the right. // System.out.println("Clicked on " + col + "," + row + " -- screen " + (x * 280) + "," + (y * 192)); - RAM128k mem = (RAM128k) Computer.getComputer().getMemory(); + RAM128k mem = (RAM128k) computer.getMemory(); PagedMemory auxMem = mem.getAuxMemory(); if (me.getButton() == MouseEvent.BUTTON1) { @@ -363,7 +367,7 @@ public class PrinceOfPersiaCheats extends Cheats implements MouseListener { * @param direction */ public void performAction(int row, int col, int direction) { - RAM128k mem = (RAM128k) Computer.getComputer().getMemory(); + RAM128k mem = (RAM128k) computer.getMemory(); PagedMemory auxMem = mem.getAuxMemory(); byte currentScrn = auxMem.readByte(KidScrn); if (col < 0) { diff --git a/src/main/java/jace/config/Configuration.java b/src/main/java/jace/config/Configuration.java index bced959..c9a2664 100644 --- a/src/main/java/jace/config/Configuration.java +++ b/src/main/java/jace/config/Configuration.java @@ -18,6 +18,7 @@ */ package jace.config; +import jace.Emulator; import jace.core.Computer; import jace.core.Utility; import java.io.File; @@ -181,7 +182,7 @@ public class Configuration implements Reconfigurable { } } public final static ConfigNode BASE; - public static Computer emulator = Computer.getComputer(); + public static Computer emulator = Emulator.computer; @ConfigurableField(name = "Autosave Changes", description = "If unchecked, changes are only saved when the Save button is pressed.") public static boolean saveAutomatically = false; @@ -341,7 +342,7 @@ public class Configuration implements Reconfigurable { public static boolean applySettings(ConfigNode node) { boolean resume = false; if (node == BASE) { - resume = Computer.pause(); + resume = Emulator.computer.pause(); } boolean hasChanged = false; if (node.changed) { @@ -360,7 +361,7 @@ public class Configuration implements Reconfigurable { } if (resume) { - Computer.resume(); + Emulator.computer.resume(); } return hasChanged; diff --git a/src/main/java/jace/config/ConfigurationPanel.java b/src/main/java/jace/config/ConfigurationPanel.java index 5891952..34ba6a0 100644 --- a/src/main/java/jace/config/ConfigurationPanel.java +++ b/src/main/java/jace/config/ConfigurationPanel.java @@ -18,6 +18,7 @@ */ package jace.config; +import jace.Emulator; import jace.apple2e.Apple2e; import jace.config.Configuration.ConfigNode; import java.awt.Component; @@ -42,8 +43,7 @@ import javax.swing.JTree; public class ConfigurationPanel extends javax.swing.JPanel { public static void main(String... args) { - new Apple2e(); - Apple2e.getComputer().reconfigure(); + Emulator.computer.reconfigure(); Configuration.loadSettings(); JFrame f = new JFrame(); f.setContentPane(new ConfigurationPanel()); diff --git a/src/main/java/jace/core/CPU.java b/src/main/java/jace/core/CPU.java index 577a063..543a399 100644 --- a/src/main/java/jace/core/CPU.java +++ b/src/main/java/jace/core/CPU.java @@ -34,12 +34,10 @@ import java.util.logging.Logger; */ public abstract class CPU extends Device { - /** - * Creates a new instance of CPU - */ - public CPU() { + public CPU(Computer computer) { + super(computer); } - + @Override public String getShortName() { return "cpu"; @@ -74,11 +72,11 @@ public abstract class CPU extends Device { } public void dumpTrace() { - Computer.pause(); + computer.pause(); ArrayList newLog = new ArrayList<>(); ArrayList log = traceLog; traceLog = newLog; - Computer.resume(); + computer.resume(); System.out.println("Most recent " + traceLength + " instructions:"); log.stream().forEach((s) -> { System.out.println(s); diff --git a/src/main/java/jace/core/Card.java b/src/main/java/jace/core/Card.java index 17c8273..e2ec510 100644 --- a/src/main/java/jace/core/Card.java +++ b/src/main/java/jace/core/Card.java @@ -45,9 +45,10 @@ public abstract class Card extends Device { /** * Creates a new instance of Card */ - public Card() { - cxRom = new PagedMemory(0x0100, PagedMemory.Type.cardFirmware); - c8Rom = new PagedMemory(0x0800, PagedMemory.Type.cardFirmware); + public Card(Computer computer) { + super(computer); + cxRom = new PagedMemory(0x0100, PagedMemory.Type.cardFirmware, computer); + c8Rom = new PagedMemory(0x0800, PagedMemory.Type.cardFirmware, computer); } @Override @@ -68,11 +69,13 @@ public abstract class Card extends Device { RAMEvent.TYPE.ANY, RAMEvent.SCOPE.RANGE, RAMEvent.VALUE.ANY) { + @Override protected void doConfig() { setScopeStart(slot * 16 + 0x00c080); setScopeEnd(slot * 16 + 0x00c08F); } + @Override protected void doEvent(RAMEvent e) { int address = e.getAddress() & 0x0f; handleIOAccess(address, e.getType(), e.getNewValue(), e); @@ -83,13 +86,15 @@ public abstract class Card extends Device { RAMEvent.TYPE.ANY, RAMEvent.SCOPE.RANGE, RAMEvent.VALUE.ANY) { + @Override protected void doConfig() { setScopeStart(slot * 256 + 0x00c000); setScopeEnd(slot * 256 + 0x00c0ff); } + @Override protected void doEvent(RAMEvent e) { - Computer.getComputer().getMemory().setActiveCard(slot); + computer.getMemory().setActiveCard(slot); if (SoftSwitches.CXROM.getState()) { return; } @@ -108,7 +113,7 @@ public abstract class Card extends Device { protected void doEvent(RAMEvent e) { if (SoftSwitches.CXROM.getState() - || Computer.getComputer().getMemory().getActiveSlot() != getSlot() + || computer.getMemory().getActiveSlot() != getSlot() || SoftSwitches.INTC8ROM.getState()) { return; } @@ -116,17 +121,17 @@ public abstract class Card extends Device { } }; - Computer.getComputer().getMemory().addListener(ioListener); - Computer.getComputer().getMemory().addListener(firmwareListener); - Computer.getComputer().getMemory().addListener(c8firmwareListener); + computer.getMemory().addListener(ioListener); + computer.getMemory().addListener(firmwareListener); + computer.getMemory().addListener(c8firmwareListener); } @Override public void detach() { suspend(); - Computer.getComputer().getMemory().removeListener(ioListener); - Computer.getComputer().getMemory().removeListener(firmwareListener); - Computer.getComputer().getMemory().removeListener(c8firmwareListener); + computer.getMemory().removeListener(ioListener); + computer.getMemory().removeListener(firmwareListener); + computer.getMemory().removeListener(c8firmwareListener); } abstract protected void handleIOAccess(int register, RAMEvent.TYPE type, int value, RAMEvent e); diff --git a/src/main/java/jace/core/Computer.java b/src/main/java/jace/core/Computer.java index 3fa411e..071ec5e 100644 --- a/src/main/java/jace/core/Computer.java +++ b/src/main/java/jace/core/Computer.java @@ -35,12 +35,12 @@ import java.io.IOException; */ public abstract class Computer implements Reconfigurable { - static private Computer theComputer; public RAM memory; public CPU cpu; public Video video; public Keyboard keyboard; public StateManager stateManager; + public Motherboard motherboard; public MediaLibrary mediaLibrary = MediaLibrary.getInstance(); @ConfigurableField(category = "advanced", name = "State management", shortName = "rewind", description = "This enables rewind support, but consumes a lot of memory when active.") public boolean enableStateManager; @@ -49,7 +49,6 @@ public abstract class Computer implements Reconfigurable { * Creates a new instance of Computer */ public Computer() { - theComputer = this; keyboard = new Keyboard(); } @@ -57,6 +56,10 @@ public abstract class Computer implements Reconfigurable { return memory; } + public Motherboard getMotherboard() { + return motherboard; + } + public void notifyVBLStateChanged(boolean state) { for (Card c : getMemory().cards) { if (c == null) { @@ -105,22 +108,18 @@ public abstract class Computer implements Reconfigurable { @InvokableAction( name = "Cold boot", - description = "Process startup sequence from power-up", - category = "general", - alternatives = "Full reset;reset emulator") + description = "Process startup sequence from power-up", + category = "general", + alternatives = "Full reset;reset emulator") public abstract void coldStart(); @InvokableAction( name = "Warm boot", - description = "Process user-initatiated reboot (ctrl+apple+reset)", - category = "general", - alternatives = "reboot;reset;three-finger-salute") + description = "Process user-initatiated reboot (ctrl+apple+reset)", + category = "general", + alternatives = "reboot;reset;three-finger-salute") public abstract void warmStart(); - static public Computer getComputer() { - return theComputer; - } - public Keyboard getKeyboard() { return this.keyboard; } @@ -132,28 +131,24 @@ public abstract class Computer implements Reconfigurable { protected abstract void doResume(); @InvokableAction(name = "Pause", description = "Stops the computer, allowing reconfiguration of core elements", alternatives = "freeze;halt") - public static boolean pause() { - boolean result = false; - if (theComputer != null) { - result = theComputer.isRunning(); - theComputer.doPause(); - } + public boolean pause() { + boolean result = isRunning(); + doPause(); return result; } @InvokableAction(name = "Resume", description = "Resumes the computer if it was previously paused", alternatives = "unpause;unfreeze;resume") - public static void resume() { - if (theComputer != null) { - theComputer.doResume(); - } + public void resume() { + doResume(); } + @Override public void reconfigure() { if (enableStateManager) { - stateManager = StateManager.getInstance(); + stateManager = StateManager.getInstance(this); } else { stateManager = null; - StateManager.getInstance().invalidate(); + StateManager.getInstance(this).invalidate(); } } } diff --git a/src/main/java/jace/core/Device.java b/src/main/java/jace/core/Device.java index 120d381..f362a96 100644 --- a/src/main/java/jace/core/Device.java +++ b/src/main/java/jace/core/Device.java @@ -36,8 +36,12 @@ import jace.config.Reconfigurable; */ @Stateful public abstract class Device implements Reconfigurable { + protected Computer computer; + public Device(Computer computer) { + this.computer = computer; + } + // Number of cycles to do nothing (for cpu/video cycle accuracy) - @Stateful private int waitCycles = 0; @Stateful diff --git a/src/main/java/jace/core/Keyboard.java b/src/main/java/jace/core/Keyboard.java index 61f5e64..620103e 100644 --- a/src/main/java/jace/core/Keyboard.java +++ b/src/main/java/jace/core/Keyboard.java @@ -47,7 +47,10 @@ import java.util.logging.Logger; * @author Brendan Robert (BLuRry) brendan.robert@gmail.com */ public class Keyboard implements Reconfigurable { - + private Computer computer; + public Keyboard(Computer computer) { + this.computer = computer; + } @Override public String getShortName() { return "kbd"; @@ -79,16 +82,16 @@ public class Keyboard implements Reconfigurable { */ public Keyboard() { } - private static Map> keyHandlersByKey = new HashMap>(); - private static Map> keyHandlersByOwner = new HashMap>(); + private static Map> keyHandlersByKey = new HashMap<>(); + private static Map> keyHandlersByOwner = new HashMap<>(); public static void registerKeyHandler(KeyHandler l, Object owner) { if (!keyHandlersByKey.containsKey(l.key)) { - keyHandlersByKey.put(l.key, new HashSet()); + keyHandlersByKey.put(l.key, new HashSet<>()); } keyHandlersByKey.get(l.key).add(l); if (!keyHandlersByOwner.containsKey(owner)) { - keyHandlersByOwner.put(owner, new HashSet()); + keyHandlersByOwner.put(owner, new HashSet<>()); } keyHandlersByOwner.get(owner).add(l); } @@ -97,12 +100,9 @@ public class Keyboard implements Reconfigurable { if (!keyHandlersByOwner.containsKey(owner)) { return; } - for (KeyHandler handler : keyHandlersByOwner.get(owner)) { - if (!keyHandlersByKey.containsKey(handler.key)) { - continue; - } + keyHandlersByOwner.get(owner).stream().filter((handler) -> !(!keyHandlersByKey.containsKey(handler.key))).forEach((handler) -> { keyHandlersByKey.get(handler.key).remove(handler); - } + }); } public static void processKeyDownEvents(KeyEvent e) { @@ -216,7 +216,7 @@ public class Keyboard implements Reconfigurable { EmulatorUILogic.toggleDebugPanel(); } if ((code == KeyEvent.VK_F12 || code == KeyEvent.VK_PAGE_UP || code == KeyEvent.VK_BACK_SPACE || code == KeyEvent.VK_PAUSE) && ((e.getModifiers() & KeyEvent.CTRL_MASK) > 0)) { - Computer.getComputer().warmStart(); + computer.warmStart(); } if (code == KeyEvent.VK_F1) { EmulatorUILogic.showMediaManager(); @@ -243,7 +243,7 @@ public class Keyboard implements Reconfigurable { } catch (IOException ex) { Logger.getLogger(Keyboard.class.getName()).log(Level.SEVERE, null, ex); } - Computer.resume(); + computer.resume(); } if ((e.getModifiers() & (KeyEvent.ALT_MASK|KeyEvent.META_MASK|KeyEvent.META_DOWN_MASK)) > 0) { // explicit left and right here because other locations @@ -261,27 +261,27 @@ public class Keyboard implements Reconfigurable { } private void pressOpenApple() { - Computer.pause(); + computer.pause(); SoftSwitches.PB0.getSwitch().setState(true); - Computer.resume(); + computer.resume(); } private void pressSolidApple() { - Computer.pause(); + computer.pause(); SoftSwitches.PB1.getSwitch().setState(true); - Computer.resume(); + computer.resume(); } private void releaseOpenApple() { - Computer.pause(); + computer.pause(); SoftSwitches.PB0.getSwitch().setState(false); - Computer.resume(); + computer.resume(); } private void releaseSolidApple() { - Computer.pause(); + computer.pause(); SoftSwitches.PB1.getSwitch().setState(false); - Computer.resume(); + computer.resume(); } }; } @@ -298,10 +298,7 @@ public class Keyboard implements Reconfigurable { contents = contents.replaceAll("\\n(\\r)?", (char) 0x0d + ""); pasteBuffer = new StringReader(contents); } - } catch (UnsupportedFlavorException ex) { - Logger.getLogger(Keyboard.class - .getName()).log(Level.SEVERE, null, ex); - } catch (IOException ex) { + } catch (UnsupportedFlavorException | IOException ex) { Logger.getLogger(Keyboard.class .getName()).log(Level.SEVERE, null, ex); } diff --git a/src/main/java/jace/core/Motherboard.java b/src/main/java/jace/core/Motherboard.java index fcfa13e..d1beab8 100644 --- a/src/main/java/jace/core/Motherboard.java +++ b/src/main/java/jace/core/Motherboard.java @@ -38,21 +38,18 @@ import java.util.Set; */ public class Motherboard extends TimedDevice { - static final Computer computer = Computer.getComputer(); - static final CPU cpu = computer.getCpu(); - static Motherboard instance; - static final public Set miscDevices = new HashSet(); + static final public Set miscDevices = new HashSet<>(); @ConfigurableField(name = "Enable Speaker", shortName = "speaker", defaultValue = "true") public static boolean enableSpeaker = true; - public static Speaker speaker; - public static SoundMixer mixer = new SoundMixer(); + public Speaker speaker; + public SoundMixer mixer; - static void vblankEnd() { + void vblankEnd() { SoftSwitches.VBL.getSwitch().setState(true); computer.notifyVBLStateChanged(true); } - static void vblankStart() { + void vblankStart() { SoftSwitches.VBL.getSwitch().setState(false); computer.notifyVBLStateChanged(false); } @@ -60,10 +57,12 @@ public class Motherboard extends TimedDevice { /** * Creates a new instance of Motherboard */ - public Motherboard() { - instance = this; + public Motherboard(Computer computer) { + super(computer); + mixer = new SoundMixer(computer); } + @Override protected String getDeviceName() { return "Motherboard"; } @@ -77,15 +76,16 @@ public class Motherboard extends TimedDevice { public int clockCounter = 1; public Card[] cards; + @Override public void tick() { try { clockCounter--; - cpu.doTick(); + computer.getCpu().doTick(); if (clockCounter > 0) { return; } clockCounter = cpuPerClock; - Computer.getComputer().getVideo().doTick(); + computer.getVideo().doTick(); // Unrolled loop since this happens so often if (cards[0] != null) { cards[0].doTick(); @@ -108,9 +108,9 @@ public class Motherboard extends TimedDevice { if (cards[6] != null) { cards[6].doTick(); } - for (Device m : miscDevices) { + miscDevices.stream().forEach((m) -> { m.doTick(); - } + }); } catch (Throwable t) { t.printStackTrace(); } @@ -120,10 +120,12 @@ public class Motherboard extends TimedDevice { public static long SPEED = 1020484L; // (NTSC) //public static long SPEED = 1015625L; // (PAL) + @Override public long defaultCyclesPerSecond() { return SPEED; } + @Override public synchronized void reconfigure() { boolean startAgain = pause(); accelorationRequestors.clear(); @@ -136,7 +138,7 @@ public class Motherboard extends TimedDevice { if (enableSpeaker) { try { if (speaker == null) { - speaker = new Speaker(); + speaker = new Speaker(computer); } else { speaker.attach(); } @@ -154,30 +156,28 @@ public class Motherboard extends TimedDevice { Motherboard.miscDevices.remove(speaker); } } - if (startAgain && Computer.getComputer().getMemory() != null) { + if (startAgain && computer.getMemory() != null) { resume(); } } - static HashSet accelorationRequestors = new HashSet(); + static HashSet accelorationRequestors = new HashSet<>(); - static public void requestSpeed(Object requester) { + public void requestSpeed(Object requester) { accelorationRequestors.add(requester); - if (instance != null) { - instance.enableTempMaxSpeed(); - } + enableTempMaxSpeed(); } - static public void cancelSpeedRequest(Object requester) { + public void cancelSpeedRequest(Object requester) { accelorationRequestors.remove(requester); - if (instance != null && accelorationRequestors.isEmpty()) { - instance.disableTempMaxSpeed(); + if (accelorationRequestors.isEmpty()) { + disableTempMaxSpeed(); } } @Override public void attach() { } - Map resume = new HashMap(); + Map resume = new HashMap<>(); @Override public boolean suspend() { diff --git a/src/main/java/jace/core/PagedMemory.java b/src/main/java/jace/core/PagedMemory.java index 9fb55bc..2eb9dc0 100644 --- a/src/main/java/jace/core/PagedMemory.java +++ b/src/main/java/jace/core/PagedMemory.java @@ -60,7 +60,9 @@ public class PagedMemory { /** * Creates a new instance of PagedMemory */ - public PagedMemory(int size, Type memType) { + Computer computer; + public PagedMemory(int size, Type memType, Computer computer) { + this.computer = computer; type = memType; internalMemory = new byte[size >> 8][256]; for (int i = 0; i < size; i += 256) { @@ -127,7 +129,7 @@ public class PagedMemory { public void writeByte(int address, byte value) { byte[] page = getMemoryPage(address); - StateManager.markDirtyValue(page); + StateManager.markDirtyValue(page, computer); getMemoryPage(address)[address & 0x0ff] = value; } diff --git a/src/main/java/jace/core/RAM.java b/src/main/java/jace/core/RAM.java index 8bbf364..8077927 100644 --- a/src/main/java/jace/core/RAM.java +++ b/src/main/java/jace/core/RAM.java @@ -23,7 +23,6 @@ import jace.config.Reconfigurable; import java.io.IOException; import java.util.ArrayList; import java.util.List; -import java.util.Vector; /** * RAM is a 64K address space of paged memory. It also manages sets of memory @@ -42,12 +41,14 @@ public abstract class RAM implements Reconfigurable { protected Card[] cards; // card 0 = 80 column card firmware / system rom public int activeSlot = 0; + protected final Computer computer; /** * Creates a new instance of RAM */ - public RAM() { - listeners = new Vector(); + public RAM(Computer computer) { + this.computer = computer; + listeners = new ArrayList<>(); cards = new Card[8]; refreshListenerMap(); } @@ -196,60 +197,60 @@ public abstract class RAM implements Reconfigurable { private void refreshListenerMap() { listenerMap = new ArrayList[256]; ioListenerMap = new ArrayList[256]; - for (RAMListener l : listeners) { + listeners.stream().forEach((l) -> { addListenerRange(l); - } + }); } public void addListener(final RAMListener l) { - boolean restart = Computer.pause(); + boolean restart = computer.pause(); if (listeners.contains(l)) { return; } listeners.add(l); addListenerRange(l); if (restart) { - Computer.resume(); + computer.resume(); } } public void removeListener(final RAMListener l) { - boolean restart = Computer.pause(); + boolean restart = computer.pause(); listeners.remove(l); refreshListenerMap(); if (restart) { - Computer.resume(); + computer.resume(); } } public byte callListener(RAMEvent.TYPE t, int address, int oldValue, int newValue, boolean requireSyncronization) { - List activeListeners = null; + List activeListeners; if (requireSyncronization) { - Computer.getComputer().getCpu().suspend(); + computer.getCpu().suspend(); } if ((address & 0x0FF00) == 0x0C000) { activeListeners = ioListenerMap[address & 0x0FF]; if (activeListeners == null && t.isRead()) { if (requireSyncronization) { - Computer.getComputer().getCpu().resume(); + computer.getCpu().resume(); } - return Computer.getComputer().getVideo().getFloatingBus(); + return computer.getVideo().getFloatingBus(); } } else { activeListeners = listenerMap[(address >> 8) & 0x0ff]; } if (activeListeners != null) { RAMEvent e = new RAMEvent(t, RAMEvent.SCOPE.ADDRESS, RAMEvent.VALUE.ANY, address, oldValue, newValue); - for (RAMListener l : activeListeners) { + activeListeners.stream().forEach((l) -> { l.handleEvent(e); - } + }); if (requireSyncronization) { - Computer.getComputer().getCpu().resume(); + computer.getCpu().resume(); } return (byte) e.getNewValue(); } if (requireSyncronization) { - Computer.getComputer().getCpu().resume(); + computer.getCpu().resume(); } return (byte) newValue; } diff --git a/src/main/java/jace/core/SoftSwitch.java b/src/main/java/jace/core/SoftSwitch.java index 29434d6..7fafe88 100644 --- a/src/main/java/jace/core/SoftSwitch.java +++ b/src/main/java/jace/core/SoftSwitch.java @@ -47,6 +47,7 @@ public abstract class SoftSwitch { private final List exclusionQuery = new ArrayList<>(); private String name; private boolean toggleType = false; + protected Computer computer; /** * Creates a new instance of SoftSwitch @@ -235,18 +236,20 @@ public abstract class SoftSwitch { } } - public void register() { - RAM m = Computer.getComputer().getMemory(); + public void register(Computer computer) { + this.computer = computer; + RAM m = computer.getMemory(); listeners.stream().forEach((l) -> { m.addListener(l); }); } public void unregister() { - RAM m = Computer.getComputer().getMemory(); + RAM m = computer.getMemory(); listeners.stream().forEach((l) -> { m.removeListener(l); }); + this.computer = null; } public void setState(boolean newState) { @@ -259,7 +262,7 @@ public abstract class SoftSwitch { state = newState; /* if (queryAddresses != null) { - RAM m = Computer.getComputer().getMemory(); + RAM m = computer.getMemory(); for (int i:queryAddresses) { byte old = m.read(i, false); m.write(i, (byte) (old & 0x7f | (state ? 0x080:0x000)), false); diff --git a/src/main/java/jace/core/SoundMixer.java b/src/main/java/jace/core/SoundMixer.java index 35bd895..7f1bd32 100644 --- a/src/main/java/jace/core/SoundMixer.java +++ b/src/main/java/jace/core/SoundMixer.java @@ -87,6 +87,10 @@ public class SoundMixer extends Device { }; private Mixer theMixer; + public SoundMixer(Computer computer) { + super(computer); + } + @Override public String getDeviceName() { return "Sound Output"; @@ -132,7 +136,7 @@ public class SoundMixer extends Device { if (activeLines.containsKey(requester)) { return activeLines.get(requester); } - SourceDataLine sdl = null; + SourceDataLine sdl; if (availableLines.isEmpty()) { sdl = getNewLine(); } else { diff --git a/src/main/java/jace/core/TimedDevice.java b/src/main/java/jace/core/TimedDevice.java index a94fa94..f12cce6 100644 --- a/src/main/java/jace/core/TimedDevice.java +++ b/src/main/java/jace/core/TimedDevice.java @@ -31,7 +31,8 @@ public abstract class TimedDevice extends Device { /** * Creates a new instance of TimedDevice */ - public TimedDevice() { + public TimedDevice(Computer computer) { + super(computer); setSpeed(cyclesPerSecond); } @ConfigurableField(name = "Speed", description = "(in hertz)") diff --git a/src/main/java/jace/core/Video.java b/src/main/java/jace/core/Video.java index cf2457f..1c8d34e 100644 --- a/src/main/java/jace/core/Video.java +++ b/src/main/java/jace/core/Video.java @@ -91,7 +91,8 @@ public abstract class Video extends Device { /** * Creates a new instance of Video */ - public Video() { + public Video(Computer computer) { + super(computer); suspend(); video = new BufferedImage(560, 192, BufferedImage.TYPE_INT_RGB); vPeriod = 0; @@ -164,7 +165,7 @@ public abstract class Video extends Device { @Override public void tick() { - setFloatingBus(Computer.getComputer().getMemory().readRaw(scannerAddress + x)); + setFloatingBus(computer.getMemory().readRaw(scannerAddress + x)); if (hPeriod > 0) { hPeriod--; if (hPeriod == 0) { @@ -201,12 +202,12 @@ public abstract class Video extends Device { y = APPLE_SCREEN_LINES - (TOTAL_LINES - APPLE_SCREEN_LINES); isVblank = true; vblankStart(); - Motherboard.vblankStart(); + computer.getMotherboard().vblankStart(); } else { y = 0; isVblank = false; vblankEnd(); - Motherboard.vblankEnd(); + computer.getMotherboard().vblankEnd(); } } } diff --git a/src/main/java/jace/hardware/CardAppleMouse.java b/src/main/java/jace/hardware/CardAppleMouse.java index 16b4eca..d0d8bbd 100644 --- a/src/main/java/jace/hardware/CardAppleMouse.java +++ b/src/main/java/jace/hardware/CardAppleMouse.java @@ -88,6 +88,10 @@ public class CardAppleMouse extends Card implements MouseListener { public boolean fullscreenFix = true; ImageIcon mouseActive = Utility.loadIcon("input-mouse.png"); + public CardAppleMouse(Computer computer) { + super(computer); + } + @Override public String getDeviceName() { return "Apple Mouse"; @@ -232,7 +236,7 @@ public class CardAppleMouse extends Card implements MouseListener { } private MOS65C02 getCPU() { - return (MOS65C02) Computer.getComputer().getCpu(); + return (MOS65C02) computer.getCpu(); } /* @@ -321,7 +325,7 @@ public class CardAppleMouse extends Card implements MouseListener { * //gs homes mouse to low address, but //c and //e do not */ private void clampMouse() { - RAM128k memory = (RAM128k) Computer.getComputer().memory; + RAM128k memory = (RAM128k) computer.memory; byte clampMinLo = memory.getMainMemory().readByte(0x0478); byte clampMaxLo = memory.getMainMemory().readByte(0x04F8); byte clampMinHi = memory.getMainMemory().readByte(0x0578); @@ -459,7 +463,7 @@ public class CardAppleMouse extends Card implements MouseListener { if (drawingArea == null) { return; } - Graphics2D screen = (Graphics2D) Computer.getComputer().getVideo().getScreen(); + Graphics2D screen = (Graphics2D) computer.getVideo().getScreen(); // Point currentMouseLocation = MouseInfo.getPointerInfo().getLocation(); // Point topLeft = drawingArea.getLocationOnScreen(); Point currentMouseLocation = Emulator.getFrame().getContentPane().getMousePosition(); @@ -506,7 +510,7 @@ public class CardAppleMouse extends Card implements MouseListener { y = clampMax.y; } - PagedMemory m = ((RAM128k) Computer.getComputer().getMemory()).getMainMemory(); + PagedMemory m = ((RAM128k) computer.getMemory()).getMainMemory(); int s = getSlot(); /* * $0478 + slot Low byte of absolute X position diff --git a/src/main/java/jace/hardware/CardDiskII.java b/src/main/java/jace/hardware/CardDiskII.java index f4d5720..d212306 100644 --- a/src/main/java/jace/hardware/CardDiskII.java +++ b/src/main/java/jace/hardware/CardDiskII.java @@ -23,7 +23,7 @@ import jace.config.ConfigurableField; import jace.config.Name; import jace.config.Reconfigurable; import jace.core.Card; -import jace.core.Motherboard; +import jace.core.Computer; import jace.core.RAMEvent; import jace.core.RAMEvent.TYPE; import jace.core.Utility; @@ -48,14 +48,15 @@ import java.util.logging.Logger; public class CardDiskII extends Card implements Reconfigurable, MediaConsumerParent { DiskIIDrive currentDrive; - DiskIIDrive drive1 = new DiskIIDrive(); - DiskIIDrive drive2 = new DiskIIDrive(); + DiskIIDrive drive1 = new DiskIIDrive(computer); + DiskIIDrive drive2 = new DiskIIDrive(computer); @ConfigurableField(category = "Disk", defaultValue = "254", name = "Default volume", description = "Value to use for disk volume number") static public int DEFAULT_VOLUME_NUMBER = 0x0FE; @ConfigurableField(category = "Disk", defaultValue = "true", name = "Speed boost", description = "If enabled, emulator will run at max speed during disk access") static public boolean USE_MAX_SPEED = true; - public CardDiskII() { + public CardDiskII(Computer computer) { + super(computer); try { loadRom("jace/data/DiskII.rom"); } catch (IOException ex) { @@ -195,10 +196,10 @@ public class CardDiskII extends Card implements Reconfigurable, MediaConsumerPar private void tweakTiming() { if (drive1.isOn() || drive2.isOn()) { if (USE_MAX_SPEED) { - Motherboard.requestSpeed(this); + computer.getMotherboard().requestSpeed(this); } } else { - Motherboard.cancelSpeedRequest(this); + computer.getMotherboard().cancelSpeedRequest(this); } } diff --git a/src/main/java/jace/hardware/CardExt80Col.java b/src/main/java/jace/hardware/CardExt80Col.java index 1ce052d..4eef085 100644 --- a/src/main/java/jace/hardware/CardExt80Col.java +++ b/src/main/java/jace/hardware/CardExt80Col.java @@ -19,6 +19,7 @@ package jace.hardware; import jace.apple2e.RAM128k; +import jace.core.Computer; import jace.core.PagedMemory; import jace.state.Stateful; @@ -45,11 +46,11 @@ public class CardExt80Col extends RAM128k { return "128kb"; } - public CardExt80Col() { - super(); - auxMemory = new PagedMemory(0xc000, PagedMemory.Type.ram); - auxLanguageCard = new PagedMemory(0x3000, PagedMemory.Type.languageCard); - auxLanguageCard2 = new PagedMemory(0x1000, PagedMemory.Type.languageCard); + public CardExt80Col(Computer computer) { + super(computer); + auxMemory = new PagedMemory(0xc000, PagedMemory.Type.ram, computer); + auxLanguageCard = new PagedMemory(0x3000, PagedMemory.Type.languageCard, computer); + auxLanguageCard2 = new PagedMemory(0x1000, PagedMemory.Type.languageCard, computer); initMemoryPattern(auxMemory); } diff --git a/src/main/java/jace/hardware/CardHayesMicromodem.java b/src/main/java/jace/hardware/CardHayesMicromodem.java index 0c6e74b..c492f03 100644 --- a/src/main/java/jace/hardware/CardHayesMicromodem.java +++ b/src/main/java/jace/hardware/CardHayesMicromodem.java @@ -19,6 +19,7 @@ package jace.hardware; import jace.config.Name; +import jace.core.Computer; import jace.core.RAMEvent; import jace.core.RAMEvent.TYPE; import java.io.IOException; @@ -42,7 +43,8 @@ public class CardHayesMicromodem extends CardSSC { public int RING_INDICATOR_REG = 5; private boolean ringIndicator = false; - public CardHayesMicromodem() { + public CardHayesMicromodem(Computer computer) { + super(computer); ACIA_Data = 7; ACIA_Status = 6; ACIA_Control = 5; diff --git a/src/main/java/jace/hardware/CardMockingboard.java b/src/main/java/jace/hardware/CardMockingboard.java index 7a05d8f..19ac8a1 100644 --- a/src/main/java/jace/hardware/CardMockingboard.java +++ b/src/main/java/jace/hardware/CardMockingboard.java @@ -86,12 +86,13 @@ public class CardMockingboard extends Card implements Runnable { return "Mockingboard"; } - public CardMockingboard() { + public CardMockingboard(Computer computer) { + super(computer); controllers = new R6522[2]; for (int i = 0; i < 2; i++) { //don't ask... final int j = i; - controllers[i] = new R6522() { + controllers[i] = new R6522(computer) { @Override public void sendOutputA(int value) { if (activeChip != null) { @@ -156,7 +157,7 @@ public class CardMockingboard extends Card implements Runnable { } if (activeChip == null) { System.err.println("Could not determine which PSG to communicate to"); - e.setNewValue(Computer.getComputer().getVideo().getFloatingBus()); + e.setNewValue(computer.getVideo().getFloatingBus()); return; } R6522 controller = controllers[chip & 1]; @@ -172,7 +173,7 @@ public class CardMockingboard extends Card implements Runnable { @Override protected void handleIOAccess(int register, TYPE type, int value, RAMEvent e) { // Oddly, all IO is done at the firmware address bank. It's a strange card. - e.setNewValue(Computer.getComputer().getVideo().getFloatingBus()); + e.setNewValue(computer.getVideo().getFloatingBus()); } long ticksSinceLastPlayback = 0; @@ -305,7 +306,7 @@ public class CardMockingboard extends Card implements Runnable { */ public void run() { try { - SourceDataLine out = Motherboard.mixer.getLine(this); + SourceDataLine out = computer.getMotherboard().mixer.getLine(this); int[] leftBuffer = new int[BUFFER_LENGTH]; int[] rightBuffer = new int[BUFFER_LENGTH]; int frameSize = out.getFormat().getFrameSize(); @@ -317,7 +318,7 @@ public class CardMockingboard extends Card implements Runnable { ticksSinceLastPlayback = 0; int zeroSamples = 0; while (isRunning()) { - Motherboard.requestSpeed(this); + computer.getMotherboard().requestSpeed(this); playSound(leftBuffer, rightBuffer); int p = 0; for (int idx = 0; idx < BUFFER_LENGTH; idx++) { @@ -345,7 +346,7 @@ public class CardMockingboard extends Card implements Runnable { if (zeroSamples >= MAX_IDLE_SAMPLES) { zeroSamples = 0; pause = true; - Motherboard.cancelSpeedRequest(this); + computer.getMotherboard().cancelSpeedRequest(this); while (pause && isRunning()) { try { Thread.sleep(50); @@ -380,9 +381,9 @@ public class CardMockingboard extends Card implements Runnable { Logger.getLogger(CardMockingboard.class .getName()).log(Level.SEVERE, null, ex); } finally { - Motherboard.cancelSpeedRequest(this); + computer.getMotherboard().cancelSpeedRequest(this); System.out.println("Mockingboard playback stopped"); - Motherboard.mixer.returnLine(this); + computer.getMotherboard().mixer.returnLine(this); } } diff --git a/src/main/java/jace/hardware/CardRamFactor.java b/src/main/java/jace/hardware/CardRamFactor.java index 6dc0a41..995822a 100644 --- a/src/main/java/jace/hardware/CardRamFactor.java +++ b/src/main/java/jace/hardware/CardRamFactor.java @@ -22,6 +22,7 @@ import jace.Emulator; import jace.config.ConfigurableField; import jace.config.Name; import jace.core.Card; +import jace.core.Computer; import jace.core.Motherboard; import jace.core.RAMEvent; import jace.core.RAMEvent.TYPE; @@ -64,7 +65,8 @@ public class CardRamFactor extends Card { return "RamFactor"; } ImageIcon indicator; - public CardRamFactor() { + public CardRamFactor(Computer computer) { + super(computer); indicator=Utility.loadIcon("ram.png"); try { loadRom("jace/data/RAMFactor14.rom"); @@ -162,7 +164,7 @@ public class CardRamFactor extends Card { @Override protected void handleFirmwareAccess(int register, TYPE type, int value, RAMEvent e) { if (speedBoost) { - Motherboard.requestSpeed(this); + computer.getMotherboard().requestSpeed(this); } } @@ -174,7 +176,7 @@ public class CardRamFactor extends Card { @Override protected void handleC8FirmwareAccess(int register, TYPE type, int value, RAMEvent e) { if (speedBoost) { - Motherboard.requestSpeed(this); + computer.getMotherboard().requestSpeed(this); } } diff --git a/src/main/java/jace/hardware/CardRamworks.java b/src/main/java/jace/hardware/CardRamworks.java index a22bb41..35aee7b 100644 --- a/src/main/java/jace/hardware/CardRamworks.java +++ b/src/main/java/jace/hardware/CardRamworks.java @@ -53,10 +53,10 @@ public class CardRamworks extends RAM128k { public int memorySize = 3072; public int maxBank = memorySize / 64; private Map generateBank() { - Map memoryBank = new EnumMap(BankType.class); - memoryBank.put(BankType.MAIN_MEMORY, new PagedMemory(0xc000, PagedMemory.Type.ram)); - memoryBank.put(BankType.LANGUAGE_CARD_1, new PagedMemory(0x3000, PagedMemory.Type.languageCard)); - memoryBank.put(BankType.LANGUAGE_CARD_2, new PagedMemory(0x1000, PagedMemory.Type.languageCard)); + Map memoryBank = new EnumMap<>(BankType.class); + memoryBank.put(BankType.MAIN_MEMORY, new PagedMemory(0xc000, PagedMemory.Type.ram, computer)); + memoryBank.put(BankType.LANGUAGE_CARD_1, new PagedMemory(0x3000, PagedMemory.Type.languageCard, computer)); + memoryBank.put(BankType.LANGUAGE_CARD_2, new PagedMemory(0x1000, PagedMemory.Type.languageCard, computer)); return memoryBank; } @@ -64,9 +64,9 @@ public class CardRamworks extends RAM128k { MAIN_MEMORY, LANGUAGE_CARD_1, LANGUAGE_CARD_2 }; - public CardRamworks() { - super(); - memory = new ArrayList>(maxBank); + public CardRamworks(Computer computer) { + super(computer); + memory = new ArrayList<>(maxBank); reconfigure(); } @@ -115,7 +115,7 @@ public class CardRamworks extends RAM128k { @Override public void reconfigure() { - boolean resume = Computer.pause(); + boolean resume = computer.pause(); maxBank = memorySize / 64; if (maxBank < 1) maxBank = 1; if (maxBank > 128) maxBank = 128; @@ -124,7 +124,7 @@ public class CardRamworks extends RAM128k { } configureActiveMemory(); if (resume) { - Computer.resume(); + computer.resume(); } } RAMListener bankSelectListener = new RAMListener(RAMEvent.TYPE.WRITE, RAMEvent.SCOPE.ADDRESS, RAMEvent.VALUE.ANY) { diff --git a/src/main/java/jace/hardware/CardSSC.java b/src/main/java/jace/hardware/CardSSC.java index b8af34a..aab5c98 100644 --- a/src/main/java/jace/hardware/CardSSC.java +++ b/src/main/java/jace/hardware/CardSSC.java @@ -94,6 +94,10 @@ public class CardSSC extends Card implements Reconfigurable, Runnable { // Bitmask for stop bits (FF = 8, 7F = 7, etc) private int DATA_BITS = 0x07F; + public CardSSC(Computer computer) { + super(computer); + } + public String getDeviceName() { return "Super Serial Card"; } @@ -390,7 +394,7 @@ public class CardSSC extends Card implements Reconfigurable, Runnable { private void triggerIRQ() { IRQ_TRIGGERED = true; - Computer.getComputer().getCpu().generateInterrupt(); + computer.getCpu().generateInterrupt(); } public void hangUp() { diff --git a/src/main/java/jace/hardware/CardThunderclock.java b/src/main/java/jace/hardware/CardThunderclock.java index e506241..782177c 100644 --- a/src/main/java/jace/hardware/CardThunderclock.java +++ b/src/main/java/jace/hardware/CardThunderclock.java @@ -59,7 +59,8 @@ public class CardThunderclock extends Card { @ConfigurableField(category = "OS", name = "Patch Prodos Year", description = "If enabled, the Prodos clock driver will be patched to use the current year.") public boolean attemptYearPatch = true; - public CardThunderclock() { + public CardThunderclock(Computer computer) { + super(computer); try { loadRom("jace/data/thunderclock_plus.rom"); } catch (IOException ex) { @@ -213,7 +214,7 @@ public class CardThunderclock extends Card { ticks = 0; irqAsserted = true; if (irqEnabled) { - Computer.getComputer().getCpu().generateInterrupt(); + computer.getCpu().generateInterrupt(); } } } @@ -295,7 +296,7 @@ public class CardThunderclock extends Card { * always tell time correctly. */ private void performProdosPatch() { - PagedMemory ram = Computer.getComputer().getMemory().activeRead; + PagedMemory ram = computer.getMemory().activeRead; if (patchLoc > 0) { // We've already patched, just validate if (ram.readByte(patchLoc) == (byte) MOS65C02.OPCODE.LDA_IMM.getCode()) { diff --git a/src/main/java/jace/hardware/DiskIIDrive.java b/src/main/java/jace/hardware/DiskIIDrive.java index fd61906..1f4e867 100644 --- a/src/main/java/jace/hardware/DiskIIDrive.java +++ b/src/main/java/jace/hardware/DiskIIDrive.java @@ -18,6 +18,7 @@ */ package jace.hardware; +import jace.core.Computer; import jace.library.MediaConsumer; import jace.library.MediaEntry; import jace.library.MediaEntry.MediaFile; @@ -41,7 +42,12 @@ import javax.swing.ImageIcon; */ @Stateful public class DiskIIDrive implements MediaConsumer { + Computer computer; + public DiskIIDrive(Computer computer) { + this.computer = computer; + } + FloppyDisk disk; // Number of milliseconds to wait between last write and update to disk image public static long WRITE_UPDATE_DELAY = 1000; @@ -77,7 +83,7 @@ public class DiskIIDrive implements MediaConsumer { public void reset() { driveOn = false; magnets = 0; - dirtyTracks = new HashSet(); + dirtyTracks = new HashSet<>(); diskUpdatePending = false; } @@ -154,7 +160,7 @@ public class DiskIIDrive implements MediaConsumer { dirtyTracks.add(trackStartOffset / FloppyDisk.TRACK_NIBBLE_LENGTH); disk.nibbles[trackStartOffset + nibbleOffset++] = latch; triggerDiskUpdate(); - StateManager.markDirtyValue(disk.nibbles); + StateManager.markDirtyValue(disk.nibbles, computer); } } @@ -186,9 +192,9 @@ public class DiskIIDrive implements MediaConsumer { diskUpdatePending = true; // Update all tracks as necessary if (disk != null) { - for (Integer track : dirtyTracks) { + dirtyTracks.stream().forEach((track) -> { disk.updateTrack(track); - } + }); } // Empty out dirty list dirtyTracks.clear(); @@ -199,53 +205,54 @@ public class DiskIIDrive implements MediaConsumer { private void triggerDiskUpdate() { lastWriteTime = System.currentTimeMillis(); if (writerThread == null || !writerThread.isAlive()) { - writerThread = new Thread(new Runnable() { - @Override - public void run() { - long diff = 0; - // Wait until there have been no virtual writes for specified delay time - while ((diff = System.currentTimeMillis() - lastWriteTime) < WRITE_UPDATE_DELAY) { - // Sleep for difference of time - LockSupport.parkNanos(diff * 1000); - // Note: In the meantime, there could have been another disk write, - // in which case this loop will repeat again as needed. - } - updateDisk(); + writerThread = new Thread(() -> { + long diff = 0; + // Wait until there have been no virtual writes for specified delay time + while ((diff = System.currentTimeMillis() - lastWriteTime) < WRITE_UPDATE_DELAY) { + // Sleep for difference of time + LockSupport.parkNanos(diff * 1000); + // Note: In the meantime, there could have been another disk write, + // in which case this loop will repeat again as needed. } + updateDisk(); }); writerThread.start(); } } void insertDisk(File diskPath) throws IOException { - disk = new FloppyDisk(diskPath); - dirtyTracks = new HashSet(); + disk = new FloppyDisk(diskPath, computer); + dirtyTracks = new HashSet<>(); // Emulator state has changed significantly, reset state manager - StateManager.getInstance().invalidate(); + StateManager.getInstance(computer).invalidate(); } private ImageIcon icon; + @Override public ImageIcon getIcon() { return icon; } + @Override public void setIcon(ImageIcon i) { icon = i; } private MediaEntry currentMediaEntry; private MediaFile currentMediaFile; + @Override public void eject() { if (disk == null) { return; } waitForPendingWrites(); disk = null; - dirtyTracks = new HashSet(); + dirtyTracks = new HashSet<>(); // Emulator state has changed significantly, reset state manager - StateManager.getInstance().invalidate(); + StateManager.getInstance(computer).invalidate(); } + @Override public void insertMedia(MediaEntry e, MediaFile f) throws IOException { if (!isAccepted(e, f)) { return; @@ -256,14 +263,17 @@ public class DiskIIDrive implements MediaConsumer { currentMediaFile = f; } + @Override public MediaEntry getMediaEntry() { return currentMediaEntry; } + @Override public MediaFile getMediaFile() { return currentMediaFile; } + @Override public boolean isAccepted(MediaEntry e, MediaFile f) { if (f == null) return false; System.out.println("Type is accepted: "+f.path+"; "+e.type.toString()+": "+e.type.is140kb); diff --git a/src/main/java/jace/hardware/FloppyDisk.java b/src/main/java/jace/hardware/FloppyDisk.java index 1d5b87b..4c29348 100644 --- a/src/main/java/jace/hardware/FloppyDisk.java +++ b/src/main/java/jace/hardware/FloppyDisk.java @@ -18,6 +18,7 @@ */ package jace.hardware; +import jace.core.Computer; import jace.state.StateManager; import jace.state.Stateful; import java.io.ByteArrayOutputStream; @@ -109,16 +110,16 @@ public class FloppyDisk { * @param diskFile * @throws IOException */ - public FloppyDisk(File diskFile) throws IOException { + public FloppyDisk(File diskFile, Computer computer) throws IOException { FileInputStream input = new FileInputStream(diskFile); String name = diskFile.getName().toUpperCase(); - readDisk(input, name.endsWith(".PO")); + readDisk(input, name.endsWith(".PO"), computer); writeProtected = !diskFile.canWrite(); diskPath = diskFile; } // brendanr: refactored to use input stream - public void readDisk(InputStream diskFile, boolean prodosOrder) throws IOException { + public void readDisk(InputStream diskFile, boolean prodosOrder, Computer computer) throws IOException { isNibblizedImage = true; volumeNumber = CardDiskII.DEFAULT_VOLUME_NUMBER; headerLength = 0; @@ -154,8 +155,8 @@ public class FloppyDisk { } catch (IOException ex) { throw ex; } - StateManager.markDirtyValue(nibbles); - StateManager.markDirtyValue(currentSectorOrder); + StateManager.markDirtyValue(nibbles, computer); + StateManager.markDirtyValue(currentSectorOrder, computer); } /* diff --git a/src/main/java/jace/hardware/Joystick.java b/src/main/java/jace/hardware/Joystick.java index 50e0cbd..edb1175 100644 --- a/src/main/java/jace/hardware/Joystick.java +++ b/src/main/java/jace/hardware/Joystick.java @@ -70,7 +70,8 @@ public class Joystick extends Device { Robot robot; Point centerPoint; - public Joystick(int port) { + public Joystick(int port, Computer computer) { + super(computer); centerPoint = new Point(screenSize.width / 2, screenSize.height / 2); this.port = port; if (port == 0) { @@ -214,7 +215,7 @@ public class Joystick extends Device { }; private void registerListeners() { - Computer.getComputer().getMemory().addListener(listener); + computer.getMemory().addListener(listener); if (useKeyboard) { System.out.println("Registering key handlers"); Keyboard.registerKeyHandler(new KeyHandler(KeyEvent.VK_LEFT, -1) { @@ -273,7 +274,7 @@ public class Joystick extends Device { } private void removeListeners() { - Computer.getComputer().getMemory().removeListener(listener); + computer.getMemory().removeListener(listener); Keyboard.unregisterAllHandlers(this); } } \ No newline at end of file diff --git a/src/main/java/jace/hardware/PassportMidiInterface.java b/src/main/java/jace/hardware/PassportMidiInterface.java index ff880c2..9243d2f 100644 --- a/src/main/java/jace/hardware/PassportMidiInterface.java +++ b/src/main/java/jace/hardware/PassportMidiInterface.java @@ -43,6 +43,10 @@ import javax.sound.midi.Synthesizer; @Name(value = "Passport Midi Interface", description = "MIDI sound card") public class PassportMidiInterface extends Card { + public PassportMidiInterface(Computer computer) { + super(computer); + } + @Override protected void handleC8FirmwareAccess(int register, TYPE type, int value, RAMEvent e) { // There is no rom on this card, so nothing to do here @@ -318,7 +322,7 @@ public class PassportMidiInterface extends Card { if (t.irqEnabled) { // System.out.println("Timer generating interrupt!"); t.irqRequested = true; - Computer.getComputer().getCpu().generateInterrupt(); + computer.getCpu().generateInterrupt(); ptmStatusReadSinceIRQ = false; } if (t.mode == TIMER_MODE.continuous || t.mode == TIMER_MODE.freqComparison) { diff --git a/src/main/java/jace/hardware/ProdosDriver.java b/src/main/java/jace/hardware/ProdosDriver.java index 4ff05d9..8c9e856 100644 --- a/src/main/java/jace/hardware/ProdosDriver.java +++ b/src/main/java/jace/hardware/ProdosDriver.java @@ -29,6 +29,12 @@ import java.io.IOException; * @author Brendan Robert (BLuRry) brendan.robert@gmail.com */ public abstract class ProdosDriver { + Computer computer; + + public ProdosDriver(Computer computer) { + this.computer = computer; + } + public static int MLI_COMMAND = 0x042; public static int MLI_UNITNUMBER = 0x043; public static int MLI_BUFFER_ADDRESS = 0x044; @@ -71,7 +77,7 @@ public abstract class ProdosDriver { public void handleMLI() { int returnCode = prodosMLI().intValue; - MOS65C02 cpu = (MOS65C02) Computer.getComputer().getCpu(); + MOS65C02 cpu = (MOS65C02) computer.getCpu(); cpu.A = returnCode; // Clear carry flag if no error, otherwise set carry flag cpu.C = (returnCode == 0x00) ? 00 : 01; @@ -79,7 +85,7 @@ public abstract class ProdosDriver { private MLI_RETURN prodosMLI() { try { - RAM memory = Computer.getComputer().getMemory(); + RAM memory = computer.getMemory(); int cmd = memory.readRaw(MLI_COMMAND); MLI_COMMAND_TYPE command = MLI_COMMAND_TYPE.fromInt(cmd); int unit = (memory.readWordRaw(MLI_UNITNUMBER) & 0x080) > 0 ? 1 : 0; @@ -96,7 +102,7 @@ public abstract class ProdosDriver { switch (command) { case STATUS: int blocks = getSize(); - MOS65C02 cpu = (MOS65C02) Computer.getComputer().getCpu(); + MOS65C02 cpu = (MOS65C02) computer.getCpu(); cpu.X = blocks & 0x0ff; cpu.Y = (blocks >> 8) & 0x0ff; if (isWriteProtected()) { diff --git a/src/main/java/jace/hardware/SmartportDriver.java b/src/main/java/jace/hardware/SmartportDriver.java index 1d6f39a..b2c56dd 100644 --- a/src/main/java/jace/hardware/SmartportDriver.java +++ b/src/main/java/jace/hardware/SmartportDriver.java @@ -31,7 +31,12 @@ import java.util.logging.Logger; * @author Brendan Robert (BLuRry) brendan.robert@gmail.com */ public abstract class SmartportDriver { + Computer computer; + public SmartportDriver(Computer computer) { + this.computer = computer; + } + public static enum ERROR_CODE { NO_ERROR(0), INVALID_COMMAND(0x01), BAD_PARAM_COUNT(0x04), INVALID_UNIT(0x011), INVALID_CODE(0x021), BAD_BLOCK_NUMBER(0x02d); int intValue; @@ -42,15 +47,15 @@ public abstract class SmartportDriver { public void handleSmartport() { int returnCode = callSmartport().intValue; - MOS65C02 cpu = (MOS65C02) Computer.getComputer().getCpu(); + MOS65C02 cpu = (MOS65C02) computer.getCpu(); cpu.A = returnCode; // Clear carry flag if no error, otherwise set carry flag cpu.C = (returnCode == 0x00) ? 00 : 01; } private ERROR_CODE callSmartport() { - MOS65C02 cpu = (MOS65C02) Computer.getComputer().getCpu(); - RAM ram = Computer.getComputer().getMemory(); + MOS65C02 cpu = (MOS65C02) computer.getCpu(); + RAM ram = computer.getMemory(); int callAddress = cpu.popWord() + 1; int command = ram.readRaw(callAddress); boolean extendedCall = command >= 0x040; diff --git a/src/main/java/jace/hardware/massStorage/CardMassStorage.java b/src/main/java/jace/hardware/massStorage/CardMassStorage.java index dc3da2c..43f632a 100644 --- a/src/main/java/jace/hardware/massStorage/CardMassStorage.java +++ b/src/main/java/jace/hardware/massStorage/CardMassStorage.java @@ -23,7 +23,6 @@ import jace.apple2e.MOS65C02; import jace.config.Name; import jace.core.Card; import jace.core.Computer; -import jace.core.Motherboard; import jace.core.RAMEvent; import jace.core.RAMEvent.TYPE; import jace.core.Utility; @@ -47,7 +46,8 @@ public class CardMassStorage extends Card implements MediaConsumerParent { MassStorageDrive drive1; MassStorageDrive drive2; - public CardMassStorage() { + public CardMassStorage(Computer computer) { + super(computer); drive1 = new MassStorageDrive(); drive2 = new MassStorageDrive(); drive1.setIcon(Utility.loadIcon("drive-harddisk.png")); @@ -86,7 +86,7 @@ public class CardMassStorage extends Card implements MediaConsumerParent { } return null; } - ProdosDriver driver = new ProdosDriver() { + ProdosDriver driver = new ProdosDriver(computer) { @Override public boolean changeUnit(int unit) { currentDrive = unit == 0 ? drive1 : drive2; @@ -110,12 +110,12 @@ public class CardMassStorage extends Card implements MediaConsumerParent { @Override public void mliRead(int block, int bufferAddress) throws IOException { - getCurrentDisk().mliRead(block, bufferAddress); + getCurrentDisk().mliRead(block, bufferAddress, computer.getMemory()); } @Override public void mliWrite(int block, int bufferAddress) throws IOException { - getCurrentDisk().mliWrite(block, bufferAddress); + getCurrentDisk().mliWrite(block, bufferAddress, computer.getMemory()); } @Override @@ -129,14 +129,14 @@ public class CardMassStorage extends Card implements MediaConsumerParent { try { detach(); - int pc = Computer.getComputer().getCpu().getProgramCounter(); + int pc = computer.getCpu().getProgramCounter(); if (drive1.getCurrentDisk() != null && getSlot() == 7 && (pc == 0x0c65e || pc == 0x0c661)) { // If the computer is in a loop trying to boot from cards 6, fast-boot from here instead // This is a convenience to boot a hard-drive if the emulator has started waiting for a currentDisk currentDrive = drive1; - getCurrentDisk().boot0(getSlot()); - Card[] cards = Computer.getComputer().getMemory().getAllCards(); - Motherboard.cancelSpeedRequest(cards[6]); + getCurrentDisk().boot0(getSlot(), computer); + Card[] cards = computer.getMemory().getAllCards(); + computer.getMotherboard().cancelSpeedRequest(cards[6]); } attach(); } catch (IOException ex) { @@ -155,7 +155,7 @@ public class CardMassStorage extends Card implements MediaConsumerParent { @Override protected void handleFirmwareAccess(int offset, TYPE type, int value, RAMEvent e) { - MOS65C02 cpu = (MOS65C02) Computer.getComputer().getCpu(); + MOS65C02 cpu = (MOS65C02) computer.getCpu(); // System.out.println(e.getType()+" "+Integer.toHexString(e.getAddress())+" from instruction at "+Integer.toHexString(cpu.getProgramCounter())); if (type.isRead()) { Emulator.getFrame().addIndicator(this, currentDrive.getIcon()); @@ -172,7 +172,7 @@ public class CardMassStorage extends Card implements MediaConsumerParent { try { if (drive1.getCurrentDisk() != null) { currentDrive = drive1; - getCurrentDisk().boot0(getSlot()); + getCurrentDisk().boot0(getSlot(), computer); } else { // Patch for crash on start when no image is mounted e.setNewValue(0x060); @@ -185,7 +185,7 @@ public class CardMassStorage extends Card implements MediaConsumerParent { cpu.setProgramCounter(0x0dfff); int address = 0x0480; for (char c : error.toCharArray()) { - Computer.getComputer().getMemory().write(address++, (byte) (c + 0x080), false, false); + computer.getMemory().write(address++, (byte) (c + 0x080), false, false); } } } else { @@ -231,7 +231,7 @@ public class CardMassStorage extends Card implements MediaConsumerParent { public void tick() { // Nothing is done per CPU cycle } - SmartportDriver smartport = new SmartportDriver() { + SmartportDriver smartport = new SmartportDriver(computer) { @Override public boolean changeUnit(int unitNumber) { currentDrive = unitNumber == 1 ? drive1 : drive2; @@ -240,12 +240,12 @@ public class CardMassStorage extends Card implements MediaConsumerParent { @Override public void read(int blockNum, int buffer) throws IOException { - getCurrentDisk().mliRead(blockNum, buffer); + getCurrentDisk().mliRead(blockNum, buffer, computer.getMemory()); } @Override public void write(int blockNum, int buffer) throws IOException { - getCurrentDisk().mliWrite(blockNum, buffer); + getCurrentDisk().mliWrite(blockNum, buffer, computer.getMemory()); } @Override diff --git a/src/main/java/jace/hardware/massStorage/IDisk.java b/src/main/java/jace/hardware/massStorage/IDisk.java index cfb5dd5..fecff4c 100644 --- a/src/main/java/jace/hardware/massStorage/IDisk.java +++ b/src/main/java/jace/hardware/massStorage/IDisk.java @@ -18,6 +18,8 @@ */ package jace.hardware.massStorage; +import jace.core.Computer; +import jace.core.RAM; import java.io.IOException; /** @@ -29,9 +31,9 @@ public interface IDisk { public static int MAX_BLOCK = 65535; public void mliFormat() throws IOException; - public void mliRead(int block, int bufferAddress) throws IOException; - public void mliWrite(int block, int bufferAddress) throws IOException; - public void boot0(int slot) throws IOException; + public void mliRead(int block, int bufferAddress, RAM memory) throws IOException; + public void mliWrite(int block, int bufferAddress, RAM memory) throws IOException; + public void boot0(int slot, Computer computer) throws IOException; // Return size in 512k blocks public int getSize(); diff --git a/src/main/java/jace/hardware/massStorage/LargeDisk.java b/src/main/java/jace/hardware/massStorage/LargeDisk.java index 1892564..ba445dc 100644 --- a/src/main/java/jace/hardware/massStorage/LargeDisk.java +++ b/src/main/java/jace/hardware/massStorage/LargeDisk.java @@ -51,12 +51,13 @@ public class LargeDisk implements IDisk { } } + @Override public void mliFormat() throws IOException { throw new UnsupportedOperationException("Not supported yet."); } - public void mliRead(int block, int bufferAddress) throws IOException { - RAM memory = Computer.getComputer().getMemory(); + @Override + public void mliRead(int block, int bufferAddress, RAM memory) throws IOException { if (block < physicalBlocks) { diskImage.seek((block * BLOCK_SIZE) + dataOffset); for (int i = 0; i < BLOCK_SIZE; i++) { @@ -69,9 +70,9 @@ public class LargeDisk implements IDisk { } } - public void mliWrite(int block, int bufferAddress) throws IOException { + @Override + public void mliWrite(int block, int bufferAddress, RAM memory) throws IOException { if (block < physicalBlocks) { - RAM memory = Computer.getComputer().getMemory(); diskImage.seek((block * BLOCK_SIZE) + dataOffset); byte[] buf = new byte[BLOCK_SIZE]; for (int i = 0; i < BLOCK_SIZE; i++) { @@ -81,19 +82,20 @@ public class LargeDisk implements IDisk { } } - public void boot0(int slot) throws IOException { - Computer.getComputer().getCpu().suspend(); - mliRead(0, 0x0800); + @Override + public void boot0(int slot, Computer computer) throws IOException { + computer.getCpu().suspend(); + mliRead(0, 0x0800, computer.getMemory()); byte slot16 = (byte) (slot << 4); - ((MOS65C02) Computer.getComputer().getCpu()).X = slot16; - RAM memory = Computer.getComputer().getMemory(); + ((MOS65C02) computer.getCpu()).X = slot16; + RAM memory = computer.getMemory(); memory.write(CardMassStorage.SLT16, slot16, false, false); memory.write(MLI_COMMAND, (byte) MLI_COMMAND_TYPE.READ.intValue, false, false); memory.write(MLI_UNITNUMBER, slot16, false, false); // Write location to block read routine to zero page memory.writeWord(0x048, 0x0c000 + CardMassStorage.DEVICE_DRIVER_OFFSET + (slot * 0x0100), false, false); - ((MOS65C02) Computer.getComputer().getCpu()).setProgramCounter(0x0800); - Computer.getComputer().getCpu().resume(); + ((MOS65C02) computer.getCpu()).setProgramCounter(0x0800); + computer.getCpu().resume(); } public File getPhysicalPath() { @@ -123,7 +125,9 @@ public class LargeDisk implements IDisk { Logger.getLogger(LargeDisk.class.getName()).log(Level.SEVERE, null, ex); } finally { try { - fis.close(); + if (fis != null) { + fis.close(); + } } catch (IOException ex) { Logger.getLogger(LargeDisk.class.getName()).log(Level.SEVERE, null, ex); } diff --git a/src/main/java/jace/hardware/massStorage/ProdosVirtualDisk.java b/src/main/java/jace/hardware/massStorage/ProdosVirtualDisk.java index 2d02ecc..443fb17 100644 --- a/src/main/java/jace/hardware/massStorage/ProdosVirtualDisk.java +++ b/src/main/java/jace/hardware/massStorage/ProdosVirtualDisk.java @@ -55,10 +55,10 @@ public class ProdosVirtualDisk implements IDisk { setPhysicalPath(rootPath); } - public void mliRead(int block, int bufferAddress) throws IOException { + @Override + public void mliRead(int block, int bufferAddress, RAM memory) throws IOException { // System.out.println("Read block " + block + " to " + Integer.toHexString(bufferAddress)); DiskNode node = physicalMap.get(block); - RAM memory = Computer.getComputer().getMemory(); Arrays.fill(ioBuffer, (byte) (block & 0x0ff)); if (node == null) { System.out.println("Reading unknown block?!"); @@ -83,11 +83,12 @@ public class ProdosVirtualDisk implements IDisk { // System.out.println(); } - public void mliWrite(int block, int bufferAddress) throws IOException { + @Override + public void mliWrite(int block, int bufferAddress, RAM memory) throws IOException { System.out.println("Write block " + block + " to " + Integer.toHexString(bufferAddress)); throw new IOException("Write not implemented yet!"); // DiskNode node = physicalMap.get(block); -// RAM memory = Computer.getComputer().getMemory(); +// RAM memory = computer.getMemory(); // if (node == null) { // // CAPTURE WRITES TO UNUSED BLOCKS // } else { @@ -98,6 +99,7 @@ public class ProdosVirtualDisk implements IDisk { // } } + @Override public void mliFormat() { throw new UnsupportedOperationException("Formatting for this type of media is not supported!"); } @@ -132,9 +134,9 @@ public class ProdosVirtualDisk implements IDisk { // Mark space occupied by node public void allocateEntry(DiskNode node) { physicalMap.put(node.baseBlock, node); - for (DiskNode sub : node.additionalNodes) { + node.additionalNodes.stream().forEach((sub) -> { physicalMap.put(sub.getBaseBlock(), sub); - } + }); } // Mark space occupied by nodes as free (remove allocation mapping) @@ -143,11 +145,11 @@ public class ProdosVirtualDisk implements IDisk { if (physicalMap.get(node.baseBlock) != null && physicalMap.get(node.baseBlock).equals(node)) { physicalMap.remove(node.baseBlock); } - for (DiskNode sub : node.additionalNodes) { - if (physicalMap.get(sub.getBaseBlock()) != null && physicalMap.get(sub.baseBlock).equals(sub)) { - physicalMap.remove(sub.getBaseBlock()); - } - } + node.additionalNodes.stream().filter((sub) -> + (physicalMap.get(sub.getBaseBlock()) != null && physicalMap.get(sub.baseBlock).equals(sub))). + forEach((sub) -> { + physicalMap.remove(sub.getBaseBlock()); + }); } // Is the specified block in use? @@ -156,22 +158,22 @@ public class ProdosVirtualDisk implements IDisk { } @Override - public void boot0(int slot) throws IOException { + public void boot0(int slot, Computer computer) throws IOException { File prodos = locateFile(physicalRoot, "PRODOS.SYS"); if (prodos == null || !prodos.exists()) { throw new IOException("Unable to locate PRODOS.SYS"); } - Computer.getComputer().getCpu().suspend(); + computer.getCpu().suspend(); byte slot16 = (byte) (slot << 4); - ((MOS65C02) Computer.getComputer().getCpu()).X = slot16; - RAM memory = Computer.getComputer().getMemory(); + ((MOS65C02) computer.getCpu()).X = slot16; + RAM memory = computer.getMemory(); memory.write(CardMassStorage.SLT16, slot16, false, false); memory.write(MLI_COMMAND, (byte) MLI_COMMAND_TYPE.READ.intValue, false, false); memory.write(MLI_UNITNUMBER, slot16, false, false); // Write location to block read routine to zero page memory.writeWord(0x048, 0x0c000 + CardMassStorage.DEVICE_DRIVER_OFFSET + (slot * 0x0100), false, false); EmulatorUILogic.brun(prodos, 0x02000); - Computer.getComputer().getCpu().resume(); + computer.getCpu().resume(); } public File getPhysicalPath() { @@ -183,7 +185,7 @@ public class ProdosVirtualDisk implements IDisk { return; } physicalRoot = f; - physicalMap = new HashMap(); + physicalMap = new HashMap<>(); if (!physicalRoot.exists() || !physicalRoot.isDirectory()) { try { throw new IOException("Root path must be a directory that exists!"); @@ -201,6 +203,7 @@ public class ProdosVirtualDisk implements IDisk { } + @Override public void eject() { // Nothing to do here... } diff --git a/src/main/java/jace/hardware/mockingboard/R6522.java b/src/main/java/jace/hardware/mockingboard/R6522.java index ba27427..58f514f 100644 --- a/src/main/java/jace/hardware/mockingboard/R6522.java +++ b/src/main/java/jace/hardware/mockingboard/R6522.java @@ -27,7 +27,8 @@ import jace.core.Device; */ public abstract class R6522 extends Device { - public R6522() { + public R6522(Computer computer) { + super(computer); } // 6522 VIA @@ -140,7 +141,7 @@ public abstract class R6522 extends Device { if (timer1interruptEnabled) { // System.out.println("Timer 1 generated interrupt"); timer1IRQ = true; - Computer.getComputer().getCpu().generateInterrupt(); + computer.getCpu().generateInterrupt(); } } } @@ -151,7 +152,7 @@ public abstract class R6522 extends Device { timer2counter = timer2latch; if (timer2interruptEnabled) { timer2IRQ = true; - Computer.getComputer().getCpu().generateInterrupt(); + computer.getCpu().generateInterrupt(); } } } diff --git a/src/main/java/jace/library/MediaLibrary.java b/src/main/java/jace/library/MediaLibrary.java index 01e1fc0..8a93f96 100644 --- a/src/main/java/jace/library/MediaLibrary.java +++ b/src/main/java/jace/library/MediaLibrary.java @@ -18,10 +18,10 @@ */ package jace.library; +import jace.Emulator; import jace.config.ConfigurableField; import jace.config.Reconfigurable; import jace.core.Card; -import jace.core.Computer; import java.awt.Dimension; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; @@ -50,14 +50,17 @@ public class MediaLibrary implements Reconfigurable { @ConfigurableField(category = "Library", defaultValue = "true", name = "Keep local copy", description = "Automatically download and save local copies of disks when written.") public static boolean CREATE_LOCAL_ON_SAVE = true; + @Override public String getName() { return "Media Library"; } + @Override public String getShortName() { return "media"; } + @Override public void reconfigure() { rebuildDriveList(); } @@ -76,7 +79,7 @@ public class MediaLibrary implements Reconfigurable { return; } userInterface.Drives.removeAll(); - for (Card card : Computer.getComputer().memory.getAllCards()) { + for (Card card : Emulator.computer.memory.getAllCards()) { if (card == null || !(card instanceof MediaConsumerParent)) { continue; } diff --git a/src/main/java/jace/state/StateManager.java b/src/main/java/jace/state/StateManager.java index f072f10..adec856 100644 --- a/src/main/java/jace/state/StateManager.java +++ b/src/main/java/jace/state/StateManager.java @@ -46,9 +46,9 @@ public class StateManager implements Reconfigurable { private static StateManager instance; - public static StateManager getInstance() { + public static StateManager getInstance(Computer computer) { if (instance == null) { - instance = new StateManager(); + instance = new StateManager(computer); } return instance; } @@ -63,9 +63,14 @@ public class StateManager implements Reconfigurable { public int captureFrequency = 3; private ObjectGraphNode imageGraphNode; + Computer computer; + private StateManager(Computer computer) { + this.computer = computer; + } + private void buildStateMap() { - allStateVariables = new HashSet(); - objectLookup = new WeakHashMap(); + allStateVariables = new HashSet<>(); + objectLookup = new WeakHashMap<>(); ObjectGraphNode emulator = new ObjectGraphNode(Emulator.instance); emulator.name = "Emulator"; Set visited = new HashSet(); @@ -235,8 +240,8 @@ public class StateManager implements Reconfigurable { } } - public static void markDirtyValue(Object o) { - StateManager manager = getInstance(); + public static void markDirtyValue(Object o, Computer computer) { + StateManager manager = getInstance(computer); if (manager.objectLookup == null) { return; } @@ -259,8 +264,9 @@ public class StateManager implements Reconfigurable { * If reconfigure is called, it means the emulator state has changed too * greatly and we need to abandon captured states and start from scratch. */ + @Override public void reconfigure() { - boolean resume = Computer.pause(); + boolean resume = computer.pause(); isValid = false; // Now figure out how much memory we're allowed to eat @@ -269,7 +275,7 @@ public class StateManager implements Reconfigurable { freeRequired = maxMemory / 50L; frameCounter = captureFrequency; if (resume) { - Computer.resume(); + computer.resume(); } } boolean isValid = false; @@ -329,7 +335,7 @@ public class StateManager implements Reconfigurable { } private BufferedImage getScreenshot() { - BufferedImage screen = Computer.getComputer().getVideo().getFrameBuffer(); + BufferedImage screen = computer.getVideo().getFrameBuffer(); ColorModel cm = screen.getColorModel(); boolean isAlphaPremultiplied = cm.isAlphaPremultiplied(); WritableRaster raster = screen.copyData(null); @@ -391,7 +397,7 @@ public class StateManager implements Reconfigurable { } public void rewind(int numStates) { - boolean resume = Computer.pause(); + boolean resume = computer.pause(); State state = alphaState.tail; while (numStates > 0 && state.previousState != null) { state = state.previousState; @@ -400,10 +406,10 @@ public class StateManager implements Reconfigurable { state.apply(); alphaState.tail = state; state.nextState = null; - Computer.getComputer().getVideo().forceRefresh(); + computer.getVideo().forceRefresh(); System.gc(); if (resume) { - Computer.resume(); + computer.resume(); } } } diff --git a/src/main/java/jace/tracker/PlaybackEngine.java b/src/main/java/jace/tracker/PlaybackEngine.java index 16689d6..5f9050d 100644 --- a/src/main/java/jace/tracker/PlaybackEngine.java +++ b/src/main/java/jace/tracker/PlaybackEngine.java @@ -31,12 +31,49 @@ import jace.hardware.CardMockingboard; */ public class PlaybackEngine extends Computer { - Motherboard motherboard = new Motherboard(); - CardMockingboard mockingboard = new CardMockingboard(); + Computer dummyComputer = new Computer() { + + @Override + public void coldStart() { + throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + } + + @Override + public void warmStart() { + throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + } + + @Override + protected boolean isRunning() { + throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + } + + @Override + protected void doPause() { + throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + } + + @Override + protected void doResume() { + throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + } + + @Override + public String getName() { + throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + } + + @Override + public String getShortName() { + throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + } + }; + Motherboard motherboard = new Motherboard(dummyComputer); + CardMockingboard mockingboard = new CardMockingboard(dummyComputer); public PlaybackEngine() { - setMemory(new CardExt80Col()); - setCpu(new MOS65C02()); + setMemory(new CardExt80Col(dummyComputer)); + setCpu(new MOS65C02(dummyComputer)); getMemory().addCard(mockingboard, 5); } diff --git a/src/main/java/jace/ui/AbstractEmulatorFrame.java b/src/main/java/jace/ui/AbstractEmulatorFrame.java index a757574..dc23def 100644 --- a/src/main/java/jace/ui/AbstractEmulatorFrame.java +++ b/src/main/java/jace/ui/AbstractEmulatorFrame.java @@ -50,12 +50,17 @@ import javax.swing.JPanel; */ public abstract class AbstractEmulatorFrame extends javax.swing.JFrame implements Reconfigurable { + Computer computer; /** * Creates new form AbstractEmulatorFrame */ public AbstractEmulatorFrame() { initComponents(); } + + public void setComputer(Computer computer) { + this.computer = computer; + } @Override public synchronized void addKeyListener(KeyListener l) { @@ -252,39 +257,32 @@ public abstract class AbstractEmulatorFrame extends javax.swing.JFrame implement private Map> indicators = new HashMap>(); public void resizeVideo() { - EventQueue.invokeLater(new Runnable() { - @Override - public void run() { - Computer.pause(); - Computer.getComputer().getVideo().suspend(); - JPanel debugger = getDebuggerPanel(); - Component screen = getScreen(); - Rectangle bounds = screen.getParent().getBounds(); - int width = (int) bounds.getWidth(); - int height = (int) bounds.getHeight(); - if (debugger.isVisible()) { - debugger.setBounds(width - debugger.getWidth(), 0, debugger.getWidth(), height); - width = (int) bounds.getWidth() - debugger.getWidth() + 1; - screen.setSize( - width, - height); - debugger.revalidate(); - } else { - screen.setSize( - width, - height); - } - Computer.getComputer().getVideo().setWidth(width); - Computer.getComputer().getVideo().setHeight(height); - if (!isFullscreen || !fullscreenEnforceRatio) { - Computer.getComputer().getVideo().setScreen(getScreenGraphics()); - } - Computer.getComputer().getVideo().forceRefresh(); - screen.validate(); - screen.requestFocusInWindow(); - Computer.resume(); - Computer.getComputer().getVideo().resume(); + EventQueue.invokeLater(() -> { + computer.pause(); + computer.getVideo().suspend(); + JPanel debugger = getDebuggerPanel(); + Component screen = getScreen(); + Rectangle bounds = screen.getParent().getBounds(); + int width1 = (int) bounds.getWidth(); + int height1 = (int) bounds.getHeight(); + if (debugger.isVisible()) { + debugger.setBounds(width1 - debugger.getWidth(), 0, debugger.getWidth(), height1); + width1 = (int) bounds.getWidth() - debugger.getWidth() + 1; + screen.setSize(width1, height1); + debugger.revalidate(); + } else { + screen.setSize(width1, height1); } + computer.getVideo().setWidth(width1); + computer.getVideo().setHeight(height1); + if (!isFullscreen || !fullscreenEnforceRatio) { + computer.getVideo().setScreen(getScreenGraphics()); + } + computer.getVideo().forceRefresh(); + screen.validate(); + screen.requestFocusInWindow(); + computer.resume(); + computer.getVideo().resume(); }); } @@ -324,8 +322,8 @@ public abstract class AbstractEmulatorFrame extends javax.swing.JFrame implement b.setSize(560 * scale, 384 * scale); b.x = (w / 2) - (b.width / 2); b.y = (h / 2) - (b.height / 2); - Computer.pause(); - Computer.getComputer().getVideo().suspend(); + computer.pause(); + computer.getVideo().suspend(); try { Thread.sleep(100); } catch (InterruptedException ex) { @@ -335,9 +333,9 @@ public abstract class AbstractEmulatorFrame extends javax.swing.JFrame implement g.fill(getBounds()); Graphics2D gg = (Graphics2D) g.create(b.x, b.y, b.width, b.height); gg.scale((double) b.width / (double) sw, (double) b.height / (double) sh); - Computer.getComputer().getVideo().setScreen(gg); - Computer.getComputer().getVideo().resume(); - Computer.resume(); + computer.getVideo().setScreen(gg); + computer.getVideo().resume(); + computer.resume(); } else { b = getBounds(); getScreen().setBounds(getBounds()); @@ -364,8 +362,8 @@ public abstract class AbstractEmulatorFrame extends javax.swing.JFrame implement EventQueue.invokeLater(new Runnable() { @Override public void run() { - Computer.pause(); - Computer.getComputer().getVideo().suspend(); + computer.pause(); + computer.getVideo().suspend(); isFullscreen = !isFullscreen; GraphicsDevice device = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice(); if (isFullscreen) { @@ -382,8 +380,8 @@ public abstract class AbstractEmulatorFrame extends javax.swing.JFrame implement device.setFullScreenWindow(null); } resizeVideo(); - Computer.getComputer().getVideo().resume(); - Computer.resume(); + computer.getVideo().resume(); + computer.resume(); } }); } diff --git a/src/main/java/jace/ui/EmulatorFrame.form b/src/main/java/jace/ui/EmulatorFrame.form index 109d3d4..1028060 100644 --- a/src/main/java/jace/ui/EmulatorFrame.form +++ b/src/main/java/jace/ui/EmulatorFrame.form @@ -1,6 +1,6 @@ -
+ @@ -47,12 +47,14 @@ - + + + - - + + @@ -70,9 +72,12 @@ + + + - - + + diff --git a/src/main/java/jace/ui/EmulatorFrame.java b/src/main/java/jace/ui/EmulatorFrame.java index f1d1964..d67b0e2 100644 --- a/src/main/java/jace/ui/EmulatorFrame.java +++ b/src/main/java/jace/ui/EmulatorFrame.java @@ -77,7 +77,8 @@ public class EmulatorFrame extends AbstractEmulatorFrame { /** * Creates new form EmulatorFrame */ - public EmulatorFrame() { + public EmulatorFrame(Computer computer) { + setComputer(computer); initComponents(); layers.setDoubleBuffered(true); screen.setDoubleBuffered(true); @@ -94,6 +95,7 @@ public class EmulatorFrame extends AbstractEmulatorFrame { screen.setFocusTraversalKeysEnabled(false); } + @Override public synchronized void addKeyListener(KeyListener l) { super.addKeyListener(l); layers.addKeyListener(l); @@ -154,10 +156,8 @@ public class EmulatorFrame extends AbstractEmulatorFrame { * @param args the command line arguments */ public static void main(String args[]) { - java.awt.EventQueue.invokeLater(new Runnable() { - public void run() { - new EmulatorFrame().setVisible(true); - } + java.awt.EventQueue.invokeLater(() -> { + new EmulatorFrame(null).setVisible(true); }); } // Variables declaration - do not modify//GEN-BEGIN:variables @@ -165,15 +165,17 @@ public class EmulatorFrame extends AbstractEmulatorFrame { public javax.swing.JLayeredPane layers; public jace.ui.ScreenPanel screen; // End of variables declaration//GEN-END:variables - Set previousIndicators = new HashSet(); + Set previousIndicators = new HashSet<>(); @Override public void doRedrawIndicators(Set ind) { synchronized (previousIndicators) { - for (JLabel l : previousIndicators) { + previousIndicators.stream().map((l) -> { l.setVisible(false); + return l; + }).forEach((l) -> { layers.remove(l); - } + }); previousIndicators.clear(); } if (ind != null && !ind.isEmpty()) { @@ -195,8 +197,8 @@ public class EmulatorFrame extends AbstractEmulatorFrame { label.setVisible(true); } } else { - if (Computer.getComputer() != null && Computer.getComputer().video != null) { - Computer.getComputer().video.forceRefresh(); + if (computer != null && computer.video != null) { + computer.video.forceRefresh(); } // This was causing a whole screen flicker -- bad. // screen.repaint(); @@ -208,16 +210,16 @@ public class EmulatorFrame extends AbstractEmulatorFrame { public void repaintIndicators() { synchronized (previousIndicators) { if (previousIndicators != null) { - for (JLabel l : previousIndicators) { + previousIndicators.stream().forEach((l) -> { Graphics g = l.getGraphics(); if (g != null) { l.paint(g); } - } + }); } } } - Map indicatorCache = new HashMap(); + Map indicatorCache = new HashMap<>(); private JLabel createIndicatorIcon(ImageIcon i) { if (indicatorCache.containsKey(i)) { @@ -240,7 +242,7 @@ public class EmulatorFrame extends AbstractEmulatorFrame { indicatorCache.put(i, renderedLabel); return renderedLabel; } - Map modals = new HashMap(); + Map modals = new HashMap<>(); @Override protected void displayModalDialog(final String name, JPanel ui, List ancestors) { diff --git a/src/main/java/jace/ui/MainFrame.java b/src/main/java/jace/ui/MainFrame.java index a3d7205..11dd520 100644 --- a/src/main/java/jace/ui/MainFrame.java +++ b/src/main/java/jace/ui/MainFrame.java @@ -91,10 +91,8 @@ public class MainFrame extends AbstractEmulatorFrame { * @param args the command line arguments */ public static void main(String args[]) { - java.awt.EventQueue.invokeLater(new Runnable() { - public void run() { - new MainFrame().setVisible(true); - } + java.awt.EventQueue.invokeLater(() -> { + new MainFrame().setVisible(true); }); } // Variables declaration - do not modify//GEN-BEGIN:variables diff --git a/src/main/java/jace/ui/ScreenCanvas.java b/src/main/java/jace/ui/ScreenCanvas.java index 9f0f56a..f235a9f 100644 --- a/src/main/java/jace/ui/ScreenCanvas.java +++ b/src/main/java/jace/ui/ScreenCanvas.java @@ -18,6 +18,7 @@ */ package jace.ui; +import jace.Emulator; import jace.core.Computer; import java.awt.Canvas; import java.awt.Color; @@ -31,15 +32,21 @@ import java.awt.Graphics; */ public class ScreenCanvas extends Canvas { + Computer computer; public ScreenCanvas() { setBackground(new Color(0, 0, 64)); setIgnoreRepaint(true); } + + public Computer getComputer() { + return Emulator.computer; + } + @Override public void paint(Graphics g) { - if (Computer.getComputer() != null) { - Computer.getComputer().getVideo().forceRefresh(); + if (getComputer() != null) { + getComputer().getVideo().forceRefresh(); } } } diff --git a/src/main/java/jace/ui/ScreenPanel.java b/src/main/java/jace/ui/ScreenPanel.java index 5f0724f..e7ceef3 100644 --- a/src/main/java/jace/ui/ScreenPanel.java +++ b/src/main/java/jace/ui/ScreenPanel.java @@ -18,6 +18,7 @@ */ package jace.ui; +import jace.Emulator; import jace.core.Computer; import java.awt.Color; import java.awt.Graphics; @@ -35,11 +36,15 @@ public class ScreenPanel extends JPanel { setBackground(new Color(0, 0, 64)); setOpaque(false); } + + public Computer getComputer() { + return Emulator.computer; + } @Override public void paint(Graphics g) { - if (Computer.getComputer() != null) { - Computer.getComputer().getVideo().forceRefresh(); + if (getComputer() != null) { + getComputer().getVideo().forceRefresh(); } } } diff --git a/target/maven-archiver/pom.properties b/target/maven-archiver/pom.properties index 387ad6d..aad01bd 100644 --- a/target/maven-archiver/pom.properties +++ b/target/maven-archiver/pom.properties @@ -1,5 +1,5 @@ #Generated by Maven -#Sun Sep 07 16:06:31 CDT 2014 +#Wed Sep 17 00:59:53 CDT 2014 version=2.0-SNAPSHOT groupId=org.badvision artifactId=jace diff --git a/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst b/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst index 9d79e28..e426053 100644 --- a/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst +++ b/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst @@ -63,7 +63,6 @@ jace/apple2e/Speaker$2.class jace/cheat/MetaCheatForm.class jace/library/MediaEditUI$1.class jace/cheat/PrinceOfPersiaCheats$5.class -.netbeans_automatic_build jace/apple2e/SoftSwitches$3.class jace/library/MediaLibraryUI$tocOptions$1.class jace/core/TimedDevice.class