TITLE 'CCPR-86 Ver. 1.2 02/08/86' PAGEWIDTH 131 INCLUDE CCPRDEFS.V12 ;Include definitions CSEG ORG 0 JMP CCP ;Cold boot w/ command JMP CCP1 ;Cold boot w/o command JMP CCP2 ;Warm boot OFF1 EQU OFFSET $ DSEG ORG OFF1 CMDBMX DB 127 CMDBNC DB 0 CMDBC1 DB 'CCP Replacement for CP/M-86 Cop' DB 'yright (c) 1985, 1986 Peter H. H' DB 'aas Version 1.2 February 8, 19' DB '86' RS 30 CMDBUF EQU BYTE PTR CMDBMX OFF2 EQU OFFSET $ CSEG ORG OFF2 ; BDOS1: MOV DX,OFFSET FCB BDOS: INT 0E0H ;Call BDOS MOV BP,CS MOV ES,BP RET ;Return ; CONSTAT: MOV CL,C_STAT ;Get Console Status CALL BDOS OR AL,AL ;Set Z-flag JNZ CONIN RET ; CONIN: MOV CL,C_READ ;Console Input CALL BDOS OR AL,AL ;Set Z-flag RET ; SPACE: MOV AL,' ' ;Output a SP ; CONOUT: PUSH CX CALL CONOUT1 POP CX RET CONOUT1: MOV DL,AL MOV CL,C_WRITE ;Console Output JMPS BDOS ; CRLF: MOV AL,CR ;Output a CR CALL CONOUT MOV AL,LF ;Output a LF JMPS CONOUT ; PRINTC: CALL CRLF ;Output CR, LF ; PRINT: POP BX ;Get string address CALL PRINT1 ;Print string INC BX ;Skip past string terminator JMP BX ;Return PRINT1: MOV AL,CS: BYTE PTR [BX] ;Get next character OR AL,AL ;String done? JNZ PRINT2 ;No RET ;Yes, return PRINT2: INC BX ;Address next character PUSH BX CALL CONOUT1 ;Output character POP BX JMPS PRINT1 ;Continue ; SELDISK: MOV DL,AL MOV CL,DRV_SET ;Select Disk JMPS BDOS ; DISPDU: CALL CRLF CALL GETDISK ;Get current disk ADD AL,'A' ;Make it displayable CALL CONOUT1 ;Output character CALL GETUSER ;Get current user IF SUPRES OR AL,AL ;Zero? JZ DISPDU2 ;Yes, suppress output ENDIF ;SUPRES SUB AH,AH AAM ;Convert to decimal OR AH,AH ;Less than 10? JZ DISPDU1 ;Yes PUSH AX MOV AL,AH CALL DISPDU1 ;Output tens digit POP AX DISPDU1: ADD AL,'0' JMPS CONOUT1 ;Output units digit IF SUPRES DISPDU2: RET ENDIF ;SUPRES ; FCBOPEN: ;Open FCB MOV FCBCR,0 MOV DX,OFFSET FCB ; OPENF: MOV CL,F_OPEN ;Open File OPENF1: CALL BDOS OPENF2: MOV RETCODE,AL ;Save return code INC AL ;Set Z-flag RET ; CLOSEF: MOV CL,F_CLOSE ;Close File CALL OPENF1 ;Good CLOSE? JZ CLOSEF1 ;No RET ;Yes, return CLOSEF1: CALL PRINTC DB CR,LF,'Close error',0 JMP CCPRET ; SEARCHF: MOV CL,F_SFIRST ;Search for First JMPS SEARCHN1 ; SEARCHN: MOV CL,F_SNEXT ;Search for Next SEARCHN1: CALL BDOS1 JMPS OPENF2 ; DELETEF: MOV CL,F_DELETE ;Delete File JMP BDOS ; FCBREAD: MOV DX,OFFSET FCB ; READSEQ: MOV CL,F_READ ;Read Sequential CALL BDOS OR AL,AL ;Set Z-flag RET ; RENAMEF: MOV CL,F_RENAME ;Rename File JMP BDOS1 ; GETUSER: MOV DL,0FFH ; SETUSER: MOV CL,F_USERNUM ;Get/Set User Code JMP BDOS ; GETDISK: MOV CL,DRV_GET ;Return Current Disk JMP BDOS ; SETDMAB: MOV CL,F_DMASEG ;Set DMA Base JMP BDOS ; SETDMA: MOV CL,F_DMAOFF ;Set DMA Address JMP BDOS ; UPCASE: CMP AL,'a' ;Less than 'a' JB UPCASE1 ;Yes, return CMP AL,'z' ;Greater than 'z' JA UPCASE1 ;Yes, return AND AL,5FH ;Convert lower to upper case UPCASE1: RET IF WHEEL ; WHLCHK: TEST WHLBYTE,0FFH ;Set Z-flag RET ENDIF ;WHEEL ; PROMPT: PUSH AX CALL DISPDU POP AX JMP CONOUT1 ; GETCMD: TEST SUBIND,0FFH ;SUBMITing commands JZ GETCMD2 ;No IF SUBON SUB AL,AL ;Log-in A: disk CALL SELDISK SUB DL,DL ;Set user zero CALL SETUSER MOV DX,OFFSET SUBFCB ;Open $$$.SUB CALL OPENF JZ GETCMD1 ;Abort if end-of-file MOV AL,SUBFRC ;Get last record in file DEC AL ;Compute next to last MOV SUBFCR,AL ;Set last record in file MOV DX,OFFSET SUBFCB ;Read last record CALL READSEQ JNZ GETCMD1 ;Abort if error CLD MOV SI,OFFSET DISKBUF ;Move last record to command buffer MOV DI,OFFSET CMDBNC MOV CX,64 REP MOVSW MOV SUBFS2,0 ;Set s2 to zero DEC SUBFRC ;Decrement record count MOV DX,OFFSET SUBFCB ;Close $$$.SUB CALL CLOSEF JZ GETCMD1 ;Abort if error CALL SETCDU ;Set current disk, user MOV AL,SPRMPT CALL PROMPT MOV BX,OFFSET CMDBC1 ;Display SUBMITed command CALL PRINT1 CALL CONSTAT ;Any key struck? JZ GETCMD3 ;No CALL SUBERA ;Yes, erase $$$.SUB JMP CCP5 ;Restart GETCMD1: CALL SUBERA1 ;Erase $$$.SUB GETCMD2: ENDIF ;SUBON IF (NOT SUBON) GETCMD1: CALL SUBERA ;Erase $$$.SUB GETCMD2: ENDIF ;(NOT SUBON) MOV AL,CPRMPT CALL PROMPT MOV CL,C_READSTR ;Read Console Buffer MOV DX,OFFSET CMDBUF CALL BDOS GETCMD3: MOV BX,OFFSET CMDBC1 ;Get command address MOV CL,CMDBNC ;Get command length SUB CH,CH JCXZ GETCMD5 GETCMD4: MOV AL,BYTE PTR [BX] ;Get character CALL UPCASE ;Convert to upper case MOV BYTE PTR [BX],AL ;Store character INC BX LOOP GETCMD4 ;Loop 'till done GETCMD5: MOV BYTE PTR [BX],0 ;Terminate string MOV NEXTC1,OFFSET CMDBC1 RET ; SUBERA: SUB AL,AL ;Log-in A: disk CALL SELDISK SUB DL,DL ;Log-in user zero CALL SETUSER SUBERA1: MOV DX,OFFSET SUBFCB ;Erase $$$.SUB CALL DELETEF MOV SUBIND,0 JMP SETCDU ;Set current disk, user ; SCANNER: MOV AL,BYTE PTR [SI] OR AL,AL ;End? JZ SCANNER1 ;Yes CMP AL,20H ;CTRL character? JB SCANNER2 ;Yes PUSH DI CLD MOV DI,OFFSET SCANTBL MOV CX,9 REPNZ SCASB POP DI SCANNER1: RET SCANNER2: JMP CCPERR ; SCANBLK: MOV AL,BYTE PTR [SI] OR AL,AL ;End? JZ SCANBLK1 ;Yes CMP AL,' ' ;Space? JNE SCANBLK1 ;No INC SI JMPS SCANBLK SCANBLK1: RET ; SCANFIL: PUSH CX CALL SCANNER POP CX JZ SCANFIL4 INC BX CMP AL,'*' ;Asterisk? JNE SCANFIL1 ;No MOV AL,'?' ;Yes, make into a question JMPS SCANFIL2 SCANFIL1: INC SI SCANFIL2: MOV BYTE PTR [BX],AL LOOP SCANFIL SCANFIL3: CALL SCANNER JZ SCANFIL5 INC SI JMPS SCANFIL3 SCANFIL4: INC BX MOV BYTE PTR [BX],' ' LOOP SCANFIL4 SCANFIL5: RET ; BLDFCB: MOV CMDBNC,0 BLDFCB1: MOV BX,OFFSET FCB BLDFCB2: PUSH BX ;Save FCB address SUB AX,AX ;Reset NEWDISK, NEWUSER MOV WORD PTR NEWDISK,AX MOV SI,NEXTC1 CALL SCANBLK MOV NEXTC2,SI JZ BLDFCB5 PUSH SI MOV CX,3 BLDFCB3: INC SI MOV AL,BYTE PTR [SI] OR AL,AL JZ BLDFCB4 CMP AL,':' ;Colon present? JE BLDFCB6 ;Yes, process D:, DU:, or DUU: LOOP BLDFCB3 BLDFCB4: ;No POP SI BLDFCB5: MOV AL,CURDISK ;Get current disk INC AL ;Make one-based JMP BLDFCB14 BLDFCB6: POP SI MOV AL,BYTE PTR [SI] CMP AL,'A' ;Less than 'A'? JB BLDFCB9 ;Yes, process U: or UU: MOV AH,'P' ;Assume no WHEEL IF (WMAXD AND (MAXDISK LT 'P')) CALL WHLCHK ;MAXDISK in effect? JNZ BLDFCB7 ;No MOV AH,MAXDISK ;Yes BLDFCB7: ENDIF ;(WMAXD AND (MAXDISK LT 'P')) CMP AL,AH ;Good disk? JBE BLDFCB8 ;Yes IF (RAMON AND WMAXD AND (MAXDISK LT 'P') AND (RAMDISK GT MAXDISK)) CMP AL,RAMDISK ;RAM disk? JE BLDFCB8 ;Yes ENDIF ;(RAMON AND WMAXD AND (MAXDISK LT 'P') AND (RAMDISK GT MAXDISK)) JMPS BLDFCB12 ;Neither, abort BLDFCB8: SUB AL,'A' INC AL ;Make one-based MOV NEWDISK,AL ;Save new disk CMP BYTE PTR 1[SI],':' ;Is D: properly terminated? JE BLDFCB13 ;Yes, all done INC SI ;No, process DU: or DUU: MOV AL,BYTE PTR [SI] BLDFCB9: CMP AL,'0' ;less than '0' JB BLDFCB12 ;Yes, abort CMP AL,'9' ;Greater than '9' JA BLDFCB12 ;Yes, abort SUB AL,'0' MOV AH,AL CMP BYTE PTR 1[SI],':' ;Is DU: or U: properly terminated? JE BLDFCB10 ;Yes, all done INC SI ;No, process DUU: or UU: MOV AL,BYTE PTR [SI] CMP AL,'0' ;Less than '0' JB BLDFCB12 ;Yes, abort CMP AL,'9' ;Greater than '9' JA BLDFCB12 ;Yes, abort SUB AL,'0' AAD ;Convert to binary MOV AH,AL CMP BYTE PTR 1[SI],':' ;Is DUU: or UU: properly terminated? JNE BLDFCB12 ;No, abort BLDFCB10: MOV AL,15 ;Assume no WHEEL IF (WMAXU AND (MAXUSER LT 15)) CALL WHLCHK ;MAXUSER in effect? JNZ BLDFCB11 ;No MOV AL,MAXUSER ;Yes BLDFCB11: ENDIF ;(WMAXU AND (MAXUSER LT 15)) CMP AH,AL ;User allowable? JA BLDFCB12 ;No, abort INC AH ;Make one-based MOV NEWUSER,AH ;Save new user MOV AL,NEWDISK ;Get new disk JMPS BLDFCB13 BLDFCB12: SUB AX,AX ;Reset NEWDISK, NEWUSER MOV WORD PTR NEWDISK,AX DEC AH ;Indicate error POP BX ;Get back FCB address JMPS BLDFCB18 BLDFCB13: INC SI ;Skip over ':' INC SI BLDFCB14: MOV BYTE PTR [BX],AL ;Place NEWDISK in FCB MOV CX,8 ;Scan FN CALL SCANFIL CMP AL,'.' ;'.' present? JNE BLDFCB15 ;Yes, skip over it INC SI BLDFCB15: MOV CX,3 ;Scan FT CALL SCANFIL INC BX CLD MOV DI,BX MOV CX,3 SUB AL,AL REP STOSB MOV NEXTC1,SI POP BX MOV CX,11 SUB AH,AH BLDFCB16: INC BX CMP BYTE PTR [BX],'?' ;'?' present JNE BLDFCB17 INC AH ;Yes, count it BLDFCB17: LOOP BLDFCB16 MOV AL,BYTE PTR [SI] BLDFCB18: OR AH,AH RET ; CCP2: MOV NEXTC1,OFFSET CMDBC1 CMP CMDBC1,CTRLC JNE CCP3 MOV CMDBNC,0 CCP3: MOV SP,OFFSET STACK ;Set stack CALL SETCDU JMPS CCP4 CCP1: MOV CMDBNC,0 CCP: MOV SP,OFFSET STACK ;Set stack PUSH CX ;Save passed parameter MOV DI,13EAH ;Patch BDOS ... MOV AX,OFFSET SUBIND ;... so we're told ... STOSW ;... about $$$.SUB file MOV CL,DRV_ALLRESET ;Reset Disk System CALL BDOS MOV SUBIND,AL ;Save $$$.SUB indicator MOV CL,MC_ALLFREE ;Free All Memory CALL BDOS POP AX ;Get passed parameter PUSH AX AND AL,0FH ;Extract disk MOV CURDISK,AL CALL SELDISK POP AX ;Get passed parameter MOV CL,4 ;Extract user SHR AL,CL AND AL,0FH MOV CURUSER,AL MOV DL,AL CALL SETUSER CCP4: CALL CCPDMA ;Set DMA CMP CMDBNC,0 JNE CCP6 CCP5: MOV SP,OFFSET STACK ;Set stack CALL CCPDMA ;Set DMA CALL GETCMD ;Get command CCP6: CALL GETDISK ;Get BDOS's version of current disk MOV CURDISK,AL ;Save it CALL GETUSER ;Get BDOS's version of current user MOV CURUSER,AL ;Save it CMP CMDBC1,COMMENT ;Is command a comment? JE CCP5 ;Yes, ignore it CLD MOV SI,NEXTC1 CALL SCANBLK JZ CCP5 CALL BLDFCB1 JNZ CCPERR CMP WORD PTR NEWDISK,0 ;New disk or new user specified? JNZ CCP10 ;Yes, may be transient command CMP FCBF1,' ' ;File specified? JE CCPERR ;No, abort IF (DIRON OR ERAON OR RENON OR TYPEON) MOV BL,NCMNDS ;Lookup command in command table CLD MOV DI,OFFSET CMDTBL CCP7: MOV SI,OFFSET FCBF1 ;Match? MOV CX,4 REP CMPSB JNE CCP8 ;No CMP BYTE PTR [SI],' ' ;Command properly terminated? JNE CCP9 ;No, must be transient command JMP WORD PTR [DI] ;Yes, go do built-in command CCP8: ADD DI,CX ;Skip over remainder of name ADD DI,2 ;Skip over address DEC BL ;Any more built-in commands? JNZ CCP7 ;Yes, continue lookup ENDIF ;(DIRON OR ERAON OR RENON OR TYPEON) CCP9: JMP TRANSCMD CCP10: CMP FCBF1,' ' ;File specified? JNE CCP9 ;Yes, must be transient command ; ; d: Switches default disk ; u: or uu: Switches default user ; du: or duu: Switches both default disk and user ; IF WDU CALL WHLCHK ;DU: allowed? JZ CCPERR ;No, abort ENDIF ;WDU CALL SETND ;Disk changed? JNC CCP11 ;No MOV CURDISK,AL ;Yes, new disk becomes current CCP11: CALL SETNU ;User changed? JNC CCP12 ;No MOV CURUSER,DL ;Yes, new user becomes current CCP12: JMP CCP5 ; CCPRET: CALL SETCDU CALL BLDFCB1 CMP WORD PTR NEWDISK,0 ;Disk or user specified? JNE CCPERR ;Yes CMP FCBF1,' ' ;File specified? JE CCP12 ;No ; CCPERR: CALL CRLF ;Go to new line MOV BX,NEXTC2 ;Where to start CCPERR1: MOV AL,BYTE PTR [BX] ;Get character OR AL,AL ;Zero? JZ CCPERR2 ;Yes, end of command CMP AL,' ' ;Space? JE CCPERR2 ;Yes, end of parameter PUSH BX CALL CONOUT1 ;Output character POP BX INC BX JMPS CCPERR1 ;Keep looking for end CCPERR2: MOV AL,'?' ;Output '?' CALL CONOUT1 CALL CRLF ;Go to new line MOV CMDBNC,0 JMP CCP5 ; CCPDMA: MOV DX,CS ;Set segment CALL SETDMAB MOV DX,OFFSET DISKBUF ;Set offset CALL SETDMA RET ; SETCDU: MOV AL,CURDISK ;Get current disk CALL SELDISK ;Set disk MOV DL,CURUSER ;Get current user JMP SETUSER ;Set user ; SETNDU: MOV FCBDR,0 ;Initialize FCB for new disk SETNDU1: CALL SETND ;Set new disk ; SETNU: MOV DL,NEWUSER ;Get new user OR DL,DL ;Was it specified? JZ SETNU1 ;No, leave DEC DL CMP DL,CURUSER ;User changed? JE SETNU1 ;No, leave PUSH DX CALL SETUSER ;Yes, set new user POP DX STC ;Indicate new user set SETNU1: RET ; SETND: MOV AL,NEWDISK ;Get new disk OR AL,AL ;Was it specified? JZ SETND1 ;No, leave DEC AL CMP AL,CURDISK ;Disk changed? JE SETND1 ;No, leave PUSH AX CALL SELDISK ;Yes, set new disk POP AX STC ;Indicate new disk set SETND1: RET IF DIRON ; DIRCMD: ;DIR Built-in Command ; ; DIR [] Displays $DIR files ; DIR S Displays $SYS files ; DIR A Displays both $DIR and $SYS files ; DIR K Displays $ARCV files ; DIR N Displays non-$ARCV files ; SUB AX,AX ;Initialize some variables MOV WORD PTR DIRIND1,AX ENDIF ;DIRON IF (DIRON AND DIRDS AND DIRDT) MOV FILCNT,AX MOV TOTSPC,AX ENDIF ;(DIRON AND DIRDS AND DIRDT) IF DIRON MOV DIRIND3,AL MOV DIRTYPE,SYSTYP CALL BLDFCB INC AH ;Error? JNZ DIR2 ;No DIR1: JMP CCPERR ;Yes, abort DIR2: MOV SI,NEXTC1 CALL SCANBLK ;Was option specified? JZ DIR6 ;No INC SI MOV NEXTC1,SI CMP AL,SYSOPT ;Was SYS specified? JNZ DIR3 ;No NOT DIRIND1 ;Indicate SYS option JMPS DIR6 DIR3: CMP AL,ALLOPT ;Was ALL specified? JNZ DIR4 ;No NOT DIRIND3 ;Indicate ALL option JMPS DIR6 DIR4: ENDIF ;DIRON IF (DIRON AND WARCV) CALL WHLCHK ;Other option allowed? JZ DIR1 ;No, abort ENDIF ;(DIRON AND WARCV) IF DIRON MOV DIRTYPE,ARCVTYP CMP AL,ARCOPT ;Was ARCV specified? JNE DIR5 ;No NOT DIRIND1 ;Indicate ARCV option JMPS DIR6 DIR5: CMP AL,NARCOPT ;Was non-ARCV specified? JE DIR6 ;Yes MOV NEXTC2,SI JMPS DIR1 ;Unsupported option, abort DIR6: CALL DIR11 TEST DIRIND2,0FFH ;Any excluded files? JZ DIR10 ;No CALL CRLF CALL CRLF TEST DIRIND1,0FFH ;Affirmative attribute? JZ DIR7 CALL PRINT ;No DB 'Non-',0 DIR7: CMP DIRTYPE,ARCVTYP ;Archive type? JNE DIR8 CALL PRINT ;Yes DB 'Archive',0 JMPS DIR9 DIR8: CALL PRINT ;No, must be system type DB 'System',0 DIR9: CALL PRINT DB ' file(s) exist',0 DIR10: JMP CCPRET DIR11: CALL SETNDU CMP FCBF1,' ' ;Is FN blank? JNE DIR13 ;No CLD MOV DI,OFFSET FCBF1 ;Yes, make FN+FT all wild MOV CX,11 MOV AL,'?' REP STOSB DIR13: ENDIF ;DIRON IF (DIRON AND DIRDS) MOV SI,OFFSET FCBF1 ;Save AFN MOV DI,OFFSET SAVEAFN CALL MOVED1 MOV CL,DRV_DPB ;Get disk parameters CALL BDOS MOV AL,CS: BYTE PTR 3[BX] SUB AH,AH MOV RNDMASK,AX ;Save rounding mask ENDIF ;(DIRON AND DIRDS) IF DIRON MOV DL,0 PUSH DX CALL SEARCHF JNZ DIR14 CALL NOFILE JMP DIR24 DIR14: MOV AL,RETCODE ;Get directory code MOV CL,5 ;Multiply by 32 SHL AL,CL MOV CL,AL TEST DIRIND3,0FFH ;ALL option? JNZ DIR16 ;Yes MOV AL,DIRTYPE ;Get type of test ($SYS or $ARCV) CALL GETBYTE ;Get associated byte RCL AL,1 ;MSB set? JNC DIR15 ;No TEST DIRIND1,0FFH ;Include or exclude? JNZ DIR16 ;Include, display file MOV DIRIND2,0FFH ;Set exclude indicator JMP DIR23 ;Go search for next DIR15: TEST DIRIND1,0FFH ;Include or exclude? JZ DIR16 ;Include, display file MOV DIRIND2,0FFH ;Set exclude indicator JMP DIR23 ;Go search for next DIR16: POP DX MOV AL,DL INC DL ;Increment file count PUSH DX AND AL,3 ;Four files displayed? PUSH AX JNZ DIR17 ENDIF ;DIRON IF (DIRON AND DIRDU) PUSH CX CALL DISPDUD ;Yes, display DU: on new line POP CX ENDIF ;(DIRON AND DIRDU) IF (DIRON AND (NOT DIRDU)) CALL CRLF ;Yes, go to new line ENDIF ;(DIRON AND (NOT DIRDU)) IF DIRON JMPS DIR18 DIR17: PUSH CX CALL PRINT ;No, generate separator ENDIF ;DIRON IF (DIRON AND (DIRSEP NE ' ')) DB ' ',DIRSEP ENDIF ;DIRON AND (DIRSEP NE ' ')) IF DIRON DB ' ',0 POP CX DIR18: MOV CH,FNOFF ;Offset of FN DIR19: MOV AL,CH ;Save offset CALL GETBYTE ;Get associated byte AND AL,7FH ;Kill MSB CMP AL,' ' ;Space? JNE DIR21 ;Yes POP AX PUSH AX CMP AL,3 JNE DIR20 MOV AL,FTOFF ;Offset of FT CALL GETBYTE AND AL,7FH CMP AL,' ' JE DIR22 DIR20: MOV AL,' ' DIR21: CALL CONOUT ;Display character INC CH ;Advance to next character CMP CH,12 ;Done with FN and FT? JE DIR22 ;Yes, display space CMP CH,9 ;Done with FN? JNE DIR19 ;No MOV AL,TYPSEP ;Yes, display separator CALL CONOUT JMPS DIR19 ;Go do FT DIR22: POP AX ;Cleanup stack ENDIF ;DIRON IF (DIRON AND DIRDS AND DIRDT) INC FILCNT ;Increment file count ENDIF ;(DIRON AND DIRDS AND DIRDT) IF (DIRON AND DIRDS) MOV AL,FNOFF ;Get FN+FT CALL GETBYTE MOV SI,BX ;Move it to FCB CALL MOVED MOV CL,F_SIZE ;Get file size in records CALL BDOS1 MOV AX,WORD PTR FCBR0 MOV DL,FCBR2 MOV CX,RNDMASK ;Round up in BLS units MOV DH,CH ADD AX,CX ADC DX,0 NOT CX AND AX,CX MOV CX,8 ;Convert records to kilobytes DIV CX ENDIF ;(DIRON AND DIRDS) IF (DIRON AND DIRDS AND DIRDT) ADD TOTSPC,AX ;Update total space ENDIF ;(DIRON AND DIRDS AND DIRDT) IF (DIRON AND DIRDS) CALL PRINTD MOV AL,'k' ;Display unit CALL CONOUT CALL SEARCHF ;Restart search JZ DIR24 ;Abort if error MOV SI,OFFSET SAVEAFN ;Restore AFN CALL MOVED SUB AL,AL MOV CX,21 REP STOSB ENDIF ;(DIRON AND DIRDS) IF DIRON DIR23: CALL CONSTAT ;Any key struck? JNZ DIR25 ;Yes, abort CALL SEARCHN ;No, continue search JZ DIR24 ;Abort if error JMP DIR14 DIR24: ENDIF ;DIRON IF (DIRON AND DIRDS AND DIRDT) CALL DISPDUD CALL PRINT DB 'has ',0 MOV AX,TOTSPC CALL PRINTD CALL PRINT DB 'k in ',0 MOV AX,FILCNT CALL PRINTD CALL PRINT DB ' file(s)',0 ENDIF ;(DIRON AND DIRDS AND DIRDT) IF DIRON DIR25: POP DX RET ; GETBYTE: MOV BX,OFFSET DISKBUF ADD AL,CL SUB AH,AH ADD BX,AX MOV AL,BYTE PTR [BX] RET ENDIF ;DIRON IF (DIRON AND (DIRDU OR DIRDS)) ; DISPDUD: CALL DISPDU CALL PRINT DB ': ',0 RET ENDIF ;(DIRON AND (DIRDU OR DIRDS)) IF (DIRON AND DIRDS) ; MOVED: MOV DI,OFFSET FCBF1 MOVED1: CLD MOV CX,11 REP MOVSB RET ; PRINTD: MOV SIGIND,0 ;Reset significance indicator MOV BX,1000 ;Display thousands digit CALL PRINTD1 MOV BX,100 ;Display hundreds digit CALL PRINTD1 MOV BX,10 ;Display tens digit CALL PRINTD1 ADD AL,'0' ;Display units digit JMP CONOUT PRINTD1: SUB DX,DX ;Prepare double-length accumulator DIV BX ADD AL,'0' ;Make quotient displayable CMP AL,'0' ;Is it zero? JNE PRINTD2 ;No, display it TEST SIGIND,0FFH ;Significant digit encountered? JNZ PRINTD3 ;Yes, display it MOV AL,' ' ;No, do zero-suppress JMPS PRINTD3 PRINTD2: MOV SIGIND,0FFH ;Set significance indicator PRINTD3: PUSH DX ;Save remainder CALL CONOUT ;Display digit POP AX ;Remainder becomes dividend RET ENDIF ;(DIRON AND DIRDS) IF (DIRON OR ERAON OR TYPEON OR RENON) ; NOFILE: CALL PRINTC DB 'No file',0 RET ENDIF ;(DIRON OR ERAON OR TYPEON OR RENON) IF (ERAON OR RENON) ; CONFIRM: PUSH BX CALL PRINT1 ;Issue message MOV CL,C_READSTR ;Read Console Buffer MOV DX,OFFSET ANSBUF CALL BDOS MOV BX,OFFSET ANSBNC DEC BYTE PTR [BX] ;Single character response? JNZ CONFIRM2 ;No, try again INC BX ;Get response address MOV AL,BYTE PTR [BX] ;Get response CALL UPCASE ;Convert to upper case CMP AL,'Y' ;Was response 'Y'? JE CONFIRM1 ;Yes, set Z-flag CMP AL,'N' ;Was response 'N'? JNE CONFIRM2 ;No, try again OR AL,AL ;Yes, reset Z-flag CONFIRM1: POP BX RET CONFIRM2: POP BX JMPS CONFIRM ENDIF ;(ERAON OR RENON) IF ERAON ; ERACMD: ;ERA Built-in Command ; ; ERA Erases files ; ENDIF ;ERAON IF (ERAON AND WERA) CALL WHLCHK ;ERA allowed? JZ ERA2 ;No, abort ENDIF ;(ERAON AND WERA) IF ERAON CALL BLDFCB CMP AH,11 ;Was FN+FT all wild? JNE ERA1 ;No MOV BX,OFFSET ERAMSG CALL CONFIRM ;Erase all files? JE ERA3 ;Yes, do the erase JMP CCP5 ;No, abort ERA1: CMP FCBF1,' ' ;Any file? JNE ERA3 ;Yes ERA2: JMP CCPERR ;No, abort ERA3: CALL SETNDU MOV DX,OFFSET FCB CALL DELETEF INC AL JNZ ERA5 ERA4: CALL NOFILE ERA5: JMP CCPRET ENDIF ;ERAON IF RENON ; RENCMD: ;REN Built-in Command ; ; REN = Renames a file ; ENDIF ;RENON IF (RENON AND WREN) CALL WHLCHK ;REN allowed? JZ REN8 ;No, abort ENDIF ;(RENON AND WREN) IF RENON CALL BLDFCB ;New file good? JNZ REN8 ;No, abort PUSH WORD PTR NEWDISK ;Save new file disk, user CALL SETNDU ;Set new file disk, user CALL SEARCHF ;New file exist? JZ REN2 ;No MOV BX,OFFSET RENMSG CALL CONFIRM ;Erase file? JE REN1 ;Yes POP AX JMP CCP5 ;No, abort REN1: MOV DX,OFFSET FCB ;Yes, erase it CALL DELETEF REN2: CLD MOV SI,OFFSET FCB MOV DI,OFFSET FCBD0 MOV CX,8 REP MOVSW MOV SI,NEXTC1 CALL SCANBLK CMP AL,'=' ;'=' present? JNE REN6 ;No, abort INC SI MOV NEXTC1,SI CALL BLDFCB ;Old file good? JNZ REN6 ;No, abort MOV BX,OFFSET NEWDISK MOV CX,WORD PTR [BX] ;Get old file disk, user POP WORD PTR [BX] ;Restore new file disk, user OR CX,CX ;Old file disk, user specified? JZ REN3 ;No CMP CX,WORD PTR [BX] ;Old file disk, user same as new? JNE REN7 ;No, error REN3: MOV FCBDR,0 CALL SEARCHF ;Old file exist? JNZ REN4 ;Yes CALL NOFILE ;No, error JMPS REN5 REN4: CALL RENAMEF ;Rename file REN5: JMP CCPRET REN6: POP AX ;Clean stack REN7: CALL SETCDU ;Set current disk, user REN8: JMP CCPERR ENDIF ;RENON IF TYPEON ; TYPECMD: ;TYPE Built-in Command ; ; TYPE Displays a file ; ENDIF ;TYPEON IF (TYPEON AND WTYPE) CALL WHLCHK ;TYPE allowed? JZ TYPE4 ;No, abort ENDIF ;(TYPEON AND WTYPE) IF TYPEON CALL BLDFCB ;File good? JNZ TYPE4 ;No, abort CMP FCBF1,' ' ;File specified? JE TYPE4 ;No, abort CALL SETNDU ;Set disk, user CALL FCBOPEN ;Good OPEN? JZ TYPE5 ;No CALL CRLF MOV BX,81H ;Indicate buffer empty TYPE1: CMP BX,80H ;Buffer empty? JB TYPE2 ;No PUSH BX CALL FCBREAD ;Fill buffer POP BX JNZ TYPE3 MOV BX,0 ;Point to first byte TYPE2: MOV AL,BYTE PTR DISKBUF[BX] ;Get a byte INC BX ;Point to next CMP AL,CTRLZ ;CTRL-Z? JE TYPE6 ;Yes, all done PUSH BX CALL CONOUT1 ;Output byte CALL CONSTAT ;Break? POP BX JZ TYPE1 ;No JMPS TYPE6 TYPE3: DEC AL JZ TYPE6 CALL PRINTC DB 'Read error',0 CALL SETCDU TYPE4: JMP CCPERR TYPE5: CALL NOFILE TYPE6: JMP CCPRET ENDIF ;TYPEON ; TRANSCMD: ;Invoke Transient Command ; ; [du:]fn Invokes command files ; CMP FCBT1,' ' ;FT specified? JNE TRANS5 ;Yes, abort CALL SETNDU CLD MOV SI,OFFSET CMDTYP ;Set FT to 'CMD' MOV DI,OFFSET FCBT1 MOV CX,3 REP MOVSB MOV SI,OFFSET PATH ;Set PATH TRANS1: CALL FCBOPEN ;Good OPEN? JNZ TRANS6 ;Yes, go do program load LODSW ;Get next PATH word OR AL,AL ;End of PATH? JZ TRANS4 ;Yes, abort CMP AL,'$' ;Default disk? JNE TRANS2 ;No MOV AL,CURDISK ;Yes, get current disk INC AL ;Make it one-based, like PATH TRANS2: CMP AH,'$' ;Default user? JNE TRANS3 ;No MOV AH,CURUSER ;Yes, get current user INC AH ;Make it one-based, like PATH TRANS3: MOV WORD PTR NEWDISK,AX CALL SETNDU1 ;Set new disk, user JMPS TRANS1 ;Retry TRANS4: CALL SETCDU ;Set current disk, user TRANS5: JMP CCPERR ;Abort TRANS6: MOV CL,P_LOAD ;Program Load CALL BDOS1 INC AX ;Good PROGRAM LOAD? JNZ TRANS7 ;Yes CALL PRINTC ;No, tell user DB 'Full',0 JMP CCPRET TRANS7: MOV DMABASE,BX ;Save Base Page Address CALL SETCDU ;Set current disk, user CALL BLDFCB1 ;Setup FCB1 MOV AL,NEWDISK MOV BYTE PTR FCBDR,AL MOV BX,OFFSET FCB + 10H ;Setup FCB2 CALL BLDFCB2 MOV AL,NEWDISK MOV BYTE PTR FCBDR + 10H,AL CLD MOV SI,OFFSET FCB ;Move FCB1 and FCB2 to default FCB MOV ES,DMABASE MOV DI,OFFSET DFLTFCB MOV CX,16 REP MOVSW SUB AL,AL STOSB MOV SI,OFFSET CMDBC1 CALL SCANBLK ;Any command tail? JZ TRANS10 ;No TRANS8: LODSB OR AL,AL ;End of command buffer? JZ TRANS10 ;Yes, end of command CMP AL,' ' ;End of command? JE TRANS9 ;Yes JMPS TRANS8 TRANS9: CALL SCANBLK ;Find command tail TRANS10: MOV CH,0 DEC SI ;Move command tail MOV DI,OFFSET DFLTBUF + 1 TRANS11: LODSB STOSB OR AL,AL ;Done? JZ TRANS12 ;Yes INC CH ;No, increment length JMPS TRANS11 TRANS12: MOV ES: DFLTBUF,CH ;Set command tail length MOV AX,ES: WORD PTR BC0 ;Setup far call address MOV CMDFSEG,AX MOV AH,ES: M80 AND AX,0100H ;Allow for 8080 and compact models MOV CMDFOFF,AX CALL CRLF MOV CMDBNC,0 MOV DX,DMABASE ;Set DMAB address PUSH DX CALL SETDMAB MOV DX,OFFSET DFLTBUF ;Set DMA address CALL SETDMA POP DS ;Set DS PUSH DS POP ES ;Assume no extra segment CMP WORD PTR BE0,0 ;Extra segment present? JE TRANS13 MOV ES,WORD PTR BE0 ;Yes, set ES to BE TRANS13: CALLF CMDFILE ;Call CMD file MOV SP,OFFSET STACK ;Reset stack MOV CL,P_TERMCPM ;System Reset SUB DX,DX JMP BDOS CMDFOFF DW 0 CMDFSEG DW 0 CMDFILE EQU DWORD PTR CMDFOFF IF ERAON ERAMSG DB CR,LF,'All (y/n)? ',0 ENDIF ;ERAON IF RENON RENMSG DB CR,LF,'Erase (y/n)? ',0 ENDIF ;RENON OFF3 EQU OFFSET $ DSEG ORG OFF3 INCLUDE CCPRPATH.V12 ;Include PATH table DMABASE DW 0 SUBFDR DB 1 ;dr DB '$$$ ' ;f1, ..., f8 DB 'SUB' ;t1, ..., t3 DB 0 ;ex DB 0 ;s1 SUBFS2 DB 0 ;s2 SUBFRC DB 0 ;rc RS 16 ;d0, ..., dn SUBFCR DB 0 ;cr SUBFCB EQU BYTE PTR SUBFDR SUBIND RB 1 CMDTYP DB 'CMD' FCBDR RS 1 ;dr FCBF1 RS 8 ;f1, ..., f8 FCBT1 RS 1 ;t1 FCBT2 RS 1 ;t2 FCBT3 RS 1 ;t3 FCBEX RS 1 ;ex FCBS1 RS 1 ;s1 RS 2 ;s2, rc FCBD0 RS 16 ;d0, ..., dn FCBCR RS 1 ;cr IF (DIRON AND DIRDS) FCBR0 RS 1 ;r0 FCBR1 RS 1 ;r1 FCBR2 RS 1 ;r2 ENDIF ;(DIRON AND DIRDS) FCB EQU BYTE PTR FCBDR FNOFF EQU OFFSET FCBF1 - OFFSET FCB FTOFF EQU OFFSET FCBT1 - OFFSET FCB IF DIRON SYSTYP EQU OFFSET FCBT2 - OFFSET FCB ARCVTYP EQU OFFSET FCBT3 - OFFSET FCB ENDIF ;DIRON DIRIND1 RB 1 ;Must be in order, ind1 then ind2 DIRIND2 RB 1 DIRIND3 RB 1 DIRTYPE RB 1 RETCODE RB 1 IF (DIRON AND DIRDS) SAVEAFN RB 11 RNDMASK RW 1 SIGIND RB 1 ENDIF ;(DIRON AND DIRDS) IF (DIRON AND DIRDS AND DIRDT) FILCNT RW 1 TOTSPC RW 1 ENDIF ;(DIRON AND DIRDS AND DIRDT) IF (ERAON OR RENON) ANSBMX DB 7 ANSBNC DB 0 ANSBC1 RS 8 ANSBUF EQU BYTE PTR ANSBMX ENDIF ;(ERAON OR RENON) DISKBUF RS 128 ;Disk buffer RW STKSIZE ;CCP Stack STACK EQU $ CURDISK DB 0 CURUSER DB 0 NEWDISK DB 0 ;Must be in order, disk then user NEWUSER DB 0 SCANTBL DB ' =_.:;<>,' NEXTC1 DW 0 NEXTC2 DW 0 CMDTBL EQU $ IF DIRON DB 'DIR ' DW DIRCMD ENDIF ;DIRON IF ERAON DB 'ERA ' DW ERACMD ENDIF ;ERAON IF RENON DB 'REN ' DW RENCMD ENDIF ;RENON IF TYPEON DB 'TYPE' DW TYPECMD ENDIF ;TYPEON NCMNDS EQU (OFFSET $ - OFFSET CMDTBL)/6 CCPEND EQU OFFSET $ IF (CCPEND LT CCPMAX) ORG CCPMAX - 1 DB 0 ENDIF ;(CCTEND LT CCPMAX) DSEG ORG 0 LC0 RB 1 LC1 RB 1 LC2 RB 1 BC0 RB 1 BC1 RB 1 M80 RB 1 ORG 0FH BE0 RB 1 BE1 RB 1 ORG 5CH DFLTFCB RB 33 ORG 80H DFLTBUF RB 128 CCPSIZE EQU CCPEND ! ERROR ;Size of CCPR