11 #define SOP_OP(op) ((op) & 0xff)
12 #define SOP_LEN(op) ((op) >> 16)
14 #pragma pack (push, 1)
17 uint16_t width, height, bpp;
23 static int read_sprite(struct sprite *spr, int pixsz, FILE *fp);
26 void destroy_sprites(struct sprites *ss)
30 for(i=0; i<ss->num_sprites; i++) {
31 free(ss->sprites[i].ops);
36 int load_sprites(struct sprites *ss, const char *fname)
40 struct file_header hdr;
44 if(!(fp = fopen(fname, "rb"))) {
45 fprintf(stderr, "failed to load sprites from %s: %s\n", fname, strerror(errno));
48 if(fread(&hdr, sizeof hdr, 1, fp) <= 0) {
49 fprintf(stderr, "unexpected EOF while reading from %s\n", fname);
52 if(memcmp(hdr.magic, "RLESPRIT", sizeof hdr.magic) != 0) {
53 fprintf(stderr, "invalid magic in %s\n", fname);
57 ss->width = hdr.width;
58 ss->height = hdr.height;
60 ss->num_sprites = hdr.count;
62 if(!(ss->sprites = malloc(hdr.count * sizeof *ss->sprites))) {
63 fprintf(stderr, "failed to allocate %d sprites for %s\n", hdr.count, fname);
67 for(i=0; i<ss->num_sprites; i++) {
68 if(read_sprite(ss->sprites + i, (hdr.bpp + 7) / 8, fp) == -1) {
82 static int read_sprite(struct sprite *spr, int pixsz, FILE *fp)
84 int i, idx, max_ops, newmax, len, bufsz;
89 spr->num_ops = max_ops = 0;
93 if(fread(&op, sizeof op, 1, fp) <= 0) {
98 /* realloc ops array if necessary */
99 if(spr->num_ops >= max_ops) {
100 newmax = max_ops ? max_ops << 1 : 16;
101 if(!(tmp = realloc(spr->ops, newmax * sizeof *spr->ops))) {
102 fprintf(stderr, "failed to add sprite op (newmax: %d)\n", newmax);
110 idx = spr->num_ops++;
111 spr->ops[idx].op = SOP_OP(op);
114 spr->ops[idx].size = bufsz;
116 /* if the op was copy, we need to grab the pixel data */
117 if(SOP_OP(op) == SOP_COPY) {
118 if(!(tmp = malloc(bufsz))) {
119 fprintf(stderr, "failed to allocate sprite pixel data (%d bytes)\n", bufsz);
122 if(fread(tmp, 1, bufsz, fp) < bufsz) {
123 fprintf(stderr, "unexpected EOF while trying to read sprite data (%d pixels)\n", len);
126 spr->ops[idx].data = tmp;
128 spr->ops[idx].data = 0;
131 } while(SOP_OP(op) != SOP_END);
136 for(i=0; i<spr->num_ops; i++) {
137 free(spr->ops[i].data);
143 void draw_sprite(void *dest, int fbpitch, struct sprites *ss, int idx)
145 struct sprite_op *sop = ss->sprites[idx].ops;
146 unsigned char *fbptr = dest;
150 assert((xoffs & 1) == 0);
162 memcpy(fbptr + xoffs, sop->data, sop->size);