Add game layer linking

This commit is contained in:
Phireh 2024-12-16 20:16:27 +01:00
commit 9a4c57d4c2
8 changed files with 146 additions and 74 deletions

185
wayland.c
View file

@ -17,6 +17,7 @@
#include <linux/input-event-codes.h>
#include <fcntl.h>
#include <errno.h>
#include <dlfcn.h>
// libevdev
#include <libevdev-1.0/libevdev/libevdev.h>
// 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);