;  DISK OPERATING SYSTEM
;  OF MP/M  ( BDOS )
;
;  1980.10.31.  VER.1.0
;  1980.11.11.  VER.1.1
;
;
;  BDOS FUNCTION CODES
;
CRCNIN	EQU	3		;RAW CONSOLE INPUT
CRCNOT	EQU	4		;RAW CONSOLE OUTPUT
CLIST	EQU	5		;LIST OUTPUT
CDKRST	EQU	13		;DISK SYSTEM RESET
CSELDSK	EQU	14		;SELECT DISK
CSETDMA	EQU	26		;SET DMA ADDRESS
CSETUSR	EQU	32		;SET USER NUMBER
;
;  XDOS FUNCTION CODES
;
CMKQU	EQU	134		;MAKE QUEUE
CRDQU	EQU	137		;READ QUEUE
CCRDQU	EQU	138		;CONDITIONAL READ QUEUE
CWTQU	EQU	139		;WRITE QUEUE
CCWTQU	EQU	140		;CONDITIONAL WRITE QUEUE
CDISP	EQU	142		;DISPATCH
CTERM	EQU	143		;TERMINATE PROGRAM
CATACH	EQU	146		;ATTACH CONSOLE
CDETACH	EQU	147		;DETACH CONSOLE
CGSDA	EQU	154		;GET SYSTEM DATA ADDRESS
;
;  OTHER DATA
;
CR	EQU	0DH		;CARRIAGE RETURN
LF	EQU	0AH		;LINE FEED
;
;  LINKS TO XDOS
;
DISP	EQU	$-3		;DISPATCH ENTRY
XDOS	EQU	DISP-3		;EXTENDED ROUTINE ENTRY
;
;  JUMP VECTORS
;
	JMP	XBDOS		;XDOS BDOS ENTRY
	JMP	XIOS		;XIOS LINK
;
;  BDOS INITIALIZE ROUTINE
;  INPUT
;  HL:SYSTEM DATA AREA
;
INITL:
	SHLD	SYSDT		;SAVE SYSTEM DATA AREA
	MOV	C,H		;SAVE SYSTEM DATA AREA TOP
	MVI	L,0FCH
	MOV	A,M
	INX	H
	MOV	H,M		;GET PARAMETER TABLE POINTER
	MOV	L,A
	LXI	D,5
	DAD	D
	SHLD	PDPNT		;SAVE PROCESS DESCRIPTOR POINTER POINT
	MOV	H,C
	MVI	L,3
	MOV	A,M		;GET STACK MODE
	STA	STKMD		;SAVE STACK MODE
	DCR	L
	MOV	L,M		;GET RESTART NUMBER
	MVI	H,0
	MOV	C,L
	DAD	H
	DAD	H
	DAD	H
	MVI	M,0C3H		;SET RESTART ENTRY
	INX	H
	LXI	D,RSTENT
	MOV	M,E		;SET VECTOR
	INX	H
	MOV	M,D
	MVI	A,0C3H
	STA	0
	LXI	H,JWBOOT	;TO WORM BOOT
	SHLD	1		;SET JUMP VECTOR TO BIOS DUMMY
	CALL	SYSIN		;TO SYSTEM INITIALIZE
	EI
	MVI	C,CMKQU
	LXI	D,QMXDISK
	CALL	XDOS		;MAKE "MXDISK  " QUEUE FOR DISK SCHEDULE
	MVI	C,CWTQU
	LXI	D,UMXDISK
	CALL	XDOS		;WRITE ONE PRIVILEGE
	MVI	C,CMKQU
	LXI	D,QMXLIST
	CALL	XDOS		;MAKE "MXLIST  " QUEUE FOR LISTER SCHEDULE
	MVI	C,CWTQU
	LXI	D,UMXLIST
	CALL	XDOS		;WRITE ONE PRIVILEGE
	JMP	MINBD		;DISK RESET
;
;
	DB	'COPYRIGHT (C) 1980,'
	DB	'  DIGITAL RESEARCH '
;
;  USER CODE
;
	DB	0		;OEM CODE
	DB	11		;VERSION 1.1
	DB	1		;MP/M
	DB	0,0,0		;USER CODE
;
;  BDOS SYSTEM STACK BOTTOM
;
INSTK	EQU	$-2		;USER STACK SAVE AREA & STACK
;
;  DUMMY CONSOLE STATUS
;
CONSTD:
	CALL	DBIOS		;GET PROCESS DESCRIPTOR TOP & SET FLAG
	LXI	H,14
	DAD	D
	MOV	D,M		;GET CONSOLE NUMBER
	JMP	CONSTB
;
;  DUMMY CONSOLE INPUT
;
CONIND:
	CALL	DBIOS		;SET FLAG
	MVI	C,CRCNIN
	JMP	XBDOS		;RAW CONSOLE INPUT
;
;  DUMMY CONSOLE OUTPUT
;
CONOTD:
	CALL	DBIOS		;SET FLAG
	MOV	E,C
	MVI	C,CRCNOT
	JMP	XBDOS		;RAW CONSOLE OUTPUT
;
;  DUMMY LIST OUTPUT
;
LISTD:
	MOV	E,C
	MVI	C,CLIST
	CALL	XBDOS		;LIST OUT
;
;  GET PROCESS DESCRIPTOR TOP & SET DUMMY BIOS ENTRY FLAG
;  OUTPUT
;  DE:P.D. TOP
;
DBIOS:
	LHLD	PDPNT
	MOV	E,M
	INX	H
	MOV	D,M
	LXI	H,6
	DAD	D
	MOV	A,M
	ORI	80H		;SET FLAG
	MOV	M,A
	RET
;
;  QUEUE CONTROL BLOCKS
;
QMXDISK:
	DS	2		;QL
	DB	'MXD'		;NAME
	DB	69H,73H,6BH,'  '
	DW	0		;MESSAGE LENGTH
	DW	1		;NUMBER OF MESSAGE
	DS	2		;DQ PROCESS HEADER
	DS	2		;NQ PROCESS HEADER
	DS	2		;NEXT MESSAGE IN
	DS	2		;NEXT MESSAGE OUT
	DS	2		;NUMBER OF MESSAGE TO BE READ
	DS	2		;BUFFER DUMMY
;
UMXDISK:
	DW	QMXDISK		;POINTER TO QCB
QMXLIST:
	DS	2		;QL
	DB	'MXL'
	DB	69H,73H,74H,'  '
	DW	0		;MESSAGE LENGTH
	DW	1		;NUMBER OF MESSAGE
	DS	2		;DQ
	DS	2		;NQ
	DS	2		;NEXT MSG IN
	DS	2		;NEXT MSG OUT
	DS	2		;NUMBER OF MSG
	DS	2		;BUFFER DUMMY
;
UMXLIST:
	DW	QMXLIST		;POINTER TO QCB
;
;  XDOS LINK DATA
;
PDPNT:	DS	2		;PROCESS DESCRIPTOR POINTER POINT
SYSDT:	DS	2		;SYSEM DATA ADDRESS
STKMD:	DS	1		;SYSTEM STACK MODE  0 NOT USED
;
;  BREAK POINT DATA SAVE AREA
;
RSVHL:	DS	2		;HL SAVE AREA
RSVPC:	DS	2		;PC SAVE AREA
;
;  BIOS DUMMY JUMP TABLE
;
	DS	1		;ADJUST TO THE PAGE TOP
	JMP	BOOT		;TO COLD START DUMMY
JWBOOT:				;WARM BOOT POINT
	JMP	WBOOT		;TO WARM BOOT
	JMP	CONSTD		;CONSOLE STATUS
	JMP	CONIND		;CONSOLE INPUT
	JMP	CONOTD		;CONSOLE OUTPUT
	JMP	LISTD		;LIST OUT
;
;  DOS FUNCTION CALL ENTRY FOR XDOS OR BDOS
;  INPUT
;   C:COMMAND CODE
;  DE:INPUT PARAMETER
;
XBDOS:
	MOV	A,C
	ORA	C
	JZ	SRESET		;TERMINATE CURRENT PROCESS
	JP	BDOS		;BDOS FUNCTIONS
	CALL	XDOS		;XDOS FUNCTIONS
	MOV	A,L
	RET
;
;  BDOS FUNCTION NUMBER ERROR
;
BDOSR:
	LXI	H,-1
	MOV	A,L
	RET
;
;  RESTART ENTRY
;
RSTENT:
	DI
	SHLD	RSVHL		;SAVE HL
	POP	H
	SHLD	RSVPC		;SAVE RETURN ADDRESS
	PUSH	PSW
	LHLD	PDPNT		;GET PROCESS DESCRIPTOR POINTER
	MOV	A,M
	INX	H
	MOV	H,M		;GET CURRENT DESCRIPTOR TOP
	MOV	L,A
	MVI	A,15
	ADD	L
	MOV	L,A
	MVI	A,0
	ADC	H
	MOV	H,A
	MOV	A,M		;GET MEMORY SEGMENT
	ADD	A
	ADI	30H		;GET B.P. VECTOR TABLE BIAS
	LHLD	SYSDT		;GET SYSTEM DATA ADDRESS
	MOV	L,A
	MOV	A,M
	INX	H
	MOV	H,M		;GET B.P. VECTOR
	MOV	L,A
	SHLD	BPRTN		;SAVE VECTOR
	POP	PSW
	LHLD	RSVPC		;GET RETURN ADDRESS
	PUSH	H
	LHLD	RSVHL		;RESTORE HL
	JMP	0
BPRTN	EQU	$-2		;JUMP VECTOR
;
;  GET ORIGINAL STACK POINRER
;
GETSP:
	XCHG			;SAVE HL
	POP	H		;GET SP
	SPHL			;SET SP
	XCHG			;RESTORE HL
	RET
;
;  BDOS FUNCTION CALL ENTRY
;
BDOS:
	LDA	STKMD		;GET STACK MODE
	ORA	A
	JZ	BDOSP		;NO USER STACK MODE
	LHLD	PDPNT
	MOV	A,M
	INX	H
	MOV	H,M
	MOV	L,A		;GET P.D. TOP
	MVI	A,15
	ADD	L
	MOV	L,A
	MVI	A,0
	ADC	H
	MOV	H,A
	MOV	A,M		;GET MEMORY SEGMENT
	INR	A
	JZ	BDOSP		;SYSTEM MODE
	DCR	A		;SET STACK FOR USER SYSTEM CALL
	ADD	A
	ADI	50H		;GET BIAS TO STACK VECTOR
	LHLD	SYSDT
	MOV	L,A
	MOV	A,D
	MOV	B,E		;SAVE INPUT PARAMETERS
	MOV	E,M
	INX	H
	MOV	D,M
	LXI	H,0
	DAD	SP		;GET CURRENT STACK
	XCHG
	SPHL			;SET STACK FOR SYSTEM CALL
	PUSH	D		;SAVE USER STACK POINTER
	LXI	H,GETSP
	PUSH	H		;SAVE STACK RESTORE ROUTINE POINT
	MOV	D,A
	MOV	E,B		;RESTORE INPUT PARAMETER
;
BDOSP:
	MOV	A,C
	CPI	12
	JC	BDOSS		;SIMPLE I/O OPERATIONS
	CPI	40
	JNC	BDOSR		;FUNCTION NUMBER ERROR
	PUSH	D		;FILE OPERATIONS
	PUSH	B
	CALL	GETPD
	LXI	B,6
	DAD	B
	MOV	A,M
	ANI	80H		;GET DUMMY BIOS CALL MODE
	CZ	MSNCN		;CHECK CONSOLE
	MVI	C,CRDQU
	LXI	D,UMXDISK
	CALL	XDOS		;WAIT FOR GETTING FILE OPERATION PRIVILEGE
	CALL	GETPD
	LXI	B,20
	DAD	B
	MOV	E,M
	INX	H
	MOV	D,M		;GET CURRENT DMA OF PROCESS DESCRIPTOR
	PUSH	H
	XCHG
	SHLD	DMADD		;SAVE DMA ADDRESS
	MOV	B,H
	MOV	C,L
	CALL	SETDM		;SET DMA ADDRESS
	POP	H
	INX	H
	PUSH	H
	MOV	A,M		;GET DISK SELECT CODE OF P.D.
	RRC
	RRC
	RRC
	RRC
	ANI	0FH
	MOV	E,A
	MVI	C,CSELDSK
	LDA	NDRIV		;GET CURRENT DISK
	CMP	E
	CNZ	BDOST		;SELECT DISK
	POP	H
	PUSH	H
	MOV	A,M
	ANI	0FH
	MOV	E,A
	MVI	C,CSETUSR
	LDA	MDUSR		;GET CURRENT USER CODE
	CMP	E
	CNZ	BDOST		;SET USER CODE
	POP	H
	INX	H
	PUSH	H
	LXI	D,DIRCT
	CALL	COPYP		;COPY DISK PARAMETERS
	POP	H
	POP	B
	POP	D
	PUSH	H
	CALL	BDOST		;MAKE TARGET COMMAND
	POP	D
	PUSH	PSW
	PUSH	H
	LXI	H,DIRCT
	CALL	COPYP		;RESTORE DISK PARAMETERS
	MVI	C,CWTQU
	LXI	D,UMXDISK
	CALL	XDOS		;RELEASE THE FILE OPERATION PRIVILEGE
	POP	H
	POP	PSW
	RET
;
;  MAIN ROUTINE OF BDOS
;  INPUT
;   C:NUMBER OF BDOS FUNCTION
;  DE:INPUT PARAMETER
;  OUTPUT
;   A:OUTPUT PARAMETER   ONE BYTE DATA OR LOWER DATA
;   B:OUTPUT PARAMETER   HIGHER DATA WHEN DOUBLE BYTES
;  HL:PARAMETER OF DOUBLE BYTES
;
BDOST:
	XCHG
	SHLD	INPAR		;SAVE INPUT PARAMETER
	XCHG
	MOV	A,E
	STA	OUTSP		;SET ONE BYTE PARAMETER
	LXI	H,0
	SHLD	OTPAR		;CLEAR OUTPUT PARAMETERS
	DAD	SP		;GET USER STACK POINTER
	SHLD	INSTK		;SAVE USER STACK POINTER
	LXI	SP,INSTK	;SET BDOS STACK
	XRA	A
	STA	ENTYP		;ENTRY TYPE
	STA	FLMOD		;CLEAR FILE COMMAND MODE
	STA	DIRMD		;CLEAR DIRECTORY BUFFER MODE
	LXI	H,BDOSE		;COMMAND END ROUTINE
	PUSH	H		;SET RETURN ADDRESS TO END ROUTINE
BDOSS:				;SIMPLE I/O ROUTINE ENTRY
	MOV	A,C
	MOV	C,E		;SAVE INPUT DATA
	MOV	B,D
	LXI	H,MINDX		;MAIN INDEX OF FUNCTION
	MOV	E,A
	MVI	D,0
	DAD	D
	DAD	D
	MOV	E,M
	INX	H
	MOV	D,M		;GET EACH FUNCTION ROUTINE ADDRESS
	XCHG
	PCHL			;TO EACH ROUTINE
;
;  MAIN INDEX OF BODS FUNCTIONS
;
MINDX:
	DW	BOOT		;SYSTEM RESET   NOT USED	0
	DW	MCNIN		;CONSOLE INPUT
	DW	MCNOT		;CONSOLE OUTPUT
	DW	MRCNIN		;RAW CONSOLE INPUT
	DW	MRCNOT		;RAW CONSOLE OUTPUT
	DW	LIST		;LIST OUTPUT			5
	DW	MDCIO		;DIRECT CONSOLE I/O
	DW	MGIOB		;GET I/O BYTE
	DW	MSIOB		;SET I/O BYTE
	DW	MBFPR		;PRINT STRING
	DW	MBFRD		;READ CONSOLE BUFFER		10
	DW	MSNCN		;GET CONSOLE STATUS
	DW	MVSNM		;RETURN VERSION NUMBER
	DW	MINBD		;RESET DISK SYSTEM
	DW	MDVSL		;SELECT DISK
	DW	MOPEN		;OPEN FILE			15
	DW	MCLOS		;CLOSE FILE
	DW	MSERH		;SEARCH FOR FIRST
	DW	MSENX		;SEARCH FOR NEXT
	DW	MDELE		;DELETE FILE
	DW	MRDNX		;READ SEQUENTIAL		20
	DW	MWTNX		;WRITE SEQUENTIAL
	DW	MAKFL		;MAKE FILE
	DW	MRNAM		;RENAME FILE
	DW	MLIVC		;RETURN LOG-IN VECTOR
	DW	MNDIV		;RETURN CURRENT DISK		25
	DW	MSDMA		;SET DMA ADDRESS
	DW	MALOC		;GET ALLOCATION MAP POINT
	DW	MWTPR		;SET DISK R/O VECTOR
	DW	MGWPR		;GET DISK R/O VECTOR
	DW	MSFAT		;SET FILE ATTRIBUTES		30
	DW	MGDPR		;GET DISK PARAMETER ADDRESS
	DW	MUSER		;SET OR GET USER CODE
	DW	MRDRN		;READ RANDOM
	DW	MWTRN		;WRITE RANDOM
	DW	MCFSZ		;COMPUTE FILE SIZE		35
	DW	MSRRC		;SET RANDOM RECODE
	DW	MRSDV		;RESET DISK
	DW	MACDV		;ACCESS DRIVE
	DW	MFRDV		;FREE DRIVE
;
;   1:CONSOLE INPUT
;
MCNIN:
	CALL	CONAC		;ACTIVATE CONSOLE
	CALL	CONCI		;CONSOLE INPUT
	MOV	L,A
	RET
;
;   2:CONSOLE OUTPUT
;
MCNOT:
	CALL	CONAC		;ACTIVAE CONSOLE
	JMP	PRINS
;
;   3:RAW CONSOLE INPUT
;
MRCNIN:
	CALL	GETCM		;GET CONSOLE MODE
	JMP	MDCIN
;
;   4:RAW CONSOLE OUTPUT
;
MRCNOT:
	CALL	GETCM		;GET CONSOLE MODE
	JMP	CONOTB
;
;   6:DIRECT CONSOLE I/O
;  INPUT
;   C:-1 INPUT  -2 GET STATUS  OTHER OUTPUT
;
MDCIO:
	CALL	CONAC		;ACTIVATE CONSOLE
	MOV	A,C
	INR	A
	JZ	MDCIN		;INPUT MODE
	INR	A
	JZ	MDCIS		;STATUS MODE
	JMP	CONOTB		;OUTPUT MODE
;
MDCIN:				;INPUT MODE
	LXI	H,INCON
	CALL	GETCP
	MOV	A,M		;GET BUFFERED CODE
	MVI	M,0		;CLEAR BUFFER
	ORA	A
	CZ	CONINB		;GET CODE IF NOT BUFFERED
	MOV	L,A
	RET
MDCIS:				;STATUS MODE
	CALL	CONSTB
	MOV	L,A
	RET
;
;   7:GET I/O BYTE
;
MGIOB:				;NOT IMPREMENTED MOW
	XRA	A
	MOV	L,A
	RET
;
;   9:PRINT STRING
;
MBFPR:
	CALL	CONAC		;ACTIVATE CONSOLE
	JMP	BUFPR
;
;  10:READ CONSOLE BUFFER
;
MBFRD:
	CALL	CONAC
	JMP	STRED
;
;  11:GET CONSOLE STATUS
;
MSNCN:
	CALL	GETCM		;GET CONSOLE MODE
	JZ	MSNCS		;NOW ACTIVE
	MVI	C,CDISP
	CALL	XDOS		;DISPATCH
	XRA	A
	MOV	L,A		;NOT READY
	RET
;
MSNCS:				;NOW ACTIVE
	CALL	CONIS
	MOV	L,A
MSIOB:				;DUMMY FOR SET I/O BYTE
	RET
;
;  ERROR COMMENT OUT ROUTINES
;
; DISK READ WRITE ERROR
;
EFLRW:
	LXI	H,CFLRW		;"BAD SECTOR"
	JMP	ERPRN
;
;  DRIVE SELECT ERROR
;
EDRIV:
	LXI	H,CDRIV		;"SELECT"
	JMP	ERPRN
;
;  DISK WRITE PROTECT ERROR
;
EDKCG:
	LXI	H,CDKCG		;"R/O"
	JMP	ERPRN
;
;  FILE WRITE PROTECT ERROR
;
EFLRO:
	LXI	H,CDKCH		;"FILE R/O"
;
;  ERROR COMMENT OU & KEY RESPONSE WAIT
;  INPUT
;  HL:ADDRESS OF COMMENT
;
ERPRN:
	PUSH	H		;SAVE COMMENT POINT
	CALL	GETPD		;GET PROCESS DESCRIPTOR POINT
	LXI	D,14
	DAD	D
	MOV	D,M		;GET CONSOLE NUMBER
	CALL	CRLFM		;CR & LF
	LDA	NDRIV		;GET DISK NUMBER
	ADI	'A'
	STA	CERPN+12	;SET CODE TO COMMENT
	LXI	B,CERPN
	CALL	BFPRN		;"BDOS ERR ON "X": "
	POP	B
	CALL	BFPRN		;PRINT EACH COMMENT
	LXI	H,-1
	SHLD	OTPAR		;SET OUTPUT PARAMETER
	CALL	GETPD		;GET P.D.POINT
	LXI	D,15
	DAD	D
	MOV	A,M		;GET MEMORY SEGMENT
	INR	A
	JZ	BDOSF		;NOW SYSTEM MODE
;
;  SYSTEM RESET     TERMINATION OF CURRENT PROCESS
;
SRESET:
	MVI	C,CTERM
	LXI	D,0
	JMP	XDOS		;TERMINATE
;
;  ERROR COMMENT CODES
;
CERPN:				;"BDOS ERR ON  : "
	DB	42H,64H,6FH,73H,20H,45H,72H,72H
	DB	20H,4FH,6EH,'  : $'
CFLRW:				;"BAD SECTOR"
	DB	42H,61H,64H,20H
	DB	53H,65H,63H,74H,6FH,72H,'$'
CDRIV:				;"SELECT"
	DB	53H,65H,6CH,65H,63H,74H,'$'
CDKCH:				;"FILE R/O"
	DB	46H,69H,6CH,65H,' '
CDKCG:				;"R/O"
	DB	'R/O$'
;
;  GET PROCESS DESCRIPTOR POINT
;  OUTPUT
;  HL:P.D. POINT
;
GETPD:
	LHLD	PDPNT
	MOV	A,M
	INX	H
	MOV	H,M
	MOV	L,A		;GET P.D. POINT
	RET
;
;  GET MEMORY SEGMENT
;  OUTPUT
;   A:DATA
;  HL:CODE POINTER
;
GETMS:
	CALL	GETPD		;GET P.D. POINT
	MVI	A,15
	ADD	L
	MOV	L,A
	MVI	A,0
	ADC	H
	MOV	H,A		;GET MEMORY SEGMENT POINT
	MOV	A,M
	RET
;
; GET CONSOLE MODE
;  OUTPUT
;   D:CONSOLE NUMBER
;  ZF:ON CURRENT P.D.
;
GETCM:
	CALL	GETPD
	XCHG
	LXI	H,14
	DAD	D
	MOV	A,M		;GET CONSOLE
	PUSH	PSW
	PUSH	B
	LHLD	PDPNT
	LXI	B,15
	DAD	B
	ADD	A
	MOV	C,A
	MVI	B,0
	DAD	B		;GET P.D. POINT OF CURRENT CONSOLE
	MOV	A,M
	CMP	E
	JNZ	$+6		;NOT CURRENT P.D.
	INX	H
	MOV	A,M
	CMP	D		;CHECK CURRENT P.D.
	POP	B
	POP	D
	MVI	E,0
	RET
;
;  ACTIVATE CONSOLE
;  OUTPUT
;   E:-1 FOR DETACH WAIT
;
CONAC:
	CALL	GETCM		;CONSOLE MODE
	MVI	E,-1
	RZ			;CURRENT P.D.
	PUSH	B
	PUSH	D
	MVI	C,CATACH
	CALL	XDOS		;ATTACH CONSOLE
	POP	D
	POP	B
	RET
;
;  GET CONSOLE DATA POSITION
;  INPUT
;  HL:DATA TOP POINT
;   D:CONSOLE NUMBER
;  OUTPUT
;  HL:NOW CONSOLE DATA POINT
;
GETCP:
	PUSH	PSW
	MOV	A,D
	ADD	L
	MOV	L,A
	MVI	A,0
	ADC	H
	MOV	H,A
	POP	PSW
	RET
;
;  CONSOLE STATUS
;
CONST:
	PUSH	D
	CALL	CONSTB
	POP	D
	RET
;
;  CONSOLE INPUT
;  OUTPUT
;   A:CODE
;  ZF:OFF  DUMMY BIOS CALL EXIST
;
CONIN:
	PUSH	D
	CALL	GETPD
	LXI	D,6
	DAD	D
	POP	D
	PUSH	D
	MOV	A,M
	ANI	80H		;GET DUMMY BIOS CALL MODE
	PUSH	PSW
	CALL	CONINB
	MOV	B,A
	POP	PSW
	MOV	A,B
	POP	D
	RET
;
;  CONSOLE OUTPUT
;
CONOT:
	PUSH	D
	CALL	CONOTB
	POP	D
	RET
;
;  CONSOLE I/O ROUTINES
;
;  CONSOLE INPUT WITH CONSOLE INTERRUPT CODE CHECK
;  OUTPUT
;   A:CODE OF INPUT
;
CONSI:
	LXI	H,INCON		;CONSOLE INTERRUPT CODE
	CALL	GETCP
	MOV	A,M		;GET CODE
	MVI	M,0		;CLEAR CODE
	ORA	A
	RNZ			;NOW CODE EXISTS
	CALL	CONIT		;CHECK INPUT
	JMP	CONSI
;
;  CONSOLE INPUT WITHOUT ECHO BACK OF CONTROL CODE
;
CONCI:
	CALL	CONSI		;CONSOLE INPUT
	CALL	CONCK		;CONTROL CODE CHECK
	RC			;CONTROL CODE
	PUSH	PSW		;NORMAL CODE
	MOV	C,A
	CALL	PRINS		;PRINT WITH TAB
	POP	PSW
	RET
;
;  CONTROL CODE CHECK EXCEPT CR,LF,HTAB,BACK SPACE
;  INPUT
;   A:CODE
;  OUTPUT
;  CF:ON CONTROL CODE
;
CONCK:
	CPI	0DH		;CARRIAGE RETURN
	RZ
	CPI	0AH		;LINE FEED
	RZ
	CPI	09H		;HORIZONTAL TAB
	RZ
	CPI	08H		;BACK SPACE
	RZ
	CPI	20H		;SPACE
	RET
;
;  CHECK CONSOLE STATUS
;  INPUT
;   D:CONSOLE NUMBER
;   E:0 SYSTEM POLL MODE
;  OUTPUT
;   0:NOT READY
;   1:READY
;
CONIS:
	CALL	CONST		;GET CONSOLE STATUS
	ANI	1
	LXI	H,INCON
	CALL	GETCP		;GET INPUT DATA POINT
	JNZ	CONIR		;READY
	MOV	A,M		;NOT READY NOW
	ORA	A		;CHECK STORED CODE
	RZ			;NOT READY
	JMP 	CONID		;READY
;
CONIR:				;GET NEXT CODE
	MVI	M,0		;CLEAR BUFFER
;
CONIT:
	CALL	CONIN		;CONSOLE INPUT
	JNZ	CONIE		;DUMMY BIOS CALLED
	CPI	13H		;CONTROL-S
	JNZ	CONIF
	CALL	CONIN		;FREEZE
	CPI	03H		;CONTOL-C
	JZ	CONIA		;ABORT
	XRA	A
	RET
;
CONIF:
	CPI	04H		;CONTROL-D
	JNZ	CONIC
	PUSH	D		;DETACH
	MVI	C,CDETACH
	CALL	XDOS		;DETACH CONSOLE & WAIT
	POP	D
	MOV	A,E
	ORA	A
	RZ			;POLLING MODE
	PUSH	D		;ATTACHED ENYRT MODE
	MVI	C,CATACH
	CALL	XDOS		;ATTACH CONSOLE
	POP	D
	LXI	B,MATACH
	CALL	BFPRN		;"ATTACH: "
	CALL	GETPD
CONIV:				;PRINT PROGRAM NAME
	LXI	B,6
	DAD	B
	MVI	E,8
CONIP:				;PROCESS NAME PRINT LOOP
	MOV	C,M
	PUSH	H
	PUSH	D
	CALL	CONOT
	POP	D
	POP	H
	INX	H
	DCR	E
	JNZ	CONIP
	INR	E
;
;  CR & LF OF SYSTEM MODE
;
CRLFM:
	MVI	C,0DH		;CR
	CALL	CONOT
	MVI	C,0AH		;LF
	CALL	CONOT
	XRA	A
	RET
;
CONIC:
	CPI	03H		;CONTROL-C
	JNZ	CONIE
;
CONIA:				;ABORT
	CALL	GETMS		;GET MEMORY SEGMENT
	INR	A
	RZ			;SYSTEM MODE
	LXI	B,MABORT
	CALL	CONAB		;CHECK ABORT
	JZ	SRESET		;TERMINATE PROCESS
	XRA	A
	RET
;
CONIE:
	LXI	H,INCON
	CALL	GETCP		;GET DATD POINT
	MOV	M,A		;SET INPUT CODE
CONID:
	MVI	A,1		;SET READY FLAG
	RET
;
;  CHECK ABORT
;
CONAB:
	CALL	BFPRN		;COMMENT OUT
	CALL	CONIN		;GET INPUT FOR CHECK
	PUSH	PSW
	MOV	C,A
	CALL	CONOT		;ECHO BACK
	MVI	C,CR
	CALL	CONOT
	MVI	C,LF
	CALL	CONOT
	POP	PSW
	ANI	5FH
	CPI	'Y'
	RET
;
;  PRINT TO CONSOLE
;  INPUT
;   C:CODE
;
PRINT:
	LXI	H,ECHKL
	CALL	GETCP
	MOV	A,M		;GET ECHO KILL MODE
	ORA	A
	JNZ	PRINK		;KILL MODE
	PUSH	B
	CALL	CONOT		;CONSOLE OUTPUT
	CALL	CONIS		;CHECK CONSOLE STATUS
	POP	B
	PUSH	B
	PUSH	D
	LXI	H,OTLST
	CALL	GETCP
	MOV	A,M		;GET LSITER ECHO MODE
	ANI	1
	CNZ	LIST
	POP	D
	POP	B
PRINK:
	MOV	A,C
	LXI	H,PCARI
	CALL	GETCP		;GET CARRIAGE POSITION DATA POINT
	CPI	7FH
	RZ			;DELETE CODE
	INR	M		;UP OF CARRIAGE POSITION COUNTER
	CPI	20H
	RNC			;NORMAL CODE
	DCR	M		;CONTROL CODE
	MOV	A,M
	ORA	A
	RZ			;ZERO POSITION
	MOV	A,C
	CPI	8		;BACK SPACE
	JNZ	$+5
	DCR	M		;DOWN OF COUNT
	RET
;
	CPI	0AH		;NEW LINE
	RNZ
	MVI	M,0		;CLEAR
	RET
;
;  PRINT WITH CONTROL CODE VISIBLE
;  INPUT
;   C:CODE
;
PRINC:
	MOV	A,C
	CALL	CONCK		;CONTROL CODE CHECK
	JNC	PRINS		;NORMAL CODE
	PUSH	PSW		;CONTROL CODE
	MVI	C,5EH		;UPER ARROW IS CONTROL CODE MARK
	CALL	PRINT
	POP	PSW
	ORI	40H		;MAKE TO VISIBLE CODE
	MOV	C,A
;
;   CONSOLE OUTPUT
;  INPUT
;   C:CODE
;
PRINS:
	MOV	A,C
	CPI	09H		;HORIZONTAL TAB
	JNZ	PRINT		;OTHER CODE
	MVI	C,' '
	CALL	PRINT		;SPACE PRINT
	CALL	GETCR		;GET CARRIAGE POSITION
	ANI	07H		;CHECK CARRIAGE POSITION
	JNZ	$-10		;TO TAB LOOP
	RET
;
;  BACK SPACE WITH ERASE ON CRT
;
BACKS:
	CALL	BACK
	MVI	C,' '
	CALL	CONOT		;ERASE
BACK:
	MVI	C,08H
	JMP	CONOT
;
;  PRINT "#" & CRLF FOR LINE CANCEL (CONTOL-U OR ...)
;
NCRLF:
	MVI	C,'#'
	CALL	PRINT
	CALL	CRLF
NCRLL:				;LOOP FOR MOVING TO PROMPT POSITION
	CALL	GETCR		;GET CARRIAGE POSITION
	LXI	H,PPROM
	CALL	GETCP		;GET PROMPT POSITION
	CMP	M		;COMPARE WITH PROMPT POSITION
	RNC
	MVI	C,' '		;MOVE TO PROMPT POSITION
	CALL	PRINT
	JMP	NCRLL
;
;  CARRIAGE RETURN & LINE FEED
;
CRLF:
	MVI	C,0DH		;CARRIAGE RETURN
	CALL	PRINT
	MVI	C,0AH		;LINE FEED
	JMP	PRINT
;
;  BUFFERED STRING PRINT  END BY "$"
;  INPUT
;  BC:BUFFER TOP ADDRESS
;
;  FOR SYSTEM MODE
;
BFPRN:
	LDAX	B		;GET CODE
	CPI	'$'
	RZ			;END
	PUSH	B
	MOV	C,A
	CALL	CONOT		;PRINT ONE CODE
	POP	B
	INX	B
	JMP	BFPRN
;
;  FOR BDOS FUNCTION MODE
;
BUFPR:
	LDAX	B		;GET CODE
	CPI	'$'
	RZ			;END CODE
	INX	B
	PUSH	B
	MOV	C,A
	CALL	PRINS		;PRINT WITH TAB
	POP	B
	JMP	BUFPR		;TO NEXT CODE
;
;  READ CONSOLE BUFFER
;  INPUT
;  BC:BUFFER POINTER
;
	POP	B
STRED:
	PUSH	B
	CALL	GETCR		;GET	CARRIAGE POSITION
	LXI	H,PPROM
	CALL	GETCP		;GET PROMPT POSITION
	MOV	M,A		;SET PROMPT POSITION
	MOV	H,B
	MOV	L,C
	MOV	C,M		;GET MAXIMUM BUFFER LENGTH
	INX	H
	PUSH	H		;SAVE POINTER OF CURRENT LENGTH COUNTER
	MVI	B,0		;RESET COUNTER
STREL:				;ONE CHARACTER LOOP
	PUSH	B
	PUSH	H
	CALL	CONSI
	ANI	7FH		;CUT OF PARITY
	POP	H
	POP	B
	CPI	0DH		;CARRIAGE RETURN
	JZ	STREE		;GET END CODE
	CPI	0AH		;LINE FEED
	JZ	STREE		;GET END CODE
	CPI	08H		;BACK SPACE
	JNZ	STREK
	MOV	A,B		;BACK SPACE
	ORA	A
	JZ	STREL		;COUNT IS ZERO SO NO MEANING
	DCR	B
	CALL	GETCR
	LXI	H,ECHKL
	CALL	GETCP
	MOV	M,A		;SAVE NOW POSITION
	JMP	STREI
STREK:
	CPI	7FH		;RUBOUT IS LAST CHARACTER DELETE
	JNZ	STREA
	MOV	A,B
	ORA	A		;COUNTER CHECK
	JZ	STREL		;THERE IS NO CHARACTER
	MOV	A,M		;GET LAST CODE
	DCR	B		;DOWN OF POINTER & COUNTER
	DCX	H
	JMP	STRES		;TO PRINT
STREA:
	CPI	05H		;CONTROL-E "ONLY LINE CHANGE"
	JNZ	STREB
	PUSH	B
	PUSH	H
	CALL	CRLF		;LINE CHANGE
	LXI	H,PPROM
	CALL	GETCP
	XRA	A
	MOV	M,A		;PROMPT POSITION TO TOP
	JMP	STREL+2		;TO NEXT READ
STREB:
	CPI	10H		;CONTROL-P "LIST MODE CHANGE"
	JNZ	$+8
	MVI	A,1
	JMP	$+10
;
	CPI	11H		;CONTROL-Q "OBTAIN OWNERSHIP OF PRINTER"
	JNZ	STREC
	MVI	A,80H
	PUSH	H
	PUSH	B
	PUSH	D
	LXI	H,OTLST
	CALL	GETCP
	XRA	M
	MOV	M,A		;CHANGE LIST ECHO MODE
	PUSH	H
	JNZ	STRET		;TO ECHO MODE
STREQ:				;CUT OFF OF ECHO MODE
	MVI	M,0
	MVI	C,CCWTQU
	LXI	D,UMXLIST
	CALL	XDOS		;SET QUEUE
	POP	H
	JMP	STREP
;
STRET:				;TO LIST ECHO MODE
	CPI	81H
	JZ	STREQ		;^Q & ^P THEN OFF THE MODE
	MVI	C,CCRDQU
	LXI	D,UMXLIST
	CALL	XDOS		;GET QUEUE
	MOV	A,L
	ORA	A
	POP	H
	JZ	STREP		;GET MODE
	MVI	M,0		;NOW BUSY
	LXI	B,MPRBSY
	POP	D
	PUSH	D		;GET & SAVE CONSOLE NUMBER
	CALL	BFPRN		;"PRINTER BUSY"
STREP:
	POP	D
	POP	B
	POP	H
	JMP	STREL		;TO NEXT
STREC:
	CPI	18H		;CONTROL-X CANCEL OF NOW SET
	JNZ	STREY
	POP	H
STREX:				;CANSEL BY ERASE
	LXI	H,PPROM
	CALL	GETCP
	MOV	A,M		;GET PROMPT
	LXI	H,PCARI
	CALL	GETCP
	CMP	M
	JNC	STRED-1		;NOW TO TOP
	DCR	M
	CALL	BACKS		;ERASE BACK
	JMP	STREX		;ERASE LOOP
STREY:
	CPI	15H		;CONTROL-U "CANCEL OF NOW SET"
	JNZ	STREF
	CALL	NCRLF		;"#" & CR,LF
	POP	H
	JMP	STRED-1		;TO START POINT
STREF:
	CPI	12H		;CONTROL-R "CHANGE LINE & PRINT LEFT CODES"
	JNZ	STREN		;NORMAL CODE
STREI:
	PUSH	B
	CALL	NCRLF		;"#" & CR,LF
	POP	B
	POP	H		;GET READ BUFFER TOP +1
	PUSH	H
	PUSH	B
STREG:				;PRINT LEFT CODES
	MOV	A,B		;COUNT OF LEFT CODES
	ORA	A
	JZ	STREH		;END OF PRINT
	INX	H
	MOV	C,M		;GET CODE
	DCR	B
	PUSH	B
	PUSH	H
	CALL	PRINC		;PRINT WITH CONTROL CODE VISIBLE
	POP	H
	POP	B
	JMP	STREG		;TO NEXT CHARACTER PRINT
STREH:
	PUSH	H
	LXI	H,ECHKL
	CALL	GETCP
	MOV	A,M		;GET ECHO KILL MODE
	ORA	A
	JZ	STREL+2		;NORMAL MODE
	LXI	H,PCARI
	CALL	GETCP
	SUB	M
	LXI	H,ECHKL
	CALL	GETCP
	MOV	M,A		;SET CLEAR COUNT
	CALL	BACKS		;BACK TO LAST POSITION
	LXI	H,ECHKL
	CALL	GETCP
	DCR	M
	JNZ	$-10
	JMP	STREL+2
STREN:				;NORMAL CODES
	INX	H
	MOV	M,A		;SET CODE & POINTER UP
	INR	B		;COUNTER UP
STRES:				;ECHO PRINT
	PUSH	B
	PUSH	H
	MOV	C,A
	CALL	PRINC		;PRINT WITH CONTROL CODE VISIBLE
	POP	H
	POP	B
	MOV	A,B
	CMP	C
	JC	STREL		;TO NEXT READ
STREE:
	POP	H		;BUFFER FULL OR END
	MOV	M,B		;SET COUNT
	POP	H
	MVI	C,0DH
	JMP	PRINT		;PRINT CARRIAGE RETURN & END
;
;  GET CARRIAGE POSITION
;  OUTPUT
;   A:PSITION COUNT
;  HL:DATA POINTER
;
GETCR:
	LXI	H,PCARI
	CALL	GETCP
	MOV	A,M
	RET
;
;  COMMENTS
;
MPRBSY:				;PRINTER BUSY
	DB	CR,LF,50H,72H,69H,6EH,74H
	DB	65H,72H,20H,42H,75H,73H,79H
	DB	2EH,CR,LF,24H
;
MABORT:				;ABORT (Y/N) ?
	DB	CR,LF,41H,62H,6FH,72H,74H
	DB	' (Y/N) ?$'
;
MATACH:				;ATTACH:
	DB	CR,LF,41H,74H,74H,61H
	DB	63H,68H,3AH,24H
;
;  DATA AREA FOR BASIC I/O
;
ECHKL:	DB	0,0,0,0,0,0,0,0	;ECHO KILL MODE COUNT
	DB	0,0,0,0,0,0,0,0
PPROM:	DB	0,0,0,0,0,0,0,0	;PROMPT POSITION
	DB	0,0,0,0,0,0,0,0
PCARI:	DB	0,0,0,0,0,0,0,0	;CONSOLE CARRIAGE POSITION COUNTER
	DB	0,0,0,0,0,0,0,0
OTLST:	DB	0,0,0,0,0,0,0,0	;LIST OUTPUT MODE  0 NOT OUT
	DB	0,0,0,0,0,0,0,0
INCON:	DB	0,0,0,0,0,0,0,0	;CONSOLE INTERRUPT CODE
	DB	0,0,0,0,0,0,0,0
MDUSR:	DB	0		;USER CODE
NDRIV:	DB	0		;DISK NUMBER
INPAR:	DW	0000H		;INPUT PARAMETER BUFFER
OTPAR:	DW	0000H		;OUTPUT PARAMETER BUFFER
;
;  DISK OPERATION ROUTINES
;
;  COPY PROCESS DESCRIPTOR PARAMETERS
;
COPYP:
	MVI	C,5
	XCHG
;
;  COPY DATA
;  INPUT
;  DE:SOURCE POINTER
;  HL:DESTINATION POINTER
;   C:COUNT
;
COPY:
	INR	C
	DCR	C
	RZ
	LDAX	D
	MOV	M,A
	INX	D
	INX	H
	JMP	COPY+1
;
;  SELECT & GET DISK PARAMETER
;  OUTPUT
;  ZF:ON  NOT AVAILABLE DISK
;
GDTBL:
	LDA	NDRIV		;GET CURRENT DISK
	MOV	C,A
	CALL	SELDK		;SELECT DISK
	MOV	A,H
	ORA	L
	RZ			;NOT AVAILABLE DISK
	MOV	E,M
	INX	H
	MOV	D,M		;GET TRANSLATE TABLE POINTER
	INX	H
	SHLD	PHLEV		;GET TEMPORARY FOR HASH CHECK LEVEL
	INX	H
	INX	H
	SHLD	PTRAK		;GET TRACK NUMBER AREA
	INX	H
	INX	H
	SHLD	PSECT		;GET SECTOR CALCULATION AREA
	INX	H
	INX	H
	XCHG
	SHLD	XTL		;SAVE TRANSLATE TABLE POINT
	LXI	H,DIRBF		;DISK PARAMETER HEADER SAVE AREA
	MVI	C,8
	CALL	COPY		;COPY DISK PARAMETER HEADER
	LHLD	DPB		;GET DISK PARAMETER BLOCK POINTER
	XCHG			;DISK PARAMETER BLOCK SAVE AREA
	LXI	H,SPT
	MVI	C,15
	CALL	COPY		;COPY DISK PARAMETER BLOCK
	LHLD	DSM		;GET MAXIMUM DISK BLOCK SIZE
	MOV	A,H
	LXI	H,DSMMD		;DISK SIZE MODE
	MVI	M,-1
	ORA	A
	JZ	$+5		;<256
	MVI	M,0		;>255
	MVI	A,-1
	ORA	A		;ZF OFF FOR NORML END
	RET
