From 9a4c57d4c2c837e37fcd71d0933e8f86e098affa Mon Sep 17 00:00:00 2001 From: Phireh Date: Mon, 16 Dec 2024 20:16:27 +0100 Subject: [PATCH] Add game layer linking --- .gitignore | 1 + Makefile | 2 + arena.h | 4 ++ debug.h | 1 + game.c | 7 ++ game.h | 16 +++++ input.h | 2 + wayland.c | 185 ++++++++++++++++++++++++++++++++--------------------- 8 files changed, 145 insertions(+), 73 deletions(-) create mode 100644 game.c create mode 100644 game.h diff --git a/.gitignore b/.gitignore index 55c8309..25063ef 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ wayland +game.so xdg-shell-client-protocol.h xdg-shell-protocol.c zwp-text-input-unstable-v3-client-protocol.c diff --git a/Makefile b/Makefile index b2a0f07..220194e 100644 --- a/Makefile +++ b/Makefile @@ -17,3 +17,5 @@ xdg-decoration-unstable-v1.c: wayland-scanner private-code $(INTERFACEDIR)/unstable/xdg-decoration/xdg-decoration-unstable-v1.xml xdg-decoration-unstable-v1.c xdg-decoration-unstable-v1.h: wayland-scanner client-header $(INTERFACEDIR)/unstable/xdg-decoration/xdg-decoration-unstable-v1.xml xdg-decoration-unstable-v1.h +game.so: game.c game.h + gcc $(CFLAGS) game.c --shared -o game.so diff --git a/arena.h b/arena.h index f9fd13e..fd3ac11 100644 --- a/arena.h +++ b/arena.h @@ -1,6 +1,10 @@ #ifndef ARENA_H #define ARENA_H +#include +#include +#include + typedef enum { ARENA_ZERO = 1 << 0, ARENA_SOFTFAIL = 1 << 1, diff --git a/debug.h b/debug.h index 9aac243..1f94910 100644 --- a/debug.h +++ b/debug.h @@ -8,6 +8,7 @@ typedef enum { MODULE_MOUSE = 1 << 2, MODULE_WAYLAND = 1 << 3, MODULE_CONTROLLER = 1 << 4, + MODULE_HOTRELOAD = 1 << 5, MODULE_ALL = ~0 } console_verbosity_t; diff --git a/game.c b/game.c new file mode 100644 index 0000000..e5b1da3 --- /dev/null +++ b/game.c @@ -0,0 +1,7 @@ +#include "game.h" + +void simulate_frame(game_state_t *state) +{ + // TODO: Do something amazing here + ; +} diff --git a/game.h b/game.h new file mode 100644 index 0000000..25bba70 --- /dev/null +++ b/game.h @@ -0,0 +1,16 @@ +#ifndef GAME_H +#define GAME_H + +#include "input.h" +#include "arena.h" + +typedef struct { + input_t game_input; + arena_t main_arena; + int32_t window_h; + int32_t window_w; + int64_t frame; + double dt; +} game_state_t; + +#endif diff --git a/input.h b/input.h index f7d80de..bae3795 100644 --- a/input.h +++ b/input.h @@ -1,6 +1,8 @@ #ifndef INPUT_H #define INPUT_H +#include + // NOTE: KEY_STATE_RELEASED does not imply KEY_STATE_UNPRESSED, which can be funky. Maybe give this another look? typedef enum { KEY_STATE_UNPRESSED = 0, diff --git a/wayland.c b/wayland.c index 11cba0a..093c898 100644 --- a/wayland.c +++ b/wayland.c @@ -17,6 +17,7 @@ #include #include #include +#include // libevdev #include // generated header using wayland-scanner @@ -27,6 +28,7 @@ #include "input.h" #include "arena.h" #include "debug.h" +#include "game.h" struct wl_compositor *compositor = NULL; struct wl_registry *registry = NULL; @@ -55,16 +57,26 @@ struct xkb_state *xkb_state = NULL; struct xkb_keymap *xkb_keymap = NULL; /* libevdev */ -struct libevdev *libevdev; +struct libevdev *libevdev = NULL; /* Misc. global state */ +game_state_t game_state = {}; EGLBoolean errcode = 0; bool running = true; input_t user_input = {}; arena_t main_arena = {}; -console_verbosity_t console_verbosity = { MODULE_CONTROLLER }; +console_verbosity_t console_verbosity = { MODULE_ALL }; error_level_t error_verbosity = { ERROR_LEVEL_DEBUG }; +typedef void (*simulate_frame_fn)(game_state_t*); + +/* Game layer */ +typedef struct { + simulate_frame_fn simulate_frame; +} game_api_t; + +game_api_t game_api = {}; + char *egl_s(int code) { switch (code) @@ -225,7 +237,9 @@ void keymap_callback(void *data, struct wl_keyboard *kb, uint format, int fd, ui // TODO: Check for XKB compatibility and use xkbcommon to extract console_debug_ss(MODULE_KEYBOARD, "KBMAP of size %d detected\n", size); - char *mem = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0); + char *mem = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0); + if (mem == MAP_FAILED) + console_err_ss(MODULE_KEYBOARD, "Could not mmap keyboard: %s\n", strerror(errno)); console_debug_ss(MODULE_KEYBOARD, "XKBMAP desc:\n\t%s\n", mem); xkb_keymap = xkb_keymap_new_from_string(xkb_context, mem, XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS); munmap(mem, size); @@ -727,6 +741,18 @@ int main() // necessary before our first eglSwapBuffers wl_surface_commit(surface); + // Trying to link with game layer + void *dlhandle = dlopen("./game.so", RTLD_NOW); + if (!dlhandle) + console_err_ss(MODULE_HOTRELOAD, "Could not load game layer\n"); + dlerror(); + + game_api.simulate_frame = (simulate_frame_fn)dlsym(dlhandle, "simulate_frame"); + + char *dlerr = NULL; + if ((dlerr = dlerror())) + console_err_ss(MODULE_HOTRELOAD, "Could not link game layer: %s\n", dlerr); + // Main event loop int framecount = 0; while (running) @@ -734,83 +760,96 @@ int main() wl_display_dispatch_pending(display); /* Controller input handling */ - struct input_event iev; - int errcode = libevdev_next_event(libevdev, LIBEVDEV_READ_FLAG_NORMAL | LIBEVDEV_READ_FLAG_BLOCKING, &iev); - do { - if (errcode == LIBEVDEV_READ_STATUS_SYNC) - { - // TODO: Debug printing, deal with lost controller - while ((errcode = libevdev_next_event(libevdev, LIBEVDEV_READ_FLAG_SYNC, &iev)) == LIBEVDEV_READ_STATUS_SYNC); - } - else if (errcode == LIBEVDEV_READ_STATUS_SUCCESS) - { - // TODO: Debug printing - if (iev.type == EV_ABS || iev.type == EV_KEY) - console_debug_ss(MODULE_CONTROLLER, "Controller event\n\tTime: %ld.%06ld\n\tType: %s\n\tCode: %s\n\tValue: %d\n", iev.input_event_sec, iev.input_event_usec, libevdev_event_type_get_name(iev.type), libevdev_event_code_get_name(iev.type, iev.code), iev.value); - - if (iev.type == EV_ABS) + if (libevdev_get_fd(libevdev) != -1) // check if we actually found a controller to query + { + struct input_event iev; + int errcode = libevdev_next_event(libevdev, LIBEVDEV_READ_FLAG_NORMAL | LIBEVDEV_READ_FLAG_BLOCKING, &iev); + do { + if (errcode == LIBEVDEV_READ_STATUS_SYNC) { - int max_val = libevdev_event_type_get_max(EV_ABS); - float normalized_val = (2 * iev.value / (float)max_val) - 1.0f; - - if (!strcmp(libevdev_event_code_get_name(iev.type, iev.code), "ABS_X")) - user_input.lx_axis = normalized_val; - if (!strcmp(libevdev_event_code_get_name(iev.type, iev.code), "ABS_Y")) - user_input.ly_axis = normalized_val; - if (!strcmp(libevdev_event_code_get_name(iev.type, iev.code), "ABS_Z")) - user_input.lz_axis = normalized_val; - if (!strcmp(libevdev_event_code_get_name(iev.type, iev.code), "ABS_RX")) - user_input.rx_axis = normalized_val; - if (!strcmp(libevdev_event_code_get_name(iev.type, iev.code), "ABS_RY")) - user_input.ry_axis = normalized_val; - if (!strcmp(libevdev_event_code_get_name(iev.type, iev.code), "ABS_RZ")) - user_input.rz_axis = normalized_val; - if (!strcmp(libevdev_event_code_get_name(iev.type, iev.code), "ABS_HAT0X")) - { - user_input.controller_buttons[CONT_LEFT] = iev.value == -1 ? 1 : 0; - user_input.controller_buttons[CONT_RIGHT] = iev.value == 1 ? 1 : 0; - } - if (!strcmp(libevdev_event_code_get_name(iev.type, iev.code), "ABS_HAT0Y")) - { - user_input.controller_buttons[CONT_UP] = iev.value == -1 ? 1 : 0; - user_input.controller_buttons[CONT_DOWN] = iev.value == 1 ? 1 : 0; - } - + // TODO: Debug printing, deal with lost controller + while ((errcode = libevdev_next_event(libevdev, LIBEVDEV_READ_FLAG_SYNC, &iev)) == LIBEVDEV_READ_STATUS_SYNC); } - if (iev.type == EV_KEY) + else if (errcode == LIBEVDEV_READ_STATUS_SUCCESS) { - if (!strcmp(libevdev_event_code_get_name(iev.type, iev.code), "BTN_TL")) - user_input.controller_buttons[CONT_L] = iev.value; - if (!strcmp(libevdev_event_code_get_name(iev.type, iev.code), "BTN_TR")) - user_input.controller_buttons[CONT_R] = iev.value; - if (!strcmp(libevdev_event_code_get_name(iev.type, iev.code), "BTN_SELECT")) - user_input.controller_buttons[CONT_SELECT] = iev.value; - if (!strcmp(libevdev_event_code_get_name(iev.type, iev.code), "BTN_START")) - user_input.controller_buttons[CONT_START] = iev.value; - if (!strcmp(libevdev_event_code_get_name(iev.type, iev.code), "BTN_MODE")) - user_input.controller_buttons[CONT_MODE] = iev.value; - if (!strcmp(libevdev_event_code_get_name(iev.type, iev.code), "BTN_THUMBR")) - user_input.controller_buttons[CONT_RTHUMB] = iev.value; - if (!strcmp(libevdev_event_code_get_name(iev.type, iev.code), "BTN_THUMBL")) - user_input.controller_buttons[CONT_RTHUMB] = iev.value; - if (!strcmp(libevdev_event_code_get_name(iev.type, iev.code), "BTN_NORTH")) - user_input.controller_buttons[CONT_NORTH] = iev.value; - if (!strcmp(libevdev_event_code_get_name(iev.type, iev.code), "BTN_EAST")) - user_input.controller_buttons[CONT_EAST] = iev.value; - if (!strcmp(libevdev_event_code_get_name(iev.type, iev.code), "BTN_SOUTH")) - user_input.controller_buttons[CONT_SOUTH] = iev.value; - if (!strcmp(libevdev_event_code_get_name(iev.type, iev.code), "BTN_WEST")) - user_input.controller_buttons[CONT_WEST] = iev.value; - if (!strcmp(libevdev_event_code_get_name(iev.type, iev.code), "BTN_MODE")) - user_input.controller_buttons[CONT_MODE] = iev.value; + // TODO: Debug printing + if (iev.type == EV_ABS || iev.type == EV_KEY) + console_debug_ss(MODULE_CONTROLLER, "Controller event\n\tTime: %ld.%06ld\n\tType: %s\n\tCode: %s\n\tValue: %d\n", iev.input_event_sec, iev.input_event_usec, libevdev_event_type_get_name(iev.type), libevdev_event_code_get_name(iev.type, iev.code), iev.value); + + if (iev.type == EV_ABS) + { + int max_val = libevdev_event_type_get_max(EV_ABS); + float normalized_val = (2 * iev.value / (float)max_val) - 1.0f; + + if (!strcmp(libevdev_event_code_get_name(iev.type, iev.code), "ABS_X")) + user_input.lx_axis = normalized_val; + if (!strcmp(libevdev_event_code_get_name(iev.type, iev.code), "ABS_Y")) + user_input.ly_axis = normalized_val; + if (!strcmp(libevdev_event_code_get_name(iev.type, iev.code), "ABS_Z")) + user_input.lz_axis = normalized_val; + if (!strcmp(libevdev_event_code_get_name(iev.type, iev.code), "ABS_RX")) + user_input.rx_axis = normalized_val; + if (!strcmp(libevdev_event_code_get_name(iev.type, iev.code), "ABS_RY")) + user_input.ry_axis = normalized_val; + if (!strcmp(libevdev_event_code_get_name(iev.type, iev.code), "ABS_RZ")) + user_input.rz_axis = normalized_val; + if (!strcmp(libevdev_event_code_get_name(iev.type, iev.code), "ABS_HAT0X")) + { + user_input.controller_buttons[CONT_LEFT] = iev.value == -1 ? 1 : 0; + user_input.controller_buttons[CONT_RIGHT] = iev.value == 1 ? 1 : 0; + } + if (!strcmp(libevdev_event_code_get_name(iev.type, iev.code), "ABS_HAT0Y")) + { + user_input.controller_buttons[CONT_UP] = iev.value == -1 ? 1 : 0; + user_input.controller_buttons[CONT_DOWN] = iev.value == 1 ? 1 : 0; + } + + } + if (iev.type == EV_KEY) + { + if (!strcmp(libevdev_event_code_get_name(iev.type, iev.code), "BTN_TL")) + user_input.controller_buttons[CONT_L] = iev.value; + if (!strcmp(libevdev_event_code_get_name(iev.type, iev.code), "BTN_TR")) + user_input.controller_buttons[CONT_R] = iev.value; + if (!strcmp(libevdev_event_code_get_name(iev.type, iev.code), "BTN_SELECT")) + user_input.controller_buttons[CONT_SELECT] = iev.value; + if (!strcmp(libevdev_event_code_get_name(iev.type, iev.code), "BTN_START")) + user_input.controller_buttons[CONT_START] = iev.value; + if (!strcmp(libevdev_event_code_get_name(iev.type, iev.code), "BTN_MODE")) + user_input.controller_buttons[CONT_MODE] = iev.value; + if (!strcmp(libevdev_event_code_get_name(iev.type, iev.code), "BTN_THUMBR")) + user_input.controller_buttons[CONT_RTHUMB] = iev.value; + if (!strcmp(libevdev_event_code_get_name(iev.type, iev.code), "BTN_THUMBL")) + user_input.controller_buttons[CONT_RTHUMB] = iev.value; + if (!strcmp(libevdev_event_code_get_name(iev.type, iev.code), "BTN_NORTH")) + user_input.controller_buttons[CONT_NORTH] = iev.value; + if (!strcmp(libevdev_event_code_get_name(iev.type, iev.code), "BTN_EAST")) + user_input.controller_buttons[CONT_EAST] = iev.value; + if (!strcmp(libevdev_event_code_get_name(iev.type, iev.code), "BTN_SOUTH")) + user_input.controller_buttons[CONT_SOUTH] = iev.value; + if (!strcmp(libevdev_event_code_get_name(iev.type, iev.code), "BTN_WEST")) + user_input.controller_buttons[CONT_WEST] = iev.value; + if (!strcmp(libevdev_event_code_get_name(iev.type, iev.code), "BTN_MODE")) + user_input.controller_buttons[CONT_MODE] = iev.value; + } } - } - } while (errcode != LIBEVDEV_READ_STATUS_SYNC && errcode != LIBEVDEV_READ_STATUS_SUCCESS && errcode != -EAGAIN); + } while (errcode != LIBEVDEV_READ_STATUS_SYNC && errcode != LIBEVDEV_READ_STATUS_SUCCESS && errcode != -EAGAIN); - if (errcode != LIBEVDEV_READ_STATUS_SUCCESS && errcode != -EAGAIN) - console_warn_ss(MODULE_CONTROLLER, "Failed to handle controller event: %s\n", strerror(-errcode)); + if (errcode != LIBEVDEV_READ_STATUS_SUCCESS && errcode != -EAGAIN) + console_warn_ss(MODULE_CONTROLLER, "Failed to handle controller event: %s\n", strerror(-errcode)); + } // end of input handling + game_state.game_input = user_input; + game_state.main_arena = main_arena; + int32_t w, h; + wl_egl_window_get_attached_size(window, &w, &h); + game_state.window_w = w; + game_state.window_h = h; + game_state.frame = framecount; + // TODO: Get delta time since last frame + game_state.dt = 0; + game_api.simulate_frame(&game_state); //console_debug_ss(MODULE_WAYLAND, "Frame %d\n", framecount); glClearColor(0.5, 0.3, 0.0, 1.0); glClear(GL_COLOR_BUFFER_BIT);