initial commit

This commit is contained in:
2026-04-06 13:27:44 -04:00
commit 5aaecdeac6
24 changed files with 2246 additions and 0 deletions
+366
View File
@@ -0,0 +1,366 @@
#include "client/input.h"
#include "client/video.h"
#include <SDL3/SDL.h>
#include <string.h>
static uint8_t key_held[SKELE_KEY_COUNT];
static uint8_t key_down[SKELE_KEY_COUNT];
static SDL_Gamepad *pads[SKELE_MAX_PADS];
static uint8_t pad_btn_held[SKELE_MAX_PADS][SKELE_PAD_BUTTON_COUNT];
static uint8_t pad_btn_down[SKELE_MAX_PADS][SKELE_PAD_BUTTON_COUNT];
static float pad_axes[SKELE_MAX_PADS][SKELE_PAD_AXIS_COUNT];
static int32_t mouse_dx = 0;
static int32_t mouse_dy = 0;
static skele_key_t scancode_to_key(SDL_Scancode sc)
{
switch (sc) {
case SDL_SCANCODE_A:
return SKELE_KEY_A;
case SDL_SCANCODE_B:
return SKELE_KEY_B;
case SDL_SCANCODE_C:
return SKELE_KEY_C;
case SDL_SCANCODE_D:
return SKELE_KEY_D;
case SDL_SCANCODE_E:
return SKELE_KEY_E;
case SDL_SCANCODE_F:
return SKELE_KEY_F;
case SDL_SCANCODE_G:
return SKELE_KEY_G;
case SDL_SCANCODE_H:
return SKELE_KEY_H;
case SDL_SCANCODE_I:
return SKELE_KEY_I;
case SDL_SCANCODE_J:
return SKELE_KEY_J;
case SDL_SCANCODE_K:
return SKELE_KEY_K;
case SDL_SCANCODE_L:
return SKELE_KEY_L;
case SDL_SCANCODE_M:
return SKELE_KEY_M;
case SDL_SCANCODE_N:
return SKELE_KEY_N;
case SDL_SCANCODE_O:
return SKELE_KEY_O;
case SDL_SCANCODE_P:
return SKELE_KEY_P;
case SDL_SCANCODE_Q:
return SKELE_KEY_Q;
case SDL_SCANCODE_R:
return SKELE_KEY_R;
case SDL_SCANCODE_S:
return SKELE_KEY_S;
case SDL_SCANCODE_T:
return SKELE_KEY_T;
case SDL_SCANCODE_U:
return SKELE_KEY_U;
case SDL_SCANCODE_V:
return SKELE_KEY_V;
case SDL_SCANCODE_W:
return SKELE_KEY_W;
case SDL_SCANCODE_X:
return SKELE_KEY_X;
case SDL_SCANCODE_Y:
return SKELE_KEY_Y;
case SDL_SCANCODE_Z:
return SKELE_KEY_Z;
case SDL_SCANCODE_0:
return SKELE_KEY_0;
case SDL_SCANCODE_1:
return SKELE_KEY_1;
case SDL_SCANCODE_2:
return SKELE_KEY_2;
case SDL_SCANCODE_3:
return SKELE_KEY_3;
case SDL_SCANCODE_4:
return SKELE_KEY_4;
case SDL_SCANCODE_5:
return SKELE_KEY_5;
case SDL_SCANCODE_6:
return SKELE_KEY_6;
case SDL_SCANCODE_7:
return SKELE_KEY_7;
case SDL_SCANCODE_8:
return SKELE_KEY_8;
case SDL_SCANCODE_9:
return SKELE_KEY_9;
case SDL_SCANCODE_F1:
return SKELE_KEY_F1;
case SDL_SCANCODE_F2:
return SKELE_KEY_F2;
case SDL_SCANCODE_F3:
return SKELE_KEY_F3;
case SDL_SCANCODE_F4:
return SKELE_KEY_F4;
case SDL_SCANCODE_F5:
return SKELE_KEY_F5;
case SDL_SCANCODE_F6:
return SKELE_KEY_F6;
case SDL_SCANCODE_F7:
return SKELE_KEY_F7;
case SDL_SCANCODE_F8:
return SKELE_KEY_F8;
case SDL_SCANCODE_F9:
return SKELE_KEY_F9;
case SDL_SCANCODE_F10:
return SKELE_KEY_F10;
case SDL_SCANCODE_F11:
return SKELE_KEY_F11;
case SDL_SCANCODE_F12:
return SKELE_KEY_F12;
case SDL_SCANCODE_SPACE:
return SKELE_KEY_SPACE;
case SDL_SCANCODE_RETURN:
return SKELE_KEY_ENTER;
case SDL_SCANCODE_ESCAPE:
return SKELE_KEY_ESCAPE;
case SDL_SCANCODE_TAB:
return SKELE_KEY_TAB;
case SDL_SCANCODE_BACKSPACE:
return SKELE_KEY_BACKSPACE;
case SDL_SCANCODE_LSHIFT:
return SKELE_KEY_LSHIFT;
case SDL_SCANCODE_RSHIFT:
return SKELE_KEY_RSHIFT;
case SDL_SCANCODE_LCTRL:
return SKELE_KEY_LCTRL;
case SDL_SCANCODE_RCTRL:
return SKELE_KEY_RCTRL;
case SDL_SCANCODE_LALT:
return SKELE_KEY_LALT;
case SDL_SCANCODE_RALT:
return SKELE_KEY_RALT;
case SDL_SCANCODE_UP:
return SKELE_KEY_UP;
case SDL_SCANCODE_DOWN:
return SKELE_KEY_DOWN;
case SDL_SCANCODE_LEFT:
return SKELE_KEY_LEFT;
case SDL_SCANCODE_RIGHT:
return SKELE_KEY_RIGHT;
default:
return SKELE_KEY_UNKNOWN;
}
}
static skele_pad_button_t sdl_btn_to_pad(SDL_GamepadButton btn)
{
switch (btn) {
case SDL_GAMEPAD_BUTTON_SOUTH:
return SKELE_PAD_A;
case SDL_GAMEPAD_BUTTON_EAST:
return SKELE_PAD_B;
case SDL_GAMEPAD_BUTTON_WEST:
return SKELE_PAD_X;
case SDL_GAMEPAD_BUTTON_NORTH:
return SKELE_PAD_Y;
case SDL_GAMEPAD_BUTTON_LEFT_SHOULDER:
return SKELE_PAD_LB;
case SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER:
return SKELE_PAD_RB;
case SDL_GAMEPAD_BUTTON_LEFT_STICK:
return SKELE_PAD_LSTICK;
case SDL_GAMEPAD_BUTTON_RIGHT_STICK:
return SKELE_PAD_RSTICK;
case SDL_GAMEPAD_BUTTON_START:
return SKELE_PAD_START;
case SDL_GAMEPAD_BUTTON_BACK:
return SKELE_PAD_BACK;
case SDL_GAMEPAD_BUTTON_DPAD_UP:
return SKELE_PAD_DPAD_UP;
case SDL_GAMEPAD_BUTTON_DPAD_DOWN:
return SKELE_PAD_DPAD_DOWN;
case SDL_GAMEPAD_BUTTON_DPAD_LEFT:
return SKELE_PAD_DPAD_LEFT;
case SDL_GAMEPAD_BUTTON_DPAD_RIGHT:
return SKELE_PAD_DPAD_RIGHT;
default:
return SKELE_PAD_BUTTON_COUNT;
}
}
static int8_t pad_slot(SDL_JoystickID id)
{
uint8_t i;
for (i = 0; i < SKELE_MAX_PADS; i++)
if (pads[i] && SDL_GetGamepadID(pads[i]) == id)
return (int8_t)i;
return -1;
}
static int8_t free_slot(void)
{
uint8_t i;
for (i = 0; i < SKELE_MAX_PADS; i++)
if (!pads[i])
return (int8_t)i;
return -1;
}
static void update_axes(uint8_t slot)
{
pad_axes[slot][SKELE_PAD_AXIS_LX] =
SDL_GetGamepadAxis(pads[slot], SDL_GAMEPAD_AXIS_LEFTX) / 32767.0f;
pad_axes[slot][SKELE_PAD_AXIS_LY] =
SDL_GetGamepadAxis(pads[slot], SDL_GAMEPAD_AXIS_LEFTY) / 32767.0f;
pad_axes[slot][SKELE_PAD_AXIS_RX] =
SDL_GetGamepadAxis(pads[slot], SDL_GAMEPAD_AXIS_RIGHTX) / 32767.0f;
pad_axes[slot][SKELE_PAD_AXIS_RY] =
SDL_GetGamepadAxis(pads[slot], SDL_GAMEPAD_AXIS_RIGHTY) / 32767.0f;
pad_axes[slot][SKELE_PAD_AXIS_LT] =
SDL_GetGamepadAxis(pads[slot], SDL_GAMEPAD_AXIS_LEFT_TRIGGER) /
32767.0f;
pad_axes[slot][SKELE_PAD_AXIS_RT] =
SDL_GetGamepadAxis(pads[slot], SDL_GAMEPAD_AXIS_RIGHT_TRIGGER) /
32767.0f;
}
uint8_t skele_input_poll(void)
{
SDL_Event e;
skele_key_t key;
int8_t slot;
uint8_t i;
skele_pad_button_t btn;
memset(key_down, 0, sizeof(key_down));
memset(pad_btn_down, 0, sizeof(pad_btn_down));
mouse_dx = 0;
mouse_dy = 0;
while (SDL_PollEvent(&e)) {
switch (e.type) {
case SDL_EVENT_QUIT:
return 0;
case SDL_EVENT_MOUSE_MOTION:
mouse_dx += (int32_t)e.motion.xrel;
mouse_dy += (int32_t)e.motion.yrel;
break;
case SDL_EVENT_KEY_DOWN:
if (e.key.repeat)
break;
switch (e.key.scancode) {
case SDL_SCANCODE_F11:
skele_video_toggle_fullscreen();
break;
case SDL_SCANCODE_F4:
skele_video_cycle_scale();
break;
default:
key = scancode_to_key(e.key.scancode);
if (key != SKELE_KEY_UNKNOWN) {
key_down[key] = 1;
key_held[key] = 1;
}
break;
}
break;
case SDL_EVENT_KEY_UP:
key = scancode_to_key(e.key.scancode);
if (key != SKELE_KEY_UNKNOWN)
key_held[key] = 0;
break;
case SDL_EVENT_GAMEPAD_ADDED:
slot = free_slot();
if (slot >= 0) {
pads[slot] = SDL_OpenGamepad(e.gdevice.which);
if (pads[slot])
memset(pad_btn_held[slot], 0,
sizeof(pad_btn_held[slot]));
}
break;
case SDL_EVENT_GAMEPAD_REMOVED:
slot = pad_slot(e.gdevice.which);
if (slot >= 0) {
SDL_CloseGamepad(pads[slot]);
pads[slot] = NULL;
memset(pad_btn_held[slot], 0,
sizeof(pad_btn_held[slot]));
memset(pad_axes[slot], 0,
sizeof(pad_axes[slot]));
}
break;
case SDL_EVENT_GAMEPAD_BUTTON_DOWN:
slot = pad_slot(e.gbutton.which);
btn =
sdl_btn_to_pad((SDL_GamepadButton)e.gbutton.button);
if (slot >= 0 && btn != SKELE_PAD_BUTTON_COUNT) {
pad_btn_down[slot][btn] = 1;
pad_btn_held[slot][btn] = 1;
}
break;
case SDL_EVENT_GAMEPAD_BUTTON_UP:
slot = pad_slot(e.gbutton.which);
btn =
sdl_btn_to_pad((SDL_GamepadButton)e.gbutton.button);
if (slot >= 0 && btn != SKELE_PAD_BUTTON_COUNT)
pad_btn_held[slot][btn] = 0;
break;
default:
break;
}
}
for (i = 0; i < SKELE_MAX_PADS; i++)
if (pads[i])
update_axes(i);
return 1;
}
uint8_t skele_key_down(skele_key_t key)
{
return key < SKELE_KEY_COUNT ? key_down[key] : 0;
}
uint8_t skele_key_held(skele_key_t key)
{
return key < SKELE_KEY_COUNT ? key_held[key] : 0;
}
uint8_t skele_pad_connected(uint8_t pad)
{
return pad < SKELE_MAX_PADS ? pads[pad] != NULL : 0;
}
uint8_t skele_pad_button_down(uint8_t pad, skele_pad_button_t btn)
{
return (pad < SKELE_MAX_PADS && btn < SKELE_PAD_BUTTON_COUNT)
? pad_btn_down[pad][btn]
: 0;
}
uint8_t skele_pad_button_held(uint8_t pad, skele_pad_button_t btn)
{
return (pad < SKELE_MAX_PADS && btn < SKELE_PAD_BUTTON_COUNT)
? pad_btn_held[pad][btn]
: 0;
}
float skele_pad_axis(uint8_t pad, skele_pad_axis_t axis)
{
return (pad < SKELE_MAX_PADS && axis < SKELE_PAD_AXIS_COUNT)
? pad_axes[pad][axis]
: 0.0f;
}
void skele_mouse_delta(int32_t *dx, int32_t *dy)
{
if (dx)
*dx = mouse_dx;
if (dy)
*dy = mouse_dy;
}
+179
View File
@@ -0,0 +1,179 @@
#include "client/video.h"
#include "skele.h"
#include <SDL3/SDL.h>
#include <stk/stk_log.h>
static SDL_Window *window = NULL;
static SDL_GLContext gl_ctx = NULL;
static uint16_t vid_w = 0;
static uint16_t vid_h = 0;
static uint8_t cur_scale = 1;
static uint8_t fullscreen = 0;
static uint8_t max_scale(uint16_t rw, uint16_t rh)
{
SDL_DisplayID display;
const SDL_DisplayMode *mode;
uint16_t aw, ah;
uint8_t scale;
display =
window ? SDL_GetDisplayForWindow(window) : SDL_GetPrimaryDisplay();
mode = SDL_GetCurrentDisplayMode(display);
if (!mode)
return 1;
aw = (uint16_t)((mode->w * 3) / 4);
ah = (uint16_t)((mode->h * 3) / 4);
scale = 1;
while ((rw * (scale + 1)) <= aw && (rh * (scale + 1)) <= ah)
scale++;
return scale;
}
static void set_scale(uint8_t scale)
{
SDL_DisplayID display;
cur_scale = scale;
display = SDL_GetDisplayForWindow(window);
SDL_SetWindowSize(window, (int)(vid_w * scale), (int)(vid_h * scale));
SDL_SetWindowPosition(window, SDL_WINDOWPOS_CENTERED_DISPLAY(display),
SDL_WINDOWPOS_CENTERED_DISPLAY(display));
}
static void toggle_fullscreen(void)
{
fullscreen = !fullscreen;
SDL_SetWindowFullscreen(window, fullscreen);
}
static void cycle_scale(void)
{
uint8_t next;
if (fullscreen)
return;
next = cur_scale + 1;
if (next > max_scale(vid_w, vid_h))
next = 1;
set_scale(next);
}
uint8_t skele_video_init(skele_video_config_t cfg)
{
SDL_DisplayID display;
SDL_WindowFlags flags = 0;
const SDL_DisplayMode *mode;
uint16_t window_w, window_h, aw, ah;
if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMEPAD)) {
stk_log(STK_LOG_ERROR, "video: SDL_Init failed: %s",
SDL_GetError());
return SKELE_INIT_FAILURE;
}
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, GL_MAJOR);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, GL_MINOR);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK,
SDL_GL_CONTEXT_PROFILE_CORE);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
flags |= SDL_WINDOW_OPENGL;
if (cfg.flags & SKELE_VIDEO_FULLSCREEN)
flags |= SDL_WINDOW_FULLSCREEN;
if (cfg.flags & SKELE_VIDEO_BORDERLESS)
flags |= SDL_WINDOW_BORDERLESS;
if (cfg.flags & SKELE_VIDEO_RESIZABLE)
flags |= SDL_WINDOW_RESIZABLE;
if (cfg.flags & SKELE_VIDEO_HIGHDPI)
flags |= SDL_WINDOW_HIGH_PIXEL_DENSITY;
display = SDL_GetPrimaryDisplay();
vid_w =
cfg.render_width ? cfg.render_width : SKELE_DEFAULT_RENDER_WIDTH;
vid_h =
cfg.render_height ? cfg.render_height : SKELE_DEFAULT_RENDER_HEIGHT;
if (cfg.window_width && cfg.window_height) {
window_w = cfg.window_width;
window_h = cfg.window_height;
cur_scale = 1;
} else {
mode = SDL_GetCurrentDisplayMode(display);
if (!mode) {
stk_log(STK_LOG_ERROR,
"video: SDL_GetCurrentDisplayMode failed: %s",
SDL_GetError());
SDL_Quit();
return SKELE_INIT_FAILURE;
}
aw = (uint16_t)((mode->w * 3) / 4);
ah = (uint16_t)((mode->h * 3) / 4);
cur_scale = 1;
while ((vid_w * (cur_scale + 1)) <= aw &&
(vid_h * (cur_scale + 1)) <= ah)
cur_scale++;
window_w = vid_w * cur_scale;
window_h = vid_h * cur_scale;
}
window = SDL_CreateWindow("skele", window_w, window_h,
flags | SDL_WINDOW_HIDDEN);
if (!window) {
stk_log(STK_LOG_ERROR, "video: SDL_CreateWindow failed: %s",
SDL_GetError());
SDL_Quit();
return SKELE_INIT_FAILURE;
}
SDL_SetWindowPosition(window, SDL_WINDOWPOS_CENTERED_DISPLAY(display),
SDL_WINDOWPOS_CENTERED_DISPLAY(display));
if (cfg.flags & SKELE_VIDEO_FULLSCREEN)
fullscreen = 1;
gl_ctx = SDL_GL_CreateContext(window);
if (!gl_ctx) {
stk_log(STK_LOG_ERROR, "video: SDL_GL_CreateContext failed: %s",
SDL_GetError());
SDL_DestroyWindow(window);
SDL_Quit();
return SKELE_INIT_FAILURE;
}
SDL_GL_SetSwapInterval(1);
SDL_ShowWindow(window);
return SKELE_INIT_SUCCESS;
}
void skele_video_shutdown(void)
{
if (gl_ctx)
SDL_GL_DestroyContext(gl_ctx);
if (window)
SDL_DestroyWindow(window);
SDL_Quit();
gl_ctx = NULL;
window = NULL;
vid_w = 0;
vid_h = 0;
cur_scale = 1;
fullscreen = 0;
}
void skele_video_present(void) { SDL_GL_SwapWindow(window); }
void skele_video_toggle_fullscreen(void) { toggle_fullscreen(); }
void skele_video_cycle_scale(void) { cycle_scale(); }
void skele_video_set_mouse_grab(uint8_t grab)
{
SDL_SetWindowMouseGrab(window, grab ? true : false);
SDL_SetWindowRelativeMouseMode(window, grab ? true : false);
}
void skele_video_set_title(const char *title)
{
SDL_SetWindowTitle(window, title);
}
+253
View File
@@ -0,0 +1,253 @@
#include "client/blit.h"
#include "client/palette.h"
#include "client/video.h"
#include "skele.h"
#include <SDL3/SDL.h>
#include <stdint.h>
#include <stk/stk_log.h>
#include <string.h>
static SDL_Window *window = NULL;
static SDL_Renderer *renderer = NULL;
static SDL_Texture *texture = NULL;
static SDL_Palette *sdl_pal = NULL;
static uint16_t vid_w = 0;
static uint16_t vid_h = 0;
static uint32_t vid_total = 0;
static uint8_t cur_scale = 1;
static uint8_t fullscreen = 0;
static uint8_t max_scale(uint16_t rw, uint16_t rh)
{
SDL_DisplayID display;
const SDL_DisplayMode *mode;
uint16_t aw, ah;
uint8_t scale;
display =
window ? SDL_GetDisplayForWindow(window) : SDL_GetPrimaryDisplay();
mode = SDL_GetCurrentDisplayMode(display);
if (!mode)
return 1;
aw = (uint16_t)((mode->w * 3) / 4);
ah = (uint16_t)((mode->h * 3) / 4);
scale = 1;
while ((rw * (scale + 1)) <= aw && (rh * (scale + 1)) <= ah)
scale++;
return scale;
}
static void set_scale(uint8_t scale)
{
SDL_DisplayID display;
cur_scale = scale;
display = SDL_GetDisplayForWindow(window);
SDL_SetWindowSize(window, (int)(vid_w * scale), (int)(vid_h * scale));
SDL_SetWindowPosition(window, SDL_WINDOWPOS_CENTERED_DISPLAY(display),
SDL_WINDOWPOS_CENTERED_DISPLAY(display));
}
static void toggle_fullscreen(void)
{
fullscreen = !fullscreen;
SDL_SetWindowFullscreen(window, fullscreen);
}
static void cycle_scale(void)
{
uint8_t next;
if (fullscreen)
return;
next = cur_scale + 1;
if (next > max_scale(vid_w, vid_h))
next = 1;
set_scale(next);
}
uint8_t skele_video_init(skele_video_config_t cfg)
{
SDL_DisplayID display;
SDL_WindowFlags flags = 0;
const SDL_DisplayMode *mode;
uint16_t window_w, window_h, aw, ah;
if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMEPAD)) {
stk_log(STK_LOG_ERROR, "video: SDL_Init failed: %s",
SDL_GetError());
return SKELE_INIT_FAILURE;
}
if (cfg.flags & SKELE_VIDEO_FULLSCREEN)
flags |= SDL_WINDOW_FULLSCREEN;
if (cfg.flags & SKELE_VIDEO_BORDERLESS)
flags |= SDL_WINDOW_BORDERLESS;
if (cfg.flags & SKELE_VIDEO_RESIZABLE)
flags |= SDL_WINDOW_RESIZABLE;
if (cfg.flags & SKELE_VIDEO_HIGHDPI)
flags |= SDL_WINDOW_HIGH_PIXEL_DENSITY;
display = SDL_GetPrimaryDisplay();
vid_w =
cfg.render_width ? cfg.render_width : SKELE_DEFAULT_RENDER_WIDTH;
vid_h =
cfg.render_height ? cfg.render_height : SKELE_DEFAULT_RENDER_HEIGHT;
vid_total = (uint32_t)(vid_w * vid_h);
if (cfg.window_width && cfg.window_height) {
window_w = cfg.window_width;
window_h = cfg.window_height;
cur_scale = 1;
} else {
mode = SDL_GetCurrentDisplayMode(display);
if (!mode) {
stk_log(STK_LOG_ERROR,
"video: SDL_GetCurrentDisplayMode failed: %s",
SDL_GetError());
SDL_Quit();
return SKELE_INIT_FAILURE;
}
aw = (uint16_t)((mode->w * 3) / 4);
ah = (uint16_t)((mode->h * 3) / 4);
cur_scale = 1;
while ((vid_w * (cur_scale + 1)) <= aw &&
(vid_h * (cur_scale + 1)) <= ah)
cur_scale++;
window_w = vid_w * cur_scale;
window_h = vid_h * cur_scale;
}
window = SDL_CreateWindow("skele", window_w, window_h,
flags | SDL_WINDOW_HIDDEN);
if (!window) {
stk_log(STK_LOG_ERROR, "video: SDL_CreateWindow failed: %s",
SDL_GetError());
SDL_Quit();
return SKELE_INIT_FAILURE;
}
SDL_SetWindowPosition(window, SDL_WINDOWPOS_CENTERED_DISPLAY(display),
SDL_WINDOWPOS_CENTERED_DISPLAY(display));
if (cfg.flags & SKELE_VIDEO_FULLSCREEN)
fullscreen = 1;
renderer = SDL_CreateRenderer(window, NULL);
if (!renderer) {
stk_log(STK_LOG_ERROR, "video: SDL_CreateRenderer failed: %s",
SDL_GetError());
SDL_DestroyWindow(window);
SDL_Quit();
return SKELE_INIT_FAILURE;
}
texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_INDEX8,
SDL_TEXTUREACCESS_STREAMING, vid_w, vid_h);
if (!texture) {
stk_log(STK_LOG_ERROR, "video: SDL_CreateTexture failed: %s",
SDL_GetError());
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
return SKELE_INIT_FAILURE;
}
sdl_pal = SDL_CreatePalette(SKELE_PALETTE_COLORS);
if (!sdl_pal) {
stk_log(STK_LOG_ERROR, "video: SDL_CreatePalette failed: %s",
SDL_GetError());
SDL_DestroyTexture(texture);
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
return SKELE_INIT_FAILURE;
}
SDL_SetTexturePalette(texture, sdl_pal);
{
SDL_Color black[SKELE_PALETTE_COLORS];
uint16_t i;
memset(black, 0, sizeof(black));
for (i = 0; i < SKELE_PALETTE_COLORS; i++)
black[i].a = 255;
SDL_SetPaletteColors(sdl_pal, black, 0, SKELE_PALETTE_COLORS);
}
SDL_SetTextureScaleMode(texture, SDL_SCALEMODE_NEAREST);
SDL_SetRenderVSync(renderer, 1);
SDL_ShowWindow(window);
return SKELE_INIT_SUCCESS;
}
void skele_video_shutdown(void)
{
if (sdl_pal)
SDL_DestroyPalette(sdl_pal);
if (texture)
SDL_DestroyTexture(texture);
if (renderer)
SDL_DestroyRenderer(renderer);
if (window)
SDL_DestroyWindow(window);
SDL_Quit();
sdl_pal = NULL;
texture = NULL;
renderer = NULL;
window = NULL;
vid_w = 0;
vid_h = 0;
vid_total = 0;
cur_scale = 1;
fullscreen = 0;
}
void skele_video_present(void) { SDL_RenderPresent(renderer); }
void skele_video_toggle_fullscreen(void) { toggle_fullscreen(); }
void skele_video_cycle_scale(void) { cycle_scale(); }
void skele_video_set_mouse_grab(uint8_t grab)
{
SDL_SetWindowMouseGrab(window, grab ? true : false);
SDL_SetWindowRelativeMouseMode(window, grab ? true : false);
}
void skele_palette_set(skele_palette_t pal)
{
SDL_Color colors[SKELE_PALETTE_COLORS];
uint16_t i;
uint32_t c;
for (i = 0; i < SKELE_PALETTE_COLORS; i++) {
c = pal[i];
colors[i].r = (uint8_t)(c >> 16);
colors[i].g = (uint8_t)(c >> 8);
colors[i].b = (uint8_t)(c);
colors[i].a = 255;
}
SDL_SetPaletteColors(sdl_pal, colors, 0, SKELE_PALETTE_COLORS);
}
void skele_palette_set_index(uint8_t index, uint32_t color)
{
SDL_Color c;
c.r = (uint8_t)(color >> 16);
c.g = (uint8_t)(color >> 8);
c.b = (uint8_t)(color);
c.a = 255;
SDL_SetPaletteColors(sdl_pal, &c, index, 1);
}
void skele_video_blit(uint8_t *pixels)
{
SDL_UpdateTexture(texture, NULL, pixels, vid_w);
SDL_RenderTexture(renderer, texture, NULL, NULL);
}
void skele_video_set_title(const char *title)
{
SDL_SetWindowTitle(window, title);
}
+35
View File
@@ -0,0 +1,35 @@
#define _POSIX_C_SOURCE 199309L
#include "clock.h"
#include <signal.h>
#include <time.h>
static void (*signal_cb)(void) = NULL;
static void handle_signal(int sig)
{
(void)sig;
if (signal_cb)
signal_cb();
}
void skele_clock_init(void (*on_signal)(void))
{
signal_cb = on_signal;
signal(SIGINT, handle_signal);
signal(SIGTERM, handle_signal);
}
uint64_t skele_time_ns(void)
{
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
return (uint64_t)(ts.tv_sec * 1000000000ULL + ts.tv_nsec);
}
void skele_sleep_ns(uint64_t ns)
{
struct timespec ts;
ts.tv_sec = (time_t)(ns / 1000000000ULL);
ts.tv_nsec = (long)(ns % 1000000000ULL);
nanosleep(&ts, NULL);
}
+37
View File
@@ -0,0 +1,37 @@
#include "clock.h"
#include <windows.h>
static void (*signal_cb)(void) = NULL;
static LARGE_INTEGER perf_freq;
static BOOL WINAPI handle_ctrl(DWORD type)
{
(void)type;
if (signal_cb)
signal_cb();
return TRUE;
}
void skele_clock_init(void (*on_signal)(void))
{
signal_cb = on_signal;
QueryPerformanceFrequency(&perf_freq);
SetConsoleCtrlHandler(handle_ctrl, TRUE);
}
uint64_t skele_time_ns(void)
{
LARGE_INTEGER cnt;
QueryPerformanceCounter(&cnt);
return (uint64_t)(cnt.QuadPart * 1000000000ULL / perf_freq.QuadPart);
}
void skele_sleep_ns(uint64_t ns)
{
HANDLE timer = CreateWaitableTimer(NULL, TRUE, NULL);
LARGE_INTEGER li;
li.QuadPart = -(LONGLONG)(ns / 100);
SetWaitableTimer(timer, &li, 0, NULL, NULL, FALSE);
WaitForSingleObject(timer, INFINITE);
CloseHandle(timer);
}
+51
View File
@@ -0,0 +1,51 @@
#include "skele.h"
#include <stk/stk.h>
#include <stk/stk_log.h>
uint64_t skele_tick_ns = 1000000000ULL / SKELE_DEFAULT_TICK_RATE;
static uint8_t stk_initialized = 0;
const char *skele_version(void) { return "0.0.0"; }
void skele_set_tick_rate(uint8_t rate)
{
skele_tick_ns = 1000000000ULL / (rate ? rate : SKELE_DEFAULT_TICK_RATE);
}
uint8_t skele_init(void) { return SKELE_INIT_SUCCESS; }
void skele_shutdown(void) {}
void skele_tick(void) {}
uint8_t skele_stk_setup(void)
{
if (stk_initialized)
return SKELE_INIT_SUCCESS;
stk_set_log_prefix("skele");
stk_set_module_init_fn("skele_mod_init");
stk_set_module_shutdown_fn("skele_mod_shutdown");
stk_set_module_name_fn("skele_mod_name");
stk_set_module_version_fn("skele_mod_ver");
stk_set_module_description_fn("skele_mod_desc");
stk_set_module_deps_sym("skele_mod_deps");
if (stk_init() != STK_INIT_SUCCESS) {
stk_log(STK_LOG_ERROR, "failed to initialize stk");
return SKELE_INIT_FAILURE;
}
stk_initialized = 1;
stk_log(STK_LOG_INFO, "skele v%s", SKELE_VERSION);
return SKELE_INIT_SUCCESS;
}
void skele_stk_teardown(void)
{
if (!stk_initialized)
return;
stk_shutdown();
stk_initialized = 0;
}