;  BASIC DISK OPERATING SYSTEM  OF CP/M 86
;
;  1983.8.16.
;
;  EQUATIONS OF FUNCTION
;
CLIST	EQU	5		;LIST OUT
CRTVNO	EQU	12		;RETURN VERION NUMBER
CREADS	EQU	20		;READ SEQUENTIAL
CSTDMA	EQU	26		;SET DMA OFFSET
CSTDMS	EQU	51		;SET DMA SEGMENT
CGTMXM	EQU	53		;GET MAXIMUM MEMORY
CGTAMX	EQU	54		;GET ABSOLUTE MAXIMUM MEOMRY
CALMEM	EQU	55		;ALLOCATE MEMORY
CALAME	EQU	56		;ALLOCATE ABSOLUTE MEMORY
;
;  EQUATIONS OF DATA
;
BS	EQU	8		;BACK SPACE
HT	EQU	9		;HORIZONTAL TAB
LF	EQU	0AH		;LINE FEED
CR	EQU	0DH		;CARRIAGE RETURN
ITBDOS	EQU	0E0H		;BDOS INTERRUPT VECTOR
DELCOD	EQU	0E5H		;DELETED FILE DIRECTORY CODE
;
;  EQUATIONS OF DATA
;
COMBUF	EQU	9		;COMMAND BUFFER OF CCP
MDSUBE	EQU	0805H		;SUBMIT MODE
;
;  EQUATIONS OF BIOS VECTOR
;
VBIOS	EQU	2500H		;BIOS JUMP VECTOR TOP
VINIT	EQU	VBIOS+00H	;INITIALIZE  COLD START
VWBOOT	EQU	VBIOS+03H	;WARM START
VCONST	EQU	VBIOS+06H	;CONSOLE STATUS
VCONIN	EQU	VBIOS+09H	;CONSOLE INPUT
VCONOT	EQU	VBIOS+0CH	;CONSOLE OUTPUT
VLIST	EQU	VBIOS+0FH	;LIST OUT
VPUNCH	EQU	VBIOS+12H	;PUNCH OUT
VREADR	EQU	VBIOS+15H	;READER IN
VHOME	EQU	VBIOS+18H	;HOME
VSLDSK	EQU	VBIOS+1BH	;SELECT DISK
VSTTRK	EQU	VBIOS+1EH	;SET TRACK
VSTSEC	EQU	VBIOS+21H	;SET SECTOR
VSTDMA	EQU	VBIOS+24H	;SET DMA OFFSET
VDREAD	EQU	VBIOS+27H	;READ ONE SECTOR
VDWRIT	EQU	VBIOS+2AH	;WRITE ONE SECTOR
VSCTRN	EQU	VBIOS+30H	;SECTOR TRANSLATE
VSTDMS	EQU	VBIOS+33H	;SET DMA SEGMENT
VGTMRT	EQU	VBIOS+36H	;GET MEMORY REGION TABLE
VGTIOB	EQU	VBIOS+39H	;GET I/O BYTE
VSTIOB	EQU	VBIOS+3CH	;SET I/ BYTE
;
;
	CSEG
	ORG	0
TOP:				;DUMMY FOR TAGGED LABEL
;
	ORG	0A20H
;
;  PATCH AREA
;
;  FOR LOAD PROGRAM
;
MLOADK:				;OK END
	MOV	INSTOF,AX	;RESTORE ENTRY STACK & END FOR LOAD PROGRAM
	POP	ES
	RET
;
	ORG	0A30H
;
MLOADQ:				;ERROR END OF LOAD PROGRAM
	MOV	AX,FCBSEG
	MOV	INDSEG,AX
	MOV	OTPARA,-1
	JMP	MLOADE
;
	ORG	0A50H
;
;  FOR BDOS BODY
;  CHECK BDOS FUNCTION CODE RANGE
;
BDOSBC:
	JC	BDOSBI		;IN RANGE
	MOV	OTPARA,-1	;OVER END
	RET
;
BDOSBI:				;IN RANGE
	JMP	BDOSBS
;
;
	ORG	0A60H
	DB	'12 january 82'
;
	ORG	0A80H
;
;  BDOS FUNCTION INDEX
;
IXMAIN:
	DW	MSYRST		; 0 SYSTEM RESET
	DW	MCONIN		; 1 CONSOLE INPUT
	DW	CONOUT		; 2 CONSOLE OUTPUT
	DW	MREDER		; 3 READER INPUT
	DW	VPUNCH		; 4 PUNCHER UTPUT
	DW	BLIST		; 5 LIST OUTPUT
	DW	MDCNIO		; 6 DIRECT CONSOLE I/O
	DW	MGTIOB		; 7 GET I/O BYTE
	DW	MSTIOB		; 8 SET I/O BYTE
	DW	MBUFPR		; 9 PRINT STRING
	DW	MRDCBF		;10 READ CONSOLE BUFFER
	DW	MCONST		;11 CONSOLE STATUS
	DW	MRTVNO		;12 RETURN VERSION NUMBER
	DW	MRSDSY		;13 RESET DISK SYSTEM
	DW	MSELDK		;14 SELECT DISK
	DW	MOPEN		;15 OPEN FILE
	DW	MCLOSE		;16 CLOSE FILE
	DW	MSRCHF		;17 SEARCH FOR FIRST
	DW	MSRCHN		;18 SEARCH FOR NEXT
	DW	MDELET		;19 DELETE FILE
	DW	MREADS		;20 READ SEQUENTIAL
	DW	MWRITS		;21 WRITE SEQUENTIAL
	DW	MMAKE		;22 MAKE FILE
	DW	MRENAM		;23 RENAME FILE
	DW	MRTLIV		;24 RETURN LOGIN VECTOR
	DW	MRTCDK		;25 RETURN CURRENT DISK
	DW	MSTDMO		;26 SET DMA OFFSET
	DW	MGTALM		;27 GET ALLOCATION MAP ADDRESS
	DW	MWPDSK		;28 WRITE PROTECT DISK
	DW	MGTROV		;29 GET READ/ONLY VECTOR
	DW	MSTFAT		;30 SET FILE ATTRIBUTE
	DW	MGDPBA		;31 GET DISK PARAMETER BLOCK ADDRESS
	DW	MSTUCD		;32 SET/GET USER CODE
	DW	MREADR		;33 READ RANDOM
	DW	MWRITR		;34 WRITE RANDOM
	DW	MCMPFS		;35 COMPUTE FILE SIZE
	DW	MSTRRC		;36 SET RANDOM RECORD
	DW	MRSTDV		;37 RESET DRIVE
	DW	NOPROC		;38 ACCESS DRIVE
	DW	NOPROC		;39 FREE DRIVE
	DW	MWRITZ		;40 WRITE RANDOM WITH ZERO FILL
	DW	MCHAIN		;47 CHAIN TO PROGRAM
	DW	MFLUSH		;48 FLUSH BUFFERS
	DW	MGTSAD		;49 GET SYSTEM ADDRESS
	DW	MDBIOS		;50 DIRECT BIOS CALL
	DW	MSTDMS		;51 SET DMA SEGMENT
	DW	MGTDMS		;52 GET DMA ADDRESS
	DW	MGTMXM		;53 GET MAXIMUM MEMORY
	DW	MGTAMX		;54 GET ABSOLUTE MAXIMUM MEMORY
	DW	MALMEM		;55 ALLOCATE MEMORY SEGMENT
	DW	MALAME		;56 ALLOCATE ABSOLUTE MEMORY SEGMENT
	DW	MFRMEM		;57 FREE SPECIFIED MEMORY SEGMENT
	DW	MFRALM		;58 FREE ALL MEMORY
	DW	MLOADP		;59 PROGRAM LOAD
;
;  12:RETURN VERSION NUMBER
;
MRTVNO:
	MOV	AL,022H		;2.2 IS VERSION NUMBER
	JMP	BTPRST		;H=0 SIMPLE CP/M
;
;  49:GET SYSTEM ADDRESS
;
MGTSAD:
	MOV	BX,OFFSET DMAADD ;SYSTEM DATA AREA TOP
	JMP	WDPRST
;
;  BDOS NORMAL TOP
;
	ORG	0B00H
;
;  USER ID CODE OF BDOS
;
	DB	1		;OEM CODE
	DB	10		;VERSION NUMBER
	DB	0
	DB	0,0,0		;USER ID
;
;  BDOS ENTRY
;
BDOSEN:
	PUSH	DS
	MOV	AX,CS
	MOV	DS,AX
	POP	INDSEG		;SAVE ENTRY DATA SEGMENT
	CMP	CL,CLIST
	JZ	BDOSEC
	CMP	CL,CRTVNO+1
	JC	BDOSES		;SIMPLE BDOS CALL
BDOSEC:				;COMPLICATED I/O FUNCTION
	MOV	MDCONF,-1	;SET COMPLICATED I/O MODE
BDOSES:
	MOV	INSTSG,SS
	MOV	INSTOF,SP	;SAVE ENTRY STACK
	CMP	FLINSD,1
	JZ	BDOSEI		;FROM INSIDE
	MOV	AX,CS
	MOV	SS,AX
	MOV	SP,OFFSET STACK	;SET SYSTEM STACK
BDOSEI:
	MOV	BX,INSTOF
	MOV	ES,INSTSG
	MOV	BX,ES:4[BX]
	AND	BX,200H		;GET INTERRUPT FALG
	JZ	$+3		;DI
	STI			;EI
	MOV	AX,DS
	PUSH	BP
	PUSH	DI
	PUSH	SI
	PUSH	CS
	POP	ES
	MOV	CURSEG,ES	;SAVE CURRENT SEGMENT
	CALL	BDOSB		;CALL BDOS BODY
	POP	SI
	POP	DI
	POP	BP
	MOV	ES,CURSEG
	CLI
	MOV	SS,INSTSG	;RESTORE STACK
	MOV	SP,INSTOF
	MOV	MDCONF,0	;CLEAR COMPLICATED I/O MODE
	MOV	DS,INDSEG
	IRET
;
;  BDOS BODY
;
BDOSB:
	MOV	INPARA,DX
	MOV	INPARB,DL
	XOR	AX,AX
	MOV	OTPARA,AX	;CLEAR OUTPUT PARAMETER
	MOV	AFWFCB,AL
	MOV	ENTTYP,AL
	MOV	FLOMOD,AL
	MOV	BX,OFFSET ENDPRC
	PUSH	BX		;SET RETURN ADDRESS
	CMP	CL,41
	JC	BDOSBS		;0 TO 40
	SUB	CL,6
	CMP	CL,60-6		;47 TO 59
	JMP	BDOSBC		;CHECK OVER
;
BDOSBS:
	MOV	BL,CL
	MOV	BH,0
	MOV	CL,DL		;SET BYTE PARAMETER
	ADD	BX,BX
	JMP	WORD PTR IXMAIN[BX] ;TO EACH ROUTINE
;
;  ERROR ROUTINES
;
;  BAD SECTOR ERROR
;
EBADSC:
	MOV	BX,OFFSET CBADSC ;BAD SECTOR
	CALL	ERPROC
	CMP	AL,'C'-40H
	JNZ	STWFCE		;CONTINUE
	JMPS	EROFIE		;ABORT
;
;  SELECT ERROR
;
ESELCT:
	MOV	BX,OFFSET CSELCT
	JMPS	EROFIS
;
;  R/O DISK
;
ERODSK:
	MOV	BX,OFFSET CRODSK
	JMPS	EROFIS
;
;  R/O FILE
;
EROFIL:
	MOV	BX,OFFSET CROFIL
EROFIS:
	CALL	ERPROC		;OUT COMMENT & WAIT RESPONSE
EROFIE:
	JMP	MSYRSA
;
;  ERROR TRAP PROCESS
;  INPUT
;  BX:COMMENT POINT
;
ERPROC:
	PUSH	BX		;SAVE EACH COMMNET POINT
	CALL	CRLF
	MOV	AL,CURDSK
	ADD	AL,'A'
	MOV	CERRDK,AL	;SET DRIVE NAME
	MOV	CX,OFFSET CERROR
	CALL	BUFPRN		;BDOS ERROR ON X:
	POP	CX
	CALL	BUFPRN		;OUT EACH COMMENT
	JMP	CONINC		;RESPONSE WAIT
;
;  SET INPUT DATA TO WORK FCB OR MCB
;  INPUT
;  CL:COPY COUNT
;
STWFCB:
	PUSH	DS
	PUSH	AX
	PUSH	CX
	MOV	AFWFCB,0FFH
	MOV	CNFCBC,CL	;SAVE COPY LENGTH
	XOR	CH,CH
	MOV	SI,INPARA	;OFFSET OF INPUT PARAMETER
	MOV	PTUFCB,SI
	MOV	DI,OFFSET WKFCB ;OFFSET OF WORK
	MOV	INPARA,DI
	MOV	DS,INDSEG	;SEGMENT OF INPUT PARAMETER
	CLD
	REP	MOVSB		;GET DATA
	POP	CX
	POP	AX
	POP	DS
STWFCE:
	RET
;
;  SET SEQUENTIAL FCB
;
STWFCS:
	PUSH	CX
	MOV	CL,33		;SEQUENTIAL FCB LENGTH IS 33
	JMPS	STWFCC
;
;  SET RANDOM FCB
;
STWFCR:
	PUSH	CX
	MOV	CL,36		;RANDOM FCB LENGTH IS 36
STWFCC:
	CALL	STWFCB
	POP	CX
	RET
;
;  RESTORE FCB DATA
;
RSTFCB:
	PUSH	ES
	PUSH	AX
	PUSH	CX
	MOV	CL,CNFCBC	;GET LENGTH
	XOR	CH,CH
	MOV	ES,INDSEG	;SEGMENT OF INPUT PARAMETER
	MOV	SI,OFFSET WKFCB
	MOV	DI,PTUFCB	;OFFSET OF ORIGINAL
	MOV	INPARA,DI
	CLD
	REP	MOVSB		;RESTORE FCB DATA
	POP	CX
	POP	AX
	POP	ES
	RET
;
;  READ BY FAR ADDRESS FCB
;
READFR:
	MOV	CL,CREADS
	MOV	DX,UFCBOF	;USER FCB OFFSET
	MOV	DS,FCBSEG	;USER FCB SEGMENT
	CALL	BDOSIS		;READ SEQUENTIAL
	MOV	AX,CS
	MOV	DS,AX		;RESTORE SEGMENT
	RET
;
;   BDOS CALL FROM INSIDE OF BDOS
;
;  MUST BE SAVE STACK SAVE AREA
;  & CLEAR INSIDE FLAG AT END  ???
;
BDOSIS:
	MOV	CS:FLINSD,1	;SET INSIDE FLAG
	INT	ITBDOS
	RET
;
;  INTERNAL BDOS CALL FOR MEMORY MANAGEMENT
;  INPUT
;  CL:FUNCTION CODE
;
BDOSMM:
	PUSH	BX
	MOV	DX,OFFSET SYSMCB
	CALL	BDOSIS
	POP	BX
	RET
;
;  MEMORY MANAGEMENT UTILITY
;
;  COMPARE MEMORY REQUEST BETWEEN MAX-MIN
;  INPUT
;  SI:GROUP DESCRIPTOR TOP
;  DI:GROUP DESCRIPTOR TOP
;  OUTPUT
;  SI:SMALLER GD
;  DI:LARGER GD
;
CMPMRQ:
	PUSH	AX
	PUSH	BX
	MOV	BX,7[SI]
	SUB	BX,5[SI]	;GET MAX-MIN
	MOV	AX,7[DI]
	SUB	AX,5[DI]
	CMP	BX,AX
	JBE	$+4		;(DI) > (SI)
	XCHG	SI,DI
	POP	BX
	POP	AX
	RET
;
;  ALLOCATE MEMORY FOR LOAD PROGRAM
;  OUTPUT
;  AL:0 OK  -1 CANNOT ALLOCATE
;
ALMEMR:
	SUB	BX,BX		;CLEAR MIN SIZE
	SUB	DX,DX		;CLEAR MAX SIZE
	MOV	FMODEL,0FFH	;SET 8080 MODEL FLAG
	MOV	CX,8		;COUNT OF GROUP DESCRIPTOR
	MOV	SI,OFFSET BFGRDC ;BUFFER TOP
ALMEML:				;LOOP OF ONE GROUP DESCRIPTOR
	CMP	BYTE PTR [SI],0
	JZ	ALMEMN		;NOT ACTIVE DESCRIPTOR
	CMP	BYTE PTR [SI],2
	JNZ	ALMEMD		;NOT DATA GROUP
	MOV	FMODEL,0	;DATA GROUP  SO NOT 8080 MODEL
ALMEMD:
	CMP	WORD PTR 3[SI],0
	JZ	ALMEMG		;RELOCATABLE
	MOV	AX,3[SI]	;ABSOLUTE
	MOV	SYSMCB,AX	;SET ABSOLUTE BASE
	CMP	WORD PTR 7[SI],0
	MOV	AX,5[SI]	;MIN
	JZ	$+5		;NO MAX SO DO BY MIN
	MOV	AX,7[SI]	;WITH MAX SO DO BY MAX
	MOV	SYSMCB+2,AX	;SET LENGTH
	PUSH	CX
	MOV	CL,CALAME
	PUSH	DX
	CALL	BDOSMM		;ALLOCATE ABSOLUTE MEMORY SEGMENT
	POP	DX
	POP	CX
	CMP	OTPARB,0
	JZ	ALMEMN		;OK ALLOCATED
	PUSH	CX		;NOT ALLOCATED
	MOV	CL,CGTAMX
	CALL	BDOSMM		;GET AVAILABLE MAXIMUM SIZE
	POP	CX
	MOV	AX,SYSMCB+2
	CMP	5[SI],AX
	JNC	ALMEME		;SMALLER THAN MIN  SO ERROR END
	MOV	7[SI],AX	;SET AVAILABLE MAX AS LENGTH
	MOV	CL,CALAME
	CALL	BDOSMM		;ALLOCATE
	JMPS	ALMEMN		;TO NEXT
;
ALMEMG:				;RELOCATABLE GROUP
	ADD	BX,5[SI]	;GET TOTAL BY MIN
	CMP	WORD PTR 7[SI],0
	JZ	ALMEMM		;NO MAX   SO DO BY MIN
	ADD	DX,7[SI]	;GET TOTAL MAX
	JNC	ALMEMN		;NOT OVER
	MOV	DX,0FFF0H	;OVER SO DO BY ABSOLUTE MAX VALUE
	JMPS	ALMEMN
;
ALMEME:				;ERROR
	JMPS	SRTGFF
;
ALMEMM:				;NO MAX SPECIFIED SO MIN USED AS MAX
	ADD	DX,5[SI]	;GET MAX TOTAL
ALMEMN:				;END OF ONE GROUP DESCRIPTOR
	ADD	SI,9
	LOOP	ALMEML		;TO NEXT GD
	OR	DX,DX
	JZ	ALMEMF		;NO RELOCATABLE LENGTH
	MOV	SYSMCB+2,DX	;SET MAX LENGTH
	MOV	CL,CALMEM
	CALL	BDOSMM		;ALLOCATE RELOCATABLE MEMORY
	CMP	OTPARB,0
	JZ	ALMEMF		;OK ALLOCATED
	MOV	CL,CGTMXM
	CALL	BDOSMM		;GET MAX SIZE
	CMP	BX,SYSMCB+2
	JA	ALMEME		;SMALLER THAN MIN  SO ERROR END
	MOV	CL,CALMEM
	CALL	BDOSMM		;ALLOCATE BY MAXIMUM AVAILABLE SIZE
	MOV	DX,SYSMCB+2
	SUB	DX,BX		;GET SPACE BETWEEN AVAIL TO MIN
	CALL	STMXGD		;SET AVAILABLE MAX TO GD
ALMEMF:
	MOV	DI,PNUMCB
	MOV	AX,FCBSEG
	MOV	CX,CS
	CMP	AX,CX
	JNZ	ALMEMS		;NOT SYSTEM
	MOV	BYTE PTR 4[DI],1 ;SYSTEM
	INC	CNUMCB
ALMEMS:
	JMPS	SRTGFG
;
;  SEARCH TARGET GROUP FORM
;  INPUT
;  AL:TARGET GROUP FORM
;  OUTPUT
;  SI:GD TOP
;  AL:0 OK  -1 NOT FOUND
;
SRTGFM:
	MOV	SI,OFFSET BFGRDC
	MOV	CX,8
SRTGFL:
	CMP	[SI],AL
	JZ	SRTGFG		;GET MATCHED GD
	ADD	SI,9
	LOOP	SRTGFL		;TO NEXT
SRTGFF:				;FAIL END
	MOV	AL,0FFH
	RET
;
SRTGFG:				;OK END
	MOV	AL,0
	RET
;
;  SETUP MAXIMUM VALUE OF GROUP DESCRIPTOR
;  INPUT
;  DX:EXTRA SPACE
;
STMXGD:
	CMP	FMODEL,0FFH
	JNZ	STMXGN		;NOT 8080 MODEL
	MOV	BX,BFGRDC+5	;8080 MODEL
	ADD	BX,DX
	MOV	BFGRDC+7,BX	;SO SET IN TOP GD
	RET
;
STMXGN:				;NOT 8080 MODEL
	MOV	AL,2
	CALL	SRTGFM		;SEARCH DATA GROUP
	CMP	WORD PTR 7[SI],0
	JZ	STMXGX		;NO REQUEST OF MAX
	MOV	DI,SI
	MOV	AX,3
	CALL	SRTGFM		;SEARCH EXTRA GROUP
	CMP	WORD PTR 7[SI],0
	JZ	STMXGS		;NO REQUEST OF MAX
	CALL	CMPMRQ		;GET LARGER REQUESTED GROUP
	SHR	DX,1		;GET HALF SPACE
	MOV	BX,DX
	ADD	BX,5[SI]
	CMP	BX,7[SI]
	JBE	STMXGR		;REQUESTED IS LARGER THAN AVAIL HALF
	SUB	BX,7[SI]	;REQUESTED IS SMALLER
	ADD	DX,BX		;SO GET LEFT AVAIL SPACE
	JMPS	STMXGS
;
STMXGR:				;REQUESTED IS LARGER 
	MOV	7[SI],BX	;SET HALF SPACE
STMXGS:
	ADD	DX,5[DI]
	MOV	7[DI],DX	;SET LEFT SPACE
	RET
;
STMXGX:				;DATA GROUP HAS NO REQUEST
	MOV	AL,3
	CALL	SRTGFM		;SEARCH EXTRA GROUP
	ADD	DX,5[SI]
	MOV	7[SI],DX	;SET LEFT SPACE
	RET
;
;  ADD GROUP LENGTH
;  INPUT
;  SI:GD POINT
;  AX:TOTAL
;  OUTPUT
;  AX:TOTAL
;
ADDGLN:
	CMP	WORD PTR 7[SI],0
	JZ	ADDGLS		;NO MAX  SO DO BY MIN
	ADD	AX,7[SI]	;ADD MAX
	RET
;
ADDGLS:				;DO BY MIN
	ADD	AX,5[SI]	;ADD MIN
	RET
;
;  SETUP LOADING BASE
;
STLDBS:
	MOV	MODE80,0
	MOV	AX,SYSMCB	;GET LOADING BASE OF RELOCATABLE
	CMP	FMODEL,0FFH
	JNZ	STLDBM		;NOT 8080 MODEL
	MOV	MODE80,1	;8080 MODEL
	MOV	BFGRDC+3,AX	;SET BASE OF TOP GD
	MOV	DGBASE,AX	;SET SAME BASE TO DATA SEGMENT BASE
	JMPS	STLDBF
;
STLDBM:				;NOT 8080 MODEL
	MOV	SI,OFFSET BFGRDC
	MOV	CX,8
STLDBL:				;ONE GD LOOP
	CMP	BYTE PTR [SI],0
	JZ	STLDBA		;NOT ACTIVE
	CMP	BYTE PTR [SI],2
	JNZ	STLDBD		;NO DATA GROUP
	MOV	DGBASE,AX	;SAVE DATA SEGMENT BASE
STLDBD:
	CMP	WORD PTR 3[SI],0
	JNZ	STLDBN		;ABSOULTE
	MOV	3[SI],AX	;RELOCATABLE SO SET BASE
	CMP	BYTE PTR [SI],9
	JNZ	STLDBA
	MOV	BYTE PTR [SI],1	;SHARED CODE GROUP  SO TO CODE GROUP
STLDBA:
	CALL	ADDGLN		;ADD GROUP LENGTH
STLDBN:
	ADD	SI,9
	LOOP	STLDBL		;TO NEXT GD
STLDBF:
	RET
;
;  GET ONE PARAGRAPH DATA
;  INPUT
;  BP:COUNT
;  OUTPUT
;  SI:DATA POINT
;
GOPGDT:
	CMP	BP,16*7
	JNZ	GOPGDS		;NOT END
	PUSH	BX		;END OF ONE SECTOR  SO GET NEXT SECTOR
	PUSH	ES
	CALL	READFR		;GET ONE SECTOR
	POP	ES
	POP	BX
	MOV	BP,0		;CLEAR COUNT
	MOV	SI,OFFSET BFLDPR ;SET DATA TOP POINT
	RET
;
GOPGDS:				;NOT END
	ADD	BP,16		;UP COUNT
	RET
;
;  MAKE LENGTH BY BYTE
;  INPUT
;  AX:LENGTH BY PARAGRAPH
;  OUTPUT
;  AH,BX:BYTE LENGTH
;
MKBTLG:
	MOV	BX,AX
	AND	AX,0F000H
	MOV	CL,4
	SHR	AH,CL		;GET HIGHER 4 BITS
	MOV	CL,4
	SHL	BX,CL
	SUB	BX,1
	JNC	$+4
	DEC	AH
	RET
;
;  59:LOAD PROGRAM
;
MLOADP:
	MOV	AX,INDSEG
	MOV	FCBSEG,AX	;SET FCB SEGMENT
	PUSH	ES
	NOP
	MOV	UFCBOF,DX	;SET FCB OFFSET
	MOV	AX,INSTSG
	MOV	LPSTSG,AX
	MOV	AX,INSTOF
	MOV	LPSTOF,AX	;SAVE ENTRY STACK POINTER
	MOV	DX,CS
	MOV	CL,CSTDMS
	CALL	BDOSIS		;SET DATA SEGMENT
	MOV	DX,OFFSET BFGRDC
	MOV	CL,CSTDMA
	CALL	BDOSIS		;SET DMA OFFSET TO GD WORK
	CALL	READFR		;GET GROUP DESCRIPTOR
	CMP	OTPARB,0
	JZ	MLOADS		;OK
MLOADM:				;ERROR END
	JMP	MLOADR
;
MLOADS:
	CALL	ALMEMR		;ALLOCATE REQUESTED MEMORY
	TEST	AL,AL
	JNZ	MLOADM		;CANNOT ALLOCATE
	CALL	STLDBS		;SETUP LOADING BASE OF EACH GD
	MOV	DX,OFFSET BFLDPR
	MOV	CL,CSTDMA
	CALL	BDOSIS		;SET DMA OFFSET TO READ WORK
	MOV	BP,16*7
	MOV	CX,8
	MOV	BX,OFFSET BFGRDC
MLOADL:				;ONE GD LOOP
	PUSH	CX
	CMP	BYTE PTR [BX],0
	JZ	MLOADN		;NOT ACTIVE GD
	MOV	ES,3[BX]	;GET BASE
	MOV	DI,0
	MOV	CX,1[BX]	;GET PARAGRAPH LENGTH
	JCXZ	MLOADN		;NO LENGTH
MLOADG:				;ONE PARAGRAPH LOADING LOOP
	PUSH	CX
	CALL	GOPGDT		;GET DATA
	MOV	CX,8
	CLD
	REP	MOVSW		;MOVE TO TARGET
	CMP	DI,0
	JNZ	MLOADB		;NOT 64K BAUNDARY
	MOV	DX,ES		;UP SEGMENT
	ADD	DH,010H
	MOV	ES,DX
MLOADB:
	POP	CX
	LOOP	MLOADG		;TO NEXT
MLOADN:
	POP	CX
	ADD	BX,9
	LOOP	MLOADL		;TO NEXT GD
	MOV	ES,DGBASE	;GET DATA GROUP SEGMENT
	MOV	OTPARA,ES
	MOV	DI,0
	MOV	CX,48
	MOV	AL,0
	CLD
	REP	STOSB		;CLEAR BASE PAGE
	MOV	DI,0
	MOV	AL,MODE80
	MOV	ES:5[DI],AL	;SET 8080 MODEL MODE
	MOV	DL,1		;CODE GROUP FORM
MLOADF:				;ONE FORM TYPE PARAMETER SETUP LOOP
	MOV	SI,OFFSET BFGRDC
	MOV	CX,8
MLOADC:				;GD SEARCH LOOP
	CMP	[SI],DL
	JZ	MLOADT		;GET TARGET GD
	ADD	SI,9
	LOOP	MLOADC		;TO NEXT GD
	JMPS	MLOADX		;NOT MATCH SO TO NEXT FORM
;
MLOADT:				;GET TARGET GD
	MOV	AX,3[SI]
	MOV	ES:3[DI],AX	;SET BASE PARAGRAPH ADDRESS
	MOV	AX,5[SI]
	CMP	WORD PTR 7[SI],0
	JZ	$+5		;NO MAX  SO BY MIN
	MOV	AX,7[SI]	;GET MAX SIZE
	CALL	MKBTLG		;TO BYTE LENGTH
	MOV	ES:2[DI],AH	;SET HIGHER 4 BITS
	MOV	ES:[DI],BX	;SET LOWER 16 BITS
	CMP	FMODEL,0FFH
	JNZ	MLOADX		;NOT 8080 MODEL
	ADD	DI,6		;8080 MODEL
	MOV	ES:2[DI],AH	;SET ALSO IN DATA SEGMENT PARAMETER
	MOV	ES:[DI],BX
	JMPS	MLOADE
;
MLOADX:				;TO NEXT FORM
	INC	DL
	ADD	DI,6
	CMP	DL,8
	JBE	MLOADF		;TO NEXT FORM
MLOADE:				;END OF LOADING
	MOV	AX,UFCBOF
	MOV	INPARA,AX
	MOV	FLINSD,0	;CLEAR INSIDE MODE
	MOV	AX,LPSTSG
	MOV	INSTSG,AX	;RESTORE ENTRY STACK
	MOV	AX,LPSTOF
	JMP	MLOADK		;TO RETSTORE & END
;
	NOP
;
MLOADR:				;ERROR END
	JMP	MLOADQ
;
;  NOT USED BY PATCH
;
	DB		24H,0FFH,0FFH
	JMPS	MLOADE
;
;  0:SYSTEM RESET
;  INPUT PARAMETER:ABORT CODE	BYTE
;
MSYRST:
	MOV	AL,INPARB	;GET ABORT MODE
	CMP	AL,1
	JZ	MSYRSR		;MEMORY REMAINING ABORT
MSYRSA:
	MOV	BYTE PTR .COMBUF+1,0
MSYRSF:
	CMP	CNUMCB,001H
	JA	MSYRSC		;SOME MEMORY AREA ACTIVE
	CALL	MFRALM		;FREE ALL MEMORY
	JMPS	MSYRSR
;
MSYRSC:				;FREE CURRENT MEMORY
	CALL	FRCRAR
	MOV	BX,PNUMCB	;GET USED MCB BUFFER POINT
	CALL	FREMEM		;FREE LAST MEMORY AREA
	DEC	CNUMCB		;DOWN USED MCB COUNT
MSYRSR:
	MOV	FLINSD,0	;CLEAR BDOS INSIDE MODE
	MOV	BX,VWBOOT
	JMP	BIOSCL		;WARM BOOT
;
;  50:DIRECT BIOS CALL
;
MDBIOS:
	PUSH	DS
	MOV	DS,INDSEG
	MOV	BX,DX
	MOV	AL,[BX]		;GET FUNCTION NUMBER
	MOV	CX,1[BX]	;GET CX
	MOV	DX,3[BX]	;GET DX
	POP	DS
	POP	BX		;CANCEL END PROCESS DIRECT RETURN TO BDOS MAIN
	XOR	BX,BX
	MOV	BL,AL
	ADD	AL,AL
	ADD	BL,AL		;*3
	ADD	BX,VINIT	;GET VECTOR
	JMP	BX		;TO BIOS ROUTINE
;
;  51:SET DMA SEGMNET
;
MSTDMS:
	MOV	DMASEG,DX	;SAVE SEGMENT
	MOV	CX,DX
	CALL	TOP+VSTDMS	;SET IN BIOS
	RET
;
;  52:GET DMA SEGMENT
;
MGTDMS:
	MOV	BX,DMASEG	;GET SEGMENT
	MOV	CURSEG,BX	;SAVE SEGMENT
	MOV	BX,DMAADD	;GET OFFSET
	JMP	WDPRST
;
;  SAVE MCB DATA TO BUFFER
;  INPUT
;  BX:MCB POINT
;
SVMCBD:
	SUB	PNUMCB,5	;DOWN USED MCB BUFFER POINTER
	MOV	DI,PNUMCB
	MOV	AX,[BX]		;GET BASE
	MOV	[DI],AX
	MOV	AX,2[BX]	;GET LENGTH
	MOV	2[DI],AX
	MOV	BYTE PTR 4[DI],0 ;SET AS CURRENT MODE
	ADD	CNTREG,1	;UP COUNT
	RET
;
;  53:GET MAXIMUM AVAILABLE MEMORY
;
MGTMXM:
	CALL	CGBSPR		;CHECK & GET BASE
	JNZ	MGTMXS		;NO SPACE
	CMP	SIZREG,0
	JZ	MALAMR		;NO REGION DATA
	CALL	GMXRTP		;GET MAXIMUM REGION POINT
MGTMXS:
	JNZ	MALAMR		;NO SPACE
	MOV	AX,2[SI]
	CMP	2[BX],AX
	JC	$+5		;ENOUGH LENGTH
	MOV	2[BX],AX	;SHORT SO SET LENGTH
	MOV	AX,[SI]
	MOV	[BX],AX		;SET BASE
	JMPS	MALAMS
;
;  54:GET ABSOLUTE MAXIMUM ADDRESS
;
MGTAMX:
	CALL	CGBSPR		;CHECK & GET BASE
	JNZ	MALAMR		;NO SPACE
MGTAML:				;CHECK LOOP
	ADD	SI,4
	INC	CL
	CMP	CL,SIZREG
	JNC	MALAMR		;ALL OVER
	CALL	CKABAR		;CHECK REQUESTED AREA WITH TABLE
	JNZ	MGTAML		;NOT MATCH TO NEXT
	MOV	AX,2[SI]	;GET MATCHED AREA
	ADD	AX,[SI]		;GET MAXIMUM ADDRESS
	SUB	AX,[BX]
	CMP	2[BX],AX
	JC	MGTAME		;ENOUGH LENGTH
	MOV	2[BX],AX	;SET LENGTH
MGTAME:
	JMPS	MALAMS
;
;  55:ALLOCATE MEMORY AREA
;
MALMEM:
	CALL	CGBSPR		;CHECK & GET BASE
	JNZ	MALAMR		;NO SPACE
	CALL	SRSTRG		;SEARCH SUITABLE REGION
	JNZ	MALAMR		;NO SPACE
	CALL	GSREGN		;GET & SET REGION
	CALL	SVMCBD		;SAVE IN USED MCB BUFFER
	JMPS	MALAMS
;
;  56:ALLOCATE ABSOLUTE MEMORY AREA
;
MALAME:
	CALL	CGBSPR		;CHECK & GET BASE
	JNZ	MALAMR		;NO SPACE
MALAML:				;CHECK LOOP
	ADD	SI,4
	INC	CL
	CMP	CL,SIZREG
	JNC	MALAMR		;ALL OVER
	CALL	CKABAR		;CHECK REQUESTED AREA WITH TABLE
	JNZ	MALAML		;NOT MATCH TO NEXT
	CALL	SRTAAL		;SETUP REGION TABLE
	CALL	SVMCBD		;SAVE IN USED MCB BUFFER
MALAMS:
	MOV	AL,SIZREG
	MOV	4[BX],AL	;SET REGION NUMBER
	XOR	AL,AL
	JMPS	MALAMN		;OK END
;
MALAMR:				;ERROR END
	MOV	AL,0FFH
MALAMN:
	MOV	OTPARB,AL
	RET
;
;  FREE MCB BUFFERED MEMORY AREA
;  INPUT
;  BX:MCB SAVE BUFFER POINT
;
FREMEM:
	MOV	AX,2[BX]
	MOV	SYSMCB+2,AX	;SET LENGTH
	MOV	AX,[BX]
	MOV	SYSMCB,AX	;SET BASE
	MOV	BX,OFFSET SYSMCB
	CALL	CGBSPA		;CHECK AVAIL
	JMPS	MFRMES		;FREE SPECIFIED MEMORY ABORT
;
;  57:FREE MEMORY AREA
;
MFRMEM:
	CALL	CGBSPR
	CMP	BYTE PTR 4[BX],0FFH
	JNZ	MFRMES		;SPECIFIED AREA MODE
	CALL	FRCRAR		;FREE MEMORY AREA ONLY ALLOCATED BY CURRENT PRO
	JMPS	MALAMS
