A.N.A.L.O.G. ISSUE 72 / MAY 1989 / PAGE 36

Super Command Processor

by Bryan Schappel

Do you use DOS 2.0 or 2.5? If so, this article is for you. If you tire of waiting for DUP.SYS to load, and hate MEM.SAV, you will enjoy this memory-resident DUP.SYS file. The BBK Command Processor.

The idea of a command processor is not new; they have been around for quite some time. Have you ever used UNIX, OSS A+ or SpartaDOS? All these operating systems use a system of input called Command Processing. Put simply, you type in commands, followed by a string of arguments which are then interpreted by the computer. This is what the BBK Command Processor does and what is better is that it gives you most of the functions of DUP.SYS (and some DUP never thought of) in less than 2,000 bytes!

Typing It In

Listing 1 is the data used to create the AUTORUN.SYS file of BBKCP. Please refer to the M/L Editor, found elsewhere in this issue, for typing instructions.

Listing 2 is the MAC/65 source code which need not be typed in to use the program, but is provided so you can see how the program works and so we can refer to it in later discussions.

About the BBKCP

BBKCP has ten internal commands and can have an extensive library of external commands. The built-in commands are given, with syntax, below:


COMMAND DESCRIPTION
ERASE fname
delete file
PROTECT fname
lock file
UNPROTECT fname
unlock file
RENAME old new
rename file
DIR [Dx:]
disk directory
COPY fn1 fn2
copy file
RUN [hex addr]
run at address
CAR
run cartridge
TYPE fname
type file
KILL
kill BBKCP

In the table above, fname stands for any legal DOS filename in the format of [Dx:]filename.ext, where x is any legal drive number. Anything in brackets is considered optional. For optional arguments, certain default conditions will be used. For example, just giving a filename following a command will tell BBKCP that this command is issued to the default device. (The default device is used as the prompt.) So if you typed PROTECT MYFILE.BAS, BBKCP would expand this to PROTECT D1:MYFILE.BAS—assuming D1: is the default device.

To change the default device, just enter it on the command line. For example, if the prompt is D1: , and you type D2:, you are now prompted with D2:.

Any legal Atari device may be used for the default device, such as P:, E:, S: and C:. You should remember, though, that most of the commands are used for disk operation and will give errors with another device.

BBKCP uses the Space (ATASCII 32) as a delimiter to separate commands and arguments on the command line. You may put as many spaces between arguments as you like, however there may be no spaces before a command.

To enter the BBKCP from BASIC or MAC/65 (or any other language cartridge), simply use the DOS command. Any program currently in memory will remain safe unless you use the COPY command or use an external command. (We’ll discuss external commands in a little while.)

About the Commands

You are only required to enter the first three letters of any internal command, but in all examples the entire command name will be used.

ERASE. This command accepts a filename as the argument (wildcards are allowed) and will delete the matching file(s) from your disk. You are not asked for verification, so be careful with this command.

PROTECT. Again only specify the file to be used, and voila, it’s locked. Use UNPROTECT to reverse the locking process. Wildcards are allowed.

RENAME. This requires two arguments, namely the current name of the file and its new name. Separate the names by at least one space to ensure the rename will function correctly. Wildcards are allowed—but be careful not to rename two files with the same name.

Do not supply a device prefix for the new filename with a rename command, as it will cause unpredictable results. It will not destroy your disk, but it will cause some headaches. It is, however, perfectly legal to put a device prefix on the old filename.

DIR. This command takes an optional argument, the directory specifier. The default specifier is [*].[*], but you may use D2:[*].BAS or anything else you may think of. To get the directory from anything but the default device, just type the device name after the DIR command.

COPY. This command will copy one file to another disk drive or file. Wildcards will produce strange results—Don’t use them. COPY will make as many passes as needed to duplicate the file. COPY is mainly for a two-drive system; if used with a one-drive system, it can only duplicate the file to the same disk under a separate name. (Note: If you are using one drive with COPY, make certain that you use unique filenames for the source and destination files. Otherwise you could loose the source file forever!) Another great use for COPY is to copy a text file to the screen or printer. To do this your commands would look like this:

COPY MYFILE.TXT E: (screen)
COPY MYFILE.TXT P: (printer)

Using the COPY command will destroy any program in memory, so save your work before performing a COPY.

RUN. This command takes an optional hexadecimal address as its parameter and is used to execute a machine-language program in memory. If an address is supplied, RUN will execute at the supplied address. If no address is given, the last run address will be used. At the end of your machine-language routine, execute an RTS instruction to return to BBKCP.

RUN (with no argument) may also be used to re-run the last external command, assuming it still resides in memory.

The RUN command checks to see if the address given as an argument contains only legal hexadecimal digits and that the number contains no more than four digits. If these conditions are not met, an ERROR 180 is given, and control passes back to BBKCP.

CAR. This command will attempt to pass control to the left cartridge, if it is present. (In the case of an XL or XE, the “left” cartridge is either the built-in BASIC or whatever cartridge is plugged into the computer.) If no cartridge exists, the message “No Cart” will appear, and you are returned to BBKCP; otherwise, the cartridge will be entered.

TYPE. This command will print the contents of a text file (the name of which you supply) to the screen, assuming each line of the text has a maximum of 64 characters per line. Mainly this is used to show the contents of a BATCH file. (More on BATCH files later.)

KILL. Use of this command will (1) remove BBKCP from memory, (2) wipe out any program in memory and (3) pass control to either a cartridge (if present) or go to DOS.

External Commands

If you enter something that BBKCP does not understand, it assumes that it is an external command, and BBKCP attempts to binary load the file. If what you typed has no filename extension, BBKCP adds on a .COM extension. Executing an external command is destructive to memory, in most cases. External commands must be binary, load-and-go machine-language files. If the file doesn’t begin with a $FF $FF header, an ERROR 181 is given and control passes back to BBKCP.

Next month, a library of external commands will be published.

Batch Files

Batch files are a wonderful way of automating certain processes. A batch file is simply a text file full of commands that either BBKCP understands or commands that the left cartridge understands. You may use a batch file to perform simple operations like copying a few files or running other external commands.

Use any text editor to make a batch file or simply use the COPY command like this:

COPY E1: D1:MYBATCH.BAT

When using this command, type your text one line at a time (maximum length is 64 characters), and press Return after each line. When you are finished press Control-3 to terminate the COPY.

To execute a batch file, type a “[*]” before the filename at the prompt. You are also allowed to chain batch files if the last line in the batch file looks like “[*] batfile”. If no file extension is supplied on the filename a .BAT extension is used. Here is a sample batch file:

;BATCH FILE TO GIVE DIRECTORY AND
;RUN THE CART.
;ANY LINE STARTING MITH A ';'
;IS IGNORED BY BBKCP!
DIR
CAR

Upon power-up, after it has loaded, BBKCP will attempt to run the batch file called AUTORUN.BAT from Drive 1. If the file does not exist you are left in BBKCP, or control is passed to a cartridge (if present).

The AUTORUN.BAT file is extremely powerful. You could use it to copy files to a RAMdisk or go to the cartridge and run a program or simply print a “hello” message whenever you boot up your system. You can think of this file as giving you an infinite number of AUTORUN.SYS files.

Next Month

Next time around, we will provide some library functions and tell you how to interface into BBKCP so you can write your own commands!


By the time you read this, Bryan and Carol will have been happily married for a while. Their new (read: same) apartment contains a new Mega ST2, which shares the computer room with the 800XL. The compu-kids get along very well—if you overlook the constant battle for the printer.

LISTING 1: M/L EDITOR

