;
;***************************************************************
;                                                              *
; F I L E   N A M E :    M A C R O Z . M 8 0                   *
;                                                              *
;***************************************************************
;
;***************************************************************
;                                                              *
; THIS IS THE "OLD" MACRO.LIB SUPPLIED WITH "MAC" BY DIGITAL   *
; RESEARCH.  I HAVE MODIFIED IT TO RUN WITH "M80" BY MICROSOFT *
; BY CHANGING SOME OF THE PSUEDO OP'S AND CONVERTED THE 8080   *
; MNEMONICS TO Z-80 MNEMONICS.                                 *
;                                                              *
;           DAVID NIENHISER     NOVEMBER 3, 1980               *
;                                                              *
;***************************************************************

;NOTE: Z80 MODE ENABLED HERE!
Z80
;
;       SAVE MACRO      SAVE SPECIFIED REGISTERS
;
;       SAVE    R1,R2,R3,R4
;
;               R1-R4 MAY BE BC,DE,HL OR AF  SAVED IN ORDER SPECIFIED
;               IF REGS ARE OMITTED SAVE BC,DE AND HL
;
SAVE    MACRO   R1,R2,R3,R4
       IFNB    <R1&R2&R3&R4>
       IRP     R,<<R1>,<R2>,<R3>,<R4>>
       IFB     <R>
       EXITM
       ENDIF
       PUSH    R
       ENDM
       ELSE
       IRP     REG,<BC,DE,HL>
       PUSH    REG
       ENDM
       ENDIF
       ENDM
;
;       . . . . . . . . . . . . . . . . . . . . . . . . . . . .
;
;       RESTORE MACRO   RESTORE REGISTERS  (INVERSE OF SAVE)
;
;       RESTORE R1,R2,R3,R4
;
;               R1-R4 MAY BE BC,DE,HL OR AF  RESTORED IN ORDER SPECIFIED
;               IF REGS OMITTED RESTORE HL,DE AND BC
;
RESTORE MACRO   R1,R2,R3,R4
       IFNB    <R1&R2&R3&R4>
       IRP     R,<<R1>,<R2>,<R3>,<R4>>
       IFB     <R>
       EXITM
       ENDIF
       POP     R
       ENDM
       ELSE
       IRP     REG,<HL,DE,BC>
       POP     REG
       ENDM
       ENDIF
       ENDM
;
;
;       . . . . . . . . . . . . . . . . . . . . . . . . . . . .
;
;       CHARIN MACRO    CONSOLE INPUT TO A
;
;       CHARIN  ADDR
;
CHARIN  MACRO   ADDR
       LD      C,1D
       CALL    5               ;;CALL BDOS
       IFNB    <ADDR>
       LD      (ADDR),A
       ENDIF
       ENDM
;
;
;       . . . . . . . . . . . . . . ... ... . .. . . . . . . . .
;
;       CHAROUT MACRO   CONSOLE OUTPUT FROM A
;
;       CHAROUT ADDR
;
CHAROUT MACRO   ADDR
       IFNB    <ADDR>
       LD      A,(ADDR)
       ENDIF
       LD      C,2D
       LD      E,A
       CALL    5               ;;CALL BDOS
       ENDM
;
;       . . . . . . . . . . . . . . . . . . . . . . . . . . . .
;
;       CHARSTAT MACRO  CHECK CONSOLE STATUS
;
;                       RETURN TRUE (FF) IF CHAR READY FALSE (0) IF NOT
;
CHARSTAT MACRO
       LOCAL   ENDSTA
       LD      C,11D
       CALL    5
       OR      A
       JP      Z,ENDSTA
       LD      A,X'FF'
ENDSTA:
       ENDM
;
;       . . . . . . . . . . . . . . . . . . . . . . . . . . . .
;
;       INPUT MACRO     INPUT CHARACTER STRING FROM CONSOLE
;
;       INPUT   ADDR,BUFLEN
;
;               ADDR    START OF TEXT BUFFER
;               BUFLEN  LENGTH OF BUFFER  (DEFAULT IS 127)
;
INPUT   MACRO   ADDR,BUFLEN
       LD      C,10D
       IFNB    <ADDR>
       LD      DE,ADDR
       ENDIF
       IFNB    <BUFLEN>
       LD      A,BUFLEN
       LD      (DE),A
       ELSE
       LD      A,127D
       LD      (DE),A
       ENDIF
       CALL    5               ;;BDOS ENTRY
       ENDM
