Skip to content

Instantly share code, notes, and snippets.

@mendsley
Last active December 12, 2015 04:08
Show Gist options
  • Save mendsley/4712333 to your computer and use it in GitHub Desktop.
Save mendsley/4712333 to your computer and use it in GitHub Desktop.
Sketchy NDK controller support for OUYA... using unexported
//------------------------------------------------------------------------------
// Heat Engine - Copyright (c) 2011-2013 by Carbon Games Inc.
//------------------------------------------------------------------------------
#ifndef __INPUTPADDEVICE_H__
#define __INPUTPADDEVICE_H__
struct PadDeviceState
{
PadDeviceState()
: buttons(0)
{
leftThumb[0] = 0;
leftThumb[1] = 0;
rightThumb[0] = 0;
rightThumb[1] = 0;
}
void Reset()
{
buttons = 0;
leftThumb[0] = 0;
leftThumb[1] = 0;
rightThumb[0] = 0;
rightThumb[1] = 0;
}
uint32_t buttons;
int16_t leftThumb[2];
int16_t rightThumb[2];
};
void padDeviceInit();
bool padDeviceUpdateFocus();
bool padRumbleSupport();
void padMapControllerToDevice( int _controller, int _deviceIndex );
void padRumbleSet( int _controller, float _small, float _big );
bool padDeviceValid( int _controller );
void padGetState( int _controller, PadDeviceState* _state );
#endif // __INPUTPADDEVICE_H__
//------------------------------------------------------------------------------
// Heat Engine - Copyright (c) 2013 by Carbon Games Inc.
//------------------------------------------------------------------------------
#ifndef INPUTPAD_IMPL
#error Do not include this file directly
#endif
#include <limits.h>
#include <stdint.h>
#include <dlfcn.h>
#include <android/input.h>
#include "input/old/inputButtons.h"
#include "input/old/inputPad.h"
namespace {
struct OuyaButtonMapping {
int code;
uint32_t mapping;
};
}
static PadDeviceState g_pad0;
enum {
OUYA_PAD_BUTTON_O = 96,
OUYA_PAD_BUTTON_U = 99,
OUYA_PAD_BUTTON_Y = 100,
OUYA_PAD_BUTTON_A = 97,
OUYA_PAD_BUTTON_L1 = 102,
OUYA_PAD_BUTTON_L2 = 104,
OUYA_PAD_BUTTON_R1 = 103,
OUYA_PAD_BUTTON_R2 = 105,
OUYA_PAD_BUTTON_SYSTEM = 3,
OUYA_PAD_BUTTON_PADUP = 19,
OUYA_PAD_BUTTON_PADRIGHT = 22,
OUYA_PAD_BUTTON_PADDOWN = 20,
OUYA_PAD_BUTTON_PADLEFT = 21,
OUYA_PAD_BUTTON_L3 = 106,
OUYA_PAD_BUTTON_R3 = 107,
};
static const OuyaButtonMapping g_buttonMappings[] = {
{OUYA_PAD_BUTTON_O, 1 << PadButton::A},
{OUYA_PAD_BUTTON_U, 1 << PadButton::X},
{OUYA_PAD_BUTTON_Y, 1 << PadButton::Y},
{OUYA_PAD_BUTTON_A, 1 << PadButton::B},
{OUYA_PAD_BUTTON_L1, 1 << PadButton::LShoulder},
{OUYA_PAD_BUTTON_L2, 1 << PadButton::LeftTrigger},
{OUYA_PAD_BUTTON_R1, 1 << PadButton::RShoulder},
{OUYA_PAD_BUTTON_R2, 1 << PadButton::RightTrigger},
{OUYA_PAD_BUTTON_PADUP, 1 << PadButton::D_Up},
{OUYA_PAD_BUTTON_PADRIGHT, 1 << PadButton::D_Right},
{OUYA_PAD_BUTTON_PADDOWN, 1 << PadButton::D_Down},
{OUYA_PAD_BUTTON_PADLEFT, 1 << PadButton::D_Left},
{OUYA_PAD_BUTTON_L3, 1 << PadButton::LStick},
{OUYA_PAD_BUTTON_R3, 1 << PadButton::RStick},
};
enum {
OUYA_PAD_AXIS_LS_X = 0,
OUYA_PAD_AXIS_LS_Y = 1,
OUYA_PAD_AXIS_RS_X = 11,
OUYA_PAD_AXIS_RS_Y = 14,
OUYA_PAD_AXIS_L2 = 17,
OUYA_PAD_AXIS_R2 = 18,
};
static const int AINPUT_SOURCE_CLASS_JOYSTICK = 0x10;
typedef float (*GetAxisValueFunc)(const AInputEvent* motion_event, int32_t axis, size_t pointerId);
static GetAxisValueFunc AMotionEvent_getAxisValue;
static const int c_ncontrollers = 8;
static int g_controllerMapping[c_ncontrollers];
void padDeviceInit() {
void* dlandroid = dlopen("libandroid.so", 0);
HEATFATAL(dlandroid, HEAT_FATAL_UNSPECIFIED, "Couldn't open libandroid.so!");
AMotionEvent_getAxisValue = (GetAxisValueFunc)dlsym(dlandroid, "AMotionEvent_getAxisValue");
HEATFATAL(AMotionEvent_getAxisValue, HEAT_FATAL_UNSPECIFIED, "OUYA doesn't support AMotionEvent_getAxisValue!");
}
bool padDeviceUpdateFocus() {
return true;
}
bool padRumbleSupport() {
return false;
}
void padMapControllerToDevice( int _controller, int _deviceIndex ) {
if (_controller < c_ncontrollers) {
g_controllerMapping[_controller] = _deviceIndex;
}
}
void padRumbleSet( int _controller, float _small, float _big ) {
}
bool padDeviceValid( int _controller ) {
return _controller < c_ncontrollers && g_controllerMapping[_controller] == 0;
}
void padGetState( int _controller, PadDeviceState* _state ) {
*_state = g_pad0;
}
bool android_UpdatePadState(AInputEvent* event) {
if (AInputEvent_getSource(event) & AINPUT_SOURCE_CLASS_JOYSTICK) {
const float lx = AMotionEvent_getAxisValue(event, OUYA_PAD_AXIS_LS_X, 0);
const float ly = AMotionEvent_getAxisValue(event, OUYA_PAD_AXIS_LS_Y, 0);
const float rx = AMotionEvent_getAxisValue(event, OUYA_PAD_AXIS_RS_X, 0);
const float ry = AMotionEvent_getAxisValue(event, OUYA_PAD_AXIS_RS_Y, 0);
g_pad0.leftThumb[0] = int16_t(lx * SHRT_MAX);
g_pad0.leftThumb[1] = int16_t(-ly * SHRT_MAX);
g_pad0.rightThumb[0] = int16_t(rx * SHRT_MAX);
g_pad0.rightThumb[1] = int16_t(-ry * SHRT_MAX);
return true;
}
if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_KEY) {
const int action = AKeyEvent_getAction(event);
const int32_t keyCode = AKeyEvent_getKeyCode(event);
static const int nbuttons = sizeof(g_buttonMappings)/sizeof(g_buttonMappings[0]);
for (int ii = 0; ii < nbuttons; ++ii) {
if (g_buttonMappings[ii].code == keyCode) {
if (action == AKEY_EVENT_ACTION_DOWN) {
g_pad0.buttons |= g_buttonMappings[ii].mapping;
} else if (action == AKEY_EVENT_ACTION_UP) {
g_pad0.buttons &= ~g_buttonMappings[ii].mapping;
}
return true;
}
}
}
return false;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment