home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power-Programmierung
/
CD1.mdf
/
magazine
/
pcmagazi
/
1989
/
09
/
split.asm
< prev
next >
Wrap
Assembly Source File
|
1989-01-29
|
32KB
|
814 lines
PAGE 78,132
TITLE "SPLIT - Break file for multiple diskettes"
CSEG SEGMENT PARA PUBLIC 'CODE'
ASSUME CS:CSEG, DS:CSEG, ES:CSEG, SS:CSEG
; ---------------------------------------------------------------------------
; DTA structure for DOS "find matching" call
; ---------------------------------------------------------------------------
ORG 80H ; dta offset
DTA DB 21 dup (0) ; start of find file area
DTA_ATTR DB 0 ; file attribute
DTA_TIME DW 0 ; file time
DTA_DATE DW 0 ; file date
DTA_LSIZ DW 0 ; file lsw of size
DTA_HSIZ DW 0 ; file msw of size
DTA_NAME DB 12 DUP (0) ; file name of file
DTA_LEN EQU $-DTA ; length of dta find entry
ORG 100H ; start of program area
START: JMP MAIN ; go to the code
; ---------------------------------------------------------------------------
; Common initialized work areas
; ---------------------------------------------------------------------------
ARG DW 0 ; addr of first argument
FLOPDRV DB 0,":\" ; output drive letter
DESTFILE DB " ",0 ; output file name
DESTEXT DW 0 ; pointer to extension
DESTEXTC DB "0" ; 1st character of extension
DESTNBR DW 1 ; file extension counter
RSTFLAG DB 0 ; split/restore flag
CURRDIR DB ".",0 ; argument for current directory
IHANDLE DW 0 ; input file handle
OHANDLE DW 0 ; output file handle
; ---------------------------------------------------------------------------
; Messages to user
; ---------------------------------------------------------------------------
HEADER_MSG DB "SPLIT 1.0 - (c) 1989 Ziff Communications Co.",0DH,0AH
DB "PC Magazine ",254," Bob Flanders & Michael Holmes",0AH
DB 0DH,0AH
DOLLAR DB "$"
FILENF DB "File not found$"
NOCREATE DB "Error opening output$"
NOROOM DB "Not enough room, try another$"
WRONGDISK DB "Wrong restore disk, insert number "
DISKNO DB "XX$"
DRVNR DB "Must be removable media$"
RDERROR DB "Error reading input$"
WRTERROR DB "Error writing output$"
FILEFND DB "File exists$"
NEXTDISK DB "Insert #"
DISKNO2 DB "XX$"
HITANYKEY DB ", Press any key ..",07H,0DH,0AH,"$"
FORMAT DB 0DH,0AH,"format:",09H,"$"
RSFORM DB "UNSPLIT d: d:[\path]",0DH,0AH,"$"
RESTORING DB "Restoring: "
RESTFILE DB 12 DUP (" "),0DH,0AH,"$"
; ---------------------------------------------------------------------------
; File ID Header
; ---------------------------------------------------------------------------
RSTLAST DB 0 ; last file flag
RSTATTR DB 0 ; file attributes
RSTTIME DW 0 ; file time
RSTDATE DW 0 ; file date
RSTLSIZ DW 0 ; file lsw of size
RSTHSIZ DW 0 ; file msw of size
RSTNAME DB 12 DUP (0) ; file name of file
RST_FFLEN EQU $-RSTATTR ; length to move from ff area
RSTSDTE DD 0 ; date ..
RSTSTME DD 0 ; ..and time of save
RST_LEN EQU $-RSTLAST ; length of our file header
; ---------------------------------------------------------------------------
; MAIN - Mainline of program
; ---------------------------------------------------------------------------
MAIN PROC ; start of program
CMP RSTFLAG, 0 ; q. restoring?
JNZ RESTORE ; a. goto restore section
CALL INIT ; initialize program
CALL PARMS ; check parameters
CALL OPEN ; open the input file
CALL SAVE ; copy/split the file to output
JMP SHORT MAIN10 ; return to dos
RESTORE: CALL INIT ; perform restore setup
CALL PARMS ; check parameters
CALL ROPEN ; open the output file
CALL RFILE ; restore the file
MAIN10: MOV DX, OFFSET DOLLAR ; dx -> null message
CALL DIE ; .. say goodnight
MAIN ENDP
; ---------------------------------------------------------------------------
; INIT - Handle initialization
; ---------------------------------------------------------------------------
INIT PROC
CLD ; assure ascending
MOV DX, OFFSET HEADER_MSG ; dx -> header message
MOV AH, 9 ; ah = print ascii$ message
INT 21H ; .. ask DOS to do it
RET ; return to caller
INIT ENDP
; ---------------------------------------------------------------------------
; ROPEN - open the file to restore
; ---------------------------------------------------------------------------
ROPEN PROC
MOV DI, OFFSET ROPENFILE ; di -> work area
MOV SI, ARG ; si -> where to restore
ROPEN10: MOVSB ; move a character
CMP BYTE PTR [SI], 0 ; q. end of parm?
JNE ROPEN10 ; a. yes .. continue
CMP BYTE PTR [DI-1], "\" ; q. last byte a back-slash?
JE ROPEN20 ; a. yes .. continue
CMP BYTE PTR [DI-1],":" ; q. last byte a colon (drive)?
JE ROPEN20 ; a. yes .. continue
MOV AL, "\" ; end as directory
STOSB
ROPEN20: MOV SI, OFFSET RSTNAME ; si -> name of original file
MOV BX, OFFSET RESTFILE ; bx -> restore filename
ROPEN30: LODSB ; al = char of filename
STOSB ; .. save it
OR AL, AL ; q. end of file name?
JZ ROPEN40 ; a. yes .. continue
MOV [BX], AL ; save in message
INC BX ; bx -> next char
JMP ROPEN30 ; .. continue
ROPEN40: MOV AH, 4EH ; ah = find first
MOV DX, OFFSET ROPENFILE ; dx -> file to find
MOV CX, 0FFH ; .. any attribute
INT 21H ; q. file found?
JC ROPEN45 ; a. no .. continue
MOV DX, OFFSET FILEFND ; dx -> file already exists
CALL DIE ; .. push up some daisies
ROPEN45: MOV AH, 3CH ; ah = create function code
MOV CL, RSTATTR ; cx = original attributes
XOR CH,CH ; .. upper byte off
INT 21H ; issue DOS call
JNC ROPEN50 ; if no problems, continue
MOV DX, OFFSET NOCREATE ; dx -> create error message
CALL DIE ; .. go deep six
ROPEN50: MOV OHANDLE, AX ; save the file handle
MOV DX, OFFSET RESTORING ; dx -> restore message
MOV AH, 09H ; ah = print ascii$
INT 21H ; .. tell the user
RET ; return to caller
ROPEN ENDP
; ---------------------------------------------------------------------------
; RFILE - restore file
; ---------------------------------------------------------------------------
RFILE PROC
CALL NEXTFILE ; create a file name
RFILE10: MOV DX, OFFSET FLOPDRV ; dx -> file name
MOV AX, 3D00H ; al = open for read
INT 21H ; .. ask DOS to do it.
JNC RFILE20 ; ok .. continue
RFILE15: MOV DX, OFFSET WRONGDISK ; dx -> wrong disk message
CALL HITKEY ; .. display and wait
JMP RFILE10 ; .. and try again
RFILE20: MOV IHANDLE, AX ; save file handle
MOV BX, AX ; bx = handle
MOV AH, 03FH ; ah = read file
MOV CX, RST_LEN ; cx = len to read
MOV DX, OFFSET BUFFER ; dx -> buffer to read
INT 21H ; read a buffer
JC RFILE35 ; tell 'em we cant read it
MOV SI, DX ; si -> buffer
MOV DI, OFFSET RSTLAST ; di -> our header
MOVSB ; move last flag, setup for compare
MOV CX, RST_LEN-1 ; cx = bytes to check
REPE CMPSB ; q. headers the same?
JE RFILE30 ; a. yes .. continue
MOV AH, 3EH ; ah = close file
INT 21H ; close output file
MOV IHANDLE, 0 ; .. show file not open
JMP RFILE15 ; tell 'em
RFILE30: MOV AH, 03FH ; ah = read file
MOV BX, IHANDLE ; bx = handle of file to read
MOV CX, BUFLEN ; cx = amount to read
MOV DX, OFFSET BUFFER ; dx -> buffer
INT 21H ; read, please
JNC RFILE40 ; if no error .. continue
RFILE35: MOV DX, OFFSET RDERROR ; dx -> read error message
CALL DIE ; ..and die gracefully
RFILE40: MOV CX, AX ; cx = bytes to write
JCXZ RFILE80 ; if finished .. exit loop
MOV AH, 40H ; ax = write
MOV BX, OHANDLE ; bx = output file handle
INT 21H ; write a buffer
JC RFILE50 ; error .. die
CMP AX, CX ; q. able to write it?
JE RFILE30 ; a. no .. tell 'em
MOV DI, OFFSET NOROOM ; di -> wontfit msg
JMP SHORT RFILE60 ; ..and exit gracefully
RFILE50: MOV DI, OFFSET WRTERROR ; di -> write error message
RFILE60: MOV AH, 41H ; ah = delete function
MOV DX, OFFSET ROPENFILE ; dx -> filename
INT 21H ; issue DOS call
MOV DX, DI ; dx -> error message to give
CALL DIE ; ..make my day, punk!
RFILE80: MOV AH, 3EH ; ah = close file
INT 21H ; close input file
MOV IHANDLE, 0 ; .. clear the input handle
CMP RSTLAST, 0 ; q. end of file
JNE RFILE90 ; a. no .. continue
MOV DX, OFFSET NEXTDISK ; dx -> next disk message
CALL HITKEY ; display message and wait
JMP RFILE ; .. get next file
RFILE90: MOV DX, RSTDATE ; dx = original file date
MOV CX, RSTTIME ; cx = original file time
MOV BX, OHANDLE ; bx = output file handle
MOV AX, 5701H ; ax = set file date & time
INT 21H ; .. Please, Mr. DOS?
RET ; .. return to caller
RFILE ENDP
; ---------------------------------------------------------------------------
; NEXTFILE - Build next filename
; ---------------------------------------------------------------------------
NEXTFILE PROC
MOV AX, DESTNBR ; ax = current count
PUSH AX ; .. save the value
MOV BL, 10 ; bl = divisor
DIV BL ; ax = almost ascii nbr
OR AX, 3030H ; ax = ascii values
MOV BX, DESTEXT ; bx -> 2nd char of extension
MOV [BX], AX ; store rest of extension
MOV WORD PTR DISKNO, AX ; .. and in message
POP AX ; ax = current count
INC AX ; ax = next count
MOV DESTNBR, AX ; .. save new count
MOV BL, 10 ; bl = divisor
DIV BL ; ax = almost ascii nbr
OR AX, 3030H ; ax = ascii values
MOV WORD PTR DISKNO2, AX ; ..
RET ; ..and return to caller
NEXTFILE ENDP
; ---------------------------------------------------------------------------
; HITKEY - Allow user to change diskettes; dx -> first message
; ---------------------------------------------------------------------------
HITKEY PROC
MOV AH, 9H ; ah = print string
INT 21H ; .. call dos to print message
MOV DX, OFFSET HITANYKEY ; dx -> prompt
INT 21H ; issue prompt message
MOV AX, 0C08H ; ax = clear buffer, wait for key
INT 21H ; issue DOS call
OR AL, AL ; q. function key hit?
JNZ HITKEY90 ; a. no .. exit
MOV AH, 08H ; ah = wait for key
INT 21H ; issue DOS call
HITKEY90: RET
HITKEY ENDP
; ---------------------------------------------------------------------------
; PARMS - Parses the command line
; ---------------------------------------------------------------------------
PARMS PROC
CALL UPCASE ; upper case the parm area
MOV SI, 81H ; si -> parms area
PARMS10: LODSB ; get parameter character
CMP AL, 0DH ; q. end of line?
JE PARMS50 ; a. yes .. exit
CMP AL, " " ; q. blank?
JNA PARMS10 ; a. yes .. skip
CALL ARGCHK ; set the argument
JC PARMSERR ; .. die on an error
PARMS30: LODSB ; get next character
CMP AL, 0DH ; q. end of line?
JE PARMS50 ; a. yes .. process
CMP AL, " " ; q. end of PARMS?
JA PARMS30 ; a. no .. next char
MOV BYTE PTR [SI-1], 0 ; end the parameter
JMP PARMS10 ; .. look for next
PARMS50: MOV BYTE PTR [SI-1], 0 ; end the parameter
CMP ARG, 0 ; q. PARMS 1 available?
JNE PARMS60 ; a. no .. error
CMP RSTFLAG, 0 ; q. restoring?
JE PARMSERR ; a. no .. error
MOV ARG, OFFSET CURRDIR ; arg -> current directory
PARMS60: CMP FLOPDRV, 0 ; q. Drive given?
JE PARMSERR ; a. no .. error also
RET ; .. else .. return to caller
PARMSERR: MOV DX, OFFSET FORMAT ; dx -> format message
MOV AH, 09H ; ah = print ascii$
INT 21H ; hey DOS .. print it!
MOV DX, OFFSET RSFORM ; dx -> restore format
CMP RSTFLAG, 0 ; q. restore?
JNZ PARMSERR1 ; a. yes .. die now
MOV DX, OFFSET SPFORM ; dx -> split format
PARMSERR1: CALL DIE ; .. play taps
PARMS ENDP
; ---------------------------------------------------------------------------
; ARGCHK - Setup pointers to command line args; si -> 2nd char in arg
; Exit: ARG or FLOPDRV filled in; Carry set if > 2 args
; ---------------------------------------------------------------------------
ARGCHK PROC
LEA BX, [SI-1] ; bx -> argument
CMP RSTFLAG, 0 ; q. restoring?
JE ARG05 ; a. no .. continue
CMP FLOPDRV, 0 ; q. drive filled in?
JE ARG20 ; a. no .. fill it in
ARG05: CMP ARG, 0 ; q. ARG filled in?
JNE ARG10 ; a. yes .. check 2
MOV ARG, BX ; save ARG pointer
JMP SHORT ARG90 ; .. exit ok!
ARG10: CMP FLOPDRV, 0 ; q. drive filled in?
JE ARG20 ; a. no .. fill it in
STC ; else .. error
RET ; .. and return to caller
ARG20: MOV FLOPDRV, AL ; save drive
MOV UNSPLITDRV, AL ; .. in file and program names
MOV BL, AL ; bl = drive letter
SUB BL, "@" ; bl = drive number
MOV AX, 4408H ; ax = ioctl, removable?
INT 21H ; issue DOS call
OR AL, AL ; q. removable media drive?
JZ ARG90 ; a. yes .. return
MOV DX, OFFSET DRVNR ; dx -> error message
CALL DIE ; issue non-removable message
ARG90: CLC ; show no error
RET ; return to caller
ARGCHK ENDP
; ---------------------------------------------------------------------------
; UPCASE - Convert command line arguments to uppercase
; ---------------------------------------------------------------------------
UPCASE PROC
PUSH SI ; save caller regs
PUSH DI
MOV SI, 81H ; si -> start of parm area
MOV DI, SI ; .. same for di
CLD ; .. assure ascending
UPCASE10: LODSB ; al = char
CMP AL, 0DH ; q. end of line?
JE UPCASE90 ; a. yes .. end of line!
CMP AL, "a" ; q. is it below 'a'?
JB UPCASE20 ; a. yes .. continue
CMP AL, "z" ; q. is it above 'z'?
JA UPCASE20 ; a. yes .. continue
SUB AL, 20H ; set to upper case
UPCASE20: STOSB ; save the byte
JMP UPCASE10 ; .. and continue
UPCASE90: POP DI ; restore caller regs
POP SI
RET ; .. and return to caller
UPCASE ENDP
; ---------------------------------------------------------------------------
; DIE - Display an error message and return to DOS; dx -> ascii$ error msg
; ---------------------------------------------------------------------------
DIE PROC
MOV AH, 9H ; ah = print string
INT 21H ; .. call dos to print error
MOV BX, IHANDLE ; bx = input file handle
OR BX, BX ; q. file opened?
JZ DIE90 ; a. no .. try output file
MOV AH, 3EH ; ah = close file
INT 21H ; .. ask DOS to do it
DIE90: MOV BX, OHANDLE ; bx = output file handle
OR BX, BX ; q. file opened?
JZ DIE95 ; a. no .. just exit
MOV AH, 3EH ; ah = close file
INT 21H ; .. ask DOS to do it
DIE95: MOV AX, 4C00H ; ax = exit
INT 21H ; .. terminate routine
DIE ENDP
RESTLIMIT EQU $ ; only need up to here
; ---------------------------------------------------------------------------
; Split only areas and messages
; ---------------------------------------------------------------------------
SPFORM DB "SPLIT [d:\path\]filename[.ext] "
DB " d:",0DH,0AH,0AH,"$"
ZEROLEN DB "Input file empty",0DH,0AH,"$"
NOCOM DB "Program won't fit",0DH,0AH,"$"
UNSPLITDRV DB "x:\"
UNSPLIT DB "UNSPLIT.COM",0
; ---------------------------------------------------------------------------
; OPEN - Opens next file to process; Carry indicates file would not open.
; ---------------------------------------------------------------------------
OPEN PROC
MOV DX, ARG ; dx -> file name
MOV AX, 3D00H ; al = open for read
INT 21H ; .. ask DOS to do it.
JC OPEN05 ; ok .. continue
MOV IHANDLE, AX ; save file handle
MOV AH, 4EH ; ah = find first
MOV DX, ARG ; dx -> file to find
XOR CX, CX ; cx = search attribute
INT 21H ; q. find first file ok?
JNC OPEN10 ; a. yes .. continue
OPEN05: MOV DX, OFFSET FILENF ; dx -> file not found
CALL DIE ; .. gasp your final breath
OPEN10: MOV AX, DS:DTA_LSIZ ; ax = lsw of size
OR AX, DS:DTA_HSIZ ; q. any data?
JNZ OPEN90 ; a. yes ..continue
MOV DX, OFFSET ZEROLEN ; dx -> file contains no data
CALL DIE ; .. dearly beloved ...
OPEN90: RET
OPEN ENDP
; ---------------------------------------------------------------------------
; SAVE - Handle building split files on destination
; ---------------------------------------------------------------------------
SAVE PROC
CALL BLD_RESTORE ; build restore program
SAVE10: MOV AH, 03FH ; ah = read file
MOV BX, IHANDLE ; bx = handle of file to read
MOV CX, BUFLEN ; cx = amount to read
MOV DX, OFFSET BUFFER ; dx -> buffer
INT 21H ; read, please
JNC SAVE20 ; if no error .. continue
MOV DX, OFFSET RDERROR ; dx -> read error message
CALL DIE ; ..and die gracefully
SAVE20: CALL WRITE ; ..and write out a buffer full
JC SAVE90 ; if finished .. exit loop
JMP SAVE10 ; else .. get next buffer
SAVE90: RET ; return to caller
SAVE ENDP
; ---------------------------------------------------------------------------
; BLD_RESTORE - Build the restore program
; ---------------------------------------------------------------------------
BLD_RESTORE PROC
MOV AH, 2AH ; ah = get date function call
INT 21H ; issue DOS call
MOV WORD PTR RSTSDTE, CX ; save year
MOV WORD PTR RSTSDTE+2, DX ; ..and month and day
MOV AH, 2CH ; ah = get time function call
INT 21H ; issue DOS call
MOV WORD PTR RSTSTME, CX ; save hours and minutes
MOV WORD PTR RSTSTME+2, DX ; ..and seconds and hundredths
MOV SI, OFFSET DTA_ATTR ; si -> source string
MOV DI, OFFSET RSTATTR ; di -> save area
MOV CX, RST_FFLEN ; cx = length to move
REP MOVSB ; copy string
MOV DI, OFFSET HEADER_MSG ; di -> program name
MOV SI, OFFSET UNSPLIT ; si -> restore program name
MOV CX, 7 ; cx = length
REP MOVSB ; .. setup program name
MOV SI, OFFSET DTA_NAME ; si -> source file name
MOV DI, OFFSET DESTFILE ; di -> work file name
MOV CX, 8 ; cx = length to move
BLD_REST10: LODSB ; al = char from filename
CMP AL, "." ; q. end of filename?
JE BLD_REST30 ; a. yes .. exit loop
OR AL, AL ; q. end of string?
JZ BLD_REST20 ; a. yes .. exit loop
STOSB ; save character
LOOP BLD_REST10 ; ..and loop till end of string
BLD_REST20: MOV AL, "." ; assure file separator char
BLD_REST30: STOSB ; save the separator
MOV DESTEXT, DI ; save pointer to file extension
CMP BYTE PTR [SI-1], "." ; q. was extension found?
JNE BLD_REST32 ; a. no .. allow default
LODSB ; get 1st char after extenstion
MOV DESTEXTC, AL ; ..and save for later
BLD_REST32: MOV RSTFLAG, 1 ; set restore flag
MOV AL, DESTEXTC ; al = 1st char of extension
MOV DI, DESTEXT ; di -> position in filename
STOSB ; save 1st character
MOV DESTEXT, DI ; save pointer to 2nd char
BLD_REST35: MOV DX, OFFSET UNSPLITDRV ; dx -> UNSPLIT program name
CALL CREATE ; create the new file
PUSH WORD PTR FLOPDRV ; save drive parameter
PUSH ARG ; .. and ARG
MOV FLOPDRV, 0 ; zero ..
MOV ARG, 0 ; .. them out
MOV AH, 40H ; ah = write function code
MOV CX, OFFSET RESTLIMIT ; cx = length to move
MOV DX, OFFSET START ; dx -> start of program
SUB CX, DX ; .. forget the PSP
INT 21H ; issue DOS call
POP ARG ; restore ..
POP WORD PTR FLOPDRV ; .. parameters
JC BLD_REST40 ; if error .. try again
CMP AX, CX ; q. all of pgm get out?
JE BLD_REST50 ; a. yes .. continue
BLD_REST40: MOV AH, 3EH ; ah = close function
INT 21H ; close file
CALL DELETE ; delete output file
MOV DX, OFFSET NOCOM ; dx -> no room at the inn
CALL HITKEY ; ..issue message
JMP BLD_REST35 ; ..and try with a new diskette
BLD_REST50: MOV AH, 3EH ; ah = close file
INT 21H ; .. ask DOS to do it
RET ; return to caller
BLD_RESTORE ENDP
; ---------------------------------------------------------------------------
; WRITE - Write a file segment; ax = nbr of bytes to write (0 if EOF)
; Exit: Carry set if EOF processing complete
; ---------------------------------------------------------------------------
WRITE PROC
MOV BX, OHANDLE ; bx = handle number
MOV CX, AX ; q. anything to write?
JCXZ WRITE50 ; a. no .. EOF request
MOV DX, OFFSET BUFFER ; dx -> start of buffer
OR BX, BX ; q. handle open?
JNZ WRITE40 ; a. yes .. continue
WRITE05: PUSH CX ; save length
PUSH DX ; ..and buffer address
CALL NEXTFILE ; build extension for next file
WRITE10: MOV DX, OFFSET FLOPDRV ; dx -> file to create
CALL CREATE ; open new file
MOV OHANDLE, BX ; save file handle
MOV CX, RST_LEN ; cx = length of header
CALL HOWMUCH ; update remaining disk space
MOV AH, 40H ; ah = write file function
MOV DX, OFFSET RSTLAST ; dx -> our file header
INT 21H ; issue DOS call
JNC WRITE20 ; if no error .. continue
MOV DX, OFFSET WRTERROR ; dx -> error message
CALL DIE ; ..then display and die
WRITE20: CMP AX, CX ; q. write out all of header?
JE WRITE30 ; a. yes .. continue
MOV AH, 3EH ; ah = close function
INT 21H ; issue DOS call
MOV OHANDLE, 0 ; .. show file closed
CALL DELETE ; delete new file
MOV DX, OFFSET NOROOM ; dx -> next disk message
CALL HITKEY ; issue message and wait
JMP WRITE10 ; ..try to get next file
WRITE30: POP DX ; restore registers
POP CX ;
WRITE40: CALL HOWMUCH ; get how much to write
MOV AH, 40H ; ah = write file
INT 21H ; issue DOS call
JNC WRITE45 ; die on any error
MOV DX, OFFSET WRTERROR ; dx -> general error msg
CALL DIE ; issue msg and terminate
WRITE45: ADD DX, AX ; dx -> next buffer address
MOV CX, DI ; cx = remainder of bytes to write
JCXZ WRITE48 ; if no more, exit
PUSH DX ; save buffer address
MOV AH, 3EH ; ah = close function
INT 21H ; issue DOS call
MOV OHANDLE, 0 ; .. show file closed
MOV DX, OFFSET NEXTDISK ; dx -> next disk message
CALL HITKEY ; display message and wait
POP DX ; .. restore buffer address
JMP WRITE05 ; ..then get next file
WRITE48: CLC ; clear carry for caller
RET ; ..and return
WRITE50: OR BX, BX ; q. handle open?
JZ WRITE60 ; a. no .. continue
MOV AX, 4200H ; ah = position file
XOR CX, CX ; cx = file position
XOR DX, DX ; dx = msb of file position
INT 21H ; position to top of file
MOV RSTLAST, 1 ; set flag
MOV AH, 40H ; ah = write function
MOV CX, 1 ; cx = length
MOV DX, OFFSET RSTLAST ; dx -> buffer
INT 21H ; write eof marker in header
MOV AH, 3EH ; ah = close function
INT 21H ; issue DOS call
MOV OHANDLE, 0 ; .. show file closed
WRITE60: STC ; set carry flag
RET ; ..and return to caller
WRITE ENDP
; ---------------------------------------------------------------------------
; HOWMUCH - Calculate how much to write; cx = requested amount to write
; Exit: cx = nbr of bytes which will fit
; di = remainder
; ---------------------------------------------------------------------------
HOWMUCH PROC
PUSH DX ; save registers
MOV AX, WORD PTR AVAIL ; get howmuch is available
MOV DX, WORD PTR AVAIL+2 ; . . . .
MOV DI, 0 ; assume everything will fit
OR DX, DX ; q. more than 64k?
JNZ HOWMUCH80 ; a. no .. must be less than 64k
CMP CX, AX ; q. enough room left?
JNA HOWMUCH80 ; a. yes .. use it all
MOV DI, CX ; di = nbr requested
SUB DI, AX ; di = remainder
MOV CX, AX ; cx = nbr to write
HOWMUCH80: SUB AX, CX ; ax = new available
SBB DX, 0 ; dx:ax = new available
MOV WORD PTR AVAIL, AX ; store for later
MOV WORD PTR AVAIL+2, DX ; . . . .
HOWMUCH90: POP DX ; restore registers
RET ; ..and return
HOWMUCH ENDP
; ---------------------------------------------------------------------------
; CREATE - Create new file; dx -> file to open
; Exit: bx = handle of opened file
; ---------------------------------------------------------------------------
CREATE PROC
MOV BP, DX ; save file name pointer
CREATE10: MOV AH, 36H ; ah = get drive info
MOV DL, FLOPDRV ; dl = drive letter
SUB DL, "@" ; dl = drive number
INT 21H ; get free space
CMP AX, -1 ; q. drive ok?
JE CREATE15 ; a. no .. next disk
OR BX, BX ; q. any clusters available?
JNZ CREATE18 ; a. yes .. build new file
CREATE15: MOV DX, OFFSET NOROOM ; dx -> no room at inn message
CALL HITKEY ; get new diskette
JMP CREATE10 ; ..try again
CREATE18: MUL BX ; dx:ax = nbr of sectors available
MUL CX ; dx:ax = nbr of bytes available
MOV WORD PTR AVAIL, AX ; store howmuch is available
MOV WORD PTR AVAIL+2, DX ; . . . .
MOV AH, 4EH ; ah = find first function code
MOV CX, 0FFH ; cx = any attributes
MOV DX, BP ; dx -> filename
INT 21H ; issue DOS call
JC CREATE20 ; if not available, create it
MOV DX, OFFSET FILEFND ; dx -> file found message
CALL HITKEY ; let user change diskette
JMP CREATE10 ; ..then try again
CREATE20: MOV AH, 3CH ; ah = create function code
XOR CX, CX ; cx = no (special) attributes
INT 21H ; issue DOS call
JNC CREATE90 ; if problems, exit
MOV DX, OFFSET NOCREATE ; dx -> create error message
CALL DIE ; ..and die
CREATE90: MOV BX, AX ; bx = handle
RET ; ..and return to caller
CREATE ENDP
; ---------------------------------------------------------------------------
; DELETE - Delete a file
; ---------------------------------------------------------------------------
DELETE PROC
MOV AH, 41H ; ah = delete function
MOV DX, OFFSET FLOPDRV ; dx -> filename
INT 21H ; issue DOS call
RET ; ..and return
DELETE ENDP
; ---------------------------------------------------------------------------
; Uninitialized data areas
; ---------------------------------------------------------------------------
UDATA EQU $ ; start of unitialized data
ROPENFILE EQU BYTE PTR UDATA ; word area for ropen
AVAIL EQU DWORD PTR ROPENFILE+65 ; available output space
BUFFER EQU BYTE PTR AVAIL+4 ; file buffer
BUFLEN EQU 32*1024 ; length of buffer
CSEG ENDS ; end of code segment
END START