/* list64.c 27 Aug 88 - CS =========================================================================== Converts a tokenized Commodore 64 or 128 BASIC program to standard ASCII. Some steps are taken to aid in converting the file to Microsoft QuickBASIC, but alot of manual editing will invariably be nessessary to complete the conversion. Special Commodore cursor control and color control characters are shown as "[Text]" so it should be fairly simple to deal with them using your editor's search and replace function. =========================================================================== */ #include #include #ifdef MPU8086 /* If Manx */ #define ROPEN "r" #else /* If the rest of the civilized world */ #define ROPEN "rb" #endif /* -------------------- BASIC 2.0 keywords -------------------- */ char * KeyWord[] = { " end ", /* Token 0x80 */ " for ", /* 0x81 */ " next ", /* ... */ " data ", " input #", " input ", " dim ", " read ", " let ", " goto ", " run ", " if ", " restore ", " gosub ", " return ", " rem ", " stop ", " on ", " wait ", " load ", " save ", " verify ", " def ", " poke ", " print #", " print ", " cont ", " list ", " clr", " cmd ", " sys ", " open ", " close ", " get ", " new ", " tab(", " to ", " fn", " spc(", " then ", " not ", " step ", "+", "-", "*", "/", "^", " and ", " or ", ">", "=", "<", "sgn", "int", "abs", "usr", "fre", "pos", "sqr", "rnd", "log", "exp", "cos", "sin", "tan", "atn", "peek", "len", "str$", "val", "asc", "chr$", "left$", "right$", "mid$", " go ", /* ---------------- C128 additions ---------------- */ " rgr ", " rclr ", " [Function Token Extender] ", /* 0xce */ " joy", " rdot", " dec", " hex$", " err$", " instr", " else ", " resume ", " trap ", " tron ", " troff ", " sound ", " vol ", " auto ", " pudef ", " graphic ", " paint ", " char ", " box ", " circle ", " gshape ", " sshape ", " draw ", " locate ", " color ", " scnclr ", " scale ", " help ", " do ", " loop ", " exit ", " directory ", " dsave ", " dload ", " header ", " scratch ", " collect ", " copy ", " rename ", " backup ", " delete ", " renumber ", " key ", " monitor ", " using ", " until ", " while ", " [Satement Token Extender] ", /* 0xfe */ 0 }; /* ------------------------- C128 extended functions ------------------------- */ char *Function[] = { " pot", " bump", " pen", " rsppos", " rsprite", " rspcolor", " xor", " rwindow", " pointer", " [Undefined Token] ", 0 }; char *Statement[] = { " bank ", " filter ", " play ", " tempo ", " movspr ", " sprite ", " sprcolor ", " rreg ", " envelope ", " sleep ", " catalog ", " dopen ", " append ", " dclose ", " bsave ", " bload ", " record ", " concat ", " dverify ", " dclear ", " sprsav ", " collision ", " begin ", " bend ", " window ", " boot ", " width ", " sprdef ", " quit ", " stash ", " [Undefined Token] ", " fetch ", " [Undefined Token] ", " swap ", " off ", " fast ", " slow ", " [Undefined Token] ", 0 }; unsigned getw(FILE * fp) { union { unsigned u; char c[2]; } x; x.c[0] = fgetc(fp); x.c[1] = fgetc(fp); return x.u; } main(argc,argv) unsigned argc; char *argv[]; { FILE * fp; int c, i; char * a; char filename[65]; int Status = 0; if (argc != 2) { if ( (a=strrchr(argv[0],'\\')) == 0) a=argv[0]; else a++; printf("\nUsage: %s [d:path\\]filename[.bas] [>output.file]\n",a); printf("\nPurpose: Convert tokenized Commodore 64 or 128 BASIC to standard ASCII.\n"); printf(" Use redirection to create an output file.\n"); exit(1); } strcpy(filename,argv[1]); if ( access(filename,0) ) { if ( strchr(argv[1],'.') == 0 ) strcat(filename,".bas"); if ( access(filename,0) ) { printf("\nCan't open source file\n"); exit(1); } } if ((fp = fopen(filename, ROPEN)) == 0){ printf("\nCan't open \"%s\"\n",filename); exit(2); } getw(fp); /* Ignore load address */ while(Status != EOF) { /* While still more data */ Status=DoLine(fp); /* Display one line */ } fclose(fp); } /* Convert CBM ASCII to Standard ASCII */ char *p2a(c) int c; { static unsigned cc; static unsigned oldcc; static char s[2]; oldcc = cc; cc = c; switch (cc) { case 5: return "[White]"; /* White */ case 7: return "[Bell]"; case 10: { /* LF */ if (oldcc!=13) return "\012"; else return "\0"; } case 13: return "\n"; /* CR */ case 14: return "[Text Mode]"; /* Select character set */ case 17: return "[Down]"; /* Cursor Down */ case 18: return "[Reverse]"; /* Reverse On */ case 19: return "[Home]"; /* Cursor Home */ case 20: return "[Delete]"; case 28: return "[Red]"; /* Red */ case 29: return "[Right]"; /* Cursor Right */ case 30: return "[Green]"; /* Green */ case 31: return "[Blue]"; /* Blue */ case 129: return "[Orange]"; /* Orange */ case 133: return "[F1]"; /* Function keys*/ case 134: return "[F3]"; case 135: return "[F5]"; case 136: return "[F7]"; case 137: return "[F2]"; case 138: return "[F4]"; case 139: return "[F6]"; case 140: return "[F8]"; case 141: return "\n"; /* Shifted CR */ case 142: return "[Graphic Mode]"; /* Select character set */ case 145: return "[Up]"; /* Cursor up */ case 144: return "[Black]"; /* Black */ case 146: return "[Reverse Off]"; /* Reverse Off */ case 147: return "[Clear]"; /* Clear Screen */ case 148: return "[Insert]"; case 149: return "[Brown]"; /* Brown */ case 150: return "[Light Red]"; /* Light Red */ case 151: return "[Dark Grey]"; /* Dark Grey */ case 152: return "[Medium Grey]"; /* Medium Grey */ case 153: return "[Light Green]"; /* Light Green */ case 154: return "[Light Blue]"; /* Light Blue */ case 155: return "[Light Grey]"; /* Light grey */ case 156: return "[Purple]"; /* Purple */ case 157: return "[Left]"; /* Cursor Left */ case 158: return "[Yellow]"; /* Yellow */ case 159: return "[Cyan]"; /* Cyan */ case 160: return " "; /* Shift+space */ case 164: return "_"; case 171: return "Ì"; case 173: return "È"; case 174: return "»"; case 175: return "~"; case 176: return "É"; case 177: return "Ê"; case 178: return "Ë"; case 179: return "¹"; case 189: return "¼"; case 192: return "Í"; case 219: return "Î"; case 221: return "º"; case 223: return "|"; default: { s[0] = cc; s[1] = 0; if (cc<65 || cc>219) return s; if (cc<91) { s[0]=cc|0x20; return s; } if (cc<193) return s; s[0]=cc&0x7f; return s; } } } /* ---------------------------------------------------------- Concatenate keywords eliminating spaces where not needed ---------------------------------------------------------- */ cat(dest,add) char *dest; char *add; { size_t last; last = strlen(dest)-1; /* Assume no null strings */ switch (dest[last]) { case ' ': { if ( (*add == ' ') || (*add == ':') ) dest[last]=0; strcat(dest,add); break; } case ':': { if (*add == ' ') strcat(dest,&add[1]); else strcat(dest,add); break; } default: strcat(dest,add); } } /* --------------------- List one BASIC line --------------------- */ int DoLine(fp) FILE *fp; { unsigned LineNumber; unsigned Link; int c, flag=0; int QuoteFlag = 0; char Line[300]; *Line = 0; if ( !(Link = getw(fp)) ) /* Exit if end of BASIC */ return EOF; LineNumber = getw(fp); sprintf(Line,"%u ",LineNumber); while ( ((c=fgetc(fp)) != 0) && (c != EOF) ) { if (strlen(Line) > 255) break; if ( (c==' ') && flag) /* Eliminate double spaces */ continue; flag = 0; if (c=='\"') { strcat(Line,"\""); QuoteFlag = !QuoteFlag; continue; } if (QuoteFlag) { /* Print literally inside quotes */ strcat(Line,p2a(c)); continue; } if ( c == 0xce ) { /* C128 extended function */ if ( (c = fgetc(fp)) == EOF) continue; if ( (c<2) || (c>10) ) c = 11; cat(Line,Function[c-2]); flag = 1; continue; } if ( c == 0xfe ) { /* C128 extended statement */ if ( (c = fgetc(fp)) == EOF) continue; if ( (c<2) || (c>38) ) c = 39; cat(Line,Statement[c-2]); flag = 1; continue; } if ( c>127 ) { /* Regular token */ cat(Line,KeyWord[c-128]); flag = 1; continue; } strcat(Line,p2a(c)); } printf("%s\n",Line); return c; }