Mirai's Miscellaneous Misadventures

M50 / engines / minifb.c

1/* license: AGPLv3 or later */
2/* copyright 2024 zamfofex */
3
4#include <stdlib.h>
5#include <MiniFB.h>
6#include <mimimi.h>
7
8static void *mimimi_minifb_texture(void *data, struct mimimi_image *image)
9{
10	(void) data;
11	return image;
12}
13
14static void mimimi_minifb_invalidate(void *data, void *texture)
15{
16	(void) data;
17	(void) texture;
18}
19
20static void mimimi_minifb_stamp(void *data, int x1, int y1, void *texture)
21{
22	static unsigned char rch[] = {0x11, 0x44, 0x77, 0x99, 0xCC, 0xFF};
23	static unsigned char gch[] = {0x11, 0x33, 0x55, 0x77, 0x99, 0xBB, 0xDD, 0xFF};
24	static unsigned char bch[] = {0x22, 0x55, 0x88, 0xBB, 0xEE};
25	
26	struct mimimi_image *image;
27	uint32_t *buffer;
28	int x, y;
29	int x0, y0;
30	int x2, y2;
31	int width, height;
32	unsigned char color;
33	int offset;
34	unsigned char r, g, b;
35	
36	image = texture;
37	
38	buffer = data;
39	
40	x0 = 0;
41	y0 = 0;
42	
43	if (x1 < 0) x0 = -x1;
44	if (y1 < 0) y0 = -y1;
45	
46	width = image->width;
47	height = image->height;
48	
49	if (width + x1 > 512) width = 512 - x1;
50	if (height + y1 > 256) height = 256 - y1;
51	
52	for (y = y0 ; y < height ; y++)
53	for (x = x0 ; x < width ; x++)
54	{
55		color = image->colors[x + y * image->width];
56		if (color == 0) continue;
57		
58		x2 = x + x1;
59		y2 = y + y1;
60		
61		offset = x2 + y2 * 512;
62		
63		if (color < 0x10)
64		{
65			r = color * 0x11;
66			buffer[offset] = MFB_RGB(r, r, r);
67		}
68		else
69		{
70			color -= 0x10;
71			r = rch[(color / 40) % 6];
72			g = gch[(color / 5) % 8];
73			b = bch[(color / 1) % 5];
74			buffer[offset] = MFB_RGB(r, g, b);
75		}
76	}
77}
78
79int mimimi_minifb(void *(*start)(void *chapter, struct mimimi_engine *engine), void (*tick)(void *chapter, unsigned char left, unsigned char right))
80{
81	struct mfb_window *window;
82	uint32_t *buffer;
83	struct mimimi_engine engine;
84	unsigned char *keys;
85	void *chapter;
86	mfb_update_state state;
87	
88	buffer = malloc(512 * 256 * 4);
89	if (buffer == NULL) return 1;
90	
91	window = mfb_open_ex("Mirai's Miscellaneous Misadventures", 512, 256, WF_RESIZABLE);
92	if (window == NULL) return 1;
93	
94	engine.data = buffer;
95	engine.texture = &mimimi_minifb_texture;
96	engine.invalidate = &mimimi_minifb_invalidate;
97	engine.stamp = &mimimi_minifb_stamp;
98	engine.size.width = 512;
99	engine.size.height = 256;
100	
101	chapter = (*start)(&engine);
102	
103	for (;;)
104	{
105		keys = (void *) mfb_get_key_buffer(window);
106		if (keys[KB_KEY_Q] != 0) break;
107		
108		(*tick)(chapter, keys[KB_KEY_LEFT], keys[KB_KEY_RIGHT]);
109		
110		state = mfb_update_ex(window, buffer, 512, 256);
111		if (state == -1) break;
112		if (state < 0) return 1;
113		if (mfb_wait_sync(window) == 0) return 1;
114	}
115	
116	mfb_close(window);
117	free(chapter);
118	free(buffer);
119	
120	return 0;
121}