From bebb02a472ecf3ba95366bbd3934478433cd9498 Mon Sep 17 00:00:00 2001 From: John Tsiombikas Date: Wed, 18 Dec 2019 07:30:43 +0200 Subject: [PATCH] made sprite compiler able to handle 565 formats. the assembly output seems plausible, need to test --- tools/csprite/src/image.c | 46 +++++++++++++++++++++++++++++++++++ tools/csprite/src/image.h | 2 ++ tools/csprite/src/main.c | 58 +++++++++++++++++++++++++++++++++------------ 3 files changed, 91 insertions(+), 15 deletions(-) diff --git a/tools/csprite/src/image.c b/tools/csprite/src/image.c index 18e8609..84bad81 100644 --- a/tools/csprite/src/image.c +++ b/tools/csprite/src/image.c @@ -1,5 +1,6 @@ #include #include +#include #include #include #include @@ -186,6 +187,51 @@ int save_image(struct image *img, const char *fname) return 0; } +int conv_image_rgb565(struct image *img16, struct image *img) +{ + int i, j; + uint16_t *dptr; + unsigned char *sptr; + + if(!img->cmap_ncolors && img->bpp < 24) { + fprintf(stderr, "unsupported conversion from %dbpp to 16bpp 565\n", img->bpp); + return -1; + } + + img16->width = img->width; + img16->height = img->height; + img16->nchan = img->nchan; + img16->bpp = 16; + img16->scansz = img16->pitch = img->width * 2; + if(!(img16->pixels = malloc(img16->height * img16->scansz))) { + return -1; + } + + sptr = img->pixels; + dptr = (uint16_t*)img16->pixels; + + for(i=0; iheight; i++) { + for(j=0; jwidth; j++) { + unsigned int r, g, b; + if(img->bpp <= 8 && img->cmap_ncolors) { + int idx = *sptr++ % img->cmap_ncolors; + r = img->cmap[idx].r >> 3; + g = img->cmap[idx].g >> 2; + b = img->cmap[idx].b >> 3; + } else if(img->nchan == 1) { + g = (*sptr++ >> 2) & 0x3f; + r = b = g >> 1; + } else { + r = (*sptr++ >> 3) & 0x1f; + g = (*sptr++ >> 2) & 0x3f; + b = (*sptr++ >> 3) & 0x1f; + } + *dptr++ = (r << 11) | (g << 5) | b; + } + } + return 0; +} + int cmp_image(struct image *a, struct image *b) { diff --git a/tools/csprite/src/image.h b/tools/csprite/src/image.h index 63352f8..0b966a6 100644 --- a/tools/csprite/src/image.h +++ b/tools/csprite/src/image.h @@ -19,6 +19,8 @@ int alloc_image(struct image *img, int x, int y, int bpp); int load_image(struct image *img, const char *fname); int save_image(struct image *img, const char *fname); +int conv_image_rgb565(struct image *img16, struct image *img); + int cmp_image(struct image *a, struct image *b); void blit_image(struct image *src, int sx, int sy, int w, int h, struct image *dst, int dx, int dy); diff --git a/tools/csprite/src/main.c b/tools/csprite/src/main.c index 4c291b9..f0880b8 100644 --- a/tools/csprite/src/main.c +++ b/tools/csprite/src/main.c @@ -20,9 +20,10 @@ int tile_xsz, tile_ysz; struct rect rect; int cmap_offs; int ckey; -int fbpitch = 320; +int fbpitch, fbwidth = 320; const char *name = "sprite"; int asyntax = AS_GNU; +int conv565; int main(int argc, char **argv) { @@ -52,6 +53,13 @@ int main(int argc, char **argv) return 1; } + } else if(strcmp(argv[i], "-fbwidth") == 0) { + fbwidth = atoi(argv[++i]); + if(fbwidth <= 0) { + fprintf(stderr, "-fbwidth must be followed by a positive number\n"); + return 1; + } + } else if(strcmp(argv[i], "-fbpitch") == 0) { fbpitch = atoi(argv[++i]); if(fbpitch <= 0) { @@ -68,11 +76,14 @@ int main(int argc, char **argv) } else if(strcmp(argv[i], "-k") == 0 || strcmp(argv[i], "-key") == 0) { ckey = strtol(argv[++i], &endp, 10); - if(endp == argv[i] || ckey < 0 || ckey >= 256) { + if(endp == argv[i] || ckey < 0) { fprintf(stderr, "%s must be followed by a valid color key\n", argv[i - 1]); return 1; } + } else if(strcmp(argv[i], "-conv565") == 0) { + conv565 = 1; + } else if(strcmp(argv[i], "-gas") == 0) { asyntax = AS_GNU; @@ -99,6 +110,7 @@ int main(int argc, char **argv) return 0; } +/* prototype of generated function is (void *fb, int x, int y, int idx) */ const char *prefixfmt[] = { /* GNU assembler template */ "\t.global %s\n" @@ -136,6 +148,19 @@ int proc_sheet(const char *fname) fprintf(stderr, "failed to load image: %s\n", fname); return -1; } + if(conv565) { + struct image tmp; + if(conv_image_rgb565(&tmp, &img) == -1) { + fprintf(stderr, "failed to convert image to 16bpp 565: %s\n", fname); + free(img.pixels); + return -1; + } + free(img.pixels); + img = tmp; + } + + if(!fbpitch) fbpitch = fbwidth * img.bpp / 8; + if(rect.w <= 0) { rect.w = img.width; rect.h = img.height; @@ -170,6 +195,7 @@ int proc_sheet(const char *fname) } } + free(img.pixels); return 0; } @@ -187,8 +213,8 @@ struct csop { int csprite(struct image *img, int x, int y, int xsz, int ysz) { - int i, j, numops, mode, new_mode, start, skip_acc; - unsigned char *pptr = img->pixels + y * img->scansz + x; + int i, j, numops, mode, new_mode, start, skip_acc, lenbytes, pixsz = img->bpp / 8; + unsigned char *pptr = img->pixels + y * img->scansz + x * pixsz; struct csop *ops, *optr; ops = optr = alloca((xsz + 1) * ysz * sizeof *ops); @@ -202,7 +228,7 @@ int csprite(struct image *img, int x, int y, int xsz, int ysz) } for(j=0; jscansz - xsz; + pptr += img->scansz - xsz * pixsz; if(mode != -1) { assert(start >= 0); @@ -231,7 +257,7 @@ int csprite(struct image *img, int x, int y, int xsz, int ysz) } numops = optr - ops; - pptr = img->pixels + y * img->scansz + x; + pptr = img->pixels + y * img->scansz + x * img->bpp / 8; optr = ops; skip_acc = 0; /* edx points to dest */ @@ -239,25 +265,26 @@ int csprite(struct image *img, int x, int y, int xsz, int ysz) switch(optr->op) { case CSOP_SKIP: skip_acc += optr->len; - pptr += optr->len; + pptr += optr->len * pixsz; break; case CSOP_ENDL: - skip_acc += fbpitch - xsz; - pptr += img->scansz - xsz; + skip_acc += fbwidth - xsz; + pptr += img->scansz - xsz * pixsz; break; case CSOP_COPY: if(skip_acc) { if(asyntax == AS_GNU) { - printf("\tadd $%d, %%edx\n", skip_acc); + printf("\tadd $%d, %%edx\n", skip_acc * pixsz); } else { - printf("\tadd edx, %d\n", skip_acc); + printf("\tadd edx, %d\n", skip_acc * pixsz); } skip_acc = 0; } - for(j=0; jlen / 4; j++) { + lenbytes = optr->len * pixsz; + for(j=0; jlen % 4) { + switch(lenbytes % 4) { case 3: if(asyntax == AS_GNU) { printf("\tmovb $0x%x, %d(%%edx)\n", (unsigned int)*pptr++, j++); @@ -313,6 +340,7 @@ void print_usage(const char *argv0) printf(" -coffset : colormap offset [0, 255] (default: 0)\n"); printf(" -fbpitch : target framebuffer pitch (scanline size in bytes)\n"); printf(" -k,-key : color-key for transparency (default: 0)\n"); + printf(" -conv565: convert image to 16bpp 565 before processing\n"); printf(" -gas: output GNU assembler code (default)\n"); printf(" -nasm: output NASM-compatible code\n"); printf(" -h: print usage and exit\n"); -- 1.7.10.4