Mirai's Miscellaneous Misadventures

M12 / game.c

1#include "game.h"
2#include "math.c"
3
4// types
5
6struct mirai_animation
7{
8	int count;
9	struct mirai_image *images;
10};
11
12struct mirai_direction_animation_set
13{
14	int count;
15	struct mirai_animation *standing;
16	struct mirai_animation knocked;
17};
18
19struct mirai_animation_set
20{
21	struct mirai_direction_animation_set left, right;
22};
23
24struct mirai_sprite_type
25{
26	struct mirai_animation_set animations;
27	int width;
28	int height;
29};
30
31struct mirai_sprite
32{
33	struct mirai_sprite_type *type;
34	
35	int x, y;
36	// speed
37	int dx, dy;
38	// acceleration
39	int ax;
40	
41	char airborne;
42	char moving_direction;
43	char last_moving_direction;
44	
45	int attack_y;
46	int attack_width;
47	int attack_height;
48	int attack_time;
49	
50	void (*behave)(struct mirai_game *game, struct mirai_sprite *sprite);
51	
52	unsigned char animation_time;
53	
54	unsigned char knocked_time;
55};
56
57struct mirai_rotating_image_row
58{
59	int size;
60	unsigned char count;
61	unsigned char colors[64];
62};
63
64struct mirai_rotating_image
65{
66	int count;
67	struct mirai_rotating_image_row rows[];
68};
69
70
71// constants
72
73#include "assets.c"
74
75static int mirai_gravity = 4;
76
77static unsigned char mirai_ground_colors[16 * 16];
78
79static unsigned char mirai_colors[80686];
80
81static struct mirai_image mirai_images[145] =
82{
83	{16, 16, mirai_ground_colors},
84};
85
86static struct mirai_animation mirai_animations[9];
87
88static struct mirai_image *mirai_ground_image = mirai_images;
89
90static struct mirai_sprite_type mirai_mirai = {{}, 80, 250};
91
92static struct mirai_image *mirai_glyphs[26 * 2 + 10];
93
94
95// state
96
97struct mirai_game
98{
99	struct mirai_engine engine;
100	struct mirai_sprite sprites[256];
101	unsigned char sprite_count;
102	
103	unsigned int left_history:16;
104	unsigned int right_history:16;
105	
106	struct mirai_sprite *camera_sprite;
107	int camera_x;
108	int camera_y;
109};
110
111
112// functions
113
114static void mirai_stamp(struct mirai_game *game, int x, int y, struct mirai_image *image)
115{
116	x -= game->camera_x;
117	x += mirai_width * 4;
118	y -= game->camera_y;
119	y += mirai_height * 4;
120	
121	x -= image->width * 4;
122	y -= image->height * 8;
123	
124	(*game->engine.stamp)(game->engine.data, x / 8, y / 8, image);
125}
126
127static int mirai_text(struct mirai_game *game, int x, int y, char *text)
128{
129	for (int i = 0 ; *text != '\0' ; i++)
130	{
131		char ch = *text++;
132		
133		if (ch == ' ')
134		{
135			x += 4;
136			continue;
137		}
138		
139		struct mirai_image *image;
140		
141		if (ch >= '0' && ch <= '9')
142		{
143			image = mirai_glyphs[ch - '0' + 0];
144		}
145		else if (ch >= 'A' && ch <= 'Z')
146		{
147			image = mirai_glyphs[ch - 'A' + 10];
148		}
149		else if (ch >= 'a' && ch <= 'z')
150		{
151			image = mirai_glyphs[ch - 'a' + 36];
152		}
153		else
154		{
155			continue;
156		}
157		
158		(*game->engine.stamp)(game->engine.data, x - 1, y - image->height + 5, image);
159		x += image->width - 1;
160	}
161	
162	return x;
163}
164
165static void mirai_wall_physics(struct mirai_sprite *sprite)
166{
167	int x0 = sprite->x;
168	int x1 = sprite->type->width / 2;
169	int y0 = sprite->y;
170	int y1 = sprite->type->height;
171	
172	int top = (y0 - y1) / 128;
173	int top2 = top - 1;
174	int bottom = (y0 - 127) / 128;
175	int bottom2 = bottom - 1;
176	int left = (x0 - x1) / 128;
177	int right = (x0 + x1) / 128;
178	
179	if (
180		mirai_ground[bottom][left] != 0 && mirai_ground[bottom2][left] != 0 ||
181		mirai_ground[top][left] != 0 && mirai_ground[top2][left]
182	)
183	{
184		if (sprite->dx < 0) sprite->dx = 0;
185		sprite->x = (left + 1) * 128 + x1;
186	}
187	if (
188		mirai_ground[bottom][right] != 0 && mirai_ground[bottom2][right] != 0 ||
189		mirai_ground[top][right] != 0 && mirai_ground[top2][right]
190	)
191	{
192		if (sprite->dx > 0) sprite->dx = 0;
193		sprite->x = right * 128 - x1 - 1;
194	}
195}
196
197static void mirai_step_physics(struct mirai_sprite *sprite)
198{
199	int x0 = sprite->x;
200	int x1 = sprite->type->width / 2;
201	int y0 = sprite->y;
202	int y1 = sprite->type->height;
203	
204	int top = (y0 - y1) / 128;
205	int bottom = (y0 - 127) / 128;
206	int left = (x0 - x1) / 128;
207	int right = (x0 + x1) / 128;
208	
209	if (mirai_ground[bottom][left] != 0 && mirai_ground[top][left] == 0)
210		sprite->y = bottom * 128;
211	if (mirai_ground[bottom][right] != 0 && mirai_ground[top][right] == 0)
212		sprite->y = bottom * 128;
213}
214
215static void mirai_ceiling_physics(struct mirai_sprite *sprite)
216{
217	int x0 = sprite->x;
218	int x1 = sprite->type->width / 2;
219	int y0 = sprite->y;
220	int y1 = sprite->type->height;
221	
222	int top = (y0 - y1) / 128;
223	int top2 = top - 1;
224	int left = (x0 - x1) / 128;
225	int right = (x0 + x1) / 128;
226	
227	if (sprite->dy > 0) return;
228	
229	if (mirai_ground[top][left] != 0)
230	if (mirai_ground[top][right] != 0)
231	if (mirai_ground[top2][left] != 0 || mirai_ground[top2][right] != 0)
232	{
233		sprite->dy = 0;
234		sprite->y = (top + 1) * 128 + y1;
235	}
236}
237
238static void mirai_landing_physics(struct mirai_sprite *sprite)
239{
240	int x0 = sprite->x;
241	int x1 = sprite->type->width / 2;
242	int y0 = sprite->y;
243	
244	int bottom = y0 / 128;
245	int left = (x0 - x1) / 128;
246	int right = (x0 + x1) / 128;
247	
248	if (sprite->dy < 0) return;
249	
250	if (mirai_ground[bottom][left] != 0 || mirai_ground[bottom][right] != 0)
251	{
252		sprite->airborne = 0;
253		sprite->dy = 0;
254		sprite->y = bottom * 128;
255	}
256}
257
258static void mirai_fall_physics(struct mirai_sprite *sprite)
259{
260	int x0 = sprite->x;
261	int x1 = sprite->type->width / 2;
262	int y0 = sprite->y;
263	
264	int bottom = y0 / 128;
265	int center = x0 / 128;
266	int left = (x0 - x1) / 128;
267	int right = (x0 + x1) / 128;
268	
269	if (mirai_ground[bottom][left] == 0 && mirai_ground[bottom][right] == 0)
270	{
271		if (mirai_ground[bottom + 1][center] == 0)
272			// fall
273			sprite->airborne = 1;
274		else
275			// step down
276			sprite->y = (bottom + 1) * 128;
277	}
278}
279
280static void mirai_physics_dynamics(struct mirai_sprite *sprite)
281{
282	sprite->dx += sprite->ax;
283	sprite->x += sprite->dx;
284	sprite->y += sprite->dy;
285}
286
287static void mirai_ground_physics(struct mirai_sprite *sprite)
288{
289	sprite->dx *= 7;
290	sprite->dx /= 8;
291	sprite->dy = 0;
292	
293	mirai_physics_dynamics(sprite);
294	
295	mirai_step_physics(sprite);
296	mirai_wall_physics(sprite);
297	mirai_fall_physics(sprite);
298}
299
300static void mirai_airborne_physics(struct mirai_sprite *sprite)
301{
302	sprite->dx *= 15;
303	sprite->dx /= 16;
304	sprite->dy += mirai_gravity;
305	
306	mirai_physics_dynamics(sprite);
307	
308	mirai_ceiling_physics(sprite);
309	mirai_wall_physics(sprite);
310	mirai_landing_physics(sprite);
311}
312
313static void mirai_jump(struct mirai_sprite *sprite)
314{
315	if (sprite->airborne) return;
316	sprite->airborne = 1;
317	sprite->dy = -64;
318}
319
320static void mirai_damage(struct mirai_game *game, struct mirai_sprite *sprite)
321{
322	/*
323	struct mirai_image area = {sprite->attack_width / 16, sprite->attack_height / 8};
324	int x = sprite->x + sprite->attack_width / 4;
325	int y = (sprite->y + sprite->attack_y);
326	
327	if (sprite->moving_direction == 1) x -= sprite->attack_width / 2;
328	
329	mirai_stamp(game, x, y, &area);
330	*/
331}
332
333static void mirai_attack(struct mirai_game *game, struct mirai_sprite *sprite)
334{
335	sprite->attack_y = -16;
336	sprite->attack_width = 512;
337	sprite->attack_height = 256;
338	mirai_damage(game, sprite);
339}
340
341static void mirai_rapid_attack(struct mirai_game *game, struct mirai_sprite *sprite)
342{
343	sprite->attack_y = -128;
344	sprite->attack_width = sprite->attack_time * 16 + 64;
345	sprite->attack_height = 64;
346	if (sprite->attack_time != 0x7F) sprite->attack_time++;
347	mirai_damage(game, sprite);
348}
349
350static unsigned char mirai_count_oscillations(unsigned int history)
351{
352	unsigned char count = 0;
353	unsigned char prev = history&1;
354	for (int i = 0 ; i < 16 ; i++)
355	{
356		if ((history&1) != prev) count++;
357		prev = history&1;
358		history >>= 1;
359	}
360	return count;
361}
362
363static void mirai_controls(struct mirai_game *game, struct mirai_sprite *sprite)
364{
365	unsigned char left_oscillations = mirai_count_oscillations(game->left_history);
366	unsigned char right_oscillations = mirai_count_oscillations(game->right_history);
367	
368	switch (sprite->moving_direction)
369	{
370	case 0:
371		if ((game->left_history&1) != 0)
372			sprite->moving_direction = 1;
373		if ((game->right_history&1) != 0)
374			sprite->moving_direction = 2;
375		break;
376	case 1:
377		if ((game->left_history&1) == 0)
378			sprite->moving_direction = 0;
379		else if (left_oscillations > 1)
380			mirai_jump(sprite);
381		if ((game->right_history&1) != 0)
382		{
383			if (right_oscillations == 0)
384				mirai_rapid_attack(game, sprite);
385			else
386				sprite->attack_time = 0;
387		}
388		if ((game->right_history&1) != 0 && (game->right_history&2) == 0)
389			mirai_attack(game, sprite);
390		break;
391	case 2:
392		if ((game->right_history&1) == 0)
393			sprite->moving_direction = 0;
394		else if (right_oscillations > 1)
395			mirai_jump(sprite);
396		if ((game->left_history&1) != 0)
397		{
398			if (left_oscillations == 0)
399				mirai_rapid_attack(game, sprite);
400			else
401				sprite->attack_time = 0;
402		}
403		if ((game->left_history&1) != 0 && (game->left_history&2) == 0)
404			mirai_attack(game, sprite);
405		break;
406	}
407}
408
409static void mirai_spawn(struct mirai_game *game, int x, int y, struct mirai_sprite_type *type, void (*behave)(struct mirai_game *game, struct mirai_sprite *sprite))
410{
411	if (game->sprite_count == 0xFF) return;
412	struct mirai_sprite *sprite = game->sprites + game->sprite_count;
413	game->sprite_count++;
414	sprite->type = type;
415	sprite->x = x;
416	sprite->y = y;
417	sprite->dx = 0;
418	sprite->dy = 0;
419	sprite->ax = 0;
420	sprite->airborne = 1;
421	sprite->moving_direction = 0;
422	sprite->last_moving_direction = 1;
423	sprite->attack_time = 0;
424	sprite->animation_time = 0;
425	sprite->behave = behave;
426}
427
428static void mirai_image_rotation(struct mirai_image *image, struct mirai_rotating_image *rotating_image, unsigned char angle, int x0, int y0, int tilt, int tilt_origin, int tilt_threshold, char flip)
429{
430	if (flip != 0) angle = 0x100 - angle;
431	
432	int width = image->width;
433	int height = image->height;
434	
435	for (int y = 0 ; y < rotating_image->count ; y++)
436	for (int x = 0 ; x < rotating_image->rows[y].size ; x++)
437	{
438		int count = rotating_image->rows[y].count;
439		
440		int w = rotating_image->rows[y].size;
441		int h = rotating_image->count;
442		
443		unsigned int a = angle;
444		a *= count;
445		a += 128;
446		a /= 256;
447		a += x;
448		a %= count;
449		
450		if (flip != 0) a = count - a - 1;
451		
452		int yy = y;
453		if (yy < tilt_threshold) yy = tilt_threshold;
454		
455		int x1 = x + x0 + (width - w) / 2 + tilt * (tilt_origin - yy) / 256;
456		int y1 = y - y0 + height - h;
457		
458		unsigned char color = rotating_image->rows[y].colors[a];
459		if (color == 0) continue;
460		
461		image->colors[x1 + y1 * width] = color;
462	}
463}
464
465static void mirai_mirai_animation_frame(struct mirai_image *image, unsigned char **colors_pointer, int angle, int tilt, int arm_tilt)
466{
467	unsigned char *colors = *colors_pointer;
468	
469	image->colors = colors;
470	image->width = 26;
471	image->height = 36;
472	
473	(*colors_pointer) += image->width * image->height;
474	
475	for (int x = 0 ; x < image->width ; x++)
476	for (int y = 0 ; y < image->height ; y++)
477		image->colors[x + y * image->width] = 0;
478	
479	int x = mirai_sine[angle];
480	x *= 5;
481	x /= 128;
482	int left_x = x + (mirai_mirai_left_arm.count + 10) * tilt / 256;
483	int right_x = x - (mirai_mirai_right_arm.count + 10) * tilt / 256;
484	
485	int height = mirai_mirai_torso.count;
486	
487	mirai_image_rotation(image, &mirai_mirai_hair, angle, 0, 7, tilt, height, 11, 1);
488	if ((angle + 64) % 256 < 128)
489	{
490		mirai_image_rotation(image, &mirai_mirai_left_arm, angle, left_x, 10, tilt - arm_tilt, 0, 0, 0);
491		mirai_image_rotation(image, &mirai_mirai_torso, angle, 0, 0, tilt, height, 11, 0);
492		mirai_image_rotation(image, &mirai_mirai_right_arm, angle, -right_x, 10, tilt + arm_tilt, 0, 0, 0);
493	}
494	else
495	{
496		mirai_image_rotation(image, &mirai_mirai_right_arm, angle, -right_x, 10, tilt + arm_tilt, 0, 0, 0);
497		mirai_image_rotation(image, &mirai_mirai_torso, angle, 0, 0, tilt, height, 11, 0);
498		mirai_image_rotation(image, &mirai_mirai_left_arm, angle, left_x, 10, tilt - arm_tilt, 0, 0, 0);
499	}
500	mirai_image_rotation(image, &mirai_mirai_hair, angle, 0, 7, tilt, height, 11, 0);
501}
502
503static void mirai_mirai_animation(struct mirai_animation *animation, struct mirai_image **images, unsigned char **colors, int angle, int count, int tilt, int arm_tilt)
504{
505	animation->count = count;
506	animation->images = *images;
507	
508	for (int i = 0 ; i < count ; i++)
509		mirai_mirai_animation_frame((*images)++, colors, angle, tilt, arm_tilt * mirai_sine[i * 255 / count] / 128);
510}
511
512static void mirai_mirai_animation_set(struct mirai_animation **animations, struct mirai_image **images, unsigned char **colors, int coefficient, int count, int count2, int tilt, int arm_tilt)
513{
514	for (int i = 0 ; i < count ; i++)
515		mirai_mirai_animation((*animations)++, images, colors, 64 + (12 + 34 * i / count) * coefficient, count2, -tilt * i / count * coefficient, arm_tilt * i / count);
516}
517
518// adapted from https://rosettacode.org/wiki/Matrix_transposition#C
519static void mirai_transpose_image(struct mirai_image *image)
520{
521	int width = image->width;
522	int height = image->height;
523	image->width = height;
524	image->height = width;
525	
526	for (int start = 0 ; start < width * height ; start++)
527	{
528		int next = start;
529		int i = 0;
530		for (;;)
531		{
532			i++;
533			next = (next % height) * width + next / height;
534			if (next <= start) break;
535		}
536		
537		if (i == 1) continue;
538		if (next < start) continue;
539		
540		char tmp = image->colors[next = start];
541		for (;;)
542		{
543			int i = (next % height) * width + next / height;
544			image->colors[next] = (i == start) ? tmp : image->colors[i];
545			next = i;
546			if (next <= start) break;
547		}
548	}
549}
550
551static void mirai_flip_image(struct mirai_image *image)
552{
553	for (int x = 0 ; x < image->width / 2 ; x++)
554	for (int y = 0 ; y < image->height ; y++)
555	{
556		char color = image->colors[image->width - x - 1 + y * image->width];
557		image->colors[image->width - x - 1 + y * image->width] = image->colors[x + y * image->width];
558		image->colors[x + y * image->width] = color;
559	}
560}
561
562static void mirai_rotate_image_cw(struct mirai_image *image)
563{
564	mirai_transpose_image(image);
565	mirai_flip_image(image);
566}
567
568static void mirai_rotate_image_ccw(struct mirai_image *image)
569{
570	mirai_flip_image(image);
571	mirai_transpose_image(image);
572}
573
574
575// constant exports
576
577int mirai_game_size = sizeof (struct mirai_game);
578int mirai_width = 512;
579int mirai_height = 256;
580
581
582// function exports
583
584void mirai_start(struct mirai_game *game, struct mirai_engine *engine)
585{
586	game->engine = *engine;
587	
588	game->left_history = 0;
589	game->right_history = 0;
590	game->sprite_count = 0;
591	
592	for (int y = 0 ; y < sizeof mirai_ground / sizeof *mirai_ground ; y++)
593	for (int x = 0 ; x < sizeof *mirai_ground / sizeof **mirai_ground ; x++)
594	{
595		if (mirai_ground[y][x] == 2)
596		{
597			game->camera_x = x * 128;
598			game->camera_y = y * 128 - 512;
599			game->camera_sprite = game->sprites + game->sprite_count;
600			mirai_spawn(game, x * 128, y * 128, &mirai_mirai, &mirai_controls);
601		}
602	}
603	
604	mirai_assets();
605}
606
607void mirai_step(struct mirai_game *game, struct mirai_keys keys)
608{
609	game->left_history <<= 1;
610	game->left_history |= keys.left;
611	game->right_history <<= 1;
612	game->right_history |= keys.right;
613	
614	game->camera_x *= 3;
615	game->camera_y *= 3;
616	game->camera_x += game->camera_sprite->x;
617	game->camera_y += game->camera_sprite->y - 512;
618	game->camera_x /= 4;
619	game->camera_y /= 4;
620	
621	for (int x0 = -16 ; x0 <= 16 ; x0++)
622	for (int y0 = -8 ; y0 <= 8 ; y0++)
623	{
624		int x = x0 + game->camera_x / 128;
625		int y = y0 + game->camera_y / 128;
626		if (mirai_ground[y][x] != 0)
627			mirai_stamp(game, x * 128 + 64, y * 128 + 128, mirai_ground_image);
628	}
629	
630	for (int i = 0 ; i < game->sprite_count ; i++)
631	{
632		struct mirai_sprite *sprite = game->sprites + i;
633		
634		if (sprite->dy > 128)
635			sprite->knocked_time = 64;
636		else if (sprite->knocked_time != 0)
637			sprite->knocked_time--;
638		
639		sprite->ax = 0;
640		if (sprite->knocked_time == 0)
641		{
642			(*sprite->behave)(game, sprite);
643			
644			if (sprite->moving_direction != 0)
645				sprite->last_moving_direction = sprite->moving_direction;
646			
647			if (sprite->airborne)
648			{
649				if (sprite->moving_direction == 1)
650					sprite->ax = -3;
651				if (sprite->moving_direction == 2)
652					sprite->ax = 3;
653			}
654			else
655			{
656				if (sprite->moving_direction == 1)
657					sprite->ax = -4;
658				if (sprite->moving_direction == 2)
659					sprite->ax = 4;
660			}
661		}
662		
663		if (sprite->airborne == 0)
664			mirai_ground_physics(sprite);
665		else
666			mirai_airborne_physics(sprite);
667		
668		int dx;
669		int dy = sprite->dy;
670		
671		struct mirai_direction_animation_set *animations;
672		
673		if (sprite->last_moving_direction == 1)
674		{
675			dx = -sprite->dx;
676			animations = &sprite->type->animations.left;
677		}
678		if (sprite->last_moving_direction == 2)
679		{
680			dx = sprite->dx;
681			animations = &sprite->type->animations.right;
682		}
683		
684		struct mirai_animation *animation;
685		
686		if (dx > 32) dx = 32;
687		if (dx < 0) dx = 0;
688		if (dy < 0) dy = 0;
689		
690		if (sprite->knocked_time == 0)
691		{
692			animation = animations->standing + dx * (animations->count - 1) / 32;
693			sprite->animation_time += dx / 4;
694		}
695		else
696		{
697			animation = &animations->knocked;
698			if (dy == 0) sprite->animation_time = 0;
699			else sprite->animation_time += dy / 8;
700		}
701		
702		struct mirai_image *image = animation->images + sprite->animation_time * (animation->count - 1) / 256;
703		int y = 0;
704		if (sprite->knocked_time != 0) y = image->height * 4 - 56;
705		
706		mirai_stamp(game, sprite->x, sprite->y + y, image);
707	}
708	
709	mirai_text(game, 16, 16, "Mirai's Miscellaneous Misadventures M12 November 1 2021");
710	mirai_text(game, 16, 32, "a Senran Kagura fangame by zamfofex");
711}
712
713struct mirai_image *mirai_assets(void)
714{
715	static char done = 0;
716	if (done != 0) return mirai_images;
717	
718	int color_count = sizeof mirai_colors / sizeof *mirai_colors;
719	unsigned char *last_color = mirai_colors + color_count - 1;
720	
721	int image_count = sizeof mirai_images / sizeof *mirai_images;
722	struct mirai_image *last_image = mirai_images + image_count - 1;
723	
724	int animation_count = sizeof mirai_animations / sizeof *mirai_animations;
725	struct mirai_animation *last_animation = mirai_animations + animation_count - 1;
726	
727	last_image->width = 0;
728	last_image->height = 0;
729	
730	for (int i = 0 ; i < 256 ; i++)
731		mirai_ground_colors[i] = 0x3B;
732	
733	unsigned char *colors = mirai_colors;
734	struct mirai_image *images = mirai_images + 1;
735	struct mirai_animation *animations = mirai_animations;
736	
737	mirai_mirai.animations.left.standing = animations;
738	mirai_mirai.animations.left.count = 4;
739	mirai_mirai_animation_set(&animations, &images, &colors, 1, 4, 8, 64, 128);
740	
741	mirai_mirai.animations.right.standing = animations;
742	mirai_mirai.animations.right.count = 4;
743	mirai_mirai_animation_set(&animations, &images, &colors, -1, 4, 8, 64, 128);
744	
745	struct mirai_image *rotated_ccw = images;
746	mirai_mirai_animation(&mirai_mirai.animations.left.knocked, &images, &colors, 64 - 16, 8, 0, 128);
747	while (rotated_ccw != images) mirai_rotate_image_ccw(rotated_ccw++);
748	
749	struct mirai_image *rotated_cw = images;
750	mirai_mirai_animation(&mirai_mirai.animations.right.knocked, &images, &colors, 64 + 16, 8, 0, 128);
751	while (rotated_cw != images) mirai_rotate_image_cw(rotated_cw++);
752	
753	for (int i = 0 ; i < 10 ; i++)
754	{
755		mirai_glyphs[i] = images;
756		images->colors = colors;
757		images->height = 15;
758		
759		for (int x = 1 ; x < 12 ; x++)
760		{
761			int done = 1;
762			for (int y = 0 ; y < images->height ; y++)
763			{
764				if (mirai_digits[i][y][x] != 0)
765				{
766					done = 0;
767					break;
768				}
769			}
770			if (done == 0) continue;
771			images->width = x + 1;
772			break;
773		}
774		
775		for (int y = 0 ; y < images->height ; y++)
776		for (int x = 0 ; x < images->width ; x++)
777			*colors++ = mirai_digits[i][y][x] == 0 ? 0 : 108;
778		
779		images++;
780	}
781	
782	for (int c = 0 ; c < 2 ; c++)
783	for (int i = 0 ; i < 26 ; i++)
784	{
785		mirai_glyphs[i + 26 * c + 10] = images;
786		images->colors = colors;
787		images->height = 15;
788		
789		for (int x = 1 ; x < 12 ; x++)
790		{
791			int done = 1;
792			for (int y = 0 ; y < images->height ; y++)
793			{
794				if (mirai_letters[i][y * 2 + c][x] != 0)
795				{
796					done = 0;
797					break;
798				}
799			}
800			if (done == 0) continue;
801			images->width = x + 1;
802			break;
803		}
804		
805		for (int y = 0 ; y < images->height ; y++)
806		for (int x = 0 ; x < images->width ; x++)
807			*colors++ = mirai_letters[i][y * 2 + c][x] == 0 ? 0 : 108;
808		
809		images++;
810	}
811	
812	if (colors != last_color) return 0;
813	if (images != last_image - 1) return 0;
814	if (animations != last_animation) return 0;
815	
816	done = 1;
817	return mirai_images;
818}