; HSAVE.ASM v1 - Copies message files to a backup disk - 17 Apr 88 ; ; COPYRIGHT 1987,1988 ; by Irv Hoff ; ; Used to save the following files to the same user area on the "OUTDRV" ; disk. Saves 16k blocks (one CP/M extent) to minimize disk writes. ; Set the following options to the drive and user area desired for the ; backup files. (Use a capital letter for the drive.) ; OUTDRV EQU 'C' ; Drive for the output backup files OUTUSR EQU 14 ; User area for output backup files ; ;----------------------------------------------------------------------- ; .Z80 ASEG ; ORG 100H ; BEGIN: JP START ; Skip the next few lines ; ; DEFB 0,'Copyright (c) 1987, 1988 by Irvin M. Hoff ' ; DEFB 22 Jan 1988',0 ; ; Files to move to the backup drive ; FILE1: DEFB 'CALLERS ' ; Must be 11 bytes each FILE2: DEFB 'INDEX BBS' FILE3: DEFB 'MESSAGESBBS' FILE4: DEFB 'MSGINDEXBBS' FILE5: DEFB 'USERS BBS' ; ; Equates ; CR EQU 0DH ; Carriage return FCB EQU 5CH ; Default file control block LF EQU 0AH ; Line feed RLEN EQU 128 ; Record length ;..... ; ; BDOS equates ; BDOS EQU 0005H ; CP/M BDOS entry address WRCON EQU 2 ; Write character to console STRING EQU 9 ; Print string (DE) until '$' SELDSK EQU 14 OPENF EQU 15 ; Open disk file CLOSEF EQU 16 ; Close disk file DELET EQU 19 ; Delete file READ EQU 20 ; Read sequential file WRITE EQU 21 ; Disk file write MAKE EQU 22 ; Make file CURDRV EQU 25 SETDMA EQU 26 ; Set DMA address SETUSR EQU 32 ;..... ; ; Program starts here ; START: LD HL,0 ADD HL,SP ; Get 'CCP' stack LD (STACK),HL ; Save it for exit LD SP,STACK ; Set stack pointer ; CALL ILPRT DEFB 'Copies message files to backup disk' DEFB CR,LF,'copyright (c) 1987 by Irvin M. Hoff' DEFB CR,LF,CR,LF,'Copying from ',0 ; ; Store current drive/user area for files to be copied ; LD C,SETUSR LD E,0FFH CALL BDOS LD (OLDUSR),A ; Store current user LD A,OUTUSR LD (NEWUSR),A ; Store user area for backup files ; ; Show drive and user area being copied to what drive and user area ; LD C,CURDRV CALL BDOS ADD A,'A' CALL TYPE LD A,(OLDUSR) CP 10 JP C,START1 PUSH AF LD A,'1' CALL TYPE POP AF SUB 10 ; START1: ADD A,'0' ; Convert to ASCII CALL TYPE CALL ILPRT DEFB ': to ',0 LD A,OUTDRV CALL TYPE LD A,OUTUSR CP 10 JP C,START2 PUSH AF LD A,'1' CALL TYPE POP AF SUB 10 ; START2: ADD A,'0' ; Convert to ASCII CALL TYPE CALL ILPRT DEFB ':',CR,LF,0 ; ; ;======================================================================= ; ; Main file handling routine ; LD SP,STACK ; Reset the stack CALL ILPRT DEFB CR,LF,'Copying CALLERS...',0 LD HL,FILE1 ; Source code filename CALL MOVEF LD HL,FILE1 ; Destination filename CALL MOVED ; LD SP,STACK ; Reset the stack CALL ILPRT DEFB CR,LF,'Copying INDEX.BBS...',0 LD HL,FILE2 ; Source code filename CALL MOVEF LD HL,FILE2 ; Destination filename CALL MOVED ; LD SP,STACK ; Reset the stack CALL ILPRT DEFB CR,LF,'Copying MESSAGES.BBS...',0 LD HL,FILE3 ; Source code filename CALL MOVEF LD HL,FILE3 ; Destination filename CALL MOVED ; LD SP,STACK ; Reset the stack CALL ILPRT DEFB CR,LF,'Copying MSGINDEX.BBS...',0 LD HL,FILE4 ; Source code filename CALL MOVEF LD HL,FILE4 ; Destination filename CALL MOVED ; LD SP,STACK ; Reset the stack CALL ILPRT DEFB CR,LF,'Copying USERS.BBS...',0 LD HL,FILE5 ; Source code filename CALL MOVEF LD HL,FILE5 ; Destination filename CALL MOVED CALL ILPRT DEFB CR,LF,0 ; JP EXIT ; Finished, exit ; ;======================================================================= ; ; Open the source file ; OPENIT: XOR A LD (FCB+12),A ; Zero current record byte LD (FCB+32),A CALL SETRD ; Insure on proper drive and user area LD C,OPENF LD DE,FCB CALL BDOS INC A JP NZ,OPNOK ; No error, continue CALL ILPRT DEFB CR,LF,'++ SOURCE FILE NOT FOUND ++',0 JP EXIT ; OPNOK: XOR A LD (DEST+12),A LD (DEST+32),A ; ; See if a file already exists with that name on backup drive ; CALL SETWRT LD C,OPENF LD DE,DEST CALL BDOS INC A ; Check for existing file JP Z,MAKFIL ; No file that name, continue ; LD C,DELET ; Erase the output file, in case there LD DE,DEST ; Already was one CALL BDOS ; MAKFIL: LD C,MAKE ; Now open the output file LD DE,DEST CALL BDOS INC A JP NZ,READIN ; CALL ILPRT DEFB CR,LF,'NO DIR SPACE: OUTPUT',0 JP EXIT ;..... ; ;======================================================================= ; ; File is open, read into the buffer then dump to the new file. Do it ; in 16k increments, if over 16k total length. ; READIN: CALL SETRD ; Insure on proper drive and user area LD C,0 ; Reset the 'record' counter LD DE,BUFFER ; Start of the buffer area ; READIN1:PUSH BC PUSH DE LD C,SETDMA ; Use the Buffer to store the file CALL BDOS ; LD C,READ ; Read a record from the file and store LD DE,FCB CALL BDOS ; POP DE POP BC OR A ; Read ok? JP NZ,REOF ; If not, error or end of file ; LD HL,RLEN ; Add length of one record ADD HL,DE ; to next buffer address EX DE,HL ; Buffer address for next record to 'DE' INC C ; Increment records in buffer count LD A,C CP RLEN ; See if buffer is full yet (16k) JP NZ,READIN1 ; If not full, do another ;... ; ; Buffer is full now ; RDFULL: LD (RECNBF),A ; Store number of records in buffer LD HL,BUFFER ; Start at beginning of buffer JP WRBLK ; Now write to the output file ;..... ; ; End of File or error in reading ; REOF: DEC A ; 'EOF' yet? JP NZ,RDERR ; If not, was an error INC A LD (EOFLG),A LD A,C JP RDFULL ;..... ; RDERR: LD C,STRING LD DE,RDERR1 CALL BDOS JP 0000H ; RDERR1: DEFB '++ FILE READ ERROR ++','$' ;..... ; end of read file section ;======================================================================= ; write file section ; WRBLK: CALL SETWRT ; Insure on proper drive and user area LD A,(RECNBF) ; Number of records in the buffer OR A ; 0 means end of file JP Z,DONE ; Get set for next file LD C,A ; Save count LD DE,BUFFER ; Point to memory buffer ; WRBLK1: PUSH BC PUSH DE PUSH HL LD C,SETDMA ; Set DMA to memory buffer in 'DE' CALL BDOS ; LD C,WRITE LD DE,DEST CALL BDOS ; POP HL POP DE POP BC OR A JP NZ,WRERR ; Exit if error ; LD HL,RLEN ; Length of 1 record ADD HL,DE ; Increment the current buffer address EX DE,HL ; Put in 'DE' for new buffer address DEC C ; One less record left to move to disk JP NZ,WRBLK1 ; If not finished, write another record ; LD A,(EOFLG) ; See if finished now DEC A JP Z,DONE ; XOR A LD (RECNBF),A ; Zero the 'records in buffer' count LD HL,BUFFER ; Reset location to next buffer start JP READIN ; DONE: XOR A ; Reset the end of file flag LD (EOFLG),A LD C,CLOSEF ; Close the input file LD DE,DEST CALL BDOS ; LD C,CLOSEF ; Close the output file LD DE,FCB CALL BDOS RET ; Finished with this file ;..... ; end of write file section ;======================================================================= ; ; GENERAL SUBROUTINES ; ;======================================================================= ; ; Exit to CP/M via CCP ; EXIT: CALL SETRD ; Insure on original drive and user area CALL ILPRT DEFB CR,LF,0 LD HL,(STACK) LD SP,HL RET ;..... ; ; Inline print routine - prints string pointed to by stack until a zero ; is found. Returns to caller at the next address after the zero ter- ; minator. ; ILPRT: EX (SP),HL ; Save HL, get message address ; ILPLP: LD A,(HL) ; Get character CALL TYPE ; Output it INC HL ; Point to next LD A,(HL) ; Test OR A ; For end JP NZ,ILPLP EX (SP),HL ; Restore HL, ret address RET ; Return past the end of the message ;..... ; ; Move the output file name to the destination file block ; MOVED: LD DE,DEST+1 ; Otherwise use same filename LD B,11 CALL MOVE LD A,OUTDRV-40H LD (DEST),A JP OPENIT ; Handle the file ;... ; ; Move the input file name to the FCB file block area at 05Ch ; MOVEF: LD DE,FCB+1 ; Otherwise use same filename LD B,11 ; MOVE: LD A,(HL) LD (DE),A INC HL INC DE DEC B ; Decrement byte count JP NZ,MOVE ; If not zero, move another byte RET ;..... ; ; Set the drive and user area for reading files to be copied ; SETRD: LD A,(OLDUSR) ; Insure now on correct user are LD E,A LD C,SETUSR CALL BDOS RET ;..... ; ; Set the drive and user area to write the backup files ; SETWRT: LD A,(NEWUSR) ; Insure now on correct user are LD E,A LD C,SETUSR CALL BDOS RET ;..... ; ; Send character in 'A' register to console ; TYPE: PUSH BC PUSH DE PUSH HL LD E,A ; Character to 'E' for CP/M LD C,WRCON ; Write to console CALL BDOS POP HL POP DE POP BC RET ;..... ; ; Error statement while writing the output. (Disk might be full, etc.) ; WRERR: LD C,STRING LD DE,WRERR1 CALL BDOS JP EXIT ; WRERR1: DEFB CR,LF,'++ Can''t write to disk ++','$' ;..... ; ;----------------------------------------------------------------------- ; ; Data bytes ; EOFLG: DEFB 0 ; End of file flag NEWUSR: DEFB 0 ; User area to copy files onto OLDUSR: DEFB 0 ; User area to copy files from RECNBF: DEFB 0 ; Number of records in the buffer ;..... ; ; Output file block area ; DEST: DEFB 0,' ',0,0,0,0,0,0,0 DEFB 0,0,0,0,0,0,0,0,0,0,0,0,0,0 ; DEFS 28 ; Room for 14-level stack ; ; Set write buffer to even page boundry ; DEFS 256-($-BEGIN) AND 255 ; BUFFER EQU $ ; Write buffer starts here STACK EQU BUFFER-2 ; END