;
;       . . . . . . . . . . . . . . . . . . . . . . . . . . . .
;
;       PRINT MACRO     PRINT A STRING ON CONSOLE
;
;       PRINT                           (CARRIAGE RETURN, LINE FEED)
;       PRINT   'LITERAL'
;       PRINT   <'LITERAL',CR,LF,'SECOND LITERAL'>
;
;       PRINT   ADDR,$                  (ASCII OUTPUT UNTIL $)
;       PRINT   ADDR,L,H                (HEX OUTPUT L CHARACTERS)
;       PRINT   ADDR,L,A                (ASCII OUTPUT L CHARACTERS)
;
;               LITERALS MUST BE IN SINGLE QUOTES  'LIT'
;               IF LITERAL CONTAINS CONTROL CODES ENTIRE STRING IN <> BRACKETS
;               MACRO ALSO ASSEMBLES
;                       CR = CARRIAGE RETURN
;                       LF = LINE FEED
;                       BEL = BELL CODE
;
;               MACRO ASSUMES ADDR ALREADY LOADED TO HL IF ARGUMENT OMITTED
;
PRINT   MACRO   ?STRING,LEN,TC
       LOCAL   @OVER,@MESS,PLOOP,PASTCR,@CRLF
       LOCAL   HLAB
8080
CR      SET     0DH
LF      SET     0AH
BEL     SET     07H
HLAB    EQU     'H'
Z80
       IFB     <?STRING&LEN&TC>
       JP      PASTCR
       DSEG
@CRLF:
       DB      CR
       DB      LF
       DB      '$'
       CSEG
PASTCR: LD      DE,@CRLF
       LD      C,9D
       CALL    5
       ELSE
       IFB     <LEN&TC>
       JP      @OVER
       DSEG
@MESS:
       DB      ?STRING
       DB      '$'
       CSEG
@OVER:  LD      DE,@MESS
       LD      C,9D
       CALL    5               ;;BDOS ENTRY
       ELSE
       IFB     <TC>
       IFNB    <?STRING>
       LD      DE,?STRING
       ENDIF
       LD      C,9D
       CALL    5               ;;BDOS ENTRY
       ELSE
       IFNB    <?STRING>
       LD      HL,?STRING
       ENDIF
       LD      C,LEN
PLOOP:  PUSH    BC
       PUSH    HL
       IF  '&TC' EQ HLAB
       LD      A,(HL)
       HEXOUT                  ;;CONV TO HEX & OUTPUT
       ELSE
       LD      E,(HL)
       LD      C,2D
       CALL    5
       ENDIF
       POP     HL
       POP     BC
       INC     HL
       DEC     C
       JP      NZ,PLOOP
       ENDIF
       ENDIF
       ENDIF
       ENDM
;
;       . . . . . . . . . . . . . . . . . . . . . . . . . . . .
;
;       HEXOUT MACRO    CONVERT BINARY NO AND OUTPUT TO CONSOLE
;
;       HEXOUT  ADDR
;
;               NUMBER ASSUMED IN A IF NO ARGUMENT
;
HEXOUT  MACRO   ADDR
       LOCAL   OUTCHR,HEXEND
       JR      HEXEND
HEXPRN: SAVE    AF
       RRCA
       RRCA
       RRCA
       RRCA                    ;;SHIFT RIGHT 4
       CALL    OUTCHR
       RESTORE AF
OUTCHR: AND     X'0F'
       ADD     A,X'90'
       DAA                     ;;DEC ADJUST
       ADC     A,X'40'
       DAA                     ;;DEC ADJUST
       LD      E,A
       LD      C,2
       JP      5               ;;CALL BDOS
HEXEND:
HEXOUT  MACRO   ?ADDR
       IFNB    <?ADDR>
       LD      A,(?ADDR)
       ENDIF
       CALL    HEXPRN
       ENDM
       HEXOUT  ADDR
       ENDM
