; The following equates may be used to customize this CCP for the user's ; system and integration technique. The following constants are provided: ; ; REL - TRUE if integration is to be done via MOVCPM ; - FALSE if integration is to be done via DDT and SYSGEN ; ; BASE - Base Address of user's CP/M system (normally 0 for DR version) ; This equate allows easy modification by non-standard CP/M (eg,H89) ; ; CCPLOC - Base Page Address of CCP; this value can be obtained by running ; the BDOSLOC program on your system, or by setting the ; MSIZE and BIOSEX equates to the system memory size in ; K-bytes and the "extra" memory required by your BIOS ; in K-bytes. BIOSEX is zero if your BIOS is normal size, ; and can be negative if your BIOS is in PROM or in ; non-contiguous memory. ; ; RAS - Remote-Access System; setting this equate to TRUE disables ; certain CCP commands that are considered harmful in a Remote- ; Access environment; use under Remote-Access Systems (RBBS) for ; security purposes ; REL EQU FALSE ;SET TO TRUE FOR MOVCPM INTEGRATION ; BASE EQU 0 ;BASE OF CP/M SYSTEM (SET FOR STANDARD CP/M) ; IF REL CCPLOC EQU 0 ;MOVCPM IMAGE ELSE ; ; If REL is FALSE, the value of CCPLOC may be set in one Š; of two ways. The first way is to set MSIZE and BIOSEX ; as described above using the following three lines: ; MSIZE EQU 64 ;SIZE OF MEM IN K-BYTES BIOSEX EQU 2 ;EXTRA # K-BYTES IN BIOS CCPLOC EQU 3400H+(MSIZE-20-BIOSEX)*1024 ;CCP ORIGIN ; ; The second way is to obtain the origin of your current ; CCP using BDSLOC or its equivalent, then merely set CCPLOC ; to that value as as in the following line: ; ;CCPLOC EQU 0BD00H ;FILL IN WITH BDOSLOC SUPPLIED VALUE ; ; Note that you should only use one method or the other. ; Do NOT define CCPLOC twice! ; ; The following gives the required offset to load the CCP into the ; CP/M SYSGEN Image through DDT (the Roffset command); Note that this ; value conform (see Location 4: the ; most significant nybble contains the User Number and the least significant ; nybble contains the Disk Number). ; ; Some user programs (such as SYNONYM3) attempt to use the default ; command facility. Under the original CCP, it was necessary to initialize ; the pointer after the reserved space for the command buffer to point to ; the first byte of the command buffer. Under Version 4.x of CCPZ, this is ; no longer the case. The CIBPTR (Command Input Buffer PoinTeR) is located ; to be compatible with such programs (provided they determine the buffer ; length from the byte at MBUFF [CCPLOC + 6]), but under Version 4.x of CCPZ ; this is no longer necessary. CCPZ Version 4.x automatically initializes ; this buffer pointer in all cases. ; ENTRY: Š JMP CCP ; Process potential default command JMP CCP1 ; Do NOT process potential default command ; ;**** Section 1 **** ; ; BUFFERS ET AL ; ; INPUT COMMAND LINE AND DEFAULT COMMAND ; ; The command line to be executed is stored here. This command line ; is generated in one of three ways: ; ; (1) by the user entering it through the BDOS READLN function at ; the du> prompt [user input from keyboard] ; (2) by the SUBMIT File Facility placing it there from a $$$.SUB ; file ; (3) by an external program or user placing the required command ; into this buffer ; ; In all cases, the command line is placed into the buffer starting at ; CIBUFF. This command line is terminated by the last character (NOT Carriage ; Return), and a character count of all characters in the command line ; up to and including the last character is placed into location CBUFF ; (immediately before the command line at CIBUFF). The placed command line ; is then parsed, interpreted, and the indicated command is executed. ; If CLEVEL3 is permitted, a terminating zero is placed after the command ; (otherwise the user program has to place this zero) and the CIBPTR is ; properly initialized (otherwise the user program has to init this ptr). ; If the command is placed by a user program, entering at CCPLOC is enough ; to have the command processed. Again, under CCPZ Version 4.x, it is not ; necessary to store the pointer to CIBUFF in CIBPTR; CCPZ will do this for ; the calling program if CLEVEL3 is made TRUE. ; ; WARNING: The command line must NOT exceed BUFLEN characters in length. ; For user programs which load this command, the value of BUFLEN can be ; obtained by examining the byte at MBUFF (CCPLOC + 6). ; BUFLEN EQU 80 ;MAXIMUM BUFFER LENGTH MBUFF: DB BUFLEN ;MAXIMUM BUFFER LENGTH CBUFF: DB 0 ;NUMBER OF VALID CHARS IN COMMAND LINE CIBUFF: DB ' ' ;DEFAULT (COLD BOOT) COMMAND CIBUF: DB 0 ;COMMAND STRING TERMINATOR DB ' CCPZ-V4.1 of 11/27/81 ' ;FOR DUMP IDENTIFICATION DS BUFLEN-($-CIBUFF)+1 ;TOTAL IS 'BUFLEN' BYTES ; CIBPTR: DW CIBUFF ;POINTER TO COMMAND INPUT BUFFER CIPTR: DW CIBUF ;PTR TO CURR CMD FOR ERROR REPORTING ; DS 26 ;STACK AREA ŠSTACK EQU $ ;TOP OF STACK ; ; FILE TYPE FOR COMMAND ; COMMSG: DB 'COM' ; ; SUBMIT FILE CONTROL BLOCK ; SUBFCB: IF SUBA ;IF $$$.SUB ON A: DB 1 ;DISK NAME SET TO DEFAULT TO DRIVE A: ENDIF ; IF NOT SUBA ;IF $$$.SUB ON CURRENT DRIVE DB 0 ;DISK NAME SET TO DEFAULT TO CURRENT DRIVE ENDIF ; DB '$$$' ;FILE NAME DB ' ' DB 'SUB' ;FILE TYPE DB 0 ;EXTENT NUMBER DB 0 ;S1 SUBFS2: DS 1 ;S2 SUBFRC: DS 1 ;RECORD COUNT DS 16 ;DISK GROUP MAP SUBFCR: DS 1 ;CURRENT RECORD NUMBER ; ; COMMAND FILE CONTROL BLOCK ; FCBDN: DS 1 ;DISK NAME FCBFN: DS 8 ;FILE NAME FCBFT: DS 3 ;FILE TYPE DS 1 ;EXTENT NUMBER DS 2 ;S1 AND S2 DS 1 ;RECORD COUNT FCBDM: DS 16 ;DISK GROUP MAP FCBCR: DS 1 ;CURRENT RECORD NUMBER ; ; OTHER BUFFERS ; PAGCNT: DB NLINES-2 ;LINES LEFT ON PAGE CHRCNT: DB 0 ;CHAR COUNT FOR TYPE ; ; CCP BUILT-IN COMMAND TABLE Š; NCHARS EQU 4 ;NUMBER OF CHARS/COMMAND ; ; CCP COMMAND NAME TABLE ; EACH TABLE ENTRY IS COMPOSED OF THE 4-BYTE COMMAND AND 2-BYTE ADDRESS ; CMDTBL: DB 'DIR ' DW DIR DB 'LIST' DW LIST DB 'TYPE' DW TYPE DB 'USER' DW USER DB 'DFU ' DW DFU ; IF NOT RAS ;FOR NON-RAS DB 'GO ' DW GO DB 'ERA ' DW ERA DB 'SAVE' DW SAVE DB 'REN ' DW REN DB 'GET ' DW GET DB 'JUMP' DW JUMP ENDIF ; NCMNDS EQU ($-CMDTBL)/(NCHARS+2) ; ; ;**** Section 2 **** ; CCP STARTING POINTS ; ; START CCP AND DON'T PROCESS DEFAULT COMMAND STORED ; CCP1: XRA A ;SET NO DEFAULT COMMAND STA CBUFF ; ; START CCP AND POSSIBLY PROCESS DEFAULT COMMAND ; ; NOTE ON MODIFICATION BY RGF: BDOS RETURNS 0FFH IN ; ACCUMULATOR WHENEVER IT LOGS IN A DIRECTORY, IF ANY ; FILE NAME CONTAINS A '$' IN IT. THIS IS NOW USED AS ; A CLUE TO DETERMINE WHETHER OR NOT TO DO A SEARCH ; FOR SUBMIT FILE, IN ORDER TO ELIMINATE WASTEFUL SEARCHES. ; CCP: LXI SP,STACK ;RESET STACK Š PUSH B MOV A,C ;C=USER/DISK NUMBER (SEE LOC 4) RAR ;EXTRACT USER NUMBER RAR RAR RAR ANI 0FH MOV E,A ;SET USER NUMBER CALL SETUSR CALL RESET ;RESET DISK SYSTEM STA RNGSUB ;SAVE SUBMIT CLUE FROM DRIVE A: POP B MOV A,C ;C=USER/DISK NUMBER (SEE LOC 4) ANI 0FH ;EXTRACT DEFAULT DISK DRIVE STA TDRIVE ;SET IT JRZ NOLOG ;SKIP IF 0...ALREADY LOGGED CALL LOGIN ;LOG IN DEFAULT DISK ; IF NOT SUBA ;IF $$$.SUB IS ON CURRENT DRIVE STA RNGSUB ;BDOS '$' CLUE ENDIF ; NOLOG: LXI D,SUBFCB ;CHECK FOR $$$.SUB ON CURRENT DISK RNGSUB EQU $+1 ;POINTER FOR IN-THE-CODE MODIFICATION MVI A,0 ;2ND BYTE (IMMEDIATE ARG) IS THE RNGSUB FLAG ORA A ;SET FLAGS ON CLUE CMA ;PREPARE FOR COMING 'CMA' CNZ SEAR1 CMA ;0FFH IS RETURNED IF NO $$$.SUB, SO COMPLEMENT STA RNGSUB ;SET FLAG (0=NO $$$.SUB) LDA CBUFF ;EXECUTE DEFAULT COMMAND? ORA A ;0=NO JRNZ RS1 ; ; PROMPT USER AND INPUT COMMAND LINE FROM HIM ; RESTRT: LXI SP,STACK ;RESET STACK ; ; PRINT PROMPT (DU>) ; CALL CRLF ;PRINT PROMPT CALL GETDRV ;CURRENT DRIVE IS PART OF PROMPT ADI 'A' ;CONVERT TO ASCII A-P CALL CONOUT CALL GETUSR ;GET USER NUMBER ; IF SUPRES ;IF SUPPRESSING USR # REPORT FOR USR 0 ORA A JRZ RS000 ENDIF ; CPI 10 ;USER < 10? JRC RS00 Š SUI 10 ;SUBTRACT 10 FROM IT PUSH PSW ;SAVE IT MVI A,'1' ;OUTPUT 10'S DIGIT CALL CONOUT POP PSW RS00: ADI '0' ;OUTPUT 1'S DIGIT (CONVERT TO ASCII) CALL CONOUT ; ; READ INPUT LINE FROM USER OR $$$.SUB ; RS000: CALL REDBUF ;INPUT COMMAND LINE FROM USER (OR $$$.SUB) ; ; PROCESS INPUT LINE ; RS1: ; IF CLEVEL3 ;IF THIRD COMMAND LEVEL IS PERMITTED CALL CNVBUF ;CAPITALIZE COMMAND LINE, PLACE ENDING 0, ; AND SET CIBPTR VALUE ENDIF ; CALL DEFDMA ;SET TBUFF TO DMA ADDRESS CALL GETDRV ;GET DEFAULT DRIVE NUMBER STA TDRIVE ;SET IT CALL SCANER ;PARSE COMMAND NAME FROM COMMAND LINE CNZ ERROR ;ERROR IF COMMAND NAME CONTAINS A '?' LXI D,RSTCCP ;PUT RETURN ADDRESS OF COMMAND PUSH D ;ON THE STACK LDA TEMPDR ;IS COMMAND OF FORM 'D:COMMAND'? ORA A ;NZ=YES JNZ COM ; IMMEDIATELY CALL CMDSER ;SCAN FOR CCP-RESIDENT COMMAND JNZ COM ;NOT CCP-RESIDENT MOV A,M ;FOUND IT: GET LOW-ORDER PART INX H ;GET HIGH-ORDER PART MOV H,M ;STORE HIGH MOV L,A ;STORE LOW PCHL ;EXECUTE CCP ROUTINE ; ; ENTRY POINT FOR RESTARTING CCP AND LOGGING IN DEFAULT DRIVE ; RSTCCP: CALL DLOGIN ;LOG IN DEFAULT DRIVE ; ; ENTRY POINT FOR RESTARTING CCP WITHOUT LOGGING IN DEFAULT DRIVE ; RCCPNL: CALL SCANER ;EXTRACT NEXT TOKEN FROM COMMAND LINE LDA FCBFN ;GET FIRST CHAR OF TOKEN SUI ' ' ;ANY CHAR? LXI H,TEMPDR ORA M JNZ ERROR Š JR RESTRT ; ; No File Error Message ; PRNNF: CALL PRINTC ;NO FILE MESSAGE DB 'No Fil','e'+80H RET ; ;**** Section 3 **** ; I/O UTILITIES ; ; OUTPUT CHAR IN REG A TO CONSOLE AND DON'T CHANGE BC ; ; ; OUTPUT ; CRLF: MVI A,CR CALL CONOUT MVI A,LF ;FALL THRU TO CONOUT ; CONOUT: PUSH B MVI C,02H OUTPUT: MOV E,A PUSH H CALL BDOS POP H POP B RET ; CONIN: MVI C,01H ;GET CHAR FROM CON: WITH ECHO JR BDOSB ; LCOUT: PUSH PSW ;OUTPUT CHAR TO CON: OR LST: ;SET NEW VALUE DJNZ NUM1 ;COUNT DOWN ; ; RETURN FROM NUMBER ; NUM2: MOV A,C ;GET ACCUMULATED VALUE RET ; ; NUMBER ERROR ROUTINE FOR SPACE CONSERVATION ; NUMERR: JMP ERROR ;USE ERROR ROUTINE - THIS IS RELATIVE PT ; ; EXTRACT HEXADECIMAL NUMBER FROM COMMAND LINE ; RETURN WITH VALUE IN REG A; ALL REGISTERS MAY BE AFFECTED ; HEXNUM: CALL SCANER ;PARSE NUMBER AND PLACE IN FCBFN HNUM0: LXI H,FCBFN ;PT TO TOKEN FOR CONVERSION LXI D,0 ;DE=ACCUMULATED VALUE MVI B,11 ;B=CHAR COUNT HNUM1: MOV A,M ;GET CHAR CPI ' ' ;DONE? JRZ HNUM3 ;RETURN IF SO CPI 'H' ;DONE IF H SUFFIX JRZ HNUM3 SUI '0' ;CONVERT TO BINARY JRC NUMERR ;RETURN AND DONE IF ERROR CPI 10 ;0-9? JRC HNUM2 SUI 7 ;A-F? CPI 10H ;ERROR? JRNC NUMERR HNUM2: INX H ;PT TO NEXT CHAR MOV C,A ;DIGIT IN C MOV A,D ;GET ACCUMULATED VALUE RLC ;EXCHANGE NYBBLES RLC RLC RLC ANI 0F0H ;MASK OUT LOW NYBBLE MOV D,A MOV A,E ;SWITCH LOW-ORDER NYBBLES RLC RLC RLC Š RLC MOV E,A ;HIGH NYBBLE OF E=NEW HIGH OF E, ; LOW NYBBLE OF E=NEW LOW OF D ANI 0FH ;GET NEW LOW OF D ORA D ;MASK IN HIGH OF D MOV D,A ;NEW HIGH BYTE IN D MOV A,E ANI 0F0H ;MASK OUT LOW OF E ORA C ;MASK IN NEW LOW MOV E,A ;NEW LOW BYTE IN E DJNZ HNUM1 ;COUNT DOWN ; ; RETURN FROM HEXNUM ; HNUM3: XCHG ;RETURNED VALUE IN HL MOV A,L ;LOW-ORDER BYTE IN A RET ; ; PT TO DIRECTORY ENTRY IN TBUFF WHOSE OFFSET IS SPECIFIED BY A AND C ; DIRPTR: LXI H,TBUFF ;PT TO TEMP BUFFER ADD C ;PT TO 1ST BYTE OF DIR ENTRY CALL ADDAH ;PT TO DESIRED BYTE IN DIR ENTRY MOV A,M ;GET DESIRED BYTE RET ; ; CHECK FOR SPECIFIED DRIVE AND LOG IT IN IF NOT DEFAULT ; SLOGIN: XRA A ;SET FCBDN FOR DEFAULT DRIVE STA FCBDN CALL COMLOG ;CHECK DRIVE RZ JR DLOG5 ;DO LOGIN OTHERWISE ; ; CHECK FOR SPECIFIED DRIVE AND LOG IN DEFAULT DRIVE IF SPECIFIED<>DEFAULT ; DLOGIN: CALL COMLOG ;CHECK DRIVE RZ ;ABORT IF SAME LDA TDRIVE ;LOG IN DEFAULT DRIVE ; DLOG5: JMP LOGIN ; ; ROUTINE COMMON TO BOTH LOGIN ROUTINES; ON EXIT, Z SET MEANS ABORT ; COMLOG: TEMPDR EQU $+1 ;POINTER FOR IN-THE-CODE MODIFICATION MVI A,0 ;2ND BYTE (IMMEDIATE ARG) IS TEMPDR ORA A ;0=NO RZ DCR A ;COMPARE IT AGAINST DEFAULT LXI H,TDRIVE Š CMP M RET ;ABORT IF SAME ; ; EXTRACT TOKEN FROM COMMAND LINE AND PLACE IT INTO FCBDN; ; FORMAT FCBDN FCB IF TOKEN RESEMBLES FILE NAME AND TYPE (FILENAME.TYP); ; ON INPUT, CIBPTR PTS TO CHAR AT WHICH TO START SCAN; ; ON OUTPUT, CIBPTR PTS TO CHAR AT WHICH TO CONTINUE AND ZERO FLAG IS RESET ; IF '?' IS IN TOKEN ; SCANER: XRA A ;A=0 TO START AT DRIVE SPECIFICATION