aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorB. Watson <urchlay@slackware.uk>2024-07-21 05:19:13 -0400
committerB. Watson <urchlay@slackware.uk>2024-07-21 05:19:13 -0400
commit0a892d1ef0aca718c82603f2df1406cf76c017f6 (patch)
tree65e588c1411deaff0665149f86b816267638651b
parent416ed5c987a59cbb69b6cc2694c098c7d8d55130 (diff)
downloadbw-atari8-tools-0a892d1ef0aca718c82603f2df1406cf76c017f6.tar.gz
bas2aplus: added.
-rw-r--r--Makefile6
-rw-r--r--bas2aplus.1166
-rw-r--r--bas2aplus.c230
-rw-r--r--bas2aplus.rst99
4 files changed, 499 insertions, 2 deletions
diff --git a/Makefile b/Makefile
index 5a785a5..036929f 100644
--- a/Makefile
+++ b/Makefile
@@ -16,9 +16,9 @@ CC=gcc
CFLAGS=-Wall $(COPT) -ansi -D_GNU_SOURCE -DVERSION=\"$(VERSION)\"
# BINS and SCRIPTS go in $BINDIR, DOCS go in $DOCDIR
-BINS=a8eol atr2xfd atrsize axe blob2c blob2xex cart2xex cxrefbas dumpbas fenders protbas renumbas rom2cart unmac65 unprotbas vxrefbas xex1to2 xexamine xexcat xexsplit xfd2atr listbas a8cat a8xd whichbas
+BINS=a8eol atr2xfd atrsize axe blob2c blob2xex cart2xex cxrefbas dumpbas fenders protbas renumbas rom2cart unmac65 unprotbas vxrefbas xex1to2 xexamine xexcat xexsplit xfd2atr listbas a8cat a8xd whichbas bas2aplus
SCRIPTS=dasm2atasm diffbas a8diff
-MANS=a8eol.1 xfd2atr.1 atr2xfd.1 blob2c.1 cart2xex.1 fenders.1 xexsplit.1 xexcat.1 atrsize.1 rom2cart.1 unmac65.1 axe.1 dasm2atasm.1 blob2xex.1 xexamine.1 xex1to2.1 unprotbas.1 protbas.1 renumbas.1 dumpbas.1 vxrefbas.1 cxrefbas.1 listbas.1 a8cat.1 a8xd.1 whichbas.1 diffbas.1 a8diff.1
+MANS=a8eol.1 xfd2atr.1 atr2xfd.1 blob2c.1 cart2xex.1 fenders.1 xexsplit.1 xexcat.1 atrsize.1 rom2cart.1 unmac65.1 axe.1 dasm2atasm.1 blob2xex.1 xexamine.1 xex1to2.1 unprotbas.1 protbas.1 renumbas.1 dumpbas.1 vxrefbas.1 cxrefbas.1 listbas.1 a8cat.1 a8xd.1 whichbas.1 diffbas.1 a8diff.1 bas2aplus.1
MAN5S=xex.5
MAN7S=atascii.7
DOCS=README.txt equates.inc *.dasm LICENSE ksiders/atr.txt
@@ -63,6 +63,8 @@ vxrefbas: bas.o
cxrefbas: bas.o bcdfp.o linetab.o
+bas2aplus: bas.o
+
listbas: listbas.c bas.o bcdfp.o tokens.o atables.o turbo_tokens.o aplus_tokens.o bxl_tokens.o bxe_tokens.o
$(CC) $(CFLAGS) -o listbas listbas.c bas.o bcdfp.o tokens.o atables.o turbo_tokens.o aplus_tokens.o bxl_tokens.o bxe_tokens.o -lm
diff --git a/bas2aplus.1 b/bas2aplus.1
new file mode 100644
index 0000000..d263293
--- /dev/null
+++ b/bas2aplus.1
@@ -0,0 +1,166 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "BAS2APLUS" 1 "2024-07-21" "0.2.1" "Urchlay's Atari 8-bit Tools"
+.SH NAME
+bas2aplus \- Convert Atari BASIC (and some BASIC XL) programs to BASIC/A+
+.SH SYNOPSIS
+.sp
+bas2aplus \fIinput\-file\fP \fIoutput\-file\fP
+.SH DESCRIPTION
+.sp
+\fBbas2aplus\fP reads an Atari BASIC or BASIC XL tokenized (SAVEd) program
+and converts it to BASIC/A+.
+.sp
+All Atari BASIC programs can be successfully converted. Some BASIC
+XL operators have no equivalent in BASIC/A+, so programs using these
+can\(aqt be converted (you will see messages on standard error, in that
+case).
+.SH OPTIONS
+.SS General Options
+.INDENT 0.0
+.TP
+.B \fB\-\-help\fP
+Print usage message and exit.
+.TP
+.B \fB\-\-version\fP
+Print version number and exit.
+.TP
+.B \fB\-v\fP
+Verbose operation. When displaying a number in verbose mode, it will
+be prefixed with \fI$\fP if it\(aqs in hex, or no prefix for decimal.
+.UNINDENT
+.SH BASIC
+.sp
+BASIC/A+ is basically a later version of Atari BASIC, by the same team
+that developed Atari BASIC. As such, it\(aqs source\-compatible with Atari
+BASIC, but \fInot\fP token\-compatible.
+.sp
+BASIC/A+ uses a different set of token numbers, but has all but two
+of the same tokens used by Atari BASIC. Conversion should always
+succeed, for an Atari BASIC program.
+.sp
+The two missing tokens are the \fBCOM\fP and \fBGO TO\fP commands, which
+are converted to \fBDIM\fP and \fBGOTO\fP, respectively.
+.sp
+The resulting program should \fBLOAD\fP and \fBRUN\fP in BASIC/A+ and
+function identically to the BASIC version, unless it uses memory
+that\(aqs reserved in A+. \fBUSR()\fP routines that are stored in the lower
+half of Page 6 will have to be relocated, since A+ uses this area
+itself. See the BASIC/A+ manual for full details.
+.SH BASIC XL
+.sp
+BASIC XL is basically the next version of BASIC/A+, by the
+same developers. The token lists were rearranged so that it\(aqs
+token\-compatible with Atari BASIC, and includes all the extra
+commands/functions/etc from BASIC/A+... with different token numbers.
+.sp
+BASIC XL has keywords and operators that don\(aqt exist in BASIC/A+. These
+are:
+.INDENT 0.0
+.TP
+.B \fBNUM\fP
+Rarely found in a program (usually only used in direct mode).
+.TP
+.B \fBFAST\fP
+Just doesn\(aqt exist in BASIC/A+.
+.TP
+.B \fBLOCAL\fP, \fBEXIT\fP, \fBPROCEDURE\fP, \fBCALL\fP, \fBSORTUP\fP, \fBSORTDOWN\fP
+These BASIC XL commands are provided by the disk\-based Toolkit
+extension, which doesn\(aqt exist for BASIC/A+.
+.TP
+.B \fBString Arrays\fP
+BASIC/A+ doesn\(aqt support these; if your BASIC XL program uses them,
+it won\(aqt convert correctly.
+.TP
+.B \fBBUMP\fP and \fBFIND\fP
+While BASIC/A+ does support these functions, the token\-level syntax
+is different; it would be possible to translate them, but it would
+require recalculating the line offset and statement offsets for
+every line that uses them. For now, they\(aqre not supported.
+.TP
+.B \fB%\fP
+The exclusive OR operator in BASIC XL. No such animal, in A+.
+.TP
+.B \fBHEX$\fP, \fBRANDOM\fP, \fBLEFT$\fP, \fBRIGHT$\fP, \fBMID$\fP
+These functions don\(aqt exist in BASIC/A+.
+.UNINDENT
+.sp
+Also, BASIC XL supports hex constants, with a leading \fB$\fP\&. A+
+doesn\(aqt support these, so they get converted to the equivalent decimal
+constant. This is basically a cosmetic change; \fBA=$0600\fP assigns the
+same value as \fBA=1536\fP\&.
+.SH EXIT STATUS
+.sp
+0 for success, non\-zero for failuse.
+.SH COPYRIGHT
+.sp
+WTFPL. See \fI\%http://www.wtfpl.net/txt/copying/\fP for details.
+.SH AUTHOR
+.INDENT 0.0
+.IP B. 3
+Watson <\fI\%urchlay@slackware.uk\fP>; Urchlay on irc.libera.chat \fI##atari\fP\&.
+.UNINDENT
+.SH SEE ALSO
+.sp
+\fBa8cat\fP(1),
+\fBa8eol\fP(1),
+\fBa8xd\fP(1),
+\fBatr2xfd\fP(1),
+\fBatrsize\fP(1),
+\fBaxe\fP(1),
+\fBblob2c\fP(1),
+\fBblob2xex\fP(1),
+\fBcart2xex\fP(1),
+\fBcxrefbas\fP(1),
+\fBdasm2atasm\fP(1),
+\fBdiffbas\fP(1),
+\fBdumpbas\fP(1),
+\fBf2toxex\fP(1),
+\fBfenders\fP(1),
+\fBlistbas\fP(1),
+\fBprotbas\fP(1),
+\fBrenumbas\fP(1),
+\fBrom2cart\fP(1),
+\fBunmac65\fP(1),
+\fBunprotbas\fP(1),
+\fBvxrefbas\fP(1),
+\fBwhichbas\fP(1),
+\fBxex1to2\fP(1),
+\fBxexamine\fP(1),
+\fBxexcat\fP(1),
+\fBxexsplit\fP(1),
+\fBxfd2atr\fP(1),
+\fBxex\fP(5),
+\fBatascii\fP(7).
+.sp
+Any good Atari 8\-bit book: \fIDe Re Atari\fP, \fIThe Atari BASIC Reference
+Manual\fP, the \fIOS Users\(aq Guide\fP, \fIMapping the Atari\fP, etc.
+.\" Generated by docutils manpage writer.
+.
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;
+}
diff --git a/bas2aplus.rst b/bas2aplus.rst
new file mode 100644
index 0000000..0eb44d6
--- /dev/null
+++ b/bas2aplus.rst
@@ -0,0 +1,99 @@
+=========
+bas2aplus
+=========
+
+------------------------------------------------------------
+Convert Atari BASIC (and some BASIC XL) programs to BASIC/A+
+------------------------------------------------------------
+
+.. include:: manhdr.rst
+
+SYNOPSIS
+========
+
+bas2aplus *input-file* *output-file*
+
+DESCRIPTION
+===========
+
+**bas2aplus** reads an Atari BASIC or BASIC XL tokenized (SAVEd) program
+and converts it to BASIC/A+.
+
+All Atari BASIC programs can be successfully converted. Some BASIC
+XL operators have no equivalent in BASIC/A+, so programs using these
+can't be converted (you will see messages on standard error, in that
+case).
+
+OPTIONS
+=======
+
+.. include:: genopts.rst
+
+BASIC
+=====
+
+BASIC/A+ is basically a later version of Atari BASIC, by the same team
+that developed Atari BASIC. As such, it's source-compatible with Atari
+BASIC, but *not* token-compatible.
+
+BASIC/A+ uses a different set of token numbers, but has all but two
+of the same tokens used by Atari BASIC. Conversion should always
+succeed, for an Atari BASIC program.
+
+The two missing tokens are the **COM** and **GO TO** commands, which
+are converted to **DIM** and **GOTO**, respectively.
+
+The resulting program should **LOAD** and **RUN** in BASIC/A+ and
+function identically to the BASIC version, unless it uses memory
+that's reserved in A+. **USR()** routines that are stored in the lower
+half of Page 6 will have to be relocated, since A+ uses this area
+itself. See the BASIC/A+ manual for full details.
+
+BASIC XL
+========
+
+BASIC XL is basically the next version of BASIC/A+, by the
+same developers. The token lists were rearranged so that it's
+token-compatible with Atari BASIC, and includes all the extra
+commands/functions/etc from BASIC/A+... with different token numbers.
+
+BASIC XL has keywords and operators that don't exist in BASIC/A+. These
+are:
+
+**NUM**
+ Rarely found in a program (usually only used in direct mode).
+
+**FAST**
+ Just doesn't exist in BASIC/A+.
+
+**LOCAL**, **EXIT**, **PROCEDURE**, **CALL**, **SORTUP**, **SORTDOWN**
+ These BASIC XL commands are provided by the disk-based Toolkit
+ extension, which doesn't exist for BASIC/A+.
+
+**String Arrays**
+ BASIC/A+ doesn't support these; if your BASIC XL program uses them,
+ it won't convert correctly.
+
+**BUMP** and **FIND**
+ While BASIC/A+ does support these functions, the token-level syntax
+ is different; it would be possible to translate them, but it would
+ require recalculating the line offset and statement offsets for
+ every line that uses them. For now, they're not supported.
+
+**%**
+ The exclusive OR operator in BASIC XL. No such animal, in A+.
+
+**HEX$**, **RANDOM**, **LEFT$**, **RIGHT$**, **MID$**
+ These functions don't exist in BASIC/A+.
+
+Also, BASIC XL supports hex constants, with a leading **$**. A+
+doesn't support these, so they get converted to the equivalent decimal
+constant. This is basically a cosmetic change; **A=$0600** assigns the
+same value as **A=1536**.
+
+EXIT STATUS
+===========
+
+0 for success, non-zero for failuse.
+
+.. include:: manftr.rst