Skip to content
17 changes: 17 additions & 0 deletions .vscode/c_cpp_properties.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"configurations": [
{
"name": "Linux",
"includePath": [
"${workspaceFolder}/**",
"/usr/include/SDL2"
],
"defines": [],
"compilerPath": "/usr/bin/gcc",
"cStandard": "c17",
"cppStandard": "gnu++17",
"intelliSenseMode": "linux-gcc-x64"
}
],
"version": 4
}
5 changes: 3 additions & 2 deletions src/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,19 @@ bin_PROGRAMS = sopwith

COMMON_SOURCES = \
font.h \
gamepad.h \
pcsound.h \
std.h \
swasynio.c swasynio.h \
swauto.c swauto.h \
swcollsn.c swcollsn.h \
swconf.c swconf.h \
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please move swconf.c and swinit.c back to their previous location, they don't belong in the sdl/ subdirectory.

I understand why you had to do this: the new feature requires using new SDL functions. But the correct way to do this is to create accessor functions to access them. For example, we have Vid_GetKey() that is used by the configuration code to read a keypress. You need a similar function that your change_btn_binding function can call to read a gamepad press.

In case it's not clear: the code in src/ is the "core code" of the game. The idea is that if someone wants to port the game to a new system where SDL isn't available, they should just be able to reimplement the files in src/sdl/ . Think of it as though there were multiple other directories alongside src/sdl/ - we wouldn't want to contain duplicate implementations of the initialization and configuration code for every one of them.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My bad - I should've asked in Discord for some more context. This is all moved back and straightened out.

swconf.h \
swdisp.c swdisp.h \
swend.c swend.h \
swgames.c swgames.h \
swgrpha.c swgrpha.h \
sw.h \
swinit.c swinit.h \
swinit.h \
swmain.c swmain.h \
swmove.c swmove.h \
swobject.c swobject.h \
Expand Down
14 changes: 14 additions & 0 deletions src/gamepad.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
//
// Gamepad Interface
//

#ifndef __GAMEPAD_H__
#define __GAMEPAD_H__

void Gamepad_Init(void);
void Gamepad_Update(void);
void Gamepad_CheckState(void);

extern int btnbindings[NUM_KEYS];
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NUM_KEYS is the number of keyboard bindings. You'll want to define a new one, eg. NUM_GAMEPAD_BUTTONS

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done


#endif
2 changes: 1 addition & 1 deletion src/sdl/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@ AM_CFLAGS=@CFLAGS@ @SDL_CFLAGS@ -I$(srcdir)/..

noinst_LIBRARIES = libsdlsopwith.a libsdlsopmain.a

libsdlsopwith_a_SOURCES = video.c pcsound.c timer.c
libsdlsopwith_a_SOURCES = video.c pcsound.c timer.c gamepad.c swconf.c swinit.c
libsdlsopmain_a_SOURCES = main.c

64 changes: 64 additions & 0 deletions src/sdl/gamepad.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
#include <SDL.h>
#include "video.h"

SDL_GameController *gamepad = NULL;
static int gamepad_initted = 0;

int btnbindings[NUM_KEYS] = {
-1, // KEY_UNKNOWN
SDL_CONTROLLER_BUTTON_DPAD_LEFT, // KEY_PULLUP
SDL_CONTROLLER_BUTTON_DPAD_RIGHT, // KEY_PULLDOWN
SDL_CONTROLLER_BUTTON_Y, // KEY_FLIP
SDL_CONTROLLER_BUTTON_A, // KEY_BOMB
SDL_CONTROLLER_BUTTON_X, // KEY_FIRE
SDL_CONTROLLER_BUTTON_START, // KEY_HOME
SDL_CONTROLLER_BUTTON_LEFTSTICK, // KEY_MISSILE
SDL_CONTROLLER_BUTTON_RIGHTSTICK, // KEY_STARBURST
SDL_CONTROLLER_BUTTON_RIGHTSHOULDER,// KEY_ACCEL
SDL_CONTROLLER_BUTTON_LEFTSHOULDER, // KEY_DECEL
SDL_CONTROLLER_BUTTON_BACK, // KEY_SOUND
};

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_Update(void) {
if (!gamepad_initted || gamepad == NULL) {
Gamepad_Init();
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't need to try to initialize again every time the function is called. Let's just return here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

return;
}

for (int i = 1; i < NUM_KEYS; ++i) {
if (btnbindings[i] != -1) {
if (SDL_GameControllerGetButton(gamepad, btnbindings[i])) {
keysdown[i] |= 3; // Button is pressed
} else {
keysdown[i] &= ~1; // Button is not pressed
}
}
}
}