;
MFRMES:				;FREE SPECIFIED MEMORY AREA
	CMP	WORD PTR 2[BX],0
	JZ	MALAMR		;NO LENGTH
	CALL	CKMRTB		;CHECK WITH BASE TABLE
	JNZ	MALAMR		;NOT IN RANGE ERROR
	CALL	CKOVRG		;CHECK OVERLAPPED REGION
	JZ	MALAMR		;OVERLAPPED SO ERROR
	CALL	MDUMCB		;MODIFY USED MCB TABLE
	CMP	AL,0
	JNZ	MALAMR		;ERROR
	CALL	CKLMCB		;CHECK MATCHED MCB TABLE BY LOWER
	JNZ	MFRMEN		;NOT MACTH
	MOV	DI,SI
	MOV	CH,CL		;SAVE PARAMETERS
	CALL	CKUMCB		;CHECK BY UPER
	JZ	MFRMEE		;EACH SIDE MATCH
	MOV	AX,2[BX]	;LOWER SIDE MATCH
	ADD	2[DI],AX	;UP LENGTH
	JMPS	MALAMS
;
MFRMEE:				;EACH SIDE MATCH
	CALL	CHNMCB		;CHAIN TO ONE MCB
	JMPS	MALAMS
;
MFRMEN:				;NOT MATCH BY LOWER
	CALL	CKUMCB		;CHECK BY UPER
	JNZ	MFRMEI		;NOT MATCH
	MOV	AX,[BX]		;MATCH BY LOWER
	MOV	[SI],AX		;CHANGE BASE
	MOV	AX,2[BX]
	ADD	2[SI],AX	;UP LENGTH
MFRMEK:
	JMPS	MALAMS
;
MFRMEI:				;NO MATCH DATA
	CALL	UGMRTP		;MAKE SPACE IN TABLE
	MOV	AX,[BX]
	MOV	[SI],AX		;SET BASE
	MOV	AX,2[BX]
	MOV	2[SI],AX	;SET LENGTH
	JMPS	MFRMEK
;
;  58:FREE ALL MEMORY
;
MFRALM:
	XOR	AX,AX
	MOV	CNTREG,AL	;CLEAR REGION COUNT
	MOV	CNUMCB,AL	;CLEAR USED MCB BUFFER COUNT
	MOV	AX,OFFSET TBUMCB+40
	MOV	PNUMCB,AX	;SET USED MCB BUFFER POINTER TO BOTTOM
	CALL	TOP+VGTMRT	;GET MEMORY REGION TABLE POINT
	MOV	SI,BX
	MOV	CL,[SI]		;GET REGION COUNT
	SHL	CL,1
	SHL	CL,1
	INC	CL		;GET AREA LENGTH
	XOR	CH,CH
	MOV	DI,OFFSET SIZREG
	CLD
	REP	MOVSB		;INITIALIZE REGION TABLE
	RET
;
;  MODIFY USED MCB BUFFER
;  INPUT
;  BX:REQUESTED MCB POINT
;  OUTPUT
;  AL:0 OK
;
MDUMCB:
	MOV	CL,CNTREG
	MOV	CH,000H
	MOV	DI,OFFSET TBUMCB+35 ;FIRST USED MCB
MDUMCL:				;CHECK LOOP
	MOV	AX,[BX]
	CMP	[DI],AX
	JZ	MDUMCS		;SAME BASE
	JNC	MDUMCN		;REQUESTED BASE < TABLE BASE SO TO NEXT
	MOV	DX,[DI]		;REQUESTED BASE > TABLE BASE
	ADD	DX,2[DI]	;GET MAXIMUM SEGMENT OF TABLE
	ADD	AX,2[BX]	;GET MAXIMUM SEGMENT OF REQUESTED
	CMP	AX,DX
	JNZ	MDUMCN		;NOT MATCH
	MOV	AX,2[DI]
	SUB	AX,2[BX]
	MOV	2[DI],AX	;DOWN USED MCB TABLE DATA
	JMPS	MDUMCE
;
MDUMCN:				;CHECK NEXT
	SUB	DI,5
	LOOP	MDUMCL
MDUMCF:				;NOT FOUND END
	MOV	AL,0FFH
	RET
;
MDUMCS:				;SAME BASE
	MOV	AX,2[BX]
	CMP	AX,2[DI]
	JZ	MDUMCV		;SAME LENGTH
	JNC	MDUMCF		;REQUESTED IS TOO LONG
	ADD	AX,[DI]
	MOV	[DI],AX		;UP BASE
	MOV	AX,2[DI]
	SUB	AX,2[BX]
	MOV	2[DI],AX	;DOWN LENGTH
	JMPS	MDUMCE		;OK END
;
MDUMCV:				;EVEN REGION
	MOV	AX,-5[DI]	;COMPRESS USED MCB TABLE
	MOV	[DI],AX
	MOV	AX,-3[DI]
	MOV	2[DI],AX
	MOV	AL,-1[DI]
	MOV	4[DI],AL
	SUB	DI,5		;TO NEXT BLOCK
	LOOP	MDUMCS
	DEC	CNTREG		;DOWN COUNT
	ADD	PNUMCB,5		;UP POINTER
MDUMCE:
	MOV	AL,0
	RET
;
;  FREE MEMORY AREA ONLY ALLOCATED BY CURRENT PROGRAM
;
FRCRAR:
	CMP	CNTREG,0
	JZ	FRCRAE		;NO REGION
	MOV	BX,PNUMCB
	CMP	BYTE PTR 4[BX],0
	JNZ	FRCRAE		;NOT CURRENT
	CALL	FREMEM		;FREE THIS REGION
	JMPS	FRCRAR		;TO NEXT
;
FRCRAE:
	RET
;
;  CHECK & GET BASE PARAMETERS
;  OUTPUT
;  AL:0 OK  -1 NO SPACE
;  SI:REGION TABLE TOP-4
;  CL:BLOCK COUNT-1
;
CGBSPR:
	MOV	CL,5
	CALL	STWFCB		;GET MCB
	MOV	BX,INPARA
CGBSPA:
	MOV	CL,0FFH
	MOV	SI,OFFSET TBLREG-4
	MOV	AL,0FFH
	CMP	CNTREG,8
	JNC	CGBSPE		;NO SPACE IN TABLE
	CMP	WORD PTR 2[BX],0
	JZ	CGBSPE		;LENGTH ZERO
	INC	AL
CGBSPE:
	OR	AL,AL
	RET
;
;  GET & SET REGION
;  INPUT
;  SI:TABLE POINT-4
;  BX:REQUESTED MCB POINT
;  CL:POINT OF TABLE
;
GSREGN:
	PUSH	CX
	MOV	AX,2[SI]
	SUB	AX,2[BX]	;GET LENGTH DIFFERENCE
	JNZ	GSREGS		;SAME DIFFERENCE
	MOV	AX,[SI]		;EVEN
	MOV	[BX],AX		;SAVE BASE
	CALL	CMPRTB		;COMPRESS
	JMPS	GSREGE
;
GSREGS:
	MOV	2[SI],AX	;SAVE LEFT LENGTH
	ADD	AX,[SI]		;GET BOTTOM
	MOV	[BX],AX		;SET AS BASE
GSREGE:
	POP	CX
	RET
;
;  COMPRESS REGION TABLE
;  INPUT
;  CL:TABLE POINT COUNT
;  SI:TABLE POINT
;
CMPRTB:
	PUSH	CX
	PUSH	SI
	PUSH	DI
	MOV	AL,SIZREG
	DEC	AL
	MOV	SIZREG,AL	;DOWN COUNT OF TABLE SIZE
	SUB	AL,CL
	JZ	CMPRTE		;LAST DATA SO END
	MOV	CL,AL
	XOR	CH,CH
	ADD	CX,CX		;GET LEFT LENGTH COUNT
	MOV	DI,SI
	ADD	SI,4
	CLD
	REP	MOVSW		;COMPRESS LEFT DATA
CMPRTE:
	POP	DI
	POP	SI
	POP	CX
	RET
;
;  GET MAXIMUM REGION TABLE POINT
;  INPUT
;  SI:REGION TABLE POINT TOP-4
;  CL:BLOCK POSITION COUNT -1
;  OUTPUT
;  SI:MAXIMUM REGION TABLE POINT
;  CL:MAXIMUM REGION POINT COUNT
;  AL:0 GET  -1 NOT FOUND
;
GMXRTP:
	PUSH	DX
	PUSH	DI
	XOR	DX,DX		;CLEAR LENGTH
	MOV	CH,0FFH
GMXRTL:				;SEARCH LOOP
	ADD	SI,4
	INC	CL
	CMP	CL,SIZREG
	JNC	GMXRTV		;ALL OVER
	MOV	AX,2[SI]	;GET LENGTH
	CMP	AX,DX
	JC	GMXRTL		;TOO SHORT
	MOV	DX,AX		;SET CURRENT MAX
	MOV	CH,CL
	MOV	DI,SI
	JMPS	GMXRTL		;TO NEXT
;
GMXRTV:
	MOV	AL,0FFH
	MOV	SI,DI
	MOV	CL,CH
	INC	CH
	JZ	GMXRTE		;NO SPACE
	INC	AL
GMXRTE:
	OR	AL,AL
	POP	DI
	POP	DX
	RET
;
;  SEARCH SUITABLE REGION
;  INPUT
;  SI:TABLE-4
;  BX:REQUESTED MCB POINT
;  OUTPUT
;  SI:NEAR OR EVEN REGION POINT
;  CL:COUNT OF REGION
;  AL:0 OK
;
SRSTRG:
	PUSH	DX
	PUSH	DI
	MOV	DX,-1
	MOV	CH,0FFH
SRSTRL:				;CHECK LOOP
	ADD	SI,4
	INC	CL
	CMP	CL,SIZREG
	JNC	SRSTRV		;OVER
	MOV	AX,2[SI]
	SUB	AX,2[BX]
	JZ	SRSTRE		;EVEN LENGTH SO GET
	JC	SRSTRL		;TOO SHORT
	CMP	AX,DX
	JNC	SRSTRL		;TOO LONG
	MOV	DX,AX		;SET CURRENT
	MOV	CH,CL
	MOV	DI,SI
	JMPS	SRSTRL		;TO NEXT
;
SRSTRV:
	MOV	AL,0FFH
	MOV	SI,DI
	MOV	CL,CH
	INC	CH
	JZ	SRSTRE		;NOT FOUND
	INC	AL
SRSTRE:
	OR	AL,AL
	POP	DI
	POP	DX
	RET
;
;  GET TOTAL DATA
;  INPUT
;  BX:MCB POINT
;  OUTPUT
;  AX:TOTAL DATA
;
GTTODT:
	MOV	AX,2[BX]
	ADD	AX,[BX]
	RET
;
;  GET EACH MAXIMUM ADDRESS
;  INPUT
;  BP:PARAMETER BUFFER POINT +0 REQUESTED  +2 TABLE DATA
;  BX:REQUESETED MCB POINT
;  SI:TABLE POINT
;
GTEMXA:
	PUSH	BX
	CALL	GTTODT
	MOV	2[BP],AX	;GET REQUESTED MAX
	MOV	BX,SI
	CALL	GTTODT
	MOV	0[BP],AX	;GET TABLE MAX
	POP	BX
	RET
;
;  CHECK ABSOLUTE AREA
;  INPUT
;  BX:REQUESTED MCB POINT
;  SI:TABLE POINT
;  OUTPUT
;  AL:0 OK -1 FAIL
;
CKABAR:
	PUSH	BP
	SUB	SP,4
	MOV	BP,SP		;MAKE WORK
	PUSH	CX
	MOV	CH,0FFH
	CALL	GTEMXA		;GET EACH MAX
	MOV	AX,[BX]
	CMP	AX,[SI]
	JC	CKABAE		;REQUESTED BASE < TABLE BASE
	MOV	AX,0[BP]
	CMP	AX,2[BP]
	JC	CKABAE		;REQUESTED MAX < TABLE MAX
	MOV	CH,0		;OK GET
CKABAE:
	MOV	AL,CH
	POP	CX
	ADD	SP,4
	POP	BP
	OR	AL,AL
	RET
;
;  UP & GET MAXIMUM REGION TABLE POINT
;  OUTPUT
;  SI:LAST REGION DATA POINT
;
UGMRTP:
	MOV	AL,SIZREG
	INC	SIZREG		;UP COUNT
	MOV	AH,4
	MUL	AH
	MOV	SI,AX		;GET BIAS
	LEA	SI,TBLREG[SI]	;GET TABLE POINT
	RET
;
;  SETUP REGION TABLE FOR ABSOLUTE ALLOCATION
;  INPUT
;  SI:TABLE POINT
;  BX:REQUESTED MCB POINT
;  CL:TABLE CUNT
;
SRTAAL:
	PUSH	BP
	SUB	SP,4
	MOV	BP,SP		;MAKE WORK
	PUSH	DX
	PUSH	CX
	CALL	GTEMXA		;GET EACH MAX
	MOV	AX,[BX]
	CMP	AX,[SI]
	JNZ	SRTAAD		;NOT SAME BASE
	MOV	AX,2[BP]
	CMP	AX,0[BP]
	JNZ	SRTAAM		;NOT EVEN
	POP	CX		;EVEN
	PUSH	CX
	CALL	CMPRTB		;COMPRESS CURRENT REGION
	JMPS	SRTAAE
;
SRTAAM:				;LENGTH MISS MATCH
	MOV	[SI],AX		;SET NEW BASE
	MOV	AX,2[BX]
	SUB	2[SI],AX	;SET NEW LENGTH
	JMPS	SRTAAE
;
SRTAAD:				;DIFFERENT BASE
	MOV	AX,0[BP]
	SUB	AX,2[BP]
	JNZ	SRTAAB		;NOT EVEN END
	MOV	AX,[BX]		;EVEN END
	SUB	AX,[SI]
	MOV	2[SI],AX	;DOWN ONLY LENGTH
	JMPS	SRTAAE
;
SRTAAB:				;MISS MATCH BOTH
	MOV	AX,[BX]
	SUB	AX,[SI]
	MOV	2[SI],AX	;SET LOWER SPACE LENGTH
	CALL	UGMRTP		;GET NEW DATA SPACE
	MOV	AX,2[BP]
	MOV	[SI],AX		;SET UPER BASE
	SUB	AX,0[BP]
	NEG	AX
	MOV	2[SI],AX	;SAVE LENGTH
SRTAAE:
	POP	CX
	POP	DX
	ADD	SP,4
	POP	BP
	RET
;
;  CHAIN TO ONE MCB
;  INPUT
;  BX:REQUESTED MCB POINT
;  SI:UPER MATCH TABLE POINT
;  DI:LOWER MATCH TABLE POINT
;
CHNMCB:
	MOV	AX,2[BX]
	ADD	AX,2[SI]
	ADD	2[DI],AX	;SET TOTAL LENGTH
	CALL	CMPRTB		;COMPRESS TABLE
	RET
;
;  CHECK MEMORY REGION TABLE
;  INPUT
;  BX:REQUESTED MCB POINT
;  OUTPUT
;  AL:0 GET
;
CKMRTB:
	PUSH	CX
	PUSH	DX
	PUSH	SI
	PUSH	BX
	CALL	TOP+VGTMRT	;GET MEMORY REGION TABLE BASE
	MOV	CH,[BX]		;GET TABLE SIZE
	MOV	SI,BX
	SUB	SI,3		;TABLE TOP -4
	POP	BX
	MOV	CL,0FFH
CKMRTL:				;CHECK LOOP
	ADD	SI,4
	INC	CL
	CMP	CL,CH
	JNC	CKMRTN		;OVER ALL
	CALL	CKABAR		;CHECK ABSOLUTE AREA
	JNZ	CKMRTL		;NOT MATCH
	MOV	AL,0		;GET
	JMPS	CKMRTE
;
CKMRTN:				;NOT MATCH END
	MOV	AL,0FFH
CKMRTE:
	POP	SI
	POP	DX
	POP	CX
	OR	AL,AL
	RET
;
;  CHECK OVERLAPPED REGION
;  INPUT
;  BX:REQUESTED MCB POINT
;  OUTPUT
;  AL:0 OVERLAPPED
;
CKOVRG:
	PUSH	BP
	SUB	SP,4
	MOV	BP,SP
	PUSH	SI
	PUSH	CX
	MOV	SI,OFFSET TBLREG-4
	MOV	CL,0FFH
CKOVRL:				;CHECK LOOP
	ADD	SI,4
	INC	CL
	CMP	CL,SIZREG
	JNC	CKOVRV		;ALL OVER
	CALL	GTEMXA		;GET EACH MAX
	MOV	AX,[BX]
	CMP	AX,[SI]
	JNC	CKOVRR		;REQUESTED BASE > TABLE BASE
	MOV	AX,2[BP]
	CMP	AX,[SI]
	JA	CKOVRF		;REQUESTED MAX > TABLE BASE   SO OVERLAP
	JMPS	CKOVRL		;CHECK NEXT
;
CKOVRR:				;REQUESETD BASE > TABLE BASE
	CMP	AX,0[BP]
	JNC	CKOVRL		;REQUESTED BASE > TABLE MAX
CKOVRF:				;GET OVERLAPPED REGION
	MOV	AL,0
	JMPS	CKOVRE
;
CKOVRV:
	MOV	AL,0FFH
CKOVRE:
	POP	CX
	POP	SI
	ADD	SP,4
	POP	BP
	OR	AL,AL
	RET
;
;  CHECK MATCHED MCB TABLE BY LOWER
;  INPUT
;  BX:REQUESTED MCB POINT
;  OUTPUT
;  SI:MATCHED TABLE POINT
;  CL:MATCHED TABLE COUNT
;  AL:0 GET
;
CKLMCB:
	PUSH	BP
	SUB	SP,4
	MOV	BP,SP
	MOV	SI,OFFSET TBLREG-4
	MOV	CL,0FFH
CKLMCL:				;CHECK LOOP
	ADD	SI,4
	INC	CL
	CMP	CL,SIZREG
	JNC	CKLMCV		;ALL OVER
	CALL	GTEMXA		;GET EACH MAX
	MOV	AX,[BX]
	SUB	AX,0[BP]
	JNZ	CKLMCL		;NOT MATCH
	JMPS	CKLMCE		;MATCH
;
CKLMCV:
	MOV	AL,0FFH
CKLMCE:
	ADD	SP,4
	POP	BP
	OR	AL,AL
	RET
;
;  CHECK MATCHED TABLE BY UPER
;  INPUT
;  BX:REQUESTED MCB POINT
;  OUTPUT
;  SI:MATCHED TABLE POINT
;  CL:MATCHED TABLE COUNT
;  AL:0 GET
;
CKUMCB:
	PUSH	BP
	SUB	SP,4
	MOV	BP,SP
	MOV	SI,OFFSET TBLREG-4
	MOV	CL,0FFH
CKUMCL:				;CHECK LOOP
	ADD	SI,4
	INC	CL
	CMP	CL,SIZREG
	JNC	CKUMCV		;OVER
	CALL	GTEMXA		;GET MAX
	MOV	AX,2[BP]
	SUB	AX,[SI]
	JNZ	CKUMCL		;NOT MATCH
	JMPS	CKUMCE		;MATCHED
;
CKUMCV:
	MOV	AL,0FFH
CKUMCE:
	ADD	SP,4
	POP	BP
	OR	AL,AL
	RET
;
;  CONSOLE I/O ROUTINES
;
;  CONSOLE INPUT WITH STORED DATA CHECKING
;  OUTPUT
;  AL:DATA
;
CONINC:
	MOV	BX,OFFSET BFCONC
	MOV	AL,[BX]		;GET BUFFERED DATA
	MOV	BYTE PTR [BX],0	;CLEAR DATA
	OR	AL,AL
	JNZ	CONCHE		;GET SOME CODE
	JMP	BCONIN		;GET INPUT BY BIOS CONSOLE INPUT
;
;  CONSOLE INPUT BODDY
;  OUTPUT
;  AL:CODE
;
CONINP:
	CALL	CONINC		;GET CONSOLE INPUT CODE
	CALL	CONCHK		;CHECK CONTROL CODE
	JC	CONCHE		;CONTROL CODE SO NO ECHO
	PUSH	AX
	MOV	CL,AL
	CALL	CONOUT		;ECHO BACK
	POP	AX
	RET
;
;  CHECK CONTROL CODE
;  INPUT
;  AL:CODE
;  OUTPUT
;  CF:OFF VISIBLE OR VALID CONTROL
;
CONCHK:
	CMP	AL,CR
	JZ	CONCHE
	CMP	AL,LF
	JZ	CONCHE
	CMP	AL,HT
	JZ	CONCHE
	CMP	AL,BS
	JZ	CONCHE
	CMP	AL,' '
CONCHE:
	RET
;
;  GET CONSOLE STATUS
;  OUTPUT
;  AL:STATUS  0 NOT READY  1 READY
;
CONSTS:
	MOV	AL,BFCONC
	OR	AL,AL
	JNZ	CONSTD		;EXIST SOME CODE SO READY
	CALL	BCONST		;CHECK STATUS
	AND	AL,1
	JZ	CONCHE		;NO READY
	CALL	BCONIN		;READY SO GET CODE
	CMP	AL,'S'-40H
	JNZ	CONSTG		;NORMAL CODE
	CALL	BCONIN		;FREEZE MODE WAIT NEXT INPUT
	CMP	AL,'C'-40H
	JZ	CONSTA		;ABORT
	XOR	AL,AL
	RET			;NOT READY END
;
CONSTA:				;ABORT
	MOV	PCARIG,0	;CLEAR CARRIAGE POSITION
	CMP	CNUMCB,0
	JNZ	CONSTM		;SOME MEMORY USED
	CALL	MRSDSY		;RESET SYSTEM DISK
	MOV	AL,OTPARB	;GET SUBMIT FILE MODE
	MOV	.MDSUBE,AL	;SET SUBMIT MODE
	JMPS	CONSTR
;
CONSTM:				;SOME MEMORY USED
	TEST	MODABT,0FFH	;		NOT SETUP ?????
	JZ	CONSTE
	CMP	CNUMCB,1
	JNZ	CONSTE		;NOT SIMPLE SO RESET ALL
CONSTR:
	MOV	BYTE PTR .COMBUF+1,0 ;CLEAR COMMAND COUNT
	JMP	MSYRSR		;RESET SYSTEM WITH MEMORY REMAINDING
;
CONSTE:				;RESET ALL SYSTEM
	JMP	MSYRSA
;
CONSTG:				;GET CODE
	MOV	BFCONC,AL	;SAVE CODE
CONSTD:
	MOV	AL,1		;READY END
	RET
;
;  CONSOLE OUT DIRECT
;  INPUT
;  CL:CODE
;
CONOTS:
	MOV	AL,ECHKIL
	OR	AL,AL
	JNZ	CONOTT		;NO ECHO MODE
	PUSH	CX
	CALL	CONSTS		;CHECK CONSOLE IN
	POP	CX
	PUSH	CX
	CALL	BCONOT		;OUT BY BIOS ROUTINE
	POP	CX
	PUSH	CX
	CMP	LSTTGL,0	;LIST OUT TOGGLE
	JZ	$+5		;NO OUT
	CALL	BLIST		;WITH LIST OUT
	POP	CX
CONOTT:
	MOV	AL,CL
	MOV	BX,OFFSET PCARIG
	CMP	AL,07FH
	JZ	CONOTE		;DELETE CODE SO NOT UP
	INC	BYTE PTR [BX]	;UP CARRIAGE POSITION
	CMP	AL,' '
	JNC	CONOTE		;OK VISIBLE CODE
	DEC	BYTE PTR [BX]	;DOWN AS CONTROL CODE
	MOV	AL,[BX]
	OR	AL,AL
	JZ	CONOTE		;TOP SO OK
	MOV	AL,CL
	CMP	AL,BS
	JNZ	CONOTL		;NOT BACK SPACE
	DEC	BYTE PTR [BX]	;DOWN AS BACK SPACE
CONOTE:
	RET
;
CONOTL:
	CMP	AL,LF
	JNZ	CONOTE
	MOV	BYTE PTR [BX],0	;LINE FEED SO TOP
	RET
;
;  CONSOLE OUT WITH CONTROL CODE VISIBLE
;  INPUT
;  CL:CODE
;
CONOTC:
	MOV	AL,CL
	CALL	CONCHK		;CHECK CONTROL CODE
	JNC	CONOUT		;VISIBLE OR VALID CONTROL CODE
	PUSH	AX		;UNVISIBLE
	MOV	CL,'^'
	CALL	CONOTS		;OUT CONTROL CODE MARK
	POP	CX
	OR	CL,040H		;TO VISIBLE CODE
;
;  CONSOLE OUT WITH TAB EXPANSION
;  INPUT
;  CL:CODE
;
CONOUT:
	CMP	CL,HT
	JNZ	CONOTS		;OTHER CODE
CONOUL:				;TAB EXPAND LOOP
	MOV	CL,' '
	CALL	CONOTS		;OUT SPACE
	MOV	AL,PCARIG
	AND	AL,07H
	JNZ	CONOUL		;NOT TAB POINT
CONOUE:
	RET
;
;  BACK SPACE WITH ERASE
;
BACKS:
	CALL	BACK
	MOV	CL,' '
	CALL	BCONOT		;ERASE
BACK:
	MOV	CL,BS
	JMP	BCONOT
;
;  TO NEW LINE WITH END MARK '#'  FOR ^U OR SO
;
NCRLF:
	MOV	CL,'#'
	CALL	CONOTS
	CALL	CRLF
NCRLFL:				;TO CURRENT PROMPT POSITION
	MOV	AL,PCARIG
	CMP	AL,PPROMP
	JNC	CONOUE
	MOV	CL,' '
	CALL	CONOTS
	JMPS	NCRLFL
;
;  CARRIAGE RETURN & LINE FEED
;
CRLF:
	MOV	CL,CR
	CALL	CONOTS
	MOV	CL,LF
	JMP	CONOTS
;
;  OUT STRING  END BY '$'
;  INPUT
;  CX:STRING POINTER
;
BUFPRN:
	MOV	SI,CX
	LODSB			;GET CODE
	CMP	AL,'$'
	JZ	CONOUE		;END
	INC	CX		;ACTIVE CODE
	PUSH	CX
	MOV	CL,AL
	PUSH	DS
	PUSH	SS
	POP	DS
	CALL	CONOUT		;OUT CODE
	POP	DS
	POP	CX
	JMPS	BUFPRN		;TO NEXT CODE
;
;  READ CONSOLE BUFFER
;  INPUT
;  ES:BUFFER SEGMENT
;
RDCNBF:
	MOV	AL,PCARIG
	MOV	PPROMP,AL	;SET PROMPT POSITION
	MOV	BX,INPARA	;GET BUFFER OFFSET
	MOV	CL,ES:[BX]	;GET MAX LENGTH
	INC	BX
	PUSH	BX		;SAVE LENGTH COUNTER ADDRESS
	MOV	CH,0		;CLEAR COUNT
RDCNBL:				;ONE CHARACTER LOOP
	PUSH	CX
	PUSH	BX
RDCNBD:
	CALL	CONINC		;GET CODE
	POP	BX
	POP	CX
	CMP	AL,CR
	JNZ	$+5		;NOT END
RDCNBQ:				;END OF INPUT
	JMP	RDCNBE
;
	CMP	AL,LF
	JZ	RDCNBQ		;END CODE
	CMP	AL,BS
	JNZ	RDCNBK
	OR	CH,CH		;BACK SPACE
	JZ	RDCNBL		;TOP SO DO NOTHING
	DEC	CH		;DOWN COUNT
	MOV	AL,PCARIG
	MOV	ECHKIL,AL	;SAVE CURRENT POINT
	JMPS	RDCNBI
;
RDCNBK:
	CMP	AL,07FH
	JNZ	RDCNBA
	OR	CH,CH		;DELETE
	JZ	RDCNBL		;TOP SO DO NOTHING
	MOV	AL,ES:[BX]	;GET LAST CODE
	DEC	CH
	DEC	BX
	JMPS	RDCNBS		;ECHO LAST CODE
;
RDCNBA:
	CMP	AL,'E'-40H
	JNZ	RDCNBP
	PUSH	CX		;CHANGE LINE
	PUSH	BX
	CALL	CRLF
	MOV	PPROMP,0
RDCNBB:
	JMPS	RDCNBD
;
RDCNBP:
	CMP	AL,'P'-40H
	JNZ	RDCNBC
	NOT	LSTTGL		;LIST ECHO MODE TOGGLE
	JMPS	RDCNBL
;
RDCNBC:
	CMP	AL,'X'-40H
	JNZ	RDCNBY
	POP	BX		;ERASE LINE
RDCNBX:
	MOV	AL,PPROMP	;GET PROMPT POSITION
	MOV	BX,OFFSET PCARIG
	NOP
	CMP	AL,[BX]
	JNC	RDCNBF		;REACH TO TOP
	NOP
	DEC	BYTE PTR [BX]	;DOWN POSITION
	CALL	BACKS		;ERASE & BACK
	JMPS	RDCNBX		;TO NEXT
;
RDCNBY:
	CMP	AL,'U'-40H
	JNZ	RDCNBR
	CALL	NCRLF		;CANCEL CARRIAGE LINE
	POP	BX
	JMP	RDCNBF
;
RDCNBR:
	CMP	AL,'R'-40H
	JNZ	RDCNBN
RDCNBI:				;CANCEL LINE & OUT LEFT CODE
	PUSH	CX
	CALL	NCRLF
	POP	CX
	POP	BX
	PUSH	BX
	PUSH	CX
RDCNBG:				;OUT LEFT CODE
	OR	CH,CH
	JZ	RDCNBH		;END OF OUT
	INC	BX
	MOV	CL,ES:[BX]	;GET CODE
	DEC	CH
	PUSH	CX
	PUSH	BX
	CALL	CONOTC		;OUT CODE
	POP	BX
	POP	CX
	JMPS	RDCNBG		;TO NEXT
;
RDCNBH:
	PUSH	BX
	MOV	AL,ECHKIL	;GET ECHO MODE
	OR	AL,AL
	JZ	RDCNBJ		;NORMAL
	SUB	AL,PCARIG	;KILL MODE
	MOV	ECHKIL,AL	;GET BACK COUNT
RDCNBO:				;BACK TO LAST POINT
	CALL	BACKS
	DEC	ECHKIL
	JNZ	RDCNBO
RDCNBJ:
	JMPS	RDCNBB
;
RDCNBN:				;NORMAL CODE
	INC	BX
	MOV	ES:[BX],AL	;SET CODE TO BUFFER
	INC	CH		;UP COUNT
RDCNBS:
	PUSH	CX
	PUSH	BX
	MOV	CL,AL
	CALL	CONOTC		;ECHO BACK
	POP	BX
	POP	CX
	MOV	AL,ES:[BX]
	CMP	AL,'C'-40H
	MOV	AL,CH
	JNZ	RDCNBM		;NOT ABRT
	CMP	AL,1
	JNZ	RDCNBM		;NOT TOP
	MOV	AX,DS		;ABORT
	MOV	ES,AX		;RESTORE SEGMENT
	JMP	CONSTA		;TO ABORT ROUTINE
;
RDCNBM:
	CMP	AL,CL
	JNC	RDCNBE		;END OF BUFFER LENGTH
	JMP	RDCNBL		;TO NEXT
;
RDCNBE:				;END OF INPUT
	POP	BX
	MOV	ES:[BX],CH	;SET COUNT
	MOV	CL,CR
	MOV	AX,DS
	MOV	ES,AX
	JMP	CONOTS		;ECHO LINE END
;
;  1:CONSOLE INPUT
;
MCONIN:
	CALL	CONINP
	JMPS	BTPRST
;
;  3:READER INPUT
;
MREDER:
	CALL	TOP+VREADR
	JMPS	BTPRST
;
;  6:DIRECT CONSOLE I/O
;  INPUT
;  CL:-1 INPUT/STATUS  -2 STATUS   OTHER OUTPUT
;
MDCNIO:
	MOV	AL,CL
	INC	AL
	JZ	MDCNIS		;INPUT/STATUS
	INC	AL
	JNZ	BCONOT		;OUTPUT
	CALL	BCONST		;STATUS
	JMPS	BTPRST
;
MDCNIS:				;INPUT/STATUS
	CALL	BCONST
	OR	AL,AL
	JNZ	MDCNIG		;GET SOME CODE
	JMP	ENDPRN		;NOT READY
;
MDCNIG:				;GET SOME CODE
	CALL	BCONIN		;GET CODE
	JMPS	BTPRST
;
;  7:GET I/O BYTE
;
MGTIOB:
	CALL	TOP+VGTIOB
	JMPS	BTPRST
;
;  8:SET I/O BYTE
;
MSTIOB:
	MOV	CX,DX
	CALL	TOP+VSTIOB
	RET
;
;  9:CONSOLE OUT STRING  END BY '$'
;
MBUFPR:
	MOV	CX,DX
	PUSH	DS
	MOV	DS,INDSEG
	CALL	BUFPRN
	POP	DS
	RET
;
;  10:READ CONSOLE BUFFER
;
MRDCBF:
	MOV	ES,INDSEG
	JMP	RDCNBF
;
;  11:GET CONSOLE STATUS
;
MCONST:
	CALL	CONSTS
;
;  SET BYTE RESULT & END
;
BTPRST:
	MOV	OTPARB,AL
NOPROC:
	RET
;
;  NO DATA EXIST END IN DISK OPERATION
;
NODTEX:
	MOV	AL,1
	JMPS	BTPRST
;
;  BIOS ROUTINE CALL
;
;  5:LIST OUT
;
BLIST:
	MOV	BX,VLIST
	JMPS	BIOSCL
;
;  CONSOLE INPUT
;
BCONIN:
	MOV	BX,VCONIN
	JMPS	BIOSCL
;
;  CONSOLE STATUS
;
BCONST:
	MOV	BX,VCONST
	JMPS	BIOSCL
;
;  CONSOLE OUTPUT
;
BCONOT:
	MOV	BX,VCONOT
;
;  BIOS CALL
;  INPUT
;  BX:ROUTINE ADDRESS
;
BIOSCL:
	CALLF	DWORD PTR JPBIOS
	RET
;
;
DBIOS:
	CALL	BX		;TO EACH ROUTINE
	RETF
;
;  DISK I/O ROUTINES
;
;  SELECT ERROR
;
DSEROR:
	MOV	BX,OFFSET VSELCT
ERROR:				;ERROR COMMON ROUTINE
	JMP	WORD PTR [BX]
;
;  COPY DATA
;  INPUT
;  DX:SOURCE POINTER
;  BX:DESTINATION POINTER
;  CL:LENGTH
;
COPY:
	PUSH	CX
	MOV	CH,0
	MOV	SI,DX
	MOV	DI,BX
	CLD
	REP	MOVSB		;COPY DATA
	POP	CX
	RET
;
;  SELECCT & GET DISK PARAMETER
;  OUTPUT
;  ZF:ON NO UNIT
;
GDPTBL:
	MOV	CL,CURDSK
	CALL	TOP+VSLDSK	;SELECT DISK BY BIOS ROUTINE
	CMP	BX,0
	JZ	GDPTBE		;NOT ACTIVE DISK END
	MOV	DX,[BX]		;GET TRANSLATION TABLE POINT
	ADD	BX,2
	MOV	PNDRCK,BX	;DIRECTORY CHECK LEVEL WORK POINT
	ADD	BX,2
	MOV	PNTRAK,BX	;TRACK NUMBER WORK POINT
	ADD	BX,2
	MOV	PNSCTR,BX	;TOTAL SECTOR WORK POINT
	ADD	BX,2
	XCHG	BX,DX
	MOV	PNXTBL,BX	;SAVE TRANSLATION TABLE POINT
	MOV	BX,DIRBUF
	MOV	LSDRBF,BX	;SAVE LAST DIRECTORY BUFFER POINT  NOT USED ??
	MOV	BX,OFFSET DIRBUF
	MOV	CL,8
	CALL	COPY		;GET DISK PARAMETER HEADER DATA
	MOV	DX,PNTDPB	;DISK PARAMETER BLOCK POINT
	MOV	BX,OFFSET SPT
	MOV	CL,15
	CALL	COPY		;GET DISK PARAMETER BLOCK DATA
	MOV	AL,BYTE PTR DSM+1
	MOV	BX,OFFSET DSMMOD
	MOV	BYTE PTR [BX],0FFH
	OR	AL,AL
	JZ	$+5		;DSM <= 255	ONE BYTE MODE
	MOV	BYTE PTR [BX],0	;DSM > 256	TWO BYTE MODE
	MOV	AL,0FFH
	OR	AL,AL
GDPTBE:
	RET
;
;  TO HOME FOR DIECTORY READ
;
TOHOME:
	CALL	TOP+VHOME
	XOR	AX,AX
	MOV	BX,PNTRAK
	MOV	[BX],AX		;CLEAR CURRENT TRACK WORK
	RET
;
;  ONE SECTOR READ
;
DREAD:
	MOV	DX,TGSECT	;			?????
	CALL	TOP+VDREAD
	JMPS	DWRITN