;
;
;       . . . . . . . . . . . . . . . . . . . . . . . . . . . .
;
;       HEXIN MACRO     CONVERT A NUMBER IN MEMORY FROM HEX TO BINARY
;
;                       IF NO ARGUMENT MACRO ASSUMES ADDR OF HEX STRING IN HL
;                       ANSWER LEFT IN HL WITH LEAST SIGNIFICANT 8 BITS IN A
;                       CARRY SET ON ERROR. CONVERSION STOPS WHEN ZERO IS
;                       FOUND IN HEX STRING.
;
HEXIN   MACRO   ADDR
       LOCAL   IN1,IN2,OVRHEX
       JR      OVRHEX
@HEXIN: LD      HL,0D
IN1:    LD      A,(DE)
       OR      A               ;;CHECK FOR END OF BUFFER
       RET     Z
       SUB     '0'             ;;CHECK < 0 AND CONVERT TO HEX
       RET     C
       ADD     A,'0'-'G'               ;;CHECK > F
       RET     C
       ADD     A,6
       JP      P,IN2
       ADD     A,7
       RET     C
IN2:    ADD     A,10
       OR      A               ;;CLEAR CARRY
       LD      C,A
       LD      B,0             ;;ZERO TO B
       ADD     HL,HL
       ADD     HL,HL
       ADD     HL,HL
       ADD     HL,HL           ;;SHIFT LEFT 4
       ADD     HL,BC
       INC     DE              ;;INCR BUFFER POINTER
       JR      IN1             ;;RETURN FOR MORE INPUT
OVRHEX:
HEXIN   MACRO   ?ADDR
       IFNB    <?ADDR>
       LD      DE,?ADDR                ;;LOAD BUFFER ADDR
       ELSE
       EX      DE,HL
       ENDIF
       CALL    @HEXIN
       LD      A,L             ;;LEAST SIGNIFICANT 8 BITS TO A
       ENDM
       HEXIN   ADDR
       ENDM
;
;       . . . . . . . . . . . . . . . . . . . . . . . . . . . .
;
;       DECOUT MACRO    CONVERT A POSITIVE INTEGER TO DECIMAL AND OUTPUT
;                       TO THE CONSOLE.
;
;       DECOUT  ADDR
;
;               IF ADDR OMITTED, NUMBER ASSUMED TO BE IN HL, ELSE LOADED TO HL
;               LEADING ZEROS SUPRESSED. MAXIMUM NUMBER 65,767
;
DECOUT  MACRO   ADDR
       LOCAL   ENDDEC,DX
       JR      ENDDEC
@DECOUT:SAVE                    ;;PUSH STACK
       LD      BC,-10          ;;RADIX FOR CONVERSION
       LD      DE,-1           ;;THIS BECOMES NO DIVIDED BY RADIX
DX:     ADD     HL,BC           ;;SUBTRACT 10
       INC     DE
       JP      C,DX
       LD      BC,10
       ADD     HL,BC           ;;ADD RADIX BACK IN ONCE
       EX      DE,HL
       LD      A,H
       OR      L               ;;TEST FOR ZERO
       CALL    NZ,@DECOUT      ;;RECURSIVE CALL
       LD      A,E
       ADD     A,'0'           ;;CONVERT FROM BCD TO HEX
       LD      E,A             ;;TO E FOR OUTPUT
       CHAROUT                 ;;CONSOLE OUTPUT
       RESTORE                 ;;POP STACK
       RET
ENDDEC:
DECOUT  MACRO   ?ADDR
       IFNB    <?ADDR>
       LD      HL,(?ADDR)
       ENDIF
       CALL    @DECOUT         ;;CALL THE SUBROUTINE
       ENDM
       DECOUT  ADDR
       ENDM
;
;
;
;       . . . . . . . . . . . . . . . . . . . . . . . . . . . .
;
;       DECIN MACRO     CONVERT A NUMBER IN MEMORY FROM ASCII TO BINARY
;
;       DECIN   ADDR
;
;               ADDR POINTS TO MEMORY LOCATION OF START OF NO, IF
;               ARG OMITTED POINTER ASSUMED LOADED TO HL
;               MACRO RETURNS WITH CARRY SET IF ALPHABETIC CHAR FOUND
;               CONVERSION STOPS WHEN CHAR LESS THAN ZERO IS FOUND.
;               BINARY NUMBER IS LEFT IN HL, MAXIMUM 65,767
;               LEAST SIGNIFICANT 8 BITS OF NUMBER IN A.
;
DECIN   MACRO   ADDR
       LOCAL   DLOOP,@OVER1
       JR      @OVER1
