-
Notifications
You must be signed in to change notification settings - Fork 14
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add basic gamepad support and button remapping #35
base: trunk
Are you sure you want to change the base?
Changes from all commits
24fd6f8
f324e8e
d2d579e
383bef2
d820241
3716a5c
afa49d4
8fcf1e8
dbbebdb
c4b11c3
1f3f9f2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
// | ||
// Gamepad Interface | ||
// | ||
|
||
#ifndef __GAMEPAD_H__ | ||
#define __GAMEPAD_H__ | ||
|
||
typedef enum { | ||
BTN_UNKNOWN, | ||
BTN_PULLUP, | ||
BTN_PULLDOWN, | ||
BTN_FLIP, | ||
BTN_BOMB, | ||
BTN_FIRE, | ||
BTN_HOME, | ||
BTN_MISSILE, | ||
BTN_STARBURST, | ||
BTN_ACCEL, | ||
BTN_DECEL, | ||
BTN_SOUND, | ||
NUM_BTNS, | ||
} sopbtn_t; | ||
|
||
void Gamepad_Init(void); | ||
int Gamepad_GetBtn(void); | ||
int Gamepad_GetGameBtns(void); | ||
const char *Gamepad_BtnName(int btn); | ||
|
||
int isLastInputGamepad(void); | ||
void setLastInputGamepad(int input); | ||
int isGamepadInitted(void); | ||
|
||
extern int btnbindings[NUM_BTNS]; | ||
extern int btnsdown[NUM_BTNS]; | ||
|
||
#endif |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,194 @@ | ||
#include <SDL.h> | ||
#include "gamepad.h" | ||
#include "video.h" | ||
|
||
SDL_GameController *gamepad = NULL; | ||
static int gamepad_initted = 0; | ||
static int last_input_gamepad = 0; | ||
|
||
int btnbindings[NUM_BTNS] = { | ||
-1, // BTN_UNKNOWN | ||
SDL_CONTROLLER_BUTTON_DPAD_LEFT, // BTN_PULLUP | ||
SDL_CONTROLLER_BUTTON_DPAD_RIGHT, // BTN_PULLDOWN | ||
SDL_CONTROLLER_BUTTON_Y, // BTN_FLIP | ||
SDL_CONTROLLER_BUTTON_A, // BTN_BOMB | ||
SDL_CONTROLLER_BUTTON_X, // BTN_FIRE | ||
SDL_CONTROLLER_BUTTON_START, // BTN_HOME | ||
SDL_CONTROLLER_BUTTON_LEFTSTICK, // BTN_MISSILE | ||
SDL_CONTROLLER_BUTTON_RIGHTSTICK, // BTN_STARBURST | ||
SDL_CONTROLLER_BUTTON_RIGHTSHOULDER,// BTN_ACCEL | ||
SDL_CONTROLLER_BUTTON_LEFTSHOULDER, // BTN_DECEL | ||
SDL_CONTROLLER_BUTTON_BACK, // BTN_SOUND | ||
}; | ||
|
||
int btnsdown[NUM_BTNS]; | ||
|
||
const char *btnnames[] = { | ||
"A", // 0, SDL_CONTROLLER_BUTTON_A | ||
"B", // 1, SDL_CONTROLLER_BUTTON_B | ||
"X", // 2, SDL_CONTROLLER_BUTTON_X | ||
"Y", // 3, SDL_CONTROLLER_BUTTON_Y | ||
"Back", // 4, SDL_CONTROLLER_BUTTON_BACK | ||
"Guide Button", // 5, SDL_CONTROLLER_BUTTON_GUIDE | ||
"Start", // 6, SDL_CONTROLLER_BUTTON_START | ||
"Left Stick", // 7, SDL_CONTROLLER_BUTTON_LEFTSTICK | ||
"Right Stick", // 8, SDL_CONTROLLER_BUTTON_RIGHTSTICK | ||
"LB", // 9, SDL_CONTROLLER_BUTTON_LEFTSHOULDER | ||
"RB", // 10, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER | ||
"D-Pad Up", // 11, SDL_CONTROLLER_BUTTON_DPAD_UP | ||
"D-Pad Down", // 12, SDL_CONTROLLER_BUTTON_DPAD_DOWN | ||
"D-Pad Left", // 13, SDL_CONTROLLER_BUTTON_DPAD_LEFT | ||
"D-Pad Right", // 14, SDL_CONTROLLER_BUTTON_DPAD_RIGHT | ||
"Misc", // 15, SDL_CONTROLLER_BUTTON_MISC1 | ||
"Paddle 1", // 16, SDL_CONTROLLER_BUTTON_PADDLE1 | ||
"Paddle 2", // 17, SDL_CONTROLLER_BUTTON_PADDLE2 | ||
"Paddle 3", // 18, SDL_CONTROLLER_BUTTON_PADDLE3 | ||
"Paddle 4", // 19, SDL_CONTROLLER_BUTTON_PADDLE4 | ||
"Touchpad", // 20, SDL_CONTROLLER_BUTTON_TOUCHPAD | ||
}; | ||
|
||
void Gamepad_Init(void) | ||
{ | ||
if (SDL_Init(SDL_INIT_GAMECONTROLLER) < 0) { | ||
printf("Gamepad could not initialize! SDL_Error: %s\n", SDL_GetError()); | ||
} else { | ||
if (SDL_NumJoysticks() > 0) { | ||
gamepad = SDL_GameControllerOpen(0); | ||
} | ||
} | ||
|
||
gamepad_initted = 1; | ||
} | ||
|
||
void Gamepad_Shutdown(void) | ||
{ | ||
if (gamepad_initted) { | ||
// Close the gamepad | ||
if (gamepad != NULL) { | ||
SDL_GameControllerClose(gamepad); | ||
gamepad = NULL; | ||
} | ||
gamepad_initted = 0; | ||
} | ||
} | ||
|
||
static void getevents(void) | ||
{ | ||
SDL_Event event; | ||
|
||
while (SDL_PollEvent(&event)) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Doing this means that there are now two event loops: the one in the gamepad code and the one in the video code. This will mean that some events get discarded mistakenly. You need to use a single combined event loop. |
||
switch (event.type) { | ||
case SDL_CONTROLLERBUTTONDOWN: | ||
case SDL_CONTROLLERBUTTONUP: | ||
last_input_gamepad = 1; | ||
break; | ||
} | ||
} | ||
|
||
if(last_input_gamepad == 1) { | ||
for (int i = 1; i < NUM_BTNS; ++i) { | ||
if (btnbindings[i] != -1) { | ||
if (SDL_GameControllerGetButton(gamepad, btnbindings[i])) { | ||
btnsdown[i] |= 3; // Button is pressed | ||
} else { | ||
btnsdown[i] &= ~1; // Button is not pressed | ||
} | ||
} | ||
} | ||
} | ||
} | ||
|
||
int Gamepad_GetBtn(void) | ||
{ | ||
int btn = -1; | ||
SDL_Event event; | ||
|
||
while (btn == -1) { | ||
if (SDL_WaitEventTimeout(&event, 10)) { | ||
if (event.type == SDL_CONTROLLERBUTTONDOWN) { | ||
btn = event.cbutton.button; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just |
||
break; | ||
} else if (event.type == SDL_KEYDOWN) { | ||
if (event.key.keysym.sym == SDLK_ESCAPE) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You can combine the two |
||
return -1; | ||
} | ||
} | ||
} | ||
} | ||
return btn; | ||
} | ||
|
||
int Gamepad_GetGameBtns(void) | ||
{ | ||
int i, c = 0; | ||
|
||
getevents(); | ||
|
||
if (btnsdown[BTN_FLIP]) { | ||
btnsdown[BTN_FLIP] = 0; | ||
c |= K_FLIP; | ||
} | ||
if (btnsdown[BTN_PULLUP]) { | ||
c |= K_FLAPU; | ||
} | ||
if (btnsdown[BTN_PULLDOWN]) { | ||
c |= K_FLAPD; | ||
} | ||
if (btnsdown[BTN_ACCEL]) { | ||
c |= K_ACCEL; | ||
} | ||
if (btnsdown[BTN_DECEL]) { | ||
c |= K_DEACC; | ||
} | ||
if (btnsdown[BTN_SOUND]) { | ||
btnsdown[BTN_SOUND] = 0; | ||
c |= K_SOUND; | ||
} | ||
if (btnsdown[BTN_BOMB]) { | ||
c |= K_BOMB; | ||
} | ||
if (btnsdown[BTN_FIRE]) { | ||
c |= K_SHOT; | ||
} | ||
if (btnsdown[BTN_HOME]) { | ||
c |= K_HOME; | ||
} | ||
if (btnsdown[BTN_MISSILE]) { | ||
btnsdown[BTN_MISSILE] = 0; | ||
c |= K_MISSILE; | ||
} | ||
if (btnsdown[BTN_STARBURST]) { | ||
btnsdown[BTN_STARBURST] = 0; | ||
c |= K_STARBURST; | ||
} | ||
|
||
// clear bits in button array | ||
|
||
for (i=0; i<NUM_BTNS; ++i) { | ||
btnsdown[i] &= ~2; | ||
} | ||
|
||
return c; | ||
} | ||
|
||
const char *Gamepad_BtnName(int btn) | ||
{ | ||
if (btn < 0 || btn >= sizeof(btnnames) / sizeof(btnnames[0])) { | ||
return "Unknown"; | ||
} | ||
return btnnames[btn]; | ||
} | ||
|
||
int isLastInputGamepad(void) | ||
{ | ||
return last_input_gamepad; | ||
} | ||
|
||
void setLastInputGamepad(int input) | ||
{ | ||
last_input_gamepad = input; | ||
} | ||
|
||
int isGamepadInitted(void) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You can get rid of this function; just add a check to |
||
return gamepad_initted; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -23,13 +23,10 @@ | |
#include <sys/types.h> | ||
|
||
#include "video.h" | ||
#include "gamepad.h" | ||
#include "sw.h" | ||
#include "swinit.h" | ||
|
||
// lcd mode to emulate my old laptop i used to play sopwith on :) | ||
|
||
//#define LCD | ||
|
||
static SDL_Color cga_pal[] = {{}, {}, {}, {}}; | ||
|
||
typedef struct { | ||
|
@@ -536,12 +533,12 @@ void Vid_SetVideoPalette(int palette) | |
|
||
const char* Vid_GetVideoPaletteName(int palette) | ||
{ | ||
return VideoPalettes[palette].name; | ||
return VideoPalettes[palette].name; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is too much indentation. Side note, can you try to avoid including unrelated changes? |
||
} | ||
|
||
int Vid_GetNumVideoPalettes(void) | ||
{ | ||
int numPalettes = sizeof(VideoPalettes) / sizeof(VideoPalettes[0]); | ||
int numPalettes = sizeof(VideoPalettes) / sizeof(VideoPalettes[0]); | ||
return numPalettes; | ||
} | ||
|
||
|
@@ -609,8 +606,10 @@ static void getevents(void) | |
sopkey_t translated; | ||
|
||
while (SDL_PollEvent(&event)) { | ||
|
||
switch (event.type) { | ||
case SDL_KEYDOWN: | ||
setLastInputGamepad(false); | ||
if (event.key.keysym.sym == SDLK_LALT) { | ||
altdown = 1; | ||
} else if (event.key.keysym.sym == SDLK_LCTRL | ||
|
@@ -649,6 +648,7 @@ static void getevents(void) | |
break; | ||
|
||
case SDL_KEYUP: | ||
setLastInputGamepad(false); | ||
if (event.key.keysym.sym == SDLK_LALT) { | ||
altdown = 0; | ||
} else if (event.key.keysym.sym == SDLK_LCTRL | ||
|
@@ -689,6 +689,9 @@ static void getevents(void) | |
need_redraw = 1; | ||
break; | ||
} | ||
case SDL_CONTROLLERBUTTONDOWN: | ||
case SDL_CONTROLLERBUTTONUP: | ||
setLastInputGamepad(true); | ||
} | ||
} | ||
|
||
|
@@ -779,4 +782,4 @@ void error_exit(char *s, ...) | |
|
||
fprintf(stderr, "%s\n", buf); | ||
exit(1); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.