; MULTIPLE FILE COPY PROGRAM
; COPYRIGHT 1982, G. YOUNG, INC.
; UPDATED 10/9/82
*
* TO EXECUTE, ENTER THE PROGRAM NAME FOLLOWED BY THE FILE MASK:
*       A>MULTCOPY *.COM
*
* THE PURPOSE OF THIS PROGRAM IS TO COPY MULTIPLE FILES TO A FLOPPY DISK
* FROM A HARD DISK.  IF YOU USED PIP FOR D:=*.COM AND THER WERE MORE
* COM FILES THAN WOULD FIT ON ONE DISK, PIP WOULD STOP WHEN THE FIRST
* DISK WAS FULL.  IF MULTCOPY, WHEN ONE DISK WAS FULL, IT WOULD ASK
* YOU TO MOUNT A NEW DISK AND CONTINUE COPYING.  THE FLOPPY DISK DRIVE
* IS HARD CODED INTO THE PROGRAM.  THE SOURCE MAY BE ANY HARD DISK.
*    EXAMPLE MULTCOPY B:LN*.ASM
* CHANGED 10/9/82 TO ASK DESTINATION FLOPPY DRIVE



* WRITTEN BY GARY YOUNG, BOX 3218, NO. HOLLYWOOD, CA 91609

       TITLE   '*** MULTCOPY FILE COPY PROGRAM ***'
BDOS    EQU     5
RECSIZE EQU     12
BOOT    EQU     0
       ORG     100H
       JMP     START
       DB      'COPYRIGHT 1982, G. YOUNG, INC.'
START   LXI     SP,STACK+80
       LDA     5DH             ;SEE IF A MASK WAS ENTERED
       CPI     20H             ;BUFFER WILL BE BLANK IF NOT
       JZ      NOMASK
       MVI     C,0DH           ;DISK RESET
       CALL    BDOS
       LXI     H,RAM           ;SET UP TABLE ADDRESS
       SHLD    TABADDR
       LXI     H,0000H
       SHLD    TABCNT
       XRA     A               ;THE TABLE REFERS TO THE REMAINING AREA
       STA     ABORT           ;OF RAM TO HOLD AS MANY DIRECTORY ENTRIES
       STA     EOF             ;AS POSSIBLE
       LXI     D,SIGNON        ;PRINT SIGNON MESSAGE
       CALL    OUTPUT
       LXI     D,DESTFLPMSG
       CALL    QUESTION
       ORA     A
       JNZ     QUEST1A
       LDA     DESTFLP
       JMP     QUEST1B
QUEST1A LDA     INREC
QUEST1B STA     FLOPPY
       CALL    EXTRACT         ;GET DIRECTORY ENTRIES
NOMORE  CALL    SORT
       CALL    KILLDUPS        ;REMOVE ENTRIES FROM MULTIPLE EXTENTS
       LDA     5CH             ;SOURCE DISK
       STA     SRCE
       LDA     FLOPPY          ;FLOPPY DISK IS ALWAYS THE DESTINATION
       ANI     0FH
       STA     DEST
       LXI     D,MNTBLANK
       CALL    QUESTION
       MVI     C,0DH
       CALL    BDOS
       CALL    CPYFILE
       JMP     BOOT            ;RESET AND RETURN TO CPM
NOMASK  LXI     D,ERRNOMSK
       CALL    OUTPUT
       JMP     BOOT
*
* THE EXTRACT ROUTINE SCANS THE DIRECTORY ON THE FLOPPY DISK
* AND CREATES A LIST OF FILES TO BE COPIED.  AFTERS SORTING,
* DUPLICATE ENTRIES RESULTING FROM MULTIPLE EXTENT ENTRIES WILL
* BE REMOVED.
*
* THE DUMMYFCB SETS UP A SKELETON TO READ ALL FILES ON THE DIRECTORY
* TO BE MODIFIED BY THE SKELATON SETUP IN THE CALL (EX: FLOPCOPY *.ASC).
*
DUMMYFCB        DB      0,'????????????',0,0,0,0,0,0,0,0,0
               DB      0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
