   888888888            666666666         DDDDDDDDDDDD            OOOOOOOOO            SSSSSSSSSSSS
   888888888            666666666         DDDDDDDDDDDD            OOOOOOOOO            SSSSSSSSSSSS
   888888888            666666666         DDDDDDDDDDDD            OOOOOOOOO            SSSSSSSSSSSS
888         888      666                  DDD         DDD      OOO         OOO      SSS            
888         888      666                  DDD         DDD      OOO         OOO      SSS            
888         888      666                  DDD         DDD      OOO         OOO      SSS            
888         888      666                  DDD         DDD      OOO         OOO      SSS            
888         888      666                  DDD         DDD      OOO         OOO      SSS            
888         888      666                  DDD         DDD      OOO         OOO      SSS            
   888888888         666666666666         DDD         DDD      OOO         OOO         SSSSSSSSS   
   888888888         666666666666         DDD         DDD      OOO         OOO         SSSSSSSSS   
   888888888         666666666666         DDD         DDD      OOO         OOO         SSSSSSSSS   
888         888      666         666      DDD         DDD      OOO         OOO                  SSS
888         888      666         666      DDD         DDD      OOO         OOO                  SSS
888         888      666         666      DDD         DDD      OOO         OOO                  SSS
888         888      666         666      DDD         DDD      OOO         OOO                  SSS
888         888      666         666      DDD         DDD      OOO         OOO                  SSS
888         888      666         666      DDD         DDD      OOO         OOO                  SSS
   888888888            666666666         DDDDDDDDDDDD            OOOOOOOOO         SSSSSSSSSSSS   
   888888888            666666666         DDDDDDDDDDDD            OOOOOOOOO         SSSSSSSSSSSS   
   888888888            666666666         DDDDDDDDDDDD            OOOOOOOOO         SSSSSSSSSSSS   




   AAAAAAAAA            SSSSSSSSSSSS      MMM         MMM
   AAAAAAAAA            SSSSSSSSSSSS      MMM         MMM
   AAAAAAAAA            SSSSSSSSSSSS      MMM         MMM
AAA         AAA      SSS                  MMMMMM   MMMMMM
AAA         AAA      SSS                  MMMMMM   MMMMMM
AAA         AAA      SSS                  MMMMMM   MMMMMM
AAA         AAA      SSS                  MMM   MMM   MMM
AAA         AAA      SSS                  MMM   MMM   MMM
AAA         AAA      SSS                  MMM   MMM   MMM
AAA         AAA         SSSSSSSSS         MMM         MMM
AAA         AAA         SSSSSSSSS         MMM         MMM
AAA         AAA         SSSSSSSSS         MMM         MMM
AAAAAAAAAAAAAAA                  SSS      MMM         MMM
AAAAAAAAAAAAAAA                  SSS      MMM         MMM
AAAAAAAAAAAAAAA                  SSS      MMM         MMM
AAA         AAA                  SSS      MMM         MMM
AAA         AAA                  SSS      MMM         MMM
AAA         AAA                  SSS      MMM         MMM
AAA         AAA      SSSSSSSSSSSS         MMM         MMM
AAA         AAA      SSSSSSSSSSSS         MMM         MMM
AAA         AAA      SSSSSSSSSSSS         MMM         MMM




 *START* User ROS BASIC [500,500]  Job  86DOS Seq. 7115 Date 16-Jun-81 15:13:30 Monitor Microsoft 1091 603a4d80j *START*
File: DSKC:86DOS.ASM<055>[500,500] Created: 15-Jun-81 03:18:51 Printed: 16-Jun-81 15:17:10
QUEUE Switches:  /FILE:ASCII /COPIES:1 /SPACING:1 /LIMIT:565 /FORMS:NORMAL
   888888888            666666666         DDDDDDDDDDDD            OOOOOOOOO            SSSSSSSSSSSS
   888888888            666666666         DDDDDDDDDDDD            OOOOOOOOO            SSSSSSSSSSSS
   888888888            666666666         DDDDDDDDDDDD            OOOOOOOOO            SSSSSSSSSSSS
888         888      666                  DDD         DDD      OOO         OOO      SSS            
888         888      666                  DDD         DDD      OOO         OOO      SSS            
888         888      666                  DDD         DDD      OOO         OOO      SSS            
888         888      666                  DDD         DDD      OOO         OOO      SSS            
888         888      666                  DDD         DDD      OOO         OOO      SSS            
888         888      666                  DDD         DDD      OOO         OOO      SSS            
   888888888         666666666666         DDD         DDD      OOO         OOO         SSSSSSSSS   
   888888888         666666666666         DDD         DDD      OOO         OOO         SSSSSSSSS   
   888888888         666666666666         DDD         DDD      OOO         OOO         SSSSSSSSS   
888         888      666         666      DDD         DDD      OOO         OOO                  SSS
888         888      666         666      DDD         DDD      OOO         OOO                  SSS
888         888      666         666      DDD         DDD      OOO         OOO                  SSS
888         888      666         666      DDD         DDD      OOO         OOO                  SSS
888         888      666         666      DDD         DDD      OOO         OOO                  SSS
888         888      666         666      DDD         DDD      OOO         OOO                  SSS
   888888888            666666666         DDDDDDDDDDDD            OOOOOOOOO         SSSSSSSSSSSS   
   888888888            666666666         DDDDDDDDDDDD            OOOOOOOOO         SSSSSSSSSSSS   
   888888888            666666666         DDDDDDDDDDDD            OOOOOOOOO         SSSSSSSSSSSS   




   AAAAAAAAA            SSSSSSSSSSSS      MMM         MMM
   AAAAAAAAA            SSSSSSSSSSSS      MMM         MMM
   AAAAAAAAA            SSSSSSSSSSSS      MMM         MMM
AAA         AAA      SSS                  MMMMMM   MMMMMM
AAA         AAA      SSS                  MMMMMM   MMMMMM
AAA         AAA      SSS                  MMMMMM   MMMMMM
AAA         AAA      SSS                  MMM   MMM   MMM
AAA         AAA      SSS                  MMM   MMM   MMM
AAA         AAA      SSS                  MMM   MMM   MMM
AAA         AAA         SSSSSSSSS         MMM         MMM
AAA         AAA         SSSSSSSSS         MMM         MMM
AAA         AAA         SSSSSSSSS         MMM         MMM
AAAAAAAAAAAAAAA                  SSS      MMM         MMM
AAAAAAAAAAAAAAA                  SSS      MMM         MMM
AAAAAAAAAAAAAAA                  SSS      MMM         MMM
AAA         AAA                  SSS      MMM         MMM
AAA         AAA                  SSS      MMM         MMM
AAA         AAA                  SSS      MMM         MMM
AAA         AAA      SSSSSSSSSSSS         MMM         MMM
AAA         AAA      SSSSSSSSSSSS         MMM         MMM
AAA         AAA      SSSSSSSSSSSS         MMM         MMM




 *START* User ROS BASIC [500,500]  Job  86DOS Seq. 7115 Date 16-Jun-81 15:13:30 Monitor Microsoft 1091 603a4d80j *START*