;
;  SET UP FOR DIRECTORY READ
;
DRDMD:
	CALL	HOME		;TO HOME POSITION
	LXI	H,OFF
	MOV	C,M
	INX	H
	MOV	B,M		;GET OFF SET
	CALL	SETRK		;SEEK TO DIRECTORY TOP
	XRA	A
	LHLD	PTRAK		;GET TRACK BUFFER POINTER
	MOV	M,A
	INX	H
	MOV	M,A		;CLEAR TRACK NUMBER
	LHLD	PSECT		;GET SECTOR BUFFER POINTER
	MOV	M,A
	INX	H
	MOV	M,A		;CLEAR SECTOR CALCULATE AREA
	RET
;
;  ONE SECTOR READ
;
FREAD:
	CALL	READ		;READ BY BIOS ROUTINE
	ORA	A
	JNZ	EFLRW		;ERROR
	RET
;
;  ONE SECTOR WRITE
;
FWRIT:
	CALL	WRITE		;WRITE BY BIOS ROUTINE
	ORA	A
	JNZ	EFLRW		;ERROR
	RET
;
;  SET DIRECTORY TRACK & SECTOR
;
SDIRT:
	LHLD	DIRCT		;DIRECTORY COUNTER
	MVI	C,2
	CALL	DSHFR		;1/4
	SHLD	TSECT		;SAVE TO TARGET SECTOR BUFFER
	SHLD	DIRSC		;SAVE TO DIRECTORY SECTOR BUFFER
;
;  TRACK & SECTOR SET FROM LOGICAL
;  "TSECT"  TARGET SECTOR NUMBER
;
TSSET:
	LXI	H,TSECT
	MOV	C,M
	INX	H
	MOV	B,M		;GET TARGET SECTOR
	LHLD	PSECT		;GET SECTOR BUFFER POINTER
	MOV	E,M
	INX	H
	MOV	D,M		;GET CURRENT SECTOR
	LHLD	PTRAK		;GET TRACK BUFFER POINTER
	MOV	A,M
	INX	H
	MOV	H,M
	MOV	L,A		;GET CURRENT TRACK
TSSEL:				;TRACK COUNT DOWN LOOP
	MOV	A,C
	SUB	E
	MOV	A,B
	SBB	D		;COMPARE SECTOR COUNT WITH TARGET SECTOR
	JNC	TSSES		;UNDER SO CHECK COUNT UP
	PUSH	H		;OVER SO COUNT DOWN
	LHLD	SPT		;SECTOR / TRACK
	MOV	A,E
	SUB	L
	MOV	E,A
	MOV	A,D
	SBB	H
	MOV	D,A		;SUBTRUCT SECTOR COUNT OF ONE TRACK
	POP	H
	DCX	H		;DOWN ONE TRACK
	JMP	TSSEL		;TO DOWN LOOP
TSSES:				;TRACK COUNT UP LOOP
	PUSH	H
	LHLD	SPT
	DAD	D		;ADD SECTOR OF ONE TRACK
	JC	TSSEN
	MOV	A,C
	SUB	L
	MOV	A,B
	SBB	H
	JC	TSSEN
	XCHG
	POP	H
	INX	H		;UP ONE TRACK
	JMP	TSSES		;TO UP LOOP
TSSEN:				;TARGET SECTOR IN THE TRACK
	POP	H		;GET TRACK NUMBER
	PUSH	B		;SAVE TARGET SECTOR
	PUSH	D		;SAVE SECTOR NUMBER
	PUSH	H		;SAVE TRACK NUMBER
	XCHG
	LHLD	OFF		;GET OFFSET OF DIRECTORY
	DAD	D		;GET PHYSICAL TRACK
	MOV	B,H
	MOV	C,L
	CALL	SETRK		;SET TRACK
	POP	D		;GET TRACK NUMBER
	LHLD	PTRAK		;GET TRACK NUMBER BUFFER POINTER
	MOV	M,E
	INX	H
	MOV	M,D		;SAVE TRACK TO TEMPORARY BUFFER
	POP	D		;GET SECTOR NUMBER OF THE TRACK TOP
	LHLD	PSECT		;GET SCTOR BUFFER POINTER
	MOV	M,E
	INX	H
	MOV	M,D		;SAVE SECTOR
	POP	B
	MOV	A,C
	SUB	E
	MOV	C,A
	MOV	A,B
	SBB	D		;SUBTRUCT SECTOR COUNT OF THE TRACK TOP
	MOV	B,A		;GET LOGICAL SECTOR
	LHLD	XTL		;GET SECTOR TRANSLATE TABLE POINTER
	XCHG
	CALL	SCTRN		;TRANSLATE TO PHYSICAL SECTOR
	MOV	C,L
	MOV	B,H
	JMP	SETSC		;SET SECTOR
;
;  GET BIAS IN DIRECTORY BLOCK MAP
;  OUTPUT
;   A:BIAS
;
GBSDM:
	LXI	H,BSH
	MOV	C,M		;GET BLOCK SHIFT FACTOR
	LDA	CRCNT		;GET CURRENT RECODE COUNT  0 TO 7FH
	ORA	A
	RAR			;SHIFT & GET COUNT BY BLOCK
	DCR	C
	JNZ	$-3
	MOV	B,A		;SAVE COUNT BY RECODE COUNT
	MVI	A,8
	SUB	M		;GET EXTENT SHIFT FACTOR
	MOV	C,A
	LDA	EXTNT		;GET EXTENT OF COUNT
GBSDL:				;SHIFT LOOP FOR COUNT BY BLOCK
	DCR	C
	JZ	GBSDE
	ORA	A
	RAL			;SHIFT OF EXTENT COUNT
	JMP	GBSDL
GBSDE:
	ADD	B		;GET TOTAL COUNT BY BLOCK
	RET
;
;  GET BLOCK NUMBER
;  INPUT
;  BC:BIAS IN DIRECTORY BLOCK MAP
;  OUTPUT
;  HL:BLOCK NUMBER
;
GBLNM:
	LHLD	INPAR
	LXI	D,16
	DAD	D		;TOP OF DIRECTORY BLOCK MAP
	DAD	B
	LDA	DSMMD		;GET DISK SIZE MODE
	ORA	A
	JZ	GBLNS		;DOUBLE BYTES  DSM > 255
	MOV	L,M		;SINGLE BYTE   DSM < 256
	MVI	H,0
	RET
GBLNS:				;DOUBLE BYTES
	DAD	B		;SO ADD BIAS TWICE
	MOV	E,M
	INX	H
	MOV	D,M		;GET BLOCK NUMBER
	XCHG
	RET
;
;  GET TARGET BLOCK
;
GBLOK:
	CALL	GBSDM		;GET BIAS IN DM
	MOV	C,A
	MVI	B,0
	CALL	GBLNM		;GET BLOCK NUMBER
	SHLD	TSECT		;SAVE BLOCK NUMBER
	RET
;
;  CHECK BLOCK EMPTY
;  OUTPUT
;  ZF:ON  EMPTY
;
CKBLK:
	LHLD	TSECT
	MOV	A,L
	ORA	H
	RET
;
;  BLOCK NUMBER TO TARGET SECTOR CONVERSION
;
BLSCV:
	LDA	BSH		;GET SHIFT FACTOR
	LHLD	TSECT
	DAD	H		;MAKE BASE
	DCR	A
	JNZ	$-2
	SHLD	BTSEC		;SAVE BLOCK TOP SECOR
	LDA	BLM		;IN ONE BLOCK
	MOV	C,A
	LDA	CRCNT		;GET CURRENT RECODE COUNT
	ANA	C		;GET BIAS IN ONE BLOCK
	ORA	L
	MOV	L,A
	SHLD	TSECT		;SET TARGET SECTOR
	RET
;
;  GET FILE EXTENT POINT
;  OUTPUT
;  HL:POINT
;
EXTPT:
	LHLD	INPAR
	LXI	D,12
	DAD	D
	RET
;
;  GET RECODE COUNT POINTS
;  OUTPUT
;  HL:CURRENT RECODE COUNT POINT
;  DE:RECODE COUNT POINT
;
GRCPT:
	LHLD	INPAR
	LXI	D,15
	DAD	D		;GET RECODE COUNT POINT
	XCHG
	LXI	H,17
	DAD	D		;GET CURRENT RECODE COUNT POINT
	RET
;
;  GET RECODE COUNTERS
;
GRCNT:
	CALL	GRCPT		;GET RECODE COUNTER POINTER
	MOV	A,M
	STA	CRCNT		;SET CURRENT RECODE COUNT
	XCHG
	MOV	A,M
	STA	RECNT		;SET RECODE COUNT
	CALL	EXTPT		;GET FILE EXTENT POINT
	LDA	EXM		;GET FILE EXTENT MASK
	ANA	M
	STA	EXTNT		;SAVE EXTENT OF RECODE COUNT
	RET
;
;  UP & SET RECODE COUNTERS TO FCB
;
SRCNT:
	CALL	GRCPT		;GET RECODE COUNT POINTS
	LDA	URCNT		;GET UP COUNT MODE
	CPI	2
	JNZ	$+4		;NORMAL MODE
	XRA	A		;RANDOM WRITE WITH ZERO FILL
	MOV	C,A		;SAVE UP COUNT
	LDA	CRCNT		;NOW COUNT
	ADD	C		;UP THE COUNT
	MOV	M,A		;SAVE CURRENT RECODE COUNT
	XCHG
	LDA	RECNT
	MOV	M,A		;SET RECODE COUNT
	RET
;
;  DOUBLE BYTE SHIFT RIGHT
;  HL:DATA
;  INPUT
;   C:COUNT
;
DSHFR:
	INR	C
	DCR	C
	RZ
	MOV	A,H
	ORA	A
	RAR
	MOV	H,A
	MOV	A,L
	RAR
	MOV	L,A
	JMP	DSHFR+1
;
;  GET DIRECTORY BUFFER
;  OUTPUT
;  HL:DIRECTORY BUFFER
;
GDRBF:
	LHLD	DIRBF
	LDA	DIRMD		;GET DIRECTORY BUFFER MODE
	ORA	A
	RZ
	LHLD	DMADD
	RET
;
;  GET HASH TOTAL OF DIRECTORY TO CHECK DISK CHANGE
;
HASH:
	MVI	C,128		;COUNT OF ONE SECTOR
	CALL	GDRBF		;GET BUFFER
	XRA	A
	ADD	M
	INX	H
	DCR	C
	JNZ	$-3
	RET
;
;  DOUBLE BYTE SHIFT LEFT
;  HL:DATA 
;  INPUT
;   C:COUNT
;
DSHFL:
	INR	C
	DCR	C
	RZ
	DAD	H
	JMP	DSHFL+1
;
;  SET DISK VECTOR
;  INPUT
;  BC:LAST VECTOR
;  OUTPUT
;  HL:NEW VECTOR
;
SDFLG:
	PUSH	B
	LDA	NDRIV		;GET NOW DISK
	MOV	C,A
	LXI	H,1
	CALL	DSHFL		;GET DISK BIT
	POP	B
	MOV	A,C
	ORA	L
	MOV	L,A
	MOV	A,B
	ORA	H
	MOV	H,A		;GET NEW VECTOR
	RET
;
;  CHECK READ ONLY VECTOR
;  OUTPUT
;  ZF:ON READ WRITE DISK
;
HSCHK:
	LHLD	DROVC		;GET R/O VECTOR
	LDA	NDRIV
	MOV	C,A		;GET NOW DISK 
	CALL	DSHFR		;SHIFT RIGHT
	MOV	A,L
	ANI	1		;CHECK BIT
	RET
;
;  SET DISK WRITE PROTECT FLAG
;
SHSER:
	LXI	H,DROVC
	MOV	C,M
	INX	H
	MOV	B,M		;GET NOW R/O VECTOR
	CALL	SDFLG		;SET FLAG
	SHLD	DROVC		;SAVE NEW VECTOR
	LHLD	DRM
	INX	H
	XCHG
	LHLD	PHLEV
	MOV	M,E
	INX	H
	MOV	M,D		;SET DIRECTORY BLOCK MAX
	RET
;
;  CHECK WRITE PROTECT FILE
;
CHTPF:
	CALL	GDRPT		;GET DIRECTORY TOP
CHTEM:
	LXI	D,9
	DAD	D
	MOV	A,M		;GET FILE TYPE TOP
	RAL
	RNC			;READ WRITE FILE
	JMP	EFLRO		;READ ONLY FILE
;
;  CHECK CHANGE OR WRITE PROTECT DISK
; 
HSERT:
	CALL	HSCHK		;CHECK R/O VECTOR
	RZ			;READ WRITE DISK
	JMP	EDKCG		;READ ONLY DISK
;
;  GET DIRECTORY POINT
;  OUTPUT
;  HL:POINT
;
GDRPT:
	CALL	GDRBF		;DIRECTORY BUFFER
	LDA	BIDIR		;BIAS
;
;  DOUBLE BYTES & SINGLE BYTE ADD
;   A:ADDEND
;  HL:DESTINATION
;
DSADD:
	ADD	L
	MOV	L,A
	RNC
	INR	H
	RET
;
;  GET RECODE READ / WRITE MODE
;  MODE BIT 7:R/W MODE  H READ ONLY
;       BIT 6:H  RANDOM R/W ERROR
;       BIT 0-4:EXTENTION OF FILE
;  OUTPUT
;   A:MODE
;  HL:POINT OF MODE
;
MDPNT:
	LHLD	INPAR
	LXI	D,14
	DAD	D
	MOV	A,M
	RET
;
;  CLEAR READ WRITE MODE TO WRITE MODE
;
MDCLS:
	CALL	MDPNT
	MVI	M,0
	RET
;
;  INITIALIZE READ WRITE MODE TO READ ONLY
;
MDOPN:
	CALL	MDPNT
	ORI	80H
	MOV	M,A
	RET
;
;  SET ERROR FLAG TO OUTPUT PARAMETER AREA
;
STOTP:
	MVI	A,1
	STA	OTPAR
	RET
;
;  CHECK HASH CHECK LEVEL
;  OUTPUT
;  CF:ON UNDER LEVEL
;  DE:NOW LEVEL
;  HL:LEVEL BUFFER POINT +1
;
CHLEV:
	LHLD	DIRCT
	XCHG
	LHLD	PHLEV
	MOV	A,E
	SUB	M
	INX	H
	MOV	A,D
	SBB	M
	RET
;
;  SET HASH CHECK LEVEL
;
STHLV:
	CALL	CHLEV
	RC			;UNDER LEVEL
	INX	D
	MOV	M,D
	DCX	H
	MOV	M,E		;SET NEW LEVEL
	RET
;
;  SUBTRUCT DOUBLE BYTE
;  HL = DE - HL
;
DSUB:
	MOV	A,E
	SUB	L
	MOV	L,A
	MOV	A,D
	SBB	H
	MOV	H,A
	RET
