;DOSMISC/ASM
*TITLE	'DOSMISC - SYSTEM & MATH ROUTINES'
;
;	THIS PACKAGE CONTAINS SYSTEM ROUTINES AND
;	MATH OPERATIONS THE FOLLOWING ARE CONTAINED:
;
;		$PRLINE - OUTPUT LINE TO PRINTER
;		$VDLINE - OUTPUT LINE TO VIDEO
;		$KILL	- KILL OPEN/CLOSED FILE
;		$DIRRED - READ DIRECTORY FOR FILE
;		$DIRWRT - WRITE DIRECTORY FOR FILE
;		$SMULT	- SINGLE PRECISION MULTIPLY
;		$SDIVD	- SINGLE PRECISION DIVIDE
;		$DMULT	- DOUBLE PRECISION MULTIPLY
;		$DDIVD	- DOUBLE PRECISION DIVIDE
;		$TMULT	- TRIPLE PRECISION MULTIPLY
;		$TDIVD	- TRIPLE PRECISION DIVIDE
;
*EJECT
;	DEVICE LINE HANDLER(S)
;
;	ENT	 B =	BUFFER LENGTH
;		 C =	TERM CHARACTER
;		HL =>	ASCII TEXT
;
PRLINE	LD	A,PDCB@ 	;PRINTER DEVICE
	JR	DVLINE		;SKIP
;
VDLINE	LD	A,DDCB@ 	;DISPLAY DEVICE
;
DVLINE	CALL	REGSAV		;SAVE REGISTERS
	CALL	LOCDCB		;LOCATE DCB
	PUSH	IX
	POP	DE		;DE => DCB
	INC	B
	DEC	B		;NULL?
	JR	Z,DVLRET	;SKIP
;
DVLIN1	PUSH	BC		;SAVE COUNT
	LD	B,(HL)		;GET CHAR
	CALL	PUT		;OUTPUT
	POP	BC		;GET COUNT
	RET	NZ		;IF ERROR
	INC	HL		;NEXT
	DJNZ	DVLIN1		;TIL DONE
DVLRET	INC	C
	DEC	C		;ANY TERM?
	LD	B,C		;GET TERM
	CALL	NZ,PUT		;IF YES
	RET
;
*EJECT
;	KILL FILE ROUTINE
;
;	ENT	DE =>	FILE DCB
;
KILL	PUSH	HL		;SAVE
	LD	HL,PLIST	;OPEN PARAM LIST
	LD	A,(DE)		;GET TYPE
	CPL			;INVERT
	AND	80H		;OPEN?
	CALL	NZ,OPEN 	;OPEN FILE
	POP	HL		;RESTORE
	CALL	Z,KILLO 	;NO ERROR
	RET
;
*EJECT
;	READ/WRITE DIR FOR SPECIFIC FILE
;
;	ENT	 B =	LFN
;		 C =	DEVICE NUMBER
;
;	EXT	HL =>	DIRECTORY ENTRY
;
DIRRED	LD	A,6		;SREAD
	CALL	DIRIO		;GO--
	RET	Z		;ALL OK
	LD	A,17		;DIR READ ERROR!
	RET
;
DIRWRT	LD	A,7		;SWRITE
	CALL	DIRIO		;GO--
	RET	Z		;ALL OK
	LD	A,18		;DIR WRITE ERROR!
	RET
;
;	CONVERT LFN AND PERFORM I/O
;
;	ENT	 B =	LOGICAL FILE NUMBER
;		 C =	DEVICE NUMBER
;
;	EXT	HL =>	DIRECTORY ENTRY
;
DIRIO	PUSH	BC		;SAVE
	PUSH	DE		;SAVE
	PUSH	AF		;SAVE I/O
	LD	A,B		;LFN
	AND	0E0H		;SEC
	LD	L,A
	LD	H,BUFFER<-8	;HL => FILE
	XOR	B		;LOW NIB
	ADD	A,2		;CORRECT
	LD	E,A
	POP	AF		;GET I/O
	PUSH	HL		;SAVE => FILE
	LD	B,0		;BE = SECTOR
	LD	L,B		;HL => BUFFER
	RST	IODISK		;DO IT!
	POP	HL		;HL => FILE
	POP	DE		;RESTORE
	POP	BC		;RESTORE
	RET
;
*EJECT
;	SINGLE PRECISION MULTIPLY
;
;	ENT	E =	MULTIPLICAND
;		A =	MULTIPLIER
;
;	EXT	A =	RESULT
;
SMULT	PUSH	BC		;SAVE
	LD	D,A		;D = MULTIPLIER
	XOR	A		;INIT RESULT
	LD	B,8		;MULTIPLIER PRECISION
SMULT1	ADD	A,A		;SHIFT RESULT LEFT
	SLA	E		;1 BIT?
	JR	NC,SMULT2	;IF NOT
	ADD	A,D		;RESULT+MULTIPLICAND
SMULT2	DJNZ	SMULT1		;TIL DONE
	POP	BC		;RESTORE
	RET
;
;	SINGLE PRECISION DIVIDE
;
;	ENT	E =	DIVIDEND
;		A =	DIVISOR
;
;	EXT	A =	QUOTIENT
;		E =	REMAINDER
;
SDIVD	PUSH	BC		;SAVE
	LD	C,A		;C = DIVISOR
	LD	B,8		;DIVIDEND PRECISION
	XOR	A		;INIT REMAINDER