File: DSKC:86DOS.ASM<055>[500,500] Created: 15-Jun-81 03:18:51 Printed: 16-Jun-81 15:17:17
QUEUE Switches:  /FILE:ASCII /COPIES:1 /SPACING:1 /LIMIT:565 /FORMS:NORMAL
00010	
00020	; 86-DOS  High-performance operating system for the 8086  version 1.00 04/28/81
00030	;	by Tim Paterson
00040	
00050	; ****************** Revision History *************************
00060	;          >> EVERY change must noted below!! <<
00070	;
00080	; 0.34 12/29/80 General release, updating all past customers
00090	; 0.42 02/25/81 32-byte directory entries added
00100	; 0.56 03/23/81 Variable record and sector sizes
00110	; 0.60 03/27/81 Ctrl-C exit changes, including register save on user stack
00120	; 0.74 04/15/81 Recognize I/O devices with file names
00130	; 0.75 04/17/81 Improve and correct buffer handling
00140	; 0.76 04/23/81 Correct directory size when not 2^N entries
00150	; 0.80 04/27/81 Add console input without echo, Functions 7 & 8
00160	; 1.00 04/28/81 Renumber for general release
00170	;
00180	; *************************************************************
00190	
00200	; Use the switch below to generate code to accept the old 16-byte
00210	; directory entry as well as the new 32-byte entry.
00220	
00230	SMALLDIR:	EQU	1	;1 to enable, 0 to disable
00240	
00250	
00260	; Turn on switch below to allow testing disk code with DEBUG. It sets
00270	; up a different stack for disk I/O (functions > 11) than that used for
00280	; character I/O which effectively makes the DOS re-entrant.
00290	
00300	DSKTEST:	EQU	0	;1 to enable, 0 to disable
00310	
00320	
00330	; Interrupt Entry Points:
00340	
00350	; INTBASE:	ABORT
00360	; INTBASE+4:	COMMAND
00370	; INTBASE+8:	BASE EXIT ADDRESS
00380	; INTBASE+C:	CONTROL-C ABORT
00390	; INTBASE+10H:	FATAL ERROR ABORT
00400	; INTBASE+14H:	BIOS DISK READ
00410	; INTBASE+18H:	BIOS DISK WRITE
00420	; INTBASE+40H:	Long jump to CALL entry point
00430	
00440	
00450	MAXCALL:EQU	36
00460	MAXCOM:	EQU	41
00470	ESCCH:	EQU	1BH
00480	INTBASE:EQU	80H
00490	INTTAB:	EQU	20H
00500	ENTRYPOINTSEG:	EQU	0CH
00510	ENTRYPOINT:	EQU	INTBASE+40H
00520	CONTC:	EQU	INTTAB+3
00530	EXIT:	EQU	INTBASE+8
00540	LONGJUMP:EQU	0EAH
00550	LONGCALL:EQU	9AH
00560	MAXDIF:	EQU	0FFFH
00570	SAVEXIT:EQU	10
00580	
00590	; Field definition for FCBs
00600	
00610		ORG	0
00620		DS	12		;Drive code and name
00630	EXTENT:	DS	2
00640	RECSIZ:	DS	2		;Size of record (user settable)
00650	FILSIZ:	DS	4		;Size of file in bytes
00660	FDATE:	DS	2		;Date of last writing
00670	FILDIRBLK:DS	2		;Location in directory
00680	FIRCLUS:DS	2		;First cluster of file
00690	LSTCLUS:DS	2		;Last cluster accessed
00700	CLUSPOS:DS	2		;Position of last cluster accessed
00710	DIRTYFIL:DS	1		;File has been written to if <>0
00720		ORG	32
00730	NR:	DS	1		;Next record
00740	RR:	DS	3		;Random record
00750	
00760	
00770	; Description of 32-byte directory entry (same as returned by SEARCH FIRST
00780	; and SEARCH NEXT, functions 17 and 18).
00790	;
00800	; Location	bytes	Description
00810	;
00820	;    0		11	File name and extension ( 0E5H if empty)
00830	;   11		13	Zero field (for expansion)
00840	;   24		 2	Date. Bits 0-4=day, bits 5-8=month, bits 9-15=year-1980
00850	;   26		 2	First allocation unit ( < 4080 )
00860	;   28		 4	File size, in bytes (LSB first, 30 bits max.)
00870	;
00880	; The File Allocation Table uses a 12-bit entry for each allocation unit on
00890	; the disk. These entries are packed, two for every three bytes. The contents
00900	; of entry number N is found by 1) multiplying N by 1.5; 2) adding the result
00910	; to the base address of the Allocation Table; 3) fetching the 16-bit word at
00920	; this address; 4) If N was odd (so that N*1.5 was not an integer), shift the
00930	; word right four bits; 5) mask to 12 bits (AND with 0FFF hex). Entry number
00940	; zero is used as an end-of-file trap in the OS and as a flag for directory
00950	; entry size (if SMALLDIR selected). Entry 1 is reserved for future use. The
00960	; first available allocation unit is assigned entry number two, and for Drive Parameter Block
00970	
00980		ORG	0
00990	DRVNUM:	DS	1		;Drive number
01000	SECSIZ:	DS	2		;Size of physical sector in bytes
01010	CLUSMSK:DS	1		;Sectors/cluster - 1
01020	CLUSSHFT:DS	1		;Log2 of sectors/cluster
01030	FIRFAT:	DS	2		;Starting record of FATs
01040	FATCNT:	DS	1		;Number of FATs for this drive
01050	MAXENT:	DS	2		;Number of directory entries
01060	DIRSEC:				;Number of dir. sectors (init temporary)
01070	FIRREC:	DS	2		;First sector of first cluster
01080	DSKSIZ:				;Size of disk (temp used during init only)
01090	MAXCLUS:DS	2		;Number of clusters on drive + 1
01100	FATSIZ:	DS	1		;Number of records occupied by FAT
01110	FIRDIR:	DS	2		;Starting record of directory
01120	
01130		IF	SMALLDIR
01140	FIRREC1:DS	2		;First data sector with 16-byte dir. entries
01150	MAXCLUS1:DS	2		;No. of clusters + 1 with 16-byte dir. entries
01160	FIRREC2:DS	2		;First data sector with 32-byte dir. entries
01170	MAXCLUS2:DS	2		;No. of clusters + 1 with 32-byte dir entries
01180		ENDIF
01190	
01200	DIRTYFAT:DS	1		;1=FAT has been changed, -1=never been read
01210	FAT:				;Start of FAT
01220	DIRSIZ:				;-1=small dir. entry, else large
01230	
01240	
01250	; BIOS entry point defintions
01260	
01270	BIOSSEG:	EQU	40H
01280			ORG	0
01290			DS	3
01300	BIOSSTAT:	DS	3
01310	BIOSIN:		DS	3
01320	BIOSOUT:	DS	3
01330	BIOSPRINT:	DS	3
01340	BIOSAUXIN:	DS	3
01350	BIOSAUXOUT:	DS	3
01360	BIOSREAD:	DS	3
01370	BIOSWRITE:	DS	3
01380	BIOSDSKCHG:	DS	3
01390	
01400	
01410	; Location of user registers relative user stack pointer
01420	
01430		ORG	0
01440	AXSAVE:	DS	2
01450	BXSAVE:	DS	2
01460	CXSAVE:	DS	2
01470	DXSAVE:	DS	2
01480	SISAVE:	DS	2
01490	DISAVE:	DS	2
01500	BPSAVE:	DS	2
01510	DSSAVE:	DS	2
01520	ESSAVE:	DS	2
01530	IPSAVE:	DS	2
01540	CSSAVE:	DS	2
01550	FSAVE:	DS	2
01560	
01570	
01580	; Start of code
01590	
01600		ORG	0
01610		PUT	100H
01620	
01630		JMP	DOSINIT
01640	
01650	ESCTAB:	
01660		DB	"SC"	;Copy one char
01670		DB	"VN"	;Skip one char
01680		DB	"TA"	;Copy to char
01690		DB	"WB"	;Skip to char
01700		DB	"UH"	;Copy line
01710		DB	"HH"	;Kill line (no change in template)
01720		DB	"RM"	;Reedit line (new template)
01730		DB	"DD"	;Backspace
01740		DB	"P@"	;Enter insert mode
01750		DB	"QL"	;Exit insert mode
01760		DB	ESCCH,ESCCH	;Escape character
01770		DB	ESCCH,ESCCH	;End of table
01780	
01790	ESCTABLEN:EQU	$-ESCTAB
01800	
01810	HEADER:	DB	13,10,"86-DOS version 1.00"
01820	
01830		IF	DSKTEST
01840		DB	"D"
01850		ENDIF
01860	
01870		DB	13,10
01880		DB	"Copyright 1980,81 Seattle Computer Products, Inc.",13,10,"$"
01890	
01900	QUIT:
01910		MOV	AH,0
01920		JP	SAVREGS
01930	
01940	COMMAND: ;Interrupt call entry point
01950		CMP	AH,MAXCOM
01960		JBE	SAVREGS
01970	BADCALL:
01980		MOV	AL,0
01990	IRET:	IRET
02000	
02010	ENTRY:	;System call entry point and dispatcher
02020		POP	AX		;IP from the long call at 5
02030		POP	AX		;Segment from the long call at 5
02040		SEG	CS
02050		POP	[TEMP]		;IP from the CALL 5
02060		PUSHF			;Start re-ordering the stack
02070		DI
02080		PUSH	AX		;Save segment
02090		SEG	CS
02100		PUSH	[TEMP]		;Stack now ordered as if INT had been used
02110		CMP	CL,MAXCALL	;This entry point doesn't get as many calls
02120		JA	BADCALL
02130		MOV	AH,CL
02140	SAVREGS:
02150		PUSH	ES
02160		PUSH	DS
02170		PUSH	BP
02180		PUSH	DI
02190		PUSH	SI
02200		PUSH	DX
02210		PUSH	CX
02220		PUSH	BX
02230		PUSH	AX
02240	
02250		IF	DSKTEST
02260		SEG	CS
02270		MOV	AX,[SPSAVE]
02280		SEG	CS
02290		MOV	[NSP],AX
02300		SEG	CS
02310		MOV	AX,[SSSAVE]
02320		SEG	CS
02330		MOV	[NSS],AX
02340		POP	AX
02350		PUSH	AX
02360		ENDIF
02370	
02380		SEG	CS
02390		MOV	[SPSAVE],SP
02400		SEG	CS
02410		MOV	[SSSAVE],SS
02420		MOV	BP,SP
02430		MOV	BX,[BP+CSSAVE]
02440		SEG	CS
02450		MOV	[CSLOC],BX
02460		MOV	SP,CS
02470		MOV	SS,SP
02480		MOV	SP,STACK
02490		EI			;Stack OK now
02500		SEG	CS
02510		MOV	[FUNC],AH
02520		MOV	BL,AH
02530		MOV	BH,0
02540		SHL	BX
02550		UP
02560	
02570		IF	DSKTEST
02580		CMP	AH,12
02590		JL	SAMSTK
02600		MOV	SP,TESTSTK
02610	SAMSTK:
02620		ENDIF
02630	
02640		SEG	CS
02650		CALL	[BX+DISPATCH]
02660	LEAVE:
02670		DI
02680		SEG	CS
02690		MOV	SP,[SPSAVE]
02700		SEG	CS
02710		MOV	SS,[SSSAVE]
02720		MOV	BP,SP
02730		MOV	[BP+AXSAVE],AL
02740	
02750		IF	DSKTEST
02760		SEG	CS
02770		MOV	AX,[NSP]
02780		SEG	CS
02790		MOV	[SPSA	ENDIF
02800	
02810		PBX
02820		POP	CX
02830		POP	DX
02840		POP	SI
02850		POP	DI
02860		POP	BP
02870		POP	DS
02880		POP	ES
02890		IRET
02900	
02910	DISPATCH:
02920	; Standard Functions
02930		DW	ABORT		;0
02940		DW	CONIN
02950		DW	CONOUT
02960		DW	READER
02970		DW	PUNCH
02980		DW	LIST		;5
02990		DW	RAWIO
03000		DW	RAWINP
03010		DW	IN
03020		DW	PRTBUF
03030		DW	BUFIN		;10
03040		DW	CONSTAT
03050		DW	VERSION
03060		DW	DSKRESET
03070		DW	SELDSK
03080		DW	OPEN		;15
03090		DW	CLOSE
03100		DW	SRCHFRST
03110		DW	SRCHNXT
03120		DW	DELETE
03130		DW	SEQRD		;20
03140		DW	SEQWRT
03150		DW	CREATE
03160		DW	RENAME
03170		DW	INUSE
03180		DW	CURDRV		;25
03190		DW	SETDMA
03200		DW	GETFATPT
03210		DW	WRTPROT
03220		DW	GETRDONLY
03230		DW	SETATTRIB	;30
03240		DW	GETDSKPT
03250		DW	USERCODE
03260		DW	RNDRD
03270		DW	RNDWRT
03280		DW	FILESIZE	;35
03290		DW	SETRNDREC
03300	; Extended Functions
03310		DW	SETVECT
03320		DW	NEWBASE
03330		DW	BLKRD
03340		DW	BLKWRT		;40
03350		DW	MAKEFCB
03360	
03370	VERSION:
03380	GETIO:
03390	SETIO:
03400	WRTPROT:
03410	GETRDONLY:
03420	SETATTRIB:
03430	USERCODE:
03440		MOV	AL,0
03450		RET
03460	
03470	
03480	READER:
03490		CALL	BIOSAUXIN,BIOSSEG
03500		RET
03510	
03520	PUNCH:
03530		MOV	AL,DL
03540		CALL	BIOSAUXOUT,BIOSSEG
03550		RET
03560	
03570	
03580	UNPACK:
03590	
03600	; Inputs:
03610	;	DS = CS
03620	;	BX = Cluster number
03630	;	BP = Base of drive parameters
03640	;	SI = Pointer to drive FAT
03650	; Outputs:
03660	;	DI = Contents of FAT for given cluster
03670	;	Zero set means DI=0 (free cluster)
03680	; No other registers affected. Fatal error if cluster too big.
03690	
03700		CMP	BX,[BP+MAXCLUS]
03710		JA	HURTFAT
03720		LEA	DI,[SI+BX]
03730		SHR	BX
03740		MOV	DI,[DI+BX]
03750		JNC	HAVCLUS
03760		SHR	DI
03770		SHR	DI
03780		SHR	DI
03790		SHR	DI
03800		STC
03810	HAVCLUS:
03820		RCL	BX
03830		AND	DI,0FFFH
03840		RET
03850	HURTFAT:
03860		MOV	SI,BADMES
03870		CALL	OUTMES
03880		JMP	ERROR
03890	
03900	
03910	PACK:
03920	
03930	; Inputs:
03940	;	DS = CS
03950	;	BX = Cluster number
03960	;	DX = Data
03970	;	SI = Pointer to drive FAT
03980	; Outputs:
03990	;	The data is stored in the FAT at the given cluster.
04000	;	BX,DX,DI all destroyed
04010	;	No other registers affected
04020	
04030		MOV	DI,BX
04040		SHR	BX
04050		ADD	BX,SI
04060		ADD	BX,DI
04070		SHR	DI
04080		MOV	DI,[BX]
04090		JNC	ALIGNED
04100		SHL	DX
04110		SHL	DX
04120		SHL	DX
04130		SHL	DX
04140		AND	DI,0FH
04150		JP	PACKIN
04160	ALIGNED:
04170		AND	DI,0F000H
04180	PACKIN:
04190		OR	DI,DX
04200		MOV	[BX],DI
04210		RET
04220	
04230	IOCHK:
04240		MOV	CX,5		;Check rest of name but not extension
04250		CMP	B,[DI],":"
04260		JNZ	NOCOL
04270		INC	DI		;Skip over colon
04280		DEC	CX
04290	NOCOL:
04300		MOV	AL," "
04310		REPE
04320		SCAB			;Make sure rest of name is blanks
04330		JNZ	FILSRCH
04340		DEC	BL
04350		RET
04360	
04370	GETFILE:
04380	
04390	; Inputs:
04400	;	DS,DX point to FCB
04410	; Function:
04420	;	Find file name in disk directory. First byte is
04430	;	drive number (0=current disk). "?" matches any
04440	;	character.
04450	; Outputs:
04460	;	Carry set if file not found
04470	;	ELSE
04480	;	BP = Base of drive parameters
04490	;	DS = CS
04500	;	ES = CS
04510	;	BX = Pointer into directory buffer
04520	;	SI = Pointer to First Cluster field in directory entry
04530	;	[DIRBUF] has directory record with match
04540	;	[NAME1] has file name
04550	; All other registers destroyed.
04560	
04570		CALL	MOVNAME
04580		JC	RET		;Bad file name?
04590	FINDNAME:
04600		MOV	AX,CS
04610		MOV	DS,AX
04620		MOV	SI,IONAME	;List of I/O devices with file names
04630		MOV	BX,0FF04H	;BL = number of devices
04640	LOOKIO:
04650		MOV	DI,NAME1
04660		MOV	CX,3		;All device names are 3 letters
04670		REPE
04680		CMPB			;Check for name in list
04690		JZ	IOCHK		;If first 3 letters OK, check the rest
04700		ADD	SI,CX		;Point to next device name
04710		DEC	BL
04720		JNZ	LOOKIO
04730	FILSRCH:			;Not a device name
04740		CALL	STARTSRCH
04750	CONTSRCH:
04760		CALL	GETENTRY
04770		JC	RET
04780	SRCH:
04790		CMP	B,[BX],0E5H
04800		JZ	NEXTENT
04810		MOV	SI,BX
04820		MOV	DI,NAME1
04830		MOV	CX,11
04840	WILDCRD:
04850		REPE
04860		CMPB
04870		JZ	FOUND
04880		CMP	B,[DI-1],"?"
04890		JZ	WILDCRD
04900	NEXTENT:
04910		CALL	NEXTENTRY
04920		JNC	SRCH
04930		RET
04940	
04950	FOUND:
04960		IF	SMALLDIR
04970		CMP	B,[BP+DIRSIZ],-1
04980		JZ	RET
04990		ENDIF
05000	
05010		ADD	SI,15	
05020		RET
05030	
05040	
05050	GETENTRY:
05060	
05070	; Inputs:
05080	;	[LASTENT] has previously searched directory entry
05090	; Function:
05100	;	Locates next sequential directory entry in preparation for search
05110	; Outputs:
05120	;	Carry set if none
05130	;	ELSE
05140	;	AL = Current directory block
05150	;	BX = Pointer to next directory entry in [DIRBUF]
05160	;	DX = Pointer to first byte after end of DIRBUF
05170	;	[LASTENT] = New directory entry number
05180	
05190		MOV	AX,[LASTENT]
05200		INC	AX			;Start with next entry
05210		CMP	AX,[BP+MAXENT]
05220		JAE	NONE
05230		MOV	[LASTENT],AX
05240		MOV	CL,4
05250		SHL	AX,CL
05260		XOR	DX,DX
05270	
05280		IF	SMALLDIR
05290		CMP	B,[BP+DIRSIZ],-1
05300		JZ	SMALENT1
05310		ENDIF
05320	
05330		SHL	AX
05340		RCL	DX			;Account for overflow in last shift
05350	SMALENT1:
05360		MOV	BX,[BP+SECSIZ]
05370		AND	BL,255-31		;Must be multiple of 32
05380		DIV	AX,BX
05390		MOV	BX,DX			;Position within sector
05400		MOV	AH,[BP+DRVNUM]		;AL=Directory sector no.
05410		CMP	AX,[DIRBUFID]
05420		JZ	HAVDIRBUF
05430		PUSH	BX
05440		CALL	DIRREAD
05450		POP	BX
05460	HAVDIRBUF:
05470		MOV	DX,DIRBUF
05480		ADD	BX,DX
05490		ADD	DX,[BP+SECSIZ]
05500		RET
05510	
05520	NEXTENTRY:
05530	
05540	; Inputs:
05550	;	Same as outputs of GETENTRY, above
05560	; Function:
05570	;	Update AL, BX, and [LASTENT] for next directory entry.
05580	;	Carry set if no more.
05590	
05600		MOV	DI,[LASTENT]
05610		INC	DI
05620		CMP	DI,[BP+MAXENT]
05630		JAE	NONE
05640		MOV	[LASTENT],DI
05650		ADD	BX,32
05660	
05670		IF	SMALLDIR
05680		CMP	B,[BP+DIRSIZ],-1
05690		JNZ	BIGENT3
05700		SUB	BX,16
05710	BIGENT3:
05720		ENDIF
05730	
05740		CMP	BX,DX
05750		JB	HAVIT
05760		INC	AL			;Next directory sector
05770		PUSH	DX			;Save limit
05780		CALL	DIRREAD
05790		POP	DX
05800		MOV	BX,DIRBUF
05810	HAVIT:
05820		CLC
05830		RET
05840	
05850	NONE:
05860		CALL	CHKDIRWRITE
05870		STC
05880		RET
05890	
05900	
05910	DELETE:	; System call 19
05920		CALL	GETFILE
05930		JC	ERRET
05940		CMP	BH,-1		;Check if device name
05950		JZ	ERRET		;Can't delete I/O devices
05960	DELFILE:
05970		MOV	B,[DIRTYDIR],-1
05980		MOV	B,[BX],0E5H
05990		MOV	BX,[SI]
06000		LEA	SI,[BP+FAT]
06010		OR	BX,BX
06020		JZ	DELNXT
06030		CMP	BX,[BP+MAXCLUS]
06040		JA	DELNXT
06050		CALL	RELEASE
06060	DELNXT:
06070		CALL	CONTSRCH
06080		JNC	DELFILE
06090		CALL	FATWRT
06100		CALL	CHKDIRWRITE
06110		XOR	AL,AL
06120		RET
06130	
06140	
06150	RENAME:	;System call 23
06160		CALL	MOVNAME
06170		JC	ERRET
06180		CMP	BH,-1		;Check if I/O device name
06190		JZ	ERRET		;If so, can't rename it
06200		ADD	SI,5
06210		MOV	DI,NAME2
06220		CALL	LODNAME
06230		CALL	FINDNAME
06240		JC	ERRET
06250	RENFIL:
06260		MOV	B,[DIRTYDIR],-1
06270		MOV	DI,BX
06280		MOV	SI,NAME2
06290		MOV	CX,11
06300	NEWNAM:
06310		LODB
06320		CMP	AL,"?"
06330		JZ	NOCHG
06340		MOV	[DI],AL
06350	NOCHG:
06360		INC	DI
06370		LOOP	NEWNAM
06380		CALL	CONTSRCH
06390		JNC	RENFIL
06400		CALL	CHKDIRWRITE
06410		XOR	AL,AL
06420		RET
06430	
06440	ERRET:
06450		MOV	AL,-1
06460		RET
06470	
06480	
06490	MOVNAME:
06500	
06510	; Inputs:
06520	;	DS, DX point to FCB
06530	; Outputs:
06540	;	ES = CS
06550	;	If file name OK:
06560	;	BP has base of driver parameters
06570	;	[NAME1] has name in upper case
06580	; All registers except DX destroyed
06590	; Carry set if bad file name or drive
06600	
06610		MOV	AX,CS
06620		MOV	ES,AX
06630		MOV	DI,NAME1
06640		MOV	SI,DX
06650		LODB
06660		CALL	GETBP
06670		JB	RET
06680	LODNAME:
06690	; This entry point copies a file name from DS,SI
06700	; to ES,DI converting to upper case.
06710		MOV	CX,11
06720	MOVCHK:
06730		LODB
06740		AND	AL,7FH
06750		CMP	AL,60H
06760		JLE	CASEOK
06770		AND	AL,5FH
06780	CASEOK:
06790		CMP	AL,20H
06800		JC	RET
06810		STOB
06820		LOOP	MOVCHK
06830		RET
06840	
06850	GETBP:
06860		SEG	CS
06870		CMP	[NUMDRV],AL
06880		JC	RET
06890		CBW
06900		XCHG	BP,AX
06910		SHL	BP
06920		MOV	BP,[BP+CURDRVPT]
06930		RET
06940	
06950	
06960	OPEN:	;System call 15
06970		PUSH	DX
06980		PUSH	DS
06990		CALL	GETFILE
07000	DOOPEN:
07010	; Enter here to perform OPEN on file already found
07020	; in directory. DS=ES=CS, BX points to directory
07030	; entry in DIRBUF, SI points to First Cluster field, and
07040	; the top of the stack has the address and segment
07050	; of the FCB to be opened. This entry point is used
07060	; by CREATE.
07070		POP	ES
07080		POP	DI
07090		JC	ERRET
07100		CMP	BH,-1		;Check if file is I/O device
07110		JZ	OPENDEV		;Special handler if so
07120		MOV	AL,[BP+DRVNUM]
07130		INC	AL
07140		STOB
07150		ADD	DI,11		;Point to extent field
07160		XOR	AX,AX
07170		STOW			;Set extent field to 0
07180		MOV	AX,128		;Default record size
07190		STOW			;Set record size
07200		LODW			;Get starting cluster
07210		MOV	DX,AX		;Save it for the moment
07220		MOVW			;Transfer size to FCB
07230		MOVW
07240		MOV	AX,[SI-8]	;Get date
07250	
07260		IF	SMALLDIR
07270		CMP	B,[BP+DIRSIZ],-1
07280		JNZ	BIGENT10
07290		SEG	ES
07300		MOV	[DI-1],0
07310		XOR	AX,AX		;Date not available in small entry
07320	BIGENT10:
07330		ENDIF
07340	
07350		STOW			;Save date in FCB
07360		MOV	AX,[LASTENT]
07370		STOW			;directory location
07380		MOV	AX,DX		;Restore starting cluster
07390		STOW			; first cluster
07400		STOW			; last cluster accessed
07410		XOR	AX,AX
07420		STOW			; position of last cluster
07430		STOB			; dirty flag
07440		RET
07450	
07460	OPENDEV:
07470		SEG	ES
07480		MOV	[DI+FILDIRBLK],BX ;Use dir. entry number as flag
07490		XOR	AL,AL
07500		RET
07510	
07520	
07530	STARTSRCH:
07540		MOV	[LASTENT],-1
07550	FATREAD:
07560	
07570	; Inputs:
07580	;	DS = CS
07590	;	BP = Base of drive parameters
07600	; Function:
07610	;	If disk may have been changed, FAT is read in and buffers are
07620	;	flagged invalid. If not, no action is taken.
07630	; Outputs:
07640	;	AL = 0
07650	;	BP unchanged
07660	; All other registers destroyed
07670	
07680		MOV	AL,[BP+DRVNUM]
07690		CALL	BIOSDSKCHG,BIOSSEG	;See what BIOS has to say
07700		MOV	AL,[BP+DRVNUM]
07710		OR	AH,[BP+DIRTYFAT]
07720		JS	NEWDSK		;If either say new disk, then it's so
07730		DEC	AH		;Check for AH=1 (disk not changed)
07740		JZ	RET
07750		MOV	AH,1
07760		CMP	AX,[BUFDRVNO]	;Does buffer have dirty sector of this drive?
07770		JZ	RET		;If so, disk has not been changed
07780	NEWDSK:
07790		CMP	AL,[BUFDRVNO]	;See if buffer is for this drive
07800		JNZ	BUFOK		;If not, don't touch it
07810		MOV	[BUFSECNO],0	;Flag buffers invalid
07820		MOV	[BUFDRVNO],00FFH
07830	BUFOK:
07840		MOV	[DIRBUFID],-1
07850		CALL	FIGFAT
07860	NEXTFAT:
07870		PUSH	DX
07880		PUSH	CX
07890		PUSH	BX
07900		PUSH	AX
07910		CALL	DREAD
07920		OR	AL,AL
07930		POP	AX
07940		POP	BX
07950		POP	CX
07960		POP	DX
07970		JNZ	BADFAT
07980	
07990		IF	SMALLDIR
08000		MOV	DL,AL
08010		LEA	SI,[BP+FIRREC1]	;FIRREC and MAXCLUS for 16-byte dir entries
08020		CMP	B,[BP+DIRSIZ],-1
08030		JZ	SETSIZ
08040		ADD	SI,4		;FIRREC and MAXCLUS for 32-byte entries
08050	SETSIZ:
08060		LODW
08070		MOV	[BP+FIRREC],AX
08080		LODW
08090		MOV	[BP+MAXCLUS],AX
08100		MOV	AL,DL
08110		ENDIF
08120	
08130		SUB	AL,[BP+FATCNT]
08140		JZ	RET
08150		NEG	AL
08160	;{Insert error code here. AL=number of bad fats.
08170	;Since one good FAT was read, should include option
08180	;to rewrite all FATs.}
08190		JMP	FATWRT
08200	
08210	BADFAT:
08220		ADD	DX,CX
08230		DEC	AL
08240		JNZ	NEXTFAT
08250		POP	BP
08260	;{Insert error code here. All FATs on drive are bad.}
08270		MOV	SI,BADFATMES
08280		CALL	HARDERR
08290		JP	FATREAD
08300	
08310	OKRET1:
08320		MOV	AL,0
08330		RET
08340	
08350	CLOSE:	;System call 16
08360		MOV	DI,DX
08370		CMP	B,[DI+FILDIRBLK],-1  ;Check for I/O device
08380		JZ	OKRET1		;Can't close I/O device
08390		TEST	B,[DI+DIRTYFIL],-1
08400		JZ	OKRET1		;If not written to, do nothing
08410		MOV	AL,[DI]		;Get drive number
08420		CALL	GETBP		;Get base of drive parameters
08430		JC	BADCLOSEJ
08440		MOV	AL,[BP+DRVNUM]
08450		MOV	AH,1		;Look for dirty buffer
08460		SEG	CS
08470		CMP	AX,[BUFDRVNO]
08480		JNZ	FNDDIR
08490	;Write back dirty buffer if on same drive
08500		PUSH	DX
08510		PUSH	DS
08520		PUSH	CS
08530		POP	DS
08540		MOV	B,[DIRTYBUF],0
08550		MOV	BX,[BUFFER]
08560		MOV	CX,1
08570		MOV	DX,[BUFSECNO]
08580		CALL	DWRITE
08590		POP	DS
08600		POP	DX
08610	FNDDIR:
08620		PUSH	DX
08630		PUSH	DS
08640		CALL	GETFILE
08650		POP	ES
08660		POP	DI
08670	BADCLOSEJ:
08680		JC	BADCLOSE
08690		MOV	AX,[LASTENT]
08700		SEG	ES
08710		CMP	AX,[DI+FILDIRBLK]
08720		JNZ	BADCLOSE
08730		SEG	ES
08740		MOV	CX,[DI+FIRCLUS]
08750		MOV	[SI],CX
08760		SEG	ES
08770		MOV	DX,[DI+FILSIZ]
08780		MOV	[SI+2],DX
08790		SEG	ES
08800		MOV	DX,[DI+FILSIZ+2]
08810	
08820		IF	SMALLDIR
08830		CMP	B,[BP+DIRSIZ],-1
08840		JNZ	BIGENT11
08850		MOV	[SI+4],DL
08860		JP	SMALLENT2
08870	BIGENT11:
08880		ENDIF
08890	
08900		MOV	[SI+4],DX
08910		SEG	ES
08920		MOV	DX,[DI+FDATE]
08930		MOV	[SI-2],DX
08940	SMALLENT2:
08950		CALL	DIRWRITE
08960	
08970	CHKFATWRT:
08980	; Do FATWRT only if FAT is dirty
08990	
09000		CMP	B,[BP+DIRTYFAT],1
09010		JNZ	OKRET
09020	
09030	FATWRT:
09040	
09050	; Inputs:
09060	;	DS = CS
09070	;	BP = Base of drive parameter table
09080	; Function:
09090	;	Write the FAT back to disk and reset FAT
09100	;	dirty bit.
09110	; Outputs:
09120	;	AL = 0
09130	;	BP unchanged
09140	; All other registers destroyed
09150	
09160		MOV	B,[BP+DIRTYFAT],0
09170		CALL	FIGFAT
09180	EACHFAT:
09190		PUSH	DX
09200		PUSH	CX
09210		PUSH	BX
09220		PUSH	AX
09230		CALL	DWRITE
09240		POP	AX
09250		POP	BX
09260		POP	CX
09270		POP	DX
09280		ADD	DX,CX
09290		DEC	AL
09300		JNZ	EACHFAT
09310	OKRET:
09320		MOV	AL,0
09330		RET
09340	
09350	BADCLOSE:
09360		MOV	B,[BP+DIRTYFAT],0
09370		MOV	AL,-1
09380		RET
09390	
09400	
09410	FIGFAT:
09420	; Loads registers with values needed to read or
09430	; write a FAT.
09440		MOV	AL,[BP+FATCNT]
09450		LEA	BX,[BP+FAT]
09460		MOV	CL,[BP+FATSIZ]	;No. of records occupied by FAT
09470		MOV	CH,0
09480		MOV	DX,[BP+FIRFAT]	;Record number of start of FATs
09490		RET
09500	
09510	
09520	DIRCOMP:
09530	; Prepare registers for directory read or write
09540		CBW
09550		ADD	AX,[BP+FIRDIR]
09560		MOV	DX,AX
09570		MOV	BX,DIRBUF
09580		MOV	CX,1
09590		RET
09600	
09610	
09620	CREATE:	;System call 22
09630		CALL	MOVNAME
09640		JC	ERRET3
09650		MOV	DI,NAME1
09660		MOV	CX,11
09670		MOV	AL,"?"
09680		REPNE
09690		SCAB
09700		JZ	ERRET3
09710		PUSH	DX
09720		PUSH	DS
09730		CALL	FINDNAME
09740		JNC	EXISTENT
09750		CALL	STARTSRCH
09760		CALL	GETENTRY
09770	LOOKFRE:
09780		CMP	B,[BX],0E5H
09790		JZ	FREESPOT
09800		CALL	NEXTENTRY
09810		JNC	LOOKFRE
09820		POP	DS
09830		POP	DX
09840	ERRET3:
09850		MOV	AL,-1
09860		RET
09870	
09880	EXISTENT:
09890		CMP	BH,-1		;Check if file is I/O device
09900		JZ	OPENJMP		;If so, no action
09910		XOR	CX,CX
09920		MOV	[SI+2],CX
09930		MOV	AX,[DATE]
09940	
09950		IF	SMALLDIR
09960		MOV	[SI+4],CL
09970		CMP	B,[BP+DIRSIZ],-1
09980		JZ	SMLENT
09990		MOV	[SI+5],CL
10000		MOV	[SI-2],AX
10010	SMLENT:
10020		ENDIF
10030	
10040		IF	1-SMALLDIR
10050		MOV	[SI+4],CX
10060		MOV	[SI-2],AX
10070		ENDIF
10080	
10090		XCHG	CX,[SI]
10100		PUSH	SI
10110		PUSH	BX
10120		JCXZ	WRTBACK
10130		CMP	CX,[BP+MAXCLUS]
10140		JA	WRTBACK
10150		MOV	BX,CX
10160		LEA	SI,[BP+FAT]
10170		CALL	RELEASE
10180		CALL	FATWRT
10190		JP	WRTBACK
10200	
10210	FREESPOT:
10220		MOV	DI,BX
10230		MOV	SI,NAME1
10240		MOV	CX,5
10250		MOVB
10260		REP
10270		MOVW
10280		XOR	AX,AX
10290	
10300		IF	SMALLDIR
10310		CMP	B,[BP+DIRSIZ],-1
10320		JNZ	BIGENT4
10330		PUSH	DI
10340		MOV	CL,5
10350		JP	SMALLENT
10360	BIGENT4:
10370		ENDIF
10380	
10390		MOV	CL,13
10400		REP
10410		STOB
10420		MOV	AX,[DATE]
10430		STOW
10440		XOR	AX,AX
10450		PUSH	DI
10460		MOV	CL,6
10470	SMALLENT:
10480		REP
10490		STOB
10500		PUSH	BX
10510	WRTBACK:
10520		CALL	DIRWRITE
10530		POP	BX
10540		POP	SI
10550	OPENJMP:
10560		CLC			;Clear carry so OPEN won't fail
10570		JMP	DOOPEN
10580	
10590	
10600	DIRREAD:
10610	
10620	; Inputs:
10630	;	DS = CS
10640	;	AL = Directory block number
10650	;	BP = Base of drive parameters
10660	; Function:
10670	;	Read the directory block into DIRBUF.
10680	; Outputs:
10690	;	AX,BP unchanged
10700	; All other registers destroyed.
10710	
10720		PUSH	AX
10730		CALL	CHKDIRWRITE
10740		POP	AX
10750		PUSH	AX
10760		MOV	AH,[BP+DRVNUM]
10770		MOV	[DIRBUFID],AX
10780		CALL	DIRCOMP
10790		CALL	DREAD
10800		POP	AX
10810		RET
10820	
10830	
10840	DREAD:
10850	
10860	; Inputs:
10870	;	BX,DS = Transfer address
10880	;	CX = Number of sectors
10890	;	DX = Absolute record number
10900	;	BP = Base of drive parameters
10910	; Function:
10920	;	Calls BIOS to perform disk read. If BIOS reports
10930	;	errors, will call HARDERR for further action.
10940	; Outputs:
10950	;	AL = 0 if no error, otherwise non-zero
10960	; BP preserved. All other registers destroyed.
10970	
10980		MOV	AL,[BP+DRVNUM]
10990		PUSH	BP
11000		PUSH	BX
11010		PUSH	CX
11020		PUSH	DX
11030		CALL	BIOSREAD,BIOSSEG
11040		POP	DX
11050		POP	DI
11060		POP	BX
11070		POP	BP
11080		JC	HARDREAD
11090		XOR	AL,AL
11100		RET
11110	
11120	HARDREAD:
11130		MOV	SI,RDERRMES
11140		CALL	HARDERR
11150		JP	DREAD
11160	
11170	
11180	CHKDIRWRITE:
11190		TEST	B,[DIRTYDIR],-1
11200		JZ	RET
11210	
11220	DIRWRITE:
11230	
11240	; Inputs:
11250	;	DS = CS
11260	;	AL = Directory block number
11270	;	BP = Base of drive parameters
11280	; Function:
11290	;	Write the directory block into DIRBUF.
11300	; Outputs:
11310	;	BP unchanged
11320	; All other registers destroyed.
11330	
11340		MOV	B,[DIRTYDIR],0
11350		MOV	AL,[DIRBUFID]
11360		CALL	DIRCOMP
11370	
11380	
11390	DWRITE:
11400	
11410	; Inputs:
11420	;	BX,DS = Transfer address
11430	;	CX = Number of sectors
11440	;	DX = Absolute record number
11450	;	BP = Base of drive parameters
11460	; Function:
11470	;	Calls BIOS to perform disk write. If BIOS reports
11480	;	errors, will call HARDERR for further action.
11490	; Outputs:
11500	;	AL = 0 if no error, otherwise non-zero
11510	; BP preserved. All other registers destroyed.
11520	
11530		MOV	AL,[BP+DRVNUM]
11540	WRTDRV:
11550		PUSH	AX
11560		PUSH	BP
11570		PUSH	BX
11580		PUSH	CX
11590		PUSH	DX
11600		CALL	BIOSWRITE,BIOSSEG
11610		POP	DX
11620		POP	DI
11630		POP	BX
11640		POP	BP
11650		POP	AX
11660		JC	HARDWRITE
11670		XOR	AL,AL
11680		RET
11690	HARDWRITE:
11700		MOV	SI,WRTERRMES
11710		CALL	HARDERR
11720		JP	WRTDRV
11730	
11740	
11750	HARDERR:
11760		SUB	DI,CX
11770		ADD	DX,DI
11780		CALL	SHFTDI7
11790		ADD	BX,DI
11800		MOV	AH,AL		;Save drive number
11810		CALL	OUTMES
11820	GETINSTR:
11830		CALL	IN
11840		OR	AL,20H
11850		CMP	AL,"a"
11860		JZ	ERROR
11870		CMP	AL,"r"
11880		JZ	RETRY
11890		CMP	AL,"i"
11900		JZ	IGNORE
11910		CMP	AL,"c"
11920		JNZ	GETINSTR
11930	CONTINUE:
11940		POP	AX
11950		MOV	AL,1
11960		RET
11970	IGNORE:
11980		POP	AX
11990		MOV	AL,0
12000		RET
12010	RETRY:
12020		MOV	AL,AH		;Restore drive number
12030		RET
12040	
12050	
12060	ABORT:
12070		SEG	CS
12080		MOV	DS,[CSLOC]
12090		XOR	AX,AX
12100		MOV	ES,AX
12110		MOV	SI,SAVEXIT
12120		MOV	DI,EXIT
12130		MOVW
12140		MOVW
12150		MOVW
12160		MOVW
12170	ERROR:
12180		MOV	AX,CS
12190		MOV	DS,AX
12200		MOV	ES,AX
12210		CALL	WRTFATS
12220		XOR	AX,AX
12230		DI
12240		MOV	SS,[SSSAVE]
12250		MOV	SP,[SPSAVE]
12260		MOV	DS,AX
12270		MOV	SI,EXIT
12280		MOV	DI,EXITHOLD
12290		MOVW
12300		MOVW
12310		POP	AX
12320		POP	BX
12330		POP	CX
12340		POP	DX
12350		POP	SI
12360		POP	DI
12370		POP	BP
12380		POP	DS
12390		POP	ES
12400		EI			;Stack OK now
12410		SEG	CS
12420		JMP	L,[EXITHOLD]
12430	
12440	
12450	SEQRD:	;System call 20
12460		CALL	GETREC
12470		CALL	LOAD
12480		JP	FINSEQ
12490	
12500	SEQWRT:	;System call 21
12510		CALL	GETREC
12520		CALL	STORE
12530	FINSEQ:
12540		JCXZ	SETNREX
12550		ADD	AX,1
12560		ADC	DX,0
12570		JP	SETNREX
12580	
12590	RNDRD:	;System call 33
12600		CALL	GETRRPOS1
12610		CALL	LOAD
12620		JP	FINRND
12630	
12640	RNDWRT:	;System call 34
12650		CALL	GETRRPOS1
12660		CALL	STORE
12670		JP	FINRND
12680	
12690	BLKRD:	;System call 39
12700		CALL	GETRRPOS
12710		CALL	LOAD
12720		JP	FINBLK
12730	
12740	BLKWRT:	;System call 40
12750		CALL	GETRRPOS
12760		CALL	STORE
12770	FINBLK:
12780		LDS	SI,[SPSAVE]
12790		MOV	[SI+CXSAVE],CX
12800		JCXZ	FINRND
12810		ADD	AX,1
12820		ADC	DX,0
12830	FINRND:
12840		SEG	ES
12850		MOV	[DI+RR],AX
12860		SEG	ES
12870		MOV	[DI+RR+2],DL
12880		OR	DH,DH
12890		JZ	SETNREX
12900		SEG	ES
12910		MOV	[DI+RR+3],DH	;Save 4 byte of RECPOS only if significant
12920	SETNREX:
12930		MOV	CX,AX
12940		AND	AL,7FH
12950		SEG	ES
12960		MOV	[DI+NR],AL
12970		AND	CL,80H
12980		SHL	CX
12990		RCL	DX
13000		MOV	AL,CH
13010		MOV	AH,DL
13020		SEG	ES
13030		MOV	[DI+EXTENT],AX
13040		SEG	CS
13050		MOV	AL,[DSKERR]
13060		RET
13070	
13080	GETRRPOS1:
13090		MOV	CX,1
13100	GETRRPOS:
13110		MOV	DI,DX
13120		MOV	AX,[DI+RR]
13130		MOV	DX,[DI+RR+2]
13140		RET
13150	
13160	NOFILERR:
13170		XOR	CX,CX
13180		MOV	B,[DSKERR],-2
13190		POP	BX
13200		RET
13210	
13220	SETUP:
13230	
13240	; Inputs:
13250	;	DS:DI point to FCB
13260	;	DX:AX = Record position in file of disk transfer
13270	;	CX = Record count
13280	; Outputs:
13290	;	DS = CS
13300	;	ES:DI point to FCB
13310	;	CX = No. of bytes to transfer
13320	;	BP = Base of drive parameters
13330	;	SI = FAT pointer
13340	;	[RECCNT] = Record count
13350	;	[RECPOS] = Record position in file
13360	;	[FCB] = DI
13370	;	[NEXTADD] = Displacement of disk transfer within segment
13380	;	[SECPOS] = Position of first sector
13390	;	[BYTPOS] = Byte position in file
13400	;	[BYTSECPOS] = Byte position in first sector
13410	;	[CLUSNUM] = First cluster
13420	;	[SECCLUSPOS] = Sector within first cluster
13430	;	[DSKERR] = 0 (no errors yet)
13440	;	[TRANS] = 0 (No transfers yet)
13450	; If SETUP detects no records will be transfered, it returns 1 level up 
13460	; with CX = 0.
13470	
13480		PUSH	AX
13490		MOV	AL,[DI]
13500		MOV	SI,[DI+RECSIZ]
13510		OR	SI,SI
13520		JNZ	HAVRECSIZ
13530		MOV	SI,128
13540		MOV	[DI+RECSIZ],SI
13550	HAVRECSIZ:
13560		MOV	BX,DS
13570		MOV	ES,BX
13580		MOV	BX,CS
13590		MOV	DS,BX
13600		CALL	GETBP
13610		POP	AX
13620		JC	NOFILERR
13630		CMP	SI,64		;Check if highest byte of RECPOS is significant
13640		JB	SMALREC
13650		MOV	DH,0		;Ignore MSB if record >= 64 bytes
13660	SMALREC:
13670		MOV	[RECCNT],CX
13680		MOV	[RECPOS],AX
13690		MOV	[RECPOS+2],DX
13700		MOV	[FCB],DI
13710		MOV	BX,[DMAADD]
13720		MOV	[NEXTADD],BX
13730		MOV	B,[DSKERR],0
13740		MOV	B,[TRANS],0
13750		MOV	BX,DX
13760		MUL	AX,SI
13770		MOV	[BYTPOS],AX
13780		PUSH	DX
13790		MOV	AX,BX
13800		MUL	AX,SI
13810		POP	BX
13820		ADD	AX,BX
13830		ADC	DX,0		;Ripple carry
13840		JNZ	EOFERR
13850		MOV	[BYTPOS+2],AX
13860		MOV	DX,AX
13870		MOV	AX,[BYTPOS]
13880		DIV	AX,[BP+SECSIZ]
13890		MOV	[SECPOS],AX
13900		MOV	[BYTSECPOS],DX
13910		MOV	DX,AX
13920		AND	AL,[BP+CLUSMSK]
13930		MOV	[SECCLUSPOS],AL
13940		MOV	AX,CX		;Record count
13950		MOV	CL,[BP+CLUSSHFT]
13960		SHR	DX,CL
13970		MOV	[CLUSNUM],DX
13980		MUL	AX,SI		;Multiply by bytes per record
13990		MOV	CX,AX
14000		ADD	AX,[DMAADD]	;See if it will fit in one segment
14010		ADC	DX,0
14020		JZ	OK		;Must stay within 64K
14030		MOV	AX,[DMAADD]
14040		NEG	AX		;Amount of room left in segment
14050		XOR	DX,DX
14060		DIV	AX,SI		;How many records will fit?
14070		MUL	AX,SI		;Translate that back into bytes
14080		MOV	B,[DSKERR],2	;Flag that trimming took place
14090		MOV	CX,AX
14100		JCXZ	NOROOM
14110	OK:
14120		LEA	SI,[BP+FAT]
14130		RET
14140	
14150	EOFERR:
14160		MOV	B,[DSKERR],1
14170		XOR	CX,CX
14180	NOROOM:
14190		POP	BX		;Kill return address
14200		RET
14210	
14220	BREAKDOWN:
14230	
14240	;Inputs:
14250	;	DS = CS
14260	;	CX = Length of disk transfer in bytes
14270	;	BP = Base of drive parameters
14280	;	[BYTSECPOS] = Byte position witin first sector
14290	;Outputs:
14300	;	[BYTCNT1] = Bytes to transfer in first sector
14310	;	[SECCNT] = No. of whole sectors to transfer
14320	;	[BYTCNT2] = Bytes to transfer in last sector
14330	;AX, BX, DX destroyed. No other registers affected.
14340	
14350		MOV	AX,[BYTSECPOS]
14360		MOV	BX,CX
14370		OR	AX,AX
14380		JZ	SAVFIR		;Partial first sector?
14390		SUB	AX,[BP+SECSIZ]
14400		NEG	AX		;Max number of bytes left in first sector
14410		SUB	BX,AX		;Subtract from total length
14420		JAE	SAVFIR
14430		ADD	AX,BX		;Don't use all of the rest of the sector
14440		XOR	BX,BX		;And no bytes are left
14450	SAVFIR:
14460		MOV	[BYTCNT1],AX
14470		MOV	AX,BX
14480		XOR	DX,DX
14490		DIV	AX,[BP+SECSIZ]	;How many whole sectors?
14500		MOV	[SECCNT],AX
14510		MOV	[BYTCNT2],DX	;Bytes remaining for last sector
14520		RET
14530	
14540	
14550	FNDCLUS:
14560	
14570	; Inputs:
14580	;	DS = CS
14590	;	CX = No. of clusters to skip
14600	;	BP = Base of drive parameters
14610	;	SI = FAT pointer
14620	;	ES:DI point to FCB
14630	; Outputs:
14640	;	BX = Last cluster skipped to
14650	;	CX = No. of clusters remaining (0 unless EOF)
14660	;	DX = Position of last cluster
14670	; DI destroyed. No other registers affected.
14680	
14690		SEG	ES
14700		MOV	BX,[DI+LSTCLUS]
14710		SEG	ES
14720		MOV	DX,[DI+CLUSPOS]
14730		OR	BX,BX
14740		JZ	NOCLUS
14750		SUB	CX,DX
14760		JNB	FINDIT
14770		ADD	CX,DX
14780		XOR	DX,DX
14790		SEG	ES
14800		MOV	BX,[DI+FIRCLUS]
14810	FINDIT:
14820		JCXZ	RET
14830	SKPCLP:
14840		CALL	UNPACK
14850		CMP	DI,0FF8H
14860		JAE	RET
14870		XCHG	BX,DI
14880		INC	DX
14890		LOOP	SKPCLP
14900		RET
14910	NOCLUS:
14920		INC	CX
14930		DEC	DX
14940		RET
14950	
14960	
14970	BUFSEC:
14980	; Inputs:
14990	;	AL = 0 if buffer must be read, 1 if no pre-read needed
15000	;	BP = Base of drive parameters
15010	;	[CLUSNUM] = Physical cluster number
15020	;	[SECCLUSPOS] = Sector position of transfer within cluster
15030	;	[BYTCNT1] = Size of transfer
15040	; Function:
15050	;	Insure specified sector is in buffer, flushing buffer before
15060	;	read if necessary.
15070	; Outputs:
15080	;	SI = Pointer to buffer
15090	;	DI = Pointer to transfer address
15100	;	CX = Number of bytes
15110	;	[NEXTADD] updated
15120	;	[TRANS] set to indicate a transfer will occur
15130	
15140		MOV	DX,[CLUSNUM]
15150		MOV	BL,[SECCLUSPOS]
15160		CALL	FIGREC
15170		OR	AL,AL
15180		JNZ	SETBUF
15190		CMP	DX,[BUFSECNO]
15200		JNZ	GETSEC
15210		MOV	AL,[BUFDRVNO]
15220		CMP	AL,[BP+DRVNUM]
15230		JZ	FINBUF		;Already have it?
15240	GETSEC:
15250		TEST	B,[DIRTYBUF],-1
15260		JZ	RDSEC
15270		PUSH	DX
15280		MOV	AL,[BUFDRVNO]
15290		MOV	BX,[BUFFER]
15300		MOV	CX,1
15310		MOV	DX,[BUFSECNO]
15320		CALL	WRTDRV
15330		POP	DX
15340	RDSEC:
15350		MOV	BX,[BUFFER]
15360		MOV	CX,1
15370		PUSH	DX
15380		CALL	DREAD
15390		POP	DX
15400	SETBUF:
15410		MOV	[BUFSECNO],DX
15420		MOV	AL,[BP+DRVNUM]
15430		MOV	AH,0
15440		MOV	[BUFDRVNO],AX
15450	FINBUF:
15460		MOV	B,[TRANS],1	;A transfer is taking place
15470		MOV	DI,[NEXTADD]
15480		MOV	SI,DI
15490		MOV	CX,[BYTCNT1]
15500		ADD	SI,CX
15510		MOV	[NEXTADD],SI
15520		MOV	SI,[BUFFER]
15530		ADD	SI,[BYTSECPOS]
15540		RET
15550	
15560	BUFRD:
15570		XOR	AL,AL		;Pre-read necessary
15580		CALL	BUFSEC
15590		PUSH	ES
15600		MOV	ES,[DMAADD+2]
15610		SHR	CX
15620		JNC	EVENRD
15630		MOVB
15640	EVENRD:
15650		REP
15660		MOVW
15670		POP	ES
15680		RET
15690	
15700	BUFWRT:
15710		MOV	AX,[SECPOS]
15720		INC	AX		;Set for next sector
15730		MOV	[SECPOS],AX
15740		CMP	AX,[VALSEC]	;Has sector been written before?
15750		MOV	AL,1
15760		JA	NOREAD		;Skip preread if SECPOS>VALSEC
15770		MOV	AL,0
15780	NOREAD:
15790		CALL	BUFSEC
15800		XCHG	DI,SI
15810		PUSH	DS
15820		PUSH	ES
15830		PUSH	CS
15840		POP	ES
15850		MOV	DS,[DMAADD+2]
15860		SHR	CX
15870		JNC	EVENWRT
15880		MOVB
15890	EVENWRT:
15900		REP
15910		MOVW
15920		POP	ES
15930		POP	DS
15940		MOV	B,[DIRTYBUF],1
15950		RET
15960	
15970	NEXTSEC:
15980		TEST	B,[TRANS],-1
15990		JZ	CLRET
16000		MOV	AL,[SECCLUSPOS]
16010		INC	AL
16020		CMP	AL,[BP+CLUSMSK]
16030		JBE	SAVPOS
16040		MOV	BX,[CLUSNUM]
16050		CMP	BX,0FF8H
16060		JAE	NONEXT
16070		LEA	SI,[BP+FAT]
16080		CALL	UNPACK
16090		MOV	[CLUSNUM],DI
16100		INC	[LASTPOS]
16110		MOV	AL,0
16120	SAVPOS:
16130		MOV	[SECCLUSPOS],AL
16140	CLRET:
16150		CLC
16160		RET
16170	NONEXT:
16180		STC
16190		RET
16200	
16210	TRANBUF:
16220		LODB
16230		STOB
16240		CMP	AL,13		;Check for carriage return
16250		JNZ	NORMCH
16260		MOV	[SI],10
16270	NORMCH:
16280		CMP	AL,10
16290		LOOPNZ	TRANBUF
16300		JNZ	ENDRDCON
16310		CALL	OUT		;Transmit linefeed
16320		XOR	SI,SI
16330		OR	CX,CX
16340		JNZ	GETBUF
16350		OR	AL,1		;Clear zero flag--not end of file
16360	ENDRDCON:
16370		MOV	[CONTPOS],SI
16380	ENDRDDEV:
16390		MOV	[NEXTADD],DI
16400		POP	ES
16410		JNZ	SETFCBJ		;Zero set if Ctrl-Z found in input
16420		MOV	DI,[FCB]
16430		SEG	ES
16440		OR	B,[DI+FILDIRBLK],80H	;Mark as no more data available
16450	SETFCBJ:
16460		JMP	SETFCB
16470	
16480	READDEV:
16490		PUSH	ES
16500		LES	DI,[DMAADD]
16510		OR	BL,BL
16520		JZ	READCON
16530		DEC	BL
16540		JNZ	ENDRDDEV
16550	READAUX:
16560		CALL	BIOSAUXIN,BIOSSEG
16570		STOB
16580		CMP	AL,1AH
16590		LOOPNZ	READAUX
16600		JP	ENDRDDEV
16610	
16620	READCON:
16630		PUSH	CS
16640		POP	DS
16650		MOV	SI,[CONTPOS]
16660		OR	SI,SI
16670		JNZ	TRANBUF
16680		CMP	B,[CONBUF],128
16690		JZ	GETBUF
16700		MOV	[CONBUF],0FF80H	;Set up 128-byte buffer with no template
16710	GETBUF:
16720		PUSH	CX
16730		PUSH	ES
16740		PUSH	DI
16750		MOV	DX,CONBUF
16760		CALL	BUFIN		;Get input buffer
16770		POP	DI
16780		POP	ES
16790		POP	CX
16800		MOV	SI,CONBUF+2
16810		CMP	B,[SI],1AH	;Check for Ctrl-Z in first character
16820		JNZ	TRANBUF
16830		MOV	AL,1AH
16840		STOB
16850		MOV	AL,10
16860		CALL	OUT		;Send linefeed
16870		XOR	SI,SI
16880		JP	ENDRDCON
16890	
16900	RDERR:
16910		XOR	CX,CX
16920		JMP	WRTERR
16930	
16940	RDLASTJ:JMP	RDLAST
16950	
16960	LOAD:
16970	
16980	; Inputs:
16990	;	DS:DI point to FCB
17000	;	DX:AX = Position in file to read
17010	;	CX = No. of records to read
17020	; Outputs:
17030	;	DX:AX = Position of last record read
17040	;	CX = No. of bytes read
17050	;	ES:DI point to FCB
17060	;	LSTCLUS, CLUSPOS fields in FCB set
17070	
17080		CALL	SETUP
17090		SEG	ES
17100		MOV	BX,[DI+FILDIRBLK]
17110		CMP	BH,-1		;Check for named device I/O
17120		JZ	READDEV
17130		SEG	ES
17140		MOV	AX,[DI+FILSIZ]
17150		SEG	ES
17160		MOV	BX,[DI+FILSIZ+2]
17170		SUB	AX,[BYTPOS]
17180		SBC	BX,[BYTPOS+2]
17190		JB	RDERR
17200		JNZ	ENUF
17210		OR	AX,AX
17220		JZ	RDERR
17230		CMP	AX,CX
17240		JAE	ENUF
17250		MOV	CX,AX
17260	ENUF:
17270		CALL	BREAKDOWN
17280		MOV	CX,[CLUSNUM]
17290		CALL	FNDCLUS
17300		OR	CX,CX
17310		JNZ	RDERR
17320		MOV	[LASTPOS],DX
17330		MOV	[CLUSNUM],BX
17340		CMP	[BYTCNT1],0
17350		JZ	RDMID
17360		CALL	BUFRD
17370	RDMID:
17380		CMP	[SECCNT],0
17390		JZ	RDLASTJ
17400		CALL	NEXTSEC
17410		JC	SETFCB
17420		MOV	B,[TRANS],1	;A transfer is taking place
17430	ONSEC:
17440		MOV	DL,[SECCLUSPOS]
17450		MOV	CX,[SECCNT]
17460		MOV	BX,[CLUSNUM]
17470	RDLP:
17480		CALL	OPTIMIZE
17490		PUSH	DI
17500		PUSH	AX
17510		PUSH	DS
17520		MOV	DS,[DMAADD+2]
17530		CALL	DREAD
17540		POP	DS
17550		POP	CX
17560		POP	BX
17570		JCXZ	RDLAST
17580		CMP	BX,0FF8H
17590		JAE	SETFCB
17600		MOV	DL,0
17610		INC	[LASTPOS]	;We'll be using next cluster
17620		JP	RDLP
17630	
17640	SETFCB:
17650		MOV	SI,[FCB]
17660		MOV	AX,[NEXTADD]
17670		MOV	DI,AX
17680		SUB	AX,[DMAADD]	;Number of bytes transfered
17690		XOR	DX,DX
17700		SEG	ES
17710		MOV	CX,[SI+RECSIZ]
17720		DIV	AX,CX		;Number of records
17730		CMP	AX,[RECCNT]	;Check if all records transferred
17740		JZ	FULLREC
17750		MOV	B,[DSKERR],1
17760		OR	DX,DX
17770		JZ	FULLREC		;If remainder 0, then full record transfered
17780		MOV	B,[DSKERR],3	;Flag partial last record
17790		SUB	CX,DX		;Bytes left in last record
17800		PUSH	ES
17810		MOV	ES,[DMAADD+2]
17820		XCHG	AX,BX		;Save the record count temporarily
17830		XOR	AX,AX		;Fill with zeros
17840		SHR	CX
17850		JNC	EVENFIL
17860		STOB
17870	EVENFIL:
17880		REP
17890		STOW
17900		XCHG	AX,BX		;Restore record count to AX
17910		POP	ES
17920		INC	AX		;Add last (partial) record to total
17930	FULLREC:
17940		MOV	CX,AX
17950		MOV	DI,SI		;ES:DI point to FCB
17960	SETCLUS:
17970		MOV	AX,[CLUSNUM]
17980		SEG	ES
17990		MOV	[DI+LSTCLUS],AX
18000		MOV	AX,[LASTPOS]
18010		SEG	ES
18020		MOV	[DI+CLUSPOS],AX
18030	ADDREC:
18040		MOV	AX,[RECPOS]
18050		MOV	DX,[RECPOS+2]
18060		DEC	CX
18070		ADD	AX,CX		;Update current record position
18080		ADC	DX,0
18090		INC	CX	
18100		RET
18110	
18120	RDLAST:
18130		MOV	AX,[BYTCNT2]
18140		OR	AX,AX
18150		JZ	SETFCB
18160		MOV	[BYTCNT1],AX
18170		CALL	NEXTSEC
18180		JC	SETFCB
18190		MOV	[BYTSECPOS],0
18200		CALL	BUFRD
18210		JP	SETFCB
18220	
18230	WRTDEV:
18240		PUSH	DS
18250		LDS	SI,[DMAADD]
18260		AND	BL,7FH
18270		OR	BL,BL
18280		JZ	WRTCON
18290		DEC	BL
18300		JZ	WRTAUX
18310	WRTLST:
18320		LODB
18330		CMP	AL,1AH
18340		JZ	ENDWRDEV
18350		CALL	BIOSPRINT,BIOSSEG
18360		LOOP	WRTLST
18370		JP	ENDWRDEV
18380	
18390	WRTAUX:
18400		LODB
18410		CALL	BIOSAUXOUT,BIOSSEG
18420		CMP	AL,1AH
18430		LOOPNZ	WRTAUX
18440		JP	ENDWRDEV
18450	
18460	WRTCON:
18470		LODB
18480		CMP	AL,1AH
18490		JZ	ENDWRDEV
18500		CALL	OUT
18510		LOOP	WRTCON
18520	ENDWRDEV:
18530		POP	DS
18540		MOV	CX,[RECCNT]
18550		MOV	DI,[FCB]
18560		JP	ADDREC
18570	
18580	HAVSTART:
18590		MOV	CX,AX
18600		CALL	SKPCLP
18610		JCXZ	DOWRTJ
18620		CALL	ALLOCATE
18630		JNC	DOWRTJ
18640	WRTERR:
18650		MOV	B,[DSKERR],1
18660	LVDSK:
18670		MOV	AX,[RECPOS]
18680		MOV	DX,[RECPOS+2]
18690		MOV	DI,[FCB]
18700		RET
18710	
18720	DOWRTJ:	JMP	DOWRT
18730	
18740	WRTEOFJ:
18750		JMP	WRTEOF
18760	
18770	STORE:
18780	
18790	; Inputs:
18800	;	DS:DI point to FCB
18810	;	DX:AX = Position in file of disk transfer
18820	;	CX = Record count
18830	; Outputs:
18840	;	DX:AX = Position of last record written
18850	;	CX = No. of records written
18860	;	ES:DI point to FCB
18870	;	LSTCLUS, CLUSPOS fields in FCB set
18880	
18890		MOV	B,[DI+DIRTYFIL],1
18900		SEG	CS
18910		MOV	BX,[DATE]
18920		MOV	[DI+FDATE],BX
18930		CALL	SETUP
18940		SEG	ES
18950		MOV	BX,[DI+FILDIRBLK]
18960		CMP	BH,-1
18970		JZ	WRTDEV
18980		CALL	BREAKDOWN
18990		MOV	AX,[BYTPOS]
19000		MOV	DX,[BYTPOS+2]
19010		JCXZ	WRTEOFJ
19020		DEC	CX
19030		ADD	AX,CX
19040		ADC	DX,0		;AX:DX=last byte accessed
19050		DIV	AX,[BP+SECSIZ]	;AX=last sector accessed
19060		MOV	CL,[BP+CLUSSHFT]
19070		SHR	AX,CL		;Last cluster to be accessed
19080		PUSH	AX
19090		SEG	ES
19100		MOV	AX,[DI+FILSIZ]
19110		SEG	ES
19120		MOV	DX,[DI+FILSIZ]
19130		DIV	AX,[BP+SECSIZ]
19140		OR	DX,DX
19150		JZ	NORNDUP
19160		INC	AX		;Round up if any remainder
19170	NORNDUP:
19180		MOV	[VALSEC],AX	;Number of sectors that have been written
19190		POP	AX
19200		MOV	CX,[CLUSNUM]	;First cluster accessed
19210		CALL	FNDCLUS
19220		MOV	[CLUSNUM],BX
19230		MOV	[LASTPOS],DX
19240		SUB	AX,DX		;Last cluster minus current cluster
19250		JZ	DOWRT		;If we have last clus, we must have first
19260		JCXZ	HAVSTART
19270		PUSH	CX		;No. of clusters short of first
19280		MOV	CX,AX
19290		CALL	ALLOCATE
19300		POP	AX
19310		JC	WRTERR
19320		MOV	CX,AX
19330		MOV	DX,[LASTPOS]
19340		INC	DX
19350		DEC	CX
19360		JZ	NOSKIP
19370		CALL	SKPCLP
19380	NOSKIP:
19390		MOV	[CLUSNUM],BX
19400		MOV	[LASTPOS],DX
19410	DOWRT:
19420		CMP	[BYTCNT1],0
19430		JZ	WRTMID
19440		MOV	BX,[CLUSNUM]
19450		CALL	BUFWRT	
19460	WRTMID:
19470		MOV	AX,[SECCNT]
19480		OR	AX,AX
19490		JZ	WRTLAST
19500		ADD	[SECPOS],AX
19510		CALL	NEXTSEC
19520		MOV	B,[TRANS],1	;A transfer is taking place
19530		MOV	DL,[SECCLUSPOS]
19540		MOV	BX,[CLUSNUM]
19550		MOV	CX,[SECCNT]
19560	WRTLP:
19570		CALL	OPTIMIZE
19580		PUSH	DI
19590		PUSH	AX
19600		PUSH	DS
19610		MOV	DS,[DMAADD+2]
19620		CALL	DWRITE
19630		POP	DS
19640		POP	CX
19650		POP	BX
19660		JCXZ	WRTLAST
19670		MOV	DL,0
19680		INC	[LASTPOS]	;We'll be using next cluster
19690		JP	WRTLP
19700	WRTLAST:
19710		MOV	AX,[BYTCNT2]
19720		OR	AX,AX
19730		JZ	FINWRT
19740		MOV	[BYTCNT1],AX
19750		CALL	NEXTSEC
19760		MOV	[BYTSECPOS],0
19770		CALL	BUFWRT
19780	FINWRT:
19790		MOV	AX,[NEXTADD]
19800		SUB	AX,[DMAADD]
19810		ADD	AX,[BYTPOS]
19820		MOV	DX,[BYTPOS+2]
19830		ADC	DX,0
19840		MOV	CX,DX
19850		MOV	DI,[FCB]
19860		SEG	ES
19870		CMP	AX,[DI+FILSIZ]
19880		SEG	ES
19890		SBB	CX,[DI+FILSIZ+2]
19900		JB	SAMSIZ
19910		SEG	ES
19920		MOV	[DI+FILSIZ],AX
19930		SEG	ES
19940		MOV	[DI+FILSIZ+2],DX
19950	SAMSIZ:
19960		MOV	CX,[RECCNT]
19970		JMP	SETCLUS
19980	
19990	
20000	WRTERRJ:JMP	WRTERR
20010	
20020	WRTEOF:
20030		MOV	CX,AX
20040		OR	CX,DX
20050		JZ	KILLFIL
20060		SUB	AX,1
20070		SBC	DX,0
20080		DIV	AX,[BP+SECSIZ]
20090		MOV	CL,[BP+CLUSSHFT]
20100		SHR	AX,CL
20110		MOV	CX,AX
20120		CALL	FNDCLUS
20130		JCXZ	RELFILE
20140		CALL	ALLOCATE
20150		JC	WRTERRJ
20160	UPDATE:
20170		MOV	DI,[FCB]
20180		MOV	AX,[BYTPOS]
20190		SEG	ES
20200		MOV	[DI+FILSIZ],AX
20210		MOV	AX,[BYTPOS+2]
20220		SEG	ES
20230		MOV	[DI+FILSIZ+2],AX
20240		XOR	CX,CX
20250		RET
20260	
20270	RELFILE:
20280		MOV	DX,0FFFH
20290		CALL	RELBLKS
20300	SETDIRT:
20310		MOV	B,[BP+DIRTYFAT],1
20320		JP	UPDATE
20330	
20340	KILLFIL:
20350		XOR	BX,BX
20360		SEG	ES
20370		XCHG	BX,[DI+FIRCLUS]
20380		OR	BX,BX
20390		JZ	UPDATE
20400		CALL	RELEASE
20410		JP	SETDIRT
20420	
20430	
20440	OPTIMIZE:
20450	
20460	; Inputs:
20470	;	DS = CS
20480	;	BX = Physical cluster
20490	;	CX = No. of records
20500	;	DL = sector within cluster
20510	;	BP = Base of drives parameters
20520	;	[NEXTADD] = transfer address
20530	; Outputs:
20540	;	AX = No. of records remaining
20550	;	BX = Transfer address
20560	;	CX = No. or records to be transferred
20570	;	DX = Physical sector address
20580	;	DI = Next cluster
20590	;	[CLUSNUM] = Last cluster accessed
20600	;	[NEXTADD] updated
20610	; BP unchanged. Note that segment of transfer not set.
20620	
20630		PUSH	DX
20640		PUSH	BX
20650		MOV	AL,[BP+CLUSMSK]
20660		INC	AL		;Number of sectors per cluster
20670		MOV	AH,AL
20680		SUB	AL,DL		;AL = Number of sectors left in first cluster
20690		MOV	DX,CX
20700		LEA	SI,[BP+FAT]
20710		MOV	CX,0
20720	OPTCLUS:
20730	;AL has number of sectors available in current cluster
20740	;AH has number of sectors available in next cluster
20750	;BX has current physical cluster
20760	;CX has number of sequential sectors found so far
20770	;DX has number of sectors left to transfer
20780	;SI has FAT pointer
20790		CALL	UNPACK
20800		ADD	CL,AL
20810		ADC	CH,0
20820		CMP	CX,DX
20830		JAE	BLKDON
20840		MOV	AL,AH
20850		INC	BX
20860		CMP	DI,BX
20870		JZ	OPTCLUS
20880		DEC	BX
20890	FINCLUS:
20900		MOV	[CLUSNUM],BX	;Last cluster accessed
20910		SUB	DX,CX		;Number of sectors still needed
20920		PUSH	DX
20930		MOV	AX,CX
20940		MUL	AX,[BP+SECSIZ]	;Number of sectors times sector size
20950		MOV	SI,[NEXTADD]
20960		ADD	AX,SI		;Adjust by size of transfer
20970		MOV	[NEXTADD],AX
20980		POP	AX		;Number of sectors still needed
20990		POP	DX		;Starting cluster
21000		SUB	BX,DX		;Number of new clusters accessed
21010		ADD	[LASTPOS],BX
21020		POP	BX		;BL = sector postion within cluster
21030		CALL	FIGREC
21040		MOV	BX,SI
21050		RET
21060	BLKDON:
21070		SUB	CX,DX		;Number of sectors in cluster we don't want
21080		SUB	AH,CL		;Number of sectors in cluster we accepted
21090		DEC	AH		;Adjust to mean position within cluster
21100		MOV	[SECCLUSPOS],AH
21110		MOV	CX,DX		;Anyway, make the total equal to the request
21120		JP	FINCLUS
21130	
21140	
21150	FIGREC:
21160	
21170	;Inputs:
21180	;	DX = Physical cluster number
21190	;	BL = Sector postion within cluster
21200	;	BP = Base of drive parameters
21210	;Outputs:
21220	;	DX = physical sector number
21230	;No other registers affected.
21240	
21250		PUSH	CX
21260		MOV	CL,[BP+CLUSSHFT]
21270		DEC	DX
21280		DEC	DX
21290		SHL	DX,CL
21300		OR	DL,BL
21310		ADD	DX,[BP+FIRREC]
21320		POP	CX
21330		RET
21340	
21350	GETREC:
21360	
21370	; Inputs:
21380	;	DS:DX point to FCB
21390	; Outputs:
21400	;	CX = 1
21410	;	DX:AX = Record number determined by EXTENT and NR fields
21420	;	DS:DI point to FCB
21430	; No other registers affected.
21440	
21450		MOV	DI,DX
21460		MOV	CX,1
21470		MOV	AL,[DI+NR]
21480		MOV	DX,[DI+EXTENT]
21490		SHL	AL
21500		SHR	DX
21510		RCR	AL
21520		MOV	AH,DL
21530		MOV	DL,DH
21540		MOV	DH,0
21550		RET
21560	
21570	
21580	ALLOCATE:
21590	
21600	; Inputs:
21610	;	DS = CS
21620	;	ES = Segment of FCB
21630	;	BX = Last cluster of file (0 if null file)
21640	;	CX = No. of clusters to allocate
21650	;	DX = Position of cluster BX
21660	;	BP = Base of drive parameters
21670	;	SI = FAT pointer
21680	;	[FCB] = Displacement of FCB within segment
21690	; Outputs:
21700	;	IF insufficient space
21710	;	  THEN
21720	;	Carry set
21730	;	CX = max. no. of records that could be added to file
21740	;	  ELSE
21750	;	Carry clear
21760	;	BX = First cluster allocated
21770	;	FAT is fully updated including dirty bit
21780	;	FIRCLUS field of FCB set if file was null
21790	; SI,BP unchanged. All other registers destroyed.
21800	
21810		PUSH	[SI]
21820		PUSH	DX
21830		PUSH	CX
21840		PUSH	BX
21850		MOV	AX,BX
21860	ALLOC:
21870		MOV	DX,BX
21880	FINDFRE:
21890		INC	BX
21900		CMP	BX,[BP+MAXCLUS]
21910		JLE	TRYOUT
21920		CMP	AX,1
21930		JG	TRYIN
21940		POP	BX
21950		MOV	DX,0FFFH
21960		CALL	RELBLKS
21970		POP	AX		;No. of clusters requested
21980		SUB	AX,CX		;AX=No. of clusters allocated
21990		POP	DX
22000		POP	[SI]
22010		INC	DX		;Position of first cluster allocated
22020		ADD	AX,DX		;AX=max no. of cluster in file
22030		MOV	DL,[BP+CLUSMSK]
22040		MOV	DH,0
22050		INC	DX		;DX=records/cluster
22060		MUL	AX,DX		;AX=max no. of records in file
22070		MOV	CX,AX
22080		SUB	CX,[RECPOS]	;CX=max no. of records that could be written
22090		JA	MAXREC
22100		XOR	CX,CX		;If CX was negative, zero it
22110	MAXREC:
22120		STC
22130		RET
22140	
22150	TRYOUT:
22160		CALL	UNPACK
22170		JZ	HAVFRE
22180	TRYIN:
22190		DEC	AX
22200		JLE	FINDFRE
22210		XCHG	AX,BX
22220		CALL	UNPACK
22230		JZ	HAVFRE
22240		XCHG	AX,BX
22250		JP	FINDFRE
22260	HAVFRE:
22270		XCHG	BX,DX
22280		MOV	AX,DX
22290		CALL	PACK
22300		MOV	BX,AX
22310		LOOP	ALLOC
22320		MOV	DX,0FFFH
22330		CALL	PACK
22340		MOV	B,[BP+DIRTYFAT],1
22350		POP	BX
22360		POP	CX		;Don't need this stuff since we're successful
22370		POP	DX
22380		CALL	UNPACK
22390		POP	[SI]
22400		XCHG	BX,DI
22410		OR	DI,DI
22420		JNZ	RET
22430		MOV	DI,[FCB]
22440		SEG	ES
22450		MOV	[DI+FIRCLUS],BX
22460		RET
22470	
22480	
22490	RELEASE:
22500	
22510	; Inputs:
22520	;	DS = CS
22530	;	BX = Cluster in file
22540	;	SI = FAT pointer
22550	;	BP = Base of drive parameters
22560	; Function:
22570	;	Frees cluster chain starting with [BX]
22580	; AX,BX,DX,DI all destroyed. Other registers unchanged.
22590	
22600		XOR	DX,DX
22610	RELBLKS:
22620	; Enter here with DX=0FFFH to put an end-of-file mark
22630	; in the first cluster and free the rest in the chain.
22640		CALL	UNPACK
22650		JZ	RET
22660		MOV	AX,DI
22670		CALL	PACK
22680		CMP	AX,0FF8H
22690		MOV	BX,AX
22700		JB	RELEASE
22710		RET
22720	
22730	
22740	GETEOF:
22750	
22760	; Inputs:
22770	;	BX = Cluster in a file
22780	;	SI = Base of drive FAT
22790	;	DS = CS
22800	; Outputs:
22810	;	BX = Last cluster in the file
22820	; DI destroyed. No other registers affected.
22830	
22840		CALL	UNPACK
22850		CMP	DI,0FF8H
22860		JAE	RET
22870		MOV	BX,DI
22880		JP	GETEOF
22890	
22900	
22910	SRCHFRST: ;System call 17
22920		PUSH	DX
22930		PUSH	DS
22940		CALL	GETFILE
22950	SAVPLCE:
22960	; Search-for-next enters here to save place and report
22970	; findings.
22980		POP	ES
22990		POP	DI
23000		JC	KILLSRCH
23010		CMP	BH,-1
23020		JZ	SRCHDEV
23030		MOV	AX,[LASTENT]
23040		SEG	ES
23050		MOV	[DI+FILDIRBLK],AX
23060	;Information in directory entry must be copied into the first
23070	; 33 bytes starting at the disk transfer address.
23080		MOV	SI,BX
23090		LES	DI,[DMAADD]
23100		MOV	AL,[BP+DRVNUM]
23110		INC	AL
23120		STOB		;Set drive number
23130		MOVB		;Copy first character of name
23140		MOV	CX,5
23150		REP
23160		MOVW		;Copy remaining 10 characters of name
23170		XOR	AX,AX
23180	
23190		IF	SMALLDIR
23200		CMP	B,[BP+DIRSIZ],-1
23210		JNZ	BIGENT5
23220		STOB		;Zero out unused portion
23230		MOV	CX,7
23240		REP
23250		STOW		;Zero a total of 15 bytes
23260		MOVW		;Copy first cluster pointer
23270		MOVW		;Copy low word of length
23280		MOVB		;Copy 3rd byte of length
23290		STOB		;4th byte of length must be zero
23300		RET
23310	BIGENT5:
23320		ENDIF
23330	
23340		MOV	CX,10
23350		REP
23360		MOVW
23370		MOVB
23380		RET
23390	
23400	KILLSRCH:
23410		SEG	ES
23420	KILLSRCH1:
23430		MOV	[DI+FILDIRBLK],-2
23440		MOV	AL,-1
23450		RET
23460	
23470	SRCHDEV:
23480		SEG	ES
23490		MOV	[DI+FILDIRBLK],BX
23500		LES	DI,[DMAADD]
23510		XOR	AX,AX
23520		STOB			;Zero drive byte
23530		SUB	SI,3		;Point to device name
23540		MOVW
23550		MOVB
23560		MOV	AX,2020H
23570		MOV	CX,4
23580		REP
23590		STOW			;Fill with 8 blanks
23600		XOR	AX,AX
23610		MOV	CX,10
23620		REP
23630		STOW
23640		STOB
23650		RET
23660	
23670	SRCHNXT: ;System call 18
23680		CALL	MOVNAME
23690		MOV	DI,DX
23700		JC	KILLSRCH1
23710		PUSH	DX
23720		PUSH	DS
23730		MOV	AX,[DI+FILDIRBLK]
23740		PUSH	CS
23750		POP	DS
23760		MOV	[LASTENT],AX
23770		CALL	CONTSRCH
23780		JMP	SAVPLCE
23790	
23800	
23810	FILESIZE: ;System call 35
23820		PUSH	DS
23830		PUSH	DX
23840		CALL	GETFILE
23850		POP	DI
23860		POP	ES
23870		MOV	AL,-1
23880		JC	RET
23890		ADD	DI,33		;Write size in RR field
23900		SEG	ES
23910		MOV	CX,[DI-33+RECSIZ]
23920		OR	CX,CX
23930		JNZ	RECOK
23940		MOV	CX,128
23950	RECOK:
23960		XOR	AX,AX
23970		XOR	DX,DX		;Intialize size to zero
23980		CMP	BH,-1		;Check for named I/O device
23990		JZ	DEVSIZ
24000		INC	SI
24010		INC	SI		;Point to length field
24020		MOV	AX,[SI+2]	;Get high word of size
24030	
24040		IF	SMALLDIR
24050		CMP	B,[BP+DIRSIZ],-1
24060		JNZ	BIGSIZ
24070		MOV	AH,0
24080	BIGSIZ:
24090		ENDIF
24100	
24110		DIV	AX,CX
24120		PUSH	AX		;Save high part of result
24130		LODW			;Get low word of size
24140		DIV	AX,CX
24150		OR	DX,DX		;Check for zero remainder
24160		POP	DX
24170		JZ	DEVSIZ
24180		INC	AX		;Round up for partial record
24190		JNZ	DEVSIZ		;Propagate carry?
24200		INC	DX
24210	DEVSIZ:
24220		STOW
24230		MOV	AX,DX
24240		STOB
24250		MOV	AL,0
24260		CMP	CX,64
24270		JAE	RET		;Only 3-byte field if RECSIZ >= 64
24280		SEG	ES
24290		MOV	[DI],AH
24300		RET
24310	
24320	
24330	SETDMA:	;System call 26
24340		SEG	CS
24350		MOV	[DMAADD],DX
24360		SEG	CS
24370		MOV	[DMAADD+2],DS
24380		RET
24390	
24400	
24410	GETFATPT: ;System call 27
24420		MOV	AX,CS
24430		MOV	DS,AX
24440		MOV	BP,[CURDRVPT]
24450		CALL	FATREAD
24460		LEA	BX,[BP+FAT]
24470		MOV	AL,[BP+CLUSMSK]
24480		INC	AL
24490		MOV	DX,[BP+MAXCLUS]
24500		DEC	DX
24510		MOV	B,[BP+DIRTYFAT],1
24520		MOV	CX,[BP+SECSIZ]
24530		LDS	SI,[SPSAVE]
24540		MOV	[SI+BXSAVE],BX
24550		MOV	[SI+DXSAVE],DX
24560		MOV	[SI+CXSAVE],CX
24570		MOV	[SI+DSSAVE],CS
24580		RET
24590	
24600	
24610	GETDSKPT: ;System call 31
24620		SEG	CS
24630		MOV	BX,[CURDRVPT]
24640		SEG	CS
24650		LDS	SI,[SPSAVE]
24660		MOV	[SI+BXSAVE],BX
24670		MOV	[SI+DSSAVE],CS
24680		RET
24690	
24700	
24710	DSKRESET: ;System call 13
24720		SEG	CS
24730		MOV	[DMAADD+2],DS
24740		MOV	AX,CS
24750		MOV	DS,AX
24760		MOV	[DMAADD],80H
24770		MOV	AX,[CURDRVPT+2]
24780		MOV	[CURDRVPT],AX
24790	WRTFATS:
24800	; DS=CS. Writes back all dirty FATs. All registers destroyed.
24810		MOV	CL,[NUMDRV]
24820		MOV	CH,0
24830		MOV	SI,CURDRVPT+2
24840	WRTFAT:
24850		LODW
24860		PUSH	CX
24870		PUSH	SI
24880		MOV	BP,AX
24890		CALL	CHKFATWRT
24900		POP	SI
24910		POP	CX
24920		LOOP	WRTFAT
24930		MOV	AX,[BUFDRVNO]
24940		OR	AH,AH
24950		JZ	RET
24960		CBW
24970		MOV	BX,AX
24980		SHL	BX
24990		MOV	BP,[BX+DRVTAB]
25000		MOV	B,[DIRTYBUF],0
25010		MOV	DX,[BUFSECNO]
25020		MOV	BX,BUFFER
25030		MOV	CX,1
25040		JMP	DWRITE
25050	
25060	
25070	CURDRV:	;System call 25
25080		SEG	CS
25090		MOV	BP,[CURDRVPT]
25100		MOV	AL,[BP+DRVNUM]
25110		RET
25120	
25130	
25140	INUSE:	;System call 24
25150		MOV	AX,CS
25160		MOV	DS,AX
25170		MOV	CL,[NUMDRV]
25180		MOV	CH,0
25190		MOV	SI,CX
25200		SHL	SI
25210		ADD	SI,CURDRVPT
25220		MOV	BX,0
25230		DOWN
25240	CHKUSE:
25250		LODW
25260		MOV	BP,AX
25270		CMP	B,[BP+DIRTYFAT],-1	;Carry set if not equal
25280		RCL	BX
25290		LOOP	CHKUSE
25300		MOV	AL,BL
25310		RET
25320	
25330	
25340	SETRNDREC: ;System call 36
25350		CALL	GETREC
25360		MOV	[DI+33],AX
25370		MOV	[DI+35],DL
25380		RET
25390	
25400	
25410	SELDSK:	;System call 14
25420		MOV	DH,0
25430		MOV	BX,DX
25440		PUSH	CS
25450		POP	DS
25460		MOV	AL,[NUMDRV]
25470		CMP	BL,AL
25480		JNB	RET
25490		SHL	BX
25500		MOV	DX,[BX+CURDRVPT+2]
25510		MOV	[CURDRVPT],DX
25520		RET
25530	
25540	
25550	BUFIN:	;System call 10
25560		MOV	AX,CS
25570		MOV	ES,AX
25580		MOV	SI,DX
25590		MOV	CH,0
25600		LODW
25610		OR	AL,AL
25620		JZ	RET
25630		MOV	BL,AH
25640		MOV	BH,CH
25650		CMP	AL,BL
25660		JBE	NOEDIT
25670		CMP	B,[BX+SI],0DH
25680		JZ	EDITON
25690	NOEDIT:
25700		MOV	BL,CH
25710	EDITON:
25720		MOV	DL,AL
25730		DEC	DX
25740	NEWLIN:
25750		SEG	CS
25760		MOV	AL,[CARPOS]
25770		SEG	CS
25780		MOV	[STARTPOS],AL
25790		PUSH	SI
25800		MOV	DI,INBUF
25810		MOV	AH,CH
25820		MOV	BH,CH
25830		MOV	DH,CH
25840	GETCH:
25850		CALL	IN
25860		CMP	AL,7FH
25870		JZ	BACKSP
25880		CMP	AL,8
25890		JZ	BACKSP
25900		CMP	AL,13
25910		JZ	ENDLIN
25920		CMP	AL,10
25930		JZ	PHYCRLF
25940		CMP	AL,"X"-"@"
25950		JZ	KILNEW
25960		CMP	AL,ESCCH
25970		JZ	ESC
25980	SAVCH:
25990		CMP	DH,DL
26000		JAE	GETCH
26010		STOB
26020		INC	DH
26030		CALL	BUFOUT
26040		OR	AH,AH
26050		JNZ	GETCH
26060		CMP	BH,BL
26070		JAE	GETCH
26080		INC	SI
26090		INC	BH
26100		JP	GETCH
26110	
26120	ESC:
26130		CALL	IN
26140		MOV	CL,ESCTABLEN
26150		PUSH	DI
26160		MOV	DI,ESCTAB
26170		REPNE
26180		SCAB
26190		POP	DI
26200		AND	CL,0FEH
26210		MOV	BP,CX
26220		SEG	CS		;To work in init
26230		JMP	[BP+ESCFUNC]
26240	
26250	ENDLIN:
26260		STOB
26270		CALL	OUT
26280		POP	DI
26290		MOV	[DI-1],DH
26300		INC	DH
26310	COPYNEW:
26320		MOV	BP,ES
26330		MOV	BX,DS
26340		MOV	ES,BX
26350		MOV	DS,BP
26360		MOV	SI,INBUF
26370		MOV	CL,DH
26380		REP
26390		MOVB
26400		RET
26410	CRLF:
26420		MOV	AL,13
26430		CALL	OUT
26440		MOV	AL,10
26450		JMP	OUT
26460	
26470	PHYCRLF:
26480		CALL	CRLF
26490		JP	GETCH
26500	
26510	KILNEW:
26520		MOV	AL,"\"
26530		CALL	OUT
26540		POP	SI
26550	PUTNEW:
26560		CALL	CRLF
26570		SEG	CS
26580		MOV	AL,[STARTPOS]
26590		CALL	TAB
26600		JMP	NEWLIN
26610	
26620	BACKSP:
26630		OR	DH,DH
26640		JZ	OLDBAK
26650		CALL	BACKUP
26660		SEG	ES
26670		MOV	AL,[DI]
26680		CMP	AL," "
26690		JAE	OLDBAK
26700		CMP	AL,9
26710		JZ	BAKTAB
26720		CALL	BACKMES
26730	OLDBAK:
26740		OR	AH,AH
26750		JNZ	GETCH1
26760		OR	BH,BH
26770		JZ	GETCH1
26780		DEC	BH
26790		DEC	SI
26800	GETCH1:
26810		JMP	GETCH
26820	BAKTAB:
26830		PUSH	DI
26840		DEC	DI
26850		DOWN
26860		MOV	CL,DH
26870		MOV	AL," "
26880		PUSH	BX
26890		MOV	BL,7
26900		JCXZ	FIGTAB
26910	FNDPOS:
26920		SCAB
26930		JNA	CHKCNT
26940		SEG	ES
26950		CMP	B,[DI+1],9
26960		JZ	HAVTAB
26970		DEC	BL
26980	CHKCNT:
26990		LOOP	FNDPOS
27000	FIGTAB:
27010		SEG	CS
27020		SUB	BL,[STARTPOS]
27030	HAVTAB:
27040		SUB	BL,DH
27050		ADD	CL,BL
27060		AND	CL,7
27070		UP
27080		POP	BX
27090		POP	DI
27100		JZ	OLDBAK
27110	TABBAK:
27120		CALL	BACKMES
27130		LOOP	TABBAK
27140		JP	OLDBAK
27150	BACKUP:
27160		DEC	DH
27170		DEC	DI
27180	BACKMES:
27190		MOV	AL,8
27200		CALL	OUT
27210		MOV	AL," "
27220		CALL	OUT
27230		MOV	AL,8
27240		JMP	OUT
27250	
27260	TWOESC:
27270		MOV	AL,ESCCH
27280		JMP	SAVCH
27290	
27300	COPYLIN:
27310		MOV	CL,BL
27320		SUB	CL,BH
27330		JP	COPYEACH
27340	
27350	COPYSTR:
27360		CALL	FINDOLD
27370		JP	COPYEACH
27380	
27390	COPYONE:
27400		MOV	CL,1
27410	COPYEACH:
27420		CMP	DH,DL
27430		JZ	GETCH2
27440		CMP	BH,BL
27450		JZ	GETCH2
27460		LODB
27470		STOB
27480		CALL	BUFOUT
27490		INC	BH
27500		INC	DH
27510		LOOP	COPYEACH
27520	GETCH2:
27530		JMP	GETCH
27540	
27550	SKIPONE:
27560		CMP	BH,BL
27570		JZ	GETCH2
27580		INC	BH
27590		INC	SI
27600		JMP	GETCH
27610	
27620	SKIPSTR:
27630		CALL	FINDOLD
27640		ADD	SI,CX
27650		ADD	BH,CL
27660		JMP	GETCH
27670	
27680	FINDOLD:
27690		CALL	IN
27700		MOV	CL,BL
27710		SUB	CL,BH
27720		JZ	NOTFND
27730		DEC	CX
27740		JZ	NOTFND
27750		PUSH	ES
27760		PUSH	DS
27770		POP	ES
27780		PUSH	DI
27790		MOV	DI,SI
27800		INC	DI
27810		REPNE
27820		SCAB
27830		POP	DI
27840		POP	ES
27850		JNZ	NOTFND
27860		NOT	CL
27870		ADD	CL,BL
27880		SUB	CL,BH
27890		RET
27900	NOTFND:
27910		POP	BP
27920		JMP	GETCH
27930	
27940	REEDIT:
27950		MOV	AL,"@"
27960		CALL	OUT
27970		POP	DI
27980		PUSH	DI
27990		PUSH	ES
28000		PUSH	DS
28010		CALL	COPYNEW
28020		POP	DS
28030		POP	ES
28040		POP	SI
28050		MOV	BL,DH
28060		JMP	PUTNEW
28070	
28080	ENTERINS:
28090		MOV	AH,-1
28100		JMP	GETCH
28110	
28120	EXITINS:
28130		MOV	AH,0
28140		JMP	GETCH
28150	
28160	ESCFUNC:
28170		DW	GETCH
28180		DW	TWOESC
28190		DW	EXITINS
28200		DW	ENTERINS
28210		DW	BACKSP
28220		DW	REEDIT
28230		DW	KILNEW
28240		DW	COPYLIN
28250		DW	SKIPSTR
28260		DW	COPYSTR
28270		DW	SKIPONE
28280		DW	COPYONE
28290	
28300	BUFOUT:
28310		CMP	AL," "
28320		JAE	OUT
28330		CMP	AL,9
28340		JZ	OUT
28350		PUSH	AX
28360		MOV	AL,"^"
28370		CALL	OUT
28380		POP	AX
28390		OR	AL,40H
28400		JP	OUT
28410	
28420	CONOUT:	;System call 2
28430		MOV	AL,DL
28440	OUT:
28450		CMP	AL,20H
28460		JB	CTRLOUT
28470		CMP	AL,7FH
28480		JZ	OUTCH
28490		SEG	CS
28500		INC	B,[CARPOS]
28510	OUTCH:
28520		CALL	BIOSOUT,BIOSSEG
28530		SEG	CS
28540		TEST	B,[PFLAG],-1
28550		JZ	STATCHK
28560		CALL	BIOSPRINT,BIOSSEG
28570	STATCHK:
28580		CALL	BIOSSTAT,BIOSSEG
28590		JZ	RET
28600	INCHK:
28610		CALL	BIOSIN,BIOSSEG
28620		CMP	AL,'S'-'@'
28630		JNZ	NOSTOP
28640		CALL	BIOSIN,BIOSSEG
28650	NOSTOP:
28660		CMP	AL,'P'-'@'
28670		JZ	PRINTON
28680		CMP	AL,'N'-'@'
28690		JZ	PRINTOFF
28700		CMP	AL,'C'-'@'
28710		JNZ	RET
28720	; Ctrl-C handler.
28730	; If function 9 or 10 was in progress, a backslash, CR, and LF are printed
28740	; to show line is canceled. Then the user registers are restored and the
28750	; user CTRL-C handler is executed. At this point the top of the stack has
28760	; 1) the interrupt return address should the user CTRL-C handler wish to
28770	; allow processing to continue; 2) the original interrupt return address
28780	; to the code that performed the function call in the first place. If the
28790	; user CTRL-C handler wishes to continue, it must leave all registers
28800	; unchanged and IRET. The function that was interrupted will simply be
28810	; repeated, except for console output (function 2), which has already output
28820	; its character before the interrupt.
28830		SEG	CS
28840		MOV	AL,[FUNC]	;Get currently executing function
28850		CMP	AL,10		;Check if buffered line input
28860		JZ	CANLIN
28870		CMP	AL,9		;Check if buffered line output
28880		JNZ	RESTREG
28890	CANLIN:
28900		MOV	AL,"\"		;Display cancel line symbol
28910		CALL	OUT
28920		CALL	CRLF
28930	RESTREG:
28940		DI			;Prepare to play with stack
28950		SEG	CS
28960		MOV	SS,[SSSAVE]
28970		SEG	CS
28980		MOV	SP,[SPSAVE]	;User stack now restored
28990		POP	AX
29000		POP	BX
29010		POP	CX
29020		POP	DX
29030		POP	SI
29040		POP	DI
29050		POP	BP
29060		POP	DS
29070		POP	ES		;User registers now restored
29080		INT	CONTC		;Execute user Ctrl-C handler
29090		CMP	AH,2		;Check if function was console output
29100		JZ	SETAL
29110		JMP	COMMAND		;Repeat command otherwise
29120	SETAL:
29130		MOV	AL,DL
29140		IRET			;Return to user program
29150	
29160	PRINTON:
29170		SEG	CS
29180		MOV	B,[PFLAG],1
29190		RET
29200	PRINTOFF:
29210		SEG	CS
29220		MOV	B,[PFLAG],0
29230		RET
29240	CTRLOUT:
29250		CMP	AL,13
29260		JZ	ZERPOS
29270		CMP	AL,8
29280		JZ	BACKPOS
29290		CMP	AL,9
29300		JNZ	OUTCHJ
29310		SEG	CS
29320		MOV	AL,[CARPOS]
29330		OR	AL,0F8H
29340		NEG	AL
29350	TAB:
29360		PUSH	CX
29370		MOV	CL,AL
29380		MOV	CH,0
29390	TABLP:
29400		MOV	AL," "
29410		CALL	OUT
29420		LOOP	TABLP
29430		POP	CX
29440		RET
29450	
29460	ZERPOS:
29470		SEG	CS
29480		MOV	B,[CARPOS],0
29490	OUTCHJ:	JMP	OUTCH
29500	
29510	BACKPOS:
29520		SEG	CS
29530		DEC	B,[CARPOS]
29540		JMP	OUTCH
29550	
29560	
29570	CONSTAT: ;System call 11
29580		CALL	BIOSSTAT,BIOSSEG
29590		JZ	RET
29600		OR	AL,-1
29610		RET
29620	
29630	
29640	CONIN:	;System call 1
29650		CALL	IN
29660		PUSH	AX
29670		CALL	OUT
29680		POP	AX
29690		RET
29700	
29710	
29720	IN:	;Internal input routine
29730		CALL	INCHK
29740		JZ	IN
29750		RET
29760	
29770	RAWIO:	;System call 6
29780		MOV	AL,DL
29790		CMP	AL,-1
29800		JNZ	RAWOUT
29810		CALL	BIOSSTAT,BIOSSEG
29820		JZ	RET
29830	RAWINP:	;System call 7
29840		CALL	BIOSIN,BIOSSEG
29850		RET
29860	RAWOUT:
29870		CALL	BIOSOUT,BIOSSEG
29880		RET
29890	
29900	LIST:	;System call 5
29910		MOV	AL,DL
29920		CALL	BIOSPRINT,BIOSSEG
29930		RET
29940	
29950	PRTBUF:	;System call 9
29960		MOV	SI,DX
29970	OUTSTR:
29980		LODB
29990		CMP	AL,"$"
30000		JZ	RET
30010		CALL	OUT
30020		JP	OUTSTR
30030	
30040	OUTMES:	;String output for internal messages
30050		SEG	CS
30060		LODB
30070		CMP	AL,"$"
30080		JZ	RET
30090		CALL	OUT
30100		JP	OUTMES
30110	
30120	
30130	MAKEFCB: ;Interrupt call 41
30140		MOV	DL,0		;Flag--not ambiguous file name
30150		OR	AL,AL		;Scan off separators if not zero
30160		JZ	NOSCAN
30170	SCAN:
30180		CALL	GETLET
30190		JZ	SCAN		;Get rid of leading separators (e.g., blanks)
30200		DEC	SI		;Point back to first non-separator
30210	NOSCAN:
30220		CMP	B,[SI+1],":"	;Check for potential drive specifier
30230		JNZ	DEFAULT
30240		CALL	GETLET
30250		SUB	AL,"@"		;Convert drive letter to binary drive number
30260		JZ	NODRV		;Valid drive numbers are 1-15
30270		INCcifier--back up pointer
30280	DEFAULT:
30290		XOR	AL,AL
30300	HAVDRV:
30310		STOB			;Put drive specifier in first byte
30320		MOV	CX,8
30330		CALL	GETWORD		;Get 8-letter file name
30340		CMP	B,[SI],"."
30350		JNZ	NODOT
30360		INC	SI		;Skip over dot if present
30370	NODOT:
30380		MOV	CX,3		;Get 3-letter extension
30390		CALL	GETWORD
30400		SEG	CS
30410		LDS	BX,[SPSAVE]
30420		MOV	[BX+SISAVE],SI
30430		XOR	AX,AX
30440		STOW
30450		STOW
30460		MOV	AL,DL
30470		RET
30480	
30490	GETWORD:
30500		CALL	GETLET
30510		JZ	FILLNAM		;Exit if invalid character
30520		CMP	AL," "
30530		JBE	FILLNAM
30540		CMP	AL,"*"		;Check for ambiguous file specifier
30550		JNZ	NOSTAR
30560		MOV	AL,"?"
30570		DEC	CX
30580		REP
30590		STOB			;Fill rest of word with "?"
30600		INC	CX
30610	NOSTAR:
30620		STOB
30630		CMP	AL,"?"
30640		JNZ	NOTQ
30650		MOV	DL,1		;Flag ambiguous file name
30660	NOTQ:
30670		LOOP	GETWORD
30680		INC	SI		;Point to "termination" character
30690	FILLNAM:
30700		MOV	AL," "
30710		REP
30720		STOB
30730		DEC	SI
30740		RET
30750	
30760	GETLET:
30770		LODB
30780		CMP	AL,"a"
30790		JB	CHK
30800		CMP	AL,"z"
30810		JA	CHK
30820		SUB	AL,20H		;Convert to upper case
30830	CHK:
30840		CMP	AL," "
30850		JZ	RET
30860		CMP	AL,"="
30870		JZ	RET
30880		CMP	AL,","
30890		JZ	RET
30900		CMP	AL,";"
30910		JZ	RET
30920		CMP	AL,"."
30930		JZ	RET
30940		CMP	AL,":"
30950		JZ	RET
30960		CMP	AL,9		;Filter out TABs too
30970		RET
30980	
30990	
31000	SETVECT: ; Interrupt call 37
31010		XOR	BX,BX
31020		MOV	ES,BX
31030		MOV	BL,AL
31040		SHL	BX
31050		SHL	BX
31060		SEG	ES
31070		MOV	[BX],DX
31080		SEG	ES
31090		MOV	[BX+2],DS
31100		RET
31110	
31120	
31130	NEWBASE: ; Interrupt call 38
31140		MOV	ES,DX
31150		SEG	CS
31160		MOV	DS,[CSLOC]
31170		XOR	SI,SI
31180		MOV	DI,SI
31190		MOV	CX,80H
31200		REP
31210		MOVW
31220	
31230	SETMEM:
31240	
31250	; Inputs:
31260	;	DX = Segment
31270	; Function:
31280	;	Completely prepares a program base at the 
31290	;	specified segment.
31300	; Outputs:
31310	;	DS = DX
31320	;	ES = DX
31330	;	[0] has INT 20H
31340	;	[2] = First unavailable segment ([ENDMEM])
31350	;	[5] to [9] form a long call to the entry point
31360	;	[10] to [13] have exit address (from INT 22H)
31370	;	[14] to [17] have ctrl-C exit address (from INT 23H)
31380	; AX,DX,BP unchanged. All other registers destroyed.
31390	
31400		XOR	CX,CX
31410		MOV	DS,CX
31420		MOV	ES,DX
31430		MOV	SI,EXIT
31440		MOV	DI,SAVEXIT
31450		MOVW
31460		MOVW
31470		MOVW
31480		MOVW
31490		SEG	CS
31500		MOV	CX,[ENDMEM]
31510		SEG	ES
31520		MOV	[2],CX
31530		SUB	CX,DX
31540		CMP	CX,MAXDIF
31550		JBE	HAVDIF
31560		MOV	CX,MAXDIF
31570	HAVDIF:
31580		MOV	BX,ENTRYPOINTSEG
31590		SUB	BX,CX
31600		SHL	CX
31610		SHL	CX
31620		SHL	CX
31630		SHL	CX
31640		MOV	DS,DX
31650		MOV	[6],CX
31660		MOV	[8],BX
31670		MOV	[0],20CDH	;"INT INTTAB"
31680		MOV	B,[5],LONGCALL
31690		RET
31700	
31710	
31720	SHFTDI7:
31730		SHL	DI
31740		SHL	DI
31750		SHL	DI
31760		SHL	DI
31770		SHL	DI
31780		SHL	DI
31790		SHL	DI
31800		RET
31810	
31820	
31830	; Default handler for division overflow trap
31840	DIVOV:
31850		XOR	DX,DX		;Say no remainder
31860		MOV	AX,-1		;But large quotient
31870		IRET
31880	
31890	
31900	;***** DATA AREA *****
31910	
31920	BADMES:	DB	13,10,"Bad FAT",13,10,"$"
31930	BADFATMES:DB	13,10,"All FATs on disk are bad",13,10,"$"
31940	RDERRMES:DB	13,10,"Disk read error",13,10,"$"
31950	WRTERRMES:DB	13,10,"Disk write error",13,10,"$"
31960	IONAME:	DB	"PRN","LST","AUX","CON"
31970	
31980	CARPOS:	DB	0
31990	STARTPOS:DB	0
32000	PFLAG:	DB	0
32010	DIRTYDIR:DB	0	;Dirty buffer flag
32020	NUMDRV:	DS	1	;Number of drives
32030	CONTPOS:DW	0
32040	DMAADD:	DW	80H	;User's disk transfer address (disp/seg)
32050		DS	2
32060	ENDMEM:	DS	2
32070	MAXSEC:	DW	0
32080	BUFFER:	DS	2
32090	BUFSECNO:DW	0
32100	BUFDRVNO:DB	-1
32110	DIRTYBUF:DB	0
32120	DIRBUFID:DW	-1
32130	DATE:	DS	2
32140	CURDRVPT:DS	2
32150	DRVTAB:	DS	30	;Enough for 15 drives
32160	INBUF:	DS	15	;Only the first part
32170	
32180	; Init code overlaps with data area below
32190	
32200	INITCODE:
32210	
32220		DS	128-15	;More of INBUF
32230	CONBUF:	DS	130	;The rest of INBUF and console buffer
32240	FUNC:	DS	1	;Currently executing function code
32250	LASTENT:DS	2
32260	EXITHOLD:DS	4
32270	FATBASE:DS	2
32280	NAME1:	DS	11	;File name buffer
32290	NAME2:	DS	11
32300	TEMP:
32310	CSLOC:	DS	2
32320	SPSAVE:	DS	2
32330	SSSAVE:	DS	2
32340	SECCLUSPOS:DS	1	;Position of first sector within cluster
32350	DSKERR:	DS	1
32360	TRANS:	DS	1
32370	
32380		ALIGN
32390	FCB:	DS	2	;Address of user FCB
32400	NEXTADD:DS	2
32410	RECPOS:	DS	4
32420	RECCNT:	DS	2
32430	LASTPOS:DS	2
32440	CLUSNUM:DS	2
32450	SECPOS:	DS	2		;Position of first sector accessed
32460	VALSEC:	DS	2		;Number of valid (previously written) sectors
32470	BYTSECPOS:DS	2	;Position of first byte within sector
32480	BYTPOS:	DS	4		;Byte position in file of access
32490	BYTCNT1:DS	2		;No. of bytes in first sector
32500	BYTCNT2:DS	2		;No. of bytes in last sector
32510	SECCNT:	DS	2		;No. of whole sectors
32520	
32530		DS	60	;Stack space
32540	STACK:
32550	
32560		IF	DSKTEST
32570	NSS:	DS	2
32580	NSP:	DS	2
32590		DS	60
32600	TESTSTK:
32610		ENDIF
32620	
32630	DIRBUF:
32640	
32650	;Init code below overlaps with data area above
32660	
32670		ORG	INITCODE
32680		PUT	$+100H
32690	
32700	MOVFAT:
32710	;This section of code is safe from being overwritten by block move
32720		SEG	ES
32730		REP
32740		MOVB
32750		UP
32760	FININIT:
32770		CALL	SETMEM		;Set up segment
32780		RET	L
32790	
32800	DOSINIT:
32810		DI
32820		UP
32830		PUSH	CS
32840		POP	ES
32850		LODB
32860		SEG	ES
32870		MOV	[NUMDRV],AL
32880		MOV	BX,DRVTAB
32890		MOV	DI,MEMSTRT
32900	PERDRV:
32910		SEG	ES
32920		MOV	[BX],DI
32930		MOV	BP,DI
32940		INC	BX
32950		INC	BX
32960		SEG	ES
32970		MOV	AL,[DRVCNT]
32980		STOB			;DRVNUM
32990		LODW			;Pointer to DPT
33000		PUSH	SI
33010		MOV	SI,AX
33020		LODW
33030		STOW			;SECSIZ
33040		MOV	DX,AX
33050		SEG	ES
33060		CMP	AX,[MAXSEC]
33070		JBE	NOTMAX
33080		SEG	ES
33090		MOV	[MAXSEC],AX
33100	NOTMAX:
33110		LODB
33120		DEC	AL
33130		STOB			;CLUSMSK
33140		JZ	HAVSHFT
33150		CBW
33160	FIGSHFT:
33170		INC	AH
33180		SAR	AL
33190		JNZ	FIGSHFT
33200		MOV	AL,AH
33210	HAVSHFT:
33220		STOB			;CLUSSHFT
33230		MOVW			;FIRFAT (= number of reserved sectors)
33240		MOVB			;FATCNT
33250		MOVW			;MAXENT
33260		MOV	AX,DX		;SECSIZ again
33270		MOV	CL,5
33280		SHR	AX,CL
33290		MOV	CX,AX		;Directory entries per sector
33300		DEC	AX
33310		SEG	ES
33320		ADD	AX,[BP+MAXENT]
33330		XOR	DX,DX
33340		DIV	AX,CX
33350		STOW			;DIRSEC (temporarily)
33360		SHR	AX		;Divide by two
33370		ADC	AX,0		;Round up
33380		SEG	ES
33390		MOV	[SDIRSEC],AX	;Number of directory records for small entries
33400		MOVW			;DSKSIZ (temporarily)
33410	FNDFATSIZ:
33420		MOV	AL,1
33430		MOV	DX,1
33440	GETFATSIZ:
33450		PUSH	DX
33460		CALL	FIGFATSIZ
33470		POP	DX
33480		CMP	AL,DL		;Compare newly computed FAT size with trial
33490		JZ	HAVFATSIZ	;Has sequence converged?
33500		CMP	AL,DH		;Compare with previous trial
33510		MOV	DH,DL
33520		MOV	DL,AL		;Shuffle trials
33530		JNZ	GETFATSIZ	;Continue iterations if not oscillating
33540		SEG	ES
33550		DEC	[BP+DSKSIZ]	;Damp those oscillations
33560		JP	FNDFATSIZ	;Try again
33570	HAVFATSIZ:
33580		STOB			;FATSIZ
33590		SEG	ES
33600		MUL	AL,[BP+FATCNT]	;Space occupied by all FATs
33610		SEG	ES
33620		ADD	AX,[BP+FIRFAT]
33630		STOW			;FIRDIR
33640	
33650		IF	SMALLDIR-1
33660		SEG	ES
33670		ADD	AX,[BP+DIRSEC]
33680		SEG	ES
33690		MOV	[BP+FIRREC],AX	;Destroys DIRSEC
33700		CALL	FIGMAX
33710		SEG	ES
33720		MOV	[BP+MAXCLUS],CX
33730		ENDIF
33740	
33750		IF	SMALLDIR
33760		MOV	DX,AX		;Save FIRDIR momentarily
33770		SEG	ES
33780		ADD	AX,[SDIRSEC]	;Add number of dir. sectors for 16-byte entry
33790		STOW			;FIRREC1
33800		XCHG	AX,CX		;Previously computed MAXCLUS
33810		STOW			;MAXCLUS1
33820		XCHG	DX,AX
33830		SEG	ES
33840		ADD	AX,[BP+DIRSEC]	;Add number of dir. sectores for 32-byte entry
33850		STOW			;FIRREC2
33860		CALL	FIGMAX
33870		XCHG	AX,CX
33880		STOW			;MAXCLUS2
33890		ENDIF
33900	
33910		MOV	AX,0FFH
33920		STOB			;DIRTYFAT
33930		SEG	ES
33940		MOV	AL,[BP+FATSIZ]
33950		SEG	ES
33960		MUL	AX,[BP+SECSIZ]
33970		ADD	DI,AX		;Allocate FAT
33980		POP	SI		;Restore pointer to init. table
33990		SEG	ES
34000		MOV	AL,[DRVCNT]
34010		INC	AL
34020		SEG	ES
34030		MOV	[DRVCNT],AL
34040		SEG	ES
34050		CMP	AL,[NUMDRV]
34060		JAE	CONTINIT
34070		JMP	PERDRV	
34080	CONTINIT:
34090		LODW			;Max. buffer size
34100		SEG	ES
34110		MOV	BX,[MAXSEC]
34120		MOV	AX,DIRBUF
34130		ADD	AX,BX
34140		SEG	ES
34150		MOV	[BUFFER],AX	;Start of buffer
34160		PUSH	DI		;Save ending location
34170		ADD	DI,BX		;Allocate directory buffer
34180		ADD	DI,BX		;Allocate buffer space
34190		ADD	DI,ADJFAC+15	;True start of free space
34200		MOV	CL,4
34210		SHR	DI,CL		;First free segment
34220		MOV	BP,DI
34230		XOR	AX,AX
34240		MOV	DS,AX
34250		MOV	ES,AX
34260		MOV	DI,INTBASE
34270		MOV	AX,QUIT
34280		STOW			;Set abort address--displacement
34290		MOV	AX,CS
34300		MOV	B,[ENTRYPOINT],LONGJUMP
34310		MOV	[ENTRYPOINT+1],ENTRY
34320		MOV	[ENTRYPOINT+3],AX
34330		MOV	[0],DIVOV	;Set default divide trap address
34340		MOV	[2],AX
34350		MOV	CX,9
34360		REP
34370		STOW				;Set 5 segments (skip 2 between each)
34380		MOV	[INTBASE+4],COMMAND
34390		MOV	[INTBASE+12],IRET	;CTRL-C exit
34400		MOV	[INTBASE+16],IRET	;Fatal error exit
34410		MOV	AX,BIOSREAD
34420		STOW
34430		MOV	AX,BIOSSEG
34440		STOW
34450		STOW	;Add 2 to DI
34460		STOW
34470		MOV	[INTBASE+18H],BIOSWRITE
34480		MOV	DX,CS
34490		MOV	DS,DX
34500		ADD	DX,BP
34510		MOV	[DMAADD],80H
34520		MOV	[DMAADD+2],DX
34530		MOV	AX,[DRVTAB]
34540		MOV	[CURDRVPT],AX
34550		MOV	CX,DX
34560		MOV	BX,0FH
34570	MEMSCAN:
34580		INC	CX
34590		JZ	HAVMEM
34600		MOV	DS,CX
34610		MOV	AL,[BX]
34620		NOT	AL
34630		MOV	[BX],AL
34640		CMP	AL,[BX]
34650		NOT	AL
34660		MOV	[BX],AL
34670		JZ	MEMSCAN
34680	HAVMEM:
34690		SEG	CS
34700		MOV	[ENDMEM],CX
34710		XOR	CX,CX
34720		MOV	DS,CX
34730		MOV	[EXIT],100H
34740		MOV	[EXIT+2],DX
34750		MOV	SI,HEADER
34760		CALL	OUTMES
34770		PUSH	CS
34780		POP	DS
34790		PUSH	CS
34800		POP	ES
34810		PUSH	DX
34820	GETDAT:
34830		MOV	SI,DATMES
34840		CALL	OUTMES
34850		MOV	DX,DATBUF
34860		CALL	BUFIN
34870		CALL	CRLF
34880		MOV	SI,DATBUF+2
34890		MOV	DX,12
34900		CALL	MYD
34910		JC	GETDAT
34920		MOV	CL,5
34930		SHL	AX,CL
34940		MOV	[DATE],AX
34950		MOV	DX,31
34960		CALL	MYD
34970		JC	GETDAT
34980		OR	[DATE],AL
34990		MOV	DX,2100
35000		CALL	MYD
35010		JC	GETDAT
35020		SUB	AX,80
35030		JC	GETDAT
35040		CMP	AX,19
35050		JBE	SAVYR
35060		SUB	AX,1900
35070		JC	GETDAT
35080	SAVYR:
35090		SHL	AL
35100		OR	[DATE+1],AL
35110	;Move the FATs into position and adjust the drive pointer table
35120		POP	DX
35130		POP	SI
35140		MOV	AX,[MAXSEC]
35150		SHL	AX		;Allocate two buffers
35160		ADD	AX,ADJFAC
35170		JZ	FINJMP
35180		MOV	DI,DRVTAB
35190		MOV	CX,15
35200	ADJLP:
35210		ADD	[DI],AX
35220		INC	DI
35230		INC	DI
35240		LOOP	ADJLP
35250		MOV	CX,SI
35260		MOV	SI,MEMSTRT	;Place to move FATs from
35270		SUB	CX,SI		;Total length of FATs
35280		MOV	DI,AX
35290		ADD	DI,SI		;Place to move FATs to
35300		OR	AX,AX
35310		JS	MOVJMP
35320		DEC	CX
35330		ADD	DI,CX
35340		ADD	SI,CX
35350		INC	CX
35360		DOWN
35370	MOVJMP:
35380		JMP	MOVFAT
35390	FINJMP:	JMP	FININIT
35400	
35410	FIGFATSIZ:
35420		SEG	ES
35430		MUL	AL,[BP+FATCNT]
35440		SEG	ES
35450		ADD	AX,[BP+FIRFAT]
35460		SEG	ES
35470		ADD	AX,[SDIRSEC]	;Use small dir. entry to figure FAT size
35480	FIGMAX:
35490	;AX has equivalent of FIRREC
35500		SEG	ES
35510		SUB	AX,[BP+DSKSIZ]
35520		NEG	AX
35530		SEG	ES
35540		MOV	CL,[BP+CLUSSHFT]
35550		SHR	AX,CL
35560		INC	AX
35570		MOV	CX,AX		;MAXCLUS
35580		INC	AX
35590		MOV	DX,AX
35600		SHR	DX
35610		ADC	AX,DX		;Size of FAT in bytes
35620		SEG	ES
35630		MOV	SI,[BP+SECSIZ]
35640		ADD	AX,SI
35650		DEC	AX
35660		XOR	DX,DX
35670		DIV	AX,SI
35680		RET
35690	
35700	MYD:
35710	;SI points to input buffer. Get decimal number < DX and return it
35720	;in AX. Carry set on error.
35730		XOR	BX,BX
35740		MOV	AH,0
35750	GETDIG:
35760		LODB
35770		SUB	AL,"0"
35780		JC	CHKRET
35790		CMP	AL,10
35800		JNC	CHKRET
35810		SHL	BX
35820		MOV	CX,BX
35830		SHL	BX
35840		SHL	BX
35850		ADD	BX,CX
35860		ADD	BX,AX
35870		JP	GETDIG
35880	CHKRET:
35890		MOV	AX,BX
35900		OR	AX,AX
35910		STC
35920		JZ	RET
35930		CMP	DX,AX
35940		RET
35950	
35960	DRVCNT:	DB	0
35970	
35980	DATMES:	DB	"Enter today's date (m-d-y): $"
35990	DATBUF:	DB	12,8,"04-28-81",13
36000		DS	5
36010	
36020	SDIRSEC:DS	2
36030	
36040	MEMSTRT:
36050	ADJFAC:	EQU	DIRBUF-MEMSTRT
   CCCCCCCCCCCC         OOOOOOOOO         MMM         MMM         AAAAAAAAA         NNN	        NNN      DDDDDDDDDDDD   
   СССССССССССС         OOOOOOOOO         MMM         MMM         AAAAAAAAA         NNN         NNN      DDDDDDDDDDDD   
   СССССССССССС         OOOOOOOOO         MMM         MMM         AAAAAAAAA         NNN         NNN      DDDDDDDDDDDD   
