unit IS18WG93;{эмулятор БИС 1818 ВГ 93}
interface
uses crt,dos,specproc;
function inDatIS18WG93(portNumber:byte):byte;
procedure outDatIS18WG93(portNumber,datas:byte);
procedure taktIS18WG93;
procedure InitDrivers;
procedure DoneDrivers;
var ClockIS18WG93:longint;
const maxClockIS18WG93=4;
implementation
const
maxSIDE=2;{сторон диска}
maxTR=86;{кол-во дорожек}
maxSekt=16;{кол-во секторов}
maxSektSize=512;{кол-во данных в секторе}
maxTRSize=maxSekt*maxSektSize;{данных на дорожке}
maxTaktsForShift=10;{число тактов для одного проворота диска}
(****************************************************************************)
type tBuffDat=array[0..maxTRSize-1]of byte;
type oMG=object{привод дисковвода}
emulDisk:file;
buffer:record
 change:boolean;{нужна ли запись на винт}
 buffTR:byte;{кешированая дорожка}
 buffDat:^tBuffDat;{данные}
 end;
_IPbool,{поворот диска обнаружил IP}
readyIO,{готовность обмена с диском}
insertDisk:boolean;{диск вставлен}
DIRC,{направление шага 1=к центру (вперед)}
realPosMG,{дорожка реального положения МГ}
HLT,{готовность головки 1-ready}
TaktsForShift,{текущий такт для сдвига}
_DDEN,{вход - плотность записи 0=двойная}
SIDEup,{сторона диска 0-верхняя}
TR43,{выход rDor>43}
WPRT,{защита записи}
DAM,{байт адресной метки данных}
WSTB{строб записи}
:byte;
SektSize,{длина сектора с НГМД}
CRC{полиномиальный КК}
:word;
realPosDisk:word;{реальное положение диска под головкой}
function _IP:byte;{выравнивание по началу дорожки =1 - приходил импульс}
procedure getBuffer(_TRnum:byte);{обновление буфера _TRnum-ной дорожкой}
procedure CheckChange;{обновление данных на диске}
function BeginTrack(_tr:byte):longint;{дрес начала дорожки в файле}
procedure ProworotDiska;{поддержка прокрутки диска}
procedure InitDisk(fName:string);{инициализация виртуального диска}
procedure DoneDisk;{закрытие}
procedure HLD(mode:byte);{загрузка головки}
procedure STEP;{перемещение МГ на шаг}
function _TR00:byte;{головка в исходном состоянии}
function IAM:boolean;{головка над ИАМ}
function getDAM:boolean;{-/- над ДАМ ->DAM}
function GetByte:byte;{считывание байта над которым головка}
procedure WriteByte(_dat:byte);{запись байта -/-}
function CRCErr:boolean;{проверка CRC}
procedure BeginCRC;{генерировать CRC}
 end;
(****************************************************************************)
procedure oMg.ProworotDiska;
begin
if not(insertDisk)then exit;
inc(TaktsForShift);
if TaktsForShift<maxTaktsForShift then exit;
TaktsForShift:=0;
readyIO:=true;
inc(realPosDisk);
if realPosDisk=maxTRSize then begin _IPbool:=true;realPosDisk:=0;end {else _IPbool:=false;}
end;
(****************************************************************************)
function oMg._IP:byte;
begin
if _IPbool=true then begin _IP:=1;_IPBool:=false;end else _IP:=0;
end;
(****************************************************************************)
procedure oMg.InitDisk(fName:string);
var _w:word;
begin
new(buffer.buffDat);
for _w:=0 to maxTRSize-1 do buffer.buffDat^[_w]:=0;
buffer.change:=false;
buffer.buffTR:=$FF;
WPRT:=0;
insertDisk:=true;
{создание диска}
assign(emulDisk,fName);
{$I-}
reset(emulDisk,1);
{$I+}
if ioResult<>0 then
 begin
 rewrite(emulDisk,1);
 for _w:=1 to 344 do blockWrite(emulDisk,buffer.buffDat^,$1000);
 seek(emulDisk,maxSIDE*maxTR*maxSekt*maxSektSize);
 truncate(emulDisk);
 seek(emulDisk,0);
 end;
