Mirai's Miscellaneous Misadventures
M40 / engines / wasm.c
1
2
3
4#include <stdlib.h>
5
6#include <mimimi/assets.h>
7#include <mimimi/engines.h>
8#include <mimimi/behaviors.h>
9#include <mimimi/geometry.h>
10#include <mimimi/chapters.h>
11#include <mimimi/malloc.h>
12#include <mimimi/coroutine-providers.h>
13
14
15
16static void *mimimi_wasm_texture(void *data, struct mimimi_image *image)
17{
18 (void) data;
19 return image;
20}
21
22static void mimimi_wasm_invalidate(void *data, void *texture)
23{
24 (void) data;
25 (void) texture;
26}
27
28static void mimimi_wasm_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 unsigned char (*buffer)[4] = 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][0] = ch;
65 buffer[offset][1] = ch;
66 buffer[offset][2] = ch;
67 buffer[offset][3] = 0xFF;
68 }
69 else
70 {
71 color -= 0x10;
72 unsigned char r, g, b;
73 r = rch[(color / 40) % 6];
74 g = gch[(color / 5) % 8];
75 b = bch[(color / 1) % 5];
76
77 buffer[offset][0] = r;
78 buffer[offset][1] = g;
79 buffer[offset][2] = b;
80 buffer[offset][3] = 0xFF;
81 }
82 }
83}
84
85
86
87struct mimimi_wasm_asyncify_buffer
88{
89 void *begin;
90 void *end;
91};
92
93struct mimimi_wasm_coroutine_data
94{
95 unsigned int state;
96 struct mimimi_wasm_asyncify_buffer buffer;
97 void (*start)(struct mimimi_behavior *behavior, void *data);
98 void (*finish)(void *data);
99 void *data;
100 struct mimimi_behavior *behavior;
101 struct mimimi_behavior *coroutine;
102};
103
104void mimimi_wasm_yield(void *data);
105
106void mimimi_wasm_continue(void *data);
107
108void mimimi_wasm_start_coroutine(void *data)
109{
110 struct mimimi_wasm_coroutine_data *coroutine_data = data;
111 (*coroutine_data->start)(coroutine_data->behavior, coroutine_data->data);
112}
113
114void mimimi_wasm_finish_coroutine(void *data)
115{
116 struct mimimi_wasm_coroutine_data *coroutine_data = data;
117
118 coroutine_data->state = 2;
119
120 (*coroutine_data->finish)(coroutine_data->data);
121 free(coroutine_data->buffer.begin);
122 free(coroutine_data->behavior);
123}
124
125static void mimimi_wasm_finish_coroutine2(void *data)
126{
127 struct mimimi_wasm_coroutine_data *coroutine_data = data;
128
129 if (coroutine_data->state != 2) mimimi_wasm_finish_coroutine(coroutine_data);
130
131 free(coroutine_data->coroutine);
132 free(coroutine_data);
133}
134
135static struct mimimi_behavior *mimimi_wasm_create_coroutine(void (*start)(struct mimimi_behavior *behavior, void *data), void (*finish)(void *data), void *data, void *self)
136{
137 (void) self;
138
139 unsigned char *begin = mimimi_allocate(mimimi_malloc, 8192);
140
141 struct mimimi_wasm_coroutine_data *coroutine_data = mimimi_allocate(mimimi_malloc, sizeof *coroutine_data);
142 coroutine_data->start = start;
143 coroutine_data->finish = finish;
144 coroutine_data->data = data;
145 coroutine_data->buffer.begin = begin;
146 coroutine_data->buffer.end = begin + 8192;
147 coroutine_data->state = 0;
148
149 struct mimimi_behavior *behavior = mimimi_allocate(mimimi_malloc, sizeof *behavior);
150 behavior->behave = &mimimi_wasm_yield;
151 behavior->finish = &mimimi_wasm_finish_coroutine;
152 behavior->data = coroutine_data;
153 coroutine_data->behavior = behavior;
154
155 struct mimimi_behavior *coroutine = mimimi_allocate(mimimi_malloc, sizeof *coroutine);
156 coroutine->behave = &mimimi_wasm_continue;
157 coroutine->finish = &mimimi_wasm_finish_coroutine2;
158 coroutine->data = coroutine_data;
159 coroutine_data->coroutine = coroutine;
160
161 return coroutine;
162}
163
164static struct mimimi_coroutine_provider mimimi_wasm_coroutines = {&mimimi_wasm_create_coroutine, 0};
165
166
167
168static struct mimimi_chapter *mimimi_wasm_chapter;
169static unsigned char (*mimimi_wasm_buffer)[4];
170
171void *mimimi_wasm_behave(unsigned char left, unsigned char right)
172{
173 mimimi_wasm_chapter->left = left;
174 mimimi_wasm_chapter->right = right;
175 struct mimimi_behavior *behavior = mimimi_wasm_chapter->behavior;
176 (*behavior->behave)(behavior->data);
177 return mimimi_wasm_buffer;
178}
179
180void mimimi_wasm(struct mimimi_chapter *(*start)(struct mimimi_engine *engine))
181{
182 static struct mimimi_size size = {512, 256};
183 mimimi_wasm_buffer = mimimi_allocate(mimimi_malloc, size.width * size.height * 4);
184
185 static struct mimimi_engine engine;
186 engine.data = mimimi_wasm_buffer;
187 engine.texture = &mimimi_wasm_texture;
188 engine.invalidate = &mimimi_wasm_invalidate;
189 engine.stamp = &mimimi_wasm_stamp;
190 engine.size = &size;
191 engine.allocator = mimimi_malloc;
192 engine.coroutines = &mimimi_wasm_coroutines;
193 mimimi_wasm_chapter = (*start)(&engine);
194}