mirror of
https://github.com/badvision/jace.git
synced 2024-11-28 10:52:33 +00:00
Lambda simplification and code cleanup
This commit is contained in:
parent
5c0855d966
commit
e7f731900a
@ -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) {
|
||||||
|
@ -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.
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -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
|
||||||
@ -59,7 +59,7 @@ public class Speaker extends Device {
|
|||||||
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,8 +164,9 @@ 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);
|
||||||
@ -206,7 +185,7 @@ public class Speaker extends Device {
|
|||||||
}
|
}
|
||||||
}, 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() {
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -105,28 +105,26 @@ 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) {
|
||||||
@ -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();
|
||||||
|
@ -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
|
||||||
|
@ -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) {
|
||||||
@ -188,28 +189,11 @@ public class Joystick extends Device {
|
|||||||
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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user