From 0205fd10aef03caf19318d2b3ab9e427c352e6d0 Mon Sep 17 00:00:00 2001 From: meancoot Date: Sun, 5 May 2013 10:18:24 -0400 Subject: [PATCH] (iOS) Add untested iCade support --- ios/RetroArch/main.m | 191 +++++++++++++++++++----------- ios/RetroArch/settings/settings.m | 1 + 2 files changed, 121 insertions(+), 71 deletions(-) diff --git a/ios/RetroArch/main.m b/ios/RetroArch/main.m index 3845e100e2..f3d9496ec4 100644 --- a/ios/RetroArch/main.m +++ b/ios/RetroArch/main.m @@ -42,13 +42,16 @@ static ios_input_data_t g_input_data; +static bool use_icade; +static uint32_t icade_buttons; + // Input helpers void ios_copy_input(ios_input_data_t* data) { // Call only from main thread memcpy(data, &g_input_data, sizeof(g_input_data)); - data->pad_buttons = btpad_get_buttons(); + data->pad_buttons = btpad_get_buttons() | (use_icade ? icade_buttons : 0); for (int i = 0; i < 4; i ++) data->pad_axis[i] = btpad_get_axis(i); @@ -64,6 +67,112 @@ static uint32_t translate_mods(uint32_t flags) return result; } +static void handle_touch_event(NSArray* touches) +{ + const int numTouches = [touches count]; + const float scale = [[UIScreen mainScreen] scale]; + + g_input_data.touch_count = 0; + + for(int i = 0; i != numTouches && g_input_data.touch_count < MAX_TOUCHES; i ++) + { + UITouch* touch = [touches objectAtIndex:i]; + const CGPoint coord = [touch locationInView:touch.view]; + + if (touch.phase != UITouchPhaseEnded && touch.phase != UITouchPhaseCancelled) + { + g_input_data.touches[g_input_data.touch_count ].screen_x = coord.x * scale; + g_input_data.touches[g_input_data.touch_count ++].screen_y = coord.y * scale; + } + } +} + +static void handle_key_event(unsigned keycode, bool down, uint8_t* eventMem) +{ + if (keycode < MAX_KEYS) + g_input_data.keys[keycode] = down; + + // Key events + // ios_add_key_event(eventType == GSEVENT_TYPE_KEYDOWN, data[0], data[1], translate_mods(*(uint32_t*)&eventMem[0x30])); + // printf("%d %d %d %08X\n", data[0], data[1], data[2], *(uint32_t*)&eventMem[0x30]); +} + +static void handle_modifier_key_event(uint8_t* eventMem) +{ +#if 0 + static const struct + { + unsigned key; + unsigned retrokey; + uint32_t hidid; + } modmap[] = + { + { 0x37, RETROK_LMETA, KEY_LeftGUI }, + { 0x36, RETROK_RMETA, KEY_RightGUI }, + { 0x38, RETROK_LSHIFT, KEY_LeftShift }, + { 0x3C, RETROK_RSHIFT, KEY_RightShift }, + { 0x3A, RETROK_LALT, KEY_LeftAlt }, + { 0x3D, RETROK_RALT, KEY_RightAlt }, + { 0x3B, RETROK_LCTRL, KEY_LeftControl }, + { 0x3E, RETROK_RCTRL, KEY_RightControl }, + { 0x39, RETROK_CAPSLOCK, KEY_CapsLock }, + { 0, RETROK_UNKNOWN, 0} + }; + + static bool keystate[9]; + + // TODO: Not sure how to add this. + // The key value indicates the key that was pressed or released. + // The flags indicates the current modifier state. + // There is no way to determine if this is a keydown or a keyup event, + // except to look at the flags, but the bits in flags are shared between + // the left and right versions of a given key pair. + // The current method assumes that all key up and down events are processed, + // otherwise it may become confused. + const uint32_t key = *(uint32_t*)&eventMem[0x3C]; + + for (int i = 0; i < 9; i ++) + { + if (key == modmap[i].key) + { + keystate[i] = !keystate[i]; + g_input_data.keys[modmap[i].hidid] = keystate[i]; + // ios_add_key_event(keystate[i], modmap[i].retrokey, 0, translate_mods(*(uint32_t*)&eventMem[0x30])); + } + } + +#endif +} + +static void handle_icade_event(unsigned keycode) +{ + static const struct + { + bool up; + int button; + } icade_map[0x20] = + { + { false, -1 }, { false, -1 }, { false, -1 }, { false, -1 }, // 0 + { false, 2 }, { false, -1 }, { true , 3 }, { false, 3 }, // 4 + { true , 0 }, { true, 5 }, { true , 7 }, { false, 8 }, // 8 + { false, 6 }, { false, 9 }, { false, 10 }, { false, 11 }, // C + { true , 6 }, { true , 9 }, { false, 7 }, { true, 10 }, // 0 + { true , 2 }, { true , 8 }, { false, -1 }, { true , 4 }, // 4 + { false, 5 }, { true , 11 }, { false, 0 }, { false, 1 }, // 8 + { false, 4 }, { true , 1 }, { false, -1 }, { false, -1 } // C + }; + + if ((keycode < 0x20) && (icade_map[keycode].button >= 0)) + { + const int button = icade_map[keycode].button; + + if (icade_map[keycode].up) + icade_buttons &= ~(1 << button); + else + icade_buttons |= (1 << button); + } +} + @interface RApplication : UIApplication @end @@ -74,88 +183,26 @@ static uint32_t translate_mods(uint32_t flags) [super sendEvent:event]; if ([[event allTouches] count]) - { - NSArray* touches = [[event allTouches] allObjects]; - const int numTouches = [touches count]; - const float scale = [[UIScreen mainScreen] scale]; + handle_touch_event(event.allTouches.allObjects); - g_input_data.touch_count = 0; - - for(int i = 0; i != numTouches && g_input_data.touch_count < MAX_TOUCHES; i ++) - { - UITouch* touch = [touches objectAtIndex:i]; - const CGPoint coord = [touch locationInView:touch.view]; - - if (touch.phase != UITouchPhaseEnded && touch.phase != UITouchPhaseCancelled) - { - g_input_data.touches[g_input_data.touch_count ].screen_x = coord.x * scale; - g_input_data.touches[g_input_data.touch_count ++].screen_y = coord.y * scale; - } - } - } // Stolen from: http://nacho4d-nacho4d.blogspot.com/2012/01/catching-keyboard-events-in-ios.html // TODO: Key events need to be synced, I just disabled them because the data isn't available on device (only in simulator) else if ([event respondsToSelector:@selector(_gsEvent)]) { uint8_t* eventMem = (uint8_t*)(void*)CFBridgingRetain([event performSelector:@selector(_gsEvent)]); int eventType = eventMem ? *(int*)&eventMem[8] : 0; - + if (eventType == GSEVENT_TYPE_KEYDOWN || eventType == GSEVENT_TYPE_KEYUP) { - uint16_t* data = (uint16_t*)&eventMem[0x3C]; + uint16_t key = *(uint16_t*)&eventMem[0x3C]; - if (data[0] < MAX_KEYS) - g_input_data.keys[data[0]] = (eventType == GSEVENT_TYPE_KEYDOWN) ? 1 : 0; - - // Key events - // ios_add_key_event(eventType == GSEVENT_TYPE_KEYDOWN, data[0], data[1], translate_mods(*(uint32_t*)&eventMem[0x30])); - // printf("%d %d %d %08X\n", data[0], data[1], data[2], *(uint32_t*)&eventMem[0x30]); + if (!use_icade) + handle_key_event(key, eventType == GSEVENT_TYPE_KEYDOWN, eventMem); + else if (eventType == GSEVENT_TYPE_KEYDOWN) + handle_icade_event(key); } -#if 0 else if(eventType == GSEVENT_TYPE_MODS) - { - static const struct - { - unsigned key; - unsigned retrokey; - uint32_t hidid; - } modmap[] = - { - { 0x37, RETROK_LMETA, KEY_LeftGUI }, - { 0x36, RETROK_RMETA, KEY_RightGUI }, - { 0x38, RETROK_LSHIFT, KEY_LeftShift }, - { 0x3C, RETROK_RSHIFT, KEY_RightShift }, - { 0x3A, RETROK_LALT, KEY_LeftAlt }, - { 0x3D, RETROK_RALT, KEY_RightAlt }, - { 0x3B, RETROK_LCTRL, KEY_LeftControl }, - { 0x3E, RETROK_RCTRL, KEY_RightControl }, - { 0x39, RETROK_CAPSLOCK, KEY_CapsLock }, - { 0, RETROK_UNKNOWN, 0} - }; - - static bool keystate[9]; - - // TODO: Not sure how to add this. - // The key value indicates the key that was pressed or released. - // The flags indicates the current modifier state. - // There is no way to determine if this is a keydown or a keyup event, - // except to look at the flags, but the bits in flags are shared between - // the left and right versions of a given key pair. - // The current method assumes that all key up and down events are processed, - // otherwise it may become confused. - const uint32_t key = *(uint32_t*)&eventMem[0x3C]; - - for (int i = 0; i < 9; i ++) - { - if (key == modmap[i].key) - { - keystate[i] = !keystate[i]; - g_input_data.keys[modmap[i].hidid] = keystate[i]; - // ios_add_key_event(keystate[i], modmap[i].retrokey, 0, translate_mods(*(uint32_t*)&eventMem[0x30])); - } - } - } -#endif + handle_modifier_key_event(eventMem); CFBridgingRelease(eventMem); } @@ -322,6 +369,8 @@ static void event_reload_config(void* userdata) bool autoStartBluetooth = false; if (conf && config_get_bool(conf, "ios_auto_bluetooth", &autoStartBluetooth) && autoStartBluetooth) [self startBluetooth]; + if (conf) + config_get_bool(conf, "ios_use_icade", &use_icade); config_file_free(conf); } diff --git a/ios/RetroArch/settings/settings.m b/ios/RetroArch/settings/settings.m index 468fe5bb2e..ed927d5125 100644 --- a/ios/RetroArch/settings/settings.m +++ b/ios/RetroArch/settings/settings.m @@ -150,6 +150,7 @@ static RASettingData* custom_action(NSString* action) custom_action(@"Module Info"), custom_action(@"Diagnostic Log"), boolean_setting(config, @"ios_auto_bluetooth", @"Auto Enable Bluetooth", @"false"), + boolean_setting(config, @"ios_use_icade", @"Native BT is iCade", @"false"), nil], [NSArray arrayWithObjects:@"Video",