EXTRACT EQU     $
       LXI     D,DUMMYFCB      ;COPY THE MASK SET UP BY CCP
       LXI     H,5CH           ;OVER THE DUMMY FCB TO LIMIT WHAT IS COPIED
       MVI     B,12
       CALL    MOVE
       LDA     DUMMYFCB
       ORI     40H
       STA     RDISK
       LXI     D,DISKBUF       ;SET A DMA ADDRESS FOR DIRECTORY ENTRIES
       MVI     C,1AH
       CALL    BDOS            ;SET DMA
       LXI     D,DUMMYFCB      ;GET FIRST DIRECTORY ENTRY
       MVI     C,11H
       CALL    BDOS            ;GET DIRECTORY
       INR     A
       RZ
       JMP     GETFCB          ;EXTRACT DATA FROM FCB
NEXTFCB LXI     D,DUMMYFCB      ;GET NEXT ENTRY AFTER THE FIRST
       MVI     C,12H
       CALL    BDOS
       INR     A
       RZ
GETFCB  LXI     D,32            ;EACH ENTRY IS 32 BYTES LONG
       LXI     H,DISKBUF       ;DIRECTORY RECORD IS IN DISKBUF
       CPI     1               ;FIRST ENTRY IN RECORD???
       JZ      FORMREC         ;YES
       DAD     D               ;ADD 32 TO ADDRESS IN RECORD
       CPI     2               ;SECOND ENTRY IN RECORD???
       JZ      FORMREC
       DAD     D               ;ADD 64 TO ADDRESS OF RECORD
       CPI     3               ;THIRD ENTRY IN RECORD???
       JZ      FORMREC
       DAD     D               ;ADD 96 TO ADDRESS OF RECORD
FORMREC INX     H               ;PASS DRIVE BYTE
       LXI     D,RFILE         ;MOVE FILE NAME
       MVI     B,8             ;MOVE 8 CHARACTERS
       CALL    MOVE
       LXI     D,8             ;POSITION PAST NAME TO TYPE
       DAD     D
       LXI     D,RTYPE         ;MOVE TYPE
       MVI     B,3             ;MOVE 3 CHARACTERS
       CALL    MOVE
       INX     H               ;POSITION TO THE EXTENT NUMBER
       INX     H
       INX     H
       LXI     H,RTYPE         ;STRIP OFF THE HIGH BIT SET BY
       MVI     B,11            ;THE VERSION PROGRAM
STRIP   MOV     A,M
       ANI     07FH
       MOV     M,A
       INX     H
       DCR     B
       JNZ     STRIP
       LXI     H,RTYPE         ;SKIP OVER JUNK DISK ENTRIES
       MVI     B,11            ;CONTAINING NONPRINTING CHARACTERS
NONPRNT MOV     A,M
       CPI     20H             ;ANY CHAR LESS THAN A BLANK
       JC      NEXTFCB         ;GO TO NEXT ONE IF SO
       INX     H
       DCR     B
       JNZ     NONPRNT
FIRSTEXT        EQU     $       ;GOT THE FIRST EXTENT
       LHLD    TABADDR         ;GET MEMORY TABLE ADDRESS
       LXI     D,RTYPE         ;GET MEMORY RECORD ADDRESS
       XCHG                    ;RTYPE (HL) TO TABADDR (DE)
       MVI     B,RECSIZE       ;MOVE RECSIZE BYTES
       CALL    MOVE
       LHLD    TABADDR         ;INCREMENT FOR NEXT ENTRY
       LXI     D,RECSIZE               ;RECSIZE BYTES IN RECORD
       DAD     D
       SHLD    TABADDR         ;SAVE NEW ADDRESS
       MVI     M,1AH           ;SET AN END-OF-TABLE INDICATOR
       LHLD    TABCNT          ;GET RECORD COUNT
       INX     H
       SHLD    TABCNT          ;INCREMENT RECORD COUNT
       LHLD    TABADDR         ;SEE IF NEW ADDRESS IS GREATER
       XCHG                    ;THAN THE TOP OF TPA-128
       LHLD    BDOS+1          ;HL=TOP...DE=TABLE+RECSIZE
       LXI     B,-128
       DAD     B               ;SUBTRACT 128 FROM TOP
       CALL    COMPREG         ;COMPARE REGISTER VALUES
       JNC     NEXTFCB         ;THERE IS ROOM FOR MORE
       MVI     A,1             ;NO MORE ROOM...ABORT NOW
       STA     ABORT
       RET

* COPY THE FILE FROM ONE DISK TO ANOTHER
* THIS CODE WAS TAKEN FROM BACKUP.ASM SO HDFCB REFERS TO THE SOURCE DISK
* AND FPFCB REFERS TO THE DESTINATION DISK REGARDLESS OF FLOPPY OR HARD.