1000 DATA 255,255,124,29,198,35,160,0,132,226,140,224,2,140,225,2,7642
1010 DATA 32,212,31,160,0,32,237,33,169,121,160,35,32,163,32,32,2915
1020 DATA 221,30,32,195,34,32,149,31,169,4,157,74,3,32,86,228,3431
1030 DATA 16,7,76,165,31,160,181,208,249,32,81,30,166,220,232,208,1852
1040 DATA 244,166,221,232,208,239,32,158,32,169,118,141,226,2,169,30,8118
1050 DATA 141,227,2,32,81,30,166,220,232,208,8,166,221,232,208,3,823
1060 DATA 32,81,30,165,220,133,216,165,221,133,217,166,226,208,10,230,4112
1070 DATA 226,141,182,35,165,216,141,181,35,32,81,30,165,220,56,229,8435
1080 DATA 216,133,218,165,221,229,217,133,219,230,218,208,2,230,219,32,4146
1090 DATA 43,30,48,9,32,16,30,76,191,29,108,226,2,32,221,30,2625
1100 DATA 173,224,2,170,13,225,2,240,9,142,181,35,173,225,2,141,7353
1110 DATA 182,35,108,181,35,165,216,133,214,165,217,133,215,162,16,169,1717
1120 DATA 7,157,66,3,165,214,157,68,3,165,215,157,69,3,165,218,8231
1130 DATA 157,72,3,165,219,157,73,3,76,86,228,169,220,133,214,169,1388
1140 DATA 0,133,215,133,219,169,2,133,218,208,210,133,212,132,213,160,4077
1150 DATA 0,177,212,240,11,32,119,30,230,212,208,243,230,213,208,239,6730
1160 DATA 96,168,173,7,228,72,173,6,228,72,152,96,162,0,169,64,6231
1170 DATA 141,190,2,169,0,133,214,133,219,169,64,133,218,169,5,133,9097
1180 DATA 215,76,55,30,169,0,133,226,133,212,133,213,185,0,5,201,8448
1190 DATA 155,208,8,165,226,240,2,24,96,56,96,162,15,221,105,35,5069
1200 DATA 240,5,202,16,248,48,242,6,212,38,213,6,212,38,213,6,6672
1210 DATA 212,38,213,6,212,38,213,138,5,212,133,212,230,226,200,165,4010
1220 DATA 226,201,5,176,212,144,197,162,16,208,2,162,32,138,72,169,7488
1230 DATA 12,157,66,3,32,86,228,104,170,96,169,81,160,35,32,97,4793
1240 DATA 30,32,130,30,16,6,32,165,31,76,240,30,173,0,5,201,3083
1250 DATA 155,240,231,96,165,6,208,7,169,72,160,35,76,97,30,108,4280
1260 DATA 250,191,32,35,31,133,8,32,10,31,108,10,0,169,255,133,3420
1270 DATA 10,169,255,133,11,173,194,32,133,12,173,195,32,133,13,172,6407
1280 DATA 216,35,169,0,153,26,3,169,228,153,27,3,169,255,141,231,9860
1290 DATA 2,169,255,141,232,2,169,0,141,217,35,96,169,33,208,40,6709
1300 DATA 169,35,208,36,169,36,208,32,32,212,31,164,223,32,237,33,7227
1310 DATA 166,222,169,44,157,186,35,185,0,5,157,187,35,232,200,201,169
1320 DATA 155,208,244,169,32,72,208,4,72,32,212,31,32,221,30,104,4675
1330 DATA 157,66,3,32,149,31,157,74,3,32,86,228,48,17,96,169,3413
1340 DATA 183,157,68,3,169,35,157,69,3,169,0,157,75,3,96,132,2929
1350 DATA 212,169,0,133,213,32,221,30,32,170,217,32,230,216,160,255,2729
1360 DATA 200,177,243,153,100,35,16,248,41,127,153,100,35,169,155,153,8177
1370 DATA 101,35,169,0,153,102,35,169,93,160,35,76,97,30,173,82,4344
1380 DATA 35,141,183,35,173,83,35,141,184,35,162,0,185,1,5,201,4620
1390 DATA 58,240,24,185,2,5,201,58,208,25,185,1,5,141,184,35,4179
1400 DATA 185,0,5,141,183,35,200,200,200,208,8,185,0,5,141,183,7590
1410 DATA 35,200,200,185,0,5,157,186,35,201,155,240,10,201,32,240,9976
1420 DATA 6,200,232,224,13,208,236,169,155,157,186,35,169,0,157,187,710
1430 DATA 35,134,222,96,185,0,5,201,155,240,15,32,154,30,176,13,4965
1440 DATA 165,212,141,181,35,165,213,141,182,35,108,181,35,160,180,76,8919
1450 DATA 165,31,169,6,208,2,169,4,141,112,32,32,212,31,173,186,6361
1460 DATA 35,201,155,208,11,162,3,189,86,35,157,186,35,202,16,247,8312
1470 DATA 32,221,30,32,195,34,32,149,31,169,6,157,74,3,32,86,1536
1480 DATA 228,48,204,162,16,32,137,30,48,27,160,0,185,0,5,201,2693
1490 DATA 155,240,3,200,208,246,169,0,153,1,5,169,0,160,5,32,2930
1500 DATA 97,30,76,121,32,76,221,30,169,0,133,8,96,133,212,132,6254
1510 DATA 213,162,255,160,4,232,189,186,35,201,46,240,13,201,155,208,2022
1520 DATA 244,177,212,157,186,35,232,136,16,247,96,32,255,255,32,35,9213
1530 DATA 31,162,0,32,227,30,32,195,34,169,90,141,68,3,169,35,3811
1540 DATA 141,69,3,142,75,3,169,12,141,74,3,32,86,228,216,172,6796
1550 DATA 4,228,174,5,228,200,208,1,232,140,82,34,142,83,34,160,7232
1560 DATA 0,185,26,3,201,69,240,7,200,200,200,192,33,144,242,200,2754
1570 DATA 140,216,35,169,234,153,26,3,169,35,153,27,3,162,80,32,3114
1580 DATA 227,30,160,15,185,0,228,153,234,35,185,144,3,153,250,35,8862
1590 DATA 136,16,241,169,71,141,238,35,169,34,141,239,35,173,217,35,9276
1600 DATA 208,61,238,217,35,165,12,141,194,32,165,13,141,195,32,169,7673
1610 DATA 193,133,12,169,32,133,13,165,10,141,36,31,165,11,141,40,2472
1620 DATA 31,169,118,133,10,169,33,133,11,173,231,2,141,67,31,173,5632
1630 DATA 232,2,141,72,31,169,10,141,231,2,169,36,141,232,2,96,5981
1640 DATA 32,228,32,169,255,133,8,216,32,240,30,173,0,5,201,42,5608
1650 DATA 208,3,76,8,34,201,59,240,238,160,0,32,212,31,173,186,8720
1660 DATA 35,201,155,208,15,173,183,35,141,82,35,173,184,35,141,83,6943
1670 DATA 35,76,125,33,169,131,133,212,169,35,133,213,162,0,160,0,7018
1680 DATA 185,0,5,209,212,208,26,200,192,3,208,244,189,161,35,141,1272
1690 DATA 210,33,189,171,35,141,211,33,32,237,33,32,255,255,76,125,9409
1700 DATA 33,165,212,24,105,3,133,212,144,2,230,213,232,224,10,208,1997
1710 DATA 205,32,124,29,76,125,33,185,0,5,201,32,240,7,201,155,6666
1720 DATA 240,3,200,208,242,185,0,5,201,32,208,3,200,208,246,132,1525
1730 DATA 223,96,160,0,169,32,141,0,5,32,237,33,32,212,31,169,4570
1740 DATA 126,160,35,32,163,32,169,12,32,112,34,169,183,141,254,35,7238
1750 DATA 169,35,141,255,35,169,4,141,4,36,169,3,32,112,34,16,818
1760 DATA 10,169,12,132,212,32,112,34,32,167,31,76,125,33,169,155,5293
1770 DATA 208,35,173,250,35,16,7,162,0,160,1,76,255,255,169,0,7126
1780 DATA 141,2,36,141,3,36,169,7,32,112,34,48,234,173,233,35,5944
1790 DATA 72,32,119,30,104,162,0,160,1,96,141,252,35,32,137,34,4221
1800 DATA 162,80,32,86,228,141,233,35,16,9,152,72,162,80,32,227,6567
1810 DATA 30,104,168,152,72,160,15,185,32,0,72,185,218,35,153,32,5496
1820 DATA 0,104,153,218,35,185,144,3,72,185,250,35,153,144,3,104,7058
1830 DATA 153,250,35,136,16,225,104,168,96,157,66,3,169,0,157,72,5534
1840 DATA 3,157,68,3,169,48,157,73,3,157,69,3,96,169,3,157,3752
1850 DATA 66,3,96,32,165,31,76,225,30,32,212,31,32,221,30,32,3447
1860 DATA 149,31,32,195,34,169,4,157,74,3,32,86,228,48,228,169,7255
1870 DATA 183,160,35,32,97,30,164,223,32,237,33,32,212,31,32,225,6878
1880 DATA 30,32,149,31,32,195,34,169,8,157,74,3,32,86,228,48,3765
1890 DATA 194,32,158,32,162,16,169,7,32,175,34,32,86,228,48,6,2817
1900 DATA 169,1,133,226,208,4,169,0,133,226,189,72,3,133,224,189,306
1910 DATA 73,3,133,225,162,32,169,11,32,175,34,165,224,157,72,3,6191
1920 DATA 165,225,157,73,3,32,86,228,165,226,208,200,32,221,30,76,9540
1930 DATA 225,30,78,111,32,67,97,114,116,155,0,155,68,49,58,0,1940
1940 DATA 42,46,42,155,69,58,155,69,114,114,111,114,45,32,32,32,1930
1950 DATA 32,155,0,48,49,50,51,52,53,54,55,56,57,65,66,67,9809
1960 DATA 68,69,70,155,77,79,67,46,155,84,65,66,46,69,82,65,2268
1970 DATA 80,82,79,85,78,80,82,69,78,68,73,82,67,79,80,82,2445
1980 DATA 85,78,67,65,82,84,89,80,75,73,76,82,86,90,94,72,3024
1990 DATA 207,42,10,76,24,31,31,31,31,32,34,32,31,32,31,118,7947
2000 DATA 30,68,49,58,65,85,84,79,82,85,78,46,66,65,84,155,3106
2010 DATA 0,10,36,139,36,162,0,142,217,35,134,8,232,134,9,32,4394
2020 DATA 199,32,169,83,160,36,32,97,30,32,225,30,32,195,34,32,2731
2030 DATA 149,31,169,4,157,74,3,32,86,228,8,32,225,30,40,16,1997
2040 DATA 10,165,6,208,3,108,10,0,108,250,191,169,81,160,35,32,5894
2050 DATA 97,30,169,186,160,35,32,97,30,104,104,76,28,34,125,155,4029
2060 DATA 66,66,75,32,67,80,32,45,32,40,67,41,32,49,57,56,8780
2070 DATA 55,32,65,78,65,76,79,71,32,67,111,109,112,117,116,105,4599
2080 DATA 110,103,155,98,121,58,32,66,114,121,97,110,32,83,99,104,4308
2090 DATA 97,112,112,101,108,155,0,226,2,227,2,10,36,0,0,0,9327

LISTING 2: ASSEMBLY

	.OPT	NOLIST
;-------------------------------
;
;Super Command Processor
;
;by: Bryan Schappel
;
;If the typed line does not
;contain a command, then the
;filename entered will be loaded
;as a binary file.
;
;-------------------------------
;
;*** Commands ***
;
;ERA [fname] = delete file
;REN [f1,f2] = rename f1 to f2
;PRO [fname] = lock file
;UNP [fname] = unlock file
;DIR [Dn:]   = directory of D#:
;RUN [adr]   = run at address
;COPY        = copy a File
;CAR         = enter Cart
;TYPE        = read BATCH file
;KILL        = KILL BBK CP
;
NUMCOM	=	10	;# OF COMMANDS
IOCB5	=	$0390	;Adr of IOCB5
MYBUF	=	$0500	;I/O Buffer
ZIOCB	=	$20	;Zpage IOCB
;
;Zero Page Variables
;
	*=	$D6
SL	.DS	1	;Load adr lo
SH	.DS	1	;Load adr hi
STL	.DS	1	;start adr lo
STH	.DS	1	;start adr hi
BLL	.DS	1	;length lo
BLH	.DS	1	;length hi
BAL	.DS	1	;buffer byte 1
BAH	.DS	1	;buffer byte 2
XSAV	.DS	1	;save loc
LNPOS	.DS	1	;CP line pos
LENSAV	.DS	2	;COPY length
COUNT	.DS	1	;counter
;
;OS Equates
;
CIOV	=	$E456	;CIO Vector
ICCOM	=	$0342	;CIO Command
ICBAL	=	$0344	;CIO buffer lo
ICBAH	=	$0345	;CIO buffer hi
ICBLL	=	$0348	;CIO length lo
ICBLH	=	$0349	;CIO length hi
AUX1	=	$034A	;CIO aux 1
AUX2	=	$034B	;CIO aux 2
RUNAD	=	$02E0	;run address
EOL	=	$9B	;end of line
FR0	=	$D4	;FP number
TRAMSZ	=	$06	;cart in?
BOOT?	=	$09	;boot flag
DOSVEC	=	$0A	;DOS Vector
DOSINI	=	$0C	;init vec
WARMST	=	$08	;warm st flag
MEMLO	=	$02E7	;lo mem pntr
INITAD	=	$02E2	;init addr
HATABS	=	$031A	;Handler Table
SHFLOK	=	$02BE	;Caps toggle
IFP	=	$D9AA	;Int to FP
FASC	=	$D8E6	;FP to ASC
INBUFF	=	$F3	;FP pntr
EDITRV	=	$E400	;E: Handler Tab
;
;BUMP Macro
;
	.MACRO	BUMP 
	INC	%1
	BNE	@BUMP
	INC	%1+1
@BUMP
	.ENDM
;
;PRINT Macro
;
	.MACRO	PRINT 
	LDA	#<%1
	LDY	#>%1
	JSR	EPRINT
	.ENDM
;
ORIGIN	=	$1D7C
	*=	ORIGIN
;
;This routine attempts to
;Binary Load a file.
;If the file is not Binary an
;Error #181 is given.
;
;ENTER:
;MYBUF=Filename to load minus
;      a .COM extension.
;      Load is on IOCB #1
;
LOADIT	LDY	#0
	STY	COUNT
	STY	RUNAD
	STY	RUNAD+1
	JSR	FINDFILE
	LDY	#0
	JSR	FINDARG
	LDA	#<COM
	LDY	#>COM
	JSR	ADD_EXT
	JSR	CLOSE1
;
	JSR	SET_OPN
	JSR	SET_DEV
	JSR	SET_4
	BPL	LOAD_MAIN
GO_ERR	JMP	IOERROR
NO_BIN	LDY	#181
	BNE	GO_ERR
;
;Main load Loop
;
LOAD_MAIN	JSR	READ2
	LDX	BAL
	INX
	BNE	NO_BIN
	LDX	BAH
	INX
	BNE	NO_BIN
	JSR	SET_DEST
;
GET_FIL	LDA	#<EPRDN
	STA	INITAD
	LDA	#>EPRDN
	STA	INITAD+1
	JSR	READ2
	LDX	BAL
	INX
	BNE	NOT_FF
	LDX	BAH
	INX
	BNE	NOT_FF
	JSR	READ2
NOT_FF	LDA	BAL
	STA	STL
	LDA	BAH
	STA	STH
	LDX	COUNT
	BNE	PASS2
	INC	COUNT
	STA	ADDRESS+1
	LDA	STL
	STA	ADDRESS
PASS2	JSR	READ2
	LDA	BAL
	SEC
	SBC	STL
	STA	BLL
	LDA	BAH
	SBC	STH
	STA	BLH
		BUMP BLL
	JSR	GET_DATA
	BMI	JSTART
	JSR	JINIT
	JMP	GET_FIL
;
JINIT	JMP	(INITAD)
JSTART	JSR	CLOSE1
	LDA	RUNAD
	TAX
	ORA	RUNAD+1
	BEQ	LOAD_GO
	STX	ADDRESS
	LDA	RUNAD+1
	STA	ADDRESS+1
LOAD_GO	JMP	(ADDRESS)
;
;Get DATA from file
;
GET_DATA	LDA	STL
	STA	SL
	LDA	STH
	STA	SH
;
GET_REC	LDX	#$10
	LDA	#7
CALL_CIO	STA	ICCOM,X
	LDA	SL
	STA	ICBAL,X
	LDA	SH
	STA	ICBAH,X
	LDA	BLL
	STA	ICBLL,X
	LDA	BLH
	STA	ICBLH,X
	JMP	CIOV
;
;Read 2 bytes from file
;
READ2	LDA	#<BAL
	STA	SL
	LDA	#0
	STA	SH
	STA	BLH
	LDA	#2
	STA	BLL
	BNE	GET_REC
;
;Set AUX1 to 4
;
SET_4	LDA	#4
	STA	AUX1,X
	JMP	CIOV
;
;E: Print Routine
;
;ENTER:
;A=LSB of string
;Y=MSB of string
;
;EXIT:
;A=zero
;
EPRINT	STA	FR0
	STY	FR0+1
EPL	LDY	#0
	LDA	(FR0),Y
	BEQ	EPRDN
	JSR	EPUT
	INC	FR0
	BNE	EPL
	INC	FR0+1
	BNE	EPL
EPRDN	RTS
;
;E: Put Byte Routine
;
;ENTER:
;A=character to print
;
EPUT	TAY
	LDA	EDITRV+7
	PHA
	LDA	EDITRV+6
	PHA
	TYA
	RTS
;
;E: Input Routine
;
EINPUT	LDX	#$00
	LDA	#$40
	STA	SHFLOK
;
;Get a 64 byte line in MYBUF
;
;ENTER:
;X=IOCB Index ($10,$20,...)
;
INP_MYB	LDA	#0
	STA	SL
	STA	BLH
	LDA	#64
	STA	BLL
	LDA	#5
	STA	SH
	JMP	CALL_CIO
;
;Get a Hex # from MYBUF
;
;ENTER:
;Y=offset into MYBUF where
;  the Hex # starts
;
;EXIT:
;FR0,FR0+1 = binary number
;
;
GRAB_HEX	LDA	#0
	STA	COUNT
	STA	FR0
	STA	FR0+1
G4LOOP	LDA	MYBUF,Y
	CMP	#EOL
	BEQ	HEX_OUT
	CMP	#$20
	BNE	TESTIT
HEX_OUT	LDA	COUNT
	BEQ	HEX_BAD
HEX_GOOD	CLC
	RTS
HEX_BAD	SEC
	RTS
;
TESTIT	LDX	#$0F
G4SCAN	CMP	HEXDIG,X
	BEQ	GOTG4D
	DEX
	BPL	G4SCAN
	BMI	HEX_BAD
;
GOTG4D	ASL	FR0
	ROL	FR0+1
	ASL	FR0
	ROL	FR0+1
	ASL	FR0
	ROL	FR0+1
	ASL	FR0
	ROL	FR0+1
	TXA
	ORA	FR0
	STA	FR0
	INC	COUNT
	INY
	LDA	COUNT
	CMP	#5
	BCS	HEX_BAD
	BCC	G4LOOP
;
;Close IOCB #1
;
CLOSE1	LDX	#$10
	BNE	CLOSEIT
;
;Close IOCB #2
;
CLOSE2	LDX	#$20
;
;Close Any IOCB
;
;ENTER:
;X=IOCB Index ($10,$20,...)
;
;EXIT:
;X=IOCB Index
;
CLOSEIT	TXA
	PHA
	LDA	#$0C
	STA	ICCOM,X
	JSR	CIOV
	PLA
	TAX
	RTS
;
;CP's PROMPT + INPUT Routine
;
INPUT		PRINT PROMPT
	JSR	EINPUT
	BPL	INPUTLV
	JSR	IOERROR
	JMP	INPUT
INPUTLV	LDA	MYBUF
	CMP	#EOL
	BEQ	INPUT
	RTS
;
;########################
;
;Start of Commands
;
;########################
;
;Enter Cart
;
GOCART	LDA	TRAMSZ
	BNE	TRY_CART
	LDA	#<NOCART
	LDY	#>NOCART
	JMP	EPRINT
TRY_CART	JMP	($BFFA)
;
;Kill CP
;
KILL	JSR	UNHOOK
	STA	WARMST
	JSR	GOCART
	JMP	(DOSVEC)
;
;Un-Hook OS Patches
;
UNHOOK	LDA	#$FF
	STA	DOSVEC
CP_HI	LDA	#$FF
	STA	DOSVEC+1
	LDA	RESET+1
	STA	DOSINI
	LDA	RESET+2
	STA	DOSINI+1
	LDY	INDEX
	LDA	#<EDITRV
	STA	HATABS,Y
	LDA	#>EDITRV
	STA	HATABS+1,Y
OLD_ML	LDA	#$FF
	STA	MEMLO
OLD_MH	LDA	#$FF
	STA	MEMLO+1
	LDA	#0
	STA	SETFLAG
	RTS
;
;Erase a File
;
ERASE	LDA	#33
	BNE	DOXIO
;
;Lock a File
;
PROTECT	LDA	#35
	BNE	DOXIO
;
;Unlock a File
;
UNPROTECT	LDA	#36
	BNE	DOXIO
;
;Rename a File
;
RENAME	JSR	FINDFILE
	LDY	LNPOS
	JSR	FINDARG
	LDX	XSAV
	LDA	#',
	STA	FNAME,X
REN_LP	LDA	MYBUF,Y
	STA	FNAME+1,X
	INX
	INY
	CMP	#EOL
	BNE	REN_LP
	LDA	#32
	PHA
	BNE	XIO_ENT
;
;Perform an XIO
;
;ENTER:
;A=XIO Number
;Y=Offset to Filename in MYBUF
;
DOXIO	PHA
	JSR	FINDFILE
