Detatch is now reserved only for removal of hardware (will unhook keyboard shortcuts) whereas listener registration can be performed during reconfiguration. This distinction had to be made because reconfiguration was disconnecting keyboard shortcuts and making a general mess of things. Also, now the correct open/closed apple key behavior is working.

This commit is contained in:
Brendan Robert 2015-02-21 10:52:26 -06:00
parent 9dcbc3422e
commit 7e5ddac0e6
20 changed files with 157 additions and 148 deletions

View File

@ -327,6 +327,8 @@ public class Apple2e extends Computer {
} }
private List<RAMListener> hints = new ArrayList<>(); private List<RAMListener> hints = new ArrayList<>();
Thread twinkleEffect;
private void enableHints() { private void enableHints() {
if (hints.isEmpty()) { if (hints.isEmpty()) {
hints.add(new RAMListener(RAMEvent.TYPE.EXECUTE, RAMEvent.SCOPE.ADDRESS, RAMEvent.VALUE.ANY) { hints.add(new RAMListener(RAMEvent.TYPE.EXECUTE, RAMEvent.SCOPE.ADDRESS, RAMEvent.VALUE.ANY) {
@ -340,64 +342,66 @@ public class Apple2e extends Computer {
if (getCpu().getProgramCounter() != getScopeStart()) { if (getCpu().getProgramCounter() != getScopeStart()) {
return; return;
} }
Thread t = new Thread(() -> { if (twinkleEffect == null || !twinkleEffect.isAlive()) {
try { twinkleEffect = new Thread(() -> {
// Give the floppy drive time to start try {
Thread.sleep(1000); // Give the floppy drive time to start
if (getCpu().getProgramCounter() >> 8 != 0x0c6) { Thread.sleep(1000);
return; if (getCpu().getProgramCounter() >> 8 != 0x0c6) {
} return;
}
int row = 2; int row = 2;
for (String s : new String[]{ for (String s : new String[]{
" Welcome to", " Welcome to",
" _ __ ___ ____ ", " _ __ ___ ____ ",
" | | / /\\ / / ` | |_ ", " | | / /\\ / / ` | |_ ",
" \\_|_| /_/--\\ \\_\\_, |_|__ ", " \\_|_| /_/--\\ \\_\\_, |_|__ ",
"", "",
" Java Apple Computer Emulator", " Java Apple Computer Emulator",
"", "",
" Presented by BLuRry", " Presented by BLuRry",
" http://goo.gl/SnzqG", " http://goo.gl/SnzqG",
"", "",
"Press F1 to insert disk in Slot 6, D1", "Press F1 to insert disk in Slot 6, D1",
"Press F2 to insert disk in Slot 6, D2", "Press F2 to insert disk in Slot 6, D2",
"Press F3 to insert HDV or 2MG in slot 7", "Press F3 to insert HDV or 2MG in slot 7",
"Press F4 to open configuration", "Press F4 to open configuration",
"Press F5 to run raw binary program", "Press F5 to run raw binary program",
"Press F8 to correct the aspect ratio", "Press F8 to correct the aspect ratio",
"Press F9 to toggle fullscreen", "Press F9 to toggle fullscreen",
"Press F10 to open/close the debugger", "Press F10 to open/close the debugger",
"", "",
" If metacheat is enabled:", " If metacheat is enabled:",
"Press HOME to activate memory heatmap", "Press HOME to activate memory heatmap",
"Press END to activate metacheat search" "Press END to activate metacheat search"
}) { }) {
int addr = 0x0401 + VideoDHGR.calculateTextOffset(row++); int addr = 0x0401 + VideoDHGR.calculateTextOffset(row++);
for (char c : s.toCharArray()) { for (char c : s.toCharArray()) {
getMemory().write(addr++, (byte) (c | 0x080), false, true); getMemory().write(addr++, (byte) (c | 0x080), false, true);
}
}
while (getCpu().getProgramCounter() >> 8 == 0x0c6) {
int x = (int) (Math.random() * 26.0) + 7;
int y = (int) (Math.random() * 4.0) + 3;
int addr = 0x0400 + VideoDHGR.calculateTextOffset(y) + x;
byte old = getMemory().readRaw(addr);
for (char c : "+xX*+".toCharArray()) {
if (getCpu().getProgramCounter() >> 8 != 0x0c6) {
break;
} }
getMemory().write(addr, (byte) (c | 0x080), true, true);
Thread.sleep(100);
} }
getMemory().write(addr, old, true, true); while (getCpu().getProgramCounter() >> 8 == 0x0c6) {
int x = (int) (Math.random() * 26.0) + 7;
int y = (int) (Math.random() * 4.0) + 3;
int addr = 0x0400 + VideoDHGR.calculateTextOffset(y) + x;
byte old = getMemory().readRaw(addr);
for (char c : "+xX*+".toCharArray()) {
if (getCpu().getProgramCounter() >> 8 != 0x0c6) {
break;
}
getMemory().write(addr, (byte) (c | 0x080), true, true);
Thread.sleep(100);
}
getMemory().write(addr, old, true, true);
}
} catch (InterruptedException ex) {
Logger.getLogger(Apple2e.class.getName()).log(Level.SEVERE, null, ex);
} }
} catch (InterruptedException ex) { });
Logger.getLogger(Apple2e.class.getName()).log(Level.SEVERE, null, ex); twinkleEffect.setName("Startup Animation");
} twinkleEffect.start();
}); }
t.setName("Startup Animation");
t.start();
} }
}); });
// Latch to the PRODOS SYNTAX CHECK parser // Latch to the PRODOS SYNTAX CHECK parser

View File

@ -321,5 +321,6 @@ public class Speaker extends Device {
public void detach() { public void detach() {
removeListener(); removeListener();
suspend(); suspend();
super.detach();
} }
} }

View File

@ -734,11 +734,6 @@ public class VideoDHGR extends Video {
// Do nothing // Do nothing
} }
@Override
public void detach() {
// Do nothing
}
@Override @Override
public void hblankStart(WritableImage screen, int y, boolean isDirty) { public void hblankStart(WritableImage screen, int y, boolean isDirty) {
// Do nothing // Do nothing

View File

@ -328,10 +328,8 @@ public class VideoNTSC extends VideoDHGR {
@Override @Override
public void reconfigure() { public void reconfigure() {
detach();
activePalette = useTextPalette ? textPalette : solidPalette; activePalette = useTextPalette ? textPalette : solidPalette;
super.reconfigure(); super.reconfigure();
attach();
} }
// The following section captures changes to the RGB mode // The following section captures changes to the RGB mode
// The details of this are in Brodener's patent application #4631692 // The details of this are in Brodener's patent application #4631692
@ -456,10 +454,10 @@ public class VideoNTSC extends VideoDHGR {
@Override @Override
public void detach() { public void detach() {
super.detach();
rgbStateListeners.stream().forEach((l) -> { rgbStateListeners.stream().forEach((l) -> {
computer.getMemory().removeListener(l); computer.getMemory().removeListener(l);
}); });
super.detach();
} }
@Override @Override

View File

@ -41,8 +41,20 @@ public abstract class Cheats extends Device {
computer.getMemory().addListener(l); computer.getMemory().addListener(l);
} }
@Override
public void attach() {
registerListeners();
}
@Override @Override
public void detach() { public void detach() {
unregisterListeners();
super.detach();
}
abstract void registerListeners();
protected void unregisterListeners() {
listeners.stream().forEach((l) -> { listeners.stream().forEach((l) -> {
computer.getMemory().removeListener(l); computer.getMemory().removeListener(l);
}); });
@ -51,8 +63,8 @@ public abstract class Cheats extends Device {
@Override @Override
public void reconfigure() { public void reconfigure() {
detach(); unregisterListeners();
attach(); registerListeners();
} }
@Override @Override

View File

@ -165,7 +165,7 @@ public class MetaCheats extends Cheats {
@Override @Override
public void attach() { public void registerListeners() {
this.addCheat(new RAMListener(RAMEvent.TYPE.READ, RAMEvent.SCOPE.ANY, RAMEvent.VALUE.ANY) { this.addCheat(new RAMListener(RAMEvent.TYPE.READ, RAMEvent.SCOPE.ANY, RAMEvent.VALUE.ANY) {
@Override @Override
protected void doConfig() { protected void doConfig() {
@ -205,12 +205,6 @@ public class MetaCheats extends Cheats {
}); });
} }
@Override
public void detach() {
super.detach();
Keyboard.unregisterAllHandlers(this);
}
public void addByteCheat(int addr, int val) { public void addByteCheat(int addr, int val) {
holdBytes.put(addr, val); holdBytes.put(addr, val);
redrawCheats(); redrawCheats();

View File

@ -99,9 +99,9 @@ public class PrinceOfPersiaCheats extends Cheats implements MouseListener {
public static int InEditor = 0x0202; public static int InEditor = 0x0202;
public static int MinLeft = 0x0300; public static int MinLeft = 0x0300;
public static int hasSword = 0x030a; public static int hasSword = 0x030a;
public static int mobtables = 0x0b600; public static final int mobtables = 0x0b600;
public static int trloc = mobtables; public static final int trloc = mobtables;
public static int trscrn = trloc + 0x020; public static final int trscrn = trloc + 0x020;
public static int trdirec = trscrn + 0x020; public static int trdirec = trscrn + 0x020;
// Blueprint (map level data)0 // Blueprint (map level data)0
public static int BlueSpec = 0x0b9d0; public static int BlueSpec = 0x0b9d0;
@ -164,7 +164,7 @@ public class PrinceOfPersiaCheats extends Cheats implements MouseListener {
} }
@Override @Override
public void attach() { public void registerListeners() {
if (velocityHack) { if (velocityHack) {
addCheat(new RAMListener(RAMEvent.TYPE.READ_DATA, RAMEvent.SCOPE.ADDRESS, RAMEvent.VALUE.ANY) { addCheat(new RAMListener(RAMEvent.TYPE.READ_DATA, RAMEvent.SCOPE.ADDRESS, RAMEvent.VALUE.ANY) {
@Override @Override
@ -269,8 +269,8 @@ public class PrinceOfPersiaCheats extends Cheats implements MouseListener {
} }
@Override @Override
public void detach() { public void unregisterListeners() {
super.detach(); super.unregisterListeners();
if (Emulator.getScreen() != null) { if (Emulator.getScreen() != null) {
Emulator.getScreen().removeMouseListener(this); Emulator.getScreen().removeMouseListener(this);
} }
@ -411,11 +411,8 @@ public class PrinceOfPersiaCheats extends Cheats implements MouseListener {
if (blockType == gate || blockType == exit2 || blockType == exit) { if (blockType == gate || blockType == exit2 || blockType == exit) {
// If the object in question can be opened (exit or gate) add it to the transitional animation buffer // If the object in question can be opened (exit or gate) add it to the transitional animation buffer
//System.out.print("Triggering screen " + currentScrn + " at pos " + clickedLoc); //System.out.print("Triggering screen " + currentScrn + " at pos " + clickedLoc);
boolean addTransition = false; boolean addTransition = true;
if (numTransition == 0) { if (numTransition > 0) {
addTransition = true;
} else {
addTransition = true;
for (int i = 1; i <= numTransition; i++) { for (int i = 1; i <= numTransition; i++) {
byte scrn = auxMem.readByte(trscrn + i); byte scrn = auxMem.readByte(trscrn + i);
byte loc = auxMem.readByte(trloc + i); byte loc = auxMem.readByte(trloc + i);

View File

@ -68,6 +68,7 @@ public class Configuration implements Reconfigurable {
return null; return null;
} }
@Override
public String getName() { public String getName() {
return "Configuration"; return "Configuration";
} }
@ -77,6 +78,7 @@ public class Configuration implements Reconfigurable {
return "cfg"; return "cfg";
} }
@Override
public void reconfigure() { public void reconfigure() {
} }

View File

@ -158,8 +158,4 @@ public abstract class CPU extends Device {
@Override @Override
public void attach() { public void attach() {
} }
@Override
public void detach() {
}
} }

View File

@ -65,6 +65,57 @@ public abstract class Card extends Device {
@Override @Override
public void attach() { public void attach() {
registerListeners();
}
@Override
public void detach() {
suspend();
unregisterListeners();
super.detach();
}
abstract protected void handleIOAccess(int register, RAMEvent.TYPE type, int value, RAMEvent e);
abstract protected void handleFirmwareAccess(int register, RAMEvent.TYPE type, int value, RAMEvent e);
abstract protected void handleC8FirmwareAccess(int register, RAMEvent.TYPE type, int value, RAMEvent e);
public int getSlot() {
return slot;
}
public void setSlot(int slot) {
this.slot = slot;
}
public PagedMemory getCxRom() {
return cxRom;
}
public PagedMemory getC8Rom() {
return c8Rom;
}
@Override
public void reconfigure() {
boolean restart = suspend();
unregisterListeners();
if (restart) {
resume();
}
registerListeners();
}
public void notifyVBLStateChanged(boolean state) {
// Do nothing unless overridden
}
public boolean suspendWithCPU() {
return false;
}
protected void registerListeners() {
ioListener = new RAMListener( ioListener = new RAMListener(
RAMEvent.TYPE.ANY, RAMEvent.TYPE.ANY,
RAMEvent.SCOPE.RANGE, RAMEvent.SCOPE.RANGE,
@ -106,11 +157,13 @@ public abstract class Card extends Device {
RAMEvent.TYPE.ANY, RAMEvent.TYPE.ANY,
RAMEvent.SCOPE.RANGE, RAMEvent.SCOPE.RANGE,
RAMEvent.VALUE.ANY) { RAMEvent.VALUE.ANY) {
@Override
protected void doConfig() { protected void doConfig() {
setScopeStart(slot * 256 + 0x00c800); setScopeStart(slot * 256 + 0x00c800);
setScopeEnd(slot * 256 + 0x00cfff); setScopeEnd(slot * 256 + 0x00cfff);
} }
@Override
protected void doEvent(RAMEvent e) { protected void doEvent(RAMEvent e) {
if (SoftSwitches.CXROM.getState() if (SoftSwitches.CXROM.getState()
|| computer.getMemory().getActiveSlot() != getSlot() || computer.getMemory().getActiveSlot() != getSlot()
@ -126,51 +179,9 @@ public abstract class Card extends Device {
computer.getMemory().addListener(c8firmwareListener); computer.getMemory().addListener(c8firmwareListener);
} }
@Override protected void unregisterListeners() {
public void detach() {
suspend();
computer.getMemory().removeListener(ioListener); computer.getMemory().removeListener(ioListener);
computer.getMemory().removeListener(firmwareListener); computer.getMemory().removeListener(firmwareListener);
computer.getMemory().removeListener(c8firmwareListener); computer.getMemory().removeListener(c8firmwareListener);
} }
abstract protected void handleIOAccess(int register, RAMEvent.TYPE type, int value, RAMEvent e);
abstract protected void handleFirmwareAccess(int register, RAMEvent.TYPE type, int value, RAMEvent e);
abstract protected void handleC8FirmwareAccess(int register, RAMEvent.TYPE type, int value, RAMEvent e);
public int getSlot() {
return slot;
}
public void setSlot(int slot) {
this.slot = slot;
}
public PagedMemory getCxRom() {
return cxRom;
}
public PagedMemory getC8Rom() {
return c8Rom;
}
@Override
public void reconfigure() {
boolean restart = suspend();
detach();
if (restart) {
resume();
}
attach();
}
public void notifyVBLStateChanged(boolean state) {
// Do nothing unless overridden
}
public boolean suspendWithCPU() {
return false;
}
} }

View File

@ -114,5 +114,7 @@ public abstract class Device implements Reconfigurable {
public abstract void attach(); public abstract void attach();
public abstract void detach(); public void detach() {
Keyboard.unregisterAllHandlers(this);
}
} }

View File

@ -98,11 +98,11 @@ public class Keyboard implements Reconfigurable {
if (!action.notifyOnRelease()) { if (!action.notifyOnRelease()) {
return false; return false;
} }
System.out.println("Key up: "+method.toString()); // System.out.println("Key up: "+method.toString());
Object returnValue = null; Object returnValue = null;
try { try {
if (method.getParameterCount() > 0) { if (method.getParameterCount() > 0) {
returnValue = method.invoke(isStatic ? null : owner, true); returnValue = method.invoke(isStatic ? null : owner, false);
} else { } else {
returnValue = method.invoke(isStatic ? null : owner); returnValue = method.invoke(isStatic ? null : owner);
} }
@ -117,7 +117,7 @@ public class Keyboard implements Reconfigurable {
@Override @Override
public boolean handleKeyDown(KeyEvent e) { public boolean handleKeyDown(KeyEvent e) {
System.out.println("Key down: "+method.toString()); // System.out.println("Key down: "+method.toString());
Object returnValue = null; Object returnValue = null;
try { try {
if (method.getParameterCount() > 0) { if (method.getParameterCount() > 0) {
@ -263,7 +263,7 @@ public class Keyboard implements Reconfigurable {
computer.resume(); computer.resume();
} }
@InvokableAction(name = "Closed Apple Key", alternatives = "CA", category = "Keyboard", notifyOnRelease = true, defaultKeyMapping = "Meta", consumeKeyEvent = false) @InvokableAction(name = "Closed Apple Key", alternatives = "CA", category = "Keyboard", notifyOnRelease = true, defaultKeyMapping = {"Shortcut","Meta","Command"}, consumeKeyEvent = false)
public void solidApple(boolean pressed) { public void solidApple(boolean pressed) {
computer.pause(); computer.pause();
SoftSwitches.PB1.getSwitch().setState(pressed); SoftSwitches.PB1.getSwitch().setState(pressed);

View File

@ -198,5 +198,6 @@ public class Motherboard extends TimedDevice {
}); });
miscDevices.clear(); miscDevices.clear();
// halt(); // halt();
super.detach();
} }
} }

View File

@ -218,6 +218,7 @@ public class SoundMixer extends Device {
} }
availableLines.clear(); availableLines.clear();
activeLines.clear(); activeLines.clear();
super.detach();
} }
private void initMixer() { private void initMixer() {

View File

@ -221,6 +221,8 @@ public class CardMockingboard extends Card implements Runnable {
resume(); resume();
} }
} }
/////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////
public static int[] VolTable; public static int[] VolTable;
int[][] buffers; int[][] buffers;

View File

@ -18,7 +18,6 @@
*/ */
package jace.hardware; package jace.hardware;
import jace.Emulator;
import jace.config.ConfigurableField; import jace.config.ConfigurableField;
import jace.config.Name; import jace.config.Name;
import jace.config.Reconfigurable; import jace.config.Reconfigurable;
@ -415,6 +414,7 @@ public class CardSSC extends Card implements Reconfigurable, Runnable {
/** /**
* Detach from server socket port and ensure that the card's resources are * Detach from server socket port and ensure that the card's resources are
* no longer in use * no longer in use
* @return
*/ */
@Override @Override
public boolean suspend() { public boolean suspend() {
@ -458,7 +458,6 @@ public class CardSSC extends Card implements Reconfigurable, Runnable {
} catch (IOException ex) { } catch (IOException ex) {
suspend(); suspend();
Logger.getLogger(CardSSC.class.getName()).log(Level.SEVERE, null, ex); Logger.getLogger(CardSSC.class.getName()).log(Level.SEVERE, null, ex);
ex.printStackTrace();
} }
} }
} }
@ -484,7 +483,6 @@ public class CardSSC extends Card implements Reconfigurable, Runnable {
@Override @Override
protected void handleFirmwareAccess(int register, TYPE type, int value, RAMEvent e) { protected void handleFirmwareAccess(int register, TYPE type, int value, RAMEvent e) {
// Do nothing -- the card rom does everything // Do nothing -- the card rom does everything
return;
} }
@Override @Override

View File

@ -18,7 +18,6 @@
*/ */
package jace.hardware; package jace.hardware;
import jace.Emulator;
import jace.apple2e.MOS65C02; import jace.apple2e.MOS65C02;
import jace.config.ConfigurableField; import jace.config.ConfigurableField;
import jace.config.Name; import jace.config.Name;

View File

@ -180,6 +180,7 @@ public class Joystick extends Device {
@Override @Override
public void detach() { public void detach() {
removeListeners(); removeListeners();
super.detach();
} }
@Override @Override

View File

@ -128,8 +128,7 @@ public class CardMassStorage extends Card implements MediaConsumerParent {
@Override @Override
public void reconfigure() { public void reconfigure() {
try { try {
detach(); unregisterListeners();
int pc = computer.getCpu().getProgramCounter(); int pc = computer.getCpu().getProgramCounter();
if (drive1.getCurrentDisk() != null && getSlot() == 7 && (pc == 0x0c65e || pc == 0x0c661)) { if (drive1.getCurrentDisk() != null && getSlot() == 7 && (pc == 0x0c65e || pc == 0x0c661)) {
// If the computer is in a loop trying to boot from cards 6, fast-boot from here instead // If the computer is in a loop trying to boot from cards 6, fast-boot from here instead
@ -139,7 +138,7 @@ public class CardMassStorage extends Card implements MediaConsumerParent {
Optional<Card>[] cards = computer.getMemory().getAllCards(); Optional<Card>[] cards = computer.getMemory().getAllCards();
cards[6].ifPresent(card->computer.getMotherboard().cancelSpeedRequest(card)); cards[6].ifPresent(card->computer.getMotherboard().cancelSpeedRequest(card));
} }
attach(); registerListeners();
} catch (IOException ex) { } catch (IOException ex) {
Logger.getLogger(CardMassStorage.class.getName()).log(Level.SEVERE, null, ex); Logger.getLogger(CardMassStorage.class.getName()).log(Level.SEVERE, null, ex);
} }
@ -255,6 +254,7 @@ public class CardMassStorage extends Card implements MediaConsumerParent {
} }
}; };
@Override
public MediaConsumer[] getConsumers() { public MediaConsumer[] getConsumers() {
return new MediaConsumer[]{drive1, drive2}; return new MediaConsumer[]{drive1, drive2};
} }

View File

@ -165,11 +165,6 @@ public abstract class R6522 extends Device {
// Start chip // Start chip
} }
@Override
public void detach() {
// Reset
}
@Override @Override
public void reconfigure() { public void reconfigure() {
// Reset // Reset