; *********************************************************** ; ; DISASSEMBLY OF CONSOLE COMMAND PROCESSOR ; FOR CP/M VERSION 2.2 ; ; *********************************************************** ; LAST REVISION: 23 DEC 1981 ; *********************************************************** ; ; LEGAL NOTICE: ; ; THIS ASSEMBLY LISTING IS NOT THE PRODUCT OF DIGITAL ; RESEARCH INC. AND AS SUCH CANNOT BE GUARANTEED FOR ; ACCURACY OR COMPLETENESS. THE ASSIGNMENT OF LABELS, ; COMMENTS AND INTERPRETATION OF THE CODE IS THOUGHT ; TO BE APPROPRIATE, BUT MAY NOT BE WHAT WAS ORIGINALLY ; INTENDED. THIS DISCLAIMER RENOUNCES AND IGNORES ALL ; OTHER CLAIMS AND DISCLAIMERS REGARDLESS OF SOURCE. ; NO WARRANTEE IS MADE AS TO THE MERCHANTABILITY OR ; FITNESS FOR ANY PURPOSE. SIMILARITY BETWEEN THIS ; PROGRAM LISTING AND ANY OTHER PROGRAM LIVING OR DEAD ; IS PURELY COINCIDENTAL. ; ; EQUATES ; 0038 = MSIZE: EQU 56 ;CPM SIZE IN KILOBYTES ; BD00 = START: EQU (MSIZE - 20) * 1024 + 2D00H ; 0005 = BDOS: EQU 0005H ;LINK TO OPERATING SYSTEM 0003 = IOBYTE: EQU 0003H ;I/O ASSIGMENT BYTE FOR TRANSIENT PROGRAMS 0004 = LOGIN: EQU 0004H ;USER NUMBER AND DISK NUMBER FOR TRANSIENT PROGRAMS 005C = DFCB: EQU 005CH ;DEFAULT FILE CONTROL BLOCK 0100 = TPA: EQU 0100H ;START OF TRANSIENT PROGRAM AREA 0080 = DDMA: EQU 0080H ;DEFAULT DMA BLOCK 0080 = SECLEN: EQU 0080H ;SECTOR LENGTH := 128 BYTES. C500 = FBASE: EQU START + 0800H ;START OF OPERATING SYSTEM & ;LOCATION OF BDOS SERIAL NUMBERS. ; ; SERIAL NUMBERS ; 0002 = VER: EQU 2 ;CPM VERSION 0002 = REL EQU 2 ;CPM RELEASE 0000 = REV: EQU 00 ;USER REVISION 0000 = SNH EQU 00 ;SERIAL NUMBER, HIGH 0000 = SNL EQU 00 ;SERIAL NUMBER, LOW ; ; NOTE: ; USER MUST INSERT CORRECT SERIAL NUMBER ; IN THE FORMAT HH-LLLL, WHERE HH IS TWO ; DIGITS & LLLL IS FOUR DIGITS. IF THE ; SERIAL NUMBERS IN CCP/CPM AND BDOS/CPM ; DO NOT MATCH, YOU WILL BOMB OUT WHEN ; LOADING A TRANSIENT PROGRAM. ; ; BD00 ORG START ;SET PROGRAM START ; ; NOTE: ; ON ENTRY (C) CONTAINS THE USER NUMBER IN THE ; UPPER 4 BITS, AND THE CURRENT LOGGED IN DISK ; NUMBER IN TO LOWER 4 BITS. THIS IS WHY YOU LOG ; BACK TO DISK B: IF YOU REBOOTED WHILE LOGGED ; INTO B: ; BD00 C35CC0 ORIGIN: JMP CCP1 ;JUMP TO START OF CONSOLE COMMAND PROGRAM ; BD03 C358C0 JMP CCP0 ;JUMP TO START OF CCP W/ CLEARING OF INPUT BUFFER COUNTER ; ; INPUT BUFFER WITH COPYRIGHT MESSAGE THROWN IN ; BD06 7F INPB: DB 127 ;MAXIMUM LENGTH OF INPUT BUFFER BD07 00 INBLEN: DB 0 ;CURRENT LENGTH OF INPUT BUFFER BD08 2020202020BUFFER: DB ' ' BD18 434F505952 DB 'COPYRIGHT (C) 1979, ' BD2C 4449474954 DB 'DIGITAL RESEARCH ' BD3E DS BUFFER+128-$ ; ; POINTERS TO INPUT BUFFER ; BD88 08BD BPTR1: DW BUFFER ;POINTER TO INPUT BUFFER USED WHILE PARSING INPUT LINE BD8A 0000 BPTR2: DW 0000H ;POINTER TO START OF CURRENT COMMAND INN INPUT BUFFER. ;USED BY WHAT FOR ERROR PROMPT. ; *************** ; SUBROUTINE AREA ; *************** ; ; TIES TO BDOS VIA VECTOR IN 0005H ; ; NOTE: ; THE CODE IN THIS SECTION COULD BE CLEANED UP ; SHORTENED BY REARRANGING THINGS TO HAVE THE ; CODE FLOW FROM ONE SEGMENT TO THE NEXT ; INSTEAD OF JUMPING BACK. ; BD8C 5F OUTPUT: MOV E,A ;OUTPUT 1 BYTE TO CONSOLE BD8D 0E02 MVI C,02H ; BD8F C30500 JMP BDOS ; ; ; NOTE: ; WHY NOT INCLUDE OUTPUT INSIDE OF PCHAR AND ; THUS ELIMINATE AN- EXTRA CALL? ; THE ONLY OTHER CALL TO OUTPUT IS IN PMSG, ; WHICH SHOULD BE CHANGED ANYWAY. ; ;PCHAR: PUSH B ; ; MOV E,A ; ; MVI C,02H ; ; CALL BDOS ; ; POP B ; ; RET ; ; BD92 C5 PCHAR: PUSH B ;PRINT A CHARACTER ON THE CONSOLE BD93 CD8CBD CALL OUTPUT ; BD96 C1 POP B ; BD97 C9 RET ; ; BD98 3E0D PCRLF: MVI A,0DH ;PRINT A CARRIAGE RETURN & LINE FEED BD9A CD92BD CALL PCHAR ; BD9D 3E0A MVI A,0AH ; BD9F C392BD JMP PCHAR ; ; BDA2 3E20 SPACE: MVI A,20H ;PRINT A SPACE BDA4 C392BD JMP PCHAR ; ; BDA7 C5 CRMSG: PUSH B ;PRINT A STRING PRECEDED BY A CR/LF BDA8 CD98BD CALL PCRLF ; BDAB E1 POP H ; ; ; THIS CODE COULD BE SHORTENED BY TERMINATING THE ; ERROR CODE STRINGS WITH A '$' AND USING BDOS ; COMMAND 9. ; BDAC 7E PMSG: MOV A,M ;PRINT A STRING TERMINATED BY A NULL BDAD B7 ORA A ; BDAE C8 RZ ; BDAF 23 INX H ; BDB0 E5 PUSH H ; BDB1 CD8CBD CALL OUTPUT ; BDB4 E1 POP H ; BDB5 C3ACBD JMP PMSG ; ; BDB8 0E0D RESET: MVI C,0DH ;RESET THE DISK SYSTEM BDBA C30500 JMP BDOS ; ; BDBD 5F SELDSK: MOV E,A ;SELECT DISK BDBE 0E0E MVI C,0EH ; BDC0 C30500 JMP BDOS ; ; BDC3 CD0500 BDOS1: CALL BDOS ; CALL TO BDOS W/ RETURN VALUE SAVED BDC6 32EEC4 STA RETVAL ; BDC9 3C INR A ;SET THE ZFLAG FOR ERROR CONDITION BDCA C9 RET ; ; BDCB 0E0F OPENF: MVI C,0FH ;OPEN DISK FILE FOR READING OR WRITING BDCD C3C3BD JMP BDOS1 ; CALL TO BDOS W/ RETURN VALUE ; BDD0 AF OPENF1: XRA A ;OPEN FILE @ FCB, AND ZERO RECORD COUNTER BDD1 32EDC4 STA FCB+32 ; BDD4 11CDC4 LXI D,FCB ; BDD7 C3CBBD JMP OPENF ; ; BDDA 0E10 CLOSEF: MVI C,10H ;CLOSE FILE AFTER READING OR WRITING BDDC C3C3BD JMP BDOS1 ; CALL TO BDOS W/ RETURN VALUE ; BDDF 0E11 SRCHF: MVI C,11H ;SEARCH FOR FIRST OCCURENCE OF FILE NAME BDE1 C3C3BD JMP BDOS1 ; CALL TO BDOS W/ RETURN VALUE ; BDE4 0E12 SRCHNX: MVI C,12H ;SEARCH FOR NEXT OCCURENCE OF FILE NAME BDE6 C3C3BD JMP BDOS1 ; CALL TO BDOS W/ RETURN VALUE ; BDE9 11CDC4 SRCHF1: LXI D,FCB ;SEARCH FOR FIRST OCCURENCE OF FILE BDEC C3DFBD JMP SRCHF ; NAME USING (FCB). ; BDEF 0E13 DELETF: MVI C,13H ;DELETE FILE FROM DIRECTORY BDF1 C30500 JMP BDOS ; ; BDF4 CD0500 BDOS2: CALL BDOS ; CALL TO BDOS W/ RETURN VALUE BDF7 B7 ORA A ; BDF8 C9 RET ; ; BDF9 0E14 READF: MVI C,14H ;READ ONE SECTOR FROM DISK BDFB C3F4BD JMP BDOS2 ; CALL TO BDOS W/ RETURN VALUE ; BDFE 11CDC4 READ1: LXI D,FCB ;READ ONE SECTOR USING 'FCB' BE01 C3F9BD JMP READF ; ; BE04 0E15 WRITEF: MVI C,15H ;WRITE ONE SECTOR TO DISK BE06 C3F4BD JMP BDOS2 ; CALL TO BDOS W/ RETURN VALUE ; BE09 0E16 CREATE: MVI C,16H ;CREATE A NEW FILE NAME IN DISK DIRECTORY BE0B C3C3BD JMP BDOS1 ; CALL TO BDOS W/ RETURN VALUE ; BE0E 0E17 RENAME: MVI C,17H ;RENAME EXISTING FILE IN DISK DIRECTORY BE10 C30500 JMP BDOS ; ; BE13 1EFF GETUSR: MVI E,0FFH ;GET CURRENT USER NUMBER ; ; SET USER NUMBER TO VALUE IN (E), EXCEPT IF ; VALUE IS 0FFH. ; BE15 0E20 SETUSR: MVI C,20H ; BE17 C30500 JMP BDOS ; ; ; SET LOG-IN BYTE FOR TRANSIENT PROGRAM WITH CURRENT ; USER NUMBER IN UPPER 4 BITS AND CURRENT DRIVE IN ; LOWER 4 BITS. ; BE1A CD13BE SETLOG: CALL GETUSR ; SET LOG-IN BYTE W/ CURRENT DRIVE & USER NUMBER BE1D 87 ADD A ; BE1E 87 ADD A ; BE1F 87 ADD A ; BE20 87 ADD A ;SHIFT USER NUMBER TO UPPER NIBBLE BE21 21EFC4 LXI H,CURDSK ; BE24 B6 ORA M ;COMBINE WITH DISK NUMBER BE25 320400 STA LOGIN ;PLACE WHERE TRANSIENT PROGRAMS BE28 C9 RET ; CAN FIND IT. ; ; LOG IN CURRENT DISK ; PLACE CURRENT DRIVE NUMBER IN LOG-IN BYTE WITHOUT ; INCLUDING USER NUMBER. ; BE29 3AEFC4 LOGCUR: LDA CURDSK ; BE2C 320400 STA LOGIN ; BE2F C9 RET ; ; ; CONVERT LOWER CASE INPUT TO UPPER CASE ; BE30 FE61 LCUC: CPI 61H ;'A' BE32 D8 RC ; BE33 FE7B CPI 7BH ;'Z'+1 BE35 D0 RNC ; BE36 E65F ANI 5FH ;MASK OFF BIT 5 BE38 C9 RET ; ; ; COMMAND INPUT ; ; IF SUBMIT FLAG <> 0 THEN INPUT FROM SUBMIT FILE\ ; ELSE INPUT FROM KEYBOARD INPUT BUFFER ; BE39 3AABC4 CMNDIN: LDA SUBFL ;CHECK SUBMIT FILE FLAG BE3C B7 ORA A ; BE3D CA96BE JZ LINEIN ;FLAG RESET: GET INPUT FROM KEYBOARD ; ; NOTE ABOUT SUBMIT FILES: ; ; WHEN THE COMMAND SUBMIT ; IS GIVEN, A FILE NAMED $$$.SUB IS COMPILED WITH ; ONE COMMAND LINE PER RECORD IN THE FILE. ; THE FILE IS UNUSUAL IN THAT THE COMMANDS ARE STORED ; IN REVERSE ORDER. THIS MAKES IT SIMPLE FOR THE ; FOLLOWING CODE TO PULL ONE COMMAND OFF AT A TIME, ; ERASING AS IT GOES. NOTE THAT THE SECTOR COUNTER IS ; DECREMENTED AND THE FILE CLOSED EACH TIME. ; WHEN THE LAST COMMAND HAS BEEN EXECUTED, OR IF AN ; ERROR IS ENCOUNTERED, THE $$$.SUB FILE IS ERASED ; AND CONTROL REVERTS TO THE KEYBOARD FOR INPUT. ; BE40 3AEFC4 LDA CURDSK ;FLAG SET: GET INPUT FROM SUBMIT FILE ON CURRENT DISK BE43 B7 ORA A ; BE44 3E00 MVI A,00H ; BE46 C4BDBD CNZ SELDSK ;SET TO DISK 0 IF NOT THERE ALREADY BE49 11ACC4 LXI D,SUBFCB ; POINT TO SUBMIT FILE'S FILE CONTROL BLOCK BE4C CDCBBD CALL OPENF ; OPEN THE SUBMIT FILE FOR READING BE4F CA96BE JZ LINEIN ;GO TO CONSOLE ON OPEN FILE ERROR BE52 3ABBC4 LDA SUBFCB+15 ;GET TOP SECTOR NUMBER BE55 3D DCR A ;DECREMENT? YES $$$.SUB FILES ARE BACKWARDS BE56 32CCC4 STA SUBFCB+32 ;PUT NUMBER IN NEXT SECTOR SLOT BE59 11ACC4 LXI D,SUBFCB ; BE5C CDF9BD CALL READF ;READ SECTOR INTO BUFFER BE5F C296BE JNZ LINEIN ;GO TO CONSOLE ON READ ERROR BE62 1107BD LXI D,INBLEN ;POINT TO START OF KEYBOARD BUFFER BE65 218000 LXI H,DDMA ;POINT TO START OF DEFAULT BUFFER BE68 0680 MVI B,SECLEN ;SET COUNTER BE6A CD42C1 CALL BLKMOV ;MOVE LINE INTO KEYBOARD BUFFER BE6D 21BAC4 LXI H,SUBFCB+14 ; BE70 3600 MVI M,00H ; BE72 23 INX H ; BE73 35 DCR M ;DECREMENT SECTOR COUNT BE74 11ACC4 LXI D,SUBFCB ;CLOSE THE FILE BE77 CDDABD CALL CLOSEF ; BE7A CA96BE JZ LINEIN ;GO TO CONSOLE ON CLOSE ERROR BE7D 3AEFC4 LDA CURDSK ; BE80 B7 ORA A ; BE81 C4BDBD CNZ SELDSK ;SET TO CURRENT DISK IF NOT SO ALREADY BE84 2108BD LXI H,BUFFER ; BE87 CDACBD CALL PMSG ;ECHO THE $$$.SUB LINE TO CONSOLE BE8A CDC2BE CALL KSTAT ;CHECK FOR A KEYBOARD BREAK BE8D CAA7BE JZ LINP1 ;NO BREAK- CONTINUE BE90 CDDDBE CALL EXITSB ; BREAK- CLOSE OFF SUBMIT MODE BE93 C382C0 JMP NXTCMD ;THIS LEAVES THE RETURN ADDRESS ON THE ;STACK, BUT NXTCMD RE-INITIALIZES STACK ; ; GET THE INPUT FROM THE CONSOLE DEVICE ; BE96 CDDDBE LINEIN: CALL EXITSB ;RESET SUBMIT MODE FLAGS< ETC BE99 CD1ABE CALL SETLOG ; SET LOG-IN BYTE W/ CURRENT DRIVE & USER NUMBER BE9C 0E0A MVI C,0AH ;BDOS COMMAND 10 ::= READ INPUT BUFFER BE9E 1106BD LXI D,INPB ;POINT TO START OF INPUT BUFFER BEA1 CD0500 CALL BDOS ;GET A LINE FROM THE CONSOLE BEA4 CD29BE CALL LOGCUR ; BEA7 2107BD LINP1: LXI H,INBLEN ; BEAA 46 MOV B,M ;MOVE THE LINE BYTE COUNT INTO (B) BEAB 23 LINP2: INX H ;STEP THROUGH BUFFER CHANGING LOWER BEAC 78 MOV A,B ;CASE INTO UPPER CASE. BEAD B7 ORA A ; BEAE CABABE JZ LINP3 ;EXIT WHEN (B)=0 BEB1 7E MOV A,M ; BEB2 CD30BE CALL LCUC ;CONVERT LOWER CASE TO UPPER CASE BEB5 77 MOV M,A ; BEB6 05 DCR B ; BEB7 C3ABBE JMP LINP2 ;LOOP ; BEBA 77 LINP3: MOV M,A ;POKE A ZERO INTO END OF LINE TO MARK END BEBB 2108BD LXI H,BUFFER ;SAVE COMMAND STARTING ADDRESS BEBE 2288BD SHLD BPTR1 ; FOR LATER USE. BEC1 C9 RET ; ; ; KEYBOARD STATUS CHECK ; RETURN WITH ZFLAG SET IS NO KEY PRESSED ; ELSE RETURN WITH CHARACTER IN ACCUMULATOR ; BEC2 0E0B KSTAT: MVI C,0BH ; BEC4 CD0500 CALL BDOS ; BEC7 B7 ORA A ; BEC8 C8 RZ ; BEC9 0E01 MVI C,01H ; BECB CD0500 CALL BDOS ; BECE B7 ORA A ; BECF C9 RET ; ; ; INTEROGATE THE DISK ; BED0 0E19 INTDSK: MVI C,19H ; BED2 C30500 JMP BDOS ; ; ; SET THE DMA ADDRESS ; BED5 118000 SETDMA: LXI D,DDMA ; BED8 0E1A STDMA1: MVI C,1AH ; BEDA C30500 JMP BDOS ; ; ; EXIT THE SUBMIT MODE ; CHECK TO SEE IF THE SUBMIT FLAG IS SET ; AND RESET IT, ALONG WITH THE DISK SELECTION ; ERASE ANY $$$.SUB FILE THAT MAY BE IN THE DIRECTORY ; BEDD 21ABC4 EXITSB: LXI H,SUBFL ;SUBMIT FILE FLAG BEE0 7E MOV A,M ; BEE1 B7 ORA A ; BEE2 C8 RZ ;NOT IN SUBMIT MODE, EXIT BEE3 3600 MVI M,00H ;RESET SUBMIT FLAG BEE5 AF XRA A ; BEE6 CDBDBD CALL SELDSK ;SELECT CORRECT DISK BEE9 11ACC4 LXI D,SUBFCB ; BEEC CDEFBD CALL DELETF ;DELETE THE $$$.SUB FILE FROM DISK BEEF 3AEFC4 LDA CURDSK ; BEF2 C3BDBD JMP SELDSK ;RESTORE CURRENT DISK AND EXIT ; ; COMPARE SERIAL NUMBERS ; SERIAL NUMBERS OF CCP AND BDOS ARE ; COMPARED. IF THERE IS NO MATCH, YOU ; ARE BANISHED TO DIGITAL SIBERIA. ; THIS S/R IS CALLED BEFORE A TRANSIENT ; PROGRAM IS LOADED INTO THE TPA. ; BEF5 1128C0 CMPSER: LXI D,SERNO ;POINT TO SERIAL NO IN CCP BEF8 2100C5 LXI H,FBASE ;POINT TO SERIAL NO IN BDOS BEFB 0606 MVI B,6 ;NUMBER OF BYTES TO COMPARED BEFD 1A CMPSN1: LDAX D ; BEFE BE CMP M ; BEFF C2CFC0 JNZ FATAL ; OK, YOU'VE HAD IT. YOU ARE LOCKED OUT. BF02 13 INX D ; BF03 23 INX H ; BF04 05 DCR B ; BF05 C2FDBE JNZ CMPSN1 ; BF08 C9 RET ; GOOD COMPARISON. YOU ARE HOME FREE ; ; GENERAL PURPOSE ERROR HANDLING ROUTINE ; ANYTHING THAT YOU DO WRONG IN ENTERING A ; COMMAND LANDS YOU HERE. THE COMMAND LINE ; IS TYPED BACK AT YOU FOR YOUR EDIFICATION ; AND EMBARRASSMENT. AFTER YOU HAVE BEEN SHOWN ; A '?', YOU ARE PUT BACK IN THE COMMAND MODE. ; BF09 CD98BD WHAT: CALL PCRLF ; BF0C 2A8ABD LHLD BPTR2 ; POINT TO THE OFFENDING COMMAND BF0F 7E WHAT1: MOV A,M ; AND PRINT UNTIL A SPACE OR NULL IS FOUND BF10 FE20 CPI ' ' ; BF12 CA22BF JZ WHAT2 ; BF15 B7 ORA A ; BF16 CA22BF JZ WHAT2 ; BF19 E5 PUSH H ; BF1A CD8CBD CALL OUTPUT ; BF1D E1 POP H ; BF1E 23 INX H ; BF1F C30FBF JMP WHAT1 ; ; BF22 3E3F WHAT2: MVI A,'?' ; OK, WHAT DID YOU HAVE IN MIND? BF24 CD8CBD CALL OUTPUT ; BF27 CD98BD CALL PCRLF ; BF2A CDDDBE CALL EXITSB ; BF2D C382C0 JMP NXTCMD ; BACK FOR ANOTHER COMMAND. ; ; SPECIAL CHARACTER CHECK ; RETURNS WITH ZFLAG SET IF ANY OF THE SPECIAL ; CHARACTERS IS FOUND, OR BOMBS YOU OUT IF A ; CONTROL CHARACTER IS FOUND. CONTAINS A USELESS ; BYTE. ; BF30 1A CHRCHK: LDAX D ; BF31 B7 ORA A ; BF32 C8 RZ ;EXIT ON NULL BF33 FE20 CPI ' ' ; BF35 DA09BF JC WHAT ;BOMB OUT ON CONTROL CHARACTER BF38 C8 RZ ; BF39 FE3D CPI '=' ; BF3B C8 RZ ; BF3C FE5F CPI '_' ; BF3E C8 RZ ; BF3F FE2E CPI '.' ; BF41 C8 RZ ; BF42 FE3A CPI ':' ; BF44 C8 RZ ; BF45 FE3B CPI ';' ; BF47 C8 RZ ; BF48 FE3C CPI '<' ; BF4A C8 RZ ; BF4B FE3E CPI '>' ; BF4D C8 RZ ; THIS COMMAND IS REDUNDANT! BF4E C9 RET ; ; ; STEP (DE) UNTIL A NULL OR NON-SPACE IS FOUND ; RETURN WITH THE CHARACTER IN THE ACCUMULATOR. ; BF4F 1A STEP: LDAX D ; BF50 B7 ORA A ; BF51 C8 RZ ; BF52 FE20 CPI 20H ;' ' BF54 C0 RNZ ; BF55 13 INX D ; BF56 C34FBF JMP STEP ; ; ; ADD THE ACCUMULATOR TO (HL) ; RETURN WITH THE RESULT IN (HL) ; BF59 85 ADDAH: ADD L ; (HL) <- (HL) + (A) BF5A 6F MOV L,A ; BF5B D0 RNC ; BF5C 24 INR H ; BF5D C9 RET ; ; ; TRANSFER FILE CONTROL BLOCK ; THIS IS A KEY SUBROUTINE THAT HANDLES ALL ; OF THE SETTING UP OF FILE CONTROL BLOCKS ; AND OF MOVING AROUND THE CONTROL BUFFER. ; ; NO ENTRY PARAMETERS ARE PASSED IN REGISTERS ; ON EXIT (A) CONTAINS A COUNT OF THE NUMBER OF ; '?' WILDCARDS IN FILE CONTROL BLOCK AND ZFLAG ; IS SET IF THIS COUNT =0 AND FCB CONTAINS THE ; FILE BLOCK. THE INPUT BUFFER POINTER HAS BEEN ; ADVANCED TO ONE BEYOND END OF INFORMATION USED. ; ; THIS SUBROUTINE IS NOT ONLY USED TO SET UP ; FILE CONTROL BLOCKS, BUT ALSO THE NUMBERS ; FOR SAVE AND USER. ; BF5E 3E00 TRFCB: MVI A,00H ;INITIAL OFFSET=0, PRIMARY ENTRY POINT BF60 21CDC4 TRFCB1: LXI H,FCB ;(ALTERNATE ENTRY POINT, OFFSET IN (A)) BF63 CD59BF CALL ADDAH ;POINT TO CURRENT CHARACTER IN FCB BF66 E5 PUSH H ; BF67 E5 PUSH H ;SAVE POINTER TWICE. BF68 AF XRA A ; BF69 32F0C4 STA TRDISK ; BF6C 2A88BD LHLD BPTR1 ;GET CURRENT POINTER TO THE INPUT BUFFER BF6F EB XCHG ; BF70 CD4FBF CALL STEP ;GET FIRST NON-BLANK CHARACTER BF73 EB XCHG ; BF74 228ABD SHLD BPTR2 ;SAVE POINTER IN CASE OF ERROR BF77 EB XCHG ; BF78 E1 POP H ;GET FCB POINTER BF79 1A LDAX D ; BF7A B7 ORA A ;CHECK FOR NULL COMMAND BF7B CA89BF JZ TRFCB2 ; BF7E DE40 SBI 40H ;REMOVE ASCII BIAS. BF80 47 MOV B,A ;SAVE POSSIBLE DISK NUMBER IN (B) BF81 13 INX D ; BF82 1A LDAX D ; BF83 FE3A CPI ':' ; THIS MEANS THAT THIS IS A DISK NUMBER. BF85 CA90BF JZ TRFCB3 ; GO SET TRANSIENT DISK. BF88 1B DCX D ; GET CURRENT LOGGED IN DISK NUMBER. BF89 3AEFC4 TRFCB2: LDA CURDSK ; BF8C 77 MOV M,A ; BF8D C396BF JMP TRFCB4 ; ; BF90 78 TRFCB3: MOV A,B ; SET TRANSIENT DISK NUMBER. BF91 32F0C4 STA TRDISK ; BF94 70 MOV M,B ; PUT DISK NUMBER INTO HEAD OF FILE CONTROL BLOCK. BF95 13 INX D ; ; ; MOVE FILE NAME OF UP TO 8 CHARACTERS INTO BYTES ; 1 THROUGH 8 OF FCB. EXIT AT REACHING A SPECIAL ; CHARACTER OR A NULL. PAD EXCESS WITH BLANKS. ; IF A '*' IS FOUND, FILL THE REST OF THE NAME BLOCK ; WITH '?' ; BF96 0608 TRFCB4: MVI B,08H ; MOVE FILE NAME OF UP TO 8 CHARACTERS. BF98 CD30BF TRFCB5: CALL CHRCHK ; EXIT IF A SPECIAL CHARACTER IS FOUND. BF9B CAB9BF JZ TRFCB9 ; GO PAD THE REST OF THE BLOCK W/ ' ' BF9E 23 INX H ; BF9F FE2A CPI '*' ;THIS IS A WILD CARD MATCH BFA1 C2A9BF JNZ TRFCB6 ; BFA4 363F MVI M,'?' ;THIS IS AN 'ANYTHING MATCH'. BFA6 C3ABBF JMP TRFCB7 ; ; BFA9 77 TRFCB6: MOV M,A ; BFAA 13 INX D ; BFAB 05 TRFCB7: DCR B ; BFAC C298BF JNZ TRFCB5 ; ; BFAF CD30BF TRFCB8: CALL CHRCHK ;CHECK FOR SPECIAL CHARACTER BFB2 CAC0BF JZ TRFC10 ; BFB5 13 INX D ; BFB6 C3AFBF JMP TRFCB8 ; ; BFB9 23 TRFCB9: INX H ; PAD THE REST OF THE FILE NAME WITH BLANKS. BFBA 3620 MVI M,' ' ; BFBC 05 DCR B ; BFBD C2B9BF JNZ TRFCB9 ; ; ; MOVE THE FILE EXTENTION INTO BYTES 9 THROUGH 11 OF ; FCB. PAD EXCESS WITH BLANCKS, AND FILL WITH '?' ; IN THE SAME MANNER AS THE FILENAME. ; BFC0 0603 TRFC10: MVI B,03H ; MOVE A FILE TYPE OF UP TO 3 CHARACTERS. BFC2 FE2E CPI '.' ;A PERIOD IS THE ONLY LEGAL SPECIAL CHARACTER IN THIS CASE. BFC4 C2E9BF JNZ TRFC15 ; BFC7 13 INX D ; BFC8 CD30BF TRFC11: CALL CHRCHK ; CHECK FOR SPECIAL CHARACTERS. BFCB CAE9BF JZ TRFC15 ; BFCE 23 INX H ; BFCF FE2A CPI '*' ;WILD CARD MATCH- PAD THE 3 BYTES WITH ??? BFD1 C2D9BF JNZ TRFC12 ; BFD4 363F MVI M,'?' ; BFD6 C3DBBF JMP TRFC13 ; ; BFD9 77 TRFC12: MOV M,A ;PUT THE CHARACTER INTO FCB BFDA 13 INX D ;ADVANCE FCB POINTER BFDB 05 TRFC13: DCR B ;DECREMENT CHARACTER COUNTER BFDC C2C8BF JNZ TRFC11 ;LOOP UNTIL COUNTER IS ZERO BFDF CD30BF TRFC14: CALL CHRCHK ;STEP BUFFER UNTIL SPECIAL CHARACTER, BFE2 CAF0BF JZ TRFC16 ; OR NULL IS FOUND. BFE5 13 INX D ; BFE6 C3DFBF JMP TRFC14 ; ; BFE9 23 TRFC15: INX H ;PAD THE REST OF THE EXTENT WITH ' ' BFEA 3620 MVI M,' ' ; BFEC 05 DCR B ; BFED C2E9BF JNZ TRFC15 ; ; BFF0 0603 TRFC16: MVI B,03H ;ZERO OUT BYTES 12 THROUGH 14 BFF2 23 TRFC17: INX H ; BFF3 3600 MVI M,00H ; BFF5 05 DCR B ; BFF6 C2F2BF JNZ TRFC17 ; ; BFF9 EB XCHG ; BFFA 2288BD SHLD BPTR1 ;SAVE THE INPUT BUFFER POINTER BFFD E1 POP H ;(HL) = FCB BFFE 010B00 LXI B,11 ;SET COUNTER C001 23 TRFC18: INX H ;COUNT NUMBER OF '?' IN FILENAME.EXT C002 7E MOV A,M ; C003 FE3F CPI '?' ; C005 C209C0 JNZ TRFC19 ;SKIP IF NOT'?' C008 04 INR B ; C009 0D TRFC19: DCR C ; C00A C201C0 JNZ TRFC18 ; C00D 78 MOV A,B ;MOVE '?' COUNT INTO (A) C00E B7 ORA A ;SET FLAGS TO INDICATE AMBIGOUS FILENAME C00F C9 RET ; ; ; COMMAND NAME LIST ; C010 44495220 CMNDL: DB 'DIR ' ;READ DIRECTORY C014 45524120 DB 'ERA ' ;ERASE FILE C018 54595045 DB 'TYPE' ;OUTPUT NAMED FILE TO CONSOLE C01C 53415645 DB 'SAVE' ;SAVE NAMED FILE ON DISK C020 52454E20 DB 'REN ' ;RENAME FILE C024 55534552 DB 'USER' ;SET USER NUMBER ; ; SERIAL NUMBERS ; C028 00 SERNO: DB SNH ; C029 16 DB VER*10+REL ;2.2 IS 16H C02A 0000 DW REV ; C02C 00 DB SNL/256 ; C02D 00 DB SNL MOD 256 ; ; ; COMMAND SEARCH ; ; TRY TO MATCH COMMAND NAME STARTING AT FCB + 1 ; WITH THOSE IN THE INTRINSIC COMMAND LIST. ; EXIT WITH COMMAND NUMBER (0 TO 5) IN (A) IF A ; MATCH HAS BEEN MADE, ELSE EXIT WITH A 6 IN (A) ; SIGNIFYING THAT THIS MAY BE A TRANSIENT COMMAND. ; C02E 2110C0 CSRCH: LXI H,CMNDL ; POINT TO START OF COMMAND LIST. C031 0E00 MVI C,00H ; ZERO OUT COMMAND COUNTER. C033 79 CSRCH1: MOV A,C ; CHECK COUNTER FOR MAXIMUM NUMBER OF TRIES. C034 FE06 CPI 6 ;(THERE ARE 6 INTRINSIC COMMANDS + TRANSIENTS) C036 D0 RNC ; RETURN IS NO MATCH IN SIX TRIES. IT IS A TRANSIENT COMMAND. C037 11CEC4 LXI D,FCB+1 ; POINT TO START OF COMMAND TO BE MATCHED. C03A 0604 MVI B,04H ; MAXIMUM NUMBER OF CHARACTERS IN COMMAND NAME. C03C 1A CSRCH2: LDAX D ; C03D BE CMP M ; C03E C24FC0 JNZ CSRCH3 ; NO MATCH- EXIT LOOP. C041 13 INX D ; C042 23 INX H ; C043 05 DCR B ; C044 C23CC0 JNZ CSRCH2 ; BACK FOR ANOTHER MATCH. C047 1A LDAX D ; FOUND THE COMMAND, NOW CHECK FOR A SEPARATING SPACE. C048 FE20 CPI ' ' ; C04A C254C0 JNZ CSRCH4 ; NO SPACE, TRY FOR SOMETHING ELSE. C04D 79 MOV A,C ; PUT COMMAND COUNT IN ACCUMULATOR. C04E C9 RET ; EXIT ROUTINE WITH COMMAND NUMBER. ; C04F 23 CSRCH3: INX H ; STEP FORWARDS TO THAT START OF THE NEXT COMMAND NAME. C050 05 DCR B ; C051 C24FC0 JNZ CSRCH3 ; C054 0C CSRCH4: INR C ; BUMP COMMAND COUNTER BY ONE. C055 C333C0 JMP CSRCH1 ; BACK FOR ANOTHER TRY. ; ; ****************************** ; MAIN OPERATING ROUTINE FOR CCP ; ****************************** ; ; ENTRY POINT NUMBER 1 ; INPUT BUFFER COUNTER IS ZEROED OUT SO NO IMBEDDED ; COMMAND CAN BE EXECUTED ON INITIAL BOOT UP. ; C058 AF CCP0: XRA A ; C059 3207BD STA INBLEN ; ; ; ; ENTRY POINT NUMBER 2 ; ENTRY A THIS POINT ALLOWS COMMANDS INBEDDED IN ; INPUT BUFFER TO BE AUTOMATICALLY EXECUTED ; ON INITIAL BOOT UP. ; ; ON ENTRY (C) HAS USER NUMBER IN THE HIGH NIBBLE ; AND THE DISK DRIVE IN THE LOWER NIBBLE ; C05C 31ABC4 CCP1: LXI SP,STACK ;SET UP LOACAL STACK C05F C5 PUSH B ;SAVE ENTRY PARAMETER C060 79 MOV A,C ; C061 1F RAR ;MOVE UPPER 4 BITS DOWN C062 1F RAR ; C063 1F RAR ; C064 1F RAR ; C065 E60F ANI 0FH ;EXTRACT USER NUMBER FROM INPUT PARAMETER C067 5F MOV E,A ; C068 CD15BE CALL SETUSR ;PUT USER NUMBER IN ITS PLACE C06B CDB8BD CALL RESET ;RESET DISK SYSTEM C06E 32ABC4 STA SUBFL ;SUBMIT FILE FLAG C071 C1 POP B ;GET BACK ENTRY PARAMETER C072 79 MOV A,C ; C073 E60F ANI 0FH ;EXTRACT DISK DRIVE NUMBER FROM INPUT PARAMETER C075 32EFC4 STA CURDSK ;SET TO CORRECT DISK DRIVE C078 CDBDBD CALL SELDSK ; C07B 3A07BD LDA INBLEN ; C07E B7 ORA A ;CHECK TO SEE IF THERE IS ANYTHING IN THE INPUT BUFFER C07F C298C0 JNZ CCP2 ;THERE IS, SO DON'T BOTHER WITH INPUT. ; ; RE-ENTRY POINT FOR NEXT COMMAND ; C082 31ABC4 NXTCMD: LXI SP,STACK ; RESET STACK, AND PUT OUT A PROMPT SO ; THAT YOU KNOW WHAT DISK YOU ARE OPERATING ON. C085 CD98BD CALL PCRLF ; C088 CDD0BE CALL INTDSK ;GET DRIVE NUMBER C08B C641 ADI 'A' ;ADD ASCII BIAS C08D CD8CBD CALL OUTPUT ; C090 3E3E MVI A,'>' ;PROMPT CHARACTER C092 CD8CBD CALL OUTPUT ; C095 CD39BE CALL CMNDIN ; INPUT THE NEXT COMMAND LINE FROM THE CONSOLE OR SUBMIT FILE. C098 118000 CCP2: LXI D,DDMA ;SET TO THE DEFAULT DMA (0080H) C09B CDD8BE CALL STDMA1 ; C09E CDD0BE CALL INTDSK ;CHECK DISK DRIVE C0A1 32EFC4 STA CURDSK ; C0A4 CD5EBF CALL TRFCB ;PUT COMMAND NAME IN FCB C0A7 C409BF CNZ WHAT ;AMBIGOUS FILENAME.EXT NO GOOD C0AA 3AF0C4 LDA TRDISK ; C0AD B7 ORA A ; C0AE C2A5C3 JNZ TRANS ;TRANSIENT COMMAND C0B1 CD2EC0 CALL CSRCH ;FIND COMMAND IN COMMAND LIST C0B4 21C1C0 LXI H,CMNDT ;POINT TO COMMAND VECTOR TABLE C0B7 5F MOV E,A ;PUT COMMAND NUMBER IN (DE) C0B8 1600 MVI D,00H ; C0BA 19 DAD D ; C0BB 19 DAD D ;(HL) <-- CMNDT + 2 * COMMAND NUMBER C0BC 7E MOV A,M ;MOVE COMMAND VECTOR INTO (HL) C0BD 23 INX H ; C0BE 66 MOV H,M ; C0BF 6F MOV L,A ; C0C0 E9 PCHL ;GO FORTH AND EXECUTE THE COMMAND. ; ; COMMAND VECTOR TABLE ; C0C1 77C1 CMNDT: DW DIR ;DISPLAY DIRECTORY C0C3 1FC2 DW ERA ;ERASE FILE C0C5 5DC2 DW TYPE ;TYPE FILE TO CONSOLE C0C7 ADC2 DW SAVE ;SAVE FILE ON DISK C0C9 10C3 DW REN ;RENAME FILE C0CB 8EC3 DW USER ;SET USER NUMBER C0CD A5C3 DW TRANS ;LOAD AND EXECUTE TRANSIENT COMMAND ; ; OK- YOU WERE WARNED ABOUT THE SERIAL NUMBERS, BUT ; YOU WENT AHEAD ANYWAY. NOW YOU MUST PAY THE PENALTY ; C0CF 21F376 FATAL: LXI H,76F3H ;STUFF A DI & HLT C0D2 2200BD SHLD ORIGIN ;AT THE HEAD OF CCP C0D5 2100BD LXI H,ORIGIN ; C0D8 E9 PCHL ;HANG UP THERE UNTIL RESET ; ; FILE READ ERROR ; C0D9 01DFC0 RDERR: LXI B,MSG1 ;LOAD POINTER TO MESSAGE C0DC C3A7BD JMP CRMSG ;DISPLAY MESSAGE & RETURN ; C0DF 5245414420MSG1: DB 'READ ERROR',0 ; ; FILE NOT FOUND ERROR ; C0EA 01F0C0 NFERR: LXI B,MSG2 ;LOAD POINTER TO MESSAGE C0ED C3A7BD JMP CRMSG ;DISPLAY MESSAGE & RETURN ; C0F0 4E4F204649MSG2: DB 'NO FILE',0 ; ; DECIMAL TO BINARY CONVERSION ; USED BY SAVE AND USER ; ; NOTE: ; ; THERE IS SOME INEFFICIENT CODE IN THIS SUBROUTINE ; TRFCB WILL MOVE THE NUMBERS INTO FCB AND PAD THE ; REST OF THE BLOCK WITH ' '. THE NUMBER CAN BE 3 ; DIGITS LONG AT MOST, SO THAT THE ELABORATE STEPPING ; PAST BLANKS, ETC IS NOT NEEDED. CODE THAT CAN BE ; REVISED IS MARKED BY '*' ; C0F8 CD5EBF DECIML: CALL TRFCB ;MOVE NUMBERS INTO FCB C0FB 3AF0C4 LDA TRDISK ; C0FE B7 ORA A ; C0FF C209BF JNZ WHAT ; C102 21CEC4 LXI H,FCB+1 ; C105 010B00 LXI B,11 ;8 NUMBER FILE NAME & 3 CHAR EXT C108 7E DEC1: MOV A,M ; C109 FE20 CPI ' ' ; C10B CA33C1 JZ DEC2 ; C10E 23 INX H ; C10F D630 SUI '0' ;REMOVE ASCII BIAS C111 FE0A CPI 10 ; C113 D209BF JNC WHAT ; C116 57 MOV D,A ; C117 78 MOV A,B ;* C118 E6E0 ANI 0E0H ;* C11A C209BF JNZ WHAT ;* C11D 78 MOV A,B ;* C11E 07 RLC ;MULTIPLY BY 10 C11F 07 RLC ; C120 07 RLC ; C121 80 ADD B ; C122 DA09BF JC WHAT ;OVERFLOW C125 80 ADD B ; C126 DA09BF JC WHAT ;OVERFLOW C129 82 ADD D ; C12A DA09BF JC WHAT ;OVERFLOW C12D 47 MOV B,A ; C12E 0D DCR C ;* C12F C208C1 JNZ DEC1 ;* SHOULD BE JMP DEC1 C132 C9 RET ;* ; C133 7E DEC2: MOV A,M ;*STEP OVER BLANKS TO END OF BLOCK C834 FE20 CPI ' ' ;* C836 C209C6 JNZ WHAT ;* C839 23 INX H ;* C13A 0D DCR C ;* C13B C233C1 JNZ DEC2 ;* C13E 78 MOV A,B ;RETURN WITH BINARY VALUE IN (A) C13F C9 RET ; ; ; BLOCK MOVE ; SOURCE :: ((HL)) ; DESTINATION :: ((DE)) ; COUNT :: (B) ; C140 0603 MOVE3: MVI B,03H ;3 BYTE MOVE C142 7E BLKMOV: MOV A,M ;SOURCE C143 12 STAX D ;DESTINATION C144 23 INX H ; C145 13 INX D ; C146 05 DCR B ;COUNTER C147 C242C1 JNZ BLKMOV ; C14A C9 RET ; ; ; SET DIRECTORY POINTER ; POINT TO (DDMA) + (C) + (A) ; RETURN WITH CHARACTER IN (A) ; ; ON ENTRY (C) CONTAINS DIRECTORY ENTRY OFFSET ; I.E. 00H, 20H, 40H, OR 60H. ; ACCUMULATOR (A) CONTAINS NUMBER OF THE BYTE ; WITHIN THE DIRECTORY THAT THE POINTER IS TO ; BE SET TO. ; C14B 218000 DIRPTR: LXI H,DDMA ;POINT TO START OF DIRECTORY SECTOR C14E 81 ADD C ;ADD BYTE NUMBER TO DIRECTORY OFFSET C14F CD59BF CALL ADDAH ; THEN ADD THE RESULT TO (HL) C152 7E MOV A,M ; AND GET THE BYTE POINTED TO. C153 C9 RET ; ; ; SET TO TRANSIENT DISK ; SET THE DISK SPECIFIED BY (TRDISK) FOR ; READING OR WRITING. IF (TRDISK) = (CURDISK), YOU ; ARE ALREADY ON THE RIGHT DISK, SO NO CHANGE IS NEEDED ; C154 AF SETTRD: XRA A ; C155 32CDC4 STA FCB ;SET FIRST BYTE OF FCB TO 0 C158 3AF0C4 LDA TRDISK ; C15B B7 ORA A ;CHECK TO SEE IF TRANSIENT DISK= 0 C15C C8 RZ ;OK- NO CHANGE NEEDED C15D 3D DCR A ; C15E 21EFC4 LXI H,CURDSK ;NOW CHECK CURRENT DISK C161 BE CMP M ; C162 C8 RZ ;OK- NO CHANGE NEEDED C163 C3BDBD JMP SELDSK ;DISK DIFFERENT, SO GO GET RIGHT ONE ; ; SET CURRENT DISK ; RESTORE THE CURRENT LOGGED-IN DISK AS THE READ/WRITE ; DISK. IF ALREADY ON THE PROPER DISK, NO ACTION IS REQUIRED ; C166 3AF0C4 SETCUR: LDA TRDISK ; C169 B7 ORA A ; C16A C8 RZ ;OK- ON LOG-IN DISK, NO CHANGE C16B 3D DCR A ; C16C 21EFC4 LXI H,CURDSK ; C16F BE CMP M ; C170 C8 RZ ;OK C171 3AEFC4 LDA CURDSK ;ON DIFFERENT DISK. ;(NOTE: CHANGE THIS COMMAND TO MOV A,M AND SAVE 2 BYTES) C174 C3BDBD JMP SELDSK ; SO GO MAKE CHANGE ; ; START OF INTRINSIC COMMANDS ; ; ******************************* ; DIR SEARCHES FILE DIRECTORY FOR ; FILES BY FILE NAME OR FILE TYPE ; ? MATCHES ANY LETTER ; * MATCHES THE WHOLE FILENAME OR ; FILETYPE ; ******************************* ; ; NOTE ON SYSTEM FILES: ; 'SYSTEM' TYPE FILES ARE RENDERED INVISIBLE TO THE ; DIR COMMAND BECAUSE THE MSB OF THE SECOND BYTE OF ; THE FILE EXT IS SET. A MINOR CHANGE IN THE FOLLOWING ; CODE COULD MAKE THESE FILES LISTABLE IN THE DIRECTORY ; C177 CD5EBF DIR: CALL TRFCB ; TRANSFER THE COMMAND LINE INTO 005CH. C17A CD54C1 CALL SETTRD ; SET TO TRANSIENT DISK C17D 21CEC4 LXI H,FCB+1 ; POINT TO START OF FILE NAME C180 7E MOV A,M ; CHECK FOR A BLANK C181 FE20 CPI 20H ;' ' C183 C28FC1 JNZ DIR1 ; NOT BLANK, GO FIND WHAT IS WANTED. ; C186 060B MVI B,11 ; BLANK ::= DISPLAY ENTIRE DIRECTORY C188 363F DIR0: MVI M,3FH ; FILL ENTIRE FILENAME/TYPE ARE WITH WILDCARD [?]'?' C18A 23 INX H ; C18B 05 DCR B ; C18C C288C1 JNZ DIR0 ; ; C18F 1E00 DIR1: MVI E,00H ; SEARCH FOR FILE. C191 D5 PUSH D ; C192 CDE9BD CALL SRCHF1 ; C195 CCEAC0 CZ NFERR ; ERROR C198 CA1BC2 DIR2: JZ DIR10 ; C19B 3AEEC4 LDA RETVAL ;GET DIRECTORY ENTRY NUMBER C19E 0F RRC ;CONVERT TO DIRECTORY BLOCK POINTER C19F 0F RRC ;BY MULTIPLYING BY 32 AND MASKING OFF C1A0 0F RRC ;THE EXCESS C1A1 E660 ANI 60H ; C1A3 4F MOV C,A ;STASH BLOCK POINTER C1A4 3E0A MVI A,10 ; C1A6 CD4BC1 CALL DIRPTR ;GET CHARACTER @ DDMA + BLOCK POINTER + 10 = SECOND CHAR OF EXT C1A9 17 RAL ;CHECK FOR MSB SET :: SYSTEM FILE C1AA DA0FC2 JC DIR9 ;SKIP- SYSTEM FILES ARE NOT LISTED BY DIR C1AD D1 POP D ; C1AE 7B MOV A,E ; C1AF 1C INR E ; C1B0 D5 PUSH D ; C1B1 E603 ANI 03H ;CHECK FOR EVERY 4TH DIRECTORY ITEM C1B3 F5 PUSH PSW ; C1B4 C2CCC1 JNZ DIR3 ;NOT THE 4TH C1B7 CD98BD CALL PCRLF ; 4TH, SO START NEW LINE AND MARK C1BA C5 PUSH B ; WITH DISK DRIVE LETTER C1BB CDD0BE CALL INTDSK ;GET DISK NUMBER C1BE C1 POP B ; C1BF C641 ADI 'A' ;PRINT THE DISK NUMBER & COLON AT THE C1C1 CD92BD CALL PCHAR ;START OF EACH DIRECTORY PRINT LINE C1C4 3E3A MVI A,':' ; C1C6 CD92BD CALL PCHAR ; C1C9 C3D4C1 JMP DIR4 ; ; C1CC CDA2BD DIR3: CALL SPACE ;PRINT A SPACE/COLON/SPACE BETWEEN C1CF 3E3A MVI A,':' ;DIRECTORY ITEMS C1D1 CD92BD CALL PCHAR ; C1D4 CDA2BD DIR4: CALL SPACE ; C1D7 0601 MVI B,01H ; ; ; THE CODE IN THIS AREA IS SOMEWHAT TANGLED ; SPACE COULD BE SAVED BY REDOING SOME OF THE ; WAYS THAT POINTERS ARE SET UP. CURRENTLY THE ; POINTER TO THE DIRECTORY ENTRY IS RECOMPUTED ; FOR EACH BYTE. WHY NOT JUST LOAD (HL) ONCE ; AND INCREMENT? ; C1D9 78 DIR5: MOV A,B ;PRINT THE FILENAME.EXT TO THE CONSOLE C1DA CD4BC1 CALL DIRPTR ;POINT TO BYTE AND REURN W/ BYTE IN (A) C1DD E67F ANI 7FH ; C1DF FE20 CPI ' ' ; C1E1 C2F9C1 JNZ DIR7 ; C1E4 F1 POP PSW ; C1E5 F5 PUSH PSW ; C1E6 FE03 CPI 03H ;CHACK FOR FILE EXT END C1E8 C2F7C1 JNZ DIR6 ; C1EB 3E09 MVI A,09H ;CHECK FOR FILE NAME END C1ED CD4BC1 CALL DIRPTR ; C1F0 E67F ANI 7FH ; C1F2 FE20 CPI ' ' ;CHECK FOR NO FILE EXT C1F4 CA0EC2 JZ DIR8 ; C1F7 3E20 DIR6: MVI A,' ' ;SEPARATOR BETWEEN FILENAME & EXT C1F9 CD92BD DIR7: CALL PCHAR ; C1FC 04 INR B ; C1FD 78 MOV A,B ; C1FE FE0C CPI 12 ;FILE EXT END +1 C200 D20EC2 JNC DIR8 ; C203 FE09 CPI 9 ;FILE NAME END +1 C205 C2D9C1 JNZ DIR5 ; C208 CDA2BD CALL SPACE ; C20B C3D9C1 JMP DIR5 ; ; C20E F1 DIR8: POP PSW ; C20F CDC2BE DIR9: CALL KSTAT ;CHECK KEY BOARD, ANY KEY BREAKS C212 C21BC2 JNZ DIR10 ;EXIT ON BREAK C215 CDE4BD CALL SRCHNX ;LOOK FOR ANOTHER DIRECTORY ITEM C218 C398C1 JMP DIR2 ;LOOP BACK FOR MORE ; C21B D1 DIR10: POP D ; C21C C386C4 JMP COMEND ;EXIT ; ; ****************************************************** ; ERASE FILES FROM DISK ; ; '*' AND '?' CAN BE USED THE SAME AS IN 'DIR' ; DOES NOT ACTUALLY WIPE OUT INFORMATION FROM THE DISK, ; BUT MERELY HAS THE FIRST BYTE OF THE FILE CONTROL BLOCK ; SET TO 0E5H. THIS ROUTINE IN CCP MERELY SETS UP THE ; FILE NAMES TO BE ERASED; THE REAL WORK IS DONE BY BDOS ; ****************************************************** ; C21F CD5EBF ERA: CALL TRFCB ;SET UP THE FILE CONTROL BLOCK C222 FE0B CPI 11 ;IF 11 '?' ARE IN THE FCB THEN YOU ARE C224 C242C2 JNZ ERA1 ;ASKING TO ERASE THE WHOLE DISK. *.* C227 0152C2 LXI B,MSG3 ;ASK FOR VERIFICATION BEFORE PROCEEDING C22A CDA7BD CALL CRMSG ; C22D CD39BE CALL CMNDIN ;GET KEYBOARD ENTRY C230 2107BD LXI H,INBLEN ;CHECK FOR RETURN WITHOUT ENTRY C233 35 DCR M ; C234 C282C0 JNZ NXTCMD ;ABORT ON EMPTY LINE C237 23 INX H ; C238 7E MOV A,M ; C239 FE59 CPI 'Y' ;YES, PROCEED WITH ERASING EVERYTHING C23B C282C0 JNZ NXTCMD ;CHICKENED OUT C23E 23 INX H ; C23F 2288BD SHLD BPTR1 ; C242 CD54C1 ERA1: CALL SETTRD ;SET THE TRANSIENT DISK C245 11CDC4 LXI D,FCB ;POINT TO THE FILE CONTROL BLOCK C248 CDEFBD CALL DELETF ;CALL THE ROUTINE THAT CALLS TH E BDOS ERASE C24B 3C INR A ;CHECK THE RETURN PARAMETER C24C CCEAC0 CZ NFERR ;WARN IF ITEM NOT FOUND C24F C386C4 JMP COMEND ;EXIT ; C252 414C4C2028MSG3: DB 'ALL (Y/N)?',0 ; ; *********************************** ; OUTPUT NAMED FILE TO THE CONSOLE ; FILE NAME.EXT MUST BE UNCONDITIONAL ; *********************************** ; C25D CD5EBF TYPE: CALL TRFCB ;SET UP FILE NAME IN FCB C260 C209BF JNZ WHAT ;BADLY FORMED FILENAME: AMBIGOUS C263 CD54C1 CALL SETTRD ;SET THE DISK C266 CDD0BD CALL OPENF1 ;OPEN THE FILE FOR READING C269 CAA7C2 JZ TYPE4 ;ERROR ON OPENING C26C CD98BD CALL PCRLF ; C26F 21F1C4 LXI H,TYPCTR ;INITIATE COUNTER C272 36FF MVI M,0FFH ; C274 21F1C4 TYPE1: LXI H,TYPCTR ; C277 7E MOV A,M ;GET THE BUFFER COUNTER C278 FE80 CPI 80H ;CHECK FOR END OF BUFFER C27A DA87C2 JC TYPE2 ;NOT AT END, GET CHARACTER FROM BUFFER ; ; AT END OF BUFFER- READ FROM DISK ; C27D E5 PUSH H ;READ A SECTOR FROM DISK TO THE BUFFER C27E CDFEBD CALL READ1 ; C281 E1 POP H ; C282 C2A0C2 JNZ TYPE3 ;RETURN VALUE <> 0. END OF FILE OR BAD READ C285 AF XRA A ; C286 77 MOV M,A ;ZERO (TYPCTR) C287 34 TYPE2: INR M ; C288 218000 LXI H,DDMA ; C28B CD59BF CALL ADDAH ;POINT TO CHARACTER C28E 7E MOV A,M ;GET THE CHARACTER C28F FE1A CPI 1AH ;CHECK FOR END OF FILE C291 CA86C4 JZ COMEND ;EXIT C294 CD8CBD CALL OUTPUT ;NOT EOF, OUTPUT THE BYTE TO THE CONSOLE C297 CDC2BE CALL KSTAT ;CHECK FOR KEYBOARD BREAK C29A C286C4 JNZ COMEND ;EXIT ON ANY KEY C29D C374C2 JMP TYPE1 ;BACK FOR THE NEXT LETTER ; ; (A) = 1 :: END OF FILE ; (A) = 2 :: READ ERROR ; C2A0 3D TYPE3: DCR A ; C2A1 CA86C4 JZ COMEND ;EXIT AT END OF FILE C2A4 CDD9C0 CALL RDERR ; C2A7 CD66C1 TYPE4: CALL SETCUR ;THIS PIECE OF CODE CAN BE USED TO C2AA C309BF JMP WHAT ;REPLACE REN4 AND TRANS8 ; ; ********************************** ; SAVE CREATES DISK FILE FROM MEMORY ; STARTING AT 0100H. 256 BYTE PAGES ; FILENAME MUST BE UNCONDITIONAL ; IF A FILE OF THE SAME NAME & TYPE ; ALREADY EXISTS, IT IS ERASED. ; ********************************** ; C2AD CDF8C0 SAVE: CALL DECIML ;GET THE NUMBER OF PAGES TO BE SAVED C2B0 F5 PUSH PSW ; C2B1 CD5EBF CALL TRFCB ;SET UP THE FILE NAME C2B4 C209BF JNZ WHAT ;CANNOT BE AMBIGOUS FILE C2B7 CD54C1 CALL SETTRD ;SET UP DISK C2BA 11CDC4 LXI D,FCB ; C2BD D5 PUSH D ; C2BE CDEFBD CALL DELETF ;DELETE OLD FILE OF SAME NAME C2C1 D1 POP D ; C2C2 CD09BE CALL CREATE ;CREATE A NEW FILE IN DIRECTORY C2C5 CAFBC2 JZ SAVE3 ; C2C8 AF XRA A ; C2C9 32EDC4 STA FCB+32 ;ZERO OUT SECTOR COUNTER C2CC F1 POP PSW ; C2CD 6F MOV L,A ; C2CE 2600 MVI H,00H ;CHECK PAGE COUNTER C2D0 29 DAD H ; C2D1 110001 LXI D,TPA ; C2D4 7C SAVE1: MOV A,H ;CHECK PAGE COUNTER C2D5 B5 ORA L ; C2D6 CAF1C2 JZ SAVE2 ;EXIT, LAST PAGE HAS BEEN WRITTEN C2D9 2B DCX H ; C2DA E5 PUSH H ;SAVE COUNTER C2DB 218000 LXI H,SECLEN ;ADVANCE DMA LOCATION C2DE 19 DAD D ;BY ONE SECTOR C2DF E5 PUSH H ; C2E0 CDD8BE CALL STDMA1 ;SET THE DMA ADDRESS C2E3 11CDC4 LXI D,FCB ; C2E6 CD04BE CALL WRITEF ;WRITE THE SECTOR TO DISK C2E9 D1 POP D ; C2EA E1 POP H ; C2EB C2FBC2 JNZ SAVE3 ;ERROR CONDITION C2EE C3D4C2 JMP SAVE1 ;LOOP BACK TO WRITE ANOTHER SECTOR ; C2F1 11CDC4 SAVE2: LXI D,FCB ;CLOSE THE FILE TO MAKE IT OFFICIAL C2F4 CDDABD CALL CLOSEF ; C2F7 3C INR A ;CHECK FOR GOOD CLOSING C2F8 C201C3 JNZ SAVE4 ;OK C2FB 0107C3 SAVE3: LXI B,MSG4 ; ERROR C2FE CDA7BD CALL CRMSG ; C301 CDD5BE SAVE4: CALL SETDMA ; C304 C386C4 JMP COMEND ;EXIT ; C307 4E4F205350MSG4: DB 'NO SPACE',0 ; ; ******************************************* ; RENAME A FILE THE FORMAT IS ; .=. ; A '_' MAY BE SUBSTITUTED FOR THE '=' ; ******************************************* ; C310 CD5EBF REN: CALL TRFCB ;PUT NEW FILENAME INTO FCB C313 C209BF JNZ WHAT ;CANNOT BE AMBIGOUS FILENAME C316 3AF0C4 LDA TRDISK ;GET THE DISK NUMBER C319 F5 PUSH PSW ; C31A CD54C1 CALL SETTRD ;LOG INTO THE CORRECT DISK C31D CDE9BD CALL SRCHF1 ;CHECK TO SEE IF SUCH A NAME EXISTS C320 C279C3 JNZ FEERR ;ERROR- FILE NAME ALREADY USED C323 21CDC4 LXI H,FCB ;MOVE NEW FILENAME TO UPPER HALF OF FCB C326 11DDC4 LXI D,FCB+16 ; C329 0610 MVI B,10H ; C32B CD42C1 CALL BLKMOV ; C32E 2A88BD LHLD BPTR1 ;BACK TO INPUT BUFFER C331 EB XCHG ; C332 CD4FBF CALL STEP ; C335 FE3D CPI '=' ;CHECK FOR PROPER SEPARATOR C337 CA3FC3 JZ REN1 ;OK C33A FE5F CPI '_' ; C33C C273C3 JNZ REN4 ;NO GOOD C33F EB REN1: XCHG ; C340 23 INX H ;STEP OVER SEPARARTOR C341 2288BD SHLD BPTR1 ;STORE POINTER FOR TRFCB TO USE C344 CD5EBF CALL TRFCB ;MOVE NAME.TYPE OF OLD FILE INTO PLACE C347 C273C3 JNZ REN4 ;ERROR- CANNOT BE AMBIGOUS C34A F1 POP PSW ;GET BACK DISK NUMBER C34B 47 MOV B,A ; C34C 21F0C4 LXI H,TRDISK ; C34F 7E MOV A,M ; C350 B7 ORA A ; C351 CA59C3 JZ REN2 ;OK- CURRENT DISK=TRANSIENT DISK C354 B8 CMP B ;CHECK DISK NUMBER C355 70 MOV M,B ;SAVE BACK INTO TRDISK C356 C273C3 JNZ REN4 ;ERROR C359 70 REN2: MOV M,B ; C35A AF XRA A ; C35B 32CDC4 STA FCB ;ZERO IN FCB :: LOGGED IN DISK C35E CDE9BD CALL SRCHF1 ;DOES OLD FILE EXIST? C361 CA6DC3 JZ REN3 ;NO- ERROR C364 11CDC4 LXI D,FCB ;OK- RENAME IT C367 CD0EBE CALL RENAME ; VIA CALL TO BDOS C36A C386C4 JMP COMEND ;EXIT ; C36D CDEAC0 REN3: CALL NFERR ; ERROR C370 C386C4 JMP COMEND ;EXIT ; ; THIS PIECE OF CODE CAN BE DELETED, AND JUMPS ; TO IT REROUTED TO TYPE4 ; C373 CD66C1 REN4: CALL SETCUR ;RETURN TO CURRENT DISK C376 C309BF JMP WHAT ;?????????? ; ; FILE EXISTS ERROR ; C379 0182C3 FEERR: LXI B,MSG6 ;LOAD ERROR MESSAGE POINTER C37C CDA7BD CALL CRMSG ;DISPLAY MAESSAGE C37F C386C4 JMP COMEND ;EXIT ; ; NOTE: ; IF THESE ERROR MESSAGES ENDED WITH '$' INSTEAD OF ; A NULL, THEN THE BDOS STRING OUTPUT COMMAND COULD ; BE USED INSTEAD OF THE PMSG SUBROUTINE. ; C382 46494C4520MSG6: DB 'FILE EXISTS',0 ; ; ************************************ ; SET THE USER NUMBER FROM THE CONSOLE ; NOBODY USES THIS IN ONE-USER CP/M ; ************************************ ; C38E CDF8C0 USER: CALL DECIML ;CONVERT NUMBER TO BINARY C391 FE10 CPI 10H ;MUST BE 0 TO 15 C393 D209BF JNC WHAT ;OUT OF RANGE C396 5F MOV E,A ;SET IN PLACE FOR BDOS CALL C397 3ACEC4 LDA FCB+1 ;CHECK FOR BLANK 'FILENAME' C39A FE20 CPI ' ' ; C39C CA09BF JZ WHAT ;ERROR C39F CD15BE CALL SETUSR ;SET VIA BDOS C3A2 C389C4 JMP CMEND1 ;EXIT ; ; ************************************************* ; TRANS LOADS A PROGRAM INTO THE TPA IF IT IS NOT A ; COMMAND NAME, AND A PROPER .COM FILE ; EXISTS ON THE TRANSIENT DISK. ; ************************************************* ; C3A5 CDF5BE TRANS: CALL CMPSER ; CHECK FOR A KOSHER SERIAL NUMBER. BOMB OUT IF NO GOOD. C3A8 3ACEC4 LDA FCB+1 ; SPACE ::= NO FILE NAME PRESENT. C3AB FE20 CPI ' ' ; C3AD C2C4C3 JNZ TRANS1 ;OK- FILENAME PRESENT C3B0 3AF0C4 LDA TRDISK ;NG- JUST CLEAN THINGS UP AND LEAVE C3B3 B7 ORA A ; C3B4 CA89C4 JZ CMEND1 ;EXIT IF ON THE LOGIN DISK C3B7 3D DCR A ; C3B8 32EFC4 STA CURDSK ;OTHERWISE LOG BACK TO THE LOGIN DISK C3BB CD29BE CALL LOGCUR ; C3BE CDBDBD CALL SELDSK ; C3C1 C389C4 JMP CMEND1 ;AND GO BACK FOR ANOTHER COMMAND ; C3C4 11D6C4 TRANS1: LXI D,FCB+9 ; CHECK THE FILE TYPE. C3C7 1A LDAX D ; C3C8 FE20 CPI ' ' ; C3CA C209BF JNZ WHAT ; YOU'RE NOT SUPPOSED TO HAVE A FILE TYPE W/ A TRANSIENT. C3CD D5 PUSH D ; C3CE CD54C1 CALL SETTRD ; SET TO TRANSIENT DRIVE. C3D1 D1 POP D ; C3D2 2183C4 LXI H,COM ; MOVE FILE TYPE "COM" INTO FCB. C3D5 CD40C1 CALL MOVE3 ; C3D8 CDD0BD CALL OPENF1 ; OPEN FILE FOR READING. C3DB CA6BC4 JZ TRANS8 ; ERROR CONDITION, FILE NOT FOUND. C3DE 210001 LXI H,TPA ; STARTING POINT FOR PROGRAM LOADING. ; C3E1 E5 TRANS2: PUSH H ; MOVE PROGRAM INTO TPA SECTOR BY SECTOR. C3E2 EB XCHG ; C3E3 CDD8BE CALL STDMA1 ; POINT TO LOADING LOCATION. C3E6 11CDC4 LXI D,FCB ; C3E9 CDF9BD CALL READF ; READ 1 SECTOR INTO MEMORY. C3EC C201C4 JNZ TRANS3 ; ZFLAG RESET ::= GOOD READ, GO AROUND FOR MORE. C3EF E1 POP H ; C3F0 118000 LXI D,SECLEN ; C3F3 19 DAD D ; ADVANCE POINTER FOR NEXT SECTOR. C3F4 1100BD LXI D,ORIGIN ; CHECK FOR PROGRAM OVERLAPPING CCP AREA. C3F7 7D MOV A,L ; C3F8 93 SUB E ; C3F9 7C MOV A,H ; C3FA 9A SBB D ; C3FB D271C4 JNC LDERR ; ERROR CONDITION, PROGRAM TOO BIG FOR MEMORY. C3FE C3E1C3 JMP TRANS2 ; BACK FOR NEXT SECTOR. ; C401 E1 TRANS3: POP H ; CLEAR STACK. C402 3D DCR A ; 1 ::= END OF FILE (GOOD) OR 2 ::= READ ERROR (BAD). C403 C271C4 JNZ LDERR ; READ ERROR. C406 CD66C1 CALL SETCUR ; SET BACK TO CURRENT DRIVE. C409 CD5EBF CALL TRFCB ; MOVE ANY FURTHER FCB'S AT 005CH AND 006CH. C40C 21F0C4 LXI H,TRDISK ; C40F E5 PUSH H ; C410 7E MOV A,M ;PUT TRANSIENT DISK NUMBER INTO C411 32CDC4 STA FCB ; FIRST BYTE OF FILE CONTROL BLOCK. C414 3E10 MVI A,16 ;SET OFFSET FOR TRFCB TO UPPER HALF OF FCB C416 CD60BF CALL TRFCB1 ;MOVE SECONF FILE NAME INTO FCB + 16 C419 E1 POP H ; C41A 7E MOV A,M ;GET TRANSIENT DISK NUMBER OF SECOND FN C41B 32DDC4 STA FCB+16 ; AND INSERT IT INTO FCB + 16 C41E AF XRA A ;ZERO OUT SECTOR COUNTER C41F 32EDC4 STA FCB+32 ; C422 115C00 LXI D,DFCB ;MOVE FILENAMES TO DEFAULT FCB C425 21CDC4 LXI H,FCB ; C428 0621 MVI B,33 ;FILE CONTROL BLOCK & SECTOR COUNTER C42A CD42C1 CALL BLKMOV ; ; C42D 2108BD LXI H,BUFFER ;START AT THE HEAD OF BUFFER C430 7E TRANS4: MOV A,M ;STEP UNTIL BLANK OR NULL FOUND C431 B7 ORA A ; I.E. STEP OVER TRANSIENT NAME C432 CA3EC4 JZ TRANS5 ; C435 FE20 CPI ' ' ; C437 CA3EC4 JZ TRANS5 ; C43A 23 INX H ; C43B C330C4 JMP TRANS4 ;LOOP ; C43E 0600 TRANS5: MVI B,00H ;COMMAND LINE BYTE COUNTER C440 118100 LXI D,DDMA+1 ; C443 7E TRANS6: MOV A,M ;MOVE COMMAND LINE INTO DEFAULT BUFFER C444 12 STAX D ; C445 B7 ORA A ;EXIT ON NULL C446 CA4FC4 JZ TRANS7 ; C449 04 INR B ;BUMP COUNTER C44A 23 INX H ; C44B 13 INX D ; C44C C343C4 JMP TRANS6 ; ; C44F 78 TRANS7: MOV A,B ;PUT BUFFER COUNTER AT START C450 328000 STA DDMA ; OF DEFAULT BUFFER C453 CD98BD CALL PCRLF ; C456 CDD5BE CALL SETDMA ;SET DMA TO DEFAULT BUFFER C459 CD1ABE CALL SETLOG ; SET LOG-IN BYTE W/ CURRENT DRIVE & USER NUMBER C45C CD0001 CALL TPA ; GO OUT AND RUN THE PROGRAM. C45F 31ABC4 LXI SP,STACK ; RESTORE STACK ON RETURN. C462 CD29BE CALL LOGCUR ;LOG BACK TO THE CURRENT DISK C465 CDBDBD CALL SELDSK ; C468 C382C0 JMP NXTCMD ; READY FOR ANOTHER ASSIGNMENT. ; ; REDUNDANT CODE: ; THIS CAN BE DELETED, AND JUMPS TO THIS ; POINT CHANGED TO TYPE4 ; C46B CD66C1 TRANS8: CALL SETCUR ;ERROR EXIT C46E C309BF JMP WHAT ; ; ; LOAD ERROR ; C471 017AC4 LDERR: LXI B,MSG7 ;LOAD THE ERROR POINTER C474 CDA7BD CALL CRMSG ;DISPLAY THE MESSAGE C477 C386C4 JMP COMEND ;EXIT ; C47A 424144204CMSG7: DB 'BAD LOAD',0 ; C483 434F4D COM: DB 'COM' ; FILE TYPE FOR TRANSIENT COMMANDS. ; ; COMMAND END ; CLEAN-UP AND EXIT POINT FOR ALL COMMANDS ; EXCEPT TRANSIENT COMMANDS. ; C486 CD66C1 COMEND: CALL SETCUR ;PRIMARY EXIT POINT C489 CD5EBF CMEND1: CALL TRFCB ;SECONDARY EXIT POINT C48C 3ACEC4 LDA FCB+1 ; CHECK FOR FURTHER COMMANDS. C48F D620 SUI ' ' ; C491 21F0C4 LXI H,TRDISK ; C494 B6 ORA M ; C495 C209BF JNZ WHAT ; C498 C382C0 JMP NXTCMD ; BACK TO THE RATRACE. ; ; END OF THE PROGRAM AREA ; ; START OF PARAMETER STORAGE AREA ; C49B DS 16 ;STACK AREA C4AB = STACK: EQU $ ;CCP STACK ; C4AB SUBFL: DS 1 ; SUBMIT FLAG. FLAG SET WHEN COMMANDS COME FROM $$$.SUB FILE. C4AC 0024242420SUBFCB: DB 0,'$$$ SUB',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 C4CD FCB: DS 33 ;FILE CONTROL BLOCK FOR CCP READ/WRITE C4EE RETVAL: DS 1 ; VALUE RETURNED IN (A) FROM CALLS TO BDOS. C4EF CURDSK: DS 1 ; CURRENT LOGGED IN DISK. C4F0 TRDISK: DS 1 ; CURRENT TRANSIENT DISK. C4F1 TYPCTR: DS 1 ; INPUT BUFFER COUNTER USED BY 'TYPE' TO KEEP TRACK ; OF INPUT DISK BUFFER. ; C4F2 FINISH: END ORIGIN ;END OF SOURCE CODE