home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / zsys / simtel20 / zsig / lrunz3.asm < prev    next >
Encoding:
Assembly Source File  |  1994-07-13  |  26.8 KB  |  1,230 lines

  1. TITLE    'LRUNZ  Library Run for ZCPR2 -- a utility for .LBR files'
  2. VERSION EQU    1$0    ;82-08-06 Initial source release
  3.     PAGE    60
  4. ;
  5. ; Requires MAC for assembly.  Due to the complexity of
  6. ; the relocation macros, this program may take a while
  7. ; to assemble.    Be prepared for periods of no disk activity
  8. ; on both passes before pressing panic button.    G.P.N.
  9. ;
  10.  
  11. ;--------------------------NOTICE------------------------------
  12. ;
  13. ;   (c) Copyright 1982    Gary P. Novosielski
  14. ;    All rights reserved.
  15. ;    
  16. ;   The following features courtesy of Ron Fowler:
  17. ;    1) command line reparsing and repacking (this allows
  18. ;    the former load-only program to become a load & run
  19. ;    utility).
  20. ;    2) code necessary to actually execute the loaded file
  21. ;    3) the HELP facility (LRUN with no arguments)
  22. ;    4) modified error routines to avoid warm-boot delay
  23. ;       (return to CCP directly instead)
  24. ;    
  25. ;    Permission to distribute this program in source or
  26. ;    object form without prior written aproval is granted
  27. ;    only under the following conditions.
  28. ;
  29. ;        1. No charge is imposed for the program.
  30. ;        2. Charges for incidental costs including
  31. ;           but not limited to media, postage, tele-
  32. ;           communications, and data storage do not
  33. ;           exceed those costs actually incurred.
  34. ;        3. This Notice and any copright notices in
  35. ;           the object code remain intact 
  36. ;
  37. ;            (signed)  Gary P. Novosielski
  38. ;
  39. ;--------------------------------------------------------------
  40. ;
  41. ; LRUN is intended to be used in conjunction with libraries
  42. ; created with LU.COM, a library utility based upon the
  43. ; groundwork laid by Michael Rubenstien, with some additional
  44. ; inspiration from Leor Zolman's CLIB librarian for .CRL files.
  45. ;
  46. ; The user can place the less frequently used command (.COM)
  47. ; files in a library to save space, and  still be able to run
  48. ; them when required, by typing:
  49. ;     LRUN <normal command line>.
  50. ; The name of the library can be specified, but the greatest
  51. ; utility will be achieved by placing all commands in one
  52. ; library called COMMAND.LBR, or some locally defined name,
  53. ; and always letting LRUN use that name as the default.
  54. ;
  55.  
  56. ;Syntax:
  57. ;    LRUN [-<lbrname>] <command> [<parameters>]
  58. ;
  59. ;where:
  60. ;<lbrname>    is the optional library name.  In the
  61. ;        distrubution version, this defaults to
  62. ;        COMMAND.LBR.  If the user wishes to use a
  63. ;        different name for the default, the 8-byte
  64. ;        literal at DFLTNAM below may be changed to
  65. ;        suit local requirements. The current drive
  66. ;        is searched for the .LBR file, and if not
  67. ;        found there, the A: drive is searched.
  68. ;        **Note that the leading minus sign (not a part
  69. ;        of the name) is required to indicate an
  70. ;        override library name is being entered.
  71. ;
  72. ;<command>    is the name of the .COM file in the library
  73. ;
  74. ;<line>        is the (possibly empty) set of parameters
  75. ;        which are to be passed to <command>, as in
  76. ;        normal CP/M syntax.  Notice that if the
  77. ;        library name is defaulted, the syntax is
  78. ;        simply:
  79. ;     LRUN <command line>
  80. ;        which is just the normal command line with
  81. ;        LRUN prefixed to it.
  82. ;
  83. ;Wheel Mod    If the 'CMDRUN' facility of ZCPR3 is enabled
  84.         then it is very handy to take all of your less
  85.         often used command files and place them in a
  86.         'COMMAND.LBR' and rename LRUNZ to CMDRUN.
  87.         Then whenever a command is not found by the
  88.         CCP if will run 'CMDRUN' (actually LRUNZ3) which
  89.         will look in the 'COMMAND.LBR' and run the command.
  90.         Furthermore if you enable the 'ROOTONLY' ZCPR3 option
  91.         then the CCP will automatically look at A:15 only
  92.         for 'CMDRUN' which will then look for 'COMMAND.LBR'
  93.         and run the command. This change to enable the 
  94.         Wheel Byte is almost an exact copy of PIP-ZCPR by
  95.          John D'Amico
  96.                
  97.                     Richard Cole
  98.                       
  99. ;
  100. ; MACROS TO PROVIDE Z80 EXTENSIONS
  101. ;   MACROS INCLUDE:
  102. ;
  103. $-MACRO         ;FIRST TURN OFF THE EXPANSIONS
  104. ;
  105. ;    JR    - JUMP RELATIVE
  106. ;    JRC    - JUMP RELATIVE IF CARRY
  107. ;    JRNC    - JUMP RELATIVE IF NO CARRY
  108. ;    JRZ    - JUMP RELATIVE IF ZERO
  109. ;    JRNZ    - JUMP RELATIVE IF NO ZERO
  110. ;    DJNZ    - DECREMENT B AND JUMP RELATIVE IF NO ZERO
  111. ;    LDIR    - MOV @HL TO @DE FOR COUNT IN BC
  112. ;    LXXD    - LOAD DOUBLE REG DIRECT
  113. ;    SXXD    - STORE DOUBLE REG DIRECT
  114. ;
  115. ;
  116. ;
  117. ;    @GENDD MACRO USED FOR CHECKING AND GENERATING
  118. ;    8-BIT JUMP RELATIVE DISPLACEMENTS
  119. ;
  120. @GENDD    MACRO    ?DD    ;;USED FOR CHECKING RANGE OF 8-BIT DISPLACEMENTS
  121.     IF (?DD GT 7FH) AND (?DD LT 0FF80H)
  122.     DB    100H    ;Displacement Range Error on Jump Relative
  123.     ELSE
  124.     DB    ?DD
  125.     ENDIF
  126.     ENDM
  127. ;
  128. ;
  129. ; Z80 MACRO EXTENSIONS
  130. ;
  131. JR    MACRO    ?N    ;;JUMP RELATIVE
  132.     DB    18H
  133.     @GENDD    ?N-$-1
  134.     ENDM
  135. ;
  136. JRC    MACRO    ?N    ;;JUMP RELATIVE ON CARRY
  137.     DB    38H
  138.     @GENDD    ?N-$-1
  139.     ENDM
  140. ;
  141. JRNC    MACRO    ?N    ;;JUMP RELATIVE ON NO CARRY
  142.     DB    30H
  143.     @GENDD    ?N-$-1
  144.     ENDM
  145. ;
  146. JRZ    MACRO    ?N    ;;JUMP RELATIVE ON ZERO
  147.     DB    28H
  148.     @GENDD    ?N-$-1
  149.     ENDM
  150. ;
  151. JRNZ    MACRO    ?N    ;;JUMP RELATIVE ON NO ZERO
  152.     DB    20H
  153.     @GENDD    ?N-$-1
  154.     ENDM
  155. ;
  156. DJNZ    MACRO    ?N    ;;DECREMENT B AND JUMP RELATIVE ON NO ZERO
  157.     DB    10H
  158.     @GENDD    ?N-$-1
  159.     ENDM
  160. ;
  161. LDIR    MACRO        ;;LDIR
  162.     DB    0EDH,0B0H
  163.     ENDM
  164. ;
  165. LDED    MACRO    ?N    ;;LOAD DE DIRECT
  166.     DB    0EDH,05BH
  167.     DW    ?N
  168.     ENDM
  169. ;
  170. LBCD    MACRO    ?N    ;;LOAD BC DIRECT
  171.     DB    0EDH,4BH
  172.     DW    ?N
  173.     ENDM
  174. ;
  175. SDED    MACRO    ?N    ;;STORE DE DIRECT
  176.     DB    0EDH,53H
  177.     DW    ?N
  178.     ENDM
  179. ;
  180. SBCD    MACRO    ?N    ;;STORE BC DIRECT
  181.     DB    0EDH,43H
  182.     DW    ?N
  183.     ENDM
  184. ;
  185. ; END OF Z80 MACRO EXTENSIONS
  186. ;
  187.  
  188. @SYS    SET    0
  189. @KEY    SET    1
  190. @CON    SET    2
  191. @RDR    SET    3
  192. @PUN    SET    4
  193. @LST    SET    5
  194. @DIO    SET    6
  195. @RIO    SET    7
  196. @SIO    SET    8
  197. @MSG    SET    9
  198. @INP    SET    10
  199. @RDY    SET    11
  200. @VER    SET    12
  201. @LOG    SET    13
  202. @DSK    SET    14
  203. @OPN    SET    15
  204. @CLS    SET    16
  205. @DIR    SET    17
  206. @NXT    SET    18
  207. @DEL    SET    19
  208. @FRD    SET    20
  209. @FWR    SET    21
  210. @MAK    SET    22
  211. @REN    SET    23
  212. @CUR    SET    25
  213. @DMA    SET    26
  214. @CHG    SET    30
  215. @USR    SET    32
  216. @RRD    SET    33
  217. @RWR    SET    34
  218. @SIZ    SET    35
  219. @REC    SET    36
  220. @LOGV    SET    37    ;2.2 only
  221. @RWR0    SET    40    ;2.2 only
  222. ;
  223. CPMBASE EQU    0
  224. BOOT    SET    CPMBASE
  225. BDOS    SET    BOOT+5
  226. TFCB    EQU    BOOT+5CH
  227. TFCB1    EQU    TFCB
  228. TFCB2    EQU    TFCB+16
  229. TBUFF    EQU    BOOT+80H
  230. TPA    EQU    BOOT+100H
  231. CTRL    EQU    ' '-1        ;Ctrl char mask
  232. CR    SET    CTRL AND 'M'
  233. LF    SET    CTRL AND 'J'
  234. TAB    SET    CTRL AND 'I'
  235. FF    SET    CTRL AND 'L'
  236. BS    SET    CTRL AND 'H'
  237. FALSE    SET    0
  238. TRUE    SET    NOT FALSE
  239. ;
  240. CPM    MACRO    FUNC,OPERAND,CONDTN
  241.     LOCAL    PAST
  242.     IF    NOT NUL CONDTN
  243.     DB    ( J&CONDTN ) XOR 8
  244.     DW    PAST
  245.     ENDIF        ;;of not nul condtn
  246.     IF    NOT NUL OPERAND
  247.     LXI    D,OPERAND
  248.     ENDIF        ;;of not nul operand
  249.     IF    NOT NUL FUNC
  250.     MVI    C,@&FUNC
  251.     ENDIF
  252.     CALL    BDOS
  253. PAST:
  254.     ENDM
  255. ;
  256. BLKMOV    MACRO    DEST,SRCE,LEN,COND
  257.     LOCAL    PAST
  258.     JMP    PAST
  259. @BMVSBR:
  260.     MOV    A,B
  261.     ORA    C
  262.     RZ
  263.     DCX    B
  264.     MOV    A,M
  265.     INX    H
  266.     STAX    D
  267.     INX    D
  268.     JMP    @BMVSBR
  269. BLKMOV    MACRO    DST,SRC,LN,CC
  270.     LOCAL    PST
  271.     IF    NOT NUL CC
  272.     DB    ( J&CC ) XOR 8
  273.     DW    PST
  274.     ENDIF
  275.     IF    NOT NUL DST
  276.     LXI    D,DST
  277.     ENDIF
  278.     IF    NOT NUL SRC
  279.     LXI    H,SRC
  280.     ENDIF
  281.     IF    NOT NUL LN
  282.     LXI    B,LN
  283.     ENDIF
  284.     CALL    @BMVSBR
  285.     IF    NOT NUL CC
  286. PST:
  287.     ENDIF
  288.     ENDM
  289. PAST:    BLKMOV    DEST,SRCE,LEN,COND
  290.     ENDM
  291.  
  292. ;
  293. OVERLAY SET    0
  294. ; Macro Definitions
  295. ;
  296. RTAG    MACRO    LBL
  297. ??R&LBL EQU    $+2-@BASE
  298.     ENDM
  299. ;
  300. RGRND    MACRO    LBL
  301. ??R&LBL EQU    0FFFFH
  302.     ENDM
  303. ;
  304. R    MACRO    INST
  305. @RLBL    SET    @RLBL+1
  306.     RTAG    %@RLBL
  307.     INST-@BASE
  308.     ENDM
  309. ;
  310. NXTRLD    MACRO    NN
  311. @RLD    SET    ??R&NN
  312. @NXTRLD SET    @NXTRLD + 1
  313.     ENDM
  314. ;
  315. ;
  316. ; Enter here from Console Command Processor (CCP)
  317. ;
  318.     ORG    TPA
  319. CCPIN:
  320. ;
  321. ;  Branch to Start of Program
  322. ;
  323.     jmp    start
  324.  
  325. ;
  326. ;******************************************************************
  327. ;
  328. ;  SINSFORM -- ZCPR2 Utility Standard General Purpose Initialization Format
  329. ;
  330. ;    This data block precisely defines the data format for
  331. ; initial features of a ZCPR2 system which are required for proper
  332. ; initialization of the ZCPR2-Specific Routines in SYSLIB.
  333. ;
  334.  
  335. ;
  336. ;  EXTERNAL PATH DATA
  337. ;
  338. EPAVAIL:
  339.     DB    0FFH    ; IS EXTERNAL PATH AVAILABLE? (0=NO, 0FFH=YES)
  340. EPADR:
  341.     DW    40H    ; ADDRESS OF EXTERNAL PATH IF AVAILABLE
  342.  
  343. ;
  344. ;  INTERNAL PATH DATA
  345. ;
  346. INTPATH:
  347.     DB    0,0    ; DISK, USER FOR FIRST PATH ELEMENT
  348.             ; DISK = 1 FOR A, '$' FOR CURRENT
  349.             ; USER = NUMBER, '$' FOR CURRENT
  350.     DB    0,0
  351.     DB    0,0
  352.     DB    0,0
  353.     DB    0,0
  354.     DB    0,0
  355.     DB    0,0
  356.     DB    0,0    ; DISK, USER FOR 8TH PATH ELEMENT
  357.     DB    0    ; END OF PATH
  358.  
  359. ;
  360. ;  MULTIPLE COMMAND LINE BUFFER DATA
  361. ;
  362. MCAVAIL:
  363.     DB    0FFH    ; IS MULTIPLE COMMAND LINE BUFFER AVAILABLE?
  364. MCADR:
  365.     DW    0F900H    ; ADDRESS OF MULTIPLE COMMAND LINE BUFFER IF AVAILABLE
  366.  
  367. ;
  368. ;  DISK/USER LIMITS
  369. ;
  370. MDISK:
  371.     DB    4    ; MAXIMUM NUMBER OF DISKS
  372. MUSER:
  373.     DB    15    ; MAXIMUM USER NUMBER
  374.  
  375. ;
  376. ;  FLAGS TO PERMIT LOG IN FOR DIFFERENT USER AREA OR DISK
  377. ;
  378. DOK:
  379.     DB    0FFH    ; ALLOW DISK CHANGE? (0=NO, 0FFH=YES)
  380. UOK:
  381.     DB    0FFH    ; ALLOW USER CHANGE? (0=NO, 0FFH=YES)
  382.  
  383. ;
  384. ;  PRIVILEGED USER DATA
  385. ;
  386. PUSER:
  387.     DB    15    ; BEGINNING OF PRIVILEGED USER AREAS
  388. PPASS:
  389.     DB    'SYSTEM',0    ; PASSWORD FOR MOVING INTO PRIV USER AREAS
  390.     DS    41-($-PPASS)    ; 40 CHARS MAX IN BUFFER + 1 for ending NULL
  391.  
  392. ;
  393. ;  CURRENT USER/DISK INDICATOR
  394. ;
  395. CINDIC:
  396.     DB    '$'    ; USUAL VALUE (FOR PATH EXPRESSIONS)
  397.  
  398. ;
  399. ;  DMA ADDRESS FOR DISK TRANSFERS
  400. ;
  401. DMADR:
  402.     DW    80H    ; TBUFF AREA
  403.  
  404. ;
  405. ;  NAMED DIRECTORY INFORMATION
  406. ;
  407. NDRADR:
  408.     DW    0F800H    ; ADDRESS OF MEMORY-RESIDENT NAMED DIRECTORY
  409. NDNAMES:
  410.     DB    14    ; MAX NUMBER OF DIRECTORY NAMES
  411. DNFILE:
  412.     DB    'SYS     '    ; NAME OF DISK NAME FILE
  413.     DB    'NDR'        ; TYPE OF DISK NAME FILE
  414.  
  415. ;
  416. ;  REQUIREMENTS FLAGS
  417. ;
  418. EPREQD:
  419.     DB    0FFH    ; EXTERNAL PATH?
  420. MCREQD:
  421.     DB    0FFH    ; MULTIPLE COMMAND LINE?
  422. MXREQD:
  423.     DB    000H    ; MAX USER/DISK?
  424. UDREQD:
  425.     DB    0FFH    ; ALLOW USER/DISK CHANGE?
  426. PUREQD:
  427.     DB    000H    ; PRIVILEGED USER?
  428. CDREQD:
  429.     DB    0FFH    ; CURRENT INDIC AND DMA?
  430. NDREQD:
  431.     DB    0FFH    ; NAMED DIRECTORIES?
  432. Z3CLASS:
  433.     DB    5    ; CLASS 5
  434.     DB    'ZCPR3'
  435.     DS    10    ; RESERVED
  436. ;
  437. WHEEL    EQU    04BH    ;ZCPR3 WHEEL BYTE LOCATION
  438.  
  439.  
  440. ;
  441. ;  END OF SINSFORM -- STANDARD DEFAULT PARAMETER DATA
  442. ;
  443. ;******************************************************************
  444. ;
  445. DFLTNAM:
  446.     DB    'COMMAND ' ; <---change this if you like---
  447. LBRLIT:
  448.     DB    'LBR'
  449. ;
  450. SIGNON:
  451.     DB    'LRUNZ  Version '    ;Signon message
  452.     DB    VERSION/10+'0'
  453.     DB    '.'
  454.     DB    VERSION MOD 10+'0'
  455.     DB    CR,LF
  456.     DB    '$',CTRL AND 'Z'
  457.     DB    ' Copyright (c) 1982  Gary P. Novosielski '
  458.     DB    CR,LF
  459.     DB    ' Modified for Use Under ZCPR2 by Richard Conn'
  460.     DB    '$',CTRL AND 'Z'
  461. ;
  462. ;
  463. ;  START OF PROGRAM
  464. ;
  465. START: 
  466.     LDA    WHEEL        ;load wheel byte
  467.     MVI    E,9
  468.     CMP    E        ;binary subtract
  469.     JC    MSGA        ;jump to abort message if carry flag set
  470.     JMP    START1        ;jump to lrunz if not aborted
  471. MSG:    
  472.     DB    'Wheel Byte Not Set ==> Aborting $'
  473. MSGA:    
  474.     MVI    C,09H        ;bdos print function
  475.     LXI    D,MSG        ;pointer to abort message
  476.     CALL    05H        ;do it
  477.     JMP    0000H        ;warm boot if aborted
  478. START1:         
  479.     LXI    H,0        ;get the CCP entry stackpointer
  480.     DAD    SP        ;(used only if HELP request
  481.     SHLD    SPSAVE        ; is encountered)
  482.     CPM    MSG,SIGNON;    ;Display signon
  483.     CALL    SETUP        ;initialize.
  484.     LHLD    BDOS+1        ;find top of memory
  485.     MOV    A,H        ;page address
  486.                 ;Form destination...
  487.     SUI    PAGES         ;...address in
  488.     MOV    D,A        ;DE pair.
  489.     MVI    E,0
  490.     PUSH    D        ;save on stack
  491. ;
  492.     BLKMOV    ,@BASE,SEGLEN    ;Move the active segment.
  493. ;
  494. ;The segment is now moved to high memory, but not
  495. ;properly relocated.  The bit table which specifies
  496. ;which addresses need to be adjusted is located
  497. ;just after the last byte of the source segment,
  498. ;so (HL) is now pointing at it.
  499.     POP    D    ;beginning of newly moved code.
  500.     LXI    B,SEGLEN;length of segment
  501.     PUSH    H    ;save pointer to reloc info
  502.     MOV    H,D    ;offset page address
  503. ;
  504. ;Scan through the newly moved code, and adjust any
  505. ;page addresses by adding (H) to them.    The word on
  506. ;top of the stack points to the next byte of the
  507. ;relocation bit table.    Each bit in the table
  508. ;corresponds to one byte in the destination code.
  509. ;A value of 1 indicates the byte is to be adjusted.
  510. ;A value of 0 indicates the byte is to be unchanged.
  511. ;
  512. ;Thus one byte of relocation information serves to
  513. ;mark 8 bytes of object code.  The bits which have
  514. ;not been used yet are saved in L until all 8
  515. ;are used.
  516. ;
  517. FIXLOOP:
  518.     MOV    A,B
  519.     ORA    C        ;test if finished
  520.     JRZ    FIXDONE
  521.     DCX    B        ;count down
  522.     MOV    A,E
  523.     ANI    07H        ;on 8-byte boundry?
  524.     JRNZ    NEXTBIT
  525. ;
  526. NEXTBYT:
  527. ;Get another byte of relocation bits
  528.     XTHL
  529.     MOV    A,M
  530.     INX    H
  531.     XTHL
  532.     MOV    L,A        ;save in register L
  533. ;
  534. NEXTBIT:
  535.     MOV    A,L        ;remaining bits from L
  536.     RAL            ;next bit to CARRY
  537.     MOV    L,A        ;save the rest
  538.     JRNC    NEXTADR
  539. ;
  540. ;CARRY was = 1.  Fix this byte.
  541.     LDAX    D
  542.     ADD    H        ;(H) is the page offset
  543.     STAX    D
  544. ;
  545. NEXTADR:
  546.     INX    D
  547.     JR    FIXLOOP
  548. ;
  549. ;Finished.  Jump to the first address in the new
  550. ;segment in high memory.
  551. ;
  552. ;First adjust the stack.  One garbage word was
  553. ;left by fixloop.
  554. ;
  555. FIXDONE:
  556.     INX    SP
  557.     INX    SP
  558. ;
  559. ;(HL) still has the page address
  560. ;
  561.     MOV    L,A    ;move zero to l
  562. ;
  563. ;  Set User/Disk for Return
  564. ;
  565.     LDA    CDISK    ;Set Disk
  566.     MOV    B,A
  567.     LDA    CUSER    ;Set User
  568.     MOV    C,A
  569.     PCHL        ;Stack is valid
  570. ;
  571. ;Any one-shot initialization code goes here.
  572. ;
  573. SETUP:
  574.     LXI    H,NOLOAD
  575.     SHLD    CCPIN+1     ;Prevent reentry
  576. ;
  577.     CALL    REPARS        ;Re-parse command line
  578. ;
  579.     LXI    D,MEMBER+9    ;Check member filetype
  580.     LDAX    D
  581.     CPI    ' '        ;If blank,
  582.     BLKMOV    ,COMLIT,3,Z    ; default to COM.
  583. ;
  584.     LXI    D,LBRFIL+9    ;Check library filetype
  585.     LDAX    D
  586.     CPI    ' '        ;If blank,
  587.     BLKMOV    ,LBRLIT,3,Z    ; default to LBR
  588. ;
  589.     LXI    D,LBRFIL+1    ;Check name
  590.     LDAX    D
  591.     CPI    ' '        ;If blank,
  592.     BLKMOV    ,DFLTNAM,8,Z    ; use default name.
  593. ;
  594. ;  Set Current Disk and User and then Search Along ZCPR2 Path for
  595. ;    the Library File
  596. ;
  597.     CPM    CUR        ;Get Current Disk
  598.     STA    CDISK        ;Save It
  599.     CPM    USR,0FFH    ;Get Current User
  600.     STA    CUSER        ;Save It
  601.     CPM    OPN,LBRFIL    ;Try to Open Library File Now
  602.     INR    A        ;Zero Means Not Found
  603.     JRNZ    DIROK        ;Process if Found
  604.     XRA    A        ;Set to Select Current Disk
  605.     STA    LBRFIL
  606.     LXI    H,INTPATH    ;Point to Internal Path
  607.     LDA    EPAVAIL        ;External Path Available?
  608.     ORA    A        ;Zero = No
  609.     JRZ    INPATH
  610.     LHLD    EPADR        ;Get Address of External Path
  611. INPATH:
  612.     MOV    A,M        ;Get Drive
  613.     ORA    A        ;0=Command Not Found
  614.     JZ    NODIR        ;Not Found
  615.     ANI    7FH        ;Mask MSB
  616.     MOV    B,A        ;Save in B for a While
  617.     LDA    CINDIC        ;Get Current Indicator
  618.     CMP    B        ;Compare for Current
  619.     JRNZ    INPATH1        ;Good Disk In B
  620.     LDA    CDISK        ;Get Current Disk
  621.     INR    A        ;Add 1 to be good
  622.     MOV    B,A        ;Disk In B
  623. INPATH1:
  624.     DCR    B        ;Disk in Range 0-15
  625.     INX    H        ;Pt to User Number
  626.     MOV    A,M        ;Get User Number
  627.     INX    H        ;Pt to Next Disk
  628.     PUSH    H        ;Save Ptr
  629.     ANI    7FH        ;Mask User Number
  630.     MOV    C,A        ;User in C for now
  631.     LDA    CINDIC        ;Compare to Current Indicator
  632.     CMP    C        ;See if Current User
  633.     JRNZ    INPATH2        ;Good User In C
  634.     LDA    CUSER        ;User Current User
  635.     MOV    C,A        ;User in C
  636. INPATH2:
  637.     MOV    E,B        ;Select Disk
  638.     PUSH    B        ;Save User in C
  639.     CPM    DSK        ;Set Disk
  640.     POP    D        ;Get User in E
  641.     CPM    USR        ;Set User
  642.     CPM    DIR,LBRFIL    ;See if File Exists in this Directory
  643.     POP    H        ;Restore Path Pointer
  644.     INR    A        ;Error Code (Not Found) is Zero
  645.     JRZ    INPATH        ;Continue Thru Path
  646. DIROPN:
  647.     CPM    OPN,LBRFIL    ;Open for directory read.
  648. DIROK:
  649.     CPM    DMA,TBUFF    ;Set DMA for Block Read
  650. FINDMBR:
  651.     CPM    FRD,LBRFIL    ;Read the directory
  652.     ORA    A
  653.     JNZ    FISHY        ;Empty file, Give up.
  654.     LXI    H,TBUFF
  655.     MOV    A,M
  656.     ORA    A
  657.     JNZ    FISHY        ;Directory not active??
  658.     MVI    B,8+3        ;Check for blanks
  659.     MVI    A,' '
  660. VALIDLOOP:
  661.     INX    H
  662.     CMP    M
  663.     JNZ    FISHY
  664.     DCR    B
  665.     JRNZ    VALIDLOOP
  666. ;
  667.     LHLD    TBUFF+1+8+3    ;Index must be 0000
  668.     MOV    A,H
  669.     ORA    L
  670.     JNZ    FISHY
  671. ;
  672.     LHLD    TBUFF+1+8+3+2    ;Get directory size
  673.     DCX    H        ;We already read one.
  674.     PUSH    H        ;Save on stack
  675.     JR    FINDMBRN    ;Jump into loop
  676. FINDMBRL:
  677.     POP    H        ;Read sector count from TOS
  678.     MOV    A,H
  679.     ORA    L        ;0 ?
  680.     JZ    NOMEMB        ;Member not found in library
  681.     DCX    H        ;Count down
  682.     PUSH    H        ;and put it back.
  683.     CPM    FRD,LBRFIL    ;Get next directory sector
  684.     ORA    A
  685.     JNZ    FISHY
  686.  
  687.  
  688. FINDMBRN:
  689.     LXI    H,TBUFF       ;Point to buffer.
  690.     MVI    C,128/32    ;Number of directory entries
  691. ;
  692. FINDMBR1:
  693.     CALL    COMPARE     ;Check if found yet.
  694.     JZ    GETLOC        ;Found member in .DIR
  695.     DCR    C
  696.     JRZ    FINDMBRL
  697. ;
  698.     LXI    D,32        ;No match, point to next one.
  699.     DAD    D
  700.     JR    FINDMBR1
  701. ;
  702. GETLOC:     ;The name was found now get index and length
  703.     POP    B    ;Clear stack garbage
  704.     XCHG        ;Pointer to sector address.
  705.     MOV    E,M    ;Get First
  706.     INX    H
  707.     MOV    D,M
  708.     XCHG
  709.     SHLD    INDEX    ;Save it
  710.     XCHG
  711.     INX    H    ;Get Size to DE
  712.     MOV    E,M
  713.     INX    H
  714.     MOV    D,M
  715.     XCHG        ; Size to HL
  716.     SHLD    LENX
  717.     CALL    PACKUP    ;Repack command line arguments
  718.     CPM    CON,CR    ;do <cr> only (look like CCP)
  719.     RET
  720. ;        End of setup.
  721. ;
  722. ;    Utility subroutines
  723. NEGDE:            ;DE = -DE
  724.     MOV    A,D
  725.     CMA
  726.     MOV    D,A
  727. ;
  728.     MOV    A,E
  729.     CMA
  730.     MOV    E,A
  731.     INX    D
  732.     RET
  733. ;
  734. ;    REPARSE re-parses the fcbs from the command line,
  735. ;    to allow the "-" character to prefix the library name
  736. ;
  737. REPARS:
  738.     LXI    D,MEMBER    ;first reinitialize both fcbs
  739.     CALL    NITF
  740.     LXI    D,LBRFIL
  741.     CALL    NITF
  742.     LXI    H,TBUFF     ;store a null at the end of
  743.     MOV    E,M        ; the command line (this is
  744.     MVI    D,0        ; done by CP/M usually, except
  745.     XCHG            ; in the case of a full com-
  746.     DAD    D        ; mand line
  747.     INX    H
  748.     MVI    M,0
  749.     XCHG            ;tbuff pointer back in hl
  750. SCANBK:
  751.     INX    H        ;bump to next char position
  752.     MOV    A,M        ;fetch next char
  753.     ORA    A        ;reached a null? (no arguments)
  754.     JZ    HELP        ;interpret as a call for help
  755.     CPI    ' '        ;not null, skip blanks
  756.     JRZ    SCANBK
  757.     CPI    '-'        ;library name specifier?
  758.     JRNZ    NOTLBR        ;skip if not
  759.     INX    H        ;it is, skip over flag character
  760.     LXI    D,LBRFIL    ;parse library name into FCB
  761.     CALL    GETFN
  762. NOTLBR:
  763.     LXI    D,MEMBER    ;now parse the command name
  764.     CALL    GETFN
  765.     LXI    D,HOLD+1    ;pnt to temp storage for rest of cmd line
  766.     MVI    B,-1        ;init a counter
  767. CLSAVE:
  768.     INR    B        ;bump up counter
  769.     MOV    A,M        ;fetch a char
  770.     STAX    D        ;move it to hold area
  771.     INX    H        ;bump pointers
  772.     INX    D
  773.     ORA    A        ;test whether char was a terminator
  774.     JRNZ    CLSAVE        ;continue moving line if not
  775.     MOV    A,B        ;it was, get count
  776.     STA    HOLD        ;save it in hold area
  777.     RET
  778. ;
  779. ;    PACKUP retrieves the command line stored at
  780. ;    HOLD and moves it back to tbuff, then reparses
  781. ;    the default file control blocks so the command
  782. ;    will never know it was run from a library
  783. ;
  784. PACKUP:
  785.     LXI    H,HOLD        ;point to length byte of HOLD
  786.     MOV    C,M        ;get length in BC
  787.     MVI    B,0
  788.     INX    B        ;bump up to because length byte doesn't
  789.     INX    B        ;  include itself or null terminator
  790.     BLKMOV    TBUFF        ;moving everybody to Tbuff
  791.     LXI    H,TBUFF+1    ;point to the command tail
  792.     LXI    D,TFCB1     ;first parse out tfcb1
  793.     CALL    GETFN
  794.     LXI    D,TFCB2     ;then tfcb2
  795.     CALL    GETFN
  796.     RET
  797. ;
  798. ;    Here when HELP is requested (indicated
  799. ;    by LRUN with no arguments)
  800. ;
  801. HELP:
  802.     CPM    MSG,HLPMSG    ;print the HELP message
  803. EXIT:
  804.     LHLD    SPSAVE        ;find CCP re-entry adrs
  805.     SPHL            ;fix & return
  806.     RET
  807. ;
  808. ;    the HELP message
  809. ;
  810. HLPMSG:
  811.     DB    CR,LF,'Correct syntax is:'
  812.     DB    CR,LF
  813.     DB    LF,TAB,'LRUN [-<lbrname>] <command line>'
  814.     DB    CR,LF
  815.     DB    LF,'Where <lbrname> is the optional library name'
  816.     DB    CR,LF,'(Note the preceding "-".  ) If omitted,'
  817.     DB    CR,LF,'the default command library is used.'
  818.     DB    LF
  819.     DB    CR,LF,'<command line> is the name and parameters'
  820.     DB    CR,LF,'of the command being run from the library,'
  821.     DB    CR,LF,'just as if a separate .COM file were being run.'
  822.     DB    CR,LF,'$'
  823. ;
  824. ;
  825. COMPARE:        ;Test status, name and type of
  826.     PUSH    H        ;a directory entry.
  827.     MVI    B,1+8+3
  828.     XCHG            ;with the one we're
  829.     LXI    H,MEMBER    ;looking for.
  830. COMPAR1:
  831.     LDAX    D
  832.     CMP    M
  833.     JRNZ    COMPEXIT
  834.     INX    D
  835.     INX    H
  836.     DCR    B
  837.     JRNZ    COMPAR1
  838. COMPEXIT:            ;Return with DE pointing to
  839.     POP    H        ;last match + 1, and HL still
  840.     RET            ;pointing to beginning.
  841. ;
  842. ;
  843. ;    File name parsing subroutines
  844. ;
  845. ; getfn gets a file name from text pointed to by reg hl into
  846. ; an fcb pointed to by reg de.    leading delimeters are 
  847. ; ignored.
  848. ; entry hl    first character to be scanned
  849. ;    de    first byte of fcb
  850. ; exit    hl    character following file name
  851. ;
  852. ;
  853. ;
  854. GETFN:
  855.     CALL    NITF    ;init 1st half of fcb
  856.     CALL    GSTART    ;scan to first character of name
  857.     RZ        ;end of line was found - leave fcb blank
  858.     CALL    GETDRV    ;get drive spec. if present
  859.     CALL    GETPS    ;get primary and secondary name
  860.     RET
  861.  
  862.  
  863. ;
  864. ; nitf fills the fcb with dflt info - 0 in drive field
  865. ; all-blank in name field, and 0 in ex,s1,s2 and rc flds
  866. ;
  867. NITF:
  868.     PUSH    D    ;save fcb loc
  869.     XCHG        ;move it to hl
  870.     MVI    M,0    ;zap dr field
  871.     INX    H    ;bump to name field
  872.     MVI    B,11    ;zap all of name fld
  873. NITLP1:
  874.     MVI    M,' '
  875.     INX    H
  876.     DJNZ    NITLP1
  877.     MVI    B,4    ;zero others
  878. NITLP2:
  879.     MVI    M,0
  880.     INX    H
  881.     DJNZ    NITLP2
  882.     XCHG        ;restore hl
  883.     POP    D    ;restore fcb pointer
  884.     RET
  885. ;
  886. ; gstart advances the text pointer (reg hl) to the first
  887. ; non delimiter character (i.e. ignores blanks).  returns a
  888. ; flag if end of line (00h or ';') is found while scaning.
  889. ; exit    hl    pointing to first non delimiter
  890. ;    a    clobbered
  891. ;    zero    set if end of line was found
  892. ;
  893. GSTART:
  894.     CALL    GETCH    ;see if pointing to delim?
  895.     RNZ        ;nope - return
  896.     CPI    ';'    ;end of line?
  897.     RZ        ;yup - return w/flag
  898.     ORA    A
  899.     RZ        ;yup - return w/flag
  900.     INX    H    ;nope - move over it
  901.     JR    GSTART    ;and try next char
  902. ;
  903. ; getdrv checks for the presence of a drive spec at the text
  904. ; pointer, and if present formats it into the fcb and
  905. ; advances the text pointer over it.
  906. ; entry hl    text pointer
  907. ;    de    pointer to first byte of fcb
  908. ; exit    hl    possibly updated text pointer
  909. ;    de    pointer to second (primary name) byte of fcb
  910. ;
  911. GETDRV:
  912.     INX    D    ;point to name if spec not found
  913.     INX    H    ;look ahead to see if ':' present
  914.     MOV    A,M
  915.     DCX    H    ;put back in case not present
  916.     CPI    ':'    ;is a drive spec present?
  917.     RNZ        ;nope - return
  918.     MOV    A,M    ;yup - get the ascii drive name
  919.     SUI    'A'-1    ;convert to fcb drive spec
  920.     DCX    D    ;point back to drive spec byte
  921.     STAX    D    ;store spec into fcb
  922.     INX    D    ;point back to name
  923.     INX    H    ;skip over drive name
  924.     INX    H    ;and over ':'
  925.     RET
  926. ;
  927. ; getps gets the primary and secondary names into the fcb.
  928. ; entry hl    text pointer
  929. ; exit    hl    character following secondary name (if present)
  930. ;
  931. GETPS:
  932.     MVI    C,8    ;max length of primary name
  933.     CALL    GETNAM    ;pack primary name into fcb
  934.     MOV    A,M    ;see if terminated by a period
  935.     CPI    '.'
  936.     RNZ        ;nope - secondary name not given
  937.             ;return default (blanks)
  938.     INX    H    ;yup - move text pointer over period
  939. FTPOINT:
  940.     MOV    A,C    ;yup - update fcb pointer to secondary
  941.     ORA    A
  942.     JRZ    GETFT
  943.     INX    D
  944.     DCR    C
  945.     JR    FTPOINT
  946. GETFT:
  947.     MVI    C,3    ;max length of secondary name
  948.     CALL    GETNAM    ;pack secondary name into fcb
  949.     RET
  950. ;
  951. ; getnam copies a name from the text pointer into the fcb for
  952. ; a given maximum length or until a delimiter is found, which
  953. ; ever occurs first.  if more than the maximum number of
  954. ; characters is present, characters are ignored until a
  955. ; a delimiter is found.
  956. ; entry hl    first character of name to be scaned
  957. ;    de    pointer into fcb name field
  958. ;    c    maximum length
  959. ; exit    hl    pointing to terminating delimiter
  960. ;    de    next empty byte in fcb name field
  961. ;    c    max length - number of characters transfered
  962. ;
  963. GETNAM:
  964.     CALL    GETCH    ;are we pointing to a delimiter yet?
  965.     RZ        ;if so, name is transfered
  966.     INX    H    ;if not, move over character
  967.     CPI    '*'    ;ambigious file reference?
  968.     JRZ    AMBIG    ;if so, fill the rest of field with '?'
  969.     STAX    D    ;if not, just copy into name field
  970.     INX    D    ;increment name field pointer
  971.     DCR    C    ;if name field full?
  972.     JRNZ    GETNAM    ;nope - keep filling
  973.     JR    GETDEL    ;yup - ignore until delimiter
  974. AMBIG:
  975.     MVI    A,'?'    ;fill character for wild card match
  976. QFILL:
  977.     STAX    D    ;fill until field is full
  978.     INX    D
  979.     DCR    C
  980.     JRNZ    QFILL    ;fall thru to ingore rest of name
  981. GETDEL:
  982.     CALL    GETCH    ;pointing to a delimiter?
  983.     RZ        ;yup - all done
  984.     INX    H    ;nope - ignore antoher one
  985.     JR    GETDEL
  986. ;
  987. ; getch gets the character pointed to by the text pointer
  988. ; and sets the zero flag if it is a delimiter.
  989. ; entry hl    text pointer
  990. ; exit    hl    preserved
  991. ;    a    character at text pointer
  992. ;    z    set if a delimiter
  993. ;
  994. GETCH:
  995.     MOV    A,M    ;get the character
  996.     CPI    '.'
  997.     RZ
  998.     CPI    ','
  999.     RZ      
  1000.     CPI    ';'
  1001.     RZ
  1002.     CPI    ' '
  1003.     RZ
  1004.     CPI    ':'
  1005.     RZ
  1006.     CPI    '='
  1007.     RZ
  1008.     CPI    '<'
  1009.     RZ
  1010.     CPI    '>'
  1011.     RZ
  1012.     ORA    A    ;Set zero flag on end of text
  1013.     RET
  1014. ;
  1015. ;
  1016. ; Error routines:
  1017. ;
  1018. NODIR:
  1019.     CALL    ABEND
  1020.     DB    'Library not found'
  1021.     DB    '$'
  1022. FISHY:
  1023.     CALL    ABEND
  1024.     DB    'Name after "-" isn''t a library'
  1025.     DB    '$'
  1026. NOMEMB:
  1027.     LXI    H,MEMBER+1    ;Pt to first char of Command Name
  1028.     MVI    B,8        ;Print 8 Chars
  1029. NOMEMBL:
  1030.     MOV    E,M        ;Print Char
  1031.     INX    H        ;Pt to Next
  1032.     PUSH    H        ;Save Ptr and Count
  1033.     PUSH    B
  1034.     CPM    CON
  1035.     POP    B
  1036.     POP    H
  1037.     DJNZ    NOMEMBL
  1038.     CALL    ABEND1        ;No Initial New Line
  1039.     DB    ' -- Command not in directory'
  1040.     DB    '$'
  1041. NOLOAD:
  1042.     CALL    ABEND
  1043.     DB    'No program in memory'
  1044.     DB    '$'
  1045. NOFIT:
  1046.     POP    B    ;Clear Stack
  1047.     CALL    ABEND
  1048.     DB    'Program too large to load'
  1049.     DB    '$'
  1050. ;
  1051. COMLIT:
  1052.     DB    'COM'
  1053. ;
  1054. ABEND:
  1055.     CPM    MSG,NEWLIN
  1056. ABEND1:
  1057.     POP    D
  1058.     CPM    MSG
  1059.     CPM    DEL,SUBFILE
  1060.     CPM    MSG,ABTMSG
  1061.     JMP    EXIT
  1062. ABTMSG:
  1063.     DB    ' -- Aborting$'
  1064. NEWLIN:
  1065.     DB    CR,LF,'$'
  1066. CDISK:
  1067.     DS    1    ;CURRENT DISK BUFFER
  1068. CUSER:
  1069.     DS    1    ;CURRENT USER BUFFER
  1070. SPSAVE:
  1071.     DS    2        ;stack pointer save
  1072. ;
  1073.     PAGE
  1074. ;Adjust location counter to next 256-byte boundry
  1075. @BASE    ORG    ($ + 0FFH) AND 0FF00H
  1076. @RLBL    SET    0
  1077. ;
  1078. ; The segment to be relocated goes here.
  1079. ; Any position dependent (3-byte) instructions
  1080. ; are handled by the "R" macro.
  1081. ;*************************************************
  1082. ;
  1083.     PUSH    B    ;Save Original User/Disk
  1084.  R    <LHLD    LENX>    ;Get length of .COM member to load.
  1085.     MVI    A,TPA/128
  1086.     ADD    L    ;Calculate highest address
  1087.     MOV    L,A    ;To see if it will fit in
  1088.     ADC    H    ;available memory
  1089.     SUB    L
  1090.     MOV    H,A
  1091.     REPT    7
  1092.     DAD    H
  1093.     ENDM
  1094.     XCHG    
  1095.     CALL    NEGDE    ;IT'S STILL IN LOW MEMORY
  1096.  R    <LXI    H,PROTECT>
  1097.     DAD    D
  1098.     JNC    NOFIT    ;Haven't overwritten it yet.
  1099. ;
  1100. ; The library file is still open.  The open FCB has been
  1101. ; moved up here into high memory with the loader code.
  1102. ;
  1103. LBROPN:
  1104.  R    <LHLD    INDEX>        ;Set up for random reads
  1105.  R    <SHLD    RANDOM>
  1106.     XRA    A
  1107.  R    <STA    RANDOM+2>
  1108. ;
  1109.     LXI    H,TPA
  1110.  R    <SHLD    LOADDR>
  1111.  
  1112. ;
  1113. ; This high memory address and above, including CCP, must be
  1114. ; protected from being overlaid by loaded program
  1115. ;
  1116. PROTECT:
  1117. ;
  1118. LOADLOOP:            ;Load that sucker.
  1119.  R    <LHLD    LENX>        ;See if done yet.
  1120.     MOV    A,L
  1121.     ORA    H
  1122.     JRZ    LOADED
  1123.     DCX    H
  1124.  R    <SHLD    LENX>
  1125. ;
  1126.  R    <LHLD    LOADDR>     ;Increment for next time
  1127.     MOV    D,H
  1128.     MOV    E,L
  1129.     LXI    B,80H
  1130.     DAD    B
  1131.  R    <SHLD    LOADDR>
  1132.     CPM    DMA        ;but use old value (DE)
  1133. ;
  1134.  R    <LXI    D,LBRFIL>
  1135.     CPM    RRD        ;Read the sector
  1136.     ORA    A        ;Ok?
  1137.     JRNZ    ERR        ;No, bail out.
  1138. ;
  1139.  R    <LHLD    RANDOM>     ;Increment random record field
  1140.     INX    H
  1141.  R    <SHLD    RANDOM>
  1142. ;
  1143.     JR    LOADLOOP    ;Until done.
  1144. ;
  1145. ERR:
  1146.     MVI    A,( JMP )    ;Prevent execution of bad code
  1147.     STA    TPA
  1148.     LXI    H,BOOT
  1149.     SHLD    TPA+1
  1150. ;
  1151.  R    <LXI    D,LDMSG>
  1152.     CPM    MSG
  1153.  R    <LXI    D,SUBFILE>    ;Abort SUBMIT if in progress
  1154.     CPM    DEL
  1155. LOADED:
  1156.     CPM    DMA,TBUFF    ;Restore DMA adrs for user pgm
  1157.     CPM    CON,LF        ;Turn up a new line on console
  1158.     POP    B        ;Restore Current User/Disk
  1159.     PUSH    B        ;Save it again
  1160.     MOV    E,B        ;Restore Disk
  1161.     CPM    DSK        ;Log In Disk
  1162.     POP    D        ;E=USER
  1163.     CPM    USR        ;Log In User
  1164.     JMP    TPA
  1165. ;
  1166. LDMSG:
  1167.     DB    CR,LF,'Bad Load$'
  1168. INDEX:
  1169.     DW    0
  1170. LENX:
  1171.     DW    0
  1172. SUBFILE:
  1173.     DB    1,'$$$     SUB',0,0,0,0
  1174.     ;If used, this FCB will clobber the following one.
  1175.     ;but it's only used on a fatal error, anyway.
  1176. LBRFIL:
  1177.     DS    32        ;Name placed here at setup
  1178.     DB    0        ;Normal FCB plus...
  1179. OVERLAY SET    $        ;(Nothing past here but DS's)
  1180. RANDOM:
  1181.     DS    3        ;...Random access bytes
  1182. MAXMEM:
  1183.     DS    2
  1184. LOADDR:
  1185.     DS    2
  1186. ;*************************************************
  1187. ;End of segment to be relocated.
  1188.     IF    OVERLAY EQ 0
  1189. OVERLAY SET    $
  1190.     ENDIF
  1191. ;
  1192. PAGES    EQU    ($-@BASE+0FFH)/256+8
  1193. ;
  1194. SEGLEN    EQU    OVERLAY-@BASE
  1195.     ORG    @BASE+SEGLEN
  1196.     PAGE
  1197. ;    Build the relocation information into a
  1198. ; bit table immediately following.
  1199. ;
  1200. @X    SET    0
  1201. @BITCNT SET    0
  1202. @RLD    SET    ??R1
  1203. @NXTRLD SET    2
  1204.     RGRND    %@RLBL+1    ;define one more label
  1205. ;
  1206.     REPT    SEGLEN+8
  1207.     IF    @BITCNT>@RLD
  1208.     NXTRLD    %@NXTRLD    ;next value
  1209.     ENDIF
  1210.     IF    @BITCNT=@RLD
  1211. @X    SET    @X OR 1     ;mark a bit
  1212.     ENDIF
  1213. @BITCNT SET    @BITCNT + 1
  1214.     IF    @BITCNT MOD 8 = 0
  1215.     DB    @X
  1216. @X    SET    0    ;clear hold variable for more
  1217.     ELSE
  1218. @X    SET    @X SHL 1    ;not 8 yet. move over.
  1219.     ENDIF
  1220.     ENDM
  1221. ;
  1222.     DB    0
  1223. HOLD:
  1224.     DB    0,0        ;0 length, null terminator
  1225.     DS    128-2        ;rest of HOLD area
  1226. MEMBER:
  1227.     DS    16
  1228. ;
  1229.     END    CCPIN
  1230.