Mirai's Miscellaneous Misadventures
M23 / engines / x86.c
1
2
3
4#include <mimimi/allocators.h>
5#include <mimimi/test.h>
6#include <mimimi/engines.h>
7#include <mimimi/geometry.h>
8#include <mimimi/assets.h>
9#include <mimimi/chapters.h>
10#include <mimimi/behaviors.h>
11
12struct mimimi_vbe_screen
13{
14 unsigned int *buffer;
15 unsigned short int width;
16 unsigned short int height;
17 unsigned short int bytes_per_line;
18 unsigned short int bytes_per_pixel;
19};
20
21extern struct mimimi_vbe_screen mimimi_vbe_screen;
22
23void mimimi_x86_exit(void);
24
25extern unsigned char mimimi_x86_heap_start;
26static unsigned char *mimimi_x86_heap = &mimimi_x86_heap_start;
27
28static unsigned char mimimi_x86_blocks[8192] = {};
29
30static void *mimimi_x86_allocate(unsigned int size)
31{
32 int blocks = (size - 1) / 1024 + 1;
33
34 for (int i = 0 ; i < 8192 ; i++)
35 {
36 for (int j = 0 ; j < blocks ; j++)
37 {
38 if (mimimi_x86_blocks[i + j] != 0)
39 goto next;
40 }
41
42 mimimi_x86_blocks[i] = 1;
43 for (int j = 1 ; j < blocks ; j++)
44 mimimi_x86_blocks[i + j] = 2;
45
46 unsigned char *data = mimimi_x86_heap + i * 1024;
47 return data;
48
49 next:;
50 }
51
52 mimimi_x86_exit();
53}
54
55static void mimimi_x86_deallocate(void *data0)
56{
57 unsigned char *data = data0;
58 int block = (data - mimimi_x86_heap) / 1024;
59
60 mimimi_x86_blocks[block] = 0;
61 for (int i = 1 ; mimimi_x86_blocks[block + i] == 2 ; i++)
62 mimimi_x86_blocks[block + i] = 0;
63}
64
65static void *mimimi_x86_reallocate(void *data0, unsigned int size)
66{
67 if (data0 == 0) return mimimi_x86_allocate(size);
68
69 unsigned char *data = data0;
70 int block = (data - mimimi_x86_heap) / 1024;
71
72 int current_count = 1;
73 while (mimimi_x86_blocks[block + current_count] == 2) current_count++;
74
75 int target_count = (size - 1) / 1024 + 1;
76
77 if (target_count <= current_count)
78 {
79 for (int i = target_count ; i < current_count ; i++)
80 mimimi_x86_blocks[block + i] = 0;
81 return data;
82 }
83
84 for (int i = current_count ; i < target_count ; i++)
85 {
86 if (mimimi_x86_blocks[block + i] != 0)
87 {
88 unsigned char *new = mimimi_x86_allocate(size);
89 for (unsigned int i = 0 ; i < current_count * 1024 ; i++)
90 new[i] = data[i];
91 mimimi_x86_deallocate(data);
92 return new;
93 }
94 }
95
96 for (int i = current_count ; i < target_count ; i++)
97 mimimi_x86_blocks[block + i] = 2;
98 return data;
99}
100
101static struct mimimi_allocator mimimi_x86_allocator_value = {&mimimi_x86_allocate, &mimimi_x86_reallocate, &mimimi_x86_deallocate, 0};
102static struct mimimi_allocator *mimimi_x86_allocator = &mimimi_x86_allocator_value;
103
104static unsigned char *mimimi_x86_buffer;
105static unsigned char *mimimi_x86_out_buffer;
106
107static void mimimi_x86_stamp(void *data, int x1, int y1, struct mimimi_image *image)
108{
109 int x0 = 0;
110 int y0 = 0;
111
112 if (x1 < 0) x0 = -x1;
113 if (y1 < 0) y0 = -y1;
114
115 int width = image->width;
116 int height = image->height;
117
118 if (width + x1 > 512) width = 512 - x1;
119 if (height + y1 > 256) height = 256 - y1;
120
121 for (int y = y0 ; y < height ; y++)
122 for (int x = x0 ; x < width ; x++)
123 {
124 unsigned char color = image->colors[x + y * image->width];
125 if (color == 0) continue;
126
127 int x2 = x + x1;
128 int y2 = y + y1;
129
130 mimimi_x86_buffer[x2 + y2 * 512] = color;
131 }
132}
133
134static struct mimimi_chapter *chapter;
135
136void mimimi_x86_start(void)
137{
138 mimimi_x86_buffer = mimimi_x86_allocate(512 * 256);
139 mimimi_x86_out_buffer = mimimi_x86_allocate(512 * 256 * 4);
140
141 static struct mimimi_size size = {512, 256};
142 chapter = mimimi_test(mimimi_x86_allocator);
143 chapter->engine->size = &size;
144 chapter->engine->stamp = &mimimi_x86_stamp;
145}
146
147void mimimi_x86_step(void)
148{
149 extern unsigned char mimimi_x86_left;
150 extern unsigned char mimimi_x86_right;
151
152 chapter->left = mimimi_x86_left;
153 chapter->right = mimimi_x86_right;
154
155 (*chapter->behavior->behave)(chapter->behavior->data);
156
157 static unsigned char rch[] = {0x11, 0x44, 0x77, 0x99, 0xCC, 0xFF};
158 static unsigned char gch[] = {0x11, 0x33, 0x55, 0x77, 0x99, 0xBB, 0xDD, 0xFF};
159 static unsigned char bch[] = {0x22, 0x55, 0x88, 0xBB, 0xEE};
160
161 unsigned int width = 512;
162 unsigned int height = 256;
163
164 unsigned int x0 = (mimimi_vbe_screen.width - width) / 2;
165 unsigned int y0 = (mimimi_vbe_screen.height - height) / 2;
166
167 if (mimimi_vbe_screen.width < width) x0 = 0, width = mimimi_vbe_screen.width;
168 if (mimimi_vbe_screen.height < height) y0 = 0, height = mimimi_vbe_screen.height;
169
170 for (unsigned int y = 0 ; y < height ; y++)
171 for (unsigned int x = 0 ; x < width ; x++)
172 {
173 unsigned char color = mimimi_x86_buffer[x + y * 512];
174 unsigned int i = (x + y * 512) * 4;
175
176 if (color < 0x10)
177 {
178 unsigned char ch = color * 0x11;
179 mimimi_x86_out_buffer[i + 0] = ch;
180 mimimi_x86_out_buffer[i + 1] = ch;
181 mimimi_x86_out_buffer[i + 2] = ch;
182 }
183 else
184 {
185 color -= 0x10;
186 unsigned char r, g, b;
187 r = rch[(color / 40) % 6];
188 g = gch[(color / 5) % 8];
189 b = bch[(color / 1) % 5];
190
191 mimimi_x86_out_buffer[i + 0] = b;
192 mimimi_x86_out_buffer[i + 1] = g;
193 mimimi_x86_out_buffer[i + 2] = r;
194 }
195 }
196
197 unsigned int *buffer = (void *)mimimi_x86_out_buffer;
198
199 unsigned int o = x0 + y0 * mimimi_vbe_screen.bytes_per_line / 4;
200 for (unsigned int y = 0 ; y < height ; y++)
201 for (unsigned int x = 0 ; x < width ; x++)
202 {
203 unsigned int i = x + y * 512;
204 unsigned int j = x + y * mimimi_vbe_screen.bytes_per_line / 4;
205 mimimi_vbe_screen.buffer[j + o] = buffer[i];
206 }
207}