CP/M RMAC ASSEM 1.1 #001 BODY OF CPM (CCP/BDOS) 17 DEC 84 TITLE 'BODY OF CPM (CCP/BDOS) 17 DEC 84' ; *********************************************************** ; ; R.H. PETERS RELOCATABLE CONSOLE COMMAND PROCESSOR ; FOR CP/M VERSION 2.2 ; ; *********************************************************** ; LAST REVISION: 2 JULY 1984 ; *********************************************************** ; ; Patched to cause the CCP of a cp/m 2.x system to look on drive A ; when you are logged into a drive other than A and call for a .COM ; file that does not exist on that drive. Giving an explicit drive ; reference overrides this feature, so that you can always force ; the file to be loaded from a specific drive. ; ; The serial number check routine has been removed. ; ; EQUATES ; 0005 = BDOS: EQU 0005H ;Link to operating system 0003 = BYTEIO: EQU 0003H ;I/O assigment byte for transient programs 0004 = INLOG: 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 = DMAD: EQU 0080H ;Default DMA block 0080 = LENSEC: EQU 0080H ;Sector length := 128 bytes. ; ; 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: PUBLIC @CCP ; @CCP: 0000 C32C03 ORIGIN: JMP CCP1 ;JUMP TO START OF CONSOLE COMMAND PROGRAM ; 0003 C32803 JMP CCP0 ;JUMP TO START OF CCP W/ CLEARING OF INPUT BUFFER COUNTER ; ; INPUT BUFFER WITH COPYRIGHT MESSAGE THROWN IN ; 0006 7F INPB: DB 127 ;MAXIMUM LENGTH OF INPUT BUFFER 0007 00 INBLEN: DB 0 ;CURRENT LENGTH OF INPUT BUFFER 0008 2020202020BUFFER: DB ' ' 0018 DS BUFFER+128-$ ; ; POINTERS TO INPUT BUFFER ; 0088 0800 BPTR1: DW BUFFER ;Pointer to input buffer used while parsing input line 008A 0000 BPTR2: DW 0000H ;Pointer to start of current command inn input buffer. ;Used by WHAT for error prompt. PAGE CP/M RMAC ASSEM 1.1 #002 BODY OF CPM (CCP/BDOS) 17 DEC 84 ; *************** ; SUBROUTINE AREA ; *************** ; ; TIES TO BDOS VIA VECTOR IN 0005H ; ; ; 008C 3E20 SPACE: MVI A,20H ;PRINT A SPACE 008E C39800 JMP PCHAR ; ; 0091 3E0D CRLFP: MVI A,0DH ;PRINT A CARRIAGE RETURN & LINE FEED 0093 CD9800 CALL PCHAR ; 0096 3E0A MVI A,0AH ; 0098 C5 PCHAR: PUSH B ;PRINT A CHARACTER ON THE CONSOLE 0099 5F MOV E,A ; 009A 0E02 MVI C,02H ; 009C CD0500 CALL BDOS ; 009F C1 POP B ; 00A0 C9 RET ; ; 00A1 C5 CRMSG: PUSH B ;PRINT A STRING PRECEDED BY A CR/LF 00A2 CD9100 CALL CRLFP ; 00A5 E1 POP H ; ; 00A6 7E PMSG: MOV A,M ;PRINT A STRING TERMINATED BY A NULL 00A7 B7 ORA A ; 00A8 C8 RZ ; 00A9 23 INX H ; 00AA E5 PUSH H ; 00AB CD9800 CALL PCHAR ; 00AE E1 POP H ; 00AF C3A600 JMP PMSG ; ; 00B2 0E0D RESET: MVI C,0DH ;RESET THE DISK SYSTEM 00B4 C30500 JMP BDOS ; ; 00B7 5F SELDSK: MOV E,A ;SELECT DISK 00B8 0E0E MVI C,0EH ; 00BA C30500 JMP BDOS ; ; 00BD AF F1OPEN: XRA A ;OPEN FILE @ FCB, AND ZERO RECORD COUNTER 00BE 32B007 STA FCB+32 ; 00C1 119007 LXI D,FCB ; 00C4 0E0F FOPEN: MVI C,0FH ;OPEN DISK FILE FOR READING OR WRITING 00C6 CD0500 BDOS6: CALL BDOS ; CALL TO BDOS W/ RETURN VALUE SAVED 00C9 32B107 STA RETVAL ; 00CC 3C INR A ;Set the ZFLAG for error condition 00CD C9 RET ; ; 00CE 0E10 FCLOSE: MVI C,10H ;CLOSE FILE AFTER READING OR WRITING 00D0 C3C600 JMP BDOS6 ; CALL TO BDOS W/ RETURN VALUE ; 00D3 119007 SRCHF1: LXI D,FCB ;SEARCH FOR FIRST OCCURENCE OF FILE 00D6 0E11 SRCHF: MVI C,11H ;SEARCH FOR FIRST OCCURENCE OF FILE NAME CP/M RMAC ASSEM 1.1 #003 BODY OF CPM (CCP/BDOS) 17 DEC 84 00D8 C3C600 JMP BDOS6 ; CALL TO BDOS W/ RETURN VALUE ; 00DB 0E12 SRCHNX: MVI C,12H ;SEARCH FOR NEXT OCCURENCE OF FILE NAME 00DD C3C600 JMP BDOS6 ; CALL TO BDOS W/ RETURN VALUE ; 00E0 0E13 DELETF: MVI C,13H ;DELETE FILE FROM DIRECTORY 00E2 C30500 JMP BDOS ; ; 00E5 119007 READ1: LXI D,FCB ;READ ONE SECTOR USING 'FCB' 00E8 0E14 READF: MVI C,14H ;READ ONE SECTOR FROM DISK 00EA CD0500 BDOS7: CALL BDOS ; CALL TO BDOS W/ RETURN VALUE 00ED B7 ORA A ; 00EE C9 RET ; ; 00EF 0E15 WRITEF: MVI C,15H ;WRITE ONE SECTOR TO DISK 00F1 C3EA00 JMP BDOS7 ; CALL TO BDOS W/ RETURN VALUE ; 00F4 0E16 CREATE: MVI C,16H ;CREATE A NEW FILE NAME IN DISK DIRECTORY 00F6 C3C600 JMP BDOS6 ; CALL TO BDOS W/ RETURN VALUE ; 00F9 0E17 NEWNAM: MVI C,17H ;RENAME EXISTING FILE IN DISK DIRECTORY 00FB C30500 JMP BDOS ; ; 00FE 1EFF GETUSR: MVI E,0FFH ;GET CURRENT USER NUMBER ; ; SET USER NUMBER TO VALUE IN (E), EXCEPT IF ; VALUE IS 0FFH. ; 0100 0E20 USRSET: MVI C,20H ; 0102 C30500 JMP BDOS ; PAGE CP/M RMAC ASSEM 1.1 #004 BODY OF CPM (CCP/BDOS) 17 DEC 84 ; ; Set log-in byte for transient program with current ; user number in upper 4 bits and current drive in ; lower 4 bits. ; 0105 CDFE00 SETLOG: CALL GETUSR ; SET LOG-IN BYTE W/ CURRENT DRIVE & USER NUMBER 0108 87 ADD A ; 0109 87 ADD A ; 010A 87 ADD A ; 010B 87 ADD A ;Shift user number to upper nibble 010C 21B207 LXI H,CRNDSK ; 010F B6 ORA M ;Combine with disk number 0110 320400 STA INLOG ;Place where transient programs 0113 C9 RET ; can find it. ; ; LOG IN CURRENT DISK ; Place current drive number in log-in byte without ; including user number. ; 0114 3AB207 LOGCUR: LDA CRNDSK ; 0117 320400 STA INLOG ; 011A C9 RET ; ; ; CONVERT lower case INPUT TO UPPER CASE ; 011B FE61 LCUC: CPI 61H ;'a' 011D D8 RC ; 011E FE7B CPI 7BH ;'z'+1 0120 D0 RNC ; 0121 E65F ANI 5FH ;MASK OFF BIT 5 0123 C9 RET ; PAGE CP/M RMAC ASSEM 1.1 #005 BODY OF CPM (CCP/BDOS) 17 DEC 84 ; ; COMMAND INPUT ; ; IF SUBMIT FLAG <> 0 THEN INPUT FROM SUBMIT FILE\ ; ELSE INPUT FROM KEYBOARD INPUT BUFFER ; 0124 3A6E07 CMNDIN: LDA SUBFL ;CHECK SUBMIT FILE FLAG 0127 B7 ORA A ; 0128 CA8101 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. ; 012B 3AB207 LDA CRNDSK ;FLAG SET: GET INPUT FROM SUBMIT FILE ON CURRENT DISK 012E B7 ORA A ; 012F 3E00 MVI A,00H ; 0131 C4B700 CNZ SELDSK ;Set to disk 0 if not there already 0134 116F07 LXI D,SUBFCB ; Point to submit file's file control block 0137 CDC400 CALL FOPEN ; Open the submit file for reading 013A CA8101 JZ LINEIN ;Go to console on Open File Error 013D 3A7E07 LDA SUBFCB+15 ;Get top sector number 0140 3D DCR A ;Decrement? Yes $$$.SUB files are backwards 0141 328F07 STA SUBFCB+32 ;Put number in Next Sector slot 0144 116F07 LXI D,SUBFCB ; 0147 CDE800 CALL READF ;Read sector into buffer 014A C28101 JNZ LINEIN ;Go to console on read error 014D 110700 LXI D,INBLEN ;Point to start of keyboard buffer 0150 218000 LXI H,DMAD ;Point to start of default buffer 0153 0680 MVI B,LENSEC ;Set counter 0155 CD0804 CALL MOVBLK ;Move line into keyboard buffer 0158 217D07 LXI H,SUBFCB+14 ; 015B 3600 MVI M,00H ; 015D 23 INX H ; 015E 35 DCR M ;Decrement sector count 015F 116F07 LXI D,SUBFCB ;close the file 0162 CDCE00 CALL FCLOSE ; 0165 CA8101 JZ LINEIN ;Go to console on close error 0168 3AB207 LDA CRNDSK ; 016B B7 ORA A ; 016C C4B700 CNZ SELDSK ;Set to current disk if not so already 016F 210800 LXI H,BUFFER ; 0172 CDA600 CALL PMSG ;Echo the $$$.SUB line to console 0175 CDAD01 CALL KSTAT ;Check for a keyboard break 0178 CA9201 JZ LINP1 ;NO BREAK- Continue CP/M RMAC ASSEM 1.1 #006 BODY OF CPM (CCP/BDOS) 17 DEC 84 017B CDC801 CALL EXITSB ; BREAK- Close off submit mode 017E C35203 JMP NXTCMD ;This leaves the return address on the ;stack, but NXTCMD re-initializes stack PAGE CP/M RMAC ASSEM 1.1 #007 BODY OF CPM (CCP/BDOS) 17 DEC 84 ; ; Get the input from the Console Device ; 0181 CDC801 LINEIN: CALL EXITSB ;RESET SUBMIT MODE FLAGS< ETC 0184 CD0501 CALL SETLOG ; SET LOG-IN BYTE W/ CURRENT DRIVE & USER NUMBER 0187 0E0A MVI C,0AH ;BDOS COMMAND 10 ::= READ INPUT BUFFER 0189 110600 LXI D,INPB ;POINT TO START OF INPUT BUFFER 018C CD0500 CALL BDOS ;GET A LINE FROM THE CONSOLE 018F CD1401 CALL LOGCUR ; 0192 210700 LINP1: LXI H,INBLEN ; 0195 46 MOV B,M ;Move the line byte count into (B) 0196 23 LINP2: INX H ;Step through buffer changing lower 0197 78 MOV A,B ;case into upper case. 0198 B7 ORA A ; 0199 CAA501 JZ LINP3 ;Exit when (B)=0 019C 7E MOV A,M ; 019D CD1B01 CALL LCUC ;Convert lower case to UPPER CASE 01A0 77 MOV M,A ; 01A1 05 DCR B ; 01A2 C39601 JMP LINP2 ;Loop ; 01A5 77 LINP3: MOV M,A ;Poke a zero into end of line to mark end 01A6 210800 LXI H,BUFFER ;Save command starting address 01A9 228800 SHLD BPTR1 ; for later use. 01AC C9 RET ; ; ; KEYBOARD STATUS CHECK ; Return with ZFLAG set is no key pressed ; Else return with character in accumulator ; 01AD 0E0B KSTAT: MVI C,0BH ; 01AF CD0500 CALL BDOS ; 01B2 B7 ORA A ; 01B3 C8 RZ ; 01B4 0E01 MVI C,01H ; 01B6 CD0500 CALL BDOS ; 01B9 B7 ORA A ; 01BA C9 RET ; PAGE CP/M RMAC ASSEM 1.1 #008 BODY OF CPM (CCP/BDOS) 17 DEC 84 ; ; INTEROGATE THE DISK ; 01BB 0E19 INTDSK: MVI C,19H ; 01BD C30500 JMP BDOS ; ; ; SET THE DMA ADDRESS ; 01C0 118000 SETDMA: LXI D,DMAD ; 01C3 0E1A STDMA1: MVI C,1AH ; 01C5 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 ; 01C8 216E07 EXITSB: LXI H,SUBFL ;SUBMIT FILE FLAG 01CB 7E MOV A,M ; 01CC B7 ORA A ; 01CD C8 RZ ;Not in submit mode, exit 01CE 3600 MVI M,00H ;Reset submit flag 01D0 AF XRA A ; 01D1 CDB700 CALL SELDSK ;Select correct disk 01D4 116F07 LXI D,SUBFCB ; 01D7 CDE000 CALL DELETF ;Delete the $$$.SUB file from disk 01DA 3AB207 LDA CRNDSK ; 01DD C3B700 JMP SELDSK ;Restore current disk and exit ; ; 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. ; 01E0 CD9100 WHAT: CALL CRLFP ; 01E3 2A8A00 LHLD BPTR2 ; Point to the offending command 01E6 7E WHAT1: MOV A,M ; and print until a space or null is found 01E7 FE20 CPI ' ' ; 01E9 CAF901 JZ WHAT2 ; 01EC B7 ORA A ; 01ED CAF901 JZ WHAT2 ; 01F0 E5 PUSH H ; 01F1 CD9800 CALL PCHAR ; 01F4 E1 POP H ; 01F5 23 INX H ; 01F6 C3E601 JMP WHAT1 ; ; 01F9 3E3F WHAT2: MVI A,'?' ; OK, what did you have in mind? 01FB CD9800 CALL PCHAR ; 01FE CD9100 CALL CRLFP ; 0201 CDC801 CALL EXITSB ; 0204 C35203 JMP NXTCMD ; Back for another command. CP/M RMAC ASSEM 1.1 #009 BODY OF CPM (CCP/BDOS) 17 DEC 84 PAGE CP/M RMAC ASSEM 1.1 #010 BODY OF CPM (CCP/BDOS) 17 DEC 84 ; ; 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. ; 0207 1A CHRCHK: LDAX D ; 0208 B7 ORA A ; 0209 C8 RZ ;Exit on null 020A FE20 CPI ' ' ; 020C DAE001 JC WHAT ;Bomb out on control character 020F C8 RZ ; 0210 FE3D CPI '=' ; 0212 C8 RZ ; 0213 FE5F CPI '_' ; 0215 C8 RZ ; 0216 FE2E CPI '.' ; 0218 C8 RZ ; 0219 FE3A CPI ':' ; 021B C8 RZ ; 021C FE3B CPI ';' ; 021E C8 RZ ; 021F FE3C CPI '<' ; 0221 C8 RZ ; 0222 FE3E CPI '>' ; 0224 C9 RET ; ; ; STEP (DE) UNTIL A NULL OR NON-SPACE IS FOUND ; Return with the character in the accumulator. ; 0225 1A STEP: LDAX D ; 0226 B7 ORA A ; 0227 C8 RZ ; 0228 FE20 CPI 20H ;' ' 022A C0 RNZ ; 022B 13 INX D ; 022C C32502 JMP STEP ; ; ; ADD THE ACCUMULATOR TO (HL) ; Return with the result in (HL) ; 022F 85 ADDAH: ADD L ; (HL) <- (HL) + (A) 0230 6F MOV L,A ; 0231 D0 RNC ; 0232 24 INR H ; 0233 C9 RET ; PAGE CP/M RMAC ASSEM 1.1 #011 BODY OF CPM (CCP/BDOS) 17 DEC 84 ; ; 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. ; 0234 3E00 TRFCB: MVI A,00H ;Initial offset=0, primary entry point 0236 219007 TRFCB1: LXI H,FCB ;(Alternate entry point, offset in (A)) 0239 CD2F02 CALL ADDAH ;Point to current character in FCB 023C E5 PUSH H ; 023D E5 PUSH H ;Save pointer twice. 023E AF XRA A ; 023F 32B307 STA TRDISK ; 0242 2A8800 LHLD BPTR1 ;Get current pointer to the input buffer 0245 EB XCHG ; 0246 CD2502 CALL STEP ;Get first non-blank character 0249 EB XCHG ; 024A 228A00 SHLD BPTR2 ;Save pointer in case of error 024D EB XCHG ; 024E E1 POP H ;Get FCB pointer 024F 1A LDAX D ; 0250 B7 ORA A ;Check for null command 0251 CA5F02 JZ TRFCB2 ; 0254 DE40 SBI 40H ;Remove ASCII bias. 0256 47 MOV B,A ;Save possible disk number in (B) 0257 13 INX D ; 0258 1A LDAX D ; 0259 FE3A CPI ':' ; This means that this is a disk number. 025B CA6602 JZ TRFCB3 ; Go set transient disk. 025E 1B DCX D ; Get current logged in disk number. 025F 3AB207 TRFCB2: LDA CRNDSK ; 0262 77 MOV M,A ; 0263 C36C02 JMP TRFCB4 ; ; 0266 78 TRFCB3: MOV A,B ; Set transient disk number. 0267 32B307 STA TRDISK ; 026A 70 MOV M,B ; Put disk number into head of File Control Block. 026B 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 '?' CP/M RMAC ASSEM 1.1 #012 BODY OF CPM (CCP/BDOS) 17 DEC 84 ; 026C 0608 TRFCB4: MVI B,08H ; Move file name of up to 8 Characters. 026E CD0702 TRFCB5: CALL CHRCHK ; Exit if a special character is found. 0271 CA8F02 JZ TRFCB9 ; Go pad the rest of the block w/ ' ' 0274 23 INX H ; 0275 FE2A CPI '*' ;This is a Wild card match 0277 C27F02 JNZ TRFCB6 ; 027A 363F MVI M,'?' ;This is an 'anything match'. 027C C38102 JMP TRFCB7 ; ; 027F 77 TRFCB6: MOV M,A ; 0280 13 INX D ; 0281 05 TRFCB7: DCR B ; 0282 C26E02 JNZ TRFCB5 ; ; 0285 CD0702 TRFCB8: CALL CHRCHK ;Check for special character 0288 CA9602 JZ TRFC10 ; 028B 13 INX D ; 028C C38502 JMP TRFCB8 ; ; 028F 23 TRFCB9: INX H ; Pad the rest of the file name with blanks. 0290 3620 MVI M,' ' ; 0292 05 DCR B ; 0293 C28F02 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. ; 0296 0603 TRFC10: MVI B,03H ; Move a file type of up to 3 Characters. 0298 FE2E CPI '.' ;A period is the only legal special character in this case. 029A C2BF02 JNZ TRFC15 ; 029D 13 INX D ; 029E CD0702 TRFC11: CALL CHRCHK ; Check for special characters. 02A1 CABF02 JZ TRFC15 ; 02A4 23 INX H ; 02A5 FE2A CPI '*' ;Wild card match- Pad the 3 bytes with ??? 02A7 C2AF02 JNZ TRFC12 ; 02AA 363F MVI M,'?' ; 02AC C3B102 JMP TRFC13 ; ; 02AF 77 TRFC12: MOV M,A ;Put the character into FCB 02B0 13 INX D ;Advance FCB pointer 02B1 05 TRFC13: DCR B ;Decrement character counter 02B2 C29E02 JNZ TRFC11 ;Loop until counter is zero 02B5 CD0702 TRFC14: CALL CHRCHK ;Step buffer until special character, 02B8 CAC602 JZ TRFC16 ; or null is found. 02BB 13 INX D ; 02BC C3B502 JMP TRFC14 ; ; 02BF 23 TRFC15: INX H ;Pad the rest of the extent with ' ' 02C0 3620 MVI M,' ' ; 02C2 05 DCR B ; 02C3 C2BF02 JNZ TRFC15 ; ; 02C6 0603 TRFC16: MVI B,03H ;Zero out bytes 12 through 14 CP/M RMAC ASSEM 1.1 #013 BODY OF CPM (CCP/BDOS) 17 DEC 84 02C8 23 TRFC17: INX H ; 02C9 3600 MVI M,00H ; 02CB 05 DCR B ; 02CC C2C802 JNZ TRFC17 ; ; 02CF EB XCHG ; 02D0 228800 SHLD BPTR1 ;Save the input buffer pointer 02D3 E1 POP H ;(HL) = FCB 02D4 010B00 LXI B,11 ;Set counter 02D7 23 TRFC18: INX H ;Count number of '?' in filename.ext 02D8 7E MOV A,M ; 02D9 FE3F CPI '?' ; 02DB C2DF02 JNZ TRFC19 ;Skip if not'?' 02DE 04 INR B ; 02DF 0D TRFC19: DCR C ; 02E0 C2D702 JNZ TRFC18 ; 02E3 78 MOV A,B ;Move '?' count into (A) 02E4 B7 ORA A ;Set flags to indicate ambigous filename 02E5 C9 RET ; PAGE CP/M RMAC ASSEM 1.1 #014 BODY OF CPM (CCP/BDOS) 17 DEC 84 ; ; COMMAND NAME LIST ; 02E6 44495220 CMNDL: DB 'DIR ' ;Read directory 02EA 45524120 DB 'ERA ' ;Erase file 02EE 54595045 DB 'TYPE' ;Output named file to console 02F2 53415645 DB 'SAVE' ;Save named file on disk 02F6 52454E20 DB 'REN ' ;Rename file 02FA 55534552 DB 'USER' ;Set user number PAGE CP/M RMAC ASSEM 1.1 #015 BODY OF CPM (CCP/BDOS) 17 DEC 84 ; ; 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. ; 02FE 21E602 CSRCH: LXI H,CMNDL ; Point to start of command list. 0301 0E00 MVI C,00H ; Zero out command counter. 0303 79 CSRCH1: MOV A,C ; Check counter for maximum number of tries. 0304 FE06 CPI 6 ;(There are 6 intrinsic commands + transients) 0306 D0 RNC ; Return is no match in six tries. It is a transient command. 0307 119107 LXI D,FCB+1 ; Point to start of command to be matched. 030A 0604 MVI B,04H ; Maximum number of characters in command name. 030C 1A CSRCH2: LDAX D ; 030D BE CMP M ; 030E C21F03 JNZ CSRCH3 ; No match- exit loop. 0311 13 INX D ; 0312 23 INX H ; 0313 05 DCR B ; 0314 C20C03 JNZ CSRCH2 ; Back for another match. 0317 1A LDAX D ; Found the command, now check for a separating space. 0318 FE20 CPI ' ' ; 031A C22403 JNZ CSRCH4 ; No space, try for something else. 031D 79 MOV A,C ; Put command count in accumulator. 031E C9 RET ; Exit routine with command number. ; 031F 23 CSRCH3: INX H ; Step forwards to that start of the next command name. 0320 05 DCR B ; 0321 C21F03 JNZ CSRCH3 ; 0324 0C CSRCH4: INR C ; Bump command counter by one. 0325 C30303 JMP CSRCH1 ; Back for another try. PAGE CP/M RMAC ASSEM 1.1 #016 BODY OF CPM (CCP/BDOS) 17 DEC 84 ; ; ****************************** ; 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. ; 0328 AF CCP0: XRA A ; 0329 320700 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 ; 032C 316E07 CCP1: LXI SP,STACK ;Set up loacal stack 032F C5 PUSH B ;Save entry parameter 0330 79 MOV A,C ; 0331 1F RAR ;Move upper 4 bits down 0332 1F RAR ; 0333 1F RAR ; 0334 1F RAR ; 0335 E60F ANI 0FH ;Extract user number from input parameter 0337 5F MOV E,A ; 0338 CD0001 CALL USRSET ;Put user number in its place 033B CDB200 CALL RESET ;Reset disk system 033E 326E07 STA SUBFL ;SUBMIT FILE FLAG 0341 C1 POP B ;Get back entry parameter 0342 79 MOV A,C ; 0343 E60F ANI 0FH ;Extract disk drive number from input parameter 0345 32B207 STA CRNDSK ;Set to correct disk drive 0348 CDB700 CALL SELDSK ; 034B 3A0700 LDA INBLEN ; 034E B7 ORA A ;Check to see if there is anything in the input buffer 034F C26803 JNZ CCP2 ;There is, so don't bother with input. ; ; RE-ENTRY POINT FOR NEXT COMMAND ; 0352 316E07 NXTCMD: LXI SP,STACK ; Reset stack, and put out a prompt so ; that you know what disk you are operating on. 0355 CD9100 CALL CRLFP ; 0358 CDBB01 CALL INTDSK ;Get drive number 035B C641 ADI 'A' ;Add ASCII bias 035D CD9800 CALL PCHAR ; 0360 3E3E MVI A,'>' ;Prompt character 0362 CD9800 CALL PCHAR ; 0365 CD2401 CALL CMNDIN ; Input the next command line from the console or submit file. 0368 118000 CCP2: LXI D,DMAD ;Set to the default DMA (0080H) 036B CDC301 CALL STDMA1 ; CP/M RMAC ASSEM 1.1 #017 BODY OF CPM (CCP/BDOS) 17 DEC 84 036E CDBB01 CALL INTDSK ;Check disk drive 0371 32B207 STA CRNDSK ; 0374 CD3402 CALL TRFCB ;Put command name in FCB 0377 C4E001 CNZ WHAT ;Ambigous filename.ext No good 037A 3AB307 LDA TRDISK ; 037D B7 ORA A ; 037E C26306 JNZ TRANS ;Transient command 0381 CDFE02 CALL CSRCH ;Find command in command list 0384 219103 LXI H,CMNDT ;Point to command vector table 0387 5F MOV E,A ;Put command number in (DE) 0388 1600 MVI D,00H ; 038A 19 DAD D ; 038B 19 DAD D ;(HL) <-- CMNDT + 2 * Command number 038C 7E MOV A,M ;Move command vector into (HL) 038D 23 INX H ; 038E 66 MOV H,M ; 038F 6F MOV L,A ; 0390 E9 PCHL ;Go forth and execute the command. ; ; COMMAND VECTOR TABLE ; 0391 3B04 CMNDT: DW DIR ;Display directory 0393 E304 DW ERA ;Erase file 0395 2105 DW TYPE ;Type file to console 0397 7105 DW SAVE ;Save file on disk 0399 D405 DW REN ;Rename file 039B 4C06 DW USER ;Set user number 039D 6306 DW TRANS ;Load and execute transient command PAGE CP/M RMAC ASSEM 1.1 #018 BODY OF CPM (CCP/BDOS) 17 DEC 84 ; ; FILE READ ERROR ; 039F 01A503 RDERR: LXI B,MSG1 ;Load pointer to message 03A2 C3A100 JMP CRMSG ;Display message & return ; 03A5 5245414420MSG1: DB 'READ ERROR',0 ; ; FILE NOT FOUND ERROR ; 03B0 01B603 NFERR: LXI B,MSG2 ;Load pointer to message 03B3 C3A100 JMP CRMSG ;Display message & return ; 03B6 4E4F204649MSG2: DB 'NO FILE',0 PAGE CP/M RMAC ASSEM 1.1 #019 BODY OF CPM (CCP/BDOS) 17 DEC 84 ; ; 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 '*' ; 03BE CD3402 DECIML: CALL TRFCB ;Move numbers into FCB 03C1 3AB307 LDA TRDISK ; 03C4 B7 ORA A ; 03C5 C2E001 JNZ WHAT ; 03C8 219107 LXI H,FCB+1 ; 03CB 010B00 LXI B,11 ;8 NUMBER FILE NAME & 3 CHAR EXT 03CE 7E DEC1: MOV A,M ; 03CF FE20 CPI ' ' ; 03D1 CAF903 JZ DEC2 ; 03D4 23 INX H ; 03D5 D630 SUI '0' ;REMOVE ASCII BIAS 03D7 FE0A CPI 10 ; 03D9 D2E001 JNC WHAT ; 03DC 57 MOV D,A ; 03DD 78 MOV A,B ;* 03DE E6E0 ANI 0E0H ;* 03E0 C2E001 JNZ WHAT ;* 03E3 78 MOV A,B ;* 03E4 07 RLC ;MULTIPLY BY 10 03E5 07 RLC ; 03E6 07 RLC ; 03E7 80 ADD B ; 03E8 DAE001 JC WHAT ;Overflow 03EB 80 ADD B ; 03EC DAE001 JC WHAT ;Overflow 03EF 82 ADD D ; 03F0 DAE001 JC WHAT ;Overflow 03F3 47 MOV B,A ; 03F4 0D DCR C ;* 03F5 C2CE03 JNZ DEC1 ;* Should be JMP DEC1 03F8 C9 RET ;* ; 03F9 7E DEC2: MOV A,M ;*Step over blanks to end of block 03FA FE20 CPI ' ' ;* 03FC C2E001 JNZ WHAT ;* 03FF 23 INX H ;* 0400 0D DCR C ;* 0401 C2F903 JNZ DEC2 ;* 0404 78 MOV A,B ;Return with binary value in (A) 0405 C9 RET ; PAGE CP/M RMAC ASSEM 1.1 #020 BODY OF CPM (CCP/BDOS) 17 DEC 84 ; ; BLOCK MOVE ; Source :: ((HL)) ; Destination :: ((DE)) ; Count :: (B) ; 0406 0603 MOVE3: MVI B,03H ;3 byte move 0408 7E MOVBLK: MOV A,M ;Source 0409 12 STAX D ;Destination 040A 23 INX H ; 040B 13 INX D ; 040C 05 DCR B ;Counter 040D C20804 JNZ MOVBLK ; 0410 C9 RET ; ; ; SET DIRECTORY POINTER ; Point to (DMAD) + (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. ; 0411 218000 PTRDIR: LXI H,DMAD ;Point to start of directory sector 0414 81 ADD C ;Add byte number to directory offset 0415 CD2F02 CALL ADDAH ; then add the result to (HL) 0418 7E MOV A,M ; and get the byte pointed to. 0419 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 ; 041A AF SETTRD: XRA A ; 041B 329007 STA FCB ;Set first byte of FCB to 0 041E 3AB307 LDA TRDISK ; 0421 B7 ORA A ;Check to see if transient disk= 0 0422 C8 RZ ;OK- no change needed 0423 3D DCR A ; 0424 21B207 LXI H,CRNDSK ;Now check current disk 0427 BE CMP M ; 0428 C8 RZ ;OK- no change needed 0429 C3B700 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 ; 042C 3AB307 SETCUR: LDA TRDISK ; 042F B7 ORA A ; 0430 C8 RZ ;OK- On log-in disk, no change 0431 3D DCR A ; CP/M RMAC ASSEM 1.1 #021 BODY OF CPM (CCP/BDOS) 17 DEC 84 0432 21B207 LXI H,CRNDSK ; 0435 BE CMP M ; 0436 C8 RZ ;OK 0437 7E MOV A,M ;On different disk. 0438 C3B700 JMP SELDSK ; so go make change PAGE CP/M RMAC ASSEM 1.1 #022 BODY OF CPM (CCP/BDOS) 17 DEC 84 ; ; 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 ; 043B CD3402 DIR: CALL TRFCB ; TRANSFER THE COMMAND LINE INTO 005CH. 043E CD1A04 CALL SETTRD ; SET TO TRANSIENT DISK 0441 219107 LXI H,FCB+1 ; POINT TO START OF FILE NAME 0444 7E MOV A,M ; CHECK FOR A BLANK 0445 FE20 CPI 20H ;' ' 0447 C25304 JNZ DIR1 ; NOT BLANK, GO FIND WHAT IS WANTED. ; 044A 060B MVI B,11 ; BLANK ::= DISPLAY ENTIRE DIRECTORY 044C 363F DIR0: MVI M,3FH ; FILL ENTIRE FILENAME/TYPE ARE WITH WILDCARD [?]'?' 044E 23 INX H ; 044F 05 DCR B ; 0450 C24C04 JNZ DIR0 ; ; 0453 1E00 DIR1: MVI E,00H ; SEARCH FOR FILE. 0455 D5 PUSH D ; 0456 CDD300 CALL SRCHF1 ; 0459 CCB003 CZ NFERR ; ERROR 045C CADF04 DIR2: JZ DIR10 ; 045F 3AB107 LDA RETVAL ;Get directory entry number 0462 0F RRC ;Convert to directory block pointer 0463 0F RRC ;by multiplying by 32 and masking off 0464 0F RRC ;the excess 0465 E660 ANI 60H ; 0467 4F MOV C,A ;Stash block pointer 0468 3E0A MVI A,10 ; 046A CD1104 CALL PTRDIR ;Get character @ DMAD + block pointer + 10 = Second char of ext 046D 17 RAL ;Check for MSB set :: SYSTEM file 046E DAD304 JC DIR9 ;Skip- System files are not listed by DIR 0471 D1 POP D ; 0472 7B MOV A,E ; 0473 1C INR E ; 0474 D5 PUSH D ; 0475 E603 ANI 03H ;Check for every 4th directory item 0477 F5 PUSH PSW ; 0478 C29004 JNZ DIR3 ;Not the 4th 047B CD9100 CALL CRLFP ; 4th, so start new line and mark 047E C5 PUSH B ; with disk drive letter 047F CDBB01 CALL INTDSK ;Get disk number CP/M RMAC ASSEM 1.1 #023 BODY OF CPM (CCP/BDOS) 17 DEC 84 0482 C1 POP B ; 0483 C641 ADI 'A' ;Print the disk number & colon at the 0485 CD9800 CALL PCHAR ;start of each directory print line 0488 3E3A MVI A,':' ; 048A CD9800 CALL PCHAR ; 048D C39804 JMP DIR4 ; ; 0490 CD8C00 DIR3: CALL SPACE ;Print a space/colon/space between 0493 3E3A MVI A,':' ;directory items 0495 CD9800 CALL PCHAR ; 0498 CD8C00 DIR4: CALL SPACE ; 049B 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? ; 049D 78 DIR5: MOV A,B ;Print the filename.ext to the console 049E CD1104 CALL PTRDIR ;Point to byte and reurn w/ byte in (A) 04A1 E67F ANI 7FH ; 04A3 FE20 CPI ' ' ; 04A5 C2BD04 JNZ DIR7 ; 04A8 F1 POP PSW ; 04A9 F5 PUSH PSW ; 04AA FE03 CPI 03H ;Check for file ext end 04AC C2BB04 JNZ DIR6 ; 04AF 3E09 MVI A,09H ;Check for file name end 04B1 CD1104 CALL PTRDIR ; 04B4 E67F ANI 7FH ; 04B6 FE20 CPI ' ' ;Check for no file ext 04B8 CAD204 JZ DIR8 ; 04BB 3E20 DIR6: MVI A,' ' ;Separator between filename & ext 04BD CD9800 DIR7: CALL PCHAR ; 04C0 04 INR B ; 04C1 78 MOV A,B ; 04C2 FE0C CPI 12 ;File ext end +1 04C4 D2D204 JNC DIR8 ; 04C7 FE09 CPI 9 ;File name end +1 04C9 C29D04 JNZ DIR5 ; 04CC CD8C00 CALL SPACE ; 04CF C39D04 JMP DIR5 ; ; 04D2 F1 DIR8: POP PSW ; 04D3 CDAD01 DIR9: CALL KSTAT ;CHECK KEY BOARD, ANY KEY BREAKS 04D6 C2DF04 JNZ DIR10 ;Exit on break 04D9 CDDB00 CALL SRCHNX ;Look for another directory item 04DC C35C04 JMP DIR2 ;Loop back for more ; 04DF D1 DIR10: POP D ; 04E0 C34907 JMP COMEND ;EXIT PAGE CP/M RMAC ASSEM 1.1 #024 BODY OF CPM (CCP/BDOS) 17 DEC 84 ; ; ****************************************************** ; 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 ; ****************************************************** ; 04E3 CD3402 ERA: CALL TRFCB ;Set up the file control block 04E6 FE0B CPI 11 ;If 11 '?' are in the FCB then you are 04E8 C20605 JNZ ERA1 ;asking to erase the whole disk. *.* 04EB 011605 LXI B,MSG3 ;Ask for verification before proceeding 04EE CDA100 CALL CRMSG ; 04F1 CD2401 CALL CMNDIN ;Get keyboard entry 04F4 210700 LXI H,INBLEN ;check for return without entry 04F7 35 DCR M ; 04F8 C25203 JNZ NXTCMD ;Abort on empty line 04FB 23 INX H ; 04FC 7E MOV A,M ; 04FD FE59 CPI 'Y' ;Yes, proceed with erasing everything 04FF C25203 JNZ NXTCMD ;Chickened out 0502 23 INX H ; 0503 228800 SHLD BPTR1 ; 0506 CD1A04 ERA1: CALL SETTRD ;set the transient disk 0509 119007 LXI D,FCB ;Point to the file control block 050C CDE000 CALL DELETF ;Call the routine that calls th e BDOS erase 050F 3C INR A ;Check the return parameter 0510 CCB003 CZ NFERR ;Warn if item not found 0513 C34907 JMP COMEND ;EXIT ; 0516 414C4C2028MSG3: DB 'ALL (Y/N)?',0 PAGE CP/M RMAC ASSEM 1.1 #025 BODY OF CPM (CCP/BDOS) 17 DEC 84 ; ; *********************************** ; OUTPUT NAMED FILE TO THE CONSOLE ; File name.ext must be unconditional ; *********************************** ; 0521 CD3402 TYPE: CALL TRFCB ;Set up file name in FCB 0524 C2E001 JNZ WHAT ;Badly formed filename: ambigous 0527 CD1A04 CALL SETTRD ;Set the disk 052A CDBD00 CALL F1OPEN ;Open the file for reading 052D CA6B05 JZ TYPE4 ;Error on opening 0530 CD9100 CALL CRLFP ; 0533 21B407 LXI H,TYPCTR ;Initiate counter 0536 36FF MVI M,0FFH ; 0538 21B407 TYPE1: LXI H,TYPCTR ; 053B 7E MOV A,M ;Get the buffer counter 053C FE80 CPI 80H ;Check for end of buffer 053E DA4B05 JC TYPE2 ;Not at end, get character from buffer ; ; At end of buffer- Read from disk ; 0541 E5 PUSH H ;Read a sector from disk to the buffer 0542 CDE500 CALL READ1 ; 0545 E1 POP H ; 0546 C26405 JNZ TYPE3 ;RETURN VALUE <> 0. End of file or bad read 0549 AF XRA A ; 054A 77 MOV M,A ;Zero (TYPCTR) 054B 34 TYPE2: INR M ; 054C 218000 LXI H,DMAD ; 054F CD2F02 CALL ADDAH ;Point to character 0552 7E MOV A,M ;Get the character 0553 FE1A CPI 1AH ;Check for end of file 0555 CA4907 JZ COMEND ;EXIT 0558 CD9800 CALL PCHAR ;Not EOF, output the byte to the console 055B CDAD01 CALL KSTAT ;Check for keyboard break 055E C24907 JNZ COMEND ;EXIT ON ANY KEY 0561 C33805 JMP TYPE1 ;Back for the next letter ; ; (A) = 1 :: End of file ; (A) = 2 :: Read error ; 0564 3D TYPE3: DCR A ; 0565 CA4907 JZ COMEND ;EXIT AT END OF FILE 0568 CD9F03 CALL RDERR ; 056B CD2C04 TYPE4: CALL SETCUR ; 056E C3E001 JMP WHAT ; PAGE CP/M RMAC ASSEM 1.1 #026 BODY OF CPM (CCP/BDOS) 17 DEC 84 ; ; ********************************** ; 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. ; ********************************** ; 0571 CDBE03 SAVE: CALL DECIML ;GET THE NUMBER OF PAGES TO BE SAVED 0574 F5 PUSH PSW ; 0575 CD3402 CALL TRFCB ;SET UP THE FILE NAME 0578 C2E001 JNZ WHAT ;Cannot be ambigous file 057B CD1A04 CALL SETTRD ;SET UP DISK 057E 119007 LXI D,FCB ; 0581 D5 PUSH D ; 0582 CDE000 CALL DELETF ;DELETE OLD FILE OF SAME NAME 0585 D1 POP D ; 0586 CDF400 CALL CREATE ;CREATE A NEW FILE IN DIRECTORY 0589 CABF05 JZ SAVE3 ; 058C AF XRA A ; 058D 32B007 STA FCB+32 ;ZERO OUT SECTOR COUNTER 0590 F1 POP PSW ; 0591 6F MOV L,A ; 0592 2600 MVI H,00H ;CHECK PAGE COUNTER 0594 29 DAD H ; 0595 110001 LXI D,TPA ; 0598 7C SAVE1: MOV A,H ;CHECK PAGE COUNTER 0599 B5 ORA L ; 059A CAB505 JZ SAVE2 ;EXIT, LAST PAGE HAS BEEN WRITTEN 059D 2B DCX H ; 059E E5 PUSH H ;SAVE COUNTER 059F 218000 LXI H,LENSEC ;ADVANCE DMA LOCATION 05A2 19 DAD D ;BY ONE SECTOR 05A3 E5 PUSH H ; 05A4 CDC301 CALL STDMA1 ;SET THE DMA ADDRESS 05A7 119007 LXI D,FCB ; 05AA CDEF00 CALL WRITEF ;WRITE THE SECTOR TO DISK 05AD D1 POP D ; 05AE E1 POP H ; 05AF C2BF05 JNZ SAVE3 ;ERROR CONDITION 05B2 C39805 JMP SAVE1 ;LOOP BACK TO WRITE ANOTHER SECTOR ; 05B5 119007 SAVE2: LXI D,FCB ;CLOSE THE FILE TO MAKE IT OFFICIAL 05B8 CDCE00 CALL FCLOSE ; 05BB 3C INR A ;CHECK FOR GOOD CLOSING 05BC C2C505 JNZ SAVE4 ;OK 05BF 01CB05 SAVE3: LXI B,MSG4 ; ERROR 05C2 CDA100 CALL CRMSG ; 05C5 CDC001 SAVE4: CALL SETDMA ; 05C8 C34907 JMP COMEND ;EXIT ; 05CB 4E4F205350MSG4: DB 'NO SPACE',0 PAGE CP/M RMAC ASSEM 1.1 #027 BODY OF CPM (CCP/BDOS) 17 DEC 84 ; ; ******************************************* ; RENAME A FILE THE FORMAT IS ; .=. ; A '_' may be substituted for the '=' ; ******************************************* ; 05D4 CD3402 REN: CALL TRFCB ;Put new filename into FCB 05D7 C2E001 JNZ WHAT ;Cannot be ambigous filename 05DA 3AB307 LDA TRDISK ;Get the disk number 05DD F5 PUSH PSW ; 05DE CD1A04 CALL SETTRD ;Log into the correct disk 05E1 CDD300 CALL SRCHF1 ;Check to see if such a name exists 05E4 C23706 JNZ FEERR ;ERROR- File name already used 05E7 219007 LXI H,FCB ;Move new filename to upper half of FCB 05EA 11A007 LXI D,FCB+16 ; 05ED 0610 MVI B,10H ; 05EF CD0804 CALL MOVBLK ; 05F2 2A8800 LHLD BPTR1 ;Back to input buffer 05F5 EB XCHG ; 05F6 CD2502 CALL STEP ; 05F9 FE3D CPI '=' ;Check for proper separator 05FB CA0306 JZ REN1 ;OK 05FE FE5F CPI '_' ; 0600 C26B05 JNZ TYPE4 ;NO GOOD 0603 EB REN1: XCHG ; 0604 23 INX H ;Step over separartor 0605 228800 SHLD BPTR1 ;Store pointer for TRFCB to use 0608 CD3402 CALL TRFCB ;Move name.type of Old file into place 060B C26B05 JNZ TYPE4 ;Error- cannot be ambigous 060E F1 POP PSW ;Get back disk number 060F 47 MOV B,A ; 0610 21B307 LXI H,TRDISK ; 0613 7E MOV A,M ; 0614 B7 ORA A ; 0615 CA1D06 JZ REN2 ;OK- current disk=transient disk 0618 B8 CMP B ;Check disk number 0619 70 MOV M,B ;Save back into TRDISK 061A C26B05 JNZ TYPE4 ;Error 061D 70 REN2: MOV M,B ; 061E AF XRA A ; 061F 329007 STA FCB ;Zero in FCB :: Logged in disk 0622 CDD300 CALL SRCHF1 ;Does old file exist? 0625 CA3106 JZ REN3 ;NO- Error 0628 119007 LXI D,FCB ;OK- Rename it 062B CDF900 CALL NEWNAM ; via call to BDOS 062E C34907 JMP COMEND ;EXIT ; 0631 CDB003 REN3: CALL NFERR ; Error 0634 C34907 JMP COMEND ;EXIT ; ; FILE EXISTS ERROR ; 0637 014006 FEERR: LXI B,MSG6 ;Load error message pointer 063A CDA100 CALL CRMSG ;Display maessage CP/M RMAC ASSEM 1.1 #028 BODY OF CPM (CCP/BDOS) 17 DEC 84 063D C34907 JMP COMEND ;EXIT ; 0640 46494C4520MSG6: DB 'FILE EXISTS',0 PAGE CP/M RMAC ASSEM 1.1 #029 BODY OF CPM (CCP/BDOS) 17 DEC 84 ; ; ************************************ ; SET THE USER NUMBER FROM THE CONSOLE ; Nobody uses this in one-user CP/M ; ************************************ ; 064C CDBE03 USER: CALL DECIML ;Convert number to binary 064F FE10 CPI 10H ;Must be 0 to 15 0651 D2E001 JNC WHAT ;Out of range 0654 5F MOV E,A ;Set in place for BDOS call 0655 3A9107 LDA FCB+1 ;Check for blank 'filename' 0658 FE20 CPI ' ' ; 065A CAE001 JZ WHAT ;Error 065D CD0001 CALL USRSET ;Set via BDOS 0660 C34C07 JMP CMEND1 ;EXIT PAGE CP/M RMAC ASSEM 1.1 #030 BODY OF CPM (CCP/BDOS) 17 DEC 84 ; ; ************************************************* ; TRANS LOADS A PROGRAM INTO THE TPA IF IT IS NOT A ; COMMAND NAME, AND A PROPER .COM FILE ; EXISTS ON THE TRANSIENT DISK. ; ************************************************* ; 0663 3A9107 TRANS: LDA FCB+1 ; SPACE ::= NO FILE NAME PRESENT. 0666 FE20 CPI ' ' ; 0668 C27F06 JNZ TRANS1 ;OK- Filename present 066B 3AB307 LDA TRDISK ;NG- Just clean things up and leave 066E B7 ORA A ; 066F CA4C07 JZ CMEND1 ;EXIT IF ON THE LOGIN DISK 0672 3D DCR A ; 0673 32B207 STA CRNDSK ;OTHERWISE LOG BACK TO THE LOGIN DISK 0676 CD1401 CALL LOGCUR ; 0679 CDB700 CALL SELDSK ; 067C C34C07 JMP CMEND1 ;AND GO BACK FOR ANOTHER COMMAND ; 067F 119907 TRANS1: LXI D,FCB+9 ; CHECK THE FILE TYPE. 0682 1A LDAX D ; 0683 FE20 CPI ' ' ; 0685 C2E001 JNZ WHAT ; YOU'RE NOT SUPPOSED TO HAVE A FILE TYPE W/ A TRANSIENT. 0688 D5 PATCH1: PUSH D ; 0689 CD1A04 CALL SETTRD ; SET TO TRANSIENT DRIVE. 068C D1 POP D ; 068D 214607 LXI H,COM ; MOVE FILE TYPE "COM" INTO FCB. 0690 CD0604 CALL MOVE3 ; 0693 CDBD00 CALL F1OPEN ; OPEN FILE FOR READING. 0696 C2A706 JNZ PAT2 ; NORMAL PATH 0699 21B307 LXI H,TRDISK ; GET DRIVE FROM CURRENT COMMAND 069C B6 ORA M ; ACCUM WAS 0 ON ENTRY, SO THIS FETCHES DRIVE 069D C26B05 JNZ TYPE4 ; COMMAND HAS EXPLICIT DRIVE...GIVE ERROR 06A0 34 INR M ; FORCE EXPLICITE REFERENCE TO DRIVE A 06A1 119907 LXI D,FCB+9 ; WE NEED TO SET UP DE WHEN WE 06A4 C38806 JMP PATCH1 ; RE-ENTER CCP ; 06A7 210001 PAT2: LXI H,TPA ; STARTING POINT FOR PROGRAM LOADING. ; 06AA E5 TRANS2: PUSH H ; MOVE PROGRAM INTO TPA SECTOR BY SECTOR. 06AB EB XCHG ; 06AC CDC301 CALL STDMA1 ; POINT TO LOADING LOCATION. 06AF 119007 LXI D,FCB ; 06B2 CDE800 CALL READF ; READ 1 SECTOR INTO MEMORY. 06B5 C2CA06 JNZ TRANS3 ; ZFLAG RESET ::= GOOD READ, GO AROUND FOR MORE. 06B8 E1 POP H ; 06B9 118000 LXI D,LENSEC ; 06BC 19 DAD D ; ADVANCE POINTER FOR NEXT SECTOR. 06BD 110000 LXI D,ORIGIN ; CHECK FOR PROGRAM OVERLAPPING CCP AREA. 06C0 7D MOV A,L ; 06C1 93 SUB E ; 06C2 7C MOV A,H ; 06C3 9A SBB D ; 06C4 D23407 JNC LDERR ; ERROR CONDITION, PROGRAM TOO BIG FOR MEMORY. 06C7 C3AA06 JMP TRANS2 ; BACK FOR NEXT SECTOR. CP/M RMAC ASSEM 1.1 #031 BODY OF CPM (CCP/BDOS) 17 DEC 84 ; 06CA E1 TRANS3: POP H ; CLEAR STACK. 06CB 3D DCR A ; 1 ::= END OF FILE (GOOD) OR 2 ::= READ ERROR (BAD). 06CC C23407 JNZ LDERR ; READ ERROR. 06CF CD2C04 CALL SETCUR ; SET BACK TO CURRENT DRIVE. 06D2 CD3402 CALL TRFCB ; MOVE ANY FURTHER FCB'S AT 005CH AND 006CH. 06D5 21B307 LXI H,TRDISK ; 06D8 E5 PUSH H ; 06D9 7E MOV A,M ;Put transient disk number into 06DA 329007 STA FCB ; first byte of file control block. 06DD 3E10 MVI A,16 ;Set offset for TRFCB to upper half of FCB 06DF CD3602 CALL TRFCB1 ;Move seconf file name into FCB + 16 06E2 E1 POP H ; 06E3 7E MOV A,M ;Get transient disk number of second FN 06E4 32A007 STA FCB+16 ; and insert it into FCB + 16 06E7 AF XRA A ;Zero out sector counter 06E8 32B007 STA FCB+32 ; 06EB 115C00 LXI D,DFCB ;Move filenames to default FCB 06EE 219007 LXI H,FCB ; 06F1 0621 MVI B,33 ;File control block & sector counter 06F3 CD0804 CALL MOVBLK ; ; 06F6 210800 LXI H,BUFFER ;Start at the head of buffer 06F9 7E TRANS4: MOV A,M ;Step until blank or null found 06FA B7 ORA A ; i.e. step over transient name 06FB CA0707 JZ TRANS5 ; 06FE FE20 CPI ' ' ; 0700 CA0707 JZ TRANS5 ; 0703 23 INX H ; 0704 C3F906 JMP TRANS4 ;Loop ; 0707 0600 TRANS5: MVI B,00H ;Command line byte counter 0709 118100 LXI D,DMAD+1 ; 070C 7E TRANS6: MOV A,M ;Move command line into default buffer 070D 12 STAX D ; 070E B7 ORA A ;Exit on null 070F CA1807 JZ TRANS7 ; 0712 04 INR B ;Bump counter 0713 23 INX H ; 0714 13 INX D ; 0715 C30C07 JMP TRANS6 ; ; 0718 78 TRANS7: MOV A,B ;Put buffer counter at start 0719 328000 STA DMAD ; of default buffer 071C CD9100 CALL CRLFP ; 071F CDC001 CALL SETDMA ;Set DMA to default buffer 0722 CD0501 CALL SETLOG ; SET LOG-IN BYTE W/ CURRENT DRIVE & USER NUMBER 0725 CD0001 CALL TPA ; GO OUT AND RUN THE PROGRAM. 0728 316E07 LXI SP,STACK ; RESTORE STACK ON RETURN. 072B CD1401 CALL LOGCUR ;Log back to the current disk 072E CDB700 CALL SELDSK ; 0731 C35203 JMP NXTCMD ; READY FOR ANOTHER ASSIGNMENT. ; ; LOAD ERROR ; 0734 013D07 LDERR: LXI B,MSG7 ;Load the error pointer CP/M RMAC ASSEM 1.1 #032 BODY OF CPM (CCP/BDOS) 17 DEC 84 0737 CDA100 CALL CRMSG ;Display the message 073A C34907 JMP COMEND ;EXIT ; 073D 424144204CMSG7: DB 'BAD LOAD',0 ; 0746 434F4D COM: DB 'COM' ; FILE TYPE FOR TRANSIENT COMMANDS. PAGE CP/M RMAC ASSEM 1.1 #033 BODY OF CPM (CCP/BDOS) 17 DEC 84 ; ; COMMAND END ; CLEAN-UP AND EXIT POINT FOR ALL COMMANDS ; EXCEPT TRANSIENT COMMANDS. ; 0749 CD2C04 COMEND: CALL SETCUR ;PRIMARY EXIT POINT 074C CD3402 CMEND1: CALL TRFCB ;SECONDARY EXIT POINT 074F 3A9107 LDA FCB+1 ; CHECK FOR FURTHER COMMANDS. 0752 D620 SUI ' ' ; 0754 21B307 LXI H,TRDISK ; 0757 B6 ORA M ; 0758 C2E001 JNZ WHAT ; 075B C35203 JMP NXTCMD ; BACK TO THE RATRACE. ; ; END OF THE PROGRAM AREA ; PAGE CP/M RMAC ASSEM 1.1 #034 BODY OF CPM (CCP/BDOS) 17 DEC 84 ; ; START OF PARAMETER STORAGE AREA ; 075E DS 16 ;STACK AREA 076E = STACK: EQU $ ;CCP STACK ; 076E SUBFL: DS 1 ; SUBMIT FLAG. FLAG SET WHEN COMMANDS COME FROM $$$.SUB FILE. 076F 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 0790 FCB: DS 33 ;FILE CONTROL BLOCK FOR CCP READ/WRITE 07B1 RETVAL: DS 1 ; VALUE RETURNED IN (A) FROM CALLS TO BDOS. 07B2 CRNDSK: DS 1 ; CURRENT LOGGED IN DISK. 07B3 TRDISK: DS 1 ; CURRENT TRANSIENT DISK. 07B4 TYPCTR: DS 1 ; INPUT BUFFER COUNTER USED BY 'TYPE' TO KEEP TRACK ; OF INPUT DISK BUFFER. 07B5 PADOUT: DS 75 ;PAD OUT THE CCP TO THE PAGE BOUNDERY ; ; ; ****************************************** ; ; RELOCATABLE ASSEMBLY OF MYBDOS ; ; ****************************************** ; LAST REVISION: 03 JULY 84 ; ****************************************** ; ; ; The points still being puzzled out are: ; ; 1. The use of the null block mask for non 8" s.d. ; disk systems. ; ; 2. The use of the upper 3 bits of FILE CONTROL ; BLOCK Byte 12 (extent byte). This is tied in with ; the null block mask mentioned in #1 above. ; ; 3. The full use of the 3- 16 bit parameters in each ; disk parameter block. The vectors to these 3 items are ; DWORD1, DWORD2 & DWORD3. These are set to 0000H when ; BIOS is first loaded. ((DWORD1)) is set to 0003H by ; LOGIN, and ((DWORD2)) & ((DWORD3)) are set to 0000H by ; SETDIR which in in turn is called by LOGIN and SERCHF. ; No explanation for these parameters is given in the ; Digital Research documentation. ; ; 4. The setting and resetting of the MSB of FCB byte ; 14. The bit is set when the file is opened, and when ; each extent is opened. It is reset when a sector is ; is written, or when the random read/write parameters ; are set up. This may be some sort of flag to prevent ; trying to read a write file. More digging into this ; is required. ; ; 5. The reason for FCB Byte 13 being skipped during ; a directory file name search. The Digital Reasearch ; documentation merely says that the byte is for int- CP/M RMAC ASSEM 1.1 #035 BODY OF CPM (CCP/BDOS) 17 DEC 84 ; ernal use only, and that it is always set to 00H. ; Does the skipping of this byte mean that it is used ; for some purpose in MP/M, or is this something reser- ; ved for future use in a subsequent release? ; ; ;Note that if files of the same name are present on both USER 0 and ;the logged-in USER number, the OPEN, SEARCH for FIRST, SEARCH for NEXT ;and READ SEQUENTIAL functions will match directory entries on a first-come ;first-served basis. This will cause exciting results if multiple extent ;files of the same name are present on both USER 0 and logged-in USER. ; ;Recommended use: ; ; 1) Keep on USER 0 only commonly used programs (Files.COM) ; 2) Set these programs to $SYS to reduce directory clutter. ; 3) Set these programs to $R/O to avoid accidental erasure of ; invisible programs. ; 4) NEVER place on any other USER number programs of the same name. ; 5) Have turn-key applications cold-boot directly into the assigned ; USER number. The USER number is the high nibble of address 4. ; ; EQUATES ; 0000 = REBOOT: EQU 0000H ;REBOOT CP/M VIA VECTOR @ 0000H 0003 = IOBYTE: EQU 0003H ;I/O ALLOCATION BYTE 0080 = DDMA: EQU 0080H ;DEFAULT DMA ADDRESS 0080 = SECLEN: EQU 0080H ;STANDARD CP/M SECTOR LENGTH= 128 ; 000D = CR: EQU 0DH ;CARRIAGE RETURN 000A = LF: EQU 0AH ;LINE FEED 0009 = TAB: EQU 09H ;TAB 0008 = BCKSPA: EQU 08H ;BACKSPACE 007F = RUBOUT: EQU 7FH ;DELETE ; 0002 = VER: EQU 2 ;CP/M VERSION 0002 = REL: EQU 2 ;CP/M RELEASE 0000 = REV: EQU 0 ;REVISION 0000 = SNH: EQU 00 ;SERIAL NUMBER, HIGH. 2 DIGITS 0000 = SNL: EQU 0000 ;SERIAL NUMBER, LOW. 4 DIGITS ; ; PUBLIC @BDOS ; EXTRN @CBOOT,@WBOOT,@CONST,@CONIN,@CONOUT EXTRN @LIST,@PUNCH,@READER,@LISTST EXTRN @HOME,@SELDSK,@SETTRK,@SETSEC,@SETDMA EXTRN @READ,@WRITE,@SECTRN ; FBASE: 0800 00 SERNO: DB SNH ;HIGH DIGITS OF SERIAL NUMBER 0801 16 DB VER*10+REL ; 0802 0000 DW REV ; 0804 0000 DB SNL/256,SNL MOD 256 ; ; ; NOTE: CP/M RMAC ASSEM 1.1 #036 BODY OF CPM (CCP/BDOS) 17 DEC 84 ; The user must insert the proper serial numbers ; into BDOS since these numbers are checked by ; MOVECPM when creating a new system. ; Failure to have matching serial numbers will ; cause an error condition. ; ; MAIN BDOS ENTRY POINT. ; ALL CALL ARE ROUTED THROUGH HERE BY ; VECTOR LOCATED AT 0005H ; @BDOS: ;BDOS: JMP BDOS1 ;JUMP OVER ERROR VECTORS TO START ; ; ERROR HANDLER VECTORS ; 0806 9608 ERR1: DW BSERR ; 0808 A208 ERR2: DW SELER1 ; 080A A808 ERR3: DW ROERR ; 080C AE08 ERR4: DW ROERR1 ; ; ; STARTING POINT OF BASIC DISK OPERATING SYSTEM ; 080E EB BDOS1: XCHG ; 080F 22440B SHLD ENTPAR ;SAVE ENTRY PARAMETER FROM (DE) 0812 EB XCHG ; 0813 7B MOV A,E ; 0814 32D415 STA PARAM1 ;ALSO SAVE CONTENTS OF (E) 0817 210000 LXI H,0000 ; 081A 22460B SHLD RETPAR ;ZERO OUT RETURN PARAMETER 081D 39 DAD SP ; 081E 22100B SHLD PSTACK ;SAVE CALLING PROGRAM STACK POINTER 0821 31420B LXI SP,BSTACK ;SET UP BDOS STACK 0824 AF XRA A ; 0825 32DE15 STA DISKNO ;ZERO OUT DISK NUMBER 0828 32DC15 STA SETUPF ; & DISK SETUP FLAG 082B 217215 LXI H,BDOS2 ;PUT EXIT POINT ADDRESS UP FOR 082E E5 PUSH H ; USE WHEN COMMAND IS COMPLETED 082F 79 MOV A,C ;MOVE COMMAND NUMBER INTO (A) 0830 FE29 CPI 29H ;CHECK FOR VALID COMMAND NUMBER 0832 D0 RNC ;NO GOOD- THERE ARE ONLY 40 COMMANDS 0833 4B MOV C,E ; 0834 214408 LXI H,COMTAB ;POINT TO START OF COMMAND TABLE 0837 5F MOV E,A ; 0838 1600 MVI D,00H ; 083A 19 DAD D ; 083B 19 DAD D ;POINT TO COMMAND VECTOR 083C 5E MOV E,M ; 083D 23 INX H ; 083E 56 MOV D,M ;MOVE COMMAND VECTOR INTO (DE) 083F 2A440B LHLD ENTPAR ;GET BACK ORIGINAL ENTRY CONTENTS OF (DE) 0842 EB XCHG ;SWAP 'EM 0843 E9 PCHL ;THEN GO OFF TO DO THE COMMAND ; ; BDOS COMMAND VECTOR TABLE ; ; Contains vectors for 40 commands, including two CP/M RMAC ASSEM 1.1 #037 BODY OF CPM (CCP/BDOS) 17 DEC 84 ; reserved spaces for future commands, and two ; undocumented commands. Commands marked '*' are ; different from the similarly numbered commands ; in CP/M 1.4 ; 0844 0000 COMTAB: DW @WBOOT ; BIOS CALL/WARM BOOT 0846 BB0A DW COM01 ; CONSOLE INPUT 0848 9109 DW COM02 ; CONSOLE OUTPUT 084A C10A DW COM03 ; TAPE READER INPUT 084C 0000 DW @PUNCH ; BIOS CALL/PUNCH DEVICE OUTPUT 084E 0000 DW @LIST ; BIOS CALL/LIST DEVICE OUTPUT 0850 C70A DW COM06 ;* DIRECT CONSOLE I/O 0852 E00A DW COM07 ; GET I/O BYTE 0854 E60A DW COM08 ; SET I/O BYTE 0856 EB0A DW COM09 ; PRINT STRING 0858 D409 DW COM10 ;* READ CONSOLE BUFFER 085A FF0A DW COM11 ; GET CONSOLE STATUS 085C 7C14 DW COM12 ;* RETURN VERSION NUMBER 085E 8114 DW COM13 ; RESET DISK SYSTEM 0860 CD13 DW COM14 ; SELECT DISK DRIVE 0862 9A14 DW COM15 ;* OPEN FILE 0864 A314 DW COM16 ; CLOSE FILE 0866 A914 DW COM17 ;* SEARCH FOR FIRST OCCURENCE 0868 C614 DW COM18 ; SEARCH FOR NEXT OCCURENCE 086A D514 DW COM19 ;* DELETE FILE 086C DE14 DW COM20 ; READ SEQUENTIAL FILE 086E E414 DW COM21 ; WRITE SEQUENTIAL FILE 0870 EA14 DW COM22 ;* MAKE FILE 0872 F314 DW COM23 ;* RENAME FILE 0874 FC14 DW COM24 ; RETURN LOG-IN VECTOR 0876 0215 DW COM25 ; RETURN CURRENT DISK NUMBER 0878 0815 DW COM26 ; GET DMA ADDRESS 087A 0F15 DW COM27 ; INTEROGATE DISK ALLOCATION 087C 2D0D DW COM28 ;* WRITE PROTECT DISK 087E 1515 DW COM29 ;* GET R/O VECTOR ADDRESS 0880 1B15 DW COM30 ;* SET FILE ATTRIBUTES 0882 2415 DW COM31 ;* GET DISK PARAMETER ADDRESS 0884 2B15 DW COM32 ;* SET USER/GET USER NUMBER 0886 3F15 DW COM33 ;* READ RANDOM FILE 0888 4515 DW COM34 ;* WRITE RANDOM FILE 088A 4B15 DW COM35 ;* COMPUTE FILE SIZE 088C BA13 DW COM36 ;* SET RAMDOM RECORD LENGTH 088E 5115 DW COM37 ;** UNDOCUMENTED COMMAND 0890 050B DW DUMMY ;** RESERVED FOR FUTURE USE 0892 050B DW DUMMY ;** RESERVED FOR FUTURE USE 0894 9915 DW COM40 ;** UNDOCUMENTED COMMAND ; ; BDOS ERROR HANDLING ROUTINES ; 0896 21CB08 BSERR: LXI H,ERMSG2 ; 0899 CDE608 CALL ERRMSG ; 089C FE03 CPI 03H ;CHECK FOR A CONTROL C 089E CA0000 JZ REBOOT ; 08A1 C9 RET ; ; 08A2 21D608 SELER1: LXI H,ERMSG3 ; CP/M RMAC ASSEM 1.1 #038 BODY OF CPM (CCP/BDOS) 17 DEC 84 08A5 C3B108 JMP ROERR2 ; ; 08A8 21E208 ROERR: LXI H,ERMSG5 ; 08AB C3B108 JMP ROERR2 ; ; 08AE 21DD08 ROERR1: LXI H,ERMSG4 ; 08B1 CDE608 ROERR2: CALL ERRMSG ; 08B4 AF XRA A ; CLEAR A TO POINT TO DISK 'A' 08B5 32DE15 STA DISKNO ; STORE IN DISK LOCATION 08B8 C30000 JMP REBOOT ; ; ; ERROR MESSAGE STRINGS ; 08BB 42646F7320ERMSG0: DB 'Bdos Err On : $' 08C7 = ERMSG1: EQU ERMSG0+12 ; ; 08CB 4261642053ERMSG2: DB 'Bad Sector$' ; ; 08D6 53656C6563ERMSG3: DB 'Select$' ; ; 08DD 46696C6520ERMSG4: DB 'File R/O$' ; 08E2 = ERMSG5: EQU ERMSG4+5 ; ; ; PRINT OUT THE ERROR MESSAGE ; 08E6 E5 ERRMSG: PUSH H ;SAVE THE POINTER 08E7 CDCA09 CALL PCRLF ;START A NEW LINE 08EA 3A430B LDA CURDSK ;GET THE CURRENT DISK NUMBER 08ED C641 ADI 'A' ;ADD THE ASCII BIAS+1 08EF 32C708 STA ERMSG1 ;POKE INTO ERROR MESSAGE 08F2 01BB08 LXI B,ERMSG0 ;POINT TO ERROR MESSAGE 08F5 CDEE0A CALL PRNSTR ;PRINT ERROR MESSAGE STRING 08F8 C1 POP B ;GET BACK ORIGINAL POINTER 08F9 CDEE0A CALL PRNSTR ; AND PRINT THAT STRING TOO. ; ; CONSOLE KEYBOARD INPUT ; 08FC 210F0B INPUT: LXI H,KYBDFL;SWAP THE CONTENTS OF THE KEYBOARD FLAG BYTE 08FF 7E MOV A,M ;WITH A 00 0900 3600 MVI M,00H ; 0902 B7 ORA A ; 0903 C0 RNZ ;RETURN IF SOMETHING ALREADY THERE 0904 C30000 JMP @CONIN ;ELSE GET SOMETHING VIA A BIOS CALL TO CONSOLE INPUT ; 0907 CDFC08 INCHR: CALL INPUT ;GET A CHARACTER FROM KEYBOARD 090A CD1509 CALL SETFLG ;CHECK TO SEE IF IS A COTROL CHARACTER 090D D8 RC ;RETURN IF IT IS 090E F5 PUSH PSW ;ELSE ECHO IT TO THE CONSOLE 090F 4F MOV C,A ; (AND PERHAPS THE LIST DEVICE) 0910 CD9109 CALL COM02 ;CONSOLE OUTPUT 0913 F1 POP PSW ; 0914 C9 RET ; ; ; SET THE CARRY FLAG IF A CONTROL CHARACTER OTHER THAN ; CR, LF, TAB OR BACKSPACE IS ENCOUNTERED ; CP/M RMAC ASSEM 1.1 #039 BODY OF CPM (CCP/BDOS) 17 DEC 84 0915 FE0D SETFLG: CPI CR ; 0917 C8 RZ ; 0918 FE0A CPI LF ; 091A C8 RZ ; 091B FE09 CPI TAB ; 091D C8 RZ ; 091E FE08 CPI BCKSPA ; 0920 C8 RZ ; 0921 FE20 CPI ' ' ; 0923 C9 RET ; ; ; CHECK TO KEYBOARD STATUS TO SEE IF THERE IS ; SOMETHING TO REPORT ; 0924 3A0F0B KBSTAT: LDA KYBDFL ;CHECK THE FLAG 0927 B7 ORA A ; 0928 C24609 JNZ KBSTA2 ;SOMETHING ALREADY ON HAND ; 092B CD0000 CALL @CONST ;BIOS CALL/CONSOLE STATUS 092E E601 ANI 01H ;CHECK LSB ONLY 0930 C8 RZ ;NOTHING, SO JUST RETURN ; 0931 CD0000 CALL @CONIN ;BIOS CALL/CONSOLE INPUT 0934 FE20 CPI ' ' ;CHECK FOR A SPACE 0936 C24309 JNZ KBSTA1 ;EXIT ON SPACE 0939 CD0000 CALL @CONIN ;BIOS CALL/CONSOLE INPUT 093C FE03 CPI 03H ;CHECK AGAIN FOR A CONTROL C 093E CA0000 JZ REBOOT ;REBOOT IF THE IS ^C 0941 AF XRA A ; ELSE CLEAR THE EVIDENCE 0942 C9 RET ; AND EXIT ; 0943 320F0B KBSTA1: STA KYBDFL ;MARK THE FLAG 'IN USE' 0946 3E01 KBSTA2: MVI A,01H ; SET RETURN BYTE 0948 C9 RET ; ; ; OUTPUT ONE CHARACTER TO THE CONSOLE OUTPUT DEVICE ; (AND TO THE LIST DEVICE IF THE ^P FLAG IS SET) ; ; CHARACTER TO BE OUTPUT IS RECEIVED IN (C) ; 0949 3A0B0B OUTPUT: LDA CHCTR1 ; 094C B7 ORA A ; 094D C26309 JNZ OUTPT1 ; 0950 C5 PUSH B ; 0951 CD2409 CALL KBSTAT ; 0954 C1 POP B ; 0955 C5 PUSH B ; 0956 CD0000 CALL @CONOUT ;BIOS CALL/CONSOLE OUTPUT 0959 C1 POP B ; 095A C5 PUSH B ; 095B 3A0E0B LDA LISTFL ;CHECK TO SEE IF LIST DEVICE IS SET 095E B7 ORA A ; 095F C40000 CNZ @LIST ; IT IS SO DO A BIOS CALL TO LIST DEVICE OUTPUT 0962 C1 POP B ; 0963 79 OUTPT1: MOV A,C ; 0964 210D0B LXI H,CHRCTR ; CP/M RMAC ASSEM 1.1 #040 BODY OF CPM (CCP/BDOS) 17 DEC 84 0967 FE7F CPI RUBOUT ;DON'T COUNT RUBOUTS 0969 C8 RZ ; 096A 34 INR M ;BUMP CHARACTER COUNTER 096B FE20 CPI ' ' ; 096D D0 RNC ;OK- IT WAS A PRINTABLE CHARACTER 096E 35 DCR M ;UNDO WHAT YOU JUST DID 096F 7E MOV A,M ;** SUPERFLOUS CODE! 0970 B7 ORA A ;** SET FLAG LIKE IT WAS SET BY DCR M 0971 C8 RZ ; 0972 79 MOV A,C ; 0973 FE08 CPI BCKSPA ;CHECK FOR A BACKSPACE 0975 C27A09 JNZ OUTPT2 ; 0978 35 DCR M ;DECREASE COUNTER IF BACKSPACE 0979 C9 RET ; ; 097A FE0A OUTPT2: CPI LF ;ZERO OUT CHARACTER COUNTER IF 097C C0 RNZ ;A LINE FEED IS FOUND, ELSE JUST 097D 3600 MVI M,00H ;RETURN TO CALLER 097F C9 RET ; ; ; CHARACTER OUTPUT ; ; CHARACTER TO BE PRINTED RECEIVED IN (C) ; ; PRINTS CONTROL CHARACTERS AS ^[LETTER] ; EXPANDS TABS TO 8 BYTE BOUNDARIES ; 0980 79 OUTCHR: MOV A,C ; 0981 CD1509 CALL SETFLG ; 0984 D29109 JNC COM02 ; NOT A CONTROL CHAR SO JUST DO CONSOLE OUTPUT 0987 F5 PUSH PSW ;STASH THE CHARACTER 0988 0E5E MVI C,'^' ;PRINT AN UP-ARROW 098A CD4909 CALL OUTPUT ; 098D F1 POP PSW ;GET CHARACTER BACK 098E F640 ORI 40H ;REPLACE ASCII BIAS 0990 4F MOV C,A ; 0991 79 COM02: MOV A,C ;CONSOLE OUTPUT 0992 FE09 CPI TAB ; 0994 C24909 JNZ OUTPUT ;NOT A TAB, JUST OUTPUT 0997 0E20 OUTCH2: MVI C,' ' ; IT WAS A TAB, SPACE TO NEXT 8 BYTE STOP. 0999 CD4909 CALL OUTPUT ; 099C 3A0D0B LDA CHRCTR ;CHECK THE COUNTER 099F E607 ANI 07H ; 09A1 C29709 JNZ OUTCH2 ;NOT AT EVEN LOCATION, DO ANOTHER 09A4 C9 RET ; ; ; BLANK OUT THE CURRENT CURSOR POSITION ; BY BACKSPACE, SPACE. ; 09A5 CDAD09 BLANK: CALL BLANK1 ; 09A8 0E20 MVI C,' ' ; 09AA CD0000 CALL @CONOUT ;BIOS CALL/CONSOLE OUTPUT 09AD 0E08 BLANK1: MVI C,BCKSPA ; 09AF C30000 JMP @CONOUT ;BIOS CALL/CONSOLE OUTPUT ; ; BREAK OUT OF THE CURRENT DISPLAY LINE AND CP/M RMAC ASSEM 1.1 #041 BODY OF CPM (CCP/BDOS) 17 DEC 84 ; START A NEW LINE. USED BY ^U (ABORT LINE), ; AND ^R (RETYPE LINE) IN CONSOLE BUFFER INPUT. ; 09B2 0E23 BREAK: MVI C,'#' ;MARK THE EXIT POINT 09B4 CD4909 CALL OUTPUT ; 09B7 CDCA09 CALL PCRLF ;START A NEW LINE 09BA 3A0D0B BREAK1: LDA CHRCTR ;OUTPUT BLANKS UNTIL COUNTERS MATCH 09BD 210C0B LXI H,CHCTR2 ; 09C0 BE CMP M ; 09C1 D0 RNC ; 09C2 0E20 MVI C,' ' ; 09C4 CD4909 CALL OUTPUT ; 09C7 C3BA09 JMP BREAK1 ; ; ; STANDARD CARRIAGE RETURN/LINE FEED SUBROUTINE ; 09CA 0E0D PCRLF: MVI C,CR ; 09CC CD4909 CALL OUTPUT ; 09CF 0E0A MVI C,LF ; 09D1 C34909 JMP OUTPUT ; ; ; BDOS COMMAND #10....READ THE CONSOLE BUFFER ; ON ENTRY (DE) POINTS TO START OF THE BUFFER ; FIRST BYTE OF BUFFER CONTAINS THE MAXIMUM ; ALLOWABLE LINE LENGTH. SECOND BYTE WILL ; CONTAIN CURRENT BUFFER LENGTH ON RETURN. ; 09D4 3A0D0B COM10: LDA CHRCTR ; 09D7 320C0B STA CHCTR2 ; 09DA 2A440B LHLD ENTPAR ;WHY? YOU ALREADY HAVE THIS IN (DE)! 09DD 4E MOV C,M ;PUT MAXIMUM COUNT IN (C) 09DE 23 INX H ; 09DF E5 PUSH H ;SAVE START+1 09E0 0600 MVI B,00H ;ZERO THE CURRENT CHARACTER COUNTER ; ; TOP OF INPUT LINE LOOP ; 09E2 C5 LLOOP: PUSH B ; 09E3 E5 PUSH H ; 09E4 CDFC08 LINE1: CALL INPUT ;GET A CHAR FROM KEYBOARD 09E7 E67F ANI 7FH ;STRIP OFF MSB 09E9 E1 POP H ; 09EA C1 POP B ; 09EB FE0D CPI CR ; 09ED CAB40A JZ LINE16 ;EXIT ON OR 09F0 FE0A CPI LF ; 09F2 CAB40A JZ LINE16 ; 09F5 FE08 CPI BCKSPA ; 09F7 C2090A JNZ LINE2 ; 09FA 78 MOV A,B ; 09FB B7 ORA A ; 09FC CAE209 JZ LLOOP ;DO NOTHING IF AT START OF LINE 09FF 05 DCR B ; 0A00 3A0D0B LDA CHRCTR ; 0A03 320B0B STA CHCTR1 ; 0A06 C3630A JMP LINE9 ; CP/M RMAC ASSEM 1.1 #042 BODY OF CPM (CCP/BDOS) 17 DEC 84 ; 0A09 FE7F LINE2: CPI RUBOUT ;RUBOUT? 0A0B C2190A JNZ LINE3 ; 0A0E 78 MOV A,B ; 0A0F B7 ORA A ; 0A10 CAE209 JZ LLOOP ;DO NOTHING IF AT START OF A LINE 0A13 7E MOV A,M ; 0A14 05 DCR B ; 0A15 2B DCX H ; 0A16 C39C0A JMP LINE14 ; ; ; CONTROL E....OUTPUT A CR/LF TO THE CONSOLE, BUT ; DON'T INSERT IT INTO THE LINE ; 0A19 FE05 LINE3: CPI 05H ;^E 0A1B C22A0A JNZ LINE4 ; 0A1E C5 PUSH B ; 0A1F E5 PUSH H ; 0A20 CDCA09 CALL PCRLF ; 0A23 AF XRA A ; 0A24 320C0B STA CHCTR2 ; 0A27 C3E409 JMP LINE1 ; ; ; CONTROL P....SET THE LIST DEVICE FLAG SO THAT ; ALL CONSOLE OUTPUT IS ALSO SENT TO ; THE LIST DEVICE. ; 0A2A FE10 LINE4: CPI 10H ;^P 0A2C C23B0A JNZ LINE5 ; 0A2F E5 PUSH H ; 0A30 210E0B LXI H,LISTFL ; 0A33 3E01 MVI A,01H ; 0A35 AE XRA M ; 0A36 77 MOV M,A ; 0A37 E1 POP H ; 0A38 C3E209 JMP LLOOP ; ; ; CONTROL X....BACKSPACE OVER THE CONSOLE LINE ; AND RESTART THE LINE INPUT. THIS SOUNDS LIKE ; A NICE IDEA, BUT THINGS GET SCREWED UP BY ; BACKSPACING THEN RETYPING AT TAB LOCATIONS, ; AND BY CONTROL CHARACTERS BEING DISPLAYED AS ; TWO CHARACTERS, BUT STORED IN MEMORY AS ONLY ; ONE CHARACTER. IN SHORT, EXPECT TO SEE A MESS ; EVERY SO OFTEN. CONTROL U IS REALLY BETTER. ; 0A3B FE18 LINE5: CPI 18H ;^X 0A3D C2520A JNZ LINE7 ; 0A40 E1 POP H ; 0A41 3A0C0B LINE6: LDA CHCTR2 ;WIPE OUT CHARACTERS UNTIL THE COUNTERS MATCH 0A44 210D0B LXI H,CHRCTR ; 0A47 BE CMP M ; 0A48 D2D409 JNC COM10 ;THEY MATCH, SO RESTART CONSOLE INPUT 0A4B 35 DCR M ; 0A4C CDA509 CALL BLANK ;DESTRUCTIVE BACKSPACE 0A4F C3410A JMP LINE6 ; CP/M RMAC ASSEM 1.1 #043 BODY OF CPM (CCP/BDOS) 17 DEC 84 ; ; CONTROL U....ABORT OUT OF CURRENT INPUT LINE ; AND START OVER AGAIN. ; 0A52 FE15 LINE7: CPI 15H ;^U 0A54 C25E0A JNZ LINE8 ; 0A57 CDB209 CALL BREAK ;ECHO A '#' AND A CR/LF 0A5A E1 POP H ;GET BACK POINTER TO START OF BUFFER 0A5B C3D409 JMP COM10 ; AND START ALL OVER AGAIN. ; ; CONTROL R....DROP DOWN TO NEW LINE AND RETYPE ; THE CONTENTS OF THE CONSOLE BUFFER. USEFULL ; TO CLEAN UP MESS MADE WHEN BACKSPACING HAS ; SCREWED UP THE TAB COUNT OR CONTROL CHARACTER DISPLAY ; 0A5E FE12 LINE8: CPI 12H ;^R 0A60 C2990A JNZ LINE13 ; 0A63 C5 LINE9: PUSH B ;SAVE THE CHARACTER COUNT 0A64 CDB209 CALL BREAK ;OUTPUT A '#' AND CR/LF 0A67 C1 POP B ; 0A68 E1 POP H ;GET BACK POINTER TO START OF LINE 0A69 E5 PUSH H ; AND RESAVE IT. 0A6A C5 PUSH B ;RESAVE CHARACTER COUNT ; ; RETYPE UNTIL COUNT IN (B) IS 0 ; 0A6B 78 LINE10: MOV A,B ; 0A6C B7 ORA A ; 0A6D CA7D0A JZ LINE11 ; 0A70 23 INX H ; 0A71 4E MOV C,M ; 0A72 05 DCR B ; 0A73 C5 PUSH B ; 0A74 E5 PUSH H ; 0A75 CD8009 CALL OUTCHR ; 0A78 E1 POP H ; 0A79 C1 POP B ; 0A7A C36B0A JMP LINE10 ; ; 0A7D E5 LINE11: PUSH H ; 0A7E 3A0B0B LDA CHCTR1 ; 0A81 B7 ORA A ; 0A82 CAE409 JZ LINE1 ; 0A85 210D0B LXI H,CHRCTR ; 0A88 96 SUB M ; 0A89 320B0B STA CHCTR1 ; 0A8C CDA509 LINE12: CALL BLANK ; 0A8F 210B0B LXI H,CHCTR1 ; 0A92 35 DCR M ; 0A93 C28C0A JNZ LINE12 ; 0A96 C3E409 JMP LINE1 ; ; 0A99 23 LINE13: INX H ; 0A9A 77 MOV M,A ;STORE CHARACTER IN INPUT BUFFER 0A9B 04 INR B ;INCREMENT CURRENT COUNTER 0A9C C5 LINE14: PUSH B ; CP/M RMAC ASSEM 1.1 #044 BODY OF CPM (CCP/BDOS) 17 DEC 84 0A9D E5 PUSH H ; 0A9E 4F MOV C,A ;ECHO CHARACTER TO CONSOLE OUTPUT 0A9F CD8009 CALL OUTCHR ; 0AA2 E1 POP H ; 0AA3 C1 POP B ; 0AA4 7E MOV A,M ;CHECK TO SEE IF A CONTROL C HAS 0AA5 FE03 CPI 03H ; BEEN SNUCK IN ON US. 0AA7 78 MOV A,B ; 0AA8 C2B00A JNZ LINE15 ;NOPE- CONTINUE ON OUR WAY 0AAB FE01 CPI 01H ;YEP- DO A REBOOT ONLY IF AT THE 0AAD CA0000 JZ REBOOT ; HEAD OF A LINE. 0AB0 B9 LINE15: CMP C ;CHECK THE CURRENT LINE COUNT AGAINST MAXIMUM. 0AB1 DAE209 JC LLOOP ;OK- THERE'S STILL ROOM, BACK FOR MORE ; ; EXIT POINT....WE GET HERE BY A , A OR ; IF THE LINE IS AT THE MAXIMUM. ; 0AB4 E1 LINE16: POP H ;RESTORE POINTER TO HEAD OF LINE 0AB5 70 MOV M,B ;STASH THE LINE COUNT IN IT 0AB6 0E0D MVI C,CR ; AND DO A CARRIAGE RETURN TO 0AB8 C34909 JMP OUTPUT ; MARK OUR DEPARTURE ; ; BDOS COMMAND #1....GET A CHARACTER FROM THE KEYBOARD ; ECHO IT TO THE CONSOLE UNLESS IT IS A ; CONTROL CHARACTER. ; 0ABB CD0709 COM01: CALL INCHR ;CONSOLE INPUT 0ABE C3020B JMP EXIT1 ; ; ; BDOS COMMAND #3....READ ONE CHARACTER FROM THE ; PAPER TAKE READER ATTACHED TO YOUR ; ASR-33 TELETYPE. (YOU OWN ONE OF THOSE ; BEASTS, AND USE IT AS YOUR PRIMARY CONSOLE ; DEVICE DON'T YOU?) ; 0AC1 CD0000 COM03: CALL @READER ;INPUTBIOS CALL/TAPE READER INPUT 0AC4 C3020B JMP EXIT1 ; ; ; BDOS COMMAND #6....DIRECT CONSOLE I/O ; ; PARAMETER PASSED IN (C) ; IF (C)= 0FFH THEN DIRECT CONSOLE INPUT IS MADE ; i.e. returns (A)=0 if console is not ready ; else (A)=ASCII input character ; IF (C)<>0FFH THEN (C) IS ASSUMED TO BE A VALID ASCII ; CHARACTER, AND IT IS OUTPUT TO THE CONSOLE. ; ; NOTE: ; The lines marked ** don't make sense to me. ; Why would an entrance parameter of 0FEH, ; which is an invalid ASCII character cause a ; console status request? ; 0AC7 79 COM06: MOV A,C ;Check the entry parameter. 0AC8 3C INR A ; 0AC9 CAD30A JZ DIRINP ;It was 0FFH, direct input. CP/M RMAC ASSEM 1.1 #045 BODY OF CPM (CCP/BDOS) 17 DEC 84 0ACC 3C INR A ; 0ACD CA0000 JZ @CONST ;**(Why this call on (C)=0FEH?) BIOS CALL/CONSOLE STATUS 0AD0 C30000 JMP @CONOUT ;BIOS CALL/CONSOLE OUTPUT ; 0AD3 CD0000 DIRINP: CALL @CONST ;BIOS CALL/CONSOLE STATUS 0AD6 B7 ORA A ; 0AD7 CA8F15 JZ BDOS3 ;Key not pressed, exit emptyhanded. 0ADA CD0000 CALL @CONIN ;Got one. BIOS CALL/CONSOLE INPUT 0ADD C3020B JMP EXIT1 ;Go stuff it into (RETPAR) and exit. ; ; BDOS COMMAND #7....GET THE I/O BYTE AND RETURN IT ; TO A PROGRAM THAT IS NOT BRIGHT ENOUGH TO ; KNOW THAT IT IS ALWAYS AT (0003H) AND COULD ; HAVE GOTTEN IT WITH A SIMPLE LDA 0003H ; INSTEAD OF GOING THROUGH BDOS. ; 0AE0 3A0300 COM07: LDA IOBYTE ;GET I/O BYTE LOCATED AT 0003H 0AE3 C3020B JMP EXIT1 ; ; ; BDOS COMMAND #8....SET I/O BYTE ; SAME COMMENTS AS FOR COM07. ; 0AE6 210300 COM08: LXI H,IOBYTE ;SET I/O BYTE LOCATED AT 0003H 0AE9 71 MOV M,C ; 0AEA C9 RET ; ; ; BDOS COMMAND #9....PRINT STRING TO THE CONSOLE ; UNTIL A '$' OR A 0 IS FOUND. ; ; COMMENT: ; The use of '$', or for that matter any printable ; character, is inconvenient. Business programs ; cannot use this command if a dollar sign is to ; be printed in the string. The proper way to ; mark the end of a literal is with a null or ; by setting MSB. ; 0AEB EB COM09: XCHG ;MOVE POINTER TO START OF STRING FROM 0AEC 4D MOV C,L ;(DE) TO (HL), AND THEN TO (BC). WHY 0AED 44 MOV B,H ;THE GRAND TOUR?? ; ; PRINT A STRING UNTIL A '$' IS FOUND ; 0AEE 0A PRNSTR: LDAX B ; 0AEF FE24 CPI '$' ;END OF STRING MARKER 0AF1 C8 RZ ; 0AF2 FE00 CPI 0H ;OR NULL AS END OF STRING MARK 0AF4 C8 RZ ; 0AF5 03 INX B ; 0AF6 C5 PUSH B ; 0AF7 4F MOV C,A ; 0AF8 CD9109 CALL COM02 ;CONSOLE OUTPUT 0AFB C1 POP B ; 0AFC C3EE0A JMP PRNSTR ; ; ; BDOS COMMAND #11....GET CONSOLE INPUT STATUS CP/M RMAC ASSEM 1.1 #046 BODY OF CPM (CCP/BDOS) 17 DEC 84 ; RETURNS 00 IF NO KEY PRESSED, ELSE 01 ; ; NOTE: ; This command is not quite compatible with ; CP/M 1.4 or 2.0 because if a ' ' is pressed ; the console then waits for another input, ; and reboots if that input is ^C. If the ; second input is not ^C, then Command 11 ; returns like nothing happened, but has ; swallowed the ' '. This does strange things ; with some older CPMUG programs like Tiny ; Basic with polled Command 11 until a key ; was pressed. If you try some of these ; programs which ran fine under 1.4, but ; do strange things under 2.2, this may be ; the place to look. ; 0AFF CD2409 COM11: CALL KBSTAT ;GET CONSOLE STATUS 0B02 32460B EXIT1: STA RETPAR ; STORE THE RETURN PARAMETER 0B05 C9 DUMMY: RET ;(USED AS EXIT POINT FOR COM38 AND ;COM39) ; ; COMMAND EXIT POINT THAT SETS RETURN PARAMETER= 01H ; 0B06 3E01 EXIT2: MVI A,01H ; 0B08 C3020B JMP EXIT1 ; ; ; PARAMETER STORAGE AREA #1 ; 0B0B 00 CHCTR1: DB 0 ;CHARACTER COUNTER #1, ;USED IN READ CONSOLE BUFFER 0B0C 00 CHCTR2: DB 0 ;CHARACTER COUNTER #2, ;USED IN READ CONSOLE BUFFER 0B0D 00 CHRCTR: DB 0 ;OUTPUT LINE CHARACTER COUNTER, ;USED TO KEEP COUNT FOR TAB CHARACTER. 0B0E 00 LISTFL: DB 0 ;LIST DEVICE FLAG. WHEN <> 00, ;OUTPUT GOES TO LIST DEVICE. 0B0F 00 KYBDFL: DB 0 ;KEYBOARD STATUS FLAG. IF <> 0 THEN ;CHARACTER IS AVAILABLE. 0B10 0000 PSTACK: DW 0000 ;CALLING PROGRAM STACK POINTER 0B12 DS 48 ;BDOS STACK AREA 0B42 = BSTACK: EQU $ ;BDOS' OWN STACK POINTER 0B42 00 USERNO: DB 0 ;CURRENT USER NUMBER STORAGE 0B43 00 CURDSK: DB 0 ;CURRENT DISK NUMBER STORAGE 0B44 0000 ENTPAR: DW 0000 ;ENTRY PARAMETER 0B46 0000 RETPAR: DW 0000 ;RETURN PARAMETER ; ; ERROR HANDLING ROUTINES ; ; NOTE: ; Again we see that convoluted nature of this ; program. Why don't the error calls from the ; program just jump to the code just following ; command table instead of this intermedeate ; step of picking up an inderect jump vector? ; CP/M RMAC ASSEM 1.1 #047 BODY OF CPM (CCP/BDOS) 17 DEC 84 0B48 210808 SELERR: LXI H,ERR2 ;DISK SELECT ERROR ; 0B4B 5E ERROR: MOV E,M ;Move (Vector) to (DE) 0B4C 23 INX H ; 0B4D 56 MOV D,M ; 0B4E EB XCHG ;Swap it to (HL) 0B4F E9 PCHL ; and do the indirect jump ; ; BLOCK MOVE SUBROUTINE ; ; ENTRY PARAMETERS: ; (HL) DESTINATION ; (DE) SOURCE ; (C) BYTE COUNT ; ; NOTE: ; Z80 users may want to eliminate this and ; use LDIR with a suitable swapping of the ; HL and DE register pairs & using (BC) ; of just (C) as the counter. ; 0B50 0C BLKMOV: INR C ; 0B51 0D BLMOV1: DCR C ; 0B52 C8 RZ ; 0B53 1A LDAX D ; 0B54 77 MOV M,A ; 0B55 13 INX D ; 0B56 23 INX H ; 0B57 C3510B JMP BLMOV1 ; ; ; SET UP DISK PARAMETERS WHEN LOGGIN IN A NEW DISK ; ; THE VARIOUS PARAMETERS FROM BIOS ARE MOVE TO ; WHERE BDOS CAN USED THEM. THE LOCATION OF THE ; DISK SIZE, DIRECTORY TRACK ETC. ARE MOVED TO ; A PARAMETER BLOCK AT THE END OF BDOS. ; ; NOTE: ; 1. If the program involves much action ; between disk drives, considerable time ; can be wasted in this swapping process. ; This may be an area where improvemnts ; can be made. ; ; 2. If the disk is not a single sided, ; double density 5 1/4" or a single density ; 8", and can thus hold more than 255K, then ; the block numbers must be double precision ; and will occupy 2 bytes. Consequently a ; single directory extent can only hold 8 ; block numbers, and therefore 8K if 1K ; blocks are used. In order to get enough ; directory space either the number of ; directory entries must be increased, or ; the block size increased to 2K. For ; more details on this read the Digital CP/M RMAC ASSEM 1.1 #048 BODY OF CPM (CCP/BDOS) 17 DEC 84 ; Research documentation (and you will ; get thoroughly confused). ; 0B5A 3A430B SETDSK: LDA CURDSK ;GET THE NUMBER OF THE DISK 0B5D 4F MOV C,A ; 0B5E CD0000 CALL @SELDSK ;BIOS CALL/SELECT DISK DRIVE 0B61 7C MOV A,H ;IF SELDSK RETURNS (HL)= 0000H 0B62 B5 ORA L ;YOU ARE TRYING TO ACCESS A 0B63 C8 RZ ;NONEXISTENT DRIVE. ERROR RETURN. ; ; LEGAL DRIVE- LET'S SET THINGS UP ; ; SELDSK RETURNS WITH POINTER TO START OF DISK ; PARAMETER BLOCK IN (HL). THE BLOCK CONTAINS ; 8 DATA WORDS: ; DW TRANS ;START OF SECTOR TRANS TABLE ; DW DWORD1 ; ; DW DWORD2 ; ; DW DWORD3 ; ; DW DIRBUF ;DIRECTORY BUFFER LOCATION ; DW DPBLK ;DISK PARAMETER BLOCK LOCATION ; DW CHKxx ;CHECK VECTOR, DRIVE xx ; DW ALLxx ;ALLOCATION BLOCK VECTOR, DRIVE xx ; 0B64 5E MOV E,M ; 0B65 23 INX H ; 0B66 56 MOV D,M ;(DE) <-- ((TRANS)) 0B67 23 INX H ; 0B68 22B115 SHLD DWORD1 ; 0B6B 23 INX H ; 0B6C 23 INX H ; 0B6D 22B315 SHLD DWORD2 ; 0B70 23 INX H ; 0B71 23 INX H ; 0B72 22B515 SHLD DWORD3 ; 0B75 23 INX H ; 0B76 23 INX H ; 0B77 EB XCHG ; 0B78 22CE15 SHLD SECTBL ; ; ; (DE) NOW POINTS TO DIRBUF IN PARAMETER TABLE. ; THE FOLLOWING ARE NOW MOVED INTO BDOS PARAMETER AREA: ; ; (DIRBUF) POINTER TO DIRECTORY BUFFER ; (DPBLK) POINTER TO DISK PARAMETER BLOCK ; (CHKxx) POINTER TO DIRECTORY CHECKSUM BLOCK ; (ALLxx) POINTER TO ALLOCATION BLOCK MAP ; 0B7B 21B715 LXI H,DIRBPT ;DIRECTORY BUFFER POINTER 0B7E 0E08 MVI C,08H ; 0B80 CD500B CALL BLKMOV ; ; ; THE DISK PARAMETER BLOCK IS NOW MOVED INTO ; BDOS'S PARAMETER AREA. THIS BLOCK IS 15 ; BYTES LONG AND CONTAINS THE FOLLOWING: ; (VALUES GIVEN ARE FOR 8" SINGLE DENSITY) CP/M RMAC ASSEM 1.1 #049 BODY OF CPM (CCP/BDOS) 17 DEC 84 ; ; DW 26 ;SECTORS PER TRACK ; DB 3 ;BLOCK SHIFT FACTOR ; DB 7 ;BLOCK MASK ; DB 0 ;NULL MASK ; DW 242 ;DISK SIZE -1 ; DW 63 ;DIRECTORY ENTRIES -1 ; DB 192 ;ALLOC 0 ; DB 0 ;ALLOC 1 ; DB 2 ;DIRECTORY TRACK OFFSET ; 0B83 2AB915 LHLD DPBLK ; 0B86 EB XCHG ; 0B87 21BF15 LXI H,SECTRS ;SECTORS PER TRACK= ;HEAD OF DP BLOCK 0B8A 0E0F MVI C,0FH ; 0B8C CD500B CALL BLKMOV ; ; ; DETERMINE IF WE ARE ON A 5 1/4" OR SINGLE DENSITY ; 8" DISK WHICH HAS A CAPACITY OF LESS THAN 256 K ; OR IF WE ARE ON A BIG DISK THAT REQUIRES A DOUBLE ; PRECISION BLOCK NUMBER. ; 0B8F 2AC415 LHLD DSKSIZ ;DISK SIZE, # OF 1K BLOCKS -1 0B92 7C MOV A,H ; 0B93 21DB15 LXI H,BIGDSK ;8" SD: 0FFH, LARGE CAP DISK: 00H 0B96 36FF MVI M,0FFH ; 0B98 B7 ORA A ; 0B99 CA9E0B JZ SETDS1 ; 0B9C 3600 MVI M,00H ; 0B9E 3EFF SETDS1: MVI A,0FFH ; 0BA0 B7 ORA A ;SET ZFLAG TO MARK NON-ERROR RETURN 0BA1 C9 RET ; ; ; HOME THE DRIVE HEAD AND ZERO OUT SOME PARAMETERS ; IN PREPARATION FOR DIRECTORY OPERATIONS. ; 0BA2 CD0000 SETDIR: CALL @HOME ;BIOS CALL/MOVE DISK HEAD TO TRACK 00 0BA5 AF XRA A ; 0BA6 2AB315 LHLD DWORD2 ; 0BA9 77 MOV M,A ; 0BAA 23 INX H ; 0BAB 77 MOV M,A ;((DWORD2)) <-- 0000H 0BAC 2AB515 LHLD DWORD3 ; 0BAF 77 MOV M,A ; 0BB0 23 INX H ; 0BB1 77 MOV M,A ;((DWORD3)) <-- 0000H 0BB2 C9 RET ; ; ; READ AND WRITE DISK SECTOR ; ; ALL CALLS TO THESE ROUTINES IN BIOS ARE ROUTED ; THROUGH THIS AREA. RETURN PARAMETER IS MONITORED ; FOR POSSIBLE ERROR CONDITION. ; ; TRACK AND SECTOR INFORMATION MUST HAVE BEEN PASSED CP/M RMAC ASSEM 1.1 #050 BODY OF CPM (CCP/BDOS) 17 DEC 84 ; TO BIOS PRIOR TO INVOKING THESE CALLS. ; 0BB3 CD0000 RDSECT: CALL @READ ;BIOS CALL/READ DISK SECTOR 0BB6 C3BC0B JMP WRSEC1 ; ; 0BB9 CD0000 WRSECT: CALL @WRITE ;BIOS CALL/WRITE DISK SECTOR 0BBC B7 WRSEC1: ORA A ; 0BBD C8 RZ ; 0BBE 210608 LXI H,ERR1 ; 0BC1 C34B0B JMP ERROR ; ; ; SET TRACK AND SECTOR ; ; THIS SUBROUTINE CONVERTS THE LOGICAL BLOCK NUMBER ; INFORMATION IN THE FILE CONTROL BLOCK AND SECTOR ; COUNTERS AND POINTERS TO THE ACTUAL PHYSICAL ; TRACK AND SECTOR INFORMATION TO BE PASSED TO ; BIOS PRIOR TO A SECTOR READ OR WRITE. ; 0BC4 2AE815 TRKSEC: LHLD BLCTR1 ; 0BC7 0E02 MVI C,02H ; 0BC9 CDEB0C CALL SHRHLC ;SHIFT (HL) RIGHT PER COUNT IN (C) 0BCC 22E315 SHLD SCNTR1 ;SECTOR COUNTER #1 0BCF 22EA15 SHLD BLCTR2 ;BLOCK COUNTER #2 ; ; SECONDARY ENTRY POINT ; 0BD2 21E315 TRSEC1: LXI H,SCNTR1 ;SECTOR COUNTER #1 0BD5 4E MOV C,M ; 0BD6 23 INX H ; 0BD7 46 MOV B,M ;(BC) <-- (SCNTR1) 0BD8 2AB515 LHLD DWORD3 ; 0BDB 5E MOV E,M ; 0BDC 23 INX H ; 0BDD 56 MOV D,M ;(DE) <-- ((DWORD3)) 0BDE 2AB315 LHLD DWORD2 ; 0BE1 7E MOV A,M ; 0BE2 23 INX H ; 0BE3 66 MOV H,M ; 0BE4 6F MOV L,A ;(HL) <-- ((DWORD2)) ; ; SUBTRACT THE NUMBER OF SECTORS/TRACK FROM SECTOR ; NUMBER UNTIL (BC) >= (DE) ; COUNT IN (HL) DECREMENTED ; 0BE5 79 TRSEC2: MOV A,C ; 0BE6 93 SUB E ; 0BE7 78 MOV A,B ; 0BE8 9A SBB D ;SET FLAG ON (BC) - (DE) 0BE9 D2FB0B JNC TRSEC3 ;(BC)>=(DE) 0BEC E5 PUSH H ;SAVE COUNT 0BED 2ABF15 LHLD SECTRS ;(HL) <-- SECTORS PER TRACK 0BF0 7B MOV A,E ; 0BF1 95 SUB L ; 0BF2 5F MOV E,A ; 0BF3 7A MOV A,D ; CP/M RMAC ASSEM 1.1 #051 BODY OF CPM (CCP/BDOS) 17 DEC 84 0BF4 9C SBB H ; 0BF5 57 MOV D,A ;(DE) <-- (DE) - (SECTRS) 0BF6 E1 POP H ;GET BACK THE COUNT 0BF7 2B DCX H ; AND DECREMENT IT 0BF8 C3E50B JMP TRSEC2 ; LOOP ; ; ADD NUMBER OF SECTORS/TRACK TO (DE) UNTIL (HL) > (BC) ; OR (DE) + (SECTRS) OVERFLOWS. ; COUNT IN (HL) INCREMENTED ; 0BFB E5 TRSEC3: PUSH H ; 0BFC 2ABF15 LHLD SECTRS ;SECTORS PER TRACK 0BFF 19 DAD D ; 0C00 DA100C JC TRSEC4 ; 0C03 79 MOV A,C ; 0C04 95 SUB L ; 0C05 78 MOV A,B ; 0C06 9C SBB H ;(BC) - (HL) 0C07 DA100C JC TRSEC4 ; 0C0A EB XCHG ; 0C0B E1 POP H ; 0C0C 23 INX H ;BUMP COUNTER 0C0D C3FB0B JMP TRSEC3 ; LOOP ; 0C10 E1 TRSEC4: POP H ; 0C11 C5 PUSH B ; 0C12 D5 PUSH D ; 0C13 E5 PUSH H ; 0C14 EB XCHG ; 0C15 2ACC15 LHLD DIRTRK ;DIRECTORY TRACK NUMBER 0C18 19 DAD D ; 0C19 44 MOV B,H ; 0C1A 4D MOV C,L ;(BC) <-- PHYSICAL TRACK NUMBER 0C1B CD0000 CALL @SETTRK ;BIOS CALL/SET DISK TRACK 0C1E D1 POP D ; 0C1F 2AB315 LHLD DWORD2 ; 0C22 73 MOV M,E ; 0C23 23 INX H ; 0C24 72 MOV M,D ;((DWORD2)) <-- (DE) 0C25 D1 POP D ; 0C26 2AB515 LHLD DWORD3 ; 0C29 73 MOV M,E ; 0C2A 23 INX H ; 0C2B 72 MOV M,D ;((DWORD3)) <-- (DE) 0C2C C1 POP B ; 0C2D 79 MOV A,C ; 0C2E 93 SUB E ; 0C2F 4F MOV C,A ; 0C30 78 MOV A,B ; 0C31 9A SBB D ; 0C32 47 MOV B,A ;(BC) <-- LOGICAL SECTOR NUMBER 0C33 2ACE15 LHLD SECTBL ; 0C36 EB XCHG ;(DE) <-- SECTOR TRANSLATE TABLE ADDR 0C37 CD0000 CALL @SECTRN ;BIOS CALL/SECTOR TRANSLATE 0C3A 4D MOV C,L ; 0C3B 44 MOV B,H ;(BC) <-- PHYSICAL SECTOR NUMBER CP/M RMAC ASSEM 1.1 #052 BODY OF CPM (CCP/BDOS) 17 DEC 84 0C3C C30000 JMP @SETSEC ;BIOS CALL/SET DISK SECTOR ; ; POINT TO FILE CONTROL BLOCK NUMBER ; ; RETURN WITH ABSOLUTE DIRECTORY BLOCK NUMBER IN (A) ; FILE EXTENT 00= 00H THROUGH 0FH ; FILE EXTENT 01= 10H THROUGH 1FH, ETC. TO ; FILE EXTENT 15= F0H THROUGH FFH. ; 0C3F 21C115 BLPNTR: LXI H,BLSHFT ;(C) <-- BLOCK SHIFT FACTOR 0C42 4E MOV C,M ; 0C43 3AE115 LDA CURREC ;CURRENT RECORD:: FCB + 32 ; ; DIVIDE (CURREC) BY 2^(BLSFT)...(USUALLY 8) ; 0C46 B7 BLPNT1: ORA A ;CLEAR CARRY FLAG 0C47 1F RAR ; 0C48 0D DCR C ; 0C49 C2460C JNZ BLPNT1 ; ; 0C4C 47 MOV B,A ; 0C4D 3E08 MVI A,08H ; 0C4F 96 SUB M ;SUBTRACT BLOCK SHIFT FACTOR FROM 8 0C50 4F MOV C,A ;AND SET AS COUNTER IN (C) 0C51 3AE015 LDA EXTCTR ;GET THE FILE EXTENT COUNTER: FCB + 12 0C54 0D BLPNT2: DCR C ; AND MULTIPLY IT BY 2^(C) 0C55 CA5D0C JZ BLPNT3 ; (THIS IS 32 FOR 8" SD) 0C58 B7 ORA A ; 0C59 17 RAL ; 0C5A C3540C JMP BLPNT2 ; ; 0C5D 80 BLPNT3: ADD B ;COMBINE W/ LOCAL POINTER 0C5E C9 RET ; ; ; GET BLOCK NUMBER ; ; ON ENTRY (BC) CONTAINS BLOCK NUMBER OFFSET ; ON RETURN (HL) CONTAINS LOGICAL BLOCK NUMBER ; ; CHECK IS MADE TO SEE IF SINGLE OR DOUBLE ; PRECISION LOGICAL BLOCK NUMBER IS CALLED FOR ; 0C5F 2A440B GETBLN: LHLD ENTPAR ;POINT TO START OF FILE CONTROL BLOCK 0C62 111000 LXI D,16 ; 0C65 19 DAD D ;MOVE POINTER TO FIRST BLOCK NUMBER 0C66 09 DAD B ; THEN TO THE DESIRED BLOCK NUMBER 0C67 3ADB15 LDA BIGDSK ;8" SD: 0FFH, LARGE CAP DISK: 00H 0C6A B7 ORA A ; 0C6B CA720C JZ GETBL1 ;BIG DISK, SO HIT IT AGAIN ; 0C6E 6E MOV L,M ;CHEAPSKATE W/ SINGLE DENSITY 0C6F 2600 MVI H,00H ;SINGLE PREC. BLOCK NUMBER 0C71 C9 RET ; ; 0C72 09 GETBL1: DAD B ;DOUBLE PREC. BLOCK NUMBER 0C73 5E MOV E,M ; BRING BACK BOTH BYTES IN (HL) CP/M RMAC ASSEM 1.1 #053 BODY OF CPM (CCP/BDOS) 17 DEC 84 0C74 23 INX H ; 0C75 56 MOV D,M ; 0C76 EB XCHG ; 0C77 C9 RET ; ; ; SET SECTOR COUNTER #1 ; ; PUT THE LOGICAL BLOCK NUMBER OF THE CURRENT ; 1K BLOCK INTO SECTOR COUNTER #1 ; 0C78 CD3F0C SETSC1: CALL BLPNTR ; 0C7B 4F MOV C,A ; 0C7C 0600 MVI B,00H ; 0C7E CD5F0C CALL GETBLN ;GET BLOCK NUMBER IN (HL) 0C81 22E315 SHLD SCNTR1 ;SECTOR COUNTER #1 0C84 C9 RET ; ; ; CHECK TO SEE IF (SECTOR COUNTER #1)= 0000H ; 0C85 2AE315 CHKSC1: LHLD SCNTR1 ;SECTOR COUNTER #1 0C88 7D MOV A,L ; 0C89 B4 ORA H ; 0C8A C9 RET ; ; ; COMPUTE LOGICAL SECTOR NUMBER ; ; ON ENTRY:-(SECTOR COUNTER #1) CONTAINS BLOCK ; NUMBER OF CURRENT BLOCK AND (FILE RECORD ; COUNTER) THE SECTOR NUMBER WITHIN THE ; CURRENT FILE EXTENT. ; ON EXIT:-(SECTOR COUNTER #1) CONTAINS TO ABSOLUTE ; SECTOR NUMBER OF THE CURRENT SECTOR OF THE ; CURRENT DISK ; -(SECTOR COUNTER #2) CONTAINS THE ABSOLUTE ; SECTOR NUMBER OF THE START OF THE CURRENT ; LOGICAL BLOCK ; -(RECORD COUNTER) IS UNCHANGED ; 0C8B 3AC115 COMSEC: LDA BLSHFT ;GET BLOCK SHIFT FACTOR 0C8E 2AE315 LHLD SCNTR1 ;SECTOR COUNTER #1 0C91 29 CONSE1: DAD H ;MULTIPLY BY 2^(BLSHFT)...USUALLY 8 0C92 3D DCR A ; 0C93 C2910C JNZ CONSE1 ; ; 0C96 22E515 SHLD SCNTR2 ;STORE RESULT IN SECTOR COUNTER #2 0C99 3AC215 LDA BLMASK ;(C) <-- DISK BLOCK MASK 0C9C 4F MOV C,A ; 0C9D 3AE115 LDA CURREC ;CURRENT RECORD:: FCB + 32 0CA0 A1 ANA C ;GET SECTOR NUMBER WITHIN BLOCK 0CA1 B5 ORA L ;ADD TO BLOCK STARTING SECTOR NUMBER 0CA2 6F MOV L,A ; 0CA3 22E315 SHLD SCNTR1 ;STORE IN SECTOR COUNTER #1 0CA6 C9 RET ; ; ; POINT TO FILE CONTROL BLOCK BYTE 12 ; CP/M RMAC ASSEM 1.1 #054 BODY OF CPM (CCP/BDOS) 17 DEC 84 ; BYTE 12 IS THE FILE EXTENT BYTE ; ; ENTRY PARAMETERS: NONE ; RETURN PARAMETER: ADDRESS OF FCB +12 IN (HL) ; 0CA7 2A440B FCB12: LHLD ENTPAR ;LOAD THE POINTER TO START OF FCB 0CAA 110C00 LXI D,12 ; AND ADD 12 TO IT. 0CAD 19 DAD D ; 0CAE C9 RET ; ; ; SET POINTERS TO FCB+15 AND FCB+32 ; ; ENTRY PARAMETERS: NONE ; EXIT PARAMETERS: POINTER TO FCB+15 IN (DE) ; POINTER TO FCB+32 IN (HL) ; ; FCB +15 IS THE RECORD COUNT OF THE CURRENT FILE EXTENT ; FCB +32 IS THE CURRENT RECORD TO BE READ/WRITTEN IN ; SEQUENTIAL R/W OPERATIONS ; 0CAF 2A440B FC1532: LHLD ENTPAR ;GET THE POINTER TO START OF FCB 0CB2 110F00 LXI D,15 ; 0CB5 19 DAD D ;ADD 15 TO POINT TO RECORD COUNT 0CB6 EB XCHG ;MOVE IT TO (DE) 0CB7 211100 LXI H,17 ;ADD ANOTHER 17 TO MAKE 0CBA 19 DAD D ;(HL) POINT TO FCB + 32 0CBB C9 RET ; ; ; UPDATE THE CURRENT DISK INFORMATION ; BY MOVING THE CONTENTS OF FCB+15 AND FCB+32 ; INTO (RECCTR) AND (CURREC) RESPECTIVELY ; 0CBC CDAF0C UPDATE: CALL FC1532 ;(DE) <-- FCB+15, (HL) <-- FCB+32 0CBF 7E MOV A,M ;GET CURRENT VALUE OF FCB+32 0CC0 32E115 STA CURREC ;AND STORE IN CURRENT RECORD NUMBER 0CC3 EB XCHG ;SWAP POINTERS 0CC4 7E MOV A,M ;GET CURRENT VALUE OF FCB+15 0CC5 32DF15 STA RECCTR ;AND STORE IN FILE RECORD COUNTER 0CC8 CDA70C CALL FCB12 ; (HL) <-- FCB + 12 , EXT BYTE PTR 0CCB 3AC315 LDA NLMASK ;NULL BLOCK MASK 0CCE A6 ANA M ; 0CCF 32E015 STA EXTCTR ;FILE EXTENT COUNTER: FCB + 12 0CD2 C9 RET ; ; ; LOAD AND INCREMENT THE VALUE OF THE CURRENT RECORD ; NUMBER BY 2 IF THE SEQUENTIAL/RANDOM READ/WRITE ; FLAG=2, OR LEAVE UNCHANGED IF=0. MOVE THE VALUE TO ; (RECCTR) AND (CURREC) ; 0CD3 CDAF0C RWEXIT: CALL FC1532 ;(DE) <-- FCB+15, (HL) <-- FCB+32 0CD6 3AD315 LDA SERNFL ;SEQUENTIAL/RANDOM I/O FLAG 0CD9 FE02 CPI 02H ; 0CDB C2DF0C JNZ RWEXT1 ; 0CDE AF XRA A ; 0CDF 4F RWEXT1: MOV C,A ; 0CE0 3AE115 LDA CURREC ;CURRENT RECORD:: FCB + 32 CP/M RMAC ASSEM 1.1 #055 BODY OF CPM (CCP/BDOS) 17 DEC 84 0CE3 81 ADD C ; 0CE4 77 MOV M,A ; 0CE5 EB XCHG ; 0CE6 3ADF15 LDA RECCTR ;FILE RECORD COUNTER:: FCB + 15 0CE9 77 MOV M,A ; 0CEA C9 RET ; ; ; SHIFT THE CONTENTS OF (HL) RIGHT ; PER THE COUNT IN (C) ; ; ENTRY PARAMETERS: ......... IN (HL) ; COUNT IN (C) ; EXIT PARAMETER: SHIFTED VALUE OF (HL) IN (HL) ; 0CEB 0C SHRHLC: INR C ; 0CEC 0D SHRHL1: DCR C ;CHECK THE COUNT 0CED C8 RZ ;EXIT ON ZERO 0CEE 7C MOV A,H ; 0CEF B7 ORA A ;CLEAR CARRY BIT 0CF0 1F RAR ;SHIFT (H) TO THE RIGHT 0CF1 67 MOV H,A ; 0CF2 7D MOV A,L ; 0CF3 1F RAR ;SHIFT (L) TO THE RIGHT 0CF4 6F MOV L,A ; 0CF5 C3EC0C JMP SHRHL1 ;LOOP ; ; CALCULATE CHECKSUM OF 128 BYTE DIRECTORY SECTOR ; AT ((DIRBPT)) ; ; ENTRY PARAMETER: POINTER TO START OF DIRECTORY ; SECTOR IN (DIRBPT) ; EXIT PARAMETER: VALUE OF CHECKSUM IN (A) ; 0CF8 0E80 CHKSUM: MVI C,SECLEN ;COUNT= 128 BYTE SECTOR LENGTH 0CFA 2AB715 LHLD DIRBPT ;GET DIRECTORY BUFFER POINTER 0CFD AF XRA A ;CLEAR CHECKSUM REGISTER 0CFE 86 CHKSM1: ADD M ;ADD TO TOTAL IN (A) 0CFF 23 INX H ;STEP THE POINTER 0D00 0D DCR C ;DECREMENT THE COUNT 0D01 C2FE0C JNZ CHKSM1 ;LOOP UNTIL COUNT=0 0D04 C9 RET ;RETURN WITH CRC IN (A) ; ; SHIFT (HL) LEFT PER COUNT IN (C) ; ; ENTRY PARAMETERS: ...... IN (HL) ; COUNT IN (C) ; EXIT PARAMETER: SHIFTED VALUE OF (HL) IN (HL) ; 0D05 0C SHLHLC: INR C ; 0D06 0D SHLHL1: DCR C ; 0D07 C8 RZ ; 0D08 29 DAD H ; 0D09 C3060D JMP SHLHL1 ; ; ; SET CURRENT DISK'S READ ONLY STATUS OR LOGGED IN STATUS ; CP/M RMAC ASSEM 1.1 #056 BODY OF CPM (CCP/BDOS) 17 DEC 84 ; ENTRY PARAMETER: (LOGVEC) or (ROWORD) IN (BC) ; CURRENT DISK NUMBER = (CURDSK) ; EXIT PARAMETER: UPDATED VERSION OF (BC) IN (HL). ; ; NOTE: ; (LOGVEC) AND (ROWORD) ARE 16 BIT WORDS ; EACH BIT REPRESENTS THE LOG IN AND READ ONLY ; STATUS OF THE DRIVE REPRESENTED BY THE BIT. ; LSB CORRESPONDS TO DRIVE 'A'. ; MSB CORRESPONDS TO DRIVE 'P'. ; 0D0C C5 SETVEC: PUSH B ;SAVE ENTRY PARAMETER 0D0D 3A430B LDA CURDSK ; 0D10 4F MOV C,A ;PUT DISK NUMBER AS COUNTER IN (C) 0D11 210100 LXI H,0001 ;SET-BIT IN (HL) 0D14 CD050D CALL SHLHLC ;SHIFT (HL) LEFT PER COUNT IN (C) 0D17 C1 POP B ;RESTORE PARAMETER 0D18 79 MOV A,C ;COMBINE SHIFTED SET-BIT WITH 0D19 B5 ORA L ; PREVIOUS CONTENTS OF 0D1A 6F MOV L,A ; (BC) INTO (HL) 0D1B 78 MOV A,B ; 0D1C B4 ORA H ; 0D1D 67 MOV H,A ; 0D1E C9 RET ;RETURN W/ UPDATED VALUE IN (HL) ; ; GET CURRENT READ ONLY STATUS OF DISK ; ; ENTRY PARAMETERS: NONE ; EXIT PARAMETER: LSB OF (A) SET IF DISK IS ; WRITE PROTECTED. ; 0D1F 2AAB15 GETRO: LHLD ROWORD ;GET R/O STATUS WORD 0D22 3A430B LDA CURDSK ;GET DISK NUMBER AS COUNTER IN (C) 0D25 4F MOV C,A ; 0D26 CDEB0C CALL SHRHLC ;SHIFT (HL) RIGHT PER COUNT IN (C) 0D29 7D MOV A,L ;MOVE CURRENT DISK STATUS TO (A) 0D2A E601 ANI 01H ;MASK OFF EXTRANEOUS INFORMATION 0D2C C9 RET ; ; ; BDOS COMMAND #28....SET CURRENT DISK TO READ ONLY ; ; CONTENTS OF (ROWORD) UPDATED TO INCLUDE ; CURRENT DISK. ; 0D2D 21AB15 COM28: LXI H,ROWORD ;MOVE (ROWORD) TO (BC) 0D30 4E MOV C,M ; 0D31 23 INX H ; 0D32 46 MOV B,M ; 0D33 CD0C0D CALL SETVEC ;SET CURRENT DISK TO READ ONLY 0D36 22AB15 SHLD ROWORD ;STORE UPDATED INFO IN (ROWORD) 0D39 2AC615 LHLD DIRMAX ;MAX NUMBER OF ENTRIES IN DIRECTORY 0D3C 23 INX H ; 0D3D EB XCHG ; 0D3E 2AB115 LHLD DWORD1 ; 0D41 73 MOV M,E ; 0D42 23 INX H ; CP/M RMAC ASSEM 1.1 #057 BODY OF CPM (CCP/BDOS) 17 DEC 84 0D43 72 MOV M,D ;((DWORD1)) <-- (DIRMAX) + 1 0D44 C9 RET ; ; ; CHECK THE READ ONLY STATUS OF A FILE DIRECTORY ; ENTRY POINTED TO BY (DIRBPT) + (DIROFF) ; ; R/O STATUS IS MARKED BY MSB OF FIRST BYTE OF ; FILE TYPE BEING SET. (FCB + 9) ; ; IF THE FILE IS WRITE PROTECTED, AN ERROR MESSAGE ; WILL BE SENT TO THE CONSOLE AND THE CHOICE OF ; REBOOTING OR LIVING WITH THE R/O FILE GIVEN ; 0D45 CD5F0D CHKRO: CALL DIRPTR ;(HL) <-- (DIRBPT) + (DIROFF) 0D48 110900 CHKRO1: LXI D,09 ; 0D4B 19 DAD D ;POINT TO FIRST BYTE OF FILETYPE 0D4C 7E MOV A,M ;MOVE INTO (A) 0D4D 17 RAL ;SHIFT MSB INTO CARRY 0D4E D0 RNC ;OK- FILE NOT WRITE PROTECTED 0D4F 210C08 LXI H,ERR4 ;ERROR CONDITION....... 0D52 C34B0B JMP ERROR ;.....WRITE PROTECTED FILE ; ; INTEROGATE READ ONLY STATUS OF CURRENT DISK ; ; SAME GENRAL RULES AS PREVIOUS SUBROUTINE, ; EXEPT THAT IS FOR R/O DISK ; 0D55 CD1F0D INTRRO: CALL GETRO ;GET READ ONLY STATUS OF CURRENT DISK 0D58 C8 RZ ;OK- THE DISK IS NOT WRITE PROTECTED 0D59 210A08 LXI H,ERR3 ;ERROR CONDITION.......... 0D5C C34B0B JMP ERROR ;..........WRITE PROTECTED DISK ; ; SET DIRECTORY POINTER TO START OF CURRENT ; DIRECTORY ENTRY. ; 0D5F 2AB715 DIRPTR: LHLD DIRBPT ;GET THE DIRECTORY BUFFER POINTER 0D62 3AE715 LDA DIROFF ;AND THE DIRECTORY OFFSET ; 0D65 85 ADA2HL: ADD L ; ADD CONTENTS OF (A) TO (HL) 0D66 6F MOV L,A ; AND RETURN WITH THE RESULT 0D67 D0 RNC ; IN (HL) 0D68 24 INR H ; 0D69 C9 RET ; ; ; GET THE CONTENTS OF S2 BYTE ; ; ENTRY PARAMETER: START OF FCB IN (ENTPAR) ; EXIT PARAMETERS: POINTER TO FCB+14 IN (HL) ; CONTENTS OF (FCB+14) IN (A) ; 0D6A 2A440B FCB14: LHLD ENTPAR ;POINT TO START OF FCB 0D6D 110E00 LXI D,14 ; 0D70 19 DAD D ;POINT TO FCB+14 0D71 7E MOV A,M ;GET THE VALUE OF FCB+14 0D72 C9 RET ; ; CP/M RMAC ASSEM 1.1 #058 BODY OF CPM (CCP/BDOS) 17 DEC 84 ; ZERO OUT THE VALUE OF FCB BYTE S2.(FCB + 14) ; 0D73 CD6A0D ZRFCTR: CALL FCB14 ;(HL) <-- FCB + 14, (A) <-- (FCB + 14) 0D76 3600 MVI M,00H ;PUT A ZERO IN IT 0D78 C9 RET ; ; ; SET THE MSB OF FCB BYTE S2.(FCB + 14) ; 0D79 CD6A0D SET14: CALL FCB14 ;(HL) <-- FCB + 14, (A) <-- (FCB + 14) 0D7C F680 ORI 80H ;SET THE HIGH BIT 0D7E 77 MOV M,A ;MOV IT BACK INTO MEMORY 0D7F C9 RET ; ; ; COMPARE ((DWORD1)) TO (BLCTR1) ; ; FLAGS SET ONLY, NUMERICAL RESULT NOT STORED ; ZFLAG SET IF THEY ARE EQUAL ; CFLAG SET IF ((DWORD1)) > (BLCTR1) ; 0D80 2AE815 FLB1D1: LHLD BLCTR1 ;BLOCK COUNTER #1 0D83 EB XCHG ; 0D84 2AB115 LHLD DWORD1 ; 0D87 7B MOV A,E ;(BLCTR1)-((DWORD1)) 0D88 96 SUB M ; 0D89 23 INX H ; 0D8A 7A MOV A,D ; 0D8B 9E SBB M ; 0D8C C9 RET ; ; ; IF ((DWORD1)) > (BLCTR1) THEN RETURN UNCHANGED ; ELSE ((DWORD1)) <-- (BLCTR1) + 1 ; 0D8D CD800D SWB1D1: CALL FLB1D1 ; 0D90 D8 RC ; 0D91 13 INX D ; 0D92 72 MOV M,D ; 0D93 2B DCX H ; 0D94 73 MOV M,E ; 0D95 C9 RET ; ; ; SUBTRACT (HL) FROM (DE) ; RESULT RETURNED IN (HL) ; 0D96 7B DEMIHL: MOV A,E ;(HL) <-- (DE) - (HL) 0D97 95 SUB L ; 0D98 6F MOV L,A ; 0D99 7A MOV A,D ; 0D9A 9C SBB H ; 0D9B 67 MOV H,A ; 0D9C C9 RET ; ; ; CHECK THE DIRECTORY CHECKSUM STORED IN ; CURRENT DISK PARAMETER AREA WITH ; CHECKSUM COMPUTED FROM DIRECTORY OF ; DISK MOUNTED IN CURRENT DRIVE ; CP/M RMAC ASSEM 1.1 #059 BODY OF CPM (CCP/BDOS) 17 DEC 84 ; IF CHECKSUMS DON'T MATCH, THE DISK IS ; SET TO READ ONLY STATUS ; 0D9D 0EFF CHKCRC: MVI C,0FFH ; 0D9F 2AEA15 CHKCR1: LHLD BLCTR2 ;BLOCK COUNTER #2 0DA2 EB XCHG ; 0DA3 2ACA15 LHLD CHKSIZ ;NUMBER OF DIRECTORY ENTRIES TO BE CHECKED 0DA6 CD960D CALL DEMIHL ;(HL) <-- (DE) - (HL) 0DA9 D0 RNC ; 0DAA C5 PUSH B ; 0DAB CDF80C CALL CHKSUM ;CRC OF 128 BYTES POINTED TO BY (DIRBPT) 0DAE 2ABB15 LHLD DIRCRC ;DIRECTORY BUFFER POINTER 0DB1 EB XCHG ; 0DB2 2AEA15 LHLD BLCTR2 ;BLOCK COUNTER #2 0DB5 19 DAD D ; 0DB6 C1 POP B ; 0DB7 0C INR C ; 0DB8 CAC50D JZ CHKCR2 ; 0DBB BE CMP M ; 0DBC C8 RZ ; 0DBD CD800D CALL FLB1D1 ; 0DC0 D0 RNC ; 0DC1 CD2D0D CALL COM28 ;* WRITE PROTECT DISK 0DC4 C9 RET ; ; 0DC5 77 CHKCR2: MOV M,A ; 0DC6 C9 RET ; ; ; DIRECTORY SECTOR WRITE ; ; DMA ADDRESS IS SET TO (DIRBPT) ; SECTOR IS WRITEN ; DMA ADDRESS IS SET BACK TO (CURDMA) ; ; (A)= 01 IS PASSED TO BIOS TO INDICATE THAT THIS ; IS A DIRECTORY WRITE OPERATION ; 0DC7 CD9D0D DIRWRT: CALL CHKCRC ;COMPARE CHECKSUMS BEFORE WRITING 0DCA CDE10D CALL DIRDMA ;SET DMA FOR DIRECTORY READ/WRITE 0DCD 0E01 MVI C,01H ;TELL BIOS THAT THIS IS A DIR WRITE 0DCF CDB90B CALL WRSECT ; 0DD2 C3DB0D JMP DIRD1 ; ; ; DIRECTORY SECTOR READ ; ; DMA ADDRESS IS SET TO (DIRBPT) ; THE SECTOR IS READ, AND ; DMA ADDRESS IS SET BACK TO (CURDMA) ; ; THIS PROCEDURE AVOIDS OVERWRITING DATA AREAS ; BY THE DIRECTORY OPERATIONS A OCCURED IN CP/M 1.4 ; DURING 'SAVE' OPERATIONS ; 0DD5 CDE10D DIREAD: CALL DIRDMA ;SET DMA FOR DIRECTORY READ/WRITE 0DD8 CDB30B CALL RDSECT ; 0DDB 21AF15 DIRD1: LXI H,CURDMA ; CP/M RMAC ASSEM 1.1 #060 BODY OF CPM (CCP/BDOS) 17 DEC 84 0DDE C3E40D JMP DIRDM1 ; ; ; SET DMA ADDRES FOR DIRECTORY READ/WRITE ; 0DE1 21B715 DIRDMA: LXI H,DIRBPT ;GET DIRECTORY BUFFER POINTER 0DE4 4E DIRDM1: MOV C,M ;(BC) <-- ((HL)) 0DE5 23 INX H ; 0DE6 46 MOV B,M ; 0DE7 C30000 JMP @SETDMA ;BIOS CALL/SET DMA ; ; MOVE SECTOR FROM ((DIRBPT)) TO ((CURDMA)) ; ;Z80 USERS MIGHT CHANGE THIS TO SOMETHING LIKE: ; ;MOVSEC:LD HL,(CURDMA) ; EX DE,HL ; LD HL,(DIRBPT) ; LD BC,SECLEN ; LDIR ; RET ; 0DEA 2AB715 MOVSEC: LHLD DIRBPT ;SOURCE 0DED EB XCHG ; 0DEE 2AAF15 LHLD CURDMA ;DESTINATION 0DF1 0E80 MVI C,SECLEN ;COUNT 0DF3 C3500B JMP BLKMOV ; ; ; CHECK THE CONTENTS OF BLOCK COUNTER #1 ; ; RETURNS WITH (A)= LOW ORDER BYTE OF (BLCTR1)+1 ; IF THE LOW ORDER BYTE = THE HIGH ORDER BYTE ; ELSE RETURNS WITH LOW ORDER BYTE ; OF (BLCTR1) IN (A). ; ZFLAG ALWAYS RESET UNLESS (BLCTR1)= -1 ; COME TO THINK ABOUT IT, THIS IS REALLY A CHECK OF ; WHETHER (BLCTR1)= -1. IN THAT CASE WHY THE HELL IS ; THIS THING NOT WRITTEN AS FOLLOWS: ; ;CHKBC1:LHLD BLCTR1 ; ; INX H ;MAKE -1 INTO 00 ; MOV A,L ; ; ORA H ; ; RET ; ; ; THIS SUBROUTINE IS ALWAYS CALLED IMMEDIATELY AFTER ; CALLS TO SERCHF, SERCHN, MAKEF AND CLOSEF. ; 0DF6 21E815 CHKBC1: LXI H,BLCTR1 ; 0DF9 7E MOV A,M ; 0DFA 23 INX H ; 0DFB BE CMP M ; 0DFC C0 RNZ ;NOT EQUAL- RETURN W/ LOW ORDER BYTE 0DFD 3C INR A ;EQUAL-- BUMP LOW ORDER BYTE 0DFE C9 RET ; ; ; SET THE CONTENTS OF BLOCK COUNTER #1 TO -1 CP/M RMAC ASSEM 1.1 #061 BODY OF CPM (CCP/BDOS) 17 DEC 84 ; 0DFF 21FFFF SETBC1: LXI H,-1 ; 0E02 22E815 SHLD BLCTR1 ;BLOCK COUNTER #1 0E05 C9 RET ; ; ; COMPARE THE CONTENTS OF BLOCK COUNTER #1 AGAINST ; THE MAXIMUM DIRECTORY CAPACITY OF THE DISK. ; ; SET (BLCTR1) <-- -1 IF DIRECTORY CAPACITY IS EXCEEDED ; ELSE READ DIRECTORY SECTOR AND CHECK DIRECTORY ; CHECKSUM. ; 0E06 2AC615 GETDIR: LHLD DIRMAX ;MAX NUMBER OF ENTRIES IN DIRECTORY 0E09 EB XCHG ; 0E0A 2AE815 LHLD BLCTR1 ;BLOCK COUNTER #1 0E0D 23 INX H ; 0E0E 22E815 SHLD BLCTR1 ;BLOCK COUNTER #1 0E11 CD960D CALL DEMIHL ;(HL) <-- (DE) - (HL) 0E14 DAFF0D JC SETBC1 ; SET (BLCTR1) <-- -1 ; ERROR EXIT ; 0E17 3AE815 GETDI1: LDA BLCTR1 ;BLOCK COUNTER #1 0E1A E603 ANI 03H ; 0E1C 0605 MVI B,05H ; 0E1E 87 GETDI2: ADD A ; 0E1F 05 DCR B ; 0E20 C21E0E JNZ GETDI2 ; 0E23 32E715 STA DIROFF ;DIRECTORY OFFSET 0E26 B7 ORA A ; 0E27 C0 RNZ ; 0E28 C5 PUSH B ; 0E29 CDC40B CALL TRKSEC ;SET TRACK AND SECTOR 0E2C CDD50D CALL DIREAD ;READ DIRECTORY SECTOR FROM DISK 0E2F C1 POP B ; 0E30 C39F0D JMP CHKCR1 ;OK EXIT ; ; GET STATUS OF ALLOCATION OF BLOCK IN (A) ; ; ENTRY PARAMETER:(BC) CONTAINS DISK BLOCK # ; EXIT PARAMETER: (A)... STATUS OF 1K BLOCK ; (D)... BIT NUMBER ; (HL).. POINTER TO BYTE IN ALLOCAION ; MAP ; ; THIS SUBROUTINE IS CALLED: ; TWICE BY WRSUB ; ONCE BY BLKMP5 ; REPLACEMENT CODE: ;GETALC:MOV A,C ; ; ANI 07H ; ; INR A ; ; MOV E,A ; ; MOV D,A ;BIT COUNTER TO (D) & (E) ; MOV L,C ; ; MOV H,B ; ; MVI C,03H ; CP/M RMAC ASSEM 1.1 #062 BODY OF CPM (CCP/BDOS) 17 DEC 84 ; PUSH D ; ; CALL SHRHLC ;(HL) <-- ENTRY PARAMETER/8 ; XCHG ; ; LHLD DALLOC ; ; DAD D ;POINT TO BYTE IN ALLOCATION BLOCK ; POP D ;RESTORE COUNTERS ; MOV A,M ;GET BIT MAP BYTE ;GETAL1:RLC ;ROTATE UNTIL DESIRED BIT ; DCR E ; IS LSB OF (A) ; JNZ GETAL1 ; ; RET ; ; 0E33 79 GETALC: MOV A,C ; 0E34 E607 ANI 07H ; 0E36 3C INR A ; 0E37 5F MOV E,A ;BIT NUMBER INTO (E) & (D) 0E38 57 MOV D,A ; 0E39 79 MOV A,C ; 0E3A 0F RRC ;/2 0E3B 0F RRC ; /4 0E3C 0F RRC ; /8 0E3D E61F ANI 1FH ; 0E3F 4F MOV C,A ; 0E40 78 MOV A,B ; 0E41 87 ADD A ;*2 0E42 87 ADD A ; *4 0E43 87 ADD A ; *8 0E44 87 ADD A ; *16 0E45 87 ADD A ; *32 0E46 B1 ORA C ; 0E47 4F MOV C,A ; 0E48 78 MOV A,B ; 0E49 0F RRC ;/2 0E4A 0F RRC ; /4 0E4B 0F RRC ; /8 0E4C E61F ANI 1FH ; 0E4E 47 MOV B,A ;(BC) <-- (BC)/8= BYTE NUMBER ; IN ALLOCATION BLOCK 0E4F 2ABD15 LHLD DALLOC ; 0E52 09 DAD B ;(HL) <-- POINTER TO ALLOC BYTE 0E53 7E MOV A,M ;ALLOCATION BYTE 0E54 07 GETAL1: RLC ;ROTATE BIT INTO LSB (A) 0E55 1D DCR E ; 0E56 C2540E JNZ GETAL1 ; 0E59 C9 RET ; ; ; SET OR CLEAR 1K BLOCK FROM THE ALLOCATION MAP ; ; ENTRY PARAMETER: (BC)= DISK BLOCK NUMBER ; 00 OR 01 IN (E) ; IF (E)= 00 THEN THE BLOCK IS CLEARED ; IF (E)= 01 THEN THE BLOCK IS MARKED "IN USE" ; 0E5A D5 BLKMP5: PUSH D ;SAVE ENTRY PARAMETER 0E5B CD330E CALL GETALC ;GET STATUS OF ALLOCATION BLOCK IN LSB OF (A) 0E5E E6FE ANI 0FEH ;MASK OFF LSB ::= CLEAR ALLOCATION CP/M RMAC ASSEM 1.1 #063 BODY OF CPM (CCP/BDOS) 17 DEC 84 0E60 C1 POP B ;GET BACK ENTRY PARAMETER TO (BC) 0E61 B1 ORA C ;.OR. LSB WITH ENTRY PARAMETER 0E62 0F BLKMP6: RRC ;ROTATE (A) PER COUNT IN (D) 0E63 15 DCR D ; 0E64 C2620E JNZ BLKMP6 ; ; 0E67 77 MOV M,A ;STORE BYTE BACK INTO ALLOCATION BLOCK 0E68 C9 RET ; ; ; SET OR CLEAR THE BIT CORRECPONDING TO THE ; 1K DISK BLOCK NUMBER IN (HL). ; ; ENTRY PARAMETER: (HL)=DISK 1K BLOCK NUMBER ; (C)= 0 WHEN CALLED BY DELETE ; (C)= 1 WHEN CALLED BY LOGIN ; PASSES ENTRY PARAMETER TO BLKMP5 IN (E) ; IF PARAMETER IS 1, THEN THE 1K BLOCK IS MARKED AS ; AS BEING IN USE. ; IF PARAMETER IS 0, THEN THE 1K BLOCK IS CLEARED AND ; CAN BE REALLOCATED. ; 0E69 CD5F0D BLKMAP: CALL DIRPTR ;(HL) <-- (DIRBPT) + (DIROFF) 0E6C 111000 LXI D,16 ; 0E6F 19 DAD D ;POINT TO START OF BLOCK NUMBERS 0E70 C5 PUSH B ;SAVE ENTRY PARAMETER 0E71 0E11 MVI C,11H ;COUNTER 16 BYTES + 1 0E73 D1 BLKMP1: POP D ; 0E74 0D DCR C ; 0E75 C8 RZ ;EXIT WHEN LAST BLOCK IS CHECKED 0E76 D5 PUSH D ; 0E77 3ADB15 LDA BIGDSK ;8" SD: 0FFH, LARGE CAP DISK: 00H 0E7A B7 ORA A ; 0E7B CA860E JZ BLKMP2 ; ; ; CODE FOR 8" SD ; 0E7E C5 PUSH B ; 0E7F E5 PUSH H ; 0E80 4E MOV C,M ; 0E81 0600 MVI B,00H ; 0E83 C38C0E JMP BLKMP3 ; ; ; CODE FOR LARGE DISK ; 0E86 0D BLKMP2: DCR C ; 0E87 C5 PUSH B ; 0E88 4E MOV C,M ; 0E89 23 INX H ; 0E8A 46 MOV B,M ; 0E8B E5 PUSH H ; ; ; RESUME COMMON CODE ; ; IF (BC) <> 0000H AND (HL) >= (BC)\ ; THEN UPDATE ALLOCATION MAP ; CP/M RMAC ASSEM 1.1 #064 BODY OF CPM (CCP/BDOS) 17 DEC 84 0E8C 79 BLKMP3: MOV A,C ; 0E8D B0 ORA B ; 0E8E CA9B0E JZ BLKMP4 ; 0E91 2AC415 LHLD DSKSIZ ;DISK SIZE, # OF 1K BLOCKS -1 0E94 7D MOV A,L ; 0E95 91 SUB C ; 0E96 7C MOV A,H ; 0E97 98 SBB B ;(HL) - (BC) 0E98 D45A0E CNC BLKMP5 ;UPDATE ALLOCATION MAP 0E9B E1 BLKMP4: POP H ; 0E9C 23 INX H ;POINT TO NEXT BLOCK 0E9D C1 POP B ;RESTORE INPUT PARAMETER 0E9E C3730E JMP BLKMP1 ;LOOP ; ; PICK UP THE FLAG SET BY SEARCH OPERATIONS ; THEN VAMOOSE OUT OF BDOS ; 0EA1 3AD215 EXIT3: LDA SRCHFL ;POINTER SET BY SERCHF FOR USE BY SERCHN 0EA4 C3020B JMP EXIT1 ; ; ; SUBROUTINE CALLED BY SEARCH WHEN COMPARING ; BYTE 12. THIS HAS SOMETHING TO DO WITH THE ; EXTENT NUMBER BYTE, BUT EXACT USE NOT ; DETERMINED YET. (NLMASK)* ::= .NOT.(NLMASK) ; ; (A) <-- ((A).AND.(NLMASK)* - (C).AND.(NLMASK)*).AND.1FH ; 0EA7 C5 SERCH7: PUSH B ; 0EA8 F5 PUSH PSW ; 0EA9 3AC315 LDA NLMASK ;NULL BLOCK MASK 0EAC 2F CMA ; 0EAD 47 MOV B,A ; 0EAE 79 MOV A,C ; 0EAF A0 ANA B ; 0EB0 4F MOV C,A ; 0EB1 F1 POP PSW ; 0EB2 A0 ANA B ; 0EB3 91 SUB C ; 0EB4 E61F ANI 1FH ; 0EB6 C1 POP B ; 0EB7 C9 RET ; ; ; SEARCH FOR OCCURENCE OF FILE NAME IN DIRECTORY ; ; SERCHF IS INITIAL ENTRY POINT WHICH LEAVES ; FCB VECTOR FOR USE BY SUBSEQUENT SEARCHES ; WHICH ENTER BY WAY OF SERCHN. NO OTHER BDOS ; CALLS WHICH MAKE USE OF SRCHFP BETWEEN THE ; INTIAL CALL TO SERCHF AND CALLS TO SERCHN ARE ; ARE ALLOWED OR ELSE RATHER STRANGE THINGS MAY HAPPEN. ; REMEMBER THAT BDOS IS NOT DESIGNED FOR RECURSIVE CALLS ; AND STORED VALUES ARE OVERWRITTEN INSTEAD OF BEING ; PUSHED UP ONTO A LOCAL STACK. ; ; SERCHF INITIATES (SRCHFL) TO 0FFH. ; A SUCCESSFUL MATCH CLEARS IT TO 00 CP/M RMAC ASSEM 1.1 #065 BODY OF CPM (CCP/BDOS) 17 DEC 84 ; ; ENTRY PARAMETER: (C)= NUMBER OF BYTES TO BE MATCHED ; THIS COUNT IS STORED IN (SRCHCT) ; FOR SUBSEQUENT CALLS TO SERCHN ; 0EB8 3EFF SERCHF: MVI A,0FFH ;SEARCH FOR FIRST OCCURENCE OF FILE NAME 0EBA 32D215 STA SRCHFL ;POINTER SET BY SERCHF FOR USE BY SERCHN 0EBD 21D615 LXI H,SRCHCT ;SEARCH BYTE COUNTER 0EC0 71 MOV M,C ; 0EC1 2A440B LHLD ENTPAR ;ENTRY PARAMETER 0EC4 22D715 SHLD SRCHFP ;SEARCH FCB POINTER, SET BY SERCHF 0EC7 CDFF0D CALL SETBC1 ;SET (BLCTR1) <-- -1 0ECA CDA20B CALL SETDIR ; ; ; ENTRY POINT FOR SUBSEQUENT SEARCHES ; 0ECD 0E00 SERCHN: MVI C,00H ;SEARCH FOR NEXT OCCURENCE OF FILE NAME 0ECF CD060E CALL GETDIR ;GET DIRECTORY SECTOR 0ED2 CDF60D CALL CHKBC1 ; 0ED5 CA400F JZ SERCH6 ; 0ED8 2AD715 LHLD SRCHFP ;SEARCH FCB POINTER, SET BY SERCHF 0EDB EB XCHG ; 0EDC 1A LDAX D ; 0EDD FEE5 CPI 0E5H ;IS THIS DIRECTORY BLOCK IN USE? 0EDF CAEA0E JZ SERCH1 ;NO- 0EE2 D5 PUSH D ; 0EE3 CD800D CALL FLB1D1 ; 0EE6 D1 POP D ; 0EE7 D2400F JNC SERCH6 ; 0EEA CD5F0D SERCH1: CALL DIRPTR ;(HL) <-- (DIRBPT) + (DIROFF) 0EED 3AD615 LDA SRCHCT ;NUMBER OF BYTES TO BE COMPARED 0EF0 4F MOV C,A ; 0EF1 0600 MVI B,00H ;COUNTER FOR BYTE BEING COMPARED 0EF3 79 SERCH2: MOV A,C ; 0EF4 B7 ORA A ;CHECK THE COUNT 0EF5 CA330F JZ SERCH5 ;END OF THE MATCH- EXIT TRIUMPHANTLY 0EF8 1A LDAX D ; 0EF9 FE3F CPI '?' ;WILDCARD MATCH 0EFB CA2C0F JZ SERCH4 ; 0EFE 78 MOV A,B ; 0EFF B7 PATCH: ORA A ; 0F00 C20E0F JNZ PATCH2 ; 0F03 1A LDAX D ; 0F04 FEE5 CPI 0E5H ; 0F06 CA0E0F JZ PATCH2 ; 0F09 7E MOV A,M ; 0F0A B7 ORA A ; 0F0B CA2C0F JZ SERCH4 ; 0F0E 78 PATCH2: MOV A,B ; 0F0F FE0D CPI 0DH ;ARE WE AT BYTE 13? 0F11 CA2C0F JZ SERCH4 ;SKIP- WE DON'T HAVE TO MATCH BYTE 13 0F14 FE0C CPI 0CH ;ARE WE AT BYTE 12? 0F16 1A LDAX D ; 0F17 CA230F JZ SERCH3 ; 0F1A 96 SUB M ;COMPARE FCB BYTE TO DIR ENTRY BYTE W/ ;MSB MASKED. THIS IS SO THAT SYSTEM CP/M RMAC ASSEM 1.1 #066 BODY OF CPM (CCP/BDOS) 17 DEC 84 ;AND R/O FILENAMES CAN BE MATCHED 0F1B E67F ANI 7FH ; 0F1D C2CD0E JNZ SERCHN ;NO MATCH- GET ANOTHER DIRECTORY ENTRY 0F20 C32C0F JMP SERCH4 ;GOT A MATCH GOING, GO TO NEXT BYTE ; ; WE COME HERE ON BYTE 12 (EXTENT BYTE) ; 0F23 C5 SERCH3: PUSH B ; 0F24 4E MOV C,M ; 0F25 CDA70E CALL SERCH7 ; 0F28 C1 POP B ; 0F29 C2CD0E JNZ SERCHN ;SEARCH FOR NEXT OCCURENCE OF FILE NAME ; ; WE HAVE A MATCH GOING, BUMP THE COUNTERS & POINTERS ; FOR ANOTHER TURN AROUND THE LOOP ; 0F2C 13 SERCH4: INX D ;INCREMENT POINTERS 0F2D 23 INX H ; 0F2E 04 INR B ; 0F2F 0D DCR C ;DECREMENT LOOP COUNT 0F30 C3F30E JMP SERCH2 ;LOOP ; ; FILE NAME FOUND EXIT ; ; LEAVE WITH (RETPAR) SET TO THE DIRECTORY OFFSET ; NUMBER. I.E. 0, 1, 2 OR 3 THAT MARKS THE DIRECTORY ; ENTRY IN (DIRBPT) THAT MATCHED FCB. ; (SRCHFL) CLEARED IF WAS NOT ALREADY DONE SO IN A ; PREVIOUS PASS. ; 0F33 3AE815 SERCH5: LDA BLCTR1 ;BLOCK COUNTER #1 0F36 E603 ANI 03H ; 0F38 32460B STA RETPAR ;RETURN PARAMETER 0F3B AF XRA A ; CLEAR IT NOW 0F3C 32D215 STA SRCHFL ; 0F3F C9 RET ; ; ; FILE NAME NOT FOUND EXIT ; ; SET (BLKCTR)= 0FFFFH AND (RETVAL)= 0FFH ; TO TELL THE WORLD THAT NO MATCH WAS FOUND ; 0F40 CDFF0D SERCH6: CALL SETBC1 ;SET (BLCTR1) <-- -1 0F43 3EFF MVI A,0FFH ; 0F45 C3020B JMP EXIT1 ;(RETVAL) <-- (A) AND RETURN ; ; DELETE FILE FROM DIRECTORY ; ; THE FIRST 12 CHARACTERS OF THE FILENAME.TYP ARE ; COMPARED TO THE DIRECTORY ENTRIES, AND IF A MATCH ; IS FOUND, THE FIRST BYTE OF THE DIRECTORY ENTRY ; IS CHANEG TO 0E5H. THE DATA IS ON THE DISK AND ; CAN BE RECOVERED BY SUCH UTILITIES AS UNERASE OR ; SPAT. ; 0F48 CD550D DELETE: CALL INTRRO ;INTEROGATE CURRENT R/O STATUS CP/M RMAC ASSEM 1.1 #067 BODY OF CPM (CCP/BDOS) 17 DEC 84 0F4B 0E0C MVI C,0CH ;12 CHARACTER MATCH 0F4D CDB80E CALL SERCHF ;SEARCH FOR FIRST OCCURENCE OF FILE NAME 0F50 CDF60D DELET1: CALL CHKBC1 ;CHECK CONTENTS OF (BLCTR1) 0F53 C8 RZ ;EXIT WHEN THERE IS NO FURTHER MATCH 0F54 CD450D CALL CHKRO ;CHECK CURRENT R/O STATUS 0F57 CD5F0D CALL DIRPTR ;(HL) <-- (DIRBPT) + (DIROFF) 0F5A 36E5 MVI M,0E5H ;INSERT ERASE CHAR IN DIR FCB 0F5C 0E00 MVI C,00H ; 0F5E CD690E CALL BLKMAP ; 0F61 CDC70D CALL DIRWRT ;WRITE DIRECTORY SECTOR TO DISK 0F64 CDCD0E CALL SERCHN ;FIND NEXT OCCURENCE OF FILE NAME 0F67 C3500F JMP DELET1 ;LOOP BACK FOR ANOTHER TRY ; ; SUBROUTINE CALLED BY WRSEQ ; ; SEARCHES FOR FIRST UNUSED 1K BLOCK IN THE ALLOCATION ; ALLOCATION MAP ; ; ENTRY PARAMETERS:(BC) CURRENT BLOCK NUMBER OR 0000H ; (SEE NOTE BELOW) ; EXIT PARAMETERS: (HL) NUMBER OF NEXT FREE BLOCK OR ; 0000H IF NO BLOCK AVAILABLE ; ; NOTE: ; SEARCH STARTS AT BLOCK 0000H FOR FIRST ALLOC- ; ATION FOR A NEW DIRECTORY EXTENT, OR FROM THE ; CURRENT BLOCK NUMBER FOR SUBSEQUENT ALLOCATIONS ; THIS SAVES TIME SINCE IT ASSUMES THAT ALL ; BLOCKS UP TO THE CURRENT ONE HAVE BEEN USED. ; THIS MAY CAUSE AN 'OUT OF DISK SPACE' ERROR ; IF OTHER FILES ARE BEING DELETED WHILE THIS ; ONE IS BEING WRITTEN. A REMOTE, BUT REAL, ; POSSIBILITY. ; 0F6A 50 WRSUB: MOV D,B ; 0F6B 59 MOV E,C ;(DE) <-- (BC) 0F6C 79 WRSUB1: MOV A,C ; 0F6D B0 ORA B ; 0F6E CA7D0F JZ WRSUB2 ; 0F71 0B DCX B ; 0F72 D5 PUSH D ; 0F73 C5 PUSH B ; 0F74 CD330E CALL GETALC ;GET STATUS OF ALLOCATION BLOCK IN LSB OF (A) 0F77 1F RAR ; 0F78 D2980F JNC WRSUB3 ;FOUND AN EMPTY ONE 0F7B C1 POP B ; 0F7C D1 POP D ; 0F7D 2AC415 WRSUB2: LHLD DSKSIZ ;DISK SIZE, # OF 1K BLOCKS -1 0F80 7B MOV A,E ; 0F81 95 SUB L ; 0F82 7A MOV A,D ; 0F83 9C SBB H ; 0F84 D2A00F JNC WRSUB4 ; 0F87 13 INX D ; 0F88 C5 PUSH B ; 0F89 D5 PUSH D ; CP/M RMAC ASSEM 1.1 #068 BODY OF CPM (CCP/BDOS) 17 DEC 84 0F8A 42 MOV B,D ; 0F8B 4B MOV C,E ; 0F8C CD330E CALL GETALC ;GET STATUS OF ALLOCATION BLOCK IN LSB OF (A) 0F8F 1F RAR ; 0F90 D2980F JNC WRSUB3 ; 0F93 D1 POP D ; 0F94 C1 POP B ; 0F95 C36C0F JMP WRSUB1 ; ; ; BLOCK FOUND ; 0F98 17 WRSUB3: RAL ;ROTATE BACK INTO PLACE 0F99 3C INR A ;MARK IT 'IN USE' 0F9A CD620E CALL BLKMP6 ;PUT BACK INTO BLOCK MAP 0F9D E1 POP H ;(HL) <-- BLOCK NUMBER 0F9E D1 POP D ;WASTE STACK 0F9F C9 RET ; ; ; NO EMPTY BLOCKS ; 0FA0 79 WRSUB4: MOV A,C ; 0FA1 B0 ORA B ; 0FA2 C26C0F JNZ WRSUB1 ; 0FA5 210000 LXI H,0000H ; 0FA8 C9 RET ; ; ; SUBROUTINE CALLED BY MAKEF ; ; MOVES 32 BYTES FROM FILE CONTROL BLOCK TO ; DIRECTORY ENTRY THEN WRITES DIRECTORY SECTOR ; TO DISK. ; ; ALSO CALLED THROUGH SECONDARY ENTRY POINT: ; ; (C)= 16, (E)= 12 WHEN CALLED BY RENAME ; (C)= 00, (E)= 12 WHEN CALLED BY ATTRIB ; 0FA9 0E00 MAKESR: MVI C,00H ; 0FAB 1E20 MVI E,32 ;DIRECTORY ENTRY IS 32 BYTES ; ; SECONDARY ENTRY POINT ; (C)= OFFSET, (E)= BYTE COUNTER ; 0FAD D5 MAKES1: PUSH D ;SAVE COUNTER 0FAE 0600 MVI B,00H ; 0FB0 2A440B LHLD ENTPAR ;ENTRY PARAMETER 0FB3 09 DAD B ; ADD OFFSET 0FB4 EB XCHG ; MOVE TO (DE) 0FB5 CD5F0D CALL DIRPTR ;(HL) <-- (DIRBPT) + (DIROFF) 0FB8 C1 POP B ; 0FB9 CD500B CALL BLKMOV ;MOVE FILENAME.EXT INTO DIR BUFFER 0FBC CDC40B MAKES2: CALL TRKSEC ;SET TRACK AND SECTOR 0FBF C3C70D JMP DIRWRT ;WRITE DIRECTORY BUFFER TO DISK ; ; RENAME FILE ; CP/M RMAC ASSEM 1.1 #069 BODY OF CPM (CCP/BDOS) 17 DEC 84 ; ON ENTRY THE CONTENTS OF (DE) POINTS TO A 32 ; BYTE BLOCK WHERE THE FIRST 16 BYTES ARE THE ; OLD FILENAME.TYP AND THE SECOND 16 ARE THE ; NEW FILENAME.EXT. THIS PIECE OF CODE MAKES A ; 12 BYTE SEARCH TO MATCH THE OLD FILENAME.TYP ; WITH ENTRIES IN THE DIRECTORY. WHEN A MATCH ; IS MADE THE NEW FILENAME.TYP IS INSERTED INTO ; THE DIRECTORY SECTOR AND THE SECTOR WRITTTEN ; BACK ONTO THE DISK. ; 0FC2 CD550D RENAME: CALL INTRRO ;INTEROGATE CURRENT R/O STATUS 0FC5 0E0C MVI C,0CH ;SET UP FOR 12 BYTE SEARCH 0FC7 CDB80E CALL SERCHF ;SEARCH FOR FIRST OCCURENCE OF FILE NAME 0FCA 2A440B LHLD ENTPAR ;ENTRY PARAMETER 0FCD 7E MOV A,M ; 0FCE 111000 LXI D,16 ; 0FD1 19 DAD D ;POINT TO NEW FILENAME.TYP 0FD2 77 MOV M,A ; 0FD3 CDF60D RENAM1: CALL CHKBC1 ;CHECK CONTENTS OF (BLCTR1) 0FD6 C8 RZ ;EXIT- NO MATCH 0FD7 CD450D CALL CHKRO ;CHECK CURRENT R/O STATUS 0FDA 0E10 MVI C,10H ;16 BYTE OFFSET 0FDC 1E0C MVI E,0CH ;12 BYTE MOVE 0FDE CDAD0F CALL MAKES1 ;MOVE FILENAME.TYP & WRITE DIR TO DISK 0FE1 CDCD0E CALL SERCHN ;SEARCH FOR NEXT OCCURENCE OF FILE NAME 0FE4 C3D30F JMP RENAM1 ;LOOP BACK FOR ANOTHER GO AT IT ; ; SET FILE ATTRIBUTES ; ; THIS PIECE OF CODE IS USED OFFICIALLY TO MAKE ; SYSTEM FILES INVISIBLE TO DIRECTORY OPERATIONS ; BY SETTING MSB OF T1 HIGH AND TO MAKE FILES "READ ; ONLY" BY SETTING MSB OF T2 HIGH. COULD BE USED FOR ; OTHER MISCHIEF. ; 0FE7 0E0C ATTRIB: MVI C,0CH ;12 BYTE SEARCH 0FE9 CDB80E CALL SERCHF ;SEARCH FOR FIRST OCCURENCE OF FILE NAME 0FEC CDF60D ATTRB1: CALL CHKBC1 ;CHECK CONTENTS OF (BLCTR1) 0FEF C8 RZ ;RETURN WHEN FILENAME.EXT CANNOT BE ;FOUND, EITHER ON THE FIRST PASS OR ;SUBSEQUENT PASSES 0FF0 0E00 MVI C,00H ; 0FF2 1E0C MVI E,0CH ;MOVE 12 BYTES INTO DIRECTORY BUFFER 0FF4 CDAD0F CALL MAKES1 ;REPLACING CURRENT NAME & REWRITING DIR 0FF7 CDCD0E CALL SERCHN ;SEARCH FOR NEXT OCCURENCE OF FILE NAME 0FFA C3EC0F JMP ATTRB1 ;LOOP ; ; OPEN A FILE FOR READING OR WRITING ; 0FFD 0E0F OPENF: MVI C,0FH ;15 BYTES SEARCH 0FFF CDB80E CALL SERCHF ;SEARCH FOR FIRST OCCURENCE OF FILE NAME 1002 CDF60D CALL CHKBC1 ;CHECK CONTENTS OF (BLCTR1) 1005 C8 RZ ;--ERROR EXIT FILE NOT FOUND 1006 CDA70C OPENF1: CALL FCB12 ; (HL) <-- FCB + 12 , EXT BYTE PTR 1009 7E MOV A,M ; 100A F5 PUSH PSW ; CP/M RMAC ASSEM 1.1 #070 BODY OF CPM (CCP/BDOS) 17 DEC 84 100B E5 PUSH H ; 100C CD5F0D CALL DIRPTR ;(HL) <-- (DIRBPT) + (DIROFF) 100F EB XCHG ; 1010 2A440B LHLD ENTPAR ;ENTRY PARAMETER 1013 0E20 MVI C,32 ;SIZE OF DIRECTORY BLOCK 1015 D5 PUSH D ; 1016 CD500B CALL BLKMOV ;MOVE DIRECTORY BLOCK INTO FCB 1019 CD790D CALL SET14 ;SET MSB OF BYTE 14 TO SAY FILE OPEN 101C D1 POP D ; 101D 210C00 LXI H,12 ; 1020 19 DAD D ; 1021 4E MOV C,M ;(C) <-- (DIRECTORY ENTRYI+12)= EXTENT 1022 210F00 LXI H,15 ; 1025 19 DAD D ; 1026 46 MOV B,M ;(B) <-- (DIRECTORY ENTRY+15)= RECORD CTR 1027 E1 POP H ; 1028 F1 POP PSW ;(A) <-- (FCB + 12) 1029 77 MOV M,A ; 102A 79 MOV A,C ; ; ; IF (FCB+12)=(DIR ENTRY+12) THEN (FCB+15) <-- (DIR ENTRY+15) ; IF (FCB+12)>(DIR ENTRY+12) THEN (FCB+15) <-- 80H ; IF (FCB+12)<(DIR ENTRY+12) THEN (FCB+15) <-- 00H ; 102B BE CMP M ; 102C 78 MOV A,B ; 102D CA3710 JZ OPENF2 ; 1030 3E00 MVI A,00H ; 1032 DA3710 JC OPENF2 ; 1035 3E80 MVI A,80H ; 1037 2A440B OPENF2: LHLD ENTPAR ;ENTRY PARAMETER 103A 110F00 LXI D,15 ; 103D 19 DAD D ; 103E 77 MOV M,A ; 103F C9 RET ; ; ; SUBROUTINE CALLED WHILE CLOSING A BIG DISK ; ; IF ((HL)) = 0 THEN ((HL)) <-- ((DE)) ; 1040 7E CLOSE8: MOV A,M ;IS ((HL)) = 0? 1041 23 INX H ; 1042 B6 ORA M ; 1043 2B DCX H ; 1044 C0 RNZ ;NO- RETURN AS IS 1045 1A LDAX D ;((HL)) IS 0, REPLACE WITH ((DE)) 1046 77 MOV M,A ; 1047 13 INX D ; 1048 23 INX H ; 1049 1A LDAX D ; 104A 77 MOV M,A ; 104B 1B DCX D ; 104C 2B DCX H ; 104D C9 RET ; ; ; CLOSE DISK FILE AFTER READING OR WRITING CP/M RMAC ASSEM 1.1 #071 BODY OF CPM (CCP/BDOS) 17 DEC 84 ; 104E AF CLOSEF: XRA A ;CLOSE FILE 104F 32460B STA RETPAR ;RETURN PARAMETER 1052 32E815 STA BLCTR1 ;BLOCK COUNTER #1 1055 32E915 STA BLCTR1+1 ;BLOCK COUNTER #1 1058 CD1F0D CALL GETRO ;GET READ ONLY STATUS OF CURRENT DISK 105B C0 RNZ ; 105C CD6A0D CALL FCB14 ;(HL) <-- FCB + 14, (A) <-- (FCB + 14) 105F E680 ANI 80H ;CHECK MSB OF (FCB+14) 1061 C0 RNZ ;RETURN IF MSB SET ; 1062 0E0F MVI C,0FH ;15 BYTE SEARCH 1064 CDB80E CALL SERCHF ;SEARCH FOR FIRST OCCURENCE OF FILE NAME 1067 CDF60D CALL CHKBC1 ;CHECK CONTENTS OF (BLCTR1) 106A C8 RZ ; 106B 011000 LXI B,16 ; 106E CD5F0D CALL DIRPTR ;(HL) <-- (DIRBPT) + (DIROFF) 1071 09 DAD B ; 1072 EB XCHG ; 1073 2A440B LHLD ENTPAR ;ENTRY PARAMETER 1076 09 DAD B ; ; ; (DE) <-- FCB + 16 ; (HL) <-- (DIRBPT) + (DIROFF) + 16 ; (C) <-- COUNTER ; ; CHECK TO SEE IF THE BLOCK NUMBERS IN ((HL)) OR ((DE)) ; ARE EQUAL TO ZERO. IF ONE IS ZERO, IT IS SET TO THE ; VALUE OF THE OTHER. IF THE BLOCK NUMBERS ARE NOT ; EQUAL AFTER THIS, THERE IS AN ERROR. ; 1077 0E10 MVI C,10H ; 1079 3ADB15 CLOSE1: LDA BIGDSK ;8" SD: 0FFH, LARGE CAP DISK: 00H 107C B7 ORA A ; 107D CA9410 JZ CLOSE4 ; ; ; CODE FOR 8" SD DISK ; 1080 7E MOV A,M ; 1081 B7 ORA A ; 1082 1A LDAX D ; 1083 C28710 JNZ CLOSE2 ; 1086 77 MOV M,A ; 1087 B7 CLOSE2: ORA A ; 1088 C28D10 JNZ CLOSE3 ; 108B 7E MOV A,M ; 108C 12 STAX D ; 108D BE CLOSE3: CMP M ; 108E C2CB10 JNZ CLOSE7 ;ERROR 1091 C3A910 JMP CLOSE5 ;OK ; ; CODE FOR DISK > 255K ; EQUIVALENT TO CODE ABOVE ; 1094 CD4010 CLOSE4: CALL CLOSE8 ; 1097 EB XCHG ; CP/M RMAC ASSEM 1.1 #072 BODY OF CPM (CCP/BDOS) 17 DEC 84 1098 CD4010 CALL CLOSE8 ; 109B EB XCHG ; 109C 1A LDAX D ; 109D BE CMP M ; 109E C2CB10 JNZ CLOSE7 ;ERROR 10A1 13 INX D ; 10A2 23 INX H ; 10A3 1A LDAX D ; 10A4 BE CMP M ; 10A5 C2CB10 JNZ CLOSE7 ; 10A8 0D DCR C ; ; ; RESUME CODE COMMON TO ALL SIZES ; 10A9 13 CLOSE5: INX D ; 10AA 23 INX H ; 10AB 0D DCR C ; 10AC C27910 JNZ CLOSE1 ; ; 10AF 01ECFF LXI B,-20 ; 10B2 09 DAD B ; 10B3 EB XCHG ; 10B4 09 DAD B ; ; (DE)= FCB+12 ; (HL)= DIR ENTRY+12 10B5 1A LDAX D ; 10B6 BE CMP M ; ; IF (DIR ENTRY+12) <= (FCB+12) THEN (DIR ENTRY+15) <-- (FCB+15) 10B7 DAC310 JC CLOSE6 ; 10BA 77 MOV M,A ; 10BB 010300 LXI B,03 ; 10BE 09 DAD B ; 10BF EB XCHG ; 10C0 09 DAD B ; 10C1 7E MOV A,M ; 10C2 12 STAX D ; ; ; OK EXIT: DIRECTORY WRITTEN TO DISK ; 10C3 3EFF CLOSE6: MVI A,0FFH ; 10C5 32D015 STA MAKEFL ;MAKE-FILE FLAG 10C8 C3BC0F JMP MAKES2 ;EXIT VIA SET TRACK & SECTOR ;AND WRITE DIRECTORY TO DISK ; ; ERROR EXIT: RETURN PARAMETER SET TO 0FFH ; MEANING THAT FILE CANNOT BE CLOSED ; 10CB 21460B CLOSE7: LXI H,RETPAR ;RETURN PARAMETER <-- 0FFH 10CE 35 DCR M ; 10CF C9 RET ; ; ; MAKE A NEW FILE ENTRY IN THE DIRECTORY ; 10D0 CD550D MAKEF: CALL INTRRO ;INTEROGATE CURRENT R/O STATUS 10D3 2A440B LHLD ENTPAR ;GET ENTRY PARAMETER 10D6 E5 PUSH H ;STASH IT CP/M RMAC ASSEM 1.1 #073 BODY OF CPM (CCP/BDOS) 17 DEC 84 10D7 21AA15 LXI H,DMYFCB ;DUMMY FCB 0E5H 10DA 22440B SHLD ENTPAR ;ENTRY PARAMETER ; ; SEARCH DISK DIRECTORY FOR AN ENTRY THAT ; STARTS WITH 0E5H. I.E. AN UNUSED SLOT ; 10DD 0E01 MVI C,01H ;1 BYTE MATCH 10DF CDB80E CALL SERCHF ;SEARCH FOR FIRST OCCURENCE OF FILE NAME 10E2 CDF60D CALL CHKBC1 ;CHECK CONTENTS OF (BLCTR1) 10E5 E1 POP H ; 10E6 22440B SHLD ENTPAR ;RESTORE ENTRY PARAMETER 10E9 C8 RZ ;ERROR EXIT- COULD NOT FIND EMPTY SLOT ; 10EA EB XCHG ; 10EB 210F00 LXI H,15 ;POINT TO FCB + 15 10EE 19 DAD D ; 10EF 0E11 MVI C,11H ;17 BYTE COUNT 10F1 AF XRA A ;(A) <-- 0 10F2 77 MAKEF1: MOV M,A ;ZERO OUT FCB BYTES 15 THROUGH 32 10F3 23 INX H ; ^ 10F4 0D DCR C ; | 10F5 C2F210 JNZ MAKEF1 ;---------------| ; 10F8 210D00 LXI H,13 ;ZERO OUT FCB BYTE 13 10FB 19 DAD D ; 10FC 77 MOV M,A ; 10FD CD8D0D CALL SWB1D1 ; 1100 CDA90F CALL MAKESR ;MOVE FCB TO DIRECTORY BUFFER & WRITE ;DIRECTORY BUFFER TO DISK 1103 C3790D JMP SET14 ;SET MSB OF FCB+14 & EXIT ; ; OPEN NEXT FILE DIRECTORY EXTENT ; 1106 AF OPNNXT: XRA A ; 1107 32D015 STA MAKEFL ;MAKE-FILE FLAG 110A CD4E10 CALL CLOSEF ;CLOSE CURRENT EXTENT 110D CDF60D CALL CHKBC1 ;CHECK CONTENTS OF (BLCTR1) 1110 C8 RZ ;ERROR EXIT...CANNOT CLOSE CURRENT EXT ; 1111 2A440B LHLD ENTPAR ;ENTRY PARAMETER 1114 010C00 LXI B,12 ; 1117 09 DAD B ;POINT TO FCB+12 :: EXTENT BYTE 1118 7E MOV A,M ; 1119 3C INR A ;INCREMENT EXTENT 111A E61F ANI 1FH ; 111C 77 MOV M,A ; 111D CA2F11 JZ OPNXT1 ; EXTENT > 31 1120 47 MOV B,A ; 1121 3AC315 LDA NLMASK ;NULL BLOCK MASK 1124 A0 ANA B ; 1125 21D015 LXI H,MAKEFL ;MAKE-FILE FLAG 1128 A6 ANA M ; 1129 CA3A11 JZ OPNXT2 ; 112C C35811 JMP OPNXT3 ; ; ; EXTENT IN BYTE 12 WAS > 31 CP/M RMAC ASSEM 1.1 #074 BODY OF CPM (CCP/BDOS) 17 DEC 84 ; INCREMENT 3RD LEVEL COUNTER ; IN LOWER NIBBLE OF BYTE 14 ; 112F 010200 OPNXT1: LXI B,02 ; 1132 09 DAD B ;(HL) <-- FCB + 14 1133 34 INR M ; 1134 7E MOV A,M ; 1135 E60F ANI 0FH ; 1137 CA6211 JZ OPNXT5 ;OVERFLOW ERROR ; 113A 0E0F OPNXT2: MVI C,0FH ;15 BYTE MATCH 113C CDB80E CALL SERCHF ;SEARCH FOR FIRST OCCURENCE OF FILE NAME 113F CDF60D CALL CHKBC1 ;CHECK CONTENTS OF (BLCTR1) 1142 C25811 JNZ OPNXT3 ;FILE NAME FOUND 1145 3AD115 LDA RDWRFL ;READ/WRITE FLAG:: 0FFH= READ/0= WRITE 1148 3C INR A ; 1149 CA6211 JZ OPNXT5 ;ERROR EXIT-TRYING TO OPEN NONEXISTENT ;EXTENT FOR READING ; 114C CDD010 CALL MAKEF ;MAKE NEW DIRECTORY ENTRY 114F CDF60D CALL CHKBC1 ;CHECK CONTENTS OF (BLCTR1) 1152 CA6211 JZ OPNXT5 ;ERROR EXIT-COULD NOT OPEN NEW EXT 1155 C35B11 JMP OPNXT4 ;OK ; 1158 CD0610 OPNXT3: CALL OPENF1 ;OPEN THE EXTENT 115B CDBC0C OPNXT4: CALL UPDATE ;UPDATE SECTOR COUNTERS 115E AF XRA A ;SET OK FLAG 115F C3020B JMP EXIT1 ;STORE IT IN RETURN VALUE & EXIT ; ; ERROR EXIT ; 1162 CD060B OPNXT5: CALL EXIT2 ;PUT 01 IN RETURN VALUE 1165 C3790D JMP SET14 ;SET MSB OF FCB + 14 & EXIT ; ; READ SECTOR TO MEMORY ; ; THIS TANGLED PIECE OF CODE DOESN'T DO THE ; ACTUAL WRITING, JUST THE SETTING UP OF ALL ; KINDS OF FLAGS AND THINGS ; ; ENTRY POINT FOR SEQUENTIAL READ: RDSEQ ; ENTRY POINT FOR RANDOM READ: RDSEQ1 ; 1168 3E01 RDSEQ: MVI A,01H ;READ SEQUENTIAL FILE 116A 32D315 STA SERNFL ;SEQUENTIAL/RANDOM I/O FLAG ; 116D 3EFF RDSEQ1: MVI A,0FFH ; 116F 32D115 STA RDWRFL ;READ/WRITE FLAG 1172 CDBC0C CALL UPDATE ;UPDATE SECTOR COUNTERS 1175 3AE115 LDA CURREC ;CURRENT RECORD:: FCB + 32 1178 21DF15 LXI H,RECCTR ;FILE RECORD COUNTER:: FCB + 15 117B BE CMP M ; 117C DA9211 JC RDSEQ2 ; 117F FE80 CPI 80H ; 1181 C2A711 JNZ RDSEQ3 ; 1184 CD0611 CALL OPNNXT ; CP/M RMAC ASSEM 1.1 #075 BODY OF CPM (CCP/BDOS) 17 DEC 84 1187 AF XRA A ; 1188 32E115 STA CURREC ;CURRENT RECORD:: FCB + 32 118B 3A460B LDA RETPAR ;RETURN PARAMETER 118E B7 ORA A ; 118F C2A711 JNZ RDSEQ3 ; 1192 CD780C RDSEQ2: CALL SETSC1 ; 1195 CD850C CALL CHKSC1 ; 1198 CAA711 JZ RDSEQ3 ; 119B CD8B0C CALL COMSEC ;COMPUTE SECTOR NUMBER 119E CDD20B CALL TRSEC1 ; 11A1 CDB30B CALL RDSECT ; 11A4 C3D30C JMP RWEXIT ; ; 11A7 C3060B RDSEQ3: JMP EXIT2 ; ; ; WRITE SEQUENTIAL SECTOR ; ; ENTRY POINT FOR SEQUENTIAL WRITE: WRSEQ ; ENTRY POINT FOR RANDOM WRITE: WRSEQ1 ; SERNFL= 00H FOR RANDOM WRITE (COM34) ; = 02H FOR FILL RANDOM (COM40) ; 11AA 3E01 WRSEQ: MVI A,01H ;WRITE SEQUENTIAL FILE 11AC 32D315 STA SERNFL ;SEQUENTIAL/RANDOM I/O FLAG ; 11AF 3E00 WRSEQ1: MVI A,00H ; 11B1 32D115 STA RDWRFL ;READ/WRITE FLAG 11B4 CD550D CALL INTRRO ;INTEROGATE CURRENT R/O STATUS 11B7 2A440B LHLD ENTPAR ;ENTRY PARAMETER 11BA CD480D CALL CHKRO1 ; 11BD CDBC0C CALL UPDATE ;UPDATE SECTOR COUNTERS 11C0 3AE115 LDA CURREC ;CURRENT RECORD:: FCB + 32 11C3 FE80 CPI 80H ; 11C5 D2060B JNC EXIT2 ; 11C8 CD780C CALL SETSC1 ; 11CB CD850C CALL CHKSC1 ; 11CE 0E00 MVI C,00H ; 11D0 C21A12 JNZ WRSEQ6 ; 11D3 CD3F0C CALL BLPNTR ; 11D6 32D515 STA BLKOFF ;TEMPORARY STORAGE 11D9 010000 LXI B,0000H ; 11DC B7 ORA A ; 11DD CAE711 JZ WRSEQ2 ; 11E0 4F MOV C,A ; 11E1 0B DCX B ; 11E2 CD5F0C CALL GETBLN ;GET BLOCK NUMBER IN (HL) 11E5 44 MOV B,H ; 11E6 4D MOV C,L ;(BC) <-- BLOCK NUMBER 11E7 CD6A0F WRSEQ2: CALL WRSUB ; 11EA 7D MOV A,L ; 11EB B4 ORA H ; 11EC C2F411 JNZ WRSEQ3 ; 11EF 3E02 MVI A,02H ;#2 ERROR- END OF DISK DATA 11F1 C3020B JMP EXIT1 ;ERROR EXIT ; 11F4 22E315 WRSEQ3: SHLD SCNTR1 ;SECTOR COUNTER #1 CP/M RMAC ASSEM 1.1 #076 BODY OF CPM (CCP/BDOS) 17 DEC 84 11F7 EB XCHG ; 11F8 2A440B LHLD ENTPAR ;ENTRY PARAMETER 11FB 011000 LXI B,16 ; 11FE 09 DAD B ; 11FF 3ADB15 LDA BIGDSK ;8" SD: 0FFH, LARGE CAP DISK: 00H 1202 B7 ORA A ; 1203 3AD515 LDA BLKOFF ;TEMPORARY STORAGE 1206 CA1012 JZ WRSEQ4 ; ; ; CODE FOR 8" S.D. SMALL DISK ; 1209 CD650D CALL ADA2HL ;(HL) <-- (HL) + (A) 120C 73 MOV M,E ;STORE BLOCK NUMBER 120D C31812 JMP WRSEQ5 ; ; ; CODE FOR BIG DISK ; 1210 4F WRSEQ4: MOV C,A ; 1211 0600 MVI B,00H ; 1213 09 DAD B ; 1214 09 DAD B ;POINT TO SLOT 1215 73 MOV M,E ; 1216 23 INX H ; 1217 72 MOV M,D ;STORE BLOCK NUMBER ; ; RESUME CODE COMMON TO ALL DISKS ; 1218 0E02 WRSEQ5: MVI C,02H ; 121A 3A460B WRSEQ6: LDA RETPAR ;RETURN PARAMETER 121D B7 ORA A ; 121E C0 RNZ ; 121F C5 PUSH B ; 1220 CD8B0C CALL COMSEC ;COMPUTE SECTOR NUMBER 1223 3AD315 LDA SERNFL ;SEQUENTIAL/RANDOM I/O FLAG 1226 3D DCR A ;CHECK TO SEE IF (SERNFL)= 2 1227 3D DCR A ; 1228 C26712 JNZ WRSEQ9 ;NO- ; ; (SERNFL) IS SET = 2 ONLY BY UNDOCUMENTED COMMAND #40 ; THE FOLLOWING CODE WRITES 0'S TO THE DIRECTORY ; SECTOR, THEN WRITES THE SECTOR TO DISK ; 122B C1 POP B ; 122C C5 PUSH B ; 122D 79 MOV A,C ;CHECK TO SEE IF (C)= 2, WHICH IT ;ALWAYS IS, BECAUSE IT WAS SET ;JUST 12 COMMANDS BACK. MORE USELESS ;CODE! 122E 3D DCR A ; 122F 3D DCR A ; 1230 C26712 JNZ WRSEQ9 ;(THIS WILLNEVER HAPPEN) 1233 E5 PUSH H ; ; ; FILL ((DIRBPT)) WITH 128 0'S ; 1234 2AB715 LHLD DIRBPT ;DIRECTORY BUFFER POINTER CP/M RMAC ASSEM 1.1 #077 BODY OF CPM (CCP/BDOS) 17 DEC 84 1237 57 MOV D,A ;(D) <-- 0 1238 77 WRSEQ7: MOV M,A ;((HL)) <-- 0 1239 23 INX H ; 123A 14 INR D ; 123B F23812 JP WRSEQ7 ; ; ; WRITE BLANKED SECTOR TO DISK ; UNTIL ENTIRE 1K BLOCK HAS BEEN ; WRITTEN. ; 123E CDE10D CALL DIRDMA ;SET DMA FOR DIRECTORY READ/WRITE 1241 2AE515 LHLD SCNTR2 ;SECTOR COUNTER #2 1244 0E02 MVI C,02H ; 1246 22E315 WRSEQ8: SHLD SCNTR1 ;SECTOR COUNTER #1 1249 C5 PUSH B ; 124A CDD20B CALL TRSEC1 ; 124D C1 POP B ; 124E CDB90B CALL WRSECT ; 1251 2AE315 LHLD SCNTR1 ;SECTOR COUNTER #1 1254 0E00 MVI C,00H ; 1256 3AC215 LDA BLMASK ;DISK BLOCK MASK 1259 47 MOV B,A ; 125A A5 ANA L ; 125B B8 CMP B ; 125C 23 INX H ; 125D C24612 JNZ WRSEQ8 ; 1260 E1 POP H ; 1261 22E315 SHLD SCNTR1 ;SECTOR COUNTER #1 1264 CDDB0D CALL DIRD1 ;GET BACK INITIAL SECTOR OF THE 1K ;BLOCK, AND PREPARE TO WRITE IT ;BACK TO DISK (FOR REASONS UNKNOWN) ; 1267 CDD20B WRSEQ9: CALL TRSEC1 ;SET UP THE TRACK & SECTOR IN BIOS 126A C1 POP B ; 126B C5 PUSH B ; 126C CDB90B CALL WRSECT ;DO THE ACTUAL WRITING OF THE SECTOR 126F C1 POP B ; 1270 3AE115 LDA CURREC ;CURRENT RECORD:: FCB + 32 1273 21DF15 LXI H,RECCTR ;FILE RECORD COUNTER: FCB + 15 1276 BE CMP M ;CHECK TO SEE IF BEYOND END OF EXTENT 1277 DA7E12 JC WRSE10 ;NOT BEYOND END- SKIP 127A 77 MOV M,A ;AT OR BEYOND- 127B 34 INR M ; INCREMENT RECORD COUNTER 127C 0E02 MVI C,02H ; ?? ; ; THE FOLLOWING 5 BYTES ARE NOT NEEDED; HOWEVER ; THEY MAY BE THERE TO ALLOW CUSTOMIZERS TO INSERT ; SOMETHING WITHOUT A COMPLETE REASSEMBLY. ; Otherwise, your guess is as good as mine. ; 127E 00 WRSE10: NOP ;A blank- 127F 00 NOP ; and another blank. 1280 210008 LXI H,FBASE ;Don't know what this is for. ; 1283 F5 PUSH PSW ; 1284 CD6A0D CALL FCB14 ;(HL) <-- FCB + 14, (A) <-- (FCB + 14) CP/M RMAC ASSEM 1.1 #078 BODY OF CPM (CCP/BDOS) 17 DEC 84 1287 E67F ANI 7FH ;RESET MSB OF FCB + 14 1289 77 MOV M,A ; 128A F1 POP PSW ; 128B FE7F CPI 7FH ;HAVE WE JUST WRITTEN THE LAST SECTOR ;IN THE CURRENT EXTENT? 128D C2AC12 JNZ WRSE12 ;NO- 1290 3AD315 LDA SERNFL ;LOAD THE SEQUENTIAL/RANDOM I/O FLAG 1293 FE01 CPI 01H ;IS THIS A SEQUENTIAL WRITE? 1295 C2AC12 JNZ WRSE12 ;NOPE- 1298 CDD30C CALL RWEXIT ;YEP- CLOSE OUT THE CURRENT EXTENT 129B CD0611 CALL OPNNXT ; AND GO ABOUT MAKING A NEW ONE 129E 21460B LXI H,RETPAR ;RETURN PARAMETER 12A1 7E MOV A,M ; 12A2 B7 ORA A ; 12A3 C2AA12 JNZ WRSE11 ; 12A6 3D DCR A ; 12A7 32E115 STA CURREC ;CURRENT RECORD:: FCB + 32 12AA 3600 WRSE11: MVI M,00H ; 12AC C3D30C WRSE12: JMP RWEXIT ; ; ; SET PARAMETERS FOR RANDOM READ OR WRITE ; ; ENTRY PARAMETER: (C)=00H WHEN CALLED BY RDRAND ; (C)=0FFH WHEN CALLED BY WRRAND ; EXIT PARAMETER: (A)=00 AND ZFLAG RESET-- OK ; (RETPAR)<>0 & ZFLAG SET- ERROR ; ; THE ENTRY PARAMETER IS PASSED THROUGH UNUSED, ; AND INSPECTION OF WRSEQ1 AND RDSEQ1 DOES NOT ; REVEAL ANY USE OF THE PARAMETER. THIS MAY BE ; A LEFTOVER FROM CP/M 1.4 WHEN THERE WAS ONE CALL ; FOR READING OR WRITING A SECTOR, WITH THE ; DESIRED ACTION BEING SPECIFIED BY (C). ; 12AF AF SETRND: XRA A ; 12B0 32D315 STA SERNFL ;SEQUENTIAL/RANDOM I/O FLAG 12B3 C5 SETRN1: PUSH B ; 12B4 2A440B LHLD ENTPAR ;ENTRY PARAMETER 12B7 EB XCHG ; 12B8 212100 LXI H,33 ; 12BB 19 DAD D ; 12BC 7E MOV A,M ; 12BD E67F ANI 7FH ;(A) <-- (FCB+32).AND.7FH 12BF F5 PUSH PSW ; 12C0 7E MOV A,M ; 12C1 17 RAL ;CFLAG <-- MSB(FCB+32) 12C2 23 INX H ; 12C3 7E MOV A,M ; 12C4 17 RAL ;LSB(FCB+33) <-- CFLAG 12C5 E61F ANI 1FH ; 12C7 4F MOV C,A ; 12C8 7E MOV A,M ; 12C9 1F RAR ; 12CA 1F RAR ; 12CB 1F RAR ; 12CC 1F RAR ; CP/M RMAC ASSEM 1.1 #079 BODY OF CPM (CCP/BDOS) 17 DEC 84 12CD E60F ANI 0FH ; 12CF 47 MOV B,A ; 12D0 F1 POP PSW ; 12D1 23 INX H ;POINT TO FCB+35, OVERFLOW BYTE 12D2 6E MOV L,M ; 12D3 2C INR L ; 12D4 2D DCR L ;SET FLAGS (8080 DOES NOT HAVE BIT OPCODE) 12D5 2E06 MVI L,06H ;#6 ERROR- SEEK PAST END OF DISK 12D7 C23713 JNZ SETRN5 ; 12DA 212000 LXI H,32 ; 12DD 19 DAD D ; 12DE 77 MOV M,A ; 12DF 210C00 LXI H,12 ; 12E2 19 DAD D ; 12E3 79 MOV A,C ; 12E4 96 SUB M ; 12E5 C2F312 JNZ SETRN2 ; 12E8 210E00 LXI H,14 ; 12EB 19 DAD D ; 12EC 78 MOV A,B ; 12ED 96 SUB M ; 12EE E67F ANI 7FH ; 12F0 CA2B13 JZ SETRN3 ; 12F3 C5 SETRN2: PUSH B ; 12F4 D5 PUSH D ; 12F5 CD4E10 CALL CLOSEF ;CLOSE FILE 12F8 D1 POP D ; 12F9 C1 POP B ; 12FA 2E03 MVI L,03H ; 12FC 3A460B LDA RETPAR ;RETURN PARAMETER 12FF 3C INR A ; 1300 CA3013 JZ SETRN4 ; 1303 210C00 LXI H,12 ; 1306 19 DAD D ; 1307 71 MOV M,C ; 1308 210E00 LXI H,14 ; 130B 19 DAD D ; 130C 70 MOV M,B ; 130D CDFD0F CALL OPENF ;OPEN FILE 1310 3A460B LDA RETPAR ;RETURN PARAMETER 1313 3C INR A ; 1314 C22B13 JNZ SETRN3 ; 1317 C1 POP B ; 1318 C5 PUSH B ; 1319 2E04 MVI L,04H ;#4 ERROR- SEEK TO UNWRITTEN EXTENT 131B 0C INR C ; 131C CA3013 JZ SETRN4 ; 131F CDD010 CALL MAKEF ;MAKE NEW DIRECTORY ENTRY 1322 2E05 MVI L,05H ;#5 ERROR- CANNOT OPEN NEW DIR EXTENT 1324 3A460B LDA RETPAR ;RETURN PARAMETER 1327 3C INR A ; 1328 CA3013 JZ SETRN4 ; 132B C1 SETRN3: POP B ;GET BACK ENTRY PARAMETER 132C AF XRA A ;CLEAR RETURN PARAMETER 132D C3020B JMP EXIT1 ;OK EXIT ; CP/M RMAC ASSEM 1.1 #080 BODY OF CPM (CCP/BDOS) 17 DEC 84 1330 E5 SETRN4: PUSH H ; 1331 CD6A0D CALL FCB14 ;(HL) <-- FCB + 14, (A) <-- (FCB + 14) 1334 36C0 MVI M,0C0H ;??????? 1336 E1 POP H ; 1337 C1 SETRN5: POP B ;GET BACK ENTRY PARAMETER 1338 7D MOV A,L ; 1339 32460B STA RETPAR ;STORE ERROR # IN RETURN PARAMETER 133C C3790D JMP SET14 ;ERROR EXIT W/ MSB OF (FCB+14) SET ; ; READ RANDOM SECTOR ; 133F 0EFF RDRAND: MVI C,0FFH ;SET PARAMETER FOR SETRND (USELESS) 1341 CDAF12 CALL SETRND ; 1344 CC6D11 CZ RDSEQ1 ;IF OK CALL, ELSE DROP THROUGH 1347 C9 RET ; ; ; WRITE RANDOM SECTOR ; 1348 0E00 WRRAND: MVI C,00H ;SET PARAMETER FOR SETRND (USELESS) 134A CDAF12 CALL SETRND ; 134D CCAF11 CZ WRSEQ1 ;IF OK CALL, ELSE DROP THROUGH 1350 C9 RET ; ; ; COMPUTE ABSOLUTE SECTOR NUMBER FOR FSIZE & COM36 ; ;ENTRY PARAMETERS: ; WHEN CALLED BY FSIZE ; (HL)= POINTER TO CURRENT ENTRY IN DIRECTORY ; BUFFER. ; (DE)= 15. OFFSET TO DIRECTORY RECORD COUNTER ; ; WHEN CALLED BY COM36 ; (HL)= POINTER TO FCB, I.E. (ENTPAR) ; (DE)= 32. OFFSET TO RANDOM READ/WRITE COUNTER ; ;ON EXIT: ; REGISTERS A,B & C HOLD TRIPLE PRECISION SECTOR ; NUMBER IN THE FOLLOWING FORMAT: ; (C) LOW ORDER BYTE ; (B) HIGH ORDER BYTE ; (A) OVERFLOW ; ; (A) (B) (C) <-- (BYTE14).AND.0FH*2^12+(BYTE12).AND.1FH*2^7+(BYTE32)or(BYTE15) ; 1351 EB RNDPAR: XCHG ; 1352 19 DAD D ; 1353 4E MOV C,M ; 1354 0600 MVI B,00H ; 1356 210C00 LXI H,12 ; 1359 19 DAD D ; 135A 7E MOV A,M ; 135B 0F RRC ; 135C E680 ANI 80H ; 135E 81 ADD C ; 135F 4F MOV C,A ;(C) <-- ((HL)+(C))+(BYTE12)SHL7 ;LOW ORDER BYTE CP/M RMAC ASSEM 1.1 #081 BODY OF CPM (CCP/BDOS) 17 DEC 84 1360 3E00 MVI A,00H ; 1362 88 ADC B ; 1363 47 MOV B,A ;SAVE POSSIBLE CARRY BIT IN (B) 1364 7E MOV A,M ; 1365 0F RRC ; 1366 E60F ANI 0FH ; 1368 80 ADD B ; 1369 47 MOV B,A ; 136A 210E00 LXI H,14 ; 136D 19 DAD D ; 136E 7E MOV A,M ;(A) <-- (BYTE14) 136F 87 ADD A ;*2 1370 87 ADD A ; *4 1371 87 ADD A ; *8 1372 87 ADD A ; *16 1373 F5 PUSH PSW ;SAVE FLAGS FOR POSSIBLE OVERFLOW 1374 80 ADD B ; 1375 47 MOV B,A ;(B) <-- (BYTE14)SHL4+(BYTE12).AND.1FHSHR1 ;HIGH ORDER BYTE 1376 F5 PUSH PSW ; 1377 E1 POP H ;(L) <-- FLAGS 1378 7D MOV A,L ;(A) <-- FLAGS 1379 E1 POP H ;(L) <-- FLAGS AGAIN 137A B5 ORA L ;.OR. THEM TOGETHER 137B E601 ANI 01H ;MASK OFF ALL BUT CARRY BIT IN ;OVERFLOW BYTE. 137D C9 RET ; ; ; SET FILE SIZE ; ; SEE NOTES AT HEAD OF BDOS COMMAND #35 ; 137E 0E0C FSIZE: MVI C,0CH ;COMPUTE FILE SIZE 1380 CDB80E CALL SERCHF ;SEARCH FOR FIRST OCCURENCE OF FILE NAME 1383 2A440B LHLD ENTPAR ;ENTRY PARAMETER 1386 112100 LXI D,33 ; 1389 19 DAD D ; 138A E5 PUSH H ; 138B 72 MOV M,D ;(FCB+33) <-- 00H 138C 23 INX H ; 138D 72 MOV M,D ;(FCB+34) <-- 00H 138E 23 INX H ; 138F 72 MOV M,D ;(FCB+35) <-- 00H 1390 CDF60D FSIZE1: CALL CHKBC1 ;CHECK CONTENTS OF (BLCTR1) 1393 CAB813 JZ FSIZE3 ;EXIT LOOP- NO FILE NAME MATCH 1396 CD5F0D CALL DIRPTR ;(HL) <-- (DIRBPT) + (DIROFF) 1399 110F00 LXI D,15 ;OFFSET TO RECORD COUNTER 139C CD5113 CALL RNDPAR ;GET ABSOLUTE SECTOR NUMBER IN (A)(B)(C) 139F E1 POP H ; 13A0 E5 PUSH H ; ; ; IF (A)(B)(C) > (FCB35)(FCB34)(FCB33) THEN \ ; (FCB35)(FCB34)(FCB33) <-- (A)(B)(C) ; 13A1 5F MOV E,A ; 13A2 79 MOV A,C ; CP/M RMAC ASSEM 1.1 #082 BODY OF CPM (CCP/BDOS) 17 DEC 84 13A3 96 SUB M ; 13A4 23 INX H ; 13A5 78 MOV A,B ; 13A6 9E SBB M ; 13A7 23 INX H ; 13A8 7B MOV A,E ; 13A9 9E SBB M ;(A)(B)(C) - (FCB35)(FCB34)(FCB33) 13AA DAB213 JC FSIZE2 ; 13AD 73 MOV M,E ;(FCB33) <-- LOW ORDER BYTE 13AE 2B DCX H ; 13AF 70 MOV M,B ;(FCB34) <-- HIGH ORDER BYTE 13B0 2B DCX H ; 13B1 71 MOV M,C ;(FCB35) <-- OVERFLOW BYTE 13B2 CDCD0E FSIZE2: CALL SERCHN ;SEARCH FOR NEXT OCCURENCE OF FILE NAME 13B5 C39013 JMP FSIZE1 ; ; 13B8 E1 FSIZE3: POP H ; 13B9 C9 RET ; ; ; BDOS COMMAND #36....SET RANDOM RECORD LENGTH ; ; THIS PIECE OF CODE AUTOMATICALLY PRODUCES THE ; RANDOM RECORD POSITION OF A FILE THAT HAS BEEN ; READ OR WRITTEN TO UP TO THIS POINT. ; 13BA 2A440B COM36: LHLD ENTPAR ;ENTRY PARAMETER 13BD 112000 LXI D,32 ;OFFSET TO RANDON R/W COUNTER 13C0 CD5113 CALL RNDPAR ;GET ABSOLUTE SECTOR NUMBER OF ;CURRENT SECTOR NUMBER IN (A)(B)(C) 13C3 212100 LXI H,33 ; 13C6 19 DAD D ; 13C7 71 MOV M,C ;(FCB33) <-- LOW ORDER BYTE 13C8 23 INX H ; 13C9 70 MOV M,B ;(FCB34) <-- HIGH ORDER BYTE 13CA 23 INX H ; 13CB 77 MOV M,A ;(FCB35) <-- OVERFLOW BYTE 13CC C9 RET ; ; ; BDOS COMMAND #14....SELECT DISK DRIVE ; 13CD 3AD415 COM14: LDA PARAM1 ;GET THE SELECTED DISK DRIVE NUMBER 13D0 21430B LXI H,CURDSK ; 13D3 BE CMP M ;COMPARE TO CURRENT DISK NUMBER 13D4 C8 RZ ;RETURN IF NO CHANGE NEEDED 13D5 77 MOV M,A ;ELSE SET (CURDSK) TO NEW DRIVE ; ; HERE WE HAVE THE WAY THAT DISKS ARE LOGGED, ; 13D6 2AAD15 LOGIN: LHLD LOGVEC ;LOG IN VECTOR 13D9 3A430B LDA CURDSK ; 13DC 4F MOV C,A ; 13DD CDEB0C CALL SHRHLC ;SHIFT (HL) RIGHT PER COUNT IN (C) 13E0 E5 PUSH H ; 13E1 EB XCHG ; 13E2 CD5A0B CALL SETDSK ;SET UP DISK PARAMETERS 13E5 E1 POP H ; CP/M RMAC ASSEM 1.1 #083 BODY OF CPM (CCP/BDOS) 17 DEC 84 13E6 CC480B CZ SELERR ;DISK SELECT ERROR 13E9 7D MOV A,L ;LOG IN BIT IN LSB(A) 13EA 1F RAR ;CHECK TO SEE IF ON MAP 13EB D8 RC ;OK- DISK ALREADY LOGGED IN 13EC 2AAD15 LHLD LOGVEC ;LOG IN VECTOR 13EF 4D MOV C,L ; 13F0 44 MOV B,H ; 13F1 CD0C0D CALL SETVEC ;NEW DISK- PUT ON THE MAP 13F4 22AD15 SHLD LOGVEC ;LOG IN VECTOR ; ; SECOND HALF OF DISK LOG-IN PROCEDURES ; 13F7 2AC815 LOGIN1: LHLD ALLOC0 ; 13FA 44 MOV B,H ;PUT THE NUMBER OF ALLOCATION BYTES 13FB 4D MOV C,L ; INTO (BC) 13FC 2ABD15 LHLD DALLOC ;POINT TO START OF ALLOCATION BLOCK 13FF 3600 LOGIN2: MVI M,00H ;ZERO OUT THE ALLOCATION BLOCK 1401 23 INX H ; 1402 0B DCX B ; 1403 78 MOV A,B ; 1404 B1 ORA C ; 1405 C2FF13 JNZ LOGIN2 ; ; 1408 2AC815 LHLD ALLOC0 ;SIZE OF ALLOCATION BLOCK 140B EB XCHG ; 140C 2ABD15 LHLD DALLOC ; 140F 73 MOV M,E ; 1410 23 INX H ; 1411 72 MOV M,D ;(DALLOC) <-- ((ALLOC0)) 1412 CDA20B CALL SETDIR ; 1415 2AB115 LHLD DWORD1 ; 1418 3603 MVI M,03H ; 141A 23 INX H ; 141B 3600 MVI M,00H ;((DWORD1)) <-- 0003H 141D CDFF0D CALL SETBC1 ;SET (BLCTR1) <-- -1 1420 0EFF LOGIN3: MVI C,0FFH ; 1422 CD060E CALL GETDIR ;GET DIRECTORY SECTOR 1425 CDF60D CALL CHKBC1 ;CHECK CONTENTS OF (BLCTR1) 1428 C8 RZ ; 1429 CD5F0D CALL DIRPTR ;(HL) <-- (DIRBPT) + (DIROFF) 142C 3EE5 MVI A,0E5H ; 142E BE CMP M ;CHECK FOR UNUSED DIRECTORY ENTRY 142F CA2014 JZ LOGIN3 ;NOT IN USE- GO LOOK FOR ANOTHER ; ; CHECK TO SEE IF FIRST BYTE OF FCB MATCHES ; THE CURRENT USER NUMBER. ; 1432 3A420B LDA USERNO ; 1435 BE CMP M ; 1436 C24414 JNZ LOGIN4 ;NO MATCH- SKIP IT 1439 23 INX H ;MATCH- CHECK TO SEE IF THIS IS SOME 143A 7E MOV A,M ; SORT OF TEMPORARY FILE OF THE 143B D624 SUI '$' ; $$$.EXT VARIETY 143D C24414 JNZ LOGIN4 ; NO MATCH- JUST SKIP 1440 3D DCR A ;MATCH- SO MAKE RETURN PARAMETER= 0FFH 1441 32460B STA RETPAR ;RETURN PARAMETER CP/M RMAC ASSEM 1.1 #084 BODY OF CPM (CCP/BDOS) 17 DEC 84 1444 0E01 LOGIN4: MVI C,01H ; 1446 CD690E CALL BLKMAP ; 1449 CD8D0D CALL SWB1D1 ; 144C C32014 JMP LOGIN3 ;LOOP ; ; SET UP THE DISK PARAMETERS ; ; ALL BDOS COMMANDS THAT USE THE DISKS MUST ; MAKE A PASS THROUGH THIS SUBROUTINE ; ; NOTE: ; THE DIGITAL RESEARCH DOCUMENTATION DOES ; NOT MENTION WHAT IS DONE WITH THE USER ; NUMBER. WELL HERE IT IS..... ; THE USER NUMBER IS PUT INTO THE FIRST ; BYTE OF THE DIRECTORY ENTRY. USER 0 ; IS THEREFORE COMPATIBLE WITH CP/M 1.4 ; BUT HIGHER USER NUMBERS ARE NOT. ; TRY CREATING A DUMMY FILE WITH VARIOUS ; USER NUMBERS, THEN INSPECTING THE ; DIRECTORY TRACK WITH SPAT. ; THIS PIECE OF CODE PUTS THE CURRENT ; USER NUMBER INTO THE START OF THE ; FILE CONTROL BLOCK SO THAT A MATCH CAN ; BE MADE DURING DIRECTORY SEARCHES. ; 144F 3EFF SETUP: MVI A,0FFH ;SET FLAG TO TELL BDOS2 THAT 1451 32DC15 STA SETUPF ; THE DISKS HAVE BEEN USED 1454 2A440B LHLD ENTPAR ;(HL) <-- ENTRY PARAMETER 1457 7E MOV A,M ;GET THE DISK NUMBER FROM FCB 1458 E61F ANI 1FH ;DISK NUMBER TO BE IN RANGE OF ;0 TO 1FH. I.E. DRIVES A THROUGH P 145A 3D DCR A ; 145B 32D415 STA PARAM1 ;STORE IT FOR SELDSK 145E FE1E CPI 1EH ; 1460 D27314 JNC SETUP1 ;SKIP OVER- ACCESSING LOGGED IN DISK ; 1463 3A430B LDA CURDSK ;SAVE CURRENT DISK NUMBER IN 1466 32DD15 STA LOGDSK ;LOGDSK FOR RESTORING ON EXIT 1469 7E MOV A,M ;GET DISK NUMBER FROM FCB AGAIN 146A 32DE15 STA DISKNO ;SAVE IT ; ; THE REASON FOR SETTING THE UPPER 3 BITS OF ; (FCB+12) WITH THE UPPER 3 BITS OF THE DRIVE ; NUMBER BROUGHT IN IN THE ENTRY PARAMETER IS ; NOT DOCUMENTED. THIS MAY BE SOME SORT OF ; PASSWORD SECURITY SYSTEM ; 146D E6E0 ANI 0E0H ;KEEP UPPER 3 BITS 146F 77 MOV M,A ; AND PUT THEM BACK IN FCB 1470 CDCD13 CALL COM14 ;SELECT DISK DRIVE 1473 3A420B SETUP1: LDA USERNO ;GET THE USER NUMBER 1476 2A440B LHLD ENTPAR ;GET THE ENTRY PARAMETER ;WHICH WAS ALREADY THERE ;ANOTHER EXAMPLE OF REDUNDANCY 1479 B6 ORA M ;COMBINE USER NUMBER W/ (FCB) CP/M RMAC ASSEM 1.1 #085 BODY OF CPM (CCP/BDOS) 17 DEC 84 147A 77 MOV M,A ;MOVE INTO FIRST BYTE OF FCB 147B C9 RET ; ; ; BDOS COMMAND #12....RETURN THE CURRENT CP/M VERSION ; ; THIS REPLACES A RETURN WITH 00 IN CP/M 1.4 ; AND EARLIER. THIS IS USED BY CBASIC2 TO ; DETERMINE IF RANDOM READ/WRITE IS POSSIBLE. ; 147C 3E22 COM12: MVI A,VER*16+REL ;LOAD VERSION NUMBER 147E C3020B JMP EXIT1 ;MOVE IT TO RETURN PARAMETER & EXIT ; ; BDOS COMMAND #13....RESET DISK SYSTEM ; 1481 210000 COM13: LXI H,0000H ; 1484 22AB15 SHLD ROWORD ;CLEAR READ ONLY WORD 1487 22AD15 SHLD LOGVEC ; AND LOG IN VECTOR 148A AF XRA A ;CLEAR CURRENT DISK 148B 32430B STA CURDSK ; 148E 218000 LXI H,DDMA ;SET TO DEFAULT DMA ADDRESS 1491 22AF15 SHLD CURDMA ; 1494 CDDB0D CALL DIRD1 ; 1497 C3D613 JMP LOGIN ;LOG-IN THE DISK & EXIT ; ; BDOS COMMAND #14....OPEN FILE ; 149A CD730D COM15: CALL ZRFCTR ;ZERO OUT FCB COUNTER 149D CD4F14 CALL SETUP ;SET UP DISK PARAMETERS 14A0 C3FD0F JMP OPENF ;OPEN FILE & EXIT ; ; BDOS COMMAND #14....CLOSE FILE ; 14A3 CD4F14 COM16: CALL SETUP ;SET UP DISK PARAMETERS 14A6 C34E10 JMP CLOSEF ;CLOSE FILE & EXIT ; ; BDOS COMMAND #17....SEARCH FOR FIRST OCCURENCE ; OF FILENAME.EXT IN DIRECTORY ; 14A9 0E00 COM17: MVI C,00H ; 14AB EB XCHG ; 14AC 7E MOV A,M ; 14AD FE3F CPI '?' ;FIRST FCB BYTE A WILDCARD? 14AF CAC014 JZ COM17A ; 14B2 CDA70C CALL FCB12 ; (HL) <-- FCB + 12 , EXT BYTE PTR 14B5 7E MOV A,M ; 14B6 FE3F CPI '?' ;EXTENT BYTE A WILDCARD? 14B8 C4730D CNZ ZRFCTR ;ZERO OUT FCB COUNTER 14BB CD4F14 CALL SETUP ;SET UP DISK PARAMETERS 14BE 0E0F MVI C,0FH ;15 BYTE SEARCH 14C0 CDB80E COM17A: CALL SERCHF ;SEARCH FOR FIRST OCCURENCE OF FILE NAME 14C3 C3EA0D JMP MOVSEC ;SECTOR MOVE ((CURDMA)) <-- ((DIRBPT)) ; ; BDOS COMMAND #18....SEARCH FOR NEXT OCCURERENCE ; OF FILENAME.EXT IN DIRECTORY. ; ; PICKS UP POINTER TO FILE CONTROL BLOCK LEFT BY CP/M RMAC ASSEM 1.1 #086 BODY OF CPM (CCP/BDOS) 17 DEC 84 ; THE FIRST SEARCH. IF THERE HAS BEEN A USE OF ; THE DIRECTORY SEARCH BETWEEN THE FIRST CALL AND ; THIS ONE, WATCH OUT...CP/M IS NOT REENTRANT SO ; YOU MAY NOT HAVE WHAT YOU THINK YOU HAVE. ; OF PARTICULAR DANGER ARE READ AND WRITE OPERATIONS ; TO ANOTHER FILE BECAUSE THEY MAY HAVE TO OPEN UP ; NEW DIRECTORY EXTENTS WITHOUT YOUR KNOWING ABOUT IT. ; 14C6 2AD715 COM18: LHLD SRCHFP ;SEARCH FCB POINTER, SET BY SERCHF 14C9 22440B SHLD ENTPAR ;ENTRY PARAMETER 14CC CD4F14 CALL SETUP ; 14CF CDCD0E CALL SERCHN ;SEARCH FOR NEXT OCCURENCE OF FILE NAME 14D2 C3EA0D JMP MOVSEC ;SECTOR MOVE ((CURDMA)) <-- ((DIRBPT)) ; ; BDOS COMMAND #19....DELETE A FILE FROM THE DISK ; 14D5 CD4F14 COM19: CALL SETUP ;SET UP DISK PARAMETERS 14D8 CD480F CALL DELETE ;GO DELETE THE FILE 14DB C3A10E JMP EXIT3 ;MOVE SEARCH RESULT TO RETURN ;VALUE & EXIT ; ; BDOS COMMAND #20....READ SECTOR FROM DISK TO MEMORY ; 14DE CD4F14 COM20: CALL SETUP ;SET UP DISK PARAMETERS 14E1 C36811 JMP RDSEQ ;READ SEQUENTIAL FILE & EXIT ; ; BDOS COMMAND #21....WRITE SECTOR FROM MEMORY TO DISK ; 14E4 CD4F14 COM21: CALL SETUP ;SET UP DISK PARAMETERS 14E7 C3AA11 JMP WRSEQ ;WRITE SEQUENTIAL FILE & EXIT ; ; BDOS COMMAND #22....CREATE A NEW ENTRY IN DIRECTORY ; 14EA CD730D COM22: CALL ZRFCTR ;ZERO OUT FCB COUNTER 14ED CD4F14 CALL SETUP ;SET UP DISK PARAMETERS 14F0 C3D010 JMP MAKEF ;MAKE NEW DIRECTORY ENTRY & EXIT ; ; BDOS COMMAND #23....RENAME EXISTING FILE ; 14F3 CD4F14 COM23: CALL SETUP ;SET UP DISK PARAMETERS 14F6 CDC20F CALL RENAME ;DO THE RENAMING 14F9 C3A10E JMP EXIT3 ;PUT MARKER IN RETURN VALUE & EXIT ; ; BDOS COMMAND #24....RETURN LOG-IN VECTOR ; ; LOG-IN VECTOR IS A 16 BIT WORD THAT SHOWS WHICH ; DRIVES HAVE BEEN LOGGED IN. LSB= DRIVE A, ; MSB= DRIVE P. ; 14FC 2AAD15 COM24: LHLD LOGVEC ;GET LOG IN VECTOR IN (HL) 14FF C32715 JMP COM31A ;PUT IT IN RETURN VALUE & EXIT ; ; BDOS COMMAND #25....RETURN CURRENT DISK NUMBER ; 1502 3A430B COM25: LDA CURDSK ;GET CURRENT DISK NUMBER 1505 C3020B JMP EXIT1 ;PUT IT IN RETURN VALUE & EXIT CP/M RMAC ASSEM 1.1 #087 BODY OF CPM (CCP/BDOS) 17 DEC 84 ; ; BDOS COMMAND #26....SET CURRENT DMA ADDRESS ; 1508 EB COM26: XCHG ;MOVE ADDRESS INTO (HL) 1509 22AF15 SHLD CURDMA ;STORE IT 150C C3DB0D JMP DIRD1 ;GO SET ADDRESS VIA BIOS CALL ; ; BDOS COMMAND #27....INTEROGATE DISK ALLOCATION ; ; BRINGS BACK ADDRESS OF START OF DISK ALLOCATION ; MAP. GENERALLY USED FOR DISK STATUS PROGRAMS ; 150F 2ABD15 COM27: LHLD DALLOC ;GET POINTER TO ALLOCATION MAP 1512 C32715 JMP COM31A ;STORE IN RETURN VALUE & EXIT ; ; BDOS COMMAND #29....GET DISK WRITE PROTECT STATUS WORD ; ; BRINGS BACK 16 BIT WORD. FORMAT IS SIMILAR TO ; LOG-IN VECTOR EXCEPT THAT A SET BIT MEANS ; THAT THE DISK IS READ ONLY ; 1515 2AAB15 COM29: LHLD ROWORD ;* GET R/O VECTOR ADDRESS 1518 C32715 JMP COM31A ;STORE IN RETURN VALUE & EXIT ; ; BDOS COMMAND #30....SET FILE ATTRIBUTES ; ; USED TO SET A FILE TO READ ONLY, OR TO MAKE ; A SYSTEM FILE INVISIBLE TO DIRECTORY READS ; ; ON ENTRY THE FILE CONTROL BLOCK CONTAINS THE ; FILENAME.EXT EXACTLY AS IT WILL GO INTO THE ; DIRECTORY. THIS MEANS THAT THE MSB OF BYTES ; T1 AND T2 MUST BE SET FOR R/O AND SYSTEM FILES. ; A FILE OF THE SAME NAME & EXT MUST ALREADY ; EXIST IN MEMORY. ; 151B CD4F14 COM30: CALL SETUP ;SET UP DISK PARAMETERS 151E CDE70F CALL ATTRIB ;GO SET ATTRIBUTES 1521 C3A10E JMP EXIT3 ;STORE FLAG IN RETURN VALUE & EXIT ; ; BDOS COMMAND #31....GET DISK PARAMETER ADDRESS ; ; BRINGS BACK POINTER TO START OF 15 BYTE ; DISK PARAMETER BLOCK. ; 1524 2AB915 COM31: LHLD DPBLK ;* GET DISK PARAMETER ADDRESS 1527 22460B COM31A: SHLD RETPAR ;STORE IN RETURN PARAMETER 152A C9 RET ;EXIT ; ; BDOS COMMAND #32....SET/GET USER NUMBER ; ; ENTRY PARAMETER IS CHECKED AND IF IT IS 0FFH ; THE CURRENT USER NUMBER IS RETURNED, ELSE ; VALUE OF THE ENTRY PARAMETER IS SET AS THE ; CURRENT USER NUMBER. ; CP/M RMAC ASSEM 1.1 #088 BODY OF CPM (CCP/BDOS) 17 DEC 84 152B 3AD415 COM32: LDA PARAM1 ;GET THE ENTRY PARAMETER 152E FEFF CPI 0FFH ;CHECK IT 1530 C23915 JNZ SETUSR ;NOT 0FFH- GO SET THE NUMBER 1533 3A420B LDA USERNO ;IT IS 0FFH- GET THE USER NUMBER 1536 C3020B JMP EXIT1 ;PUT IN RETURN VALUE & EXIT ; 1539 E61F SETUSR: ANI 1FH ;NUMBER MUST BE IN THE RANGE 153B 32420B STA USERNO ;OF 00 TO 31 153E C9 RET ;EXIT ; ; BDOS COMMAND #33....READ RANDOM FILE ; ; ON ENTRY FCB BYTES 33 AND 34 CONTAIN SECTOR ; NUMBER IN THE RANGE OF 0 TO 65535. FILE ; MUST HAVE BEEN PREVIOUSLY OPENED FOR ; RANDOM READING. ; 153F CD4F14 COM33: CALL SETUP ;SET UP DISK PARAMETERS 1542 C33F13 JMP RDRAND ;GO READ THE SECTOR ; ; BDOS COMMAND #34....WRITE RANDOM FILE ; ; SAME AS ABOVE, EXCEPT THAT THE SECTOR ; IS WRITTEN TO. ; 1545 CD4F14 COM34: CALL SETUP ;SET UP DISK PARAMETERS 1548 C34813 JMP WRRAND ;GO WRITE THE SECTOR ; ; BDOS COMMAND #35....COMPUTE FILE SIZE ; ; BRINGS BACK THE NUMBER OF THE LAST SECTOR ; OF A FILE IN FCB BYTES 33 & 34. USED TO ; CHANGE FROM SEQUENTIAL TO RANDOM WRITING ; OF A FILE AFTER PART OF THE FILE HAS BEEN ; SEQUENTIALLY WRITTEN. ; 154B CD4F14 COM35: CALL SETUP ;SET UP DISK PARAMETERS 154E C37E13 JMP FSIZE ;GO COMPUTE FILE SIZE ; ; BDOS COMMAND #37....UNDOCUMENTED COMMAND ; ; THIS COMMAND UNLOGS AND UNPROTECTS SELECTED ; DISK DRIVES. ON ENTRY A 16 BIT WORD WITH ; BITS SET CORRESPONDING TO THE DRIVES TO BE ; CLEARED IS USED TO CLEAR THE CORRESPONDING ; BITS FROM THE LOG-IN AND R/OJ WORDS ; 1551 2A440B COM37: LHLD ENTPAR ;GET LOG-OFF WORD 1554 7D MOV A,L ;COMPLEMENT IT 1555 2F CMA ; 1556 5F MOV E,A ; 1557 7C MOV A,H ; 1558 2F CMA ; 1559 2AAD15 LHLD LOGVEC ;GET LOG IN VECTOR 155C A4 ANA H ;.AND. OUT THE LOG-IN WORD 155D 57 MOV D,A ; CP/M RMAC ASSEM 1.1 #089 BODY OF CPM (CCP/BDOS) 17 DEC 84 155E 7D MOV A,L ; 155F A3 ANA E ; 1560 5F MOV E,A ;PLACE RESULT IN (DE) 1561 2AAB15 LHLD ROWORD ;GET THE WRITE PROTECT STATUS WORD 1564 EB XCHG ;PUT IT IN (DE) 1565 22AD15 SHLD LOGVEC ;STORE THE UPDATED LOG IN VECTOR 1568 7D MOV A,L ;.AND. IT WITH THE R/O WORD TO 1569 A3 ANA E ; REMOVE ANY LOGGED OUT BITS 156A 6F MOV L,A ; 156B 7C MOV A,H ; 156C A2 ANA D ; 156D 67 MOV H,A ; 156E 22AB15 SHLD ROWORD ;STORE UPDATED R/O WORD 1571 C9 RET ;EXIT ; ; EXIT POINT FOR ALL BDOS COMMANDS ; ; CHECK IS MADE AS TO WHETHER DISK WAS USED DURING ; THE BDOS CALL. IF IT WAS, THE APPROPRIATE DISK ; NUMBER IS PUT BACK INTO THE FIRST BYTE OF THE ; FILE CONTROL BLOCK. ; THE RETURN PARAMETER IS PICKED UP AND PLACED IN ; BOTH (HL) AND (A) & (B). THE USE OF (A) & (B) IS ; DONE TO MAINTAIN COMPATABILITY WITH CP/M 1.4 ; 1572 3ADC15 BDOS2: LDA SETUPF ;WAS DISK USED? 1575 B7 ORA A ; 1576 CA8F15 JZ BDOS3 ;NO- SKIP OVER ; 1579 2A440B LHLD ENTPAR ;POINT TO START OF FCB 157C 3600 MVI M,00H ;SET TO CURRENT DRIVE 157E 3ADE15 LDA DISKNO ; AHA, BUT WAS IT A TRANSIENT DRIVE? 1581 B7 ORA A ; 1582 CA8F15 JZ BDOS3 ;NO- SKIP OVER 1585 77 MOV M,A ;YES- SET BACK TO CORRECT DRIVE 1586 3ADD15 LDA LOGDSK ;NOW GET LOGGED IN DRIVE NUMBER 1589 32D415 STA PARAM1 ; PUT IT IN PLACE FOR DISK CHANGE 158C CDCD13 CALL COM14 ;SELECT LOGGED-IN DISK DRIVE 158F 2A100B BDOS3: LHLD PSTACK ;RESTORE CALLING PROGRAM STACK POINTER 1592 F9 SPHL ; 1593 2A460B LHLD RETPAR ;GET RETURN PARAMETER IN (HL) 1596 7D MOV A,L ;ECHO IT IN (A) & (B) 1597 44 MOV B,H ; 1598 C9 RET ;GRAND EXIT FROM BDOS.......... ;...............BACK TO CALLER. ; ; BDOS COMMAND #40....UNDOCUMENTED COMMAND ; ; EXACT USE HAS NOT BEEN DETERMINED AS YET, ; BUT IT SEEMS TO BE SOME SORT OF RANDOM ; WRITE. ; ....MUST LOOK INTO THIS FURTHER. ; 1599 CD4F14 COM40: CALL SETUP ;SET UP DISK PARAMETERS 159C 3E02 MVI A,02H ;SET SERNFL TO 02 (ALL OTHER ;TIMES IT IS SET TO 00 OR 0FFH) CP/M RMAC ASSEM 1.1 #090 BODY OF CPM (CCP/BDOS) 17 DEC 84 159E 32D315 STA SERNFL ;SEQUENTIAL/RANDOM I/O FLAG 15A1 0E00 MVI C,00H ;WRITE FLAG 15A3 CDB312 CALL SETRN1 ;SET UP THE RANDOM PARAMETERS 15A6 CCAF11 CZ WRSEQ1 ;WRITE A SECTOR 15A9 C9 RET ; ; ; END OF PROGRAM AREA......... ; ..........START OF PARAMETER ; STORAGE AREA #2............. ; 15AA E5 DMYFCB: DB 0E5H ;DUMMY FCB- USED FOR SEARCHING FOR ;UNUSED DIRECTORY SLOTS 15AB 0000 ROWORD: DW 0000H ;READ ONLY DISK STATUS WORD 15AD 0000 LOGVEC: DW 0000H ;LOG IN VECTOR 15AF 8000 CURDMA: DW DDMA ;CURRENT DMA ADDRESS. INTIALLY = DDMA 15B1 0000 DWORD1: DW 0000H ; 15B3 0000 DWORD2: DW 0000H ; 15B5 0000 DWORD3: DW 0000H ; 15B7 0000 DIRBPT: DW 0000H ;DIRECTORY BUFFER POINTER 15B9 0000 DPBLK: DW 0000H ;DISK PARAMETER BLOCK POINTER 15BB 0000 DIRCRC: DW 0000H ;DIRECTORY CHECKSUM BLOCK POINTER 15BD 0000 DALLOC: DW 0000H ;ALLOCATION BIT MAP POINTER ; ; DISK PARAMETER BLOCK ; Moved into place when disk is logged in ; 15BF 0000 SECTRS: DW 0000H ;SECTORS PER TRACK 15C1 00 BLSHFT: DB 00H ;BLOCK SHIFT FACTOR 15C2 00 BLMASK: DB 00H ;DISK BLOCK MASK 15C3 00 NLMASK: DB 00H ;NULL BLOCK MASK 15C4 0000 DSKSIZ: DW 0000H ;DISK SIZE, # OF 1K BLOCKS -1 15C6 0000 DIRMAX: DW 0000H ;MAX NUMBER OF ENTRIES IN DIRECTORY 15C8 0000 ALLOC0: DW 0000H ;SIZE OF ALLOCATION BLOCK 15CA 0000 CHKSIZ: DW 0000H ;NUMBER OF DIRECTORY SECTORS TO BE CHECKED 15CC 0000 DIRTRK: DW 0000H ;DIRECTORY TRACK NUMBER ; 15CE 0000 SECTBL: DW 0000H ;VECTOR TO SECTOR TRANSLATION TABLE 15D0 00 MAKEFL: DB 00H ;MAKE-FILE FLAG 15D1 00 RDWRFL: DB 00H ;READ/WRITE FLAG 15D2 00 SRCHFL: DB 00H ;POINTER SET TO 0FFH BY SERCHF AND ;CLEARED TO 00 WHEN A FILE NAME MATCH ;HAS BEEN MADE 15D3 00 SERNFL: DB 00H ;SEQUENTIAL/RANDOM I/O FLAG ;SET 01 FOR SEQUENTIAL READ/WRITE ;SET 00 FOR RANDOM READ/WRITE ;SET 02 FOR UNDOCUMENTED COMMAND #40 15D4 00 PARAM1: DB 00H ;SET TO (E) ON ENTRY TO BDOS, THEN ;USED TO STORE DISK NUMBER 15D5 00 BLKOFF: DB 00H ;TEMPORARY STORAGE FOR OFFSET TO BLOCK ;NUMBER IN DIRECTORY DURING WRSEQ. ;POINTS TO BYTE(S) THAT CONTAIN THE ;CURRENT BLOCK NUMBER. WHEN THE 8TH ;SECTOR OF THE BLOCK HAS BEEN WRITTEN, ;BLKOFF IS INCREMENTED AND A NEW BLOCK ;SELECTED. 15D6 00 SRCHCT: DB 00H ;SEARCH COUNTER-NUMBER OF BYTES TO BE CP/M RMAC ASSEM 1.1 #091 BODY OF CPM (CCP/BDOS) 17 DEC 84 ;COMPARED BETWEEN THE FILE CONTROL ;BLOCK AND THE DIRECTORY ENTRY. THE ;COUNT IS SET ON ENTRY VIA SERCHF & ;PICKED UP FOR USE BY SERCHN 15D7 0000 SRCHFP: DW 0000H ;SEARCH FCB POINTER, SET BY SERCHF/SERCHN 15D9 0000 DW 0000H ;(NOT USED) 15DB 00 BIGDSK: DB 00H ;8" SD: 0FFH, LARGE CAP DISK: 00H 15DC 00 SETUPF: DB 00H ; 15DD 00 LOGDSK: DB 00H ; 15DE 00 DISKNO: DB 00H ; 15DF 00 RECCTR: DB 00H ;FILE RECORD COUNTER:: FCB + 15 15E0 00 EXTCTR: DB 00H ;FILE EXTENT COUNTER: FCB + 12 15E1 0000 CURREC: DW 0000H ;CURRENT RECORD:: FCB + 32 15E3 0000 SCNTR1: DW 0000H ;SECTOR COUNTER #1 15E5 0000 SCNTR2: DW 0000H ;SECTOR COUNTER #2 15E7 00 DIROFF: DB 00H ;DIRECTORY OFFSET 15E8 0000 BLCTR1: DW 0000H ;BLOCK COUNTER #1 15EA 0000 BLCTR2: DW 0000H ;BLOCK COUNTER #2 ; 15EC FINISH: END FBASE ;END OF SOURCE CODE