Skip to content

Commit 62759d1

Browse files
committed
Console: add input rebinding settings
1 parent c081555 commit 62759d1

File tree

6 files changed

+228
-108
lines changed

6 files changed

+228
-108
lines changed

src/console/console_ui.cpp

+138-43
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,6 @@ void *ConsoleUI::fileTextures[2];
3939
void *ConsoleUI::folderTextures[2];
4040
void *ConsoleUI::fontTexture;
4141

42-
int ConsoleUI::showFpsCounter = 0;
43-
int ConsoleUI::menuTheme = 0;
44-
4542
const uint32_t *ConsoleUI::palette;
4643
uint32_t ConsoleUI::uiWidth, ConsoleUI::uiHeight;
4744
uint32_t ConsoleUI::lineHeight;
@@ -61,6 +58,10 @@ std::thread *ConsoleUI::coreThread, *ConsoleUI::saveThread;
6158
std::condition_variable ConsoleUI::cond;
6259
std::mutex ConsoleUI::mutex;
6360

61+
int ConsoleUI::showFpsCounter = 0;
62+
int ConsoleUI::menuTheme = 0;
63+
int ConsoleUI::keyBinds[] = {};
64+
6465
const uint32_t ConsoleUI::themeColors[] =
6566
{
6667
0xFF2D2D2D, 0xFFFFFFFF, 0xFF4B4B4B, 0xFF232323, 0xFFE1B955, 0xFFC8FF00, // Dark
@@ -179,11 +180,27 @@ void ConsoleUI::initialize(int width, int height, std::string root, std::string
179180
// Create the settings folder if it doesn't exist
180181
mkdir(prefix.c_str(), 0777);
181182

183+
// Set the default input bindings
184+
for (int i = 0; i < INPUT_MAX; i++)
185+
keyBinds[i] = defaultKeys[i];
186+
182187
// Define the platform settings
183188
std::vector<Setting> platformSettings =
184189
{
185190
Setting("showFpsCounter", &showFpsCounter, false),
186-
Setting("menuTheme", &menuTheme, false)
191+
Setting("menuTheme", &menuTheme, false),
192+
Setting("keyA", &keyBinds[INPUT_A], false),
193+
Setting("keyB", &keyBinds[INPUT_B], false),
194+
Setting("keySelect", &keyBinds[INPUT_SELECT], false),
195+
Setting("keyStart", &keyBinds[INPUT_START], false),
196+
Setting("keyRight", &keyBinds[INPUT_RIGHT], false),
197+
Setting("keyLeft", &keyBinds[INPUT_LEFT], false),
198+
Setting("keyUp", &keyBinds[INPUT_UP], false),
199+
Setting("keyDown", &keyBinds[INPUT_DOWN], false),
200+
Setting("keyR", &keyBinds[INPUT_R], false),
201+
Setting("keyL", &keyBinds[INPUT_L], false),
202+
Setting("keyX", &keyBinds[INPUT_X], false),
203+
Setting("keyY", &keyBinds[INPUT_Y], false),
187204
};
188205

189206
// Add the platform settings
@@ -274,9 +291,9 @@ void ConsoleUI::mainLoop(MenuTouch (*specialTouch)(), ScreenLayout *touchLayout)
274291
// Send input to the core
275292
for (int i = 0; i < 12; i++)
276293
{
277-
if (pressed & BIT(i))
294+
if (pressed & keyBinds[i])
278295
core->input.pressKey(i);
279-
else if (~held & BIT(i))
296+
else if (!(held & keyBinds[i]))
280297
core->input.releaseKey(i);
281298
}
282299

@@ -310,7 +327,7 @@ void ConsoleUI::mainLoop(MenuTouch (*specialTouch)(), ScreenLayout *touchLayout)
310327
if (botTexture) destroyTexture(botTexture);
311328

312329
// Open the pause menu if requested
313-
if (held & INPUT_PAUSE)
330+
if (held & keyBinds[INPUT_PAUSE])
314331
pauseMenu();
315332
}
316333
}
@@ -323,7 +340,7 @@ int ConsoleUI::setPath(std::string path)
323340
// If a GBA path is set, allow clearing it
324341
if (gbaPath != "")
325342
{
326-
if (!message("Loading NDS ROM", "Load the previous GBA ROM alongside this ROM?", true))
343+
if (!message("Loading NDS ROM", "Load the previous GBA ROM alongside this ROM?", 1))
327344
gbaPath = "";
328345
}
329346

@@ -346,7 +363,7 @@ int ConsoleUI::setPath(std::string path)
346363
// If an NDS path is set, allow clearing it
347364
if (ndsPath != "")
348365
{
349-
if (!message("Loading GBA ROM", "Load the previous NDS ROM alongside this ROM?", true))
366+
if (!message("Loading GBA ROM", "Load the previous NDS ROM alongside this ROM?", 1))
350367
ndsPath = "";
351368
}
352369