@DECIN: LD      DE,0            ;;ZERO DE
       EX      DE,HL
DLOOP:  LD      A,(DE)
       SUB     'O'
       AND     A
       RET     M
       CP      10D
       CCF
       RET     C
       INC     DE              ;;INCR ADDR POINTER
       ADD     HL,HL           ;;SHIFT LEFT 1
       PUSH    HL              ;;SAVE RESULT
       ADD     HL,HL
       ADD     HL,HL
       POP     BC              ;;NO * 2 TO B
       ADD     HL,BC
       LD      C,A             ;;ADD PRODUCT TO DIGIT
       LD      B,0
       ADD     HL,BC
       JP      DLOOP           ;;BACK FOR ANOTHER DIGIT
@OVER1:
DECIN   MACRO   ?ADDR
       IFNB    <?ADDR>
       LD      HL,?ADDR
       ENDIF
       CALL    @DECIN          ;;CALL THE SUBROUTINE
       LD      A,L             ;;LEAST SIGNIFICANT HALF OF NO TO A
       ENDM
       DECIN   ADDR
       ENDM
;
;       . . . . . . . . . . . . . . . . . . . . . . . . . . . .
;
;       MOVE MACRO      MOVE A BLOCK FROM SOURCE TO DEST
;
;       MOVE    SOURCE,DEST,COUNT
;
;               SOURCE TO HL    MACRO ASSUMES REGISTERS ALREADY
;               DEST TO DE      LOADED IF ARG OMITTED
;               COUNT TO BC
;
MOVE    MACRO   SOURCE,DEST,COUNT
       LOCAL   OVRMOV
       JR      OVRMOV
@MOVE:  LD      A,B
       OR      C
       RET     Z
       LD      A,(HL)
       LD      (DE),A
       INC     HL
       INC     DE
       DEC     BC
       JR      @MOVE           ;;BACK TO MOVE LOOP
OVRMOV:
MOVE    MACRO   SRC,?D,?C
       IFNB    <SRC>
       LD      HL,SRC
       ENDIF
       IFNB    <?D>
       LD      DE,?D
       ENDIF
       IFNB    <?C>
       LD      BC,?C
       ENDIF
       CALL    @MOVE           ;;CALL THE MOVE SUBROUTINE
       ENDM
       MOVE    SOURCE,DEST,COUNT
       ENDM
;
;       . . . . . . . . . . . . . . . . . . . . . . . . . . . .
;
;       FILL MACRO - FILL A BLOCK OF MEMORY WITH A CONSTANT
;
;       FILL    START,STOP,CONSTANT
;
;               CONSTANT OMITTED, FILL WITH 0
;               END OMITTED, FILL ONE BYTE
;
FILL    MACRO   START,STOP,CONST
       LOCAL   @FILL,BLKLEN
8080
BLKLEN  SET     STOP-START+1
Z80
       LD      HL,START                ;;LOAD START ADDR
       IFNB    <STOP>
       IF      BLKLEN GT 255
       LD      BC,BLKLEN       ;;LOAD BLOCK LENGTH
       ELSE
       LD      C,BLKLEN AND X'FF'
       ENDIF
       IFNB    <CONST>
       LD      E,CONST         ;;LOAD CONST IF NOT NULL
       ELSE
       LD      E,0
       ENDIF
@FILL:  LD      (HL),E          ;;STORE A BYTE
       INC     HL              ;;INCR MEMORY POINTER
       IF      BLKLEN GT 255
       DEC     BC              ;;DECR COUNT
       LD      A,C             ;;TEST LIMIT
       OR      B
       JR      NZ,@FILL                ;;CONTINUE
       ELSE
       DEC     C
       JR      NZ,@FILL
       ENDIF
       ELSE
       IFB     <CONST>
       LD      (HL),0
       ELSE
       LD      (HL),CONST
       ENDIF
       ENDIF
       ENDM
