'===========================================================================
' Subject: Floppy Disk Image Writer           Date: 06-16-02 (  :  )       
'  Author: Harold Koenig                      Code: QB, PDS                
'  Origin: harkon@shaw.ca                   Packet: DISK.ABC
'===========================================================================
'===========================================================================
' Subject: FLOPPY DISK IMAGE WRITER           Date: 05-29-02 (10:00:00)
'  Author: Harold Koenig                      Code: QB          
'  Origin: harkon@shaw.ca                   Packet: DISK.ABC
'===========================================================================

'*******************************************************
'*                                                     *
'*          Floppy Image Writer (FIWRITE)              *
'*                                                     *
'* This program was created by Harold Koenig (2002)    *
'*                                                     *
'* You are welcome to use any part of this code for    *
'*  your own purposes, but if you do, please give      *
'*  credit where it's due.                             *
'*                                                     *
'* FIWRITE will write the floppy disk image created by *
'*  FIREAD or RAREAD for that matter. FIWRITE was      *
'*  designed to be compatible with these programs. It  *
'*  is kind of a RAWRITE clone without the command     *
'*  line interface. Ther are some things RAWRITE does  *
'*  however that I didn't implement, as the program    *
'*  fullfilled my requirement at the time I wrote it.  *
'*                                                     *
'*  1) FIWRITE does not format the disk in the drive   *
'*     It is assumed the disk is in the drive and it   *
'*     is already formatted                            *
'*  2) FIWRITE does not verify that the disk is good   *
'*  3) FIWRITE does not verify that the diskette in    *
'*     the target drive is of the correct capacity     *
'*     or that the drive is the correct format. Again  *
'*     it is assumed that the user knows the diskette  *
'*     type that the image was created from. It would  *
'*     not be too hard to verify the capacity of the   *
'*     destination disk, and then make sure it matches *
'*     the file size, but this was not done here.      *
'*                                                     *
'* The companion to this file is the FIREAD program    *
'*  which is used to create the image file to be       *
'*  written by FIWRITE.                                *
'*                                                     *
'* Somewhere along the way I intend to add the command *
'*  line interface, add some command line help and     *
'*  maybe add a GUI, maybe with VBDOS, do't know yet.  *
'*  I also intend to be able to make SFX image files,  *
'*  this would just be a function of creating the SFX  *
'*  program, most of the FIWRITE code, and putting     *
'*  it in fron of the image file.                      *
'*                                                     *
'* This program should work to create an image of      *
'*  almost any floppy disk, but it has been tested     *
'*  only with 1.44MB disks and drives.                 *
'*                                                     *
'*                                                     *
'*******************************************************


DEFINT A-Z

'define regtype for interrupt call
  TYPE RegTypeX
     ax AS INTEGER
     bx AS INTEGER
     cx AS INTEGER
     dx AS INTEGER
     BP AS INTEGER
     SI AS INTEGER
     DI AS INTEGER
     flags AS INTEGER
     DS AS INTEGER
     es AS INTEGER
  END TYPE


'declare interrupt sub (in library)
DECLARE SUB interruptx (intnum AS INTEGER, InReg AS RegTypeX, OutReg AS RegTypeX)

'declare subs and functions here
DECLARE SUB dinfo (drive, maxhead, maxsector, maxtrac)
DECLARE SUB dwrite (drive, Head, track, sector, maxsector, buffer$, flag)
DECLARE SUB dreset (drive)

ON ERROR GOTO ErrorHandler

CLS

INPUT "Enter drive A or B "; drive$
drive$ = LTRIM$(RTRIM$(UCASE$(drive$)))
IF drive$ <> "A" AND drive$ <> "B" THEN
   PRINT "not a valid drive"
   PRINT "enter only the drive letter A or B"
   END
END IF


drive = ASC(drive$) - ASC("A")

dinfo drive, maxhead, maxsector, maxtrac