XIO_ENT	JSR	CLOSE1
	PLA
	STA	ICCOM,X
	JSR	SET_DEV
	STA	AUX1,X
	JSR	CIOV
	BMI	IOERROR
	RTS
;
;Set ICBAL/H to DEVICE
;
;ENTER:
;X=IOCB Index
;
SET_DEV	LDA	#<DEVICE
	STA	ICBAL,X
	LDA	#>DEVICE
	STA	ICBAH,X
	LDA	#0
	STA	AUX2,X
	RTS
;
;Handle I/O error
;
;ENTER:
;Y=I/O Error #
;
;EXIT:
;Channel #1 is closed
;
IOERROR	STY	FR0
IO_ERR	LDA	#0
	STA	FR0+1
	JSR	CLOSE1
	JSR	IFP
	JSR	FASC
	LDY	#$FF
IOERR	INY
	LDA	(INBUFF),Y
	STA	ERBUF,Y
	BPL	IOERR
	AND	#$7F
	STA	ERBUF,Y
	LDA	#EOL
	STA	ERBUF+1,Y
	LDA	#0
	STA	ERBUF+2,Y
	LDA	#<ERTXT
	LDY	#>ERTXT
	JMP	EPRINT
;
;This will grab a filename from
;MYBUF and put it in the
;device buffer.
;
;ENTER:
;Y=Offset to Filename in MYBUF
;
FINDFILE	LDA	DEFDEV
	STA	DEVICE
	LDA	DEFDEV+1
	STA	DEVICE+1
;
FIND1	LDX	#0
	LDA	MYBUF+1,Y
	CMP	#':
	BEQ	X2
	LDA	MYBUF+2,Y
	CMP	#':
	BNE	FIND2
	LDA	MYBUF+1,Y
	STA	DEVICE+1
	LDA	MYBUF,Y
	STA	DEVICE
	INY
	INY
	INY
	BNE	FIND2
;
X2	LDA	MYBUF,Y
	STA	DEVICE
	INY
	INY
;
FIND2	LDA	MYBUF,Y
	STA	FNAME,X
	CMP	#EOL
	BEQ	FIND3
	CMP	#$20
	BEQ	FIND3
	INY
	INX
	CPX	#13
	BNE	FIND2
FIND3	LDA	#EOL
	STA	FNAME,X
	LDA	#0
	STA	FNAME+1,X
	STX	XSAV
	RTS
;
;This handles the 'RUN' command
;
MEMRUN	LDA	MYBUF,Y
	CMP	#EOL
	BEQ	RUN_IT
;
PULL_IT	JSR	GRAB_HEX
	BCS	BAD_RUN
	LDA	FR0
	STA	ADDRESS
	LDA	FR0+1
	STA	ADDRESS+1
RUN_IT	JMP	(ADDRESS)
BAD_RUN	LDY	#180
MEM_ERR	JMP	IOERROR
;
;Get disk Directory
;
DIRECT	LDA	#6
	BNE	DIR_GO
;
;Get a TYPE of a File
;
TYPE	LDA	#4
DIR_GO	STA	DIR_COM+1
	JSR	FINDFILE
	LDA	DEVICE+3
	CMP	#EOL
	BNE	OPEN_DIR
	LDX	#3
CP_DIR	LDA	DIRNAM,X
	STA	DEVICE+3,X
	DEX
	BPL	CP_DIR
;
OPEN_DIR	JSR	CLOSE1
	JSR	SET_OPN
	JSR	SET_DEV
DIR_COM	LDA	#6
	STA	AUX1,X
	JSR	CIOV
	BMI	MEM_ERR
;
DIROK	LDX	#$10
	JSR	INP_MYB
	BMI	DIRDONE
	LDY	#0
DIRCK1	LDA	MYBUF,Y
	CMP	#EOL
	BEQ	DIRCK2
	INY
	BNE	DIRCK1
DIRCK2	LDA	#0
	STA	MYBUF+1,Y
		PRINT MYBUF
	JMP	DIROK
DIRDONE	JMP	CLOSE1
;
;Set Destroy Flag
;
SET_DEST	LDA	#0
	STA	WARMST
	RTS
;
;Add File Extension
;
;ENTER:
;A=LSB of extension
;Y=MSB of extension
;
ADD_EXT	STA	FR0
	STY	FR0+1
	LDX	#$FF
	LDY	#4
;
EXT_SCAN	INX
	LDA	FNAME,X
	CMP	#'.
	BEQ	EXT_RTS
	CMP	#EOL
	BNE	EXT_SCAN
EXT_ADD	LDA	(FR0),Y
	STA	FNAME,X
	INX
	DEY
	BPL	EXT_ADD
EXT_RTS	RTS
;
;This is where RESET comes
;
RESET	JSR	$FFFF
	JSR	UNHOOK
;
HOOKUP	LDX	#$00
	JSR	CLOSEIT
	JSR	SET_OPN
	LDA	#<EDEV
	STA	ICBAL
	LDA	#>EDEV
	STA	ICBAH
	STX	AUX2
	LDA	#12
	STA	AUX1
	JSR	CIOV
;
HOOK1	CLD
	LDY	EDITRV+4
	LDX	EDITRV+5
	INY
	BNE	NO_UPX
	INX
NO_UPX	STY	EGET+1
	STX	EGET+2
	LDY	#0
;
FIND_E	LDA	HATABS,Y
	CMP	#'E
	BEQ	GOT_E
	INY
	INY
	INY
	CPY	#33
	BCC	FIND_E
;
GOT_E	INY
	STY	INDEX
	LDA	#<NEW_E.HAN
	STA	HATABS,Y
	LDA	#>NEW_E.HAN
	STA	HATABS+1,Y
;
	LDX	#$50
	JSR	CLOSEIT
	LDY	#$0F
COPY_E	LDA	EDITRV,Y
	STA	NEW_E.HAN,Y
	LDA	IOCB5,Y
	STA	BAT_IOCB,Y
	DEY
	BPL	COPY_E
;
	LDA	#<[BAT_GET-1]
	STA	NEW_E.HAN+4
	LDA	#>[BAT_GET-1]
	STA	NEW_E.HAN+5
;
SKIP_BAT	LDA	SETFLAG
	BNE	INIT_RTS
	INC	SETFLAG
	LDA	DOSINI
	STA	RESET+1
	LDA	DOSINI+1
	STA	RESET+2
	LDA	#<RESET
	STA	DOSINI
	LDA	#>RESET
	STA	DOSINI+1
;
	LDA	DOSVEC
	STA	UNHOOK+1
	LDA	DOSVEC+1
	STA	CP_HI+1
	LDA	#<GO_CP
	STA	DOSVEC
	LDA	#>GO_CP
	STA	DOSVEC+1
;
	LDA	MEMLO
	STA	OLD_ML+1
	LDA	MEMLO+1
	STA	OLD_MH+1
	LDA	#<PROGEND
	STA	MEMLO
	LDA	#>PROGEND
	STA	MEMLO+1
INIT_RTS	RTS
;
;COMMAND PROCESSOR ENTRY
;
GO_CP	JSR	HOOK1
	LDA	#$FF
	STA	WARMST
;
MAIN	CLD
	JSR	INPUT	;get line
	LDA	MYBUF
	CMP	#'*	;Batch?
	BNE	NO_BAT
	JMP	BATCH
;
NO_BAT	CMP	#';
	BEQ	MAIN
	LDY	#0
	JSR	FINDFILE
	LDA	DEVICE+3
	CMP	#EOL
	BNE	NO_REM
	LDA	DEVICE
	STA	DEFDEV
	LDA	DEVICE+1
	STA	DEFDEV+1
	JMP	MAIN
;
NO_REM	LDA	#<COMTAB
	STA	FR0
	LDA	#>COMTAB
	STA	FR0+1
	LDX	#0
COMLP	LDY	#0
COMCK	LDA	MYBUF,Y
	CMP	(FR0),Y
	BNE	TRYNEXT
	INY
	CPY	#3
	BNE	COMCK
;
	LDA	COMADRL,X
	STA	COMJSR+1
	LDA	COMADRH,X
	STA	COMJSR+2
	JSR	FINDARG
COMJSR	JSR	$FFFF
	JMP	MAIN
;
TRYNEXT	LDA	FR0
	CLC
	ADC	#3
	STA	FR0
	BCC	TRY_NH
	INC	FR0+1
TRY_NH	INX
	CPX	#NUMCOM
	BNE	COMLP
	JSR	LOADIT
	JMP	MAIN
;
;Find an Argument on Line
;
;ENTER:
;Y=Offset to start search
;
;EXIT:
;Y=1st char of argument
;
FINDARG	LDA	MYBUF,Y
	CMP	#$20
	BEQ	NEXTARG
	CMP	#EOL
	BEQ	NEXTARG
	INY
	BNE	FINDARG
NEXTARG	LDA	MYBUF,Y
	CMP	#$20
	BNE	FOUNDARG
	INY
	BNE	NEXTARG
FOUNDARG	STY	LNPOS
	RTS
;
;Handle a BATCH File
;
BATCH	LDY	#0
	LDA	#$20
	STA	MYBUF
	JSR	FINDARG
	JSR	FINDFILE
	LDA	#<BAT
	LDY	#>BAT
	JSR	ADD_EXT
BAT_GO	LDA	#12
	JSR	BAT_CIO
;
	LDA	#<DEVICE
	STA	ICBALB
	LDA	#>DEVICE
	STA	ICBAHB
	LDA	#4
	STA	AUX1B
	LDA	#3
	JSR	BAT_CIO
	BPL	BAT_MAIN
	LDA	#12
	STY	FR0
	JSR	BAT_CIO
	JSR	IO_ERR
BAT_MAIN	JMP	MAIN
BAT_9B	LDA	#EOL
	BNE	BAT_XIT
;
BAT_GET	LDA	BAT_IOCB
	BPL	BAT_PROC
BAT_NORM	LDX	#$00
	LDY	#1
