diff options
| -rw-r--r-- | Makefile | 8 | ||||
| -rw-r--r-- | a8eol.1 | 4 | ||||
| -rw-r--r-- | a8utf8.1 | 4 | ||||
| -rw-r--r-- | atascii.7 | 4 | ||||
| -rw-r--r-- | atr2xfd.1 | 4 | ||||
| -rw-r--r-- | atrsize.1 | 4 | ||||
| -rw-r--r-- | axe.1 | 4 | ||||
| -rw-r--r-- | bas.c | 2 | ||||
| -rw-r--r-- | blob2c.1 | 4 | ||||
| -rw-r--r-- | blob2xex.1 | 4 | ||||
| -rw-r--r-- | cart2xex.1 | 4 | ||||
| -rw-r--r-- | dasm2atasm.1 | 4 | ||||
| -rw-r--r-- | dumpbas.1 | 267 | ||||
| -rw-r--r-- | dumpbas.c | 160 | ||||
| -rw-r--r-- | dumpbas.rst | 163 | ||||
| -rw-r--r-- | fenders.1 | 4 | ||||
| -rw-r--r-- | manftr.rst | 2 | ||||
| -rw-r--r-- | rom2cart.1 | 4 | ||||
| -rw-r--r-- | unmac65.1 | 4 | ||||
| -rw-r--r-- | unprotbas.1 | 4 | ||||
| -rw-r--r-- | xex.5 | 4 | ||||
| -rw-r--r-- | xex1to2.1 | 4 | ||||
| -rw-r--r-- | xexamine.1 | 4 | ||||
| -rw-r--r-- | xexcat.1 | 4 | ||||
| -rw-r--r-- | xexsplit.1 | 4 | ||||
| -rw-r--r-- | xfd2atr.1 | 4 | 
26 files changed, 659 insertions, 23 deletions
@@ -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 xfd2atr atr2xfd blob2c cart2xex fenders xexsplit xexcat atrsize rom2cart unmac65 axe blob2xex xexamine xex1to2 unprotbas protbas +BINS=a8eol xfd2atr atr2xfd blob2c cart2xex fenders xexsplit xexcat atrsize rom2cart unmac65 axe blob2xex xexamine xex1to2 unprotbas protbas renumbas dumpbas  SCRIPTS=dasm2atasm a8utf8 -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 a8utf8.1 blob2xex.1 xexamine.1 xex1to2.1 unprotbas.1 protbas.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 a8utf8.1 blob2xex.1 xexamine.1 xex1to2.1 unprotbas.1 protbas.1 renumbas.1 dumpbas.1  MAN5S=xex.5  MAN7S=atascii.7  DOCS=README.txt equates.inc *.dasm LICENSE ksiders/atr.txt @@ -53,6 +53,10 @@ unprotbas: bas.o  protbas: bas.o +renumbas: bas.o + +dumpbas: bas.o +  bas.o: bas.c bas.h  subdirs: @@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]  .\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]  .in \\n[rst2man-indent\\n[rst2man-indent-level]]u  .. -.TH "A8EOL" 1 "2024-06-03" "0.2.1" "Urchlay's Atari 8-bit Tools" +.TH "A8EOL" 1 "2024-06-07" "0.2.1" "Urchlay's Atari 8-bit Tools"  .SH NAME  a8eol \- convert Atari 8-bit text files to/from UNIX/Windows/Mac  .\" RST source for a8eol(1) man page. Convert with: @@ -470,9 +470,11 @@ Watson <\fI\%urchlay@slackware.uk\fP>; Urchlay on irc.libera.chat \fI##atari\fP\  \fBblob2xex\fP(1),  \fBcart2xex\fP(1),  \fBdasm2atasm\fP(1), +\fBdumpbas\fP(1),  \fBf2toxex\fP(1),  \fBfenders\fP(1),  \fBprotbas\fP(1), +\fBrenumbas\fP(1),  \fBrom2cart\fP(1),  \fBunmac65\fP(1),  \fBunprotbas\fP(1), @@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]  .\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]  .in \\n[rst2man-indent\\n[rst2man-indent-level]]u  .. -.TH "A8UTF8" 1 "2024-06-03" "0.2.1" "Urchlay's Atari 8-bit Tools" +.TH "A8UTF8" 1 "2024-06-07" "0.2.1" "Urchlay's Atari 8-bit Tools"  .SH NAME  a8utf8 \- Convert Atari 8-bit text to UTF-8 encoded Unicode.  .\" RST source for a8utf8(1) man page. Convert with: @@ -101,9 +101,11 @@ Watson <\fI\%urchlay@slackware.uk\fP>; Urchlay on irc.libera.chat \fI##atari\fP\  \fBblob2xex\fP(1),  \fBcart2xex\fP(1),  \fBdasm2atasm\fP(1), +\fBdumpbas\fP(1),  \fBf2toxex\fP(1),  \fBfenders\fP(1),  \fBprotbas\fP(1), +\fBrenumbas\fP(1),  \fBrom2cart\fP(1),  \fBunmac65\fP(1),  \fBunprotbas\fP(1), @@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]  .\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]  .in \\n[rst2man-indent\\n[rst2man-indent-level]]u  .. -.TH "ATASCII" 7 "2024-06-03" "0.2.1" "Urchlay's Atari 8-bit Tools" +.TH "ATASCII" 7 "2024-06-07" "0.2.1" "Urchlay's Atari 8-bit Tools"  .SH NAME  atascii \- Atari 8-bit character set  .\" RST source for atascii(7) man page. Convert with: @@ -2161,9 +2161,11 @@ Watson <\fI\%urchlay@slackware.uk\fP>; Urchlay on irc.libera.chat \fI##atari\fP\  \fBblob2xex\fP(1),  \fBcart2xex\fP(1),  \fBdasm2atasm\fP(1), +\fBdumpbas\fP(1),  \fBf2toxex\fP(1),  \fBfenders\fP(1),  \fBprotbas\fP(1), +\fBrenumbas\fP(1),  \fBrom2cart\fP(1),  \fBunmac65\fP(1),  \fBunprotbas\fP(1), @@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]  .\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]  .in \\n[rst2man-indent\\n[rst2man-indent-level]]u  .. -.TH "ATR2XFD" 1 "2024-06-03" "0.2.1" "Urchlay's Atari 8-bit Tools" +.TH "ATR2XFD" 1 "2024-06-07" "0.2.1" "Urchlay's Atari 8-bit Tools"  .SH NAME  atr2xfd \- Convert an Atari 8-bit ATR disk image to a raw (XFD) image  .\" RST source for atr2xfd(1) man page. Convert with: @@ -190,9 +190,11 @@ Watson <\fI\%urchlay@slackware.uk\fP>; Urchlay on irc.libera.chat \fI##atari\fP\  \fBblob2xex\fP(1),  \fBcart2xex\fP(1),  \fBdasm2atasm\fP(1), +\fBdumpbas\fP(1),  \fBf2toxex\fP(1),  \fBfenders\fP(1),  \fBprotbas\fP(1), +\fBrenumbas\fP(1),  \fBrom2cart\fP(1),  \fBunmac65\fP(1),  \fBunprotbas\fP(1), @@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]  .\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]  .in \\n[rst2man-indent\\n[rst2man-indent-level]]u  .. -.TH "ATRSIZE" 1 "2024-06-03" "0.2.1" "Urchlay's Atari 8-bit Tools" +.TH "ATRSIZE" 1 "2024-06-07" "0.2.1" "Urchlay's Atari 8-bit Tools"  .SH NAME  atrsize \- Change the size of an Atari 8-bit ATR disk image, or create a blank ATR image  .\" RST source for atrsize(1) man page. Convert with: @@ -204,9 +204,11 @@ Watson <\fI\%urchlay@slackware.uk\fP>; Urchlay on irc.libera.chat \fI##atari\fP\  \fBblob2xex\fP(1),  \fBcart2xex\fP(1),  \fBdasm2atasm\fP(1), +\fBdumpbas\fP(1),  \fBf2toxex\fP(1),  \fBfenders\fP(1),  \fBprotbas\fP(1), +\fBrenumbas\fP(1),  \fBrom2cart\fP(1),  \fBunmac65\fP(1),  \fBunprotbas\fP(1), @@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]  .\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]  .in \\n[rst2man-indent\\n[rst2man-indent-level]]u  .. -.TH "AXE" 1 "2024-06-03" "0.2.1" "Urchlay's Atari 8-bit Tools" +.TH "AXE" 1 "2024-06-07" "0.2.1" "Urchlay's Atari 8-bit Tools"  .SH NAME  axe \- ATR/XFD Editor  .\" RST source for axe(1) man page. Convert with: @@ -145,9 +145,11 @@ Watson <\fI\%urchlay@slackware.uk\fP>; Urchlay on irc.libera.chat \fI##atari\fP\  \fBblob2xex\fP(1),  \fBcart2xex\fP(1),  \fBdasm2atasm\fP(1), +\fBdumpbas\fP(1),  \fBf2toxex\fP(1),  \fBfenders\fP(1),  \fBprotbas\fP(1), +\fBrenumbas\fP(1),  \fBrom2cart\fP(1),  \fBunmac65\fP(1),  \fBunprotbas\fP(1), @@ -217,7 +217,7 @@ FILE *open_file(const char *name, const char *mode) {  }  void open_input(const char *name) { -	if(!name) { +	if(!name || strcmp(name, "-") == 0) {  		if(isatty(fileno(stdin))) {  			die("Can't read binary data from the terminal.");  		} @@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]  .\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]  .in \\n[rst2man-indent\\n[rst2man-indent-level]]u  .. -.TH "BLOB2C" 1 "2024-06-03" "0.2.1" "Urchlay's Atari 8-bit Tools" +.TH "BLOB2C" 1 "2024-06-07" "0.2.1" "Urchlay's Atari 8-bit Tools"  .SH NAME  blob2c \- Create C source and header files from a binary file  .\" RST source for blob2c(1) man page. Convert with: @@ -125,9 +125,11 @@ Watson <\fI\%urchlay@slackware.uk\fP>; Urchlay on irc.libera.chat \fI##atari\fP\  \fBblob2xex\fP(1),  \fBcart2xex\fP(1),  \fBdasm2atasm\fP(1), +\fBdumpbas\fP(1),  \fBf2toxex\fP(1),  \fBfenders\fP(1),  \fBprotbas\fP(1), +\fBrenumbas\fP(1),  \fBrom2cart\fP(1),  \fBunmac65\fP(1),  \fBunprotbas\fP(1), @@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]  .\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]  .in \\n[rst2man-indent\\n[rst2man-indent-level]]u  .. -.TH "BLOB2XEX" 1 "2024-06-03" "0.2.1" "Urchlay's Atari 8-bit Tools" +.TH "BLOB2XEX" 1 "2024-06-07" "0.2.1" "Urchlay's Atari 8-bit Tools"  .SH NAME  blob2xex \- Create Atari 8-bit executables from arbitrary data  .\" RST source for blob2xex(1) man page. Convert with: @@ -216,9 +216,11 @@ Watson <\fI\%urchlay@slackware.uk\fP>; Urchlay on irc.libera.chat \fI##atari\fP\  \fBblob2xex\fP(1),  \fBcart2xex\fP(1),  \fBdasm2atasm\fP(1), +\fBdumpbas\fP(1),  \fBf2toxex\fP(1),  \fBfenders\fP(1),  \fBprotbas\fP(1), +\fBrenumbas\fP(1),  \fBrom2cart\fP(1),  \fBunmac65\fP(1),  \fBunprotbas\fP(1), @@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]  .\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]  .in \\n[rst2man-indent\\n[rst2man-indent-level]]u  .. -.TH "CART2XEX" 1 "2024-06-03" "0.2.1" "Urchlay's Atari 8-bit Tools" +.TH "CART2XEX" 1 "2024-06-07" "0.2.1" "Urchlay's Atari 8-bit Tools"  .SH NAME  cart2xex \- Convert an Atari 8-bit ROM cartridge image to a binary load file  .\" RST source for cart2xex(1) man page. Convert with: @@ -235,9 +235,11 @@ Watson <\fI\%urchlay@slackware.uk\fP>; Urchlay on irc.libera.chat \fI##atari\fP\  \fBblob2xex\fP(1),  \fBcart2xex\fP(1),  \fBdasm2atasm\fP(1), +\fBdumpbas\fP(1),  \fBf2toxex\fP(1),  \fBfenders\fP(1),  \fBprotbas\fP(1), +\fBrenumbas\fP(1),  \fBrom2cart\fP(1),  \fBunmac65\fP(1),  \fBunprotbas\fP(1), diff --git a/dasm2atasm.1 b/dasm2atasm.1 index 7e8e0fc..e51c1f5 100644 --- a/dasm2atasm.1 +++ b/dasm2atasm.1 @@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]  .\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]  .in \\n[rst2man-indent\\n[rst2man-indent-level]]u  .. -.TH "DASM2ATASM" 1 "2024-06-03" "0.2.1" "Urchlay's Atari 8-bit Tools" +.TH "DASM2ATASM" 1 "2024-06-07" "0.2.1" "Urchlay's Atari 8-bit Tools"  .SH NAME  dasm2atasm \- Convert 6502 assembly source from dasm syntax to atasm or ca65 syntax.  .\" RST source for dasm2atasm(1) man page. Convert with: @@ -232,9 +232,11 @@ Watson <\fI\%urchlay@slackware.uk\fP>; Urchlay on irc.libera.chat \fI##atari\fP\  \fBblob2xex\fP(1),  \fBcart2xex\fP(1),  \fBdasm2atasm\fP(1), +\fBdumpbas\fP(1),  \fBf2toxex\fP(1),  \fBfenders\fP(1),  \fBprotbas\fP(1), +\fBrenumbas\fP(1),  \fBrom2cart\fP(1),  \fBunmac65\fP(1),  \fBunprotbas\fP(1), diff --git a/dumpbas.1 b/dumpbas.1 new file mode 100644 index 0000000..9da3e11 --- /dev/null +++ b/dumpbas.1 @@ -0,0 +1,267 @@ +.\" 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 "DUMPBAS" 1 "2024-06-07" "0.2.1" "Urchlay's Atari 8-bit Tools" +.SH NAME +dumpbas \- Formatted hexdump for tokenized Atari 8-bit BASIC files +.SH SYNOPSIS +.sp +dumpbas [\fB\-v\fP] [\fB\-l\fP \fIlineno\fP] [\fB\-s\fP \fIstart\-lineno\fP] [\fB\-e\fP \fIend\-lineno\fP] \fIinput\-file\fP +.SH DESCRIPTION +.sp +\fBdumpbas\fP reads a tokenized Atari 8\-bit BASIC program and prints a +formatted hexdump on standard output. The formatting groups the hex bytes +by line and statement, and includes special characters to mark different +types of token (see \fBFORMATTING\fP, below). +.sp +\fBdumpbas\fP does not detokenize BASIC programs or dump information +about variable names/values. Use \fBchkbas\fP(1) for that. This tool is +intended to help the user learn about the tokenized BASIC format, or +as an aid for developing/debugging other tools that process tokenized +files. It\(aqs an alternative to looking at raw hex dumps. +.sp +It\(aqs assumed the user has at least some knowledge of BASIC\(aqs tokenized +SAVE format. The \fBAtari BASIC Sourcebook\fP is a good starting point +for learning the tokenized format. +.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 +.SS Dump Options +.INDENT 0.0 +.TP +.B \fB\-s\fP \fIstart\-lineno\fP +Don\(aqt dump lines before \fBstart\-lineno\fP\&. Default: \fI0\fP\&. +.TP +.B \fB\-e\fP \fIend\-lineno\fP +Don\(aqt dump lines after \fBstart\-lineno\fP\&. Default: \fI32768\fP\&. +.TP +.B \fB\-l\fP \fIlineno\fP +Only dump one line. This is exactly equivalent to "\fB\-s\fP \fInum\fP \fB\-e\fP \fInum\fP". +.UNINDENT +.SH FORMATTING +.sp +Every byte in the file is displayed in hex. However, they are grouped by line +and statement, and certain tokens get marker characters to help keep track +of what they\(aqre for. Strings are displayed in both hex and ASCII. Floating +point constants are displayed as 6 hex bytes with square brackets around them. +.sp +If \fBdumpbas\fP is run on the following program: +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +10 ? "HOW MANY TIMES";:INPUT N +20 FOR I=1 TO N +30 ? "HELLO ";:? I;"/";N:NEXT I +40 REM WAIT FOR KEY +50 POKE 764,255 +60 ? "PRESS ANY KEY" +70 IF PEEK(764)=255 THEN 70 +80 POKE 764,255:GOTO 10 +.ft P +.fi +.UNINDENT +.UNINDENT +.sp +\fBNote:\fP The "PRESS ANY KEY" was entered in inverse video. +.sp +\&...it produces the following output: +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +   10@0021 (0a 00): ^1b +    >17 !28 $0f =0e "H/48 O/4f W/57  /20 M/4d A/41 N/4e Y/59  /20 T/54 I/49 M/4d E/45 S/53" 15 14: +    >1b !02 80 16 +   20@003c (14 00): ^11 +    >11 !08 81 2d #0e [40 01 00 00 00 00] 19 80 16 +   30@004d (1e 00): ^1d +    >0f !28 $0f =06 "H/48 E/45 L/4c L/4c O/4f  /20" 15 14: +    >19 !28 81 15 $0f =01 "//2f" 15 80 14: +    >1d !09 81 16 +   40@006a (28 00): ^12 +    >12 !00 57 41 49 54 20 46 4f 52 20 4b 45 59 9b +   50@007c (32 00): ^15 +    >15 !1f #0e [41 07 64 00 00 00] 12 #0e [41 02 55 00 00 00] 16 +   60@0091 (3c 00): ^15 +    >15 !28 $0f =0d "|P/d0 |R/d2 |E/c5 |S/d3 |S/d3 | /a0 |A/c1 |N/ce |Y/d9 | /a0 |K/cb |E/c5 |Y/d9" 16 +   70@00a6 (46 00): ^20 +    >20 !07 46 3a #0e [41 07 64 00 00 00] 2c 22 #0e [41 02 55 00 00 00] 1b #0e [40 70 00 00 00 00] 16 +   80@00c6 (50 00): ^1f +    >15 !1f #0e [41 07 64 00 00 00] 12 #0e [41 02 55 00 00 00] 14: +    >1f !0a #0e [40 10 00 00 00 00] 16 +32768@00e5 (00 80): ^0f +    >0f !19 $0f =07 "H/48 :/3a B/42 ./2e B/42 A/41 S/53" 16 +.ft P +.fi +.UNINDENT +.UNINDENT +.SS Line header +.sp +Each line number begins with the line number (decimal) and offset from +the start of the file (hex), followed by the 2 hex bytes for the line +number in parentheses, followed by the line length (hex, preceded by +^). From the example: +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +10@0021 (0a 00): ^1b +.ft P +.fi +.UNINDENT +.UNINDENT +.sp +The line number is \fI10\fP, the file offset is \fI0021\fP\&. The \fI0a 00\fP are 10 again, in +hex, LSB first. The \fI^1b\fP is the line length. +.SS Statements +.sp +Each statement within the line is displayed separately. Line 10\(aqs first statement: +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +>17 !28 $0f =0e "H/48 O/4f W/57  /20 M/4d A/41 N/4e Y/59  /20 T/54 I/49 M/4d E/45 S/53" 15 14: +.ft P +.fi +.UNINDENT +.UNINDENT +.sp +This looks cryptic, but it includes a lot of information. +.INDENT 0.0 +.IP \(bu 2 +\fI>\fP is the marker for the statement offset (\fI17\fP). +.IP \(bu 2 +\fI!\fP marks a command token (unmarked tokens are operator +tokens). \fI28\fP is the token for \fB?\fP (short form of PRINT, which has a +separate token). +.IP \(bu 2 +\fI$\fP marks the string\-constant token (\fI0f\fP). +.IP \(bu 2 +\fI=\fP marks the string length byte (\fI0e\fP). +.IP \(bu 2 +The string itself is printed inside double quotes, with each character in +both ASCII and hex (e.g. \fIH/48\fP). +.IP \(bu 2 +The \fI15\fP is unmarked. It\(aqs the semicolon after the string. +.IP \(bu 2 +There\(aqs a \fI:\fP at the end of the line (after the \fI14\fP, which is the end\-of\-statement +token). +.UNINDENT +.sp +Line 10\(aqs second statement: +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +>1b !02 80 16 +.ft P +.fi +.UNINDENT +.UNINDENT +.sp +The \fI80\fP is a token for a variable (variable tokens always have bit 7 set, so they\(aqre +always >= 80 hex). The \fI16\fP is the end\-of\-line token. +.sp +Line 20\(aqs first statement has an example of a floating point constant: +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +#0e [40 01 00 00 00 00] +.ft P +.fi +.UNINDENT +.UNINDENT +.INDENT 0.0 +.IP \(bu 2 +\fI#\fP marks the token for a FP constant. +.IP \(bu 2 +The actual 6\-byte constant is surrounded with \fI[\fP and \fI]\fP\&. +.IP \(bu 2 +The last token is \fI16\fP, which is BASIC\(aqs end\-of\-line token. +.UNINDENT +.SH EXIT STATUS +.sp +0 for success, 1 for failure. +.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 +\fBa8eol\fP(1), +\fBa8utf8\fP(1), +\fBatr2xfd\fP(1), +\fBatrsize\fP(1), +\fBaxe\fP(1), +\fBblob2c\fP(1), +\fBblob2xex\fP(1), +\fBcart2xex\fP(1), +\fBdasm2atasm\fP(1), +\fBdumpbas\fP(1), +\fBf2toxex\fP(1), +\fBfenders\fP(1), +\fBprotbas\fP(1), +\fBrenumbas\fP(1), +\fBrom2cart\fP(1), +\fBunmac65\fP(1), +\fBunprotbas\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/dumpbas.c b/dumpbas.c new file mode 100644 index 0000000..b7607ea --- /dev/null +++ b/dumpbas.c @@ -0,0 +1,160 @@ +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include <time.h> + +#include "bas.h" + +int startlineno = 0; +int endlineno = 32768; + +/* dump tokens for each line in a BASIC program. easier to read than +   a plain hex dump. */ +void print_help(void) { +	fprintf(stderr, "Usage: %s [-v] [-s start-lineno] [-e end-lineno] <inputfile>\n", self); +} + +unsigned short getlineno(char opt, const char *arg) { +	int lineno; +	char *e; + +	lineno = (int)strtol(arg, &e, 10); + +	if(*e) { +		fprintf(stderr, "%s: Invalid line number for -%c option: %s is not a number.\n", +				self, opt, arg); +		exit(1); +	} + +	if(lineno < 0 || lineno > 32767) { +		fprintf(stderr, "%s: Invalid line number for -%c option: %d > 32767.\n", +				self, opt, lineno); +		exit(1); +	} + +	return ((unsigned short)lineno); +} + +void parse_args(int argc, char **argv) { +	int opt; + +	while( (opt = getopt(argc, argv, "vs:e:l:")) != -1) { +		switch(opt) { +			case 'v': verbose = 1; break; +			case 's': startlineno = getlineno(opt, optarg); break; +			case 'e': endlineno   = getlineno(opt, optarg); break; +			case 'l': startlineno = getlineno(opt, optarg); +						 endlineno   = startlineno; break; +			default: +				print_help(); +				exit(1); +		} +	} + +	if(optind >= argc) +		die("No input file given (use - for stdin)."); +	else +		open_input(argv[optind]); +} + +void print_atascii(unsigned char c) { +	if(c & 0x80) { +		putchar('|'); +		c &= 0x7f; +	} + +	if(c < 32) { +		putchar('^'); +		c += 0x40; +	} + +	if(c == 0x7f) +		printf("del"); +	else +		putchar(c); +	putchar('/'); +} + +/* sorry, this is horrid, more like assembly than C. */ +int main(int argc, char **argv) { +	int pos, nextpos, offset, soffset, lineno, cmd, i, end; +	int numcount = 0, start_string = 0, end_string = 0; + +	set_self(*argv); +	parse_general_args(argc, argv, print_help); +	parse_args(argc, argv); + +	readfile(); +	parse_header(); + +	pos = codestart; +	while(pos < filelen) { +		lineno = getword(pos); +		offset = program[pos + 2]; +		nextpos = pos + offset; + +		if(lineno >= startlineno) { +			printf("%5d@%04x (%02x %02x): ^%02x ", lineno, pos, program[pos], program[pos + 1], offset); + +			i = pos + 3; +			while(i < nextpos) { +				soffset = program[i]; +				end = pos + soffset; +				while(i < end) { +					printf("\n    >%02x ", program[i]); /* offset */ +					i++; +					cmd = 1; +					while(i < end) { +						if(cmd) { +							putchar('!'); +						} else if(program[i] == 0x0e && program[i - 1] != 0x0f && (i < start_string || i > end_string)) { +							putchar('#'); +							numcount = 7; +						} else if(program[i] == 0x0f) { +							putchar('$'); +							start_string = i + 2; +							end_string = start_string + program[i + 1]; +						} + +						if(numcount == 6) +							putchar('['); + +						if(i == start_string) +							putchar('"'); + +						if(i == (start_string - 1)) +							putchar('='); + +						if(i >= start_string && i < end_string) +							print_atascii(program[i]); + +						printf("%02x", program[i]); +						if(i == (end - 1) && program[i] == 0x14) +							putchar(':'); + +						if(numcount) { +							if(--numcount == 0) +								putchar(']'); +						} + +						i++; +						if(i == end_string) +							putchar('"'); + +						putchar(' '); +						cmd = 0; +					} +				} +			} + +			putchar('\n'); +		} + +		if(lineno == endlineno) break; +		pos = nextpos; +	} + +	return 0; +} diff --git a/dumpbas.rst b/dumpbas.rst new file mode 100644 index 0000000..8b116c3 --- /dev/null +++ b/dumpbas.rst @@ -0,0 +1,163 @@ +======= +dumpbas +======= + +------------------------------------------------------- +Formatted hexdump for tokenized Atari 8-bit BASIC files +------------------------------------------------------- + +.. include:: manhdr.rst + +SYNOPSIS +======== +dumpbas [**-v**] [**-l** *lineno*] [**-s** *start-lineno*] [**-e** *end-lineno*] *input-file* + +DESCRIPTION +=========== +**dumpbas** reads a tokenized Atari 8-bit BASIC program and prints a +formatted hexdump on standard output. The formatting groups the hex bytes +by line and statement, and includes special characters to mark different +types of token (see **FORMATTING**, below). + +**dumpbas** does not detokenize BASIC programs or dump information +about variable names/values. Use **chkbas**\(1) for that. This tool is +intended to help the user learn about the tokenized BASIC format, or +as an aid for developing/debugging other tools that process tokenized +files. It's an alternative to looking at raw hex dumps. + +It's assumed the user has at least some knowledge of BASIC's tokenized +SAVE format. The **Atari BASIC Sourcebook** is a good starting point +for learning the tokenized format. + +OPTIONS +======= + +General Options +--------------- +**--help** +  Print usage message and exit. + +**--version** +  Print version number and exit. + +**-v** +  Verbose operation. When displaying a number in verbose mode, it will +  be prefixed with *$* if it's in hex, or no prefix for decimal. + +Dump Options +------------ +**-s** *start-lineno* +  Don't dump lines before **start-lineno**. Default: *0*. + +**-e** *end-lineno* +  Don't dump lines after **start-lineno**. Default: *32768*. + +**-l** *lineno* +  Only dump one line. This is exactly equivalent to "**-s** *num* **-e** *num*". + +FORMATTING +========== +Every byte in the file is displayed in hex. However, they are grouped by line +and statement, and certain tokens get marker characters to help keep track +of what they're for. Strings are displayed in both hex and ASCII. Floating +point constants are displayed as 6 hex bytes with square brackets around them. + +If **dumpbas** is run on the following program:: + +  10 ? "HOW MANY TIMES";:INPUT N +  20 FOR I=1 TO N +  30 ? "HELLO ";:? I;"/";N:NEXT I +  40 REM WAIT FOR KEY +  50 POKE 764,255 +  60 ? "PRESS ANY KEY" +  70 IF PEEK(764)=255 THEN 70 +  80 POKE 764,255:GOTO 10 + +**Note:** The "PRESS ANY KEY" was entered in inverse video. + +...it produces the following output:: + +     10@0021 (0a 00): ^1b  +      >17 !28 $0f =0e "H/48 O/4f W/57  /20 M/4d A/41 N/4e Y/59  /20 T/54 I/49 M/4d E/45 S/53" 15 14:  +      >1b !02 80 16  +     20@003c (14 00): ^11  +      >11 !08 81 2d #0e [40 01 00 00 00 00] 19 80 16  +     30@004d (1e 00): ^1d  +      >0f !28 $0f =06 "H/48 E/45 L/4c L/4c O/4f  /20" 15 14:  +      >19 !28 81 15 $0f =01 "//2f" 15 80 14:  +      >1d !09 81 16  +     40@006a (28 00): ^12  +      >12 !00 57 41 49 54 20 46 4f 52 20 4b 45 59 9b  +     50@007c (32 00): ^15  +      >15 !1f #0e [41 07 64 00 00 00] 12 #0e [41 02 55 00 00 00] 16  +     60@0091 (3c 00): ^15  +      >15 !28 $0f =0d "|P/d0 |R/d2 |E/c5 |S/d3 |S/d3 | /a0 |A/c1 |N/ce |Y/d9 | /a0 |K/cb |E/c5 |Y/d9" 16  +     70@00a6 (46 00): ^20  +      >20 !07 46 3a #0e [41 07 64 00 00 00] 2c 22 #0e [41 02 55 00 00 00] 1b #0e [40 70 00 00 00 00] 16  +     80@00c6 (50 00): ^1f  +      >15 !1f #0e [41 07 64 00 00 00] 12 #0e [41 02 55 00 00 00] 14:  +      >1f !0a #0e [40 10 00 00 00 00] 16  +  32768@00e5 (00 80): ^0f  +      >0f !19 $0f =07 "H/48 :/3a B/42 ./2e B/42 A/41 S/53" 16  + +Line header +----------- +Each line number begins with the line number (decimal) and offset from +the start of the file (hex), followed by the 2 hex bytes for the line +number in parentheses, followed by the line length (hex, preceded by +^). From the example:: + +     10@0021 (0a 00): ^1b  + +The line number is *10*, the file offset is *0021*. The *0a 00* are 10 again, in +hex, LSB first. The *^1b* is the line length. + +Statements +---------- +Each statement within the line is displayed separately. Line 10's first statement:: + +      >17 !28 $0f =0e "H/48 O/4f W/57  /20 M/4d A/41 N/4e Y/59  /20 T/54 I/49 M/4d E/45 S/53" 15 14:  + +This looks cryptic, but it includes a lot of information. + +- *>* is the marker for the statement offset (*17*). + +- *!* marks a command token (unmarked tokens are operator +  tokens). *28* is the token for **?** (short form of PRINT, which has a +  separate token). + +- *$* marks the string-constant token (*0f*). + +- *=* marks the string length byte (*0e*). + +- The string itself is printed inside double quotes, with each character in +  both ASCII and hex (e.g. *H/48*). + +- The *15* is unmarked. It's the semicolon after the string. + +- There's a *:* at the end of the line (after the *14*, which is the end-of-statement +  token). + +Line 10's second statement:: + +      >1b !02 80 16  + +The *80* is a token for a variable (variable tokens always have bit 7 set, so they're +always >= 80 hex). The *16* is the end-of-line token. + +Line 20's first statement has an example of a floating point constant:: + +  #0e [40 01 00 00 00 00] + +- *#* marks the token for a FP constant. + +- The actual 6-byte constant is surrounded with *[* and *]*. + +- The last token is *16*, which is BASIC's end-of-line token. + +EXIT STATUS +=========== + +0 for success, 1 for failure. + +.. include:: manftr.rst @@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]  .\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]  .in \\n[rst2man-indent\\n[rst2man-indent-level]]u  .. -.TH "FENDERS" 1 "2024-06-03" "0.2.1" "Urchlay's Atari 8-bit Tools" +.TH "FENDERS" 1 "2024-06-07" "0.2.1" "Urchlay's Atari 8-bit Tools"  .SH NAME  fenders \- Install Fenders 3-sector loader in boot sectors of an ATR image  .\" RST source for fenders(1) man page. Convert with: @@ -279,9 +279,11 @@ Watson <\fI\%urchlay@slackware.uk\fP>; Urchlay on irc.libera.chat \fI##atari\fP\  \fBblob2xex\fP(1),  \fBcart2xex\fP(1),  \fBdasm2atasm\fP(1), +\fBdumpbas\fP(1),  \fBf2toxex\fP(1),  \fBfenders\fP(1),  \fBprotbas\fP(1), +\fBrenumbas\fP(1),  \fBrom2cart\fP(1),  \fBunmac65\fP(1),  \fBunprotbas\fP(1), @@ -20,9 +20,11 @@ SEE ALSO  **blob2xex**\(1),   **cart2xex**\(1),   **dasm2atasm**\(1),  +**dumpbas**\(1),   **f2toxex**\(1),   **fenders**\(1),   **protbas**\(1), +**renumbas**\(1),   **rom2cart**\(1),   **unmac65**\(1),  **unprotbas**\(1), @@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]  .\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]  .in \\n[rst2man-indent\\n[rst2man-indent-level]]u  .. -.TH "ROM2CART" 1 "2024-06-03" "0.2.1" "Urchlay's Atari 8-bit Tools" +.TH "ROM2CART" 1 "2024-06-07" "0.2.1" "Urchlay's Atari 8-bit Tools"  .SH NAME  rom2cart \- Convert a raw ROM image to an Atari800 CART image, or vice versa  .\" RST source for rom2cart(1) man page. Convert with: @@ -248,9 +248,11 @@ Watson <\fI\%urchlay@slackware.uk\fP>; Urchlay on irc.libera.chat \fI##atari\fP\  \fBblob2xex\fP(1),  \fBcart2xex\fP(1),  \fBdasm2atasm\fP(1), +\fBdumpbas\fP(1),  \fBf2toxex\fP(1),  \fBfenders\fP(1),  \fBprotbas\fP(1), +\fBrenumbas\fP(1),  \fBrom2cart\fP(1),  \fBunmac65\fP(1),  \fBunprotbas\fP(1), @@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]  .\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]  .in \\n[rst2man-indent\\n[rst2man-indent-level]]u  .. -.TH "UNMAC65" 1 "2024-06-03" "0.2.1" "Urchlay's Atari 8-bit Tools" +.TH "UNMAC65" 1 "2024-06-07" "0.2.1" "Urchlay's Atari 8-bit Tools"  .SH NAME  unmac65 \- Detokenize Atari 8-bit Mac/65 SAVEd files.  .\" RST source for unmac65(1) man page. Convert with: @@ -380,9 +380,11 @@ Watson <\fI\%urchlay@slackware.uk\fP>; Urchlay on irc.libera.chat \fI##atari\fP\  \fBblob2xex\fP(1),  \fBcart2xex\fP(1),  \fBdasm2atasm\fP(1), +\fBdumpbas\fP(1),  \fBf2toxex\fP(1),  \fBfenders\fP(1),  \fBprotbas\fP(1), +\fBrenumbas\fP(1),  \fBrom2cart\fP(1),  \fBunmac65\fP(1),  \fBunprotbas\fP(1), diff --git a/unprotbas.1 b/unprotbas.1 index 06e8af7..c464b12 100644 --- a/unprotbas.1 +++ b/unprotbas.1 @@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]  .\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]  .in \\n[rst2man-indent\\n[rst2man-indent-level]]u  .. -.TH "UNPROTBAS" 1 "2024-06-03" "0.2.1" "Urchlay's Atari 8-bit Tools" +.TH "UNPROTBAS" 1 "2024-06-07" "0.2.1" "Urchlay's Atari 8-bit Tools"  .SH NAME  unprotbas \- Unprotect LIST-protected Atari 8-bit BASIC programs  .SH SYNOPSIS @@ -347,9 +347,11 @@ Watson <\fI\%urchlay@slackware.uk\fP>; Urchlay on irc.libera.chat \fI##atari\fP\  \fBblob2xex\fP(1),  \fBcart2xex\fP(1),  \fBdasm2atasm\fP(1), +\fBdumpbas\fP(1),  \fBf2toxex\fP(1),  \fBfenders\fP(1),  \fBprotbas\fP(1), +\fBrenumbas\fP(1),  \fBrom2cart\fP(1),  \fBunmac65\fP(1),  \fBunprotbas\fP(1), @@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]  .\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]  .in \\n[rst2man-indent\\n[rst2man-indent-level]]u  .. -.TH "XEX" 5 "2024-06-03" "0.2.1" "Urchlay's Atari 8-bit Tools" +.TH "XEX" 5 "2024-06-07" "0.2.1" "Urchlay's Atari 8-bit Tools"  .SH NAME  xex \- Atari 8-bit executable file format.  .\" RST source for xex(5) man page. Convert with: @@ -307,9 +307,11 @@ Watson <\fI\%urchlay@slackware.uk\fP>; Urchlay on irc.libera.chat \fI##atari\fP\  \fBblob2xex\fP(1),  \fBcart2xex\fP(1),  \fBdasm2atasm\fP(1), +\fBdumpbas\fP(1),  \fBf2toxex\fP(1),  \fBfenders\fP(1),  \fBprotbas\fP(1), +\fBrenumbas\fP(1),  \fBrom2cart\fP(1),  \fBunmac65\fP(1),  \fBunprotbas\fP(1), @@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]  .\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]  .in \\n[rst2man-indent\\n[rst2man-indent-level]]u  .. -.TH "XEX1TO2" 1 "2024-06-03" "0.2.1" "Urchlay's Atari 8-bit Tools" +.TH "XEX1TO2" 1 "2024-06-07" "0.2.1" "Urchlay's Atari 8-bit Tools"  .SH NAME  xex1to2 \- Convert an Atari DOS 1.0 executable to a standard Atari executable  .\" RST source for xex1to2(1) man page. Convert with: @@ -81,9 +81,11 @@ Watson <\fI\%urchlay@slackware.uk\fP>; Urchlay on irc.libera.chat \fI##atari\fP\  \fBblob2xex\fP(1),  \fBcart2xex\fP(1),  \fBdasm2atasm\fP(1), +\fBdumpbas\fP(1),  \fBf2toxex\fP(1),  \fBfenders\fP(1),  \fBprotbas\fP(1), +\fBrenumbas\fP(1),  \fBrom2cart\fP(1),  \fBunmac65\fP(1),  \fBunprotbas\fP(1), @@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]  .\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]  .in \\n[rst2man-indent\\n[rst2man-indent-level]]u  .. -.TH "XEXAMINE" 1 "2024-06-03" "0.2.1" "Urchlay's Atari 8-bit Tools" +.TH "XEXAMINE" 1 "2024-06-07" "0.2.1" "Urchlay's Atari 8-bit Tools"  .SH NAME  xexamine \- Show information on Atari 8-bit executables (XEX)  .\" RST source for xexamine(1) man page. Convert with: @@ -139,9 +139,11 @@ Watson <\fI\%urchlay@slackware.uk\fP>; Urchlay on irc.libera.chat \fI##atari\fP\  \fBblob2xex\fP(1),  \fBcart2xex\fP(1),  \fBdasm2atasm\fP(1), +\fBdumpbas\fP(1),  \fBf2toxex\fP(1),  \fBfenders\fP(1),  \fBprotbas\fP(1), +\fBrenumbas\fP(1),  \fBrom2cart\fP(1),  \fBunmac65\fP(1),  \fBunprotbas\fP(1), @@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]  .\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]  .in \\n[rst2man-indent\\n[rst2man-indent-level]]u  .. -.TH "XEXCAT" 1 "2024-06-03" "0.2.1" "Urchlay's Atari 8-bit Tools" +.TH "XEXCAT" 1 "2024-06-07" "0.2.1" "Urchlay's Atari 8-bit Tools"  .SH NAME  xexcat \- Concatenate Atari 8-bit executables (XEX) into a single XEX file.  .\" RST source for xexcat(1) man page. Convert with: @@ -199,9 +199,11 @@ Watson <\fI\%urchlay@slackware.uk\fP>; Urchlay on irc.libera.chat \fI##atari\fP\  \fBblob2xex\fP(1),  \fBcart2xex\fP(1),  \fBdasm2atasm\fP(1), +\fBdumpbas\fP(1),  \fBf2toxex\fP(1),  \fBfenders\fP(1),  \fBprotbas\fP(1), +\fBrenumbas\fP(1),  \fBrom2cart\fP(1),  \fBunmac65\fP(1),  \fBunprotbas\fP(1), @@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]  .\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]  .in \\n[rst2man-indent\\n[rst2man-indent-level]]u  .. -.TH "XEXSPLIT" 1 "2024-06-03" "0.2.1" "Urchlay's Atari 8-bit Tools" +.TH "XEXSPLIT" 1 "2024-06-07" "0.2.1" "Urchlay's Atari 8-bit Tools"  .SH NAME  xexsplit \- Split a multi-segment Atari 8-bit executable (XEX) into multiple single-segment files.  .\" RST source for xexsplit(1) man page. Convert with: @@ -192,9 +192,11 @@ Watson <\fI\%urchlay@slackware.uk\fP>; Urchlay on irc.libera.chat \fI##atari\fP\  \fBblob2xex\fP(1),  \fBcart2xex\fP(1),  \fBdasm2atasm\fP(1), +\fBdumpbas\fP(1),  \fBf2toxex\fP(1),  \fBfenders\fP(1),  \fBprotbas\fP(1), +\fBrenumbas\fP(1),  \fBrom2cart\fP(1),  \fBunmac65\fP(1),  \fBunprotbas\fP(1), @@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]  .\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]  .in \\n[rst2man-indent\\n[rst2man-indent-level]]u  .. -.TH "XFD2ATR" 1 "2024-06-03" "0.2.1" "Urchlay's Atari 8-bit Tools" +.TH "XFD2ATR" 1 "2024-06-07" "0.2.1" "Urchlay's Atari 8-bit Tools"  .SH NAME  xfd2atr \- Convert an Atari 8-bit XFD (raw) disk image to an ATR image.  .\" RST source for xfd2atr(1) man page. Convert with: @@ -120,9 +120,11 @@ Watson <\fI\%urchlay@slackware.uk\fP>; Urchlay on irc.libera.chat \fI##atari\fP\  \fBblob2xex\fP(1),  \fBcart2xex\fP(1),  \fBdasm2atasm\fP(1), +\fBdumpbas\fP(1),  \fBf2toxex\fP(1),  \fBfenders\fP(1),  \fBprotbas\fP(1), +\fBrenumbas\fP(1),  \fBrom2cart\fP(1),  \fBunmac65\fP(1),  \fBunprotbas\fP(1),  | 
