	CSEG		;INCLUDE WITH CODE SEGMENT
BIAS	EQU	01503H	;ADDRESS OF WBOOT ENTRY RELATIVE TO 0000
SSIZE	EQU	24	;24 LEVEL STACK
REBOOT	EQU	0000H	;REBOOT SYSTEM
;	BDOS INTERFACE MODULE
;
;	COPYRIGHT (C) 1978 DIGITAL RESEARCH
;	BOX 579 PACIFIC GROVE, CALIFORNIA
;
;	EXTERNALLY DEFINED DISK MONITOR ENTRY POINTS
	EXTRN	DSKMON
;
;	PUBLICALLY DEFINED ENTRY AND EXIT PARAMETERS
	PUBLIC	FUNC	;FUNCTION NUMBER
	PUBLIC	INFO	;INFORMATION ADDRESS IN CP/M CALL
	PUBLIC	ARET	;RETURNED VALUE
	PUBLIC	BOOT	;WARM START
	PUBLIC	CONRDY	;RETURNS CONSOLE STATUS
	PUBLIC	CONINE	;RETURNS CHARACTER IN A
	PUBLIC	CONCHAR	;CONSOLE CHARACTER SENT FROM C
	PUBLIC	LSTOUT	;LIST CHARACTER SENT FROM C
	PUBLIC	PUNOUT	;PUNCH CHARACTER SENT FROM C
	PUBLIC	READIN	;READER CHARACTER RETURNED IN A
	PUBLIC	TRACK0	;MOVE TRACK HEAD TO TRACK 0
	PUBLIC	SELDISK	;SELECT DISK DRIVE GIVEN BY REG C
	PUBLIC	SELTRK	;SELECT TRACK GIVEN BY REG C
	PUBLIC	SELSEC	;SELECT SECTOR GIVEN BY REG C
	PUBLIC	SELDMA	;SET DMA ADDRESS TO ADD IN B & C
	PUBLIC	READDISK	;READ DISK SECTOR
	PUBLIC	WRITEDISK	;WRITE DISK SECTOR
;
	DB	0,0,0,0,0,0
;
;
;
;	ENTER HERE FROM THE USER'S PROGRAM WITH FUNCTION NUMBER IN C,
;	AND INFORMATION ADDRESS IN D,E.  CALL THE PL/M DISK MONITOR
	JMP	BDOSE	;PAST PARAMETER BLOCK
;
	PUBLIC	PERERR
	PUBLIC	SELERR
	PUBLIC	RODERR	;USED BY BDOS FOR ERROR REPORTS
;	************************************************
;	*** RELATIVE LOCATIONS 0009 - 000E           ***
;	************************************************
PERERR:	DW	PERSUB	;PERMANENT ERROR SUBROUTINE
SELERR:	DW	SELSUB	;SELECT ERROR SUBROUTINE
RODERR:	DW	RODSUB	;RO DISK ERROR SUBROUTINE
;
;	FIXED DATA AREAS FOR USER PARAMETERS
;
	PUBLIC	TRSECT
	PUBLIC	TRAN
;	************************************************
;	** RELATIVE LOCATIONS 000F-0019 = TRSECT     ***
;	************************************************
TRSECT:	;TRANSLATE LOGICAL TO PHYSICAL SECTOR
;	REGISTER-C CONTAINS LOGICAL SECTOR 0 ... N
;	COMPUTE PHYSICAL SECTOR BASED UPON
;	SECTOR TRANSLATE TABLE.  NOTE:  THIS SUBROUTINE AND/OR
;	TABLE CAN BE REPLACED FOR USE WITH DIFFERING DRIVE
;	TYPES.
	LXI	H,TRAN	;0009 = LOAD TRANSLATE BASE
	MVI	B,0	;0012 = DOUBLE PRECISION LOGICAL SEC#
	DAD	B	;0014 = HL = .TRAN(SECTOR)
	MOV	C,M	;0015 = TRANSLATED VALUE TO C
	JMP	SELSEC	;0016 = TO SELECT PHYSICAL SECTOR
	NOP		;0019 = (FILL)
