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