program MS_DOS_Reformatter; (* MSFORM.PAS vom 3.9.87, Tilmann Reh *) const bufgr = 2047; (* max. Puffer fuer Boot/FAT/Dir *) titel = ^M^J'MS-DOS-Reformatter V1.2 vom 3.9.87'; var buffer : array[0..bufgr] of byte; psize,secptrk,lsecptrk,heads, tracks,sektoren,reservsec, eintraege,fatsecs,ident : integer; secpcl,fatzahl,medium, msdrive,logdrive,i : byte; eingabe : string[14]; (*********************************************************** ** U T I L I T I E S ** ***********************************************************) (* Direkter BIOS-Aufruf ueber BDOS-Funktion 50 *) function UBIOS(fn,pa,pbc,pde,phl:integer):integer; var biospb : record func,a : byte; bc,de,hl : integer; end; result : integer; begin with biospb do begin func:=fn; a:=pa; bc:=pbc; de:=pde; hl:=phl; end; result:=0; case fn of 2,3,7,13..15,17..19,24 : result:=BDOS(50,addr(biospb)); 9,16,20,22,25 : result:=BDOSHL(50,addr(biospb)); else BDOS(50,addr(biospb)); end; ubios:=result; end; (* RWSECTOR liest/schreibt phys. Sektor auf MS-Drive *) (* Absolute Sektorangabe, Sektoren ab 1 gezaehlt !! *) procedure rwsector(abssec:integer; wflag:boolean; buf:integer); var trk,sec,k : integer; dph : ^integer absolute k; begin abssec:=pred(abssec); (* zaehlt ab 0 *) trk:=abssec div lsecptrk; sec:=abssec mod lsecptrk; k:=ubios(9,0,msdrive,1,0); (* SELDSK *) sec:=ubios(16,0,sec,dph^,0); (* SECTRN *) k:=ubios(23,0,1,0,0); (* MULTIO *) k:=ubios(10,0,trk,0,0); (* SETTRK *) k:=ubios(11,0,sec,0,0); (* SETSEC *) k:=ubios(12,0,buf,0,0); (* SETDMA *) k:=ubios(28,1,0,0,0); (* SETBNK *) if wflag then k:=ubios(14,0,0,0,0) (* WRITE *) else k:=ubios(13,0,0,0,0); (* READ *) end; (* MSLOGIN schaltet BDOS und BIOS 'kalt' auf MS-Drive um. *) (* Physikalische Sektorgroesse (CP/M) wird gelesen. *) procedure mslogin; type dpb = record spt : integer; bsh,blm,exm : byte; dsm,drm : integer; al0,al1 : byte; cks,off : integer; psh,phm : byte; end; var k : integer; ptr : ^dpb absolute k; begin k:=ubios(9,0,msdrive,0,0); (* SELDSK kalt *) bdos(14,msdrive); (* Select Drive *) k:=bdoshl(31); (* Get DPB *) psize:=128 shl ptr^.psh; (* Byte/Sektor *) end; (* RELOG schaltet 'warm' auf angegebenes Drive um. *) procedure relog(drive:byte); var k : integer; begin k:=ubios(9,0,drive,1,0); (* SELDSK *) bdos(14,drive); (* Select Drive *) end; (* FAT's auf Diskette schreiben *) procedure writefat; var i,j,sec : integer; begin for i:=1 to fatzahl do begin sec:=reservsec+pred(i)*fatsecs; for j:=1 to fatsecs do rwsector(sec+j,true,addr(buffer[psize*pred(j)])); end; end; (* Verwaltungsdaten fuer IBM-Disketten berechnen *) procedure calculate_ibm; begin reservsec:=1; fatzahl:=2; tracks:=40; case ident of 160 : begin heads:=1; secpcl:=1; secptrk:=8; fatsecs:=1; eintraege:=64; end; 180 : begin heads:=1; secpcl:=1; secptrk:=9; fatsecs:=2; eintraege:=64; end; 320 : begin heads:=2; secpcl:=2; secptrk:=8; fatsecs:=1; eintraege:=112; end; 360 : begin heads:=2; secpcl:=2; secptrk:=9; fatsecs:=2; eintraege:=112; end; end; end; (* Format-Daten manuell eingeben *) procedure input_data; begin write('Seitenzahl : '); readln(heads); write('Spurzahl : '); readln(tracks); write('Sektoren/Spur : '); readln(secptrk); write('Boot-Sektoren : '); readln(reservsec); write('Anzahl FATs : '); readln(fatzahl); write('Sektoren/FAT : '); readln(fatsecs); write('DIR-Eintr{ge : '); readln(eintraege); write('Sektoren/Cluster : '); readln(secpcl); end; (* RE-FORMATTING : Boot-Record/FAT's/Directory schreiben *) procedure reformat; const oem : array[1..8] of char = 'REH V1.2'; var i,s : integer; begin sektoren:=tracks*secptrk*heads; lsecptrk:=secptrk*heads; medium:=$7C+byte(heads=2) +byte(secptrk=8) shl 1 +byte(tracks<>80) shl 7; rwsector(1,false,addr(buffer)); (* Boot-Record lesen *) fillchar(buffer,32,0); move(oem,buffer[3],8); buffer[$0B]:=lo(psize); buffer[$0C]:=hi(psize); buffer[$0D]:=secpcl; buffer[$0E]:=reservsec; buffer[$0F]:=0; buffer[$10]:=fatzahl; buffer[$11]:=lo(eintraege); buffer[$12]:=hi(eintraege); buffer[$13]:=lo(sektoren); buffer[$14]:=hi(sektoren); buffer[$15]:=medium; buffer[$16]:=fatsecs; buffer[$17]:=0; buffer[$18]:=secptrk; buffer[$19]:=0; buffer[$1A]:=heads; buffer[$1B]:=0; rwsector(1,true,addr(buffer)); (* Boot-Record *) fillchar(buffer,succ(bufgr),0); buffer[0]:=medium; buffer[1]:=$FF; buffer[2]:=$FF; writefat; fillchar(buffer,1024,$F6); (* FAT's *) for i:=0 to 32 do buffer[i shl 5]:=0; s:=reservsec+fatzahl*fatsecs; for i:=succ(s) to s+eintraege shl 5 div psize do rwsector(i,true,addr(buffer)); (* Directory *) end; (*********************************************************** ** H A U P T P R O G R A M M ** ***********************************************************) begin logdrive:=BDOS(25); writeln(titel); repeat write(^M^J'Laufwerk mit MS-DOS-Diskette : '); readln(eingabe); msdrive:=ord(upcase(eingabe[1]))-$41; until msdrive in [0..3]; write('Hinweis: phys. Disk-Parameter m}ssen korrekt ', 'gesetzt sein !'^M^J^J); repeat mslogin; ident:=0; if psize=512 then begin write('Kapazit{t in KB (nur IBM) : '); readln(ident); end; case ident of 160,180,320,360 : calculate_ibm; else input_data; end; repeat reformat; write('Weitere Diskette gleiche Daten (J/N) ? '); readln(eingabe); until (length(eingabe)=0) or (upcase(eingabe[1])='N'); write('Weitere Diskette andere Daten (J/N) ? '); readln(eingabe); until (length(eingabe)=0) or (upcase(eingabe[1])='N'); relog(logdrive); end.