{
+----------------------------------------------+
| Форматирование дорожки нестандартными секто- |
| рами с помощью прерывания  $13. Используется |
| дисковод 5 1/4 дюймов в режиме 360 Кбайт.    |
|   Эта программа готовит дискету для работы   |
|             с модулем F_Prot.                |
+----------------------------------------------+}
Program Diskett;
Uses DOS,F_disk;
const
  TRK = 40; 		        {Номер нестандартной дорожки}
  DSK = 0;  		        {Номер диска}
  SIZ = 1;  		        {Код размера сектора}
type
  PDBT_Type =^DBT_Type;  	{Указатель на ТПД}
  {Таблица параметров дискеты}
  DBT_Type = record
    Reserv1 : array [0..2] of Byte;
    SizeCode: Byte; 	        {Код размера сектора}
    LastSect: Byte; 	        {Количество секторов на дорожке}
    Reserv2 : array [5..7] of Byte;
    FillChar: Char; 	{Символ-заполнитель форматирования}
    Reserv3 : Word
  end;
  {Элемент буфера форматирования}
  F_Buf = record
    Track: Byte;     	{Номер дорожки}
    Head : Byte;     	{Номер головки}
    Sect : Byte;     	{Номер сектора}
    Size : Byte      	{Код размера}
  end;
var
  Old: PDBT_Type;    	{Указатель на исходную ТПД}
{-------------------}
PROCEDURE Intr13(var R: registers; S: String);
 {Обращается к прерыванию 13 и анализирует ошибку
 (CF=1 - признак ошибки). Если ошибка обнаружена,
  печатает строку S и завершает работу программы}
BEGIN
  Intr($13,R);
  if R.Flags and FCarry<>0 then
  if R.ah <> 6 then        {Игнорируем ошибку от смены типа дискеты}
    begin
      WriteLn(S);
      SetIntVec($1E,Old);  {Восстанавливаем старую ТПД}
      Halt
    end
END;  {Intr13}
{------------------}
FUNCTION AccessTime(DSK,TRK: Byte): Real;
  {Измеряет время доступа к дорожке и возвращает его
   	своим результатом(в секундах)}

var
  E: array [1..9*512] of Byte;
  t,k: LongInt;
  R: registers;
BEGIN
   t := MemL[0:$046C];
   while t=MemL[0:$046C] do;
   for k := 1 to 10 do with R do
     begin
       ah := 2;
       al := 9;
       ch := TRK;
       cl := 1;
       dh := 0;
       dl := DSK;
       es := seg(E);
       bx := ofs(E);
       Intr13(R,'Error')
     end;
   AccessTime := (MemL[0:$046C]-t-1)*0.055
END;
{------------------}
var
  B: array [1..9] of F_Buf;   	        {Буфер для форматирования}
  k,N: Integer;           		{Счетчик цикла}
  R: registers;          		{Регистры}
  DBT: PDBT_Type;        		{Указатель на новую ТПД}
  C,D: array [1..1024] of Byte; 	{Буферы чтения/записи}
  Size: Word;            		{Длина сектора}
  Info: TDisk;
BEGIN  {Главная программа}
{Проверяем доступ к диску и настраиваем драйвер}
  GetDiskInfo(DSK,Info);
  if Disk_Error then
    begin
      WriteLn('Ошибка доступа к диску');
      Halt
    end;
{Получаем длину сектора в байтах}
  case SIZ of
    0: Size := 128;
    1: Size := 256;
    2: Size := 512;
    3: Size := 1024
  else
    WriteLn('Недопустимый код длины сектора')
  end;

{Корректируем таблицу параметров дискеты. Поскольку исходная ТПД может быть
в ПЗУ, делаем ее копию в ОЗУ и изменяем нужные элементы}
  Old := ptr(MemW[0:$1E*4+2],MemW[0:$1E*4]);
  New(DBT);
  DBT^:= Old^;        	{Получаем копию ТПД в ОЗУ}
  SetIntVec($1E,DBT); 	{Изменяем ссылку на ТПД}
  with DBT^ do
    begin
      SizeCode := SIZ;
      LastSect := 9;
      FillChar := '+'
    end;
  with R do
    begin
{Сбрасываем дисковод}
      ax := 0;
      dl := DSK;
      Intr13(R,'Ошибка доступа к диску');
{Готовим буфер форматирования с обратным
 фактором чередования секторов}
      for k := 1 to 9 do 	{Для каждого из 9 секторов:}
      with B[k] do
        begin
          Track := TRK; 	{указываем номер дорожки}
          Head  := 0;           {номер головки}
          Sect  := 10-k;        {номер сектора
                 	        (в обратной последовательности)}
          Size  := SIZ          {и код размера}
        end;
{Форматируем дорожку}
      ah :=$05;    	{Код операции форматирования}
      al :=9;      	{Создаем 9 секторов}
      ch := TRK;   	{на дорожке TRK}
      cl := 1;     	{начиная с сектора 1}
      dh := 0;     	{на поверхности 0}
      dl := DSK;   	{диска DSK}
      es := seg(B);	{ES:BX - адрес буфера}
      bx := ofs(B);
      Intr13(R,'Ошибка форматирования');
{Заполняем сектор случайными числами}
      Randomize;
      for k := 2 to 255 do
	C[k] := Random(256);
{Запрашиваем количество инсталляций на ЖД}
      Write('Кол-во установок на ЖД: ');
      ReadLn(C[200]);
      C[17] := 0;
{Считаем контрольную сумму}
      N := 0;
      for k := 2 to 255 do
	N := N+C[k];
      C[256] := N mod 256;
{Шифруем сектор}
      C[1] := Random(255)+1;
      for k := 2 to 256 do
	C[k] := C[k] xor C[1];
{Записываем сектор}
      ah := $03;    	{Код операции записи}
      al := 1;      	{Записать 1 сектор}
      ch := TRK;    	{На дорожке TRK}
      cl := 1;      	{Начиная с сектора 1}
      dh := 0;      	{На поверхности 0}
      dl := DSK;    	{Диск DSK}
      es := seg(C); 	{Адрес буфера C для записи}
      bx := ofs(C);
      Intr13(R,'Ошибка записи');
{Читаем сектор}
     ah := $02;     	{Код операции чтения}
     al := 1;
     ch := TRK;
     cl := 1;
     dh := 0;
     dl := DSK;
     es := seg(D);  	{Адрес буфера D для чтения}
     bx := ofs(D);
     Intr13(R,'Ошибка чтения')
    end;
{Проверяем совпадение}
   for k := 1 to Size do
     if c[k]<>d[k] then
       begin
         WriteLn('Несовпадение данных');
         SetIntVec($1E,Old);
         Halt
       end;
   WriteLn('Создана и проверена ',TRK+1,
     		'-я дорожка с секторами по ',Size,' байт');
{Измеряем время доступа к новой дорожке}
   Write('Время доступа к скрытой дорожке: ');
   WriteLn(AccessTime(DSK,TRK):6:2,' c');
{Измеряем время доступа к стандартной дорожке}
   DBT^.SizeCode := 2; {Указываем стандартную 					длину сектора в ТПД}
   Write('Доступ к обычной дорожке: ');
   WriteLn(AccessTime(DSK,20):6:2,' c');
{Восстанавливаем старую ТПД}
   SetIntVec($1E,Old)
END.
