diff --git a/src/main/java/jace/JaceApplication.java b/src/main/java/jace/JaceApplication.java index 576cf79..c11d048 100644 --- a/src/main/java/jace/JaceApplication.java +++ b/src/main/java/jace/JaceApplication.java @@ -47,7 +47,7 @@ public class JaceApplication extends Application { Scene s = new Scene(node); primaryStage.setScene(s); primaryStage.setTitle("Jace"); - primaryStage.getIcons().add(Utility.loadIcon("woz_figure.gif")); + Utility.loadIcon("woz_figure.gif").ifPresent(primaryStage.getIcons()::add); } catch (IOException exception) { throw new RuntimeException(exception); } @@ -86,7 +86,7 @@ public class JaceApplication extends Application { Scene s = new Scene(node); cheatStage.setScene(s); cheatStage.setTitle("Jace: MetaCheat"); - cheatStage.getIcons().add(Utility.loadIcon("woz_figure.gif")); + Utility.loadIcon("woz_figure.gif").ifPresent(cheatStage.getIcons()::add); } catch (IOException exception) { throw new RuntimeException(exception); } diff --git a/src/main/java/jace/JaceUIController.java b/src/main/java/jace/JaceUIController.java index 7181bd3..778b64c 100644 --- a/src/main/java/jace/JaceUIController.java +++ b/src/main/java/jace/JaceUIController.java @@ -3,7 +3,6 @@ * To change this template file, choose Tools | Templates * and open the template in the editor. */ - package jace; import com.sun.glass.ui.Application; @@ -57,7 +56,7 @@ public class JaceUIController { @FXML private AnchorPane rootPane; - + @FXML private StackPane stackPane; @@ -68,7 +67,7 @@ public class JaceUIController { private ImageView appleScreen; Computer computer; - + @FXML void initialize() { assert rootPane != null : "fx:id=\"rootPane\" was not injected: check your FXML file 'JaceUI.fxml'."; @@ -80,18 +79,18 @@ public class JaceUIController { rootPane.setOnDragEntered(this::processDragEnteredEvent); rootPane.setOnDragExited(this::processDragExitedEvent); } - + public void connectComputer(Computer computer, Stage primaryStage) { this.computer = computer; appleScreen.setImage(computer.getVideo().getFrameBuffer()); EventHandler keyboardHandler = computer.getKeyboard().getListener(); - primaryStage.setOnShowing(evt->computer.getKeyboard().resetState()); + primaryStage.setOnShowing(evt -> computer.getKeyboard().resetState()); rootPane.setFocusTraversable(true); rootPane.setOnKeyPressed(keyboardHandler); rootPane.setOnKeyReleased(keyboardHandler); rootPane.requestFocus(); } - + private void processDragEnteredEvent(DragEvent evt) { MediaEntry media = null; if (evt.getDragboard().hasFiles()) { @@ -115,63 +114,68 @@ public class JaceUIController { startDragEvent(media); } } - + private void processDragExitedEvent(DragEvent evt) { endDragEvent(); } - private File getDraggedFile(List files) { if (files == null || files.isEmpty()) { return null; } for (File f : files) { - if (f.exists()) return f; + if (f.exists()) { + return f; + } } return null; } HBox drivePanel; + private void startDragEvent(MediaEntry media) { List consumers = getMediaConsumers(); drivePanel = new HBox(); consumers.stream() - .filter((consumer) -> (consumer.isAccepted(media, media.files.get(0)))) - .forEach((consumer) -> { - Label icon = consumer.getIcon(); - icon.setTextFill(Color.WHITE); - icon.setPadding(new Insets(2.0)); - drivePanel.getChildren().add(icon); - icon.setOnDragOver(event -> { - event.acceptTransferModes(TransferMode.ANY); - event.consume(); - }); - icon.setOnDragDropped(event -> { - System.out.println("Dropping media on "+icon.getText()); - try { - computer.pause(); - consumer.insertMedia(media, media.files.get(0)); - computer.resume(); - event.setDropCompleted(true); - event.consume(); - } catch (IOException ex) { - Logger.getLogger(JaceUIController.class.getName()).log(Level.SEVERE, null, ex); + .filter((consumer) -> (consumer.isAccepted(media, media.files.get(0)))) + .forEach((consumer) -> { + Label icon = consumer.getIcon().orElse(null); + if (icon == null) { + return; } - endDragEvent(); + icon.setTextFill(Color.WHITE); + icon.setPadding(new Insets(2.0)); + drivePanel.getChildren().add(icon); + icon.setOnDragOver(event -> { + event.acceptTransferModes(TransferMode.ANY); + event.consume(); + }); + icon.setOnDragDropped(event -> { + System.out.println("Dropping media on " + icon.getText()); + try { + computer.pause(); + consumer.insertMedia(media, media.files.get(0)); + computer.resume(); + event.setDropCompleted(true); + event.consume(); + } catch (IOException ex) { + Logger.getLogger(JaceUIController.class.getName()).log(Level.SEVERE, null, ex); + } + endDragEvent(); + }); }); - }); - stackPane.getChildren().add(drivePanel); + stackPane.getChildren().add(drivePanel); drivePanel.setLayoutX(10); drivePanel.setLayoutY(10); } - + private void endDragEvent() { stackPane.getChildren().remove(drivePanel); drivePanel.getChildren().stream().forEach((n) -> { n.setOnDragDropped(null); }); } - + private List getMediaConsumers() { List consumers = new ArrayList<>(); for (Optional card : computer.memory.getAllCards()) { @@ -181,14 +185,16 @@ public class JaceUIController { } return consumers; } - + Map iconTTL = new ConcurrentHashMap<>(); + void addIndicator(Label icon) { addIndicator(icon, 250); } + void addIndicator(Label icon, long TTL) { if (!iconTTL.containsKey(icon)) { - Application.invokeLater(()->{ + Application.invokeLater(() -> { if (!notificationBox.getChildren().contains(icon)) { notificationBox.getChildren().add(icon); } @@ -198,39 +204,40 @@ public class JaceUIController { } void removeIndicator(Label icon) { - Application.invokeLater(()->{ + Application.invokeLater(() -> { notificationBox.getChildren().remove(icon); iconTTL.remove(icon); }); - } + } ScheduledExecutorService notificationExecutor = Executors.newSingleThreadScheduledExecutor(); ScheduledFuture ttlCleanupTask = null; + private void trackTTL(Label icon, long TTL) { - iconTTL.put(icon, System.currentTimeMillis()+TTL); - - if (ttlCleanupTask == null || ttlCleanupTask.isCancelled()) { + iconTTL.put(icon, System.currentTimeMillis() + TTL); + + if (ttlCleanupTask == null || ttlCleanupTask.isCancelled()) { ttlCleanupTask = notificationExecutor.scheduleWithFixedDelay(this::processTTL, 1, 100, TimeUnit.MILLISECONDS); } } - + private void processTTL() { Long now = System.currentTimeMillis(); iconTTL.keySet().stream() - .filter((icon) -> (iconTTL.get(icon) <= now)) - .forEach((icon) -> { - removeIndicator(icon); - }); + .filter((icon) -> (iconTTL.get(icon) <= now)) + .forEach((icon) -> { + removeIndicator(icon); + }); if (iconTTL.isEmpty()) { ttlCleanupTask.cancel(true); ttlCleanupTask = null; } } - + public void addMouseListener(EventHandler handler) { appleScreen.addEventHandler(MouseEvent.ANY, handler); } - + public void removeMouseListener(EventHandler handler) { appleScreen.removeEventHandler(MouseEvent.ANY, handler); } diff --git a/src/main/java/jace/apple2e/MOS65C02.java b/src/main/java/jace/apple2e/MOS65C02.java index b19b3cc..09574a4 100644 --- a/src/main/java/jace/apple2e/MOS65C02.java +++ b/src/main/java/jace/apple2e/MOS65C02.java @@ -77,12 +77,29 @@ public class MOS65C02 extends CPU { public MOS65C02(Computer computer) { super(computer); + clearState(); } @Override public void reconfigure() { } + @Override + public void clearState() { + A = 0x0ff; + X = 0x0ff; + Y = 0x0ff; + C = 1; + interruptSignalled = false; + Z = true; + I = true; + D = true; + B = true; + V = true; + N = true; + STACK = 0xff; + } + public enum OPCODE { ADC_IMM(0x0069, COMMAND.ADC, MODE.IMMEDIATE, 2), ADC_ZP(0x0065, COMMAND.ADC, MODE.ZEROPAGE, 3), @@ -369,7 +386,7 @@ public class MOS65C02 extends CPU { int pc = cpu.getProgramCounter(); 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)); + cpu.setPageBoundaryPenalty((address & 0x00ff00) != ((pc+2) & 0x00ff00)); return address; }, false), IMMEDIATE(2, "#$~1", (cpu) -> cpu.getProgramCounter() + 1), diff --git a/src/main/java/jace/assembly/AssemblyHandler.java b/src/main/java/jace/assembly/AssemblyHandler.java index d462d16..5cc12b3 100644 --- a/src/main/java/jace/assembly/AssemblyHandler.java +++ b/src/main/java/jace/assembly/AssemblyHandler.java @@ -32,7 +32,11 @@ public class AssemblyHandler implements LanguageHandler { public void execute(CompileResult lastResult) { if (lastResult.isSuccessful()) { try { - Emulator.computer.pause(); + boolean resume = false; + if (Emulator.computer.isRunning()) { + resume = true; + Emulator.computer.pause(); + } RAM memory = Emulator.computer.getMemory(); FileInputStream input = new FileInputStream(lastResult.getCompiledAsset()); int startLSB = input.read(); @@ -43,7 +47,9 @@ public class AssemblyHandler implements LanguageHandler { while ((next=input.read()) != -1) { memory.write(pos++, (byte) next, false, true); } - Emulator.computer.resume(); + if (resume) { + Emulator.computer.resume(); + } } catch (IOException ex) { Logger.getLogger(AssemblyHandler.class.getName()).log(Level.SEVERE, null, ex); } diff --git a/src/main/java/jace/config/Configuration.java b/src/main/java/jace/config/Configuration.java index e60459d..277e8dc 100644 --- a/src/main/java/jace/config/Configuration.java +++ b/src/main/java/jace/config/Configuration.java @@ -51,6 +51,7 @@ import java.util.logging.Level; import java.util.logging.Logger; import javafx.collections.ObservableList; import javafx.scene.control.TreeItem; +import javafx.scene.image.Image; import javafx.scene.image.ImageView; /** @@ -93,8 +94,13 @@ public class Configuration implements Reconfigurable { return null; } - public static ImageView getChangedIcon() { - return new ImageView(Utility.loadIcon("icon_exclaim.gif")); + public static Optional getChangedIcon() { + Optional icon = Utility.loadIcon("icon_exclaim.gif"); + if (icon.isPresent()) { + return Optional.of(new ImageView(icon.get())); + } else { + return Optional.empty(); + } } @Override @@ -251,7 +257,7 @@ public class Configuration implements Reconfigurable { if (!changed) { setGraphic(null); } else { - setGraphic(getChangedIcon()); + getChangedIcon().ifPresent(this::setGraphic); } } } diff --git a/src/main/java/jace/core/CPU.java b/src/main/java/jace/core/CPU.java index aa7bb8b..3718133 100644 --- a/src/main/java/jace/core/CPU.java +++ b/src/main/java/jace/core/CPU.java @@ -175,4 +175,6 @@ public abstract class CPU extends Device { lastTrace = trace; singleTraceEnabled = false; } + + abstract public void clearState(); } \ No newline at end of file diff --git a/src/main/java/jace/core/Utility.java b/src/main/java/jace/core/Utility.java index 63f596b..533be9f 100644 --- a/src/main/java/jace/core/Utility.java +++ b/src/main/java/jace/core/Utility.java @@ -31,6 +31,7 @@ import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; @@ -280,13 +281,24 @@ public class Utility { return result; } - public static Image loadIcon(String filename) { + private static boolean isHeadless = false; + public static void setHeadlessMode(boolean headless) { + isHeadless = headless; + } + + public static Optional loadIcon(String filename) { + if (isHeadless) { + return Optional.empty(); + } InputStream stream = Utility.class.getClassLoader().getResourceAsStream("jace/data/" + filename); - return new Image(stream); + return Optional.of(new Image(stream)); } - public static Label loadIconLabel(String filename) { - Image img = loadIcon(filename); + public static Optional