;
;	*************************************************
;	** RELATIVE LOCATIONS 001A-0033 TRAN (26 SECT) **
;	*************************************************
TRAN:	DB	01H,07H,0DH,13H
	DB	19H,05H,0BH,11H
	DB	17H,03H,09H,0FH
	DB	15H,02H,08H,0EH
	DB	14H,1AH,06H,0CH
	DB	12H,18H,04H,0AH
	DB	10H,16H
;
;	************************************************
;	** RELATIVE LOCATIONS 0034-0039 EXTEND TRAN   **
;	************************************************
	DB	        00H,00H	;34-35
	DB	00H,00H,00H,00H	;36-39
;
;	NOTE THAT TRAN CAN BE EXTENDED TO OCCUPY THE AREA
;	FROM 001A THROUGH 0039, OR 3AH - 1AH BYTES, OR
;	20H = 32 (DECIMAL) BYTES, WHERE
;	001AH: TRAN(0)	- TRANSLATION OF SECTOR 0
;	001BH: TRAN(1)	- TRANSLATION OF SECTOR 1
;	...
;	0039H: TRAN(31) - TRANSLATION OF SECTOR 31
;	IF THERE ARE MORE THAN 32 SECTORS TO TRANSLATE,
;	REPLACE
;			LXI H,TRAN
;	BY A REFERENCE TO YOUR OWN TABLE ELSEWHERE IN
;	MEMORY, OR REPLACE THE LXI INSTRUCTION BY A JUMP
;	TO A TRANSLATION SUBROUTINE.
;
	PUBLIC	SECSIZ		;3A - SECTOR SIZE
	PUBLIC	DIRMAX		;3B - DIRECTORY MAX
	PUBLIC	BLKSHF		;3C - BLOCK SHIFT
	PUBLIC	BLKMSK		;3D - BLOCK MASK
	PUBLIC	MAXALL		;3E - MAXIMUM ALLOC
	PUBLIC	DIRBLK		;3F - DIRECTORY BLOCKS
	PUBLIC	OSTRKS		;40 - OPERATING SYSTEM TRACKS
;	**************************************************
;	** RELATIVE LOCATIONS 003A-0040 HOLD PARAMETERS **
;	**************************************************
SECSIZ:	DB	26	;003A=SECTORS PER TRACK
DIRMAX:	DB	63	;003B=MAXIMUM DIRECTORY NUMBER
BLKSHF:	DB	3	;003C=2**3 = 8 SECTORS PER BLOCK
BLKMSK:	DB	111B	;003D=2**3-1
MAXALL:	DB	242	;003E=243 BLOCKS
DIRBLK:	DB	0C0H	;003F=1100 0000 RESERVES TWO BLOCKS
OSTRKS:	DB	2	;0040=NUMBER OF OPERATING SYSTEM TRACKS
;
;	************************************************
;	** END OF DISK PARAMETER BLOCK 0007-0040      **
;	************************************************
;
;
;
;
BDOSE:	;ARRIVE HERE FROM USER PROGRAMS
	XCHG
	SHLD	INFO
	LXI	H,FUNC	;INFORMATION ADDRESS AND FUNCTION STORED
	MOV	M,C
;	SAVE THE USER'S STACK POINTER, AND SET TO A LOCAL STACK
	LXI	H,0
	DAD	SP
	SHLD	ENTSP	;USE THE MONITOR'S STACK
	LXI	SP,LSTACK	;SET TO LOCAL STACK
	CALL	DSKMON
;
;	RETURN FROM THE DISK MONITOR
	LHLD	ENTSP
	SPHL		;ENTRY STACK POINTER RESTORED
	LHLD	ARET	;RETURNED VALUE
	MOV	A,L
	MOV	B,H	;B,A AND H,L CONTAIN RETURN VALUE
