aboutsummaryrefslogtreecommitdiff
path: root/bas2aplus.c
diff options
context:
space:
mode:
Diffstat (limited to 'bas2aplus.c')
-rw-r--r--bas2aplus.c230
1 files changed, 230 insertions, 0 deletions
diff --git a/bas2aplus.c b/bas2aplus.c
new file mode 100644
index 0000000..d7768cd
--- /dev/null
+++ b/bas2aplus.c
@@ -0,0 +1,230 @@
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <time.h>
+
+#include "bas.h"
+
+#undef DUMP_TABLES
+
+#ifdef DUMP_TABLES
+#include "tokens.c"
+#include "aplus_tokens.c"
+#include "bxl_tokens.c"
+#endif
+
+/* 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 GO<sp>TO 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 <silent-let> 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[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0x0e, /* convert BXL hex const to decimal */
+ 0, 0, 0, 0,
+
+ /* 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.");
+}
+
+CALLBACK(conv_cmd) {
+ if(tok > LAST_BXL_CMD) {
+ fprintf(stderr, "%s: Invalid cmd token %02x at line %d, pos %04x, skipping.\n",
+ self, tok, lineno, pos);
+ return;
+ }
+
+ program[pos] = cmd_table[tok];
+ if(verbose)
+ fprintf(stderr, "cmd tok %02x converted to %02x at line %d, pos %04x\n", tok, program[pos], lineno, pos);
+}
+
+CALLBACK(conv_op) {
+ unsigned char newtok;
+
+ if(tok < 0x12 && tok != OP_HEXCONST) return;
+
+ if(tok > LAST_BXL_OP) {
+ fprintf(stderr, "%s: Invalid op token %02x at line %d, pos %04x, skipping.\n",
+ self, tok, lineno, pos);
+ return;
+ }
+
+ newtok = op_table[tok];
+ if(newtok == 0xff) {
+ fprintf(stderr, "%s: BXL op token %02x at line %d, pos %04x, has no A+ equivalent, skipping.\n",
+ self, tok, lineno, pos);
+ return;
+ }
+
+ program[pos] = newtok;
+ if(verbose)
+ fprintf(stderr, "op tok %02x converted to %02x at line %d, pos %04x\n", 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();
+
+ return 0;
+}