Mirai's Miscellaneous Misadventures
M24 / engines / x86.c
#include <mimimi/allocators.h>
#include <mimimi/test.h>
#include <mimimi/engines.h>
#include <mimimi/geometry.h>
#include <mimimi/assets.h>
#include <mimimi/chapters.h>
#include <mimimi/behaviors.h>
struct mimimi_vbe_screen
{
unsigned int *buffer;
unsigned short int width;
unsigned short int height;
unsigned short int bytes_per_line;
unsigned short int bytes_per_pixel;
};
extern struct mimimi_vbe_screen mimimi_vbe_screen;
void mimimi_x86_exit(void);
extern unsigned char mimimi_x86_heap_start;
static unsigned char *mimimi_x86_heap = &mimimi_x86_heap_start;
static unsigned char mimimi_x86_blocks[8192] = {};
static void *mimimi_x86_allocate(unsigned int size)
{
int blocks = (size - 1) / 1024 + 1;
for (int i = 0 ; i < 8192 ; i++)
{
for (int j = 0 ; j < blocks ; j++)
{
if (mimimi_x86_blocks[i + j] != 0)
goto next;
}
mimimi_x86_blocks[i] = 1;
for (int j = 1 ; j < blocks ; j++)
mimimi_x86_blocks[i + j] = 2;
unsigned char *data = mimimi_x86_heap + i * 1024;
return data;
next:;
}
mimimi_x86_exit();
}
static void mimimi_x86_deallocate(void *data0)
{
unsigned char *data = data0;
int block = (data - mimimi_x86_heap) / 1024;
mimimi_x86_blocks[block] = 0;
for (int i = 1 ; mimimi_x86_blocks[block + i] == 2 ; i++)
mimimi_x86_blocks[block + i] = 0;
}
static void *mimimi_x86_reallocate(void *data0, unsigned int size)
{
if (data0 == 0) return mimimi_x86_allocate(size);
unsigned char *data = data0;
int block = (data - mimimi_x86_heap) / 1024;
int current_count = 1;
while (mimimi_x86_blocks[block + current_count] == 2) current_count++;
int target_count = (size - 1) / 1024 + 1;
if (target_count <= current_count)
{
for (int i = target_count ; i < current_count ; i++)
mimimi_x86_blocks[block + i] = 0;
return data;
}
for (int i = current_count ; i < target_count ; i++)
{
if (mimimi_x86_blocks[block + i] != 0)
{
unsigned char *new = mimimi_x86_allocate(size);
for (unsigned int i = 0 ; i < current_count * 1024 ; i++)
new[i] = data[i];
mimimi_x86_deallocate(data);
return new;
}
}
for (int i = current_count ; i < target_count ; i++)
mimimi_x86_blocks[block + i] = 2;
return data;
}
static struct mimimi_allocator mimimi_x86_allocator_value = {&mimimi_x86_allocate, &mimimi_x86_reallocate, &mimimi_x86_deallocate, 0};
static struct mimimi_allocator *mimimi_x86_allocator = &mimimi_x86_allocator_value;
static unsigned char *mimimi_x86_buffer;
static unsigned char *mimimi_x86_out_buffer;
static void mimimi_x86_stamp(void *data, int x1, int y1, struct mimimi_image *image)
{
int x0 = 0;
int y0 = 0;
if (x1 < 0) x0 = -x1;
if (y1 < 0) y0 = -y1;
int width = image->width;
int height = image->height;
if (width + x1 > 512) width = 512 - x1;
if (height + y1 > 256) height = 256 - y1;
for (int y = y0 ; y < height ; y++)
for (int x = x0 ; x < width ; x++)
{
unsigned char color = image->colors[x + y * image->width];
if (color == 0) continue;
int x2 = x + x1;
int y2 = y + y1;
mimimi_x86_buffer[x2 + y2 * 512] = color;
}
}
static struct mimimi_chapter *chapter;
void mimimi_x86_start(void)
{
mimimi_x86_buffer = mimimi_x86_allocate(512 * 256);
mimimi_x86_out_buffer = mimimi_x86_allocate(512 * 256 * 4);
static struct mimimi_size size = {512, 256};
chapter = mimimi_test(mimimi_x86_allocator);
chapter->engine->size = &size;
chapter->engine->stamp = &mimimi_x86_stamp;
}
void mimimi_x86_step(void)
{
extern unsigned char mimimi_x86_left;
extern unsigned char mimimi_x86_right;
chapter->left = mimimi_x86_left;
chapter->right = mimimi_x86_right;
(*chapter->behavior->behave)(chapter->behavior->data);
static unsigned char rch[] = {0x11, 0x44, 0x77, 0x99, 0xCC, 0xFF};
static unsigned char gch[] = {0x11, 0x33, 0x55, 0x77, 0x99, 0xBB, 0xDD, 0xFF};
static unsigned char bch[] = {0x22, 0x55, 0x88, 0xBB, 0xEE};
unsigned int width = 512;
unsigned int height = 256;
unsigned int x0 = (mimimi_vbe_screen.width - width) / 2;
unsigned int y0 = (mimimi_vbe_screen.height - height) / 2;
if (mimimi_vbe_screen.width < width) x0 = 0, width = mimimi_vbe_screen.width;
if (mimimi_vbe_screen.height < height) y0 = 0, height = mimimi_vbe_screen.height;
for (unsigned int y = 0 ; y < height ; y++)
for (unsigned int x = 0 ; x < width ; x++)
{
unsigned char color = mimimi_x86_buffer[x + y * 512];
unsigned int i = (x + y * 512) * 4;
if (color < 0x10)
{
unsigned char ch = color * 0x11;
mimimi_x86_out_buffer[i + 0] = ch;
mimimi_x86_out_buffer[i + 1] = ch;
mimimi_x86_out_buffer[i + 2] = ch;
}
else
{
color -= 0x10;
unsigned char r, g, b;
r = rch[(color / 40) % 6];
g = gch[(color / 5) % 8];
b = bch[(color / 1) % 5];
mimimi_x86_out_buffer[i + 0] = b;
mimimi_x86_out_buffer[i + 1] = g;
mimimi_x86_out_buffer[i + 2] = r;
}
}
unsigned int *buffer = (void *)mimimi_x86_out_buffer;
unsigned int o = x0 + y0 * mimimi_vbe_screen.bytes_per_line / 4;
for (unsigned int y = 0 ; y < height ; y++)
for (unsigned int x = 0 ; x < width ; x++)
{
unsigned int i = x + y * 512;
unsigned int j = x + y * mimimi_vbe_screen.bytes_per_line / 4;
mimimi_vbe_screen.buffer[j + o] = buffer[i];
}
}