diff --git a/src/main/java/jace/JaceApplication.java b/src/main/java/jace/JaceApplication.java index abf8ffe..741435f 100644 --- a/src/main/java/jace/JaceApplication.java +++ b/src/main/java/jace/JaceApplication.java @@ -29,22 +29,6 @@ public class JaceApplication extends Application { JaceUIController controller; static boolean romStarted = false; - static RAMListener startListener = new RAMListener(RAMEvent.TYPE.EXECUTE, RAMEvent.SCOPE.ADDRESS, RAMEvent.VALUE.ANY) { - @Override - protected void doConfig() { - setScopeStart(0x0FA62); - } - - @Override - protected void doEvent(RAMEvent e) { - romStarted = true; - } - - @Override - public boolean isRelevant(RAMEvent e) { - return super.isRelevant(e); - } - }; @Override public void start(Stage stage) throws Exception { @@ -95,12 +79,16 @@ public class JaceApplication extends Application { * Start the computer and make sure it runs through the expected rom routine for cold boot */ private void bootWatchdog() { - Emulator.computer.getMemory().addListener(startListener); + romStarted = false; + RAMListener startListener = Emulator.computer.getMemory(). + observe(RAMEvent.TYPE.EXECUTE, 0x0FA62, (e)-> { + romStarted = true; + }); Emulator.computer.coldStart(); try { Thread.sleep(250); if (!romStarted) { - System.out.println("Boot not detected, performing a cold start"); + Logger.getLogger(getClass().getName()).log(Level.WARNING,"Boot not detected, performing a cold start"); Emulator.computer.coldStart(); } } catch (InterruptedException ex) { diff --git a/src/main/java/jace/apple2e/Apple2e.java b/src/main/java/jace/apple2e/Apple2e.java index 45bda56..5b24d83 100644 --- a/src/main/java/jace/apple2e/Apple2e.java +++ b/src/main/java/jace/apple2e/Apple2e.java @@ -425,19 +425,11 @@ public class Apple2e extends Computer { 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) { - animationTimer.schedule(drawHints, 1, TimeUnit.SECONDS); - animationSchedule = + hints.add(getMemory().observe(RAMEvent.TYPE.EXECUTE, 0x0FB63, (e)->{ + animationTimer.schedule(drawHints, 1, TimeUnit.SECONDS); + animationSchedule = animationTimer.scheduleAtFixedRate(doAnimation, 1250, 100, TimeUnit.MILLISECONDS); - } - }); + })); // Latch to the PRODOS SYNTAX CHECK parser /* hints.add(new RAMListener(RAMEvent.TYPE.EXECUTE, RAMEvent.SCOPE.ADDRESS, RAMEvent.VALUE.ANY) { @@ -458,9 +450,6 @@ public class Apple2e extends Computer { }); */ } - hints.stream().forEach((hint) -> { - getMemory().addListener(hint); - }); } private void disableHints() { @@ -473,8 +462,4 @@ public class Apple2e extends Computer { public String getShortName() { return "computer"; } - - private void attachMiscDevices() { - throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. - } } \ No newline at end of file diff --git a/src/main/java/jace/apple2e/Speaker.java b/src/main/java/jace/apple2e/Speaker.java index a162ed7..23bf18c 100644 --- a/src/main/java/jace/apple2e/Speaker.java +++ b/src/main/java/jace/apple2e/Speaker.java @@ -26,17 +26,17 @@ import jace.core.RAMEvent; import jace.core.RAMListener; import jace.core.SoundMixer; import java.io.File; +import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; -import java.util.logging.Level; -import java.util.logging.Logger; -import javax.sound.sampled.LineUnavailableException; -import javax.sound.sampled.SourceDataLine; -import java.io.FileNotFoundException; import java.util.Timer; import java.util.TimerTask; +import java.util.logging.Level; +import java.util.logging.Logger; import javafx.stage.FileChooser; +import javax.sound.sampled.LineUnavailableException; +import javax.sound.sampled.SourceDataLine; /** * Apple // Speaker Emulation Created on May 9, 2007, 9:55 PM @@ -58,8 +58,8 @@ public class Speaker extends Device { out = null; fileOutputActive = false; } else { - FileChooser fileChooser = new FileChooser(); - File f = fileChooser.showSaveDialog(null); + FileChooser fileChooser = new FileChooser(); + File f = fileChooser.showSaveDialog(null); if (f == null) { return; } @@ -93,7 +93,7 @@ public class Speaker extends Device { /** * Number of samples in buffer */ - static int BUFFER_SIZE = (int) (((float) SoundMixer.RATE) * 0.4); + static int BUFFER_SIZE = (int) (SoundMixer.RATE * 0.4); // Number of samples available in output stream before playback happens (avoid extra blocking) // static int MIN_PLAYBACK_BUFFER = BUFFER_SIZE / 2; static int MIN_PLAYBACK_BUFFER = 64; @@ -129,35 +129,13 @@ public class Speaker extends Device { byte[] secondaryBuffer; int bufferPos = 0; Timer playbackTimer; - private double TICKS_PER_SAMPLE = ((double) Motherboard.SPEED) / ((double) SoundMixer.RATE); - private double TICKS_PER_SAMPLE_FLOOR = Math.floor(TICKS_PER_SAMPLE); - private final RAMListener listener - = new RAMListener(RAMEvent.TYPE.ANY, RAMEvent.SCOPE.RANGE, RAMEvent.VALUE.ANY) { - - @Override - public boolean isRelevant(RAMEvent e) { - return true; - } - - @Override - protected void doConfig() { - setScopeStart(0x0C030); - setScopeEnd(0x0C03F); - } - - @Override - protected void doEvent(RAMEvent e) { - if (e.getType() == RAMEvent.TYPE.WRITE) { - level += 2; - } else { - speakerBit = !speakerBit; - } - resetIdle(); - } - }; + private final double TICKS_PER_SAMPLE = ((double) Motherboard.SPEED) / SoundMixer.RATE; + private final double TICKS_PER_SAMPLE_FLOOR = Math.floor(TICKS_PER_SAMPLE); + private RAMListener listener = null; /** * Creates a new instance of Speaker + * * @param computer */ public Speaker(Computer computer) { @@ -186,11 +164,12 @@ public class Speaker extends Device { */ @Override public void resume() { - if (sdl != null && isRunning()) return; - System.out.println("Resuming speaker sound"); + if (sdl != null && isRunning()) { + return; + } try { if (sdl == null || !sdl.isOpen()) { - sdl = computer.mixer.getLine(this); + sdl = computer.mixer.getLine(this); } sdl.start(); setRun(true); @@ -199,14 +178,14 @@ public class Speaker extends Device { level = 0; bufferPos = 0; playbackTimer = new Timer(); - playbackTimer.scheduleAtFixedRate(new TimerTask() { + playbackTimer.scheduleAtFixedRate(new TimerTask() { @Override public void run() { playCurrentBuffer(); } }, 10, 30); } catch (LineUnavailableException ex) { - System.out.println("ERROR: Could not output sound: " + ex.getMessage()); + Logger.getLogger(getClass().getName()).log(Level.SEVERE, "ERROR: Could not output sound", ex); } } @@ -275,11 +254,20 @@ public class Speaker extends Device { } } + private void toggleSpeaker(RAMEvent e) { + if (e.getType() == RAMEvent.TYPE.WRITE) { + level += 2; + } else { + speakerBit = !speakerBit; + } + resetIdle(); + } + /** * Add a memory event listener for C03x for capturing speaker events */ private void configureListener() { - computer.getMemory().addListener(listener); + listener = computer.getMemory().observe(RAMEvent.TYPE.ANY, 0x0c030, 0x0c03f, this::toggleSpeaker); } private void removeListener() { diff --git a/src/main/java/jace/apple2e/VideoDHGR.java b/src/main/java/jace/apple2e/VideoDHGR.java index 9f9da03..5fccd57 100644 --- a/src/main/java/jace/apple2e/VideoDHGR.java +++ b/src/main/java/jace/apple2e/VideoDHGR.java @@ -22,8 +22,10 @@ import jace.core.Computer; import jace.core.Font; import jace.core.Palette; import jace.core.RAMEvent; -import jace.core.RAMListener; import jace.core.Video; +import static jace.core.Video.hiresOffset; +import static jace.core.Video.hiresRowLookup; +import static jace.core.Video.textRowLookup; import jace.core.VideoWriter; import java.util.logging.Logger; import javafx.scene.image.PixelWriter; @@ -69,6 +71,7 @@ public class VideoDHGR extends Video { /** * Creates a new instance of VideoDHGR + * * @param computer */ public VideoDHGR(Computer computer) { @@ -681,47 +684,31 @@ public class VideoDHGR extends Video { } } + private void registerTextDirtyFlag(RAMEvent e) { + int row = textRowLookup[e.getAddress() & 0x03ff]; + if (row > 23) { + return; + } + VideoWriter tmark = (e.getAddress() < 0x0800) ? textPage1 : textPage2; + row <<= 3; + int yy = row + 8; + for (int y = row; y < yy; y++) { + tmark.markDirty(y); + } + } + + private void registerHiresDirtyFlag(RAMEvent e) { + int row = hiresRowLookup[e.getAddress() & 0x01fff]; + if (row < 0 || row >= 192) { + return; + } + VideoWriter mark = (e.getAddress() < 0x04000) ? hiresPage1 : hiresPage2; + mark.markDirty(row); + } + private void registerDirtyFlagChecks() { - ((RAM128k) computer.getMemory()).addListener(new RAMListener(RAMEvent.TYPE.WRITE, RAMEvent.SCOPE.RANGE, RAMEvent.VALUE.ANY) { - @Override - protected void doConfig() { - setScopeStart(0x0400); - setScopeEnd(0x0bff); - } - - @Override - protected void doEvent(RAMEvent e) { - int row = textRowLookup[e.getAddress() & 0x03ff]; -// int row = identifyTextRow(e.getAddress() & 0x03ff); - if (row > 23) { - return; - } - VideoWriter tmark = (e.getAddress() < 0x0800) ? textPage1 : textPage2; - row <<= 3; - int yy = row + 8; - for (int y = row; y < yy; y++) { - tmark.markDirty(y); - } - } - }); - ((RAM128k) computer.getMemory()).addListener(new RAMListener(RAMEvent.TYPE.WRITE, RAMEvent.SCOPE.RANGE, RAMEvent.VALUE.ANY) { - @Override - protected void doConfig() { - setScopeStart(0x2000); - setScopeEnd(0x5fff); - } - - @Override - protected void doEvent(RAMEvent e) { - int row = hiresRowLookup[e.getAddress() & 0x01fff]; -// int row = identifyHiresRow(e.getAddress() & 0x03fff); - if (row < 0 || row >= 192) { - return; - } - VideoWriter mark = (e.getAddress() < 0x04000) ? hiresPage1 : hiresPage2; - mark.markDirty(row); - } - }); + computer.getMemory().observe(RAMEvent.TYPE.WRITE, 0x0400, 0x0bff, this::registerTextDirtyFlag); + computer.getMemory().observe(RAMEvent.TYPE.WRITE, 0x02000, 0x05fff, this::registerHiresDirtyFlag); } @Override diff --git a/src/main/java/jace/apple2e/VideoNTSC.java b/src/main/java/jace/apple2e/VideoNTSC.java index a6919e1..a806c9d 100644 --- a/src/main/java/jace/apple2e/VideoNTSC.java +++ b/src/main/java/jace/apple2e/VideoNTSC.java @@ -18,11 +18,12 @@ */ package jace.apple2e; +import static jace.apple2e.VideoDHGR.BLACK; import jace.config.ConfigurableField; import jace.core.Computer; +import jace.core.RAM; import jace.core.RAMEvent; import jace.core.RAMListener; -import jace.core.Video; import java.util.Arrays; import java.util.HashSet; import java.util.Set; @@ -64,7 +65,7 @@ public class VideoNTSC extends VideoDHGR { public VideoNTSC(Computer computer) { super(computer); - createStateListeners(); + registerStateListeners(); } @Override @@ -269,7 +270,7 @@ public class VideoNTSC extends VideoDHGR { col = ((col & 8) >> 3) | ((col << 1) & 0x0f); } double y1 = YIQ_VALUES[col][0]; - double y2 = ((double) level / (double) maxLevel); + double y2 = (level / (double) maxLevel); SOLID_PALETTE[offset][pattern] = yiqToRgb(y1, YIQ_VALUES[col][1] * MAX_I, YIQ_VALUES[col][2] * MAX_Q); TEXT_PALETTE[offset][pattern] = yiqToRgb(y2, YIQ_VALUES[col][1] * MAX_I, YIQ_VALUES[col][2] * MAX_Q); } @@ -325,113 +326,61 @@ public class VideoNTSC extends VideoDHGR { } boolean f1 = true; boolean f2 = true; - boolean an3 = true; + boolean an3 = false; + + public void rgbStateChange() { - public void rgbStateChange(ModeStateChanges state) { - switch (state) { - case CLEAR_80: - break; - case CLEAR_AN3: - an3 = false; - break; - case SET_80: - break; - case SET_AN3: - if (!an3) { - f2 = f1; - f1 = SoftSwitches._80COL.getState(); - } - an3 = true; - break; - } // This is the more technically correct implementation except for two issues: // 1) 160-column mode isn't implemented so it's not worth bothering to capture that state // 2) A lot of programs are clueless about RGB modes so it's good to default to normal color mode // graphicsMode = f1 ? (f2 ? rgbMode.color : rgbMode.mix) : (f2 ? rgbMode._160col : rgbMode.bw); graphicsMode = f1 ? (f2 ? rgbMode.COLOR : rgbMode.MIX) : (f2 ? rgbMode.COLOR : rgbMode.BW); -// System.out.println(state + ": "+ graphicsMode); } // These catch changes to the RGB mode to toggle between color, BW and mixed Set rgbStateListeners = new HashSet<>(); - private void createStateListeners() { - rgbStateListeners.add(new RAMListener(RAMEvent.TYPE.ANY, RAMEvent.SCOPE.ADDRESS, RAMEvent.VALUE.ANY) { - @Override - protected void doConfig() { - setScopeStart(0x0c05e); + private void registerStateListeners() { + if (!rgbStateListeners.isEmpty() || computer.getVideo() != this) { + return; + } + RAM memory = computer.getMemory(); + rgbStateListeners.add(memory.observe(RAMEvent.TYPE.ANY, 0x0c05e, (e) -> { + an3 = false; + rgbStateChange(); + })); + rgbStateListeners.add(memory.observe(RAMEvent.TYPE.ANY, 0x0c05f, (e) -> { + if (!an3) { + f2 = f1; + f1 = SoftSwitches._80COL.getState(); } - - @Override - protected void doEvent(RAMEvent e) { - Video v = computer.getVideo(); - if (v instanceof VideoNTSC) { - ((VideoNTSC) v).rgbStateChange(ModeStateChanges.CLEAR_AN3); - } - } - }); - rgbStateListeners.add(new RAMListener(RAMEvent.TYPE.ANY, RAMEvent.SCOPE.ADDRESS, RAMEvent.VALUE.ANY) { - @Override - protected void doConfig() { - setScopeStart(0x0c05f); - } - - @Override - protected void doEvent(RAMEvent e) { - Video v = computer.getVideo(); - if (v instanceof VideoNTSC) { - ((VideoNTSC) v).rgbStateChange(ModeStateChanges.SET_AN3); - } - } - }); - rgbStateListeners.add(new RAMListener(RAMEvent.TYPE.EXECUTE, RAMEvent.SCOPE.ADDRESS, RAMEvent.VALUE.ANY) { - @Override - protected void doConfig() { - setScopeStart(0x0fa62); - } - - @Override - protected void doEvent(RAMEvent e) { - Video v = computer.getVideo(); - if (v instanceof VideoNTSC) { - // When reset hook is called, reset the graphics mode - // This is useful in case a program is running that - // is totally clueless how to set the RGB state correctly. - ((VideoNTSC) v).f1 = true; - ((VideoNTSC) v).f2 = true; - ((VideoNTSC) v).an3 = false; - ((VideoNTSC) v).graphicsMode = rgbMode.COLOR; - } - } - }); - rgbStateListeners.add(new RAMListener(RAMEvent.TYPE.WRITE, RAMEvent.SCOPE.ADDRESS, RAMEvent.VALUE.ANY) { - @Override - protected void doConfig() { - setScopeStart(0x0c00d); - } - - @Override - protected void doEvent(RAMEvent e) { - Video v = computer.getVideo(); - if (v instanceof VideoNTSC) { - ((VideoNTSC) v).rgbStateChange(ModeStateChanges.SET_80); - } - } - }); + an3 = true; + rgbStateChange(); + })); + rgbStateListeners.add(memory.observe(RAMEvent.TYPE.EXECUTE, 0x0fa62, (e) -> { + // When reset hook is called, reset the graphics mode + // This is useful in case a program is running that + // is totally clueless how to set the RGB state correctly. + f1 = true; + f2 = true; + an3 = false; + graphicsMode = rgbMode.COLOR; + rgbStateChange(); + })); } @Override + public void detach() { rgbStateListeners.stream().forEach((l) -> { computer.getMemory().removeListener(l); }); + rgbStateListeners.clear(); super.detach(); } @Override public void attach() { super.attach(); - rgbStateListeners.stream().forEach((l) -> { - computer.getMemory().addListener(l); - }); + registerStateListeners(); } } diff --git a/src/main/java/jace/core/Card.java b/src/main/java/jace/core/Card.java index 3cd15d9..6eb6301 100644 --- a/src/main/java/jace/core/Card.java +++ b/src/main/java/jace/core/Card.java @@ -31,7 +31,7 @@ import jace.apple2e.SoftSwitches; * synchronization. * Created on February 1, 2007, 5:35 PM * - * @author Brendan Robert (BLuRry) brendan.robert@gmail.com + * @author Brendan Robert (BLuRry) brendan.robert@gmail.com */ public abstract class Card extends Device { @@ -44,6 +44,7 @@ public abstract class Card extends Device { /** * Creates a new instance of Card + * * @param computer */ public Card(Computer computer) { @@ -117,72 +118,32 @@ public abstract class Card extends Device { } protected void registerListeners() { - ioListener = new RAMListener( - RAMEvent.TYPE.ANY, - RAMEvent.SCOPE.RANGE, - RAMEvent.VALUE.ANY) { - @Override - protected void doConfig() { - setScopeStart(slot * 16 + 0x00c080); - setScopeEnd(slot * 16 + 0x00c08F); - } + RAM memory = computer.getMemory(); + int baseIO = 0x0c080 + slot * 16; + int baseRom = 0x0c000 + slot * 256; + ioListener = memory.observe(RAMEvent.TYPE.ANY, baseIO, baseIO + 15, (e) -> { + int address = e.getAddress() & 0x0f; + handleIOAccess(address, e.getType(), e.getNewValue(), e); + }); - @Override - protected void doEvent(RAMEvent e) { - int address = e.getAddress() & 0x0f; - handleIOAccess(address, e.getType(), e.getNewValue(), e); - } - }; - - firmwareListener = new RAMListener( - RAMEvent.TYPE.ANY, - RAMEvent.SCOPE.RANGE, - RAMEvent.VALUE.ANY) { - @Override - protected void doConfig() { - setScopeStart(slot * 256 + 0x00c000); - setScopeEnd(slot * 256 + 0x00c0ff); - } - - @Override - protected void doEvent(RAMEvent e) { - computer.getMemory().setActiveCard(slot); - if (SoftSwitches.CXROM.getState()) { - return; - } + firmwareListener = memory.observe(RAMEvent.TYPE.ANY, baseRom, baseRom + 255, (e) -> { + computer.getMemory().setActiveCard(slot); + if (SoftSwitches.CXROM.isOff()) { handleFirmwareAccess(e.getAddress() & 0x0ff, e.getType(), e.getNewValue(), e); } - }; + }); - c8firmwareListener = new RAMListener( - RAMEvent.TYPE.ANY, - RAMEvent.SCOPE.RANGE, - RAMEvent.VALUE.ANY) { - @Override - protected void doConfig() { - setScopeStart(slot * 256 + 0x00c800); - setScopeEnd(slot * 256 + 0x00cfff); - } - - @Override - protected void doEvent(RAMEvent e) { - if (SoftSwitches.CXROM.getState() - || computer.getMemory().getActiveSlot() != getSlot() - || SoftSwitches.INTC8ROM.getState()) { - return; - } + c8firmwareListener = memory.observe(RAMEvent.TYPE.ANY, 0xc800, 0xcfff, (e) -> { + if (SoftSwitches.CXROM.isOff() && SoftSwitches.INTC8ROM.isOff() + && computer.getMemory().getActiveSlot() == slot) { handleC8FirmwareAccess(e.getAddress() - 0x0c800, e.getType(), e.getNewValue(), e); } - }; - - computer.getMemory().addListener(ioListener); - computer.getMemory().addListener(firmwareListener); - computer.getMemory().addListener(c8firmwareListener); + }); } protected void unregisterListeners() { computer.getMemory().removeListener(ioListener); computer.getMemory().removeListener(firmwareListener); computer.getMemory().removeListener(c8firmwareListener); - } -} \ No newline at end of file + } +} diff --git a/src/main/java/jace/core/RAM.java b/src/main/java/jace/core/RAM.java index 6bfc182..1687b06 100644 --- a/src/main/java/jace/core/RAM.java +++ b/src/main/java/jace/core/RAM.java @@ -105,30 +105,28 @@ public abstract class RAM implements Reconfigurable { abstract public void configureActiveMemory(); - public byte write(int address, byte b, boolean generateEvent, boolean requireSynchronization) { + public void write(int address, byte b, boolean generateEvent, boolean requireSynchronization) { byte[] page = activeWrite.getMemoryPage(address); - byte old = 0; if (page == null) { if (generateEvent) { - callListener(RAMEvent.TYPE.WRITE, address, old, b, requireSynchronization); + callListener(RAMEvent.TYPE.WRITE, address, 0, b, requireSynchronization); } } else { int offset = address & 0x0FF; - old = page[offset]; + byte old = page[offset]; if (generateEvent) { - b = callListener(RAMEvent.TYPE.WRITE, address, old, b, requireSynchronization); + page[offset] = callListener(RAMEvent.TYPE.WRITE, address, old, b, requireSynchronization); + } else { + page[offset] = b; } - page[offset] = b; } - return old; } public void writeWord(int address, int w, boolean generateEvent, boolean requireSynchronization) { - int lsb = write(address, (byte) (w & 0x0ff), generateEvent, requireSynchronization); - int msb = write(address + 1, (byte) (w >> 8), generateEvent, requireSynchronization); -// int oldValue = msb << 8 + lsb; + write(address, (byte) (w & 0x0ff), generateEvent, requireSynchronization); + write(address + 1, (byte) (w >> 8), generateEvent, requireSynchronization); } - + public byte readRaw(int address) { // if (address >= 65536) return 0; return activeRead.getMemoryPage(address)[address & 0x0FF]; @@ -236,7 +234,7 @@ public abstract class RAM implements Reconfigurable { } public RAMListener observe(RAMEvent.TYPE type, int addressStart, int addressEnd, RAMEvent.RAMEventHandler handler) { - return addListener(new RAMListener(type, RAMEvent.SCOPE.ADDRESS, RAMEvent.VALUE.ANY) { + return addListener(new RAMListener(type, RAMEvent.SCOPE.RANGE, RAMEvent.VALUE.ANY) { @Override protected void doConfig() { setScopeStart(addressStart); @@ -251,7 +249,7 @@ public abstract class RAM implements Reconfigurable { } public RAMListener observe(RAMEvent.TYPE type, int addressStart, int addressEnd, boolean auxFlag, RAMEvent.RAMEventHandler handler) { - return addListener(new RAMListener(type, RAMEvent.SCOPE.ADDRESS, RAMEvent.VALUE.ANY) { + return addListener(new RAMListener(type, RAMEvent.SCOPE.RANGE, RAMEvent.VALUE.ANY) { @Override protected void doConfig() { setScopeStart(addressStart); @@ -334,40 +332,6 @@ public abstract class RAM implements Reconfigurable { abstract protected void loadRom(String path) throws IOException; - public void dump() { - for (int i = 0; i < 0x0FFFF; i += 16) { - System.out.print(Integer.toString(i, 16)); - System.out.print(":"); - String part1 = ""; - String part2 = ""; - for (int j = 0; j < 16; j++) { - int a = i + j; - int br = 0x0FF & activeRead.getMemory()[i >> 8][i & 0x0ff]; - String s1 = Integer.toString(br, 16); - System.out.print(' '); - if (s1.length() == 1) { - System.out.print('0'); - } - System.out.print(s1); - - /* - try { - int bw = 0; - bw = 0x0FF & activeWrite.getMemory().get(a/256)[a%256]; - String s2 = (br == bw) ? "**" : Integer.toString(bw,16); - System.out.print(' '); - if (s2.length()==1) System.out.print('0'); - System.out.print(s2); - } catch (NullPointerException ex) { - System.out.print(" --"); - } - */ - } - System.out.println(); -// System.out.println(Integer.toString(i, 16)+":"+part1+" -> "+part2); - } - } - abstract public void attach(); abstract public void detach(); diff --git a/src/main/java/jace/hardware/CardRamworks.java b/src/main/java/jace/hardware/CardRamworks.java index e1baad6..7e6549f 100644 --- a/src/main/java/jace/hardware/CardRamworks.java +++ b/src/main/java/jace/hardware/CardRamworks.java @@ -117,8 +117,11 @@ public class CardRamworks extends RAM128k { public void reconfigure() { boolean resume = computer.pause(); maxBank = memorySize / 64; - if (maxBank < 1) maxBank = 1; - if (maxBank > 128) maxBank = 128; + if (maxBank < 1) { + maxBank = 1; + } else if (maxBank > 128) { + maxBank = 128; + } for (int i = memory.size(); i < maxBank; i++) { memory.add(null); } @@ -127,23 +130,14 @@ public class CardRamworks extends RAM128k { computer.resume(); } } - RAMListener bankSelectListener = new RAMListener(RAMEvent.TYPE.WRITE, RAMEvent.SCOPE.ADDRESS, RAMEvent.VALUE.ANY) { - @Override - protected void doConfig() { - setScopeStart(BANK_SELECT); - setScopeEnd(BANK_SELECT); - } - - @Override - protected void doEvent(RAMEvent e) { - currentBank = e.getNewValue(); - configureActiveMemory(); - } - }; + private RAMListener bankSelectListener; @Override public void attach() { - addListener(bankSelectListener); + bankSelectListener = computer.getMemory().observe(RAMEvent.TYPE.WRITE, BANK_SELECT, (e) -> { + currentBank = e.getNewValue(); + configureActiveMemory(); + }); } @Override diff --git a/src/main/java/jace/hardware/Joystick.java b/src/main/java/jace/hardware/Joystick.java index 7719dfb..cfd413f 100644 --- a/src/main/java/jace/hardware/Joystick.java +++ b/src/main/java/jace/hardware/Joystick.java @@ -46,6 +46,7 @@ import java.util.logging.Logger; */ @Stateful public class Joystick extends Device { + @ConfigurableField(name = "Center Mouse", shortName = "center", description = "Moves mouse back to the center of the screen, can get annoying.") public boolean centerMouse = false; @ConfigurableField(name = "Use keyboard", shortName = "useKeys", description = "Arrow keys will control joystick instead of the mouse.") @@ -91,8 +92,8 @@ public class Joystick extends Device { private void readJoystick() { if (useKeyboard) { - joyX = (leftPressed ? -128 : 0) + (rightPressed ? 255:128); - joyY = (upPressed ? -128 : 0) + (downPressed ? 255:128); + joyX = (leftPressed ? -128 : 0) + (rightPressed ? 255 : 128); + joyY = (upPressed ? -128 : 0) + (downPressed ? 255 : 128); } else { Point l = MouseInfo.getPointerInfo().getLocation(); if (l.x < lastMouseLocation.x) { @@ -187,29 +188,12 @@ public class Joystick extends Device { y = 0; registerListeners(); } - - RAMListener listener = new RAMListener(RAMEvent.TYPE.ANY, RAMEvent.SCOPE.RANGE, RAMEvent.VALUE.ANY) { - @Override - protected void doConfig() { - setScopeStart(0x0C070); - setScopeEnd(0x0C07f); - } - - @Override - protected void doEvent(RAMEvent e) { - readJoystick(); - xSwitch.setState(true); - x = 10 + joyX * 11; - ySwitch.setState(true); - y = 10 + joyY * 11; - e.setNewValue(computer.getVideo().getFloatingBus()); - resume(); - } - }; @InvokableAction(name = "Left", category = "joystick", defaultKeyMapping = "left", notifyOnRelease = true) public boolean joystickLeft(boolean pressed) { - if (!useKeyboard) return false; + if (!useKeyboard) { + return false; + } leftPressed = pressed; if (pressed) { rightPressed = false; @@ -220,7 +204,9 @@ public class Joystick extends Device { ; @InvokableAction(name = "Right", category = "joystick", defaultKeyMapping = "right", notifyOnRelease = true) public boolean joystickRight(boolean pressed) { - if (!useKeyboard) return false; + if (!useKeyboard) { + return false; + } rightPressed = pressed; if (pressed) { leftPressed = false; @@ -231,7 +217,9 @@ public class Joystick extends Device { ; @InvokableAction(name = "Up", category = "joystick", defaultKeyMapping = "up", notifyOnRelease = true) public boolean joystickUp(boolean pressed) { - if (!useKeyboard) return false; + if (!useKeyboard) { + return false; + } upPressed = pressed; if (pressed) { downPressed = false; @@ -242,7 +230,9 @@ public class Joystick extends Device { ; @InvokableAction(name = "Down", category = "joystick", defaultKeyMapping = "down", notifyOnRelease = true) public boolean joystickDown(boolean pressed) { - if (!useKeyboard) return false; + if (!useKeyboard) { + return false; + } downPressed = pressed; if (pressed) { upPressed = false; @@ -250,12 +240,23 @@ public class Joystick extends Device { return hogKeyboard; } + public void initJoystickRead(RAMEvent e) { + readJoystick(); + xSwitch.setState(true); + x = 10 + joyX * 11; + ySwitch.setState(true); + y = 10 + joyY * 11; + e.setNewValue(computer.getVideo().getFloatingBus()); + resume(); + } + + RAMListener listener; + private void registerListeners() { - computer.getMemory().addListener(listener); + listener = computer.getMemory().observe(RAMEvent.TYPE.ANY, 0x0c070, 0x0c07f, this::initJoystickRead); } private void removeListeners() { computer.getMemory().removeListener(listener); -// Keyboard.unregisterAllHandlers(this); } }