;
;       . . . . . . . . . . . . . . . . . . . . . . . . . . . .
;
;
;       MATCH MACRO     COMPARE 2 STRINGS OF SAME LENGTH SET CARRY IF EQUAL
;
;       MATCH   STR1,'LITERAL STRING'
;       MATCH   STR1,STR2,LENGTH
;       MATCH
;
;               DE POINTS TO STR1       MACRO WILL LOAD REG IF ARG
;               HL POINTS TO STR2       PRESENT
;               C CONTAINS LENGTH
;
;               SUBTRACT STR2 FROM STR1 AND SET FLAGS, ZERO INDICATES MATCH.
;               NORMALLY THE SECOND ARG IS A LITERAL STRING AND THE LENGTH
;               IS OMITTED. IF THE LEN ARG IS PRESENT THE SECOND STRING
;               ARG IS ASSUMED TO BE A MEMORY ADDR. IF ALL ARGUMENTS OMITTED
;               REGISTERS ASSUMED ALREADY LOADED.
;
;    NOTE:  I HAD BETTER LUCK WITH THIS ONE TESTING THE ZERO
;           FLAG INSTEAD OF THE CARRY FLAG.  D. NIENHISER
;
MATCH   MACRO   STR1,STR2,LEN
       LOCAL   OVRMAT,M1
       JR      OVRMAT
@MATCH: INC     C               ;;PRE INCREMENT COUNT (IT MIGHT BE ZERO)
M1:     DEC     C               ;;DECR LENGTH COUNT
       RET     Z
       LD      A,(DE)
       SUB     (HL)            ;;COMPARE WITH OTHER
       RET     NZ
       INC     HL
       INC     DE              ;;INCR STRING POINTERS
       JR      M1              ;;TRY SOME MORE
OVRMAT:
MATCH   MACRO   ?STR1,?STR2,?LEN
       LOCAL   LITSTR,ENDLIT
       IFB     <?STR1&?STR2&LEN>
       CALL    @MATCH
       ELSE
       IFNB    <?STR1>
       LD      DE,?STR1                ;;LOAD STRING1 POINTER
       ENDIF
       IFB     <?LEN>
       LD      C,ENDLIT-LITSTR ;;LENGTH OF LITERAL STRING
       LD      HL,LITSTR       ;;POINTER TO LITERAL
       CALL    @MATCH
       JR      ENDLIT
LITSTR: DB      ?STR2           ;;LITERAL STRING
ENDLIT:                         ;;END OF STRING
       ELSE
       IFNB    <?STR2>
       LD      HL,?STR2                ;;LOAD POINTER TO STRING2
       ENDIF
       LD      C,?LEN          ;;LOAD STRING LENGTH
       CALL    @MATCH          ;;CALL MATCH SUBROUTINE
       ENDIF
       ENDIF
       ENDM
       MATCH   STR1,STR2,LEN
       ENDM
;
;       . . . . . . . . . . . . . . . . . . . . . . . . . . . .
;
;       INSTR MACRO     SEARCH STRING FOR SUBSTRING AND SET CARRY IF FOUND
;
;       INSTR   STRING,LENGTH,SUBSTR
;
;               HL      POINTS TO STRING
;               DE      POINTS TO SUBSTRING
;               B       CONTAINS STRING LENGTH
;               C       CONTAINS SUBSTRING LENGTH
;
;               MACRO RETURNS POINTER TO END OF SUBSTRING IN HL
;
;             N O T E:  THE MATCH MACRO MUST BE INVOKED BEFORE
;                       THIS MACRO CAN BE USED.
;
INSTR   MACRO   STRING,LENGTH,SUBST
       LOCAL   OVRINS,S1,SSX
       JR      OVRINS
@INSTR: LD      A,B             ;;STRING LENGTH
       SUB     C               ;;SUBTRACT SUBSTR LENGTH
       CCF                     ;;COMP CARRY
       RET     NC
       LD      B,A             ;;NEW STRING LIMIT TO B
S1:     SAVE
       MATCH
       RESTORE
       JR      Z,SSX           ;;MATCH IF ZERO ON RET
       AND     A               ;;RESET CARRY
       DEC     B               ;;BYTES LEFT
       RET     M
       INC     HL              ;;INCR STRING POINTER
       JR      S1              ;;TRY AGAIN