end;
(****************************************************************************)
function oMG.BeginTrack(_tr:byte):longint;
var _l1,_l2:longint;
begin
_l1:=_tr;
{_l1:=_l1*2;
_l2:=SIDEup;
_l1:=_l1+_l2;}
_l2:=maxTRSize;
_l1:=_l1*_l2;
BeginTrack:=_l1;
{:=_tr*maxTRSize}
end;
(****************************************************************************)
procedure oMG.CheckChange;
begin
if buffer.change then
 begin
  seek(emulDisk,BeginTrack(buffer.buffTR));
  blockWrite(emulDisk,buffer.buffDat^,maxTRSize);
  buffer.change:=false;
 end;
end;
(****************************************************************************)
procedure oMG.DoneDisk;
begin
CheckChange;
dispose(buffer.buffDat);
insertDisk:=false;
close(emulDisk);
end;
(****************************************************************************)
procedure oMG.HLD(mode:byte);
begin HLT:=mode;end;
(****************************************************************************)
procedure oMG.STEP;
begin
if DIRC=1 then
 begin
  if realPosMG<maxTR then inc(realPosMG);
 end else
 begin
  if realPosMG>0 then dec(realPosMG);
 end;
end;
(****************************************************************************)
function oMG._TR00:byte;
begin if realPosMG=0 then _TR00:=0 else _TR00:=1;end;
(****************************************************************************)
procedure oMG.getBuffer(_TRnum:byte);
begin
CheckChange;
if _TRnum>2*(maxTR-1) then
begin
_TRnum:=2*(maxTR-1);
end;
seek(emulDisk,BeginTrack(_TRnum));
blockRead(emulDisk,buffer.buffDat^,maxTRSize);
buffer.buffTR:=_TRnum;
end;
(****************************************************************************)
function oMG.GetByte:byte;
begin
readyIO:=false;
if (2*realPosMG+SIDEup)<>buffer.buffTR then getBuffer(2*realPosMG+SIDEup);
getByte:=buffer.buffDat^[realPosDisk];
end;
(****************************************************************************)
procedure oMG.WriteByte(_dat:byte);
begin
{if WSTB=0 then exit;}
readyIO:=false;
if (2*realPosMG+SIDEup)<>buffer.buffTR then getBuffer(2*realPosMG+SIDEup);
buffer.buffDat^[realPosDisk]:=_dat;
buffer.change:=true;
end;
(****************************************************************************)
function oMG.CRCErr:boolean;
begin CRCErr:=false; end;
(****************************************************************************)
procedure oMg.BeginCRC;{генерировать CRC}
begin CRC:=0;end;
(****************************************************************************)
function oMg.IAM:boolean;
var _w:word;
begin
if GetByte=$FE then IAM:=true else
 begin
for _w:=realPosDisk to maxTRSize-1 do
 if buffer.buffDat^[_w]=$FE then begin IAM:=true;realPosDisk:=_w;exit;end;
realPosDisk:=_w;
IAM:=false;
 end;
end;
(****************************************************************************)
function oMg.getDAM:boolean;
var _w:word;
bb:byte;
begin
bb:=GetByte;
if (bb=$FB)or(bb=$F8) then getDAM:=true else
 begin
for _w:=realPosDisk to maxTRSize-1 do
 begin
 bb:=buffer.buffDat^[_w];
 if (bb=$FB)or(bb=$F8)then begin DAM:=bb;getDAM:=true;realPosDisk:=_w;exit;end;
 end;
realPosDisk:=_w;
getDAM:=false;
 end;