;
;  MAKE HASH OR CHECK ROUTINE
;  INPUT
;   C: 0= CHECK -1= SET
;
HSHTS:
	MVI	C,-1		;FOR SET MODE
HSHTR:
	LHLD	DIRSC		;GET BIAS BY SECTOR IN DIRECTORY
	XCHG
	LHLD	CKS		;SIZE OF HASH CHECK TABLE
	CALL	DSUB
	RNC			;OVER OF CHECK TABLE
	PUSH	B
	CALL	HASH		;GET HASH TOTAL
	LHLD	CSV		;GET HASH CHECK AREA
	XCHG
	LHLD	DIRSC		;GET BIAS
	DAD	D
	POP	B
	INR	C
	JZ	HSHTT		;SET MODE
	CMP	M
	RZ			;GOOD
	CALL	CHLEV		;NOT MATCH ,SO CHECK THE LEVEL
	RNC			;HASH DATA WAS NOT ALREADY SET
	CALL	SHSER		;SET R/O VECTOR FOR ERROR(CHANGE DISK)
	RET
HSHTT:
	MOV	M,A		;SET HASH DATA
	RET
;
;  WRITE DIRECTORY WITH SET UP OF ITS HASH DATA
;
DIWRT:
	CALL	HSHTS		;SET UP OF HASH CHECK DATA
	CALL	STDMD		;TO DIRECTORY DMA AREA
	MVI	C,1
	CALL	FWRIT		;WRITE
STDMA:				;SET NORMAL DMA ADDRESS
	LXI	H,DMADD		;NORMAL DMA AREA
STDMS:
	MOV	C,M
	INX	H
	MOV	B,M		;GET DMA AREA ADDRESS
	JMP	SETDM
STDMD:
	LXI	H,DIRBF		;DIRECTORY READ BUFFER POINTER
	JMP	STDMS
;
;  READ DIRECTORY ONE SECTOR
;
DREAD:
	LDA	DIRMD
	ORA	A
	CZ	STDMD		;TO DIRECTORY AREA
	CALL	FREAD		;READ ONE SECTOR
	JMP	STDMA		;TO NORMAL DMA
;
;  CHECK DIRECTORY END
;  OUTPUT
;  ZF:ON END
;
DICHK:
	LXI	H,DIRCT		;DIRECTORY COUNTER AREA
	MOV	A,M
	INX	H
	CMP	M
	RNZ			;NOT TO END
	INR	A		;IF DATA IS 0FFFFH, ZF BECOMES ON
	RET
;
;  INITIALIZE DIRECTORY COUNTER
;
DIRCI:
	LXI	H,-1
	SHLD	DIRCT		;INCREMENT AT FIRST IN THE DIRECTORY READ
	RET
;
;  GET NEXT DIRECTORY
;  INPUT
;   C:0 HASH CHECK  1 SET
;
DIRED:
	LHLD	DRM		;GET MAX OF DIRECTORY NUMBER
	XCHG
	LHLD	DIRCT
	INX	H
	SHLD	DIRCT		;DIRECTORY COUNTER UP
	CALL	DSUB		;COMPARE WITH LENGTH
	JNC	DIRES		;IN DIRECTORY DATA
	CALL	DIRCI		;DIRECTORY OVER
	RET
DIRES:
	LDA	DIRCT
	ANI	3		;GET BIAS BASE IN ONE SECTOR 8 DIRECTORIES
	MVI	B,5
	ADD	A		;ONE DIRECTORY IS CONSTRUCTED FROM 32 BYTES
	DCR	B
	JNZ	$-2		;*32
	STA	BIDIR		;SAVE BIAS IN ONE SECTOR
	ORA	A
	RNZ			;IN THE SAME SECTOR
	PUSH	B
	CALL	SDIRT		;TO NEW SECTOR, SO SET DIRECTORY T & S
	CALL	DREAD		;READ NEXT TO DIRECTORY BUFFER
	POP	B
	JMP	HSHTR		;TO HASH CHECK OR SET
;
;  GET DISK ALLOCATION MAP BIT
;  INPUT
;  BC:TARGET BLOCK NUBER
;  OUTPUT
;   A:BIT 0 IS TARGET BIT
;   D:ROTATION FOR SET
;  HL:ALLOCATION MAP POINT OF TARGET BYTE
;
DMBGT:
	MOV	A,C
	ANI	7
	INR	A
	MOV	E,A		;GET ROTATION IN ONE BYTE
	MOV	D,A
	MOV	A,C
	RRC
	RRC
	RRC
	ANI	1FH		;1/8 TO BYTE COUNT
	MOV	C,A
	MOV	A,B
	ADD	A
	ADD	A
	ADD	A
	ADD	A
	ADD	A		;*32
	ORA	C		;GET BYTE BIAS LOWER BYTE
	MOV	C,A
	MOV	A,B
	RRC
	RRC
	RRC
	ANI	1FH		;GET BYTE BIAS HIGER BYTE
	MOV	B,A
	LHLD	ALV		;ALLOCATION MAP AREA
	DAD	B
	MOV	A,M		;GET TARGET BYTE
	RLC			;ROTATE
	DCR	E
	JNZ	$-2
	RET
;
;  CHANGE DISK ALLOCATION MAP BIT
;  INPUT
;  BC:BLOCK NUMBER
;   E:0 DELETE   1 TO USE
;
DMTRT:
	PUSH	D
	CALL	DMBGT		;GET BYTE
	ANI	0FEH		;DELETE BIT
	POP	B		;SET BIT FOR USE OR NOT SET FOR DELETE
	ORA	C
;
;  SET DISK ALLOCATION MAP BIT
;  INPUT
;   A:MAP CODE
;   D:ROTATION
;  HL:ALLOCATION MAP POINT OF THE BYTE
;
DMBST:
	RRC			;ROTATE TO THE NORMAL DATA
	DCR	D
	JNZ	DMBST
	MOV	M,A		;SET DATA TO ALLOCATION MAP
	RET
;
;  CHANGE DISK ALLOCATION MAP BIT OF ONE DIRECTORY
;  INPUT
;   C:0 DELETE   1 TO USE
;
DMCHG:
	CALL	GDRPT		;SET DIRECTORY POINT
	LXI	D,16
	DAD	D		;GET DM POINT
	PUSH	B
	MVI	C,17		;DM COUNT +1
DMCHL:				;NE BLOCK LOOP
	POP	D
	DCR	C
	RZ			;END OF ONE DIRCTORY
	PUSH	D
	LDA	DSMMD		;GET DISK SIZE MODE
	ORA	A
	JZ	DMCHD		;DOUBLE BYTES
	PUSH	B		;SINGLE BYTE
	PUSH	H
	MOV	C,M		;GET BLOCK NUMBER
	MVI	B,0
	JMP	DMCHS
DMCHD:				;DOUBLE BYTES
	DCR	C		;ONE MORE COUNT DOWN FOR USING DOUBLE BYTES
	PUSH	B
	MOV	C,M
	INX	H
	MOV	B,M		;GET BLOCK NUMBER
	PUSH	H
DMCHS:
	MOV	A,C
	ORA	B
	JZ	DMCHB		;NOT USING BLOCK
	LHLD	DSM		;GET MAX OF DISK STRAGE SIZE
	MOV	A,L
	SUB	C
	MOV	A,H
	SBB	B		;CHECK OVER SIZE
	CNC	DMTRT		;SET OR DELETE IF IN THE SIZE
DMCHB:
	POP	H
	INX	H
	POP	B
	JMP	DMCHL		;TO NEXT BLOCK
;
;  INITIALIZE OF DISK ALLOCATION MAP & HASH CHECK TABLE
;
INDMP:
	LHLD	DSM
	MVI	C,3
	CALL	DSHFR		;TO BYTE LENGTH AS MAP IS BIT STRING
	INX	H		;GET ALLOCATION MAP BYTE LENGTH
	MOV	B,H
	MOV	C,L
	LHLD	ALV		;GET ALLOCATION MAP AREA
	MVI	M,0		;CLEAR MAP
	INX	H
	DCX	B
	MOV	A,B
	ORA	C
	JNZ	$-6
	LHLD	AL0		;GET RESERVED ALLOCATION FOR DIRECTORY
	XCHG
	LHLD	ALV
	MOV	M,E
	INX	H
	MOV	M,D		;SET RESERVED ALLOCATION
	CALL	DRDMD		;TO DIRECTORY READ MODE
	LHLD	PHLEV
	MVI	M,3
	INX	H
	MVI	M,0		;INITIALIZE HASH CHECK LEVEL
	CALL	DIRCI		;INITIALIZE DIRECTORY COUNTER
INDML:				;DISK ALLOCATION MAP SETTING LOOP
	MVI	C,-1		;HASH SET MODE
	CALL	DIRED		;READ DIRECTORY
	CALL	DICHK		;DIRECTORY END CHECK
	RZ			;ALL DIRECTORIES HAVE BEEN READ
	CALL	GDRPT		;GET DIRECTORY POINT
	MVI	A,0E5H		;DELETED CODE
	CMP	M
	JZ	INDML		;DELETED DIRECTORY
	LDA	MDUSR
	CMP	M		;CHECK USER CODE
	JNZ	INDMS		;NOT SAME CODE
	INX	H		;GET AVAILABLE FILE
	MOV	A,M
	SUI	24H		;"$" IS SUBMIT FILE
	JNZ	INDMS		;NOT SUBMIT FILE
	DCR	A
	STA	OTPAR		;SET SUBMIT FLAG
INDMS:
	MVI	C,1		;TO USE MODE
	CALL	DMCHG		;SET DISK ALLOCATION MAP
	CALL	STHLV		;SET HASH CHECK LEVEL TO NOW LEVEL
	JMP	INDML		;TO NEXT DIERCTORY
;
;  SET DIRECTORY CODE   -1 NOT FOUND
;
SDCNT:
	LDA	DIRCC
	STA	OTPAR
	RET
;
;  COMPARE DIRECTORY EXTENTION
;  INPUT
;   A:EXTENT CODE 1
;   C:EXTENT CODE 2
;  OUTPUT
;  ZF:ON SAME DIRECTORY
;  CONSTRUCTED FROM EXTENT OF RECODE COUNT AND EXTENT OF DIRECTORY BLOCK
;
EXMCK:
	PUSH	B
	PUSH	PSW
	LDA	EXM		;GET EXTENT MASK
	CMA			;TO DIRECTORY EXTENTION MASK
	MOV	B,A
	MOV	A,C
	ANA	B		;GET EXTENTION OF DIRECTORY BLOCK
	MOV	C,A
	POP	PSW
	ANA	B		;GET EXTENTIN OF 1
	SUB	C		;COMPARE THE EXTENTION OF DIRECTORY BLOCK
	ANI	1FH
	POP	B
	RET
;
;  DIRECTORY SEARCH ROUTINE
;  INPUT
;   C:LENGTH OF COMPARE
;
DRSRH:
	MVI	A,-1
	STA	DIRCC		;ITIALIZE DIRECTORY CODE
	LXI	H,DRSLN
	MOV	M,C		;SAVE LENGTH
	LHLD	INPAR
	SHLD	FCBPN		;SET FCB POINT
	CALL	DIRCI		;INITIALIZE DIRECTORY COUNTER
	CALL	DRDMD		;SET DIRECTORY READ PARAMETER
;
;  MATCHING OF DIRECTORY
;
DRMAT:
	MVI	C,0		;SET HASH MODE TO CHECK
	CALL	DIRED		;READ DIRECTORY 
	CALL	DICHK		;END CHECK
	JZ	DRMAE		;END
	LHLD	FCBPN
	XCHG
	LDAX	D		;GET ENTRY TYPE
	CPI	0E5H
	JZ	DRMAD		;DELETE
	PUSH	D
	CALL	CHLEV		;CHECK HASH LEVEL
	POP	D
	JNC	DRMAE		;OVER THE DRECTORY AREA
DRMAD:
	CALL	GDRPT		;GET DIRECTORY POINT
	LDA	DRSLN		;GET COMPARE LENGTH
	MOV	C,A
	MVI	B,0
DRMAL:				;ONE BYTE LOOP
	MOV	A,C
	ORA	A
	JZ	DRMAO		;GET MATCH DIRECTORY
	LDAX	D
	CPI	'?'
	JZ	DRMAI		;WILD CARD
	MOV	A,B
	ORA	A
	JNZ	DRMAU+1
	LDAX	D		;USER CODE
	CPI	0E5H
	JZ	DRMAU		;DELETE DIRECTORY
	MOV	A,M
	ORA	A
	JZ	DRMAI		;0 CAN USER IN ALL USER
DRMAU:
	MOV	A,B
	CPI	13
	JZ	DRMAI		;NOT USE CODE
	CPI	12
	LDAX	D
	JZ	DRMAX		;FILE EXTENT
	SUB	M
	ANI	7FH
	JNZ	DRMAT		;MISS MATCH TO NEXT DIRECTORY BLOCK
	JMP	DRMAI		;MATCH TO NEXT BYTE
DRMAX:				;FILE EXTENT
	PUSH	B
	MOV	C,M		;GET DIRECTORY EXTENT
	CALL	EXMCK		;COMPARE DIRECTORY EXTENT
	POP	B
	JNZ	DRMAT		;NOT MATCH TO NEXT BLOCK
DRMAI:				;TO NEXT BYTE
	INX	D
	INX	H
	INR	B
	DCR	C
	JMP	DRMAL
DRMAO:				;GET MATCH DIRECTORY
	LDA	DIRCT
	ANI	3		;GET BIAS IN SECTOR
	STA	OTPAR		;SET DIRECTORY BIAS
	LXI	H,DIRCC
	MOV	A,M
	RAL
	RNC			;NOW SET SOME CODE
	XRA	A
	MOV	M,A		;CLEAR CODE
	RET
DRMAE:				;NOT MATCH
	CALL	DIRCI		;COUNTER INITIALIZE
	MVI	A,-1
	STA	OTPAR		;NOT MATCH
	RET
;
;  DELETE DIRECTORY & DISK ALLOCATION MAP BITS
;
DEDMP:
	CALL	HSERT		;CHECK DISK R/O & ERROR IF R/O
	MVI	C,12		;COMPARE ONLY NAME PART
	CALL	DRSRH		;SEARCH THE TARGET DIRECTORY 
DEDML:
	CALL	DICHK		;CHECK END
	RZ			;AL SEARCHED
	CALL	CHTPF		;CHECK WRITE PROTECT FILE  ERROR IF PROTECTED
	CALL	GDRPT		;GET DIRECTORY POINT
	LDA	MDUSR		;GET USER CODE
	CMP	M
	JNZ	DEDMS		;USER CODE MISS MATCH
	MVI	M,0E5H		;DELETE CODE
	MVI	C,0		;DELETE BIT MODE
	CALL	DMCHG		;DELETE DISK ALLOCATION BITS
	CALL	DIWRT		;WRITE DIRECTORY
DEDMS:				;TO NEXT
	CALL	DRMAT		;SEARCH NEXT
	JMP	DEDML		;TO NEXT DIRECTORY
;
;  GET AVAILABLE BLOCK BY SEARCHING NEAREST BLOCK
;  INPUT
;  BC:LAST BLOCK NUMBER
;    :0 WHEN FIRST BLOCK
;  OUTPUT
;  HL:AVAILABLE BLOCK NUMBER
;     0 NO AVAILABLE BLOCK
;
GAVAI:
	MOV	D,B
	MOV	E,C
GAVAL:				;SEARCH LOOP  BC DOWN SEARCH  DE UP SEARCH
	MOV	A,C
	ORA	B
	JZ	GAVAS		;NOW BECOME TOP, SO TO UP SEARCH
	DCX	B		;DOWN SEARCH
	PUSH	D
	PUSH	B
	CALL	DMBGT		;GET ALLOCATION MAP BIT
	RAR
	JNC	GAVAA		;GET AVAILABLE BLOCK
	POP	B
	POP	D
GAVAS:
	LHLD	DSM		;GET MAXIMUM SIZE
	MOV	A,E
	SUB	L
	MOV	A,D
	SBB	H
	JNC	GAVAE		;NO AVAILABLE BY UP SEARCH
	INX	D		;UP SEARCH
	PUSH	B
	PUSH	D
	MOV	B,D
	MOV	C,E
	CALL	DMBGT		;GET ALLOCATION MAP BIT
	RAR
	JNC	GAVAA		;GET AVAILABLE BLOCK
	POP	D
	POP	B
	JMP	GAVAL		;CHECK NEXT
GAVAA:				;GET AVAILABLE BLOCK
	RAL
	INR	A
	CALL	DMBST		;SET USE FLAG
	POP	H		;GET AVAILABLE BLOCK NUMBER
	POP	D
	RET
GAVAE:
	MOV	A,C
	ORA	B
	JNZ	GAVAL+5		;NOT TO TOP, SO CHECK NEXT
	LXI	H,0		;NO AVAILABLE BLOCK
	RET
;
;  ALL FCB DATA COPY TO DIRECTORY & WRITE
;
COPYA:
	MVI	C,0
	MVI	E,32
;
;  COPY TO DIRECTORY & WRITE
;  INPUT
;   C:BIAS OF FCB TO DIRECTORY
;    :16 RENAME  0 SET ATTRIBUTE
;   E:COPY LENGTH
;
CPDIR:
	PUSH	D
	MVI	B,0
	LHLD	INPAR
	DAD	B		;GET FCB COPY AREA TOP
	XCHG
	CALL	GDRPT		;GET DIRECTORY TOP
	POP	B
	CALL	COPY
CPDIE:
	CALL	SDIRT		;SET DIRECTORY TRACK & SECTOR
	JMP	DIWRT		;WRITE DIRECTORY
;
;  RENAME 
;
RENAM:
	CALL	HSERT		;CHECK DISK R/O
	MVI	C,12		;CHECK ONLY NAME
	CALL	DRSRH		;SEARCH DIRECTORY
	LHLD	INPAR
	MOV	A,M
	LXI	D,16
	DAD	D
	MOV	M,A		;SET ENTRY TYPE
RENAL:				;LOOP OF DIRECTORY BLOCK RENAME
	CALL	DICHK		;CHECK DIRECTORY END
	RZ			;NOT FOUND OR END
	CALL	CHTPF		;CHECK WRITE PROTECT FILE
	CALL	GDRPT		;GET DIRECTORY POINT
	LDA	MDUSR
	CMP	M
	JNZ	RENAS		;USER CODE MISS MATCH
	MVI	C,16		;BIAS IN FCB
	MVI	E,12		;COPY ONLY NAME
	CALL	CPDIR		;COPY OF DIRECTORY & WRITE
RENAS:				;TO NEXT
	CALL	DRMAT		;SEARCH NEXT
	JMP	RENAL		;TO NEXT DIRECTORY BLOCK
;
;  SET ATTRIBUTE
;
SFATR:
	MVI	C,12		;ONLY NAME
	CALL	DRSRH		;SEARCH DIRECTORY
SFATL:				;LOOP OF DIRECTORY BLOCK
	CALL	DICHK		;CHECK DIRECTORY END
	RZ			;ALL OVER
	MVI	C,0
	MVI	E,12
	CALL	CPDIR		;COPY TO DIRECTORY AND WRITE
	CALL	DRMAT		;SEARCH NEXT
	JMP	SFATL		;TO NEXT DIRECTORY BLOCK
;
;  OPEN FILE
;
OPEN:
	MVI	C,15		;SEARCH WITH EXTENT
	CALL	DRSRH		;SEARCH DIRECTORY
	CALL	DICHK		;CHECK EXISTENCE OF FILE
	RZ			;NOT EXIST
	CALL	SETAC		;SET ACCESS MODE
OPENS:
	CALL	EXTPT		;GET FILE EXTENT POINT
	MOV	A,M
	PUSH	PSW
	PUSH	H		;SAVE ENTRY FILE EXTENT
	CALL	GDRPT		;GET DIRECTORY POINT
	XCHG
	LHLD	INPAR		;GET FCB POINT
	MVI	C,32
	PUSH	D
	CALL	COPY		;COPY DIRECTORY TO FCB
	CALL	MDOPN		;INITIALIZE R/W MODE
	POP	D
	LXI	H,12
	DAD	D
	MOV	C,M		;GET FILE EXTENT
	LXI	H,15
	DAD	D
	MOV	B,M		;GET RECODE COUNT
	POP	H
	POP	PSW
	MOV	M,A		;RESTORE FILE EXTENT
	MOV	A,C
	CMP	M
	MOV	A,B
	JZ	OPENE		;MATCH EXTENT, SO RECODE COUNT IS AVAILABLE
	MVI	A,0
	JC	OPENE		;UNDER FILE EXTENT
	MVI	A,80H		;OVER FILE EXTENT
OPENE:
	LHLD	INPAR
	LXI	D,15
	DAD	D
	MOV	M,A		;SET RECODE COUNT
	RET
;
;  DIRECTORY CHECK OF DISK ALLOCATION MAP 
;  FOR LARGE STRAGE SIZE
;  INPUT
;  HL:DESTINATION
;  DE:SOURCE
;
DMCHK:
	MOV	A,M
	INX	H
	ORA	M
	DCX	H
	RNZ			;SOME DATA EXISTS
	LDAX	D
	MOV	M,A
	INX	D
	INX	H
	LDAX	D
	MOV	M,A		;COPY SOURCE DATA TO DESTINATION
	DCX	D
	DCX	H
	RET
;
;  CLOSE A FILE
;
CLOSE:
	LXI	H,0
	SHLD	OTPAR		;CLEAR OUTPUT PARAMETER
	SHLD	DIRCT		;CLEAR DIRECTORY COUNTER
	CALL	HSCHK		;CHECK DISK R/O VECTOR
	RNZ			;ERROR OF R/O DISK
	CALL	MDPNT		;GET MODE BYTE
	ANI	80H		;ONLY READ OPERATION, SO END
	RNZ
	MVI	C,15
	CALL	DRSRH		;SEARCH DIRECTORY
	CALL	DICHK		;CHECK EXISTENCE
	RZ			;NOT EXIST
	LXI	B,16
	CALL	GDRPT		;GET DIRECTORY POINT
	DAD	B
	XCHG
	LXI	H,-5
	DAD	D		;GET T3 POINT
	MOV	A,M
	ANI	7FH
	MOV	M,A		;SET FILE UPDATE MODE
	LHLD	INPAR
	DAD	B
	MVI	C,16
CLOSC:				;LOOP OF CHECK & MAKE DIRECTORY MAP
	LDA	DSMMD		;GET STRAGE SIZE MODE
	ORA	A
	JZ	CLOSL		;DOUBLE BYTES  DSM>255
	MOV	A,M		;SINGLE BYTE   DSM<256
	ORA	A
	LDAX	D
	JNZ	$+4		;SOME DATA EXISTS
	MOV	M,A		;NO DATA
	ORA	A
	JNZ	$+5		;SOME DATA EXISTS
	MOV	A,M		;NEW BLOCK NUMBER
	STAX	D
	CMP	M
	JNZ	CLOSR		;ERROR OF MISS MATCH
	JMP	CLOSS		;TO NEW DIRECTORY MAP
CLOSL:				;DOUBLE BYTE MODE
	CALL	DMCHK
	XCHG
	CALL	DMCHK		;DATA CHECK & COPY
	XCHG
	LDAX	D
	CMP	M
	JNZ	CLOSR		;ERROR OF MISS MATCH
	INX	D
	INX	H
	LDAX	D
	CMP	M
	JNZ	CLOSR		;ERROR OF MISS MATCH
	DCR	C
CLOSS:
	INX	D
	INX	H
	DCR	C
	JNZ	CLOSC		;TO NEXT DM
	LXI	B,-20		;ALL CHECKED
	DAD	B
	XCHG
	DAD	B
	LDAX	D
	CMP	M		;COMPARE FILE EXTENT
	JC	CLOST
	MOV	M,A
	LXI	B,3
	DAD	B
	XCHG
	DAD	B
	MOV	A,M
	STAX	D		;SET RECODE COUNT
CLOST:				;SET TO DIRECTORY
	MVI	A,-1
	STA	EXMOD		;SET ENTRY MODE
	CALL	CPDIE		;DIRECTORY WRITE
	RET
CLOSR:
	LXI	H,OTPAR
	DCR	M		;MISS MATCH ERROR
	RET
;
;  GET AVAILABLE DIRECTORY
;
GADIR:
	CALL	HSERT		;CHECK DISK R/O
	LHLD	INPAR
	PUSH	H		;SAVE FCB POINT
	LXI	H,DLCOD		;DELETE MARK
	SHLD	INPAR
	MVI	C,1
	CALL	DRSRH		;SEARCH DELETE DIRECTORY
	CALL	DICHK		;CHECK DIRECTORY END
	POP	H
	SHLD	INPAR		;RESTORE FCB POINT
	RZ			;NO AVAILABLE
	XCHG
	LXI	H,15
	DAD	D
	MVI	C,17
	XRA	A
	MOV	M,A		;CLEAR DM AREA
	INX	H
	DCR	C
	JNZ	$-3
	LXI	H,13
	DAD	D
	MOV	M,A		;CLEAR CURRENT RECODE COUNT
	CALL	STHLV		;SET UP OF HASH CHECK LEVEL
	CALL	COPYA		;WRITE NEW DIRECTORY
	CALL	MDOPN		;TO INITIALIZE OF R/W MODE
;
;  ACCESS CURRENT DRIVE
;
SETAC:
	LXI	H,1
	LDA	OUTSP
	MOV	C,A
	CALL	DSHFL		;GET DRIVE BIT
	JMP	MACDV+3		;TO ACCESS DRIVE
;
;
;  ONE DIRECTORY OVER TO NEXT
;
DOVER:
	XRA	A
	STA	EXMOD		;CLEAR CLOSE WRITE MODE
	CALL	CLOSE		;LOSE NOW DIRECTORY
	CALL	DICHK
	RZ			;CLOSE DIRECTORY NOT FOUND
	LHLD	INPAR
	LXI	B,12
	DAD	B		;GET FILE EXTENT
	MOV	A,M
	INR	A
	ANI	1FH
	MOV	M,A
	JZ	DOVEN		;UP OF EXTENTION
	MOV	B,A
	LDA	EXM		;EXTENT MASK
	ANA	B
	LXI	H,EXMOD
	ANA	M
	JZ	DOVES		;OVER TO NEXT
	JMP	DOVEO		;OR THE SAME DIRECTORY
DOVEN:
	LXI	B,2
	DAD	B
	INR	M		;UP OF EXTENTION
	MOV	A,M
	ANI	0FH
	JZ	DOVEL		;TOO LONG
DOVES:
	MVI	C,15
	CALL	DRSRH		;DIRECTORY SEARCH
	CALL	DICHK
	JNZ	DOVEO		;GET NEXT
	LDA	DOVMD		;GET READ MODE
	INR	A
	JZ	DOVEL		;FILE END, AS NOW READ MODE
	CALL	GADIR		;GET AVAILABLE DIRECTORY
	CALL	DICHK
	JZ	DOVEL		;NO AVAILABLE
	JMP	DOVEO+3
DOVEO:
	CALL	OPENS		;SET OPEN PARAMETER 
	CALL	GRCNT		;GET RECODE COUNTS
	XRA	A
	STA	OTPAR		;SUCCEED
	RET
DOVEL:				;OVER OF FILE
	CALL	STOTP		;SET OVER FLAG
	JMP	MDOPN
;
;  READ NEXT RECODE
;
RNEXT:
	MVI	A,1
	STA	URCNT		;UP COUNT OF RECODE COUNT
RNEXR:				;RANDOM READ ENTRY
	MVI	A,-1
	STA	DOVMD		;TO READ MODE
	CALL	GRCNT		;GET RECODE COUNT
	LDA	CRCNT		;CURRENT RECODE COUNT
	LXI	H,RECNT
	CMP	M
	JC	RNEXS		;GET IN THE SAME DIRECTORY
	CPI	80H
	JNZ	RNEXN		;OVER THE RECODE COUNT
	CALL	DOVER		;TO NEXT DIRECTORY
	XRA	A
	STA	CRCNT		;CLERAR RECODE COUNT
	LDA	OTPAR
	ORA	A
	JNZ	RNEXN		;NEXT DIRECTORY ERROR
RNEXS:				;GET NEXT SECTOR
	CALL	GBLOK		;GET TARGET BLOCK
	CALL	CKBLK		;BLOCK EMPTY CHECK
	JZ	RNEXN		;EMPTY
	CALL	BLSCV		;BLOCK TO SECTOR CONVERSION
	CALL	TSSET		;SET TRACK & SECTOR
	CALL	FREAD		;READ ONE SECTOR
	CALL	SRCNT		;SET COUNTS TO FCB
	RET
RNEXN:				;SOME ERROR
	JMP	STOTP		;SET ERROR FLAG
;
;  WRITE NEXT RECODE
;
WNEXT:
	MVI	A,1
	STA	URCNT		;UP COUNT OF RECODE COUNT TO SEQUENTIAL WRITE
WNEXR:				;RANDOM WRITE ENTRY
	MVI	A,0
	STA	DOVMD		;MODE TO WRITE
	CALL	HSERT		;CHECK WRITE PROTECT OF DISK
	LHLD	INPAR
	CALL	CHTEM		;CHECK WRITE PROTECT OF FILE
	CALL	GRCNT		;GET RECODE COUNTS
	LDA	CRCNT
	CPI	80H
	JC	$+7
	CALL	STOTP		;FILE EXTENT ERROR
	RET
	CALL	GBLOK		;GET TARGET BLOCK
	CALL	CKBLK		;CHECK EMPTY
	MVI	C,0		;SET CURRENT BLOCK MODE
	JNZ	WNEXS		;IN THE CURRENT BLOCK
	CALL	GBSDM		;TO NEXT BLOCK
	STA	DRBSW		;SAME DIRECTORY BIAS FOR WRITE
	LXI	B,0
	ORA	A
	JZ	WNEXF		;FIRST BLOCK
	MOV	C,A
	DCX	B
	CALL	GBLNM		;GET LAST BLOCK NUMBER
	MOV	B,H
	MOV	C,L
