nuclear@3: #include nuclear@0: #include nuclear@0: #include nuclear@3: #include nuclear@0: #include "image.h" nuclear@3: #include "logger.h" nuclear@3: nuclear@3: #ifdef __unix__ nuclear@3: #include nuclear@3: #define HAVE_NTOHS nuclear@3: #else nuclear@3: static int bigendian(void); nuclear@3: static uint16_t swap16(uint16_t x); nuclear@3: static uint16_t nop16(uint16_t x); nuclear@3: static uint16_t (*ntohs)(uint16_t); nuclear@3: #endif nuclear@3: nuclear@3: struct ham_image_header { nuclear@3: char magic[4]; nuclear@3: uint16_t width, height; nuclear@3: unsigned char nbitplanes, padding; nuclear@3: uint16_t nchg; nuclear@3: uint16_t palette[16]; nuclear@3: }; nuclear@0: nuclear@0: struct ham_image *load_ham_image(const char *fname) nuclear@0: { nuclear@3: int i, num; nuclear@3: unsigned long imgsz; nuclear@3: struct ham_image_header hdr; nuclear@3: struct ham_image *img = 0; nuclear@3: struct palchange *tail = 0; nuclear@3: FILE *fp; nuclear@3: nuclear@3: #ifndef HAVE_NTOHS nuclear@3: ntohs = bigendian() ? nop16 : swap16; nuclear@3: #endif nuclear@3: nuclear@3: logmsg("opening file: %s\n", fname); nuclear@3: if(!(fp = fopen(fname, "rb"))) { nuclear@3: logmsg("failed to open %s: %s\n", fname, strerror(errno)); nuclear@3: return 0; nuclear@3: } nuclear@3: nuclear@3: if(fread(&hdr, sizeof hdr, 1, fp) < 1) { nuclear@3: logmsg("unexpected eof while reading image header\n"); nuclear@3: goto err; nuclear@3: } nuclear@3: if(memcmp(hdr.magic, "HAAM", 4) != 0) { nuclear@3: logmsg("failed to load image: %s: unknown file type\n", fname); nuclear@3: goto err; nuclear@3: } nuclear@3: nuclear@3: if(!(img = malloc(sizeof *img))) { nuclear@3: logmsg("failed to allocate image structure\n"); nuclear@3: goto err; nuclear@3: } nuclear@3: img->width = ntohs(hdr.width); nuclear@3: img->height = ntohs(hdr.height); nuclear@3: img->nbitplanes = hdr.nbitplanes; nuclear@3: nuclear@3: imgsz = img->width * img->height / 8 * img->nbitplanes; nuclear@3: nuclear@3: logmsg("header info: %dx%d, %d bpl, size: %lu\n", img->width, img->height, (int)img->nbitplanes, imgsz); nuclear@3: nuclear@3: if(!(img->pixels = malloc(imgsz))) { nuclear@3: logmsg("failed to allocate %dx%d (%d bitplane) image\n", img->width, img->height, img->nbitplanes); nuclear@3: goto err; nuclear@3: } nuclear@3: nuclear@3: for(i=0; i<16; i++) { nuclear@3: img->palette[i] = ntohs(hdr.palette[i]); nuclear@3: } nuclear@3: nuclear@3: num = ntohs(hdr.nchg); nuclear@3: for(i=0; iline, 2, 1, fp) < 1 || fread(&chg->entry, 2, 1, fp) < 1) { nuclear@3: logmsg("unexpected end of file while reading palette changelist\n"); nuclear@3: goto err; nuclear@3: } nuclear@3: chg->line = ntohs(chg->line); nuclear@3: chg->entry = ntohs(chg->entry); nuclear@3: chg->next = 0; nuclear@3: nuclear@3: if(tail) { nuclear@3: tail->next = chg; nuclear@3: tail = chg; nuclear@3: } else { nuclear@3: img->chglist = tail = chg; nuclear@3: } nuclear@3: } nuclear@3: nuclear@3: if(fread(img->pixels, 1, imgsz, fp) < imgsz) { nuclear@3: logmsg("unexpected end of file while reading image pixels\n"); nuclear@3: goto err; nuclear@3: } nuclear@3: nuclear@3: fclose(fp); nuclear@3: return img; nuclear@3: nuclear@3: err: nuclear@3: if(img) { nuclear@3: while(img->chglist) { nuclear@3: void *tmp = img->chglist; nuclear@3: img->chglist = img->chglist->next; nuclear@3: free(tmp); nuclear@3: } nuclear@3: free(img->pixels); nuclear@3: free(img); nuclear@3: } nuclear@3: if(fp) fclose(fp); nuclear@3: return 0; nuclear@0: } nuclear@0: nuclear@0: struct ham_image *gen_ham_image(int w, int h, int nbpl) nuclear@0: { nuclear@0: int i, x, y; nuclear@0: struct ham_image *img; nuclear@0: unsigned char *pptr; nuclear@0: unsigned char pixval; nuclear@0: /*static const uint16_t defpal[] = { nuclear@0: 0x000, 0xf00, 0xff0, 0x0f0, 0x0ff, 0x00f, 0xf0f, 0xfff, nuclear@0: 0x444, 0x800, 0x880, 0x080, 0x088, 0x008, 0x808, 0x888 nuclear@0: };*/ nuclear@0: nuclear@0: if(!(img = malloc(sizeof *img))) { nuclear@0: return 0; nuclear@0: } nuclear@0: if(!(img->pixels = calloc(w * h / 8 * nbpl, 1))) { nuclear@0: free(img); nuclear@0: return 0; nuclear@0: } nuclear@0: img->width = w; nuclear@0: img->height = h; nuclear@0: img->chglist = 0; nuclear@0: nuclear@0: img->nbitplanes = nbpl; nuclear@0: /*memcpy(img->palette, defpal, sizeof defpal);*/ nuclear@0: for(i=0; i<16; i++) { nuclear@0: img->palette[i] = i | (i << 4) | (i << 8); nuclear@0: } nuclear@0: nuclear@0: pptr = img->pixels; nuclear@0: for(i=0; i<4; i++) { nuclear@0: pptr = img->pixels + i * w / 8; nuclear@0: for(y=0; y> 1) | ((((x ^ y) >> i) & 1) ? 0x80 : 0); nuclear@0: if((x & 7) == 7) { nuclear@0: *pptr++ = pixval; nuclear@0: pixval = 0; nuclear@0: } nuclear@0: } nuclear@0: pptr += w / 8 * (img->nbitplanes - 1); nuclear@0: } nuclear@0: } nuclear@0: nuclear@0: return img; nuclear@0: } nuclear@3: nuclear@3: #ifndef HAVE_NTOHS nuclear@3: static int bigendian(void) nuclear@3: { nuclear@3: static const uint16_t x = 0xaabb; nuclear@3: return *(unsigned char*)&x == 0xaa; nuclear@3: } nuclear@3: nuclear@3: static uint16_t swap16(uint16_t x) nuclear@3: { nuclear@3: return (x << 8) | (x >> 8); nuclear@3: } nuclear@3: nuclear@3: static uint16_t nop16(uint16_t x) nuclear@3: { nuclear@3: return x; nuclear@3: } nuclear@3: #endif