From e3a2bca7941cebd366e8093337df0c6ad4020455 Mon Sep 17 00:00:00 2001 From: Michael Smith Date: Wed, 11 Feb 2026 16:08:13 +0100 Subject: [PATCH] Add --debug flag for diagnosing controller input on handheld Logs joystick enumeration at startup (name, GameController status, GUID) and all SDL input events in the main loop to help diagnose why the retro handheld's d-pad/buttons aren't recognized by the GameController API. Co-Authored-By: Claude Opus 4.6 --- docs/sdlamp2-fsd.md | 13 +++++- src/sdlamp2.c | 97 ++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 104 insertions(+), 6 deletions(-) diff --git a/docs/sdlamp2-fsd.md b/docs/sdlamp2-fsd.md index e8ade3b..eeeca97 100644 --- a/docs/sdlamp2-fsd.md +++ b/docs/sdlamp2-fsd.md @@ -36,7 +36,18 @@ This document specifies the functional requirements for an SDL2 based media play - Keep it simple, apply Casey Muratori's `semantic compression` principles, don't refactor too soon or write code that's too clever for its own good - Keep a changelog in this functional specification document -## 5. Changelog +## 5. Target Platforms + +- **Deployment**: Linux ARM64 (aarch64) on a retro handheld gaming device +- **Development/testing**: macOS Apple Silicon + +## 6. Changelog + +### 2026-02-11 — Debug flag for input diagnostics + +- **`--debug` flag**: New command-line option (`./sdlamp2 --debug [audio_dir]`) that enables verbose logging of all SDL input events to stdout. Designed to diagnose controller issues on retro handheld devices where non-standard controllers may not be recognized by SDL's GameController API. +- **Startup enumeration**: When debug is on, logs the number of detected joysticks, each joystick's name, whether SDL recognizes it as a GameController, and its GUID. +- **Event logging**: Logs `KEYDOWN/UP`, `CONTROLLERBUTTONDOWN/UP`, `JOYBUTTONDOWN/UP`, `JOYHATMOTION`, `JOYAXISMOTION` (with deadzone filter), and device add/remove events with identifying details. ### 2026-02-11 — Lossless M4A concatenation tool diff --git a/src/sdlamp2.c b/src/sdlamp2.c index 0ed2309..43d7806 100644 --- a/src/sdlamp2.c +++ b/src/sdlamp2.c @@ -65,6 +65,7 @@ static int current_file_index = 0; static float volume = 0.5f; static int focus_index = FOCUS_PLAY; static SDL_GameController* controller = NULL; +static int debug_mode = 0; /* --- Utility --- */ @@ -533,8 +534,18 @@ static void activate_focused_button(void) { /* --- Main --- */ int main(int argc, char** argv) { - if (argc > 1) { - strncpy(audio_dir, argv[1], sizeof(audio_dir) - 1); + /* Parse arguments: [--debug] [audio_directory] */ + int argi = 1; + while (argi < argc && argv[argi][0] == '-') { + if (strcmp(argv[argi], "--debug") == 0) { + debug_mode = 1; + } else { + fprintf(stderr, "Unknown option: %s\n", argv[argi]); + } + argi++; + } + if (argi < argc) { + strncpy(audio_dir, argv[argi], sizeof(audio_dir) - 1); audio_dir[sizeof(audio_dir) - 1] = '\0'; } @@ -590,8 +601,21 @@ int main(int argc, char** argv) { panic_and_abort("Could not open audio device!", SDL_GetError()); } - /* Open first available game controller */ - for (int i = 0; i < SDL_NumJoysticks(); i++) { + /* Enumerate and open game controllers */ + int num_joy = SDL_NumJoysticks(); + if (debug_mode) { + printf("[debug] Joysticks detected: %d\n", num_joy); + for (int i = 0; i < num_joy; i++) { + SDL_JoystickGUID guid = SDL_JoystickGetDeviceGUID(i); + char guid_str[64]; + SDL_JoystickGetGUIDString(guid, guid_str, sizeof(guid_str)); + printf("[debug] #%d: \"%s\" | GameController=%s | GUID=%s\n", i, + SDL_JoystickNameForIndex(i), SDL_IsGameController(i) ? "yes" : "no", guid_str); + } + fflush(stdout); + } + + for (int i = 0; i < num_joy; i++) { if (SDL_IsGameController(i)) { controller = SDL_GameControllerOpen(i); if (controller) { @@ -627,6 +651,64 @@ int main(int argc, char** argv) { while (running) { /* --- Event handling --- */ while (SDL_PollEvent(&e)) { + /* Debug: log all input-related events */ + if (debug_mode) { + switch (e.type) { + case SDL_KEYDOWN: + printf("[debug] KEYDOWN: sym=%s (0x%x) scancode=%d\n", + SDL_GetKeyName(e.key.keysym.sym), e.key.keysym.sym, e.key.keysym.scancode); + break; + case SDL_KEYUP: + printf("[debug] KEYUP: sym=%s (0x%x) scancode=%d\n", + SDL_GetKeyName(e.key.keysym.sym), e.key.keysym.sym, e.key.keysym.scancode); + break; + case SDL_CONTROLLERBUTTONDOWN: + printf("[debug] CONTROLLERBUTTONDOWN: button=%d (%s)\n", e.cbutton.button, + SDL_GameControllerGetStringForButton(e.cbutton.button)); + break; + case SDL_CONTROLLERBUTTONUP: + printf("[debug] CONTROLLERBUTTONUP: button=%d (%s)\n", e.cbutton.button, + SDL_GameControllerGetStringForButton(e.cbutton.button)); + break; + case SDL_JOYBUTTONDOWN: + printf("[debug] JOYBUTTONDOWN: joy=%d button=%d\n", e.jbutton.which, + e.jbutton.button); + break; + case SDL_JOYBUTTONUP: + printf("[debug] JOYBUTTONUP: joy=%d button=%d\n", e.jbutton.which, e.jbutton.button); + break; + case SDL_JOYHATMOTION: + printf("[debug] JOYHATMOTION: joy=%d hat=%d value=%d\n", e.jhat.which, e.jhat.hat, + e.jhat.value); + break; + case SDL_JOYAXISMOTION: + if (e.jaxis.value > 8000 || e.jaxis.value < -8000) { + printf("[debug] JOYAXISMOTION: joy=%d axis=%d value=%d\n", e.jaxis.which, + e.jaxis.axis, e.jaxis.value); + } + break; + case SDL_CONTROLLERDEVICEADDED: { + SDL_JoystickGUID guid = SDL_JoystickGetDeviceGUID(e.cdevice.which); + char guid_str[64]; + SDL_JoystickGetGUIDString(guid, guid_str, sizeof(guid_str)); + printf("[debug] CONTROLLERDEVICEADDED: index=%d name=\"%s\" GUID=%s\n", e.cdevice.which, + SDL_JoystickNameForIndex(e.cdevice.which), guid_str); + break; + } + case SDL_CONTROLLERDEVICEREMOVED: + printf("[debug] CONTROLLERDEVICEREMOVED: id=%d\n", e.cdevice.which); + break; + case SDL_JOYDEVICEADDED: + printf("[debug] JOYDEVICEADDED: index=%d name=\"%s\"\n", e.jdevice.which, + SDL_JoystickNameForIndex(e.jdevice.which)); + break; + case SDL_JOYDEVICEREMOVED: + printf("[debug] JOYDEVICEREMOVED: id=%d\n", e.jdevice.which); + break; + } + fflush(stdout); + } + switch (e.type) { case SDL_QUIT: running = SDL_FALSE; @@ -677,7 +759,12 @@ int main(int argc, char** argv) { if (!controller && SDL_IsGameController(e.cdevice.which)) { controller = SDL_GameControllerOpen(e.cdevice.which); if (controller) { - printf("Controller added: %s\n", SDL_GameControllerName(controller)); + SDL_Joystick* joy = SDL_GameControllerGetJoystick(controller); + SDL_JoystickGUID guid = SDL_JoystickGetGUID(joy); + char guid_str[64]; + SDL_JoystickGetGUIDString(guid, guid_str, sizeof(guid_str)); + printf("Controller added: %s (GUID: %s)\n", SDL_GameControllerName(controller), + guid_str); } } break;