Mirai's Miscellaneous Misadventures
M36 / engines / wasm.c
1
2
3
4#include <mimimi/allocators.h>
5#include <mimimi/coroutine-providers.h>
6#include <mimimi/assets.h>
7
8void *mimimi_wasm_javascript_texture(void *data, struct mimimi_image *image);
9void *mimimi_wasm_texture(void *data, struct mimimi_image *image)
10{
11 return mimimi_wasm_javascript_texture(data, image);
12}
13
14void mimimi_wasm_javascript_invalidate(void *data, void *texture);
15void mimimi_wasm_invalidate(void *data, void *texture)
16{
17 mimimi_wasm_javascript_invalidate(data, texture);
18}
19
20void mimimi_wasm_javascript_stamp(void *data, int x, int y, void *texture);
21void mimimi_wasm_stamp(void *data, int x, int y, void *texture)
22{
23 mimimi_wasm_javascript_stamp(data, x, y, texture);
24}
25
26extern unsigned char __heap_base;
27static unsigned char *mimimi_wasm_heap = &__heap_base;
28static unsigned long int mimimi_wasm_start = (unsigned long int) &__heap_base;
29
30static unsigned char mimimi_wasm_blocks[0x10000] = {0};
31
32static void mimimi_wasm_grow(unsigned int n)
33{
34 unsigned long int size = __builtin_wasm_memory_size(0) * 0x10000 - mimimi_wasm_start;
35 if (size < n)
36 {
37 if (__builtin_wasm_memory_grow(0, (n - size - 1) / 0x10000 + 1) < 0)
38 __builtin_trap();
39 }
40}
41
42void *mimimi_wasm_allocate(void *ignored, unsigned int size)
43{
44 (void) ignored;
45
46 int blocks = (size - 1) / 8192 + 1;
47
48 for (int i = 0 ; i < 0x10000 ; i++)
49 {
50 for (int j = 0 ; j < blocks ; j++)
51 {
52 if (mimimi_wasm_blocks[i + j] != 0)
53 goto next;
54 }
55
56 mimimi_wasm_blocks[i] = 1;
57 for (int j = 1 ; j < blocks ; j++)
58 mimimi_wasm_blocks[i + j] = 2;
59
60 unsigned char *null = 0;
61 unsigned char *data = mimimi_wasm_heap + i * 8192;
62 mimimi_wasm_grow(data - null + size);
63 return data;
64
65 next:;
66 }
67
68 __builtin_trap();
69}
70
71void mimimi_wasm_deallocate(void *ignored, void *data0)
72{
73 (void) ignored;
74
75 unsigned char *data = data0;
76 int block = (data - mimimi_wasm_heap) / 8192;
77
78 mimimi_wasm_blocks[block] = 0;
79 for (int i = 1 ; mimimi_wasm_blocks[block + i] == 2 ; i++)
80 mimimi_wasm_blocks[block + i] = 0;
81}
82
83void *mimimi_wasm_reallocate(void *ignored, void *data0, unsigned int size)
84{
85 (void) ignored;
86
87 if (data0 == 0) return mimimi_wasm_allocate(0, size);
88
89 unsigned char *data = data0;
90 int block = (data - mimimi_wasm_heap) / 8192;
91
92 unsigned int current_count = 1;
93 while (mimimi_wasm_blocks[block + current_count] == 2) current_count++;
94
95 unsigned int target_count = (size - 1) / 8192 + 1;
96
97 if (target_count <= current_count)
98 {
99 for (unsigned int i = target_count ; i < current_count ; i++)
100 mimimi_wasm_blocks[block + i] = 0;
101 return data;
102 }
103
104 for (unsigned int i = current_count ; i < target_count ; i++)
105 {
106 if (mimimi_wasm_blocks[block + i] != 0)
107 {
108 unsigned char *new = mimimi_wasm_allocate(0, size);
109 for (unsigned int i = 0 ; i < current_count * 8192 ; i++)
110 new[i] = data[i];
111 mimimi_wasm_deallocate(0, data);
112 return new;
113 }
114 }
115
116 for (unsigned int i = current_count ; i < target_count ; i++)
117 mimimi_wasm_blocks[block + i] = 2;
118
119 return data;
120}
121
122static struct mimimi_allocator mimimi_wasm_allocator_value = {&mimimi_wasm_allocate, &mimimi_wasm_reallocate, &mimimi_wasm_deallocate, 0, 0};
123struct mimimi_allocator *mimimi_wasm_allocator = &mimimi_wasm_allocator_value;
124
125struct mimimi_behavior *mimimi_wasm_javascript_create_coroutine(void (*start)(struct mimimi_behavior *behavior, void *data), void (*finish)(void *data), void *data);
126void mimimi_wasm_javascript_yield(void *data);
127void mimimi_wasm_javascript_continue(void *data);
128void mimimi_wasm_javascript_finish_coroutine(void *data);
129void mimimi_wasm_javascript_finish_coroutine2(void *data);
130
131static struct mimimi_behavior *mimimi_wasm_create_coroutine(void (*start)(struct mimimi_behavior *behavior, void *data), void (*finish)(void *data), void *data, void *self)
132{
133 (void) self;
134 return mimimi_wasm_javascript_create_coroutine(start, finish, data);
135}
136
137void mimimi_wasm_yield(void *data)
138{
139 mimimi_wasm_javascript_yield(data);
140}
141
142void mimimi_wasm_continue(void *data)
143{
144 mimimi_wasm_javascript_continue(data);
145}
146
147void mimimi_wasm_finish_coroutine(void *data)
148{
149 mimimi_wasm_javascript_finish_coroutine(data);
150}
151
152void mimimi_wasm_finish_coroutine2(void *data)
153{
154 mimimi_wasm_javascript_finish_coroutine2(data);
155}
156
157static struct mimimi_coroutine_provider mimimi_wasm_coroutines_value = {&mimimi_wasm_create_coroutine, 0};
158struct mimimi_coroutine_provider *mimimi_wasm_coroutines = &mimimi_wasm_coroutines_value;