end;
(****************************************************************************)
(****************************************************************************)
(****************************************************************************)
var
MG:array[0..3]of oMG;{блок дисковводов}
{регистры контроллера:}
rD,{данных}
rSekt,{сектора}
rDor,{дорожки}
rKom,{комманд}
rSost,{состояния}
rSdw,{сдвиговый}
stMK,{адрес выполняемой микрокоманды}
{данные с ножек:}
DRQ,{запрос данных(=1 - готов принять/передать rD) - выход с открытым стоком}
INTRQ,{запрос прерывания(=1 - команда выполнена) - выход с открытым стоком}
DRIVE,{номер дисковода (0-3)}
{дополнительные данные}
tz,{временная задержка на выполнение Мк}
stIP{счет IP}
:byte;
(****************************************************************************)
procedure _CLR;
begin
outDatIS18WG93($1F,$03);
outDatIS18WG93($5F,$01);
outDatIS18WG93($3F,$00);
end;
(****************************************************************************)
procedure setQ;begin setBit(0,rSost)end;procedure resQ;begin resBit(0,rSost)end;
procedure setW;begin setBit(2,rSost)end;procedure resW;begin resBit(2,rSost)end;
procedure setC;begin setBit(3,rSost)end;procedure resC;begin resBit(3,rSost)end;
procedure setF;begin setBit(4,rSost)end;procedure resF;begin resBit(4,rSost)end;
procedure setN;begin setBit(4,rSost)end;procedure resN;begin resBit(4,rSost)end;
procedure setE;begin setBit(5,rSost)end;procedure resE;begin resBit(5,rSost)end;
procedure setA;begin setBit(5,rSost)end;procedure resA;begin resBit(5,rSost)end;
procedure setP;begin setBit(6,rSost)end;procedure resP;begin resBit(6,rSost)end;
(****************************************************************************)
function inDatIS18WG93(portNumber:byte):byte;
var _dat:byte;
begin
_dat:=0;
case portNumber of
$1F:begin _dat:=rSost;INTRQ:=0;end;
$3F:_dat:=rDor;
$5F:_dat:=rSekt;
$7F:begin _dat:=rD;DRQ:=0;end;
$FF:
  begin
   if INTRQ=1 then setBit(7,_dat);
   if DRQ=1 then setBit(6,_dat);
  end;
 end;
inDatIS18WG93:=_dat;
end;
(****************************************************************************)
procedure outDatIS18WG93(portNumber,datas:byte);
begin
case portNumber of
$1F:begin rKom:=datas;INTRQ:=0;stMK:=1;end;
$3F:rDor:=datas;
$5F:rSekt:=datas;
$7F:begin rD:=datas;DRQ:=0;end;
$FF:
 begin
 if setsBit(6,datas) then MG[DRIVE]._DDEN:=1 else MG[DRIVE]._DDEN:=0;
 if setsBit(4,datas) then MG[DRIVE].SIDEup:=0 else MG[DRIVE].SIDEup:=1;
 if setsBit(3,datas) then MG[DRIVE].HLT:=1 else MG[DRIVE].HLT:=0;
 if not(setsBit(2,datas)) then _CLR;
 DRIVE:=datas and $03;
 end;
end;
end;
(****************************************************************************)
procedure taktIS18WG93;
var tmpIP:byte;{IP на 2 захода}
begin
MG[DRIVE].ProworotDiska;
case rKom and $C0 of
$00..$40:{команды первого типа}
 begin
tmpIP:=MG[DRIVE]._IP;
   case stMk of{рис.16}
   $FF:asm nop end;
    1:stMk:=2;
    2:begin stMk:=3;setQ;DRQ:=0;INTRQ:=0;resC;resF;end;
    3:if setsBit(3,rKom)then stMk:=5 else stMk:=4;
    4:begin stMk:=6;MG[DRIVE].HLD(0);end;
    5:begin stMk:=6;MG[DRIVE].HLD(1);end;
    6:if (rKom and $60)=$40 then{шаг вперед}stMk:=7 else stMk:=8;
    7:begin MG[DRIVE].DIRC:=1;stMk:=12;end;
    8:if (rKom and $60)=$60 then{шаг назад}stMk:=9 else stMk:=10;
    9:begin MG[DRIVE].DIRC:=0;stMk:=12;end;
   10:if (rKom and $60)=$20 then{шаг головки в том же направлении}stMk:=12 else stMk:=11;
   11:if (rKom and $F0)=$10 then{поиск}
    begin
    stMk:=15
    end else stMk:=13;
   12:if setsBit(4,rKom)then stMk:=20 else stMk:=23;
   13:begin{восстановление}stMk:=14;rDor:=$FF;end;
   14:begin stMk:=15;rKom:=0;end;
   15:begin stMk:=16;rSdw:=rD;end;
   16:if rDor=rSdw then stMk:=28 else stMk:=17;
   17:if rSdw>rDor then stMk:=19 else stMk:=18;
   18:begin stMk:=20; MG[DRIVE].DIRC:=0 end;
   19:begin stMk:=20; MG[DRIVE].DIRC:=1 end;
   20:if MG[DRIVE].DIRC=1 then stMk:=22 else stMk:=21;
   21:begin stMk:=23;dec(rDor)end;
   22:begin stMk:=23;inc(rDor)end;
   23:if (MG[DRIVE]._TR00=0)and(MG[DRIVE].DIRC=0)then stMk:=24 else stMk:=25;
   24:begin stMk:=28;rDor:=0;end;
   25:begin stMk:=26;MG[DRIVE].STEP;tz:=0;end;
   26:if tz=(rKom and $03)then stMk:=27 else inc(tz);
   27:if (rKom and $60)<>0 then stMk:=28 else stMk:=15;
   28:if setsBit(2,rKom)then stMk:=30 else stMk:=29;
   29:begin stMk:=$FF;INTRQ:=1;resQ;end;
   30:begin stMk:=31;tz:=0;MG[DRIVE].HLD(1); end;
   31:if tz=3 then stMk:=32 else inc(tz);
   32:begin stIP:=0;if MG[DRIVE].HLT=1 then stMk:=33;end;
   33:begin if tmpIP<>0{ожидание фронта IP} then
       begin inc(stIP);if stIP>9 then stMk:=34 else stMk:=35 end;end;
   34:begin stMk:=$FF;INTRQ:=1;resQ;setF end;
   35:if not(MG[DRIVE].IAM)then stMk:=33 else stMk:=36;
   36:begin if MG[DRIVE].readyIO then
       begin if rDor=MG[DRIVE].GetByte then stMk:=37 else stMk:=33;end;end;
   37:if MG[DRIVE].CRCErr then begin stMk:=33;setC;end else stMk:=38;
   38:begin stMk:=39; resC;end;
   39:begin stMk:=$FF;INTRQ:=1;resQ;end;
   end;
if tmpIP=1 then setBit(1,rSost) else resBit(1,rSost);
if MG[DRIVE]._TR00=0 then setBit(2,rSost) else resBit(2,rSost);
if MG[DRIVE].HLT=1 then setBit(5,rSost) else resBit(5,rSost);
 end;