SSX:    LD      B,0             ;;SET D TO 0
       ADD     HL,BC
       SCF                     ;;SET CARRY
       RET
OVRINS:
INSTR   MACRO   ?STR,?LEN,?SUBST
       LOCAL   LITSTR,ENDLIT
       IFNB    <?STR>
       LD      HL,?STR
       ENDIF
       LD      B,?LEN
       LD      C,ENDLIT-LITSTR
       LD      DE,LITSTR
       CALL    @INSTR
       JR      ENDLIT
LITSTR: DB      ?SUBST
ENDLIT:
       ENDM
       INSTR   STRING,LENGTH,SUBST
       ENDM
;
;       . . . . . . . . . . . . . . . . . . . . . . . . . . . .
;
;       SCAN MACRO      SCAN A STRING UNTIL A CHAR IS FOUND, SKIP BLANKS
;                       AND CONTROL CHARACTERS
;
;                       CARRY SET IF NUMERIC, CARRY OFF IF ALPHABETIC
;
;
SCAN    MACRO   ADDR
       LOCAL   OVRSCA
       JR      OVRSCA
@SCAN:  LD      A,(HL)
       CP      21H             ;;SPACE OR LESS?
       RET     P
       INC     HL              ;;INCR POINTER
       JR      @SCAN           ;;KEEP SEARCHING
OVRSCA:
SCAN    MACRO   ?ADDR
       IFNB    <?ADDR>
       LD      HL,?ADDR
       ENDIF
       CALL    @SCAN           ;;CALL SUBROUTINE
       CP      3AH             ;;NUMBER OR ALPHA
       ENDM
       SCAN    ADDR
       ENDM
;
;       . . . . . . . . . . . . . . . . . . . . . . . . . . . .
;
;       DISKIO MACRO    EXECUTE BDOS DISK ACCESS PRIMITIVES
;
;       NOTE: CP/M 2.2 FUNCTIONS ADDED!  D.NIENHISER 11/80
;
;       DISKIO  FUNCTION,PARAMETER
;
;               NO      FUNCTION        ENTRY PARAM
;
;               12      LIFTHEAD
;               13      INITIAL
;               14      LOGIN           DISK NO 0 - 1
;               15      OPEN            FCB
;               16      CLOSE           FCB
;               17      SEARCH          FCB
;               18      SERNXT          FCB
;               19      DELETE          FCB
;               20      READ            FCB
;               21      WRITE           FCB
;               22      MAKE            FCB
;               23      RENAME          FCB
;               24      ?LOGIN
;               25      ?DRIVE
;               26      SETDMA          BUFFER
;               27      ?ALLOC
;               28      WRPDSK
;               29      GETROV
;               30      SETFAT          FCB
;               31      GETDAT
;               32      GTSTUC
;               33      READRA          FCB
;               34      WRITRA          FCB
;               35      COMFSZ          FCB
;               36      SETRRC          FCB
;               37      RSTDRV
;               40      RANWR           FCB
;               SEE CP/M INTERFACE GUIDE FOR DETAILED INFORMATION ON THE
;               DISK ACCESS PRIMITIVES
;
;       DISKIO  READ,FCB        (TYPICAL MACRO CALL)
;
DISKIO  MACRO   FUNCTI,PARAME
8080
LIFTHEAD        SET     12
INITIAL         SET     13
LOGIN           SET     14
OPEN            SET     15
CLOSE           SET     16
SEARCH          SET     17
SERNXT          SET     18
DELETE          SET     19
READ            SET     20
WRITE           SET     21
MAKE            SET     22
RENAME          SET     23
?LOGIN          SET     24
?DRIVE          SET     25
SETDMA          SET     26
?ALLOC          SET     27
WRPDSK          SET     28
GETROV          SET     29
SETFAT          SET     30
GETDAT          SET     31
GTSTUC          SET     32
READRA          SET     33
WRITRA          SET     34
COMFSZ          SET     35
SETRRC          SET     36
RSTDRV          SET     37
RANWR           SET     40
;
?C      SET     FUNCTI
Z80
       IFNB    <PARAME>
       LD      DE,PARAME
       ENDIF
       LD      BC,?C
       CALL    5               ;;BDOS ENTRY
       ENDM
;
;       . . . . . . . . . . . . . . . . . . . . . . . . . . . .
;
;       CALLBIOS MACRO  CALL BIOS ROUTINES DIRECTLY
;
;       NOTE:   CP/M 2.2 VECTORS HAVE BEEN ADDED
;               D. NIENHISER    11/80
;
;       CALLBIOS        FUNCTION,PARAM
;
CALLBIOS        MACRO   FUNCT,PARAM
       LOCAL   @CALL
;
8080
DCOLD   SET     00H
DWBOOT  SET     03H
DSTAT   SET     06H
DCONIN  SET     09H
DCONOUT SET     0CH             ;;CHAR IN C
DLIST   SET     0FH             ;;CHAR IN C
DPUNCH  SET     12H
DREADER SET     15H
DHOME   SET     18H
DSELDSK SET     1BH
DSETTRK SET     1EH
DSETSEC SET     21H             ;;SECTOR NO IN C
DSETDMA SET     24H             ;;DMA ADDR IN BC
DREAD   SET     27H
DWRITE  SET     2AH
LISTST  SET     2DH
SECTRN  SET     30H
;
?F      SET     FUNCT
Z80
       IFNB    <PARAM>
       LD      BC,PARAM
       ENDIF
       LD      HL,(1)
       LD      L,?F AND X'FF'
       LD      (@CALL+1),HL
@CALL:  CALL    0
       ENDM
;
;       . . . . . . . . . . . . . . . . . . . . . . . . . . . .
;
;       DLOAD MACRO     DOUBLE PRECISION INDEXED LOAD HL
;
;               LOAD (ADDR + INDX) TO HL
;
DLOAD   MACRO   ADDR,INDX
       IFB     <INDX>
       LD      HL,(ADDR)
       ELSE
       LD      HL,(INDX)
       LD      DE,ADDR
       ADD     HL,DE
       LD      E,(HL)
       INC     HL
       LD      D,(HL)
       EX      DE,HL
       ENDIF
       ENDM
;       . . . . . . . . . . . . . . . . . . . . . . . . . . . .
;
;       CPHL MACRO      SUBTRACT DE FROM HL AND SET FLAGS
;
CPHL    MACRO
       LOCAL   @END
       LD      A,H
       CP      D               ;;COMPARE HIGH BYTES
       JR      NZ,@END
       LD      A,L
       CP      E               ;;COMPARE LOW BYTES
@END:
       ENDM
;
;       . . . . . . . . . . . . . . . . . . . . . . . . . . . .
;
;       DJZ MACRO       DOUBLE PRECISION TEST HL AND JUMP ON ZERO
;
DJZ     MACRO   ADDR
       LD      A,H
       OR      L
       JP      Z,ADDR
       ENDM
;       . . . . . . . . . . . . . . . . . . . . . . . . . . . .
;
;       DSTORE MACRO    DOUBLE PRECISION INDEXED STORE HL
;
;               STORE (HL) IN (ADDR + INDX)
;
DSTORE  MACRO   ADDR,INDX
       IFB     <INDX>
       LD      (ADDR),HL
       ELSE
       SAVE    HL
       LD      HL,(INDX)
       EX      DE,HL
       LD      HL,ADDR
       ADD     HL,DE
       RESTORE DE
       LD      (HL),E
       INC     HL
       LD      (HL),D
       ENDIF
       ENDM
;
;       . . . . . . . . . . . . . . . . . . . . . . . . . . . .
;
;       INDEX MACRO     INDEX AN ADDRESS POINTER BY A CONSTANT
;
;       INDEX   POINTER,INCR
;
INDEX   MACRO   POINTER,INCR
       LD      HL,(POINTER)
       LD      DE,INCR
       ADD     HL,DE
       LD      (POINTER),HL
       ENDM
