1 
2 #include "input.h"
3 
4 #include "Utils/Logger.h"
5 #include "console.h"
6 #include "game.h"
7 #include "nx.h"
8 #include "settings.h"
9 #include "sound/SoundManager.h"
10 
11 #include <array>
12 
13 in_action mappings[INPUT_COUNT];
14 
15 bool inputs[INPUT_COUNT];
16 bool lastinputs[INPUT_COUNT];
17 in_action last_sdl_action;
18 SDL_Joystick *joy;
19 
20 int ACCEPT_BUTTON = JUMPKEY;
21 int DECLINE_BUTTON = FIREKEY;
22 
23 
input_init(void)24 bool input_init(void)
25 {
26   memset(inputs, 0, sizeof(inputs));
27   memset(lastinputs, 0, sizeof(lastinputs));
28   memset(mappings, -1, sizeof(mappings));
29   for (int i = 0; i < INPUT_COUNT; i++)
30   {
31     mappings[i].key   = -1;
32     mappings[i].jbut  = -1;
33     mappings[i].jhat  = -1;
34     mappings[i].jaxis = -1;
35   }
36 
37   // default mappings
38   mappings[LEFTKEY].key      = SDLK_LEFT;
39   mappings[RIGHTKEY].key     = SDLK_RIGHT;
40   mappings[UPKEY].key        = SDLK_UP;
41   mappings[DOWNKEY].key      = SDLK_DOWN;
42   mappings[JUMPKEY].key      = SDLK_z;
43   mappings[FIREKEY].key      = SDLK_x;
44   mappings[STRAFEKEY].key    = SDLK_c;
45   mappings[PREVWPNKEY].key   = SDLK_a;
46   mappings[NEXTWPNKEY].key   = SDLK_s;
47   mappings[INVENTORYKEY].key = SDLK_q;
48   mappings[MAPSYSTEMKEY].key = SDLK_w;
49 
50   mappings[ESCKEY].key = SDLK_ESCAPE;
51 
52 #if defined(__VITA__)
53   mappings[MAPSYSTEMKEY].jbut = 0; // Triangle
54   mappings[FIREKEY].jbut      = 1; // Circle
55   mappings[JUMPKEY].jbut      = 2; // Cross
56   mappings[INVENTORYKEY].jbut = 3; // Square
57   mappings[PREVWPNKEY].jbut   = 4; // LTrig
58   mappings[NEXTWPNKEY].jbut   = 5; // Rtrig
59 
60   mappings[DOWNKEY].jbut  = 6;
61   mappings[LEFTKEY].jbut  = 7;
62   mappings[UPKEY].jbut    = 8;
63   mappings[RIGHTKEY].jbut = 9;
64   mappings[ESCKEY].jbut   = 11;
65 #endif
66 
67 #if defined(__SWITCH__)
68   mappings[LEFTKEY].jbut      = 16;
69   mappings[UPKEY].jbut        = 17;
70   mappings[RIGHTKEY].jbut     = 18;
71   mappings[DOWNKEY].jbut      = 19;
72 
73   mappings[FIREKEY].jbut      = 1;  // A
74   mappings[JUMPKEY].jbut      = 0;  // B
75   mappings[MAPSYSTEMKEY].jbut = 3;  // X
76   mappings[INVENTORYKEY].jbut = 2;  // Y
77 
78   mappings[PREVWPNKEY].jbut   = 6;  // L
79   mappings[NEXTWPNKEY].jbut   = 7;  // R
80 
81   mappings[ENTERKEY].jbut     = 10; // +
82   mappings[ESCKEY].jbut       = 11; // -
83 #endif
84 
85   mappings[F1KEY].key  = SDLK_F1;
86   mappings[F2KEY].key  = SDLK_F2;
87   mappings[F3KEY].key  = SDLK_F3;
88   mappings[F4KEY].key  = SDLK_F4;
89   mappings[F5KEY].key  = SDLK_F5;
90   mappings[F6KEY].key  = SDLK_F6;
91   mappings[F7KEY].key  = SDLK_F7;
92   mappings[F8KEY].key  = SDLK_F8;
93   mappings[F9KEY].key  = SDLK_F9;
94   mappings[F10KEY].key = SDLK_F10;
95   mappings[F11KEY].key = SDLK_F11;
96   mappings[F12KEY].key = SDLK_F12;
97 #if defined(DEBUG)
98   mappings[FREEZE_FRAME_KEY].key  = SDLK_SPACE;
99   mappings[FRAME_ADVANCE_KEY].key = SDLK_b;
100   mappings[DEBUG_FLY_KEY].key     = SDLK_v;
101 #else
102   mappings[FREEZE_FRAME_KEY].key  = 0;
103   mappings[FRAME_ADVANCE_KEY].key = 0;
104   mappings[DEBUG_FLY_KEY].key     = 0;
105 #endif
106   mappings[ENTERKEY].key = SDLK_RETURN;
107 
108   SDL_InitSubSystem(SDL_INIT_JOYSTICK);
109   if (SDL_NumJoysticks() > 0)
110   {
111     // Open joystick
112     joy = SDL_JoystickOpen(0);
113 
114     if (joy)
115     {
116       LOG_INFO("Opened Joystick 0");
117       LOG_INFO("Name: {}", SDL_JoystickNameForIndex(0));
118       LOG_INFO("Number of Axes: {}", SDL_JoystickNumAxes(joy));
119       LOG_INFO("Number of Buttons: {}", SDL_JoystickNumButtons(joy));
120       LOG_INFO("Number of Balls: {}", SDL_JoystickNumBalls(joy));
121     }
122     else
123     {
124       LOG_WARN("Couldn't open Joystick 0");
125     }
126   }
127   return 0;
128 }
129 
rumble(float str,uint32_t len)130 void rumble(float str, uint32_t len)
131 {
132   if (settings->rumble)
133     SDL_JoystickRumble(joy, 0xFFFF * str, 0xFFFF * str, len);
134 }
135 
136 // set the SDL key that triggers an input
input_remap(int keyindex,in_action sdl_key)137 void input_remap(int keyindex, in_action sdl_key)
138 {
139   LOG_DEBUG("input_remap(%d => %d)", keyindex, sdl_key.key);
140   //	in_action old_mapping = input_get_mapping(keyindex);
141   //	if (old_mapping != -1)
142   //		mappings[old_mapping] = 0xff;
143 
144   mappings[keyindex] = sdl_key;
145 }
146 
147 // get which SDL key triggers a given input
input_get_mapping(int keyindex)148 in_action input_get_mapping(int keyindex)
149 {
150   return mappings[keyindex];
151 }
152 
input_get_action(int32_t sdlkey)153 int input_get_action(int32_t sdlkey)
154 {
155   for (int i = 0; i < INPUT_COUNT; i++)
156   {
157     if (mappings[i].key == sdlkey)
158     {
159       return i;
160     }
161   }
162   return -1;
163 }
164 
input_get_action_but(int32_t jbut)165 int input_get_action_but(int32_t jbut)
166 {
167   for (int i = 0; i < INPUT_COUNT; i++)
168   {
169     if (mappings[i].jbut == jbut)
170     {
171       return i;
172     }
173   }
174   return -1;
175 }
176 
input_get_action_hat(int32_t jhat,int32_t jvalue)177 int input_get_action_hat(int32_t jhat, int32_t jvalue)
178 {
179   for (int i = 0; i < INPUT_COUNT; i++)
180   {
181     if ((mappings[i].jhat == jhat) && (jvalue & mappings[i].jhat_value))
182     {
183       return i;
184     }
185   }
186   return -1;
187 }
188 
input_get_action_axis(int32_t jaxis,int32_t jvalue)189 int input_get_action_axis(int32_t jaxis, int32_t jvalue)
190 {
191   for (int i = 0; i < INPUT_COUNT; i++)
192   {
193     if ((mappings[i].jaxis == jaxis)
194         && ((jvalue > 0 && mappings[i].jaxis_value > 0) || (jvalue < 0 && mappings[i].jaxis_value < 0)))
195     {
196       return i;
197     }
198   }
199   return -1;
200 }
201 
input_get_name(int index)202 const std::string input_get_name(int index)
203 {
204   static std::array<std::string, 28> input_names = {"Left",         "Right",
205                                                     "Up",           "Down",
206                                                     "Jump",         "Fire",
207                                                     "Strafe",       "Wpn Prev",
208                                                     "Wpn Next",     "Inventory",
209                                                     "Map",          "Pause",
210                                                     "f1",           "f2",
211                                                     "f3",           "f4",
212                                                     "f5",           "f6",
213                                                     "f7",           "f8",
214                                                     "f9",           "f10",
215                                                     "f11",          "f12",
216                                                     "freeze frame", "frame advance",
217                                                     "debug fly",    "Enter"};
218 
219   if (index < 0 || index >= INPUT_COUNT)
220     return "invalid";
221 
222   return input_names[index];
223 }
224 
input_set_mappings(in_action * array)225 void input_set_mappings(in_action *array)
226 {
227   memset(mappings, 0xff, sizeof(mappings));
228   for (int i = 0; i < INPUT_COUNT; i++)
229     mappings[i] = array[i];
230 }
231 
232 /*
233 void c------------------------------() {}
234 */
235 
236 // keys that we don't want to send to the console
237 // even if the console is up.
IsNonConsoleKey(int key)238 static int IsNonConsoleKey(int key)
239 {
240   static const int nosend[] = {SDLK_LEFT, SDLK_RIGHT, 0};
241 
242   for (int i = 0; nosend[i]; i++)
243     if (key == nosend[i])
244       return true;
245 
246   return false;
247 }
248 
input_poll(void)249 void input_poll(void)
250 {
251   SDL_Event evt;
252   int32_t key;
253   int ino; //, key;
254 
255   while (SDL_PollEvent(&evt))
256   {
257     switch (evt.type)
258     {
259       case SDL_KEYDOWN:
260       case SDL_KEYUP:
261       {
262         key = evt.key.keysym.sym;
263 
264         static uint8_t shiftstates = 0;
265 
266         if (console.IsVisible() && !IsNonConsoleKey(key))
267         {
268           if (key == SDLK_LSHIFT)
269           {
270             if (evt.type == SDL_KEYDOWN)
271               shiftstates |= LEFTMASK;
272             else
273               shiftstates &= ~LEFTMASK;
274           }
275           else if (key == SDLK_RSHIFT)
276           {
277             if (evt.type == SDL_KEYDOWN)
278               shiftstates |= RIGHTMASK;
279             else
280               shiftstates &= ~RIGHTMASK;
281           }
282           else
283           {
284             int ch = key;
285             if (shiftstates != 0)
286             {
287               ch = toupper(ch);
288               if (ch == '.')
289                 ch = '>';
290               if (ch == '-')
291                 ch = '_';
292               if (ch == '/')
293                 ch = '?';
294               if (ch == '1')
295                 ch = '!';
296             }
297 
298             if (evt.type == SDL_KEYDOWN)
299               console.HandleKey(ch);
300             else
301               console.HandleKeyRelease(ch);
302           }
303         }
304         else
305         {
306           ino = input_get_action(key); // mappings[key];
307 
308           if (ino != -1)
309             inputs[ino] = (evt.type == SDL_KEYDOWN);
310 
311           if (evt.type == SDL_KEYDOWN)
312           {
313             if (key == '`') // bring up console
314             {
315 #if defined(DEBUG)
316               extern bool freezeframe;
317               if (!freezeframe)
318               {
319                 NXE::Sound::SoundManager::getInstance()->playSfx(NXE::Sound::SFX::SND_SWITCH_WEAPON);
320                 console.SetVisible(true);
321               }
322 #endif
323             }
324             else
325             {
326               last_sdl_action.key = key;
327             }
328           }
329         }
330       }
331       break;
332 
333       case SDL_QUIT:
334       {
335         inputs[ESCKEY] = true;
336         game.running   = false;
337       }
338       break;
339 
340       case SDL_JOYBUTTONDOWN:
341       {
342         Uint8 but            = evt.jbutton.button;
343         last_sdl_action.jbut = but;
344         ino                  = input_get_action_but(but); // mappings[key];
345         if (ino != -1)
346           inputs[ino] = (evt.jbutton.state == SDL_PRESSED);
347       }
348       break;
349 
350       case SDL_JOYBUTTONUP:
351       {
352         Uint8 but = evt.jbutton.button;
353         ino       = input_get_action_but(but); // mappings[key];
354         if (ino != -1)
355           inputs[ino] = (evt.jbutton.state == SDL_PRESSED);
356       }
357       break;
358 
359       case SDL_JOYHATMOTION:
360       {
361         if (evt.jhat.value != SDL_HAT_CENTERED)
362         {
363           last_sdl_action.jhat       = evt.jhat.hat;
364           last_sdl_action.jhat_value = evt.jhat.value;
365         }
366         ino = input_get_action_hat(evt.jhat.hat, evt.jhat.value); // mappings[key];
367         // cleanup all hat-binded states
368         for (int i = 0; i < INPUT_COUNT; i++)
369         {
370           if (mappings[i].jhat != -1)
371             inputs[i] = false;
372         }
373 
374         if (ino != -1)
375           inputs[ino] = true;
376       }
377       break;
378 
379       case SDL_JOYAXISMOTION:
380       {
381         // this only used for control remapping.
382         // for actual in-game handling see below.
383         if (evt.jaxis.value > 20000 || evt.jaxis.value < -20000) // dead zone
384         {
385           last_sdl_action.jaxis       = evt.jaxis.axis;
386           last_sdl_action.jaxis_value = evt.jaxis.value;
387         }
388       }
389       break;
390     }
391   }
392 
393   // handle gamepad sticks
394 
395   for (int i = 0; i < INPUT_COUNT; i++)
396   {
397     if (mappings[i].jaxis >= 0) // reset all mapped axises
398     {
399       inputs[i] = false;
400     }
401   }
402 
403   // now get current values of all axises
404   for (int ax = 0; ax < SDL_JoystickNumAxes(joy); ax++)
405   {
406     int value = SDL_JoystickGetAxis(joy, ax);
407     ino       = input_get_action_axis(ax, value); // this returns actual mapping for axis direction
408 
409     if (ino != -1 && (value > 20000 || value < -20000))
410       inputs[ino] = true;
411   }
412 }
413 
input_close(void)414 void input_close(void)
415 {
416   // Close if opened
417   if (SDL_JoystickGetAttached(joy))
418   {
419     SDL_JoystickClose(joy);
420   }
421 }
422 
423 /*
424 void c------------------------------() {}
425 */
426 
427 static const int buttons[] = {JUMPKEY, FIREKEY, STRAFEKEY, ACCEPT_BUTTON, DECLINE_BUTTON, 0};
428 
buttondown(void)429 bool buttondown(void)
430 {
431   for (int i = 0; buttons[i]; i++)
432   {
433     if (inputs[buttons[i]])
434       return 1;
435   }
436 
437   return 0;
438 }
439 
buttonjustpushed(void)440 bool buttonjustpushed(void)
441 {
442   for (int i = 0; buttons[i]; i++)
443   {
444     if (inputs[buttons[i]] && !lastinputs[buttons[i]])
445       return 1;
446   }
447 
448   return 0;
449 }
450 
justpushed(int k)451 bool justpushed(int k)
452 {
453   return (inputs[k] && !lastinputs[k]);
454 }
455