lawless-legends/Platform/Apple/tools/jace/src/main/java/jace/hardware/Joystick.java

214 lines
6.5 KiB
Java

/*
* Copyright (C) 2012 Brendan Robert (BLuRry) brendan.robert@gmail.com.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
package jace.hardware;
import jace.LawlessLegends;
import jace.apple2e.SoftSwitches;
import jace.apple2e.softswitch.MemorySoftSwitch;
import jace.config.ConfigurableField;
import jace.config.InvokableAction;
import jace.core.Computer;
import jace.core.Device;
import jace.core.RAMEvent;
import jace.core.RAMListener;
import jace.state.Stateful;
import javafx.scene.input.MouseEvent;
import javafx.stage.Stage;
/**
* Simple implementation of joystick support that supports mouse or keyboard.
* Actual joystick support isn't offered by Java at this moment in time
* unfortunately.
*
* @author Brendan Robert (BLuRry) brendan.robert@gmail.com
*/
@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.")
public boolean useKeyboard = true;
@ConfigurableField(name = "Hog keypresses", shortName = "hog", description = "Key presses will not be sent to emulator.")
public boolean hogKeyboard = false;
public int port;
@Stateful
public int x = 0;
@Stateful
public int y = 0;
private int joyX = 0;
private int joyY = 0;
MemorySoftSwitch xSwitch;
MemorySoftSwitch ySwitch;
public Joystick(int port, Computer computer) {
super(computer);
if (LawlessLegends.getApplication() == null) {
return;
}
Stage stage = LawlessLegends.getApplication().primaryStage;
// Register a mouse handler on the primary stage that tracks the
// mouse x/y position as a percentage of window width and height
stage.addEventHandler(MouseEvent.MOUSE_MOVED, event -> {
if (!useKeyboard) {
joyX = (int) (event.getX() / stage.getWidth() * 255);
joyY = (int) (event.getY() / stage.getHeight() * 255);
}
});
this.port = port;
if (port == 0) {
xSwitch = (MemorySoftSwitch) SoftSwitches.PDL0.getSwitch();
ySwitch = (MemorySoftSwitch) SoftSwitches.PDL1.getSwitch();
} else {
xSwitch = (MemorySoftSwitch) SoftSwitches.PDL2.getSwitch();
ySwitch = (MemorySoftSwitch) SoftSwitches.PDL3.getSwitch();
}
}
public boolean leftPressed = false;
public boolean rightPressed = false;
public boolean upPressed = false;
public boolean downPressed = false;
private void readJoystick() {
if (useKeyboard) {
joyX = (leftPressed ? -128 : 0) + (rightPressed ? 255 : 128);
joyY = (upPressed ? -128 : 0) + (downPressed ? 255 : 128);
}
}
@Override
protected String getDeviceName() {
return "Joystick (port " + port + ")";
}
@Override
public String getShortName() {
return "joy" + port;
}
@Override
public void tick() {
boolean finished = true;
if (x > 0) {
if (--x == 0) {
xSwitch.setState(false);
} else {
finished = false;
}
}
if (y > 0) {
if (--y == 0) {
ySwitch.setState(false);
} else {
finished = false;
}
}
if (finished) {
setRun(false);
}
}
@Override
public void attach() {
registerListeners();
}
@Override
public void detach() {
removeListeners();
super.detach();
}
@Override
public void reconfigure() {
removeListeners();
x = 0;
y = 0;
registerListeners();
}
@InvokableAction(name = "Left", category = "joystick", defaultKeyMapping = "left", notifyOnRelease = true)
public boolean joystickLeft(boolean pressed) {
if (!useKeyboard) {
return false;
}
leftPressed = pressed;
if (pressed) {
rightPressed = false;
}
return hogKeyboard;
}
@InvokableAction(name = "Right", category = "joystick", defaultKeyMapping = "right", notifyOnRelease = true)
public boolean joystickRight(boolean pressed) {
if (!useKeyboard) {
return false;
}
rightPressed = pressed;
if (pressed) {
leftPressed = false;
}
return hogKeyboard;
}
@InvokableAction(name = "Up", category = "joystick", defaultKeyMapping = "up", notifyOnRelease = true)
public boolean joystickUp(boolean pressed) {
if (!useKeyboard) {
return false;
}
upPressed = pressed;
if (pressed) {
downPressed = false;
}
return hogKeyboard;
}
@InvokableAction(name = "Down", category = "joystick", defaultKeyMapping = "down", notifyOnRelease = true)
public boolean joystickDown(boolean pressed) {
if (!useKeyboard) {
return false;
}
downPressed = pressed;
if (pressed) {
upPressed = false;
}
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() {
listener = computer.getMemory().observe("Joystick I/O", RAMEvent.TYPE.ANY, 0x0c070, 0x0c07f, this::initJoystickRead);
}
private void removeListeners() {
computer.getMemory().removeListener(listener);
}
}