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;
import jace.apple2e.MOS65C02;
import jace.config.InvokableAction;
import jace.core.Computer;
import jace.core.Device;
import jace.core.RAMEvent;
@ -33,12 +34,22 @@ import java.util.Set;
* @author Brendan Robert (BLuRry) brendan.robert@gmail.com
*/
public abstract class Cheats extends Device {
boolean cheatsActive = true;
Set<RAMListener> listeners = new HashSet<>();
public Cheats(Computer 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) {
int noOperation = MOS65C02.COMMAND.NOP.ordinal();
@ -103,7 +114,9 @@ public abstract class Cheats extends Device {
@Override
public void reconfigure() {
unregisterListeners();
registerListeners();
if (cheatsActive) {
registerListeners();
}
}
@Override

View File

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

View File

@ -107,7 +107,6 @@ public class MontezumasRevengeCheats extends Cheats {
forceValue(32, FLOOR_TIMER);
forceValue(32, HAZARD_TIMER);
forceValue(1, HAZARD_FLAG);
}
if (scoreHack) {
@ -123,11 +122,15 @@ public class MontezumasRevengeCheats extends Cheats {
}
if (mouseHack) {
EmulatorUILogic.addMouseListener(listener);
} else {
EmulatorUILogic.removeMouseListener(listener);
}
}
@Override
protected void unregisterListeners() {
super.unregisterListeners();
EmulatorUILogic.removeMouseListener(listener);
}
private void repulsiveBehavior(RAMEvent e) {
int playerX = computer.getMemory().readRaw(PLAYER_X);
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_Y, newY, false, false);
}
}
}

View File

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