luma/luma/vid/main.c
2025-07-06 17:58:57 +03:00

583 lines
20 KiB
C

#include<stddef.h>
#include<stdint.h>
#include"../sys.h"
#include"../std.h"
#include"api.h"
#include"kmeans.h"
asm("modentry:\n"
"mov $stack + 2816, %esp\n"
"call startc");
static uint8_t *FrameBuffer;
typedef struct {
uint32_t name;
uint32_t len;
uint8_t code[];
} DL;
static struct {
size_t idx;
uint8_t *buf;
} DLs;
typedef struct {
uint16_t w, h;
uint8_t format;
uint8_t data[];
} Image;
static struct {
size_t idx;
Image **handles;
} Images;
char stack[2816];
static uint8_t(*colorFunc)(uint16_t x, uint16_t y);
static uint8_t color_flat[] = {0xB8, 0x78, 0x56, 0x34, 0x12, 0xC3};
static uint8_t gradCols[16];
__attribute__((optimize("Ofast"))) static uint8_t color_grad(uint16_t x, uint16_t y) {
static uint8_t matrix[16][16] = {{0, 64, 16, 80, 4, 68, 20, 84, 1, 65, 17, 81, 5, 69, 21, 85}, {192, 128, 208, 144, 196, 132, 212, 148, 193, 129, 209, 145, 197, 133, 213, 149}, {48, 112, 32, 96, 52, 116, 36, 100, 49, 113, 33, 97, 53, 117, 37, 101}, {240, 176, 224, 160, 244, 180, 228, 164, 241, 177, 225, 161, 245, 181, 229, 165}, {12, 76, 28, 92, 8, 72, 24, 88, 13, 77, 29, 93, 9, 73, 25, 89}, {204, 140, 220, 156, 200, 136, 216, 152, 205, 141, 221, 157, 201, 137, 217, 153}, {60, 124, 44, 108, 56, 120, 40, 104, 61, 125, 45, 109, 57, 121, 41, 105}, {252, 188, 236, 172, 248, 184, 232, 168, 253, 189, 237, 173, 249, 185, 233, 169}, {3, 67, 19, 83, 7, 71, 23, 87, 2, 66, 18, 82, 6, 70, 22, 86}, {195, 131, 211, 147, 199, 135, 215, 151, 194, 130, 210, 146, 198, 134, 214, 150}, {51, 115, 35, 99, 55, 119, 39, 103, 50, 114, 34, 98, 54, 118, 38, 102}, {243, 179, 227, 163, 247, 183, 231, 167, 242, 178, 226, 162, 246, 182, 230, 166}, {15, 79, 31, 95, 11, 75, 27, 91, 14, 78, 30, 94, 10, 74, 26, 90}, {207, 143, 223, 159, 203, 139, 219, 155, 206, 142, 222, 158, 202, 138, 218, 154}, {63, 127, 47, 111, 59, 123, 43, 107, 62, 126, 46, 110, 58, 122, 42, 106}, {255, 191, 239, 175, 251, 187, 235, 171, 254, 190, 238, 174, 250, 186, 234, 170}};
int i = x * 256 / 320;
i += matrix[x % 16][y % 16] / 16;
i /= 16;
if(i > 15) i = 15;
return gradCols[i];
}
__attribute__((optimize("Ofast"))) static void select_planes(int planes) {
asm("out %%al, %%dx" : : "a"(2), "d"(0x3C4));
asm("out %%al, %%dx" : : "a"(planes), "d"(0x3C5));
}
__attribute__((optimize("Ofast"))) static void clear() {
if((uintptr_t) colorFunc == (uintptr_t) color_flat) {
uint8_t col = colorFunc(0, 0);
select_planes(15);
for(int i = 0; i < 4800; i++) {
((uint32_t*) FrameBuffer)[i] = col | (col << 8) | (col << 16) | (col << 24);
}
} else {
for(int p = 0; p < 4; p++) {
select_planes(1 << p);
for(int y = 0; y < 240; y++) {
for(int x = 0; x < 80; x++) {
FrameBuffer[80 * y + x] = colorFunc(x * 4 + p, y);
}
}
}
}
}
__attribute__((optimize("Ofast"))) static void rect(int x1, int y1, int x2, int y2) {
select_planes(1 << ((x1 + 0) & 3));
for(int y = y1; y <= y2; y++) {
for(int x = x1 + 0; x <= x2; x += 4) {
FrameBuffer[80 * y + x / 4] = colorFunc(x, y);
}
}
select_planes(1 << ((x1 + 1) & 3));
for(int y = y1; y <= y2; y++) {
for(int x = x1 + 1; x <= x2; x += 4) {
FrameBuffer[80 * y + x / 4] = colorFunc(x, y);
}
}
select_planes(1 << ((x1 + 2) & 3));
for(int y = y1; y <= y2; y++) {
for(int x = x1 + 2; x <= x2; x += 4) {
FrameBuffer[80 * y + x / 4] = colorFunc(x, y);
}
}
select_planes(1 << ((x1 + 3) & 3));
for(int y = y1; y <= y2; y++) {
for(int x = x1 + 3; x <= x2; x += 4) {
FrameBuffer[80 * y + x / 4] = colorFunc(x, y);
}
}
}
__attribute__((optimize("Ofast"))) static void image(Image *img, uint16_t subX, uint16_t subY, uint16_t x, uint16_t y, uint16_t width, uint16_t height) {
if(img->format == LUMA_VID_IMAGE_FORMAT_BLALPHA) {
uint8_t c = colorFunc(0, 0);
for(int ix = 0; ix < width; ix++) {
select_planes(1 << ((x + ix) & 3));
for(int iy = 0; iy < height; iy++) {
uint8_t v = img->data[(iy * img->w + ix) / 8];
if(v & (1 << (ix % 8))) {
FrameBuffer[80 * (iy + y) + (ix + x) / 4] = c;
}
}
}
} else if(img->format == LUMA_VID_IMAGE_FORMAT_R8G8B8) {
for(int plane = 0; plane < 4; plane++) {
select_planes(1 << ((x + plane) & 3));
for(int iy = 0; iy < height; iy++) {
uint8_t *dst = FrameBuffer + 80 * (iy + y) + x / 4;
for(int ix = plane; ix < width; ix += 4) {
*(dst++) = q_p2c(*(MiniCol*) &img->data[((iy + subY) * img->w + ix + subX) * 2]);
}
}
}
}
}
static const uint8_t font[] = {
0x20, 0x31, 0x95, 0x00, 0x21, 0x17, 0x15, 0x5f, 0x22, 0x32, 0x15, 0x2d,
0x23, 0x47, 0x15, 0xaa, 0xaf, 0x5f, 0x05, 0x24, 0x48, 0x15, 0x5e, 0x65,
0xcc, 0x47, 0x25, 0x57, 0x15, 0x6b, 0x1d, 0xc2, 0xb5, 0x06, 0x26, 0x57,
0x15, 0x44, 0x19, 0x9b, 0x92, 0x05, 0x27, 0x12, 0x15, 0x03, 0x28, 0x28,
0x15, 0x56, 0x95, 0x29, 0x28, 0x15, 0xa9, 0x6a, 0x2a, 0x34, 0x15, 0xfa,
0x05, 0x2b, 0x55, 0x35, 0x84, 0x7c, 0x42, 0x00, 0x2c, 0x22, 0x75, 0x06,
0x2d, 0x31, 0x55, 0x07, 0x2e, 0x11, 0x75, 0x01, 0x2f, 0x37, 0x15, 0xa4,
0xa4, 0x04, 0x30, 0x47, 0x15, 0x96, 0xb9, 0x99, 0x06, 0x31, 0x37, 0x15,
0x93, 0x24, 0x1d, 0x32, 0x47, 0x15, 0x87, 0x48, 0x12, 0x0f, 0x33, 0x47,
0x15, 0x87, 0x68, 0x88, 0x07, 0x34, 0x57, 0x15, 0x8c, 0xa9, 0xf4, 0x11,
0x02, 0x35, 0x47, 0x15, 0x1f, 0x71, 0x88, 0x07, 0x36, 0x47, 0x15, 0x1e,
0x71, 0x99, 0x06, 0x37, 0x47, 0x15, 0x8f, 0x44, 0x22, 0x01, 0x38, 0x47,
0x15, 0x96, 0x69, 0x99, 0x06, 0x39, 0x47, 0x15, 0x96, 0xe9, 0x88, 0x07,
0x3a, 0x15, 0x35, 0x11, 0x3b, 0x26, 0x35, 0x02, 0x06, 0x3c, 0x35, 0x25,
0x54, 0x44, 0x3d, 0x43, 0x45, 0x0f, 0x0f, 0x3e, 0x35, 0x25, 0x11, 0x15,
0x3f, 0x37, 0x15, 0x2a, 0x25, 0x08, 0x40, 0x57, 0x15, 0x2e, 0xf6, 0xde,
0x82, 0x03, 0x41, 0x57, 0x15, 0x84, 0x28, 0xe5, 0x62, 0x04, 0x42, 0x47,
0x15, 0x97, 0x79, 0x99, 0x07, 0x43, 0x47, 0x15, 0x1e, 0x11, 0x11, 0x0e,
0x44, 0x47, 0x15, 0x97, 0x99, 0x99, 0x07, 0x45, 0x47, 0x15, 0x1f, 0xf1,
0x11, 0x0f, 0x46, 0x47, 0x15, 0x1f, 0xf1, 0x11, 0x01, 0x47, 0x47, 0x15,
0x1e, 0x11, 0x9d, 0x0e, 0x48, 0x47, 0x15, 0x99, 0xf9, 0x99, 0x09, 0x49,
0x37, 0x15, 0x97, 0x24, 0x1d, 0x4a, 0x37, 0x15, 0x24, 0x49, 0x0e, 0x4b,
0x57, 0x15, 0x31, 0x95, 0x93, 0x52, 0x04, 0x4c, 0x47, 0x15, 0x11, 0x11,
0x11, 0x0f, 0x4d, 0x47, 0x15, 0xb9, 0xbf, 0x99, 0x09, 0x4e, 0x47, 0x15,
0xb9, 0xbb, 0xdd, 0x09, 0x4f, 0x47, 0x15, 0x96, 0x99, 0x99, 0x06, 0x50,
0x47, 0x15, 0x97, 0x79, 0x11, 0x01, 0x51, 0x48, 0x15, 0x96, 0x99, 0x99,
0x86, 0x52, 0x57, 0x15, 0x27, 0xa5, 0x53, 0x52, 0x04, 0x53, 0x47, 0x15,
0x1e, 0x61, 0x88, 0x07, 0x54, 0x57, 0x15, 0x9f, 0x10, 0x42, 0x08, 0x01,
0x55, 0x47, 0x15, 0x99, 0x99, 0x99, 0x06, 0x56, 0x57, 0x15, 0x31, 0x2a,
0xa5, 0x08, 0x01, 0x57, 0x57, 0x15, 0x31, 0xd6, 0xba, 0x94, 0x02, 0x58,
0x47, 0x15, 0x99, 0x66, 0x96, 0x09, 0x59, 0x57, 0x15, 0x51, 0x29, 0x42,
0x08, 0x01, 0x5a, 0x47, 0x15, 0x8f, 0x24, 0x12, 0x0f, 0x5b, 0x28, 0x15,
0x57, 0xd5, 0x5c, 0x37, 0x15, 0x89, 0x24, 0x12, 0x5d, 0x28, 0x15, 0xab,
0xea, 0x5e, 0x53, 0x25, 0x44, 0x45, 0x5f, 0x51, 0x95, 0x1f, 0x60, 0x22,
0x15, 0x09, 0x61, 0x45, 0x35, 0x87, 0x9e, 0x0e, 0x62, 0x47, 0x15, 0x11,
0x97, 0x99, 0x07, 0x63, 0x45, 0x35, 0x1e, 0x11, 0x0e, 0x64, 0x47, 0x15,
0x88, 0x9e, 0x99, 0x0e, 0x65, 0x45, 0x35, 0x96, 0x1f, 0x0e, 0x66, 0x47,
0x15, 0x2c, 0x2f, 0x22, 0x02, 0x67, 0x47, 0x35, 0x5e, 0x12, 0x9f, 0x06,
0x68, 0x47, 0x15, 0x11, 0xb5, 0x99, 0x09, 0x69, 0x27, 0x15, 0xb2, 0x2a,
0x6a, 0x39, 0x15, 0x84, 0x49, 0x92, 0x03, 0x6b, 0x57, 0x15, 0x21, 0xa4,
0x72, 0x52, 0x04, 0x6c, 0x37, 0x15, 0x93, 0x24, 0x19, 0x6d, 0x55, 0x35,
0xab, 0xd6, 0x5a, 0x01, 0x6e, 0x45, 0x35, 0xb5, 0x99, 0x09, 0x6f, 0x45,
0x35, 0x96, 0x99, 0x06, 0x70, 0x47, 0x35, 0x97, 0x99, 0x17, 0x01, 0x71,
0x47, 0x35, 0x9e, 0x99, 0x8e, 0x08, 0x72, 0x35, 0x35, 0x4f, 0x12, 0x73,
0x45, 0x35, 0x1f, 0x86, 0x07, 0x74, 0x46, 0x25, 0xf2, 0x22, 0xc2, 0x75,
0x45, 0x35, 0x99, 0x99, 0x0e, 0x76, 0x45, 0x35, 0xa9, 0x4a, 0x04, 0x77,
0x55, 0x35, 0xb1, 0x56, 0xa5, 0x00, 0x78, 0x45, 0x35, 0x69, 0x66, 0x09,
0x79, 0x47, 0x35, 0xa9, 0x4a, 0x44, 0x03, 0x7a, 0x45, 0x35, 0x4f, 0x12,
0x0f, 0x7b, 0x39, 0x15, 0x94, 0x14, 0x49, 0x04, 0x7c, 0x18, 0x15, 0xff,
0x7d, 0x39, 0x15, 0x91, 0x44, 0x49, 0x01, 0x7e, 0x52, 0x45, 0x36, 0x01
};
const uint8_t *find(char c) {
const uint8_t *a = font;
while(a - font < sizeof(font)) {
if(*a == c) {
return a;
} else {
a += 3 + ((a[1] & 15) * (a[1] >> 4) + 7) / 8;
}
}
return NULL;
}
__attribute__((optimize("Ofast"))) static void line_extent(const char **strp, size_t len, size_t wall, uint16_t *w, uint16_t *h) {
*w = 0;
*h = 13;
const char *str = *strp;
while(len--) {
if(*str == 10) {
str++;
*strp = str;
return;
}
const uint8_t *data = find(*(str++));
if(data == NULL) continue;
uint8_t width = data[2] & 0x0F;
if(*w + width >= wall) {
if(*w != 0) {
str--;
}
*strp = str;
return;
}
*w += width;
}
*strp = str;
}
__attribute__((optimize("Ofast"))) static void text_line(const char *str, size_t len, uint16_t x, uint16_t y, uint16_t wall) {
if(wall <= x) wall = 320;
uint16_t startX = x;
int col = colorFunc(0, 0);
while(len--) {
if(*str == 10) {
return;
}
const uint8_t *data = find(*(str++));
if(data == NULL) continue;
uint16_t cx = 0, cy = data[2] >> 4;
uint8_t width = data[2] & 0x0F;
if(x + width >= wall) {
y += 13;
return;
}
for(int ix = 0; ix < (data[1] >> 4); ix++) {
select_planes(1 << ((x + ix) & 3));
for(int iy = 0; iy < (data[1] & 15); iy++) {
uint8_t v = data[3 + (iy * (data[1] >> 4) + ix) / 8];
if(v & (1 << ((iy * (data[1] >> 4) + ix) % 8))) {
FrameBuffer[80 * (iy + y + cy) + (ix + x + cx) / 4] = col;
}
}
}
x += width;
}
}
__attribute__((optimize("Ofast"))) static void text_extent(const char *str, size_t len, size_t wall, uint16_t *w, uint16_t *h) {
*w = 0;
*h = 0;
const char *str2 = str;
while(len) {
uint16_t lineWidth = 0, lineHeight = 0;
line_extent(&str2, len, wall, &lineWidth, &lineHeight);
len = str + len - str2;
if(*w < lineWidth) {
*w = lineWidth;
}
*h += lineHeight;
}
}
__attribute__((optimize("Ofast"))) static void text(const char *str, size_t len, uint16_t x, uint16_t y, uint16_t wall, uint8_t align) {
if(wall <= x) wall = 320;
uint16_t lineW, lineH;
while(len) {
const char *lineEnd = str;
line_extent(&lineEnd, len, wall, &lineW, &lineH);
if(align == LUMA_VID_TEXT_ALIGN_LEFT) {
text_line(str, len, x, y, wall);
} else if(align == LUMA_VID_TEXT_ALIGN_CENTER) {
text_line(str, len, (wall + x) / 2 - lineW / 2, y, wall);
} else if(align == LUMA_VID_TEXT_ALIGN_RIGHT) {
text_line(str, len, wall - lineW, y, wall);
}
if(lineEnd == str) {
break;
}
len = str + len - lineEnd;
str = lineEnd;
y += lineH;
}
}
static void compileCommandList(uint8_t *src, uint8_t *dst) {
size_t len = 0;
while(1) {
LumaVidCommand *cmd = (void*) src;
if(cmd->op == LUMA_VID_COMMAND_CLEAR) {
dst[len++] = 0xE8; /* call rel32 */
*((uint32_t*) &dst[len]) = (uint32_t) &clear - (uint32_t) &dst[len + 4];
len += 4;
src += sizeof(cmd->clear);
} else if(cmd->op == LUMA_VID_COMMAND_END) {
dst[len++] = 0xC3; /* ret */
break;
} else if(cmd->op == LUMA_VID_COMMAND_RECT) {
dst[len++] = 0x68; /* push imm32 */
dst[len++] = cmd->rect.y2 & 0xFF;
dst[len++] = cmd->rect.y2 >> 8;
dst[len++] = 0;
dst[len++] = 0;
dst[len++] = 0x68; /* push imm32 */
dst[len++] = cmd->rect.x2 & 0xFF;
dst[len++] = cmd->rect.x2 >> 8;
dst[len++] = 0;
dst[len++] = 0;
dst[len++] = 0x68; /* push imm32 */
dst[len++] = cmd->rect.y1 & 0xFF;
dst[len++] = cmd->rect.y1 >> 8;
dst[len++] = 0;
dst[len++] = 0;
dst[len++] = 0x68; /* push imm32 */
dst[len++] = cmd->rect.x1 & 0xFF;
dst[len++] = cmd->rect.x1 >> 8;
dst[len++] = 0;
dst[len++] = 0;
dst[len++] = 0xE8; /* call rel32 */
*((uint32_t*) &dst[len]) = (uint32_t) &rect - (uint32_t) &dst[len + 4];
len += 4;
dst[len++] = 0x83; /* add */
dst[len++] = 0xC4; /* esp */
dst[len++] = 16;
src += sizeof(cmd->rect);
} else if(cmd->op == LUMA_VID_COMMAND_IMAGE) {
dst[len++] = 0x68; /* push imm32 */
dst[len++] = cmd->image.height & 0xFF;
dst[len++] = cmd->image.height >> 8;
dst[len++] = 0;
dst[len++] = 0;
dst[len++] = 0x68; /* push imm32 */
dst[len++] = cmd->image.width & 0xFF;
dst[len++] = cmd->image.width >> 8;
dst[len++] = 0;
dst[len++] = 0;
dst[len++] = 0x68; /* push imm32 */
dst[len++] = cmd->image.y & 0xFF;
dst[len++] = cmd->image.y >> 8;
dst[len++] = 0;
dst[len++] = 0;
dst[len++] = 0x68; /* push imm32 */
dst[len++] = cmd->image.x & 0xFF;
dst[len++] = cmd->image.x >> 8;
dst[len++] = 0;
dst[len++] = 0;
dst[len++] = 0x68; /* push imm32 */
dst[len++] = cmd->image.subY & 0xFF;
dst[len++] = cmd->image.subY >> 8;
dst[len++] = 0;
dst[len++] = 0;
dst[len++] = 0x68; /* push imm32 */
dst[len++] = cmd->image.subX & 0xFF;
dst[len++] = cmd->image.subX >> 8;
dst[len++] = 0;
dst[len++] = 0;
dst[len++] = 0x68; /* push imm32 */
Image *img = Images.handles[cmd->image.name];
dst[len++] = ((uint32_t) img >> 0) & 0xFF;
dst[len++] = ((uint32_t) img >> 8) & 0xFF;
dst[len++] = ((uint32_t) img >> 16) & 0xFF;
dst[len++] = ((uint32_t) img >> 24) & 0xFF;
dst[len++] = 0xE8; /* call rel32 */
*((uint32_t*) &dst[len]) = (uint32_t) &image - (uint32_t) &dst[len + 4];
len += 4;
dst[len++] = 0x83; /* add */
dst[len++] = 0xC4; /* esp */
dst[len++] = 28;
src += sizeof(cmd->image);
} else if(cmd->op == LUMA_VID_COMMAND_IMAGE_NEW) {
Image *img = NULL;
if(cmd->imageNew.format == LUMA_VID_IMAGE_FORMAT_BLALPHA) {
img = sys_vpm_map(SYS_MAP_VIRT_ANY, SYS_MAP_PHYS_ANY, sizeof(Image) + (cmd->imageNew.width * cmd->imageNew.height + 7) / 8);
} else if(cmd->imageNew.format == LUMA_VID_IMAGE_FORMAT_R8G8B8) {
img = sys_vpm_map(SYS_MAP_VIRT_ANY, SYS_MAP_PHYS_ANY, sizeof(Image) + cmd->imageNew.width * cmd->imageNew.height * 2);
}
if(img) {
img->w = cmd->imageNew.width;
img->h = cmd->imageNew.height;
img->format = cmd->imageNew.format;
}
Images.handles[cmd->imageNew.name] = img;
src += sizeof(cmd->imageNew);
} else if(cmd->op == LUMA_VID_COMMAND_IMAGE_WRITE) {
Image *img = Images.handles[cmd->imageWrite.name];
if(img->format == LUMA_VID_IMAGE_FORMAT_BLALPHA) {
// Copy data
std_copy(img->data + cmd->imageWrite.y * img->w + cmd->imageWrite.x, cmd->imageWrite.data, cmd->imageWrite.len);
} else if(img->format == LUMA_VID_IMAGE_FORMAT_R8G8B8) {
// Copy data and reformat
MiniCol *dst = (MiniCol*) img->data + cmd->imageWrite.y * img->w + cmd->imageWrite.x;
for(size_t i = 0; i < cmd->imageWrite.len; i += 3) {
*(dst++) = ((cmd->imageWrite.data[i + 0] & ~7) << 8) | ((cmd->imageWrite.data[i + 1] & ~3) << 3) | (cmd->imageWrite.data[i + 2] >> 3);
}
}
src += sizeof(cmd->imageWrite) + cmd->imageWrite.len;
} else if(cmd->op == LUMA_VID_COMMAND_SET_COLOR_FLAT) {
MiniCol minicol = ((cmd->colorFlat.r & ~7) << 8) | ((cmd->colorFlat.g & ~3) << 3) | (cmd->colorFlat.b >> 3);
dst[len++] = 0xC7; /* mov [abs], imm */
dst[len++] = 0x05;
*((uint32_t*) &dst[len]) = (uint32_t) &colorFunc;
len += 4;
*((uint32_t*) &dst[len]) = (uint32_t) color_flat;
len += 4;
dst[len++] = 0x68; /* push imm32 */
*((uint32_t*) &dst[len]) = minicol;
len += 4;
dst[len++] = 0xE8; /* call rel32 */
*((uint32_t*) &dst[len]) = (uint32_t) &q_p2c - (uint32_t) &dst[len + 4];
len += 4;
dst[len++] = 0x83; /* add */
dst[len++] = 0xC4; /* esp */
dst[len++] = 4;
dst[len++] = 0xA3; /* mov [abs], eax */
*((uint32_t*) &dst[len]) = (uint32_t) color_flat + 1;
len += 4;
src += sizeof(cmd->colorFlat);
} else if(cmd->op == LUMA_VID_COMMAND_SET_COLOR_GRAD) {
MiniCol cols[16];
for(int i = 15; i >= 0; i--) {
unsigned int r = (cmd->colorGrad.r1 * (15 - i) + cmd->colorGrad.r2 * i) / 15;
unsigned int g = (cmd->colorGrad.g1 * (15 - i) + cmd->colorGrad.g2 * i) / 15;
unsigned int b = (cmd->colorGrad.b1 * (15 - i) + cmd->colorGrad.b2 * i) / 15;
cols[i] = ((r & ~7) << 8) | ((g & ~3) << 3) | (b >> 3);
}
dst[len++] = 0xC7; /* mov [abs], imm32 */
dst[len++] = 0x05;
*((uint32_t*) &dst[len]) = (uint32_t) &colorFunc;
len += 4;
*((uint32_t*) &dst[len]) = (uint32_t) &color_grad;
len += 4;
dst[len++] = 0x83; /* sub esp, imm8 */
dst[len++] = 0xEC;
dst[len++] = 0x04;
for(int i = 0; i < 16; i++) {
dst[len++] = 0x66; /* mov [esp], imm16 */
dst[len++] = 0xC7;
dst[len++] = 0x04;
dst[len++] = 0x24;
*((uint16_t*) &dst[len]) = cols[i];
len += 2;
dst[len++] = 0xE8; /* call rel32 */
*((uint32_t*) &dst[len]) = (uint32_t) &q_p2c - (uint32_t) &dst[len + 4];
len += 4;
dst[len++] = 0xA2; /* mov [abs], al */
*((uint32_t*) &dst[len]) = (uint32_t) &gradCols[i];
len += 4;
}
dst[len++] = 0x83; /* add esp, imm8 */
dst[len++] = 0xC4;
dst[len++] = 0x04;
src += sizeof(cmd->colorGrad);
} else if(cmd->op == LUMA_VID_COMMAND_IMAGE_DEL) {
src += sizeof(cmd->imageDel);
} else if(cmd->op == LUMA_VID_COMMAND_TEXT) {
dst[len++] = 0x68;
*((uint32_t*) &dst[len]) = cmd->text.align;
len += 4;
dst[len++] = 0x68;
*((uint32_t*) &dst[len]) = cmd->text.wall;
len += 4;
dst[len++] = 0x68;
*((uint32_t*) &dst[len]) = cmd->text.y;
len += 4;
dst[len++] = 0x68;
*((uint32_t*) &dst[len]) = cmd->text.x;
len += 4;
dst[len++] = 0x68;
*((uint32_t*) &dst[len]) = cmd->text.len;
len += 4;
dst[len++] = 0x68;
*((uint32_t*) &dst[len]) = (uint32_t) &dst[len + 14];
len += 4;
dst[len++] = 0x68;
*((uint32_t*) &dst[len]) = (uint32_t) &dst[len + 9 + cmd->text.len];
len += 4;
dst[len++] = 0xE9;
*((uint32_t*) &dst[len]) = (uint32_t) &text - (uint32_t) &dst[len + 4];
len += 4;
std_copy(&dst[len], cmd->text.data, cmd->text.len);
len += cmd->text.len;
dst[len++] = 0x83; /* add esp, imm8 */
dst[len++] = 0xC4;
dst[len++] = 0x18;
src += sizeof(cmd->text) + cmd->text.len;
} else if(cmd->op == LUMA_VID_COMMAND_NEW_COLOR_FLAT) {
MiniCol minicol = ((cmd->colorFlat.r & ~7) << 8) | ((cmd->colorFlat.g & ~3) << 3) | (cmd->colorFlat.b >> 3);
q_addp(minicol);
q_reavg();
src += sizeof(cmd->colorFlat);
} else if(cmd->op == LUMA_VID_COMMAND_NEW_COLOR_GRAD) {
MiniCol cols[16];
for(int i = 15; i >= 0; i--) {
unsigned int r = (cmd->colorGrad.r1 * (15 - i) + cmd->colorGrad.r2 * i) / 15;
unsigned int g = (cmd->colorGrad.g1 * (15 - i) + cmd->colorGrad.g2 * i) / 15;
unsigned int b = (cmd->colorGrad.b1 * (15 - i) + cmd->colorGrad.b2 * i) / 15;
q_addp(cols[i] = ((r & ~7) << 8) | ((g & ~3) << 3) | (b >> 2));
}
q_reavg();
src += sizeof(cmd->colorGrad);
} else if(cmd->op == LUMA_VID_COMMAND_TEXT_EXTENT) {
uint16_t w, h;
text_extent(cmd->textExtent.data, cmd->textExtent.len, cmd->textExtent.wall, &w, &h);
cmd->textExtent.w = w;
cmd->textExtent.h = h;
src += sizeof(cmd->textExtent) + cmd->textExtent.len;
}
}
}
static void removeDL(DL *dl) {
/*size_t sz = sizeof(*dl) + dl->len;
std_move(dl, (void*) ((uintptr_t) dl + sz), (uintptr_t) dl + DLs.idx - (uintptr_t) DLs.buf - sz);
memory_barrier();
DLs.idx -= sz;*/
/* TODO: relocate */
}
void startc() {
FrameBuffer = sys_vpm_map(SYS_MAP_VIRT_ANY, (void*) 0xA0000, 32000);
DLs.buf = sys_vpm_map(SYS_MAP_VIRT_ANY, SYS_MAP_PHYS_ANY, 4096);
Images.handles = sys_vpm_map(SYS_MAP_VIRT_ANY, SYS_MAP_PHYS_ANY, 4096);
q_init();
uint32_t canalID = sys_canal_create('LUMA', 'VID\0');
uint8_t *buf = (void*) -1;
do {
buf = sys_canal_accept(canalID);
} while(buf == (void*) -1);
while(1) {
uint32_t meta;
sys_signal_wait(SYS_SIGNAL_WAIT_ANY, &meta);
memory_barrier();
if(meta == 0xFFFFFFFF) {
void *f = sys_vpm_map(SYS_MAP_VIRT_ANY, SYS_MAP_PHYS_ANY, 4096);
compileCommandList(buf, f);
q_reassign();
((void(*)()) f)();
sys_vpm_unmap(f, 4096);
}
memory_barrier();
sys_signal_send(buf, 1);
}
}