home *** CD-ROM | disk | FTP | other *** search
/ ftp.barnyard.co.uk / 2015.02.ftp.barnyard.co.uk.tar / ftp.barnyard.co.uk / cpm / walnut-creek-CDROM / BEEHIVE / ZSUS / ZSUS009.LBR / NZFCP13.LBR / NZFCP13.ZZ0 / NZFCP13.Z80
Text File  |  1990-07-14  |  34KB  |  1,424 lines

  1.  
  2. ; Program:    NZFCP
  3. ; Date:        October 9, 1989
  4. ; Author:    Carson Wilson <crw>
  5. ; Version:    1.3
  6. ; Changes:    Updated & improved JetLDR signon.
  7. ;        Changed four JR's to JP's.
  8.  
  9. ;  Date:    August 21, 1988
  10. ;  Author:    Carson Wilson
  11. ;  Version:    1.2
  12.  
  13. ;  Derived from:
  14.  
  15. ;  Date:    April 1988
  16. ;  Name changed and code modified for NZ-COM.
  17.  
  18. ;  Derived from:
  19.  
  20. ;  PROGRAM:    Z34FCP
  21. ;  AUTHOR:    Jay Sage
  22. ;  VERSION:    1.0
  23. ;  DATE:    May 25, 1987
  24. ;  DERIVATION:    FCP10 by Jay Sage (ZSIG)
  25.  
  26. ; ZCPR34 is copyright 1987 by Jay P. Sage.  All rights reserved.  End-user
  27. ; distribution and duplication permitted for non-commercial purposes only.
  28. ; Any commercial use of ZCPR34, defined as any situation where the duplicator
  29. ; recieves revenue by duplicating or distributing ZCPR34 by itself or in
  30. ; conjunction with any hardware or software product, is expressly prohibited
  31. ; unless authorized in writing by Jay P. Sage.
  32.  
  33. ;=============================================================================
  34. ;
  35. ;            R E V I S I O N    H I S T O R Y
  36. ;
  37. ;=============================================================================
  38. ;
  39. ;  21 Aug 88    Added JetLDR signon description.
  40. ;        IF IN now prints ' (Y/N)? ', and accepts only Y or y or
  41. ;        N or n.
  42. ;        Added macro code to show FCP length following assembly.
  43. ;
  44. ;                    Carson Wilson.
  45. ;
  46. ;  6 April 88    Handles latest Type 4 IF.COM
  47. ;    1.2    Changed command tail loader to accept :IF.  Joe Wright
  48. ;
  49. ;  12/31/87    Modified for use with Z34CMN.LIB for NZ-COM.  Joe Wright.
  50. ;    1.1
  51. ;
  52. ;  05/25/87    Created ZCPR33 version from the code I released through ZSIG.
  53. ;    1.0    This code differs only in the more efficient way in which it
  54. ;        determines if it was invoked with a directory prefix that
  55. ;        signals that the transient IF.COM should be used to process
  56. ;        the IF command.  This permits the user to force the use of a
  57. ;        more powerful option processor in the transient IF.COM than in
  58. ;        the resident code.  Option bytes were added after the end of
  59. ;        the resident option dispatch table so that SHOW can report
  60. ;        configuration options to the user.
  61. ;
  62. ;  FCP10 notes
  63. ;
  64. ;        The transient processor can now be loaded at an address other
  65. ;        than 100h so as not to interfere with code loaded in the TPA.
  66. ;        Then the GO command can normally be used even after IF.COM is
  67. ;        used to process the flow test.    If the LOADCHK equate
  68. ;        is true then the FCP will verify that the transient
  69. ;        processor has been loaded to the page in memory for which
  70. ;        it was assembled.  If loaded to the wrong page, it will
  71. ;        be reloaded to the correct one.
  72. ;
  73. ;        The test for the form ARG1=ARG2 was tightened up so as not to
  74. ;        be confused by an equal sign in some later part of the command
  75. ;        tail (e.g., "IF REG 1 = 2").  Now only the first token
  76. ;        (contiguous string of characters) is checked.  This extra code
  77. ;        is under the control of the XEQOPT equate.  The only option
  78. ;        that is still a problem is the COMIF form '~='.  Since the '='
  79. ;        is in the first token, this 'not equal' condition cannot be
  80. ;        distinguished from an equality test against the character '~'.
  81. ;        The solution is to turn off equality testing in the resident FCP
  82. ;        or to use the alternative COMIF options 'NE' or '~EQ' for this
  83. ;        test.
  84. ;
  85. ;        Added optional commands AND and OR.  These work like IF except
  86. ;        that they affect the current IF level rather than going one
  87. ;        level deeper.
  88. ;
  89. ;        Added optional command ZIF to zero out all IF states no matter
  90. ;        whether current state is true or false (XIF only works if state
  91. ;        is true.
  92. ;
  93. ;        Added new optional command IFQ (if-query) and enhanced the
  94. ;        IFSTAT code that is invoked when the NOISE equate is true.
  95. ;        In both cases, the entire tree of IF states is now shown,
  96. ;        starting with the current level.  For example, IFQ might result
  97. ;        in the display "IF FTT" (we are at third IF level and it is
  98. ;        false; the second and first IF levels are true).  If the
  99. ;        current IF level is 0, then the display is "IF None".
  100. ;
  101. ;        Added two new resident options: AMBIGUOUS (AM) returns true if
  102. ;        the file specification in the second token has a '?' (or '*')
  103. ;        in it; COMPRESSED (CO) returns true if the file specificaton in
  104. ;        the second token has a 'Z' or a 'Q' in the second character of
  105. ;        the file type.
  106. ;
  107. ;        Howard Goldstein contributed significantly to the development
  108. ;        of this code.  Bridger Mitchell also offered helpful
  109. ;        suggestions.
  110. ;
  111. ;                    Jay Sage
  112. ;
  113. ;  Notes from earlier SYSFCP revisions
  114. ;
  115. ;  09/12/85    Fixed bug in my code used when IF.COM is found in a specified
  116. ;        drive/user area.  The values of CDISK and CUSER were not being
  117. ;        set, and as a result the user was not returned to the correct
  118. ;        directory.  The EXIST and EMPTY tests did not work correctly
  119. ;        unless a DIR: or DU: was given explicitly with each file name.
  120. ;                    Jay Sage
  121.  
  122. ;  08/29/85    Reorganized code so that COMIF code handles only those
  123. ;        options not in the table of local IF functions.  Also changed
  124. ;        code to allow searching for IF.COM in a specified directory
  125. ;        instead of using the ROOT of the path.    Also renamed macros
  126. ;        to make code ZAS compatible.
  127. ;                    Jay Sage
  128.  
  129. ;  07/21/85    Corrected reversed sensing of program error flag in the
  130. ;        IF ERROR test.
  131. ;                    Jay Sage
  132.  
  133. ;  01/02/85    Revised to correct a bug in the IF EMPTY test.    First, the
  134. ;        current record byte was not being set to zero before trying
  135. ;        to read from the file.    Secondly, the test for error was not
  136. ;        testing for FF but for 00.  My BDOS does not return 0 for
  137. ;        success.  It seems to return 00, 01, 02, or 03.  This made the
  138. ;        file appear to be empty.
  139. ;                    Jay Sage
  140.  
  141.  
  142. ;=============================================================================
  143. ;
  144. ;        M A C R O S    A N D    E Q U A T E S
  145. ;
  146. ;=============================================================================
  147.  
  148.     name    ('FCP')
  149.  
  150. ; External macro references
  151.  
  152.     maclib    Z34CMN.LIB    ; Source of system addresses
  153.     maclib    NZFCP.LIB    ; Source of configuration options
  154.     maclib    Z34MAC.LIB    ; Z34 macros
  155.  
  156. ; Equates section
  157.  
  158. version    equ    13
  159.  
  160. lf    equ    0ah
  161. cr    equ    0dh
  162. bell    equ    07h
  163.  
  164. base    equ    0
  165. wboot    equ    base+0000h    ; CP/M warm boot address
  166. udflag    equ    base+0004h    ; User num in high nybble, disk in low
  167. bdos    equ    base+0005h    ; BDOS function call entry point
  168. tfcb    equ    base+005ch    ; Default FCB buffer
  169. fcb1    equ    tfcb        ; 1st and 2nd FCBs
  170. fcb2    equ    tfcb+16
  171. tbuff    equ    base+0080h    ; Default disk I/O buffer
  172. tpa    equ    base+0100h    ; Base of TPA
  173.  
  174.  
  175. ;=============================================================================
  176. ;
  177. ;        J e t L D R    S I G N - O N
  178. ;
  179. ;=============================================================================
  180.  
  181. ; This prints an extended ID message upon loading with JetLDR.
  182. ; These are NOT the command names.
  183.  
  184.     COM    /_ID_/
  185.  
  186.     db    'Copyright 1989 ZSA',cr,lf
  187.     db    'Commands:',cr,lf
  188.     db    ' IF ELSE FI XIF '
  189.  
  190.      if    andopt
  191.     db    'AND '
  192.      endif
  193.      if    oropt
  194.     db    'OR '
  195.      endif
  196.      if    ifqopt
  197.     db    'IFQ '
  198.      endif
  199.      if    zifopt
  200.     db    'ZIF '
  201.      endif
  202.  
  203.     db    cr,lf,'Options'
  204.      if    ifoneg
  205.     db    ' (use "',negchar,'" to negate)'
  206.      endif
  207.      if    noise
  208.     db    '; (noise)'
  209.      endif
  210.     db    ':',cr,lf
  211.  
  212.      if    ifotrue
  213.     db    ' T F '
  214.      endif
  215.      if    ifambig
  216.     db    'AMbig '
  217.      endif
  218.      if    ifcompr
  219.     db    'COmpr '
  220.      endif
  221.      if    ifoempty
  222.     db    'EMpty '
  223.      endif
  224.      if    ifoeq
  225.     db    'x=y '
  226.      endif
  227.      if    ifoerror
  228.     db    'ERror '
  229.      endif
  230.      if    ifoexist
  231.     db    'EXist '
  232.      endif
  233.      if    ifoinput
  234.     db    'INput '
  235.      endif
  236.      if    ifonull
  237.     db    'NUll '
  238.      endif
  239.      if    iforeg
  240.     db    'REgs '
  241.      endif
  242.      if    ifotcap
  243.     db    'TCap '
  244.      endif
  245.      if    ifowheel
  246.     db    'WHeel '
  247.      endif
  248.  
  249.      if    comif
  250.     db    cr,lf,' Use '
  251.      if    pathroot
  252.     db    'root:'
  253.      endif
  254.     db    'IF.COM'
  255.      endif
  256.  
  257.     db    0        ; End of JetLDR sign-on message
  258.  
  259.     CSEG
  260.  
  261. ;=============================================================================
  262.  
  263. ; Start of code
  264.  
  265. start:
  266.     db    'Z3FCP'        ; Flag for Package Loader
  267.  
  268. ;=============================================================================
  269. ;
  270. ;            C O M M A N D     T A B L E
  271. ;
  272. ;=============================================================================
  273.  
  274. ; The command name table is structured as follows:
  275. ;
  276. ;    The first byte is the number of characters in each command name.
  277. ;    Next come records consisting of command names followed by entry
  278. ;    point addresses for the code to process the command.  Finally,
  279. ;    there is a null to indicate the end of the dispatch table.
  280.  
  281.     db    cmdsize        ; Size of text entries
  282. ctab:    ctable            ; Macro defined in NZFCP.LIB
  283.     db    0
  284.  
  285. ;=============================================================================
  286. ;
  287. ;        I F    C O N D I T I O N    O P T I O N S
  288. ;
  289. ;=============================================================================
  290.  
  291. condtab:
  292.  
  293.      if    ifotrue
  294.     db    'T '        ; TRUE
  295.     dw    ifctrue
  296.     db    'F '        ; FALSE
  297.     dw    ifcfalse
  298.      endif    ; ifotrue
  299.  
  300.      if    ifambig        ; Ambiguous file spec
  301.     db    'AM'
  302.     dw    ifcambig
  303.      endif    ; ifambig
  304.  
  305.      if    ifcompr        ; Squeezed or crunched
  306.     db    'CO'
  307.     dw    ifccompr
  308.      endif    ; ifcompr
  309.  
  310.      if    ifoempty
  311.     db    'EM'        ; File empty
  312.     dw    ifcempty
  313.      endif    ; ifoempty
  314.  
  315.      if    ifoerror
  316.     db    'ER'        ; Error message
  317.     dw    ifcerror
  318.      endif    ; ifoerror
  319.  
  320.      if    ifoexist
  321.     db    'EX'        ; File exists
  322.     dw    ifcex
  323.      endif    ; ifoexist
  324.  
  325.      if    ifoinput
  326.     db    'IN'        ; User input
  327.     dw    ifcinput
  328.      endif    ; ifoinput
  329.  
  330.      if    ifonull
  331.     db    'NU'
  332.     dw    ifcnull
  333.      endif    ; ifonull
  334.  
  335.      if    ifotcap        ; Z3 TCAP available
  336.     db    'TC'
  337.     dw    ifctcap
  338.      endif    ; ifotcap
  339.  
  340.      if    ifowheel    ; Wheel Byte
  341.     db    'WH'
  342.     dw    ifcwheel
  343.      endif    ; ifowheel
  344.  
  345.     db    0
  346.  
  347. ; Option bytes: these option bytes can be used to convey information to
  348. ; programs such as SHOW.  The first one is used to reduce the chance of
  349. ; misinterpreting data from an earlier version of the FCP that does not
  350. ; have the option bytes.  The next byte tells if COMIF has been activated
  351. ; and if the root of the path will be used as the directory in which to look
  352. ; for IF.COM.  If PATHROOT is not selected (or if the path is empty), then
  353. ; the specified drive/user will be used.  The overflow bit in case the user
  354. ; number is greater than 15 is kept in bit 2 of the second option byte.  The
  355. ; combined user/drive value is kept in the third option byte.
  356.  
  357. highuser defl    ifusr gt 15
  358.  
  359. opt0:    db    34h        ; ZCPR34 version ID
  360. opt1:    optflag    highuser,pathroot,comif
  361. opt2:    db ( ifusr and 0fh ) shl 4 + ( ifdrv - 'A' )    ; user/drive flag
  362.  
  363. ;=============================================================================
  364. ;
  365. ;        C O M M A N D     P R O C E S S I N G    C O D E
  366. ;
  367. ;=============================================================================
  368.  
  369. ; Command: ZIF
  370. ;
  371. ;    This command zeros out the IF system no matter what the current
  372. ;    level IF state is.
  373.  
  374.      if    zifopt
  375.  
  376. ifzero:
  377.      if    noise
  378.     call    nl        ; Print new line
  379.      endif    ; noise
  380.  
  381.     jr    ifexit1
  382.  
  383.      endif    ; zifopt
  384.  
  385. ;-----------------------------------------------------------------------------
  386.  
  387. ; Command: XIF
  388. ;
  389. ;    If current IF state is true, XIF terminates all IFs, restoring a basic
  390. ;    TRUE state.
  391.  
  392. ifexit:
  393.      if    noise
  394.     call    nl        ; Print new line
  395.      endif    ; noise
  396.  
  397.     call    iftest        ; See if current IF is running and FALSE
  398.  
  399.      if    noise
  400.     jr    z,ifstat    ; Abort with status message if so
  401.      else    ; not noise
  402.     ret    z        ; Or just return if false
  403.      endif    ; noise
  404.  
  405. ifexit1:
  406.     ld    hl,z3msg+1    ; Pt to IF flag
  407.     ld    (hl),0        ; Zero IF flag
  408.     jr    ifendmsg    ; Print message
  409.  
  410. ;-----------------------------------------------------------------------------
  411.  
  412. ; Command: FI
  413. ;
  414. ;    FI decrements to the previous IF level.  It does this by shifting the
  415. ;    current-if-bit in the first 'if' message in the Z3MSG buffer right one
  416. ;    position.
  417.  
  418. ifend:
  419.      if    noise
  420.     call    nl        ; Print new line
  421.      endif    ; noise
  422.  
  423. ;    ld    hl,z3msg+1    ; Point to IF flag
  424. ;    ld    a,(hl)        ; Get it
  425. ;    or    a        ; No IF active?
  426.  
  427.     call    msgbf1
  428.     dec    hl        ; Save a byte over the three lines above
  429.  
  430.     jr    z,ifnderr
  431.  
  432. ifendmsg:
  433.      if    noise
  434.     call    print
  435.     dc    'To '        ; Prefix to status display
  436.      endif    ; noise
  437.  
  438.     srl    (hl)        ; Adjust active bit
  439.  
  440.      if    noise
  441.     jr    nz,ifstat    ; Print status if IF still active
  442.      endif    ; noise
  443.  
  444. ifnderr:
  445.      if    noise
  446.  
  447.     call    print        ; Print message
  448.     dc    'No '
  449.     jp    prif
  450.  
  451.      else    ; not noise
  452.  
  453.     ret
  454.  
  455.      endif    ; noise
  456.  
  457. ;-----------------------------------------------------------------------------
  458.  
  459. ; Command: ELSE
  460. ;
  461. ;    ELSE complements the Active Bit for the Current IF provided the
  462. ;    previous IF state was true.  If the previous state was false, the
  463. ;    command is flushed.
  464. ;
  465. ;    This is accomplished according to the following algorithm.  If the
  466. ;    current IF is 0 (no IF) or 1 (one IF), then take the previous state
  467. ;    to be true and perform the toggle.  Otherwise, test the previous
  468. ;    IF level condition and toggle only if it is true.
  469.  
  470. ifelse:
  471.      if    noise and (not ifqopt)
  472.     call    nl        ; Print new line
  473.      endif    ; noise and (not ifqopt)
  474.  
  475.     call    msgbf1        ; Get current if
  476.     ld    b,a        ; Save in B
  477.     srl    a        ; Back up if pointer bit to previous IF level
  478.     jr    z,iftog        ; If no previous IF level, go to toggle code
  479.     and    (hl)        ; Determine state of previous IF level
  480.  
  481.      if    noise
  482.      if    ifqopt
  483.     jr    z,ifstat0    ; Print status on new line
  484.      else
  485.     jr    z,ifstat    ; If false, just print status
  486.      endif            ; Ifqopt
  487.      else    ; not noise
  488.     ret    z        ; Or simply return
  489.      endif    ; noise
  490.  
  491. iftog:
  492.     ld    a,(hl)        ; Get if-status message byte
  493.     xor    b        ; Flip current state
  494.     ld    (hl),a        ; Put result back in message byte
  495.                 ; ..and fall thru to print status
  496.  
  497.      if    not noise
  498.     ret
  499.      endif
  500.  
  501. ;-----------------------------------------------------------------------------
  502.  
  503. ; Indicate if current IF is True or False
  504.  
  505. ifstat0:
  506.     call    nl
  507. ifstat:
  508.     call    prif        ; Print 'IF '
  509.     call    msgbf1        ; Get current if byte and set flags
  510.     ld    b,a        ; Get it into B
  511.     jr    nz,ifstat1    ; Nz means if active
  512.  
  513.     call    print
  514.     dc    'None'
  515.     ret
  516.  
  517. ifstat1:
  518.     ld    a,(hl)        ; Get if-status message byte
  519.     and    b        ; Mask in currently active IF level status
  520.     ld    c,'F'        ; Load with false indicator
  521.     jr    z,ifstat2    ; If current IF is false, jump
  522.     ld    c,'T'        ; Else, load with true indicator
  523. ifstat2:
  524.     ld    a,c
  525.     call    conout
  526.  
  527.     srl    b        ; Drop one IF level
  528.     jr    nz,ifstat1    ; Loop through all IF states
  529.     ret
  530.  
  531. ;-------------------------
  532.  
  533. ;  Output CRLF
  534.  
  535. nl:    call    print
  536.     dc    cr,lf
  537.     ret
  538.  
  539. ;-----------------------------------------------------------------------------
  540.  
  541. ; Command:  OR
  542.  
  543. ;    This command performs a logical or operation by updating the
  544. ;    if state without going to a new level.    If there are active
  545. ;    IFs and the current state is true, we do nothing.  Else we back
  546. ;    up one level and fall through to normal IF processing.
  547.  
  548.      if    oropt
  549.  
  550. orstart:
  551.     call    msgbf1        ; Get if active byte
  552.     jr    z,backup    ; Treat like if if no IFs active
  553.     and    (hl)        ; Check current state
  554.     jr    z,backup    ; Current STATE false so go proecess
  555.  
  556.      if    noise
  557.     jr    ifstat0        ; Else return and show status
  558.      else
  559.     ret            ; Or just return
  560.  
  561.      endif            ; Noise
  562.      endif        ; Oropt
  563.  
  564. ;-----------------------------------------------------------------------------
  565.  
  566. ; Command:  AND
  567.  
  568. ;    This command performs a logical and operation by updating the
  569. ;    if state without going to a new level.    If there are active
  570. ;    IFs and the current state is false, we do nothing.  Else we back
  571. ;    up one level and fall through to normal IF processing.
  572.  
  573.      if    andopt
  574.  
  575. andstart:
  576.     call    iftest        ; Test for IF running and false
  577.      if    noise
  578.     jr    z,ifstat0    ; Condition met, show status & return
  579.      else
  580.     ret    z        ; Condition met, return
  581.      endif            ; Noise
  582.      endif        ; Andopt
  583.  
  584. ; Common stuff for and and or
  585.  
  586.     if andopt or oropt
  587.  
  588. backup:
  589.     dec    hl        ; Pt to flag byte
  590.     srl    (hl)        ; Drop back one level
  591. ;
  592. ; Poke "IF" into external fcb for transient
  593. ;
  594.      if    comif
  595. pokefcb:
  596.     ld    de,extfcb+1    ; Pt to external fcb
  597.     ld    hl,ifcmd    ; Pointer to IF command in table
  598.     ld    bc,cmdsize    ; Length
  599.     ldir            ; Move it in
  600.  
  601.      endif            ; comif
  602.  
  603. ;    Fall through to IF PROCESSING
  604.      endif            ;Andopt or oropt
  605.  
  606. ;-----------------------------------------------------------------------------
  607.  
  608. ; FCP Command: IF
  609. ;
  610. ;    If current IF state is false, then advance to next level and set it
  611. ;    to false also.    If current IF state is true, then test condition and
  612. ;    set the next level accordingly.
  613.  
  614. ifstart:
  615.      if    not ifqopt
  616.  
  617.     ld    a,(extfcb)    ; NZ if explicit
  618.     ld    hl,tbuff
  619.     or    (hl)
  620.     jp    z,ifstat0    ; Report IF status
  621.  
  622.      endif    ; not ifqopt
  623.  
  624. ifstrt:
  625.      if    noise
  626.     call    nl        ; Print new line
  627.      endif    ; noise
  628.  
  629.     call    iftest        ; See if current IF is running and FALSE
  630.     jP    z,ifcf        ; Yes, do the right thing
  631.  
  632. ; Test for presence of colon in command.  If colon present, then go directly
  633. ; to COMIF processing.
  634.  
  635.      if    comif
  636.     ld    a,(extfcb)    ; Check drive byte of external FCB
  637.     or    a        ; If it is zero, no colon was present
  638.     jp    nz,runcomif    ; If colon, go to comif processing
  639.                 ; Else fall through to resident processing
  640.      endif    ; comif
  641.  
  642. ;-----------------------------------------------------------------------------
  643. ;
  644. ;    R E S I D E N T    C O M M A N D    P R O C E S S I N G
  645. ;
  646. ;-----------------------------------------------------------------------------
  647.  
  648. resident:
  649.  
  650. ; Test for Equality if Equal Sign in Token
  651.  
  652.      if    ifoeq
  653.  
  654.     ld    hl,tbuff+1
  655.  
  656.      if    xeqopt        ; Extended equal testing
  657.  
  658. skipsp:                ; Skip over any space to first token
  659.     ld    a,(hl)
  660.     or    a        ; Check for end of tail
  661.     jr    z,ifck0        ; If so , go on
  662.     cp    ' '+1        ; Test for space or control character
  663.     jr    nc,tsteq    ; If not, we are at first token
  664.     inc    hl        ; Otherwise advance to next character
  665.     jr    skipsp        ; ..and continue testing
  666.  
  667.      endif    ; xeqopt
  668.  
  669. tsteq:
  670.     ld    a,(hl)        ; Get character from command tail
  671.     inc    hl        ; Point to next one
  672.     or    a        ; EOL?
  673.     jr    z,ifck0        ; Continue if so
  674.  
  675.      if    xeqopt
  676.     cp    ' '+1        ; End of token?
  677.     jr    c,ifck0        ; If so, go on
  678.      endif    ; xeqopt
  679.  
  680.     cp    '='        ; Found '=' ?
  681.     jr    nz,tsteq    ; If not, continue scan
  682.  
  683.     ld    hl,fcb1+1    ; Else, get ready to compare FCBs
  684.     ld    de,fcb2+1
  685.     ld    b,11        ; 11 bytes
  686. eqtest:
  687.     ld    a,(de)        ; Compare
  688.     cp    (hl)
  689.     jr    nz,ifcf
  690.     inc    hl        ; Pt to next
  691.     inc    de
  692.     djnz    eqtest
  693.     jr    ifct
  694.  
  695.      endif    ; ifoeq
  696.  
  697.  
  698. ifck0:
  699.     ld    de,fcb1+1    ; Point to first character in FCB1
  700.  
  701.      if    ifoneg
  702.     ld    a,(de)        ; Get it
  703.     ld    (negflag),a    ; Set negate flag
  704.     cp    negchar        ; Is it a negate?
  705.     jr    nz,ifck1    ; If not, go on
  706.     inc    de        ; Else point to character after negchar
  707. ifck1:
  708.      endif    ; ifoneg
  709.  
  710.      if    iforeg        ; REGISTERS
  711.     call    regtest        ; Test for register value
  712.     jr    nz,runreg
  713.      endif    ; iforeg
  714.  
  715.     call    condtest    ; Test of condition match
  716.     jr    nz,runcond    ; If found, process condition
  717.  
  718.      if    comif
  719.     jp    runcomif    ; If function not found in table, use transient
  720.      else
  721.  
  722.     call    print        ; Beep to indicate error
  723.     dc    bell
  724.  
  725.      if    noise
  726.     jp    ifstat        ; No condition, display current condition
  727.      else    ; no noise
  728.     ret
  729.      endif    ; noise
  730.      endif    ; comif
  731.  
  732. ;-----------------------------------------------------------------------------
  733. ;
  734. ; Process register - register value is in A
  735. ;
  736. ;-----------------------------------------------------------------------------
  737.  
  738.      if    iforeg
  739. runreg:
  740.     push    af        ; Save value
  741.     call    getnum        ; Extract value in FCB2 as a number
  742.     pop    af        ; Get value
  743.     cp    b        ; Compare against extracted value
  744.     jr    jrtrue        ; True if match; false if not
  745.      endif    ; iforeg
  746.  
  747. ;-----------------------------------------------------------------------------
  748. ;
  749. ; Process conditional test - address of conditional routine is in HL
  750. ;
  751. ;-----------------------------------------------------------------------------
  752.  
  753. runcond:
  754.     jp    (hl)        ; "call" routine pted to by HL
  755.  
  756. ;=============================================================================
  757. ;
  758. ;        R E S I D E N T    C O N D I T I O N    O P T I O N S
  759. ;
  760. ;=============================================================================
  761.  
  762. ; Condition:  AMBIGUOUS
  763.  
  764.      if    ifambig
  765.  
  766. ifcambig:
  767.     ld    hl,fcb2+1    ; Scan FCB2 for a '?' character
  768.     ld    bc,11        ; Characters to scan
  769.     ld    a,'?'        ; Reference character
  770.     cpir
  771.     jr    jrtrue        ; True if '?' found; false if not
  772.  
  773.      endif    ; ifambig
  774.  
  775. ;-----------------------------------------------------------------------------
  776.  
  777. ; Condition:  COMPRESSED
  778.  
  779.      if    ifcompr
  780.  
  781. ifccompr:
  782.     ld    a,(fcb2+10)    ; Get middle character of file type
  783.     cp    'Z'        ; Crunched
  784.     jr    z,ifctrue
  785.     cp    'Q'        ; Squeezed
  786.     jr    jrtrue
  787.  
  788.      endif    ; ifcompr
  789.  
  790. ;-----------------------------------------------------------------------------
  791.  
  792. ; Condition:  TRUE
  793. ;    IFCTRUE  enables an active IF
  794. ; Condition:  FALSE
  795. ;    IFCFALSE enables an inactive IF
  796.  
  797.      if    ifoempty or ifoerror or    ifoexist or ifowheel
  798. jrfalse:
  799.     jr    z,ifcfalse
  800.      endif    ; Ifoempty or ifoerror or ifoexist or ifowheel
  801.  
  802. ifctrue:
  803.  
  804.      if    ifoneg
  805.     call    negtest        ; Test for negate
  806.     jr    z,ifcf
  807.      endif    ; ifoneg
  808.  
  809. ifct:
  810.     ld    b,0ffh        ; Active
  811.     jp    ifset
  812.  
  813.      if    iforeg or ifambig or ifcompr or    ifoinput or ifonull
  814. jrtrue:
  815.     jr    z,ifctrue
  816.      endif    ; Iforeg or ifambig or ifcompr or ifoinput or ifonull
  817.  
  818. ifcfalse:
  819.  
  820.      if    ifoneg
  821.     call    negtest        ; Test for negate
  822.     jr    z,ifct
  823.      endif    ; ifoneg
  824.  
  825. ifcf:
  826.     ld    b,0        ; Inactive
  827.     jp    ifset
  828.  
  829. ;-----------------------------------------------------------------------------
  830.  
  831. ; Condition: EMPTY filename.typ
  832.  
  833.      if    ifoempty
  834. ifcempty:
  835.     call    tlog        ; Log into FCB2's DU
  836.     ld    de,fcb2        ; Pt to fcb2
  837.     ld    c,15        ; Open file
  838.     push    de        ; Save fcb ptr
  839.     call    bdos
  840.     pop    de
  841.     inc    a        ; Not found?
  842.     jr    z,ifctrue
  843.     ld    c,20        ; Try to read a record
  844.     xor    a        ; <JPS> set cr value to zero
  845.     ld    (fcb2+32),a    ; <JPS> to attempt to read first record
  846.     call    bdos
  847.     or    a        ; 0=OK
  848.     jr    jrfalse        ; true if no read
  849.      endif    ; ifoempty
  850.  
  851. ;-----------------------------------------------------------------------------
  852.  
  853. ; Condition: ERROR
  854.  
  855.      if    ifoerror
  856. ifcerror:
  857.     ld    a,(z3msg+6)    ; Get error byte
  858.     or    a        ; 0=FALSE (no error registered)
  859.     jr    jrfalse
  860.      endif    ; ifoerror
  861.  
  862. ;-----------------------------------------------------------------------------
  863.  
  864. ; Condition: EXIST filename.typ
  865.  
  866.      if    ifoexist
  867. ifcex:
  868.     call    tlog        ; Log into DU
  869.     ld    de,fcb2        ; Pt to fcb
  870.     ld    c,17        ; Search for first
  871.     call    bdos
  872.     inc    a        ; Set zero if error
  873.     jr    jrfalse
  874.      endif            ; Ifoexist
  875.  
  876. ;-----------------------------------------------------------------------------
  877.  
  878. ; Condition: INPUT (from user)
  879.  
  880. ; Modified to say " (Y/N)? ", and accept ONLY Y or y or N or n
  881. ; Carson Wilson  3/1/88
  882.  
  883.      if    ifoinput
  884. ifcinput:
  885.     call    print
  886.     dc    ' (Y/N)? '
  887. ifcinp1:
  888.     ld    hl,z3msg+7    ; Pt to ZEX message byte
  889.     ld    (hl),10b    ; Suspend ZEX input
  890.     push    hl        ; Save ptr to ZEX message byte
  891. ifcinp2:
  892.     ld    e,0ffh
  893.     ld    c,6        ; Direct input from console
  894.     call    bdos
  895.     or    a        ; Any input yet?
  896.     jr    z,ifcinp2    ; Nope, try again
  897.  
  898.     pop    hl        ; Get ptr to ZEX message byte
  899.     ld    (hl),0        ; Return ZEX to normal processing
  900.     and    5fh        ; Mask and capitalize user input
  901.     cp    'Y'
  902.     jr    nz,testN    ; No, check if 'N'
  903.     call    conout        ; Display 'Y'
  904.     jr    ifctrue        ; Process as true
  905. testN:
  906.     cp    'N'
  907.     jr    nz,notN        ; Not 'N' or 'n'
  908.     call    conout        ; Display 'N'
  909.     jr    ifcfalse    ; Process as false
  910. notN:
  911.     ld    a,bell        ; Protest!
  912.     call    conout
  913.     jr    ifcinp1        ; Force either Y or y or N or n
  914.  
  915.      endif    ; ifoinput
  916.  
  917. ;-----------------------------------------------------------------------------
  918.  
  919. ; Condition:  NULL (2nd file name)
  920.  
  921.      if    ifonull
  922. ifcnull:
  923.     ld    a,(fcb2+1)    ; Get first char of 2nd file name
  924.     cp    ' '        ; Space = null
  925.     jr    jrtrue
  926.      endif    ; ifonull
  927.  
  928. ;-----------------------------------------------------------------------------
  929.  
  930. ; Condition:  TCAP
  931.  
  932.      if    ifotcap
  933. ifctcap:
  934.     ld    a,(z3env+80h)    ; Get first char of Z3 TCAP Entry
  935.     cp    ' '+1        ; Space or less = none
  936.     jP    c,ifcfalse
  937.     jP    ifctrue
  938.      endif    ; ifotcap
  939.  
  940. ;-----------------------------------------------------------------------------
  941.  
  942. ; Condition:  WHEEL
  943.  
  944.      if    ifowheel
  945. ifcwheel:
  946.     ld    hl,(z3env+29h)    ; Get address of wheel byte
  947.     ld    a,(hl)        ; Get byte
  948.     or    a        ; Test for true
  949.     jP    jrfalse    ; False if 0
  950.      endif    ; ifowheel
  951.  
  952. ;=============================================================================
  953. ;
  954. ;        S U P P O R T     R O U T I N E S
  955. ;
  956. ;=============================================================================
  957.  
  958. ; Convert chars in FCB2 into a number in B
  959.  
  960.      if    iforeg
  961. getnum:
  962.     ld    b,0        ; Set number
  963.     ld    hl,fcb2+1    ; Pt to first char
  964. getn1:
  965.     ld    a,(hl)        ; Get char
  966.     inc    hl        ; Pt to next
  967.     sub    '0'        ; Convert to binary
  968.     ret    c        ; Done if error
  969.     cp    10        ; Range?
  970.     ret    nc        ; Done if out of range
  971.     ld    c,a        ; Value in C
  972.     ld    a,b        ; A=old value
  973.     add    a,a        ; *2
  974.     add    a,a        ; *4
  975.     add    a,b        ; *5
  976.     add    a,a        ; *10
  977.     add    a,c        ; Add in new digit value
  978.     ld    b,a        ; Result in B
  979.     jr    getn1        ; Continue processing
  980.      endif    ; iforeg
  981.  
  982. ;-----------------------------------------------------------------------------
  983.  
  984. ; Log into DU in FCB2
  985.  
  986.      if    ifoexist or ifoempty
  987.  
  988. tlog:
  989.     ld    a,(fcb2)    ; Get disk
  990.     or    a        ; Current?
  991.     jr    nz,tlog1
  992.     ld    c,25        ; Get disk
  993.     call    bdos
  994.     inc    a        ; Increment for following decrement
  995. tlog1:
  996.     dec    a        ; A=0
  997.     ld    e,a        ; Disk in E
  998.     ld    c,14
  999.     call    bdos
  1000.     ld    a,(fcb2+13)    ; Pt to user
  1001.     ld    e,a
  1002.     ld    c,32        ; Set user
  1003.     jp    bdos
  1004.  
  1005.      endif    ; ifoexist or ifoempty
  1006.  
  1007. ;-----------------------------------------------------------------------------
  1008.  
  1009. ; Test of Negate Flag = negchar
  1010.  
  1011.      if    ifoneg
  1012. negtest:
  1013. negflag    equ    $+1        ; Pointer for in-the-code modification
  1014.     ld    a,0        ; 2nd byte is filled in
  1015.     cp    negchar        ; Test for No
  1016.     ret
  1017.      endif    ; ifoneg
  1018.  
  1019. ;-----------------------------------------------------------------------------
  1020.  
  1021. ; Test FCB1 against a single digit (0-9)
  1022. ;  Return with register value in A and NZ if so
  1023.  
  1024.      if    iforeg
  1025. regtest:
  1026.     ld    a,(de)        ; Get digit
  1027.     sub    '0'
  1028.     jr    c,zret        ; Z flag for no digit
  1029.     cp    10        ; Range?
  1030.     jr    nc,zret        ; Z flag for no digit
  1031.     ld    hl,z3msg+30h    ; Pt to registers
  1032.     add    a,l        ; Pt to register
  1033.     ld    l,a
  1034.     ld    a,h        ; Add in H
  1035.     adc    0
  1036.     ld    h,a
  1037.     xor    a        ; Set NZ
  1038.     dec    a
  1039.     ld    a,(hl)        ; Get register value
  1040.     ret
  1041. zret:
  1042.     xor    a        ; Set Z
  1043.     ret
  1044.      endif    ; iforeg
  1045.  
  1046. ;-----------------------------------------------------------------------------
  1047.  
  1048. ; Test to see if a current IF is running and if it is FALSE
  1049. ;   If so, return with Zero Flag Set (Z)
  1050. ;   If not, return with Zero Flag Clear (NZ)
  1051. ; Affect only HL and PSW
  1052.  
  1053. iftest:
  1054.     call    msgbf1        ; Test for active IF
  1055.     jr    z,ifok        ; No active IF
  1056.     and    (hl)        ; Check active flag
  1057.     ret    z        ; Return Z since IF running and FALSE
  1058. ifok:
  1059.     or    255        ; Return NZ for OK
  1060.     ret
  1061.  
  1062. msgbf1:
  1063.     ld    hl,z3msg+1    ; Get IF active flag
  1064.     ld    a,(hl)
  1065.     inc    hl        ; Pt to If status byte
  1066.     or    a        ; Set z if no IF active
  1067.     ret
  1068.  
  1069. ;-----------------------------------------------------------------------------
  1070.  
  1071. ; Test FCB1 against condition table (must have 2-char entries)
  1072. ;  Return with routine address in HL if match and NZ flag
  1073.  
  1074. condtest:
  1075.     ld    hl,condtab    ; Pt to table
  1076. condt1:
  1077.     ld    a,(hl)        ; End of table?
  1078.     or    a
  1079.     ret    z
  1080.     ld    a,(de)        ; Get char
  1081.     cp    (hl)        ; Comppare entries
  1082.     inc    hl        ; Pt to next
  1083.     inc    de
  1084.     jr    nz,condt2
  1085.     ld    a,(de)        ; Get 2nd char
  1086.     cp    (hl)        ; Compare
  1087.     jr    nz,condt2
  1088.     inc    hl        ; Pt to address
  1089.     ld    a,(hl)        ; Get address in HL
  1090.     inc    hl
  1091.     ld    h,(hl)
  1092.     ld    l,a        ; HL = address
  1093.     jr    ifok        ; Set NZ for OK
  1094. condt2:
  1095.     inc    hl        ; Pt to next entry
  1096.     inc    hl        ; Skip over addr
  1097.     inc    hl
  1098.     dec    de        ; Pt to 1st char of condition
  1099.     jr    condt1
  1100.  
  1101. ;-----------------------------------------------------------------------------
  1102.  
  1103. ; Turn on next IF level
  1104. ;   B register is 0 if level is inactive, 0FFH if level is active
  1105.  
  1106. ifset:
  1107. ;    ld    hl,z3msg+1    ; Get IF flag
  1108. ;    ld    a,(hl)
  1109. ;    or    a        ; If no if at all, start 1st one
  1110.  
  1111.     call    msgbf1
  1112.     dec    hl
  1113.  
  1114.     jr    z,ifset1
  1115. ifset0:
  1116.     add    a,a        ; Advance to next level
  1117.     jr    c,iferr        ; Check for overflow (8 IFs max)
  1118.     ld    (hl),a        ; Set IF byte
  1119.     jr    ifset2
  1120. ifset1:
  1121.     inc    a        ; A=1
  1122.     ld    (hl),a        ; Set 1st IF
  1123. ifset2:
  1124.     ld    d,a        ; Get IF byte
  1125.     and    b        ; Set interested bit
  1126.     ld    b,a
  1127.     inc    hl        ; Pt to active flag
  1128.     ld    a,d        ; Complement IF byte
  1129.     cpl
  1130.     and    (hl)        ; Mask in only uninterested bits
  1131.     or    b        ; Mask in interested bit
  1132.     ld    (hl),a        ; Save result
  1133.  
  1134.      if    noise
  1135.     jp    ifstat        ; Print status and exit
  1136.      else
  1137.     ret            ; Or just exit
  1138.      endif    ; noise
  1139.  
  1140. iferr:
  1141.     call    print        ; Beep to indicate overflow
  1142.     dc    bell
  1143.     ret
  1144.  
  1145. ;=============================================================================
  1146. ;
  1147. ;        T R A N S I E N T    I F    P R O C E S S I N G
  1148. ;
  1149. ;=============================================================================
  1150.  
  1151.  
  1152.      if    comif
  1153.  
  1154. runcomif:
  1155.  
  1156. ; First we have to find IF.COM
  1157.  
  1158.     ld    bc,100h*(ifdrv-'A')+ifusr ; Values to use if null path
  1159.  
  1160.      if    pathroot
  1161.  
  1162.     ld    hl,(expath)    ; Point to symbolic path (indirect)
  1163. fndroot:
  1164.     ld    a,(hl)        ; Check for end of path
  1165.     or    a
  1166.     jr    z,froot2    ; If end, branch
  1167.  
  1168. ; Process Next Path Element
  1169.  
  1170.     cp    curint        ; Current disk/user symbol?
  1171.     jr    nz,froot0    ; If not, branch
  1172.     ld    a,(curdr)    ; Get current disk
  1173.     inc    a        ; Compensate for following decrement
  1174. froot0:
  1175.     dec    a        ; Shift to range 0..15
  1176.     ld    b,a        ; Set disk
  1177.     inc    hl        ; Point to user in path
  1178.     ld    a,(hl)        ; Get user
  1179.     cp    curint        ; Current drive/user symbol?
  1180.     jr    nz,froot1    ; If not, branch
  1181.     ld    a,(curusr)    ; Get current user
  1182. froot1:
  1183.     ld    c,a        ; Set user
  1184.     inc    hl        ; Point to next element in symbolic path
  1185.     jr    fndroot
  1186.  
  1187. ; Done with Search - BC Contains ROOT DU (or specified DU if path is empty)
  1188.  
  1189.      endif    ; pathroot
  1190.  
  1191. froot2:
  1192.     call    logbc        ; Log into IF.COM's directory
  1193.  
  1194. ; Try to Open File IF.COM
  1195.  
  1196.     ld    de,extfcb    ; Point to command FCB
  1197.     xor    a
  1198.     ld    (de),a        ; Force current drive
  1199.     ld    c,15        ; Open file
  1200.     call    bdos
  1201.     inc    a
  1202.     jr    nz,ifload    ; Branch if file found
  1203.  
  1204. ; IF.COM not found - process as IF F
  1205.  
  1206. ifnotfnd:
  1207.     call    iferr        ; Ring bell
  1208.     call    reset        ; Return home
  1209.     jp    ifcf
  1210.  
  1211. ; Load File IF.COM
  1212.  
  1213. ifload:
  1214.     call    defdma        ; First record to tbuff
  1215.     call    readcmd        ; Read 1st record from IF.COM
  1216.     jr    nz,ifnotfnd    ; If eof, treat as if file not found
  1217.  
  1218.     ld    (extfcb+32),a    ; Start from scratch (record 0)
  1219.     ld    a,(tbuff+8)
  1220.     cp    3
  1221.     jr    c,ifnotfnd    ; Only Types 3 and 4 are acceptable
  1222.  
  1223.     call    loadif        ; Load IF.COM and set IFADR appropriately
  1224. ;
  1225. ; Build the command tail at tbuff
  1226. ;
  1227.     ld    de,tbuff    ; Point DE to tbuff
  1228.     push    de        ; Save it for later
  1229.     ld    hl,(z3msg+4)    ; Points into MCL buffer
  1230. ;
  1231. ; Advance HL to first 'space' after IF or .IF or :IF
  1232. ;
  1233. advsp:    inc    hl
  1234.     ld    a,(hl)
  1235.     cp    ' '+1        ; Carry if space or null
  1236.     jr    nc,advsp
  1237.  
  1238.     ld    c,0        ; Clear a counter
  1239.  
  1240. putt:    inc    de        ; Advance tbuff pointer
  1241.     ld    a,(hl)        ; From MCL
  1242.     ld    (de),a        ; To tbuff
  1243.     inc    hl        ; Advance MCL pointer
  1244.     or    a        ; Check for null
  1245.     jr    z,putx        ; End of command line
  1246.     cp    ';'        ; Command separator
  1247.     jr    z,putx        ; End of command
  1248.     inc    c        ; Count it up
  1249.     jr    putt        ; Next..
  1250.  
  1251. putx:    xor    a        ; Get a null
  1252.     ld    (de),a        ; Terminate the line in tbuff
  1253.     pop    hl        ; Beginning of tbuff
  1254.     ld    (hl),c        ; Character count
  1255. ;
  1256. ; Pick up the execution address for Type 3 or 4
  1257. ;
  1258.     ld    hl,(ifadr)    ; Load address
  1259.     ld    a,(hl)        ; First byte at load address
  1260.     cp    0c7h        ; Test for RST 0
  1261.     jr    nz,runif    ; Nope, execute it
  1262.     ld    (hl),0c3h    ; Plug in a JP
  1263. ;
  1264. ; Arrive here to execute IF.COM
  1265. ;
  1266. runif:    ld    hl,z3env    ; Pass environment in HL
  1267.     db    0c3h        ; JP instruction
  1268. ifadr:    dw    0        ; Load/Execution address of IF.COM
  1269.  
  1270. ;
  1271. ; Load IF.COM
  1272. ;
  1273. loadif:
  1274.     ld    hl,(tbuff+11)    ; Type 3 load address
  1275.     jr    z,loada        ; Load as Type 3
  1276. ;
  1277. ; Assume Type 4 (or higher)
  1278. ;
  1279.     ld    hl,extfcb+32    ; Point to CR of extfcb
  1280.     ld    (hl),2        ; Set up for record 2
  1281.     push    hl        ; Save the pointer
  1282.     call    readcmd        ; Get it into tbuff
  1283.     pop    hl
  1284.     jp    nz,ifnotfnd    ; Too short
  1285.     ld    (hl),a        ; Record 0 again
  1286.     ld    hl,(tbuff+11)    ; Size word
  1287.     push    hl        ; Save it
  1288.     call    readcmd        ; Read record 0 again
  1289.     pop    bc        ; Size
  1290.     ld    de,(ccp)    ; CCP start
  1291.     ld    hl,z3env
  1292.     dec    a        ; Phony fullget flag
  1293.     call    tbuff+9        ; Call Type 4 loader
  1294.     push    hl        ; Save load address
  1295.     call    readcmd        ; Read record 1 to tbuff (point to record 2)
  1296.     pop    hl        ; Load address
  1297. ;
  1298. loada:    ld    (ifadr),hl    ; Save it
  1299. ;
  1300. ; Load IF.COM to (HL) until end of file, reset DMA and DU and return
  1301. ;
  1302. load:    push    hl        ; Save loading address
  1303.     call    setdma        ; According to HL
  1304.     call    readcmd        ; Read a record from file
  1305.     pop    hl        ; Get current loading address back
  1306.     jr    nz,reset    ; End of file
  1307.     ld    de,128        ; Advance it by one record
  1308.     add    hl,de
  1309.     jr    load        ; Back to read some more
  1310.  
  1311. ; Reset DMA and Current DU
  1312.  
  1313. reset:    call    defdma
  1314.     ld    bc,(curusr)    ; Return home
  1315.  
  1316. ; Log Into DU in BC
  1317.  
  1318. logbc:    ld    e,b        ; Set disk
  1319.     push    bc
  1320.     ld    c,14        ; Select disk
  1321.     call    bdos
  1322.     pop    bc
  1323.     ld    e,c        ; Set user
  1324.     ld    c,32        ; Select user
  1325.     jp    bdos
  1326.  
  1327.  
  1328. ; Set default DMA address
  1329.  
  1330. defdma:    ld    hl,tbuff
  1331.  
  1332. ; Set DMA to address according to HL
  1333.  
  1334. setdma:    push    hl        ; Save it
  1335.     ex    de,hl        ; To DE
  1336.     ld    c,26        ; Set DMA command
  1337.     call    bdos        ; Do it
  1338.     pop    hl        ; DMA address
  1339.     ret
  1340.  
  1341. ; Read a record from file in EXTFCB
  1342.  
  1343. readcmd:
  1344.     ld    de,extfcb
  1345.     ld    c,20
  1346.     call    bdos
  1347.     or    a        ; Set NZ if error (end of file)
  1348.     ret
  1349.  
  1350.      endif    ; comif
  1351.  
  1352. ;=============================================================================
  1353. ;
  1354. ;        U T I L I T Y     S U B R O U T I N E S
  1355. ;
  1356. ;=============================================================================
  1357.  
  1358. ;  Print "IF "
  1359.  
  1360. prif:
  1361.     call    print
  1362.     dc    'IF '
  1363.     ret
  1364.  
  1365. ;-----------------------------------------------------------------------------
  1366.  
  1367. ;  Print String (terminated in 0 or MSB Set) at Return Address
  1368.  
  1369. print:
  1370.     ex    (sp),hl        ; Get address
  1371.     call    print1
  1372.     ex    (sp),hl        ; Put address
  1373.     ret
  1374.  
  1375. ;  Print String (terminated by MSB Set) pted to by HL
  1376.  
  1377. print1:
  1378.     ld    a,(hl)        ; Done?
  1379.     inc    hl        ; Pt to next
  1380.     call    conout        ; Print char
  1381.     or    a        ; Set msb flag (m)
  1382.     ret    m        ; Msb terminator
  1383.     jr    print1
  1384.  
  1385. ;-----------------------------------------------------------------------------
  1386.  
  1387. ;  Console Output Routine
  1388.  
  1389. conout:
  1390.     push    hl        ; Save regs
  1391.     push    de
  1392.     push    bc
  1393.     push    af
  1394.     and    7fh        ; Clear msb
  1395.     ld    e,a        ; Char in E
  1396.     ld    c,2        ; Output
  1397.     call    bdos
  1398.     pop    af        ; Get regs
  1399.     pop    bc
  1400.     pop    de
  1401.     pop    hl
  1402.     ret
  1403.  
  1404. ;=============================================================================
  1405. ;
  1406. ; Display current length in records
  1407. ;
  1408. prtval    macro m1,v1,m2,v2,m3
  1409.     .radix 10
  1410.     .printx    m1 v1 m2 v2 m3
  1411.     endm
  1412.  
  1413. length    equ    $ - start
  1414. recs    equ    length / 128
  1415. bytes    equ    length mod 128
  1416.  
  1417.     .printx
  1418.     prtval <FCP is now>,%recs,<records and>,%bytes,<bytes long.>
  1419.     .printx
  1420.  
  1421.     end
  1422.  
  1423. ; End of NZFCP.Z80
  1424.