CPYFILE EQU     $
       LHLD    ADDR2           ;GET THE CURRENT END OF TABLE
       INX     H               ;PLUS ONE FOR THE START OF THE
       SHLD    ADDR3           ;READ/WRITE BUFFER
       LXI     H,RAM           ;SET THE ADDRESS OF THE FIRST ENTRY
       SHLD    ADDR1
       JMP     PASSMOVE
NEXTFILE        EQU     $
       LHLD    ADDR1
       LXI     D,RECSIZE
       DAD     D
       SHLD    ADDR1
PASSMOVE LHLD   ADDR1
       MOV     A,M
       CPI     1AH
       RZ
FORMFCB LXI     D,HDFCB         ;CLEAR THE FCB
       MVI     B,36
       XRA     A
ZEROFCB STAX    D
       INX     D
       DCR     B
       JNZ     ZEROFCB
       LHLD    ADDR1           ;GET ADDRESS OF TABLE ENTRY
       LXI     D,HDTYPE        ;MOVE IN THE TYPE
       MVI     B,3
       CALL    MOVE
       INX     H
       INX     H               ;POSITION TO NAME
       INX     H
       LXI     D,HDFILE        ;MOVE THE FILE NAME
       MVI     B,8
       CALL    MOVE
       LXI     D,8
       DAD     D               ;POSITION TO DISK ID, A:, B: ETC
       LDA     SRCE
       STA     HDFCB
       LXI     D,FPFCB         ;COPY THE HDFCB TO THE FLOPPY FCB
       LXI     H,HDFCB
       MVI     B,36
       CALL    MOVE
       LDA     DEST
       STA     FPFCB
       LHLD    ADDR1
       CALL    FORMAT
       LXI     D,PRNTREC
       CALL    OUTPUT
       LXI     D,HDFCB         ;OPEN THE SOURCE FILE DRIVE
       MVI     C,0FH
       CALL    BDOS
       INR     A
       JZ      NOTFOUND
       LXI     D,FPFCB         ;SEE IF THE FILE IS ON THE DESTINATION DRV
       MVI     C,0FH
       CALL    BDOS            ;DUMMY OPEN
       INR     A
       JZ      MAKEIT          ;NOT THERE...MAKE IT
ERAIT   EQU     $
       LXI     D,FPFCB         ;DELETE THE FILE ON FLOPPY IF IT
       MVI     C,13H           ;EXISTS
       CALL    BDOS
MAKEIT  EQU     $
       LXI     D,FPFCB         ;CREATE THE FILE ON FLOPPY
       MVI     C,16H
       CALL    BDOS            ;MAKE FILE
       INR     A
       JZ      DISKFULL
COPYLOOP        CALL    LOADBUFF        ;LOAD MEMORY WITH FILE
       CALL    WRITEBUF                ;WRITE MEMORY FILE
       LDA     EOF
       CPI     1
       JZ      ENDOFFILE
       CPI     2
       JZ      DISKFULL
       JMP     COPYLOOP
ENDOFFILE       LXI     D,FPFCB         ;CLOSE FLOPPY FILE
       MVI     C,10H
       CALL    BDOS                    ;CLOSE
       JMP     NEXTFILE
DISKFULL        LXI     D,FPFCB
       MVI     C,13H           ;DELETE FILE ON FLOPPY
       CALL    BDOS
       LXI     D,MNTBLANK
       CALL    QUESTION
       MVI     C,0DH
       CALL    BDOS
       JMP     FORMFCB
NOTFOUND LHLD   ADDR1
       CALL    FORMAT
       LXI     D,NFMSG
       CALL    OUTPUT
       LXI     D,PRNTREC
       CALL    OUTPUT
       RET


* THE FOLLOWING ROUTINE IS A BUBBLE SORT.  IN PSEUDOBASIC
* IS WOULD BE DONE AS FOLLOWS:
*SORT   ADDR1=BOTTOM(RAM)-RECSIZE (RECSIZE IS COUNT OF BYTES IN ONE RECORD)
*       MAX1=0
*LOOP1  MAX1=MAX1+1
*       ADDR1=ADDR1+RECSIZE     (FIRST TIME THIS WOULD BE THE BOTTOM)
*       IF MAX1>TABCNT-1 THEN GO TO SORTED
*       ADDR2=ADDR1
*       MAX2=MAX1
*LOOP2  MAX2=MAX2+1
*       ADDR2=ADDR2+RECSIZE
*       IF MAX2>TABCNT THEN GO TO LOOP1
*       IF TABLE(ADDR1)<TABLE(ADDR2) THEN GO TO LOOP2
*       TEMP=TABLE(ADDR1)
*       TABLE(ADDR1)=TABLE(ADDR2)
*       TABLE(ADDR2)=TEMP
*       GO TO LOOP2
*SORTED RETURN
*
*NOW THAT THIS LOGIC IS INTUITIVELY OBVIOUS, HERE'S THE NOT SO
*OBVIOUS CODE:

SORT
       LXI     H,0000          ;INITIALIZE COUNT
       SHLD    MAX1            ;SINCE IT WILL DECREMENT FIRST
       LXI     D,-RECSIZE      ;SUBTRACT RECSIZE FROM THE BEGINNING
       LXI     H,RAM           ;OF THE TABLE SINCE IT WILL ADD
       DAD     D               ;RECSIZE TO IT FIRST
       SHLD    ADDR1
LOOP1   LHLD    ADDR1           ;GET THE CURRENT ADDRESS
       LXI     D,RECSIZE               ;INCREMENT IT BY RECSIZE
       DAD     D               ;PAST THE NEXT ENTRY
       SHLD    ADDR1
       LHLD    MAX1            ;SEE IF THE COUNT HAS REACHED THE LIMIT
       INX     H               ;INCREMENT THE COUNTER
       SHLD    MAX1
       XCHG                    ;MOVE TO DE TO COMPARE TO LIMIT
       LHLD    TABCNT
       DCX     H               ; IS MAX1 > TABCNT - 1 ???
       CALL    COMPREG         ;COMPARE DE (CURRENT COUNT) TO HL (TABCNT-1)
       JC      SORTED          ;FINISHED WHEN MAX1 > TABCNT-1
       LHLD    ADDR1           ;SETUP FOR THE INNER LOOP
       SHLD    ADDR2
       LHLD    MAX1
       SHLD    MAX2
LOOP2   LHLD    ADDR2           ;START WITH ONE ENTRY GREATER THEN
       LXI     D,RECSIZE               ;THE OUTER LOOP AND INCREMENT
       DAD     D               ;BY RECSIZE EACH TIME PAST THE NEXT RECORD
       SHLD    ADDR2           ;POINTER TO THE CURRENT RECORD
       LHLD    MAX2            ;LIKEWISE SEE IF THE COUNTER FOR THE
       INX     H
       SHLD    MAX2
       XCHG
       LHLD    TABCNT
       CALL    COMPREG
       JC      LOOP1           ;WHEN FINISHED, INCREMENT OUTER LOOP
       LHLD    ADDR2
       XCHG                    ;ADDR2 NOW IN DE
       LHLD    ADDR1
       CALL    COMPARE         ;COMPARE STRINGS POINTED TO BY DE/HL
       JNC     LOOP2           ;TABLE(HL) < TABLE (DE)
* EXCHANGE THE TWO ENTRIES VIA A TEMPORARY RECORD
       LXI     D,TEMP
       LHLD    ADDR1
       MVI     B,RECSIZE
       CALL    MOVE            ;TEMP=TABLE(ADDR1)
       XCHG                    ;ADDR1=DESTINATION
       LHLD    ADDR2           ;ADDR2=SOURCE
       CALL    MOVE            ;TABLE(ADDR1)=TABLE(ADDR2)
       XCHG                    ;ADDR2 = DESTINATION
       LXI     H,TEMP
       CALL    MOVE            ;TABLE(ADDR2)=TEMP
       JMP     LOOP2
SORTED  RET                     ;FINISHED SORTING



KILLDUPS EQU    $       ;KILL DUPLICATE ENTRIES FROM MULTIPLE EXTENTS
       LXI     H,RAM
       SHLD    ADDR1                   ;SET THE START OF THE TABLE
NEXTEQUAL       LHLD    ADDR1           ;CHECK EACH ENTRY AGAINST THE NEXT
       LXI     D,RECSIZE
       DAD     D
       SHLD    ADDR2
