You are on page 1of 65

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 0,0,3,2 ; place holder for the track #
db 0,0,4,2 ; the second zero is a place holder
db 0,0,5,2 ; for the head (ie. side) number
db 0,0,6,2 ; n - is the sector number
db 0,0,7,2 ; 2 - code for 512 bytes/sector
db 0,0,8,2
db 0,0,9,2
db 0,0,0ah,2
db 0,0,0bh,2 ;space is kept for more sectors if 256 bytes or HD
db 0,0,0ch,2
db 0,0,0dh,2
db 0,0,0eh,2
db 0,0,0fh,2
db 0,0,10h,2
db 0,0,11h,2
db 0,0,12h,2
db 0,0,13h,2
db 0,0,14h,2
db 0,0,15h,2
db 0,0,16h,2
db 0,0,17h,2

;
; 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 ? ;store address of r/w buffer in segment form
double db 1 ;formatting single(0) or double(1)
quad_den db 0 ;quad density?
firstside db 0 ;side to start formatting on
verify db 0 ;verifying(1) or no verify(0)
drive db 0 ;which drive 0=A, 1=B
db 0
track db 0,0 ;track counter for format & verify
maxtrack db 82d
max db 10d ;max sector number on track
db 0
imax db 9d ;max sector number initialized
dosv db 6 ;using with which version of PC-DOS
dosvm db 1 ; minor version
jdos db 0 ;Formatting for JDos (patched DOS 1.1)
sec_size db 2 ; 512 bytes / sector
nodrives db 1 ; number of floppies (will be set later)
defvid db 1
mod_vid db 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 movit
try6:
cmp al,'s'
je Hi_dens5pm
cmp al,'y'
je Hi_dens5palt
cmp al,'x'
je Hi_dens5p
cmp al,'h'
je Hi_dens5
cmp al,'i'
je Hi_dens3
cmp al,'z'
je TO_Hi_dens3p
cmp al,'q'
je quad
cmp al,'w'
je wquad
cmp al,'v'
je vquad
cmp al,'e' ;8 sec init on 10 sec format?
jne unknown_format
jmp f8t ; yes
quad: mov byte ptr max,9d
mov byte ptr imax,9d
lea si,nines
mov quad_den,1
jmp movit
wquad: mov byte ptr max,10d
mov byte ptr imax,10d
lea si,tens
mov quad_den,1
jmp movit
vquad: mov byte ptr max,12d
mov byte ptr imax,12d
lea 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 ;interleave factor of 1 is common default
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 ;ask about interleave factor
jmp il_test_it
il_1718:
cmp max,17d
jne il_18
lea bx,ile_2
lea dx,intlve2 ;ask about interleave factor
jmp il_1817
il_18:
lea bx,ile_1
lea dx,intlve3 ;ask about interleave factor
il_1817:
push bx
mov ah,9
int 21h
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 ;ask about interleave factor
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 ;default ?
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
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 al,10
je to_do_il
lea bx,il9_3
cmp al,9
je to_do_il
lea bx,il8_3
cmp al,8
je to_do_il
lea bx,ilt_3
jmp do_il
il_not3:
cmp al,'4' ;is it 4?
jne il_not4
lea bx,ila_4
mov al,byte ptr max
cmp al,10
je to_do_il
lea bx,il9_4
cmp al,9
je to_do_il
lea bx,il8_4
cmp al,8
je to_do_il
lea bx,ilt_4
jmp do_il
il_not4:
cmp al,'5' ;is it 5?
jne il_not5
lea bx,il8_5
mov al,byte ptr max
cmp al,8
je to_do_il
lea bx,ila_5
cmp al,11
jb to_do_il
lea bx,ilt_5
jmp do_il
il_not5:
cmp al,'6' ;is it 6?
jne il_not6
lea bx,ila_6
mov al,byte ptr max
cmp al,10
je t0_do_il
lea bx,il9_6
cmp al,9
je t0_do_il
lea bx,il8_6
cmp al,8
je t0_do_il
lea bx,ilt_6
t0_do_il:
jmp do_il
il_not6:
cmp al,'7' ;is it 7?
jne il_not7
lea bx,ila_7
mov al,byte ptr max
cmp al,10
je do_il
lea bx,il9_7
cmp al,9
je do_il
lea bx,il8_7
cmp al,8
je do_il
lea bx,ilt_7
jmp do_il
il_not7:
cmp al,'8' ;is it 8?
jne il_not8
lea bx,ila_8
mov al,byte ptr max
cmp al,10
je do_il
lea bx,il9_8
cmp al,9
je do_il
lea bx,il8_8
cmp al,8
je do_il
lea bx,ilt_8
jmp do_il
il_not8:
cmp al,'9' ;is it 9?
jne il_not9
lea bx,ila_9
mov al,byte ptr max
cmp al,10
je do_il
lea bx,il9_9
cmp al,9
je do_il
lea bx,il8_9
cmp al,8
je do_il
lea bx,ilt_9
jmp do_il
il_not9:
lea bx,ila_2
cmp byte ptr max,10d
je do_il
jmp il_extend
il_is1:
lea bx,ilt_1
do_il:
mov il_addr,bx
do_il_:
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 al,10d
je t0_d0_1l
lea bx,ilw_2
cmp al,'2'
je t0_d0_1l
lea bx,ilw_3
cmp al,'3'
je t0_d0_1l
lea bx,ilw_4
cmp al,'4'
je t0_d0_1l
lea bx,ilw_5
cmp al,'5'
je t0_d0_1l
lea bx,ilw_6
cmp al,'6'
je t0_d0_1l
lea bx,ilw_7
cmp al,'7'
je t0_d0_1l
lea bx,ilw_8
cmp al,'8'
je t0_d0_1l
lea bx,ilw_9
cmp al,'9'
je t0_d0_1l
lea bx,ilw_1
cmp al,'1'
je t0_d0_1l
lea bx,ilw_2
t0_d0_1l:
jmp do_il_
il_is20:
lea bx,ilt_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_20
jmp askbios
next_test_20:
lea bx,ilt_2
cmp al,13d ;default ?
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
cmp al,'9'
je t0_d0_1l
lea bx,ilt_1
cmp al,'1'
je t0_d0_1l
lea bx,ilt_2
jmp 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 qverf
ntrk42:
cmp al,'4'
jne ntrk43
add maxtrack,43d
jmp qverf
ntrk43:
cmp al,'5'
jne ntrk44
add maxtrack,44d
jmp qverf
ntrk44:
cmp al,'6'
jne ntrk45
add maxtrack,45d
jmp qverf
ntrk45:
cmp al,'8'
jne ntrk80
mov quad_den,1
mov maxtrack,79d
jmp qverf
ntrk80:
cmp al,'9'
jne ntrk81
mov quad_den,1
mov maxtrack,80d
jmp qverf
ntrk81:
cmp al,'0'
jne ntrk82
mov quad_den,1
mov maxtrack,81d
jmp qverf
ntrk82:
cmp 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 dos1q
do_jdos:
mov dosv,1
mov dosvm,1
mov jdos,1
jmp askdrive
dos_help:
lea dx,doshelp
call help
jmp askdos
dos1q:
cmp al,'1'
jb askdos
cmp al,'7'
jb gotdos
mov al,'3'-'0'
mov dosv,al
mov dosvm,030d
jmp askdrive
gotdos:
sub al,'0' ;got dos version - convert to binary
mov dosv,al
cmp al,0
je askdrive
mov al,byte ptr [bootbuf+10d] ;boot rec for which dos minor
sub al,'0' ;got dos version - convert to binary
mov dosvm,al
askdrive:
mov al,nodrives ;ask which drive A or B?
cmp al,1
jne oneplus
lea dx,dr1vemess
jmp askdrv
oneplus:
cmp al,2
jne twoplus
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 askdrive
cmp al,'1' ;1, b, B all mean drive B
je dob
cmp al,'B'
je dob
cmp al,'b'
je dob
cmp ah,3
jae try_c
jmp haskdrive ;wasn't A or B - ask again
dob:
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 ah,17h
mov cx,0
mov dh,ch
mov al,byte ptr format_type
mov dl,drive
call near ptr disk
mov al,byte ptr disk_state_machine
mov byte ptr es:[si],al
push cs
pop 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 ;ifdef do_kfmt

