Tracks:=(TotSecs+pred(TrackSiz)) div (TrackSiz*Heads);
ClusSize:=BPB.ClustSiz;
FATLock:=BPB.ResSecs;
FATCnt:=BPB.FatCnt;
FATSize:=BPB.FatSize;
RootLock:=FATLock+FATCnt*FATSize;
RootSize:=BPB.RootSiz;
DataLock:=RootLock+(RootSize*SizeOf(Dir_Type)) div SectSize;
MaxClus:=(TotSecs-DataLock) div ClusSize+2;
FAT16:=(MaxClus>4086) and (TotSecs>20790)
end
end; {GetDiskinfo}
{----------------}
function GetDiskNumber(c:Char):Byte;
{Преобразует имя диска A...Z в номер 0...26.
Если указано недействительное имя, возвращает 255}
var
DrvNumber:Byte;
begin
if UpCase(c) in ['A'..'Z'] then
DrvNumber:=ord(UpCase(c))-ord('A')
else
DrvNumber:=255;
if DrvNumber>GetMaxDrv then
GetDiskNumber:=DrvNumber;
end; {GetDiskNumber}
{---------------------}
function GetFATItem(Disk:Byte;Item:Word):Word;
{Возвращает содержимое указанного элемента FAT}
DI:TDisk;
k,j,n:Integer;
Fat:record
case Byte of
0: (w:array[0..255] of Word);
1: (b:array[0..512*3-1] of Byte);
end;
GetDiskInfo(Disk,DI);
if not Disk_Error then with DI do
if (Item>MaxClus) or (Item<2) then
Item:=$FFFF {Задан ошибочный номер кластера}
if FAT16 then
k:=Item div 256; {Нужный сектор FAT}
j:=Item mod 256; {Смещение в секторе}
n:=1 {Количество читаемых секторов}
k:=Item div 1024; {Нужная тройка секторов FAT}
j:=(3*Item) shr 1-k*1536; {Смещение в секторе}
n:=3 {Количество читаемых секторов}
{Читаем 1 или 3 сектора FAT}
ReadSector(Disk,FATLock+k*n,n,Fat);
if not Disk_Error then
Item:=Fat.w[j]
n:=Item; {Старое значение Item для проверки четности}
Item:=Fat.b[j]+Fat.b[j+1] shl 8;
if odd(n) then
Item:=Item shr 4
Item:=Item and $FFF;
if Item>$FF6 then
Item:=$F000+Item
GetFatItem:=Item
end; {GetFATItem}
{------------------}
procedure GetIOCTLInfo(Disk:Byte;var IO:IOCTL_Type);
{Получаем информацию об устройстве согласно общему вызову IOCTL}
with Reg do
ah:=$44; {Функция 44}
al:=$0D; {Общий вызов IOCTL}
cl:=$60; {Дать параметры устройства}
ch:=$8; {Устройство - диск}
bl:=Disk+1; {Диск 1=А,...}
bh:=0;
ds:=seg(IO);
dx:=ofs(IO);
Intr($21,Reg);
Output
end; {GetIOCTLInfo}
{-------------------}
procedure GetListDisk(var List:PListDisk);
{Формирует список дисковых описателей}
Disk:Byte;
P,PP:PListDisk;
Disk:=2; {Начать с диска С:}
List:=NIL;
repeat
New(P);
if List=NIL then
List:=P
PP^.NextDisk:=P;
with P^ do
DiskInfo:=DI;
NextDisk:=NIL;
inc(Disk);
PP:=P
until Disk_Error;
Disk_Error:=False
end; {GetListDisk}
procedure GetMasterBoot(var Buf);
{Возвращает в переменной Buf главный загрузочный сектор}
GetAbsSector($80,0,1,Buf)
end; {GetMasterBoot}
{--------------------}
function GetMaxDrv:Byte;
{Возвращает количество логических дисков}
const
Max:Byte=0;
if Max=0 then with Reg do
ah:=$19;
MSDOS(Reg);
ah:=$0E;
dl:=al;
Max:=al
GetMaxDrv:=Max
end; {GetMaxDrv}
function GetSector(Disk:Byte;Cluster:Word):Word;
{Преобразуем номер кластера в номер сектора}
Disk_Error:=(Cluster>MaxClus) or (Cluster<2);
GetSector:=(Cluster-2)*ClusSize+DataLock
if Disk_Error then
GetSector:=$FFFF
end; {GetSector}
{----------------------}
function PackCylSec(Cyl,Sec:Word):Word;
{Упаковывает цилиндр и сектор в одно слово для прерывания $13}
PackCylSec:=Sec+(Cyl and $300) shr 2+(Cyl shl 8)
end; {PackCylSec}
procedure ReadWriteSector(Disk:Byte;
Sec:LongInt;NSec:Word; var Buf; Op:Byte);
{Читает или записывает сектор (секторы):
Ор = 0 - читать; 1 - записать (малый диск)
= 2 - читать; 3 - записать (большой диск)}
type
TBuf0=record
StartSec:LongInt;
Secs:Word;
AdrBuf:Pointer
Buf0:TBuf0;
S:Word;
O:Word;
if Op>1 then with Buf0 do
{Готовим ссылочную структуру для большого диска}
AdrBuf:=Ptr(Seg(Buf),Ofs(Buf));
StartSec:=Sec;
Secs:=NSec;
S:=Seg(Buf0);
O:=Ofs(Buf0);
asm
mov CX,$FFFF
mov AL,Op
shr AX,1
mov AL,Disk
push DS
push BP
mov BX,O
mov DS,S
jc @1
int 25H
jmp @2
@1: int 26H
@2: pop DX
pop BP
pop DS
mov BX,1
jc @3
mov Bx,0
xor AX,AX
@3: mov Disk_Error,BL
mov Disk_Status,AX
else {Обращение к диску малой емкости}
mov DX,Word Ptr Sec {DX:=Sec}
mov CX,NSec {CX:=NSec}
push DS {Сохраняем DS - он будет испорчен}
push BP {Сохраняем BP}
lds BX,Buf {DS:BX - адрес буфера}
mov AL,Op {AL:=Op}
shr AX,1 {Переносим младший бит Oр в CF}
mov AL,Disk {AL:=Disk}
jc @Write {Перейти, если младший бит Ор<>0}
int 25H {Читаем данные}
jmp @Go {Обойти запись}
@WRITE:
int 26H {Записываем данные}
@GO:
pop DX {Извлекаем флаги из стека}
pop BP {Восстанавливаем BP}
pop DS {Восстанавливаем DS}
mov BX,1 {BX:=True}
jc @Exit {Перейти, если была ошибка}
mov BX,0 {BX:=False}
xor AX,AX {Обнуляем код ошибки}
@EXIT:
mov Disk_Error,BL {Флаг ошибки взять из BX}
mov Disk_Status,AX {Код ошибки взять из AX}
end; {ReadWriteSector}
{------------------------}
procedure ReadSector(Disk:Byte;Sec:LongInt;NSec:Word;var Buf);
{Читает сектор(секторы) на указанном диске}
if DI.TotSecs>$FFFF then {Диск большой емкости?}
ReadWriteSector(Disk,Sec,Nsec,Buf,2) {-Да: операция 2}
ReadWriteSector(Disk,Sec,Nsec,Buf,0) {-Нет: операция 0}
end; {ReadSector}
procedure SetAbsSector(Disk,Head:Byte;CSec:Word;var Buf);
{Записывает абсолютный дисковый сектор с помощью прерывания $13}
ah:=3; {Операция записи}
dl:=Disk; {Номер привода}
dh:=Head; {Номер головки}
Страницы: 1, 2, 3, 4, 5, 6, 7, 8, 9