mirror of
https://github.com/badvision/lawless-legends.git
synced 2024-07-05 01:28:57 +00:00
Removal of legacy "JaceApplication" and added bootup animation which bypasses the coldstart routine.
This commit is contained in:
parent
c98bf87549
commit
76c97b4978
@ -18,8 +18,8 @@
|
||||
*/
|
||||
package jace;
|
||||
|
||||
import jace.apple2e.Apple2e;
|
||||
import jace.config.Configuration;
|
||||
import jace.lawless.LawlessComputer;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@ -39,7 +39,7 @@ public class Emulator {
|
||||
// instance = new Emulator(args);
|
||||
// }
|
||||
|
||||
public static Apple2e computer;
|
||||
public static LawlessComputer computer;
|
||||
|
||||
/**
|
||||
* Creates a new instance of Emulator
|
||||
@ -47,7 +47,7 @@ public class Emulator {
|
||||
*/
|
||||
public Emulator(List<String> args) {
|
||||
instance = this;
|
||||
computer = new Apple2e();
|
||||
computer = new LawlessComputer();
|
||||
Configuration.buildTree();
|
||||
Configuration.loadSettings();
|
||||
mainThread = Thread.currentThread();
|
||||
|
@ -201,7 +201,7 @@ public class EmulatorUILogic implements Reconfigurable {
|
||||
public static void runFile() {
|
||||
Emulator.computer.pause();
|
||||
FileChooser select = new FileChooser();
|
||||
File binary = select.showOpenDialog(JaceApplication.getApplication().primaryStage);
|
||||
File binary = select.showOpenDialog(LawlessLegends.getApplication().primaryStage);
|
||||
if (binary == null) {
|
||||
Emulator.computer.resume();
|
||||
return;
|
||||
@ -266,7 +266,7 @@ public class EmulatorUILogic implements Reconfigurable {
|
||||
defaultKeyMapping = "ctrl+shift+f")
|
||||
public static void toggleFullscreen() {
|
||||
Platform.runLater(() -> {
|
||||
Stage stage = JaceApplication.getApplication().primaryStage;
|
||||
Stage stage = LawlessLegends.getApplication().primaryStage;
|
||||
stage.setFullScreenExitKeyCombination(KeyCombination.NO_MATCH);
|
||||
stage.setFullScreen(!stage.isFullScreen());
|
||||
});
|
||||
@ -324,7 +324,7 @@ public class EmulatorUILogic implements Reconfigurable {
|
||||
Emulator.computer.pause();
|
||||
Image i = Emulator.computer.getVideo().getFrameBuffer();
|
||||
// BufferedImage bufImageARGB = SwingFXUtils.fromFXImage(i, null);
|
||||
File targetFile = select.showSaveDialog(JaceApplication.getApplication().primaryStage);
|
||||
File targetFile = select.showSaveDialog(LawlessLegends.getApplication().primaryStage);
|
||||
if (targetFile == null) {
|
||||
return;
|
||||
}
|
||||
@ -396,7 +396,10 @@ public class EmulatorUILogic implements Reconfigurable {
|
||||
defaultKeyMapping = {"ctrl+shift+a"})
|
||||
public static void scaleIntegerRatio() {
|
||||
Platform.runLater(() -> {
|
||||
JaceApplication.getApplication().primaryStage.setFullScreen(false);
|
||||
if (LawlessLegends.getApplication() == null
|
||||
|| LawlessLegends.getApplication().primaryStage == null) {
|
||||
return;
|
||||
}
|
||||
size++;
|
||||
if (size > 3) {
|
||||
size = 0;
|
||||
@ -404,29 +407,29 @@ public class EmulatorUILogic implements Reconfigurable {
|
||||
int width = 0, height = 0;
|
||||
switch (size) {
|
||||
case 0: // 1x
|
||||
width = 560;
|
||||
width = 560;
|
||||
height = 384;
|
||||
break;
|
||||
case 1: // 1.5x
|
||||
width = 840;
|
||||
width = 840;
|
||||
height = 576;
|
||||
break;
|
||||
case 2: // 2x
|
||||
width = 560*2;
|
||||
height = 384*2;
|
||||
width = 560 * 2;
|
||||
height = 384 * 2;
|
||||
break;
|
||||
case 3: // 3x (retina) 2880x1800
|
||||
width = 560*3;
|
||||
height = 384*3;
|
||||
width = 560 * 3;
|
||||
height = 384 * 3;
|
||||
break;
|
||||
default: // 2x
|
||||
width = 560*2;
|
||||
height = 384*2;
|
||||
width = 560 * 2;
|
||||
height = 384 * 2;
|
||||
}
|
||||
Stage stage = JaceApplication.getApplication().primaryStage;
|
||||
Stage stage = LawlessLegends.getApplication().primaryStage;
|
||||
double vgap = stage.getScene().getY();
|
||||
double hgap = stage.getScene().getX();
|
||||
stage.setWidth(hgap*2 + width);
|
||||
stage.setWidth(hgap * 2 + width);
|
||||
stage.setHeight(vgap + height);
|
||||
});
|
||||
}
|
||||
@ -443,7 +446,7 @@ public class EmulatorUILogic implements Reconfigurable {
|
||||
}
|
||||
|
||||
static public void addIndicator(Object owner, Label icon, long TTL) {
|
||||
if (JaceApplication.getApplication() == null) {
|
||||
if (LawlessLegends.getApplication() == null) {
|
||||
return;
|
||||
}
|
||||
synchronized (INDICATORS) {
|
||||
@ -453,12 +456,12 @@ public class EmulatorUILogic implements Reconfigurable {
|
||||
INDICATORS.put(owner, ind);
|
||||
}
|
||||
ind.add(icon);
|
||||
JaceApplication.getApplication().controller.addIndicator(icon);
|
||||
LawlessLegends.getApplication().controller.addIndicator(icon);
|
||||
}
|
||||
}
|
||||
|
||||
static public void removeIndicator(Object owner, Label icon) {
|
||||
if (JaceApplication.singleton == null) {
|
||||
if (LawlessLegends.singleton == null) {
|
||||
return;
|
||||
}
|
||||
synchronized (INDICATORS) {
|
||||
@ -466,12 +469,12 @@ public class EmulatorUILogic implements Reconfigurable {
|
||||
if (ind != null) {
|
||||
ind.remove(icon);
|
||||
}
|
||||
JaceApplication.singleton.controller.removeIndicator(icon);
|
||||
LawlessLegends.singleton.controller.removeIndicator(icon);
|
||||
}
|
||||
}
|
||||
|
||||
static public void removeIndicators(Object owner) {
|
||||
if (JaceApplication.singleton == null) {
|
||||
if (LawlessLegends.singleton == null) {
|
||||
return;
|
||||
}
|
||||
synchronized (INDICATORS) {
|
||||
@ -480,26 +483,26 @@ public class EmulatorUILogic implements Reconfigurable {
|
||||
return;
|
||||
}
|
||||
ind.stream().forEach((icon) -> {
|
||||
JaceApplication.singleton.controller.removeIndicator(icon);
|
||||
LawlessLegends.singleton.controller.removeIndicator(icon);
|
||||
});
|
||||
INDICATORS.remove(owner);
|
||||
}
|
||||
}
|
||||
|
||||
static public void addMouseListener(EventHandler<MouseEvent> handler) {
|
||||
if (JaceApplication.singleton != null) {
|
||||
JaceApplication.singleton.controller.addMouseListener(handler);
|
||||
if (LawlessLegends.singleton != null) {
|
||||
LawlessLegends.singleton.controller.addMouseListener(handler);
|
||||
}
|
||||
}
|
||||
|
||||
static public void removeMouseListener(EventHandler<MouseEvent> handler) {
|
||||
if (JaceApplication.singleton != null) {
|
||||
JaceApplication.singleton.controller.removeMouseListener(handler);
|
||||
if (LawlessLegends.singleton != null) {
|
||||
LawlessLegends.singleton.controller.removeMouseListener(handler);
|
||||
}
|
||||
}
|
||||
|
||||
public static void simulateCtrlAppleReset() {
|
||||
Computer computer = JaceApplication.singleton.controller.computer;
|
||||
Computer computer = LawlessLegends.singleton.controller.computer;
|
||||
computer.keyboard.openApple(true);
|
||||
computer.warmStart();
|
||||
Platform.runLater(() -> {
|
||||
@ -513,8 +516,8 @@ public class EmulatorUILogic implements Reconfigurable {
|
||||
}
|
||||
|
||||
public static void notify(String message) {
|
||||
if (JaceApplication.singleton != null) {
|
||||
JaceApplication.singleton.controller.displayNotification(message);
|
||||
if (LawlessLegends.singleton != null) {
|
||||
LawlessLegends.singleton.controller.displayNotification(message);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,130 +0,0 @@
|
||||
/*
|
||||
* 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 jace.core.RAMEvent;
|
||||
import jace.core.RAMListener;
|
||||
import jace.core.Utility;
|
||||
import jace.ui.MetacheatUI;
|
||||
import java.io.IOException;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import javafx.application.Application;
|
||||
import javafx.application.Platform;
|
||||
import javafx.fxml.FXMLLoader;
|
||||
import javafx.scene.Scene;
|
||||
import javafx.scene.layout.AnchorPane;
|
||||
import javafx.scene.layout.VBox;
|
||||
import javafx.stage.Stage;
|
||||
import javafx.stage.StageStyle;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author blurry
|
||||
*/
|
||||
public class JaceApplication extends Application {
|
||||
|
||||
static JaceApplication singleton;
|
||||
|
||||
public Stage primaryStage;
|
||||
JaceUIController controller;
|
||||
|
||||
static boolean romStarted = false;
|
||||
|
||||
@Override
|
||||
public void start(Stage stage) throws Exception {
|
||||
singleton = this;
|
||||
primaryStage = stage;
|
||||
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("/fxml/JaceUI.fxml"));
|
||||
fxmlLoader.setResources(null);
|
||||
try {
|
||||
AnchorPane node = (AnchorPane) fxmlLoader.load();
|
||||
controller = fxmlLoader.getController();
|
||||
controller.initialize();
|
||||
Scene s = new Scene(node);
|
||||
primaryStage.setScene(s);
|
||||
primaryStage.setTitle("Jace");
|
||||
EmulatorUILogic.scaleIntegerRatio();
|
||||
Utility.loadIcon("woz_figure.gif").ifPresent(primaryStage.getIcons()::add);
|
||||
} catch (IOException exception) {
|
||||
throw new RuntimeException(exception);
|
||||
}
|
||||
|
||||
primaryStage.show();
|
||||
Emulator emulator = new Emulator(getParameters().getRaw());
|
||||
javafx.application.Platform.runLater(() -> {
|
||||
while (Emulator.computer.getVideo() == null || Emulator.computer.getVideo().getFrameBuffer() == null) {
|
||||
Thread.yield();
|
||||
}
|
||||
controller.connectComputer(Emulator.computer, primaryStage);
|
||||
bootWatchdog();
|
||||
});
|
||||
primaryStage.setOnCloseRequest(event -> {
|
||||
Emulator.computer.deactivate();
|
||||
Platform.exit();
|
||||
System.exit(0);
|
||||
});
|
||||
}
|
||||
|
||||
public static JaceApplication getApplication() {
|
||||
return singleton;
|
||||
}
|
||||
|
||||
Stage cheatStage;
|
||||
private MetacheatUI cheatController;
|
||||
|
||||
public MetacheatUI showMetacheat() {
|
||||
if (cheatController == null) {
|
||||
cheatStage = new Stage(StageStyle.DECORATED);
|
||||
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("/fxml/Metacheat.fxml"));
|
||||
fxmlLoader.setResources(null);
|
||||
try {
|
||||
VBox node = fxmlLoader.load();
|
||||
cheatController = fxmlLoader.getController();
|
||||
Scene s = new Scene(node);
|
||||
cheatStage.setScene(s);
|
||||
cheatStage.setTitle("Jace: MetaCheat");
|
||||
Utility.loadIcon("woz_figure.gif").ifPresent(cheatStage.getIcons()::add);
|
||||
} catch (IOException exception) {
|
||||
throw new RuntimeException(exception);
|
||||
}
|
||||
|
||||
}
|
||||
cheatStage.show();
|
||||
return cheatController;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param args the command line arguments
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
launch(args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Start the computer and make sure it runs through the expected rom routine
|
||||
* for cold boot
|
||||
*/
|
||||
private void bootWatchdog() {
|
||||
romStarted = false;
|
||||
RAMListener startListener = Emulator.computer.getMemory().
|
||||
observe(RAMEvent.TYPE.EXECUTE, 0x0FA62, (e) -> {
|
||||
romStarted = true;
|
||||
});
|
||||
Emulator.computer.coldStart();
|
||||
try {
|
||||
Thread.sleep(250);
|
||||
if (!romStarted) {
|
||||
Logger.getLogger(getClass().getName()).log(Level.WARNING, "Boot not detected, performing a cold start");
|
||||
Emulator.computer.coldStart();
|
||||
}
|
||||
} catch (InterruptedException ex) {
|
||||
Logger.getLogger(JaceApplication.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
Emulator.computer.getMemory().removeListener(startListener);
|
||||
}
|
||||
|
||||
}
|
@ -30,6 +30,7 @@ import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import javafx.application.Platform;
|
||||
import javafx.event.EventHandler;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.geometry.Insets;
|
||||
@ -85,14 +86,21 @@ public class JaceUIController {
|
||||
}
|
||||
|
||||
public void connectComputer(Computer computer, Stage primaryStage) {
|
||||
if (computer == null) {
|
||||
return;
|
||||
}
|
||||
this.computer = computer;
|
||||
appleScreen.setImage(computer.getVideo().getFrameBuffer());
|
||||
EventHandler<KeyEvent> keyboardHandler = computer.getKeyboard().getListener();
|
||||
primaryStage.setOnShowing(evt -> computer.getKeyboard().resetState());
|
||||
rootPane.setFocusTraversable(true);
|
||||
rootPane.setOnKeyPressed(keyboardHandler);
|
||||
rootPane.setOnKeyReleased(keyboardHandler);
|
||||
rootPane.requestFocus();
|
||||
Platform.runLater(() -> {
|
||||
if (computer.getKeyboard() != null) {
|
||||
EventHandler<KeyEvent> keyboardHandler = computer.getKeyboard().getListener();
|
||||
primaryStage.setOnShowing(evt -> computer.getKeyboard().resetState());
|
||||
rootPane.setOnKeyPressed(keyboardHandler);
|
||||
rootPane.setOnKeyReleased(keyboardHandler);
|
||||
rootPane.setFocusTraversable(true);
|
||||
}
|
||||
appleScreen.setImage(computer.getVideo().getFrameBuffer());
|
||||
rootPane.requestFocus();
|
||||
});
|
||||
}
|
||||
|
||||
private void processDragEnteredEvent(DragEvent evt) {
|
||||
|
@ -48,7 +48,7 @@ public class LawlessLegends extends Application {
|
||||
static LawlessLegends singleton;
|
||||
|
||||
public Stage primaryStage;
|
||||
JaceUIController controller;
|
||||
public JaceUIController controller;
|
||||
|
||||
static boolean romStarted = false;
|
||||
|
||||
@ -65,7 +65,6 @@ public class LawlessLegends extends Application {
|
||||
Scene s = new Scene(node);
|
||||
primaryStage.setScene(s);
|
||||
primaryStage.setTitle("Lawless Legends");
|
||||
EmulatorUILogic.scaleIntegerRatio();
|
||||
Utility.loadIcon("game_icon.png").ifPresent(primaryStage.getIcons()::add);
|
||||
} catch (IOException exception) {
|
||||
throw new RuntimeException(exception);
|
||||
@ -73,20 +72,25 @@ public class LawlessLegends extends Application {
|
||||
|
||||
primaryStage.show();
|
||||
new Emulator(getParameters().getRaw());
|
||||
configureEmulatorForGame();
|
||||
javafx.application.Platform.runLater(() -> {
|
||||
new Thread(() -> {
|
||||
reconnectUIHooks();
|
||||
EmulatorUILogic.scaleIntegerRatio();
|
||||
while (Emulator.computer.getVideo() == null || Emulator.computer.getVideo().getFrameBuffer() == null) {
|
||||
Thread.yield();
|
||||
}
|
||||
controller.connectComputer(Emulator.computer, primaryStage);
|
||||
configureEmulatorForGame();
|
||||
bootWatchdog();
|
||||
});
|
||||
}).start();
|
||||
primaryStage.setOnCloseRequest(event -> {
|
||||
Emulator.computer.deactivate();
|
||||
Platform.exit();
|
||||
System.exit(0);
|
||||
});
|
||||
}
|
||||
|
||||
public void reconnectUIHooks() {
|
||||
controller.connectComputer(Emulator.computer, primaryStage);
|
||||
}
|
||||
|
||||
public static LawlessLegends getApplication() {
|
||||
return singleton;
|
||||
@ -130,12 +134,12 @@ public class LawlessLegends extends Application {
|
||||
private void bootWatchdog() {
|
||||
romStarted = false;
|
||||
RAMListener startListener = Emulator.computer.getMemory().
|
||||
observe(RAMEvent.TYPE.EXECUTE, 0x0FA62, (e) -> {
|
||||
observe(RAMEvent.TYPE.EXECUTE, 0x0c700, (e) -> {
|
||||
romStarted = true;
|
||||
});
|
||||
Emulator.computer.coldStart();
|
||||
try {
|
||||
Thread.sleep(250);
|
||||
Thread.sleep(10000);
|
||||
if (!romStarted) {
|
||||
Logger.getLogger(getClass().getName()).log(Level.WARNING, "Boot not detected, performing a cold start");
|
||||
Emulator.computer.coldStart();
|
||||
@ -172,7 +176,7 @@ public class LawlessLegends extends Application {
|
||||
MediaFile f1 = new MediaEntry.MediaFile();
|
||||
f1.path = getGamePath("game.2mg");
|
||||
|
||||
if (f1.path != null) {
|
||||
if (f1.path != null && f1.path.exists()) {
|
||||
memory.getCard(7).ifPresent(card -> {
|
||||
try {
|
||||
((CardMassStorage) card).currentDrive.insertMedia(e1, f1);
|
||||
@ -189,7 +193,7 @@ public class LawlessLegends extends Application {
|
||||
e2.type = DiskType.FLOPPY140_DO;
|
||||
MediaFile f2 = new MediaEntry.MediaFile();
|
||||
f2.path = getGamePath("utilities.dsk");
|
||||
if (f2.path != null) {
|
||||
if (f2.path != null && f2.path.exists()) {
|
||||
memory.getCard(6).ifPresent(card -> {
|
||||
try {
|
||||
((CardDiskII) card).getConsumers()[0].insertMedia(e2, f2);
|
||||
|
@ -19,6 +19,8 @@
|
||||
package jace.apple2e;
|
||||
|
||||
import jace.Emulator;
|
||||
import jace.LawlessLegends;
|
||||
import jace.apple2e.softswitch.VideoSoftSwitch;
|
||||
import jace.cheat.Cheats;
|
||||
import jace.config.ClassSelection;
|
||||
import jace.config.ConfigurableField;
|
||||
@ -37,6 +39,7 @@ import jace.hardware.ConsoleProbe;
|
||||
import jace.hardware.Joystick;
|
||||
import jace.hardware.NoSlotClock;
|
||||
import jace.hardware.massStorage.CardMassStorage;
|
||||
import jace.lawless.LawlessComputer;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.ArrayList;
|
||||
@ -121,7 +124,7 @@ public class Apple2e extends Computer {
|
||||
return "Computer (Apple //e)";
|
||||
}
|
||||
|
||||
private void reinitMotherboard() {
|
||||
protected void reinitMotherboard() {
|
||||
if (motherboard != null && motherboard.isRunning()) {
|
||||
motherboard.suspend();
|
||||
}
|
||||
@ -158,7 +161,9 @@ public class Apple2e extends Computer {
|
||||
public void warmStart() {
|
||||
boolean restart = pause();
|
||||
for (SoftSwitches s : SoftSwitches.values()) {
|
||||
s.getSwitch().reset();
|
||||
if (! (s.getSwitch() instanceof VideoSoftSwitch)) {
|
||||
s.getSwitch().reset();
|
||||
}
|
||||
}
|
||||
getMemory().configureActiveMemory();
|
||||
getVideo().configureVideoMode();
|
||||
@ -216,9 +221,7 @@ public class Apple2e extends Computer {
|
||||
if (getMemory() == null) {
|
||||
try {
|
||||
currentMemory = (RAM128k) ramCard.getValue().getConstructor(Computer.class).newInstance(this);
|
||||
} catch (InstantiationException | IllegalAccessException | NoSuchMethodException | SecurityException ex) {
|
||||
Logger.getLogger(Apple2e.class.getName()).log(Level.SEVERE, null, ex);
|
||||
} catch (IllegalArgumentException | InvocationTargetException ex) {
|
||||
} catch (InstantiationException | IllegalAccessException | NoSuchMethodException | SecurityException | IllegalArgumentException | InvocationTargetException ex) {
|
||||
Logger.getLogger(Apple2e.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
try {
|
||||
@ -281,6 +284,9 @@ public class Apple2e extends Computer {
|
||||
} else {
|
||||
loadRom("jace/data/apple2e.rom");
|
||||
}
|
||||
RAM128k ram = (RAM128k) getMemory();
|
||||
ram.activeRead.writeByte(0x0fffc, (byte) 0x000);
|
||||
ram.activeRead.writeByte(0x0fffd, (byte) 0x0c7);
|
||||
|
||||
if (getVideo() == null || getVideo().getClass() != videoRenderer.getValue()) {
|
||||
if (getVideo() != null) {
|
||||
@ -291,6 +297,7 @@ public class Apple2e extends Computer {
|
||||
getVideo().configureVideoMode();
|
||||
getVideo().reconfigure();
|
||||
Emulator.resizeVideo();
|
||||
LawlessLegends.getApplication().reconnectUIHooks();
|
||||
getVideo().resume();
|
||||
} catch (InstantiationException | IllegalAccessException ex) {
|
||||
Logger.getLogger(Apple2e.class.getName()).log(Level.SEVERE, null, ex);
|
||||
|
@ -18,7 +18,7 @@
|
||||
*/
|
||||
package jace.apple2e;
|
||||
|
||||
import jace.JaceApplication;
|
||||
import jace.LawlessLegends;
|
||||
import jace.config.ConfigurableField;
|
||||
import jace.core.Computer;
|
||||
import jace.core.Device;
|
||||
@ -60,7 +60,7 @@ public class Speaker extends Device {
|
||||
fileOutputActive = false;
|
||||
} else {
|
||||
FileChooser fileChooser = new FileChooser();
|
||||
File f = fileChooser.showSaveDialog(JaceApplication.getApplication().primaryStage);
|
||||
File f = fileChooser.showSaveDialog(LawlessLegends.getApplication().primaryStage);
|
||||
if (f == null) {
|
||||
return;
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
package jace.cheat;
|
||||
|
||||
import jace.Emulator;
|
||||
import jace.JaceApplication;
|
||||
import jace.LawlessLegends;
|
||||
import jace.core.CPU;
|
||||
import jace.core.Computer;
|
||||
import jace.core.RAM;
|
||||
@ -172,7 +172,7 @@ public class MetaCheat extends Cheats {
|
||||
|
||||
@Override
|
||||
public void attach() {
|
||||
ui = JaceApplication.getApplication().showMetacheat();
|
||||
ui = LawlessLegends.getApplication().showMetacheat();
|
||||
ui.registerMetacheatEngine(this);
|
||||
super.attach();
|
||||
}
|
||||
|
@ -128,10 +128,18 @@ public abstract class Computer implements Reconfigurable {
|
||||
}
|
||||
|
||||
public void deactivate() {
|
||||
cpu.suspend();
|
||||
motherboard.suspend();
|
||||
video.suspend();
|
||||
mixer.detach();
|
||||
if (cpu != null) {
|
||||
cpu.suspend();
|
||||
}
|
||||
if (motherboard != null) {
|
||||
motherboard.suspend();
|
||||
}
|
||||
if (video != null) {
|
||||
video.suspend();
|
||||
}
|
||||
if (mixer != null) {
|
||||
mixer.detach();
|
||||
}
|
||||
}
|
||||
|
||||
@InvokableAction(
|
||||
|
@ -132,13 +132,15 @@ public abstract class Video extends Device {
|
||||
public static int MIN_SCREEN_REFRESH = 15;
|
||||
|
||||
Runnable redrawScreen = () -> {
|
||||
if (computer.getRunningProperty().get()) {
|
||||
visible.getPixelWriter().setPixels(0, 0, 560, 192, video.getPixelReader(), 0, 0);
|
||||
if (visible != null && video != null) {
|
||||
// if (computer.getRunningProperty().get()) {
|
||||
screenDirty = false;
|
||||
visible.getPixelWriter().setPixels(0, 0, 560, 192, video.getPixelReader(), 0, 0);
|
||||
// }
|
||||
}
|
||||
};
|
||||
|
||||
public void redraw() {
|
||||
screenDirty = false;
|
||||
javafx.application.Platform.runLater(redrawScreen);
|
||||
}
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
*/
|
||||
package jace.ide;
|
||||
|
||||
import jace.JaceApplication;
|
||||
import jace.LawlessLegends;
|
||||
import jace.ide.Program.DocumentType;
|
||||
import jace.ide.Program.Option;
|
||||
import java.io.File;
|
||||
@ -163,7 +163,7 @@ public class IdeController {
|
||||
chooser.getExtensionFilters().addAll(
|
||||
new FileChooser.ExtensionFilter("All Files", "*.*")
|
||||
);
|
||||
File file = chooser.showOpenDialog(JaceApplication.getApplication().primaryStage);
|
||||
File file = chooser.showOpenDialog(LawlessLegends.getApplication().primaryStage);
|
||||
if (file != null && file.isFile() && file.exists()) {
|
||||
DocumentType type = DocumentType.fromFile(file);
|
||||
createTab(type, file, true);
|
||||
@ -210,7 +210,7 @@ public class IdeController {
|
||||
new FileChooser.ExtensionFilter(type.name(), type.extensions),
|
||||
new FileChooser.ExtensionFilter("All Files", "*.*")
|
||||
);
|
||||
return chooser.showSaveDialog(JaceApplication.getApplication().primaryStage);
|
||||
return chooser.showSaveDialog(LawlessLegends.getApplication().primaryStage);
|
||||
}
|
||||
|
||||
@FXML
|
||||
|
@ -0,0 +1,163 @@
|
||||
package jace.lawless;
|
||||
|
||||
import jace.apple2e.Apple2e;
|
||||
import jace.apple2e.RAM128k;
|
||||
import jace.apple2e.SoftSwitches;
|
||||
import jace.apple2e.VideoNTSC;
|
||||
import jace.core.Card;
|
||||
import jace.core.Video;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.Semaphore;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* Extends standard implementation to provide different cold start behavior
|
||||
*/
|
||||
public class LawlessComputer extends Apple2e {
|
||||
|
||||
byte[] bootScreen = null;
|
||||
|
||||
@Override
|
||||
public void coldStart() {
|
||||
pause();
|
||||
reinitMotherboard();
|
||||
for (SoftSwitches s : SoftSwitches.values()) {
|
||||
s.getSwitch().reset();
|
||||
}
|
||||
(new Thread(this::startAnimation)).start();
|
||||
}
|
||||
|
||||
public void startAnimation() {
|
||||
doResume();
|
||||
getCpu().suspend();
|
||||
SoftSwitches._80COL.getSwitch().setState(true);
|
||||
SoftSwitches.TEXT.getSwitch().setState(false);
|
||||
SoftSwitches.HIRES.getSwitch().setState(true);
|
||||
SoftSwitches.PAGE2.getSwitch().setState(false);
|
||||
SoftSwitches.DHIRES.getSwitch().setState(true);
|
||||
((VideoNTSC) getVideo()).enableVideo7 = false;
|
||||
getMemory().configureActiveMemory();
|
||||
getVideo().configureVideoMode();
|
||||
|
||||
try {
|
||||
waitForVBL(1);
|
||||
renderWithMask(0x8, 0x11, 0x22, 0x44);
|
||||
Video.forceRefresh();
|
||||
waitForVBL(10);
|
||||
renderWithMask(0x4c, 0x19, 0x33, 0x66);
|
||||
Video.forceRefresh();
|
||||
waitForVBL(10);
|
||||
renderWithMask(0x6e, 0x5d, 0x3B, 0x77);
|
||||
Video.forceRefresh();
|
||||
waitForVBL(10);
|
||||
renderWithMask(0x7f, 0x7f, 0x7f, 0x7f);
|
||||
Video.forceRefresh();
|
||||
waitForVBL(250);
|
||||
renderWithMask(0x6e, 0x5d, 0x3B, 0x77);
|
||||
Video.forceRefresh();
|
||||
waitForVBL(10);
|
||||
renderWithMask(0x4c, 0x19, 0x33, 0x66);
|
||||
Video.forceRefresh();
|
||||
waitForVBL(10);
|
||||
renderWithMask(0x8, 0x11, 0x22, 0x44);
|
||||
Video.forceRefresh();
|
||||
waitForVBL(10);
|
||||
finishColdStart();
|
||||
} catch (InterruptedException ex) {
|
||||
Logger.getLogger(LawlessComputer.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void renderWithMask(int i1, int i2, int i3, int i4) {
|
||||
RAM128k ram = (RAM128k) getMemory();
|
||||
byte[] framebuffer = getBootScreen();
|
||||
for (int i = 0; i < 0x02000; i += 2) {
|
||||
int next = 0;
|
||||
if (i < 0x02000) {
|
||||
next = (framebuffer[i] & 1) << 6;
|
||||
}
|
||||
Byte b1 = (byte) ((framebuffer[i + 0x02000] & 0x07f) >> 1 | next);
|
||||
ram.getAuxMemory().writeByte(0x02000 + i, (byte) (b1 & i1));
|
||||
if (i < 0x01FFF) {
|
||||
next = (framebuffer[i + 0x02001] & 1) << 6;
|
||||
}
|
||||
Byte b2 = (byte) ((framebuffer[i] & 0x07f) >> 1 | next);
|
||||
ram.getMainMemory().writeByte(0x02000 + i, (byte) (b2 & i2));
|
||||
if (i < 0x01FFF) {
|
||||
next = (framebuffer[i + 1] & 1) << 6;
|
||||
}
|
||||
Byte b3 = (byte) ((framebuffer[i + 0x02001] & 0x07f) >> 1 | next);
|
||||
ram.getAuxMemory().writeByte(0x02001 + i, (byte) (b3 & i3));
|
||||
if (i < 0x01FFE) {
|
||||
next = (framebuffer[i + 0x02002] & 1) << 6;
|
||||
}
|
||||
Byte b4 = (byte) ((framebuffer[i + 1] & 0x07f) >> 1 | next);
|
||||
ram.getMainMemory().writeByte(0x02001 + i, (byte) (b4 & i4));
|
||||
}
|
||||
}
|
||||
|
||||
List<Runnable> vblCallbacks = Collections.synchronizedList(new ArrayList<Runnable>());
|
||||
|
||||
public void waitForVBL() throws InterruptedException {
|
||||
waitForVBL(1);
|
||||
}
|
||||
|
||||
public void waitForVBL(int count) throws InterruptedException {
|
||||
Semaphore s = new Semaphore(0);
|
||||
onNextVBL(s::release);
|
||||
s.acquire();
|
||||
if (count > 1) {
|
||||
waitForVBL(count - 1);
|
||||
}
|
||||
}
|
||||
|
||||
public void onNextVBL(Runnable r) {
|
||||
vblCallbacks.add(r);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyVBLStateChanged(boolean state) {
|
||||
super.notifyVBLStateChanged(state);
|
||||
if (state) {
|
||||
Runnable r;
|
||||
while (!vblCallbacks.isEmpty()) {
|
||||
vblCallbacks.remove(0).run();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void finishColdStart() {
|
||||
for (Optional<Card> c : getMemory().getAllCards()) {
|
||||
c.ifPresent(Card::reset);
|
||||
}
|
||||
reboot();
|
||||
cpu.resume();
|
||||
resume();
|
||||
warmStart();
|
||||
}
|
||||
|
||||
private byte[] getBootScreen() {
|
||||
if (bootScreen == null) {
|
||||
InputStream in = getClass().getClassLoader().getResourceAsStream("jace/data/bootscreen.bin");
|
||||
bootScreen = new byte[0x04000];
|
||||
int len, offset = 0;
|
||||
try {
|
||||
while (offset < 0x04000 && (len = in.read(bootScreen, offset, 0x04000 - offset)) > 0) {
|
||||
offset += len;
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
Logger.getLogger(LawlessComputer.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
|
||||
}
|
||||
return bootScreen;
|
||||
}
|
||||
|
||||
}
|
@ -2,7 +2,7 @@ package jace.ui;
|
||||
|
||||
import com.sun.glass.ui.Application;
|
||||
import jace.Emulator;
|
||||
import jace.JaceApplication;
|
||||
import jace.LawlessLegends;
|
||||
import jace.cheat.DynamicCheat;
|
||||
import jace.cheat.MemoryCell;
|
||||
import jace.cheat.MetaCheat;
|
||||
@ -171,7 +171,7 @@ public class MetacheatUI {
|
||||
FileChooser chooser = new FileChooser();
|
||||
chooser.setTitle("Load cheats");
|
||||
chooser.setInitialFileName("cheat.txt");
|
||||
File saveFile = chooser.showOpenDialog(JaceApplication.getApplication().primaryStage);
|
||||
File saveFile = chooser.showOpenDialog(LawlessLegends.getApplication().primaryStage);
|
||||
if (saveFile != null) {
|
||||
cheatEngine.loadCheats(saveFile);
|
||||
}
|
||||
@ -186,7 +186,7 @@ public class MetacheatUI {
|
||||
FileChooser chooser = new FileChooser();
|
||||
chooser.setTitle("Save current cheats");
|
||||
chooser.setInitialFileName("cheat.txt");
|
||||
File saveFile = chooser.showSaveDialog(JaceApplication.getApplication().primaryStage);
|
||||
File saveFile = chooser.showSaveDialog(LawlessLegends.getApplication().primaryStage);
|
||||
if (saveFile != null) {
|
||||
cheatEngine.saveCheats(saveFile);
|
||||
}
|
||||
|
Binary file not shown.
@ -24,6 +24,7 @@ import jace.core.SoundMixer;
|
||||
import jace.core.Utility;
|
||||
import jace.ide.HeadlessProgram;
|
||||
import jace.ide.Program;
|
||||
import jace.lawless.LawlessComputer;
|
||||
import org.junit.AfterClass;
|
||||
import static org.junit.Assert.*;
|
||||
import org.junit.Before;
|
||||
@ -48,7 +49,7 @@ public class Basic6502FuncationalityTest {
|
||||
computer = new Apple2e();
|
||||
cpu = (MOS65C02) computer.getCpu();
|
||||
ram = computer.getMemory();
|
||||
Emulator.computer = (Apple2e) computer;
|
||||
Emulator.computer = (LawlessComputer) computer;
|
||||
computer.pause();
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user