;
;  ONE SECTOR WRITE
;
DWRITE:
	MOV	CL,MDWRIT	;GET WRITE MODE
DWRITS:
	CALL	TOP+VDWRIT
DWRITN:
	OR	AL,AL
	JZ	GDPTBE		;OK END
	MOV	BX,OFFSET VBADSC ;DISK READ / WRITE ERROR
	JMP	ERROR
;
;  SET DIRECTORY TRACK & SECTOR
;
STDIRT:
	MOV	BX,DIRCNT
	MOV	CL,2
	SHR	BX,CL		;GET SECTOR COUNT
	MOV	TGSECT,BX	;SET TARGET SECTOR
	MOV	DIRSCT,BX	;SAVE SECTOR
;
;  SET PHYSICAL TRACK & SECTOR
;
TRSSET:
	MOV	AX,TGSECT
	MOV	DX,0
	DIV	SPT		;GET TRACK & SECTOR
	PUSH	DX		;SAVE SECTOR
	MOV	CX,AX
	MOV	SI,PNTRAK
	MOV	[SI],CX		;SET TARGET TRACK
	ADD	CX,TRKOFF	;GET PHYSICAL TRACK
	CALL	TOP+VSTTRK	;SET TRACK
	POP	CX
	MOV	DX,PNXTBL	;TRANSLATION TABLE POINT
	CALL	TOP+VSCTRN	;TO PHYSICAL SECTOR
	MOV	CX,BX
	JMP	TOP+VSTSEC	;SET PHYSICAL SECTOR
;
;  GET BIAS IN DIRECTORY
;  OUTPUT
;  AL:BIAS
;
GBSDIR:
	MOV	BX,OFFSET BSH
	MOV	CL,[BX]		;GET BLOCK SHIFT FACTOR
	MOV	AL,CURCNT	;GET CURRENT COUNT
	SHR	AL,CL
	MOV	CH,AL		;GET BIAS BY CURRENT COUNT
	MOV	CL,7
	SUB	CL,[BX]		;GET SHIFT FACTOR OF EXTENT
	MOV	AL,EXTENT
	SHL	AL,CL		;GET BIAS BY EXTENT
	ADD	AL,CH		;GET TOTAL BIAS
	RET
;
;  GET BLOCK NUMBER
;  INPUT
;  CX:BIAS IN DIRECTORY
;  OUTPUT
;  BX:BLOCK NUMBER
;
GTBLNM:
	MOV	BX,INPARA
	ADD	BX,16		;GET DIRECTORY MAP TOP
	ADD	BX,CX		;GET MAP POINT ( IF ONE BYTE )
	CMP	DSMMOD,0	;CHECK MAP MODE
	JZ	GTBLNS		;TWO BYTE MODE
	MOV	BL,[BX]		;ONE BYTE MODE
	MOV	BH,0		;GET BLOCK NUMBER
	RET
;
GTBLNS:				;TWO BYTE MODE
	ADD	BX,CX		;GET MAP POINT ( TWO BYTE MODE )
	MOV	BX,[BX]		;GET BLOCK NUMBER
	RET
;
;  GET TARGET BLOCK
;
GTBLCK:
	CALL	GBSDIR		;GET BIAS IN DIRECTORY
	MOV	CL,AL
	MOV	CH,0
	CALL	GTBLNM		;GET BLOCK NUMBER
	MOV	TGSECT,BX	;SET TO TARGET WORK
	RET
;
;  CHECK BLOCK EMPTY
;  OUTPUT
;  ZF:ON EMPTY
;
CHKBLK:
	MOV	BX,TGSECT
	OR	BX,BX
	RET
;
;  BLOCK NUMBER TO LOGICAL SECTOR
;
BLTSCT:
	MOV	CL,BSH
	MOV	BX,TGSECT
	SHL	BX,CL		;GET BLOCK TOP SECTOR
	MOV	BTSECT,BX	;SAVE BLOCK TOP
	MOV	AL,CURCNT	;GET CURRENT COUNT
	AND	AL,BLM		;GET BIAS IN BLOCK
	OR	BL,AL		;GET TOTAL SECTOR
	MOV	TGSECT,BX	;SAVE TOTAL LOGICAL SECTOR
	RET
;
;  GET EXTENT POINT & DATA
;  OUTPUT
;  AL:EXTENT
;  BX:DATA POINT
;
EXTPNT:
	MOV	BX,INPARA
	ADD	BX,12
	MOV	AL,[BX]		;GET EXTENT
	RET
;
;  GET RECORD COUNT POINT
;  OUTPUT
;  BX:CURRENT RECORD COUNT POINT
;  DX:RECORD COUNT POINT
;
GTRCPT:
	MOV	DX,15
	ADD	DX,INPARA	;RECRD COUNT POINT
	MOV	BX,17
	ADD	BX,DX		;CURRENT RECORD COUNT POINT
	RET
;
;  GET RECORD COUNT DATA
;
GTRCNT:
	CALL	GTRCPT		;GET RECORD COUNT POINT
	MOV	AL,[BX]		;GET CURRENT RECORD
	MOV	CURCNT,AL	;SAVE
	XCHG	BX,DX
	MOV	AL,[BX]		;GET RECORD COUNT
	MOV	RECUNT,AL	;SAVE
	CALL	EXTPNT		;GET EXTENT POINT
	MOV	AL,EXM		;GET EXTENT MASK
	AND	AL,[BX]		;GET MASKED EXTENT
	MOV	EXTENT,AL
	RET
;
;  UP & SET RECORD COUNT TO FCB
;
USRCNT:
	CALL	GTRCPT		;GET RECORD COUNT POINT
	MOV	AL,RUPCNT	;GET COUNT UP COUNT
	CMP	AL,2
	JNZ	$+4		;0 RANDOM  OR 1 SEQUENTIAL
	XOR	AL,AL		;RANDOM WRITE WITH ZERO FILL  SO NOT UP
	ADD	AL,CURCNT	;UP CURRENT RECORD COUNT
	MOV	[BX],AL		;SAVE CURRENT RECORD
	XCHG	BX,DX
	MOV	AL,RECUNT
	MOV	[BX],AL		;SET RECORD COUNT
	RET
;
;  GET HASH TOTAL FOR DIRECTORY CHECK SUM
;  OUTPUT
;  AL:HASH TOTAL
;
HASH:
	MOV	CX,128		;SECTOR LENGTH
	MOV	BX,DIRBUF
	XOR	AL,AL
HASHL:				;TOTAL LOOP
	ADD	AL,[BX]
	INC	BX
	LOOP	HASHL
	RET
;
;  SET CURRENT DISK BIT
;  INPUT
;  CX:BASE VECTOR
;  OUTPUT
;  BX:NEW VECTOR
;
STDKVC:
	PUSH	CX
	MOV	CL,CURDSK
	MOV	BX,1
	SHL	BX,CL		;GET CURRENT DISK BIT
	POP	CX
	OR	BX,CX
	RET
;
;  CHECK R/O DISK VECTOR
;  OUTPUT
;  ZF:ON R/W DISK	OFF R/O DISK
;
CHKROV:
	MOV	AX,RODSKV	;GET R/O DISK VECTOR
	MOV	CL,CURDSK
	SHR	AX,CL
	AND	AL,1		;GET MODE
	RET
;
;  28:WRITE PROTECT DISK
;
MWPDSK:
	MOV	CX,RODSKV	;GET R/O DISK VECTOR
	CALL	STDKVC		;SET CURRENT DISK BIT
	MOV	RODSKV,BX	;SAVE NEW R/O DISK VECTOR
	MOV	DX,DRM
	INC	DX		;GET DIRECTORY MAXIMUM
	MOV	BX,PNDRCK
	MOV	[BX],DX		;DIRECTORY CHECK LEVEL TO FULL
	RET
;
;  CHECK WRITE PROTECT FILE
;
CHKROF:
	CALL	GTDRPT		;GET FCB POINT IN DIRECTORY
CHKROL:
	MOV	DX,9
	ADD	BX,DX
	MOV	AL,[BX]		;GET R/O BYTE
	RCL	AL,1
	JNC	GTDRPE		;R/W FILE
	MOV	BX,OFFSET VROFIL ;R/O FILE
	JMPS	CHKROE		;ERROR
;
;  CHECK WRITE PROTECT DISK
;
CHKROD:
	CALL	CHKROV		;CHECK R/O DISK
	JZ	GTDRPE		;R/W DISK
	MOV	BX,OFFSET VRODSK ;R/O DISK ERROR
CHKROE:				;ERROR END
	JMP	ERROR
;
;  GET DIRECTORY POINT
;
GTDRPT:
	MOV	BX,DIRBUF
	MOV	AL,BISDIR	;GET BIAS IN DIRECTORY
	MOV	AH,0
	ADD	BX,AX		;GET POINT
GTDRPE:
	RET
;
;  GET FILE MODE
;  OUTPUT
;  BX:FILE MODE DATA POINT
;  AL:B7:WRITE OPERATION MODE	READ ONLY
;     B6:RANDOM READ/WRITE ERROR
;     B0-4:EXTENTION OF EXTENT
;
FMDPNT:
	MOV	BX,INPARA
	ADD	BX,14
	MOV	AL,[BX]
	RET
;
;  CLEAR FILE MODE
;
FMDCLR:
	CALL	FMDPNT
	MOV	BYTE PTR [BX],0
	RET
;
;  INITIALIZE FILE MODIFY MODE
;
FMDRON:
	CALL	FMDPNT
	OR	AL,80H
	MOV	[BX],AL
	RET
;
;  CHECK DIRECTORY LEVEL
;  OUTPUT
;  DX:CURRENT DIREORY COUNT
;  BX:DIRETCORY DATA POINT
;  CF:ON UNDER
;
CHKDLV:
	MOV	DX,DIRCNT
	MOV	BX,PNDRCK
	CMP	DX,[BX]
CHKDLE:
	RET
;
;  CHECK & SET DIRECTORY LEVEL
;
STDLVL:
	CALL	CHKDLV
	JC	CHKDLE		;UNDER
	INC	DX		;UP DIRECTORY COUNT
	MOV	[BX],DX		;SAVE NEW MAXIMUM LEVEL
	RET
;
;  INVERTED SUBTRACT
;  BX=DX-BX
;
INVSUB:
	PUSH	DX
	SUB	DX,BX
	MOV	BX,DX
	POP	DX
	RET
;
;  SET OR CHECK DIRECTORY HASH (CHECK SUM)
;  INPUT
;  CL:0 CHECK  -1 SET
;
HASHST:
	MOV	CL,-1		;SET CHECK SUM
HASHSC:
	MOV	DX,DIRSCT	;GET SECTOR OF CURRENT DIRECTORY
	MOV	BX,CHKSIZ
	CALL	INVSUB
	JNC	CHKDLE		;OVER OF CHECKED DIRECTORY SIZE
	PUSH	CX
	CALL	HASH		;GET HASH TOTAL OF DIRECTORY DATA
	MOV	BX,DIRSCT
	ADD	BX,PNCHSM
	POP	CX
	INC	CL
	JZ	HASHSS		;SET MODE
	CMP	AL,[BX]		;CHECK MODE
	JZ	HASHSE		;OK END
	CALL	CHKDLV		;MISS MATCH
	JNC	HASHSE		;CHECKED DIRECTORY LEVEL IS LOWER
	CALL	MWPDSK		;ERROR MAYBE CHANGED MEDIA  SO TO R/O DISK
	RET
;
HASHSS:				;SET MODE
	MOV	[BX],AL		;SET SUM DATA
HASHSE:				;OK END
	RET
;
;  WRITE DIRECTORY
;
DRWRIT:
	CALL	HASHST		;SET NEW CHECK SUM DATA
	CALL	STDDMA		;DMA ADDRESS TO DIRECTORY BUFFER
	MOV	CL,1
	CALL	DWRITS		;WRITE AS DIRECTORY
	JMPS	STBDMA		;RESTORE DMA ADDRESS
;
;  READ DIRECTORY
;
DRREAD:
	CALL	STDDMA		;DMA ADDRESS TO DIRECTORY BUFFER
	CALL	DREAD		;READ DIRECTORY SECTOR
;
;  SET BASE DMA ADDRESS
;
STBDMA:
	MOV	CX,DMASEG
	CALL	TOP+VSTDMS	;SET SEGMENT
	MOV	BX,OFFSET DMAADD
	JMPS	STDDMS		;SET OFFSET
;
;  SET DMA ADDRESS TO DIRECTORY BUFFER
;
STDDMA:
	MOV	CX,DS
	CALL	TOP+VSTDMS	;SET SEGMENT
	MOV	BX,OFFSET DIRBUF
STDDMS:				;SET OFFSET
	MOV	CX,[BX]
	JMP	TOP+VSTDMA
;
;  COPY DIRECTORY DATA TO USER DMA AREA
;
DRCOPY:
	MOV	DX,DIRBUF
	MOV	BX,DMAADD
	MOV	CL,128		;SECTOR LENGTH
	PUSH	ES
	MOV	ES,DMASEG
	CALL	COPY		;COPY DATA
	POP	ES
	RET
;
;  CHECK DIRECTORY END
;  OUTPUT
;  ZF:ON END
;
CKDREN:
	MOV	BX,OFFSET DIRCNT
	MOV	AL,[BX]
	INC	BX
	CMP	AL,[BX]
	JNZ	CKDREE		;NOT END
	INC	AL		;0FFFFH IS END CODE
CKDREE:
	RET
;
;  INITIALIZE DIRECTORY COUNT
;
INDRCN:
	MOV	BX,-1
	MOV	DIRCNT,BX
	RET
;
;  GET NEXT DIRECTORY SECTOR
;  INPUT
;  CL:0 CHECK  -1 SET  DIRECTORY CHECK SUM
;
GTNDSC:
	MOV	DX,DRM		;GET MAX OF DIRECTORY
	MOV	BX,DIRCNT
	INC	BX
	MOV	DIRCNT,BX	;UP DIRECTORY COUNT
	CALL	INVSUB		;CHECK OVER
	JNC	GTNDSS		;IN RANGE
	JMPS	INDRCN		;OVER OF DIRECTORY
;
GTNDSS:
	MOV	AL,BYTE PTR DIRCNT
	AND	AL,3		;GET BIAS IN SECTOR
	PUSH	CX
	MOV	CL,5
	SHL	AL,CL		;*32 GET BIAS BY BYTE
	POP	CX
	MOV	BISDIR,AL	;SAVE BIAS
	OR	AL,AL
	JNZ	GTDMBE		;NOT TOP SO ALREADY DATA READ
	PUSH	CX		;TOP SO READ NEW SECTOR
	CALL	STDIRT		;SET DIRECTORY TRACK & SECTOR
	CALL	DRREAD		;READ DIRECTORY DATA
	POP	CX
	JMP	HASHSC		;CHECK OR SET DIRECTORY CHECK SUM
;
;  GET DIRECTORY ALLOCATION MAP BIT
;  INPUT
;  CX:TARGET BLOCK NUMBER
;  OUTPUT
;  AL:BIT 0 IS TARGET BIT
;  DH:ROTATE COUN IN BYTE
;  BX:MAP POINT
;
GTDMBT:
	MOV	DX,CX
	AND	CL,7		;GET BIAS IN BYTE
	INC	CL
	MOV	CH,CL
	MOV	CL,3
	SHR	DX,CL		;GET BIAS OF BYTE
	MOV	BX,PNALMP
	ADD	BX,DX		;GET MAP POINT
	MOV	AL,[BX]		;GET MAP DATA
	MOV	CL,CH
	ROL	AL,CL		;ROTATE TO TARGET BIT
	MOV	DX,CX
GTDMBE:
	RET
;
;  CHANGE DISK ALLOCATION MAP BIT
;  INPUT
;  CX:BLOCK NUMBER
;  DL:0 DELETE  1 SET
;
CGDMBT:
	PUSH	DX
	CALL	GTDMBT		;GET MAP BIT
	AND	AL,0FEH		;OFF BIT
	POP	CX
	OR	AL,CL		;SET OR NOT SET
;
;  SET DISK ALLOCATION MAP BIT
;  INPUT
;  AL:BYTE DATA
;  DH:ROTATE COUNT
;  BX:MAP POINT
;
STDMBT:
	PUSH	CX
	MOV	CL,DH
	ROR	AL,CL
	MOV	[BX],AL		;SET TO ALLOCATION MAP
	POP	CX
	RET
;
;  CHANGE DISK ALLOCATION MAP BY ONE DIRECTORY DATA
;  INPUT
;  CL:0 DELETE  1 USE
;
CHGDMP:
	CALL	GTDRPT		;GET DIRECTORY BLOCK TOP
	ADD	BX,16
	PUSH	CX
	MOV	CL,17		;BLOCK NUMBER DATA +1
CHGDML:				;ONE BLOCK SET/CLEAR LOOP
	POP	DX
	DEC	CL
	JNZ	CHGDMS		;NOT END
	RET			;END OF ONE DIRECTORY
;
CHGDMS:
	PUSH	DX
	CMP	DSMMOD,0	;CHECK BLOCK NUMBER MODE
	JZ	CHGDMT		;TWO BYTE MODE
	PUSH	CX		;ONE BYTE MODE
	PUSH	BX
	MOV	CL,[BX]		;GET BLOCK NUMBER
	MOV	CH,0
	JMPS	CHGDMG
;
CHGDMT:				;TWO BYTE MODE
	DEC	CL
	PUSH	CX
	MOV	CX,[BX]		;GET BLOCK NUMBER
	INC	BX
	PUSH	BX
CHGDMG:
	OR	CX,CX
	JZ	CHGDMN		;NOT ALLOCATED
	MOV	BX,DSM
	CMP	BX,CX
	JC	CHGDMN		;OVER OF SIZE
	CALL	CGDMBT		;SET/CLEAR TARGET BIT IN MAP
CHGDMN:				;TO NEXT BLOCK NUMBER
	POP	BX
	INC	BX
	POP	CX
	JMPS	CHGDML
;
;  INITIALIZE DISK ALLOCATION MAP & CHECK SUM TABLE
;
INIDMP:
	MOV	BX,DSM
	MOV	CL,3
	SHR	BX,CL
	INC	BX		;GET ALL MAP SIZE
	MOV	CX,BX
	MOV	BX,PNALMP	;MAP TOP
INIDMC:				;CLEAR OF ALLOCATION MAP
	MOV	BYTE PTR [BX],0
	INC	BX
	LOOP	INIDMC
	MOV	DX,ALMASK	;GET DIRECTORY RESERVED BIT
	MOV	BX,PNALMP
	MOV	[BX],DX		;SET INITIAL DATA OF ALLOCATION MAP
	CALL	TOHOME		;RESTORE
	MOV	BX,PNDRCK
	MOV	WORD PTR [BX],3	;INITIALIZE DIRETORY CHECK LEVEL
	CALL	INDRCN		;INITIALIZE DATA COUNT