CCC                  OOO         OOO      MMMMMM   MMMMMM      AAA         AAA      NNN         NNN      DDD         DDD
CCC                  OOO         OOO      MMMMMM   MMMMMM      AAA         AAA      NNN         NNN      DDD         DDD
CCC                  OOO         OOO      MMMMMM   MMMMMM      AAA         AAA      NNN         NNN      DDD         DDD
CCC                  OOO         OOO      MMM   MMM   MMM      AAA         AAA      NNNNNN      NNN      DDD         DDD
CCC                  OOO         OOO      MMM   MMM   MMM      AAA         AAA      NNNNNN      NNN      DDD         DDD
CCC                  OOO         OOO      MMM   MMM   MMM      AAA         AAA      NNNNNN      NNN      DDD         DDD
CCC                  OOO         OOO      MMM         MMM      AAA         AAA      NNN   NNN   NNN      DDD         DDD
CCC                  OOO         OOO      MMM         MMM      AAA         AAA      NNN   NNN   NNN      DDD         DDD
CCC                  OOO         OOO      MMM         MMM      AAA         AAA      NNN   NNN   NNN      DDD         DDD
CCC                  OOO         OOO      MMM         MMM      AAAAAAAAAAAAAAA      NNN      NNNNNN      DDD         DDD
CCC                  OOO         OOO      MMM         MMM      AAAAAAAAAAAAAAA      NNN      NNNNNN      DDD         DDD
CCC                  OOO         OOO      MMM         MMM      AAAAAAAAAAAAAAA      NNN      NNNNNN      DDD         DDD
CCC                  OOO         OOO      MMM         MMM      AAA         AAA      NNN         NNN      DDD         DDD
CCC                  OOO         OOO      MMM         MMM      AAA         AAA      NNN         NNN      DDD         DDD
CCC                  OOO         OOO      MMM         MMM      AAA         AAA      NNN         NNN      DDD         DDD
   CCCCCCCCCCCC         OOOOOOOOO         MMM         MMM      AAA         AAA      NNN         NNN      DDDDDDDDDDDD   
   СССССССССССС         OOOOOOOOO         MMM         MMM      AAA         AAA      NNN         NNN      DDDDDDDDDDDD   
   СССССССССССС         OOOOOOOOO         MMM         MMM      AAA         AAA      NNN         NNN      DDDDDDDDDDDD   




