mirror of
https://github.com/skyline-emu/skyline.git
synced 2024-12-28 07:35:29 +03:00
Move to Callback for Input Initialization + ConditionalVariable for Surface
This commit is contained in:
parent
07c2f2d891
commit
7290a80c3e
@ -53,6 +53,7 @@ extern "C" JNIEXPORT void Java_emu_skyline_EmulationActivity_executeApplication(
|
|||||||
try {
|
try {
|
||||||
skyline::kernel::OS os(jvmManager, logger, settings, std::string(appFilesPath));
|
skyline::kernel::OS os(jvmManager, logger, settings, std::string(appFilesPath));
|
||||||
inputWeak = os.state.input;
|
inputWeak = os.state.input;
|
||||||
|
jvmManager->InitializeControllers();
|
||||||
env->ReleaseStringUTFChars(appFilesPathJstring, appFilesPath);
|
env->ReleaseStringUTFChars(appFilesPathJstring, appFilesPath);
|
||||||
|
|
||||||
auto romUri = env->GetStringUTFChars(romUriJstring, nullptr);
|
auto romUri = env->GetStringUTFChars(romUriJstring, nullptr);
|
||||||
@ -100,27 +101,22 @@ extern "C" JNIEXPORT jfloat Java_emu_skyline_EmulationActivity_getFrametime(JNIE
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT void JNICALL Java_emu_skyline_EmulationActivity_setController(JNIEnv *, jobject, jint index, jint type, jint partnerIndex) {
|
extern "C" JNIEXPORT void JNICALL Java_emu_skyline_EmulationActivity_setController(JNIEnv *, jobject, jint index, jint type, jint partnerIndex) {
|
||||||
while (inputWeak.expired()); // If this isn't called then the guest won't know that the following host controller exists
|
|
||||||
auto input = inputWeak.lock();
|
auto input = inputWeak.lock();
|
||||||
std::lock_guard guard(input->npad.mutex);
|
std::lock_guard guard(input->npad.mutex);
|
||||||
input->npad.controllers[index] = skyline::input::GuestController{static_cast<skyline::input::NpadControllerType>(type), static_cast<skyline::i8>(partnerIndex)};
|
input->npad.controllers[index] = skyline::input::GuestController{static_cast<skyline::input::NpadControllerType>(type), static_cast<skyline::i8>(partnerIndex)};
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT void JNICALL Java_emu_skyline_EmulationActivity_updateControllers(JNIEnv *, jobject) {
|
extern "C" JNIEXPORT void JNICALL Java_emu_skyline_EmulationActivity_updateControllers(JNIEnv *, jobject) {
|
||||||
while (inputWeak.expired()); // If this isn't called then the mappings will not update unless the guest initiates an update itself
|
inputWeak.lock()->npad.Update();
|
||||||
auto input = inputWeak.lock();
|
|
||||||
std::unique_lock lock(input->npad.mutex);
|
|
||||||
input->npad.Update(lock, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT void JNICALL Java_emu_skyline_EmulationActivity_setButtonState(JNIEnv *, jobject, jint index, jlong mask, jint state) {
|
extern "C" JNIEXPORT void JNICALL Java_emu_skyline_EmulationActivity_setButtonState(JNIEnv *, jobject, jint index, jlong mask, jboolean pressed) {
|
||||||
try {
|
try {
|
||||||
auto input = inputWeak.lock();
|
auto input = inputWeak.lock();
|
||||||
auto device = input->npad.controllers[index].device;
|
auto device = input->npad.controllers[index].device;
|
||||||
skyline::input::NpadButton button{.raw = static_cast<skyline::u64>(mask)};
|
|
||||||
if (device)
|
if (device)
|
||||||
device->SetButtonState(button, state);
|
device->SetButtonState(skyline::input::NpadButton{.raw = static_cast<skyline::u64>(mask)}, pressed);
|
||||||
} catch (const std::bad_weak_ptr) {
|
} catch (const std::bad_weak_ptr&) {
|
||||||
// We don't mind if we miss button updates while input hasn't been initialized
|
// We don't mind if we miss button updates while input hasn't been initialized
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -131,7 +127,7 @@ extern "C" JNIEXPORT void JNICALL Java_emu_skyline_EmulationActivity_setAxisValu
|
|||||||
auto device = input->npad.controllers[index].device;
|
auto device = input->npad.controllers[index].device;
|
||||||
if (device)
|
if (device)
|
||||||
device->SetAxisValue(static_cast<skyline::input::NpadAxisId>(axis), value);
|
device->SetAxisValue(static_cast<skyline::input::NpadAxisId>(axis), value);
|
||||||
} catch (const std::bad_weak_ptr) {
|
} catch (const std::bad_weak_ptr&) {
|
||||||
// We don't mind if we miss axis updates while input hasn't been initialized
|
// We don't mind if we miss axis updates while input hasn't been initialized
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,15 +13,8 @@ namespace skyline::input {
|
|||||||
{*this, hid->npad[8], NpadId::Unknown}, {*this, hid->npad[9], NpadId::Handheld},
|
{*this, hid->npad[8], NpadId::Unknown}, {*this, hid->npad[9], NpadId::Handheld},
|
||||||
} {}
|
} {}
|
||||||
|
|
||||||
void NpadManager::Update(std::unique_lock<std::mutex> &lock, bool host) {
|
void NpadManager::Update() {
|
||||||
if (host) {
|
std::lock_guard guard(mutex);
|
||||||
updated = true;
|
|
||||||
} else if (!updated) {
|
|
||||||
lock.unlock();
|
|
||||||
while (!updated);
|
|
||||||
lock.lock();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!activated)
|
if (!activated)
|
||||||
return;
|
return;
|
||||||
@ -85,17 +78,17 @@ namespace skyline::input {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void NpadManager::Activate() {
|
void NpadManager::Activate() {
|
||||||
std::unique_lock lock(mutex);
|
std::lock_guard guard(mutex);
|
||||||
|
|
||||||
supportedIds = {NpadId::Handheld, NpadId::Player1, NpadId::Player2, NpadId::Player3, NpadId::Player4, NpadId::Player5, NpadId::Player6, NpadId::Player7, NpadId::Player8};
|
supportedIds = {NpadId::Handheld, NpadId::Player1, NpadId::Player2, NpadId::Player3, NpadId::Player4, NpadId::Player5, NpadId::Player6, NpadId::Player7, NpadId::Player8};
|
||||||
styles = {.proController = true, .joyconHandheld = true, .joyconDual = true, .joyconLeft = true, .joyconRight = true};
|
styles = {.proController = true, .joyconHandheld = true, .joyconDual = true, .joyconLeft = true, .joyconRight = true};
|
||||||
activated = true;
|
activated = true;
|
||||||
|
|
||||||
Update(lock);
|
Update();
|
||||||
}
|
}
|
||||||
|
|
||||||
void NpadManager::Deactivate() {
|
void NpadManager::Deactivate() {
|
||||||
std::unique_lock lock(mutex);
|
std::lock_guard guard(mutex);
|
||||||
|
|
||||||
supportedIds = {};
|
supportedIds = {};
|
||||||
styles = {};
|
styles = {};
|
||||||
|
@ -22,7 +22,6 @@ namespace skyline::input {
|
|||||||
private:
|
private:
|
||||||
const DeviceState &state;
|
const DeviceState &state;
|
||||||
bool activated{false}; //!< If this NpadManager is activated or not
|
bool activated{false}; //!< If this NpadManager is activated or not
|
||||||
std::atomic<bool> updated{false}; //!< If this NpadManager has been updated by the guest
|
|
||||||
|
|
||||||
friend NpadDevice;
|
friend NpadDevice;
|
||||||
|
|
||||||
@ -43,7 +42,7 @@ namespace skyline::input {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
std::mutex mutex; //!< This mutex must be locked before any modifications to class members
|
std::recursive_mutex mutex; //!< This mutex must be locked before any modifications to class members
|
||||||
std::array<NpadDevice, constant::NpadCount> npads;
|
std::array<NpadDevice, constant::NpadCount> npads;
|
||||||
std::array<GuestController, constant::ControllerCount> controllers;
|
std::array<GuestController, constant::ControllerCount> controllers;
|
||||||
std::vector<NpadId> supportedIds; //!< The NpadId(s) that are supported by the application
|
std::vector<NpadId> supportedIds; //!< The NpadId(s) that are supported by the application
|
||||||
@ -71,10 +70,9 @@ namespace skyline::input {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This deduces all the mappings from guest controllers -> players based on the configuration supplied by HID services and available controllers
|
* @brief This deduces all the mappings from guest controllers -> players based on the configuration supplied by HID services and available controllers
|
||||||
* @param lock A unique_lock which locks the mutex in the class, it should be locked before modifications to any members and must not be passed in an unlocked state
|
* @note If any class members were edited, the mutex shouldn't be released till this is called
|
||||||
* @param host If the update is host-initiated rather than the guest
|
|
||||||
*/
|
*/
|
||||||
void Update(std::unique_lock<std::mutex> &lock, bool host = false);
|
void Update();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This activates the mapping between guest controllers -> players, a call to this is required for function
|
* @brief This activates the mapping between guest controllers -> players, a call to this is required for function
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
thread_local JNIEnv *env;
|
thread_local JNIEnv *env;
|
||||||
|
|
||||||
namespace skyline {
|
namespace skyline {
|
||||||
JvmManager::JvmManager(JNIEnv *environ, jobject instance) : instance(instance), instanceClass(reinterpret_cast<jclass>(environ->NewGlobalRef(environ->GetObjectClass(instance)))) {
|
JvmManager::JvmManager(JNIEnv *environ, jobject instance) : instance(instance), instanceClass(reinterpret_cast<jclass>(environ->NewGlobalRef(environ->GetObjectClass(instance)))), initializeControllersId(environ->GetMethodID(instanceClass, "initializeControllers", "()V")) {
|
||||||
env = environ;
|
env = environ;
|
||||||
if (env->GetJavaVM(&vm) < 0)
|
if (env->GetJavaVM(&vm) < 0)
|
||||||
throw exception("Cannot get JavaVM from environment");
|
throw exception("Cannot get JavaVM from environment");
|
||||||
@ -37,4 +37,8 @@ namespace skyline {
|
|||||||
bool JvmManager::CheckNull(jobject &object) {
|
bool JvmManager::CheckNull(jobject &object) {
|
||||||
return env->IsSameObject(object, nullptr);
|
return env->IsSameObject(object, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void JvmManager::InitializeControllers() {
|
||||||
|
env->CallVoidMethod(instance, initializeControllersId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -35,7 +35,7 @@ namespace skyline {
|
|||||||
/**
|
/**
|
||||||
* @brief Returns a pointer to the JNI environment for the current thread
|
* @brief Returns a pointer to the JNI environment for the current thread
|
||||||
*/
|
*/
|
||||||
JNIEnv *GetEnv();
|
static JNIEnv *GetEnv();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Retrieves a specific field of the given type from the activity
|
* @brief Retrieves a specific field of the given type from the activity
|
||||||
@ -85,6 +85,14 @@ namespace skyline {
|
|||||||
* @param object The jobject to check
|
* @param object The jobject to check
|
||||||
* @return If the object is null or not
|
* @return If the object is null or not
|
||||||
*/
|
*/
|
||||||
bool CheckNull(jobject &object);
|
static bool CheckNull(jobject &object);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief A call to EmulationActivity.initializeControllers in Kotlin
|
||||||
|
*/
|
||||||
|
void InitializeControllers();
|
||||||
|
|
||||||
|
private:
|
||||||
|
jmethodID initializeControllersId;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -29,9 +29,9 @@ namespace skyline::service::hid {
|
|||||||
|
|
||||||
void IHidServer::SetSupportedNpadStyleSet(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
void IHidServer::SetSupportedNpadStyleSet(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
auto styleSet = request.Pop<NpadStyleSet>();
|
auto styleSet = request.Pop<NpadStyleSet>();
|
||||||
std::unique_lock lock(state.input->npad.mutex);
|
std::lock_guard lock(state.input->npad.mutex);
|
||||||
state.input->npad.styles = styleSet;
|
state.input->npad.styles = styleSet;
|
||||||
state.input->npad.Update(lock);
|
state.input->npad.Update();
|
||||||
|
|
||||||
state.logger->Debug("Controller Support:\nPro-Controller: {}\nJoy-Con: Handheld: {}, Dual: {}, L: {}, R: {}\nGameCube: {}\nPokeBall: {}\nNES: {}, NES Handheld: {}, SNES: {}", static_cast<bool>(styleSet.proController), static_cast<bool>(styleSet.joyconHandheld), static_cast<bool>(styleSet.joyconDual), static_cast<bool>(styleSet.joyconLeft), static_cast<bool>
|
state.logger->Debug("Controller Support:\nPro-Controller: {}\nJoy-Con: Handheld: {}, Dual: {}, L: {}, R: {}\nGameCube: {}\nPokeBall: {}\nNES: {}, NES Handheld: {}, SNES: {}", static_cast<bool>(styleSet.proController), static_cast<bool>(styleSet.joyconHandheld), static_cast<bool>(styleSet.joyconDual), static_cast<bool>(styleSet.joyconLeft), static_cast<bool>
|
||||||
(styleSet.joyconRight), static_cast<bool>(styleSet.gamecube), static_cast<bool>(styleSet.palma), static_cast<bool>(styleSet.nes), static_cast<bool>(styleSet.nesHandheld), static_cast<bool>(styleSet.snes));
|
(styleSet.joyconRight), static_cast<bool>(styleSet.gamecube), static_cast<bool>(styleSet.palma), static_cast<bool>(styleSet.nes), static_cast<bool>(styleSet.nesHandheld), static_cast<bool>(styleSet.snes));
|
||||||
@ -45,16 +45,16 @@ namespace skyline::service::hid {
|
|||||||
const auto &buffer = request.inputBuf.at(0);
|
const auto &buffer = request.inputBuf.at(0);
|
||||||
u64 address = buffer.address;
|
u64 address = buffer.address;
|
||||||
size_t size = buffer.size / sizeof(NpadId);
|
size_t size = buffer.size / sizeof(NpadId);
|
||||||
std::vector<NpadId> supportedIds;
|
|
||||||
|
|
||||||
|
std::vector<NpadId> supportedIds(size);
|
||||||
for (size_t i = 0; i < size; i++) {
|
for (size_t i = 0; i < size; i++) {
|
||||||
supportedIds.push_back(state.process->GetObject<NpadId>(address));
|
supportedIds[i] = state.process->GetObject<NpadId>(address);
|
||||||
address += sizeof(NpadId);
|
address += sizeof(NpadId);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_lock lock(state.input->npad.mutex);
|
std::lock_guard lock(state.input->npad.mutex);
|
||||||
state.input->npad.supportedIds = supportedIds;
|
state.input->npad.supportedIds = supportedIds;
|
||||||
state.input->npad.Update(lock);
|
state.input->npad.Update();
|
||||||
}
|
}
|
||||||
|
|
||||||
void IHidServer::ActivateNpad(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
void IHidServer::ActivateNpad(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
@ -75,10 +75,10 @@ namespace skyline::service::hid {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void IHidServer::SetNpadJoyHoldType(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
void IHidServer::SetNpadJoyHoldType(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
std::unique_lock lock(state.input->npad.mutex);
|
std::lock_guard lock(state.input->npad.mutex);
|
||||||
request.Skip<u64>();
|
request.Skip<u64>();
|
||||||
state.input->npad.orientation = request.Pop<NpadJoyOrientation>();
|
state.input->npad.orientation = request.Pop<NpadJoyOrientation>();
|
||||||
state.input->npad.Update(lock);
|
state.input->npad.Update();
|
||||||
}
|
}
|
||||||
|
|
||||||
void IHidServer::GetNpadJoyHoldType(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
void IHidServer::GetNpadJoyHoldType(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
@ -87,22 +87,22 @@ namespace skyline::service::hid {
|
|||||||
|
|
||||||
void IHidServer::SetNpadJoyAssignmentModeSingleByDefault(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
void IHidServer::SetNpadJoyAssignmentModeSingleByDefault(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
auto id = request.Pop<NpadId>();
|
auto id = request.Pop<NpadId>();
|
||||||
std::unique_lock lock(state.input->npad.mutex);
|
std::lock_guard lock(state.input->npad.mutex);
|
||||||
state.input->npad.at(id).SetAssignment(NpadJoyAssignment::Single);
|
state.input->npad.at(id).SetAssignment(NpadJoyAssignment::Single);
|
||||||
state.input->npad.Update(lock);
|
state.input->npad.Update();
|
||||||
}
|
}
|
||||||
|
|
||||||
void IHidServer::SetNpadJoyAssignmentModeSingle(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
void IHidServer::SetNpadJoyAssignmentModeSingle(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
auto id = request.Pop<NpadId>();
|
auto id = request.Pop<NpadId>();
|
||||||
std::unique_lock lock(state.input->npad.mutex);
|
std::lock_guard lock(state.input->npad.mutex);
|
||||||
state.input->npad.at(id).SetAssignment(NpadJoyAssignment::Single);
|
state.input->npad.at(id).SetAssignment(NpadJoyAssignment::Single);
|
||||||
state.input->npad.Update(lock);
|
state.input->npad.Update();
|
||||||
}
|
}
|
||||||
|
|
||||||
void IHidServer::SetNpadJoyAssignmentModeDual(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
void IHidServer::SetNpadJoyAssignmentModeDual(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
auto id = request.Pop<NpadId>();
|
auto id = request.Pop<NpadId>();
|
||||||
std::unique_lock lock(state.input->npad.mutex);
|
std::lock_guard lock(state.input->npad.mutex);
|
||||||
state.input->npad.at(id).SetAssignment(NpadJoyAssignment::Dual);
|
state.input->npad.at(id).SetAssignment(NpadJoyAssignment::Dual);
|
||||||
state.input->npad.Update(lock);
|
state.input->npad.Update();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@ namespace skyline::service::settings {
|
|||||||
{0x3, SFUNC(ISystemSettingsServer::GetFirmwareVersion)}}) {}
|
{0x3, SFUNC(ISystemSettingsServer::GetFirmwareVersion)}}) {}
|
||||||
|
|
||||||
void ISystemSettingsServer::GetFirmwareVersion(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
void ISystemSettingsServer::GetFirmwareVersion(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
SysVerTitle title{.major=5, .minor=0, .micro=0, .revMajor=4, .revMinor=0, .platform="NX", .verHash="4de65c071fd0869695b7629f75eb97b2551dbf2f", .dispVer="9.0.0", .dispTitle="NintendoSDK Firmware for NX 9.0.0-4.0"};
|
SysVerTitle title{.major=9, .minor=0, .micro=0, .revMajor=4, .revMinor=0, .platform="NX", .verHash="4de65c071fd0869695b7629f75eb97b2551dbf2f", .dispVer="9.0.0", .dispTitle="NintendoSDK Firmware for NX 9.0.0-4.0"};
|
||||||
state.process->WriteMemory(title, request.outputBuf.at(0).address);
|
state.process->WriteMemory(title, request.outputBuf.at(0).address);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@ import android.content.Intent
|
|||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
import android.os.ConditionVariable
|
||||||
import android.os.ParcelFileDescriptor
|
import android.os.ParcelFileDescriptor
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.view.*
|
import android.view.*
|
||||||
@ -52,6 +53,11 @@ class EmulationActivity : AppCompatActivity(), SurfaceHolder.Callback {
|
|||||||
@Volatile
|
@Volatile
|
||||||
private var surface : Surface? = null
|
private var surface : Surface? = null
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A condition variable keeping track of if the surface is ready or not
|
||||||
|
*/
|
||||||
|
private var surfaceReady = ConditionVariable()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A boolean flag denoting if the emulation thread should call finish() or not
|
* A boolean flag denoting if the emulation thread should call finish() or not
|
||||||
*/
|
*/
|
||||||
@ -120,9 +126,9 @@ class EmulationActivity : AppCompatActivity(), SurfaceHolder.Callback {
|
|||||||
*
|
*
|
||||||
* @param index The index of the controller this is directed to
|
* @param index The index of the controller this is directed to
|
||||||
* @param mask The mask of the button that are being set
|
* @param mask The mask of the button that are being set
|
||||||
* @param state The state to set the button to
|
* @param pressed If the buttons are being pressed or released
|
||||||
*/
|
*/
|
||||||
private external fun setButtonState(index : Int, mask : Long, state : Int)
|
private external fun setButtonState(index : Int, mask : Long, pressed : Boolean)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This sets the value of a specific axis on a specific controller
|
* This sets the value of a specific axis on a specific controller
|
||||||
@ -141,13 +147,13 @@ class EmulationActivity : AppCompatActivity(), SurfaceHolder.Callback {
|
|||||||
val controller = entry.value
|
val controller = entry.value
|
||||||
|
|
||||||
if (controller.type != ControllerType.None) {
|
if (controller.type != ControllerType.None) {
|
||||||
val type : Int = when (controller.type) {
|
val type = when (controller.type) {
|
||||||
ControllerType.None -> throw IllegalArgumentException()
|
ControllerType.None -> throw IllegalArgumentException()
|
||||||
ControllerType.HandheldProController -> if (operationMode) ControllerType.ProController.id else ControllerType.HandheldProController.id
|
ControllerType.HandheldProController -> if (operationMode) ControllerType.ProController.id else ControllerType.HandheldProController.id
|
||||||
ControllerType.ProController, ControllerType.JoyConLeft, ControllerType.JoyConRight -> controller.type.id
|
ControllerType.ProController, ControllerType.JoyConLeft, ControllerType.JoyConRight -> controller.type.id
|
||||||
}
|
}
|
||||||
|
|
||||||
val partnerIndex : Int? = when (controller) {
|
val partnerIndex = when (controller) {
|
||||||
is JoyConLeftController -> controller.partnerId
|
is JoyConLeftController -> controller.partnerId
|
||||||
is JoyConRightController -> controller.partnerId
|
is JoyConRightController -> controller.partnerId
|
||||||
else -> null
|
else -> null
|
||||||
@ -170,10 +176,7 @@ class EmulationActivity : AppCompatActivity(), SurfaceHolder.Callback {
|
|||||||
romFd = contentResolver.openFileDescriptor(rom, "r")!!
|
romFd = contentResolver.openFileDescriptor(rom, "r")!!
|
||||||
|
|
||||||
emulationThread = Thread {
|
emulationThread = Thread {
|
||||||
while (surface == null)
|
surfaceReady.block()
|
||||||
Thread.yield()
|
|
||||||
|
|
||||||
runOnUiThread { initializeControllers() }
|
|
||||||
|
|
||||||
executeApplication(rom.toString(), romType, romFd.fd, preferenceFd.fd, applicationContext.filesDir.canonicalPath + "/")
|
executeApplication(rom.toString(), romType, romFd.fd, preferenceFd.fd, applicationContext.filesDir.canonicalPath + "/")
|
||||||
|
|
||||||
@ -216,14 +219,12 @@ class EmulationActivity : AppCompatActivity(), SurfaceHolder.Callback {
|
|||||||
val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this)
|
val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this)
|
||||||
|
|
||||||
if (sharedPreferences.getBoolean("perf_stats", false)) {
|
if (sharedPreferences.getBoolean("perf_stats", false)) {
|
||||||
val perfRunnable = object : Runnable {
|
perf_stats.postDelayed(object : Runnable {
|
||||||
override fun run() {
|
override fun run() {
|
||||||
perf_stats.text = "${getFps()} FPS\n${getFrametime()}ms"
|
perf_stats.text = "${getFps()} FPS\n${getFrametime()}ms"
|
||||||
perf_stats.postDelayed(this, 250)
|
perf_stats.postDelayed(this, 250)
|
||||||
}
|
}
|
||||||
}
|
}, 250)
|
||||||
|
|
||||||
perf_stats.postDelayed(perfRunnable, 250)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
operationMode = sharedPreferences.getBoolean("operation_mode", operationMode)
|
operationMode = sharedPreferences.getBoolean("operation_mode", operationMode)
|
||||||
@ -274,6 +275,7 @@ class EmulationActivity : AppCompatActivity(), SurfaceHolder.Callback {
|
|||||||
Log.d("surfaceCreated", "Holder: $holder")
|
Log.d("surfaceCreated", "Holder: $holder")
|
||||||
surface = holder.surface
|
surface = holder.surface
|
||||||
setSurface(surface)
|
setSurface(surface)
|
||||||
|
surfaceReady.open()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -288,6 +290,7 @@ class EmulationActivity : AppCompatActivity(), SurfaceHolder.Callback {
|
|||||||
*/
|
*/
|
||||||
override fun surfaceDestroyed(holder : SurfaceHolder) {
|
override fun surfaceDestroyed(holder : SurfaceHolder) {
|
||||||
Log.d("surfaceDestroyed", "Holder: $holder")
|
Log.d("surfaceDestroyed", "Holder: $holder")
|
||||||
|
surfaceReady.close()
|
||||||
surface = null
|
surface = null
|
||||||
setSurface(surface)
|
setSurface(surface)
|
||||||
}
|
}
|
||||||
@ -299,7 +302,7 @@ class EmulationActivity : AppCompatActivity(), SurfaceHolder.Callback {
|
|||||||
if (event.repeatCount != 0)
|
if (event.repeatCount != 0)
|
||||||
return super.dispatchKeyEvent(event)
|
return super.dispatchKeyEvent(event)
|
||||||
|
|
||||||
val action : ButtonState = when (event.action) {
|
val action = when (event.action) {
|
||||||
KeyEvent.ACTION_DOWN -> ButtonState.Pressed
|
KeyEvent.ACTION_DOWN -> ButtonState.Pressed
|
||||||
KeyEvent.ACTION_UP -> ButtonState.Released
|
KeyEvent.ACTION_UP -> ButtonState.Released
|
||||||
else -> return super.dispatchKeyEvent(event)
|
else -> return super.dispatchKeyEvent(event)
|
||||||
@ -308,7 +311,7 @@ class EmulationActivity : AppCompatActivity(), SurfaceHolder.Callback {
|
|||||||
return when (val guestEvent = input.eventMap[KeyHostEvent(event.device.descriptor, event.keyCode)]) {
|
return when (val guestEvent = input.eventMap[KeyHostEvent(event.device.descriptor, event.keyCode)]) {
|
||||||
is ButtonGuestEvent -> {
|
is ButtonGuestEvent -> {
|
||||||
if (guestEvent.button != ButtonId.Menu)
|
if (guestEvent.button != ButtonId.Menu)
|
||||||
setButtonState(guestEvent.id, guestEvent.button.value(), action.ordinal)
|
setButtonState(guestEvent.id, guestEvent.button.value(), action.state)
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -356,7 +359,7 @@ class EmulationActivity : AppCompatActivity(), SurfaceHolder.Callback {
|
|||||||
when (guestEvent) {
|
when (guestEvent) {
|
||||||
is ButtonGuestEvent -> {
|
is ButtonGuestEvent -> {
|
||||||
if (guestEvent.button != ButtonId.Menu)
|
if (guestEvent.button != ButtonId.Menu)
|
||||||
setButtonState(guestEvent.id, guestEvent.button.value(), if (abs(value) >= guestEvent.threshold) ButtonState.Pressed.ordinal else ButtonState.Released.ordinal)
|
setButtonState(guestEvent.id, guestEvent.button.value(), if (abs(value) >= guestEvent.threshold) ButtonState.Pressed.state else ButtonState.Released.state)
|
||||||
}
|
}
|
||||||
|
|
||||||
is AxisGuestEvent -> {
|
is AxisGuestEvent -> {
|
||||||
|
@ -179,7 +179,7 @@ class MainActivity : AppCompatActivity(), View.OnClickListener {
|
|||||||
setupAppList()
|
setupAppList()
|
||||||
|
|
||||||
app_list.addOnScrollListener(object : RecyclerView.OnScrollListener() {
|
app_list.addOnScrollListener(object : RecyclerView.OnScrollListener() {
|
||||||
var y : Int = 0
|
var y = 0
|
||||||
|
|
||||||
override fun onScrolled(recyclerView : RecyclerView, dx : Int, dy : Int) {
|
override fun onScrolled(recyclerView : RecyclerView, dx : Int, dy : Int) {
|
||||||
y += dy
|
y += dy
|
||||||
|
@ -65,12 +65,14 @@
|
|||||||
android:key="category_input"
|
android:key="category_input"
|
||||||
android:title="@string/input"
|
android:title="@string/input"
|
||||||
app:initialExpandedChildrenCount="4">
|
app:initialExpandedChildrenCount="4">
|
||||||
|
<!--
|
||||||
<CheckBoxPreference
|
<CheckBoxPreference
|
||||||
android:defaultValue="true"
|
android:defaultValue="true"
|
||||||
android:summaryOff="@string/osc_not_shown"
|
android:summaryOff="@string/osc_not_shown"
|
||||||
android:summaryOn="@string/osc_shown"
|
android:summaryOn="@string/osc_shown"
|
||||||
app:key="show_osc"
|
app:key="show_osc"
|
||||||
app:title="@string/show_osc" />
|
app:title="@string/show_osc" />
|
||||||
|
-->
|
||||||
<emu.skyline.preference.ControllerPreference index="0" />
|
<emu.skyline.preference.ControllerPreference index="0" />
|
||||||
<emu.skyline.preference.ControllerPreference index="1" />
|
<emu.skyline.preference.ControllerPreference index="1" />
|
||||||
<emu.skyline.preference.ControllerPreference index="2" />
|
<emu.skyline.preference.ControllerPreference index="2" />
|
||||||
|
Loading…
Reference in New Issue
Block a user