home *** CD-ROM | disk | FTP | other *** search
- (*
- To: INFO-IBMPC-REQUEST@USC-ISIB.ARPA
- From: U001222%HNYKUN11.BITNET@WISCVM.WISC.EDU
- Subject: reformat.pas
- *)
- PROGRAM reformat;
- {
- Program to reformat any disk attached to an Olivetti PC or compatible.
- The progam will work well on any MS/PC-DOS machine running under DOS
- versions 2.00 up to and including 3.10. Fixed disks up to 32 Meg.
-
- V1.50 Extensions made for big FATs. WORD.INC included for handling of
- word integers. MS-DOS function INT21 / 32H used for drive information.
- Corrected the problem of DOS losing track of the current directory.
-
- The program has been tested under DOS 2.00 thru 3.10
- It will probably work under DOS 3.20 too, but this version will not
- run when you try to do so. If you want to test it with DOS 3.20, look
- for the string DOS_Versions (it's somewhere near the end of the program)
- in this program, and include that version number into the test.
- Please let the author know whether you had success or not.
-
- Jos Wennmacker July 86.
- Universitair Rekencentrum
- Geert Grooteplein Zuid 41
- 6525 GA Nijmegen
- The Netherlands
-
- BITNET address: U015415 at HNYKUN22
-
- V1.5 Jos added new 16-bit and word code, handling up to 30Meg
- hard disks, etc. I cleaned up the integer math inline procedures
- a little.
- David Kirschbaum, Toad Hall
-
- V1.23 Added FRAMER.INC, WRITEF.INC for framing, fast screen write,
- fast screen line clear. Tightened up displays a little.
- This version is now VERY PC-specific. Generic MS-DOS functions
- for screen stuff to follow.
- David Kirschbaum, Toad Hall.
-
- V1.22 Added inline code to replace the INT25.ASM and INT26.ASM
- files.
- David Kirschbaum, Toad Hall, 3 May 86
-
- V1.21(mod) not publicly released. Changes made by Rick Watson to let
- the program recognize the big (16 bit) FATs. He made it run on 20 Meggers
- under DOS 3.x. Martin Hobson made it run on 30 Meggers under DOS 3.x.
- May 86.
-
- V1.21 Small corrections made to avoid Turbo integer overflow. (Hey,
- Borland, what about a WORD type in Turbo, would be very usefull using
- the MSDOS features!).
-
- V1.20 First release to the public domain.
- What started as a favour to a friend grew into a nice program.
- Do you like it? Let me know about it! If I know many people to use it,
- I'll keep it up to date, and send you new releases.
- Jos Wennmacker
-
- }
- {$C-}
- {-------------------------------- Global types -------------------------------}
-
- TYPE
-
- {------------------- types for word arithmetic see REFORMAT.IN1 -------------}
-
- word = INTEGER;
-
- Relational_Operator = (Eq, Gt, Lt, Ne, Ge, Le);
-
- {------------------------ for interrupts and DOS calls -----------------------}
-
- Regpack =
- RECORD CASE INTEGER OF
- 1: (ax, bx, cx, dx, bp, si, di, ds, es, flags : word);
- 2: (al, ah, bl, bh, cl, ch, dl, dh : Byte);
- END;
-
- {----------------------------- Bootrecord layout -----------------------------}
-
- Boot = { the layout of the DOS boot record }
- RECORD
- Jump: ARRAY[0..2] OF Byte; { Near jump to boot code }
- OEM : ARRAY[0..7] OF CHAR; { eight character OEM name }
- sectorSize: word; { number of bytes in one sector }
- clusterSize: Byte; { sectors per cluster }
- reservedSectors: word; { DOS boot code sector(s) typically 1 }
- numberOfFATs: Byte; { usually 2, but often 1 for RAM disks }
- rootDirSize, { maximum entries in root directory }
- totalSectors: word; { total sectors in the logical image }
- mediaDescriptor: Byte; { A limited description of the drive
- bit 0 = 1: twosided, 0: not two-sided
- bit 1 = 1: 8-sector, 0: not 8-sector
- bit 2 = 1: removable 0: not removable
- bits 3-7 must be set to 1 }
- fatSize, { number of sectors in each FAT copy }
- trackSize, { number of sectors per track }
- numberOfHeads, { number of heads }
- hiddenSectors: word; { sectors hidden from DOS, preceding
- the DOS partition: including the
- master boot record and any non-DOS
- partitions }
- END;
-
- {---------------- Layout of DOS function 32h disk parameter block ------------}
-
- Parms_32 = ^Parameter_table;
-
- Parameter_Table = { layout of the DOS function 32 table }
- RECORD
- assignedDisk, { 0 = A, 1 = B, ... }
- altAD: Byte; { same as above, but 0 for RAM disk }
- sectorSize: word; { number of bytes in one sector }
- clusterSize_1, { sectors per cluster minus 1 }
- numberOfHeads_1: Byte; { number of heads minus 1 }
- reservedSectors: word; { DOS boot code sector(s) typically 1 }
- numberOfFATs: Byte; { usually 2, but often 1 for RAM disks }
- rootDirSize, { maximum entries in root directory }
- firstDataSector, { first sector for data storage }
- totalDataClusters_1: word; { total data clusters plus 1 }
- fatSize: Byte; { number of sectors in each FAT copy }
- firstDirectorySector: word; { first sector of the root directory }
- DeviceDriverAddress: ^byte; { Far (offset, segment) address of the
- DOS device driver for the drive }
- mediaDescriptor: word; { A limited description of the drive
- only the low order byte is used:
- bit 0 = 1: twosided, 0: not two-sided
- bit 1 = 1: 8-sector, 0: not 8-sector
- bit 2 = 1: removable 0: not removable
- bits 3-7 must be set to 1 }
- NextParameterTable: Parms_32; { far pointer to next disk table }
- currentDirCluster: word; { Starting cluster of current working
- directory. According to Glenn Roberts
- in his May 86 PC Tech Journal article
- "Finding Disk Parameters" this would
- only hold for PC DOS 2.00
- }
- CurrentDirName: ARRAY [0..63] OF CHAR
- {
- The name of the current working
- directory. This does not hold for
- DOS 3.x versions. Only for 2.00 }
- END;
-
- {-------- Long byte and integerarays for Disk Transfer Area, Fats etc. -------}
-
- intArray = ARRAY[0..32766] OF INTEGER;
-
- buffer = ARRAY[0..32766] OF Byte;
-
- {--------------------- Element of tree of directory entries ------------------}
-
- DirectoryPointer = ^DirectoryEntry;
-
- longInteger = ARRAY[0..1] OF INTEGER;
-
- DirectoryEntry =
- RECORD
- EntryName: ARRAY[0..10] OF CHAR; { name + extension w/o period
- If the first char is $00 then this
- entry was never used. Also the next
- entries in this directory have never
- been used.
- If the first char is $E5 then this
- entry was erased. }
- attribute: Byte; { attribute of entry:
- bit if set means
- 0 read only file
- 1 hidden file
- 2 system file
- 3 volume label
- 4 subdirectory
- 5 archive bit }
- reserved: ARRAY[1..10] OF Byte; { for future use }
- timeLastUpdated: word; { mapped in the bits:
- < hh > < mm > < xx >
- 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
- where:
- hh binary number of hours [0..23]
- mm binary number of minutes [0..59]
- xx binary number of two-second
- increments [0..28] }
- dateLastUpdated: word; { mapped in the bits
- < yy > < mm > < dd >
- 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
- where:
- yy binary number of years [0..119]
- (1980-2099)
- mm binary number of month [1..129]
- dd binary number of day [1..31] }
- startingCluster: word; { index of the file's first cluster }
- fileSize: longInteger; { filesize in bytes }
- newStartingCluster: word;
- Next,
- SubDirectory: DirectoryPointer;
- END;
-
- {------------------------------- Helps for I/O -------------------------------}
-
- WorkString = STRING[255];
- Line = STRING[78];
- Str40 = STRING[40];
-
- Disk_Activity = (reading,writing);
-
- {-------------------------------- constants ----------------------------------}
-
- CONST
-
- Header: STRING[37] = ' REFORMAT: an original JOS disk tool ';
- Version: STRING[10] = 'Ver: 1.50 ';
- PDS: STRING[24] = ' Public Domain Software ';
- EnterStr: STRING[28] = 'Press Enter to return to DOS';
- HiSpace: STRING[01] = #160; {WriteF blank line flag }
-
- {--------------------------- FAT special values ------------------------------}
-
- unused: word = $0000; { we use typed constants, because }
- reservedMinimum: word = $0FF0; { we might have to change these values }
- reservedMaximum: word = $0FF6; { the values entered here are for }
- badCluster: word = $0FF7; { the old, small FAT format of 12 bits }
- lastMinimum: word = $0FF8; { per entry. The new FAT format uses }
- lastMaximum: word = $0FFF; { 16 bit-entries. See the procedure }
- lastNormal: word = $0FFF; { Getinformation. }
-
- {---------------------- file attribute byte values----------------------------}
-
- READONLY = $01; { file attribute byte }
- HIDDENFILE = $02;
- SYSTEMFILE = $04;
- VOLUMELABEL = $08;
- SUBDIRECTORY = $10;
- ARCHIVE = $20;
-
- NEVERUSED = $00; { first byte of file's name }
- ERASED = $E5;
-
- FIXEDDISK = $F8; { some values of mediaDescriptor }
- DUAL8SECTOR = $FF;
- SINGLE8SECTOR = $FE;
- DUAL9SECTOR = $FD;
- SINGLE9SECTOR = $FC;
-
- {---------- constants for the screen layout, for FRAMER and WRITEF procedures }
-
- MIDDLEFIELDY = 18; { little window in the middle }
- INPUTFIELDX = 22; { User Input Field }
- INPUTFIELDY = 20;
- LOGFIELDX = 22; { Activity Logging }
- LOGFIELDY = 21;
- WARNINGFIELDX = 22; { Warning Message Field }
- WARNINGFIELDY = 22;
- ERRORFIELDX = 22; { Error Message Field }
- ERRORFIELDY = 23;
- DISASTERFIELDX = 22; { Disaster Message Field }
- DISASTERFIELDY = 24;
-
- {-------- Drive characteristics and constants communications block -----------}
-
- VAR
-
- DriveLetter: CHAR;
- driveNumber: Byte;
- defaultDrive: Byte;
-
- totalSectors,
- sectorSize: word;
- media: Byte;
- trackSize,
- numberOfHeads,
- hiddenSectors,
- reservedSectors,
- rootDirSize: word;
- numberOfFATs: Byte;
- fatSize: word;
- clusterSize: Byte;
- firstDataSector,
- firstDirectorySector,
- totalDataClusters,
- freeClusters,
- badClusters,
- usedClusters: word;
- DeviceDriverAddress: ^byte;
- CurrentDirectory: ARRAY[0..63] OF CHAR;
- DiskLabel: STRING[11];
- diskCreationDate,
- diskCreationTime: word;
- OEM: ARRAY[0..7] OF CHAR;
- assignedDisk,
- altAD: Byte;
-
- BigFAT: BOOLEAN;
-
- firstFATsector,
- directorySectors: word;
-
- {----------------------------- Global variables ------------------------------}
-
- Register: Regpack;
-
- oldFATindex,
- newFATindex: word;
- totalFiles,
- hiddenFiles,
- hiddenDirectories,
- inRootDirectory,
- inSubdirectories,
- nonContiguousFiles,
- subdirectories,
- movedClusters,
- clustersToMove,
- lostClusters,
- errors,
- count: INTEGER;
-
- SAVEaddress,
- DTAddress: ^buffer;
-
- PermutationAddress,
- NewFATAddress,
- OldFATAddress: ^intArray;
-
- RootDir: DirectoryPointer;
-
- {---------------------------------- miscellaneous vars -----------------------}
-
- hour,
- min,
- sec,
- frac: INTEGER;
- time: REAL;
-
- movedFieldX,
- movedFieldY: INTEGER;
-
- Instr: CHAR;
- AlreadyWritten: BOOLEAN;
- TmpStr: STRING[2];
- NrStr,
- S40: Str40;
- Legals: STRING[3];
- Parms: Line;
-
- {-----------------------------------------------------------------------------}
- {$I REFORMAT.IN1} {Nijmegen .. word arithmetic }
- {$I REFORMAT.IN2} {Toad Hall.. InLine code FOR Int25 AND Int26 }
- {$I REFORMAT.IN3} {Toad Hall.. fast screen framer, FRAMER.INC }
- {$I REFORMAT.IN4} {Toad Hall.. better screen writing AND clearing, WRITEF.INC}
- {-----------------------------------------------------------------------------}
-
- {----------------------- general screen I/O routines -------------------------}
-
- PROCEDURE Beep;
- BEGIN
- WRITE(CHR(7));
- END; { of Beep }
-
- PROCEDURE WriteLog(Text: Line);
- BEGIN
- WriteF(LOGFIELDX, LOGFIELDY, HiSpace);
- WriteF(LOGFIELDX, LOGFIELDY, Text);
- END; { of WriteLog }
-
- PROCEDURE WriteWarning(Text: Line);
- BEGIN
- WriteF(WARNINGFIELDX, WARNINGFIELDY, HiSpace);
- WriteF(WARNINGFIELDX, WARNINGFIELDY, Text);
- END; { of WriteWarning }
-
- PROCEDURE WriteError(Text: Line);
- BEGIN
- WriteF(ERRORFIELDX, ERRORFIELDY, HiSpace);
- WriteF(ERRORFIELDX, ERRORFIELDY, Text);
- END; { of WriteError }
-
- PROCEDURE WriteDisaster(Text: Line);
- BEGIN
- WriteF(DISASTERFIELDX, DISASTERFIELDY, HiSpace);
- WriteF(DISASTERFIELDX, DISASTERFIELDY, Text);
- END; { of WriteDisaster }
-
- PROCEDURE BlankFields;
- BEGIN
- WriteError(' ');
- WriteWarning(' ');
- WriteDisaster(' ');
- IF Instr = 'I' THEN Register.flags := 0;
- END; { of BlankFields }
-
- PROCEDURE GetInput(Prompt: Str40; VAR Instr: CHAR);
- BEGIN
- WriteF(INPUTFIELDX, INPUTFIELDY, HiSpace); { really only needs 1 }
- WriteF(INPUTFIELDX, INPUTFIELDY, Prompt + ': ');
- Beep;
- REPEAT UNTIL KeyPressed;
- READ(Kbd, Instr);
- Instr := UpCase(Instr);
- WRITE(Instr);
- END; { of GetInput }
-
- PROCEDURE Exeunt(Prompt: Str40); { we do this a lot }
- BEGIN
- GetInput(Prompt, Instr);
- Height := 25;
- WriteF(1, 24, HiSpace); { clear bottom line and leave screen
- for user to contemplate }
- HALT;
- END; { of Exeunt }
-
- {---------------------------- timer control routines -------------------------}
-
- PROCEDURE StartTimer;
- {
- We want to let the user know how long REFORMAT took to do the job.
- }
- BEGIN
- (* In Turbo:
- with Register do begin
- ah := $2C;
- msdos(Register);
- hour := hi(cx);
- min := lo(cx);
- sec := hi(dx);
- frac := lo(dx);
- end;
- *)
- {Toad Hall note: tighter, quicker inline}
- InLine(
- $B4/$2C { mov ah,$2C}
- /$CD/$21 { int $21}
- /$31/$C0 { xor ax,ax ;clear msb}
- /$86/$E8 { xchg al,ch ;the hour}
- /$A3/>HOUR { mov [>hour],ax}
- /$86/$C8 { xchg al,cl ;the minute}
- /$A3/>MIN { mov [>min],ax}
- /$86/$F0 { xchg al,dh ;the second}
- /$A3/>SEC { mov [>sec],ax}
- /$86/$D0 { xchg al,dl ;the fraction}
- /$A3/>FRAC { mov [>frac],ax}
- );
- END; { of StartTimer }
-
- PROCEDURE StopTimer;
- {
- We want to let the user know how long REFORMAT took to do the job.
- }
- BEGIN
- (* In Turbo:
- with Register do begin
- ah := $2C;
- msdos(Register);
- frac := lo(dx) - frac;
- if frac < 0
- then begin
- frac := frac + 100;
- sec := succ(sec);
- end;
-
- sec := hi(dx) - sec;
- if sec < 0
- then begin
- sec := sec + 60;
- min := succ(min);
- end
- else if sec >= 60
- then begin
- sec := sec - 60;
- min := pred(min);
- end;
-
- min := lo(cx) - min;
- if min < 0
- then begin
- min := min + 60;
- hour := succ(hour);
- end
- else if min >= 60
- then begin
- min := min - 60;
- hour := pred(hour);
- end;
- hour := hi(cx) - hour;
- end;
- *)
- {Toad Hall Note: Tighter, faster inline. You won't BELIEVE
- what a kludge Turbo makes of the above routine.
- }
- InLine(
- $B4/$2C { mov ah,$2C}
- /$CD/$21 { int $21}
- /$BB/>FRAC { mov bx,>frac ;fraction offset}
- /$BE/>SEC { mov si,>sec ;seconds offset}
- /$31/$C0 { xor ax,ax ;clear msb}
- /$86/$D0 { xchg al,dl ;get fraction}
- /$2B/$07 { sub ax,[bx] ;frac = lo(dx)-frac}
- /$73/$05 { jnc S1 ;no carry, so not <0}
- /$05/$64/$00 { add ax,100 ;<0, adjust}
- /$FF/$04 { inc word [si] ;bump seconds}
- {S1:}
- /$89/$07 { mov [bx],ax ;save fraction}
- /$BB/>MIN { mov bx,>min ;get Minute offset}
- /$31/$C0 { xor ax,ax ;clear msb}
- /$BF/$3C/$00 { mov di,60 ;constant}
- /$86/$F0 { xchg al,dh ;get seconds}
- /$2B/$04 { sub ax,[si] ;sec = hi(dx)-sec}
- /$73/$06 { jnc S2 ;not <0}
- /$01/$F8 { add ax,di ;<0, adjust}
- /$FF/$07 { inc word [bx] ;min=min+1}
- /$EB/$08 { jmp short S3}
- {S2:}
- /$39/$F8 { cmp ax,di ;>=60?}
- /$72/$04 { jb S3 ; nope}
- /$29/$F8 { sub ax,di ; sec=sec-60}
- /$FF/$0F { dec word [bx] ;min=min-1}
- {S3:}
- /$89/$04 { mov [si],ax ;save seconds}
- /$BE/>HOUR { mov si,>hour ;hour offset}
- /$31/$C0 { xor ax,ax ;clear msb}
- /$86/$C8 { xchg al,cl ;get minutes}
- /$2B/$07 { sub ax,[bx] ;min=lo(cx)-min}
- /$73/$06 { jnc S4 ; not below 0}
- /$01/$F8 { add ax,di ;min=min+60}
- /$FF/$04 { inc word [si] ;hour=hour+1}
- /$EB/$08 { jmp short S5}
- {S4:}
- /$39/$F8 { cmp ax,di ;>=60?}
- /$72/$04 { jb S5 ; nope}
- /$29/$F8 { sub ax,di ;min=min-60}
- /$FF/$0C { dec word [si] ;hour=hour-1}
- {S5:}
- /$89/$07 { mov [bx],ax ;save minutes}
- /$31/$C0 { xor ax,ax ;clear msb}
- /$86/$E8 { xchg al,ch ;get hour}
- /$2B/$04 { sub ax,[si] ;hour=hi(cx)-hour}
- /$89/$04 { mov [si],ax}
- );
- END; { of StopTimer }
-
- {$I REFORMAT.IN5} {Nijmegen .. disk, FAT, directory, misc. routines }
-