;-----------------------------------------------------------------------
;
;  Assembly Language Macros  Version 0.1
;  Written by: Malcolm McCorquodale III  Houston, Texas  713-626-4979
;
;  (c) 1984 by Malcolm McCorquodale III  All commercial rights reserved.
;
;  This software is distributed using the "FREE-SOFTWARE" concept.
;  If you find these macros useful send whatever contribution you
;  deem appropriate to:
;
;	     Malcolm McCorquodale III
;	     3470 Locke Lane,
;	     Houston Texas 77027.
;	     (713) 626 - 4979
;
;-----------------------------------------------------------------------

;;-----------------------------------------------------------------------
;;
;;	 General Purpose Macros
;;
;;-----------------------------------------------------------------------

;;-----------------------------------------------------------------------
;;
;; SAVE <p1,..,p8>  Pushes 1 to 8 parameters.
;;		    Parameters p2 through p8 are optional.
;;
;;-----------------------------------------------------------------------
SAVE	MACRO	P1,P2,P3,P4,P5,P6,P7,P8
	IRP	X,<P1,P2,P3,P4,P5,P6,P7,P8>
IFNB	<X>
	PUSH   X
ENDIF
	ENDM
	ENDM

;;-----------------------------------------------------------------------
;;
;; RESTORE <p1,..,p8>  Pops 1 to 8 parameters.
;;		       Parameters p2 through p8 are optional.
;;
;;-----------------------------------------------------------------------
RESTORE MACRO	P1,P2,P3,P4,P5,P6,P7,P8
	IRP	X,<P1,P2,P3,P4,P5,P6,P7,P8>
IFNB	<X>
	POP    X
ENDIF
	ENDM
	ENDM

;;-----------------------------------------------------------------------
;;
;; PRINT <msg> - Writes msg on the screen.
;;
;;		 No registers destroyed.
;;
;;-----------------------------------------------------------------------
PRINT	MACRO	MSG		; Print message on the screen.
	LOCAL	TEXT,PEXIT
	SAVE	DS,DX
	MOV	DX,CS
	MOV	DS,DX
	MOV	DX,OFFSET TEXT
	MOV	AH,9
	INT	21H
	RESTORE DX,DS
	JMP	PEXIT
TEXT	DB	MSG,'$'
PEXIT:
	ENDM

;;-----------------------------------------------------------------------
;;
;; The macros below this point have not been fully tested.  MM.
;;
;;-----------------------------------------------------------------------
;;-----------------------------------------------------------------------
;;
;; TERMINATE - End program and return to caller.
;;
;;-----------------------------------------------------------------------
TERMINATE MACRO 		; End of program.
	  INT	  20H
	  ENDM

;;-----------------------------------------------------------------------
;;
;; RWABS <rw>,<drive>,<nofsect>,<beg>
;;	 <rw>	   - 'R' for read, 'W' for write.
;;	 <drive>   - drive number.
;;	 <nofsect> - number of sectors to transfer.
;;	 <beg>	   - Begining logical sector number.
;;
;;	 Read and write absolute sectors.
;;
;;	 Note: 1) Status information is returned in flags, After the
;;		  flags are sampled they should be poped off the stack
;;		  with a POPF.
;;
;;	       2) DS:DX must point to the DTA before this call.
;;
;;-----------------------------------------------------------------------
RWABS	MACRO	RW,DRIVE,NOFSECT,BEG	; R/W absolute disk sector.
	SAVE	BX,CX,DX
	MOV	AL,DRIVE
	MOV	CX,NOFSECT
	MOV	DX,BEG
IFIDN	<RW>,<'R'>
	INT	25H
ENDIF
IFIDN	<RW>,<'W'>
	INT	26H
ENDIF
	RESTORE DX,CX,BX
	ENDM

;;-----------------------------------------------------------------------
;;
;; ADDTODOS <dosend> - Add the current proc to DOS.
;;
;;	    Note: <dosend> is a label at the highest memory address
;;		  used by your code.
;;
;;-----------------------------------------------------------------------
ADDTODOS MACRO	DOSEND		; Add a procedure to DOS.
	MOV	DX,DOSEND
	INC	DX
	INT	27H
	ENDM

;;-----------------------------------------------------------------------
;;
;; DOSRS232 <char>
;;	    Sends or receives a <char> to/from the standard RS232 port.
;;
;;	    If <char> is specified then it is sent to the RS232 port.
;;	    If <char> is not specified then a character is read into AL.
;;
;;	    OUTPUT: If receiving data AL will contain the byte received.
;;
;;	    All registers saved.
;;
;;-----------------------------------------------------------------------
DOSRS232 MACRO	CHAR
	SAVE	AH,DL
IFB	<CHAR>
	MOV	AH,3	; Receive a character from the RS232 port.
ELSE
	MOV	AH,4	; Send a character to the RS232 port.
ENDIF
	INT	21H
	RESTORE DL,AH
	ENDM

;;-----------------------------------------------------------------------
;;
;; PRINT1 <char> - Send <char> to the standard printer.
;;
;;		   No registers destroyed.
;;
;;-----------------------------------------------------------------------
PRINT1	MACRO	CHAR		; Send a character to the printer.
	SAVE	AH,DL
	MOV	DL,CHAR
	MOV	AH,5
	INT	21H
	RESTORE DL,AH
	ENDM

;;-----------------------------------------------------------------------
;;
;; INPUTSTR <len>,<bufoff>,[<bufseg>]
;;	    <len> - Length of input buffer.
;;	    <bufoff> - Offset from <bufseg> to message buffer.
;;	    <bufseg> - Optional segment for input buffer.
;;
;;	    Input a string ending with a RETURN from the standard
;;	    input device.
;;
;;	    No registers destroyed except DS:DX which points to
;;	    input buffer on output.
;;
;;	    On exit: DS:DX will have <bufseg>:<bufoff>.
;;		     Byte 1 of buffer = Size of buffer.
;;		     Byte 2 of buffer = Number of bytes read w/o c/r.
;;		     Byte 3 of buffer = Start of text read.
;;
;;-----------------------------------------------------------------------
INPUTSTR MACRO	LEN,BUFOFF,BUFSEG	; Get a line of text.
	PUSH	AH
IFNB	<BUFSEG>
	MOV	DX,BUFSEG
	MOV	DS,DX
ENDIF
	MOV	DX,BUFOFF
	MOV	[DX],LEN
	MOV	AH,0AH
	INT	21H
	POP	AH
	ENDM

;;-----------------------------------------------------------------------
;;
;; POLLSTDIN - Check the status of the standard input device.
;;
;;	       On exit: AL = 0FFH - Character is available.
;;			      00H - Character not available.
;;
;;	       Note: This routine executes an INT 23H if a ctl-brk
;;		     is detected.
;;
;;	       No registesrs destroyed.
;;
;;-----------------------------------------------------------------------
POLLSTDIN MACRO 		; Poll the standard input device.
	PUSH	AH
	MOV	AH,0BH
	INT	21H
	POP	AH
	ENDM

;;-----------------------------------------------------------------------
;;
;; CLRSTDIN <func> - Clear standard input buffer then execute
;;		     function <func>.
;;	    <func> may be 1 - Keyboard input.
;;			  6 - Direct Console I/O.
;;			  7 - Direct Console Input w/o Echo.
;;			  8 - Console Input w/o Echo.
;;			  A - Buffered Keyboard Input.
;;
;;	    No registers destroyed except AX.
;;
;;-----------------------------------------------------------------------
CLRSTDIN MACRO	FUNC		; Clear the standard input device.
	MOV	AL,FUNC
	MOV	AH,0CH
	INT	21H
	ENDM

;;-----------------------------------------------------------------------
;;
;; DISKRESET - Flushes all file buffers.
;;
;;-----------------------------------------------------------------------
DISKRESET MACRO 		; Reset the disk.
	PUSH	AH
	MOV	AH,0DH
	INT	21H
	POP	AH
	ENDM

;;-----------------------------------------------------------------------
;;
;; PICKDRIVE  <drive> - Select the default disk drive.
;;
;;			Input: 0 = Drive A, 1 = Drive B, etc.
;;
;;			Output: AL = number of drives. Minimum=2.
;;
;;			No registers destroyed.
;;
;;-----------------------------------------------------------------------
PICKDRIVE MACRO DRIVE		; Pick the default disk drive.
	SAVE	DL,AH
	MOV	DL,DRIVE
	MOV	AH,0EH
	INT	21H
	RESTORE AH,DL
	ENDM

;;-----------------------------------------------------------------------
;;
;; FINDRIVE - Determine the default drive.
;;
;;	      Output: AL = 0 = Drive A, 1 = Drive B, etc.
;;
;;	      No registers destroyed except AL.
;;
;;-----------------------------------------------------------------------
FINDRIVE MACRO			; Find the default disk drive.
	PUSH	AH
	MOV	AH,19H
	INT	21H
	POP	AH
	ENDM

