Lambda simplification and code cleanup

This commit is contained in:
Brendan Robert 2015-08-15 22:57:49 -05:00
parent 5c0855d966
commit e7f731900a
9 changed files with 170 additions and 353 deletions

View File

@ -29,22 +29,6 @@ public class JaceApplication extends Application {
JaceUIController controller; JaceUIController controller;
static boolean romStarted = false; 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 @Override
public void start(Stage stage) throws Exception { 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 * Start the computer and make sure it runs through the expected rom routine for cold boot
*/ */
private void bootWatchdog() { 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(); Emulator.computer.coldStart();
try { try {
Thread.sleep(250); Thread.sleep(250);
if (!romStarted) { 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(); Emulator.computer.coldStart();
} }
} catch (InterruptedException ex) { } catch (InterruptedException ex) {

View File

@ -425,19 +425,11 @@ public class Apple2e extends Computer {
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(getMemory().observe(RAMEvent.TYPE.EXECUTE, 0x0FB63, (e)->{
@Override animationTimer.schedule(drawHints, 1, TimeUnit.SECONDS);
protected void doConfig() { animationSchedule =
setScopeStart(0x0FB63);
}
@Override
protected void doEvent(RAMEvent e) {
animationTimer.schedule(drawHints, 1, TimeUnit.SECONDS);
animationSchedule =
animationTimer.scheduleAtFixedRate(doAnimation, 1250, 100, TimeUnit.MILLISECONDS); animationTimer.scheduleAtFixedRate(doAnimation, 1250, 100, TimeUnit.MILLISECONDS);
} }));
});
// Latch to the PRODOS SYNTAX CHECK parser // Latch to the PRODOS SYNTAX CHECK parser
/* /*
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) {
@ -458,9 +450,6 @@ public class Apple2e extends Computer {
}); });
*/ */
} }
hints.stream().forEach((hint) -> {
getMemory().addListener(hint);
});
} }
private void disableHints() { private void disableHints() {
@ -473,8 +462,4 @@ public class Apple2e extends Computer {
public String getShortName() { public String getShortName() {
return "computer"; return "computer";
} }
private void attachMiscDevices() {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
} }

View File

@ -26,17 +26,17 @@ import jace.core.RAMEvent;
import jace.core.RAMListener; import jace.core.RAMListener;
import jace.core.SoundMixer; import jace.core.SoundMixer;
import java.io.File; import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStream; 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.Timer;
import java.util.TimerTask; import java.util.TimerTask;
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.stage.FileChooser; 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 * Apple // Speaker Emulation Created on May 9, 2007, 9:55 PM
@ -58,8 +58,8 @@ public class Speaker extends Device {
out = null; out = null;
fileOutputActive = false; fileOutputActive = false;
} else { } else {
FileChooser fileChooser = new FileChooser(); FileChooser fileChooser = new FileChooser();
File f = fileChooser.showSaveDialog(null); File f = fileChooser.showSaveDialog(null);
if (f == null) { if (f == null) {
return; return;
} }
@ -93,7 +93,7 @@ public class Speaker extends Device {
/** /**
* Number of samples in buffer * 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) // 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 = BUFFER_SIZE / 2;
static int MIN_PLAYBACK_BUFFER = 64; static int MIN_PLAYBACK_BUFFER = 64;
@ -129,35 +129,13 @@ public class Speaker extends Device {
byte[] secondaryBuffer; byte[] secondaryBuffer;
int bufferPos = 0; int bufferPos = 0;
Timer playbackTimer; Timer playbackTimer;
private double TICKS_PER_SAMPLE = ((double) Motherboard.SPEED) / ((double) SoundMixer.RATE); private final double TICKS_PER_SAMPLE = ((double) Motherboard.SPEED) / SoundMixer.RATE;
private double TICKS_PER_SAMPLE_FLOOR = Math.floor(TICKS_PER_SAMPLE); private final double TICKS_PER_SAMPLE_FLOOR = Math.floor(TICKS_PER_SAMPLE);
private final RAMListener listener private RAMListener listener = null;
= 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();
}
};
/** /**
* Creates a new instance of Speaker * Creates a new instance of Speaker
*
* @param computer * @param computer
*/ */
public Speaker(Computer computer) { public Speaker(Computer computer) {
@ -186,11 +164,12 @@ public class Speaker extends Device {
*/ */
@Override @Override
public void resume() { public void resume() {
if (sdl != null && isRunning()) return; if (sdl != null && isRunning()) {
System.out.println("Resuming speaker sound"); return;
}
try { try {
if (sdl == null || !sdl.isOpen()) { if (sdl == null || !sdl.isOpen()) {
sdl = computer.mixer.getLine(this); sdl = computer.mixer.getLine(this);
} }
sdl.start(); sdl.start();
setRun(true); setRun(true);
@ -199,14 +178,14 @@ public class Speaker extends Device {
level = 0; level = 0;
bufferPos = 0; bufferPos = 0;
playbackTimer = new Timer(); playbackTimer = new Timer();
playbackTimer.scheduleAtFixedRate(new TimerTask() { playbackTimer.scheduleAtFixedRate(new TimerTask() {
@Override @Override
public void run() { public void run() {
playCurrentBuffer(); playCurrentBuffer();
} }
}, 10, 30); }, 10, 30);
} catch (LineUnavailableException ex) { } 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 * Add a memory event listener for C03x for capturing speaker events
*/ */
private void configureListener() { private void configureListener() {
computer.getMemory().addListener(listener); listener = computer.getMemory().observe(RAMEvent.TYPE.ANY, 0x0c030, 0x0c03f, this::toggleSpeaker);
} }
private void removeListener() { private void removeListener() {

View File

@ -22,8 +22,10 @@ import jace.core.Computer;
import jace.core.Font; import jace.core.Font;
import jace.core.Palette; import jace.core.Palette;
import jace.core.RAMEvent; import jace.core.RAMEvent;
import jace.core.RAMListener;
import jace.core.Video; 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 jace.core.VideoWriter;
import java.util.logging.Logger; import java.util.logging.Logger;
import javafx.scene.image.PixelWriter; import javafx.scene.image.PixelWriter;
@ -69,6 +71,7 @@ public class VideoDHGR extends Video {
/** /**
* Creates a new instance of VideoDHGR * Creates a new instance of VideoDHGR
*
* @param computer * @param computer
*/ */
public VideoDHGR(Computer 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() { private void registerDirtyFlagChecks() {
((RAM128k) computer.getMemory()).addListener(new RAMListener(RAMEvent.TYPE.WRITE, RAMEvent.SCOPE.RANGE, RAMEvent.VALUE.ANY) { computer.getMemory().observe(RAMEvent.TYPE.WRITE, 0x0400, 0x0bff, this::registerTextDirtyFlag);
@Override computer.getMemory().observe(RAMEvent.TYPE.WRITE, 0x02000, 0x05fff, this::registerHiresDirtyFlag);
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);
}
});
} }
@Override @Override

View File

@ -18,11 +18,12 @@
*/ */
package jace.apple2e; package jace.apple2e;
import static jace.apple2e.VideoDHGR.BLACK;
import jace.config.ConfigurableField; import jace.config.ConfigurableField;
import jace.core.Computer; import jace.core.Computer;
import jace.core.RAM;
import jace.core.RAMEvent; import jace.core.RAMEvent;
import jace.core.RAMListener; import jace.core.RAMListener;
import jace.core.Video;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;
@ -64,7 +65,7 @@ public class VideoNTSC extends VideoDHGR {
public VideoNTSC(Computer computer) { public VideoNTSC(Computer computer) {
super(computer); super(computer);
createStateListeners(); registerStateListeners();
} }
@Override @Override
@ -269,7 +270,7 @@ public class VideoNTSC extends VideoDHGR {
col = ((col & 8) >> 3) | ((col << 1) & 0x0f); col = ((col & 8) >> 3) | ((col << 1) & 0x0f);
} }
double y1 = YIQ_VALUES[col][0]; 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); 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); 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 f1 = true;
boolean f2 = 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: // 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 // 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 // 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._160col : rgbMode.bw);
graphicsMode = f1 ? (f2 ? rgbMode.COLOR : rgbMode.MIX) : (f2 ? rgbMode.COLOR : 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 // These catch changes to the RGB mode to toggle between color, BW and mixed
Set<RAMListener> rgbStateListeners = new HashSet<>(); Set<RAMListener> rgbStateListeners = new HashSet<>();
private void createStateListeners() { private void registerStateListeners() {
rgbStateListeners.add(new RAMListener(RAMEvent.TYPE.ANY, RAMEvent.SCOPE.ADDRESS, RAMEvent.VALUE.ANY) { if (!rgbStateListeners.isEmpty() || computer.getVideo() != this) {
@Override return;
protected void doConfig() { }
setScopeStart(0x0c05e); 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();
} }
an3 = true;
@Override rgbStateChange();
protected void doEvent(RAMEvent e) { }));
Video v = computer.getVideo(); rgbStateListeners.add(memory.observe(RAMEvent.TYPE.EXECUTE, 0x0fa62, (e) -> {
if (v instanceof VideoNTSC) { // When reset hook is called, reset the graphics mode
((VideoNTSC) v).rgbStateChange(ModeStateChanges.CLEAR_AN3); // This is useful in case a program is running that
} // is totally clueless how to set the RGB state correctly.
} f1 = true;
}); f2 = true;
rgbStateListeners.add(new RAMListener(RAMEvent.TYPE.ANY, RAMEvent.SCOPE.ADDRESS, RAMEvent.VALUE.ANY) { an3 = false;
@Override graphicsMode = rgbMode.COLOR;
protected void doConfig() { rgbStateChange();
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);
}
}
});
} }
@Override @Override
public void detach() { public void detach() {
rgbStateListeners.stream().forEach((l) -> { rgbStateListeners.stream().forEach((l) -> {
computer.getMemory().removeListener(l); computer.getMemory().removeListener(l);
}); });
rgbStateListeners.clear();
super.detach(); super.detach();
} }
@Override @Override
public void attach() { public void attach() {
super.attach(); super.attach();
rgbStateListeners.stream().forEach((l) -> { registerStateListeners();
computer.getMemory().addListener(l);
});
} }
} }

View File

@ -31,7 +31,7 @@ import jace.apple2e.SoftSwitches;
* synchronization. * synchronization.
* Created on February 1, 2007, 5:35 PM * 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 { public abstract class Card extends Device {
@ -44,6 +44,7 @@ public abstract class Card extends Device {
/** /**
* Creates a new instance of Card * Creates a new instance of Card
*
* @param computer * @param computer
*/ */
public Card(Computer computer) { public Card(Computer computer) {
@ -117,72 +118,32 @@ public abstract class Card extends Device {
} }
protected void registerListeners() { protected void registerListeners() {
ioListener = new RAMListener( RAM memory = computer.getMemory();
RAMEvent.TYPE.ANY, int baseIO = 0x0c080 + slot * 16;
RAMEvent.SCOPE.RANGE, int baseRom = 0x0c000 + slot * 256;
RAMEvent.VALUE.ANY) { ioListener = memory.observe(RAMEvent.TYPE.ANY, baseIO, baseIO + 15, (e) -> {
@Override int address = e.getAddress() & 0x0f;
protected void doConfig() { handleIOAccess(address, e.getType(), e.getNewValue(), e);
setScopeStart(slot * 16 + 0x00c080); });
setScopeEnd(slot * 16 + 0x00c08F);
}
@Override firmwareListener = memory.observe(RAMEvent.TYPE.ANY, baseRom, baseRom + 255, (e) -> {
protected void doEvent(RAMEvent e) { computer.getMemory().setActiveCard(slot);
int address = e.getAddress() & 0x0f; if (SoftSwitches.CXROM.isOff()) {
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;
}
handleFirmwareAccess(e.getAddress() & 0x0ff, e.getType(), e.getNewValue(), e); handleFirmwareAccess(e.getAddress() & 0x0ff, e.getType(), e.getNewValue(), e);
} }
}; });
c8firmwareListener = new RAMListener( c8firmwareListener = memory.observe(RAMEvent.TYPE.ANY, 0xc800, 0xcfff, (e) -> {
RAMEvent.TYPE.ANY, if (SoftSwitches.CXROM.isOff() && SoftSwitches.INTC8ROM.isOff()
RAMEvent.SCOPE.RANGE, && computer.getMemory().getActiveSlot() == slot) {
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;
}
handleC8FirmwareAccess(e.getAddress() - 0x0c800, e.getType(), e.getNewValue(), e); handleC8FirmwareAccess(e.getAddress() - 0x0c800, e.getType(), e.getNewValue(), e);
} }
}; });
computer.getMemory().addListener(ioListener);
computer.getMemory().addListener(firmwareListener);
computer.getMemory().addListener(c8firmwareListener);
} }
protected void unregisterListeners() { protected void unregisterListeners() {
computer.getMemory().removeListener(ioListener); computer.getMemory().removeListener(ioListener);
computer.getMemory().removeListener(firmwareListener); computer.getMemory().removeListener(firmwareListener);
computer.getMemory().removeListener(c8firmwareListener); computer.getMemory().removeListener(c8firmwareListener);
} }
} }

View File

@ -105,30 +105,28 @@ public abstract class RAM implements Reconfigurable {
abstract public void configureActiveMemory(); 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[] page = activeWrite.getMemoryPage(address);
byte old = 0;
if (page == null) { if (page == null) {
if (generateEvent) { if (generateEvent) {
callListener(RAMEvent.TYPE.WRITE, address, old, b, requireSynchronization); callListener(RAMEvent.TYPE.WRITE, address, 0, b, requireSynchronization);
} }
} else { } else {
int offset = address & 0x0FF; int offset = address & 0x0FF;
old = page[offset]; byte old = page[offset];
if (generateEvent) { 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) { public void writeWord(int address, int w, boolean generateEvent, boolean requireSynchronization) {
int lsb = write(address, (byte) (w & 0x0ff), generateEvent, requireSynchronization); write(address, (byte) (w & 0x0ff), generateEvent, requireSynchronization);
int msb = write(address + 1, (byte) (w >> 8), generateEvent, requireSynchronization); write(address + 1, (byte) (w >> 8), generateEvent, requireSynchronization);
// int oldValue = msb << 8 + lsb;
} }
public byte readRaw(int address) { public byte readRaw(int address) {
// if (address >= 65536) return 0; // if (address >= 65536) return 0;
return activeRead.getMemoryPage(address)[address & 0x0FF]; 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) { 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 @Override
protected void doConfig() { protected void doConfig() {
setScopeStart(addressStart); 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) { 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 @Override
protected void doConfig() { protected void doConfig() {
setScopeStart(addressStart); setScopeStart(addressStart);
@ -334,40 +332,6 @@ public abstract class RAM implements Reconfigurable {
abstract protected void loadRom(String path) throws IOException; 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 attach();
abstract public void detach(); abstract public void detach();

View File

@ -117,8 +117,11 @@ public class CardRamworks extends RAM128k {
public void reconfigure() { public void reconfigure() {
boolean resume = computer.pause(); boolean resume = computer.pause();
maxBank = memorySize / 64; maxBank = memorySize / 64;
if (maxBank < 1) maxBank = 1; if (maxBank < 1) {
if (maxBank > 128) maxBank = 128; maxBank = 1;
} else if (maxBank > 128) {
maxBank = 128;
}
for (int i = memory.size(); i < maxBank; i++) { for (int i = memory.size(); i < maxBank; i++) {
memory.add(null); memory.add(null);
} }
@ -127,23 +130,14 @@ public class CardRamworks extends RAM128k {
computer.resume(); 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 @Override
public void attach() { public void attach() {
addListener(bankSelectListener); bankSelectListener = computer.getMemory().observe(RAMEvent.TYPE.WRITE, BANK_SELECT, (e) -> {
currentBank = e.getNewValue();
configureActiveMemory();
});
} }
@Override @Override

View File

@ -46,6 +46,7 @@ import java.util.logging.Logger;
*/ */
@Stateful @Stateful
public class Joystick extends Device { public class Joystick extends Device {
@ConfigurableField(name = "Center Mouse", shortName = "center", description = "Moves mouse back to the center of the screen, can get annoying.") @ConfigurableField(name = "Center Mouse", shortName = "center", description = "Moves mouse back to the center of the screen, can get annoying.")
public boolean centerMouse = false; public boolean centerMouse = false;
@ConfigurableField(name = "Use keyboard", shortName = "useKeys", description = "Arrow keys will control joystick instead of the mouse.") @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() { private void readJoystick() {
if (useKeyboard) { if (useKeyboard) {
joyX = (leftPressed ? -128 : 0) + (rightPressed ? 255:128); joyX = (leftPressed ? -128 : 0) + (rightPressed ? 255 : 128);
joyY = (upPressed ? -128 : 0) + (downPressed ? 255:128); joyY = (upPressed ? -128 : 0) + (downPressed ? 255 : 128);
} else { } else {
Point l = MouseInfo.getPointerInfo().getLocation(); Point l = MouseInfo.getPointerInfo().getLocation();
if (l.x < lastMouseLocation.x) { if (l.x < lastMouseLocation.x) {
@ -187,29 +188,12 @@ public class Joystick extends Device {
y = 0; y = 0;
registerListeners(); 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) @InvokableAction(name = "Left", category = "joystick", defaultKeyMapping = "left", notifyOnRelease = true)
public boolean joystickLeft(boolean pressed) { public boolean joystickLeft(boolean pressed) {
if (!useKeyboard) return false; if (!useKeyboard) {
return false;
}
leftPressed = pressed; leftPressed = pressed;
if (pressed) { if (pressed) {
rightPressed = false; rightPressed = false;
@ -220,7 +204,9 @@ public class Joystick extends Device {
; ;
@InvokableAction(name = "Right", category = "joystick", defaultKeyMapping = "right", notifyOnRelease = true) @InvokableAction(name = "Right", category = "joystick", defaultKeyMapping = "right", notifyOnRelease = true)
public boolean joystickRight(boolean pressed) { public boolean joystickRight(boolean pressed) {
if (!useKeyboard) return false; if (!useKeyboard) {
return false;
}
rightPressed = pressed; rightPressed = pressed;
if (pressed) { if (pressed) {
leftPressed = false; leftPressed = false;
@ -231,7 +217,9 @@ public class Joystick extends Device {
; ;
@InvokableAction(name = "Up", category = "joystick", defaultKeyMapping = "up", notifyOnRelease = true) @InvokableAction(name = "Up", category = "joystick", defaultKeyMapping = "up", notifyOnRelease = true)
public boolean joystickUp(boolean pressed) { public boolean joystickUp(boolean pressed) {
if (!useKeyboard) return false; if (!useKeyboard) {
return false;
}
upPressed = pressed; upPressed = pressed;
if (pressed) { if (pressed) {
downPressed = false; downPressed = false;
@ -242,7 +230,9 @@ public class Joystick extends Device {
; ;
@InvokableAction(name = "Down", category = "joystick", defaultKeyMapping = "down", notifyOnRelease = true) @InvokableAction(name = "Down", category = "joystick", defaultKeyMapping = "down", notifyOnRelease = true)
public boolean joystickDown(boolean pressed) { public boolean joystickDown(boolean pressed) {
if (!useKeyboard) return false; if (!useKeyboard) {
return false;
}
downPressed = pressed; downPressed = pressed;
if (pressed) { if (pressed) {
upPressed = false; upPressed = false;
@ -250,12 +240,23 @@ public class Joystick extends Device {
return hogKeyboard; 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() { private void registerListeners() {
computer.getMemory().addListener(listener); listener = computer.getMemory().observe(RAMEvent.TYPE.ANY, 0x0c070, 0x0c07f, this::initJoystickRead);
} }
private void removeListeners() { private void removeListeners() {
computer.getMemory().removeListener(listener); computer.getMemory().removeListener(listener);
// Keyboard.unregisterAllHandlers(this);
} }
} }