Uses ModeXLib,Crt;

Var x,                          {x-position in pixels}
    x_dir,                      {x-direction}
    y,                          {y-position in pixels}
    y_dir:Word;                 {y-direction}

Procedure Wait_In_Display;assembler;
{Counterpart to Wait_In_Retrace, waits for display via cathode ray}
asm
  mov dx,3dah                   {Input Status 1}
@wait2:
  in al,dx
  test al,8h
  jnz @wait2                    {Display on ? -> then finished}
End;
Procedure Wait_In_Retrace;assembler;
{waits for retrace, also resets the ATC flip-flop by read access to Input Status 1}
asm
  mov dx,3dah                   {Input Status 1}
@wait1:
  in al,dx
  test al,8h
  jz @wait1                     {Retrace active ? -> then finished}
End;

Procedure FillScreen;
{Fills video RAM with test image 160*50 characters in size}
var i:word;
Begin
  For i:=0 to 160*50 do Begin   {character loop}
    If i mod 10 <> 0 Then       {write column counter ?}
      mem[$b800:i shl 1]:=      {no, then '-'}
        Ord('-') Else
      mem[$b800:i shl 1]:=      {yes, then column number in tens}
      ((i mod 160) div 10) mod 10 + Ord('0');
    If i mod 160 = 0 Then       {column 0 ? -> write row counter}
      mem[$b800:i shl 1]:=(i div 160) mod 10 + Ord('0');
  End;
End;
Procedure V_Pan(n:Byte);assembler;
{performs vertical panning}
asm
  mov dx,3d4h                   {CRTC Register 8 (Initial Row Adress)}
  mov al,8
  mov ah,n                      {set panning width}
  out dx,ax
End;
Procedure H_Pan(n:Byte);assembler;
{performs horizontal panning}
asm
  mov dx,3c0h                   {ATC Index/Data Port}
  mov al,13h or 32d             {Register 13h (Horizontal Pixel Panning)}
  out dx,al                     {select; Bit 5 (Palette RAM Address Source)}
  mov al,n                      {set, in order not to switch off screen}
  or al,32d                     {write panning value}
  out dx,al
End;

Begin
  TextMode(3);                  {set BIOS mode 3 (80*25 characters, Color)}
  FillScreen;                   {build test picture}
  portw[$3d4]:=$5013;           {double virtual screen width(160 character)}
  x:=0;                         {initialize coordinates and directions}
  x_dir:=1;
  y:=0;
  y_dir:=1;
  Repeat
    Inc(x,x_dir);               {movement in x and y-directions}
    Inc(y,y_dir);
    If (x<=0) or (x>=80*9)      {turn around at borders}
      Then x_dir:=-x_dir;
    if (y<=0) or (y>=25*16)
      Then y_dir:=-y_dir;
    Wait_in_Display;            {wait until display running}
    SetStart((y div 16 *160)    {set start address (rough scrolling}
      + x div 9);
    Wait_in_Retrace;            {wait until retrace active}
    V_Pan(y mod 16);            {vertical panning   (fine scrolling)}
    H_Pan((x-1) mod 9);         {horizontal panning (fine scrolling)}
  Until KeyPressed;             {wait for key}
  TextMode(3);                  {and set normal video mode}
End.