;;-----------------------------------------------------------------------
;;
;; SETDTA - Set the DTA.
;;
;;	    On input: DS:DX must point to new DTA.
;;
;;-----------------------------------------------------------------------
SETDTA	MACRO			; Set the DTA.
	PUSH	AH
	MOV	AH,1AH
	INT	21H
	POP	AH
	ENDM

;;-----------------------------------------------------------------------
;;
;; ALLOCTAB <drive> - Get pointer to FAT ID byte.
;;
;;	    If <drive> is specified then the pointer to the FAT ID
;;		       for drive <drive> is returned.
;;	    If <drive> is not specified then a pointer to the FAT ID
;;		       byte for the default drive is returned.
;;
;;	    Output: [DS:BX] = FAT ID byte.
;;		    DX	    = Number of allocation units.
;;		    AL	    = Number of sectors per allocation unit.
;;		    CX	    = Size of the physical sector.
;;
;;-----------------------------------------------------------------------
ALLOCTAB MACRO	DRIVE
	PUSH	AH
IFB	<DRIVE>
	MOV	AH,1BH		; Get FAT ID for default drive.
ELSE
	MOV	AH,1CH		; Get FAT ID for specified drive.
	MOV	DL,DRIVE
ENDIF
	INT	21H
	POP	AH
	ENDM

;;-----------------------------------------------------------------------
;;
;; CHANGEINT <int>,<seg>,<off> - If <seg> and <off> are specified then
;;	     interupt vector <int> is set to <seg>:<off>. If <seg> and
;;	     <off> are not specified then interupt vector <int> is
;;	     returned in ES:BX.
;;
;;	     All registers saved except ES and BX when a GET VECTOR
;;-----------------------------------------------------------------------
CHANGEINT MACRO INT,SEG,OFF
	PUSH	AX
	MOV	AL,INT
IFNB	<SEG>
	MOV	AH,25H		; Set interupt vector.
	MOV	DX,SEG
	MOV	DS,DX
	MOV	DX,OFF
ELSE
	MOV	AH,35H		; Get interupt vector.
ENDIF
	INT	21H
	POP	AX
	ENDM

;;-----------------------------------------------------------------------
;;
;; GETDATE - Return the date in CX:DX. CX has the year (1980-2099) in bi
;;	     in binary. DH has the month (1-0C). DL has the day.
;;	     All registers preserved
;;
;;-----------------------------------------------------------------------
GETDATE MACRO			; Get the date.
	PUSH	AH
	MOV	AH,2AH
	INT	21H
	POP	AH
	ENDM

;;-----------------------------------------------------------------------
;;
;; SETDATE <yr>,<mo>,<day> - Set the date. <yr> is 1980..2099.
;;	   <mo> is 1..0CH. <day> is 1..31. On return: AL = 00 = sucess
;;	   AL = 0FFH = failure.
;;
;;-----------------------------------------------------------------------
SETDATE MACRO YR,MO,DAY 	; Set the date.
	SAVE	CX,DX,AH
	MOV	AH,2BH
	MOV	CX,YR
	MOV	DH,MO
	MOV	DL,DAY
	INT	21H
	RESTORE AH,DX,CX
	ENDM

;;-----------------------------------------------------------------------
;;
;; GETTIME - Get the time of day. Returns CX:DX. CH = hours (0..23),
;;	     CL = minutes (0..59), DH = seconds (0..59), DL = 1/100
;;	     seconds (0..99).
;;
;;-----------------------------------------------------------------------
GETTIME MACRO			; Get the time.
	PUSH	AH
	MOV	AH,2CH
	INT	21H
	POP	AH
	ENDM

;;-----------------------------------------------------------------------
;;
;; SETTIME <hr>,<min>,<sec>,<sec100> - Set the time.
;;
;;-----------------------------------------------------------------------
SETTIME MACRO	HR,MIN,SEC,SEC100	; Set the time.
	SAVE	CX,DX,AH
	MOV	AH,2D
	MOV	CH,HR
	MOV	CL,MIN
	MOV	DH,SEC
	MOV	DL,SEC100
	INT	21H
	RESTORE AH,DX,CX
	ENDM

;;-----------------------------------------------------------------------
;;
;; VERIFY <flag> - Set or reset the verify flag.
;;
;;	  <flag> may be either 'ON', 'OFF' or 'QUERY'.
;;		 For 'OFF' and 'ON' all regs are
;;		 saved.  For 'QUERY' AL returns 00 if off, 01 if on.
;;
;;	   OUTPUT: If <flag> is 'QUERY' then: AL = 0 for verify off
;;						   1 for verify on
;;	   All registers saved if <flag> is not 'QUERY' else AL destroyed.
;;
;;-----------------------------------------------------------------------
VERIFY	MACRO	FLAG
IFIDN	<FLAG>,<'OFF'>  ; TURN VERIFY SWITCH OFF.
	SAVE	AX,DL
	XOR	DL,DL
	XOR	AL,AL
	MOV	AH,2EH
	INT	21H
	RESTORE DL,AX
