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

1
.gitignore vendored
View file

@ -1,4 +1,5 @@
wayland wayland
game.so
xdg-shell-client-protocol.h xdg-shell-client-protocol.h
xdg-shell-protocol.c xdg-shell-protocol.c
zwp-text-input-unstable-v3-client-protocol.c zwp-text-input-unstable-v3-client-protocol.c

View file

@ -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 wayland-scanner private-code $(INTERFACEDIR)/unstable/xdg-decoration/xdg-decoration-unstable-v1.xml xdg-decoration-unstable-v1.c
xdg-decoration-unstable-v1.h: xdg-decoration-unstable-v1.h:
wayland-scanner client-header $(INTERFACEDIR)/unstable/xdg-decoration/xdg-decoration-unstable-v1.xml 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

View file

@ -1,6 +1,10 @@
#ifndef ARENA_H #ifndef ARENA_H
#define ARENA_H #define ARENA_H
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
typedef enum { typedef enum {
ARENA_ZERO = 1 << 0, ARENA_ZERO = 1 << 0,
ARENA_SOFTFAIL = 1 << 1, ARENA_SOFTFAIL = 1 << 1,

View file

@ -8,6 +8,7 @@ typedef enum {
MODULE_MOUSE = 1 << 2, MODULE_MOUSE = 1 << 2,
MODULE_WAYLAND = 1 << 3, MODULE_WAYLAND = 1 << 3,
MODULE_CONTROLLER = 1 << 4, MODULE_CONTROLLER = 1 << 4,
MODULE_HOTRELOAD = 1 << 5,
MODULE_ALL = ~0 MODULE_ALL = ~0
} console_verbosity_t; } console_verbosity_t;

7
game.c Normal file
View file

@ -0,0 +1,7 @@
#include "game.h"
void simulate_frame(game_state_t *state)
{
// TODO: Do something amazing here
;
}

16
game.h Normal file
View file

@ -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

View file

@ -1,6 +1,8 @@
#ifndef INPUT_H #ifndef INPUT_H
#define INPUT_H #define INPUT_H
#include <stdint.h>
// NOTE: KEY_STATE_RELEASED does not imply KEY_STATE_UNPRESSED, which can be funky. Maybe give this another look? // NOTE: KEY_STATE_RELEASED does not imply KEY_STATE_UNPRESSED, which can be funky. Maybe give this another look?
typedef enum { typedef enum {
KEY_STATE_UNPRESSED = 0, KEY_STATE_UNPRESSED = 0,

185
wayland.c
View file

@ -17,6 +17,7 @@
#include <linux/input-event-codes.h> #include <linux/input-event-codes.h>
#include <fcntl.h> #include <fcntl.h>
#include <errno.h> #include <errno.h>
#include <dlfcn.h>
// libevdev // libevdev
#include <libevdev-1.0/libevdev/libevdev.h> #include <libevdev-1.0/libevdev/libevdev.h>
// generated header using wayland-scanner // generated header using wayland-scanner
@ -27,6 +28,7 @@
#include "input.h" #include "input.h"
#include "arena.h" #include "arena.h"
#include "debug.h" #include "debug.h"
#include "game.h"
struct wl_compositor *compositor = NULL; struct wl_compositor *compositor = NULL;
struct wl_registry *registry = NULL; struct wl_registry *registry = NULL;
@ -55,16 +57,26 @@ struct xkb_state *xkb_state = NULL;
struct xkb_keymap *xkb_keymap = NULL; struct xkb_keymap *xkb_keymap = NULL;
/* libevdev */ /* libevdev */
struct libevdev *libevdev; struct libevdev *libevdev = NULL;
/* Misc. global state */ /* Misc. global state */
game_state_t game_state = {};
EGLBoolean errcode = 0; EGLBoolean errcode = 0;
bool running = true; bool running = true;
input_t user_input = {}; input_t user_input = {};
arena_t main_arena = {}; 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 }; 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) char *egl_s(int code)
{ {
switch (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 // TODO: Check for XKB compatibility and use xkbcommon to extract
console_debug_ss(MODULE_KEYBOARD, "KBMAP of size %d detected\n", size); 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); 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); xkb_keymap = xkb_keymap_new_from_string(xkb_context, mem, XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS);
munmap(mem, size); munmap(mem, size);
@ -727,6 +741,18 @@ int main()
// necessary before our first eglSwapBuffers // necessary before our first eglSwapBuffers
wl_surface_commit(surface); 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 // Main event loop
int framecount = 0; int framecount = 0;
while (running) while (running)
@ -734,83 +760,96 @@ int main()
wl_display_dispatch_pending(display); wl_display_dispatch_pending(display);
/* Controller input handling */ /* Controller input handling */
struct input_event iev; if (libevdev_get_fd(libevdev) != -1) // check if we actually found a controller to query
int errcode = libevdev_next_event(libevdev, LIBEVDEV_READ_FLAG_NORMAL | LIBEVDEV_READ_FLAG_BLOCKING, &iev); {
do { struct input_event iev;
if (errcode == LIBEVDEV_READ_STATUS_SYNC) int errcode = libevdev_next_event(libevdev, LIBEVDEV_READ_FLAG_NORMAL | LIBEVDEV_READ_FLAG_BLOCKING, &iev);
{ do {
// TODO: Debug printing, deal with lost controller if (errcode == LIBEVDEV_READ_STATUS_SYNC)
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)
{ {
int max_val = libevdev_event_type_get_max(EV_ABS); // TODO: Debug printing, deal with lost controller
float normalized_val = (2 * iev.value / (float)max_val) - 1.0f; while ((errcode = libevdev_next_event(libevdev, LIBEVDEV_READ_FLAG_SYNC, &iev)) == LIBEVDEV_READ_STATUS_SYNC);
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) else if (errcode == LIBEVDEV_READ_STATUS_SUCCESS)
{ {
if (!strcmp(libevdev_event_code_get_name(iev.type, iev.code), "BTN_TL")) // TODO: Debug printing
user_input.controller_buttons[CONT_L] = iev.value; if (iev.type == EV_ABS || iev.type == EV_KEY)
if (!strcmp(libevdev_event_code_get_name(iev.type, iev.code), "BTN_TR")) 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);
user_input.controller_buttons[CONT_R] = iev.value;
if (!strcmp(libevdev_event_code_get_name(iev.type, iev.code), "BTN_SELECT")) if (iev.type == EV_ABS)
user_input.controller_buttons[CONT_SELECT] = iev.value; {
if (!strcmp(libevdev_event_code_get_name(iev.type, iev.code), "BTN_START")) int max_val = libevdev_event_type_get_max(EV_ABS);
user_input.controller_buttons[CONT_START] = iev.value; float normalized_val = (2 * iev.value / (float)max_val) - 1.0f;
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), "ABS_X"))
if (!strcmp(libevdev_event_code_get_name(iev.type, iev.code), "BTN_THUMBR")) user_input.lx_axis = normalized_val;
user_input.controller_buttons[CONT_RTHUMB] = iev.value; if (!strcmp(libevdev_event_code_get_name(iev.type, iev.code), "ABS_Y"))
if (!strcmp(libevdev_event_code_get_name(iev.type, iev.code), "BTN_THUMBL")) user_input.ly_axis = normalized_val;
user_input.controller_buttons[CONT_RTHUMB] = iev.value; if (!strcmp(libevdev_event_code_get_name(iev.type, iev.code), "ABS_Z"))
if (!strcmp(libevdev_event_code_get_name(iev.type, iev.code), "BTN_NORTH")) user_input.lz_axis = normalized_val;
user_input.controller_buttons[CONT_NORTH] = iev.value; if (!strcmp(libevdev_event_code_get_name(iev.type, iev.code), "ABS_RX"))
if (!strcmp(libevdev_event_code_get_name(iev.type, iev.code), "BTN_EAST")) user_input.rx_axis = normalized_val;
user_input.controller_buttons[CONT_EAST] = iev.value; if (!strcmp(libevdev_event_code_get_name(iev.type, iev.code), "ABS_RY"))
if (!strcmp(libevdev_event_code_get_name(iev.type, iev.code), "BTN_SOUTH")) user_input.ry_axis = normalized_val;
user_input.controller_buttons[CONT_SOUTH] = iev.value; if (!strcmp(libevdev_event_code_get_name(iev.type, iev.code), "ABS_RZ"))
if (!strcmp(libevdev_event_code_get_name(iev.type, iev.code), "BTN_WEST")) user_input.rz_axis = normalized_val;
user_input.controller_buttons[CONT_WEST] = iev.value; if (!strcmp(libevdev_event_code_get_name(iev.type, iev.code), "ABS_HAT0X"))
if (!strcmp(libevdev_event_code_get_name(iev.type, iev.code), "BTN_MODE")) {
user_input.controller_buttons[CONT_MODE] = iev.value; 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) if (errcode != LIBEVDEV_READ_STATUS_SUCCESS && errcode != -EAGAIN)
console_warn_ss(MODULE_CONTROLLER, "Failed to handle controller event: %s\n", strerror(-errcode)); 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); //console_debug_ss(MODULE_WAYLAND, "Frame %d\n", framecount);
glClearColor(0.5, 0.3, 0.0, 1.0); glClearColor(0.5, 0.3, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT);