;===================================================================
;	MICRO RESOURCES CP/M -- FDOS III FILE TRANSFER PROGRAM
;===================================================================
;
;
; THIS PROGRAM IS A UTILITY TO TRANSFER FILES FROM FDOS III
; SINGLE DENSITY DISKS TO CP/M DISKS OR TO TRANSFER A CP/M
; FILE TO AN FDOS III SINGLE DENSITY DISK. A PROVISION HAS
; ALSO BEEN INCLUDED TO ALLOW EXAMINATION THE DIRECTORY OF
; THE FDOS III DISKETTE. THE OPERATION OF THIS PROGRAM ASSUMES
; THAT A CP/M SYSTEM DISK IS PRESENT IN DRIVE A: AND THAT THE
; FDOS III DISK IS IN DRIVE B:. THE BIOS PRIMITIVES OF THE CP/M
; SYSTEM ARE ACCESSED DIRECTLY TO ALLOW READING AND WRITING
; OF THE SINGLE DENSITY FDOS III DISK WITH IT'S 10 TO 1 LOGICAL
; TO PHYSICAL SECTOR MAPPING.
;
; THIS PROGRAM DOES NOT PACK THE FILES OF THE FDOS III DISK
; WHEN CREATING NEW FILES UPON TRANSFER FROM A CP/M FILE.
; SUBSEQUENT PACKING MAY DONE UPON THE DESTINATION FDOS III
; SYSTEM.
;
; THE DIRECTORIES OF EITHER DISK WILL BE SCANNED FOR FILES
; OF SIMILAR NAMES BEFORE A TRANSFER IS ACTUALLY MADE. A PROMPT
; QUESTION WILL INDICATE WHEN THE FILE ALREADY EXISTS. IN THE
; CASE OF THE CP/M DISK THE INDICATED FILE MAY BE ERASED IF
; DESIRED. WITH THE FDOS III DISK A FILE WILL NOT BE DELETED
; AND THE NAME OF THE SOURCE FILE ON THE CP/M DISK WILL HAVE
; TO BE CHANGED TO A NAME NOT CURRENTLY ON THE FDOS III DISK.
; FILE NAMES OF FDOS FILES ARE A MAXIMUM OF 5 ASCII CHARACTERS
; IN LENGTH SO THE CP/M FILE TRANSFERRED TO THE FDOS III DISK
; WILL HAVE ITS NAME TRUNCATED TO THE FIRST FIVE CHARACTERS.
; THE FDOS FILE TYPE WILL ALWAYS BE SET TO 00 AS A USER TYPE
; DATA FILE.
;
; THIS PROGRAM BUFFERS SECTOR READS UP SIXTEEN IN LENGTH
; TO MAKE THE TRANSFER MORE EFFICIENT.
;
;
;
;
;*****************************************************************
;
;THIS SOFTWARE IS PROTECTED UNDER THE FOLLOWING COPYRIGHT
;AND MAY NOT BE REPRODUCED OR COPIED IN ANY FORM WITHOUT 
;SPECIFIC PERMISSION FROM MICRO RESOURCES.
;
;
;   COPYRIGHT (C) 1980
;
;
;	MICRO RESOURCES
;	MICHAEL J. KARAS
;	2468 HANSEN CT.
;	SIMI VALLEY, CA 93065
;	(805) 527-7922
;
;ANY QUESTIONS ABOUT THIS PROGRAM OR ITS APPLICATION
;CAN BE DIRECTED TO THE ABOVE ADDRESS OR TELEPHONE NUMBER.
;
;**********************************************************************
;
WBOOT	EQU	00	;CP/M WARM BOOT ENTRY ADDRESS
;
ERRLIM	EQU	10	;MAX ALLOWABLE ERRORS
; 
;DEFINE ASCII CHARACTERS USED
;
LF	EQU	10	;LINEFEED
CR	EQU	13	;CARRIAGE RETURN
; 
;
;START OF EXECUTABLE CODE
;
	ORG	100H
	CALL	START	;GO PRINT ID
	DB	'MICRO RESOURCES FILE TRANSFER UTILITY '
	DB	CR,LF,'         CP/M <----> FDOS III'
	DB	CR,LF,'           VER 1.4 5/29/80'
	DB	CR,LF,'$'
; 
START:
	POP	D	;GET ID MESSAGE
	MVI	C,PRINT
	CALL	BDOS	;PRINT ID MESSAGE
;
;INIT PRIVATE STACK
;
	LXI	H,0	;HL=0
	DAD	SP	;HL=STACK FROM CP/M
	SHLD	STACK	;..SAVE IT
	LXI	SP,STACK ;SP=MY STACK
;
;INITIALIZE THE JMPS TO CP/M BIOS
;
	CALL	INITADR
;
;SAVE PROGRAM OPTION
;
	CALL	PROCOPT
;
;MOVE THE FILENAME FROM FCB 2 TO FCB 1
;
	CALL	MOVEFCB
;
;JMP TO APPROPRIATE FUNCTION
;
	LDA	OPTION	;GET PROGRAM OPTION
;
	CPI	'R'	;READ FDOS FILE?
	JZ	FDOSRD
;
	CPI	'W'	;WRITE FDOS FILE?
	JZ	FDOSWR
;
	CPI	'D'     ;LOOK AT FDOS III DIRECTORY
	JZ	FDOSDIR
;
	CPI	'H'	;GO TO HELP FILE PRINTOUT?
	JZ	HELP
;
;INVALID OPTION
;
	JMP	BADOPT
;
;
;
* * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*				                        *
*	FDOSDIR: LISTS FDOS DIRECTORY TO CONSOLE        *
*       					        *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * *
;
;
;THE DIRECTORY OF THE SINGLE DENSITY FDOS III
;DISK IN DRIVE B: IS LISTED TO THE CONSOLE IN
;A SINGLE COLUMN FORMAT. CONSOLE I/O IS DONE
;THROUGH CP/M SO THAT THE CTL-S AND CTL-P
;FUNCTIONS WILL WORK. THE LISTING ALSO STOPS
;AFTER EACH 16 ENTRIES HAVE BEEN TYPED
;
FDOSDIR:
	CALL	ILPRT	;PRINT THE DIRECTORY HEADER LABEL
	DB	CR,LF,'FDOS III DISK DIRECTORY'
	DB	CR,LF,CR,LF
	DB	'FILENAME  TYPE TRK SEC LENGTH',CR,LF,CR,LF,0
;
	MVI	C,01H	;SELECT DISK DRIVE B:
	CALL	SELDSK	;..THROUGH BIOS ACCESS
	MVI	A,016	;SET PRINT LOOP COUNT
	STA	LISTCNT
	MVI	A,00	;SET SCAN FOR FIRST ENTRY
	JMP	FDIR2	;JUMP INTO LOOP
FDIR1:
	MVI	A,01	;SET SCAN CODE FOR NEXT ENTRY
FDIR2:
	CALL	FDIRSC	;SCAN FOR NEXT DIRECTORY ENTRY
	ORA	A	;SET FLAGES FOR RETURN CODE
	JNZ	FDEREX	;GO EXIT FOR FULL DISK DIRECTORY
	LDA	FDENT+5	;GET ENTRY TYPE BYTE
	CPI	0FFH	;MUST BE AT END OF THE LIST
	JZ	FDIREX
	CALL	PRTDIR	;PRINT THIS ENTRY
;
	LDA	LISTCNT	;GET LIST LINE COUNT
	DCR	A	;DECREMENT IT
	STA	LISTCNT	;STORE NEW COUNT BACK
	JNZ	FDIR1	;GO TO DO NEXT ENTRY
;
	CALL	ILPRT	;GIVE THE GUY A CHANCE TO STOP A LONG DIRECTORY
	DB	1,CR,LF,0
;
	MVI	A,016	;RESET PRINT LOOP COUNT
	STA	LISTCNT
	JMP	FDIR1	;GO START ON 16 MORE ENTRIES
;
FDIREX:
	CALL	ILPRT	;PRINT END OF LIST MESSAGE
	DB	CR,LF,CR,LF,'END OF FDOS III DISK DIRECTORY',CR,LF,0
FDIREX1:
	MVI	C,00H	;RESTORE SELECT OF DRIVE A:
	CALL	SELDSK	;DIRECT BIOS ACCESS
	JMP	EXIT	;DONE WITH DIRECTORY
;
FDEREX:
	CALL	ILPRT	;PRINT DISK FULL MESSAGE
	DB	CR,LF,'++FDOS III DISK DIRECTORY SPACE FULL++',CR,LF,0
;
	JMP	FDIREX1
;
;
;
;
;SCAN FDOS III DIRECTORY ROUTINE
;	ROUTINE ENTRY IS CODED TO ALLOW VARIABLE FUNCTIONS
;	CODE IS PASSED IN THE A REGISTER
;	CODES AS FOLLOWS:
;		00=OPEN SCAN FROM BEGINNING OF TRACK 0 SECTOR 4
;		01=GET NEXT DIRECTORY ENTRY
;
;	RETURN VALUE IS THE FIRST OR NEXT ENTRY AS SPECIFIED BY THE
;	FUNCTION CODE AND IS PASSED IN BUFFER "FDENT" WHICH IS 11
;	BYTES LONG.
;
;	THIS ROUTINE SCANS AND RETURNS ALL POSSIBLE ENTRIES
;	AND WHEN END OF TRACK 0 IS ENCOUNTERED AN 0FFH CODE
;	IS RETURNED IN THE ACCUMULATOR. ELSE A 00H CODE IS 
;	RETURNED.
;
;
;
FDIRSC:
	ORA	A	;SET FLAGS FOR FUNCTION CHECK
	JNZ	NEXTENT	;FOR NON-ZERO CODE JUST GET NEXT ENTRY
;
;SETUP FOR BEGINNING OF SCAN
	MVI	A,003H	;SETUP START SECTOR OF DIRECTORY-1 
	STA	FDIRSEC
	MVI	A,011	;SET CURRENT SUBSCAN COUNT TO MAX
	STA	DIRSECI
	MVI	C,00H	;SET TRACK NUMBER TO ZERO
	CALL	SETTRK
;
NEXTENT:
	LDA	DIRSECI	;GET SECTOR INDEX
	CPI	011	;AT MAXIMUM ENTRY?
	JNZ	SAMSEC	;NO STAY WITH THIS SECTOR
	LXI	H,FDIRSEC
	INR	M	;INCREMENT CURRENT SECTOR NUMBER
	MOV	A,M	;GET THE SECTOR NUMBER
	CPI	01BH	;CHECK FOR THE LAST SECTOR
	JNZ	NXTSEC	;GO AROUND THE END OF TRACK EXIT
;
	MVI	A,0FFH	;SETUP EXIT FOR END OF DIRECTORY SPACE
	RET
;
NXTSEC:
	MOV	C,A
	CALL	FRDSEC	;GO READ FDOS III SECTOR
	LXI	H,IDBUF	;MOVE INPUT BUFFER 
	LXI	D,DIRBUF;..TO DIRECTORY BUFFER
	CALL	MOVE128
	MVI	A,00
	STA	DIRSECI	;SET SECTOR INDEX TO MINIMUM
;
SAMSEC:
	LXI	H,DIRSECI
	MOV	B,M	;GET THE INDEX
	INR	M	;INCR THE SECTOR INDEX
	LXI	H,DIRBUF;POINT TO THE FDOS III DIRECTORY BUFFER
	LXI	D,011	;LENGTH OF AN ENTRY
	MOV	A,B
	CPI	00H	;CHECK FOR ILLEGAL ZERO LOOP COUNT
	JZ	SAMSEC2
SAMSEC1:
	DAD	D	;LOOP TO MAKE OFFSET INDEX
	DCR	B
	JNZ	SAMSEC1
SAMSEC2:
	LXI	D,FDENT	;POINT TO ENTRY PASS BUFFER
	MVI	B,011	;SETUP LENGTH OF DIRECTORY ENTRY
	CALL	MOVE	;GO MOVE A DIRECTORY ENTRY
	MVI	A,00H	;SET NORMAL RETURN FLAG
	RET
;
;
;
;
;DIRECTORY SCAN POINTER PARAMETERS
;
;
FDIRSEC	DB	00	;CURRENT DIRECTORY SECTOR NUMBER
DIRSECI	DB	00	;INDEX OF SCAN INTO CURRENT DIRECTORY SECTOR
DIRBUF	DS	128	;128 BYTE DIRECTORY ENTRY BUFFER
LISTCNT	DB	00	;DIRECTORY LIST ENTRY COUNT
;
;
;
;PRINT DIRECTORY ENTRY SUBROUTINE
;
;
PRTDIR:
	LXI	H,FDENT	;POINT TO DIRECTORY ENTRY BUFFER
	MVI	A,'B'
	CALL	CTYPE	;PRINT OUT DRIVE DESIGNATOR
	MVI	A,':'
	CALL	CTYPE
	MVI	B,05	;FILE NAME CHARACTER COUNT
NAMLP:
	MOV	A,M	;GET NAME CHARACTER
	CALL	CTYPE
	INX	H	;INCREMENT BUFFER POINTER
	DCR	B
	JNZ	NAMLP	;GO FOR NEXT NAME CHAR
;
	CALL	SP4	;FOUR SPACES
	MOV	A,M	;GET TYPE BYTE
	CALL	HEXO	;SHOW IT
	INX	H	;INCREMENT THE BUFFER POINTER
;
	CALL	SP3	;THREE SPACES
	MOV	A,M	;GET START TRACK ADDRESS
	CALL	HEXO	;SHOW IT
	INX	H	;INCR THE BUFFER POINTER
;
	CALL	SP2	;TWO SPACES
	MOV	A,M	;GET START SECTOR NUMBER
	CALL	HEXO	;SHOW IT
	INX	H	;INCR THE BUFFER POINTER
;
	CALL	SP2	;FINALLY TWO LAST SPACES
	PUSH	D
	MOV	D,M	;GET MSB OF LENGTH
	INX	H
	MOV	E,M	;GET LSB OF LENGTH
	DCX	D	;DECREMENT LENGTH FOR CRAZY FDOS
	MOV	A,D	;PRINT MSB OF ADJ LENGTH
	CALL	HEXO	
	MOV	A,E	;PRINT LSB OF ADJ LENGTH
	CALL	HEXO
	POP 	D
;
	CALL	CRLF	;GET READY FOR NEXT LINE
	RET
;
;
;CONSOLE SPACE PRINTING ROUTINE
;
SP5:
	MVI	A,' '	;5 SPACES
	CALL	CTYPE
SP4:
	MVI	A,' '	;4 SPACES
	CALL	CTYPE
SP3:
	MVI	A,' '	;3 SPACES
	CALL	CTYPE
SP2:
	MVI	A,' '	;2 SPACES
	CALL	CTYPE
SP1:
	MVI	A,' '	;1 SPACE
	CALL	CTYPE
	RET
;
;
;
;
* * * * * * * * * * * * * * * * * * * * *
*					*
*	FDOSWR: COPIES FILE TO FDOS     *
*					*
* * * * * * * * * * * * * * * * * * * * *
;
;THE CP/M FILE SPECIFIED IN THE COMMAND
;IS TRANSFERRED TO THE FDOS III DISK IN DRIVE B:
;
FDOSWR:
	CALL	OPENFIL	;OPEN THE FILE
	MVI	C,01	;SELECT DRIVE B:
	CALL	SELDSK
	MVI	A,00H	;SET FDOS FILE EXIST FLAG FALSE
	STA	FEFLG
	MVI	A,00H	;SETUP FOR DIRECTORY SCAN
	JMP	SCAN2	;JUMP INTO LOOP
SCAN1:
	MVI	A,01H	;SET SCAN CODE FOR NEXT ENTRY
SCAN2:
	CALL	FDIRSC	;SCAN FOR NEXT DIRECTORY ENTRY
	ORA	A	;SET FLAGS FOR RETURN CODE
	JNZ	FDIRFUL	;EXIT FOR FULL DIRECTORY
	MVI	B,05	;SETUP COMPARE OF FILE NAMES
	LXI	D,FCB+1	;..FOR 5 CHAR FROM CP/M FCB
	LXI	H,FDENT	;..TO FDOS III DIRECTORY ENTRY
	CALL	COMPARE	;GO DO THE COMPARE
	ORA	A	;CHECK	RETURN FLAG
	JZ	FNOMAT	;IF ZERO SKIP FLAG SET
	MVI	A,0FFH	;SET FILE EXISTS FLAG
	STA	FEFLG
FNOMAT:
	LDA	FDENT+5	;GET ENTRY TYPE BYTE
	CPI	0FFH	;ARE WE AT END OF LIST?
	JNZ	SCAN1	;IF NOT AT END THEN GO GET NEXT ENTRY
;
	LDA	FEFLG	;GET FLAG TO SEE IF FILE EXISTED
	ORA	A
	JNZ	FEXEX	;GO EXIT WITH FILE EXISTS MESSAGE
	MVI	B,11	;MOVE END ENTRY INTO THE END HOLDING AREA
	LXI	H,FDENT
	LXI	D,ENDENT
	CALL	MOVE
	MVI	B,05	;MOVE FILE NAME INTO FDOS DIRECTORY ENTRY
	LXI	H,FCB+1
	LXI	D,FDENT
	CALL	MOVE
	MVI	A,00	;SET THE NEW FILE TYPE TO ZERO AS USER DATA
	STA	FDENT+5
	LXI	H,0000	;SET INITIAL FILE LENGTH TO ZERO
	SHLD	FDENT+8
SENDLP:
	CALL	RDSECT	;READ A SECTOR
	JC	UPDATD	;UPDATE FDOS III DIRECTORY IF DONE
	LXI	H,080H	;MOVE SECTOR FROM CPM AREA
	LXI	D,ODBUF
	CALL	MOVE128
	MVI	C,01	;SELECT DISK DRIVE B:
	CALL	SELDSK
	LDA	ENDENT+6
	MOV	C,A	;GET AND SET TRACK NUMBER
	CALL	SETTRK
	LDA	ENDENT+7
	MOV	C,A	;GET SECTOR AND WRITE IT ON B:
	CALL	FWRSEC
;
	LDA	ENDENT+7  ;INCREMENT SECTOR NUMBER
	INR	A
	STA	ENDENT+7
	CPI	01BH	;CHECK IF TRACK FULL
	JC	SAMTRK	;NO, THEN STAY WITH THIS ONE
	MVI	A,01H	;SET SECTOR BACK IF NEW TRACK
	STA	ENDENT+7
	LDA	ENDENT+6  ;INCREMENT TRACK NUMBER
	INR	A
	STA	ENDENT+6
	CPI	04DH	;CHECK TRACK NUMBER FOR FULL DISK
	JNC	DSKFUL
;
SAMTRK:
	LHLD	FDENT+8	;GET CURRENT WRITTEN FILE SIZE
	XCHG		;CHANGE SIGNIFICANT ORDER
	MOV	L,D
	MOV	H,E
	INX	H	;INCREMENT BLOCK COUNT
	XCHG		;CHANGE ORDER BACK
	MOV	L,D
	MOV	H,E
	SHLD	FDENT+8	;SAVE NEW BLOCK COUNT
	JMP	SENDLP	;GO DO NEXT SECTOR
;
;FILE WRITTEN, NOW UPDATE THE DIRECTORY
;
UPDATD:
	XRA	A	;INITIALIZE TWO SECTOR UPDATE FLAG
	STA	U2SEC
;
	LHLD	FDENT+8	;GET CURRENT WRITTEN FILE SIZE
	XCHG		;CHANGE SIGNIFICANT ORDER
	MOV	L,D
	MOV	H,E
	INX	H	;INCREMENT BLOCK COUNT
			;ONE LAST TIME FOR COMPATABILITY
			;WITH CRAZY FDOS
	XCHG		;CHANGE ORDER BACK
	MOV	L,D
	MOV	H,E
	SHLD	FDENT+8	;SAVE NEW BLOCK COUNT
;
	LXI	H,DIRBUF ;MOVE DIRECTORY SECTOR TO OUTPUT BUFFER
	LXI	D,ODBUF
	CALL	MOVE128
	LDA	DIRSECI	;GET DIRECTORY SECTOR INDEX	
	LXI	H,ODBUF-11
	LXI	D,11	;MAKE INSERT POINTER FOR NEW ENTRY
UPDAT:
	DAD	D
	DCR	A
	JNZ	UPDAT
;
	XCHG		;PUT INSERT POINTER IN DE
	LXI	H,FDENT	;POINT TO NEW DIRECTORY ENTRY
	MVI	B,11	;LENGTH OF DIRECTORY ENTRY
	CALL	MOVE	;MOVE INTO OUTPUT BUFFER
	LDA	DIRSECI	;SEE IF NEW ENTRY IS LAST IN SECTOR
	CPI	011
	JNZ	ONESEC	;JUMP TO PUT END ENTRY IN THIS SECTOR
;
	MVI	A,0FFH	;SET U2SEC FLAG
	STA	U2SEC
	JMP	WDIRSEC	;GO WRITE CURRENT SECTOR
;
ONESEC:
	LXI	H,ENDENT ;PUT END ENTRY INTO THIS SECTOR
	MVI	B,11	;ENTRY LENGTH-- DE OK FROM PREVIOUS MOVE
	CALL	MOVE	;PUT IT IN
;
WDIRSEC:
	MVI	C,01	;SELECT DRIVE B:
	CALL	SELDSK
	MVI	C,00	;GO TO TRACK OF DIRECTORY
	CALL	SETTRK
	LDA	FDIRSEC	;GET THE DIRECTORY SECTOR NUMBER
	MOV	C,A
	CALL	FWRSEC	;GO WRITE THE SECTOR OF DIRECTORY
	LDA	U2SEC	;CHECK IF WE SHOULD UPDATE TWO SECTORS
	ORA	A
	JNZ	GETSEC	;IF SO GO PREPARE FOR IT
;
	JMP	DONE	;ALL DONE
;
GETSEC:
	XRA	A
	STA	U2SEC	;RESET UPDATE TWO SECTORS FLAG
	LDA	FDIRSEC	;GET CURRENT DIRECTORY SECTOR NUMBER
	INR	A
	STA	FDIRSEC	;STORE THIS NEW ONE AWAY
	CPI	01BH	;SEE IF DIRECTORY FULL HERE
	JZ	UDFULL	;GO PRINT EXIT MESSAGE
	MOV	C,A
	CALL	FRDSEC	;GO READ NEXT SECTOR
	LXI	H,IDBUF	;MOVE INPUT BUFFER TO OUTPUT BUFFER
	LXI	D,ODBUF
	CALL	MOVE128
	MVI	B,11	;PUT IN ENDING ENTRY IN FIRST SLOT OF SECTOR
	LXI	H,ENDENT
	LXI	D,ODBUF
	CALL	MOVE
	JMP	WDIRSEC	;GO WRITE THE SECOND UPDATED SECTOR
;
;
;EXIT POINT FROM WRITE IF FDOS III DIRECTORY IS FULL UPON UPDATE
;
UDFULL:
	CALL	ILPRT	;PRINT DIRECTORY FULL MESSAGE
	DB	CR,LF,'++FDOS III DIRECTORY FULL UPON UPDATE++'
	DB	CR,LF,'++TRANSFERRED FILE EXISTS ON DISK++',CR,LF,0
	JMP	EXIT
;
;
;EXIT POINT FROM WRITE IF FDOS III DIRECTORY IS FULL
;
FDIRFUL:
	CALL	ILPRT	;PRINT DIRECTORY FULL MESSAGE
	DB	CR,LF,'++FDOS III DIRECTORY MUST BE FULL++',CR,LF,0
	JMP	EXIT
;
;
;EXIT POINT FROM WRITE IF FDOS III DISK GETS FULL
;
DSKFUL:
	CALL	ILPRT	;PRINT DISK FULL MESSAGE
	DB	CR,LF,'++FILE TOO BIG - FDOS III DISK FULL++'
	DB	CR,LF,'++DIRECTORY NOT UPDATED WITH NEW FILE++',CR,LF,0
	JMP	EXIT
;
;EXIT POINT FROM WRITE IF FDOS III FILE ALREADY EXISTS
;
FEXEX:
	CALL	ILPRT
	DB	CR,LF,'++FDOS III FILE ALREADY EXISTS++'
	DB	CR,LF,'++CHANGE NAME OF SOURCE FILE ON CP/M++',CR,LF,0
	JMP	EXIT
;
;
;
;
;PARAMETER STORAGE AREA FOR FDOS WRITE ROUTINE
;
U2SEC	DB	00	;USED TO SEE IF TWO SECTORS S/B SET IN DIRECTORY
FEFLG	DB	00	;FDOS III FILE EXISTS IF SET
ENDENT	DS	11	;STORAGE FOR END ENTRY OF DIRECTORY
;
;
;
* * * * * * * * * * * * * * * * * * * * *
*					*
*	FDOSRD: COPY FILE FROM FDOS     *
*					*
* * * * * * * * * * * * * * * * * * * * *
;
;FETCHES AN FDOS III FILE AND THEN WRITES
;IT TO A CP/M FILE ON DRIVE A:
;
FDOSRD:
	CALL	ERASFIL	;ERASE THE CP/M FILE
	CALL	MAKEFIL	;..THEN MAKE NEW
	MVI	C,01H	;SELECT DISK DRIVE B:
	CALL	SELDSK	;..THROUGH BIOS ACCESS
	MVI	A,00	;SET SCAN FOR FIRST ENTRY
	JMP	FIND2	;JUMP INTO LOOP
FIND1:
	MVI	A,01	;SET SCAN CODE FOR NEXT ENTRY
FIND2:
	CALL	FDIRSC	;SCAN FOR NEXT DIRECTORY ENTRY
	ORA	A	;SET FLAGES FOR RETURN CODE
	JNZ	FDNFEX	;GO EXIT FOR NOT FOUND FDOS FILE
	LDA	FDENT+5	;GET ENTRY TYPE BYTE
	CPI	0FFH	;MUST BE AT END OF THE LIST
	JZ	FDNFEX	;GO EXIT FOR NOT FOUND FDOS FILE
	MVI	B,05H	;SETUP FOR COMPARE FILE NAMES
	LXI	D,FCB+1	;..FOR 5 CHAR FROM FCB TO
	LXI	H,FDENT	;..FDOS III DIRECTORY ENTRY
	CALL	COMPARE	;GO COMPARE
	ORA	A	;CHECK THE RETURN FLAG
	JZ	FIND1	;NO NAME MATCH IF ZERO	
;
;ADJUST BLOCK COUNT FOR REAL WORLD PEOPLE
;
	LHLD	FDENT+8	;GET REMAINING FILE SIZE
	XCHG		;CHANGE SIGNIFICANT ORDER
	MOV	L,D
	MOV	H,E
	DCX	H	;DECREMENT BLOCK COUNT
			;THIS ADJUSTS FILE SIZE FROM
			;CRAZY FDOS THAT SAVES LENGTH+1
	XCHG		;CHANGE ORDER BACK
	MOV	L,D
	MOV	H,E
	SHLD	FDENT+8	;PUT NEW BLOCK COUNT BACK
;
;FOUND FILE ON FDOS III DISK
;
RCVLP:
	MVI	C,01	;SELECT DRIVE B: FOR FDOS
	CALL	SELDSK
	LDA	FDENT+6	;GET AND SET TRACK NUMBER
	MOV	C,A	;GO DIRECT TO BDOS
	CALL	SETTRK
	LDA	FDENT+7	;GET AND SET SECTOR NUMBER
	MOV	C,A	;SET AND READ SECTOR
	CALL	FRDSEC
;
	LXI	H,IDBUF	;MOVE SECTOR TO CP/M AREA
	LXI	D,080H
	CALL	MOVE128
	CALL	WRSECT	;MOVE DATA TO CP/M QUEUE
;
	LDA	FDENT+7	;INCREMENT SECTOR NUMBER
	INR	A
	STA	FDENT+7	;SAVE INCREMENTED SECTOR
	CPI	01BH	;CHECK IF TRACK DONE
	JC	TRKOK
	MVI	A,01H	;SET SECTOR BACK FOR NEW TRACK
	STA	FDENT+7	;SAVE NEW SECTOR NUMBER
	LDA	FDENT+6	;INCREMENT TRACK NUMBER
	INR	A
	STA	FDENT+6
TRKOK:
	LHLD	FDENT+8	;GET REMAINING FILE SIZE
	XCHG		;CHANGE SIGNIFICANT ORDER
	MOV	L,D
	MOV	H,E
	DCX	H	;DECREMENT BLOCK COUNT
	XCHG		;CHANGE ORDER BACK
	MOV	L,D
	MOV	H,E
	SHLD	FDENT+8	;PUT NEW BLOCK COUNT BACK
	MOV	A,L	;CHECK FOR DONE
	ORA	H
	JZ	RCVEOF	;EXIT FOR END OF FDOS FILE
;
	JMP	RCVLP	;GO FOR NEXT SECTOR
;
;GOT EOF ON SECTOR - FLUSH BUFFERS, END
;
RCVEOF:
	CALL	WRBLOCK	;WRITE THE LAST BLOCK
	CALL	CLOSFIL	;CLOSE THE FILE
	JMP	DONE	;GO PRINT END OF TRANSFER MESSAGE
;
;
;
FDNFEX:
	CALL	ILPRT	;PRINT FDOS III FILE NOT FOUND
	DB	CR,LF,'++FDOS FILE NOT FOUND++',CR,LF,0
	JMP	EXIT
;
;
;
* * * * * * * * * * * * * * * * * * * * *
*					*
*		SUBROUTINES		*
*					*
* * * * * * * * * * * * * * * * * * * * *
;
;
;
;---->	ERASFIL: ERASE THE INCOMING FILE.
;
;IF IT EXISTS, ASK IF IT MAY BE ERASED.
;
ERASFIL:
	LXI	D,FCB	;POINT TO CTL BLOCK
	MVI	C,SRCHF ;SEE IF IT..
	CALL	BDOS	;..EXISTS
	INR	A	;FOUND?
	RZ		;..NO, RETURN
	CALL	ILPRT	;PRINT:
	DB	'++CP/M FILE EXISTS, TYPE Y TO ERASE: ',0
	CALL	KEYIN	;GET A CHARACTER FROM CONSOLE
	ANI	5FH	;MAKE UPPER CASE
	CPI	'Y'	;WANT ERASED?
	JNZ	EXIT	;QUIT IF NOT ERASE
	CALL	CRLF	;BACK TO START OF LINE
;
;ERASE OLD FILE
;
	LXI	D,FCB	;POINT TO FCB
	MVI	C,ERASE	;GET BDOS FNC
	CALL	BDOS	;DO THE ERASE
	RET		;FROM "ERASFIL"
;
;---->	MAKEFIL: MAKES THE FILE TO BE RECEIVED
;
MAKEFIL:
	LXI	D,FCB	;POINT TO FCB
	MVI	C,MAKE	;GET BDOS FNC
	CALL	BDOS	;TO THE MAKE
	INR	A	;FF=BAD?
	RNZ		;OPEN OK
;DIRECTORY FULL - CAN'T MAKE FILE
	CALL	ERXIT
	DB	'++ERROR - CANNOT MAKE FILE',CR,LF
	DB	'++DIRECTORY MUST BE FULL',CR,LF,'$'
;
;---->	OPENFIL: OPENS THE FILE TO BE SENT
;
OPENFIL:
	LXI	D,FCB	;POINT TO FILE
	MVI	C,OPEN	;GET FUNCTION
	CALL	BDOS	;OPEN IT
	INR	A	;OPEN OK?
	RNZ		;FILE OPENED OK
	CALL	ERXIT	;..NO, ABORT
	DB	'CANNOT OPEN CP/M FILE$'
;
;
;---->	CLOSFIL: CLOSES THE RECEIVED FILE
;
CLOSFIL:
	LXI	D,FCB	;POINT TO FILE
	MVI	C,CLOSE	;GET FUNCTION
	CALL	BDOS	;CLOSE IT
	INR	A	;CLOSE OK?
	RNZ		;..YES, RETURN
	CALL	ERXIT	;..NO, ABORT
	DB	'CANNOT CLOSE CP/M FILE$'
;
;---->	RDSECT: READS A SECTOR
;
;FOR SPEED, THIS ROUTINE BUFFERS UP 16
;SECTORS AT A TIME.
;
RDSECT:
	LDA	SECINBF	;GET # SECT IN BUFF.
	DCR	A	;DECREMENT..
	STA	SECINBF	;..IT
	JM	RDBLOCK	;EXHAUSTED?  NEED MORE.
	LHLD	SECPTR	;GET POINTER
	LXI	D,80H	;TO DATA 
	CALL	MOVE128	;MOVE TO BUFFER
	SHLD	SECPTR	;SAVE BUFFER POINTER
	STC
	CMC		;CLEAR CARRY SO EOF NOT INDICATED
			;ON NORMAL RETURN
	RET		;FROM "READSEC"
;
;BUFFER IS EMPTY - READ IN ANOTHER BLOCK OF 16
;
RDBLOCK:
	LDA	EOFLG	;GET EOF FLAG
	CPI	1	;IS IT SET?
	STC		;TO SHOW EOF
	RZ		;GOT EOF
	MVI	C,00H	;SELECT DRIVE A:
	CALL	SELDSK
	MVI	C,0	;SECTORS IN BLOCK
	LXI	D,DBUF	;TO DISK BUFFER