EGET	JMP	$FFFF
;
BAT_PROC	LDA	#0
	STA	ICBLLB
	STA	ICBLHB
	LDA	#7
	JSR	BAT_CIO
	BMI	BAT_NORM
	LDA	BAT_ZIO+15
	PHA
	JSR	EPUT
	PLA
BAT_XIT	LDX	#$00
	LDY	#1
	RTS
;
;Perform BATCH CIO
;
BAT_CIO	STA	ICCOMB
	JSR	BAT_SWAP
	LDX	#$50
	JSR	CIOV
	STA	BAT_ZIO+15
	BPL	BAT_SWAP
	TYA
	PHA
	LDX	#$50
	JSR	CLOSEIT
	PLA
	TAY
;
;Swap IOCB Blocks
;
BAT_SWAP	TYA
	PHA
	LDY	#$0F
BAT_SLP	LDA	ZIOCB,Y
	PHA
	LDA	BAT_ZIO,Y
	STA	ZIOCB,Y
	PLA
	STA	BAT_ZIO,Y
	LDA	IOCB5,Y
	PHA
	LDA	BAT_IOCB,Y
	STA	IOCB5,Y
	PLA
	STA	BAT_IOCB,Y
	DEY
	BPL	BAT_SLP
	PLA
	TAY
	RTS
;
;Set COPY IOCB
;
;ENTER:
;X=IOCB Index
;A=CIO Command
;
;EXIT:
;CIO set for I/O of 12K block
;at $3000
;
SET_CPY	STA	ICCOM,X
	LDA	#0
	STA	ICBLL,X
	STA	ICBAL,X
	LDA	#$30
	STA	ICBLH,X
	STA	ICBAH,X
	RTS
;
;Set ICCOM for Open
;
;ENTER:
;X=IOCB Index
;
SET_OPN	LDA	#3
	STA	ICCOM,X
	RTS
;
;Copy I/O Error
;
;ENTER:
;Y=CIO Error #
;
;EXIT:
;Channels #1 and #2 are closed
;
CPY_IOR	JSR	IOERROR
	JMP	CLOSE2
;
;Handle COPY Verb
;
COPY	JSR	FINDFILE
	JSR	CLOSE1
	JSR	SET_DEV
	JSR	SET_OPN
	JSR	SET_4
	BMI	CPY_IOR
		PRINT DEVICE
	LDY	LNPOS
	JSR	FINDARG
	JSR	FINDFILE
	JSR	CLOSE2
	JSR	SET_DEV
	JSR	SET_OPN
	LDA	#8
	STA	AUX1,X
	JSR	CIOV
	BMI	CPY_IOR
;
	JSR	SET_DEST
COPY.2	LDX	#$10
	LDA	#7
	JSR	SET_CPY
	JSR	CIOV
	BMI	EOF
	LDA	#1
	STA	COUNT
	BNE	SAVLEN
;
EOF	LDA	#0
	STA	COUNT
;
SAVLEN	LDA	ICBLL,X
	STA	LENSAV
	LDA	ICBLH,X
	STA	LENSAV+1
	LDX	#$20
	LDA	#11
	JSR	SET_CPY
	LDA	LENSAV
	STA	ICBLL,X
	LDA	LENSAV+1
	STA	ICBLH,X
	JSR	CIOV
	LDA	COUNT
	BNE	COPY.2
	JSR	CLOSE1
	JMP	CLOSE2
;
;Program Text/Buffers
;
NOCART	.BYTE	"No Cart",EOL,0
PROMPT	.BYTE	EOL
DEFDEV	.BYTE	"D1:",0
DIRNAM	.BYTE	"*.*",EOL
EDEV	.BYTE	"E:",EOL
ERTXT	.BYTE	"Error- "
ERBUF	.BYTE	"   ",EOL,0
HEXDIG	.BYTE	"0123456789"
	.BYTE	"ABCDEF"
COM	.BYTE	EOL,"MOC."
BAT	.BYTE	EOL,"TAB."
;
;Command Tables
;
COMTAB	.BYTE	"ERAPROUNPREN"
	.BYTE	"DIRCOPRUN"
	.BYTE	"CARTYPKIL"
;
COMADRL	.BYTE	<ERASE
	.BYTE	<PROTECT
	.BYTE	<UNPROTECT
	.BYTE	<RENAME
	.BYTE	<DIRECT
	.BYTE	<COPY
	.BYTE	<MEMRUN
	.BYTE	<GOCART
	.BYTE	<TYPE
	.BYTE	<KILL
;
COMADRH	.BYTE	>ERASE
	.BYTE	>PROTECT
	.BYTE	>UNPROTECT
	.BYTE	>RENAME
	.BYTE	>DIRECT
	.BYTE	>COPY
	.BYTE	>MEMRUN
	.BYTE	>GOCART
	.BYTE	>TYPE
	.BYTE	>KILL
;
ADDRESS	.WORD	EPRDN	;RUN Addr
DEVICE	.BYTE	"D1:"
;
;Buffers
;
FNAME	.BYTE	"AUTORUN.BAT"
	.BYTE	EOL,0
	.DS	17
INDEX	.DS	1	;HATABS Index
SETFLAG	.DS	1	;set up?
;
;Wedge/Handler Space
;
;For Batch Processing
;
BAT_ZIO	.DS	16	;Zpage IOCB
NEW_E.HAN	.DS	16	;E: Handler
BAT_IOCB	.DS	16	;IOCB #5 Copy
ICCOMB	=	BAT_IOCB+2
ICBALB	=	BAT_IOCB+4
ICBAHB	=	BAT_IOCB+5
ICBLLB	=	BAT_IOCB+8
ICBLHB	=	BAT_IOCB+9
AUX1B	=	BAT_IOCB+10
;
PROGEND	=	*
T_LENGTH	=	PROGEND-ORIGIN
;
;Entry Point to Start CP
;
ENTRY	LDX	#0
	STX	SETFLAG
	STX	WARMST
	INX
	STX	BOOT?
	JSR	HOOKUP
		PRINT CREDITS
	JSR	CLOSE2
	JSR	SET_OPN
	JSR	SET_DEV
	JSR	SET_4
	PHP
	JSR	CLOSE2
	PLP
	BPL	HAV_BAT
	LDA	TRAMSZ
	BNE	G_CART
	JMP	(DOSVEC)
G_CART	JMP	($BFFA)
HAV_BAT		PRINT PROMPT
		PRINT FNAME
	PLA
	PLA
	JMP	BAT_GO
;
CREDITS	.BYTE	$7D,EOL
	.BYTE	"BBK CP - (C) 1987 "
	.BYTE	"ANALOG Computing",EOL
	.BYTE	"by: Bryan Schappel"
	.BYTE	EOL,0
;
;Set Run Address
;
	*=	RUNAD
	.WORD	ENTRY
	.OPT	LIST
	.END
A.N.A.L.O.G. ISSUE 74 / JUNE 1989 / PAGE 46

Super Command Processor, Part II

by Bryan Schappel

Welcome back! This month we will discuss external commands, how external commands interface with BBKCP, and how to write your own external commands. There are also four external commands supplied with this installment. Let’s get to it.

More on External Commands

Last month we said an external command is something that the internal or memory resident portion of BBKCP does not understand. Such a command is loaded from disk each time it is called. Almost all external commands are destructive to memory, meaning that when an external command is executed any program in memory will be lost!

External commands interface directly by calling routines built into BBKCP. By doing this, filenames, addresses and numbers may be sent to an external command. Table 1 gives the name, address and description of special routines in BBKCP. These routines are called by a 6502 JSR instruction. Any parameters or initial conditions for the routines will be given also.

By using the routines in the table, we may write any number of external commands, performing almost any operation. Here are some samples.

The External Goodies

Listings 1 through 4 are the data needed to create your copies of the four external commands described below. You should type in this data using the M/L Editor on page 61. Listings 5 through 8 are the assembly language source codes for the four external commands. You need not type these listings; they are provided only for those who are interested in assembly language programming.

COMMAND #1: DISBAT**

This command will toggle the batch-file processing feature of BBKCP on or off. After the file executes, a message will be displayed telling you about the status of batch processing.

This command is not destructive to memory. It was included because certain programs and games published in ANALOG will fail to run if batch processing is left on.

COMMAND #2; DUMP [addr]

This is a memory dump utility that loads and runs at $2480. It will begin dumping the contents of memory on the screen from the address you specify. Press Start or Break to return to BBKCP.

COMMAND #3: SAVE fname start end [init run]

This allows you to perform a binary save of memory. You must provide a legal filename, a start address, an end address and optional initialize and run addresses.

COMMAND PROCESSOR
NAMEHEX ADDRESSDESCRIPTION
ADDRESS23B7 Contains the last RUN address of an external command. Contains address for the RUN command.
CLOSE11EE4 Closes IOCB #1 Returns with X=$10.
CLOSE21EE8 Closes IOCB #2. Returns with X=$20.
CLOSEIT1EEA Closes ANY IOCB. enter with X=IOCB offset. ($00, $10, $20, …)
DEFDEV2354 This is the default device and device number in the format D1.
DEVICE23B9 Contains a correct DOS filename in the format of D1:filename.ext.
EPRINT1E64 Will print a NULL terminated string to the screen. Enter with A,Y being the LO,HI of your text. (NULL=0).
FINDARG21F4 Will find the start of the next argument on the command line. Enter with Y = search offset. (i.e. Y = 3 says start search on Character 4.) Exits with Y and LNPOS = start of argument.
FINDFILE1FDB Enter with Y = start of name and DEVICE will return the filename in the D1:filename.ext format.
FNAME23BC Start of formatted filename. Same as DEVICE + 3.
FR000D4 Contains the result of a GRAB_HEX. $D4 is LO byte and $D5 is HI byte.
GOCART1F11 Tries to RUN a cartridge. Calling this is the same as issuing a CAR command.
GRAB_HEX1E9D Pulls a hex address from the command line. Enter with Y = offset. Exit: Carry Clear means good number Carry Set means bad number.
HEXDIG236B Contains the ATASCII hexadecimal digits. 0-9 and A-F.
INPUT1EF7 Prints the current prompt and accepts one 64-byte line from the screen editor.
IOERROR1FAC Closes IOCB #1 and prints the I/O error number on the screen in decimal. Enter with Y = error number.
LNPOS00DF Contains the current offset to the argument on the command line.
MYBUF0500 64-byte command line buffer.
WARMST0008 Warm start flag. If the value here is $FF, memory contents are OK. If value is $00, memory will be wiped out.

