;LBCOPYB/ASM - COPY/APPEND Common Routines SUBTTL '' PAGE ; ; CVRTUC - Transfer partspec & convert to U/C ; HL => Buffer containing characters to parse ; DE => Destination of converted line ; CVRTUC CALL CVRT ;Convert line LD A,CR ;Ensure end-of-line LD (DE),A ; with a carriage return RET ; ; Position to First non-space character ; CVRT0 INC HL CVRT LD A,(HL) ;P/u possible dest char CP CR ;Exit on CR RET Z CP ' ' ;Loop on space JR Z,CVRT0 DEC HL ;Backup to 1st separator ; ; HL => Filespec or Devspec, convert to U/C ; LD B,32 ;Max 32 chars COP1 LD A,(HL) ;Transfer the partial CP 'a' ;Cvrt lc to uc JR C,COP2 CP 'z'+1 JR NC,COP2 RES 5,A COP2 LD (DE),A ;Filespec until paren CP CR ;RETurn if terminator RET Z CP '(' ;Parameter ? RET Z INC HL ;Bump ptr INC DE DJNZ COP1 ;32 characters max RET ; ; PRSPC - Match Source & Dest. specs for defaults ; PRSPC LD HL,FCB1 ;HL => Source FCB LD DE,FCB2 ;DE => Destin FCB ; ; Abort if first character is illegal ; LD A,(DE) ;P/u 1st char of dest CP CR ;Is it a C/R ? JP Z,DSTREQ ;"Destination spec req" CP '0' ;Numeric ? JR C,CHKDEST CP '9'+1 JP C,DSTREQ ;Yes - "Dest spec req" ; CHKDEST PUSH DE ;Save Destination FCB ptr ; ; If no dest. filename, xfer source filename ; LD A,(DE) ;P/u a dest char CP 'A' ;Filename present ? CALL C,PRSPC7 ;No - xfer src filename LD B,'/' ;With an alpha, init to CALL PRSPC2 ; test for extension LD B,'.' ;Init to test for pswd CALL PRSPC2 POP DE RET ; ; PRSPC2 - Transfer Field to destination ; DE => Start of Destination Field ; B = Delimiter to Position one byte after ; PRSPC1 INC DE ; ; Finished with Field (Delimiter hit) ? ; PRSPC2 LD A,(DE) ;Is the next char the CP B ;Separator to look for JR Z,PRSPC3 ; ; Skip over an existing destination field ; CP 'A' ;Alphabetic ? JR NC,PRSPC1 ;Yes - skip it CP '0' ;Numeric ? JR C,PRSPC4 ;No - use source field CP '9'+1 ;Numeric ? JR C,PRSPC1 ;Yes - skip it ; JR PRSPC4 ;Use source field ; ; Hit the delimiter - Position to next char ; PRSPC3 INC DE ;Position to next field RET ; and RETurn ; ; Scan Source spec & see if it contains field ; PRSPC4 PUSH HL ;Save ptr to source PRSPC5 LD A,(HL) ;Grab a source char INC HL ;Position to next char ; ; Is the character a Terminator ? ; CP ETX ;End of line ? JR Z,PRSPC6 ;If so, not in source CP CR ;End of line? JR Z,PRSPC6 ;If so, not in source ; ; is the character the field delimiter ? ; CP B ;Delimiter ? JR NZ,PRSPC5 ;Nope, continue ; ; Transfer Source Field to Destination ; CALL MVFLD1 ;Yes, xfer the SRC field ; PRSPC6 POP HL ;Rcvr source ptr RET ; ; PRSPC7 - Shoehorn source into destination field ; ; Check if 1st char in (HL) is alphanumeric ; PRSPC7 LD A,(HL) ;P/u source char CP '0' ;RET NC if alphanumeric RET C ;C - not alphanumeric CP '9'+1 ;Numeric (0-9) ? JR C,MVFLD ;Xfer if it is CP 'A' ;Not numeric - RET C ;Must be alphabetic ; ; Shoehorn a source field byte into dest FCB ; MVFLD INC HL ;Bump source pointer MVFLD1 PUSH HL LD H,D ;Xfer dest ptr to HL LD L,E ; ; P/u current char, & stuff in last char ; MVFLD2 LD C,(HL) ;P/u dest char LD (HL),A ;Stuff in last character INC HL ;Posn to next char ; ; Finished with field ? ; LD A,C ;Test dest for CP ETX ;End of line ? JR Z,MVFLD3 ; CP CR ;End of line ? JR NZ,MVFLD2 ;Ripple the destination ; ; Done stuffing 1 source byte into dest field ; MVFLD3 LD (HL),A ;Stuff the terminator POP HL ;Restore Source FCB INC DE ;Advance to next pos JR PRSPC7 ;Go get next source byte ; ; DOSVC - Get Filespec/Devspec & Issue @OPEN/@INIT ; DOSVC PUSH AF ;Save SVC # PUSH HL ;Buffer ptr PUSH DE ;FCB ; ; Transfer Filespec/Devspec into TEMBUF ; LD HL,TEMBUF TLP LD A,(DE) ;P/u byte from FCB CP '/' ;Extension ? JR NZ,STUFCHR ;No - save the char INC DE ;Is the next character LD A,(DE) ; valid ? CP 'A' JR C,STUFCHR ;No - don't output it DEC DE ;Back one LD A,(DE) ;P/u slash STUFCHR LD (HL),A ;Xfer to TEMBUF INC HL INC DE CP CR+1 ;Done ? JR C,DUN CP ':' JR Z,DUN CP '.' JR NZ,TLP ; ; Found valid terminator - Is this a device ? ; DUN DEC HL ;Back up to term POP DE ;DE => FCB+0 LD A,(DE) ;Device ? CP '*' JR Z,DUN2 ;Yes - done LD (HL),':' ;No - overwrite with ":" INC HL ;Bump LD (DSPEC+1),HL ;Save drivespec location INC HL ;Bump DUN2 LD (HL),ETX ;End with X'03' POP HL ;HL => Disk I/O buffer POP AF ;A = SVC # LD (SVCNUM+1),A ;Save SVC # ; ; Issue Supervisory Call ; RST 28H ;Do it PUSH AF ;Save SVC condition CALL GETDRIV ;P/u drv (in C) if file JR Z,DEVICE ;Z - this is a device ; ; This is a file - did we @INIT it ? ; LD A,(SVCNUM+1) ;P/u SVC # CP @INIT ;Is it @INIT ? JR NZ,DEVICE ;No - don't worry ; ; Was the @INIT successful ? ; POP AF ;Don't perform PUSH AF ; a @CKDRV if you didn't JR Z,DO_CKDR ; successfully @INIT it. CP 42 ;LRL Open Fault ? JR NZ,DEVICE ;No - Don't @CKDRV ; ; @INIT was ok - is this a Write Prot Disk? ; DO_CKDR @@CKDRV ;Write Protected Disk ? LD A,15 ;Init WP disk error code JP C,IOERR ;Yes - abort ; ; Check status on the @INIT we did ; DEVICE POP AF ;Recover status JR Z,CHKPROT ;Check PROTection status ; ; Ignore Error #42 - "LRL Open Fault" ; CP 42 ;Ignore this error RET NZ ;NZ - Abort ; ; Check if File has proper Access ; CHKPROT BIT 7,(IX) ;Is this a filespec ? JR Z,OKYDOKY ;No - don't check LD A,(IX+1) ;P/u protection byte AND 7 LD B,A ;Xfer to B SVCNUM LD A,$-$ ;P/u SVC # CP @INIT ;@INIT ? LD A,B ;P/u protection level JR Z,INIT1 ;Z - Must be < 5 CP 6 ;Read Access ? JR C,OKYDOKY ;Yes - set Z & RETurn ; ; Illegal Access to protected file ; ILLACC @@CLOSE ;Close File LD A,25 ;File Access Denied JP IOERR ;Error - Regardless ; INIT1 CP 5 ;Update Access ? JR NC,ILLACC ;No - Illegal Access ; OKYDOKY XOR A ;Set Z flag RET ;And RETurn ; ; GETDRIV - P/u Drive # from FCB & convert to ASCII ; GETDRIV PUSH DE ;Get fcb to POP IX ; here. LD A,(DE) ;Device ? BIT 7,A RET Z ;Device - RETurn ; ; Stuff Drive # into Buffer ; LD A,(IX+6) LD C,A ;Xfer to C ADD A,'0' ;Convert to ASCII DSPEC LD ($-$),A RET ;RETurn w/ condition ; ; PUTSOUR/PUTDEST - Create Src/Dest File/Dev specs ; PUTSOUR PUSH HL ;Save HL LD HL,FROM ;Xfer there JR XBUFF PUTDEST PUSH HL ;Save HL LD HL,TO2 ; ; XBUFF - Transfer TEMBUF contents to User Buffer ; HL => Destination of Filespec/Devspec ; XBUFF PUSH DE ;Save FCB ptr LD DE,TEMBUF ;DE => Source EX DE,HL ;Swap for LDIR LD BC,15 ;15 bytes Max LDIR ;Xfer POP DE ;DE => FCB+0 POP HL ;Recover Buffer ptr RET ;Done ; ; CPYFILE - Display Copying/Appending Message ; CPYFILE PUSH HL ;Save registers PUSH DE LD HL,COPYMS ;"Copying : " APPFLAG LD A,$-$+1 ;Append or Copy ? OR A JR NZ,ITSCOPY LD HL,APPDMS ;"Appending : " ITSCOPY CALL DSPLY LD HL,FROM ;Source CALL DSPLY LD HL,TO ;" TO " CALL DSPLY LD C,CR ;End line CALL DISPB ;Display byte POP DE ;Restore Regs POP HL RET ; ; GETLRL - Get LRL from a Directory Entry ; DE => FCB of filespec ; IX <= FCB of filespec ; A <= LRL of file ; GETLRL PUSH DE ;Xfer fcb to IX POP IX LD A,(IX+7) ;P/u DEC AND 0E0H ;Calculate Record Number ADD A,4 ;Pt to LRL LD L,A SYSBUF LD H,$-$ ;P/u hi-byte of SBUFF$ LD A,(HL) ;P/u LRL RET ; ; GETCLON - Recover Cloning info from Source ; GETCLON PUSH DE POP IX ;Xfer FCB to IX LD A,(IX+7) ;P/u source DEC AND 0E0H ;Pt to start of record LD L,A ;Pt to core record SYSBUF2 LD H,$-$ ;P/u hi-byte of SBUFF$ LD DE,CLONSAV ;Save clone info LD BC,3 LDIR LD A,13 ;Pt to password fields ADD A,L LD L,A LD BC,4 ;Save them also LDIR RET ; ; Change drive # in A to Bit x,A opcode ; WHATBIT LD B,A ;Drive # to B INC B ;Always do once LD A,47H-8 ;Init opcode WHTB1 ADD A,8 ;Index to proper opcode DJNZ WHTB1 RET ; ; DOINIT - Initialization for APPEND or COPY ; DOINIT EQU $ ; ; Calculate high byte of available memory ; PUSH HL ;Save HL @@FLAGS ;IY => System Flags PUSH IY POP DE LD HL,'Y'-'A' ;Find year type flag locn ADD HL,DE LD (YFLAG1),HL ;Save for date test LD (YFLAG2),HL LD HL,0 ;P/u HIGH$ LD B,L BIT 1,(IY+CFLAG$) ;@CMNDR ? JR Z,USEHI ;No - use HIGH$ INC B ;Yes - use LOW$ USEHI @@HIGH$ ; ; Stuff high byte into memory check locations ; INC HL ; 256-byte block DEC H LD A,H ;Set up test bytes LD (RDREC3+1),A LD (RDREC5+1),A LD (GEOF6+1),A ; ; Pick up high byte of System Buffer (SBUFF$) ; LD BC,0 ;DEC = 0, Drive = 0 @@DIRRD ;Read in BOOT/SYS LD A,H ;P/u high byte of SBUFF$ LD (SYSBUF+1),A ;Stuff away for LRL LD (SYSBUF2+1),A ;Stuff away for CLONE ; ; Reset & bits ; CALL RESKFLG ;Reset bits 1-2 POP HL RET ; ; GEOF5 - Write out the last sector of destination ; GEOF5 LD A,H ;P/u hi-order pointer CP BUF1<-8 ;Same as start? RET Z ;Ret if finished ; ; At the end of buffer area ? ; GEOF6 CP $-$ ;GEOF6+1 = msb of top RET Z ;Return if finished ; ; Flash "Insert Dest. Disk" & write remainder ; CALL PMTDST ;Prompt destination LD B,H ;Save highest used LD HL,BUF1 ;Pt to start ; ; Loop to write out remainder of dest. file ; GEOF7 LD (FCB2+3),HL ;Set dest buffer address LD DE,FCB2 ;DE => Dest. FCB @@WRITE ;Write a record JP NZ,IOERR ;Jump on write error ; ; Finished writing ? ; INC H ;Bump buff ptr LD A,H CP B ;Finished? JR NZ,GEOF7 ;Loop if not RET ;Return ; ; CKBRK - Check for BREAK ; NZ - key was depressed ; CKBRK @@CKBRKC ; hit ? RET ;Z - No, NZ - Yes ; ; PMTSYS - Prompt for a system disk ; PMTSYS LD A,(XPARM+1) ;X parameter entered ? OR A RET Z ;No - need to prompt ; ; If Xfer drive number isn't 0 - don't prompt ; XFRDRV LD A,$-$ ;XFRDRV+1 contains drv # OR A ;Is it zero ? RET NZ ;Ret if not SYSTEM drive ; ; Flash "Insert SYSTEM disk" message ; PUSH HL ;Save HL LD HL,PMTSYS$ ;"Insert SYSTEM disk" CALL FLASH ;Flash, & RET if POP HL ;Restore HL RET ; ; PMTSRC - Prompt for Source Disk ; PMTSRC LD A,(XPARM+1) ;X parameter entered ? OR A RET Z ;No - don't display it ; ; Flash "Insert Source disk" message ; PUSH HL LD HL,PMTSRC$ ;Init for source CALL FLASH ;Dsp msg & await reply ; ; Read in the GAT from the Source Disk ; LD A,(XFRDRV+1) ;P/u drive LD C,A ;Stuff in C CALL RDGAT ;Get GAT ; ; Is this the correct source disk ? ; LD HL,GAT+0CEH ;HL => Name & Date field LD DE,SRCSTR ;DE => Original Source LD B,18 ;Same source disk ? CALL CPRHLDE ;Z - same, NZ - different POP HL ;Restore HL JR NZ,PMTSRC ;Re-request if not match RET ;Okay ; ; PMTDST - Prompt for Destination disk ; PMTDST LD A,(XPARM+1) ;X parameter entered ? OR A RET Z ;No - RETurn ; ; Flash "Insert Destination disk" message ; PUSH HL LD HL,PMTDST$ ;Pt to msg CALL FLASH ;Prompt & await reply ; ; Read in GAT from original destination disk ; LD A,(XFRDRV+1) ;P/u drive # LD C,A ;Stuff in C CALL RDGAT ;Get GAT ; ; Is this the same destination disk ? ; LD HL,GAT+0CEH ;HL => Name & Date field LD DE,DSTSTR ;DE => Original dest LD B,18 ;Same destination disk ? CALL CPRHLDE ;Z - Same, NZ - different POP HL ;Restore HL JR NZ,PMTDST ;Re-request if wrong disk RET ; ; CPRHLDE - Compare string @ HL to string @ DE ; B => Number of characters to compare ; Z - Set if strings match ; CPRHLDE LD A,(DE) ;P/u character @ DE CP (HL) ;Same ? RET NZ ;Ret (NZ) if no match INC HL ;Bump each INC DE DJNZ CPRHLDE ;Check B characters RET ;Matched - RETurn Z ; ; FLASH & FLASH0 - Flash a message string ; HL => Message string to flash ; FLASH0 CALL RESKFLG ;Reset Pause, Enter ; ; Pause briefly ; FLASH LD BC,16893 ;Delay count @@PAUSE ; ; Wait for no Enter or Break ; LD A,(IY+KFLAG$) ;P/u KFLAG$ AND 4!1 ;Wait until no ENTER!BRK JR NZ,FLASH0 ;Still down, go flash CALL RESKFLG ;Reset ; ; Display the message & wait for 1/4 second ; FLS1 CALL DSPLY LD BC,4000H ;Delay 4000 iterations CALL FLS2 ; & scan for Break,Enter ; ; Erase the message & wait ; LD C,EL ;Erase line CALL DISPB LD BC,3333H ;Delay 3333 iterations CALL FLS2 ; & scan for Break,Enter JR FLS1 ;Loop if neither ; ; FLS2 - Delay BC loops & scan for ; FLS2 CALL CKBRK ;Check for JP NZ,ABORT ; ; Was the pressed ? ; BIT 2,(IY+KFLAG$) ; hit ? JR NZ,FLS4 ;Go on ENTER down ; ; Nothing hit - Count down ; DEC BC ;Decrement count LD A,B ;Done ? OR C JR NZ,FLS2 ;No - check again RET ;Yes - RETurn ; ; hit - POP ret addr & clr type ahead ; FLS4 POP AF ;Pop return address CLRTYPE @@KBD ;Clear type ahead JR Z,CLRTYPE ;Good - get another OR A ;O.K. ? JP NZ,IOERR ;No - I/O Error ; ; Erase message line ; LD C,EL ;Erase line CALL DISPB ;Fall into RESKFLG ; ; RESKFLG - Reset & bits in KFLAG ; RESKFLG @@FLAGS ;IY => Flag Table LD A,(IY+KFLAG$) ;P/u KFLAG$ AND 0F9H ;Reset bits 2 & 1 LD (IY+KFLAG$),A ;Stuff in KFLAG$ RET ;RETurn ; ; DISPB - Output a byte to the Video ; DISPB @@DSP ;Output byte RET Z ;Good - RETurn JP IOERR ;Bad - I/O error ; ; DSPLY - Display line to video ; DSPLY @@DSPLY ;Display RET Z JP IOERR ;Bad - I/O Error ; ; STOP - Display Transfer aborted & Abort ; STOP LD HL,STOP$ ;"Transfer Aborted" @@LOGOT ;Log message CALL PMTSYS ;"Insert SYSTEM disk" JP ABORT ;Abort ; ; GETSYS2 - Bring in SYS2 ; GETSYS2 LD A,84H RST 28H ; ; GETSYS3 - Bring in SYS3 ; GETSYS3 LD A,85H RST 28H ; ; CKDEV - Is the source or Destination a device ? ; Z - Either Source or Destination is a device ; CKDEV LD A,(FCB1) ;Is source a device? CP '*' RET Z LD A,(FCB2) ;Is destination a device? CP '*' RET ; ; RDGAT - Read GAT of Drive C ; RDGAT PUSH DE ;Save DE & HL PUSH HL PUSH IY ;Save IY ; ; Set D = Cyl, E = Sector, HL => Buffer ; @@GTDCT ;Point IY to DCT LD D,(IY+9) ;P/u dir cyl in D LD E,0 ;GAT is sector 0 LD HL,GAT ;HL => GAT I/O Buffer @@RDSSC ;Read Track D, Sector E ; ; Restore Registers ; POP IY ;Restore IY POP HL ;Restore HL & DE POP DE LD A,14H ;Else reset to GAT error RET ;RETurn with condition ; ; OPENDES - OPEN Destination File ; OPENDES LD HL,BUF2 ;HL => Dest I/O Buffer LD DE,FCB2 ;DE => Dest FCB JR OPENFIL ;Open the file ; ; INITDES - INIT the destination file ; INITDES LD A,@INIT ;A = @INIT SVC Number JR INITFIL ;Go into OPEN routine ; ; OPENSRC - Open Source File ; OPENSRC LD DE,FCB1 ;DE => Source FCB ; ; Set the File OPEN inhibit flag ; @@FLAGS ;IY => System Flag Table SET 0,(IY+SFLAG$) ;Set file open inhibit ; OPENSR2 LD HL,BUF1 ;HL => Source I/O buffer OPENFIL LD A,@OPEN ;A = @OPEN SVC number INITFIL LD B,0 ;B = LRL = 256 ; ; OPEN or INIT the File ; GETFILE CALL DOSVC ;OPEN or INIT the file RET Z ;RETurn with Z set JP IOERR ;NZ - I/O Error ; ; Error & Informative message strings ; COPYMS DB 'Copying: ',ETX APPDMS DB 'Appending: ',ETX ; DIFLRL$ DB 'Files have different LRLs',CR DSTREQ$ DB 'Destination spec required',CR STOP$ DB BL,'Transfer aborted',CR SPCREQ$ DB 'File spec required',CR NOINDO$ DB 'Invalid command during ' DB 'processing',CR SAMERR$ DB 'Source and destination disks' DB ' are the same',CR ; PMTSYS$ DB BL,EL,' Insert SYSTEM disk ' DB BL,ETX ; PMTSRC$ DB BL,EL,' Insert SOURCE disk ' DB 'in drive :' SRC_DR DB '0 and press ' DB BL,ETX ; PMTDST$ DB BL,EL,' Insert DESTINATION disk ' DB 'in drive :' DEST_DR DB '0 and press ' DB BL,ETX ; ; ; APPEND PARAMETER TABLE ; APPTBL DB 80H ;Use new @PARAM ; DB FLAG!ABB!5 DB 'STRIP' DB 0 DW SPARM+1 ; DB FLAG!ABB!4 DB 'ECHO' DB 0 DW EPARM+1 DB 0 ; ; COPY PARAMETER TABLE ; COPYTBL DB 80H ;New @PARAM ; DB FLAG!ABB!4 DB 'ECHO' DB 0 DW EPARM+1 ; DB NUM!ABB!3 DB 'LRL' DB 0 DW LPARM+1 ; DB FLAG!ABB!5 DB 'CLONE' DB 0 DW CPARM+1 ; DB FLAG!1 DB 'X' DB 0 DW XPARM+1 DB 0 ;End of COPY parm table ; ; I/O & Storage Buffers ; FCB2 DB 0 ;Show closed on LOAD DS 31 TEMBUF DS 16 FROM DS 16 TO DB ' to ' TO2 DS 16 FCB1 DB 0 DS 31 SRCSTR DS 18 DSTSTR DS 18 CLONSAV DS 7 ; ORG $<-8+1<+8 ; GAT DS 256 BUF1 DS 256 BUF2 DS 256 ; END COPY