Mirai's Miscellaneous Misadventures

M51 / engines / sdl2.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 void *mimimi_sdl2_texture(void *data, 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	SDL_Texture *texture;
17	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, 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF);
23	for (x = 0 ; x < image->width ; x++)
24	for (y = 0 ; y < image->height ; y++)
25	{
26		offset = x * 4 + y * surface->pitch;
27		pixel = (Uint32 *) ((char *) surface->pixels + offset);
28		
29		color = image->colors[x + y * image->width];
30		if (color == 0)
31		{
32			*pixel = 0;
33		}
34		else if (color < 0x10)
35		{
36			a = color * 0x11;
37			*pixel = (a << 24) | (a << 16) | (a << 8) | 0xFF;
38		}
39		else
40		{
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 = (r << 24) | (g << 16) | (b << 8) | (a << 0);
47		}
48	}
49	
50	texture = SDL_CreateTextureFromSurface(data, surface);
51	
52	SDL_FreeSurface(surface);
53	
54	return texture;
55}
56
57static void mimimi_sdl2_invalidate(void *data, void *texture)
58{
59	(void) data;
60	SDL_DestroyTexture(texture);
61}
62
63static void mimimi_sdl2_stamp(void *data, int x, int y, void *texture)
64{
65	SDL_Rect rect;
66	
67	rect.x = x;
68	rect.y = y;
69	SDL_QueryTexture(texture, NULL, NULL, &rect.w, &rect.h);
70	
71	SDL_RenderCopy(data, texture, NULL, &rect);
72}
73
74int mimimi_sdl2(void *(*start)(struct mimimi_engine *engine), void (*tick)(void *chapter, unsigned char left, unsigned char right))
75{
76	static SDL_Rect rect = {0, 0, 1024, 512};
77	
78	SDL_Window *window;
79	SDL_Renderer *renderer;
80	struct mimimi_engine engine;
81	void *chapter;
82	Uint32 past, current, delay;
83	SDL_Event event;
84	unsigned char *keys;
85	
86	atexit(&SDL_Quit);
87	
88	SDL_Init(SDL_INIT_VIDEO);
89	
90	SDL_CreateWindowAndRenderer(rect.w, rect.h, SDL_WINDOW_RESIZABLE, &window, &renderer);
91	SDL_SetWindowTitle(window, "Mirai's Miscellaneous Misadventures");
92	
93	engine.data = renderer;
94	engine.texture = &mimimi_sdl2_texture;
95	engine.invalidate = &mimimi_sdl2_invalidate;
96	engine.stamp = &mimimi_sdl2_stamp;
97	engine.size.width = rect.w;
98	engine.size.height = rect.h;
99	SDL_RenderSetLogicalSize(renderer, rect.w, rect.h);
100	
101	chapter = (*start)(chapter, &engine);
102	
103	past = SDL_GetTicks();
104	
105	for (;;)
106	{
107		rect.w = engine.size.width;
108		rect.h = engine.size.height;
109		SDL_RenderSetLogicalSize(renderer, rect.w, rect.h);
110		
111		current = SDL_GetTicks();
112		delay = current - past;
113		past = current;
114		if (delay < 33) SDL_Delay(33 - delay);
115		
116		while (SDL_PollEvent(&event))
117		{
118			if (event.type == SDL_QUIT) return 0;
119			
120			if (event.type == SDL_KEYDOWN)
121			{
122				switch (event.key.keysym.sym)
123				{
124					default: continue;
125					case SDLK_q: return 0;
126				}
127			}
128		}
129		
130		keys = (void *) SDL_GetKeyboardState(NULL);
131		
132		SDL_SetRenderDrawColor(renderer, 0x00, 0x00, 0x00, 0xFF);
133		SDL_RenderClear(renderer);
134		SDL_SetRenderDrawColor(renderer, 0xEE, 0xEE, 0xEE, 0xFF);
135		SDL_RenderFillRect(renderer, &rect);
136		SDL_GetWindowSize(window, &engine.size.width, &engine.size.height);
137		(*tick)(chapter, keys[SDL_SCANCODE_LEFT], keys[SDL_SCANCODE_RIGHT]);
138		SDL_RenderPresent(renderer);
139	}
140}