; maildisk/asm - kjw/bqsd - version 2.00 - 01/83
;
; revised 02/03/83
;
	SUBTTL	'<maildisk/asm - machine dependent I/O>'
;
	IF	MOD1.OR.MOD3
@ROM	EQU	0125H		;rom to detect model
@ROM3	EQU	'I'		;test byte = III
@HIGH1	EQU	4049H		;topmem mod I
@HIGH3	EQU	4411H		;topmem mod III
@OPEN	EQU	4424H		;open existing file
@RUN	EQU	4433H		;run program
@CLOSE	EQU	4428H		;close file
@ERROR	EQU	4409H		;display error message
@READ	EQU	4436H		;read record
@POSN	EQU	4442H		;position to record
@WRITE	EQU	4439H		;write record
@EXIT	EQU	402DH		;exit to dos
@KILL	EQU	442CH		;kill file
@INIT	EQU	4420H		;create/open file
@PRT	EQU	003BH		;char to printer
@DSP	EQU	0033H		;char to video
@KBD	EQU	002BH		;char from keyboard
	ENDIF
;
	IF	MOD2
SVC	EQU	08H		;execute SVC call
@HIGH2	EQU	0173H		;topmem mod II
@OPEN	EQU	40		;open file
@CLOSE	EQU	42		;close file
@RUN	EQU	85		;run program
@ERROR	EQU	39		;display error message
@DIRRD	EQU	35		;direct read
@DIRWT	EQU	44		;direct write
@READNX	EQU	34		;read next record
@POSN	EQU	79		;position to record
@WRITNX	EQU	43		;write next record
@EXIT	EQU	57		;exit to dos
@KILL	EQU	41		;delete file
@DIRWR	EQU	44		;direct record write
@KBD	EQU	04		;keyboard char
@VDCHAR	EQU	08		;char to video
@VDGRAF	EQU	10		;video graphics
@VDREAD	EQU	11		;read cursor address
@PRCTRL	EQU	95		;printer control
@PRCHAR	EQU	18		;char to printer
	ENDIF
;
	IF	LDOSSVC
SVC	EQU	28H		;SVC executor
@DSP	EQU	02		;char to video
@PRT	EQU	06		;char to printer
@KBD	EQU	08		;read keyboard
@EXIT	EQU	22		;exit to dos
@ERROR	EQU	26		;display error message
@KILL	EQU	57		;kill file
@INIT	EQU	58		;init file
@OPEN	EQU	59		;open file
@CLOSE	EQU	60		;close file
@POSN	EQU	66		;position to file
@READ	EQU	67		;read record
@WRITE	EQU	75		;write record
@RUN	EQU	77		;run program
@HIGH	EQU	100		;fetch topmem
@ROM	EQU	0125H		;rom address
@ROM3	EQU	'I'		;III compare
	ENDIF
;
	PAGE
;
;	open file
;
	IF	MOD1.OR.MOD3
OPEN$	MACRO
	LD	B,0		;logical record length
	CALL	@OPEN		;open the file
	ENDM
	ENDIF
;
	IF	MOD2
OPEN$	MACRO
	LD	(OLIST),HL	;pass I/O buffer address
	LD	HL,OLIST	;start of param
	LD	A,@OPEN		;SVC #
	RST	SVC		;open the file!
	ENDM
	ENDIF
;
	IF	LDOSSVC
OPEN$	MACRO
	LD	B,0		;LRL
	LD	A,@OPEN		;SVC #
	RST	SVC		;open file!
	ENDM
	ENDIF
;
;	open/create new file
;
	IF	MOD1.OR.MOD3
INIT$	MACRO
	LD	B,0		;LRL
	CALL	@INIT		;init file
	ENDM
	ENDIF
;
	IF	MOD2
INIT$	MACRO
	LD	(OLISTI),HL	;pass I/O buffer
	LD	HL,OLISTI	;start of param list
	LD	A,@OPEN		;SVC #
	RST	SVC		;open the file
	ENDM
	ENDIF
;
	IF	LDOSSVC
INIT$	MACRO
	LD	B,0		;LRL
	LD	A,@INIT		;SVC #
	RST	SVC		;open/create file
	ENDM
	ENDIF
;
;	position to logical record
;
	IF	MOD1.OR.MOD3
;
;	since the Mod I/III systems cannot address
;	3 byte logical records, we must drop MSB
;
POSN$	MACRO
	LD	H,B		;pass pointer to HL
	LD	L,C		;HL => 3 byte record #
	INC	HL		;skip MSB
	LD	B,(HL)		;get NSB
	INC	HL		;bump
	LD	C,(HL)		;get LSB
	CALL	@POSN		;position to record
	ENDM
	ENDIF
;
	IF	MOD2
POSN$	MACRO
	LD	A,@POSN		;SVC#
	RST	SVC		;position!
	ENDM
	ENDIF
;
	IF	LDOSSVC
POSN$	MACRO
	LD	H,B		;pass to HL
	LD	L,C
	INC	HL		;skip MSB
	LD	B,(HL)		;get NSB
	INC	HL		;bump
	LD	C,(HL)		;get LSB
	LD	A,@POSN		;SVC #
	RST	SVC		;position to record
	ENDM
	ENDIF
;
;	read next logical record
;
	IF	MOD1.OR.MOD3
READ$	MACRO
	CALL	@READ		;read next record
	ENDM
	ENDIF
;
	IF	MOD2
READ$	MACRO
	LD	A,@READNX	;SVC #
	RST	SVC		;read next
	ENDM
	ENDIF
;
	IF	LDOSSVC
READ$	MACRO
	LD	A,@READ		;SVC #
	RST	SVC		;read it
	ENDM
	ENDIF
;
;	write next record
;
	IF	MOD1.OR.MOD3
WRITE$	MACRO
	CALL	@WRITE		;write next record
	ENDM
	ENDIF
;
	IF	MOD2
WRITE$	MACRO
	LD	A,@WRITNX	;SVC #
	RST	SVC		;write next
	ENDM
	ENDIF
;
	IF	LDOSSVC
WRITE$	MACRO
	LD	A,@WRITE	;SVC #
	RST	SVC		;write next
	ENDM
	ENDIF
;
;	close file
;
	IF	MOD1.OR.MOD3
CLOSE$	MACRO
	CALL	@CLOSE		;close file
	ENDM
	ENDIF
;
	IF	MOD2
CLOSE$	MACRO
	LD	A,@CLOSE	;SVC #
	RST	SVC		;close file
	ENDM
	ENDIF
;
	IF	LDOSSVC
CLOSE$	MACRO
	LD	A,@CLOSE	;SVC #
	RST	SVC		;close file
	ENDM
	ENDIF
;
;	delete existing file
;
	IF	MOD1.OR.MOD3
KILL$	MACRO
	CALL	@KILL		;delete file
	ENDM
	ENDIF
;
	IF	MOD2
KILL$	MACRO
	LD	A,@KILL		;SVC #
	RST	SVC		;delete file
	ENDM
	ENDIF
;
	IF	LDOSSVC
KILL$	MACRO
	LD	A,@KILL		;SVC #
	RST	SVC		;kill file
	ENDM
	ENDIF
;
;	run program file
;
	IF	MOD1.OR.MOD3
RUN$	MACRO
	CALL	@RUN		;run program
	ENDM
	ENDIF
;
	IF	MOD2
RUN$	MACRO
	LD	A,@RUN		;SVC #
	RST	SVC		;run program
	ENDM
	ENDIF
;
	IF	LDOSSVC
RUN$	MACRO
	LD	A,@RUN		;SVC #
	RST	SVC		;run program
	ENDM
	ENDIF
;
;	exit program to DOS READY
;
	IF	MOD1.OR.MOD3
EXIT$	MACRO
	JP	@EXIT		;exit to dos
	ENDM
	ENDIF
;
	IF	MOD2
EXIT$	MACRO
	LD	A,@EXIT		;SVC #
	RST	SVC		;exit to dos
	ENDM
	ENDIF
;
	IF	LDOSSVC
EXIT$	MACRO
	LD	A,@EXIT		;SVC #
	RST	SVC		;exit to dos
	ENDM
	ENDIF
;
;	display error message
;
	IF	MOD1.OR.MOD3
