diff --git a/.gitignore b/.gitignore
index bfd9e992..ec5693fa 100644
--- a/.gitignore
+++ b/.gitignore
@@ -60,4 +60,11 @@ error_stack.txt
# Ignore special links Martin uses
/Platform/Apple/virtual/genBuild
/Platform/Apple/virtual/mapBuild
-/Platform/Apple/virtual/plasBuild
\ No newline at end of file
+/Platform/Apple/virtual/plasBuild
+
+# Hey, don't include the commercial game data you ninny!
+/Platform/Apple/tools/jace/src/main/resources/jace/data/game.2mg
+
+# Ignore NetBeans project files
+Platform/Apple/tools/jace/nb-configuration.xml
+Platform/Apple/tools/jace/nbactions.xml
diff --git a/.java-version b/.java-version
new file mode 100644
index 00000000..2f32724e
--- /dev/null
+++ b/.java-version
@@ -0,0 +1 @@
+graalvm64-17.0.6
diff --git a/OutlawEditor/.java-version b/OutlawEditor/.java-version
new file mode 100644
index 00000000..62593409
--- /dev/null
+++ b/OutlawEditor/.java-version
@@ -0,0 +1 @@
+1.8
diff --git a/Platform/Apple/tools/jace/.java-version b/Platform/Apple/tools/jace/.java-version
index 62593409..2f32724e 100644
--- a/Platform/Apple/tools/jace/.java-version
+++ b/Platform/Apple/tools/jace/.java-version
@@ -1 +1 @@
-1.8
+graalvm64-17.0.6
diff --git a/Platform/Apple/tools/jace/nb-configuration.xml b/Platform/Apple/tools/jace/nb-configuration.xml
index 4a4218e2..b60ff425 100644
--- a/Platform/Apple/tools/jace/nb-configuration.xml
+++ b/Platform/Apple/tools/jace/nb-configuration.xml
@@ -14,6 +14,6 @@ That way multiple projects can share the same settings (useful for formatting ru
Any value defined here will override the pom.xml file value but is only applicable to the current project.
-->
HTML5
- JDK_1.8
+ GraalVM_JDK_17
diff --git a/Platform/Apple/tools/jace/nbactions.xml b/Platform/Apple/tools/jace/nbactions.xml
index e228a7ad..763c4850 100644
--- a/Platform/Apple/tools/jace/nbactions.xml
+++ b/Platform/Apple/tools/jace/nbactions.xml
@@ -6,15 +6,11 @@
jar
- -X
- -e
- process-classes
- org.codehaus.mojo:exec-maven-plugin:1.2.1:exec
+ clean
+ javafx:run
+
+
-
- -classpath %classpath jace.LawlessLegends
- java
-
profile
@@ -22,12 +18,13 @@
jar
+ clean
process-classes
- org.codehaus.mojo:exec-maven-plugin:1.2.1:exec
+ javafx:run@ide-debug
- -classpath %classpath jace.LawlessLegends
- java
+
+
true
@@ -37,12 +34,12 @@
jar
- process-classes
- org.codehaus.mojo:exec-maven-plugin:1.2.1:exec
+ clean
+ javafx:run@ide-debug
- -agentlib:jdwp=transport=dt_socket,server=n,address=${jpda.address} -classpath %classpath jace.LawlessLegends
- java
+
+
true
diff --git a/Platform/Apple/tools/jace/pom.xml b/Platform/Apple/tools/jace/pom.xml
index 469845fa..1cee8b3b 100644
--- a/Platform/Apple/tools/jace/pom.xml
+++ b/Platform/Apple/tools/jace/pom.xml
@@ -25,86 +25,168 @@
org.apache.maven.plugins
- maven-dependency-plugin
- 3.1.2
-
+ maven-compiler-plugin
+
+
+ 17
+
+ 3.11.0
+
+
+ com.gluonhq
+ gluonfx-maven-plugin
+ 1.0.18
+
+ jace.LawlessLegends
+
+
+
+ org.openjfx
+ javafx-maven-plugin
+ 0.0.8
+
+ lawlesslegends/jace.LawlessLegends
+
- unpack-dependencies
- package
-
- unpack-dependencies
-
+
+
+ default-cli
+
+
+
+
+ debug
- **/*.SF,**/*.DSA,**/*.RSA
- system
- junit,org.mockito,org.hamcrest
- ${project.build.directory}/classes
+
+
+
+
+
+
+
+ ide-debug
+
+
+
+
+
+
+
+
+ ide-profile
+
+
+
+
+
+
+
+
+
- org.codehaus.mojo
- exec-maven-plugin
- 3.0.0
+ org.moditect
+ moditect-maven-plugin
+ 1.0.0.Final
- unpack-dependencies
- package
+ add-module-infos
+ generate-resources
- exec
+ add-module-info
- ${java.home}/../bin/javapackager
-
- -createjar
- -nocss2bin
- -appclass
- ${mainClass}
- -srcdir
- ${project.build.directory}/classes
- -outdir
- ${project.build.directory}
- -outfile
- ${project.build.finalName}.jar
-
+
+
+
+ org.xerial.thirdparty
+ nestedvm
+ 1.0
+
+
+ module nestedvm {
+ exports org.ibex.nestedvm;
+ exports org.ibex.nestedvm.util;
+ }
+
+
+
+
+ org.reflections
+ reflections
+ 0.10.2
+
+
+ module reflections {
+ exports org.reflections;
+ }
+
+
+
+ true
-
-
-
- org.apache.maven.plugins
- maven-compiler-plugin
-
-
- 1.8
-
- 3.8.1
+
-
- org.reflections
- reflections
- 0.9.12
-
junit
junit
4.13.2
test
-
-
- org.eclipse.collections
- eclipse-collections
- 10.4.0
org.xerial.thirdparty
nestedvm
1.0
+
+ org.openjfx
+ javafx-base
+ 20
+ jar
+
+
+ org.openjfx
+ javafx-fxml
+ 20
+ jar
+
+
+ org.openjfx
+ javafx-web
+ 20
+ jar
+
+
+ org.openjfx
+ javafx-media
+ 20
+ jar
+
+
+ org.openjfx
+ javafx-graphics
+ 20
+ jar
+
+
+ org.openjfx
+ javafx-swing
+ 18
+ jar
+
+
+ org.reflections
+ reflections
+ 0.10.2
+ jar
+
diff --git a/Platform/Apple/tools/jace/src/main/java/jace/Emulator.java b/Platform/Apple/tools/jace/src/main/java/jace/Emulator.java
index 534822a4..a3100f85 100644
--- a/Platform/Apple/tools/jace/src/main/java/jace/Emulator.java
+++ b/Platform/Apple/tools/jace/src/main/java/jace/Emulator.java
@@ -18,11 +18,15 @@
*/
package jace;
-import jace.config.Configuration;
-import jace.lawless.LawlessComputer;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
+import java.util.function.Consumer;
+import java.util.function.Function;
+
+import jace.config.Configuration;
+import jace.core.RAM;
+import jace.lawless.LawlessComputer;
/**
* Created on January 15, 2007, 10:10 PM
@@ -47,6 +51,16 @@ public class Emulator {
return i;
}
+ public static void abort() {
+ if (instance != null) {
+ if (instance.computer != null) {
+ instance.computer.getMotherboard().suspend();
+ instance.computer.getMotherboard().detach();
+ }
+ }
+ instance = null;
+ }
+
public static Emulator getInstance() {
if (instance == null) {
instance = new Emulator();
@@ -54,10 +68,55 @@ public class Emulator {
return instance;
}
- public static LawlessComputer getComputer() {
+ private static LawlessComputer getComputer() {
return getInstance().computer;
}
+ public static void withComputer(Consumer c) {
+ LawlessComputer computer = getComputer();
+ if (computer != null) {
+ c.accept(computer);
+ } else {
+ System.err.println("No computer available!");
+ Thread.dumpStack();
+ }
+ }
+
+ public static T withComputer(Function f, T defaultValue) {
+ LawlessComputer computer = getComputer();
+ if (computer != null) {
+ return f.apply(computer);
+ } else {
+ System.err.println("No computer available!");
+ Thread.dumpStack();
+ return defaultValue;
+ }
+ }
+
+ public static void withMemory(Consumer m) {
+ withComputer(c->{
+ RAM memory = c.getMemory();
+ if (memory != null) {
+ m.accept(memory);
+ } else {
+ System.err.println("No memory available!");
+ Thread.dumpStack();
+ }
+ });
+ }
+
+ public static void withVideo(Consumer v) {
+ withComputer(c->{
+ jace.core.Video video = c.getVideo();
+ if (video != null) {
+ v.accept(video);
+ } else {
+ System.err.println("No video available!");
+ Thread.dumpStack();
+ }
+ });
+ }
+
/**
* Creates a new instance of Emulator
*/
@@ -65,6 +124,7 @@ public class Emulator {
instance = this;
computer = new LawlessComputer();
Configuration.buildTree();
+ computer.getMotherboard().suspend();
Configuration.loadSettings();
mainThread = Thread.currentThread();
// EmulatorUILogic.registerDebugger();
diff --git a/Platform/Apple/tools/jace/src/main/java/jace/EmulatorUILogic.java b/Platform/Apple/tools/jace/src/main/java/jace/EmulatorUILogic.java
index 15c5b3a3..18e7c278 100644
--- a/Platform/Apple/tools/jace/src/main/java/jace/EmulatorUILogic.java
+++ b/Platform/Apple/tools/jace/src/main/java/jace/EmulatorUILogic.java
@@ -18,20 +18,6 @@
*/
package jace;
-import jace.apple2e.MOS65C02;
-import jace.apple2e.RAM128k;
-import jace.apple2e.SoftSwitches;
-import jace.config.ConfigurableField;
-import jace.config.ConfigurationUIController;
-import jace.config.InvokableAction;
-import jace.config.Reconfigurable;
-import jace.core.CPU;
-import jace.core.Computer;
-import jace.core.Debugger;
-import jace.core.RAM;
-import jace.core.RAMListener;
-import static jace.core.Utility.*;
-import jace.ide.IdeController;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
@@ -43,15 +29,28 @@ import java.util.HashMap;
import java.util.HashSet;
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;
+
+import jace.apple2e.MOS65C02;
+import jace.apple2e.RAM128k;
+import jace.apple2e.SoftSwitches;
+import jace.config.ConfigurableField;
+import jace.config.ConfigurationUIController;
+import jace.config.InvokableAction;
+import jace.config.Reconfigurable;
+import jace.core.Debugger;
+import jace.core.RAM;
+import jace.core.RAMListener;
+import static jace.core.Utility.gripe;
+import jace.ide.IdeController;
import javafx.application.Platform;
import javafx.event.EventHandler;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.control.Label;
-import javafx.scene.image.Image;
import javafx.scene.input.KeyCombination;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.AnchorPane;
@@ -75,7 +74,7 @@ public class EmulatorUILogic implements Reconfigurable {
@Override
public void updateStatus() {
enableDebug(true);
- MOS65C02 cpu = (MOS65C02) Emulator.getComputer().getCpu();
+ MOS65C02 cpu = (MOS65C02) Emulator.withComputer(c->c.getCpu(), null);
updateCPURegisters(cpu);
}
};
@@ -113,7 +112,7 @@ public class EmulatorUILogic implements Reconfigurable {
}
public static void enableTrace(boolean b) {
- Emulator.getComputer().getCpu().setTraceEnabled(b);
+ Emulator.withComputer(c->c.getCpu().setTraceEnabled(b));
}
public static void stepForward() {
@@ -121,7 +120,7 @@ public class EmulatorUILogic implements Reconfigurable {
}
static void registerDebugger() {
- Emulator.getComputer().getCpu().setDebug(debugger);
+ Emulator.withComputer(c->c.getCpu().setDebug(debugger));
}
public static Integer getValidAddress(String s) {
@@ -210,14 +209,14 @@ public class EmulatorUILogic implements Reconfigurable {
alternatives = "Execute program;Load binary;Load program;Load rom;Play single-load game",
defaultKeyMapping = "ctrl+shift+b")
public static void runFile() {
- Emulator.getComputer().pause();
- FileChooser select = new FileChooser();
- File binary = select.showOpenDialog(LawlessLegends.getApplication().primaryStage);
- if (binary == null) {
- Emulator.getComputer().resume();
- return;
- }
- runFileNamed(binary);
+ Emulator.withComputer(c->
+ c.getMotherboard().whileSuspended(()->{
+ FileChooser select = new FileChooser();
+ File binary = select.showOpenDialog(LawlessLegends.getApplication().primaryStage);
+ if (binary != null) {
+ runFileNamed(binary);
+ }
+ }));
}
public static void runFileNamed(File binary) {
@@ -232,7 +231,6 @@ public class EmulatorUILogic implements Reconfigurable {
}
} catch (NumberFormatException | IOException ex) {
}
- Emulator.getComputer().getCpu().resume();
}
public static void brun(File binary, int address) throws IOException {
@@ -240,16 +238,19 @@ public class EmulatorUILogic implements Reconfigurable {
// 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
- Emulator.getComputer().pause();
- FileInputStream in = new FileInputStream(binary);
- byte[] data = new byte[in.available()];
- in.read(data);
- RAM ram = Emulator.getComputer().getMemory();
- for (int i = 0; i < data.length; i++) {
- ram.write(address + i, data[i], false, true);
+ byte[] data;
+ try (FileInputStream in = new FileInputStream(binary)) {
+ data = new byte[in.available()];
+ in.read(data);
}
- Emulator.getComputer().getCpu().setProgramCounter(address);
- Emulator.getComputer().resume();
+
+ Emulator.withComputer(c->c.getMotherboard().whileSuspended(()->{
+ RAM ram = c.getMemory();
+ for (int i = 0; i < data.length; i++) {
+ ram.write(address + i, data[i], false, true);
+ }
+ c.getCpu().setProgramCounter(address);
+ }));
}
@InvokableAction(
@@ -293,7 +294,7 @@ public class EmulatorUILogic implements Reconfigurable {
SimpleDateFormat df = new SimpleDateFormat("yyyy.MM.dd.HH.mm.ss");
String timestamp = df.format(new Date());
String type;
- int start = Emulator.getComputer().getVideo().getCurrentWriter().actualWriter().getYOffset(0);
+ int start = Emulator.withComputer(c->c.getVideo().getCurrentWriter().actualWriter().getYOffset(0), 0);
int len;
if (start < 0x02000) {
// Lo-res or double-lores
@@ -310,16 +311,23 @@ public class EmulatorUILogic implements Reconfigurable {
}
File outFile = new File("screen_" + type + "_a" + Integer.toHexString(start) + "_" + timestamp);
try (FileOutputStream out = new FileOutputStream(outFile)) {
- RAM128k ram = (RAM128k) Emulator.getComputer().memory;
- Emulator.getComputer().pause();
- if (dres) {
- for (int i = 0; i < len; i++) {
- out.write(ram.getAuxVideoMemory().readByte(start + i));
- }
- }
- for (int i = 0; i < len; i++) {
- out.write(ram.getMainMemory().readByte(start + i));
- }
+ Emulator.withComputer(c -> {
+ RAM128k ram = (RAM128k) c.getMemory();
+ c.getMotherboard().whileSuspended(() -> {
+ try {
+ if (dres) {
+ for (int i = 0; i < len; i++) {
+ out.write(ram.getAuxVideoMemory().readByte(start + i));
+ }
+ }
+ for (int i = 0; i < len; i++) {
+ out.write(ram.getMainMemory().readByte(start + i));
+ }
+ } catch (IOException e) {
+ Logger.getLogger(EmulatorUILogic.class.getName()).log(Level.SEVERE, "Error writing screenshot", e);
+ }
+ });
+ });
}
System.out.println("Wrote screenshot to " + outFile.getAbsolutePath());
}
@@ -332,8 +340,7 @@ public class EmulatorUILogic implements Reconfigurable {
defaultKeyMapping = "ctrl+shift+s")
public static void saveScreenshot() throws IOException {
FileChooser select = new FileChooser();
- Emulator.getComputer().pause();
- Image i = Emulator.getComputer().getVideo().getFrameBuffer();
+ // Image i = Emulator.getComputer().getVideo().getFrameBuffer();
// BufferedImage bufImageARGB = SwingFXUtils.fromFXImage(i, null);
File targetFile = select.showSaveDialog(LawlessLegends.getApplication().primaryStage);
if (targetFile == null) {
@@ -421,25 +428,31 @@ public class EmulatorUILogic implements Reconfigurable {
} else {
int width, height;
switch (size) {
- case 0: // 1x
+ case 0 -> {
+ // 1x
width = 560;
height = 384;
- break;
- case 1: // 1.5x
+ }
+ case 1 -> {
+ // 1.5x
width = 840;
height = 576;
- break;
- case 2: // 2x
+ }
+ case 2 -> {
+ // 2x
width = 560 * 2;
height = 384 * 2;
- break;
- case 3: // 3x (retina) 2880x1800
+ }
+ case 3 -> {
+ // 3x (retina) 2880x1800
width = 560 * 3;
height = 384 * 3;
- break;
- default: // 2x
+ }
+ default -> {
+ // 2x
width = 560 * 2;
height = 384 * 2;
+ }
}
double vgap = stage.getScene().getY();
double hgap = stage.getScene().getX();
@@ -527,16 +540,17 @@ public class EmulatorUILogic implements Reconfigurable {
}
public static void simulateCtrlAppleReset() {
- Computer computer = LawlessLegends.singleton.controller.computer;
- computer.keyboard.openApple(true);
- computer.warmStart();
- Platform.runLater(() -> {
- try {
- Thread.sleep(500);
- } catch (InterruptedException ex) {
- Logger.getLogger(EmulatorUILogic.class.getName()).log(Level.SEVERE, null, ex);
- }
- computer.keyboard.openApple(false);
+ Emulator.withComputer(c -> {
+ c.getKeyboard().openApple(true);
+ c.warmStart();
+ Platform.runLater(() -> {
+ try {
+ Thread.sleep(500);
+ } catch (InterruptedException ex) {
+ Logger.getLogger(EmulatorUILogic.class.getName()).log(Level.SEVERE, null, ex);
+ }
+ c.getKeyboard().openApple(false);
+ });
});
}
@@ -558,6 +572,8 @@ public class EmulatorUILogic implements Reconfigurable {
@Override
public void reconfigure() {
- LawlessLegends.getApplication().controller.setSpeed(speedSetting);
+ // Null-safe so there are no errors in unit tests
+ Optional.ofNullable(LawlessLegends.getApplication())
+ .ifPresent(app->app.controller.setSpeed(speedSetting));
}
}
diff --git a/Platform/Apple/tools/jace/src/main/java/jace/JaceUIController.java b/Platform/Apple/tools/jace/src/main/java/jace/JaceUIController.java
index 455c79ff..9359c049 100644
--- a/Platform/Apple/tools/jace/src/main/java/jace/JaceUIController.java
+++ b/Platform/Apple/tools/jace/src/main/java/jace/JaceUIController.java
@@ -1,15 +1,26 @@
-/*
- * To change this license header, choose License Headers in Project Properties.
- * To change this template file, choose Tools | Templates
- * and open the template in the editor.
- */
package jace;
-import com.sun.glass.ui.Application;
+import java.io.File;
+import java.io.IOException;
+import java.net.URI;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.TimeUnit;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
import jace.core.Card;
-import jace.core.Computer;
import jace.core.Motherboard;
import jace.core.Utility;
+import jace.core.Video;
import jace.lawless.LawlessComputer;
import jace.lawless.LawlessHacks;
import jace.library.MediaCache;
@@ -39,21 +50,18 @@ import javafx.scene.input.DragEvent;
import javafx.scene.input.KeyEvent;
import javafx.scene.input.MouseEvent;
import javafx.scene.input.TransferMode;
-import javafx.scene.layout.*;
+import javafx.scene.layout.AnchorPane;
+import javafx.scene.layout.Background;
+import javafx.scene.layout.BackgroundFill;
+import javafx.scene.layout.BorderPane;
+import javafx.scene.layout.CornerRadii;
+import javafx.scene.layout.HBox;
+import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import javafx.util.Duration;
import javafx.util.StringConverter;
-import java.io.File;
-import java.io.IOException;
-import java.net.URI;
-import java.net.URL;
-import java.util.*;
-import java.util.concurrent.*;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
/**
*
* @author blurry
@@ -90,8 +98,6 @@ public class JaceUIController {
@FXML
private ComboBox musicSelection;
- Computer computer;
-
private final BooleanProperty aspectRatioCorrectionEnabled = new SimpleBooleanProperty(false);
@FXML
@@ -117,12 +123,14 @@ public class JaceUIController {
rootPane.setBackground(new Background(new BackgroundFill(Color.BLACK, null, null)));
rootPane.setOnMouseMoved(this::showMenuButton);
rootPane.setOnMouseExited(this::hideControlOverlay);
+ rootPane.setOnMouseClicked((evt)->rootPane.requestFocus());
menuButton.setOnMouseClicked(this::showControlOverlay);
controlOverlay.setOnMouseClicked(this::hideControlOverlay);
delayTimer.getKeyFrames().add(new KeyFrame(Duration.millis(3000), evt -> {
hideControlOverlay(null);
rootPane.requestFocus();
}));
+ rootPane.requestFocus();
}
private void showMenuButton(MouseEvent evt) {
@@ -198,15 +206,24 @@ public class JaceUIController {
}
}
- private void connectControls(Stage primaryStage) {
+ Stage primaryStage;
+
+ public void reconnectKeyboard() {
+ Emulator.withComputer(computer -> {
+ if (computer.getKeyboard() != null) {
+ EventHandler keyboardHandler = computer.getKeyboard().getListener();
+ primaryStage.setOnShowing(evt -> computer.getKeyboard().resetState());
+ rootPane.setOnKeyPressed(keyboardHandler);
+ rootPane.setOnKeyReleased(keyboardHandler);
+ rootPane.setFocusTraversable(true);
+ }
+ });
+ }
+
+ private void connectControls(Stage ps) {
+ primaryStage = ps;
+
connectButtons(controlOverlay);
- if (computer.getKeyboard() != null) {
- EventHandler keyboardHandler = computer.getKeyboard().getListener();
- primaryStage.setOnShowing(evt -> computer.getKeyboard().resetState());
- rootPane.setOnKeyPressed(keyboardHandler);
- rootPane.setOnKeyReleased(keyboardHandler);
- rootPane.setFocusTraversable(true);
- }
speedSlider.setMinorTickCount(0);
speedSlider.setMajorTickUnit(1);
speedSlider.setLabelFormatter(new StringConverter() {
@@ -237,29 +254,33 @@ public class JaceUIController {
setSpeed(Emulator.logic.speedSetting);
});
musicSelection.getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) ->
+ Emulator.withComputer(computer ->
((LawlessHacks) ((LawlessComputer) computer).activeCheatEngine).changeMusicScore(String.valueOf(newValue))
+ )
);
+ reconnectKeyboard();
}
private void connectButtons(Node n) {
- if (n instanceof Button) {
- Button button = (Button) n;
+ if (n instanceof Button button) {
Runnable action = Utility.getNamedInvokableAction(button.getText());
button.setOnMouseClicked(evt -> action.run());
- } else if (n instanceof Parent) {
- ((Parent) n).getChildrenUnmodifiable().forEach(child -> connectButtons(child));
+ } else if (n instanceof Parent parent) {
+ parent.getChildrenUnmodifiable().forEach(child -> connectButtons(child));
}
}
- protected void setSpeed(double speed) {
+ public void setSpeed(double speed) {
Emulator.logic.speedSetting = (int) speed;
double speedRatio = convertSpeedToRatio(speed);
if (speedSlider.getValue() != speed) {
Platform.runLater(()->speedSlider.setValue(speed));
}
if (speedRatio >= 100.0) {
- Emulator.getComputer().getMotherboard().setMaxSpeed(true);
- Emulator.getComputer().getMotherboard().setSpeedInPercentage(20000);
+ Emulator.withComputer(c -> {
+ c.getMotherboard().setSpeedInPercentage(20000);
+ c.getMotherboard().setMaxSpeed(true);
+ });
// Motherboard.cpuPerClock = 10;
} else {
if (speedRatio > 1000) {
@@ -267,10 +288,12 @@ public class JaceUIController {
} else {
Motherboard.cpuPerClock = 1;
}
- Emulator.getComputer().getMotherboard().setMaxSpeed(false);
- Emulator.getComputer().getMotherboard().setSpeedInPercentage((int) (speedRatio * 100));
+ Emulator.withComputer(c -> {
+ c.getMotherboard().setMaxSpeed(false);
+ c.getMotherboard().setSpeedInPercentage((int) (speedRatio * 100));
+ });
}
- Emulator.getComputer().getMotherboard().reconfigure();
+ Emulator.withComputer(c -> c.getMotherboard().reconfigure());
}
public void toggleAspectRatio() {
@@ -281,19 +304,23 @@ public class JaceUIController {
aspectRatioCorrectionEnabled.set(enabled);
}
- public void connectComputer(Computer computer, Stage primaryStage) {
- if (computer == null) {
- return;
- }
- this.computer = computer;
+ public void connectComputer(Stage primaryStage) {
Platform.runLater(() -> {
connectControls(primaryStage);
- appleScreen.setImage(computer.getVideo().getFrameBuffer());
+ Emulator.withVideo(this::connectVideo);
appleScreen.setVisible(true);
rootPane.requestFocus();
});
}
+ public void connectVideo(Video video) {
+ if (video != null) {
+ appleScreen.setImage(video.getFrameBuffer());
+ } else {
+ appleScreen.setImage(null);
+ }
+ }
+
private void processDragEnteredEvent(DragEvent evt) {
MediaEntry media = null;
if (evt.getDragboard().hasFiles()) {
@@ -355,15 +382,17 @@ public class JaceUIController {
});
icon.setOnDragDropped(event -> {
System.out.println("Dropping media on " + icon.getText());
- try {
- computer.pause();
- consumer.insertMedia(media, media.files.get(0));
- computer.resume();
+ Emulator.withComputer(c -> {
+ c.getMotherboard().whileSuspended(() -> {
+ try {
+ consumer.insertMedia(media, media.files.get(0));
+ } catch (IOException ex) {
+ Logger.getLogger(JaceUIController.class.getName()).log(Level.SEVERE, null, ex);
+ }
+ });
+ });
event.setDropCompleted(true);
event.consume();
- } catch (IOException ex) {
- Logger.getLogger(JaceUIController.class.getName()).log(Level.SEVERE, null, ex);
- }
endDragEvent();
});
});
@@ -379,13 +408,15 @@ public class JaceUIController {
private List getMediaConsumers() {
List consumers = new ArrayList<>();
- consumers.add(Emulator.getComputer().getUpgradeHandler());
+ Emulator.withComputer(c -> consumers.add(((LawlessComputer) c).getUpgradeHandler()));
if (Emulator.logic.showDrives) {
- for (Optional card : computer.memory.getAllCards()) {
- card.filter(c -> c instanceof MediaConsumerParent).ifPresent(parent ->
+ Emulator.withMemory(m -> {
+ for (Optional card : m.getAllCards()) {
+ card.filter(c -> c instanceof MediaConsumerParent).ifPresent(parent ->
consumers.addAll(Arrays.asList(((MediaConsumerParent) parent).getConsumers()))
- );
- }
+ );
+ }
+ });
}
return consumers;
}
@@ -398,7 +429,7 @@ public class JaceUIController {
public void addIndicator(Label icon, long TTL) {
if (!iconTTL.containsKey(icon)) {
- Application.invokeLater(() -> {
+ Platform.runLater(() -> {
if (!notificationBox.getChildren().contains(icon)) {
notificationBox.getChildren().add(icon);
}
@@ -408,7 +439,7 @@ public class JaceUIController {
}
public void removeIndicator(Label icon) {
- Application.invokeLater(() -> {
+ Platform.runLater(() -> {
notificationBox.getChildren().remove(icon);
iconTTL.remove(icon);
});
@@ -453,13 +484,13 @@ public class JaceUIController {
notification.setEffect(new DropShadow(2.0, Color.BLACK));
notification.setTextFill(Color.WHITE);
notification.setBackground(new Background(new BackgroundFill(Color.rgb(0, 0, 80, 0.7), new CornerRadii(5.0), new Insets(-5.0))));
- Application.invokeLater(() -> {
+ Platform.runLater(() -> {
stackPane.getChildren().remove(oldNotification);
stackPane.getChildren().add(notification);
});
notificationExecutor.schedule(
- () -> Application.invokeLater(() -> stackPane.getChildren().remove(notification)),
+ () -> Platform.runLater(() -> stackPane.getChildren().remove(notification)),
4, TimeUnit.SECONDS);
}
}
diff --git a/Platform/Apple/tools/jace/src/main/java/jace/LawlessLegends.java b/Platform/Apple/tools/jace/src/main/java/jace/LawlessLegends.java
index f02ed123..00ae4542 100644
--- a/Platform/Apple/tools/jace/src/main/java/jace/LawlessLegends.java
+++ b/Platform/Apple/tools/jace/src/main/java/jace/LawlessLegends.java
@@ -1,8 +1,16 @@
package jace;
+import java.awt.Taskbar;
+import java.io.IOException;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import jace.apple2e.Apple2e;
import jace.apple2e.SoftSwitches;
import jace.apple2e.VideoNTSC;
import jace.config.Configuration;
+import jace.core.Computer;
import jace.core.RAMEvent;
import jace.core.RAMListener;
import jace.core.Utility;
@@ -10,12 +18,14 @@ import jace.hardware.CardDiskII;
import jace.hardware.CardRamFactor;
import jace.hardware.CardRamworks;
import jace.hardware.massStorage.CardMassStorage;
+import jace.lawless.LawlessComputer;
import jace.lawless.LawlessHacks;
import jace.lawless.LawlessImageTool;
import jace.lawless.LawlessVideo;
import jace.ui.MetacheatUI;
import javafx.application.Application;
import javafx.application.Platform;
+import javafx.embed.swing.SwingFXUtils;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.layout.AnchorPane;
@@ -24,10 +34,6 @@ import javafx.scene.paint.Color;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
-import java.io.IOException;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
/**
*
* @author blurry
@@ -54,8 +60,18 @@ public class LawlessLegends extends Application {
Scene s = new Scene(node);
s.setFill(Color.BLACK);
primaryStage.setScene(s);
- primaryStage.setTitle("Lawless Legends");
- Utility.loadIcon("game_icon.png").ifPresent(primaryStage.getIcons()::add);
+ primaryStage.titleProperty().set("Lawless Legends");
+ Utility.loadIcon("game_icon.png").ifPresent(icon -> {
+ primaryStage.getIcons().add(icon);
+ try {
+ //set icon for mac os (and other systems which do support this method)
+ Taskbar.getTaskbar().setIconImage(SwingFXUtils.fromFXImage(icon, null));
+ } catch (final UnsupportedOperationException e) {
+ System.out.println("The os does not support: 'taskbar.setIconImage'");
+ } catch (final SecurityException e) {
+ System.out.println("There was a security exception for: 'taskbar.setIconImage'");
+ }
+ });
} catch (IOException exception) {
throw new RuntimeException(exception);
}
@@ -63,23 +79,30 @@ public class LawlessLegends extends Application {
primaryStage.show();
Platform.runLater(() -> new Thread(() -> {
Emulator.getInstance(getParameters().getRaw());
+ Emulator.withComputer(c->((LawlessComputer)c).initLawlessLegendsConfiguration());
configureEmulatorForGame();
reconnectUIHooks();
EmulatorUILogic.scaleIntegerRatio();
- while (Emulator.getComputer().getVideo() == null || Emulator.getComputer().getVideo().getFrameBuffer() == null) {
- Thread.yield();
+ AtomicBoolean waitingForVideo = new AtomicBoolean(true);
+ while (waitingForVideo.get()) {
+ Emulator.withVideo(v -> {
+ if (v.getFrameBuffer() != null) {
+ waitingForVideo.set(false);
+ }
+ });
+ Thread.onSpinWait();
}
bootWatchdog();
}).start());
primaryStage.setOnCloseRequest(event -> {
- Emulator.getComputer().deactivate();
+ Emulator.withComputer(Computer::deactivate);
Platform.exit();
System.exit(0);
});
}
public void reconnectUIHooks() {
- controller.connectComputer(Emulator.getComputer(), primaryStage);
+ controller.connectComputer(primaryStage);
}
public static LawlessLegends getApplication() {
@@ -123,51 +146,76 @@ public class LawlessLegends extends Application {
*/
private void bootWatchdog() {
romStarted = false;
- if (Emulator.getComputer().PRODUCTION_MODE) {
- RAMListener startListener = Emulator.getComputer().getMemory().
- observe(RAMEvent.TYPE.EXECUTE, 0x0c700, (e) -> romStarted = true);
- Emulator.getComputer().invokeColdStart();
- try {
- Thread.sleep(7500);
- if (!romStarted) {
- Logger.getLogger(getClass().getName()).log(Level.WARNING, "Boot not detected, performing a cold start");
- Emulator.getComputer().invokeColdStart();
- }
- } catch (InterruptedException ex) {
- Logger.getLogger(LawlessLegends.class.getName()).log(Level.SEVERE, null, ex);
+ Emulator.withComputer(c -> {
+ if (c.PRODUCTION_MODE) {
+ new Thread(()->{
+ Logger.getLogger(getClass().getName()).log(Level.WARNING, "Booting with watchdog");
+ RAMListener startListener = c.getMemory().
+ observe(RAMEvent.TYPE.EXECUTE, 0x2000, (e) -> {
+ Logger.getLogger(getClass().getName()).log(Level.WARNING, "Boot was detected, watchdog terminated.");
+ romStarted = true;
+ });
+ c.invokeColdStart();
+ try {
+ Thread.sleep(6500);
+ if (!romStarted) {
+ Logger.getLogger(getClass().getName()).log(Level.WARNING, "Boot not detected, performing a cold start");
+ resetEmulator();
+ configureEmulatorForGame();
+ bootWatchdog();
+ // Emulator.getComputer().getCpu().trace=true;
+ } else {
+ c.getMemory().removeListener(startListener);
+ }
+ } catch (InterruptedException ex) {
+ Logger.getLogger(LawlessLegends.class.getName()).log(Level.SEVERE, null, ex);
+ }
+ }).start();
+ } else {
+ romStarted = true;
+ c.invokeColdStart();
}
- Emulator.getComputer().getMemory().removeListener(startListener);
- } else {
- romStarted = true;
- Emulator.getComputer().invokeColdStart();
- }
+ });
+ }
+
+ public void resetEmulator() {
+ // Reset the emulator memory and reconfigure
+ Emulator.withComputer(c -> {
+ c.pause();
+ c.getMemory().resetState();
+ c.reconfigure();
+ c.resume();
+ });
}
private void configureEmulatorForGame() {
- Emulator.getComputer().enableHints = false;
- Emulator.getComputer().clockEnabled = true;
- Emulator.getComputer().joy1enabled = false;
- Emulator.getComputer().joy2enabled = false;
- Emulator.getComputer().enableStateManager = false;
- Emulator.getComputer().ramCard.setValue(CardRamworks.class);
- Emulator.getComputer().videoRenderer.setValue(LawlessVideo.class);
- if (Emulator.getComputer().PRODUCTION_MODE) {
- Emulator.getComputer().card7.setValue(CardMassStorage.class);
- Emulator.getComputer().card6.setValue(CardDiskII.class);
- Emulator.getComputer().card5.setValue(CardRamFactor.class);
- Emulator.getComputer().card4.setValue(null);
- Emulator.getComputer().card2.setValue(null);
- }
- Emulator.getComputer().cheatEngine.setValue(LawlessHacks.class);
- Configuration.buildTree();
- Emulator.getComputer().reconfigure();
- VideoNTSC.setVideoMode(VideoNTSC.VideoMode.TextFriendly, false);
- if (Emulator.getComputer().PRODUCTION_MODE) {
- ((LawlessImageTool) Emulator.getComputer().getUpgradeHandler()).loadGame();
- } else {
- for (SoftSwitches s : SoftSwitches.values()) {
- s.getSwitch().reset();
+ Emulator.withComputer(c -> {
+ c.enableHints = false;
+ c.clockEnabled = true;
+ c.joy1enabled = false;
+ c.joy2enabled = false;
+ c.enableStateManager = false;
+ c.ramCard.setValue(CardRamworks.class);
+ c.videoRenderer.setValue(LawlessVideo.class);
+ if (c.PRODUCTION_MODE) {
+ c.card7.setValue(CardMassStorage.class);
+ c.card6.setValue(CardDiskII.class);
+ c.card5.setValue(CardRamFactor.class);
+ c.card4.setValue(null);
+ c.card2.setValue(null);
+ c.getMemory().writeWord(0x03f0, 0x0c700, false, false);
}
- }
+ c.cheatEngine.setValue(LawlessHacks.class);
+ Configuration.buildTree();
+ c.reconfigure();
+ VideoNTSC.setVideoMode(VideoNTSC.VideoMode.TextFriendly, false);
+ if (c.PRODUCTION_MODE) {
+ ((LawlessImageTool) c.getUpgradeHandler()).loadGame();
+ } else {
+ for (SoftSwitches s : SoftSwitches.values()) {
+ s.getSwitch().reset();
+ }
+ }
+ });
}
}
diff --git a/Platform/Apple/tools/jace/src/main/java/jace/apple2e/Apple2e.java b/Platform/Apple/tools/jace/src/main/java/jace/apple2e/Apple2e.java
index 368f0fc2..4d237945 100644
--- a/Platform/Apple/tools/jace/src/main/java/jace/apple2e/Apple2e.java
+++ b/Platform/Apple/tools/jace/src/main/java/jace/apple2e/Apple2e.java
@@ -18,21 +18,13 @@
*/
package jace.apple2e;
-import jace.LawlessLegends;
-import jace.apple2e.softswitch.VideoSoftSwitch;
-import jace.cheat.Cheats;
-import jace.config.ClassSelection;
-import jace.config.ConfigurableField;
-import jace.core.*;
-import jace.hardware.*;
-import jace.hardware.massStorage.CardMassStorage;
-import jace.lawless.FPSMonitorDevice;
-import jace.lawless.LawlessVideo;
-import jace.state.Stateful;
-
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Optional;
+import java.util.Set;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ScheduledThreadPoolExecutor;
@@ -40,6 +32,32 @@ import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;
+import jace.LawlessLegends;
+import jace.apple2e.softswitch.VideoSoftSwitch;
+import jace.cheat.Cheats;
+import jace.config.ClassSelection;
+import jace.config.ConfigurableField;
+import jace.core.Card;
+import jace.core.Computer;
+import jace.core.Device;
+import jace.core.Motherboard;
+import jace.core.RAM;
+import jace.core.RAMEvent;
+import jace.core.RAMListener;
+import jace.core.Utility;
+import jace.core.Video;
+import jace.hardware.CardDiskII;
+import jace.hardware.CardExt80Col;
+import jace.hardware.CardRamworks;
+import jace.hardware.ConsoleProbe;
+import jace.hardware.Joystick;
+import jace.hardware.NoSlotClock;
+import jace.hardware.ZipWarpAccelerator;
+import jace.hardware.massStorage.CardMassStorage;
+import jace.lawless.FPSMonitorDevice;
+import jace.lawless.LawlessVideo;
+import jace.state.Stateful;
+
/**
* Apple2e is a computer with a 65c02 CPU, 128k of bankswitched ram,
* double-hires graphics, and up to seven peripheral I/O cards installed. Pause
@@ -173,7 +191,7 @@ public class Apple2e extends Computer {
if (getMemory().getCard(slot).isPresent()) {
if (getMemory().getCard(slot).get().getClass().equals(type)) {
return;
- }
+ }
getMemory().removeCard(slot);
}
if (type != null) {
@@ -214,13 +232,12 @@ public class Apple2e extends Computer {
return;
}
motherboard.whileSuspended(()-> {
- if (getMemory() != null) {
- for (SoftSwitches s : SoftSwitches.values()) {
- s.getSwitch().unregister();
- }
- }
if (!isMemoryConfigurationCorrect()) {
try {
+ if (getVideo() != null) {
+ getVideo().suspend();
+ }
+ setVideo(null);
System.out.println("Creating new ram using " + getDesiredMemoryConfiguration().getName());
RAM128k newMemory = getDesiredMemoryConfiguration().getConstructor(Computer.class).newInstance(this);
@@ -232,15 +249,12 @@ public class Apple2e extends Computer {
Logger.getLogger(Apple2e.class.getName()).log(Level.SEVERE, null, ex);
}
}
- for (SoftSwitches s : SoftSwitches.values()) {
- s.getSwitch().register(this);
- }
try {
if (useDebugRom) {
- loadRom("jace/data/apple2e_debug.rom");
+ loadRom("/jace/data/apple2e_debug.rom");
} else {
- loadRom("jace/data/apple2e.rom");
+ loadRom("/jace/data/apple2e.rom");
}
} catch (IOException ex) {
Logger.getLogger(Apple2e.class.getName()).log(Level.SEVERE, null, ex);
@@ -331,15 +345,18 @@ public class Apple2e extends Computer {
if (cheatEngine.getValue() == null) {
if (activeCheatEngine != null) {
activeCheatEngine.detach();
- newDeviceSet.add(activeCheatEngine);
+ activeCheatEngine.suspend();
+ activeCheatEngine = null;
}
- activeCheatEngine = null;
} else {
boolean startCheats = true;
if (activeCheatEngine != null) {
if (activeCheatEngine.getClass().equals(cheatEngine.getValue())) {
startCheats = false;
+ newDeviceSet.add(activeCheatEngine);
} else {
+ activeCheatEngine.detach();
+ activeCheatEngine.suspend();
activeCheatEngine = null;
}
}
@@ -354,7 +371,7 @@ public class Apple2e extends Computer {
}
newDeviceSet.add(cpu);
- newDeviceSet.add(video);
+ newDeviceSet.add(getVideo());
for (Optional c : getMemory().getAllCards()) {
c.ifPresent(newDeviceSet::add);
}
@@ -481,6 +498,7 @@ public class Apple2e extends Computer {
private void disableHints() {
hints.forEach((hint) -> getMemory().removeListener(hint));
+ hints.clear();
}
@Override
diff --git a/Platform/Apple/tools/jace/src/main/java/jace/apple2e/MOS65C02.java b/Platform/Apple/tools/jace/src/main/java/jace/apple2e/MOS65C02.java
index 8a1acf10..a088baa4 100644
--- a/Platform/Apple/tools/jace/src/main/java/jace/apple2e/MOS65C02.java
+++ b/Platform/Apple/tools/jace/src/main/java/jace/apple2e/MOS65C02.java
@@ -1075,33 +1075,31 @@ public class MOS65C02 extends CPU {
int bytes;
int n = op & 0x0f;
switch (n) {
- case 2:
+ case 2 -> {
bytes = 2;
wait = 2;
- break;
- case 3:
- case 7:
- case 0x0b:
- case 0x0f:
+ }
+ case 3, 7, 0x0b, 0x0f -> {
wait = 1;
bytes = 1;
- break;
- case 4:
+ }
+ case 4 -> {
bytes = 2;
if ((op & 0x0f0) == 0x040) {
wait = 3;
} else {
wait = 4;
- } break;
- case 0x0c:
+ }
+ }
+ case 0x0c -> {
bytes = 3;
if ((op & 0x0f0) == 0x050) {
wait = 8;
} else {
wait = 4;
- } break;
- default:
- bytes = 2;
+ }
+ }
+ default -> bytes = 2;
}
incrementProgramCounter(bytes);
addWaitCycles(wait);
@@ -1230,10 +1228,8 @@ public class MOS65C02 extends CPU {
// N = true;
// V = true;
// Z = true;
- int newPC = getMemory().readWord(RESET_VECTOR, TYPE.READ_DATA, true, false);
- if (Emulator.getComputer().PRODUCTION_MODE) {
- newPC = 0x0C700;
- }
+ int resetVector = getMemory().readWord(RESET_VECTOR, TYPE.READ_DATA, true, false);
+ int newPC = Emulator.withComputer(c->c.PRODUCTION_MODE ? 0x0C700 : resetVector, resetVector);
LOG.log(Level.WARNING, "Reset called, setting PC to ({0}) = {1}", new Object[]{Integer.toString(RESET_VECTOR, 16), Integer.toString(newPC, 16)});
setProgramCounter(newPC);
}
@@ -1347,16 +1343,13 @@ public class MOS65C02 extends CPU {
case 0x65:
// CPU functions
switch (param2 & 0x0ff) {
- case 0x00:
- // Turn off tracing
+ case 0x00 -> // Turn off tracing
trace = false;
- break;
- case 0x01:
- // Turn on tracing
+ case 0x01 -> // Turn on tracing
trace = true;
- break;
}
break;
+
case 0x64:
// Memory functions
getMemory().performExtendedCommand(param2 & 0x0ff);
diff --git a/Platform/Apple/tools/jace/src/main/java/jace/apple2e/RAM128k.java b/Platform/Apple/tools/jace/src/main/java/jace/apple2e/RAM128k.java
index e04fee54..18817d79 100644
--- a/Platform/Apple/tools/jace/src/main/java/jace/apple2e/RAM128k.java
+++ b/Platform/Apple/tools/jace/src/main/java/jace/apple2e/RAM128k.java
@@ -25,7 +25,6 @@ import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
-import java.util.concurrent.Semaphore;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Collectors;
@@ -157,8 +156,6 @@ abstract public class RAM128k extends RAM {
}
}
- private final Semaphore configurationSemaphore = new Semaphore(1, true);
-
public String getReadConfiguration() {
String rstate = "";
if (SoftSwitches.RAMRD.getState()) {
@@ -374,8 +371,7 @@ abstract public class RAM128k extends RAM {
*
*/
@Override
- public void configureActiveMemory() {
-
+ public synchronized void configureActiveMemory() {
String auxZpConfiguration = getAuxZPConfiguration();
String readConfiguration = getReadConfiguration() + auxZpConfiguration;
String writeConfiguration = getWriteConfiguration() + auxZpConfiguration;
@@ -385,27 +381,20 @@ abstract public class RAM128k extends RAM {
}
state = newState;
- try {
- log("MMU Switches");
- configurationSemaphore.acquire();
+ log("MMU Switches");
- if (memoryConfigurations.containsKey(readConfiguration)) {
- activeRead = memoryConfigurations.get(readConfiguration);
- } else {
- activeRead = buildReadConfiguration();
- memoryConfigurations.put(readConfiguration, activeRead);
- }
+ if (memoryConfigurations.containsKey(readConfiguration)) {
+ activeRead = memoryConfigurations.get(readConfiguration);
+ } else {
+ activeRead = buildReadConfiguration();
+ memoryConfigurations.put(readConfiguration, activeRead);
+ }
- if (memoryConfigurations.containsKey(writeConfiguration)) {
- activeWrite = memoryConfigurations.get(writeConfiguration);
- } else {
- activeWrite = buildWriteConfiguration();
- memoryConfigurations.put(writeConfiguration, activeWrite);
- }
-
- configurationSemaphore.release();
- } catch (InterruptedException ex) {
- Logger.getLogger(RAM128k.class.getName()).log(Level.SEVERE, null, ex);
+ if (memoryConfigurations.containsKey(writeConfiguration)) {
+ activeWrite = memoryConfigurations.get(writeConfiguration);
+ } else {
+ activeWrite = buildWriteConfiguration();
+ memoryConfigurations.put(writeConfiguration, activeWrite);
}
}
@@ -443,11 +432,13 @@ abstract public class RAM128k extends RAM {
activeWrite.setBanks(0, cPageRom.getMemory().length, 0x011, cPageRom);
activeWrite.setBanks(0, rom.getMemory().length, 0x020, rom);
//----------------------
- InputStream inputRom = getClass().getClassLoader().getResourceAsStream(path);
+ InputStream inputRom = getClass().getResourceAsStream(path);
if (inputRom == null) {
- LOG.log(Level.SEVERE, "Rom not found: " + path);
+ LOG.log(Level.SEVERE, "Rom not found: {0}", path);
return;
}
+ // Clear cached configurations as we might have outdated references now
+ memoryConfigurations.clear();
int read = 0;
int addr = 0;
byte[] in = new byte[1024];
@@ -458,11 +449,9 @@ abstract public class RAM128k extends RAM {
}
// System.out.println("Finished reading rom with " + inputRom.available() + " bytes left unread!");
//dump();
- // Clear cached configurations as we might have outdated references now
for (int i = 0; i < 17; i++) {
activeWrite.set(i, restore[i]);
}
- memoryConfigurations.clear();
configureActiveMemory();
}
@@ -523,4 +512,9 @@ abstract public class RAM128k extends RAM {
// Clear cached configurations as we might have outdated references now
memoryConfigurations.clear();
}
+
+ @Override
+ public void resetState() {
+ memoryConfigurations.clear();
+ }
}
diff --git a/Platform/Apple/tools/jace/src/main/java/jace/apple2e/SoftSwitches.java b/Platform/Apple/tools/jace/src/main/java/jace/apple2e/SoftSwitches.java
index 1b63f99f..97baa17d 100644
--- a/Platform/Apple/tools/jace/src/main/java/jace/apple2e/SoftSwitches.java
+++ b/Platform/Apple/tools/jace/src/main/java/jace/apple2e/SoftSwitches.java
@@ -18,6 +18,7 @@
*/
package jace.apple2e;
+import jace.Emulator;
import jace.apple2e.softswitch.IntC8SoftSwitch;
import jace.apple2e.softswitch.KeyboardSoftSwitch;
import jace.apple2e.softswitch.Memory2SoftSwitch;
@@ -83,9 +84,9 @@ public enum SoftSwitches {
// PAGE2 is a hybrid switch; 80STORE ? memory : video
if (_80STORE.isOn()) {
- computer.getMemory().configureActiveMemory();
+ Emulator.withMemory(m->m.configureActiveMemory());
} else {
- computer.getVideo().configureVideoMode();
+ Emulator.withVideo(v->v.configureVideoMode());
}
}
}),
@@ -102,7 +103,7 @@ public enum SoftSwitches {
@Override
protected byte readSwitch() {
setState(true);
- return computer.getVideo().getFloatingBus();
+ return Emulator.withComputer(c->c.getVideo().getFloatingBus(), (byte) 0);
}
@Override
@@ -129,7 +130,7 @@ public enum SoftSwitches {
KEYBOARD_STROBE_READ(new SoftSwitch("KeyStrobe_Read", 0x0c010, -1, -1, RAMEvent.TYPE.READ, false) {
@Override
protected byte readSwitch() {
- return computer.getVideo().getFloatingBus();
+ return Emulator.withComputer(c->c.getVideo().getFloatingBus(), (byte) 0);
}
@Override
@@ -142,10 +143,7 @@ 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.getVideo() == null) {
- return 0;
- }
- return computer.getVideo().getFloatingBus();
+ return Emulator.withComputer(c->c.getVideo().getFloatingBus(), (byte) 0);
}
@Override
diff --git a/Platform/Apple/tools/jace/src/main/java/jace/apple2e/Speaker.java b/Platform/Apple/tools/jace/src/main/java/jace/apple2e/Speaker.java
index a82ad212..23b96631 100644
--- a/Platform/Apple/tools/jace/src/main/java/jace/apple2e/Speaker.java
+++ b/Platform/Apple/tools/jace/src/main/java/jace/apple2e/Speaker.java
@@ -18,19 +18,29 @@
*/
package jace.apple2e;
-import jace.LawlessLegends;
-import jace.config.ConfigurableField;
-import jace.core.*;
-import javafx.stage.FileChooser;
-
-import javax.sound.sampled.LineUnavailableException;
-import javax.sound.sampled.SourceDataLine;
-import java.io.*;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
import java.util.Timer;
-import java.util.TimerTask;
import java.util.logging.Level;
import java.util.logging.Logger;
+import javax.sound.sampled.SourceDataLine;
+
+import jace.Emulator;
+import jace.LawlessLegends;
+import jace.config.ConfigurableField;
+import jace.config.InvokableAction;
+import jace.core.Computer;
+import jace.core.Motherboard;
+import jace.core.RAMEvent;
+import jace.core.RAMListener;
+import jace.core.SoundGeneratorDevice;
+import jace.core.SoundMixer;
+import javafx.stage.FileChooser;
+
/**
* Apple // Speaker Emulation Created on May 9, 2007, 9:55 PM
*
@@ -40,7 +50,11 @@ public class Speaker extends SoundGeneratorDevice {
static boolean fileOutputActive = false;
static OutputStream out;
+
+ @ConfigurableField(category = "sound", name = "1mhz timing", description = "Force speaker output to 1mhz?")
+ public static boolean force1mhz = true;
+ @InvokableAction(category = "sound", name = "Record sound", description="Toggles recording (saving) sound output to a file", defaultKeyMapping = "ctrl+shift+w")
public static void toggleFileOutput() {
if (fileOutputActive) {
try {
@@ -56,12 +70,6 @@ public class Speaker extends SoundGeneratorDevice {
if (f == null) {
return;
}
-// if (f.exists()) {
-// int i = JOptionPane.showConfirmDialog(null, "Overwrite existing file?");
-// if (i != JOptionPane.OK_OPTION && i != JOptionPane.YES_OPTION) {
-// return;
-// }
-// }
try {
out = new FileOutputStream(f);
fileOutputActive = true;
@@ -70,6 +78,7 @@ public class Speaker extends SoundGeneratorDevice {
}
}
}
+
/**
* Counter tracks the number of cycles between sampling
*/
@@ -87,9 +96,6 @@ public class Speaker extends SoundGeneratorDevice {
* Number of samples in buffer
*/
static int BUFFER_SIZE = (int) (SoundMixer.RATE * 0.4);
- // Number of samples available in output stream before playback happens (avoid extra blocking)
-// static int MIN_PLAYBACK_BUFFER = BUFFER_SIZE / 2;
- static int MIN_PLAYBACK_BUFFER = 64;
/**
* Playback volume (should be < 1423)
*/
@@ -122,8 +128,8 @@ public class Speaker extends SoundGeneratorDevice {
private byte[] secondaryBuffer;
private int bufferPos = 0;
private Timer playbackTimer;
- private final double TICKS_PER_SAMPLE = ((double) Motherboard.SPEED) / SoundMixer.RATE;
- private final double TICKS_PER_SAMPLE_FLOOR = Math.floor(TICKS_PER_SAMPLE);
+ private double TICKS_PER_SAMPLE = ((double) Motherboard.DEFAULT_SPEED) / SoundMixer.RATE;
+ private double TICKS_PER_SAMPLE_FLOOR = Math.floor(TICKS_PER_SAMPLE);
private RAMListener listener = null;
/**
@@ -145,13 +151,14 @@ public class Speaker extends SoundGeneratorDevice {
boolean result = super.suspend();
if (playbackTimer != null) {
playbackTimer.cancel();
+ playbackTimer = null;
}
speakerBit = false;
- sdl = null;
- if (computer.getMotherboard() != null) {
- computer.getMotherboard().cancelSpeedRequest(this);
- computer.mixer.returnLine(this);
+ if (sdl != null && sdl.isOpen()) {
+ sdl.stop();
+ sdl.close();
}
+ sdl = null;
return result;
}
@@ -161,29 +168,29 @@ public class Speaker extends SoundGeneratorDevice {
*/
@Override
public void resume() {
- if (sdl != null && isRunning()) {
- return;
- }
- try {
- if (sdl == null || !sdl.isOpen()) {
- sdl = computer.mixer.getLine(this);
+ if (sdl == null || !sdl.isOpen()) {
+ sdl = computer.mixer.getLine();
+ if (sdl != null) {
+ sdl.start();
+ counter = 0;
+ idleCycles = 0;
+ level = 0;
+ bufferPos = 0;
+ } else {
+ Logger.getLogger(getClass().getName()).severe("Unable to get audio line for speaker!");
+ detach();
+ return;
}
- sdl.start();
- setRun(true);
- counter = 0;
- idleCycles = 0;
- level = 0;
- bufferPos = 0;
- playbackTimer = new Timer();
- playbackTimer.scheduleAtFixedRate(new TimerTask() {
- @Override
- public void run() {
- playCurrentBuffer();
- }
- }, 10, 30);
- } catch (LineUnavailableException ex) {
- Logger.getLogger(getClass().getName()).log(Level.SEVERE, "ERROR: Could not output sound", ex);
}
+
+ if (force1mhz) {
+ TICKS_PER_SAMPLE = ((double) Motherboard.DEFAULT_SPEED) / SoundMixer.RATE;
+ } else {
+ TICKS_PER_SAMPLE = Emulator.withComputer(c-> ((double) c.getMotherboard().getSpeedInHz()) / SoundMixer.RATE, 0.0);
+ }
+ TICKS_PER_SAMPLE_FLOOR = Math.floor(TICKS_PER_SAMPLE);
+
+ setRun(true);
}
public void playCurrentBuffer() {
@@ -196,7 +203,7 @@ public class Speaker extends SoundGeneratorDevice {
bufferPos = 0;
}
secondaryBuffer = buffer;
- if (sdl != null && buffer != null) {
+ if (sdl != null && len > 0) {
sdl.write(buffer, 0, len);
}
}
@@ -218,9 +225,6 @@ public class Speaker extends SoundGeneratorDevice {
*/
@Override
public void tick() {
- if (!isRunning() || sdl == null) {
- return;
- }
if (idleCycles++ >= MAX_IDLE_CYCLES) {
suspend();
}
@@ -229,22 +233,7 @@ public class Speaker extends SoundGeneratorDevice {
}
counter += 1.0d;
if (counter >= TICKS_PER_SAMPLE) {
- int sample = level * VOLUME;
- int bytes = SoundMixer.BITS >> 3;
- int shift = SoundMixer.BITS;
-
- while (bufferPos >= primaryBuffer.length) {
- Thread.yield();
- }
- synchronized (bufferLock) {
- int index = bufferPos;
- for (int i = 0; i < SoundMixer.BITS; i += 8, index++) {
- shift -= 8;
- primaryBuffer[index] = primaryBuffer[index + bytes] = (byte) ((sample >> shift) & 0x0ff);
- }
-
- bufferPos += bytes * 2;
- }
+ playSample(level * VOLUME);
// Set level back to 0
level = 0;
@@ -256,11 +245,33 @@ public class Speaker extends SoundGeneratorDevice {
private void toggleSpeaker(RAMEvent e) {
if (e.getType() == RAMEvent.TYPE.WRITE) {
level += 2;
- } else {
- speakerBit = !speakerBit;
}
+ speakerBit = !speakerBit;
resetIdle();
}
+
+ private void playSample(int sample) {
+ if (sdl == null || !sdl.isOpen()) {
+ resume();
+ }
+ int bytes = SoundMixer.BITS >> 3;
+
+ // Prepare sound output in little endian format
+ for (int i = 0; i < bytes; i++) {
+ primaryBuffer[i] = primaryBuffer[i+bytes] = (byte) (sample & 0x0ff);
+ sample >>= 8;
+ }
+ sdl.write(primaryBuffer, 0, bytes*2);
+ if (fileOutputActive) {
+ try {
+ out.write(primaryBuffer, 0, bytes*2);
+ } catch (IOException ex) {
+ Logger.getLogger(getClass().getName()).log(Level.SEVERE, "Error recording sound", ex);
+ toggleFileOutput();
+ }
+ }
+
+ }
/**
* Add a memory event listener for C03x for capturing speaker events
diff --git a/Platform/Apple/tools/jace/src/main/java/jace/apple2e/VideoDHGR.java b/Platform/Apple/tools/jace/src/main/java/jace/apple2e/VideoDHGR.java
index ce1c6464..9a2bb0bf 100644
--- a/Platform/Apple/tools/jace/src/main/java/jace/apple2e/VideoDHGR.java
+++ b/Platform/Apple/tools/jace/src/main/java/jace/apple2e/VideoDHGR.java
@@ -18,13 +18,18 @@
*/
package jace.apple2e;
-import jace.core.*;
+import java.util.logging.Logger;
+
+import jace.core.Computer;
+import jace.core.Font;
+import jace.core.Palette;
+import jace.core.RAMEvent;
+import jace.core.Video;
+import jace.core.VideoWriter;
import javafx.scene.image.PixelWriter;
import javafx.scene.image.WritableImage;
import javafx.scene.paint.Color;
-import java.util.logging.Logger;
-
/**
* This is the primary video rendering class, which provides all necessary video
* writers for every display mode as well as managing the display mode (via
@@ -430,7 +435,7 @@ public class VideoDHGR extends Video {
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) {
+ if (useColOffset >= 77 || useColOffset < 0) {
useColOffset = 76;
}
useColor[useColOffset ] = (b1 & 0x80) != 0;
diff --git a/Platform/Apple/tools/jace/src/main/java/jace/apple2e/VideoNTSC.java b/Platform/Apple/tools/jace/src/main/java/jace/apple2e/VideoNTSC.java
index 3289cc2e..a1c38d78 100644
--- a/Platform/Apple/tools/jace/src/main/java/jace/apple2e/VideoNTSC.java
+++ b/Platform/Apple/tools/jace/src/main/java/jace/apple2e/VideoNTSC.java
@@ -18,6 +18,10 @@
*/
package jace.apple2e;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+
import jace.Emulator;
import jace.EmulatorUILogic;
import jace.config.ConfigurableField;
@@ -30,10 +34,6 @@ import javafx.scene.image.PixelWriter;
import javafx.scene.image.WritableImage;
import javafx.scene.paint.Color;
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.Set;
-
/**
* Provides a clean color monitor simulation, complete with text-friendly
* palette and mixed color/bw (mode 7) rendering. This class extends the
@@ -94,51 +94,51 @@ public class VideoNTSC extends VideoDHGR {
defaultKeyMapping = {"ctrl+shift+g"})
public static void changeVideoMode() {
currentMode = (currentMode + 1) % VideoMode.values().length;
- ((VideoNTSC) Emulator.getComputer().getVideo())._setVideoMode(VideoMode.values()[currentMode], true);
+ Emulator.withVideo(v->((VideoNTSC) v)._setVideoMode(VideoMode.values()[currentMode], true));
}
public static void setVideoMode(VideoMode newMode, boolean showNotification) {
- ((VideoNTSC) Emulator.getComputer().getVideo())._setVideoMode(newMode, showNotification);
+ Emulator.withVideo(v->((VideoNTSC) v)._setVideoMode(newMode, showNotification));
}
private void _setVideoMode(VideoMode newMode, boolean showNotification) {
- VideoNTSC thiss = (VideoNTSC) Emulator.getComputer().video;
- thiss.monochomeMode = false;
- WHITE = Color.WHITE;
- switch (newMode) {
- case Amber:
- thiss.monochomeMode = true;
- WHITE = Color.web("ff8000");
- break;
- case Greenscreen:
- thiss.monochomeMode = true;
- WHITE = Color.web("0ccc68");
- break;
- case Monochrome:
- thiss.monochomeMode = true;
- break;
- case Color:
- thiss.useTextPalette = false;
- thiss.enableVideo7 = false;
- break;
- case Mode7:
- thiss.useTextPalette = false;
- thiss.enableVideo7 = true;
- break;
- case Mode7TextFriendly:
- thiss.useTextPalette = true;
- thiss.enableVideo7 = true;
- break;
- case TextFriendly:
- thiss.useTextPalette = true;
- thiss.enableVideo7 = false;
- break;
- }
- thiss.activePalette = thiss.useTextPalette ? TEXT_PALETTE : SOLID_PALETTE;
- if (showNotification) {
- EmulatorUILogic.notify("Video mode: " + newMode.name);
- }
- forceRefresh();
+ Emulator.withVideo(v-> {
+ VideoNTSC thiss = (VideoNTSC) v;
+ thiss.monochomeMode = false;
+ WHITE = Color.WHITE;
+ switch (newMode) {
+ case Amber -> {
+ thiss.monochomeMode = true;
+ WHITE = Color.web("ff8000");
+ }
+ case Greenscreen -> {
+ thiss.monochomeMode = true;
+ WHITE = Color.web("0ccc68");
+ }
+ case Monochrome -> thiss.monochomeMode = true;
+ case Color -> {
+ thiss.useTextPalette = false;
+ thiss.enableVideo7 = false;
+ }
+ case Mode7 -> {
+ thiss.useTextPalette = false;
+ thiss.enableVideo7 = true;
+ }
+ case Mode7TextFriendly -> {
+ thiss.useTextPalette = true;
+ thiss.enableVideo7 = true;
+ }
+ case TextFriendly -> {
+ thiss.useTextPalette = true;
+ thiss.enableVideo7 = false;
+ }
+ }
+ thiss.activePalette = thiss.useTextPalette ? TEXT_PALETTE : SOLID_PALETTE;
+ if (showNotification) {
+ EmulatorUILogic.notify("Video mode: " + newMode.name);
+ }
+ forceRefresh();
+ });
}
@Override
diff --git a/Platform/Apple/tools/jace/src/main/java/jace/apple2e/softswitch/IntC8SoftSwitch.java b/Platform/Apple/tools/jace/src/main/java/jace/apple2e/softswitch/IntC8SoftSwitch.java
index 385ce419..edf81787 100644
--- a/Platform/Apple/tools/jace/src/main/java/jace/apple2e/softswitch/IntC8SoftSwitch.java
+++ b/Platform/Apple/tools/jace/src/main/java/jace/apple2e/softswitch/IntC8SoftSwitch.java
@@ -18,6 +18,7 @@
*/
package jace.apple2e.softswitch;
+import jace.Emulator;
import jace.apple2e.SoftSwitches;
import jace.core.RAMEvent;
import jace.core.RAMListener;
@@ -76,8 +77,6 @@ public class IntC8SoftSwitch extends SoftSwitch {
@Override
public void stateChanged() {
- if (computer.getMemory() != null) {
- computer.getMemory().configureActiveMemory();
- }
+ Emulator.withMemory(m->m.configureActiveMemory());
}
}
\ No newline at end of file
diff --git a/Platform/Apple/tools/jace/src/main/java/jace/apple2e/softswitch/MemorySoftSwitch.java b/Platform/Apple/tools/jace/src/main/java/jace/apple2e/softswitch/MemorySoftSwitch.java
index 811970e2..ba3bf8d6 100644
--- a/Platform/Apple/tools/jace/src/main/java/jace/apple2e/softswitch/MemorySoftSwitch.java
+++ b/Platform/Apple/tools/jace/src/main/java/jace/apple2e/softswitch/MemorySoftSwitch.java
@@ -18,6 +18,7 @@
*/
package jace.apple2e.softswitch;
+import jace.Emulator;
import jace.core.RAMEvent;
import jace.core.SoftSwitch;
@@ -40,15 +41,13 @@ public class MemorySoftSwitch extends SoftSwitch {
@Override
public void stateChanged() {
// System.out.println(getName()+ " was switched to "+getState());
- if (computer.getMemory() != null) {
- computer.getMemory().configureActiveMemory();
- }
+ Emulator.withMemory(m->m.configureActiveMemory());
}
// Todo: Implement floating bus, maybe?
@Override
protected byte readSwitch() {
- byte value = computer.getVideo().getFloatingBus();
+ byte value = Emulator.withComputer(c->c.getVideo().getFloatingBus(), (byte) 0);
if (getState()) {
return (byte) (value | 0x080);
} else {
diff --git a/Platform/Apple/tools/jace/src/main/java/jace/apple2e/softswitch/VideoSoftSwitch.java b/Platform/Apple/tools/jace/src/main/java/jace/apple2e/softswitch/VideoSoftSwitch.java
index 7413cb70..dfc219d6 100644
--- a/Platform/Apple/tools/jace/src/main/java/jace/apple2e/softswitch/VideoSoftSwitch.java
+++ b/Platform/Apple/tools/jace/src/main/java/jace/apple2e/softswitch/VideoSoftSwitch.java
@@ -18,6 +18,7 @@
*/
package jace.apple2e.softswitch;
+import jace.Emulator;
import jace.core.RAMEvent;
import jace.core.SoftSwitch;
@@ -40,9 +41,7 @@ public class VideoSoftSwitch extends SoftSwitch {
@Override
public void stateChanged() {
// System.out.println("Set "+getName()+" -> "+getState());
- if (computer.getVideo() != null) {
- computer.getVideo().configureVideoMode();
- }
+ Emulator.withVideo(video -> video.configureVideoMode());
}
@Override
diff --git a/Platform/Apple/tools/jace/src/main/java/jace/applesoft/ApplesoftHandler.java b/Platform/Apple/tools/jace/src/main/java/jace/applesoft/ApplesoftHandler.java
index b8d10fcc..f962fa64 100644
--- a/Platform/Apple/tools/jace/src/main/java/jace/applesoft/ApplesoftHandler.java
+++ b/Platform/Apple/tools/jace/src/main/java/jace/applesoft/ApplesoftHandler.java
@@ -17,7 +17,7 @@ public class ApplesoftHandler implements LanguageHandler {
@Override
public String getNewDocumentContent() {
- return ApplesoftProgram.fromMemory(Emulator.getComputer().getMemory()).toString();
+ return Emulator.withComputer(c->ApplesoftProgram.fromMemory(c.getMemory()).toString(), "");
}
@Override
diff --git a/Platform/Apple/tools/jace/src/main/java/jace/applesoft/ApplesoftProgram.java b/Platform/Apple/tools/jace/src/main/java/jace/applesoft/ApplesoftProgram.java
index 90888482..ed421b99 100644
--- a/Platform/Apple/tools/jace/src/main/java/jace/applesoft/ApplesoftProgram.java
+++ b/Platform/Apple/tools/jace/src/main/java/jace/applesoft/ApplesoftProgram.java
@@ -18,10 +18,6 @@
*/
package jace.applesoft;
-import jace.Emulator;
-import jace.core.RAM;
-import jace.core.RAMEvent;
-import jace.core.RAMListener;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
@@ -33,6 +29,11 @@ import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Collectors;
+import jace.Emulator;
+import jace.core.RAM;
+import jace.core.RAMEvent;
+import jace.core.RAMListener;
+
/**
* Decode an applesoft program into a list of program lines Right now this is an
* example/test program but it successfully tokenized the source of Lemonade
@@ -149,70 +150,70 @@ public class ApplesoftProgram {
}
public void run() {
- RAM memory = Emulator.getComputer().memory;
- Emulator.getComputer().pause();
- int programStart = memory.readWordRaw(START_OF_PROG_POINTER);
- int programEnd = programStart + getProgramSize();
- if (isProgramRunning()) {
- whenReady(()->{
- relocateVariables(programEnd);
+ Emulator.withComputer(c->c.getMotherboard().whileSuspended(()->{
+ int programStart = c.getMemory().readWordRaw(START_OF_PROG_POINTER);
+ int programEnd = programStart + getProgramSize();
+ if (isProgramRunning()) {
+ whenReady(()->{
+ relocateVariables(programEnd);
+ injectProgram();
+ });
+ } else {
injectProgram();
- });
- } else {
- injectProgram();
- clearVariables(programEnd);
- }
- Emulator.getComputer().resume();
+ clearVariables(programEnd);
+ }
+ }));
}
private void injectProgram() {
- RAM memory = Emulator.getComputer().memory;
- int pos = memory.readWordRaw(START_OF_PROG_POINTER);
- for (Line line : lines) {
- int nextPos = pos + line.getLength();
- memory.writeWord(pos, nextPos, false, true);
- pos += 2;
- memory.writeWord(pos, line.getNumber(), false, true);
- pos += 2;
- boolean isFirst = true;
- for (Command command : line.getCommands()) {
- if (!isFirst) {
- memory.write(pos++, (byte) ':', false, true);
- }
- isFirst = false;
- for (Command.ByteOrToken part : command.parts) {
- memory.write(pos++, part.getByte(), false, true);
+ Emulator.withMemory(memory->{
+ int pos = memory.readWordRaw(START_OF_PROG_POINTER);
+ for (Line line : lines) {
+ int nextPos = pos + line.getLength();
+ memory.writeWord(pos, nextPos, false, true);
+ pos += 2;
+ memory.writeWord(pos, line.getNumber(), false, true);
+ pos += 2;
+ boolean isFirst = true;
+ for (Command command : line.getCommands()) {
+ if (!isFirst) {
+ memory.write(pos++, (byte) ':', false, true);
+ }
+ isFirst = false;
+ for (Command.ByteOrToken part : command.parts) {
+ memory.write(pos++, part.getByte(), false, true);
+ }
}
+ memory.write(pos++, (byte) 0, false, true);
}
memory.write(pos++, (byte) 0, false, true);
- }
- memory.write(pos++, (byte) 0, false, true);
- memory.write(pos++, (byte) 0, false, true);
- memory.write(pos++, (byte) 0, false, true);
- memory.write(pos++, (byte) 0, false, true);
+ memory.write(pos++, (byte) 0, false, true);
+ memory.write(pos++, (byte) 0, false, true);
+ memory.write(pos++, (byte) 0, false, true);
+ });
}
private boolean isProgramRunning() {
- RAM memory = Emulator.getComputer().memory;
- return (memory.readRaw(RUNNING_FLAG) & 0x0FF) != NOT_RUNNING;
+ return Emulator.withComputer(c->(c.getMemory().readRaw(RUNNING_FLAG) & 0x0FF) != NOT_RUNNING, false);
}
/**
* If the program is running, wait until it advances to the next line
*/
private void whenReady(Runnable r) {
- RAM memory = Emulator.getComputer().memory;
- memory.addListener(new RAMListener(RAMEvent.TYPE.EXECUTE, RAMEvent.SCOPE.ADDRESS, RAMEvent.VALUE.ANY) {
- @Override
- protected void doConfig() {
- setScopeStart(GOTO_CMD);
- }
+ Emulator.withMemory(memory->{
+ memory.addListener(new RAMListener(RAMEvent.TYPE.EXECUTE, RAMEvent.SCOPE.ADDRESS, RAMEvent.VALUE.ANY) {
+ @Override
+ protected void doConfig() {
+ setScopeStart(GOTO_CMD);
+ }
- @Override
- protected void doEvent(RAMEvent e) {
- r.run();
- memory.removeListener(this);
- }
+ @Override
+ protected void doEvent(RAMEvent e) {
+ r.run();
+ memory.removeListener(this);
+ }
+ });
});
}
@@ -222,11 +223,12 @@ public class ApplesoftProgram {
* @param programEnd Program ending address
*/
private void clearVariables(int programEnd) {
- RAM memory = Emulator.getComputer().memory;
- memory.writeWord(ARRAY_TABLE, programEnd, false, true);
- memory.writeWord(VARIABLE_TABLE, programEnd, false, true);
- memory.writeWord(VARIABLE_TABLE_END, programEnd, false, true);
- memory.writeWord(END_OF_PROG_POINTER, programEnd, false, true);
+ Emulator.withMemory(memory->{
+ memory.writeWord(ARRAY_TABLE, programEnd, false, true);
+ memory.writeWord(VARIABLE_TABLE, programEnd, false, true);
+ memory.writeWord(VARIABLE_TABLE_END, programEnd, false, true);
+ memory.writeWord(END_OF_PROG_POINTER, programEnd, false, true);
+ });
}
/**
@@ -234,20 +236,21 @@ public class ApplesoftProgram {
* @param programEnd Program ending address
*/
private void relocateVariables(int programEnd) {
- RAM memory = Emulator.getComputer().memory;
- int currentEnd = memory.readWordRaw(END_OF_PROG_POINTER);
- memory.writeWord(END_OF_PROG_POINTER, programEnd, false, true);
- if (programEnd > currentEnd) {
- int diff = programEnd - currentEnd;
- int himem = memory.readWordRaw(HIMEM);
- for (int i=himem - diff; i >= programEnd; i--) {
- memory.write(i+diff, memory.readRaw(i), false, true);
+ Emulator.withMemory(memory->{
+ int currentEnd = memory.readWordRaw(END_OF_PROG_POINTER);
+ memory.writeWord(END_OF_PROG_POINTER, programEnd, false, true);
+ if (programEnd > currentEnd) {
+ int diff = programEnd - currentEnd;
+ int himem = memory.readWordRaw(HIMEM);
+ for (int i=himem - diff; i >= programEnd; i--) {
+ memory.write(i+diff, memory.readRaw(i), false, true);
+ }
+ memory.writeWord(VARIABLE_TABLE, memory.readWordRaw(VARIABLE_TABLE) + diff, false, true);
+ memory.writeWord(ARRAY_TABLE, memory.readWordRaw(ARRAY_TABLE) + diff, false, true);
+ memory.writeWord(VARIABLE_TABLE_END, memory.readWordRaw(VARIABLE_TABLE_END) + diff, false, true);
+ memory.writeWord(STRING_TABLE, memory.readWordRaw(STRING_TABLE) + diff, false, true);
}
- memory.writeWord(VARIABLE_TABLE, memory.readWordRaw(VARIABLE_TABLE) + diff, false, true);
- memory.writeWord(ARRAY_TABLE, memory.readWordRaw(ARRAY_TABLE) + diff, false, true);
- memory.writeWord(VARIABLE_TABLE_END, memory.readWordRaw(VARIABLE_TABLE_END) + diff, false, true);
- memory.writeWord(STRING_TABLE, memory.readWordRaw(STRING_TABLE) + diff, false, true);
- }
+ });
}
private int getProgramSize() {
diff --git a/Platform/Apple/tools/jace/src/main/java/jace/assembly/AcmeCrossAssembler.java b/Platform/Apple/tools/jace/src/main/java/jace/assembly/AcmeCrossAssembler.java
index 12642236..c599d43e 100644
--- a/Platform/Apple/tools/jace/src/main/java/jace/assembly/AcmeCrossAssembler.java
+++ b/Platform/Apple/tools/jace/src/main/java/jace/assembly/AcmeCrossAssembler.java
@@ -91861,283 +91861,283 @@ public final class AcmeCrossAssembler extends UnixRuntime {
private static final java.util.Hashtable symbols = new java.util.Hashtable();
static {
- symbols.put("setgrent",new Integer(0x53c00));
- symbols.put("chroot",new Integer(0x4cc00));
- symbols.put("strcpy",new Integer(0x42e00));
- symbols.put("cliargs_get_rest",new Integer(0x16e00));
- symbols.put("flow_store_doloop_condition",new Integer(0x19600));
- symbols.put("fabs",new Integer(0x32a00));
- symbols.put("waitpid",new Integer(0x4ae00));
- symbols.put("vcpu_set_pc",new Integer(0x27e00));
- symbols.put("flow_parse_block_else_block",new Integer(0x19a00));
- symbols.put("Output_passinit",new Integer(0x27600));
- symbols.put("Input_until_terminator",new Integer(0x1d800));
- symbols.put("GetQuotedByte",new Integer(0x1c600));
- symbols.put("getgid",new Integer(0x496c4));
- symbols.put("sysconf",new Integer(0x4a400));
- symbols.put("printf",new Integer(0x3fc00));
- symbols.put("vsprintf",new Integer(0x65200));
- symbols.put("utime",new Integer(0x4a800));
- symbols.put("Input_skip_or_store_block",new Integer(0x1d400));
- symbols.put("getlogin",new Integer(0x54e00));
- symbols.put("recv",new Integer(0x4fe00));
- symbols.put("Input_skip_remainder",new Integer(0x1c800));
- symbols.put("connect",new Integer(0x4e200));
- symbols.put("ungetc",new Integer(0x6a800));
- symbols.put("GetByte",new Integer(0x1c000));
- symbols.put("safe_malloc",new Integer(0x1b400));
- symbols.put("geteuid",new Integer(0x496b4));
- symbols.put("symbol_fix_forward_anon_name",new Integer(0x30800));
- symbols.put("memmove",new Integer(0x5b600));
- symbols.put("keyword_is_65816mnemo",new Integer(0x24e00));
- symbols.put("snprintf",new Integer(0x41c00));
- symbols.put("pathconf",new Integer(0x4c800));
- symbols.put("Tree_easy_scan",new Integer(0x31000));
- symbols.put("mknod",new Integer(0x4ce00));
- symbols.put("getgrgid",new Integer(0x53800));
- symbols.put("dump_tree",new Integer(0x31400));
- symbols.put("getenv",new Integer(0x3e000));
- symbols.put("fchmod",new Integer(0x4c000));
- symbols.put("floor",new Integer(0x37600));
- symbols.put("getegid",new Integer(0x496d4));
- symbols.put("setpriority",new Integer(0x4e000));
- symbols.put("getpriority",new Integer(0x4de00));
- symbols.put("usleep",new Integer(0x4d200));
- symbols.put("typesystem_want_imm",new Integer(0x32000));
- symbols.put("getpagesize",new Integer(0x48b80));
- symbols.put("fchown",new Integer(0x4ba00));
- symbols.put("fgets",new Integer(0x59400));
- symbols.put("dirname",new Integer(0x55000));
- symbols.put("Section_finalize",new Integer(0x2e600));
- symbols.put("Throw_warning",new Integer(0x1ac00));
- symbols.put("memcpy",new Integer(0x48fdc));
- symbols.put("DynaBuf_to_lower",new Integer(0x18000));
- symbols.put("Throw_error",new Integer(0x1b000));
- symbols.put("ALU_any_result",new Integer(0x16400));
- symbols.put("readlink",new Integer(0x4b600));
- symbols.put("puts",new Integer(0x40400));
- symbols.put("dup2",new Integer(0x4ac00));
- symbols.put("mbrtowc",new Integer(0x66200));
- symbols.put("getpass",new Integer(0x54a00));
- symbols.put("getuid",new Integer(0x496a4));
- symbols.put("malloc",new Integer(0x3e800));
- symbols.put("isatty",new Integer(0x5a200));
- symbols.put("symbol_define",new Integer(0x30200));
- symbols.put("iswspace",new Integer(0x65e00));
- symbols.put("endpwent",new Integer(0x54800));
- symbols.put("sleep",new Integer(0x48af0));
- symbols.put("vsnprintf",new Integer(0x64e00));
- symbols.put("recvfrom",new Integer(0x4f800));
- symbols.put("strtoul",new Integer(0x5fc00));
- symbols.put("ACME_finalize",new Integer(0x11800));
- symbols.put("typesystem_force_address_statement",new Integer(0x31e00));
- symbols.put("gethostbyaddr",new Integer(0x53200));
- symbols.put("rmdir",new Integer(0x4a200));
- symbols.put("Input_append_keyword_to_global_dynabuf",new Integer(0x1dc00));
- symbols.put("socket",new Integer(0x4e400));
- symbols.put("select",new Integer(0x4fa00));
- symbols.put("readdir",new Integer(0x52600));
- symbols.put("lchown",new Integer(0x4bc00));
- symbols.put("setgroups",new Integer(0x50e00));
- symbols.put("fflush",new Integer(0x39a00));
- symbols.put("cliargs_safe_get_next",new Integer(0x16a00));
- symbols.put("ftruncate",new Integer(0x4d000));
- symbols.put("realpath",new Integer(0x4d800));
- symbols.put("keyword_is_6510mnemo",new Integer(0x23000));
- symbols.put("chown",new Integer(0x4b800));
- symbols.put("send",new Integer(0x4fc00));
- symbols.put("vcpu_check_and_set_reg_length",new Integer(0x17200));
- symbols.put("Output_init",new Integer(0x26e00));
- symbols.put("chmod",new Integer(0x4be00));
- symbols.put("alarm",new Integer(0x49a64));
- symbols.put("Parse_optional_block",new Integer(0x1b600));
- symbols.put("strtol",new Integer(0x43600));
- symbols.put("pipe",new Integer(0x4aa00));
- symbols.put("encoding_passinit",new Integer(0x18e00));
- symbols.put("uname",new Integer(0x55400));
- symbols.put("symbol_parse_definition",new Integer(0x2fc00));
- symbols.put("Output_start_segment",new Integer(0x27a00));
- symbols.put("accept",new Integer(0x4ea00));
- symbols.put("rint",new Integer(0x38000));
- symbols.put("basename",new Integer(0x55200));
- symbols.put("ALU_optional_defined_int",new Integer(0x15a00));
- symbols.put("output_set_output_filename",new Integer(0x26c00));
- symbols.put("DynaBuf_get_copy",new Integer(0x17a00));
- symbols.put("output_set_output_format",new Integer(0x26800));
- symbols.put("strtod",new Integer(0x68800));
- symbols.put("Throw_first_pass_warning",new Integer(0x1ae00));
- symbols.put("Parse_until_eob_or_eof",new Integer(0x1a400));
- symbols.put("sysctl",new Integer(0x4dc00));
- symbols.put("fstat",new Integer(0x62e00));
- symbols.put("fprintf",new Integer(0x3bc00));
- symbols.put("cputype_passinit",new Integer(0x17400));
- symbols.put("setpwent",new Integer(0x54600));
- symbols.put("bind",new Integer(0x4f000));
- symbols.put("inet_addr",new Integer(0x56200));
- symbols.put("mkfifo",new Integer(0x4d400));
- symbols.put("chdir",new Integer(0x4a600));
- symbols.put("Input_read_keyword",new Integer(0x1ec00));
- symbols.put("cputype_find",new Integer(0x17000));
- symbols.put("initgroups",new Integer(0x56600));
- symbols.put("Macro_parse_definition",new Integer(0x20600));
- symbols.put("endgrent",new Integer(0x53e00));
- symbols.put("setsockopt",new Integer(0x4ee00));
- symbols.put("fseek",new Integer(0x3d400));
- symbols.put("cos",new Integer(0x32800));
- symbols.put("memchr",new Integer(0x5b400));
- symbols.put("output_le16",new Integer(0x26000));
- symbols.put("umask",new Integer(0x49694));
- symbols.put("symbol_set_value",new Integer(0x2f600));
- symbols.put("symbol_find",new Integer(0x2f400));
- symbols.put("lstat",new Integer(0x4c200));
- symbols.put("sin",new Integer(0x32c00));
- symbols.put("setgid",new Integer(0x50a00));
- symbols.put("signal",new Integer(0x5ea00));
- symbols.put("output_8",new Integer(0x25e00));
- symbols.put("strncmp",new Integer(0x43000));
- symbols.put("DynaBuf_create",new Integer(0x17600));
- symbols.put("pow",new Integer(0x33400));
- symbols.put("keyword_is_6502mnemo",new Integer(0x22600));
- symbols.put("strncpy",new Integer(0x5f400));
- symbols.put("DynaBuf_add_string",new Integer(0x17e00));
- symbols.put("Input_read_filename",new Integer(0x1fc00));
- symbols.put("sync",new Integer(0x51e00));
- symbols.put("ALU_int_result",new Integer(0x15c00));
- symbols.put("sendto",new Integer(0x4f600));
- symbols.put("realloc",new Integer(0x40600));
- symbols.put("vcpu_get_statement_size",new Integer(0x28200));
- symbols.put("Section_passinit",new Integer(0x2e800));
- symbols.put("listen",new Integer(0x4f200));
- symbols.put("fork",new Integer(0x62c00));
- symbols.put("sscanf",new Integer(0x5f000));
- symbols.put("getgrent",new Integer(0x53a00));
- symbols.put("sigaction",new Integer(0x52200));
- symbols.put("fread",new Integer(0x3c600));
- symbols.put("inet_aton",new Integer(0x55e00));
- symbols.put("Input_read_and_lower_keyword",new Integer(0x1f400));
- symbols.put("symlink",new Integer(0x4b400));
- symbols.put("encoding_find",new Integer(0x19200));
- symbols.put("Tree_add_table",new Integer(0x30e00));
- symbols.put("DynaBuf_init",new Integer(0x18200));
- symbols.put("fopen",new Integer(0x3b800));
- symbols.put("memset",new Integer(0x48fec));
- symbols.put("main",new Integer(0x11c00));
- symbols.put("typesystem_want_addr",new Integer(0x32200));
- symbols.put("Output_end_segment",new Integer(0x27800));
- symbols.put("Output_fake",new Integer(0x25c00));
- symbols.put("add_node_to_tree",new Integer(0x30c00));
- symbols.put("pseudoopcodes_init",new Integer(0x2e000));
- symbols.put("DynaBuf_append",new Integer(0x17c00));
- symbols.put("matherr",new Integer(0x37c00));
- symbols.put("fclose",new Integer(0x39200));
- symbols.put("inet_ntoa",new Integer(0x52a00));
- symbols.put("getppid",new Integer(0x491bc));
- symbols.put("opendir",new Integer(0x52400));
- symbols.put("getgroups",new Integer(0x50000));
- symbols.put("keyword_is_c64dtv2mnemo",new Integer(0x23a00));
- symbols.put("getgrouplist",new Integer(0x56400));
- symbols.put("seteuid",new Integer(0x50800));
- symbols.put("keyword_is_65c02mnemo",new Integer(0x24400));
- symbols.put("putc",new Integer(0x40000));
- symbols.put("output_initmem",new Integer(0x26600));
- symbols.put("finite",new Integer(0x37400));
- symbols.put("herror",new Integer(0x53000));
- symbols.put("strcmp",new Integer(0x42c00));
- symbols.put("flow_forloop",new Integer(0x19400));
- symbols.put("shutdown",new Integer(0x4f400));
- symbols.put("tan",new Integer(0x32e00));
- symbols.put("ttyname",new Integer(0x52000));
- symbols.put("vfiprintf",new Integer(0x64a00));
- symbols.put("getpwuid",new Integer(0x54200));
- symbols.put("Input_read_zone_and_keyword",new Integer(0x1e400));
- symbols.put("dup",new Integer(0x4c600));
- symbols.put("copysign",new Integer(0x38800));
- symbols.put("getcwd",new Integer(0x4b000));
- symbols.put("Section_new_zone",new Integer(0x2e400));
- symbols.put("encoding_load",new Integer(0x19000));
- symbols.put("gethostbyname",new Integer(0x53400));
- symbols.put("getpwnam",new Integer(0x54000));
- symbols.put("getservbyname",new Integer(0x52c00));
- symbols.put("atan",new Integer(0x32400));
- symbols.put("gethostname",new Integer(0x55a00));
- symbols.put("sprintf",new Integer(0x42000));
- symbols.put("pseudoopcode_parse",new Integer(0x2e200));
- symbols.put("Tree_hard_scan",new Integer(0x31200));
- symbols.put("strtof",new Integer(0x68a00));
- symbols.put("atexit",new Integer(0x38a00));
- symbols.put("cliargs_get_next",new Integer(0x16600));
- symbols.put("output_le32",new Integer(0x26400));
- symbols.put("asin",new Integer(0x33200));
- symbols.put("setlocale",new Integer(0x5b000));
- symbols.put("getpeername",new Integer(0x50400));
- symbols.put("Throw_serious_error",new Integer(0x1b200));
- symbols.put("nanf",new Integer(0x66a00));
- symbols.put("cliargs_init",new Integer(0x16c00));
- symbols.put("scalbn",new Integer(0x38400));
- symbols.put("vfork",new Integer(0x4ca00));
- symbols.put("ALU_liberal_int",new Integer(0x16200));
- symbols.put("symbols_vicelabels",new Integer(0x30600));
- symbols.put("fsync",new Integer(0x51200));
- symbols.put("Mnemo_init",new Integer(0x22400));
- symbols.put("fputc",new Integer(0x3c000));
- symbols.put("symbol_set_label",new Integer(0x2f800));
- symbols.put("DynaBuf_enlarge",new Integer(0x17800));
- symbols.put("getsockopt",new Integer(0x4ec00));
- symbols.put("typesystem_force_address_block",new Integer(0x31c00));
- symbols.put("hstrerror",new Integer(0x52e00));
- symbols.put("vcpu_end_statement",new Integer(0x28400));
- symbols.put("nan",new Integer(0x37e00));
- symbols.put("Macro_parse_call",new Integer(0x20a00));
- symbols.put("encoding_encode_char",new Integer(0x18c00));
- symbols.put("Input_new_file",new Integer(0x1be00));
- symbols.put("localeconv",new Integer(0x5b200));
- symbols.put("Tree_dump_forest",new Integer(0x31800));
- symbols.put("Bug_found",new Integer(0x1b800));
- symbols.put("Output_save_file",new Integer(0x27000));
- symbols.put("fwrite",new Integer(0x3dc00));
- symbols.put("vcpu_read_pc",new Integer(0x28000));
- symbols.put("access",new Integer(0x4a000));
- symbols.put("ALU_any_int",new Integer(0x15e00));
- symbols.put("notreallypo_setpc",new Integer(0x2de00));
- symbols.put("getdents",new Integer(0x4c400));
- symbols.put("Input_accept_comma",new Integer(0x20000));
- symbols.put("exit",new Integer(0x38e00));
- symbols.put("klogctl",new Integer(0x4d600));
- symbols.put("typesystem_says_address",new Integer(0x31a00));
- symbols.put("getgrnam",new Integer(0x53600));
- symbols.put("make_hash",new Integer(0x30a00));
- symbols.put("output_prefer_cbm_file_format",new Integer(0x26a00));
- symbols.put("AnyOS_entry",new Integer(0x28600));
- symbols.put("Macro_init",new Integer(0x20400));
- symbols.put("ALU_init",new Integer(0x15800));
- symbols.put("getpwent",new Integer(0x54400));
- symbols.put("daemon",new Integer(0x55c00));
- symbols.put("strlen",new Integer(0x10268));
- symbols.put("open",new Integer(0x63000));
- symbols.put("Input_get_force_bit",new Integer(0x20200));
- symbols.put("fputs",new Integer(0x59a00));
- symbols.put("setsid",new Integer(0x51000));
- symbols.put("setegid",new Integer(0x50c00));
- symbols.put("closedir",new Integer(0x52800));
- symbols.put("cliargs_handle_options",new Integer(0x16800));
- symbols.put("acos",new Integer(0x33000));
- symbols.put("output_le24",new Integer(0x26200));
- symbols.put("vasprintf",new Integer(0x54c00));
- symbols.put("Input_ensure_EOS",new Integer(0x1ce00));
- symbols.put("setuid",new Integer(0x50600));
- symbols.put("mkdir",new Integer(0x49e00));
- symbols.put("ALU_defined_int",new Integer(0x16000));
- symbols.put("wcrtomb",new Integer(0x6ac00));
- symbols.put("close",new Integer(0x62a00));
- symbols.put("symbols_list",new Integer(0x30400));
- symbols.put("flow_parse_and_close_file",new Integer(0x19c00));
- symbols.put("flow_doloop",new Integer(0x19800));
- symbols.put("_call_helper",new Integer(0x10284));
- symbols.put("vfprintf",new Integer(0x48000));
- symbols.put("fputwc",new Integer(0x65c00));
- symbols.put("raise",new Integer(0x5e800));
- symbols.put("free",new Integer(0x3ea00));
- symbols.put("getsockname",new Integer(0x50200));
+ symbols.put("setgrent",Integer.valueOf(0x53c00));
+ symbols.put("chroot",Integer.valueOf(0x4cc00));
+ symbols.put("strcpy",Integer.valueOf(0x42e00));
+ symbols.put("cliargs_get_rest",Integer.valueOf(0x16e00));
+ symbols.put("flow_store_doloop_condition",Integer.valueOf(0x19600));
+ symbols.put("fabs",Integer.valueOf(0x32a00));
+ symbols.put("waitpid",Integer.valueOf(0x4ae00));
+ symbols.put("vcpu_set_pc",Integer.valueOf(0x27e00));
+ symbols.put("flow_parse_block_else_block",Integer.valueOf(0x19a00));
+ symbols.put("Output_passinit",Integer.valueOf(0x27600));
+ symbols.put("Input_until_terminator",Integer.valueOf(0x1d800));
+ symbols.put("GetQuotedByte",Integer.valueOf(0x1c600));
+ symbols.put("getgid",Integer.valueOf(0x496c4));
+ symbols.put("sysconf",Integer.valueOf(0x4a400));
+ symbols.put("printf",Integer.valueOf(0x3fc00));
+ symbols.put("vsprintf",Integer.valueOf(0x65200));
+ symbols.put("utime",Integer.valueOf(0x4a800));
+ symbols.put("Input_skip_or_store_block",Integer.valueOf(0x1d400));
+ symbols.put("getlogin",Integer.valueOf(0x54e00));
+ symbols.put("recv",Integer.valueOf(0x4fe00));
+ symbols.put("Input_skip_remainder",Integer.valueOf(0x1c800));
+ symbols.put("connect",Integer.valueOf(0x4e200));
+ symbols.put("ungetc",Integer.valueOf(0x6a800));
+ symbols.put("GetByte",Integer.valueOf(0x1c000));
+ symbols.put("safe_malloc",Integer.valueOf(0x1b400));
+ symbols.put("geteuid",Integer.valueOf(0x496b4));
+ symbols.put("symbol_fix_forward_anon_name",Integer.valueOf(0x30800));
+ symbols.put("memmove",Integer.valueOf(0x5b600));
+ symbols.put("keyword_is_65816mnemo",Integer.valueOf(0x24e00));
+ symbols.put("snprintf",Integer.valueOf(0x41c00));
+ symbols.put("pathconf",Integer.valueOf(0x4c800));
+ symbols.put("Tree_easy_scan",Integer.valueOf(0x31000));
+ symbols.put("mknod",Integer.valueOf(0x4ce00));
+ symbols.put("getgrgid",Integer.valueOf(0x53800));
+ symbols.put("dump_tree",Integer.valueOf(0x31400));
+ symbols.put("getenv",Integer.valueOf(0x3e000));
+ symbols.put("fchmod",Integer.valueOf(0x4c000));
+ symbols.put("floor",Integer.valueOf(0x37600));
+ symbols.put("getegid",Integer.valueOf(0x496d4));
+ symbols.put("setpriority",Integer.valueOf(0x4e000));
+ symbols.put("getpriority",Integer.valueOf(0x4de00));
+ symbols.put("usleep",Integer.valueOf(0x4d200));
+ symbols.put("typesystem_want_imm",Integer.valueOf(0x32000));
+ symbols.put("getpagesize",Integer.valueOf(0x48b80));
+ symbols.put("fchown",Integer.valueOf(0x4ba00));
+ symbols.put("fgets",Integer.valueOf(0x59400));
+ symbols.put("dirname",Integer.valueOf(0x55000));
+ symbols.put("Section_finalize",Integer.valueOf(0x2e600));
+ symbols.put("Throw_warning",Integer.valueOf(0x1ac00));
+ symbols.put("memcpy",Integer.valueOf(0x48fdc));
+ symbols.put("DynaBuf_to_lower",Integer.valueOf(0x18000));
+ symbols.put("Throw_error",Integer.valueOf(0x1b000));
+ symbols.put("ALU_any_result",Integer.valueOf(0x16400));
+ symbols.put("readlink",Integer.valueOf(0x4b600));
+ symbols.put("puts",Integer.valueOf(0x40400));
+ symbols.put("dup2",Integer.valueOf(0x4ac00));
+ symbols.put("mbrtowc",Integer.valueOf(0x66200));
+ symbols.put("getpass",Integer.valueOf(0x54a00));
+ symbols.put("getuid",Integer.valueOf(0x496a4));
+ symbols.put("malloc",Integer.valueOf(0x3e800));
+ symbols.put("isatty",Integer.valueOf(0x5a200));
+ symbols.put("symbol_define",Integer.valueOf(0x30200));
+ symbols.put("iswspace",Integer.valueOf(0x65e00));
+ symbols.put("endpwent",Integer.valueOf(0x54800));
+ symbols.put("sleep",Integer.valueOf(0x48af0));
+ symbols.put("vsnprintf",Integer.valueOf(0x64e00));
+ symbols.put("recvfrom",Integer.valueOf(0x4f800));
+ symbols.put("strtoul",Integer.valueOf(0x5fc00));
+ symbols.put("ACME_finalize",Integer.valueOf(0x11800));
+ symbols.put("typesystem_force_address_statement",Integer.valueOf(0x31e00));
+ symbols.put("gethostbyaddr",Integer.valueOf(0x53200));
+ symbols.put("rmdir",Integer.valueOf(0x4a200));
+ symbols.put("Input_append_keyword_to_global_dynabuf",Integer.valueOf(0x1dc00));
+ symbols.put("socket",Integer.valueOf(0x4e400));
+ symbols.put("select",Integer.valueOf(0x4fa00));
+ symbols.put("readdir",Integer.valueOf(0x52600));
+ symbols.put("lchown",Integer.valueOf(0x4bc00));
+ symbols.put("setgroups",Integer.valueOf(0x50e00));
+ symbols.put("fflush",Integer.valueOf(0x39a00));
+ symbols.put("cliargs_safe_get_next",Integer.valueOf(0x16a00));
+ symbols.put("ftruncate",Integer.valueOf(0x4d000));
+ symbols.put("realpath",Integer.valueOf(0x4d800));
+ symbols.put("keyword_is_6510mnemo",Integer.valueOf(0x23000));
+ symbols.put("chown",Integer.valueOf(0x4b800));
+ symbols.put("send",Integer.valueOf(0x4fc00));
+ symbols.put("vcpu_check_and_set_reg_length",Integer.valueOf(0x17200));
+ symbols.put("Output_init",Integer.valueOf(0x26e00));
+ symbols.put("chmod",Integer.valueOf(0x4be00));
+ symbols.put("alarm",Integer.valueOf(0x49a64));
+ symbols.put("Parse_optional_block",Integer.valueOf(0x1b600));
+ symbols.put("strtol",Integer.valueOf(0x43600));
+ symbols.put("pipe",Integer.valueOf(0x4aa00));
+ symbols.put("encoding_passinit",Integer.valueOf(0x18e00));
+ symbols.put("uname",Integer.valueOf(0x55400));
+ symbols.put("symbol_parse_definition",Integer.valueOf(0x2fc00));
+ symbols.put("Output_start_segment",Integer.valueOf(0x27a00));
+ symbols.put("accept",Integer.valueOf(0x4ea00));
+ symbols.put("rint",Integer.valueOf(0x38000));
+ symbols.put("basename",Integer.valueOf(0x55200));
+ symbols.put("ALU_optional_defined_int",Integer.valueOf(0x15a00));
+ symbols.put("output_set_output_filename",Integer.valueOf(0x26c00));
+ symbols.put("DynaBuf_get_copy",Integer.valueOf(0x17a00));
+ symbols.put("output_set_output_format",Integer.valueOf(0x26800));
+ symbols.put("strtod",Integer.valueOf(0x68800));
+ symbols.put("Throw_first_pass_warning",Integer.valueOf(0x1ae00));
+ symbols.put("Parse_until_eob_or_eof",Integer.valueOf(0x1a400));
+ symbols.put("sysctl",Integer.valueOf(0x4dc00));
+ symbols.put("fstat",Integer.valueOf(0x62e00));
+ symbols.put("fprintf",Integer.valueOf(0x3bc00));
+ symbols.put("cputype_passinit",Integer.valueOf(0x17400));
+ symbols.put("setpwent",Integer.valueOf(0x54600));
+ symbols.put("bind",Integer.valueOf(0x4f000));
+ symbols.put("inet_addr",Integer.valueOf(0x56200));
+ symbols.put("mkfifo",Integer.valueOf(0x4d400));
+ symbols.put("chdir",Integer.valueOf(0x4a600));
+ symbols.put("Input_read_keyword",Integer.valueOf(0x1ec00));
+ symbols.put("cputype_find",Integer.valueOf(0x17000));
+ symbols.put("initgroups",Integer.valueOf(0x56600));
+ symbols.put("Macro_parse_definition",Integer.valueOf(0x20600));
+ symbols.put("endgrent",Integer.valueOf(0x53e00));
+ symbols.put("setsockopt",Integer.valueOf(0x4ee00));
+ symbols.put("fseek",Integer.valueOf(0x3d400));
+ symbols.put("cos",Integer.valueOf(0x32800));
+ symbols.put("memchr",Integer.valueOf(0x5b400));
+ symbols.put("output_le16",Integer.valueOf(0x26000));
+ symbols.put("umask",Integer.valueOf(0x49694));
+ symbols.put("symbol_set_value",Integer.valueOf(0x2f600));
+ symbols.put("symbol_find",Integer.valueOf(0x2f400));
+ symbols.put("lstat",Integer.valueOf(0x4c200));
+ symbols.put("sin",Integer.valueOf(0x32c00));
+ symbols.put("setgid",Integer.valueOf(0x50a00));
+ symbols.put("signal",Integer.valueOf(0x5ea00));
+ symbols.put("output_8",Integer.valueOf(0x25e00));
+ symbols.put("strncmp",Integer.valueOf(0x43000));
+ symbols.put("DynaBuf_create",Integer.valueOf(0x17600));
+ symbols.put("pow",Integer.valueOf(0x33400));
+ symbols.put("keyword_is_6502mnemo",Integer.valueOf(0x22600));
+ symbols.put("strncpy",Integer.valueOf(0x5f400));
+ symbols.put("DynaBuf_add_string",Integer.valueOf(0x17e00));
+ symbols.put("Input_read_filename",Integer.valueOf(0x1fc00));
+ symbols.put("sync",Integer.valueOf(0x51e00));
+ symbols.put("ALU_int_result",Integer.valueOf(0x15c00));
+ symbols.put("sendto",Integer.valueOf(0x4f600));
+ symbols.put("realloc",Integer.valueOf(0x40600));
+ symbols.put("vcpu_get_statement_size",Integer.valueOf(0x28200));
+ symbols.put("Section_passinit",Integer.valueOf(0x2e800));
+ symbols.put("listen",Integer.valueOf(0x4f200));
+ symbols.put("fork",Integer.valueOf(0x62c00));
+ symbols.put("sscanf",Integer.valueOf(0x5f000));
+ symbols.put("getgrent",Integer.valueOf(0x53a00));
+ symbols.put("sigaction",Integer.valueOf(0x52200));
+ symbols.put("fread",Integer.valueOf(0x3c600));
+ symbols.put("inet_aton",Integer.valueOf(0x55e00));
+ symbols.put("Input_read_and_lower_keyword",Integer.valueOf(0x1f400));
+ symbols.put("symlink",Integer.valueOf(0x4b400));
+ symbols.put("encoding_find",Integer.valueOf(0x19200));
+ symbols.put("Tree_add_table",Integer.valueOf(0x30e00));
+ symbols.put("DynaBuf_init",Integer.valueOf(0x18200));
+ symbols.put("fopen",Integer.valueOf(0x3b800));
+ symbols.put("memset",Integer.valueOf(0x48fec));
+ symbols.put("main",Integer.valueOf(0x11c00));
+ symbols.put("typesystem_want_addr",Integer.valueOf(0x32200));
+ symbols.put("Output_end_segment",Integer.valueOf(0x27800));
+ symbols.put("Output_fake",Integer.valueOf(0x25c00));
+ symbols.put("add_node_to_tree",Integer.valueOf(0x30c00));
+ symbols.put("pseudoopcodes_init",Integer.valueOf(0x2e000));
+ symbols.put("DynaBuf_append",Integer.valueOf(0x17c00));
+ symbols.put("matherr",Integer.valueOf(0x37c00));
+ symbols.put("fclose",Integer.valueOf(0x39200));
+ symbols.put("inet_ntoa",Integer.valueOf(0x52a00));
+ symbols.put("getppid",Integer.valueOf(0x491bc));
+ symbols.put("opendir",Integer.valueOf(0x52400));
+ symbols.put("getgroups",Integer.valueOf(0x50000));
+ symbols.put("keyword_is_c64dtv2mnemo",Integer.valueOf(0x23a00));
+ symbols.put("getgrouplist",Integer.valueOf(0x56400));
+ symbols.put("seteuid",Integer.valueOf(0x50800));
+ symbols.put("keyword_is_65c02mnemo",Integer.valueOf(0x24400));
+ symbols.put("putc",Integer.valueOf(0x40000));
+ symbols.put("output_initmem",Integer.valueOf(0x26600));
+ symbols.put("finite",Integer.valueOf(0x37400));
+ symbols.put("herror",Integer.valueOf(0x53000));
+ symbols.put("strcmp",Integer.valueOf(0x42c00));
+ symbols.put("flow_forloop",Integer.valueOf(0x19400));
+ symbols.put("shutdown",Integer.valueOf(0x4f400));
+ symbols.put("tan",Integer.valueOf(0x32e00));
+ symbols.put("ttyname",Integer.valueOf(0x52000));
+ symbols.put("vfiprintf",Integer.valueOf(0x64a00));
+ symbols.put("getpwuid",Integer.valueOf(0x54200));
+ symbols.put("Input_read_zone_and_keyword",Integer.valueOf(0x1e400));
+ symbols.put("dup",Integer.valueOf(0x4c600));
+ symbols.put("copysign",Integer.valueOf(0x38800));
+ symbols.put("getcwd",Integer.valueOf(0x4b000));
+ symbols.put("Section_new_zone",Integer.valueOf(0x2e400));
+ symbols.put("encoding_load",Integer.valueOf(0x19000));
+ symbols.put("gethostbyname",Integer.valueOf(0x53400));
+ symbols.put("getpwnam",Integer.valueOf(0x54000));
+ symbols.put("getservbyname",Integer.valueOf(0x52c00));
+ symbols.put("atan",Integer.valueOf(0x32400));
+ symbols.put("gethostname",Integer.valueOf(0x55a00));
+ symbols.put("sprintf",Integer.valueOf(0x42000));
+ symbols.put("pseudoopcode_parse",Integer.valueOf(0x2e200));
+ symbols.put("Tree_hard_scan",Integer.valueOf(0x31200));
+ symbols.put("strtof",Integer.valueOf(0x68a00));
+ symbols.put("atexit",Integer.valueOf(0x38a00));
+ symbols.put("cliargs_get_next",Integer.valueOf(0x16600));
+ symbols.put("output_le32",Integer.valueOf(0x26400));
+ symbols.put("asin",Integer.valueOf(0x33200));
+ symbols.put("setlocale",Integer.valueOf(0x5b000));
+ symbols.put("getpeername",Integer.valueOf(0x50400));
+ symbols.put("Throw_serious_error",Integer.valueOf(0x1b200));
+ symbols.put("nanf",Integer.valueOf(0x66a00));
+ symbols.put("cliargs_init",Integer.valueOf(0x16c00));
+ symbols.put("scalbn",Integer.valueOf(0x38400));
+ symbols.put("vfork",Integer.valueOf(0x4ca00));
+ symbols.put("ALU_liberal_int",Integer.valueOf(0x16200));
+ symbols.put("symbols_vicelabels",Integer.valueOf(0x30600));
+ symbols.put("fsync",Integer.valueOf(0x51200));
+ symbols.put("Mnemo_init",Integer.valueOf(0x22400));
+ symbols.put("fputc",Integer.valueOf(0x3c000));
+ symbols.put("symbol_set_label",Integer.valueOf(0x2f800));
+ symbols.put("DynaBuf_enlarge",Integer.valueOf(0x17800));
+ symbols.put("getsockopt",Integer.valueOf(0x4ec00));
+ symbols.put("typesystem_force_address_block",Integer.valueOf(0x31c00));
+ symbols.put("hstrerror",Integer.valueOf(0x52e00));
+ symbols.put("vcpu_end_statement",Integer.valueOf(0x28400));
+ symbols.put("nan",Integer.valueOf(0x37e00));
+ symbols.put("Macro_parse_call",Integer.valueOf(0x20a00));
+ symbols.put("encoding_encode_char",Integer.valueOf(0x18c00));
+ symbols.put("Input_new_file",Integer.valueOf(0x1be00));
+ symbols.put("localeconv",Integer.valueOf(0x5b200));
+ symbols.put("Tree_dump_forest",Integer.valueOf(0x31800));
+ symbols.put("Bug_found",Integer.valueOf(0x1b800));
+ symbols.put("Output_save_file",Integer.valueOf(0x27000));
+ symbols.put("fwrite",Integer.valueOf(0x3dc00));
+ symbols.put("vcpu_read_pc",Integer.valueOf(0x28000));
+ symbols.put("access",Integer.valueOf(0x4a000));
+ symbols.put("ALU_any_int",Integer.valueOf(0x15e00));
+ symbols.put("notreallypo_setpc",Integer.valueOf(0x2de00));
+ symbols.put("getdents",Integer.valueOf(0x4c400));
+ symbols.put("Input_accept_comma",Integer.valueOf(0x20000));
+ symbols.put("exit",Integer.valueOf(0x38e00));
+ symbols.put("klogctl",Integer.valueOf(0x4d600));
+ symbols.put("typesystem_says_address",Integer.valueOf(0x31a00));
+ symbols.put("getgrnam",Integer.valueOf(0x53600));
+ symbols.put("make_hash",Integer.valueOf(0x30a00));
+ symbols.put("output_prefer_cbm_file_format",Integer.valueOf(0x26a00));
+ symbols.put("AnyOS_entry",Integer.valueOf(0x28600));
+ symbols.put("Macro_init",Integer.valueOf(0x20400));
+ symbols.put("ALU_init",Integer.valueOf(0x15800));
+ symbols.put("getpwent",Integer.valueOf(0x54400));
+ symbols.put("daemon",Integer.valueOf(0x55c00));
+ symbols.put("strlen",Integer.valueOf(0x10268));
+ symbols.put("open",Integer.valueOf(0x63000));
+ symbols.put("Input_get_force_bit",Integer.valueOf(0x20200));
+ symbols.put("fputs",Integer.valueOf(0x59a00));
+ symbols.put("setsid",Integer.valueOf(0x51000));
+ symbols.put("setegid",Integer.valueOf(0x50c00));
+ symbols.put("closedir",Integer.valueOf(0x52800));
+ symbols.put("cliargs_handle_options",Integer.valueOf(0x16800));
+ symbols.put("acos",Integer.valueOf(0x33000));
+ symbols.put("output_le24",Integer.valueOf(0x26200));
+ symbols.put("vasprintf",Integer.valueOf(0x54c00));
+ symbols.put("Input_ensure_EOS",Integer.valueOf(0x1ce00));
+ symbols.put("setuid",Integer.valueOf(0x50600));
+ symbols.put("mkdir",Integer.valueOf(0x49e00));
+ symbols.put("ALU_defined_int",Integer.valueOf(0x16000));
+ symbols.put("wcrtomb",Integer.valueOf(0x6ac00));
+ symbols.put("close",Integer.valueOf(0x62a00));
+ symbols.put("symbols_list",Integer.valueOf(0x30400));
+ symbols.put("flow_parse_and_close_file",Integer.valueOf(0x19c00));
+ symbols.put("flow_doloop",Integer.valueOf(0x19800));
+ symbols.put("_call_helper",Integer.valueOf(0x10284));
+ symbols.put("vfprintf",Integer.valueOf(0x48000));
+ symbols.put("fputwc",Integer.valueOf(0x65c00));
+ symbols.put("raise",Integer.valueOf(0x5e800));
+ symbols.put("free",Integer.valueOf(0x3ea00));
+ symbols.put("getsockname",Integer.valueOf(0x50200));
}
public int lookupSymbol(String symbol) { Integer i = (Integer) symbols.get(symbol); return i==null ? -1 : i.intValue(); }
diff --git a/Platform/Apple/tools/jace/src/main/java/jace/assembly/AssemblyHandler.java b/Platform/Apple/tools/jace/src/main/java/jace/assembly/AssemblyHandler.java
index 2846674a..bd62aa60 100644
--- a/Platform/Apple/tools/jace/src/main/java/jace/assembly/AssemblyHandler.java
+++ b/Platform/Apple/tools/jace/src/main/java/jace/assembly/AssemblyHandler.java
@@ -1,16 +1,18 @@
package jace.assembly;
-import jace.Emulator;
-import jace.core.RAM;
-import jace.ide.CompileResult;
-import jace.ide.LanguageHandler;
-import jace.ide.Program;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
+import jace.Emulator;
+import jace.core.RAM;
+import jace.ide.CompileResult;
+import jace.ide.HeadlessProgram;
+import jace.ide.LanguageHandler;
+import jace.ide.Program;
+
/**
*
* @author blurry
@@ -28,24 +30,27 @@ public class AssemblyHandler implements LanguageHandler {
return compiler;
}
- @Override
- public void execute(CompileResult lastResult) {
+ public void compileToRam(String code) {
+ HeadlessProgram prg = new HeadlessProgram(Program.DocumentType.assembly);
+ prg.setValue(code);
+
+ CompileResult lastResult = compile(prg);
if (lastResult.isSuccessful()) {
- RAM memory = Emulator.getComputer().getMemory();
+ Emulator.withComputer(c -> {
+ RAM memory = c.getMemory();
try {
FileInputStream input = new FileInputStream(lastResult.getCompiledAsset());
int startLSB = input.read();
int startMSB = input.read();
int start = startLSB + startMSB << 8;
- System.out.printf("Issuing JSR to $%s%n", Integer.toHexString(start));
- Emulator.getComputer().getCpu().whileSuspended(() -> {
+ System.out.printf("Storing assembled code to $%s%n", Integer.toHexString(start));
+ c.getCpu().whileSuspended(() -> {
try {
int pos = start;
int next;
while ((next=input.read()) != -1) {
memory.write(pos++, (byte) next, false, true);
}
- Emulator.getComputer().getCpu().JSR(start);
} catch (IOException ex) {
Logger.getLogger(AssemblyHandler.class.getName()).log(Level.SEVERE, null, ex);
}
@@ -53,6 +58,37 @@ public class AssemblyHandler implements LanguageHandler {
} catch (IOException ex) {
Logger.getLogger(AssemblyHandler.class.getName()).log(Level.SEVERE, null, ex);
}
+ });
+ }
+ }
+
+ @Override
+ public void execute(CompileResult lastResult) {
+ if (lastResult.isSuccessful()) {
+ Emulator.withComputer(c -> {
+ RAM memory = c.getMemory();
+ try {
+ FileInputStream input = new FileInputStream(lastResult.getCompiledAsset());
+ int startLSB = input.read();
+ int startMSB = input.read();
+ int start = startLSB + startMSB << 8;
+ System.out.printf("Issuing JSR to $%s%n", Integer.toHexString(start));
+ c.getCpu().whileSuspended(() -> {
+ try {
+ int pos = start;
+ int next;
+ while ((next=input.read()) != -1) {
+ memory.write(pos++, (byte) next, false, true);
+ }
+ c.getCpu().JSR(start);
+ } catch (IOException ex) {
+ Logger.getLogger(AssemblyHandler.class.getName()).log(Level.SEVERE, null, ex);
+ }
+ });
+ } catch (IOException ex) {
+ Logger.getLogger(AssemblyHandler.class.getName()).log(Level.SEVERE, null, ex);
+ }
+ });
}
clean(lastResult);
}
diff --git a/Platform/Apple/tools/jace/src/main/java/jace/cheat/MetaCheat.java b/Platform/Apple/tools/jace/src/main/java/jace/cheat/MetaCheat.java
index 49cb600e..cc201efc 100644
--- a/Platform/Apple/tools/jace/src/main/java/jace/cheat/MetaCheat.java
+++ b/Platform/Apple/tools/jace/src/main/java/jace/cheat/MetaCheat.java
@@ -1,26 +1,38 @@
package jace.cheat;
-import jace.Emulator;
-import jace.LawlessLegends;
-import jace.core.*;
-import jace.state.State;
-import jace.ui.MetacheatUI;
-import javafx.application.Platform;
-import javafx.beans.property.*;
-import javafx.beans.value.ObservableValue;
-import javafx.collections.FXCollections;
-import javafx.collections.ObservableList;
-
-import javax.script.Invocable;
-import javax.script.ScriptEngine;
-import javax.script.ScriptEngineManager;
-import java.io.*;
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.logging.Level;
import java.util.logging.Logger;
+import javax.script.Invocable;
+import javax.script.ScriptEngine;
+import javax.script.ScriptEngineManager;
+
+import jace.Emulator;
+import jace.LawlessLegends;
+import jace.core.CPU;
+import jace.core.Computer;
+import jace.core.RAMEvent;
+import jace.core.RAMListener;
+import jace.state.State;
+import jace.ui.MetacheatUI;
+import javafx.application.Platform;
+import javafx.beans.property.BooleanProperty;
+import javafx.beans.property.Property;
+import javafx.beans.property.SimpleBooleanProperty;
+import javafx.beans.property.SimpleStringProperty;
+import javafx.beans.property.StringProperty;
+import javafx.beans.value.ObservableValue;
+import javafx.collections.FXCollections;
+import javafx.collections.ObservableList;
+
public class MetaCheat extends Cheats {
static final ScriptEngine NASHORN_ENGINE = new ScriptEngineManager().getEngineByName("nashorn");
@@ -219,54 +231,56 @@ public class MetaCheat extends Cheats {
}
public void newSearch() {
- RAM memory = Emulator.getComputer().getMemory();
- resultList.clear();
- int compare = parseInt(searchValueProperty.get());
- for (int i = 0; i < 0x10000; i++) {
- boolean signed = signedProperty.get();
- int val
- = byteSized
- ? signed ? memory.readRaw(i) : memory.readRaw(i) & 0x0ff
- : signed ? memory.readWordRaw(i) : memory.readWordRaw(i) & 0x0ffff;
- if (!searchType.equals(SearchType.VALUE) || val == compare) {
- SearchResult result = new SearchResult(i, val);
- resultList.add(result);
+ Emulator.withMemory(memory -> {
+ resultList.clear();
+ int compare = parseInt(searchValueProperty.get());
+ for (int i = 0; i < 0x10000; i++) {
+ boolean signed = signedProperty.get();
+ int val
+ = byteSized
+ ? signed ? memory.readRaw(i) : memory.readRaw(i) & 0x0ff
+ : signed ? memory.readWordRaw(i) : memory.readWordRaw(i) & 0x0ffff;
+ if (!searchType.equals(SearchType.VALUE) || val == compare) {
+ SearchResult result = new SearchResult(i, val);
+ resultList.add(result);
+ }
}
- }
+ });
}
public void performSearch() {
- RAM memory = Emulator.getComputer().getMemory();
- boolean signed = signedProperty.get();
- resultList.removeIf((SearchResult result) -> {
- int val = byteSized
- ? signed ? memory.readRaw(result.address) : memory.readRaw(result.address) & 0x0ff
- : signed ? memory.readWordRaw(result.address) : memory.readWordRaw(result.address) & 0x0ffff;
- int last = result.lastObservedValue;
- result.lastObservedValue = val;
- switch (searchType) {
- case VALUE:
- int compare = parseInt(searchValueProperty.get());
- return compare != val;
- case CHANGE:
- switch (searchChangeType) {
- case AMOUNT:
- int amount = parseInt(searchChangeByProperty().getValue());
- return (val - last) != amount;
- case GREATER:
- return val <= last;
- case ANY_CHANGE:
- return val == last;
- case LESS:
- return val >= last;
- case NO_CHANGE:
- return val != last;
- }
- break;
- case TEXT:
- break;
- }
- return false;
+ Emulator.withMemory(memory -> {
+ boolean signed = signedProperty.get();
+ resultList.removeIf((SearchResult result) -> {
+ int val = byteSized
+ ? signed ? memory.readRaw(result.address) : memory.readRaw(result.address) & 0x0ff
+ : signed ? memory.readWordRaw(result.address) : memory.readWordRaw(result.address) & 0x0ffff;
+ int last = result.lastObservedValue;
+ result.lastObservedValue = val;
+ switch (searchType) {
+ case VALUE:
+ int compare = parseInt(searchValueProperty.get());
+ return compare != val;
+ case CHANGE:
+ switch (searchChangeType) {
+ case AMOUNT:
+ int amount = parseInt(searchChangeByProperty().getValue());
+ return (val - last) != amount;
+ case GREATER:
+ return val <= last;
+ case ANY_CHANGE:
+ return val == last;
+ case LESS:
+ return val >= last;
+ case NO_CHANGE:
+ return val != last;
+ }
+ break;
+ case TEXT:
+ break;
+ }
+ return false;
+ });
});
}
@@ -278,23 +292,24 @@ public class MetaCheat extends Cheats {
}
public void initMemoryView() {
- RAM memory = Emulator.getComputer().getMemory();
- for (int addr = getStartAddress(); addr <= getEndAddress(); addr++) {
- if (getMemoryCell(addr) == null) {
- MemoryCell cell = new MemoryCell();
- cell.address = addr;
- cell.value.set(memory.readRaw(addr));
- memoryCells.put(addr, cell);
+ Emulator.withMemory(memory -> {
+ for (int addr = getStartAddress(); addr <= getEndAddress(); addr++) {
+ if (getMemoryCell(addr) == null) {
+ MemoryCell cell = new MemoryCell();
+ cell.address = addr;
+ cell.value.set(memory.readRaw(addr));
+ memoryCells.put(addr, cell);
+ }
}
- }
- if (memoryViewListener == null) {
- memoryViewListener = memory.observe(RAMEvent.TYPE.ANY, startAddress, endAddress, this::processMemoryEvent);
- listeners.add(memoryViewListener);
- }
+ if (memoryViewListener == null) {
+ memoryViewListener = memory.observe(RAMEvent.TYPE.ANY, startAddress, endAddress, this::processMemoryEvent);
+ listeners.add(memoryViewListener);
+ }
+ });
}
int fadeCounter = 0;
- int FADE_TIMER_VALUE = (int) (Emulator.getComputer().getMotherboard().getSpeedInHz() / 60);
+ int FADE_TIMER_VALUE = Emulator.withComputer(c-> (int) (c.getMotherboard().getSpeedInHz() / 60), 100);
@Override
public void tick() {
@@ -328,107 +343,90 @@ public class MetaCheat extends Cheats {
private void processMemoryEvent(RAMEvent e) {
MemoryCell cell = getMemoryCell(e.getAddress());
if (cell != null) {
- CPU cpu = Emulator.getComputer().getCpu();
- int pc = cpu.getProgramCounter();
- String trace = cpu.getLastTrace();
- switch (e.getType()) {
- case EXECUTE:
- cell.execInstructionsDisassembly.add(trace);
- if (cell.execInstructionsDisassembly.size() > historyLength) {
- cell.execInstructionsDisassembly.remove(0);
- }
- case READ_OPERAND:
- cell.execCount.set(Math.min(255, cell.execCount.get() + lightRate));
- break;
- case WRITE:
- cell.writeCount.set(Math.min(255, cell.writeCount.get() + lightRate));
- if (ui.isInspecting(cell.address)) {
- if (pendingInspectorUpdates.incrementAndGet() < 5) {
- Platform.runLater(() -> {
- pendingInspectorUpdates.decrementAndGet();
- cell.writeInstructions.add(pc);
- cell.writeInstructionsDisassembly.add(trace);
- if (cell.writeInstructions.size() > historyLength) {
- cell.writeInstructions.remove(0);
- cell.writeInstructionsDisassembly.remove(0);
- }
- });
+ Emulator.withComputer(c -> {
+ CPU cpu = c.getCpu();
+ int pc = cpu.getProgramCounter();
+ String trace = cpu.getLastTrace();
+ switch (e.getType()) {
+ case EXECUTE:
+ cell.execInstructionsDisassembly.add(trace);
+ if (cell.execInstructionsDisassembly.size() > historyLength) {
+ cell.execInstructionsDisassembly.remove(0);
}
- } else {
- cell.writeInstructions.add(cpu.getProgramCounter());
- cell.writeInstructionsDisassembly.add(cpu.getLastTrace());
- if (cell.writeInstructions.size() > historyLength) {
- cell.writeInstructions.remove(0);
- cell.writeInstructionsDisassembly.remove(0);
+ case READ_OPERAND:
+ cell.execCount.set(Math.min(255, cell.execCount.get() + lightRate));
+ break;
+ case WRITE:
+ cell.writeCount.set(Math.min(255, cell.writeCount.get() + lightRate));
+ if (ui.isInspecting(cell.address)) {
+ if (pendingInspectorUpdates.incrementAndGet() < 5) {
+ Platform.runLater(() -> {
+ pendingInspectorUpdates.decrementAndGet();
+ cell.writeInstructions.add(pc);
+ cell.writeInstructionsDisassembly.add(trace);
+ if (cell.writeInstructions.size() > historyLength) {
+ cell.writeInstructions.remove(0);
+ cell.writeInstructionsDisassembly.remove(0);
+ }
+ });
+ }
+ } else {
+ cell.writeInstructions.add(cpu.getProgramCounter());
+ cell.writeInstructionsDisassembly.add(cpu.getLastTrace());
+ if (cell.writeInstructions.size() > historyLength) {
+ cell.writeInstructions.remove(0);
+ cell.writeInstructionsDisassembly.remove(0);
+ }
}
- }
- break;
- default:
- cell.readCount.set(Math.min(255, cell.readCount.get() + lightRate));
- if (ui.isInspecting(cell.address)) {
- if (pendingInspectorUpdates.incrementAndGet() < 5) {
- Platform.runLater(() -> {
- pendingInspectorUpdates.decrementAndGet();
- cell.readInstructions.add(pc);
- cell.readInstructionsDisassembly.add(trace);
- if (cell.readInstructions.size() > historyLength) {
- cell.readInstructions.remove(0);
- cell.readInstructionsDisassembly.remove(0);
- }
- });
+ break;
+ default:
+ cell.readCount.set(Math.min(255, cell.readCount.get() + lightRate));
+ if (ui.isInspecting(cell.address)) {
+ if (pendingInspectorUpdates.incrementAndGet() < 5) {
+ Platform.runLater(() -> {
+ pendingInspectorUpdates.decrementAndGet();
+ cell.readInstructions.add(pc);
+ cell.readInstructionsDisassembly.add(trace);
+ if (cell.readInstructions.size() > historyLength) {
+ cell.readInstructions.remove(0);
+ cell.readInstructionsDisassembly.remove(0);
+ }
+ });
+ }
+ } else {
+ cell.readInstructions.add(cpu.getProgramCounter());
+ cell.readInstructionsDisassembly.add(cpu.getLastTrace());
+ if (cell.readInstructions.size() > historyLength) {
+ cell.readInstructions.remove(0);
+ cell.readInstructionsDisassembly.remove(0);
+ }
}
- } else {
- cell.readInstructions.add(cpu.getProgramCounter());
- cell.readInstructionsDisassembly.add(cpu.getLastTrace());
- if (cell.readInstructions.size() > historyLength) {
- cell.readInstructions.remove(0);
- cell.readInstructionsDisassembly.remove(0);
- }
- }
- }
- cell.value.set(e.getNewValue());
+ }
+ cell.value.set(e.getNewValue());
+ });
}
}
public void saveCheats(File saveFile) {
- FileWriter writer = null;
- try {
- writer = new FileWriter(saveFile);
+ try (FileWriter writer = new FileWriter(saveFile)) {
for (DynamicCheat cheat : cheatList) {
writer.write(cheat.serialize());
writer.write("\n");
}
- writer.close();
} catch (IOException ex) {
Logger.getLogger(MetaCheat.class.getName()).log(Level.SEVERE, null, ex);
- } finally {
- try {
- writer.close();
- } catch (IOException ex) {
- Logger.getLogger(MetaCheat.class.getName()).log(Level.SEVERE, null, ex);
- }
}
}
public void loadCheats(File saveFile) {
- BufferedReader in = null;
- try {
- in = new BufferedReader(new FileReader(saveFile));
- StringBuilder guts = new StringBuilder();
+ try (BufferedReader in = new BufferedReader(new FileReader(saveFile))) {
String line;
while ((line = in.readLine()) != null) {
DynamicCheat cheat = DynamicCheat.deserialize(line);
addCheat(cheat);
}
- in.close();
} catch (IOException ex) {
Logger.getLogger(MetaCheat.class.getName()).log(Level.SEVERE, null, ex);
- } finally {
- try {
- in.close();
- } catch (IOException ex) {
- Logger.getLogger(MetaCheat.class.getName()).log(Level.SEVERE, null, ex);
- }
}
}
}
diff --git a/Platform/Apple/tools/jace/src/main/java/jace/cheat/MontezumasRevengeCheats.java b/Platform/Apple/tools/jace/src/main/java/jace/cheat/MontezumasRevengeCheats.java
index 76f194b1..b30e4d5e 100644
--- a/Platform/Apple/tools/jace/src/main/java/jace/cheat/MontezumasRevengeCheats.java
+++ b/Platform/Apple/tools/jace/src/main/java/jace/cheat/MontezumasRevengeCheats.java
@@ -4,7 +4,6 @@ import jace.Emulator;
import jace.EmulatorUILogic;
import jace.config.ConfigurableField;
import jace.core.Computer;
-import jace.core.RAM;
import jace.core.RAMEvent;
import javafx.event.EventHandler;
import javafx.scene.Node;
@@ -71,7 +70,6 @@ public class MontezumasRevengeCheats extends Cheats {
@Override
public void registerListeners() {
- RAM memory = Emulator.getComputer().memory;
if (repulsiveHack) {
addCheat(RAMEvent.TYPE.WRITE, this::repulsiveBehavior, 0x1508, 0x1518);
}
@@ -91,22 +89,24 @@ public class MontezumasRevengeCheats extends Cheats {
}
if (safePassage) {
- //blank out pattern for floors/doors
- for (int addr = 0x0b54; addr <= 0xb5f; addr++) {
- memory.write(addr, (byte) 0, false, false);
- memory.write(addr + 0x0400, (byte) 0, false, false);
- }
- memory.write(0x0b50, (byte) 0b11010111, false, false);
- memory.write(0x0b51, (byte) 0b00010000, false, false);
- memory.write(0x0b52, (byte) 0b10001000, false, false);
- memory.write(0x0b53, (byte) 0b10101010, false, false);
- memory.write(0x0f50, (byte) 0b10101110, false, false);
- memory.write(0x0f51, (byte) 0b00001000, false, false);
- memory.write(0x0f52, (byte) 0b10000100, false, false);
- memory.write(0x0f53, (byte) 0b11010101, false, false);
- forceValue(32, FLOOR_TIMER);
- forceValue(32, HAZARD_TIMER);
- forceValue(1, HAZARD_FLAG);
+ Emulator.withMemory(memory -> {
+ //blank out pattern for floors/doors
+ for (int addr = 0x0b54; addr <= 0xb5f; addr++) {
+ memory.write(addr, (byte) 0, false, false);
+ memory.write(addr + 0x0400, (byte) 0, false, false);
+ }
+ memory.write(0x0b50, (byte) 0b11010111, false, false);
+ memory.write(0x0b51, (byte) 0b00010000, false, false);
+ memory.write(0x0b52, (byte) 0b10001000, false, false);
+ memory.write(0x0b53, (byte) 0b10101010, false, false);
+ memory.write(0x0f50, (byte) 0b10101110, false, false);
+ memory.write(0x0f51, (byte) 0b00001000, false, false);
+ memory.write(0x0f52, (byte) 0b10000100, false, false);
+ memory.write(0x0f53, (byte) 0b11010101, false, false);
+ forceValue(32, FLOOR_TIMER);
+ forceValue(32, HAZARD_TIMER);
+ forceValue(1, HAZARD_FLAG);
+ });
}
if (scoreHack) {
@@ -198,7 +198,7 @@ public class MontezumasRevengeCheats extends Cheats {
private void mouseClicked(MouseButton button) {
byte newX = (byte) (mouseX * X_MAX);
byte newY = (byte) (mouseY * Y_MAX);
- computer.memory.write(PLAYER_X, newX, false, false);
- computer.memory.write(PLAYER_Y, newY, false, false);
+ computer.getMemory().write(PLAYER_X, newX, false, false);
+ computer.getMemory().write(PLAYER_Y, newY, false, false);
}
}
\ No newline at end of file
diff --git a/Platform/Apple/tools/jace/src/main/java/jace/config/Configuration.java b/Platform/Apple/tools/jace/src/main/java/jace/config/Configuration.java
index fdbbc5b3..aa974ebc 100644
--- a/Platform/Apple/tools/jace/src/main/java/jace/config/Configuration.java
+++ b/Platform/Apple/tools/jace/src/main/java/jace/config/Configuration.java
@@ -18,6 +18,35 @@
*/
package jace.config;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InvalidClassException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.ObjectStreamException;
+import java.io.Serializable;
+import java.lang.reflect.Field;
+import java.lang.reflect.GenericArrayType;
+import java.lang.reflect.Method;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import java.util.stream.Stream;
+
import jace.Emulator;
import jace.EmulatorUILogic;
import jace.core.Computer;
@@ -27,13 +56,6 @@ import javafx.collections.ObservableList;
import javafx.scene.control.TreeItem;
import javafx.scene.image.ImageView;
-import java.io.*;
-import java.lang.reflect.*;
-import java.util.*;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-import java.util.stream.Stream;
-
/**
* Manages the configuration state of the emulator components.
*
@@ -104,7 +126,7 @@ public class Configuration implements Reconfigurable {
public transient ConfigNode root;
public transient ConfigNode parent;
- private transient final ObservableList children;
+ private transient ObservableList children;
public transient Reconfigurable subject;
private transient boolean changed = true;
@@ -124,6 +146,9 @@ public class Configuration implements Reconfigurable {
private void readObject(java.io.ObjectInputStream in)
throws IOException, ClassNotFoundException {
+ if (children == null) {
+ children = getChildren();
+ }
children.setAll(super.getChildren());
id = (String) in.readObject();
name = (String) in.readObject();
@@ -254,13 +279,18 @@ public class Configuration implements Reconfigurable {
}
public static ConfigNode BASE;
public static EmulatorUILogic ui = Emulator.logic;
- public static Computer emulator = Emulator.getComputer();
@ConfigurableField(name = "Autosave Changes", description = "If unchecked, changes are only saved when the Save button is pressed.")
public static boolean saveAutomatically = false;
public static void buildTree() {
BASE = new ConfigNode(new Configuration());
- buildTree(BASE, new LinkedHashSet());
+ Set visited = new LinkedHashSet();
+ buildTree(BASE, visited);
+ Emulator.withComputer(c->{
+ ConfigNode computer = new ConfigNode(BASE, c);
+ BASE.putChild(c.getName(), computer);
+ buildTree(computer, visited);
+ });
}
private static void buildTree(ConfigNode node, Set visited) {
@@ -299,8 +329,7 @@ public class Configuration implements Reconfigurable {
continue;
}
- if (o instanceof Reconfigurable) {
- Reconfigurable r = (Reconfigurable) o;
+ if (o instanceof Reconfigurable r) {
ConfigNode child = node.findChild(r.getName());
if (child == null || !child.subject.equals(o)) {
child = new ConfigNode(node, r);
@@ -317,8 +346,7 @@ public class Configuration implements Reconfigurable {
if (Optional.class.isAssignableFrom(type)) {
Type genericTypes = f.getGenericType();
// System.out.println("Looking at generic parmeters " + genericTypes.getTypeName() + " for reconfigurable class, type " + genericTypes.getClass().getName());
- if (genericTypes instanceof GenericArrayType) {
- GenericArrayType aType = (GenericArrayType) genericTypes;
+ if (genericTypes instanceof GenericArrayType aType) {
ParameterizedType pType = (ParameterizedType) aType.getGenericComponentType();
if (pType.getActualTypeArguments().length != 1) {
continue;
@@ -450,7 +478,7 @@ public class Configuration implements Reconfigurable {
public static boolean applySettings(ConfigNode node) {
boolean resume = false;
if (node == BASE) {
- resume = Emulator.getComputer().pause();
+ resume = Emulator.withComputer(c->c.pause(), false);
}
boolean hasChanged = false;
if (node.changed) {
@@ -469,7 +497,7 @@ public class Configuration implements Reconfigurable {
}
if (resume) {
- Emulator.getComputer().resume();
+ Emulator.withComputer(Computer::resume);
}
return hasChanged;
diff --git a/Platform/Apple/tools/jace/src/main/java/jace/config/InvokableAction.java b/Platform/Apple/tools/jace/src/main/java/jace/config/InvokableAction.java
index 739dcca1..16dce814 100644
--- a/Platform/Apple/tools/jace/src/main/java/jace/config/InvokableAction.java
+++ b/Platform/Apple/tools/jace/src/main/java/jace/config/InvokableAction.java
@@ -26,19 +26,19 @@ import java.lang.annotation.Target;
/**
* A invokable action annotation means that an object method can be called by the end-user.
* This serves as a hook for keybindings as well as semantic navigation potential.
- *
+ *
* Name should be short, meaningful, and succinct. e.g. "Insert disk"
- *
+ *
* Category can be used to group actions by overall topic, for example an automated table of contents
- *
+ *
* Description is descriptive text which provides additional clarity, e.g.
* "This will present you with a file selection dialog to pick a floppy disk image.
* Currently, dos-ordered (DSK, DO), Prodos-ordered (PO), and Nibble (NIB) formats are supported.
- *
+ *
* Alternatives should be delimited by semicolons) can provide more powerful search
* For "insert disk", alternatives might be "change disk;switch disk" and
* reboot might have alternatives as "warm start;cold start;boot;restart".
- *
+ *
* NOTE: Any method that implements this must be public and take no parameters!
* If a method signature is not correct, it will result in a runtime exception
* when the action is triggered. There is no way to offer a compiler
diff --git a/Platform/Apple/tools/jace/src/main/java/jace/core/CPU.java b/Platform/Apple/tools/jace/src/main/java/jace/core/CPU.java
index a54c87da..4f0bd7b7 100644
--- a/Platform/Apple/tools/jace/src/main/java/jace/core/CPU.java
+++ b/Platform/Apple/tools/jace/src/main/java/jace/core/CPU.java
@@ -127,11 +127,7 @@ public abstract class CPU extends Device {
// If the debugger is active and we aren't ready for the next step, sleep and exit
// Without the sleep, this would constitute a very rapid-fire loop and would eat
// an unnecessary amount of CPU.
- try {
- Thread.sleep(10);
- } catch (InterruptedException ex) {
- Logger.getLogger(CPU.class.getName()).log(Level.SEVERE, null, ex);
- }
+ Thread.onSpinWait();
return;
}
}
diff --git a/Platform/Apple/tools/jace/src/main/java/jace/core/Computer.java b/Platform/Apple/tools/jace/src/main/java/jace/core/Computer.java
index 7a1b33b1..c32bf0ef 100644
--- a/Platform/Apple/tools/jace/src/main/java/jace/core/Computer.java
+++ b/Platform/Apple/tools/jace/src/main/java/jace/core/Computer.java
@@ -18,15 +18,6 @@
*/
package jace.core;
-import jace.config.ConfigurableField;
-import jace.config.InvokableAction;
-import jace.config.Reconfigurable;
-import jace.lawless.FPSMonitorDevice;
-import jace.state.StateManager;
-import javafx.beans.property.BooleanProperty;
-import javafx.beans.property.SimpleBooleanProperty;
-import javafx.beans.value.ChangeListener;
-
import java.io.IOException;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
@@ -34,6 +25,16 @@ import java.util.concurrent.ExecutionException;
import java.util.logging.Level;
import java.util.logging.Logger;
+import jace.LawlessLegends;
+import jace.apple2e.SoftSwitches;
+import jace.config.ConfigurableField;
+import jace.config.InvokableAction;
+import jace.config.Reconfigurable;
+import jace.state.StateManager;
+import javafx.beans.property.BooleanProperty;
+import javafx.beans.property.SimpleBooleanProperty;
+import javafx.beans.value.ChangeListener;
+
/**
* This is a very generic stub of a Computer and provides a generic set of
* overall functionality, namely boot, pause and resume features. What sort of
@@ -44,9 +45,9 @@ import java.util.logging.Logger;
*/
public abstract class Computer implements Reconfigurable {
- public RAM memory;
+ private RAM memory;
public CPU cpu;
- public Video video;
+ private Video video;
public Keyboard keyboard;
public StateManager stateManager;
public Motherboard motherboard;
@@ -100,12 +101,20 @@ public abstract class Computer implements Reconfigurable {
public void setMemory(RAM memory) {
if (this.memory != memory) {
+ // for (SoftSwitches s : SoftSwitches.values()) {
+ // s.getSwitch().unregister();
+ // }
if (this.memory != null) {
this.memory.detach();
}
- memory.attach();
+ this.memory = memory;
+ if (memory != null) {
+ memory.attach();
+ for (SoftSwitches s : SoftSwitches.values()) {
+ s.getSwitch().register();
+ }
+ }
}
- this.memory = memory;
}
public void waitForNextCycle() {
@@ -118,6 +127,9 @@ public abstract class Computer implements Reconfigurable {
public void setVideo(Video video) {
this.video = video;
+ if (LawlessLegends.getApplication() != null) {
+ LawlessLegends.getApplication().controller.connectVideo(video);
+ }
}
public CPU getCpu() {
@@ -159,6 +171,7 @@ public abstract class Computer implements Reconfigurable {
Thread delayedStart = new Thread(() -> {
try {
romLoaded.get();
+ memory.resetState();
coldStart();
} catch (InterruptedException | ExecutionException ex) {
Logger.getLogger(Computer.class.getName()).log(Level.SEVERE, null, ex);
@@ -166,6 +179,7 @@ public abstract class Computer implements Reconfigurable {
});
delayedStart.start();
} else {
+ memory.resetState();
coldStart();
}
}
diff --git a/Platform/Apple/tools/jace/src/main/java/jace/core/Device.java b/Platform/Apple/tools/jace/src/main/java/jace/core/Device.java
index ea86ecf1..415cb81f 100644
--- a/Platform/Apple/tools/jace/src/main/java/jace/core/Device.java
+++ b/Platform/Apple/tools/jace/src/main/java/jace/core/Device.java
@@ -20,10 +20,9 @@ package jace.core;
import jace.config.Reconfigurable;
import jace.state.Stateful;
-import org.eclipse.collections.api.factory.Sets;
-import org.eclipse.collections.api.set.MutableSet;
-
import java.util.Collection;
+import java.util.Set;
+import java.util.concurrent.CopyOnWriteArraySet;
/**
* Device is a very simple abstraction of any emulation component. A device
@@ -41,11 +40,12 @@ import java.util.Collection;
public abstract class Device implements Reconfigurable {
protected Computer computer;
- private final MutableSet children;
+ private final Set children;
private Device[] childrenArray = new Device[0];
+ private Runnable tickHandler = this::__doTickNotRunning;
private Device() {
- children = Sets.mutable.empty();
+ children = new CopyOnWriteArraySet<>();
}
public Device(Computer computer) {
@@ -59,7 +59,9 @@ public abstract class Device implements Reconfigurable {
@Stateful
private boolean run = false;
@Stateful
- public boolean isPaused = false;
+ // Pausing a device overrides its run state, and is not reset by resuming directly
+ // Therefore a caller pausing a device must unpause it directly!
+ private boolean paused = false;
@Stateful
public boolean isAttached = false;
@@ -68,10 +70,9 @@ public abstract class Device implements Reconfigurable {
return;
}
children.add(d);
- if (isAttached) {
- d.attach();
- }
- childrenArray = children.toArray(new Device[0]);
+ d.attach();
+ childrenArray = children.toArray(Device[]::new);
+ updateTickHandler();
}
public void removeChildDevice(Device d) {
@@ -80,10 +81,9 @@ public abstract class Device implements Reconfigurable {
}
children.remove(d);
d.suspend();
- if (isAttached) {
- d.detach();
- }
- childrenArray = children.toArray(new Device[0]);
+ d.detach();
+ childrenArray = children.toArray(Device[]::new);
+ updateTickHandler();
}
public void addAllDevices(Iterable devices) {
@@ -91,7 +91,7 @@ public abstract class Device implements Reconfigurable {
}
public Iterable getChildren() {
- return children.asUnmodifiable();
+ return children;
}
public void setAllDevices(Collection newDevices) {
@@ -111,28 +111,61 @@ public abstract class Device implements Reconfigurable {
waitCycles = wait;
}
- public void doTick() {
- if (isRunning()) {
- for (Device d : childrenArray) {
- d.doTick();
- }
- if (waitCycles > 0) {
- waitCycles--;
- return;
- }
- tick();
+ private void updateTickHandler() {
+ if (!isRunning() || isPaused()) {
+ tickHandler = this::__doTickNotRunning;
+ } else if (childrenArray.length == 0) {
+ tickHandler = this::__doTickNoDevices;
+ } else {
+ tickHandler = this::__doTickIsRunning;
}
}
+
+ private void __doTickNotRunning() {
+ // Do nothing
+ }
+
+ private void __doTickIsRunning() {
+ for (Device d : childrenArray) {
+ d.doTick();
+ }
+ if (waitCycles <= 0) {
+ tick();
+ return;
+ }
+ waitCycles--;
+ }
+
+ private void __doTickNoDevices() {
+ if (waitCycles <= 0) {
+ tick();
+ return;
+ }
+ waitCycles--;
+ }
+
+ public final void doTick() {
+ tickHandler.run();
+ }
public boolean isRunning() {
return run;
}
-
- public synchronized void setRun(boolean run) {
- isPaused = false;
- this.run = run;
+
+ public boolean isPaused() {
+ return paused;
}
+ public final synchronized void setRun(boolean run) {
+ this.run = run;
+ updateTickHandler();
+ }
+
+ public final synchronized void setPaused(boolean paused) {
+ this.paused = paused;
+ updateTickHandler();
+ }
+
protected abstract String getDeviceName();
@Override
@@ -141,35 +174,25 @@ public abstract class Device implements Reconfigurable {
}
public abstract void tick();
-
- private Runnable buildSuspendedRunnable(Runnable r) {
- Runnable finalProcess = () -> {
- if (isRunning()) {
- suspend();
- r.run();
- resume();
- } else {
- r.run();
- }
- };
- for (Device child : getChildren()) {
- finalProcess = child.buildSuspendedRunnable(finalProcess);
- }
- return finalProcess;
- }
public void whileSuspended(Runnable r) {
- buildSuspendedRunnable(r).run();
+ if (isRunning()) {
+ suspend();
+ r.run();
+ resume();
+ } else {
+ r.run();
+ }
}
public boolean suspend() {
- children.forEach(Device::suspend);
if (isRunning()) {
// System.out.println(getName() + " Suspended");
// Utility.printStackTrace();
setRun(false);
return true;
}
+ children.forEach(Device::suspend);
return false;
}
@@ -189,8 +212,8 @@ public abstract class Device implements Reconfigurable {
}
public void detach() {
- Keyboard.unregisterAllHandlers(this);
children.forEach(Device::suspend);
children.forEach(Device::detach);
+ Keyboard.unregisterAllHandlers(this);
}
}
diff --git a/Platform/Apple/tools/jace/src/main/java/jace/core/Font.java b/Platform/Apple/tools/jace/src/main/java/jace/core/Font.java
index d142fa9b..896c16bd 100644
--- a/Platform/Apple/tools/jace/src/main/java/jace/core/Font.java
+++ b/Platform/Apple/tools/jace/src/main/java/jace/core/Font.java
@@ -45,7 +45,7 @@ public class Font {
initialized = true;
font = new int[256][8];
Thread fontLoader = new Thread(() -> {
- InputStream in = Font.class.getClassLoader().getResourceAsStream("jace/data/font.png");
+ InputStream in = Font.class.getResourceAsStream("/jace/data/font.png");
Image image = new Image(in);
PixelReader reader = image.getPixelReader();
for (int i = 0; i < 256; i++) {
diff --git a/Platform/Apple/tools/jace/src/main/java/jace/core/Keyboard.java b/Platform/Apple/tools/jace/src/main/java/jace/core/Keyboard.java
index 8c1bfdb7..aa8ccbec 100644
--- a/Platform/Apple/tools/jace/src/main/java/jace/core/Keyboard.java
+++ b/Platform/Apple/tools/jace/src/main/java/jace/core/Keyboard.java
@@ -18,15 +18,7 @@
*/
package jace.core;
-import jace.Emulator;
-import jace.apple2e.SoftSwitches;
-import jace.config.InvokableAction;
-import jace.config.Reconfigurable;
-import javafx.event.EventHandler;
-import javafx.scene.input.KeyCode;
-import javafx.scene.input.KeyEvent;
-
-import java.awt.*;
+import java.awt.Toolkit;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.UnsupportedFlavorException;
@@ -42,6 +34,14 @@ import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
+import jace.Emulator;
+import jace.apple2e.SoftSwitches;
+import jace.config.InvokableAction;
+import jace.config.Reconfigurable;
+import javafx.event.EventHandler;
+import javafx.scene.input.KeyCode;
+import javafx.scene.input.KeyEvent;
+
/**
* Keyboard manages all keyboard-related activities. For now, all hotkeys are
* hard-coded. The eventual direction for this class is to only manage key
@@ -104,7 +104,7 @@ public class Keyboard implements Reconfigurable {
registerKeyHandler(new KeyHandler(code) {
@Override
public boolean handleKeyUp(KeyEvent e) {
- Emulator.getComputer().getKeyboard().shiftPressed = e.isShiftDown();
+ Emulator.withComputer(c -> c.getKeyboard().shiftPressed = e.isShiftDown());
if (action == null || !action.notifyOnRelease()) {
return false;
}
@@ -128,7 +128,7 @@ public class Keyboard implements Reconfigurable {
@Override
public boolean handleKeyDown(KeyEvent e) {
// System.out.println("Key down: "+method.toString());
- Emulator.getComputer().getKeyboard().shiftPressed = e.isShiftDown();
+ Emulator.withComputer(c -> c.getKeyboard().shiftPressed = e.isShiftDown());
Object returnValue = null;
try {
if (method.getParameterCount() > 0) {
@@ -251,7 +251,7 @@ public class Keyboard implements Reconfigurable {
default:
}
- Emulator.getComputer().getKeyboard().shiftPressed = e.isShiftDown();
+ Emulator.withComputer(compter -> computer.getKeyboard().shiftPressed = e.isShiftDown());
if (e.isShiftDown()) {
c = fixShiftedChar(c);
}
@@ -311,20 +311,20 @@ public class Keyboard implements Reconfigurable {
@InvokableAction(name = "Open Apple Key", alternatives = "OA", category = "Keyboard", notifyOnRelease = true, defaultKeyMapping = "Alt", consumeKeyEvent = false)
public void openApple(boolean pressed) {
- boolean isRunning = computer.pause();
+ // boolean isRunning = computer.pause();
SoftSwitches.PB0.getSwitch().setState(pressed);
- if (isRunning) {
- computer.resume();
- }
+ // if (isRunning) {
+ // computer.resume();
+ // }
}
@InvokableAction(name = "Closed Apple Key", alternatives = "CA", category = "Keyboard", notifyOnRelease = true, defaultKeyMapping = {"Shortcut","Meta","Command"}, consumeKeyEvent = false)
public void solidApple(boolean pressed) {
- boolean isRunning = computer.pause();
+ // boolean isRunning = computer.pause();
SoftSwitches.PB1.getSwitch().setState(pressed);
- if (isRunning) {
- computer.resume();
- }
+ // if (isRunning) {
+ // computer.resume();
+ // }
}
public static void pasteFromString(String text) {
diff --git a/Platform/Apple/tools/jace/src/main/java/jace/core/Motherboard.java b/Platform/Apple/tools/jace/src/main/java/jace/core/Motherboard.java
index 9b20bcb6..dc087741 100644
--- a/Platform/Apple/tools/jace/src/main/java/jace/core/Motherboard.java
+++ b/Platform/Apple/tools/jace/src/main/java/jace/core/Motherboard.java
@@ -18,12 +18,12 @@
*/
package jace.core;
+import java.util.HashSet;
+
import jace.apple2e.SoftSwitches;
import jace.apple2e.Speaker;
import jace.config.ConfigurableField;
-import java.util.HashSet;
-
/**
* Motherboard is the heart of the computer. It can have a list of cards
* inserted (the behavior and number of cards is determined by the Memory class)
@@ -75,15 +75,18 @@ public class Motherboard extends TimedDevice {
public String getShortName() {
return "mb";
}
- @ConfigurableField(category = "advanced", shortName = "cpuPerClock", name = "CPU per clock", defaultValue = "1", description = "Number of CPU cycles per clock cycle (normal = 1)")
- public static int cpuPerClock = 1;
+ @ConfigurableField(category = "advanced", shortName = "cpuPerClock", name = "CPU per clock", defaultValue = "1", description = "Number of extra CPU cycles per clock cycle (normal = 1)")
+ public static int cpuPerClock = 0;
public int clockCounter = 1;
@Override
public void tick() {
// Extra CPU cycles requested, other devices are called by the TimedDevice abstraction
for (int i=1; i < cpuPerClock; i++) {
- computer.getCpu().doTick();
+ computer.getCpu().doTick();
+ if (Speaker.force1mhz) {
+ speaker.tick();
+ }
}
/*
try {
@@ -106,12 +109,12 @@ public class Motherboard extends TimedDevice {
}
// From the holy word of Sather 3:5 (Table 3.1) :-)
// This average speed averages in the "long" cycles
- public static long SPEED = 1020484L; // (NTSC)
+ public static final long DEFAULT_SPEED = 1020484L; // (NTSC)
//public static long SPEED = 1015625L; // (PAL)
@Override
public long defaultCyclesPerSecond() {
- return SPEED;
+ return DEFAULT_SPEED;
}
@Override
@@ -126,13 +129,10 @@ public class Motherboard extends TimedDevice {
try {
if (speaker == null) {
speaker = new Speaker(computer);
- if (computer.mixer.lineAvailable) {
- speaker.attach();
- } else {
- System.out.print("No lines available! Speaker not running.");
- }
+ speaker.attach();
}
speaker.reconfigure();
+ addChildDevice(speaker);
} catch (Throwable t) {
System.out.println("Unable to initalize sound -- deactivating speaker out");
}
@@ -157,12 +157,14 @@ public class Motherboard extends TimedDevice {
}
void adjustRelativeSpeeds() {
- if (isMaxSpeed()) {
- computer.getVideo().setWaitPerCycle(8);
- } else if (getSpeedInHz() > SPEED) {
- computer.getVideo().setWaitPerCycle(getSpeedInHz()/SPEED);
- } else {
- computer.getVideo().setWaitPerCycle(0);
- }
+ if (computer.getVideo() != null) {
+ if (isMaxSpeed()) {
+ computer.getVideo().setWaitPerCycle(8);
+ } else if (getSpeedInHz() > DEFAULT_SPEED) {
+ computer.getVideo().setWaitPerCycle(getSpeedInHz() / DEFAULT_SPEED);
+ } else {
+ computer.getVideo().setWaitPerCycle(0);
+ }
+ }
}
}
diff --git a/Platform/Apple/tools/jace/src/main/java/jace/core/PagedMemory.java b/Platform/Apple/tools/jace/src/main/java/jace/core/PagedMemory.java
index 5336a7a3..fd0b77d3 100644
--- a/Platform/Apple/tools/jace/src/main/java/jace/core/PagedMemory.java
+++ b/Platform/Apple/tools/jace/src/main/java/jace/core/PagedMemory.java
@@ -18,9 +18,10 @@
*/
package jace.core;
+import java.util.Arrays;
+
import jace.state.StateManager;
import jace.state.Stateful;
-import java.util.Arrays;
/**
* This represents bank-switchable ram which can reside at fixed portions of the
@@ -77,7 +78,7 @@ public class PagedMemory {
loadData(romData);
}
- public void loadData(byte[] romData) {
+ public final void loadData(byte[] romData) {
for (int i = 0; i < romData.length; i += 256) {
byte[] b = new byte[256];
System.arraycopy(romData, i, b, 0, 256);
diff --git a/Platform/Apple/tools/jace/src/main/java/jace/core/RAM.java b/Platform/Apple/tools/jace/src/main/java/jace/core/RAM.java
index f1c1287e..be6dd540 100644
--- a/Platform/Apple/tools/jace/src/main/java/jace/core/RAM.java
+++ b/Platform/Apple/tools/jace/src/main/java/jace/core/RAM.java
@@ -25,6 +25,7 @@ import java.util.Collections;
import java.util.HashSet;
import java.util.Optional;
import java.util.Set;
+import java.util.function.Consumer;
/**
* RAM is a 64K address space of paged memory. It also manages sets of memory
@@ -125,7 +126,7 @@ public abstract class RAM implements Reconfigurable {
public void writeWord(int address, int w, boolean generateEvent, boolean requireSynchronization) {
write(address, (byte) (w & 0x0ff), generateEvent, requireSynchronization);
- write(address + 1, (byte) (w >> 8), generateEvent, requireSynchronization);
+ write(address + 1, (byte) ((w >> 8) & 0x0ff), generateEvent, requireSynchronization);
}
public byte readRaw(int address) {
@@ -137,7 +138,8 @@ public abstract class RAM implements Reconfigurable {
// if (address >= 65536) return 0;
byte value = activeRead.getMemoryPage(address)[address & 0x0FF];
// if (triggerEvent || ((address & 0x0FF00) == 0x0C000)) {
- if (triggerEvent || (address & 0x0FFF0) == 0x0c030) {
+// if (triggerEvent || (address & 0x0FFF0) == 0x0c030) {
+ if (triggerEvent) {
value = callListener(eventType, address, value, value, requireSyncronization);
}
return value;
@@ -165,7 +167,7 @@ public abstract class RAM implements Reconfigurable {
}
ioListeners.add(l);
} else {
- int index = address >> 8;
+ int index = (address >> 8) & 0x0FF;
Set otherListeners = listenerMap[index];
if (otherListeners == null) {
otherListeners = Collections.synchronizedSet(new HashSet<>());
@@ -179,11 +181,12 @@ public abstract class RAM implements Reconfigurable {
if (l.getScope() == RAMEvent.SCOPE.ADDRESS) {
mapListener(l, l.getScopeStart());
} else {
- int start = 0;
- int end = 0x0ffff;
- if (l.getScope() == RAMEvent.SCOPE.RANGE) {
- start = l.getScopeStart();
- end = l.getScopeEnd();
+ int start = l.getScopeStart();
+ int end = l.getScopeEnd();
+ if (l.getScope() == RAMEvent.SCOPE.ANY) {
+ Thread.dumpStack();
+ start = 0;
+ end = 0x0FFFF;
}
for (int i = start; i <= end; i++) {
mapListener(l, i);
@@ -269,17 +272,31 @@ public abstract class RAM implements Reconfigurable {
}
public RAMListener addListener(final RAMListener l) {
- boolean restart = computer.pause();
if (listeners.contains(l)) {
return l;
}
- listeners.add(l);
- addListenerRange(l);
- if (restart) {
- computer.resume();
- }
+ computer.cpu.whileSuspended(()->{
+ listeners.add(l);
+ addListenerRange(l);
+ });
return l;
}
+
+ public RAMListener addExecutionTrap(int address, Consumer handler) {
+ RAMListener listener = new RAMListener(RAMEvent.TYPE.EXECUTE, RAMEvent.SCOPE.ADDRESS, RAMEvent.VALUE.ANY) {
+ @Override
+ protected void doConfig() {
+ setScopeStart(address);
+ }
+
+ @Override
+ protected void doEvent(RAMEvent e) {
+ handler.accept(e);
+ }
+ };
+ addListener(listener);
+ return listener;
+ }
public void removeListener(final RAMListener l) {
boolean restart = computer.pause();
@@ -330,4 +347,6 @@ public abstract class RAM implements Reconfigurable {
abstract public void performExtendedCommand(int i);
abstract public String getState();
+
+ abstract public void resetState();
}
diff --git a/Platform/Apple/tools/jace/src/main/java/jace/core/RAMEvent.java b/Platform/Apple/tools/jace/src/main/java/jace/core/RAMEvent.java
index 1e0d5c50..18aaec5b 100644
--- a/Platform/Apple/tools/jace/src/main/java/jace/core/RAMEvent.java
+++ b/Platform/Apple/tools/jace/src/main/java/jace/core/RAMEvent.java
@@ -39,8 +39,8 @@ public class RAMEvent {
READ(true),
READ_DATA(true),
- EXECUTE(true),
READ_OPERAND(true),
+ EXECUTE(true),
WRITE(false),
ANY(false);
boolean read;
@@ -98,6 +98,9 @@ public class RAMEvent {
}
public final void setType(TYPE type) {
+ if (type == TYPE.ANY) {
+ throw new RuntimeException("Event type=Any is reserved for listeners, not for triggering events!");
+ }
this.type = type;
}
diff --git a/Platform/Apple/tools/jace/src/main/java/jace/core/RAMListener.java b/Platform/Apple/tools/jace/src/main/java/jace/core/RAMListener.java
index c12b1227..c02de2e9 100644
--- a/Platform/Apple/tools/jace/src/main/java/jace/core/RAMListener.java
+++ b/Platform/Apple/tools/jace/src/main/java/jace/core/RAMListener.java
@@ -118,16 +118,6 @@ public abstract class RAMListener implements RAMEvent.RAMEventHandler {
}
public boolean isRelevant(RAMEvent e) {
- // Skip event if it's not the right type
- if (type != TYPE.ANY && type != e.getType()) {
- if (e.getType() != TYPE.ANY && type == TYPE.READ) {
- if (!e.getType().isRead()) {
- return false;
- }
- } else {
- return false;
- }
- }
// Skip event if it's not in the scope we care about
if (scope != RAMEvent.SCOPE.ANY) {
if (scope == RAMEvent.SCOPE.ADDRESS && e.getAddress() != scopeStart) {
@@ -137,6 +127,11 @@ public abstract class RAMListener implements RAMEvent.RAMEventHandler {
}
}
+ // Skip event if it's not the right type
+ if (!(type == TYPE.ANY || type == e.getType() || (type == TYPE.READ && e.getType().isRead()))) {
+ return false;
+ }
+
// Skip event if the value modification is uninteresting
if (value != RAMEvent.VALUE.ANY) {
if (value == RAMEvent.VALUE.CHANGE_BY && e.getNewValue() - e.getOldValue() != valueAmount) {
@@ -154,7 +149,7 @@ public abstract class RAMListener implements RAMEvent.RAMEventHandler {
}
@Override
- public void handleEvent(RAMEvent e) {
+ public final void handleEvent(RAMEvent e) {
if (isRelevant(e)) {
doEvent(e);
}
diff --git a/Platform/Apple/tools/jace/src/main/java/jace/core/SoftSwitch.java b/Platform/Apple/tools/jace/src/main/java/jace/core/SoftSwitch.java
index 8a937197..aba74d74 100644
--- a/Platform/Apple/tools/jace/src/main/java/jace/core/SoftSwitch.java
+++ b/Platform/Apple/tools/jace/src/main/java/jace/core/SoftSwitch.java
@@ -18,11 +18,13 @@
*/
package jace.core;
-import jace.state.Stateful;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import jace.Emulator;
+import jace.state.Stateful;
+
/**
* A softswitch is a hidden bit that lives in the MMU, it can be activated or
* deactivated to change operating characteristics of the computer such as video
@@ -47,7 +49,6 @@ public abstract class SoftSwitch {
private final List exclusionQuery = new ArrayList<>();
private final String name;
private boolean toggleType = false;
- protected Computer computer;
/**
* Creates a new instance of SoftSwitch
@@ -145,7 +146,7 @@ public abstract class SoftSwitch {
@Override
protected void doEvent(RAMEvent e) {
if (e.getType().isRead()) {
- e.setNewValue(computer.getVideo().getFloatingBus());
+ e.setNewValue(Emulator.withComputer(c->c.getVideo().getFloatingBus(), (byte) 0));
}
if (!exclusionActivate.contains(e.getAddress())) {
// System.out.println("Access to "+Integer.toHexString(e.getAddress())+" ENABLES switch "+getName());
@@ -239,16 +240,16 @@ public abstract class SoftSwitch {
}
}
- public void register(Computer computer) {
- this.computer = computer;
- listeners.forEach(computer.getMemory()::addListener);
+ public void register() {
+ Emulator.withMemory(m -> {
+ listeners.forEach(m::addListener);
+ });
}
public void unregister() {
- if (computer != null && computer.getMemory() != null) {
- listeners.forEach(computer.getMemory()::removeListener);
- }
- this.computer = null;
+ Emulator.withMemory(m -> {
+ listeners.forEach(m::removeListener);
+ });
}
public void setState(boolean newState) {
diff --git a/Platform/Apple/tools/jace/src/main/java/jace/core/SoundMixer.java b/Platform/Apple/tools/jace/src/main/java/jace/core/SoundMixer.java
index fe0b5910..25e4c1dd 100644
--- a/Platform/Apple/tools/jace/src/main/java/jace/core/SoundMixer.java
+++ b/Platform/Apple/tools/jace/src/main/java/jace/core/SoundMixer.java
@@ -18,27 +18,17 @@
*/
package jace.core;
-import jace.config.ConfigurableField;
-import jace.config.DynamicSelection;
-import jace.config.Reconfigurable;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.LinkedHashMap;
-import java.util.Map;
-import java.util.Set;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-import java.util.regex.Pattern;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
-import javax.sound.sampled.Line;
import javax.sound.sampled.LineUnavailableException;
-import javax.sound.sampled.Mixer;
-import javax.sound.sampled.Mixer.Info;
import javax.sound.sampled.SourceDataLine;
+import jace.config.ConfigurableField;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import javax.sound.sampled.FloatControl;
+
/**
* Manages sound resources used by various audio devices (such as speaker and
* mockingboard cards.) The plumbing is managed in this class so that the
@@ -50,8 +40,6 @@ import javax.sound.sampled.SourceDataLine;
*/
public class SoundMixer extends Device {
- private final Set availableLines = Collections.synchronizedSet(new HashSet<>());
- private final Map