COMMAND #4: FORMAT**

This is a diskette initialization program. The menu contains five options: Format, Write DOS, Format and Write DOS, Change Drive and Exit. Just press the number next to the description to select your option. If you choose an option between 1 and 3, you are asked to insert a disk and press Return. Pressing Return begins the process; pressing any other key aborts the option, returning you to the menu.

When you choose to write DOS, FORMAT not only writes the DOS.SYS file, but it also writes the AUTORUN.SYS version of BBKCP to the disk.

Option 4 allows you to alter the drive number that the commands are being executed on. Just type the new drive number, and you are returned to the menu.

Option 5 returns you to BBKCP.

Writing External Commands

All external commands must be written in machine language, therefore you must be familiar with 6502 assembly language. Here are a couple of rules to follow.

Rule #1: Assemble all your commands with an origin not less than $2410, otherwise part of BBKCP would be overwritten, causing a system crash.

Rule #2: While a batch file is being processed never use IOCB #5. Doing so will most likely cause a system crash. This is the IOCB that the input is being redirected from—take care.

Some Tips

If you write a small external command that is less than 448 bytes long, you may load it at $0540 and set WARMST back to a $FF, thus preserving the contents of memory.

Study the source code for the external commands given in this issue. They will guide you in the method of writing your own commands. Some extra commands you may consider writing would be a multifile copy program, a disk copier or a simple assembler/disassembler. The possibilities are quite endless.


By the time you read this, Bryan and Carol will have been happily married for a while. Tlteir new apartment contains a new Mega ST2, which shares the computer room with the 800XL. The compu-kids get along very well—if you overlook the constant battle for the printer.

LISTING 1: M/L EDITOR

1000 DATA 255,255,0,5,84,5,104,104,173,8,34,201,160,240,32,169,6842
1010 DATA 160,141,8,34,169,0,141,9,34,169,169,141,10,34,169,185,5164
1020 DATA 141,247,32,169,26,141,248,32,169,3,141,249,32,208,41,169,8132
1030 DATA 76,141,247,32,141,8,34,169,51,141,248,32,169,33,141,249,8339
1040 DATA 32,169,125,141,9,34,169,33,141,10,34,172,216,35,169,0,3685
1050 DATA 153,26,3,169,228,153,27,3,76,116,228,0,0,0,0,0,8563

LISTING 2: M/L EDITOR

1000 DATA 255,255,128,36,78,37,164,223,185,0,5,201,155,208,13,173,7859
1010 DATA 181,35,133,212,173,182,35,133,213,76,156,36,32,154,30,144,5925
1020 DATA 1,96,165,212,133,203,165,213,133,204,165,204,160,0,32,8,7486
1030 DATA 37,165,203,160,2,32,8,37,160,0,132,224,177,203,72,201,8219
1040 DATA 155,208,2,169,27,153,62,37,166,224,189,71,37,168,104,32,5646
1050 DATA 8,37,164,224,200,192,8,208,225,152,24,101,203,133,203,144,1263
1060 DATA 2,230,204,162,0,169,9,141,66,3,169,33,141,68,3,169,3400
1070 DATA 37,141,69,3,169,1,141,73,3,141,254,2,32,86,228,48,4093
1080 DATA 7,173,31,208,201,7,240,162,169,0,141,254,2,96,72,41,5607
1090 DATA 15,170,189,105,35,153,34,37,104,41,240,74,74,74,74,170,4761
1100 DATA 189,105,35,153,33,37,96,48,48,48,48,32,48,48,32,48,8027
1110 DATA 48,32,48,48,32,48,48,32,48,48,32,48,48,32,48,48,6998
1120 DATA 32,48,48,32,32,32,32,32,32,32,32,32,155,5,8,11,6077
1130 DATA 14,17,20,23,26,0,0,0,0,0,0,0,0,0,0,0,1460

LISTING 3: M/L EDITOR

1000 DATA 255,255,16,36,16,37,164,223,32,212,31,164,223,32,237,33,7338
1010 DATA 32,154,30,176,47,165,212,133,204,165,213,133,205,164,223,32,2160
1020 DATA 237,33,132,203,32,154,30,176,27,165,212,133,206,165,213,133,1365
1030 DATA 207,32,221,30,32,195,34,32,149,31,169,8,157,74,3,32,1148
1040 DATA 86,228,16,3,76,221,30,32,205,36,48,248,32,205,36,48,4117
1050 DATA 243,32,252,36,48,238,165,204,133,214,165,205,133,215,165,206,4834
1060 DATA 56,229,214,133,218,165,207,229,215,133,219,230,218,208,2,230,5999
1070 DATA 219,32,10,37,48,206,164,203,32,237,33,132,203,32,154,30,6261
1080 DATA 176,194,32,241,36,169,226,133,204,169,228,133,206,169,2,133,1376
1090 DATA 205,133,207,32,252,36,48,172,32,227,36,48,167,164,203,32,7052
1100 DATA 237,33,32,154,30,176,157,32,241,36,169,224,133,204,169,226,2488
1110 DATA 133,206,169,2,133,205,133,207,32,252,36,48,135,32,227,36,6616
1120 DATA 76,221,30,169,255,72,162,16,169,0,157,72,3,157,73,3,2865
1130 DATA 169,11,157,66,3,104,76,86,228,173,17,37,32,207,36,48,2950
1140 DATA 16,173,18,37,76,207,36,165,212,141,17,37,165,213,141,18,6377
1150 DATA 37,96,169,4,133,218,169,0,133,219,133,215,169,204,133,214,2960
1160 DATA 169,11,162,16,76,55,30,0,0,0,0,0,0,0,0,0,2821

LISTING 4: M/L EDITOR

1000 DATA 255,255,128,36,199,39,173,184,35,141,90,38,160,2,185,8,4387
1010 DATA 34,153,36,39,185,30,39,153,8,34,185,247,32,153,39,39,3394
1020 DATA 185,33,39,153,247,32,136,16,229,169,65,160,38,32,97,30,3770
1030 DATA 173,90,38,141,36,38,141,55,38,141,40,38,32,13,38,48,8480
1040 DATA 251,141,20,39,56,233,49,48,243,201,5,176,239,72,169,20,7528
1050 DATA 160,39,32,97,30,133,203,104,170,240,11,202,240,14,202,240,1634
1060 DATA 17,202,240,27,208,43,32,29,37,76,163,36,32,102,37,76,996
1070 DATA 163,36,32,29,37,165,203,208,3,32,107,37,76,163,36,169,4259
1080 DATA 7,160,39,32,97,30,32,13,38,41,127,141,90,38,76,163,1936
1090 DATA 36,160,2,185,36,39,153,8,34,185,39,39,153,247,32,136,4897
1100 DATA 16,241,96,32,22,38,240,3,230,203,96,169,211,160,38,32,7305
1110 DATA 97,30,32,221,30,169,35,157,68,3,169,38,157,69,3,169,3625
1120 DATA 0,157,75,3,157,74,3,169,254,157,66,3,32,86,228,16,4187
1130 DATA 26,152,72,169,21,160,39,32,97,30,104,168,32,165,31,230,5150
1140 DATA 203,169,198,160,38,32,97,30,76,29,38,96,32,22,38,208,1382
1150 DATA 250,169,227,160,38,32,97,30,32,252,37,169,54,157,68,3,3571
1160 DATA 169,38,157,69,3,32,86,228,48,199,32,252,37,169,39,157,6527
1170 DATA 68,3,169,38,157,69,3,32,86,228,48,181,162,16,169,24,4382
1180 DATA 157,68,3,169,39,157,69,3,169,6,157,72,3,169,0,157,2891
1190 DATA 73,3,169,11,157,66,3,32,86,228,48,149,162,16,169,124,5497
1200 DATA 157,68,3,169,29,157,69,3,169,57,157,72,3,169,6,157,3461
1210 DATA 73,3,169,11,157,66,3,32,86,228,48,32,162,16,169,11,2305
1220 DATA 157,66,3,169,42,157,68,3,169,39,157,69,3,169,158,157,5599
1230 DATA 72,3,169,0,157,73,3,32,86,228,16,3,76,75,37,76,390
1240 DATA 221,30,32,221,30,32,195,34,169,8,157,74,3,169,0,157,3613
1250 DATA 75,3,96,173,37,228,72,173,36,228,72,96,169,185,160,38,8095
1260 DATA 32,97,30,32,13,38,201,155,96,68,32,58,155,68,32,58,1611
1270 DATA 65,85,84,79,82,85,78,46,83,89,83,155,68,32,58,68,1607
1280 DATA 79,83,46,83,89,83,155,125,70,79,82,77,65,84,32,85,2130
1290 DATA 84,73,76,73,84,89,155,155,68,101,118,105,99,101,32,68,3768
1300 DATA 32,58,155,155,160,205,197,206,213,160,155,49,46,32,70,111,7272
1310 DATA 114,109,97,116,155,50,46,32,87,114,105,116,101,32,68,79,2565
1320 DATA 83,155,51,46,32,70,111,114,109,97,116,32,97,110,100,32,2743
1330 DATA 87,114,105,116,101,32,68,79,83,155,52,46,32,67,104,97,2116
1340 DATA 110,103,101,32,68,114,105,118,101,32,35,155,53,46,32,69,1181
1350 DATA 120,105,116,155,155,79,112,116,105,111,110,32,62,32,0,73,1680
1360 DATA 110,115,101,114,116,32,68,73,83,75,44,32,80,114,101,115,2647
1370 DATA 115,32,82,69,84,85,82,78,0,155,155,70,111,114,109,97,4520
1380 DATA 116,116,105,110,103,46,46,46,0,155,155,87,114,105,116,105,4635
1390 DATA 110,103,32,68,79,83,46,46,46,0,155,155,87,114,105,116,3794
1400 DATA 105,110,103,32,66,66,75,67,80,46,46,46,0,78,101,119,698
1410 DATA 32,68,114,105,118,101,32,35,32,0,32,155,155,0,255,255,6460
1420 DATA 124,29,198,35,160,0,169,185,26,3,0,0,0,0,0,0,6063
1430 DATA 118,30,68,49,58,65,85,84,79,82,85,78,46,66,65,84,1198
1440 DATA 155,0,10,36,139,36,162,0,142,217,35,134,8,232,134,9,4761
1450 DATA 32,199,32,169,83,160,36,32,97,30,32,225,30,32,195,34,3067
1460 DATA 32,149,31,169,4,157,74,3,32,86,228,8,32,225,30,40,2471
1470 DATA 16,10,165,6,208,3,108,10,0,108,250,191,169,81,160,35,6332
1480 DATA 32,97,30,169,186,160,35,32,97,30,104,104,76,28,34,125,2318
1490 DATA 155,66,66,75,32,67,80,32,45,32,40,67,41,32,49,57,8250
1500 DATA 56,55,32,65,78,65,76,79,71,32,67,111,109,112,117,116,3590
1510 DATA 105,110,103,155,98,121,58,32,66,114,121,97,110,32,83,99,3578
1520 DATA 104,97,112,112,101,108,155,0,224,2,2,0,10,36,0,0,7532