WNEXF:
	CALL	GAVAI		;SEARCH AVAILABLE BLOCK
	MOV	A,L
	ORA	H
	JNZ	WNEXG		;GET BLOCK
	MVI	A,2		;NO AVAILABLE
	STA	OTPAR
	RET
WNEXG:
	SHLD	TSECT
	XCHG
	LHLD	INPAR
	LXI	B,16
	DAD	B		;DM TOP
	LDA	DSMMD		;GET STRAGE SIZE MODE
	ORA	A
	LDA	DRBSW		;BIAS
	JZ	WNEXD		;DOUBLE BYTES  DSM>255
	CALL	DSADD		;SINGLE BYTE   DSM<256
	MOV	M,E		;SAVE BLOCK NUMBER
	JMP	WNEXS-2
WNEXD:				;DOUBLE BYTES
	MOV	C,A
	MVI	B,0
	DAD	B
	DAD	B
	MOV	M,E
	INX	H
	MOV	M,D		;SAVE BLOCK NUMBER
	MVI	C,2		;SET NEW BLOCK MODE
WNEXS:
	LDA	OTPAR
	ORA	A
	RNZ			;SOME ERROR
	PUSH	B
	CALL	BLSCV		;TO SECTOR
	LDA	URCNT		;GET COUNT UP MODE
	DCR	A
	DCR	A
	JNZ	WNEXN		;NOT WRITE WITH ZERO
	POP	B		;WRITE WITH ZERO FILL MODE
	PUSH	B
	MOV	A,C
	DCR	A
	DCR	A
	JNZ	WNEXN		;NOT WRITE ZERO	AS NOT NEW BLOCK
	PUSH	H		;FILL ZERO TO THE BLOCK
	LHLD	DIRBF		;GET BUFFER
	MOV	D,A
	MOV	M,A		;CLEAR DATA
	INX	H
	INR	D
	JP	$-3
	CALL	STDMD		;SET DMA ADDRESS
	LHLD	BTSEC		;BLOCK TOP SECTOR
	MVI	C,2		;SET NEW BLOCK MODE
WNEXZ:				;FILL LOOP
	SHLD	TSECT
	PUSH	B
	CALL	TSSET		;SET TRACK & SECTOR
	POP	B
	CALL	FWRIT		;WRITE DATA
	LHLD	TSECT
	MVI	C,0		;SET CURRENT BLOCK MODE
	LDA	BLM		;GET MASK CODE
	MOV	B,A
	ANA	L
	CMP	B		;CHECK BLOCK END
	INX	H
	JNZ	WNEXZ		;FILL TO BLOCK END
	POP	H
	SHLD	TSECT		;RESTORE TARGET SECTOR
	CALL	STDMA		;TO NORMAL DMA ADDRESS
WNEXN:				;WRITE OF ONE SECTOR
	CALL	TSSET		;SET TRACK & SECTOR
	POP	B
	PUSH	B
	CALL	FWRIT		;WRITE ONE SECTOR
	POP	B
	LDA	CRCNT
	LXI	H,RECNT
	CMP	M
	JC	$+7
	MOV	M,A		;UP OF COUNT
	INR	M
	MVI	C,2		;SET NEW BLOCK MODE
	NOP
	NOP
	NOP
	NOP
	NOP
	PUSH	PSW
	CALL	MDPNT		;GET R/W MODE
	ANI	7FH
	MOV	M,A		;SET TO WRITEN MODE
	POP	PSW
WNEXV:
	CPI	7FH
	JNZ	WNEXE		;RECODE COUNT IN RANGE (0-127)
	LDA	URCNT
	ORA	A
	JZ	WNEXE
;!!!!!!!!!
;  UPSER TWO LINES MUST BE
;	CPI	1
;	JNZ	WNEXE
;!!!!!!!!!
	CALL	SRCNT		;SET NOW RECODE COUNT
	CALL	DOVER		;TO NEXT DIRECTORY
	LXI	H,OTPAR
	MOV	A,M
	ORA	A
	JNZ	WNEXE-2		;SOME ERROR IN DIRECTORY EXTENTION
	DCR	A
	STA	CRCNT		;INITIALIZE OF CURRENT RECODE
	MVI	M,0
WNEXE:
	JMP	SRCNT
;
;  DIRECTORY READ & COUNT FOR RANDOM FILE ACCESS
;  INPUT
;   C:-1 READ MODE
;  OUTPUT
;  ZF:ON SUCCESS
;
RNDIR:
	XRA	A
	STA	URCNT		;NOT UP COUNT MODE
RNDIS:
	PUSH	B
	LHLD	INPAR
	XCHG
	LXI	H,33
	DAD	D		;GET COUNTER POINT
	MOV	A,M
	ANI	7FH		;GET COUNT IN LAST DIRECTORY
	PUSH	PSW
	MOV	A,M
	RAL
	INX	H
	MOV	A,M
	RAL
	ANI	1FH
	MOV	C,A		;SAVE FILE EXTENT COUNT
	MOV	A,M
	RAR
	RAR
	RAR
	RAR
	ANI	0FH
	MOV	B,A		;EXTENTION
	POP	PSW
	INX	H
	MOV	L,M		;GET THIRD BYTE
	INR	L
	DCR	L
	MVI	L,6		;PASSED PHYSICAL END
	JNZ	RNDIE		;THIRD BYTE MUST BE ZERO
	LXI	H,32
	DAD	D
	MOV	M,A		;SET NEXT RECODE COUNT
	LXI	H,12
	DAD	D		;FILE EXTENT
	MOV	A,C
	SUB	M
	JNZ	RNDIN		;NOT MATCH
	LXI	H,14
	DAD	D		;EXTENTION
	MOV	A,B
	SUB	M
	ANI	7FH
	JZ	RNDIM		;GET MATCH DIRECTORY
RNDIN:				;NOT MATCH, SO SEARCH DIRECTORY
	PUSH	B
	PUSH	D
	CALL	CLOSE
	POP	D
	POP	B
	MVI	L,3
	LDA	OTPAR
	INR	A
	JZ	RNIDC		;CAN NOT CLOSE
	LXI	H,12
	DAD	D
	MOV	M,C		;SET TARGET FILE EXTENT
	LXI	H,14
	DAD	D
	MOV	M,B		;SET TARGET EXTENTION
	CALL	OPEN
	LDA	OTPAR
	INR	A
	JNZ	RNDIM		;GET MATCH DIRECTORY
	POP	B
	PUSH	B
	MVI	L,4
	INR	C		;READ MODE IS  C -1
	JZ	RNIDC		;UNWRITEN EXTENT
	CALL	GADIR		;WRITE MODE, SO SEARCH AVAILABLE DIRECTORY
	MVI	L,5
	LDA	OTPAR
	INR	A
	JZ	RNIDC		;DIRECTORY OVERFLOW
RNDIM:				;GET MATCH DIRECTORY
	POP	B
	XRA	A
	STA	OTPAR
	RET
RNIDC:				;ERROR   L IS ERROR CODE
	PUSH	H
	CALL	MDPNT
	MVI	M,0C0H		;SET ERROR CODE
	POP	H
RNDIE:
	POP	B
	MOV	A,L
	STA	OTPAR
	JMP	MDOPN
;
;  RANDOM READ
;
RREAD:
	MVI	C,-1		;READ MODE
	CALL	RNDIR
	CZ	RNEXR		;READ WHEN NOT ERROR
	RET
;
;  RANDOM WRITE
;
RWRIT:
	MVI	C,0		;WRITE MODE
	CALL	RNDIR
	CZ	WNEXR		;WRITE WHEN NOT ERROR
	RET
;
;  COMPUTE SIZE FROM FCB DATA
;  INPUT
;  HL:DIRECTORY TOP
;  DE:BIAS
;  OUTPUT
;  ABC:COUNT
;
DRSIZ:
	XCHG
	DAD	D
	MOV	C,M		;GET RECODE COUNT OR CURRENT RECODE COUNT
	MVI	B,0
	LXI	H,12
	DAD	D
	MOV	A,M		;GET EXTENT
	RRC
	ANI	80H
	ADD	C
	MOV	C,A		;GET LOWER 8 BITS
	MVI	A,0
	ADC	B		;SAVE CARRY
	MOV	B,A
	MOV	A,M
	RRC
	ANI	0FH
	ADD	B
	MOV	B,A		;GET HIGHER 4 BITS
	LXI	H,14
	DAD	D
	MOV	A,M		;GET EXTENTION
	ADD	A
	ADD	A
	ADD	A
	ADD	A
	PUSH	PSW		;SAVE CF
	ADD	B		;GET HIGHER BYTE
	MOV	B,A
	PUSH	PSW
	POP	H
	MOV	A,L		;GET FLAG BYTE
	POP	H
	ORA	L
	ANI	1		;GET OVER FLOW BIT
	RET
;
;  COMPUTE FILE LENGTH BY DIRECTORY SEARCH
;
CFSIZ:
	MVI	C,12
	CALL	DRSRH		;GET DIRECTORY ONLY NAME
	LHLD	INPAR
	LXI	D,33
	DAD	D
	PUSH	H
	MOV	M,D
	INX	H
	MOV	M,D
	INX	H
	MOV	M,D		;CLEAR COUNTER
CFSIC:
	CALL	DICHK
	JZ	CFSIE		;END
	CALL	GDRPT		;GET DIRECTORY POINT
	LXI	D,15
	CALL	DRSIZ		;GET SIZE BY RECODE COUNT
	POP	H
	PUSH	H
	MOV	E,A
	MOV	A,C
	SUB	M
	INX	H
	MOV	A,B
	SBB	M
	INX	H
	MOV	A,E
	SBB	M		;COMPARE WITH NOW MAX COUNT
	JC	CFSIS		;NOW IS SMALL, SO NOT MATCH
	MOV	M,E
	DCX	H
	MOV	M,B
	DCX	H
	MOV	M,C		;SET LARGER NUMBER
CFSIS:
	CALL	DRMAT		;MATCHING OF DIRECTORY
	JMP	CFSIC
CFSIE:				;END
	POP	H
	RET
;
;  36:SET RANDOM RECODE COUNT
;
MSRRC:
	LHLD	INPAR
	LXI	D,32		;CURRENT RECODE
	CALL	DRSIZ		;GET COUNT BY CURRENT RECODE COUNT
	LXI	H,33
	DAD	D
	MOV	M,C
	INX	H
	MOV	M,B
	INX	H
	MOV	M,A		;SET COUNT OF NOW
	RET
;
;  LOG-IN & SELECT DRIVE
;
DVSET:
	LDA	OUTSP		;NEW DRIVE
	LXI	H,NDRIV		;CURRENT DRIVE
	MOV	M,A		;CHANGE DRIVE
;
;  DRIVE SELECT
;
DVSEL:
	LHLD	DLOGI		;GET DISK LOG-IN VETCOR
	LDA	NDRIV		;GET CORRENT DRIVE
	MOV	C,A
	CALL	DSHFR		;SHIFT TO VECTOR BIT
	PUSH	H
	XCHG
	CALL	GDTBL		;GET DISK PARAMETERS
	POP	H
	CZ	EDRIV		;NO DISK  SELECT ERROR
	MOV	A,L
	RAR			;GET LOG-IN VECTOR
	RC			;ALREADY LOG-IN DISK
	LHLD	DLOGI
	MOV	C,L
	MOV	B,H
	CALL	SDFLG		;SET LOG-IN BIT
	SHLD	DLOGI		;SAVE NEW VECTOR
	JMP	INDMP		;INITIALIZE OF DISK ALLOCATION MAP
;
;  CHECK ENTRY TYPE & SELECT
;
ENTRY:
	MVI	A,-1
	STA	FLMOD		;SET FILE MODE
	LHLD	INPAR
	MOV	A,M
	ANI	1FH
	DCR	A
	STA	OUTSP		;SAVE REQUIRED DISK CODE
	CPI	10H
	JC	ENTRE		;CURRENT DRIVE
	LDA	NDRIV
	STA	OUTSP
ENTRE:
	LDA	NDRIV		;GET CURRENT DISK
	STA	ENTDV		;SAVE DISK NUMBER
	MOV	A,M
	STA	ENTYP		;SAVE ENTRY TYPE
	ANI	0E0H
	MOV	M,A		;OFF THE REQUEST
	CALL	DVSET		;CHANGE DISK
	LDA	MDUSR
	LHLD	INPAR
	ORA	M
	MOV	M,A		;SET USER NUMBER
	RET
;
;  FREE DRIVE & CHECK
;
DVCHK:
	CALL	MFRDV		;FREE DRIVE
	LHLD	INPAR		;GET DRIVE CODE
DVCHW:				;FOR WRITE PROTECT CHECK
	XCHG
	LHLD	PDPNT
	LXI	B,12
	DAD	B		;GET THREAD TOP POINTER
DVCHL:				;ONE P.D. CHECK LOOP
	MOV	C,M
	INX	H
	MOV	B,M		;GET P.D.
	MOV	A,C
	ORA	B
	RZ			;END OF P.D.  ALL FREE OK
	LXI	H,28
	DAD	B
	MOV	A,M		;GET DRVACT
	ANA	E
	INX	H
	JNZ	DVCHS
	MOV	A,M
	ANA	D
	JNZ	DVCHT
	LXI	H,18
	DAD	B		;GET THREAD POINT
	JMP	DVCHL
;
DVCHS:
	MVI	L,-1
	JMP	DVCHT+2
;
DVCHT:
	MVI	L,7
	INR	L		;SEARCH DRIVE NUMBER
	RAR
	JNC	$-2
	MVI	A,'A'
	ADD	L		;GET DRIVE NAME
	PUSH	B
	PUSH	PSW
	CALL	GETPD
	LXI	D,14
	DAD	D
	MOV	D,M		;GET CONSOLE
	LXI	B,CDVCK
	CALL	BFPRN		;"DISK RESET DENIED DRIVE "
	POP	PSW
	MOV	C,A
	CALL	CONOT		;PRINT DRIVE NAME
	MVI	C,':'
	CALL	CONOT
	LXI	B,CDVCN
	CALL	BFPRN		;" CONSOLE "
	POP	H
	PUSH	H
	LXI	B,14
	DAD	B
	MOV	A,M		;GET CONSOLE
	ADI	'0'
	MOV	C,A
	CALL	CONOT
	LXI	B,CDVCP
	CALL	BFPRN		;" PROGRAM "
	POP	H
	CALL	CONIV		;PRINT PROGRAM NAME
	POP	H
	LXI	H,-1
	SHLD	OTPAR		;SET FAIL END FLAG
	RET
