;    **************************************************
;    **************************************************
;    **************************************************

			.LCTL



;                         ************
	.TITLE           "COPYFILE.COM"
;                         ************


;                        Version:    1.03

;                  First Written:    08/19/89

;                  Last Modified:    11/08/89



;                          **********
;                          LABEL DATA:
;                          **********



                      VERSION	=       '1'
                      MODIF	=	'03'
                      CHANGE	=	' '

                      MONTH	=	'11'
                      DAY	=	'08'
                      YEAR	=	'89'



;                            ******
;                            SAMPLE
;                            DIALOG:
;                            ******



;	A>COPYFILE TESTFILE.TYP
;
;
;		COPYFILE UTILITY     Version:  1.02a
;
;	        Insert Source Disk <CR>: <CR>
;               Insert Object Disk <CR>: <CR>
;
;               COPY VERIFIED
;
;               Re-Insert The System Disk If Desired <CR>: <CR>
;
;		EXIT TO CP/M
;
;
;	A>



;                           *******
;                           HISTORY:
;                           *******



;	11/08/89:	Version 1.03 trims out
;			unused library routines to
;			maximize source file size
;			limit (54 K + 384 Bytes).

;	11/04/89:	Version 1.02 adds post-entry of
;			source  filename, with full
;			syntactical parsing.

;			Prompt initiated automatically,
;			by lack of source filename on 
;			command-line.

;			Improved messages.

;			Streamlined interactives.

;	09/10/89:	Version 1.01 incorporates a few
;			refinements:

;			(a)	Rig to abort auto-
;			matically, if filename's not on
;			the command-line.

;			(b)	Add a filter to elim-
;			inate "wildcards" from FCB.

;			(c)	Add option of over-
;			writing an existing object file
;			- AFTER warning the operator.

;			(d)	Convert to use temp 
;			($$$) file, until copy is
;			verified, then rename.

;	08/19/89:	Original 1.00 Version written
;			to cope with the single-drive
;			problem.

;			Devised as a one-shot method of
;			transferring a single file of
;			54K or less from one diskette
;			to another.

;			Original version is non-repeat-
;			ing, and requires source file-
;			name to be typed in WITH the 
;			command line.

;			Program aborts if a file of the
;			same name already exists on
;			the object disk.



;    **************************************************
;    **************************************************



;                          ********
;                          ASSEMBLY
;                          CONTROLS:
;                          ********



			.PABS
			.PHEX

			.RADIX	16
			.LADDR



;                         **********
;                          SYMBOLIC
;                         REFERENCES:
;                         **********



;                        CP/M  SYSTEM:
;                        ----  ------


		PAGE.0		==	0000
		BIOS.JUMP	==	PAGE.0 + 0001
		IO.BYTE		==	PAGE.0 + 0003
		USER.DRIVE	==	PAGE.0 + 0004
		BDOS.JUMP	==	PAGE.0 + 0005
		SYSTEM		==	BDOS.JUMP
		DEF.FCB		==	PAGE.0 + 005C
		DEF.DISK.BUFF	==	PAGE.0 + 0080
		TPA		==	PAGE.0 + 0100


;                        CHARACTER  I/O:
;                        ---------  ---


		WARM.BOOT	==	0
		CONS.INPUT	==	1
		CONS.OUTPUT	==	2
		LIST.CHAR	==	5
		CONS.DIRECT	==	6
		STRING.PRINT	==	9
		  END.MESSAGE	==	0
		READ.LINE	==	0A
		CONS.STATUS	==	0B

		BREAK		==	''


;                            ASCII:
;                            -----


		NULL		==	00
		BEL		==	07
		BACKSPACE	==	08
		LF		==	0A
		CR		==	0D
		SPACE		==	20
		FORMFEED	==	0C
		RUBOUT		==	7F
		DEL		==	RUBOUT
		QUESTION.MARK	==	'?'
		HUH		==	QUESTION.MARK
		CNTRL.CHAR	==	'^'


;                           UTILITY:
;                           -------


		ZERO		==	0000
		OFF		=	ZERO
		ON		=	#ZERO
		CLEAR		=	OFF
		SET		=	ON
		OK		=	ZERO
		NOT.OK		=	#ZERO


;                           MAPPING:
;                           -------


		LOAD.POINT	==	TPA

		STACK.SIZE	==	40 ; words


;                           PROGRAM:
;                           -------


		MAX.FILE.SIZE	==	01B0 ; sectors

		DRV.A.RESET	==	0001



;    **************************************************
;    **************************************************



;                          *********
;                          PROCEDURE:
;                          *********



		       .LOC   LOAD.POINT


			     FIRST:

	JMP	START


;                            LABEL:
;                            -----


..NAME:
		.ASCII	' COPYFILE.COM'

VERS.NUMBER:
		.ASCII	'Version:  '
		.BYTE	VERSION
		.BYTE	'.'
		.BYTE	MODIF / 100
		.BYTE	MODIF @ 100
		.BYTE	CHANGE
		.BYTE	END.MESSAGE

..DATE:
		.ASCII	'Date:  '
		.BYTE	MONTH / 100
		.BYTE	MONTH @ 100
		.BYTE	'/'
		.BYTE	DAY / 100
		.BYTE	DAY @ 100
		.BYTE	'/'
		.BYTE	YEAR / 100
		.BYTE	YEAR @ 100
		.BYTE	END.MESSAGE



START:
	LXI	SP, TOP.STACK

MAIN:
	LXI	D, HELLO
	CALL	FLASH
	LXI	D, VERS.NUMBER
	CALL	FLASH
	CALL	CRLF
	CALL	LFEED

	LDA	COM.TAIL.LENGTH
	LXI	H, COMMAND.TAIL
	CALL	MARK.END
	CALL	PARSE.LINE

	LDA	ARGC
	CPI	ZERO
	JRZ	PROMPT.LINE

	CPI	1
	JRZ	DISSECT.INPUT.STRING

TROUBLE:

;		BAIL OUT OF THIS, IF
;		COMMAND-TAIL IS A DUD:

	LXI	D, COMPLAIN
	CALL	FLASH

PROMPT.LINE:

	LXI	D, NAME.PROMPT
	CALL	FLASH

	MVI	A, 10
	STA	MAX.LINE
	CALL	GET.LINE
	CALL	CRLF
	CALL	LFEED

;		CHECK FOR INPUT OVERFLOW:

	LDA	CHAR.COUNT
	LXI	H, MAX.LINE
	CMP	M
	JRZ	TROUBLE

;		PARSE THE INPUT STRING

	LXI	H, LINE.IN
	CALL	MARK.END
	CALL	PARSE.LINE

	LDA	ARGC
	CPI	1
	JRNZ	TROUBLE

DISSECT.INPUT.STRING:
	CALL	ANALYZE.FILESPEC
	CPI	OK
	JRNZ	TROUBLE

SETUP.FCB:
	CALL	PREPARE.FCB

REJECT.ANY.WILDCARDS:
	LXI	H, FILENAME
	MVI	C, 0B

..SCAN:
	MOV	A, M
	CPI	'*'
	JRZ	..TROUBLE
	CPI	'?'
	JRZ	..TROUBLE

	INX	H
	DCR	C
	JRNZ	..SCAN

	JMPR	GET.SOURCE.FILE

..TROUBLE:
	LXI	D, NO.WILDCARDS
	CALL	FLASH
	JMPR	PROMPT.LINE

GET.SOURCE.FILE:
	LXI	D, CUE.SOURCE.DISK
	CALL	FLASH

;		WAIT FOR OPERATOR'S CUE:

	CALL	AWAIT.CUE

;		RESET THE DISK:

	LXI	H, DRV.A.RESET
	SHLD	DRV.VECTOR
	CALL	DISK.RESET

;		PREPARE THE DEFAULT FCB:

..A.DRIVE.SELECT:
	MVI	A, 01
	STA	DRIVE.SELECT

;		OPEN THE SOURCE FILE:

OPEN.SOURCE:
	CALL	OPEN.FILE
	CPI	OK
	JRZ	SIZE.CHECK

	LXI	D, BUM.FILENAME
	CALL	FLASH
	JMP	PROMPT.LINE

;		CHECK FILESIZE AGAINST BUFFER LIMIT:

SIZE.CHECK:
	CALL	SIZE.FILE

	LDA	FILE.LENGTH + 2
	ORA	A
	JRNZ	..SIZ1

	LHLD	FILE.LENGTH
	LXI	D, MAX.FILE + 1
	STC
	CMC
	DSBC	D
	JC	LOAD.FILE

..SIZ1:
	LXI	D, TOO.LONG
	JMP	ERR.EXIT

;		LOAD SOURCE FILE INTO THE BUFFER:
	
LOAD.FILE:
	LHLD	FILE.LENGTH
	SHLD	SIZE.SAVE
	SHLD	XFER.COUNT

	LXI	H, TRANSFER.BUFFER
	SHLD	BUFF.POINTER

	MVI	A, ZERO
	STA	SEQ.POINTER

..LD1:
	LHLD	XFER.COUNT
	LXI	D, 0
	STC
	CMC
	DSBC	D
	JRZ	CUE2

	DCX	H
	SHLD	XFER.COUNT

	LDED	BUFF.POINTER
	LXI	H, 80
	DAD	D
	SHLD	BUFF.POINTER

	CALL	SET.DMA

	CALL	SEQ.READ
	JMPR	..LD1

;		PROMPT OPERATOR FOR THE OBJECT DISK:

CUE2:
	LXI	D, CUE.OBJECT.DISK
	CALL	FLASH

	CALL	AWAIT.CUE
	CALL	LFEED

	LXI	H, DRV.A.RESET
	SHLD	DRV.VECTOR
	CALL	DISK.RESET

;		MAKE SURE THAT FILE DOESN'T EXIST YET:

SEARCH.DIRECTORY:
	CALL	OPEN.FILE
	CPI	NOT.OK
	JRZ	CREATE

	LXI	D, FILE.ALREADY.EXISTS
	CALL	FLASH

..OPTION:
	CALL	GETCHAR
	CALL	TO.UPPER

	CPI	'Y'	
	JZ	..YES
	CPI	CR
	JZ	..YES

	CPI	'N'
	JZ	..NO
	CPI	BREAK
	JZ	..NO

	JMPR	..OPTION

..YES:
	MVI	A, 'Y'
	JMP	..GO.AHEAD.ANYWAY

..NO:
	MVI	A, 'N'
	CALL	ECHO
	CALL	CRLF
	CALL	LFEED

	JMP	RECOVERY.LOOP

..GO.AHEAD.ANYWAY:
	CALL	ECHO
	CALL	CRLF
	CALL	LFEED
	MVI	A, SET
	STA	OLD.FILE.ERASE

;		OK?  THEN CREATE TEMPORARY $$$ FILE:

CREATE:
	LXI	H, FILETYPE
	LXI	D, TYPE.SAVE
	LXI	B, 3
	CALL	MOVE

	LXI	H, FILETYPE
	LXI	B, 3
	MVI	A, '$'
	CALL	FILL

	CALL	ERASE.FILE
	CALL	MAKE.FILE
	CPI	OK
	JRZ	FLUSH

	LXI	D, DIRECTORY.FULL
	JMP	ERR.EXIT

;		FLUSH FILE BUFFER TO DISK:

FLUSH:
	LHLD	SIZE.SAVE
	SHLD	XFER.COUNT

	LXI	H, TRANSFER.BUFFER
	SHLD	BUFF.POINTER

	MVI	A, ZERO
	STA	SEQ.POINTER

..FL1:
	LHLD	XFER.COUNT
	LXI	D, 0
	STC
	CMC
	DSBC	D
	JRZ	CLOSE

	DCX	H
	SHLD	XFER.COUNT

	LDED	BUFF.POINTER
	LXI	H, 80
	DAD	D
	SHLD	BUFF.POINTER

	CALL	SET.DMA

	CALL	SEQ.WRITE
	CPI	OK
	JRZ	..FL1

;		DISK/DIRECTORY OVERFLOW ROUTINE:

..DISK.OVERFLOW:
	CALL	CLOSE.FILE
	CALL	ERASE.FILE
	LXI	D, DISK.OVERFLOW
	JMP	ERR.EXIT

;		CLOSE THE $$$ OBJECT FILE:

CLOSE:
	CALL	CLOSE.FILE

;		THEN VERIFY ITS READABILITY:

CHECK:
	CALL	OPEN.FILE

	LHLD	SIZE.SAVE
	SHLD	XFER.COUNT

	MVI	A, ZERO
	STA	SEQ.POINTER

	LXI	D, DISK.BUFFER
	CALL	SET.DMA

..CHK1:
	LHLD	XFER.COUNT
	LXI	D, 0
	STC
	CMC
	DSBC	D
	JRZ	PURGE.DIRECTORY

	DCX	H
	SHLD	XFER.COUNT

	CALL	SEQ.READ
	CPI	OK
	JRZ	..CHK1

	LXI	D, NO.VERIFY
	JMP	ERR.EXIT

;		ERASE ANY PRE-EXISTING FILE:

PURGE.DIRECTORY:
	LDA	OLD.FILE.ERASE
	CPI	CLEAR
	JRZ	RE.NAME

	MVI	A, CLEAR
	STA	OLD.FILE.ERASE

	LXI	H, TYPE.SAVE
	LXI	D, FILETYPE
	LXI	B, 3
	CALL	MOVE

	CALL	ERASE.FILE

;		THEN RENAME THE $$$ FILE:

RE.NAME:
	CALL	ZERO.FCB

	LXI	H, FILENAME
	LXI	D, NEW.NAME
	LXI	B, 8
	CALL	MOVE

	LXI	H, TYPE.SAVE
	LXI	D, NEW.NAME + 8
	LXI	B, 3
	CALL	MOVE

	LXI	H, FILETYPE
	LXI	B, 3
	MVI	A, '$' 		; WIPED OUT BY "ERASE:"
	CALL	FILL		; IF EXECUTED

	CALL	RENAME.FILE

;		EXIT TO ORIGINAL SYSTEM DISK:

CUE3:
	LXI	D, CUE.SYSTEM.DISK
	CALL	FLASH

..OPTION:
	CALL	GETCHAR
	CALL	TO.UPPER

	CPI	'Y'	
	JZ	..YES
	CPI	SPACE
	JZ	..YES

	CPI	'N'
	JZ	..NO
	CPI	CR
	JZ	..NO
	CPI	BREAK
	JZ	..NO

	JMPR	..OPTION

..YES:
	MVI	A, 'Y'
	CALL	ECHO
	CALL	CRLF
	CALL	LFEED
	JMP	PROMPT.LINE

..NO:
	MVI	A, 'N'
	CALL	ECHO
	CALL	CRLF
	CALL	LFEED
	JMP	RECOVERY.LOOP

ERR.EXIT:
	CALL	FLASH

RECOVERY.LOOP:

;	PERMITS A GRACEFUL RECOVERY TO THE
;	ORIGINAL SYSTEM DISK, WHENEVER AN
;	UNRECOVERABLE CONDITION OCCURS:

	LXI	D, LOOP.MESSAGE
	CALL	FLASH

	CALL	AWAIT.CUE
	CALL	LFEED

NORM.EXIT:
	LXI	H, DRV.A.RESET
	SHLD	DRV.VECTOR
	CALL	DISK.RESET

	LXI	D, GOODBYE
	CALL	FLASH

	MVI	C, WARM.BOOT
	CALL	SYSTEM



;    **************************************************
;    **************************************************



;                           ********
;                           MESSAGES:
;                           ********



HELLO:
	.BYTE	LF, LF
	.ASCII	'     COPYFILE UTILITY    '
	.BYTE	END.MESSAGE

NAME.PROMPT:
	.ASCII	'     ENTER FILE NAME: '
	.BYTE	END.MESSAGE

COMPLAIN:
	.ASCII	'     @#!!  ARE YOU JIVING ME?'
	.BYTE	BEL
	.BYTE	CR, LF, LF
	.BYTE	END.MESSAGE

NO.WILDCARDS:
	.ASCII	'     NO WILDCARDS IN THIS GAME!'
	.BYTE	BEL
	.BYTE	CR, LF, LF
	.BYTE	END.MESSAGE

CUE.SOURCE.DISK:
	.ASCII	'     Insert Source Disk <CR>: '
	.BYTE	END.MESSAGE

BUM.FILENAME:
	.BYTE	LF
	.ASCII	/     SOURCE FILE'S NOT THERE!/
	.BYTE	BEL
	.BYTE	CR, LF, LF
	.BYTE	END.MESSAGE

TOO.LONG:
	.BYTE	LF
	.ASCII	/     SOURCE FILE'S TOO LONG!   (54 KB  Maximum)/
	.BYTE	BEL
	.BYTE	CR, LF, LF
	.BYTE	END.MESSAGE

CUE.OBJECT.DISK:
	.ASCII	'     Insert Object Disk <CR>: '
	.BYTE	END.MESSAGE

FILE.ALREADY.EXISTS:
	.ASCII	'     OBJECT DISK ALREADY CONTAINS THAT FILENAME'
	.BYTE	CR, LF
	.ASCII	'        ERASE IT?   (Yes or No?)  .  .  .  '
	.BYTE	BEL
	.BYTE	END.MESSAGE

DIRECTORY.FULL:
	.ASCII	'     DISK DIRECTORY FULL'
	.BYTE	BEL
	.BYTE	CR, LF, LF
	.BYTE	END.MESSAGE

DISK.OVERFLOW:
	.ASCII	'     DISK OVERFLOW'
	.BYTE	BEL
	.BYTE	CR, LF, LF
	.BYTE	END.MESSAGE

NO.VERIFY:
	.ASCII	/     *** WARNING:  CAN'T VERIFY THE COPY! ***/
	.BYTE	BEL
	.BYTE	CR, LF, LF
	.BYTE	END.MESSAGE

CUE.SYSTEM.DISK:
	.ASCII	'     COPY VERIFIED'
	.BYTE	CR, LF, LF
	.ASCII	'     More Files To Copy?  (Yes or No?)  .  .  .  '
	.BYTE	END.MESSAGE

LOOP.MESSAGE:
	.ASCII	'     Re-Insert The System Disk If Desired <CR>: '
	.BYTE	END.MESSAGE

GOODBYE:
	.ASCII	'     EXIT TO CP/M'
	.BYTE	CR, LF, LF
	.BYTE	END.MESSAGE



;    **************************************************
;    **************************************************



;                         ***********
;                         SUBROUTINES:
;                         ***********



;                     CONSOLE CHARACTER  I/O:
;                     ------- ---------  ---

GETCHAR:
	CALL	REG.SAVE

GETC1:
	MVI	C, CONS.DIRECT
	MVI	E, SET
	CALL	SYSTEM
	CPI	ZERO
	JRZ	GETC1

	CALL	REG.RESTORE

	RET

TO.UPPER:
	CPI	'a'
	RM
	CPI	'z' + 1
	RP
	SUI	20H

        RET

GET.LINE:
	CALL	REG.SAVE

	MVI	C, READ.LINE
	LXI	D, CONSOLE.BUFFER
	CALL	SYSTEM

	CALL	REG.RESTORE

	RET

PUTCHAR:
ECHO:
	PUSH	PSW
	CALL	REG.SAVE

	MOV	E, A
	MVI	C, CONS.OUTPUT
	CALL	SYSTEM

	CALL	REG.RESTORE
	POP	PSW

	RET

