diff --git a/CLAUDE.md b/CLAUDE.md index c5f25e8..b7165ad 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -10,17 +10,23 @@ See `docs/sdlamp2-fsd.md` for the full functional specification and changelog. ## Build and Run -**Dependencies:** SDL2, SDL2_image, FFmpeg libraries (libavformat, libavcodec, libavutil, libswresample). Installed via system package manager; resolved at build time with `sdl2-config` and `pkgconf`. +**Dependencies:** SDL2, SDL2_image, FFmpeg libraries (libavformat, libavcodec, libavutil, libswresample). Installed via system package manager (native) or into the Buildroot sysroot (cross-compile). ```sh -./build.sh # macOS — builds to build/sdlamp2 -./build_aarch64.sh # Linux aarch64 variant +make # native build — uses pkg-config +make clean # remove build artifacts ./build/sdlamp2 [audio_directory] ``` +Cross-compilation inside the Docker toolchain container (where `CROSS_COMPILE` and `PREFIX` are set by the environment): + +```sh +make # picks up CROSS_COMPILE and PREFIX automatically +``` + The controls spritesheet (`controls.png`) is embedded in the binary. If an external `controls.png` exists in the current working directory it takes precedence, allowing custom skins. Audio directory defaults to cwd if not specified. -No test suite, no linter, no Makefile/CMake. +No test suite, no linter. ## Architecture diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..cd269a1 --- /dev/null +++ b/Makefile @@ -0,0 +1,32 @@ +CC = $(CROSS_COMPILE)gcc + +CFLAGS = -Wall -Wno-unused -O2 +LDLIBS = -lSDL2 -lSDL2_image -lavformat -lavcodec -lavutil -lswresample + +ifdef PREFIX + # Cross-compile: headers and libraries live under PREFIX + CFLAGS += -I$(PREFIX)/include -I$(PREFIX)/include/SDL2 + LDLIBS := -L$(PREFIX)/lib $(LDLIBS) +else + # Native: use pkg-config + PKG_CONFIG ?= pkg-config + PKGS = sdl2 SDL2_image libavformat libavcodec libavutil libswresample + CFLAGS += $(shell $(PKG_CONFIG) --cflags $(PKGS)) + LDLIBS = $(shell $(PKG_CONFIG) --libs $(PKGS)) +endif + +BUILD_DIR = build +TARGET = $(BUILD_DIR)/sdlamp2 + +.PHONY: all clean + +all: $(TARGET) + +$(TARGET): src/sdlamp2.c src/controls_png.h | $(BUILD_DIR) + $(CC) $(CFLAGS) -o $@ $< $(LDLIBS) + +$(BUILD_DIR): + mkdir -p $@ + +clean: + rm -f $(TARGET) diff --git a/build.sh b/build.sh deleted file mode 100755 index 487f4d2..0000000 --- a/build.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/sh - -pushd build 2>&1 >/dev/null - -gcc -Wall -Wno-unused -O0 -ggdb3 \ - -o sdlamp2 \ - `sdl2-config --cflags --libs` \ - `pkgconf --cflags --libs libavformat` \ - `pkgconf --cflags --libs libavcodec` \ - `pkgconf --cflags --libs libavutil` \ - `pkgconf --cflags --libs libswresample` \ - -lSDL2_image \ - ../src/sdlamp2.c - -popd 2>&1 >/dev/null diff --git a/build_aarch64.sh b/build_aarch64.sh deleted file mode 100755 index 9c276be..0000000 --- a/build_aarch64.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/bash - -pushd build 2>&1 >/dev/null - -gcc -Wall -Wno-unused \ - -o sdlamp2 \ - `sdl2-config --cflags --libs` \ - -I/usr/include/aarch64-linux-gnu -L/usr/lib/aarch64-linux-gnu -lavformat \ - -I/usr/include/aarch64-linux-gnu -L/usr/lib/aarch64-linux-gnu -lavcodec \ - -I/usr/include/aarch64-linux-gnu -L/usr/lib/aarch64-linux-gnu -lavutil \ - -I/usr/include/aarch64-linux-gnu -L/usr/lib/aarch64-linux-gnu -lswresample \ - -lSDL2_image \ - ../src/sdlamp2.c - -popd 2>&1 >/dev/null diff --git a/docs/sdlamp2-fsd.md b/docs/sdlamp2-fsd.md index a02c677..e3e82b0 100644 --- a/docs/sdlamp2-fsd.md +++ b/docs/sdlamp2-fsd.md @@ -30,7 +30,7 @@ This document specifies the functional requirements for an SDL2 based media play ## 4. Design principles - Version control (git) must be used -- Compilation should be performed by a simple shell script or batch file, not a complicated build system like make or cmake +- Compilation should be performed by a simple Makefile supporting both native and cross-compilation - C source code files should be formatted using "Google" style with an additional change of `ColumnLimit` set to 100 - Less is more, minimize dependencies, avoid pulling in extra libraries, always talk through with owner first - 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 @@ -43,6 +43,10 @@ This document specifies the functional requirements for an SDL2 based media play ## 6. Changelog +### 2026-02-13 — Replace build scripts with Makefile + +- **Makefile**: Replaced `build.sh` (macOS) and `build_aarch64.sh` (Linux ARM) with a single `Makefile`. Native builds use `pkg-config` to resolve SDL2 and FFmpeg flags; cross-compilation uses `CROSS_COMPILE` and `PREFIX` environment variables set by the Docker/Buildroot toolchain. + ### 2026-02-13 — Raw joystick fallback for non-standard controllers - **Joystick fallback**: When no SDL GameController mapping exists for a connected device, the joystick is now opened directly via `SDL_JoystickOpen()` as a fallback. This fixes d-pad and face button input on devices like the Anbernic retro handheld whose GUID is not in SDL's GameController database. diff --git a/src/sdlamp2.c b/src/sdlamp2.c index ec8f95c..7eae181 100644 --- a/src/sdlamp2.c +++ b/src/sdlamp2.c @@ -49,7 +49,7 @@ static SDL_bool paused = SDL_TRUE; static Decoder decoder = {0}; static char audio_dir[512] = "."; -static char current_file[512] = ""; +static char current_file[256] = ""; static char audio_files[MAX_FILES][256]; static int num_audio_files = 0; static int current_file_index = 0; @@ -111,8 +111,7 @@ static void save_position(const char* filename, double seconds) { snprintf(lines[num_lines], sizeof(lines[0]), "%s\t%.2f", filename, seconds); found = SDL_TRUE; } else { - strncpy(lines[num_lines], line, sizeof(lines[0]) - 1); - lines[num_lines][sizeof(lines[0]) - 1] = '\0'; + snprintf(lines[num_lines], sizeof(lines[0]), "%s", line); } num_lines++; } @@ -210,8 +209,7 @@ static void scan_audio_files(const char* dir) { while ((entry = readdir(d)) != NULL && num_audio_files < MAX_FILES) { if (entry->d_name[0] == '.') continue; if (has_audio_extension(entry->d_name)) { - strncpy(audio_files[num_audio_files], entry->d_name, 255); - audio_files[num_audio_files][255] = '\0'; + snprintf(audio_files[num_audio_files], sizeof(audio_files[0]), "%s", entry->d_name); num_audio_files++; } }