RDSECLP:
	PUSH	B
	PUSH	D
	MVI	C,STDMA	;SET DMA..
	CALL	BDOS	;..ADDR
	LXI	D,FCB
	MVI	C,READ
	CALL	BDOS
	POP	D
	POP	B
	ORA	A	;READ OK?
	JZ	RDSECOK	;YES
	DCR	A	;EOF?
	JZ	REOF	;GOT EOF
;
;READ ERROR
;
	CALL	ERXIT
	DB	'++CP/M FILE READ ERROR$'
;
RDSECOK:
	LXI	H,80H
	DAD	D	;TO NEXT BUFF
	XCHG		;BUFF TO DE
	INR	C	;MORE SECTORS?
	MOV	A,C	;GET COUNT
	CPI	16	;DONE?
	JZ	RDBFULL	;..YES, BUF IS FULL
	JMP	RDSECLP	;READ MORE
;
REOF:
	MVI	A,1
	STA	EOFLG	;SET EOF FLAG
	MOV	A,C
;
;BUFFER IS FULL, OR GOT EOF
;
RDBFULL:
	STA	SECINBF	;STORE SECTOR COUNT
	LXI	H,DBUF	;INIT BUFFER..
	SHLD	SECPTR	;..POINTER
	LXI	D,80H	;RESET..
	MVI	C,STDMA	;..DMA..
	CALL	BDOS	;..ADDR
	JMP	RDSECT	;PASS SECT TO CALLER
;
;---->	WRSECT: WRITE A SECTOR
;
;WRITES THE SECTOR INTO A BUFFER. WHEN 16
;HAVE BEEN WRITTEN, WRITES THE BLOCK TO DISK.
;
;ENTRY POINT "WRBLOCK" FLUSHES THE BUFFER AT EOF.
;
WRSECT:
	LHLD	SECPTR	;GET BUFF ADDR
	XCHG		;TO DE FOR MOVE
	LXI	H,80H	;FROM HERE
	CALL	MOVE128	;MOVE TO BUFFER
	XCHG		;SAVE NEXT..
	SHLD	SECPTR	;..BLOCK POINTER
	LDA	SECINBF	;BUMP THE..
	INR	A	;..SECTOR #..
	STA	SECINBF	;..IN THE BUFF
	CPI	16	;HAVE WE 16?
	RNZ		;NO, RETURN
;
;---->	WRBLOCK: WRITES A BLOCK TO DISK
;
WRBLOCK:
	LDA	SECINBF	;# SECT IN BUFFER
	ORA	A	;0 MEANS END OF FILE
	RZ		;NONE TO WRITE
	PUSH	PSW	;SAVE SECINBUF
	MVI	C,00H	;SELECT DISK DRIVE A:
	CALL	SELDSK
	POP	PSW	;GET SECINBUF BACK
	MOV	C,A	;SAVE COUNT
	LXI	D,DBUF	;POINT TO DISK BUFF
DKWRLP:
	PUSH	H
	PUSH	D
	PUSH	B
	MVI	C,STDMA	;SET DMA
	CALL	BDOS	;TO BUFFER
	LXI	D,FCB	;THEN WRITE
	MVI	C,WRITE	;..THE..
	CALL	BDOS	;..BLOCK
	POP	B
	POP	D
	POP	H
	ORA	A
	JNZ	WRERR	;OOPS, ERROR
	LXI	H,80H	;LENGTH OF 1 SECT
	DAD	D	;HL= NEXT BUFF
	XCHG		;TO DE FOR SETDMA
	DCR	C	;MORE SECTORS?
	JNZ	DKWRLP	;..YES, LOOP
	XRA	A	;GET A ZERO
	STA	SECINBF	;RESET # OF SECTORS
	LXI	H,DBUF	;RESET BUFFER..
	SHLD	SECPTR	;..POINTER
	RET
;
WRERR:
	CALL	ERXIT	;EXIT W/MSG:

	DB	'++ERROR WRITING CP/M FILE',CR,LF,'$'
;
;
;---->  FRDSEC: READS A GIVEN SECTOR ACCORDING
;		TO FDOS III CONVENTION. REGISTER
;		C CONTAINS THE LOGICAL SECTOR NUMBER.
;
FRDSEC:
	MVI	B,00H	;SET THE TABLE INDEX RIGHT
	PUSH	B
	PUSH	H
	PUSH	D
	LXI	H,TBL-1	;MAKE POINTER TO SECTOR TRANSLATION TABLE
	DAD	B	;MAKE POINTER INTO TABLE
	MOV	C,M	;GET PHYSICAL SECTOR
	CALL	SETSEC	;SET SECTOR NUMBER PHYSICAL AT CONTROLLER
	LXI	B,IDBUF	;SETUP THE POINTER TO THE FDOS INPUT BUFFER
	CALL	SETDMA	;ACCESS BIOS DIRECT
	CALL	RDSEC	;READ THE SECTOR INTO BUFFER
	POP	D
	POP	H
	POP	B
	ORA	A	;LOOK TO SEE IF READ ERROR
	RZ		;GO BACK IF NO ERRORS DETECTED
;
;FDOS DISK READ ERROR
;
	CALL	ERXIT
	DB	'++FDOS III DISK READ ERROR$'
;
;
;---->  FWRSEC:	WRITES A GIVEN SECTOR ACCORDING 
;		TO FDOS III CONVENTION. REGISTER C 
;		CONTAINS THE LOGICAL SECTOR NUMBER.
;
;
FWRSEC:
	MVI	B,00H	;SET THE TABLE INDEX RIGHT
	PUSH	B
	PUSH	H
	PUSH	D
	LXI	H,TBL-1	;MAKE POINTER TO SECTOR TRANSLATION TABLE
	DAD	B	;MAKE POINTER INTO TABLE
	MOV	C,M	;GET PHYSICAL SECTOR
	CALL	SETSEC	;SET SECTOR NUMBER PHYSICAL AT CONTROLLER
	LXI	B,ODBUF	;SETUP THE POINTER TO THE FDOS OUTPUT BUFFER
	CALL	SETDMA	;ACCESS BIOS DIRECT
	CALL	WRTSEC	;WRITE THE SECTOR INTO BUFFER
	POP	D
	POP	H
	POP	B
	ORA	A	;LOOK TO SEE IF WRITE ERROR
	RZ		;GO BACK IF NO ERRORS DETECTED
;
;FDOS DISK WRITE ERROR
;
	CALL	ERXIT
	DB	'++FDOS III DISK WRITE ERROR$'