NEXTCHK MOV     A,M                     ;CHECK FOR END OF TABLE
       CPI     1AH
       RZ
       XCHG
       LHLD    ADDR1                   ;COMPARE ADDR1 WITH ADDR2
       MVI     B,RECSIZE
       CALL    COMPARE
       JNZ     SAVELAST
       PUSH    H                       ;SAVE CURRENT POSITION
       LHLD    ADDR2                   ;SET UP FOR MOVING LIST
       SHLD    ADDR1                   ;DOWN ONE ENTRY
       LXI     D,RECSIZE
       DAD     D                       ;MOVE THIRD ENTRY TO THE SECOND
       SHLD    ADDR2
       CALL    MOVELIST
       LHLD    TABCNT
       DCX     H
       SHLD    TABCNT
       POP     H                       ;RESTORE CURRENT POSITION
       SHLD    ADDR1                   ;NOW COMPARE 1ST & 3RD
       JMP     NEXTEQUAL
SAVELAST        LHLD    ADDR2           ;MAKE NEW ONE THE CURRENT ONE
       SHLD    ADDR1
       JMP     NEXTEQUAL               ;COMPARE

MOVELIST        LHLD    ADDR2           ;MOVE THE TABLE FROM ADDR2 DOWN
       XCHG                            ;TO ADDR1 THEREBY ELIMINATING
       LHLD    ADDR1                   ;UNWANTED ENTRIES
MOVENEXT        LDAX    D               ;AND MAKING MORE ROOM FOR THE
       MOV     M,A
       CPI     1AH
       RZ
       INX     H
       INX     D
       JMP     MOVENEXT


* ASSORTED ROUTINES


LOADBUFF        EQU     $       ;THIS ROUTINE LOADS AS MUCH OF
       LXI     H,0000          ;MEMORY WITH THE FILE AS POSSIBLE
       SHLD    MAX1
       LHLD    ADDR3           ;NEW TOP OF TABLE +2
       SHLD    TEMP
       XRA     A
       STA     EOF             ;CLEAR EOF FLAG
LOADNEXT        LHLD    TEMP
       XCHG                    ;SET DMA ADDRESS
       MVI     C,1AH
       CALL    BDOS
       LXI     D,HDFCB         ;READ HARD DISK
       MVI     C,14H
       CALL    BDOS
       ORA     A
       JNZ     HDEOF           ;EOF?
       LHLD    MAX1
       INX     H               ;INCREMENT RECORD COUNT
       SHLD    MAX1
       LHLD    TEMP            ;SEE IF NEXT RECORD WOULD EXCEED THE
       LXI     D,128           ;TPA AREA
       DAD     D
       SHLD    TEMP
       DAD     D               ;WILL THE NEXT RECORD OVERWRITE BDOS?
       XCHG
       LHLD    BDOS+1          ;FIND THE TOP OF MEMORY
       CALL    COMPREG         ;COMPARE REGISTERS
       RC                      ;RETURN IF MEMORY ALREADY FULL
       JMP     LOADNEXT        ;GET ANOTHER RECORD
HDEOF   MVI     A,1             ;SET FILE EOF
       STA     EOF
       RET

WRITEBUF        EQU     $       ;WRITE FROM THE MEMORY BUFFER
       LHLD    ADDR3
       SHLD    TEMP
       LHLD    MAX1            ;ALLOW FOR FILES THAT HAVE NO
       LXI     D,0000          ;RECORDS SUCH AS RESTART
       CALL    COMPREG
       RZ
WRITENEXT       LHLD    TEMP
       XCHG                    ;SET DMA ADDRESS
       MVI     C,1AH
       CALL    BDOS
       LXI     D,FPFCB
       MVI     C,15H           ;WRITE SEQUENTIAL
       CALL    BDOS
       ORA     A
       JNZ     FPFULL          ;FLOPPY DISK FULL
       LHLD    MAX1            ;DECREASE RECORD COUNT
       DCX     H
       SHLD    MAX1
       LXI     D,0000          ;CHECK FOR NO MORE TO WRITE
       CALL    COMPREG
       RZ
       LHLD    TEMP
       LXI     D,128           ;INCREMENT WRITE ADDRESS
       DAD     D
       SHLD    TEMP
       JMP     WRITENEXT
FPFULL  MVI     A,2             ;FULL DISKETTE
       STA     EOF
       RET

FORMAT  LXI     D,PRNTYPE       ;FORMAT THE ENTRY FROM THE TABLE
       MVI     B,3             ;FORMAT TO THE PRINT FORMAT
       CALL    MOVE            ;THE TABLE ADDRESS IS ASSUMMED TO BE
       LXI     D,3             ;IN HL. FIRST MOVE THE TYPE
       DAD     D               ;NOW POSITION TO THE FILE NAME
       LXI     D,PRNFILE       ;MOVE THE FILE NAME
       MVI     B,8
       CALL    MOVE
       LXI     D,8             ;POSITION TO THE DISK ID
       DAD     D
       LDA     SRCE
       ORI     40H
       STA     PRNTREC
       MVI     A,':'
       STA     PRNTREC+1
       MVI     A,'.'
       STA     PRNTYPE-1
       RET

