63 lines
1.8 KiB
C++
63 lines
1.8 KiB
C++
|
#include <stdint.h>
|
||
|
#include <stdio.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <error.h>
|
||
|
#include "engine.h"
|
||
|
#include <inttypes.h>
|
||
|
|
||
|
// TODO: even better compression using zlib or something - or vector graphics
|
||
|
|
||
|
#define MAX_SPRITES 5000
|
||
|
static struct sprite sprites[MAX_SPRITES];
|
||
|
static int numsprites;
|
||
|
|
||
|
struct sprite *get_decompressed_sprite(const unsigned char *spritedata) {
|
||
|
for(int i = 0; i < numsprites; i++) {
|
||
|
if(sprites[i].original_data_source == spritedata)
|
||
|
return &sprites[i];
|
||
|
}
|
||
|
struct sprite *s = &sprites[numsprites++];
|
||
|
s->width = *(uint16_t*)(spritedata + 0);
|
||
|
s->height = *(uint16_t*)(spritedata + 2);
|
||
|
s->original_data_source = spritedata;
|
||
|
spritedata += 4;
|
||
|
|
||
|
s->pixels = (uint32_t*)malloc(s->width*s->height*4);
|
||
|
if(!s->pixels) error(1, 0, "get_decompressed_sprite: memory allocation failed");
|
||
|
|
||
|
for(int channel = 0; channel < 4; channel++) {
|
||
|
unsigned char *pixels = (unsigned char*)s->pixels;
|
||
|
pixels += channel;
|
||
|
unsigned int pixelsleft = s->width * s->height;
|
||
|
while(pixelsleft > 0) {
|
||
|
unsigned char control = *spritedata++;
|
||
|
if(control & 0x80) {
|
||
|
control &= 0x7f;
|
||
|
if(control > pixelsleft) error(1, 0, "corrupted compressed sprite A %u > %u", (unsigned int)control, (unsigned int)pixelsleft);
|
||
|
for(int i = 0; i < control; i++) {
|
||
|
*pixels = *spritedata++;
|
||
|
pixels += 4;
|
||
|
}
|
||
|
pixelsleft -= control;
|
||
|
} else {
|
||
|
uint32_t count;
|
||
|
if(control == 0) {
|
||
|
count = *(uint32_t*)spritedata;
|
||
|
spritedata += 4;
|
||
|
} else {
|
||
|
count = control;
|
||
|
}
|
||
|
unsigned char value = *spritedata++;
|
||
|
if(count > pixelsleft) error(1, 0, "corrupted compressed sprite B %u > %u", (unsigned int)count, (unsigned int)pixelsleft);
|
||
|
for(uint32_t i = 0; i < count; i++) {
|
||
|
*pixels = value;
|
||
|
pixels += 4;
|
||
|
}
|
||
|
pixelsleft -= count;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return s;
|
||
|
}
|
||
|
|