From 3a5e9ff79a2c4e85ae34b079fa6a277e8ffa5cda Mon Sep 17 00:00:00 2001 From: meancoot Date: Tue, 31 Dec 2013 12:52:24 -0500 Subject: [PATCH 1/4] (iOS) Make cocoa menu button image show up more constantly. --- apple/common/RAGameView.m | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/apple/common/RAGameView.m b/apple/common/RAGameView.m index 409e6d2111..28aae118ed 100644 --- a/apple/common/RAGameView.m +++ b/apple/common/RAGameView.m @@ -166,10 +166,24 @@ static bool g_is_syncing = true; [g_view addSubview:g_pause_indicator_view]; self.view = g_view; + + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(showPauseIndicator) name:UIApplicationWillEnterForegroundNotification object:nil]; return self; } // Pause Menus +- (void)viewDidAppear:(BOOL)animated +{ + [self showPauseIndicator]; +} + +- (void)showPauseIndicator +{ + g_pause_indicator_view.alpha = 1.0f; + [NSObject cancelPreviousPerformRequestsWithTarget:g_instance]; + [g_instance performSelector:@selector(hidePauseButton) withObject:g_instance afterDelay:3.0f]; +} + - (void)viewWillLayoutSubviews { UIInterfaceOrientation orientation = self.interfaceOrientation; @@ -419,16 +433,8 @@ static RAScreen* get_chosen_screen() bool apple_gfx_ctx_init(void) { // Make sure the view was created - [RAGameView get]; - -#ifdef IOS // Show pause button for a few seconds, so people know it's there - g_pause_indicator_view.alpha = 1.0f; - [NSObject cancelPreviousPerformRequestsWithTarget:g_instance]; - [g_instance performSelector:@selector(hidePauseButton) withObject:g_instance afterDelay:3.0f]; -#endif - + [RAGameView get]; g_initialized = true; - return true; } From 1ff9630d74a936be0cac03efeb707da1d50a1e49 Mon Sep 17 00:00:00 2001 From: meancoot Date: Thu, 2 Jan 2014 16:41:34 -0500 Subject: [PATCH 2/4] Add support for mapping keyboard keys to input overlays. --- input/overlay.c | 171 ++++++++++++++++++++++++++++++- input/overlay.h | 1 + media/overlays/qwerty/qwerty.cfg | 107 +++++++++++++++++++ media/overlays/qwerty/qwerty.png | Bin 0 -> 20806 bytes retroarch.c | 5 + 5 files changed, 282 insertions(+), 2 deletions(-) create mode 100644 media/overlays/qwerty/qwerty.cfg create mode 100644 media/overlays/qwerty/qwerty.png diff --git a/input/overlay.c b/input/overlay.c index eead9243c8..40e2ad8ef6 100644 --- a/input/overlay.c +++ b/input/overlay.c @@ -35,7 +35,8 @@ enum overlay_type { OVERLAY_TYPE_BUTTONS = 0, OVERLAY_TYPE_ANALOG_LEFT, - OVERLAY_TYPE_ANALOG_RIGHT + OVERLAY_TYPE_ANALOG_RIGHT, + OVERLAY_TYPE_KEYBOARD }; struct overlay_desc @@ -181,6 +182,162 @@ static unsigned input_str_to_bind(const char *str) return RARCH_BIND_LIST_END; } +static const struct str_to_bind_map str_to_keyboard[] = { + { "retrok_backspace", RETROK_BACKSPACE }, + { "retrok_tab", RETROK_TAB }, + { "retrok_clear", RETROK_CLEAR }, + { "retrok_return", RETROK_RETURN }, + { "retrok_pause", RETROK_PAUSE }, + { "retrok_escape", RETROK_ESCAPE }, + { "retrok_space", RETROK_SPACE }, + { "retrok_exclaim", RETROK_EXCLAIM }, + { "retrok_quotedbl", RETROK_QUOTEDBL }, + { "retrok_hash", RETROK_HASH }, + { "retrok_dollar", RETROK_DOLLAR }, + { "retrok_ampersand", RETROK_AMPERSAND }, + { "retrok_quote", RETROK_QUOTE }, + { "retrok_leftparen", RETROK_LEFTPAREN }, + { "retrok_rightparen", RETROK_RIGHTPAREN }, + { "retrok_asterisk", RETROK_ASTERISK }, + { "retrok_plus", RETROK_PLUS }, + { "retrok_comma", RETROK_COMMA }, + { "retrok_minus", RETROK_MINUS }, + { "retrok_period", RETROK_PERIOD }, + { "retrok_slash", RETROK_SLASH }, + { "retrok_0", RETROK_0 }, + { "retrok_1", RETROK_1 }, + { "retrok_2", RETROK_2 }, + { "retrok_3", RETROK_3 }, + { "retrok_4", RETROK_4 }, + { "retrok_5", RETROK_5 }, + { "retrok_6", RETROK_6 }, + { "retrok_7", RETROK_7 }, + { "retrok_8", RETROK_8 }, + { "retrok_9", RETROK_9 }, + { "retrok_colon", RETROK_COLON }, + { "retrok_semicolon", RETROK_SEMICOLON }, + { "retrok_less", RETROK_LESS }, + { "retrok_equals", RETROK_EQUALS }, + { "retrok_greater", RETROK_GREATER }, + { "retrok_question", RETROK_QUESTION }, + { "retrok_at", RETROK_AT }, + { "retrok_leftbracket", RETROK_LEFTBRACKET }, + { "retrok_backslash", RETROK_BACKSLASH }, + { "retrok_rightbracket", RETROK_RIGHTBRACKET }, + { "retrok_caret", RETROK_CARET }, + { "retrok_underscore", RETROK_UNDERSCORE }, + { "retrok_backquote", RETROK_BACKQUOTE }, + { "retrok_a", RETROK_a }, + { "retrok_b", RETROK_b }, + { "retrok_c", RETROK_c }, + { "retrok_d", RETROK_d }, + { "retrok_e", RETROK_e }, + { "retrok_f", RETROK_f }, + { "retrok_g", RETROK_g }, + { "retrok_h", RETROK_h }, + { "retrok_i", RETROK_i }, + { "retrok_j", RETROK_j }, + { "retrok_k", RETROK_k }, + { "retrok_l", RETROK_l }, + { "retrok_m", RETROK_m }, + { "retrok_n", RETROK_n }, + { "retrok_o", RETROK_o }, + { "retrok_p", RETROK_p }, + { "retrok_q", RETROK_q }, + { "retrok_r", RETROK_r }, + { "retrok_s", RETROK_s }, + { "retrok_t", RETROK_t }, + { "retrok_u", RETROK_u }, + { "retrok_v", RETROK_v }, + { "retrok_w", RETROK_w }, + { "retrok_x", RETROK_x }, + { "retrok_y", RETROK_y }, + { "retrok_z", RETROK_z }, + { "retrok_delete", RETROK_DELETE }, + + { "retrok_kp0", RETROK_KP0 }, + { "retrok_kp1", RETROK_KP1 }, + { "retrok_kp2", RETROK_KP2 }, + { "retrok_kp3", RETROK_KP3 }, + { "retrok_kp4", RETROK_KP4 }, + { "retrok_kp5", RETROK_KP5 }, + { "retrok_kp6", RETROK_KP6 }, + { "retrok_kp7", RETROK_KP7 }, + { "retrok_kp8", RETROK_KP8 }, + { "retrok_kp9", RETROK_KP9 }, + { "retrok_kp_period", RETROK_KP_PERIOD }, + { "retrok_kp_divide", RETROK_KP_DIVIDE }, + { "retrok_kp_multiply", RETROK_KP_MULTIPLY }, + { "retrok_kp_minus", RETROK_KP_MINUS }, + { "retrok_kp_plus", RETROK_KP_PLUS }, + { "retrok_kp_enter", RETROK_KP_ENTER }, + { "retrok_kp_equals", RETROK_KP_EQUALS }, + + { "retrok_up", RETROK_UP }, + { "retrok_down", RETROK_DOWN }, + { "retrok_right", RETROK_RIGHT }, + { "retrok_left", RETROK_LEFT }, + { "retrok_insert", RETROK_INSERT }, + { "retrok_home", RETROK_HOME }, + { "retrok_end", RETROK_END }, + { "retrok_pageup", RETROK_PAGEUP }, + { "retrok_pagedown", RETROK_PAGEDOWN }, + + { "retrok_f1", RETROK_F1 }, + { "retrok_f2", RETROK_F2 }, + { "retrok_f3", RETROK_F3 }, + { "retrok_f4", RETROK_F4 }, + { "retrok_f5", RETROK_F5 }, + { "retrok_f6", RETROK_F6 }, + { "retrok_f7", RETROK_F7 }, + { "retrok_f8", RETROK_F8 }, + { "retrok_f9", RETROK_F9 }, + { "retrok_f10", RETROK_F10 }, + { "retrok_f11", RETROK_F11 }, + { "retrok_f12", RETROK_F12 }, + { "retrok_f13", RETROK_F13 }, + { "retrok_f14", RETROK_F14 }, + { "retrok_f15", RETROK_F15 }, + + { "retrok_numlock", RETROK_NUMLOCK }, + { "retrok_capslock", RETROK_CAPSLOCK }, + { "retrok_scrollock", RETROK_SCROLLOCK }, + { "retrok_rshift", RETROK_RSHIFT }, + { "retrok_lshift", RETROK_LSHIFT }, + { "retrok_rctrl", RETROK_RCTRL }, + { "retrok_lctrl", RETROK_LCTRL }, + { "retrok_ralt", RETROK_RALT }, + { "retrok_lalt", RETROK_LALT }, + { "retrok_rmeta", RETROK_RMETA }, + { "retrok_lmeta", RETROK_LMETA }, + { "retrok_lsuper", RETROK_LSUPER }, + { "retrok_rsuper", RETROK_RSUPER }, + { "retrok_mode", RETROK_MODE }, + { "retrok_compose", RETROK_COMPOSE }, + + { "retrok_help", RETROK_HELP }, + { "retrok_print", RETROK_PRINT }, + { "retrok_sysreq", RETROK_SYSREQ }, + { "retrok_break", RETROK_BREAK }, + { "retrok_menu", RETROK_MENU }, + { "retrok_power", RETROK_POWER }, + { "retrok_euro", RETROK_EURO }, + { "retrok_undo", RETROK_UNDO }, +}; + +static unsigned input_str_to_keyboard(const char *str) +{ + unsigned i; + for (i = 0; i < ARRAY_SIZE(str_to_keyboard); i++) + { + if (!strcmp(str_to_keyboard[i].str, str)) + return str_to_keyboard[i].bind; + } + + RARCH_ERR("[Overlay] Unknown keyboard key: %s.\n", str); + return RETROK_UNKNOWN; +} + static void input_overlay_scale(struct overlay *overlay, float scale) { size_t i; @@ -322,6 +479,11 @@ static bool input_overlay_load_desc(input_overlay_t *ol, config_file_t *conf, st desc->type = OVERLAY_TYPE_ANALOG_LEFT; else if (strcmp(key, "analog_right") == 0) desc->type = OVERLAY_TYPE_ANALOG_RIGHT; + else if (strstr(key, "retrok_") == key) + { + desc->type = OVERLAY_TYPE_KEYBOARD; + desc->key_mask = input_str_to_keyboard(key); + } else { const char *tmp; @@ -357,7 +519,7 @@ static bool input_overlay_load_desc(input_overlay_t *ol, config_file_t *conf, st goto end; } - if (desc->type != OVERLAY_TYPE_BUTTONS) + if (desc->type == OVERLAY_TYPE_ANALOG_LEFT || desc->type == OVERLAY_TYPE_ANALOG_RIGHT) { if (desc->hitbox != OVERLAY_HITBOX_RADIAL) { @@ -760,6 +922,11 @@ void input_overlay_poll(input_overlay_t *ol, input_overlay_state_t *out, int16_t if (mask & (UINT64_C(1) << RARCH_OVERLAY_NEXT)) ol->next_index = desc->next_index; } + else if (desc->type == OVERLAY_TYPE_KEYBOARD) + { + if (desc->key_mask < RETROK_LAST) + out->keys[desc->key_mask] = 1; + } else { float x_dist = x - desc->x; diff --git a/input/overlay.h b/input/overlay.h index 0ea51dddb2..ce0afbee4c 100644 --- a/input/overlay.h +++ b/input/overlay.h @@ -34,6 +34,7 @@ typedef struct input_overlay_state { uint64_t buttons; // This is a bitmask of (1 << key_bind_id). int16_t analog[4]; // Left X, Left Y, Right X, Right Y + bool keys[RETROK_LAST]; } input_overlay_state_t; input_overlay_t *input_overlay_new(const char *overlay); diff --git a/media/overlays/qwerty/qwerty.cfg b/media/overlays/qwerty/qwerty.cfg new file mode 100644 index 0000000000..d765e18106 --- /dev/null +++ b/media/overlays/qwerty/qwerty.cfg @@ -0,0 +1,107 @@ +overlays = 1 +overlay0_normalized = true +overlay0_full_screen = true +overlay0_descs = 101 +overlay0_overlay = qwerty.png + +overlay0_desc0 = "retrok_escape,0.020833,0.784722,rect,0.020833,0.015625" +overlay0_desc1 = "retrok_f1,0.108796,0.784722,rect,0.020833,0.015625" +overlay0_desc2 = "retrok_f2,0.152778,0.784722,rect,0.020833,0.015625" +overlay0_desc3 = "retrok_f3,0.196759,0.784722,rect,0.020833,0.015625" +overlay0_desc4 = "retrok_f4,0.240741,0.784722,rect,0.020833,0.015625" +overlay0_desc5 = "retrok_f5,0.307870,0.784722,rect,0.020833,0.015625" +overlay0_desc6 = "retrok_f6,0.351852,0.784722,rect,0.020833,0.015625" +overlay0_desc7 = "retrok_f7,0.395833,0.784722,rect,0.020833,0.015625" +overlay0_desc8 = "retrok_f8,0.439815,0.784722,rect,0.020833,0.015625" +overlay0_desc9 = "retrok_f9,0.506944,0.784722,rect,0.020833,0.015625" +overlay0_desc10 = "retrok_f10,0.550926,0.784722,rect,0.020833,0.015625" +overlay0_desc11 = "retrok_f11,0.594907,0.784722,rect,0.020833,0.015625" +overlay0_desc12 = "retrok_f12,0.638889,0.784722,rect,0.020833,0.015625" +overlay0_desc13 = "retrok_print,0.699074,0.784722,rect,0.020833,0.015625" +overlay0_desc14 = "retrok_scrollock,0.743056,0.784722,rect,0.020833,0.015625" +overlay0_desc15 = "retrok_pause,0.787037,0.784722,rect,0.020833,0.015625" +overlay0_desc16 = "retrok_tilde,0.020833,0.852431,rect,0.020833,0.015625" +overlay0_desc17 = "retrok_1,0.064815,0.852431,rect,0.020833,0.015625" +overlay0_desc18 = "retrok_2,0.108796,0.852431,rect,0.020833,0.015625" +overlay0_desc19 = "retrok_3,0.152778,0.852431,rect,0.020833,0.015625" +overlay0_desc20 = "retrok_4,0.196759,0.852431,rect,0.020833,0.015625" +overlay0_desc21 = "retrok_5,0.240741,0.852431,rect,0.020833,0.015625" +overlay0_desc22 = "retrok_6,0.284722,0.852431,rect,0.020833,0.015625" +overlay0_desc23 = "retrok_7,0.328704,0.852431,rect,0.020833,0.015625" +overlay0_desc24 = "retrok_8,0.372685,0.852431,rect,0.020833,0.015625" +overlay0_desc25 = "retrok_9,0.416667,0.852431,rect,0.020833,0.015625" +overlay0_desc26 = "retrok_0,0.460648,0.852431,rect,0.020833,0.015625" +overlay0_desc27 = "retrok_minus,0.504630,0.852431,rect,0.020833,0.015625" +overlay0_desc28 = "retrok_equals,0.548611,0.852431,rect,0.020833,0.015625" +overlay0_desc29 = "retrok_backspace,0.615741,0.852431,rect,0.043981,0.015625" +overlay0_desc30 = "retrok_tab,0.032407,0.885417,rect,0.032407,0.015625" +overlay0_desc31 = "retrok_q,0.087963,0.885417,rect,0.020833,0.015625" +overlay0_desc32 = "retrok_w,0.131944,0.885417,rect,0.020833,0.015625" +overlay0_desc33 = "retrok_e,0.175926,0.885417,rect,0.020833,0.015625" +overlay0_desc34 = "retrok_r,0.219907,0.885417,rect,0.020833,0.015625" +overlay0_desc35 = "retrok_t,0.263889,0.885417,rect,0.020833,0.015625" +overlay0_desc36 = "retrok_y,0.307870,0.885417,rect,0.020833,0.015625" +overlay0_desc37 = "retrok_u,0.351852,0.885417,rect,0.020833,0.015625" +overlay0_desc38 = "retrok_i,0.395833,0.885417,rect,0.020833,0.015625" +overlay0_desc39 = "retrok_o,0.439815,0.885417,rect,0.020833,0.015625" +overlay0_desc40 = "retrok_p,0.483796,0.885417,rect,0.020833,0.015625" +overlay0_desc41 = "retrok_leftbracket,0.527778,0.885417,rect,0.020833,0.015625" +overlay0_desc42 = "retrok_rightbracket,0.571759,0.885417,rect,0.020833,0.015625" +overlay0_desc43 = "retrok_backslash,0.627315,0.885417,rect,0.032407,0.015625" +overlay0_desc44 = "retrok_capslock,0.038194,0.918403,rect,0.038194,0.015625" +overlay0_desc45 = "retrok_a,0.099537,0.918403,rect,0.020833,0.015625" +overlay0_desc46 = "retrok_s,0.143519,0.918403,rect,0.020833,0.015625" +overlay0_desc47 = "retrok_d,0.187500,0.918403,rect,0.020833,0.015625" +overlay0_desc48 = "retrok_f,0.231481,0.918403,rect,0.020833,0.015625" +overlay0_desc49 = "retrok_g,0.275463,0.918403,rect,0.020833,0.015625" +overlay0_desc50 = "retrok_h,0.319444,0.918403,rect,0.020833,0.015625" +overlay0_desc51 = "retrok_j,0.363426,0.918403,rect,0.020833,0.015625" +overlay0_desc52 = "retrok_k,0.407407,0.918403,rect,0.020833,0.015625" +overlay0_desc53 = "retrok_l,0.451389,0.918403,rect,0.020833,0.015625" +overlay0_desc54 = "retrok_semicolon,0.495370,0.918403,rect,0.020833,0.015625" +overlay0_desc55 = "retrok_quote,0.539352,0.918403,rect,0.020833,0.015625" +overlay0_desc56 = "retrok_return,0.611111,0.918403,rect,0.048611,0.015625" +overlay0_desc57 = "retrok_lshift,0.048611,0.951389,rect,0.048611,0.015625" +overlay0_desc58 = "retrok_z,0.120370,0.951389,rect,0.020833,0.015625" +overlay0_desc59 = "retrok_x,0.164352,0.951389,rect,0.020833,0.015625" +overlay0_desc60 = "retrok_c,0.208333,0.951389,rect,0.020833,0.015625" +overlay0_desc61 = "retrok_v,0.252315,0.951389,rect,0.020833,0.015625" +overlay0_desc62 = "retrok_b,0.296296,0.951389,rect,0.020833,0.015625" +overlay0_desc63 = "retrok_n,0.340278,0.951389,rect,0.020833,0.015625" +overlay0_desc64 = "retrok_m,0.384259,0.951389,rect,0.020833,0.015625" +overlay0_desc65 = "retrok_comma,0.428241,0.951389,rect,0.020833,0.015625" +overlay0_desc66 = "retrok_period,0.472222,0.951389,rect,0.020833,0.015625" +overlay0_desc67 = "retrok_slash,0.516204,0.951389,rect,0.020833,0.015625" +overlay0_desc68 = "retrok_rshift,0.599537,0.951389,rect,0.060185,0.015625" +overlay0_desc69 = "retrok_lctrl,0.031250,0.984375,rect,0.031250,0.015625" +overlay0_desc70 = "retrok_lalt,0.142361,0.984375,rect,0.031250,0.015625" +overlay0_desc71 = "retrok_space,0.329861,0.984375,rect,0.153935,0.015625" +overlay0_desc72 = "retrok_ralt,0.517361,0.984375,rect,0.031250,0.015625" +overlay0_desc73 = "retrok_rctrl,0.628472,0.984375,rect,0.031250,0.015625" +overlay0_desc74 = "retrok_insert,0.699074,0.852431,rect,0.020833,0.015625" +overlay0_desc75 = "retrok_home,0.743056,0.852431,rect,0.020833,0.015625" +overlay0_desc76 = "retrok_pageup,0.787037,0.852431,rect,0.020833,0.015625" +overlay0_desc77 = "retrok_delete,0.699074,0.885417,rect,0.020833,0.015625" +overlay0_desc78 = "retrok_end,0.743056,0.885417,rect,0.020833,0.015625" +overlay0_desc79 = "retrok_pagedown,0.787037,0.885417,rect,0.020833,0.015625" +overlay0_desc80 = "retrok_up,0.743056,0.951389,rect,0.020833,0.015625" +overlay0_desc81 = "retrok_left,0.699074,0.984375,rect,0.020833,0.015625" +overlay0_desc82 = "retrok_down,0.743056,0.984375,rect,0.020833,0.015625" +overlay0_desc83 = "retrok_right,0.787037,0.984375,rect,0.020833,0.015625" +overlay0_desc84 = "retrok_numlock,0.847222,0.852431,rect,0.020833,0.015625" +overlay0_desc85 = "retrok_kp_divide,0.891204,0.852431,rect,0.020833,0.015625" +overlay0_desc86 = "retrok_kp_multiply,0.935185,0.852431,rect,0.020833,0.015625" +overlay0_desc87 = "retrok_kp_minus,0.979167,0.852431,rect,0.020833,0.015625" +overlay0_desc88 = "retrok_kp7,0.847222,0.885417,rect,0.020833,0.015625" +overlay0_desc89 = "retrok_kp8,0.891204,0.885417,rect,0.020833,0.015625" +overlay0_desc90 = "retrok_kp9,0.935185,0.885417,rect,0.020833,0.015625" +overlay0_desc91 = "retrok_kp_plus,0.979167,0.901910,rect,0.020833,0.032118" +overlay0_desc92 = "retrok_kp4,0.847222,0.918403,rect,0.020833,0.015625" +overlay0_desc93 = "retrok_kp5,0.891204,0.918403,rect,0.020833,0.015625" +overlay0_desc94 = "retrok_kp6,0.935185,0.918403,rect,0.020833,0.015625" +overlay0_desc95 = "retrok_kp1,0.847222,0.951389,rect,0.020833,0.015625" +overlay0_desc96 = "retrok_kp2,0.891204,0.951389,rect,0.020833,0.015625" +overlay0_desc97 = "retrok_kp3,0.935185,0.951389,rect,0.020833,0.015625" +overlay0_desc98 = "retrok_kp_enter,0.979167,0.967882,rect,0.020833,0.032118" +overlay0_desc99 = "retrok_kp0,0.869213,0.984375,rect,0.042824,0.015625" +overlay0_desc100 = "retrok_kp_equals,0.935185,0.984375,rect,0.020833,0.015625" diff --git a/media/overlays/qwerty/qwerty.png b/media/overlays/qwerty/qwerty.png new file mode 100644 index 0000000000000000000000000000000000000000..18bffcb54fa0ca571529200d30c75e60652668e0 GIT binary patch literal 20806 zcmeIaXHb)A*gtAn7gq&z6_CEJYoP>`E-kBwh!Btx5^4mbg;be69fJe zVkZtAI>c{y_qO?=Lx&+_~wN`fQO2pZaW^@ePe~B?-OH|HwGMjBm%>GXJD~ z=ZO!ed})kqyT3layuT0b+6H&6S`+(M=RFoi9CjP0N2##XT|LWks zWAGmo{D*}9A>n^W_#YDfhlKwj;eSZ@9}@nDg#RBR;p6KUzY9-WfTyNFy6YDcX)|th zEqd~Sc+W(>_~=gOoMQf^X_Z#s6**+$=C-2J8$`uBFIwYl{GlVqe|z-q!AZYE;`5Vw zvp=Bf-cKJ6dyxiQ+vvP|E#k?;E-vP1qke}7Z_>^jK6b^Hn(t~aPa8nu%PPaBGOlEK zme*B6t*kF;jXphFN!{lz>3v|*c0QX%zl@r*$fFC}`Mp2wS%k5oH|;QquEfR-8xDN= zICYo3RQXKAp*GlI+&^xRLr17JWWmLzXN&VXHwHb4Ue7P3ej45&kzH1{-U~)w`@?P^ zh>0lm+8PS%Vr%wQb?Ig;)J^9OjKwSFHgXqy1tBOrnp{eVwBo@KQL0+s-yMDO1Y0*2 zC+9ky9cVH-G3Vq_7+tn|QPjxA=jGUT-ZjTt8%>*yidkyjHXHp^Ud`tj$*?`pXRn>L z*@0NywKwzZrRb2aEmur)v+YCJD9P>2ptUMH2-YB1>@eGRBZ=5MBf~Vtu0IgM8rJpM z`s#!<^Q*s_Vm{6KXyaK{GxS1KIU9UegPL5+Cms1EYV2&DUvz6$y-Gq2@O<^a1F&>> zTjPuC{fLkx-JKFv#8M+$*w(9CGd1Bmnab@btDDMP{OX(}sYLYl%Yv);`y!WthrfaT z7O=ZSrAAC78~nAlif-Rc2n#bmDjx4DShdPI>GhwVhY^^QJcGcNI79&oj zeh_;M8D}@xIcFzy(SdJ&tr%R#@~Q9es2}vDa#d>0DwU-D-W~Sgl#zos*&%tmZ3y02 zwaL!etK{xG;;L~4#=>~SBu@E3sNP{vcIcZDEeLhH!*@uH$72inSpPh!itw zTQ5p;ptoAYk8RA_cyE{8Cs=w2ri_#U)+6=tJ} ztcD!_@Jqj_TXuIc+euX>jfx9yQ>Z6c5ct);zT<9?sU6Ok4rOlrxqrO6Z+)gkwE^d8 z%0zRv@a=m}`|?zluYlXj)af20MSi)^H2td*kO~gng+Zj_zd@VF&wK24p?QJRzN-_B z_0NmsuH+n=uV|I>=_xd{r%_hua?N*eM{(wJ=EvbZRqlJIRd$NE&R#J&bw$odq3)qZ zSlw!;R)IuEhXr|Po0$rheosCJ38|n7b9QeUFyu3> z>{4qR<$W(a=&kb7q@*NEz3YQJ^A|6yWw_=30;^hH>oDijK-XWB>g_J)_D78D4*Ol& zYX$SVb%4|B1Ju*fC+CW|DH%|jiBvR~gV5Ul^iC4hYvz*zQTyzyUuEbC{^<|=GxLq& zQOzga3wf1m$w`q9zY08nPR6xaR6BWuHjJqz6fIY;%%-vdu)ufzGuRSWOa>Mx%|Yhl z_E<1v?fI2lzj*n|zZswlM)b4AYMjR{@x{p`&#f!q?azK+x)+4^_hiqz$Cj`ZQZsF4 z{0b49(a!$prRQx1F4r1lAZrb*1Nb$H3%{(_6)8=Ho z9hXTzo7U`e0l7U7fQ6XE%ay__R%*r&xvE9s*%OeBE4iWh^_=qhF)x!{Vkmp@{FZAh z4QXB;8d;XN6gjQ6>Y%@BM3wsK4{^m;cACf=Ti>3r>xb9N-yWHHq2A<1^wKeI3bLe? z$)&BpW!vz-Ts0l=69@au1vhJQ2+9-D5$Y9d+7R(}3a4B=_vk=SW{VA)yUy+{weYU~ zVmz&1k$L&p-PWb!4n4~S(%cd}-i#g4R|S^z3tH!W(Gz?&eP%iFu8Xg&f=-_HV(oa$ zE0Tvi1YOmk7D(NjRMe}BUXDl9CZYGnM{lGb^F|H^Woo)d18@|g`8VfX`IDWn>70H> z*`$)XT*QE1R%^92$wwupRl@-)FNZK=&F3unTy3>kL&p zm^%fe;X*$*jrbCh{0BceD3i61zlLsF@L0>CVr6xfriD+vX zP}Qqq)o`Y8!C#){`BKFs14ENT&h^C!+(}gd)%4SP7Ot}|$EV~TrIG*2Y^gl2$>{@0 z+h4$zddP!L+Ot~>*{fY(^so`IlnIt@$$W`6K6R7A#VkUqicSsrIrLSC{O~Q6i=M(A zWPS^V{CISqZs1hA-)|NntfT3)t4N>P(HN5}dm97`Sd#yZta8%{&#SMWojxi8dR3h# zb+1LRK6X{uNpqocu`=u}rq(M|Vrhp%6x4b&G|>ubNQ^1Vr?rN`fN4Bq^dK~l>yg$R5aOh*jVuy z{KNzPeUEG(yLEXJMG72g6WvC1?G9=kGm===PU{HCZaw(q<#Oe~j;aR*N1W_-qCpxZ z3R859!V$kY=u$8Pewg2F&mO+n`tE0G^>y5m5X|n3a614_^NG4UGvDvwCq+*x`e#S3 zd>$or0^s3MrCR7Aemf`4f!3#k^8SP3jg|YEeWDk?mI^HMp1*QVbjqYx*tsi`;KZ^G zh&sF19>s*3wC!ME4*ry=5`52A2LU_TfAXpgdac0#W*mIdj2s{jV8x#1KMGatN+yb} z=ZdfuYxnA<$~nUM^mROfD?4PqMm^TnoN1kcy@Ly6;)ephn92qHT9PL`bLD3q*-et+ z^{brpn}-y2;4Y0mW)3T-z{Q4pYZOvRRhp(Wck?NVww0@Qgos0^rnmlUSu(ByvBhqRJ@ zoe6&9L!;l+GOTAl99IQVS6VqGHMSC}eAiRymT8v39j5j;x-;Yc3xGOaZjdinFymA& z{xPHfd)d*{CV)WJLt*x+2({w8XbS%c2+hKXsiJB}Rb^x)?|gn?vJ>R@qP6?^OH6|6 z(h*0{td4Q&_Op+zk+y%*jpQQZ&F)o^Dt^#ig8ACRccE`*rnN6eO6G90J72fVr8{a; zgtuDNGbjS@{|2}(K!9H~9O8SMtnL=~sfA}$O{|(ex z9Q|7Z?TV9X+DCjHCSXjJ(=Z6B(-YYc9sy%zBeOdPqh>Y&pQQ2J zbwE8tr-2&2f3WYuzlh^eK)no8aLz(azr(<P4oc);gNRZ$xQR~Wx=?*4(kM#q}wR^bBHfcqkU*NGU%NoiVqhU{yq$ikO=^>h5E>xQQorI^O0AE1 zOZz;<-F`H;f4+7+@nj>b-9nRVEoJ1U#l8FTtp@Omx%Hzl;@M!vTZghtVL)Z{1t`0= z`|*Ao-8(TR75V+<=5y1?58IMK!vnOp6% ztK~hHb45IN^E+r(TP8QgcKGpgArVSiFtFe;9bQ93!w55Z@g<;q>Q>1K1YpU}8Ex6T z-~8$aM^3k*RnM^u=t|o%O=?~Q|ZnE)4od@3zka_t0q|w3$Qes z=m+C* zH+-%%adz&9z6oB#&%K4mgGlgNO48~a-A-#1``Jmg1A*ys^2oWmix&e+3Aa}AY?e^! zdaxOQmY1&!aI%AWykLsfTuH&uVmL@Cwt9;U^PO8I%A7ZcQ1R(O=K zqYe?qd+>0P&1dA)$iepdv#08>dWg2d+$fc$HX=e6d{-CVEdk4Y;esMyHuwqUy9AFt zzd|`cvTgxwfkKZ$LvHmvXxlBk6WmJfj1-%5T($4*{Vo{!?dT$Ue-q6V>j9C6#`ac& zITF9N{rq)7t*nj2b5F-wpnkfPelWm7!$x96QLe=>k1d>Q?ZtpJO$q0?$VOXM!oBMzXL!MXU@tm@=#U4 z3)<22j;y|j0nQ^|m>Fg4YcR{ZIiso1akt7p=$eu5;lXRF7zCf9z06fBvmWT*K3XOj zN|z+gSIgtg#R}Y6=3uSuw|o9gPXu)}MmENIsW1qK$jYV+RusxnLK->teK#f!VVBpg zWKE{pc1lKXjXE}x&Zrpoxs)P@RgK532ZEgNc(|4anb-HC_{?UN2b^#*QR8=sQ{4D_ zqqlyOG##HKdgYD<@LLi>?}U4hMPE37eC@wa*-%Lh{%B)XJ&w%kfiG`SFsdVwtF%U0 z7AO@opYQ7O$o(}fE_||VFr89&;tNQEZ2~AV5gJ*2%u#>Aqb}%jsV#EwpTW!Vmz?cu z07(|^m=DyW{x+(Gz$%8M&}8eMl}O%UJgj&HwwKOqc^fG#mvA=3c9`NSA=iONeeB!i zS0DP~;pW>Vg!;LB)*2abXm?Z)J=4TnC&r#N-oMwFU^8erfHT*0vXc_;E6l^b+0zdj z=Xnc0u!^a49axh`GaE!O)?FU^+j;vph9uv9?W<1LOmF1^l2&T7|Ch3yhOf2Dew;M5 zc)IHGintNQnmXx6SajC))y)*;{gwwCi2Zd$6eu~GI@a~drnNV8Ht(+z1o$PjU6A;k zoKQ1|!wV;l!CF4>AmKY?fhxtQS)&Z_Yqie~nZ+fiqMKzpMqJ;0zLJ-{jgM0+c-kP% z`yQ)|u3=rzMfaWUBPZtaYsK|Fk0}U#Xf*zjEh$<*|An(g(%vhpYDe6B$Qy9_8}Jjk zgp0Un%9t-EWX(uRjUB{j2R}Ih)}Pr_%QW%SpsX{FptY0)7nU9b)o>>d?+gL1S^Y!b zD2{D&*BSY0>aF%YOa;o7w|HmRfvM!&^5VNKV!z~#tZjkg(KB*7J;AK98z!yZ0S`@E z&B(MBEv#SGOuKTIJiV_ZkJcl{qNEX77buNbxsyM1;K9DpM}i$dsUur#Ku!objQ5qD zWb5`aUH7oC?ls_G8Y!mEU;=c+zX+wUZ}paC0eCJ$E%!>bcFnjzMh>?0;FrSRmD~O; zn$7DPEmX4F~bDPl)4* z-EGEQ0_(RD9SCMUtY_hJ5ST-F%p{sR;NOzl^zlua&e*z)!_xluSnyM~qL3kfgC_av zgzb^OXD&r9M6z{FBD5%SLfv-E)3j+fzX`WXS!ID zb8}p#3!|z5z;$aCNgY;SU`Tw~f}vu$d)^xtoQREAdJFlhe#HU5f1ArGR?~0R>zc?L z6PnDKtaup^%=S=rSC(ntB0?U-3nk@|)T44(PX9{9*dEWy@G@IPznQ}x;nIz`Y+?M> zBzpg4YkBXX@ay_y6i2!_-vd3LQk8I<2hqQUKH#1@5a*2)K0T$c; z)Xisbu{x21it2EKDrMEq_elv>1$(x*bZ13m#>CLLAm1TG7d}X-Xxd@NB4Y1U8?b_B zTMb!l*y2cGJgziS|N36q%N3sHFTE$#NJ9#B6E7p-+Buc*aB;IX`zxyYjGj<`^Dw6U zs}QS}6A^6Lc5L(Bi!*qc)UH_AN%@9B$MpgH`bW<@UnmHSz7`!f3UIU)H7ixYaYx>+ zYSPjDQv~EqZN=!3lz?Yhx!IX4Urf}xUMOX_XP#ndJHy5Jj-I|2_%mDoS@=FN9L z>+9p+7{JRd>g3bbX8-E5{|OWyC;vLb%6bAhsr||K=YdN;j4+wDR_)Z!=QdmMUyBG! zufs7I^#$TeF?Vcn`K@HjY8ELec6+H`JK*GX`-qu42Y>p!(2=OH=X$x`5;zlxS*AGqZF_vN%7{&e0*{%ES1(;iaD7M{ zqq_7wFVI!55|0L3h;{W(W47s6l@W5c(~Y$il~#lzTmhLRw@2cnC$6{T^IFm9jg_Rt z7;o>Eaoi(%9>XY#U_)OurgSLBqkcPOP3?_qW67-_pZ z#Auzrqd5w5Y3CFM=jxHElAvM5SdLqvRjgSPY<(MRE@olK1#X50%!XD*MfZ9gU=Om& z3+@$!hFis^>FSBV)KwLnL|>{ppXU_2LTkpw3{=x`^sp$Sc`$DroDEifVbI0mhc;tO z<(}xi#tFuyLbRlBc$mpU*WV0c7=?m%a~Fw_6pYdK`UO)cB){@N6G)`b2)dj;R?~w?s}}8 zM<&#e0m{rHMo!ATAEraeIY=>=3i%lR{@5li)OgFGpy_%^lCW)0lWd|YYOeSDGD6(v zI-wqCmvY6llX$A_)L5uy=(Zg3ExLMZ`Fm}i?rjNJ&bc(}?G`6OOMfGvl{XK7T|V*y zx*$P~zQ?Diwa4WHD?@3ok-zMv4Ody1>eM)g4lXbFqO~SgrO)z{6%=Z}{iR}5u!!on zS3g+!mn3KQV|#VAS7(*~A8a)6@MoASJQ{^Qs)rP4^AUjLiM5!S5Xm7G`Gf@jdr2_FK(^ayU^xb!V!*{>{ywlwd<7Jv4?}jjW587Me zlD;7oHCGK+3z>>W7r)T@T}+;tQuR00rx4+s5?flKY>ca-<~LCCfc%trP9 zqYn#NhEkCE{(UFk9~$oLTItD!AHf z);43yLw=p3<{)7dqGTDBI5HqJ@%9p=O4j3p{%QgKc2tyo>E~da$5o;ehCAQ~?RGve zhXhsi;N%S#fBAJ7L|A(78z0EXVHi7!RN80xQlrul=p(77tu{{5_0MYiY&=oDO;TxL z?JY{DJzK8z5z7bt6VAdumj$!$$={2?jV^28hTpgk>R%`1Ih96VK*#(Vz8yEaV(Vy= zE(S2yx}f+^FsbRiCtcr*l}Z~Sm2feGan|E}$f-8**2+*dg12&F(a!52*6k}7Jrb%R zV>X0*7pq>PES46xTAkoHZbJylt&YZ&rKtG~R>NhD8p?6@9K)=K6<*ms)28Fa6}?1O zs0YC?YTkUK^2H~E|YQfIO`9pmVwU{b&C)(&Y8T)xl<}B?%jK_>31-Sc>Eb zI5lUebl@!2z?v7Bi8ep>@fGdF&EY-RLy^s@N^C_?tif(Ztw|YnvNB!2BS;hX5e1}g zN%2GOVR9SrB<74L+`eY~ub!&IM&SZeA_SDMTAD-n>;-11h^yBZM!#%UP5@mdgUD4~ zfMPRp8FVn+?fFWO)j%AB${eLMO$xBRlM zJ++3HNSp9H-WBQcJOg||qIO_a@udszn;2d7C96~_>UyswVuzUHAJ3Ye z+J1$A8FRK}8{@I;>j6EE6?=!}hN?CM@3Vn)LS)cXcYETG5L7YEe4&c+(gHd_`E_^J z6fK4fD3_`aETNf?kXCy|J!S?-4wrIo1Y%eDDpWkZL+lh>c!T{-!ahkj*=^EiCnnT; z_>Xd+@Paw66>FE%`((;&cZ~4QlZv5zJ{56&zGZ>H0j>0>8#7=nue zHzrO$lT0lHZZ1gglmU58D)igo%}GUc-MH$`WmYNnOsi~`XqJ_>_F{1q)LNeTt?|?E z@e`9kiZ@k+9B#uFaFd7oHWX8zIkim2w@H$d;^E7u@Quf@2g_2>|6)21&HL{4`m^WS z;Nd0eK5w+{sROltGPJvzu|i{$9<3d+>MC6mKhqfWW@GD(m$r#@J*~%2G7{zaC-g06 zzK#0WTFu6BU&D$OcJF9Qg^DpWmZMfWRpC9a(wAbYI|~>v=_Zu`MaSU>8w{_-7j4Vz zdj4t%@kwQxE6 zN!fduuFxJ0lGIE_nuBk@sYov1xF-6ceyl@fx<4Z(tUZvQqVkkODmbgJT4&)2$BoDh1ME`A)A*@QuBw@?--oJzn#ky`~j zF)72c30H_Dj?0;cb4BT?I0rOI+g~}6X(T~=;Y?$E2O|Z@6Wpvu|D~pC&rIm!>a*oy z!$I(Y231LLXa5r1f4(|OyB$rPT9&po!`ZJ|FXXO-pa z74zuS)ECb${>VoR57$?6P*bi;u-6VJls;|Zb|;&)Nw#|5Gf@r;*dg5zu#b05-rS6+ zv-W)8PK`?Kv#*MVWB&#yB|x^KP`3a|S1=G{;%5SHhl{`MhqF^JNcq;%zjzKgw35Sm ztXJsa%%FN1qUp2OU-wC`bP4!+M zUocb4I%;9ZPOVV6_DuHb-G;})r^*+E)R5j^dA^Hv)18quN*Vicci~+~gG8k@o5ZW< z%IuF9^1?m8!n`toP6z)BHVxTVjMM+wCSo2QSn_)!?lH#R_nrA=N|w%a!3x%4;_F6= zjpuax^Oq7zO@52I)dHKD*)wqP&XVrKx)vhNo-c*-yqciNjDS*ls*i;jo~0qyMNWIn6UC$er&?=T(4j6^duZ;cZNx%N4)Jg0t^%1;0fdIvW=7fwNZ-h{C$UoD zCA)yTbN-p=;2iZQNnPwLvGc(EJ&jYWu*-CZVmO*teSpZ_=gl+W6C)zMt&aio>v!=+ z=i>XSIgwA}gl*kX48rkb!Adw!o$pPLF>}3ONe$`XJah0S;HSp%Wba5SeR3+biCwQgRHLo#E}<-d-_7(E#almBGHY6I>^z*mlJ-PZbPvD-kp3^)=G04_S{ z&CODY5LHh=oRiBPQ9(n=G+8l(v~q69aM)@$9@mhRW;^6_QG{l?TWZU=A7wr0YUz@6 z36o+8`b|!m`MwPib_3B|dnN|UpA><-p$KF?VTura$<&a4oM=p6+U|9XDm%%esh2vV z*#5eyshs!+?2_c8$aV2IPBjIIn)F$@iPUp&L;;MJwnJ$cJfLyn5=bJmzaCXojIRfx z{sC_whuZdgVwHrOow#UO4VP!8+p2cNo!)0`UnaKVD&O zZTTB;KMaI=kk@^Cj9a1Ggcp#Oq}9R-6+%B;e;mC0@odq`_ryo1MT@N^RnvXzeD8tD*H}oc)iiN}%J*mb;R21SCSuHhi zF-6{AXqz$$qyXnpF{bU^<~(jApRfehlu&E;!9|&A$75PZi)w%*q4#sNNg2`B4stL% z;T(CKW;miXElbJe-uW6s%qIPO>+@pkUhqQkB9I#@OM!f0Hw>9aKD>M*;4rA}DTqwBEfWdGNTG3PRRMa4tb-@bYg}K7dvu zyP0p2fSqe$fMPUI;`p@lYCd)fIZz~VHg_&?R!`0A|3eHt!x?usZYPvNqqMa{lOh=KP? zCjE6wWo2pPadyQP|ey=_t;SK5kqS@6%A8xR_tIUOQiW^<4Tc# zuc^!eF(tPeG01I6_ucE)PQe{BpDrU04|-5Vi)EeLic3!g$jcQAJRnIkB5Au7LEMCC z+Xcs;_gBID48V6pREFwh0{NL+YerM9W6|TF0XIW3D~MGlKg+96EKfZ}@zG4B0%g>r zJ*&bP)n^MEVQd8EK(`w~NJH}3@kuA3Jk^r)$A#8Cf0gTGsKq4MT9zlM4PLc-Z<`Ag zrpq?7jCGb>sA8pl-79amGwnMU9Rj?YR(aR76 zBoD^*AYx{wn|aNnY^P=sL}WJz@P6K04(7Lri=}qE&7dKdI<)Rq5I$0#xdRmkqe#d1 z|4+p!*8m<^J&Y84arkh_pW&Zx`o_=b^XWW| z$J_Pm4at?){x0zoB6`~;WUbpkt8vBS^J@;)dHerz`phw7nO8cpe4I@9prOz&~<8Axeudz~{AII4aLeq+g7+@;{ub3L z83HHW0hT7iC73Q#TwM;e2IP)qQ|$}2gv%W&Rw@4U6*!@?a^_u8CXIt@Aa4N@-s`L5 z+$cJG%_+&@d$;K7K>*{hXIPvO+&YfWE<_#%)j$=yfCiHWcEr2l2b)jH_5cyRq|{o|w9e8mL<*I%w2&{3 z(jPuslotH@>ivT|D-ZF56Rw>x`0Vsxu++gR;S9 z%3dk8`O`!{1~3VCNBa@zM!(vY_!MmZ;>{OD>)qxJ(iYYXZu$;}Cv#WTjeDOPJ}8o} z>ue~1sQv!1{GlIyc>G2xnys=*+;Zco`z3V5FpLn#(%o{yl+bTI?4;T>vL`D&f*3E_ zip1i%Rio`AE5{KH?&6Ax%-|svG}yVQVwYW3xuG=$kLyp0s?^@8GkNilptf7FXJPK_ zaqPV5Y9+%&%Z0ZYma(5;KSeEk3CYzCd*C{R@zhj`j3|OJ9e+T54R7?dYV&k z4ZK#`0Fb-qY||z5IR$;IlAag*J)4_l=Ec&ye|C#%Ss`3(f6n_oFC@PMbJoTVET zJ_Vk9wM~RPmCl>nyxk-gPg%C*-$Yb>+JhaswLYZ}jw~O1YXkYa{rIWZkM@t;-2n2R zTKvm|4R1^GH+j^tFU@ydb}^Ma9b=qt0oG*|ag-iOOU)o+ZW!w|FZh0V`b)Vt`jsv?UJ~u0|bIw!GtXUVtEnGn?~aR?$+*<5aS(mceFrCO?s|qBl%vY!+_fT zKEybXc+&B+?t}gVYi5&x?bf;d1m-{pt!46IeXAFNvmKV}f5s>fuh`6~_i-_VqnI6X zN!%iT0(!7I(gV#QjUro4HpjGfX!zRK(^g;^CN)O3I|nLQV4{y*=uz=%6KKvCkk;)} zmrjE_{Swk5>ZbBb@^l5fO}@%_%e|7n76`htcWMlUjqZ%>O{q7lOF%&{khhrR*11&VR@q_r5)%#T}Zq-MTt>=+K$N2j2yttNu`2v~&fj>7Rl6-V>a^L~Qv? zm)c~s_O>A(S~Xo4HBu%4{TYBXWjefi%B-er{|=A0Ry7X8#jyUWf%o+qJcW_~`)&5g z2cV%kXop_Mvvi5tOCG&^9h9o8gtxf^wJx5kGUFmWBy~~C@~OHKgg7v$)JbdIGetht z7;5pTDW4c-QQ!1&_%f{`vz*Umc^nSp`bG6qnVug4U{O$<+D#Ng^?%cBNu%`)$$(E6 zpg<3}>!cVz%YF1z!vJGSF9#`IS~!bYfDzE$YWa$Vtv|LCp0R$$KWfWPdKs{rbr$z$ z3X)Q#-nDqiAGQnX)*m(E;I3OkV`pA~O+FxP*pX)lG@KY#8`|vs-bP*(s`?S=!5XvF zH_AHK+LO`IskJ1*i?ez~sRhi%nLehW;%BFWM#@g~D|Nvl+)uqkfCecgaFi?>y`iWY zA;`rGw><MZ>prRvob6|Oo?cwIL$^%OS7)}j zR#XR?J;UsHMtDLd-@*r%t=KWpVamgbH3@U_?m1I55=K36R>OLksrEqW9Xw0CXlteR zvgTPb>w6`ZCM!OS-S=yu02e;H&@g52+?6izG|w;O?uIYNK$%I_$(FAwQS=>rhR;O` z=6rFod_BfG#34~<B{ku*jA66nYtWA;OaOWi(cL*gxLJMQXJ|(=tCXL)k6n zXvX2&Pj2BsdsuGU*vIiSnx&NOc_eIs&O=2`gR!{IKAFTKx;D(tUw@jKx!60bW=)8e zdS@8}G<5xLc{Ox6Z2H-TPunF1C80`z1Q5Ly86Y_zUbT|A=tGPva1_QXAW}w~MUD6r z*}pGbhGIOwkh*c(@zZ(>7crLDO3f7lwXZHnyxY(@`wp%lGZ8E9%NPD$Axh$mU{agt zzh+YFg63+!9;)bfLVmPMnBG4xHPnndDv|A~?ZPocwU1>DEA%(!ko6@XDNMkpi3Oz= zxOw0tD!nV=+=gc*N+ss%?7=<2OETE;) zxPiBP3hgDz`yMy{wKb;H+A5(gX5hnp6k}HWhS)IhB#rKGgqm}yCHAVFBtsz0eBRvO zErhIHyqwz7ebk!iPzJ6cL#z})#VBsPc(|USqQAQ}{?4$POd=)`Mv^MrCe;7f1+qUq zQ@Ab0b4cw#L<+#<5u-(nlM?L9a{caK@8GApr}V;lbJbl+yIZ*8!ALryBxKHy2HO6H2FAVozgRH)%++xy@D z>M-%8?3(0V0iCrkdxWCna*M?qmDEpxpKd*mEo~%-1@gy>-07}n*&HNEC0V1F|U_8hTrlAv{M@JFhP<-@(;6^E?=Z@dccl`;*1$HM2Qhv7zSLXE z&{y?&lW`w9d#pMbcZL4c;!!+ijf8l@zAmJja)B<6BNAV`P;U2~RdTnT+7svb9sNY=babJK-%Vl`V87R7q2exXAf z8t6M?(96n|T!!yLk%cMIXUto(gSE7HdG|#{@G;?CwTyk))td<}oS}K>GwG*}q(e@h zZeA5}`SZ|Y^`Cl<_PPg(E=-y>?$&il047~~?Xz@+D9Voj_|CI;f9n`a3W=Tj^+%Ze z_1HYUy#JSuVd9^V6G{@~!v>VSi#HlCV<$4!kJu0m0vgYsWSKF|IcYB7G$X2W!pA)r zq+sD~a`wKO%eb(UIB4bf1GDeci+As+AG`6d8q1vg=STBUjN1?X_z5m(a4YOBwtHfs z<-P3kj2tBT*c4UxpN0CRrVJuOc9m+?wI}jhB``h_V%gDc?Uo~i8?a)$6o7BIap{?} zCRllC?wOKb&v$S}U(fUH)PZDEd6$jTPj7hcysw|C0$i2e?1;s><|P3xOj`+Iq^CZ5 zuhnc%V_Wgb!zQP;_I|oVcoc&e< zG!MEqH4)pM7u;8#lXbWh;u;Pp55QJeP>A+TppQqLKUNZSGPZGTyt2~8f1Ic`lAHg%BR z|1ADgP=>XIbckH0T_}%HtoZorn{ra<7BIAS7Wq%#$`=@CeD1fg$ZA3AqcV}qp1WnS zY%e+Jc**>eO6mL7bP|-m%Cd(4YlEz>8Q~x+HenT+GkF~&$tPI#pz(b8&V3Sd=uIfy z89kSn(kCcqYi+UZtvT4WBS*X-eT_Wo?}ce@dMo{-W40(7_ZqevBv(8JA9kP%*&;=8 zB>#n01)xJzy9sNtR;=`~O=td}AJLg&Ra%j60aPA!W zB>vLhkHba)q4Ff((@K|;(_%2`b5>>T`l>V$npK$)SNjodcP*3`0fI>wNnf!7E#U|# zpetIca!56Ax$<6GgvO)NK_pc9e(K)lq$aM23V3fTbOru;L+Gl@NkSUW%9ZJWbhE_u za{%34eKV}e{mt~zC?mGtlRRLYVg<=Rwp?cKA9Tsx5XD~veZ{(_iilcg`b{Fab92Is z?|^0esj?mztr(m&PFC^!$*b{8uK`kL-X%*$4CW&Jiu;IeP6nwB{OnbCj@I+McnVgE z+{YeG+_<7&ac&&QD^OWJ6c0zHp+18d{rVGlu~^B&PO`!B4&)-l-zy4=Q0?8deKEQS z&m@;?CAx$$6^DykS4TYSfDyQ&j~>>&l8X4Cy4a)XJ{C~Pch${_zGjWUJl>nZ$Dyv{ zwsCWL!ne6&&w7c$G-wYr5xsGGkZBo`83zn=m5Td($Bi2@6=r1b@!dl&-4HlCrL$ok zVW(eL-cDi%v;6QDjB4;nb69FN$~AZHuvmywV|d*j7;mRTgrwLTbZvw?ad9 z7l0wlREl@SXSD}yMORbjbgGZSnLG&U;#{JIgptq^Qi3b9;ikKqk!T<*OEvEfg8C>c zdJfiVikiFBQ;n89b-D$<)AD>FCg}1F_G^TQEzL_4v)%<-JXtat*8SA;Y%( z#Zc>_Ho$fb%Bz|ac48h;o9~qa{T-7Adh4(wS1wQzE?nd>m`7oPP4r!m%0u5&JAp}s zvpyH+`i23iJ#Be2_Y&la&LbN1mG8l@7vKAXN!1tm$|bd4D86eDQ@2Zn?@zy7clx8h z*@2Xi?|RCb>zc6sQKGVBs={ILi=nG^WW_vpXRP+%>#3YRzn{qJY_rg z{-VboH1ubnD}GzbWrF(cL+q#Wx+i^mW)j3u2w+Z7Qh(LWE(4qyvKFu9nisWU?Axbe zC`W7vP;;Tb`Y!wuJ*+lyg-@ySk9uINWKdHX9dUit%_sx?%O7iuEq@yq473s`G?_(a z_u>*e_PnIdZ2IJpDkq)!Y2zd;_fI105&F4omWqe@H$02FomPD>gUd9V@>PxjKB`Hr zN*+JlHN%Ba;~&`aLUaHa3(3ks^R^ROMW4U8Xr{1`axi{A)rR~O(4V|S6G5C3R4F#e z5zAeec?sFHEDHwer(!sq^9-2E!p1wy+y@)Ynptq;clh~m*dp~m##c)6D8L|vZ_Shk z(03M8oE<>_XV41t1ep(n!mhJ^7)03m+vPa9^5ZaT9@F`U!MCsc)5)___T-lji_$bK zB_n~l9k$U1M!@wF-iC}sk!^uvs@2c~{K?Y{Y5CPH+_p7Y$g-oh{A1*$#Dn3B_E?5e zB>+ky(uI@ z5KYy8?DjOe^7NE~{i0(m;X?SCKeY^@kIPxUgE!}(zL(g=z(~4IbD%W)ghfQ;QqN^E zCF(Y@1i}7`<63)p8t6=+0$tY96vo`-dQAG1QCEB%J>>JHw5M||Z872v0uGw5IT?=~ ziu&~+k|pvo!BC+|pz{DxB4)Sw4JEF}N2u1exsNZWAmPH{9lfxx?xT9Ez}!x7E$WR+ zQRHk3BRM0{QRv_L_aR|${-@keZyc44C&gBRTbY^u4l$Bt%MnOO|5n(jzLes4%9A#bb=QpYwk>GYCXk3HOWzwJwJI#j5Q{;&$X%SA7NtCLdprlUgGfQdPdk zl{NaowxFV$o;*CZI~Y!#rXp6qZa2Op1?ort`<)oB$?wwl(|w8MD7W~=7PrWsGLOHN zQZxHK>8BvR64}{HWb5QHl!gzvGAIz*a=3l%UgmY=necA+D&#R4*^}Ism_OAyqhHel zr}E3*y Date: Thu, 2 Jan 2014 23:20:06 -0500 Subject: [PATCH 3/4] (Overlay Keyboard) Use 1 bit per key to store state. --- input/overlay.c | 2 +- input/overlay.h | 6 +++++- retroarch.c | 6 +++--- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/input/overlay.c b/input/overlay.c index 40e2ad8ef6..490b01e7e4 100644 --- a/input/overlay.c +++ b/input/overlay.c @@ -925,7 +925,7 @@ void input_overlay_poll(input_overlay_t *ol, input_overlay_state_t *out, int16_t else if (desc->type == OVERLAY_TYPE_KEYBOARD) { if (desc->key_mask < RETROK_LAST) - out->keys[desc->key_mask] = 1; + OVERLAY_SET_KEY(out, desc->key_mask); } else { diff --git a/input/overlay.h b/input/overlay.h index ce0afbee4c..fd7cb4f65e 100644 --- a/input/overlay.h +++ b/input/overlay.h @@ -34,9 +34,13 @@ typedef struct input_overlay_state { uint64_t buttons; // This is a bitmask of (1 << key_bind_id). int16_t analog[4]; // Left X, Left Y, Right X, Right Y - bool keys[RETROK_LAST]; + uint32_t keys[RETROK_LAST / 32 + 1]; } input_overlay_state_t; +#define OVERLAY_GET_KEY(state, key) (((state)->keys[(key) / 32] >> ((key) % 32)) & 1) +#define OVERLAY_SET_KEY(state, key) (state)->keys[(key) / 32] |= 1 << ((key) % 32) +#define OVERLAY_CLEAR_KEY(state, key) (state)->keys[(key) / 32] &= ~(1 << ((key) % 32)) + input_overlay_t *input_overlay_new(const char *overlay); void input_overlay_free(input_overlay_t *ol); diff --git a/retroarch.c b/retroarch.c index eb099646d3..fdabe7edd3 100644 --- a/retroarch.c +++ b/retroarch.c @@ -513,7 +513,7 @@ static inline void input_poll_overlay(void) driver.overlay_state.buttons |= polled_data.buttons; - for (j = 0; j < RETROK_LAST; j ++) + for (j = 0; j < ARRAY_SIZE(driver.overlay_state.keys); j ++) driver.overlay_state.keys[j] |= polled_data.keys[j]; // Fingers pressed later take prio and matched up with overlay poll priorities. @@ -592,8 +592,8 @@ static int16_t input_state(unsigned port, unsigned device, unsigned index, unsig #ifdef HAVE_OVERLAY if (device == RETRO_DEVICE_JOYPAD && port == 0) res |= driver.overlay_state.buttons & (UINT64_C(1) << id) ? 1 : 0; - else if (device == RETRO_DEVICE_KEYBOARD && port == 0) - res |= driver.overlay_state.keys[(id < RETROK_LAST) ? id : 0]; + else if (device == RETRO_DEVICE_KEYBOARD && port == 0 && id < RETROK_LAST) + res |= OVERLAY_GET_KEY(&driver.overlay_state, id) ? 1 : 0; else if (device == RETRO_DEVICE_ANALOG && port == 0) { unsigned base = (index == RETRO_DEVICE_INDEX_ANALOG_RIGHT) ? 2 : 0; From 65c368140c6c9dfa7694c115c2907098d23f2f0a Mon Sep 17 00:00:00 2001 From: meancoot Date: Fri, 3 Jan 2014 12:56:21 -0500 Subject: [PATCH 4/4] (Overlay Keyboard) Handle key events (no character data yet) --- retroarch.c | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/retroarch.c b/retroarch.c index fdabe7edd3..6e935d9a2b 100644 --- a/retroarch.c +++ b/retroarch.c @@ -492,6 +492,8 @@ size_t audio_sample_batch(const int16_t *data, size_t frames) #ifdef HAVE_OVERLAY static inline void input_poll_overlay(void) { + input_overlay_state_t old_key_state; + memcpy(old_key_state.keys, driver.overlay_state.keys, sizeof(driver.overlay_state.keys)); memset(&driver.overlay_state, 0, sizeof(driver.overlay_state)); unsigned device = input_overlay_full_screen(driver.overlay) ? @@ -513,7 +515,7 @@ static inline void input_poll_overlay(void) driver.overlay_state.buttons |= polled_data.buttons; - for (j = 0; j < ARRAY_SIZE(driver.overlay_state.keys); j ++) + for (j = 0; j < ARRAY_SIZE(driver.overlay_state.keys); j++) driver.overlay_state.keys[j] |= polled_data.keys[j]; // Fingers pressed later take prio and matched up with overlay poll priorities. @@ -524,6 +526,29 @@ static inline void input_poll_overlay(void) polled = true; } + for (i = 0; i < ARRAY_SIZE(driver.overlay_state.keys); i++) + if (driver.overlay_state.keys[i] != old_key_state.keys[i]) + { + uint32_t orig = old_key_state.keys[i]; + uint32_t new = driver.overlay_state.keys[i]; + + uint16_t mod = 0; + mod |= (OVERLAY_GET_KEY(&driver.overlay_state, RETROK_LSHIFT) || + OVERLAY_GET_KEY(&driver.overlay_state, RETROK_RSHIFT)) ? RETROKMOD_SHIFT : 0; + mod |= (OVERLAY_GET_KEY(&driver.overlay_state, RETROK_LCTRL) || + OVERLAY_GET_KEY(&driver.overlay_state, RETROK_RCTRL)) ? RETROKMOD_CTRL : 0; + mod |= (OVERLAY_GET_KEY(&driver.overlay_state, RETROK_LALT) || + OVERLAY_GET_KEY(&driver.overlay_state, RETROK_RALT)) ? RETROKMOD_ALT : 0; + mod |= (OVERLAY_GET_KEY(&driver.overlay_state, RETROK_LMETA) || + OVERLAY_GET_KEY(&driver.overlay_state, RETROK_RMETA)) ? RETROKMOD_META : 0; +// CAPSLOCK SCROLLOCK NUMLOCK + + for (j = 0; j < 32; j++) + if ((orig & (1 << j)) != (new & (1 << j))) + input_keyboard_event(new & (1 << j), i * 32 + j, 0, mod); + } + + if (polled) input_overlay_post_poll(driver.overlay); else