Mirai's Miscellaneous Misadventures

M53 / engines / sdl.c

1/* license: AGPLv3 or later */
2/* copyright 2024 zamfofex */
3
4#include <stdlib.h>
5#include <SDL2/SDL.h>
6#include "../mimimi.h"
7
8static SDL_Texture *mimimi_sdl2_texture(SDL_Renderer *renderer,
9    struct mimimi_image *image)
10{
11    static unsigned char rch[] = { 0x11, 0x44, 0x77, 0x99, 0xCC, 0xFF };
12    static unsigned char gch[] = { 0x11, 0x33, 0x55, 0x77, 0x99, 0xBB,
13        0xDD, 0xFF };
14    static unsigned char bch[] = { 0x22, 0x55, 0x88, 0xBB, 0xEE };
15
16    int x, y;
17    unsigned char color;
18    SDL_Texture *texture;
19    SDL_Surface *surface;
20    Uint32 offset;
21    Uint32 *pixel;
22    Uint32 r, g, b, a;
23
24    surface = SDL_CreateRGBSurface(0, image->width, image->height, 32,
25        0xFF0000, 0x00FF00, 0x0000FF, 0xFF000000L);
26    for (x = 0; x < image->width; x++) {
27        for (y = 0; y < image->height; y++) {
28            offset = x * 4 + y * surface->pitch;
29            pixel = (Uint32 *) ((char *) surface->pixels + offset);
30
31            color = image->colors[x + y * image->width];
32            if (color == 0) {
33                *pixel = 0;
34            } else if (color < 0x10) {
35                a = color * 0x11;
36                *pixel = (0xFFL << 24) | (a << 16) | (a << 8) | (a << 0);
37            } else {
38                color -= 0x10;
39                r = rch[(color / 40) % 6];
40                g = gch[(color / 5) % 8];
41                b = bch[(color / 1) % 5];
42                a = 0xFF;
43                *pixel = (a << 24) | (r << 16) | (g << 8) | (b << 0);
44            }
45        }
46    }
47
48    texture = SDL_CreateTextureFromSurface(renderer, surface);
49
50    SDL_FreeSurface(surface);
51
52    return texture;
53}
54
55void mimimi_main(void (*tick)(void *data, struct mimimi_output *output,
56    struct mimimi_input *input), void *data)
57{
58    struct mimimi_input input;
59    struct mimimi_output output;
60    SDL_Window *window;
61    SDL_Renderer *renderer;
62    Uint32 tickno, now;
63    SDL_Event event;
64    unsigned char *keys;
65    SDL_Texture *texture;
66
67    atexit(&SDL_Quit);
68    SDL_Init(SDL_INIT_VIDEO);
69
70    input.size.width = 1024;
71    input.size.height = 512;
72
73    SDL_CreateWindowAndRenderer(input.size.width, input.size.height,
74        SDL_WINDOW_RESIZABLE, &window, &renderer);
75    SDL_SetWindowTitle(window, "Mirai's Miscellaneous Misadventures");
76
77    tickno = 0;
78
79    for (;;) {
80        keys = (void *) SDL_GetKeyboardState(NULL);
81        SDL_GetWindowSize(window, &input.size.width, &input.size.height);
82        input.left = keys[SDL_SCANCODE_LEFT] || keys[SDL_SCANCODE_A];
83        input.right = keys[SDL_SCANCODE_RIGHT] || keys[SDL_SCANCODE_D];
84        (*tick)(data, &output, &input);
85
86        SDL_RenderSetLogicalSize(renderer, output.image.width,
87            output.image.height);
88        texture = mimimi_sdl2_texture(renderer, &output.image);
89        SDL_RenderCopy(renderer, texture, NULL, NULL);
90        SDL_DestroyTexture(texture);
91        SDL_RenderPresent(renderer);
92
93        now = SDL_GetTicks();
94        do {
95             tickno++;
96        } while (tickno * 100 < now * 6);
97        SDL_Delay(tickno * 100.0 / 6 - now);
98
99        while (SDL_PollEvent(&event)) {
100            if (event.type == SDL_QUIT) exit(0);
101            if (event.type == SDL_KEYDOWN && event.key.keysym.sym == SDLK_q) exit(0);
102        }
103    }
104}