#include <errno.h>
#include "byteorder.h"
+#include "pack.h"
#include "misc.h"
#include "lbx.h"
#include "image.h"
#define FLAG_OVERWRITE 0x0400 /* Draw each frame on a clean slate (unsure). */
#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 HDR_LEN 12
struct lbx_image {
- uint16_t width, height;
- uint16_t wtf1;
- uint16_t frames, leadin;
- uint16_t flags;
- uint16_t palstart, palcount;
+ unsigned short width, height;
+ unsigned short wtf, flags;
+ unsigned short frames, leadin;
+ unsigned short palstart, palcount;
FILE *f;
long foff, paloff;
unsigned char **framedata;
unsigned char **mask;
- uint32_t offsets[];
+ unsigned long offsets[];
};
+static struct lbx_image *lbximg_init(unsigned char hdr[static HDR_LEN])
+{
+ unsigned short nframes = unpack_16_le(hdr+6);
+ struct lbx_image *img;
+
+ img = malloc(sizeof *img + sizeof img->offsets[0] * (nframes+1));
+ if (!img) {
+ lbx_errno = -errno;
+ return NULL;
+ }
+
+ *img = (struct lbx_image) {
+ .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),
+ .flags = unpack_16_le(hdr+10),
+
+ .currentframe = -1,
+ };
+
+ return img;
+}
+
struct lbx_image *lbximg_fopen(FILE *f)
{
- struct lbx_image tmp = {.f = f}, *new = NULL;
+ unsigned char hdr_buf[HDR_LEN];
+ struct lbx_image *img;
size_t rc;
- if (fread(&tmp.width, sizeof tmp.width, 1, f) != 1) goto readerr;
- if (fread(&tmp.height, sizeof tmp.height, 1, f) != 1) goto readerr;
- if (fread(&tmp.wtf1, sizeof tmp.wtf1, 1, f) != 1) goto readerr;
- if (fread(&tmp.frames, sizeof tmp.frames, 1, f) != 1) goto readerr;
- if (fread(&tmp.leadin, sizeof tmp.leadin, 1, f) != 1) goto readerr;
- if (fread(&tmp.flags, sizeof tmp.flags, 1, f) != 1) goto readerr;
+ if (fread(hdr_buf, 1, sizeof hdr_buf, f) != sizeof hdr_buf) {
+ lbx_errno = -errno;
+ if (feof(f))
+ lbx_errno = LBX_EEOF;
+ return NULL;
+ }
+
+ img = lbximg_init(hdr_buf);
+ if (!img)
+ return NULL;
- tmp.width = letohs(tmp.width); tmp.foff += sizeof tmp.width;
- tmp.height = letohs(tmp.height); tmp.foff += sizeof tmp.height;
- tmp.wtf1 = letohs(tmp.wtf1); tmp.foff += sizeof tmp.wtf1;
- tmp.frames = letohs(tmp.frames); tmp.foff += sizeof tmp.frames;
- tmp.leadin = letohs(tmp.leadin); tmp.foff += sizeof tmp.leadin;
- tmp.flags = letohs(tmp.flags); tmp.foff += sizeof tmp.flags;
+ img->f = f;
+ img->foff = sizeof hdr_buf;
/*
* DEBUG ONLY. These assertions exist to catch otherwise valid image
* If we never find any exceptions, we can replace the assertions with
* assumptions.
*/
- _lbx_assert(tmp.wtf1 == 0);
- _lbx_assert(tmp.frames > tmp.leadin); /* cmbtshp.lbx breaks this. */
- _lbx_assert(!(tmp.flags & ~(FLAG_PALETTE|FLAG_OVERWRITE|FLAG_LOOPING)));
+ _lbx_assert(img->wtf == 0); /* version? */
+ _lbx_assert(img->frames > img->leadin); /* cmbtshp.lbx breaks this. */
+ _lbx_assert(!(img->flags & ~FLAG_ALL));
+
+ /* Read all offsets. Should be merged with identical code in lbx.c */
+ for (unsigned i = 0; i <= img->frames; i++) {
+ unsigned char buf[4];
+
+ if (fread(buf, 1, sizeof buf, f) != sizeof buf) {
+ lbx_errno = -errno;
+ if (feof(f))
+ lbx_errno = LBX_EEOF;
+ free(img);
+ return NULL;
+ }
- new = malloc(sizeof *new + (tmp.frames+1) * sizeof *new->offsets);
- if (!new) {
- lbx_errno = -errno;
- return NULL;
+ img->offsets[i] = unpack_32_le(buf);
+ img->foff += 4;
}
- *new = tmp;
- new->currentframe = -1;
+ if (img->flags & FLAG_PALETTE) {
+ unsigned char buf[4];
- rc = fread(new->offsets, sizeof *new->offsets, new->frames+1, f);
- if (rc < new->frames+1)
- goto readerr;
- new->foff += sizeof *new->offsets * (new->frames+1);
-
- if (new->flags & FLAG_PALETTE) {
- if (fread(&new->palstart, sizeof new->palstart, 1, f) != 1)
- goto readerr;
- if (fread(&new->palcount, sizeof new->palcount, 1, f) != 1)
- goto readerr;
+ if (fread(buf, 1, sizeof buf, f) != sizeof buf) {
+ lbx_errno = -errno;
+ if (feof(f))
+ lbx_errno = LBX_EEOF;
+ free(img);
+ return NULL;
+ }
- new->palstart = letohs(new->palstart);
- new->palcount = letohs(new->palcount);
- new->foff += sizeof new->palstart + sizeof new->palcount;
- new->paloff = new->foff;
+ img->palstart = unpack_16_le(buf+0);
+ img->palcount = unpack_16_le(buf+2);
+ img->foff += sizeof buf;
+ img->paloff = img->foff;
- if (new->palstart + new->palcount > 256) {
+ if (img->palstart + img->palcount > 256) {
lbx_errno = LBX_EFORMAT;
- free(new);
+ free(img);
return NULL;
}
}
- return new;
-readerr:
- if (feof(f)) {
- lbx_errno = LBX_EEOF;
- } else {
- lbx_errno = -errno;
- }
-
- free(new);
- return NULL;
+ return img;
}
static int _lbx_drawrow(int first, struct lbx_image *img)
if (_lbx_fseek(img->f, &img->foff, img->paloff) == -1)
return -1;
-
+
for (i = 0; i < img->palcount; i++) {
rc = fread(entry, 1, sizeof entry, img->f);
img->foff += rc;