;************************************************************ ;* * ;* SINGLE DRIUE FILECOPY V80.1 11 FEB 80 * ;* WILL COPY FILES UP TO (11 K BYTES + BIAS) IN LENGTH * ;* ALL CONSOLE AND DISC I/O IS THROUGH BDOS CALL AT LOC 5 * ;* * ;************************************************************ ;* CP/M BDOS ADDRESSES RBOOT EQU 0 ; RE-BOOT CP/M BDOS EQU 5 ; BDOS CALL ENTRY FCB EQU 5CH ; DEFAULT FILE CONTROL BLOCK INBUF EQU 80H ; DEFAULT DMA ADDRESS ;* CP/M BDOS FUNCTIONS READF EQU 1 ; READ CONSOLE INTO (A) TYPEF EQU 2 ; WRITE CONSOLE FROM (E) INIT EQU 13 ; INITIALIZE DISC IN DRIUE A: OPEN EQU 15 ; OPEN FILE CLOS EQU 16 ; CLOSE FILE FIND EQU 17 ; FIND FILE IN DIRECTORY DELE EQU 19 ; DELETE FILE READ EQU 20 ; READ FILE WRIT EQU 21 ; WRITE FILE MAKE EQU 22 ; CREATE FILE OIRECTORY ENTRY ORG 0100H ; TPA PROGRAM START ADDRESS JMP START ; GO TO PROGRAM START ;*CONSOLE I/O THROUGH BOOS CALL CI PUSH H ; SAVE REGISTERS PUSH D PUSH B MVI C,READF ; READ FUNCTION CALL BDOS ; RETURN CHAR IN (A) POP B ; RESTORE OTHER REGISTERS POP D POP H RET CO PUSH H PUSH D PUSH B MOV E,A ; MOVE PRINT CHAR TO (E) MVI C,TYPEF CALL BDOS POP B POP D POP H RET CCRLF MVI A,0DH ; CR LF TO CONSOLE CALL CO MVI A,0AH JMP CO MSGXP POP H ; OUTPUT MESSAGE AND RETURN MSGX1 MOV A,M ; THROUGH INDEX (H,L) CPI 0 ; TEXT TERMINATOR = 0 JZ MSGEX CALL CO INX H JMP MSGX1 MSGEX INX H ; POINT TO TEXT + 1 PCHL ; AND RETURN THERE ;* FILECOPY CONSOLE MESSAGE SUBROUTINES RDMSG CALL CCRLF ; PROMPT FOR READ DISC CALL MSGXP DB 'READ DISC IN DRIVE. THEN CR ' DB 0 RDMS1 CALL CI ; GET RESPONSE CPI 'X' ; ALLOW EXIT JZ RBOOT ; BACK TO CP/M CPI 0DH ; ACCEPT CR ONLY JNZ RDMS1 CALL CCRLF ; ACKNOWLEDGE RET ; AND RETURN WRMSG CALL CCRLF ; PROMPT FOR WRITE DISC CALL MSGXP DB 'WRITE DISC IN DRIVE. THEN CR ' DB 0 WRMS1 CALL CI CPI 'X' JZ RBOOT CPI 0DH JNZ WRMS1 CALL CCRLF RET RDERR CALL CCRLF ; SHOW READ ERROR CALL MSGXP DB 'READ ERROR! ENTER X TO ABORT ' DB 0DH,0AH DB ' CR TO IGNORE ' DB 0 RDER1 CALL CI ; ACCEPT CR OR X CPI 'X' JZ EXIT CPI 0DH RZ ; RETURN MEANS IGNORE JMP RDER1 ; READ ERROR WRERR CALL CCRLF ; SHOW WRITE ERROR CALL MSGXP DB 'PERMANENT WRITE ERROR! ' DB 0 EXIT CALL MSGXP DB 'BACK TO CP/M? ' DB 0 WRER1 CALL CI ; WAIT FOR CR OR X CPI 0DH JZ RBOOT CPI 'X' JZ RBOOT JNZ WRER1 ; AS ONLY LEGAL RESPONSE ;* BEGIN FILECOPY PROGRAM START CALL CCRLF ; SIGN ON MESSAGE CALL MSGXP DB 'SINGLE DRIVE FILECOPY V80.1 11 FEB 80' DB 0DH,0AH DB 0 CALL RDMSG ; PROMT FOR READ DISC LXI D,FCB ; LOOK FOR FILE MVI C,FIND ; BEFORE GOING AHEAD CALL BDOS CPI 255 ; DOES FILE EXIST? JNZ RUN ; YES. READ IT CALL CCRLF ; NO. GIVE UP CALL MSGXP DB 'FILE DOES NOT EXIST! ' DB 0 JMP EXIT ; REBOOT CP/M RUN LXI H,FCB ; SET UP FCB'S FOR LXI D,RFCB ; READ AND WRITE MVI C,16 RUN1 MOV A,M STAX D INX H INX D DCR C JNZ RUN1 LXI H,FCB LXI D,WFCB MVI C,16 RUN2 MOV A,M STAX D INX H INX D DCR C JNZ RUN2 LXI H,BUFFR ; INITIALIZE POINTER SHLD HSAVE ; INTO BUFFER XRA A ; ZERO RECORD COUNTS STA ASAVE STA RFCBN STA WFCBN ;* READ THE FILE INTO RAM RFILE LXI D,RFCB ; USE READ FCB MVI C,OPEN ; AND OPEN THE FILE CALL BDOS CPI 255 ; ERROR? JNZ RFIL1 CALL CCRLF CALL MSGXP ; YES. SHOW IT DB 'UNABLE TO OPEN FILE! ' DB 0 JMP EXIT ; AND ABORT RFIL1 LXI D,RFCB ; READ A RECORD MVI C,READ CALL BDOS CPI 0 ; GOOD READ? JZ RFIL2 ; YES. STORE IT CPI 1 ; OR END OF FILE? JZ WFILE ; YES. WRITE IT CALL RDERR ; NO. SHOW ERROR RFIL2 LHLD HSAVE ; STORE THE RECORD LXI D,INBUF MVI C,80H RFIL3 LDAX D MOV M,A INX H INX D DCR C JNZ RFIL3 SHLD HSAVE ; AND NEXT ADDRESS LDA ASAVE ; COUNT THE RECORO INR A STA ASAVE LDA 7 ; ANY MEMORY LEFT? DCR A CMP H JNZ RFIL1 ; YES. KEEP READING CALL CCRLF ; NO. ABORT CALL MSGXP DB 'FILE IS TOO BIG! ' DB 0 JMP EXIT ;* WRITE THE FILE ONTO DISC WFILE CALL WRMSG ; PROMPT FOR WRITE DISC MVI C,INIT ; INITIALIZE DISC FOR WRITE CALL BDOS LXI D,WFCB ; SEE IF FILE EXITS MVI C,FIND CALL BDOS ; WE CAN'T WRITE TWO! CPI 255 JZ WFIL1 ; NO. CONTINUE CALL CCRLF CALL MSGXP ; YES. ERASE OR ABORT? DB 'FILE ALREADY EXISTS. ENTER: X TO ABORT' DB 0DH,0AH DB ' CR TO ERASE IT ' DB 0 WAIT1 CALL CI CPI 'X' JZ RBOOT CPI 0DH JNZ WAIT1 LXI D,WFCB ; ERASE THE OLD FILE MVI C,DELE CALL BDOS WFIL1 LXI D,WFCB ; OPEN FILE FOR WRITE MVI C,MAKE CALL BDOS CPI 255 ; OPEN OK? JNZ WFIL2 ; YES. CONTINUE CALL CCRLF CALL MSGXP ; SHOW UNABLE TO OPEN DB 'OUT OF DIRECTORY SPACE !' DB 0 JMP EXIT WFIL2 LXI H,BUFFR ; INITIALIZE POINTER SHLD HSAVE WFIL3 LHLD HSAVE ; MOVE RECORD TO OUTPUT LXI D,INBUF ; BUFFER (SAME AS INPUT) MVI C,80H WFIL4 MOV A,M STAX D INX H INX D DCR C JNZ WFIL4 SHLD HSAVE ; SAVE NEXT ADDRESS LXI D,WFCB ; WRITE THE RECORD MVI C,WRIT CALL BDOS CPI 0 CNZ WRERR ; SHOW WRITE ERROR LDA ASAVE ; COUNT RECORD WRITTEN DCR A STA ASAVE JNZ WFIL3 ; AND WRITE ANOTHER LXI D,WFCB ; DONE. CLOSE THE FILE MVI C,CLOS CALL BDOS CALL CCRLF CALL MSGXP ; PROMPT FOR RE-BOOT DB 'ALL DONE! ' DB 0 JMP EXIT ; AND WE ARE ALL DONE! ;* RAM BUFFERS HSAVE DS 2 ; BUFFER ADDRESS STORE ASAVE DS 1 ; RECORD COUNT RFCB DS 33 ; READ FILE CONTROL BLOCK WFCB DS 33 ; WRITE FILE CONTROL BLOCK BUFFR DB 0 ; DATA BUFFER START RFCBN EQU RFCB+32 ; RECORD COUNTS. READ WFCBN EQU WFCB+32 ; AND WRITE END