; ; FROMHARD.ASM ver 1.2 ; by Keith Petersen, W8SDZ ; (revised 9/26/80) ; ;This program will transfer files from CP/M on hard disk ;to CP/M on floppy disk. (It can also be used for transfers ;from 8" floppy to 5-1/4" minifloppy.) ; ;To do this you must bring up the floppy CP/M as a small ;system (say 24k). The system location isn't important so ;long as it does not overwrite the larger system in use by ;the hard disk. It is assumed that the user's system allows ;both disk controller boards to be used without conflict. ; ; ; USING THIS PROGRAM ; ; 1 - Bring up the hard disk CP/M as a large system (eg. 56k). ; 2 - Cold boot the floppy CP/M. Log into the drive you will ; be transferring files to, then run this program. ; ;COMMANDS: ; FROMHARD filename.type ;gets file from default drive ; FROMHARD B:filename.type ;gets file from B: ; FROMHARD *.* ;gets all files ; FROMHARD B:*.* ;gets all files from B: ; ;All normal ambiguous file names are allowed. Files written to ;the floppy disk will go to the default drive. ; FALSE EQU 0 TRUE EQU NOT FALSE ; ;CONDITIONAL ASSEMBLY SWITCHES FOR CP/M VERSION ; (only one should be true) ; CPM14 EQU FALSE ;CP/M VERSION 1.4 CPM2 EQU TRUE ;CP/M VERSION 2.x ; ;OTHER CONDITIONAL ASSEMBLY SWITCHES ; DJ2D EQU FALSE ;TRUE IF BIG SYSTEM IS DISCUS 2D FLOPPY REPORT EQU FALSE ;TRUE TO REPORT READS AND WRITES ;(nice, but slows down transfers) ; ;EQUATES ; MSIZE EQU 56 ;PUT BIG SYSTEM MEMORY SIZE HERE ; IF CPM14 BIAS EQU (MSIZE-16)*1024 CCP EQU BIAS+2900H ;BASE OF CCP ENDIF ;CP/M 1.4 ; IF CPM2 AND (NOT DJ2D) BIAS EQU (MSIZE-20)*1024 CCP EQU BIAS+3400H ;BASE OF CCP ENDIF ;STANDARD CP/M 2.x ; IF CPM2 AND DJ2D BIAS EQU (MSIZE-20)*1024 CCP EQU BIAS+2D00H ;BASE DISCUS 2D CCP ENDIF ;CP/M 2.x ON DISCUS 2D ; SRC$BDOS EQU CCP+806H ;SENDING BDOS VECTOR ; BELL EQU 7 ;BELL CHARACTER TAB EQU 9 ;TAB CHARACTER CR EQU 0DH ;CARRIAGE RETURN LF EQU 0AH ;LINE FEED ; ;BDOS/CBIOS EQUATES ; WBOOT EQU 0 ;WARM BOOT ENTRY ADRS WRCON EQU 2 ;WRITE CHARACTER TO CONSOLE BDOS EQU 0005H ;THE RECEIVING BDOS VECTOR PRINT EQU 9 ;PRINT STRING (DE) UNTIL '$' OPEN EQU 15 ;OPEN FILE CLOSE EQU 16 ;CLOSE FILE SRCHF EQU 17 ;SEARCH DIR FOR FIRST OCCUR. SRCHN EQU 18 ;SEARCH DIR FOR NEXT OCCUR. DELETE EQU 19 ;ERASE FILE READ EQU 20 ;READ RECORD WRITE EQU 21 ;WRITE RECORD MAKE EQU 22 ;MAKE FILE STDMA EQU 26 ;SET DMA ADRS FCB EQU 5CH ;DEFAULT FILE CONTROL BLOCK FCBEXT EQU FCB+12 ;EXTENT BYTE IN FCB FCBRNO EQU FCB+32 ;RECORD NUMBER IN FCB ; NOERR EQU 0 ;NO ERROR EOF EQU 1 ;END OF FILE NTFND EQU 255 ;NOT FOUND NOMAKE EQU 255 ;CAN'T MAKE FILE BDCLOS EQU 255 ;BAD FILE CLOSE ; ; THIS IS THE START OF THE PROGRAM. ; ORG 100H ; START LDA FCB+1 CPI ' ' ;SEE IF FILENAME THERE JNZ SIGNON CALL ILPRT ;PRINT: DB CR,LF,'++NO FILE NAME SPECIFIED++',0 RET ;EXIT TO CP/M ; SIGNON: LXI SP,STACK ;SET STACK POINTER CALL ILPRT ;PRINT: DB CR,LF,'HARD DISK to FLOPPY',CR,LF DB 'multiple file transfer program',CR,LF,0 MORE: CALL MFNAME ;SEE IF FILE IS IN DIRECTORY JNC MOVNAM ;ANOTHER FILE FOUND, GET IT LDA MFFLG1 ;NOTHING FOUND, CHECK... ORA A ;... FIRST TIME FLAG JZ DONE ;AT LEAST ONE WAS FOUND CALL EXIT DB '++FILE NOT FOUND++$' ; DONE: CALL EXIT DB CR,LF,'DONE$' ; ;MOVE FILENAME FROM FCB TO FNAME AND PRINT IT ; MOVNAM: LXI H,FCB+1 LXI D,FNAME MVI B,8 ;8 CHARS IN FILE NAME CALL MOVER LXI H,FCB+9 LXI D,FNAME+9 MVI B,3 ;3 CHARS IN FILE TYPE CALL MOVER CALL ILPRT ;PRINT: DB CR,LF,'--> FILE: ' FNAME: DB 'XXXXXXXX.XXX' DB CR,LF,0 ; ;SAVE FIRST FCB FOR USE LATER AS DESTINATION FILE NAME MVI B,11 ;NUMBER OF CHARACTERS TO MOVE LXI H,FCB+1 ;...FROM FIRST FCB LXI D,NEWFCB+1 ;...TO NEWFCB (USE DEFAULT DRIVE) CALL MOVER ; ;OPEN THE SOURCE FILE LXI D,FCB MVI C,OPEN CALL SRC$BDOS CPI NTFND ;NOT FOUND? JNZ OPENOK CALL EXIT DB BELL DB '++CAN''T OPEN FILE ON SOURCE DISK++$' ; ;OPEN THE DESTINATION FILE ; OPENOK: CALL ILPRT ;PRINT: DB 'Opening file on destination disk',0 LXI D,NEWFCB MVI C,DELETE ;ERASE ANY OLD FILE CALL BDOS LXI D,NEWFCB MVI C,MAKE ;MAKE THE NEW ONE CALL BDOS CPI NOMAKE JNZ RDLOOP CALL EXIT DB BELL DB '++CANNOT CREATE FILE ON DESTINATION DISK++$' ; ;READ A SECTOR FROM BIG DISK ; RDLOOP: EQU $ ; IF REPORT CALL ILPRT ;PRINT: DB TAB,'Reading sector from source disk',0 ENDIF ;REPORT ; LXI D,80H MVI C,STDMA ;SET DMA TO 80H CALL SRC$BDOS LXI D,FCB MVI C,READ ;READ A RECORD CALL SRC$BDOS CPI NOERR JZ WRLOOP ;NO ERROR, GO WRITE SECTOR CPI EOF JZ TDONE ;END OF FILE, GO CLOSE IT CALL EXIT DB BELL DB '++READ ERROR ON SOURCE DISK++$' ; ;WRITE A SECTOR TO SMALL DISK ; WRLOOP: EQU $ ; IF REPORT CALL ILPRT ;PRINT: DB TAB,'Writing sector to destination disk',0 ENDIF ;REPORT ; LXI D,80H MVI C,STDMA ;SET DMA TO 80H CALL BDOS LXI D,NEWFCB MVI C,WRITE ;WRITE A RECORD CALL BDOS CPI NOERR JZ RDLOOP CALL EXIT DB BELL DB '++WRITE ERROR ON DESTINATION DISK++$' ; TDONE: CALL ILPRT ;PRINT: DB 'Closing file on destination disk now',0 LXI D,NEWFCB MVI C,CLOSE ;CLOSE DESTINATION FILE CALL BDOS CPI BDCLOS JNZ MORE ;ANOTHER FILE? CALL EXIT DB BELL DB '++BAD CLOSE ON DESTINATION DISK++$' ; ;PRINT MESSAGE THEN EXIT TO CP/M WARM BOOT ; EXIT: POP D MVI C,PRINT CALL BDOS JMP WBOOT ; ;INLINE PRINT ROUTINE ; ILPRT XTHL ;SAVE HL, GET MSG ; ILPLP MOV A,M ;GET CHAR CALL TYPE ;OUTPUT IT INX H ;POINT TO NEXT MOV A,M ;TEST ORA A ;..FOR END JNZ ILPLP MVI A,CR ;CARRIAGE RETURN CALL TYPE MVI A,LF ;LINE FEED CALL TYPE XTHL ;RESTORE HL, RET ADDR RET ;RET PAST MSG ; TYPE PUSH B PUSH D PUSH H MOV E,A ;CHAR TO E FOR CP/M MVI C,WRCON ;WRITE TO CONSOLE CALL BDOS POP H POP D POP B RET ; ;MULTI-FILE ACCESS SUBROUTINE. ALLOWS PROCESSING ;OF MULTIPLE FILES (I.E. *.ASM) FROM DISK. THIS ;ROUTINE BUILDS THE PROPER NAME IN THE FCB EACH ;TIME IT IS CALLED. CARRY IS SET IF NO MORE NAMES ;CAN BE FOUND. THE ROUTINE IS COMMENTED IN PSEUDO ;CODE, EACH PSEUDO CODE STATEMENT IS IN <<...>> ; MFNAME: ;<> MVI C,STDMA LXI D,80H CALL SRC$BDOS XRA A STA FCBEXT STA FCBRNO ;<> LDA MFFLG1 ORA A JZ MFN01 ;<> ;SAVE ORIG REQ LXI H,FCB LXI D,MFREQ MVI B,12 CALL MOVER LDA FCB STA MFCUR ;SAVE DISK IN CURR FCB ;<> LXI H,MFREQ LXI D,FCB MVI B,12 CALL MOVER MVI C,SRCHF LXI D,FCB CALL SRC$BDOS ;<> JMP MFN02 ; MFN01: ;<> LXI H,MFCUR LXI D,FCB MVI B,12 CALL MOVER MVI C,SRCHF LXI D,FCB CALL SRC$BDOS ;<> LXI H,MFREQ LXI D,FCB MVI B,12 CALL MOVER MVI C,SRCHN LXI D,FCB CALL SRC$BDOS ;<> MFN02: ;<> INR A STC RZ ;<> DCR A ANI 3 ADD A ADD A ADD A ADD A ADD A ADI 81H MOV L,A MVI H,0 PUSH H ;SAVE NAME POINTER LXI D,MFCUR+1 MVI B,11 CALL MOVER ;<> POP H LXI D,FCB+1 MVI B,11 CALL MOVER ;<> XRA A STA FCBEXT STA FCBRNO STA NEWFCB STA NEWFCB+12 STA NEWFCB+32 STA MFFLG1 ;TURN OFF 1ST TIME SW ;<> RET ;------------------------------------------------ ; ;MOVE SUBROUTINE MOVE (B) BYTES FROM (HL) TO (DE) ; MOVER MOV A,M ANI 7FH ;STRIP CP/M 2.x ATTRIBUTES STAX D INX H INX D DCR B JNZ MOVER RET ; ;MULTI-FILE ACCESS WORK AREA ; MFFLG1 DB 1 ;1ST TIME SW MFREQ DS 12 ;REQ NAME MFCUR DS 12 ;CURR NAME ; NEWFCB DS 33 STACK EQU $+100 ; END