From 6515c90856c2aa659921a28c330d4375ee544f76 Mon Sep 17 00:00:00 2001 From: Brendan Robert Date: Tue, 23 Feb 2016 01:45:11 -0600 Subject: [PATCH] Issue #22: Minor progress hooking up state manager; still doesn't work and crashes the emulator when triggered. :/ --- src/main/java/jace/Emulator.java | 1 + src/main/java/jace/core/Video.java | 37 ++++++++++++---------- src/main/java/jace/state/State.java | 3 +- src/main/java/jace/state/StateManager.java | 22 +++++++++++-- 4 files changed, 43 insertions(+), 20 deletions(-) diff --git a/src/main/java/jace/Emulator.java b/src/main/java/jace/Emulator.java index 6349dfa..c34a18b 100644 --- a/src/main/java/jace/Emulator.java +++ b/src/main/java/jace/Emulator.java @@ -46,6 +46,7 @@ public class Emulator { * @param args */ public Emulator(List args) { + instance = this; computer = new Apple2e(); Configuration.buildTree(); Configuration.loadSettings(); diff --git a/src/main/java/jace/core/Video.java b/src/main/java/jace/core/Video.java index 45f90e0..1867a06 100644 --- a/src/main/java/jace/core/Video.java +++ b/src/main/java/jace/core/Video.java @@ -29,10 +29,9 @@ import javafx.scene.image.WritableImage; * Generic abstraction of a 560x192 video output device which renders 40 columns * per scanline. This also triggers VBL and updates the physical screen. * Subclasses are used to manage actual rendering via ScreenWriter - * implementations. - * Created on November 10, 2006, 4:29 PM + * implementations. Created on November 10, 2006, 4:29 PM * - * @author Brendan Robert (BLuRry) brendan.robert@gmail.com + * @author Brendan Robert (BLuRry) brendan.robert@gmail.com */ @Stateful public abstract class Video extends Device { @@ -90,6 +89,7 @@ public abstract class Video extends Device { /** * Creates a new instance of Video + * * @param computer */ public Video(Computer computer) { @@ -99,21 +99,21 @@ public abstract class Video extends Device { visible = new WritableImage(560, 192); vPeriod = 0; hPeriod = 0; - forceRefresh(); + _forceRefresh(); } public void setWidth(int w) { width = w; } - + public int getWidth() { return width; } - + public void setHeight(int h) { height = h; } - + public int getHeight() { return height; } @@ -136,6 +136,7 @@ public abstract class Video extends Device { visible.getPixelWriter().setPixels(0, 0, 560, 192, video.getPixelReader(), 0, 0); } }; + public void redraw() { screenDirty = false; javafx.application.Platform.runLater(redrawScreen); @@ -209,8 +210,8 @@ public abstract class Video extends Device { abstract public void configureVideoMode(); protected static int byteDoubler(byte b) { - int num = - // Skip hi-bit because it's not used in display + int num + = // Skip hi-bit because it's not used in display // ((b&0x080)<<7) | ((b & 0x040) << 6) | ((b & 0x020) << 5) @@ -271,18 +272,22 @@ public abstract class Video extends Device { } @InvokableAction(name = "Refresh screen", - category = "display", - description = "Marks screen contents as changed, forcing full screen redraw", - alternatives = "redraw", - defaultKeyMapping = {"ctrl+shift+r"}) + category = "display", + description = "Marks screen contents as changed, forcing full screen redraw", + alternatives = "redraw", + defaultKeyMapping = {"ctrl+shift+r"}) public static final void forceRefresh() { if (Emulator.computer != null && Emulator.computer.video != null) { - Emulator.computer.video.lineDirty = true; - Emulator.computer.video.screenDirty = true; - Emulator.computer.video.forceRedrawRowCount = APPLE_SCREEN_LINES + 1; + Emulator.computer.video._forceRefresh(); } } + private void _forceRefresh() { + lineDirty = true; + screenDirty = true; + forceRedrawRowCount = APPLE_SCREEN_LINES + 1; + } + @Override public String getShortName() { return "vid"; diff --git a/src/main/java/jace/state/State.java b/src/main/java/jace/state/State.java index 9e535d4..44f2f5c 100644 --- a/src/main/java/jace/state/State.java +++ b/src/main/java/jace/state/State.java @@ -21,6 +21,7 @@ package jace.state; import java.io.Serializable; import java.util.HashMap; import java.util.HashSet; +import java.util.LinkedHashSet; import java.util.Set; import javafx.scene.image.Image; @@ -78,7 +79,7 @@ public class State extends HashMap implements Seria } public void apply() { - Set applied = new HashSet<>(); + Set applied = new LinkedHashSet<>(); State current = this; while (current != null) { for (StateValue val : current.values()) { diff --git a/src/main/java/jace/state/StateManager.java b/src/main/java/jace/state/StateManager.java index 33de3ad..224007c 100644 --- a/src/main/java/jace/state/StateManager.java +++ b/src/main/java/jace/state/StateManager.java @@ -21,14 +21,17 @@ package jace.state; import jace.Emulator; import jace.apple2e.SoftSwitches; import jace.config.ConfigurableField; +import jace.config.InvokableAction; import jace.config.Reconfigurable; import jace.core.Computer; import jace.core.PagedMemory; +import jace.core.Video; import java.awt.image.BufferedImage; import java.lang.annotation.Annotation; import java.lang.reflect.Field; import java.lang.reflect.Type; import java.util.HashSet; +import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Set; @@ -37,6 +40,7 @@ import java.util.logging.Level; import java.util.logging.Logger; import javafx.scene.image.Image; import javafx.scene.image.WritableImage; +import javafx.scene.input.KeyCode; /** * @@ -64,12 +68,13 @@ public class StateManager implements Reconfigurable { private ObjectGraphNode imageGraphNode; Computer computer; + private StateManager(Computer computer) { this.computer = computer; } private void buildStateMap() { - allStateVariables = new HashSet<>(); + allStateVariables = new LinkedHashSet<>(); objectLookup = new WeakHashMap<>(); ObjectGraphNode emulator = new ObjectGraphNode(Emulator.instance); emulator.name = "Emulator"; @@ -295,7 +300,7 @@ public class StateManager implements Reconfigurable { public void captureState() { // If the state graph is invalidated it means we have to abandon all - // previously captured states. This helps ensure that rewinding will + // previously captured states. This helps ensure that rewinding will // not result in an unintended or invalid state. if (!isValid) { alphaState = null; @@ -402,6 +407,17 @@ public class StateManager implements Reconfigurable { captureState(); } + @InvokableAction( + name = "Rewind", + alternatives = "Timewarp", + description = "Go back 1 second", + defaultKeyMapping = {"ctrl+shift+Open Bracket"} + ) + public static void beKindRewind() { + StateManager manager = getInstance(Emulator.computer); + new Thread(()->manager.rewind(60 / manager.captureFrequency)).start(); + } + public void rewind(int numStates) { boolean resume = computer.pause(); State state = alphaState.tail; @@ -412,7 +428,7 @@ public class StateManager implements Reconfigurable { state.apply(); alphaState.tail = state; state.nextState = null; - computer.getVideo().forceRefresh(); + Video.forceRefresh(); System.gc(); if (resume) { computer.resume();