;************************************************************ ;* * ;* 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 jp start ; GO TO PROGRAM START ;*CONSOLE I/O THROUGH BOOS CALL ci: push hl ; SAVE REGISTERS push de push bc ld c,readf ; READ FUNCTION call bdos ; RETURN CHAR IN (A) pop bc ; RESTORE OTHER REGISTERS pop de pop hl ret co: push hl push de push bc ld e,a ; MOVE PRINT CHAR TO (E) ld c,typef call bdos pop bc pop de pop hl ret ccrlf: ld a,0dh ; CR LF TO CONSOLE call co ld a,0ah jp co msgxp: pop hl ; OUTPUT MESSAGE AND RETURN msgx1: ld a,(hl) ; THROUGH INDEX (H,L) cp 0 ; TEXT TERMINATOR = 0 jp z,msgex call co inc hl jp msgx1 msgex: inc hl ; POINT TO TEXT + 1 jp (hl) ; 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 cp 'X' ; ALLOW EXIT jp z,rboot ; BACK TO CP/M cp 0dh ; ACCEPT CR ONLY jp nz,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 cp 'X' jp z,rboot cp 0dh jp nz,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 cp 'X' jp z,exit cp 0dh ret z ; RETURN MEANS IGNORE jp 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 cp 0dh jp z,rboot cp 'X' jp z,rboot jp nz,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 ld de,fcb ; LOOK FOR FILE ld c,find ; BEFORE GOING AHEAD call bdos cp 255 ; DOES FILE EXIST? jp nz,run ; YES. READ IT call ccrlf ; NO. GIVE UP call msgxp db 'FILE DOES NOT EXIST! ' db 0 jp exit ; REBOOT CP/M run: ld hl,fcb ; SET UP FCB'S FOR ld de,rfcb ; READ AND WRITE ld c,16 run1: ld a,(hl) ld (de),a inc hl inc de dec c jp nz,run1 ld hl,fcb ld de,wfcb ld c,16 run2: ld a,(hl) ld (de),a inc hl inc de dec c jp nz,run2 ld hl,buffr ; INITIALIZE POINTER ld (hsave),hl ; INTO BUFFER xor a ; ZERO RECORD COUNTS ld (asave),a ld (rfcbn),a ld (wfcbn),a ;* READ THE FILE INTO RAM rfile: ld de,rfcb ; USE READ FCB ld c,open ; AND OPEN THE FILE call bdos cp 255 ; ERROR? jp nz,rfil1 call ccrlf call msgxp ; YES. SHOW IT db 'UNABLE TO OPEN FILE! ' db 0 jp exit ; AND ABORT rfil1: ld de,rfcb ; READ A RECORD ld c,read call bdos cp 0 ; GOOD READ? jp z,rfil2 ; YES. STORE IT cp 1 ; OR END OF FILE? jp z,wfile ; YES. WRITE IT call rderr ; NO. SHOW ERROR rfil2: ld hl,(hsave) ; STORE THE RECORD ld de,inbuf ld c,80h rfil3: ld a,(de) ld (hl),a inc hl inc de dec c jp nz,rfil3 ld (hsave),hl ; AND NEXT ADDRESS ld a,(asave) ; COUNT THE RECORO inc a ld (asave),a ld a,(7) ; ANY MEMORY LEFT? dec a cp h jp nz,rfil1 ; YES. KEEP READING call ccrlf ; NO. ABORT call msgxp db 'FILE IS TOO BIG! ' db 0 jp exit ;* WRITE THE FILE ONTO DISC wfile: call wrmsg ; PROMPT FOR WRITE DISC ld c,init ; INITIALIZE DISC FOR WRITE call bdos ld de,wfcb ; SEE IF FILE EXITS ld c,find call bdos ; WE CAN'T WRITE TWO! cp 255 jp z,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 cp 'X' jp z,rboot cp 0dh jp nz,wait1 ld de,wfcb ; ERASE THE OLD FILE ld c,dele call bdos wfil1: ld de,wfcb ; OPEN FILE FOR WRITE ld c,make call bdos cp 255 ; OPEN OK? jp nz,wfil2 ; YES. CONTINUE call ccrlf call msgxp ; SHOW UNABLE TO OPEN db 'OUT OF DIRECTORY SPACE !' db 0 jp exit wfil2: ld hl,buffr ; INITIALIZE POINTER ld (hsave),hl wfil3: ld hl,(hsave) ; MOVE RECORD TO OUTPUT ld de,inbuf ; BUFFER (SAME AS INPUT) ld c,80h wfil4: ld a,(hl) ld (de),a inc hl inc de dec c jp nz,wfil4 ld (hsave),hl ; SAVE NEXT ADDRESS ld de,wfcb ; WRITE THE RECORD ld c,writ call bdos cp 0 call nz,wrerr ; SHOW WRITE ERROR ld a,(asave) ; COUNT RECORD WRITTEN dec a ld (asave),a jp nz,wfil3 ; AND WRITE ANOTHER ld de,wfcb ; DONE. CLOSE THE FILE ld c,clos call bdos call ccrlf call msgxp ; PROMPT FOR RE-BOOT db 'ALL DONE! ' db 0 jp 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