home *** CD-ROM | disk | FTP | other *** search
/ Oakland CPM Archive / oakcpm.iso / sigm / vol111 / backup.asm < prev    next >
Encoding:
Assembly Source File  |  1984-04-29  |  29.0 KB  |  1,355 lines

  1. ; DISK DIRECTORY AND BACKUP PROGRAM
  2. ;COPYRIGHT 1980, G. YOUNG, INC.'
  3. ;UPDATED 02/06/83
  4. * THE PRIMARY PURPOSE OF THIS PROGRAM IS TO BACKUP HARD DISKS ON TO
  5. * MULTIPLE FLOPPIES.  FIRST, IT EXTRACTS THE DIRECTORIES FROM ALL OF
  6. * THE HARD DISKS, SORTS BY TYPE AND FILE NAME, AND PRINTS A CONSOLIDATED
  7. * DIRECTORY.  THEN IT DELETES DUPLICATE FILES FROM THE CONSOLIDATED
  8. * DIRECTORY, DELETES UNWANTED TYPES (PRN, BAK, ETC), AND UNWANTED
  9. * FILES TO CREATE A LIST OF FILES TO BACKUP.  THESE ARE COPIED TO
  10. * MULTIPLE FLOPPIES AS NEEDED WHILE PRODUCING AN INDEX OF WHAT FILES ARE
  11. * ON EACH DISKETTE.  RESTART CAPABILITY IS PROVIDED TO BEGIN THE BACKUP
  12. * AT ANY FILE.
  13. * RESTART CAPABILITY ADDED 6/20
  14. * TO RESTART, ENTER A FILE NAME, I.E. A>BACKUP LOAD.COM
  15. * 10/1 ADDED A MORE EFFICIENT SHELL/METZER SORT WHICH DECREASED THE
  16. * SORT TIME FROM 2 MINUTES TO 2 SECONDS
  17. * 10/9/82 ADDED QUESTIONS TO MAKE IT MORE GENERAL PURPOSE
  18.  
  19. * WRITTEN BY GARY YOUNG, BOX 3218, NO. HOLLYWOOD, CA 91609
  20.  
  21.     TITLE    '*** HARD DISK BACKUP PROGRAM ***'
  22.     ORG    100H
  23.     JMP    START
  24.     DB    'COPYRIGHT 1980, G. YOUNG, INC.'
  25. TRUE    EQU    0FFH
  26. FALSE    EQU    0
  27. CLOCK    EQU    TRUE
  28. DEBUG    EQU    FALSE
  29. RECSIZE    EQU    12        ;RECORD SIZE AS FOLLOWS
  30.                 ; TYPE   = 3 BYTES
  31.                 ; FILE     = 8 BYTES
  32.                 ; DISKID = 1 BYTES
  33. IDSIZE        EQU    1    ;ID NOW MEANS A:, B:, C:, ETC
  34. LINESPAGE    EQU    60    ;LINES PER PAGE
  35. RECLINE        EQU    4    ;ENTRIES PER LINE
  36. START    LXI    SP,STACK+80
  37.     LXI    H,RAM        ;SET UP TABLE ADDRESS
  38.     SHLD    TABADDR
  39.     LXI    H,0000H
  40.     SHLD    TABCNT
  41.     XRA    A        ;THE TABLE REFERS TO THE REMAINING AREA
  42.     STA    ABORT        ;OF RAM TO HOLD AS MANY DIRECTORY ENTRIES
  43.     STA    EOF        ;AS POSSIBLE
  44.     LXI    D,SIGNON    ;PRINT SIGNON MESSAGE
  45.     CALL    OUTPUT
  46.     LXI    H,5DH        ;SAVE THE FILE NAME FOR RESTARTING
  47.     LXI    D,RESTART
  48.     MVI    B,32
  49.     CALL    MOVE
  50.     IF    CLOCK
  51.     CALL    GETDATE
  52.     LXI    H,DATETIME+1
  53.     ELSE
  54. MSG1    LXI    D,DATEMSG    ;GET CURRENT DATE FOR REPORTS
  55.      CALL    QUESTION    ;PRINT MSG AND GET REPLY
  56.      CPI    8        ;8 CHAR MUST HAVE BEEN ENTERED
  57.      JNZ    MSG1        ;REPEAT QUESTION IF NOT
  58.      LXI    H,INREC        ;MOVE DATE FROM INREC
  59.     ENDIF
  60.     MVI    B,8        ;MOVE THE DATE TO A HOLD AREA
  61.     LXI    D,DATE        ;TO "DATE"
  62.     CALL    MOVE
  63.     LXI    D,DESTMSG    ;GET DESTINATION DRIVES
  64.     CALL    QUESTION
  65.     ORA    A
  66.     JZ    LOGICQUS    ;DEFAULT
  67.     LDA    INREC
  68.     STA    BACKUPDRV
  69. LOGICQUS LDA    NODRV
  70.     LXI    H,DRIVES    ;FORMAT THE QUESTION FOR WHICH DRIVES TO 
  71. SHIFT1    INX    H        ;(HARD DISK DRIVES) TO BACKUP
  72.     DCR    A
  73.     JNZ    SHIFT1
  74.     MVI    M,')'
  75.     INX    H
  76.     MVI    M,20H
  77.     INX    H
  78.     MVI    M,'$'
  79.     LXI    D,HD2BU
  80.     CALL    QUESTION
  81.     ORA    A
  82.     JZ    GETTYPEQUS
  83.     STA    NODRV
  84.     MOV    B,A        ;NO ERROR CHECKING IS DONE ON THE DATA
  85.     LXI    H,INREC
  86.     LXI    D,DRIVES    ;SO IF YOU PUT IN DRIVE Z, IT WILL CRASH
  87.     CALL    MOVE        ;BUT YOU WOULD NOT BE THAT STUPID???
  88. GETTYPEQUS LDA    NOSKIP
  89.     MOV    B,A
  90.     ADD    A        ;MULTIPLY BY 3
  91.     ADD    B
  92.     LXI    H,SKIPTYPE
  93. SHIFT2    INX    H
  94.     DCR    A
  95.     JNZ    SHIFT2
  96.     MVI    M,')'
  97.     INX    H
  98.     MVI    M,20H        ;FORMAT TYPE TO SKIP QUESTION
  99.     INX    H
  100.     MVI    M,'$'
  101.     LXI    D,SKPMSG
  102.     CALL    QUESTION
  103.     ORA    A
  104.     JZ    DEFAULTTYPE
  105.     STA    NOSKIP
  106.     LXI    H,INREC
  107.     LXI    D,SKIPTYPE
  108.     MOV    B,A
  109.     CALL    MOVE
  110.     LDA    NOSKIP
  111.     MVI    B,0
  112. DIVBY3    INR    B
  113.     DCR    A
  114.     JZ    CNTTYPE
  115.     DCR    A
  116.     JZ    CNTTYPE
  117.     DCR    A
  118.     JNZ    DIVBY3        ;CONVERT BYTE COUNT TO TYPE COUNT
  119. CNTTYPE    MOV    A,B
  120.     STA    NOSKIP
  121. DEFAULTTYPE
  122.     CALL    EXTRACT        ;GET DIRECTORY ENTRIES
  123.     LDA    ABORT        ;SEE IF TOO MANY ENTRIES FOR MEMORY SIZE
  124.     ORA    A        ;SHOULD BE ZERO TO BE OK
  125.     JZ    NOMORE
  126.     LXI    D,TABFULL    ;REPORT WILL NOT BE COMPLETE
  127.     CALL    OUTPUT        ;MEMORY FULL ERROR
  128. NOMORE    CALL    SORT        ;SORT THE MEMORY TABLE BY TYPE, FILE
  129.                 ;NAME, THEN DISK ID
  130.     MVI    A,RECSIZE    ;SETUP TO REMOVE DUPLICATE ENTRIES
  131.     STA    COMPSIZE    ;COMPARE ON ALL CHAR
  132.     CALL    KILLDUPS    ;REMOVE DUPLICATE ENTRIES
  133.     LDA    RESTART
  134.     CPI    20H
  135.     CZ      REPORT        ;PRINT ALL ENTRIES
  136.     MVI    A,11        ;REMOVE FILES THAT ARE ON MULTIPLE DISKS
  137.     STA    COMPSIZE
  138.     CALL    KILLDUPS
  139.     LDA    RESTART
  140.     CPI    20H
  141.     CNZ    POSITION    ;POSITION LIST FOR A RESTART
  142.     CALL    SELECT        ;RESTRICT THE FILES TO BACKUP
  143. MSG3    LXI    D,BACKQUS    ;ASK IF YOU WANT BACKUP FUNCTION
  144.     CALL    QUESTION
  145.     CPI    1
  146.     JNZ    MSG3
  147.     LDA    INREC
  148.     CPI    'N'
  149.     JZ    FINISHED
  150.     CPI    'Y'
  151.     JNZ    MSG3
  152.     CALL    BACKUP        ;BACKUP THOSE FILES REPORTED ON
  153. FINISHED    MVI    C,0
  154.     JMP    BDOS        ;RESET AND RETURN TO CPM
  155. *
  156. * THE EXTRACT ROUTINE SCANS ALL THE DRIVES IN THE DRIVE TABLE
  157. * WHEN COMPLETE, IT ASKS FOR THE NEXT DRIVE ID
  158. * WHEN THE HARD DISK IS UP, IT WILL NOT ASK FOR THE DRIVE ID BUT
  159. * WILL AUTOMATICALLY SCAN THE THREE HARD DISKS AND FINISH WITHOUT
  160. * EVER ASKING FOR THE DRIVE ID.
  161. *
  162. * THE DUMMYFCB SETS UP A SKELETON TO READ ALL FILES ON THE DIRECTORY
  163. *
  164. DUMMYFCB    DB    0,'????????????',0,0,0,0,0,0,0,0,0
  165.         DB    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  166. EXTRACT LXI    D,EXTRMSG
  167.     CALL    OUTPUT
  168.            LXI    H,DRIVES    ;GET ADDRESS OF THE DRIVE TABLE
  169.     SHLD    ADDR1        ;TO SCAN
  170.     LDA    NODRV        ;SET UP COUNTER FOR THE NUMBER TO SCAN
  171.     INR    A
  172.     STA    MAX1
  173. NEXTDRV    LDA    MAX1        ;SEE IF THERE ARE MORE DRIVES TO SCAN
  174.     DCR    A
  175.     STA    MAX1        ;RETURN WHEN ALL HAVE BEEN SCANNED
  176.     RZ
  177.     LHLD    ADDR1        ;GET ADDRESS OF DRIVE TABLE
  178.     MOV    A,M        ;GET DRIVE CHARACTER
  179.     STA    RDISK
  180.     ANI    0FH        ;CONVERT A=1...P=15
  181.     STA    DUMMYFCB    ;SET IN DR OF DUMMYFCB
  182.     INX    H        ;SET FOR NEXT READ OF DRIVE TABLE
  183.     SHLD    ADDR1
  184.     LXI    D,DISKBUF    ;SET A DMA ADDRESS FOR DIRECTORY ENTRIES
  185.     MVI    C,1AH
  186.     CALL    BDOS        ;SET DMA
  187.     LXI    D,DUMMYFCB    ;GET FIRST DIRECTORY ENTRY
  188.     MVI    C,11H
  189.     CALL    BDOS        ;GET DIRECTORY
  190.     INR    A
  191.     JZ    NEXTDRV        ;NO MORE ENTRIES ON THIS DRIVE
  192.     JMP    GETFCB        ;EXTRACT DATA FROM FCB
  193. NEXTFCB    LXI    D,DUMMYFCB    ;GET NEXT ENTRY AFTER THE FIRST
  194.     MVI    C,12H
  195.     CALL    BDOS
  196.     INR    A
  197.     JZ    NEXTDRV        ;NO MORE DIRECTORIES ON THIS DISK
  198. GETFCB    LXI    D,32        ;EACH ENTRY IS 32 BYTES LONG
  199.     LXI    H,DISKBUF    ;DIRECTORY RECORD IS IN DISKBUF
  200.     CPI    1        ;FIRST ENTRY IN RECORD???
  201.     JZ    FORMREC        ;YES
  202.     DAD    D        ;ADD 32 TO ADDRESS IN RECORD
  203.     CPI    2        ;SECOND ENTRY IN RECORD???
  204.     JZ    FORMREC
  205.     DAD    D        ;ADD 64 TO ADDRESS OF RECORD
  206.     CPI    3        ;THIRD ENTRY IN RECORD???
  207.     JZ    FORMREC
  208.     DAD    D        ;ADD 96 TO ADDRESS OF RECORD
  209. FORMREC    INX    H        ;PASS DRIVE BYTE
  210.     LXI    D,RFILE        ;MOVE FILE NAME
  211.     MVI    B,8        ;MOVE 8 CHARACTERS
  212.     CALL    MOVE
  213.     LXI    D,8        ;POSITION PAST NAME TO TYPE
  214.     DAD    D
  215.     LXI    D,RTYPE        ;MOVE TYPE
  216.     MVI    B,3        ;MOVE 3 CHARACTERS
  217.     CALL    MOVE
  218.     INX    H        ;POSITION TO THE EXTENT NUMBER
  219.     INX    H
  220.     INX    H
  221.     MOV    A,M        ;GET THE EXTENT
  222.     IF    DEBUG
  223.      ORI    30H        ;DIAGNOSTIC DISPLAY
  224.      STA    RDISK+1
  225.      LXI    D,RTYPE
  226.      CALL    OUTPUT
  227.      LDA    RDISK+1
  228.      ANI    0FH
  229.     ENDIF
  230.     LXI    H,RTYPE        ;STRIP OFF THE HIGH BIT SET BY
  231.     MVI    B,11        ;THE VERSION PROGRAM
  232. STRIP    MOV    A,M
  233.     ANI    07FH
  234.     MOV    M,A
  235.     INX    H
  236.     DCR    B
  237.     JNZ    STRIP
  238.     LXI    H,RTYPE        ;SKIP OVER JUNK DISK ENTRIES
  239.     MVI    B,11        ;CONTAINING NONPRINTING CHARACTERS
  240. NONPRNT MOV    A,M
  241.     CPI    20H        ;ANY CHAR LESS THAN A BLANK
  242.     JC    NEXTFCB        ;GO TO NEXT ONE IF SO
  243.     INX    H
  244.     DCR    B
  245.     JNZ    NONPRNT
  246. FIRSTEXT    EQU    $    ;GOT THE FIRST EXTENT
  247.     LHLD    TABADDR        ;GET MEMORY TABLE ADDRESS
  248.     LXI    D,RTYPE        ;GET MEMORY RECORD ADDRESS
  249.     XCHG            ;RTYPE (HL) TO TABADDR (DE)
  250.     MVI    B,RECSIZE    ;MOVE RECSIZE BYTES
  251.     CALL    MOVE
  252.     LHLD    TABADDR        ;INCREMENT FOR NEXT ENTRY
  253.     LXI    D,RECSIZE        ;RECSIZE BYTES IN RECORD
  254.     DAD    D
  255.     SHLD    TABADDR        ;SAVE NEW ADDRESS
  256.     MVI    M,1AH        ;SET AN END-OF-TABLE INDICATOR
  257.     LHLD    TABCNT        ;GET RECORD COUNT
  258.     INX    H
  259.     SHLD    TABCNT        ;INCREMENT RECORD COUNT
  260.     LHLD    TABADDR        ;SEE IF NEW ADDRESS IS GREATER
  261.     XCHG            ;THAN THE TOP OF TPA-128
  262.     LHLD    BDOS+1        ;HL=TOP...DE=TABLE+RECSIZE
  263.     LXI    B,-128
  264.     DAD    B        ;SUBTRACT 128 FROM TOP
  265.     CALL    COMPREG        ;COMPARE REGISTER VALUES
  266.     JNC    NEXTFCB        ;THERE IS ROOM FOR MORE
  267.     MVI    A,1        ;NO MORE ROOM...ABORT NOW
  268.     STA    ABORT
  269.     RET
  270.  
  271.  
  272. ;THIS ROUTINE IS USED TO POSITION THE LIST OF FILES FOR A RESTART
  273.  
  274. POSITION LXI    D,POSMSG
  275.     CALL    OUTPUT
  276.         LXI    H,RESTART+8    ;CONVERT FILE NAME TO TYP.FILENAME
  277.     LXI    D,REPO
  278.     MVI    B,3
  279.     CALL    MOVE
  280.     LXI    H,RESTART
  281.     LXI    D,REPO+3
  282.     MVI    B,8
  283.     CALL    MOVE
  284.     LXI    H,RAM-RECSIZE    ;SETUP FOR COMPARES
  285.     SHLD    ADDR1
  286. NE1    LHLD    ADDR1
  287.     LXI    D,RECSIZE
  288.     DAD    D
  289.     SHLD    ADDR1
  290. CNXT    MOV    A,M
  291.     CPI    1AH        ;EOF ON LIST?
  292.     JZ    LBU
  293.     LHLD    ADDR1
  294.     LXI    D,REPO
  295.     MVI    B,11
  296.     CALL    COMPARE
  297.     JZ    LBU
  298.     LHLD    ADDR1
  299.     LXI    D,RECSIZE
  300.     DAD    D
  301.     SHLD    ADDR2
  302.     CALL    MOVELIST    ;TABLE MOVES DOWN SO ADDR1 IS NOT INCREMENTED
  303.     LHLD    ADDR1
  304.     JMP    CNXT
  305. LBU    SHLD    ADDR2
  306.     RET
  307.  
  308.  
  309. SORT    LXI    D,SORTMSG    ;PUT OUT A MESSAGE SO THE USER DOES
  310.     CALL    OUTPUT        ;NOT THINK THIS CRASHED WHILE SORTING
  311.     LHLD    TABCNT
  312.     SHLD    N1
  313.     SHLD    M1
  314.     LXI    H,RECSIZE
  315.     SHLD    K1  
  316.     LXI    H,RAM
  317.     SHLD    J1
  318.     CALL    SHELLM
  319.           RET            ;FINISHED SORTING
  320.  
  321. ;TITLE    'IN MEMORY SHELL-metzner sort'
  322. ;sbttl    'from KILOBAUD april 1981 p164'
  323. ;
  324. ;remark    'For fixed length records stored in memory
  325. ;Put no. of records in n1 and m1. The length
  326. ;of each record is stored at k1, and the starting
  327. ;address at j1. Start sort by calling location
  328. ;"entry". To change to descending sort change the
  329. ;instruction at neq: to DAH.'
  330. ;
  331. n1:    DW       0    ; number of records
  332. m1:    DW       0    ; ..same here
  333. k1:    DW       0    ; length of records
  334. j1:    DW       0    ; starting address of strings
  335. i1:    DW       0    ; ptr
  336. ml1:    DW       0    ; ptr
  337. dj1:    DW       0    ; ptr
  338. di1:    DW       0    ;ptr
  339. ;
  340. SHELLM    lhld    j1    ; get start address
  341.     push    h    ; ..save
  342.     lhld    k1    ; get length
  343.     push    h    ; ..it too
  344. div:    xra    a    ; m1=m1/2
  345.     lhld    m1
  346.     mov    a,h
  347.     rar
  348.     mov    h,a
  349.     mov    a,l
  350.     rar
  351.     mov    l,a
  352.     shld    m1    ; save new m1
  353. ;
  354.     ora    h    ; check if done
  355.     jnz    ndon
  356.     pop    b    ; finished
  357.     pop    d    ; ..so return
  358.     ret        ; ...now
  359. ;
  360. ;    set k1=n1-m1
  361. ;
  362. ndon:    xchg        ; m1 to de
  363.     lhld    n1
  364.     mov    a,l
  365.     sub    e
  366.     mov    l,a
  367.     mov    a,h
  368.     sbb    d
  369.     mov    h,a
  370.     shld    k1
  371.     lxi    h,1    ; set and save i=j=1
  372.     shld    j1
  373.     shld    i1
  374. ;
  375. ;    calc & save addr offset = m1*i1
  376. ;
  377.     dcr    l
  378.     pop    b    ; length of str=i1
  379.     push    b    ; ..put it back
  380. lp1:    dad    d
  381.     dcx    b
  382.     mov    a,b
  383.     ora    c
  384.     jnz    lp1
  385.     shld    ml1
  386. ;
  387.     xchg        ; calc & save d(j), d(i), d(i+m)
  388.     pop    b
  389.     pop    h
  390.     push    h
  391.     push    b
  392. lp2:    shld    dj1
  393.     shld    di1
  394.     xchg
  395.     dad    d
  396.     xchg        ; HL has d(i), DE has d(i+m)
  397. ;
  398. ;    compare strings and switch
  399. ;
  400. cp1:    pop    b    ; len of string=l1
  401.     push    b
  402. lp3:    ldax    d    ; compare each byte
  403.     sub    m
  404.     jnz    neq    ; not equal
  405.     inx    h    ; if =, then next byte
  406.     inx    d
  407.     dcx    b
  408.     mov    a,b
  409.     ora    c
  410.     jnz    lp3
  411.     jmp    nsw    ; if done, don't switch
  412. ;
  413. ;    change next instruction to jc for descending
  414. ;
  415. neq:    jnc    nsw    ; if d(i)<d(i+m) don't switch
  416. ;
  417. sw:    push    b    ; switch bytes not equal
  418.     mov    b,m
  419.     ldax    d
  420.     mov    m,a
  421.     mov    a,b
  422.     stax    d
  423.     inx    h
  424.     inx    d
  425.     pop    b
  426.     dcx    b
  427.     mov    a,b
  428.     ora    c
  429.     jnz    sw
  430. ;
  431. ;    strings switched, chk if i1-m1 < 1
  432. ;
  433.     lhld    m1
  434.     mov    a,h
  435.     cma
  436.     mov    d,a
  437.     mov    a,l
  438.     cma    
  439.     mov    e,a
  440.     lhld    i1
  441.     dad    d    ; if i1-m1<1 then jump to same as
  442.             ; ..no switch
  443.     jnc    nsw
  444. ;
  445. ;    calc new d(i), d(i+m)
  446. ;
  447.     inx    h    ; save    new i1=i1-m
  448.     shld    i1
  449.     lhld    di1    ; old d(i)=new d(i+m)
  450.     xchg
  451.     lhld    ml1    ; address offset
  452.     mov    a,e    ; new d(i)=old d(i)-offset
  453.     sub    l
  454.     mov    l,a
  455.     mov    a,d
  456.     sbb    h
  457.     mov    h,a
  458.     shld    di1    ; save new d(i)
  459.     jmp    cp1    ; goto compare strings
  460. ;
  461. ;    check for j>k
  462. ;
  463. nsw:    lhld    j1
  464.     inx    h    ; save new j=old j+1
  465.     shld    j1
  466.     shld    i1
  467.     xchg
  468.     lhld    k1
  469.     mov    a,l
  470.     sub    e
  471.     mov    a,h
  472.     sbb    d
  473.     jc    div    ; if j>k goto beginning and
  474.             ; ..divide m1
  475. ;
  476. ;    calc new d(j), d(i)
  477. ;
  478.     lhld    dj1
  479.     pop    d
  480.     push    d
  481.     dad    d    ; new d(j)=old d(j+1)
  482.     xchg
  483.     lhld    ml1
  484.     xchg
  485.     jmp    lp2
  486. ;
  487. ; that all folks
  488. ;
  489.  
  490.  
  491. * REPORT PRINTS THE SORTED CONSOLIDATED DIRECTORY ENTRIES.  
  492. * LINESPAGE IS THE NUMBER OF LINES PER PAGE AND RECLINE IS THE
  493. * NUMBER OF 20 BYTE ENTRIES PER LINE.  EACH TYPE BEGINS ON A 
  494. * NEW PAGE.
  495.  
  496. REPORT    LXI    D,RPTMSG
  497.     CALL    OUTPUT
  498.           LHLD    TABCNT        ;SET COUNT OF ENTRIES
  499.     INX    H        ;PLUS ONE
  500.     SHLD    LASTTYPE    ;INIT LASTTYPE TO INVALID DATA
  501.     SHLD    MAX1        ;TO DECREMENT FIRST
  502.     LXI    H,RAM-RECSIZE    ;SET STARTING ADDRESS
  503.     SHLD    ADDR1
  504.     CALL    HEADING
  505. NEXTPRT    LHLD    ADDR1
  506.     LXI    D,RECSIZE    ;SET TO ADD THE REC LENGTH
  507.     DAD    D
  508.     SHLD    ADDR1
  509.     LHLD    MAX1        ;DECREMENT COUNT TO SEE WHEN DONE
  510.     DCX    H
  511.     SHLD    MAX1
  512.     LXI    D,0000        ;SEE IF REACHED ZERO YET
  513.     CALL    COMPREG
  514.     JZ    TOPPAGE        ;GO TO TOP OF NEXT PAGE
  515.     LHLD    ADDR1        ;CURRENT TYPE = LAST TYPE?
  516.     MVI    B,3        ;COMPARE 3 CHARACTERS
  517.     LXI    D,LASTTYPE
  518.     CALL    COMPARE
  519.     JNZ    SKIP3        ;NEW TYPE ON NEW PAGE
  520. PRNTNOW    LDA    MAX2        ;DECREMENT RECORDS PER LINE
  521.     DCR    A
  522.     STA    MAX2
  523.     JZ    NEWLINE        ;LINE FULL, GO TO NEW LINE
  524.     CALL    FORMAT
  525.     LXI    D,PRNTREC
  526.     CALL    LIST
  527.     JMP    NEXTPRT
  528. SKIP3    LDA    LINECNT
  529.     DCR    A
  530.     JZ    NEWPAGE
  531.     DCR    A
  532.     JZ    NEWPAGE
  533.     DCR    A
  534.     JZ    NEWPAGE
  535.     STA    LINECNT
  536.     LXI    D,CRLFLFLF
  537.     CALL    LIST
  538.     JMP    CHKTYPE
  539. NEWPAGE    CALL    HEADING
  540. CHKTYPE    LXI    D,LASTTYPE    ;SET LAST TYPE TO CURRENT TYPE
  541.     LHLD    ADDR1
  542.     MVI    B,3
  543.     CALL    MOVE
  544. SETCNT    MVI    A,RECLINE+1
  545.     STA    MAX2
  546.     JMP    PRNTNOW
  547. NEWLINE    LXI    D,CRLF
  548.     CALL    LIST
  549.     LDA    LINECNT
  550.     DCR    A
  551.     STA    LINECNT
  552.     JZ    NEWPAGE        ;PAGE FULL
  553.     JMP    SETCNT
  554. TOPPAGE    RET
  555.  
  556.  
  557. * THE PURPOSE OF SELECT IS TO CREATE A FINAL LIST OF FILES TO
  558. * BACKUP.  SINCE BACKING UP 26 MEG CAN BE QUITE LONG, THIS REDUCES
  559. * THE LIST TO ONLY NECCESSARY FILES.   IT ALSO ALLOWS A RESTART
  560. * AT ANY FILE.  IT WILL DELETE DUPLICATE FILE NAMES (FILES ON A:
  561. * WILL BE USED SINCE THAT IS ASSUMED TO BE THE LATEST), AND
  562. * WILL DELETE THE FILE TYPES LISTED IN THE SKIP TABLE.  THEN IT
  563. * WILL LIST EACH TYPE AND ASK IF YOU DO WANT TO BACK UP ALL OF
  564. * THIS TYPE (Y), SKIP BACKING UP OF THE ENTIRE TYPE (N), OR
  565. * SELECT CERTAIN FILES (S) TO BACK UP.  IF THE SELECT OPTION IS
  566. * CHOSEN, EACH FILE NAME WILL BE PRINTED AND YOU BE ASKED TO
  567. * BACK UP THE FILE (Y), IGNORE THE FILE DURING THE BACKUP
  568. * (N), OR CONTINUE (C) TO BACKUP ALL OF THE REMAINING FILES
  569. * WITHIN THIS TYPE WITHOUT ASKING ANY FURTHER NAMES (USED FOR 
  570. * RESTART).  AFTER THE LIST HAS BEEN REDUCED, IT WILL BE LISTED
  571. * BEFORE THE BACKUP ACTUALLY BEGINS.
  572.  
  573. KILLDUPS EQU    $    ;KILL DUPLICATE ENTRIES FROM MULTIPLE EXTENTS
  574.     LXI    D,KILLMSG
  575.     CALL    OUTPUT
  576.     LXI    H,RAM
  577.     SHLD    ADDR1            ;SET THE START OF THE TABLE
  578. NEXTEQUAL    LHLD    ADDR1        ;CHECK EACH ENTRY AGAINST THE NEXT
  579.     LXI    D,RECSIZE
  580.     DAD    D
  581.     SHLD    ADDR2
  582. NEXTCHK    MOV    A,M            ;CHECK FOR END OF TABLE
  583.     CPI    1AH
  584.     RZ
  585.     XCHG
  586.     LHLD    ADDR1            ;COMPARE ADDR1 WITH ADDR2
  587.     LDA    COMPSIZE
  588.     MOV    B,A
  589.     CALL    COMPARE
  590.     JNZ    SAVELAST
  591.     PUSH    H            ;SAVE CURRENT POSITION
  592.     LHLD    ADDR2            ;SET UP FOR MOVING LIST
  593.     SHLD    ADDR1            ;DOWN ONE ENTRY
  594.     LXI    D,RECSIZE
  595.     DAD    D            ;MOVE THIRD ENTRY TO THE SECOND
  596.     SHLD    ADDR2
  597.     CALL    MOVELIST
  598.     LHLD    TABCNT
  599.     DCX    H
  600.     SHLD    TABCNT
  601.     POP    H            ;RESTORE CURRENT POSITION
  602.     SHLD    ADDR1            ;NOW COMPARE 1ST & 3RD
  603.     JMP    NEXTEQUAL
  604. SAVELAST    LHLD    ADDR2        ;MAKE NEW ONE THE CURRENT ONE
  605.     SHLD    ADDR1
  606.     JMP    NEXTEQUAL        ;COMPARE
  607.  
  608. SELECT    EQU    $
  609. NOWSELECT    EQU    $        ;LET USER ELIMINATE SOME
  610.     LXI    H,RAM-RECSIZE        ;INITIALIZE
  611.     SHLD    ADDR1
  612.     SHLD    LASTTYPE        ;MAKE SURE LASTTYPE DOES NOT MATCH
  613. NEXTENTRY    LHLD    ADDR1        ;GET NEXT RECORD IN TABLE
  614.     LXI    D,RECSIZE
  615.     DAD    D
  616.     SHLD    ADDR1            ;INCREMENT TABLE ENTRY
  617. CHKNEXT    MOV    A,M            ;CHECK FOR THE END OF THE TABLE
  618.     CPI    1AH            ;CNTL-Z IS AT END
  619.     JZ    LISTBKUP        ;LIST THE FINAL TABLE
  620.     LXI    D,LASTTYPE        ;SEE IF THE CURRENT TYPE IS THE
  621.     LHLD    ADDR1            ;LAST TYPE
  622.     MVI    B,3
  623.     CALL    COMPARE
  624.     JZ    CHKSELECT        ;TYPES MATCH, CHECK FILE SELECT
  625.     CALL    MOVE            ;TYPES DON'T MATCH, MAKE THE
  626.                     ;LAST TYPE = CURRENT TYPE NOW
  627.     LDA    NOSKIP
  628.     INR    A
  629.     MOV    C,A                 ;SEE IF THE NEW TYPE IS IN THE
  630.     LXI    D,SKIPTYPE        ;LIST OF FILE TYPES TO SKIP
  631.     MVI    B,3
  632. NEXTSKIP    DCR    C        ;DECREMENT NO OF FILES TO SKIP
  633.     JZ    FORMQUS            ;FILE IS GOOD
  634.     LHLD    ADDR1
  635.     CALL    COMPARE
  636.     JZ    SKIPALLTYPE        ;FILE WAS ON THE SKIP LIST
  637.     INX    D            ;INCREMENT TO NEXT SKIP FILE
  638.     INX    D
  639.     INX    D
  640.     JMP    NEXTSKIP
  641. FORMQUS    LXI    D,QTYPE            ;FORM THE QUESTION ABOUT WHETHER
  642.     LHLD    ADDR1            ;TO SKIP THIS FILE TYPE OR NOT
  643.     MVI    B,3            ;MOVE THE FILE TYPE TO THE 
  644.     CALL    MOVE            ;QUESTION PRINT LINE
  645.     XRA    A
  646.     STA    SELFLAG            ;RESET THE SELECT FLAG
  647. REASK1    LXI    D,QUEST1
  648.     CALL    QUESTION        ;ASK THE QUESTION ABOUT THE TYPE
  649.     CPI    1            ;ONE CHARACTER RESPONSE ALLOWED
  650.     JNZ    REASK1
  651.     LDA    INREC            ;GET THE RESPONSE
  652.     CPI    'N'
  653.     JZ    SKIPALLTYPE
  654.     CPI    'Y'
  655.     JZ    SAVEALLTYPE
  656.     CPI    'S'            ;S=SELECT CERTAIN FILES FROM THIS
  657.     JNZ    REASK1            ;TYPE
  658.     MVI    A,1            ;SET THE SELECT FLAG
  659.     STA    SELFLAG            ;TO ASK THE NEXT QUESTION
  660. ASKFILE    LHLD    ADDR1            ;FORMAT A QUESTION TO ASK IF THIS
  661.     LXI    D,QTYPE2        ;PARTICULAR FILE IS TO BE SAVED
  662.     MVI    B,3
  663.     CALL    MOVE
  664.     LXI    D,QFILE2        ;MOVE THE FILE NAME TO THE QUESTION
  665.     INX    H
  666.     INX    H            ;POSITION PAST THE FILE TYPE
  667.     INX    H            ;IN THE TABLE
  668.     MVI    B,8
  669.     CALL    MOVE            ;MOVE THE NAME
  670.     LXI    D,8            ;POSITION PAST NAME TO THE
  671.     DAD    D            ;DISK ID
  672.     LXI    D,QDISK2        ;MOVE THE DISK ID
  673.     MVI    B,IDSIZE
  674.     CALL    MOVE    
  675. REASK2    LXI    D,QUEST2        ;ASK THE FILE QUESTION
  676.     CALL    QUESTION
  677.     CPI    1            ;ONLY A 1 CHAR RESPONSE ALLOWED
  678.     LDA    INREC
  679.     JNZ    REASK2
  680.     CPI    'C'            ;CONTINUE WITH THE REST OF THE
  681.     JZ    SAVEALLTYPE        ;FILES WITHIN THIS TYPE - RESTART
  682.     CPI    'Y'            ;SAVE THIS PARTICULAR FILE
  683.     JZ    NEXTENTRY
  684.     CPI    'N'
  685.     JNZ    REASK2
  686.     LHLD    ADDR1            ;SHORTEN THE LIST BY ONE ENTRY
  687.     LXI    D,RECSIZE
  688.     DAD    D
  689.     SHLD    ADDR2            ;SKIP THE LAST ONE
  690.     CALL    MOVELIST        ;MOVES THE LIST DOWN FROM ADDR1
  691.                     ;TO ADDR2
  692.     LHLD    ADDR1
  693.     JMP    CHKNEXT            ;CHECK NEXT ENTRY
  694. CHKSELECT    LDA    SELFLAG        ;CHECK THE SELECT FLAG
  695.     ORA    A            ;IF NOT ZERO, ASK THE QUESTION
  696.     JNZ    ASKFILE            ;ABOUT EACH FILE
  697.     JMP    NEXTENTRY
  698. SKIPALLTYPE    CALL    FINDTYPE    ;FIND THE NEXT TYPE NOT MATCHING
  699.     CALL    MOVELIST        ;THIS ONE AND MOVE THE LIST DOWN
  700.     LHLD    ADDR1
  701.     JMP    CHKNEXT            ;TO SKIP THIS TYPE
  702. SAVEALLTYPE    CALL    FINDTYPE    ;SAVE ALL OF THIS TYPE
  703.     LHLD    ADDR2            ;RESET THE ADDRESS TO THE NEXT
  704.     SHLD    ADDR1            ;TYPE
  705.     JMP    CHKNEXT
  706. MOVELIST    LHLD    ADDR2        ;MOVE THE TABLE FROM ADDR2 DOWN
  707.     XCHG                ;TO ADDR1 THEREBY ELIMINATING
  708.     LHLD    ADDR1            ;UNWANTED ENTRIES
  709. MOVENEXT    LDAX    D        ;AND MAKING MORE ROOM FOR THE
  710.     MOV    M,A
  711.     CPI    1AH
  712.     RZ
  713.     INX    H
  714.     INX    D
  715.     JMP    MOVENEXT
  716. FINDTYPE    LHLD    ADDR1        ;FIND THE NEXT ENTRY
  717.     SHLD    ADDR2            ;WITH A TYPE DIFFERENT
  718. FINDIT    LHLD    ADDR2            ;THAN THE CURRENT TYPE
  719.     LXI    D,RECSIZE
  720.     DAD    D
  721.     SHLD    ADDR2
  722.     MOV    A,M            ;STOP AT END OF THE TABLE
  723.     CPI    1AH
  724.     RZ
  725.     XCHG
  726.     LHLD    ADDR1
  727.     MVI    B,3
  728.     CALL    COMPARE
  729.     RNZ
  730.     JMP    FINDIT            ;ADDR2 WILL HAVE THE ADDRESS OF
  731.                     ;THE NEXT TYPE WHEN FINISHED
  732. LISTBKUP    EQU    $        ;LIST THE FILES TO BE BACKED
  733.     SHLD    ADDR2            ;SAVE THE END OF THE TABLE FOR LATER
  734.     LXI    H,RAM-RECSIZE
  735.     SHLD    ADDR1
  736.     IF    DEBUG            ;PRINT LIST ONLY IF DEBUGGING
  737.     CALL    HEADING2
  738. NEXTONE    LHLD    ADDR1            ;PRINT THE NEXT TABLE ENTRY
  739.     LXI    D,RECSIZE
  740.     DAD    D
  741.     SHLD    ADDR1            ;INCREMENT TO THE NEXT ENTRY
  742.     MOV    A,M            ;CHECK FOR THE END OF THE
  743.     CPI    1AH            ;TABLE
  744.     RZ
  745.     CALL    FORMAT            ;FORMAT ENTRY
  746.     LXI    D,PRNTREC
  747.     CALL    LIST            ;PRINT IT
  748.     LDA    MAX2            ;SEE MORE WILL FIT ON THIS LINE
  749.     DCR    A
  750.     STA    MAX2
  751.     JZ    LINEFULL
  752.     JMP    NEXTONE
  753. LINEFULL    LXI    D,CRLF
  754.     CALL    LIST
  755.     LDA    LINECNT
  756.     DCR    A
  757.     STA    LINECNT
  758.     JZ    PAGEFULL
  759.     JMP    SETLINE
  760. PAGEFULL    CALL    HEADING2
  761.     MVI    A,LINESPAGE
  762.     STA    LINECNT
  763. SETLINE    MVI    A,RECLINE
  764.     STA    MAX2
  765.     JMP    NEXTONE
  766. HEADING2    LXI    D,HEAD2
  767.     CALL    LIST
  768.     LXI    D,CRLF
  769.     CALL    LIST
  770.     MVI    A,LINESPAGE
  771.     STA    LINECNT
  772.     MVI    A,RECLINE
  773.     STA    MAX2
  774.     ENDIF
  775.     RET
  776.  
  777.  
  778.  
  779. * BACKUP IS USED TO BACKUP THE FILES IN THE CREATED LIST.  IT
  780. * WILL NOT BACK UP ANY FILE THAT WILL NOT FIT ON ONE DISK ENTIRELY.
  781. * THE FILES THAT IT BACKS UP WILL COME FROM ANY OF THE HARD DISKS,
  782. * BUT NOT NECCESSARILY IN DISK ORDER, BUT RATHER ALPHABETICAL FILE
  783. * NAME ORDER.  IT WILL PROMPT FOR THE FLOPPY DISK ID AND PRINT A 
  784. * REPORT SHOWING THE FLOPPY ID AND THE FILES COPIED FOR INDEX.
  785. * IF THE FILE WILL NOT FIT ON A DISK, IT WILL BE DELETED FROM THE
  786. * DISK, THAT DISK CLOSED AND REMOVED, AND PROMPTED FOR A NEW DISK
  787. * TO RECEIVE THE FILE.  BLANK 1024 BYTE SECTORED DISKS SHOULD BE
  788. * USED FOR BEST PERFORMANCE.  WHEN ONE DISKETTE IS FULL, IT WILL
  789. * PROMPT FOR A NEW ONE SO MANY DISKETTES CAN BE USED TO BACKUP
  790. * THE HARD DISKS.  IF IT IS NECESSARY TO ABORT DURING THIS PROCESS,
  791. * USE THE RESTART CAPABILITY PROVIDED IN "SELECT".  THE AREA
  792. * FOR THE DISK BUFFER IS ALL OF RAM FROM THE END OF THE TABLE
  793. * TO THE START OF BDOS.
  794.  
  795. BACKUP    EQU    $
  796.     CALL TOPOFFORM
  797.     LHLD    ADDR2        ;GET THE CURRENT END OF TABLE
  798.     INX    H        ;PLUS ONE FOR THE START OF THE
  799.     SHLD    ADDR3        ;READ/WRITE BUFFER
  800.     LXI    H,RAM        ;SET THE ADDRESS OF THE FIRST ENTRY
  801.     SHLD    ADDR1
  802.     LXI    D,RECSIZE    ;SET AN ADDRESS FOR THE SECOND ENTRY
  803.     DAD    D        ;NEXT ENTRY = CURRENT + RECSIZE
  804.     SHLD    ADDR2        ;LATER, USE MOVELIST TO MOVE THE LIST
  805.                 ;DOWN FROM ADDR2 TO ADDR1 AFTER EACH FILE
  806.                 ;HAS BEEN COPIED.  THIS IS SO THAT THE
  807.                 ;RAM BUFFER WILL EXPAND AS THE FILES ARE
  808.                 ;COPIED SO THAT COPYING WILL BE FASTER.
  809.     CALL    MOUNT
  810.     JMP    PASSMOVE
  811. NEXTFILE    EQU    $
  812.     CALL    MOVELIST
  813.     INX    H        ;NEW START OF READ/WRITE BUFFER
  814.     SHLD    ADDR3
  815.     XRA    A        ;RESET THE FLAG FOR FILES TOO BIG
  816.     STA    TOOBIG        ;TO FIT ON ONE FLOPPY
  817. PASSMOVE    LXI    H,RAM    ;THE TABLE SHRINKS SO THE CURRENT 
  818.                 ;ENTRY IS ALWAYS AT "RAM" BUT THE
  819.                 ;READ/WRITE BUFFER GROWS
  820.     MOV    A,M
  821.     CPI    1AH
  822.     JZ    DISMOUNT    ;FINISHED
  823. FORMFCB    LXI    D,HDFCB        ;CLEAR THE FCB
  824.     MVI    B,36
  825.     XRA    A
  826. ZEROFCB    STAX    D
  827.     INX    D
  828.     DCR    B
  829.     JNZ    ZEROFCB
  830.     LXI    H,RAM        ;GET ADDRESS OF TABLE ENTRY
  831.     LXI    D,HDTYPE    ;MOVE IN THE TYPE
  832.     MVI    B,3
  833.     CALL    MOVE
  834.     INX    H
  835.     INX    H        ;POSITION TO NAME
  836.     INX    H
  837.     LXI    D,HDFILE    ;MOVE THE FILE NAME
  838.     MVI    B,8
  839.     CALL    MOVE
  840.     LXI    D,8
  841.     DAD    D        ;POSITION TO DISK ID, A:, B: ETC
  842.     MOV    A,M
  843.     ANI    0FH        ;CONVERT A=1...P=15
  844.     STA    HDFCB
  845.     LXI    D,FPFCB        ;COPY THE HDFCB TO THE FLOPPY FCB
  846.     LXI    H,HDFCB
  847.     MVI    B,36
  848.     CALL    MOVE
  849.     LDA    BACKUPDRV    ;SET THE RECEIVING FLOPPY DRIVE NUMBER
  850.     ANI    0FH        ;CONVERT D: TO 4
  851.     STA    FPFCB
  852.     LXI    D,HDFCB        ;OPEN THE HD FILE
  853.     MVI    C,0FH
  854.     CALL    BDOS        ;OPEN THE INPUT FILE
  855.     INR    A
  856.     JZ    NOTFOUND
  857.     LXI    D,FPFCB        ;DELETE THE FILE ON FLOPPY IF IT
  858.     MVI    C,13H        ;EXISTS
  859.     CALL    BDOS
  860.     LXI    D,FPFCB        ;CREATE THE FILE ON FLOPPY 
  861.     MVI    C,16H
  862.     CALL    BDOS        ;MAKE FILE
  863.     INR    A
  864.     JZ    DISKFULL
  865.     LXI    H,RAM
  866.     CALL    FORMAT
  867.     LXI    D,PRNTREC
  868.     CALL    OUTPUT
  869. COPYLOOP    CALL    LOADBUFF    ;LOAD MEMORY WITH FILE
  870.     CALL    WRITEBUF        ;WRITE MEMORY FILE
  871.     LDA    EOF            ;DISPLAY THE STATUS
  872.     ADI    30H
  873.     MOV    E,A            ;CONSOLE OUTPUT
  874.     MVI    C,2
  875.     CALL    BDOS
  876.     LDA    EOF
  877.     CPI    1
  878.     JZ    ENDOFFILE
  879.     CPI    2
  880.     JZ    DISKFULL
  881.     JMP    COPYLOOP
  882. ENDOFFILE    LXI    D,FPFCB        ;CLOSE FLOPPY FILE
  883.     MVI    C,10H
  884.     CALL    BDOS            ;CLOSE
  885.     LXI    H,RAM
  886.     CALL    PRINTFILE    ;WRITE FILE NAME ON INDEX LIST
  887.     JMP    NEXTFILE
  888. DISKFULL    LXI    D,FPFCB
  889.     MVI    C,13H        ;DELETE FILE ON FLOPPY
  890.     CALL    BDOS
  891.     MVI    C,23H        ;GET FILE SIZE
  892.     LXI    D,HDFCB
  893.     CALL    BDOS        ;SEE IF IT IS TOO BIG TO FIT ON A FLOPPY
  894.     LDA    HDFCB+34    ;GET THE HIGH ORDER BYTE OF THE FILE SIZE
  895.     ANI    0F8H        ;SEE IF THE FILE IS > 256K
  896.     JNZ    HUGE        ;YEP, TOO BIG FOR SINGLE DENSITY FLOPPY
  897.     CALL    MOUNT        ;NO, JUST MOUNT ANOTHER FLOPPY
  898.     JMP    FORMFCB
  899. HUGE    LXI    D,BIGMSG        ;YES, SECOND FLOPPY. SEND MESSAGE
  900.     CALL    LIST            ;WARNING THAT THIS FILE CANNOT
  901.     LXI    H,RAM
  902.     CALL    FORMAT            ;BE BACKED UP WITH THIS PROGRAM
  903.     LXI    D,PRNTREC
  904.     CALL    LIST            ;PRINT THE FILE NAME ALSO
  905.     JMP    NEXTFILE
  906. NOTFOUND LXI    H,RAM
  907.     CALL    FORMAT
  908.     LXI    D,NFMSG
  909.     CALL    OUTPUT
  910.     LXI    D,PRNTREC
  911.     CALL    OUTPUT
  912.     RET
  913. DISMOUNT CALL    BELL
  914.     LXI    D,DMNTMSG    ;DISMOUNT FLOPPY
  915.     CALL    QUESTION
  916.     CALL    TOPOFFORM
  917.     RET
  918.  
  919.  
  920.  
  921. * ASSORTED ROUTINES
  922.  
  923. PRINTFILE    CALL    FORMAT
  924.     LXI    D,PRNTREC    ;PRINT THE FILE ENTRY
  925.     CALL    LIST
  926.     LDA    MAX2
  927.     DCR    A
  928.     STA    MAX2        ;ENTRIES PER LINE COUNTER
  929.     RNZ
  930.     LXI    D,CRLF        ;GO TO NEW LINE
  931.     CALL    LIST
  932.     MVI    A,RECLINE
  933.     STA    MAX2
  934.     RET
  935.  
  936. HEADING3    LXI    D,CRLFLFLF    ;INDEX HEADING NOT AT TOP OF FORM
  937.     CALL    LIST
  938.     LXI    D,IDISKNO        ;MOVE THE DISK ID NO TO HEADING
  939.     LXI    H,VOLSER
  940.     MVI    B,3
  941.     CALL    MOVE
  942.     LXI    D,IDATE
  943.     LXI    H,DATE
  944.     MVI    B,8
  945.     CALL    MOVE
  946.     LXI    D,INDEX
  947.     CALL    LIST
  948.     LXI    D,CRLF
  949.     CALL    LIST
  950.     MVI    A,RECLINE
  951.     STA    MAX2
  952.     MVI    A,LINESPAGE
  953.     STA    LINECNT
  954.     RET
  955.  
  956. TOPOFFORM    MVI    E,0CH    ;POSITION PRINTER TO TOP OF FORM
  957.     MVI    C,5
  958.     JMP    BDOS
  959.  
  960. MOUNT    CALL    BELL
  961.     LXI    D,MNTMSG
  962.     CALL    QUESTION
  963.     CPI    3
  964.     JNZ    MOUNT
  965.     LXI    H,INREC
  966.     LXI    D,ENDLIT
  967.     MVI    B,3
  968.     CALL    COMPARE
  969.     JZ    FINISHED
  970.     LXI    D,VOLSER
  971.     LXI    H,INREC
  972.     MVI    B,3
  973.     CALL    MOVE        ;MOVE VOLSER ID TO VOLSER
  974.     MVI    C,0DH        ;DO A SYSTEM RESET TO  CHANGE DISKS
  975.     CALL    BDOS
  976. ERA    LXI    D,ERASE
  977.     CALL    QUESTION
  978.     CPI    1
  979.     JNZ    ERA
  980.     LDA    INREC
  981.     CPI    'N'
  982.     JZ    NOERA
  983.     CPI    'Y'
  984.     JNZ    ERA
  985.     LDA    BACKUPDRV
  986.     ANI    0FH
  987.     STA    DUMMYFCB
  988.     MVI    C,13H
  989.     LXI    D,DUMMYFCB
  990.     CALL    BDOS        ;DELETE ALL FILES ON FLOPPY
  991. NOERA    EQU    $
  992.     CALL    HEADING3
  993.     LXI    D,FPFCB        ;CLEAR THE FCB TO CREATE A FILE NAME
  994.     MVI    B,36
  995.     XRA    A
  996. CLRFCB    STAX    D
  997.     INX    D
  998.     DCR    B
  999.     JNZ    CLRFCB
  1000.     LDA    BACKUPDRV    ;SET UP THE DRIVE AS THE BACKUP
  1001.     ANI    0FH        ;CONVERT D: TO 4
  1002.     STA    FPFCB
  1003.     LXI    H,DATE        ;CREATE A NULL FILE WITH THE DATE AS
  1004.     LXI    D,FPFCB+1    ;THE FILE NAME AND THE 3 DIGIT
  1005.     MVI    B,8
  1006.     CALL    MOVE
  1007.     LXI    H,VOLSER        ;3 DIGIT VOLSER AS THE FILE TYPE
  1008.     LXI    D,FPFCB+9
  1009.     MVI    B,3        ;THIS FILE WILL BE USED TO IDENTIFY
  1010.     CALL    MOVE        ; THE DISK AND MARK THE DATE
  1011.     LXI    D,FPFCB
  1012.     MVI    C,16H        ;CREATE THE FILE
  1013.     CALL    BDOS
  1014.     INR    A
  1015.     JZ    MOUNT        ;DISK FULL?
  1016.     LXI    D,FPFCB
  1017.     MVI    C,10H        ;CLOSE THE FILE
  1018.     CALL    BDOS
  1019.     RET
  1020.  
  1021. LOADBUFF    EQU    $    ;THIS ROUTINE LOADS AS MUCH OF
  1022.     LXI    H,0000        ;MEMORY WITH THE FILE AS POSSIBLE
  1023.     SHLD    MAX1
  1024.     LHLD    ADDR3        ;NEW TOP OF TABLE +2
  1025.     SHLD    TEMP
  1026.     XRA    A
  1027.     STA    EOF        ;CLEAR EOF FLAG
  1028. LOADNEXT    LHLD    TEMP
  1029.     XCHG            ;SET DMA ADDRESS
  1030.     MVI    C,1AH
  1031.     CALL    BDOS
  1032.     LXI    D,HDFCB        ;READ HARD DISK
  1033.     MVI    C,14H
  1034.     CALL    BDOS
  1035.     ORA    A
  1036.     JNZ    HDEOF        ;EOF?
  1037.     LHLD    MAX1
  1038.     INX    H        ;INCREMENT RECORD COUNT
  1039.     SHLD    MAX1
  1040.     LHLD    TEMP        ;SEE IF NEXT RECORD WOULD EXCEED THE
  1041.     LXI    D,128        ;TPA AREA
  1042.     DAD    D
  1043.     SHLD    TEMP
  1044.     DAD    D        ;WILL THE NEXT RECORD OVERWRITE BDOS?
  1045.     XCHG
  1046.     LHLD    BDOS+1        ;FIND THE TOP OF MEMORY
  1047.     CALL    COMPREG        ;COMPARE REGISTERS
  1048.     RC            ;RETURN IF MEMORY ALREADY FULL
  1049.     JMP    LOADNEXT    ;GET ANOTHER RECORD
  1050. HDEOF    MVI    A,1        ;SET FILE EOF
  1051.     STA    EOF
  1052.     RET
  1053.  
  1054. BELL    EQU    $
  1055.     MVI    C,9
  1056.     LXI    D,MSG
  1057.     CALL    BDOS
  1058. BEEP
  1059.     MVI    C,2        ;07H ON CRT
  1060.     MVI    E,07H
  1061.     CALL    BDOS
  1062.     MVI    C,0BH
  1063.     CALL    BDOS        ;GET CONSOLE STATUS
  1064.     ORA    A
  1065.     JZ    BEEP
  1066.     MVI    C,01
  1067.     CALL    BDOS        ;GET THE DUMMY CHAR
  1068.     RET
  1069. MSG    DB    0DH,0AH,0AH,'PRESS ANY KEY TO CONTINUE'
  1070.     DB    0DH,0AH,0AH,'$'
  1071.  
  1072. WRITEBUF    EQU    $    ;WRITE FROM THE MEMORY BUFFER
  1073.     LHLD    ADDR3
  1074.     SHLD    TEMP
  1075.     LHLD    MAX1        ;ALLOW FOR FILES THAT HAVE NO 
  1076.     LXI    D,0000        ;RECORDS SUCH AS RESTART
  1077.     CALL    COMPREG
  1078.     RZ
  1079. WRITENEXT    LHLD    TEMP
  1080.     XCHG            ;SET DMA ADDRESS
  1081.     MVI    C,1AH
  1082.     CALL    BDOS
  1083.     LXI    D,FPFCB
  1084.     MVI    C,15H        ;WRITE SEQUENTIAL
  1085.     CALL    BDOS
  1086.     ORA    A
  1087.     JNZ    FPFULL        ;FLOPPY DISK FULL
  1088.     LHLD    MAX1        ;DECREASE RECORD COUNT
  1089.     DCX    H
  1090.     SHLD    MAX1
  1091.     LXI    D,0000        ;CHECK FOR NO MORE TO WRITE
  1092.     CALL    COMPREG
  1093.     RZ
  1094.     LHLD    TEMP
  1095.     LXI    D,128        ;INCREMENT WRITE ADDRESS
  1096.     DAD    D
  1097.     SHLD    TEMP
  1098.     JMP    WRITENEXT
  1099. FPFULL    MVI    A,2        ;FULL DISKETTE
  1100.     STA    EOF
  1101.     RET
  1102.  
  1103. FORMAT    LXI    D,PRNTYPE    ;FORMAT THE ENTRY FROM THE TABLE
  1104.     MVI    B,3        ;FORMAT TO THE PRINT FORMAT
  1105.     CALL    MOVE        ;THE TABLE ADDRESS IS ASSUMMED TO BE
  1106.     LXI    D,3        ;IN HL. FIRST MOVE THE TYPE
  1107.     DAD    D        ;NOW POSITION TO THE FILE NAME
  1108.     LXI    D,PRNFILE    ;MOVE THE FILE NAME
  1109.     MVI    B,8
  1110.     CALL    MOVE
  1111.     LXI    D,8        ;POSITION TO THE DISK ID
  1112.     DAD    D
  1113.     LXI    D,PRNTREC    ;MOVE THE DISK ID TO THE LINE
  1114.     MVI    B,IDSIZE
  1115.     CALL    MOVE
  1116.     RET
  1117.  
  1118. COMPREG    MOV    A,H        ;COMPARE HL TO DE
  1119.     CMP    D
  1120.     RNZ
  1121.     MOV    A,L
  1122.     CMP    E
  1123.     RET
  1124.  
  1125. OUTPUT    PUSH    D        ;PUT OUT A CRLF
  1126.     LXI    D,CRLF
  1127.     MVI    C,09
  1128.     CALL    BDOS
  1129.     POP    D        ;NOW PUT OUT THE MESSAGE
  1130. OUT1    MVI    C,09
  1131.     JMP    BDOS
  1132.  
  1133. HEADING    LXI    D,HEAD1
  1134.     CALL    LIST
  1135.     LXI    D,DATE
  1136.     CALL    LIST
  1137.     LXI    D,TABFULL
  1138.     LDA    ABORT
  1139.     ORA    A
  1140.     CNZ    LIST
  1141.     MVI    A,LINESPAGE
  1142.     STA    LINECNT
  1143.     LXI    D,CRLF
  1144.     CALL    LIST
  1145.     LXI    D,CRLF
  1146.     JMP    LIST
  1147.  
  1148. LIST    PUSH    H        ;THIS DIFFERS FROM OUTPUT
  1149.     PUSH    B        ; IN THAT LIST GOES TO THE
  1150.     PUSH    D        ;LIST DEVICE AND OUTPUT GOES
  1151. LIST1    LDAX    D        ;TO THE CONSOLE DEVICE
  1152.     CPI    '$'
  1153.     JZ    LIST2
  1154.     INX    D
  1155.     PUSH    D
  1156.     MOV    E,A
  1157.     MVI    C,5
  1158.     CALL    BDOS
  1159.     POP    D
  1160.     JMP    LIST1
  1161. LIST2    POP    D
  1162.     POP    B
  1163.     POP    H
  1164.     RET
  1165.  
  1166.  
  1167. QUESTION    CALL    OUTPUT    ;PUT OUT THE QUESTION
  1168.     LXI    D,INBUF
  1169.     MVI    C,0AH        ;INPUT THE REPLY
  1170.     CALL    BDOS
  1171.     LDA    INCNT        ;SEE IF ANYTHING WAS ENTERED
  1172.     RET
  1173.  
  1174. MOVE    PUSH    H        ;MOVE DATA POINTED TO IN HL
  1175.     PUSH    D        ;TO THE AREA POINTED TO IN DE
  1176.     PUSH    B        ;BY THE BYTE COUNT IN B
  1177. MOVE1    MOV    A,M
  1178.     ANI    7FH        ;RESET THE HIGH ORDER BIT BECAUSE IT
  1179.                 ;MAY HAVE BEEN TURNED ON FOR THE TYPE
  1180.     STAX    D
  1181.     INX    H
  1182.     INX    D
  1183.     DCR    B
  1184.     JNZ    MOVE1
  1185.     POP    B        ;RESTORE THE TOTAL ENVIRONMENT
  1186.     POP    D
  1187.     POP    H
  1188.     RET
  1189.  
  1190. COMPARE    PUSH    H        ;COMPARE THE STRINGS POINTED TO IN HL
  1191.     PUSH    D        ;TO THE STRING POINTED TO IN DE
  1192.     PUSH    B        ;FOR A LENGTH OF B CHARACTERS
  1193. COMP1    LDAX    D        ; JC IF HL > DE
  1194.     CMP    M        ; JZ IF HL = DE
  1195.     JNZ    COMP2        ;JNC IF HL < DE
  1196.     INX    H
  1197.     INX    D
  1198.     DCR    B
  1199.     JNZ    COMP1
  1200. COMP2    POP    B
  1201.     POP    D
  1202.     POP    H
  1203.     RET
  1204.  
  1205.     IF    CLOCK
  1206. ; THIS ROUTINE READS THE COMPUTIME CLOCK AND FORMATS THE TIME AND DATE
  1207. GETDATE    EQU    $
  1208.     MVI    A,16        ;RAISE THE HOLD SIGNAL
  1209.     OUT    C2
  1210.     MVI    A,50        ;DELAY AT LEAST 50 MILLISECONDS
  1211. WAIT50 DCR    A
  1212.     JNZ    WAIT50
  1213.     LXI    H,DATETIME    ;SET MESSAGE START.  NOTE 1ST CHAR IS SPACE
  1214.     MVI    A,42        ;GET MONTH TENS CHAR
  1215.     CALL    GETTIME
  1216.     MVI    A,41        ;GET MONTH UNITS CHAR
  1217.     CALL    GETTIME
  1218.     INX    H        ;SKIP SLASH
  1219.     MVI    A,40        ;GET DAY TENS CHAR
  1220.     CALL    GETTIME
  1221.     ANI    0F3H        ;DROP LEAP YEAR INDICATOR
  1222.     MOV    M,A
  1223.     MVI    A,39        ;GET DAY UNITS CHAR
  1224.     CALL    GETTIME        
  1225.     INX    H        ;SKIP SLASH
  1226.     MVI    A,44        ;GET YEAR TENS CHAR
  1227.     CALL    GETTIME
  1228.     MVI    A,43        ;GET YEAR UNITS CHAR
  1229.     CALL    GETTIME
  1230.     INX    H        ;SKIP BLANK
  1231.     MVI    A,37        ;GET HOUR TENS CHAR
  1232.     CALL    GETTIME
  1233.     ANI    0F3H        ;DROP AM/PM AND 24HR INDICATORS
  1234.     MOV    M,A
  1235.     MVI    A,36        ;GET HOUR UNITS CHAR
  1236.     CALL    GETTIME
  1237.     INX    H        ;SKIP COLON
  1238.     MVI    A,35        ;GET MINUTES TENS CHAR
  1239.     CALL    GETTIME
  1240.     MVI    A,34        ;GET MINUTES UNITS CHAR
  1241.     CALL    GETTIME
  1242.     INX    H        ;SKIP COLON
  1243.     MVI    A,33        ;GET SECONDS TENS CHAR
  1244.     CALL    GETTIME
  1245.     MVI    A,32        ;GET SECONDS UNITS CHAR
  1246.     CALL    GETTIME
  1247.     XRA    A
  1248.     OUT    C2        ;LOWER HOLD SIGNAL
  1249.     RET
  1250. C1    EQU    254        ;CLOCK ADDRESS PORT
  1251. C2    EQU    253        ;CLOCK DATA OUTPUT PORT
  1252. GETTIME    INX    H        ;ADVANCE TO NEXT PRINT POSITION
  1253.     OUT    C1
  1254.     MVI    A,6        ;DELAY AT LEAST 6 MILLISECONDS
  1255. WAIT6    DCR    A
  1256.     JNZ    WAIT6
  1257.     IN    C1
  1258.     ORI    30H        ;CONVERT TO ASCII
  1259.     MOV    M,A
  1260.     RET
  1261. DATETIME DB    ' 00/00/00 HH:MM:SS$'
  1262.     ENDIF
  1263.  
  1264. SIGNON    DB    'HARD DISK CATALOG AND BACKUP '
  1265.     DB    '10/09/82A$'
  1266. RESTART DS    32
  1267. REPO    DS    12
  1268. DATEMSG    DB    'ENTER 8 CHAR DATE FOR REPORTS MM/DD/YY: $'
  1269. ERASE    DB    'ERASE FLOPPY DISK FIRST (Y/N)? $'
  1270. TABFULL    DB    'MEMORY FULL...REPORT NOT COMPLETE$'
  1271. BACKQUS    DB    'BEGIN BACKUP PROCEDURE (Y/N)? $'
  1272. SORTMSG    DB    'SORTING...$'
  1273. RPTMSG  DB    'PRINTING REPORTS...$'
  1274. EXTRMSG DB    'EXTRACTING DIRECTORY...$'
  1275. POSMSG    DB    'POSITION FOR RESTART...$'
  1276. KILLMSG    DB    'REMOVING DUPLICATES...$'
  1277. NFMSG    DB    'FILE NOT FOUND...ABORTING$'
  1278. DMNTMSG    DB    'DISMOUNT BACKUP DISK AND ENTER RETURN$'
  1279. MNTMSG    DB    'MOUNT DISKETTE FOR BACKUP AND ENTER '
  1280.     DB    '3 CHAR DISK ID OR "END": $'
  1281. ENDLIT    DB    'END'
  1282. VOLSER    DS    3
  1283. QUEST1    DB    'BACKUP ALL FILES OF TYPE '
  1284. QTYPE    DS    3
  1285.     DB    ', (Y/N/S)? $'
  1286. QUEST2    DB    'BACKUP FILE NAMED '
  1287. QDISK2    DS    1
  1288.     DB    ':'
  1289. QFILE2    DS    8
  1290.     DB    '.'
  1291. QTYPE2    DS    3
  1292.     DB    ', (Y/N/C)? $'
  1293. HEAD2    DB    0CH,'THE FOLLOWING FILES WILL BE COPIED TO DISKETTES$'
  1294. PRNTREC    DS    1
  1295.     DB    ':'
  1296. PRNFILE    DS    8
  1297.     DB    '.'
  1298. PRNTYPE    DS    3
  1299.     DB    '    $'
  1300. CRLFLFLF    DB    0DH,0AH,0AH,0AH,'$'
  1301. INDEX    DB    'THE FOLLOWING FILES ARE ON DISKETTE NO. '
  1302. IDISKNO    DS    3
  1303.     DB    ' AS OF '
  1304. IDATE    DS    8
  1305.     DB    '$'
  1306. CRLF    DB    0DH,0AH,'$'
  1307. HEAD1    DB    0CH,'CONSOLIDATED INDEX BY FILE TYPE AS OF $'
  1308. DATE    DS    8
  1309.     DB    '   $'
  1310. BIGMSG    DB    0DH,0AH,'FILE TOO LARGE TO FIT ON ONE DISKETTE '
  1311.     DB    'SO NOT BACKED UP **** $'
  1312. DESTMSG    DB    'DESTINATION FLOPPY (DEFAULT='
  1313. BACKUPDRV DB    'D) $'
  1314. HD2BU    DB    'LOGICAL HARD DISK DRIVES TO BACKUP (DEFAULT='
  1315. DRIVES    DB    'ABCDEFGHIJKLMNOP'
  1316. NODRV    DB    3
  1317. SKPMSG    DB    'FILE TYPES TO SKIP (DEFAULT='
  1318. SKIPTYPE DB    'PRNHEXSYMBAKTMP'
  1319.     DS    45
  1320. NOSKIP    DB    5
  1321. HDFCB    DS    1
  1322. HDFILE    DS    8
  1323. HDTYPE    DS    3
  1324.     DS    24
  1325. FPFCB    DS    36
  1326. TOP    DB    0CH,'$'
  1327. INBUF    DB    60
  1328. INCNT    DS    1
  1329. INREC    DS    60
  1330. STACK    DS    80
  1331. EOF    DS    1
  1332. ABORT    DS    1
  1333. LINECNT    DS    1
  1334. LASTTYPE DS     3
  1335. LASTFILE DS    8
  1336. TABADDR    DS    2
  1337. TABCNT    DS    2
  1338. SELFLAG    DS    1
  1339. TOOBIG    DS    1
  1340. ADDR1    DS    2
  1341. ADDR2    DS    2
  1342. ADDR3    DS    2
  1343. MAX1    DS    2
  1344. MAX2    DS    2
  1345. RTYPE    DS    3
  1346. RFILE    DS    8
  1347. RDISK    DS    3
  1348.     DB    '$'
  1349. TEMP    DS    RECSIZE
  1350. DISKBUF    DS    128
  1351. COMPSIZE DS    1
  1352. RAM    EQU    $
  1353. BDOS    EQU    05H
  1354.     END    100H
  1355.