#include "lbx.h"
#include "image.h"
+#define FLAG_RAW 0x0100 /* Image is stored as a flat array of bytes. */
#define FLAG_OVERWRITE 0x0400 /* Draw each frame on a clean slate (unsure). */
+#define FLAG_BUILDING 0x0800 /* Buildings have this, related to shadow? */
#define FLAG_PALETTE 0x1000 /* Image contains embedded palette. */
#define FLAG_LOOPING 0x2000 /* Loop over all frames in the image (unsure). */
-#define FLAG_ALL (FLAG_OVERWRITE|FLAG_PALETTE|FLAG_LOOPING)
+
+#define FLAG_ALL (FLAG_RAW|FLAG_OVERWRITE|FLAG_BUILDING|FLAG_PALETTE|FLAG_LOOPING)
#define HDR_LEN 12
struct lbx_image {
unsigned short width, height;
unsigned short wtf, flags;
- unsigned short frames, leadin;
+ unsigned char frames, wtf2, leadin, chunk;
unsigned short palstart, palcount;
const struct lbx_file_ops *fops;
.width = unpack_16_le(hdr+0),
.height = unpack_16_le(hdr+2),
.wtf = unpack_16_le(hdr+4),
- .frames = unpack_16_le(hdr+6),
- .leadin = unpack_16_le(hdr+8),
+ .frames = hdr[6],
+ .wtf2 = hdr[7],
+ .leadin = hdr[8],
+ .chunk = hdr[9],
.flags = unpack_16_le(hdr+10),
.currentframe = -1,
/*
* DEBUG ONLY. These assertions exist to catch otherwise valid image
* files which differ from what I believe to be true of all LBX images.
- * If we never find any exceptions, we can replace the assertions with
- * assumptions.
+ * When we can decode every image, then these assertions should be
+ * replaced with constraints.
*/
- _lbx_assert(img->wtf == 0); /* version? */
- _lbx_assert(img->frames > img->leadin); /* cmbtshp.lbx breaks this. */
+ _lbx_assert(img->wtf == 0); /* version? */
+ _lbx_assert(img->wtf2 == 0); /* very likely is simply reserved. */
+ _lbx_assert(img->frames > img->leadin);
_lbx_assert(!(img->flags & ~FLAG_ALL));
/* Read all offsets. Should be merged with identical code in lbx.c */
return new;
}
+static unsigned char **read_raw_frame(struct lbx_image *img, int frame)
+{
+ unsigned long size = img->width * img->height;
+
+ assert(img->flags & FLAG_RAW);
+
+ if (img->fops->seek(img->f, img->offsets[frame], SEEK_SET)) {
+ lbx_errno = -errno;
+ return NULL;
+ }
+
+ if (img->fops->read(img->framedata[0], size, img->f) != size) {
+ lbx_errno = -errno;
+ if (img->fops->eof(img->f))
+ lbx_errno = LBX_EEOF;
+ return NULL;
+ }
+ memset(img->mask[0], 1, size);
+
+ if (img->fops->tell(img->f) > img->offsets[frame+1]) {
+ lbx_errno = LBX_EFORMAT;
+ return NULL;
+ }
+
+ return img->framedata;
+}
+
unsigned char **lbximg_getframe(struct lbx_image *img, int frame)
{
if (frame >= img->frames || frame < 0) {
return NULL;
}
- if (img->flags & FLAG_OVERWRITE) {
+ if (img->flags & FLAG_RAW)
+ return read_raw_frame(img, frame);
+
+ if ((img->flags & FLAG_OVERWRITE)
+ || (img->chunk && !(frame % img->chunk))) {
/* Clear the slate. */
img->currentframe = -1;
memset(img->framedata[0], 0, img->width * img->height);
memset(img->mask[0], 0, img->width * img->height);
} else {
/* Start over if we are backtracking. */
- if (img->currentframe > frame)
+ if (img->currentframe > frame) {
+ memset(img->mask[0], 0, img->width * img->height);
img->currentframe = -1;
+ }
/* We must have previous frame decoded to continue. */
if (frame > img->currentframe + 1) {
return img->framedata;
}
-int lbximg_loadpalette(FILE *f, struct lbx_colour palette[static 256])
+int
+lbximg_loadpalette(void *f, const struct lbx_file_ops *fops,
+ struct lbx_colour palette[static 256])
{
unsigned char entry[4];
int i;
for (i = 0; i < 256; i++) {
- if (fread(entry, sizeof entry, 1, f) != 1) {
+ if (fops->read(entry, sizeof entry, f) != sizeof entry) {
lbx_errno = (feof(f)) ? LBX_EEOF : -errno;
return -1;
}
return -1;
}
- palette[i] = (struct lbx_colour){
- .red = entry[1] << 2,
- .green = entry[2] << 2,
- .blue = entry[3] << 2,
+ palette[i] = (struct lbx_colour) {
+ .red = entry[1] << 2,
+ .green = entry[2] << 2,
+ .blue = entry[3] << 2,
+ .active = 1,
};
}
for (i = 0; i < img->palcount; i++) {
rc = img->fops->read(entry, sizeof entry, img->f);
-
if (rc < sizeof entry) {
goto readerr;
}
}
palette[img->palstart + i] = (struct lbx_colour){
- .red = entry[1] << 2,
- .green = entry[2] << 2,
- .blue = entry[3] << 2,
+ .red = entry[1] << 2,
+ .green = entry[2] << 2,
+ .blue = entry[3] << 2,
+ .active = 1,
};
}
.width = img->width,
.height = img->height,
.nframes = img->frames,
+ .chunk = img->chunk,
.palettesz = (img->flags & FLAG_PALETTE) ? img->palcount : 0,
};