home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / magazine / pcmagazi / 1989 / 09 / slice.asm < prev    next >
Assembly Source File  |  1989-02-20  |  31KB  |  789 lines

  1.         PAGE    78,132
  2.         TITLE   "SLICE - Break file for multiple diskettes"
  3.  
  4. CSEG        SEGMENT PARA PUBLIC 'CODE'
  5.         ASSUME  CS:CSEG, DS:CSEG, ES:CSEG, SS:CSEG
  6.  
  7. ; ---------------------------------------------------------------------------
  8. ;   DTA structure for DOS "find matching" call
  9. ; ---------------------------------------------------------------------------
  10.         ORG     80H             ; dta offset
  11. DTA        DB        21 dup (0)            ; start of find file area
  12. DTA_ATTR    DB        0                ; file attribute
  13. DTA_TIME    DW        0                ; file time
  14. DTA_DATE    DW        0                ; file date
  15. DTA_LSIZ    DW        0                ; file lsw of size
  16. DTA_HSIZ    DW        0                ; file msw of size
  17. DTA_NAME    DB        12 DUP (0)            ; file name of file
  18. DTA_LEN     EQU     $-DTA            ; length of dta find entry
  19.  
  20.         ORG     100H            ; start of program area
  21. START:        JMP     MAIN            ; go to the code
  22.  
  23. ; ---------------------------------------------------------------------------
  24. ;   Common initialized work areas
  25. ; ---------------------------------------------------------------------------
  26. ARG        DW        0                ; addr of first argument
  27. FLOPDRV     DB        0,":\"                  ; output drive letter
  28. DESTFILE    DB        "            ",0        ; output file name
  29. DESTEXT     DW        0                ; pointer to extension
  30. DESTEXTC    DB        "0"                     ; 1st character of extension
  31. DESTNBR     DW        1                ; file extension counter
  32. RSTFLAG     DB        0                ; slice/restore flag
  33. CURRDIR     DB        ".",0                   ; argument for current directory
  34. IHANDLE     DW        0                ; input file handle
  35. OHANDLE     DW        0                ; output file handle
  36.  
  37. ; ---------------------------------------------------------------------------
  38. ;   Messages to user
  39. ; ---------------------------------------------------------------------------
  40. HEADER_MSG  DB        "SLICE   1.0 - (c) 1989 Ziff Communications Co.",0DH,0AH
  41.         DB        "PC Magazine ",254," Bob Flanders & Michael Holmes",0AH
  42.         DB        0DH,0AH
  43. DOLLAR        DB        "$"
  44. FILENF        DB        "File not found$"
  45. NOCREATE    DB        "Error opening output$"
  46. NOROOM        DB        "Not enough room$"
  47. WRONGDISK   DB        "Wrong restore disk, insert number "
  48. DISKNO        DB        "XX$"
  49. DRVNR        DB        "Must be removable media$"
  50. RDERROR     DB        "Error reading input$"
  51. WRTERROR    DB        "Error writing output$"
  52. FILEFND     DB        "File exists$"
  53. NEXTDISK    DB        "Next diskette$"
  54. HITANYKEY   DB        ", Press any key ..",0DH,0AH,"$"
  55. FORMAT        DB        0DH,0AH,"format:",09H,"$"
  56. RSFORM        DB        "SPLICE   d:  d:[\path]",0DH,0AH,"$"
  57. RESTORING   DB        "Restoring: "
  58. RESTFILE    DB        12 DUP (" "),0DH,0AH,"$"
  59.  
  60. ; ---------------------------------------------------------------------------
  61. ;   File ID Header
  62. ; ---------------------------------------------------------------------------
  63. RSTLAST     DB        0                ; last file flag
  64. RSTATTR     DB        0                ; file attributes
  65. RSTTIME     DW        0                ; file time
  66. RSTDATE     DW        0                ; file date
  67. RSTLSIZ     DW        0                ; file lsw of size
  68. RSTHSIZ     DW        0                ; file msw of size
  69. RSTNAME     DB        12 DUP (0)            ; file name of file
  70. RST_FFLEN   EQU     $-RSTATTR            ; length to move from ff area
  71. RSTSDTE     DD        0                ; date ..
  72. RSTSTME     DD        0                ; ..and time of save
  73. RST_LEN     EQU     $-RSTLAST            ; length of our file header
  74.  
  75. ; ---------------------------------------------------------------------------
  76. ;   MAIN - Mainline of program
  77. ; ---------------------------------------------------------------------------
  78. MAIN        PROC                ; start of program
  79.         CMP     RSTFLAG, 0            ; q. restoring?
  80.         JNZ     RESTORE            ; a. goto restore section
  81.  
  82.         CALL    INIT            ; initialize program
  83.         CALL    PARMS            ; check parameters
  84.         CALL    OPEN            ; open the input file
  85.         CALL    SAVE            ; copy/slice the file to output
  86.         JMP     SHORT MAIN10        ; return to dos
  87.  
  88. RESTORE:    CALL    INIT            ; perform restore setup
  89.         CALL    PARMS            ; check parameters
  90.         CALL    ROPEN            ; open the output file
  91.         CALL    RFILE            ; restore the file
  92.  
  93. MAIN10:     MOV     DX, OFFSET DOLLAR        ; dx -> null message
  94.         CALL    DIE             ; .. say goodnight
  95. MAIN        ENDP
  96.  
  97. ; ---------------------------------------------------------------------------
  98. ;   INIT - Handle initialization
  99. ; ---------------------------------------------------------------------------
  100. INIT        PROC
  101.         CLD                 ; assure ascending
  102.         MOV     DX, OFFSET HEADER_MSG   ; dx -> header message
  103.         MOV     AH, 9            ; ah = print ascii$ message
  104.         INT     21H             ; .. ask DOS to do it
  105.         RET                 ; return to caller
  106. INIT        ENDP
  107.  
  108. ; ---------------------------------------------------------------------------
  109. ;   ROPEN - open the file to restore
  110. ; ---------------------------------------------------------------------------
  111. ROPEN        PROC
  112.         MOV     DI, OFFSET ROPENFILE    ; di -> work area
  113.         MOV     SI, ARG            ; si -> where to restore
  114.  
  115. ROPEN10:    MOVSB                ; move a character
  116.  
  117.         CMP     BYTE PTR [SI], 0        ; q. end of parm?
  118.         JNE     ROPEN10            ; a. yes .. continue
  119.  
  120.         CMP     BYTE PTR [DI-1], "\"    ; q. last byte a back-slash?
  121.         JE        ROPEN20            ; a. yes .. continue
  122.  
  123.         CMP     BYTE PTR [DI-1],":"     ; q. last byte a colon (drive)?
  124.         JE        ROPEN20            ; a. yes .. continue
  125.  
  126.         MOV     AL, "\"                 ; end as directory
  127.         STOSB
  128.  
  129. ROPEN20:    MOV     SI, OFFSET RSTNAME        ; si -> name of original file
  130.         MOV     BX, OFFSET RESTFILE     ; bx -> restore filename
  131.  
  132. ROPEN30:    LODSB                ; al = char of filename
  133.         STOSB                ; .. save it
  134.  
  135.         OR        AL, AL            ; q. end of file name?
  136.         JZ        ROPEN40            ; a. yes .. continue
  137.  
  138.         MOV     [BX], AL            ; save in message
  139.         INC     BX                ; bx -> next char
  140.         JMP     ROPEN30            ; .. continue
  141.  
  142. ROPEN40:    MOV     AH, 4EH            ; ah = find first
  143.         MOV     DX, OFFSET ROPENFILE    ; dx -> file to find
  144.         MOV     CX, 0FFH            ; .. any attribute
  145.         INT     21H             ; q. file found?
  146.         JC        ROPEN45            ; a. no .. continue
  147.  
  148.         MOV     DX, OFFSET FILEFND        ; dx -> file already exists
  149.         CALL    DIE             ; .. push up some daisies
  150.  
  151. ROPEN45:    MOV     AH, 3CH            ; ah = create function code
  152.         MOV     CL, RSTATTR         ; cx = original attributes
  153.         XOR     CH,CH            ; .. upper byte off
  154.         INT     21H             ; issue DOS call
  155.         JNC     ROPEN50            ; if no problems, continue
  156.  
  157.         MOV     DX, OFFSET NOCREATE     ; dx -> create error message
  158.         CALL    DIE             ; .. go deep six
  159.  
  160. ROPEN50:    MOV     OHANDLE, AX         ; save the file handle
  161.  
  162.         MOV     DX, OFFSET RESTORING    ; dx -> restore message
  163.         MOV     AH, 09H            ; ah = print ascii$
  164.         INT     21H             ; .. tell the user
  165.  
  166.         RET                 ; return to caller
  167. ROPEN        ENDP
  168.  
  169. ; ---------------------------------------------------------------------------
  170. ;   RFILE - restore file
  171. ; ---------------------------------------------------------------------------
  172. RFILE        PROC
  173.         CALL    NEXTFILE            ; create a file name
  174.  
  175. RFILE10:    MOV     DX, OFFSET FLOPDRV        ; dx -> file name
  176.         MOV     AX, 3D00H            ; al = open for read
  177.         INT     21H             ; .. ask DOS to do it.
  178.         JNC     RFILE20            ; ok .. continue
  179.  
  180. RFILE15:    MOV     DX, OFFSET WRONGDISK    ; dx -> wrong disk message
  181.         CALL    HITKEY            ; .. display and wait
  182.         JMP     RFILE10            ; .. and try again
  183.  
  184. RFILE20:    MOV     IHANDLE, AX         ; save file handle
  185.  
  186.         MOV     BX, AX            ; bx = handle
  187.         MOV     AH, 03FH            ; ah = read file
  188.         MOV     CX, RST_LEN         ; cx = len to read
  189.         MOV     DX, OFFSET BUFFER        ; dx -> buffer to read
  190.         INT     21H             ; read a buffer
  191.         JC        RFILE35            ; tell 'em we cant read it
  192.  
  193.         MOV     SI, DX            ; si -> buffer
  194.         MOV     DI, OFFSET RSTLAST        ; di -> our header
  195.         MOVSB                ; move last flag, setup for compare
  196.         MOV     CX, RST_LEN-1        ; cx = bytes to check
  197.        REPE CMPSB                ; q. headers the same?
  198.         JE        RFILE30            ; a. yes .. continue
  199.  
  200.         MOV     AH, 3EH            ; ah = close file
  201.         INT     21H             ; close output file
  202.         JMP     RFILE15            ; tell 'em
  203.  
  204. RFILE30:    MOV     AH, 03FH            ; ah = read file
  205.         MOV     BX, IHANDLE         ; bx = handle of file to read
  206.         MOV     CX, BUFLEN            ; cx = amount to read
  207.         MOV     DX, OFFSET BUFFER        ; dx -> buffer
  208.         INT     21H             ; read, please
  209.         JNC     RFILE40            ; if no error .. continue
  210.  
  211. RFILE35:    MOV     DX, OFFSET RDERROR        ; dx -> read error message
  212.         CALL    DIE             ; ..and die gracefully
  213.  
  214. RFILE40:    MOV     CX, AX            ; cx = bytes to write
  215.         JCXZ    RFILE80            ; if finished .. exit loop
  216.  
  217.         MOV     AH, 40H            ; ax = write
  218.         MOV     BX, OHANDLE         ; bx = output file handle
  219.         INT     21H             ; write a buffer
  220.         JC        RFILE50            ; error .. die
  221.  
  222.         CMP     AX, CX            ; q. able to write it?
  223.         JE        RFILE30            ; a. no .. tell 'em
  224.  
  225.         MOV     DI, OFFSET NOROOM        ; di -> wontfit msg
  226.         JMP     SHORT RFILE60        ; ..and exit gracefully
  227.  
  228. RFILE50:    MOV     DI, OFFSET WRTERROR     ; di -> write error message
  229.  
  230. RFILE60:    MOV     AH, 41H            ; ah = delete function
  231.         MOV     DX, OFFSET ROPENFILE    ; dx -> filename
  232.         INT     21H             ; issue DOS call
  233.  
  234.         MOV     DX, DI            ; dx -> error message to give
  235.         CALL    DIE             ; ..make my day, punk!
  236.  
  237. RFILE80:    MOV     AH, 3EH            ; ah = close file
  238.         INT     21H             ; close output file
  239.  
  240.         CMP     RSTLAST, 0            ; q. end of file
  241.         JNE     RFILE90            ; a. no .. continue
  242.  
  243.         MOV     DX, OFFSET NEXTDISK     ; dx -> next disk message
  244.         CALL    HITKEY            ; display message and wait
  245.         JMP     RFILE            ; .. get next file
  246.  
  247. RFILE90:    RET                 ; else .. return to caller
  248. RFILE        ENDP
  249.  
  250. ; ---------------------------------------------------------------------------
  251. ;   NEXTFILE - Build next filename
  252. ; ---------------------------------------------------------------------------
  253. NEXTFILE    PROC
  254.         MOV     AX, DESTNBR         ; ax = current count
  255.         AAA                 ; ax = almost ascii nbr
  256.         OR        AX, 3030H            ; ax = ascii values
  257.         XCHG    AL, AH            ; swap bytes for store
  258.         MOV     BX, DESTEXT         ; bx -> 2nd char of extension
  259.         MOV     [BX], AX            ; store rest of extension
  260.         MOV     WORD PTR DISKNO, AX     ; .. and in message
  261.         INC     DESTNBR            ; increment for next time
  262.         RET                 ; ..and return to caller
  263. NEXTFILE    ENDP
  264.  
  265. ; ---------------------------------------------------------------------------
  266. ;   HITKEY - Allow user to change diskettes; dx -> first message
  267. ; ---------------------------------------------------------------------------
  268. HITKEY        PROC
  269.         MOV     AH, 9H            ; ah = print string
  270.         INT     21H             ; .. call dos to print message
  271.  
  272.         MOV     DX, OFFSET HITANYKEY    ; dx -> prompt
  273.         INT     21H             ; issue prompt message
  274.  
  275.         MOV     AX, 0C08H            ; ax = clear buffer, wait for key
  276.         INT     21H             ; issue DOS call
  277.  
  278.         OR        AL, AL            ; q. function key hit?
  279.         JNZ     HITKEY90            ; a. no .. exit
  280.  
  281.         MOV     AH, 08H            ; ah = wait for key
  282.         INT     21H             ; issue DOS call
  283.  
  284. HITKEY90:   RET
  285. HITKEY        ENDP
  286.  
  287. ; ---------------------------------------------------------------------------
  288. ;   PARMS - Parses the command line
  289. ; ---------------------------------------------------------------------------
  290. PARMS        PROC
  291.         CALL    UPCASE            ; upper case the parm area
  292.         MOV     SI, 81H            ; si -> parms area
  293.  
  294. PARMS10:    LODSB                ; get parameter character
  295.  
  296.         CMP     AL, 0DH            ; q. end of line?
  297.         JE        PARMS50            ; a. yes .. exit
  298.         CMP     AL, " "                 ; q. blank?
  299.         JNA     PARMS10            ; a. yes .. skip
  300.         CALL    ARGCHK            ; set the argument
  301.         JC        PARMSERR            ; .. die on an error
  302.  
  303. PARMS30:    LODSB                ; get next character
  304.         CMP     AL, 0DH            ; q. end of line?
  305.         JE        PARMS50            ; a. yes .. process
  306.         CMP     AL, " "                 ; q. end of PARMS?
  307.         JA        PARMS30            ; a. no .. next char
  308.  
  309.         MOV     BYTE PTR [SI-1], 0        ; end the parameter
  310.         JMP     PARMS10            ; .. look for next
  311.  
  312. PARMS50:    MOV     BYTE PTR [SI-1], 0        ; end the parameter
  313.  
  314.         CMP     ARG, 0            ; q. PARMS 1 available?
  315.         JNE     PARMS60            ; a. no .. error
  316.  
  317.         CMP     RSTFLAG, 0            ; q. restoring?
  318.         JE        PARMSERR            ; a. no .. error
  319.  
  320.         MOV     ARG, OFFSET CURRDIR     ; arg -> current directory
  321.  
  322. PARMS60:    CMP     FLOPDRV, 0            ; q. Drive given?
  323.         JE        PARMSERR            ; a. no .. error also
  324.  
  325.         RET                 ; .. else .. return to caller
  326.  
  327. PARMSERR:   MOV     DX, OFFSET FORMAT        ; dx -> format message
  328.         MOV     AH, 09H            ; ah = print ascii$
  329.         INT     21H             ; hey DOS .. print it!
  330.  
  331.         MOV     DX, OFFSET RSFORM        ; dx -> restore format
  332.  
  333.         CMP     RSTFLAG, 0            ; q. restore?
  334.         JNZ     PARMSERR1            ; a. yes .. die now
  335.  
  336.         MOV     DX, OFFSET SPFORM        ; dx -> slice format
  337.  
  338. PARMSERR1:  CALL    DIE             ; .. play taps
  339. PARMS        ENDP
  340.  
  341. ; ---------------------------------------------------------------------------
  342. ;   ARGCHK - Setup pointers to command line args; si -> 2nd char in arg
  343. ;         Exit: ARG or FLOPDRV filled in; Carry set if > 2 args
  344. ; ---------------------------------------------------------------------------
  345. ARGCHK        PROC
  346.         LEA     BX, [SI-1]            ; bx -> argument
  347.  
  348.         CMP     RSTFLAG, 0            ; q. restoring?
  349.         JE        ARG05            ; a. no .. continue
  350.  
  351.         CMP     FLOPDRV, 0            ; q. drive filled in?
  352.         JE        ARG20            ; a. no .. fill it in
  353.  
  354. ARG05:        CMP     ARG, 0            ; q. ARG filled in?
  355.         JNE     ARG10            ; a. yes .. check 2
  356.         MOV     ARG, BX            ; save ARG pointer
  357.         JMP     SHORT ARG90         ; .. exit ok!
  358.  
  359. ARG10:        CMP     FLOPDRV, 0            ; q. drive filled in?
  360.         JE        ARG20            ; a. no .. fill it in
  361.         STC                 ; else .. error
  362.         RET                 ; .. and return to caller
  363.  
  364. ARG20:        MOV     FLOPDRV, AL         ; save drive
  365.         MOV     SPLICEDRV, AL        ; .. in file and program names
  366.  
  367.         MOV     BL, AL            ; bl = drive letter
  368.         SUB     BL, "@"                 ; bl = drive number
  369.         MOV     AX, 4408H            ; ax = ioctl, removable?
  370.         INT     21H             ; issue DOS call
  371.  
  372.         OR        AL, AL            ; q. removable media drive?
  373.         JZ        ARG90            ; a. yes .. return
  374.  
  375.         MOV     DX, OFFSET DRVNR        ; dx -> error message
  376.         CALL    DIE             ; issue non-removable message
  377.  
  378. ARG90:        CLC                 ; show no error
  379.         RET                 ; return to caller
  380. ARGCHK        ENDP
  381.  
  382. ; ---------------------------------------------------------------------------
  383. ;   UPCASE - Convert command line arguments to uppercase
  384. ; ---------------------------------------------------------------------------
  385. UPCASE        PROC
  386.         PUSH    SI                ; save caller regs
  387.         PUSH    DI
  388.         MOV     SI, 81H            ; si -> start of parm area
  389.         MOV     DI, SI            ; .. same for di
  390.         CLD                 ; .. assure ascending
  391.  
  392. UPCASE10:   LODSB                ; al = char
  393.         CMP     AL, 0DH            ; q. end of line?
  394.         JE        UPCASE90            ; a. yes .. end of line!
  395.         CMP     AL, "a"                 ; q. is it below 'a'?
  396.         JB        UPCASE20            ; a. yes .. continue
  397.         CMP     AL, "z"                 ; q. is it above 'z'?
  398.         JA        UPCASE20            ; a. yes .. continue
  399.         SUB     AL, 20H            ; set to upper case
  400.  
  401. UPCASE20:   STOSB                ; save the byte
  402.         JMP     UPCASE10            ; .. and continue
  403.  
  404. UPCASE90:   POP     DI                ; restore caller regs
  405.         POP     SI
  406.         RET                 ; .. and return to caller
  407. UPCASE        ENDP
  408.  
  409. ; ---------------------------------------------------------------------------
  410. ;   DIE - Display an error message and return to DOS; dx -> ascii$ error msg
  411. ; ---------------------------------------------------------------------------
  412. DIE        PROC
  413.         MOV     AH, 9H            ; ah = print string
  414.         INT     21H             ; .. call dos to print error
  415.  
  416.         MOV     BX, IHANDLE         ; bx = input file handle
  417.         OR        BX, BX            ; q. file opened?
  418.         JZ        DIE90            ; a. no .. try output file
  419.  
  420.         MOV     AH, 3EH            ; ah = close file
  421.         INT     21H             ; .. ask DOS to do it
  422.  
  423. DIE90:        MOV     BX, OHANDLE         ; bx = output file handle
  424.         OR        BX, BX            ; q. file opened?
  425.         JZ        DIE95            ; a. no .. just exit
  426.  
  427.         MOV     AH, 3EH            ; ah = close file
  428.         INT     21H             ; .. ask DOS to do it
  429.  
  430. DIE95:        MOV     AX, 4C00H            ; ax = exit
  431.         INT     21H             ; .. terminate routine
  432. DIE        ENDP
  433.  
  434.  
  435. RESTLIMIT   EQU     $                ; only need up to here
  436.  
  437.  
  438. ; ---------------------------------------------------------------------------
  439. ;   Slice only areas and messages
  440. ; ---------------------------------------------------------------------------
  441. SPFORM        DB        "SLICE     [d:\path\]filename[.ext] "
  442.         DB        " d:",0DH,0AH,0AH,"$"
  443. ZEROLEN     DB        "Input file empty",0DH,0AH,"$"
  444. NOCOM        DB        "Program won't fit",0DH,0AH,"$"
  445. SPLICEDRV   DB        "x:\"
  446. SPLICE        DB        "SPLICE.COM",0
  447.  
  448. ; ---------------------------------------------------------------------------
  449. ;   OPEN - Opens next file to process; Carry indicates file would not open.
  450. ; ---------------------------------------------------------------------------
  451. OPEN        PROC
  452.         MOV     DX, ARG            ; dx -> file name
  453.         MOV     AX, 3D00H            ; al = open for read
  454.         INT     21H             ; .. ask DOS to do it.
  455.         JC        OPEN05            ; ok .. continue
  456.  
  457.         MOV     IHANDLE, AX         ; save file handle
  458.  
  459.         MOV     AH, 4EH            ; ah = find first
  460.         MOV     DX, ARG            ; dx -> file to find
  461.         XOR     CX, CX            ; cx = search attribute
  462.         INT     21H             ; q. find first file ok?
  463.         JNC     OPEN10            ; a. yes .. continue
  464.  
  465. OPEN05:     MOV     DX, OFFSET FILENF        ; dx -> file not found
  466.         CALL    DIE             ; .. gasp your final breath
  467.  
  468. OPEN10:     MOV     AX, DS:DTA_LSIZ        ; ax = lsw of size
  469.         OR        AX, DS:DTA_HSIZ        ; q. any data?
  470.         JNZ     OPEN90            ; a. yes ..continue
  471.  
  472.         MOV     DX, OFFSET ZEROLEN        ; dx -> file contains no data
  473.         CALL    DIE             ; .. dearly beloved ...
  474.  
  475. OPEN90:     RET
  476. OPEN        ENDP
  477.  
  478. ; ---------------------------------------------------------------------------
  479. ;   SAVE - Handle building slice files on destination
  480. ; ---------------------------------------------------------------------------
  481. SAVE        PROC
  482.         CALL    BLD_RESTORE         ; build restore program
  483.  
  484. SAVE10:     MOV     AH, 03FH            ; ah = read file
  485.         MOV     BX, IHANDLE         ; bx = handle of file to read
  486.         MOV     CX, BUFLEN            ; cx = amount to read
  487.         MOV     DX, OFFSET BUFFER        ; dx -> buffer
  488.         INT     21H             ; read, please
  489.         JNC     SAVE20            ; if no error .. continue
  490.  
  491.         MOV     DX, OFFSET RDERROR        ; dx -> read error message
  492.         CALL    DIE             ; ..and die gracefully
  493.  
  494. SAVE20:     CALL    WRITE            ; ..and write out a buffer full
  495.         JC        SAVE90            ; if finished .. exit loop
  496.         JMP     SAVE10            ; else .. get next buffer
  497.  
  498. SAVE90:     RET                 ; return to caller
  499. SAVE        ENDP
  500.  
  501. ; ---------------------------------------------------------------------------
  502. ;   BLD_RESTORE - Build the restore program
  503. ; ---------------------------------------------------------------------------
  504. BLD_RESTORE PROC
  505.         MOV     AH, 2AH            ; ah = get date function call
  506.         INT     21H             ; issue DOS call
  507.  
  508.         MOV     WORD PTR RSTSDTE, CX    ; save year
  509.         MOV     WORD PTR RSTSDTE+2, DX  ; ..and month and day
  510.  
  511.         MOV     AH, 2CH            ; ah = get time function call
  512.         INT     21H             ; issue DOS call
  513.  
  514.         MOV     WORD PTR RSTSTME, CX    ; save hours and minutes
  515.         MOV     WORD PTR RSTSTME+2, DX  ; ..and seconds and hundredths
  516.  
  517.         MOV     SI, OFFSET DTA_ATTR     ; si -> source string
  518.         MOV     DI, OFFSET RSTATTR        ; di -> save area
  519.         MOV     CX, RST_FFLEN        ; cx = length to move
  520.     REP MOVSB                ; copy string
  521.  
  522.         MOV     DI, OFFSET HEADER_MSG   ; di -> program name
  523.         MOV     SI, OFFSET SPLICE        ; si -> restore program name
  524.         MOV     CX, 7            ; cx = length
  525.     REP MOVSB                ; .. setup program name
  526.  
  527.         MOV     SI, OFFSET DTA_NAME     ; si -> source file name
  528.         MOV     DI, OFFSET DESTFILE     ; di -> work file name
  529.         MOV     CX, 8            ; cx = length to move
  530.  
  531. BLD_REST10: LODSB                ; al = char from filename
  532.  
  533.         CMP     AL, "."                 ; q. end of filename?
  534.         JE        BLD_REST30            ; a. yes .. exit loop
  535.         OR        AL, AL            ; q. end of string?
  536.         JZ        BLD_REST20            ; a. yes .. exit loop
  537.  
  538.         STOSB                ; save character
  539.         LOOP    BLD_REST10            ; ..and loop till end of string
  540.  
  541. BLD_REST20: MOV     AL, "."                 ; assure file separator char
  542. BLD_REST30: STOSB                ; save the separator
  543.  
  544.         MOV     DESTEXT, DI         ; save pointer to file extension
  545.  
  546.         CMP     BYTE PTR [SI-1], "."    ; q. was extension found?
  547.         JNE     BLD_REST32            ; a. no .. allow default
  548.  
  549.         LODSB                ; get 1st char after extenstion
  550.         MOV     DESTEXTC, AL        ; ..and save for later
  551.  
  552. BLD_REST32: MOV     RSTFLAG, 1            ; set restore flag
  553.  
  554.         MOV     AL, DESTEXTC        ; al = 1st char of extension
  555.         MOV     DI, DESTEXT         ; di -> position in filename
  556.         STOSB                ; save 1st character
  557.         MOV     DESTEXT, DI         ; save pointer to 2nd char
  558.  
  559. BLD_REST35: MOV     DX, OFFSET SPLICEDRV    ; dx -> SPLICE program name
  560.         CALL    CREATE            ; create the new file
  561.  
  562.         PUSH    WORD PTR FLOPDRV        ; save drive parameter
  563.         PUSH    ARG             ; .. and ARG
  564.         MOV     FLOPDRV, 0            ; zero ..
  565.         MOV     ARG, 0            ; .. them out
  566.  
  567.         MOV     AH, 40H            ; ah = write function code
  568.         MOV     CX, OFFSET RESTLIMIT    ; cx = length to move
  569.         MOV     DX, OFFSET START        ; dx -> start of program
  570.         SUB     CX, DX            ; .. forget the PSP
  571.         INT     21H             ; issue DOS call
  572.  
  573.         POP     ARG             ; restore ..
  574.         POP     WORD PTR FLOPDRV        ; .. parameters
  575.         JC        BLD_REST40            ; if ok, continue
  576.  
  577.         CMP     AX, CX            ; q. all of pgm get out?
  578.         JE        BLD_REST50            ; a. yes .. continue
  579.  
  580. BLD_REST40: MOV     AH, 3EH            ; ah = close function
  581.         INT     21H             ; close file
  582.  
  583.         CALL    DELETE            ; delete output file
  584.         MOV     DX, OFFSET NOCOM        ; dx -> no room at the inn
  585.         CALL    HITKEY            ; ..issue message
  586.         JMP     BLD_REST35            ; ..and try with a new diskette
  587.  
  588. BLD_REST50: MOV     AH, 3EH            ; ah = close file
  589.         INT     21H             ; .. ask DOS to do it
  590.  
  591.         RET                 ; return to caller
  592. BLD_RESTORE ENDP
  593.  
  594. ; ---------------------------------------------------------------------------
  595. ;   WRITE - Write a file segment; ax = nbr of bytes to write (0 if EOF)
  596. ;                Exit: Carry set if EOF processing complete
  597. ; ---------------------------------------------------------------------------
  598. WRITE        PROC
  599.         MOV     BX, OHANDLE         ; bx = handle number
  600.         MOV     CX, AX            ; q. anything to write?
  601.         JCXZ    WRITE50            ; a. no .. EOF request
  602.  
  603.         MOV     DX, OFFSET BUFFER        ; dx -> start of buffer
  604.         OR        BX, BX            ; q. handle open?
  605.         JNZ     WRITE40            ; a. yes .. continue
  606.  
  607. WRITE05:    PUSH    CX                ; save length
  608.         PUSH    DX                ; ..and buffer address
  609.         CALL    NEXTFILE            ; build extension for next file
  610.  
  611. WRITE10:    MOV     DX, OFFSET FLOPDRV        ; dx -> file to create
  612.         CALL    CREATE            ; open new file
  613.  
  614.         MOV     OHANDLE, BX         ; save file handle
  615.         MOV     CX, RST_LEN         ; cx = length of header
  616.         CALL    HOWMUCH            ; update remaining disk space
  617.         MOV     AH, 40H            ; ah = write file function
  618.         MOV     DX, OFFSET RSTLAST        ; dx -> our file header
  619.         INT     21H             ; issue DOS call
  620.         JNC     WRITE20            ; if no error .. continue
  621.  
  622.         MOV     DX, OFFSET WRTERROR     ; dx -> error message
  623.         CALL    DIE             ; ..then display and die
  624.  
  625. WRITE20:    CMP     AX, CX            ; q. write out all of header?
  626.         JE        WRITE30            ; a. yes .. continue
  627.  
  628.         MOV     AH, 3EH            ; ah = close function
  629.         INT     21H             ; issue DOS call
  630.  
  631.         CALL    DELETE            ; delete new file
  632.  
  633.         MOV     DX, OFFSET NOROOM        ; dx -> next disk message
  634.         CALL    HITKEY            ; issue message and wait
  635.         JMP     WRITE10            ; ..try to get next file
  636.  
  637. WRITE30:    POP     DX                ; restore registers
  638.         POP     CX                ;
  639.  
  640. WRITE40:    CALL    HOWMUCH            ; get how much to write
  641.  
  642.         MOV     AH, 40H            ; ah = write file
  643.         INT     21H             ; issue DOS call
  644.         JNC     WRITE45            ; die on any error
  645.  
  646.         MOV     DX, OFFSET WRTERROR     ; dx -> general error msg
  647.         CALL    DIE             ; issue msg and terminate
  648.  
  649. WRITE45:    ADD     DX, AX            ; dx -> next buffer address
  650.         MOV     CX, DI            ; cx = remainder of bytes to write
  651.         JCXZ    WRITE48            ; if no more, exit
  652.  
  653.         PUSH    DX                ; save buffer address
  654.         MOV     AH, 3EH            ; ah = close function
  655.         INT     21H             ; issue DOS call
  656.  
  657.         MOV     DX, OFFSET NEXTDISK     ; dx -> next disk message
  658.         CALL    HITKEY            ; display message and wait
  659.         POP     DX                ; .. restore buffer address
  660.         JMP     WRITE05            ; ..then get next file
  661.  
  662. WRITE48:    CLC                 ; clear carry for caller
  663.         RET                 ; ..and return
  664.  
  665.  
  666. WRITE50:    OR        BX, BX            ; q. handle open?
  667.         JZ        WRITE60            ; a. no .. continue
  668.  
  669.         MOV     AX, 4200H            ; ah = position file
  670.         XOR     CX, CX            ; cx = file position
  671.         XOR     DX, DX            ; dx = msb of file position
  672.         INT     21H             ; position to top of file
  673.  
  674.         MOV     RSTLAST, 1            ; set flag
  675.         MOV     AH, 40H            ; ah = write function
  676.         MOV     CX, 1            ; cx = length
  677.         MOV     DX, OFFSET RSTLAST        ; dx -> buffer
  678.         INT     21H             ; write eof marker in header
  679.  
  680.         MOV     AH, 3EH            ; ah = close function
  681.         INT     21H             ; issue DOS call
  682.  
  683. WRITE60:    STC                 ; set carry flag
  684.         RET                 ; ..and return to caller
  685. WRITE        ENDP
  686.  
  687. ; ---------------------------------------------------------------------------
  688. ;   HOWMUCH - Calculate how much to write; cx = requested amount to write
  689. ;                     Exit: cx = nbr of bytes which will fit
  690. ;                       di = remainder
  691. ; ---------------------------------------------------------------------------
  692. HOWMUCH     PROC
  693.         PUSH    DX                ; save registers
  694.  
  695.         MOV     AX, WORD PTR AVAIL        ; get howmuch is available
  696.         MOV     DX, WORD PTR AVAIL+2    ; . . . .
  697.         MOV     DI, 0            ; assume everything will fit
  698.  
  699.         OR        DX, DX            ; q. more than 64k?
  700.         JNZ     HOWMUCH80            ; a. no .. must be less than 64k
  701.  
  702.         CMP     CX, AX            ; q. enough room left?
  703.         JNA     HOWMUCH80            ; a. yes .. use it all
  704.  
  705.         MOV     DI, CX            ; di = nbr requested
  706.         SUB     DI, AX            ; di = remainder
  707.         MOV     CX, AX            ; cx = nbr to write
  708.  
  709. HOWMUCH80:  SUB     AX, CX            ; ax = new available
  710.         SBB     DX, 0            ; dx:ax = new available
  711.         MOV     WORD PTR AVAIL, AX        ; store for later
  712.         MOV     WORD PTR AVAIL+2, DX    ; . . . .
  713.  
  714. HOWMUCH90:  POP     DX                ; restore registers
  715.         RET                 ; ..and return
  716. HOWMUCH     ENDP
  717.  
  718. ; ---------------------------------------------------------------------------
  719. ;   CREATE - Create new file; dx -> file to open
  720. ;            Exit: bx = handle of opened file
  721. ; ---------------------------------------------------------------------------
  722. CREATE        PROC
  723.         MOV     BP, DX            ; save file name pointer
  724.  
  725. CREATE10:   MOV     AH, 36H            ; ah = get drive info
  726.         MOV     DL, FLOPDRV         ; dl = drive letter
  727.         SUB     DL, "@"                 ; dl = drive number
  728.         INT     21H             ; get free space
  729.  
  730.         CMP     AX, -1            ; q. drive ok?
  731.         JE        CREATE15            ; a. no .. next disk
  732.  
  733.         OR        BX, BX            ; q. any clusters available?
  734.         JNZ     CREATE18            ; a. yes .. build new file
  735.  
  736. CREATE15:   MOV     DX, OFFSET NOROOM        ; dx -> no room at inn message
  737.         CALL    HITKEY            ; get new diskette
  738.         JMP     CREATE10            ; ..try again
  739.  
  740. CREATE18:   MUL     BX                ; dx:ax = nbr of sectors available
  741.         MUL     CX                ; dx:ax = nbr of bytes available
  742.         MOV     WORD PTR AVAIL, AX        ; store howmuch is available
  743.         MOV     WORD PTR AVAIL+2, DX    ; . . . .
  744.  
  745.         MOV     AH, 4EH            ; ah = find first function code
  746.         MOV     CX, 0FFH            ; cx = any attributes
  747.         MOV     DX, BP            ; dx -> filename
  748.         INT     21H             ; issue DOS call
  749.         JC        CREATE20            ; if not available, create it
  750.  
  751.         MOV     DX, OFFSET FILEFND        ; dx -> file found message
  752.         CALL    HITKEY            ; let user change diskette
  753.         JMP     CREATE10            ; ..then try again
  754.  
  755. CREATE20:   MOV     AH, 3CH            ; ah = create function code
  756.         XOR     CX, CX            ; cx = no (special) attributes
  757.         INT     21H             ; issue DOS call
  758.         JNC     CREATE90            ; if problems, exit
  759.  
  760.         MOV     DX, OFFSET NOCREATE     ; dx -> create error message
  761.         CALL    DIE             ; ..and die
  762.  
  763. CREATE90:   MOV     BX, AX            ; bx = handle
  764.         RET                 ; ..and return to caller
  765. CREATE        ENDP
  766.  
  767. ; ---------------------------------------------------------------------------
  768. ;   DELETE - Delete a file
  769. ; ---------------------------------------------------------------------------
  770. DELETE        PROC
  771.         MOV     AH, 41H            ; ah = delete function
  772.         MOV     DX, OFFSET FLOPDRV        ; dx -> filename
  773.         INT     21H             ; issue DOS call
  774.  
  775.         RET                 ; ..and return
  776. DELETE        ENDP
  777.  
  778. ; ---------------------------------------------------------------------------
  779. ;   Uninitialized data areas
  780. ; ---------------------------------------------------------------------------
  781. UDATA        EQU     $                ; start of unitialized data
  782. ROPENFILE   EQU     BYTE PTR UDATA        ; word area for ropen
  783. AVAIL        EQU     DWORD PTR ROPENFILE+65  ; available output space
  784. BUFFER        EQU     BYTE PTR AVAIL+4        ; file buffer
  785. BUFLEN        EQU     32*1024            ; length of buffer
  786.  
  787. CSEG        ENDS                ; end of code segment
  788.         END     START
  789.