@@ -408,7 +425,7 @@ uint32_t ConsoleUI::menu(std::string title, std::vector<MenuItem> &items,
408425
uint32_t held = getInputHeld();
409426

410427
// Handle up input presses
411-
if ((pressed & INPUT_UP) && !(pressed & INPUT_DOWN))
428+
if ((pressed & defaultKeys[INPUT_UP]) && !(pressed & defaultKeys[INPUT_DOWN]))
412429
{
413430
// Disable touch mode or move the selection box up
414431
if (touchMode)
@@ -422,7 +439,7 @@ uint32_t ConsoleUI::menu(std::string title, std::vector<MenuItem> &items,
422439
}
423440

424441
// Handle down input presses
425-
if ((pressed & INPUT_DOWN) && !(pressed & INPUT_UP))
442+
if ((pressed & defaultKeys[INPUT_DOWN]) && !(pressed & defaultKeys[INPUT_UP]))
426443
{
427444
// Disable touch mode or move the selection box down
428445
if (touchMode)
@@ -436,26 +453,26 @@ uint32_t ConsoleUI::menu(std::string title, std::vector<MenuItem> &items,
436453
}
437454

438455
// Return button presses so they can be handled externally
439-
if (((pressed & INPUT_A) && !touchMode) || (pressed & INPUT_B) || (actionX != ""
440-
&& (pressed & INPUT_X)) || (actionPlus != "" && (pressed & INPUT_START)))
456+
if (((pressed & defaultKeys[INPUT_A]) && !touchMode) || (pressed & defaultKeys[INPUT_B]) || (actionX != ""
457+
&& (pressed & defaultKeys[INPUT_X])) || (actionPlus != "" && (pressed & defaultKeys[INPUT_START])))
441458
{
442459
touchMode = false;
443460
return pressed;
444461
}
445462

446463
// Disable touch mode before allowing A presses so the selector is visible
447-
if ((pressed & INPUT_A) && touchMode)
464+
if ((pressed & defaultKeys[INPUT_A]) && touchMode)
448465
touchMode = false;
449466

450467
// Cancel up input if it was released
451-
if (upHeld && !(held & INPUT_UP))
468+
if (upHeld && !(held & defaultKeys[INPUT_UP]))
452469
{
453470
upHeld = false;
454471
scroll = false;
455472
}
456473

457474
// Cancel down input if it was released
458-
if (downHeld && !(held & INPUT_DOWN))
475+
if (downHeld && !(held & defaultKeys[INPUT_DOWN]))
459476
{
460477
downHeld = false;
461478
scroll = false;
@@ -514,11 +531,11 @@ uint32_t ConsoleUI::menu(std::string title, std::vector<MenuItem> &items,
514531
if (!touchScroll && touchStart.y >= 650)
515532
{
516533
if (touchStart.x >= boundsBX && touchStart.x < boundsAB)
517-
return INPUT_B;
534+
return defaultKeys[INPUT_B];
518535
else if (touchStart.x >= boundsXPlus && touchStart.x < boundsBX)
519-
return INPUT_X;
536+
return defaultKeys[INPUT_X];
520537
else if (touchStart.x >= boundsPlus && touchStart.x < boundsXPlus)
521-
return INPUT_START;
538+
return defaultKeys[INPUT_START];
522539
}
523540
touchStarted = false;
524541
}
@@ -544,7 +561,7 @@ uint32_t ConsoleUI::menu(std::string title, std::vector<MenuItem> &items,
544561
1190 && touchStart.y >= 124 + i * 70 && touchStart.y < 194 + i * 70)
545562
{
546563
index = offset;
547-
return INPUT_A;
564+
return defaultKeys[INPUT_A];
548565
}
549566

550567
// Draw UI elements around the list items
@@ -582,7 +599,7 @@ uint32_t ConsoleUI::menu(std::string title, std::vector<MenuItem> &items,
582599
}
583600
}
584601

585-
bool ConsoleUI::message(std::string title, std::string text, bool cancel)
602+
uint32_t ConsoleUI::message(std::string title, std::string text, int type)
586603
{
587604
// Define the action strings
588605
std::string actionB = "\x81 Back ";
@@ -605,7 +622,7 @@ bool ConsoleUI::message(std::string title, std::string text, bool cancel)
605622
drawString(title, SCALE(72), SCALE(30), SCALE(42), palette[1]);
606623
drawRectangle(SCALE(30), SCALE(88), SCALE(1220), lineHeight, palette[1]);
607624
drawRectangle(SCALE(30), SCALE(648), SCALE(1220), lineHeight, palette[1]);
608-
drawString((cancel ? actionB : "") + actionA, SCALE(1218), SCALE(667), SCALE(34), palette[1], true);
625+
if (type < 2) drawString((type ? actionB : "") + actionA, SCALE(1218), SCALE(667), SCALE(34), palette[1], true);
609626

610627
// Draw each line of text, separated by newline characters
611628
for (int i = 0, j = 0, y = 0; j != std::string::npos; y += 38)
@@ -619,10 +636,12 @@ bool ConsoleUI::message(std::string title, std::string text, bool cancel)
619636
uint32_t pressed = getInputPress();
620637

621638
// Dismiss the message and return the result if an action is pressed
622-
if (pressed & INPUT_A)
623-
return true;
624-
else if ((pressed & INPUT_B) && cancel)
625-
return false;
639+
if (pressed && type == 2) // Input
640+
return pressed;
641+
else if (pressed & defaultKeys[INPUT_A]) // Default
642+
return 1;
643+
else if ((pressed & defaultKeys[INPUT_B]) && type == 1) // Cancel
644+
return 0;
626645

627646
// Scan for touch input
628647
MenuTouch touch = getInputTouch();
@@ -649,10 +668,10 @@ bool ConsoleUI::message(std::string title, std::string text, bool cancel)
649668
// Simulate a button press if its action text was tapped
650669
if (!touchScroll && touchStart.y >= 650)
651670
{
652-
if (touchStart.x >= boundsAB && touchStart.x < boundsA)
653-
return true;
654-
else if (touchStart.x >= boundsB && touchStart.x < boundsAB && cancel)
655-
return false;
671+
if (touchStart.x >= boundsAB && touchStart.x < boundsA && type < 2)
672+
return 1;
673+
else if (touchStart.x >= boundsB && touchStart.x < boundsAB && type == 1)
674+
return 0;
656675
}
657676
touchStarted = false;
658677
}
@@ -708,7 +727,7 @@ void ConsoleUI::fileBrowser()
708727
uint32_t pressed = menu("NooDS", files, index, "Settings", "Exit");
709728

710729
// Handle menu input
711-
if (pressed & INPUT_A)
730+
if (pressed & defaultKeys[INPUT_A])
712731
{
713732
// Navigate to the selected file if any exist
714733
if (files.empty()) continue;
@@ -731,7 +750,7 @@ void ConsoleUI::fileBrowser()
731750
return;
732751
}
733752
}
734-
else if (pressed & INPUT_B)
753+
else if (pressed & defaultKeys[INPUT_B])
735754
{
736755
// Navigate to the previous directory
737756
if (curPath != basePath)
@@ -740,12 +759,12 @@ void ConsoleUI::fileBrowser()
740759
index = 0;
741760
}
742761
}
743-
else if (pressed & INPUT_X)
762+
else if (pressed & defaultKeys[INPUT_X])
744763
{
745764
// Open the settings menu
746765
settingsMenu();
747766
}
748-
else if (pressed & INPUT_START)
767+
else if (pressed & defaultKeys[INPUT_START])
749768
{
750769
// Close the file browser
751770
return;
@@ -790,10 +809,10 @@ void ConsoleUI::settingsMenu()
790809
};
791810

792811
// Create the settings menu
793-
uint32_t pressed = menu("Settings", settings, index);
812+
uint32_t pressed = menu("Settings", settings, index, "Controls");
794813

795814
// Handle menu input
796-
if (pressed & INPUT_A)
815+
if (pressed & defaultKeys[INPUT_A])
797816
{
798817
// Change the chosen setting to its next value
799818
switch (index)
@@ -821,13 +840,89 @@ void ConsoleUI::settingsMenu()
821840
break;
822841
}
823842
}
824-
else if (pressed & INPUT_B)
843+
else if (pressed & defaultKeys[INPUT_B])
825844
{
826845
// Close the settings menu
827846
changed = true;
828847
Settings::save();
829848
return;
830849
}
850+
else if (pressed & defaultKeys[INPUT_X])
851+
{
852+
// Open the controls menu
853+
controlsMenu();
854+
}
855+
}
856+
}
857+
858+
void ConsoleUI::controlsMenu()
859+
{
860+
int index = 0;
861+
while (true)
862+
{
863+
// Define names for the bindable inputs
864+
const char *names[] =
865+
{
866+
"A Button", "B Button", "Select Button", "Start Button",
867+
"Right Button", "Left Button", "Up Button", "Down Button",
868+
"R Button", "L Button", "X Button", "Y Button", "Menu Button"
869+
};
870+
871+
// Build strings for the input bindings
872+
std::string bindings[INPUT_MAX];
873+
for (int i = 0; i < INPUT_MAX; i++)
874+
{
875+
// Add the input name with a comma (up to 8 entries)
876+
for (int j = 0, k = -1; j < 32 && k < 8; j++)
877+
{
878+
if (!(keyBinds[i] & (1 << j))) continue;
879+
if (bindings[i] != "") bindings[i] += ", ";
880+
bindings[i] += (++k < 8) ? keyNames[j] : "...";
881+
}
882+
883+
// Replace empty strings with the word none
884+
if (bindings[i] == "")
885+
bindings[i] = "None";
886+
}
887+
888+
// Create a list of inputs and current bindings
889+
std::vector<MenuItem> controls =
890+
{
891+
MenuItem(names[INPUT_A], bindings[INPUT_A]),
892+
MenuItem(names[INPUT_B], bindings[INPUT_B]),
893+
MenuItem(names[INPUT_SELECT], bindings[INPUT_SELECT]),
894+
MenuItem(names[INPUT_START], bindings[INPUT_START]),
895+
MenuItem(names[INPUT_RIGHT], bindings[INPUT_RIGHT]),
896+
MenuItem(names[INPUT_LEFT], bindings[INPUT_LEFT]),
897+
MenuItem(names[INPUT_UP], bindings[INPUT_UP]),
898+
MenuItem(names[INPUT_DOWN], bindings[INPUT_DOWN]),
899+
MenuItem(names[INPUT_R], bindings[INPUT_R]),
900+
MenuItem(names[INPUT_L], bindings[INPUT_L]),
901+
MenuItem(names[INPUT_X], bindings[INPUT_X]),
902+
MenuItem(names[INPUT_Y], bindings[INPUT_Y]),
903+
MenuItem(names[INPUT_PAUSE], bindings[INPUT_PAUSE]),
904+
};
905+
906+
// Create the controls menu
907+
uint32_t pressed = menu("Controls", controls, index, "Clear");
908+
909+
// Handle menu input
910+
if (pressed & defaultKeys[INPUT_A])
911+
{
912+
// Show a binding message and bind the pressed input
913+
keyBinds[index] |= message(std::string("Remap ") + names[index],
914+
"Press an input to add it as a binding.", 2);
915+
}
916+
else if (pressed & defaultKeys[INPUT_B])
917+
{
918+
// Close the controls menu
919+
return;
920+
}
921+
else if (pressed & defaultKeys[INPUT_X])
922+
{
923+
// Clear an input binding
924+
keyBinds[index] = 0;
925+
}
831926
}
832927
}
833928

