home *** CD-ROM | disk | FTP | other *** search
- ;********* S E N D D I S K . A S M *******************************************
- ; A disk duplication utility to allow all sectors (including boot)
- ; of a floppy disk to be transmitted via a temporary file over a
- ; modem and replaced on another floppy disk. With this utility,
- ; you should be able to distribute the IBM PC-DOS 4.0 fix disks
- ; with the SBBS system. The temporary file is 368,640 bytes long
- ; for a 360k diskette and twice that for a 720k diskette. This is long,
- ; but length should compress nicely using pkarc or equivalent.
- ; The .exe version of this file needs to be included in the .ARC
- ; file distributed to enable recreation of the disk.
- ;
- ; This program will allow a BOOTABLE disk to be transmitted via a
- ; modem and recreated at another location.
- ;
- ; created 2 November 1988
- ; Jim Offenbecher, Software Librarian, Huntsville PC Users Group
- ; 13920 Creely Drive SW
- ; Huntsville, AL 35803
- ; Tel: [H] (205) 882-3205
- ; [W] (205) 881-5741
- ;
- ; modified to: 1. Allow 720k disk usage with message showing type.
- ; 2. Check file length prior to disk write.
- ; 3. Comment the source code.
- ; 4 November 1988 - jko (per conversation with IBM SBBS)
- ;
- ; This program including source code is hereby placed in the
- ; Public Domain for all to use. This program including source
- ; code may be freely distributed provided that no fee is charged
- ; for it or it's distribution. Feel free to modify it providing
- ; original credits are retained - it is quick and dirty to allow
- ; early distribution of the DOS 4.0 fixes...
- ; yes I know the error exits don't reset the stack on exit...
- ; assemble with MASM 5.0 or above - no macros or libraries needed.
-
- .model small
-
- .data
- cr equ 0dh
- lf equ 0ah
-
- secsiz equ 512
- sectrk equ 9
- ;track count for 3.5" 720k disks
- trks7 equ 80
- ;track count for 5.25" 360k disks
- trks equ 40
- sides equ 2
- trklen equ secsiz * sectrk
-
- ; number of clusters to check for when IDing the floppy
- ; if it's more than this, and the FAT ID is 0F9h, then it's a
- ; 5.25" 1.2 Meg and not a 720k 3.5" diskette...
-
- clustchk equ 750
-
- signon db ' SENDDISK.EXE',cr,lf
- db cr,lf
- db 'A Utility program to allow the IBM SBBS to',cr,lf
- db 'distribute the patches for IBM Dos 4.0 via',cr,lf
- db 'file mode. This Program captures the entire',cr,lf
- db 'disk into a single file and/or recreates the',cr,lf
- db 'disk from the file. It requires a disk which',cr,lf
- db 'has been formatted to 360k (9 secs per track)',cr,lf
- db 'or to 720k (80 tracks-9 secs per track- 3.5")',cr,lf
- db 'in the A: or B: drive. It is quick and dirty,',cr,lf
- db 'written in assembly, and is hereby placed in',cr,lf
- db 'the public domain for all to use.',cr,lf
- db cr,lf
- db ' by Jim Offenbecher',cr,lf
- db ' SSS Computer Center Inc.',cr,lf
- db ' Huntsville, Alabama',cr,lf
- db 'Software Librarian- Huntsville PC Users Group (P1239 AL)',cr,lf
- db cr,lf
- dirask db cr,lf,'Do you want to:',cr,lf
- db ' 1. Read a floppy disk into a file on hard disk',cr,lf
- db ' 2. Write a hard disk file onto a floppy disk',cr,lf
- db ' Enter your choice (1-2)->','$'
-
- askerr db cr,lf,'Must be a 1 or 2 only',cr,lf,'$'
- as2err db cr,lf,'Must be an A or B only',cr,lf,'$'
-
- askdsk db cr,lf,'Enter Floppy Disk Drive Designation (A-B)->','$'
-
- typ360 db cr,lf,'Diskette is 360k 5.25 inch',cr,lf,'$'
- typ720 db cr,lf,'Diskette is 720k 3.5 inch',cr,lf,'$'
-
- askfil db cr,lf,'Enter Hard Disk File Name ->','$'
-
- rerr001 db cr,lf,'Error Reading Floppy Disk',cr,lf,'$'
-
- werr001 db cr,lf,'Error Writing Floppy Disk',cr,lf,'$'
-
- serr001 db cr,lf,'File Size does NOT match disk type',cr,lf,'$'
-
- newlin db cr,lf,'$'
-
- nofile db cr,lf,'File Not Found',cr,lf,'$'
- badpath db cr,lf,'Invalid Path',cr,lf,'$'
- nohand db cr,lf,'No Handle Available',cr,lf,'$'
- accden db cr,lf,'Access to File Denied',cr,lf,'$'
- gopnerr db cr,lf,'Error Opening File',cr,lf,'$'
- gmaker db cr,lf,'Error Creating File',cr,lf,'$'
- rfiler db cr,lf,'Error Reading File',cr,lf,'$'
- wfiler db cr,lf,'Error Writing File',cr,lf,'$'
- closerr db cr,lf,'Error Closing File',cr,lf,'$'
-
- fwtok db cr,lf,'Disk Capture Successful',cr,lf,'$'
- dwtok db cr,lf,'Disk Re-Creation Successful',cr,lf,'$'
-
- dotmsg db '.$'
-
- ; storage for temporary variables
-
- ;file name input buffer
- bufinp db 40 ;max length of buffer
- chrcnt db 0
- ; 1234567890123456789012345678901234567890
- filsto db ' '
-
- ; ascii storage for the floppy drive involved
- drivasc db 'A'
-
- ; binary storage for the floppy drive involved
- dskbin db 1
-
- ; disk type (number of tracks)
- dsktyp dw 80
-
- ;current sector storage for reading and writing floppy disk
- cursec dw 0
-
- ; storage for the file handle assigned to the temp file
- handle dw 0
-
- ; buffer for a single track of data...
- bugbuff db sectrk+1 dup (secsiz dup (?))
-
- ; executable code begins here...
-
- .code
- mov ax,@data ;MASM 5.0+ find data segment
- mov ds,ax ;set up data segment
- mov es,ax ;set up extended segment too
- restart:
- mov dx,offset signon
- mov ah,9
- int 21h ;sign on the system
- mov ah,1
- int 21h ;get a single character
- cmp al,'1' ;check for make file condition
-
- jz makfil ;go make a file if so
- cmp al,'2' ;check for make disk condition
- jz makdsk ;go make a disk if a 2
- mov dx,offset askerr
- mov ah,9 ;print error if not 1 or 2
- int 21h
- jmp restart ;and ask again
-
- ;this module creates a file on the hard disk from all sectors on the
- ;specified floppy drive. Drive type is checked to determine correct
- ;number of sectors to read.
-
- makfil:
- call getdisk ;find out which floppy to use
- call getfile ;and the file name to use too
- call makefile ; make the file
- jc exit ;exit if error
- mov cx,0 ;start at sector zero
- mov cursec,cx
- mov cx,dsktyp ;get # tracks this type
-
- ; copy a single track from the floppy to a file, looping till all tracks done
- fillop:
- push cx ;save track counter
- mov dx,offset dotmsg;tell user another track
- mov ah,9
- int 21h
- call readdisk ;go read track into buffer
- call writfile ;write buffer out to file
- mov cx,cursec ;get starting sector read last time
- add cx,9
- mov cursec,cx ;bump the starting sector for next loop
- pop cx ;get track counter back
- dec cx ;one less track to do
- jnz fillop ;loop till all tracks done...
-
- ; all done writing the file, so bye-bye
- call closfile ;close the new file
- mov dx,offset fwtok
- jmp errexit ;tell user OK, and leave the program
-
-
- ; this module writes all sectors on a floppy disk from data in a
- ; file on the hard disk. The floppy must be formatted, and the file
- ; length must match the format of the floppy disk.
-
- makdsk:
- call getdisk ;find out which floppy to use
- call getfile ;and which file to write to it
- call openfile ;open the file using handles
- jc exit ;abort if can't open
- call lenchk ;check length and abort if wrong
- mov cx,0 ;initialize the sector to write to
- mov cursec,cx
- mov cx,dsktyp ;and get the track count from storage
-
- ; this module reads one track's worth of data from the file and
- ; writes it out to the floppy, looping until 'dsktyp' tracks are written
-
- fil2lop:
- push cx ;save the track counter on stack
- mov dx,offset dotmsg ;tell him we're working
- mov ah,9
- int 21h
- call readfile ;get one tracks data from file
- call writdisk ;put it on the floppy
- mov cx,cursec ;get the old starting sector written
- add cx,9 ;bump it one track's worth
- mov cursec,cx ;and save it for next loop
- pop cx ;get track counter back
- dec cx ;one less track to do
- jnz fil2lop ;loop till all tracks done...
- ;all done writing the floppy drive now...
- call closfile ;close the file
- mov dx,offset dwtok
- jmp errexit ;tell user OK, and exit the program
-
- ;common exit point for errors... prints string at DS:DX and then exits...
- errexit:
- mov ah,9
- int 21h
- exit:
- mov ah,4ch
- int 21h
-
- ; this module prompts the operator for the floppy drive to use, only A and
- ; B are acceptable answers. It then checks the type of media involved using
- ; the FAT Descriptor for 360k drives, and a combination of the FAT Descriptor
- ; and the cluster count for 720k drives. The correct number of 9 sectored
- ; tracks is stored for later loop usage.
-
- getdisk:
- mov dx,offset askdsk
- mov ah,9
- int 21h ;ask the question
- mov ah,1
- int 21h ;get the answer
- and al,05fh ;make lower case
- cmp al,3
- jz exit ;exit on control-c
- cmp al,27
- jz exit ;or on escape char
- cmp al,'A' ;was it an 'A'???
- jnz gd002
- ;process drive A request
- mov drivasc,al ;save for later use
- sub al,41h ;convert to binary
- mov dskbin,al ;save it too
- jmp gdret ;jump around the B check and error for
- ;common return
- ;it wasn't an A so check for a B
- gd002:
- cmp al,'B'
- jnz gd003 ;not B either - then must be wrong
- mov drivasc,al ;save the B for later use
- sub al,41h ;convert to binary
- mov dskbin,al ;save it too
- jmp gdret
-
- ;here if not A or B - must be error...
- gd003: ;here if in error
- mov dx,offset as2err
- mov ah,9
- int 21h ;tell him A or B only
- jmp getdisk ;ask again...
-
- ;here with al containing binary drive value...0=A, 1=B
- gdret:
- inc al ;convert to base 1 for absolute call
- mov dl,al ;put in DL for absolute call
- mov ah,1ch ;put the GET FAT function in AH
- push ds ;save from int 21 function
- int 21h
- jnc gdret1 ;got a good fat description
- jmp readerr ;couldn't get a good FAT description
-
- ;here if got good fat function call - note: DS has changed.....
- gdret1:
- mov al,Byte Ptr[bx] ;get the Media Descriptor Byte...
- pop ds ;restore Data Segment to ours...
- cmp al,0fdh ;check for 9 sector 5.25 inch disk
- jnz chk720 ;no, check for the 720k...
- mov ax,80 ;360k disk has 40 trks, 2 sides, for tot of 80
- mov dsktyp,ax ;save in storage for later loop
- mov dx,offset typ360
- mov ah,9
- int 21h ;tell user it's a 360
- jmp dskgood ;go to common exit point...
-
- ;here if wasn't a 360k drive in the selected drive...
- chk720:
- cmp al,0f9h ;check for 3.5 inch disk...(maybe 1.2 Meg)??
- jnz readerr ;if not 0fdh or 0f9h then must be wrong type
-
- ; both the 3.5" 720k and the 1.2m 5.25 have an f9 Fat descriptor -
- ; use the tot clusters to insure it's a 720k...
- cmp dx,clustchk ;check for 720k
- jnc readerr ;error if it's too many
- mov ax,160 ;track count on 3.5 inch disk
- mov dsktyp,ax ;save the total tracks for later looping use
-
- ; now have good drive type entered, and know correct number of tracks to use
- dskgood:
- mov dx,offset newlin
- mov ah,9
- int 21h ;just start a new line for clarity...
- ret
-
-
- ; this module prompts for and inputs a file name to use via the buffered
- ; input routine. It also terminates the input with a zero byte for the
- ; file handle routines to come later...
-
- getfile:
- mov dx,offset askfil
- mov ah,9
- int 21h ;show user what we want...
- mov ah,0ah ;buffered input for file name...
- mov dx,offset bufinp
- int 21h ;get an input from him..
- mov al,chrcnt ;get character count he entered
- cmp al,0 ;nothing means exit...
- jnz gfl01 ;he did something...
- jmp exit
- ;operator entered a response other than enter key...
- gfl01:
- mov ah,0 ;clear hi byte of AX
- mov di,offset filsto;set offset to 1st character entered
- add di,ax ;add the number of chars entered
- mov byte ptr[di],0 ;put a zero terminator there
- mov dx,offset newlin;clear the line for clarity...
- mov ah,9
- int 21h
- ret
-
- ; this module opens the file using the handle function...
- openfile:
- mov ah,3dh ;function to open file handle
- mov al,0 ;read only mode - careful...
- mov dx,offset filsto;point to ASCIIZ name...
- int 21h ;go try to open...
- jnc openok ;if carry not set, then ok...
-
- ;here if error opening file... check sequentially for errors...
- mov dx,offset nofile
- cmp al,2 ;error 2 is no file found
- jz openerr
- mov dx,offset badpath
- cmp al,3 ;error 3 is can't find path
- jz openerr
- mov dx,offset nohand
- cmp al,4 ;error 4 is no handle available
- jz openerr
- mov dx,offset accden
- cmp al,5 ;error 5 is Access Denied
- jz openerr
- mov dx,offset gopnerr
- ;use general error if not above...
- openerr:
- jmp errexit ;go print the error and quit...
-
- ;here if file opened ok...
- openok:
- mov handle,ax ;save handle for later use.
- ret
-
- ;tell operator we had an error reading file and then exit..
- readerr:
- mov dx,offset rerr001
- jmp errexit
-
- ; this module creates a new file when reading in a floppy disk
- makefile:
- mov ah,3ch ;function in AH
- mov cx,0 ;attributes set to none
- mov dx,offset filsto;point to ASCIIZ string inputted
- int 21h ;go try to make it
- jnc makeok ;carry not set - then OK - it's made
- mov dx,offset badpath
- cmp al,3 ;error 3 is can't find path
- jz makerr
- mov dx,offset nohand
- cmp al,4 ;error 4 is no handle available
- jz makerr
- mov dx,offset accden
- cmp al,5 ;error 5 is access denied
- jz makerr
- mov dx,offset gmaker
- ;use general error if not above...
- makerr:
- jmp errexit ;print the error for user and exit
-
- ;here if file was created OK
- makeok:
- mov handle,ax ;save handle for later writes...
- ret
-
- ;this module closes the file and updates the directory
- closfile:
- mov ah,3eh ;function to close in AH
- mov bx,handle ;get the saved handle
- int 21h ;go close it
- jnc closok ;branch if no error ocurred
- ;here if error closing file
- mov dx,offset closerr
- jmp errexit ;print the error and exit
- ;here if closed OK
- closok:
- ret
-
- ; this module reads one tracks worth of data (9 sectors) into the buffer.
- ; the file pointer is left for DOS to handle, we only do a sequential read.
-
- readfile:
- mov ah,3fh ;function in AH
- mov bx,handle ;handle in BX
- mov dx,offset bugbuff;point to the buffer to use
- mov cx,trklen ;number of bytes to read in CX
- int 21h ;go read the file
- jnc readok ;skip error if none ocurred
- rfiler2:
- mov dx,offset rfiler
- jmp errexit ;tell him an error and exit
-
- ;here if no error ocurred, however, make sure we didn't run out of bytes...
- readok:
- cmp ax,cx ;see if we read all we wanted...
- jnz rfiler2 ;error if short read...
- ret
-
- ; this routine writes one track's worth of data from the buffer to the file
- ; the file pointer is left for DOS to handle, we only do a sequential write.
- writfile:
- mov ah,40h ;function in AH
- mov bx,handle ;handle in BX
- mov dx,offset bugbuff;point to the buffer to use
- mov cx,trklen ;number of bytes to write in CX
- int 21h ;go write it
- jnc writok ;skip error if none ocurred
-
- ;here if DOS reported an error
- wfiler2:
- call closfile ;don't leave lost clusters
- mov dx,offset wfiler
- jmp errexit ;tell user we can't write and exit
-
- ;here if no error ocurred, however, make sure we wrote the whole buffer...
- writok:
- cmp ax,cx ;check to see complete write
- jnz wfiler2 ;error if not
- ret ;else all is ok
-
- ; this module reads one track's worth of data from the floppy disk
- readdisk:
- mov al,dskbin ;get the disk to use
- mov cx,9 ;nine sectors per track
- mov dx,cursec ;where to start
- mov bx,offset bugbuff;where to put data
- int 25h ;go do it
- pop cx ;clean up stack from int 25h (the flags)
- jnc dredok ;skip the error if ok
- jmp readerr ;else tell user and exit
- ;here if read the track ok
- dredok:
- ret
-
- ; this module writes one track's worth of data to the floppy disk
- writdisk:
- mov al,dskbin ;get the disk to use
- mov cx,9 ;write the whole nine sectors
- mov dx,cursec ;where to start
- mov bx,offset bugbuff;where to get data from
- int 26h ;go do it
- pop cx ;clean up stack from int 25h (the flags)
- jnc dwitok ;skip the error if ok
- jmp writerr ;else tell user and exit
- ;here if wrote the whole track
- dwitok:
- ret
-
- ;here if an error writing a track to floppy disk
- writerr:
- mov dx,offset werr001
- jmp errexit
-
- ; check the length of the file to see if it came from the same type
- ; disk drive - 360k disks return DX=0005 and AX=A000 while
- ; 720k drives return DX=000B and AX=4000... error exit if no match..
-
- lenchk:
- mov ax,4202h ;LSEEK ref EOF
- mov bx,handle ;file handle to use
- mov cx,0 ;cx and dx set the offset
- mov dx,cx ;offset 0 from end
- int 21h ;go move the DOS pointer
- push dx ;save the pointer (DX:AX) on stack for rewind
- push ax
- mov ax,4200h ;LSEEK ref beginning
- mov bx,handle ;same file
- mov cx,0 ;same offset
- mov dx,cx ;offset 0 from beginning
- int 21h ;reset pointer to beginning
- pop ax ;get the length back from the stack
- pop dx
- ; now have file length in DX:AX and pointer back at beginning of file...
- mov cx,dsktyp ;get # tracks in CX
- mov si,5 ;set to 360k first
- mov di,0a000h
- cmp cx,80 ;check for 360k track count
- jz chkit ;ok, then skip the set to 720k value
- mov si,0bh ;set comparators to 720k standard
- mov di,04000h
- chkit:
- ; now compare DX with SI and AX with DI - if they dont both match, file
- ; is the wrong size...
- cmp dx,si ;check hi words first
- jnz sizerr ;error if not equal
- cmp ax,di ;check lo words too
- jnz sizerr ;error if not equal
- ret ;ok, file is right length
-
- ; here if wrong size file - tell user and abort program.
- sizerr:
- mov dx,offset serr001
- jmp errexit
-
- ;thats all folks......
- end