#include #include #include #include #include #include #include "bas.h" #undef DUMP_TABLES #include "tokens.c" #include "aplus_tokens.c" #include "bxl_tokens.c" #include "bxe_tokens.c" int errs = 0; /* there are a few more BXL commands past 0x55, but they have no A+ equivalents. */ #define LAST_BXL_CMD 0x55 #define LAST_BXL_OP 0x65 /* cmd_table[basic_token] or op_table[basic_token] gives the equivalent A+ token. note that there's no "GO TO" or "COM" in A+, we translate those as GOTO and DIM. */ unsigned char cmd_table[] = { /* Atari BASIC: */ /* REM DATA INPUT COLOR LIST ENTER LET IF:*/ 0x00, 0x01, 0x02, 0x3f, 0x03, 0x04, 0x05, 0x06, /* 0x00 - 0x07 */ /* FOR NEXT GOTO GOTO GOSUB TRAP BYE CONT: */ 0x07, 0x08, 0x09, 0x09, 0x0b, 0x0c, 0x0d, 0x0e, /* 0x08 - 0x0f */ /* COM CLOSE CLR DEG DIM END NEW OPEN: */ 0x12, 0x0f, 0x10, 0x11, 0x12, 0x19, 0x1a, 0x1b, /* 0x10 - 0x17 */ /* LOAD SAVE STATUS NOTE POINT XIO ON POKE: */ 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, /* 0x18 - 0x1f */ /* PRINT RAD READ RESTORE RETURN RUN STOP POP: */ 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, /* 0x20 - 0x27 */ /* ? GET PUT GRAPHICS PLOT POSITION DOS DRAWTO: */ 0x2d, 0x2e, 0x2f, 0x40, 0x41, 0x42, 0x38, 0x43, /* 0x28 - 0x2f */ /* SETCOLOR LOCATE SOUND LPRINT CSAVE CLOAD ERROR-: */ 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x52, 0x53, /* 0x30 - 0x37 */ /* BASIC XL: */ /* WHILE ENDWHILE TRACEOFF TRACE ELSE ENDIF DPOKE LOMEM: */ 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x24, 0x30, /* 0x38-0x3f */ /* DEL RPUT RGET BPUT BGET TAB CP ERASE: */ 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x39, /* 0x40-0x47 */ /* PROTECT UNPROTECT DIR RENAME MOVE MISSILE PMCLR PMCOLOR: */ 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x4a, 0x4b, 0x4c, /* 0x48-0x4f */ /* PMGRAPHICS PMMOVE PMWIDTH SET LVAR RENUM: */ 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x0a, /* 0x50-0x55 */ }; /* 0xff means "untranslatable". these are: BUMP( FIND( HEX$ RANDOM( ...though BUMP( and FIND( do have A+ equivalents (they just need a left paren inserted after) */ unsigned char op_table[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* not used: 0x00-0x07 */ 0xff, 0xff, 0xff, 0xff, 0xff, /* not used: 0x08-0x0c */ 0x0e, /* convert BXL hex const to decimal */ 0x0e, 0x0f, /* numeric and string consts are the same */ 0xff, 0xff, /* these 2 not used: 0x10-0x11 */ /* these are the same, 0x12-0x1b */ 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, /* 0x1c-0x2a off by one due to USING inserted at 0x1c */ 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, /* 0x2b-0x43 off by 3 due to ! and & */ 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, /* 0x44-0x50 */ 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, /* 0x51-0x54 (last BASIC) */ 0x58, 0x59, 0x5a, 0x5b, /* BXL stuff, 0x55-0x5f */ 0x1c, 0xff /* % */, 0x2c, 0x2d, 0xff, /* string array semicolon */ 0xff, /* BUMP( (TODO: A+ token 0x47 plus a paren) */ 0xff, /* FIND( (TODO: A+ token 0x48 plus a paren) */ 0xff, /* HEX$ */ 0xff, /* RANDOM( */ 0x49, /* DPEEK */ 0x57, /* SYS */ 0x5c, /* VSTICK */ 0x5d, /* HSTICK */ 0x5e, /* PMADR */ 0x5f, /* ERR */ 0x60, /* TAB */ 0x61, /* PEN */ }; #ifdef DUMP_TABLES void dump_tables(void) { int i; for(i = 0; i <= LAST_BXL_CMD; i++) { const char *b, *ap = aplus_cmds[cmd_table[i]]; if(i <= last_command) b = commands[i]; else b = bxl_cmds[i - 0x38]; printf("%02x: %s %s%s\n", i, b, ap, (strcmp(b, ap) == 0) ? " SAME" : ""); } printf("\n\n"); for(i = 0x12; i <= LAST_BXL_OP; i++) { int j = op_table[i];; const char *b, *ap; if(j == 0xff) ap = "(not in A+)"; else ap = aplus_ops[j]; if(i <= last_operator) b = operators[i]; else b = bxl_ops[i - 0x55]; printf("%02x: %s %s%s\n", i, b, ap, (strcmp(b, ap) == 0) ? " SAME" : ""); } } #endif void print_help(void) { printf("%s [input-file] [output-file]\n", self); } void parse_args(int argc, char **argv) { int opt; while( (opt = getopt(argc, argv, "v")) != -1) { switch(opt) { case 'v': verbose = 1; break; case 'h': print_help(); exit(0); default: print_help(); exit(1); } } if(optind == argc) die("No input file given."); else open_input(argv[optind]); if(++optind == argc) die("No output file given."); else output_filename = argv[optind]; if(argv[++optind]) die("Only one input and one output file allowed."); } const char *get_tok_name(unsigned char tok, int is_cmd) { if(is_cmd) { if(tok <= last_command) { return commands[tok]; } else if(tok == 0x5a) { return "BASIC XL LOCAL/EXIT/PROCEDURE/CALL/SORTUP/SORTDOWN"; } else if(tok == 0x59 || (tok > 0x5a && tok < 0x65)) { return bxe_cmds[tok - 0x57]; } else if(tok > last_command && tok <= 0x58) { return bxl_cmds[tok - 0x38]; } else { return "(maybe Turbo BASIC?)"; } } else { if(tok < 0x12) return ""; if(tok <= last_operator) { return operators[tok]; } else if(tok <= 0x68) { return bxl_ops[tok - 0x55]; } else { return "(maybe Turbo BASIC?)"; } } } void unsupported_msg(unsigned char tok, int lineno, int is_cmd) { fprintf(stderr, "%s: Invalid %s \"%s\" ($%02x) at line %d, not converted.\n", self, is_cmd ? "command" : "operator", get_tok_name(tok, is_cmd), tok, lineno); errs++; } int is_supported_cmd(unsigned char tok, int lineno) { if(tok > LAST_BXL_CMD) { unsupported_msg(tok, lineno, 1); return 0; } return 1; } int is_supported_op(unsigned char tok, int lineno) { if(tok > LAST_BXL_OP || op_table[tok] == 0xff) { unsupported_msg(tok, lineno, 0); return 0; } return 1; } CALLBACK(conv_cmd) { if(!is_supported_cmd(tok, lineno)) return; program[pos] = cmd_table[tok]; if(verbose && tok != program[pos]) fprintf(stderr, "command \"%s\" ($%02x) converted to $%02x at line %d, pos $%04x\n", get_tok_name(tok, 1), tok, program[pos], lineno, pos); } CALLBACK(conv_op) { if(!is_supported_op(tok, lineno)) return; program[pos] = op_table[tok]; if(verbose && tok != program[pos]) fprintf(stderr, "operator \"%s\" ($%02x) converted to $%02x at line %d, pos $%04x\n", get_tok_name(tok, 0), tok, program[pos], lineno, pos); } int main(int argc, char **argv) { #ifdef DUMP_TABLES dump_tables(); exit(0); #endif set_self(*argv); parse_general_args(argc, argv, print_help); parse_args(argc, argv); readfile(); parse_header(); on_cmd_token = conv_cmd; on_exp_token = conv_op; allow_hex_const = 1; walk_all_code(); open_output(output_filename); writefile(); if(errs) { fprintf(stderr, "%s: program has %d invalid tokens; BASIC/A+ won't RUN it.\n", self, errs); return 1; } return 0; }