mov ax,0
mov dx,ax
mov cx,ax
call near ptr disk ;reset disk after formatting
mov ah,9
lea dx,tell2 ;initialize message
int 21h
mov ax,0
mov dx,ax
mov cx,ax
call near ptr disk ;reset disk after formatting
lea di,byte ptr bootbuf[20h] ;setup disk parms in boot rec
; in dos3.1 they are @ offset 20h
cmp dosv,1
ja notdos1
lea di,byte ptr bootbuf[1abH] ;in jdos 1.77 @ offset 1ab
cmp jdos,1
je move_it
jmp 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 byte ptr [si+11h],70h;7 directory sectors for double
mov byte ptr [si+1ah],02 ;2 r/w heads (ie. double)
; mov word ptr [si+13h],ax
cmp imax,9
jne notd9
; mov word ptr [si+13h],ax ;02d0h sectors/disk in ds9
mov byte ptr [si+15h],0fdh
mov byte ptr [si+0dh],02 ;2 sectors/cluster on double sided
jmp writeit
notd9:
cmp imax,8
jne notd8
; mov word ptr [si+13h],ax ;0280h sectors/disk in ds8
mov byte ptr [si+0dh],02 ;2 sectors/cluster on double sided
mov byte ptr [si+15h],0ffh
jmp writeit
notd8:
mov word ptr [si+11h],090h
mov byte ptr [si+15h],0f9h
cmp imax,12d
je is_20
cmp imax,18d
jae is_20
cmp imax,15d
jae is_15
; mov word ptr [si+13h],ax ;is double but not ds9 nor ds8
;so initialize as ds10
jmp writeit
is_20:
mov byte ptr [si+15h],0f0h
jmp writeit
is_15:
writeit: ;First figure Number of FAT sectors
cmp al,0 ; ax has total number of sectors on disk
je no_round ; ax * 1.5 /512 /#sect/clu = # FAT sectors
inc ah ; * 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 dh,0 ;with zeroes
mov ch,0 ;track 0
mov cl,2 ;start with sector 2
mov al,max ;do 1 less than # sectors/track
sub al,cl
inc al
mov ah,3 ;write
call near ptr disk
jnc cool11 ;no errors?
mov al,ah
call die ;report error
mov ah,0
mov dh,0
mov dl,byte ptr drive
call near ptr disk ;reset disk after error
cool11:
mov ah,9
lea dx,tell4 ;message: Side 1 FAT & Root
int 21h
cmp double,0 ;if single
je cool21_no_write ; skip over next
mov bx,buffer ;fill track 0, side 1
mov es,bx ;with zeroes
mov bx,0
mov dl,byte ptr drive
mov dh,1 ;side 1
mov ch,0 ;track 0
mov cl,1 ;start @ sector 1
mov al,max ;do whole track
; sub al,cl
; inc al
mov ah,3 ;write
call near ptr disk
jnc cool21 ;no errors?
mov al,ah
call 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 ah,9
int 21h
mov dl,byte ptr drive
mov dh,0 ;read side 0
mov al,byte ptr max
mov cl,1
mov ch,byte ptr track
mov bx,buffer
mov es,bx
mov bx,0
mov ah,2
mov bx,buffer
mov es,bx
mov bx,0
call near ptr disk
jnc cool15
mov al,ah
call die ;error - report it
mov ah,0
mov dx,0
call near ptr disk ;reset disk after error
cool15:
mov dl,byte ptr drive
mov dh,1 ;read side 1
mov al,byte ptr max
mov cl,1
mov ch,byte ptr track
mov bx,buffer
mov es,bx
mov bx,0
mov ah,2
call near ptr disk
jnc cool17
mov al,ah
call die ;error - report it
mov ah,0
mov dx,0
call near ptr disk ;reset disk after error
cool17: ;next track
inc byte ptr track
push ax
mov ax,word ptr track
cmp al,byte ptr maxtrack
pop ax
ja qano
jmp vloop

endif ;ifdef do_kfmt

qano:
lea dx,another ;done with this disk
mov ah,9 ;do another?
int 21h
mov ah,1
int 21h
cmp al,'Y'
je toaskdrive ;if so - go ask drive
cmp al,'y'
je toaskdrive
cmp al,'M'
jne ism
jmp askbios ;do another - but new parameters
ism:
cmp al,'m'
jne notm
jmp askbios
notm:
cmp al,24d
jne not_C_X
jmp askbios
not_C_X:
jmp 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 ax
mov al,0
mov byte ptr cs:flag,al
pop ax
retry:
push ax
push bx
push cx
push dx
push es
int 13h ;do BIOS disk routine
pop es
pop dx
pop cx
pop bx
jnc disk_ok ;disk error?
cmp al,80h ;yes - time out?
jne disk_ok ;no - return
mov al,byte ptr cs:flag ;yes is time out
inc al
mov byte ptr cs:flag,al
cmp al,2 ;retry count is ???
je disk_ok ;exceeded - bye!
pop ax
push ax
push bx
push cx
push dx
push es
mov ax,0
int 13h ;do BIOS disk routine
pop es
pop dx
pop cx
pop bx
pop 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

You might also like