X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?p=dosdemo;a=blobdiff_plain;f=tools%2Fcsprite%2Fsrc%2Fmain.c;h=fab302beeccd20cd14eaa9ba69a67253dc8ef2d5;hp=4c291b949f3e929697328deb8752948c7fe62f54;hb=c912e59b898fe1ac461a1468e4a2e1937de286d7;hpb=02d3f6c78597600d2b100748aa54241228b9ca09 diff --git a/tools/csprite/src/main.c b/tools/csprite/src/main.c index 4c291b9..fab302b 100644 --- a/tools/csprite/src/main.c +++ b/tools/csprite/src/main.c @@ -20,9 +20,12 @@ 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 padding; +const char *wrop = "mov"; int main(int argc, char **argv) { @@ -45,6 +48,13 @@ int main(int argc, char **argv) return 1; } + } else if(strcmp(argv[i], "-p") == 0 || strcmp(argv[i], "-pad") == 0) { + padding = strtol(argv[++i], &endp, 10); + if(endp == argv[i] || padding < 0) { + fprintf(stderr, "%s must be followed by a positive number\n", argv[i - 1]); + return 1; + } + } else if(strcmp(argv[i], "-coffset") == 0) { cmap_offs = strtol(argv[++i], &endp, 10); if(endp == argv[i] || cmap_offs < 0 || cmap_offs >= 256) { @@ -52,6 +62,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 +85,17 @@ 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], "-x") == 0 || strcmp(argv[i], "-xor") == 0) { + wrop = "xor"; + } else if(strcmp(argv[i], "-gas") == 0) { asyntax = AS_GNU; @@ -99,10 +122,14 @@ 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.text\n" "\t.global %s\n" + "\t.global _%s\n" "%s:\n" + "_%s:\n" "\tmov 12(%%esp), %%eax\n" "\tmov $%d, %%ecx\n" "\tmul %%ecx\n" @@ -114,11 +141,22 @@ const char *prefixfmt[] = { "tiletab:\n", /* NASM template */ - "\tglobl %s\n" + /* TODO hardcoding the 16bpp changes for now, generalize later + * and while we're at it, let's get rid of the mul too ... + */ + "\tsection .text\n" + "\tglobal %s\n" + "\tglobal _%s\n" "%s:\n" + "_%s:\n" "\tmov eax, [esp + 12]\n" - "\tmov ecx. %d\n" - "\tmul ecx\n" + ";\tmov ecx, %d\n" + ";\tmul ecx\n" + "\tmov ecx, eax\n" + "\tshl eax, 9\n" + "\tshl ecx, 7\n" + "\tadd eax, ecx\n" + "\tadd eax, [esp + 8]\n" "\tadd eax, [esp + 8]\n" "\tadd eax, [esp + 4]\n" "\tmov edx, eax\n" @@ -129,13 +167,26 @@ const char *prefixfmt[] = { int proc_sheet(const char *fname) { - int i, j, num_xtiles, num_ytiles, xsz, ysz, tidx; + int i, j, x, y, num_xtiles, num_ytiles, xsz, ysz, tidx; struct image img; if(load_image(&img, fname) == -1) { 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; @@ -143,16 +194,30 @@ int proc_sheet(const char *fname) if(tile_xsz <= 0) { num_xtiles = num_ytiles = 1; - xsz = rect.w; - ysz = rect.h; + xsz = rect.w - padding; + ysz = rect.h - padding; } else { - num_xtiles = rect.w / tile_xsz; - num_ytiles = rect.h / tile_ysz; + if(padding) { + num_xtiles = num_ytiles = 0; + i = 0; + while(i < rect.w) { + num_xtiles++; + i += tile_xsz + padding; + } + i = 0; + while(i < rect.h) { + num_ytiles++; + i += tile_ysz + padding; + } + } else { + num_xtiles = rect.w / tile_xsz; + num_ytiles = rect.h / tile_ysz; + } xsz = tile_xsz; ysz = tile_ysz; } - printf(prefixfmt[asyntax], name, name, fbpitch); + printf(prefixfmt[asyntax], name, name, name, name, fbpitch); for(i=0; ipixels + 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 +272,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 +301,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,54 +309,55 @@ 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++); + printf("\t%sb $0x%x, %d(%%edx)\n", wrop, (unsigned int)*pptr++, j++); } else { - printf("\tmov byte [edx + %d], 0x%x\n", j++, (unsigned int)*pptr++); + printf("\t%s byte [edx + %d], 0x%x\n", wrop, j++, (unsigned int)*pptr++); } case 2: if(asyntax == AS_GNU) { - printf("\tmovw $0x%x, %d(%%edx)\n", (unsigned int)*(uint16_t*)pptr, j); + printf("\t%sw $0x%x, %d(%%edx)\n", wrop, (unsigned int)*(uint16_t*)pptr, j); } else { - printf("\tmov word [edx + %d], 0x%x\n", j, (unsigned int)*(uint16_t*)pptr); + printf("\t%s word [edx + %d], 0x%x\n", wrop, j, (unsigned int)*(uint16_t*)pptr); } pptr += 2; j += 2; break; case 1: if(asyntax == AS_GNU) { - printf("\tmovb $0x%x, %d(%%edx)\n", (unsigned int)*pptr++, j++); + printf("\t%sb $0x%x, %d(%%edx)\n", wrop, (unsigned int)*pptr++, j++); } else { - printf("\tmov byte [edx + %d], 0x%x\n", j++, (unsigned int)*pptr++); + printf("\t%s byte [edx + %d], 0x%x\n", wrop, j++, (unsigned int)*pptr++); } break; } @@ -310,9 +381,12 @@ void print_usage(const char *argv0) printf("Options:\n"); printf(" -s,-size : tile size (default: whole image)\n"); printf(" -r,-rect : use rectangle of the input image (default: whole image)\n"); + printf(" -p,-pad : how many pixels to skip between tiles in source image (default: 0)\n"); 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(" -x,-xor: use XOR for writing pixels instead of MOV\n"); printf(" -gas: output GNU assembler code (default)\n"); printf(" -nasm: output NASM-compatible code\n"); printf(" -h: print usage and exit\n");