INIDML:
	MOV	CL,-1
	CALL	GTNDSC		;GET NEXT DIRECTORY
	CALL	CKDREN		;CHECK END
	JZ	CPEXTE		;END OF DIRECTORY
	CALL	GTDRPT		;GET DIRECTORY POINT
	CMP	BYTE PTR [BX],DELCOD
	JZ	INIDML		;DELETED FILE
	MOV	AL,USRCOD
	CMP	AL,[BX]
	JNZ	INIDMS		;NOT CURRENT USER DIRECTORY
	INC	BX
	MOV	AL,[BX]
	SUB	AL,'$'
	JNZ	INIDMS		;NOT SUBMIT TEMPORARY
	DEC	AL
	MOV	OTPARB,AL	;SUBMIT TEMPORARY EXISTS
INIDMS:
	MOV	CL,1
	CALL	CHGDMP		;SET DISK ALLOCATION MAP BIT
	CALL	STDLVL		;UP DIRECTROY LEVEL AS AVAILABLE
	JMPS	INIDML
;
;  SET DIRECTORY CODE  -1 NOT FOUND
;
SDRCOD:
	MOV	AL,DIRCOD
	JMP	BTPRST
;
;  COMPARE DIRECTORY EXTENSION AS DIRECTORY NUMBER
;  INPUT
;  AL:CODE 1
;  CL:CODE 2
;  OUTPUT
;  AL:DIRECTORY DIFFERENCE
;  ZF:ON EVEN
;
CPEXTM:
	PUSH	CX
	MOV	CH,EXM
	NOT	CH		;GET MASK AS DIREORY NUMBER
	AND	CL,CH
	AND	AL,CH
	SUB	AL,CL
	AND	AL,01FH		;EXTENT AVAILABLE ONLY 5 BITS
	POP	CX
CPEXTE:
	RET
;
;  SET DIRECTORY SEARCH PARAMETER
;  INPUT
;  CL:COMPARE LENGTH
;
STDRSP:
	MOV	BX,INPARA
	MOV	FCBOFF,BX	;SET FCB OFFSET
	MOV	DIRCOD,-1	;INITIALIZE DIRECTORY CODE AS NOT FOUND
	MOV	DIRCLN,CL	;SET COMPARE LENGTH
	RET
;
;  SEARCH DIRECTORY FROM TOP
;  INPUT
;  CL:COMPARE LENGTH  0,1,12,15, ETC
;
SRDRFS:
	CALL	STDRSP		;SET DIRECTORY SEARCH PARAMETER
	CALL	INDRCN		;INITIALIZE DIRECTORY COUNT
	CALL	TOHOME		;RESTORE
;
;  SEARCH DIRECTORY OF NEXT
;  OUTPUT
;  CH:DIRECTORY CODE +1
;
SRDRNX:
	MOV	SYSFLG,0		;CLEAR USER 0 MATCH MODE
	MOV	CL,0		;HASH MODE TO CHECK
	CALL	GTNDSC		;GET DIRECTORY DATA
	CALL	CKDREN		;CHECK END
	JNZ	SRDRNS		;NOT END
SRDRNO:				;END OF DIRECTORY
	JMP	SRDRNF		;NOT FOUND END
;
SRDRNS:
	MOV	DX,FCBOFF
	MOV	SI,DX
	LODSB			;GET TOP CODE
	CMP	AL,DELCOD
	JZ	SRDRND		;DELETED FILE SEARCH MODE
	PUSH	DX
	CALL	CHKDLV		;CHECK DIRECTORY LEVEL
	POP	DX
	JNC	SRDRNO		;OVER ACTIVE DIRECTORY
SRDRND:
	CALL	GTDRPT		;GET DIRECTORY POINT
	MOV	CL,DIRCLN	;COMPARE LENGTH
	MOV	CH,0		;CLEAR COUNT
SRDRNL:				;ONE BYTE COMPARE LOOP
	OR	CL,CL
	JZ	SRDRNG		;END OF COMPARE  MATCHED
	MOV	SI,DX
	LODSB			;GET CODE
	CMP	AL,'?'
	JZ	SRDRNN		;WILD CARD SO DO NOT CARE
	CMP	CH,13
	JZ	SRDRNN		;SYSTEM BYTE SO IGNORED
	CMP	CH,12
	JZ	SRDRNE		;FILE EXTENT
	SUB	AL,[BX]
	AND	AL,07FH
	JNZ	SRDRNM		;MISS MATCH
	JMPS	SRDRNN		;MATCH
;
SRDRNE:				;FILE EXTENT
	PUSH	CX
	MOV	CL,[BX]
	CALL	CPEXTM		;COMPARE EXTENT AS DIRECTORY NUMBER
	POP	CX
	LAHF
	TEST	SYSFLG,0FFH
	JNZ	SRDRNZ		;USER CODE MISS MATCH  USER 0
	MOV	SYSSRC,0		;CLEAR USER 0 SEARCH MODE   AS SAME NAME FILE
	SAHF
	JNZ	SRDRNX		;EXTENT MISS MATCH
SRDRNN:				;MATCH TO NEXT BYTE
	INC	DX
	INC	BX
	INC	CH
	DEC	CL
	JMPS	SRDRNL
;
SRDRNG:				;OK GET MATCHED DIRECTORY
	MOV	DIRCOD,0	;USER DIRECTORY CODE MODE
	MOV	AL,BYTE PTR DIRCNT
	AND	AL,3
	MOV	OTPARB,AL	;SET DIRECTORY CODE
	MOV	CH,AL
	INC	CH
SRDRNR:
	RET
;
SRDRNM:				;MISS MATCH OF BYTE
	OR	CH,CH
	JNZ	SRDRNT		;NOT TOP
	TEST	BYTE PTR [BX],0FFH
	JNZ	SRDRNT		;NOT USER ZERO
	TEST	SYSSRC,0FFH
	JZ	SRDRNT		;NOT USER 0 SEARCH MODE
	MOV	SYSFLG,0FFH	;SET USER 0 DIRECTORY MODE
	JMPS	SRDRNN
;
SRDRNF:				;NOT FOUND END
	CALL	INDRCN		;INITIALIZE COUNT
	MOV	AL,0FFH		;FAIL END CODE
	MOV	CH,AL
	INC	CH
	JMP	BTPRST
;
SRDRNZ:				;USER 0 MISS MATCH FILE
	SAHF
	JNZ	SRDRNT		;EXTENT MISS MATCH
	INC	BX
	CMP	BYTE PTR [BX],0
	JNZ	SRDRNT		;MISS MATCH
	MOV	SI,DIRCNT
	MOV	SYSCNT,SI	;SAVE MATCHED DIRECTORY COUNT
SRDRNT:
	JMP	SRDRNX		;TO NEXT
;
;  DELETE DIRECTORY & ALLOCATION MAP
;
DELDMP:
	CALL	CHKROD		;CHECK R/O DISK
	MOV	CL,12		;COMPARE ONLY NAME PART
	CALL	SRDRFS		;SEARCH FIRST
DELDML:				;ONE DIRECTORY ERASE LOOP
	CALL	CKDREN		;CHECK END
	JZ	SRDRNR		;ALL OVER
	CALL	CHKROF		;CHECK R/O FILE
	CALL	GTDRPT		;GET DIRECTORY POINT
	MOV	BYTE PTR [BX],DELCOD ;SET DELETE CODE
	MOV	CL,0		;DELETE MODE
	CALL	CHGDMP		;DELETE ALL MAP
	CALL	DRWRIT		;WRITE DIRECTORY
	CALL	SRDRNX		;SEARCH NEXT
	JMPS	DELDML		;TO NEXT DIRECTORY
;
;  GET AVAILABLE BLOCK BY SEARCHING NEAREST BLOCK
;  INPUT
;  CX:LAST BLOCK NUMBER   0 FIRST BLOCK
;  OUTPUT
;  BX:AVAILABLE BLOCK NUMBER   0 NO SPACE
;
GAVLBK:
	MOV	DX,CX
GAVLBL:				;SEARCH LOOP  CX LOWER SEARCH   DX UP SEARCH
	OR	CX,CX
	JZ	GAVLBS		;NO LOWER SPACE
	DEC	CX
	PUSH	DX
	PUSH	CX
	CALL	GTDMBT		;GET ALLOCATION MAP BIT
	RCR	AL,1
	JNC	GAVLBA		;GET AVAILABLE BLOCK
	POP	CX		;NOT AVAILABLE
	POP	DX
GAVLBS:				;SEARCH UPER
	CMP	DX,DSM
	JNC	GAVLBE		;NO UPER SPACE
	INC	DX
	PUSH	CX
	PUSH	DX
	MOV	CX,DX
	CALL	GTDMBT		;GET ALLOCATION MAP BIT
	RCR	AL,1
	JNC	GAVLBA		;GET AVAILABLE BLOCK
	POP	DX		;NO AVAILABLE
	POP	CX
	JMPS	GAVLBL		;CHECK NEXT
;
GAVLBA:				;GET AVAILABLE BLOCK
	RCL	AL,1
	INC	AL		;ON BIT FOR USE
	CALL	STDMBT		;SET TO ALLOCATION MAP
	POP	BX
	POP	DX
	RET
;
GAVLBE:				;NO UPER SPACE
	OR	CX,CX
	JNZ	GAVLBL		;SOME LOWER SPACE LEFT
	MOV	BX,0		;NO DISK SPACE
	RET
;
;  COPY ALL FCB DATA TO DIRECTORY & WRITE
;  INPUT
;  CL:BIAS OF FCB SOURCE TOP  0 NORMAL  16 REBAME
;  DL:COPY LENGTH
;
COPYDA:
	MOV	CL,0		;FOR ALL COPY MODE
	MOV	DL,32
COPYDR:
	PUSH	DX		;SAVE LENGTH
	MOV	CH,0
	MOV	DX,INPARA
	ADD	DX,CX		;GET SOURCE POINT
	CALL	GTDRPT		;GET DIRECTORY TOP
	POP	CX
	CALL	COPY		;COPY
COPYDE:
	CALL	STDIRT		;SET DIRECTORY  TRACK & SECTOR
	JMP	DRWRIT		;WRITE DIRECTORY
;
;  RENAME
;
RENAME:
	CALL	CHKROD		;CHECK R/O DISK
	MOV	CL,12		;ONLY NAME
	CALL	SRDRFS		;SEARCH FIRST
	MOV	BX,INPARA
	MOV	AL,[BX]
	ADD	BX,16
	MOV	[BX],AL		;SET SAME USER CODE TO NEW NAME
RENAML:				;ONE DIRECTORY RENAME LOOP
	CALL	CKDREN		;CHECK END
	JNZ	RENAMS		;NOT END
RENAMN:				;END
	RET
;
RENAMS:
	CALL	CHKROF		;CHECK R/O FILE
	MOV	CL,16		;NEW NAME
	MOV	DL,12		;COPY LENGTH
	CALL	COPYDR		;SET NEW NAME & WRITE
	CALL	SRDRNX		;SEARCH NEXT
	JMPS	RENAML		;TO NEXT
;
;  SET FILE ATTRBUTE
;
STFATR:
	MOV	CL,12		;ONLY NAME
	CALL	SRDRFS		;SEARCH FIRST
STFATL:				;ATTRIBUTE SET LOOP
	CALL	CKDREN		;CHECK END
	JZ	RENAMN		;END
	MOV	CL,0		;FROM TOP
	MOV	DL,12		;NAME PART ONLY
	CALL	COPYDR		;SET & WRITE DIRECTORY
	CALL	SRDRNX		;SEARCH NEXT
	JMPS	STFATL		;TO NEXT
;
;  OPEN  FILE
;
OPENFL:
	MOV	CL,15		;WITH EXTENT
	CALL	SRDRFS		;SEARCH FIRST
	CALL	CKDREN		;CHECK NOT FOUND
OPENFN:
	JZ	RENAMN		;NOT FOUND END
OPENFS:
	CALL	EXTPNT		;GET EXTENT POINT
	PUSH	AX		;SAVE FILE EXTENT
	PUSH	BX
	CALL	GTDRPT		;GET DIRECTORY POINT
	XCHG	BX,DX
	MOV	BX,INPARA
	MOV	CL,32
	PUSH	DX
	CALL	COPY		;COPY DIRECTORY DATA TO FCB
	CALL	FMDRON		;INITIALIZE MODIFY MODE
	POP	DX
	MOV	BX,12
	ADD	BX,DX
	MOV	CL,[BX]		;GET FILE EXTENT
	MOV	BX,15
	ADD	BX,DX
	MOV	CH,[BX]		;GET RECORD COUNT
	POP	BX
	POP	AX
	MOV	[BX],AL		;RESTORE FILE EXTENT
	CMP	CL,[BX]
	MOV	AL,CH
	JZ	OPENFX		;MATCH EXTENT SO RECORD COUNT IS AVAILABLE
	MOV	AL,0
	JC	OPENFX		;UNDER
	MOV	AL,80H		;OVER
OPENFX:
	MOV	BX,INPARA
	MOV	DX,15
	ADD	BX,DX
	MOV	[BX],AL		;SET RECORD COUNT
OPENFE:
	RET
;
;  CHECK DIRECTORY MAP FOR TWO BYTE MODE
;  INPUT
;  BX:DESTINATION POINTER
;  DX:SOURCE POINTER
;
CHKDMP:
	CMP	WORD PTR [BX],0
	JNZ	OPENFE		;SOME DATA EXIST SO NOT SET
	MOV	SI,DX
	LODSW			;GET SOURCE DATA
	MOV	[BX],AX		;SET DATA
CHKDME:
	RET
;
;  CLOSE FILE
;
CLOSEF:
	XOR	AX,AX
	MOV	OTPARB,AL	;CLEAR RESULT PARAMETER
	MOV	DIRCNT,AX	;CLEAR DIRECTORY COUNT
	CALL	CHKROV		;CHECK R/O DISK
	JNZ	CHKDME		;R/O DISK SO END
	CALL	FMDPNT		;GET MODIFY MODE
	AND	AL,080H
	JNZ	CHKDME		;NO MODIFY MODE SO END
	MOV	CL,15		;WITH EXTENT
	CALL	SRDRFS		;SEARCH
	CALL	CKDREN
	JZ	CHKDME		;NOT FOUND
	MOV	CX,16
	CALL	GTDRPT		;GET DIECTORY POINT
	ADD	BX,CX		;GET DIRECTORY MAP POINT
	XCHG	BX,DX
	MOV	BX,INPARA
	ADD	BX,CX		;GET FCB MAP TOP
	MOV	CL,16
CLOSEL:				;LOOP TO CHECK & MAKE DIRECTORY MAP
	CMP	DSMMOD,0
	JZ	CLOSED		;TWO BYTE MODE
	MOV	AL,[BX]		;ONE BYTE MODE  GET FCB DATA
	OR	AL,AL
	MOV	SI,DX
	LODSB			;GET DIRECTORY DATA
	JNZ	$+4		;SOME BLOCK NUMBER EXISTS IN FCB
	MOV	[BX],AL		;SET TO FCB
	OR	AL,AL
	JNZ	CLOSES		;SOME DATA IN DIRECTORY
	MOV	AL,[BX]		;GET FCB DATA
	MOV	DI,DX
	CLD
	STOSB			;SET TO DIRECTORY
CLOSES:
	CMP	AL,[BX]
	JNZ	CLOSER		;MAP MISS MATCH
	JMPS	CLOSEN		;TO NEXT
;
CLOSED:				;TWO BYTE MODE
	CALL	CHKDMP
	XCHG	BX,DX
	CALL	CHKDMP		;CHECK & SET IF EMPTY
	XCHG	BX,DX
	MOV	SI,DX
	MOV	AX,[SI]		;GET DIRECTORY DATA
	CMP	AX,[BX]		;COMPARE WITH FCB DATA
	JNZ	CLOSER		;MAP MISS MATCH
	INC	DX
	INC	BX
	DEC	CL
CLOSEN:				;TO NEXT
	INC	DX
	INC	BX
	DEC	CL
	JNZ	CLOSEL		;TO NEXT MAP
	MOV	CX,-20		;ALL MAP MATCHED & SETUPED
	ADD	BX,CX
	XCHG	BX,DX
	ADD	BX,CX
	MOV	SI,DX
	LODSB
	CMP	AL,[BX]		;COMPARE FILE EXTENT
	JC	CLOSET		;DIRECTORY IS LARGER SO NOT CHANGE
	MOV	[BX],AL		;FCB IS LARGER   SO SET EXTENT
	MOV	CX,3
	ADD	BX,CX
	XCHG	BX,DX
	ADD	BX,CX
	MOV	AL,[BX]
	MOV	DI,DX
	CLD
	STOSB			;SET NEW RECORD COUNT
CLOSET:				;WRITE TO DIRECTORY FOR CLOSE
	MOV	EXTMOD,0FFH	;SET CLOSE MODE FOR EXTENT
	JMP	COPYDE
;
CLOSER:				;MAP MISS MATCH ERROR
	DEC	OTPARB
CLOSEE:
	RET
;
;  GET AVAILABLE DIRECTORY
;
GTADIR:
	CALL	CHKROD		;CHECK R/O DISK
	PUSH	INPARA		;SAVE FCB POINT
	MOV	INPARA,OFFSET DLTFCB ;DUMMY FCB AS DELETED FCB
	MOV	CL,1
	CALL	SRDRFS		;SEARCH DELETED DIRECTORY
	CALL	CKDREN
	POP	INPARA
	JZ	CLOSEE		;NO DIRECTORY SPACE
	MOV	DX,INPARA
	MOV	BX,15
	ADD	BX,DX
	MOV	CL,17
	XOR	AL,AL
GTADIL:				;CLEAR DIRECTORY MAP & CURRENT RECORD COUNT
	MOV	[BX],AL
	INC	BX
	DEC	CL
	JNZ	GTADIL
	MOV	BX,13
	ADD	BX,DX
	MOV	[BX],AL		;CLEAR RECORD COUNT
	CALL	STDLVL
	CALL	COPYDA		;WRITE TO DIRECTORY
	JMP	FMDRON		;INITIALIZE MODIFY MODE
;
;  GET NEXT DIRECTORY
;
GTNXDR:
	XOR	AL,AL
	MOV	EXTMOD,AL	;CLEAR EXTENT MODE OF CLOSE
	CALL	CLOSEF		;CLOSE CURRENT
	CALL	CKDREN
	JZ	CLOSEE		;CLOSE DIRECTORY NOT FOUND
	MOV	BX,INPARA
	ADD	BX,12
	MOV	AL,[BX]		;GET EXTENT
	INC	AL		;UP EXTENT
	AND	AL,01FH
	MOV	[BX],AL
	JZ	GTNXDX		;UP S2 EXTENT
	MOV	CH,AL
	MOV	AL,EXM
	AND	AL,CH
	AND	AL,EXTMOD
	JZ	GTNXDN		;TO NEXT DIRECTORY
	JMPS	GTNXDO		;IN SAME DIRECTORY
;
GTNXDX:				;S2 EXTENT
	ADD	BX,2
	INC	BYTE PTR [BX]	;UP S2 EXTENT
	MOV	AL,[BX]
	AND	AL,00FH
	JZ	GTNXDV		;OVER SO NO DATA EXIST END
GTNXDN:				;TO NEXT DIRECTORY
	MOV	CL,15		;WITH EXTENT
	CALL	SRDRFS		;SEARCH
	CALL	CKDREN
	JNZ	GTNXDO		;OK GET
	MOV	AL,RWMODE
	INC	AL
	JZ	GTNXDV		;READ MODE SO FILE OVER
	CALL	GTADIR		;GET AVAILABLE DIRECTORY AS WRITE MODE
	CALL	CKDREN
	JZ	GTNXDV		;NO DIRECTORY SPACE
	JMPS	GTNXDW		;OK END
;
GTNXDO:				;OPEN BY NEW EXTENT
	CALL	OPENFS
GTNXDW:
	CALL	GTRCNT		;GET RECORD COUNT
	XOR	AL,AL
	JMP	BTPRST		;SUCCESS END
;
GTNXDV:				;FILE OVER END
	CALL	NODTEX		;TO NO DATA EXIST MODE
	JMP	FMDRON
;
;  READ RECORD
;
RDNEXT:				;READ NEXT RECORD
	MOV	RUPCNT,1	;SET UP COUNT
RDNEXR:				;RE RANDOM ENTRY
	MOV	RWMODE,-1	;TO READ MODE
	CALL	GTRCNT		;GET RECORD COUNT
	MOV	AL,CURCNT
	CMP	AL,RECUNT
	JC	RDNEXS		;IN SAME DIRECTORY
	CMP	AL,080H
	JNZ	RDNEXV		;TOO LARGE  VALUE ERROR
	CALL	GTNXDR		;TO NEXT DIRECTORY
	CALL	GTRCPT
	XOR	AX,AX
	MOV	WORD PTR CURCNT,AX
	MOV	[BX],AL		;CLEAR CURRENT RECORD
	CMP	OTPARB,0
	JNZ	RDNEXV		;ERROR OF DIRECTORY EXTENT
RDNEXS:				;GET IN DIRECTORY
	CALL	GTBLCK		;GET TARGET BLOCK
	CALL	CHKBLK
	JZ	RDNEXV		;EMPTY
	CALL	BLTSCT		;BLOCK NUMBER TO SECTOR
	CALL	TRSSET		;TO TRACK & SECTOR
	CALL	DREAD		;READ ONE SECTOR
	JMP	USRCNT		;SET RECORD COUNT TO FCB
;
RDNEXV:				;OVER OF FILE OR ERROR
	JMP	NODTEX
;
;  WRITE NEXT RECORD
;
WTNEXT:
	MOV	RUPCNT,1	;SET UP COUNT
WTNEXR:				;WRITE RANDOM ENTRY
	MOV	RWMODE,0	;SET WRITE MODE
	CALL	CHKROD		;CHECK R/O DISK
	MOV	BX,INPARA
	CALL	CHKROL		;CHECK R/O FILE
	CALL	GTRCNT		;GET RECORD COUNT
	MOV	AL,CURCNT
	CMP	AL,080H
	JC	WTNEXS
	JMP	NODTEX		;FILE EXTENT ERROR
;
WTNEXS:
	CALL	GTBLCK		;GET BLOCK
	CALL	CHKBLK
	MOV	CL,0		;ALLOCATED MODE FLAG
	JNZ	WTNEXW		;ALLOCATED BLOCK
	CALL	GBSDIR		;UNALLOCATED BLOCK
	MOV	DRBSWT,AL	;SAVE DIRECTORY BIAS
	XOR	CX,CX
	OR	AL,AL
	JZ	WTNEXF		;FIRST BLOCK
	MOV	CL,AL
	DEC	CX
	CALL	GTBLNM		;GET LAST BLOCK NUMBER
	MOV	CX,BX
WTNEXF:
	CALL	GAVLBK		;GET AVAILABLE BLOCK NUMBER
	OR	BX,BX
	JNZ	WTNEXG		;GET BLOCK
	MOV	AL,2
	JMP	BTPRST		;DISK FULL
;
WTNEXG:				;GET TARGET BLOCK
	MOV	TGSECT,BX	;SET BLOCK
	XCHG	BX,DX
	MOV	BX,INPARA
	ADD	BX,16
	CMP	DSMMOD,0
	MOV	AL,DRBSWT	;BIAS IN DIRECTORY
	MOV	AH,0
	JZ	WTNEXD		;TWO BYTE MODE
	ADD	BX,AX		;ONE BYTE MODE
	MOV	[BX],DL		;SET BLOCK NUMBER
	JMPS	WTNEXO
;
WTNEXD:				;TWO BYTE MODE
	ADD	BX,AX
	ADD	BX,AX
	MOV	[BX],DX		;SET BLOCK NUMBER
	INC	BX
WTNEXO:
	MOV	CL,2		;UNALLOCATED MODE
WTNEXW:
	CMP	OTPARB,0
	JZ	$+3		;OK WRITE
	RET			;SOME ERROR END
;
	MOV	MDWRIT,CL	;SET WRITE MODE
	CALL	BLTSCT		;SET TRACK & SECTOR
	CMP	RUPCNT,2
	JNZ	WTNEXN		;NOT WRITE WITH ZERO FILL
	CMP	MDWRIT,2
	JNZ	WTNEXN		;NOT UNALLOCATED MODE
	PUSH	TGSECT		;WRITE ZERO SECTOR
	MOV	DI,DIRBUF
	XOR	AX,AX
	MOV	CX,64
	CLD
	REP	STOSW		;CLEAR BUFFER
	CALL	STDDMA		;DMA TO WORK
	MOV	BX,BTSECT	;GET BLOCK TOP
WTNEXZ:				;ZERO DATA WRITE LOOP
	MOV	TGSECT,BX
	CALL	TRSSET		;SET TRACK & SECTOR
	CALL	DWRITE		;WRITE ZERO DATA
	MOV	BX,TGSECT
	MOV	MDWRIT,0	;WRITE MODE TO ALLOCATED
	MOV	AL,BL
	MOV	DH,BLM
	AND	AL,DH
	INC	BX		;UP SECTOR
	CMP	AL,DH
	JNZ	WTNEXZ		;TO NEXT SECTOR
	POP	TGSECT
	CALL	STBDMA		;RESTORE DMA ADDRESS
WTNEXN:
	CALL	TRSSET		;TO TARGET TRACK & SECTOR
	CALL	DWRITE		;WRITE
	MOV	AL,CURCNT
	MOV	BX,OFFSET RECUNT
	CMP	AL,[BX]
	JC	WTNEXV		;FILE SIZE IS LARGER
	MOV	[BX],AL		;SETUP RECORD COUNT
	INC	BYTE PTR [BX]
	MOV	CL,2
WTNEXV:
	PUSH	AX
	CALL	FMDPNT		;GET MODIFY MODE
	AND	AL,07FH		;OFF NO MODIFY BIT
	MOV	[BX],AL
	POP	AX
	CMP	AL,07FH
	JNZ	WTNEXE		;RECORD COUNT IN RANGE
	CMP	RUPCNT,1
	JNZ	WTNEXE		;NOT SEQUENTIAL WRITE
	CALL	USRCNT		;SET RECORD COUNT TO FCB
	CALL	GTNXDR		;TO NEXT DIRECTORY
	MOV	BX,OFFSET OTPARB
	MOV	AL,[BX]
	OR	AL,AL
	JNZ	WTNEXA		;SOME ERROR
	DEC	AL
	MOV	CURCNT,AL	;SET CURRENT RECORD COUNT FOR UP COUNT
WTNEXA:
	MOV	BYTE PTR [BX],0	;CLEAR ERROR FLAG  AS CURRENT IS PRE-OPERATION
WTNEXE:
	JMP	USRCNT
;
;  GET DIRECTORY FOR RANDOM ACCESS
;  INPUT
;  CL:-1 READ MODE   0 WRITE MODE
;  OUTPUT
;  ZF:ON OK
;
RNDDIR:
	MOV	RUPCNT,0	;NO UP COUNT MODE
RNDDIS:
	PUSH	CX
	MOV	DX,INPARA
	MOV	BX,33
	ADD	BX,DX
	MOV	AL,[BX]
	AND	AL,07FH		;GET RECORD COUNT VALUE
	PUSH	AX
	MOV	AL,[BX]
	RCL	AL,1
	INC	BX
	MOV	AL,[BX]
	RCL	AL,1
	AND	AL,01FH		;GET EXTENT VALUE
	MOV	CL,AL
	MOV	AL,[BX]
	RCR	AL,1
	RCR	AL,1
	RCR	AL,1
	RCR	AL,1
	AND	AL,00FH		;GET S2 EXTENT
	MOV	CH,AL
	POP	AX
	INC	BX
	MOV	BL,[BX]
	OR	BL,BL
	MOV	BL,6		;TOO LARGE ERROR CODE
	JNZ	RNDDIF		;TOO LARGE
	MOV	BX,32
	ADD	BX,DX
	MOV	[BX],AL		;SET CURRENT RECORD COUNT
	MOV	BX,12
	ADD	BX,DX
	MOV	AL,CL
	SUB	AL,[BX]
	JNZ	RNDDID		;DIFFERENT EXTENT
	MOV	BX,14		;EVEN EXTENT
	ADD	BX,DX
	MOV	AL,CH
	SUB	AL,[BX]
	AND	AL,07FH
	JZ	RNDDIE		;EVEN ALL EXTENT
RNDDID:				;DIFFERENT EXTENT
	PUSH	CX
	PUSH	DX
	CALL	CLOSEF		;CLOSE CURRENT DIRECTORY
	POP	DX
	POP	CX
	MOV	BL,3
	MOV	AL,OTPARB
	INC	AL
	JZ	RNDDIU		;CANNOT CLOSE
	MOV	BX,12
	ADD	BX,DX
	MOV	[BX],CL		;SET TARGET EXTENT
	MOV	BX,14
	ADD	BX,DX
	MOV	[BX],CH		;SET TARGET S2 EXTENT
	CALL	OPENFL		;OPEN TARGET DIRECTORY
	MOV	AL,OTPARB
	INC	AL
	JNZ	RNDDIE		;OK GET
	POP	CX
	PUSH	CX
	MOV	BL,4
	INC	CL
	JZ	RNDDIU		;READ MODE SO UNWRITTEN EXTENT
	CALL	GTADIR		;WRITE MODE  SO SEARCH AVAILABLE DIRECTORY
	MOV	BL,5
	MOV	AL,OTPARB
	INC	AL
	JZ	RNDDIU		;NO DIRECTORY SPACE
RNDDIE:				;GET TARGET DIRECTORY
	POP	CX
	XOR	AL,AL
	JMP	BTPRST
;
RNDDIU:				;ERROR END  BL=ERROR CODE
	PUSH	BX
	CALL	FMDPNT
	MOV	BYTE PTR [BX],0C0H ;SET DIRECTORY NOT ACTIVE MODE
	POP	BX
RNDDIF:				;ERROR END
	POP	CX
	MOV	AL,BL
	MOV	OTPARB,AL	;SET ERROR CODE
	JMP	FMDRON
;
;  READ RANDOM
;
RDRAND:
	MOV	CL,-1		;REDA MODE
	CALL	RNDDIR		;GET DIRECTORY
	JNZ	RDRANE		;ERROR
	CALL	RDNEXR		;GET RECORD
RDRANE:
	RET
;
;  WRITE RANDOM
;
WTRAND:
	MOV	CL,0		;WRITE MODE
	CALL	RNDDIR		;GET DIRECTORY
	JNZ	WTRANE		;ERROR
	CALL	WTNEXR		;WRITE ONE SECTOR
WTRANE:
	RET
;
;  COMPUTE FILE SIZE FROM FCB DATA
;  INPUT
;  BX:DIRECTORY DATA TOP
;  DX:BIAS  15 RECORD COUNT  32 CURRENT RECORD
;  OUTPUT
;  ALCX:COUNT
;
DIRSIZ:
	XCHG	BX,DX
	ADD	BX,DX
	MOV	CL,[BX]		;GET RECORD COUNT
	MOV	CH,0
	MOV	BX,12
	ADD	BX,DX
	MOV	AH,[BX]		;GET EXTENT
	MOV	AL,0
	SHR	AX,1
	AND	AH,00FH
	ADD	CX,AX
	MOV	BX,14
	ADD	BX,DX
	MOV	AL,[BX]		;GET S2 EXTENT
	MOV	AH,16
	MUL	AH		;*16
	PUSH	AX
	ADD	CH,AL
	PUSHF
	POP	BX
	MOV	AL,BL		;GET FLAG
	POP	BX
	OR	AL,BL
	AND	AL,1		;GET OVERFLOW BIT
	RET
;
;  COMPUTE FILE SIZE BY DIRECTORY SEARCH
;
CFLSIZ:
	MOV	CL,12
	CALL	SRDRFS		;SEARCH DIRECTORY BY NAME ONLY
	MOV	BX,INPARA
	MOV	DX,33
	ADD	BX,DX
	PUSH	BX
	MOV	[BX],DH		;CLEAR RANDOM RECORD COUNT
	INC	BX
	MOV	[BX],DH
	INC	BX
	MOV	[BX],DH
CFLSIL:				;ONE DIRECTORY CHECK LOOP
	CALL	CKDREN
	JZ	CFLSIE		;END
	CALL	GTDRPT		;GET DIRECTORY POINT
	MOV	DX,15
	CALL	DIRSIZ		;GET SIZE BY RECORD COUNT
	POP	BX
	PUSH	BX
	MOV	DL,AL
	MOV	AX,CX
	SUB	AX,[BX]
	MOV	AL,DL
	SBB	AL,2[BX]	;COMPARE WITH CURRENT
	JC	CFLSIS		;SMALL SO NOT CHANGE
	MOV	2[BX],DL	;SET LARGER VALUE
	MOV	[BX],CX
CFLSIS:
	CALL	SRDRNX		;SEARCH NEXT
	JMPS	CFLSIL
;
CFLSIE:				;END OF DIRECTORY
	POP	BX
	RET
;
;  SET RANDOM RECORD COUNT
;
STRCNT:
	MOV	BX,INPARA
	MOV	DX,32
	CALL	DIRSIZ		;GET SIZE BY CURRENT RECORD
	MOV	BX,33
	ADD	BX,DX
	MOV	[BX],CX		;SET COUNT
	MOV	2[BX],AL
	RET
;
;  SELECT DISK
;
SELDSK:
	MOV	BX,LGDSKV	;LOGIN DISK VECTOR
	MOV	CL,CURDSK	;CURRENT DISK
	ROR	BX,CL
	PUSH	BX		;SAVE LOGIN VECTOR
	XCHG	BX,DX
	CALL	GDPTBL		;GET DISK PARAMETER
	POP	BX
	JNZ	$+5		;OK
	CALL	DSEROR		;SELECT ERROR & ABORT
	RCR	BL,1
	JC	ENTRYE		;ALREADY LOGIN DISK
	MOV	CX,LGDSKV
	CALL	STDKVC		;SET LOGIN BIT
	MOV	LGDSKV,BX	;SAVE NEW VECCTOR
	JMP	INIDMP		;INITIALIZE DISK ALLOCATION MAP & CHECK SUM
;
;  14:SELECT DISK
;
MSELDK:
	MOV	AL,INPARB
	MOV	CURDSK,AL	;SET AS CURRENT DISK
	JMPS	SELDSK
;
;  CHECK ENTRY TYPE & SELECT FOR FCB FUNCTIONS
;
ENTRYS:
	CALL	STWFCS		;SET FCB TO WORK FOR SEQUENTIAL ACCESS
	JMPS	ENTRYC
;
ENTRYR:
	CALL	STWFCR		;SET FCB TO WORK FOR RANDOM ACCESS
ENTRYC:
	MOV	BX,INPARA
	MOV	SYSMOD,000H
	TEST	BYTE PTR 8[BX],80H
	JZ	ENTRYM		;NOT SYSTEM MODE FILE
	AND	BYTE PTR 8[BX],07FH
	MOV	SYSMOD,60H	;USER 0 SYSTEM MODE FILE
ENTRYM:
	MOV	FLOMOD,-1	;SET FCB OPERATION MODE
	MOV	BX,INPARA
	MOV	AL,[BX]
	AND	AL,01FH
	DEC	AL
	MOV	INPARB,AL	;SET REQUIRED DISK FOR SELECT DISK
	CMP	AL,01EH
	JNC	ENTRYD		;ZERO SO CURRENT DISK
	MOV	AL,CURDSK
	MOV	ENTDSK,AL	;SAVE DEFAULT DISK
	MOV	AL,[BX]
	MOV	ENTTYP,AL	;SAVE ENTRY TYPE
	AND	AL,0E0H
	MOV	[BX],AL		;OFF DISK ENTRY
	CALL	MSELDK		;SELECT DISK
ENTRYD:
	MOV	AL,USRCOD
	MOV	BX,INPARA
	OR	[BX],AL		;SET USER CODE
ENTRYE:
	RET
;
;  CHECK SYSTEM MODE & SET
;
STSYSM:
	CMP	SYSMOD,60H
	JNZ	STSYSE		;NOT USER 0 SYSTEM MODE
	MOV	BX,INPARA	;USER 0 SYSTEM MODE
	MOV	BYTE PTR [BX],0
STSYSE:
	RET
;
;  13:RESET DISK SYSTEM
;
MRSDSY:
	TEST	SGBIOS,0FFFFH
	JNZ	MRSDSS		;ALREADY SET BIOS CODE SEGMENT DATA
	MOV	SGBIOS,CS	;SET CURRENT CODE SEGMENT
MRSDSS:
	XOR	BX,BX
	MOV	RODSKV,BX	;CLEAR R/O DISK VECTOR
	MOV	LGDSKV,BX	;CLEAR LOGIN DISK VECTOR
	MOV	BL,CURDRV
	MOV	CURDSK,BL	;SET CURRENT DISK
	JMP	SELDSK		;SELECT DISK
