Merge pull request #3593 from Sonicadvance1/Android_Mayflash_adapter
[Android] Implement support for real Wiimotes with the DolphinBar
This commit is contained in:
commit
35d7c2bc78
|
@ -379,6 +379,11 @@ public final class NativeLibrary
|
||||||
/** Native EGL functions not exposed by Java bindings **/
|
/** Native EGL functions not exposed by Java bindings **/
|
||||||
public static native void eglBindAPI(int api);
|
public static native void eglBindAPI(int api);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides a way to refresh the connections on Wiimotes
|
||||||
|
*/
|
||||||
|
public static native void RefreshWiimotes();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The methods C++ uses to find references to Java classes and methods
|
* The methods C++ uses to find references to Java classes and methods
|
||||||
* are really expensive. Rather than calling them every time we want to
|
* are really expensive. Rather than calling them every time we want to
|
||||||
|
|
|
@ -33,6 +33,7 @@ import org.dolphinemu.dolphinemu.fragments.SaveStateFragment;
|
||||||
import org.dolphinemu.dolphinemu.ui.main.MainPresenter;
|
import org.dolphinemu.dolphinemu.ui.main.MainPresenter;
|
||||||
import org.dolphinemu.dolphinemu.utils.Animations;
|
import org.dolphinemu.dolphinemu.utils.Animations;
|
||||||
import org.dolphinemu.dolphinemu.utils.Java_GCAdapter;
|
import org.dolphinemu.dolphinemu.utils.Java_GCAdapter;
|
||||||
|
import org.dolphinemu.dolphinemu.utils.Java_WiimoteAdapter;
|
||||||
import org.dolphinemu.dolphinemu.utils.Log;
|
import org.dolphinemu.dolphinemu.utils.Log;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -120,6 +121,7 @@ public final class EmulationActivity extends AppCompatActivity
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
Java_GCAdapter.manager = (UsbManager) getSystemService(Context.USB_SERVICE);
|
Java_GCAdapter.manager = (UsbManager) getSystemService(Context.USB_SERVICE);
|
||||||
|
Java_WiimoteAdapter.manager = (UsbManager) getSystemService(Context.USB_SERVICE);
|
||||||
|
|
||||||
// Picasso will take a while to load these big-ass screenshots. So don't run
|
// Picasso will take a while to load these big-ass screenshots. So don't run
|
||||||
// the animation until we say so.
|
// the animation until we say so.
|
||||||
|
@ -392,6 +394,10 @@ public final class EmulationActivity extends AppCompatActivity
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case R.id.menu_refresh_wiimotes:
|
||||||
|
NativeLibrary.RefreshWiimotes();
|
||||||
|
return;
|
||||||
|
|
||||||
// Screenshot capturing
|
// Screenshot capturing
|
||||||
case R.id.menu_emulation_screenshot:
|
case R.id.menu_emulation_screenshot:
|
||||||
NativeLibrary.SaveScreenShot();
|
NativeLibrary.SaveScreenShot();
|
||||||
|
|
|
@ -0,0 +1,156 @@
|
||||||
|
package org.dolphinemu.dolphinemu.utils;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.app.PendingIntent;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.hardware.usb.UsbConfiguration;
|
||||||
|
import android.hardware.usb.UsbDevice;
|
||||||
|
import android.hardware.usb.UsbDeviceConnection;
|
||||||
|
import android.hardware.usb.UsbEndpoint;
|
||||||
|
import android.hardware.usb.UsbInterface;
|
||||||
|
import android.hardware.usb.UsbManager;
|
||||||
|
|
||||||
|
import org.dolphinemu.dolphinemu.NativeLibrary;
|
||||||
|
import org.dolphinemu.dolphinemu.services.USBPermService;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class Java_WiimoteAdapter
|
||||||
|
{
|
||||||
|
final static int MAX_PAYLOAD = 23;
|
||||||
|
final static int MAX_WIIMOTES = 4;
|
||||||
|
final static int TIMEOUT = 200;
|
||||||
|
final static short NINTENDO_VENDOR_ID = 0x057e;
|
||||||
|
final static short NINTENDO_WIIMOTE_PRODUCT_ID = 0x0306;
|
||||||
|
public static UsbManager manager;
|
||||||
|
|
||||||
|
static UsbDeviceConnection usb_con;
|
||||||
|
static UsbInterface[] usb_intf = new UsbInterface[MAX_WIIMOTES];
|
||||||
|
static UsbEndpoint[] usb_in = new UsbEndpoint[MAX_WIIMOTES];
|
||||||
|
|
||||||
|
public static byte[][] wiimote_payload = new byte[MAX_WIIMOTES][MAX_PAYLOAD];
|
||||||
|
|
||||||
|
private static void RequestPermission()
|
||||||
|
{
|
||||||
|
HashMap<String, UsbDevice> devices = manager.getDeviceList();
|
||||||
|
for (Map.Entry<String, UsbDevice> pair : devices.entrySet())
|
||||||
|
{
|
||||||
|
UsbDevice dev = (UsbDevice) pair.getValue();
|
||||||
|
if (dev.getProductId() == NINTENDO_WIIMOTE_PRODUCT_ID && dev.getVendorId() == NINTENDO_VENDOR_ID)
|
||||||
|
{
|
||||||
|
if (!manager.hasPermission(dev))
|
||||||
|
{
|
||||||
|
Log.warning("Requesting permission for Wiimote adapter");
|
||||||
|
Intent intent = new Intent();
|
||||||
|
PendingIntent pend_intent;
|
||||||
|
intent.setClass(NativeLibrary.sEmulationActivity, USBPermService.class);
|
||||||
|
pend_intent = PendingIntent.getService(NativeLibrary.sEmulationActivity, 0, intent, 0);
|
||||||
|
manager.requestPermission(dev, pend_intent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean QueryAdapter()
|
||||||
|
{
|
||||||
|
HashMap<String, UsbDevice> devices = manager.getDeviceList();
|
||||||
|
for (Map.Entry<String, UsbDevice> pair : devices.entrySet())
|
||||||
|
{
|
||||||
|
UsbDevice dev = (UsbDevice) pair.getValue();
|
||||||
|
if (dev.getProductId() == NINTENDO_WIIMOTE_PRODUCT_ID && dev.getVendorId() == NINTENDO_VENDOR_ID)
|
||||||
|
{
|
||||||
|
if (manager.hasPermission(dev))
|
||||||
|
return true;
|
||||||
|
else
|
||||||
|
RequestPermission();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int Input(int index)
|
||||||
|
{
|
||||||
|
return usb_con.bulkTransfer(usb_in[index], wiimote_payload[index], MAX_PAYLOAD, TIMEOUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int Output(int index, byte[] buf, int size)
|
||||||
|
{
|
||||||
|
byte report_number = buf[0];
|
||||||
|
|
||||||
|
// Remove the report number from the buffer
|
||||||
|
buf = Arrays.copyOfRange(buf, 1, buf.length);
|
||||||
|
size--;
|
||||||
|
|
||||||
|
final int LIBUSB_REQUEST_TYPE_CLASS = (1 << 5);
|
||||||
|
final int LIBUSB_RECIPIENT_INTERFACE = 0x1;
|
||||||
|
final int LIBUSB_ENDPOINT_OUT = 0;
|
||||||
|
|
||||||
|
final int HID_SET_REPORT = 0x9;
|
||||||
|
final int HID_OUTPUT = (2 << 8);
|
||||||
|
|
||||||
|
int write = usb_con.controlTransfer(
|
||||||
|
LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE | LIBUSB_ENDPOINT_OUT,
|
||||||
|
HID_SET_REPORT,
|
||||||
|
HID_OUTPUT | report_number,
|
||||||
|
index,
|
||||||
|
buf, size,
|
||||||
|
1000);
|
||||||
|
|
||||||
|
if (write < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return write + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean OpenAdapter()
|
||||||
|
{
|
||||||
|
// If the adapter is already open. Don't attempt to do it again
|
||||||
|
if (usb_con != null && usb_con.getFileDescriptor() != -1)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
HashMap<String, UsbDevice> devices = manager.getDeviceList();
|
||||||
|
for (Map.Entry<String, UsbDevice> pair : devices.entrySet())
|
||||||
|
{
|
||||||
|
UsbDevice dev = (UsbDevice) pair.getValue();
|
||||||
|
if (dev.getProductId() == NINTENDO_WIIMOTE_PRODUCT_ID && dev.getVendorId() == NINTENDO_VENDOR_ID)
|
||||||
|
{
|
||||||
|
if (manager.hasPermission(dev))
|
||||||
|
{
|
||||||
|
usb_con = manager.openDevice(dev);
|
||||||
|
UsbConfiguration conf = dev.getConfiguration(0);
|
||||||
|
|
||||||
|
Log.info("Number of configurations: " + dev.getConfigurationCount());
|
||||||
|
Log.info("Number of Interfaces: " + dev.getInterfaceCount());
|
||||||
|
Log.info("Number of Interfaces from conf: " + conf.getInterfaceCount());
|
||||||
|
|
||||||
|
// Sometimes the interface count is returned as zero.
|
||||||
|
// Means the device needs to be unplugged and plugged back in again
|
||||||
|
if (dev.getInterfaceCount() > 0)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < MAX_WIIMOTES; ++i)
|
||||||
|
{
|
||||||
|
// One interface per Wiimote
|
||||||
|
usb_intf[i] = dev.getInterface(i);
|
||||||
|
usb_con.claimInterface(usb_intf[i], true);
|
||||||
|
|
||||||
|
// One endpoint per Wiimote. Input only
|
||||||
|
// Output reports go through the control channel.
|
||||||
|
usb_in[i] = usb_intf[i].getEndpoint(0);
|
||||||
|
Log.info("Interface " + i + " endpoint count:" + usb_intf[i].getEndpointCount());
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// XXX: Message that the device was found, but it needs to be unplugged and plugged back in?
|
||||||
|
usb_con.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
|
@ -59,6 +59,11 @@
|
||||||
android:text="@string/settings"
|
android:text="@string/settings"
|
||||||
style="@style/InGameMenuOption"/>
|
style="@style/InGameMenuOption"/>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/menu_refresh_wiimotes"
|
||||||
|
android:text="@string/emulation_refresh_wiimotes"
|
||||||
|
style="@style/InGameMenuOption"/>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/menu_exit"
|
android:id="@+id/menu_exit"
|
||||||
android:text="@string/overlay_exit_emulation"
|
android:text="@string/overlay_exit_emulation"
|
||||||
|
|
|
@ -346,6 +346,7 @@
|
||||||
<string name="emulation_toggle_input">Toggle Touch Controls</string>
|
<string name="emulation_toggle_input">Toggle Touch Controls</string>
|
||||||
<string name="emulation_quicksave">Quick Save</string>
|
<string name="emulation_quicksave">Quick Save</string>
|
||||||
<string name="emulation_quickload">Quick Load</string>
|
<string name="emulation_quickload">Quick Load</string>
|
||||||
|
<string name="emulation_refresh_wiimotes">Refresh Wiimotes</string>
|
||||||
|
|
||||||
<!-- GC Adapter Menu-->
|
<!-- GC Adapter Menu-->
|
||||||
<string name="gc_adapter_rumble">Enable Vibration</string>
|
<string name="gc_adapter_rumble">Enable Vibration</string>
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
#include "Core/Host.h"
|
#include "Core/Host.h"
|
||||||
#include "Core/State.h"
|
#include "Core/State.h"
|
||||||
#include "Core/HW/Wiimote.h"
|
#include "Core/HW/Wiimote.h"
|
||||||
|
#include "Core/HW/WiimoteReal/WiimoteReal.h"
|
||||||
#include "Core/PowerPC/JitInterface.h"
|
#include "Core/PowerPC/JitInterface.h"
|
||||||
#include "Core/PowerPC/PowerPC.h"
|
#include "Core/PowerPC/PowerPC.h"
|
||||||
#include "Core/PowerPC/Profiler.h"
|
#include "Core/PowerPC/Profiler.h"
|
||||||
|
@ -632,6 +633,10 @@ JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_SurfaceDestr
|
||||||
Renderer::s_ChangedSurface.Wait();
|
Renderer::s_ChangedSurface.Wait();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_RefreshWiimotes(JNIEnv *env, jobject obj)
|
||||||
|
{
|
||||||
|
WiimoteReal::Refresh();
|
||||||
|
}
|
||||||
|
|
||||||
JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_Run(JNIEnv *env, jobject obj)
|
JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_Run(JNIEnv *env, jobject obj)
|
||||||
{
|
{
|
||||||
|
@ -646,6 +651,8 @@ JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_Run(JNIEnv *
|
||||||
UICommon::SetUserDirectory(g_set_userpath);
|
UICommon::SetUserDirectory(g_set_userpath);
|
||||||
UICommon::Init();
|
UICommon::Init();
|
||||||
|
|
||||||
|
WiimoteReal::InitAdapterClass();
|
||||||
|
|
||||||
// No use running the loop when booting fails
|
// No use running the loop when booting fails
|
||||||
if ( BootManager::BootCore( g_filename.c_str() ) )
|
if ( BootManager::BootCore( g_filename.c_str() ) )
|
||||||
{
|
{
|
||||||
|
|
|
@ -256,6 +256,8 @@ elseif(UNIX)
|
||||||
if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux" AND BLUEZ_FOUND)
|
if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux" AND BLUEZ_FOUND)
|
||||||
set(SRCS ${SRCS} HW/WiimoteReal/IONix.cpp)
|
set(SRCS ${SRCS} HW/WiimoteReal/IONix.cpp)
|
||||||
set(LIBS ${LIBS} bluetooth)
|
set(LIBS ${LIBS} bluetooth)
|
||||||
|
elseif(ANDROID)
|
||||||
|
set(SRCS ${SRCS} HW/WiimoteReal/IOAndroid.cpp)
|
||||||
else()
|
else()
|
||||||
set(SRCS ${SRCS} HW/WiimoteReal/IODummy.cpp)
|
set(SRCS ${SRCS} HW/WiimoteReal/IODummy.cpp)
|
||||||
endif()
|
endif()
|
||||||
|
|
|
@ -0,0 +1,165 @@
|
||||||
|
// Copyright 2016 Dolphin Emulator Project
|
||||||
|
// Licensed under GPLv2+
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#include <jni.h>
|
||||||
|
|
||||||
|
#include "Common/CommonTypes.h"
|
||||||
|
#include "Common/Event.h"
|
||||||
|
#include "Common/Flag.h"
|
||||||
|
#include "Common/StringUtil.h"
|
||||||
|
#include "Common/Thread.h"
|
||||||
|
#include "Common/Timer.h"
|
||||||
|
#include "Common/Logging/Log.h"
|
||||||
|
|
||||||
|
#include "Core/HW/WiimoteReal/WiimoteReal.h"
|
||||||
|
|
||||||
|
// Global java_vm class
|
||||||
|
extern JavaVM* g_java_vm;
|
||||||
|
|
||||||
|
namespace WiimoteReal
|
||||||
|
{
|
||||||
|
|
||||||
|
// Java classes
|
||||||
|
static jclass s_adapter_class;
|
||||||
|
|
||||||
|
class WiimoteAndroid final : public Wiimote
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
WiimoteAndroid(int index);
|
||||||
|
~WiimoteAndroid() override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool ConnectInternal() override;
|
||||||
|
void DisconnectInternal() override;
|
||||||
|
bool IsConnected() const override;
|
||||||
|
void IOWakeup() {}
|
||||||
|
int IORead(u8* buf) override;
|
||||||
|
int IOWrite(u8 const* buf, size_t len) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
int m_mayflash_index;
|
||||||
|
bool is_connected = true;
|
||||||
|
|
||||||
|
JNIEnv* m_env;
|
||||||
|
|
||||||
|
jmethodID m_input_func;
|
||||||
|
jmethodID m_output_func;
|
||||||
|
|
||||||
|
jbyteArray m_java_wiimote_payload;
|
||||||
|
};
|
||||||
|
|
||||||
|
WiimoteScanner::WiimoteScanner()
|
||||||
|
{}
|
||||||
|
|
||||||
|
WiimoteScanner::~WiimoteScanner()
|
||||||
|
{}
|
||||||
|
|
||||||
|
void WiimoteScanner::Update()
|
||||||
|
{}
|
||||||
|
|
||||||
|
void WiimoteScanner::FindWiimotes(std::vector<Wiimote*>& found_wiimotes, Wiimote*& found_board)
|
||||||
|
{
|
||||||
|
found_wiimotes.clear();
|
||||||
|
found_board = nullptr;
|
||||||
|
|
||||||
|
NOTICE_LOG(WIIMOTE, "Finding Wiimotes");
|
||||||
|
|
||||||
|
JNIEnv* env;
|
||||||
|
int get_env_status = g_java_vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6);
|
||||||
|
|
||||||
|
if (get_env_status == JNI_EDETACHED)
|
||||||
|
g_java_vm->AttachCurrentThread(&env, nullptr);
|
||||||
|
|
||||||
|
jmethodID openadapter_func = env->GetStaticMethodID(s_adapter_class, "OpenAdapter", "()Z");
|
||||||
|
jmethodID queryadapter_func = env->GetStaticMethodID(s_adapter_class, "QueryAdapter", "()Z");
|
||||||
|
|
||||||
|
if (env->CallStaticBooleanMethod(s_adapter_class, queryadapter_func) &&
|
||||||
|
env->CallStaticBooleanMethod(s_adapter_class, openadapter_func))
|
||||||
|
{
|
||||||
|
for (int i = 0; i < MAX_WIIMOTES; ++i)
|
||||||
|
found_wiimotes.emplace_back(new WiimoteAndroid(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (get_env_status == JNI_EDETACHED)
|
||||||
|
g_java_vm->DetachCurrentThread();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WiimoteScanner::IsReady() const
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
WiimoteAndroid::WiimoteAndroid(int index)
|
||||||
|
: Wiimote(), m_mayflash_index(index)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
WiimoteAndroid::~WiimoteAndroid()
|
||||||
|
{
|
||||||
|
Shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Connect to a Wiimote with a known address.
|
||||||
|
bool WiimoteAndroid::ConnectInternal()
|
||||||
|
{
|
||||||
|
g_java_vm->AttachCurrentThread(&m_env, nullptr);
|
||||||
|
|
||||||
|
jfieldID payload_field = m_env->GetStaticFieldID(s_adapter_class, "wiimote_payload", "[[B");
|
||||||
|
jobjectArray payload_object = reinterpret_cast<jobjectArray>(m_env->GetStaticObjectField(s_adapter_class, payload_field));
|
||||||
|
m_java_wiimote_payload = (jbyteArray)m_env->GetObjectArrayElement(payload_object, m_mayflash_index);
|
||||||
|
|
||||||
|
// Get function pointers
|
||||||
|
m_input_func = m_env->GetStaticMethodID(s_adapter_class, "Input", "(I)I");
|
||||||
|
m_output_func = m_env->GetStaticMethodID(s_adapter_class, "Output", "(I[BI)I");
|
||||||
|
|
||||||
|
is_connected = true;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WiimoteAndroid::DisconnectInternal()
|
||||||
|
{
|
||||||
|
g_java_vm->DetachCurrentThread();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WiimoteAndroid::IsConnected() const
|
||||||
|
{
|
||||||
|
return is_connected;
|
||||||
|
}
|
||||||
|
|
||||||
|
// positive = read packet
|
||||||
|
// negative = didn't read packet
|
||||||
|
// zero = error
|
||||||
|
int WiimoteAndroid::IORead(u8* buf)
|
||||||
|
{
|
||||||
|
int read_size = m_env->CallStaticIntMethod(s_adapter_class, m_input_func, m_mayflash_index);
|
||||||
|
jbyte* java_data = m_env->GetByteArrayElements(m_java_wiimote_payload, nullptr);
|
||||||
|
memcpy(buf + 1, java_data, std::min(MAX_PAYLOAD - 1, read_size));
|
||||||
|
buf[0] = 0xA1;
|
||||||
|
m_env->ReleaseByteArrayElements(m_java_wiimote_payload, java_data, 0);
|
||||||
|
return read_size <= 0 ? read_size : read_size + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int WiimoteAndroid::IOWrite(u8 const* buf, size_t len)
|
||||||
|
{
|
||||||
|
jbyteArray output_array = m_env->NewByteArray(len);
|
||||||
|
jbyte* output = m_env->GetByteArrayElements(output_array, nullptr);
|
||||||
|
memcpy(output, buf, len);
|
||||||
|
m_env->ReleaseByteArrayElements(output_array, output, 0);
|
||||||
|
int written = m_env->CallStaticIntMethod(s_adapter_class, m_output_func, m_mayflash_index, output_array, len);
|
||||||
|
m_env->DeleteLocalRef(output_array);
|
||||||
|
return written;
|
||||||
|
}
|
||||||
|
|
||||||
|
void InitAdapterClass()
|
||||||
|
{
|
||||||
|
JNIEnv* env;
|
||||||
|
g_java_vm->AttachCurrentThread(&env, nullptr);
|
||||||
|
|
||||||
|
jclass adapter_class = env->FindClass("org/dolphinemu/dolphinemu/utils/Java_WiimoteAdapter");
|
||||||
|
s_adapter_class = reinterpret_cast<jclass>(env->NewGlobalRef(adapter_class));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -161,4 +161,8 @@ void ChangeWiimoteSource(unsigned int index, int source);
|
||||||
bool IsValidBluetoothName(const std::string& name);
|
bool IsValidBluetoothName(const std::string& name);
|
||||||
bool IsBalanceBoardName(const std::string& name);
|
bool IsBalanceBoardName(const std::string& name);
|
||||||
|
|
||||||
|
#ifdef ANDROID
|
||||||
|
void InitAdapterClass();
|
||||||
|
#endif
|
||||||
|
|
||||||
} // WiimoteReal
|
} // WiimoteReal
|
||||||
|
|
Loading…
Reference in New Issue