ERROR$	MACRO
	OR	0C0H		;set bits 7/6
	CALL	@ERROR		;display error message
	ENDM
	ENDIF
;
	IF	MOD2
ERROR$	MACRO
	PUSH	BC		;save
	AND	7FH		;assure a return
	LD	B,A		;pass error code
	LD	A,@ERROR	;SVC #
	RST	SVC		;display message
	POP	BC		;restore
	ENDM
	ENDIF
;
	IF	LDOSSVC
ERROR$	MACRO
	PUSH	BC		;save BC
	OR	0C0H		;set bits 7/6
	LD	C,A		;pass error code
	LD	A,@ERROR	;SVC #
	RST	SVC		;display error message
	POP	BC		;restore stack
	ENDM
	ENDIF
;
;	fetch top memory
;
	IF	MOD1.OR.MOD3
TOPMEM$	MACRO
	LD	HL,@HIGH3	;topmem III
	LD	A,(@ROM)	;read rom address
	CP	@ROM3		;mod III?
	JR	Z,$+5		;go if yes
	LD	HL,@HIGH1	;topmem I
	LD	(DY?MEM),HL	;save topmem address
	LD	HL,($)		;read topmem
DY?MEM	EQU	$-2
	ENDM
	ENDIF
;
	IF	MOD2
TOPMEM$	MACRO
	LD	HL,(@HIGH2)	;get topmem II
	ENDM
	ENDIF
;
	IF	LDOSSVC
TOPMEM$	MACRO
	LD	A,@HIGH		;SVC #
	LD	HL,0		;command
	RST	SVC		;fetch topmem
	ENDM
	ENDIF
;
;	send char to display device
;
	IF	MOD1.OR.MOD3
VOUT$	MACRO
	PUSH	IY		;must save
	PUSH	DE
	CALL	@DSP		;to display
	POP	DE		;restore
	POP	IY
	ENDM
	ENDIF
;
	IF	MOD2
VOUT$	MACRO
	PUSH	BC		;save
	LD	B,A		;pass char
	LD	A,@VDCHAR	;SVC #
	RST	SVC		;char to video
	POP	BC		;restore
	ENDM
	ENDIF
;
	IF	LDOSSVC
VOUT$	MACRO
	PUSH	BC		;save
	LD	C,A		;pass character
	LD	A,@DSP		;SVC #
	RST	SVC		;display char
	POP	BC		;restore
	ENDM
	ENDIF
;
;	send character to printer device
;
	IF	MOD1.OR.MOD3
POUT$	MACRO
	PUSH	IY		;save
	PUSH	DE
	CALL	@PRT		;print character
	POP	DE		;restore
	POP	IY
	ENDM
	ENDIF
;
	IF	MOD2
POUT$	MACRO
	PUSH	BC		;save
	LD	B,A		;pass character
	LD	A,@PRCHAR	;SVC #
	RST	SVC		;print char
	POP	BC		;restore
	ENDM
	ENDIF
;
	IF	LDOSSVC
POUT$	MACRO
	PUSH	BC		;save
	LD	C,A		;pass character
	LD	A,@PRT		;SVC#
	RST	SVC		;print char
	POP	BC		;restore
	ENDM
	ENDIF
;
;	fetch character from keyboard
;
	IF	MOD1.OR.MOD3
KEYIN$	MACRO
	PUSH	IY		;save
	PUSH	DE
	CALL	@KBD		;scan keyboard
	POP	DE		;unstack
	POP	IY
	OR	A		;set flags
	ENDM
	ENDIF
;
	IF	MOD2
KEYIN$	MACRO
	PUSH	BC		;save
	LD	A,@KBD		;SVC #
	RST	SVC		;read keyboard
	LD	A,0		;init nil key
	JR	NZ,$+3		;go if no key
	LD	A,B		;else get key
	POP	BC		;restore stack
	OR	A		;set flags
	ENDM
	ENDIF
;
	IF	LDOSSVC
KEYIN$	MACRO
	LD	A,@KBD		;SVC #
	RST	SVC		;scan keyboard
	OR	A		;anything?
	ENDM
	ENDIF
;
