/* genaif: Generate EPOC32 AIF files, which are used by the EPOC32 shell e.g. to display the icon and the program name on the extras bar Copyright 1999 Rudolf Koenig. License: GPL. See AIF format dokumentation on http://koeniglich.de Modified by Kevin Boone to generate APP files, and insert correct magic numbers for PJava applications */ #include #include #include /* NOTE: we have to write intel byte oder. Fix this if not on native */ #define PUTLONG(X) fwrite(&X, sizeof(long), 1, stdout) #define GETLONG(X) fread(&X, sizeof(long), 1, mbm) static char *Usage = "Usage: genaif UID3 < aifspecfile > app.aif\n" " Or: genaif UID1 UID2 UID3 > pkgfile.pkg\n" "\n" "# Sample aifspecfile:\n" "# Mbmfile contains a number of icon/mask pairs\n" "mbmfile=app.mbm\n" "ELangEnglish=The test app\n" "ELangGerman=Die Test App\n" "hidden=0\n" "embeddability=0\n" "newfile=1\n"; static char *langs[] = { "ELangTest", "ELangEnglish", "ELangFrench", "ELangGerman", "ELangSpanish", "ELangItalian", "ELangSwedish", "ELangDanish", "ELangNorwegian", "ELangFinnish", "ELangAmerican", "ELangSwissFrench", "ELangSwissGerman", "ELangPortuguese", "ELangTurkish", "ELangIcelandic", "ELangRussian", "ELangHungarian", "ELangDutch", "ELangBelgianFlemish", "ELangAustralian", "ELangBelgianFrench", "ELangAustrian", "ELangNewZealand", 0 }; int docrc16_1(crc, c) unsigned int crc; unsigned char c; { unsigned int acc, i; acc = crc; acc ^= c << 8; for(i = 0; i < 8; i++) if(acc & 0x8000) { acc <<= 1; acc ^= 0x1021; } else { acc <<= 1; } return acc & 0xffff; } unsigned long uidcsum(unsigned long u[3]) { unsigned int i, crc1 = 0, crc2 = 0; unsigned char *c; for(i = 0; i < 3; i++) { c = (unsigned char *)&u[i]; crc1 = docrc16_1(crc1, c[0]); crc2 = docrc16_1(crc2, c[1]); crc1 = docrc16_1(crc1, c[2]); crc2 = docrc16_1(crc2, c[3]); } return (crc2 << 16) | crc1; } int main(int ac, char *av[]) { char *s, *arg, buf[1024], *caps[128], *mbmfile; int len, rd, idx, no, capno, embed, hidden, new, cappos[128]; unsigned char outchar, caplang[128]; unsigned long l[3], uid; FILE *mbm; if(ac == 4) { l[0] = strtol(av[1], 0, 0); l[1] = strtol(av[2], 0, 0); l[2] = strtol(av[3], 0, 0); //printf("%#08x\n", uidcsum(l)); fwrite(&(l[0]), 1, 4, stdout); fwrite(&(l[1]), 1, 4, stdout); fwrite(&(l[2]), 1, 4, stdout); int b = uidcsum(l); fwrite(&b, 1, 4, stdout); return 0; } if(ac != 2) { fprintf(stderr, "%s", Usage); return 1; } uid = strtol(av[1], 0, 0); rd = no = hidden = embed = capno = new = 0; mbmfile = 0; while(fgets(buf, sizeof(buf), stdin)) { no++; if(!*buf || *buf == '#') continue; if(!(s = strtok(buf, "=")) || !(arg = strtok(0, "\n\r"))) { fprintf(stderr, "Bogus data in line %d\n\n%s", no, Usage); return 1; } if(!strcasecmp(s, "mbmfile")) mbmfile = strdup(arg); else if(!strcasecmp(s, "hidden")) hidden = strtol(arg, 0, 0); else if(!strcasecmp(s, "embeddability")) embed = strtol(arg, 0, 0); else if(!strcasecmp(s, "newfile")) new = strtol(arg, 0, 0); else { for(idx = 0; langs[idx]; idx++) if(!strcasecmp(langs[idx], s)) break; if(capno > 128) { fprintf(stderr, "Sorry, too man captions\n"); return 1; } if(langs[idx]) { if(strlen(arg) > 63) { fprintf(stderr, "Sorry, caption in line %d too long\n", no); return 1; } rd += strlen(arg) + 1; caps[capno] = strdup(arg); caplang[capno++] = idx; continue; } fprintf(stderr, "Unknown keyword in line %d\n\n%s", no, Usage); return 1; } } if(uid == 0 || mbmfile == 0 || capno == 0) { fprintf(stderr, "Data (uid, mbmfile or caption) is missing\n%s", Usage); return 0; } l[0] = 0x10000037; PUTLONG(l[0]); // l[1] = 0x1000006a; PUTLONG(l[1]); l[1] = 0x10003a38; PUTLONG(l[1]); l[2] = uid; PUTLONG(l[2]); no = uidcsum(l); PUTLONG(no); /* Mbmfile reading */ if(!(mbm = fopen(mbmfile, "r"))) { perror(mbmfile); return 1; } GETLONG(no); GETLONG(uid); if(no != 0x10000037 || uid != 0x10000042) { fprintf(stderr, "Unknown MBM file, sorry, no output\n"); return 1; } GETLONG(no); /* Ignored */ GETLONG(no); /* Ignored */ GETLONG(no); /* This is the trailer offset */ idx = no + rd; PUTLONG(idx); /* This is the output offset */ /* Copy the MBM file */ for(idx = 20; idx < no && rd != 0; idx += rd) { rd = (no-idx) > sizeof(buf) ? sizeof(buf) : no-idx; rd = fread(buf, 1, rd, mbm); fwrite(buf, 1, rd, stdout); } if(!rd) { fprintf(stderr, "Sorry, mbm file too short!\n"); return 1; } /* write out the captions */ rd = no; for(idx = 0; idx < capno; idx++) { cappos[idx] = rd; len = strlen(caps[idx]); outchar = len * 4 + 2; putchar(outchar); fwrite(caps[idx], len, 1, stdout); rd += len + 1; } /* Trailer time!! */ /* First the caption offsets */ outchar = 2 * capno; putchar(outchar); for(idx = 0; idx < capno; idx++) { PUTLONG(cappos[idx]); putchar(caplang[idx]); putchar(0); /* This fails if there are more than 255 langs */ } /* Now the Picture offsets */ GETLONG(no); if(no % 2 != 0 || !no) { fprintf(stderr, "Sorry, we need some icon PAIRS (image/mask)\n"); return 1; } outchar = no; /* Hope this works every time... */ putchar(outchar); for(idx = 0; idx < no; idx += 2) { GETLONG(rd); /* Offsets are in mbm and aif the same */ PUTLONG(rd); len = ftell(mbm); fseek(mbm, rd, SEEK_SET); GETLONG(rd); /* Length of chunk, ignored */ GETLONG(rd); /* Headerlength, ignored */ GETLONG(rd); /* X-Size! This is what we are looking for */ outchar = rd & 0xff; putchar(outchar); /* Write it as short */ outchar = (rd & 0xff00) >> 8; putchar(outchar); fseek(mbm, len, SEEK_SET); GETLONG(rd); } no = 0x00000001; PUTLONG(no); PUTLONG(embed); PUTLONG(new); PUTLONG(hidden); return 0; }