Skip to content

Commit 04955c0

Browse files
authored
Add support for analog controls (#113)
1 parent e3d7a2b commit 04955c0

File tree

11 files changed

+270
-72
lines changed

11 files changed

+270
-72
lines changed

src/Application.cpp

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -371,8 +371,8 @@ void Application::processEvents()
371371

372372
void Application::runSmoothed()
373373
{
374-
const int TARGET_FRAMES = (int)round(_core.getSystemAVInfo()->timing.fps);
375-
const int SMOOTHING_FRAMES = 32;
374+
const unsigned int TARGET_FRAMES = (int)round(_core.getSystemAVInfo()->timing.fps);
375+
const unsigned int SMOOTHING_FRAMES = 32;
376376
uint32_t frameMicroseconds[SMOOTHING_FRAMES];
377377
uint32_t totalMicroseconds;
378378
int frameIndex = 0;
@@ -393,7 +393,7 @@ void Application::runSmoothed()
393393
const auto tFirstFrameEnd = std::chrono::steady_clock::now();
394394
const auto tFirstFrameElapsed = std::chrono::duration_cast<std::chrono::microseconds>(tFirstFrameEnd - tFirstFrameStart);
395395

396-
for (int i = 0; i < SMOOTHING_FRAMES; ++i)
396+
for (unsigned int i = 0; i < SMOOTHING_FRAMES; ++i)
397397
frameMicroseconds[i] = (uint32_t)tFirstFrameElapsed.count();
398398
totalMicroseconds = frameMicroseconds[0] * SMOOTHING_FRAMES;
399399

@@ -685,6 +685,8 @@ bool Application::loadCore(const std::string& coreName)
685685
});
686686

687687
free(data);
688+
689+
_config.initializeInput(_input);
688690
}
689691

690692
_coreName = coreName;
@@ -2125,7 +2127,7 @@ void Application::handle(const SDL_SysWMEvent* syswm)
21252127
break;
21262128

21272129
case IDM_CORE_CONFIG:
2128-
_config.showDialog(_core.getSystemInfo()->library_name);
2130+
_config.showDialog(_core.getSystemInfo()->library_name, _input);
21292131
break;
21302132

21312133
case IDM_INPUT_CONFIG:
@@ -2236,6 +2238,12 @@ void Application::handle(const KeyBinds::Action action, unsigned extra)
22362238
case KeyBinds::Action::kButtonSelect: _input.buttonEvent(extra >> 8, Input::Button::kSelect, (extra & 0xFF) != 0); break;
22372239
case KeyBinds::Action::kButtonStart: _input.buttonEvent(extra >> 8, Input::Button::kStart, (extra & 0xFF) != 0); break;
22382240

2241+
// Joypad analog sticks
2242+
case KeyBinds::Action::kAxisLeftX: _input.axisEvent(extra >> 16, Input::Axis::kLeftAxisX, (int16_t)(extra & 0xFFFF)); break;
2243+
case KeyBinds::Action::kAxisLeftY: _input.axisEvent(extra >> 16, Input::Axis::kLeftAxisY, (int16_t)(extra & 0xFFFF)); break;
2244+
case KeyBinds::Action::kAxisRightX: _input.axisEvent(extra >> 16, Input::Axis::kRightAxisX, (int16_t)(extra & 0xFFFF)); break;
2245+
case KeyBinds::Action::kAxisRightY: _input.axisEvent(extra >> 16, Input::Axis::kRightAxisY, (int16_t)(extra & 0xFFFF)); break;
2246+
22392247
// State management
22402248
case KeyBinds::Action::kSaveState: saveState(extra); break;
22412249
case KeyBinds::Action::kLoadState: loadState(extra); break;

src/Application.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,6 @@ class Application
5454
void unloadCore();
5555
void resetGame();
5656
bool hardcore();
57-
void setTurbo(bool turbo);
5857
bool unloadGame();
5958
void pauseGame(bool pause);
6059

src/Emulator.cpp

Lines changed: 5 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,9 @@ bool loadCores(Config* config, Logger* logger)
170170
ud->core->systems.insert(static_cast<System>(std::stoi(system)));
171171
}
172172
break;
173+
174+
default:
175+
break;
173176
}
174177

175178
return 0;
@@ -290,30 +293,6 @@ const char* getSystemName(System system)
290293
return "?";
291294
}
292295

293-
static bool romLoadedWithPadding(void* rom, size_t size, size_t max_size, int fill)
294-
{
295-
uint8_t* data = (uint8_t*)malloc(max_size);
296-
297-
if (data != NULL)
298-
{
299-
if (size < max_size)
300-
{
301-
memcpy(data, rom, size);
302-
memset(data + size, fill, max_size - size);
303-
}
304-
else
305-
{
306-
memcpy(data, rom, max_size);
307-
}
308-
309-
RA_OnLoadNewRom(data, max_size);
310-
free(data);
311-
return true;
312-
}
313-
314-
return false;
315-
}
316-
317296
static bool romLoadSnes(void* rom, size_t size)
318297
{
319298
// if the file contains a header, ignore it
@@ -542,7 +521,7 @@ class CoreDialog : public Dialog
542521
continue;
543522

544523
if (core.systems.find(system) != core.systems.end())
545-
systemCores.insert_or_assign(core.name, &core);
524+
systemCores.emplace(core.name, &core);
546525
}
547526

548527
char buffer[64];
@@ -819,7 +798,7 @@ bool showCoresDialog(Config* config, Logger* logger)
819798

820799
for (auto system : core.systems)
821800
{
822-
allSystems.insert_or_assign(getSystemName(system), system);
801+
allSystems.emplace(getSystemName(system), system);
823802
if (++systemCoreCounts[(int)system] > maxSystemCoreCount)
824803
maxSystemCoreCount = systemCoreCounts[(int)system];
825804
}

src/KeyBinds.cpp

Lines changed: 109 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,10 @@ enum
5050
kJoy0R3,
5151
kJoy0Select,
5252
kJoy0Start,
53+
kJoy0LeftAnalogX,
54+
kJoy0LeftAnalogY,
55+
kJoy0RightAnalogX,
56+
kJoy0RightAnalogY,
5357

5458
kJoy1Up,
5559
kJoy1Down,
@@ -67,6 +71,10 @@ enum
6771
kJoy1R3,
6872
kJoy1Select,
6973
kJoy1Start,
74+
kJoy1LeftAnalogX,
75+
kJoy1LeftAnalogY,
76+
kJoy1RightAnalogX,
77+
kJoy1RightAnalogY,
7078