;
;  15:OPEN FILE
;
MOPEN:
	CALL	ENTRYS		;ENTRY PROCESS
	CALL	FMDCLR
	CMP	USRCOD,0
	JZ	MOPENS		;USER ZERO MODE SO NO SYSTEM CHECKING
	MOV	SYSCNT+1,00FEH	;WITH USER 0 SYSTEM MODE CHECKING
	MOV	SYSSRC,-1
MOPENS:
	CALL	OPENFL		;OPEN
	CALL	MOPENC		;CHECK FOUND MODE & OVERRIDE RETURN IF FOUND
	TEST	SYSSRC,-1
	JNZ	MOPENZ		;WITH USER 0 SYSTEM MODE CHECKING
MOPENE:				;NOT FOUND END
	RET
;
MOPENZ:				;CHECK USER 0 SYSTEM FILE
	MOV	SYSSRC,0	;CLEAR USE 0 SYSTEM MODE
	CMP	SYSCNT+1,00FEH
	JZ	MOPENE		;NO SYSTEM FILE
	MOV	BX,SYSCNT	;GET FILE DIRECTORY COUNT
	AND	BL,0FCH		;TO SECTOR TOP
	DEC	BX
	MOV	DIRCNT,BX
	MOV	SYSMOD,60H	;BY SYSTEM MODE
	MOV	BX,INPARA
	MOV	BYTE PTR [BX],0	;USER 0
	MOV	CL,15
	CALL	STDRSP		;SET PARAMETER
	CALL	SRDRNX		;SEARCH
	CALL	OPENFN		;DO OPEN PROCESS
	CALL	MOPENC		;CHECK MODE
	RET
;
MOPENC:				;CHECK OPEN MODE
	CALL	CKDREN
	JZ	MOPENE		;NOT FOUND END
	POP	BX		;OVERRIDING RETURN
	CMP	SYSMOD,60H
	JNZ	MOPENG		;NOT SYSTEM MODE SO SIMPLE END
	MOV	BX,INPARA
	MOV	AL,10[BX]
	AND	AL,080H
	JNZ	MOPENG		;SYSTEM FILE SO OK
	MOV	SYSMOD,AL	;CLEAR SYSTEM MODE AS NOT SYSTEM FILE
	MOV	AL,-1		;NOT FOUND END
	JMPS	MRTCDS
;
MOPENG:
	RET
;
;  16:CLOSE FILE
;
MCLOSE:
	CALL	ENTRYS		;ENTRY PROCESS
	JMP	CLOSEF
;
;  17:SEARCH FOR FIRST
;
MSRCHF:
	CALL	STWFCS		;SET FCB TO WORK
	MOV	BX,INDSEG
	MOV	SGUFCB,BX	;SAVE FCB SEGMENT
	MOV	CL,0
	MOV	BX,INPARA
	CMP	BYTE PTR [BX],'?'
	JZ	MSRCHA		;ANY DIRECTORY
	CALL	EXTPNT		;GET EXTENT POINT
	CMP	BYTE PTR [BX],'?'
	JZ	MSRCHX		;NO CHECK
	CALL	FMDCLR		;CLEAR FILE MODE
MSRCHX:
	CALL	ENTRYC		;DO ENTRY PROCESS
	MOV	CL,15
MSRCHA:
	CALL	SRDRFS		;SEARCH FIRST
	JMPS	MSRCHC		;COPY DIRECTORY DATA
;
;  18:SEARCH FOR NEXT
;
MSRCHN:
	MOV	BX,SGUFCB
	MOV	INDSEG,BX	;GET FCB SEGMENT
	MOV	BX,PTUFCB
	MOV	INPARA,BX	;GET FCB OFFSET
	CALL	ENTRYS		;ENTRY PROCESS
	CALL	SRDRNX		;SEARCH NEXT
MSRCHC:
	JMP	DRCOPY		;COPY DIRECTORY DATA
;
;  19:DELETE FILE
;
MDELET:
	CALL	ENTRYS		;ENTRY PROCESS
	CALL	DELDMP
	JMP	SDRCOD
;
;  20:READ SEQUENTIAL
;
MREADS:
	CALL	ENTRYS		;ENTRY PROCESS
	CALL	STSYSM		;CHECK & SET SYSTEM FILE MODE
	JMP	RDNEXT
;
;  21:WRITE SEQUENTIAL
;
MWRITS:
	CALL	ENTRYS		;ENTRY PROCESS
	JMP	WTNEXT
;
;  22:MAKE FILE
;
MMAKE:
	CALL	ENTRYS		;ENTRY PROCESS
	CALL	FMDCLR		;CLEAR FILE MODE
	JMP	GTADIR		;GET AVAILABLE DIRECTORY
;
;  23:RENAME FILE
;
MRENAM:
	CALL	ENTRYS		;ENTRY PROCESS
	CALL	RENAME
	JMP	SDRCOD
;
;  24:RETURN LOGIN VECTOR
;
MRTLIV:
	MOV	BX,LGDSKV	;LOGIN VECTOR
	JMPS	WDPRST
;
;  25:RETURN CURRENT DISK
;
MRTCDK:
	MOV	AL,CURDSK	;CURRENT DISK
MRTCDS:
	JMP	BTPRST
;
;  26:SET DMA ADDRESS
;
MSTDMO:
	MOV	DMAADD,DX	;DMA ADDRESS
	JMP	STBDMA		;SET IN BIOS
;
;  27:GET ALLOCATION MAP ADDRESS
;
MGTALM:
	MOV	BX,PNALMP	;ALLOCATION MAP POINT
	JMPS	WDPRST
;
;  29:GET R/O VECTOR
;
MGTROV:
	MOV	BX,RODSKV	;R/O VECTOR
	JMPS	WDPRST
;
;  30:SET FILE ATTRIBUTE
;
MSTFAT:
	CALL	ENTRYS		;ENTRY PROCESS
	CALL	STFATR		;SET ATTRIBUTE
	JMP	SDRCOD
;
;  31:GET DISK PARAMETER BLOCK ADDRESS
;
MGDPBA:
	MOV	BX,PNTDPB	;DISK PARAMER BLOCK POINT
;
;  WORD PARAMETER SET END
;
WDPRST:
	MOV	OTPARA,BX
	RET
;
;  32:SET/GET USER CODE
;
MSTUCD:
	MOV	AL,INPARB
	CMP	AL,0FFH
	JNZ	MSTUCE		;SET MODE
	MOV	AL,USRCOD	;GET USER CODE
	JMPS	MRTCDS
;
MSTUCE:
	AND	AL,01FH
	MOV	USRCOD,AL	;SET USER CODE
	RET
;
;  33:READ RANDOM
;
MREADR:
	CALL	ENTRYR		;ENTRY PROCESS
	CALL	STSYSM		;CHECK & SET USER 0 SYSTEM MODE
	JMP	RDRAND
;
;  34:WRITE RANDOM
;
MWRITR:
	CALL	ENTRYR		;ENTRY PROCESS
	JMP	WTRAND
;
;  35:COMPUTE FILE SIZE
;
MCMPFS:
	CALL	ENTRYR		;ENTRY PROCESS
	JMP	CFLSIZ
;
;  36:SET RANDOM RECORD
;
MSTRRC:
	CALL	STWFCR		;SET FCB TO WORK
	JMP	STRCNT		;SET COUNT
;
;  37:RESET DRIVE
;
MRSTDV:
	MOV	AX,INPARA
	NOT	AX		;GET VECTOR MASK
	PUSH	AX
	MOV	BX,OFFSET LGDSKV
	AND	AX,[BX]		;OFF LOGIN VECTOR
	MOV	[BX],AX
	POP	AX
	MOV	BX,OFFSET RODSKV
	AND	AX,[BX]		;OFF R/O DISK
	MOV	[BX],AX
	RET
;
;  BDOS END PROCESS
;
ENDPRC:
	CMP	FLOMOD,0
	JZ	ENDPRN		;NOT FILE OPERATION
	MOV	BX,INPARA	;FILE OPERATION
	CMP	SYSMOD,060H
	JNZ	ENDPRS		;NOT USER 0 SYSTEM FILE
	OR	BYTE PTR 8[BX],80H ;SET USER 0 SYSTEM FILE MODE
ENDPRS:
	MOV	BYTE PTR [BX],0	;CLEAR ENTRY TYPE
	MOV	AL,ENTTYP
	OR	AL,AL
	JZ	ENDPRN		;DEFAULT DISK
	MOV	[BX],AL		;RESTORE ENTRY TYPE
	MOV	AL,ENTDSK
	MOV	INPARB,AL	;SET DISK
	CALL	MSELDK		;SELECT TO DEFAULT DISK
ENDPRN:
	CMP	AFWFCB,-1
	JNZ	ENDPRW		;NOT FCB SAVED
	CALL	RSTFCB		;RESTORE FCB
ENDPRW:
	MOV	AX,OTPARA	;GET OUTPUT PARAMETER
	MOV	BX,AX
ENDPRE:
	RET
;
;  40:WRITE RANDOM WITH ZERO FILL
;
MWRITZ:
	CALL	ENTRYR
	MOV	RUPCNT,2	;SET COUNT TO WRITE WITH ZERO FILL MODE
	MOV	CL,0		;WRITE MODE
	CALL	RNDDIS		;GET DIRETORY
	JNZ	ENDPRE		;NO DIRECTORY SPACE OR SOME ERROR
	JMP	WTNEXR		;WRITE
;
;  47:CHAIN PROGRAM
;
MCHAIN:
	PUSH	DS
	MOV	CX,128
	MOV	DI,COMBUF+2	;CCP COMMAND BUFFER
	MOV	SI,DMAADD
	MOV	DS,DMASEG
MCHAIL:				;COMMAND COPY LOOP
	LODSB
	STOSB
	OR	AL,AL
	JZ	MCHAIV		;GET END
	LOOP	MCHAIL
MCHAIV:
	MOV	AL,128
	SUB	AL,CL		;GET LENGTH
	POP	DS
	MOV	.COMBUF+1,AL	;SET LENGTH OF COMMAND
	JMP	MSYRSF		;TO RESET SYSTEM
;
;  48:FLUSH BUFFERS
;
MFLUSH:
	RET			;NO PROCESS IN THIS VERSION
;
	DSEG
	ORG	2200H
;
;  DATA AREA
;
JPBIOS	DW	DBIOS		;BIOS CALL ROUTINE OFFSET
SGBIOS	DW	0		;BIOS CALL ROUTINE SEGMENT
;
;  ERROR ROUTINE VECTORS
;
VBADSC	DW	EBADSC		;BAD SECTOR
VSELCT	DW	ESELCT		;SELECT
VRODSK	DW	ERODSK		;R/O DISK
VROFIL	DW	EROFIL		;R/O FILE
;
;  WORK FOR LOAD PROGRAM
;
;  GROUP DESCRIPTION BUFFER    9B * 8
;    0:FORM
;  1-2:LENGTH
;  3-4:ABSOLUTE SEGMENT
;  5-6:MINIMUM SIZE
;  7-8:MAXIMUM SIZE
;
BFGRDC	RW	36
;
BFLDPR:				;PROGRAM LOADING BUFFER
	RS	128
;
DGBASE	DW	0		;DATA GROUP BASE
MODE80	DB	0		;8080 MODEL 1  OTHER 0
;
;  MEMORY CONTROL BLOCK WORK
;
SYSMCB	DW	0		;M-BASE
	DW	0		;M-LENGTH
	DB	0		;M-EXTENT
;
UFCBOF	DW	0		;USER FCB OFFSET FOR FAR READ
LPSTOF	DW	0		;STACK OFFSET SAVE FOR LOAD PROGRAM FUNCTION
LPSTSG	DW	0		;STACK SEGMENT SAVE FOR LOAD PROGRAM
FMODEL	DB	0		;MODEL MODE  -1 8080    0 OTHER
;
;  WORK FOR CONSOLE I/O
;
ECHKIL	DB	0		;ECHO KILL MODE 0 ECHO OUT
PPROMP	DB	0		;PROMPT POSITION
PCARIG	DB	0		;CONSOLE CARRIAGE POSITION
BFCONC	DB	0		;CONSOLE INPUT CODE BUFFER
;
;  WORK FOR DISK I/O
;
DLTFCB	DB	DELCOD		;DELETED FCB DUMMY
RODSKV	DW	0		;R/O DISK VECTOR
LGDSKV	DW	0		;LOGIN VECTOR
;
;  DATA FOR DISK PARAMETERS
;
PNDRCK	DW	0		;DIRECTORY CHECK LEVEL WORK POINT
PNTRAK	DW	0		;TRACK NUMBER WORK POINT
PNSCTR	DW	0		;SECTOR NUMBER WORK POINT
;
;  DISK PARAMETER HEADER COPY
;
DIRBUF	DW	0		;DIRECTORY BUFFER POINTER
PNTDPB	DW	0		;DISK PARAMETER BLOCK POINTER
PNCHSM	DW	0		;CHECK SUM AREA POINTER
PNALMP	DW	0		;ALLOCATION MAP AREA POINTER
;
;  DISK PARAMETER BLOCK COPY
;
SPT	DW	0		;SECTOR / TRACK
BSH	DB	0		;BLOCK SHIFT FACTOR
BLM	DB	0		;BLOCK MASK
EXM	DB	0		;EXTENT MASK
DSM	DW	0		;DISK SIZE MAXIMUM-1
DRM	DW	0		;DIRECTORY SIZE MAXIMUM-1
ALMASK	DW	0		;ALLOCATION MAP RESERVE MASK
CHKSIZ	DW	0		;CHECKED DIRECTORY SIZE
TRKOFF	DW	0		;TRACK OFFSET
PNXTBL	DW	0		;SECTOR TRANSLATION TABLE POINT
;
;  DISK WORK PARAMETERS
;
EXTMOD	DB	0		;FILE EXTENT CLOSE MODE     -1 CLOSED LAST DIR
RWMODE	DB	0		;DISK READ/WRITE MODE  0 WRITE  -1 READ
MDWRIT	DB	0		;WRITE MODE 0 NORMAL  1 DIRECTOR  2 UNALLOC
DIRCOD	DB	0		;DIRECTORY SEARCH CODE  -1 NOT FOUND
RUPCNT	DB	0		;RECORD UP COUNT 0 RANDOM 1 SEQUENTIAL 2 WITH 0
INPARB	DB	0		;INPUT PARAMETER BYTE
DRBSWT	DB	0		;DIRECTORY BIAS FOR WRITE
DSMMOD	DB	0		;DISK SIZE MODE  -1 ONE BYTE    0 TWO BYTES
FLOMOD	DB	0		;FILE OPERATION FUNCTION MODE BY FCB  -1 ON
ENTDSK	DB	0		;DEFAULT DISK IN ENTRY DISK MODE
ENTTYP	DB	0		;ENTRY TYPE SAVE
RECUNT	DB	0		;RECORD COUNT
EXTENT	DB	0		;EXTENT
CURCNT	DB	0,0		;CURRENT RECORD COUNT
TGSECT	DW	0		;TARGET SECTOR OR TARGET BLOCK
BTSECT	DW	0		;BLOCK TOP SECTOR
BISDIR	DB	0		;BIAS IN DIRECTORY
DIRSCT	DW	0		;DIRECTORY SECTOR FOR CHECK SUM BIAS
FCBOFF	DW	0		;FCB OFFSET
FCBSEG	DW	0		;USER FCB SEGMENT
CURSEG	DW	0		;CURRENT SEGMENT BASE
AFWFCB	DB	0		;WORK FCB ACTIVE FLAG
CNFCBC	DB	0		;WORK FCB COPY LENGTH
;
;  MEMORY MANAGEMENT WORK
;
CNTREG	DB	0		;MEMORY REGION BUFFER COUNT
SIZREG	DB	0		;MEMORY REGION TABLE SIZE
TBLREG:				;MEMORY REGION TABLE
	RS	64
;
TBUMCB:				;USED MCB BUFFER AREA  5B*8
	RS	40
;
CNUMCB	DB	0		;USED MCB BUFFER COUNT
PNUMCB	DW	0		;USED MCB BUFFER POINTER
SYSMOD	DB	0		;SYSTEM FILE ACCESS MODE  0 NOT 60H SYSTEM FILE
SYSSRC	DB	0		;WITH USER 0 SEARCH MODE  0 NOT
SYSCNT	DW	0		;MATCH DIRECTORY COUNT BY USER 0
SYSFLG	DB	0		;USER 0 MATCH MODE  -1 USER CODE MISS SEARCH
;
;  ERROR COMMENTS
;
CERROR	DB	'Bdos Err On '
CERRDK	DB	' : $'
CBADSC	DB	'Bad Sector$'
CSELCT	DB	'Select$'
CROFIL	DB	'File '
CRODSK	DB	'R/O$'
;
WKFCB:
	RS	36		;WORKING FCB OR MCB
;
	RS	164
STACK:				;BDOS SYSTEM STACK
;
	DW	0,0,0
INSTSG	DW	0		;ENTRY STACK SEGMENT
INSTOF	DW	0		;ENTRY STACK OFFSET
FLINSD	DB	0		;INSIDE FLAG FOR BDOS CALL
INPARA	DW	0		;INPUT PARAMETER WORD
OTPARA	DW	0		;OUTPUT PARAETER
INDSEG	DW	0		;ENTRY DATA SEGMENT
	DB	0
;
OTPARB	EQU	BYTE PTR OTPARA	;OUTPUT PARAMETER AS BYTE
;
;  SYSTEM DATA AREA
;
DMAADD	DW	0		;DMA OFFESET
DMASEG	DW	0		;DMA SEGMENT
CURDSK	DB	0		;CURRENT DISK
USRCOD	DB	0		;USER CODE
DIRCNT	DW	0		;DIRECTORY COUNTER
DIRCLN	DB	0		;COMPARE LENGTH FOR DIRECTORY MATCH
PTUFCB	DW	0		;USER FCB OR MCB POINT
SGUFCB	DW	0		;USER FCB SEGMENT FOR SEARCH NEXT
LSDRBF	DW	0		;LAST DIRECTORY BUFFER
MODABT	DB	0		;ABORT MODE  0 SIMPLE ABORT NO INTERNAL SETUP
	DB	0
MDCONF	DB	0		;COMPLICATED I/O MODE
	DB	0,0,0,0
LSTTGL	DB	0		;LIST OUT ECHO TOGGLE
CURDRV	DB	0		;CURRENT DRIVE
	RS	40
;
CONWID	DB	80		;CONSOLE WIDTH
PRNWID	DB	0		;PRINTER WIDTH
CONCOL	DB	0		;CONSOLE COLUMN
PRNCOL	DB	0		;PRINTER COLUMN
;
	RS	16
	DB	0
;
;
	END