LISTING 5: ASSEMBLY

	.OPT	NOLIST
;-----------------------------
;BATCH File Processing Disable
;Utility.
;
;External Command #1
;
;by: Bryan Schappel
;
;CP Call:
;DISBAT
;-----------------------------
;
;Equates
;
FIND_E	=	$20F7
BATCH	=	$2208
MAIN	=	$217D
SKIP_BAT	=	$2133
HATABS	=	$031A
INDEX	=	$23D8
RESET	=	$20C1
;
	*=	$0500
;
START	PLA
	PLA
	LDA	BATCH
	CMP	#$A0	;LDY #
	BEQ	DIS_BAT
;
;Re-enable Batch Processing
;
	LDA	#$A0	;LDY #
	STA	BATCH
	LDA	#0
	STA	BATCH+1
	LDA	#$A9	;LDA #
	STA	BATCH+2
	LDA	#$B9	;LDA HATABS,Y
	STA	FIND_E
	LDA	#<HATABS
	STA	FIND_E+1
	LDA	#>HATABS
	STA	FIND_E+2
	BNE	LEAVE
;
;Disable BATCH Processing
;
DIS_BAT	LDA	#$4C	;JMP
	STA	FIND_E
	STA	BATCH
	LDA	#<SKIP_BAT
	STA	FIND_E+1
	LDA	#>SKIP_BAT
	STA	FIND_E+2
	LDA	#<MAIN
	STA	BATCH+1
	LDA	#>MAIN
	STA	BATCH+2
	LDY	INDEX
	LDA	#$00
	STA	HATABS,Y
	LDA	#$E4
	STA	HATABS+1,Y
LEAVE	JMP	$E474

LISTING 6: ASSEMBLY

	.OPT	NOLIST
;-------------------
;MEMORY DUMPER
;External Command #2
;
;By: Bryan Schappel
;
;CP Call:
;DUMP [addr]
;-------------------
;
;Equates
;
HEXDIG	=	$2369
GRAB_HEX	=	$1E9A
CONSOL	=	$D01F
LNPOS	=	$DF
SAVEY	=	$E0
EOL	=	$9B
FR0	=	$D4
DSPFLG	=	$02FE
MYBUF	=	$0500
ADDRESS	=	$23B5
INDR	=	$CB
ICCOM	=	$0342
ICBAL	=	$0344
ICBAH	=	$0345
ICBLL	=	$0348
ICBLH	=	$0349
CIOV	=	$E456
;
	*=	$2480
;
START	LDY	LNPOS
	LDA	MYBUF,Y
	CMP	#EOL
	BNE	GET_HEX
	LDA	ADDRESS
	STA	FR0
	LDA	ADDRESS+1
	STA	FR0+1
	JMP	HEX1
;
GET_HEX	JSR	GRAB_HEX
	BCC	HEX1
	RTS
;
;Memory Dump is Here
;
HEX1	LDA	FR0
	STA	INDR
	LDA	FR0+1
	STA	INDR+1
NEXT	LDA	INDR+1
	LDY	#0
	JSR	MAKE_HEX
	LDA	INDR
	LDY	#2
	JSR	MAKE_HEX
	LDY	#0
LOOP	STY	SAVEY
	LDA	(INDR),Y
	PHA
	CMP	#EOL
	BNE	NOT_EOL
	LDA	#27
NOT_EOL	STA	HEX_BUF+29,Y
	LDX	SAVEY
	LDA	POSIT,X
	TAY
	PLA
	JSR	MAKE_HEX
	LDY	SAVEY
	INY
	CPY	#8
	BNE	LOOP
	TYA
	CLC
	ADC	INDR
	STA	INDR
	BCC	NO_HI
	INC	INDR+1
NO_HI	LDX	#$00
	LDA	#9
	STA	ICCOM
	LDA	#<HEX_BUF
	STA	ICBAL
	LDA	#>HEX_BUF
	STA	ICBAH
	LDA	#1
	STA	ICBLH
	STA	DSPFLG
	JSR	CIOV
	BMI	XIT
	LDA	CONSOL
	CMP	#7
	BEQ	NEXT
XIT	LDA	#0
	STA	DSPFLG
	RTS
;
;Make a Number Hexadeximal
;
MAKE_HEX	PHA
	AND	#$0F
	TAX
	LDA	HEXDIG,X
	STA	HEX_BUF+1,Y
	PLA
	AND	#$F0
	LSR	A
	LSR	A
	LSR	A
	LSR	A
	TAX
	LDA	HEXDIG,X
	STA	HEX_BUF,Y
	RTS
;
;Buffers
;
HEX_BUF	.BYTE	"0000 00 00 00 "
	.BYTE	"00 00 00 00 00 "
	.BYTE	"        ",EOL
POSIT	.BYTE	5,8,11,14,17,20
	.BYTE	23,26

LISTING 7: ASSEMBLY

	.OPT	NOLIST
;-------------------------------
;BINARY SAVE
;External Command #3
;
;by: Bryan Schappel
;
;CP Call:
;SAVE fname start end [init run]
;-------------------------------
;
;Equates
;
LNPOS	=	$DF
GRAB_HEX	=	$1E9A
FINDFILE	=	$1FD4
FINDARG	=	$21ED
CALL_CIO	=	$1E37
CLOSE1	=	$1EDD
SET_DEV	=	$1F95
SET_OPN	=	$22C3
RUNAD	=	$02E0
INITAD	=	$02E2
FR0	=	$D4
ICCOM	=	$0342
ICBAL	=	$0344
ICBAH	=	$0345
ICBLL	=	$0348
ICBLH	=	$0349
AUX1	=	$034A
CIOV	=	$E456
LPOS	=	$CB
S_SAVE	=	$CC
E_SAVE	=	$CE
SL	=	$D6
SH	=	$D7
BLL	=	$DA
BLH	=	$DB
;
	*=	$2410
;
START	LDY	LNPOS
	JSR	FINDFILE	;filename
	LDY	LNPOS
	JSR	FINDARG
	JSR	GRAB_HEX	;start adr
	BCS	NO_SAVE
	LDA	FR0
	STA	S_SAVE
	LDA	FR0+1
	STA	S_SAVE+1
	LDY	LNPOS
	JSR	FINDARG
	STY	LPOS
	JSR	GRAB_HEX	;end adr
	BCS	NO_SAVE
	LDA	FR0
	STA	E_SAVE
	LDA	FR0+1
	STA	E_SAVE+1
;
;Start Save
;
	JSR	CLOSE1	;open file
	JSR	SET_OPN
	JSR	SET_DEV
	LDA	#8
	STA	AUX1,X
	JSR	CIOV
	BPL	DO_SAVE
;
NO_SAVE	JMP	CLOSE1
;
DO_SAVE	JSR	PUT_FF	;send $FF
	BMI	NO_SAVE	;header
	JSR	PUT_FF
	BMI	NO_SAVE
	JSR	PUT_HEADER	;send load
	BMI	NO_SAVE	;adr's
;
	LDA	S_SAVE	;get len
	STA	SL	;to save
	LDA	S_SAVE+1
	STA	SH
	LDA	E_SAVE
	SEC
	SBC	SL
	STA	BLL
	LDA	E_SAVE+1
	SBC	SH
	STA	BLH
	INC	BLL
	BNE	N_HI
	INC	BLH
N_HI	JSR	S_SEG	;send seg
	BMI	NO_SAVE
	LDY	LPOS
	JSR	FINDARG
	STY	LPOS
	JSR	GRAB_HEX	;init adr
	BCS	NO_SAVE
	JSR	MOVE_2
	LDA	#<INITAD
	STA	S_SAVE
	LDA	#<[INITAD+2]
	STA	E_SAVE
	LDA	#>INITAD
	STA	S_SAVE+1
	STA	E_SAVE+1
	JSR	PUT_HEADER	;put addr's
	BMI	NO_SAVE
	JSR	PUT_TEMP	;init adr
	BMI	NO_SAVE
	LDY	LPOS
	JSR	FINDARG
	JSR	GRAB_HEX	;run adr
	BCS	NO_SAVE
	JSR	MOVE_2	;save it
	LDA	#<RUNAD	;headers
	STA	S_SAVE
	LDA	#<[RUNAD+2]
	STA	E_SAVE
	LDA	#>RUNAD
	STA	S_SAVE+1
	STA	E_SAVE+1
	JSR	PUT_HEADER	;send 'em
	BMI	NO_SAVE
	JSR	PUT_TEMP	;send run adr
	JMP	CLOSE1	;all done
