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)
{
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) {
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) {
} 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;
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"
"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"
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;
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; i<num_ytiles*num_xtiles; i++) {
if(asyntax == AS_GNU) {
printf("\t.long tile%d\n", i);
putchar('\n');
tidx = 0;
+ y = rect.y;
for(i=0; i<num_ytiles; i++) {
+ x = rect.x;
for(j=0; j<num_xtiles; j++) {
printf("tile%d:\n", tidx++);
- csprite(&img, rect.x + j * xsz, rect.y + i * ysz, xsz, ysz);
+ csprite(&img, x, y, xsz, ysz);
+ x += xsz + padding;
}
+ y += ysz + padding;
}
+ free(img.pixels);
return 0;
}
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);
}
for(j=0; j<xsz; j++) {
- if(*pptr == ckey) {
+ if(memcmp(pptr, &ckey, pixsz) == 0) {
new_mode = CSOP_SKIP;
} else {
new_mode = CSOP_COPY;
mode = new_mode;
start = j;
}
- pptr++;
+ pptr += pixsz;
}
- pptr += img->scansz - xsz;
+ pptr += img->scansz - xsz * pixsz;
if(mode != -1) {
assert(start >= 0);
}
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 */
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; j<optr->len / 4; j++) {
+ lenbytes = optr->len * pixsz;
+ for(j=0; j<lenbytes / 4; j++) {
if(asyntax == AS_GNU) {
- printf("\tmovl $0x%x, %d(%%edx)\n", *(uint32_t*)pptr, j * 4);
+ printf("\t%sl $0x%x, %d(%%edx)\n", wrop, *(uint32_t*)pptr, j * 4);
} else {
- printf("\tmov dword [edx + %d], 0x%x\n", j * 4, *(uint32_t*)pptr);
+ printf("\t%s dword [edx + %d], 0x%x\n", wrop, j * 4, *(uint32_t*)pptr);
}
pptr += 4;
}
j *= 4;
- switch(optr->len % 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;
}
printf("Options:\n");
printf(" -s,-size <WxH>: tile size (default: whole image)\n");
printf(" -r,-rect <WxH+X+Y>: use rectangle of the input image (default: whole image)\n");
+ printf(" -p,-pad <N>: how many pixels to skip between tiles in source image (default: 0)\n");
printf(" -coffset <offs>: colormap offset [0, 255] (default: 0)\n");
printf(" -fbpitch <pitch>: target framebuffer pitch (scanline size in bytes)\n");
printf(" -k,-key <color>: 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");