Program Trackdisk;

Uses ExecSupport, Crt;

{$include "devices/trackdisk.h" }

Const Drive = 0;     { Laufwerksnummer }
      Hex   = '0123456789abcdef';

Type ModeType = (Hexdump, AsciiDump);

Var diskport    : p_MsgPort;
    diskreq     : p_IOExtTD;
    DiskBuffer  : ^Array[1..TD_SECTOR] Of Byte;
    DeviceFehler: integer;      { Fehlernummer von OpenDevice }
    Err         : integer;      { Fehlernummer von IO-Operationen }
    DiskChangeCount : integer;
    i, j        : integer;
    b           : Byte;
    c           : Char;
    Modus       : ModeType;
    Block       : integer;
    st          : String[20];


Procedure Exitus;
  { Nach Programmende oder Fehler System aufräumen }
  Begin
    If DeviceFehler <> 0 Then CloseDevice(diskreq);
  End;


Procedure MotorOn;
  Begin
    diskreq^.iotd_Req.io_Length := 1;
    diskreq^.iotd_Req.io_Command := TD_MOTOR;
    Err := DoIO(diskreq)
  End;


Procedure MotorOff;
  Begin
    diskreq^.iotd_Req.io_Length := 0;
    diskreq^.iotd_Req.io_Command := TD_MOTOR
    Err := DoIO(diskreq)
  End;


Procedure ReadDiskBlock( nr: integer);
  Begin
    With diskreq^, iotd_Req Do
      Begin
        io_Length := TD_SECTOR;
        io_Data := DiskBuffer;
        io_Command := ETD_READ;
        iotd_Count := DiskChangeCount;
        io_Offset := TD_SECTOR*nr;
      End;
    Err := DoIO(diskreq);
  End;


Begin
  diskport := Nil;
  diskreq  := Nil;
  DeviceFehler := 0;
  AddExitServer(Exitus);

  diskport := CreatePort('Trackdisk-Port' ,0);
  If diskport=Nil Then Error('CreatePort hat versagt.');

  diskreq := Ptr( CreateExtIO(diskport, SizeOf(IOExtTD)) );
  If diskreq=Nil Then Error('CreateExtIO hat versagt.');

  DeviceFehler := OpenDevice(TD_NAME, Drive, diskreq, 0);
  If DeviceFehler <> 0 Then Error('OpenDevice ging nicht.');

  DiskBuffer := Ptr(Alloc_Mem(SizeOf(Diskbuffer^), 2));

  diskreq^.iotd_Req.io_Command := TD_CHANGENUM;
  Err := DoIO(diskreq);
  DiskChangeCount := diskreq^.iotd_Req.io_Actual;


  Block := 880;


  Page;
  Modus := HexDump;

  Repeat

    MotorOn;
    ReadDiskBlock( Block );
    MotorOff;

    GotoXY(1,1);
    Write('Sektor', Block:6);

    Case Modus Of
      HexDump:
        Begin
          For i:=0 to 15 Do
            Begin
              GotoXY(1, i+3);
              For j:=1 to 32 Do
                Begin
                  b := DiskBuffer^[32*i+j];
                  Write( Hex.[b shr 4 + 1], Hex.[b And 15 + 1] )
                  If (j and 3)=0 Then Write(' ');
                End;
            End
        End;
      AsciiDump:
        Begin
          For i:=0 to 15 Do
            Begin
              GotoXY(1,i+3); Write(i:3,': ');
              For j:=1 to 32 Do
                Begin
                  c := Chr(DiskBuffer^[32*i+j]);
                  If c in [' '..#127, #160..#255] Then
                    Write(c)
                  Else
                    Write('_');
                End;
              ClrEol;
            End
        End;
    End;

    GotoXY(1, 20);
    Write('A Asciidump   H HexDump    S Sector   Esc Exit   > ');

    Repeat
      c := Upcase(ReadKey)
    Until (c In ['H', 'A', 'S', #x] ) Or WindowClosed;

    Case c Of
      'H': Modus := HexDump;
      'A': Modus := AsciiDump;
      'S': Begin
             GotoXY(1,20);
             Write('Nummer: '); ClrEol;
             Readln(st);
             While st[1]=' ' Do Delete(st,1,1);
             If st <> '' Then
               Begin
                 Val(st,i,j);
                 If (j<>0) Or (i<0) Then Writeln('Illegal Number!')
                 Else
                   Block := i
               End;
           End;
    Otherwise
    End;

  Until WindowClosed or (c=#x);

End.

