lzy/inc/lzy.h

393 lines
7.6 KiB
C
Raw Normal View History

2022-02-28 15:38:08 +01:00
#ifndef LZY_H_
#define LZY_H_
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
2022-02-28 16:26:59 +01:00
#define LZY_UNUSED(x) (void)(x)
2022-02-28 18:01:06 +01:00
int LZY_Init(const char *title, int target_fps);
2022-02-28 16:26:59 +01:00
void LZY_Quit(void);
2022-02-28 15:38:08 +01:00
int LZY_DrawBegin(void);
int LZY_DrawEnd(void);
void LZY_DrawSetColor(uint8_t r, uint8_t g, uint8_t b);
2022-02-28 15:49:33 +01:00
void LZY_DrawSetColorNone(void);
2022-02-28 15:38:08 +01:00
int LZY_DrawClear(void);
2022-02-28 21:47:26 +01:00
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);
2022-02-28 15:38:08 +01:00
void LZY_CycleEvents(void);
2022-02-28 16:43:45 +01:00
int LZY_KeyDown(unsigned int key);
2022-02-28 16:26:59 +01:00
int LZY_ShouldQuit(void);
void LZY_Log(const char *msg);
2022-02-28 15:38:08 +01:00
const char *LZY_GetError(void);
#ifdef FXCG50
#include <gint/keycodes.h>
enum LZY_ScanCode {
2022-02-28 16:43:45 +01:00
LZYK_LEFT = KEY_LEFT,
LZYK_RIGHT = KEY_RIGHT,
LZYK_UP = KEY_UP,
LZYK_DOWN = KEY_DOWN,
2022-02-28 15:38:08 +01:00
};
#else /* end FXCG50, begin SDL2 */
#include <SDL.h>
enum LZY_ScanCode {
2022-02-28 16:43:45 +01:00
LZYK_LEFT,
LZYK_RIGHT,
LZYK_UP,
LZYK_DOWN,
LZYK_COUNT,
2022-02-28 15:38:08 +01:00
};
#endif /* SDL2 */
#ifdef __cplusplus
}
#endif
#endif /* LZY_H_ */
/* implementation */
#ifdef LZY_IMPLEMENTATION
2022-02-28 23:13:20 +01:00
#undef LZY_IMPLEMENTATION
2022-02-28 15:38:08 +01:00
#ifndef LZY_TILE_SIZE
#define LZY_TILE_SIZE 16
#endif
2022-02-28 16:26:59 +01:00
#ifndef LZY_DISPLAY_WIDTH
2022-02-28 21:47:26 +01:00
#define LZY_DISPLAY_WIDTH 396
2022-02-28 16:26:59 +01:00
#endif
#ifndef LZY_DISPLAY_HEIGHT
#define LZY_DISPLAY_HEIGHT 224
#endif
2022-02-28 15:38:08 +01:00
#ifdef FXCG50
2022-02-28 18:01:06 +01:00
#include <gint/cpu.h>
2022-02-28 15:38:08 +01:00
#include <gint/display.h>
2022-02-28 15:49:33 +01:00
#include <gint/keyboard.h>
2022-02-28 18:01:06 +01:00
#include <gint/timer.h>
2022-02-28 15:38:08 +01:00
#include <stdint.h>
2022-02-28 16:26:59 +01:00
static color_t draw_color = C_BLACK;
static int should_quit = 0;
2022-02-28 18:01:06 +01:00
static int timer = 0;
static volatile int has_ticked = 0;
2022-02-28 15:38:08 +01:00
2022-02-28 18:01:06 +01:00
static int timer_callback(volatile int *);
int LZY_Init(const char *title, int target_fps) {
2022-02-28 16:26:59 +01:00
LZY_UNUSED(title);
2022-02-28 18:01:06 +01:00
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;
2022-02-28 15:38:08 +01:00
return 0;
}
2022-02-28 18:01:06 +01:00
void LZY_Quit(void) {
if (timer) {
timer_stop(timer);
timer = 0;
}
}
2022-02-28 15:38:08 +01:00
int LZY_DrawBegin(void) {
return 0;
}
int LZY_DrawEnd(void) {
2022-02-28 15:49:33 +01:00
dupdate();
2022-02-28 18:01:06 +01:00
while (timer && !has_ticked)
sleep();
has_ticked = 0;
2022-02-28 15:38:08 +01:00
return 0;
}
void LZY_DrawSetColor(uint8_t r, uint8_t g, uint8_t b) {
2022-02-28 18:01:06 +01:00
draw_color = C_RGB(r / 8, g / 8, b / 8);
2022-02-28 15:38:08 +01:00
}
2022-02-28 15:49:33 +01:00
void LZY_DrawSetColorNone(void) {
draw_color = C_NONE;
}
2022-02-28 15:38:08 +01:00
int LZY_DrawClear(void) {
2022-02-28 15:49:33 +01:00
dclear(draw_color);
2022-02-28 15:38:08 +01:00
return 0;
}
2022-02-28 21:47:26 +01:00
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;
}
2022-02-28 15:49:33 +01:00
void LZY_CycleEvents(void) {
clearevents();
2022-02-28 16:43:45 +01:00
should_quit = should_quit || keydown(KEY_EXIT);
2022-02-28 15:49:33 +01:00
}
2022-02-28 15:38:08 +01:00
2022-02-28 16:43:45 +01:00
int LZY_KeyDown(unsigned int key) {
return keydown(key);
2022-02-28 15:38:08 +01:00
}
2022-02-28 16:26:59 +01:00
int LZY_ShouldQuit(void) {
return should_quit;
}
void LZY_Log(const char *msg) {
LZY_UNUSED(msg);
}
2022-02-28 15:38:08 +01:00
const char *LZY_GetError(void) {
return NULL;
}
#else /* end FXCG50, begin SDL2 */
#include <SDL.h>
#include <stdint.h>
2022-02-28 16:26:59 +01:00
static const char *error = NULL;
static SDL_Window *window = NULL;
static SDL_Renderer *renderer = NULL;
2022-02-28 22:15:00 +01:00
static SDL_Texture *target = NULL;
2022-02-28 16:26:59 +01:00
static int should_quit = 0;
2022-02-28 16:43:45 +01:00
static int input[LZYK_COUNT] = {0};
2022-02-28 18:01:06 +01:00
static int fps_limiter = 0;
static uint64_t min_dt;
static uint64_t next_time;
2022-02-28 16:26:59 +01:00
2022-02-28 18:01:06 +01:00
int LZY_Init(const char *title, int target_fps) {
2022-02-28 16:26:59 +01:00
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
error = SDL_GetError();
2022-02-28 21:47:26 +01:00
return -1;
2022-02-28 16:26:59 +01:00
}
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, 0);
window = SDL_CreateWindow(title, SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED, LZY_DISPLAY_WIDTH,
2022-02-28 22:15:00 +01:00
LZY_DISPLAY_HEIGHT, SDL_WINDOW_RESIZABLE);
2022-02-28 16:26:59 +01:00
if (window == NULL) {
error = SDL_GetError();
2022-02-28 21:47:26 +01:00
return -2;
2022-02-28 16:26:59 +01:00
}
SDL_SetWindowMinimumSize(window, LZY_DISPLAY_WIDTH, LZY_DISPLAY_HEIGHT);
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
if (renderer == NULL) {
error = SDL_GetError();
2022-02-28 21:47:26 +01:00
return -3;
2022-02-28 16:26:59 +01:00
}
2022-02-28 22:15:00 +01:00
target = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGB888,
SDL_TEXTUREACCESS_TARGET, LZY_DISPLAY_WIDTH,
LZY_DISPLAY_HEIGHT);
if (target == NULL) {
error = SDL_GetError();
return -4;
}
2022-02-28 18:01:06 +01:00
fps_limiter = target_fps > 0;
if (fps_limiter) {
min_dt = 1000 / target_fps;
next_time = SDL_GetTicks64();
}
2022-02-28 15:38:08 +01:00
return 0;
}
2022-02-28 16:26:59 +01:00
void LZY_Quit(void) {
2022-02-28 22:15:00 +01:00
if (target != NULL) {
SDL_DestroyTexture(target);
target = NULL;
}
2022-02-28 16:26:59 +01:00
if (renderer != NULL) {
SDL_DestroyRenderer(renderer);
renderer = NULL;
}
if (window != NULL) {
SDL_DestroyWindow(window);
window = NULL;
}
SDL_Quit();
2022-02-28 15:38:08 +01:00
}
int LZY_DrawBegin(void) {
2022-02-28 18:01:06 +01:00
if (fps_limiter)
next_time += min_dt;
2022-02-28 22:15:00 +01:00
if (SDL_SetRenderTarget(renderer, target) < 0) {
error = SDL_GetError();
return -1;
}
2022-02-28 15:38:08 +01:00
return 0;
}
int LZY_DrawEnd(void) {
2022-02-28 22:15:00 +01:00
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);
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;
}
2022-02-28 16:26:59 +01:00
SDL_RenderPresent(renderer);
2022-02-28 18:01:06 +01:00
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);
}
2022-02-28 15:38:08 +01:00
return 0;
}
2022-02-28 16:26:59 +01:00
void LZY_DrawSetColor(uint8_t r, uint8_t g, uint8_t b) {
SDL_SetRenderDrawColor(renderer, r, g, b, 0xff);
}
2022-02-28 15:38:08 +01:00
2022-02-28 16:26:59 +01:00
void LZY_DrawSetColorNone(void) {
SDL_SetRenderDrawColor(renderer, 0x00, 0x00, 0x00, 0x00);
}
2022-02-28 15:49:33 +01:00
2022-02-28 15:38:08 +01:00
int LZY_DrawClear(void) {
2022-02-28 16:26:59 +01:00
if (SDL_RenderClear(renderer) < 0) {
error = SDL_GetError();
2022-02-28 21:47:26 +01:00
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};
2022-02-28 22:15:00 +01:00
if (w == 0 || h == 0) {
error = "rectangle dimensions cannot be 0";
return -1;
}
2022-02-28 21:47:26 +01:00
if (SDL_RenderDrawRect(renderer, &rect) < 0) {
error = SDL_GetError();
2022-02-28 22:15:00 +01:00
return -2;
2022-02-28 21:47:26 +01:00
}
return 0;
}
int LZY_DrawFillRect(int x, int y, unsigned int w, unsigned int h) {
const SDL_Rect rect = {x, y, w, h};
2022-02-28 22:15:00 +01:00
if (w == 0 || h == 0) {
error = "rectangle dimensions cannot be 0";
return -1;
}
2022-02-28 21:47:26 +01:00
if (SDL_RenderFillRect(renderer, &rect) < 0) {
error = SDL_GetError();
2022-02-28 22:15:00 +01:00
return -2;
2022-02-28 16:26:59 +01:00
}
2022-02-28 15:38:08 +01:00
return 0;
}
2022-02-28 16:26:59 +01:00
void LZY_CycleEvents(void) {
2022-02-28 16:43:45 +01:00
static const SDL_Scancode sc[LZYK_COUNT] = {
SDL_SCANCODE_LEFT,
SDL_SCANCODE_RIGHT,
SDL_SCANCODE_UP,
SDL_SCANCODE_DOWN,
};
2022-02-28 16:26:59 +01:00
SDL_Event e;
while (SDL_PollEvent(&e) != 0) {
switch (e.type) {
case SDL_QUIT:
should_quit = 1;
break;
2022-02-28 16:43:45 +01:00
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;
2022-02-28 16:26:59 +01:00
default:
break;
}
}
}
2022-02-28 15:38:08 +01:00
2022-02-28 16:43:45 +01:00
int LZY_KeyDown(unsigned int key) {
if (key >= LZYK_COUNT)
return 0;
return input[key];
2022-02-28 15:38:08 +01:00
}
2022-02-28 16:26:59 +01:00
int LZY_ShouldQuit(void) {
return should_quit;
}
void LZY_Log(const char *msg) {
SDL_Log(msg);
}
2022-02-28 15:38:08 +01:00
const char *LZY_GetError(void) {
2022-02-28 16:26:59 +01:00
return error;
2022-02-28 15:38:08 +01:00
}
#endif /* SDL2 */
#endif /* LZY_IMPLEMENTATION */