do_kfmt equ

1

;comment out this line and assembly for KINIT

; .xlist ; originally written as KFORMAT, updated to KFMT (KINIT as alternative) ; KFORMAT - An extremely simple floppy disk formatter for the IBM PC(tm) ; and clones. (c) 1985,86,91,95 1996 - Kevin G. Rhoads ; KFMT - Extended for High Density Floppies 1991 ; modified to work with FLOP 1995 ; modified for DMF in 1996 ; GPL version 1999 -- this version is the latest pre-Win95 version ; and is more suitable to a DOS environment ; ; ; KFMT (c) 1996 - Kevin G. Rhoads, All Rights Reserved. ; KFMT Copyright (c) 1999 & 1991-98 - Kevin G. Rhoads, All Rights Reserved. ; ; ;-----------; IBM, IBM PC & PC-DOS are trademarks of International Business Machines Corp. ; NEC is a trademark of NEC Corp. ;-----------; ; This code is copyrighted, all rights reserved except as stated below. ; ; This software is provided "as-is". ; ; This program is distributed in the hope that it will be useful, ; but WITHOUT ANY WARRANTY; without even the implied warranty of ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ; GNU General Public License for more details. ; ; You should have received a copy of the GNU General Public License ; along with this program; if not, write to the Free Software ; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ;--------------------------------------------------------------------;

; Permission to copy and distribute source (kformat.asm, kfmt.asm), binary ; (kfmt.com, kinit.com & kformat.com) and documentation is ; granted to any individuals or companies who do so in accordance with ; the GNU Public License v 2.0 or later. ; ; ; See accompanying documentation for full details of license. ; ; ; It is believed that this program will perform adequately in the task of ; formatting floppy diskettes for use with the MS-DOS operating system ; when this program is executed on an IBM PC/AT or compatible hardware. ; This program is NOT intended or warranted for other purposes. Not all ; disk formats generated are suitable for all operating systems, MS-DOS ; version 3.3 or higher is recommended, and disks formatted with this ; program are only partially compatible with DOS versions 1.0, 1.1 and 1.25. ; ; Formatting will destroy existing information on a diskette. The user ; assumes all risk of loss of data. This program is written to the BIOS ; standard introduced by IBM on the IBM PC/AT and back engineered by ; Award, AMI, Phoenix and many others. It is intended for use on machines ; using AT standard BIOSes and AT style floppy disk state machine (DSM) BIOS ; control for floppy diskette drives. Use on any other kind of hardware ; constitutes misuse and the user assumes all risk resulting therefrom. ; ;AS IS: ; Although tested, this program is supplied "as is" without any warrants of ; implied merchandiseability or suitability as defined by the Uniform ; Commercial Code. Users of this program are expected to determine ; it's suitability to their tasks. In no event will Kevin G. Rhoads or ; Kevin G. Rhoads Engineering, Inc. be liable for consequential damages or ; any other damages resulting from the use or misuse of this program. If ; you cannot agree to the terms of this license, then destroy all program ; materials and cease using this program. ; ;