;
;
;
;
;---->	INITADR: INIT'S CP/M BDOS ADDRESSES
;
;THIS ROUTINE FILLS IN THE ADDRESSES OF VARIOUS
;JUMP VECTOR ENTRY POINTS SO THAT CP/M BDOS
;IS BYPASSED WHILE ACCESSING THE FDOS III DISK
;IN DRIVE B: SO THAT THE MODIFIED LOGICAL
;SECTORING MAY BE USED.
;
INITADR:
	LHLD	1	;GET WARM BOOT ADDR
	LXI	D,015H	;OFFSET TO HOME VECTOR
	DAD	D	;TO HOME DISK ROUTINE
	SHLD	HOME+1  ;SET INTERNAL HOME VECTOR
	LXI	D,003H	;OFFSET TO NEXT VECTOR
	DAD	D	;TO SELECT DISK ROUTINE
	SHLD 	SELDSK+1;SET INTERNAL SELDSK VECTOR
	DAD	D	;TO SET TRACK ROUTINE
	SHLD	SETTRK+1;SET INTERNAL SETTRK VECTOR
	DAD	D	;TO SET SECTOR ROUTINE
	SHLD	SETSEC+1;SET INTERNAL SETSEC VECTOR
	DAD	D	;TO SET DMA ADDRESS ROUTINE
	SHLD	SETDMA+1;SET INTERNAL SETDMA VECTOR
	DAD	D	;TO READ SECTOR ROUTINE
	SHLD	RDSEC+1	;SET INTERNAL READ VECTOR
	DAD	D	;TO WRITE SECTOR ROUTINE
	SHLD	WRTSEC+1;SET INTERNAL WRITE VECTOR
;
	RET
;
;
;----> ENTRY POINTS FOR BIOS DISK ACCESS PRIMATIVES-ADDRESSES SETUP AT INIT
;
HOME:
	JMP	$-$	;HOME DISK INTERNAL VECTOR
SELDSK:
	JMP	$-$	;SELECT DISK INTERNAL VECTOR
SETTRK:
	JMP	$-$	;SET TRACK INTERNAL VECTOR
SETSEC:
	JMP	$-$	;SET SECTOR INTERNAL VECTOR
SETDMA:
	JMP	$-$	;SET DMA ADDRESS INTERNAL VECTOR
RDSEC:
	JMP	$-$	;READ SECTOR INTERNAL VECTOR
WRTSEC:
	JMP	$-$	;WRITE SECTOR INTERNAL VECTOR
;
;
;
;---->	PROCOPT: PROCESS COMMAND OPTIONS
; 
;SAVES THE PROGRAM OPTION IN 'OPTION';
;
PROCOPT:
	LXI	D,FCB+1	;TO PROGRAM OPT.
	LDAX	D	;GET OPTION
	STA	OPTION	;SAVE IT
	RET		;FROM 'PROCOPT'
;
;DONE - CLOSE UP SHOP
;
DONE:
	CALL	ILPRT
	DB	CR,LF,'TRANSFER COMPLETE'
	DB	CR,LF,0
;
	JMP	EXIT	;DONE, GO BACK
;
;
;ROUTINE MOVES THE FILENAME FROM THE SECOND FCB
;TO THE FIRST
;
MOVEFCB:
	LXI	H,FCB+16 ;FROM
	LXI	D,FCB	;TO
	MVI	B,16	;LEN
	CALL	MOVE	;DO THE MOVE
	XRA	A	;GET 0
	STA	FCBSNO	;ZERO SECTOR #
	STA	FCB	;..AND DRIVE DESIGNATOR
	STA	FCBEXT	;..AND EXTENT
	RET
;
;
;---->  KEYIN: GETS A KEY CODE IN FROM CONSOLE
;
KEYIN:
	PUSH	B	;SAVE..
	PUSH	D	;..ALL..
	PUSH	H	;..REGS
	MVI	C,RDCON	;GET CONSOLE CHARACTER FUNCTION CODE
	CALL	BDOS	;GET CHARACTER
	MOV	A,E
	POP	H	;RESTORE..
	POP	D	;..ALL..
	POP	B	;..REGS
	RET
;
;
;---->	CTYPE: TYPES VIA CP/M SO TABS ARE EXPANDED
;
CTYPE:
	PUSH	B	;SAVE..
	PUSH	D	;..ALL..
	PUSH	H	;..REGS
	MOV	E,A	;CHAR TO E
	MVI	C,WRCON	;GET BDOS FNC
	CALL	BDOS	;PRIN THE CHR
	POP	H	;RESTORE..
	POP	D	;..ALL..
	POP	B	;..REGS
	RET		;FROM "CTYPE"
;
CRLF:
	MVI	A,CR
	CALL	CTYPE
	MVI	A,LF
	CALL	CTYPE
	RET
;
;
;HEX OUTPUT
;
HEXO:
	PUSH	PSW	;SAVE FOR RIGHT DIGIT
	RAR		;RIGHT..
	RAR		;..JUSTIFY..
	RAR		;..LEFT..
	RAR		;..DIGIT..
	CALL	NIBBL	;PRINT LEFT DIGIT
	POP	PSW	;RESTORE RIGHT
	CALL	NIBBL	;PRINT RIGHT DIGIT
	RET
;
;
NIBBL:
	ANI	0FH	;ISOLATE DIGIT
	CPI	10	;IS IS <10?
	JC	ISNUM	;YES, NOT ALPHA
	ADI	7	;ADD ALPHA BIAS
ISNUM:
	ADI	'0'	;MAKE PRINTABLE
	CALL	CTYPE	;..THEN TYPE IT
	RET
;
;
;---->	ILPRT: INLINE PRINT OF MSG
;
;THE CALL TO ILPRT IS FOLLOWED BY A MESSAGE,
;BINARY 0 AS THE END.  BINARY 1 MAY BE USED TO
;PAUSE (MESSAGE 'PRESS RETURN TO CONTINUE')
;
ILPRT:
	XTHL		;SAVE HL, GET HL=MSG
ILPLP:
	MOV	A,M	;GET CHAR
	ORA	A	;END OF MSG?
	JZ	ILPRET	;..YES, RETURN
	CPI	1	;PAUSE?
	JZ	ILPAUSE	;..YES
	CALL	CTYPE	;TYPE THE CHARACTER OF MESSAGE
ILPNEXT:
	INX	H	;TO NEXT CHAR
	JMP	ILPLP	;LOOP
;
;PAUSE WHILE TYPING HELP SO INFO DOESN'T
;	SCROLL OFF OF VIDEO SCREENS
;
ILPAUSE:
	CALL	ILPRT	;PRINT:

	DB	CR,LF,'PRESS RETURN TO CONTINUE OR ^C TO EXIT'
	DB	CR,LF,0
	CALL	KEYIN	;GET ANY CHAR
	CPI	'C'-40H	;REBOOT?
	JZ	EXIT	;YES.
	JMP	ILPNEXT	;LOOP
;
ILPRET:
	XTHL		;RESTORE HL
	RET		; & RETURN ADDR PAST MESSAGE