7179
// State management
7280
kSaveState1,
@@ -127,9 +135,11 @@ enum
127135
static const char* bindingNames[] = {
128136
"J0_UP", "J0_DOWN", "J0_LEFT", "J0_RIGHT", "J0_X", "J0_Y", "J0_A", "J0_B",
129137
"J0_L", "J0_R", "J0_L2", "J0_R2", "J0_L3", "J0_R3", "J0_SELECT", "J0_START",
138+
"J0_LSTICK_X", "J0_LSTICK_Y", "J0_RSTICK_X", "J0_RSTICK_Y",
130139

131140
"J1_UP", "J1_DOWN", "J1_LEFT", "J1_RIGHT", "J1_X", "J1_Y", "J1_A", "J1_B",
132141
"J1_L", "J1_R", "J1_L2", "J1_R2", "J1_L3", "J1_R3", "J1_SELECT", "J1_START",
142+
"J1_LSTICK_X", "J1_LSTICK_Y", "J1_RSTICK_X", "J1_RSTICK_Y",
133143

134144
"SAVE1", "SAVE2", "SAVE3", "SAVE4", "SAVE5", "SAVE6", "SAVE7", "SAVE8", "SAVE9", "SAVE0",
135145
"LOAD1", "LOAD2", "LOAD3", "LOAD4", "LOAD5", "LOAD6", "LOAD7", "LOAD8", "LOAD9", "LOAD0",
@@ -170,6 +180,10 @@ bool KeyBinds::init(libretro::LoggerComponent* logger)
170180
_bindings[kJoy0R2] = { 0, SDL_CONTROLLER_AXIS_TRIGGERRIGHT, Binding::Type::Axis, 0 };
171181
_bindings[kJoy0L3] = { 0, SDL_CONTROLLER_BUTTON_LEFTSTICK, Binding::Type::Button, 0 };
172182
_bindings[kJoy0R3] = { 0, SDL_CONTROLLER_BUTTON_RIGHTSTICK, Binding::Type::Button, 0 };
183+
_bindings[kJoy0LeftAnalogX] = { 0, SDL_CONTROLLER_AXIS_LEFTX, Binding::Type::Axis, 0 };
184+
_bindings[kJoy0LeftAnalogY] = { 0, SDL_CONTROLLER_AXIS_LEFTY, Binding::Type::Axis, 0 };
185+
_bindings[kJoy0RightAnalogX] = { 0, SDL_CONTROLLER_AXIS_RIGHTX, Binding::Type::Axis, 0 };
186+
_bindings[kJoy0RightAnalogY] = { 0, SDL_CONTROLLER_AXIS_RIGHTY, Binding::Type::Axis, 0 };
173187
_bindings[kJoy0Select] = { 0, SDL_CONTROLLER_BUTTON_BACK, Binding::Type::Button, 0 };
174188
_bindings[kJoy0Start] = { 0, SDL_CONTROLLER_BUTTON_START, Binding::Type::Button, 0 };
175189
}
@@ -391,6 +405,34 @@ KeyBinds::Action KeyBinds::translateButtonReleased(int button, unsigned* extra)
391405
}
392406
}
393407