COMPREG MOV     A,H             ;COMPARE HL TO DE
       CMP     D
       RNZ
       MOV     A,L
       CMP     E
       RET

OUTPUT  PUSH    D               ;PUT OUT A CRLF
       LXI     D,CRLF
       MVI     C,09
       CALL    BDOS
       POP     D               ;NOW PUT OUT THE MESSAGE
OUT1    MVI     C,09
       JMP     BDOS


QUESTION        CALL    OUTPUT  ;PUT OUT THE QUESTION
       LXI     D,INBUF
       MVI     C,0AH           ;INPUT THE REPLY
       CALL    BDOS
       LDA     INCNT           ;SEE IF ANYTHING WAS ENTERED
       RET

MOVE    PUSH    H               ;MOVE DATA POINTED TO IN HL
       PUSH    D               ;TO THE AREA POINTED TO IN DE
       PUSH    B               ;BY THE BYTE COUNT IN B
MOVE1   MOV     A,M
       ANI     7FH             ;RESET THE HIGH ORDER BIT BECAUSE IT
                               ;MAY HAVE BEEN TURNED ON FOR THE TYPE
       STAX    D
       INX     H
       INX     D
       DCR     B
       JNZ     MOVE1
       POP     B               ;RESTORE THE TOTAL ENVIRONMENT
       POP     D
       POP     H
       RET

COMPARE PUSH    H               ;COMPARE THE STRINGS POINTED TO IN HL
       PUSH    D               ;TO THE STRING POINTED TO IN DE
       PUSH    B               ;FOR A LENGTH OF B CHARACTERS
COMP1   LDAX    D               ; JC IF HL > DE
       CMP     M               ; JZ IF HL = DE
       JNZ     COMP2           ;JNC IF HL < DE
       INX     H
       INX     D
       DCR     B
       JNZ     COMP1
COMP2   POP     B
       POP     D
       POP     H
       RET


SIGNON  DB      'MULTIPLE FILE COPY PROGRAM '
       DB      '10/9/82$'
ERRNOMSK DB     'ERROR...NO FILE MASK IN COMMAND'
       DB      CR,LF,'COMMAND MUST BE IN THE FORMAT "MULTCOPY *.*"'
       DB      CR,LF,'$'
NFMSG   DB      'FILE NOT FOUND...ABORTING$'
DMNTMSG DB      'DISMOUNT DISKETTE AND ENTER RETURN$'
MNTBLANK DB     'MOUNT A FORMATTED BLANK DISKETTE AND ENTER RETURN$'
PRNTREC DS      1
       DB      ':'
PRNFILE DS      8
       DB      '.'
PRNTYPE DS      3
       DB      '    $'
CRLFLFLF        DB      0DH,0AH,0AH,0AH,'$'
CRLF    DB      0DH,0AH,'$'
BIGMSG  DB      0DH,0AH,'FILE TOO LARGE TO FIT ON ONE DISKETTE '
       DB      'SO NOT BACKED UP **** $'
DESTFLPMSG DB   'DESTINATION FLOPPY DRIVE (DEFAULT='
DESTFLP DB      'D) $'
HDFCB   DS      1
HDFILE  DS      8
HDTYPE  DS      3
       DS      24
FPFCB   DS      36
FLOPPY  DS      1
SRCE    DS      1
DEST    DS      1
INBUF   DB      30
INCNT   DS      1
INREC   DS      30
STACK   DS      80
EOF     DS      1
ABORT   DS      1
LINECNT DS      1
LASTTYPE DS     3
LASTFILE DS     8
TABADDR DS      2
TABCNT  DS      2
SELFLAG DS      1
TOOBIG  DS      1
ADDR1   DS      2
ADDR2   DS      2
ADDR3   DS      2
MAX1    DS      2
MAX2    DS      2
RTYPE   DS      3
RFILE   DS      8
RDISK   DS      3
       DB      '$'
TEMP    DS      RECSIZE
DISKBUF DS      128
COMPSIZE DS     1
CR      EQU     0DH
LF      EQU     0AH
RAM     EQU     $
       END     100H