mirror of
https://github.com/libretro/RetroArch
synced 2025-03-23 01:21:47 +00:00
Merge branch 'ios' of git://github.com/meancoot/RetroArch
This commit is contained in:
commit
3bc487be87
@ -22,8 +22,7 @@
|
||||
#include "../boolean.h"
|
||||
#include <pthread.h>
|
||||
|
||||
#include <CoreAudio/CoreAudio.h>
|
||||
#include <CoreServices/CoreServices.h>
|
||||
#include <CoreAudio/CoreAudioTypes.h>
|
||||
#include <AudioUnit/AudioUnit.h>
|
||||
#include <AudioUnit/AUComponent.h>
|
||||
|
||||
@ -32,7 +31,7 @@ typedef struct coreaudio
|
||||
pthread_mutex_t lock;
|
||||
pthread_cond_t cond;
|
||||
|
||||
ComponentInstance dev;
|
||||
AudioComponentInstance dev;
|
||||
bool dev_alive;
|
||||
|
||||
fifo_buffer_t *buffer;
|
||||
@ -49,7 +48,7 @@ static void coreaudio_free(void *data)
|
||||
if (dev->dev_alive)
|
||||
{
|
||||
AudioOutputUnitStop(dev->dev);
|
||||
CloseComponent(dev->dev);
|
||||
AudioComponentInstanceDispose(dev->dev);
|
||||
}
|
||||
|
||||
if (dev->buffer)
|
||||
@ -102,43 +101,32 @@ static void *coreaudio_init(const char *device, unsigned rate, unsigned latency)
|
||||
if (!dev)
|
||||
return NULL;
|
||||
|
||||
CFRunLoopRef run_loop = NULL;
|
||||
AudioObjectPropertyAddress addr = {
|
||||
kAudioHardwarePropertyRunLoop,
|
||||
kAudioObjectPropertyScopeGlobal,
|
||||
kAudioObjectPropertyElementMaster
|
||||
};
|
||||
|
||||
pthread_mutex_init(&dev->lock, NULL);
|
||||
pthread_cond_init(&dev->cond, NULL);
|
||||
AudioObjectSetPropertyData(kAudioObjectSystemObject, &addr, 0, NULL,
|
||||
sizeof(CFRunLoopRef), &run_loop);
|
||||
|
||||
ComponentDescription desc = {0};
|
||||
// Create AudioComponent
|
||||
AudioComponentDescription desc = {0};
|
||||
desc.componentType = kAudioUnitType_Output;
|
||||
#ifdef IOS
|
||||
desc.componentSubType = kAudioUnitSubType_RemoteIO;
|
||||
#else
|
||||
desc.componentSubType = kAudioUnitSubType_HALOutput;
|
||||
#endif
|
||||
desc.componentManufacturer = kAudioUnitManufacturer_Apple;
|
||||
|
||||
AudioStreamBasicDescription stream_desc = {0};
|
||||
AudioStreamBasicDescription real_desc;
|
||||
AudioChannelLayout layout = {0};
|
||||
AURenderCallbackStruct cb = {0};
|
||||
|
||||
Component comp = NULL;
|
||||
OSStatus res = noErr;
|
||||
UInt32 i_size = 0;
|
||||
size_t fifo_size;
|
||||
|
||||
comp = FindNextComponent(NULL, &desc);
|
||||
AudioComponent comp = AudioComponentFindNext(NULL, &desc);
|
||||
if (comp == NULL)
|
||||
goto error;
|
||||
|
||||
res = OpenAComponent(comp, &dev->dev);
|
||||
if (res != noErr)
|
||||
|
||||
if (AudioComponentInstanceNew(comp, &dev->dev) != noErr)
|
||||
goto error;
|
||||
|
||||
dev->dev_alive = true;
|
||||
|
||||
// Set audio format
|
||||
AudioStreamBasicDescription stream_desc = {0};
|
||||
AudioStreamBasicDescription real_desc;
|
||||
|
||||
stream_desc.mSampleRate = rate;
|
||||
stream_desc.mBitsPerChannel = sizeof(float) * CHAR_BIT;
|
||||
stream_desc.mChannelsPerFrame = 2;
|
||||
@ -147,20 +135,16 @@ static void *coreaudio_init(const char *device, unsigned rate, unsigned latency)
|
||||
stream_desc.mFramesPerPacket = 1;
|
||||
stream_desc.mFormatID = kAudioFormatLinearPCM;
|
||||
stream_desc.mFormatFlags = kAudioFormatFlagIsFloat | kAudioFormatFlagIsPacked | (is_little_endian() ? 0 : kAudioFormatFlagIsBigEndian);
|
||||
|
||||
res = AudioUnitSetProperty(dev->dev, kAudioUnitProperty_StreamFormat,
|
||||
kAudioUnitScope_Input, 0, &stream_desc, sizeof(stream_desc));
|
||||
if (res != noErr)
|
||||
|
||||
if (AudioUnitSetProperty(dev->dev, kAudioUnitProperty_StreamFormat,
|
||||
kAudioUnitScope_Input, 0, &stream_desc, sizeof(stream_desc)) != noErr)
|
||||
goto error;
|
||||
|
||||
i_size = sizeof(real_desc);
|
||||
res = AudioUnitGetProperty(dev->dev, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &real_desc, &i_size);
|
||||
if (res != noErr)
|
||||
|
||||
// Check returned audio format
|
||||
UInt32 i_size = sizeof(real_desc);;
|
||||
if (AudioUnitGetProperty(dev->dev, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &real_desc, &i_size) != noErr)
|
||||
goto error;
|
||||
|
||||
RARCH_LOG("[CoreAudio]: Using output sample rate of %.1f Hz\n", (float)real_desc.mSampleRate);
|
||||
g_settings.audio.out_rate = real_desc.mSampleRate;
|
||||
|
||||
if (real_desc.mChannelsPerFrame != stream_desc.mChannelsPerFrame)
|
||||
goto error;
|
||||
if (real_desc.mBitsPerChannel != stream_desc.mBitsPerChannel)
|
||||
@ -170,26 +154,34 @@ static void *coreaudio_init(const char *device, unsigned rate, unsigned latency)
|
||||
if (real_desc.mFormatID != stream_desc.mFormatID)
|
||||
goto error;
|
||||
|
||||
layout.mChannelLayoutTag = kAudioChannelLayoutTag_UseChannelBitmap;
|
||||
layout.mChannelBitmap = 0x03;
|
||||
RARCH_LOG("[CoreAudio]: Using output sample rate of %.1f Hz\n", (float)real_desc.mSampleRate);
|
||||
g_settings.audio.out_rate = real_desc.mSampleRate;
|
||||
|
||||
res = AudioUnitSetProperty(dev->dev, kAudioUnitProperty_AudioChannelLayout,
|
||||
kAudioUnitScope_Input, 0, &layout, sizeof(layout));
|
||||
if (res != noErr)
|
||||
|
||||
// Set channel layout (fails on iOS)
|
||||
#ifndef IOS
|
||||
AudioChannelLayout layout = {0};
|
||||
|
||||
layout.mChannelLayoutTag = kAudioChannelLayoutTag_Stereo;
|
||||
if (AudioUnitSetProperty(dev->dev, kAudioUnitProperty_AudioChannelLayout,
|
||||
kAudioUnitScope_Input, 0, &layout, sizeof(layout)) != noErr)
|
||||
goto error;
|
||||
#endif
|
||||
|
||||
// Set callbacks and finish up
|
||||
AURenderCallbackStruct cb = {0};
|
||||
cb.inputProc = audio_cb;
|
||||
cb.inputProcRefCon = dev;
|
||||
|
||||
res = AudioUnitSetProperty(dev->dev, kAudioUnitProperty_SetRenderCallback,
|
||||
kAudioUnitScope_Input, 0, &cb, sizeof(cb));
|
||||
if (res != noErr)
|
||||
if (AudioUnitSetProperty(dev->dev, kAudioUnitProperty_SetRenderCallback,
|
||||
kAudioUnitScope_Input, 0, &cb, sizeof(cb)) != noErr)
|
||||
goto error;
|
||||
|
||||
res = AudioUnitInitialize(dev->dev);
|
||||
if (res != noErr)
|
||||
if (AudioUnitInitialize(dev->dev) != noErr)
|
||||
goto error;
|
||||
|
||||
size_t fifo_size;
|
||||
|
||||
fifo_size = (latency * g_settings.audio.out_rate) / 1000;
|
||||
fifo_size *= 2 * sizeof(float);
|
||||
dev->buffer_size = fifo_size;
|
||||
@ -200,8 +192,7 @@ static void *coreaudio_init(const char *device, unsigned rate, unsigned latency)
|
||||
|
||||
RARCH_LOG("[CoreAudio]: Using buffer size of %u bytes: (latency = %u ms)\n", (unsigned)fifo_size, latency);
|
||||
|
||||
res = AudioOutputUnitStart(dev->dev);
|
||||
if (res != noErr)
|
||||
if (AudioOutputUnitStart(dev->dev) != noErr)
|
||||
goto error;
|
||||
|
||||
return dev;
|
||||
|
@ -72,6 +72,7 @@ enum
|
||||
INPUT_WII,
|
||||
INPUT_XINPUT,
|
||||
INPUT_LINUXRAW,
|
||||
INPUT_IOS,
|
||||
INPUT_NULL
|
||||
};
|
||||
|
||||
@ -157,6 +158,8 @@ enum
|
||||
#define INPUT_DEFAULT_DRIVER INPUT_WII
|
||||
#elif defined(HAVE_XVIDEO)
|
||||
#define INPUT_DEFAULT_DRIVER INPUT_X
|
||||
#elif defined(IOS)
|
||||
#define INPUT_DEFAULT_DRIVER INPUT_IOS
|
||||
#else
|
||||
#define INPUT_DEFAULT_DRIVER INPUT_NULL
|
||||
#endif
|
||||
|
3
driver.c
3
driver.c
@ -152,6 +152,9 @@ static const input_driver_t *input_drivers[] = {
|
||||
#if defined(__linux__) && !defined(ANDROID)
|
||||
&input_linuxraw,
|
||||
#endif
|
||||
#ifdef IOS
|
||||
&input_ios,
|
||||
#endif
|
||||
#ifdef HAVE_NULLINPUT
|
||||
&input_null,
|
||||
#endif
|
||||
|
1
driver.h
1
driver.h
@ -488,6 +488,7 @@ extern const input_driver_t input_xenon360;
|
||||
extern const input_driver_t input_gx;
|
||||
extern const input_driver_t input_xinput;
|
||||
extern const input_driver_t input_linuxraw;
|
||||
extern const input_driver_t input_ios;
|
||||
extern const input_driver_t input_null;
|
||||
|
||||
#include "driver_funcs.h"
|
||||
|
141
gfx/context/ioseagl_ctx.c
Normal file
141
gfx/context/ioseagl_ctx.c
Normal file
@ -0,0 +1,141 @@
|
||||
/* 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 "../../driver.h"
|
||||
#include "../gfx_common.h"
|
||||
#include "../gl_common.h"
|
||||
#include "../image.h"
|
||||
|
||||
#include "../fonts/gl_font.h"
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef HAVE_GLSL
|
||||
#include "../shader_glsl.h"
|
||||
#endif
|
||||
|
||||
// C interface
|
||||
static void gfx_ctx_set_swap_interval(unsigned interval)
|
||||
{
|
||||
extern void ios_set_game_view_sync(bool on);
|
||||
ios_set_game_view_sync(interval ? true : false);
|
||||
}
|
||||
|
||||
static void gfx_ctx_destroy(void)
|
||||
{
|
||||
extern void ios_destroy_game_view();
|
||||
ios_destroy_game_view();
|
||||
}
|
||||
|
||||
static void gfx_ctx_get_video_size(unsigned *width, unsigned *height)
|
||||
{
|
||||
extern void ios_get_game_view_size(unsigned *, unsigned *);
|
||||
ios_get_game_view_size(width, height);
|
||||
}
|
||||
|
||||
static bool gfx_ctx_init(void)
|
||||
{
|
||||
extern bool ios_init_game_view();
|
||||
return ios_init_game_view();
|
||||
}
|
||||
|
||||
static void gfx_ctx_swap_buffers(void)
|
||||
{
|
||||
extern void ios_flip_game_view();
|
||||
ios_flip_game_view();
|
||||
}
|
||||
|
||||
static void gfx_ctx_check_window(bool *quit,
|
||||
bool *resize, unsigned *width, unsigned *height, unsigned frame_count)
|
||||
{
|
||||
(void)frame_count;
|
||||
|
||||
*quit = false;
|
||||
|
||||
unsigned new_width, new_height;
|
||||
gfx_ctx_get_video_size(&new_width, &new_height);
|
||||
if (new_width != *width || new_height != *height)
|
||||
{
|
||||
*width = new_width;
|
||||
*height = new_height;
|
||||
*resize = true;
|
||||
}
|
||||
}
|
||||
|
||||
static void gfx_ctx_set_resize(unsigned width, unsigned height)
|
||||
{
|
||||
(void)width;
|
||||
(void)height;
|
||||
}
|
||||
|
||||
static void gfx_ctx_update_window_title(bool reset)
|
||||
{
|
||||
}
|
||||
|
||||
static bool gfx_ctx_set_video_mode(
|
||||
unsigned width, unsigned height,
|
||||
bool fullscreen)
|
||||
{
|
||||
(void)width;
|
||||
(void)height;
|
||||
(void)fullscreen;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void gfx_ctx_input_driver(const input_driver_t **input, void **input_data)
|
||||
{
|
||||
*input = NULL;
|
||||
*input_data = NULL;
|
||||
}
|
||||
|
||||
static bool gfx_ctx_bind_api(enum gfx_ctx_api api)
|
||||
{
|
||||
return api == GFX_CTX_OPENGL_ES_API;
|
||||
}
|
||||
|
||||
static bool gfx_ctx_has_focus(void)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool gfx_ctx_init_egl_image_buffer(const video_info_t *video)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool gfx_ctx_write_egl_image(const void *frame, unsigned width, unsigned height, unsigned pitch, bool rgb32, unsigned index, void **image_handle)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const gfx_ctx_driver_t gfx_ctx_ios = {
|
||||
gfx_ctx_init,
|
||||
gfx_ctx_destroy,
|
||||
gfx_ctx_bind_api,
|
||||
gfx_ctx_set_swap_interval,
|
||||
gfx_ctx_set_video_mode,
|
||||
gfx_ctx_get_video_size,
|
||||
NULL,
|
||||
gfx_ctx_update_window_title,
|
||||
gfx_ctx_check_window,
|
||||
gfx_ctx_set_resize,
|
||||
gfx_ctx_has_focus,
|
||||
gfx_ctx_swap_buffers,
|
||||
gfx_ctx_input_driver,
|
||||
NULL,
|
||||
gfx_ctx_init_egl_image_buffer,
|
||||
gfx_ctx_write_egl_image,
|
||||
NULL,
|
||||
"ios",
|
||||
};
|
@ -51,6 +51,9 @@ static const gfx_ctx_driver_t *gfx_ctx_drivers[] = {
|
||||
#if defined(__BLACKBERRY_QNX__)
|
||||
&gfx_ctx_bbqnx,
|
||||
#endif
|
||||
#if defined(IOS)
|
||||
&gfx_ctx_ios,
|
||||
#endif
|
||||
};
|
||||
|
||||
const gfx_ctx_driver_t *gfx_ctx_find_driver(const char *ident)
|
||||
|
@ -140,6 +140,7 @@ extern const gfx_ctx_driver_t gfx_ctx_xdk;
|
||||
extern const gfx_ctx_driver_t gfx_ctx_wgl;
|
||||
extern const gfx_ctx_driver_t gfx_ctx_videocore;
|
||||
extern const gfx_ctx_driver_t gfx_ctx_bbqnx;
|
||||
extern const gfx_ctx_driver_t gfx_ctx_ios;
|
||||
|
||||
const gfx_ctx_driver_t *gfx_ctx_find_driver(const char *ident); // Finds driver with ident. Does not initialize.
|
||||
const gfx_ctx_driver_t *gfx_ctx_init_first(enum gfx_ctx_api api); // Finds first suitable driver and initializes.
|
||||
|
12
gfx/gl.c
12
gfx/gl.c
@ -760,7 +760,7 @@ void gl_set_viewport(void *data, unsigned width, unsigned height, bool force_ful
|
||||
gl->vp.height = height;
|
||||
}
|
||||
|
||||
#ifdef ANDROID
|
||||
#if defined(ANDROID) || defined(IOS)
|
||||
// In portrait mode, we want viewport to gravitate to top of screen.
|
||||
if (device_aspect < 1.0f)
|
||||
gl->vp.y *= 2;
|
||||
@ -901,7 +901,13 @@ static void gl_frame_fbo(void *data, const struct gl_tex_info *tex_info)
|
||||
set_texture_coords(fbo_tex_coords, xamt, yamt);
|
||||
|
||||
// Render our FBO texture to back buffer.
|
||||
#ifdef IOS
|
||||
// There is no default frame buffer on IOS.
|
||||
extern void ios_bind_game_view_fbo();
|
||||
ios_bind_game_view_fbo();
|
||||
#else
|
||||
pglBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
#endif
|
||||
gl_shader_use_func(gl, gl->fbo_pass + 1);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, gl->fbo_texture[gl->fbo_pass - 1]);
|
||||
@ -1329,6 +1335,10 @@ static bool gl_frame(void *data, const void *frame, unsigned width, unsigned hei
|
||||
RARCH_PERFORMANCE_START(copy_frame);
|
||||
gl_copy_frame(gl, frame, width, height, pitch);
|
||||
RARCH_PERFORMANCE_STOP(copy_frame);
|
||||
|
||||
#ifdef IOS // Apparently the viewport is lost each frame, thanks apple.
|
||||
gl_set_viewport(gl, gl->win_width, gl->win_height, false, true);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
glBindTexture(GL_TEXTURE_2D, gl->texture[gl->tex_index]);
|
||||
|
@ -34,7 +34,10 @@
|
||||
#include <EGL/eglext.h>
|
||||
#endif
|
||||
|
||||
#if defined(__APPLE__)
|
||||
#if defined(IOS)
|
||||
#include <OpenGLES/ES2/gl.h>
|
||||
#include <OpenGLES/ES2/glext.h>
|
||||
#elif defined(__APPLE__)
|
||||
#include <OpenGL/gl.h>
|
||||
#include <OpenGL/glext.h>
|
||||
#elif defined(HAVE_PSGL)
|
||||
@ -330,7 +333,11 @@ extern PFNGLACTIVETEXTUREPROC pglActiveTexture;
|
||||
#ifndef GL_BGRA_EXT
|
||||
#define GL_BGRA_EXT 0x80E1
|
||||
#endif
|
||||
#ifdef IOS
|
||||
#define RARCH_GL_INTERNAL_FORMAT32 GL_RGBA // Stupid Apple
|
||||
#else
|
||||
#define RARCH_GL_INTERNAL_FORMAT32 GL_BGRA_EXT
|
||||
#endif
|
||||
#define RARCH_GL_INTERNAL_FORMAT16 GL_RGB
|
||||
#define RARCH_GL_TEXTURE_TYPE32 GL_BGRA_EXT
|
||||
#define RARCH_GL_TEXTURE_TYPE16 GL_RGB
|
||||
|
@ -27,7 +27,10 @@
|
||||
#include "../config.h"
|
||||
#endif
|
||||
|
||||
#if defined(__APPLE__) // Because they like to be "oh, so, special".
|
||||
#if defined(IOS)
|
||||
#include <OpenGLES/ES2/gl.h>
|
||||
#include <OpenGLES/ES2/glext.h>
|
||||
#elif defined(__APPLE__) // Because they like to be "oh, so, special".
|
||||
#include <OpenGL/gl.h>
|
||||
#include <OpenGL/glext.h>
|
||||
#elif defined(HAVE_PSGL)
|
||||
|
BIN
ios/Assets/Default-568h@2x.png
Normal file
BIN
ios/Assets/Default-568h@2x.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 18 KiB |
BIN
ios/Assets/Default.png
Normal file
BIN
ios/Assets/Default.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 6.4 KiB |
BIN
ios/Assets/Default@2x.png
Normal file
BIN
ios/Assets/Default@2x.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 16 KiB |
BIN
ios/Assets/Icon-72.png
Normal file
BIN
ios/Assets/Icon-72.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.1 KiB |
BIN
ios/Assets/Icon.png
Normal file
BIN
ios/Assets/Icon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.2 KiB |
261
ios/Assets/PauseIndicatorView.xib
Normal file
261
ios/Assets/PauseIndicatorView.xib
Normal file
@ -0,0 +1,261 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<archive type="com.apple.InterfaceBuilder3.CocoaTouch.iPad.XIB" version="8.00">
|
||||
<data>
|
||||
<int key="IBDocument.SystemTarget">1552</int>
|
||||
<string key="IBDocument.SystemVersion">12C60</string>
|
||||
<string key="IBDocument.InterfaceBuilderVersion">3084</string>
|
||||
<string key="IBDocument.AppKitVersion">1187.34</string>
|
||||
<string key="IBDocument.HIToolboxVersion">625.00</string>
|
||||
<object class="NSMutableDictionary" key="IBDocument.PluginVersions">
|
||||
<string key="NS.key.0">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
<string key="NS.object.0">2083</string>
|
||||
</object>
|
||||
<array key="IBDocument.IntegratedClassDependencies">
|
||||
<string>IBNSLayoutConstraint</string>
|
||||
<string>IBProxyObject</string>
|
||||
<string>IBUIButton</string>
|
||||
<string>IBUIView</string>
|
||||
</array>
|
||||
<array key="IBDocument.PluginDependencies">
|
||||
<string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
</array>
|
||||
<object class="NSMutableDictionary" key="IBDocument.Metadata">
|
||||
<string key="NS.key.0">PluginDependencyRecalculationVersion</string>
|
||||
<integer value="1" key="NS.object.0"/>
|
||||
</object>
|
||||
<array class="NSMutableArray" key="IBDocument.RootObjects" id="1000">
|
||||
<object class="IBProxyObject" id="372490531">
|
||||
<string key="IBProxiedObjectIdentifier">IBFilesOwner</string>
|
||||
<string key="targetRuntimeIdentifier">IBIPadFramework</string>
|
||||
</object>
|
||||
<object class="IBProxyObject" id="975951072">
|
||||
<string key="IBProxiedObjectIdentifier">IBFirstResponder</string>
|
||||
<string key="targetRuntimeIdentifier">IBIPadFramework</string>
|
||||
</object>
|
||||
<object class="IBUIView" id="191373211">
|
||||
<reference key="NSNextResponder"/>
|
||||
<int key="NSvFlags">274</int>
|
||||
<array class="NSMutableArray" key="NSSubviews">
|
||||
<object class="IBUIButton" id="1072319895">
|
||||
<reference key="NSNextResponder" ref="191373211"/>
|
||||
<int key="NSvFlags">292</int>
|
||||
<string key="NSFrameSize">{768, 1005}</string>
|
||||
<reference key="NSSuperview" ref="191373211"/>
|
||||
<string key="NSReuseIdentifierKey">_NS:9</string>
|
||||
<object class="NSColor" key="IBUIBackgroundColor" id="107526919">
|
||||
<int key="NSColorSpace">3</int>
|
||||
<bytes key="NSWhite">MCAwAA</bytes>
|
||||
</object>
|
||||
<bool key="IBUIOpaque">NO</bool>
|
||||
<int key="IBUIContentMode">5</int>
|
||||
<string key="targetRuntimeIdentifier">IBIPadFramework</string>
|
||||
<int key="IBUIContentHorizontalAlignment">0</int>
|
||||
<int key="IBUIContentVerticalAlignment">0</int>
|
||||
<object class="NSColor" key="IBUIHighlightedTitleColor">
|
||||
<int key="NSColorSpace">3</int>
|
||||
<bytes key="NSWhite">MQA</bytes>
|
||||
</object>
|
||||
<object class="NSColor" key="IBUINormalTitleColor">
|
||||
<int key="NSColorSpace">1</int>
|
||||
<bytes key="NSRGB">MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA</bytes>
|
||||
</object>
|
||||
<reference key="IBUINormalTitleShadowColor" ref="107526919"/>
|
||||
<object class="NSCustomResource" key="IBUINormalBackgroundImage">
|
||||
<string key="NSClassName">NSImage</string>
|
||||
<string key="NSResourceName">ic_pause.png</string>
|
||||
</object>
|
||||
<object class="IBUIFontDescription" key="IBUIFontDescription">
|
||||
<int key="type">2</int>
|
||||
<double key="pointSize">15</double>
|
||||
</object>
|
||||
<object class="NSFont" key="IBUIFont">
|
||||
<string key="NSName">Helvetica-Bold</string>
|
||||
<double key="NSSize">15</double>
|
||||
<int key="NSfFlags">16</int>
|
||||
</object>
|
||||
</object>
|
||||
</array>
|
||||
<string key="NSFrame">{{0, 20}, {768, 1004}}</string>
|
||||
<reference key="NSSuperview"/>
|
||||
<reference key="NSNextKeyView" ref="1072319895"/>
|
||||
<string key="NSHuggingPriority">{250, 250}</string>
|
||||
<reference key="IBUIBackgroundColor" ref="107526919"/>
|
||||
<bool key="IBUIOpaque">NO</bool>
|
||||
<float key="IBUIAlpha">0.0</float>
|
||||
<object class="IBUISimulatedStatusBarMetrics" key="IBUISimulatedStatusBarMetrics">
|
||||
<int key="IBUIStatusBarStyle">2</int>
|
||||
</object>
|
||||
<string key="targetRuntimeIdentifier">IBIPadFramework</string>
|
||||
</object>
|
||||
</array>
|
||||
<object class="IBObjectContainer" key="IBDocument.Objects">
|
||||
<array class="NSMutableArray" key="connectionRecords">
|
||||
<object class="IBConnectionRecord">
|
||||
<object class="IBCocoaTouchEventConnection" key="connection">
|
||||
<string key="label">showPauseMenu:</string>
|
||||
<reference key="source" ref="1072319895"/>
|
||||
<reference key="destination" ref="372490531"/>
|
||||
<int key="IBEventType">7</int>
|
||||
</object>
|
||||
<int key="connectionID">71</int>
|
||||
</object>
|
||||
</array>
|
||||
<object class="IBMutableOrderedSet" key="objectRecords">
|
||||
<array key="orderedObjects">
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">0</int>
|
||||
<array key="object" id="0"/>
|
||||
<reference key="children" ref="1000"/>
|
||||
<nil key="parent"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">1</int>
|
||||
<reference key="object" ref="191373211"/>
|
||||
<array class="NSMutableArray" key="children">
|
||||
<object class="IBNSLayoutConstraint" id="483291458">
|
||||
<reference key="firstItem" ref="1072319895"/>
|
||||
<int key="firstAttribute">10</int>
|
||||
<int key="relation">0</int>
|
||||
<reference key="secondItem" ref="191373211"/>
|
||||
<int key="secondAttribute">10</int>
|
||||
<float key="multiplier">1</float>
|
||||
<object class="IBLayoutConstant" key="constant">
|
||||
<double key="value">0.0</double>
|
||||
</object>
|
||||
<float key="priority">1000</float>
|
||||
<reference key="containingView" ref="191373211"/>
|
||||
<int key="scoringType">5</int>
|
||||
<float key="scoringTypeFloat">22</float>
|
||||
<int key="contentType">2</int>
|
||||
</object>
|
||||
<object class="IBNSLayoutConstraint" id="446468022">
|
||||
<reference key="firstItem" ref="1072319895"/>
|
||||
<int key="firstAttribute">3</int>
|
||||
<int key="relation">0</int>
|
||||
<reference key="secondItem" ref="191373211"/>
|
||||
<int key="secondAttribute">3</int>
|
||||
<float key="multiplier">1</float>
|
||||
<object class="IBLayoutConstant" key="constant">
|
||||
<double key="value">0.0</double>
|
||||
</object>
|
||||
<float key="priority">1000</float>
|
||||
<reference key="containingView" ref="191373211"/>
|
||||
<int key="scoringType">8</int>
|
||||
<float key="scoringTypeFloat">29</float>
|
||||
<int key="contentType">3</int>
|
||||
</object>
|
||||
<object class="IBNSLayoutConstraint" id="925773848">
|
||||
<reference key="firstItem" ref="1072319895"/>
|
||||
<int key="firstAttribute">5</int>
|
||||
<int key="relation">0</int>
|
||||
<reference key="secondItem" ref="191373211"/>
|
||||
<int key="secondAttribute">5</int>
|
||||
<float key="multiplier">1</float>
|
||||
<object class="IBLayoutConstant" key="constant">
|
||||
<double key="value">0.0</double>
|
||||
</object>
|
||||
<float key="priority">1000</float>
|
||||
<reference key="containingView" ref="191373211"/>
|
||||
<int key="scoringType">8</int>
|
||||
<float key="scoringTypeFloat">29</float>
|
||||
<int key="contentType">3</int>
|
||||
</object>
|
||||
<object class="IBNSLayoutConstraint" id="474429653">
|
||||
<reference key="firstItem" ref="1072319895"/>
|
||||
<int key="firstAttribute">6</int>
|
||||
<int key="relation">0</int>
|
||||
<reference key="secondItem" ref="191373211"/>
|
||||
<int key="secondAttribute">6</int>
|
||||
<float key="multiplier">1</float>
|
||||
<object class="IBLayoutConstant" key="constant">
|
||||
<double key="value">0.0</double>
|
||||
</object>
|
||||
<float key="priority">1000</float>
|
||||
<reference key="containingView" ref="191373211"/>
|
||||
<int key="scoringType">8</int>
|
||||
<float key="scoringTypeFloat">29</float>
|
||||
<int key="contentType">3</int>
|
||||
</object>
|
||||
<reference ref="1072319895"/>
|
||||
</array>
|
||||
<reference key="parent" ref="0"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">-1</int>
|
||||
<reference key="object" ref="372490531"/>
|
||||
<reference key="parent" ref="0"/>
|
||||
<string key="objectName">File's Owner</string>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">-2</int>
|
||||
<reference key="object" ref="975951072"/>
|
||||
<reference key="parent" ref="0"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">54</int>
|
||||
<reference key="object" ref="1072319895"/>
|
||||
<array class="NSMutableArray" key="children"/>
|
||||
<reference key="parent" ref="191373211"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">61</int>
|
||||
<reference key="object" ref="474429653"/>
|
||||
<reference key="parent" ref="191373211"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">63</int>
|
||||
<reference key="object" ref="925773848"/>
|
||||
<reference key="parent" ref="191373211"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">69</int>
|
||||
<reference key="object" ref="446468022"/>
|
||||
<reference key="parent" ref="191373211"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">72</int>
|
||||
<reference key="object" ref="483291458"/>
|
||||
<reference key="parent" ref="191373211"/>
|
||||
</object>
|
||||
</array>
|
||||
</object>
|
||||
<dictionary class="NSMutableDictionary" key="flattenedProperties">
|
||||
<string key="-1.CustomClassName">RetroArch_iOS</string>
|
||||
<string key="-1.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
<string key="-2.CustomClassName">UIResponder</string>
|
||||
<string key="-2.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
<string key="1.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
<array class="NSMutableArray" key="1.IBViewMetadataConstraints">
|
||||
<reference ref="474429653"/>
|
||||
<reference ref="925773848"/>
|
||||
<reference ref="446468022"/>
|
||||
<reference ref="483291458"/>
|
||||
</array>
|
||||
<string key="54.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
<real value="0.0" key="54.IBUIButtonInspectorSelectedEdgeInsetMetadataKey"/>
|
||||
<real value="0.0" key="54.IBUIButtonInspectorSelectedStateConfigurationMetadataKey"/>
|
||||
<boolean value="NO" key="54.IBViewMetadataTranslatesAutoresizingMaskIntoConstraints"/>
|
||||
<string key="61.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
<string key="63.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
<string key="69.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
<string key="72.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
</dictionary>
|
||||
<dictionary class="NSMutableDictionary" key="unlocalizedProperties"/>
|
||||
<nil key="activeLocalization"/>
|
||||
<dictionary class="NSMutableDictionary" key="localizations"/>
|
||||
<nil key="sourceID"/>
|
||||
<int key="maxID">72</int>
|
||||
</object>
|
||||
<object class="IBClassDescriber" key="IBDocument.Classes"/>
|
||||
<int key="IBDocument.localizationMode">0</int>
|
||||
<string key="IBDocument.TargetRuntimeIdentifier">IBIPadFramework</string>
|
||||
<bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool>
|
||||
<int key="IBDocument.defaultPropertyAccessControl">3</int>
|
||||
<object class="NSMutableDictionary" key="IBDocument.LastKnownImageSizes">
|
||||
<string key="NS.key.0">ic_pause.png</string>
|
||||
<string key="NS.object.0">{100, 40}</string>
|
||||
</object>
|
||||
<bool key="IBDocument.UseAutolayout">YES</bool>
|
||||
<string key="IBCocoaTouchPluginVersion">2083</string>
|
||||
</data>
|
||||
</archive>
|
950
ios/Assets/PauseView.xib
Normal file
950
ios/Assets/PauseView.xib
Normal file
@ -0,0 +1,950 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<archive type="com.apple.InterfaceBuilder3.CocoaTouch.iPad.XIB" version="8.00">
|
||||
<data>
|
||||
<int key="IBDocument.SystemTarget">1552</int>
|
||||
<string key="IBDocument.SystemVersion">12C60</string>
|
||||
<string key="IBDocument.InterfaceBuilderVersion">3084</string>
|
||||
<string key="IBDocument.AppKitVersion">1187.34</string>
|
||||
<string key="IBDocument.HIToolboxVersion">625.00</string>
|
||||
<object class="NSMutableDictionary" key="IBDocument.PluginVersions">
|
||||
<string key="NS.key.0">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
<string key="NS.object.0">2083</string>
|
||||
</object>
|
||||
<array key="IBDocument.IntegratedClassDependencies">
|
||||
<string>IBNSLayoutConstraint</string>
|
||||
<string>IBProxyObject</string>
|
||||
<string>IBUIButton</string>
|
||||
<string>IBUISegmentedControl</string>
|
||||
<string>IBUIView</string>
|
||||
</array>
|
||||
<array key="IBDocument.PluginDependencies">
|
||||
<string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
</array>
|
||||
<object class="NSMutableDictionary" key="IBDocument.Metadata">
|
||||
<string key="NS.key.0">PluginDependencyRecalculationVersion</string>
|
||||
<integer value="1" key="NS.object.0"/>
|
||||
</object>
|
||||
<array class="NSMutableArray" key="IBDocument.RootObjects" id="1000">
|
||||
<object class="IBProxyObject" id="372490531">
|
||||
<string key="IBProxiedObjectIdentifier">IBFilesOwner</string>
|
||||
<string key="targetRuntimeIdentifier">IBIPadFramework</string>
|
||||
</object>
|
||||
<object class="IBProxyObject" id="975951072">
|
||||
<string key="IBProxiedObjectIdentifier">IBFirstResponder</string>
|
||||
<string key="targetRuntimeIdentifier">IBIPadFramework</string>
|
||||
</object>
|
||||
<object class="IBUIView" id="191373211">
|
||||
<reference key="NSNextResponder"/>
|
||||
<int key="NSvFlags">274</int>
|
||||
<array class="NSMutableArray" key="NSSubviews">
|
||||
<object class="IBUIButton" id="61755535">
|
||||
<reference key="NSNextResponder" ref="191373211"/>
|
||||
<int key="NSvFlags">292</int>
|
||||
<string key="NSFrame">{{160, 237}, {120, 44}}</string>
|
||||
<reference key="NSSuperview" ref="191373211"/>
|
||||
<reference key="NSNextKeyView"/>
|
||||
<string key="NSReuseIdentifierKey">_NS:9</string>
|
||||
<bool key="IBUIOpaque">NO</bool>
|
||||
<string key="targetRuntimeIdentifier">IBIPadFramework</string>
|
||||
<int key="IBUIContentHorizontalAlignment">0</int>
|
||||
<int key="IBUIContentVerticalAlignment">0</int>
|
||||
<int key="IBUIButtonType">1</int>
|
||||
<string key="IBUINormalTitle">Exit</string>
|
||||
<object class="NSColor" key="IBUIHighlightedTitleColor" id="428922964">
|
||||
<int key="NSColorSpace">3</int>
|
||||
<bytes key="NSWhite">MQA</bytes>
|
||||
</object>
|
||||
<object class="NSColor" key="IBUINormalTitleColor">
|
||||
<int key="NSColorSpace">1</int>
|
||||
<bytes key="NSRGB">MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA</bytes>
|
||||
</object>
|
||||
<object class="NSColor" key="IBUINormalTitleShadowColor" id="899103122">
|
||||
<int key="NSColorSpace">3</int>
|
||||
<bytes key="NSWhite">MC41AA</bytes>
|
||||
</object>
|
||||
<object class="IBUIFontDescription" key="IBUIFontDescription" id="230061939">
|
||||
<int key="type">2</int>
|
||||
<double key="pointSize">15</double>
|
||||
</object>
|
||||
<object class="NSFont" key="IBUIFont" id="495303882">
|
||||
<string key="NSName">Helvetica-Bold</string>
|
||||
<double key="NSSize">15</double>
|
||||
<int key="NSfFlags">16</int>
|
||||
</object>
|
||||
</object>
|
||||
<object class="IBUIButton" id="38801877">
|
||||
<reference key="NSNextResponder" ref="191373211"/>
|
||||
<int key="NSvFlags">292</int>
|
||||
<string key="NSFrame">{{20, 20}, {260, 44}}</string>
|
||||
<reference key="NSSuperview" ref="191373211"/>
|
||||
<reference key="NSNextKeyView" ref="1033465661"/>
|
||||
<string key="NSReuseIdentifierKey">_NS:9</string>
|
||||
<bool key="IBUIOpaque">NO</bool>
|
||||
<string key="targetRuntimeIdentifier">IBIPadFramework</string>
|
||||
<int key="IBUIContentHorizontalAlignment">0</int>
|
||||
<int key="IBUIContentVerticalAlignment">0</int>
|
||||
<int key="IBUIButtonType">1</int>
|
||||
<string key="IBUINormalTitle">Resume Game</string>
|
||||
<reference key="IBUIHighlightedTitleColor" ref="428922964"/>
|
||||
<object class="NSColor" key="IBUINormalTitleColor">
|
||||
<int key="NSColorSpace">1</int>
|
||||
<bytes key="NSRGB">MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA</bytes>
|
||||
</object>
|
||||
<reference key="IBUINormalTitleShadowColor" ref="899103122"/>
|
||||
<reference key="IBUIFontDescription" ref="230061939"/>
|
||||
<reference key="IBUIFont" ref="495303882"/>
|
||||
</object>
|
||||
<object class="IBUIButton" id="721040644">
|
||||
<reference key="NSNextResponder" ref="191373211"/>
|
||||
<int key="NSvFlags">292</int>
|
||||
<string key="NSFrame">{{20, 237}, {120, 44}}</string>
|
||||
<reference key="NSSuperview" ref="191373211"/>
|
||||
<reference key="NSNextKeyView" ref="61755535"/>
|
||||
<string key="NSReuseIdentifierKey">_NS:9</string>
|
||||
<bool key="IBUIOpaque">NO</bool>
|
||||
<string key="targetRuntimeIdentifier">IBIPadFramework</string>
|
||||
<int key="IBUIContentHorizontalAlignment">0</int>
|
||||
<int key="IBUIContentVerticalAlignment">0</int>
|
||||
<int key="IBUIButtonType">1</int>
|
||||
<string key="IBUINormalTitle">Reset</string>
|
||||
<reference key="IBUIHighlightedTitleColor" ref="428922964"/>
|
||||
<object class="NSColor" key="IBUINormalTitleColor">
|
||||
<int key="NSColorSpace">1</int>
|
||||
<bytes key="NSRGB">MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA</bytes>
|
||||
</object>
|
||||
<reference key="IBUINormalTitleShadowColor" ref="899103122"/>
|
||||
<reference key="IBUIFontDescription" ref="230061939"/>
|
||||
<reference key="IBUIFont" ref="495303882"/>
|
||||
</object>
|
||||
<object class="IBUIButton" id="694263183">
|
||||
<reference key="NSNextResponder" ref="191373211"/>
|
||||
<int key="NSvFlags">292</int>
|
||||
<string key="NSFrame">{{20, 186}, {120, 44}}</string>
|
||||
<reference key="NSSuperview" ref="191373211"/>
|
||||
<reference key="NSNextKeyView" ref="58186559"/>
|
||||
<string key="NSReuseIdentifierKey">_NS:9</string>
|
||||
<bool key="IBUIOpaque">NO</bool>
|
||||
<string key="targetRuntimeIdentifier">IBIPadFramework</string>
|
||||
<int key="IBUIContentHorizontalAlignment">0</int>
|
||||
<int key="IBUIContentVerticalAlignment">0</int>
|
||||
<int key="IBUIButtonType">1</int>
|
||||
<string key="IBUINormalTitle">Save State</string>
|
||||
<reference key="IBUIHighlightedTitleColor" ref="428922964"/>
|
||||
<object class="NSColor" key="IBUINormalTitleColor">
|
||||
<int key="NSColorSpace">1</int>
|
||||
<bytes key="NSRGB">MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA</bytes>
|
||||
</object>
|
||||
<reference key="IBUINormalTitleShadowColor" ref="899103122"/>
|
||||
<reference key="IBUIFontDescription" ref="230061939"/>
|
||||
<reference key="IBUIFont" ref="495303882"/>
|
||||
</object>
|
||||
<object class="IBUIButton" id="58186559">
|
||||
<reference key="NSNextResponder" ref="191373211"/>
|
||||
<int key="NSvFlags">292</int>
|
||||
<string key="NSFrame">{{160, 186}, {120, 44}}</string>
|
||||
<reference key="NSSuperview" ref="191373211"/>
|
||||
<reference key="NSNextKeyView" ref="721040644"/>
|
||||
<string key="NSReuseIdentifierKey">_NS:9</string>
|
||||
<bool key="IBUIOpaque">NO</bool>
|
||||
<string key="targetRuntimeIdentifier">IBIPadFramework</string>
|
||||
<int key="IBUIContentHorizontalAlignment">0</int>
|
||||
<int key="IBUIContentVerticalAlignment">0</int>
|
||||
<int key="IBUIButtonType">1</int>
|
||||
<string key="IBUINormalTitle">Load State</string>
|
||||
<reference key="IBUIHighlightedTitleColor" ref="428922964"/>
|
||||
<object class="NSColor" key="IBUINormalTitleColor">
|
||||
<int key="NSColorSpace">1</int>
|
||||
<bytes key="NSRGB">MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA</bytes>
|
||||
</object>
|
||||
<reference key="IBUINormalTitleShadowColor" ref="899103122"/>
|
||||
<reference key="IBUIFontDescription" ref="230061939"/>
|
||||
<reference key="IBUIFont" ref="495303882"/>
|
||||
</object>
|
||||
<object class="IBUISegmentedControl" id="562513162">
|
||||
<reference key="NSNextResponder" ref="191373211"/>
|
||||
<int key="NSvFlags">292</int>
|
||||
<string key="NSFrame">{{20, 135}, {260, 44}}</string>
|
||||
<reference key="NSSuperview" ref="191373211"/>
|
||||
<reference key="NSNextKeyView" ref="694263183"/>
|
||||
<string key="NSReuseIdentifierKey">_NS:9</string>
|
||||
<bool key="IBUIOpaque">NO</bool>
|
||||
<int key="IBUITag">1</int>
|
||||
<string key="targetRuntimeIdentifier">IBIPadFramework</string>
|
||||
<int key="IBNumberOfSegments">10</int>
|
||||
<int key="IBSelectedSegmentIndex">0</int>
|
||||
<array key="IBSegmentTitles">
|
||||
<string>1</string>
|
||||
<string>2</string>
|
||||
<string>3</string>
|
||||
<string>4</string>
|
||||
<string>5</string>
|
||||
<string>6</string>
|
||||
<string>7</string>
|
||||
<string>8</string>
|
||||
<string>9</string>
|
||||
<string>10</string>
|
||||
</array>
|
||||
<array class="NSMutableArray" key="IBSegmentWidths">
|
||||
<real value="0.0"/>
|
||||
<real value="0.0"/>
|
||||
<real value="0.0"/>
|
||||
<real value="0.0"/>
|
||||
<real value="0.0"/>
|
||||
<real value="0.0"/>
|
||||
<real value="0.0"/>
|
||||
<real value="0.0"/>
|
||||
<real value="0.0"/>
|
||||
<real value="0.0"/>
|
||||
</array>
|
||||
<array class="NSMutableArray" key="IBSegmentEnabledStates">
|
||||
<boolean value="YES"/>
|
||||
<boolean value="YES"/>
|
||||
<boolean value="YES"/>
|
||||
<boolean value="YES"/>
|
||||
<boolean value="YES"/>
|
||||
<boolean value="YES"/>
|
||||
<boolean value="YES"/>
|
||||
<boolean value="YES"/>
|
||||
<boolean value="YES"/>
|
||||
<boolean value="YES"/>
|
||||
</array>
|
||||
<array class="NSMutableArray" key="IBSegmentContentOffsets">
|
||||
<string>{0, 0}</string>
|
||||
<string>{0, 0}</string>
|
||||
<string>{0, 0}</string>
|
||||
<string>{0, 0}</string>
|
||||
<string>{0, 0}</string>
|
||||
<string>{0, 0}</string>
|
||||
<string>{0, 0}</string>
|
||||
<string>{0, 0}</string>
|
||||
<string>{0, 0}</string>
|
||||
<string>{0, 0}</string>
|
||||
</array>
|
||||
<array class="NSMutableArray" key="IBSegmentImages">
|
||||
<object class="NSNull" id="4"/>
|
||||
<reference ref="4"/>
|
||||
<reference ref="4"/>
|
||||
<reference ref="4"/>
|
||||
<reference ref="4"/>
|
||||
<reference ref="4"/>
|
||||
<reference ref="4"/>
|
||||
<reference ref="4"/>
|
||||
<reference ref="4"/>
|
||||
<reference ref="4"/>
|
||||
</array>
|
||||
</object>
|
||||
<object class="IBUIButton" id="1033465661">
|
||||
<reference key="NSNextResponder" ref="191373211"/>
|
||||
<int key="NSvFlags">292</int>
|
||||
<string key="NSFrame">{{20, 71}, {260, 44}}</string>
|
||||
<reference key="NSSuperview" ref="191373211"/>
|
||||
<reference key="NSNextKeyView" ref="562513162"/>
|
||||
<string key="NSReuseIdentifierKey">_NS:9</string>
|
||||
<bool key="IBUIOpaque">NO</bool>
|
||||
<string key="targetRuntimeIdentifier">IBIPadFramework</string>
|
||||
<int key="IBUIContentHorizontalAlignment">0</int>
|
||||
<int key="IBUIContentVerticalAlignment">0</int>
|
||||
<int key="IBUIButtonType">1</int>
|
||||
<string key="IBUINormalTitle">Settings</string>
|
||||
<reference key="IBUIHighlightedTitleColor" ref="428922964"/>
|
||||
<object class="NSColor" key="IBUINormalTitleColor">
|
||||
<int key="NSColorSpace">1</int>
|
||||
<bytes key="NSRGB">MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA</bytes>
|
||||
</object>
|
||||
<reference key="IBUINormalTitleShadowColor" ref="899103122"/>
|
||||
<reference key="IBUIFontDescription" ref="230061939"/>
|
||||
<reference key="IBUIFont" ref="495303882"/>
|
||||
</object>
|
||||
</array>
|
||||
<string key="NSFrame">{{0, 20}, {300, 300}}</string>
|
||||
<reference key="NSSuperview"/>
|
||||
<reference key="NSNextKeyView" ref="38801877"/>
|
||||
<object class="NSColor" key="IBUIBackgroundColor">
|
||||
<int key="NSColorSpace">3</int>
|
||||
<bytes key="NSWhite">MQA</bytes>
|
||||
<object class="NSColorSpace" key="NSCustomColorSpace">
|
||||
<int key="NSID">2</int>
|
||||
</object>
|
||||
</object>
|
||||
<bool key="IBUIOpaque">NO</bool>
|
||||
<float key="IBUIAlpha">0.0</float>
|
||||
<object class="IBUISimulatedStatusBarMetrics" key="IBUISimulatedStatusBarMetrics">
|
||||
<int key="IBUIStatusBarStyle">2</int>
|
||||
</object>
|
||||
<object class="IBUISimulatedSizeMetrics" key="IBUISimulatedDestinationMetrics">
|
||||
<string key="IBUISimulatedSizeMetricsClass">IBUISimulatedFreeformSizeMetricsSentinel</string>
|
||||
<string key="IBUIDisplayName">Freeform</string>
|
||||
</object>
|
||||
<string key="targetRuntimeIdentifier">IBIPadFramework</string>
|
||||
</object>
|
||||
</array>
|
||||
<object class="IBObjectContainer" key="IBDocument.Objects">
|
||||
<array class="NSMutableArray" key="connectionRecords">
|
||||
<object class="IBConnectionRecord">
|
||||
<object class="IBCocoaTouchEventConnection" key="connection">
|
||||
<string key="label">closeGamePressed:</string>
|
||||
<reference key="source" ref="61755535"/>
|
||||
<reference key="destination" ref="372490531"/>
|
||||
<int key="IBEventType">7</int>
|
||||
</object>
|
||||
<int key="connectionID">23</int>
|
||||
</object>
|
||||
<object class="IBConnectionRecord">
|
||||
<object class="IBCocoaTouchEventConnection" key="connection">
|
||||
<string key="label">closePauseMenu:</string>
|
||||
<reference key="source" ref="38801877"/>
|
||||
<reference key="destination" ref="372490531"/>
|
||||
<int key="IBEventType">7</int>
|
||||
</object>
|
||||
<int key="connectionID">25</int>
|
||||
</object>
|
||||
<object class="IBConnectionRecord">
|
||||
<object class="IBCocoaTouchEventConnection" key="connection">
|
||||
<string key="label">resetGame:</string>
|
||||
<reference key="source" ref="721040644"/>
|
||||
<reference key="destination" ref="372490531"/>
|
||||
<int key="IBEventType">7</int>
|
||||
</object>
|
||||
<int key="connectionID">138</int>
|
||||
</object>
|
||||
<object class="IBConnectionRecord">
|
||||
<object class="IBCocoaTouchEventConnection" key="connection">
|
||||
<string key="label">saveState:</string>
|
||||
<reference key="source" ref="694263183"/>
|
||||
<reference key="destination" ref="372490531"/>
|
||||
<int key="IBEventType">7</int>
|
||||
</object>
|
||||
<int key="connectionID">137</int>
|
||||
</object>
|
||||
<object class="IBConnectionRecord">
|
||||
<object class="IBCocoaTouchEventConnection" key="connection">
|
||||
<string key="label">loadState:</string>
|
||||
<reference key="source" ref="58186559"/>
|
||||
<reference key="destination" ref="372490531"/>
|
||||
<int key="IBEventType">7</int>
|
||||
</object>
|
||||
<int key="connectionID">136</int>
|
||||
</object>
|
||||
<object class="IBConnectionRecord">
|
||||
<object class="IBCocoaTouchEventConnection" key="connection">
|
||||
<string key="label">chooseState:</string>
|
||||
<reference key="source" ref="562513162"/>
|
||||
<reference key="destination" ref="372490531"/>
|
||||
<int key="IBEventType">13</int>
|
||||
</object>
|
||||
<int key="connectionID">139</int>
|
||||
</object>
|
||||
<object class="IBConnectionRecord">
|
||||
<object class="IBCocoaTouchEventConnection" key="connection">
|
||||
<string key="label">showSettings</string>
|
||||
<reference key="source" ref="1033465661"/>
|
||||
<reference key="destination" ref="372490531"/>
|
||||
<int key="IBEventType">7</int>
|
||||
</object>
|
||||
<int key="connectionID">148</int>
|
||||
</object>
|
||||
</array>
|
||||
<object class="IBMutableOrderedSet" key="objectRecords">
|
||||
<array key="orderedObjects">
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">0</int>
|
||||
<array key="object" id="0"/>
|
||||
<reference key="children" ref="1000"/>
|
||||
<nil key="parent"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">1</int>
|
||||
<reference key="object" ref="191373211"/>
|
||||
<array class="NSMutableArray" key="children">
|
||||
<object class="IBNSLayoutConstraint" id="331948221">
|
||||
<reference key="firstItem" ref="61755535"/>
|
||||
<int key="firstAttribute">5</int>
|
||||
<int key="relation">0</int>
|
||||
<reference key="secondItem" ref="58186559"/>
|
||||
<int key="secondAttribute">5</int>
|
||||
<float key="multiplier">1</float>
|
||||
<object class="IBLayoutConstant" key="constant">
|
||||
<double key="value">0.0</double>
|
||||
</object>
|
||||
<float key="priority">1000</float>
|
||||
<reference key="containingView" ref="191373211"/>
|
||||
<int key="scoringType">6</int>
|
||||
<float key="scoringTypeFloat">24</float>
|
||||
<int key="contentType">2</int>
|
||||
</object>
|
||||
<object class="IBNSLayoutConstraint" id="214855274">
|
||||
<reference key="firstItem" ref="191373211"/>
|
||||
<int key="firstAttribute">4</int>
|
||||
<int key="relation">0</int>
|
||||
<reference key="secondItem" ref="61755535"/>
|
||||
<int key="secondAttribute">4</int>
|
||||
<float key="multiplier">1</float>
|
||||
<object class="IBNSLayoutSymbolicConstant" key="constant">
|
||||
<double key="value">20</double>
|
||||
</object>
|
||||
<float key="priority">1000</float>
|
||||
<reference key="containingView" ref="191373211"/>
|
||||
<int key="scoringType">8</int>
|
||||
<float key="scoringTypeFloat">29</float>
|
||||
<int key="contentType">3</int>
|
||||
</object>
|
||||
<object class="IBNSLayoutConstraint" id="963730365">
|
||||
<reference key="firstItem" ref="191373211"/>
|
||||
<int key="firstAttribute">6</int>
|
||||
<int key="relation">0</int>
|
||||
<reference key="secondItem" ref="61755535"/>
|
||||
<int key="secondAttribute">6</int>
|
||||
<float key="multiplier">1</float>
|
||||
<object class="IBNSLayoutSymbolicConstant" key="constant">
|
||||
<double key="value">20</double>
|
||||
</object>
|
||||
<float key="priority">1000</float>
|
||||
<reference key="containingView" ref="191373211"/>
|
||||
<int key="scoringType">8</int>
|
||||
<float key="scoringTypeFloat">29</float>
|
||||
<int key="contentType">3</int>
|
||||
</object>
|
||||
<object class="IBNSLayoutConstraint" id="700933706">
|
||||
<reference key="firstItem" ref="191373211"/>
|
||||
<int key="firstAttribute">6</int>
|
||||
<int key="relation">0</int>
|
||||
<reference key="secondItem" ref="58186559"/>
|
||||
<int key="secondAttribute">6</int>
|
||||
<float key="multiplier">1</float>
|
||||
<object class="IBNSLayoutSymbolicConstant" key="constant">
|
||||
<double key="value">20</double>
|
||||
</object>
|
||||
<float key="priority">1000</float>
|
||||
<reference key="containingView" ref="191373211"/>
|
||||
<int key="scoringType">8</int>
|
||||
<float key="scoringTypeFloat">29</float>
|
||||
<int key="contentType">3</int>
|
||||
</object>
|
||||
<object class="IBNSLayoutConstraint" id="911823456">
|
||||
<reference key="firstItem" ref="58186559"/>
|
||||
<int key="firstAttribute">11</int>
|
||||
<int key="relation">0</int>
|
||||
<reference key="secondItem" ref="694263183"/>
|
||||
<int key="secondAttribute">11</int>
|
||||
<float key="multiplier">1</float>
|
||||
<object class="IBLayoutConstant" key="constant">
|
||||
<double key="value">0.0</double>
|
||||
</object>
|
||||
<float key="priority">1000</float>
|
||||
<reference key="containingView" ref="191373211"/>
|
||||
<int key="scoringType">6</int>
|
||||
<float key="scoringTypeFloat">24</float>
|
||||
<int key="contentType">2</int>
|
||||
</object>
|
||||
<object class="IBNSLayoutConstraint" id="120087908">
|
||||
<reference key="firstItem" ref="191373211"/>
|
||||
<int key="firstAttribute">4</int>
|
||||
<int key="relation">0</int>
|
||||
<reference key="secondItem" ref="721040644"/>
|
||||
<int key="secondAttribute">4</int>
|
||||
<float key="multiplier">1</float>
|
||||
<object class="IBNSLayoutSymbolicConstant" key="constant">
|
||||
<double key="value">20</double>
|
||||
</object>
|
||||
<float key="priority">1000</float>
|
||||
<reference key="containingView" ref="191373211"/>
|
||||
<int key="scoringType">8</int>
|
||||
<float key="scoringTypeFloat">29</float>
|
||||
<int key="contentType">3</int>
|
||||
</object>
|
||||
<object class="IBNSLayoutConstraint" id="217059225">
|
||||
<reference key="firstItem" ref="721040644"/>
|
||||
<int key="firstAttribute">3</int>
|
||||
<int key="relation">0</int>
|
||||
<reference key="secondItem" ref="694263183"/>
|
||||
<int key="secondAttribute">4</int>
|
||||
<float key="multiplier">1</float>
|
||||
<object class="IBNSLayoutSymbolicConstant" key="constant">
|
||||
<double key="value">8</double>
|
||||
</object>
|
||||
<float key="priority">1000</float>
|
||||
<reference key="containingView" ref="191373211"/>
|
||||
<int key="scoringType">6</int>
|
||||
<float key="scoringTypeFloat">24</float>
|
||||
<int key="contentType">3</int>
|
||||
</object>
|
||||
<object class="IBNSLayoutConstraint" id="770441708">
|
||||
<reference key="firstItem" ref="721040644"/>
|
||||
<int key="firstAttribute">5</int>
|
||||
<int key="relation">0</int>
|
||||
<reference key="secondItem" ref="191373211"/>
|
||||
<int key="secondAttribute">5</int>
|
||||
<float key="multiplier">1</float>
|
||||
<object class="IBNSLayoutSymbolicConstant" key="constant">
|
||||
<double key="value">20</double>
|
||||
</object>
|
||||
<float key="priority">1000</float>
|
||||
<reference key="containingView" ref="191373211"/>
|
||||
<int key="scoringType">8</int>
|
||||
<float key="scoringTypeFloat">29</float>
|
||||
<int key="contentType">3</int>
|
||||
</object>
|
||||
<object class="IBNSLayoutConstraint" id="837542760">
|
||||
<reference key="firstItem" ref="694263183"/>
|
||||
<int key="firstAttribute">3</int>
|
||||
<int key="relation">0</int>
|
||||
<reference key="secondItem" ref="562513162"/>
|
||||
<int key="secondAttribute">4</int>
|
||||
<float key="multiplier">1</float>
|
||||
<object class="IBNSLayoutSymbolicConstant" key="constant">
|
||||
<double key="value">8</double>
|
||||
</object>
|
||||
<float key="priority">1000</float>
|
||||
<reference key="containingView" ref="191373211"/>
|
||||
<int key="scoringType">6</int>
|
||||
<float key="scoringTypeFloat">24</float>
|
||||
<int key="contentType">3</int>
|
||||
</object>
|
||||
<object class="IBNSLayoutConstraint" id="1015088714">
|
||||
<reference key="firstItem" ref="694263183"/>
|
||||
<int key="firstAttribute">6</int>
|
||||
<int key="relation">0</int>
|
||||
<reference key="secondItem" ref="721040644"/>
|
||||
<int key="secondAttribute">6</int>
|
||||
<float key="multiplier">1</float>
|
||||
<object class="IBLayoutConstant" key="constant">
|
||||
<double key="value">0.0</double>
|
||||
</object>
|
||||
<float key="priority">1000</float>
|
||||
<reference key="containingView" ref="191373211"/>
|
||||
<int key="scoringType">6</int>
|
||||
<float key="scoringTypeFloat">24</float>
|
||||
<int key="contentType">2</int>
|
||||
</object>
|
||||
<object class="IBNSLayoutConstraint" id="85952235">
|
||||
<reference key="firstItem" ref="694263183"/>
|
||||
<int key="firstAttribute">5</int>
|
||||
<int key="relation">0</int>
|
||||
<reference key="secondItem" ref="191373211"/>
|
||||
<int key="secondAttribute">5</int>
|
||||
<float key="multiplier">1</float>
|
||||
<object class="IBNSLayoutSymbolicConstant" key="constant">
|
||||
<double key="value">20</double>
|
||||
</object>
|
||||
<float key="priority">1000</float>
|
||||
<reference key="containingView" ref="191373211"/>
|
||||
<int key="scoringType">8</int>
|
||||
<float key="scoringTypeFloat">29</float>
|
||||
<int key="contentType">3</int>
|
||||
</object>
|
||||
<object class="IBNSLayoutConstraint" id="201787259">
|
||||
<reference key="firstItem" ref="191373211"/>
|
||||
<int key="firstAttribute">6</int>
|
||||
<int key="relation">0</int>
|
||||
<reference key="secondItem" ref="562513162"/>
|
||||
<int key="secondAttribute">6</int>
|
||||
<float key="multiplier">1</float>
|
||||
<object class="IBNSLayoutSymbolicConstant" key="constant">
|
||||
<double key="value">20</double>
|
||||
</object>
|
||||
<float key="priority">1000</float>
|
||||
<reference key="containingView" ref="191373211"/>
|
||||
<int key="scoringType">8</int>
|
||||
<float key="scoringTypeFloat">29</float>
|
||||
<int key="contentType">3</int>
|
||||
</object>
|
||||
<object class="IBNSLayoutConstraint" id="804573855">
|
||||
<reference key="firstItem" ref="562513162"/>
|
||||
<int key="firstAttribute">5</int>
|
||||
<int key="relation">0</int>
|
||||
<reference key="secondItem" ref="191373211"/>
|
||||
<int key="secondAttribute">5</int>
|
||||
<float key="multiplier">1</float>
|
||||
<object class="IBNSLayoutSymbolicConstant" key="constant">
|
||||
<double key="value">20</double>
|
||||
</object>
|
||||
<float key="priority">1000</float>
|
||||
<reference key="containingView" ref="191373211"/>
|
||||
<int key="scoringType">8</int>
|
||||
<float key="scoringTypeFloat">29</float>
|
||||
<int key="contentType">3</int>
|
||||
</object>
|
||||
<object class="IBNSLayoutConstraint" id="65927411">
|
||||
<reference key="firstItem" ref="1033465661"/>
|
||||
<int key="firstAttribute">5</int>
|
||||
<int key="relation">0</int>
|
||||
<reference key="secondItem" ref="191373211"/>
|
||||
<int key="secondAttribute">5</int>
|
||||
<float key="multiplier">1</float>
|
||||
<object class="IBNSLayoutSymbolicConstant" key="constant">
|
||||
<double key="value">20</double>
|
||||
</object>
|
||||
<float key="priority">1000</float>
|
||||
<reference key="containingView" ref="191373211"/>
|
||||
<int key="scoringType">8</int>
|
||||
<float key="scoringTypeFloat">29</float>
|
||||
<int key="contentType">3</int>
|
||||
</object>
|
||||
<object class="IBNSLayoutConstraint" id="402510427">
|
||||
<reference key="firstItem" ref="191373211"/>
|
||||
<int key="firstAttribute">6</int>
|
||||
<int key="relation">0</int>
|
||||
<reference key="secondItem" ref="1033465661"/>
|
||||
<int key="secondAttribute">6</int>
|
||||
<float key="multiplier">1</float>
|
||||
<object class="IBNSLayoutSymbolicConstant" key="constant">
|
||||
<double key="value">20</double>
|
||||
</object>
|
||||
<float key="priority">1000</float>
|
||||
<reference key="containingView" ref="191373211"/>
|
||||
<int key="scoringType">8</int>
|
||||
<float key="scoringTypeFloat">29</float>
|
||||
<int key="contentType">3</int>
|
||||
</object>
|
||||
<object class="IBNSLayoutConstraint" id="828923997">
|
||||
<reference key="firstItem" ref="1033465661"/>
|
||||
<int key="firstAttribute">3</int>
|
||||
<int key="relation">0</int>
|
||||
<reference key="secondItem" ref="38801877"/>
|
||||
<int key="secondAttribute">4</int>
|
||||
<float key="multiplier">1</float>
|
||||
<object class="IBNSLayoutSymbolicConstant" key="constant">
|
||||
<double key="value">8</double>
|
||||
</object>
|
||||
<float key="priority">1000</float>
|
||||
<reference key="containingView" ref="191373211"/>
|
||||
<int key="scoringType">6</int>
|
||||
<float key="scoringTypeFloat">24</float>
|
||||
<int key="contentType">3</int>
|
||||
</object>
|
||||
<object class="IBNSLayoutConstraint" id="38515434">
|
||||
<reference key="firstItem" ref="191373211"/>
|
||||
<int key="firstAttribute">6</int>
|
||||
<int key="relation">0</int>
|
||||
<reference key="secondItem" ref="38801877"/>
|
||||
<int key="secondAttribute">6</int>
|
||||
<float key="multiplier">1</float>
|
||||
<object class="IBNSLayoutSymbolicConstant" key="constant">
|
||||
<double key="value">20</double>
|
||||
</object>
|
||||
<float key="priority">1000</float>
|
||||
<reference key="containingView" ref="191373211"/>
|
||||
<int key="scoringType">8</int>
|
||||
<float key="scoringTypeFloat">29</float>
|
||||
<int key="contentType">3</int>
|
||||
</object>
|
||||
<object class="IBNSLayoutConstraint" id="509206074">
|
||||
<reference key="firstItem" ref="38801877"/>
|
||||
<int key="firstAttribute">5</int>
|
||||
<int key="relation">0</int>
|
||||
<reference key="secondItem" ref="191373211"/>
|
||||
<int key="secondAttribute">5</int>
|
||||
<float key="multiplier">1</float>
|
||||
<object class="IBNSLayoutSymbolicConstant" key="constant">
|
||||
<double key="value">20</double>
|
||||
</object>
|
||||
<float key="priority">1000</float>
|
||||
<reference key="containingView" ref="191373211"/>
|
||||
<int key="scoringType">8</int>
|
||||
<float key="scoringTypeFloat">29</float>
|
||||
<int key="contentType">3</int>
|
||||
</object>
|
||||
<object class="IBNSLayoutConstraint" id="89828506">
|
||||
<reference key="firstItem" ref="38801877"/>
|
||||
<int key="firstAttribute">3</int>
|
||||
<int key="relation">0</int>
|
||||
<reference key="secondItem" ref="191373211"/>
|
||||
<int key="secondAttribute">3</int>
|
||||
<float key="multiplier">1</float>
|
||||
<object class="IBNSLayoutSymbolicConstant" key="constant">
|
||||
<double key="value">20</double>
|
||||
</object>
|
||||
<float key="priority">1000</float>
|
||||
<reference key="containingView" ref="191373211"/>
|
||||
<int key="scoringType">8</int>
|
||||
<float key="scoringTypeFloat">29</float>
|
||||
<int key="contentType">3</int>
|
||||
</object>
|
||||
<reference ref="694263183"/>
|
||||
<reference ref="38801877"/>
|
||||
<reference ref="721040644"/>
|
||||
<reference ref="58186559"/>
|
||||
<reference ref="562513162"/>
|
||||
<reference ref="61755535"/>
|
||||
<reference ref="1033465661"/>
|
||||
</array>
|
||||
<reference key="parent" ref="0"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">-1</int>
|
||||
<reference key="object" ref="372490531"/>
|
||||
<reference key="parent" ref="0"/>
|
||||
<string key="objectName">File's Owner</string>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">-2</int>
|
||||
<reference key="object" ref="975951072"/>
|
||||
<reference key="parent" ref="0"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">12</int>
|
||||
<reference key="object" ref="61755535"/>
|
||||
<array class="NSMutableArray" key="children"/>
|
||||
<reference key="parent" ref="191373211"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">17</int>
|
||||
<reference key="object" ref="38801877"/>
|
||||
<array class="NSMutableArray" key="children"/>
|
||||
<reference key="parent" ref="191373211"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">30</int>
|
||||
<reference key="object" ref="721040644"/>
|
||||
<array class="NSMutableArray" key="children"/>
|
||||
<reference key="parent" ref="191373211"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">86</int>
|
||||
<reference key="object" ref="694263183"/>
|
||||
<array class="NSMutableArray" key="children">
|
||||
<object class="IBNSLayoutConstraint" id="229625608">
|
||||
<reference key="firstItem" ref="694263183"/>
|
||||
<int key="firstAttribute">7</int>
|
||||
<int key="relation">0</int>
|
||||
<nil key="secondItem"/>
|
||||
<int key="secondAttribute">0</int>
|
||||
<float key="multiplier">1</float>
|
||||
<object class="IBLayoutConstant" key="constant">
|
||||
<double key="value">120</double>
|
||||
</object>
|
||||
<float key="priority">1000</float>
|
||||
<reference key="containingView" ref="694263183"/>
|
||||
<int key="scoringType">3</int>
|
||||
<float key="scoringTypeFloat">9</float>
|
||||
<int key="contentType">1</int>
|
||||
</object>
|
||||
</array>
|
||||
<reference key="parent" ref="191373211"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">88</int>
|
||||
<reference key="object" ref="85952235"/>
|
||||
<reference key="parent" ref="191373211"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">89</int>
|
||||
<reference key="object" ref="89828506"/>
|
||||
<reference key="parent" ref="191373211"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">94</int>
|
||||
<reference key="object" ref="509206074"/>
|
||||
<reference key="parent" ref="191373211"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">97</int>
|
||||
<reference key="object" ref="38515434"/>
|
||||
<reference key="parent" ref="191373211"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">98</int>
|
||||
<reference key="object" ref="963730365"/>
|
||||
<reference key="parent" ref="191373211"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">113</int>
|
||||
<reference key="object" ref="770441708"/>
|
||||
<reference key="parent" ref="191373211"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">115</int>
|
||||
<reference key="object" ref="217059225"/>
|
||||
<reference key="parent" ref="191373211"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">116</int>
|
||||
<reference key="object" ref="120087908"/>
|
||||
<reference key="parent" ref="191373211"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">118</int>
|
||||
<reference key="object" ref="214855274"/>
|
||||
<reference key="parent" ref="191373211"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">119</int>
|
||||
<reference key="object" ref="229625608"/>
|
||||
<reference key="parent" ref="694263183"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">121</int>
|
||||
<reference key="object" ref="1015088714"/>
|
||||
<reference key="parent" ref="191373211"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">122</int>
|
||||
<reference key="object" ref="58186559"/>
|
||||
<array class="NSMutableArray" key="children">
|
||||
<object class="IBNSLayoutConstraint" id="685350466">
|
||||
<reference key="firstItem" ref="58186559"/>
|
||||
<int key="firstAttribute">7</int>
|
||||
<int key="relation">0</int>
|
||||
<nil key="secondItem"/>
|
||||
<int key="secondAttribute">0</int>
|
||||
<float key="multiplier">1</float>
|
||||
<object class="IBLayoutConstant" key="constant">
|
||||
<double key="value">120</double>
|
||||
</object>
|
||||
<float key="priority">1000</float>
|
||||
<reference key="containingView" ref="58186559"/>
|
||||
<int key="scoringType">3</int>
|
||||
<float key="scoringTypeFloat">9</float>
|
||||
<int key="contentType">1</int>
|
||||
</object>
|
||||
</array>
|
||||
<reference key="parent" ref="191373211"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">125</int>
|
||||
<reference key="object" ref="911823456"/>
|
||||
<reference key="parent" ref="191373211"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">127</int>
|
||||
<reference key="object" ref="331948221"/>
|
||||
<reference key="parent" ref="191373211"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">129</int>
|
||||
<reference key="object" ref="700933706"/>
|
||||
<reference key="parent" ref="191373211"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">130</int>
|
||||
<reference key="object" ref="685350466"/>
|
||||
<reference key="parent" ref="58186559"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">131</int>
|
||||
<reference key="object" ref="562513162"/>
|
||||
<reference key="parent" ref="191373211"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">132</int>
|
||||
<reference key="object" ref="804573855"/>
|
||||
<reference key="parent" ref="191373211"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">133</int>
|
||||
<reference key="object" ref="837542760"/>
|
||||
<reference key="parent" ref="191373211"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">135</int>
|
||||
<reference key="object" ref="201787259"/>
|
||||
<reference key="parent" ref="191373211"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">140</int>
|
||||
<reference key="object" ref="1033465661"/>
|
||||
<array class="NSMutableArray" key="children"/>
|
||||
<reference key="parent" ref="191373211"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">142</int>
|
||||
<reference key="object" ref="828923997"/>
|
||||
<reference key="parent" ref="191373211"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">143</int>
|
||||
<reference key="object" ref="402510427"/>
|
||||
<reference key="parent" ref="191373211"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">146</int>
|
||||
<reference key="object" ref="65927411"/>
|
||||
<reference key="parent" ref="191373211"/>
|
||||
</object>
|
||||
</array>
|
||||
</object>
|
||||
<dictionary class="NSMutableDictionary" key="flattenedProperties">
|
||||
<string key="-1.CustomClassName">RetroArch_iOS</string>
|
||||
<string key="-1.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
<string key="-2.CustomClassName">UIResponder</string>
|
||||
<string key="-2.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
<string key="1.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
<array class="NSMutableArray" key="1.IBViewMetadataConstraints">
|
||||
<reference ref="89828506"/>
|
||||
<reference ref="509206074"/>
|
||||
<reference ref="38515434"/>
|
||||
<reference ref="828923997"/>
|
||||
<reference ref="402510427"/>
|
||||
<reference ref="65927411"/>
|
||||
<reference ref="804573855"/>
|
||||
<reference ref="201787259"/>
|
||||
<reference ref="85952235"/>
|
||||
<reference ref="1015088714"/>
|
||||
<reference ref="837542760"/>
|
||||
<reference ref="770441708"/>
|
||||
<reference ref="217059225"/>
|
||||
<reference ref="120087908"/>
|
||||
<reference ref="911823456"/>
|
||||
<reference ref="700933706"/>
|
||||
<reference ref="963730365"/>
|
||||
<reference ref="214855274"/>
|
||||
<reference ref="331948221"/>
|
||||
</array>
|
||||
<string key="113.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
<string key="115.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
<string key="116.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
<string key="118.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
<string key="119.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
<string key="12.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
<boolean value="NO" key="12.IBViewMetadataTranslatesAutoresizingMaskIntoConstraints"/>
|
||||
<string key="121.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
<string key="122.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
<array class="NSMutableArray" key="122.IBViewMetadataConstraints">
|
||||
<reference ref="685350466"/>
|
||||
</array>
|
||||
<boolean value="NO" key="122.IBViewMetadataTranslatesAutoresizingMaskIntoConstraints"/>
|
||||
<string key="125.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
<string key="127.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
<string key="129.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
<string key="130.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
<string key="131.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
<boolean value="NO" key="131.IBViewMetadataTranslatesAutoresizingMaskIntoConstraints"/>
|
||||
<integer value="9" key="131.IUISegmentedControlInspectorSelectedSegmentMetadataKey"/>
|
||||
<string key="132.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
<string key="133.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
<string key="135.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
<string key="140.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
<boolean value="NO" key="140.IBViewMetadataTranslatesAutoresizingMaskIntoConstraints"/>
|
||||
<string key="142.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
<string key="143.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
<string key="146.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
<string key="17.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
<boolean value="NO" key="17.IBViewMetadataTranslatesAutoresizingMaskIntoConstraints"/>
|
||||
<string key="30.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
<boolean value="NO" key="30.IBViewMetadataTranslatesAutoresizingMaskIntoConstraints"/>
|
||||
<string key="86.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
<array key="86.IBViewMetadataConstraints">
|
||||
<reference ref="229625608"/>
|
||||
</array>
|
||||
<boolean value="NO" key="86.IBViewMetadataTranslatesAutoresizingMaskIntoConstraints"/>
|
||||
<string key="88.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
<string key="89.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
<string key="94.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
<string key="97.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
<string key="98.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
</dictionary>
|
||||
<dictionary class="NSMutableDictionary" key="unlocalizedProperties"/>
|
||||
<nil key="activeLocalization"/>
|
||||
<dictionary class="NSMutableDictionary" key="localizations"/>
|
||||
<nil key="sourceID"/>
|
||||
<int key="maxID">148</int>
|
||||
</object>
|
||||
<object class="IBClassDescriber" key="IBDocument.Classes"/>
|
||||
<int key="IBDocument.localizationMode">0</int>
|
||||
<string key="IBDocument.TargetRuntimeIdentifier">IBIPadFramework</string>
|
||||
<bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool>
|
||||
<int key="IBDocument.defaultPropertyAccessControl">3</int>
|
||||
<bool key="IBDocument.UseAutolayout">YES</bool>
|
||||
<string key="IBCocoaTouchPluginVersion">2083</string>
|
||||
</data>
|
||||
</archive>
|
BIN
ios/Assets/ic_pause.png
Normal file
BIN
ios/Assets/ic_pause.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.8 KiB |
55
ios/BUILDING
Normal file
55
ios/BUILDING
Normal file
@ -0,0 +1,55 @@
|
||||
The following instructions will only work if building from OS X, using latest XCode with fake signing enabled.
|
||||
|
||||
To build RetroArch:
|
||||
Open $(root)/ios/RetroArch.xcodeproj, change build type to iOSDevice then choose Product->Build For->Archiving.
|
||||
After compilation finishes goto Window->Organizer->Projects->RetroArch then click the small arrow beside
|
||||
the Derived Data field, this will open a finder window with the projects build files directory highlighted.
|
||||
The app bundle can be found at Build/Products/* in that folder. Use scp to copy the .app bundle to the appropriate place
|
||||
on your device.
|
||||
|
||||
|
||||
To build libretro cores:
|
||||
In general, to build for iOS devices, copy the configuration for OSX, then at the end add the lines:
|
||||
sysroot = -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS6.0.sdk/
|
||||
CC = /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/gcc -arch armv7 $(sysroot)
|
||||
CXX = /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/g++ -arch armv7 $(sysroot)
|
||||
|
||||
Here is how it would look in Makefile.libretro for vba-next:
|
||||
...
|
||||
else ifeq ($(platform), osx)
|
||||
TARGET := vba_next_libretro.dylib
|
||||
fpic := -fPIC
|
||||
SHARED := -dynamiclib
|
||||
ENDIANNESS_DEFINES = -DLSB_FIRST
|
||||
else ifeq ($(platform), ios)
|
||||
TARGET := vba_next_libretro.dylib
|
||||
fpic := -fPIC
|
||||
SHARED := -dynamiclib
|
||||
ENDIANNESS_DEFINES = -DLSB_FIRST
|
||||
|
||||
sysroot = -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS6.0.sdk/
|
||||
CC = /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/gcc -arch armv7 $(sysroot)
|
||||
CXX = /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/g++ -arch armv7 $(sysroot)
|
||||
else ifeq ($(platform), ps3)
|
||||
...
|
||||
|
||||
Other arm specific flags can be added if needed.
|
||||
|
||||
Finally issue the make command for the module adding 'platform=ios' at the of the command.
|
||||
(e.g. 'make -f Makefile.libretro platform=ios'). Then copy the resulting .dylib file into a sub-directory of the app
|
||||
bundle named modules. (e.g. RetroArch.app/modules/vba_next_libretro.dylib).
|
||||
|
||||
Paths:
|
||||
/var/mobile/Library/RetroArch: Will be created to store both saved games and the retroarch.cfg.
|
||||
/var/mobile/RetroArchGames: If this exists and is a directory it will be used as the root for game browsing.
|
||||
/var/mobile: If RetroArchGames does not exist this will be used as the root for game browsing,
|
||||
if another browser root is desired make RetroArchGames a symlink to the preferred path.
|
||||
RetroArch.app/shaders: Contains .shader format shaders, sub-directories are supported.
|
||||
RetroArch.app/overlays: Contains input overlay definitions, sub-directories are supported.
|
||||
RetroArch.app/modules: Contains .dylib files for the libretro modules. The only constraint on the file name
|
||||
is that it must end in .dylib, sub-directories are not supported.
|
||||
|
||||
Simulator:
|
||||
To test in iOS Simulator you will need to create the '/var/mobile' directory on you computer, and give yourself full
|
||||
access to it.
|
||||
|
1301
ios/RetroArch.xcodeproj/project.pbxproj
Normal file
1301
ios/RetroArch.xcodeproj/project.pbxproj
Normal file
File diff suppressed because it is too large
Load Diff
7
ios/RetroArch.xcodeproj/project.xcworkspace/contents.xcworkspacedata
generated
Normal file
7
ios/RetroArch.xcodeproj/project.xcworkspace/contents.xcworkspacedata
generated
Normal file
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "self:RetroArch.xcodeproj">
|
||||
</FileRef>
|
||||
</Workspace>
|
28
ios/RetroArch/RAConfig.h
Normal file
28
ios/RetroArch/RAConfig.h
Normal file
@ -0,0 +1,28 @@
|
||||
/* 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/>.
|
||||
*/
|
||||
|
||||
@interface RAConfig : NSObject
|
||||
- (id)initWithPath:(NSString*)path;
|
||||
- (void)writeToFile:(NSString*)path;
|
||||
|
||||
- (bool)getBoolNamed:(NSString*)name withDefault:(bool)def;
|
||||
- (int)getIntNamed:(NSString*)name withDefault:(int)def;
|
||||
- (unsigned)getUintNamed:(NSString*)name withDefault:(unsigned)def;
|
||||
- (double)getDoubleNamed:(NSString*)name withDefault:(double)def;
|
||||
- (NSString*)getStringNamed:(NSString*)name withDefault:(NSString*)def;
|
||||
|
||||
- (void)putIntNamed:(NSString*)name value:(int)value;
|
||||
- (void)putStringNamed:(NSString*)name value:(NSString*)value;
|
||||
@end
|
91
ios/RetroArch/RAConfig.m
Normal file
91
ios/RetroArch/RAConfig.m
Normal file
@ -0,0 +1,91 @@
|
||||
/* 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/>.
|
||||
*/
|
||||
|
||||
#import "RAConfig.h"
|
||||
#include "conf/config_file.h"
|
||||
|
||||
@implementation RAConfig
|
||||
{
|
||||
config_file_t* _config;
|
||||
}
|
||||
|
||||
- (id)initWithPath:(NSString*)path
|
||||
{
|
||||
_config = config_file_new([path UTF8String]);
|
||||
_config = _config ? _config : config_file_new(0);
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
config_file_free(_config);
|
||||
}
|
||||
|
||||
- (void)writeToFile:(NSString*)path
|
||||
{
|
||||
config_file_write(_config, [path UTF8String]);
|
||||
}
|
||||
|
||||
- (bool)getBoolNamed:(NSString*)name withDefault:(bool)def
|
||||
{
|
||||
bool result = def;
|
||||
config_get_bool(_config, [name UTF8String], &result);
|
||||
return result;
|
||||
}
|
||||
|
||||
- (int)getIntNamed:(NSString*)name withDefault:(int)def
|
||||
{
|
||||
int result = def;
|
||||
config_get_int(_config, [name UTF8String], &result);
|
||||
return result;
|
||||
}
|
||||
|
||||
- (unsigned)getUintNamed:(NSString*)name withDefault:(unsigned)def
|
||||
{
|
||||
unsigned result = def;
|
||||
config_get_uint(_config, [name UTF8String], &result);
|
||||
return result;
|
||||
}
|
||||
|
||||
- (double)getDoubleNamed:(NSString*)name withDefault:(double)def
|
||||
{
|
||||
double result = def;
|
||||
config_get_double(_config, [name UTF8String], &result);
|
||||
return result;
|
||||
}
|
||||
|
||||
- (NSString*)getStringNamed:(NSString*)name withDefault:(NSString*)def
|
||||
{
|
||||
NSString* result = def;
|
||||
|
||||
char* data = 0;
|
||||
if (config_get_string(_config, [name UTF8String], &data))
|
||||
result = [NSString stringWithUTF8String:data];
|
||||
free(data);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
- (void)putIntNamed:(NSString*)name value:(int)value
|
||||
{
|
||||
config_set_int(_config, [name UTF8String], value);
|
||||
}
|
||||
|
||||
- (void)putStringNamed:(NSString*)name value:(NSString*)value
|
||||
{
|
||||
config_set_string(_config, [name UTF8String], [value UTF8String]);
|
||||
}
|
||||
|
||||
@end
|
172
ios/RetroArch/RAGameView.m
Normal file
172
ios/RetroArch/RAGameView.m
Normal file
@ -0,0 +1,172 @@
|
||||
/* 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 "general.h"
|
||||
#include "rarch_wrapper.h"
|
||||
|
||||
static const float ALMOST_INVISIBLE = .021f;
|
||||
static float g_screen_scale;
|
||||
static int g_frame_skips = 4;
|
||||
static bool g_is_syncing = true;
|
||||
static RAGameView* g_instance;
|
||||
|
||||
@implementation RAGameView
|
||||
{
|
||||
EAGLContext* _glContext;
|
||||
|
||||
UIView* _pauseView;
|
||||
UIView* _pauseIndicatorView;
|
||||
}
|
||||
|
||||
+ (RAGameView*)get
|
||||
{
|
||||
if (!g_instance)
|
||||
g_instance = [RAGameView new];
|
||||
|
||||
return g_instance;
|
||||
}
|
||||
|
||||
- (id)init
|
||||
{
|
||||
self = [super init];
|
||||
|
||||
UINib* xib = [UINib nibWithNibName:@"PauseView" bundle:nil];
|
||||
_pauseView = [[xib instantiateWithOwner:[RetroArch_iOS get] options:nil] lastObject];
|
||||
|
||||
xib = [UINib nibWithNibName:@"PauseIndicatorView" bundle:nil];
|
||||
_pauseIndicatorView = [[xib instantiateWithOwner:[RetroArch_iOS get] options:nil] lastObject];
|
||||
|
||||
self.view = [GLKView new];
|
||||
self.view.multipleTouchEnabled = YES;
|
||||
[self.view addSubview:_pauseView];
|
||||
[self.view addSubview:_pauseIndicatorView];
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
// Driver
|
||||
- (void)driverInit
|
||||
{
|
||||
g_screen_scale = [[UIScreen mainScreen] scale];
|
||||
|
||||
_glContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
|
||||
[EAGLContext setCurrentContext:_glContext];
|
||||
((GLKView*)self.view).context = _glContext;
|
||||
|
||||
// Show pause button for a few seconds, so people know it's there
|
||||
_pauseIndicatorView.alpha = 1.0f;
|
||||
[self performSelector:@selector(hidePauseButton) withObject:self afterDelay:3.0f];
|
||||
}
|
||||
|
||||
- (void)driverQuit
|
||||
{
|
||||
glFinish();
|
||||
|
||||
((GLKView*)self.view).context = nil;
|
||||
[EAGLContext setCurrentContext:nil];
|
||||
_glContext = nil;
|
||||
}
|
||||
|
||||
- (void)flip
|
||||
{
|
||||
if (--g_frame_skips < 0)
|
||||
{
|
||||
[self.view setNeedsDisplay];
|
||||
[(GLKView*)self.view bindDrawable];
|
||||
g_frame_skips = g_is_syncing ? 0 : 3;
|
||||
}
|
||||
}
|
||||
|
||||
// Pause Menus
|
||||
- (void)viewWillLayoutSubviews
|
||||
{
|
||||
UIInterfaceOrientation orientation = self.interfaceOrientation;
|
||||
CGRect screenSize = [[UIScreen mainScreen] bounds];
|
||||
|
||||
const float width = ((int)orientation < 3) ? CGRectGetWidth(screenSize) : CGRectGetHeight(screenSize);
|
||||
const float height = ((int)orientation < 3) ? CGRectGetHeight(screenSize) : CGRectGetWidth(screenSize);
|
||||
|
||||
float tenpctw = width / 10.0f;
|
||||
float tenpcth = height / 10.0f;
|
||||
|
||||
_pauseView.frame = CGRectMake(width / 2.0f - 150.0f, height / 2.0f - 150.0f, 300.0f, 300.0f);
|
||||
_pauseIndicatorView.frame = CGRectMake(tenpctw * 4.0f, 0.0f, tenpctw * 2.0f, tenpcth);
|
||||
}
|
||||
|
||||
- (void)openPauseMenu
|
||||
{
|
||||
// Setup save state selector
|
||||
UISegmentedControl* stateSelect = (UISegmentedControl*)[_pauseView viewWithTag:1];
|
||||
stateSelect.selectedSegmentIndex = (g_extern.state_slot < 10) ? g_extern.state_slot : -1;
|
||||
|
||||
//
|
||||
[UIView animateWithDuration:0.2
|
||||
animations:^ { _pauseView.alpha = 1.0f; }
|
||||
completion:^(BOOL finished){}];
|
||||
}
|
||||
|
||||
- (void)closePauseMenu
|
||||
{
|
||||
[UIView animateWithDuration:0.2
|
||||
animations:^ { _pauseView.alpha = 0.0f; }
|
||||
completion:^(BOOL finished) { }
|
||||
];
|
||||
}
|
||||
|
||||
- (void)hidePauseButton
|
||||
{
|
||||
[UIView animateWithDuration:0.2
|
||||
animations:^ { _pauseIndicatorView.alpha = ALMOST_INVISIBLE; }
|
||||
completion:^(BOOL finished) { }
|
||||
];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
bool ios_init_game_view()
|
||||
{
|
||||
[RAGameView.get driverInit];
|
||||
return true;
|
||||
}
|
||||
|
||||
void ios_destroy_game_view()
|
||||
{
|
||||
[RAGameView.get driverQuit];
|
||||
}
|
||||
|
||||
void ios_flip_game_view()
|
||||
{
|
||||
[RAGameView.get flip];
|
||||
}
|
||||
|
||||
void ios_set_game_view_sync(bool on)
|
||||
{
|
||||
g_is_syncing = on;
|
||||
g_frame_skips = on ? 0 : 3;
|
||||
}
|
||||
|
||||
void ios_get_game_view_size(unsigned *width, unsigned *height)
|
||||
{
|
||||
*width = RAGameView.get.view.bounds.size.width * g_screen_scale;
|
||||
*width = *width ? *width : 640;
|
||||
|
||||
*height = RAGameView.get.view.bounds.size.height * g_screen_scale;
|
||||
*height = *height ? *height : 480;
|
||||
}
|
||||
|
||||
void ios_bind_game_view_fbo()
|
||||
{
|
||||
[(GLKView*)RAGameView.get.view bindDrawable];
|
||||
}
|
87
ios/RetroArch/RAModuleInfoList.m
Normal file
87
ios/RetroArch/RAModuleInfoList.m
Normal file
@ -0,0 +1,87 @@
|
||||
/* 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/>.
|
||||
*/
|
||||
|
||||
@implementation RAModuleInfo
|
||||
+ (RAModuleInfo*)moduleWithPath:(NSString*)thePath data:(RAConfig*)theData
|
||||
{
|
||||
RAModuleInfo* new = [RAModuleInfo new];
|
||||
|
||||
new.displayName = [theData getStringNamed:@"display_name" withDefault:[[thePath lastPathComponent] stringByDeletingPathExtension]];
|
||||
new.path = thePath;
|
||||
new.configPath = [NSString stringWithFormat:@"%@/%@.cfg", [RetroArch_iOS get].system_directory, [[thePath lastPathComponent] stringByDeletingPathExtension]];
|
||||
new.data = theData;
|
||||
|
||||
new.supportedExtensions = [[theData getStringNamed:@"supported_extensions" withDefault:@""] componentsSeparatedByString:@"|"];
|
||||
return new;
|
||||
}
|
||||
|
||||
- (bool)supportsFileAtPath:(NSString*)path
|
||||
{
|
||||
return [self.supportedExtensions containsObject:[[path pathExtension] lowercaseString]];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
static NSString* const labels[3] = {@"Emulator Name", @"Manufacturer", @"Name"};
|
||||
static NSString* const keys[3] = {@"emuname", @"manufacturer", @"systemname"};
|
||||
static NSString* const sectionNames[2] = {@"Emulator", @"Hardware"};
|
||||
static const uint32_t sectionSizes[2] = {1, 2};
|
||||
|
||||
@implementation RAModuleInfoList
|
||||
{
|
||||
RAModuleInfo* _data;
|
||||
}
|
||||
|
||||
- (id)initWithModuleInfo:(RAModuleInfo*)info
|
||||
{
|
||||
self = [super initWithStyle:UITableViewStyleGrouped];
|
||||
|
||||
_data = info;
|
||||
return self;
|
||||
}
|
||||
|
||||
- (NSInteger)numberOfSectionsInTableView:(UITableView*)tableView
|
||||
{
|
||||
return sizeof(sectionSizes) / sizeof(sectionSizes[0]);
|
||||
}
|
||||
|
||||
- (NSString*)tableView:(UITableView*)tableView titleForHeaderInSection:(NSInteger)section
|
||||
{
|
||||
return sectionNames[section];
|
||||
}
|
||||
|
||||
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
|
||||
{
|
||||
return sectionSizes[section];
|
||||
}
|
||||
|
||||
- (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
|
||||
{
|
||||
UITableViewCell* cell = [self.tableView dequeueReusableCellWithIdentifier:@"datacell"];
|
||||
cell = (cell != nil) ? cell : [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:@"datacell"];
|
||||
|
||||
uint32_t sectionBase = 0;
|
||||
for (int i = 0; i != indexPath.section; i ++)
|
||||
{
|
||||
sectionBase += sectionSizes[i];
|
||||
}
|
||||
|
||||
cell.textLabel.text = labels[sectionBase + indexPath.row];
|
||||
cell.detailTextLabel.text = [_data.data getStringNamed:keys[sectionBase + indexPath.row] withDefault:@"Unspecified"];
|
||||
|
||||
return cell;
|
||||
}
|
||||
|
||||
@end
|
49
ios/RetroArch/RetroArch-Info.plist
Normal file
49
ios/RetroArch/RetroArch-Info.plist
Normal file
@ -0,0 +1,49 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleDisplayName</key>
|
||||
<string>${PRODUCT_NAME}</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>${EXECUTABLE_NAME}</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>libretro.${PRODUCT_NAME:rfc1034identifier}</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>${PRODUCT_NAME}</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1.0</string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>UIApplicationExitsOnSuspend</key>
|
||||
<false/>
|
||||
<key>UIRequiredDeviceCapabilities</key>
|
||||
<array>
|
||||
<string>armv7</string>
|
||||
</array>
|
||||
<key>UIStatusBarHidden</key>
|
||||
<false/>
|
||||
<key>UISupportedInterfaceOrientations</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations~ipad</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
31
ios/RetroArch/RetroArch-Prefix.pch
Normal file
31
ios/RetroArch/RetroArch-Prefix.pch
Normal file
@ -0,0 +1,31 @@
|
||||
/* 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/>.
|
||||
*/
|
||||
|
||||
//
|
||||
// Prefix header for all source files of the 'RetroArch' target in the 'RetroArch' project
|
||||
//
|
||||
|
||||
#import <Availability.h>
|
||||
|
||||
#ifndef __IPHONE_5_0
|
||||
#warning "This project uses features only available in iOS SDK 5.0 and later."
|
||||
#endif
|
||||
|
||||
#ifdef __OBJC__
|
||||
#import <UIKit/UIKit.h>
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "views.h"
|
||||
#import "RetroArch_iOS.h"
|
||||
#endif
|
32
ios/RetroArch/RetroArch_iOS.h
Normal file
32
ios/RetroArch/RetroArch_iOS.h
Normal file
@ -0,0 +1,32 @@
|
||||
/* 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/>.
|
||||
*/
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@interface RetroArch_iOS : UINavigationController<UIApplicationDelegate, UINavigationControllerDelegate>
|
||||
|
||||
+ (void)displayErrorMessage:(NSString*)message;
|
||||
|
||||
+ (RetroArch_iOS*)get;
|
||||
- (void)runGame:(NSString*)path;
|
||||
- (void)refreshConfig;
|
||||
|
||||
- (IBAction)showSettings;
|
||||
|
||||
@property (strong, nonatomic) RAModuleInfo* moduleInfo;
|
||||
|
||||
@property (strong, nonatomic) NSString* system_directory;
|
||||
|
||||
@end
|
287
ios/RetroArch/RetroArch_iOS.m
Normal file
287
ios/RetroArch/RetroArch_iOS.m
Normal file
@ -0,0 +1,287 @@
|
||||
/* 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 <sys/stat.h>
|
||||
#include "rarch_wrapper.h"
|
||||
#include "general.h"
|
||||
#import "browser/browser.h"
|
||||
#import "settings/settings.h"
|
||||
|
||||
#ifdef WIIMOTE
|
||||
#import "input/BTStack/WiiMoteHelper.h"
|
||||
#endif
|
||||
|
||||
@implementation RetroArch_iOS
|
||||
{
|
||||
UIWindow* _window;
|
||||
NSTimer* _gameTimer;
|
||||
|
||||
bool _isGameTop;
|
||||
bool _isPaused;
|
||||
bool _isRunning;
|
||||
}
|
||||
|
||||
+ (void)displayErrorMessage:(NSString*)message
|
||||
{
|
||||
UIAlertView* alert = [[UIAlertView alloc] initWithTitle:@"RetroArch"
|
||||
message:message
|
||||
delegate:nil
|
||||
cancelButtonTitle:@"OK"
|
||||
otherButtonTitles:nil];
|
||||
[alert show];
|
||||
}
|
||||
|
||||
+ (RetroArch_iOS*)get
|
||||
{
|
||||
return (RetroArch_iOS*)[[UIApplication sharedApplication] delegate];
|
||||
}
|
||||
|
||||
// UIApplicationDelegate
|
||||
- (void)applicationDidFinishLaunching:(UIApplication *)application
|
||||
{
|
||||
// TODO: Relocate this!
|
||||
self.system_directory = @"/var/mobile/Library/RetroArch/";
|
||||
mkdir([self.system_directory UTF8String], 0755);
|
||||
|
||||
// Setup window
|
||||
self.delegate = self;
|
||||
[self pushViewController:[RADirectoryList directoryListOrGridWithPath:nil] animated:YES];
|
||||
|
||||
_window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
|
||||
_window.rootViewController = self;
|
||||
[_window makeKeyAndVisible];
|
||||
}
|
||||
|
||||
- (void)applicationDidBecomeActive:(UIApplication*)application
|
||||
{
|
||||
[self startTimer];
|
||||
}
|
||||
|
||||
- (void)applicationWillResignActive:(UIApplication*)application
|
||||
{
|
||||
[self stopTimer];
|
||||
}
|
||||
|
||||
- (void)applicationWillEnterForeground:(UIApplication *)application
|
||||
{
|
||||
if (_isRunning)
|
||||
init_drivers();
|
||||
}
|
||||
|
||||
- (void)applicationDidEnterBackground:(UIApplication *)application
|
||||
{
|
||||
if (_isRunning)
|
||||
uninit_drivers();
|
||||
}
|
||||
|
||||
// UINavigationControllerDelegate
|
||||
- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated
|
||||
{
|
||||
_isGameTop = [viewController isKindOfClass:[RAGameView class]];
|
||||
[[UIApplication sharedApplication] setStatusBarHidden:_isGameTop withAnimation:UIStatusBarAnimationNone];
|
||||
self.navigationBarHidden = _isGameTop;
|
||||
|
||||
if (_isGameTop)
|
||||
[self startTimer];
|
||||
|
||||
self.topViewController.navigationItem.rightBarButtonItem = [self createBluetoothButton];
|
||||
}
|
||||
|
||||
// UINavigationController: Never animate when pushing onto, or popping, an RAGameView
|
||||
- (void)pushViewController:(UIViewController*)theView animated:(BOOL)animated
|
||||
{
|
||||
[super pushViewController:theView animated:animated && !_isGameTop];
|
||||
}
|
||||
|
||||
- (UIViewController*)popViewControllerAnimated:(BOOL)animated
|
||||
{
|
||||
return [super popViewControllerAnimated:animated && !_isGameTop];
|
||||
}
|
||||
|
||||
#pragma mark EMULATION
|
||||
- (void)runGame:(NSString*)path
|
||||
{
|
||||
assert(self.moduleInfo);
|
||||
|
||||
[RASettingsList refreshConfigFile];
|
||||
|
||||
const char* const sd = [[RetroArch_iOS get].system_directory UTF8String];
|
||||
const char* const cf = (ra_ios_is_file(self.moduleInfo.configPath)) ? [self.moduleInfo.configPath UTF8String] : 0;
|
||||
const char* const libretro = [self.moduleInfo.path UTF8String];
|
||||
|
||||
struct rarch_main_wrap main_wrapper = {[path UTF8String], sd, sd, cf, libretro};
|
||||
if (rarch_main_init_wrap(&main_wrapper) == 0)
|
||||
{
|
||||
rarch_init_msg_queue();
|
||||
|
||||
// Read load time settings
|
||||
RAConfig* conf = [[RAConfig alloc] initWithPath:self.moduleInfo.configPath];
|
||||
if ([conf getBoolNamed:@"ios_auto_bluetooth" withDefault:false])
|
||||
[self startBluetooth];
|
||||
|
||||
//
|
||||
[self pushViewController:RAGameView.get animated:NO];
|
||||
_isRunning = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
_isRunning = false;
|
||||
[RetroArch_iOS displayErrorMessage:@"Failed to load game."];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)closeGame
|
||||
{
|
||||
if (_isRunning)
|
||||
{
|
||||
_isRunning = false;
|
||||
|
||||
rarch_main_deinit();
|
||||
rarch_deinit_msg_queue();
|
||||
rarch_main_clear_state();
|
||||
|
||||
// Stop bluetooth (might be annoying but forgetting could eat battery of device AND wiimote)
|
||||
[self stopBluetooth];
|
||||
|
||||
//
|
||||
[self popToViewController:[RAGameView get] animated:NO];
|
||||
[self popViewControllerAnimated:NO];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)refreshConfig
|
||||
{
|
||||
// Need to clear these otherwise stale versions may be used!
|
||||
memset(g_settings.input.overlay, 0, sizeof(g_settings.input.overlay));
|
||||
memset(g_settings.video.bsnes_shader_path, 0, sizeof(g_settings.video.bsnes_shader_path));
|
||||
|
||||
if (_isRunning)
|
||||
{
|
||||
uninit_drivers();
|
||||
config_load();
|
||||
init_drivers();
|
||||
}
|
||||
}
|
||||
|
||||
- (void)iterate
|
||||
{
|
||||
if (_isPaused || !_isRunning || !_isGameTop)
|
||||
[self stopTimer];
|
||||
else if (_isRunning && !rarch_main_iterate())
|
||||
[self closeGame];
|
||||
}
|
||||
|
||||
- (void)startTimer
|
||||
{
|
||||
if (!_gameTimer)
|
||||
_gameTimer = [NSTimer scheduledTimerWithTimeInterval:0.001f target:self selector:@selector(iterate) userInfo:nil repeats:YES];
|
||||
}
|
||||
|
||||
- (void)stopTimer
|
||||
{
|
||||
if (_gameTimer)
|
||||
[_gameTimer invalidate];
|
||||
|
||||
_gameTimer = nil;
|
||||
}
|
||||
|
||||
#pragma mark PAUSE MENU
|
||||
- (IBAction)showPauseMenu:(id)sender
|
||||
{
|
||||
if (_isRunning && !_isPaused && _isGameTop)
|
||||
{
|
||||
_isPaused = true;
|
||||
[[RAGameView get] openPauseMenu];
|
||||
}
|
||||
}
|
||||
|
||||
- (IBAction)resetGame:(id)sender
|
||||
{
|
||||
if (_isRunning) rarch_game_reset();
|
||||
[self closePauseMenu:sender];
|
||||
}
|
||||
|
||||
- (IBAction)loadState:(id)sender
|
||||
{
|
||||
if (_isRunning) rarch_load_state();
|
||||
[self closePauseMenu:sender];
|
||||
}
|
||||
|
||||
- (IBAction)saveState:(id)sender
|
||||
{
|
||||
if (_isRunning) rarch_save_state();
|
||||
[self closePauseMenu:sender];
|
||||
}
|
||||
|
||||
- (IBAction)chooseState:(id)sender
|
||||
{
|
||||
g_extern.state_slot = ((UISegmentedControl*)sender).selectedSegmentIndex;
|
||||
}
|
||||
|
||||
- (IBAction)closePauseMenu:(id)sender
|
||||
{
|
||||
[[RAGameView get] closePauseMenu];
|
||||
|
||||
if (_isPaused)
|
||||
{
|
||||
_isPaused = false;
|
||||
[self startTimer];
|
||||
}
|
||||
}
|
||||
|
||||
- (IBAction)closeGamePressed:(id)sender
|
||||
{
|
||||
[self closePauseMenu:sender];
|
||||
[self closeGame];
|
||||
}
|
||||
|
||||
- (IBAction)showSettings
|
||||
{
|
||||
[self pushViewController:[RASettingsList new] animated:YES];
|
||||
}
|
||||
|
||||
#pragma mark Bluetooth Helpers
|
||||
- (UIBarButtonItem*)createBluetoothButton
|
||||
{
|
||||
#ifdef WIIMOTE
|
||||
const bool isBTOn = [WiiMoteHelper isBluetoothRunning];
|
||||
return [[UIBarButtonItem alloc]
|
||||
initWithTitle:isBTOn ? @"Stop Bluetooth" : @"Start Bluetooth"
|
||||
style:UIBarButtonItemStyleBordered
|
||||
target:[RetroArch_iOS get]
|
||||
action:isBTOn ? @selector(stopBluetooth) : @selector(startBluetooth)];
|
||||
#else
|
||||
return nil;
|
||||
#endif
|
||||
}
|
||||
|
||||
- (IBAction)startBluetooth
|
||||
{
|
||||
#ifdef WIIMOTE
|
||||
[WiiMoteHelper startBluetooth];
|
||||
[self.topViewController.navigationItem setRightBarButtonItem:[self createBluetoothButton] animated:YES];
|
||||
#endif
|
||||
}
|
||||
|
||||
- (IBAction)stopBluetooth
|
||||
{
|
||||
#ifdef WIIMOTE
|
||||
[WiiMoteHelper stopBluetooth];
|
||||
[self.topViewController.navigationItem setRightBarButtonItem:[self createBluetoothButton] animated:YES];
|
||||
#endif
|
||||
}
|
||||
|
||||
@end
|
||||
|
110
ios/RetroArch/browser/RADirectoryGrid.m
Normal file
110
ios/RetroArch/browser/RADirectoryGrid.m
Normal file
@ -0,0 +1,110 @@
|
||||
/* 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/>.
|
||||
*/
|
||||
|
||||
#import "RAConfig.h"
|
||||
#import "browser.h"
|
||||
|
||||
@implementation RADirectoryGrid
|
||||
{
|
||||
NSString* _path;
|
||||
NSArray* _list;
|
||||
RAConfig* _config;
|
||||
}
|
||||
|
||||
- (id)initWithPath:(NSString*)path config:(RAConfig*)config
|
||||
{
|
||||
_path = path;
|
||||
_config = config;
|
||||
_list = ra_ios_list_directory(_path);
|
||||
|
||||
[self setTitle: [_path lastPathComponent]];
|
||||
|
||||
// Init collection view
|
||||
UICollectionViewFlowLayout* layout = [UICollectionViewFlowLayout new];
|
||||
layout.itemSize = CGSizeMake([config getUintNamed:@"cover_width" withDefault:100], [config getUintNamed:@"cover_height" withDefault:100]);
|
||||
self = [super initWithCollectionViewLayout:layout];
|
||||
|
||||
[self.collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:@"dircell"];
|
||||
[self.collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:@"textcell"];
|
||||
[self.collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:@"imagecell"];
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
|
||||
{
|
||||
return [_list count];
|
||||
}
|
||||
|
||||
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
|
||||
{
|
||||
RADirectoryItem* path = [_list objectAtIndex: indexPath.row];
|
||||
|
||||
if(path.isDirectory)
|
||||
[[RetroArch_iOS get] pushViewController:[RADirectoryList directoryListOrGridWithPath:path.path] animated:YES];
|
||||
else
|
||||
[[RetroArch_iOS get] pushViewController:[[RAModuleList alloc] initWithGame:path.path] animated:YES];
|
||||
}
|
||||
|
||||
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
|
||||
{
|
||||
RADirectoryItem* path = [_list objectAtIndex: indexPath.row];
|
||||
UICollectionViewCell* cell = nil;
|
||||
|
||||
if (path.isDirectory)
|
||||
{
|
||||
cell = [self.collectionView dequeueReusableCellWithReuseIdentifier:@"dircell" forIndexPath:indexPath];
|
||||
|
||||
if (!cell.backgroundView)
|
||||
{
|
||||
cell.backgroundView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"ic_dir"]];
|
||||
((UIImageView*)cell.backgroundView).contentMode = UIViewContentModeScaleAspectFit;
|
||||
}
|
||||
}
|
||||
else if (path.coverPath)
|
||||
{
|
||||
cell = [self.collectionView dequeueReusableCellWithReuseIdentifier:@"imagecell" forIndexPath:indexPath];
|
||||
|
||||
if (!cell.backgroundView)
|
||||
{
|
||||
cell.backgroundView = [UIImageView new];
|
||||
((UIImageView*)cell.backgroundView).contentMode = UIViewContentModeScaleAspectFit;
|
||||
}
|
||||
|
||||
((UIImageView*)cell.backgroundView).image = [UIImage imageWithContentsOfFile:path.coverPath];
|
||||
}
|
||||
else
|
||||
{
|
||||
cell = [self.collectionView dequeueReusableCellWithReuseIdentifier:@"textcell" forIndexPath:indexPath];
|
||||
|
||||
if (!cell.backgroundView)
|
||||
{
|
||||
cell.backgroundView = [UILabel new];
|
||||
((UILabel*)cell.backgroundView).numberOfLines = 0;
|
||||
((UILabel*)cell.backgroundView).textAlignment = NSTextAlignmentCenter;
|
||||
}
|
||||
|
||||
((UILabel*)cell.backgroundView).text = [path.path lastPathComponent];
|
||||
}
|
||||
|
||||
return cell;
|
||||
}
|
||||
|
||||
@end
|
80
ios/RetroArch/browser/RADirectoryList.m
Normal file
80
ios/RetroArch/browser/RADirectoryList.m
Normal file
@ -0,0 +1,80 @@
|
||||
/* 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/>.
|
||||
*/
|
||||
|
||||
#import "browser.h"
|
||||
|
||||
@implementation RADirectoryList
|
||||
{
|
||||
NSString* _path;
|
||||
NSArray* _list;
|
||||
RAConfig* _config;
|
||||
}
|
||||
|
||||
+ (id)directoryListOrGridWithPath:(NSString*)path
|
||||
{
|
||||
path = ra_ios_check_path(path);
|
||||
RAConfig* config = [[RAConfig alloc] initWithPath:[path stringByAppendingPathComponent:@".raconfig"]];
|
||||
|
||||
if ([UICollectionViewController instancesRespondToSelector:@selector(initWithCollectionViewLayout:)])
|
||||
{
|
||||
NSString* coverDir = [path stringByAppendingPathComponent:@".coverart"];
|
||||
if (ra_ios_is_directory(coverDir))
|
||||
return [[RADirectoryGrid alloc] initWithPath:path config:config];
|
||||
}
|
||||
|
||||
return [[RADirectoryList alloc] initWithPath:path config:config];
|
||||
}
|
||||
|
||||
- (id)initWithPath:(NSString*)path config:(RAConfig*)config
|
||||
{
|
||||
self = [super initWithStyle:UITableViewStylePlain];
|
||||
|
||||
_path = path;
|
||||
_config = config;
|
||||
_list = ra_ios_list_directory(_path);
|
||||
|
||||
[self setTitle: [_path lastPathComponent]];
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
|
||||
{
|
||||
RADirectoryItem* path = [_list objectAtIndex: indexPath.row];
|
||||
|
||||
if(path.isDirectory)
|
||||
[[RetroArch_iOS get] pushViewController:[RADirectoryList directoryListOrGridWithPath:path.path] animated:YES];
|
||||
else
|
||||
[[RetroArch_iOS get] pushViewController:[[RAModuleList alloc] initWithGame:path.path] animated:YES];
|
||||
}
|
||||
|
||||
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
|
||||
{
|
||||
return [_list count];
|
||||
}
|
||||
|
||||
- (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
|
||||
{
|
||||
RADirectoryItem* path = [_list objectAtIndex: indexPath.row];
|
||||
|
||||
UITableViewCell* cell = [self.tableView dequeueReusableCellWithIdentifier:@"path"];
|
||||
cell = (cell != nil) ? cell : [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"path"];
|
||||
cell.textLabel.text = [path.path lastPathComponent];
|
||||
cell.accessoryType = (path.isDirectory) ? UITableViewCellAccessoryDisclosureIndicator : UITableViewCellAccessoryNone;
|
||||
cell.imageView.image = [UIImage imageNamed:(path.isDirectory) ? @"ic_dir" : @"ic_file"];
|
||||
return cell;
|
||||
}
|
||||
|
||||
@end
|
128
ios/RetroArch/browser/RAModuleList.m
Normal file
128
ios/RetroArch/browser/RAModuleList.m
Normal file
@ -0,0 +1,128 @@
|
||||
/* 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/>.
|
||||
*/
|
||||
|
||||
#import "browser.h"
|
||||
|
||||
@implementation RAModuleList
|
||||
{
|
||||
NSMutableArray* _supported;
|
||||
NSMutableArray* _other;
|
||||
|
||||
NSString* _game;
|
||||
}
|
||||
|
||||
- (id)initWithGame:(NSString*)path
|
||||
{
|
||||
self = [super initWithStyle:UITableViewStyleGrouped];
|
||||
_game = path;
|
||||
|
||||
// Get the contents of the modules directory of the bundle.
|
||||
NSString* module_dir = [NSString stringWithFormat:@"%@/modules", [[NSBundle mainBundle] bundlePath]];
|
||||
|
||||
NSArray* moduleList = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:module_dir error:nil];
|
||||
|
||||
if (moduleList != nil)
|
||||
{
|
||||
moduleList = [module_dir stringsByAppendingPaths:moduleList];
|
||||
moduleList = [moduleList pathsMatchingExtensions:[NSArray arrayWithObject:@"dylib"]];
|
||||
}
|
||||
|
||||
if (moduleList == nil || [moduleList count] == 0)
|
||||
{
|
||||
[RetroArch_iOS displayErrorMessage:@"No libretro cores were found."];
|
||||
}
|
||||
|
||||
// Load the modules with their data
|
||||
_supported = [NSMutableArray array];
|
||||
_other = [NSMutableArray array];
|
||||
|
||||
for (int i = 0; i != [moduleList count]; i ++)
|
||||
{
|
||||
NSString* modulePath = [moduleList objectAtIndex:i];
|
||||
NSString* baseName = [[modulePath stringByDeletingPathExtension] stringByAppendingPathExtension:@"info"];
|
||||
|
||||
RAModuleInfo* module = [RAModuleInfo moduleWithPath:modulePath data:[[RAConfig alloc] initWithPath:baseName]];
|
||||
|
||||
if ([module supportsFileAtPath:_game])
|
||||
[_supported addObject:module];
|
||||
else
|
||||
[_other addObject:module];
|
||||
}
|
||||
|
||||
// Sort
|
||||
[_supported sortUsingComparator:^(RAModuleInfo* left, RAModuleInfo* right)
|
||||
{
|
||||
return [left.displayName caseInsensitiveCompare:right.displayName];
|
||||
}];
|
||||
|
||||
[_other sortUsingComparator:^(RAModuleInfo* left, RAModuleInfo* right)
|
||||
{
|
||||
return [left.displayName caseInsensitiveCompare:right.displayName];
|
||||
}];
|
||||
|
||||
[self setTitle:[_game lastPathComponent]];
|
||||
return self;
|
||||
}
|
||||
|
||||
- (NSInteger)numberOfSectionsInTableView:(UITableView*)tableView
|
||||
{
|
||||
return _supported.count ? 2 : 1;
|
||||
}
|
||||
|
||||
- (NSString*)tableView:(UITableView*)tableView titleForHeaderInSection:(NSInteger)section
|
||||
{
|
||||
if (_supported.count)
|
||||
return (section == 0) ? @"Suggested Emulators" : @"Other Emulators";
|
||||
|
||||
return @"All Emulators";
|
||||
}
|
||||
|
||||
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
|
||||
{
|
||||
NSMutableArray* sectionData = (_supported.count && section == 0) ? _supported : _other;
|
||||
return sectionData.count;
|
||||
}
|
||||
|
||||
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
|
||||
{
|
||||
NSMutableArray* sectionData = (_supported.count && indexPath.section == 0) ? _supported : _other;
|
||||
[RetroArch_iOS get].moduleInfo = (RAModuleInfo*)sectionData[indexPath.row];
|
||||
|
||||
[[RetroArch_iOS get] runGame:_game];
|
||||
}
|
||||
|
||||
- (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath
|
||||
{
|
||||
NSMutableArray* sectionData = (_supported.count && indexPath.section == 0) ? _supported : _other;
|
||||
[RetroArch_iOS get].moduleInfo = (RAModuleInfo*)sectionData[indexPath.row];
|
||||
|
||||
[[RetroArch_iOS get] showSettings];
|
||||
}
|
||||
|
||||
- (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
|
||||
{
|
||||
UITableViewCell* cell = [self.tableView dequeueReusableCellWithIdentifier:@"module"];
|
||||
cell = (cell != nil) ? cell : [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"module"];
|
||||
|
||||
NSMutableArray* sectionData = (_supported.count && indexPath.section == 0) ? _supported : _other;
|
||||
RAModuleInfo* info = (RAModuleInfo*)sectionData[indexPath.row];
|
||||
|
||||
cell.textLabel.text = info.displayName;
|
||||
cell.accessoryType = (info.data) ? UITableViewCellAccessoryDetailDisclosureButton : UITableViewCellAccessoryNone;
|
||||
|
||||
return cell;
|
||||
}
|
||||
|
||||
@end
|
38
ios/RetroArch/browser/browser.h
Normal file
38
ios/RetroArch/browser/browser.h
Normal file
@ -0,0 +1,38 @@
|
||||
/* 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/>.
|
||||
*/
|
||||
|
||||
extern BOOL ra_ios_is_directory(NSString* path);
|
||||
extern BOOL ra_ios_is_file(NSString* path);
|
||||
extern NSArray* ra_ios_list_directory(NSString* path);
|
||||
extern NSString* ra_ios_check_path(NSString* path);
|
||||
|
||||
@interface RADirectoryItem : NSObject
|
||||
@property (strong) NSString* path;
|
||||
@property (strong) NSString* coverPath;
|
||||
@property bool isDirectory;
|
||||
@end
|
||||
|
||||
@interface RADirectoryGrid : UICollectionViewController
|
||||
- (id)initWithPath:(NSString*)path config:(RAConfig*)config;
|
||||
@end
|
||||
|
||||
@interface RADirectoryList : UITableViewController
|
||||
+ (id)directoryListOrGridWithPath:(NSString*)path;
|
||||
- (id)initWithPath:(NSString*)path config:(RAConfig*)config;
|
||||
@end
|
||||
|
||||
@interface RAModuleList : UITableViewController
|
||||
- (id)initWithGame:(NSString*)path;
|
||||
@end
|
104
ios/RetroArch/browser/browser.m
Normal file
104
ios/RetroArch/browser/browser.m
Normal file
@ -0,0 +1,104 @@
|
||||
/* 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 <dirent.h>
|
||||
#include <sys/stat.h>
|
||||
#import "browser.h"
|
||||
|
||||
@implementation RADirectoryItem
|
||||
+ (RADirectoryItem*)directoryItemFromPath:(const char*)thePath checkForCovers:(BOOL)checkCovers
|
||||
{
|
||||
RADirectoryItem* result = [RADirectoryItem new];
|
||||
result.path = [NSString stringWithUTF8String:thePath];
|
||||
|
||||
struct stat statbuf;
|
||||
if (stat(thePath, &statbuf) == 0)
|
||||
result.isDirectory = S_ISDIR(statbuf.st_mode);
|
||||
|
||||
if (checkCovers && !result.isDirectory)
|
||||
{
|
||||
result.coverPath = [NSString stringWithFormat:@"%@/.coverart/%@.png", [result.path stringByDeletingLastPathComponent], [[result.path lastPathComponent] stringByDeletingPathExtension]];
|
||||
|
||||
if (!ra_ios_is_file(result.coverPath))
|
||||
result.coverPath = nil;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
@end
|
||||
|
||||
|
||||
BOOL ra_ios_is_file(NSString* path)
|
||||
{
|
||||
return [[NSFileManager defaultManager] fileExistsAtPath:path isDirectory:nil];
|
||||
}
|
||||
|
||||
BOOL ra_ios_is_directory(NSString* path)
|
||||
{
|
||||
BOOL result = NO;
|
||||
[[NSFileManager defaultManager] fileExistsAtPath:path isDirectory:&result];
|
||||
return result;
|
||||
}
|
||||
|
||||
NSArray* ra_ios_list_directory(NSString* path)
|
||||
{
|
||||
NSMutableArray* result = [NSMutableArray array];
|
||||
|
||||
// Build list
|
||||
char* cpath = malloc([path length] + sizeof(struct dirent));
|
||||
sprintf(cpath, "%s/", [path UTF8String]);
|
||||
size_t cpath_end = strlen(cpath);
|
||||
|
||||
DIR* dir = opendir(cpath);
|
||||
if (!dir)
|
||||
return result;
|
||||
|
||||
for(struct dirent* item = readdir(dir); item; item = readdir(dir))
|
||||
{
|
||||
if (strcmp(item->d_name, ".") == 0 || strcmp(item->d_name, "..") == 0)
|
||||
continue;
|
||||
|
||||
cpath[cpath_end] = 0;
|
||||
strcat(cpath, item->d_name);
|
||||
|
||||
[result addObject:[RADirectoryItem directoryItemFromPath:cpath checkForCovers:YES]];
|
||||
}
|
||||
|
||||
closedir(dir);
|
||||
free(cpath);
|
||||
|
||||
// Sort
|
||||
[result sortUsingComparator:^(RADirectoryItem* left, RADirectoryItem* right)
|
||||
{
|
||||
return (left.isDirectory != right.isDirectory) ?
|
||||
(left.isDirectory ? -1 : 1) :
|
||||
([left.path caseInsensitiveCompare:right.path]);
|
||||
}];
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
NSString* ra_ios_check_path(NSString* path)
|
||||
{
|
||||
if (path && ra_ios_is_directory(path))
|
||||
return path;
|
||||
|
||||
if (path)
|
||||
[RetroArch_iOS displayErrorMessage:@"Browsed path is not a directory."];
|
||||
|
||||
if (ra_ios_is_directory(@"/var/mobile/RetroArchGames")) return @"/var/mobile/RetroArchGames";
|
||||
else if (ra_ios_is_directory(@"/var/mobile")) return @"/var/mobile";
|
||||
else return @"/";
|
||||
}
|
2
ios/RetroArch/en.lproj/InfoPlist.strings
Normal file
2
ios/RetroArch/en.lproj/InfoPlist.strings
Normal file
@ -0,0 +1,2 @@
|
||||
/* Localized versions of Info.plist keys */
|
||||
|
92
ios/RetroArch/input/BTStack/BTDevice.h
Normal file
92
ios/RetroArch/input/BTStack/BTDevice.h
Normal file
@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright (C) 2009 by Matthias Ringwald
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holders nor the names of
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY MATTHIAS RINGWALD AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
|
||||
* RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
//
|
||||
// BTDevice.h
|
||||
//
|
||||
// Created by Matthias Ringwald on 3/30/09.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#include "btstack/utils.h"
|
||||
|
||||
#define kCODHID 0x2540
|
||||
#define kCODZeeMote 0x584
|
||||
#define kCODInvalid 0xffff
|
||||
|
||||
typedef enum {
|
||||
kBluetoothDeviceTypeGeneric = 0,
|
||||
kBluetoothDeviceTypeHID,
|
||||
kBluetoothDeviceTypeMobilePhone,
|
||||
kBluetoothDeviceTypeSmartPhone,
|
||||
kBluetoothDeviceTypeZeeMote,
|
||||
} BluetoothDeviceType;
|
||||
|
||||
typedef enum {
|
||||
kBluetoothConnectionNotConnected = 0,
|
||||
kBluetoothConnectionRemoteName,
|
||||
kBluetoothConnectionConnecting,
|
||||
kBluetoothConnectionConnected
|
||||
} BluetoothConnectionState;
|
||||
|
||||
@interface BTDevice : NSObject {
|
||||
|
||||
bd_addr_t _address;
|
||||
|
||||
NSString * name;
|
||||
uint32_t classOfDevice;
|
||||
|
||||
uint8_t pageScanRepetitionMode;
|
||||
uint16_t clockOffset;
|
||||
|
||||
uint8_t rssi;
|
||||
|
||||
// deprecated
|
||||
BluetoothConnectionState connectionState;
|
||||
}
|
||||
|
||||
- (void) setAddress:(bd_addr_t*)addr;
|
||||
- (BOOL) setAddressFromString:(NSString *) addressString;
|
||||
- (bd_addr_t*) address;
|
||||
- (NSString *) toString;
|
||||
- (NSString *) addressString;
|
||||
+ (NSString *) stringForAddress:(bd_addr_t*) address;
|
||||
+ (BOOL) address:(bd_addr_t *) address fromString:(NSString *) addressString;
|
||||
@property (readonly) BluetoothDeviceType deviceType;
|
||||
@property (readonly) NSString * nameOrAddress;
|
||||
@property (nonatomic, copy) NSString * name;
|
||||
@property (nonatomic, assign) uint32_t classOfDevice;
|
||||
@property (nonatomic, assign) uint16_t clockOffset;
|
||||
@property (nonatomic, assign) uint8_t pageScanRepetitionMode;
|
||||
@property (nonatomic, assign) uint8_t rssi;
|
||||
@property (nonatomic, assign) BluetoothConnectionState connectionState;
|
||||
|
||||
@end
|
129
ios/RetroArch/input/BTStack/BTDevice.m
Normal file
129
ios/RetroArch/input/BTStack/BTDevice.m
Normal file
@ -0,0 +1,129 @@
|
||||
/*
|
||||
* Copyright (C) 2009 by Matthias Ringwald
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holders nor the names of
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY MATTHIAS RINGWALD AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
|
||||
* RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
//
|
||||
// BTDevice.m
|
||||
//
|
||||
// Created by Matthias Ringwald on 3/30/09.
|
||||
//
|
||||
|
||||
#import "BTDevice.h"
|
||||
|
||||
@implementation BTDevice
|
||||
|
||||
@synthesize name;
|
||||
@synthesize classOfDevice;
|
||||
@synthesize connectionState;
|
||||
@synthesize pageScanRepetitionMode;
|
||||
@synthesize clockOffset;
|
||||
@synthesize rssi;
|
||||
|
||||
- (BTDevice *)init {
|
||||
name = NULL;
|
||||
memset(&_address, 0, 6);
|
||||
classOfDevice = kCODInvalid;
|
||||
connectionState = kBluetoothConnectionNotConnected;
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) setAddress:(bd_addr_t*)newAddr{
|
||||
BD_ADDR_COPY( &_address, newAddr);
|
||||
}
|
||||
|
||||
- (BOOL) setAddressFromString:(NSString *) addressString{
|
||||
return [BTDevice address:&_address fromString:addressString];
|
||||
}
|
||||
|
||||
- (bd_addr_t*) address{
|
||||
return &_address;
|
||||
}
|
||||
|
||||
+ (NSString *) stringForAddress:(bd_addr_t*) address {
|
||||
uint8_t *addr = (uint8_t*) *address;
|
||||
return [NSString stringWithFormat:@"%02x:%02x:%02x:%02x:%02x:%02x", addr[0], addr[1], addr[2],
|
||||
addr[3], addr[4], addr[5]];
|
||||
}
|
||||
|
||||
+ (BOOL) address:(bd_addr_t *)address fromString:(NSString *) addressString{
|
||||
// support both : and - or NOTHING as separator
|
||||
addressString = [addressString stringByReplacingOccurrencesOfString:@":" withString:@""];
|
||||
addressString = [addressString stringByReplacingOccurrencesOfString:@"-" withString:@""];
|
||||
if ([addressString length] != 12) return NO;
|
||||
|
||||
unsigned int bd_addr_buffer[BD_ADDR_LEN]; //for sscanf, integer needed
|
||||
// reset result buffer
|
||||
int i;
|
||||
for (i = 0; i < BD_ADDR_LEN; i++) {
|
||||
bd_addr_buffer[i] = 0;
|
||||
}
|
||||
|
||||
// parse
|
||||
int result = sscanf([addressString UTF8String], "%2x%2x%2x%2x%2x%2x", &bd_addr_buffer[0], &bd_addr_buffer[1], &bd_addr_buffer[2],
|
||||
&bd_addr_buffer[3], &bd_addr_buffer[4], &bd_addr_buffer[5]);
|
||||
// store
|
||||
if (result == 6){
|
||||
for (i = 0; i < BD_ADDR_LEN; i++) {
|
||||
(*address)[i] = (uint8_t) bd_addr_buffer[i];
|
||||
}
|
||||
return YES;
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (NSString *) nameOrAddress{
|
||||
if (name) return name;
|
||||
return [self addressString];
|
||||
}
|
||||
|
||||
- (NSString *) addressString{
|
||||
return [BTDevice stringForAddress:&_address];
|
||||
}
|
||||
|
||||
- (BluetoothDeviceType) deviceType{
|
||||
switch (classOfDevice) {
|
||||
case kCODHID:
|
||||
return kBluetoothDeviceTypeHID;
|
||||
case kCODZeeMote:
|
||||
return kBluetoothDeviceTypeZeeMote;
|
||||
default:
|
||||
return kBluetoothDeviceTypeGeneric;
|
||||
}
|
||||
}
|
||||
- (NSString *) toString{
|
||||
return [NSString stringWithFormat:@"Device addr %@ name %@ COD %x", [BTDevice stringForAddress:&_address], name, classOfDevice];
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
[name release];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
@end
|
188
ios/RetroArch/input/BTStack/BTstackManager.h
Normal file
188
ios/RetroArch/input/BTStack/BTstackManager.h
Normal file
@ -0,0 +1,188 @@
|
||||
/*
|
||||
* Copyright (C) 2009 by Matthias Ringwald
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holders nor the names of
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY MATTHIAS RINGWALD AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
|
||||
* RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <stdint.h>
|
||||
#import "btstack/btstack.h"
|
||||
|
||||
#define PREFS_REMOTE_NAME @"RemoteName"
|
||||
#define PREFS_LINK_KEY @"LinkKey"
|
||||
#define BTstackManagerID @"ch.ringwald.btstack"
|
||||
|
||||
@class BTDevice;
|
||||
|
||||
/*
|
||||
* Information on devices is stored in a system-wide plist
|
||||
* it is maintained by BTstackManager
|
||||
* this includes the link keys
|
||||
*/
|
||||
|
||||
// TODO enumerate BTstackError type
|
||||
typedef int BTstackError;
|
||||
|
||||
typedef enum {
|
||||
kDeactivated = 1,
|
||||
kW4SysBTState,
|
||||
kW4SysBTDisabled,
|
||||
kW4Activated,
|
||||
kActivated,
|
||||
kW4Deactivated,
|
||||
kSleeping,
|
||||
#if 0
|
||||
kW4DisoveryStopped,
|
||||
kW4AuthenticationEnableCommand
|
||||
#endif
|
||||
} ManagerState;
|
||||
|
||||
typedef enum {
|
||||
kInactive = 1,
|
||||
kW4InquiryMode,
|
||||
kInquiry,
|
||||
kRemoteName,
|
||||
// stopping
|
||||
kW4InquiryModeBeforeStop,
|
||||
kW4InquiryStop,
|
||||
kW4RemoteNameBeforeStop,
|
||||
} DiscoveryState;
|
||||
|
||||
@protocol BTstackManagerDelegate;
|
||||
@protocol BTstackManagerListener;
|
||||
|
||||
@interface BTstackManager : NSObject {
|
||||
@private
|
||||
NSObject<BTstackManagerDelegate>* _delegate;
|
||||
NSMutableArray *discoveredDevices;
|
||||
NSMutableSet *listeners;
|
||||
BOOL connectedToDaemon;
|
||||
ManagerState state;
|
||||
DiscoveryState discoveryState;
|
||||
int discoveryDeviceIndex;
|
||||
#if 0
|
||||
// current connection - kind a ugly
|
||||
uint8_t connType; // 0 = L2CAP, 1 = RFCOMM
|
||||
bd_addr_t connAddr;
|
||||
uint16_t connPSM;
|
||||
uint16_t connChan;
|
||||
uint8_t connAuth;
|
||||
#endif
|
||||
}
|
||||
|
||||
// shared instance
|
||||
+(BTstackManager *) sharedInstance;
|
||||
|
||||
// listeners
|
||||
-(void) addListener:(id<BTstackManagerListener>)listener;
|
||||
-(void) removeListener:(id<BTstackManagerListener>)listener;
|
||||
|
||||
// Activation
|
||||
-(BTstackError) activate;
|
||||
-(BTstackError) deactivate;
|
||||
-(BOOL) isActivating;
|
||||
-(BOOL) isActive;
|
||||
|
||||
// Discovery
|
||||
-(BTstackError) startDiscovery;
|
||||
-(BTstackError) stopDiscovery;
|
||||
-(int) numberOfDevicesFound;
|
||||
-(BTDevice*) deviceAtIndex:(int)index;
|
||||
-(BOOL) isDiscoveryActive;
|
||||
|
||||
// Link Key Management
|
||||
-(void) dropLinkKeyForAddress:(bd_addr_t*) address;
|
||||
|
||||
// Connections
|
||||
-(BTstackError) createL2CAPChannelAtAddress:(bd_addr_t*) address withPSM:(uint16_t)psm authenticated:(BOOL)authentication;
|
||||
-(BTstackError) closeL2CAPChannelWithID:(uint16_t) channelID;
|
||||
-(BTstackError) sendL2CAPPacketForChannelID:(uint16_t)channelID;
|
||||
|
||||
-(BTstackError) createRFCOMMConnectionAtAddress:(bd_addr_t*) address withChannel:(uint16_t)channel authenticated:(BOOL)authentication;
|
||||
-(BTstackError) closeRFCOMMConnectionWithID:(uint16_t) connectionID;
|
||||
-(BTstackError) sendRFCOMMPacketForChannelID:(uint16_t)connectionID;
|
||||
|
||||
|
||||
// TODO add l2cap and rfcomm incoming commands
|
||||
@property (nonatomic, assign) NSObject<BTstackManagerDelegate>* delegate;
|
||||
@property (nonatomic, retain) NSMutableArray *discoveredDevices;
|
||||
@property (nonatomic, retain) NSMutableSet *listeners;
|
||||
@end
|
||||
|
||||
|
||||
@protocol BTstackManagerDelegate
|
||||
@optional
|
||||
|
||||
// Activation callbacks
|
||||
-(BOOL) disableSystemBluetoothBTstackManager:(BTstackManager*) manager; // default: YES
|
||||
|
||||
// Connection events
|
||||
-(NSString*) btstackManager:(BTstackManager*) manager pinForAddress:(bd_addr_t)addr; // default: "0000"
|
||||
|
||||
// direct access
|
||||
-(void) btstackManager:(BTstackManager*) manager
|
||||
handlePacketWithType:(uint8_t) packet_type
|
||||
forChannel:(uint16_t) channel
|
||||
andData:(uint8_t *)packet
|
||||
withLen:(uint16_t) size;
|
||||
@end
|
||||
|
||||
|
||||
@protocol BTstackManagerListener
|
||||
@optional
|
||||
|
||||
// Activation events
|
||||
-(void) activatedBTstackManager:(BTstackManager*) manager;
|
||||
-(void) btstackManager:(BTstackManager*)manager activationFailed:(BTstackError)error;
|
||||
-(void) deactivatedBTstackManager:(BTstackManager*) manager;
|
||||
|
||||
// Power management events
|
||||
-(void) sleepModeEnterBTstackManager:(BTstackManager*) manager;
|
||||
-(void) sleepModeExtitBTstackManager:(BTstackManager*) manager;
|
||||
|
||||
// Discovery events: general
|
||||
-(void) btstackManager:(BTstackManager*)manager deviceInfo:(BTDevice*)device;
|
||||
-(void) btstackManager:(BTstackManager*)manager discoveryQueryRemoteName:(int)deviceIndex;
|
||||
-(void) discoveryStoppedBTstackManager:(BTstackManager*) manager;
|
||||
-(void) discoveryInquiryBTstackManager:(BTstackManager*) manager;
|
||||
|
||||
// Connection
|
||||
-(void) l2capChannelCreatedAtAddress:(bd_addr_t)addr withPSM:(uint16_t)psm asID:(uint16_t)channelID;
|
||||
-(void) l2capChannelCreateFailedAtAddress:(bd_addr_t)addr withPSM:(uint16_t)psm error:(BTstackError)error;
|
||||
-(void) l2capChannelClosedForChannelID:(uint16_t)channelID;
|
||||
-(void) l2capDataReceivedForChannelID:(uint16_t)channelID withData:(uint8_t *)packet ofLen:(uint16_t)size;
|
||||
|
||||
-(void) rfcommConnectionCreatedAtAddress:(bd_addr_t)addr forChannel:(uint16_t)channel asID:(uint16_t)connectionID;
|
||||
-(void) rfcommConnectionCreateFailedAtAddress:(bd_addr_t)addr forChannel:(uint16_t)channel error:(BTstackError)error;
|
||||
-(void) rfcommConnectionClosedForConnectionID:(uint16_t)connectionID;
|
||||
-(void) rfcommDataReceivedForConnectionID:(uint16_t)connectionID withData:(uint8_t *)packet ofLen:(uint16_t)size;
|
||||
|
||||
// TODO add l2cap and rfcomm incoming events
|
||||
@end
|
590
ios/RetroArch/input/BTStack/BTstackManager.m
Normal file
590
ios/RetroArch/input/BTStack/BTstackManager.m
Normal file
@ -0,0 +1,590 @@
|
||||
/*
|
||||
* Copyright (C) 2009 by Matthias Ringwald
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holders nor the names of
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY MATTHIAS RINGWALD AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
|
||||
* RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#import "BTstackManager.h"
|
||||
|
||||
#import "btstack/btstack.h"
|
||||
#import "BTDevice.h"
|
||||
|
||||
#define INQUIRY_INTERVAL 3
|
||||
|
||||
static BTstackManager * btstackManager = nil;
|
||||
|
||||
@interface BTstackManager (privat)
|
||||
- (void)handlePacketWithType:(uint8_t) packet_type forChannel:(uint16_t) channel andData:(uint8_t *)packet withLen:(uint16_t) size;
|
||||
@end
|
||||
|
||||
// needed for libBTstack
|
||||
static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
|
||||
[btstackManager handlePacketWithType:packet_type forChannel:channel andData:packet withLen:size];
|
||||
}
|
||||
|
||||
@implementation BTstackManager
|
||||
|
||||
@synthesize delegate = _delegate;
|
||||
@synthesize listeners;
|
||||
@synthesize discoveredDevices;
|
||||
|
||||
-(BTstackManager *) init {
|
||||
self = [super init];
|
||||
if (!self) return self;
|
||||
|
||||
state = kDeactivated;
|
||||
discoveryState = kInactive;
|
||||
connectedToDaemon = NO;
|
||||
|
||||
// device discovery
|
||||
[self setDiscoveredDevices: [[NSMutableArray alloc] init]];
|
||||
|
||||
// delegate and listener
|
||||
_delegate = nil;
|
||||
[self setListeners:[[NSMutableSet alloc] init]];
|
||||
|
||||
// Use Cocoa run loop
|
||||
run_loop_init(RUN_LOOP_COCOA);
|
||||
|
||||
// our packet handler
|
||||
bt_register_packet_handler(packet_handler);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
+(BTstackManager *) sharedInstance {
|
||||
if (!btstackManager) {
|
||||
btstackManager = [[BTstackManager alloc] init];
|
||||
}
|
||||
return btstackManager;
|
||||
}
|
||||
|
||||
// listeners
|
||||
-(void) addListener:(id<BTstackManagerListener>)listener{
|
||||
[listeners addObject:listener];
|
||||
}
|
||||
|
||||
-(void) removeListener:(id<BTstackManagerListener>)listener{
|
||||
[listeners removeObject:listener];
|
||||
}
|
||||
|
||||
// send events
|
||||
-(void) sendActivated {
|
||||
for (NSObject<BTstackManagerListener>* listener in listeners) {
|
||||
if ([listener respondsToSelector:@selector(activatedBTstackManager:)]){
|
||||
[listener activatedBTstackManager:self];
|
||||
}
|
||||
}
|
||||
}
|
||||
-(void) sendActivationFailed:(BTstackError)error {
|
||||
for (NSObject<BTstackManagerListener>* listener in listeners) {
|
||||
if ([listener respondsToSelector:@selector(btstackManager:activationFailed:)]){
|
||||
[listener btstackManager:self activationFailed:error];
|
||||
}
|
||||
}
|
||||
}
|
||||
-(void) sendDeactivated {
|
||||
for (NSObject<BTstackManagerListener>* listener in listeners) {
|
||||
if ([listener respondsToSelector:@selector(deactivatedBTstackManager:)]){
|
||||
[listener deactivatedBTstackManager:self];
|
||||
}
|
||||
}
|
||||
}
|
||||
-(void) sendSleepEnter {
|
||||
for (NSObject<BTstackManagerListener>* listener in listeners) {
|
||||
if ([listener respondsToSelector:@selector(sleepModeEnterBTstackManager:)]){
|
||||
[listener sleepModeEnterBTstackManager:self];
|
||||
}
|
||||
}
|
||||
}
|
||||
-(void) sendSleepExit {
|
||||
for (NSObject<BTstackManagerListener>* listener in listeners) {
|
||||
if ([listener respondsToSelector:@selector(sleepModeExtitBTstackManager:)]){
|
||||
[listener sleepModeExtitBTstackManager:self];
|
||||
}
|
||||
}
|
||||
}
|
||||
-(void) sendDiscoveryStoppedEvent {
|
||||
for (NSObject<BTstackManagerListener>* listener in listeners) {
|
||||
if ([listener respondsToSelector:@selector(discoveryStoppedBTstackManager:)]){
|
||||
[listener discoveryStoppedBTstackManager:self];
|
||||
}
|
||||
}
|
||||
}
|
||||
-(void) sendDiscoveryInquiry{
|
||||
for (NSObject<BTstackManagerListener>* listener in listeners) {
|
||||
if ([listener respondsToSelector:@selector(discoveryInquiryBTstackManager:)]){
|
||||
[listener discoveryInquiryBTstackManager:self];
|
||||
}
|
||||
}
|
||||
}
|
||||
-(void) sendDiscoveryQueryRemoteName:(int)index {
|
||||
for (NSObject<BTstackManagerListener>* listener in listeners) {
|
||||
if ([listener respondsToSelector:@selector(btstackManager:discoveryQueryRemoteName:)]){
|
||||
[listener btstackManager:self discoveryQueryRemoteName:index];
|
||||
}
|
||||
}
|
||||
}
|
||||
-(void) sendDeviceInfo:(BTDevice*) device{
|
||||
for (NSObject<BTstackManagerListener>* listener in listeners) {
|
||||
if ([listener respondsToSelector:@selector(btstackManager:deviceInfo:)]){
|
||||
[listener btstackManager:self deviceInfo:device];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Activation
|
||||
-(BTstackError) activate {
|
||||
|
||||
BTstackError err = 0;
|
||||
if (!connectedToDaemon) {
|
||||
err = bt_open();
|
||||
if (err) return BTSTACK_CONNECTION_TO_BTDAEMON_FAILED;
|
||||
}
|
||||
connectedToDaemon = YES;
|
||||
|
||||
// check system BT
|
||||
state = kW4SysBTState;
|
||||
bt_send_cmd(&btstack_get_system_bluetooth_enabled);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
-(BTstackError) deactivate {
|
||||
if (!connectedToDaemon) return BTSTACK_CONNECTION_TO_BTDAEMON_FAILED;
|
||||
state = kW4Deactivated;
|
||||
bt_send_cmd(&btstack_set_power_mode, HCI_POWER_OFF);
|
||||
return 0;
|
||||
}
|
||||
|
||||
-(BOOL) isActive {
|
||||
return state == kActivated;
|
||||
}
|
||||
|
||||
-(BOOL) isActivating {
|
||||
switch (state){
|
||||
case kW4SysBTState:
|
||||
case kW4SysBTDisabled:
|
||||
case kW4Activated:
|
||||
return YES;
|
||||
default:
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
-(BOOL) isDiscoveryActive {
|
||||
return state == kActivated && (discoveryState != kInactive);
|
||||
}
|
||||
|
||||
// Discovery
|
||||
-(BTstackError) startDiscovery {
|
||||
if (state < kActivated) return BTSTACK_NOT_ACTIVATED;
|
||||
|
||||
discoveryState = kW4InquiryMode;
|
||||
bt_send_cmd(&hci_write_inquiry_mode, 0x01); // with RSSI
|
||||
return 0;
|
||||
};
|
||||
|
||||
-(BTstackError) stopDiscovery{
|
||||
if (state < kActivated) return BTSTACK_NOT_ACTIVATED;
|
||||
switch (discoveryState){
|
||||
case kInactive:
|
||||
[self sendDiscoveryStoppedEvent];
|
||||
break;
|
||||
case kW4InquiryMode:
|
||||
discoveryState = kW4InquiryModeBeforeStop;
|
||||
break;
|
||||
case kInquiry:
|
||||
discoveryState = kW4InquiryStop;
|
||||
bt_send_cmd(&hci_inquiry_cancel);
|
||||
break;
|
||||
case kRemoteName: {
|
||||
discoveryState = kW4RemoteNameBeforeStop;
|
||||
BTDevice *device = [discoveredDevices objectAtIndex:discoveryDeviceIndex];
|
||||
bt_send_cmd(&hci_remote_name_request_cancel, [device address]);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
NSLog(@"[BTstackManager stopDiscovery] invalid discoveryState %u", discoveryState);
|
||||
[self sendDiscoveryStoppedEvent];
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
|
||||
-(int) numberOfDevicesFound{
|
||||
return [discoveredDevices count];
|
||||
};
|
||||
|
||||
-(BTDevice*) deviceAtIndex:(int)index{
|
||||
return (BTDevice*) [discoveredDevices objectAtIndex:index];
|
||||
};
|
||||
|
||||
-(BTDevice*) deviceForAddress:(bd_addr_t*) address{
|
||||
for (BTDevice *device in discoveredDevices){
|
||||
// NSLog(@"compare %@ to %@", [BTDevice stringForAddress:address], [device addressString]);
|
||||
if ( BD_ADDR_CMP(address, [device address]) == 0){
|
||||
return device;
|
||||
}
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (void) activationHandleEvent:(uint8_t *)packet withLen:(uint16_t) size {
|
||||
switch (state) {
|
||||
|
||||
case kW4SysBTState:
|
||||
case kW4SysBTDisabled:
|
||||
|
||||
// BTSTACK_EVENT_SYSTEM_BLUETOOTH_ENABLED
|
||||
if ( packet[0] == BTSTACK_EVENT_SYSTEM_BLUETOOTH_ENABLED){
|
||||
if (packet[2]){
|
||||
// system bt on - first time try to disable it
|
||||
if ( state == kW4SysBTState) {
|
||||
if (_delegate == nil
|
||||
|| ![_delegate respondsToSelector:@selector(disableSystemBluetoothBTstackManager:)]
|
||||
|| [_delegate disableSystemBluetoothBTstackManager:self]){
|
||||
state = kW4SysBTDisabled;
|
||||
bt_send_cmd(&btstack_set_system_bluetooth_enabled, 0);
|
||||
} else {
|
||||
state = kDeactivated;
|
||||
[self sendActivationFailed:BTSTACK_ACTIVATION_FAILED_SYSTEM_BLUETOOTH];
|
||||
}
|
||||
} else {
|
||||
state = kDeactivated;
|
||||
[self sendActivationFailed:BTSTACK_ACTIVATION_FAILED_UNKNOWN];
|
||||
}
|
||||
} else {
|
||||
state = kW4Activated;
|
||||
bt_send_cmd(&btstack_set_power_mode, HCI_POWER_ON);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case kW4Activated:
|
||||
switch (packet[0]){
|
||||
case BTSTACK_EVENT_STATE:
|
||||
if (packet[2] == HCI_STATE_WORKING) {
|
||||
state = kActivated;
|
||||
[self sendActivated];
|
||||
}
|
||||
break;
|
||||
case BTSTACK_EVENT_POWERON_FAILED:
|
||||
state = kDeactivated;
|
||||
[self sendActivationFailed:BTSTACK_ACTIVATION_POWERON_FAILED];
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case kW4Deactivated:
|
||||
if (packet[0] != BTSTACK_EVENT_STATE && packet[2] == HCI_STATE_OFF){
|
||||
state = kDeactivated;
|
||||
[self sendDeactivated];
|
||||
}
|
||||
break;
|
||||
|
||||
case kActivated:
|
||||
if (packet[0] != BTSTACK_EVENT_STATE && packet[2] == HCI_STATE_FALLING_ASLEEP){
|
||||
state = kSleeping;
|
||||
[self sendSleepEnter];
|
||||
}
|
||||
break;
|
||||
|
||||
case kSleeping:
|
||||
if (packet[0] != BTSTACK_EVENT_STATE && packet[2] == HCI_STATE_WORKING){
|
||||
state = kActivated;
|
||||
[self sendSleepExit];
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
-(void) discoveryRemoteName{
|
||||
BOOL found = NO;
|
||||
while ( discoveryDeviceIndex < [discoveredDevices count]){
|
||||
BTDevice *device = [discoveredDevices objectAtIndex:discoveryDeviceIndex];
|
||||
if (device.name) {
|
||||
discoveryDeviceIndex ++;
|
||||
continue;
|
||||
}
|
||||
bt_send_cmd(&hci_remote_name_request, [device address], device.pageScanRepetitionMode,
|
||||
0, device.clockOffset | 0x8000);
|
||||
[self sendDiscoveryQueryRemoteName:discoveryDeviceIndex];
|
||||
found = YES;
|
||||
break;
|
||||
}
|
||||
if (!found) {
|
||||
// printf("Queried all devices, restart.\n");
|
||||
discoveryState = kInquiry;
|
||||
bt_send_cmd(&hci_inquiry, HCI_INQUIRY_LAP, INQUIRY_INTERVAL, 0);
|
||||
[self sendDiscoveryInquiry];
|
||||
}
|
||||
}
|
||||
|
||||
- (NSString *) createRemoteNameFromRemoteNameEvent:(uint8_t *) packet {
|
||||
// get lenght: first null byte or max 248 chars
|
||||
int nameLen = 0;
|
||||
while (nameLen < 248 && packet[9+nameLen]) nameLen++;
|
||||
// Bluetooth specification mandates UTF-8 encoding...
|
||||
NSString *name = [[NSString alloc] initWithBytes:&packet[9] length:nameLen encoding:NSUTF8StringEncoding];
|
||||
// but fallback to latin-1 for non-standard products like old Microsoft Wireless Presenter
|
||||
if (!name){
|
||||
name = [[NSString alloc] initWithBytes:&packet[9] length:nameLen encoding:NSISOLatin1StringEncoding];
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
- (void) handleRemoteNameCached: (uint8_t *) packet {
|
||||
bd_addr_t addr;
|
||||
bt_flip_addr(addr, &packet[3]);
|
||||
// NSLog(@"Get remote name done for %@", [BTDevice stringForAddress:&addr]);
|
||||
BTDevice* device = [self deviceForAddress:&addr];
|
||||
if (!device) return;
|
||||
|
||||
[device setName:[self createRemoteNameFromRemoteNameEvent:packet]];
|
||||
[self sendDeviceInfo:device];
|
||||
}
|
||||
|
||||
- (void) handleRemoteName: (uint8_t *) packet {
|
||||
bd_addr_t addr;
|
||||
bt_flip_addr(addr, &packet[3]);
|
||||
// NSLog(@"Get remote name done for %@", [BTDevice stringForAddress:&addr]);
|
||||
BTDevice* device = [self deviceForAddress:&addr];
|
||||
if (!device) return;
|
||||
|
||||
[device setName:[self createRemoteNameFromRemoteNameEvent:packet]];
|
||||
[self sendDeviceInfo:device];
|
||||
|
||||
discoveryDeviceIndex++;
|
||||
[self discoveryRemoteName];
|
||||
}
|
||||
|
||||
-(void) discoveryHandleEvent:(uint8_t *)packet withLen:(uint16_t) size {
|
||||
bd_addr_t addr;
|
||||
int i;
|
||||
int numResponses;
|
||||
|
||||
switch (discoveryState) {
|
||||
|
||||
case kInactive:
|
||||
break;
|
||||
|
||||
case kW4InquiryMode:
|
||||
if (packet[0] == HCI_EVENT_COMMAND_COMPLETE && COMMAND_COMPLETE_EVENT(packet, hci_write_inquiry_mode) ) {
|
||||
discoveryState = kInquiry;
|
||||
bt_send_cmd(&hci_inquiry, HCI_INQUIRY_LAP, INQUIRY_INTERVAL, 0);
|
||||
[self sendDiscoveryInquiry];
|
||||
}
|
||||
break;
|
||||
|
||||
case kInquiry:
|
||||
|
||||
switch (packet[0]){
|
||||
case HCI_EVENT_INQUIRY_RESULT:
|
||||
numResponses = packet[2];
|
||||
for (i=0; i<numResponses ; i++){
|
||||
bt_flip_addr(addr, &packet[3+i*6]);
|
||||
// NSLog(@"found %@", [BTDevice stringForAddress:&addr]);
|
||||
BTDevice* device = [self deviceForAddress:&addr];
|
||||
if (!device) {
|
||||
device = [[BTDevice alloc] init];
|
||||
[discoveredDevices addObject:device];
|
||||
[device setAddress:&addr];
|
||||
}
|
||||
// update
|
||||
device.pageScanRepetitionMode = packet [3 + numResponses*(6) + i*1];
|
||||
device.classOfDevice = READ_BT_24(packet, 3 + numResponses*(6+1+1+1) + i*3);
|
||||
device.clockOffset = READ_BT_16(packet, 3 + numResponses*(6+1+1+1+3) + i*2) & 0x7fff;
|
||||
device.rssi = 0;
|
||||
[self sendDeviceInfo:device];
|
||||
}
|
||||
break;
|
||||
|
||||
case HCI_EVENT_INQUIRY_RESULT_WITH_RSSI:
|
||||
numResponses = packet[2];
|
||||
for (i=0; i<numResponses ;i++){
|
||||
bt_flip_addr(addr, &packet[3+i*6]);
|
||||
// NSLog(@"found %@", [BTDevice stringForAddress:&addr]);
|
||||
BTDevice* device = [self deviceForAddress:&addr];
|
||||
if (!device) {
|
||||
device = [[BTDevice alloc] init];
|
||||
[discoveredDevices addObject:device];
|
||||
[device setAddress:&addr];
|
||||
}
|
||||
device.pageScanRepetitionMode = packet [3 + numResponses*(6) + i*1];
|
||||
device.classOfDevice = READ_BT_24(packet, 3 + numResponses*(6+1+1) + i*3);
|
||||
device.clockOffset = READ_BT_16(packet, 3 + numResponses*(6+1+1+3) + i*2) & 0x7fff;
|
||||
device.rssi = packet [3 + numResponses*(6+1+1+3+2) + i*1];
|
||||
[self sendDeviceInfo:device];
|
||||
}
|
||||
break;
|
||||
|
||||
case BTSTACK_EVENT_REMOTE_NAME_CACHED:
|
||||
[self handleRemoteNameCached:packet];
|
||||
break;
|
||||
|
||||
case HCI_EVENT_INQUIRY_COMPLETE:
|
||||
// printf("Inquiry scan done.\n");
|
||||
discoveryState = kRemoteName;
|
||||
discoveryDeviceIndex = 0;
|
||||
[self discoveryRemoteName];
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case kRemoteName:
|
||||
if (packet[0] == HCI_EVENT_REMOTE_NAME_REQUEST_COMPLETE){
|
||||
[self handleRemoteName:packet];
|
||||
}
|
||||
break;
|
||||
|
||||
case kW4InquiryModeBeforeStop:
|
||||
if (packet[0] == HCI_EVENT_COMMAND_COMPLETE && COMMAND_COMPLETE_EVENT(packet, hci_write_inquiry_mode) ) {
|
||||
discoveryState = kInactive;
|
||||
[self sendDiscoveryStoppedEvent];
|
||||
}
|
||||
break;
|
||||
|
||||
case kW4InquiryStop:
|
||||
if (packet[0] == HCI_EVENT_INQUIRY_COMPLETE
|
||||
|| COMMAND_COMPLETE_EVENT(packet, hci_inquiry_cancel)) {
|
||||
discoveryState = kInactive;
|
||||
[self sendDiscoveryStoppedEvent];
|
||||
}
|
||||
break;
|
||||
|
||||
case kW4RemoteNameBeforeStop:
|
||||
if (packet[0] == HCI_EVENT_REMOTE_NAME_REQUEST_COMPLETE
|
||||
|| COMMAND_COMPLETE_EVENT(packet, hci_remote_name_request_cancel)){
|
||||
discoveryState = kInactive;
|
||||
[self sendDiscoveryStoppedEvent];
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
-(void) dropLinkKeyForAddress:(bd_addr_t*) address {
|
||||
bt_send_cmd(&hci_delete_stored_link_key, address, 0);
|
||||
// NSLog(@"Removing link key for %@", devAddress);
|
||||
}
|
||||
|
||||
-(void) handlePacketWithType:(uint8_t)packet_type forChannel:(uint16_t)channel andData:(uint8_t *)packet withLen:(uint16_t) size {
|
||||
switch (state) {
|
||||
|
||||
case kDeactivated:
|
||||
break;
|
||||
|
||||
// Activation
|
||||
case kW4SysBTState:
|
||||
case kW4SysBTDisabled:
|
||||
case kW4Activated:
|
||||
case kW4Deactivated:
|
||||
case kSleeping:
|
||||
if (packet_type != HCI_EVENT_PACKET) break;
|
||||
[self activationHandleEvent:packet withLen:size];
|
||||
break;
|
||||
|
||||
// Pairing + Discovery
|
||||
case kActivated:
|
||||
if (packet_type != HCI_EVENT_PACKET) break;
|
||||
switch (packet[0]){
|
||||
case BTSTACK_EVENT_STATE:
|
||||
[self activationHandleEvent:packet withLen:size];
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
[self discoveryHandleEvent:packet withLen:size];
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if ([_delegate respondsToSelector:@selector(btstackManager:handlePacketWithType:forChannel:andData:withLen:)]){
|
||||
[_delegate btstackManager:self handlePacketWithType:packet_type forChannel:channel andData:packet withLen:size];
|
||||
}
|
||||
}
|
||||
|
||||
// Connections
|
||||
-(BTstackError) createL2CAPChannelAtAddress:(bd_addr_t*) address withPSM:(uint16_t)psm authenticated:(BOOL)authentication {
|
||||
if (state < kActivated) return BTSTACK_NOT_ACTIVATED;
|
||||
if (state != kActivated) return BTSTACK_BUSY;
|
||||
#if 0
|
||||
// ...f (state
|
||||
// store params
|
||||
connType = 0;
|
||||
BD_ADDR_COPY(&connAddr, address);
|
||||
connPSM = psm;
|
||||
connAuth = authentication;
|
||||
|
||||
// send write authentication enabled
|
||||
bt_send_cmd(&hci_write_authentication_enable, authentication);
|
||||
state = kW4AuthenticationEnableCommand;
|
||||
#endif
|
||||
return 0;
|
||||
};
|
||||
-(BTstackError) sendL2CAPPacketForChannelID:(uint16_t)channelID {
|
||||
if (state < kActivated) return BTSTACK_NOT_ACTIVATED;
|
||||
return 0;
|
||||
};
|
||||
-(BTstackError) closeL2CAPChannelWithID:(uint16_t) channelID {
|
||||
if (state < kActivated) return BTSTACK_NOT_ACTIVATED;
|
||||
return 0;
|
||||
};
|
||||
|
||||
-(BTstackError) createRFCOMMConnectionAtAddress:(bd_addr_t*) address withChannel:(uint16_t)channel authenticated:(BOOL)authentication {
|
||||
if (state < kActivated) return BTSTACK_NOT_ACTIVATED;
|
||||
if (state != kActivated) return BTSTACK_BUSY;
|
||||
#if 0
|
||||
// store params
|
||||
connType = 1;
|
||||
BD_ADDR_COPY(&connAddr, address);
|
||||
connChan = channel;
|
||||
connAuth = authentication;
|
||||
#endif
|
||||
return 0;
|
||||
};
|
||||
-(BTstackError) sendRFCOMMPacketForChannelID:(uint16_t)connectionID {
|
||||
if (state < kActivated) return BTSTACK_NOT_ACTIVATED;
|
||||
return 0;
|
||||
};
|
||||
-(BTstackError) closeRFCOMMConnectionWithID:(uint16_t) connectionID {
|
||||
if (state <kActivated) return BTSTACK_NOT_ACTIVATED;
|
||||
return 0;
|
||||
};
|
||||
|
||||
@end
|
41
ios/RetroArch/input/BTStack/WiiMoteHelper.h
Normal file
41
ios/RetroArch/input/BTStack/WiiMoteHelper.h
Normal file
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* This file is part of MAME4iOS.
|
||||
*
|
||||
* Copyright (C) 2012 David Valdeita (Seleuco)
|
||||
*
|
||||
* This program 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 Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* In addition, as a special exception, Seleuco
|
||||
* gives permission to link the code of this program with
|
||||
* the MAME library (or with modified versions of MAME that use the
|
||||
* same license as MAME), and distribute linked combinations including
|
||||
* the two. You must obey the GNU General Public License in all
|
||||
* respects for all of the code used other than MAME. If you modify
|
||||
* this file, you may extend this exception to your version of the
|
||||
* file, but you are not obligated to do so. If you do not wish to
|
||||
* do so, delete this exception statement from your version.
|
||||
*/
|
||||
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
#import "BTstackManager.h"
|
||||
|
||||
@interface WiiMoteHelper : NSObject<BTstackManagerDelegate, BTstackManagerListener>
|
||||
+ (void)startBluetooth;
|
||||
+ (BOOL)isBluetoothRunning;
|
||||
+ (void)stopBluetooth;
|
||||
@end
|
||||
|
267
ios/RetroArch/input/BTStack/WiiMoteHelper.m
Normal file
267
ios/RetroArch/input/BTStack/WiiMoteHelper.m
Normal file
@ -0,0 +1,267 @@
|
||||
/*
|
||||
* This file is part of MAME4iOS.
|
||||
*
|
||||
* Copyright (C) 2012 David Valdeita (Seleuco)
|
||||
*
|
||||
* This program 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 Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* In addition, as a special exception, Seleuco
|
||||
* gives permission to link the code of this program with
|
||||
* the MAME library (or with modified versions of MAME that use the
|
||||
* same license as MAME), and distribute linked combinations including
|
||||
* the two. You must obey the GNU General Public License in all
|
||||
* respects for all of the code used other than MAME. If you modify
|
||||
* this file, you may extend this exception to your version of the
|
||||
* file, but you are not obligated to do so. If you do not wish to
|
||||
* do so, delete this exception statement from your version.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "wiimote.h"
|
||||
|
||||
#import "WiiMoteHelper.h"
|
||||
|
||||
#import "BTDevice.h"
|
||||
#import "BTstackManager.h"
|
||||
|
||||
static WiiMoteHelper* instance;
|
||||
static BTDevice *device;
|
||||
static bool btOK;
|
||||
|
||||
@implementation WiiMoteHelper
|
||||
+ (void)startBluetooth
|
||||
{
|
||||
instance = instance ? instance : [WiiMoteHelper new];
|
||||
|
||||
if (!btOK)
|
||||
{
|
||||
BTstackManager* bt = [BTstackManager sharedInstance];
|
||||
[bt setDelegate:instance];
|
||||
[bt addListener:instance];
|
||||
|
||||
btOK = [bt activate] == 0;
|
||||
}
|
||||
}
|
||||
|
||||
+ (BOOL)isBluetoothRunning
|
||||
{
|
||||
return btOK;
|
||||
}
|
||||
|
||||
+ (void)stopBluetooth
|
||||
{
|
||||
myosd_num_of_joys = 0;
|
||||
|
||||
if (btOK)
|
||||
{
|
||||
BTstackManager* bt = [BTstackManager sharedInstance];
|
||||
|
||||
[bt deactivate];
|
||||
[bt setDelegate:nil];
|
||||
[bt removeListener:instance];
|
||||
btOK = false;
|
||||
}
|
||||
|
||||
instance = nil;
|
||||
}
|
||||
|
||||
// BTStackManagerListener
|
||||
-(void) activatedBTstackManager:(BTstackManager*) manager
|
||||
{
|
||||
[[BTstackManager sharedInstance] startDiscovery];
|
||||
}
|
||||
|
||||
-(void) btstackManager:(BTstackManager*)manager deviceInfo:(BTDevice*)newDevice
|
||||
{
|
||||
if ([newDevice name] && [[newDevice name] hasPrefix:@"Nintendo RVL-CNT-01"])
|
||||
{
|
||||
device = newDevice;
|
||||
[[BTstackManager sharedInstance] stopDiscovery];
|
||||
}
|
||||
}
|
||||
|
||||
-(void) discoveryStoppedBTstackManager:(BTstackManager*) manager
|
||||
{
|
||||
bt_send_cmd(&hci_write_authentication_enable, 0);
|
||||
}
|
||||
|
||||
// BTStackManagerDelegate
|
||||
-(void) btstackManager:(BTstackManager*) manager
|
||||
handlePacketWithType:(uint8_t)packet_type
|
||||
forChannel:(uint16_t)channel
|
||||
andData:(uint8_t*)packet
|
||||
withLen:(uint16_t)size
|
||||
{
|
||||
bd_addr_t event_addr;
|
||||
|
||||
switch (packet_type)
|
||||
{
|
||||
case L2CAP_DATA_PACKET://0x06
|
||||
{
|
||||
struct wiimote_t *wm = wiimote_get_by_source_cid(channel);
|
||||
|
||||
if (wm != NULL)
|
||||
{
|
||||
byte* msg = packet + 2;
|
||||
byte event = packet[1];
|
||||
|
||||
switch (event)
|
||||
{
|
||||
case WM_RPT_BTN:
|
||||
{
|
||||
wiimote_pressed_buttons(wm, msg);
|
||||
break;
|
||||
}
|
||||
|
||||
case WM_RPT_READ:
|
||||
{
|
||||
/* data read */
|
||||
wiimote_pressed_buttons(wm, msg);
|
||||
|
||||
byte len = ((msg[2] & 0xF0) >> 4) + 1;
|
||||
byte *data = (msg + 5);
|
||||
|
||||
if(wiimote_handshake(wm, WM_RPT_READ, data, len))
|
||||
{
|
||||
if (device != nil)
|
||||
{
|
||||
[device setConnectionState:kBluetoothConnectionConnected];
|
||||
device = nil;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
case WM_RPT_CTRL_STATUS:
|
||||
{
|
||||
wiimote_pressed_buttons(wm, msg);
|
||||
|
||||
//handshake stuff!
|
||||
if(wiimote_handshake(wm,WM_RPT_CTRL_STATUS,msg,-1))
|
||||
{
|
||||
[device setConnectionState:kBluetoothConnectionConnected];
|
||||
|
||||
if (device != nil)
|
||||
{
|
||||
[device setConnectionState:kBluetoothConnectionConnected];
|
||||
device = nil;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
case WM_RPT_BTN_EXP:
|
||||
{
|
||||
/* button - expansion */
|
||||
wiimote_pressed_buttons(wm, msg);
|
||||
wiimote_handle_expansion(wm, msg+2);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case WM_RPT_WRITE:
|
||||
{
|
||||
/* write feedback - safe to skip */
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
printf("Unknown event, can not handle it [Code 0x%x].", event);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case HCI_EVENT_PACKET://0x04
|
||||
{
|
||||
switch (packet[0])
|
||||
{
|
||||
case HCI_EVENT_COMMAND_COMPLETE:
|
||||
{
|
||||
if (COMMAND_COMPLETE_EVENT(packet, hci_write_authentication_enable))
|
||||
bt_send_cmd(&l2cap_create_channel, [device address], PSM_HID_INTERRUPT);
|
||||
break;
|
||||
}
|
||||
|
||||
case HCI_EVENT_PIN_CODE_REQUEST:
|
||||
{
|
||||
bt_flip_addr(event_addr, &packet[2]);
|
||||
if (BD_ADDR_CMP([device address], event_addr)) break;
|
||||
|
||||
// inform about pin code request
|
||||
NSLog(@"HCI_EVENT_PIN_CODE_REQUEST\n");
|
||||
bt_send_cmd(&hci_pin_code_request_reply, event_addr, 6, &packet[2]); // use inverse bd_addr as PIN
|
||||
break;
|
||||
}
|
||||
|
||||
case L2CAP_EVENT_CHANNEL_OPENED:
|
||||
{
|
||||
// data: event (8), len(8), status (8), address(48), handle (16), psm (16), local_cid(16), remote_cid (16)
|
||||
if (packet[2] == 0)
|
||||
{
|
||||
// inform about new l2cap connection
|
||||
bt_flip_addr(event_addr, &packet[3]);
|
||||
uint16_t psm = READ_BT_16(packet, 11);
|
||||
uint16_t source_cid = READ_BT_16(packet, 13);
|
||||
uint16_t wiiMoteConHandle = READ_BT_16(packet, 9);
|
||||
|
||||
if (psm == 0x13)
|
||||
{
|
||||
// interupt channel openedn succesfully, now open control channel, too.
|
||||
bt_send_cmd(&l2cap_create_channel, event_addr, 0x11);
|
||||
struct wiimote_t *wm = &joys[myosd_num_of_joys];
|
||||
memset(wm, 0, sizeof(struct wiimote_t));
|
||||
wm->unid = myosd_num_of_joys;
|
||||
wm->i_source_cid = source_cid;
|
||||
memcpy(&wm->addr,&event_addr,BD_ADDR_LEN);
|
||||
wm->exp.type = EXP_NONE;
|
||||
}
|
||||
else
|
||||
{
|
||||
//inicializamos el wiimote!
|
||||
struct wiimote_t *wm = &joys[myosd_num_of_joys];
|
||||
wm->wiiMoteConHandle = wiiMoteConHandle;
|
||||
wm->c_source_cid = source_cid;
|
||||
wm->state = WIIMOTE_STATE_CONNECTED;
|
||||
myosd_num_of_joys++;
|
||||
wiimote_handshake(wm,-1,NULL,-1);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case L2CAP_EVENT_CHANNEL_CLOSED:
|
||||
{
|
||||
// data: event (8), len(8), channel (16)
|
||||
uint16_t source_cid = READ_BT_16(packet, 2);
|
||||
|
||||
bd_addr_t addr;
|
||||
wiimote_remove(source_cid,&addr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@end
|
86
ios/RetroArch/input/BTStack/btstack/btstack.h
Normal file
86
ios/RetroArch/input/BTStack/btstack/btstack.h
Normal file
@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright (C) 2009 by Matthias Ringwald
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holders nor the names of
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY MATTHIAS RINGWALD AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
|
||||
* RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* btstack.h
|
||||
*
|
||||
* Created by Matthias Ringwald on 7/1/09.
|
||||
*
|
||||
* BTstack client API
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "hci_cmds.h"
|
||||
#include "run_loop.h"
|
||||
#include "utils.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#if defined __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Default TCP port for BTstack daemon
|
||||
#define BTSTACK_PORT 13333
|
||||
|
||||
// UNIX domain socket for BTstack */
|
||||
#define BTSTACK_UNIX "/tmp/BTstack"
|
||||
|
||||
// packet handler
|
||||
typedef void (*btstack_packet_handler_t) (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size);
|
||||
|
||||
// optional: if called before bt_open, TCP socket is used instead of local unix socket
|
||||
// note: address is not copied and must be valid during bt_open
|
||||
void bt_use_tcp(const char * address, uint16_t port);
|
||||
|
||||
// init BTstack library
|
||||
int bt_open(void);
|
||||
|
||||
// stop using BTstack library
|
||||
int bt_close(void);
|
||||
|
||||
// send hci cmd packet
|
||||
int bt_send_cmd(const hci_cmd_t *cmd, ...);
|
||||
|
||||
// register packet handler -- channel only valid for l2cap and rfcomm packets
|
||||
// @returns old packet handler
|
||||
btstack_packet_handler_t bt_register_packet_handler(btstack_packet_handler_t handler);
|
||||
|
||||
void bt_send_acl(uint8_t * data, uint16_t len);
|
||||
|
||||
void bt_send_l2cap(uint16_t local_cid, uint8_t *data, uint16_t len);
|
||||
void bt_send_rfcomm(uint16_t rfcom_cid, uint8_t *data, uint16_t len);
|
||||
|
||||
#if defined __cplusplus
|
||||
}
|
||||
#endif
|
380
ios/RetroArch/input/BTStack/btstack/hci_cmds.h
Normal file
380
ios/RetroArch/input/BTStack/btstack/hci_cmds.h
Normal file
@ -0,0 +1,380 @@
|
||||
/*
|
||||
* Copyright (C) 2009 by Matthias Ringwald
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holders nor the names of
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY MATTHIAS RINGWALD AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
|
||||
* RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* hci_cmds.h
|
||||
*
|
||||
* Created by Matthias Ringwald on 7/23/09.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#if defined __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* packet types - used in BTstack and over the H4 UART interface
|
||||
*/
|
||||
#define HCI_COMMAND_DATA_PACKET 0x01
|
||||
#define HCI_ACL_DATA_PACKET 0x02
|
||||
#define HCI_SCO_DATA_PACKET 0x03
|
||||
#define HCI_EVENT_PACKET 0x04
|
||||
|
||||
// extension for client/server communication
|
||||
#define DAEMON_EVENT_PACKET 0x05
|
||||
|
||||
// L2CAP data
|
||||
#define L2CAP_DATA_PACKET 0x06
|
||||
|
||||
// RFCOMM data
|
||||
#define RFCOMM_DATA_PACKET 0x07
|
||||
|
||||
// Attribute protocol data
|
||||
#define ATT_DATA_PACKET 0x08
|
||||
|
||||
// Security Manager protocol data
|
||||
#define SM_DATA_PACKET 0x09
|
||||
|
||||
// debug log messages
|
||||
#define LOG_MESSAGE_PACKET 0xfc
|
||||
|
||||
|
||||
// Fixed PSM numbers
|
||||
#define PSM_SDP 0x01
|
||||
#define PSM_RFCOMM 0x03
|
||||
#define PSM_HID_CONTROL 0x11
|
||||
#define PSM_HID_INTERRUPT 0x13
|
||||
|
||||
// Events from host controller to host
|
||||
#define HCI_EVENT_INQUIRY_COMPLETE 0x01
|
||||
#define HCI_EVENT_INQUIRY_RESULT 0x02
|
||||
#define HCI_EVENT_CONNECTION_COMPLETE 0x03
|
||||
#define HCI_EVENT_CONNECTION_REQUEST 0x04
|
||||
#define HCI_EVENT_DISCONNECTION_COMPLETE 0x05
|
||||
#define HCI_EVENT_AUTHENTICATION_COMPLETE_EVENT 0x06
|
||||
#define HCI_EVENT_REMOTE_NAME_REQUEST_COMPLETE 0x07
|
||||
#define HCI_EVENT_ENCRYPTION_CHANGE 0x08
|
||||
#define HCI_EVENT_CHANGE_CONNECTION_LINK_KEY_COMPLETE 0x09
|
||||
#define HCI_EVENT_MASTER_LINK_KEY_COMPLETE 0x0A
|
||||
#define HCI_EVENT_READ_REMOTE_SUPPORTED_FEATURES_COMPLETE 0x0B
|
||||
#define HCI_EVENT_READ_REMOTE_VERSION_INFORMATION_COMPLETE 0x0C
|
||||
#define HCI_EVENT_QOS_SETUP_COMPLETE 0x0D
|
||||
#define HCI_EVENT_COMMAND_COMPLETE 0x0E
|
||||
#define HCI_EVENT_COMMAND_STATUS 0x0F
|
||||
#define HCI_EVENT_HARDWARE_ERROR 0x10
|
||||
#define HCI_EVENT_FLUSH_OCCURED 0x11
|
||||
#define HCI_EVENT_ROLE_CHANGE 0x12
|
||||
#define HCI_EVENT_NUMBER_OF_COMPLETED_PACKETS 0x13
|
||||
#define HCI_EVENT_MODE_CHANGE_EVENT 0x14
|
||||
#define HCI_EVENT_RETURN_LINK_KEYS 0x15
|
||||
#define HCI_EVENT_PIN_CODE_REQUEST 0x16
|
||||
#define HCI_EVENT_LINK_KEY_REQUEST 0x17
|
||||
#define HCI_EVENT_LINK_KEY_NOTIFICATION 0x18
|
||||
#define HCI_EVENT_DATA_BUFFER_OVERFLOW 0x1A
|
||||
#define HCI_EVENT_MAX_SLOTS_CHANGED 0x1B
|
||||
#define HCI_EVENT_READ_CLOCK_OFFSET_COMPLETE 0x1C
|
||||
#define HCI_EVENT_PACKET_TYPE_CHANGED 0x1D
|
||||
#define HCI_EVENT_INQUIRY_RESULT_WITH_RSSI 0x22
|
||||
#define HCI_EVENT_EXTENDED_INQUIRY_RESPONSE 0x2F
|
||||
#define HCI_EVENT_LE_META 0x3E
|
||||
#define HCI_EVENT_VENDOR_SPECIFIC 0xFF
|
||||
|
||||
#define HCI_SUBEVENT_LE_CONNECTION_COMPLETE 0x01
|
||||
#define HCI_SUBEVENT_LE_ADVERTISING_REPORT 0x02
|
||||
#define HCI_SUBEVENT_LE_CONNECTION_UPDATE_COMPLETE 0x03
|
||||
#define HCI_SUBEVENT_LE_READ_REMOTE_USED_FEATURES_COMPLETE 0x04
|
||||
#define HCI_SUBEVENT_LE_LONG_TERM_KEY_REQUEST 0x05
|
||||
|
||||
// last used HCI_EVENT in 2.1 is 0x3d
|
||||
|
||||
// events 0x50-0x5f are used internally
|
||||
|
||||
// BTSTACK DAEMON EVENTS
|
||||
|
||||
// events from BTstack for application/client lib
|
||||
#define BTSTACK_EVENT_STATE 0x60
|
||||
|
||||
// data: event(8), len(8), nr hci connections
|
||||
#define BTSTACK_EVENT_NR_CONNECTIONS_CHANGED 0x61
|
||||
|
||||
// data: none
|
||||
#define BTSTACK_EVENT_POWERON_FAILED 0x62
|
||||
|
||||
// data: majot (8), minor (8), revision(16)
|
||||
#define BTSTACK_EVENT_VERSION 0x63
|
||||
|
||||
// data: system bluetooth on/off (bool)
|
||||
#define BTSTACK_EVENT_SYSTEM_BLUETOOTH_ENABLED 0x64
|
||||
|
||||
// data: event (8), len(8), status (8) == 0, address (48), name (1984 bits = 248 bytes)
|
||||
#define BTSTACK_EVENT_REMOTE_NAME_CACHED 0x65
|
||||
|
||||
// data: discoverable enabled (bool)
|
||||
#define BTSTACK_EVENT_DISCOVERABLE_ENABLED 0x66
|
||||
|
||||
// L2CAP EVENTS
|
||||
|
||||
// data: event (8), len(8), status (8), address(48), handle (16), psm (16), local_cid(16), remote_cid (16), local_mtu(16), remote_mtu(16)
|
||||
#define L2CAP_EVENT_CHANNEL_OPENED 0x70
|
||||
|
||||
// data: event (8), len(8), channel (16)
|
||||
#define L2CAP_EVENT_CHANNEL_CLOSED 0x71
|
||||
|
||||
// data: event (8), len(8), address(48), handle (16), psm (16), local_cid(16), remote_cid (16)
|
||||
#define L2CAP_EVENT_INCOMING_CONNECTION 0x72
|
||||
|
||||
// data: event(8), len(8), handle(16)
|
||||
#define L2CAP_EVENT_TIMEOUT_CHECK 0x73
|
||||
|
||||
// data: event(8), len(8), local_cid(16), credits(8)
|
||||
#define L2CAP_EVENT_CREDITS 0x74
|
||||
|
||||
// data: event(8), len(8), status (8), psm (16)
|
||||
#define L2CAP_EVENT_SERVICE_REGISTERED 0x75
|
||||
|
||||
|
||||
// RFCOMM EVENTS
|
||||
|
||||
// data: event(8), len(8), status (8), address (48), handle (16), server channel(8), rfcomm_cid(16), max frame size(16)
|
||||
#define RFCOMM_EVENT_OPEN_CHANNEL_COMPLETE 0x80
|
||||
|
||||
// data: event(8), len(8), rfcomm_cid(16)
|
||||
#define RFCOMM_EVENT_CHANNEL_CLOSED 0x81
|
||||
|
||||
// data: event (8), len(8), address(48), channel (8), rfcomm_cid (16)
|
||||
#define RFCOMM_EVENT_INCOMING_CONNECTION 0x82
|
||||
|
||||
// data: event (8), len(8), rfcommid (16), ...
|
||||
#define RFCOMM_EVENT_REMOTE_LINE_STATUS 0x83
|
||||
|
||||
// data: event(8), len(8), rfcomm_cid(16), credits(8)
|
||||
#define RFCOMM_EVENT_CREDITS 0x84
|
||||
|
||||
// data: event(8), len(8), status (8), rfcomm server channel id (8)
|
||||
#define RFCOMM_EVENT_SERVICE_REGISTERED 0x85
|
||||
|
||||
// data: event(8), len(8), status (8), rfcomm server channel id (8)
|
||||
#define RFCOMM_EVENT_PERSISTENT_CHANNEL 0x86
|
||||
|
||||
|
||||
// data: event(8), len(8), status(8), service_record_handle(32)
|
||||
#define SDP_SERVICE_REGISTERED 0x90
|
||||
|
||||
|
||||
// last error code in 2.1 is 0x38 - we start with 0x50 for BTstack errors
|
||||
|
||||
#define BTSTACK_CONNECTION_TO_BTDAEMON_FAILED 0x50
|
||||
#define BTSTACK_ACTIVATION_FAILED_SYSTEM_BLUETOOTH 0x51
|
||||
#define BTSTACK_ACTIVATION_POWERON_FAILED 0x52
|
||||
#define BTSTACK_ACTIVATION_FAILED_UNKNOWN 0x53
|
||||
#define BTSTACK_NOT_ACTIVATED 0x54
|
||||
#define BTSTACK_BUSY 0x55
|
||||
#define BTSTACK_MEMORY_ALLOC_FAILED 0x56
|
||||
#define BTSTACK_ACL_BUFFERS_FULL 0x57
|
||||
|
||||
// l2cap errors - enumeration by the command that created them
|
||||
#define L2CAP_COMMAND_REJECT_REASON_COMMAND_NOT_UNDERSTOOD 0x60
|
||||
#define L2CAP_COMMAND_REJECT_REASON_SIGNALING_MTU_EXCEEDED 0x61
|
||||
#define L2CAP_COMMAND_REJECT_REASON_INVALID_CID_IN_REQUEST 0x62
|
||||
|
||||
#define L2CAP_CONNECTION_RESPONSE_RESULT_SUCCESSFUL 0x63
|
||||
#define L2CAP_CONNECTION_RESPONSE_RESULT_PENDING 0x64
|
||||
#define L2CAP_CONNECTION_RESPONSE_RESULT_REFUSED_PSM 0x65
|
||||
#define L2CAP_CONNECTION_RESPONSE_RESULT_REFUSED_SECURITY 0x66
|
||||
#define L2CAP_CONNECTION_RESPONSE_RESULT_REFUSED_RESOURCES 0x65
|
||||
|
||||
#define L2CAP_CONFIG_RESPONSE_RESULT_SUCCESSFUL 0x66
|
||||
#define L2CAP_CONFIG_RESPONSE_RESULT_UNACCEPTABLE_PARAMS 0x67
|
||||
#define L2CAP_CONFIG_RESPONSE_RESULT_REJECTED 0x68
|
||||
#define L2CAP_CONFIG_RESPONSE_RESULT_UNKNOWN_OPTIONS 0x69
|
||||
#define L2CAP_SERVICE_ALREADY_REGISTERED 0x6a
|
||||
|
||||
#define RFCOMM_MULTIPLEXER_STOPPED 0x70
|
||||
#define RFCOMM_CHANNEL_ALREADY_REGISTERED 0x71
|
||||
#define RFCOMM_NO_OUTGOING_CREDITS 0x72
|
||||
|
||||
#define SDP_HANDLE_ALREADY_REGISTERED 0x80
|
||||
|
||||
/**
|
||||
* Default INQ Mode
|
||||
*/
|
||||
#define HCI_INQUIRY_LAP 0x9E8B33L // 0x9E8B33: General/Unlimited Inquiry Access Code (GIAC)
|
||||
/**
|
||||
* Hardware state of Bluetooth controller
|
||||
*/
|
||||
typedef enum {
|
||||
HCI_POWER_OFF = 0,
|
||||
HCI_POWER_ON,
|
||||
HCI_POWER_SLEEP
|
||||
} HCI_POWER_MODE;
|
||||
|
||||
/**
|
||||
* State of BTstack
|
||||
*/
|
||||
typedef enum {
|
||||
HCI_STATE_OFF = 0,
|
||||
HCI_STATE_INITIALIZING,
|
||||
HCI_STATE_WORKING,
|
||||
HCI_STATE_HALTING,
|
||||
HCI_STATE_SLEEPING,
|
||||
HCI_STATE_FALLING_ASLEEP
|
||||
} HCI_STATE;
|
||||
|
||||
/**
|
||||
* compact HCI Command packet description
|
||||
*/
|
||||
typedef struct {
|
||||
uint16_t opcode;
|
||||
const char *format;
|
||||
} hci_cmd_t;
|
||||
|
||||
|
||||
// HCI Commands - see hci_cmds.c for info on parameters
|
||||
extern const hci_cmd_t btstack_get_state;
|
||||
extern const hci_cmd_t btstack_set_power_mode;
|
||||
extern const hci_cmd_t btstack_set_acl_capture_mode;
|
||||
extern const hci_cmd_t btstack_get_version;
|
||||
extern const hci_cmd_t btstack_get_system_bluetooth_enabled;
|
||||
extern const hci_cmd_t btstack_set_system_bluetooth_enabled;
|
||||
extern const hci_cmd_t btstack_set_discoverable;
|
||||
extern const hci_cmd_t btstack_set_bluetooth_enabled; // only used by btstack config
|
||||
|
||||
extern const hci_cmd_t hci_accept_connection_request;
|
||||
extern const hci_cmd_t hci_authentication_requested;
|
||||
extern const hci_cmd_t hci_change_connection_link_key;
|
||||
extern const hci_cmd_t hci_create_connection;
|
||||
extern const hci_cmd_t hci_create_connection_cancel;
|
||||
extern const hci_cmd_t hci_delete_stored_link_key;
|
||||
extern const hci_cmd_t hci_disconnect;
|
||||
extern const hci_cmd_t hci_host_buffer_size;
|
||||
extern const hci_cmd_t hci_inquiry;
|
||||
extern const hci_cmd_t hci_inquiry_cancel;
|
||||
extern const hci_cmd_t hci_link_key_request_negative_reply;
|
||||
extern const hci_cmd_t hci_link_key_request_reply;
|
||||
extern const hci_cmd_t hci_pin_code_request_reply;
|
||||
extern const hci_cmd_t hci_pin_code_request_negative_reply;
|
||||
extern const hci_cmd_t hci_qos_setup;
|
||||
extern const hci_cmd_t hci_read_bd_addr;
|
||||
extern const hci_cmd_t hci_read_buffer_size;
|
||||
extern const hci_cmd_t hci_read_le_host_supported;
|
||||
extern const hci_cmd_t hci_read_link_policy_settings;
|
||||
extern const hci_cmd_t hci_read_link_supervision_timeout;
|
||||
extern const hci_cmd_t hci_read_local_supported_features;
|
||||
extern const hci_cmd_t hci_read_num_broadcast_retransmissions;
|
||||
extern const hci_cmd_t hci_reject_connection_request;
|
||||
extern const hci_cmd_t hci_remote_name_request;
|
||||
extern const hci_cmd_t hci_remote_name_request_cancel;
|
||||
extern const hci_cmd_t hci_reset;
|
||||
extern const hci_cmd_t hci_role_discovery;
|
||||
extern const hci_cmd_t hci_set_event_mask;
|
||||
extern const hci_cmd_t hci_set_connection_encryption;
|
||||
extern const hci_cmd_t hci_sniff_mode;
|
||||
extern const hci_cmd_t hci_switch_role_command;
|
||||
extern const hci_cmd_t hci_write_authentication_enable;
|
||||
extern const hci_cmd_t hci_write_class_of_device;
|
||||
extern const hci_cmd_t hci_write_extended_inquiry_response;
|
||||
extern const hci_cmd_t hci_write_inquiry_mode;
|
||||
extern const hci_cmd_t hci_write_le_host_supported;
|
||||
extern const hci_cmd_t hci_write_link_policy_settings;
|
||||
extern const hci_cmd_t hci_write_link_supervision_timeout;
|
||||
extern const hci_cmd_t hci_write_local_name;
|
||||
extern const hci_cmd_t hci_write_num_broadcast_retransmissions;
|
||||
extern const hci_cmd_t hci_write_page_timeout;
|
||||
extern const hci_cmd_t hci_write_scan_enable;
|
||||
extern const hci_cmd_t hci_write_simple_pairing_mode;
|
||||
|
||||
extern const hci_cmd_t hci_le_add_device_to_whitelist;
|
||||
extern const hci_cmd_t hci_le_clear_white_list;
|
||||
extern const hci_cmd_t hci_le_connection_update;
|
||||
extern const hci_cmd_t hci_le_create_connection;
|
||||
extern const hci_cmd_t hci_le_create_connection_cancel;
|
||||
extern const hci_cmd_t hci_le_encrypt;
|
||||
extern const hci_cmd_t hci_le_long_term_key_negative_reply;
|
||||
extern const hci_cmd_t hci_le_long_term_key_request_reply;
|
||||
extern const hci_cmd_t hci_le_rand;
|
||||
extern const hci_cmd_t hci_le_read_advertising_channel_tx_power;
|
||||
extern const hci_cmd_t hci_le_read_buffer_size ;
|
||||
extern const hci_cmd_t hci_le_read_channel_map;
|
||||
extern const hci_cmd_t hci_le_read_remote_used_features;
|
||||
extern const hci_cmd_t hci_le_read_supported_features;
|
||||
extern const hci_cmd_t hci_le_read_supported_states;
|
||||
extern const hci_cmd_t hci_le_read_white_list_size;
|
||||
extern const hci_cmd_t hci_le_receiver_test;
|
||||
extern const hci_cmd_t hci_le_remove_device_from_whitelist;
|
||||
extern const hci_cmd_t hci_le_set_advertise_enable;
|
||||
extern const hci_cmd_t hci_le_set_advertising_data;
|
||||
extern const hci_cmd_t hci_le_set_advertising_parameters;
|
||||
extern const hci_cmd_t hci_le_set_event_mask;
|
||||
extern const hci_cmd_t hci_le_set_host_channel_classification;
|
||||
extern const hci_cmd_t hci_le_set_random_address;
|
||||
extern const hci_cmd_t hci_le_set_scan_enable;
|
||||
extern const hci_cmd_t hci_le_set_scan_parameters;
|
||||
extern const hci_cmd_t hci_le_set_scan_response_data;
|
||||
extern const hci_cmd_t hci_le_start_encryption;
|
||||
extern const hci_cmd_t hci_le_test_end;
|
||||
extern const hci_cmd_t hci_le_transmitter_test;
|
||||
|
||||
extern const hci_cmd_t l2cap_accept_connection;
|
||||
extern const hci_cmd_t l2cap_create_channel;
|
||||
extern const hci_cmd_t l2cap_create_channel_mtu;
|
||||
extern const hci_cmd_t l2cap_decline_connection;
|
||||
extern const hci_cmd_t l2cap_disconnect;
|
||||
extern const hci_cmd_t l2cap_register_service;
|
||||
extern const hci_cmd_t l2cap_unregister_service;
|
||||
|
||||
extern const hci_cmd_t sdp_register_service_record;
|
||||
extern const hci_cmd_t sdp_unregister_service_record;
|
||||
|
||||
// accept connection @param bd_addr(48), rfcomm_cid (16)
|
||||
extern const hci_cmd_t rfcomm_accept_connection;
|
||||
// create rfcomm channel: @param bd_addr(48), channel (8)
|
||||
extern const hci_cmd_t rfcomm_create_channel;
|
||||
// create rfcomm channel: @param bd_addr(48), channel (8), mtu (16), credits (8)
|
||||
extern const hci_cmd_t rfcomm_create_channel_with_initial_credits;
|
||||
// decline rfcomm disconnect,@param bd_addr(48), rfcomm cid (16), reason(8)
|
||||
extern const hci_cmd_t rfcomm_decline_connection;
|
||||
// disconnect rfcomm disconnect, @param rfcomm_cid(8), reason(8)
|
||||
extern const hci_cmd_t rfcomm_disconnect;
|
||||
// register rfcomm service: @param channel(8), mtu (16)
|
||||
extern const hci_cmd_t rfcomm_register_service;
|
||||
// register rfcomm service: @param channel(8), mtu (16), initial credits (8)
|
||||
extern const hci_cmd_t rfcomm_register_service_with_initial_credits;
|
||||
// unregister rfcomm service, @param service_channel(16)
|
||||
extern const hci_cmd_t rfcomm_unregister_service;
|
||||
// request persisten rfcomm channel for service name: serive name (char*)
|
||||
extern const hci_cmd_t rfcomm_persistent_channel_for_service;
|
||||
|
||||
#if defined __cplusplus
|
||||
}
|
||||
#endif
|
63
ios/RetroArch/input/BTStack/btstack/linked_list.h
Normal file
63
ios/RetroArch/input/BTStack/btstack/linked_list.h
Normal file
@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright (C) 2009 by Matthias Ringwald
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holders nor the names of
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY MATTHIAS RINGWALD AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
|
||||
* RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* linked_list.h
|
||||
*
|
||||
* Created by Matthias Ringwald on 7/13/09.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if defined __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct linked_item {
|
||||
struct linked_item *next; // <-- next element in list, or NULL
|
||||
void *user_data; // <-- pointer to struct base
|
||||
} linked_item_t;
|
||||
|
||||
typedef linked_item_t * linked_list_t;
|
||||
|
||||
void linked_item_set_user(linked_item_t *item, void *user_data); // <-- set user data
|
||||
void * linked_item_get_user(linked_item_t *item); // <-- get user data
|
||||
int linked_list_empty(linked_list_t * list);
|
||||
void linked_list_add(linked_list_t * list, linked_item_t *item); // <-- add item to list as first element
|
||||
void linked_list_add_tail(linked_list_t * list, linked_item_t *item); // <-- add item to list as last element
|
||||
int linked_list_remove(linked_list_t * list, linked_item_t *item); // <-- remove item from list
|
||||
linked_item_t * linked_list_get_last_item(linked_list_t * list); // <-- find the last item in the list
|
||||
|
||||
void test_linked_list(void);
|
||||
|
||||
#if defined __cplusplus
|
||||
}
|
||||
#endif
|
122
ios/RetroArch/input/BTStack/btstack/run_loop.h
Normal file
122
ios/RetroArch/input/BTStack/btstack/run_loop.h
Normal file
@ -0,0 +1,122 @@
|
||||
/*
|
||||
* Copyright (C) 2009 by Matthias Ringwald
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holders nor the names of
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY MATTHIAS RINGWALD AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
|
||||
* RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* run_loop.h
|
||||
*
|
||||
* Created by Matthias Ringwald on 6/6/09.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
//#include "config.h"
|
||||
#define HAVE_TIME
|
||||
|
||||
#include "linked_list.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef HAVE_TIME
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
#if defined __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
RUN_LOOP_POSIX = 1,
|
||||
RUN_LOOP_COCOA,
|
||||
RUN_LOOP_EMBEDDED
|
||||
} RUN_LOOP_TYPE;
|
||||
|
||||
typedef struct data_source {
|
||||
linked_item_t item;
|
||||
int fd; // <-- file descriptor to watch or 0
|
||||
int (*process)(struct data_source *ds); // <-- do processing
|
||||
} data_source_t;
|
||||
|
||||
typedef struct timer {
|
||||
linked_item_t item;
|
||||
#ifdef HAVE_TIME
|
||||
struct timeval timeout; // <-- next timeout
|
||||
#endif
|
||||
#ifdef HAVE_TICK
|
||||
uint32_t timeout; // timeout in system ticks
|
||||
#endif
|
||||
void (*process)(struct timer *ts); // <-- do processing
|
||||
} timer_source_t;
|
||||
|
||||
|
||||
// Set timer based on current time in milliseconds.
|
||||
void run_loop_set_timer(timer_source_t *a, uint32_t timeout_in_ms);
|
||||
|
||||
// Set callback that will be executed when timer expires.
|
||||
void run_loop_set_timer_handler(timer_source_t *ts, void (*process)(timer_source_t *_ts));
|
||||
|
||||
// Add/Remove timer source.
|
||||
void run_loop_add_timer(timer_source_t *timer);
|
||||
int run_loop_remove_timer(timer_source_t *timer);
|
||||
|
||||
// Init must be called before any other run_loop call.
|
||||
// Use RUN_LOOP_EMBEDDED for embedded devices.
|
||||
void run_loop_init(RUN_LOOP_TYPE type);
|
||||
|
||||
// Set data source callback.
|
||||
void run_loop_set_data_source_handler(data_source_t *ds, int (*process)(data_source_t *_ds));
|
||||
|
||||
|
||||
// Add/Remove data source.
|
||||
void run_loop_add_data_source(data_source_t *dataSource);
|
||||
int run_loop_remove_data_source(data_source_t *dataSource);
|
||||
|
||||
|
||||
// Execute configured run loop. This function does not return.
|
||||
void run_loop_execute(void);
|
||||
|
||||
// hack to fix HCI timer handling
|
||||
#ifdef HAVE_TICK
|
||||
// Sets how many miliseconds has one tick.
|
||||
uint32_t embedded_ticks_for_ms(uint32_t time_in_ms);
|
||||
// Queries the current time in ticks.
|
||||
uint32_t embedded_get_ticks(void);
|
||||
#endif
|
||||
#ifdef EMBEDDED
|
||||
// Sets an internal flag that is checked in the critical section
|
||||
// just before entering sleep mode. Has to be called by the interupt
|
||||
// handler of a data source to signal the run loop that a new data
|
||||
// is available.
|
||||
void embedded_trigger(void);
|
||||
#endif
|
||||
#if defined __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
138
ios/RetroArch/input/BTStack/btstack/sdp_util.h
Normal file
138
ios/RetroArch/input/BTStack/btstack/sdp_util.h
Normal file
@ -0,0 +1,138 @@
|
||||
/*
|
||||
* Copyright (C) 2010 by Matthias Ringwald
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holders nor the names of
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY MATTHIAS RINGWALD AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
|
||||
* RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* sdp_util.h
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#if defined __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
DE_NIL = 0,
|
||||
DE_UINT,
|
||||
DE_INT,
|
||||
DE_UUID,
|
||||
DE_STRING,
|
||||
DE_BOOL,
|
||||
DE_DES,
|
||||
DE_DEA,
|
||||
DE_URL
|
||||
} de_type_t;
|
||||
|
||||
typedef enum {
|
||||
DE_SIZE_8 = 0,
|
||||
DE_SIZE_16,
|
||||
DE_SIZE_32,
|
||||
DE_SIZE_64,
|
||||
DE_SIZE_128,
|
||||
DE_SIZE_VAR_8,
|
||||
DE_SIZE_VAR_16,
|
||||
DE_SIZE_VAR_32
|
||||
} de_size_t;
|
||||
|
||||
// UNIVERSAL ATTRIBUTE DEFINITIONS
|
||||
#define SDP_ServiceRecordHandle 0x0000
|
||||
#define SDP_ServiceClassIDList 0x0001
|
||||
#define SDP_ServiceRecordState 0x0002
|
||||
#define SDP_ServiceID 0x0003
|
||||
#define SDP_ProtocolDescriptorList 0x0004
|
||||
#define SDP_BrowseGroupList 0x0005
|
||||
#define SDP_LanguageBaseAttributeIDList 0x0006
|
||||
#define SDP_ServiceInfoTimeToLive 0x0007
|
||||
#define SDP_ServiceAvailability 0x0008
|
||||
#define SDP_BluetoothProfileDescriptorList 0x0009
|
||||
#define SDP_DocumentationURL 0x000a
|
||||
#define SDP_ClientExecutableURL 0x000b
|
||||
#define SDP_IconURL 0x000c
|
||||
#define SDP_AdditionalProtocolDescriptorList 0x000d
|
||||
#define SDP_SupportedFormatsList 0x0303
|
||||
|
||||
// SERVICE CLASSES
|
||||
#define SDP_OBEXObjectPush 0x1105
|
||||
#define SDP_OBEXFileTransfer 0x1106
|
||||
#define SDP_PublicBrowseGroup 0x1002
|
||||
|
||||
// PROTOCOLS
|
||||
#define SDP_SDPProtocol 0x0001
|
||||
#define SDP_UDPProtocol 0x0002
|
||||
#define SDP_RFCOMMProtocol 0x0003
|
||||
#define SDP_OBEXProtocol 0x0008
|
||||
#define SDP_L2CAPProtocol 0x0100
|
||||
|
||||
// OFFSETS FOR LOCALIZED ATTRIBUTES - SDP_LanguageBaseAttributeIDList
|
||||
#define SDP_Offest_ServiceName 0x0000
|
||||
#define SDP_Offest_ServiceDescription 0x0001
|
||||
#define SDP_Offest_ProviderName 0x0002
|
||||
|
||||
// OBEX
|
||||
#define SDP_vCard_2_1 0x01
|
||||
#define SDP_vCard_3_0 0x02
|
||||
#define SDP_vCal_1_0 0x03
|
||||
#define SDP_iCal_2_0 0x04
|
||||
#define SDP_vNote 0x05
|
||||
#define SDP_vMessage 0x06
|
||||
#define SDP_OBEXFileTypeAny 0xFF
|
||||
|
||||
// MARK: DateElement
|
||||
void de_dump_data_element(uint8_t * record);
|
||||
int de_get_len(uint8_t *header);
|
||||
de_size_t de_get_size_type(uint8_t *header);
|
||||
de_type_t de_get_element_type(uint8_t *header);
|
||||
int de_get_header_size(uint8_t * header);
|
||||
void de_create_sequence(uint8_t *header);
|
||||
void de_store_descriptor_with_len(uint8_t * header, de_type_t type, de_size_t size, uint32_t len);
|
||||
uint8_t * de_push_sequence(uint8_t *header);
|
||||
void de_pop_sequence(uint8_t * parent, uint8_t * child);
|
||||
void de_add_number(uint8_t *seq, de_type_t type, de_size_t size, uint32_t value);
|
||||
void de_add_data( uint8_t *seq, de_type_t type, uint16_t size, uint8_t *data);
|
||||
|
||||
int de_get_data_size(uint8_t * header);
|
||||
void de_add_uuid128(uint8_t * seq, uint8_t * uuid);
|
||||
|
||||
// MARK: SDP
|
||||
uint16_t sdp_append_attributes_in_attributeIDList(uint8_t *record, uint8_t *attributeIDList, uint16_t startOffset, uint16_t maxBytes, uint8_t *buffer);
|
||||
uint8_t * sdp_get_attribute_value_for_attribute_id(uint8_t * record, uint16_t attributeID);
|
||||
uint8_t sdp_set_attribute_value_for_attribute_id(uint8_t * record, uint16_t attributeID, uint32_t value);
|
||||
int sdp_record_matches_service_search_pattern(uint8_t *record, uint8_t *serviceSearchPattern);
|
||||
int spd_get_filtered_size(uint8_t *record, uint8_t *attributeIDList);
|
||||
int sdp_filter_attributes_in_attributeIDList(uint8_t *record, uint8_t *attributeIDList, uint16_t startOffset, uint16_t maxBytes, uint16_t *usedBytes, uint8_t *buffer);
|
||||
|
||||
void sdp_create_spp_service(uint8_t *service, int service_id, const char *name);
|
||||
|
||||
#if defined __cplusplus
|
||||
}
|
||||
#endif
|
127
ios/RetroArch/input/BTStack/btstack/utils.h
Normal file
127
ios/RetroArch/input/BTStack/btstack/utils.h
Normal file
@ -0,0 +1,127 @@
|
||||
/*
|
||||
* Copyright (C) 2009 by Matthias Ringwald
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holders nor the names of
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY MATTHIAS RINGWALD AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
|
||||
* RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* utils.h
|
||||
*
|
||||
* General utility functions
|
||||
*
|
||||
* Created by Matthias Ringwald on 7/23/09.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
#if defined __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
* @brief hci connection handle type
|
||||
*/
|
||||
typedef uint16_t hci_con_handle_t;
|
||||
|
||||
/**
|
||||
* @brief Length of a bluetooth device address.
|
||||
*/
|
||||
#define BD_ADDR_LEN 6
|
||||
typedef uint8_t bd_addr_t[BD_ADDR_LEN];
|
||||
|
||||
/**
|
||||
* @brief The link key type
|
||||
*/
|
||||
#define LINK_KEY_LEN 16
|
||||
typedef uint8_t link_key_t[LINK_KEY_LEN];
|
||||
|
||||
/**
|
||||
* @brief The device name type
|
||||
*/
|
||||
#define DEVICE_NAME_LEN 248
|
||||
typedef uint8_t device_name_t[DEVICE_NAME_LEN+1];
|
||||
|
||||
|
||||
// helper for BT little endian format
|
||||
#define READ_BT_16( buffer, pos) ( ((uint16_t) buffer[pos]) | (((uint16_t)buffer[pos+1]) << 8))
|
||||
#define READ_BT_24( buffer, pos) ( ((uint32_t) buffer[pos]) | (((uint32_t)buffer[pos+1]) << 8) | (((uint32_t)buffer[pos+2]) << 16))
|
||||
#define READ_BT_32( buffer, pos) ( ((uint32_t) buffer[pos]) | (((uint32_t)buffer[pos+1]) << 8) | (((uint32_t)buffer[pos+2]) << 16) | (((uint32_t) buffer[pos+3])) << 24)
|
||||
|
||||
// helper for SDP big endian format
|
||||
#define READ_NET_16( buffer, pos) ( ((uint16_t) buffer[pos+1]) | (((uint16_t)buffer[pos ]) << 8))
|
||||
#define READ_NET_32( buffer, pos) ( ((uint32_t) buffer[pos+3]) | (((uint32_t)buffer[pos+2]) << 8) | (((uint32_t)buffer[pos+1]) << 16) | (((uint32_t) buffer[pos])) << 24)
|
||||
|
||||
// HCI CMD OGF/OCF
|
||||
#define READ_CMD_OGF(buffer) (buffer[1] >> 2)
|
||||
#define READ_CMD_OCF(buffer) ((buffer[1] & 0x03) << 8 | buffer[0])
|
||||
|
||||
// check if command complete event for given command
|
||||
#define COMMAND_COMPLETE_EVENT(event,cmd) ( event[0] == HCI_EVENT_COMMAND_COMPLETE && READ_BT_16(event,3) == cmd.opcode)
|
||||
#define COMMAND_STATUS_EVENT(event,cmd) ( event[0] == HCI_EVENT_COMMAND_STATUS && READ_BT_16(event,4) == cmd.opcode)
|
||||
|
||||
// Code+Len=2, Pkts+Opcode=3; total=5
|
||||
#define OFFSET_OF_DATA_IN_COMMAND_COMPLETE 5
|
||||
|
||||
// ACL Packet
|
||||
#define READ_ACL_CONNECTION_HANDLE( buffer ) ( READ_BT_16(buffer,0) & 0x0fff)
|
||||
#define READ_ACL_FLAGS( buffer ) ( buffer[1] >> 4 )
|
||||
#define READ_ACL_LENGTH( buffer ) (READ_BT_16(buffer, 2))
|
||||
|
||||
// L2CAP Packet
|
||||
#define READ_L2CAP_LENGTH(buffer) ( READ_BT_16(buffer, 4))
|
||||
#define READ_L2CAP_CHANNEL_ID(buffer) ( READ_BT_16(buffer, 6))
|
||||
|
||||
void bt_store_16(uint8_t *buffer, uint16_t pos, uint16_t value);
|
||||
void bt_store_32(uint8_t *buffer, uint16_t pos, uint32_t value);
|
||||
void bt_flip_addr(bd_addr_t dest, bd_addr_t src);
|
||||
|
||||
void net_store_16(uint8_t *buffer, uint16_t pos, uint16_t value);
|
||||
void net_store_32(uint8_t *buffer, uint16_t pos, uint32_t value);
|
||||
|
||||
void hexdump(void *data, int size);
|
||||
void printUUID(uint8_t *uuid);
|
||||
|
||||
// @deprecated please use more convenient bd_addr_to_str
|
||||
void print_bd_addr( bd_addr_t addr);
|
||||
char * bd_addr_to_str(bd_addr_t addr);
|
||||
|
||||
int sscan_bd_addr(uint8_t * addr_string, bd_addr_t addr);
|
||||
|
||||
uint8_t crc8_check(uint8_t *data, uint16_t len, uint8_t check_sum);
|
||||
uint8_t crc8_calc(uint8_t *data, uint16_t len);
|
||||
|
||||
#define BD_ADDR_CMP(a,b) memcmp(a,b, BD_ADDR_LEN)
|
||||
#define BD_ADDR_COPY(dest,src) memcpy(dest,src,BD_ADDR_LEN)
|
||||
|
||||
#if defined __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
BIN
ios/RetroArch/input/BTStack/libBTstack.dylib
Executable file
BIN
ios/RetroArch/input/BTStack/libBTstack.dylib
Executable file
Binary file not shown.
692
ios/RetroArch/input/BTStack/wiimote.c
Normal file
692
ios/RetroArch/input/BTStack/wiimote.c
Normal file
@ -0,0 +1,692 @@
|
||||
/*
|
||||
* This file is part of iMAME4all.
|
||||
*
|
||||
* Copyright (C) 2010 David Valdeita (Seleuco)
|
||||
*
|
||||
* based on:
|
||||
*
|
||||
* wiiuse
|
||||
*
|
||||
* Written By:
|
||||
* Michael Laforest < para >
|
||||
* Email: < thepara (--AT--) g m a i l [--DOT--] com >
|
||||
*
|
||||
* Copyright 2006-2007
|
||||
*
|
||||
* This program 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 Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* In addition, as a special exception, Seleuco
|
||||
* gives permission to link the code of this program with
|
||||
* the MAME library (or with modified versions of MAME that use the
|
||||
* same license as MAME), and distribute linked combinations including
|
||||
* the two. You must obey the GNU General Public License in all
|
||||
* respects for all of the code used other than MAME. If you modify
|
||||
* this file, you may extend this exception to your version of the
|
||||
* file, but you are not obligated to do so. If you do not wish to
|
||||
* do so, delete this exception statement from your version.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "btstack/btstack.h"
|
||||
#include "wiimote.h"
|
||||
|
||||
int myosd_num_of_joys = 0;
|
||||
struct wiimote_t joys[4];
|
||||
extern int g_pref_wii_DZ_value;
|
||||
#define STICK4WAY (myosd_waysStick == 4 && myosd_inGame)
|
||||
#define STICK2WAY (myosd_waysStick == 2 && myosd_inGame)
|
||||
|
||||
int wiimote_send(struct wiimote_t* wm, byte report_type, byte* msg, int len);
|
||||
int wiimote_read_data(struct wiimote_t* wm, unsigned int addr, unsigned short len);
|
||||
int wiimote_write_data(struct wiimote_t* wm, unsigned int addr, byte* data, byte len);
|
||||
void wiimote_set_leds(struct wiimote_t* wm, int leds);
|
||||
int classic_ctrl_handshake(struct wiimote_t* wm, struct classic_ctrl_t* cc, byte* data, unsigned short len);
|
||||
void classic_ctrl_event(struct classic_ctrl_t* cc, byte* msg);
|
||||
|
||||
int wiimote_remove(uint16_t source_cid, bd_addr_t *addr){
|
||||
|
||||
int i = 0;
|
||||
int unid = -1;
|
||||
int found = 0;
|
||||
for(;i<myosd_num_of_joys;i++)
|
||||
{
|
||||
if(joys[i].c_source_cid==source_cid && !found)
|
||||
{
|
||||
found=1;
|
||||
struct wiimote_t *wm = NULL;
|
||||
wm = &joys[i];
|
||||
if(WIIMOTE_DBG)printf("%02x:%02x:%02x:%02x:%02x:%02x\n",wm->addr[0], wm->addr[1], wm->addr[2],wm->addr[3], wm->addr[4], wm->addr[5]);
|
||||
memcpy(addr,&(wm->addr),BD_ADDR_LEN);
|
||||
unid = wm->unid;
|
||||
continue;
|
||||
}
|
||||
if(found)
|
||||
{
|
||||
memcpy(&joys[i-1],&joys[i],sizeof(struct wiimote_t ));
|
||||
joys[i-1].unid = i-1;
|
||||
struct wiimote_t *wm = NULL;
|
||||
wm = &joys[i-1];
|
||||
if(wm->unid==0)
|
||||
wiimote_set_leds(wm, WIIMOTE_LED_1);
|
||||
else if(wm->unid==1)
|
||||
wiimote_set_leds(wm, WIIMOTE_LED_2);
|
||||
else if(wm->unid==2)
|
||||
wiimote_set_leds(wm, WIIMOTE_LED_3);
|
||||
else if(wm->unid==3)
|
||||
wiimote_set_leds(wm, WIIMOTE_LED_4);
|
||||
}
|
||||
}
|
||||
if(found)
|
||||
{
|
||||
myosd_num_of_joys--;
|
||||
if(WIIMOTE_DBG)printf("NUM JOYS %d\n",myosd_num_of_joys);
|
||||
return unid;
|
||||
}
|
||||
return unid;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Find a wiimote_t structure by its source_cid.
|
||||
*
|
||||
* @param wm Pointer to a wiimote_t structure.
|
||||
* @param wiimotes The number of wiimote_t structures in \a wm.
|
||||
* @param unid The unique identifier to search for.
|
||||
*
|
||||
* @return Pointer to a wiimote_t structure, or NULL if not found.
|
||||
*/
|
||||
|
||||
struct wiimote_t* wiimote_get_by_source_cid(uint16_t source_cid){
|
||||
|
||||
int i = 0;
|
||||
|
||||
for (; i < myosd_num_of_joys; ++i) {
|
||||
if(WIIMOTE_DBG)printf("0x%02x 0x%02x\n",joys[i].i_source_cid,source_cid);
|
||||
if (joys[i].i_source_cid == source_cid)
|
||||
return &joys[i];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Request the wiimote controller status.
|
||||
*
|
||||
* @param wm Pointer to a wiimote_t structure.
|
||||
*
|
||||
* Controller status includes: battery level, LED status, expansions
|
||||
*/
|
||||
void wiimote_status(struct wiimote_t* wm) {
|
||||
byte buf = 0;
|
||||
|
||||
if (!wm || !WIIMOTE_IS_CONNECTED(wm))
|
||||
return;
|
||||
|
||||
if(WIIMOTE_DBG)printf("Requested wiimote status.\n");
|
||||
|
||||
wiimote_send(wm, WM_CMD_CTRL_STATUS, &buf, 1);
|
||||
}
|
||||
|
||||
void wiimote_data_report(struct wiimote_t* wm, byte type) {
|
||||
byte buf[2] = {0x0,0x0};
|
||||
|
||||
if (!wm || !WIIMOTE_IS_CONNECTED(wm))
|
||||
return;
|
||||
|
||||
buf[1] = type;
|
||||
//CUIDADO es un &buf?
|
||||
wiimote_send(wm, WM_CMD_REPORT_TYPE, buf, 2);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the enabled LEDs.
|
||||
*
|
||||
* @param wm Pointer to a wiimote_t structure.
|
||||
* @param leds What LEDs to enable.
|
||||
*
|
||||
* \a leds is a bitwise or of WIIMOTE_LED_1, WIIMOTE_LED_2, WIIMOTE_LED_3, or WIIMOTE_LED_4.
|
||||
*/
|
||||
void wiimote_set_leds(struct wiimote_t* wm, int leds) {
|
||||
byte buf;
|
||||
|
||||
if (!wm || !WIIMOTE_IS_CONNECTED(wm))
|
||||
return;
|
||||
|
||||
/* remove the lower 4 bits because they control rumble */
|
||||
wm->leds = (leds & 0xF0);
|
||||
|
||||
buf = wm->leds;
|
||||
|
||||
wiimote_send(wm, WM_CMD_LED, &buf, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Find what buttons are pressed.
|
||||
*
|
||||
* @param wm Pointer to a wiimote_t structure.
|
||||
* @param msg The message specified in the event packet.
|
||||
*/
|
||||
void wiimote_pressed_buttons(struct wiimote_t* wm, byte* msg) {
|
||||
short now;
|
||||
|
||||
/* convert to big endian */
|
||||
now = BIG_ENDIAN_SHORT(*(short*)msg) & WIIMOTE_BUTTON_ALL;
|
||||
|
||||
/* buttons pressed now */
|
||||
wm->btns = now;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Handle data from the expansion.
|
||||
*
|
||||
* @param wm A pointer to a wiimote_t structure.
|
||||
* @param msg The message specified in the event packet for the expansion.
|
||||
*/
|
||||
void wiimote_handle_expansion(struct wiimote_t* wm, byte* msg) {
|
||||
switch (wm->exp.type) {
|
||||
case EXP_CLASSIC:
|
||||
classic_ctrl_event(&wm->exp.classic, msg);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get initialization data from the wiimote.
|
||||
*
|
||||
* @param wm Pointer to a wiimote_t structure.
|
||||
* @param data unused
|
||||
* @param len unused
|
||||
*
|
||||
* When first called for a wiimote_t structure, a request
|
||||
* is sent to the wiimote for initialization information.
|
||||
* This includes factory set accelerometer data.
|
||||
* The handshake will be concluded when the wiimote responds
|
||||
* with this data.
|
||||
*/
|
||||
int wiimote_handshake(struct wiimote_t* wm, byte event, byte* data, unsigned short len) {
|
||||
|
||||
if (!wm) return 0;
|
||||
|
||||
while(1)
|
||||
{
|
||||
if(WIIMOTE_DBG)printf("Handshake %d\n",wm->handshake_state);
|
||||
switch (wm->handshake_state) {
|
||||
case 0://no ha habido nunca handshake, debemos forzar un mensaje de staus para ver que pasa.
|
||||
{
|
||||
WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_HANDSHAKE);
|
||||
wiimote_set_leds(wm, WIIMOTE_LED_NONE);
|
||||
|
||||
/* request the status of the wiimote to see if there is an expansion */
|
||||
wiimote_status(wm);
|
||||
|
||||
wm->handshake_state=1;
|
||||
return 0;
|
||||
}
|
||||
case 1://estamos haciendo handshake o bien se necesita iniciar un nuevo handshake ya que se inserta(quita una expansion.
|
||||
{
|
||||
int attachment = 0;
|
||||
|
||||
if(event != WM_RPT_CTRL_STATUS)
|
||||
return 0;
|
||||
|
||||
/* is an attachment connected to the expansion port? */
|
||||
if ((data[2] & WM_CTRL_STATUS_BYTE1_ATTACHMENT) == WM_CTRL_STATUS_BYTE1_ATTACHMENT)
|
||||
{
|
||||
attachment = 1;
|
||||
}
|
||||
|
||||
if(WIIMOTE_DBG)printf("attachment %d %d\n",attachment,WIIMOTE_IS_SET(wm, WIIMOTE_STATE_EXP));
|
||||
|
||||
/* expansion port */
|
||||
if (attachment && !WIIMOTE_IS_SET(wm, WIIMOTE_STATE_EXP)) {
|
||||
WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_EXP);
|
||||
|
||||
/* send the initialization code for the attachment */
|
||||
if(WIIMOTE_DBG)printf("haciendo el handshake de la expansion\n");
|
||||
|
||||
if(WIIMOTE_IS_SET(wm,WIIMOTE_STATE_HANDSHAKE_COMPLETE))
|
||||
{
|
||||
if(WIIMOTE_DBG)printf("rehandshake\n");
|
||||
WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_HANDSHAKE_COMPLETE);
|
||||
WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_HANDSHAKE);//forzamos un handshake por si venimos de un hanshake completo
|
||||
}
|
||||
|
||||
byte buf;
|
||||
//Old way. initialize the extension was by writing the single encryption byte 0x00 to 0x(4)A40040
|
||||
//buf = 0x00;
|
||||
//wiimote_write_data(wm, WM_EXP_MEM_ENABLE, &buf, 1);
|
||||
|
||||
//NEW WAY 0x55 to 0x(4)A400F0, then writing 0x00 to 0x(4)A400FB. (support clones)
|
||||
buf = 0x55;
|
||||
wiimote_write_data(wm, 0x04A400F0, &buf, 1);
|
||||
usleep(100000);
|
||||
buf = 0x00;
|
||||
wiimote_write_data(wm, 0x04A400FB, &buf, 1);
|
||||
|
||||
//check extension type!
|
||||
usleep(100000);
|
||||
wiimote_read_data(wm, WM_EXP_MEM_CALIBR+220, 4);
|
||||
//wiimote_read_data(wm, WM_EXP_MEM_CALIBR, EXP_HANDSHAKE_LEN);
|
||||
|
||||
wm->handshake_state = 4;
|
||||
return 0;
|
||||
|
||||
} else if (!attachment && WIIMOTE_IS_SET(wm, WIIMOTE_STATE_EXP)) {
|
||||
/* attachment removed */
|
||||
WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_EXP);
|
||||
wm->exp.type = EXP_NONE;
|
||||
|
||||
if(WIIMOTE_IS_SET(wm,WIIMOTE_STATE_HANDSHAKE_COMPLETE))
|
||||
{
|
||||
if(WIIMOTE_DBG)printf("rehandshake\n");
|
||||
WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_HANDSHAKE_COMPLETE);
|
||||
WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_HANDSHAKE);//forzamos un handshake por si venimos de un hanshake completo
|
||||
}
|
||||
}
|
||||
|
||||
if(!attachment && WIIMOTE_IS_SET(wm,WIIMOTE_STATE_HANDSHAKE))
|
||||
{
|
||||
wm->handshake_state = 2;
|
||||
continue;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
case 2://find handshake no expansion
|
||||
{
|
||||
if(WIIMOTE_DBG)printf("Finalizado HANDSHAKE SIN EXPANSION\n");
|
||||
wiimote_data_report(wm,WM_RPT_BTN);
|
||||
wm->handshake_state = 6;
|
||||
continue;
|
||||
}
|
||||
case 3://find handshake expansion
|
||||
{
|
||||
if(WIIMOTE_DBG)printf("Finalizado HANDSHAKE CON EXPANSION\n");
|
||||
wiimote_data_report(wm,WM_RPT_BTN_EXP);
|
||||
wm->handshake_state = 6;
|
||||
continue;
|
||||
}
|
||||
case 4:
|
||||
{
|
||||
if(event != WM_RPT_READ)
|
||||
return 0;
|
||||
|
||||
int id = BIG_ENDIAN_LONG(*(int*)(data));
|
||||
|
||||
if(WIIMOTE_DBG)printf("Expansion id=0x%04x\n",id);
|
||||
|
||||
if(id!=/*EXP_ID_CODE_CLASSIC_CONTROLLER*/0xa4200101)
|
||||
{
|
||||
wm->handshake_state = 2;
|
||||
//WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_EXP);
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
usleep(100000);
|
||||
wiimote_read_data(wm, WM_EXP_MEM_CALIBR, 16);//pedimos datos de calibracion del JOY!
|
||||
wm->handshake_state = 5;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
case 5:
|
||||
{
|
||||
if(event != WM_RPT_READ)
|
||||
return 0;
|
||||
|
||||
classic_ctrl_handshake(wm, &wm->exp.classic, data,len);
|
||||
wm->handshake_state = 3;
|
||||
continue;
|
||||
|
||||
}
|
||||
case 6:
|
||||
{
|
||||
WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_HANDSHAKE);
|
||||
WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_HANDSHAKE_COMPLETE);
|
||||
wm->handshake_state = 1;
|
||||
if(wm->unid==0)
|
||||
wiimote_set_leds(wm, WIIMOTE_LED_1);
|
||||
else if(wm->unid==1)
|
||||
wiimote_set_leds(wm, WIIMOTE_LED_2);
|
||||
else if(wm->unid==2)
|
||||
wiimote_set_leds(wm, WIIMOTE_LED_3);
|
||||
else if(wm->unid==3)
|
||||
wiimote_set_leds(wm, WIIMOTE_LED_4);
|
||||
return 1;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Send a packet to the wiimote.
|
||||
*
|
||||
* @param wm Pointer to a wiimote_t structure.
|
||||
* @param report_type The report type to send (WIIMOTE_CMD_LED, WIIMOTE_CMD_RUMBLE, etc). Found in wiimote.h
|
||||
* @param msg The payload.
|
||||
* @param len Length of the payload in bytes.
|
||||
*
|
||||
* This function should replace any write()s directly to the wiimote device.
|
||||
*/
|
||||
int wiimote_send(struct wiimote_t* wm, byte report_type, byte* msg, int len) {
|
||||
byte buf[32];
|
||||
|
||||
buf[0] = WM_SET_REPORT | WM_BT_OUTPUT;
|
||||
buf[1] = report_type;
|
||||
|
||||
memcpy(buf+2, msg, len);
|
||||
|
||||
if(WIIMOTE_DBG)
|
||||
{
|
||||
int x = 2;
|
||||
printf("[DEBUG] (id %i) SEND: (%x) %.2x ", wm->unid, buf[0], buf[1]);
|
||||
for (; x < len+2; ++x)
|
||||
printf("%.2x ", buf[x]);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
bt_send_l2cap( wm->c_source_cid, buf, len+2);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Read data from the wiimote (event version).
|
||||
*
|
||||
* @param wm Pointer to a wiimote_t structure.
|
||||
* @param addr The address of wiimote memory to read from.
|
||||
* @param len The length of the block to be read.
|
||||
*
|
||||
* The library can only handle one data read request at a time
|
||||
* because it must keep track of the buffer and other
|
||||
* events that are specific to that request. So if a request
|
||||
* has already been made, subsequent requests will be added
|
||||
* to a pending list and be sent out when the previous
|
||||
* finishes.
|
||||
*/
|
||||
int wiimote_read_data(struct wiimote_t* wm, unsigned int addr, unsigned short len) {
|
||||
//No puden ser mas de 16 lo leido o vendra en trozos!
|
||||
|
||||
if (!wm || !WIIMOTE_IS_CONNECTED(wm))
|
||||
return 0;
|
||||
if (!len /*|| len > 16*/)
|
||||
return 0;
|
||||
|
||||
byte buf[6];
|
||||
|
||||
/* the offset is in big endian */
|
||||
*(int*)(buf) = BIG_ENDIAN_LONG(addr);
|
||||
|
||||
/* the length is in big endian */
|
||||
*(short*)(buf + 4) = BIG_ENDIAN_SHORT(len);
|
||||
|
||||
if(WIIMOTE_DBG)printf("Request read at address: 0x%x length: %i", addr, len);
|
||||
wiimote_send(wm, WM_CMD_READ_DATA, buf, 6);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Write data to the wiimote.
|
||||
*
|
||||
* @param wm Pointer to a wiimote_t structure.
|
||||
* @param addr The address to write to.
|
||||
* @param data The data to be written to the memory location.
|
||||
* @param len The length of the block to be written.
|
||||
*/
|
||||
int wiimote_write_data(struct wiimote_t* wm, unsigned int addr, byte* data, byte len) {
|
||||
byte buf[21] = {0}; /* the payload is always 23 */
|
||||
|
||||
if (!wm || !WIIMOTE_IS_CONNECTED(wm))
|
||||
return 0;
|
||||
if (!data || !len)
|
||||
return 0;
|
||||
|
||||
if(WIIMOTE_DBG)printf("Writing %i bytes to memory location 0x%x...\n", len, addr);
|
||||
|
||||
if(WIIMOTE_DBG)
|
||||
{
|
||||
int i = 0;
|
||||
printf("Write data is: ");
|
||||
for (; i < len; ++i)
|
||||
printf("%x ", data[i]);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
/* the offset is in big endian */
|
||||
*(int*)(buf) = BIG_ENDIAN_LONG(addr);
|
||||
|
||||
/* length */
|
||||
*(byte*)(buf + 4) = len;
|
||||
|
||||
/* data */
|
||||
memcpy(buf + 5, data, len);
|
||||
|
||||
wiimote_send(wm, WM_CMD_WRITE_DATA, buf, 21);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////// CLASSIC /////////////////
|
||||
|
||||
static void classic_ctrl_pressed_buttons(struct classic_ctrl_t* cc, short now);
|
||||
void calc_joystick_state(struct joystick_t* js, float x, float y);
|
||||
|
||||
/**
|
||||
* @brief Handle the handshake data from the classic controller.
|
||||
*
|
||||
* @param cc A pointer to a classic_ctrl_t structure.
|
||||
* @param data The data read in from the device.
|
||||
* @param len The length of the data block, in bytes.
|
||||
*
|
||||
* @return Returns 1 if handshake was successful, 0 if not.
|
||||
*/
|
||||
int classic_ctrl_handshake(struct wiimote_t* wm, struct classic_ctrl_t* cc, byte* data, unsigned short len) {
|
||||
int offset = 0;
|
||||
|
||||
cc->btns = 0;
|
||||
cc->r_shoulder = 0;
|
||||
cc->l_shoulder = 0;
|
||||
|
||||
/* decrypt data */
|
||||
/*
|
||||
for (i = 0; i < len; ++i)
|
||||
data[i] = (data[i] ^ 0x17) + 0x17;
|
||||
*/
|
||||
|
||||
if(WIIMOTE_DBG)
|
||||
{
|
||||
int x = 0;
|
||||
printf("[DECRIPTED]");
|
||||
for (; x < len; x++)
|
||||
printf("%.2x ", data[x]);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
/*
|
||||
if (data[offset] == 0xFF)
|
||||
{
|
||||
return 0;//ERROR!
|
||||
}
|
||||
*/
|
||||
/* joystick stuff */
|
||||
if (data[offset] != 0xFF && data[offset] != 0x00)
|
||||
{
|
||||
cc->ljs.max.x = data[0 + offset] / 4;
|
||||
cc->ljs.min.x = data[1 + offset] / 4;
|
||||
cc->ljs.center.x = data[2 + offset] / 4;
|
||||
cc->ljs.max.y = data[3 + offset] / 4;
|
||||
cc->ljs.min.y = data[4 + offset] / 4;
|
||||
cc->ljs.center.y = data[5 + offset] / 4;
|
||||
|
||||
cc->rjs.max.x = data[6 + offset] / 8;
|
||||
cc->rjs.min.x = data[7 + offset] / 8;
|
||||
cc->rjs.center.x = data[8 + offset] / 8;
|
||||
cc->rjs.max.y = data[9 + offset] / 8;
|
||||
cc->rjs.min.y = data[10 + offset] / 8;
|
||||
cc->rjs.center.y = data[11 + offset] / 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
cc->ljs.max.x = 55;
|
||||
cc->ljs.min.x = 5;
|
||||
cc->ljs.center.x = 30;
|
||||
cc->ljs.max.y = 55;
|
||||
cc->ljs.min.y = 5;
|
||||
cc->ljs.center.y = 30;
|
||||
|
||||
cc->rjs.max.x = 30;
|
||||
cc->rjs.min.x = 0;
|
||||
cc->rjs.center.x = 15;
|
||||
cc->rjs.max.y = 30;
|
||||
cc->rjs.min.y = 0;
|
||||
cc->rjs.center.y = 15;
|
||||
}
|
||||
|
||||
/* handshake done */
|
||||
wm->exp.type = EXP_CLASSIC;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Handle classic controller event.
|
||||
*
|
||||
* @param cc A pointer to a classic_ctrl_t structure.
|
||||
* @param msg The message specified in the event packet.
|
||||
*/
|
||||
void classic_ctrl_event(struct classic_ctrl_t* cc, byte* msg) {
|
||||
int lx, ly, rx, ry;
|
||||
byte l, r;
|
||||
|
||||
/* decrypt data */
|
||||
/*
|
||||
for (i = 0; i < 6; ++i)
|
||||
msg[i] = (msg[i] ^ 0x17) + 0x17;
|
||||
*/
|
||||
|
||||
classic_ctrl_pressed_buttons(cc, BIG_ENDIAN_SHORT(*(short*)(msg + 4)));
|
||||
|
||||
/* left/right buttons */
|
||||
l = (((msg[2] & 0x60) >> 2) | ((msg[3] & 0xE0) >> 5));
|
||||
r = (msg[3] & 0x1F);
|
||||
|
||||
/*
|
||||
* TODO - LR range hardcoded from 0x00 to 0x1F.
|
||||
* This is probably in the calibration somewhere.
|
||||
*/
|
||||
cc->r_shoulder = ((float)r / 0x1F);
|
||||
cc->l_shoulder = ((float)l / 0x1F);
|
||||
|
||||
/* calculate joystick orientation */
|
||||
lx = (msg[0] & 0x3F);
|
||||
ly = (msg[1] & 0x3F);
|
||||
rx = ((msg[0] & 0xC0) >> 3) | ((msg[1] & 0xC0) >> 5) | ((msg[2] & 0x80) >> 7);
|
||||
ry = (msg[2] & 0x1F);
|
||||
|
||||
if(WIIMOTE_DBG)
|
||||
printf("lx ly rx ry %d %d %d %d\n",lx,ly,rx,ry);
|
||||
|
||||
calc_joystick_state(&cc->ljs, lx, ly);
|
||||
calc_joystick_state(&cc->rjs, rx, ry);
|
||||
|
||||
/*
|
||||
printf("classic L button pressed: %f\n", cc->l_shoulder);
|
||||
printf("classic R button pressed: %f\n", cc->r_shoulder);
|
||||
printf("classic left joystick angle: %f\n", cc->ljs.ang);
|
||||
printf("classic left joystick magnitude: %f\n", cc->ljs.mag);
|
||||
printf("classic right joystick angle: %f\n", cc->rjs.ang);
|
||||
printf("classic right joystick magnitude: %f\n", cc->rjs.mag);
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Find what buttons are pressed.
|
||||
*
|
||||
* @param cc A pointer to a classic_ctrl_t structure.
|
||||
* @param msg The message byte specified in the event packet.
|
||||
*/
|
||||
static void classic_ctrl_pressed_buttons(struct classic_ctrl_t* cc, short now) {
|
||||
/* message is inverted (0 is active, 1 is inactive) */
|
||||
now = ~now & CLASSIC_CTRL_BUTTON_ALL;
|
||||
|
||||
/* buttons pressed now */
|
||||
cc->btns = now;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Calculate the angle and magnitude of a joystick.
|
||||
*
|
||||
* @param js [out] Pointer to a joystick_t structure.
|
||||
* @param x The raw x-axis value.
|
||||
* @param y The raw y-axis value.
|
||||
*/
|
||||
void calc_joystick_state(struct joystick_t* js, float x, float y) {
|
||||
float rx, ry, ang;
|
||||
|
||||
/*
|
||||
* Since the joystick center may not be exactly:
|
||||
* (min + max) / 2
|
||||
* Then the range from the min to the center and the center to the max
|
||||
* may be different.
|
||||
* Because of this, depending on if the current x or y value is greater
|
||||
* or less than the assoicated axis center value, it needs to be interpolated
|
||||
* between the center and the minimum or maxmimum rather than between
|
||||
* the minimum and maximum.
|
||||
*
|
||||
* So we have something like this:
|
||||
* (x min) [-1] ---------*------ [0] (x center) [0] -------- [1] (x max)
|
||||
* Where the * is the current x value.
|
||||
* The range is therefore -1 to 1, 0 being the exact center rather than
|
||||
* the middle of min and max.
|
||||
*/
|
||||
if (x == js->center.x)
|
||||
rx = 0;
|
||||
else if (x >= js->center.x)
|
||||
rx = ((float)(x - js->center.x) / (float)(js->max.x - js->center.x));
|
||||
else
|
||||
rx = ((float)(x - js->min.x) / (float)(js->center.x - js->min.x)) - 1.0f;
|
||||
|
||||
if (y == js->center.y)
|
||||
ry = 0;
|
||||
else if (y >= js->center.y)
|
||||
ry = ((float)(y - js->center.y) / (float)(js->max.y - js->center.y));
|
||||
else
|
||||
ry = ((float)(y - js->min.y) / (float)(js->center.y - js->min.y)) - 1.0f;
|
||||
|
||||
/* calculate the joystick angle and magnitude */
|
||||
ang = RAD_TO_DEGREE(atanf(ry / rx));
|
||||
ang -= 90.0f;
|
||||
if (rx < 0.0f)
|
||||
ang -= 180.0f;
|
||||
js->ang = absf(ang);
|
||||
js->mag = (float) sqrt((rx * rx) + (ry * ry));
|
||||
js->rx = rx;
|
||||
js->ry = ry;
|
||||
|
||||
}
|
292
ios/RetroArch/input/BTStack/wiimote.h
Normal file
292
ios/RetroArch/input/BTStack/wiimote.h
Normal file
@ -0,0 +1,292 @@
|
||||
/*
|
||||
* This file is part of iMAME4all.
|
||||
*
|
||||
* Copyright (C) 2010 David Valdeita (Seleuco)
|
||||
*
|
||||
* based on:
|
||||
*
|
||||
* wiiuse
|
||||
*
|
||||
* Written By:
|
||||
* Michael Laforest < para >
|
||||
* Email: < thepara (--AT--) g m a i l [--DOT--] com >
|
||||
*
|
||||
* Copyright 2006-2007
|
||||
*
|
||||
* This program 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 Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* In addition, as a special exception, Seleuco
|
||||
* gives permission to link the code of this program with
|
||||
* the MAME library (or with modified versions of MAME that use the
|
||||
* same license as MAME), and distribute linked combinations including
|
||||
* the two. You must obey the GNU General Public License in all
|
||||
* respects for all of the code used other than MAME. If you modify
|
||||
* this file, you may extend this exception to your version of the
|
||||
* file, but you are not obligated to do so. If you do not wish to
|
||||
* do so, delete this exception statement from your version.
|
||||
*/
|
||||
|
||||
#ifndef __WIIMOTE_H__
|
||||
#define __WIIMOTE_H__
|
||||
|
||||
#include "btstack/utils.h"
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef unsigned char byte;
|
||||
typedef char sbyte;
|
||||
|
||||
#define WIIMOTE_PI 3.14159265
|
||||
|
||||
#define WIIMOTE_DBG 0
|
||||
|
||||
/* Convert between radians and degrees */
|
||||
#define RAD_TO_DEGREE(r) ((r * 180.0f) / WIIMOTE_PI)
|
||||
#define DEGREE_TO_RAD(d) (d * (WIIMOTE_PI / 180.0f))
|
||||
|
||||
/* Convert to big endian */
|
||||
#define BIG_ENDIAN_LONG(i) (htonl(i))
|
||||
#define BIG_ENDIAN_SHORT(i) (htons(i))
|
||||
|
||||
#define absf(x) ((x >= 0) ? (x) : (x * -1.0f))
|
||||
#define diff_f(x, y) ((x >= y) ? (absf(x - y)) : (absf(y - x)))
|
||||
|
||||
/* wiimote state flags*/
|
||||
#define WIIMOTE_STATE_DEV_FOUND 0x0001
|
||||
#define WIIMOTE_STATE_HANDSHAKE 0x0002 /* actual connection exists but no handshake yet */
|
||||
#define WIIMOTE_STATE_HANDSHAKE_COMPLETE 0x0004
|
||||
#define WIIMOTE_STATE_CONNECTED 0x0008
|
||||
#define WIIMOTE_STATE_EXP 0x0040
|
||||
|
||||
/* Communication channels */
|
||||
#define WM_OUTPUT_CHANNEL 0x11
|
||||
#define WM_INPUT_CHANNEL 0x13
|
||||
|
||||
#define WM_SET_REPORT 0x50
|
||||
|
||||
/* commands */
|
||||
#define WM_CMD_LED 0x11
|
||||
#define WM_CMD_REPORT_TYPE 0x12
|
||||
#define WM_CMD_RUMBLE 0x13
|
||||
#define WM_CMD_IR 0x13
|
||||
#define WM_CMD_CTRL_STATUS 0x15
|
||||
#define WM_CMD_WRITE_DATA 0x16
|
||||
#define WM_CMD_READ_DATA 0x17
|
||||
#define WM_CMD_IR_2 0x1A
|
||||
|
||||
/* input report ids */
|
||||
#define WM_RPT_CTRL_STATUS 0x20
|
||||
#define WM_RPT_READ 0x21
|
||||
#define WM_RPT_WRITE 0x22
|
||||
#define WM_RPT_BTN 0x30
|
||||
#define WM_RPT_BTN_ACC 0x31
|
||||
#define WM_RPT_BTN_ACC_IR 0x33
|
||||
#define WM_RPT_BTN_EXP 0x34
|
||||
#define WM_RPT_BTN_ACC_EXP 0x35
|
||||
#define WM_RPT_BTN_IR_EXP 0x36
|
||||
#define WM_RPT_BTN_ACC_IR_EXP 0x37
|
||||
|
||||
#define WM_BT_INPUT 0x01
|
||||
#define WM_BT_OUTPUT 0x02
|
||||
|
||||
/* controller status stuff */
|
||||
#define WM_MAX_BATTERY_CODE 0xC8
|
||||
|
||||
#define EXP_ID_CODE_CLASSIC_CONTROLLER 0x9A1EFDFD
|
||||
|
||||
/* offsets in wiimote memory */
|
||||
#define WM_MEM_OFFSET_CALIBRATION 0x16
|
||||
#define WM_EXP_MEM_BASE 0x04A40000
|
||||
#define WM_EXP_MEM_ENABLE 0x04A40040
|
||||
#define WM_EXP_MEM_CALIBR 0x04A40020
|
||||
|
||||
#define EXP_HANDSHAKE_LEN 224
|
||||
|
||||
/* controller status flags for the first message byte */
|
||||
/* bit 1 is unknown */
|
||||
#define WM_CTRL_STATUS_BYTE1_ATTACHMENT 0x02
|
||||
#define WM_CTRL_STATUS_BYTE1_SPEAKER_ENABLED 0x04
|
||||
#define WM_CTRL_STATUS_BYTE1_IR_ENABLED 0x08
|
||||
#define WM_CTRL_STATUS_BYTE1_LED_1 0x10
|
||||
#define WM_CTRL_STATUS_BYTE1_LED_2 0x20
|
||||
#define WM_CTRL_STATUS_BYTE1_LED_3 0x40
|
||||
#define WM_CTRL_STATUS_BYTE1_LED_4 0x80
|
||||
|
||||
/* led bit masks */
|
||||
#define WIIMOTE_LED_NONE 0x00
|
||||
#define WIIMOTE_LED_1 0x10
|
||||
#define WIIMOTE_LED_2 0x20
|
||||
#define WIIMOTE_LED_3 0x40
|
||||
#define WIIMOTE_LED_4 0x80
|
||||
|
||||
/* button codes */
|
||||
#define WIIMOTE_BUTTON_TWO 0x0001
|
||||
#define WIIMOTE_BUTTON_ONE 0x0002
|
||||
#define WIIMOTE_BUTTON_B 0x0004
|
||||
#define WIIMOTE_BUTTON_A 0x0008
|
||||
#define WIIMOTE_BUTTON_MINUS 0x0010
|
||||
#define WIIMOTE_BUTTON_ZACCEL_BIT6 0x0020
|
||||
#define WIIMOTE_BUTTON_ZACCEL_BIT7 0x0040
|
||||
#define WIIMOTE_BUTTON_HOME 0x0080
|
||||
#define WIIMOTE_BUTTON_LEFT 0x0100
|
||||
#define WIIMOTE_BUTTON_RIGHT 0x0200
|
||||
#define WIIMOTE_BUTTON_DOWN 0x0400
|
||||
#define WIIMOTE_BUTTON_UP 0x0800
|
||||
#define WIIMOTE_BUTTON_PLUS 0x1000
|
||||
#define WIIMOTE_BUTTON_ZACCEL_BIT4 0x2000
|
||||
#define WIIMOTE_BUTTON_ZACCEL_BIT5 0x4000
|
||||
#define WIIMOTE_BUTTON_UNKNOWN 0x8000
|
||||
#define WIIMOTE_BUTTON_ALL 0x1F9F
|
||||
|
||||
/* classic controller button codes */
|
||||
#define CLASSIC_CTRL_BUTTON_UP 0x0001
|
||||
#define CLASSIC_CTRL_BUTTON_LEFT 0x0002
|
||||
#define CLASSIC_CTRL_BUTTON_ZR 0x0004
|
||||
#define CLASSIC_CTRL_BUTTON_X 0x0008
|
||||
#define CLASSIC_CTRL_BUTTON_A 0x0010
|
||||
#define CLASSIC_CTRL_BUTTON_Y 0x0020
|
||||
#define CLASSIC_CTRL_BUTTON_B 0x0040
|
||||
#define CLASSIC_CTRL_BUTTON_ZL 0x0080
|
||||
#define CLASSIC_CTRL_BUTTON_FULL_R 0x0200
|
||||
#define CLASSIC_CTRL_BUTTON_PLUS 0x0400
|
||||
#define CLASSIC_CTRL_BUTTON_HOME 0x0800
|
||||
#define CLASSIC_CTRL_BUTTON_MINUS 0x1000
|
||||
#define CLASSIC_CTRL_BUTTON_FULL_L 0x2000
|
||||
#define CLASSIC_CTRL_BUTTON_DOWN 0x4000
|
||||
#define CLASSIC_CTRL_BUTTON_RIGHT 0x8000
|
||||
#define CLASSIC_CTRL_BUTTON_ALL 0xFEFF
|
||||
|
||||
/* expansion codes */
|
||||
#define EXP_NONE 0
|
||||
#define EXP_CLASSIC 2
|
||||
|
||||
/**
|
||||
* @struct vec2b_t
|
||||
* @brief Unsigned x,y byte vector.
|
||||
*/
|
||||
typedef struct vec2b_t {
|
||||
byte x, y;
|
||||
} vec2b_t;
|
||||
|
||||
/**
|
||||
* @struct joystick_t
|
||||
* @brief Joystick calibration structure.
|
||||
*
|
||||
* The angle \a ang is relative to the positive y-axis into quadrant I
|
||||
* and ranges from 0 to 360 degrees. So if the joystick is held straight
|
||||
* upwards then angle is 0 degrees. If it is held to the right it is 90,
|
||||
* down is 180, and left is 270.
|
||||
*
|
||||
* The magnitude \a mag is the distance from the center to where the
|
||||
* joystick is being held. The magnitude ranges from 0 to 1.
|
||||
* If the joystick is only slightly tilted from the center the magnitude
|
||||
* will be low, but if it is closer to the outter edge the value will
|
||||
* be higher.
|
||||
*/
|
||||
typedef struct joystick_t {
|
||||
struct vec2b_t max; /**< maximum joystick values */
|
||||
struct vec2b_t min; /**< minimum joystick values */
|
||||
struct vec2b_t center; /**< center joystick values */
|
||||
|
||||
float ang; /**< angle the joystick is being held */
|
||||
float mag; /**< magnitude of the joystick (range 0-1) */
|
||||
float rx, ry;
|
||||
} joystick_t;
|
||||
|
||||
/**
|
||||
* @struct classic_ctrl_t
|
||||
* @brief Classic controller expansion device.
|
||||
*/
|
||||
typedef struct classic_ctrl_t {
|
||||
short btns; /**< what buttons have just been pressed */
|
||||
|
||||
float r_shoulder; /**< right shoulder button (range 0-1) */
|
||||
float l_shoulder; /**< left shoulder button (range 0-1) */
|
||||
|
||||
struct joystick_t ljs; /**< left joystick calibration */
|
||||
struct joystick_t rjs; /**< right joystick calibration */
|
||||
} classic_ctrl_t;
|
||||
|
||||
/**
|
||||
* @struct expansion_t
|
||||
* @brief Generic expansion device plugged into wiimote.
|
||||
*/
|
||||
typedef struct expansion_t {
|
||||
int type; /**< type of expansion attached */
|
||||
|
||||
union {
|
||||
struct classic_ctrl_t classic;
|
||||
};
|
||||
} expansion_t;
|
||||
|
||||
/**
|
||||
* @struct wiimote_t
|
||||
* @brief Wiimote structure.
|
||||
*/
|
||||
typedef struct wiimote_t {
|
||||
int unid; /**< user specified id */
|
||||
|
||||
uint16_t wiiMoteConHandle;
|
||||
uint16_t i_source_cid;
|
||||
uint16_t c_source_cid;
|
||||
bd_addr_t addr;
|
||||
|
||||
int state; /**< various state flags */
|
||||
byte leds; /**< currently lit leds */
|
||||
float battery_level; /**< battery level */
|
||||
|
||||
byte handshake_state; /**< the state of the connection handshake */
|
||||
|
||||
struct expansion_t exp; /**< wiimote expansion device */
|
||||
|
||||
unsigned short btns; /**< what buttons have just been pressed */
|
||||
} wiimote;
|
||||
|
||||
/**
|
||||
* @brief Check if a button is pressed.
|
||||
* @param dev Pointer to a wiimote_t or expansion structure.
|
||||
* @param button The button you are interested in.
|
||||
* @return 1 if the button is pressed, 0 if not.
|
||||
*/
|
||||
#define IS_PRESSED(dev, button) ((dev->btns & button) == button)
|
||||
|
||||
/* macro to manage states */
|
||||
#define WIIMOTE_IS_SET(wm, s) ((wm->state & (s)) == (s))
|
||||
#define WIIMOTE_ENABLE_STATE(wm, s) (wm->state |= (s))
|
||||
#define WIIMOTE_DISABLE_STATE(wm, s) (wm->state &= ~(s))
|
||||
#define WIIMOTE_TOGGLE_STATE(wm, s) ((wm->state & (s)) ? WIIMOTE_DISABLE_STATE(wm, s) : WIIMOTE_ENABLE_STATE(wm, s))
|
||||
|
||||
#define WIIMOTE_IS_CONNECTED(wm) (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_CONNECTED))
|
||||
|
||||
extern struct wiimote_t joys[4];
|
||||
extern int myosd_num_of_joys;
|
||||
|
||||
|
||||
int wiimote_remove(uint16_t source_cid, bd_addr_t *addr);
|
||||
struct wiimote_t* wiimote_get_by_source_cid(uint16_t source_cid);
|
||||
int wiimote_handshake(struct wiimote_t* wm, byte event, byte* data, unsigned short len);
|
||||
void wiimote_status(struct wiimote_t* wm);
|
||||
void wiimote_data_report(struct wiimote_t* wm, byte type);
|
||||
void wiimote_pressed_buttons(struct wiimote_t* wm, byte* msg);
|
||||
void wiimote_handle_expansion(struct wiimote_t* wm, byte* msg);
|
||||
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
31
ios/RetroArch/input/RAInputResponder.h
Normal file
31
ios/RetroArch/input/RAInputResponder.h
Normal file
@ -0,0 +1,31 @@
|
||||
/* 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/>.
|
||||
*/
|
||||
|
||||
// Input responder
|
||||
#define MAX_TOUCHES 16
|
||||
#define MAX_KEYS 256
|
||||
|
||||
typedef struct touch_data
|
||||
{
|
||||
int16_t screen_x, screen_y;
|
||||
int16_t fixed_x, fixed_y;
|
||||
int16_t full_x, full_y;
|
||||
} touch_data_t;
|
||||
|
||||
@interface RAInputResponder : NSObject
|
||||
- (void)poll;
|
||||
- (bool)isKeyPressed:(unsigned)index;
|
||||
- (const touch_data_t*)getTouchDataAtIndex:(unsigned)index;
|
||||
@end
|
97
ios/RetroArch/input/RAInputResponder.m
Normal file
97
ios/RetroArch/input/RAInputResponder.m
Normal file
@ -0,0 +1,97 @@
|
||||
/* 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/>.
|
||||
*/
|
||||
|
||||
#import "RAInputResponder.h"
|
||||
#include "input/input_common.h"
|
||||
|
||||
extern NSString* const GSEventKeyDownNotification;
|
||||
extern NSString* const GSEventKeyUpNotification;
|
||||
extern NSString* const RATouchNotification;
|
||||
|
||||
@implementation RAInputResponder
|
||||
{
|
||||
unsigned _touchCount;
|
||||
touch_data_t _touches[MAX_TOUCHES];
|
||||
bool _keys[MAX_KEYS];
|
||||
}
|
||||
|
||||
-(id)init
|
||||
{
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyPressed:) name: GSEventKeyDownNotification object:nil];
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyReleased:) name: GSEventKeyUpNotification object:nil];
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleTouches:) name: RATouchNotification object:nil];
|
||||
return self;
|
||||
}
|
||||
|
||||
-(void)dealloc
|
||||
{
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
||||
}
|
||||
|
||||
- (void)poll
|
||||
{
|
||||
for (int i = 0; i != _touchCount; i ++)
|
||||
{
|
||||
input_translate_coord_viewport(_touches[i].screen_x, _touches[i].screen_y,
|
||||
&_touches[i].fixed_x, &_touches[i].fixed_y,
|
||||
&_touches[i].full_x, &_touches[i].full_y);
|
||||
}
|
||||
}
|
||||
|
||||
- (bool)isKeyPressed:(unsigned)index
|
||||
{
|
||||
return (index < MAX_KEYS) ? _keys[index] : NO;
|
||||
}
|
||||
|
||||
- (const touch_data_t*)getTouchDataAtIndex:(unsigned)index
|
||||
{
|
||||
return (index < _touchCount) ? &_touches[index] : 0;
|
||||
}
|
||||
|
||||
// Response handlers
|
||||
- (void)keyPressed:(NSNotification*)notification
|
||||
{
|
||||
int keycode = [[notification.userInfo objectForKey:@"keycode"] intValue];
|
||||
if (keycode < MAX_KEYS) _keys[keycode] = true;
|
||||
}
|
||||
|
||||
- (void)keyReleased:(NSNotification*)notification
|
||||
{
|
||||
int keycode = [[notification.userInfo objectForKey:@"keycode"] intValue];
|
||||
if (keycode < MAX_KEYS) _keys[keycode] = false;
|
||||
}
|
||||
|
||||
- (void)handleTouches:(NSNotification*)notification
|
||||
{
|
||||
UIEvent* event = [notification.userInfo objectForKey:@"event"];
|
||||
NSArray* touches = [[event allTouches] allObjects];
|
||||
const int numTouches = [touches count];
|
||||
|
||||
_touchCount = 0;
|
||||
|
||||
for(int i = 0; i != numTouches && _touchCount != MAX_TOUCHES; i ++)
|
||||
{
|
||||
UITouch *touch = [touches objectAtIndex:i];
|
||||
CGPoint coord = [touch locationInView:touch.view];
|
||||
float scale = [[UIScreen mainScreen] scale];
|
||||
|
||||
if (touch.phase != UITouchPhaseEnded && touch.phase != UITouchPhaseCancelled)
|
||||
{
|
||||
_touches[_touchCount ].screen_x = coord.x * scale;
|
||||
_touches[_touchCount ++].screen_y = coord.y * scale;
|
||||
}
|
||||
}
|
||||
}
|
||||
@end
|
201
ios/RetroArch/input/ios_input.m
Normal file
201
ios/RetroArch/input/ios_input.m
Normal file
@ -0,0 +1,201 @@
|
||||
/* 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/>.
|
||||
*/
|
||||
|
||||
#import "RAInputResponder.h"
|
||||
|
||||
#include <unistd.h>
|
||||
#include "input/input_common.h"
|
||||
#include "general.h"
|
||||
#include "driver.h"
|
||||
|
||||
#ifdef WIIMOTE
|
||||
extern const rarch_joypad_driver_t ios_joypad;
|
||||
static const rarch_joypad_driver_t* const g_joydriver = &ios_joypad;
|
||||
#else
|
||||
static const rarch_joypad_driver_t* const g_joydriver = 0;
|
||||
#endif
|
||||
|
||||
static const struct rarch_key_map rarch_key_map_hidusage[];
|
||||
|
||||
static RAInputResponder* g_input_driver;
|
||||
|
||||
// Non-exported helpers
|
||||
static bool ios_key_pressed(enum retro_key key)
|
||||
{
|
||||
if ((int)key >= 0 && key < RETROK_LAST)
|
||||
{
|
||||
return [g_input_driver isKeyPressed:input_translate_rk_to_keysym(key)];
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool ios_is_pressed(unsigned port_num, const struct retro_keybind *key)
|
||||
{
|
||||
return ios_key_pressed(key->key) || input_joypad_pressed(g_joydriver, port_num, key);
|
||||
}
|
||||
|
||||
// Exported input driver
|
||||
static void *ios_input_init(void)
|
||||
{
|
||||
input_init_keyboard_lut(rarch_key_map_hidusage);
|
||||
g_input_driver = [RAInputResponder new];
|
||||
return (void*)-1;
|
||||
}
|
||||
|
||||
static void ios_input_poll(void *data)
|
||||
{
|
||||
[g_input_driver poll];
|
||||
input_joypad_poll(g_joydriver);
|
||||
}
|
||||
|
||||
static int16_t ios_input_state(void *data, const struct retro_keybind **binds, unsigned port, unsigned device, unsigned index, unsigned id)
|
||||
{
|
||||
switch (device)
|
||||
{
|
||||
case RETRO_DEVICE_JOYPAD:
|
||||
return (id < RARCH_BIND_LIST_END) ? ios_is_pressed(port, &binds[port][id]) : false;
|
||||
|
||||
case RARCH_DEVICE_POINTER_SCREEN:
|
||||
{
|
||||
const touch_data_t* touch = [g_input_driver getTouchDataAtIndex:index];
|
||||
|
||||
switch (id)
|
||||
{
|
||||
case RETRO_DEVICE_ID_POINTER_X: return touch ? touch->full_x : 0;
|
||||
case RETRO_DEVICE_ID_POINTER_Y: return touch ? touch->full_y : 0;
|
||||
case RETRO_DEVICE_ID_POINTER_PRESSED: return touch ? 1 : 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static bool ios_bind_button_pressed(void *data, int key)
|
||||
{
|
||||
const struct retro_keybind *binds = g_settings.input.binds[0];
|
||||
return (key >= 0 && key < RARCH_BIND_LIST_END) ? ios_is_pressed(0, &binds[key]) : false;
|
||||
}
|
||||
|
||||
static void ios_input_free_input(void *data)
|
||||
{
|
||||
(void)data;
|
||||
g_input_driver = nil;
|
||||
}
|
||||
|
||||
const input_driver_t input_ios = {
|
||||
ios_input_init,
|
||||
ios_input_poll,
|
||||
ios_input_state,
|
||||
ios_bind_button_pressed,
|
||||
ios_input_free_input,
|
||||
"ios_input",
|
||||
};
|
||||
|
||||
// Key table
|
||||
#include "keycode.h"
|
||||
static const struct rarch_key_map rarch_key_map_hidusage[] = {
|
||||
{ KEY_Left, RETROK_LEFT },
|
||||
{ KEY_Right, RETROK_RIGHT },
|
||||
{ KEY_Up, RETROK_UP },
|
||||
{ KEY_Down, RETROK_DOWN },
|
||||
{ KEY_Enter, RETROK_RETURN },
|
||||
{ KEY_Tab, RETROK_TAB },
|
||||
{ KEY_Insert, RETROK_INSERT },
|
||||
{ KEY_Delete, RETROK_DELETE },
|
||||
{ KEY_RightShift, RETROK_RSHIFT },
|
||||
{ KEY_LeftShift, RETROK_LSHIFT },
|
||||
{ KEY_RightControl, RETROK_RCTRL },
|
||||
{ KEY_LeftControl, RETROK_LCTRL },
|
||||
{ KEY_End, RETROK_END },
|
||||
{ KEY_Home, RETROK_HOME },
|
||||
{ KEY_PageDown, RETROK_PAGEDOWN },
|
||||
{ KEY_PageUp, RETROK_PAGEUP },
|
||||
{ KEY_RightAlt, RETROK_RALT },
|
||||
{ KEY_LeftAlt, RETROK_LALT },
|
||||
{ KEY_Space, RETROK_SPACE },
|
||||
{ KEY_Escape, RETROK_ESCAPE },
|
||||
{ KEY_Delete, RETROK_BACKSPACE },
|
||||
{ KP_Enter, RETROK_KP_ENTER },
|
||||
{ KP_Add, RETROK_KP_PLUS },
|
||||
{ KP_Subtract, RETROK_KP_MINUS },
|
||||
{ KP_Multiply, RETROK_KP_MULTIPLY },
|
||||
{ KP_Divide, RETROK_KP_DIVIDE },
|
||||
{ KEY_Grave, RETROK_BACKQUOTE },
|
||||
{ KEY_Pause, RETROK_PAUSE },
|
||||
{ KP_0, RETROK_KP0 },
|
||||
{ KP_1, RETROK_KP1 },
|
||||
{ KP_2, RETROK_KP2 },
|
||||
{ KP_3, RETROK_KP3 },
|
||||
{ KP_4, RETROK_KP4 },
|
||||
{ KP_5, RETROK_KP5 },
|
||||
{ KP_6, RETROK_KP6 },
|
||||
{ KP_7, RETROK_KP7 },
|
||||
{ KP_8, RETROK_KP8 },
|
||||
{ KP_9, RETROK_KP9 },
|
||||
{ KEY_0, RETROK_0 },
|
||||
{ KEY_1, RETROK_1 },
|
||||
{ KEY_2, RETROK_2 },
|
||||
{ KEY_3, RETROK_3 },
|
||||
{ KEY_4, RETROK_4 },
|
||||
{ KEY_5, RETROK_5 },
|
||||
{ KEY_6, RETROK_6 },
|
||||
{ KEY_7, RETROK_7 },
|
||||
{ KEY_8, RETROK_8 },
|
||||
{ KEY_9, RETROK_9 },
|
||||
{ KEY_F1, RETROK_F1 },
|
||||
{ KEY_F2, RETROK_F2 },
|
||||
{ KEY_F3, RETROK_F3 },
|
||||
{ KEY_F4, RETROK_F4 },
|
||||
{ KEY_F5, RETROK_F5 },
|
||||
{ KEY_F6, RETROK_F6 },
|
||||
{ KEY_F7, RETROK_F7 },
|
||||
{ KEY_F8, RETROK_F8 },
|
||||
{ KEY_F9, RETROK_F9 },
|
||||
{ KEY_F10, RETROK_F10 },
|
||||
{ KEY_F11, RETROK_F11 },
|
||||
{ KEY_F12, RETROK_F12 },
|
||||
{ KEY_A, RETROK_a },
|
||||
{ KEY_B, RETROK_b },
|
||||
{ KEY_C, RETROK_c },
|
||||
{ KEY_D, RETROK_d },
|
||||
{ KEY_E, RETROK_e },
|
||||
{ KEY_F, RETROK_f },
|
||||
{ KEY_G, RETROK_g },
|
||||
{ KEY_H, RETROK_h },
|
||||
{ KEY_I, RETROK_i },
|
||||
{ KEY_J, RETROK_j },
|
||||
{ KEY_K, RETROK_k },
|
||||
{ KEY_L, RETROK_l },
|
||||
{ KEY_M, RETROK_m },
|
||||
{ KEY_N, RETROK_n },
|
||||
{ KEY_O, RETROK_o },
|
||||
{ KEY_P, RETROK_p },
|
||||
{ KEY_Q, RETROK_q },
|
||||
{ KEY_R, RETROK_r },
|
||||
{ KEY_S, RETROK_s },
|
||||
{ KEY_T, RETROK_t },
|
||||
{ KEY_U, RETROK_u },
|
||||
{ KEY_V, RETROK_v },
|
||||
{ KEY_W, RETROK_w },
|
||||
{ KEY_X, RETROK_x },
|
||||
{ KEY_Y, RETROK_y },
|
||||
{ KEY_Z, RETROK_z },
|
||||
{ 0, RETROK_UNKNOWN }
|
||||
};
|
75
ios/RetroArch/input/ios_joypad.m
Normal file
75
ios/RetroArch/input/ios_joypad.m
Normal file
@ -0,0 +1,75 @@
|
||||
/* 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 "input/input_common.h"
|
||||
#include "BTStack/wiimote.h"
|
||||
#include "general.h"
|
||||
|
||||
static uint32_t g_buttons[MAX_PLAYERS];
|
||||
|
||||
static bool ios_joypad_init(void)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool ios_joypad_query_pad(unsigned pad)
|
||||
{
|
||||
return pad < MAX_PLAYERS;
|
||||
}
|
||||
|
||||
static void ios_joypad_destroy(void)
|
||||
{
|
||||
}
|
||||
|
||||
static bool ios_joypad_button(unsigned port, uint16_t joykey)
|
||||
{
|
||||
if (joykey == NO_BTN)
|
||||
return false;
|
||||
|
||||
// Check hat.
|
||||
if (GET_HAT_DIR(joykey))
|
||||
return false;
|
||||
else // Check the button
|
||||
return (port < MAX_PLAYERS && joykey < 32) ? (g_buttons[port] & (1 << joykey)) != 0 : false;
|
||||
}
|
||||
|
||||
static int16_t ios_joypad_axis(unsigned port, uint32_t joyaxis)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ios_joypad_poll(void)
|
||||
{
|
||||
for (int i = 0; i != MAX_PLAYERS; i ++)
|
||||
{
|
||||
g_buttons[i] = 0;
|
||||
if (i < myosd_num_of_joys)
|
||||
{
|
||||
g_buttons[i] = joys[i].btns;
|
||||
g_buttons[i] |= (joys[i].exp.type == EXP_CLASSIC) ? (joys[i].exp.classic.btns << 16) : 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const rarch_joypad_driver_t ios_joypad = {
|
||||
ios_joypad_init,
|
||||
ios_joypad_query_pad,
|
||||
ios_joypad_destroy,
|
||||
ios_joypad_button,
|
||||
ios_joypad_axis,
|
||||
ios_joypad_poll,
|
||||
"ios",
|
||||
};
|
||||
|
156
ios/RetroArch/input/keycode.h
Normal file
156
ios/RetroArch/input/keycode.h
Normal file
@ -0,0 +1,156 @@
|
||||
/*
|
||||
Taken from https://github.com/depp/keycode, distributed with the following license:
|
||||
|
||||
Copyright 2011-2012 Dietrich Epp <depp@zdome.net>
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following
|
||||
disclaimer in the documentation and/or other materials provided
|
||||
with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* This file is automatically generated by keycode.py. */
|
||||
#ifndef KEYCODE_KEYCODE_H
|
||||
#define KEYCODE_KEYCODE_H
|
||||
enum {
|
||||
KEY_A = 4,
|
||||
KEY_B = 5,
|
||||
KEY_C = 6,
|
||||
KEY_D = 7,
|
||||
KEY_E = 8,
|
||||
KEY_F = 9,
|
||||
KEY_G = 10,
|
||||
KEY_H = 11,
|
||||
KEY_I = 12,
|
||||
KEY_J = 13,
|
||||
KEY_K = 14,
|
||||
KEY_L = 15,
|
||||
KEY_M = 16,
|
||||
KEY_N = 17,
|
||||
KEY_O = 18,
|
||||
KEY_P = 19,
|
||||
KEY_Q = 20,
|
||||
KEY_R = 21,
|
||||
KEY_S = 22,
|
||||
KEY_T = 23,
|
||||
KEY_U = 24,
|
||||
KEY_V = 25,
|
||||
KEY_W = 26,
|
||||
KEY_X = 27,
|
||||
KEY_Y = 28,
|
||||
KEY_Z = 29,
|
||||
KEY_1 = 30,
|
||||
KEY_2 = 31,
|
||||
KEY_3 = 32,
|
||||
KEY_4 = 33,
|
||||
KEY_5 = 34,
|
||||
KEY_6 = 35,
|
||||
KEY_7 = 36,
|
||||
KEY_8 = 37,
|
||||
KEY_9 = 38,
|
||||
KEY_0 = 39,
|
||||
KEY_Enter = 40,
|
||||
KEY_Escape = 41,
|
||||
KEY_Delete = 42,
|
||||
KEY_Tab = 43,
|
||||
KEY_Space = 44,
|
||||
KEY_Minus = 45,
|
||||
KEY_Equals = 46,
|
||||
KEY_LeftBracket = 47,
|
||||
KEY_RightBracket = 48,
|
||||
KEY_Backslash = 49,
|
||||
KEY_Semicolon = 51,
|
||||
KEY_Quote = 52,
|
||||
KEY_Grave = 53,
|
||||
KEY_Comma = 54,
|
||||
KEY_Period = 55,
|
||||
KEY_Slash = 56,
|
||||
KEY_CapsLock = 57,
|
||||
KEY_F1 = 58,
|
||||
KEY_F2 = 59,
|
||||
KEY_F3 = 60,
|
||||
KEY_F4 = 61,
|
||||
KEY_F5 = 62,
|
||||
KEY_F6 = 63,
|
||||
KEY_F7 = 64,
|
||||
KEY_F8 = 65,
|
||||
KEY_F9 = 66,
|
||||
KEY_F10 = 67,
|
||||
KEY_F11 = 68,
|
||||
KEY_F12 = 69,
|
||||
KEY_PrintScreen = 70,
|
||||
KEY_ScrollLock = 71,
|
||||
KEY_Pause = 72,
|
||||
KEY_Insert = 73,
|
||||
KEY_Home = 74,
|
||||
KEY_PageUp = 75,
|
||||
KEY_DeleteForward = 76,
|
||||
KEY_End = 77,
|
||||
KEY_PageDown = 78,
|
||||
KEY_Right = 79,
|
||||
KEY_Left = 80,
|
||||
KEY_Down = 81,
|
||||
KEY_Up = 82,
|
||||
KP_NumLock = 83,
|
||||
KP_Divide = 84,
|
||||
KP_Multiply = 85,
|
||||
KP_Subtract = 86,
|
||||
KP_Add = 87,
|
||||
KP_Enter = 88,
|
||||
KP_1 = 89,
|
||||
KP_2 = 90,
|
||||
KP_3 = 91,
|
||||
KP_4 = 92,
|
||||
KP_5 = 93,
|
||||
KP_6 = 94,
|
||||
KP_7 = 95,
|
||||
KP_8 = 96,
|
||||
KP_9 = 97,
|
||||
KP_0 = 98,
|
||||
KP_Point = 99,
|
||||
KEY_NonUSBackslash = 100,
|
||||
KP_Equals = 103,
|
||||
KEY_F13 = 104,
|
||||
KEY_F14 = 105,
|
||||
KEY_F15 = 106,
|
||||
KEY_F16 = 107,
|
||||
KEY_F17 = 108,
|
||||
KEY_F18 = 109,
|
||||
KEY_F19 = 110,
|
||||
KEY_F20 = 111,
|
||||
KEY_F21 = 112,
|
||||
KEY_F22 = 113,
|
||||
KEY_F23 = 114,
|
||||
KEY_F24 = 115,
|
||||
KEY_Help = 117,
|
||||
KEY_Menu = 118,
|
||||
KEY_LeftControl = 224,
|
||||
KEY_LeftShift = 225,
|
||||
KEY_LeftAlt = 226,
|
||||
KEY_LeftGUI = 227,
|
||||
KEY_RightControl = 228,
|
||||
KEY_RightShift = 229,
|
||||
KEY_RightAlt = 230,
|
||||
KEY_RightGUI = 231
|
||||
};
|
||||
#endif
|
77
ios/RetroArch/main.m
Normal file
77
ios/RetroArch/main.m
Normal file
@ -0,0 +1,77 @@
|
||||
/* 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/>.
|
||||
*/
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
#define GSEVENT_TYPE 2
|
||||
#define GSEVENT_FLAGS 12
|
||||
#define GSEVENTKEY_KEYCODE 15
|
||||
#define GSEVENT_TYPE_KEYDOWN 10
|
||||
#define GSEVENT_TYPE_KEYUP 11
|
||||
|
||||
NSString *const GSEventKeyDownNotification = @"GSEventKeyDownHackNotification";
|
||||
NSString *const GSEventKeyUpNotification = @"GSEventKeyUpHackNotification";
|
||||
NSString *const RATouchNotification = @"RATouchNotification";
|
||||
|
||||
@interface RApplication : UIApplication
|
||||
@end
|
||||
|
||||
@implementation RApplication
|
||||
|
||||
- (void)sendEvent:(UIEvent *)event
|
||||
{
|
||||
[super sendEvent:event];
|
||||
|
||||
if ([[event allTouches] count])
|
||||
{
|
||||
NSDictionary* inf = [[NSDictionary alloc] initWithObjectsAndKeys:
|
||||
event, @"event", nil];
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:RATouchNotification object:nil userInfo:inf];
|
||||
}
|
||||
// Stolen from: http://nacho4d-nacho4d.blogspot.com/2012/01/catching-keyboard-events-in-ios.html
|
||||
else if ([event respondsToSelector:@selector(_gsEvent)])
|
||||
{
|
||||
int* eventMem = (int *)(void*)CFBridgingRetain([event performSelector:@selector(_gsEvent)]);
|
||||
int eventType = eventMem ? eventMem[GSEVENT_TYPE] : 0;
|
||||
|
||||
if (eventMem && (eventType == GSEVENT_TYPE_KEYDOWN || eventType == GSEVENT_TYPE_KEYUP))
|
||||
{
|
||||
// Read keycode from GSEventKey
|
||||
int tmp = eventMem[GSEVENTKEY_KEYCODE];
|
||||
UniChar *keycode = (UniChar *)&tmp;
|
||||
|
||||
// Post notification
|
||||
NSDictionary *inf = [[NSDictionary alloc] initWithObjectsAndKeys:
|
||||
[NSNumber numberWithShort:keycode[0]], @"keycode",
|
||||
nil];
|
||||
|
||||
[[NSNotificationCenter defaultCenter]
|
||||
postNotificationName:(eventType == GSEVENT_TYPE_KEYDOWN) ? GSEventKeyDownNotification : GSEventKeyUpNotification
|
||||
object:nil userInfo:inf];
|
||||
}
|
||||
|
||||
CFBridgingRelease(eventMem);
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
@autoreleasepool {
|
||||
return UIApplicationMain(argc, argv, NSStringFromClass([RApplication class]), NSStringFromClass([RetroArch_iOS class]));
|
||||
}
|
||||
}
|
||||
|
28
ios/RetroArch/rarch_wrapper.h
Normal file
28
ios/RetroArch/rarch_wrapper.h
Normal file
@ -0,0 +1,28 @@
|
||||
/* 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 __IOS_RARCH_WRAPPER_H__
|
||||
#define __IOS_RARCH_WRAPPER_H__
|
||||
|
||||
// These functions must only be called in gfx/context/ioseagl_ctx.c
|
||||
|
||||
bool ios_init_game_view();
|
||||
void ios_destroy_game_view();
|
||||
void ios_flip_game_view();
|
||||
void ios_set_game_view_sync(bool on);
|
||||
void ios_get_game_view_size(unsigned *width, unsigned *height);
|
||||
void ios_bind_game_view_fbo();
|
||||
|
||||
#endif
|
177
ios/RetroArch/settings/RAButtonGetter.m
Normal file
177
ios/RetroArch/settings/RAButtonGetter.m
Normal file
@ -0,0 +1,177 @@
|
||||
/* 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/>.
|
||||
*/
|
||||
|
||||
#import "settings.h"
|
||||
#include "../input/keycode.h"
|
||||
|
||||
#ifdef WIIMOTE
|
||||
# include "../input/BTStack/wiimote.h"
|
||||
#endif
|
||||
|
||||
extern NSString* const GSEventKeyUpNotification;
|
||||
|
||||
static const struct
|
||||
{
|
||||
const char* const keyname;
|
||||
const uint32_t hid_id;
|
||||
} ios_key_name_map[] = {
|
||||
{ "left", KEY_Left }, { "right", KEY_Right },
|
||||
{ "up", KEY_Up }, { "down", KEY_Down },
|
||||
{ "enter", KEY_Enter }, { "kp_enter", KP_Enter },
|
||||
{ "space", KEY_Space }, { "tab", KEY_Tab },
|
||||
{ "shift", KEY_LeftShift }, { "rshift", KEY_RightShift },
|
||||
{ "ctrl", KEY_LeftControl }, { "alt", KEY_LeftAlt },
|
||||
{ "escape", KEY_Escape }, { "backspace", KEY_DeleteForward },
|
||||
{ "backquote", KEY_Grave }, { "pause", KEY_Pause },
|
||||
|
||||
{ "f1", KEY_F1 }, { "f2", KEY_F2 },
|
||||
{ "f3", KEY_F3 }, { "f4", KEY_F4 },
|
||||
{ "f5", KEY_F5 }, { "f6", KEY_F6 },
|
||||
{ "f7", KEY_F7 }, { "f8", KEY_F8 },
|
||||
{ "f9", KEY_F9 }, { "f10", KEY_F10 },
|
||||
{ "f11", KEY_F11 }, { "f12", KEY_F12 },
|
||||
|
||||
{ "num0", KEY_0 }, { "num1", KEY_1 },
|
||||
{ "num2", KEY_2 }, { "num3", KEY_3 },
|
||||
{ "num4", KEY_4 }, { "num5", KEY_5 },
|
||||
{ "num6", KEY_6 }, { "num7", KEY_7 },
|
||||
{ "num8", KEY_8 }, { "num9", KEY_9 },
|
||||
|
||||
{ "insert", KEY_Insert }, { "del", KEY_DeleteForward },
|
||||
{ "home", KEY_Home }, { "end", KEY_End },
|
||||
{ "pageup", KEY_PageUp }, { "pagedown", KEY_PageDown },
|
||||
|
||||
{ "add", KP_Add }, { "subtract", KP_Subtract },
|
||||
{ "multiply", KP_Multiply }, { "divide", KP_Divide },
|
||||
{ "keypad0", KP_0 }, { "keypad1", KP_1 },
|
||||
{ "keypad2", KP_2 }, { "keypad3", KP_3 },
|
||||
{ "keypad4", KP_4 }, { "keypad5", KP_5 },
|
||||
{ "keypad6", KP_6 }, { "keypad7", KP_7 },
|
||||
{ "keypad8", KP_8 }, { "keypad9", KP_9 },
|
||||
|
||||
{ "period", KEY_Period }, { "capslock", KEY_CapsLock },
|
||||
{ "numlock", KP_NumLock }, { "print", KEY_PrintScreen },
|
||||
{ "scroll_lock", KEY_ScrollLock },
|
||||
|
||||
{ "a", KEY_A }, { "b", KEY_B }, { "c", KEY_C }, { "d", KEY_D },
|
||||
{ "e", KEY_E }, { "f", KEY_F }, { "g", KEY_G }, { "h", KEY_H },
|
||||
{ "i", KEY_I }, { "j", KEY_J }, { "k", KEY_K }, { "l", KEY_L },
|
||||
{ "m", KEY_M }, { "n", KEY_N }, { "o", KEY_O }, { "p", KEY_P },
|
||||
{ "q", KEY_Q }, { "r", KEY_R }, { "s", KEY_S }, { "t", KEY_T },
|
||||
{ "u", KEY_U }, { "v", KEY_V }, { "w", KEY_W }, { "x", KEY_X },
|
||||
{ "y", KEY_Y }, { "z", KEY_Z },
|
||||
|
||||
{ "nul", 0x00},
|
||||
};
|
||||
|
||||
static NSString* get_key_config_name(uint32_t hid_id)
|
||||
{
|
||||
for (int i = 0; ios_key_name_map[i].hid_id; i ++)
|
||||
if (hid_id == ios_key_name_map[i].hid_id)
|
||||
return [NSString stringWithUTF8String:ios_key_name_map[i].keyname];
|
||||
|
||||
return @"nul";
|
||||
}
|
||||
|
||||
@implementation RAButtonGetter
|
||||
{
|
||||
RAButtonGetter* _me;
|
||||
RASettingData* _value;
|
||||
UIAlertView* _alert;
|
||||
UITableView* _view;
|
||||
bool _finished;
|
||||
#ifdef WIIMOTE
|
||||
NSTimer* _btTimer;
|
||||
#endif
|
||||
}
|
||||
|
||||
- (id)initWithSetting:(RASettingData*)setting fromTable:(UITableView*)table
|
||||
{
|
||||
self = [super init];
|
||||
|
||||
_value = setting;
|
||||
_view = table;
|
||||
_me = self;
|
||||
|
||||
_alert = [[UIAlertView alloc] initWithTitle:@"RetroArch"
|
||||
message:_value.label
|
||||
delegate:self
|
||||
cancelButtonTitle:@"Cancel"
|
||||
otherButtonTitles:nil];
|
||||
[_alert show];
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector: @selector(keyReleased:) name: GSEventKeyUpNotification object: nil];
|
||||
|
||||
#ifdef WIIMOTE
|
||||
_btTimer = [NSTimer scheduledTimerWithTimeInterval:.05f target:self selector:@selector(checkWiiMote) userInfo:nil repeats:YES];
|
||||
#endif
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)finish
|
||||
{
|
||||
if (!_finished)
|
||||
{
|
||||
_finished = true;
|
||||
|
||||
#ifdef WIIMOTE
|
||||
[_btTimer invalidate];
|
||||
#endif
|
||||
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
||||
[_alert dismissWithClickedButtonIndex:0 animated:YES];
|
||||
[_view reloadData];
|
||||
|
||||
_me = nil;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)alertView:(UIAlertView*)alertView willDismissWithButtonIndex:(NSInteger)buttonIndex
|
||||
{
|
||||
[self finish];
|
||||
}
|
||||
|
||||
#ifdef WIIMOTE
|
||||
- (void)checkWiiMote
|
||||
{
|
||||
for (int i = 0; i != myosd_num_of_joys; i ++)
|
||||
{
|
||||
uint32_t buttons = joys[i].btns;
|
||||
buttons |= (joys[i].exp.type == EXP_CLASSIC) ? (joys[i].exp.classic.btns << 16) : 0;
|
||||
|
||||
for (int j = 0; j != sizeof(buttons) * 8; j ++)
|
||||
{
|
||||
if (buttons & (1 << j))
|
||||
{
|
||||
_value.msubValues[1] = [NSString stringWithFormat:@"%d", j];
|
||||
[self finish];
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
- (void)keyReleased:(NSNotification*) notification
|
||||
{
|
||||
int keycode = [[notification.userInfo objectForKey:@"keycode"] intValue];
|
||||
_value.msubValues[0] = get_key_config_name(keycode);
|
||||
|
||||
[self finish];
|
||||
}
|
||||
|
||||
@end
|
||||
|
64
ios/RetroArch/settings/RASettingEnumerationList.m
Normal file
64
ios/RetroArch/settings/RASettingEnumerationList.m
Normal file
@ -0,0 +1,64 @@
|
||||
/* 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/>.
|
||||
*/
|
||||
|
||||
#import "settings.h"
|
||||
|
||||
@implementation RASettingEnumerationList
|
||||
{
|
||||
RASettingData* _value;
|
||||
UITableView* _view;
|
||||
};
|
||||
|
||||
- (id)initWithSetting:(RASettingData*)setting fromTable:(UITableView*)table
|
||||
{
|
||||
self = [super initWithStyle:UITableViewStyleGrouped];
|
||||
|
||||
_value = setting;
|
||||
_view = table;
|
||||
|
||||
[self setTitle: _value.label];
|
||||
return self;
|
||||
}
|
||||
|
||||
- (NSInteger)numberOfSectionsInTableView:(UITableView*)tableView
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
|
||||
- (NSInteger)tableView:(UITableView*)tableView numberOfRowsInSection:(NSInteger)section
|
||||
{
|
||||
return (section == 1) ? [_value.subValues count] : 1;
|
||||
}
|
||||
|
||||
- (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
|
||||
{
|
||||
UITableViewCell* cell = [self.tableView dequeueReusableCellWithIdentifier:@"option"];
|
||||
cell = cell ? cell : [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"option"];
|
||||
|
||||
cell.textLabel.text = (indexPath.section == 1) ? [_value.subValues objectAtIndex:indexPath.row] : @"None";
|
||||
|
||||
return cell;
|
||||
}
|
||||
|
||||
- (void)tableView:(UITableView*)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
|
||||
{
|
||||
_value.value = (indexPath.section == 1) ? [_value.subValues objectAtIndex:indexPath.row] : @"";
|
||||
|
||||
[_view reloadData];
|
||||
[[RetroArch_iOS get] popViewControllerAnimated:YES];
|
||||
}
|
||||
|
||||
@end
|
||||
|
211
ios/RetroArch/settings/RASettingsList.m
Normal file
211
ios/RetroArch/settings/RASettingsList.m
Normal file
@ -0,0 +1,211 @@
|
||||
/* 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/>.
|
||||
*/
|
||||
|
||||
#import <objc/runtime.h>
|
||||
#import "settings.h"
|
||||
|
||||
@implementation RASettingData
|
||||
- (id)initWithType:(enum SettingTypes)aType label:(NSString*)aLabel name:(NSString*)aName
|
||||
{
|
||||
self.type = aType;
|
||||
self.label = aLabel;
|
||||
self.name = aName;
|
||||
return self;
|
||||
}
|
||||
@end
|
||||
|
||||
static NSString* get_value_from_config(RAConfig* config, NSString* name, NSString* defaultValue)
|
||||
{
|
||||
return [config getStringNamed:name withDefault:defaultValue];
|
||||
}
|
||||
|
||||
static RASettingData* boolean_setting(RAConfig* config, NSString* name, NSString* label, NSString* defaultValue)
|
||||
{
|
||||
RASettingData* result = [[RASettingData alloc] initWithType:BooleanSetting label:label name:name];
|
||||
result.value = get_value_from_config(config, name, defaultValue);
|
||||
return result;
|
||||
}
|
||||
|
||||
static RASettingData* button_setting(RAConfig* config, NSString* name, NSString* label, NSString* defaultValue)
|
||||
{
|
||||
RASettingData* result = [[RASettingData alloc] initWithType:ButtonSetting label:label name:name];
|
||||
result.msubValues = [NSMutableArray arrayWithObjects:
|
||||
get_value_from_config(config, name, defaultValue),
|
||||
get_value_from_config(config, [name stringByAppendingString:@"_btn"], @""),
|
||||
nil];
|
||||
return result;
|
||||
}
|
||||
|
||||
static RASettingData* group_setting(NSString* label, NSArray* settings)
|
||||
{
|
||||
RASettingData* result = [[RASettingData alloc] initWithType:GroupSetting label:label name:nil];
|
||||
result.subValues = settings;
|
||||
return result;
|
||||
}
|
||||
|
||||
static RASettingData* enumeration_setting(RAConfig* config, NSString* name, NSString* label, NSString* defaultValue, NSArray* values)
|
||||
{
|
||||
RASettingData* result = [[RASettingData alloc] initWithType:EnumerationSetting label:label name:name];
|
||||
result.value = get_value_from_config(config, name, defaultValue);
|
||||
result.subValues = values;
|
||||
return result;
|
||||
}
|
||||
|
||||
static RASettingData* subpath_setting(RAConfig* config, NSString* name, NSString* label, NSString* defaultValue, NSString* path, NSString* extension)
|
||||
{
|
||||
NSString* value = get_value_from_config(config, name, defaultValue);
|
||||
value = [value stringByReplacingOccurrencesOfString:path withString:@""];
|
||||
|
||||
NSArray* values = [[NSFileManager defaultManager] subpathsOfDirectoryAtPath:path error:nil];
|
||||
values = [values pathsMatchingExtensions:[NSArray arrayWithObject:extension]];
|
||||
|
||||
RASettingData* result = [[RASettingData alloc] initWithType:FileListSetting label:label name:name];
|
||||
result.value = value;
|
||||
result.subValues = values;
|
||||
result.path = path;
|
||||
return result;
|
||||
}
|
||||
|
||||
static RASettingData* aspect_setting(RAConfig* config, NSString* label)
|
||||
{
|
||||
// Why does this need to be so difficult?
|
||||
|
||||
RASettingData* result = [[RASettingData alloc] initWithType:AspectSetting label:label name:@"fram"];
|
||||
result.subValues = [NSArray arrayWithObjects:@"Fill Screen", @"Game Aspect", @"Pixel Aspect", @"4:3", @"16:9", nil];
|
||||
|
||||
bool videoForceAspect = [config getBoolNamed:@"video_force_aspect" withDefault:true];
|
||||
bool videoAspectAuto = [config getBoolNamed:@"video_aspect_ratio_auto" withDefault:false];
|
||||
double videoAspect = [config getDoubleNamed:@"video_aspect_ratio" withDefault:0.0];
|
||||
|
||||
if (!videoForceAspect)
|
||||
result.value = @"Fill Screen";
|
||||
else if (videoAspect < 0.0)
|
||||
result.value = videoAspectAuto ? @"Game Aspect" : @"Pixel Aspect";
|
||||
else
|
||||
result.value = (videoAspect < 1.5) ? @"4:3" : @"16:9";
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static RASettingData* custom_action(NSString* action)
|
||||
{
|
||||
return [[RASettingData alloc] initWithType:CustomAction label:action name:nil];
|
||||
}
|
||||
|
||||
@implementation RASettingsList
|
||||
+ (void)refreshConfigFile
|
||||
{
|
||||
(void)[[RASettingsList alloc] init];
|
||||
}
|
||||
|
||||
- (id)init
|
||||
{
|
||||
RAConfig* config = [[RAConfig alloc] initWithPath:[RetroArch_iOS get].moduleInfo.configPath];
|
||||
|
||||
NSString* overlay_path = [[[NSBundle mainBundle] bundlePath] stringByAppendingString:@"/overlays/"];
|
||||
NSString* shader_path = [[[NSBundle mainBundle] bundlePath] stringByAppendingString:@"/shaders/"];
|
||||
|
||||
NSArray* settings = [NSArray arrayWithObjects:
|
||||
[NSArray arrayWithObjects:@"Frontend",
|
||||
custom_action(@"Module Info"),
|
||||
#ifdef WIIMOTE
|
||||
boolean_setting(config, @"ios_auto_bluetooth", @"Auto Enable Bluetooth", @"false"),
|
||||
#endif
|
||||
nil],
|
||||
|
||||
[NSArray arrayWithObjects:@"Video",
|
||||
boolean_setting(config, @"video_smooth", @"Smooth Video", @"true"),
|
||||
boolean_setting(config, @"video_crop_overscan", @"Crop Overscan", @"true"),
|
||||
boolean_setting(config, @"video_scale_integer", @"Integer Scaling", @"false"),
|
||||
aspect_setting(config, @"Aspect Ratio"),
|
||||
subpath_setting(config, @"video_bsnes_shader", @"Shader", @"", shader_path, @"shader"),
|
||||
nil],
|
||||
|
||||
[NSArray arrayWithObjects:@"Audio",
|
||||
boolean_setting(config, @"audio_enable", @"Enable Output", @"true"),
|
||||
boolean_setting(config, @"audio_sync", @"Sync on Audio Stream", @"true"),
|
||||
boolean_setting(config, @"audio_rate_control", @"Adjust for Better Sync", @"true"),
|
||||
nil],
|
||||
|
||||
[NSArray arrayWithObjects:@"Input",
|
||||
subpath_setting(config, @"input_overlay", @"Input Overlay", @"", overlay_path, @"cfg"),
|
||||
group_setting(@"Player 1 Keys", [NSArray arrayWithObjects:
|
||||
[NSArray arrayWithObjects:@"Player 1",
|
||||
button_setting(config, @"input_player1_up", @"Up", @"up"),
|
||||
button_setting(config, @"input_player1_down", @"Down", @"down"),
|
||||
button_setting(config, @"input_player1_left", @"Left", @"left"),
|
||||
button_setting(config, @"input_player1_right", @"Right", @"right"),
|
||||
|
||||
button_setting(config, @"input_player1_start", @"Start", @"enter"),
|
||||
button_setting(config, @"input_player1_select", @"Select", @"rshift"),
|
||||
|
||||
button_setting(config, @"input_player1_b", @"B", @"z"),
|
||||
button_setting(config, @"input_player1_a", @"A", @"x"),
|
||||
button_setting(config, @"input_player1_x", @"X", @"s"),
|
||||
button_setting(config, @"input_player1_y", @"Y", @"a"),
|
||||
|
||||
button_setting(config, @"input_player1_l", @"L", @"q"),
|
||||
button_setting(config, @"input_player1_r", @"R", @"w"),
|
||||
button_setting(config, @"input_player1_l2", @"L2", @""),
|
||||
button_setting(config, @"input_player1_r2", @"R2", @""),
|
||||
button_setting(config, @"input_player1_l3", @"L3", @""),
|
||||
button_setting(config, @"input_player1_r3", @"R3", @""),
|
||||
nil],
|
||||
nil]),
|
||||
group_setting(@"System Keys", [NSArray arrayWithObjects:
|
||||
[NSArray arrayWithObjects:@"System Keys",
|
||||
button_setting(config, @"input_save_state", @"Save State", @"f2"),
|
||||
button_setting(config, @"input_load_state", @"Load State", @"f4"),
|
||||
button_setting(config, @"input_state_slot_increase", @"Next State Slot", @"f7"),
|
||||
button_setting(config, @"input_state_slot_decrease", @"Previous State Slot", @"f6"),
|
||||
button_setting(config, @"input_toggle_fast_forward", @"Toggle Fast Forward", @"space"),
|
||||
button_setting(config, @"input_hold_fast_forward", @"Hold Fast Forward", @"l"),
|
||||
button_setting(config, @"input_rewind", @"Rewind", @"r"),
|
||||
button_setting(config, @"input_slowmotion", @"Slow Motion", @"e"),
|
||||
button_setting(config, @"input_reset", @"Reset", @"h"),
|
||||
button_setting(config, @"input_exit_emulator", @"Close Game", @"escape"),
|
||||
nil],
|
||||
nil]),
|
||||
nil],
|
||||
|
||||
[NSArray arrayWithObjects:@"Save States",
|
||||
boolean_setting(config, @"rewind_enable", @"Enable Rewinding", @"false"),
|
||||
boolean_setting(config, @"block_sram_overwrite", @"Disable SRAM on Load", @"false"),
|
||||
boolean_setting(config, @"savestate_auto_save", @"Auto Save on Exit", @"false"),
|
||||
boolean_setting(config, @"savestate_auto_load", @"Auto Load on Startup", @"true"),
|
||||
nil],
|
||||
nil
|
||||
];
|
||||
|
||||
self = [super initWithSettings:settings title:@"RetroArch Settings"];
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
RAConfig* config = [[RAConfig alloc] initWithPath:[RetroArch_iOS get].moduleInfo.configPath];
|
||||
[config putStringNamed:@"system_directory" value:[RetroArch_iOS get].system_directory];
|
||||
[self writeSettings:nil toConfig:config];
|
||||
[config writeToFile:[RetroArch_iOS get].moduleInfo.configPath];
|
||||
[[RetroArch_iOS get] refreshConfig];
|
||||
}
|
||||
|
||||
- (void)handleCustomAction:(NSString*)action
|
||||
{
|
||||
if ([@"Module Info" isEqualToString:action])
|
||||
[[RetroArch_iOS get] pushViewController:[[RAModuleInfoList alloc] initWithModuleInfo:[RetroArch_iOS get].moduleInfo] animated:YES];
|
||||
}
|
||||
|
||||
@end
|
210
ios/RetroArch/settings/RASettingsSubList.m
Normal file
210
ios/RetroArch/settings/RASettingsSubList.m
Normal file
@ -0,0 +1,210 @@
|
||||
/* 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/>.
|
||||
*/
|
||||
|
||||
#import <objc/runtime.h>
|
||||
#import "settings.h"
|
||||
|
||||
static const char* const SETTINGID = "SETTING";
|
||||
|
||||
@implementation RASettingsSubList
|
||||
{
|
||||
NSArray* settings;
|
||||
};
|
||||
|
||||
- (id)initWithSettings:(NSArray*)values title:(NSString*)title
|
||||
{
|
||||
self = [super initWithStyle:UITableViewStyleGrouped];
|
||||
settings = values;
|
||||
|
||||
[self setTitle:title];
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)handleCustomAction:(NSString*)action
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
- (void)writeSettings:(NSArray*)settingList toConfig:(RAConfig*)config
|
||||
{
|
||||
NSArray* list = settingList ? settingList : settings;
|
||||
|
||||
for (int i = 0; i != [list count]; i ++)
|
||||
{
|
||||
NSArray* group = [list objectAtIndex:i];
|
||||
|
||||
for (int j = 1; j < [group count]; j ++)
|
||||
{
|
||||
RASettingData* setting = [group objectAtIndex:j];
|
||||
|
||||
switch (setting.type)
|
||||
{
|
||||
case GroupSetting:
|
||||
[self writeSettings:setting.subValues toConfig:config];
|
||||
break;
|
||||
|
||||
case FileListSetting:
|
||||
if ([setting.value length] > 0)
|
||||
[config putStringNamed:setting.name value:[setting.path stringByAppendingPathComponent:setting.value]];
|
||||
else
|
||||
[config putStringNamed:setting.name value:@""];
|
||||
break;
|
||||
|
||||
case ButtonSetting:
|
||||
if (setting.msubValues[0] && [setting.msubValues[0] length])
|
||||
[config putStringNamed:setting.name value:setting.msubValues[0]];
|
||||
if (setting.msubValues[1] && [setting.msubValues[1] length])
|
||||
[config putStringNamed:[setting.name stringByAppendingString:@"_btn"] value:setting.msubValues[1]];
|
||||
break;
|
||||
|
||||
case AspectSetting:
|
||||
[config putStringNamed:@"video_force_aspect" value:[@"Fill Screen" isEqualToString:setting.value] ? @"false" : @"true"];
|
||||
[config putStringNamed:@"video_aspect_ratio_auto" value:[@"Game Aspect" isEqualToString:setting.value] ? @"true" : @"false"];
|
||||
[config putStringNamed:@"video_aspect_ratio" value:@"-1.0"];
|
||||
if([@"4:3" isEqualToString:setting.value])
|
||||
[config putStringNamed:@"video_aspect_ratio" value:@"1.33333333"];
|
||||
else if([@"16:9" isEqualToString:setting.value])
|
||||
[config putStringNamed:@"video_aspect_ratio" value:@"1.777777777"];
|
||||
break;
|
||||
|
||||
case CustomAction:
|
||||
break;
|
||||
|
||||
default:
|
||||
[config putStringNamed:setting.name value:setting.value];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)tableView:(UITableView*)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
|
||||
{
|
||||
RASettingData* setting = [[settings objectAtIndex:indexPath.section] objectAtIndex:indexPath.row + 1];
|
||||
|
||||
switch (setting.type)
|
||||
{
|
||||
case EnumerationSetting:
|
||||
case FileListSetting:
|
||||
case AspectSetting:
|
||||
[[RetroArch_iOS get] pushViewController:[[RASettingEnumerationList alloc] initWithSetting:setting fromTable:(UITableView*)self.view] animated:YES];
|
||||
break;
|
||||
|
||||
case ButtonSetting:
|
||||
(void)[[RAButtonGetter alloc] initWithSetting:setting fromTable:(UITableView*)self.view];
|
||||
break;
|
||||
|
||||
case GroupSetting:
|
||||
[[RetroArch_iOS get] pushViewController:[[RASettingsSubList alloc] initWithSettings:setting.subValues title:setting.label] animated:YES];
|
||||
break;
|
||||
|
||||
case CustomAction:
|
||||
[self handleCustomAction:setting.label];
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)handleBooleanSwitch:(UISwitch*)swt
|
||||
{
|
||||
RASettingData* setting = objc_getAssociatedObject(swt, SETTINGID);
|
||||
setting.value = (swt.on ? @"true" : @"false");
|
||||
}
|
||||
|
||||
- (UITableViewCell*)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
|
||||
{
|
||||
RASettingData* setting = [[settings objectAtIndex:indexPath.section] objectAtIndex:indexPath.row + 1];
|
||||
|
||||
UITableViewCell* cell = nil;
|
||||
|
||||
switch (setting.type)
|
||||
{
|
||||
case BooleanSetting:
|
||||
{
|
||||
cell = [self.tableView dequeueReusableCellWithIdentifier:@"boolean"];
|
||||
|
||||
if (cell == nil)
|
||||
{
|
||||
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"boolean"];
|
||||
|
||||
UISwitch* accessory = [[UISwitch alloc] init];
|
||||
[accessory addTarget:self action:@selector(handleBooleanSwitch:) forControlEvents:UIControlEventValueChanged];
|
||||
cell.accessoryView = accessory;
|
||||
|
||||
[cell setSelectionStyle:UITableViewCellSelectionStyleNone];
|
||||
}
|
||||
|
||||
UISwitch* swt = (UISwitch*)cell.accessoryView;
|
||||
swt.on = [setting.value isEqualToString:@"true"];
|
||||
objc_setAssociatedObject(swt, SETTINGID, setting, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
|
||||
}
|
||||
break;
|
||||
|
||||
case EnumerationSetting:
|
||||
case FileListSetting:
|
||||
case ButtonSetting:
|
||||
case CustomAction:
|
||||
case AspectSetting:
|
||||
{
|
||||
cell = [self.tableView dequeueReusableCellWithIdentifier:@"enumeration"];
|
||||
cell = cell ? cell : [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:@"enumeration"];
|
||||
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
|
||||
}
|
||||
break;
|
||||
|
||||
case GroupSetting:
|
||||
{
|
||||
cell = [self.tableView dequeueReusableCellWithIdentifier:@"group"];
|
||||
|
||||
if (cell == nil)
|
||||
{
|
||||
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:@"group"];
|
||||
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
cell.textLabel.text = setting.label;
|
||||
|
||||
if (setting.type != ButtonSetting)
|
||||
cell.detailTextLabel.text = setting.value;
|
||||
else
|
||||
cell.detailTextLabel.text = [NSString stringWithFormat:@"[KB:%@] [JS:%@]",
|
||||
[setting.msubValues[0] length] ? setting.msubValues[0] : @"N/A",
|
||||
[setting.msubValues[1] length] ? setting.msubValues[1] : @"N/A"];
|
||||
|
||||
return cell;
|
||||
}
|
||||
|
||||
// UITableView item counts
|
||||
- (NSInteger)numberOfSectionsInTableView:(UITableView*)tableView
|
||||
{
|
||||
return [settings count];
|
||||
}
|
||||
|
||||
- (NSInteger)tableView:(UITableView*)tableView numberOfRowsInSection:(NSInteger)section
|
||||
{
|
||||
return [[settings objectAtIndex:section] count] -1;
|
||||
}
|
||||
|
||||
- (NSString*)tableView:(UITableView*)tableView titleForHeaderInSection:(NSInteger)section
|
||||
{
|
||||
return [[settings objectAtIndex:section] objectAtIndex:0];
|
||||
}
|
||||
|
||||
@end
|
52
ios/RetroArch/settings/settings.h
Normal file
52
ios/RetroArch/settings/settings.h
Normal file
@ -0,0 +1,52 @@
|
||||
/* 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/>.
|
||||
*/
|
||||
|
||||
enum SettingTypes
|
||||
{
|
||||
BooleanSetting, ButtonSetting, EnumerationSetting, FileListSetting,
|
||||
GroupSetting, AspectSetting, CustomAction
|
||||
};
|
||||
|
||||
@interface RASettingData : NSObject
|
||||
@property enum SettingTypes type;
|
||||
|
||||
@property (strong) NSString* label;
|
||||
@property (strong) NSString* name;
|
||||
@property (strong) NSString* value;
|
||||
|
||||
@property (strong) NSString* path;
|
||||
@property (strong) NSArray* subValues;
|
||||
@property (strong) NSMutableArray* msubValues;
|
||||
|
||||
- (id)initWithType:(enum SettingTypes)aType label:(NSString*)aLabel name:(NSString*)aName;
|
||||
@end
|
||||
|
||||
@interface RAButtonGetter : NSObject<UIAlertViewDelegate>
|
||||
- (id)initWithSetting:(RASettingData*)setting fromTable:(UITableView*)table;
|
||||
@end
|
||||
|
||||
@interface RASettingEnumerationList : UITableViewController
|
||||
- (id)initWithSetting:(RASettingData*)setting fromTable:(UITableView*)table;
|
||||
@end
|
||||
|
||||
@interface RASettingsSubList : UITableViewController
|
||||
- (id)initWithSettings:(NSArray*)values title:(NSString*)title;
|
||||
- (void)handleCustomAction:(NSString*)action;
|
||||
- (void)writeSettings:(NSArray*)settingList toConfig:(RAConfig*)config;
|
||||
@end
|
||||
|
||||
@interface RASettingsList : RASettingsSubList
|
||||
+ (void)refreshConfigFile;
|
||||
@end
|
40
ios/RetroArch/views.h
Normal file
40
ios/RetroArch/views.h
Normal file
@ -0,0 +1,40 @@
|
||||
/* 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/>.
|
||||
*/
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import <GLKit/GLKit.h>
|
||||
|
||||
#import "RAConfig.h"
|
||||
|
||||
@interface RAGameView : UIViewController
|
||||
+ (RAGameView*)get;
|
||||
- (void)openPauseMenu;
|
||||
- (void)closePauseMenu;
|
||||
@end
|
||||
|
||||
@interface RAModuleInfo : NSObject
|
||||
@property (strong) NSString* displayName;
|
||||
@property (strong) NSString* path;
|
||||
@property (strong) NSString* configPath;
|
||||
@property (strong) RAConfig* data;
|
||||
@property (strong) NSArray* supportedExtensions;
|
||||
|
||||
+ (RAModuleInfo*)moduleWithPath:(NSString*)thePath data:(RAConfig*)theData;
|
||||
- (bool)supportsFileAtPath:(NSString*)path;
|
||||
@end
|
||||
|
||||
@interface RAModuleInfoList : UITableViewController
|
||||
- (id)initWithModuleInfo:(RAModuleInfo*)info;
|
||||
@end
|
5
ios/modules/desmume_libretro.info
Normal file
5
ios/modules/desmume_libretro.info
Normal file
@ -0,0 +1,5 @@
|
||||
display_name = "Nintendo DS"
|
||||
recommended_extensions = "nds"
|
||||
emuname = "DeSmuME"
|
||||
manufacturer = "Nintendo"
|
||||
systemname = "Nintendo DS"
|
17
ios/modules/example.info
Normal file
17
ios/modules/example.info
Normal file
@ -0,0 +1,17 @@
|
||||
## All data is optional, but helps improve user experience.
|
||||
|
||||
# Name displayed when the user is selecting an emulator.
|
||||
# display_name = "NES / Famicom"
|
||||
|
||||
# List of supported extensions.
|
||||
# supported_extensions = "nes|fds"
|
||||
|
||||
# Name the emulator core.
|
||||
# emuname = "Nestopia"
|
||||
|
||||
# The developer of the emulated device.
|
||||
# manufacturer = "Nintendo"
|
||||
|
||||
# The name of the emulated device.
|
||||
# systemname = "Nintendo Entertainment System"
|
||||
|
5
ios/modules/gambatte_libretro.info
Normal file
5
ios/modules/gambatte_libretro.info
Normal file
@ -0,0 +1,5 @@
|
||||
display_name = "Game Boy / Game Boy Color"
|
||||
supported_extensions = "gb|gbc|dmg"
|
||||
emuname = "gambatte"
|
||||
manufacturer = "Nintendo"
|
||||
systemname = "Game Boy Color"
|
6
ios/modules/genesis_plus_gx_libretro.info
Normal file
6
ios/modules/genesis_plus_gx_libretro.info
Normal file
@ -0,0 +1,6 @@
|
||||
display_name = "Sega (MS/GG/MD/CD)"
|
||||
supported_extensions = "md|smd|gen|sms|gg|sg|bin|cue|ios"
|
||||
emuname = "Genesis Plus GX"
|
||||
manufacturer = "Sega"
|
||||
systemname = "Sega (Various)"
|
||||
|
6
ios/modules/mednafen_ngp_libretro.info
Normal file
6
ios/modules/mednafen_ngp_libretro.info
Normal file
@ -0,0 +1,6 @@
|
||||
display_name = "Neo Geo Pocket (Color)"
|
||||
supported_extensions = "ngp|ngc"
|
||||
emuname = "Mednafen Neopop"
|
||||
manufacturer = "SNK"
|
||||
systemname = "Neo Geo Pocket (Color)"
|
||||
|
6
ios/modules/mednafen_pce_fast_libretro.info
Normal file
6
ios/modules/mednafen_pce_fast_libretro.info
Normal file
@ -0,0 +1,6 @@
|
||||
display_name = "PC Engine/TurboGrafx-16"
|
||||
supported_extensions = "pce|sgx|cue"
|
||||
emuname = "Mednafen PCE Fast"
|
||||
manufacturer = "NEC"
|
||||
systemname = "PC Engine/TurboGrafx-16"
|
||||
|
6
ios/modules/mednafen_psx_libretro.info
Normal file
6
ios/modules/mednafen_psx_libretro.info
Normal file
@ -0,0 +1,6 @@
|
||||
display_name = "PlayStation"
|
||||
supported_extensions = "cue|toc"
|
||||
emuname = "Mednafen PSX"
|
||||
manufacturer = "Sony"
|
||||
systemname = "PlayStation"
|
||||
|
6
ios/modules/mednafen_vb_libretro.info
Normal file
6
ios/modules/mednafen_vb_libretro.info
Normal file
@ -0,0 +1,6 @@
|
||||
display_name = "Virtual Boy"
|
||||
supported_extensions = "vb|vboy|bin"
|
||||
emuname = "Mednafen VB"
|
||||
manufacturer = "Nintendo"
|
||||
systemname = "Virtual Boy"
|
||||
|
6
ios/modules/mednafen_wswan_libretro.info
Normal file
6
ios/modules/mednafen_wswan_libretro.info
Normal file
@ -0,0 +1,6 @@
|
||||
display_name = "WonderSwan (Color)"
|
||||
supported_extensions = "ws|wsc"
|
||||
emuname = "Mednafen WonderSwan"
|
||||
manufacturer = "Bandai"
|
||||
systemname = "WonderSwan (Color)"
|
||||
|
6
ios/modules/nestopia_libretro.info
Normal file
6
ios/modules/nestopia_libretro.info
Normal file
@ -0,0 +1,6 @@
|
||||
display_name = "NES / Famicom"
|
||||
supported_extensions = "nes|fds"
|
||||
emuname = "Nestopia"
|
||||
manufacturer = "Nintendo"
|
||||
systemname = "Nintendo Entertainment System"
|
||||
|
3
ios/modules/nxengine_libretro.info
Normal file
3
ios/modules/nxengine_libretro.info
Normal file
@ -0,0 +1,3 @@
|
||||
display_name = "NXEngine (Cave Story)"
|
||||
supported_extensions = "exe"
|
||||
emuname = "NXEngine"
|
3
ios/modules/prboom_libretro.info
Normal file
3
ios/modules/prboom_libretro.info
Normal file
@ -0,0 +1,3 @@
|
||||
display_name = "PrBoom (DOOM)"
|
||||
supported_extensions = "wad|iwad"
|
||||
emuname = "prboom"
|
5
ios/modules/snes9x_next_libretro.info
Normal file
5
ios/modules/snes9x_next_libretro.info
Normal file
@ -0,0 +1,5 @@
|
||||
display_name = "SNES / Super Famicom"
|
||||
supported_extensions = "smc|fig|sfc|gd3|gd7|dx2|bsx|swc"
|
||||
emuname = "SNES9x Next"
|
||||
manufacturer = "Nintendo"
|
||||
systemname = "Super Nintendo Entertainment System"
|
6
ios/modules/stella_libretro.info
Normal file
6
ios/modules/stella_libretro.info
Normal file
@ -0,0 +1,6 @@
|
||||
display_name = "Atari 2600"
|
||||
supported_extensions = "a26|bin"
|
||||
emuname = "Stella"
|
||||
manufacturer = "Atari"
|
||||
systemname = "Atari 2600"
|
||||
|
3
ios/modules/tyrquake_libretro.info
Normal file
3
ios/modules/tyrquake_libretro.info
Normal file
@ -0,0 +1,3 @@
|
||||
display_name = "TyrQuake"
|
||||
supported_extensions = "pak"
|
||||
emuname = "prboom"
|
5
ios/modules/vba_next_libretro.info
Normal file
5
ios/modules/vba_next_libretro.info
Normal file
@ -0,0 +1,5 @@
|
||||
display_name = "Game Boy Advance"
|
||||
supported_extensions = "gba"
|
||||
emuname = "VBA Next"
|
||||
manufacturer = "Nintendo"
|
||||
systemname = "Game Boy Advance"
|
@ -130,6 +130,8 @@ const char *config_get_default_input(void)
|
||||
return "gx";
|
||||
case INPUT_LINUXRAW:
|
||||
return "linuxraw";
|
||||
case INPUT_IOS:
|
||||
return "ios_input";
|
||||
case INPUT_NULL:
|
||||
return "null";
|
||||
default:
|
||||
|
Loading…
x
Reference in New Issue
Block a user