# HG changeset patch # User John Tsiombikas # Date 1509001469 -10800 # Node ID f75893a3323400c7279dfa496bcde16dd72f68ab # Parent 6320a20f17c5855f3488fc46bcf7c12d86377b21 hammer -> ham image converter diff -r 6320a20f17c5 -r f75893a33234 src/image.h --- a/src/image.h Wed Oct 25 21:05:24 2017 +0300 +++ b/src/image.h Thu Oct 26 10:04:29 2017 +0300 @@ -4,7 +4,7 @@ #include "inttypes.h" struct palchange { - int line; + uint16_t line; uint16_t entry; /* [ idx | r | g | b ] */ struct palchange *next; }; diff -r 6320a20f17c5 -r f75893a33234 tools/convhammer/main.c --- a/tools/convhammer/main.c Wed Oct 25 21:05:24 2017 +0300 +++ b/tools/convhammer/main.c Thu Oct 26 10:04:29 2017 +0300 @@ -1,6 +1,7 @@ #include #include #include +#include #include #include "image.h" @@ -54,7 +55,7 @@ } strcat(name, ".ham"); - if(save_ham(name, img) == -1) { + if(save_ham(img, name) == -1) { fprintf(stderr, "failed to save ham image: %s\n", name); free_image(img); continue; @@ -63,14 +64,133 @@ return 0; } +static uint16_t nops(uint16_t x) { return x; } +static uint16_t swaps(uint16_t x) { return (x >> 8) | (x << 8); } + struct ham_image *load_hammer(const char *fname) { + int i, x, y, pstart, numpix = 320 * 256; + FILE *fp = 0; + uint32_t cps, npalent; + struct ham_image *img = 0; + struct palchange *tail = 0; + unsigned char *inpixels = 0; + unsigned char *srcptr, *destptr; + uint16_t endtest = 0xaabb; + uint16_t (*letohs)(uint16_t); + + letohs = (*(unsigned char*)&endtest == 0xaa) ? swaps : nops; + + if(!(fp = fopen(fname, "rb"))) { + fprintf(stderr, "failed to open %s: %s\n", fname, strerror(errno)); + return 0; + } + + if(!(img = malloc(sizeof *img))) { + perror("failed to allocate image"); + goto err; + } + img->width = 320; + img->height = 256; + img->nbitplanes = 6; + img->chglist = 0; + + if(!(img->pixels = malloc(img->width * img->height / 8 * img->nbitplanes))) { + perror("failed to allocate pixels"); + goto err; + } + + if(fread(&cps, 4, 1, fp) < 1) goto err; + cps = letohs(cps); + if(cps <= 0 || cps > 16) { + fprintf(stderr, "invalid changes-per-line value: %u\n", (unsigned int)cps); + goto err; + } + + /* read palette changes and palette */ + + npalent = cps * 256; + pstart = npalent - 16; + + for(i=0; iline = i / cps; + chg->entry = palent; + chg->next = 0; + if(tail) { + tail->next = chg; + tail = chg; + } else { + img->chglist = tail = chg; + } + + if(i >= pstart) { + img->palette[i - pstart] = palent & 0xfff; + } + } + + /* read pixels */ + if(!(inpixels = malloc(numpix))) { + perror("failed to allocate pixel buffer"); + goto err; + } + if(fread(inpixels, 1, numpix, fp) < numpix) { + perror("unexpected end of file while reading pixels"); + goto err; + } + + for(i=0; inbitplanes; i++) { + srcptr = inpixels; + destptr = img->pixels + i * img->width / 8; + for(y=0; yheight; y++) { + unsigned char pixval = 0; + for(x=0; xwidth; x++) { + pixval = (pixval << 1) | ((*srcptr++ >> i) & 1); + if((x & 7) == 7) { + *destptr++ = pixval; + pixval = 0; + } + } + destptr += img->width / 8 * (img->nbitplanes - 1); + } + } + + return img; + +err: + free(inpixels); + if(img) { + while(img->chglist) { + void *tmp = img->chglist; + img->chglist = img->chglist->next; + free(tmp); + } + free(img->pixels); + free(img); + } + if(fp) fclose(fp); + return 0; } int save_ham(struct ham_image *img, const char *fname) { + int i, num; + unsigned char c, *pptr; uint16_t val; FILE *fp; + struct palchange *chg; if(!(fp = fopen(fname, "wb"))) { fprintf(stderr, "failed to open %s for writing: %s\n", fname, strerror(errno)); @@ -79,10 +199,41 @@ fprintf(fp, "HAAM"); val = htons(img->width); - fwrite(fp, 2, 1, &val); + fwrite(&val, 2, 1, fp); val = htons(img->height); - fwrite(fp, 2, 1, &val); - /* TODO: continue */ + fwrite(&val, 2, 1, fp); + c = img->nbitplanes; + fwrite(&c, 1, 1, fp); + fwrite(&c, 1, 1, fp); /* padding */ + + num = 0; + chg = img->chglist; + while(chg) { + ++num; + chg = chg->next; + } + num = htons(num); + fwrite(&num, 2, 1, fp); + + chg = img->chglist; + while(chg) { + val = htons(chg->line); + fwrite(&val, 2, 1, fp); + val = htons(chg->entry); + fwrite(&val, 2, 1, fp); + chg = chg->next; + } + + pptr = img->pixels; + num = img->width * img->height / 8 * img->nbitplanes; + for(i=0; i