aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicholas Tay <nick@windblume.net>2022-05-10 00:40:10 +1000
committerNicholas Tay <nick@windblume.net>2022-05-10 00:47:38 +1000
commit6a1e6a7d6b6a3d987f2fccb3c06f4f5da071f504 (patch)
tree3899a31897c01323fb5d896b08412aa45e939885
parent5270088f730a7e30155a642dcd5c4e9a80055d7a (diff)
downloadclak-6a1e6a7d6b6a3d987f2fccb3c06f4f5da071f504.tar.gz
clak-6a1e6a7d6b6a3d987f2fccb3c06f4f5da071f504.tar.bz2
clak-6a1e6a7d6b6a3d987f2fccb3c06f4f5da071f504.zip
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.
-rw-r--r--.gitignore4
-rw-r--r--Makefile2
-rw-r--r--board/Makefile32
-rw-r--r--board/board.c8
-rw-r--r--board/board.h12
-rw-r--r--board/generate.sh8
-rw-r--r--board/mxblue/board.c12
-rw-r--r--board/mxblue/board.h3
-rw-r--r--board/quack/board.c12
-rw-r--r--board/quack/board.h3
-rw-r--r--board/simple.h9
-rw-r--r--boards.h6
-rw-r--r--clak.c58
-rw-r--r--clak.h8
-rw-r--r--platform/platform.h5
-rw-r--r--platform/win32.c38
16 files changed, 149 insertions, 71 deletions
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 <stdbool.h>
+
+#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 <stdio.h>
#include <unistd.h>
#include <string.h>
-#include <stdbool.h>
#include <stdlib.h>
-#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 <stdbool.h>
+
+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 <stdbool.h>
+
+#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 <stdbool.h>
#include <windows.h>
+#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