diff --git a/audio/coreaudio.c b/audio/coreaudio.c index f3bbaddd72..239a421218 100644 --- a/audio/coreaudio.c +++ b/audio/coreaudio.c @@ -22,8 +22,7 @@ #include "../boolean.h" #include -#include -#include +#include #include #include @@ -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; diff --git a/config.def.h b/config.def.h index 78369860c5..f10124c670 100644 --- a/config.def.h +++ b/config.def.h @@ -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 diff --git a/driver.c b/driver.c index 3c36cf243d..91b3e90fb1 100644 --- a/driver.c +++ b/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 diff --git a/driver.h b/driver.h index 1767f2fc9c..420117565c 100644 --- a/driver.h +++ b/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" diff --git a/gfx/context/ioseagl_ctx.c b/gfx/context/ioseagl_ctx.c new file mode 100644 index 0000000000..1932e1e9d4 --- /dev/null +++ b/gfx/context/ioseagl_ctx.c @@ -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 . + */ + +#include "../../driver.h" +#include "../gfx_common.h" +#include "../gl_common.h" +#include "../image.h" + +#include "../fonts/gl_font.h" +#include + +#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", +}; diff --git a/gfx/gfx_context.c b/gfx/gfx_context.c index 94808e85e1..628705142c 100644 --- a/gfx/gfx_context.c +++ b/gfx/gfx_context.c @@ -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) diff --git a/gfx/gfx_context.h b/gfx/gfx_context.h index 2b2f3346c8..5f66342239 100644 --- a/gfx/gfx_context.h +++ b/gfx/gfx_context.h @@ -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. diff --git a/gfx/gl.c b/gfx/gl.c index 6d845a4e3e..e36121ea3b 100644 --- a/gfx/gl.c +++ b/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]); diff --git a/gfx/gl_common.h b/gfx/gl_common.h index 68dfc02630..2869b6dcd9 100644 --- a/gfx/gl_common.h +++ b/gfx/gl_common.h @@ -34,7 +34,10 @@ #include #endif -#if defined(__APPLE__) +#if defined(IOS) +#include +#include +#elif defined(__APPLE__) #include #include #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 diff --git a/gfx/shader_glsl.c b/gfx/shader_glsl.c index 4de50804a2..4bb7ff2667 100644 --- a/gfx/shader_glsl.c +++ b/gfx/shader_glsl.c @@ -27,7 +27,10 @@ #include "../config.h" #endif -#if defined(__APPLE__) // Because they like to be "oh, so, special". +#if defined(IOS) +#include +#include +#elif defined(__APPLE__) // Because they like to be "oh, so, special". #include #include #elif defined(HAVE_PSGL) diff --git a/ios/Assets/Default-568h@2x.png b/ios/Assets/Default-568h@2x.png new file mode 100644 index 0000000000..0891b7aabf Binary files /dev/null and b/ios/Assets/Default-568h@2x.png differ diff --git a/ios/Assets/Default.png b/ios/Assets/Default.png new file mode 100644 index 0000000000..4c8ca6f693 Binary files /dev/null and b/ios/Assets/Default.png differ diff --git a/ios/Assets/Default@2x.png b/ios/Assets/Default@2x.png new file mode 100644 index 0000000000..35b84cffeb Binary files /dev/null and b/ios/Assets/Default@2x.png differ diff --git a/ios/Assets/Icon-72.png b/ios/Assets/Icon-72.png new file mode 100644 index 0000000000..a0c2cc6e22 Binary files /dev/null and b/ios/Assets/Icon-72.png differ diff --git a/ios/Assets/Icon.png b/ios/Assets/Icon.png new file mode 100644 index 0000000000..690f28b4b3 Binary files /dev/null and b/ios/Assets/Icon.png differ diff --git a/ios/Assets/PauseIndicatorView.xib b/ios/Assets/PauseIndicatorView.xib new file mode 100644 index 0000000000..36e8e50925 --- /dev/null +++ b/ios/Assets/PauseIndicatorView.xib @@ -0,0 +1,261 @@ + + + + 1552 + 12C60 + 3084 + 1187.34 + 625.00 + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + 2083 + + + IBNSLayoutConstraint + IBProxyObject + IBUIButton + IBUIView + + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + + PluginDependencyRecalculationVersion + + + + + IBFilesOwner + IBIPadFramework + + + IBFirstResponder + IBIPadFramework + + + + 274 + + + + 292 + {768, 1005} + + _NS:9 + + 3 + MCAwAA + + NO + 5 + IBIPadFramework + 0 + 0 + + 3 + MQA + + + 1 + MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA + + + + NSImage + ic_pause.png + + + 2 + 15 + + + Helvetica-Bold + 15 + 16 + + + + {{0, 20}, {768, 1004}} + + + {250, 250} + + NO + 0.0 + + 2 + + IBIPadFramework + + + + + + + showPauseMenu: + + + 7 + + 71 + + + + + + 0 + + + + + + 1 + + + + + 10 + 0 + + 10 + 1 + + 0.0 + + 1000 + + 5 + 22 + 2 + + + + 3 + 0 + + 3 + 1 + + 0.0 + + 1000 + + 8 + 29 + 3 + + + + 5 + 0 + + 5 + 1 + + 0.0 + + 1000 + + 8 + 29 + 3 + + + + 6 + 0 + + 6 + 1 + + 0.0 + + 1000 + + 8 + 29 + 3 + + + + + + + -1 + + + File's Owner + + + -2 + + + + + 54 + + + + + + 61 + + + + + 63 + + + + + 69 + + + + + 72 + + + + + + + RetroArch_iOS + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + UIResponder + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + + + + + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + + + + + 72 + + + 0 + IBIPadFramework + YES + 3 + + ic_pause.png + {100, 40} + + YES + 2083 + + diff --git a/ios/Assets/PauseView.xib b/ios/Assets/PauseView.xib new file mode 100644 index 0000000000..238b0695a3 --- /dev/null +++ b/ios/Assets/PauseView.xib @@ -0,0 +1,950 @@ + + + + 1552 + 12C60 + 3084 + 1187.34 + 625.00 + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + 2083 + + + IBNSLayoutConstraint + IBProxyObject + IBUIButton + IBUISegmentedControl + IBUIView + + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + + PluginDependencyRecalculationVersion + + + + + IBFilesOwner + IBIPadFramework + + + IBFirstResponder + IBIPadFramework + + + + 274 + + + + 292 + {{160, 237}, {120, 44}} + + + _NS:9 + NO + IBIPadFramework + 0 + 0 + 1 + Exit + + 3 + MQA + + + 1 + MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA + + + 3 + MC41AA + + + 2 + 15 + + + Helvetica-Bold + 15 + 16 + + + + + 292 + {{20, 20}, {260, 44}} + + + _NS:9 + NO + IBIPadFramework + 0 + 0 + 1 + Resume Game + + + 1 + MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA + + + + + + + + 292 + {{20, 237}, {120, 44}} + + + _NS:9 + NO + IBIPadFramework + 0 + 0 + 1 + Reset + + + 1 + MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA + + + + + + + + 292 + {{20, 186}, {120, 44}} + + + _NS:9 + NO + IBIPadFramework + 0 + 0 + 1 + Save State + + + 1 + MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA + + + + + + + + 292 + {{160, 186}, {120, 44}} + + + _NS:9 + NO + IBIPadFramework + 0 + 0 + 1 + Load State + + + 1 + MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA + + + + + + + + 292 + {{20, 135}, {260, 44}} + + + _NS:9 + NO + 1 + IBIPadFramework + 10 + 0 + + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + + + + + + + + + + + + + + + + + + + + + + + + + + + {0, 0} + {0, 0} + {0, 0} + {0, 0} + {0, 0} + {0, 0} + {0, 0} + {0, 0} + {0, 0} + {0, 0} + + + + + + + + + + + + + + + + + 292 + {{20, 71}, {260, 44}} + + + _NS:9 + NO + IBIPadFramework + 0 + 0 + 1 + Settings + + + 1 + MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA + + + + + + + {{0, 20}, {300, 300}} + + + + 3 + MQA + + 2 + + + NO + 0.0 + + 2 + + + IBUISimulatedFreeformSizeMetricsSentinel + Freeform + + IBIPadFramework + + + + + + + closeGamePressed: + + + 7 + + 23 + + + + closePauseMenu: + + + 7 + + 25 + + + + resetGame: + + + 7 + + 138 + + + + saveState: + + + 7 + + 137 + + + + loadState: + + + 7 + + 136 + + + + chooseState: + + + 13 + + 139 + + + + showSettings + + + 7 + + 148 + + + + + + 0 + + + + + + 1 + + + + + 5 + 0 + + 5 + 1 + + 0.0 + + 1000 + + 6 + 24 + 2 + + + + 4 + 0 + + 4 + 1 + + 20 + + 1000 + + 8 + 29 + 3 + + + + 6 + 0 + + 6 + 1 + + 20 + + 1000 + + 8 + 29 + 3 + + + + 6 + 0 + + 6 + 1 + + 20 + + 1000 + + 8 + 29 + 3 + + + + 11 + 0 + + 11 + 1 + + 0.0 + + 1000 + + 6 + 24 + 2 + + + + 4 + 0 + + 4 + 1 + + 20 + + 1000 + + 8 + 29 + 3 + + + + 3 + 0 + + 4 + 1 + + 8 + + 1000 + + 6 + 24 + 3 + + + + 5 + 0 + + 5 + 1 + + 20 + + 1000 + + 8 + 29 + 3 + + + + 3 + 0 + + 4 + 1 + + 8 + + 1000 + + 6 + 24 + 3 + + + + 6 + 0 + + 6 + 1 + + 0.0 + + 1000 + + 6 + 24 + 2 + + + + 5 + 0 + + 5 + 1 + + 20 + + 1000 + + 8 + 29 + 3 + + + + 6 + 0 + + 6 + 1 + + 20 + + 1000 + + 8 + 29 + 3 + + + + 5 + 0 + + 5 + 1 + + 20 + + 1000 + + 8 + 29 + 3 + + + + 5 + 0 + + 5 + 1 + + 20 + + 1000 + + 8 + 29 + 3 + + + + 6 + 0 + + 6 + 1 + + 20 + + 1000 + + 8 + 29 + 3 + + + + 3 + 0 + + 4 + 1 + + 8 + + 1000 + + 6 + 24 + 3 + + + + 6 + 0 + + 6 + 1 + + 20 + + 1000 + + 8 + 29 + 3 + + + + 5 + 0 + + 5 + 1 + + 20 + + 1000 + + 8 + 29 + 3 + + + + 3 + 0 + + 3 + 1 + + 20 + + 1000 + + 8 + 29 + 3 + + + + + + + + + + + + + -1 + + + File's Owner + + + -2 + + + + + 12 + + + + + + 17 + + + + + + 30 + + + + + + 86 + + + + + 7 + 0 + + 0 + 1 + + 120 + + 1000 + + 3 + 9 + 1 + + + + + + 88 + + + + + 89 + + + + + 94 + + + + + 97 + + + + + 98 + + + + + 113 + + + + + 115 + + + + + 116 + + + + + 118 + + + + + 119 + + + + + 121 + + + + + 122 + + + + + 7 + 0 + + 0 + 1 + + 120 + + 1000 + + 3 + 9 + 1 + + + + + + 125 + + + + + 127 + + + + + 129 + + + + + 130 + + + + + 131 + + + + + 132 + + + + + 133 + + + + + 135 + + + + + 140 + + + + + + 142 + + + + + 143 + + + + + 146 + + + + + + + RetroArch_iOS + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + UIResponder + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + + + + + + + + + + + + + + + + + + + + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + + + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + + + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + + + + + 148 + + + 0 + IBIPadFramework + YES + 3 + YES + 2083 + + diff --git a/ios/Assets/ic_pause.png b/ios/Assets/ic_pause.png new file mode 100644 index 0000000000..b024ca8713 Binary files /dev/null and b/ios/Assets/ic_pause.png differ diff --git a/ios/BUILDING b/ios/BUILDING new file mode 100644 index 0000000000..aa1e6fb3d0 --- /dev/null +++ b/ios/BUILDING @@ -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. + diff --git a/ios/RetroArch.xcodeproj/project.pbxproj b/ios/RetroArch.xcodeproj/project.pbxproj new file mode 100644 index 0000000000..e87846a05f --- /dev/null +++ b/ios/RetroArch.xcodeproj/project.pbxproj @@ -0,0 +1,1301 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 96096DD816D1ABAF00BF4499 /* RAModuleInfoList.m in Sources */ = {isa = PBXBuildFile; fileRef = 96096DD716D1ABAF00BF4499 /* RAModuleInfoList.m */; }; + 9614C6C416DDC018000B36EF /* autosave.c in Sources */ = {isa = PBXBuildFile; fileRef = 96AFAE9D16C1D9A9009DE44C /* autosave.c */; }; + 9614C6C516DDC018000B36EF /* cheats.c in Sources */ = {isa = PBXBuildFile; fileRef = 96AFAEA016C1D9A9009DE44C /* cheats.c */; }; + 9614C6C616DDC018000B36EF /* command.c in Sources */ = {isa = PBXBuildFile; fileRef = 96AFAEA216C1D9A9009DE44C /* command.c */; }; + 9614C6C716DDC018000B36EF /* driver.c in Sources */ = {isa = PBXBuildFile; fileRef = 96AFAEA716C1D9A9009DE44C /* driver.c */; }; + 9614C6C816DDC018000B36EF /* dynamic.c in Sources */ = {isa = PBXBuildFile; fileRef = 96AFAEA916C1D9A9009DE44C /* dynamic.c */; }; + 9614C6C916DDC018000B36EF /* fifo_buffer.c in Sources */ = {isa = PBXBuildFile; fileRef = 96AFAEAB16C1D9A9009DE44C /* fifo_buffer.c */; }; + 9614C6CA16DDC018000B36EF /* file_extract.c in Sources */ = {isa = PBXBuildFile; fileRef = 96AFAEAD16C1D9A9009DE44C /* file_extract.c */; }; + 9614C6CB16DDC018000B36EF /* file_path.c in Sources */ = {isa = PBXBuildFile; fileRef = 96AFAEAF16C1D9A9009DE44C /* file_path.c */; }; + 9614C6CC16DDC018000B36EF /* file.c in Sources */ = {isa = PBXBuildFile; fileRef = 96AFAEB016C1D9A9009DE44C /* file.c */; }; + 9614C6CD16DDC018000B36EF /* hash.c in Sources */ = {isa = PBXBuildFile; fileRef = 96AFAEB316C1D9A9009DE44C /* hash.c */; }; + 9614C6CE16DDC018000B36EF /* message.c in Sources */ = {isa = PBXBuildFile; fileRef = 96AFAEB616C1D9A9009DE44C /* message.c */; }; + 9614C6CF16DDC018000B36EF /* movie.c in Sources */ = {isa = PBXBuildFile; fileRef = 96AFAEB816C1D9A9009DE44C /* movie.c */; }; + 9614C6D016DDC018000B36EF /* patch.c in Sources */ = {isa = PBXBuildFile; fileRef = 96AFAEBD16C1D9A9009DE44C /* patch.c */; }; + 9614C6D116DDC018000B36EF /* performance.c in Sources */ = {isa = PBXBuildFile; fileRef = 96AFAEBF16C1D9A9009DE44C /* performance.c */; }; + 9614C6D216DDC018000B36EF /* retroarch.c in Sources */ = {isa = PBXBuildFile; fileRef = 96AFAEC216C1D9A9009DE44C /* retroarch.c */; }; + 9614C6D316DDC018000B36EF /* rewind.c in Sources */ = {isa = PBXBuildFile; fileRef = 96AFAEC316C1D9A9009DE44C /* rewind.c */; }; + 9614C6D416DDC018000B36EF /* screenshot.c in Sources */ = {isa = PBXBuildFile; fileRef = 96AFAEC516C1D9A9009DE44C /* screenshot.c */; }; + 9614C6D516DDC018000B36EF /* settings.c in Sources */ = {isa = PBXBuildFile; fileRef = 96AFAEC716C1D9A9009DE44C /* settings.c */; }; + 9614C6D616DDC018000B36EF /* thread.c in Sources */ = {isa = PBXBuildFile; fileRef = 96AFAEC816C1D9A9009DE44C /* thread.c */; }; + 9614C6D716DDC018000B36EF /* config_file.c in Sources */ = {isa = PBXBuildFile; fileRef = 96AFAEE116C1DBDB009DE44C /* config_file.c */; }; + 9614C6D816DDC018000B36EF /* utils.c in Sources */ = {isa = PBXBuildFile; fileRef = 96AFAEFD16C1DC73009DE44C /* utils.c */; }; + 9614C6D916DDC018000B36EF /* compat.c in Sources */ = {isa = PBXBuildFile; fileRef = 96AFAF2416C1DFC8009DE44C /* compat.c */; }; + 9614C6DA16DDC018000B36EF /* rxml.c in Sources */ = {isa = PBXBuildFile; fileRef = 96AFAF2916C1DFC8009DE44C /* rxml.c */; }; + 9614C6DB16DDC018000B36EF /* bitmapfont.c in Sources */ = {isa = PBXBuildFile; fileRef = 96AFAF4816C1E00A009DE44C /* bitmapfont.c */; }; + 9614C6DC16DDC018000B36EF /* fonts.c in Sources */ = {isa = PBXBuildFile; fileRef = 96AFAF4B16C1E00A009DE44C /* fonts.c */; }; + 9614C6DD16DDC018000B36EF /* gl_font.c in Sources */ = {isa = PBXBuildFile; fileRef = 96AFAF4E16C1E00A009DE44C /* gl_font.c */; }; + 9614C6DE16DDC018000B36EF /* gl_raster_font.c in Sources */ = {isa = PBXBuildFile; fileRef = 96AFAF5016C1E00A009DE44C /* gl_raster_font.c */; }; + 9614C6DF16DDC018000B36EF /* gfx_common.c in Sources */ = {isa = PBXBuildFile; fileRef = 96AFAF5416C1E00A009DE44C /* gfx_common.c */; }; + 9614C6E016DDC018000B36EF /* gfx_context.c in Sources */ = {isa = PBXBuildFile; fileRef = 96AFAF5616C1E00A009DE44C /* gfx_context.c */; }; + 9614C6E116DDC018000B36EF /* gl.c in Sources */ = {isa = PBXBuildFile; fileRef = 96AFAF5816C1E00A009DE44C /* gl.c */; }; + 9614C6E216DDC018000B36EF /* image.c in Sources */ = {isa = PBXBuildFile; fileRef = 96AFAF5A16C1E00A009DE44C /* image.c */; }; + 9614C6E316DDC018000B36EF /* matrix.c in Sources */ = {isa = PBXBuildFile; fileRef = 96AFAF5D16C1E00A009DE44C /* matrix.c */; }; + 9614C6E416DDC018000B36EF /* matrix_3x3.c in Sources */ = {isa = PBXBuildFile; fileRef = 96AFAF5F16C1E00A009DE44C /* matrix_3x3.c */; }; + 9614C6E516DDC018000B36EF /* rpng.c in Sources */ = {isa = PBXBuildFile; fileRef = 96AFAF6716C1E00A009DE44C /* rpng.c */; }; + 9614C6E616DDC018000B36EF /* filter.c in Sources */ = {isa = PBXBuildFile; fileRef = 96AFAF6B16C1E00A009DE44C /* filter.c */; }; + 9614C6E716DDC018000B36EF /* pixconv.c in Sources */ = {isa = PBXBuildFile; fileRef = 96AFAF6D16C1E00A009DE44C /* pixconv.c */; }; + 9614C6E816DDC018000B36EF /* scaler.c in Sources */ = {isa = PBXBuildFile; fileRef = 96AFAF6F16C1E00A009DE44C /* scaler.c */; }; + 9614C6E916DDC018000B36EF /* scaler_int.c in Sources */ = {isa = PBXBuildFile; fileRef = 96AFAF7116C1E00A009DE44C /* scaler_int.c */; }; + 9614C6EA16DDC018000B36EF /* shader_glsl.c in Sources */ = {isa = PBXBuildFile; fileRef = 96AFAF7716C1E00A009DE44C /* shader_glsl.c */; }; + 9614C6EB16DDC018000B36EF /* state_tracker.c in Sources */ = {isa = PBXBuildFile; fileRef = 96AFAF7B16C1E00A009DE44C /* state_tracker.c */; }; + 9614C6EC16DDC018000B36EF /* sinc.c in Sources */ = {isa = PBXBuildFile; fileRef = 96AFAEF716C1DC73009DE44C /* sinc.c */; }; + 9614C6ED16DDC018000B36EF /* input_common.c in Sources */ = {isa = PBXBuildFile; fileRef = 96AFAFC916C1FBC0009DE44C /* input_common.c */; }; + 9614C6EE16DDC018000B36EF /* overlay.c in Sources */ = {isa = PBXBuildFile; fileRef = 96AFAFCE16C1FBC0009DE44C /* overlay.c */; }; + 9614C6EF16DDC018000B36EF /* ioseagl_ctx.c in Sources */ = {isa = PBXBuildFile; fileRef = 962979EE16C3EA3E00E6DCE0 /* ioseagl_ctx.c */; }; + 9614C6F016DDC018000B36EF /* RetroArch_iOS.m in Sources */ = {isa = PBXBuildFile; fileRef = 96297A0B16C5AD8D00E6DCE0 /* RetroArch_iOS.m */; }; + 9614C6F116DDC018000B36EF /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 96297A0E16C5AEA100E6DCE0 /* main.m */; }; + 9614C6F216DDC018000B36EF /* resampler.c in Sources */ = {isa = PBXBuildFile; fileRef = 96366C4F16C9A4E100D64A22 /* resampler.c */; }; + 9614C6F316DDC018000B36EF /* hermite.c in Sources */ = {isa = PBXBuildFile; fileRef = 96AFAEEC16C1DC73009DE44C /* hermite.c */; }; + 9614C6F416DDC018000B36EF /* coreaudio.c in Sources */ = {isa = PBXBuildFile; fileRef = 96AFAEE816C1DC73009DE44C /* coreaudio.c */; }; + 9614C6F516DDC018000B36EF /* RAButtonGetter.m in Sources */ = {isa = PBXBuildFile; fileRef = 963F5ABC16CC522F009BBD19 /* RAButtonGetter.m */; }; + 9614C6F616DDC018000B36EF /* RASettingEnumerationList.m in Sources */ = {isa = PBXBuildFile; fileRef = 963F5ABD16CC522F009BBD19 /* RASettingEnumerationList.m */; }; + 9614C6F716DDC018000B36EF /* RASettingsSubList.m in Sources */ = {isa = PBXBuildFile; fileRef = 963F5ABE16CC522F009BBD19 /* RASettingsSubList.m */; }; + 9614C6F816DDC018000B36EF /* RASettingsList.m in Sources */ = {isa = PBXBuildFile; fileRef = 963F5ABF16CC522F009BBD19 /* RASettingsList.m */; }; + 9614C6FA16DDC018000B36EF /* RAGameView.m in Sources */ = {isa = PBXBuildFile; fileRef = 963F5AC516CC523B009BBD19 /* RAGameView.m */; }; + 9614C6FC16DDC018000B36EF /* RAModuleInfoList.m in Sources */ = {isa = PBXBuildFile; fileRef = 96096DD716D1ABAF00BF4499 /* RAModuleInfoList.m */; }; + 9614C6FF16DDC018000B36EF /* RAConfig.m in Sources */ = {isa = PBXBuildFile; fileRef = 96C19C2F16D7045700FE8D5A /* RAConfig.m */; }; + 9614C70616DDC018000B36EF /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 96366C5816C9ACF500D64A22 /* AudioToolbox.framework */; }; + 9614C70716DDC018000B36EF /* CoreAudio.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 96366C5416C9AC3300D64A22 /* CoreAudio.framework */; }; + 9614C70816DDC018000B36EF /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 96AFAF2116C1DF88009DE44C /* libz.dylib */; }; + 9614C70916DDC018000B36EF /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 96AFAE2916C1D4EA009DE44C /* UIKit.framework */; }; + 9614C70A16DDC018000B36EF /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 96AFAE2B16C1D4EA009DE44C /* Foundation.framework */; }; + 9614C70B16DDC018000B36EF /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 96AFAE2D16C1D4EA009DE44C /* CoreGraphics.framework */; }; + 9614C70C16DDC018000B36EF /* GLKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 96AFAE2F16C1D4EA009DE44C /* GLKit.framework */; }; + 9614C70D16DDC018000B36EF /* OpenGLES.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 96AFAE3116C1D4EA009DE44C /* OpenGLES.framework */; }; + 9614C71016DDC018000B36EF /* overlays in Resources */ = {isa = PBXBuildFile; fileRef = 96297A2616C82FF100E6DCE0 /* overlays */; }; + 9614C71116DDC018000B36EF /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 96AFAE3616C1D4EA009DE44C /* InfoPlist.strings */; }; + 9614C71516DDC018000B36EF /* ic_dir.png in Resources */ = {isa = PBXBuildFile; fileRef = 962979F416C43B9500E6DCE0 /* ic_dir.png */; }; + 9614C71616DDC018000B36EF /* ic_file.png in Resources */ = {isa = PBXBuildFile; fileRef = 962979F516C43B9500E6DCE0 /* ic_file.png */; }; + 962979EF16C3EA3E00E6DCE0 /* ioseagl_ctx.c in Sources */ = {isa = PBXBuildFile; fileRef = 962979EE16C3EA3E00E6DCE0 /* ioseagl_ctx.c */; }; + 962979F616C43B9500E6DCE0 /* ic_dir.png in Resources */ = {isa = PBXBuildFile; fileRef = 962979F416C43B9500E6DCE0 /* ic_dir.png */; }; + 962979F716C43B9500E6DCE0 /* ic_file.png in Resources */ = {isa = PBXBuildFile; fileRef = 962979F516C43B9500E6DCE0 /* ic_file.png */; }; + 96297A0C16C5AD8D00E6DCE0 /* RetroArch_iOS.m in Sources */ = {isa = PBXBuildFile; fileRef = 96297A0B16C5AD8D00E6DCE0 /* RetroArch_iOS.m */; }; + 96297A0F16C5AEA100E6DCE0 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 96297A0E16C5AEA100E6DCE0 /* main.m */; }; + 96297A2716C82FF100E6DCE0 /* overlays in Resources */ = {isa = PBXBuildFile; fileRef = 96297A2616C82FF100E6DCE0 /* overlays */; }; + 96366C5016C9A4E100D64A22 /* resampler.c in Sources */ = {isa = PBXBuildFile; fileRef = 96366C4F16C9A4E100D64A22 /* resampler.c */; }; + 96366C5216C9A4E600D64A22 /* hermite.c in Sources */ = {isa = PBXBuildFile; fileRef = 96AFAEEC16C1DC73009DE44C /* hermite.c */; }; + 96366C5316C9A7C100D64A22 /* coreaudio.c in Sources */ = {isa = PBXBuildFile; fileRef = 96AFAEE816C1DC73009DE44C /* coreaudio.c */; }; + 96366C5516C9AC3300D64A22 /* CoreAudio.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 96366C5416C9AC3300D64A22 /* CoreAudio.framework */; }; + 96366C5916C9ACF500D64A22 /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 96366C5816C9ACF500D64A22 /* AudioToolbox.framework */; }; + 963F5AC016CC522F009BBD19 /* RAButtonGetter.m in Sources */ = {isa = PBXBuildFile; fileRef = 963F5ABC16CC522F009BBD19 /* RAButtonGetter.m */; }; + 963F5AC116CC522F009BBD19 /* RASettingEnumerationList.m in Sources */ = {isa = PBXBuildFile; fileRef = 963F5ABD16CC522F009BBD19 /* RASettingEnumerationList.m */; }; + 963F5AC216CC522F009BBD19 /* RASettingsSubList.m in Sources */ = {isa = PBXBuildFile; fileRef = 963F5ABE16CC522F009BBD19 /* RASettingsSubList.m */; }; + 963F5AC316CC522F009BBD19 /* RASettingsList.m in Sources */ = {isa = PBXBuildFile; fileRef = 963F5ABF16CC522F009BBD19 /* RASettingsList.m */; }; + 963F5AC816CC523B009BBD19 /* RAGameView.m in Sources */ = {isa = PBXBuildFile; fileRef = 963F5AC516CC523B009BBD19 /* RAGameView.m */; }; + 966B9C8A16E40D44005B61E1 /* ios_input.m in Sources */ = {isa = PBXBuildFile; fileRef = 966B9C8616E40D44005B61E1 /* ios_input.m */; }; + 966B9C8B16E40D44005B61E1 /* ios_joypad.m in Sources */ = {isa = PBXBuildFile; fileRef = 966B9C8716E40D44005B61E1 /* ios_joypad.m */; }; + 966B9C8C16E40D44005B61E1 /* RAInputResponder.m in Sources */ = {isa = PBXBuildFile; fileRef = 966B9C8916E40D44005B61E1 /* RAInputResponder.m */; }; + 966B9C8D16E40EFC005B61E1 /* RAInputResponder.m in Sources */ = {isa = PBXBuildFile; fileRef = 966B9C8916E40D44005B61E1 /* RAInputResponder.m */; }; + 966B9C8E16E40F00005B61E1 /* ios_input.m in Sources */ = {isa = PBXBuildFile; fileRef = 966B9C8616E40D44005B61E1 /* ios_input.m */; }; + 966B9CA216E418B7005B61E1 /* BTDevice.m in Sources */ = {isa = PBXBuildFile; fileRef = 966B9C9116E418B7005B61E1 /* BTDevice.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 966B9CA416E418B7005B61E1 /* BTstackManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 966B9C9C16E418B7005B61E1 /* BTstackManager.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 966B9CA516E418B7005B61E1 /* libBTstack.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 966B9C9D16E418B7005B61E1 /* libBTstack.dylib */; }; + 966B9CA616E418B7005B61E1 /* wiimote.c in Sources */ = {isa = PBXBuildFile; fileRef = 966B9C9E16E418B7005B61E1 /* wiimote.c */; }; + 966B9CA716E418B7005B61E1 /* WiiMoteHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = 966B9CA116E418B7005B61E1 /* WiiMoteHelper.m */; }; + 966B9CAE16E41C07005B61E1 /* browser.m in Sources */ = {isa = PBXBuildFile; fileRef = 966B9CAA16E41C07005B61E1 /* browser.m */; }; + 966B9CAF16E41C07005B61E1 /* browser.m in Sources */ = {isa = PBXBuildFile; fileRef = 966B9CAA16E41C07005B61E1 /* browser.m */; }; + 966B9CB016E41C07005B61E1 /* RADirectoryGrid.m in Sources */ = {isa = PBXBuildFile; fileRef = 966B9CAB16E41C07005B61E1 /* RADirectoryGrid.m */; }; + 966B9CB116E41C07005B61E1 /* RADirectoryGrid.m in Sources */ = {isa = PBXBuildFile; fileRef = 966B9CAB16E41C07005B61E1 /* RADirectoryGrid.m */; }; + 966B9CB216E41C07005B61E1 /* RADirectoryList.m in Sources */ = {isa = PBXBuildFile; fileRef = 966B9CAC16E41C07005B61E1 /* RADirectoryList.m */; }; + 966B9CB316E41C07005B61E1 /* RADirectoryList.m in Sources */ = {isa = PBXBuildFile; fileRef = 966B9CAC16E41C07005B61E1 /* RADirectoryList.m */; }; + 966B9CB416E41C07005B61E1 /* RAModuleList.m in Sources */ = {isa = PBXBuildFile; fileRef = 966B9CAD16E41C07005B61E1 /* RAModuleList.m */; }; + 966B9CB516E41C07005B61E1 /* RAModuleList.m in Sources */ = {isa = PBXBuildFile; fileRef = 966B9CAD16E41C07005B61E1 /* RAModuleList.m */; }; + 966B9CBD16E41E7A005B61E1 /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 966B9CB816E41E7A005B61E1 /* Default-568h@2x.png */; }; + 966B9CBE16E41E7A005B61E1 /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 966B9CB816E41E7A005B61E1 /* Default-568h@2x.png */; }; + 966B9CBF16E41E7A005B61E1 /* Default.png in Resources */ = {isa = PBXBuildFile; fileRef = 966B9CB916E41E7A005B61E1 /* Default.png */; }; + 966B9CC016E41E7A005B61E1 /* Default.png in Resources */ = {isa = PBXBuildFile; fileRef = 966B9CB916E41E7A005B61E1 /* Default.png */; }; + 966B9CC116E41E7A005B61E1 /* Default@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 966B9CBA16E41E7A005B61E1 /* Default@2x.png */; }; + 966B9CC216E41E7A005B61E1 /* Default@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 966B9CBA16E41E7A005B61E1 /* Default@2x.png */; }; + 966B9CC316E41E7A005B61E1 /* Icon-72.png in Resources */ = {isa = PBXBuildFile; fileRef = 966B9CBB16E41E7A005B61E1 /* Icon-72.png */; }; + 966B9CC416E41E7A005B61E1 /* Icon-72.png in Resources */ = {isa = PBXBuildFile; fileRef = 966B9CBB16E41E7A005B61E1 /* Icon-72.png */; }; + 966B9CC516E41E7A005B61E1 /* Icon.png in Resources */ = {isa = PBXBuildFile; fileRef = 966B9CBC16E41E7A005B61E1 /* Icon.png */; }; + 966B9CC616E41E7A005B61E1 /* Icon.png in Resources */ = {isa = PBXBuildFile; fileRef = 966B9CBC16E41E7A005B61E1 /* Icon.png */; }; + 966B9CC916E41EC1005B61E1 /* PauseView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 966B9CC716E41EC1005B61E1 /* PauseView.xib */; }; + 966B9CCA16E41EC1005B61E1 /* PauseView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 966B9CC716E41EC1005B61E1 /* PauseView.xib */; }; + 966B9CCB16E41EC1005B61E1 /* PauseIndicatorView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 966B9CC816E41EC1005B61E1 /* PauseIndicatorView.xib */; }; + 966B9CCC16E41EC1005B61E1 /* PauseIndicatorView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 966B9CC816E41EC1005B61E1 /* PauseIndicatorView.xib */; }; + 967D646F16E45428006BA1F2 /* ic_pause.png in Resources */ = {isa = PBXBuildFile; fileRef = 967D646E16E45428006BA1F2 /* ic_pause.png */; }; + 967D647016E45428006BA1F2 /* ic_pause.png in Resources */ = {isa = PBXBuildFile; fileRef = 967D646E16E45428006BA1F2 /* ic_pause.png */; }; + 967D647516E6EA04006BA1F2 /* modules in Resources */ = {isa = PBXBuildFile; fileRef = 967D647416E6EA04006BA1F2 /* modules */; }; + 967D647616E6EA04006BA1F2 /* modules in Resources */ = {isa = PBXBuildFile; fileRef = 967D647416E6EA04006BA1F2 /* modules */; }; + 96AFAE2A16C1D4EA009DE44C /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 96AFAE2916C1D4EA009DE44C /* UIKit.framework */; }; + 96AFAE2C16C1D4EA009DE44C /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 96AFAE2B16C1D4EA009DE44C /* Foundation.framework */; }; + 96AFAE2E16C1D4EA009DE44C /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 96AFAE2D16C1D4EA009DE44C /* CoreGraphics.framework */; }; + 96AFAE3016C1D4EA009DE44C /* GLKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 96AFAE2F16C1D4EA009DE44C /* GLKit.framework */; }; + 96AFAE3216C1D4EA009DE44C /* OpenGLES.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 96AFAE3116C1D4EA009DE44C /* OpenGLES.framework */; }; + 96AFAE3816C1D4EA009DE44C /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 96AFAE3616C1D4EA009DE44C /* InfoPlist.strings */; }; + 96AFAECA16C1D9A9009DE44C /* autosave.c in Sources */ = {isa = PBXBuildFile; fileRef = 96AFAE9D16C1D9A9009DE44C /* autosave.c */; }; + 96AFAECB16C1D9A9009DE44C /* cheats.c in Sources */ = {isa = PBXBuildFile; fileRef = 96AFAEA016C1D9A9009DE44C /* cheats.c */; }; + 96AFAECC16C1D9A9009DE44C /* command.c in Sources */ = {isa = PBXBuildFile; fileRef = 96AFAEA216C1D9A9009DE44C /* command.c */; }; + 96AFAECD16C1D9A9009DE44C /* driver.c in Sources */ = {isa = PBXBuildFile; fileRef = 96AFAEA716C1D9A9009DE44C /* driver.c */; }; + 96AFAECE16C1D9A9009DE44C /* dynamic.c in Sources */ = {isa = PBXBuildFile; fileRef = 96AFAEA916C1D9A9009DE44C /* dynamic.c */; }; + 96AFAECF16C1D9A9009DE44C /* fifo_buffer.c in Sources */ = {isa = PBXBuildFile; fileRef = 96AFAEAB16C1D9A9009DE44C /* fifo_buffer.c */; }; + 96AFAED016C1D9A9009DE44C /* file_extract.c in Sources */ = {isa = PBXBuildFile; fileRef = 96AFAEAD16C1D9A9009DE44C /* file_extract.c */; }; + 96AFAED116C1D9A9009DE44C /* file_path.c in Sources */ = {isa = PBXBuildFile; fileRef = 96AFAEAF16C1D9A9009DE44C /* file_path.c */; }; + 96AFAED216C1D9A9009DE44C /* file.c in Sources */ = {isa = PBXBuildFile; fileRef = 96AFAEB016C1D9A9009DE44C /* file.c */; }; + 96AFAED316C1D9A9009DE44C /* hash.c in Sources */ = {isa = PBXBuildFile; fileRef = 96AFAEB316C1D9A9009DE44C /* hash.c */; }; + 96AFAED416C1D9A9009DE44C /* message.c in Sources */ = {isa = PBXBuildFile; fileRef = 96AFAEB616C1D9A9009DE44C /* message.c */; }; + 96AFAED516C1D9A9009DE44C /* movie.c in Sources */ = {isa = PBXBuildFile; fileRef = 96AFAEB816C1D9A9009DE44C /* movie.c */; }; + 96AFAED716C1D9A9009DE44C /* patch.c in Sources */ = {isa = PBXBuildFile; fileRef = 96AFAEBD16C1D9A9009DE44C /* patch.c */; }; + 96AFAED816C1D9A9009DE44C /* performance.c in Sources */ = {isa = PBXBuildFile; fileRef = 96AFAEBF16C1D9A9009DE44C /* performance.c */; }; + 96AFAED916C1D9A9009DE44C /* retroarch.c in Sources */ = {isa = PBXBuildFile; fileRef = 96AFAEC216C1D9A9009DE44C /* retroarch.c */; }; + 96AFAEDA16C1D9A9009DE44C /* rewind.c in Sources */ = {isa = PBXBuildFile; fileRef = 96AFAEC316C1D9A9009DE44C /* rewind.c */; }; + 96AFAEDB16C1D9A9009DE44C /* screenshot.c in Sources */ = {isa = PBXBuildFile; fileRef = 96AFAEC516C1D9A9009DE44C /* screenshot.c */; }; + 96AFAEDC16C1D9A9009DE44C /* settings.c in Sources */ = {isa = PBXBuildFile; fileRef = 96AFAEC716C1D9A9009DE44C /* settings.c */; }; + 96AFAEDD16C1D9A9009DE44C /* thread.c in Sources */ = {isa = PBXBuildFile; fileRef = 96AFAEC816C1D9A9009DE44C /* thread.c */; }; + 96AFAEE416C1DBDB009DE44C /* config_file.c in Sources */ = {isa = PBXBuildFile; fileRef = 96AFAEE116C1DBDB009DE44C /* config_file.c */; }; + 96AFAF1816C1DC73009DE44C /* utils.c in Sources */ = {isa = PBXBuildFile; fileRef = 96AFAEFD16C1DC73009DE44C /* utils.c */; }; + 96AFAF2216C1DF88009DE44C /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 96AFAF2116C1DF88009DE44C /* libz.dylib */; }; + 96AFAF2D16C1DFC8009DE44C /* compat.c in Sources */ = {isa = PBXBuildFile; fileRef = 96AFAF2416C1DFC8009DE44C /* compat.c */; }; + 96AFAF2F16C1DFC8009DE44C /* rxml.c in Sources */ = {isa = PBXBuildFile; fileRef = 96AFAF2916C1DFC8009DE44C /* rxml.c */; }; + 96AFAF8D16C1E00A009DE44C /* bitmapfont.c in Sources */ = {isa = PBXBuildFile; fileRef = 96AFAF4816C1E00A009DE44C /* bitmapfont.c */; }; + 96AFAF8F16C1E00A009DE44C /* fonts.c in Sources */ = {isa = PBXBuildFile; fileRef = 96AFAF4B16C1E00A009DE44C /* fonts.c */; }; + 96AFAF9116C1E00A009DE44C /* gl_font.c in Sources */ = {isa = PBXBuildFile; fileRef = 96AFAF4E16C1E00A009DE44C /* gl_font.c */; }; + 96AFAF9216C1E00A009DE44C /* gl_raster_font.c in Sources */ = {isa = PBXBuildFile; fileRef = 96AFAF5016C1E00A009DE44C /* gl_raster_font.c */; }; + 96AFAF9616C1E00A009DE44C /* gfx_common.c in Sources */ = {isa = PBXBuildFile; fileRef = 96AFAF5416C1E00A009DE44C /* gfx_common.c */; }; + 96AFAF9716C1E00A009DE44C /* gfx_context.c in Sources */ = {isa = PBXBuildFile; fileRef = 96AFAF5616C1E00A009DE44C /* gfx_context.c */; }; + 96AFAF9816C1E00A009DE44C /* gl.c in Sources */ = {isa = PBXBuildFile; fileRef = 96AFAF5816C1E00A009DE44C /* gl.c */; }; + 96AFAF9916C1E00A009DE44C /* image.c in Sources */ = {isa = PBXBuildFile; fileRef = 96AFAF5A16C1E00A009DE44C /* image.c */; }; + 96AFAF9A16C1E00A009DE44C /* matrix.c in Sources */ = {isa = PBXBuildFile; fileRef = 96AFAF5D16C1E00A009DE44C /* matrix.c */; }; + 96AFAF9B16C1E00A009DE44C /* matrix_3x3.c in Sources */ = {isa = PBXBuildFile; fileRef = 96AFAF5F16C1E00A009DE44C /* matrix_3x3.c */; }; + 96AFAF9F16C1E00A009DE44C /* rpng.c in Sources */ = {isa = PBXBuildFile; fileRef = 96AFAF6716C1E00A009DE44C /* rpng.c */; }; + 96AFAFA116C1E00A009DE44C /* filter.c in Sources */ = {isa = PBXBuildFile; fileRef = 96AFAF6B16C1E00A009DE44C /* filter.c */; }; + 96AFAFA216C1E00A009DE44C /* pixconv.c in Sources */ = {isa = PBXBuildFile; fileRef = 96AFAF6D16C1E00A009DE44C /* pixconv.c */; }; + 96AFAFA316C1E00A009DE44C /* scaler.c in Sources */ = {isa = PBXBuildFile; fileRef = 96AFAF6F16C1E00A009DE44C /* scaler.c */; }; + 96AFAFA416C1E00A009DE44C /* scaler_int.c in Sources */ = {isa = PBXBuildFile; fileRef = 96AFAF7116C1E00A009DE44C /* scaler_int.c */; }; + 96AFAFA716C1E00A009DE44C /* shader_glsl.c in Sources */ = {isa = PBXBuildFile; fileRef = 96AFAF7716C1E00A009DE44C /* shader_glsl.c */; }; + 96AFAFAC16C1E279009DE44C /* state_tracker.c in Sources */ = {isa = PBXBuildFile; fileRef = 96AFAF7B16C1E00A009DE44C /* state_tracker.c */; }; + 96AFAFAD16C1EEE9009DE44C /* sinc.c in Sources */ = {isa = PBXBuildFile; fileRef = 96AFAEF716C1DC73009DE44C /* sinc.c */; }; + 96AFAFD416C1FBC0009DE44C /* input_common.c in Sources */ = {isa = PBXBuildFile; fileRef = 96AFAFC916C1FBC0009DE44C /* input_common.c */; }; + 96C19C3016D7045700FE8D5A /* RAConfig.m in Sources */ = {isa = PBXBuildFile; fileRef = 96C19C2F16D7045700FE8D5A /* RAConfig.m */; }; + 96CF015016C2C0B700ABF9C9 /* overlay.c in Sources */ = {isa = PBXBuildFile; fileRef = 96AFAFCE16C1FBC0009DE44C /* overlay.c */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 96096DD716D1ABAF00BF4499 /* RAModuleInfoList.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RAModuleInfoList.m; sourceTree = ""; }; + 9614C71E16DDC018000B36EF /* RetroArch.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = RetroArch.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 9614C71F16DDC018000B36EF /* RetroArch copy-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = "RetroArch copy-Info.plist"; path = "/Users/jason/Documents/Projects/ios/RetroArch/ios/RetroArch copy-Info.plist"; sourceTree = ""; }; + 962979EE16C3EA3E00E6DCE0 /* ioseagl_ctx.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ioseagl_ctx.c; sourceTree = ""; }; + 962979F416C43B9500E6DCE0 /* ic_dir.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = ic_dir.png; path = "../../android/phoenix/res/drawable-xhdpi/ic_dir.png"; sourceTree = ""; }; + 962979F516C43B9500E6DCE0 /* ic_file.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = ic_file.png; path = "../../android/phoenix/res/drawable-xhdpi/ic_file.png"; sourceTree = ""; }; + 96297A0A16C5AD8D00E6DCE0 /* RetroArch_iOS.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RetroArch_iOS.h; sourceTree = ""; }; + 96297A0B16C5AD8D00E6DCE0 /* RetroArch_iOS.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RetroArch_iOS.m; sourceTree = ""; }; + 96297A0D16C5ADDA00E6DCE0 /* views.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = views.h; sourceTree = ""; }; + 96297A0E16C5AEA100E6DCE0 /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 96297A2616C82FF100E6DCE0 /* overlays */ = {isa = PBXFileReference; lastKnownFileType = folder; name = overlays; path = ../../media/overlays; sourceTree = ""; }; + 96366C4F16C9A4E100D64A22 /* resampler.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = resampler.c; sourceTree = ""; }; + 96366C5416C9AC3300D64A22 /* CoreAudio.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreAudio.framework; path = System/Library/Frameworks/CoreAudio.framework; sourceTree = SDKROOT; }; + 96366C5816C9ACF500D64A22 /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = System/Library/Frameworks/AudioToolbox.framework; sourceTree = SDKROOT; }; + 96366C7216CAF62200D64A22 /* settings.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = settings.h; sourceTree = ""; }; + 963F5ABC16CC522F009BBD19 /* RAButtonGetter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RAButtonGetter.m; sourceTree = ""; }; + 963F5ABD16CC522F009BBD19 /* RASettingEnumerationList.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RASettingEnumerationList.m; sourceTree = ""; }; + 963F5ABE16CC522F009BBD19 /* RASettingsSubList.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RASettingsSubList.m; sourceTree = ""; }; + 963F5ABF16CC522F009BBD19 /* RASettingsList.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RASettingsList.m; sourceTree = ""; }; + 963F5AC516CC523B009BBD19 /* RAGameView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RAGameView.m; sourceTree = ""; }; + 9664F4A116E4409100FB28F9 /* keycode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = keycode.h; sourceTree = ""; }; + 966B9C8616E40D44005B61E1 /* ios_input.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ios_input.m; sourceTree = ""; }; + 966B9C8716E40D44005B61E1 /* ios_joypad.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ios_joypad.m; sourceTree = ""; }; + 966B9C8816E40D44005B61E1 /* RAInputResponder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RAInputResponder.h; sourceTree = ""; }; + 966B9C8916E40D44005B61E1 /* RAInputResponder.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RAInputResponder.m; sourceTree = ""; }; + 966B9C9016E418B7005B61E1 /* BTDevice.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BTDevice.h; sourceTree = ""; }; + 966B9C9116E418B7005B61E1 /* BTDevice.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BTDevice.m; sourceTree = ""; }; + 966B9C9516E418B7005B61E1 /* btstack.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = btstack.h; sourceTree = ""; }; + 966B9C9616E418B7005B61E1 /* hci_cmds.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = hci_cmds.h; sourceTree = ""; }; + 966B9C9716E418B7005B61E1 /* linked_list.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = linked_list.h; sourceTree = ""; }; + 966B9C9816E418B7005B61E1 /* run_loop.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = run_loop.h; sourceTree = ""; }; + 966B9C9916E418B7005B61E1 /* sdp_util.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sdp_util.h; sourceTree = ""; }; + 966B9C9A16E418B7005B61E1 /* utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = utils.h; sourceTree = ""; }; + 966B9C9B16E418B7005B61E1 /* BTstackManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BTstackManager.h; sourceTree = ""; }; + 966B9C9C16E418B7005B61E1 /* BTstackManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BTstackManager.m; sourceTree = ""; }; + 966B9C9D16E418B7005B61E1 /* libBTstack.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; path = libBTstack.dylib; sourceTree = ""; }; + 966B9C9E16E418B7005B61E1 /* wiimote.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = wiimote.c; sourceTree = ""; }; + 966B9C9F16E418B7005B61E1 /* wiimote.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wiimote.h; sourceTree = ""; }; + 966B9CA016E418B7005B61E1 /* WiiMoteHelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WiiMoteHelper.h; sourceTree = ""; }; + 966B9CA116E418B7005B61E1 /* WiiMoteHelper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WiiMoteHelper.m; sourceTree = ""; }; + 966B9CA916E41C07005B61E1 /* browser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = browser.h; sourceTree = ""; }; + 966B9CAA16E41C07005B61E1 /* browser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = browser.m; sourceTree = ""; }; + 966B9CAB16E41C07005B61E1 /* RADirectoryGrid.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RADirectoryGrid.m; sourceTree = ""; }; + 966B9CAC16E41C07005B61E1 /* RADirectoryList.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RADirectoryList.m; sourceTree = ""; }; + 966B9CAD16E41C07005B61E1 /* RAModuleList.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RAModuleList.m; sourceTree = ""; }; + 966B9CB816E41E7A005B61E1 /* Default-568h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-568h@2x.png"; sourceTree = ""; }; + 966B9CB916E41E7A005B61E1 /* Default.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = Default.png; sourceTree = ""; }; + 966B9CBA16E41E7A005B61E1 /* Default@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default@2x.png"; sourceTree = ""; }; + 966B9CBB16E41E7A005B61E1 /* Icon-72.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Icon-72.png"; sourceTree = ""; }; + 966B9CBC16E41E7A005B61E1 /* Icon.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = Icon.png; sourceTree = ""; }; + 966B9CC716E41EC1005B61E1 /* PauseView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = PauseView.xib; sourceTree = ""; }; + 966B9CC816E41EC1005B61E1 /* PauseIndicatorView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = PauseIndicatorView.xib; sourceTree = ""; }; + 967D646E16E45428006BA1F2 /* ic_pause.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = ic_pause.png; sourceTree = ""; }; + 967D647416E6EA04006BA1F2 /* modules */ = {isa = PBXFileReference; lastKnownFileType = folder; path = modules; sourceTree = SOURCE_ROOT; }; + 96AFAE2516C1D4EA009DE44C /* RetroArch.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = RetroArch.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 96AFAE2916C1D4EA009DE44C /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; + 96AFAE2B16C1D4EA009DE44C /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; + 96AFAE2D16C1D4EA009DE44C /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; + 96AFAE2F16C1D4EA009DE44C /* GLKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GLKit.framework; path = System/Library/Frameworks/GLKit.framework; sourceTree = SDKROOT; }; + 96AFAE3116C1D4EA009DE44C /* OpenGLES.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGLES.framework; path = System/Library/Frameworks/OpenGLES.framework; sourceTree = SDKROOT; }; + 96AFAE3516C1D4EA009DE44C /* RetroArch-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "RetroArch-Info.plist"; sourceTree = ""; }; + 96AFAE3716C1D4EA009DE44C /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; + 96AFAE3B16C1D4EA009DE44C /* RetroArch-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "RetroArch-Prefix.pch"; sourceTree = ""; }; + 96AFAE9D16C1D9A9009DE44C /* autosave.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = autosave.c; path = ../autosave.c; sourceTree = ""; }; + 96AFAE9E16C1D9A9009DE44C /* autosave.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = autosave.h; path = ../autosave.h; sourceTree = ""; }; + 96AFAE9F16C1D9A9009DE44C /* boolean.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = boolean.h; path = ../boolean.h; sourceTree = ""; }; + 96AFAEA016C1D9A9009DE44C /* cheats.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = cheats.c; path = ../cheats.c; sourceTree = ""; }; + 96AFAEA116C1D9A9009DE44C /* cheats.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = cheats.h; path = ../cheats.h; sourceTree = ""; }; + 96AFAEA216C1D9A9009DE44C /* command.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = command.c; path = ../command.c; sourceTree = ""; }; + 96AFAEA316C1D9A9009DE44C /* command.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = command.h; path = ../command.h; sourceTree = ""; }; + 96AFAEA416C1D9A9009DE44C /* config.def.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = config.def.h; path = ../config.def.h; sourceTree = ""; }; + 96AFAEA516C1D9A9009DE44C /* config.features.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = config.features.h; path = ../config.features.h; sourceTree = ""; }; + 96AFAEA616C1D9A9009DE44C /* driver_funcs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = driver_funcs.h; path = ../driver_funcs.h; sourceTree = ""; }; + 96AFAEA716C1D9A9009DE44C /* driver.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = driver.c; path = ../driver.c; sourceTree = ""; }; + 96AFAEA816C1D9A9009DE44C /* driver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = driver.h; path = ../driver.h; sourceTree = ""; }; + 96AFAEA916C1D9A9009DE44C /* dynamic.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = dynamic.c; path = ../dynamic.c; sourceTree = ""; }; + 96AFAEAA16C1D9A9009DE44C /* dynamic.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dynamic.h; path = ../dynamic.h; sourceTree = ""; }; + 96AFAEAB16C1D9A9009DE44C /* fifo_buffer.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = fifo_buffer.c; path = ../fifo_buffer.c; sourceTree = ""; }; + 96AFAEAC16C1D9A9009DE44C /* fifo_buffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = fifo_buffer.h; path = ../fifo_buffer.h; sourceTree = ""; }; + 96AFAEAD16C1D9A9009DE44C /* file_extract.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = file_extract.c; path = ../file_extract.c; sourceTree = ""; }; + 96AFAEAE16C1D9A9009DE44C /* file_extract.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = file_extract.h; path = ../file_extract.h; sourceTree = ""; }; + 96AFAEAF16C1D9A9009DE44C /* file_path.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = file_path.c; path = ../file_path.c; sourceTree = ""; }; + 96AFAEB016C1D9A9009DE44C /* file.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = file.c; path = ../file.c; sourceTree = ""; }; + 96AFAEB116C1D9A9009DE44C /* file.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = file.h; path = ../file.h; sourceTree = ""; }; + 96AFAEB216C1D9A9009DE44C /* general.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = general.h; path = ../general.h; sourceTree = ""; }; + 96AFAEB316C1D9A9009DE44C /* hash.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = hash.c; path = ../hash.c; sourceTree = ""; }; + 96AFAEB416C1D9A9009DE44C /* hash.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = hash.h; path = ../hash.h; sourceTree = ""; }; + 96AFAEB516C1D9A9009DE44C /* libretro.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = libretro.h; path = ../libretro.h; sourceTree = ""; }; + 96AFAEB616C1D9A9009DE44C /* message.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = message.c; path = ../message.c; sourceTree = ""; }; + 96AFAEB716C1D9A9009DE44C /* message.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = message.h; path = ../message.h; sourceTree = ""; }; + 96AFAEB816C1D9A9009DE44C /* movie.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = movie.c; path = ../movie.c; sourceTree = ""; }; + 96AFAEB916C1D9A9009DE44C /* movie.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = movie.h; path = ../movie.h; sourceTree = ""; }; + 96AFAEBA16C1D9A9009DE44C /* netplay_compat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = netplay_compat.h; path = ../netplay_compat.h; sourceTree = ""; }; + 96AFAEBC16C1D9A9009DE44C /* netplay.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = netplay.h; path = ../netplay.h; sourceTree = ""; }; + 96AFAEBD16C1D9A9009DE44C /* patch.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = patch.c; path = ../patch.c; sourceTree = ""; }; + 96AFAEBE16C1D9A9009DE44C /* patch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = patch.h; path = ../patch.h; sourceTree = ""; }; + 96AFAEBF16C1D9A9009DE44C /* performance.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = performance.c; path = ../performance.c; sourceTree = ""; }; + 96AFAEC016C1D9A9009DE44C /* performance.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = performance.h; path = ../performance.h; sourceTree = ""; }; + 96AFAEC116C1D9A9009DE44C /* retroarch_logger.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = retroarch_logger.h; path = ../retroarch_logger.h; sourceTree = ""; }; + 96AFAEC216C1D9A9009DE44C /* retroarch.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = retroarch.c; path = ../retroarch.c; sourceTree = ""; }; + 96AFAEC316C1D9A9009DE44C /* rewind.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = rewind.c; path = ../rewind.c; sourceTree = ""; }; + 96AFAEC416C1D9A9009DE44C /* rewind.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = rewind.h; path = ../rewind.h; sourceTree = ""; }; + 96AFAEC516C1D9A9009DE44C /* screenshot.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = screenshot.c; path = ../screenshot.c; sourceTree = ""; }; + 96AFAEC616C1D9A9009DE44C /* screenshot.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = screenshot.h; path = ../screenshot.h; sourceTree = ""; }; + 96AFAEC716C1D9A9009DE44C /* settings.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = settings.c; path = ../settings.c; sourceTree = ""; }; + 96AFAEC816C1D9A9009DE44C /* thread.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = thread.c; path = ../thread.c; sourceTree = ""; }; + 96AFAEC916C1D9A9009DE44C /* thread.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = thread.h; path = ../thread.h; sourceTree = ""; }; + 96AFAEE116C1DBDB009DE44C /* config_file.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = config_file.c; sourceTree = ""; }; + 96AFAEE216C1DBDB009DE44C /* config_file.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = config_file.h; sourceTree = ""; }; + 96AFAEE316C1DBDB009DE44C /* config_file_macros.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = config_file_macros.h; sourceTree = ""; }; + 96AFAEE816C1DC73009DE44C /* coreaudio.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = coreaudio.c; sourceTree = ""; }; + 96AFAEEB16C1DC73009DE44C /* rarch_dsp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = rarch_dsp.h; sourceTree = ""; }; + 96AFAEEC16C1DC73009DE44C /* hermite.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = hermite.c; sourceTree = ""; }; + 96AFAEF316C1DC73009DE44C /* resampler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = resampler.h; sourceTree = ""; }; + 96AFAEF716C1DC73009DE44C /* sinc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sinc.c; sourceTree = ""; }; + 96AFAEF816C1DC73009DE44C /* sinc_neon.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = sinc_neon.S; sourceTree = ""; }; + 96AFAEFD16C1DC73009DE44C /* utils.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = utils.c; sourceTree = ""; }; + 96AFAEFE16C1DC73009DE44C /* utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = utils.h; sourceTree = ""; }; + 96AFAEFF16C1DC73009DE44C /* utils_neon.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = utils_neon.S; sourceTree = ""; }; + 96AFAF2116C1DF88009DE44C /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = usr/lib/libz.dylib; sourceTree = SDKROOT; }; + 96AFAF2416C1DFC8009DE44C /* compat.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = compat.c; sourceTree = ""; }; + 96AFAF2516C1DFC8009DE44C /* getopt_rarch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = getopt_rarch.h; sourceTree = ""; }; + 96AFAF2616C1DFC8009DE44C /* posix_string.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = posix_string.h; sourceTree = ""; }; + 96AFAF2916C1DFC8009DE44C /* rxml.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = rxml.c; sourceTree = ""; }; + 96AFAF2A16C1DFC8009DE44C /* rxml.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = rxml.h; sourceTree = ""; }; + 96AFAF2C16C1DFC8009DE44C /* strl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = strl.h; sourceTree = ""; }; + 96AFAF4516C1E00A009DE44C /* bitmap.bin */ = {isa = PBXFileReference; lastKnownFileType = archive.macbinary; path = bitmap.bin; sourceTree = ""; }; + 96AFAF4616C1E00A009DE44C /* bitmap.bmp */ = {isa = PBXFileReference; lastKnownFileType = image.bmp; path = bitmap.bmp; sourceTree = ""; }; + 96AFAF4716C1E00A009DE44C /* bitmap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = bitmap.h; sourceTree = ""; }; + 96AFAF4816C1E00A009DE44C /* bitmapfont.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bitmapfont.c; sourceTree = ""; }; + 96AFAF4B16C1E00A009DE44C /* fonts.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = fonts.c; sourceTree = ""; }; + 96AFAF4C16C1E00A009DE44C /* fonts.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fonts.h; sourceTree = ""; }; + 96AFAF4D16C1E00A009DE44C /* freetype.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = freetype.c; sourceTree = ""; }; + 96AFAF4E16C1E00A009DE44C /* gl_font.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = gl_font.c; sourceTree = ""; }; + 96AFAF4F16C1E00A009DE44C /* gl_font.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = gl_font.h; sourceTree = ""; }; + 96AFAF5016C1E00A009DE44C /* gl_raster_font.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = gl_raster_font.c; sourceTree = ""; }; + 96AFAF5416C1E00A009DE44C /* gfx_common.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = gfx_common.c; sourceTree = ""; }; + 96AFAF5516C1E00A009DE44C /* gfx_common.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = gfx_common.h; sourceTree = ""; }; + 96AFAF5616C1E00A009DE44C /* gfx_context.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = gfx_context.c; sourceTree = ""; }; + 96AFAF5716C1E00A009DE44C /* gfx_context.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = gfx_context.h; sourceTree = ""; }; + 96AFAF5816C1E00A009DE44C /* gl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = gl.c; sourceTree = ""; }; + 96AFAF5916C1E00A009DE44C /* gl_common.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = gl_common.h; sourceTree = ""; }; + 96AFAF5A16C1E00A009DE44C /* image.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = image.c; sourceTree = ""; }; + 96AFAF5B16C1E00A009DE44C /* image.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = image.h; sourceTree = ""; }; + 96AFAF5D16C1E00A009DE44C /* matrix.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = matrix.c; sourceTree = ""; }; + 96AFAF5E16C1E00A009DE44C /* matrix.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = matrix.h; sourceTree = ""; }; + 96AFAF5F16C1E00A009DE44C /* matrix_3x3.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = matrix_3x3.c; sourceTree = ""; }; + 96AFAF6016C1E00A009DE44C /* matrix_3x3.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = matrix_3x3.h; sourceTree = ""; }; + 96AFAF6716C1E00A009DE44C /* rpng.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = rpng.c; sourceTree = ""; }; + 96AFAF6816C1E00A009DE44C /* rpng.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = rpng.h; sourceTree = ""; }; + 96AFAF6B16C1E00A009DE44C /* filter.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = filter.c; sourceTree = ""; }; + 96AFAF6C16C1E00A009DE44C /* filter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = filter.h; sourceTree = ""; }; + 96AFAF6D16C1E00A009DE44C /* pixconv.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pixconv.c; sourceTree = ""; }; + 96AFAF6E16C1E00A009DE44C /* pixconv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pixconv.h; sourceTree = ""; }; + 96AFAF6F16C1E00A009DE44C /* scaler.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = scaler.c; sourceTree = ""; }; + 96AFAF7016C1E00A009DE44C /* scaler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = scaler.h; sourceTree = ""; }; + 96AFAF7116C1E00A009DE44C /* scaler_int.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = scaler_int.c; sourceTree = ""; }; + 96AFAF7216C1E00A009DE44C /* scaler_int.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = scaler_int.h; sourceTree = ""; }; + 96AFAF7616C1E00A009DE44C /* shader_common.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = shader_common.h; sourceTree = ""; }; + 96AFAF7716C1E00A009DE44C /* shader_glsl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = shader_glsl.c; sourceTree = ""; }; + 96AFAF7816C1E00A009DE44C /* shader_glsl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = shader_glsl.h; sourceTree = ""; }; + 96AFAF7B16C1E00A009DE44C /* state_tracker.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = state_tracker.c; sourceTree = ""; }; + 96AFAF7C16C1E00A009DE44C /* state_tracker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = state_tracker.h; sourceTree = ""; }; + 96AFAFC916C1FBC0009DE44C /* input_common.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = input_common.c; sourceTree = ""; }; + 96AFAFCA16C1FBC0009DE44C /* input_common.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = input_common.h; sourceTree = ""; }; + 96AFAFCE16C1FBC0009DE44C /* overlay.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = overlay.c; sourceTree = ""; }; + 96AFAFCF16C1FBC0009DE44C /* overlay.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = overlay.h; sourceTree = ""; }; + 96C19C2616D455BE00FE8D5A /* rarch_wrapper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = rarch_wrapper.h; sourceTree = ""; }; + 96C19C2E16D7045600FE8D5A /* RAConfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RAConfig.h; sourceTree = ""; }; + 96C19C2F16D7045700FE8D5A /* RAConfig.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RAConfig.m; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 9614C70516DDC018000B36EF /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 9614C70616DDC018000B36EF /* AudioToolbox.framework in Frameworks */, + 9614C70716DDC018000B36EF /* CoreAudio.framework in Frameworks */, + 9614C70816DDC018000B36EF /* libz.dylib in Frameworks */, + 9614C70916DDC018000B36EF /* UIKit.framework in Frameworks */, + 9614C70A16DDC018000B36EF /* Foundation.framework in Frameworks */, + 9614C70B16DDC018000B36EF /* CoreGraphics.framework in Frameworks */, + 9614C70C16DDC018000B36EF /* GLKit.framework in Frameworks */, + 9614C70D16DDC018000B36EF /* OpenGLES.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 96AFAE2216C1D4EA009DE44C /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 96366C5916C9ACF500D64A22 /* AudioToolbox.framework in Frameworks */, + 96366C5516C9AC3300D64A22 /* CoreAudio.framework in Frameworks */, + 96AFAF2216C1DF88009DE44C /* libz.dylib in Frameworks */, + 96AFAE2A16C1D4EA009DE44C /* UIKit.framework in Frameworks */, + 96AFAE2C16C1D4EA009DE44C /* Foundation.framework in Frameworks */, + 96AFAE2E16C1D4EA009DE44C /* CoreGraphics.framework in Frameworks */, + 96AFAE3016C1D4EA009DE44C /* GLKit.framework in Frameworks */, + 96AFAE3216C1D4EA009DE44C /* OpenGLES.framework in Frameworks */, + 966B9CA516E418B7005B61E1 /* libBTstack.dylib in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 96366C6F16CAF62200D64A22 /* settings */ = { + isa = PBXGroup; + children = ( + 963F5ABC16CC522F009BBD19 /* RAButtonGetter.m */, + 963F5ABD16CC522F009BBD19 /* RASettingEnumerationList.m */, + 963F5ABF16CC522F009BBD19 /* RASettingsList.m */, + 963F5ABE16CC522F009BBD19 /* RASettingsSubList.m */, + 96366C7216CAF62200D64A22 /* settings.h */, + ); + path = settings; + sourceTree = ""; + }; + 966B9C8516E40D44005B61E1 /* input */ = { + isa = PBXGroup; + children = ( + 966B9C8F16E418B7005B61E1 /* BTStack */, + 966B9C8616E40D44005B61E1 /* ios_input.m */, + 966B9C8716E40D44005B61E1 /* ios_joypad.m */, + 9664F4A116E4409100FB28F9 /* keycode.h */, + 966B9C8816E40D44005B61E1 /* RAInputResponder.h */, + 966B9C8916E40D44005B61E1 /* RAInputResponder.m */, + ); + path = input; + sourceTree = ""; + }; + 966B9C8F16E418B7005B61E1 /* BTStack */ = { + isa = PBXGroup; + children = ( + 966B9C9016E418B7005B61E1 /* BTDevice.h */, + 966B9C9116E418B7005B61E1 /* BTDevice.m */, + 966B9C9416E418B7005B61E1 /* btstack */, + 966B9C9B16E418B7005B61E1 /* BTstackManager.h */, + 966B9C9C16E418B7005B61E1 /* BTstackManager.m */, + 966B9C9D16E418B7005B61E1 /* libBTstack.dylib */, + 966B9C9E16E418B7005B61E1 /* wiimote.c */, + 966B9C9F16E418B7005B61E1 /* wiimote.h */, + 966B9CA016E418B7005B61E1 /* WiiMoteHelper.h */, + 966B9CA116E418B7005B61E1 /* WiiMoteHelper.m */, + ); + path = BTStack; + sourceTree = ""; + }; + 966B9C9416E418B7005B61E1 /* btstack */ = { + isa = PBXGroup; + children = ( + 966B9C9516E418B7005B61E1 /* btstack.h */, + 966B9C9616E418B7005B61E1 /* hci_cmds.h */, + 966B9C9716E418B7005B61E1 /* linked_list.h */, + 966B9C9816E418B7005B61E1 /* run_loop.h */, + 966B9C9916E418B7005B61E1 /* sdp_util.h */, + 966B9C9A16E418B7005B61E1 /* utils.h */, + ); + path = btstack; + sourceTree = ""; + }; + 966B9CA816E41C07005B61E1 /* browser */ = { + isa = PBXGroup; + children = ( + 966B9CA916E41C07005B61E1 /* browser.h */, + 966B9CAA16E41C07005B61E1 /* browser.m */, + 966B9CAB16E41C07005B61E1 /* RADirectoryGrid.m */, + 966B9CAC16E41C07005B61E1 /* RADirectoryList.m */, + 966B9CAD16E41C07005B61E1 /* RAModuleList.m */, + ); + path = browser; + sourceTree = ""; + }; + 966B9CB716E41E7A005B61E1 /* Assets */ = { + isa = PBXGroup; + children = ( + 967D647416E6EA04006BA1F2 /* modules */, + 96297A2616C82FF100E6DCE0 /* overlays */, + 966B9CB816E41E7A005B61E1 /* Default-568h@2x.png */, + 966B9CB916E41E7A005B61E1 /* Default.png */, + 966B9CBA16E41E7A005B61E1 /* Default@2x.png */, + 962979F416C43B9500E6DCE0 /* ic_dir.png */, + 962979F516C43B9500E6DCE0 /* ic_file.png */, + 967D646E16E45428006BA1F2 /* ic_pause.png */, + 966B9CBB16E41E7A005B61E1 /* Icon-72.png */, + 966B9CBC16E41E7A005B61E1 /* Icon.png */, + 966B9CC716E41EC1005B61E1 /* PauseView.xib */, + 966B9CC816E41EC1005B61E1 /* PauseIndicatorView.xib */, + ); + path = Assets; + sourceTree = ""; + }; + 96AFAE1A16C1D4EA009DE44C = { + isa = PBXGroup; + children = ( + 96AFAE3316C1D4EA009DE44C /* RetroArch */, + 96AFAE9C16C1D976009DE44C /* core */, + 966B9CB716E41E7A005B61E1 /* Assets */, + 96AFAE2816C1D4EA009DE44C /* Frameworks */, + 96AFAE2616C1D4EA009DE44C /* Products */, + 96AFAE3416C1D4EA009DE44C /* Supporting Files */, + ); + sourceTree = ""; + }; + 96AFAE2616C1D4EA009DE44C /* Products */ = { + isa = PBXGroup; + children = ( + 96AFAE2516C1D4EA009DE44C /* RetroArch.app */, + 9614C71E16DDC018000B36EF /* RetroArch.app */, + ); + name = Products; + sourceTree = ""; + }; + 96AFAE2816C1D4EA009DE44C /* Frameworks */ = { + isa = PBXGroup; + children = ( + 96AFAF2116C1DF88009DE44C /* libz.dylib */, + 96366C5816C9ACF500D64A22 /* AudioToolbox.framework */, + 96366C5416C9AC3300D64A22 /* CoreAudio.framework */, + 96AFAE2916C1D4EA009DE44C /* UIKit.framework */, + 96AFAE2B16C1D4EA009DE44C /* Foundation.framework */, + 96AFAE2D16C1D4EA009DE44C /* CoreGraphics.framework */, + 96AFAE2F16C1D4EA009DE44C /* GLKit.framework */, + 96AFAE3116C1D4EA009DE44C /* OpenGLES.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + 96AFAE3316C1D4EA009DE44C /* RetroArch */ = { + isa = PBXGroup; + children = ( + 966B9CA816E41C07005B61E1 /* browser */, + 966B9C8516E40D44005B61E1 /* input */, + 96366C6F16CAF62200D64A22 /* settings */, + 96297A0E16C5AEA100E6DCE0 /* main.m */, + 96C19C2E16D7045600FE8D5A /* RAConfig.h */, + 96C19C2F16D7045700FE8D5A /* RAConfig.m */, + 963F5AC516CC523B009BBD19 /* RAGameView.m */, + 96096DD716D1ABAF00BF4499 /* RAModuleInfoList.m */, + 96C19C2616D455BE00FE8D5A /* rarch_wrapper.h */, + 96297A0A16C5AD8D00E6DCE0 /* RetroArch_iOS.h */, + 96297A0B16C5AD8D00E6DCE0 /* RetroArch_iOS.m */, + 96297A0D16C5ADDA00E6DCE0 /* views.h */, + ); + path = RetroArch; + sourceTree = ""; + }; + 96AFAE3416C1D4EA009DE44C /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 9614C71F16DDC018000B36EF /* RetroArch copy-Info.plist */, + 96AFAE3616C1D4EA009DE44C /* InfoPlist.strings */, + 96AFAE3516C1D4EA009DE44C /* RetroArch-Info.plist */, + 96AFAE3B16C1D4EA009DE44C /* RetroArch-Prefix.pch */, + ); + name = "Supporting Files"; + path = RetroArch; + sourceTree = ""; + }; + 96AFAE9C16C1D976009DE44C /* core */ = { + isa = PBXGroup; + children = ( + 96AFAEE516C1DC73009DE44C /* audio */, + 96AFAF2316C1DFC8009DE44C /* compat */, + 96AFAEE016C1DBDB009DE44C /* conf */, + 96AFAF3116C1E00A009DE44C /* gfx */, + 96AFAFC716C1FBB3009DE44C /* input */, + 96AFAE9D16C1D9A9009DE44C /* autosave.c */, + 96AFAE9E16C1D9A9009DE44C /* autosave.h */, + 96AFAE9F16C1D9A9009DE44C /* boolean.h */, + 96AFAEA016C1D9A9009DE44C /* cheats.c */, + 96AFAEA116C1D9A9009DE44C /* cheats.h */, + 96AFAEA216C1D9A9009DE44C /* command.c */, + 96AFAEA316C1D9A9009DE44C /* command.h */, + 96AFAEA416C1D9A9009DE44C /* config.def.h */, + 96AFAEA516C1D9A9009DE44C /* config.features.h */, + 96AFAEA716C1D9A9009DE44C /* driver.c */, + 96AFAEA816C1D9A9009DE44C /* driver.h */, + 96AFAEA616C1D9A9009DE44C /* driver_funcs.h */, + 96AFAEA916C1D9A9009DE44C /* dynamic.c */, + 96AFAEAA16C1D9A9009DE44C /* dynamic.h */, + 96AFAEAB16C1D9A9009DE44C /* fifo_buffer.c */, + 96AFAEAC16C1D9A9009DE44C /* fifo_buffer.h */, + 96AFAEB016C1D9A9009DE44C /* file.c */, + 96AFAEB116C1D9A9009DE44C /* file.h */, + 96AFAEAD16C1D9A9009DE44C /* file_extract.c */, + 96AFAEAE16C1D9A9009DE44C /* file_extract.h */, + 96AFAEAF16C1D9A9009DE44C /* file_path.c */, + 96AFAEB216C1D9A9009DE44C /* general.h */, + 96AFAEB316C1D9A9009DE44C /* hash.c */, + 96AFAEB416C1D9A9009DE44C /* hash.h */, + 96AFAEB516C1D9A9009DE44C /* libretro.h */, + 96AFAEB616C1D9A9009DE44C /* message.c */, + 96AFAEB716C1D9A9009DE44C /* message.h */, + 96AFAEB816C1D9A9009DE44C /* movie.c */, + 96AFAEB916C1D9A9009DE44C /* movie.h */, + 96AFAEBC16C1D9A9009DE44C /* netplay.h */, + 96AFAEBA16C1D9A9009DE44C /* netplay_compat.h */, + 96AFAEBD16C1D9A9009DE44C /* patch.c */, + 96AFAEBE16C1D9A9009DE44C /* patch.h */, + 96AFAEBF16C1D9A9009DE44C /* performance.c */, + 96AFAEC016C1D9A9009DE44C /* performance.h */, + 96AFAEC216C1D9A9009DE44C /* retroarch.c */, + 96AFAEC116C1D9A9009DE44C /* retroarch_logger.h */, + 96AFAEC316C1D9A9009DE44C /* rewind.c */, + 96AFAEC416C1D9A9009DE44C /* rewind.h */, + 96AFAEC516C1D9A9009DE44C /* screenshot.c */, + 96AFAEC616C1D9A9009DE44C /* screenshot.h */, + 96AFAEC716C1D9A9009DE44C /* settings.c */, + 96AFAEC816C1D9A9009DE44C /* thread.c */, + 96AFAEC916C1D9A9009DE44C /* thread.h */, + ); + name = core; + sourceTree = ""; + }; + 96AFAEE016C1DBDB009DE44C /* conf */ = { + isa = PBXGroup; + children = ( + 96AFAEE116C1DBDB009DE44C /* config_file.c */, + 96AFAEE216C1DBDB009DE44C /* config_file.h */, + 96AFAEE316C1DBDB009DE44C /* config_file_macros.h */, + ); + name = conf; + path = ../conf; + sourceTree = ""; + }; + 96AFAEE516C1DC73009DE44C /* audio */ = { + isa = PBXGroup; + children = ( + 96AFAEEA16C1DC73009DE44C /* ext */, + 96AFAEE816C1DC73009DE44C /* coreaudio.c */, + 96AFAEEC16C1DC73009DE44C /* hermite.c */, + 96366C4F16C9A4E100D64A22 /* resampler.c */, + 96AFAEF316C1DC73009DE44C /* resampler.h */, + 96AFAEF716C1DC73009DE44C /* sinc.c */, + 96AFAEF816C1DC73009DE44C /* sinc_neon.S */, + 96AFAEFD16C1DC73009DE44C /* utils.c */, + 96AFAEFE16C1DC73009DE44C /* utils.h */, + 96AFAEFF16C1DC73009DE44C /* utils_neon.S */, + ); + name = audio; + path = ../audio; + sourceTree = ""; + }; + 96AFAEEA16C1DC73009DE44C /* ext */ = { + isa = PBXGroup; + children = ( + 96AFAEEB16C1DC73009DE44C /* rarch_dsp.h */, + ); + path = ext; + sourceTree = ""; + }; + 96AFAF2316C1DFC8009DE44C /* compat */ = { + isa = PBXGroup; + children = ( + 96AFAF2716C1DFC8009DE44C /* rxml */, + 96AFAF2416C1DFC8009DE44C /* compat.c */, + 96AFAF2516C1DFC8009DE44C /* getopt_rarch.h */, + 96AFAF2616C1DFC8009DE44C /* posix_string.h */, + 96AFAF2C16C1DFC8009DE44C /* strl.h */, + ); + name = compat; + path = ../compat; + sourceTree = ""; + }; + 96AFAF2716C1DFC8009DE44C /* rxml */ = { + isa = PBXGroup; + children = ( + 96AFAF2916C1DFC8009DE44C /* rxml.c */, + 96AFAF2A16C1DFC8009DE44C /* rxml.h */, + ); + path = rxml; + sourceTree = ""; + }; + 96AFAF3116C1E00A009DE44C /* gfx */ = { + isa = PBXGroup; + children = ( + 96AFAF3216C1E00A009DE44C /* context */, + 96AFAF4416C1E00A009DE44C /* fonts */, + 96AFAF5C16C1E00A009DE44C /* math */, + 96AFAF6516C1E00A009DE44C /* rpng */, + 96AFAF6A16C1E00A009DE44C /* scaler */, + 96AFAF5416C1E00A009DE44C /* gfx_common.c */, + 96AFAF5516C1E00A009DE44C /* gfx_common.h */, + 96AFAF5616C1E00A009DE44C /* gfx_context.c */, + 96AFAF5716C1E00A009DE44C /* gfx_context.h */, + 96AFAF5816C1E00A009DE44C /* gl.c */, + 96AFAF5916C1E00A009DE44C /* gl_common.h */, + 96AFAF5A16C1E00A009DE44C /* image.c */, + 96AFAF5B16C1E00A009DE44C /* image.h */, + 96AFAF7616C1E00A009DE44C /* shader_common.h */, + 96AFAF7716C1E00A009DE44C /* shader_glsl.c */, + 96AFAF7816C1E00A009DE44C /* shader_glsl.h */, + 96AFAF7B16C1E00A009DE44C /* state_tracker.c */, + 96AFAF7C16C1E00A009DE44C /* state_tracker.h */, + ); + name = gfx; + path = ../gfx; + sourceTree = ""; + }; + 96AFAF3216C1E00A009DE44C /* context */ = { + isa = PBXGroup; + children = ( + 962979EE16C3EA3E00E6DCE0 /* ioseagl_ctx.c */, + ); + path = context; + sourceTree = ""; + }; + 96AFAF4416C1E00A009DE44C /* fonts */ = { + isa = PBXGroup; + children = ( + 96AFAF4516C1E00A009DE44C /* bitmap.bin */, + 96AFAF4616C1E00A009DE44C /* bitmap.bmp */, + 96AFAF4716C1E00A009DE44C /* bitmap.h */, + 96AFAF4816C1E00A009DE44C /* bitmapfont.c */, + 96AFAF4B16C1E00A009DE44C /* fonts.c */, + 96AFAF4C16C1E00A009DE44C /* fonts.h */, + 96AFAF4D16C1E00A009DE44C /* freetype.c */, + 96AFAF4E16C1E00A009DE44C /* gl_font.c */, + 96AFAF4F16C1E00A009DE44C /* gl_font.h */, + 96AFAF5016C1E00A009DE44C /* gl_raster_font.c */, + ); + path = fonts; + sourceTree = ""; + }; + 96AFAF5C16C1E00A009DE44C /* math */ = { + isa = PBXGroup; + children = ( + 96AFAF5D16C1E00A009DE44C /* matrix.c */, + 96AFAF5E16C1E00A009DE44C /* matrix.h */, + 96AFAF5F16C1E00A009DE44C /* matrix_3x3.c */, + 96AFAF6016C1E00A009DE44C /* matrix_3x3.h */, + ); + path = math; + sourceTree = ""; + }; + 96AFAF6516C1E00A009DE44C /* rpng */ = { + isa = PBXGroup; + children = ( + 96AFAF6716C1E00A009DE44C /* rpng.c */, + 96AFAF6816C1E00A009DE44C /* rpng.h */, + ); + path = rpng; + sourceTree = ""; + }; + 96AFAF6A16C1E00A009DE44C /* scaler */ = { + isa = PBXGroup; + children = ( + 96AFAF6B16C1E00A009DE44C /* filter.c */, + 96AFAF6C16C1E00A009DE44C /* filter.h */, + 96AFAF6D16C1E00A009DE44C /* pixconv.c */, + 96AFAF6E16C1E00A009DE44C /* pixconv.h */, + 96AFAF6F16C1E00A009DE44C /* scaler.c */, + 96AFAF7016C1E00A009DE44C /* scaler.h */, + 96AFAF7116C1E00A009DE44C /* scaler_int.c */, + 96AFAF7216C1E00A009DE44C /* scaler_int.h */, + ); + path = scaler; + sourceTree = ""; + }; + 96AFAFC716C1FBB3009DE44C /* input */ = { + isa = PBXGroup; + children = ( + 96AFAFC916C1FBC0009DE44C /* input_common.c */, + 96AFAFCA16C1FBC0009DE44C /* input_common.h */, + 96AFAFCE16C1FBC0009DE44C /* overlay.c */, + 96AFAFCF16C1FBC0009DE44C /* overlay.h */, + ); + name = input; + path = ../input; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 9614C6C216DDC018000B36EF /* RetroArch-nobtstack */ = { + isa = PBXNativeTarget; + buildConfigurationList = 9614C71B16DDC018000B36EF /* Build configuration list for PBXNativeTarget "RetroArch-nobtstack" */; + buildPhases = ( + 9614C6C316DDC018000B36EF /* Sources */, + 9614C70516DDC018000B36EF /* Frameworks */, + 9614C70F16DDC018000B36EF /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "RetroArch-nobtstack"; + productName = RetroArch; + productReference = 9614C71E16DDC018000B36EF /* RetroArch.app */; + productType = "com.apple.product-type.application"; + }; + 96AFAE2416C1D4EA009DE44C /* RetroArch */ = { + isa = PBXNativeTarget; + buildConfigurationList = 96AFAE5416C1D4EA009DE44C /* Build configuration list for PBXNativeTarget "RetroArch" */; + buildPhases = ( + 96AFAE2116C1D4EA009DE44C /* Sources */, + 96AFAE2216C1D4EA009DE44C /* Frameworks */, + 96AFAE2316C1D4EA009DE44C /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = RetroArch; + productName = RetroArch; + productReference = 96AFAE2516C1D4EA009DE44C /* RetroArch.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 96AFAE1C16C1D4EA009DE44C /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0450; + ORGANIZATIONNAME = RetroArch; + }; + buildConfigurationList = 96AFAE1F16C1D4EA009DE44C /* Build configuration list for PBXProject "RetroArch" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = 96AFAE1A16C1D4EA009DE44C; + productRefGroup = 96AFAE2616C1D4EA009DE44C /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 96AFAE2416C1D4EA009DE44C /* RetroArch */, + 9614C6C216DDC018000B36EF /* RetroArch-nobtstack */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 9614C70F16DDC018000B36EF /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 9614C71016DDC018000B36EF /* overlays in Resources */, + 9614C71116DDC018000B36EF /* InfoPlist.strings in Resources */, + 9614C71516DDC018000B36EF /* ic_dir.png in Resources */, + 9614C71616DDC018000B36EF /* ic_file.png in Resources */, + 966B9CBE16E41E7A005B61E1 /* Default-568h@2x.png in Resources */, + 966B9CC016E41E7A005B61E1 /* Default.png in Resources */, + 966B9CC216E41E7A005B61E1 /* Default@2x.png in Resources */, + 966B9CC416E41E7A005B61E1 /* Icon-72.png in Resources */, + 966B9CC616E41E7A005B61E1 /* Icon.png in Resources */, + 966B9CCA16E41EC1005B61E1 /* PauseView.xib in Resources */, + 966B9CCC16E41EC1005B61E1 /* PauseIndicatorView.xib in Resources */, + 967D647016E45428006BA1F2 /* ic_pause.png in Resources */, + 967D647616E6EA04006BA1F2 /* modules in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 96AFAE2316C1D4EA009DE44C /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 96297A2716C82FF100E6DCE0 /* overlays in Resources */, + 96AFAE3816C1D4EA009DE44C /* InfoPlist.strings in Resources */, + 962979F616C43B9500E6DCE0 /* ic_dir.png in Resources */, + 962979F716C43B9500E6DCE0 /* ic_file.png in Resources */, + 966B9CBD16E41E7A005B61E1 /* Default-568h@2x.png in Resources */, + 966B9CBF16E41E7A005B61E1 /* Default.png in Resources */, + 966B9CC116E41E7A005B61E1 /* Default@2x.png in Resources */, + 966B9CC316E41E7A005B61E1 /* Icon-72.png in Resources */, + 966B9CC516E41E7A005B61E1 /* Icon.png in Resources */, + 966B9CC916E41EC1005B61E1 /* PauseView.xib in Resources */, + 966B9CCB16E41EC1005B61E1 /* PauseIndicatorView.xib in Resources */, + 967D646F16E45428006BA1F2 /* ic_pause.png in Resources */, + 967D647516E6EA04006BA1F2 /* modules in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 9614C6C316DDC018000B36EF /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 9614C6C416DDC018000B36EF /* autosave.c in Sources */, + 9614C6C516DDC018000B36EF /* cheats.c in Sources */, + 9614C6C616DDC018000B36EF /* command.c in Sources */, + 9614C6C716DDC018000B36EF /* driver.c in Sources */, + 9614C6C816DDC018000B36EF /* dynamic.c in Sources */, + 9614C6C916DDC018000B36EF /* fifo_buffer.c in Sources */, + 9614C6CA16DDC018000B36EF /* file_extract.c in Sources */, + 9614C6CB16DDC018000B36EF /* file_path.c in Sources */, + 9614C6CC16DDC018000B36EF /* file.c in Sources */, + 9614C6CD16DDC018000B36EF /* hash.c in Sources */, + 9614C6CE16DDC018000B36EF /* message.c in Sources */, + 9614C6CF16DDC018000B36EF /* movie.c in Sources */, + 9614C6D016DDC018000B36EF /* patch.c in Sources */, + 9614C6D116DDC018000B36EF /* performance.c in Sources */, + 9614C6D216DDC018000B36EF /* retroarch.c in Sources */, + 9614C6D316DDC018000B36EF /* rewind.c in Sources */, + 9614C6D416DDC018000B36EF /* screenshot.c in Sources */, + 9614C6D516DDC018000B36EF /* settings.c in Sources */, + 9614C6D616DDC018000B36EF /* thread.c in Sources */, + 9614C6D716DDC018000B36EF /* config_file.c in Sources */, + 9614C6D816DDC018000B36EF /* utils.c in Sources */, + 9614C6D916DDC018000B36EF /* compat.c in Sources */, + 9614C6DA16DDC018000B36EF /* rxml.c in Sources */, + 9614C6DB16DDC018000B36EF /* bitmapfont.c in Sources */, + 9614C6DC16DDC018000B36EF /* fonts.c in Sources */, + 9614C6DD16DDC018000B36EF /* gl_font.c in Sources */, + 9614C6DE16DDC018000B36EF /* gl_raster_font.c in Sources */, + 9614C6DF16DDC018000B36EF /* gfx_common.c in Sources */, + 9614C6E016DDC018000B36EF /* gfx_context.c in Sources */, + 9614C6E116DDC018000B36EF /* gl.c in Sources */, + 9614C6E216DDC018000B36EF /* image.c in Sources */, + 9614C6E316DDC018000B36EF /* matrix.c in Sources */, + 9614C6E416DDC018000B36EF /* matrix_3x3.c in Sources */, + 9614C6E516DDC018000B36EF /* rpng.c in Sources */, + 9614C6E616DDC018000B36EF /* filter.c in Sources */, + 9614C6E716DDC018000B36EF /* pixconv.c in Sources */, + 9614C6E816DDC018000B36EF /* scaler.c in Sources */, + 9614C6E916DDC018000B36EF /* scaler_int.c in Sources */, + 9614C6EA16DDC018000B36EF /* shader_glsl.c in Sources */, + 9614C6EB16DDC018000B36EF /* state_tracker.c in Sources */, + 9614C6EC16DDC018000B36EF /* sinc.c in Sources */, + 9614C6ED16DDC018000B36EF /* input_common.c in Sources */, + 9614C6EE16DDC018000B36EF /* overlay.c in Sources */, + 9614C6EF16DDC018000B36EF /* ioseagl_ctx.c in Sources */, + 9614C6F016DDC018000B36EF /* RetroArch_iOS.m in Sources */, + 9614C6F116DDC018000B36EF /* main.m in Sources */, + 9614C6F216DDC018000B36EF /* resampler.c in Sources */, + 9614C6F316DDC018000B36EF /* hermite.c in Sources */, + 9614C6F416DDC018000B36EF /* coreaudio.c in Sources */, + 9614C6F516DDC018000B36EF /* RAButtonGetter.m in Sources */, + 9614C6F616DDC018000B36EF /* RASettingEnumerationList.m in Sources */, + 9614C6F716DDC018000B36EF /* RASettingsSubList.m in Sources */, + 9614C6F816DDC018000B36EF /* RASettingsList.m in Sources */, + 9614C6FA16DDC018000B36EF /* RAGameView.m in Sources */, + 9614C6FC16DDC018000B36EF /* RAModuleInfoList.m in Sources */, + 9614C6FF16DDC018000B36EF /* RAConfig.m in Sources */, + 966B9C8D16E40EFC005B61E1 /* RAInputResponder.m in Sources */, + 966B9C8E16E40F00005B61E1 /* ios_input.m in Sources */, + 966B9CAF16E41C07005B61E1 /* browser.m in Sources */, + 966B9CB116E41C07005B61E1 /* RADirectoryGrid.m in Sources */, + 966B9CB316E41C07005B61E1 /* RADirectoryList.m in Sources */, + 966B9CB516E41C07005B61E1 /* RAModuleList.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 96AFAE2116C1D4EA009DE44C /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 96AFAECA16C1D9A9009DE44C /* autosave.c in Sources */, + 96AFAECB16C1D9A9009DE44C /* cheats.c in Sources */, + 96AFAECC16C1D9A9009DE44C /* command.c in Sources */, + 96AFAECD16C1D9A9009DE44C /* driver.c in Sources */, + 96AFAECE16C1D9A9009DE44C /* dynamic.c in Sources */, + 96AFAECF16C1D9A9009DE44C /* fifo_buffer.c in Sources */, + 96AFAED016C1D9A9009DE44C /* file_extract.c in Sources */, + 96AFAED116C1D9A9009DE44C /* file_path.c in Sources */, + 96AFAED216C1D9A9009DE44C /* file.c in Sources */, + 96AFAED316C1D9A9009DE44C /* hash.c in Sources */, + 96AFAED416C1D9A9009DE44C /* message.c in Sources */, + 96AFAED516C1D9A9009DE44C /* movie.c in Sources */, + 96AFAED716C1D9A9009DE44C /* patch.c in Sources */, + 96AFAED816C1D9A9009DE44C /* performance.c in Sources */, + 96AFAED916C1D9A9009DE44C /* retroarch.c in Sources */, + 96AFAEDA16C1D9A9009DE44C /* rewind.c in Sources */, + 96AFAEDB16C1D9A9009DE44C /* screenshot.c in Sources */, + 96AFAEDC16C1D9A9009DE44C /* settings.c in Sources */, + 96AFAEDD16C1D9A9009DE44C /* thread.c in Sources */, + 96AFAEE416C1DBDB009DE44C /* config_file.c in Sources */, + 96AFAF1816C1DC73009DE44C /* utils.c in Sources */, + 96AFAF2D16C1DFC8009DE44C /* compat.c in Sources */, + 96AFAF2F16C1DFC8009DE44C /* rxml.c in Sources */, + 96AFAF8D16C1E00A009DE44C /* bitmapfont.c in Sources */, + 96AFAF8F16C1E00A009DE44C /* fonts.c in Sources */, + 96AFAF9116C1E00A009DE44C /* gl_font.c in Sources */, + 96AFAF9216C1E00A009DE44C /* gl_raster_font.c in Sources */, + 96AFAF9616C1E00A009DE44C /* gfx_common.c in Sources */, + 96AFAF9716C1E00A009DE44C /* gfx_context.c in Sources */, + 96AFAF9816C1E00A009DE44C /* gl.c in Sources */, + 96AFAF9916C1E00A009DE44C /* image.c in Sources */, + 96AFAF9A16C1E00A009DE44C /* matrix.c in Sources */, + 96AFAF9B16C1E00A009DE44C /* matrix_3x3.c in Sources */, + 96AFAF9F16C1E00A009DE44C /* rpng.c in Sources */, + 96AFAFA116C1E00A009DE44C /* filter.c in Sources */, + 96AFAFA216C1E00A009DE44C /* pixconv.c in Sources */, + 96AFAFA316C1E00A009DE44C /* scaler.c in Sources */, + 96AFAFA416C1E00A009DE44C /* scaler_int.c in Sources */, + 96AFAFA716C1E00A009DE44C /* shader_glsl.c in Sources */, + 96AFAFAC16C1E279009DE44C /* state_tracker.c in Sources */, + 96AFAFAD16C1EEE9009DE44C /* sinc.c in Sources */, + 96AFAFD416C1FBC0009DE44C /* input_common.c in Sources */, + 96CF015016C2C0B700ABF9C9 /* overlay.c in Sources */, + 962979EF16C3EA3E00E6DCE0 /* ioseagl_ctx.c in Sources */, + 96297A0C16C5AD8D00E6DCE0 /* RetroArch_iOS.m in Sources */, + 96297A0F16C5AEA100E6DCE0 /* main.m in Sources */, + 96366C5016C9A4E100D64A22 /* resampler.c in Sources */, + 96366C5216C9A4E600D64A22 /* hermite.c in Sources */, + 96366C5316C9A7C100D64A22 /* coreaudio.c in Sources */, + 963F5AC016CC522F009BBD19 /* RAButtonGetter.m in Sources */, + 963F5AC116CC522F009BBD19 /* RASettingEnumerationList.m in Sources */, + 963F5AC216CC522F009BBD19 /* RASettingsSubList.m in Sources */, + 963F5AC316CC522F009BBD19 /* RASettingsList.m in Sources */, + 963F5AC816CC523B009BBD19 /* RAGameView.m in Sources */, + 96096DD816D1ABAF00BF4499 /* RAModuleInfoList.m in Sources */, + 96C19C3016D7045700FE8D5A /* RAConfig.m in Sources */, + 966B9C8A16E40D44005B61E1 /* ios_input.m in Sources */, + 966B9C8B16E40D44005B61E1 /* ios_joypad.m in Sources */, + 966B9C8C16E40D44005B61E1 /* RAInputResponder.m in Sources */, + 966B9CA216E418B7005B61E1 /* BTDevice.m in Sources */, + 966B9CA416E418B7005B61E1 /* BTstackManager.m in Sources */, + 966B9CA616E418B7005B61E1 /* wiimote.c in Sources */, + 966B9CA716E418B7005B61E1 /* WiiMoteHelper.m in Sources */, + 966B9CAE16E41C07005B61E1 /* browser.m in Sources */, + 966B9CB016E41C07005B61E1 /* RADirectoryGrid.m in Sources */, + 966B9CB216E41C07005B61E1 /* RADirectoryList.m in Sources */, + 966B9CB416E41C07005B61E1 /* RAModuleList.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 96AFAE3616C1D4EA009DE44C /* InfoPlist.strings */ = { + isa = PBXVariantGroup; + children = ( + 96AFAE3716C1D4EA009DE44C /* en */, + ); + name = InfoPlist.strings; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 9614C71C16DDC018000B36EF /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_CXX_LIBRARY = "libstdc++"; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "RetroArch/RetroArch-Prefix.pch"; + INFOPLIST_FILE = "RetroArch copy-Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 6.1; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "\"$(SRCROOT)\"", + ); + OTHER_CFLAGS = ( + "-DHAVE_RARCH_MAIN_WRAP", + "-DIOS", + "-DHAVE_OPENGL", + "-DHAVE_FBO", + "-DHAVE_OPENGLES", + "-DHAVE_VID_CONTEXT", + "-DHAVE_OPENGLES2", + "-DHAVE_GLSL", + "-DINLINE=inline", + "-DLSB_FIRST", + "-D__LIBRETRO__", + "-DRARCH_PERFORMANCE_MODE", + "-DPACKAGE_VERSION=\\\"1.0\\\"", + "-DHAVE_COREAUDIO", + "-DHAVE_DYNAMIC", + "-DHAVE_OVERLAY", + "-DHAVE_ZLIB", + ); + PRODUCT_NAME = RetroArch; + WRAPPER_EXTENSION = app; + }; + name = Debug; + }; + 9614C71D16DDC018000B36EF /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_CXX_LIBRARY = "libstdc++"; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "RetroArch/RetroArch-Prefix.pch"; + INFOPLIST_FILE = "RetroArch copy-Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 6.1; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "\"$(SRCROOT)\"", + ); + OTHER_CFLAGS = ( + "-DNS_BLOCK_ASSERTIONS=1", + "-DNDEBUG", + "-DHAVE_RARCH_MAIN_WRAP", + "-DIOS", + "-DHAVE_OPENGL", + "-DHAVE_FBO", + "-DHAVE_OPENGLES", + "-DHAVE_VID_CONTEXT", + "-DHAVE_OPENGLES2", + "-DHAVE_GLSL", + "-DINLINE=inline", + "-DLSB_FIRST", + "-D__LIBRETRO__", + "-DRARCH_PERFORMANCE_MODE", + "-DPACKAGE_VERSION=\\\"1.0\\\"", + "-DHAVE_COREAUDIO", + "-DHAVE_DYNAMIC", + "-DHAVE_OVERLAY", + "-DHAVE_ZLIB", + ); + PRODUCT_NAME = RetroArch; + WRAPPER_EXTENSION = app; + }; + name = Release; + }; + 96AFAE5216C1D4EA009DE44C /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = ../; + IPHONEOS_DEPLOYMENT_TARGET = 6.0; + ONLY_ACTIVE_ARCH = YES; + OTHER_CFLAGS = ( + "-DHAVE_GRIFFIN", + "-DIOS", + "-DHAVE_DYNAMIC", + "-DHAVE_OPENGL", + "-DHAVE_FBO", + "-DHAVE_OPENGLES", + "-DHAVE_VID_CONTEXT", + "-DHAVE_OPENGLES2", + "-DHAVE_GLSL", + "-DINLINE=inline", + "-DLSB_FIRST", + "-DHAVE_THREAD", + "-D__LIBRETRO__", + "-DRARCH_PERFORMANCE_MODE", + "-DPACKAGE_VERSION=\\\"1.0\\\"", + "-std=gnu99", + "-DHAVE_FBO", + ); + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 96AFAE5316C1D4EA009DE44C /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = ../; + IPHONEOS_DEPLOYMENT_TARGET = 6.0; + OTHER_CFLAGS = ( + "-DNS_BLOCK_ASSERTIONS=1", + "-DNDEBUG", + "-DHAVE_GRIFFIN", + "-DIOS", + "-DHAVE_DYNAMIC", + "-DHAVE_OPENGL", + "-DHAVE_FBO", + "-DHAVE_OPENGLES", + "-DHAVE_VID_CONTEXT", + "-DHAVE_OPENGLES2", + "-DHAVE_GLSL", + "-DINLINE=inline", + "-DLSB_FIRST", + "-DHAVE_THREAD", + "-D__LIBRETRO__", + "-DRARCH_PERFORMANCE_MODE", + "-DPACKAGE_VERSION=\\\"1.0\\\"", + "-std=gnu99", + "-DHAVE_FBO", + ); + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 96AFAE5516C1D4EA009DE44C /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_CXX_LIBRARY = "libstdc++"; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "RetroArch/RetroArch-Prefix.pch"; + INFOPLIST_FILE = "RetroArch/RetroArch-Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 6.1; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "\"$(SRCROOT)\"", + "\"$(SRCROOT)/RetroArch/input/BTStack\"", + ); + OTHER_CFLAGS = ( + "-DHAVE_RARCH_MAIN_WRAP", + "-DIOS", + "-DHAVE_OPENGL", + "-DHAVE_FBO", + "-DHAVE_OPENGLES", + "-DHAVE_VID_CONTEXT", + "-DHAVE_OPENGLES2", + "-DHAVE_GLSL", + "-DINLINE=inline", + "-DLSB_FIRST", + "-D__LIBRETRO__", + "-DRARCH_PERFORMANCE_MODE", + "-DPACKAGE_VERSION=\\\"1.0\\\"", + "-DHAVE_COREAUDIO", + "-DHAVE_DYNAMIC", + "-DHAVE_OVERLAY", + "-DHAVE_ZLIB", + "-DWIIMOTE", + ); + PRODUCT_NAME = "$(TARGET_NAME)"; + WRAPPER_EXTENSION = app; + }; + name = Debug; + }; + 96AFAE5616C1D4EA009DE44C /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_CXX_LIBRARY = "libstdc++"; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "RetroArch/RetroArch-Prefix.pch"; + INFOPLIST_FILE = "RetroArch/RetroArch-Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 6.1; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "\"$(SRCROOT)\"", + "\"$(SRCROOT)/RetroArch/input/BTStack\"", + ); + OTHER_CFLAGS = ( + "-DNS_BLOCK_ASSERTIONS=1", + "-DNDEBUG", + "-DHAVE_RARCH_MAIN_WRAP", + "-DIOS", + "-DHAVE_OPENGL", + "-DHAVE_FBO", + "-DHAVE_OPENGLES", + "-DHAVE_VID_CONTEXT", + "-DHAVE_OPENGLES2", + "-DHAVE_GLSL", + "-DINLINE=inline", + "-DLSB_FIRST", + "-D__LIBRETRO__", + "-DRARCH_PERFORMANCE_MODE", + "-DPACKAGE_VERSION=\\\"1.0\\\"", + "-DHAVE_COREAUDIO", + "-DHAVE_DYNAMIC", + "-DHAVE_OVERLAY", + "-DHAVE_ZLIB", + "-DWIIMOTE", + ); + PRODUCT_NAME = "$(TARGET_NAME)"; + WRAPPER_EXTENSION = app; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 9614C71B16DDC018000B36EF /* Build configuration list for PBXNativeTarget "RetroArch-nobtstack" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 9614C71C16DDC018000B36EF /* Debug */, + 9614C71D16DDC018000B36EF /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 96AFAE1F16C1D4EA009DE44C /* Build configuration list for PBXProject "RetroArch" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 96AFAE5216C1D4EA009DE44C /* Debug */, + 96AFAE5316C1D4EA009DE44C /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 96AFAE5416C1D4EA009DE44C /* Build configuration list for PBXNativeTarget "RetroArch" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 96AFAE5516C1D4EA009DE44C /* Debug */, + 96AFAE5616C1D4EA009DE44C /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 96AFAE1C16C1D4EA009DE44C /* Project object */; +} diff --git a/ios/RetroArch.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/ios/RetroArch.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000000..6bce578a7f --- /dev/null +++ b/ios/RetroArch.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/ios/RetroArch/RAConfig.h b/ios/RetroArch/RAConfig.h new file mode 100644 index 0000000000..91f301d959 --- /dev/null +++ b/ios/RetroArch/RAConfig.h @@ -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 . + */ + +@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 diff --git a/ios/RetroArch/RAConfig.m b/ios/RetroArch/RAConfig.m new file mode 100644 index 0000000000..b0b0bc62db --- /dev/null +++ b/ios/RetroArch/RAConfig.m @@ -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 . + */ + +#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 diff --git a/ios/RetroArch/RAGameView.m b/ios/RetroArch/RAGameView.m new file mode 100644 index 0000000000..22f1d67860 --- /dev/null +++ b/ios/RetroArch/RAGameView.m @@ -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 . + */ + +#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]; +} diff --git a/ios/RetroArch/RAModuleInfoList.m b/ios/RetroArch/RAModuleInfoList.m new file mode 100644 index 0000000000..3ad1ba2c89 --- /dev/null +++ b/ios/RetroArch/RAModuleInfoList.m @@ -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 . + */ + +@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 diff --git a/ios/RetroArch/RetroArch-Info.plist b/ios/RetroArch/RetroArch-Info.plist new file mode 100644 index 0000000000..2abe058713 --- /dev/null +++ b/ios/RetroArch/RetroArch-Info.plist @@ -0,0 +1,49 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleDisplayName + ${PRODUCT_NAME} + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + libretro.${PRODUCT_NAME:rfc1034identifier} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1.0 + LSRequiresIPhoneOS + + UIApplicationExitsOnSuspend + + UIRequiredDeviceCapabilities + + armv7 + + UIStatusBarHidden + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/ios/RetroArch/RetroArch-Prefix.pch b/ios/RetroArch/RetroArch-Prefix.pch new file mode 100644 index 0000000000..ca2c72fb32 --- /dev/null +++ b/ios/RetroArch/RetroArch-Prefix.pch @@ -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 . + */ + +// +// Prefix header for all source files of the 'RetroArch' target in the 'RetroArch' project +// + +#import + +#ifndef __IPHONE_5_0 +#warning "This project uses features only available in iOS SDK 5.0 and later." +#endif + +#ifdef __OBJC__ + #import + #import + #import "views.h" + #import "RetroArch_iOS.h" +#endif diff --git a/ios/RetroArch/RetroArch_iOS.h b/ios/RetroArch/RetroArch_iOS.h new file mode 100644 index 0000000000..08bae16b3d --- /dev/null +++ b/ios/RetroArch/RetroArch_iOS.h @@ -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 . + */ + +#import + +@interface RetroArch_iOS : UINavigationController + ++ (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 diff --git a/ios/RetroArch/RetroArch_iOS.m b/ios/RetroArch/RetroArch_iOS.m new file mode 100644 index 0000000000..a40f382d3a --- /dev/null +++ b/ios/RetroArch/RetroArch_iOS.m @@ -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 . + */ + +#include +#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 + diff --git a/ios/RetroArch/browser/RADirectoryGrid.m b/ios/RetroArch/browser/RADirectoryGrid.m new file mode 100644 index 0000000000..03d7f86331 --- /dev/null +++ b/ios/RetroArch/browser/RADirectoryGrid.m @@ -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 . + */ + +#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 diff --git a/ios/RetroArch/browser/RADirectoryList.m b/ios/RetroArch/browser/RADirectoryList.m new file mode 100644 index 0000000000..57dff2cf8b --- /dev/null +++ b/ios/RetroArch/browser/RADirectoryList.m @@ -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 . + */ + +#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 diff --git a/ios/RetroArch/browser/RAModuleList.m b/ios/RetroArch/browser/RAModuleList.m new file mode 100644 index 0000000000..deac9a8c13 --- /dev/null +++ b/ios/RetroArch/browser/RAModuleList.m @@ -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 . + */ + +#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 diff --git a/ios/RetroArch/browser/browser.h b/ios/RetroArch/browser/browser.h new file mode 100644 index 0000000000..0e4acad2e4 --- /dev/null +++ b/ios/RetroArch/browser/browser.h @@ -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 . + */ + +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 diff --git a/ios/RetroArch/browser/browser.m b/ios/RetroArch/browser/browser.m new file mode 100644 index 0000000000..f933658c1e --- /dev/null +++ b/ios/RetroArch/browser/browser.m @@ -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 . + */ + +#include +#include +#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 @"/"; +} diff --git a/ios/RetroArch/en.lproj/InfoPlist.strings b/ios/RetroArch/en.lproj/InfoPlist.strings new file mode 100644 index 0000000000..477b28ff8f --- /dev/null +++ b/ios/RetroArch/en.lproj/InfoPlist.strings @@ -0,0 +1,2 @@ +/* Localized versions of Info.plist keys */ + diff --git a/ios/RetroArch/input/BTStack/BTDevice.h b/ios/RetroArch/input/BTStack/BTDevice.h new file mode 100644 index 0000000000..aa404ef6be --- /dev/null +++ b/ios/RetroArch/input/BTStack/BTDevice.h @@ -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 +#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 diff --git a/ios/RetroArch/input/BTStack/BTDevice.m b/ios/RetroArch/input/BTStack/BTDevice.m new file mode 100644 index 0000000000..dbb14ebbb6 --- /dev/null +++ b/ios/RetroArch/input/BTStack/BTDevice.m @@ -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 diff --git a/ios/RetroArch/input/BTStack/BTstackManager.h b/ios/RetroArch/input/BTStack/BTstackManager.h new file mode 100644 index 0000000000..cb1c4d8545 --- /dev/null +++ b/ios/RetroArch/input/BTStack/BTstackManager.h @@ -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 +#import +#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* _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)listener; +-(void) removeListener:(id)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* 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 diff --git a/ios/RetroArch/input/BTStack/BTstackManager.m b/ios/RetroArch/input/BTStack/BTstackManager.m new file mode 100644 index 0000000000..301f5be4b8 --- /dev/null +++ b/ios/RetroArch/input/BTStack/BTstackManager.m @@ -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)listener{ + [listeners addObject:listener]; +} + +-(void) removeListener:(id)listener{ + [listeners removeObject:listener]; +} + +// send events +-(void) sendActivated { + for (NSObject* listener in listeners) { + if ([listener respondsToSelector:@selector(activatedBTstackManager:)]){ + [listener activatedBTstackManager:self]; + } + } +} +-(void) sendActivationFailed:(BTstackError)error { + for (NSObject* listener in listeners) { + if ([listener respondsToSelector:@selector(btstackManager:activationFailed:)]){ + [listener btstackManager:self activationFailed:error]; + } + } +} +-(void) sendDeactivated { + for (NSObject* listener in listeners) { + if ([listener respondsToSelector:@selector(deactivatedBTstackManager:)]){ + [listener deactivatedBTstackManager:self]; + } + } +} +-(void) sendSleepEnter { + for (NSObject* listener in listeners) { + if ([listener respondsToSelector:@selector(sleepModeEnterBTstackManager:)]){ + [listener sleepModeEnterBTstackManager:self]; + } + } +} +-(void) sendSleepExit { + for (NSObject* listener in listeners) { + if ([listener respondsToSelector:@selector(sleepModeExtitBTstackManager:)]){ + [listener sleepModeExtitBTstackManager:self]; + } + } +} +-(void) sendDiscoveryStoppedEvent { + for (NSObject* listener in listeners) { + if ([listener respondsToSelector:@selector(discoveryStoppedBTstackManager:)]){ + [listener discoveryStoppedBTstackManager:self]; + } + } +} +-(void) sendDiscoveryInquiry{ + for (NSObject* listener in listeners) { + if ([listener respondsToSelector:@selector(discoveryInquiryBTstackManager:)]){ + [listener discoveryInquiryBTstackManager:self]; + } + } +} +-(void) sendDiscoveryQueryRemoteName:(int)index { + for (NSObject* listener in listeners) { + if ([listener respondsToSelector:@selector(btstackManager:discoveryQueryRemoteName:)]){ + [listener btstackManager:self discoveryQueryRemoteName:index]; + } + } +} +-(void) sendDeviceInfo:(BTDevice*) device{ + for (NSObject* 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 + +#import "BTstackManager.h" + +@interface WiiMoteHelper : NSObject ++ (void)startBluetooth; ++ (BOOL)isBluetoothRunning; ++ (void)stopBluetooth; +@end + diff --git a/ios/RetroArch/input/BTStack/WiiMoteHelper.m b/ios/RetroArch/input/BTStack/WiiMoteHelper.m new file mode 100644 index 0000000000..e337f6262a --- /dev/null +++ b/ios/RetroArch/input/BTStack/WiiMoteHelper.m @@ -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 +#include +#include + +#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 diff --git a/ios/RetroArch/input/BTStack/btstack/btstack.h b/ios/RetroArch/input/BTStack/btstack/btstack.h new file mode 100644 index 0000000000..03c02a0fb2 --- /dev/null +++ b/ios/RetroArch/input/BTStack/btstack/btstack.h @@ -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 + +#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 diff --git a/ios/RetroArch/input/BTStack/btstack/hci_cmds.h b/ios/RetroArch/input/BTStack/btstack/hci_cmds.h new file mode 100644 index 0000000000..a6e6bf4ea9 --- /dev/null +++ b/ios/RetroArch/input/BTStack/btstack/hci_cmds.h @@ -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 + +#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 diff --git a/ios/RetroArch/input/BTStack/btstack/linked_list.h b/ios/RetroArch/input/BTStack/btstack/linked_list.h new file mode 100644 index 0000000000..d9d4fba554 --- /dev/null +++ b/ios/RetroArch/input/BTStack/btstack/linked_list.h @@ -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 diff --git a/ios/RetroArch/input/BTStack/btstack/run_loop.h b/ios/RetroArch/input/BTStack/btstack/run_loop.h new file mode 100644 index 0000000000..5ff6a9c76f --- /dev/null +++ b/ios/RetroArch/input/BTStack/btstack/run_loop.h @@ -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 + +#ifdef HAVE_TIME +#include +#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 + diff --git a/ios/RetroArch/input/BTStack/btstack/sdp_util.h b/ios/RetroArch/input/BTStack/btstack/sdp_util.h new file mode 100644 index 0000000000..0ebb219766 --- /dev/null +++ b/ios/RetroArch/input/BTStack/btstack/sdp_util.h @@ -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 + +#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 diff --git a/ios/RetroArch/input/BTStack/btstack/utils.h b/ios/RetroArch/input/BTStack/btstack/utils.h new file mode 100644 index 0000000000..3fea5d5158 --- /dev/null +++ b/ios/RetroArch/input/BTStack/btstack/utils.h @@ -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 + +/** + * @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 + diff --git a/ios/RetroArch/input/BTStack/libBTstack.dylib b/ios/RetroArch/input/BTStack/libBTstack.dylib new file mode 100755 index 0000000000..7e3173a408 Binary files /dev/null and b/ios/RetroArch/input/BTStack/libBTstack.dylib differ diff --git a/ios/RetroArch/input/BTStack/wiimote.c b/ios/RetroArch/input/BTStack/wiimote.c new file mode 100644 index 0000000000..6f468e648b --- /dev/null +++ b/ios/RetroArch/input/BTStack/wiimote.c @@ -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 +#include +#include +#include +#include + +#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(;iaddr[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; + +} diff --git a/ios/RetroArch/input/BTStack/wiimote.h b/ios/RetroArch/input/BTStack/wiimote.h new file mode 100644 index 0000000000..43f52002f3 --- /dev/null +++ b/ios/RetroArch/input/BTStack/wiimote.h @@ -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 diff --git a/ios/RetroArch/input/RAInputResponder.h b/ios/RetroArch/input/RAInputResponder.h new file mode 100644 index 0000000000..b02b07fed3 --- /dev/null +++ b/ios/RetroArch/input/RAInputResponder.h @@ -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 . + */ + +// 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 diff --git a/ios/RetroArch/input/RAInputResponder.m b/ios/RetroArch/input/RAInputResponder.m new file mode 100644 index 0000000000..98af742500 --- /dev/null +++ b/ios/RetroArch/input/RAInputResponder.m @@ -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 . + */ + +#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 diff --git a/ios/RetroArch/input/ios_input.m b/ios/RetroArch/input/ios_input.m new file mode 100644 index 0000000000..badc1b74bd --- /dev/null +++ b/ios/RetroArch/input/ios_input.m @@ -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 . + */ + +#import "RAInputResponder.h" + +#include +#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 } +}; diff --git a/ios/RetroArch/input/ios_joypad.m b/ios/RetroArch/input/ios_joypad.m new file mode 100644 index 0000000000..929544a380 --- /dev/null +++ b/ios/RetroArch/input/ios_joypad.m @@ -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 . + */ + +#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", +}; + diff --git a/ios/RetroArch/input/keycode.h b/ios/RetroArch/input/keycode.h new file mode 100644 index 0000000000..e24fe023d4 --- /dev/null +++ b/ios/RetroArch/input/keycode.h @@ -0,0 +1,156 @@ +/* +Taken from https://github.com/depp/keycode, distributed with the following license: + +Copyright 2011-2012 Dietrich Epp +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 diff --git a/ios/RetroArch/main.m b/ios/RetroArch/main.m new file mode 100644 index 0000000000..faf433bb63 --- /dev/null +++ b/ios/RetroArch/main.m @@ -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 . + */ + +#import + +#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])); + } +} + diff --git a/ios/RetroArch/rarch_wrapper.h b/ios/RetroArch/rarch_wrapper.h new file mode 100644 index 0000000000..b53bb0a340 --- /dev/null +++ b/ios/RetroArch/rarch_wrapper.h @@ -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 . + */ + +#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 diff --git a/ios/RetroArch/settings/RAButtonGetter.m b/ios/RetroArch/settings/RAButtonGetter.m new file mode 100644 index 0000000000..bddaaabe73 --- /dev/null +++ b/ios/RetroArch/settings/RAButtonGetter.m @@ -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 . + */ + +#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 + diff --git a/ios/RetroArch/settings/RASettingEnumerationList.m b/ios/RetroArch/settings/RASettingEnumerationList.m new file mode 100644 index 0000000000..54266e3c9c --- /dev/null +++ b/ios/RetroArch/settings/RASettingEnumerationList.m @@ -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 . + */ + +#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 + diff --git a/ios/RetroArch/settings/RASettingsList.m b/ios/RetroArch/settings/RASettingsList.m new file mode 100644 index 0000000000..ccca49d031 --- /dev/null +++ b/ios/RetroArch/settings/RASettingsList.m @@ -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 . + */ + +#import +#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 diff --git a/ios/RetroArch/settings/RASettingsSubList.m b/ios/RetroArch/settings/RASettingsSubList.m new file mode 100644 index 0000000000..bd7b512091 --- /dev/null +++ b/ios/RetroArch/settings/RASettingsSubList.m @@ -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 . + */ + +#import +#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 diff --git a/ios/RetroArch/settings/settings.h b/ios/RetroArch/settings/settings.h new file mode 100644 index 0000000000..94a9c522c8 --- /dev/null +++ b/ios/RetroArch/settings/settings.h @@ -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 . + */ + +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 +- (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 diff --git a/ios/RetroArch/views.h b/ios/RetroArch/views.h new file mode 100644 index 0000000000..b475d4d689 --- /dev/null +++ b/ios/RetroArch/views.h @@ -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 . + */ + +#import +#import + +#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 diff --git a/ios/modules/desmume_libretro.info b/ios/modules/desmume_libretro.info new file mode 100644 index 0000000000..4ec998c734 --- /dev/null +++ b/ios/modules/desmume_libretro.info @@ -0,0 +1,5 @@ +display_name = "Nintendo DS" +recommended_extensions = "nds" +emuname = "DeSmuME" +manufacturer = "Nintendo" +systemname = "Nintendo DS" diff --git a/ios/modules/example.info b/ios/modules/example.info new file mode 100644 index 0000000000..d6174f49f1 --- /dev/null +++ b/ios/modules/example.info @@ -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" + diff --git a/ios/modules/gambatte_libretro.info b/ios/modules/gambatte_libretro.info new file mode 100644 index 0000000000..f5ee6ae08f --- /dev/null +++ b/ios/modules/gambatte_libretro.info @@ -0,0 +1,5 @@ +display_name = "Game Boy / Game Boy Color" +supported_extensions = "gb|gbc|dmg" +emuname = "gambatte" +manufacturer = "Nintendo" +systemname = "Game Boy Color" diff --git a/ios/modules/genesis_plus_gx_libretro.info b/ios/modules/genesis_plus_gx_libretro.info new file mode 100644 index 0000000000..f9d3ce29f7 --- /dev/null +++ b/ios/modules/genesis_plus_gx_libretro.info @@ -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)" + diff --git a/ios/modules/mednafen_ngp_libretro.info b/ios/modules/mednafen_ngp_libretro.info new file mode 100644 index 0000000000..6c6f672b99 --- /dev/null +++ b/ios/modules/mednafen_ngp_libretro.info @@ -0,0 +1,6 @@ +display_name = "Neo Geo Pocket (Color)" +supported_extensions = "ngp|ngc" +emuname = "Mednafen Neopop" +manufacturer = "SNK" +systemname = "Neo Geo Pocket (Color)" + diff --git a/ios/modules/mednafen_pce_fast_libretro.info b/ios/modules/mednafen_pce_fast_libretro.info new file mode 100644 index 0000000000..22279a08e4 --- /dev/null +++ b/ios/modules/mednafen_pce_fast_libretro.info @@ -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" + diff --git a/ios/modules/mednafen_psx_libretro.info b/ios/modules/mednafen_psx_libretro.info new file mode 100644 index 0000000000..5d1b2d54e0 --- /dev/null +++ b/ios/modules/mednafen_psx_libretro.info @@ -0,0 +1,6 @@ +display_name = "PlayStation" +supported_extensions = "cue|toc" +emuname = "Mednafen PSX" +manufacturer = "Sony" +systemname = "PlayStation" + diff --git a/ios/modules/mednafen_vb_libretro.info b/ios/modules/mednafen_vb_libretro.info new file mode 100644 index 0000000000..e889dd6390 --- /dev/null +++ b/ios/modules/mednafen_vb_libretro.info @@ -0,0 +1,6 @@ +display_name = "Virtual Boy" +supported_extensions = "vb|vboy|bin" +emuname = "Mednafen VB" +manufacturer = "Nintendo" +systemname = "Virtual Boy" + diff --git a/ios/modules/mednafen_wswan_libretro.info b/ios/modules/mednafen_wswan_libretro.info new file mode 100644 index 0000000000..29b02a79ac --- /dev/null +++ b/ios/modules/mednafen_wswan_libretro.info @@ -0,0 +1,6 @@ +display_name = "WonderSwan (Color)" +supported_extensions = "ws|wsc" +emuname = "Mednafen WonderSwan" +manufacturer = "Bandai" +systemname = "WonderSwan (Color)" + diff --git a/ios/modules/nestopia_libretro.info b/ios/modules/nestopia_libretro.info new file mode 100644 index 0000000000..cd3f8750c4 --- /dev/null +++ b/ios/modules/nestopia_libretro.info @@ -0,0 +1,6 @@ +display_name = "NES / Famicom" +supported_extensions = "nes|fds" +emuname = "Nestopia" +manufacturer = "Nintendo" +systemname = "Nintendo Entertainment System" + diff --git a/ios/modules/nxengine_libretro.info b/ios/modules/nxengine_libretro.info new file mode 100644 index 0000000000..997b771c86 --- /dev/null +++ b/ios/modules/nxengine_libretro.info @@ -0,0 +1,3 @@ +display_name = "NXEngine (Cave Story)" +supported_extensions = "exe" +emuname = "NXEngine" diff --git a/ios/modules/prboom_libretro.info b/ios/modules/prboom_libretro.info new file mode 100644 index 0000000000..a1012b43ef --- /dev/null +++ b/ios/modules/prboom_libretro.info @@ -0,0 +1,3 @@ +display_name = "PrBoom (DOOM)" +supported_extensions = "wad|iwad" +emuname = "prboom" diff --git a/ios/modules/snes9x_next_libretro.info b/ios/modules/snes9x_next_libretro.info new file mode 100644 index 0000000000..0c4577ef7e --- /dev/null +++ b/ios/modules/snes9x_next_libretro.info @@ -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" diff --git a/ios/modules/stella_libretro.info b/ios/modules/stella_libretro.info new file mode 100644 index 0000000000..99b8e27eea --- /dev/null +++ b/ios/modules/stella_libretro.info @@ -0,0 +1,6 @@ +display_name = "Atari 2600" +supported_extensions = "a26|bin" +emuname = "Stella" +manufacturer = "Atari" +systemname = "Atari 2600" + diff --git a/ios/modules/tyrquake_libretro.info b/ios/modules/tyrquake_libretro.info new file mode 100644 index 0000000000..cf2cd27b91 --- /dev/null +++ b/ios/modules/tyrquake_libretro.info @@ -0,0 +1,3 @@ +display_name = "TyrQuake" +supported_extensions = "pak" +emuname = "prboom" diff --git a/ios/modules/vba_next_libretro.info b/ios/modules/vba_next_libretro.info new file mode 100644 index 0000000000..359e618080 --- /dev/null +++ b/ios/modules/vba_next_libretro.info @@ -0,0 +1,5 @@ +display_name = "Game Boy Advance" +supported_extensions = "gba" +emuname = "VBA Next" +manufacturer = "Nintendo" +systemname = "Game Boy Advance" diff --git a/settings.c b/settings.c index 9a61be15d9..20351b0dc3 100644 --- a/settings.c +++ b/settings.c @@ -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: