lzy/inc/lzy.h

326 lines
6.1 KiB
C

#ifndef LZY_H_
#define LZY_H_
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#define LZY_UNUSED(x) (void)(x)
int LZY_Init(const char *title, int target_fps);
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_DrawRect(int x, int y, unsigned int w, unsigned int h);
int LZY_DrawFillRect(int x, int y, unsigned int w, unsigned int h);
void LZY_CycleEvents(void);
int LZY_KeyDown(unsigned int key);
int LZY_ShouldQuit(void);
void LZY_Log(const char *msg);
const char *LZY_GetError(void);
#ifdef FXCG50
#include <gint/keycodes.h>
enum LZY_ScanCode {
LZYK_LEFT = KEY_LEFT,
LZYK_RIGHT = KEY_RIGHT,
LZYK_UP = KEY_UP,
LZYK_DOWN = KEY_DOWN,
};
#else /* end FXCG50, begin SDL2 */
#include <SDL.h>
enum LZY_ScanCode {
LZYK_LEFT,
LZYK_RIGHT,
LZYK_UP,
LZYK_DOWN,
LZYK_COUNT,
};
#endif /* SDL2 */
#ifdef __cplusplus
}
#endif
#endif /* LZY_H_ */
/* implementation */
#ifdef LZY_IMPLEMENTATION
#ifndef LZY_TILE_SIZE
#define LZY_TILE_SIZE 16
#endif
#ifndef LZY_DISPLAY_WIDTH
#define LZY_DISPLAY_WIDTH 396
#endif
#ifndef LZY_DISPLAY_HEIGHT
#define LZY_DISPLAY_HEIGHT 224
#endif
#ifdef FXCG50
#include <gint/cpu.h>
#include <gint/display.h>
#include <gint/keyboard.h>
#include <gint/timer.h>
#include <stdint.h>
static color_t draw_color = C_BLACK;
static int should_quit = 0;
static int timer = 0;
static volatile int has_ticked = 0;
static int timer_callback(volatile int *);
int LZY_Init(const char *title, int target_fps) {
LZY_UNUSED(title);
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_DrawRect(int x, int y, unsigned int w, unsigned int h) {
if (w < 1 || h < 1)
return -1;
drect_border(x, y, x + w - 1, y + h - 1, C_NONE, 1, draw_color);
return 0;
}
int LZY_DrawFillRect(int x, int y, unsigned int w, unsigned int h) {
if (w < 1 || h < 1)
return -1;
drect(x, y, x + w - 1, y + h - 1, draw_color);
return 0;
}
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 *msg) {
LZY_UNUSED(msg);
}
const char *LZY_GetError(void) {
return NULL;
}
#else /* end FXCG50, begin SDL2 */
#include <SDL.h>
#include <stdint.h>
static const char *error = NULL;
static SDL_Window *window = NULL;
static SDL_Renderer *renderer = NULL;
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;
int LZY_Init(const char *title, int target_fps) {
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
error = SDL_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_SHOWN);
if (window == NULL) {
error = SDL_GetError();
return -2;
}
SDL_SetWindowMinimumSize(window, LZY_DISPLAY_WIDTH, LZY_DISPLAY_HEIGHT);
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
if (renderer == NULL) {
error = SDL_GetError();
return -3;
}
fps_limiter = target_fps > 0;
if (fps_limiter) {
min_dt = 1000 / target_fps;
next_time = SDL_GetTicks64();
}
return 0;
}
void LZY_Quit(void) {
if (renderer != NULL) {
SDL_DestroyRenderer(renderer);
renderer = NULL;
}
if (window != NULL) {
SDL_DestroyWindow(window);
window = NULL;
}
SDL_Quit();
}
int LZY_DrawBegin(void) {
if (fps_limiter)
next_time += min_dt;
return 0;
}
int LZY_DrawEnd(void) {
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_DrawRect(int x, int y, unsigned int w, unsigned int h) {
const SDL_Rect rect = {x, y, w, h};
if (SDL_RenderDrawRect(renderer, &rect) < 0) {
error = SDL_GetError();
return -1;
}
return 0;
}
int LZY_DrawFillRect(int x, int y, unsigned int w, unsigned int h) {
const SDL_Rect rect = {x, y, w, h};
if (SDL_RenderFillRect(renderer, &rect) < 0) {
error = SDL_GetError();
return -1;
}
return 0;
}
void LZY_CycleEvents(void) {
static const SDL_Scancode sc[LZYK_COUNT] = {
SDL_SCANCODE_LEFT,
SDL_SCANCODE_RIGHT,
SDL_SCANCODE_UP,
SDL_SCANCODE_DOWN,
};
SDL_Event e;
while (SDL_PollEvent(&e) != 0) {
switch (e.type) {
case SDL_QUIT:
should_quit = 1;
break;
case SDL_KEYDOWN: {
int i = LZYK_COUNT;
while (i-- > 0) {
if (sc[i] == e.key.keysym.scancode) {
input[i] = 1;
break;
}
}
} break;
case SDL_KEYUP: {
int i = LZYK_COUNT;
while (i-- > 0) {
if (sc[i] == e.key.keysym.scancode) {
input[i] = 0;
break;
}
}
} break;
default:
break;
}
}
}
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 *msg) {
SDL_Log(msg);
}
const char *LZY_GetError(void) {
return error;
}
#endif /* SDL2 */
#endif /* LZY_IMPLEMENTATION */