pt2game/decompress_sprite.cpp

63 lines
1.8 KiB
C++
Raw Normal View History

#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;
}