FLASH:
	CALL 	REG.SAVE

..FL1:
	LDAX	D
	CPI	END.MESSAGE
	JRZ	..FL2

	CALL	PUTCHAR
	INX	D
	JMPR	..FL1

..FL2:
	CALL	REG.RESTORE

	RET

REG.SAVE:
	XTHL
	PUSH	D
	PUSH	B
	PUSH	H

	RET

REG.RESTORE:
	POP	H
	POP	B
	POP	D
	XTHL

	RET


;                  CONSOLE UTILITY:
;                  ------- -------


CRLF:
	PUSH	PSW

	MVI	A, CR
	CALL	PUTCHAR
	MVI	A, LF
	CALL	PUTCHAR

	POP	PSW

	RET

LFEED:
	PUSH	PSW

	MVI	A, LF
	CALL	PUTCHAR

	POP	PSW

	RET

BEEP:
	PUSH	PSW

	MVI	A, BEL
	CALL	PUTCHAR

	POP	PSW

	RET


;                        DATA MANAGEMENT:
;                        ---- ----------


STRLEN:
	PUSH	H

	LXI	B, ZERO
	MVI	A, NULL

..STR1:
	CMP	M
	JRZ	..STR2

	INX	H
	INX	B
	JMPR	..STR1

..STR2:
	MOV	A, C

	POP	H

	RET

UP.CASE.STRING:

	MOV	A, M
	CPI	NULL

	RZ

	CALL	TO.UPPER
	MOV	M, A
	INX	H
	JMPR	UP.CASE.STRING

MOVE:
	MOV	A, B
	ORA	C
	RZ

	PUSH	H
	STC
	CMC
	DSBC	D
	POP	H
	JM	..UP

..DOWN:
	LDIR

	RET
..UP:
	DAD	B
	DCX	H
	XCHG
	DAD	B
	DCX	H
	XCHG

	LDDR

	RET

FILL:
	PUSH	PSW

	MOV	A, B
	ORA	C
	JRNZ	..FIL1

	POP	PSW

	RZ

..FIL1:
	POP	PSW

	MOV	M, A
	INX	H
	DCX	B
	PUSH	PSW

	MOV	A, B
	ORA	C
	JRNZ	..FIL1

	POP	PSW

	RET

SUBSCRIPT:
	CPI	ZERO
	RZ

	PUSH	D
	MVI	D, ZERO
	MOV	E, B

..SUB1:
	DAD	D
	DCR	A
	JRNZ	..SUB1

	POP	D

	RET

INDIRECT:
	PUSH	D
	MOV	E, M
	INX	H
	MOV	D, M
	XCHG
	POP	D

	RET


;                           PARSING:
;                           -------


MARK.END:

	PUSH	H
	PUSH	D

	MOV	E, A
	MVI	D, ZERO
	DAD	D
	MVI	M, NULL

	POP	D
	POP	H

	RET
	
PARSE.LINE:

	PUSH	H

	MVI	A, ZERO
	STA	ARGC

..P1:
	CALL	..NON.SPACE
	CPI	NULL
	JRZ	..P2
	CALL	..STASH.POINTER

	CALL	..NEXT.SPACE
	CPI	NULL
	JRZ	..P2
	MVI	M, NULL
	INX	H
	JMPR	..P1

..P2:
	POP H

	RET

..NON.SPACE:

	MOV	A, M
	CPI	NULL
	RZ
	CPI	SPACE
	RNZ
	INX	H
	JMPR	..NON.SPACE

..NEXT.SPACE:

	MOV	A, M
	CPI	NULL
	RZ
	CPI	SPACE
	RZ
	INX	H
	JMPR	..NEXT.SPACE

..STASH.POINTER:

	LDA	ARGC
	CPI	8
	RP

	PUSH	D
	PUSH	H

	LXI	H, ARGV
	MVI	B, 2
	CALL	SUBSCRIPT
	POP	D
	MOV	M, E
	INX	H
	MOV	M, D
	XCHG

	LDA	ARGC
	INR	A
	STA	ARGC

	POP	D

	RET

