home *** CD-ROM | disk | FTP | other *** search
-
- *
- * ENHANCED CP/M CONSOLE COMMAND PROCESSOR (CCP) for CP/M REV. 2.2
- *
- * Origianl CCP disassembled by ????
- * Original CCP disassembled further by RLC
- * Original CCP commented by RLC
- * Modified and generalized by John Thomas (6/20/81)
- * Macros expanded and condtional for terminals which
- * use form feeds to clear the screen added by
- * Bo McCormick (6/27/81)
- *
- ***** ASSEMBLING THIS CCP FOR CP/M 2.2 *****
- * You must be using a Z-80 processor to run this
- * program. You do not need MAC or any macro library.
- * If you add further modifications to the program
- * the total size of the program must not exceed
- * 2K in order to fit under the BDOS. Set the CCPLOC equate
- * to the memory location of the CCP in your system.
- * Once assembled, the hex file of this CCP program can be
- * "patched" into your sytem using DDT as outlined in the
- * CP/M 2 Alteration Guide.
- * Code must be added to use the Clear Screen command with
- * your terminal. Equates exist for the Hazeltine 1500,
- * the Heath/Zenith H19/H89, and any terminal which uses
- * a form feed to clear the screen.
- * Also, there is a provision for a boot-up command. Place
- * the command to be executed on cold and warm starts at
- * location CBUFF.
- *
- ***** NON-STANDARD FEATURES *****
- * The non-standard features incorporated into this CCP are:
- * A. The Command-Search Hierarchy, as follows --
- * 1. Scan for a CCP-resident command and execute it if
- * found
- * 2. If not CCP-resident, look for a .COM file on disk
- * 3. If the .COM file is not found in the current user
- * area and the current user area is not USER 0,
- * USER 0 is selected and scanned for the file
- * 4. If the .COM file is not found on the current
- * logged-in disk drive, drive A: is selected
- * and scanned for the file
- * B. The DIR Command no longer prints the current drive spec
- * at the beginning of each line
- * C. The TYPE Command pages its output
- * D. A LIST Command now exists which is like TYPE but does not
- * page and sends its output to the LST: device
- * E. A CLS (Clear Screen) Command now exists which clears the
- * screen of the terminal
- * F. The user number is printed as part of the command prompt;
- * the prompt is now du>, such as A0> and A15>
- * G. Z80-code is used throughout to reduce the size of the CCP
- * and give room to implement the additional functions
- * H. The input line buffer has been reduced in size to 100 bytes
- * I. The ERA Command displays the names of the files it is to
- * erase
- * J. The DIR Command has an additional special form of "DIR @"
- * which displays all files (both non-system and system),
- * while "DIR" displays just the non-system files
- * K. The Directory Display no longer displays the disk name at
- * the beginning of each line and it now includes a '.' between
- * the file name and file type (FILENAME.TYP)
- * L. The SUBMIT File Facility now expects the $$$.SUB file to be
- * on the currently logged-in disk (as opposed to always A:)
- * M. The Command Line Prompt is now '$' if the command comes from
- * a $$$.SUB file and '>' if the command comes from the user;
- * also, the '>' is not printed until all preprocessing is
- * completed
- * N. The TYPE and LIST Commands mask the MSB of each byte, so that
- * files created by editors such as EDIT80 are "printable"
- *
-
- FALSE EQU 0
- TRUE EQU NOT FALSE
-
- CCPLOC EQU 3400H+1400H ; START OF CCP IN MEMORY
- ; REPLACE WITH VALUE
- ; FOR YOUR SYSTEM
-
- NLINES EQU 16 ; NUMBER OF LINES ON CRT SCREEN
-
- H19 EQU FALSE ; USING HEATH H19/H89 TERMINAL
- HAZE EQU FALSE ; USING HAZELTINE 1500 TERMINAL
- FFTERM EQU TRUE ; USING TERMINAL THAT RESPONDS TO 0CH
- ; OR ANY CHARACTER IF YOU CHANGE THE
- ; VALUE OF FF BELOW
-
- CR EQU 0DH
- LF EQU 0AH
- TAB EQU 09H
- FF EQU 0CH ;<==== CHANGE THIS BYTE IF TERMINAL
- ESC EQU 1BH ; NEEDS A DIFFERENT CHARACTER
- ; TO CLEAR THE SCREEN
-
-
- WBOOT EQU 0000H ; CP/M WARM BOOT ADDRESS
- UDFLAG EQU 0004H ; USER NUMBER IS IN HIGH NYBBLE, DISK IN LOW
- BDOS EQU 0005H ; BDOS FUNCTION CALL ENTRY PT
- TBUFF EQU 0080H ; DEFAULT DISK I/O BUFFER
- TFCB EQU 005CH ; DEFAULT FCB BUFFER
- TPA EQU 0100H ; BASE OF TPA
-
-
-
- ORG CCPLOC ; START OF CCP IN MEMEORY IN YOUR SYSTEM
-
-
- ENTRY:
- JMP CCP
- JMP CCP1
-
- * INPUT COMMAND LINE AND DEFAULT COMMAND
- BUFLEN EQU 100 ; MAXIMUM BUFFER LENGTH
- MBUFF:
- DB BUFLEN ; MAXIMUM BUFFER LENGTH
- CBUFF:
- DB 3 ;<== NUMBER OF VALID CHARS IN COMMAND LINE
- CIBUFF:
- DB 'DIR ' ;<== DEFAULT (COLD BOOT) COMMAND
- DB ' '
- DB ' '
- DB ' '
- CIBUF:
- DS 85 ; TOTAL IS 100 BYTES
- DS 20 ; STACK AREA
- STACK EQU $ ; TOP OF STACK
-
- CIBPTR:
- DW CIBUFF ;POINTER TO CMD INPUT BUFF
- CIPTR:
- DW CIBUF ;CURRENT PNTR
-
- *
- * I/O UTILITIES
- *
-
- * OUTPUT <SP>
- SPACER:
- MVI A,' ' ; FALL THRU TO CONOUT
-
- * OUTPUT CHAR IN REG A TO CONSOLE AND DON'T CHANGE BC
- CONOUT:
- PUSH B
- PUSH H
- MVI C,02H
- OUTPUT:
- MOV E,A
- CALL BDOS
- POP H
- POP B
- RET
-
- * CALL BDOS AND SAVE BC
- BDOSB:
- PUSH B
- CALL BDOS
- POP B
- RET
-
- * OUTPUT CHAR IN REG A TO LIST DEVICE
- LSTOUT:
- PUSH B
- PUSH H
- MVI C,05H
- DB 18H
- DB OUTPUT-$-1 AND 0FFH
-
- * OUTPUT <CRLF>
- CRLF:
- MVI A,CR
- CALL CONOUT
- MVI A,LF
- DB 18H
- DB CONOUT-$-1 AND 0FFH
-
- * PRINT STRING (ENDING IN 0) PTED TO BY RET ADR; START WITH <CRLF>
- PRINT:
- XTHL ; GET PTR TO STRING
- PUSH PSW ; SAVE FLAGS
- CALL CRLF ; NEW LINE
- CALL PRIN1
- POP PSW ; GET FLAGS
- XTHL ; RESTORE HL AND RET ADR
- RET
-
- * PRINT STRING (ENDING IN 0) PTED TO BY HL
- PRIN1:
- MOV A,M ; GET NEXT BYTE
- INX H ; PT TO NEXT BYTE
- ORA A ; DONE IF 0
- RZ
- CALL CONOUT ; PRINT CHAR
- DB 18H
- DB PRIN1-$-1 AND 0FFH
-
- *
- * BDOS FUNCTION ROUTINES
- *
-
- RESET:
- MVI C,0DH
- JMP BDOS
- ;
- LOGIN:
- MOV E,A
- MVI C,0EH
- JMP BDOS
- ;
- OPENF:
- XRA A
- STA FCBCR
- LXI D,FCBDN ; FALL THRU TO OPEN
- ;
- OPEN:
- MVI C,0FH ; FALL THRU TO GRBDOS
- ;
- GRBDOS:
- CALL BDOS
- INR A ; SET ZERO FLAG FOR ERROR RETURN
- RET
- ;
- CLOSE:
- MVI C,10H
- DB 18H
- DB GRBDOS-$-1 AND 0FFH
- ;
- SEARF:
- LXI D,FCBDN ; SPECIFY FCB
- SEAR1:
- MVI C,11H
- DB 18H
- DB GRBDOS-$-1 AND 0FFH
- ;
- SEARN:
- MVI C,12H
- DB 18H
- DB GRBDOS-$-1 AND 0FFH
- ;
- DELETE:
- MVI C,13H
- JMP BDOS
- ;
- READF:
- LXI D,FCBDN ; FALL THRU TO READ
- ;
- READ:
- MVI C,14H ; FALL THRU TO GOBDOS
- ;
- GOBDOS:
- CALL BDOSB ; PRESERVE B
- ORA A
- RET
- ;
- WRITE:
- MVI C,15H
- DB 18H
- DB GOBDOS-$-1 AND 0FFH
- ;
- CREATE:
- MVI C,16H
- DB 18H
- DB GRBDOS-$-1 AND 0FFH
- ;
- GETUSR:
- MVI E,0FFH ;GET CURRENT USER NUMBER
- SETUSR:
- MVI C,20H ;SET USER NUMBER TO VALUE IN E (GET IF E=FFH)
- JMP BDOS
-
- *
- * END OF BDOS FUNCTIONS
- *
-
- *
- * CCP UTILITIES
- *
-
- * SET USER/DISK FLAG TO CURRENT USER AND DEFAULT DISK
- SETUD:
- CALL GETUSR ; GET NUMBER OF CURRENT USER
- ADD A ; PLACE IT IN HIGH NYBBLE
- ADD A
- ADD A
- ADD A
- LXI H,TDRIVE ; MASK IN DEFAULT DRIVE NUMBER (LOW NYBBLE)
- ORA M ; MASK IN
- STA UDFLAG ; SET USER/DISK NUMBER
- RET
-
- * SET USER/DISK FLAG TO USER 0 AND DEFAULT DISK
- SETU0D:
- LDA TDRIVE ; SET USER 0/DEFAULT DISK
- STA UDFLAG ; SET USER/DISK NUMBER
- RET
-
- * CONVERT CHAR IN A TO UPPER CASE
- UCASE:
- CPI 61H ; LOWER-CASE A
- RC
- CPI 7BH ; GREATER THAN LOWER-CASE Z?
- RNC
- ANI 5FH ; CAPITALIZE
- RET
-
- * INPUT NEXT COMMAND TO CCP
- REDBUF:
- LDA RNGSUB ; SUBMIT FILE CURRENTLY IN EXECUTION?
- ORA A ; 0=NO
- DB 28H
- DB RB1-$-1 AND 0FFH ; GET LINE FROM CONSOLE IF NOT
- LXI D,SUBFCB ; OPEN $$$.SUB
- CALL OPEN
- DB 28H
- DB RB1-$-1 AND 0FFH ; ERASE $$$.SUB IF END OF FILE AND GET CMND
- LDA SUBFRC ; GET VALUE OF LAST RECORD IN FILE
- DCR A ; PT TO NEXT TO LAST RECORD
- STA SUBFCR ; SAVE NEW VALUE OF LAST RECORD IN $$$.SUB
- LXI D,SUBFCB ; READ LAST RECORD OF SUBMIT FILE
- CALL READ
- DB 20H
- DB RB1-$-1 AND 0FFH ; ABORT $$$.SUB IF ERROR IN READING LAST REC
- LXI D,CBUFF ; COPY LAST RECORD (NEXT SUBMIT CMND) TO CBUFF
- LXI H,TBUFF ; FROM TBUFF
- MVI B,BUFLEN ; NUMBER OF BYTES
- CALL MOVEHD
- LXI H,SUBFS2 ; PT TO S2 OF $$$.SUB FCB
- MVI M,0 ; SET S2 TO ZERO
- INX H ; PT TO RECORD COUNT
- DCR M ; DECREMENT RECORD COUNT OF $$$.SUB
- LXI D,SUBFCB ; CLOSE $$$.SUB
- CALL CLOSE
- DB 28H
- DB RB1-$-1 AND 0FFH ; ABORT $$$.SUB IF ERROR
- MVI A,'$' ; PRINT SUBMIT PROMPT
- CALL CONOUT
- LXI H,CIBUFF ; PRINT COMMAND LINE FROM $$$.SUB
- CALL PRIN1
- CALL BREAK ; CHECK FOR ABORT (ANY CHAR)
- DB 28H
- DB CNVBUF-$-1 AND 0FFH ; IF <NULL> (NO ABORT), CAP COMMAND AND RUN
- CALL SUBKIL ; KILL $$$.SUB IF ABORT
- JMP RESTRT ; RESTART CCP
-
- * INPUT COMMAND LINE FROM USER CONSOLE
- RB1:
- CALL SUBKIL ; ERASE $$$.SUB IF PRESENT
- CALL SETUD ; SET USER AND DISK
- MVI A,'>' ; PRINT PROMPT
- CALL CONOUT
- MVI C,0AH ; READ COMMAND LINE FROM USER
- LXI D,MBUFF
- CALL BDOS
- CALL SETU0D ; SET CURRENT DISK NUMBER IN LOWER PARAMS
-
- * CAPITALIZE STRING (ENDING IN 0) IN CBUFF
- CNVBUF:
- LXI H,CBUFF ; PT TO USER'S COMMAND
- MOV B,M ; CHAR COUNT IN B
- CB1:
- INX H ; PT TO 1ST VALID CHAR
- MOV A,B ; DONE WHEN <NULL> ENCOUNTERED
- ORA A
- DB 28H
- DB CB2-$-1 AND 0FFH
- MOV A,M ; CAPITALIZE COMMAND CHAR
- CALL UCASE
- MOV M,A
- DCR B ; CONTINUE UNTIL END OF COMMAND LINE
- DB 18H
- DB CB1-$-1 AND 0FFH
- CB2:
- MOV M,A ; STORE ENDING <NULL>
- LXI H,CIBUFF ; SET COMMAND LINE PTR TO 1ST CHAR
- SHLD CIBPTR
- RET
-
- * CHECK FOR ANY CHAR FROM USER CONSOLE; RET W/ZERO SET IF NONE
- BREAK:
- PUSH D ; SAVE DE
- MVI E,0FFH ; GET STATUS
- MVI C,6 ; DIRECT CONSOLE I/O
- CALL BDOSB
- POP D
- ANI 7FH ; MASK MSB AND SET ZERO FLAG
- RET
-
- * RETURN NUMBER OF CURRENT DISK IN A
- GETDRV:
- MVI C,19H
- JMP BDOS
-
- * SET 80H AS DMA ADDRESS
- DEFDMA:
- LXI D,TBUFF ; 80H=TBUFF
- DMASET:
- MVI C,1AH
- JMP BDOS
-
- * CHECK FOR SUBMIT FILE IN EXECUTION AND ABORT IT IF SO
- SUBKIL:
- LXI H,RNGSUB ; CHECK FOR SUBMIT FILE IN EXECUTION
- MOV A,M
- ORA A ; 0=NO
- RZ
- MVI M,0 ; ABORT SUBMIT FILE
- LXI D,SUBFCB ; DELETE $$$.SUB
- JMP DELETE
-
- * INVALID COMMAND -- PRINT IT
- ERROR:
- CALL CRLF ; NEW LINE
- LHLD CIPTR ; PT TO BEGINNING OF COMMAND LINE
- ERR2:
- MOV A,M ; GET CHAR
- CPI ' ' ; SIMPLE '?' IF <SP>
- DB 28H
- DB ERR1-$-1 AND 0FFH
- ORA A ; SIMPLE '?' IF <NULL>
- DB 28H
- DB ERR1-$-1 AND 0FFH
- PUSH H ; SAVE PTR TO ERROR COMMAND CHAR
- CALL CONOUT ; PRINT COMMAND CHAR
- POP H ; GET PTR
- INX H ; PT TO NEXT
- DB 18H
- DB ERR2-$-1 AND 0FFH ; CONTINUE
- ERR1:
- MVI A,'?' ; PRINT '?'
- CALL CONOUT
- CALL SUBKIL ; TERMINATE ACTIVE $$$.SUB IF ANY
- JMP RESTRT ; RESTART CCP
-
- * CHECK TO SEE IF DE PTS TO DELIMITER; IF SO, RET W/ZERO FLAG SET
- SDELM:
- LDAX D
- ORA A ; 0=DELIMITER
- RZ
- CPI ' ' ; ERROR IF < <SP>
- JC ERROR
- RZ ; <SP>=DELIMITER
- CPI '=' ; '='=DELIMITER
- RZ
- CPI 5FH ; UNDERSCORE=DELIMITER
- RZ
- CPI '.' ; '.'=DELIMITER
- RZ
- CPI ':' ; ':'=DELIMITER
- RZ
- CPI ';' ; ';'=DELIMITER
- RZ
- CPI '<' ; '<'=DELIMITER
- RZ
- CPI '>' ; '>'=DELIMITER
- RET
-
- * SKIP STRING PTED TO BY DE (STRING ENDS IN 0) UNTIL END OF STRING
- * OR NON-BLANK ENCOUNTERED (BEGINNING OF TOKEN)
- SBLANK:
- LDAX D
- ORA A
- RZ
- CPI ' '
- RNZ
- INX D
- DB 18H
- DB SBLANK-$-1 AND 0FFH
-
- * ADD A TO HL (HL=HL+A)
- ADDAH:
- ADD L
- MOV L,A
- RNC
- INR H
- RET
-
- * EXTRACT TOKEN FROM COMMAND LINE AND PLACE IT INTO FCBDN; FORMAT FCBDN
- * 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 SET
- * IF '?' IS IN TOKEN
- SCANER:
- MVI A,0 ; START AT DRIVE SPECIFICATION BYTE
- SCAN1:
- LXI H,FCBDN ; POINT TO FCBDN
- CALL ADDAH ; OFFSET INTO FCB
- PUSH H
- PUSH H
- XRA A ; SET TEMPORARY DRIVE NUMBER TO DEFAULT
- STA TEMPDR
- LHLD CIBPTR ; GET PTR TO NEXT CHAR IN COMMAND LINE
- XCHG ; PTR IN DE
- CALL SBLANK ; SKIP TO NON-BLANK OR END OF LINE
- XCHG
- SHLD CIPTR ; SET PTR TO NON-BLANK OR END OF LINE
- XCHG ; DE PTS TO NEXT NON-BLANK OR END OF LINE CHAR
- POP H ; GET PTR TO NEXT BYTE IN FCBDN
- LDAX D ; END OF LINE?
- ORA A ; 0=YES
- DB 28H
- DB SCAN2-$-1 AND 0FFH
- SBI 'A'-1 ; CONVERT POSSIBLE DRIVE SPEC TO NUMBER
- MOV B,A ; STORE NUMBER (A:=0, B:=1, ETC) IN B
- INX D ; PT TO NEXT CHAR
- LDAX D ; SEE IF IT IS A COLON (:)
- CPI ':'
- DB 28H
- DB SCAN3-$-1 AND 0FFH ; YES^ WE HAVE A DRIVE SPEC
- DCX D ; NO^ BACK UP PTR TO FIRST NON-BLANK CHAR
- SCAN2:
- LDA TDRIVE ; SET 1ST BYTE OF FCBDN AS DEFAULT DRIVE
- MOV M,A
- DB 18H
- DB SCAN4-$-1 AND 0FFH
- SCAN3:
- MOV A,B ; WE HAVE A DRIVE SPEC^
- STA TEMPDR ; SET TEMPORARY DRIVE
- MOV M,B ; SET 1ST BYTE OF FCBDN AS SPECIFIED DRIVE
- INX D ; PT TO BYTE AFTER ':'
-
- * EXTRACT FILENAME FROM POSSIBLE FILENAME.TYP
- SCAN4:
- MVI B,08H ; MAX OF 8 CHARS IN FILE NAME
- SCAN5:
- CALL SDELM ; DONE IF DELIMITER ENCOUNTERED - <SP> FILL
- DB 28H
- DB SCAN9-$-1 AND 0FFH
- INX H ; PT TO NEXT BYTE IN FCBDN
- CPI '*' ; IS (DE) A WILD CARD?
- DB 20H
- DB SCAN6-$-1 AND 0FFH ; CONTINUE IF NOT
- MVI M,'?' ; PLACE '?' IN FCBDN AND DON'T ADVANCE DE IF SO
- DB 18H
- DB SCAN7-$-1 AND 0FFH
- SCAN6:
- MOV M,A ; STORE FILENAME CHAR IN FCBDN
- INX D ; PT TO NEXT CHAR IN COMMAND LINE
- SCAN7:
- DB 10H
- DB SCAN5-$-1 AND 0FFH ; DECREMENT CHAR COUNT UNTIL 8 ELAPSED
- SCAN8:
- CALL SDELM ; 8 CHARS OR MORE - SKIP UNTIL DELIMITER
- DB 28H
- DB SCAN10-$-1 AND 0FFH ; ZERO FLAG SET IF DELIMITER FOUND
- INX D ; PT TO NEXT CHAR IN COMMAND LINE
- DB 18H
- DB SCAN8-$-1 AND 0FFH
- SCAN9:
- INX H ; PT TO NEXT BYTE IN FCBDN
- MVI M,' ' ; FILL FILENAME PART WITH <SP>
- DB 10H
- DB SCAN9-$-1 AND 0FFH
-
- * EXTRACT FILE TYPE FROM POSSIBLE FILENAME.TYP
- SCAN10:
- MVI B,03H ; PREPARE TO EXTRACT TYPE
- CPI '.' ; IF (DE) DELIMITER IS A '.', WE HAVE A TYPE
- DB 20H
- DB SCAN15-$-1 AND 0FFH ; FILL FILE TYPE BYTES WITH <SP>
- INX D ; PT TO CHAR IN COMMAND LINE AFTER '.'
- SCAN11:
- CALL SDELM ; CHECK FOR DELIMITER
- DB 28H
- DB SCAN15-$-1 AND 0FFH ; FILL REST OF TYPE IF IT IS A DELIMITER
- INX H ; PT TO NEXT BYTE IN FCBDN
- CPI '*' ; WILD?
- DB 20H
- DB SCAN12-$-1 AND 0FFH ; STORE CHAR IF NOT WILD
- MVI M,'?' ; STORE '?' AND DON'T ADVANCE COMMAND LINE PTR
- DB 18H
- DB SCAN13-$-1 AND 0FFH
- SCAN12:
- MOV M,A ; STORE CHAR IN FCBDN
- INX D ; PT TO NEXT CHAR IN COMMAND LINE
- SCAN13:
- DB 10H
- DB SCAN11-$-1 AND 0FFH ; COUNT DOWN CHARS IN FILE TYPE (3 MAX)
- SCAN14:
- CALL SDELM ; SKIP REST OF CHARS AFTER 3-CHAR TYPE TO
- DB 28H
- DB SCAN16-$-1 AND 0FFH ; DELIMITER
- INX D
- DB 18H
- DB SCAN14-$-1 AND 0FFH
- SCAN15:
- INX H ; FILL IN REST OF TYP WITH <SP>
- MVI M,' '
- DB 10H
- DB SCAN15-$-1 AND 0FFH
-
- * FILL IN EX, S1, S2, AND RC WITH ZEROES
- SCAN16:
- MVI B,4 ; 4 BYTES
- SCAN17:
- INX H ; PT TO NEXT BYTE IN FCBDN
- MVI M,0
- DB 10H
- DB SCAN17-$-1 AND 0FFH
-
- * SCAN COMPLETE -- DE PTS TO DELIMITER BYTE AFTER TOKEN
- XCHG ; STORE PTR TO NEXT BYTE IN COMMAND LINE
- SHLD CIBPTR
-
- * SET ZERO FLAG TO INDICATE PRESENCE OF '?' IN FILENAME.TYP
- POP H ; GET PTR TO FCBDN IN HL
- LXI B,11 ; SCAN FOR '?' IN FILENAME.TYP (C=11 BYTES)
- SCAN18:
- INX H ; PT TO NEXT BYTE IN FCBDN
- MOV A,M
- CPI '?'
- DB 20H
- DB SCAN19-$-1 AND 0FFH
- INR B ; B<>0 TO INDICATE '?' ENCOUNTERED
- SCAN19:
- DCR C ; COUNT DOWN
- DB 20H
- DB SCAN18-$-1 AND 0FFH
- MOV A,B ; A=B=NUMBER OF '?' IN FILENAME.TYP
- ORA A ; SET ZERO FLAG TO INDICATE ANY '?'
- RET
-
- *
- * CCP BUILT-IN COMMAND TABLE AND COMMAND PROCESSOR
- *
- NCMNDS EQU 8 ; NUMBER OF CCP COMMANDS
- NCHARS EQU 4 ; NUMBER OF CHARS/COMMAND
- * CCP COMMAND NAME TABLE
- CMDTBL:
- DB 'DIR '
- DB 'ERA '
- DB 'LIST'
- DB 'TYPE'
- DB 'SAVE'
- DB 'REN '
- DB 'USER'
- DB 'CLS '
- * CCP COMMAND ADDRESS TABLE
- REQTBL:
- DW DIR
- DW ERA
- DW LIST
- DW TYPE
- DW SAVE
- DW REN
- DW USER
- DW CLS
- DW COM ;MUST BE A COM FILE
-
- * CMDTBL (COMMAND TABLE) SCANNER
- * ON RETURN, A=TABLE ENTRY # (0-5) OR 6 IF NOT FOUND (COM FILE)
- CMDSER:
- LXI H,CMDTBL ; PT TO COMMAND TABLE
- MVI C,0 ; SET COMMAND COUNTER
- CMS1:
- MOV A,C ; CHECK FOR DONE
- CPI NCMNDS ; NUMBER OF COMMANDS
- RNC
- LXI D,FCBFN ; PT TO STORED COMMAND NAME
- MVI B,NCHARS ; NUMBER OF CHARS/COMMAND (8 MAX)
- CMS2:
- LDAX D ; COMPARE AGAINST TABLE ENTRY
- CMP M
- DB 20H
- DB CMS3-$-1 AND 0FFH ; NO MATCH
- INX D ; PT TO NEXT CHAR
- INX H
- DB 10H
- DB CMS2-$-1 AND 0FFH ; COUNT DOWN
- LDAX D ; NEXT CHAR IN INPUT COMMAND MUST BE <SP>
- CPI ' '
- DB 20H
- DB CMS4-$-1 AND 0FFH
- MOV A,C ; TABLE ENTRY NUMBER IN A
- RET
- CMS3:
- INX H ; SKIP TO NEXT COMMAND TABLE ENTRY
- DB 10H
- DB CMS3-$-1 AND 0FFH
- CMS4:
- INR C ; INCREMENT TABLE ENTRY NUMBER
- DB 18H
- DB CMS1-$-1 AND 0FFH
-
- *
- * 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
- 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
- POP B
- MOV A,C ; C=USER/DISK NUMBER (SEE LOC 4)
- ANI 0FH ; EXTRACT DEFAULT DISK DRIVE
- STA TDRIVE ; SET IT
- CALL LOGIN ; LOG IN DEFAULT DISK
- LXI D,SUBFCB ; CHECK FOR $$$.SUB ON CURRENT DISK
- CALL 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
- DB 20H
- DB RS1-$-1 AND 0FFH
-
- * 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
- CPI 10 ; USER < 10?
- DB 38H
- DB RS00-$-1 AND 0FFH
- 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
- CALL REDBUF ; INPUT COMMAND LINE FROM USER (OR $$$.SUB)
-
- * PROCESS INPUT LINE
- RS1:
- LXI D,TBUFF ; PT TO INPUT COMMAND LINE (IN TBUFF)
- CALL DMASET ; 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 '?'
- LDA TEMPDR ; IS COMMAND OF FORM 'D:COMMAND'?
- ORA A ; NZ=YES
- JNZ COM ; PROCESS AS COM FILE IMMEDIATELY
- CALL CMDSER ; SCAN FOR CCP-RESIDENT COMMAND
- LXI H,REQTBL ; EXECUTE COMMAND (CCP-RESIDENT OR COM)
- MOV E,A ; COMPUTE OFFSET INTO ADDRESS TABLE
- MVI D,0
- DAD D
- DAD D
- MOV A,M ; GET ADDRESS IN HL
- INX H
- MOV H,M ; ADDRESS HIGH
- MOV L,A ; ADDRESS LOW
- PCHL ; EXECUTE CCP ROUTINE
-
- *
- * ERROR MESSAGES
- *
- PRNNF:
- CALL PRINT ; NO FILE MESSAGE
- DB 'No Files',0
- RET
-
- *
- * MORE CCP UTILITIES
- *
-
- * EXTRACT NUMBER FROM COMMAND LINE
- NUMBER:
- CALL SCANER ; PARSE NUMBER AND PLACE IN FCBFN
- LDA TEMPDR ; TOKEN BEGIN WITH DRIVE SPEC (D:)?
- ORA A ; ERROR IF SO
- JNZ ERROR
- LXI H,FCBFN ; PT TO TOKEN FOR CONVERSION
- LXI B,11 ; B=ACCUMULATED VALUE, C=CHAR COUNT
- NUM1:
- MOV A,M ; GET CHAR
- CPI ' ' ; DONE IF <SP>
- DB 28H
- DB NUM2-$-1 AND 0FFH
- INX H ; PT TO NEXT CHAR
- SUI '0' ; CONVERT TO BINARY (ASCII 0-9 TO BINARY)
- CPI 10 ; ERROR IF >= 10
- JNC ERROR
- MOV D,A ; DIGIT IN D
- MOV A,B ; GET ACCUMULATED VALUE
- ANI 0E0H ; CHECK FOR RANGE ERROR (>255)
- JNZ ERROR
- MOV A,B ; NEW VALUE = OLD VALUE * 10
- RLC
- RLC
- RLC
- ADD B ; CHECK FOR RANGE ERROR
- JC ERROR
- ADD B ; CHECK FOR RANGE ERROR
- JC ERROR
- ADD D ; NEW VALUE = OLD VALUE * 10 + DIGIT
- JC ERROR ; CHECK FOR RANGE ERROR
- MOV B,A ; SET NEW VALUE
- DCR C ; COUNT DOWN
- DB 20H
- DB NUM1-$-1 AND 0FFH
- RET
-
- * REST OF TOKEN BUFFER MUST BE <SP>
- NUM2:
- MOV A,M ; CHECK FOR <SP>
- CPI ' '
- JNZ ERROR
- INX H ; PT TO NEXT
- DCR C ; COUNT DOWN CHARS
- DB 20H
- DB NUM2-$-1 AND 0FFH
- MOV A,B ; GET ACCUMULATED VALUE
- RET
-
- * MOVE 3 BYTES FROM HL TO DE
- MOVHD3:
- MVI B,3 ; MOVE 3 CHARS
- MOVEHD:
- MOV A,M ; GET IT
- STAX D ; PUT IT
- INX H ; PT TO NEXT
- INX D
- DB 10H
- DB MOVEHD-$-1 AND 0FFH
- 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
- JMP LOGIN ; 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
- JMP LOGIN
-
- * ROUTINE COMMON TO BOTH LOGIN ROUTINES; ON EXIT, Z SET MEANS ABORT
- COMLOG:
- LDA TEMPDR ; DRIVE SPECIFIED?
- ORA A ; 0=NO
- RZ
- DCR A ; COMPARE IT AGAINST DEFAULT
- LXI H,TDRIVE
- CMP M
- RET ; ABORT IF SAME
-
- *
- * CCP DIRECTORY DISPLAY FUNCTION (DIR)
- *
- DIR:
- MVI A,80H ; SET SYSTEM BIT EXAMINATION
- PUSH PSW
- CALL SCANER ; EXTRACT POSSIBLE D:FILENAME.TYP TOKEN
- CALL SLOGIN ; LOG IN DRIVE IF NECESSARY
- LXI H,FCBFN ; MAKE FCB WILD (ALL '?') IF NO FILENAME.TYP
- MOV A,M ; GET FIRST CHAR OF FILENAME.TYP
- CPI ' ' ; IF <SP>, ALL WILD
- DB 28H
- DB DIR0-$-1 AND 0FFH
- CPI '@' ; SYSTEM FILES?
- DB 20H
- DB DIR2-$-1 AND 0FFH
- INX H ; JUST '@'? <SP> MUST FOLLOW
- MOV A,M
- DCX H ; BACK UP
- CPI ' ' ; JUST '@' IF <SP> FOLLOWS
- DB 20H
- DB DIR2-$-1 AND 0FFH
- POP PSW ; GET FLAG
- XRA A ; SET NO SYSTEM BIT EXAMINATION
- PUSH PSW
- DIR0:
- MVI B,11 ; NUMBER OF CHARS IN FN & FT
- DIR1:
- MVI M,'?' ; STORE '?'
- INX H
- DB 10H
- DB DIR1-$-1 AND 0FFH
- DIR2:
- POP PSW ; GET FLAG
- CALL DIRPR ; PRINT DIRECTORY
- JMP RSTCCP ; RESTART CCP
-
- * DIRECTORY PRINT ROUTINE; ON ENTRY, MSB OF A IS 1 (80H) IF SYSTEM FILES EXCL
- DIRPR:
- MOV D,A ; STORE SYSTEM FLAG IN D
- MVI E,0 ; SET COLUMN COUNTER TO ZERO
- PUSH D ; SAVE COLUMN COUNTER (E) AND SYSTEM FLAG (D)
- CALL SEARF ; SEARCH FOR SPECIFIED FILE (FIRST OCCURRANCE)
- CZ PRNNF ; PRINT NO FILE MSG; REG A NOT CHANGED
-
- * ENTRY SELECTION LOOP; ON ENTRY, A=OFFSET FROM SEARF OR SEARN
- DIR3:
- DB 28H
- DB DIR11-$-1 AND 0FFH ; DONE IF ZERO FLAG SET
- DCR A ; ADJUST TO RETURNED VALUE
- RRC ; CONVERT NUMBER TO OFFSET INTO TBUFF
- RRC
- RRC
- ANI 60H
- MOV C,A ; OFFSET INTO TBUFF IN C (C=OFFSET TO ENTRY)
- MVI A,10 ; ADD 10 TO PT TO SYSTEM FILE ATTRIBUTE BIT
- CALL DIRPTR
- POP D ; GET SYSTEM BIT MASK FROM D
- PUSH D
- ANA D ; MASK FOR SYSTEM BIT
- DB 20H
- DB DIR10-$-1 AND 0FFH ; SKIP ENTRY IF BIT IS SET
- POP D ; GET ENTRY COUNT (=<CR> COUNTER)
- MOV A,E ; ADD 1 TO IT
- INR E
- PUSH D ; SAVE IT
- ANI 03H ; OUTPUT <CRLF> IF 4 ENTRIES PRINTED IN LINE
- PUSH PSW
- DB 20H
- DB DIR4-$-1 AND 0FFH
- CALL CRLF ; NEW LINE
- DB 18H
- DB DIR5-$-1 AND 0FFH
- DIR4:
- CALL SPACER ; PRINT <SP>:<SP> BETWEEN ENTRIES
- MVI A,':'
- CALL CONOUT
- CALL SPACER
- DIR5:
- MVI B,01H ; PT TO 1ST BYTE OF FILE NAME
- DIR6:
- MOV A,B ; A=OFFSET
- CALL DIRPTR ; HL NOW PTS TO 1ST BYTE OF FILE NAME
- ANI 7FH ; MASK OUT MSB
- CPI ' ' ; NO FILE NAME?
- DB 20H
- DB DIR8-$-1 AND 0FFH ; PRINT FILE NAME IF PRESENT
- POP PSW
- PUSH PSW
- CPI 03H
- DB 20H
- DB DIR7-$-1 AND 0FFH
- MVI A,09H ; PT TO 1ST BYTE OF FILE TYPE
- CALL DIRPTR ; HL NOW PTS TO 1ST BYTE OF FILE TYPE
- ANI 7FH ; MASK OUT MSB
- CPI ' ' ; NO FILE TYPE?
- DB 28H
- DB DIR9-$-1 AND 0FFH ; CONTINUE IF SO
- DIR7:
- MVI A,' ' ; OUTPUT <SP>
- DIR8:
- CALL CONOUT ; PRINT CHAR
- INR B ; INCR CHAR COUNT
- MOV A,B
- CPI 12 ; END OF FILENAME.TYP?
- DB 30H
- DB DIR9-$-1 AND 0FFH ; CONTINUE IF SO
- CPI 09H ; END IF FILENAME ONLY?
- DB 20H
- DB DIR6-$-1 AND 0FFH ; PRINT TYP IF SO
- MVI A,'.' ; PRINT DOT BETWEEN FILE NAME AND TYPE
- CALL CONOUT
- DB 18H
- DB DIR6-$-1 AND 0FFH
- DIR9:
- POP PSW
- DIR10:
- CALL BREAK ; CHECK FOR ABORT
- DB 20H
- DB DIR11-$-1 AND 0FFH
- CALL SEARN ; SEARCH FOR NEXT FILE
- DB 18H
- DB DIR3-$-1 AND 0FFH ; CONTINUE
- DIR11:
- POP D ; RESTORE STACK
- RET
-
- *
- * CCP FILE ERASE FUNCTION (ERA)
- *
- ERA:
- CALL SCANER ; PARSE FILE SPECIFICATION
- CPI 0BH ; ALL WILD (ALL FILES = 11 '?')?
- DB 20H
- DB ERA1-$-1 AND 0FFH ; IF NOT, THEN DO ERASES
- CALL PRINT
- DB 'All (Y/N)?',0
- CALL REDBUF ; GET REPLY
- LXI H,CBUFF ; CHECK FOR <CR>
- DCR M
- JNZ RESTRT ; RESTART CCP IF JUST <CR>
- INX H ; PT TO RESPONSE BYTE
- MOV A,M ; GET IT
- CPI 'Y' ; YES?
- JNZ RESTRT ; RESTART CCP IF NOT
- INX H ; PT TO CHAR AFTER 'Y'
- SHLD CIBPTR ; SET PTR TO IT
- ERA1:
- CALL SLOGIN ; LOG IN SELECTED DISK IF ANY
- MVI A,80H ; SKIP SYSTEM FILES (EXAMINE SYSTEM BIT)
- CALL DIRPR ; PRINT DIRECTORY OF ERASED FILES
- LXI D,FCBDN ; DELETE FILE SPECIFIED
- CALL DELETE
- JMP RSTCCP ; REENTER CCP
-
- *
- * CCP LIST FUNCTION (LIST)
- *
- LIST:
- MVI A,0FFH ; TURN ON PRINTER FLAG
- DB 18H
- DB TYPE0-$-1 AND 0FFH
-
- *
- * CCP TYPE FUNCTION (TYPE)
- *
- TYPE:
- XRA A ; TURN OFF PRINTER FLAG
-
- * ENTRY POINT FOR CCP LIST FUNCTION (LIST)
- TYPE0:
- STA PRFLG ; SET FLAG
- CALL SCANER ; EXTRACT FILENAME.TYP TOKEN
- JNZ ERROR ; ERROR IF ANY QUESTION MARKS
- CALL SLOGIN ; LOG IN SELECTED DISK IF ANY
- CALL OPENF ; OPEN SELECTED FILE
- JZ TYPE4 ; ABORT IF ERROR
- CALL CRLF ; NEW LINE
- CALL PAGSET ; SET LINE COUNT
- LXI H,CHRCNT ; SET CHAR POSITION/COUNT
- MVI M,0FFH ; EMPTY LINE
- MVI B,0 ; SET TAB CHAR COUNTER
- TYPE1:
- LXI H,CHRCNT ; PT TO CHAR POSITION/COUNT
- MOV A,M ; END OF BUFFER?
- CPI 80H
- DB 38H
- DB TYPE2-$-1 AND 0FFH
- PUSH H ; READ NEXT BLOCK
- CALL READF
- POP H
- DB 20H
- DB TYPE3-$-1 AND 0FFH ; ERROR?
- XRA A ; RESET COUNT
- MOV M,A
- TYPE2:
- INR M ; INCREMENT CHAR COUNT
- LXI H,TBUFF ; PT TO BUFFER
- CALL ADDAH ; COMPUTE ADDRESS OF NEXT CHAR FROM OFFSET
- MOV A,M ; GET NEXT CHAR
- ANI 7FH ; MASK OUT MSB
- CPI 1AH ; END OF FILE (^Z)?
- JZ RSTCCP ; RESTART CCP IF SO
- PUSH PSW ; SAVE CHAR
- LDA PRFLG ; TYPE OR LIST?
- ORA A ; 0=TYPE
- DB 28H
- DB TYPE2T-$-1 AND 0FFH
-
- * OUTPUT CHAR TO LST: DEVICE WITH TABULATION
- POP PSW ; GET CHAR
- CPI CR ; RESET TAB COUNT?
- DB 28H
- DB TABRST-$-1 AND 0FFH
- CPI LF ; RESET TAB COUNT?
- DB 28H
- DB TABRST-$-1 AND 0FFH
- CPI TAB ; TAB?
- DB 28H
- DB LTAB-$-1 AND 0FFH
- CALL LSTOUT ; LIST CHAR
- INR B ; INCREMENT CHAR COUNT
- DB 18H
- DB TYPE2L-$-1 AND 0FFH
- TABRST:
- CALL LSTOUT ; OUTPUT <CR>
- MVI B,0 ; RESET TAB COUNTER
- DB 18H
- DB TYPE2L-$-1 AND 0FFH
- LTAB:
- MVI A,' ' ; <SP>
- CALL LSTOUT
- INR B ; INCR POS COUNT
- MOV A,B
- ANI 7
- DB 20H
- DB LTAB-$-1 AND 0FFH
- DB 18H
- DB TYPE2L-$-1 AND 0FFH
-
- * OUTPUT CHAR TO CON: WITH TABULATION
- TYPE2T:
- POP PSW ; GET CHAR
- PUSH PSW ; SAVE CHAR
- CALL CONOUT ; TYPE CHAR
- POP PSW
- CPI LF ; PAGE ON <LF>
- CZ PAGER ; COUNT LINES AND PAGE
-
- * CONTINUE PROCESSING
- TYPE2L:
- CALL BREAK ; CHECK FOR ABORT
- DB 28H
- DB TYPE1-$-1 AND 0FFH ; CONTINUE IF NO CHAR
- CPI 'C'-'@' ; ^C?
- JZ RSTCCP ; RESTART IF SO
- DB 18H
- DB TYPE1-$-1 AND 0FFH
- TYPE3:
- DCR A ; NO ERROR?
- JZ RSTCCP ; RESTART CCP
- CALL PRINT ; PRINT READ ERROR MSG
- DB 'Read Error',0
- TYPE4:
- CALL DLOGIN ; LOG IN DEFAULT DRIVE
- JMP ERROR
-
- *
- * PAGING ROUTINES
- * PAGER COUNTS DOWN LINES AND PAUSES FOR INPUT (DIRECT) IF COUNT EXPIRES
- * PAGSET SETS LINES/PAGE COUNT
- *
- PAGER:
- LDA PAGCNT ; COUNT DOWN
- DCR A
- STA PAGCNT
- RNZ
- PUSH H ; SAVE HL
- PAGER1:
- MVI C,6 ; DIRECT CONSOLE I/O
- MVI E,0FFH ; INPUT
- CALL BDOSB
- ORA A ; CHAR READY?
- DB 28H
- DB PAGER1-$-1 AND 0FFH ; WAIT FOR CHAR
- CPI 'C'-'@' ; ^C
- JZ RSTCCP ; RESTART CCP
- POP H ; RESTORE HL
- PAGSET:
- MVI A,NLINES-2 ; GET LINE COUNT
- STA PAGCNT
- RET
-
- *
- * CCP SAVE FUNCTION (SAVE)
- *
- SAVE:
- CALL NUMBER ; EXTRACT NUMBER FROM COMMAND LINE
- PUSH PSW ; SAVE IT
- CALL SCANER ; EXTRACT FILENAME.TYPE
- JNZ ERROR ; MUST BE NO '?' IN IT
- CALL SLOGIN ; LOG IN SELECTED DISK
- LXI D,FCBDN ; DELETE FILE IN CASE IT ALREADY EXISTS
- PUSH D
- CALL DELETE
- POP D
- CALL CREATE ; MAKE NEW FILE
- DB 28H
- DB SAVE3-$-1 AND 0FFH ; ERROR?
- XRA A ; SET RECORD COUNT FIELD OF NEW FILE'S FCB
- STA FCBCR
- POP PSW ; GET PAGE COUNT
- MOV L,A ; HL=PAGE COUNT
- MVI H,0
- DAD H ; DOUBLE IT FOR HL=SECTOR (128 BYTES) COUNT
- LXI D,TPA ; PT TO START OF SAVE AREA (TPA)
- SAVE1:
- MOV A,H ; DONE WITH SAVE?
- ORA L ; HL=0 IF SO
- DB 28H
- DB SAVE2-$-1 AND 0FFH
- DCX H ; COUNT DOWN ON SECTORS
- PUSH H ; SAVE PTR TO BLOCK TO SAVE
- LXI H,128 ; 128 BYTES PER SECTOR
- DAD D ; PT TO NEXT SECTOR
- PUSH H ; SAVE ON STACK
- CALL DMASET ; SET DMA ADDRESS FOR WRITE (ADDRESS IN DE)
- LXI D,FCBDN ; WRITE SECTOR
- CALL WRITE
- POP D ; GET PTR TO NEXT SECTOR IN DE
- POP H ; GET SECTOR COUNT
- DB 20H
- DB SAVE3-$-1 AND 0FFH ; WRITE ERROR?
- DB 18H
- DB SAVE1-$-1 AND 0FFH ; CONTINUE
- SAVE2:
- LXI D,FCBDN ; CLOSE SAVED FILE
- CALL CLOSE
- INR A ; ERROR?
- DB 20H
- DB SAVE4-$-1 AND 0FFH
- SAVE3:
- CALL PRINT
- DB 'No Space',0
- SAVE4:
- CALL DEFDMA ; SET DMA TO 0080
- JMP RSTCCP ; RESTART CCP
-
- *
- * CCP RENAME FILE FUNCTION (REN)
- *
- REN:
- CALL SCANER ; EXTRACT FILE NAME
- JNZ ERROR ; ERROR IF ANY '?' IN IT
- LDA TEMPDR ; SAVE CURRENT DEFAULT DISK
- PUSH PSW
- CALL SLOGIN ; LOG IN SELECTED DISK
- CALL SEARF ; LOOK FOR SPECIFIED FILE
- DB 28H
- DB REN0-$-1 AND 0FFH ; CONTINUE IF NOT FOUND
- CALL PRINT
- DB 'File Exists',0
- JMP RENRET
- REN0:
- LXI H,FCBDN ; SAVE NEW FILE NAME
- LXI D,FCBDM
- MVI B,16 ; 16 BYTES
- CALL MOVEHD
- LHLD CIBPTR ; GET PTR TO NEXT CHAR IN COMMAND LINE
- XCHG ; ... IN DE
- CALL SBLANK ; SKIP TO NON-BLANK
- CPI '=' ; '=' OR UNDERSCORE OK
- DB 28H
- DB REN1-$-1 AND 0FFH
- CPI 5FH
- DB 20H
- DB REN4-$-1 AND 0FFH
- REN1:
- XCHG ; PT TO CHAR AFTER '=' OR UNDERSCORE IN HL
- INX H
- SHLD CIBPTR ; SAVE PTR TO OLD FILE NAME
- CALL SCANER ; EXTRACT FILENAME.TYP TOKEN
- DB 20H
- DB REN4-$-1 AND 0FFH ; ERROR IF ANY '?'
- POP PSW ; GET OLD DEFAULT DRIVE
- MOV B,A ; SAVE IT
- LXI H,TEMPDR ; COMPARE IT AGAINST CURRENT DEFAULT DRIVE
- MOV A,M ; MATCH?
- ORA A
- DB 28H
- DB REN2-$-1 AND 0FFH
- CMP B ; CHECK FOR DRIVE ERROR
- MOV M,B
- DB 20H
- DB REN4-$-1 AND 0FFH
- REN2:
- MOV M,B
- XRA A
- STA FCBDN ; SET DEFAULT DRIVE
- LXI D,FCBDN ; RENAME FILE
- MVI C,17H ; BDOS RENAME FCT
- CALL BDOS
- INR A ; ERROR? -- FILE NOT FOUND IF SO
- DB 20H
- DB RENRET-$-1 AND 0FFH
- REN3:
- CALL PRNNF ; PRINT NO FILE MSG
- RENRET:
- JMP RSTCCP ; RESTART CCP
- REN4:
- CALL DLOGIN ; LOG IN DEFAULT DRIVE
- JMP ERROR
-
- *
- * CCP SET USER NUMBER FUNCTION
- *
- MAXUSR EQU 15 ; MAXIMUM USER AREA ACCESSABLE
- USER:
- CALL NUMBER ; EXTRACT USER NUMBER FROM COMMAND LINE
- CPI MAXUSR+1 ; ERROR IF >= MAXUSR
- JNC ERROR
- MOV E,A ; PLACE USER NUMBER IN E
- LDA FCBFN ; CHECK FOR PARSE ERROR
- CPI ' ' ; <SP>=ERROR
- JZ ERROR
- CALL SETUSR ; SET SPECIFIED USER
- JMP RCCPNL ; RESTART CCP (NO DEFAULT LOGIN)
-
- *
- * CLEAR SCREEN ROUTINE FOR CRT TERMINAL
- *
- CLS: IF H19 ; CLEAR H19/H89 CRT SCREEN
- MVI A,ESC ; GET ESCAPE CHAR
- CALL CONOUT
- MVI A,'E' ; CLEAR SCREEN
- CALL CONOUT
- ENDIF
- IF HAZE ; CLEAR HAZELTINE 1500 SCREEN
- MVI A,7EH ; TILDA PREFIX
- CALL CONOUT
- MVI A,28 ; CLEAR SCREEN
- CALL CONOUT
- ENDIF
- IF FFTERM
- MVI A,FF
- CALL CONOUT
- ENDIF
- JMP RCCPNL ; RESTART CCP (NO DEFAULT LOGIN)
-
- *
- * NOT CCP-RESIDENT COMMAND -- PROCESS AS TRANSCIENT
- *
- COM:
- CALL GETUSR ; GET CURRENT USER NUMBER
- STA TMPUSR ; SAVE IT FOR LATER
- STA TSELUSR ; TEMP USER TO SELECT
- LDA FCBFN ; ANY COMMAND?
- CPI ' ' ; ' ' MEANS COMMAND WAS 'D:' TO SWITCH
- DB 20H
- DB COM1-$-1 AND 0FFH ; NOT <SP>, SO MUST BE TRANSCIENT OR ERROR
- LDA TEMPDR ; LOOK FOR DRIVE SPEC
- ORA A ; IF ZERO, JUST BLANK
- JZ RCCPNL
- DCR A ; ADJUST FOR LOG IN
- STA TDRIVE ; SET DEFAULT DRIVE
- CALL SETU0D ; SET DRIVE WITH USER 0
- CALL LOGIN ; LOG IN DRIVE
- JMP RCCPNL ; RESTART CCP
- COM1:
- LDA FCBFT ; CHECK FOR ERROR IN FCB
- CPI ' ' ; ERROR IF SO
- JNZ ERROR
- *
- * COMA IS A REENTRY POINT FOR A NON-STANDARD CP/M MODIFICATION
- * THIS IS THE RETURN POINT FOR WHEN THE .COM FILE IS NOT FOUND THE
- * FIRST TIME, DRIVE A: IS SELECTED FOR A SECOND STTEMPT
- *
- COMA:
- CALL SLOGIN ; LOG IN SPECIFIED DRIVE IF ANY
- LXI H,COMMSG ; PLACE 'COM' IN FCB
- LXI D,FCBFT ; PT TO FILE TYPE
- CALL MOVHD3 ; MOVE 3 CHARS
- CALL OPENF ; OPEN COMMAND.COM FILE
- DB 20H
- DB COMA1-$-1 AND 0FFH ; ERROR?
-
- * ERROR ROUTINE TO SELECT USER 0 IF ALL ELSE FAILS
- LDA TSELUSR ; GET USER FLAG
- ORA A ; SET FLAGS
- DB 28H
- DB COMA0-$-1 AND 0FFH ; TRY DISK A: IF ALREADY USER 0
- XRA A ; SELECT USER 0
- MOV E,A
- STA TSELUSR ; RESET TEMPORARY USER NUMBER
- CALL SETUSR
- DB 18H
- DB COMA-$-1 AND 0FFH ; TRY AGAIN
-
- * ERROR ROUTINE TO SELECT DRIVE A: IF DEFAULT WAS ORIGINALLY SELECTED
- COMA0:
- LXI H,TEMPDR ; GET DRIVE FROM CURRENT COMMAND
- XRA A ; A=0
- ORA M
- JNZ COM8 ; ERROR IF ALREADY DISK A:
- MVI M,1 ; SELECT DRIVE A:
- DB 18H
- DB COMA-$-1 AND 0FFH
-
- * FILE FOUND -- PROCEED WITH LOAD
- COMA1:
- LXI H,TPA ; SET START ADDRESS OF MEMORY LOAD
- COM2:
- PUSH H ; SAVE ADDRESS OF NEXT SECTOR
- XCHG ; ... IN DE
- CALL DMASET ; SET DMA ADDRESS FOR LOAD
- LXI D,FCBDN ; READ NEXT SECTOR
- CALL READ
- DB 20H
- DB COM3-$-1 AND 0FFH ; READ ERROR OR EOF?
- POP H ; GET ADDRESS OF NEXT SECTOR
- LXI D,128 ; MOVE 128 BYTES PER SECTOR
- DAD D ; PT TO NEXT SECTOR IN HL
- LXI D,ENTRY-128 ; ARE WE GOING TO WRITE OVER CCP?
- MOV A,L ; COMPARE ADDRESS OF NEXT SECTOR (HL)
- SUB E ; TO START OF CCP (DE)
- MOV A,H
- SBB D
- DB 30H
- DB PRNLE-$-1 AND 0FFH ; ERROR IF SAME
- DB 18H
- DB COM2-$-1 AND 0FFH ; OTHERWISE CONTINUE
-
- * LOAD ERROR
- PRNLE:
- CALL PRINT
- DB 'Bad Load',0
- JMP RSTCCP
-
- COM3:
- POP H ; LOAD COMPLETE!
- DCR A
- DB 20H
- DB PRNLE-$-1 AND 0FFH
- CALL RESETUSR ; RESET CURRENT USER NUMBER
- ; USER MUST BE SET BEFORE LOGIN IS DONE
- CALL DLOGIN ; LOG IN DEFAULT DRIVE
- CALL SCANER ; SEARCH COMMAND LINE FOR NEXT TOKEN
- LXI H,TEMPDR ; SAVE PTR TO DRIVE SPEC
- PUSH H
- MOV A,M ; SET DRIVE SPEC
- STA FCBDN
- MVI A,10H ; OFFSET FOR 2ND FILE SPEC
- CALL SCAN1 ; SCAN FOR IT AND LOAD IT INTO FCBDN+16
- POP H ; SET UP DRIVE SPECS
- MOV A,M
- STA FCBDM
- XRA A
- STA FCBCR
- LXI D,TFCB ; COPY TO DEFAULT FCB
- LXI H,FCBDN ; FROM FCBDN
- MVI B,33 ; SET UP DEFAULT FCB
- CALL MOVEHD
- LXI H,CIBUFF
- COM4:
- MOV A,M ; SKIP TO END OF 2ND FILE NAME
- ORA A ; END OF LINE?
- DB 28H
- DB COM5-$-1 AND 0FFH
- CPI ' ' ; END OF TOKEN?
- DB 28H
- DB COM5-$-1 AND 0FFH
- INX H
- DB 18H
- DB COM4-$-1 AND 0FFH
-
- * LOAD COMMAND LINE INTO TBUFF
- COM5:
- MVI B,0 ; SET CHAR COUNT
- LXI D,TBUFF+1 ; PT TO CHAR POS
- COM6:
- MOV A,M ; COPY COMMAND LINE TO TBUFF
- STAX D
- ORA A ; DONE IF ZERO
- DB 28H
- DB COM7-$-1 AND 0FFH
- INR B ; INCR CHAR COUNT
- INX H ; PT TO NEXT
- INX D
- DB 18H
- DB COM6-$-1 AND 0FFH
-
- * RUN LOADED TRANSCIENT PROGRAM
- COM7:
- MOV A,B ; SAVE CHAR COUNT
- STA TBUFF
- CALL CRLF ; NEW LINE
- CALL DEFDMA ; SET DMA TO 0080
- CALL SETUD ; SET USER/DISK
- CALL TPA ; RUN TRANSCIENT
- CALL SETU0D ; SET USER 0/DISK
- CALL LOGIN ; LOGIN DISK
- JMP RESTRT ; RESTART CCP
-
- * TRANSCIENT LOAD ERROR
- COM8:
- CALL RESETUSR ; RESET CURRENT USER NUMBER
- ; RESET MUST BE DONE BEFORE LOGIN
- CALL DLOGIN ; LOG IN DEFAULT DISK
- JMP ERROR
-
- * RESET SELECTED USER NUMBER IF CHANGED
- RESETUSR:
- LDA TMPUSR ; GET OLD USER NUMBER
- MOV E,A ; PLACE IN E
- JMP SETUSR ; RESET
-
- * FILE TYPE FOR COMMAND
- COMMSG:
- DB 'COM'
-
- * 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
- JMP RESTRT
-
-
- RNGSUB:
- DB 0 ;0=$$$.SUB NOT PRESENT, ELSE $$$.SUB PRESENT
-
- *
- * FILE CONTROL BLOCK (FCB), ONE
- *
- SUBFCB:
- DB 0 ;DISK NAME
- 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
-
- *
- * 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
- PRFLG:
- DB 0 ;PRINTER FLAG (0=NO, 0FFH=YES)
- PAGCNT:
- DB NLINES-2 ;LINES LEFT ON PAGE
- IORESL:
- DB 0 ;I/O RESULTS
- TDRIVE:
- DB 1 ;TEMP DRIVE NUMBER
- TEMPDR:
- DB 0
- CHRCNT:
- DB 0 ;CHAR COUNT FOR TYPE
- TMPUSR:
- DB 0 ;TEMPORARY USER NUMBER FOR COM
- TSELUSR:
- DB 0 ;TEMPORARY SELECTED USER NUMBER
-
- END
-
-
- OK
- DB 28H
- DB