void Gamepad_Shutdown(void)
{
if (!gamepad_initted) {
return;
}
// Close the gamepad
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you try to be more consistent with your formatting? Not just talking about this one function but throughout the PR. You can see here that it's kind of a mess because you mixed up spaces and tabs.

The coding style for the project is to use tabs for indentation. If you configure your editor to not expand tabs to spaces then you'll probably get the right thing.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oof, sorry about that, I've fixed my settings there

if (gamepad != NULL) {
SDL_GameControllerClose(gamepad);
gamepad = NULL;
}

gamepad_initted = 0;
}
92 changes: 92 additions & 0 deletions src/swconf.c → src/sdl/swconf.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,12 @@
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <SDL.h>

#include "timer.h"
#include "pcsound.h"
#include "video.h"
#include "gamepad.h"

#include "swconf.h"
#include "swend.h"
Expand Down Expand Up @@ -82,6 +84,17 @@ static confoption_t confoptions[] = {
{"key_home", CONF_KEY, {&keybindings[KEY_HOME]}},
{"key_missile", CONF_KEY, {&keybindings[KEY_MISSILE]}},
{"key_starburst", CONF_KEY, {&keybindings[KEY_STARBURST]}},

{"btn_accelerate", CONF_BTN, {&btnbindings[KEY_ACCEL]}},
{"btn_decelerate", CONF_BTN, {&btnbindings[KEY_DECEL]}},
{"btn_pullup", CONF_BTN, {&btnbindings[KEY_PULLUP]}},
{"btn_pulldown", CONF_BTN, {&btnbindings[KEY_PULLDOWN]}},
{"btn_flip", CONF_BTN, {&btnbindings[KEY_FLIP]}},
{"btn_fire", CONF_BTN, {&btnbindings[KEY_FIRE]}},
{"btn_dropbomb", CONF_BTN, {&btnbindings[KEY_BOMB]}},
{"btn_home", CONF_BTN, {&btnbindings[KEY_HOME]}},
{"btn_missile", CONF_BTN, {&btnbindings[KEY_MISSILE]}},
{"btn_starburst", CONF_BTN, {&btnbindings[KEY_STARBURST]}},
};

static int num_confoptions = sizeof(confoptions) / sizeof(*confoptions);
Expand Down Expand Up @@ -111,6 +124,7 @@ static void parse_config_line(char *config_file, int lineno, char *line)
{
char *name, *value, *p;
int key;
int btn;
confoption_t *opt;

p = line;
Expand Down Expand Up @@ -169,6 +183,11 @@ static void parse_config_line(char *config_file, int lineno, char *line)
*opt->value.i = key;
}
break;
case CONF_BTN:
if (sscanf(value, "%d", &btn) == 1) {
*opt->value.i = btn;
}
break;
default:
break;
}
Expand Down Expand Up @@ -246,6 +265,7 @@ void swsaveconf(void)
break;
case CONF_INT:
case CONF_KEY:
case CONF_BTN:
fprintf(fs, "%d", *confoptions[i].value.i);
break;
default:
Expand Down Expand Up @@ -308,6 +328,53 @@ static void change_key_binding(struct menuitem *item)
*opt->value.i = key;
}

static void change_btn_binding(struct menuitem *item)
{
confoption_t *opt;
int btn = -1;
SDL_Event event;

Vid_ClearBuf();

swcolor(3);
swposcur(10, 5);
swputs("Press the new button for: ");

swcolor(2);
swposcur(14, 7);
swputs(item->description);

swcolor(1);
swposcur(1, 22);
swputs(" ESC - Cancel");

Vid_Update();

while (btn == -1) {
// Have to use SDL_WaitEventTimeout() instead Timer_Sleep(50) so that buttons register
if (SDL_WaitEventTimeout(&event, 10)) {
if (event.type == SDL_CONTROLLERBUTTONDOWN) {
btn = event.cbutton.button;
break;
} else if (event.type == SDL_KEYDOWN) {
if (event.key.keysym.sym == SDLK_ESCAPE) {
return;
}
}
}
swsndupdate();
if (ctlbreak()) {
return;
}
}

opt = confoption_by_name(item->config_name);
if (opt == NULL) {
return;
}
*opt->value.i = btn;
}

