From 6a1e6a7d6b6a3d987f2fccb3c06f4f5da071f504 Mon Sep 17 00:00:00 2001 From: Nicholas Tay Date: Tue, 10 May 2022 00:40:10 +1000 Subject: Dynamic load boards as DLL (windows only for now) The .h files are pretty weird, should look at other C projects to see how they load plugins. This function pointer business with typedefs is kinda weird, not sure where they should live. --- .gitignore | 4 +++- Makefile | 2 +- board/Makefile | 32 +++++++++++++++++++++++++++++ board/board.c | 8 ++++++++ board/board.h | 12 +++++++++++ board/generate.sh | 8 -------- board/mxblue/board.c | 12 +++++++++++ board/mxblue/board.h | 3 --- board/quack/board.c | 12 +++++++++++ board/quack/board.h | 3 --- board/simple.h | 9 -------- boards.h | 6 ------ clak.c | 58 ++++++++++++++++------------------------------------ clak.h | 8 ++++++++ platform/platform.h | 5 +++++ platform/win32.c | 38 ++++++++++++++++++++++++++++++++++ 16 files changed, 149 insertions(+), 71 deletions(-) create mode 100644 board/Makefile create mode 100644 board/board.c create mode 100644 board/board.h delete mode 100644 board/generate.sh create mode 100644 board/mxblue/board.c delete mode 100644 board/mxblue/board.h create mode 100644 board/quack/board.c delete mode 100644 board/quack/board.h delete mode 100644 board/simple.h delete mode 100644 boards.h create mode 100644 clak.h diff --git a/.gitignore b/.gitignore index dbfb8f5..5768e2e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,6 @@ clak clak.exe board/boards.h -board/*/sound.h \ No newline at end of file +board/*/sound.h +board/*.dll +board/*.so \ No newline at end of file diff --git a/Makefile b/Makefile index bf2bd8f..cf64742 100644 --- a/Makefile +++ b/Makefile @@ -16,7 +16,7 @@ endif default: $(NAME) -$(NAME): $(NAME).c platform/$(PLATFORM).c boards.h +$(NAME): $(NAME).c platform/$(PLATFORM).c $(CC) $(CFLAGS) $(NAME).c platform/$(PLATFORM).c $(LDLIBS) -o $(NAME) clean: diff --git a/board/Makefile b/board/Makefile new file mode 100644 index 0000000..24cb10c --- /dev/null +++ b/board/Makefile @@ -0,0 +1,32 @@ +BOARDS = mxblue quack + +CC = gcc +CFLAGS += -std=c99 -Wall -Wextra -Wshadow -Werror -pedantic -shared + +ifeq ($(OS),Windows_NT) + OUTEXT = dll +else + OUTEXT = so +endif + +default: all +all: $(BOARDS) + +# TODO: use "BOARDS" variable to generate this. +# TODO: have some preset for 'simple' board type? also in the c file. +mxblue: mxblue.$(OUTEXT) +quack: quack.$(OUTEXT) +mxblue.$(OUTEXT): mxblue/board.c mxblue/sound.h + $(CC) $(CFLAGS) mxblue/board.c -o mxblue.$(OUTEXT) +quack.$(OUTEXT): quack/board.c quack/sound.h + $(CC) $(CFLAGS) quack/board.c -o quack.$(OUTEXT) +mxblue/sound.h: + xxd -i mxblue/board_down.wav mxblue/sound.h +quack/sound.h: + xxd -i quack/board_down.wav quack/sound.h + +clean: + rm -f *.o + rm -f *.dll + rm -f *.so + rm -f */sound.h \ No newline at end of file diff --git a/board/board.c b/board/board.c new file mode 100644 index 0000000..0410aef --- /dev/null +++ b/board/board.c @@ -0,0 +1,8 @@ +#include "board.h" + +static fn_sound_play sound_play; + +void board_init(fn_sound_play sp) +{ + sound_play = sp; +} \ No newline at end of file diff --git a/board/board.h b/board/board.h new file mode 100644 index 0000000..18f6afa --- /dev/null +++ b/board/board.h @@ -0,0 +1,12 @@ +#ifndef CLAK_BOARD_H_ +#define CLAK_BOARD_H_ + +#include + +#include "../clak.h" + +typedef void (*fn_board_init)(fn_sound_play sp); +typedef void (*fn_board_on_down)(void); +typedef void (*fn_board_on_up)(void); + +#endif /* CLAK_BOARD_H_ */ \ No newline at end of file diff --git a/board/generate.sh b/board/generate.sh deleted file mode 100644 index 6d8d593..0000000 --- a/board/generate.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/sh - -BOARDS='mxblue quack' - -cd "$(dirname "$0")" -for board in $BOARDS; do - xxd -i $board/board_down.wav $board/sound.h -done \ No newline at end of file diff --git a/board/mxblue/board.c b/board/mxblue/board.c new file mode 100644 index 0000000..14277db --- /dev/null +++ b/board/mxblue/board.c @@ -0,0 +1,12 @@ +#include "sound.h" + +#include "../board.c" + +void board_on_down(void) +{ + sound_play(mxblue_board_down_wav); +} + +void board_on_up(void) +{ +} \ No newline at end of file diff --git a/board/mxblue/board.h b/board/mxblue/board.h deleted file mode 100644 index 7d17f3f..0000000 --- a/board/mxblue/board.h +++ /dev/null @@ -1,3 +0,0 @@ -#include "./sound.h" -#include "../simple.h" -SIMPLE_BOARD(mxblue) \ No newline at end of file diff --git a/board/quack/board.c b/board/quack/board.c new file mode 100644 index 0000000..893e366 --- /dev/null +++ b/board/quack/board.c @@ -0,0 +1,12 @@ +#include "sound.h" + +#include "../board.c" + +void board_on_down(void) +{ + sound_play(quack_board_down_wav); +} + +void board_on_up(void) +{ +} \ No newline at end of file diff --git a/board/quack/board.h b/board/quack/board.h deleted file mode 100644 index 64ba4cb..0000000 --- a/board/quack/board.h +++ /dev/null @@ -1,3 +0,0 @@ -#include "./sound.h" -#include "../simple.h" -SIMPLE_BOARD(quack) \ No newline at end of file diff --git a/board/simple.h b/board/simple.h deleted file mode 100644 index c2b211b..0000000 --- a/board/simple.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef CLAK_SIMPLE_H_ -#define CLAK_SIMPLE_H_ - -extern void sound_play(unsigned char *buffer); -#define SIMPLE_BOARD(name) \ - void name ## _on_down(void) { sound_play( name ## _board_down_wav ); } \ - void name ## _on_up(void) { sound_play( name ## _board_down_wav ); } - -#endif /* CLAK_SIMPLE_H_ */ \ No newline at end of file diff --git a/boards.h b/boards.h deleted file mode 100644 index 9090570..0000000 --- a/boards.h +++ /dev/null @@ -1,6 +0,0 @@ -#include "board/mxblue/board.h" -#include "board/quack/board.h" - -#define BOARDS \ - BOARD(mxblue) \ - BOARD(quack) diff --git a/clak.c b/clak.c index 7a19f4a..145709f 100644 --- a/clak.c +++ b/clak.c @@ -1,37 +1,13 @@ #include #include #include -#include #include -#define VOLUME 0.15 - -#define BOARD(x) { .name = #x, .on_down = x ## _on_down, .on_up = x ## _on_up }, -#include "boards.h" - +#include "clak.h" #include "platform/platform.h" +#include "board/board.h" -typedef struct { - char *name; - void (*on_down)(void); - void (*on_up)(void); -} Board; - -Board boards[] = { - BOARDS -}; -int const boards_n = sizeof(boards) / sizeof(boards[0]); - -Board *board = NULL; - -Board *get_board(char *board_name) -{ - for (int i = 0; i < boards_n; ++i) { - if (strcmp(boards[i].name, board_name) == 0) - return &boards[i]; - } - return NULL; -} +#define VOLUME 0.15 void do_exit(int code) { @@ -41,30 +17,32 @@ void do_exit(int code) } void on_clean_exit(void) { do_exit(0); } +fn_board_on_down board_on_down; +fn_board_on_up board_on_up; + void keyboard_on_down(void) { - if (board == NULL) - return; - board->on_down(); + board_on_down(); } void keyboard_on_up(void) { - if (board == NULL) - return; - board->on_up(); + board_on_up(); } int main(int argc, char **argv) { - if (argc < 2 || (board = get_board(argv[1])) == NULL) { - printf("Please provide a valid board name.\n"); - printf("Valid boards: "); - for (int i = 0; i < boards_n; ++i) { - printf("%s%s", boards[i].name, (i == boards_n - 1) ? "\n" : ", "); - } + fprintf(stderr, "Clak: This is Clak, Nicholas Tay, version: 0.1.0.\n"); + + if (argc < 2) { + printf("ERROR: Please provide a board name.\n"); + // TODO: List valid boards. + return 1; + } + if (!load_board(argv[1], &board_on_down, &board_on_up)) { return 1; } + fprintf(stderr, "Loaded board: %s\n", argv[1]); if (!sound_init(VOLUME)) { printf("ERROR: Could not initialise sound system.\n"); @@ -75,7 +53,7 @@ int main(int argc, char **argv) return 1; } atexit(on_clean_exit); - fprintf(stderr, "Hooks set up, welcome to Clak!\n"); + fprintf(stderr, "Hooks set up, enjoy your stay!\n"); enter_idle(); diff --git a/clak.h b/clak.h new file mode 100644 index 0000000..c700a12 --- /dev/null +++ b/clak.h @@ -0,0 +1,8 @@ +#ifndef CLAK_H_ +#define CLAK_H_ + +#include + +typedef void (*fn_sound_play)(unsigned char *buffer); + +#endif /* CLAK_H_ */ \ No newline at end of file diff --git a/platform/platform.h b/platform/platform.h index da1efa6..fd9b9bb 100644 --- a/platform/platform.h +++ b/platform/platform.h @@ -1,6 +1,11 @@ #ifndef CLAK_PLATFORM_H_ #define CLAK_PLATFORM_H_ +#include + +#include "../board/board.h" + +bool load_board(char *board_name, fn_board_on_down *on_down, fn_board_on_down *on_up); bool sound_init(float volume); void sound_play(unsigned char *buffer); void keyboard_unhook(void); diff --git a/platform/win32.c b/platform/win32.c index 90cd37c..cf22718 100644 --- a/platform/win32.c +++ b/platform/win32.c @@ -2,6 +2,9 @@ #include #include +#include "platform.h" +#include "../board/board.h" + /* Required callbacks */ extern void keyboard_on_down(void); extern void keyboard_on_up(void); @@ -77,4 +80,39 @@ void enter_idle(void) exit(1); } } +} + +bool load_board(char *board_name, fn_board_on_down *on_down, fn_board_on_down *on_up) +{ + char dll_name[100]; + int r = snprintf(dll_name, 100, "./board/%s.dll", board_name); + if (r < 0 || r >= 100) { + printf("ERROR: Invalid board name.\n"); + return false; + } + + HMODULE board_module = LoadLibrary(dll_name); + if (board_module == NULL) { + printf("ERROR: Could not load board module.\n"); + return false; + } + fn_board_init board_init = (fn_board_init) (void (*)(void)) GetProcAddress(board_module, "board_init"); + if (board_init == NULL) { + printf("ERROR: No board down function could be loaded.\n"); + return false; + } + board_init(&sound_play); + + *on_down = (fn_board_on_down) GetProcAddress(board_module, "board_on_down"); + if (on_down == NULL) { + printf("ERROR: No board down function could be loaded.\n"); + return false; + } + *on_up = (fn_board_on_up) GetProcAddress(board_module, "board_on_up"); + if (on_up == NULL) { + printf("ERROR: No board up function could be loaded.\n"); + return false; + } + + return true; } \ No newline at end of file -- cgit