DDDDDDDDDDDD            IIIIIIIII         FFFFFFFFFFFFFFF
DDDDDDDDDDDD            IIIIIIIII         FFFFFFFFFFFFFFF
DDDDDDDDDDDD            IIIIIIIII         FFFFFFFFFFFFFFF
DDD         DDD            III            FFF
DDD         DDD            III            FFF
DDD         DDD            III            FFF
DDD         DDD            III            FFF
DDD         DDD            III            FFF
DDD         DDD            III            FFF
DDD         DDD            III            FFFFFFFFFFFF
DDD         DDD            III            FFFFFFFFFFFF
DDD         DDD            III            FFFFFFFFFFFF
DDD         DDD            III            FFF
DDD         DDD            III            FFF
DDD         DDD            III            FFF
DDD         DDD            III            FFF
DDD         DDD            III            FFF
DDD         DDD            III            FFF
DDDDDDDDDDDD            IIIIIIIII         FFF
DDDDDDDDDDDD            IIIIIIIII         FFF
DDDDDDDDDDDD            IIIIIIIII         FFF




 *START* User ROS BASIC [500,500]  Job  86DOS Seq. 7115 Date 16-Jun-81 15:13:30 Monitor Microsoft 1091 603a4d80j *START*
File: DSKC:COMAND.DIF<055>[500,500] Created: 16-Jun-81 13:15:48 Printed: 16-Jun-81 15:23:55
QUEUE Switches:  /FILE:ASCII /COPIES:1 /SPACING:1 /LIMIT:565 /FORMS:NORMAL
