mirror of
https://github.com/badvision/jace.git
synced 2024-09-11 11:56:46 +00:00
Initial version: Based on last source available in SourceForge, converted to a Maven project format
This commit is contained in:
parent
c41c87c17a
commit
6341001743
2
.gitignore
vendored
2
.gitignore
vendored
@ -10,3 +10,5 @@
|
||||
|
||||
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
|
||||
hs_err_pid*
|
||||
/jace/nbproject/private/
|
||||
/jace/target/
|
3
manifest.mf
Normal file
3
manifest.mf
Normal file
@ -0,0 +1,3 @@
|
||||
Manifest-Version: 1.0
|
||||
X-COMMENT: Main-Class will be added automatically by build
|
||||
|
48
nbactions.xml
Normal file
48
nbactions.xml
Normal file
@ -0,0 +1,48 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<actions>
|
||||
<action>
|
||||
<actionName>run</actionName>
|
||||
<packagings>
|
||||
<packaging>jar</packaging>
|
||||
</packagings>
|
||||
<goals>
|
||||
<goal>-X</goal>
|
||||
<goal>-e</goal>
|
||||
<goal>process-classes</goal>
|
||||
<goal>org.codehaus.mojo:exec-maven-plugin:1.2.1:exec</goal>
|
||||
</goals>
|
||||
<properties>
|
||||
<exec.args>-classpath target/jace-2.0-SNAPSHOT.jar jace.Emulator</exec.args>
|
||||
<exec.executable>java</exec.executable>
|
||||
</properties>
|
||||
</action>
|
||||
<action>
|
||||
<actionName>debug</actionName>
|
||||
<packagings>
|
||||
<packaging>jar</packaging>
|
||||
</packagings>
|
||||
<goals>
|
||||
<goal>process-classes</goal>
|
||||
<goal>org.codehaus.mojo:exec-maven-plugin:1.2.1:exec</goal>
|
||||
</goals>
|
||||
<properties>
|
||||
<exec.args>-Xdebug -Xrunjdwp:transport=dt_socket,server=n,address=${jpda.address} -classpath %classpath jace.Emulator</exec.args>
|
||||
<exec.executable>java</exec.executable>
|
||||
<jpda.listen>true</jpda.listen>
|
||||
</properties>
|
||||
</action>
|
||||
<action>
|
||||
<actionName>profile</actionName>
|
||||
<packagings>
|
||||
<packaging>jar</packaging>
|
||||
</packagings>
|
||||
<goals>
|
||||
<goal>process-classes</goal>
|
||||
<goal>org.codehaus.mojo:exec-maven-plugin:1.2.1:exec</goal>
|
||||
</goals>
|
||||
<properties>
|
||||
<exec.args>-classpath %classpath jace.Emulator</exec.args>
|
||||
<exec.executable>java</exec.executable>
|
||||
</properties>
|
||||
</action>
|
||||
</actions>
|
108
pom.xml
Normal file
108
pom.xml
Normal file
@ -0,0 +1,108 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>org.badvision</groupId>
|
||||
<artifactId>jace</artifactId>
|
||||
<version>2.0-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>jace</name>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<mainClass>jace.MainApp</mainClass>
|
||||
</properties>
|
||||
|
||||
<organization>
|
||||
<!-- Used as the 'Vendor' for JNLP generation -->
|
||||
<name>Your Organisation</name>
|
||||
</organization>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-dependency-plugin</artifactId>
|
||||
<version>2.6</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>unpack-dependencies</id>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>unpack-dependencies</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<excludeScope>system</excludeScope>
|
||||
<excludeGroupIds>junit,org.mockito,org.hamcrest</excludeGroupIds>
|
||||
<outputDirectory>${project.build.directory}/classes</outputDirectory>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>exec-maven-plugin</artifactId>
|
||||
<version>1.2.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>unpack-dependencies</id>
|
||||
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>exec</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<executable>${java.home}/../bin/javafxpackager</executable>
|
||||
<arguments>
|
||||
<argument>-createjar</argument>
|
||||
<argument>-nocss2bin</argument>
|
||||
<argument>-appclass</argument>
|
||||
<argument>${mainClass}</argument>
|
||||
<argument>-srcdir</argument>
|
||||
<argument>${project.build.directory}/classes</argument>
|
||||
<argument>-outdir</argument>
|
||||
<argument>${project.build.directory}</argument>
|
||||
<argument>-outfile</argument>
|
||||
<argument>${project.build.finalName}.jar</argument>
|
||||
</arguments>
|
||||
</configuration>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>default-cli</id>
|
||||
<goals>
|
||||
<goal>exec</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<executable>${java.home}/bin/java</executable>
|
||||
<commandlineArgs>${runfx.args}</commandlineArgs>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.1</version>
|
||||
<configuration>
|
||||
<source>1.8</source>
|
||||
<target>1.8</target>
|
||||
<compilerArguments>
|
||||
<bootclasspath>${sun.boot.class.path}${path.separator}${java.home}/lib/jfxrt.jar</bootclasspath>
|
||||
</compilerArguments>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>2.16</version>
|
||||
<configuration>
|
||||
<additionalClasspathElements>
|
||||
<additionalClasspathElement>${java.home}/lib/jfxrt.jar</additionalClasspathElement>
|
||||
</additionalClasspathElements>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
BIN
src/.DS_Store
vendored
Normal file
BIN
src/.DS_Store
vendored
Normal file
Binary file not shown.
BIN
src/main/.DS_Store
vendored
Normal file
BIN
src/main/.DS_Store
vendored
Normal file
Binary file not shown.
BIN
src/main/java/.DS_Store
vendored
Normal file
BIN
src/main/java/.DS_Store
vendored
Normal file
Binary file not shown.
BIN
src/main/java/jace/.DS_Store
vendored
Normal file
BIN
src/main/java/jace/.DS_Store
vendored
Normal file
Binary file not shown.
128
src/main/java/jace/ConvertDiskImage.java
Normal file
128
src/main/java/jace/ConvertDiskImage.java
Normal file
@ -0,0 +1,128 @@
|
||||
/*
|
||||
* 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.hardware.FloppyDisk;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Generic disk conversion utility, using the FloppyDisk nibblize/denibblize to
|
||||
* convert between DSK and NIB formats (wherever possible anyway)
|
||||
*
|
||||
* @author Brendan Robert (BLuRry) brendan.robert@gmail.com
|
||||
*/
|
||||
public class ConvertDiskImage {
|
||||
|
||||
public static void main(String... args) {
|
||||
if (args.length != 2) {
|
||||
showHelp();
|
||||
return;
|
||||
}
|
||||
File in = new File(args[0]);
|
||||
File out = new File(args[1]);
|
||||
if (!in.exists()) {
|
||||
showHelp();
|
||||
System.out.println("Cannot find input file: " + args[0]);
|
||||
return;
|
||||
}
|
||||
if (out.exists()) {
|
||||
showHelp();
|
||||
System.out.println("Output file already exists!: " + args[1]);
|
||||
return;
|
||||
}
|
||||
String ext = args[1].substring(args[1].length() - 3);
|
||||
boolean writeNibblized = false;
|
||||
boolean writeProdosOrdered = false;
|
||||
if (ext.equalsIgnoreCase("NIB")) {
|
||||
System.out.println("Preparing to write NIB image");
|
||||
writeNibblized = true;
|
||||
} else if (ext.equalsIgnoreCase(".DO") || ext.equalsIgnoreCase("DSK")) {
|
||||
System.out.println("Preparing to write DOS 3.3 ordered disk image");
|
||||
writeNibblized = false;
|
||||
writeProdosOrdered = false;
|
||||
} else if (ext.equalsIgnoreCase(".PO")) {
|
||||
System.out.println("Preparing to write Prodos ordered image");
|
||||
writeNibblized = false;
|
||||
writeProdosOrdered = true;
|
||||
} else {
|
||||
showHelp();
|
||||
System.out.println("Could not understand desired output format");
|
||||
return;
|
||||
}
|
||||
|
||||
// First read in the disk image, this decodes the disk as necessary
|
||||
FloppyDisk theDisk = null;
|
||||
try {
|
||||
theDisk = new FloppyDisk(in);
|
||||
} catch (IOException ex) {
|
||||
System.out.println("Couldn't read disk image");
|
||||
ex.printStackTrace();
|
||||
return;
|
||||
}
|
||||
if (!writeNibblized) {
|
||||
// Now change the disk image to point to a new file and adjust the sector ordering
|
||||
System.out.println("Writing disk image with " + (writeProdosOrdered ? "prodos" : "dos 3.3") + " sector ordering");
|
||||
theDisk.diskPath = out;
|
||||
theDisk.isNibblizedImage = true;
|
||||
theDisk.currentSectorOrder = writeProdosOrdered ? FloppyDisk.PRODOS_SECTOR_ORDER : FloppyDisk.DOS_33_SECTOR_ORDER;
|
||||
theDisk.headerLength = 0;
|
||||
for (int i = 0; i < FloppyDisk.TRACK_COUNT; i++) {
|
||||
theDisk.updateTrack(i);
|
||||
}
|
||||
} else {
|
||||
FileOutputStream fos = null;
|
||||
System.out.println("Writing NIB image");
|
||||
try {
|
||||
fos = new FileOutputStream(out);
|
||||
fos.write(theDisk.nibbles);
|
||||
fos.close();
|
||||
} catch (IOException ex) {
|
||||
System.err.println("Error writing NIB image: " + ex.getMessage());
|
||||
ex.printStackTrace();
|
||||
} finally {
|
||||
try {
|
||||
fos.close();
|
||||
} catch (IOException ex) {
|
||||
System.err.println("Error closing NIB image: " + ex.getMessage());
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
System.out.println("Finished converting disk image.");
|
||||
}
|
||||
|
||||
private static void showHelp() {
|
||||
for (String s : new String[]{
|
||||
"ConvertDiskImage",
|
||||
"----------------",
|
||||
"Usage: java -cp jace.jar jace.ConvertDiskImage DISK_INPUT_NAME DISK_OUTPUT_NAME",
|
||||
"where DISK_INPUT_NAME is the path of a valid disk image, ",
|
||||
"and DISK_OUTPUT_NAME is the path where you want to ",
|
||||
"save the converted disk image.",
|
||||
"Supported input formats: ",
|
||||
" DSK (assumes DO), DO, PO, 2MG (140kb), NIB",
|
||||
"Supported output formats: ",
|
||||
" DO/DSK, PO, NIB"
|
||||
}) {
|
||||
System.out.println(s);
|
||||
}
|
||||
}
|
||||
}
|
180
src/main/java/jace/Emulator.java
Normal file
180
src/main/java/jace/Emulator.java
Normal file
@ -0,0 +1,180 @@
|
||||
/*
|
||||
* 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.Apple2e;
|
||||
import jace.config.Configuration;
|
||||
import jace.core.Computer;
|
||||
import jace.ui.AbstractEmulatorFrame;
|
||||
import jace.ui.EmulatorFrame;
|
||||
import java.awt.Component;
|
||||
import java.awt.event.ComponentEvent;
|
||||
import java.awt.event.ComponentListener;
|
||||
import java.awt.event.WindowEvent;
|
||||
import java.awt.event.WindowListener;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.swing.JFrame;
|
||||
|
||||
/**
|
||||
* Created on January 15, 2007, 10:10 PM
|
||||
* @author Brendan Robert (BLuRry) brendan.robert@gmail.com
|
||||
*/
|
||||
public class Emulator {
|
||||
|
||||
public static Emulator instance;
|
||||
public static Thread mainThread;
|
||||
|
||||
public static void main(String... args) {
|
||||
mainThread = Thread.currentThread();
|
||||
instance = new Emulator(args);
|
||||
}
|
||||
|
||||
public static AbstractEmulatorFrame getFrame() {
|
||||
if (instance != null) {
|
||||
return instance.theApp;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
public Apple2e computer;
|
||||
public AbstractEmulatorFrame theApp;
|
||||
|
||||
/**
|
||||
* Creates a new instance of Emulator
|
||||
* @param args
|
||||
*/
|
||||
public Emulator(String... args) {
|
||||
computer = new Apple2e();
|
||||
Configuration.loadSettings();
|
||||
Map<String, String> settings = new HashMap<>();
|
||||
if (args != null) {
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
if (args[i].startsWith("-")) {
|
||||
String key = args[i].substring(1);
|
||||
if ((i + 1) < args.length) {
|
||||
String val = args[i + 1];
|
||||
if (!val.startsWith("-")) {
|
||||
settings.put(key, val);
|
||||
i++;
|
||||
} else {
|
||||
settings.put(key, "true");
|
||||
}
|
||||
} else {
|
||||
settings.put(key, "true");
|
||||
}
|
||||
} else {
|
||||
System.err.println("Did not understand parameter " + args[i] + ", skipping.");
|
||||
}
|
||||
}
|
||||
}
|
||||
Configuration.applySettings(settings);
|
||||
|
||||
// theApp = new MainFrame();
|
||||
theApp = new EmulatorFrame();
|
||||
try {
|
||||
theApp.setIconImage(ImageIO.read(Emulator.class.getClassLoader().getResourceAsStream("jace/data/woz_figure.gif")));
|
||||
} catch (IOException ex) {
|
||||
Logger.getLogger(Emulator.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
//theApp.setBounds(new Rectangle((140*6),(192*3)));
|
||||
theApp.setVisible(true);
|
||||
theApp.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
theApp.setFocusTraversalKeysEnabled(false);
|
||||
theApp.setTitle("Java Apple Computer Emulator");
|
||||
theApp.addKeyListener(computer.getKeyboard().getListener());
|
||||
theApp.addComponentListener(new ComponentListener() {
|
||||
// theApp.screen.addComponentListener(new ComponentListener() {
|
||||
@Override
|
||||
public void componentResized(ComponentEvent e) {
|
||||
// System.out.println("Screen resized");
|
||||
resizeVideo();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void componentMoved(ComponentEvent e) {
|
||||
resizeVideo();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void componentShown(ComponentEvent e) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void componentHidden(ComponentEvent e) {
|
||||
}
|
||||
});
|
||||
theApp.addWindowListener(new WindowListener() {
|
||||
@Override
|
||||
public void windowOpened(WindowEvent e) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void windowClosing(WindowEvent e) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void windowClosed(WindowEvent e) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void windowIconified(WindowEvent e) {
|
||||
Computer.getComputer().getVideo().suspend();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void windowDeiconified(WindowEvent e) {
|
||||
Computer.getComputer().getVideo().resume();
|
||||
resizeVideo();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void windowActivated(WindowEvent e) {
|
||||
resizeVideo();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void windowDeactivated(WindowEvent e) {
|
||||
resizeVideo();
|
||||
}
|
||||
});
|
||||
EmulatorUILogic.registerDebugger();
|
||||
computer.getVideo().setScreen(theApp.getScreenGraphics());
|
||||
computer.coldStart();
|
||||
}
|
||||
|
||||
public static void resizeVideo() {
|
||||
AbstractEmulatorFrame window = getFrame();
|
||||
if (window != null) {
|
||||
window.resizeVideo();
|
||||
}
|
||||
}
|
||||
|
||||
public static Component getScreen() {
|
||||
AbstractEmulatorFrame window = getFrame();
|
||||
if (window != null) {
|
||||
return window.getScreen();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
372
src/main/java/jace/EmulatorUILogic.java
Normal file
372
src/main/java/jace/EmulatorUILogic.java
Normal file
@ -0,0 +1,372 @@
|
||||
/*
|
||||
* 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;
|
||||
import jace.config.ConfigurationPanel;
|
||||
import jace.config.InvokableAction;
|
||||
import jace.core.CPU;
|
||||
import jace.core.Computer;
|
||||
import jace.core.Debugger;
|
||||
import jace.core.RAM;
|
||||
import jace.core.RAMEvent;
|
||||
import jace.core.RAMListener;
|
||||
import static jace.core.Utility.*;
|
||||
import jace.library.MediaLibrary;
|
||||
import jace.ui.AbstractEmulatorFrame;
|
||||
import jace.ui.DebuggerPanel;
|
||||
import java.awt.Color;
|
||||
import java.awt.HeadlessException;
|
||||
import java.awt.image.BufferedImage;
|
||||
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;
|
||||
import java.util.List;
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.swing.JFileChooser;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JTextField;
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
public class EmulatorUILogic {
|
||||
|
||||
static Debugger debugger;
|
||||
|
||||
static {
|
||||
debugger = new Debugger() {
|
||||
@Override
|
||||
public void updateStatus() {
|
||||
enableDebug(true);
|
||||
MOS65C02 cpu = (MOS65C02) Computer.getComputer().getCpu();
|
||||
updateCPURegisters(cpu);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static void updateCPURegisters(MOS65C02 cpu) {
|
||||
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());
|
||||
}
|
||||
|
||||
public static void enableDebug(boolean b) {
|
||||
DebuggerPanel debuggerPanel = Emulator.getFrame().getDebuggerPanel();
|
||||
debugger.setActive(b);
|
||||
debuggerPanel.enableDebug.setSelected(b);
|
||||
debuggerPanel.setBackground(
|
||||
b ? Color.RED : new Color(0, 0, 0x040));
|
||||
}
|
||||
|
||||
public static void enableTrace(boolean b) {
|
||||
Computer.getComputer().getCpu().setTraceEnabled(b);
|
||||
}
|
||||
|
||||
public static void stepForward() {
|
||||
debugger.step = true;
|
||||
}
|
||||
|
||||
static void registerDebugger() {
|
||||
Computer.getComputer().getCpu().setDebug(debugger);
|
||||
}
|
||||
|
||||
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<>();
|
||||
|
||||
public static void updateWatchList(final DebuggerPanel panel) {
|
||||
java.awt.EventQueue.invokeLater(() -> {
|
||||
watches.stream().forEach((oldWatch) -> {
|
||||
Computer.getComputer().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));
|
||||
}
|
||||
};
|
||||
Computer.getComputer().getMemory().addListener(newListener);
|
||||
watches.add(newListener);
|
||||
// Print out the current value right away
|
||||
byte b = Computer.getComputer().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();
|
||||
});
|
||||
}
|
||||
|
||||
@InvokableAction(
|
||||
name = "BRUN file",
|
||||
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",
|
||||
alternatives = "Execute program;Load binary;Load program;Load rom;Play single-load game")
|
||||
public static void runFile() {
|
||||
Computer.pause();
|
||||
JFileChooser select = new JFileChooser();
|
||||
select.showDialog(Emulator.getFrame(), "Execute binary file");
|
||||
File binary = select.getSelectedFile();
|
||||
if (binary == null) {
|
||||
Computer.resume();
|
||||
return;
|
||||
}
|
||||
runFile(binary);
|
||||
}
|
||||
|
||||
public static void runFile(File binary) {
|
||||
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) {
|
||||
}
|
||||
Computer.getComputer().getCpu().resume();
|
||||
}
|
||||
|
||||
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
|
||||
Computer.pause();
|
||||
FileInputStream in = new FileInputStream(binary);
|
||||
byte[] data = new byte[in.available()];
|
||||
in.read(data);
|
||||
RAM ram = Computer.getComputer().getMemory();
|
||||
for (int i = 0; i < data.length; i++) {
|
||||
ram.write(address + i, data[i], false, true);
|
||||
}
|
||||
CPU cpu = Computer.getComputer().getCpu();
|
||||
Computer.getComputer().getCpu().setProgramCounter(address);
|
||||
Computer.resume();
|
||||
}
|
||||
|
||||
@InvokableAction(
|
||||
name = "Adjust display",
|
||||
category = "display",
|
||||
description = "Adjusts window size to 1:1 aspect ratio for optimal viewing.",
|
||||
alternatives = "Adjust screen;Adjust window size;Adjust aspect ratio;Fix screen;Fix window size;Fix aspect ratio;Correct aspect ratio;")
|
||||
static public void scaleIntegerRatio() {
|
||||
AbstractEmulatorFrame frame = Emulator.getFrame();
|
||||
if (frame == null) {
|
||||
return;
|
||||
}
|
||||
Computer.pause();
|
||||
frame.enforceIntegerRatio();
|
||||
Computer.resume();
|
||||
}
|
||||
|
||||
@InvokableAction(
|
||||
name = "Toggle Debug",
|
||||
category = "debug",
|
||||
description = "Show/hide the debug panel",
|
||||
alternatives = "Show Debug;Hide Debug")
|
||||
public static void toggleDebugPanel() {
|
||||
AbstractEmulatorFrame frame = Emulator.getFrame();
|
||||
if (frame == null) {
|
||||
return;
|
||||
}
|
||||
frame.setShowDebug(!frame.isShowDebug());
|
||||
frame.reconfigure();
|
||||
Emulator.resizeVideo();
|
||||
}
|
||||
|
||||
public static void toggleFullscreen() {
|
||||
AbstractEmulatorFrame frame = Emulator.getFrame();
|
||||
if (frame == null) {
|
||||
return;
|
||||
}
|
||||
Computer.pause();
|
||||
frame.toggleFullscreen();
|
||||
Computer.resume();
|
||||
}
|
||||
|
||||
@InvokableAction(
|
||||
name = "Save Raw Screenshot",
|
||||
category = "general",
|
||||
description = "Save raw (RAM) format of visible screen",
|
||||
alternatives = "screendump, raw screenshot")
|
||||
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;
|
||||
int start = Computer.getComputer().getVideo().getCurrentWriter().actualWriter().getYOffset(0);
|
||||
int len = 0;
|
||||
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)) {
|
||||
RAM128k ram = (RAM128k) Computer.getComputer().memory;
|
||||
Computer.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));
|
||||
}
|
||||
}
|
||||
System.out.println("Wrote screenshot to " + outFile.getAbsolutePath());
|
||||
}
|
||||
|
||||
@InvokableAction(
|
||||
name = "Save Screenshot",
|
||||
category = "general",
|
||||
description = "Save image of visible screen",
|
||||
alternatives = "Save image,save framebuffer,screenshot")
|
||||
public static void saveScreenshot() throws HeadlessException, IOException {
|
||||
JFileChooser select = new JFileChooser();
|
||||
Computer.pause();
|
||||
BufferedImage i = Computer.getComputer().getVideo().getFrameBuffer();
|
||||
BufferedImage j = new BufferedImage(i.getWidth(), i.getHeight(), i.getType());
|
||||
j.getGraphics().drawImage(i, 0, 0, null);
|
||||
select.showSaveDialog(Emulator.getFrame());
|
||||
File targetFile = select.getSelectedFile();
|
||||
if (targetFile == null) {
|
||||
return;
|
||||
}
|
||||
String filename = targetFile.getName();
|
||||
System.out.println("Writing screenshot to " + filename);
|
||||
String extension = filename.substring(filename.lastIndexOf(".") + 1);
|
||||
ImageIO.write(j, extension, targetFile);
|
||||
}
|
||||
|
||||
public static final String CONFIGURATION_DIALOG_NAME = "Configuration";
|
||||
@InvokableAction(
|
||||
name = "Configuration",
|
||||
category = "general",
|
||||
description = "Edit emulator configuraion",
|
||||
alternatives = "Reconfigure,Preferences,Settings")
|
||||
public static void showConfig() {
|
||||
if (Emulator.getFrame().getModalDialogUI(CONFIGURATION_DIALOG_NAME) == null) {
|
||||
JPanel ui = new ConfigurationPanel();
|
||||
Emulator.getFrame().registerModalDialog(ui, CONFIGURATION_DIALOG_NAME, null, false);
|
||||
}
|
||||
Emulator.getFrame().showDialog(CONFIGURATION_DIALOG_NAME);
|
||||
}
|
||||
|
||||
public static final String MEDIA_MANAGER_DIALOG_NAME = "Media Manager";
|
||||
public static final String MEDIA_MANAGER_EDIT_DIALOG_NAME = "Media Details";
|
||||
@InvokableAction(
|
||||
name = "Media Manager",
|
||||
category = "general",
|
||||
description = "Show the media manager",
|
||||
alternatives = "Insert disk;Eject disk;Browse;Download;Select")
|
||||
public static void showMediaManager() {
|
||||
if (Emulator.getFrame().getModalDialogUI(MEDIA_MANAGER_DIALOG_NAME) == null) {
|
||||
Emulator.getFrame().registerModalDialog(MediaLibrary.getInstance().buildUserInterface(), MEDIA_MANAGER_DIALOG_NAME, null, false);
|
||||
}
|
||||
Emulator.getFrame().showDialog(MEDIA_MANAGER_DIALOG_NAME);
|
||||
}
|
||||
|
||||
public static boolean confirm(String message) {
|
||||
return JOptionPane.YES_OPTION == JOptionPane.showConfirmDialog(Emulator.getFrame(), message);
|
||||
}
|
||||
}
|
38
src/main/java/jace/JaceApplication.java
Normal file
38
src/main/java/jace/JaceApplication.java
Normal file
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* 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 javafx.application.Application;
|
||||
import javafx.fxml.FXMLLoader;
|
||||
import javafx.scene.Parent;
|
||||
import javafx.scene.Scene;
|
||||
import javafx.stage.Stage;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author blurry
|
||||
*/
|
||||
public class JaceApplication extends Application {
|
||||
|
||||
@Override
|
||||
public void start(Stage stage) throws Exception {
|
||||
Parent root = FXMLLoader.load(getClass().getResource("fxml/JaceUI.fxml"));
|
||||
|
||||
Scene scene = new Scene(root);
|
||||
|
||||
stage.setScene(scene);
|
||||
stage.show();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param args the command line arguments
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
launch(args);
|
||||
}
|
||||
|
||||
}
|
38
src/main/java/jace/JaceUIController.java
Normal file
38
src/main/java/jace/JaceUIController.java
Normal file
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* 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 java.awt.Canvas;
|
||||
import java.net.URL;
|
||||
import java.util.ResourceBundle;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.fxml.Initializable;
|
||||
import javafx.scene.layout.Region;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author blurry
|
||||
*/
|
||||
public class JaceUIController {
|
||||
@FXML
|
||||
private ResourceBundle resources;
|
||||
|
||||
@FXML
|
||||
private Canvas displayCanvas;
|
||||
|
||||
@FXML
|
||||
private Region notificationRegion;
|
||||
|
||||
|
||||
@FXML
|
||||
public void initialize() {
|
||||
assert displayCanvas != null : "fx:id=\"displayCanvas\" was not injected: check your FXML file 'JaceUI.fxml'.";
|
||||
assert notificationRegion != null : "fx:id=\"notificationRegion\" was not injected: check your FXML file 'JaceUI.fxml'.";
|
||||
}
|
||||
|
||||
|
||||
}
|
433
src/main/java/jace/apple2e/Apple2e.java
Normal file
433
src/main/java/jace/apple2e/Apple2e.java
Normal file
@ -0,0 +1,433 @@
|
||||
/*
|
||||
* 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.apple2e;
|
||||
|
||||
import jace.Emulator;
|
||||
import jace.cheat.Cheats;
|
||||
import jace.config.ClassSelection;
|
||||
import jace.config.ConfigurableField;
|
||||
import jace.core.Card;
|
||||
import jace.core.Computer;
|
||||
import jace.core.Motherboard;
|
||||
import jace.core.RAM;
|
||||
import jace.core.RAMEvent;
|
||||
import jace.core.RAMListener;
|
||||
import jace.state.Stateful;
|
||||
import jace.core.Video;
|
||||
import jace.hardware.CardDiskII;
|
||||
import jace.hardware.CardExt80Col;
|
||||
import jace.hardware.ConsoleProbe;
|
||||
import jace.hardware.Joystick;
|
||||
import jace.hardware.massStorage.CardMassStorage;
|
||||
import java.awt.Graphics;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* 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
|
||||
* and resume are implemented by the Motherboard class. This class provides
|
||||
* overall configuration of the computer, but the actual operation of the
|
||||
* computer and its timing characteristics are managed in the Motherboard class.
|
||||
*
|
||||
* @author Brendan Robert (BLuRry) brendan.robert@gmail.com
|
||||
*/
|
||||
@Stateful
|
||||
public class Apple2e extends Computer {
|
||||
|
||||
static int IRQ_VECTOR = 0x003F2;
|
||||
public Motherboard motherboard;
|
||||
@ConfigurableField(name = "Slot 1", shortName = "s1card")
|
||||
public ClassSelection card1 = new ClassSelection(Card.class, null);
|
||||
@ConfigurableField(name = "Slot 2", shortName = "s2card")
|
||||
// public Class<? extends Card> card2 = CardSSC.class;
|
||||
public ClassSelection card2 = new ClassSelection(Card.class, null);
|
||||
@ConfigurableField(name = "Slot 3", shortName = "s3card")
|
||||
public ClassSelection card3 = new ClassSelection(Card.class, null);
|
||||
@ConfigurableField(name = "Slot 4", shortName = "s4card")
|
||||
public ClassSelection card4 = new ClassSelection(Card.class, null);
|
||||
@ConfigurableField(name = "Slot 5", shortName = "s5card")
|
||||
public ClassSelection card5 = new ClassSelection(Card.class, null);
|
||||
@ConfigurableField(name = "Slot 6", shortName = "s6card")
|
||||
public ClassSelection card6 = new ClassSelection(Card.class, CardDiskII.class);
|
||||
@ConfigurableField(name = "Slot 7", shortName = "s7card")
|
||||
public ClassSelection card7 = new ClassSelection(Card.class, CardMassStorage.class);
|
||||
@ConfigurableField(name = "Debug rom", shortName = "debugRom", description = "Use debugger //e rom")
|
||||
public boolean useDebugRom = false;
|
||||
@ConfigurableField(name = "Console probe", description = "Enable console redirection (experimental!)")
|
||||
public boolean useConsoleProbe = false;
|
||||
private ConsoleProbe probe = new ConsoleProbe();
|
||||
@ConfigurableField(name = "Helpful hints", shortName = "hints")
|
||||
public boolean enableHints = true;
|
||||
@ConfigurableField(name = "Renderer", shortName = "video", description = "Video rendering implementation")
|
||||
public ClassSelection videoRenderer = new ClassSelection(Video.class, VideoNTSC.class);
|
||||
@ConfigurableField(name = "Aux Ram", shortName = "ram", description = "Aux ram card")
|
||||
public ClassSelection ramCard = new ClassSelection(RAM128k.class, CardExt80Col.class);
|
||||
public Joystick joystick1;
|
||||
public Joystick joystick2;
|
||||
@ConfigurableField(name = "Activate Cheats", shortName = "cheat", defaultValue = "")
|
||||
public ClassSelection cheatEngine = new ClassSelection(Cheats.class, null);
|
||||
public Cheats activeCheatEngine = null;
|
||||
|
||||
/**
|
||||
* Creates a new instance of Apple2e
|
||||
*/
|
||||
public Apple2e() {
|
||||
super();
|
||||
try {
|
||||
reconfigure();
|
||||
// Setup core resources
|
||||
joystick1 = new Joystick(0);
|
||||
joystick2 = new Joystick(1);
|
||||
setCpu(new MOS65C02());
|
||||
reinitMotherboard();
|
||||
} catch (Throwable t) {
|
||||
System.err.println("Unable to initalize virtual machine");
|
||||
t.printStackTrace(System.err);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Computer (Apple //e)";
|
||||
}
|
||||
|
||||
private void reinitMotherboard() {
|
||||
if (motherboard != null && motherboard.isRunning()) {
|
||||
motherboard.suspend();
|
||||
}
|
||||
motherboard = new Motherboard();
|
||||
motherboard.reconfigure();
|
||||
Motherboard.miscDevices.add(joystick1);
|
||||
Motherboard.miscDevices.add(joystick2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void coldStart() {
|
||||
Computer.pause();
|
||||
reinitMotherboard();
|
||||
reboot();
|
||||
//getMemory().dump();
|
||||
for (SoftSwitches s : SoftSwitches.values()) {
|
||||
s.getSwitch().reset();
|
||||
}
|
||||
getMemory().configureActiveMemory();
|
||||
getVideo().configureVideoMode();
|
||||
getCpu().reset();
|
||||
for (Card c : getMemory().getAllCards()) {
|
||||
if (c != null) {
|
||||
c.reset();
|
||||
}
|
||||
}
|
||||
|
||||
Computer.resume();
|
||||
/*
|
||||
getCpu().resume();
|
||||
getVideo().resume();
|
||||
*/
|
||||
}
|
||||
|
||||
public void reboot() {
|
||||
RAM r = getMemory();
|
||||
r.write(IRQ_VECTOR, (byte) 0x00, false, true);
|
||||
r.write(IRQ_VECTOR + 1, (byte) 0x00, false, true);
|
||||
r.write(IRQ_VECTOR + 2, (byte) 0x00, false, true);
|
||||
warmStart();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void warmStart() {
|
||||
boolean restart = Computer.pause();
|
||||
for (SoftSwitches s : SoftSwitches.values()) {
|
||||
s.getSwitch().reset();
|
||||
}
|
||||
getMemory().configureActiveMemory();
|
||||
getVideo().configureVideoMode();
|
||||
getCpu().reset();
|
||||
for (Card c : getMemory().getAllCards()) {
|
||||
if (c != null) {
|
||||
c.reset();
|
||||
}
|
||||
}
|
||||
getCpu().resume();
|
||||
Computer.resume();
|
||||
}
|
||||
|
||||
private void insertCard(Class<? extends Card> type, int slot) {
|
||||
if (getMemory().getCard(slot) != null) {
|
||||
if (getMemory().getCard(slot).getClass().equals(type)) {
|
||||
return;
|
||||
}
|
||||
getMemory().removeCard(slot);
|
||||
}
|
||||
if (type != null) {
|
||||
try {
|
||||
getMemory().addCard(type.newInstance(), slot);
|
||||
} catch (InstantiationException | IllegalAccessException ex) {
|
||||
Logger.getLogger(Apple2e.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void reconfigure() {
|
||||
boolean restart = Computer.pause();
|
||||
|
||||
super.reconfigure();
|
||||
|
||||
RAM128k currentMemory = (RAM128k) getMemory();
|
||||
if (currentMemory != null && !(currentMemory.getClass().equals(ramCard.getValue()))) {
|
||||
try {
|
||||
RAM128k newMemory = (RAM128k) ramCard.getValue().newInstance();
|
||||
newMemory.copyFrom(currentMemory);
|
||||
setMemory(newMemory);
|
||||
} catch (InstantiationException | IllegalAccessException ex) {
|
||||
}
|
||||
}
|
||||
if (getMemory() == null) {
|
||||
try {
|
||||
currentMemory = (RAM128k) ramCard.getValue().newInstance();
|
||||
} catch (InstantiationException | IllegalAccessException ex) {
|
||||
Logger.getLogger(Apple2e.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
try {
|
||||
setMemory(currentMemory);
|
||||
for (SoftSwitches s : SoftSwitches.values()) {
|
||||
s.getSwitch().register();
|
||||
}
|
||||
} catch (Throwable ex) {
|
||||
}
|
||||
}
|
||||
currentMemory.reconfigure();
|
||||
|
||||
try {
|
||||
if (useConsoleProbe) {
|
||||
probe.init(this);
|
||||
} else {
|
||||
probe.shutdown();
|
||||
}
|
||||
|
||||
if (useDebugRom) {
|
||||
loadRom("jace/data/apple2e_debug.rom");
|
||||
} else {
|
||||
loadRom("jace/data/apple2e.rom");
|
||||
}
|
||||
|
||||
if (getVideo() == null || getVideo().getClass() != videoRenderer.getValue()) {
|
||||
Graphics g = null;
|
||||
if (getVideo() != null) {
|
||||
getVideo().suspend();
|
||||
g = getVideo().getScreen();
|
||||
}
|
||||
try {
|
||||
setVideo((Video) videoRenderer.getValue().newInstance());
|
||||
getVideo().configureVideoMode();
|
||||
getVideo().reconfigure();
|
||||
getVideo().setScreen(g);
|
||||
Emulator.resizeVideo();
|
||||
getVideo().resume();
|
||||
} catch (InstantiationException | IllegalAccessException ex) {
|
||||
Logger.getLogger(Apple2e.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
}
|
||||
|
||||
// Add all new cards
|
||||
insertCard(card1.getValue(), 1);
|
||||
insertCard(card2.getValue(), 2);
|
||||
insertCard(card3.getValue(), 3);
|
||||
insertCard(card4.getValue(), 4);
|
||||
insertCard(card5.getValue(), 5);
|
||||
insertCard(card6.getValue(), 6);
|
||||
insertCard(card7.getValue(), 7);
|
||||
if (enableHints) {
|
||||
enableHints();
|
||||
} else {
|
||||
disableHints();
|
||||
}
|
||||
getMemory().configureActiveMemory();
|
||||
|
||||
if (cheatEngine.getValue() == null) {
|
||||
if (activeCheatEngine != null) {
|
||||
activeCheatEngine.detach();
|
||||
}
|
||||
activeCheatEngine = null;
|
||||
} else {
|
||||
boolean startCheats = true;
|
||||
if (activeCheatEngine != null) {
|
||||
if (activeCheatEngine.getClass().equals(cheatEngine.getValue())) {
|
||||
startCheats = false;
|
||||
} else {
|
||||
activeCheatEngine.detach();
|
||||
activeCheatEngine = null;
|
||||
}
|
||||
}
|
||||
if (startCheats) {
|
||||
try {
|
||||
activeCheatEngine = (Cheats) cheatEngine.getValue().newInstance();
|
||||
} catch (InstantiationException | IllegalAccessException ex) {
|
||||
Logger.getLogger(Apple2e.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
activeCheatEngine.attach();
|
||||
}
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
Logger.getLogger(Apple2e.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
if (restart) {
|
||||
Computer.resume();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doPause() {
|
||||
if (motherboard == null) {
|
||||
return;
|
||||
}
|
||||
motherboard.pause();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doResume() {
|
||||
if (motherboard == null) {
|
||||
return;
|
||||
}
|
||||
motherboard.resume();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isRunning() {
|
||||
if (motherboard == null) {
|
||||
return false;
|
||||
}
|
||||
return motherboard.isRunning() && !motherboard.isPaused;
|
||||
}
|
||||
private List<RAMListener> hints = new ArrayList<>();
|
||||
|
||||
private void enableHints() {
|
||||
if (hints.isEmpty()) {
|
||||
hints.add(new RAMListener(RAMEvent.TYPE.EXECUTE, RAMEvent.SCOPE.ADDRESS, RAMEvent.VALUE.ANY) {
|
||||
@Override
|
||||
protected void doConfig() {
|
||||
setScopeStart(0x0FB63);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doEvent(RAMEvent e) {
|
||||
if (getCpu().getProgramCounter() != getScopeStart()) {
|
||||
return;
|
||||
}
|
||||
Thread t = new Thread(() -> {
|
||||
try {
|
||||
// Give the floppy drive time to start
|
||||
Thread.sleep(1000);
|
||||
if (getCpu().getProgramCounter() >> 8 != 0x0c6) {
|
||||
return;
|
||||
}
|
||||
|
||||
int row = 2;
|
||||
for (String s : new String[]{
|
||||
" Welcome to",
|
||||
" _ __ ___ ____ ",
|
||||
" | | / /\\ / / ` | |_ ",
|
||||
" \\_|_| /_/--\\ \\_\\_, |_|__ ",
|
||||
"",
|
||||
" Java Apple Computer Emulator",
|
||||
"",
|
||||
" Presented by BLuRry",
|
||||
" http://goo.gl/SnzqG",
|
||||
"",
|
||||
"Press F1 to insert disk in Slot 6, D1",
|
||||
"Press F2 to insert disk in Slot 6, D2",
|
||||
"Press F3 to insert HDV or 2MG in slot 7",
|
||||
"Press F4 to open configuration",
|
||||
"Press F5 to run raw binary program",
|
||||
"Press F8 to correct the aspect ratio",
|
||||
"Press F9 to toggle fullscreen",
|
||||
|