ARGC:
		.BYTE	0

ARGV:
		.WORD	0, 0, 0, 0, 0, 0, 0, 0


ANALYZE.FILESPEC:

;		SCREEN FOR 0 OR 1 "PERIOD",
;		SCREEN FOR "." FILENAME,
;		BISECT THE ARGUMENT, IF REQ'D,
;		CHECK LENGTHS OF THE "NAME"
;		AND "TYPE" FIELDS:

	LXI	H, ARGV
	CALL	INDIRECT
	SHLD	..NAME
	CALL	STRLEN
	DAD	B
	SHLD	..TYPE

	LHLD	..NAME
	CALL	..PERIOD.COUNT

	CPI	2
	JP	..TROUBLE

	CPI	ZERO
	JRZ	..OK

	CALL	STRLEN
	CPI	1
	JRZ	..TROUBLE

	CALL	..BISECT

..OK:

	LHLD	..NAME
	CALL	STRLEN
	CPI	9
	JP	..TROUBLE

	LHLD	..TYPE
	CALL	STRLEN
	CPI	4
	JP	..TROUBLE

	LXI	H, ..NAME
	LXI	D, ..TYPE
	MVI	A, OK

	RET

..TROUBLE:

	MVI	A, NOT.OK

	RET

..PERIOD.COUNT:

	PUSH	H

	MVI	B, ZERO

..PER1:
	MOV	A, M
	CPI	NULL
	JRZ	..PER3

	CPI	'.'
	JRNZ	..PER2

	INR	B

..PER2:
	INX	H
	JMPR	..PER1

..PER3:
	MOV	A, B

	POP	H

	RET

..BISECT:

	LHLD	..NAME
	MVI	A, '.'

	CCIR

	SHLD	..TYPE
	DCX	H
	MVI	M, NULL

	RET

..NAME:
	.WORD	0

..TYPE:
	.WORD	0


;                         FILE ACCESS:
;                         ---- ------


DISK.RESET:
	MVI	C, 25
	LXI	D, DRV.VECTOR
	CALL	SYSTEM

	RET

ZERO.FCB:
	LXI	H, FILE.EXTENT.NO
	MVI	C, DISK.BUFFER - FILE.EXTENT.NO
	MVI	A, ZERO

	CALL	FILL

	RET

MAKE.FILE:
	CALL	ZERO.FCB
	MVI 	C, 16
	LXI	D, FCB
	CALL	SYSTEM

	CPI	0
	JP	..OK1

..BUM:
	MVI	A, NOT.OK	; OUT OF DIRECTORY SPACE

	RET

..OK1:
	CPI	4
	JP	..BUM

	XRA	A

	RET

OPEN.FILE:
	CALL	ZERO.FCB
	MVI	C, 0F
	LXI	D, FCB
	CALL	SYSTEM
	CPI	0
	JP	..OK1

..BUM:
	MVI	A, NOT.OK	; NO MATCH FOUND

	RET

..OK1:
	CPI	4
	JP	..BUM

	XRA	A

	RET

SIZE.FILE:
	MVI	C, 23
	LXI	D, FCB
	CALL	SYSTEM

	RET

SET.DMA:
	MVI	C, 1A
	CALL	SYSTEM

	RET

SEQ.READ:
	MVI	C, 14
	LXI	D, FCB
	CALL	SYSTEM
	CPI	OK

	RZ

	MVI	A, NOT.OK

	RET

SEQ.WRITE:
	MVI	C, 15
	LXI	D, FCB
	CALL	SYSTEM
	CPI	OK

	RZ

	MVI	A, NOT.OK

	RET

CLOSE.FILE:
	MVI	C, 10
	LXI	D, FCB
	CALL	SYSTEM

	CPI	0
	JP	..OK1

..BUM:
	MVI	A, NOT.OK

	RET

..OK1:
	CPI	4
	JP	..BUM

	XRA	A

	RET