static void drawmenu(char *title, struct menuitem *menu)
{
int i, y, keynum, said_key = 0;
Expand Down Expand Up @@ -372,6 +439,12 @@ static void drawmenu(char *title, struct menuitem *menu)
case CONF_KEY:
swputs(Vid_KeyName(*opt->value.i));
break;
case CONF_BTN: {
char btnString[20]; // Large enough to hold any integer
sprintf(btnString, "%d", *opt->value.i); // Convert integer to string
swputs(btnString);
break;
}
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please remove the {} braces here; they are misleading.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

default:
break;
}
Expand Down Expand Up @@ -455,6 +528,9 @@ static int runmenu(char *title, struct menuitem *menu)
case CONF_KEY:
change_key_binding(pressed);
break;
case CONF_BTN:
change_btn_binding(pressed);
break;
default:
break;
}
Expand All @@ -480,6 +556,18 @@ static struct menuitem keys_menu[] = {
{NULL},
};

static struct menuitem btns_menu[] = {
{"btn_accelerate", "Accelerate"},
{"btn_decelerate", "Decelerate"},
{"btn_pullup", "Pull up"},
{"btn_pulldown", "Pull down"},
{"btn_flip", "Flip"},
{"btn_fire", "Fire machine gun"},
{"btn_dropbomb", "Drop bomb"},
{"btn_home", "Navigate home"},
{NULL},
};

static struct menuitem options_menu[] = {
{"vid_fullscreen", "Run fullscreen"},
{"conf_video_palette", "Video palette"},
Expand All @@ -492,6 +580,7 @@ static struct menuitem options_menu[] = {
{"conf_harrykeys", "Harry keys mode"},
{"", ""},
{">K", "Key bindings"},
{">G", "Gamepad bindings"},
{NULL},
};

Expand All @@ -504,6 +593,9 @@ void setconfig(void)
case 'K':
runmenu("OPTIONS > KEY BINDINGS", keys_menu);
break;
case 'G':
runmenu("OPTIONS > GAMEPAD BINDINGS", btns_menu);
break;
}
}
}
2 changes: 2 additions & 0 deletions src/swinit.c → src/sdl/swinit.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include "pcsound.h"
#include "timer.h"
#include "video.h"
#include "gamepad.h"

#include "sw.h"
#include "swasynio.h"
Expand Down Expand Up @@ -1093,6 +1094,7 @@ void swinit(int argc, char *argv[])

Timer_Init();
Vid_Init();
Gamepad_Init();
Vid_SetVideoPalette(conf_video_palette);

// dont init speaker if started with -q (quiet)
Expand Down
21 changes: 16 additions & 5 deletions src/sdl/video.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,7 @@
#include "video.h"
#include "sw.h"
#include "swinit.h"

// lcd mode to emulate my old laptop i used to play sopwith on :)

//#define LCD
#include "gamepad.h"

static SDL_Color cga_pal[] = {{}, {}, {}, {}};

Expand Down Expand Up @@ -92,6 +89,7 @@ int keybindings[NUM_KEYS] = {

static int ctrlbreak = 0;
static bool initted = 0;
static bool last_input_gamepad = 0;
static SDL_Window *window = NULL;
static uint32_t pixel_format;
static SDL_Renderer *renderer;
Expand Down Expand Up @@ -609,8 +607,11 @@ static void getevents(void)
sopkey_t translated;

while (SDL_PollEvent(&event)) {

switch (event.type) {
case SDL_KEYDOWN:
last_input_gamepad = 0;

if (event.key.keysym.sym == SDLK_LALT) {
altdown = 1;
} else if (event.key.keysym.sym == SDLK_LCTRL
Expand Down Expand Up @@ -649,6 +650,7 @@ static void getevents(void)
break;

case SDL_KEYUP:
last_input_gamepad = 0;
if (event.key.keysym.sym == SDLK_LALT) {
altdown = 0;
} else if (event.key.keysym.sym == SDLK_LCTRL
Expand Down Expand Up @@ -676,6 +678,11 @@ static void getevents(void)
}
break;

case SDL_CONTROLLERBUTTONDOWN:
case SDL_CONTROLLERBUTTONUP:
last_input_gamepad = 1;
break;

case SDL_WINDOWEVENT:
switch (event.window.event) {
case SDL_WINDOWEVENT_CLOSE:
Expand All @@ -692,6 +699,10 @@ static void getevents(void)
}
}

if(last_input_gamepad == 1) {
Gamepad_Update();
}

if (need_redraw) {
Vid_Update();
}
Expand Down Expand Up @@ -779,4 +790,4 @@ void error_exit(char *s, ...)

fprintf(stderr, "%s\n", buf);
exit(1);
}
}
Loading