408+
KeyBinds::Action KeyBinds::translateAnalog(int button, Sint16 value, unsigned* extra)
409+
{
410+
KeyBinds::Action action;
411+
unsigned controller;
412+
413+
switch (button)
414+
{
415+
case kJoy0LeftAnalogX: action = Action::kAxisLeftX; controller = 0; break;
416+
case kJoy0LeftAnalogY: action = Action::kAxisLeftY; controller = 0; break;
417+
case kJoy0RightAnalogX: action = Action::kAxisRightX; controller = 0; break;
418+
case kJoy0RightAnalogY: action = Action::kAxisRightY; controller = 0; break;
419+
case kJoy1LeftAnalogX: action = Action::kAxisLeftX; controller = 1; break;
420+
case kJoy1LeftAnalogY: action = Action::kAxisLeftY; controller = 1; break;
421+
case kJoy1RightAnalogX: action = Action::kAxisRightX; controller = 1; break;
422+
case kJoy1RightAnalogY: action = Action::kAxisRightY; controller = 1; break;
423+
424+
default:
425+
return Action::kNothing;
426+
}
427+
428+
/* if we pass -32768, it sometimes causes an overflow and acts like a positive value */
429+
if (value == -32768)
430+
value = -32767;
431+
432+
*extra = (((unsigned)value) & 0xFFFF) | (controller << 16);
433+
return action;
434+
}
435+
394436
KeyBinds::Action KeyBinds::translate(const SDL_KeyboardEvent* key, unsigned* extra)
395437
{
396438
if (key->repeat)
@@ -409,7 +451,7 @@ KeyBinds::Action KeyBinds::translate(const SDL_KeyboardEvent* key, unsigned* ext
409451
{
410452
if (_bindings[i].type == Binding::Type::Key)
411453
{
412-
if (key->keysym.sym == _bindings[i].button && mod == _bindings[i].modifiers)
454+
if ((uint32_t)key->keysym.sym == _bindings[i].button && mod == _bindings[i].modifiers)
413455
{
414456
if (key->state == SDL_PRESSED)
415457
return translateButtonPress(i, extra);
@@ -447,19 +489,48 @@ KeyBinds::Action KeyBinds::translate(const SDL_ControllerButtonEvent* cbutton, u
447489
return Action::kNothing;
448490
}
449491

492+
static bool IsAnalog(int button)
493+
{
494+
switch (button)
495+
{
496+
case kJoy0LeftAnalogX:
497+
case kJoy0LeftAnalogY:
498+
case kJoy0RightAnalogX:
499+
case kJoy0RightAnalogY:
500+
case kJoy1LeftAnalogX:
501+
case kJoy1LeftAnalogY:
502+
case kJoy1RightAnalogX:
503+
case kJoy1RightAnalogY:
504+
return true;
505+
506+
default:
507+
return false;
508+
}
509+
}
510+
450511
void KeyBinds::translate(const SDL_ControllerAxisEvent* caxis, Input& input,
451512
Action* action1, unsigned* extra1, Action* action2, unsigned* extra2)
452513
{
453514
*action1 = *action2 = Action::kNothing;
454515

455516
int threshold = static_cast<int>(32767 * input.getJoystickSensitivity(caxis->which));
517+
int analogThreshold = threshold / 4;
456518
for (size_t i = 0; i < kMaxBindings; i++)
457519
{
458520
if (_bindings[i].type == Binding::Type::Axis)
459521
{
460522
if (caxis->axis == _bindings[i].button && caxis->which == _bindings[i].joystick_id)
461523
{
462-
if ((_bindings[i].modifiers & 0xFF) == 0xFF) // negative axis
524+
if (IsAnalog(i))
525+
{
526+
if (caxis->value > analogThreshold || caxis->value < -analogThreshold)
527+
*action1 = translateAnalog(i, caxis->value, extra1);
528+
else
529+
*action1 = translateAnalog(i, 0, extra1);
530+
531+
break;
532+
}
533+
else if ((_bindings[i].modifiers & 0xFF) == 0xFF) // negative axis
463534
{
464535
if (caxis->value < -threshold)
465536
*action1 = translateButtonPress(i, extra1);
@@ -661,7 +732,6 @@ bool KeyBinds::deserializeBindings(const char* json)
661732
}
662733
else if (event == JSONSAX_STRING)
663734
{
664-
int binding = 0;
665735
for (int i = 0; i < kMaxBindings; ++i)
666736
{
667737
if (ud->key == bindingNames[i])
@@ -799,7 +869,8 @@ class ChangeInputDialog : public Dialog
799869
const KeyBinds::Binding getButtonDescriptor() const { return _buttonDescriptor; }
800870

801871
Input* _input = nullptr;
802-
bool _isOpen;
872+
bool _isOpen = false;
873+
bool _isAnalog = false;
803874

804875
bool show(HWND hParent)
805876
{
@@ -823,6 +894,9 @@ class ChangeInputDialog : public Dialog
823894
case WM_KEYDOWN:
824895
case WM_SYSKEYDOWN:
825896
{
897+
if (_isAnalog)
898+
break;
899+
826900
const auto code = WindowsScanCodeToSDLScanCode(msg.lParam, msg.wParam);
827901
const auto sdlKey = SDL_GetKeyFromScancode(code);
828902
switch (sdlKey)
@@ -903,6 +977,25 @@ class ChangeInputDialog : public Dialog
903977
_isOpen = false;
904978
}
905979

980+
bool MakeAnalog(KeyBinds::Binding& button)
981+
{
982+
if (button.type != KeyBinds::Binding::Type::Axis)
983+
return false;
984+
985+
switch (button.button)
986+
{
987+
case SDL_CONTROLLER_AXIS_LEFTX:
988+
case SDL_CONTROLLER_AXIS_LEFTY:
989+
case SDL_CONTROLLER_AXIS_RIGHTX:
990+
case SDL_CONTROLLER_AXIS_RIGHTY:
991+
button.modifiers = 0;
992+
return true;
993+
994+
default:
995+
return false;
996+
}
997+
}
998+
906999
INT_PTR dialogProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) override
9071000
{
9081001
switch (msg)
@@ -930,6 +1023,9 @@ class ChangeInputDialog : public Dialog
9301023
KeyBinds::Binding button = _input->captureButtonPress();
9311024
if (button.type != KeyBinds::Binding::Type::None)
9321025
{
1026+
if (_isAnalog && !MakeAnalog(button))
1027+
break;
1028+
9331029
_buttonDescriptor = button;
9341030
char buffer[32];
9351031
KeyBinds::getBindingString(buffer, _buttonDescriptor);
@@ -951,7 +1047,7 @@ class InputDialog : public Dialog
9511047
_bindings = bindings;
9521048

9531049
const WORD WIDTH = 478;
954-
const WORD HEIGHT = 144;
1050+
const WORD HEIGHT = 200;
9551051

9561052
addButtonInput(0, 1, "L2", kJoy0L2 + base);
9571053
addButtonInput(0, 9, "R2", kJoy0R2 + base);
@@ -968,6 +1064,13 @@ class InputDialog : public Dialog
9681064
addButtonInput(4, 1, "Down", kJoy0Down + base);
9691065
addButtonInput(4, 9, "B", kJoy0B + base);
9701066

1067+
addButtonInput(5, 1, "L3", kJoy0L3 + base);
1068+
addButtonInput(5, 9, "R3", kJoy0R3 + base);
1069+
addButtonInput(6, 0, "Left Analog X", kJoy0LeftAnalogX + base);
1070+
addButtonInput(6, 2, "Left Analog Y", kJoy0LeftAnalogY + base);
1071+
addButtonInput(6, 8, "Right Analog X", kJoy0RightAnalogX + base);
1072+
addButtonInput(6, 10, "Right Analog Y", kJoy0RightAnalogY + base);
1073+
9711074
addButton("OK", IDOK, WIDTH - 55 - 50, HEIGHT - 14, 50, 14, true);
9721075
addButton("Cancel", IDCANCEL, WIDTH - 50, HEIGHT - 14, 50, 14, false);
9731076
}
@@ -1081,6 +1184,7 @@ class InputDialog : public Dialog
10811184
ChangeInputDialog db;
10821185
db.init(buffer);
10831186
db._input = _input;
1187+
db._isAnalog = IsAnalog(button);
10841188

10851189
GetDlgItemText(hwnd, 10000 + button, buffer, sizeof(buffer));
10861190
db.addLabel(buffer, ChangeInputDialog::ID_LABEL, 0, 0, 100, 15);

src/KeyBinds.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,12 @@ class KeyBinds
5252
kButtonSelect,
5353
kButtonStart,
5454

55+
// Joypad analog sticks
56+
kAxisLeftX,
57+
kAxisLeftY,
58+
kAxisRightX,
59+
kAxisRightY,
60+
5561
// State state management (extra = slot)
5662
kSaveState,
5763
kLoadState,
@@ -99,7 +105,7 @@ class KeyBinds
99105
Type type;
100106
uint16_t modifiers;
101107
};
102-
typedef std::array<Binding, 77> BindingList;
108+
typedef std::array<Binding, 85> BindingList;
103109

104110
static void getBindingString(char buffer[32], const KeyBinds::Binding& desc);
105111

@@ -111,6 +117,7 @@ class KeyBinds
111117

112118
KeyBinds::Action translateButtonPress(int button, unsigned* extra);
113119
KeyBinds::Action translateButtonReleased(int button, unsigned* extra);
120+
KeyBinds::Action translateAnalog(int button, Sint16 value, unsigned* extra);
114121

115122
BindingList _bindings;
116123

src/Util.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -363,7 +363,7 @@ bool util::downloadFile(Logger* logger, const std::string& url, const std::strin
363363
bSuccess = TRUE;
364364
while (availableBytes > 0)
365365
{
366-
const DWORD bytesToRead = min(availableBytes, 4096);
366+
const DWORD bytesToRead = availableBytes < 4096 ? availableBytes : 4096;
367367
sBuffer.resize(bytesToRead);
368368

369369
DWORD bytesFetched = 0U;

0 commit comments

Comments
 (0)