PRINT "Drive data for "; drive$; ":"
PRINT "maxhead="; maxhead
PRINT "maxsector="; maxsector
PRINT "maxtrac="; maxtrac


'setup memory for buffer
buffersize = maxsector * 512
buffer$ = STRING$(buffersize, 21)

INPUT "Filename to write image from: "; filename$

'this begins the floppydrive read process

OPEN filename$ FOR BINARY AS #1

sector = 1
Head = 0

FOR track = 0 TO maxtrac

LOCATE 8, 1
PRINT "Writing Track# "; USING "##"; track;
PRINT "   Head# "; Head;
PRINT "  ";
PRINT USING "###"; ((track / maxtrac) * 100);
PRINT "% Written";

buffer$ = INPUT$((maxsector * 512), 1)

dwrite drive, Head, track, sector, maxsector, buffer$, flags
'if an error is detected in the write it is recommended to try 3 times
IF flags <> 0 THEN
   dreset drive
   dwrite drive, Head, track, sector, maxsector, buffer$, flags
      IF flags <> 0 THEN
         dreset drive
         dwrite drive, Head, track, sector, maxsector, buffer$, flags
            IF flags <> 0 THEN
               dreset drive
               errdesc$ = "Error reading drive " + drive$ + ":"
               GOTO ErrorHandler
               END
            END IF
      END IF
END IF


IF Head = 0 THEN
   Head = 1
   track = track - 1
   ELSE Head = 0
END IF


NEXT track
CLOSE #1
PRINT ""
PRINT ""
PRINT ""
END

ErrorHandler:
  errnum = ERR
  IF errornum = 53 THEN RESUME
  PRINT ""
  PRINT "Error Number "; errnum; ":"; errdesc$
  CLOSE #1
END

SUB dinfo (drive, maxhead, maxsector, maxtrac)

DIM inregs AS RegTypeX, outregs AS RegTypeX

inregs.ax = &H800
inregs.dx = drive

CALL interruptx(&H13, inregs, outregs)


'extract only the DH value_DL contains number of drives
maxhead = (outregs.dx AND &HF00) / &H100

'bits 0-5 are for max sector info
maxsector = outregs.cx AND &H3F

'bits 0-7 CH are the low order info for # of tracks
maxtraclow = (outregs.cx AND &HFF00) / &H100
'bits 6&7 CL are the high order info for # of tracks
'bits need to be shifted left 2 bits for final add to work
maxtrachigh = (outregs.cx AND &HC0) * &H4
maxtrac = maxtrachigh + maxtraclow



END SUB

SUB dreset (drive)

DIM inregs AS RegTypeX, outregs AS RegTypeX

inregs.ax = &H0
inregs.dx = drive

CALL interruptx(&H13, inregs, outregs)


END SUB

SUB dwrite (drive, Head, track, sector, maxsector, buffer$, flag)
DIM inregs AS RegTypeX, outregs AS RegTypeX

bufferseg = VARSEG(buffer$)
bufferadd = SADD(buffer$)

'track information is in both CH bits 0-7 low order
' and CL bits 6-7 high order. This is only an issue
' should the drive have a tack count higher than &HFF
' This is doubtful, however, for the sake of precision
' we'll parse the number and distyribute the components

'this line gets only the low order 8 bits
' we shift these left 8 bits in the inregs.cx= line
tracklow = track AND &HFF
'this line gets the 2 high order bits, and shifts them
' right 2 bits, adding the sector value (1) to this
' leaves bits 0-5 untouched and moves thee 2 bits
' into position 6&7
trackhigh = (track AND &H300) / &H4


inregs.ax = &H300 + maxsector
inregs.bx = bufferadd
'inregs.cx = (track * &H100) + sector
inregs.cx = (tracklow * &H100) + (trackhigh + sector)
inregs.dx = (Head * &H100) + drive
inregs.es = bufferseg
CALL interruptx(&H13, inregs, outregs)

flags = outregs.flags

flags = flags AND &H1



END SUB

