/* ** Copyright (c) 2022 KikooDX ** ** Permission is hereby granted, free of charge, to any person obtaining a copy ** of this software and associated documentation files (the "Software"), to ** deal in the Software without restriction, including without limitation the ** rights to use, copy, modify, merge, publish, distribute, sublicense, and/or ** sell copies of the Software, and to permit persons to whom the Software is ** furnished to do so, subject to the following conditions: ** ** The above copyright notice and this permission notice shall be included in ** all copies or substantial portions of the Software. ** ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ** FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS ** IN THE SOFTWARE. */ #ifndef LZY_H_ #define LZY_H_ #ifdef __cplusplus extern "C" { #endif #include #ifdef FXCG50 #include typedef void LZY_Music; typedef void LZY_Sound; enum LZY_ScanCode { LZYK_LEFT = KEY_LEFT, LZYK_RIGHT = KEY_RIGHT, LZYK_UP = KEY_UP, LZYK_DOWN = KEY_DOWN, LZYK_O = KEY_SHIFT, LZYK_X = KEY_OPTN, }; #else /* end FXCG50, begin SDL2 */ #ifndef LZY_SDL_MIXER_INCLUDE #define LZY_SDL_MIXER_INCLUDE #endif #include LZY_SDL_MIXER_INCLUDE enum LZY_ScanCode { LZYK_LEFT, LZYK_RIGHT, LZYK_UP, LZYK_DOWN, LZYK_O, LZYK_X, LZYK_COUNT, }; typedef Mix_Music LZY_Music; typedef Mix_Chunk LZY_Sound; #endif /* SDL2 */ enum LZY_EventType { LZY_QUIT, LZY_KEYDOWN, LZY_KEYUP, }; typedef struct LZY_KeyEvent { unsigned int scancode; int down; } LZY_KeyEvent; typedef union LZY_EventUnion { LZY_KeyEvent key; } LZY_EventUnion; typedef struct LZY_Event { int type; LZY_EventUnion u; } LZY_Event; int LZY_Init(const char *title, int target_fps, const char *tset_path, const char *font_path); void LZY_Quit(void); int LZY_DrawBegin(void); int LZY_DrawEnd(void); void LZY_DrawSetColor(uint8_t r, uint8_t g, uint8_t b); void LZY_DrawSetColorNone(void); int LZY_DrawClear(void); int LZY_DrawPoint(int x, int y); int LZY_DrawLine(int x0, int y0, int x1, int y1); int LZY_DrawRect(int x, int y, int w, int h); int LZY_FillRect(int x, int y, int w, int h); int LZY_DrawTile(unsigned int id, int x, int y); int LZY_DrawTileEx(unsigned int id, int x, int y, unsigned int w, unsigned int h); int LZY_DrawChar(unsigned char chr, int x, int y); int LZY_DrawText(int x, int y, const char *text); int LZY_DrawTextF(int x, int y, const char *fmt, ...); LZY_Music *LZY_MusicLoad(const char *path); int LZY_MusicDestroy(LZY_Music *music); int LZY_MusicPlay(LZY_Music *music, int loops); LZY_Sound *LZY_SoundLoad(const char *path); int LZY_SoundDestroy(LZY_Sound *sound); void LZY_SoundSetVolume(LZY_Sound *sound, float volume); int LZY_SoundPlay(LZY_Sound *sound, int loops); int LZY_PollEvent(LZY_Event *); void LZY_CycleEvents(void); int LZY_KeyDown(unsigned int key); int LZY_ShouldQuit(void); void LZY_Log(const char *fmt, ...); int LZY_LogError(int rv); const char *LZY_GetError(void); #ifdef __has_cpp_attribute [[deprecated("renamed to LZY_FillRect")]] #endif int LZY_DrawFillRect(int x, int y, int w, int h); #ifdef __cplusplus } #endif #endif /* LZY_H_ */ /* implementation */ #ifdef LZY_IMPLEMENTATION #undef LZY_IMPLEMENTATION #ifndef LZY_SDL_INCLUDE #define LZY_SDL_INCLUDE #endif #ifndef LZY_SDL_IMAGE_INCLUDE #define LZY_SDL_IMAGE_INCLUDE #endif #ifndef LZY_SDL_MIXER_INCLUDE #define LZY_SDL_MIXER_INCLUDE #endif #ifndef LZY_DISPLAY_WIDTH #define LZY_DISPLAY_WIDTH 396 #endif #ifndef LZY_DISPLAY_HEIGHT #define LZY_DISPLAY_HEIGHT 224 #endif #ifndef LZY_TILE_SIZE #define LZY_TILE_SIZE 16 #endif #ifndef LZY_CHR_WIDTH #define LZY_CHR_WIDTH LZY_TILE_SIZE #endif #ifndef LZY_CHR_HEIGHT #define LZY_CHR_HEIGHT LZY_TILE_SIZE #endif #ifndef LZY_FIRST_CHR #define LZY_FIRST_CHR ' ' #endif #include int LZY_DrawLine(int x0, int y0, int x1, int y1) { int dx, dy, sx, sy, err, e2; int rc = 0; dx = x1 - x0; dx = (dx < 0) ? (-dx) : (dx); dy = y1 - y0; dy = (dy < 0) ? (dy) : (-dy); sx = (x0 < x1) ? (1) : (-1); sy = (y0 < y1) ? (1) : (-1); err = dx + dy; for (;;) { if (LZY_DrawPoint(x0, y0)) rc = -1; if (x0 == x1 && y0 == y1) break; e2 = 2 * err; if (e2 >= dy) { err += dy; x0 += sx; } if (e2 <= dx) { err += dx; y0 += sy; } } return rc; } int LZY_DrawTextF(int x, int y, const char *fmt, ...) { char buf[256] = {0}; va_list args; va_start(args, fmt); vsnprintf(buf, sizeof(buf) - 1, fmt, args); va_end(args); return LZY_DrawText(x, y, buf); } int LZY_LogError(int rv) { LZY_Log("%s", LZY_GetError()); return rv; } int LZY_DrawFillRect(int x, int y, int w, int h) { return LZY_FillRect(x, y, w, h); } #ifdef FXCG50 #include #include #include #include #include static const int draw_off_x = (DWIDTH - LZY_DISPLAY_WIDTH) / 2; static const int draw_off_y = (DHEIGHT - LZY_DISPLAY_HEIGHT) / 2; static color_t draw_color = C_BLACK; static int should_quit = 0; static int timer = 0; static volatile int has_ticked = 0; static unsigned int tset_width, tset_height; static unsigned int font_width, font_height; static int timer_callback(volatile int *); static int _LZY_Sign(int n) { return (n > 0) - (n < 0); } int LZY_Init(const char *title, int target_fps, const char *tset_path, const char *font_path) { (void)title, (void)target_fps, (void)tset_path; extern bopti_image_t LZY_GINT_TILESET; extern bopti_image_t LZY_GINT_FONT; tset_width = LZY_GINT_TILESET.width / LZY_TILE_SIZE; tset_height = LZY_GINT_TILESET.height / LZY_TILE_SIZE; font_width = LZY_GINT_FONT.width / LZY_CHR_WIDTH; font_height = LZY_GINT_FONT.height / LZY_CHR_HEIGHT; if (target_fps > 0) { timer = timer_configure(TIMER_ANY, 1000000 / target_fps, GINT_CALL(timer_callback, &has_ticked)); timer_start(timer); } return 0; } static int timer_callback(volatile int *arg) { *arg += 1; return 0; } void LZY_Quit(void) { if (timer) { timer_stop(timer); timer = 0; } } int LZY_DrawBegin(void) { return 0; } int LZY_DrawEnd(void) { dupdate(); while (timer && !has_ticked) sleep(); has_ticked = 0; return 0; } void LZY_DrawSetColor(uint8_t r, uint8_t g, uint8_t b) { draw_color = C_RGB(r / 8, g / 8, b / 8); } void LZY_DrawSetColorNone(void) { draw_color = C_NONE; } int LZY_DrawClear(void) { dclear(draw_color); return 0; } int LZY_DrawPoint(int x, int y) { dpixel(x + draw_off_x, y + draw_off_y, draw_color); return 0; } int LZY_DrawRect(int x, int y, int w, int h) { w += w == 0; h += h == 0; x += draw_off_x; y += draw_off_y; drect_border(x, y, x + w - _LZY_Sign(w), y + h - _LZY_Sign(h), C_NONE, 1, draw_color); return 0; } int LZY_FillRect(int x, int y, int w, int h) { w += w == 0; h += h == 0; x += draw_off_x; y += draw_off_y; drect(x, y, x + w - _LZY_Sign(w), y + h - _LZY_Sign(h), draw_color); return 0; } int LZY_DrawTile(unsigned int id, int x, int y) { extern bopti_image_t LZY_GINT_TILESET; int ix, iy; if (id >= tset_width * tset_height) return -1; x += draw_off_x; y += draw_off_y; ix = (id % tset_width) * LZY_TILE_SIZE; iy = (id / tset_width) * LZY_TILE_SIZE; dsubimage(x, y, &LZY_GINT_TILESET, ix, iy, LZY_TILE_SIZE, LZY_TILE_SIZE, DIMAGE_NONE); return 0; } int LZY_DrawTileEx(unsigned int id, int x, int y, unsigned int w, unsigned int h) { extern bopti_image_t LZY_GINT_TILESET; int ix, iy; if (w * h == 0) return -1; x += draw_off_x; y += draw_off_y; ix = id % tset_width; iy = id / tset_width; if (ix >= (int)tset_width || ix + w - 1 >= tset_width || iy >= (int)tset_height || iy + h - 1 >= tset_height) return -1; ix *= LZY_TILE_SIZE; iy *= LZY_TILE_SIZE; dsubimage(x, y, &LZY_GINT_TILESET, ix, iy, w * LZY_TILE_SIZE, h * LZY_TILE_SIZE, DIMAGE_NONE); return 0; } int LZY_DrawChar(unsigned char chr, int x, int y) { extern bopti_image_t LZY_GINT_FONT; const unsigned int id = (unsigned int)chr - LZY_FIRST_CHR; int ix, iy; if (id >= font_width * font_height) return -1; x += draw_off_x; y += draw_off_y; ix = (id % font_width) * LZY_CHR_WIDTH; iy = (id / font_width) * LZY_CHR_HEIGHT; dsubimage(x, y, &LZY_GINT_FONT, ix, iy, LZY_CHR_WIDTH, LZY_CHR_HEIGHT, DIMAGE_NONE); return 0; } int LZY_DrawText(int x, int y, const char *text) { int err = 0; if (text == NULL) return -1; for (; *text != '\0'; text++) { const int rc = LZY_DrawChar(*text, x, y); if (rc) err = rc - 1; x += LZY_CHR_WIDTH; } return err; } LZY_Music *LZY_MusicLoad(const char *path) { (void)path; return NULL; } int LZY_MusicDestroy(LZY_Music *music) { (void)music; return -1; } int LZY_MusicPlay(LZY_Music *music, int loops) { (void)music, (void)loops; return -1; } LZY_Sound *LZY_SoundLoad(const char *path) { (void)path; return NULL; } int LZY_SoundDestroy(LZY_Sound *sound) { (void)sound; return -1; } void LZY_SoundSetVolume(LZY_Sound *sound, float volume) { (void)sound, (void)volume; } int LZY_SoundPlay(LZY_Sound *sound, int loops) { (void)sound, (void)loops; return -1; } int LZY_PollEvent(LZY_Event *e) { for (;;) { const key_event_t gk_e = pollevent(); switch (gk_e.type) { case KEYEV_NONE: return 0; case KEYEV_DOWN: e->type = LZY_KEYDOWN; e->u.key.scancode = gk_e.key; if (gk_e.key == KEY_EXIT) should_quit = 1; return 1; case KEYEV_UP: e->type = LZY_KEYUP; e->u.key.scancode = gk_e.key; return 1; default: break; } } } void LZY_CycleEvents(void) { clearevents(); should_quit = should_quit || keydown(KEY_EXIT); } int LZY_KeyDown(unsigned int key) { return keydown(key); } int LZY_ShouldQuit(void) { return should_quit; } void LZY_Log(const char *fmt, ...) { (void)fmt; } const char *LZY_GetError(void) { return NULL; } #else /* end FXCG50, begin SDL2 */ #include LZY_SDL_INCLUDE #include LZY_SDL_IMAGE_INCLUDE #include LZY_SDL_MIXER_INCLUDE #include #include #include #include static const SDL_Scancode sc[LZYK_COUNT * 2] = { SDL_SCANCODE_LEFT, SDL_SCANCODE_A, SDL_SCANCODE_RIGHT, SDL_SCANCODE_D, SDL_SCANCODE_UP, SDL_SCANCODE_W, SDL_SCANCODE_DOWN, SDL_SCANCODE_S, SDL_SCANCODE_Z, SDL_SCANCODE_J, SDL_SCANCODE_X, SDL_SCANCODE_K, }; static const SDL_Scancode fullscreen_sc = SDL_SCANCODE_F11; static const char *error = NULL; static SDL_Window *window = NULL; static SDL_Renderer *renderer = NULL; static SDL_Texture *target = NULL; static SDL_Texture *tset = NULL; static SDL_Texture *font = NULL; static int tset_width, tset_height, font_width, font_height; static int should_quit = 0; static int input[LZYK_COUNT] = {0}; static int fps_limiter = 0; static uint64_t min_dt; static uint64_t next_time; static char *datadir; static char *path_relative(const char *path) { char *buf; if (datadir == NULL) { error = "datadir is NULL"; return NULL; } if (path == NULL) { error = "path is NULL"; return NULL; } buf = calloc(strlen(datadir) + strlen(path) + 1, sizeof(char)); if (buf == NULL) { error = "calloc failed"; return NULL; } strcpy(buf, datadir); strcat(buf, path); return buf; } int LZY_Init(const char *title, int target_fps, const char *tset_path, const char *font_path) { const int img_flags = IMG_INIT_PNG; char *buf; datadir = SDL_GetBasePath(); if (datadir == NULL) { error = SDL_GetError(); return -1; } if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0) { error = SDL_GetError(); return -1; } if ((IMG_Init(img_flags) & img_flags) != img_flags) { error = IMG_GetError(); return -1; } if (Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 2, 2048) < 0) { error = Mix_GetError(); return -1; } SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, 0); window = SDL_CreateWindow(title, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, LZY_DISPLAY_WIDTH, LZY_DISPLAY_HEIGHT, SDL_WINDOW_RESIZABLE); if (window == NULL) { error = SDL_GetError(); return -1; } SDL_SetWindowMinimumSize(window, LZY_DISPLAY_WIDTH, LZY_DISPLAY_HEIGHT); renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED); if (renderer == NULL) { error = SDL_GetError(); return -1; } target = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGB888, SDL_TEXTUREACCESS_TARGET, LZY_DISPLAY_WIDTH, LZY_DISPLAY_HEIGHT); if (target == NULL) { error = SDL_GetError(); return -1; } buf = path_relative(tset_path); if (buf == NULL) return -1; tset = IMG_LoadTexture(renderer, buf); if (tset == NULL) { error = IMG_GetError(); return -1; } free(buf); if (SDL_QueryTexture(tset, NULL, NULL, &tset_width, &tset_height) < 0) { error = SDL_GetError(); return -1; } tset_width /= LZY_TILE_SIZE; tset_height /= LZY_TILE_SIZE; buf = path_relative(font_path); if (buf == NULL) return -1; font = IMG_LoadTexture(renderer, buf); if (font == NULL) { error = IMG_GetError(); return -1; } free(buf); if (SDL_QueryTexture(font, NULL, NULL, &font_width, &font_height) < 0) { error = SDL_GetError(); return -1; } font_width /= LZY_CHR_WIDTH; font_height /= LZY_CHR_HEIGHT; fps_limiter = target_fps > 0; if (fps_limiter) { min_dt = 1000 / target_fps; next_time = SDL_GetTicks64(); } return 0; } void LZY_Quit(void) { if (datadir != NULL) { SDL_free(datadir); datadir = NULL; } if (tset != NULL) { SDL_DestroyTexture(tset); tset = NULL; } if (target != NULL) { SDL_DestroyTexture(target); target = NULL; } if (renderer != NULL) { SDL_DestroyRenderer(renderer); renderer = NULL; } if (window != NULL) { SDL_DestroyWindow(window); window = NULL; } Mix_Quit(); IMG_Quit(); SDL_Quit(); } int LZY_DrawBegin(void) { if (fps_limiter) next_time += min_dt; if (SDL_SetRenderTarget(renderer, target) < 0) { error = SDL_GetError(); return -1; } return 0; } int LZY_DrawEnd(void) { int win_w, win_h, off_x, off_y; float ratio_w, ratio_h, scale; SDL_Rect src, dst; if (SDL_SetRenderTarget(renderer, NULL)) { error = SDL_GetError(); return -1; } LZY_DrawSetColor(0x00, 0x00, 0x00); if (LZY_DrawClear()) return -2; SDL_GetWindowSize(window, &win_w, &win_h); ratio_w = (float)win_w / LZY_DISPLAY_WIDTH; ratio_h = (float)win_h / LZY_DISPLAY_HEIGHT; scale = (ratio_w < ratio_h) ? (ratio_w) : (ratio_h); if (scale > 1.0) scale = (int)scale; off_x = (win_w - LZY_DISPLAY_WIDTH * scale) / 2; off_y = (win_h - LZY_DISPLAY_HEIGHT * scale) / 2; src.x = 0; src.y = 0; src.w = LZY_DISPLAY_WIDTH; src.h = LZY_DISPLAY_HEIGHT; dst.x = off_x; dst.y = off_y; dst.w = LZY_DISPLAY_WIDTH * scale; dst.h = LZY_DISPLAY_HEIGHT * scale; if (SDL_RenderCopy(renderer, target, &src, &dst) < 0) { error = SDL_GetError(); return -3; } SDL_RenderPresent(renderer); if (fps_limiter) { const uint64_t cur_time = SDL_GetTicks64(); if (next_time <= cur_time) next_time = cur_time; else SDL_Delay(next_time - cur_time); } return 0; } void LZY_DrawSetColor(uint8_t r, uint8_t g, uint8_t b) { SDL_SetRenderDrawColor(renderer, r, g, b, 0xff); } void LZY_DrawSetColorNone(void) { SDL_SetRenderDrawColor(renderer, 0x00, 0x00, 0x00, 0x00); } int LZY_DrawClear(void) { if (SDL_RenderClear(renderer) < 0) { error = SDL_GetError(); return -1; } return 0; } int LZY_DrawPoint(int x, int y) { if (SDL_RenderDrawPoint(renderer, x, y) < 0) { error = SDL_GetError(); return -1; } return 0; } int LZY_DrawRect(int x, int y, int w, int h) { const SDL_Rect rect = {x, y, w + (w == 0), h + (h == 0)}; if (SDL_RenderDrawRect(renderer, &rect) < 0) { error = SDL_GetError(); return -2; } return 0; } int LZY_FillRect(int x, int y, int w, int h) { const SDL_Rect rect = {x, y, w + (w == 0), h + (h == 0)}; if (SDL_RenderFillRect(renderer, &rect) < 0) { error = SDL_GetError(); return -2; } return 0; } int LZY_DrawTile(unsigned int id, int x, int y) { SDL_Rect src, dst; if (id >= (unsigned int)(tset_width * tset_height)) { error = "id exceeds boundaries"; return -1; } src.x = (id % tset_width) * LZY_TILE_SIZE; src.y = (id / tset_width) * LZY_TILE_SIZE; src.w = LZY_TILE_SIZE; src.h = LZY_TILE_SIZE; dst.x = x; dst.y = y; dst.w = LZY_TILE_SIZE; dst.h = LZY_TILE_SIZE; if (SDL_RenderCopy(renderer, tset, &src, &dst) < 0) { error = SDL_GetError(); return -2; } return 0; } int LZY_DrawTileEx(unsigned int id, int x, int y, unsigned int w, unsigned int h) { SDL_Rect src, dst; if (w * h == 0) { error = "tile size can't be 0"; return -1; } if (id >= (unsigned int)(tset_width * tset_height)) { error = "id exceeds boundaries"; return -1; } src.x = id % tset_width; src.y = id / tset_width; if (src.x >= tset_width || src.x + w - 1 >= (unsigned int)tset_width || src.y >= tset_height || src.y + h - 1 >= (unsigned int)tset_height) { error = "tile is not in tileset"; return -1; } src.x *= LZY_TILE_SIZE; src.y *= LZY_TILE_SIZE; src.w = w * LZY_TILE_SIZE; src.h = h * LZY_TILE_SIZE; dst.x = x; dst.y = y; dst.w = w * LZY_TILE_SIZE; dst.h = h * LZY_TILE_SIZE; if (SDL_RenderCopy(renderer, tset, &src, &dst) < 0) { error = SDL_GetError(); return -1; } return 0; } int LZY_DrawChar(unsigned char chr, int x, int y) { const unsigned int id = (unsigned int)chr - LZY_FIRST_CHR; SDL_Rect src, dst; if (id >= (unsigned int)(font_width * font_height)) { error = "chr exceeds boundaries"; return -1; } src.x = (id % font_width) * LZY_CHR_WIDTH; src.y = (id / font_width) * LZY_CHR_HEIGHT; src.w = LZY_CHR_WIDTH; src.h = LZY_CHR_HEIGHT; dst.x = x; dst.y = y; dst.w = LZY_CHR_WIDTH; dst.h = LZY_CHR_HEIGHT; if (SDL_RenderCopy(renderer, font, &src, &dst) < 0) { error = SDL_GetError(); return -2; } return 0; } int LZY_DrawText(int x, int y, const char *text) { int err = 0; if (text == NULL) { error = "text is NULL"; return -1; } for (; *text != '\0'; text++) { const int rc = LZY_DrawChar(*text, x, y); if (rc) err = rc - 1; x += LZY_CHR_WIDTH; } return err; } LZY_Music *LZY_MusicLoad(const char *path) { char *buf; LZY_Music *music; buf = path_relative(path); if (buf == NULL) return NULL; music = Mix_LoadMUS(buf); if (music == NULL) error = Mix_GetError(); free(buf); return music; } int LZY_MusicDestroy(LZY_Music *music) { if (music == NULL) { error = "music is NULL"; return -1; } Mix_FreeMusic(music); return 0; } int LZY_MusicPlay(LZY_Music *music, int loops) { if (music == NULL) { error = "music is NULL"; return -1; } if (Mix_PlayMusic(music, loops) < 0) { error = Mix_GetError(); return -2; } return 0; } LZY_Sound *LZY_SoundLoad(const char *path) { char *buf; LZY_Sound *sound; buf = path_relative(path); if (buf == NULL) return NULL; sound = Mix_LoadWAV(buf); if (sound == NULL) error = Mix_GetError(); free(buf); return sound; } int LZY_SoundDestroy(LZY_Sound *sound) { if (sound == NULL) { error = "sound is NULL"; return -1; } Mix_FreeChunk(sound); return 0; } void LZY_SoundSetVolume(LZY_Sound *sound, float volume) { if (sound != NULL) Mix_VolumeChunk(sound, MIX_MAX_VOLUME * volume); } int LZY_SoundPlay(LZY_Sound *sound, int loops) { if (sound == NULL) { error = "sound is NULL"; return -1; } if (Mix_PlayChannel(-1, sound, loops) < 0) { error = Mix_GetError(); return -2; } return 0; } int LZY_PollEvent(LZY_Event *e) { SDL_Event sdl_e; while (SDL_PollEvent(&sdl_e) != 0) { switch (sdl_e.type) { case SDL_QUIT: e->type = LZY_QUIT; should_quit = 1; return 1; case SDL_KEYDOWN: { if (!sdl_e.key.repeat) { int i = LZYK_COUNT; while (i-- > 0) { if (sc[i * 2] == sdl_e.key.keysym.scancode || sc[i * 2 + 1] == sdl_e.key.keysym.scancode) { e->type = LZY_KEYDOWN; e->u.key.scancode = i; input[i] = 1; return 1; } } if (sdl_e.key.keysym.scancode == fullscreen_sc) { const unsigned int flag = SDL_WINDOW_FULLSCREEN; const unsigned int fullscreen = SDL_GetWindowFlags(window) & flag; SDL_SetWindowFullscreen(window, !fullscreen); } } } break; case SDL_KEYUP: { int i = LZYK_COUNT; while (i-- > 0) { if (sc[i * 2] == sdl_e.key.keysym.scancode || sc[i * 2 + 1] == sdl_e.key.keysym.scancode) { e->type = LZY_KEYUP; e->u.key.scancode = i; input[i] = 0; return 1; } } } break; default: break; } } return 0; } void LZY_CycleEvents(void) { LZY_Event e; while (LZY_PollEvent(&e) != 0) ; } int LZY_KeyDown(unsigned int key) { if (key >= LZYK_COUNT) return 0; return input[key]; } int LZY_ShouldQuit(void) { return should_quit; } void LZY_Log(const char *fmt, ...) { char buf[2048] = {0}; va_list args; va_start(args, fmt); vsnprintf(buf, sizeof(buf) - 1, fmt, args); va_end(args); SDL_Log("%s", buf); } const char *LZY_GetError(void) { return error; } #endif /* SDL2 */ #endif /* LZY_IMPLEMENTATION */