ERASE.FILE:
	CALL	ZERO.FCB
	MVI	C, 13
	LXI	D, FCB
	CALL	SYSTEM

	CPI	0
	JP	..OK1

..BUM:
	MVI	A, NOT.OK

	RET

..OK1:
	CPI	4
	JP	..BUM

	XRA	A

	RET

RENAME.FILE:
	MVI	C, 17
	LXI	D, FCB
	CALL	SYSTEM

	CPI	0
	JP	..OK1

..BUM:
	MVI	A, NOT.OK

	RET

..OK1:
	CPI	4
	JP	..BUM

	XRA	A

	RET


;                           PROGRAM:
;                           -------


AWAIT.CUE:
	CALL	GETCHAR
	CPI	BREAK
	JRNZ	..CUE1

	CALL	LFEED
	MVI	C, WARM.BOOT
	CALL	SYSTEM

..CUE1:
	CPI	CR
	JRZ	..CUE2
	CALL	BEEP
	JMPR	AWAIT.CUE

..CUE2:
	LXI	D, ..VISIBLE
	CALL	FLASH
	CALL	CRLF

	RET

..VISIBLE:
	.ASCII	'<CR>'
	.BYTE	END.MESSAGE


PREPARE.FCB:

	PUSH	D
	PUSH	H

	LXI	H, FILENAME
	MVI	A, SPACE
	LXI	B, 0BH
	CALL	FILL

	POP	H
	CALL	INDIRECT
	CALL	STRLEN
	LXI	D, FILENAME
	CALL	MOVE

	POP	H
	CALL	INDIRECT
	CALL	STRLEN
	LXI	D, FILETYPE
	CALL	MOVE

	CALL	ZERO.FCB

	LXI	H, FILENAME
	CALL	UP.CASE.STRING

	RET



;    **************************************************
;    **************************************************



;                             ***
;                             RAM:
;                             ***



		  .LOC   ( . + 0F ) & 0FFF0


			RAM.VARIABLES:


DRV.VECTOR:
		.WORD	0

SIZE.SAVE:
		.WORD	0

XFER.COUNT:
		.WORD	0

BUFF.POINTER:
		.WORD	0

TYPE.SAVE:
		.BLKB	3

OLD.FILE.ERASE:
		.BYTE	0



		  .LOC	 DEF.FCB


FCB:

	DRIVE.SELECT:
			.BLKB	1

	FILENAME:
			.BLKB	8

	FILETYPE:
			.BLKB	3

	FILE.EXTENT.NO:
			.BLKB	1

	..RESERVED.CPM:
			.BLKB	2

	EXTENT.LENGTH:
			.BLKB	1

	MAP.AREA:
			.BLKB	1

	NEW.NAME:
			.BLKB	0FH

	SEQ.POINTER:
			.BLKB	1


	RAN.POINTER:
	FILE.LENGTH:
			.BLKB	3


DISK.BUFFER:
CONSOLE.BUFFER:

	COM.TAIL.LENGTH:
	MAX.LINE:
			.BLKB	1

	COMMAND.TAIL:
	CHAR.COUNT:
			.BLKB	1

	LINE.IN:
			.BLKB	7EH



;   ***************************************************
;   ***************************************************



;                            *****
;                            STACK:
;                            *****



			    .RELOC

		    .LOC  ( . + 0F ) & 0FFF0


		   .BLKW	STACK.SIZE


			   TOP.STACK:



;    **************************************************
;    **************************************************



;                          ********
;                          TRANSFER
;                           BUFFER:
;                          ********



	               TRANSFER.BUFFER:

;	           D980 Bytes  ( 54K + 384 Bytes)

;		     BDOS BEGINS AT E300



;    **************************************************
;    **************************************************



;                        ************
;                          ASSEMBLY
;                        TERMINATION:
;                        ************



			     LAST:


	      SIZE.PROGRAM   ==   LAST - FIRST



;    **************************************************
;    **************************************************
;    **************************************************



			.END	FIRST

