X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?p=dosdemo;a=blobdiff_plain;f=tools%2Fcsprite%2Fsrc%2Fmain.c;fp=tools%2Fcsprite%2Fsrc%2Fmain.c;h=4c291b949f3e929697328deb8752948c7fe62f54;hp=0000000000000000000000000000000000000000;hb=02d3f6c78597600d2b100748aa54241228b9ca09;hpb=ba648ddfc62fc6d3f47294aa8bfc10ea6ca3f479 diff --git a/tools/csprite/src/main.c b/tools/csprite/src/main.c new file mode 100644 index 0000000..4c291b9 --- /dev/null +++ b/tools/csprite/src/main.c @@ -0,0 +1,319 @@ +#include +#include +#include +#include +#include +#include +#include "image.h" + +struct rect { + int x, y, w, h; +}; + +enum { AS_GNU, AS_NASM }; + +int csprite(struct image *img, int x, int y, int xsz, int ysz); +int proc_sheet(const char *fname); +void print_usage(const char *argv0); + +int tile_xsz, tile_ysz; +struct rect rect; +int cmap_offs; +int ckey; +int fbpitch = 320; +const char *name = "sprite"; +int asyntax = AS_GNU; + +int main(int argc, char **argv) +{ + int i; + char *endp; + + for(i=1; i= 256) { + fprintf(stderr, "-coffset must be followed by a valid colormap offset\n"); + return 1; + } + + } else if(strcmp(argv[i], "-fbpitch") == 0) { + fbpitch = atoi(argv[++i]); + if(fbpitch <= 0) { + fprintf(stderr, "-fbpitch must be followed by a positive number\n"); + return 1; + } + + } else if(strcmp(argv[i], "-n") == 0 || strcmp(argv[i], "-name") == 0) { + name = argv[++i]; + if(!name) { + fprintf(stderr, "%s must be followed by a name\n", argv[i - 1]); + return 1; + } + + } 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) { + fprintf(stderr, "%s must be followed by a valid color key\n", argv[i - 1]); + return 1; + } + + } else if(strcmp(argv[i], "-gas") == 0) { + asyntax = AS_GNU; + + } else if(strcmp(argv[i], "-nasm") == 0) { + asyntax = AS_NASM; + + } else if(strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "-help") == 0) { + print_usage(argv[0]); + return 0; + + } else { + fprintf(stderr, "invalid option: %s\n", argv[i]); + print_usage(argv[0]); + return 1; + } + + } else { + if(proc_sheet(argv[i]) == -1) { + return 1; + } + } + } + + return 0; +} + +const char *prefixfmt[] = { + /* GNU assembler template */ + "\t.global %s\n" + "%s:\n" + "\tmov 12(%%esp), %%eax\n" + "\tmov $%d, %%ecx\n" + "\tmul %%ecx\n" + "\tadd 8(%%esp), %%eax\n" + "\tadd 4(%%esp), %%eax\n" + "\tmov %%eax, %%edx\n" + "\tmov 16(%%esp), %%eax\n" + "\tjmp *tiletab(,%%eax,4)\n\n" + "tiletab:\n", + + /* NASM template */ + "\tglobl %s\n" + "%s:\n" + "\tmov eax, [esp + 12]\n" + "\tmov ecx. %d\n" + "\tmul ecx\n" + "\tadd eax, [esp + 8]\n" + "\tadd eax, [esp + 4]\n" + "\tmov edx, eax\n" + "\tmov eax, [esp + 16]\n" + "\tjmp [titletab + eax * 4]\n\n" + "titletab:\n" +}; + +int proc_sheet(const char *fname) +{ + int i, j, 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(rect.w <= 0) { + rect.w = img.width; + rect.h = img.height; + } + + if(tile_xsz <= 0) { + num_xtiles = num_ytiles = 1; + xsz = rect.w; + ysz = rect.h; + } 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); + for(i=0; ipixels + y * img->scansz + x; + struct csop *ops, *optr; + + ops = optr = alloca((xsz + 1) * ysz * sizeof *ops); + + for(i=0; i 0) { + optr++->op = CSOP_ENDL; + } + + for(j=0; j= 0); + optr->op = mode; + optr->len = j - start; + optr++; + } + mode = new_mode; + start = j; + } + pptr++; + } + pptr += img->scansz - xsz; + + if(mode != -1) { + assert(start >= 0); + optr->op = mode; + optr->len = xsz - start; + optr++; + } + } + numops = optr - ops; + + pptr = img->pixels + y * img->scansz + x; + optr = ops; + skip_acc = 0; + /* edx points to dest */ + for(i=0; iop) { + case CSOP_SKIP: + skip_acc += optr->len; + pptr += optr->len; + break; + + case CSOP_ENDL: + skip_acc += fbpitch - xsz; + pptr += img->scansz - xsz; + break; + + case CSOP_COPY: + if(skip_acc) { + if(asyntax == AS_GNU) { + printf("\tadd $%d, %%edx\n", skip_acc); + } else { + printf("\tadd edx, %d\n", skip_acc); + } + skip_acc = 0; + } + + for(j=0; jlen / 4; j++) { + if(asyntax == AS_GNU) { + printf("\tmovl $0x%x, %d(%%edx)\n", *(uint32_t*)pptr, j * 4); + } else { + printf("\tmov dword [edx + %d], 0x%x\n", j * 4, *(uint32_t*)pptr); + } + pptr += 4; + } + j *= 4; + switch(optr->len % 4) { + case 3: + if(asyntax == AS_GNU) { + printf("\tmovb $0x%x, %d(%%edx)\n", (unsigned int)*pptr++, j++); + } else { + printf("\tmov byte [edx + %d], 0x%x\n", j++, (unsigned int)*pptr++); + } + case 2: + if(asyntax == AS_GNU) { + printf("\tmovw $0x%x, %d(%%edx)\n", (unsigned int)*(uint16_t*)pptr, j); + } else { + printf("\tmov word [edx + %d], 0x%x\n", 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++); + } else { + printf("\tmov byte [edx + %d], 0x%x\n", j++, (unsigned int)*pptr++); + } + break; + } + + skip_acc = optr->len; + break; + + default: + printf("\t%c invalid op: %d\n", asyntax == AS_GNU ? '#' : ';', optr->op); + } + optr++; + } + printf("\tret\n"); + + return 0; +} + +void print_usage(const char *argv0) +{ + printf("Usage: %s [options] \n", 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(" -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(" -gas: output GNU assembler code (default)\n"); + printf(" -nasm: output NASM-compatible code\n"); + printf(" -h: print usage and exit\n"); +}