ENDIF
IFIDN	<FLAG>,<'ON'>   ; TURN VERIFY SWITCH ON.
	SAVE	AX,DL
	XOR	DL,DL
	MOV	AL,1
	MOV	AH,2EH
	INT	21H
	RESTORE DL,AX
ENDIF
IFIDN	<FLAG>,<'QUERY'> ; QUERY VERIFY SWITCH.
	PUSH	AH
	MOV	AH,54H
	INT	21H
	POP	AH
ENDIF
	ENDM

;;-----------------------------------------------------------------------
;;
;; GETDTA - Get DTA (Data Transfer Area).  On return - ES:BX has address
;;	    of DTA.
;;
;;-----------------------------------------------------------------------
GETDTA	MACRO			; Get address of DTA.
	PUSH	AH
	MOV	AH,2FH
	INT	21H
	POP	AH
	ENDM

;;-----------------------------------------------------------------------
;;
;; VERSION - Get PC-DOS version number.
;;
;;  OUTPUT:  AL = major version number,
;;	     AH = minor version number.
;;	     If AL = 0 then assume pre DOS 2.0
;;
;;-----------------------------------------------------------------------
VERSION MACRO			; Get PC-DOS version number.
	MOV	AH,30H
	INT	21H
	ENDM

;;-----------------------------------------------------------------------
;;
;; KEEP <rc>,<beg>,<fin> - Terminate this program but stay resident.
;;
;;	<rc>  = The return code for this program.
;;	<beg> = The begining address of the program.
;;	<fin> = The last byte plus one used by the program.
;;		This number is divided by 16 to determine the memory
;;		size in paragraphs required.
;;	Registers may not be passed for <beg> and <fin>.
;;
;;-----------------------------------------------------------------------
KEEP	MACRO RC,BEG,FIN
	MOV	AL,RC
	MOV	DX,(FIN-BEG)/16
	MOV	AH,31H
	INT	21H
	ENDM

;;-----------------------------------------------------------------------
;;
;; CTL_BRK <flag> - Read or write the current CTL-BRK state.
;;
;;	   <flag> - Is either 'ON', 'OFF' or not specified.
;;
;;	   If flag is not specified then current CTL-BRK state is
;;	   returned in DL.
;;
;;	   All registers saved if <flag> is specified elss DL is destroyed.
;;
;;-----------------------------------------------------------------------
CTL_BRK MACRO	FLAG		; R/W  CTRL-BREAK status flag.
	PUSH	AX
	MOV	AH,33H
IFB	<FLAG>
	XOR	AL,AL
ELSE
	MOV	AL,1
ENDIF
IFNB
  IFIDN   <FLAG>,<'OFF'>
	  XOR	  DL,DL
  ENDIF
  IFIDN   <FLAG>,<'ON'>
	  MOV	  DL,1
  ENDIF
ENDIF
	INIT	21H
	POP	AX
	ENDM

;;-----------------------------------------------------------------------
;;
;; DISKAVAIL <DRIVE>
;;
;;-----------------------------------------------------------------------

;;-----------------------------------------------------------------------
;;
;;
;;
;;-----------------------------------------------------------------------

;;-----------------------------------------------------------------------
;;
;;
;;
;;-----------------------------------------------------------------------

;;-----------------------------------------------------------------------
;;
;;
;;
;;-----------------------------------------------------------------------

;;-----------------------------------------------------------------------
;;
;;
;;
;;-----------------------------------------------------------------------

;;-----------------------------------------------------------------------
;;
;;
;;
;;-----------------------------------------------------------------------

;;-----------------------------------------------------------------------
;;
;;
;;
;;-----------------------------------------------------------------------

;;-----------------------------------------------------------------------
;;
;;
;;
;;-----------------------------------------------------------------------

;;-----------------------------------------------------------------------
;;
;;
;;
;;-----------------------------------------------------------------------

;;-----------------------------------------------------------------------
;;
;;
;;
;;-----------------------------------------------------------------------

;;;;;; test prog
	assume cs:cseg,ds:cseg,es:cseg
cseg	segment para 'code'
x	proc	far
	push	ds
	xor	ax,ax
	push	ax

	writeln 'a message'     ;; test writeln, save, restore.

	ret
x	endp
cseg	ends
	end