;
;Send a $FF
;
PUT_FF	LDA	#$FF
;
;Put 1 byte to file
;
PUT_BYTE	PHA
	LDX	#$10
	LDA	#0
	STA	ICBLL,X
	STA	ICBLH,X
	LDA	#11
	STA	ICCOM,X
	PLA
	JMP	CIOV
;
;Put the TEMP location
;
PUT_TEMP	LDA	TEMP
	JSR	PUT_BYTE
	BMI	P_RTS
	LDA	TEMP+1
	JMP	PUT_BYTE
;
;Move FR0 to TEMP
;
MOVE_2	LDA	FR0
	STA	TEMP
	LDA	FR0+1
	STA	TEMP+1
P_RTS	RTS
;
;Put the Header Out
;
PUT_HEADER	LDA	#4
	STA	BLL
	LDA	#0
	STA	BLH
	STA	SH
	LDA	#S_SAVE
	STA	SL
S_SEG	LDA	#11
	LDX	#$10
	JMP	CALL_CIO
;
TEMP	.DS	2

LISTING 8: ASSEMBLY

	.OPT	NOLIST
;-------------------
;DISK FORMATTER
;External Command #4
;
;by: Bryan Schappel
;
;CP Call:
;FORMAT
;-------------------
;
;Equates
;
CLOSE1	=	$1EDD
CLOSE2	=	$1EE1
SET_DEV	=	$1F95
SET_OPN	=	$22C3
EPRINT	=	$1E61
ICCOM	=	$0342
ICBAL	=	$0344
ICBAH	=	$0345
ICBLL	=	$0348
ICBLH	=	$0349
AUX1	=	$034A
AUX2	=	$034B
CIOV	=	$E456
EOL	=	$9B
DEVICE	=	$23B7
IOERROR	=	$1FA5
ORIGIN	=	$1D7C
EPRDN	=	$1E76
ERROR	=	$CB
BATCH	=	$2208
FIND_E	=	$20F7
;
;PRINT macro
;
	.MACRO	PRINT 
	LDA	#<%1
	LDY	#>%1
	JSR	EPRINT
	.ENDM
;
	*=	$2480
;
START	LDA	DEVICE+1
	STA	MY_DEV
	LDY	#2
SV	LDA	BATCH,Y
	STA	HOLD,Y
	LDA	NORM,Y
	STA	BATCH,Y
	LDA	FIND_E,Y
	STA	HOLD+3,Y
	LDA	NORM+3,Y
	STA	FIND_E,Y
	DEY
	BPL	SV
BEGIN		PRINT TITLE
	LDA	MY_DEV
	STA	FMAT+1
	STA	DOSNAME+1
	STA	AUTO+1
;
M_LOOP	JSR	GET_KEY
	BMI	M_LOOP
	STA	OPTION
	SEC
	SBC	#'1
	BMI	M_LOOP
	CMP	#5
	BCS	M_LOOP
	PHA
		PRINT OPTION
	STA	ERROR
	PLA
	TAX
	BEQ	OPT1
	DEX
	BEQ	OPT2
	DEX
	BEQ	OPT3
	DEX
	BEQ	OPT4
	BNE	OPT5
;
;Just Format Disk
;
OPT1	JSR	FORMAT
	JMP	BEGIN
;
;Just Write DOS+BBKCP
;
OPT2	JSR	WRITE_DOS
	JMP	BEGIN
;
;Format and Write DOS
;
OPT3	JSR	FORMAT
	LDA	ERROR
	BNE	G_B
	JSR	WRITE_IT
G_B	JMP	BEGIN
;
;Get new device number
;
OPT4		PRINT NEW_DEV
	JSR	GET_KEY
	AND	#$7F
	STA	MY_DEV
	JMP	BEGIN
;
;Return to BBKCP
;
OPT5	LDY	#2
LD	LDA	HOLD,Y
	STA	BATCH,Y
	LDA	HOLD+3,Y
	STA	FIND_E,Y
	DEY
	BPL	LD
	RTS
;
;Format the Disk
;
FORMAT	JSR	PROMPT
	BEQ	GO_F
	INC	ERROR
	RTS
GO_F		PRINT F_MAT
	JSR	CLOSE1
	LDA	#<FMAT
	STA	ICBAL,X
	LDA	#>FMAT
	STA	ICBAH,X
	LDA	#0
	STA	AUX2,X
	STA	AUX1,X
	LDA	#254
	STA	ICCOM,X
	JSR	CIOV
	BPL	G_BEGIN
;
OOPS	TYA
	PHA
		PRINT EOL2
	PLA
	TAY
	JSR	IOERROR
	INC	ERROR
		PRINT H_KEY
	JMP	KEY_RET
G_BEGIN	RTS
;
;Write DOS and BBKCP
;
WRITE_DOS	JSR	PROMPT
	BNE	G_BEGIN
WRITE_IT		PRINT W_DOS
	JSR	SET_80
	LDA	#<DOSNAME
	STA	ICBAL,X
	LDA	#>DOSNAME
	STA	ICBAH,X
	JSR	CIOV
	BMI	OOPS
;
	JSR	SET_80
	LDA	#<AUTO
	STA	ICBAL,X
	LDA	#>AUTO
	STA	ICBAH,X
	JSR	CIOV
	BMI	OOPS
	LDX	#$10
	LDA	#<HEADER
	STA	ICBAL,X
	LDA	#>HEADER
	STA	ICBAH,X
	LDA	#6
	STA	ICBLL,X
	LDA	#0
	STA	ICBLH,X
	LDA	#11
	STA	ICCOM,X
	JSR	CIOV
	BMI	OOPS
	LDX	#$10
	LDA	#<ORIGIN
	STA	ICBAL,X
	LDA	#>ORIGIN
	STA	ICBAH,X
	LDA	#$39
	STA	ICBLL,X
	LDA	#$06
	STA	ICBLH,X
	LDA	#11
	STA	ICCOM,X
	JSR	CIOV
	BMI	J_ERR
	LDX	#$10
	LDA	#11
	STA	ICCOM,X
	LDA	#<END_DATA
	STA	ICBAL,X
	LDA	#>END_DATA
	STA	ICBAH,X
	LDA	#<DATLEN
	STA	ICBLL,X
	LDA	#>DATLEN
	STA	ICBLH,X
	JSR	CIOV
	BPL	J_CL
J_ERR	JMP	OOPS
J_CL	JMP	CLOSE1
;
;Set up IOCB #1
;
SET_80	JSR	CLOSE1
	JSR	SET_OPN
	LDA	#8
	STA	AUX1,X
	LDA	#0
	STA	AUX2,X
	RTS
;
;Get a Key
;
GET_KEY	LDA	$E425
	PHA
	LDA	$E424
	PHA
	RTS
;
;Prompt for a Disk
;
PROMPT		PRINT P_TXT
KEY_RET	JSR	GET_KEY
	CMP	#EOL
	RTS
;
;Program Data
;
FMAT	.BYTE	"D :",EOL
AUTO	.BYTE	"D :AUTORUN.SYS",EOL
DOSNAME	.BYTE	"D :DOS.SYS",EOL
TITLE	.BYTE	$7D,"FORMAT "
	.BYTE	"UTILITY",EOL
	.BYTE	EOL,"Device D"
MY_DEV	.BYTE	" :",EOL,EOL
	.BYTE	" MENU ",EOL
	.BYTE	"1. Format",EOL
	.BYTE	"2. Write DOS",EOL
	.BYTE	"3. Format and "
	.BYTE	"Write DOS",EOL
	.BYTE	"4. Change Drive #"
	.BYTE	EOL
	.BYTE	"5. Exit",EOL,EOL
	.BYTE	"Option > ",0
;
P_TXT	.BYTE	"Insert DISK, "
H_KEY	.BYTE	"Press RETURN",0
F_MAT	.BYTE	EOL,EOL
	.BYTE	"Formatting...",0
W_DOS	.BYTE	EOL,EOL
	.BYTE	"Writing DOS...",0
W_CP	.BYTE	EOL,EOL
	.BYTE	"Writing BBKCP...",0
NEW_DEV	.BYTE	"New Drive # ",0
OPTION	.BYTE	" "
EOL2	.BYTE	EOL,EOL,0
HEADER	.WORD	$FFFF,$1D7C,$23C6
NORM	.BYTE	$A0,$00,$A9
	.BYTE	$B9,$1A,$03
HOLD	.WORD	$00,$00,$00
;
;CP Run Stuff
;
END_DATA	.WORD	EPRDN
	.BYTE	"D1:AUTORUN.BAT"
	.BYTE	EOL,0
	.WORD	$240A
	.WORD	$248B
	LDX	#0
	STX	$23D9
	STX	$08
	INX
	STX	$09
	JSR	$20C7
	LDA	#$53	;credits
	LDY	#$24
	JSR	EPRINT
	JSR	CLOSE2
	JSR	SET_OPN
	JSR	SET_DEV
	LDA	#4
	STA	AUX1,X
	JSR	CIOV
	PHP
	JSR	CLOSE2
	PLP
	BPL	HAV_BAT
	LDA	$06
	BNE	G_CART
	JMP	($0A)
G_CART	JMP	($BFFA)
HAV_BAT	LDA	#$51	;prompt
	LDY	#$23
	JSR	EPRINT
	LDA	#$BA	;fname
	LDY	#$23
	JSR	EPRINT
	PLA
	PLA
	JMP	$221C
;
	.BYTE	$7D,EOL
	.BYTE	"BBK CP - (C) 1987 "
	.BYTE	"ANALOG Computing",EOL
	.BYTE	"by: Bryan Schappel"
	.BYTE	EOL,0
	.WORD	$02E0
	.WORD	$02
	.WORD	$240A
DATLEN	=	*-END_DATA