$80:{команды второго типа}
 begin
   case stMk of{рис.17}
   $FF:asm nop end;
    1:begin stMk:=2;SetQ;DRQ:=0;INTRQ:=0;resE;resP;resN;resW;end;
    2:stMk:=3;{НГМД готов?}
    3:begin stMk:=4;MG[DRIVE].HLD(1);end;
    4:if (rKom and $04)<>0 {E=1}then begin tz:=0;stMk:=5;end else stMk:=6;
    5:if tz=3 then stMk:=6 else inc(tz);
    6:if MG[DRIVE].HLT=1 then stMk:=7;
    7:if rDor>43 then stMk:=8 else stMk:=9;
    8:begin stMk:=10; MG[DRIVE].TR43:=1;end;
    9:begin stMk:=10; MG[DRIVE].TR43:=0;end;
   10:begin stIP:=0; if (rKom and$20)=0{чтение сектора} then stMk:=13 else stMk:=11;end;
   11:if MG[DRIVE].WPRT<>0 then stMk:=12 else stMk:=13;
   12:begin stMk:=$FF;INTRQ:=1;resQ;setP;end;
   13:begin
      if MG[DRIVE]._IP<>0{подсчет прошедших IP} then inc(stIP);
      if stIP>2{5} then stMk:=14 else stMk:=15;
      end;
   14:begin stMk:=$FF;INTRQ:=1;setN;end;
   15:if not(MG[DRIVE].IAM)then stMk:=13 else stMk:=16;
   16:begin if MG[DRIVE].readyIO then
       begin if rDor=MG[DRIVE].GetByte then stMk:=17 else stMk:=13;end;end;
   17:begin if MG[DRIVE].readyIO then
       begin
        rSdw:=MG[DRIVE].GetByte;
        if (rKom and $02)=0{C=0}then stMk:=18 else
         begin
        MG[DRIVE].SIDEup:=(rKom and $08)shr 3;{=s}
        if (MG[DRIVE].SIDEup=rSdw)then stMk:=18 else stMk:=13;
         end;
       end;
      end;
   18:begin if MG[DRIVE].readyIO then
       begin if rSekt=MG[DRIVE].GetByte then stMk:=19 else stMk:=13;end;end;
   19:begin if MG[DRIVE].readyIO then
       begin MG[DRIVE].SektSize:=128 shl MG[DRIVE].GetByte;stMk:=20;end;end;
   20:if MG[DRIVE].CRCErr then stMk:=21 else stMk:=22;
   21:begin setC;stMk:=13;end;
   22:begin resC;stMk:=23;end;
   23:if (rKom and$20)=0{чтение сектора} then stMk:=24 else begin tz:=0;stMk:=37;end;
   24:if not(MG[DRIVE].getDAM) then stMk:=13 else stMk:=25;
   25:begin stMk:=26;if MG[DRIVE].DAM=$FB then resA else setA ;end;
   26:if MG[DRIVE].readyIO then stMk:=27;
   27:
    begin rD:=MG[DRIVE].GetByte;DRQ:=1;stMk:=28;end;
   28:if MG[DRIVE].readyIO then stMk:=29;
   29:if DRQ=1 then stMk:=30 else stMk:=31;
   30:
    begin setW;stMk:=31;end;
   31:begin dec(MG[DRIVE].SektSize);if MG[DRIVE].SektSize>0 then stMk:=27 else stMk:=32;end;
   32:if MG[DRIVE].CRCErr then stMk:=33 else stMk:=34;
   33:begin INTRQ:=1;setC;resQ;stMk:=$FF;end;
   34:if (rKom and$10)=0{M=0}then stMk:=35 else stMk:=36;
   35:begin INTRQ:=1;resQ;stMk:=$FF;end;
   36:begin inc(rSekt);stMk:=10;end;
   37:
   if MG[DRIVE].readyIO then begin MG[DRIVE].GetByte;inc(tz);if tz=2+2{CRC} then stMk:=38 end;
   38:begin DRQ:=1;tz:=0;stMk:=39;end;
   39:if MG[DRIVE].readyIO then begin MG[DRIVE].GetByte;inc(tz);if tz=8 then stMk:=40 end;
   40:if DRQ=0 then stMk:=42 else stMk:=41;
   41:
{>}begin stMk:=$FF;INTRQ:=1;setW;resQ;end;
   42:if MG[DRIVE].readyIO then begin MG[DRIVE].GetByte;stMk:=43;end;
   43:begin MG[DRIVE].WSTB:=1;if MG[DRIVE]._DDEN=0 then begin stMk:=44;tz:=0;end else stMk:=46;end;
   44:if MG[DRIVE].readyIO then begin MG[DRIVE].GetByte;inc(tz);if tz=11 then begin stMk:=45;tz:=0;end end;
   45:if MG[DRIVE].readyIO then begin MG[DRIVE].WriteByte(0);inc(tz);if tz=12 then stMk:=47; end;
   46:if MG[DRIVE].readyIO then begin MG[DRIVE].WriteByte(0);inc(tz);if tz=6 then stMk:=47; end;
   47:if MG[DRIVE].readyIO then
    if MG[DRIVE].GetByte<>$A1 then
    begin stMk:=48;if (rKom and$01)<>0{A}then MG[DRIVE].WriteByte($F8) else MG[DRIVE].WriteByte($FB);end;
   48:begin rSdw:=rD;DRQ:=1;stMk:=49;end;
   49:if MG[DRIVE].readyIO then begin MG[DRIVE].WriteByte(rSdw);stMk:=50;end;
   50:if DRQ=0 then stMk:=52 else stMk:=51;
   51:
{>}begin stMk:=52;SetW;MG[DRIVE].WriteByte(0);end;
   52:begin dec(MG[DRIVE].SektSize);if MG[DRIVE].SektSize>0 then stMk:=48 else begin tz:=0;stMk:=53;end;end;
   53:begin if MG[DRIVE].readyIO then
       begin
        inc(tz);
        if tz=1 then MG[DRIVE].WriteByte(lo(MG[DRIVE].CRC)) else
         begin MG[DRIVE].WriteByte(hi(MG[DRIVE].CRC));stMk:=54;end;
        end;
      end;
   54:if MG[DRIVE].readyIO then begin MG[DRIVE].WriteByte($FF);stMk:=55;end;
   55:begin MG[DRIVE].WSTB:=0;stMk:=34;end;
   end;