@@ -855,7 +950,7 @@ void ConsoleUI::pauseMenu()
855950
uint32_t pressed = menu("NooDS", items, index);
856951

857952
// Handle menu input
858-
if (pressed & INPUT_A)
953+
if (pressed & defaultKeys[INPUT_A])
859954
{
860955
// Handle the selected item
861956
switch (index)
@@ -876,7 +971,7 @@ void ConsoleUI::pauseMenu()
876971
"loading states is dangerous and can lead to data loss.\nStates are also not guaranteed to "
877972
"be compatible across emulator versions.\nPlease rely on in-game saving to keep your progress, "
878973
"and back up .sav files\nbefore using this feature. Do you want to save the current state?" :
879-
"Do you want to overwrite the saved state with the current state? This can't be undone!", true))
974+
"Do you want to overwrite the saved state with the current state? This can't be undone!", 1))
880975
break;
881976

882977
// Save the state and return to emulation if confirmed
@@ -938,7 +1033,7 @@ void ConsoleUI::pauseMenu()
9381033
return;
9391034
}
9401035
}
941-
else if (pressed & INPUT_B)
1036+
else if (pressed & defaultKeys[INPUT_B])
9421037
{
9431038
// Return to the emulator
9441039
startCore();
@@ -983,10 +1078,10 @@ bool ConsoleUI::saveTypeMenu()
9831078
uint32_t pressed = menu("Change Save Type", items, index);
9841079

9851080
// Handle menu input
986-
if (pressed & INPUT_A)
1081+
if (pressed & defaultKeys[INPUT_A])
9871082
{
9881083
// Confirm the change because doing this accidentally could be bad
989-
if (!message("Changing Save Type", "Are you sure? This may result in data loss!", true))
1084+
if (!message("Changing Save Type", "Are you sure? This may result in data loss!", 1))
9901085
continue;
9911086

9921087
// Apply the change for the current mode
@@ -1022,7 +1117,7 @@ bool ConsoleUI::saveTypeMenu()
10221117
}
10231118
return true;
10241119
}
1025-
else if (pressed & INPUT_B)
1120+
else if (pressed & defaultKeys[INPUT_B])
10261121
{
10271122
// Close the save type menu
10281123
return false;

0 commit comments

Comments
 (0)