SDIVD1	SLA	E		;SHIFT DIVIDEND LEFT
	RLA			;OVERFLOW TO REMAINDER
	CP	C		;AT DIVISOR?
	JR	C,SDIVD2	;IF NOT
	SUB	C		;REMAINDER-DIVISOR
	INC	E		;QUOTIENT+1
SDIVD2	DJNZ	SDIVD1		;TIL DONE
	LD	C,A		;C = REMAINDER
	LD	A,E		;A = QUOTIENT
	LD	E,C		;E = REMAINDER
	POP	BC		;RESTORE
	RET
;
*EJECT
;	DOUBLE PRECISION MULTIPLY
;
;	ENT	HL =	MULTIPLICAND
;		 A =	MULTIPLIER
;
;	EXT	HL =	RESULT (MSB'S)
;		 A =	RESULT (LSB)
;
DMULT	PUSH	BC		;SAVE
	EX	DE,HL		;DE = MULTIPLICAND
	LD	C,A		;C = MULTIPLIER
	LD	HL,0		;INIT RESULT
	LD	A,L		;INIT RESULT
	LD	B,8		;MULTIPLIER PRECISION
DMULT1	ADD	HL,HL		;SHIFT RESULT LEFT
	RLA			;MSB RESULT
	RLC	C		;1 BIT?
	JR	NC,DMULT2	;IF NOT
	ADD	HL,DE		;RESULT+MULTIPLICAND
	ADC	A,0		;MSB RESULT
DMULT2	DJNZ	DMULT1		;TIL DONE
	LD	C,A		;C = MSB
	LD	A,L		;A = LSB
	LD	L,H		;L = NSB
	LD	H,C		;H = MSB
	POP	BC		;RESTORE
	RET
;
;	DOUBLE PRECISION DIVIDE
;
;	ENT	HL =	DIVIDEND
;		 A =	DIVISOR
;
;	EXT	HL =	QUOTIENT
;		 A =	REMAINDER
;
DDIVD	PUSH	DE		;SAVE
	LD	D,A		;D = DIVISOR
	LD	E,16		;DIVIDEND PRECISION
	XOR	A		;0 LS BITS
DDIVD1	ADD	HL,HL		;SHIFT DIVDEND LEFT
	RLA			;SHIFT 8 LS BITS
	JR	C,DDIVD2	;IF OVERFLOW
	CP	D		;AT DIVISOR?
	JR	C,DDIVD3	;IF NOT
DDIVD2	SUB	D		;REMAINDER-DIVISOR
	INC	L		;QUOTIENT+1
DDIVD3	DEC	E		;NEXT
	JR	NZ,DDIVD1	;TIL DONE
	POP	DE		;RESTORE
	RET
;
*EJECT
;	TRIPLE PRECISION MULTIPLY
;
;	ENT	BHL =	 MULTIPLICAND
;		  A =	 MULTIPLIER
;
;	EXT	BHL =	 RESULT (MSB'S)
;		  A =	 RESULT (LSB)
;
TMULT	PUSH	IX		;SAVE
	PUSH	BC
	LD	C,B		;BDE = MULTIPLICAND
	EX	DE,HL		;DE = MULTIPLICAND
	LD	HL,0		;INIT RESULT MSB'S
	LD	IX,0		;INIT RESULT LSB'S
	LD	B,8		;MULTILPIER PRECISION
TMULT1	ADD	IX,IX		;SHIFT RESULT LEFT
	ADC	HL,HL		;SHIFT RESULT LEFT
	RLCA			;1 BIT?
	JR	NC,TMULT2	;IF NOT
	PUSH	BC		;SAVE COUNT
	ADD	IX,DE		;RESULT+MULTIPLICAND
	LD	B,0
	ADC	HL,BC		;RESULT+MULTIPLICAND
	POP	BC		;GET COUNT
TMULT2	DJNZ	TMULT1		;TIL DONE
	PUSH	IX
	POP	DE		;DE = RESULT LSB'S
	LD	A,E		;A = RESULT LSB
	POP	BC		;RESTORE
	LD	B,H		;B = RESULT MSB
	LD	H,L		;H = RESULT NSB
	LD	L,D		;L = RESULT LSB
	POP	IX
	RET
;
;	TRIPLE PRECISION DIVIDE
;
;	ENT	BHL =	 DIVIDEND
;		  A =	 DIVISOR
;
;	EXT	BHL =	 QUOTIENT
;		  A =	 REMAINDER
;
TDIVD	PUSH	DE		;SAVE
	LD	D,A		;D = DIVISOR
	LD	E,24		;DIVIDEND PRECISION
	XOR	A		;0 LS BITS
TDIVD1	ADD	HL,HL		;SHIFT DIVDEND LEFT
	RL	B		;SHIFT DIVIDEND LEFT
	RLA			;SHIFT 8 LS BITS
	JR	C,TDIVD2	;IF OVERFLOW
	CP	D		;AT DIVISOR?
	JR	C,TDIVD3	;IF NOT
TDIVD2	SUB	D		;REMAINDER-DIVISOR
	INC	L		;QUOTIENT+1
TDIVD3	DEC	E		;NEXT
	JR	NZ,TDIVD1	;TIL DONE
	POP	DE		;RESTORE
	RET
 