if DRQ=1 then setBit(1,rSost) else resBit(1,rSost);
 end;
else
 {команды третьего типа}
 begin
  case rKom and $30 of
  $00,$20:
    begin
     case stMk of
   $FF:asm nop end;
     {чтение дорожки (рис.19)}
      1:begin setQ;INTRQ:=0;resW;resBit(3,rSost);resBit(4,rSost);resBit(5,rSost);resBit(6,rSost);stMk:=2;end;
      2:stMk:=3;{НГМД готов? - Всегда готов!}
      3:begin MG[DRIVE].HLD(1);stMk:=4;end;
      4:if (rKom and $04)<>0 {E=1}then begin tz:=0;stMk:=5;end else stMk:=6;
      5:if tz=3 then stMk:=6 else inc(tz);
      6:if MG[DRIVE].HLT=1 then stMk:=7;
      7:begin stMk:=8;if rDor>43 then MG[DRIVE].TR43:=1 else MG[DRIVE].TR43:=0;end;
      8:if (rKom and $20)=0 then begin stIP:=0;stMk:=19 end else stMk:=9;
      9:asm
{>}     nop      {???????}
        end;
     {чтение адреса (рис.20)}
     19:begin
      if MG[DRIVE]._IP<>0{ожидание фронта IP}then inc(stIP);
      if stIP<2 then stMk:=21 else stMk:=20;
        end;
     20:begin setN;INTRQ:=1;resQ;stMk:=$FF;end;
     21:if not(MG[DRIVE].IAM)then stMk:=19 else begin tz:=0;stMk:=22;end;
     22:if MG[DRIVE].ReadyIO then
      begin
       rSdw:=MG[DRIVE].GetByte;
       rD:=rSdw;DRQ:=1;stMk:=25;
      end;
{    23:
     24:}
     25:begin inc(tz);if tz=6 then stMk:=26 else stMk:=22;end;
     26:begin stMk:=27;rSekt:=rDor;end;
     27:begin stMk:=28; if MG[DRIVE].CRCErr then setC;end;
     28:begin INTRQ:=1;resQ;stMk:=$FF;end;
     end;
    end;
  $30:{запись дорожки - форматирование (рис.18)}
    begin
     case stMk of
   $FF:asm nop end;
      1:begin SetQ;INTRQ:=0;DRQ:=0;resBit(4,rSost);resE;resW;resBit(3,rSost);resP;stMk:=2;end;
      2:stMk:=4;{НГМД готов? - Всегда готов!}
      3:begin INTRQ:=1;resQ;stMk:=$FF;end;
      4:begin MG[DRIVE].HLD(1);stMk:=5;end;
      5:if (rKom and $04)<>0 {E=1}then begin tz:=0;stMk:=6;end else stMk:=7;
      6:if tz=3 then stMk:=7 else inc(tz);
      7:if MG[DRIVE].HLT=1 then stMk:=8;
      8:begin stMk:=9;if rDor>43 then MG[DRIVE].TR43:=1 else MG[DRIVE].TR43:=0;end;
      9:if MG[DRIVE].WPRT<>0 then stMk:=10 else stMk:=11;
     10:begin stMk:=$FF;INTRQ:=1;resQ;setP;end;
     11:begin DRQ:=1;stMk:=12;tz:=0;end;
     12:if MG[DRIVE].readyIO then begin MG[DRIVE].GetByte;inc(tz);if tz=3 then stMk:=13 end;
     13:if DRQ=0 then stMk:=15 else stMk:=14;
     14:begin resQ;INTRQ:=1;setW;stMk:=$FF;end;
     15:if MG[DRIVE]._IP<>0 {ожидание начала дорожки}then stMk:=16;
     16:begin
      rSdw:=rD;DRQ:=1;
      if MG[DRIVE]._DDEN=1 then stMk:=19 else begin tz:=0;stMk:=30;end;
        end;
     {17:}
     {18:}
     19:
{>}  if rSdw=$F7 then begin tz:=0;stMk:=20 end else stMk:=21;
     20:begin if MG[DRIVE].readyIO then
         begin
         inc(tz);
         if tz=1 then MG[DRIVE].WriteByte(lo(MG[DRIVE].CRC)) else
          begin MG[DRIVE].WriteByte(hi(MG[DRIVE].CRC));stMk:=26;end;
         end;
        end;
     21:if rSdw=$FC then stMk:=22 else stMk:=23;
     22:if MG[DRIVE].readyIO then begin stMk:=26;MG[DRIVE].WriteByte($FC);end;
     23:if ((rSdw>=$F8)and(rSdw<=$FB))or(rSdw=$FE) then stMk:=24 else stMk:=25;
     24:if MG[DRIVE].readyIO then begin MG[DRIVE].BeginCRC;MG[DRIVE].WriteByte(rSdw);stMk:=26;end;
     25:if MG[DRIVE].readyIO then begin MG[DRIVE].WriteByte(rSdw);stMk:=26;end;
     26:if MG[DRIVE]._IP<>0 then stMk:=27 else StMk:=28;
     27:begin
         INTRQ:=1;ResQ;stMk:=$FF;
        end;
     28:if DRQ=0 then stMk:=16{ else stMk:=29;
     29:if MG[DRIVE].readyIO then
      begin MG[DRIVE].WriteByte(0);stMk:=26;end};
     30:case rSdw of
        $F5:if MG[DRIVE].readyIO then begin MG[DRIVE].WriteByte($A1);MG[DRIVE].BeginCRC;stMk:=26;end;
        $F6:if MG[DRIVE].readyIO then begin MG[DRIVE].WriteByte($C2);stMk:=26;end;
        $F7:begin if MG[DRIVE].readyIO then
             begin
             inc(tz);
             if tz=1 then MG[DRIVE].WriteByte(lo(MG[DRIVE].CRC)) else
              begin MG[DRIVE].WriteByte(hi(MG[DRIVE].CRC));stMk:=26;end;
             end;
            end;
        else if MG[DRIVE].readyIO then begin MG[DRIVE].WriteByte(rSdw);stMk:=26;end;
        end;
{    31:
     33:
     35:
     36:}
     end;
    end;
  else{команда четвертого типа}
   {принудительное прерывание}
     begin
      if (rKom and $0F)=0 then begin resQ;stMk:=$FF;end;
{     01:if CPRDY 0 to 1 then stMk:=$FF;
      02:if CPRDY 1 to 0 then stMk:=$FF;}
      if (rKom and $04)<>0 then if MG[DRIVE]._IP<>0 then begin resQ;INTRQ:=1;stMk:=$FF;end;
      if (rKom and $08)<>0 then begin INTRQ:=1;resQ;stMk:=$FF;end;
     end;
  end;
if DRQ=1 then setBit(1,rSost) else resBit(1,rSost);
 end;
end;
end;
(****************************************************************************)
procedure InitDrivers;
begin
MG[0].InitDisk('disk0000.tmp');
{MG[1].InitDisk('disk0001.tmp');
MG[2].InitDisk('disk0002.tmp');
MG[3].InitDisk('disk0003.tmp');}
end;
procedure DoneDrivers;
var _b:byte;
begin
_b:=0;
{for _b:=0 to 3 do}
MG[_b].DoneDisk;
end;
(****************************************************************************)
begin
_CLR;{вход - сброс}
end.