From: uz Date: Wed, 28 Dec 2011 17:46:17 +0000 (+0000) Subject: Renamed the main file to main.c for consistency reasons. X-Git-Tag: V2.13.3~119 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=3364c1d779fcb5c12e604902f3662f534a01d637;p=cc65 Renamed the main file to main.c for consistency reasons. git-svn-id: svn://svn.cc65.org/cc65/trunk@5345 b7a2c559-68d2-44c3-8de9-860c34a00d81 --- diff --git a/src/grc65/grc65.c b/src/grc65/grc65.c deleted file mode 100644 index dc281c593..000000000 --- a/src/grc65/grc65.c +++ /dev/null @@ -1,822 +0,0 @@ -/* GEOS resource compiler - - by Maciej 'YTM/Elysium' Witkowiak - - see GEOSLib documentation for license info -*/ - -/* - make it work, then do it better - - more or less comments? it was hard to code, should be even harder to - understand =D - - add loadable icons feature (binary - 63 bytes) -*/ - -/* - err, maybe free allocated memory, huh? (who cares, it's just a little prog...) -*/ - -#include -#include -#include -#include -#include -#include - -/* common stuff */ -#include "fname.h" -#include "abend.h" -#include "chartype.h" -#include "target.h" -#include "xmalloc.h" - -/* I hope that no one will be able to create a .grc bigger than this... */ -#define BLOODY_BIG_BUFFER 65000 - - - -struct menuitem { - char *name; - char *type; - char *target; - struct menuitem *next; -}; - -struct menu { - char *name; - int top, left; - int bot, right; - char *type; - struct menuitem *item; -}; - -struct appheader { - int year, month, day, hour, min; - int mode; - int dostype; - int geostype; - int structure; - char *dosname; - char *classname; - char *version; - char *author; - char *info; - char *icon; -}; - -const char *mainToken[] = {"MENU", "HEADER", "ICON", "DIALOG", "VLIR", ""}; - -const char *hdrFTypes[] = {"APPLICATION", "AUTO_EXEC", "DESK_ACC", "ASSEMBLY", - "DISK_DEVICE", "PRINTER", "SYSTEM", ""}; - -const char *hdrFields[] = {"author", "info", "date", "dostype", "mode", "structure", "icon", ""}; - -const char *hdrDOSTp[] = {"seq", "SEQ", "prg", "PRG", "usr", "USR", ""}; - -const char *hdrStructTp[] = {"seq", "SEQ", "vlir", "VLIR", ""}; - -const char *hdrModes[] = {"any", "40only", "80only", "c64only", ""}; - -const int BSWTab[] = {0, 0x005, 0x007, 0x00b, 0x011, 0x017, 0x01d, 0x023, - 0x025, 0x029, 0x02d, 0x033, 0x039, 0x03c, 0x041, 0x043, 0x04a, 0x04f, - 0x052, 0x056, 0x05a, 0x05f, 0x063, 0x068, 0x06d, 0x072, 0x077, 0x079, - 0x07c, 0x080, 0x084, 0x088, 0x08e, 0x094, 0x09a, 0x09f, 0x0a4, 0x0a9, - 0x0ad, 0x0b1, 0x0b6, 0x0bc, 0x0be, 0x0c2, 0x0c8, 0x0cc, 0x0d4, 0x0da, - 0x0e0, 0x0e5, 0x0eb, 0x0f0, 0x0f5, 0x0f9, 0x0fe, 0x104, 0x10c, 0x112, - 0x118, 0x11e, 0x121, 0x129, 0x12c, 0x132, 0x13a, 0x13e, 0x143, 0x148, - 0x14d, 0x152, 0x157, 0x15a, 0x15f, 0x164, 0x166, 0x168, 0x16d, 0x16f, - 0x177, 0x17c, 0x182, 0x187, 0x18c, 0x18f, 0x193, 0x196, 0x19b, 0x1a1, - 0x1a9, 0x1af, 0x1b4, 0x1ba, 0x1be, 0x1c0, 0x1c4, 0x1ca, 0x1d2, 0x1dd}; - -const unsigned char icon1[] = {255, 255, 255, 128, 0, 1, 128, 0, 1, - 128, 0, 1, 128, 0, 1, 128, 0, 1, - 128, 0, 1, 128, 0, 1, 128, 0, 1, - 128, 0, 1, 128, 0, 1, 128, 0, 1, - 128, 0, 1, 128, 0, 1, 128, 0, 1, - 128, 0, 1, 128, 0, 1, 128, 0, 1, - 128, 0, 1, 128, 0, 1, 255, 255, 255}; - -char *ProgName; /* for AbEnd, later remove and use common/cmdline.h */ - -char *outputCName = NULL, *outputSName = NULL; -FILE *outputCFile, *outputSFile; -int CFnum = 0, SFnum = 0; -int apple = 0; -char outputCMode[2] = "w"; -char outputSMode[2] = "w"; - - -void printUsage(void) { - - printf("Usage: %s [options] file\n" - "Options:\n" - "\t-h, -?\t\tthis help\n" - "\t-o name\t\tname C output file\n" - "\t-s name\t\tname asm output file\n" - "\t-t sys\t\tset target system\n", - ProgName); -} - - -void printCHeader(void) { - - fprintf(outputCFile, - "//\n" - "//\tThis file was generated by the GEOS Resource Compiler\n" - "//\n" - "//\tDO NOT EDIT! Any changes will be lost!\n" - "//\n" - "//\tEdit proper resource file instead.\n" - "//\n\n"); -} - - -void printSHeader(void) { - - fprintf(outputSFile, - ";\n" - ";\tThis file was generated by the GEOS Resource Compiler\n" - ";\n" - ";\tDO NOT EDIT! Any changes will be lost!\n" - ";\n" - ";\tEdit proper resource file instead.\n" - ";\n\n"); -} - - -void openCFile(void) { - - if ((outputCFile = fopen(outputCName,outputCMode)) == 0) { - AbEnd("can't open file %s for writing: %s\n", outputCName, strerror(errno)); - } - - if (CFnum == 0) { - outputCMode[0] = 'a'; - printCHeader(); - CFnum++; - } -} - - -void openSFile(void) { - - if ((outputSFile = fopen(outputSName, outputSMode)) == 0) { - AbEnd("can't open file %s for writing: %s\n", outputSName, strerror(errno)); - } - - if (SFnum == 0) { - outputSMode[0] = 'a'; - printSHeader(); - SFnum++; - } -} - - -int findToken(const char **tokenTbl, const char *token) { - - /* takes as input table of tokens and token, returns position in table or -1 if not found */ - int a = 0; - - while (strlen(tokenTbl[a]) != 0) { - if (strcmp(tokenTbl[a], token) == 0) break; - a++; - } - - if (strlen(tokenTbl[a]) == 0) a = -1; - return a; -} - - -char *nextPhrase() { - return strtok(NULL, "\""); -} - - -char *nextWord() { - return strtok(NULL, " "); -} - - -void setLen(char *name, unsigned len) { - if (strlen(name) > len) - name[len] = '\0'; -} - - -void fillOut(char *name, int len, char *filler) { - - int a; - - setLen(name, len); - fprintf(outputSFile, "\t.byte \"%s\"\n", name); - - a = strlen(name); - if (a < len) { - fprintf(outputSFile, "\t.res (%i - %i), %s\n", len, a, filler); - } -} - - -char *bintos(unsigned char a, char out[7]) { - - int i=0; - - for (; i < 8; i++) { - out[7 - i] = ((a & 1) == 0) ? '0' : '1'; - a = a >> 1; - } - out[i] = '\0'; - - return out; -} - - -int getNameSize(const char *word) { - - /* count length of a word using BSW 9 font table */ - int a = 0, i = 0; - - while (word[i] != '\0') { - a += (BSWTab[word[i] - 31] - BSWTab[word[i] - 32]); - i++; - } - - return a; -} - - -void DoMenu(void) { - - int a, size, tmpsize, item = 0; - char *token; - char namebuff[255] = ""; - struct menu myMenu; - struct menuitem *curItem, *newItem; - - openCFile(); - - myMenu.name = nextWord(); - myMenu.left = atoi(nextWord()); - myMenu.top = atoi(nextWord()); - myMenu.type = nextWord(); - - if (strcmp(nextWord(), "{") != 0) { - AbEnd("menu '%s' description has no opening bracket!\n", myMenu.name); - } - curItem = xmalloc(sizeof(struct menuitem)); - myMenu.item = curItem; - do { - token = nextWord(); - if (strcmp(token, "}") == 0) break; - if (token[strlen(token) - 1] != '"') { - strcpy(namebuff, token); - do { - token = nextWord(); - strcat(namebuff, " "); - strcat(namebuff, token); - } while (token[strlen(token) - 1] != '"'); - token = xmalloc(strlen(namebuff)); - strcpy(token, namebuff); - } - curItem->name = token; - curItem->type = nextWord(); - curItem->target = nextWord(); - newItem = xmalloc(sizeof(struct menuitem)); - curItem->next = newItem; - curItem = newItem; - item++; - } while (strcmp(token, "}") != 0); - if (item == 0) AbEnd("menu '%s' has 0 items!\n", myMenu.name); - if (item > 31) AbEnd("menu '%s' has too many items!\n", myMenu.name); - - curItem->next = NULL; - - /* count menu sizes */ - size = 0; - curItem = myMenu.item; - if (strstr(myMenu.type, "HORIZONTAL") != NULL) { - /* menu is HORIZONTAL, ysize=15, sum xsize of all items +~8?*/ - myMenu.bot = myMenu.top + 15; - for (a = 0; a != item; a++) { - size += getNameSize(curItem->name); - curItem = curItem->next; - } - } else { - /* menu is VERTICAL, ysize=item*15, count largest xsize of all items +~8? */ - myMenu.bot = myMenu.top + (14 * item); - for (a = 0; a != item; a++) { - tmpsize = getNameSize(curItem->name); - size = (size > tmpsize) ? size : tmpsize; - curItem = curItem->next; - } - } - myMenu.right = myMenu.left + size - 1; - - curItem = myMenu.item; - for (a = 0; a != item; a++) { - /* print prototype only if MENU_ACTION or DYN_SUB_MENU are present in type */ - if ((strstr(curItem->type, "MENU_ACTION") != NULL) || (strstr(curItem->type, "DYN_SUB_MENU") != NULL)) { - fprintf(outputCFile, - "void %s (void);\n", - curItem->target); - } - curItem=curItem->next; - } - - fprintf(outputCFile, - "\n" - "const void %s = {\n" - "\t(char)%i, (char)%i,\n" - "\t(int)%i, (int)%i,\n" - "\t(char)(%i | %s),\n", - myMenu.name, myMenu.top, myMenu.bot, myMenu.left, myMenu.right, item, myMenu.type); - - curItem = myMenu.item; - for (a = 0; a != item; a++) { - fprintf(outputCFile, - "\t%s, (char)%s, (int)", - curItem->name, curItem->type); - if ((strstr(curItem->type, "SUB_MENU") != NULL) && (strstr(curItem->type, "DYN_SUB_MENU") == NULL)) - fprintf(outputCFile, - "&"); - fprintf(outputCFile, - "%s,\n", - curItem->target); - curItem = curItem->next; - } - - fprintf(outputCFile, - "};\n\n"); - - if (fclose(outputCFile) != 0) - AbEnd("error closing %s: %s\n", outputCName, strerror(errno)); -} - - -void DoHeader(void) { - - time_t t; - struct tm *my_tm; - - struct appheader myHead; - char *token; - char i1[9], i2[9], i3[9]; - int a, b; - - openSFile(); - - token = nextWord(); - - a = findToken(hdrFTypes, token); - - if (apple == 1) { - switch (a) { - case 0: - myHead.geostype = 0x82; - break; - default: - AbEnd("filetype '%s' is not supported yet\n", token); - } - } else { - switch (a) { - case 0: - myHead.geostype = 6; - break; - case 1: - myHead.geostype = 14; - break; - default: - AbEnd("filetype '%s' is not supported yet\n", token); - } - } - - myHead.dosname = nextPhrase(); - nextPhrase(); - myHead.classname = nextPhrase(); - nextPhrase(); - myHead.version = nextPhrase(); - - /* put default values into myHead here */ - myHead.author = "cc65"; - myHead.info = "Program compiled with cc65 and GEOSLib."; - myHead.dostype = 128; - if (apple == 0) myHead.dostype += 3; - myHead.structure = 0; - myHead.mode = 0; - myHead.icon = NULL; - - t = time(NULL); - my_tm = localtime(&t); - - myHead.year = my_tm->tm_year; - myHead.month = my_tm->tm_mon+1; - myHead.day = my_tm->tm_mday; - myHead.hour = my_tm->tm_hour; - myHead.min = my_tm->tm_min; - - if (strcmp(nextWord(), "{") != 0) { - AbEnd("header '%s' has no opening bracket!\n", myHead.dosname); - } - - do { - token = nextWord(); - if (strcmp(token, "}") == 0) break; - switch (a = findToken(hdrFields, token)) { - case -1: - AbEnd("unknown field '%s' in header '%s'\n", token, myHead.dosname); - break; - case 0: /* author */ - myHead.author = nextPhrase(); - break; - case 1: /* info */ - myHead.info = nextPhrase(); - break; - case 2: /* date */ - myHead.year = atoi(nextWord()); - myHead.month = atoi(nextWord()); - myHead.day = atoi(nextWord()); - myHead.hour = atoi(nextWord()); - myHead.min = atoi(nextWord()); - break; - case 3: /* dostype */ - switch (b = findToken(hdrDOSTp, nextWord())) { - case -1: - AbEnd("unknown dostype in header '%s'\n", myHead.dosname); - break; - default: - if (apple == 0) myHead.dostype = b / 2 + 128 + 1; - break; - } - break; - case 4: /* mode */ - switch (b = findToken(hdrModes, nextWord())) { - case -1: - AbEnd("unknown mode in header '%s'\n", myHead.dosname); - case 0: - if (apple == 0) myHead.mode = 0x40; - break; - case 1: - if (apple == 0) myHead.mode = 0x00; - break; - case 2: - if (apple == 0) myHead.mode = 0xc0; - break; - case 3: - if (apple == 0) myHead.mode = 0x80; - break; - } - break; - case 5: /* structure */ - switch (b = findToken(hdrStructTp, nextWord())) { - case -1: - AbEnd("unknown structure type in header '%s'\n", myHead.dosname); - case 0: - case 1: - myHead.structure = 0; - break; - case 2: - case 3: - myHead.structure = 1; - break; - } - break; - case 6: /* icon */ - myHead.icon = nextPhrase(); - break; - } - - } while (strcmp(token, "}") != 0); - - /* OK, all information is gathered, do flushout */ - - fprintf(outputSFile, - "\n" - "\t\t.segment \"DIRENTRY\"\n\n"); - - if (apple == 1) { - - fprintf(outputSFile, - "\t.byte %i << 4 | %u\n", - myHead.structure + 2, (unsigned) strlen(myHead.dosname)); - - fillOut(myHead.dosname, 15, "0"); - - fprintf(outputSFile, - "\t.byte $%02x\n" - "\t.word 0\n" - "\t.word 0\n" - "\t.byte 0, 0, 0\n" - "\t.word %i << 9 | %i << 5 | %i, %i << 8 | %i\n" - "\t.byte 0\n" - "\t.byte 0\n" - "\t.byte 0\n" - "\t.word 0\n" - "\t.word %i << 9 | %i << 5 | %i, %i << 8 | %i\n" - "\t.word 0\n", - myHead.geostype, - myHead.year % 100, myHead.month, myHead.day, myHead.hour, myHead.min, - myHead.year % 100, myHead.month, myHead.day, myHead.hour, myHead.min); - - } else { - - fprintf(outputSFile, - "\t.byte %i\n" - "\t.word 0\n", - myHead.dostype); - - fillOut(myHead.dosname, 16, "$a0"); - - fprintf(outputSFile, - "\t.word 0\n" - "\t.byte %i\n" - "\t.byte %i\n" - "\t.byte %i, %i, %i, %i, %i\n\n" - "\t.word 0\n" - "\t.byte \"PRG formatted GEOS file V1.0\"\n\n", - myHead.structure, myHead.geostype, - myHead.year, myHead.month, myHead.day, myHead.hour, myHead.min); - } - - fprintf(outputSFile, - "\n" - "\t\t.segment \"FILEINFO\"\n\n" - "\t.import __VLIR0_START__, __STARTUP_RUN__\n\n" - "\t.byte 3, 21, 63 | $80\n"); - - if (myHead.icon != NULL) { - fprintf(outputSFile, - "\t.incbin \"%s\", 0, 63\n", - myHead.icon); - } else { - for (a = 0; a != 63; a = a + 3) { - fprintf(outputSFile, - "\t.byte %%%s, %%%s, %%%s\n", - bintos(icon1[a], i1), bintos(icon1[a+1], i2), bintos(icon1[a+2], i3)); - } - } - - fprintf(outputSFile, - "\t.byte %i, %i, %i\n" - "\t.word __VLIR0_START__, __VLIR0_START__ - 1, __STARTUP_RUN__\n\n", - myHead.dostype, myHead.geostype, myHead.structure); - - fillOut(myHead.classname, 12, "$20"); - - fillOut(myHead.version, 4, "0"); - - fprintf(outputSFile, - "\t.byte 0, 0, 0\n" - "\t.byte %i\n\n", - myHead.mode); - - setLen(myHead.author, 62); - fprintf(outputSFile, - "\t.byte \"%s\"\n" - "\t.byte 0\n" - "\t.res (63 - %i)\n\n", - myHead.author, (int)(strlen(myHead.author) + 1)); - - setLen(myHead.info, 95); - fprintf(outputSFile, - "\t.byte \"%s\"\n" - "\t.byte 0\n\n", - myHead.info); - - if (fclose (outputSFile) != 0) - AbEnd("error closing %s: %s\n", outputSName, strerror(errno)); -} - - -void DoVLIR(void) { - - char *token; - int record, lastrecord; - int vlirsize, vlirtable[127]; - - openSFile(); - - vlirsize = strtol(nextWord(), NULL, 0); - - if (strcmp(nextWord(), "{") != 0) { - AbEnd ("VLIR description has no opening bracket!\n"); - } - - lastrecord = -1; - memset(vlirtable, 0, sizeof(vlirtable)); - - do { - token = nextWord(); - if (strcmp(token, "}") == 0) break; - - record = atoi(token); - if (record < 0 || record > 126) { - AbEnd("VLIR record %i is out of range 0-126.\n", record); - } - if (vlirtable[record] == 1) { - AbEnd("VLIR record %i is defined twice.\n", record); - } - - vlirtable[record] = 1; - if (record > lastrecord) lastrecord = record; - } while (strcmp(token, "}") != 0); - - if (lastrecord == -1) { - AbEnd("There must be at least one VLIR record.\n"); - } - - /* always include record 0 */ - vlirtable[0] = 1; - - /* OK, all information is gathered, do flushout */ - - fprintf(outputSFile, - "\n" - "\t\t.segment \"RECORDS\"\n\n" - "\t.export __OVERLAYSIZE__ : absolute = $%04x\n\n", - vlirsize); - - for (record = 0; record <= lastrecord; record++) { - if (vlirtable[record] == 1) { - fprintf(outputSFile, - "\t.import __VLIR%i_START__, __VLIR%i_LAST__\n", - record, record); - } - } - fprintf(outputSFile, - "\n"); - - for (record = 0; record <= lastrecord; record++) { - if (vlirtable[record] == 1) { - fprintf(outputSFile, - "\t.byte .lobyte ((__VLIR%i_LAST__ - __VLIR%i_START__ - 1) / 254) + 1\n" - "\t.byte .lobyte ((__VLIR%i_LAST__ - __VLIR%i_START__ - 1) .MOD 254) + 2\n", - record, record, record, record); - } else { - fprintf(outputSFile, - "\t.byte $00\n" - "\t.byte $FF\n"); - } - } - fprintf(outputSFile, - "\n"); - - if (fclose(outputSFile) != 0) - AbEnd("error closing %s: %s\n", outputSName, strerror(errno)); - - openCFile(); - - fprintf(outputCFile, - "extern void _OVERLAYADDR__;\n" - "extern void _OVERLAYSIZE__;\n\n" - "#define OVERLAY_ADDR (char*) &_OVERLAYADDR__\n" - "#define OVERLAY_SIZE (unsigned)&_OVERLAYSIZE__\n\n"); - - if (fclose(outputCFile) != 0) - AbEnd("error closing %s: %s\n", outputCName, strerror(errno)); -} - - -char *filterInput(FILE *F, char *tbl) { - - /* loads file into buffer filtering it out */ - int a, prevchar = -1, i = 0, bracket = 0, quote = 1; - - while (1) { - a = getc(F); - if ((a == '\n') || (a == '\015')) a = ' '; - if (a == ',' && quote) a = ' '; - if (a == '\042') quote =! quote; - if (quote) { - if ((a == '{') || (a == '(')) bracket++; - if ((a == '}') || (a == ')')) bracket--; - } - if (a == EOF) { - tbl[i] = '\0'; - xrealloc(tbl, i + 1); - break; - } - if (IsSpace(a)) { - if ((prevchar != ' ') && (prevchar != -1)) { - tbl[i++] = ' '; - prevchar = ' '; - } - } else { - if (a == ';' && quote) { - do { - a = getc(F); - } while (a != '\n'); - fseek(F, -1, SEEK_CUR); - } else { - tbl[i++] = a; - prevchar = a; - } - } - } - - if (bracket != 0) AbEnd("there are unclosed brackets!\n"); - - return tbl; -} - - -void processFile(const char *filename) { - - FILE *F; - - char *str; - char *token; - - int head = 0; /* number of processed HEADER sections */ - int vlir = 0; /* number of processed VLIR sections */ - - if ((F = fopen(filename, "r")) == 0) { - AbEnd("can't open file %s for reading: %s\n", filename, strerror(errno)); - } - - str = filterInput(F, xmalloc(BLOODY_BIG_BUFFER)); - - token = strtok(str, " "); - - do { - if (str != NULL) { - switch (findToken(mainToken, token)) { - case 0: - DoMenu(); - break; - case 1: - if (++head != 1) { - AbEnd("more than one HEADER section, aborting.\n"); - } else { - DoHeader(); - } - break; - case 2: break; /* icon not implemented yet */ - case 3: break; /* dialog not implemented yet */ - case 4: - if (++vlir != 1) { - AbEnd("more than one VLIR section, aborting.\n"); - } else { - DoVLIR(); - } - break; - default: - AbEnd("unknown section %s.\n",token); - break; - } - } - token = nextWord(); - } while (token != NULL); -} - - -int main(int argc, char *argv[]) { - - int ffile = 0, i = 1; - - ProgName = argv[0]; - - while (i < argc) { - const char *arg = argv[i]; - - if (arg[0] == '-') { - switch (arg[1]) { - case 'o': - outputCName = argv[++i]; - break; - case 's': - outputSName = argv[++i]; - break; - case 't': - switch (FindTarget(argv[++i])) { - case TGT_GEOS_CBM: - apple = 0; - break; - case TGT_GEOS_APPLE: - apple = 1; - break; - default: - AbEnd("unknown target system type %s\n", argv[i]); - } - break; - case 'h': - case '?': - printUsage(); - exit(EXIT_SUCCESS); - break; - default: - AbEnd("unknown option %s\n", arg); - } - } else { - ffile++; - - if (outputCName == NULL) outputCName = MakeFilename(arg, ".h"); - if (outputSName == NULL) outputSName = MakeFilename(arg, ".s"); - - processFile(arg); - } - - i++; - } - - if (ffile == 0) AbEnd("no input file\n"); - - return EXIT_SUCCESS; -} diff --git a/src/grc65/main.c b/src/grc65/main.c new file mode 100644 index 000000000..dc281c593 --- /dev/null +++ b/src/grc65/main.c @@ -0,0 +1,822 @@ +/* GEOS resource compiler + + by Maciej 'YTM/Elysium' Witkowiak + + see GEOSLib documentation for license info +*/ + +/* - make it work, then do it better + - more or less comments? it was hard to code, should be even harder to + understand =D + - add loadable icons feature (binary - 63 bytes) +*/ + +/* - err, maybe free allocated memory, huh? (who cares, it's just a little prog...) +*/ + +#include +#include +#include +#include +#include +#include + +/* common stuff */ +#include "fname.h" +#include "abend.h" +#include "chartype.h" +#include "target.h" +#include "xmalloc.h" + +/* I hope that no one will be able to create a .grc bigger than this... */ +#define BLOODY_BIG_BUFFER 65000 + + + +struct menuitem { + char *name; + char *type; + char *target; + struct menuitem *next; +}; + +struct menu { + char *name; + int top, left; + int bot, right; + char *type; + struct menuitem *item; +}; + +struct appheader { + int year, month, day, hour, min; + int mode; + int dostype; + int geostype; + int structure; + char *dosname; + char *classname; + char *version; + char *author; + char *info; + char *icon; +}; + +const char *mainToken[] = {"MENU", "HEADER", "ICON", "DIALOG", "VLIR", ""}; + +const char *hdrFTypes[] = {"APPLICATION", "AUTO_EXEC", "DESK_ACC", "ASSEMBLY", + "DISK_DEVICE", "PRINTER", "SYSTEM", ""}; + +const char *hdrFields[] = {"author", "info", "date", "dostype", "mode", "structure", "icon", ""}; + +const char *hdrDOSTp[] = {"seq", "SEQ", "prg", "PRG", "usr", "USR", ""}; + +const char *hdrStructTp[] = {"seq", "SEQ", "vlir", "VLIR", ""}; + +const char *hdrModes[] = {"any", "40only", "80only", "c64only", ""}; + +const int BSWTab[] = {0, 0x005, 0x007, 0x00b, 0x011, 0x017, 0x01d, 0x023, + 0x025, 0x029, 0x02d, 0x033, 0x039, 0x03c, 0x041, 0x043, 0x04a, 0x04f, + 0x052, 0x056, 0x05a, 0x05f, 0x063, 0x068, 0x06d, 0x072, 0x077, 0x079, + 0x07c, 0x080, 0x084, 0x088, 0x08e, 0x094, 0x09a, 0x09f, 0x0a4, 0x0a9, + 0x0ad, 0x0b1, 0x0b6, 0x0bc, 0x0be, 0x0c2, 0x0c8, 0x0cc, 0x0d4, 0x0da, + 0x0e0, 0x0e5, 0x0eb, 0x0f0, 0x0f5, 0x0f9, 0x0fe, 0x104, 0x10c, 0x112, + 0x118, 0x11e, 0x121, 0x129, 0x12c, 0x132, 0x13a, 0x13e, 0x143, 0x148, + 0x14d, 0x152, 0x157, 0x15a, 0x15f, 0x164, 0x166, 0x168, 0x16d, 0x16f, + 0x177, 0x17c, 0x182, 0x187, 0x18c, 0x18f, 0x193, 0x196, 0x19b, 0x1a1, + 0x1a9, 0x1af, 0x1b4, 0x1ba, 0x1be, 0x1c0, 0x1c4, 0x1ca, 0x1d2, 0x1dd}; + +const unsigned char icon1[] = {255, 255, 255, 128, 0, 1, 128, 0, 1, + 128, 0, 1, 128, 0, 1, 128, 0, 1, + 128, 0, 1, 128, 0, 1, 128, 0, 1, + 128, 0, 1, 128, 0, 1, 128, 0, 1, + 128, 0, 1, 128, 0, 1, 128, 0, 1, + 128, 0, 1, 128, 0, 1, 128, 0, 1, + 128, 0, 1, 128, 0, 1, 255, 255, 255}; + +char *ProgName; /* for AbEnd, later remove and use common/cmdline.h */ + +char *outputCName = NULL, *outputSName = NULL; +FILE *outputCFile, *outputSFile; +int CFnum = 0, SFnum = 0; +int apple = 0; +char outputCMode[2] = "w"; +char outputSMode[2] = "w"; + + +void printUsage(void) { + + printf("Usage: %s [options] file\n" + "Options:\n" + "\t-h, -?\t\tthis help\n" + "\t-o name\t\tname C output file\n" + "\t-s name\t\tname asm output file\n" + "\t-t sys\t\tset target system\n", + ProgName); +} + + +void printCHeader(void) { + + fprintf(outputCFile, + "//\n" + "//\tThis file was generated by the GEOS Resource Compiler\n" + "//\n" + "//\tDO NOT EDIT! Any changes will be lost!\n" + "//\n" + "//\tEdit proper resource file instead.\n" + "//\n\n"); +} + + +void printSHeader(void) { + + fprintf(outputSFile, + ";\n" + ";\tThis file was generated by the GEOS Resource Compiler\n" + ";\n" + ";\tDO NOT EDIT! Any changes will be lost!\n" + ";\n" + ";\tEdit proper resource file instead.\n" + ";\n\n"); +} + + +void openCFile(void) { + + if ((outputCFile = fopen(outputCName,outputCMode)) == 0) { + AbEnd("can't open file %s for writing: %s\n", outputCName, strerror(errno)); + } + + if (CFnum == 0) { + outputCMode[0] = 'a'; + printCHeader(); + CFnum++; + } +} + + +void openSFile(void) { + + if ((outputSFile = fopen(outputSName, outputSMode)) == 0) { + AbEnd("can't open file %s for writing: %s\n", outputSName, strerror(errno)); + } + + if (SFnum == 0) { + outputSMode[0] = 'a'; + printSHeader(); + SFnum++; + } +} + + +int findToken(const char **tokenTbl, const char *token) { + + /* takes as input table of tokens and token, returns position in table or -1 if not found */ + int a = 0; + + while (strlen(tokenTbl[a]) != 0) { + if (strcmp(tokenTbl[a], token) == 0) break; + a++; + } + + if (strlen(tokenTbl[a]) == 0) a = -1; + return a; +} + + +char *nextPhrase() { + return strtok(NULL, "\""); +} + + +char *nextWord() { + return strtok(NULL, " "); +} + + +void setLen(char *name, unsigned len) { + if (strlen(name) > len) + name[len] = '\0'; +} + + +void fillOut(char *name, int len, char *filler) { + + int a; + + setLen(name, len); + fprintf(outputSFile, "\t.byte \"%s\"\n", name); + + a = strlen(name); + if (a < len) { + fprintf(outputSFile, "\t.res (%i - %i), %s\n", len, a, filler); + } +} + + +char *bintos(unsigned char a, char out[7]) { + + int i=0; + + for (; i < 8; i++) { + out[7 - i] = ((a & 1) == 0) ? '0' : '1'; + a = a >> 1; + } + out[i] = '\0'; + + return out; +} + + +int getNameSize(const char *word) { + + /* count length of a word using BSW 9 font table */ + int a = 0, i = 0; + + while (word[i] != '\0') { + a += (BSWTab[word[i] - 31] - BSWTab[word[i] - 32]); + i++; + } + + return a; +} + + +void DoMenu(void) { + + int a, size, tmpsize, item = 0; + char *token; + char namebuff[255] = ""; + struct menu myMenu; + struct menuitem *curItem, *newItem; + + openCFile(); + + myMenu.name = nextWord(); + myMenu.left = atoi(nextWord()); + myMenu.top = atoi(nextWord()); + myMenu.type = nextWord(); + + if (strcmp(nextWord(), "{") != 0) { + AbEnd("menu '%s' description has no opening bracket!\n", myMenu.name); + } + curItem = xmalloc(sizeof(struct menuitem)); + myMenu.item = curItem; + do { + token = nextWord(); + if (strcmp(token, "}") == 0) break; + if (token[strlen(token) - 1] != '"') { + strcpy(namebuff, token); + do { + token = nextWord(); + strcat(namebuff, " "); + strcat(namebuff, token); + } while (token[strlen(token) - 1] != '"'); + token = xmalloc(strlen(namebuff)); + strcpy(token, namebuff); + } + curItem->name = token; + curItem->type = nextWord(); + curItem->target = nextWord(); + newItem = xmalloc(sizeof(struct menuitem)); + curItem->next = newItem; + curItem = newItem; + item++; + } while (strcmp(token, "}") != 0); + if (item == 0) AbEnd("menu '%s' has 0 items!\n", myMenu.name); + if (item > 31) AbEnd("menu '%s' has too many items!\n", myMenu.name); + + curItem->next = NULL; + + /* count menu sizes */ + size = 0; + curItem = myMenu.item; + if (strstr(myMenu.type, "HORIZONTAL") != NULL) { + /* menu is HORIZONTAL, ysize=15, sum xsize of all items +~8?*/ + myMenu.bot = myMenu.top + 15; + for (a = 0; a != item; a++) { + size += getNameSize(curItem->name); + curItem = curItem->next; + } + } else { + /* menu is VERTICAL, ysize=item*15, count largest xsize of all items +~8? */ + myMenu.bot = myMenu.top + (14 * item); + for (a = 0; a != item; a++) { + tmpsize = getNameSize(curItem->name); + size = (size > tmpsize) ? size : tmpsize; + curItem = curItem->next; + } + } + myMenu.right = myMenu.left + size - 1; + + curItem = myMenu.item; + for (a = 0; a != item; a++) { + /* print prototype only if MENU_ACTION or DYN_SUB_MENU are present in type */ + if ((strstr(curItem->type, "MENU_ACTION") != NULL) || (strstr(curItem->type, "DYN_SUB_MENU") != NULL)) { + fprintf(outputCFile, + "void %s (void);\n", + curItem->target); + } + curItem=curItem->next; + } + + fprintf(outputCFile, + "\n" + "const void %s = {\n" + "\t(char)%i, (char)%i,\n" + "\t(int)%i, (int)%i,\n" + "\t(char)(%i | %s),\n", + myMenu.name, myMenu.top, myMenu.bot, myMenu.left, myMenu.right, item, myMenu.type); + + curItem = myMenu.item; + for (a = 0; a != item; a++) { + fprintf(outputCFile, + "\t%s, (char)%s, (int)", + curItem->name, curItem->type); + if ((strstr(curItem->type, "SUB_MENU") != NULL) && (strstr(curItem->type, "DYN_SUB_MENU") == NULL)) + fprintf(outputCFile, + "&"); + fprintf(outputCFile, + "%s,\n", + curItem->target); + curItem = curItem->next; + } + + fprintf(outputCFile, + "};\n\n"); + + if (fclose(outputCFile) != 0) + AbEnd("error closing %s: %s\n", outputCName, strerror(errno)); +} + + +void DoHeader(void) { + + time_t t; + struct tm *my_tm; + + struct appheader myHead; + char *token; + char i1[9], i2[9], i3[9]; + int a, b; + + openSFile(); + + token = nextWord(); + + a = findToken(hdrFTypes, token); + + if (apple == 1) { + switch (a) { + case 0: + myHead.geostype = 0x82; + break; + default: + AbEnd("filetype '%s' is not supported yet\n", token); + } + } else { + switch (a) { + case 0: + myHead.geostype = 6; + break; + case 1: + myHead.geostype = 14; + break; + default: + AbEnd("filetype '%s' is not supported yet\n", token); + } + } + + myHead.dosname = nextPhrase(); + nextPhrase(); + myHead.classname = nextPhrase(); + nextPhrase(); + myHead.version = nextPhrase(); + + /* put default values into myHead here */ + myHead.author = "cc65"; + myHead.info = "Program compiled with cc65 and GEOSLib."; + myHead.dostype = 128; + if (apple == 0) myHead.dostype += 3; + myHead.structure = 0; + myHead.mode = 0; + myHead.icon = NULL; + + t = time(NULL); + my_tm = localtime(&t); + + myHead.year = my_tm->tm_year; + myHead.month = my_tm->tm_mon+1; + myHead.day = my_tm->tm_mday; + myHead.hour = my_tm->tm_hour; + myHead.min = my_tm->tm_min; + + if (strcmp(nextWord(), "{") != 0) { + AbEnd("header '%s' has no opening bracket!\n", myHead.dosname); + } + + do { + token = nextWord(); + if (strcmp(token, "}") == 0) break; + switch (a = findToken(hdrFields, token)) { + case -1: + AbEnd("unknown field '%s' in header '%s'\n", token, myHead.dosname); + break; + case 0: /* author */ + myHead.author = nextPhrase(); + break; + case 1: /* info */ + myHead.info = nextPhrase(); + break; + case 2: /* date */ + myHead.year = atoi(nextWord()); + myHead.month = atoi(nextWord()); + myHead.day = atoi(nextWord()); + myHead.hour = atoi(nextWord()); + myHead.min = atoi(nextWord()); + break; + case 3: /* dostype */ + switch (b = findToken(hdrDOSTp, nextWord())) { + case -1: + AbEnd("unknown dostype in header '%s'\n", myHead.dosname); + break; + default: + if (apple == 0) myHead.dostype = b / 2 + 128 + 1; + break; + } + break; + case 4: /* mode */ + switch (b = findToken(hdrModes, nextWord())) { + case -1: + AbEnd("unknown mode in header '%s'\n", myHead.dosname); + case 0: + if (apple == 0) myHead.mode = 0x40; + break; + case 1: + if (apple == 0) myHead.mode = 0x00; + break; + case 2: + if (apple == 0) myHead.mode = 0xc0; + break; + case 3: + if (apple == 0) myHead.mode = 0x80; + break; + } + break; + case 5: /* structure */ + switch (b = findToken(hdrStructTp, nextWord())) { + case -1: + AbEnd("unknown structure type in header '%s'\n", myHead.dosname); + case 0: + case 1: + myHead.structure = 0; + break; + case 2: + case 3: + myHead.structure = 1; + break; + } + break; + case 6: /* icon */ + myHead.icon = nextPhrase(); + break; + } + + } while (strcmp(token, "}") != 0); + + /* OK, all information is gathered, do flushout */ + + fprintf(outputSFile, + "\n" + "\t\t.segment \"DIRENTRY\"\n\n"); + + if (apple == 1) { + + fprintf(outputSFile, + "\t.byte %i << 4 | %u\n", + myHead.structure + 2, (unsigned) strlen(myHead.dosname)); + + fillOut(myHead.dosname, 15, "0"); + + fprintf(outputSFile, + "\t.byte $%02x\n" + "\t.word 0\n" + "\t.word 0\n" + "\t.byte 0, 0, 0\n" + "\t.word %i << 9 | %i << 5 | %i, %i << 8 | %i\n" + "\t.byte 0\n" + "\t.byte 0\n" + "\t.byte 0\n" + "\t.word 0\n" + "\t.word %i << 9 | %i << 5 | %i, %i << 8 | %i\n" + "\t.word 0\n", + myHead.geostype, + myHead.year % 100, myHead.month, myHead.day, myHead.hour, myHead.min, + myHead.year % 100, myHead.month, myHead.day, myHead.hour, myHead.min); + + } else { + + fprintf(outputSFile, + "\t.byte %i\n" + "\t.word 0\n", + myHead.dostype); + + fillOut(myHead.dosname, 16, "$a0"); + + fprintf(outputSFile, + "\t.word 0\n" + "\t.byte %i\n" + "\t.byte %i\n" + "\t.byte %i, %i, %i, %i, %i\n\n" + "\t.word 0\n" + "\t.byte \"PRG formatted GEOS file V1.0\"\n\n", + myHead.structure, myHead.geostype, + myHead.year, myHead.month, myHead.day, myHead.hour, myHead.min); + } + + fprintf(outputSFile, + "\n" + "\t\t.segment \"FILEINFO\"\n\n" + "\t.import __VLIR0_START__, __STARTUP_RUN__\n\n" + "\t.byte 3, 21, 63 | $80\n"); + + if (myHead.icon != NULL) { + fprintf(outputSFile, + "\t.incbin \"%s\", 0, 63\n", + myHead.icon); + } else { + for (a = 0; a != 63; a = a + 3) { + fprintf(outputSFile, + "\t.byte %%%s, %%%s, %%%s\n", + bintos(icon1[a], i1), bintos(icon1[a+1], i2), bintos(icon1[a+2], i3)); + } + } + + fprintf(outputSFile, + "\t.byte %i, %i, %i\n" + "\t.word __VLIR0_START__, __VLIR0_START__ - 1, __STARTUP_RUN__\n\n", + myHead.dostype, myHead.geostype, myHead.structure); + + fillOut(myHead.classname, 12, "$20"); + + fillOut(myHead.version, 4, "0"); + + fprintf(outputSFile, + "\t.byte 0, 0, 0\n" + "\t.byte %i\n\n", + myHead.mode); + + setLen(myHead.author, 62); + fprintf(outputSFile, + "\t.byte \"%s\"\n" + "\t.byte 0\n" + "\t.res (63 - %i)\n\n", + myHead.author, (int)(strlen(myHead.author) + 1)); + + setLen(myHead.info, 95); + fprintf(outputSFile, + "\t.byte \"%s\"\n" + "\t.byte 0\n\n", + myHead.info); + + if (fclose (outputSFile) != 0) + AbEnd("error closing %s: %s\n", outputSName, strerror(errno)); +} + + +void DoVLIR(void) { + + char *token; + int record, lastrecord; + int vlirsize, vlirtable[127]; + + openSFile(); + + vlirsize = strtol(nextWord(), NULL, 0); + + if (strcmp(nextWord(), "{") != 0) { + AbEnd ("VLIR description has no opening bracket!\n"); + } + + lastrecord = -1; + memset(vlirtable, 0, sizeof(vlirtable)); + + do { + token = nextWord(); + if (strcmp(token, "}") == 0) break; + + record = atoi(token); + if (record < 0 || record > 126) { + AbEnd("VLIR record %i is out of range 0-126.\n", record); + } + if (vlirtable[record] == 1) { + AbEnd("VLIR record %i is defined twice.\n", record); + } + + vlirtable[record] = 1; + if (record > lastrecord) lastrecord = record; + } while (strcmp(token, "}") != 0); + + if (lastrecord == -1) { + AbEnd("There must be at least one VLIR record.\n"); + } + + /* always include record 0 */ + vlirtable[0] = 1; + + /* OK, all information is gathered, do flushout */ + + fprintf(outputSFile, + "\n" + "\t\t.segment \"RECORDS\"\n\n" + "\t.export __OVERLAYSIZE__ : absolute = $%04x\n\n", + vlirsize); + + for (record = 0; record <= lastrecord; record++) { + if (vlirtable[record] == 1) { + fprintf(outputSFile, + "\t.import __VLIR%i_START__, __VLIR%i_LAST__\n", + record, record); + } + } + fprintf(outputSFile, + "\n"); + + for (record = 0; record <= lastrecord; record++) { + if (vlirtable[record] == 1) { + fprintf(outputSFile, + "\t.byte .lobyte ((__VLIR%i_LAST__ - __VLIR%i_START__ - 1) / 254) + 1\n" + "\t.byte .lobyte ((__VLIR%i_LAST__ - __VLIR%i_START__ - 1) .MOD 254) + 2\n", + record, record, record, record); + } else { + fprintf(outputSFile, + "\t.byte $00\n" + "\t.byte $FF\n"); + } + } + fprintf(outputSFile, + "\n"); + + if (fclose(outputSFile) != 0) + AbEnd("error closing %s: %s\n", outputSName, strerror(errno)); + + openCFile(); + + fprintf(outputCFile, + "extern void _OVERLAYADDR__;\n" + "extern void _OVERLAYSIZE__;\n\n" + "#define OVERLAY_ADDR (char*) &_OVERLAYADDR__\n" + "#define OVERLAY_SIZE (unsigned)&_OVERLAYSIZE__\n\n"); + + if (fclose(outputCFile) != 0) + AbEnd("error closing %s: %s\n", outputCName, strerror(errno)); +} + + +char *filterInput(FILE *F, char *tbl) { + + /* loads file into buffer filtering it out */ + int a, prevchar = -1, i = 0, bracket = 0, quote = 1; + + while (1) { + a = getc(F); + if ((a == '\n') || (a == '\015')) a = ' '; + if (a == ',' && quote) a = ' '; + if (a == '\042') quote =! quote; + if (quote) { + if ((a == '{') || (a == '(')) bracket++; + if ((a == '}') || (a == ')')) bracket--; + } + if (a == EOF) { + tbl[i] = '\0'; + xrealloc(tbl, i + 1); + break; + } + if (IsSpace(a)) { + if ((prevchar != ' ') && (prevchar != -1)) { + tbl[i++] = ' '; + prevchar = ' '; + } + } else { + if (a == ';' && quote) { + do { + a = getc(F); + } while (a != '\n'); + fseek(F, -1, SEEK_CUR); + } else { + tbl[i++] = a; + prevchar = a; + } + } + } + + if (bracket != 0) AbEnd("there are unclosed brackets!\n"); + + return tbl; +} + + +void processFile(const char *filename) { + + FILE *F; + + char *str; + char *token; + + int head = 0; /* number of processed HEADER sections */ + int vlir = 0; /* number of processed VLIR sections */ + + if ((F = fopen(filename, "r")) == 0) { + AbEnd("can't open file %s for reading: %s\n", filename, strerror(errno)); + } + + str = filterInput(F, xmalloc(BLOODY_BIG_BUFFER)); + + token = strtok(str, " "); + + do { + if (str != NULL) { + switch (findToken(mainToken, token)) { + case 0: + DoMenu(); + break; + case 1: + if (++head != 1) { + AbEnd("more than one HEADER section, aborting.\n"); + } else { + DoHeader(); + } + break; + case 2: break; /* icon not implemented yet */ + case 3: break; /* dialog not implemented yet */ + case 4: + if (++vlir != 1) { + AbEnd("more than one VLIR section, aborting.\n"); + } else { + DoVLIR(); + } + break; + default: + AbEnd("unknown section %s.\n",token); + break; + } + } + token = nextWord(); + } while (token != NULL); +} + + +int main(int argc, char *argv[]) { + + int ffile = 0, i = 1; + + ProgName = argv[0]; + + while (i < argc) { + const char *arg = argv[i]; + + if (arg[0] == '-') { + switch (arg[1]) { + case 'o': + outputCName = argv[++i]; + break; + case 's': + outputSName = argv[++i]; + break; + case 't': + switch (FindTarget(argv[++i])) { + case TGT_GEOS_CBM: + apple = 0; + break; + case TGT_GEOS_APPLE: + apple = 1; + break; + default: + AbEnd("unknown target system type %s\n", argv[i]); + } + break; + case 'h': + case '?': + printUsage(); + exit(EXIT_SUCCESS); + break; + default: + AbEnd("unknown option %s\n", arg); + } + } else { + ffile++; + + if (outputCName == NULL) outputCName = MakeFilename(arg, ".h"); + if (outputSName == NULL) outputSName = MakeFilename(arg, ".s"); + + processFile(arg); + } + + i++; + } + + if (ffile == 0) AbEnd("no input file\n"); + + return EXIT_SUCCESS; +} diff --git a/src/grc65/make/gcc.mak b/src/grc65/make/gcc.mak index 2dd9f64ba..f4b23cca1 100644 --- a/src/grc65/make/gcc.mak +++ b/src/grc65/make/gcc.mak @@ -20,7 +20,7 @@ EBIND = emxbind # ----------------------------------------------------------------------------- # List of all object files -OBJS = grc65.o +OBJS = main.o LIBS = $(COMMON)/common.a @@ -54,5 +54,5 @@ zap: clean depend dep: $(OBJS:.o=.c) @echo "Creating dependency information" $(CC) $(CFLAGS) -MM $^ > .depend - + diff --git a/src/grc65/make/watcom.mak b/src/grc65/make/watcom.mak index 84a9f2faf..7f4b83daf 100644 --- a/src/grc65/make/watcom.mak +++ b/src/grc65/make/watcom.mak @@ -60,7 +60,7 @@ endif # ------------------------------------------------------------------------------ # All OBJ files -OBJS = grc65.obj +OBJS = main.obj LIBS = ../common/common.lib