2015-03-14 08:23:32 +00:00
|
|
|
/**
|
2014-09-07 21:10:04 +00:00
|
|
|
* Copyright (C) 2012 Brendan Robert (BLuRry) brendan.robert@gmail.com.
|
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
* License along with this library; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
|
|
* MA 02110-1301 USA
|
|
|
|
*/
|
|
|
|
package jace;
|
|
|
|
|
|
|
|
import jace.apple2e.MOS65C02;
|
|
|
|
import jace.apple2e.RAM128k;
|
|
|
|
import jace.apple2e.SoftSwitches;
|
2018-01-13 05:27:56 +00:00
|
|
|
import jace.config.ConfigurableField;
|
2015-02-24 06:30:11 +00:00
|
|
|
import jace.config.ConfigurationUIController;
|
2014-09-07 21:10:04 +00:00
|
|
|
import jace.config.InvokableAction;
|
2015-02-18 14:41:59 +00:00
|
|
|
import jace.config.Reconfigurable;
|
2014-09-07 21:10:04 +00:00
|
|
|
import jace.core.CPU;
|
2015-03-29 21:07:00 +00:00
|
|
|
import jace.core.Computer;
|
2014-09-07 21:10:04 +00:00
|
|
|
import jace.core.Debugger;
|
|
|
|
import jace.core.RAM;
|
|
|
|
import jace.core.RAMListener;
|
2015-07-15 06:29:37 +00:00
|
|
|
import jace.ide.IdeController;
|
2014-09-07 21:10:04 +00:00
|
|
|
import java.io.File;
|
|
|
|
import java.io.FileInputStream;
|
|
|
|
import java.io.FileNotFoundException;
|
|
|
|
import java.io.FileOutputStream;
|
|
|
|
import java.io.IOException;
|
|
|
|
import java.text.SimpleDateFormat;
|
|
|
|
import java.util.ArrayList;
|
|
|
|
import java.util.Date;
|
2015-03-14 08:23:32 +00:00
|
|
|
import java.util.HashMap;
|
|
|
|
import java.util.HashSet;
|
2014-09-07 21:10:04 +00:00
|
|
|
import java.util.List;
|
2015-03-14 08:23:32 +00:00
|
|
|
import java.util.Map;
|
|
|
|
import java.util.Set;
|
2015-03-29 21:07:00 +00:00
|
|
|
import java.util.logging.Level;
|
|
|
|
import java.util.logging.Logger;
|
|
|
|
import javafx.application.Platform;
|
2015-03-15 06:53:56 +00:00
|
|
|
import javafx.event.EventHandler;
|
2015-02-24 06:30:11 +00:00
|
|
|
import javafx.fxml.FXMLLoader;
|
|
|
|
import javafx.scene.Scene;
|
2015-03-14 08:23:32 +00:00
|
|
|
import javafx.scene.control.Label;
|
2015-02-03 06:55:25 +00:00
|
|
|
import javafx.scene.image.Image;
|
2016-02-21 03:30:23 +00:00
|
|
|
import javafx.scene.input.KeyCombination;
|
2015-03-15 06:53:56 +00:00
|
|
|
import javafx.scene.input.MouseEvent;
|
2015-02-24 06:30:11 +00:00
|
|
|
import javafx.scene.layout.AnchorPane;
|
2015-03-30 05:28:19 +00:00
|
|
|
import javafx.stage.FileChooser;
|
2015-02-24 06:30:11 +00:00
|
|
|
import javafx.stage.Stage;
|
2014-09-07 21:10:04 +00:00
|
|
|
|
2019-06-19 05:47:04 +00:00
|
|
|
import static jace.core.Utility.*;
|
|
|
|
|
2014-09-07 21:10:04 +00:00
|
|
|
/**
|
|
|
|
* This class contains miscellaneous user-invoked actions such as debugger
|
|
|
|
* operations and running arbitrary files in the emulator. It is possible for
|
|
|
|
* these methods to be later refactored into more sensible locations. Created on
|
|
|
|
* April 16, 2007, 10:30 PM
|
|
|
|
*
|
|
|
|
* @author Brendan Robert (BLuRry) brendan.robert@gmail.com
|
|
|
|
*/
|
2015-02-18 14:41:59 +00:00
|
|
|
public class EmulatorUILogic implements Reconfigurable {
|
2014-09-07 21:10:04 +00:00
|
|
|
|
|
|
|
static Debugger debugger;
|
|
|
|
|
|
|
|
static {
|
|
|
|
debugger = new Debugger() {
|
|
|
|
@Override
|
|
|
|
public void updateStatus() {
|
|
|
|
enableDebug(true);
|
2014-09-18 04:09:57 +00:00
|
|
|
MOS65C02 cpu = (MOS65C02) Emulator.computer.getCpu();
|
2014-09-07 21:10:04 +00:00
|
|
|
updateCPURegisters(cpu);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
2019-06-19 05:47:04 +00:00
|
|
|
|
2018-05-23 05:50:56 +00:00
|
|
|
@ConfigurableField(
|
|
|
|
category = "General",
|
|
|
|
name = "Speed Setting"
|
|
|
|
)
|
|
|
|
public int speedSetting = 3;
|
2014-09-07 21:10:04 +00:00
|
|
|
|
2018-01-13 05:27:56 +00:00
|
|
|
@ConfigurableField(
|
|
|
|
category = "General",
|
|
|
|
name = "Show Drives"
|
|
|
|
)
|
2018-05-23 05:50:56 +00:00
|
|
|
public boolean showDrives = true;
|
2018-01-13 05:27:56 +00:00
|
|
|
|
2014-09-07 21:10:04 +00:00
|
|
|
public static void updateCPURegisters(MOS65C02 cpu) {
|
2015-02-03 06:55:25 +00:00
|
|
|
// DebuggerPanel debuggerPanel = Emulator.getFrame().getDebuggerPanel();
|
|
|
|
// debuggerPanel.valueA.setText(Integer.toHexString(cpu.A));
|
|
|
|
// debuggerPanel.valueX.setText(Integer.toHexString(cpu.X));
|
|
|
|
// debuggerPanel.valueY.setText(Integer.toHexString(cpu.Y));
|
|
|
|
// debuggerPanel.valuePC.setText(Integer.toHexString(cpu.getProgramCounter()));
|
|
|
|
// debuggerPanel.valueSP.setText(Integer.toHexString(cpu.getSTACK()));
|
|
|
|
// debuggerPanel.valuePC2.setText(cpu.getFlags());
|
|
|
|
// debuggerPanel.valueINST.setText(cpu.disassemble());
|
2014-09-07 21:10:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public static void enableDebug(boolean b) {
|
2015-02-03 06:55:25 +00:00
|
|
|
// DebuggerPanel debuggerPanel = Emulator.getFrame().getDebuggerPanel();
|
|
|
|
// debugger.setActive(b);
|
|
|
|
// debuggerPanel.enableDebug.setSelected(b);
|
|
|
|
// debuggerPanel.setBackground(
|
|
|
|
// b ? Color.RED : new Color(0, 0, 0x040));
|
2014-09-07 21:10:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public static void enableTrace(boolean b) {
|
2014-09-18 04:09:57 +00:00
|
|
|
Emulator.computer.getCpu().setTraceEnabled(b);
|
2014-09-07 21:10:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public static void stepForward() {
|
|
|
|
debugger.step = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void registerDebugger() {
|
2014-09-18 04:09:57 +00:00
|
|
|
Emulator.computer.getCpu().setDebug(debugger);
|
2014-09-07 21:10:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public static Integer getValidAddress(String s) {
|
|
|
|
try {
|
|
|
|
int addr = Integer.parseInt(s.toUpperCase(), 16);
|
|
|
|
if (addr >= 0 && addr < 0x10000) {
|
|
|
|
return addr;
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
} catch (NumberFormatException ex) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
public static List<RAMListener> watches = new ArrayList<>();
|
|
|
|
|
2015-03-29 05:29:41 +00:00
|
|
|
// public static void updateWatchList(final DebuggerPanel panel) {
|
|
|
|
// java.awt.EventQueue.invokeLater(() -> {
|
|
|
|
// watches.stream().forEach((oldWatch) -> {
|
|
|
|
// Emulator.computer.getMemory().removeListener(oldWatch);
|
|
|
|
// });
|
|
|
|
// if (panel == null) {
|
|
|
|
// return;
|
|
|
|
// }
|
|
|
|
// addWatch(panel.textW1, panel.valueW1);
|
|
|
|
// addWatch(panel.textW2, panel.valueW2);
|
|
|
|
// addWatch(panel.textW3, panel.valueW3);
|
|
|
|
// addWatch(panel.textW4, panel.valueW4);
|
|
|
|
// });
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
// private static void addWatch(JTextField watch, final JLabel watchValue) {
|
|
|
|
// final Integer address = getValidAddress(watch.getText());
|
|
|
|
// if (address != null) {
|
|
|
|
// //System.out.println("Adding watch for "+Integer.toString(address, 16));
|
|
|
|
// RAMListener newListener = new RAMListener(RAMEvent.TYPE.WRITE, RAMEvent.SCOPE.ADDRESS, RAMEvent.VALUE.ANY) {
|
|
|
|
// @Override
|
|
|
|
// protected void doConfig() {
|
|
|
|
// setScopeStart(address);
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
// @Override
|
|
|
|
// protected void doEvent(RAMEvent e) {
|
|
|
|
// watchValue.setText(Integer.toHexString(e.getNewValue() & 0x0FF));
|
|
|
|
// }
|
|
|
|
// };
|
|
|
|
// Emulator.computer.getMemory().addListener(newListener);
|
|
|
|
// watches.add(newListener);
|
|
|
|
// // Print out the current value right away
|
|
|
|
// byte b = Emulator.computer.getMemory().readRaw(address);
|
|
|
|
// watchValue.setText(Integer.toString(b & 0x0ff, 16));
|
|
|
|
// } else {
|
|
|
|
// watchValue.setText("00");
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
// public static void updateBreakpointList(final DebuggerPanel panel) {
|
|
|
|
// java.awt.EventQueue.invokeLater(() -> {
|
|
|
|
// Integer address;
|
|
|
|
// debugger.getBreakpoints().clear();
|
|
|
|
// if (panel == null) {
|
|
|
|
// return;
|
|
|
|
// }
|
|
|
|
// address = getValidAddress(panel.textBP1.getText());
|
|
|
|
// if (address != null) {
|
|
|
|
// debugger.getBreakpoints().add(address);
|
|
|
|
// }
|
|
|
|
// address = getValidAddress(panel.textBP2.getText());
|
|
|
|
// if (address != null) {
|
|
|
|
// debugger.getBreakpoints().add(address);
|
|
|
|
// }
|
|
|
|
// address = getValidAddress(panel.textBP3.getText());
|
|
|
|
// if (address != null) {
|
|
|
|
// debugger.getBreakpoints().add(address);
|
|
|
|
// }
|
|
|
|
// address = getValidAddress(panel.textBP4.getText());
|
|
|
|
// if (address != null) {
|
|
|
|
// debugger.getBreakpoints().add(address);
|
|
|
|
// }
|
|
|
|
// debugger.updateBreakpoints();
|
|
|
|
// });
|
|
|
|
// }
|
|
|
|
//
|
2014-09-07 21:10:04 +00:00
|
|
|
@InvokableAction(
|
|
|
|
name = "BRUN file",
|
2015-02-03 06:55:25 +00:00
|
|
|
category = "file",
|
|
|
|
description = "Loads a binary file in memory and executes it. File should end with #06xxxx, where xxxx is the start address in hex",
|
2015-02-18 14:41:59 +00:00
|
|
|
alternatives = "Execute program;Load binary;Load program;Load rom;Play single-load game",
|
|
|
|
defaultKeyMapping = "ctrl+shift+b")
|
2014-09-07 21:10:04 +00:00
|
|
|
public static void runFile() {
|
2014-09-18 04:09:57 +00:00
|
|
|
Emulator.computer.pause();
|
2015-03-30 05:28:19 +00:00
|
|
|
FileChooser select = new FileChooser();
|
2015-09-05 14:02:23 +00:00
|
|
|
File binary = select.showOpenDialog(JaceApplication.getApplication().primaryStage);
|
2014-09-07 21:10:04 +00:00
|
|
|
if (binary == null) {
|
2014-09-18 04:09:57 +00:00
|
|
|
Emulator.computer.resume();
|
2014-09-07 21:10:04 +00:00
|
|
|
return;
|
|
|
|
}
|
2016-01-15 03:29:40 +00:00
|
|
|
runFileNamed(binary);
|
2014-09-07 21:10:04 +00:00
|
|
|
}
|
|
|
|
|
2016-01-15 03:29:40 +00:00
|
|
|
public static void runFileNamed(File binary) {
|
2014-09-07 21:10:04 +00:00
|
|
|
String fileName = binary.getName().toLowerCase();
|
|
|
|
try {
|
|
|
|
if (fileName.contains("#06")) {
|
|
|
|
String addressStr = fileName.substring(fileName.length() - 4);
|
|
|
|
int address = Integer.parseInt(addressStr, 16);
|
|
|
|
brun(binary, address);
|
|
|
|
} else if (fileName.contains("#fc")) {
|
|
|
|
gripe("BASIC not supported yet");
|
|
|
|
}
|
|
|
|
} catch (NumberFormatException | IOException ex) {
|
|
|
|
}
|
2014-09-18 04:09:57 +00:00
|
|
|
Emulator.computer.getCpu().resume();
|
2014-09-07 21:10:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public static void brun(File binary, int address) throws FileNotFoundException, IOException {
|
|
|
|
// If it was halted already, then it was initiated outside of an opcode execution
|
|
|
|
// 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
|
2014-09-18 04:09:57 +00:00
|
|
|
Emulator.computer.pause();
|
2014-09-07 21:10:04 +00:00
|
|
|
FileInputStream in = new FileInputStream(binary);
|
|
|
|
byte[] data = new byte[in.available()];
|
|
|
|
in.read(data);
|
2014-09-18 04:09:57 +00:00
|
|
|
RAM ram = Emulator.computer.getMemory();
|
2014-09-07 21:10:04 +00:00
|
|
|
for (int i = 0; i < data.length; i++) {
|
|
|
|
ram.write(address + i, data[i], false, true);
|
|
|
|
}
|
2014-09-18 04:09:57 +00:00
|
|
|
CPU cpu = Emulator.computer.getCpu();
|
|
|
|
Emulator.computer.getCpu().setProgramCounter(address);
|
|
|
|
Emulator.computer.resume();
|
2014-09-07 21:10:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@InvokableAction(
|
|
|
|
name = "Toggle Debug",
|
2015-02-03 06:55:25 +00:00
|
|
|
category = "debug",
|
|
|
|
description = "Show/hide the debug panel",
|
2018-01-13 05:27:56 +00:00
|
|
|
alternatives = "Show Debug;Hide Debug;Inspect",
|
2015-02-18 14:41:59 +00:00
|
|
|
defaultKeyMapping = "ctrl+shift+d")
|
2014-09-07 21:10:04 +00:00
|
|
|
public static void toggleDebugPanel() {
|
2015-02-03 06:55:25 +00:00
|
|
|
// AbstractEmulatorFrame frame = Emulator.getFrame();
|
|
|
|
// if (frame == null) {
|
|
|
|
// return;
|
|
|
|
// }
|
|
|
|
// frame.setShowDebug(!frame.isShowDebug());
|
|
|
|
// frame.reconfigure();
|
|
|
|
// Emulator.resizeVideo();
|
2014-09-07 21:10:04 +00:00
|
|
|
}
|
|
|
|
|
2016-02-21 03:30:23 +00:00
|
|
|
@InvokableAction(
|
|
|
|
name = "Toggle fullscreen",
|
|
|
|
category = "general",
|
|
|
|
description = "Activate/deactivate fullscreen mode",
|
2018-01-13 05:27:56 +00:00
|
|
|
alternatives = "fullscreen;maximize",
|
2016-02-21 03:30:23 +00:00
|
|
|
defaultKeyMapping = "ctrl+shift+f")
|
2014-09-07 21:10:04 +00:00
|
|
|
public static void toggleFullscreen() {
|
2016-02-21 04:33:16 +00:00
|
|
|
Platform.runLater(() -> {
|
|
|
|
Stage stage = JaceApplication.getApplication().primaryStage;
|
|
|
|
stage.setFullScreenExitKeyCombination(KeyCombination.NO_MATCH);
|
|
|
|
stage.setFullScreen(!stage.isFullScreen());
|
2018-01-13 05:27:56 +00:00
|
|
|
JaceApplication.getApplication().controller.setAspectRatioEnabled(stage.isFullScreen());
|
2016-02-21 04:33:16 +00:00
|
|
|
});
|
2014-09-07 21:10:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@InvokableAction(
|
|
|
|
name = "Save Raw Screenshot",
|
2015-02-03 06:55:25 +00:00
|
|
|
category = "general",
|
|
|
|
description = "Save raw (RAM) format of visible screen",
|
2018-01-13 05:27:56 +00:00
|
|
|
alternatives = "screendump;raw screenshot",
|
2015-02-18 14:41:59 +00:00
|
|
|
defaultKeyMapping = "ctrl+shift+z")
|
2014-09-07 21:10:04 +00:00
|
|
|
public static void saveScreenshotRaw() throws FileNotFoundException, IOException {
|
|
|
|
SimpleDateFormat df = new SimpleDateFormat("yyyy.MM.dd.HH.mm.ss");
|
|
|
|
String timestamp = df.format(new Date());
|
|
|
|
String type;
|
2014-09-18 04:09:57 +00:00
|
|
|
int start = Emulator.computer.getVideo().getCurrentWriter().actualWriter().getYOffset(0);
|
2014-09-17 06:01:50 +00:00
|
|
|
int len;
|
2014-09-07 21:10:04 +00:00
|
|
|
if (start < 0x02000) {
|
|
|
|
// Lo-res or double-lores
|
|
|
|
len = 0x0400;
|
|
|
|
type = "gr";
|
|
|
|
} else {
|
|
|
|
// Hi-res or double-hires
|
|
|
|
len = 0x02000;
|
|
|
|
type = "hgr";
|
|
|
|
}
|
|
|
|
boolean dres = SoftSwitches._80COL.getState() && (SoftSwitches.DHIRES.getState() || start < 0x02000);
|
|
|
|
if (dres) {
|
|
|
|
type = "d" + type;
|
|
|
|
}
|
|
|
|
File outFile = new File("screen_" + type + "_a" + Integer.toHexString(start) + "_" + timestamp);
|
|
|
|
try (FileOutputStream out = new FileOutputStream(outFile)) {
|
2014-09-18 04:09:57 +00:00
|
|
|
RAM128k ram = (RAM128k) Emulator.computer.memory;
|
|
|
|
Emulator.computer.pause();
|
2014-09-07 21:10:04 +00:00
|
|
|
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));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
System.out.println("Wrote screenshot to " + outFile.getAbsolutePath());
|
|
|
|
}
|
|
|
|
|
|
|
|
@InvokableAction(
|
|
|
|
name = "Save Screenshot",
|
2015-02-03 06:55:25 +00:00
|
|
|
category = "general",
|
|
|
|
description = "Save image of visible screen",
|
2018-01-13 05:27:56 +00:00
|
|
|
alternatives = "Save image;save framebuffer;screenshot",
|
2015-02-18 14:41:59 +00:00
|
|
|
defaultKeyMapping = "ctrl+shift+s")
|
2015-03-30 05:28:19 +00:00
|
|
|
public static void saveScreenshot() throws IOException {
|
|
|
|
FileChooser select = new FileChooser();
|
2014-09-18 04:09:57 +00:00
|
|
|
Emulator.computer.pause();
|
2015-02-03 06:55:25 +00:00
|
|
|
Image i = Emulator.computer.getVideo().getFrameBuffer();
|
2015-03-30 05:28:19 +00:00
|
|
|
// BufferedImage bufImageARGB = SwingFXUtils.fromFXImage(i, null);
|
2015-09-05 14:02:23 +00:00
|
|
|
File targetFile = select.showSaveDialog(JaceApplication.getApplication().primaryStage);
|
2014-09-07 21:10:04 +00:00
|
|
|
if (targetFile == null) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
String filename = targetFile.getName();
|
|
|
|
System.out.println("Writing screenshot to " + filename);
|
|
|
|
String extension = filename.substring(filename.lastIndexOf(".") + 1);
|
2015-03-30 05:28:19 +00:00
|
|
|
// BufferedImage bufImageRGB = new BufferedImage(bufImageARGB.getWidth(), bufImageARGB.getHeight(), BufferedImage.OPAQUE);
|
|
|
|
//
|
|
|
|
// Graphics2D graphics = bufImageRGB.createGraphics();
|
|
|
|
// graphics.drawImage(bufImageARGB, 0, 0, null);
|
|
|
|
//
|
|
|
|
// ImageIO.write(bufImageRGB, extension, targetFile);
|
|
|
|
// graphics.dispose();
|
2014-09-07 21:10:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public static final String CONFIGURATION_DIALOG_NAME = "Configuration";
|
2015-02-03 06:55:25 +00:00
|
|
|
|
2014-09-07 21:10:04 +00:00
|
|
|
@InvokableAction(
|
|
|
|
name = "Configuration",
|
2015-02-03 06:55:25 +00:00
|
|
|
category = "general",
|
|
|
|
description = "Edit emulator configuraion",
|
2018-01-13 05:27:56 +00:00
|
|
|
alternatives = "Reconfigure;Preferences;Settings;Config",
|
2015-03-14 08:23:32 +00:00
|
|
|
defaultKeyMapping = {"f4", "ctrl+shift+c"})
|
2014-09-07 21:10:04 +00:00
|
|
|
public static void showConfig() {
|
2015-02-24 06:30:11 +00:00
|
|
|
FXMLLoader fxmlLoader = new FXMLLoader(EmulatorUILogic.class.getResource("/fxml/Configuration.fxml"));
|
|
|
|
fxmlLoader.setResources(null);
|
|
|
|
try {
|
|
|
|
Stage configWindow = new Stage();
|
|
|
|
AnchorPane node = (AnchorPane) fxmlLoader.load();
|
|
|
|
ConfigurationUIController controller = fxmlLoader.getController();
|
|
|
|
controller.initialize();
|
|
|
|
Scene s = new Scene(node);
|
|
|
|
configWindow.setScene(s);
|
|
|
|
configWindow.show();
|
2015-07-15 06:29:37 +00:00
|
|
|
} catch (IOException exception) {
|
|
|
|
throw new RuntimeException(exception);
|
|
|
|
}
|
|
|
|
}
|
2015-09-05 14:02:23 +00:00
|
|
|
|
2015-07-15 06:29:37 +00:00
|
|
|
@InvokableAction(
|
|
|
|
name = "Open IDE",
|
|
|
|
category = "development",
|
|
|
|
description = "Open new IDE window for Basic/Assembly/Plasma coding",
|
2018-01-13 05:27:56 +00:00
|
|
|
alternatives = "IDE;dev;development;acme;assembler;editor",
|
2015-07-15 06:29:37 +00:00
|
|
|
defaultKeyMapping = {"ctrl+shift+i"})
|
|
|
|
public static void showIDE() {
|
|
|
|
FXMLLoader fxmlLoader = new FXMLLoader(EmulatorUILogic.class.getResource("/fxml/editor.fxml"));
|
|
|
|
fxmlLoader.setResources(null);
|
|
|
|
try {
|
|
|
|
Stage editorWindow = new Stage();
|
|
|
|
AnchorPane node = (AnchorPane) fxmlLoader.load();
|
|
|
|
IdeController controller = fxmlLoader.getController();
|
|
|
|
controller.initialize();
|
|
|
|
Scene s = new Scene(node);
|
|
|
|
editorWindow.setScene(s);
|
|
|
|
editorWindow.show();
|
2015-02-24 06:30:11 +00:00
|
|
|
} catch (IOException exception) {
|
|
|
|
throw new RuntimeException(exception);
|
2015-03-14 08:23:32 +00:00
|
|
|
}
|
2014-09-07 21:10:04 +00:00
|
|
|
}
|
|
|
|
|
2016-02-21 00:35:26 +00:00
|
|
|
static int size = -1;
|
2016-02-21 04:33:16 +00:00
|
|
|
|
2016-02-21 00:35:26 +00:00
|
|
|
@InvokableAction(
|
|
|
|
name = "Resize window",
|
2016-02-21 03:30:23 +00:00
|
|
|
category = "general",
|
2016-02-25 18:57:22 +00:00
|
|
|
description = "Resize the screen to 1x/1.5x/2x/3x video size",
|
2018-01-13 05:27:56 +00:00
|
|
|
alternatives = "Aspect;Adjust screen;Adjust window size;Adjust aspect ratio;Fix screen;Fix window size;Fix aspect ratio;Correct aspect ratio;",
|
2016-02-21 00:35:26 +00:00
|
|
|
defaultKeyMapping = {"ctrl+shift+a"})
|
|
|
|
public static void scaleIntegerRatio() {
|
2016-02-21 04:33:16 +00:00
|
|
|
Platform.runLater(() -> {
|
2018-01-13 05:27:56 +00:00
|
|
|
if (JaceApplication.getApplication() == null
|
|
|
|
|| JaceApplication.getApplication().primaryStage == null) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
Stage stage = JaceApplication.getApplication().primaryStage;
|
2016-02-21 04:33:16 +00:00
|
|
|
size++;
|
2016-02-25 18:57:22 +00:00
|
|
|
if (size > 3) {
|
2016-02-21 04:33:16 +00:00
|
|
|
size = 0;
|
|
|
|
}
|
2018-01-13 05:27:56 +00:00
|
|
|
if (stage.isFullScreen()) {
|
|
|
|
JaceApplication.getApplication().controller.toggleAspectRatio();
|
|
|
|
} else {
|
|
|
|
int width = 0, height = 0;
|
|
|
|
switch (size) {
|
|
|
|
case 0: // 1x
|
|
|
|
width = 560;
|
|
|
|
height = 384;
|
|
|
|
break;
|
|
|
|
case 1: // 1.5x
|
|
|
|
width = 840;
|
|
|
|
height = 576;
|
|
|
|
break;
|
|
|
|
case 2: // 2x
|
|
|
|
width = 560 * 2;
|
|
|
|
height = 384 * 2;
|
|
|
|
break;
|
|
|
|
case 3: // 3x (retina) 2880x1800
|
|
|
|
width = 560 * 3;
|
|
|
|
height = 384 * 3;
|
|
|
|
break;
|
|
|
|
default: // 2x
|
|
|
|
width = 560 * 2;
|
|
|
|
height = 384 * 2;
|
|
|
|
}
|
|
|
|
double vgap = stage.getScene().getY();
|
|
|
|
double hgap = stage.getScene().getX();
|
|
|
|
stage.setWidth(hgap * 2 + width);
|
|
|
|
stage.setHeight(vgap + height);
|
2016-02-21 04:33:16 +00:00
|
|
|
}
|
|
|
|
});
|
2016-02-21 00:35:26 +00:00
|
|
|
}
|
2019-06-19 05:47:04 +00:00
|
|
|
|
2018-01-13 05:27:56 +00:00
|
|
|
@InvokableAction(
|
|
|
|
name = "About",
|
|
|
|
category = "general",
|
|
|
|
description = "Display about window",
|
|
|
|
alternatives = "info;credits",
|
|
|
|
defaultKeyMapping = {"ctrl+shift+."})
|
|
|
|
public static void showAboutWindow() {
|
|
|
|
//TODO: Implement
|
2019-06-19 05:47:04 +00:00
|
|
|
}
|
2016-02-21 00:35:26 +00:00
|
|
|
|
2014-09-07 21:10:04 +00:00
|
|
|
public static boolean confirm(String message) {
|
2015-02-03 06:55:25 +00:00
|
|
|
// return JOptionPane.YES_OPTION == JOptionPane.showConfirmDialog(Emulator.getFrame(), message);
|
|
|
|
return false;
|
2014-09-07 21:10:04 +00:00
|
|
|
}
|
2015-02-18 14:41:59 +00:00
|
|
|
|
2015-08-12 07:08:22 +00:00
|
|
|
static final Map<Object, Set<Label>> INDICATORS = new HashMap<>();
|
2015-09-05 14:02:23 +00:00
|
|
|
|
2015-03-14 08:23:32 +00:00
|
|
|
static public void addIndicator(Object owner, Label icon) {
|
2015-03-15 06:53:56 +00:00
|
|
|
addIndicator(owner, icon, 250);
|
|
|
|
}
|
2015-09-05 14:02:23 +00:00
|
|
|
|
2015-03-15 06:53:56 +00:00
|
|
|
static public void addIndicator(Object owner, Label icon, long TTL) {
|
2015-09-05 14:02:23 +00:00
|
|
|
if (JaceApplication.getApplication() == null) {
|
|
|
|
return;
|
|
|
|
}
|
2015-08-12 07:08:22 +00:00
|
|
|
synchronized (INDICATORS) {
|
|
|
|
Set<Label> ind = INDICATORS.get(owner);
|
2015-03-14 08:23:32 +00:00
|
|
|
if (ind == null) {
|
|
|
|
ind = new HashSet<>();
|
2015-08-12 07:08:22 +00:00
|
|
|
INDICATORS.put(owner, ind);
|
2015-03-14 08:23:32 +00:00
|
|
|
}
|
|
|
|
ind.add(icon);
|
2015-09-05 14:02:23 +00:00
|
|
|
JaceApplication.getApplication().controller.addIndicator(icon);
|
2015-03-14 08:23:32 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static public void removeIndicator(Object owner, Label icon) {
|
2015-09-05 14:02:23 +00:00
|
|
|
if (JaceApplication.singleton == null) {
|
|
|
|
return;
|
|
|
|
}
|
2015-08-12 07:08:22 +00:00
|
|
|
synchronized (INDICATORS) {
|
|
|
|
Set<Label> ind = INDICATORS.get(owner);
|
2015-03-14 08:23:32 +00:00
|
|
|
if (ind != null) {
|
|
|
|
ind.remove(icon);
|
|
|
|
}
|
|
|
|
JaceApplication.singleton.controller.removeIndicator(icon);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static public void removeIndicators(Object owner) {
|
2015-09-05 14:02:23 +00:00
|
|
|
if (JaceApplication.singleton == null) {
|
|
|
|
return;
|
|
|
|
}
|
2015-08-12 07:08:22 +00:00
|
|
|
synchronized (INDICATORS) {
|
|
|
|
Set<Label> ind = INDICATORS.get(owner);
|
2015-03-14 08:23:32 +00:00
|
|
|
if (ind == null) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
ind.stream().forEach((icon) -> {
|
|
|
|
JaceApplication.singleton.controller.removeIndicator(icon);
|
|
|
|
});
|
2015-08-12 07:08:22 +00:00
|
|
|
INDICATORS.remove(owner);
|
2015-03-14 08:23:32 +00:00
|
|
|
}
|
|
|
|
}
|
2015-09-05 14:02:23 +00:00
|
|
|
|
2015-03-15 06:53:56 +00:00
|
|
|
static public void addMouseListener(EventHandler<MouseEvent> handler) {
|
|
|
|
if (JaceApplication.singleton != null) {
|
|
|
|
JaceApplication.singleton.controller.addMouseListener(handler);
|
|
|
|
}
|
|
|
|
}
|
2015-03-14 08:23:32 +00:00
|
|
|
|
2015-03-15 06:53:56 +00:00
|
|
|
static public void removeMouseListener(EventHandler<MouseEvent> handler) {
|
|
|
|
if (JaceApplication.singleton != null) {
|
|
|
|
JaceApplication.singleton.controller.removeMouseListener(handler);
|
|
|
|
}
|
|
|
|
}
|
2015-03-29 21:07:00 +00:00
|
|
|
|
|
|
|
public static void simulateCtrlAppleReset() {
|
2015-09-05 14:02:23 +00:00
|
|
|
Computer computer = JaceApplication.singleton.controller.computer;
|
2015-03-29 21:07:00 +00:00
|
|
|
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);
|
|
|
|
});
|
|
|
|
}
|
2015-09-05 14:02:23 +00:00
|
|
|
|
2016-02-21 08:22:47 +00:00
|
|
|
public static void notify(String message) {
|
|
|
|
if (JaceApplication.singleton != null) {
|
|
|
|
JaceApplication.singleton.controller.displayNotification(message);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-02-18 14:41:59 +00:00
|
|
|
@Override
|
|
|
|
public String getName() {
|
|
|
|
return "Jace User Interface";
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public String getShortName() {
|
|
|
|
return "UI";
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void reconfigure() {
|
2019-06-19 05:47:04 +00:00
|
|
|
if (JaceApplication.getApplication() != null) {
|
|
|
|
JaceApplication.getApplication().controller.setSpeed(speedSetting);
|
|
|
|
}
|
2015-02-18 14:41:59 +00:00
|
|
|
}
|
2015-03-14 08:23:32 +00:00
|
|
|
}
|