;
;       . . . . . . . . . . . . . . . . . . . . . . . . . . .
;
;       FILFCB  MACRO   FILL IN THE ID FIELDS OF FCB
;
;       FILFCB  FCB,IDSTRING
;
;               IDSTRING CONTAINS FILE NAME AND TYPE  (FILNAM.TYP)
;               CARRY SET IF ERROR  (NAME TOO LONG)
;
FILFCB  MACRO   FCB,IDSTRI
       LOCAL   OVRFIL,F1,F2,F3,F4,F5,F6
       JR      OVRFIL
@FLFCB: LD      (HL),0
       INC     HL
       PUSH    HL
       LD      C,11            ;;SIZE OF ID FIELD
       LD      A,' '           ;;SPACE TO A
F1:     LD      (HL),A
       INC     HL
       DEC     C
       JR      NZ,F1
       POP     HL              ;;RESTORE NAME POINTER
       LD      C,8             ;;MAXIMUM SIZE OF NAME
F2:     LD      A,(DE)

       CP      ' '             ;;LEADING SPACES?
       JR      NZ,F3
       INC     DE
       JR      F2
F3:     LD      A,(DE)
       CP      0               ;;ZERO END OF FIELD
       RET     Z
       CP      ' '             ;;SPACE END OF FIELD
       RET     Z
       CP      '.'             ;;PERIOD TYPE SEPARATOR
       JR      Z,F4
       LD      (HL),A
       INC     HL
       INC     DE
       DEC     C
       JP      P,F3
       SCF                     ;;SET CARRY NAME TOO LARGE
       RET
F4:     INC     DE              ;;SKIP THE PERIOD
       LD      A,C
       OR      A
       JR      Z,F6            ;;TEST C FOR ZERO
F5:     INC     HL
       DEC     C
       JR      NZ,F5
F6:     LD      C,3             ;;SIZE OF TYPE FIELD
F7:     LD      A,(DE)
       CP      0               ;;ZERO?
       RET     Z
       CP      ' '             ;;SPACE?
       RET     Z
       LD      (HL),A
       INC     HL
       INC     DE
       DEC     C
       JR      NZ,F7
       RET
OVRFIL:
FILFCB  MACRO   ?FCB,?ID
       IFNB    <?ID>
       LD      DE,?ID
       ENDIF
       IFNB    <?FCB>
       LD      HL,?FCB
       ENDIF
       CALL    @FLFCB
       EX      DE,HL
       ENDM
       FILFCB  FCB,IDSTRI
       ENDM
;
;       . . . . . . . . . . . . . . . . . . . . . . . . . . . .
;
;       SETTRK MACRO    SET AND TEST TRACK NUMBER
;
;                       CARRY SET IF > 76
;
SETTRK  MACRO   TRKNO
       LOCAL   ENDTRK
       IFNB    <TRKNO>
       LD      A,TRKNO
       ENDIF
       CP      77
       CCF
       JR      C,ENDTRK
       LD      C,A             ;;TRACK NO TO C
       CALLBIOS DSETTRK
ENDTRK:
       ENDM
;
;       . . . . . . . . . . . . . . . . . . . . . . . . . . . .
;
;       SETSEC MACRO    SET AND TEST SECTOR NUMBER
;
;               RETURN WITH CARRY SET < 1 OR > 26
;
SETSEC  MACRO   SECNO
       LOCAL   ENDSEC
       IFNB    <SECNO>
       LD      A,SECNO
       ENDIF
       OR      A               ;CHECK ZERO
       SCF
       JR      Z,ENDSEC
       CP      27              ;CHECK > 26
       CCF
       JP      C,ENDSEC
       LD      C,A             ;MOVE TO C
       CALLBIOS DSETSEC
ENDSEC:
       ENDM
;       . . . . . . . . . . . . . . . . . . . . . . . . . . . .
;
;       HALF MACRO      DIVIDES A 16 BIT NUMBER BY 2
;
HALF    MACRO   I
       LOCAL   OVER
       JR      OVER
@HALF:  XOR     A               ;;CLEAR CARRY
       LD      A,H
       RRA                     ;;SHIFT UPPER HALF
       LD      H,A
       LD      A,L
       RRA                     ;;SHIFT LOWER HALF
       LD      L,A
       RET
OVER:
HALF    MACRO   ?I
       IFNB    <?I>
       LD      HL,(?I)
       ENDIF
       CALL    @HALF
       ENDM
       HALF    I
       ENDM