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 / CPM3 / CCP105P.ARK / CCP105.MAC < prev    next >
Text File  |  1986-10-17  |  82KB  |  3,677 lines

  1. ;
  2. ;This is the main module for both the CCP and CMDRUN.
  3. ;
  4. ;Assemble CCPHDR.MAC to produce the CCP, and LRUNHDR.MAC to
  5. ; produce the library processor.
  6. ;
  7. ;Version 1.02A    10/03/85 - Fixed bugs relating to loading of .SUB
  8. ;        files from COMMAND.LBR
  9. ;
  10. ;Version 1.02B  11/04/85 - Fixed bug which caused bad drive/user parse to
  11. ;        return with indication of a good drive or user parse (eg:
  12. ;        CUG: would return with a good drive C: parse). Also, CCP
  13. ;        now checks for a valid drive/user spec whenever a file is
  14. ;        to be run (ie: COMfiles, SUBfiles and PRLfiles). Also added
  15. ;        EXPAND,PRINT0 and WHLLBR equates and equates for user's own
  16. ;        MAXUSR, WHEEL, and MAXUSR boot values (see CCPHDR.MAC for
  17. ;        details).
  18. ;                        - Stuart Rose
  19. ;
  20. ;Version 1.03    11/06/85 - Removed PRINT0 equate, changed EXPAND and
  21. ;        WHLLBR equate to flag options.  Fixed more bugs relating
  22. ;        to library command processor.  CMDRUN now properly scans
  23. ;        more than one command library along the drive search chain.
  24. ;
  25. ;Version 1.04    03/08/85 - Added EXDRV and EXUSR variables for CMDRUN
  26. ;
  27. ;        04/14/86 - Fixed bug that prevents nested multiple command
  28. ;        lines from being run properly.  That is, if a multiple command
  29. ;        is issued, and one of the commands issues a chain command
  30. ;        with a multiple command, the initial multiple command line
  31. ;        would be lost, leaving an active RSX, which will not go
  32. ;        away.  Added a name to RSX containing next command.
  33. ;        (NEXTCMND)
  34. ;
  35. ;        07/13/86 - Added option to display time-on-system of current
  36. ;        caller in an RCPM running under BYE509 or newer.  If TIMEON
  37. ;        is YES, and both TIME and BYECHK are YES, then if BYE is
  38. ;        active displays time-on-system rather than time-of-day.
  39. ;        Set CCPPLUS to YES in BYE to use this option.
  40. ;        (Thanks to Stuart Rose)
  41. ;
  42. ;        07/14/86 - Changed from using a flag byte to equates in
  43. ;        CCPHDR.MAC and LRUNHDR.MAC.  It is now necessary to 
  44. ;        reassemble the source to change options.  With the new
  45. ;        fixes and options in version 1.04, the CCP will be larger
  46. ;        than 25 sectors, and may require special loading or BIOS
  47. ;        modifications to accept a larger CCP.
  48. ;
  49. ;
  50. ;Version 1.05    9/1986 - Added history mechanism,print0, and makecolon fix
  51. ;
  52. ;        Added history mechanism that is similar to 
  53. ;        Unix (tm of AT&T) csh's. This includes the internal
  54. ;        'h' command that displays the history.  This option
  55. ;        is probably only acceptable with the "temp-disk" being
  56. ;        a RAMDISK or possibly a fast Harddisk.  This
  57. ;        feature also gives a mechanism for additional extension.
  58. ;
  59. ;        Added print0 back again.
  60. ;
  61. ;        Added makecolon so when  running "make", where 
  62. ;        commands generated can have leading colons, an error
  63. ;        set by one of the commands will terminate the entire
  64. ;        rest of the (nested) submit file(s).
  65. ;
  66. ;                        -Mike Kersenbrock
  67.  
  68. bdos         EQU    5    ;Bdos entry point
  69. USRDSK         EQU    4    ;User/disk (for CP/M 1.4,2.2 compatibility)
  70. FCB         EQU    5CH    ;default FCB
  71. FCB2         EQU    6CH    ;default 2nd FCB
  72. FCBCR         EQU    7CH    ;CR field of FCB
  73. LOADDRV     EQU    50H    ;.COM file load drive
  74. PASS1ADR     EQU    51H    ;password 1 address
  75. PASS1LEN     EQU    53H    ;password 1 length
  76. PASS2ADR     EQU    54H    ;password 2 address
  77. PASS2LEN     EQU    56H    ;password 2 length
  78. SIZECMDLINE     EQU    0E7H    ;command line max length    ; V. 1.05
  79.     if    ccp
  80.  
  81. ;---------------------------------------------------------------
  82. ;Loader save area and entry points
  83.  
  84. SCBBASE     EQU    11bH    ;address of System Control Block
  85. MEMBASE     EQU    11dH    ;location of common memory base
  86. CHKRSX         EQU    11eH    ;loader check RSX entry point
  87. RELOC         EQU    121H    ;loader relocate entry point
  88. SETLOAD     EQU    124H    ;loader set load entry point
  89. SETNEXT     EQU    127H    ;loader set next RSX pointer entry point
  90. SETRSX         EQU    12aH    ;loader set RSX pointers entry point
  91. xbdos        equ    12dh    ;save IX and call bdos entry point
  92.  
  93.     endif        ;CCP
  94.  
  95. ;
  96. ;--------------------------------------------------------------
  97.  
  98. maxdrv         EQU    3dh    ;ZCPR maxdrive
  99. wheel         EQU    3eh    ;ZCPR wheel
  100. maxusr         EQU    3fh    ;ZCPR maxuser
  101.  
  102. ;........
  103. ;
  104. ;Main entry point.  The BIOS loads the CCP into the tpa.
  105. ;The loader module has a JMP START at 100H to bring us here.
  106. ;
  107.  
  108. START:
  109.     LD    SP,STACK    ;set up local stack
  110.     LD    HL,CCPRET    ;
  111.     PUSH    HL        ;push CCP return onto stack
  112.     LD    DE,SCBPB    
  113.     LD    C,49        ;RETURN BASE PAGE OF SYSTEM CONTROL BLOCK
  114.     CALL    BDOS
  115.     ld    l,80h        ;set up for IX register
  116.     LD    (SCBBASE),HL    ;Save address of SCB
  117.     push    hl
  118.     pop    ix        ;IX points to SCB (xx80H)
  119.  
  120.     if    ccp
  121.  
  122.     LD    a,(ix+7aH)    ;0FAH = COMMON MEMORY BASE PAGE
  123.     LD    (MEMBASE),A    ;Save common mem base page
  124.     LD    a,(ix+19H)    ;99H = BASE PAGE OF BDOS SYSTEM
  125.     LD    (BDOSBASE),A    ;Save Base page of BDOS system
  126. ;
  127. ;CHECK TO SEE IF ANY RSX'S AND/OR LOADER PRESENT
  128. ;
  129.     LD    A,(BDOS+2)    ;Get top of TPA page
  130.     SUB    (ix+19H)    ;compare with BDOS page
  131.     jr    NZ,NOLOAD    ;jump if loader already in place
  132. ;
  133. ;need to relocate the loader into high ram
  134. ;
  135.     LD    BC,(LOADLEN)    ;PREPARE FOR RELOCATION
  136.     CALL    SETLOAD        ;Set up relocation paramaters
  137.     LD    H,E
  138.     LD    L,E
  139.     CALL    RELOC        ;relocate the loader
  140.     LD    HL,(BDOS+1)
  141.     LD    L,E
  142.     LD    C,6
  143.     CALL    MOVEC        ;move the serial number into place
  144.     LD    E,0BH
  145.     CALL    SETNEXT        ;Set up next address in loader RSX header
  146. NOLOAD:
  147.     if    byechk
  148.  
  149.     LD    DE,rsxpb    ;point to call RSX pb
  150.     CALL    rsx        ;check for bye present
  151.     LD    (byeact),A    ;save BYE active flag
  152.  
  153.     endif            ; byechk
  154.  
  155.     LD    C,98        ;FREE BLOCKS
  156.     CALL    xbdos        ;free blocks
  157.     LD    (ix+53H),'$'    ;0B6H = String delimiter
  158.     LD    (ix+66H),1    ;0E6H = MULTI-SECTOR COUNT
  159.     LD    (ix+67H),0    ;Init BDOS error mode
  160.     LD    (ix+4FH),3    ;0CFH = CONSOLE MODE LOW BYTE
  161.     LD    (ix+50H),0    ;Init Console mode high byte
  162.     ld    a,(ix+2bh)    ;get submit drive
  163.     ld    (subfcb),a    ;save it
  164.     bit    5,(ix+34H)    ;0B4H = SYSTEM FLAGS (b5=reset disk system)
  165.     ld    c,13
  166.     CALL    NZ,xbdos    ;Reset disk system if set
  167.     bit    1,(ix+33H)    ;0B3H = SYSTEM FLAGS (b1=RSX flag)
  168.     CALL    Z,CHKRSX    ;Delete inactive RSXs if clear
  169.     res    1,(ix+33H)    ;Clear RSX flag
  170.  
  171.     endif        ;CCP
  172.  
  173.     LD    c,25
  174.     CALL    xbdos        ;get current drive
  175.     LD    (disknum),A    ;save it
  176.     LD    BC,USERNUM    ;Point to our user number save
  177.  
  178.     if    ccp
  179.  
  180.     LD    A,(ix+60h)    ;Get BDOS user number
  181.  
  182.     else        ;if not CCP
  183.  
  184.     ld    a,(ix+30h)    ;get CCP user number
  185.  
  186.     endif        ;not CCP
  187.  
  188.     LD    (BC),A        ;Save it for us
  189.  
  190.     if    ccp
  191.  
  192.     LD    A,(ix+30H)    ;Get CCP user number
  193.     bit    6,(ix+33h)    ;Bit 6 = change default u/d to last program
  194.     jr    NZ,OLDUSR    ;Jump if to set to last program user number
  195.     LD    (BC),A        ;Save CCP user number
  196. OLDUSR:
  197.     LD    (ix+60h),A    ;Set the BDOS user number
  198.     INC    BC        ;Point to our drive save
  199.     LD    A,(BC)        ;Get BDOS disk
  200.     jr    NZ,OLDDSK    ;Jump if to set to last program disk number
  201.     LD    A,0FFH        ;Flag that we must login drive
  202. OLDDSK:
  203.     res    6,(ix+33h)    ;reset default u/d bit
  204.     LD    (BC),A        ;Save disk number for us
  205.     INC    BC        ;POINT TO CURDSK
  206.     LD    A,(ix+2fH)    ;Get CCP disk
  207.     LD    (BC),A        ;Save it for us
  208.     CALL    seldsk        ;select drive
  209.     LD    DE,rsx66    ;point to RSX function 66
  210.     CALL    rsx        ;see if directory names loaded
  211.     OR    a
  212.     jr    NZ,noroot    ;jump if no directory names
  213.     LD    (diradr),HL    ;save directory name table address
  214. noroot:
  215.     bit    7,(ix+33H)    ;Bit 7 of B3H = chain flag
  216.     jr    Z,NOCHAIN    ;jump if normal CCP command
  217.     LD    HL,80H        ;Point to location of chain command
  218.  
  219.     else        ;if not CCP
  220.  
  221.     ld    hl,81h        ;point to location of command
  222.  
  223.     endif        ;not CCP
  224.  
  225. ;
  226. ;MOVE THE COMMAND LINE FOR PROCESSING
  227. ;
  228. MOVCMD:
  229.     LD    DE,CMDLINE    ;Point to internal command line buffer
  230.     LD    BC,7FH        ;Length of move
  231.     LD    A,C
  232.     LD    (DE),A        ;Save command line max length
  233.     INC    DE
  234.     ldir            ;Move command line into place
  235.  
  236.     if    ccp
  237.  
  238.     jp    DOCMD        ;And go process it.
  239. NOCHAIN:            ;Here if no chain function call
  240.     bit    1,(ix+35H)    ;0B5H = SYSTEM FLAGS (b1=cold start)
  241.     jr    nz,nocold    ;jump if normal warm start
  242.  
  243.     if   makecolon                        ; V1.05
  244.  
  245.     xor    a        ;get a zero            ; V1.05
  246.     LD    (ix+2cH),a    ;Zero program return code    ; V1.05
  247.     LD    (ix+2dH),a                    ; V1.05
  248.     
  249.     endif ; makecolon                    ; V1.05
  250.  
  251.     set    1,(ix+35h)    ;SET COLD START FLAG
  252.     ld    a,1
  253.     LD    (msgflag),A    ;Save copy for us
  254.     ld    c,13
  255.     CALL    xbdos        ;reset disk system on cold boot
  256.     ld    hl,maxdrv    ;point to ZCPR maxdrv
  257.     ld    (hl),mydrv    ;Init ZCPR MAXDRV         ; V1.02B
  258.     inc    hl
  259.     ld    (hl),mywhl    ;Init ZCPR WHEEL        ; V1.02B
  260.     inc    hl
  261.     ld    (hl),myusr    ;Init ZCPR MAXUSR        ; V1.02B
  262.     LD    HL,PROFSUB    ;point to 'PROFILE.SUB' command
  263.     jr    MOVCMD        ;execute PROFILE.SUB on cold start
  264.  
  265. PROFSUB:
  266.     DEFB    'PROFILE.S',0    ;Cold start command
  267. ;
  268. ;
  269. NOCOLD:
  270.     CALL    SETFLG        ;SETFLG sets Bits 7 & 5 in offset B4H
  271.     CALL    CRLF        ;Turn up a new line
  272.     bit    6,(ix+24h)    ;test for erase of $$$.SUB file
  273.     ld    c,19
  274.     call    nz,dosubfcb    ;erase any $$$.SUB file
  275.     res    6,(ix+24h)    ;reset erase $$$.SUB file
  276.  
  277. ;.........
  278. ;
  279. ;Internal commands and errors return here
  280. ;
  281.  
  282. CCPRET:
  283.     LD    sp,STACK-2    ;Set up the stack
  284.     LD    HL,CCPRET
  285.     PUSH    HL        ;Push return onto stack
  286.     CALL    SETFLG        ;Set bits 7 & 5 in offset B4H
  287. ;
  288. ;DISPLAY THE SYSTEM PROMPT ( A> )
  289. ;
  290.     call    prompt        ; V 1.05 (code change, but same logic)
  291.     jp    prmpt2
  292.  
  293.  
  294. prompt:    
  295.     if    time
  296.  
  297.     LD    E,'['
  298.     CALL    co        ;display "["
  299.  
  300.     if    timeon and byechk
  301.  
  302.     ld    a,(byeact)    ;get BYE active flag
  303.     or    a        ;is BYE running?
  304.     jr    nz,shwtim    ;nope, just show time
  305.     ld    c,79
  306.     call    xbdos        ;get time on from BYE
  307.     call    prtnum        ;display time on
  308.     ld    de,minmsg    ; display " min."
  309.     ld    c,9
  310.     call    xbdos
  311.     jr    st1        ;clean up
  312. shwtim:
  313.  
  314.     endif            ; timeon and byechk
  315.  
  316.     LD    DE,datpb
  317.     LD    c,105
  318.     CALL    xbdos        ;return time
  319.     LD    HL,datpb+3
  320.     LD    a,(HL)        ;get minutes
  321.     PUSH    AF        ;Save for later
  322.     DEC    HL        ;Point to hours
  323.     LD    A,(HL)
  324.     CALL    hexprt        ;display hours
  325.     LD    E,':'        ;separater
  326.     CALL    co
  327.     POP    AF        ;get minutes
  328.     CALL    hexprt        ;display minutes
  329. st1:
  330.     LD    E,']'
  331.     CALL    co
  332.     LD    E,' '    
  333.     CALL    co
  334.  
  335.     endif            ; time
  336.  
  337.     CALL    PCURDSK        ;Display the current drive
  338.     LD    A,(USERNUM)    ;get user number
  339.     
  340.     if  not print0                        ; V 1.05
  341.  
  342.     or    a                        ; V 1.05
  343.     jr    z,noprtusr    ;No user number if it is zero   ; V 1.05
  344.  
  345.     endif   ; not print0
  346.  
  347.     call    PRTNUM        ;Display user number         ; V 1.02B
  348. noprtusr:                            ; V 1.05
  349.     bit    7,(ix+24h)    ;test for directory name display
  350.     jr    Z,nodirnm    ;jump if no directory name display
  351.     LD    HL,(diradr)    ;get directory name address
  352.     LD    a,h
  353.     OR    l
  354.     jr    Z,norfile    ;jump if null
  355.     EX    DE,HL
  356.     LD    HL,rootdrv    ;point to drive returned by rootget
  357. rootloop:
  358.     CALL    rootget        ;get an entry
  359.     jr    Z,norfile    ;jump if at end
  360.     LD    A,(curdsk)    ;get current drive
  361.     CP    (HL)        ;same as table entry?
  362.     jr    NZ,rootloop
  363.     INC    HL        ;point to user number from rootget
  364.     LD    A,(usernum)    ;get current user
  365.     CP    (HL)        ;same as table entry?
  366.     jr    Z,rootok
  367.     DEC    HL
  368.     jr    rootloop
  369. rootok:
  370.     LD    a,':'
  371.     CALL    cono        ;display a colon
  372.     LD    HL,rootname    ;point to directory name
  373.     LD    c,' '        ;it terminates with a blank
  374.     CALL    prtname        ;print the directory name
  375. norfile:
  376.     LD    DE,rootrsx    ;point to RSX function 65
  377.     CALL    rsx        ;Any LBR RSX's will print their names
  378. nodirnm:
  379.     LD    A,'>'    
  380.     JP    CONO        ;Display the system prompt
  381.  
  382. prmpt2:    LD    DE,0B1BAH
  383.     CALL    MOVSCB        ;Move offsets B1,B2 to BA,BB in SCB
  384.     OR    A        ;Test for address of second command line
  385.     PUSH    AF        ;save flags on stack
  386.     jr    z,notmulti
  387.     res    7,(ix+34h)    ;Clear Multiple command line flag
  388. notmulti:
  389.     CALL    GETLINE        ;Get command
  390.     CALL    CRFLGA        ;clear bits 7 & 5 in B4H
  391.     POP    AF        ;Restore 2nd command flag
  392.     CALL    NZ,CHK2ND    ;Check 2nd command line
  393. ;........
  394. ;
  395. ;Here to process command line
  396. ;
  397. DOCMD:
  398.     endif        ;CCP
  399.  
  400.     xor    a
  401.     ld    (ix+25h),a    ;Init user number for load overlay function
  402.  
  403.     if    ccp
  404.  
  405.     ld    (subflag),a    ;init submit flag
  406.     ld    a,(ix+24h)    ;get submit user number
  407.     and    0e0h        ;set it to default
  408.     ld    (ix+24h),a    ;and save it
  409.  
  410.     endif        ;CCP
  411.  
  412.     bit    6,(ix+34h)    ;test default page mode
  413.     jr    nz,oldpmode
  414.     ld    a,(ix+49h)    ;get default page mode
  415.     ld    (ix+48h),a    ;reset default page mode
  416. oldpmode:
  417.     CALL    SCANLINE    ;get first item in command line
  418.     RET    Z        ;Return to CCPRET if nothing there
  419.     LD    DE,CMDFCB    ;Point to command FCB
  420.     CALL    CHKDRV        ;Check for drive spec and parse command line
  421.     LD    A,(FILETYPE)    ;Get Filetype first byte
  422.     CP    ' '        ;Do we have a filetype?
  423.  
  424.     if    CCP
  425.  
  426.     jr    NZ,FTYPE    ;jump if filetype present
  427.     LD    HL,CMDFCB    ;Point to command FCB
  428.     LD    A,(HL)        ;Get user number
  429.     INC    HL        ; Point to drive in FCB
  430.     OR    (HL)        ;Test for user or drive spec
  431.     INC    HL        ;Point to filename
  432.     LD    A,(HL)        ;get first byte of filename
  433.     jr    NZ,DRVSPEC    ;Jump if drive or user number specified
  434.     LD    HL,(diradr)    ;get directory name address
  435.     LD    a,h
  436.     OR    l
  437.     jr    Z,nocmd        ;jump if not loaded
  438.     EX    DE,HL
  439.     LD    HL,filename    ;point to filename retuned by rootget
  440. rootcloop:
  441.     CALL    rootget        ;get an entry
  442.     jr    Z,nocmd        ;jump if at end
  443.     CALL    scomp        ;is directory name=command?
  444.     jr    NZ,rootcloop
  445.     CALL    chkpass        ;verify if passworded directory
  446.     LD    HL,rootdrv    ;point to directory drive
  447.     LD    a,(HL)
  448.     INC    a
  449.     LD    (filedisk),A    ;save it in command drive
  450.     INC    HL        ;point to directory user
  451.     LD    a,(HL)
  452.     jp    newuser        ;process drive/user change
  453.  
  454.     else        ;if    not ccp
  455.  
  456.     ld    a,1
  457.     jr    nz,setftype
  458.     xor    a
  459. setftype:
  460.     ld    (typeflag),a    ;save filetype flag
  461.     ld    a,(ix+6ch)    ;get temp file drive
  462.     ld    (ix+2bh),a    ;set submit file drive
  463.     ld    (subfcb),a    ;save it
  464.     ld    hl,(cmdfcb)    ;get user/drive spec
  465.     ld    (lbrfcb),hl    ;put it in LBR FCB
  466.     ld    (usrsav),hl    ;and save it            ;V 1.03
  467.     ld    hl,0e704h    ;set up search offset, length    ;V 1.03
  468.     ld    (searoff),hl                    ;V 1.03
  469.     ld    a,(disknum)    ;get default drive        ;V 1.03
  470.     inc    a                        ;V 1.03
  471.     ld    h,a                        ;V 1.03
  472.     ld    l,1                        ;V 1.03
  473.     ld    (searflg),hl                    ;V 1.03
  474. docmpf:                                ;V 1.03
  475.     ld    a,(usernum)                    ;V 1.03
  476.     ld    (ix+60h),a    ;set the user number        ;V 1.03
  477.     ld    hl,0
  478.     ld    (cmdfcb),hl    ;zero user/drive for member
  479.     ld    hl,(usrsav)    ;get user/drive            ;V 1.03
  480.     ld    (lbrfcb),hl    ;put it in LBR FCB        ;V 1.03
  481.     call    cmpftype    ;attempt to open COMMAND.LBR using CPM's
  482.                 ;drive search chain.
  483.     call    lbrread        ;read first library sector
  484.     jr    z,lbrok                        ;V 1.03
  485. badlbr:                                ;V 1.03
  486.     call    ilprt                        ;V 1.03
  487.     db    'Invalid COMMAND.LBR',13,10,0            ;V 1.03
  488.     jr    lbrdone                        ;V 1.03
  489. lbrok:                                ;V 1.03
  490.     ld    hl,buff
  491.     ld    de,lbrcmp
  492.     ld    b,14
  493.     call    comp        ;test for valid library
  494.     jr    nz,badlbr                    ;V 1.03
  495.     ld    hl,(buff+14)    ;get dir length
  496.     ld    (lbrsec),hl    ;save dir length
  497.     ld    hl,buff+32    ;point to first member
  498.     ld    b,3        ; 3 members left
  499.     jr    lbr2
  500. lbr1:
  501.     ld    hl,(lbrsec)
  502.     dec    hl
  503.     ld    (lbrsec),hl    ;decr sector count
  504.     ld    a,h
  505.     or    l
  506.     jr    z,lbrdone                    ;V 1.03
  507.     call    lbrread        ;read a directory sector
  508.     jr    nz,badlbr                    ;V 1.03
  509.     ld    hl,buff
  510.     ld    b,4        ;4 members per sector
  511. lbr2:
  512.     push    bc
  513.     ld    a,(hl)
  514.     or    a        ;active member?
  515.     jr    nz,lbr3
  516.     inc    hl
  517.     ld    (memaddr),hl    ;save member address
  518.     ld    a,(typeflag)
  519.     or    a
  520.     jr    nz,ftype    ;jump if file type present
  521.  
  522.     endif        ;not CCP
  523.  
  524. NOCMD:
  525.     ld    a,(ix+34h)
  526.     and    18h        ;Test bits 3,4 of B4H (file type search order)
  527.     jr    Z,FTYPE        ;Jump if search .COM only
  528.     LD    B,8        ;init B for later
  529.     SUB    B        ;Test for .COM, then .SUB
  530.     jr    Z,NOCMD1    ;Jump if .COM, then .SUB
  531.     LD    B,0        ;Here if order is .SUB, then .COM
  532. NOCMD1:
  533.     PUSH    BC        ;Save search order indicator for 2nd filetype
  534.     CALL    MOVETYPE    ;Move first filetype into FCB (indicator in A)
  535.     CALL    CMPRFTYPE    ;Try First filetype
  536.     POP    AF        ;retrieve second filetype indicator
  537.     CALL    MOVETYPE    ;Move 2nd filetype into FCB
  538. FTYPE:
  539.     CALL    CMPRFTYPE    ;Attempt to execute the command
  540.  
  541.     if    ccp
  542.  
  543.     if    yeslbr
  544.  
  545.     ld    hl,crname    ;Point to CMDRUN fcb
  546.  
  547.     if    whllbr
  548.  
  549.     ld    A,(wheel)    ; get the wheel byte        ; V1.02B
  550.     and    A        ; check for wheel byte set (non-zero); V1.02B
  551.     call    nz,setcmd    ;set up CMDRUN fcb and attempt
  552.  
  553.     else            ; if not whllbr
  554.  
  555.     call    setcmd        ;set up CMDRUN fcb and attempt
  556.  
  557.     endif            ; not whllbr
  558.  
  559.     endif            ; yeslbr
  560.  
  561.     jp    ERRXIT        ;If we returned, then its an error
  562.  
  563.     else        ;if not CCP
  564.  
  565.     ld    hl,(memaddr)    ;get member address
  566.     dec    hl
  567. lbr3:
  568.     pop    bc
  569.     inc    (hl)        ;test for 0ffh
  570.     jr    z,lbrdone                    ;V 1.03
  571.     ld    de,32
  572.     add    hl,de        ;next member
  573.     djnz    lbr2
  574.     jr    lbr1
  575.  
  576. lbrdone:                            ;V 1.03
  577.     ld    a,(duspec)    ;drive/user specified?        ;V 1.03
  578.     or    a                        ;V 1.03
  579.     jp    z,docmpf    ;try again if no drive/user    ;V 1.03
  580.     jp    errxit                        ;V 1.03
  581.  
  582.     endif        ;not CCP
  583.  
  584.     if    ccp
  585.  
  586. ;
  587. ;.........
  588. ;
  589. ;Here if Drive spec or user number in command line
  590. ;
  591. DRVSPEC:
  592.     CP    ' '        ;Test for filename in FCB
  593.     jr    NZ,NOCMD    ;Jump if Drive spec & filename
  594.     CALL    CHKBLANK    ;Check for embedded blanks
  595.     LD    HL,cmdfcb    ;point to command user
  596.     LD    a,(HL)
  597.     DEC    a
  598.     JP    P,sisusr    ;jump if user # specified
  599.     LD    A,(usernum)    ;else get current user #
  600. sisusr:
  601.     INC    a
  602.     LD    (HL),a        ;put user number in command user
  603.     INC    HL        ;point to command drive
  604.     LD    a,(HL)
  605.     DEC    a
  606.     JP    P,sisdrv    ;jump if new drive
  607.     LD    A,(curdsk)    ;else get current drive
  608. sisdrv:
  609.     INC    a
  610.     LD    (HL),a        ;put drive in command drive
  611.     LD    A,(cmdfcb)    ;get command user
  612.     DEC    a
  613. NEWUSER:
  614.     LD    (USERNUM),A    ;Save new user number
  615.     ld    (ix+30h),a    ;Set CCP user number
  616.     ld    (ix+60h),a    ;Set BDOS user number
  617. SAMEUSER:
  618.     LD    A,(FILEDISK)    ;Get drive from FCB
  619.     DEC    A        ;Test it
  620.     RET    M        ;Back to CCPRET if no drive spec
  621.     PUSH    AF        ;Save new drive on stack
  622.     CALL    SELDSK        ;Select new drive
  623.     POP    AF        ;restore new drive
  624.     LD    (CURDSK),A    ;Save it for us
  625.     ld    (ix+2fh),a    ;Set CCP drive, and return to CCPRET
  626.     ret
  627.  
  628. ;..........
  629. ;
  630. ;PRINT DISK IN [A] IF > 0 OR CURRENT DISK
  631. ;
  632. PRTDISK:
  633.     DEC    A        ;Drive specified in FCB?
  634.     JP    P,PRTDSK    ;Jump if specified
  635. ;
  636. ;PRINT CURRENT DISK
  637. ;
  638. PCURDSK:
  639.     LD    A,(CURDSK)    ;Get current drive
  640. ;
  641. ;PRINT DISK IN [A]
  642. ;
  643. PRTDSK:
  644.     ADD    A,'A'        ;convert to ASCII
  645.     jp    CONOUT        ;and print it
  646.  
  647. ;...........
  648. ;
  649. ;SUBMIT FILE FCB
  650. ;
  651. SUBNAME:
  652.     DEFB    0,0,'SUBMIT  COM'
  653.  
  654. ;.............
  655. ;
  656. ;CONSTRUCT SUBMIT COMMAND LINE
  657. ;
  658. SUBMIT:
  659.     LD    A,(DE)        ;Save submit drive
  660.     LD    (ix+2BH),a    ;Save submit drive in SCB
  661.     inc    a        ;non-zero
  662.     ld    (subflag),a    ;set submit flag
  663.     LD    HL,SUBNAME    ;Point to submit file name
  664. setcmd:
  665.     ld    de,cmdfcb
  666.     ld    bc,13        ;13 bytes long
  667.     ldir            ;move it
  668.     ld    hl,cmdline    ;point to command line
  669.     ld    (hl),' '    ;start with a blank
  670.     inc    hl        ;point to second byte
  671.     ld    (pfcb),hl    ;Store its address for Parse
  672.     jr    cmprftype
  673.  
  674.     else        ;if not CCP
  675.  
  676. ;...........
  677. ;
  678. ;Submit file handler for CMDRUN.  The .SUB file is
  679. ;read from the Library, and saved as $$$.SUB in the current
  680. ;CCP drive/user location, and a Chain command is executed
  681. ;to let the CCP handle the submit function.
  682. ;
  683.  
  684. submit:
  685.     ld    (ix+25h),0    ;reset Loader user number
  686.     call    setlbr        ;set up things to read member
  687.     ld    c,19
  688.     call    dosubfcb    ;erase any $$$.SUB file
  689.     ld    c,22
  690.     call    dosubfcb    ;make new $$$.SUB file
  691.     jr    z,smakeok
  692.     call    ilprt
  693.     db    'No directory space for $$$.SUB',0
  694.     rst    0
  695. smakeok:
  696.     ld    hl,(lbrfcb+36)    ;get member length
  697.     inc    h
  698.     dec    h
  699.     jr    nz,longsub    ;.SUB file member must be < 16k
  700.     ld    a,l
  701.     cp    129
  702.     jr    c,slenok
  703. longsub:
  704.     call    ilprt
  705.     db    'SUB member > 16k',0
  706.     rst    0
  707. slenok:
  708.     ld    (ix+66h),a    ;set multi-sector count
  709.     ld    de,stack
  710.     call    setdma        ;set up dma for mass transfer
  711.     call    setlusr        ;set library user if no default
  712.     ld    c,20
  713.     call    xbdos        ;read in the .SUB member
  714.     or    a
  715.     jr    z,sreadok
  716.     call    ilprt
  717.     db    'Cannot read SUB member',0
  718.     rst    0
  719. sreadok:
  720.     ld    c,21
  721.     call    dosubfcb    ;write the $$$.SUB file
  722.     jr    z,swriteok
  723.     call    ilprt
  724.     db    'Out of disk space writing $$$.SUB',0
  725.     rst    0
  726. swriteok:
  727.     ld    c,16
  728.     call    dosubfcb    ;close the $$$.SUB file
  729.     jr    z,scloseok
  730.     call    ilprt
  731.     db    'Cannot close $$$.SUB',0
  732.     rst    0
  733. scloseok:
  734.     ld    (ix+66h),1    ;reset multi-sector count
  735.     call    sdefdma        ;reset dma
  736.     set    6,(ix+24h)    ;flag $$$.SUB file present
  737.     ld    a,(subfcb)    ;get submit drive
  738.     ld    de,80h        ;point to target of move
  739.     or    a        ;submit drive?
  740.     jr    z,nosubdrv
  741.     add    a,'A'-1        ;make drive ASCII
  742.     ld    (de),a
  743.     inc    de
  744.     ld    a,':'
  745.     ld    (de),a        ;put colon into place
  746.     inc    de
  747. nosubdrv:
  748.     ld    hl,subname
  749.     ld    bc,5
  750.     ldir            ;move $$$.S into place
  751.     ld    hl,(pfcb)
  752.     dec    hl        ;point to command tail
  753.     ex    de,hl
  754.     call    movetil0    ;move command tail into place
  755.     ld    c,47
  756.     ld    e,0
  757.     jp    bdos        ;chain to submit handler in CCP
  758.  
  759. subname:
  760.     db    '$$$.S'
  761.  
  762.     endif        ;not CCP
  763.  
  764. dosubfcb:
  765.     xor    a        ;submit fcb always user 0
  766.     ld    (ix+60h),a    ;set submit user number
  767.     ld    de,subfcb    ;point to submit FCB
  768.     call    xbdos        ;do the function
  769.  
  770.     if    not ccp
  771.  
  772.     or    a        ;set flag
  773.  
  774.     endif        ;not CCP
  775.  
  776.     ld    a,(usernum)    ;get our user #
  777.     ld    (ix+60h),a    ;set BDOS user number
  778.     ret
  779.  
  780. subfcb:
  781.     db    0,'$$$     SUB',0,0,0,0
  782.     ds    16
  783.     db    0        ;cr field
  784.  
  785.  
  786. ;............
  787. ;
  788. ;COMPARE AND PROCESS FILE TYPE IN COMMAND
  789. ;
  790. CMPRFTYPE:
  791.     LD    DE,FILETYPE    ;point to filetype in FCB
  792.     LD    HL,TYPNAME    ;Point to filetype table
  793.     CALL    COMPARE        ;Is it .COM, .SUB or .PRL?
  794.     RET    NZ        ;Return if no match
  795.  
  796.     if    ccp
  797.  
  798.     LD    DE,CMDFCB    ;point to command FCB
  799.  
  800.     else        ;if not CCP
  801.  
  802.     push    bc        ;save filetype code
  803.     ld    de,filename    ;point to filename
  804.     ld    hl,(memaddr)    ;get member address
  805.     ld    b,11        ;11 bytes to compare
  806.     call    comp        ;have we found the member?
  807.     pop    bc
  808.     ret    nz        ;return if not found
  809.     push    bc
  810.     dec    de        ;point to drive code
  811.     jp    noprtfile
  812.  
  813. ;..........
  814. ;
  815. ;Entry point for locating COMMAND.LBR using CP/M's search chain.
  816. ;
  817. cmpftype:
  818.     ld    de,lbrfcb
  819.     or    0ffh                        ;V 1.03
  820.     ld    (duspec),a    ;set to show is drive/user spec    ;V 1.03
  821.  
  822.     endif        ;not CCP
  823.  
  824.     CALL    setdusr        ;Set FCB user number if specified
  825.     LD    A,(DE)        ;get drive code
  826.     LD    C,A        ;    into C
  827.  
  828.     if    ccp
  829.  
  830.     PUSH    BC        ;Save filetype code
  831.  
  832.     endif        ;not CCP
  833.  
  834.     LD    C,0
  835.     OR    A        ;Test for default drive
  836.     jr    NZ,NOTDEFDSK    ;Jump if drive specified
  837.     DEC    DE        ;Point to user code
  838.     LD    A,(DE)        ;get user
  839.     INC    DE        ;back to drive code
  840.     OR    A        ;test user code
  841.     jr    NZ,notdefdsk    ;Jump if user specified
  842.  
  843.     if    ccp
  844.  
  845.     LD    BC,0E704H    ;[B] = DRIVE SEARCH OFFSET-1, (E7H)
  846.                 ;[C] = LENGTH OF TABLE (4 bytes)
  847.     LD    A,(CURDSK)    ;Get current drive
  848.     INC    A        ;Adjust drive
  849.     LD    H,A        ;H = current drive + 1
  850.     LD    L,1        ;flag to prevent duplicate search on same drive
  851.  
  852.     else        ;if not CCP
  853.  
  854.     ld    bc,(searoff)    ;get search offset and count    ;V 1.03
  855.     ld    hl,(searflg)    ;get flags            ;V 1.03
  856.     xor    a                        ;V 1.03
  857.     ld    (duspec),a    ;flag no drive/user spec    ;V 1.03
  858.  
  859.     endif        ;not CCP
  860.  
  861.  
  862. ;..........
  863. ;
  864. ;Loop to inspect drive search chain as specified in offsets E8H to EBH
  865. ;in the SCB
  866. ;
  867. CPRFT1:
  868.     INC    B        ;Bump search offset
  869.     DEC    C        ;Decrement length left
  870.     LD    A,C        ;Length left in A
  871.     PUSH    HL        ;save HL
  872.     CALL    P,GETSCB    ;Test this drive entry if length left > 0
  873.     POP    HL        ;restore HL
  874.     OR    A        ;test for end of table
  875.     JP    M,SRCHEND    ;Jump if at end of table
  876.     jr    Z,DEFSPEC    ;Jump if default drive
  877.     CP    H        ;Is the drive the current disk?
  878.     jr    NZ,NOTCURDSK    ;Jump if not current disk
  879. DEFSPEC:
  880.     LD    A,H        ;Get current drive
  881.     DEC    L        ;adjust duplicate search flag
  882.     JP    M,CPRFT1    ;Jump if we already scanned this drive
  883. NOTCURDSK:
  884.     LD    (DE),A        ;Put drive spec into FCB
  885. NOTDEFDSK:
  886.     PUSH    BC        ;Save these
  887.     PUSH    HL        ;    registers
  888.  
  889.     if    not    ccp
  890.  
  891.     call    checkex        ;Check for Exclude d/u
  892.     CALL    nz,OPENFILE    ;Attempt to open the file
  893.  
  894.     else        ;if CCP
  895.  
  896.     CALL    OPENFILE    ;Attempt to open the file
  897.  
  898.     endif        ;CCP
  899.  
  900.     jr    NZ,fileok    ;Jump if open ok
  901.     POP    HL        ;restore these
  902.     POP    BC        ;    registers
  903.     DEC    DE        ;point to user code
  904.     LD    A,(DE)        ;get user code
  905.     INC    DE        ;point to drive code
  906.     OR    A        ;test user code
  907.     jp    NZ,srchend    ;jump if user number specified
  908.     LD    A,(usernum)    ;get current user number
  909.     OR    A        ;is it zero?
  910.     jr    Z,cprft1    ;jump if current user is zero
  911.     XOR    A
  912.     PUSH    BC        ;save these
  913.     PUSH    HL        ;    registers
  914.     ld    (ix+60h),a    ;set user number to zero
  915.  
  916.     if    not    ccp
  917.  
  918.     call    checkex        ;Check for exclude d/u
  919.     CALL    nz,OPENFILE    ;Attempt to open the file (user 0)
  920.  
  921.     else        ;if CCP
  922.  
  923.     CALL    OPENFILE    ;Attempt to open the file (user 0)
  924.  
  925.     endif        ;CCP
  926.  
  927.     LD    A,(usernum)    ;get current user number
  928.     ld    (ix+60h),a    ;restore current user number
  929.     jr    NZ,filok1    ;jump if ok
  930.     POP    HL        ;restore these
  931.     POP    BC        ;    registers
  932.     jr    cprft1        ;and loop for next drive
  933.  
  934. ;............
  935. ;
  936. ;Here if file open is ok at user 0
  937. ;
  938. filok1:
  939.     DEC    DE        ;point to user number in FCB
  940.     LD    A,1        ;set it to zero (1-1)
  941.     LD    (DE),A        ;Save user number in FCB
  942.     INC    DE        ;back to drive code
  943.  
  944. ;...........
  945. ;
  946. ;Here if file open is ok at current user 
  947. ;
  948. fileok:
  949.     POP    HL        ;restore these
  950.     POP    BC        ;    registers
  951.  
  952.     if    not ccp                        ;V 1.03
  953.  
  954.     ld    (searoff),bc    ;save search offset and length    ;V 1.03
  955.     ld    (searflg),hl    ;save search flags        ;V 1.03
  956.  
  957.     endif        ;not CCP                ;V 1.03
  958.  
  959.     DEC    DE        ;point to user number
  960.  
  961.     if    ccp
  962.  
  963.     ld    a,(subflag)    ;get submit flag
  964.     or    a
  965.     jr    z,notsubset    ;jump if we haven't been here before
  966.     LD    a,(ix+25h)    ;A5H = user number for loader
  967.     ld    b,a
  968.     ld    a,(ix+24h)    ;get submit user
  969.     or    b        ;or in user number
  970.     ld    (ix+24h),a    ;save it for submit
  971. notsubset:
  972.  
  973.     endif        ;CCP
  974.  
  975.     LD    A,(DE)        ;get FCB user number
  976.  
  977.     if    not ccp
  978.  
  979.     or    80h        ;set library load flag for loader
  980.  
  981.     endif        ;not CCP
  982.  
  983.     ld    (ix+25h),a    ;Set the user number for loader
  984.  
  985.     if    ccp
  986.  
  987.     XOR    A
  988.     LD    (DE),A        ;set FCB user number to default
  989.  
  990.     endif        ; CCP
  991.  
  992.     INC    DE        ;point to drive code
  993.  
  994.     if    ccp
  995.  
  996.     LD    a,(ix+34h)
  997.     and    3        ;Test bits 0,1 of B4H (Display command flag)
  998.     jr    Z,NOPRTFILE    ;Jump if no dayfile logging
  999.     LD    A,(DE)        ;get FCB drive spec
  1000.     CALL    PRTDISK        ;print drive code
  1001.     LD    A,':'        ;print colon
  1002.     CALL    CONOUT
  1003.     PUSH    DE
  1004.     CALL    PRTFNAME    ;print the file name
  1005.     POP    DE
  1006.     PUSH    DE
  1007.     LD    HL,8
  1008.     ADD    HL,DE        ;point to sys flag
  1009.     LD    A,(HL)
  1010.     AND    80H        ;isolate sys flag
  1011.     LD    DE,USER0MSG    ;point to (User 0) msg
  1012.     CALL    NZ,PRNSTR    ;print this msg if sys file
  1013.     CALL    CRLF        ;turn up new line
  1014.     POP    DE
  1015.  
  1016.     else        ;if not CCP
  1017.  
  1018.     ret            ;all ok
  1019.  
  1020.     endif        ;not CCP
  1021.  
  1022. NOPRTFILE:
  1023.     POP    AF        ;get file type code
  1024.     LD    HL,TYPADDR    ;point to vector table
  1025.  
  1026.     if    yesprl
  1027.  
  1028.     cp    2        ;is it PRL?
  1029.     jr    nz,notprl
  1030.     set    6,(ix+25h)    ;set prl flag for loader
  1031. notprl:
  1032.  
  1033.     endif            ; yesprl
  1034.  
  1035.     ADD    A,A        ;DOUBLE COMMAND # FOR WORD OFFSET
  1036.     CALL    ADDHLA        ;form table entry address
  1037.     PUSH    DE        ;save fcb address
  1038.     LD    E,(HL)        ;Load command routine address into [DE]
  1039.     INC    HL
  1040.     LD    D,(HL)
  1041.     EX    DE,HL        ;routine address in [HL]
  1042.     POP    DE        ;restore FCB address
  1043.     JP    (HL)        ;Jump to file type handler
  1044.  
  1045. ;.............
  1046. ;
  1047. ;VALID COMMAND FILE TYPES
  1048. ;
  1049. TYPNAME:
  1050.     DEFB    'COM '
  1051.     DEFB    'SUB '
  1052.  
  1053.     if    yesprl
  1054.  
  1055.     DEFB    'PRL '
  1056.  
  1057.     endif            ; yesprl
  1058.  
  1059.     DEFB    0
  1060.  
  1061. ;...............
  1062. ;
  1063. ;SUBROUTINE ADDRESS FOR FILE TYPES
  1064. ;
  1065. TYPADDR:
  1066.     DEFW    LOADGO        ;COM handler
  1067.     DEFW    SUBMIT        ;Submit handler
  1068.  
  1069.     if    yesprl
  1070.  
  1071.     DEFW    LOADGO        ;PRL handler (same as COM)
  1072.  
  1073.     endif            ; yesprl
  1074.  
  1075. ;..............
  1076. ;
  1077. ;HERE IF AT END OF DRIVE SEARCH CHAIN
  1078. ;
  1079. SRCHEND:
  1080.  
  1081.     if    ccp
  1082.  
  1083.     POP    BC        ;restore filetype code
  1084.     LD    A,C        ;get drive spec
  1085.     LD    (DE),A        ;put drive spec into FCB
  1086.     RET            ;and return
  1087.  
  1088.     else        ;if not CCP
  1089.  
  1090.     jp    errxit
  1091.  
  1092. ;..............
  1093. ;
  1094. ;Routine to check for Exclude drive/user
  1095. ;
  1096. checkex:
  1097.     ld    a,(wheel)
  1098.     or    a
  1099.     ret    nz        ;ignore if wheel set
  1100.     ld    a,(exdrv)
  1101.     or    a        ;do we check for excluded d/u?
  1102.     jr    nz,checkex1
  1103.     or    0ffh        ;set nz
  1104.     ret
  1105. checkex1:
  1106.     ld    a,(de)        ;get drive spec
  1107.     or    a        ;default?
  1108.     jr    nz,fcbdiskok
  1109.     ld    a,(disknum)    ;get current drive
  1110.     inc    a
  1111. fcbdiskok:
  1112.     ld    b,a
  1113.     ld    a,(exdrv)
  1114.     cp    b        ;same as EXDRV?
  1115.     ret    nz
  1116.     ld    a,(exusr)    ;get exclude user
  1117.     cp    (ix+60h)    ;same as current user?
  1118.     ret            ;Z flag properly set
  1119.  
  1120.     endif        ;not CCP
  1121.  
  1122. ;.............
  1123. ;
  1124. ;MOVE FILE TYPE INTO FCB
  1125. ;
  1126. MOVETYPE:
  1127.     RRCA            ;Divide by 2
  1128.     LD    HL,TYPNAME    ;point to file type list
  1129.     CALL    ADDHLA        ;compute entry address
  1130.     LD    DE,FILETYPE    ;point to filetype in FCB
  1131.     LD    C,3        ;3 bytes to move
  1132.     jp    MOVEC        ;move file type
  1133.  
  1134.  
  1135.     if    not ccp
  1136.  
  1137. ;..........
  1138. ;
  1139. ;Read a library directory sector
  1140. ;
  1141. lbrread:
  1142.     ld    de,buff        ;point to buffer
  1143.     call    setdma        ;set the dma
  1144.     call    setlusr
  1145.     ld    c,20
  1146.     call    xbdos        ;read a sector
  1147.     or    a
  1148.     ret
  1149.  
  1150. ;...........
  1151. ;
  1152. ;Inline print routine
  1153. ;
  1154. ilprt:
  1155.     pop    hl
  1156.     ld    a,(hl)
  1157.     inc    hl
  1158.     push    hl
  1159.     or    a
  1160.     ret    z
  1161.     call    cono
  1162.     jr    ilprt
  1163.  
  1164. ;...........
  1165. ;
  1166. ;Compare two strings , ignore parity bit
  1167. ;
  1168. comp:
  1169.     push    de
  1170.     push    hl
  1171.     inc    b
  1172. comp1:
  1173.     dec    b
  1174.     jr    z,comp2
  1175.     ld    a,(de)
  1176.     and    7fh
  1177.     ld    c,a
  1178.     ld    a,(hl)
  1179.     and    7fh
  1180.     cp    c
  1181.     inc    hl
  1182.     inc    de
  1183.     jr    z,comp1
  1184. comp2:
  1185.     pop    hl
  1186.     pop    de
  1187.     ret
  1188.  
  1189. ;..............
  1190. ;
  1191. ;Set up stuff to load the Library member
  1192. ;
  1193.  
  1194. setlbr:
  1195.     ld    hl,(memaddr)    ;get member address
  1196.     ld    de,11
  1197.     add    hl,de        ;point to member start record
  1198.     ld    e,(hl)
  1199.     inc    hl
  1200.     ld    d,(hl)
  1201.     ld    (lbrfcb+34),de    ;put it in RR field
  1202.     inc    hl
  1203.     ld    e,(hl)
  1204.     inc    hl
  1205.     ld    d,(hl)        ;get member length
  1206.     push    de        ;save on stack
  1207.     ld    de,buff
  1208.     call    setdma        ;set the dma
  1209.     call    setlusr
  1210.     ld    c,33
  1211.     call    xbdos        ;random read first member sector (sets
  1212.                 ; up for loader sequential read)
  1213.     or    a
  1214.     jp    z,lbrreadok
  1215.     call    ilprt
  1216.     db    'Error reading COMMAND.LBR',13,10,0
  1217.     jp    errxit
  1218. lbrreadok:
  1219.     pop    hl        ;get member length
  1220.     ld    (lbrfcb+36),hl    ;save it for loader
  1221.     ret
  1222.  
  1223.     endif        ;not CCP
  1224.  
  1225. ;...........
  1226. ;
  1227. ;.COM and .PRL command type handler
  1228. ;SET UP PAGE ZERO AND CALL LOADER
  1229. ;
  1230. LOADGO:
  1231.  
  1232.     if    not ccp
  1233.  
  1234.     call    setlbr        ;set up for lbr member read
  1235.  
  1236.     endif        ;not CCP
  1237.  
  1238.     LD    HL,TPA        ;load address
  1239.  
  1240.     if    ccp
  1241.  
  1242.     LD    (LOADADDR),HL    ;Save load address
  1243.     LD    HL,(BOFFSET)    ;Get BDOS base page in H
  1244.     DEC    H        ;Less one
  1245.     LD    L,0C0H        ;HL points to free area in loader RSX
  1246.     PUSH    HL        ;Save on stack
  1247.  
  1248.     else        ;if not CCP
  1249.  
  1250.     ld    (lbrfcb+34),hl    ;save load address
  1251.     ld    d,(ix+19h)    ;get bdos base page
  1252.     dec    d        ;less one
  1253.     ld    e,0c0h        ;DE points to free area in loader RSX
  1254.     push    de        ;save on stack
  1255.     ld    hl,lbrfcb+1    ;source
  1256.     ld    a,(hl)        ;get load drive
  1257.  
  1258.     endif        ;not CCP
  1259.  
  1260.     if    ccp
  1261.  
  1262.     LD    A,(DE)        ;get load drive
  1263.  
  1264.     endif        ;CCP
  1265.  
  1266.     LD    (LOADDRV),A    ;save load drive
  1267.  
  1268.     if    ccp
  1269.  
  1270.     EX    DE,HL        ;swap for move
  1271.     LD    C,35        ;35 bytes to move
  1272.     CALL    MOVEC        ;Move FCB into loader RSX
  1273.  
  1274.     else        ;not CCP
  1275.  
  1276.     ld    bc,37        ;37 bytes to move
  1277.     ldir            ;move it
  1278.  
  1279.     endif        ;not CCP
  1280.  
  1281.     ld    hl,msgflag    ;point to message flag
  1282.     inc    (hl)        ;bump it
  1283.     LD    HL,(PFCB)    ;get command tail pointer
  1284.     DEC    HL
  1285.     LD    DE,81H        ;target of command tail
  1286.     EX    DE,HL    
  1287.     LD    (PFCB),HL    ;save new command tail pointer
  1288.     CALL    MOVETIL0    ;move command tail into place
  1289.     LD    (80H),A        ;save command tail length
  1290.     CALL    SETDFFCB    ;set up default FCB at 5CH
  1291.     LD    (PASS1ADR),HL    ;Save password 1 address
  1292.     LD    A,B
  1293.     LD    (PASS1LEN),A    ;Save password 1 length
  1294.     LD    DE,FCB2        ;Point to FCB2
  1295.     CALL    SETFCB        ;Set up FCB2
  1296.     LD    (PASS2ADR),HL    ;Save password 2 address
  1297.     LD    A,B
  1298.     LD    (PASS2LEN),A    ;Save password 2 length
  1299.  
  1300.     if    ccp
  1301.  
  1302.     LD    A,(curdsk)    ;get ccp drive
  1303.  
  1304.     else        ;if not CCP
  1305.  
  1306.     ld    a,(disknum)
  1307.  
  1308.     endif        ;not CCP
  1309.  
  1310.     CALL    SELDSK        ;Select drive
  1311.  
  1312.     if    ccp
  1313.  
  1314.     ld    a,(disknum)    ;get old drive flag
  1315.     or    a
  1316.     call    p,seldsk    ;select old drive if to be kept
  1317.  
  1318.     endif        ;CCP
  1319.  
  1320.     LD    A,(USERNUM)    ;get user number
  1321.     ld    (ix+60h),a    ;set the user number
  1322.     ADD    A,A        ;Shift user number over to high nybble
  1323.     ADD    A,A
  1324.     ADD    A,A
  1325.     ADD    A,A
  1326.     or    (ix+5AH)    ;or in BDOS drive
  1327.     LD    (USRDSK),A    ;Save at location 4 for previous CP/M compatibility
  1328.     call    sdefdma        ;set default dma
  1329.     POP    DE        ;restore FCB address
  1330.  
  1331.     if    ccp
  1332.  
  1333.     LD    HL,(BOFFSET)    ;Get BDOS base page in H
  1334.  
  1335.     else        ;if not CCP
  1336.  
  1337.     ld    h,(ix+19h)    ;get bdos base page
  1338.  
  1339.     endif        ;not CCP
  1340.  
  1341.     XOR    A
  1342.     LD    L,A
  1343.     LD    SP,HL        ;Set up stack just below the BDOS
  1344.     LD    H,A        ;HL = 0
  1345.     PUSH    HL        ;Push return to 0 at top of stack
  1346.     INC    H        ;HL = 100H
  1347.     PUSH    HL        ;Push return address for loader
  1348.                 ;goes to loaded program
  1349.     LD    (FCBCR),A    ;zero the record count
  1350.  
  1351.     if    ccp
  1352.  
  1353.     if    byechk
  1354.  
  1355.     ld    a,(byeact)    ;get BYE active flag
  1356.     or    a        ;is BTE active?
  1357.     jr    nz,noqs
  1358.  
  1359.     endif            ; byechk
  1360.  
  1361.     if    byechk or noxoff
  1362.  
  1363.     ld    a,2        ;disable flow control if bye present
  1364.  
  1365.     endif            ; byechk or noxoff
  1366.  
  1367.     if    byechk
  1368.  
  1369.     jr    setcon
  1370. noqs:
  1371.     XOR    A        ;enable stop/start scroll
  1372. setcon:
  1373.  
  1374.     endif            ; byechk
  1375.  
  1376.     LD    (ix+4FH),a    ;Set low byte console mode
  1377.     XOR    A
  1378.     LD    (ix+10H),a    ;Zero offsets 90H - 93H in SCB
  1379.     LD    (ix+11H),A
  1380.     LD    (ix+12H),A
  1381.     LD    (ix+13H),A
  1382.     bit    7,(ix+33H)    ;Test chain flag
  1383.     jr    NZ,CHAINSET    ;Jump if chain flag set
  1384.  
  1385.     if  makecolon                        ; V 1.05
  1386.  
  1387.     ld     a,(ix+2ch)    ;get error code lsb        ; V 1.05
  1388.     cp    0feh        ;CTL-C error?            ; V 1.05
  1389.     jr    nz,CHAINSET    ;nope, so nothing gets reset    ; V 1.05
  1390.     ld    a,(ix+2dh)    ;get error code msb        ; V 1.05
  1391.     inc    a        ;CTL-C error?            ; V 1.05
  1392.     jr    nz,CHAINSET    ;nope, so no reset again    ; V 1.05
  1393.                 ;yep, we reset ONLY CTL-C generated errors
  1394.     endif    ; makecolon                    ; V 1.05
  1395.  
  1396.  
  1397.     LD    (ix+2cH),a    ;Zero program return code
  1398.     LD    (ix+2dH),a
  1399.  
  1400. CHAINSET:
  1401.     res    7,(ix+33h)    ;Zero chain flag
  1402.  
  1403.     endif        ;CCP
  1404.  
  1405.     LD    C,59        ;load overlay function
  1406.     JP    bdos        ;jump to loader to complete load function
  1407.  
  1408.  
  1409.     if    ccp and byechk
  1410.  
  1411. ;
  1412. rsxpb:
  1413.     DEFB    4        ;rsx function for bye present test
  1414. byeact:
  1415.     DEFB    0        ;BYE active flag
  1416.  
  1417.     endif        ;CCP and byechk
  1418.  
  1419. ;...............
  1420. ;
  1421. ;OUTPUT CHAR IN [A]
  1422. ;
  1423. OUTCHAR:
  1424. cono:
  1425.     LD    E,A        ;BDOS likes char in E
  1426. ;
  1427. ;OUTPUT CHAR IN [E]
  1428. ;
  1429. CO:
  1430.     LD    C,2        ;console output function
  1431.     jp    xbdos
  1432.  
  1433. ;
  1434. ;PRINT STRING AT [DE]
  1435. ;
  1436. PRNSTR:
  1437.     LD    C,9        ;print string function
  1438.     jp    xbdos
  1439.  
  1440.     if    ccp
  1441.  
  1442. ;
  1443. ;GET LINE OF INPUT FROM CONSOLE
  1444. ;
  1445. GETLINE:
  1446.     LD    HL,CMDLINE-1    ;point to command line length
  1447.     LD    (HL),SIZECMDLINE ;set the command line max length  ; V. 1.05
  1448.     EX    DE,HL        ;BDOS likes the address in DE
  1449.     LD    C,10        ;getline function
  1450.     CALL    xbdos
  1451.     LD    HL,CMDLINE    ;point to length
  1452.     LD    A,(HL)        ;get length
  1453.     INC    HL        ;point to command string
  1454.     CALL    ADDHLA        ;point to end of command string
  1455.     LD    (HL),0        ;put terminator at end
  1456.     
  1457.     if    ccphistory
  1458.     if    ccp
  1459.  
  1460.     call    CCPEXT        ; first try for CCP extension program
  1461.     call    z,HISTORY    ; then do internal history mechanism,
  1462.                 ; optionally turned off by the CCPEXT
  1463.     endif    ; ccp
  1464.     endif    ; ccphistory
  1465.  
  1466.     jp    CRLF        ;and turn up a new line
  1467. ;
  1468. ;CHECK FOR CONSOLE INPUT
  1469. ;
  1470. STATINP:
  1471.     LD    C,11        ;console status function
  1472.     CALL    CBDOS
  1473.     RET    Z        ;return if nothing there
  1474.     LD    C,1        ;console input function
  1475.     jp    CBDOS
  1476.  
  1477.     endif        ;CCP
  1478.  
  1479. ;
  1480. ;SET DEFAULT DMA ADDRESS
  1481. ;
  1482. SDEFDMA:
  1483.     LD    DE,80H        ;default DMA address
  1484. ;
  1485. ;SET DMA ADDRESS IN [DE]
  1486. ;
  1487. SETDMA:
  1488.     LD    C,26        ;set DMA function
  1489.     jp    xbdos
  1490. ;
  1491. ;SELECT DISK IN [A]
  1492. ;
  1493. SELDSK:
  1494.     LD    E,A        ;BDOS likes it in E
  1495.     LD    C,14        ;select disk function
  1496.     jp    xbdos
  1497.  
  1498.     if    not ccp
  1499.  
  1500. ;
  1501. ;Point to Library FCB and Set user
  1502. ;
  1503. setlusr:
  1504.     ld    de,lbrfcb
  1505.  
  1506.     endif        ;not CCP
  1507.  
  1508. ;
  1509. ;Set FCB user number
  1510. ;
  1511. setdusr:
  1512.     ld    a,(de)        ;get FCB user number
  1513.     inc    de        ;point to drive code
  1514.     or    a
  1515.     ret    z        ;return if default
  1516.     DEC    A        ;adjust to true user number
  1517.     ld    (ix+60h),a    ;set the user number
  1518.     RET
  1519.  
  1520. ;
  1521. ;SET UP FCB AND OPEN DISK FILE
  1522. ;
  1523. OPENFILE:
  1524.     LD    BC,0ff0fh    ;B = Error mode to set, C = function
  1525.  
  1526.     if    ccp
  1527.  
  1528.     LD    DE,FILEDISK    ;point to drive code
  1529.  
  1530.     else        ;if not CCP
  1531.  
  1532.     ld    de,lbrfcb+1    ;point to drive code
  1533.  
  1534.     endif
  1535.  
  1536.     LD    HL,32    
  1537.     ADD    HL,DE        ;point to CR in FCB
  1538.     LD    (HL),0        ;zero CR field
  1539.  
  1540.     if    not ccp
  1541.  
  1542.     ld    hl,12
  1543.     add    hl,de        ;point to extent
  1544.     ld    (hl),0
  1545.     inc    hl
  1546.     ld    (hl),0
  1547.     inc    hl
  1548.     ld    (hl),0
  1549.  
  1550.     endif        ;not CCP
  1551.  
  1552.     PUSH    BC
  1553.     PUSH    DE
  1554.     LD    DE,PASSWORD    ;point to password field
  1555.     CALL    SETDMA        ;Set the DMA to password field
  1556.     POP    DE
  1557.     POP    BC
  1558.     PUSH    DE
  1559. openf2:
  1560.     LD    (ix+67H),B    ;set the error mode
  1561.     CALL    xbdos        ;execute the function in C
  1562.     LD    (ix+67h),0    ;set error mode to zero
  1563.     INC    L        ;test for physical error
  1564.     jr    NZ,noerr    ;jump if not physical error
  1565.     LD    A,H        ;get physical error code
  1566.     OR    A
  1567.     jr    Z,noerr        ;if zero, not a physical error
  1568.     CP    7        ;invalid password?
  1569.     jr    NZ,notpwd    ;jump if not invalid password
  1570.     CALL    getpass
  1571.     LD    BC,15        ;B = 0 (error mode), C = 15 (open file)
  1572.  
  1573.     if    ccp
  1574.  
  1575.     LD    DE,filedisk    ;point to FCB drive code
  1576.  
  1577.     else        ;if not CCP
  1578.  
  1579.     ld    de,lbrfcb+1    ;point to FCB drive code
  1580.  
  1581.     endif        ;not CCP
  1582.  
  1583.     jr    openf2        ;and attempt another open with new password
  1584.  
  1585. ;.......
  1586. ;
  1587. ;Here if not a password error.  determine physical error and print it
  1588. ;
  1589. notpwd:        
  1590.     LD    DE,iomsg
  1591.     CP    1
  1592.     jr    Z,prtmsg
  1593.     LD    DE,drvmsg
  1594.     CP    4
  1595.     jr    Z,prtmsg
  1596.     LD    DE,qmsg
  1597. prtmsg:
  1598.     CALL    prnstr        ;print error message
  1599.  
  1600.     if    ccp
  1601.  
  1602.     jp    nocold        ;and restart CCP
  1603.  
  1604.     else        ;if not CCP
  1605.  
  1606.     rst    0
  1607.  
  1608.     endif
  1609.  
  1610. ;..........
  1611. ;
  1612. ;Here if open sucessful
  1613. ;
  1614. noerr:
  1615.     DEC    L        ;test return code from open
  1616.  
  1617.     if    ccp
  1618.  
  1619.     LD    A,(CURDSK)    ;get current drive
  1620.  
  1621.     else        ;if not CCP
  1622.  
  1623.     ld    a,(disknum)
  1624.  
  1625.     endif        ;not CCP
  1626.  
  1627.     PUSH    HL        ;save return code
  1628.     call    seldsk        ;select the disk
  1629.     CALL    SDEFDMA        ;Set the DMA to 80H
  1630.     POP    HL        ;restore return code
  1631.     INC    L        ;Set return code flag from open
  1632.     POP    DE        ;align stack
  1633.     RET
  1634.  
  1635.     if    ccp
  1636.  
  1637. ;..........
  1638. ;
  1639. ;Print BCD number in A
  1640. ;
  1641. hexprt:
  1642.     PUSH    AF        ;save it
  1643.     REPT    4
  1644.     RRA            ;Shift high nibble into place
  1645.     ENDM
  1646.     CALL    hexpr1        ;print high nibble
  1647.     POP    AF        ;restore number
  1648. hexpr1:
  1649.     AND    0fh        ;isolate low nibble
  1650.     ADD    A,'0'        ;convert to ASCII
  1651.     jp    outchar        ;and print it.
  1652.  
  1653.     endif        ;CCP
  1654.  
  1655. ;............
  1656. ;
  1657. ;Physical error messages
  1658. ;
  1659.  
  1660. pwdmsg:
  1661.     DEFB    'Password: $'
  1662. iomsg:
  1663.     DEFB    'Disk I/O Error$'
  1664. drvmsg:
  1665.     DEFB    'Invalid drive$'
  1666. qmsg:
  1667.     DEFB    '"?" in command$'
  1668.  
  1669.     if    timeon
  1670.  
  1671. minmsg:
  1672.     defb    ' min.$'
  1673.  
  1674.     endif            ; timeon
  1675.  
  1676.     if    ccp
  1677.  
  1678. scomp:
  1679.     PUSH    HL
  1680.     PUSH    DE
  1681.     LD    DE,rootname
  1682. scomp1:
  1683.     LD    A,(DE)
  1684.     CP    (HL)
  1685.     jr    NZ,scompret
  1686.     CP    ' '
  1687.     jr    Z,scompret
  1688.     INC    HL
  1689.     INC    DE
  1690.     jr    scomp1
  1691. scompret:
  1692.     POP    DE
  1693.     POP    HL
  1694.     RET
  1695.  
  1696. rootget:
  1697.     PUSH    HL
  1698.     PUSH    DE
  1699.     LD    HL,rootname
  1700.     LD    DE,rootname+1
  1701.     LD    c,17
  1702.     LD    (HL),' '
  1703.     CALL    movec
  1704.     POP    DE
  1705.     LD    HL,rootname
  1706.     LD    b,8
  1707. rootnmove:
  1708.     LD    A,(DE)
  1709.     OR    a
  1710.     jr    Z,rgetdone
  1711.     INC    DE
  1712.     CP    ';'
  1713.     jr    Z,getp
  1714.     LD    (HL),a
  1715.     INC    HL
  1716.     djnz    rootnmove
  1717.     LD    A,(DE)
  1718.     INC    DE
  1719.     CP    ';'
  1720.     jr    Z,getp
  1721.     XOR    a
  1722.     jr    rgetdone
  1723. getp:
  1724.     LD    HL,rootpass
  1725.     LD    b,8
  1726. rootpmove:
  1727.     LD    A,(DE)
  1728.     INC    DE
  1729.     OR    a
  1730.     jr    Z,rgetdu
  1731.     LD    (HL),a
  1732.     INC    HL
  1733.     djnz    rootpmove
  1734.     LD    A,(DE)
  1735.     INC    DE
  1736.     OR    a
  1737.     jr    Z,rgetdu
  1738.     XOR    a
  1739.     jr    rgetdone
  1740. rgetdu:
  1741.     LD    A,(DE)
  1742.     INC    DE
  1743.     LD    b,a
  1744.     LD    HL,rootdrv
  1745.     AND    0fh
  1746.     LD    (HL),a
  1747.     INC    HL
  1748.     LD    a,b
  1749.     AND    0f0h
  1750.     RRA
  1751.     RRA
  1752.     RRA
  1753.     RRA
  1754.     LD    (HL),a
  1755.     INC    a
  1756. rgetdone:
  1757.     POP    HL
  1758.     RET
  1759.  
  1760.     endif        ;CCp
  1761.  
  1762. getpass:
  1763.     LD    DE,pwdmsg    ;point to password message
  1764.     CALL    prnstr        ;print "Password:"
  1765.     LD    B,8        ;password is 8 bytes max
  1766.     LD    HL,password    ;point to password field
  1767. pwdlop:
  1768.     PUSH    HL
  1769.     PUSH    BC
  1770.     LD    E,0fdh        ;get console input without echo
  1771.     LD    C,6
  1772.     CALL    xbdos
  1773.     POP    BC
  1774.     POP    HL
  1775.     CALL    ucase        ;convert to upper case
  1776.     CP    13        ;is it CR?
  1777.     jr    Z,pwdon        ;jump if done
  1778.     LD    (HL),A        ;save password char
  1779.     INC    HL
  1780.     djnz    pwdlop        ;and loop for more password chars
  1781.     jr    pwdon1
  1782. pwdon:
  1783.     LD    (HL),' '    ;blank out the rest of the password field
  1784.     INC    HL
  1785.     djnz    pwdon
  1786. pwdon1:
  1787.     CALL    crlf        ;turn up new line
  1788.     RET
  1789.  
  1790.     if    ccp
  1791.  
  1792. chkpass:
  1793.     LD    A,(wheel)
  1794.     INC    a
  1795.     RET    Z
  1796.     LD    A,(rootpass)
  1797.     CP    ' '
  1798.     jr    Z,norootp
  1799.     LD    HL,rootdrv
  1800.     LD    A,(maxdrv)
  1801.     DEC    a
  1802.     CP    (HL)
  1803.     jr    C,needpass
  1804.     LD    A,(maxusr)
  1805.     DEC    a
  1806.     INC    HL
  1807.     CP    (HL)
  1808.     RET    NC
  1809. needpass:
  1810.     LD    A,(password)
  1811.     CP    ' '
  1812.     CALL    Z,getpass
  1813.     LD    HL,rootpass
  1814.     LD    DE,password
  1815.     LD    b,8
  1816. rpasslop:
  1817.     LD    A,(DE)
  1818.     CP    (HL)
  1819.     jr    NZ,badpass
  1820.     CP    ' '
  1821.     jr    Z,norootp
  1822.     INC    DE
  1823.     INC    HL
  1824.     djnz    rpasslop
  1825. norootp:
  1826.  
  1827.     if    expand
  1828.  
  1829.     LD    HL,rootdrv
  1830.     LD    A,(maxdrv)
  1831.     CP    (HL)
  1832.     jr    NC,testusr
  1833.     LD    a,(HL)
  1834.     LD    (maxdrv),A
  1835. testusr:
  1836.     INC    HL
  1837.     LD    A,(maxusr)
  1838.     DEC    a
  1839.     CP    (HL)
  1840.     RET    NC
  1841.     LD    a,(HL)
  1842.     INC    a
  1843.     LD    (maxusr),A
  1844.  
  1845.     endif
  1846.  
  1847.     RET
  1848. badpass:
  1849.     POP    HL
  1850.     LD    DE,badpmsg
  1851.     JP    prnstr
  1852. badpmsg:
  1853.     DEFB    'Password Error',13,10,'$'
  1854.  
  1855.     endif        ;CCP
  1856.  
  1857. ;............
  1858. ;
  1859. ;CALL BDOS and return with Z flag status of function
  1860. ;
  1861. CBDOS:
  1862.     CALL    xbdos        ;Do the function
  1863.     OR    A        ;Set/clear the Z flag
  1864.     RET
  1865.  
  1866. ;................
  1867. ;
  1868. ;SCAN THE COMMAND LINE
  1869. ;
  1870. SCANLINE:
  1871.  
  1872.     if    ccp
  1873.  
  1874.     CALL    CRFLGA        ;Clear bits 7 & 5 if offset B4 of SCB
  1875.  
  1876.     endif        ;CCP
  1877.  
  1878.     LD    HL,CMDLINE+1    ;Point to command line start
  1879.     CALL    SIPBLNK        ;Skip over initial blanks
  1880.     CP    ';'        ;Is it a comment line?
  1881.     RET    Z        ;Ignore comment lines
  1882.  
  1883.     if    ccp
  1884.  
  1885.     CP    '!'        ;Command delimiter?
  1886.     jr    Z,DELIM        ;Jump if command delimiter
  1887.     CP    ':'        ;Conditional Execution (begins with colon)?
  1888.     jr    NZ,NOCOLON    ;Jump if not a colon
  1889.     
  1890.  
  1891.     if makecolon        ; needs to be non-destructive
  1892.  
  1893.                 ;If the error code is ff00-fffd or ffff
  1894.                 ;the command is "punted"  -mdk
  1895.  
  1896.     ld    a,(ix+2cH)    ;Test program return code for non-zero
  1897.     INC    a
  1898.     INC    a
  1899.     jr    Z,DELIM        ;If low byte is zero, then jump
  1900.     ld    a,(ix+2dH)    ;Test high byte for 0FFH
  1901.     INC    a
  1902.     RET    Z        ;Return if we are not to execute this
  1903.  
  1904.     endif    ; makecolon
  1905.  
  1906.  
  1907.  
  1908.     if not makecolon
  1909.  
  1910.     INC    (ix+2cH)    ;Test program return code for non-zero
  1911.     INC    (ix+2cH)
  1912.     jr    Z,DELIM        ;If low byte is zero, then jump
  1913.     INC    (ix+2dH)    ;Test high byte for 0FFH
  1914.     RET    Z        ;Return if we are not to execute this
  1915.                 ;command because of return code
  1916.     endif ; not makecolon
  1917.     
  1918.  
  1919. DELIM:
  1920.     INC    hl        ;skip over delimiter
  1921. NOCOLON:
  1922.  
  1923.     endif        ;CCP
  1924.  
  1925.     LD    (PFCB),HL    ;Save address of command
  1926.  
  1927. ;..........
  1928. ;
  1929. ;Loop to convert to upper case and check for second command
  1930. ;
  1931.  
  1932. NEXTCHAR:
  1933.     LD    A,(HL)        ;get char
  1934.     CALL    ucase        ;convert to upper case
  1935.     LD    (HL),A        ;put it back
  1936.  
  1937.     if    ccp
  1938.  
  1939.     CP    '!'        ;Is it command delimiter?
  1940.     CALL    Z,CHKEXCM    ;save 2nd command if present
  1941.  
  1942.     endif        ;CCP
  1943.  
  1944.     INC    HL        ;bump pointer
  1945.     OR    A        ;End of command line?
  1946.     jr    NZ,NEXTCHAR    ;loop for more
  1947.  
  1948. ;.............
  1949. ;
  1950. ;Skip over initial blanks
  1951. ;
  1952. SKIPBLA:
  1953.     LD    HL,(PFCB)    ;Get command address
  1954. SIPBLNK:
  1955.     LD    (PFCB),HL    ;Save new command address
  1956.     LD    (NXTNMA),HL    ;and Next command address
  1957.     LD    A,(HL)        ;Get char
  1958.     OR    A        ;End of command line?
  1959.     RET    Z        ;return if done
  1960.     CP    ' '        ;Is it a blank?
  1961.     jr    Z,SKPBLNK
  1962.     CP    9        ;Test for tab char too.
  1963.     RET    NZ    
  1964. SKPBLNK:
  1965.     INC    HL        ;Bump pointer
  1966.     jr    SIPBLNK        ;And loop for more
  1967.  
  1968.  
  1969.     if    ccp
  1970.  
  1971. ;................
  1972. ;
  1973. ;Save 2nd command in line by creating a dummy RSX of one page 
  1974. ;to protect the 2nd command after exclamation point
  1975. ;
  1976. CHKEXCM:
  1977.     LD    E,L
  1978.     LD    D,H        ;DE = HL
  1979.     INC    DE        ;DE points to next char after exclamation
  1980.     LD    A,(DE)        ;Get it
  1981.     CP    '!'        ;Is it another exclamation?
  1982.     PUSH    AF        ;save flags
  1983.     PUSH    HL        ;and char pointer
  1984.     CALL    Z,MOVETIL0    ;move command line down one notch to kill
  1985.                 ;2nd exclamation immediately after exclamation
  1986.     POP    HL        ;restore char pointer
  1987.     POP    AF        ;and flags
  1988.     RET    Z        ;ignore double exclamations
  1989.     LD    (HL),0        ;replace exclamation with null
  1990.     EX    DE,HL        ;char pointer in DE
  1991.     LD    HL,(BDOS+1)    ;get top of TPA
  1992.     DEC    H        ;Reserve 1 page for 2nd command
  1993.     LD    L,1ah        ;2nd command begins at offset 1bH in RSX;V1.03a
  1994.     PUSH    HL        ;save start of 2nd command addr
  1995.  
  1996. ;...............
  1997. ;
  1998. ;MOVE 2ND COMMAND LINE INTO PROTECTED PAGE
  1999. ;
  2000. MOV2ND:
  2001.     INC    HL        ;Bump these
  2002.     INC    DE        ;    pointers
  2003.     LD    A,(DE)        ;get source char
  2004.     LD    (HL),A        ;put in dest
  2005.     CP    '!'        ;Test for exclamation
  2006.     Jr    NZ,NOTEXCM    ;Jump if not exclamation
  2007.     LD    (HL),0DH    ;Replace all exclamations with CR
  2008. NOTEXCM:
  2009.     OR    A        ;End of command?
  2010.     Jr    NZ,MOV2ND    ;loop for more
  2011.     LD    (HL),0DH    ;Put a CR at end of command
  2012.     INC    HL
  2013.     LD    (HL),A        ;And a null after the CR
  2014.     LD    L,6
  2015.     LD    (HL),0C3H    ;Put a JMP inst at offset 6 in RSX
  2016.     INC    HL
  2017.     LD    (HL),9        ;Target of JMP is offset 9 
  2018.                 ;(Next in RSX header)
  2019.     INC    HL
  2020.     LD    (HL),H        ;Complete JMP inst
  2021.     INC    HL
  2022.     LD    (HL),0C3H    ;Put a JMP at location 9 in RSX
  2023.     LD    L,0EH        ;point to remove flag
  2024.     LD    (HL),A        ;clear remove flag
  2025.     ld    l,10h        ;where name goes            ;1.03a
  2026.     ld    de,next_cmnd    ;point to RSX name            ;1.03a
  2027.     EX    DE,HL        ;Setrsx likes it in DE
  2028.     ld    bc,8        ;length                    ;1.03a
  2029.     ldir            ;move it into place            ;1.03a
  2030.     LD    E,A        ;point to base of RSX
  2031.     CALL    SETRSX        ;Set up this RSX
  2032.     POP    DE        ;recover address of command line
  2033.     ld    e,19h        ;point to address of next command line    ;1.03a
  2034.     ld    a,(ix+31h)                        ;1.03a
  2035.     ld    (de),a                            ;1.03a
  2036.     inc    de                            ;1.03a
  2037.     ld    a,(ix+32h)                        ;1.03a
  2038.     ld    (de),a        ;save next 2nd command line addr    ;1.03a
  2039.     inc    de        ;start of 2nd command            ;1.03a
  2040.     LD    (ix+31H),E    ;Save command address for next time
  2041.                 ;CCP is executed
  2042.     LD    (ix+32H),D
  2043.     LD    (ix+2eH),D    ;Save the base page
  2044.     XOR    A        ;flag no errors
  2045.     RET
  2046.  
  2047. next_cmnd:
  2048.     db    'NEXTCMND'    ;RSX name for next command        ;1.03a
  2049.  
  2050.     endif        ;CCP
  2051.  
  2052. ;...................
  2053. ;
  2054. ;CONVERT TO UPPER CASE
  2055. ;
  2056. UCASE:
  2057.     AND    7fh
  2058.     CP    61H
  2059.     RET    C    
  2060.     CP    7BH
  2061.     RET    NC    
  2062.     SUB    ' '        ;Convert to upper case
  2063.     RET
  2064.  
  2065.     if    ccp
  2066.  
  2067. ;......................
  2068. ;
  2069. ;CHECK FOR SECOND COMMAND LINE
  2070. ;
  2071. CHK2ND:
  2072.     LD    DE,0BAB1H
  2073.     CALL    MOVSCB        ;Move offsets BA,BB to B1,B2 in SCB
  2074.     OR    A        ;Is address in offset BB valid?
  2075.     LD    DE,0BCB1H
  2076.     CALL    Z,MOVSCB    ;Move offsets BC,BD to B1,B2 if prev invalid
  2077.     CALL    STATINP        ;test for console break
  2078.     jr    NZ,NO2ND    ;Jump if console break
  2079. ;
  2080. ;GET ADDRESS AT B1,B2 INTO [DE] (2ND COMMAND LINE)
  2081. ;
  2082.     LD    D,(ix+32H)
  2083.     INC    d        ;Is address valid?
  2084.     DEC    d
  2085.     Jr    Z,NO2ND        ;Jump if no valid address (no 2nd command)
  2086.     LD    E,(ix+31H)
  2087.     LD    A,(DE)        ;Get first char from 2nd command
  2088.     OR    A        ;test for null
  2089.     RET    NZ        ;return if something there
  2090. NO2ND:            ;Here if no 2nd command 
  2091.     LD    H,(ix+2eh)    ;get base page
  2092.     LD    L,0EH        ;point to remove flag
  2093.     DEC    (HL)        ;set remove flag for removal
  2094.     ld    l,19h        ;point to addr of next 2nd command    ;1.03a
  2095.     ld    a,(hl)                            ;1.03a
  2096.     ld    (ix+31h),a                        ;1.03a
  2097.     inc    hl                            ;1.03a
  2098.     ld    a,(hl)                            ;1.03a
  2099.     ld    (ix+32h),a    ;save next 2nd command            ;1.03a
  2100.     ld    (ix+2eh),a    ;save base page of next 2nd command    ;1.03a
  2101.     JP    CHKRSX        ;and remove the dummy RSX
  2102.  
  2103.     endif        ;CCP
  2104.  
  2105. ;..................
  2106. ;
  2107. ;SET UP DEFAULT FCB
  2108. ;
  2109. SETDFFCB:
  2110.     LD    DE,FCB
  2111. ;
  2112. ;SET UP FCB AT [DE]
  2113. ;
  2114. SETFCB:
  2115.     CALL    SKIPBLA        ;Go over leading blanks and tabs
  2116.     PUSH    AF        ;save flags
  2117.     CALL    PARSEFCB    ;Parse the item into FCB
  2118.     POP    AF        ;restore flags
  2119.     RET
  2120. ;
  2121. ;PARSE THE COMMAND LINE INTO FCB
  2122. ;
  2123. PARSEFCB:
  2124.     LD    (PFCB),HL    ;Save item pointer
  2125.     LD    (NXTNMA),HL    ;and next item pointer
  2126.     PUSH    DE        ;save DE
  2127.     LD    DE,PFCB        ;point to parse file control block
  2128.     LD    C,152        ;parse FCB function
  2129.     CALL    xbdos        ;parse the FCB
  2130.     POP    DE        ;restore DE
  2131.     LD    A,H        ;Test for zero return
  2132.     OR    L
  2133.     LD    B,(HL)        ;get next char after parse into B
  2134.     INC    HL        ;go over delimiter or trailing blank
  2135.     Jr    NZ,NOTPEND    ;Jump if not end of command line
  2136.     LD    HL,NULCMD    ;Point to null command
  2137. NOTPEND:
  2138.     LD    A,H        ;Test for error return (0FFFFH)
  2139.     OR    L
  2140.     Jr    NZ,NOPERR    ;Jump if no error
  2141.     LD    HL,NULCMD    ;Point to null command
  2142.     CALL    ERRXIT        ;and process error
  2143. NOPERR:
  2144.     LD    A,B        ;get next char
  2145.     CP    '.'        ;is it dot (.)?
  2146.     Jr    NZ,NOPDOT    ;Jump if not dot
  2147.     DEC    HL        ;Adjust if dot
  2148. NOPDOT:
  2149.     LD    (PFCB),HL    ;Save new item pointer
  2150.     LD    C,16        ;16 bytes to move
  2151.     LD    HL,PRSEFCB    ;source
  2152.     PUSH    DE        ;save dest
  2153.     CALL    MOVEC        ;Move first 16 bytes into place
  2154.     LD    DE,PASSWORD    ;point to password field
  2155.     LD    C,10        ;10 bytes to move
  2156.     CALL    MOVEC        ;move the password into place
  2157.     POP    DE        ;restore DE
  2158.     LD    A,(HL)        ;get password length (PRSEFCB+26)
  2159.     LD    HL,0        ;init HL
  2160. NULCMD     EQU    $-1
  2161.     OR    A        ;test for no password
  2162.     LD    B,A        ;password length in B
  2163.     Jr    Z,NOPASS    ;Jump if no password
  2164.     LD    HL,(NXTNMA)    ;get next item pointer
  2165. FINDSEMI:
  2166.     LD    A,(HL)        ;get first char
  2167.     CP    ';'        ;is it password delimiter?
  2168.     INC    HL        ;bump pointer
  2169.     Jr    NZ,FINDSEMI    ;loop until ";" found
  2170. NOPASS:
  2171.     RET
  2172.  
  2173. ;...............
  2174. ;
  2175. ;CHECK FOR DRIVE SPEC IN COMMAND LINE
  2176. ;
  2177. CHKDRV:
  2178.     PUSH    DE        ;save DE
  2179.     XOR    A        ;Just a zero
  2180.     LD    (DE),A        ;clear to default user
  2181.     INC    DE
  2182.     LD    (DE),A        ;clear to default drive
  2183.     INC    DE        ;point to file name
  2184.     CALL    SKIPBLA        ;skip over leading blanks and tabs
  2185.     LD    HL,(PFCB)    ;get item address
  2186.     POP    DE        ;restore DE
  2187.     PUSH    DE
  2188.     LD    B,4        ;Colon (:) must be found with first 4 bytes
  2189. FNDCOLON:
  2190.     LD    A,(HL)        ;Get char
  2191.     CP    ':'        ;Is it colon?
  2192.     Jr    Z,COLONFND    ;Jump if colon
  2193.     OR    A        ;test for end of command line
  2194.     Jr    Z,ENDCOLON    ;jump if at end
  2195.     CP    ' '        ;is it a blank ?
  2196.     Jr    Z,endcolon
  2197.     CP    9        ;is it a tab ?
  2198.     Jr    Z,endcolon
  2199.     INC    HL        ;adjust pointer
  2200.     djNZ    FNDCOLON    ;loop for more
  2201. ENDCOLON:        ;Here if colon not found within first 4 bytes
  2202.     POP    DE        ;restore DE
  2203.     XOR    A        ;Just a zero
  2204.     LD    (DE),A        ;flag no user spec
  2205.     inc    DE        ;point to drive code    ; V1.02B
  2206.     ld    (DE),A        ;flag no drive spec    ; V1.02B
  2207.     dec    DE        ;point to user code    ; V1.02B
  2208.     LD    HL,(PFCB)    ;get item pointer
  2209. PASTCOLON:
  2210.     INC    DE        ;point to drive code
  2211.     LD    A,(DE)        ;get it
  2212.     PUSH    AF        ;save on stack
  2213.     CALL    PARSEFCB    ;parse first item into FCB
  2214.     POP    AF        ;restore drive spec
  2215.     LD    (DE),A        ;and restore it.
  2216.     RET
  2217.  
  2218.  
  2219. COLONFND:        ;Here if possible drive/user spec in command line
  2220.     LD    HL,(PFCB)    ;get item pointer
  2221.     LD    A,(HL)        ;get the char
  2222. NUMCHECK:
  2223.     CP    '0'        ;Numeric range check
  2224.     Jr    C,NOTNUM
  2225.     CP    ':'        ;Numeric range check
  2226.     Jr    NC,NOTNUM
  2227.     CALL    CVDEC        ;convert to User number in binary
  2228.     POP    DE        ;restore DE
  2229.     PUSH    DE
  2230.     LD    A,(DE)        ;get old user number
  2231.     OR    A        ;is there one already?
  2232.     Jr    NZ,ENDCOLON    ;invalid if user number specified twice
  2233.     LD    A,B        ;get the user number
  2234.     INC    A        ;adjust 
  2235.     LD    (DE),A        ;Save the user number spec
  2236.     Jr    CKDRV1        ;and go and check drive spec
  2237.  
  2238. ;.......
  2239. ;
  2240. ;check for possible drive spec
  2241. ;
  2242. NOTNUM:
  2243.     CP    'A'        ;Drive range check
  2244.     Jr    C,ENDCOLON
  2245.     CP    'Q'        ;Drive range check
  2246.     Jr    NC,ENDCOLON
  2247.     POP    DE        ;restore DE
  2248.     PUSH    DE
  2249.     INC    DE        ;point to drive spec
  2250.     LD    A,(DE)        ;get drive spec
  2251.     OR    A        ;test for drive spec
  2252.     Jr    NZ,ENDCOLON    ;jump if this is second drive spec
  2253.     LD    A,(HL)        ;Get new drive char
  2254.     SUB    40H        ;adjust
  2255.     LD    (DE),A        ;Save drive spec
  2256.     INC    HL        ;go over drive char
  2257. CKDRV1:
  2258.     LD    A,(HL)        ;get next char
  2259.     CP    ':'        ;Is it a colon?
  2260.     Jr    NZ,NUMCHECK    ;Loop until colon found
  2261.     INC    HL        ;go over colon
  2262.     POP    DE        ;restore DE
  2263.  
  2264.     if    ccp
  2265.  
  2266.     call    CHKDU        ;check the drive/user        ; V1.02B
  2267.  
  2268.     endif    ;CCP
  2269.  
  2270.     Jr    PASTCOLON    ;And continue with rest of command line
  2271.  
  2272.     if    ccp
  2273.  
  2274. CHKDU:
  2275.     LD    A,(wheel)    ;get wheel byte            ; V1.02B
  2276.     inc    a        ;is it set?            ; V1.02B
  2277.     ret    Z        ;yep, then no DU: check        ; V1.02B
  2278.     ex    de,hl        ;point to command user        ; V1.02B
  2279.     LD    A,(maxusr)    ;get max user # allowed        ; V1.02B
  2280.     CP    (HL)        ;within range?            ; V1.02B
  2281.     jr    C,invalid    ;return with CARRY set if not    ; V1.02B
  2282.     INC    HL        ;point to command drive        ; V1.02B
  2283.     LD    A,(maxdrv)    ;get max drive            ; V1.02B
  2284.     INC    a        ;adjust                ; V1.02B
  2285.     CP    (HL)        ;within range?            ; V1.02B
  2286.     dec    hl                        ; V1.02B
  2287.     ex    de,hl                        ; V1.02B
  2288.     ret    NC        ;ret with CARRY in proper state    ; V1.02B
  2289.  
  2290. invalid:
  2291.     LD    DE,baddu    ;point to Invalid drive/user msg
  2292.     call    prnstr        ;print msg
  2293.     jp    ccpret
  2294.  
  2295. baddu:
  2296.     DEFB    'Invalid Drive/User',13,10,'$'
  2297.  
  2298.  
  2299. ;.................
  2300. ;
  2301. ;MOVE 2 BYTES OF SCB FROM [D] TO [E]
  2302. ;
  2303. MOVSCB:
  2304.     LD    HL,(SCBBASE)    ;get SCB address
  2305.     LD    L,D        ;set source offset
  2306.     LD    D,H        ;set dest offset
  2307.     LD    C,2        ;2 bytes to move
  2308.  
  2309.     endif        ;CCP
  2310.  
  2311. ;................
  2312. ;
  2313. ;MOVE [HL] TO [DE] FOR LENGTH IN [C]
  2314. ;
  2315. MOVEC:
  2316.     push    bc
  2317.     ld    b,0
  2318.     ldir
  2319.     pop    bc
  2320.     dec    hl
  2321.     ld    a,(hl)
  2322.     inc    hl
  2323.     ret
  2324.  
  2325. ;....................
  2326. ;
  2327. ;MOVE [DE] TO [HL] UNTIL NULL
  2328. ;
  2329. MOVETIL0:
  2330.     LD    C,0        ;Set move terminator
  2331. MOVE1:
  2332.     LD    A,(DE)
  2333.     LD    (HL),A
  2334.     OR    A
  2335.     LD    A,C        ;Return length of move in A
  2336.     RET    Z        ;Return if at end
  2337.     INC    HL
  2338.     INC    DE
  2339.     INC    BC
  2340.     jr    MOVE1
  2341.  
  2342.     if    ccp
  2343.  
  2344. ;................
  2345. ;
  2346. ;SET BITS 7,5 IN OFFSET 0B4H in SCB
  2347. ;
  2348. SETFLG:
  2349.     set    7,(ix+34h)
  2350.     set    5,(ix+34h)
  2351.     ret
  2352.  
  2353. ;...............
  2354. ;
  2355. ;CLEAR BITS 7,5 IN OFFSET 0B4H
  2356. ;
  2357. CRFLGA:
  2358.     res    7,(ix+34h)
  2359.     res    5,(ix+34h)
  2360.     ret
  2361.  
  2362.     endif        ;CCP
  2363.  
  2364. ;..............
  2365. ;
  2366. ;GET SCB BYTE AT OFFset IN [B]
  2367. ;
  2368. GETSCB:
  2369.     LD    HL,(SCBBASE)        ;get SCB pointer
  2370.     LD    L,B        ;set the offset
  2371.     LD    A,(HL)        ;get the byte
  2372.     RET
  2373.  
  2374. ;..............
  2375. ;
  2376. ;PRINT CR,LF
  2377. ;
  2378. CRLF:
  2379.     LD    A,0DH
  2380.     CALL    CONOUT
  2381.     LD    A,0AH
  2382.     jp    CONOUT
  2383.  
  2384.     if    ccp
  2385.  
  2386. ;............
  2387. ;
  2388. ;Call RSX
  2389. ;
  2390. rsx:
  2391.     ld    c,60
  2392.     jp    xbdos
  2393.  
  2394.  
  2395. ;...............
  2396. ;
  2397. ;PRINT NUMBER IN [A]
  2398. ;
  2399. PRTNUM:
  2400.     ld    h,0
  2401.     ld    l,a
  2402. decout:
  2403.     push    hl
  2404.     push    de
  2405.     push    bc
  2406.     push    af
  2407.     ld    bc,-10
  2408.     ld    de,-1
  2409. decou1:
  2410.     add    hl,bc
  2411.     inc    de
  2412.     jr    c,decou1
  2413.     sbc    hl,bc
  2414.     ex    de,hl
  2415.     ld    a,h
  2416.     or    l
  2417.     call    nz,decout
  2418.     ld    a,e
  2419.     add    a,'0'
  2420.     call    cono
  2421.     pop    af
  2422.     pop    bc
  2423.     pop    de
  2424.     pop    hl
  2425.     ret
  2426.  
  2427.     else        ;if not CCP
  2428.  
  2429. xbdos:
  2430.     push    ix
  2431.     call    bdos
  2432.     pop    ix
  2433.     ret
  2434.  
  2435.     endif        ;not CCP
  2436.  
  2437. ;................
  2438. ;
  2439. ;PRINT STRING AT [HL] TERMINATED BY NULL OR CHAR IN [C]
  2440. ;
  2441. PRTNAME:
  2442.     LD    A,(HL)        ;get char
  2443.     OR    A        ;is it null?
  2444.     RET    Z    
  2445.     CP    C        ;is it same as char in C?
  2446.     RET    Z    
  2447.     CALL    CONOUT        ;print it
  2448.     INC    HL        ;bump pointer
  2449.     jr    PRTNAME        ;and loop
  2450.  
  2451. ;.............
  2452. ;
  2453. ;TEST FOR BLANKS AND ABORT IF BLANKS PRESENT
  2454. ;
  2455. CHKBLANK:
  2456.     CALL    SKIPBLA        ;skip over blanks
  2457.     RET    Z        ;return if non-blank found
  2458.  
  2459. ;...............
  2460. ;
  2461. ;ERROR EXIT SUBROUTINE
  2462. ;
  2463. ERRXIT:
  2464.  
  2465.     if    not ccp
  2466.  
  2467. ccpret:
  2468.  
  2469.     endif        ;not CCP
  2470.  
  2471.     LD    HL,msgflag    ;point to error count
  2472.     dec    (hl)        ;is it zero?
  2473.     inc    (hl)
  2474.     LD    (HL),0        ;reset it to zero
  2475.     RET    NZ        ;return if non-zero
  2476.     LD    HL,(nxtnma)    ;get command address
  2477.     LD    C,' '        ;print until blank or null
  2478.     CALL    prtname        ;print the first item in command line
  2479.     LD    DE,notfnm    ;point to "command not found" message
  2480.     CALL    prnstr        ;print command not found
  2481.  
  2482.     if    ccp
  2483.  
  2484.     jp    NOCOLD        ;and restart the CCP
  2485.  
  2486.     else        ;if not CCP
  2487.  
  2488.     rst    0
  2489.  
  2490.     endif        ;not CCP
  2491.  
  2492. notfnm:
  2493.     DEFB    ' command not found.$'
  2494.  
  2495. ;...............
  2496. ;
  2497. ;CONVERT ITEM IN COMMAND LINE TO BINARY
  2498. ;
  2499. CVNUM:
  2500.     CALL    SKIPBLA        ;skip over blanks
  2501.     LD    HL,(PFCB)    ;get item pointer
  2502.     LD    (NXTNMA),HL    ;save it
  2503.     RET    Z        ;return if nothing there
  2504.     LD    A,(HL)        ;get first char
  2505.     CP    '0'        ;numeric range check
  2506.     jr    C,ERRXIT
  2507.     CP    ':'        ;numeric range check
  2508.     jr    NC,ERRXIT
  2509.     CALL    CVDEC        ;convert to binary
  2510.     LD    (PFCB),HL    ;save new item pointer
  2511.     OR    1        ;set NZ return
  2512.     LD    A,B        ;return number in A
  2513.     RET
  2514.  
  2515. ;...............
  2516. ;
  2517. ;CONVERT ITEM TO BINARY NUMBER
  2518. ;
  2519. CVDEC:
  2520.     LD    B,0        ;start with 0
  2521. CVDECLP:    
  2522.     LD    A,(HL)        ;get char
  2523.     SUB    '0'        ;convert from ASCII to binary
  2524.     RET    C        ;return if out of range
  2525.     CP    10        ;numeric range check
  2526.     RET    NC        ;return if out of range
  2527.     PUSH    AF        ;save it
  2528.     LD    A,B        ;prepare to multiply B * 10
  2529.     ADD    A,A        ;*2
  2530.     ADD    A,A        ;*4
  2531.     ADD    A,B        ;*5
  2532.     ADD    A,A        ;*10
  2533.     LD    B,A
  2534.     POP    AF        ;restore number
  2535.     INC    HL        ;bump pointer
  2536.     ADD    A,B        ;add in current digit
  2537.     LD    B,A
  2538.     CP    16        ;must be less than 16
  2539.     jr    C,CVDECLP    ;loop if ok.
  2540.     jr    ERRXIT        ;otherwise an error
  2541.  
  2542.     if    ccp
  2543.  
  2544. ;.................
  2545. ;
  2546. ;PRINT FILENAME IN FCB POINTED TO BY [DE]
  2547. ;
  2548. PRTFNAME:
  2549.     INC    DE        ;point to filename
  2550.     LD    H,8        ;filename is 8 bytes
  2551.     CALL    PRTDESTR    ;print the filename
  2552.     CALL    PRTBLANK    ;print a blank
  2553.     LD    H,3        ;filetype is 3 bytes
  2554.  
  2555. ;...............
  2556. ;
  2557. ;PRINT STRING AT [DE] FOR LENGTH OF [H] BYTES
  2558. ;
  2559. PRTDESTR:
  2560.     LD    A,(DE)        ;get a char
  2561.     AND    7FH        ;strip parity
  2562.     CALL    CONOUT        ;print it
  2563.     INC    DE        ;bump pointer
  2564.     DEC    H        ;adjust count
  2565.     jr    NZ,PRTDESTR    ;loop for more
  2566.     RET
  2567.  
  2568. ;.............
  2569. ;
  2570. ;PRINT A BLANK
  2571. ;
  2572. PRTBLANK:
  2573.     LD    A,' '
  2574.  
  2575.     endif        ;CCP
  2576.  
  2577. ;.............
  2578. ;
  2579. ;CONSOLE OUTPUT WITH REGISTERS SAVED
  2580. ;
  2581. CONOUT:
  2582.     PUSH    BC
  2583.     PUSH    DE
  2584.     PUSH    HL
  2585.     CALL    CONO
  2586.     POP    HL
  2587.     POP    DE
  2588.     POP    BC
  2589.     RET
  2590.  
  2591. ;..................
  2592. ;
  2593. ;[HL] = [HL] + [A]
  2594. ;
  2595. ADDHLA:
  2596.     ADD    A,L
  2597.     LD    L,A
  2598.     RET    NC    
  2599.     INC    H
  2600.     RET
  2601.  
  2602. ;................
  2603. ;
  2604. ;COMPARE STRINGS [DE] TO [HL]
  2605. ;
  2606. COMPARE:
  2607.     LD    BC,0FFH        ;B = 0 , C = -1
  2608. CMPARE1:
  2609.     PUSH    DE        ;Save the 
  2610.     PUSH    HL        ;    pointers
  2611. CMPRLOOP:
  2612.     LD    A,(DE)        ;get a byte
  2613.     AND    7FH        ;strip parity
  2614.     CP    21h        ;is it non-blank and graphic?
  2615.     jr    C,COPARE2    ;jump if blank or non-graphic
  2616.     CP    (HL)        ;compare with target char
  2617.     jr    NZ,NOMATCH    ;jump if no match
  2618. COPARE2:
  2619.     INC    DE        ;bump source pointer
  2620.     INC    C        ;bump counter
  2621.     LD    A,' '
  2622.     CP    (HL)        ;at end of target string (terminated by blank)?
  2623.     INC    HL        ;bump target pointer
  2624.     jr    NZ,CMPRLOOP    ;jump if more to compare
  2625.     POP    HL        ;restore these
  2626.     POP    DE        ;    pointers
  2627.     CALL    MOVEC        ;move target string to source.. match found
  2628.     LD    A,B        ;A = string number
  2629.     RET
  2630. NOMATCH:        ;Here if no match found
  2631.     LD    A,' '
  2632. COMARE4:        ;Find end of target string
  2633.     CP    (HL)        ;are we at end?
  2634.     INC    HL        ;bump pointer
  2635.     jr    NZ,COMARE4
  2636.     POP    DE        ;align stack
  2637.     POP    DE        ;recover DE
  2638.     INC    B        ;bump string number
  2639.     LD    C,0FFH        ;init length
  2640.     LD    A,(HL)        ;get first char of next string
  2641.     SUB    1        ;end of list?
  2642.     jr    NC,CMPARE1    ;jump if more strings to compare
  2643.     RET
  2644.  
  2645.  
  2646.     if    ccphistory
  2647.  
  2648. ;
  2649. ;   >>>>>>--  COMMAND LINE HISTORY PROCESSING FOR CP/M PLUS --<<<<<<
  2650. ;
  2651. ;    (C) Copyright 1986 by Michael D. Kersenbrock, 18625 S.W. Hennig
  2652. ;    Court, Aloha, Oregon 97006  All rights Reserved.
  2653. ;
  2654. ;       Personal non-commercial use and distribution of this software
  2655. ;    is permitted so long as the above Copyright notice is maintained
  2656. ;    with this and subsequent copies.
  2657. ;
  2658. ;    History (no pun intended, but noted):
  2659. ;
  2660. ;        Version 1.0 - September 1986  Original release
  2661. ;
  2662. ;
  2663. ;  This was written first in psuedo HLL code, then hand coded into assembly
  2664. ;  language.  That psuedo-HLL code is included below as comment lines.
  2665. ;
  2666. ;Note: No matter how efficiently written, this isn't really practical without
  2667. ;      a ramdisk or a fast hard disk.  No strong effort is done to minimize
  2668. ;      the file size (and thus disk speed) because it isn't likely to 
  2669. ;      acceptably fast with a floppy (regardless). I use a FAST 720K ramdisk.
  2670. ;      Actually, I have tried it with my floppy, and it isn't too bad at all
  2671. ;      but then, the floppy IS cache'd.  I did my own cacheing over and above
  2672. ;      CP/M 3.0's (didn't like theirs), so I don't know how it works with
  2673. ;      DRI's version of cache. I have 178K of floppy-file cacheing.
  2674. ;
  2675. ;      This history implements "!!", "!pattern", "!number" for command
  2676. ;      substitution, and implements the command 'h' to give a list of 
  2677. ;      previous commands and their numbers.
  2678. ;
  2679. ;      These examples use '!' as the history command character, this is
  2680. ;      the same as Berkeley-UNIX's (tm of AT&T) CSH shell.  This CP/M
  2681. ;      implementation uses '|' interchangeably.  The functions implemented
  2682. ;      are:
  2683. ;
  2684. ;        !!            Repeat last command, similar to ^W
  2685. ;
  2686. ;        !<pattern>    Repeat last command that starts with
  2687. ;                the given pattern.
  2688. ;
  2689. ;        !<number>    Repeat command numbered <number>
  2690. ;
  2691. ;                EACH OF THE ABOVE THREE: append the rest of
  2692. ;                "this line" to the substituted line. Example:
  2693. ;
  2694. ;                   If command #40 were: "COMPILE -O -C", then
  2695. ;                   "!40 ROUTINE.C" would result in:
  2696. ;                   "COMPILE -O -C ROUTINE.C"
  2697. ;
  2698. ;        h        Command that gives numbered command history 
  2699. ;                list to be used with the above command.
  2700. ;
  2701. ;    When a history-substitution is made for a command, the new
  2702. ;    command line is presented to the console for editing in a
  2703. ;    similar fashion to the banked-^W command (unlike csh).
  2704. ;
  2705. ;    With the substitutions, the rest of the calling command line
  2706. ;    (if any) is added onto the substitution-replacement line.
  2707. ;
  2708. ;    If you don't want submit files to store their internal-commands
  2709. ;    into the history record, put a space in front of those commands.
  2710. ;
  2711. ;    If the file "<tempdisk>: CCP.EXT" exists, then that program is
  2712. ;    loaded into memory at address 6000H, then executed with HBUFFER 
  2713. ;    and CMDLINE address-pointers passed on the stack "above" the
  2714. ;       return address. CMDLINE's pointer is "just" above the return address.
  2715. ;
  2716. ;
  2717. ;    Data structure "buffer" has 42 CMDSIZE-byte records numbered 0-41.
  2718. ;
  2719. ;        defns: when file is read in, 
  2720. ;                record 1: contains the last command number
  2721. ;                record 2: contains the last command
  2722. ;            then...
  2723. ;                record 0: is where last command nr is moved to
  2724. ;                record 1: is where "translated" current command
  2725. ;                      is built.
  2726. ;    
  2727. ;        
  2728. ;History file format:
  2729. ;
  2730. ;        One command line per RECSIZE byte logical record.
  2731. ;
  2732. ;        First sector contains the current command number (1-byte)
  2733. ;
  2734. ;        Second sector contains the last command 
  2735. ;        Third sector contains the command before last 
  2736. ;                (etc.)
  2737. ;
  2738. ;        If the first byte of a sector is a null, we have
  2739. ;        "reached the end" of the history (null-commands are
  2740. ;        not stored).
  2741. ;
  2742. ;        The file saves the last 40 command lines.
  2743. ;
  2744. ;        A "command-line" has the first byte being the byte count,
  2745. ;        and a null-terminator just after the last "real" byte.
  2746. ;
  2747. ;            If a substituted command line is modified by the line
  2748. ;          editor (when given the opportunity), then this new changed
  2749. ;        version will be put into the history along with the one
  2750. ;        "fetched" from history.
  2751. ;
  2752. ; Pattern: String of non-space and non-control characters
  2753. ;
  2754. ;
  2755. ;
  2756. ; This history routine is called with a newly gotten command in the
  2757. ; CMDLINE buffer.  This routine will play games with the buffer (possibly
  2758. ; modifying its contents), then return.
  2759. ;
  2760.  
  2761. HBUFFER        EQU    2000H        ; Put buffer past CCP/STACK
  2762. ADRCCPEXT    EQU    6000H        ; Give buffer 16K of room
  2763. NRCMDS      EQU    40              ; Number of commands in history
  2764. NRRECS          EQU    NRCMDS + 2    ; Number of records in history buffer
  2765. RECSIZE        EQU    SIZECMDLINE + 4    ; Size of each record in history buffer
  2766. HBUFFSIZE    EQU    NRRECS * RECSIZE  ; The buffer's size
  2767. NRSECTORS    EQU    (HBUFFSIZE/128)+1 ; sector count of file
  2768. HIST1        EQU    '!'        ; Unix csh compatible history char
  2769. HIST2        EQU    '|'        ; Alternate easier to hit
  2770. RCORD0        EQU    HBUFFER        ; Address of record-0
  2771. RCORD1        EQU    HBUFFER+RECSIZE ; Address of record-1
  2772. RCORD2        EQU    HBUFFER+2*RECSIZE ; Address of record-2
  2773.  
  2774. HISTORY:
  2775.  
  2776. ;    if (Command length == 0 || cmd starts w/' ' or ':') {
  2777.  
  2778.     ld    a,(CMDLINE)    ; get command's length
  2779.     or    a        ; zero length?
  2780.  
  2781. ;        return();
  2782.  
  2783.     ret    z        ; yep, punt
  2784.     ld    a,(CMDLINE + 1);
  2785.     cp    ' '        ; space?
  2786.     ret    z
  2787.     cp    ':'
  2788.     ret    z
  2789.  
  2790. ;    }
  2791. ;    buffer is cleared to nulls
  2792.  
  2793.     ld    de,HBUFFER    ; Point to history buffer
  2794.     ld    bc,HBUFFSIZE    ; Indicate size
  2795.     call    CLRBUF        ; Clear it to zeros
  2796.  
  2797.  
  2798. ;    Check to see if "temp:Historyx.dat" exists
  2799. ;
  2800. ;    if (exists) {
  2801. ;        readfile into data buffer starting at record-1 point
  2802. ;    }
  2803. ;
  2804.  
  2805.     call    GETHIST        ; load history buffer
  2806.  
  2807. ;    read command number from record-1, and write it to record-0 
  2808.  
  2809.     ld    a,(RCORD1)     ; fetch the last command's number
  2810.  
  2811.     ld    (RCORD0),a    ; put it into place at record-0
  2812.  
  2813. ;    reset substitution and error flags;
  2814.     
  2815.     xor    a        ; get a zero
  2816.     ld    (FLAGSUB),a    ; reset substitution-happened flag
  2817.     ld    (HERROR),a    ; reset error flag
  2818.  
  2819.  
  2820.  
  2821. ;    if (first-char == '!') {
  2822.  
  2823.     ld     hl,CMDLINE+1    ; point to first character
  2824.     ld    a,(HL)        ; get that character
  2825.     call    ISHISTCHAR    ; one of the history-triggering characters?
  2826.     jp    nz,HST1        ; nope, go...
  2827.  
  2828. ;        if (2nd char == '!') {
  2829.  
  2830.     inc    hl        ; point to second character
  2831.     ld    a,(HL)        ; get it
  2832.     call     ISHISTCHAR    ; is it a history-triggering character?
  2833.     jr    nz,HST2        ; nope, go...
  2834.  
  2835. ;            copy line at record-2 to record-1;
  2836.  
  2837.     ld    hl,RCORD2    ; put record-2's address into source register
  2838.     ld    de,RCORD1    ; put record-1's address into dest register
  2839.     ld    bc,RECSIZE    ; load size of a record
  2840.     ldir            ; do the copy
  2841.  
  2842. ;            copy rest of cmdline onto end of the record-1 line;
  2843.  
  2844.     ld    hl,CMDLINE+3    ; point to rest of command line
  2845.     ld    de,RCORD1    ; point at line to put it at
  2846.     call    CMDCAT        ; concatinate the command lines
  2847.  
  2848. ;            set substitution flag;
  2849.     ld    a,1
  2850.     ld    (FLAGSUB),a    ; set substitution-happened flag
  2851.     jp    HST3
  2852.  
  2853. ;        }
  2854. ;        else if (rest up to a terminator is numeric) {
  2855.  
  2856. HST2:
  2857.  
  2858.     call    ISNUMERIC    ; numeric?
  2859.     jp    nc,HST4        ; nope
  2860. HST21:
  2861.     inc    hl        ; yep, so it MIGHT be a numeric substitution
  2862.     ld    a,(hl)        ; get next character
  2863.     call    ISNUMERIC    ; numeric?
  2864.     jr    c,HST21        ; yep, look at next character
  2865.     cp    ' '+1        ; a "proper" terminator?
  2866.     jp    nc,HST4        ; nope
  2867.                 ; yep
  2868.  
  2869. ;            translate number to binary;
  2870.  
  2871.     push    hl        ; save pointer to "rest-of-command-line".
  2872.     call    ATOI        ; value is now in DE, rest of cmd is at (HL)
  2873.  
  2874. ;            if ( command number wanted is NOT in our list ) {
  2875.  
  2876.     ld    a,(RCORD0)    ; get command number for entry at record-2
  2877.     ld    d,a
  2878.     ld    a,e
  2879.     sub    d        ; calculate difference  reqnr - cmdnr
  2880.     dec    a        ; correct boundary condition
  2881.     and    63        ; make modulo-64 loop-around
  2882. HST7:    cp    64-NRCMDS    ; range within history database size?
  2883.     jr    c,HST5        ; nope, go do error dance
  2884.     ld    d,a
  2885.     ld    a,65
  2886.     sub    d        ; calculate record number for our data
  2887.     call    RECADDR        ; calculate address of that record into HL
  2888.     ld    a,(hl)        ; get count of that record
  2889.     or    a        ; set flags, is this an active record?
  2890.     jr    nz,HST6        ; yes, so number is effectively valid
  2891.                 ; no
  2892.     
  2893. HST5:
  2894.  
  2895.     pop    hl        ; clean stack
  2896. ;                clear cmd line
  2897.  
  2898.     ld    hl,0        ; get a double-zero
  2899.     ld    (CMDLINE),hl    ; zero command line count, and nul terminate it
  2900.  
  2901. ;                print "not found"
  2902.  
  2903.     ld    hl,HERR1    ; point to error message
  2904.     ld    c,0        ; indicate null-termination
  2905.     call    PRTNAME
  2906.     call    CRLF
  2907.  
  2908. ;                set errorflag;
  2909.  
  2910.     ld    a,1
  2911.     ld    (HERROR),a
  2912. ;                break out from first level 'if'
  2913.  
  2914.     jp    HST8
  2915.  
  2916. ;            }
  2917. ;            else {
  2918.  
  2919. HST6:
  2920.  
  2921. ;                copy record[(cmdnr-number+1)] to record-1;
  2922.  
  2923.     ;
  2924.     ; we enter with the substitution record already pointed to by HL
  2925.     ;
  2926.     
  2927.     ld    de,RCORD1    ; load destination address
  2928.     ld    bc,RECSIZE    ; load size of record
  2929.     ldir            ; do the copy
  2930.  
  2931. ;            copy rest of cmdline onto end of the record-1 line;
  2932.  
  2933.     pop    hl        ; get back pointer to rest-of-command-line
  2934.     ld    de,RCORD1    ; point at line to put it at
  2935.     call    CMDCAT        ; concatinate the command lines
  2936.  
  2937. ;                set substitution flag;
  2938.  
  2939.     ld    a,1
  2940.     ld    (FLAGSUB),a
  2941.  
  2942. ;            }
  2943.     jp    HST3
  2944. ;        }
  2945. ;        else {
  2946.  
  2947. HST4:
  2948.  
  2949. ;            search (bottom-up) for a string match (no white space)
  2950.  
  2951.     ld    b,1        ; initialize record counter
  2952. HST44:    inc    b        ; point to next record
  2953.     ld    a,b        ; get record number
  2954.     cp    NRRECS        ; already checked "last" one?
  2955.     jr    nc,HST10     ; yep, none matched
  2956.     call    RECADDR        ; get pointer to next record to check
  2957.     inc    hl        ; point to first character in string
  2958.     push    hl        ; save database string pointer
  2959.     ex    de,hl        ; put record pointer into DE
  2960.     ld    hl,CMDLINE+2    ; point at first character after !/|
  2961.     call    CMPSTRG        ; string match?
  2962.     pop    de        ; get database string pointer back
  2963.     jr    nc,HST44    ; nope, try next one
  2964.                 ; yep, we found it
  2965.  
  2966. ;            if (found) {
  2967. ;                copy that line to record-1;
  2968.  
  2969.     ;
  2970.     ; We enter with the substitution record already pointed to by DE,
  2971.     ; and the "rest of the commandline" pointed to by HL.
  2972.     ;
  2973.     
  2974.     push    hl        ; save "rest of commandline"
  2975.     ex    de,hl        ; put found matching-line-pointer into src pntr
  2976.     dec    hl        ; point back to byte count part of record
  2977.     ld    de,RCORD1    ; load destination address
  2978.     ld    bc,RECSIZE    ; load size of record
  2979.     ldir            ; do the copy
  2980.  
  2981. ;                copy rest of cmd line onto end of record-1 line
  2982.  
  2983.     pop    hl        ; get pointer to "rest of commandline"
  2984.     ld    de,RCORD1    ; point to the line we just fetched above
  2985.     call    CMDCAT        ; concatinate the lines
  2986.  
  2987.  
  2988. ;                set substitution flag;
  2989.  
  2990.     ld    a,1
  2991.     ld    (FLAGSUB),a
  2992.     jp    HST11
  2993.  
  2994. ;            }
  2995. ;            else {    
  2996.  
  2997. HST10:
  2998. ;                clear cmd line
  2999. ;                print "not found"
  3000. ;                set errorflag;
  3001. ;                break out from first level 'if'
  3002.  
  3003.     jp    HST5    ; does same as needed here, so we'll save a byte or two
  3004.  
  3005. ;            }
  3006.  
  3007. HST11:
  3008.  
  3009. ;        }
  3010.  
  3011. HST3:
  3012.  
  3013. ;        copy record-1 to cmdline;
  3014.  
  3015.     ld    hl,RCORD1    ; load source pointer
  3016.     ld    de,CMDLINE    ; load destination
  3017.     ld    bc,SIZECMDLINE  ; max size
  3018.     ldir            ; do the copying
  3019.     jp    HST8    
  3020.  
  3021. ;
  3022. ;    }
  3023. ;    else if (1st char == 'h' && 2rd char == terminator) {
  3024.  
  3025. HST1:
  3026.     ld    hl,CMDLINE+1    ; point to first character
  3027.     ld    a,(hl)        ; get it
  3028.     cp    'h'        ; an 'h'?
  3029.     jp    nz,HST9        ; nope
  3030.     inc    hl        ; point to second character
  3031.     ld    a,(hl)        ; get that one also
  3032.     cp    ' '+1        ; a terminator?
  3033.     jp    nc,HST9        ; nope, so go handle "regular" command
  3034.  
  3035. ;        reset substitution flag, and set err flag
  3036.  
  3037.     xor    a        ; get a zero
  3038.     ld    (FLAGSUB),a    ; reset substitution flag
  3039.     inc    a        ; get nonzero
  3040.     ld    (HERROR),a    ; set error flag
  3041.  
  3042. ;        print cmd lines w/numbers to screen
  3043.  
  3044.  
  3045.     call    CRLF        ; start on fresh line
  3046.     ld    a,(RCORD0)    ; get cmd number of record at record-2
  3047.     sub    NRCMDS-1    ; calculate number of last record
  3048.     and    63        ; modulo 64
  3049.     ld    b,a        ; put into record counter location
  3050.     dec    b        ; pre-decrement for proper start
  3051.     ld    c,NRRECS    ; load record counter
  3052. HST111:
  3053.     ld    a,b        ; get command number
  3054.     inc    a        ; increment to next command number
  3055.     and    63        ; do modulo 64
  3056.     ld    b,a        ; put counter back
  3057.     dec    c        ; count to next record number
  3058.     ld    a,c        ; get it
  3059.     cp    2        ; Done with all of them?
  3060.     jp    c,HST8        ; yep
  3061.     call    RECADDR        ; nope, so go get pointer to record
  3062.     ld    a,(hl)        ; get byte count of that record
  3063.     or    a        ; a null-line?
  3064.     jr    z,HST111    ; yes, don't display those
  3065.     inc    hl        ; no, so point to the line's data
  3066.     push    bc        ; save counters
  3067.     push    hl        ; save that data pointer for a second
  3068.     ld    a,b        ; get command number
  3069.     cp    10        ; single digit?
  3070.     call    c,PRTBLANK    ; yes, align display columns
  3071.     ld    a,b        ; get command number
  3072.     call    PRTNUM        ; print it
  3073.     call    PRTBLANK    ; print a space
  3074.     call    PRTBLANK    ; print a space
  3075.     pop    hl        ; get data pointer to historical cmd line
  3076.     ld    c,0        ; indicate null-termination
  3077.     call    PRTNAME        ; print the string
  3078.     call    CRLF        ; and complete the line
  3079.     pop    bc        ; get our counters back
  3080.     jp    HST111        ; do next command line in history
  3081.  
  3082.  
  3083. ;    }
  3084. ;    else {
  3085.  
  3086. HST9:
  3087.  
  3088. ;        copy cmdline to record-1
  3089.  
  3090.     ld    hl,CMDLINE
  3091.     ld    de,RCORD1
  3092.     ld    bc,RECSIZE
  3093.     ldir
  3094.  
  3095. ;    }
  3096.  
  3097.  
  3098. HST8:
  3099.  
  3100.  
  3101. ;    if (not ERRORFLAG) {
  3102.  
  3103.     ld    a,(HERROR)    ;get error flag
  3104.     or    a        ;errors?
  3105.     jr    nz,HST13    ;yep, so don't change the history database
  3106.  
  3107. ;        increment command number at 0 ;
  3108.  
  3109.     ld    a,(RCORD0)    ;get the command number
  3110.     inc    a        ;increment it
  3111.     and    63        ;modulo 64
  3112.     ld    (RCORD0),a    ;put it back
  3113.  
  3114. ;        if (first-char-of-cmd is printable, and not ' ' or ':') {
  3115.  
  3116.     ld    a,(RCORD1+1)    ; get first byte of new command string
  3117.     cp    ' '+1        ; ctl char or space?
  3118.     jr    c,HST88        ; yep, so don't save line in history
  3119.     cp    ':'        ; colon?
  3120.     jr    z,HST88        ; yep, so don't save line in history
  3121.  
  3122. ;            write buffer starting at record0 (bumps last one out)
  3123.  
  3124.     call    PUTHIST        ;save history back to file in ramdisk
  3125.  
  3126. ;        }
  3127.  
  3128. HST88:    jr    HST99
  3129.  
  3130. ;    }
  3131. ;    else {
  3132. ;        reset command line;
  3133. HST13: 
  3134.     ld    hl,0        ; get a zero
  3135.     ld    (CMDLINE),hl    ; reset command line
  3136.     jr    hst14
  3137.  
  3138. ;    }
  3139.  
  3140. HST99:
  3141. ;
  3142. ;    if (substitution flag set) {
  3143.  
  3144.     ld    a,(FLAGSUB)    ;get substitution flag
  3145.     or    a        ;was the command line modified?
  3146.     jr    z,HST14        ;nope, so just process normally
  3147.                 ;yes
  3148.  
  3149. ;        calculate checksum of cmdline;
  3150.  
  3151.     ld    hl,CMDLINE-1    ; point to full command line buffer
  3152.     call    CMDSUM        ; calculate it's checksum
  3153.     ld    (HCMDSUM),de    ; save it
  3154.  
  3155. ;        set DMA address to cmdline;
  3156.  
  3157.     ld    de,CMDLINE-1    ; put buffer's address into DE
  3158.     call     SETDMA        ; set the dma address
  3159.     
  3160. ;        set DE to zero and call function 10 (edit substitution line);
  3161.  
  3162.     call    CRLF
  3163.     call    prompt        ; print a prompt
  3164.     ld    de,0        ; indicate that the buffer is loaded
  3165.     ld    c,10        ; function number 10
  3166.     call    xbdos        ; allow line be be edited
  3167.     call    SDEFDMA        ; put Dma back to default value
  3168.     ld    hl,CMDLINE    ; point to new command line
  3169.     ld    a,(hl)        ; fetch count
  3170.     inc    hl        ; point to first char
  3171.     call    addhla        ; calculate where just-past-end-is
  3172.     xor    a        ; get a zero
  3173.     ld    (hl),a        ; terminate string 
  3174.  
  3175. ;        if (new checksum != old checksum) {
  3176.  
  3177.     ld    hl,CMDLINE-1    ;point to command line buffer again
  3178.     call    CMDSUM        ;calulate checksum again
  3179.     ld    hl,(HCMDSUM)    ;get previous checksum
  3180.     or    a        ;reset carry
  3181.     sbc    hl,de        ;checksum the same (no change by user)?
  3182.  
  3183. ;            go through self again;
  3184.  
  3185.     jp    nz,HISTORY    ;do again if it was changed 
  3186.                 ;incase it was modified for substitution
  3187.                 ;again (silly operator).  Also we will put
  3188.                 ;this new version into the history.
  3189. ;        }
  3190.  
  3191.  
  3192.  
  3193. HST15:
  3194.  
  3195. ;    }
  3196.  
  3197. HST14:
  3198. ;
  3199. ;    command line now contains command line, ready for "normal" processing.
  3200.  
  3201.     ret
  3202.  
  3203.     ;
  3204.     ; Clear buffer pointed to by DE that is of size BC
  3205.     ;
  3206. CLRBUF:
  3207.     push    hl        ; save whatever
  3208.     ld     l,e        ; load hl with
  3209.     ld     h,d        ;        de
  3210.     ld     (hl),0        ; load first location in block
  3211.     inc     de        ; point the "to" pointer at second location
  3212.     dec      bc        ; count the one we did "manually"
  3213.     ldir            ; block move the rest
  3214.     pop     hl        ; get whatever back
  3215.     ret            ; all pau
  3216.  
  3217.  
  3218.     ;
  3219.     ; Calculate and return address of record number in 'a'
  3220.     ; Return value in HL
  3221.     ;
  3222. RECADDR:
  3223.     push     bc        ; save whatever
  3224.     ld      hl,0        ; zero accumulator
  3225.     ld      bc,RECSIZE    ; load size of ONE record
  3226. CALCADR: sub    1        ; set carry (borrow) flag
  3227.     jr     c,RECEXIT    ; calculated offset?
  3228.     add     hl,bc        ; nope, add in another record size
  3229.     jr     CALCADR        ; test it again
  3230. RECEXIT:
  3231.     ld      bc,HBUFFER    ; load start address of the buffer itself
  3232.     add     hl,bc        ; add in the calculated offset
  3233.     pop     bc        ; restore whatever
  3234.     ret
  3235.  
  3236.  
  3237.     ;
  3238.     ; Opens History file and loads buffer at record-1.  Hbuffer is assumed
  3239.     ; to be already cleared upon entry.
  3240.     ;
  3241. GETHIST:
  3242.     call     OPENHIST    ; open history file
  3243.     jr     nz,CLOSEHIST    ; close if only now created
  3244.     ld       e,NRSECTORS    ; Get size of file (16K max)
  3245.     ld       c,2ch        ; get bdos nr for setting multi-sectors
  3246.     call     xbdos        ; set that many sectors
  3247.     ld      de,RCORD1    ; get record-1's address into DE
  3248.     call    SETDMA        ; set the dma address
  3249.     call    GETBLK        ; read that many sectors all at once
  3250.     jr       CLOSEHIST    ; close file
  3251.  
  3252. GETBLK:
  3253.     ld       de,HFCB        ; point DE at history's FCB
  3254.     ld       c,14h        ; get bdos number for read sequential
  3255.     call     xbdos        ; read file into buffer
  3256.     push    af        ; save return value
  3257.     ld       e,1        ; set multi-sector count back to one
  3258.     ld       c,2ch        ; get bdos nr for setting multi-sectors
  3259.     call     xbdos        ; set that many sectors
  3260.     pop    af        ; get read status back
  3261.     ret
  3262.     
  3263.  
  3264.     ;
  3265.     ; Writes out History file from buffer at record-0.
  3266.     ; Also closes the file.
  3267.     ;
  3268. PUTHIST:
  3269.     call     OPENHIST    ; Open history file
  3270.     ld       e,NRSECTORS    ; Get size of file (16K max)
  3271.     ld       c,2ch        ; get bdos nr for setting multi-sectors
  3272.     call     xbdos        ; set that many sectors
  3273.     ld       de,RCORD0    ; get record-0's address into DE
  3274.     call     SETDMA        ; set the dma address
  3275.     xor    a        ; get a zero
  3276.     ld    (HFCBCR),a    ; zero "cr" field of the FCB
  3277.     ld       de,HFCB        ; point DE at history's FCB
  3278.     ld       c,15h        ; get bdos number for write sequential
  3279.     call     xbdos        ; write file from buffer
  3280.     ld       e,1        ; set multi-sector count back to one
  3281.     ld       c,2ch        ; get bdos nr for setting multi-sectors
  3282.     call     xbdos        ; set that many sectors 
  3283.  
  3284.  
  3285. CLOSEHIST:
  3286.  
  3287.     ld       de,HFCB        ; point at history's FCB again
  3288.     ld       c,10h        ; get bdos number for file closing
  3289.     call       xbdos        ; close file, then return
  3290.     jp    SDEFDMA        ; reset DMA address back to default
  3291.  
  3292.  
  3293.     ;
  3294.     ; Find and open/create history file on the "TEMP" disk.
  3295.     ;
  3296.     ; Returns: ZeroFlag   SET if file existed
  3297.     ;                RESET if file just created
  3298.     ;
  3299.  
  3300. OPENHIST:
  3301.     ld    hl,HNAME    ; load source of extension file's name
  3302.     ld    de,HFCB+1    ; load addr of FCB Name-field
  3303.     ld    bc,11        ; load size of CPM name
  3304.     ldir            ; move it
  3305.     ld    a,(usernum)    ; get user number
  3306.     add    a,'A'        ; make unique and printable
  3307.     ld    (HFCBUSER),a    ; make history file unique to user number
  3308.     ld     a,(ix+6ch)    ; get temp file drive
  3309.     ld    (HFCB),a    ; put into FCB
  3310.     xor    a        ; get a zero
  3311.     ld    (HFCBCR),a    ; zero "cr" field of the FCB
  3312.  
  3313.  
  3314.     ;
  3315.     ; Opens file at HFCB, the name is assumed
  3316.     ; to be already loaded, and it is assumed to be on the temp drive.
  3317.     ;
  3318.     ; 
  3319.  
  3320. OPENTEMP:
  3321.     call    OPENEXIST    ; Open existing file 
  3322.     ret    z        ; return with existing file opened
  3323.     ld    c,16h        ; didn't exist, so get make-file bdos number
  3324.     ld    de,HFCB        ; make sure still pointed at FCB
  3325.     call    xbdos        ; create file
  3326.     ld    a,1        ; un-set zero flag
  3327.     or    a
  3328.     ret
  3329.  
  3330.     ;
  3331.     ; Opens file at FCB if it already exists.
  3332.     ; Returns: Zero flag SET with Success 
  3333.     ;       Zero flag RESET if file doesn't already exist
  3334.  
  3335. OPENEXIST:
  3336.     ld     a,(ix+6ch)    ; get temp file drive
  3337.     ld    (HFCB),a    ; put into FCB
  3338.     ld    de,HFCB2    ; point just past name
  3339.     ld    bc,26        ; size of FCB past name
  3340.     call    CLRBUF        ; clear out FCB
  3341.     ld    de,HFCB        ; point to History file FCB
  3342.     ld    c,0fh        ; open file bdos code
  3343.     call    xbdos        ; open the file
  3344.     or    a        ; set flags, did file exist?
  3345.     ret            ; zero flag set if it did exist
  3346.  
  3347.     ;
  3348.     ; Translate numeric string at (HL) into binary, and return
  3349.     ; value in DE, and HL pointing just after the number (which is
  3350.     ; where it entered at).
  3351.     ;
  3352.     ; It is assumed that the input stream has already been checked
  3353.     ; for at least a single numeric character and that only the
  3354.     ; two LSB's count anyway.
  3355.  
  3356. ATOI:  push    hl        ;save pointer to "just after the number"
  3357.     ld    d,0        ;init our accumulator
  3358.     dec    hl        ;point to LSB character
  3359.     ld    a,(hl)        ;get character
  3360.     call    ATOB        ;convert to binary
  3361.     ld    e,a        ;finish accumulator initialization
  3362.     dec    hl        ;point to next-LSB character
  3363.     ld    a,(hl)        ;get next character
  3364.     call    ISNUMERIC    ;We have a second digit?
  3365.     jr    nc,ATOIEXIT    ;nope, so exit already
  3366.     call    ATOB        ;convert to binary
  3367.     ex    de,hl        ;put accumulator into hl
  3368.     ld    de,10        ;tens digit
  3369. ATOI4:    sub    1
  3370.     jr    c,ATOI5
  3371.     add    hl,de        ;add a ten
  3372.     jr    ATOI4
  3373. ATOI5:  ex    de,hl        ;put accumlator back
  3374.  
  3375. ATOIEXIT:
  3376.     pop    hl        ;get the "just after" pointer
  3377.     ret
  3378.     
  3379.     ;
  3380.     ; Convert ascii numeral in 'a' to binary 
  3381.     ; return: CARRY FLAG SET indicates ERROR
  3382.     ;
  3383. ATOB:    sub    '0'        ; subtract ascii offset
  3384.     ret    c        ; punt if ascii was not numeric (too low)
  3385.     cp    10        ; test to see if it was (too high) numeric
  3386.     ccf            ; make same sense as first test
  3387.     ret
  3388.     
  3389.  
  3390.     ;
  3391.     ; Calculates checksum of command line string pointed to by HL,
  3392.     ; returning that 16-bit checksum in DE
  3393.     ; 
  3394.     ; The format of the command line string is assumed to be
  3395.     ; that as returned by a BDOS-10 call.
  3396.     ;
  3397. CMDSUM:
  3398.     inc    hl        ;point at byte count
  3399.     ld    b,(hl)        ;get number of bytes
  3400.     ld    de,0        ;initialize checksum
  3401. SUMLOOP:
  3402.     inc    hl        ;point at next character
  3403.     ld    a,(hl)        ;get it
  3404.     add    a,e        ;add partially to checksum
  3405.     jr    nc,SUMLP2    ;carry into checksum MSB?
  3406.     inc    d        ;yep, do the carry
  3407. SUMLP2: ld    e,a        ;reassemble checksum
  3408.     djnz    SUMLOOP        ;do for entire string
  3409.     ret            ;and done.
  3410.  
  3411.  
  3412.  
  3413.     ;
  3414.     ; Compares string at (HL) with string at (DE) returning
  3415.     ; CARRY FLAG: SET if equal
  3416.     ; CARRY FLAG: RESET if different
  3417.     ;
  3418.     ; Returns with both DE and HL pointers pointing just one past
  3419.     ; the matching-string (when it matches).
  3420.     ;
  3421.     ; Controlling string is at (HL).  This string, up to it's first
  3422.     ; non-alphanumeric, is tested for equality to that at (DE).
  3423.     ; Comparison is not case sensitive.
  3424.     ;
  3425. CMPSTRG:
  3426.     push    bc
  3427. CMPAGN:    ld    a,(hl)        ;get controlling string
  3428.     cp    '!'        ;alpha numeric (printable)?
  3429.     jr    c,CMPST2     ;nope, HL ended first, so strings matched
  3430.     call    UCASE        ;make sure upper case
  3431.     ld    b,a        ;save for a sec.
  3432.     ld    a,(de)        ;get other string's char
  3433.     call    UCASE        ;make sure upper case
  3434.     cp    b        ;strings match?
  3435.     inc    hl        ;     (update
  3436.     inc    de        ;        pointers to next in strings)
  3437.     jr    z,CMPAGN    ;yup they match, do next character
  3438.     or    a        ;reset carry flag
  3439. CMPST2:    pop    bc
  3440.     ret            ;return a no-match
  3441.  
  3442.  
  3443.     ;
  3444.     ; This checks to see if the ascii character in register
  3445.     ; 'a' is the history-mechanism's invocation character
  3446.     ; (or it's alternate).
  3447.     ;
  3448.     ; Modifies nothing but flags
  3449.     ;
  3450.     ; Returns: ZERO FLAG SET if it is one of those characters
  3451.     ;       ZERO FLAG RESET if NOT one
  3452. ISHISTCHAR:
  3453.     cp    HIST1
  3454.     ret    z
  3455.     cp    HIST2
  3456.     ret
  3457.  
  3458.  
  3459.     ;
  3460.     ; This checks to see if the ascii character in register
  3461.     ; 'a' is numeric.
  3462.     ;
  3463.     ; Modifies nothing but flags
  3464.     ;
  3465.     ; Returns: CARRY FLAG SET if it is numeric
  3466.     ;       CARRY FLAG RESET if NOT numeric
  3467.  
  3468. ISNUMERIC:
  3469.     cp    '0'
  3470.     ccf    
  3471.     ret    nc
  3472.     cp    '9'+1
  3473.     ret
  3474.  
  3475.  
  3476.     ;
  3477.     ; Concatinate the null-terminated string pointed to by HL to
  3478.     ; the "command-format" string pointed to by DE.  The DE string
  3479.     ; has only the string-length and a null-terminated string.
  3480.     ;
  3481. CMDCAT:
  3482.     push    de        ; save pointer to string length
  3483.     ld    a,(de)        ; get current string length
  3484.     ld    b,a        ; install into our length counter
  3485.     inc    de        ; point at the string's first character
  3486.     push     hl        ; save source string for a second
  3487.     ex    de,hl        ; calculate where the command's null is at
  3488.     call    ADDHLA
  3489.     ex      de,hl        ; put destination pointer into DE
  3490.     pop    hl        ; put source string pointer into HL
  3491. CMDCT2:
  3492.     ld    a,(hl)        ; get source character
  3493.     or    a        ; null terminator?
  3494.     jr    z,CMDCT3    ; yep, go clean up
  3495.     ld    (de),a        ; nope, load it to the destination
  3496.     inc    hl        ; update..
  3497.     inc    de        ;     .. both src/dest pointers to next char
  3498.     inc    b        ; count the added character
  3499.     ld    a,b        ; get that count
  3500.     cp    SIZECMDLINE    ; combined length too long?
  3501.     jr    c,CMDCT2    ; nope, go do another character
  3502.                 ; yep, so it's exit time prematurely
  3503. CMDCT3: xor    a        ; get a null
  3504.     ld    (de),a        ; null-terminate destination string
  3505.     pop    hl        ; get back pointer to destination's byte count
  3506.     ld    (hl),b        ; update it to the new length
  3507.     ret
  3508.     
  3509.  
  3510.  
  3511.     ;
  3512.     ; Looks for file "tempdisk: CCP.EXT".  If it exists, it is loaded
  3513.     ; at address ADRCCPEXT, and passed HBUFFER (two above) and
  3514.     ; CMDLINE (just above) the return address on the stack.
  3515.     ;
  3516.     ; Upon CCP.EXT's Return: "Return value" is to be returned in register
  3517.     ; HL and it normally should be a zero.  If it is non-zero, then
  3518.     ; the internal history mechanism will be bypassed.  
  3519.     ;
  3520.     ; The basic idea here is that additional "shell" concepts could
  3521.     ; be implemented in a HLL ("C" being thought of in particular).
  3522.     ; Like this history mechanism, this probably is only practical
  3523.     ; with systems with bank-switched RAMDISK.  My system executes
  3524.     ; this history mechanism with no noticeable pause.  My "temp-disk"
  3525.     ; is a 720K DMA-driven bank-switching RAMDISK.  My floppies are
  3526.     ; 8" DSDD 1.2MB each.  I have no hard disk to try it out on.
  3527.     ; My Z80 runs at 5Mhz with no waitstates.
  3528.     ;
  3529.     ;
  3530. CCPEXT:
  3531.     ld    hl,HEXTNAME        ; load source of extension file's name
  3532.     ld    de,HFCB+1        ; load addr of FCB Name-field
  3533.     ld    bc,11            ; load size of CPM name
  3534.     ldir                ; move it
  3535.     call    OPENEXIST        ; try to open the file
  3536.     jr    nz,CCPEX2        ; exit if not successful
  3537.     xor    a            ; get a zero
  3538.     ld    (HFCBCR),a        ; zero "cr" field of the FCB
  3539.     ld    hl,ADRCCPEXT        ; get starting address
  3540.     ld    de,0
  3541. CCPEX1: add    hl,de            ; calculate next address
  3542.     push    hl            ; save it
  3543.     ex    de,hl            ; put into de
  3544.     call    SETDMA            ; point DMA there
  3545.     call    GETBLK            ; read a block
  3546.     pop    hl            ; get dma pointer back
  3547.     ld    de,128            ; sector size
  3548.     or    a            ; last sector?
  3549.     jr    z,CCPEX1        ; nope, so read another
  3550.     call    CLOSEHIST
  3551.     ld    hl,HBUFFER        ; get pointer to history buffer
  3552.     push    hl            ; 
  3553.     ld    hl,CMDLINE        ; get pointer to incoming command line
  3554.     push    hl
  3555.     call    ADRCCPEXT        ; call loaded program
  3556.     ld    a,h            ; get..
  3557.     or    l            ;     ....hl value
  3558.     pop    hl
  3559.     pop    hl            ; clean stack
  3560.     ret
  3561. CCPEX2: xor    a            ; set zero flag
  3562.     ret                ;
  3563.     
  3564.  
  3565.     
  3566.     
  3567.     
  3568.  
  3569. HEXTNAME:    defb    'CCP     EXT'
  3570. HNAME:        defb    'HISTORY DAT'
  3571. HERR1:        defb    0dh,0ah,'Substitution not found',0
  3572. HFCB:        defb    0,'HISTORY'
  3573. HFCBUSER:    defb    ' '
  3574.         defb    'DAT'
  3575. HFCB2:        defw    0,0,0,0,0,0,0,0,0,0
  3576. HFCBCR:        defb    0,0,0,0,0,0,0,0,0
  3577. FLAGSUB:    defb    0
  3578. HERROR:        defb    0
  3579. HCMDSUM:    defw    0
  3580.  
  3581.  
  3582. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  3583. ;;;;;;;;;;;;;;;;;;;;;;;                    ;;;;;;;;;;;;;;;;;;;;;;
  3584. ;;;;;;;;;;;;;;;;;;;;;;;        END OF HISTORY MODULE    ;;;;;;;;;;;;;;;;;;;;;;
  3585. ;;;;;;;;;;;;;;;;;;;;;;;                    ;;;;;;;;;;;;;;;;;;;;;;
  3586. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  3587.  
  3588.     endif    ;ccphistory
  3589.  
  3590.  
  3591. ;..................
  3592. ;
  3593. ;MESSAGES
  3594. ;
  3595.  
  3596. msgflag:    DEFB    0
  3597. SCBPB:        DEFB    3ah,0
  3598. PFCB:        DEFW    0
  3599.         DEFW    PRSEFCB
  3600.  
  3601.     if    not ccp
  3602.  
  3603. lbrcmp:        defb    0,'           ',0,0
  3604. lbrfcb:        defb    0,0,'COMMAND LBR',0,0,0,0
  3605.         defs    21
  3606.  
  3607.     else        ;if CCP
  3608.  
  3609. USER0MSG:    DEFB    ' (User 0)$'
  3610. rootrsx:    DEFB    65
  3611. rsx66:        DEFB    66
  3612. diradr:        DEFW    0
  3613. rootname:    DEFS    9
  3614. rootpass:    DEFS    9
  3615. rootdrv:    DEFS    1
  3616. rootusr:    DEFS    1
  3617. datpb:        DEFS    4
  3618.  
  3619.     endif
  3620.  
  3621. subflag:    defs    1
  3622. USERNUM:    DEFs    1
  3623. DISKNUM:    DEFs    1
  3624. CURDSK:        DEFs    1
  3625. NXTNMA:        DEFS    2
  3626. CMDPTR:        DEFS    2
  3627. BOFFSET:    DEFS    1
  3628. BDOSBASE:    DEFS    1
  3629.  
  3630.     if    not ccp
  3631.  
  3632. searoff:    ds    2
  3633. searflg:    ds    2
  3634. duspec:        ds    1
  3635. usrsav:        ds    2
  3636. buff:        defs    128
  3637. scbbase:    defs    2
  3638. memaddr:    defs    2
  3639. lbrsec:        defs    2
  3640. typeflag:    defs    1
  3641.  
  3642.     endif
  3643.  
  3644. PASSWORD:    DEFS    10
  3645. CMDFCB:        DEFS    1
  3646. FILEDISK:    DEFS    1
  3647. FILENAME:    DEFS    8
  3648. FILETYPE:    DEFS    24
  3649. LOADADDR:    DEFS    2
  3650. PRSEFCB:    DEFS    37
  3651. CMDLINE:    DEFS    138H
  3652.  
  3653.     if not ccphistory
  3654.  
  3655. STACK     EQU    $
  3656.  
  3657.     endif ; not ccphistory
  3658.  
  3659.     if ccphistory
  3660.  
  3661. STACK   EQU    1300H
  3662.  
  3663.     endif ; ccphistory
  3664.  
  3665.     END
  3666.     ;ccphistory
  3667.  
  3668.  
  3669. ;..................
  3670. ;
  3671. ;MESSAGES
  3672. ;
  3673.  
  3674. msgflag:    DEFB    0
  3675. SCBPB:        DEFB    3ah,0
  3676. PFCB:        DEFW