Mirai's Miscellaneous Misadventures
M13 / game.c
#include "mimimi.h"
#include "math.c"
struct mirai_animation
{
int count;
struct mirai_image *images;
};
struct mirai_direction_animation_set
{
int count;
struct mirai_animation *standing;
struct mirai_animation knocked;
};
struct mirai_animation_set
{
struct mirai_direction_animation_set left, right;
};
struct mirai_sprite_type
{
struct mirai_animation_set animations;
int width;
int height;
};
struct mirai_sprite
{
struct mirai_sprite_type *type;
int x, y;
int dx, dy;
int ax;
char airborne;
char moving_direction;
char facing_direction;
void (*behave)(struct mirai_game *game, struct mirai_sprite *sprite);
unsigned char animation_time;
unsigned char knocked_time;
struct mirai_sprite *ai_target;
int ai_target_x;
int ai_target_y;
unsigned char ai_attack_time;
unsigned char immunity_time;
unsigned char pristinity;
};
struct mirai_rotating_image_row
{
int size;
unsigned char count;
unsigned char colors[64];
};
struct mirai_rotating_image
{
int count;
int oy;
struct mirai_rotating_image_row rows[];
};
struct mirai_model_layer
{
int count;
struct mirai_rotating_image *images[];
};
struct mirai_model
{
struct mirai_model_layer *head;
struct mirai_model_layer *torso;
struct mirai_model_layer *left_arm;
struct mirai_model_layer *right_arm;
};
#include "assets.c"
static int mirai_gravity = 4;
static unsigned char mirai_ground_colors[16 * 16];
static unsigned char mirai_colors[80686];
static struct mirai_image mirai_images[145] =
{
{16, 16, mirai_ground_colors},
};
static struct mirai_animation mirai_animations[9];
static struct mirai_image *mirai_ground_image = mirai_images;
static struct mirai_image *mirai_glyphs[26 * 2 + 10];
static struct mirai_sprite_type mirai_mirai = {{}, 80, 250};
struct mirai_game
{
struct mirai_engine engine;
struct mirai_sprite sprites[256];
unsigned char sprite_count;
unsigned int left_history:16;
unsigned int right_history:16;
struct mirai_sprite *camera_sprite;
int camera_x;
int camera_y;
};
static void mirai_stamp(struct mirai_game *game, int x, int y, struct mirai_image *image)
{
x -= game->camera_x;
x += mirai_width * 4;
y -= game->camera_y;
y += mirai_height * 4;
x -= image->width * 4;
y -= image->height * 8;
(*game->engine.stamp)(game->engine.data, x / 8, y / 8, image);
}
static int mirai_text(struct mirai_game *game, int x, int y, char *text)
{
for (int i = 0 ; *text != '\0' ; i++)
{
char ch = *text++;
if (ch == ' ')
{
x += 4;
continue;
}
struct mirai_image *image;
if (ch >= '0' && ch <= '9')
{
image = mirai_glyphs[ch - '0' + 0];
}
else if (ch >= 'A' && ch <= 'Z')
{
image = mirai_glyphs[ch - 'A' + 10];
}
else if (ch >= 'a' && ch <= 'z')
{
image = mirai_glyphs[ch - 'a' + 36];
}
else
{
continue;
}
(*game->engine.stamp)(game->engine.data, x - 1, y - image->height + 5, image);
x += image->width - 1;
}
return x;
}
static void mirai_wall_physics(struct mirai_sprite *sprite)
{
int x0 = sprite->x;
int x1 = sprite->type->width / 2;
int y0 = sprite->y;
int y1 = sprite->type->height;
int top = (y0 - y1) / 128;
int top2 = top - 1;
int bottom = (y0 - 127) / 128;
int bottom2 = bottom - 1;
int left = (x0 - x1) / 128;
int right = (x0 + x1) / 128;
if (
mirai_ground[bottom][left] != 0 && mirai_ground[bottom2][left] != 0 ||
mirai_ground[top][left] != 0 && mirai_ground[top2][left]
)
{
if (sprite->dx < 0) sprite->dx = 0;
sprite->x = (left + 1) * 128 + x1;
}
if (
mirai_ground[bottom][right] != 0 && mirai_ground[bottom2][right] != 0 ||
mirai_ground[top][right] != 0 && mirai_ground[top2][right]
)
{
if (sprite->dx > 0) sprite->dx = 0;
sprite->x = right * 128 - x1 - 1;
}
}
static void mirai_step_physics(struct mirai_sprite *sprite)
{
int x0 = sprite->x;
int x1 = sprite->type->width / 2;
int y0 = sprite->y;
int y1 = sprite->type->height;
int top = (y0 - y1) / 128;
int bottom = (y0 - 127) / 128;
int left = (x0 - x1) / 128;
int right = (x0 + x1) / 128;
if (mirai_ground[bottom][left] != 0 && mirai_ground[top][left] == 0)
sprite->y = bottom * 128;
if (mirai_ground[bottom][right] != 0 && mirai_ground[top][right] == 0)
sprite->y = bottom * 128;
}
static void mirai_ceiling_physics(struct mirai_sprite *sprite)
{
int x0 = sprite->x;
int x1 = sprite->type->width / 2;
int y0 = sprite->y;
int y1 = sprite->type->height;
int top = (y0 - y1) / 128;
int top2 = top - 1;
int left = (x0 - x1) / 128;
int right = (x0 + x1) / 128;
if (sprite->dy > 0) return;
if (mirai_ground[top][left] != 0)
if (mirai_ground[top][right] != 0)
if (mirai_ground[top2][left] != 0 || mirai_ground[top2][right] != 0)
{
sprite->dy = 0;
sprite->y = (top + 1) * 128 + y1;
}
}
static void mirai_landing_physics(struct mirai_sprite *sprite)
{
int x0 = sprite->x;
int x1 = sprite->type->width / 2;
int y0 = sprite->y;
int bottom = y0 / 128;
int left = (x0 - x1) / 128;
int right = (x0 + x1) / 128;
if (sprite->dy < 0) return;
if (mirai_ground[bottom][left] != 0 || mirai_ground[bottom][right] != 0)
{
sprite->airborne = 0;
sprite->dy = 0;
sprite->y = bottom * 128;
}
}
static void mirai_fall_physics(struct mirai_sprite *sprite)
{
int x0 = sprite->x;
int x1 = sprite->type->width / 2;
int y0 = sprite->y;
int bottom = y0 / 128;
int center = x0 / 128;
int left = (x0 - x1) / 128;
int right = (x0 + x1) / 128;
if (mirai_ground[bottom][left] == 0 && mirai_ground[bottom][right] == 0)
{
if (mirai_ground[bottom + 1][center] == 0)
sprite->airborne = 1;
else
sprite->y = (bottom + 1) * 128;
}
}
static void mirai_physics_dynamics(struct mirai_sprite *sprite)
{
sprite->dx += sprite->ax;
sprite->x += sprite->dx;
sprite->y += sprite->dy;
}
static void mirai_ground_physics(struct mirai_sprite *sprite)
{
sprite->dx *= 7;
sprite->dx /= 8;
sprite->dy = 0;
mirai_physics_dynamics(sprite);
mirai_step_physics(sprite);
mirai_wall_physics(sprite);
mirai_fall_physics(sprite);
}
static void mirai_airborne_physics(struct mirai_sprite *sprite)
{
sprite->dx *= 15;
sprite->dx /= 16;
sprite->dy += mirai_gravity;
mirai_physics_dynamics(sprite);
mirai_ceiling_physics(sprite);
mirai_wall_physics(sprite);
mirai_landing_physics(sprite);
}
static void mirai_jump(struct mirai_sprite *sprite)
{
if (sprite->airborne) return;
sprite->airborne = 1;
sprite->dy = -64;
}
static void mirai_damage(struct mirai_game *game, struct mirai_sprite *sprite, int damage, int attack_y, int attack_width, int attack_height)
{
sprite->ai_attack_time = 32;
int x1 = sprite->x - attack_width;
int y1 = sprite->y + attack_y;
if (sprite->facing_direction == 2) x1 += attack_width;
int x2 = x1 + attack_width;
int y2 = y1 + attack_height;
for (int i = 0 ; i < game->sprite_count ; i++)
{
struct mirai_sprite *other = game->sprites + i;
if (other == sprite) continue;
if (other->immunity_time != 0) continue;
int x = other->x;
int y = other->y;
if (x > x1 && x < x2)
if (y > y1 && y < y2)
{
other->airborne = 1;
other->dy -= 32;
if (other->x > sprite->x)
other->dx += 32;
else
other->dx -= 32;
if (other->pristinity < damage)
other->knocked_time = 128;
else
other->pristinity -= damage;
}
}
}
static void mirai_attack(struct mirai_game *game, struct mirai_sprite *sprite)
{
mirai_damage(game, sprite, 64, -256, 512, 512);
}
static void mirai_rapid_attack(struct mirai_game *game, struct mirai_sprite *sprite)
{
}
static unsigned char mirai_count_oscillations(unsigned int history)
{
unsigned char count = 0;
unsigned char prev = history&1;
for (int i = 0 ; i < 16 ; i++)
{
if ((history&1) != prev) count++;
prev = history&1;
history >>= 1;
}
return count;
}
static void mirai_controls(struct mirai_game *game, struct mirai_sprite *sprite)
{
unsigned char left_oscillations = mirai_count_oscillations(game->left_history);
unsigned char right_oscillations = mirai_count_oscillations(game->right_history);
switch (sprite->moving_direction)
{
case 0:
if ((game->left_history&1) != 0)
sprite->moving_direction = 1;
if ((game->right_history&1) != 0)
sprite->moving_direction = 2;
break;
case 1:
if ((game->left_history&1) == 0)
sprite->moving_direction = 0;
else if (left_oscillations > 1)
mirai_jump(sprite);
if ((game->right_history&1) != 0)
{
if (right_oscillations == 0)
mirai_rapid_attack(game, sprite);
}
if ((game->right_history&1) != 0 && (game->right_history&2) == 0)
mirai_attack(game, sprite);
break;
case 2:
if ((game->right_history&1) == 0)
sprite->moving_direction = 0;
else if (right_oscillations > 1)
mirai_jump(sprite);
if ((game->left_history&1) != 0)
{
if (left_oscillations == 0)
mirai_rapid_attack(game, sprite);
}
if ((game->left_history&1) != 0 && (game->left_history&2) == 0)
mirai_attack(game, sprite);
break;
}
}
static void mirai_ai(struct mirai_game *game, struct mirai_sprite *sprite)
{
int x = sprite->x - sprite->ai_target->x;
int y = sprite->y - sprite->ai_target->y;
int abs_x = x;
int abs_y = y;
if (abs_x < 0) abs_x = -abs_x;
if (abs_y < 0) abs_y = -abs_y;
char attack = 1;
if (abs_x > 2048 || abs_y > 2048)
{
int distance_x = sprite->ai_target->x - sprite->ai_target_x;
int distance_y = sprite->ai_target->y - sprite->ai_target_y;
if (distance_x < 0) distance_x = -distance_x;
if (distance_y < 0) distance_y = -distance_y;
if (distance_x > 4096 || distance_y > 4096)
{
attack = 0;
x = sprite->x - sprite->ai_target_x;
y = sprite->y - sprite->ai_target_y;
}
}
sprite->moving_direction = 0;
if (x > 256)
sprite->moving_direction = 1;
else if (x < -256)
sprite->moving_direction = 2;
else if (attack && sprite->ai_attack_time == 0)
mirai_attack(game, sprite);
if (y > 512) mirai_jump(sprite);
}
static 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))
{
if (game->sprite_count == 0xFF) return;
struct mirai_sprite *sprite = game->sprites + game->sprite_count;
game->sprite_count++;
sprite->type = type;
sprite->x = x;
sprite->y = y;
sprite->dx = 0;
sprite->dy = 0;
sprite->ax = 0;
sprite->airborne = 1;
sprite->moving_direction = 0;
sprite->facing_direction = 1;
sprite->animation_time = 0;
sprite->behave = behave;
sprite->ai_target_x = x;
sprite->ai_target_y = y;
sprite->ai_attack_time = -1;
sprite->immunity_time = 0;
sprite->pristinity = -1;
}
static unsigned char mirai_rotating_image_pixel(struct mirai_rotating_image *rotating_image, unsigned char angle, int x, int y)
{
y += rotating_image->oy;
int h = rotating_image->count;
if (y < 0) return 0;
if (y >= h) return 0;
int w = rotating_image->rows[y].size;
if (x < -w / 2) return 0;
if (x >= w / 2) return 0;
x += w / 2;
int count = rotating_image->rows[y].count;
int a = angle;
a *= count;
a += 128;
a /= 256;
a += x;
a %= count;
return rotating_image->rows[y].colors[a];
}
static void mirai_rotating_image_stamp(struct mirai_image *image, struct mirai_rotating_image *rotating_image, unsigned char y_angle, unsigned char z_angle, int x0, int y0, int behind)
{
if (behind != 0) y_angle += 128;
int width = image->width;
int height = image->height;
for (int x = 0 ; x < width ; x++)
for (int y = 0 ; y < height ; y++)
{
if (behind != 0 && image->colors[x + y * width] != 0) continue;
int x1 = x - x0;
int y1 = y - y0;
int x2 = x1 + y1 * mirai_sine[z_angle] / 127;
int y2 = y1;
if (behind != 0) x2 = -x2 - 1;
unsigned char color = mirai_rotating_image_pixel(rotating_image, y_angle, x2, y2);
if (color == 0) continue;
image->colors[x + y * width] = color;
}
}
static void mirai_animation_layer(struct mirai_image *image, struct mirai_model_layer *layer, unsigned char y_angle, unsigned char z_angle, int x0, int y0)
{
for (int i = 0 ; i < layer->count ; i++)
{
mirai_rotating_image_stamp(image, layer->images[i], y_angle, z_angle, x0, y0, 0);
mirai_rotating_image_stamp(image, layer->images[i], y_angle, z_angle, x0, y0, 1);
}
}
static void mirai_animation_frame(struct mirai_image *image, unsigned char **colors, struct mirai_model *model, unsigned char y_angle, unsigned char z_angle, unsigned char arm_angle)
{
image->colors = *colors;
image->width = 26;
image->height = 36;
*colors += image->width * image->height;
for (int x = 0 ; x < image->width ; x++)
for (int y = 0 ; y < image->height ; y++)
image->colors[x + y * image->width] = 0;
int x = image->width / 2;
int head_y = 13;
int head_x = x + mirai_sine[z_angle] * (image->height - head_y) / 127;
int arm_y = 16;
int arm_x = x + mirai_sine[z_angle] * (image->height - arm_y) / 127;
int left_arm_x = arm_x + 10 * mirai_sine[y_angle] / 256;
int right_arm_x = arm_x - 10 * mirai_sine[y_angle] / 256;
if ((y_angle + 64) % 256 < 128)
{
mirai_animation_layer(image, model->left_arm, y_angle, arm_angle, left_arm_x, arm_y);
mirai_animation_layer(image, model->torso, y_angle, z_angle, x, image->height);
mirai_animation_layer(image, model->right_arm, y_angle, -arm_angle, right_arm_x, arm_y);
}
else
{
mirai_animation_layer(image, model->right_arm, y_angle, -arm_angle, right_arm_x, arm_y);
mirai_animation_layer(image, model->torso, y_angle, z_angle, x, image->height);
mirai_animation_layer(image, model->left_arm, y_angle, arm_angle, left_arm_x, arm_y);
}
mirai_animation_layer(image, model->head, y_angle, 0, head_x, head_y);
}
static void mirai_animation(struct mirai_animation *animation, struct mirai_image **images, unsigned char **colors, struct mirai_model *model, int count, unsigned char y_angle, unsigned char z_angle, unsigned char arm_angle)
{
animation->count = count;
animation->images = *images;
for (int i = 0 ; i < count ; i++)
mirai_animation_frame((*images)++, colors, model, y_angle, z_angle, arm_angle * mirai_sine[i * 255 / count] / 127);
}
static void mirai_animation_set(struct mirai_animation **animations, struct mirai_image **images, unsigned char **colors, struct mirai_model *model, int coefficient, int count, int count2, unsigned char z_angle, unsigned char arm_angle)
{
for (int i = 0 ; i < count ; i++)
mirai_animation((*animations)++, images, colors, model, count2, 64 + (12 + 34 * i / count) * coefficient, -z_angle * i / count * coefficient, arm_angle * i / count);
}
static void mirai_transpose_image(struct mirai_image *image)
{
int width = image->width;
int height = image->height;
image->width = height;
image->height = width;
for (int start = 0 ; start < width * height ; start++)
{
int next = start;
int i = 0;
for (;;)
{
i++;
next = (next % height) * width + next / height;
if (next <= start) break;
}
if (i == 1) continue;
if (next < start) continue;
char tmp = image->colors[next = start];
for (;;)
{
int i = (next % height) * width + next / height;
image->colors[next] = (i == start) ? tmp : image->colors[i];
next = i;
if (next <= start) break;
}
}
}
static void mirai_flip_image(struct mirai_image *image)
{
for (int x = 0 ; x < image->width / 2 ; x++)
for (int y = 0 ; y < image->height ; y++)
{
unsigned char color = image->colors[image->width - x - 1 + y * image->width];
image->colors[image->width - x - 1 + y * image->width] = image->colors[x + y * image->width];
image->colors[x + y * image->width] = color;
}
}
static void mirai_rotate_image_cw(struct mirai_image *image)
{
mirai_transpose_image(image);
mirai_flip_image(image);
}
static void mirai_rotate_image_ccw(struct mirai_image *image)
{
mirai_flip_image(image);
mirai_transpose_image(image);
}
static void mirai_model(struct mirai_sprite_type *type, struct mirai_model *model, struct mirai_animation **animations, struct mirai_image **images, unsigned char **colors, int count, int count2, unsigned char z_angle, unsigned char arm_angle, unsigned char arm_flail_angle)
{
type->animations.left.standing = *animations;
type->animations.left.count = 4;
mirai_animation_set(animations, images, colors, model, 1, count, count2, z_angle, arm_angle);
type->animations.right.standing = *animations;
type->animations.right.count = 4;
mirai_animation_set(animations, images, colors, model, -1, count, count2, z_angle, arm_angle);
struct mirai_image *rotated_cw = *images;
mirai_animation(&type->animations.left.knocked, images, colors, model, count2, 64 + 16, 0, arm_flail_angle);
while (rotated_cw != *images) mirai_rotate_image_cw(rotated_cw++);
struct mirai_image *rotated_ccw = *images;
mirai_animation(&type->animations.right.knocked, images, colors, model, count2, 64 - 16, 0, arm_flail_angle);
while (rotated_ccw != *images) mirai_rotate_image_ccw(rotated_ccw++);
}
int mirai_game_size = sizeof (struct mirai_game);
int mirai_width = 512;
int mirai_height = 256;
void mirai_start(struct mirai_game *game, struct mirai_engine *engine)
{
game->engine = *engine;
game->left_history = 0;
game->right_history = 0;
game->sprite_count = 0;
for (int y = 0 ; y < sizeof mirai_ground / sizeof *mirai_ground ; y++)
for (int x = 0 ; x < sizeof *mirai_ground / sizeof **mirai_ground ; x++)
{
if (mirai_ground[y][x] == 2)
{
game->camera_x = x * 128;
game->camera_y = y * 128 - 512;
game->camera_sprite = game->sprites + game->sprite_count;
mirai_spawn(game, x * 128, y * 128, &mirai_mirai, &mirai_controls);
}
if (mirai_ground[y][x] == 3)
{
int i = game->sprite_count;
mirai_spawn(game, x * 128, y * 128, &mirai_mirai, &mirai_ai);
game->sprites[i].ai_target = game->sprites;
}
}
mirai_assets();
}
void mirai_step(struct mirai_game *game, struct mirai_keys keys)
{
game->left_history <<= 1;
game->left_history |= keys.left;
game->right_history <<= 1;
game->right_history |= keys.right;
game->camera_x *= 3;
game->camera_y *= 3;
game->camera_x += game->camera_sprite->x;
game->camera_y += game->camera_sprite->y - 512;
game->camera_x /= 4;
game->camera_y /= 4;
for (int x0 = -16 ; x0 <= 16 ; x0++)
for (int y0 = -8 ; y0 <= 8 ; y0++)
{
int x = x0 + game->camera_x / 128;
int y = y0 + game->camera_y / 128;
if (mirai_ground[y][x] != 0)
mirai_stamp(game, x * 128 + 64, y * 128 + 128, mirai_ground_image);
}
for (int i = 0 ; i < game->sprite_count ; i++)
{
struct mirai_sprite *sprite = game->sprites + i;
if (sprite->dy > 128)
if (sprite->knocked_time < 64)
sprite->knocked_time = 64;
if (sprite->knocked_time != 0)
{
sprite->knocked_time--;
sprite->immunity_time = 64;
}
if (sprite->immunity_time != 0)
{
sprite->pristinity = -1;
sprite->immunity_time--;
}
if (sprite->pristinity != 0xFF)
sprite->pristinity++;
if (sprite->ai_attack_time != 0)
sprite->ai_attack_time--;
sprite->ax = 0;
if (sprite->knocked_time == 0)
{
(*sprite->behave)(game, sprite);
if (sprite->moving_direction != 0)
sprite->facing_direction = sprite->moving_direction;
if (sprite->airborne)
{
if (sprite->moving_direction == 1)
sprite->ax = -3;
if (sprite->moving_direction == 2)
sprite->ax = 3;
}
else
{
if (sprite->moving_direction == 1)
sprite->ax = -4;
if (sprite->moving_direction == 2)
sprite->ax = 4;
}
}
if (sprite->airborne == 0)
mirai_ground_physics(sprite);
else
mirai_airborne_physics(sprite);
int dx;
int dy = sprite->dy;
struct mirai_direction_animation_set *animations;
if (sprite->facing_direction == 1)
{
dx = -sprite->dx;
animations = &sprite->type->animations.left;
}
if (sprite->facing_direction == 2)
{
dx = sprite->dx;
animations = &sprite->type->animations.right;
}
struct mirai_animation *animation;
if (dx > 32) dx = 32;
if (dx < 0) dx = 0;
if (dy < 0) dy = 0;
if (sprite->knocked_time == 0)
{
animation = animations->standing + dx * (animations->count - 1) / 32;
sprite->animation_time += dx / 4;
}
else
{
animation = &animations->knocked;
if (dy == 0) sprite->animation_time = 0;
else sprite->animation_time += dy / 8;
}
struct mirai_image *image = animation->images + sprite->animation_time * (animation->count - 1) / 256;
int y = 0;
if (sprite->knocked_time != 0) y = image->height * 4 - 56;
mirai_stamp(game, sprite->x, sprite->y + y, image);
}
mirai_text(game, 16, 16, "Mirai's Miscellaneous Misadventures M13");
mirai_text(game, 16, 32, "a Senran Kagura fangame by zamfofex");
mirai_text(game, 16, 48, "December 10 2021");
}
struct mirai_image *mirai_assets(void)
{
static char done = 0;
if (done != 0) return mirai_images;
int color_count = sizeof mirai_colors / sizeof *mirai_colors;
unsigned char *last_color = mirai_colors + color_count - 1;
int image_count = sizeof mirai_images / sizeof *mirai_images;
struct mirai_image *last_image = mirai_images + image_count - 1;
int animation_count = sizeof mirai_animations / sizeof *mirai_animations;
struct mirai_animation *last_animation = mirai_animations + animation_count - 1;
last_image->width = 0;
last_image->height = 0;
for (int i = 0 ; i < 256 ; i++)
mirai_ground_colors[i] = 0x3B;
unsigned char *colors = mirai_colors;
struct mirai_image *images = mirai_images + 1;
struct mirai_animation *animations = mirai_animations;
mirai_model(&mirai_mirai, &mirai_mirai_yang, &animations, &images, &colors, 4, 8, 9, 16, 32);
for (int i = 0 ; i < 10 ; i++)
{
mirai_glyphs[i] = images;
images->colors = colors;
images->height = 15;
for (int x = 1 ; x < 12 ; x++)
{
int done = 1;
for (int y = 0 ; y < images->height ; y++)
{
if (mirai_digits[i][y][x] != 0)
{
done = 0;
break;
}
}
if (done == 0) continue;
images->width = x + 1;
break;
}
for (int y = 0 ; y < images->height ; y++)
for (int x = 0 ; x < images->width ; x++)
*colors++ = mirai_digits[i][y][x] == 0 ? 0 : 108;
images++;
}
for (int c = 0 ; c < 2 ; c++)
for (int i = 0 ; i < 26 ; i++)
{
mirai_glyphs[i + 26 * c + 10] = images;
images->colors = colors;
images->height = 15;
for (int x = 1 ; x < 12 ; x++)
{
int done = 1;
for (int y = 0 ; y < images->height ; y++)
{
if (mirai_letters[i][y * 2 + c][x] != 0)
{
done = 0;
break;
}
}
if (done == 0) continue;
images->width = x + 1;
break;
}
for (int y = 0 ; y < images->height ; y++)
for (int x = 0 ; x < images->width ; x++)
*colors++ = mirai_letters[i][y * 2 + c][x] == 0 ? 0 : 108;
images++;
}
if (colors != last_color) return 0;
if (images != last_image - 1) return 0;
if (animations != last_animation) return 0;
done = 1;
return mirai_images;
}