;
;
CDVCK:
	DB	CR,LF,'D',69H,73H,6BH
	DB	' ',72H,65H,73H,65H,74H
	DB	' ',64H,65H,6EH,69H,65H,64H
	DB	', D',72H,69H,76H,65H,' $'
CDVCN:
	DB	' C',6FH,6EH,73H,6FH,6CH,65H,' $'
CDVCP:
	DB	' P',72H,6FH,67H,72H,61H,6DH,' $'
;
;  12:GET VERSION NUMBER
;
MVSNM:
	LXI	H,0122H
	SHLD	OTPAR		;NOW VERSION NUMBER IS MP/M 1.1
	RET
;
;  13:RESET DISK SYSTEM
;
MINBD:
	LXI	H,-1
	SHLD	INPAR
	CALL	DVCHK		;RESET ALL DRIVE & CHECK
	LXI	H,0
	SHLD	DROVC		;CLEAR R/O VECTOR
	SHLD	DLOGI		;CLEAR LOG-IN VECTOR
	XRA	A
	STA	NDRIV		;CURRENT DRIVE TO 0
	CALL	GETMS		;GET MEMORY SEGMENT
	LHLD	PDPNT
	LXI	B,145
	DAD	B
	ADD	A
	ADD	A
	MOV	E,A
	MVI	D,0
	DAD	D
	MOV	H,M		;GET MEMORY SEGMENT TOP
	MVI	L,80H
	JMP	MSDMA+3;SET DMA ADDRESS
;
;  14:SELECT DISK
;
MDVSL:
	LDA	INPAR
	ANI	0FH
	PUSH	PSW
	CALL	DVSET		;SELECT DISK
	CALL	GETPD		;GET P.D. POINT
	LXI	B,22
	DAD	B		;GET DRIVE CODE POINT
	MOV	A,M
	ANI	0FH		;GET USER CODE
	RRC
	RRC
	RRC
	RRC
	MOV	B,A
	POP	PSW
	ORA	B		;GET NEW CODE
	RRC
	RRC
	RRC
	RRC
	MOV	M,A		;SAVE NEW CODE
	RET
;
;  15:OPEN FILE
;
MOPEN:
	CALL	MDCLS		;CLEAR R/W MODE
	CALL	ENTRY		;CHECK ENTRY MODE
	JMP	OPEN		;OPEN OF FILE
;
;  16:CLOSE FILE
;
MCLOS:
	CALL	ENTRY
	JMP	CLOSE		;CLOSE OF FILE
;
;  17:SEARCH FIRST
;  IF ENTRY TYPE IS "?", ALL DIRECTORY
;
MSERH:
	MVI	A,-1
	STA	DIRMD		;DIRECTORY BUFFER MODE TO DMA BUFFER
	MVI	C,0		;LENGTH ZERO FOR ALL DIRECTORY
	LHLD	INPAR
	MOV	A,M
	CPI	'?'
	JZ	MSERS		;ALL DIRECTORY
	CALL	EXTPT
	MOV	A,M
	CPI	'?'
	CNZ	MDCLS		;TO WRITE MODE
	CALL	ENTRY
	MVI	C,15		;COMPARE LENGTH FULL
MSERS:
	JMP	DRSRH		;SEARCH FILE
;
;  18:SEARCH FOR NEXT OCCURRENCE
;
MSENX:
	MVI	A,-1
	STA	DIRMD		;DIRECTORY MODE TO DMA BUFFER
	LHLD	FCBPN		;GET IMPLICIT FCB POINTER
	SHLD	INPAR		;SET TO PARAMETER
	CALL	ENTRY		;CHECK ENTRY TYPE
	JMP	DRMAT		;DIRECTORY MATCHING
;
;  19:DELETE FILE
;
MDELE:
	CALL	ENTRY
	CALL	DEDMP		;DELETE
	JMP	SDCNT		;GET DIRECTORY CODE
;
;  20:READ NEXT RECODE
;
MRDNX:
	CALL	ENTRY
	JMP	RNEXT		;READ NEXT
;
;  21:WRITE NEXT RECODE
;
MWTNX:
	CALL	ENTRY
	JMP	WNEXT		;WRITE NEXT
;
;  22:MAKE FILE
;
MAKFL:
	CALL	MDCLS		;CLEAR R/W MODE TO WRITE
	CALL	ENTRY
	JMP	GADIR		;GET AVAILABLE DIRECTORY
;
;  23:RENAME
;
MRNAM:
	CALL	ENTRY
	CALL	RENAM		;RENAME
	JMP	SDCNT
;
;  24:INTERROGATE LOG-IN VECTOR
;
MLIVC:
	LHLD	DLOGI		;GET LOG-IN VECTOR
	SHLD	OTPAR
	RET
;
;  25:INTERROGATE DISK NUMBER
;
MNDIV:
	LDA	NDRIV		;CURRENT DISK
	STA	OTPAR
	RET
;
;  26:SET DMA ADDRESS
;
MSDMA:
	LHLD	INPAR
	XCHG
	CALL	GETPD		;GET P.D. POINT
	LXI	B,20
	DAD	B
	MOV	M,E
	INX	H
	MOV	M,D		;SET TO P.D.
	XCHG
	SHLD	DMADD
	JMP	STDMA
;
;  27:INTERROGATE ALLOCATION MAP POSITION
;
MALOC:
	LHLD	ALV
	SHLD	OTPAR
	RET
;
;  28:WRITE PROTECT DISK
;
MWTPR:
	LDA	NDRIV		;GET CURRENT DISK
	MOV	C,A
	LXI	H,1
	CALL	DSHFL		;GET BIT
	CALL	DVCHW		;CHECK P.D.
	JMP	SHSER		;SET FLAG
;
;  29:GET R/O VECTOR
;
MGWPR:
	LHLD	DROVC
	SHLD	OTPAR
	RET
;
;  30:SET FILE ATTRIBUTE
;
MSFAT:
	CALL	ENTRY
	CALL	SFATR		;SET ATTRIBUTE
	JMP	SDCNT
;
;  31:GET DISK PARAMETER ADDRESS
;
MGDPR:
	LHLD	DPB
	SHLD	OTPAR
	RET
;
;  32:SET OR GET USER CODE
;
MUSER:
	LDA	OUTSP
	CPI	-1
	JNZ	MUSES		;SET MODE
	LDA	MDUSR		;GET MODE
	STA	OTPAR
	RET
MUSES:				;SET MODE
	ANI	0FH
	STA	MDUSR
	CALL	GETPD
	LXI	B,22
	DAD	B
	LDA	MDUSR
	MOV	B,A
	MOV	A,M
	ANI	0F0H
	ORA	B		;GET NEW CODE
	MOV	M,A		;SET NEW CODE TO P.D.
	RET
;
;  33:READ RANDOM
;
MRDRN:
	CALL	ENTRY
	JMP	RREAD
;
;  34:WRITE RANDOM
;
MWTRN:
	CALL	ENTRY
	JMP	RWRIT
;
;  35:COMPUTE FILE SIZE
;
MCFSZ:
	CALL	ENTRY
	JMP	CFSIZ
;
;  37:RESET DISK
;
MRSDV:
	CALL	DVCHK		;FREE DRIVE & CHECK
	LHLD	INPAR
	MOV	A,L
	CMA
	MOV	E,A
	MOV	A,H
	CMA			;GET MASK
	LHLD	DLOGI		;GET LOG-IN VETCOR
	ANA	H
	MOV	D,A
	MOV	A,L
	ANA	E
	MOV	E,A		;OFF THE BIT OF LOG-IN
	LHLD	DROVC		;GET R/O VECTOR
	XCHG
	SHLD	DLOGI
	MOV	A,L
	ANA	E
	MOV	L,A
	MOV	A,H
	ANA	D
	MOV	H,A		;OFF THE BIT OF R/O VECTOR
	SHLD	DROVC
	RET
;
;  38:ACCESS DRIVE
;
MACDV:
	LHLD	INPAR
	XCHG
	CALL	GETPD
	LXI	B,28
	DAD	B		;GET DRIVE POINT
	MOV	A,M
	ORA	E
	MOV	M,A
	INX	H
	MOV	A,M
	ORA	D
	MOV	M,A		;SET DRVACT CODE
	RET
;
;  39:FREE DRIVE
;
MFRDV:
	LHLD INPAR
	MOV	A,H
	CMA
	MOV	D,A
	MOV	A,L
	CMA
	MOV	E,A		;INVERT THE VECTOR
	CALL	GETPD
	LXI	B,28
	DAD	B		;GET DRVACT POINT
	MOV	A,M
	ANA	E
	MOV	M,A
	INX	H
	MOV	A,M
	ANA	D
	MOV	M,A		;OFF THE ACTIVE BIT
	RET
;
;  40:WRITE RANDOM WITH ZERO FILL
;
MWTRZ:
	CALL	ENTRY
	MVI	A,2
	STA	URCNT		;SET MODE
	MVI	C,0
	CALL	RNDIS		;GET TERGET DIRECTORY
	JZ	WNEXR		;WRITE IF NO ERROR
	RET			;SOME ERROR
;
;  BDOS END PROCESS
;
BDOSE:
	LDA	FLMOD		;GET FILE MODE
	ORA	A
	JZ	BDOSF		;NOT FILE COMMAND
	LHLD	INPAR
	MVI	M,0		;CLEAR USER CODE & DATA
	LDA	ENTYP		;GET ENTRY TYPE
	ORA	A
	JZ	BDOSF		;SIMPLE ENTRY TYPE
	MOV	M,A		;SET ENTRY TYPE
	LDA	ENTDV		;GET ENTRY DISK
	STA	OUTSP		;SET DISK
	CALL	DVSET		;TO ENTRIED DISK
BDOSF:
	LHLD	INSTK
	SPHL			;RESTORE STACK POINTER
	LHLD	OTPAR
	MOV	A,L
	MOV	B,H		;SET RETURN PARAMETER
	RET
;
;
DLCOD:	DB	0E5H		;DELETE CODE
;
;  DISK OPERATION DATA AREA
;
;  DISK VECTORS
;
DROVC:	DS	2		;R/O VECTOR
DLOGI:	DS	2		;LOG-IN VECTOR
;
;  DISK PARAMETERS
;
DMADD:	DS	2		;DMA ADDRESS POINTER
;
PHLEV:	DS	2		;HASH CHECK LEVEL SCRATCHPAD POINTER
PTRAK:	DS	2		;TRACK CALCULATE SCRATCHPAD POINTER
PSECT:	DS	2		;SECTOR CALCULATE SCRATCHPAD POINTER
;
;  EACH DISK PARAMETER COPY AREA
;
DIRBF:	DS	2		;ADDRESS OF DIRECTORY READ BUFFER
DPB:	DS	2		;ADDRESS OF DISK PARAMETER BLOCK
CSV:	DS	2		;ADDRESS OF HASH CHECK TABLE AREA
ALV:	DS	2		;ADDRESS OF ALLOCATION MAP AREA
;
SPT:	DS	2		;SECTOR / TRACK THIS VALUE IS COPY OF D.P.B.
BSH:	DS	1		;BLOCK SHIFT FACTOR
BLM:	DS	1		;BLOCK MASK
EXM:	DS	1		;EXTENT MASK
DSM:	DS	2		;TOTAL STRAGE CAPACITY -1
DRM:	DS	2		;TOTAL NUMBER OF DIRECTORY ENTRY -1
AL0:	DS	1		;ALLOCATION MAP MASK FOR DIRECTORY AREA
AL1:	DS	1
CKS:	DS	2		;SIZE OF HASH CHECK TABLE
OFF:	DS	2		;OFFSET OF THE DISK BEGINNING POINT FOR FILES
;
XTL:	DS	2		;LOGICAL TO PHYSICAL SECTOR TRANSFER VECTOR
;
;  OTHER DATA
;
EXMOD:	DS	1		;CLOSE MODE  -1 CLOSED
DOVMD:	DS	1		;READ OR WRITE MODE OF FILE  0 WRITE
DIRCC:	DS	1		;DIRECTORY CODE
URCNT:	DS	1		;UP COUNT OF RECODE COUNT & FLAG OF WRITE WITH ZERO
OUTSP:	DS	1		;SCRATCHPAD FOR INPUT OUTPUT DATA
DRBSW:	DS	1		;DIRECTORY BIAS FOR WRITE
;
	DS	2		;NOT USED
;
DSMMD:	DS	1		;DISK SIZE MODE  DSM < 256   = -1
FLMOD:	DS	1		;FILE MODE  0 NOT FILE COMMAND
ENTDV:	DS	1		;LAST DISK SAVE AREA FOR ENTRY
ENTYP:	DS	1		;ENTRY TYPE SAVE AREA
RECNT:	DS	1		;RECODE COUNT
EXTNT:	DS	1		;EXTENT OF RECODE COUNT
CRCNT:	DS	2		;CURRENT RECODE COUNT
TSECT:	DS	2		;TARGET SECTOR
BTSEC:	DS	2		;TARGET BLOCK TOP SECTOR
DIRMD:	DS	1		;DIRECTORY BUFFER MODE
BIDIR:	DS	1		;BIAS IN SECTOR
DIRSC:	DS	2		;SECTOR NUMBER IN DIRECTORY
;
;  PROCESS DEPEND DATA BLOCK
;
DIRCT:	DS	2		;DIREDTORY NUMBER
DRSLN:	DS	1		;LENGTH FOR COMPARISION TO DIRECTORY
FCBPN:	DS	2		;FCB POINTER
;
;
	ORG	13FAH		;$ AND 0FF00H OR 0FAH
;
;  XDOS BDOS ENTRY
;
	JMP	XBDOS
;
;  DISPATCHER ENTRY
;
	JMP	DISP
;
;
;  LINKS TO EXTENDED I/O SYSTEM
;
XIOS:
BOOT:	DS	3		;COLD START BOOTING
WBOOT:	DS	3		;WARM BOOTING
CONSTB:	DS	3		;CONSOLE STATUS
CONINB:	DS	3		;CONSOLE INPUT
CONOTB:	DS	3		;CONSOLE OUTPUT
LIST:	DS	3		;LIST OUTPUT
PUNCH:	DS	3		;PUNCH OUTPUT
READR:	DS	3		;READER INPUT
HOME:	DS	3		;MOVE DISK TO TRACK ZERO
SELDK:	DS	3		;SELECT DISK
SETRK:	DS	3		;SET TRACK NUMBER
SETSC:	DS	3		;SET SECTOR NUMBER
SETDM:	DS	3		;SET DMA ADDRESS
READ:	DS	3		;READ ONE SECTOR
WRITE:	DS	3		;WRITE ONE SECTOR
LISTS:	DS	3		;LIST STATUS
SCTRN:	DS	3		;SECTOR TRANSLATION
;
;  EXTENDED ROUTINES
;
	DS	18		;NOT USED IN BDOS
;
SYSIN:	DS	3		;INITIALIZE I/O SYSTEM
;
;
	END