;	(COMPATIBILITY BETWEEN PL/M VERSIONS REQUIRES THIS)
	RET
;
;
;
OBOOT	EQU	00H
OCONRD	EQU	03H
OCONIN	EQU	06H
OCONCH	EQU	09H
OLSTOU	EQU	0CH
OPUNOU	EQU	0FH
OREADI	EQU	12H
OTRACK	EQU	15H
OSELDI	EQU	18H
OSELTR	EQU	1BH
OSELSE	EQU	1EH
OSELDM	EQU	21H
OREADD	EQU	24H
OWRITE	EQU	27H
;
;
;
BOOT	EQU	BIAS+OBOOT
CONRDY	EQU	BIAS+OCONRD
CONINE	EQU	BIAS+OCONIN
CONCHA	EQU	BIAS+OCONCH
LSTOUT	EQU	BIAS+OLSTOU
PUNOUT	EQU	BIAS+OPUNOU
READIN	EQU	BIAS+OREADI
TRACK0	EQU	BIAS+OTRACK
SELDIS	EQU	BIAS+OSELDI
SELTRK	EQU	BIAS+OSELTR
SELSEC	EQU	BIAS+OSELSE
SELDMA	EQU	BIAS+OSELDM
READDI	EQU	BIAS+OREADD
WRITED	EQU	BIAS+OWRITE
;
;
;	EQUATES FOR NON GRAPHIC CHARACTERS
CTLC	EQU	03H	;CONTROL C
CTLS	EQU	13H	;STOP/START SCREEN
CTLU	EQU	15H	;LINE DELETE
CTLE	EQU	05H	;PHYSICAL EOL
CTLP	EQU	10H	;PRNT TOGGLE
CTLR	EQU	12H	;REPEAT LINE
CTLX	EQU	18H	;=CTL-U
CTLZ	EQU	1AH	;END OF FILE
RUBOUT	EQU	7FH	;CHAR DELETE
TAB	EQU	09H	;TAB CHAR
CR	EQU	0DH	;CARRIAGE RETURN
LF	EQU	0AH	;LINE FEED
CTL	EQU	5EH	;UP ARROW
;
	PUBLIC	CONIN	;CONSOLE INPUT
	PUBLIC	CONECH	;CONSOLE WITH ECHO
	PUBLIC	CONBRK	;CONSOLE BREAK
	PUBLIC	CONOUT	;CONSOLE OUT
	PUBLIC	TABOUT	;TAB OUT
	PUBLIC	CRLF	;CARRIAGE RETURN LINE FEED
	PUBLIC	PRINT	;PRINT 'TIL $
	PUBLIC	READ	;READ LINE
;

;	ERROR SUBROUTINES
PERSUB:	;REPORT PERMANENT ERROR
	LXI	H,PERMSG
	CALL	ERRFLG	;TO REPORT THE ERROR
	CPI	CTLC
	JZ	REBOOT
	RET		;RETURN, IGNORE ERROR
;
SELSUB:	;REPORT SELECT ERROR
	LXI	H,SELMSG
	JMP	WAITER	;WAIT FOR CONSOLE CHAR BEFORE BOOT
;
RODSUB:	;REPORT WRITE TO READ/ONLY DISK
	LXI	H,RODMSG
WAITER:	CALL	ERRFLG
	JMP	REBOOT
;
ERRFLG:	;REPORT ERROR TO CONSOLE, MESSAGE ADDRESS IN HL
	PUSH	H	;SAVE IT
	CALL	CRLF	;CLEAR TO NEW LINE
	LDA	CURDSK
	ADI	'A'	;CURRENT DISK NAME
	STA	DSKERR	;STORE INTO MESSAGE AREA
	LXI	B,DSKMSG
	CALL	PRINT	;PRINT TO THE END OF MESSAGE
	POP	B	;GET MESSAGE
	CALL	PRINT	;SEND TO CONSOLE
	JMP	CONIN	;READ CONSOLE CHARACTER
;
;	ERROR MESSAGES
DSKMSG:	DB	'BDOS ERR ON '
DSKERR:	DB	' : $'	;FILLED IN BY ERRFLG
PERMSG:	DB	'BAD SECTOR$'
SELMSG:	DB	'SELECT$'
RODMSG:	DB	'R/O$'
;
;
;	CONSOLE HANDLERS
CONIN:	;READ CONSOLE CHARACTER TO REG A
	LXI	H,KBCHAR;ALREADY FILLED?
	MOV	A,M
	MVI	M,0	;CLEAR IT IF SO
	ORA	A	;SET FLAGS
	RNZ		;IF NON ZERO, THEN RETURN KBCHAR
	JMP	CONINE	;GET CHARACTER EXTERNALLY
;
CONECH:	;READ CHARACTER WITH ECHO
	CALL	CONIN
	CALL	ECHOC	;ECHO CHARACTER?
	RC		;CARRY IF NOT GRAPIC OR CONTROL
	PUSH	PSW	;SAVE THE CHARACTER
	MOV	C,A
	CALL	TABOUT
	POP	PSW
	RET		;WITH CHAR IN A
;
ECHOC:	;ECHO CHARACTER IF GRAPHIC OR CR, LF, TAB
	CPI	CR
	RZ
	CPI	LF
	RZ
	CPI	TAB
	RZ
	CPI	' '
	RET		;CARRY IF NOT GRAPHIC HERE
;
;
CONBRK:	;CHECK FOR CHARACTER READY
	LDA	KBCHAR	;ALREADY FILLED?
	ORA	A
	JNZ	CONB1	;RETURN WITH 1 IF FILLED
	CALL	CONRDY	;CHECK FOR CHARACTER READY
	ANI	1	;CLEAR ALL BUT LSB
	RZ		;RETURN IF ZERO, OTHERWISE READ IT
	CALL	CONINE	;GET CHARACTER TO A
	CPI	CTLS	;MAY BE SCREEN FUNTCTION
	JNZ	CONB0	;RETURN 1 - SAVE CHAR
	CALL	CONINE	;STOP OUTPUT, CHECK CHAR
	CPI	CTLC	;REBOOT?
	JZ	REBOOT
	XRA	A	;CLEAR CHARACTER AND RETURN
	RET
CONB0:	;CHARACTER IN ACCUM, SAVE IT
	STA	KBCHAR
CONB1:	;RETURN WITH 1 FOR CONSOLE BREAK
	MVI	A,1
	RET
;
CONOUT:	;WRITE CONSOLE CHARACTER FROM C
	PUSH	B	;CHAR SAVED FOR LATER TESTS
	CALL	CONBRK	;CHECK FOR SCREEN STOP FUNCTION
	POP	B	;RECALL CHARACTER TO C
	PUSH	B	;SAVE IT AGAIN
	CALL	CONCHAR	;TO WRITE THE CHARACTER
	POP	B	;RECALL IT AGAIN
	PUSH	B	;SAVE IT FOR LATER TESTS
	LDA	LISTCP	;LIST COPY TOGGLE
	ORA	A	;SET?
	CNZ	LSTOUT	;TO PRINTER
	POP	B	;RECALL CHARACTER
	MOV	A,C	;GRAPIC?
	LXI	H,COLUMN
	CPI	RUBOUT
	RZ		;NO INCREMENT IF RUBOUT
	INR	M	;INCREMENT COLUMN COUNT
	CPI	' '
	RNC		;NO CARRY GEN'ED IF GRAPHIC
	DCR	M	;NO COLUMN MOVEMENT
	CPI	LF	;END OF LINE?
	RNZ		;DONE IF NOT
	MVI	M,0	;CLEAR COLUMN COUNTER
	RET
;
CTLOUT:	;SEND CHARACTER WITH POSSIBLE PRECEDING ^
;	CHARACTER IS ASSUMED TO BE IN C
	MOV	A,C
	CALL	ECHOC	;TAB, CR, OR LF?
	JNC	TABOUT	;SKIP IF GRAPIC OR TAB,CR,LF
;	SEND PRECEDING UP ARROW
	PUSH	PSW
	MVI	C,CTL
	CALL	CONOUT	;UP ARROW
	POP	PSW	;RECALL CHAR
	ORI	40H	;BECOMES GRAPHIC
	MOV	C,A
;
TABOUT:	;EXPAND TABS TO CONSOLE
	MOV	A,C	;COMPARE WITH TAB
	CPI	TAB
	JNZ	CONOUT	;DIRECT TO CONSOLE IF NOT
TAB0:	MVI	C,' '	;PAD TO NEXT COLUMNAR POSITION
	CALL	CONOUT
	LDA	COLUMN
	ANI	111B	;MOD 8
	JNZ	TAB0	;FOR ANOTHER ' '
	RET
;
CRLFP:	;# CRLF
	MVI	C,'#'
	CALL	CONOUT
;
CRLF:	;CARRIAGE RETURN LINE FEED
	MVI	C,CR
	CALL	CONOUT
	MVI	C,LF
	JMP	CONOUT
;
PRINT:	;PRINT MESSAGE GIVEN BY BC 'TIL $
	LDAX	B
	CPI	'$'	;END OF MESSAGE?
	RZ		;RETURN IF SO
	INX	B	;TO NEXT CHARACTER
	PUSH	B
	MOV	C,A	;READY TO PRINT
	CALL	TABOUT	;SEND THE CHARACTER
	POP	B	;RECALL NEXT TO GET ADDR
	JMP	PRINT
;
READ:	;READ TO INFO ADDRESS (MAX LENGTH, CURRENT LENGTH, BUFFER)
	LHLD	INFO	;MAX LENGTH
	MOV	C,M	;SAVE IN C
	INX	H	;TO CURRENT LENGTH ADDRESS
	PUSH	H	;SAVE FOR LATER FILL
	MVI	B,0	;CURRENT ACTIVE LENGTH
READNX:	;READ NEXT CHARACTER
	PUSH	B	;SAVE CURRENT/MAX LENGTHS
	PUSH	H	;SAVE NEXT TO FILL-1
READN0:	CALL	CONIN	;NEXT CHARACTER IN
	ANI	7FH	;CLEAR PARITY
	POP	H	;RECALL NEXT TO FILL-1
	POP	B	;RECALL LENGTHS
	CPI	CR	;END OF LINE?
	JZ	READEN	;SKIP TO END IF SO
	CPI	RUBOUT	;CHARACTER DELETE?
	JNZ	NOTRUB	;SKIP IF NOT
	MOV	A,B	;RUBOUT CHARACTER, IF POSSIBLE
	ORA	A	;ZERO LENGTH?
	JZ	READNX	;SKIP DELETE IF SO
	MOV	A,M	;LAST FILLED CHARACTER
	DCR	B	;DEC LENGTH TO DELETE IT
	DCX	H	;BACKUP POINTER TO BUFFER
	JMP	RDECH1	;ACT LIKE THIS IS AN ECHO
;
NOTRUB:	;NOT A RUBOUT, CHECK FOR END OF LINE
	CPI	CTLE
	JNZ	NOTE	;SKIP IF NOT
	PUSH	B
	PUSH	H	;READY FOR CRLF SEQUENCE
	CALL	CRLF
	JMP	READN0	;FOR ANOTHER CHARACTER
;
NOTE:	;NOT END OF LINE, CTL-P?
	CPI	CTLP
	JNZ	NOTP	;SKIP IF NOT
	PUSH	H	;INVERT THE PRINT TOGGLE
	LXI	H,LISTCP
	MVI	A,1	;1-LISTCP
	SUB	M
	MOV	M,A	;BACK TO LISTCOPY
	POP	H	;RECALL NXT TO FILL-1
	JMP	READNX
