mirror of
https://github.com/skyline-emu/skyline.git
synced 2024-12-23 08:51:52 +01:00
Initial Kotlin Input Implementation
This commit contains the Kotlin side of the initial Input implementation, this is based on the work done in the `hid` branch in `bylaws/skyline`. Co-authored-by: ◱ PixelyIon <pixelyion@protonmail.com>
This commit is contained in:
parent
0219eda2db
commit
b167abcdb7
@ -89,19 +89,22 @@ extern "C" JNIEXPORT void Java_emu_skyline_EmulationActivity_setSurface(JNIEnv *
|
||||
JniMtx.unlock();
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jint Java_emu_skyline_EmulationActivity_getFps(JNIEnv *, jobject ) {
|
||||
extern "C" JNIEXPORT jint Java_emu_skyline_EmulationActivity_getFps(JNIEnv *, jobject) {
|
||||
return fps;
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jfloat Java_emu_skyline_EmulationActivity_getFrametime(JNIEnv *, jobject ) {
|
||||
extern "C" JNIEXPORT jfloat Java_emu_skyline_EmulationActivity_getFrametime(JNIEnv *, jobject) {
|
||||
return static_cast<float>(frametime) / 100;
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL Java_emu_skyline_EmulationActivity_setButtonState(JNIEnv *, jobject, jlong id, jint state) {
|
||||
skyline::input::npad::NpadButton button{.raw = static_cast<skyline::u64>(id)};
|
||||
input->npad[0]->SetButtonState(button, static_cast<skyline::input::npad::NpadButtonState>(state));
|
||||
if (input) {
|
||||
skyline::input::npad::NpadButton button{.raw = static_cast<skyline::u64>(id)};
|
||||
input->npad[0]->SetButtonState(button, static_cast<skyline::input::npad::NpadButtonState>(state));
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL Java_emu_skyline_EmulationActivity_setAxisValue(JNIEnv *, jobject, jint id, jint value) {
|
||||
input->npad[0]->SetAxisValue(static_cast<skyline::input::npad::NpadAxisId>(id), value);
|
||||
if (input)
|
||||
input->npad[0]->SetAxisValue(static_cast<skyline::input::npad::NpadAxisId>(id), value);
|
||||
}
|
||||
|
@ -42,7 +42,6 @@ namespace skyline {
|
||||
bool leftSr : 1; //!< Left Joy-Con SR button
|
||||
bool rightSl : 1; //!< Right Joy-Con SL button
|
||||
bool rightSr : 1; //!< Right Joy-Con SR button
|
||||
bool touch : 1; //!< The touch button
|
||||
};
|
||||
u64 raw;
|
||||
};
|
||||
|
@ -1,6 +1,7 @@
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
// Copyright © 2020 Skyline Team and Contributors (https://github.com/skyline-emu/)
|
||||
|
||||
#include <input.h>
|
||||
#include "IAppletResource.h"
|
||||
|
||||
namespace skyline::service::hid {
|
||||
@ -9,8 +10,7 @@ namespace skyline::service::hid {
|
||||
}) {}
|
||||
|
||||
void IAppletResource::GetSharedMemoryHandle(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||
hidSharedMemory = std::make_shared<kernel::type::KSharedMemory>(state, NULL, constant::HidSharedMemSize, memory::Permission{true, false, false});
|
||||
auto handle = state.process->InsertItem<type::KSharedMemory>(hidSharedMemory);
|
||||
auto handle = state.process->InsertItem<type::KSharedMemory>(state.input->hidKMem);
|
||||
state.logger->Debug("HID Shared Memory Handle: 0x{:X}", handle);
|
||||
|
||||
response.copyHandles.push_back(handle);
|
||||
|
@ -7,25 +7,17 @@
|
||||
#include <services/base_service.h>
|
||||
#include <services/serviceman.h>
|
||||
|
||||
namespace skyline {
|
||||
namespace constant {
|
||||
constexpr auto HidSharedMemSize = 0x40000; //!< The size of HID Shared Memory (https://switchbrew.org/wiki/HID_Shared_Memory)
|
||||
}
|
||||
namespace skyline::service::hid {
|
||||
/**
|
||||
* @brief IAppletResource is used to get a handle to the HID shared memory (https://switchbrew.org/wiki/HID_services#IAppletResource)
|
||||
*/
|
||||
class IAppletResource : public BaseService {
|
||||
public:
|
||||
IAppletResource(const DeviceState &state, ServiceManager &manager);
|
||||
|
||||
namespace service::hid {
|
||||
/**
|
||||
* @brief IAppletResource is used to get a handle to the HID shared memory (https://switchbrew.org/wiki/HID_services#IAppletResource)
|
||||
* @brief This opens a handle to HID shared memory (https://switchbrew.org/wiki/HID_services#GetSharedMemoryHandle)
|
||||
*/
|
||||
class IAppletResource : public BaseService {
|
||||
public:
|
||||
std::shared_ptr<type::KSharedMemory> hidSharedMemory; //!< A pointer to HID shared memory
|
||||
|
||||
IAppletResource(const DeviceState &state, ServiceManager &manager);
|
||||
|
||||
/**
|
||||
* @brief This opens a handle to HID shared memory (https://switchbrew.org/wiki/HID_services#GetSharedMemoryHandle)
|
||||
*/
|
||||
void GetSharedMemoryHandle(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||
};
|
||||
}
|
||||
void GetSharedMemoryHandle(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||
};
|
||||
}
|
||||
|
@ -15,9 +15,13 @@ import android.util.Log
|
||||
import android.view.*
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.preference.PreferenceManager
|
||||
import emu.skyline.input.ButtonState
|
||||
import emu.skyline.input.NpadAxis
|
||||
import emu.skyline.input.NpadButton
|
||||
import emu.skyline.loader.getRomFormat
|
||||
import kotlinx.android.synthetic.main.emu_activity.*
|
||||
import java.io.File
|
||||
import kotlin.math.abs
|
||||
|
||||
class EmulationActivity : AppCompatActivity(), SurfaceHolder.Callback {
|
||||
init {
|
||||
@ -84,8 +88,14 @@ class EmulationActivity : AppCompatActivity(), SurfaceHolder.Callback {
|
||||
*/
|
||||
private external fun getFrametime() : Float
|
||||
|
||||
/**
|
||||
* This sets the state of a specific button
|
||||
*/
|
||||
private external fun setButtonState(id : Long, state : Int)
|
||||
|
||||
/**
|
||||
* This sets the value of a specific axis
|
||||
*/
|
||||
private external fun setAxisValue(id : Int, value : Int)
|
||||
|
||||
/**
|
||||
@ -210,4 +220,113 @@ class EmulationActivity : AppCompatActivity(), SurfaceHolder.Callback {
|
||||
surface = null
|
||||
setSurface(surface)
|
||||
}
|
||||
|
||||
/**
|
||||
* This handles passing on any key events to libskyline
|
||||
*/
|
||||
override fun dispatchKeyEvent(event : KeyEvent) : Boolean {
|
||||
val action : ButtonState = when (event.action) {
|
||||
KeyEvent.ACTION_DOWN -> ButtonState.Pressed
|
||||
KeyEvent.ACTION_UP -> ButtonState.Released
|
||||
else -> return false
|
||||
}
|
||||
|
||||
val buttonMap : Map<Int, NpadButton> = mapOf(
|
||||
KeyEvent.KEYCODE_BUTTON_A to NpadButton.A,
|
||||
KeyEvent.KEYCODE_BUTTON_B to NpadButton.B,
|
||||
KeyEvent.KEYCODE_BUTTON_X to NpadButton.X,
|
||||
KeyEvent.KEYCODE_BUTTON_Y to NpadButton.Y,
|
||||
KeyEvent.KEYCODE_BUTTON_THUMBL to NpadButton.L3,
|
||||
KeyEvent.KEYCODE_BUTTON_THUMBR to NpadButton.R3,
|
||||
KeyEvent.KEYCODE_BUTTON_L1 to NpadButton.L,
|
||||
KeyEvent.KEYCODE_BUTTON_R1 to NpadButton.R,
|
||||
KeyEvent.KEYCODE_BUTTON_L2 to NpadButton.ZL,
|
||||
KeyEvent.KEYCODE_BUTTON_R2 to NpadButton.ZR,
|
||||
KeyEvent.KEYCODE_BUTTON_START to NpadButton.Plus,
|
||||
KeyEvent.KEYCODE_BUTTON_SELECT to NpadButton.Minus,
|
||||
KeyEvent.KEYCODE_DPAD_DOWN to NpadButton.DpadDown,
|
||||
KeyEvent.KEYCODE_DPAD_UP to NpadButton.DpadUp,
|
||||
KeyEvent.KEYCODE_DPAD_LEFT to NpadButton.DpadLeft,
|
||||
KeyEvent.KEYCODE_DPAD_RIGHT to NpadButton.DpadRight)
|
||||
|
||||
return try {
|
||||
setButtonState(buttonMap.getValue(event.keyCode).value(), action.ordinal);
|
||||
true
|
||||
} catch (ignored : NoSuchElementException) {
|
||||
super.dispatchKeyEvent(event)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the controller HAT X value
|
||||
*/
|
||||
private var controllerHatX : Float = 0.0f
|
||||
|
||||
/**
|
||||
* This is the controller HAT Y value
|
||||
*/
|
||||
private var controllerHatY : Float = 0.0f
|
||||
|
||||
/**
|
||||
* This handles passing on any motion events to libskyline
|
||||
*/
|
||||
override fun dispatchGenericMotionEvent(event : MotionEvent) : Boolean {
|
||||
if ((event.source and InputDevice.SOURCE_DPAD) == InputDevice.SOURCE_DPAD ||
|
||||
(event.source and InputDevice.SOURCE_JOYSTICK) == InputDevice.SOURCE_JOYSTICK) {
|
||||
val hatXMap : Map<Float, NpadButton> = mapOf(
|
||||
-1.0f to NpadButton.DpadLeft,
|
||||
+1.0f to NpadButton.DpadRight)
|
||||
|
||||
val hatYMap : Map<Float, NpadButton> = mapOf(
|
||||
-1.0f to NpadButton.DpadUp,
|
||||
+1.0f to NpadButton.DpadDown)
|
||||
|
||||
if (controllerHatX != event.getAxisValue(MotionEvent.AXIS_HAT_X)) {
|
||||
if (event.getAxisValue(MotionEvent.AXIS_HAT_X) == 0.0f)
|
||||
setButtonState(hatXMap.getValue(controllerHatX).value(), ButtonState.Released.ordinal)
|
||||
else
|
||||
setButtonState(hatXMap.getValue(event.getAxisValue(MotionEvent.AXIS_HAT_X)).value(), ButtonState.Pressed.ordinal)
|
||||
|
||||
controllerHatX = event.getAxisValue(MotionEvent.AXIS_HAT_X)
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
if (controllerHatY != event.getAxisValue(MotionEvent.AXIS_HAT_Y)) {
|
||||
if (event.getAxisValue(MotionEvent.AXIS_HAT_Y) == 0.0f)
|
||||
setButtonState(hatYMap.getValue(controllerHatY).value(), ButtonState.Released.ordinal)
|
||||
else
|
||||
setButtonState(hatYMap.getValue(event.getAxisValue(MotionEvent.AXIS_HAT_Y)).value(), ButtonState.Pressed.ordinal)
|
||||
|
||||
controllerHatY = event.getAxisValue(MotionEvent.AXIS_HAT_Y)
|
||||
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
if ((event.source and InputDevice.SOURCE_JOYSTICK) == InputDevice.SOURCE_JOYSTICK && event.action == MotionEvent.ACTION_MOVE) {
|
||||
val axisMap : Map<Int, NpadAxis> = mapOf(
|
||||
MotionEvent.AXIS_X to NpadAxis.LX,
|
||||
MotionEvent.AXIS_Y to NpadAxis.LY,
|
||||
MotionEvent.AXIS_Z to NpadAxis.RX,
|
||||
MotionEvent.AXIS_RZ to NpadAxis.RY)
|
||||
|
||||
//TODO: Digital inputs based off of analog sticks
|
||||
event.device.motionRanges.forEach {
|
||||
if (axisMap.containsKey(it.axis)) {
|
||||
var axisValue : Float = event.getAxisValue(it.axis)
|
||||
if (abs(axisValue) <= it.flat)
|
||||
axisValue = 0.0f
|
||||
|
||||
val ratio : Float = axisValue / (it.max - it.min)
|
||||
val rangedAxisValue : Int = (ratio * (Short.MAX_VALUE - Short.MIN_VALUE)).toInt()
|
||||
|
||||
setAxisValue(axisMap.getValue(it.axis).ordinal, rangedAxisValue)
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
return super.dispatchGenericMotionEvent(event)
|
||||
}
|
||||
}
|
||||
|
21
app/src/main/java/emu/skyline/input/Button.kt
Normal file
21
app/src/main/java/emu/skyline/input/Button.kt
Normal file
@ -0,0 +1,21 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
* Copyright © 2020 Skyline Team and Contributors (https://github.com/skyline-emu/)
|
||||
*/
|
||||
|
||||
package emu.skyline.input
|
||||
|
||||
/**
|
||||
* This is a generic interface for all Button classes to implement
|
||||
*/
|
||||
interface ButtonId {
|
||||
/**
|
||||
* This should return the value of the Button according to what libskyline expects
|
||||
*/
|
||||
fun value() : Long
|
||||
}
|
||||
|
||||
enum class ButtonState(val state : Boolean) {
|
||||
Released(false),
|
||||
Pressed(true),
|
||||
}
|
57
app/src/main/java/emu/skyline/input/Npad.kt
Normal file
57
app/src/main/java/emu/skyline/input/Npad.kt
Normal file
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
* Copyright © 2020 Skyline Team and Contributors (https://github.com/skyline-emu/)
|
||||
*/
|
||||
|
||||
package emu.skyline.input
|
||||
|
||||
/**
|
||||
* This enumerates all buttons on an NPad controller
|
||||
*/
|
||||
enum class NpadButton : ButtonId {
|
||||
A,
|
||||
B,
|
||||
X,
|
||||
Y,
|
||||
L3,
|
||||
R3,
|
||||
L,
|
||||
R,
|
||||
ZL,
|
||||
ZR,
|
||||
Plus,
|
||||
Minus,
|
||||
DpadLeft,
|
||||
DpadUp,
|
||||
DpadRight,
|
||||
DpadDown,
|
||||
LeftStickLeft,
|
||||
LeftStickUp,
|
||||
LeftStickRight,
|
||||
LeftStickDown,
|
||||
RightStickLeft,
|
||||
RightStickUp,
|
||||
RightStickRight,
|
||||
RightStickDown,
|
||||
LeftSL,
|
||||
LeftSR,
|
||||
RightSL,
|
||||
RightSR;
|
||||
|
||||
/**
|
||||
* This just returns the value as setting the [ordinal]-th bit in a [Long]
|
||||
*/
|
||||
override fun value() : Long {
|
||||
return (1.toLong()) shl ordinal
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This enumerates all the axis on an NPad controller
|
||||
*/
|
||||
enum class NpadAxis {
|
||||
RX,
|
||||
RY,
|
||||
LX,
|
||||
LY,
|
||||
}
|
Loading…
Reference in New Issue
Block a user