(iOS) Add initial MFi game controller support.

This commit is contained in:
meancoot 2013-12-27 20:12:19 -05:00
parent f6362b459c
commit aee6bce679
7 changed files with 186 additions and 2 deletions

View File

@ -20,6 +20,8 @@
96337E82176AC6E5004685F3 /* utility.m in Sources */ = {isa = PBXBuildFile; fileRef = 96337E81176AC6E5004685F3 /* utility.m */; };
96366C5516C9AC3300D64A22 /* CoreAudio.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 96366C5416C9AC3300D64A22 /* CoreAudio.framework */; };
96366C5916C9ACF500D64A22 /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 96366C5816C9ACF500D64A22 /* AudioToolbox.framework */; };
963C3C32186E3D2600A6EB1E /* apple_gamecontroller.m in Sources */ = {isa = PBXBuildFile; fileRef = 963C3C31186E3D2600A6EB1E /* apple_gamecontroller.m */; };
963C3C34186E3DED00A6EB1E /* GameController.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 963C3C33186E3DED00A6EB1E /* GameController.framework */; settings = {ATTRIBUTES = (Required, ); }; };
963F5AC816CC523B009BBD19 /* RAGameView.m in Sources */ = {isa = PBXBuildFile; fileRef = 963F5AC516CC523B009BBD19 /* RAGameView.m */; };
9646869517BBBEAE00C5EA69 /* platform.m in Sources */ = {isa = PBXBuildFile; fileRef = 9646869417BBBEAE00C5EA69 /* platform.m */; };
966B9CBD16E41E7A005B61E1 /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 966B9CB816E41E7A005B61E1 /* Default-568h@2x.png */; };
@ -54,6 +56,9 @@
96355CD11788CF190010DBFA /* RetroArch_Apple.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RetroArch_Apple.h; sourceTree = "<group>"; };
96366C5416C9AC3300D64A22 /* CoreAudio.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreAudio.framework; path = System/Library/Frameworks/CoreAudio.framework; sourceTree = SDKROOT; };
96366C5816C9ACF500D64A22 /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = System/Library/Frameworks/AudioToolbox.framework; sourceTree = SDKROOT; };
963C3C30186E3D2600A6EB1E /* apple_gamecontroller.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = apple_gamecontroller.h; sourceTree = "<group>"; };
963C3C31186E3D2600A6EB1E /* apple_gamecontroller.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = apple_gamecontroller.m; sourceTree = "<group>"; };
963C3C33186E3DED00A6EB1E /* GameController.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GameController.framework; path = System/Library/Frameworks/GameController.framework; sourceTree = SDKROOT; };
963F5AC516CC523B009BBD19 /* RAGameView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RAGameView.m; sourceTree = "<group>"; };
9646869417BBBEAE00C5EA69 /* platform.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = platform.m; path = iOS/platform.m; sourceTree = SOURCE_ROOT; };
966B9CB816E41E7A005B61E1 /* Default-568h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-568h@2x.png"; sourceTree = "<group>"; };
@ -86,6 +91,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
963C3C34186E3DED00A6EB1E /* GameController.framework in Frameworks */,
50CCC828185E0E7D001F5BC8 /* CoreLocation.framework in Frameworks */,
501881EE184BB54C006F665D /* CoreMedia.framework in Frameworks */,
501881EC184BAD6D006F665D /* AVFoundation.framework in Frameworks */,
@ -144,6 +150,7 @@
96AFAE2816C1D4EA009DE44C /* Frameworks */ = {
isa = PBXGroup;
children = (
963C3C33186E3DED00A6EB1E /* GameController.framework */,
50CCC827185E0E7D001F5BC8 /* CoreLocation.framework */,
501881ED184BB54C006F665D /* CoreMedia.framework */,
501881EB184BAD6D006F665D /* AVFoundation.framework */,
@ -162,6 +169,8 @@
96AFAE3316C1D4EA009DE44C /* common */ = {
isa = PBXGroup;
children = (
963C3C30186E3D2600A6EB1E /* apple_gamecontroller.h */,
963C3C31186E3D2600A6EB1E /* apple_gamecontroller.m */,
509FC978183F9F18007A5A30 /* menu.m */,
9646869417BBBEAE00C5EA69 /* platform.m */,
967894571788EAAE00D6CA69 /* browser.m */,
@ -304,6 +313,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
963C3C32186E3D2600A6EB1E /* apple_gamecontroller.m in Sources */,
96297A0F16C5AEA100E6DCE0 /* main.m in Sources */,
963F5AC816CC523B009BBD19 /* RAGameView.m in Sources */,
D48581DE16F823F9004BEB17 /* griffin.c in Sources */,

View File

@ -0,0 +1,22 @@
/* RetroArch - A frontend for libretro.
* Copyright (C) 2013 - Jason Fetters
*
* RetroArch is free software: you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* RetroArch 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with RetroArch.
* If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __APPLE_RARCH_GAMECONTROLLER_H__
#define __APPLE_RARCH_GAMECONTROLLER_H__
void apple_gamecontroller_init();
void apple_gamecontroller_poll_all();
#endif

View File

@ -0,0 +1,125 @@
/* RetroArch - A frontend for libretro.
* Copyright (C) 2013 - Jason Fetters
*
* RetroArch is free software: you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* RetroArch 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with RetroArch.
* If not, see <http://www.gnu.org/licenses/>.
*/
#include <Availability.h>
#if __IPHONE_7_0
#define IS_PRESSED(x) (x.value > .01f)
#import <GameController/GameController.h>
#include "apple_input.h"
static void apple_gamecontroller_poll(GCController* controller)
{
if (!controller || controller.playerIndex == MAX_PLAYERS)
return;
uint32_t slot = controller.playerIndex;
g_current_input_data.pad_buttons[slot] = 0;
memset(g_current_input_data.pad_axis[slot], 0, sizeof(g_current_input_data.pad_axis[0]));
if (controller.extendedGamepad)
{
GCExtendedGamepad* gp = controller.extendedGamepad;
g_current_input_data.pad_buttons[slot] |= IS_PRESSED(gp.dpad.up) ? 1 : 0;
g_current_input_data.pad_buttons[slot] |= IS_PRESSED(gp.dpad.down) ? 2 : 0;
g_current_input_data.pad_buttons[slot] |= IS_PRESSED(gp.dpad.left) ? 4 : 0;
g_current_input_data.pad_buttons[slot] |= IS_PRESSED(gp.dpad.right) ? 8 : 0;
g_current_input_data.pad_buttons[slot] |= IS_PRESSED(gp.buttonA) ? 16 : 0;
g_current_input_data.pad_buttons[slot] |= IS_PRESSED(gp.buttonB) ? 32 : 0;
g_current_input_data.pad_buttons[slot] |= IS_PRESSED(gp.buttonX) ? 64 : 0;
g_current_input_data.pad_buttons[slot] |= IS_PRESSED(gp.buttonY) ? 128 : 0;
g_current_input_data.pad_buttons[slot] |= IS_PRESSED(gp.leftShoulder) ? 256 : 0;
g_current_input_data.pad_buttons[slot] |= IS_PRESSED(gp.rightShoulder) ? 512 : 0;
g_current_input_data.pad_buttons[slot] |= IS_PRESSED(gp.leftTrigger) ? 1024 : 0;
g_current_input_data.pad_buttons[slot] |= IS_PRESSED(gp.rightTrigger) ? 2048 : 0;
g_current_input_data.pad_axis[slot][0] = gp.leftThumbstick.xAxis.value * 32767.0f;
g_current_input_data.pad_axis[slot][1] = gp.leftThumbstick.yAxis.value * 32767.0f;
g_current_input_data.pad_axis[slot][2] = gp.rightThumbstick.xAxis.value * 32767.0f;
g_current_input_data.pad_axis[slot][3] = gp.rightThumbstick.yAxis.value * 32767.0f;
}
else if (controller.gamepad)
{
GCGamepad* gp = controller.gamepad;
g_current_input_data.pad_buttons[slot] |= IS_PRESSED(gp.dpad.up) ? 1 : 0;
g_current_input_data.pad_buttons[slot] |= IS_PRESSED(gp.dpad.down) ? 2 : 0;
g_current_input_data.pad_buttons[slot] |= IS_PRESSED(gp.dpad.left) ? 4 : 0;
g_current_input_data.pad_buttons[slot] |= IS_PRESSED(gp.dpad.right) ? 8 : 0;
g_current_input_data.pad_buttons[slot] |= IS_PRESSED(gp.buttonA) ? 16 : 0;
g_current_input_data.pad_buttons[slot] |= IS_PRESSED(gp.buttonB) ? 32 : 0;
g_current_input_data.pad_buttons[slot] |= IS_PRESSED(gp.buttonX) ? 64 : 0;
g_current_input_data.pad_buttons[slot] |= IS_PRESSED(gp.buttonY) ? 128 : 0;
g_current_input_data.pad_buttons[slot] |= IS_PRESSED(gp.leftShoulder) ? 256 : 0;
g_current_input_data.pad_buttons[slot] |= IS_PRESSED(gp.rightShoulder) ? 512 : 0;
}
}
void apple_gamecontroller_poll_all()
{
NSArray* controllers = [GCController controllers];
for (int i = 0; i != [controllers count]; i ++)
apple_gamecontroller_poll([controllers objectAtIndex:i]);
}
void apple_gamecontroller_connect(GCController* controller)
{
int32_t slot = apple_joypad_connect_gcapi();
controller.playerIndex = (slot >= 0 && slot < MAX_PLAYERS) ? slot : GCControllerPlayerIndexUnset;
/*
if (controller.playerIndex == GCControllerPlayerIndexUnset)
return;
else if (controller.extendedGamepad)
controller.extendedGamepad.valueChangedHandler =
^(GCExtendedGamepad *gamepad, GCControllerElement *element) { apple_gamecontroller_poll(gamepad.controller); };
else if (controller.gamepad)
controller.gamepad.valueChangedHandler =
^(GCGamepad *gamepad, GCControllerElement *element) { apple_gamecontroller_poll(gamepad.controller); };
*/
}
void apple_gamecontroller_disconnect(GCController* controller)
{
if (controller.playerIndex == GCControllerPlayerIndexUnset)
return;
apple_joypad_disconnect(controller.playerIndex);
}
void apple_gamecontroller_init()
{
[[NSNotificationCenter defaultCenter] addObserverForName:GCControllerDidConnectNotification object:nil queue:[NSOperationQueue mainQueue]
usingBlock:^(NSNotification *note) { apple_gamecontroller_connect([note object]); } ];
[[NSNotificationCenter defaultCenter] addObserverForName:GCControllerDidDisconnectNotification object:nil queue:[NSOperationQueue mainQueue]
usingBlock:^(NSNotification *note) { apple_gamecontroller_disconnect([note object]); } ];
}
#else
void apple_gamecontroller_init()
{
}
void apple_gamecontroller_poll_all()
{
}
#endif

View File

@ -16,6 +16,7 @@
#include <unistd.h>
#include "apple_gamecontroller.h"
#include "input/input_common.h"
#include "apple_input.h"
#include "general.h"
@ -108,6 +109,7 @@ void apple_input_handle_key_event(unsigned keycode, bool down)
int32_t apple_input_find_any_key(void)
{
apple_gamecontroller_poll_all();
input_init_keyboard_lut(apple_key_map_hidusage);
for (int i = 0; apple_key_name_map[i].hid_id; i++)
@ -119,6 +121,8 @@ int32_t apple_input_find_any_key(void)
int32_t apple_input_find_any_button(uint32_t port)
{
apple_gamecontroller_poll_all();
uint32_t buttons = g_current_input_data.pad_buttons[port] |
((port == 0) ? apple_input_get_icade_buttons() : 0);
@ -132,6 +136,8 @@ int32_t apple_input_find_any_button(uint32_t port)
int32_t apple_input_find_any_axis(uint32_t port)
{
apple_gamecontroller_poll_all();
for (int i = 0; i < 4; i++)
{
int16_t value = g_current_input_data.pad_axis[port][i];
@ -167,6 +173,7 @@ static void *apple_input_init(void)
static void apple_input_poll(void *data)
{
apple_gamecontroller_poll_all();
memcpy(&g_polled_input_data, &g_current_input_data, sizeof(apple_input_data_t));
for (int i = 0; i != g_polled_input_data.touch_count; i ++)

View File

@ -55,6 +55,7 @@ struct apple_pad_interface
// Joypad data
int32_t apple_joypad_connect(const char* name, struct apple_pad_connection* connection);
int32_t apple_joypad_connect_gcapi();
void apple_joypad_disconnect(uint32_t slot);
void apple_joypad_packet(uint32_t slot, uint8_t* data, uint32_t length);

View File

@ -33,6 +33,8 @@ typedef struct
bool used;
struct apple_pad_interface* iface;
void* data;
bool is_gcapi;
} joypad_slot_t;
static joypad_slot_t slots[MAX_PLAYERS];
@ -73,6 +75,20 @@ int32_t apple_joypad_connect(const char* name, struct apple_pad_connection* conn
return slot;
}
int32_t apple_joypad_connect_gcapi()
{
int32_t slot = find_empty_slot();
if (slot >= 0 && slot < MAX_PLAYERS)
{
joypad_slot_t* s = &slots[slot];
s->used = true;
s->is_gcapi = true;
}
return slot;
}
void apple_joypad_disconnect(uint32_t slot)
{
if (slot < MAX_PLAYERS && slots[slot].used)
@ -82,7 +98,7 @@ void apple_joypad_disconnect(uint32_t slot)
if (s->iface && s->data)
s->iface->disconnect(s->data);
s->used = false;
memset(s, 0, sizeof(joypad_slot_t));
}
}

View File

@ -20,6 +20,7 @@
#include "apple/common/apple_input.h"
#include "apple/common/setting_data.h"
#include "apple/common/apple_gamecontroller.h"
#include "menu.h"
#import "views.h"
@ -221,7 +222,9 @@ static void handle_touch_event(NSArray* touches)
if (!core_list || core_list->count == 0)
apple_display_alert(@"No libretro cores were found. You will not be able to run any content.", 0);
apple_gamecontroller_init();
// Load system config
const rarch_setting_t* frontend_settings = apple_get_frontend_settings();
setting_data_reset(frontend_settings);