;
NOTP:	;NOT THE PRINT TOGGLE
	CPI	CTLX	;LINE DELETE (ALTERNATE TO CTLX)
	JZ	DELINE
	CPI	CTLU	;LINE DELETE?
	JNZ	NOTU
DELINE:	CALL	CRLFP	;BACK TO BEGINNING OF LINE
	POP	H	;THROW AWAY PUSHED VALUE
	JMP	READ	;START ALL OVER
;
NOTU:
	CPI	CTLR	;REPEAT LINE?
	JNZ	NOTR
	PUSH	B	;SAVE LINE LENGTH
	CALL	CRLFP	;RETURN CARRIAGE
	POP	B	;RECALL LINE LENGTH
	POP	H	;RECALL START ADDRESS OF BUFFER-1
	PUSH	H	;PUT IT BACK
	PUSH	B	;SAVE LINE LENGTH
REP0:	MOV	A,B	;LINE LENGTH COUNTED DOWN TO ZERO?
	ORA	A
	JZ	REP1	;END OF REPEAT?
	INX	H	;NO, GET NEXT CHARACTER
	MOV	C,M	;READY TO PRINT
	DCR	B	;COUNT B DOWN
	PUSH	B	;SAVED FOR PRINTOUT
	PUSH	H	;SAVED FOR PRINTOUT
	CALL	CTLOUT	;CHARACTER ECHOED
	POP	H	;RECALL NEXT ADDR-1
	POP	B	;RECALL REMAINING COUNT
	JMP	REP0	;FOR ANOTHER CHARACTER
REP1:	POP	B	;RECALL LENGTHS
	JMP	READNX	;FOR ANOTHER CHARACTER
;
NOTR:
RDECHO:	INX	H	;NEXT TO FILL
	MOV	M,A	;STORE THE CHARACTER IN THE BUFFER
	INR	B	;INCREMENT THE LENGTH
RDECH1:	;LOOK FOR CONTROL CHARACTERS
	PUSH	B
	PUSH	H	;SAVE THE PARAMETERS
	MOV	C,A	;READY TO PRINT
	CALL	CTLOUT	;MAY BE ^CHAR
	POP	H
	POP	B	;PARAMETERS READY FOR CHECKS
	MOV	A,M	;RECALL CHARACTER
	CPI	CTLC	;SET FLAGS FOR REBOOT CHECK
	MOV	A,B	;CHECK THE LENGTH
	JNZ	NOTCTC	;SKIP IF NOT CTLC
;	CTLC FOUND, MUST BE LENGTH = 1
	CPI	1	;LENGTH ONE
	JZ	REBOOT	;BOOT THE SYSTEM IF FOUND
NOTCTC:	CMP	C	;UP TO THE END OF THE BUFFER?
	JC	READNX	;FOR ANOTHER CHARACTER
;
READEN:	;END OF READ, FILL CURRENT LENGTH
	POP	H	;.CURRENT LENGTH
	MOV	M,B	;FILLED TO MEMORY
	MVI	C,CR	;RETURN CARRIAGE
	JMP	CONOUT	;RETURN THROUGH CONOUT
;
;
;	DATA AREAS
	PUBLIC	COLUMN
	PUBLIC	LISTCP	;LIST COPY
	PUBLIC	KBCHAR	;KEYBOARD CHARACTER
	PUBLIC	CURDSK	;CURRENT DISK FOR ERR MESSAGES
;
COLUMN:	DB	0	;COLUMN POSITION
LISTCP:	DB	0	;LISTING TOGGLE
KBCHAR:	DB	0	;INITIAL KEY CHAR = 00
CURDSK:	DB	0	;CURRENT DISK NUMBER
;
FUNC:	DS	1	;FUNCTION NUMBER
INFO:	DS	2	;INFORMATION ADDRESS
ARET:	DS	2	;ADDRESS VALUE TO RE
