{$G+}
Uses Crt,ModeXLib;
Type Block=Array[0..99,0..319] of Byte;
Var
  Src_Frame,                    {previous picture}
  Dest_Frame:^Block;            {current picture}

Procedure Scroll_Up;assembler;
{scrolls the picture one line up and interpolates}
asm
  push ds
  les di,Dest_Frame             {load pointer to destination picture}
  lds si,Src_Frame              {pointer to source picture}
  add si,320                    {in source picture on line 1}
  mov cx,320*98                 {scroll 99 lines}
  xor bl,bl                     {required as dummy for High-Byte}
@lp1:
  xor ax,ax
  xor bx,bx
  mov al,[si-321]               {get first point}
  mov bl,[si-320]               {add next point}
  add ax,bx
  mov bl,[si-319]               {add next point}
  add ax,bx
  mov bl,[si-1]                 {etc...}
  add ax,bx
  mov bl,[si+1]
  add ax,bx
  mov bl,[si+319]
  add ax,bx
  mov bl,[si+320]
  adc ax,bx
  mov bl,[si+321]
  adc ax,bx
  shr ax,3

  or ax,ax                      {already 0 ?}
  je @null
  dec al                        {if no, then decrease}
@null:
  stosb                         {value to destination}
  inc si                        {next point}
  dec cx                        {other points ?}
  jne @lp1
  pop ds
End;

Procedure New_Line;             {rebuilds the bottom lines}
Var i,x:Word;
Begin
  For x:=0 to 319 do Begin      {fill bottom 3 lines with random values}
    Dest_Frame^[97,x]:=Random(15)+64;
    Dest_Frame^[98,x]:=Random(15)+64;
    Dest_Frame^[99,x]:=Random(15)+64;
  End;
  For i:=0 to Random(45) do Begin {insert random number Hotspots}
    x:=Random(320);             {to random coordinates}
    asm
      les di,Dest_Frame         {address destination picture}
      add di,98*320             {edit line 98 (second from bottom)}
      add di,x                  {add x-coordinate}
      mov al,0ffh               {brightest color}
      mov es:[di-321],al        {generate large Hotspot (9 points)}
      mov es:[di-320],al
      mov es:[di-319],al
      mov es:[di-1],al
      mov es:[di],al
      mov es:[di+1],al
      mov es:[di+319],al
      mov es:[di+320],al
      mov es:[di+321],al
    End;
  End;
End;

Procedure Show_Screen;          {copies finished screen to VGA}
Var temp:Pointer;               {for exchanging pointers}
Begin
asm
  push ds
  lds si,Dest_Frame             {finished picture as source}
  mov ax,0a000h                 {VGA as destination}
  mov es,ax
  mov di,320*100                {starting at line 100}
  mov cx,320*100/4              {copy 100 lines as Dwords}
db 66h                          {Operand Size Prefix (32 Bit)}
  rep movsw                     {copy}
  pop ds
End;
  temp:=Dest_Frame;             {exchange pointers to source and destination pictures}
  Dest_Frame:=Src_Frame;
  Src_Frame:=temp;
End;

Procedure Prep_Pal;             {prepare palette for flames}
Var i:Word;
Begin
  FillChar(Palette,80*3,0);     {foundation: all black}
  For i:=0 to 7 do Begin
    Palette[i*3+2]:=i*2;        {color 0-7: increase blue}
    Palette[(i+8)*3+2]:=16-i*2; {color 0-7: decreasing blue}
  End;
  For i:=8 to 31 do             {color 8 -31: increase red}
    Palette[i*3]:=(i-8)*63 div 23;
  For i:=32 to 55 do Begin      {color 32-55: increase green, red constant}
    Palette[i*3]:=63;
    Palette[i*3+1]:=(i-32)*63 div 23;
  End;
  For i:=56 to 79 do Begin      {color 56-79: increase blue, red and blue const.}
    Palette[i*3]:=63;
    Palette[i*3+1]:=63;
    Palette[i*3+2]:=(i-56)*63 div 23;
  End;
  FillChar(Palette[80*3],176*3,63);  {rest white}
  SetPal;                       {set finished palette}
End;

begin
  Randomize;                    {determine Random Seed}
  GetMem(Src_Frame,320*100);    {get memory for source picture and delete}
  FillChar(Src_Frame^,320*100,0);
  GetMem(Dest_Frame,320*100);   {get memory for destination picture and delete}
  FillChar(Dest_Frame^,320*100,0);
  Init_Mode13;                  {set Mode 13h}
  Prep_Pal;                     {prepare palette}
  Repeat
    Scroll_Up;                  {flames up}
    New_Line;                   {add new line at bottom}
    Show_Screen;                {show finished screen}
  Until KeyPressed;
  TextMode(3);
end.