;-----------rets macro ;near return (ie. short ret) db 0C3H endm code segment para 'code' kformat proc far assume cs:code,ds:code org 100h start: ;jump past constants & format track sub jmp begin ;jump past constants & format track sub ; ; sector length codes are: ; 0 = 128 bytes/sector (not possible in Double Density (MFM)) ; 1 = 256 bytes/sector ; 2 = 512 bytes/sector (IBM PC standard) ; 3 = 1024 bytes/sector ; 4 = 2048 bytes/sector (supported by NEC FDC but not by IBM) ; 5 = 4096 bytes/sector (supported by NEC FDC but not by IBM) ; 6 = 8192 bytes/sector (supported by NEC FDC but not by IBM; MFM only, ; only works for 8" or HD floppies, not 3.5" or 5.25" DD) ; ; can format up to 10 512 byte sectors at 250kHz at 300rpm (DD, QD) or at 300kHz at 360rpm (DD in 5.25"HD) ; can format up to 12 512 byte sectors at 300kHz at 300rpm (DD, QD, 3.5"DD) ; can format up to 17 512 byte sectors at 500kHz at 360prm (5.25" HD) ; can format up to 20 512 byte sectors at 500kHz at 300rpm (3.5" HD) ; ; could do up to 5 1024 byte sectors, 2 or 3 2048 byte sectors or 1 4096 byte ; sector per track - DD ; could also go down to 256 byte sectors, 16 (18 or 19 max) per track -DD ; ifdef do_kfmt ; table db 0,0,1,2 ;format table - up to 23 sectors -- make it longer if you need more db 0,0,2,2 ; 0,0,n,2 - the first zero is a

db db db db db db db db db db db db db db db db db db db db db

0,0,3,2 0,0,4,2 0,0,5,2 0,0,6,2 0,0,7,2 0,0,8,2 0,0,9,2 0,0,0ah,2 0,0,0bh,2 0,0,0ch,2 0,0,0dh,2 0,0,0eh,2 0,0,0fh,2 0,0,10h,2 0,0,11h,2 0,0,12h,2 0,0,13h,2 0,0,14h,2 0,0,15h,2 0,0,16h,2 0,0,17h,2

; ; ; ; ;

place holder for the track # the second zero is a place holder for the head (ie. side) number n - is the sector number 2 - code for 512 bytes/sector

;space is kept for more sectors if 256 bytes or HD

; ; interleave tables follow - not all interleaves are perfectly divisible ; best approximation is used .radix 10d ; 1:1 interleaves il8_8 label byte il8_9 label byte il8_1 label byte ; 8 sectors interleaving 1 il9_1 label byte ; 9 sectors interleaving 1 il9_9 label byte ila_1 label byte ;10 sectors interleaving 1 ilc_1 label byte ;12 sectors interleaving 1 ile_1 label byte ;18 sectors interleaving 1 ilw_1 label byte

ilt_1 db 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21 ; ; 2:1 interleaves il8_2 db 1,5,2,6,3,7,4,8,10,9 ; 8 sectors interleaving 2 il9_2 label byte ; 9 sectors interleaving 2 ila_2 db 1,6,2,7,3,8,4,9,5,10 ;10 sectors interleaving 2 ilc_2 db 1,7,2,8,3,9,4,10,5,11,6,12 ;12 sectors interleaving 2 ild_2 db 1,9,2,10,3,11,4,12,5,13,6,14,7,15,8,16 ;16 sectors interleaving 2 ile_2 db 1,10,2,11,3,12,4,13,5,14,6,15,7,16,8,17,9,18 ;18 sectors interleaving 2 ilt_2 db 1,11,2,12,3,13,4,14,5,15,6,16,7,17,8,18,9,19,10,20 ;20 sectors interleaving 2 ilw_2 db 1,12,2,13,3,14,4,15,5,16,6,17,7,18,8,19,9,20,10,21,11 ;21 sectors interleaving 2 ; ; 3:1 interleaves il8_3 db 1,4,7,2,5,8,3,6,10,9 ; 8 sectors interleaving 3 il9_3 db 7,2,5,8,3,6,9,1,4,10 ; 9 sectors interleaving 3 ila_3 db 1,8,5,2,9,6,3,10,7,4 ;10 sectors interleaving 3 ilc_3 db 1,5,9,2,6,10,3,7,11,4,8,12 ;12 sectors interleaving 3 ile_3 db 1,7,13,2,8,14,3,9,15,4,10,16,5,11,17,6,12,18 ;18 sectors interleaving 3 ;ilt_3 db 1,8,15,2,8,16,3,10,17,4,11,18,5,12,19,6,13,20,7,14 ;20 sectors interleaving 3 ilt_3 label byte ilw_3 db 1,8,15,2,8,16,3,10,17,4,11,18,5,12,19,6,13,20,7,14,21 ;21 sectors interleaving 3 ; ; 4:1 interleaves il8_4 db 8,1,3,5,7,2,4,6,10,9 ; 8 sectors interleaving 4 il9_4 db 1,8,6,4,2,9,7,5,3,10 ; 9 sectors interleaving 4 ila_4 db 1,6,4,9,2,7,5,10,3,8 ;10 sectors interleaving 4 ilc_4 db 1,4,7,10,2,5,8,11,3,6,9,12 ;12 sectors interleaving 4 ile_4 db 4,8,12,16,1,5,9,13,17,2,6,10,14,3,7,11,15,18 ;18 sectors interleaving 4 ilt_4 db 1,6,11,16,2,7,12,17,3,8,13,18,4,9,14,19,5,10,15,20 ;20 sectors interleaving 4 ilw_4 db 1,7,12,17,2,8,13,18,3,9,14,19,4,10,15,20,5,11,16,21,6 ;21 sectors interleaving 4

; ; 5:1 interleaves il8_5 db 1,6,3,8,5,2,7,4,10,9 ; 8 sectors interleaving 5 il9_5 label byte ; 9 sectors interleaving 5 ila_5 db 1,3,5,7,9,2,4,6,8,10 ;10 sectors interleaving 5 ilc_5 db 1,6,11,4,9,2,7,12,5,10,3,8 ;12 sectors interleaving 5 ile_5 db 8,5,15,12,2,9,6,16,13,3,10,7,17,4,14,11,1,18 ;18 sectors interleaving 5 ilt_5 db 1,5,9,13,17,2,6,10,14,18,3,7,11,15,19,4,8,12,16,20 ;20 sectors interleaving 5 ilw_5 db 1,6,10,14,18,2,7,11,15,19,3,8,12,16,20,4,9,13,17,21,5 ;21 sectors interleaving 5 ; ; 6:1 interleaves il8_6 db 5,1,8,4,3,7,6,2,10,9 ; 8 sectors interleaving 6 il9_6 db 7,6,2,9,5,1,8,4,3,10 ; 9 sectors interleaving 6 ila_6 db 1,6,3,8,5,10,2,7,4,9 ;10 sectors interleaving 6 ilc_6 db 1,3,5,7,9,11,2,4,6,8,10,12 ile_6 db 1,4,7,10,13,16,2,5,8,11,14,17,3,6,9,12,15,18 ilt_6 db 1,11,8,18,5,15,2,12,9,19,6,16,3,13,10,20,7,17,4,14 ilw_6 db 1,21,8,18,5,15,2,12,9,19,6,16,3,13,10,20,7,17,4,14,11 ;21 sectors interleaving 6 ; ; 7:1 interleaves il8_7 db 1,8,7,6,5,4,3,2,10,9 il9_7 db 1,5,9,4,7,3,7,2,6,10 ila_7 db 1,4,7,10,3,6,9,2,5,8 ilc_7 db 1,8,3,10,5,12,7,2,9,4,11,6 ile_7 db 1,6,11,16,4,9,14,2,7,12,17,5,10,15,3,8,13,18 ilt_7 db 1,4,7,10,13,16,19,2,5,8,11,14,17,20,3,6,9,12,15,18 ilw_7 db 1,4,7,10,13,16,19,2,5,8,11,14,17,20,3,6,9,12,15,18,21 ;21 sectors interleaving 7 ; ; 8:1 interleaves il9_8 db 9,8,7,6,5,4,3,2,1,10 ila_8 db 1,6,2,7,3,8,4,9,5,10 ilc_8 db 1,4,7,10,3,6,9,12,2,5,8,11

ile_8 db 1,16,14,12,10,8,6,4,2,17,15,13,11,9,7,5,3,18 ilt_8 db 1,6,11,16,4,9,14,19,2,7,12,17,5,10,15,20,3,8,13,18 ilw_8 db 1,6,11,16,21,4,9,14,19,2,7,12,17,5,10,15,20,3,8,13,18 ;21 sectors interleaving 8 ; ; 9:1 interleaves ila_9 db 10,9,8,7,6,5,4,3,2,1 ilc_9 db 1,5,9,4,8,12,3,7,11,2,6,10 ile_9 db 1,3,5,7,9,11,13,15,17,2,4,6,8,10,12,14,16,18 ilt_9 db 1,10,19,8,17,6,15,4,13,2,11,20,9,18,7,16,5,14,3,12 ilw_9 db 1,21,10,19,8,17,6,15,4,13,2,11,20,9,18,7,16,5,14,3,12 ; ; il_addr dw ? endif ;ifdef do_kfmt parm_addr dw buffer dw double db quad_den db firstside db verify db drive db db 0 track db maxtrack db max db 10d db 0 imax db 9d dosv db 6 dosvm db jdos db 0 sec_size db nodrives db defvid db mod_vid db ? ? 1 0 0 0 0 0,0 82d ;store address of r/w buffer in segment form ;formatting single(0) or double(1) ;quad density? ;side to start formatting on ;verifying(1) or no verify(0) ;which drive 0=A, 1=B ;track counter for format & verify ;max sector number on track ;max sector number initialized ;using with which version of PC-DOS ; minor version ;Formatting for JDos (patched DOS 1.1) ; 512 bytes / sector ; number of floppies (will be set later)

1 2 1 1 0

vid_mode db 2 vid_cols db 80d ; ; messages next ; ifdef do_kfmt hello db 'KFMT: FLOPPY Format Routine for IBM PC/AT(tm) - (c) 1985-92: KGRhoads',10d,13d else hello db 'KINIT: FLOPPY Init Routine for IBM PC/AT(tm) - (c) 1985-92: KGRhoads',10d,13d endif db 'Copyright (c) 1985-99 Kevin G. Rhoads, all rights reserved. ',10d,13d db ' IBM, IBM PC, IBM PC/AT & PC-DOS are trademarks of IBM Corp.',10d,10d,13d helloc db 'Permission is granted for ** GPL ** distribution.',10d,13d db ' All other rights reserved. See source or documentation for details.',10d,13d db '? for HELP, BREAK to abort - can be used with I/O redirection.',10d,10d,13d,'$' dosmess db 10d,13d,'Which version of PC-DOS? (1 ... 6; default is 3) ...................... $' doshelp: db 'It is necessary to adjust some of the values in the boot record,',10d,13d db 'and the manner in which they are adjusted depends on the version of',10d,13d db 'PC-DOS. Since the program could not determine the DOS version from the',10d,13d db 'boot record, it is asking.',10d,10d,13d db 'Respond with 1, 2, or 3 depending on the version of PC-DOS',10d,13d db 'you are using. DOS 3.x = 3; DOS 2.x = 2, DOS 1.x = 1.',10d,10d,13d db 'NB: Hackers who are doing custom boots: choosing 1 (=DOS 1)',10d,13d db 'will guarentee that KFORMAT will write out the boot record EXACTLY',10d,13d db 'as it was read in from BOOT.REC - NO MODIFICATIONS.',10d,13d dr1vemess db 10d,13d,'Which drive (0, a or A = A; ^C or BREAK to abort) ..................... $' dr2vemess db 10d,13d,'Which drive (0, a or A = A; 1, b or B = B; ^C=abort) .................. $' dr3vemess db 10d,13d,'Which drive (0, a, A = A; 1, b, B = B; 2, c, C = C) ................... $' dr4vemess db 10d,13d,'Which drive (0,a,A = A; 1,b,B = B; 2,c,C = C; 3,d,D = D) .............. $' three_five db 10d,13d,'Is the drive a 5.25HD, 5.25QD or 3.5? (Default 3=3.5"; 5,H=5HD; Q=5QD). $'

help_3_5 db 110d,13d,'High density 5.25" (nominal 1.2M) drives require a different data rate ',10d,13d db 'from that required by Quad density 5.25", or any 3.5" drives. Please input a ',10d,13d db ' 5 if the drive is a High Density 5.25" drive. $' drnerr db 10d,13d,'System board switches indicate 0 or more than 4 floppy',10d,13d db 'disk drives. One floppy disk drive is assumed.',10d,13d,'$' drivhelp db 10d,13d,'Equipment check indicates that this pc has ' numdr db 20d,' floppy disk drives.',10d,10d,13d db 'When asked which drive, if you respond with a drive letter which',10d,13d db 'corresponds to a non-existent (or hard) drive; the response is rejected.',10d,10d,13d db 'Please choose between 0 and ' numdr2 db 20d,' or the equivalent drive letter.',10d,10d,13d,'$' formmess db 10d,13d,'How many Sectors/Track? (9=Nine; B=Eight; 8=Eight/Nine formatted;' db 10d,13d,'N=Nine/Ten formatted; E=Eight/Ten formatted; T=Ten/Ten formatted)' db 10d,13d,'Z=20 Sector 3.5 HD; X=17 Sector 5.25 HD; H=1.2M HD; I=1.44M HD;' db 10d,13d,'Q=9 Sector QD (720k); W=10 Sector QD (800k); V=12 Sector QD (960k)... $' formhelp db 10d,13d,'5 1/4" floppy disks (ie. diskettes) can be formatted in a variety of ways.',10d,13d db 'The standard format for IBM`s PC-DOS is 9 sector double sided in DOS 2.x',10d,13d db '& DOS 3.x. It was 8 sector double sided for DOS 1.1, and 8 sector single',10d,13d db 'sided for DOS 1.0.',10d,10d,13d db 'With DOS 3.x support was added for High Density (1.2 Meg), and 3.5" drives',10d,13d db 'The 5.25" HD drive can format 1.2Meg(H) or 1.4Meg(X) on HD floppies.',10d,13d db 'It can format 720k(Q) or 800k(W) on low density floppies.',10d,13d db 'The 3.5" HD drive can format 1.44Meg(I) or 1.6Meg(Z) on HD floppies,',10d,13d db 'and all 3.5" drives can format 720k(Q), 800k(W) or 960k(V) on low ',10d,13d db 'density floppies. A QD 5.25" drive also can format these sizes.',10d,10d,13d ; db 'The choices at this point are 9, 8, B - which correspond to the options',10d,13d ; db 'used by DOS FORMAT. If this disk is for DOS 2.x or higher then choose',10d,13d ; db '9. If this disk will be used only with DOS 1.x choose B, and if it is',10d,13d ; db 'if it is to be used with DOS 2 or 3 and also DOS 1 choose 8.',10d,13d ; db 'PLANNING TO USE THE DISK W/DATA6000 - CHOOSE B.',10d,10d,13d db 'High density and 3.5" disks can be formatted on AT type machines ',10d,13d db 'to regular (H [1.2M], I [1.44M]) or extended capacity formats (Z, X) ',10d,13d

db 'Quad density (Q [720k]) and extended quad. formats (W, V) are also',10d,13d db 'available. Extended formats often require a BIOS patch TSR',10d,13d,'$' ; db 'available. These other choices are primarily useful only if:',10d,13d ; db ' 1) You are a hacker who wants to mess w/funny formats',10d,13d ;; db ' 2) You have the JFORMAT/QDRIVE software from Tall Trees',10d,13d ; db ' 2) You are running MS-DOS 3.2 or up (inc. DOS 4 and DOS 5)',10d,13d ; db 'since earlier DOSes won`t reliably read or write them, and even ',10d,13d ; db 'later versions of DOS will probably require BIOS patches.',10d,13d,'$' ready db 10d,13d,'Insert Disk, Press any key when ready (^C=ABORT) ','$' tell1 db 10d,10d,13d,'Formatting ... ',10d,13d,'$' tell2 db 10d,10d,13d,'Initializing ... ',10d,13d,'$' tell3 db 13d,'Boot Sector |$' tell4 db ' FAT & Root: side 1 |$' tell5 db ' FAT & Root: side 2 $' tell6 db 10d,13d,'First FAT w/ Media ID byte $' tell3q db 10d,13d,'Verify after formatting? (Y=Yes, else No) ............................. $' verfhelp: db 10d,13d,'Sometimes disks have bad sectors. Verify checks for bad sectors.',10d,13d db 'DOS FORMAT always does a verify pass after formatting.',10d,10d,13d db 'DOS FORMAT marks bad sectors as bad in the FAT, but this simple',10d,13d db 'formatter isn`t so sophisticated (yet). During verify this program',10d,13d db 'will only report errors. With new floppies from any quality',10d,13d db 'manufacturer, there should be no problems. It is recommended',10d,13d db 'that you skip verification by answering N (it`s faster).',10d,13d,'$' tellsq db 10d,13d,'Single sided formatting? (Y=Yes, B=Yes (Backside) else Double sided) .. $' sidehelp: db 10d,13d,'If you have SINGLE-SIDED drives or if you need to use this',10d,13d db 'disk on another pc which has single-sided drives then answer Y',10d,13d db 'If you have double sided drives and want to format only the back side',13d,10d db 'then answer B (there is generally no reason to choose this).',13d,10d db 'Any response other than Y, y, B, b or ? will choose DOUBLE-SIDE formatting.',10d,13d,'$' telltrk db 10d,13d,'Maximum track to format? (1=41, 2=42, 3=43, 8=80, 9=81, 0=82, else 40) $'

;telltrk db 10d,13d,'Maximum track to format? (1=41, 2=42, 3=43, else 40) .................. $' ;telltrk2 db 10d,13d,'Maximum track to format? (1=81, 2=82, 3=83, else 80) .................. $' telltrk2 db 10d,13d,'Maximum track to format? (1=81, 2=82, 3=83, 4=84, else 80) ............ $' hlptrk db 10d,13d,'For standard DS/DD 5 1/4", format 40 tracks. Many drives can',13d,10d db 'actually use more than 40 tracks, but DOS does not support their',13d,10d db 'use. If your drive can do more than 40 tracks, Kformat can ',13d,10d db 'format them all. This feature is primarily for hackers.',13d,10d,'$' hlptrk2 db 10d,13d,'For standard DS/HD 5 1/4", format 80 tracks. Many drives can',13d,10d db 'actually use more than 80 tracks, but DOS does not support their',13d,10d db 'use. If you`re drive can do more than 80 tracks, KFMT can ',13d,10d db 'format them all. This feature is primarily for hackers.',13d,10d,'$' intlve db 10d,13d,'Interleave factor? (1 .. 7; default 1) ................................ $' intlve4 label byte intlve2 db 10d,13d,'Interleave factor? (1 .. 9; default 2) ................................ $' intlve3 db 10d,13d,'Interleave factor? (1 .. 9; default 1) ................................ $' ;intlve4 db 10d,13d,'Interleave factor? (1 .. 7; default 2) ................................ $' intlve5 db 10d,13d,'Interleave factor? (1 .. 9; default 3) ................................ $' tell3v db 10d,13d,'Verifying ... ',10d,13d,'$' another db 10d,13d,'Do another? (y/m/N)','$' wp db 10d,13d,'Diskette is WRITE-PROTECTED!',10d,13d,'$' to db 10d,13d,'Diskette drive time-out!',10d,13d,'$' seekfail db 10d,13d,'Seek failure!',10d,13d,'$' necerror db 10d,13d,'NEC controller error!',10d,13d,'$' crc db 10d,13d,'CRC error during read!',10d,13d,'$' notfound db 10d,13d,'Sector not found!',10d,13d,'$' garrh db 10d,13d,'Diskette error?!?',10d,13d,'$' cv db '0123456789ABCDEF' tracks db ' 1 2 3 4 5 6 7 8 91011121314151617181920212223242526272829'

db '303132333435363738394041424344454647484950515253545556575859' db '606162636465666768697071727374757677787980818283848586878889' trmess db 13d,'Doing track number ' trnum db 32d,32d,'$$$' ;disk parameter table values for various formats eights db 0DFH,2,25H,2,08H,02aH,0FFH,050H,000H,1,2 nines db 0DFH,2,25H,2,09H,02aH,0FFH,050H,000H,1,2 ;tens db 0DFH,2,25H,2,0AH,01bH,0FFH,031H,000H,1,2 tens db 0DFH,2,25H,2,0AH,00bH,0FFH,020H,000H,1,2 twelve db 0DFH,2,25H,2,0CH,005H,0FFH,00AH,000H,1,2 twenty db 0DFH,2,25H,2,14H,005H,0FFH,00AH,000H,1,2 twentyone db 0DFH,2,25H,2,15H,000H,0FFH,000H,000H,1,2 eightteen db 0AFH,2,25H,2,12H,00fH,0FFH,06cH,000H,1,2 seventeen db 0DFH,2,25H,2,11H,005H,0FFH,00AH,000H,1,2 fifteen db 0DFH,2,25H,2,0FH,01BH,0FFH,054H,000H,1,2 seventoon db 0DFH,2,25H,2,11H,002H,0FFH,006H,000H,1,2 ;disk parameter table values for boot record bootparm db 0DFH,2,25H,2,07fH,005H,0FFH,031H,0F6H,1,2 Quad_density db 97h A_3_5 db 0 B_3_5 db 0 disk_state_machine db 17h dsm_addr dw 090h format_type db 6d ; ; bootbuf: ;boot record buffer jmp short bootm ;this is pseudo-boot record nop ;in case real boot rec can't be db 'KGRho3.3' ;found .radix 16d boot_sector_size dw 0200 ;sector size in bytes (512d) boot_sectors_per_cluster db 01 ;number of sectors per cluster db 01,00,02 boot_number_of_root_entries dw 040 ; boot_number_of_sectors dw 067C ;

boot_media_ID_byte db 0F9 ; boot_number_of_FAT_sectors dw 06 ; db 0A,00,02 db 16d dup (00) ;disk parameters in dos 3.3 position db 0DF,2,25,2,14,05h,0FF,0a,00,1,2 db 'NO NAME ' ;volume label ; org bootbuf+036h db 'FAT12 ' ;type .radix 10d org bootbuf+040h bootm: mov ax,1 int 10h mov ax,0 int 10h push cs pop ds mov ax,0 push ax popf kn: mov ah,1 int 16h jz kdone mov ah,0 int 16h jmp short kn kdone: lea si,mss lea dx,endmess lea cx,bootbuf sub dx,si sub si,cx add si,7c00h bloop: mov ah,14d mov al,[si] mov bx,0f0h

push si int 10h pop si inc si dec dl ja bloop mov ah,0 int 16h int 19h mss db 'This diskette was not formatted with an operating system',10d,13d db 'Please, INSERT DOS DISKETTE IN DRIVE A,',10d,13d db 'WHEN READY PRESS ANY KEY TO BOOT ',10D,13D db ' (KFMT/KINIT/KFORMAT pseudo-boot record) ' endmess db ' ' org bootbuf+509d db 0,055h,0aah ;drive 0, 55aa boot signature org bootbuf+512d bootdup db 512 dup(?) ;duplicate boot record buffer bootnam db 'BOOT.REC',0 ;file to look for errcount db 0 ;error count variable maxcount db 5d ; ifdef do_kfmt ; dotrack: push es ;format 1 track subroutine push di mov ax,040h mov es,ax mov al,disk_state_machine mov di,dsm_addr mov byte ptr es:[di],al pop es push es lea di,tracks ; does single or double sides add di,word ptr track ; double=1 means double add di,word ptr track ; double=0 means single

mov cx,[di] lea di,trnum mov [di],cx pop di lea dx,trmess ;which track are we doing mov ah,9 int 21h mov dh,firstside loop2: lea bx,table mov ch,byte ptr track mov al,byte ptr sec_size mov si,0 mov di,word ptr max shl di,1 shl di,1 loop1: mov [bx+si],ch mov [bx+si+1],dh mov [bx+si+3],al add si,4 cmp si,di jna loop1 mov si,10d push cs pop es int_input: mov ah,05h mov al,byte ptr max mov dl,byte ptr drive lea bx,table mov ch,byte ptr track xor cl,cl call disk jnc coolform sub si,1 ;retry disk operation if fail jnc int_input

mov ah,1 int 13h cmp al,0 je coolform mov al,ah call die coolform: cmp double,0 je do_ret push es mov ax,040h mov es,ax mov al,disk_state_machine mov di,dsm_addr mov byte ptr es:[di],al pop es xor dh,double cmp dh,double ;if double side - do other side je loop2 do_ret: pop es rets ; endif ;ifdef do_kfmt ; ; begin: push cs pop ds push cs pop es assume ds:code,es:nothing mov ah,10H mov dh,0 ;if FLOP active, turn it off mov dl,7fH ;use modified install check mov bx,'FL' ;as in install check, but mov cx,'OP' ;if cx='OP', then we are signaling toggle-active int 13H

call dup_boot ;make a copy of our pseudo-boot record mov ah,0fh int 10h mov vid_mode,al mov vid_cols,ah mov ah,30h ;which dos version? int 21h mov dosv,al cmp ah,20d jne not_20 mov ah,2 jmp dosvmh not_20: cmp ah,10d jne not_10 mov ah,1 not_10 label near mov si,5ch ;use FCB and command line parameter (if present) mov dx,si mov ah,0fh int 21h ;open file specified by command line for boot record or al,al jnz dosvmh jmp FCB_worked ;no such file dosvmh: cmp al,1 ja tryit ;dos2 or above jmp skipit1 ;dos1 tryit: lea dx,bootnam ;boot record in BOOT.REC ? mov ax,3d00h int 21h jnc foundboot jmp skipit2 ;no boot record - try another method foundboot: push ax mov bx,ax mov cx,512d

lea dx,byte ptr bootbuf ;read boot record into buffer mov ax,3f00h int 21h jnc read2cool mov ax,4200h mov cx,0 mov dx,0 int 21h mov cx,512d lea dx,byte ptr bootdup ;read boot record into buffer mov ax,3f00h int 21h jc to_skipit2 call rst_boot jmp read2cool to_skipit2: jmp skipit2 ;no go - try another way read2cool: pop bx mov ax,3e00h ;close file int 21h jmp skipit ;got boot record skipit1: mov si,5ch ;under dos1 - use FCB mov dx,si mov ah,0fh int 21h ;open file specified by command line for boot record or al,al jz FCB_worked ;no such file mov si,5ch ;under dos1 - use FCB, default drive, BOOT.REC mov byte ptr [si],0 mov byte ptr [si+1],'B' mov byte ptr [si+2],'O' mov byte ptr [si+3],'O' mov byte ptr [si+4],'T' mov byte ptr [si+5],' ' mov byte ptr [si+6],' '

mov byte ptr [si+7],' ' mov byte ptr [si+8],' ' mov byte ptr [si+9],'R' mov byte ptr [si+0ah],'E' mov byte ptr [si+0bh],'C' mov ah,0fh int 21h ;open BOOT.REC on default drive or al,al jnz skipit2 ;no BOOT.REC - try another method FCB_worked: mov word ptr [si+0ch],0 mov word ptr [si+0eh],200h mov word ptr [si+20h],0 ; mov word ptr [si+22h],0 lea dx,bootbuf ;set DTA to bootbuf mov ah,1ah int 21h mov dx,5ch mov ah,14h int 21h or al,al ;read ok? jnz skipit2 ; no - try another method jmp skipit ; yes - got boot record skipit2: cmp al,8 jne skipit2p5 call rst_boot lea dx,bootdup ;set DTA to bootdup mov ah,1ah int 21h mov dx,5ch mov ah,14h int 21h or al,al ;read ok? jnz skipit2p5 ; no - try another method call rst_boot

jmp skipit ; yes - got boot record skipit2p5: mov drive,0 skipit3: mov al,drive ;try reading it off floppy, drive A mov dx,0 mov cx,1 lea bx,bootbuf ;can't find boot.rec file int 25h jc try_another no_gronk: popf call rst_boot jmp skipit try_another: popf cmp al,8 jne boot_gronk mov dx,0 mov cx,1 lea bx,bootdup mov al,drive int 25h jnc no_gronk popf boot_gronk: cmp drive,2 je boot_gronk_2 inc drive jmp skipit3 boot_gronk_2: mov dosv,0 ;if using pseudo-boot note special ; skipit: push cs ;need read buffer for verifying & pop es ; write buffer for initializing assume es:code ; and it can't cross 64k boundary lea ax,end_of_code

add ax,15d mov cl,4 shr ax,cl push cs pop bx add ax,bx mov bx,ax add ax,0160h jnc coolbx and bx,0f000h add bx,01000h coolbx: mov buffer,bx ;have got seg address of r/w buffer int 11h push ax and ax,1 jne some jmp drnok some: pop ax push ax and ax,0c0h mov cx,6 shr ax,cl inc ax cmp al,4 jbe drnok mov nodrives,1 lea dx,drnerr mov ah,9 int 21h jmp chkvid drnok: mov nodrives,al chkvid: pop ax and ax,030h mov cx,4 shr ax,cl mov defvid,al

askbios: mov al,vid_mode ;clear screen and home cursor-quick and dirty mov ah,0 push ax int 10h pop ax int 10h lea dx,hello ;say hello mov ah,9 int 21h mov byte ptr helloc,'$' askagain: lea dx,formmess ;how many sectors/track ? mov ah,9 int 21h mov quad_den,0 mov ah,1 int 21h cmp al,'9' ;9 sec init on 9 sec format jne try2 mov byte ptr max,9d ; yes mov byte ptr imax,9d lea si,nines jmp movit try2: cmp al,'8' ;8 sec init on 9 sec format? jne try5 mov byte ptr imax,8d; yes mov byte ptr max,9d lea si,nines jmp movit try5: or al,32d ;convert to lower case, only alpha compares left ; cmp al,'B' ;8 sec init on 8 sec format? ; je f11 ; yes cmp al,'b' jne try3 f11: lea si,eights ; yes mov byte ptr max,8d

mov byte ptr imax,8d jmp movit try3: ; cmp al,'N' ;9 sec init on 10 sec format? ; je f9t ; yes cmp al,'n' jne try4 f9t: mov byte ptr max,10d; yes mov byte ptr imax,9d lea si,tens jmp movit try4: cmp al,'T' ;10 sec init on 10 sec format? je f10t cmp al,'t' jne try6 f10t: mov byte ptr imax,10d; yes mov byte ptr max,10d lea si,tens jmp movit To_Hi_dens3p: jmp Hi_dens3p Hi_dens5p: mov byte ptr max,17d mov byte ptr imax,17d lea si,seventeen jmp movit Hi_dens5pm: mov byte ptr max,16d mov byte ptr imax,16d lea si,seventeen jmp movit Hi_dens5palt: mov byte ptr max,17d mov byte ptr imax,17d lea si,seventoon jmp movit Hi_dens5: mov byte ptr max,15d mov byte ptr imax,15d lea si,fifteen

jmp try6: cmp je cmp je cmp je cmp je cmp je cmp je cmp je cmp je cmp je cmp jne jmp quad: mov lea mov jmp wquad: mov lea mov jmp vquad: mov lea

movit al,'s' Hi_dens5pm al,'y' Hi_dens5palt al,'x' Hi_dens5p al,'h' Hi_dens5 al,'i' Hi_dens3 al,'z' TO_Hi_dens3p al,'q' quad al,'w' wquad al,'v' vquad al,'e' ;8 sec init on 10 sec format? unknown_format f8t ; yes mov byte ptr max,9d byte ptr imax,9d si,nines quad_den,1 movit mov byte ptr max,10d byte ptr imax,10d si,tens quad_den,1 movit mov byte ptr max,12d byte ptr imax,12d si,twelve

mov quad_den,1 jmp movit DMF: mov byte ptr max,21d mov byte ptr imax,21d lea si,twentyone ; mov quad_den,1 jmp movit unknown_format: cmp al,'m' je DMF lea dx,formhelp ;not proper response call help ;do help message jmp askagain Hi_dens3: mov byte ptr max,18d mov byte ptr imax,18d lea si,eightteen jmp movit Hi_dens3p: mov byte ptr max,20d mov byte ptr imax,20d lea si,twenty jmp movit f8t: mov byte ptr max,10d mov byte ptr imax,8d lea si,tens movit: mov ax,0 ;copy new values into disk parm table mov es,ax assume es:nothing mov parm_addr,si les di,dword ptr es:[78h] ;0:78 is ptr to disk parm table mov cx,11d ;in PC-DOS this is 0:522 currently cld rep movsb push cs pop es assume es:code

ifdef do_kfmt ; interleave stuff here lea bx,ilt_1 cmp max,17d jae il_not15 jmp il_try15 is_20_21: cmp max,20d je to_is20 jmp il_is21 to_is20: jmp il_is20 il_not15: cmp max,19d ja is_20_21 jb il_1718 ; cmp max,12d ; je il_12 lea bx,ilt_2 mov il_addr,bx lea dx,intlve2 jmp il_test_it il_1718: cmp max,17d jne il_18 lea bx,ile_2 lea dx,intlve2 jmp il_1817 il_18: lea bx,ile_1 lea dx,intlve3 il_1817: push bx mov ah,9 int 21h ;interleave factor of 1 is common default

;ask about interleave factor

;ask about interleave factor

;ask about interleave factor

mov ah,1 int 21h pop bx cmp al,24d ;^X = start over jne next_test_1817 jmp askbios next_test_1817: mov il_addr,bx cmp al,13d ;default ? je t0_d0_il cmp al,10d je t0_d0_il lea bx,ile_2 cmp al,'2' je t0_d0_il lea bx,ile_3 cmp al,'3' je t0_d0_il lea bx,ile_4 cmp al,'4' je t0_d0_il lea bx,ile_5 cmp al,'5' je t0_d0_il lea bx,ile_6 cmp al,'6' je t0_d0_il lea bx,ile_7 cmp al,'7' je t0_d0_il lea bx,ile_8 cmp al,'8' je t0_d0_il lea bx,ile_9 cmp al,'9' je t0_d0_il

lea bx,ile_1 cmp al,'1' je t0_d0_il jmp do_il_ il_16: lea bx,ild_2 t0_d0_il: jmp do_il il_12: lea bx,ilc_2 lea dx,intlve4 push bx mov ah,9 int 21h mov ah,1 int 21h pop bx cmp al,24d jne next_test_12 jmp askbios next_test_12: mov il_addr,bx cmp al,13d je t0_d0_il cmp al,10d je t0_d0_il cmp al,'2' je t0_d0_il lea bx,ilc_3 cmp al,'3' je to_d0_il lea bx,ilc_1 cmp al,'1' je to_d0_il lea bx,ilc_4 cmp al,'4' je to_d0_il

;ask about interleave factor

;default ?

lea bx,ilc_5 cmp al,'5' je to_d0_il lea bx,ilc_6 cmp al,'6' je to_d0_il lea bx,ilc_7 cmp al,'7' je to_d0_il lea bx,ilc_8 cmp al,'8' je to_d0_il lea bx,ilc_9 cmp al,'9' je to_d0_il jmp do_il_ to_d0_il: jmp do_il il_try15: cmp max,16d je il_16 cmp max,12d je il_12 ; lea bx,ila_2 ; cmp max,11d ; ja to_il_is1 lea dx,intlve ;ask about interleave factor cmp max,9d jbe il_test_it lea dx,intlve2 il_test_it: ; push bx mov ah,9 int 21h mov ah,1 int 21h

;

pop bx cmp al,24d jne next_test_il_test_it jmp askbios next_test_il_test_it: cmp byte ptr max,10d jne skip_bx_if_not_ten lea bx,ila_2 mov il_addr,bx skip_bx_if_not_ten: cmp al,13d ;default ? je to_do_il cmp al,10d je to_do_il cmp al,'1' ;is it 2? jne il_not1 to_il_is1: jmp il_is1 il_not1: cmp al,'2' ;is it 2? jne il_not2 lea bx,il8_2 mov al,byte ptr max cmp al,8 je to_do_il lea bx,ila_2 cmp al,11 jb to_do_il lea bx,ilt_2 to_do_il: jmp do_il il_not2: cmp al,'3' ;is it 3? jne il_not3 lea bx,ila_3 mov al,byte ptr max

cmp je lea cmp je lea cmp je lea jmp il_not3: cmp jne lea mov cmp je lea cmp je lea cmp je lea jmp il_not4: cmp jne lea mov cmp je lea cmp jb lea

al,10 to_do_il bx,il9_3 al,9 to_do_il bx,il8_3 al,8 to_do_il bx,ilt_3 do_il al,'4' ;is it 4? il_not4 bx,ila_4 al,byte ptr max al,10 to_do_il bx,il9_4 al,9 to_do_il bx,il8_4 al,8 to_do_il bx,ilt_4 do_il al,'5' ;is it 5? il_not5 bx,il8_5 al,byte ptr max al,8 to_do_il bx,ila_5 al,11 to_do_il bx,ilt_5

jmp il_not5: cmp jne lea mov cmp je lea cmp je lea cmp je lea t0_do_il: jmp il_not6: cmp jne lea mov cmp je lea cmp je lea cmp je lea jmp il_not7: cmp jne lea

do_il al,'6' ;is it 6? il_not6 bx,ila_6 al,byte ptr max al,10 t0_do_il bx,il9_6 al,9 t0_do_il bx,il8_6 al,8 t0_do_il bx,ilt_6 do_il al,'7' ;is it 7? il_not7 bx,ila_7 al,byte ptr max al,10 do_il bx,il9_7 al,9 do_il bx,il8_7 al,8 do_il bx,ilt_7 do_il al,'8' il_not8 bx,ila_8 ;is it 8?

mov cmp je lea cmp je lea cmp je lea jmp il_not8: cmp jne lea mov cmp je lea cmp je lea cmp je lea jmp il_not9: lea cmp je jmp il_is1: lea do_il: mov do_il_:

al,byte ptr max al,10 do_il bx,il9_8 al,9 do_il bx,il8_8 al,8 do_il bx,ilt_8 do_il al,'9' ;is it 9? il_not9 bx,ila_9 al,byte ptr max al,10 do_il bx,il9_9 al,9 do_il bx,il8_9 al,8 do_il bx,ilt_9 do_il bx,ila_2 byte ptr max,10d do_il il_extend bx,ilt_1 il_addr,bx

lea si,table+2 mov cl,byte ptr max il_loop: mov al,byte ptr ds:[bx] mov byte ptr ds:[si],al inc bx add si,4 dec cl jne il_loop ; cmp max,11d ; ja doub ; cmp quad_den,1 ; je doub jmp askside il_extend: lea bx,ilt_2 cmp byte ptr max,20d je do_il lea bx,ilw_2 jmp do_il il_is21: lea bx,ilw_2 lea dx,intlve2 ;ask about interleave factor push bx mov ah,9 int 21h mov ah,1 int 21h pop bx cmp al,24d ;^X = start over jne next_test_21 jmp askbios next_test_21: lea bx,ilw_2 cmp al,13d ;default ? je t0_d0_1l

cmp je lea cmp je lea cmp je lea cmp je lea cmp je lea cmp je lea cmp je lea cmp je lea cmp je lea cmp je lea t0_d0_1l: jmp il_is20: lea lea push

al,10d t0_d0_1l bx,ilw_2 al,'2' t0_d0_1l bx,ilw_3 al,'3' t0_d0_1l bx,ilw_4 al,'4' t0_d0_1l bx,ilw_5 al,'5' t0_d0_1l bx,ilw_6 al,'6' t0_d0_1l bx,ilw_7 al,'7' t0_d0_1l bx,ilw_8 al,'8' t0_d0_1l bx,ilw_9 al,'9' t0_d0_1l bx,ilw_1 al,'1' t0_d0_1l bx,ilw_2 do_il_ bx,ilt_2 dx,intlve2 bx ;ask about interleave factor

mov ah,9 int 21h mov ah,1 int 21h pop bx cmp al,24d jne next_test_20 jmp askbios next_test_20: lea bx,ilt_2 cmp al,13d je t0_d0_1l cmp al,10d je t0_d0_1l lea bx,ilt_2 cmp al,'2' je t0_d0_1l lea bx,ilt_3 cmp al,'3' je t0_d0_1l lea bx,ilt_4 cmp al,'4' je t0_d0_1l lea bx,ilt_5 cmp al,'5' je t0_d0_1l lea bx,ilt_6 cmp al,'6' je t0_d0_1l lea bx,ilt_7 cmp al,'7' je t0_d0_1l lea bx,ilt_8 cmp al,'8' je t0_d0_1l lea bx,ilt_9

;^X = start over

;default ?

cmp je lea cmp je lea jmp

al,'9' t0_d0_1l bx,ilt_1 al,'1' t0_d0_1l bx,ilt_2 do_il_

endif ;ifdef do_kfmt askside: mov firstside,0 lea dx,tellsq ;ask about sides - single? double? mov ah,9 int 21h mov ah,1 int 21h cmp al,24d jne next_test_sides jmp askbios next_test_sides: cmp al,'Y' ;Y or y = choose single je sing cmp al,'y' je sing cmp al,'B' ;B or b = single, side 1 only je backside cmp al,'b' je backside cmp al,'?' ;? = get help jne doub ;all else = choose double lea dx,sidehelp ;do help call help jmp askside backside: mov firstside,1 sing:

mov double,0 cmp quad_den,1 je quad_tracks jmp ask_track doub: mov double,1 cmp quad_den,1 je quad_tracks ask_track: mov maxtrack,0 lea dx,telltrk ;ask about tracks cmp byte ptr max,13d jb ask_track2 quad_tracks: mov maxtrack,40d lea dx,telltrk2 ;ask about tracks ask_track2: mov ah,9 int 21h mov ah,1 int 21h cmp al,24d jne next_test_track jmp askbios next_test_track: cmp al,'1' jne ntrk40 add maxtrack,40d jmp qverf ntrk40: cmp al,'2' jne ntrk41 add maxtrack,41d jmp qverf ntrk41: cmp al,'3' jne ntrk42 add maxtrack,42d

jmp ntrk42: cmp jne add jmp ntrk43: cmp jne add jmp ntrk44: cmp jne add jmp ntrk45: cmp jne mov mov jmp ntrk80: cmp jne mov mov jmp ntrk81: cmp jne mov mov jmp ntrk82: cmp

qverf al,'4' ntrk43 maxtrack,43d qverf al,'5' ntrk44 maxtrack,44d qverf al,'6' ntrk45 maxtrack,45d qverf al,'8' ntrk80 quad_den,1 maxtrack,79d qverf al,'9' ntrk81 quad_den,1 maxtrack,80d qverf al,'0' ntrk82 quad_den,1 maxtrack,81d qverf al,'-'

jne ntrk83 mov quad_den,1 mov maxtrack,82d jmp qverf ntrk83: cmp al,'=' jne ntrk84 mov quad_den,1 mov maxtrack,83d jmp qverf ntrk84: cmp al,'?' je trkhlp add maxtrack,39d jmp qverf trkhlp: lea dx,hlptrk cmp maxtrack,40d jne helptrk lea dx,hlptrk2 helptrk: call help jmp ask_track qverf: ifdef do_kfmt lea dx,tell3q ;ask about verify mov ah,9 int 21h mov ah,1 int 21h cmp al,24d jne next_test_verf jmp askbios next_test_verf: cmp al,'Y' ;Y or y = do verify je verf

cmp al,'y' je verf cmp al,'?' ;? = get help jne noverf ;all else = no verify lea dx,verfhelp call help jmp qverf verf: mov verify,1 jmp trydos noverf: mov verify,0 trydos: endif ;ifdef do_kfmt mov al,0 cmp dosv,al jne not_special jmp askdos ;dosv=0 indicates special boot record not_special: mov al,byte ptr [bootbuf+8] ;boot rec for which dos jmp wdos askdos: lea dx,dosmess ;couldn't figure which dos - ask mov ah,9 int 21h mov ah,1 int 21h cmp al,24d jne wdos jmp askbios wdos: cmp al,'?' ;want help? je dos_help cmp al,'j' je do_jdos cmp al,'J'

jne do_jdos: mov mov mov jmp dos_help: lea call jmp dos1q: cmp jb cmp jb mov mov mov jmp gotdos: sub mov cmp je mov sub mov askdrive: mov cmp jne lea jmp oneplus: cmp jne

dos1q dosv,1 dosvm,1 jdos,1 askdrive dx,doshelp help askdos al,'1' askdos al,'7' gotdos al,'3'-'0' dosv,al dosvm,030d askdrive al,'0' ;got dos version - convert to binary dosv,al al,0 askdrive al,byte ptr [bootbuf+10d] ;boot rec for which dos minor al,'0' ;got dos version - convert to binary dosvm,al al,nodrives al,1 oneplus dx,dr1vemess askdrv al,2 twoplus ;ask which drive A or B?

lea dx,dr2vemess jmp askdrv twoplus: cmp al,3 jne thrplus lea dx,dr3vemess jmp askdrv thrplus: cmp al,4 ja fourplus lea dx,dr4vemess jmp askdrv fourplus: mov nodrives,1 lea dx,dr1vemess askdrv: mov ah,9 int 21h mov ah,1 int 21h cmp al,24d jne next_test_drive jmp askbios next_test_drive: cmp al,'0' ;0, a, A all mean drive A je doa cmp al,'A' je doa cmp al,'a' jne nota ; wasn't a - maybe b doa: mov byte ptr drive,0 jmp doit nota: mov ah,nodrives cmp ah,2

jb cmp je cmp je cmp je cmp jae jmp dob:

askdrive al,'1' ;1, b, B all mean drive B dob al,'B' dob al,'b' dob ah,3 try_c haskdrive ;wasn't A or B - ask again

mov drive,1 jmp doit try_c: cmp al,'2' ;2, c, C all mean drive C je doc cmp al,'C' je doc cmp al,'c' je doc cmp ah,4 jae try_d jmp haskdrive ;wasn't A or B - ask again doc: mov drive,2 jmp doit try_d: cmp al,'3' ;3, d, D all mean drive D je dod cmp al,'D' je dod cmp al,'d' je dod haskdrive: mov al,030h add al,nodrives

mov numdr,al cmp al,030h je already dec al already: mov numdr2,al lea dx,drivhelp call help jmp askdrive dod: mov drive,3 doit: cmp maxtrack,43d ja forty_plus jmp doit2_5 forty_plus: cmp max,11d jae doit2_5 push bp lea bp,a_3_5 add bp,word ptr drive mov al,byte ptr ds:[bp] mov Quad_density,al cmp byte ptr ds:[bp],0 jne doit2_5 lea dx,three_five ;what kind of drive do we have? mov ah,9 int 21h mov ah,1 int 21h cmp al,24d jne next_test_forty_plus jmp askbios next_test_forty_plus: cmp al,'5' je is_five

cmp al,'H' je is_five cmp al,'h' jne not_five is_five: mov Quad_density,57h jmp doit2 not_five: mov Quad_density,97h cmp al,'?' jne doit2 lea dx,help_3_5 mov ah,9 int 21h jmp forty_plus doit2: push bp ;we found out what it is, save it lea bp,a_3_5 add bp,word ptr drive mov al,Quad_density mov byte ptr ds:[bp],al pop bp doit2_5: mov ax,040H mov es,ax mov di,090H add di,word ptr drive and di,0FFFDh cmp byte ptr max,13d jb No_set_hi mov format_type,3 cmp byte ptr max,15d ja plus_formats mov byte ptr es:[di],15h jmp Done_set plus_formats:

mov format_type,6 mov byte ptr es:[di],17h jmp Done_set No_set_hi: cmp byte ptr max,11d jb No_set_mid mov format_type,7 mov byte ptr es:[di],57h jmp Done_set No_set_mid: cmp byte ptr maxtrack,42d ja No_set_double mov format_type,2 mov byte ptr es:[di],74h jmp Done_set No_set_double: mov al,byte ptr Quad_density ;97h if 3.5" ;57h if 5.25" mov format_type,5 ;or 4 mov byte ptr es:[di],al Done_set: mov al,byte ptr es:[di] mov byte ptr disk_state_machine,al mov dsm_addr,di ; push cs ; pop es mov mov mov mov mov call mov mov push pop ah,17h cx,0 dh,ch al,byte ptr format_type dl,drive near ptr disk al,byte ptr disk_state_machine byte ptr es:[si],al cs es

lea dx,ready ;all set - tell me when to start mov ah,9 int 21h mov ah,1 int 21h ;go! cmp al,24d jne next_test_go_for_it jmp askbios next_test_go_for_it: mov ah,18h mov al,max mov dl,drive mov dh,byte ptr ds:[parm_addr+5] mov cl,max mov ch,maxtrack call near ptr disk mov ax,0 mov dx,ax mov cx,ax call near ptr disk ;reset the disk system mov ah,18h mov al,max mov dl,drive mov dh,0 mov cl,max mov ch,maxtrack int 13h mov errcount,0 mov di,3 formpt: mov ax,0 mov dx,ax mov cx,ax call near ptr disk ;reset the disk system ifdef do_kfmt

mov ah,9 lea dx,tell1 ;tell 'em we're formatting int 21h mov byte ptr track,0;start at track 0 .list formloop: call dotrack ;formatting loop inc byte ptr track ; next track push ax mov ax,word ptr track cmp al,byte ptr maxtrack ; done yet? pop ax jna formloop ; no - keep going endif mov mov mov call mov lea int mov mov mov call lea ; cmp ja lea cmp je jmp ;ifdef do_kfmt ax,0 dx,ax cx,ax near ptr disk ;reset disk after formatting ah,9 dx,tell2 ;initialize message 21h ax,0 dx,ax cx,ax near ptr disk ;reset disk after formatting di,byte ptr bootbuf[20h] ;setup disk parms in boot rec in dos3.1 they are @ offset 20h dosv,1 notdos1 di,byte ptr bootbuf[1abH] ;in jdos 1.77 @ offset 1ab jdos,1 move_it writeit ;but don't mess bootrec if dos1 or special

notdos1: cmp dosv,2 .xlist jne notdos2 cmp byte ptr ds:[di],0dfh je notdos2 cmp byte ptr ds:[di],0cfh je notdos2 ; in jdos 1.77 @ offset 1ab add di,1 ; in dos2 they are @ offset 21h jmp move_it notdos2: cmp dosv,3 ;not dos2, is it higher? ja no_move_it ; if dos > 3 then skip disk parm move cmp dosvm,1 ;assume dos3 if not dos2 jbe move_it ;minor version 1 cmp dosvm,2 ;minor version 2+? jae move_it ;not 3.2+ assume 3.1/3.0 ;isdos32: add di,0bh ;is 3.2+ adjust move_it: lea si,bootparm mov cx,11d push cs pop es cld rep movsb ;actually move the disk parm to boot rec no_move_it: lea si,bootbuf ;now initialize BPB data in boot rec mov word ptr [si+0bH],0200H;512 bytes/sector mov byte ptr [si+0dH],01H ;1 sector/cluster mov byte ptr [si+0eH],01H ;# of reserved(i.e., Boot) sectors mov word ptr [si+10H],02H ; two FATs xor ax,ax mov al,max mov word ptr [si+18h],ax ;sectors/track

;

xor ax,ax mov al,double inc al mov word ptr [si+1ah],ax ;# of heads xor al,al mov word ptr [si+1eh],ax ;# of special reserved sectors ; next compute the # of sectors (#cylinders * #heads * #sectors/track) mov al,byte ptr maxtrack inc ax mul word ptr max mov word ptr [si+13h],ax ;number of sectors cmp double,0 je issing shl ax,1 mov word ptr [si+13h],ax ;number of sectors jmp isdoub issing: mov byte ptr [si+11h],40h;4 directory sectors on single mov byte ptr [si+1ah],01 ;1 r/w head (ie. single sided) cmp imax,9 jne nots9 ; mov word ptr [si+13h],ax ;0168h sectors/disk for ss9 mov byte ptr [si+15h],0fch jmp writeit nots9: cmp imax,8 jne nots8 ; mov word ptr [si+13h],ax ;0140h sectors/disk for ss8 mov byte ptr [si+15h],0feh jmp writeit nots8: ; mov word ptr [si+13h],ax ;is single sided but not ss9 ;or ss8 - init as ss10 mov byte ptr [si+15h],0fah jmp writeit isdoub:

mov mov ; mov cmp jne ; mov mov mov jmp notd9: cmp jne ; mov mov mov jmp notd8: mov mov cmp je cmp jae cmp jae ; mov jmp is_20: mov jmp is_15: writeit: cmp je inc

byte ptr [si+11h],70h;7 directory sectors for double byte ptr [si+1ah],02 ;2 r/w heads (ie. double) word ptr [si+13h],ax imax,9 notd9 word ptr [si+13h],ax ;02d0h sectors/disk in ds9 byte ptr [si+15h],0fdh byte ptr [si+0dh],02 ;2 sectors/cluster on double sided writeit imax,8 notd8 word ptr [si+13h],ax ;0280h sectors/disk in ds8 byte ptr [si+0dh],02 ;2 sectors/cluster on double sided byte ptr [si+15h],0ffh writeit word ptr [si+11h],090h byte ptr [si+15h],0f9h imax,12d is_20 imax,18d is_20 imax,15d is_15 word ptr [si+13h],ax ;is double but not ds9 nor ds8 ;so initialize as ds10 writeit byte ptr [si+15h],0f0h writeit al,0 no_round ah ;First figure Number of FAT sectors ; ax has total number of sectors on disk ; ax * 1.5 /512 /#sect/clu = # FAT sectors ; * 1.5/512 == *3 /1024 == /256 *3 /4

no_round: mov al,ah ; divide by 256 == shift 8 bit == move byte add al,ah ; add al,ah ; * 3 mov ah,al ;retain copy for rounding shr al,1 shr al,1 ; divide by 4 (to complete /1024) cmp ah,0 je no_round2 inc al xor ah,ah no_round2: lea si,bootbuf div byte ptr [si+0dh] ;divide by #sectors/Cluster cmp ah,0 je no_round3 inc al xor ah,ah no_round3: cmp ax,0 jnz sect_FAT_ok mov al,1 sect_FAT_ok: mov word ptr [si+16h],ax cld ;copy boot record to duplicate buffer ; lea si,bootbuf ; if we got loaded so that bootbuf push cs ; will cross DMA boundary pop es ; we will try again with duplicate lea di,bootdup ; (PARANOID PROGRAMMING!) mov bx,si mov cx,100h rep movsw ; lea bx,bootbuf ;write boot record to disk mov dl,byte ptr drive mov dh,0 ;on side 0 mov cx,1 ;track 0, sector 1

mov ax,0301h ;write 1 sector call near ptr disk jnc cool01 ;no errors? mov ah,0 call near ptr disk ;reset disk after error lea bx,bootdup ;flaked - try w/duplicate mov ax,0301h ;write 1 sector mov cx,1 ;track 0, sector 1 call near ptr disk jnc cool01 ;no errors? mov al,ah call die ;report error mov ah,0 mov dx,0 call near ptr disk ;reset disk after error cool01: mov ah,9 lea dx,tell3 ;message: Boot Sector int 21h ; mov bx,buffer mov es,bx assume es:nothing ;clear the r/w buffer mov bx,0 mov di,bx mov cx,5120d ;20 * 512 byte sector of 0 mov ax,0 rep stosw cmp dosv,1 ; check for dos1 jne not_dos_1 mov di,0400h ;is dos1 - fill dir w/e5 mov ax,0e5e5h mov cx,2048d ; 8 * 512 byte sector of e5 rep stosw not_dos_1: mov dl,byte ptr drive ;fill rest of track 0, side0

mov mov mov mov sub inc mov call jnc mov call mov mov mov call cool11: mov lea int cmp je mov mov mov mov mov mov mov mov ; sub ; inc mov call jnc mov call

dh,0 ;with zeroes ch,0 ;track 0 cl,2 ;start with sector 2 al,max ;do 1 less than # sectors/track al,cl al ah,3 ;write near ptr disk cool11 ;no errors? al,ah die ;report error ah,0 dh,0 dl,byte ptr drive near ptr disk ;reset disk after error ah,9 dx,tell4 ;message: Side 1 FAT & Root 21h double,0 ;if single cool21_no_write ; skip over next bx,buffer ;fill track 0, side 1 es,bx ;with zeroes bx,0 dl,byte ptr drive dh,1 ;side 1 ch,0 ;track 0 cl,1 ;start @ sector 1 al,max ;do whole track al,cl al ah,3 ;write near ptr disk cool21 ;no errors? al,ah die ;report error

mov ah,0 mov dh,0 mov dl,byte ptr drive call near ptr disk ;reset disk after error cool21: mov ah,9 lea dx,tell5 ;message: Side 2 FAT & Root int 21h cool21_no_write: mov bx,buffer ;get ready to write first FAT mov es,bx mov bx,0 mov di,0 mov al,byte ptr bootbuf+15h mov byte ptr es:[di],al ;first byte is FAT id mov word ptr es:[di+1],0ffffh mov al,1 ;do 1 sector mov ah,3 ;write mov dl,byte ptr drive mov dh,0 ;side 0 mov ch,0 ;track 0 mov cl,2 ;FAT begins in sector 2 call near ptr disk jnc cool12 ;no errors? mov al,ah call die ;report error mov ah,0 mov dx,0 call near ptr disk ;reset disk after error cool12: mov ah,9 lea dx,tell6 ;message: First FAT w/Media ID int 21h mov cl,byte ptr bootbuf+16h add cl,2 xor ch,ch

was8: mov al,1 ;rest of FAT copy (if any) is mov ah,3 ; already 0, just do first sector mov dl,byte ptr drive mov dh,0 mov ch,0 mov bx,buffer mov es,bx mov bx,0 call near ptr disk jnc cool13 mov al,ah call die mov ah,0 mov dx,0 call near ptr disk ;reset disk after error cool13: mov byte ptr track,0 ;initialization done cmp verify,1 ;do verify? je doverify ; yes - go to it jmp qano ;no verify, ask about another doverify: ifdef do_kfmt mov ah,9 ;yes verify - say so lea dx,tell3v int 21h vloop: push di lea di,tracks add di,word ptr track add di,word ptr track mov cx,[di] lea di,trnum mov [di],cx pop di lea dx,trmess ;and tell which track

mov int mov mov mov mov mov mov mov mov mov mov mov mov call jnc mov call mov mov call cool15: mov mov mov mov mov mov mov mov mov call jnc mov call mov

ah,9 21h dl,byte ptr drive dh,0 ;read side 0 al,byte ptr max cl,1 ch,byte ptr track bx,buffer es,bx bx,0 ah,2 bx,buffer es,bx bx,0 near ptr disk cool15 al,ah die ;error - report it ah,0 dx,0 near ptr disk ;reset disk after error dl,byte ptr drive dh,1 ;read side 1 al,byte ptr max cl,1 ch,byte ptr track bx,buffer es,bx bx,0 ah,2 near ptr disk cool17 al,ah die ;error - report it ah,0

mov call cool17: inc push mov cmp pop ja jmp endif qano: lea mov int mov int cmp je cmp je cmp jne jmp ism: cmp jne jmp notm: cmp jne jmp not_C_X: jmp

dx,0 near ptr disk

;reset disk after error ;next track

byte ptr track ax ax,word ptr track al,byte ptr maxtrack ax qano vloop ;ifdef do_kfmt dx,another ;done with this disk ah,9 ;do another? 21h ah,1 21h al,'Y' toaskdrive ;if so - go ask drive al,'y' toaskdrive al,'M' ism askbios ;do another - but new parameters al,'m' notm askbios al,24d not_C_X askbios exit ;no more - get out

toaskdrive: mov ax,0 mov dx,ax mov cx,ax int 13H do_il2: ifdef do_kfmt mov bx,il_addr lea si,table+2 mov cl,byte ptr max il_loop2: mov al,byte ptr ds:[bx] mov byte ptr ds:[si],al inc bx add si,4 dec cl jne il_loop2 endif ;ifdef do_kfmt movit2: mov ax,0 ;copy new values into disk parm table mov es,ax assume es:nothing mov si,parm_addr les di,dword ptr es:[78h] ;0:78 is ptr to disk parm table mov cx,11d ;in PC-DOS this is 0:522 currently cld rep movsb push cs pop es assume es:code jmp askdrive ; flag db 0,0 disk:

push mov mov pop retry: push push push push push int pop pop pop pop jnc cmp jne mov inc mov cmp je pop push push push push push mov int pop pop pop pop pop

ax al,0 byte ptr cs:flag,al ax ax bx cx dx es 13h ;do BIOS disk routine es dx cx bx disk_ok ;disk error? al,80h ;yes - time out? disk_ok ;no - return al,byte ptr cs:flag ;yes is time out al byte ptr cs:flag,al al,2 ;retry count is ??? disk_ok ;exceeded - bye! ax ax bx cx dx es ax,0 13h ;do BIOS disk routine es dx cx bx ax

jmp retry disk_ok: pop es ;throw away saved ax push cs pop ds push cs pop es rets ; ; die: cmp al,3 ;BIOS reported error - what kind? jne not_wp lea dx,wp jmp sayit not_wp: cmp al,80h jne not_to lea dx,to jmp sayit not_to: cmp al,40h jne not_seek lea dx,seekfail jmp sayit not_seek: cmp al,20h jne not_nec lea dx,necerror jmp sayit not_nec: cmp al,10h jne not_crc lea dx,crc jmp sayit not_crc: cmp al,4 jmp not_notfound lea dx,notfound jmp sayit not_notfound: cmp al,0 jne still_err

rets still_err: lea dx,garrh jmp sayit ; help: mov ah,0 mov al,vid_mode ;clear screen and home cursor-quick and dirty push ax int 10h pop ax int 10h ; to prepare for writing help message push dx lea dx,hello mov ah,9 int 21h pop dx mov ah,9 int 21h rets ; sayit: mov ah,9 ;tell error, check how many int 21h inc errcount mov ah,errcount cmp ah,maxcount jna notend ;fewer than maxcount - continue jmp qano ;too many - skip rest of disk notend: rets ; dup_boot label near push cx push si push di push ds push es cld ;copy boot record to duplicate buffer

lea si,bootbuf push cs pop es push cs pop ds lea di,bootdup mov cx,100h rep movsw pop es pop ds pop di pop si pop cx rets ; rst_boot label near push cx push si push di push ds push es cld ;copy duplicate buffer back to boot buffer lea di,bootbuf push cs pop es push cs pop ds lea si,bootdup mov cx,100h rep movsw pop es pop ds pop di pop si pop cx rets

; ; exit: cmp max,10d je endend push cs pop ds lea si,tens mov ax,0 ;copy new values into disk parm table mov es,ax les di,dword ptr es:[78h] mov cx,11d cld rep movsb push cs pop es endend: mov ah,10H mov dh,4 ;if FLOP present, turn it on mov dl,7fH ;use modified install check mov bx,'FL' ;as in install check, but mov cx,'OP' ;if cx='OP', then we are signaling toggle-active int 13H mov ax,0 int 21h ;go home! - dos2 style end_of_code: int 20h ;go home! - dos1 style ; kformat endp code ends end start