Adding better unhook and kill keystoke for cheats. Also hooked up watches and resolved some JavaFX redraw issues.

This commit is contained in:
Brendan Robert 2015-08-22 11:57:22 -05:00
parent 2d9ef8b30d
commit 76874ac514
4 changed files with 116 additions and 35 deletions

View File

@ -19,6 +19,7 @@
package jace.cheat; package jace.cheat;
import jace.apple2e.MOS65C02; import jace.apple2e.MOS65C02;
import jace.config.InvokableAction;
import jace.core.Computer; import jace.core.Computer;
import jace.core.Device; import jace.core.Device;
import jace.core.RAMEvent; import jace.core.RAMEvent;
@ -33,12 +34,22 @@ import java.util.Set;
* @author Brendan Robert (BLuRry) brendan.robert@gmail.com * @author Brendan Robert (BLuRry) brendan.robert@gmail.com
*/ */
public abstract class Cheats extends Device { public abstract class Cheats extends Device {
boolean cheatsActive = true;
Set<RAMListener> listeners = new HashSet<>(); Set<RAMListener> listeners = new HashSet<>();
public Cheats(Computer computer) { public Cheats(Computer computer) {
super(computer); super(computer);
} }
@InvokableAction(name = "Toggle Cheats", alternatives = "cheat", defaultKeyMapping = "ctrl+shift+m")
public void toggleCheats() {
cheatsActive = !cheatsActive;
if (cheatsActive) {
attach();
} else {
detach();
}
}
public RAMListener bypassCode(int address, int addressEnd) { public RAMListener bypassCode(int address, int addressEnd) {
int noOperation = MOS65C02.COMMAND.NOP.ordinal(); int noOperation = MOS65C02.COMMAND.NOP.ordinal();
@ -103,7 +114,9 @@ public abstract class Cheats extends Device {
@Override @Override
public void reconfigure() { public void reconfigure() {
unregisterListeners(); unregisterListeners();
registerListeners(); if (cheatsActive) {
registerListeners();
}
} }
@Override @Override

View File

@ -105,8 +105,8 @@ public class MetaCheat extends Cheats {
MetacheatUI ui; MetacheatUI ui;
public int fadeRate = 2; public int fadeRate = 1;
public int lightRate = 20; public int lightRate = 30;
public int historyLength = 10; public int historyLength = 10;
private int startAddress = 0; private int startAddress = 0;

View File

@ -107,7 +107,6 @@ public class MontezumasRevengeCheats extends Cheats {
forceValue(32, FLOOR_TIMER); forceValue(32, FLOOR_TIMER);
forceValue(32, HAZARD_TIMER); forceValue(32, HAZARD_TIMER);
forceValue(1, HAZARD_FLAG); forceValue(1, HAZARD_FLAG);
} }
if (scoreHack) { if (scoreHack) {
@ -123,11 +122,15 @@ public class MontezumasRevengeCheats extends Cheats {
} }
if (mouseHack) { if (mouseHack) {
EmulatorUILogic.addMouseListener(listener); EmulatorUILogic.addMouseListener(listener);
} else {
EmulatorUILogic.removeMouseListener(listener);
} }
} }
@Override
protected void unregisterListeners() {
super.unregisterListeners();
EmulatorUILogic.removeMouseListener(listener);
}
private void repulsiveBehavior(RAMEvent e) { private void repulsiveBehavior(RAMEvent e) {
int playerX = computer.getMemory().readRaw(PLAYER_X); int playerX = computer.getMemory().readRaw(PLAYER_X);
int playerY = computer.getMemory().readRaw(PLAYER_Y); int playerY = computer.getMemory().readRaw(PLAYER_Y);
@ -198,4 +201,4 @@ public class MontezumasRevengeCheats extends Cheats {
computer.memory.write(PLAYER_X, newX, false, false); computer.memory.write(PLAYER_X, newX, false, false);
computer.memory.write(PLAYER_Y, newY, false, false); computer.memory.write(PLAYER_Y, newY, false, false);
} }
} }

View File

@ -18,6 +18,7 @@ import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import javafx.application.Platform; import javafx.application.Platform;
import javafx.beans.property.BooleanProperty;
import javafx.beans.value.ChangeListener; import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue; import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections; import javafx.collections.FXCollections;
@ -262,6 +263,9 @@ public class MetacheatUI {
}); });
memoryViewPane.boundsInParentProperty().addListener((prop, oldVal, newVal) -> redrawMemoryView()); memoryViewPane.boundsInParentProperty().addListener((prop, oldVal, newVal) -> redrawMemoryView());
memoryViewCanvas.widthProperty().bind(memoryViewPane.widthProperty()); memoryViewCanvas.widthProperty().bind(memoryViewPane.widthProperty());
watchesPane.setHgap(5);
watchesPane.setVgap(5);
} }
MetaCheat cheatEngine = null; MetaCheat cheatEngine = null;
@ -312,6 +316,23 @@ public class MetacheatUI {
int row = (int) (y / MEMORY_BOX_TOTAL_SIZE); int row = (int) (y / MEMORY_BOX_TOTAL_SIZE);
int addr = cheatEngine.getStartAddress() + row * memoryViewColumns + col; int addr = cheatEngine.getStartAddress() + row * memoryViewColumns + col;
Watch watch = new Watch(addr); Watch watch = new Watch(addr);
Label addWatch = new Label("Watch >>");
addWatch.setOnMouseClicked((mouseEvent) -> {
Watch newWatch = addWatch(addr);
if (watch.holdingProperty().get()) {
newWatch.holdingProperty().set(true);
}
memoryWatchTooltip.hide();
});
watch.getChildren().add(addWatch);
Label addCheat = new Label("Cheat >>");
addCheat.setOnMouseClicked((mouseEvent) -> {
addCheat(addr, watch.getValue());
});
watch.getChildren().add(addCheat);
memoryWatchTooltip.setStyle("-fx-background-color:NAVY"); memoryWatchTooltip.setStyle("-fx-background-color:NAVY");
memoryWatchTooltip.onHidingProperty().addListener((prop, oldVal, newVal) -> { memoryWatchTooltip.onHidingProperty().addListener((prop, oldVal, newVal) -> {
watch.disconnect(); watch.disconnect();
@ -417,8 +438,36 @@ public class MetacheatUI {
searchStatusLabel.setText(size + (size == 1 ? " result" : " results") + " found."); searchStatusLabel.setText(size + (size == 1 ? " result" : " results") + " found.");
} }
private static int GRAPH_WIDTH = 50; private Watch addWatch(int addr) {
private static double GRAPH_HEIGHT = 50; Watch watch = new Watch(addr);
watch.setPadding(new Insets(5));
watch.setOpaqueInsets(new Insets(10));
Label addCheat = new Label("Cheat >>");
addCheat.setOnMouseClicked((mouseEvent) -> {
addCheat(addr, watch.getValue());
});
addCheat.setTextFill(Color.WHITE);
watch.getChildren().add(addCheat);
Label close = new Label("Close X");
close.setOnMouseClicked((mouseEvent) -> {
watch.disconnect();
watchesPane.getChildren().remove(watch);
});
close.setTextFill(Color.WHITE);
watch.getChildren().add(close);
watchesPane.getChildren().add(watch);
return watch;
}
private void addCheat(int addr, int val) {
}
private static final int GRAPH_WIDTH = 50;
private static final double GRAPH_HEIGHT = 50;
private class Watch extends VBox { private class Watch extends VBox {
@ -426,6 +475,8 @@ public class MetacheatUI {
ScheduledFuture redraw; ScheduledFuture redraw;
Canvas graph; Canvas graph;
List<Integer> samples = Collections.synchronizedList(new ArrayList<>()); List<Integer> samples = Collections.synchronizedList(new ArrayList<>());
int value = 0;
BooleanProperty holding = null;
public Watch(int address) { public Watch(int address) {
super(); super();
@ -443,54 +494,68 @@ public class MetacheatUI {
getChildren().add(graph); getChildren().add(graph);
CheckBox hold = new CheckBox("Hold"); CheckBox hold = new CheckBox("Hold");
hold.selectedProperty().addListener((prop, oldVal, newVal) -> this.hold(newVal)); holding = hold.selectedProperty();
holding.addListener((prop, oldVal, newVal) -> this.updateHold());
getChildren().add(hold); getChildren().add(hold);
hold.setTextFill(Color.WHITE);
}
public int getValue() {
return value;
} }
public void redraw() { public void redraw() {
int val = cheatEngine.getMemoryCell(address).value.get() & 0x0ff; int val = cheatEngine.getMemoryCell(address).value.get() & 0x0ff;
if (!holding.get()) {
value = val;
}
if (samples.size() >= GRAPH_WIDTH) { if (samples.size() >= GRAPH_WIDTH) {
samples.remove(0); samples.remove(0);
} }
samples.add(val); samples.add(val);
GraphicsContext g = graph.getGraphicsContext2D(); Platform.runLater(() -> {
g.setFill(Color.BLACK); GraphicsContext g = graph.getGraphicsContext2D();
g.fillRect(0, 0, GRAPH_WIDTH, GRAPH_HEIGHT); g.setFill(Color.BLACK);
g.fillRect(0, 0, GRAPH_WIDTH, GRAPH_HEIGHT);
if (samples.size() > 1) { if (samples.size() > 1) {
g.setLineWidth(1); g.setLineWidth(1);
g.setStroke(Color.LAWNGREEN); g.setStroke(Color.LAWNGREEN);
int y = (int) (GRAPH_HEIGHT - ((samples.get(0) / 255.0) * GRAPH_HEIGHT)); int y = (int) (GRAPH_HEIGHT - ((samples.get(0) / 255.0) * GRAPH_HEIGHT));
g.beginPath(); g.beginPath();
g.moveTo(0, y); g.moveTo(0, y);
for (int i = 1; i < samples.size(); i++) { for (int i = 1; i < samples.size(); i++) {
y = (int) (GRAPH_HEIGHT - ((samples.get(i) / 255.0) * GRAPH_HEIGHT)); y = (int) (GRAPH_HEIGHT - ((samples.get(i) / 255.0) * GRAPH_HEIGHT));
g.lineTo(i, y); g.lineTo(i, y);
}
g.stroke();
} }
g.stroke(); g.beginPath();
} g.setStroke(Color.WHITE);
g.beginPath(); g.strokeText(String.valueOf(val), GRAPH_WIDTH - 25, GRAPH_HEIGHT - 5);
g.setStroke(Color.WHITE); });
g.strokeText(String.valueOf(val), GRAPH_WIDTH - 25, GRAPH_HEIGHT - 5);
} }
RAMListener holdListener; RAMListener holdListener;
private void hold(boolean state) { public BooleanProperty holdingProperty() {
if (!state) { return holding;
}
private void updateHold() {
if (!holding.get()) {
cheatEngine.removeListener(holdListener); cheatEngine.removeListener(holdListener);
holdListener = null; holdListener = null;
} else { } else {
int val = cheatEngine.getMemoryCell(address).value.get() & 0x0ff; value = Emulator.computer.memory.readRaw(address) & 0x0ff;
holdListener = cheatEngine.forceValue(val, address); holdListener = cheatEngine.forceValue(value, address);
} }
} }
public void disconnect() { public void disconnect() {
if (holdListener != null) { holding.set(false);
cheatEngine.removeListener(holdListener);
}
redraw.cancel(false); redraw.cancel(false);
} }
} }