Mirai's Miscellaneous Misadventures

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