;
;---->	PRTMSG: PRINTS MSG POINTED TO BY (DE)
;
;A '$' IS THE ENDING DELIMITER FOR THE PRINT.
;NO REGISTERS SAVED.
;
PRTMSG:
	MVI	C,PRINT	;GET BDOS FNC
	JMP	BDOS	;PRINT MESSAGE, RETURN
;
;---->	ERXIT: EXIT PRINTING MSG FOLLOWING CALL
;
ERXIT:
	POP	D	;GET MESSAGE
	CALL	PRTMSG	;PRINT IT
;
EXIT:
	MVI	C,00H	;SET SELECTED UNIT BACK TO A:
	CALL	SELDSK
	LXI	D,080H	;RESET DEFAULT DMA ADDRESS FOR EXIT
	MVI	C,STDMA
	CALL	BDOS
	LHLD	STACK	;GET ORIGINAL STACK
	SPHL		;RESTORE IT
	JMP	WBOOT	;GO DO A WARM BOOT OF CP/M SO THIS 
			;THING WILL WORK IN A SUBMIT FILE
;
;MOVE 128 CHARACTERS
;
MOVE128:
	MVI	B,128	;SET MOVE COUNT
;
;MOVE FROM (HL) TO (DE) LENGTH IN (B)
;
MOVE:
	MOV	A,M	;GET A CHAR
	STAX	D	;STORE IT
	INX	H	;TO NEXT "FROM"
	INX	D	;TO NEXT "TO"
	DCR	B	;MORE?
	JNZ	MOVE	;..YES, LOOP
	RET		;..NO, RETURN
;
;
;COMPARE FROM (HL) TO (DE) FOR (B) BYTES
;RETURN WITH A REGISTER:
;	=00 IF NO COMPARE
;	=FF IF VALID COMPARE
;
COMPARE:
	LDAX	D	;GET A CHAR
	CMP	M	;CHECK AGAINST OTHER
	JNZ	COMFAL	;GO EXIT FOR FAIL
	INX	H	;INCREMENT COMPARE POINTERS
	INX	D
	DCR	B	;DECREMENT CHAR COUNT
	JNZ	COMPARE	;MORE?
	MVI	A,0FFH	;EXIT FOR GOOD COMPARE
	RET
COMFAL:
	XRA	A	;EXIT FOR NON COMPARE
	RET
;
;
;	----------------
;
;PROGRAM DATA AREA SPACE ALLOCATIONS
;
OPTION	DB	0	;PROGRAM OPTION
;
;
;FOLLOWING 3 USED BY THE CP/M DISK BUFFERING ROUTINES
;
EOFLG	DB	0	;EOF FLAG (1=TRUE)
SECPTR	DW	DBUF
SECINBF	DB	0	;# OF SECTORS IN BUFFER
;
;
;
;FDOS III LOGICAL TO PHYSICAL SECTOR MAP
;TABLE ENTRIES ARE IN LOGICAL SECTOR ORDER
;
;
TBL:	DB	001H
	DB	00AH
	DB	013H
	DB	002H
	DB	00BH
	DB	014H
	DB	003H
	DB	00CH
	DB	015H
	DB	004H
	DB	00DH
	DB	016H
	DB	005H
	DB	00EH
	DB	017H
	DB	006H
	DB	00FH
	DB	018H
	DB	007H
	DB	010H
	DB	019H
	DB	008H
	DB	011H
	DB	01AH
	DB	009H
	DB	012H
	DB	000H	;DUMMY ENTRY
	DB	000H	;DUMMY ENTRY
	DB	000H	;DUMMY ENTRY
;
;
;FDOS III FILE HANDLER PARAMETER STORAGE LOCATIONS
;
;
FDENT	DS	11	;TEMPORARY STORAGE FOR A DIRECTORY ENTRY
;
;
;SETUP A STACK AREA
;
	DS	200	;STACK AREA
STACK	DS	2	;STACK POINTER
;
;+++++++++
;+++++++++
;++
;++ NOTE: THE FOLLOWING DISK DATA BUFFERS ARE ALLOCATED
;++       OVER THE HELP FILE AND NON DISK I/O SOFTWARE
;++
;+++++++++
;+++++++++
;
;
;
;INPUT AND OUTPUT BUFFER STORAGE ALLOCATIONS FOR FDOS III DISK
;
IDBUF	EQU	$ 	;SINGLE SECTOR INPUT BUFFER
ODBUF	EQU	$+128	;SINGLE SECTOR OUTPUT BUFFER
;
;
;
;16 SECTOR CP/M DISK BUFFER 
;
DBUF	EQU	$+256	;16 SECTOR CP/M DISK BUFFER
;
;INVALID COMMAND
;
BADOPT:
	CALL	CTYPE
	CALL	ILPRT	;EXIT W/ERROR
	DB	': INVALID OPTION FOR PROGRAM SELECTION '
	DB	'COMMAND - ',CR,LF
	DB	'PRESS CTL-C TO ABORT',1,0
;
HELP:
	CALL	ILPRT
	DB	CR,LF,CR,LF,'FORMAT FOR COMMAND IS:',CR,LF,CR,LF
	DB	'FDOS # FILENAME',CR,LF,CR,LF
	DB	'WHERE # IS A 1 CHARACTER PROGRAM OPTION,',CR,LF
	DB	'PROGRAM OPTIONS:',CR,LF
	DB	'	R TO READ AN FDOS III FILE FROM B:',CR,LF
	DB	'	W TO WRITE AN FDOS III FILE TO B:',CR,LF
	DB	'	D TO VIEW THE FDOS III DIRECTORY ON B:',CR,LF
	DB	'	H TO PRINT THIS HELP FILE',CR,LF,CR,LF,0
	JMP	EXIT
;
;
; BDOS EQUATES (VERSION 2)
;
RDCON	EQU	1
WRCON	EQU	2
PRINT	EQU	9
CONST	EQU	11	;CONSOLE STAT
OPEN	EQU	15	;0FFH=NOT FOUND
CLOSE	EQU	16	;	"	"
SRCHF	EQU	17	;	"	"
SRCHN	EQU	18	;	"	"
ERASE	EQU	19	;NO RET CODE
READ	EQU	20	;0=OK, 1=EOF
WRITE	EQU	21	;0=OK, 1=ERR, 2=?, 0FFH=NO DIR SPC
MAKE	EQU	22	;0FFH=BAD
REN	EQU	23	;0FFH=BAD
STDMA	EQU	26	;SET DMA
BDOS	EQU	5
REIPL	EQU	0
FCB	EQU	5CH	;SYSTEM FCB
FCBEXT	EQU	FCB+12	;FILE EXTENT
FCBSNO	EQU	FCB+32	;SECTOR #
FCB2	EQU	6CH	;SECOND FCB
	END
