Mirai's Miscellaneous Misadventures

M39 / engines / mfb.c

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