Const
  CLOCK_HZ              =4608;
  MONItoR_HZ            =70;
  CLOCK_SCALE           =CLOCK_HZ div MONItoR_HZ;

  BUFFERSIZE            =$FFFE;
  CDATA                 =$040;
  CMODE                 =$043;
  CO80                  =$3;
  KEYBOARD              =28;
  MOUSE                 =60;
  MCGA                  =$13;
  MCGACheck:Boolean     =True;
  UseXMS:Boolean        =True;
  XMSError:Byte         =0;

Type
  EMMStructure          =Record
                           BytestoMoveLo,
                           BytestoMoveHi,
                           SourceHandle,
                           SourceoffsetLo,
                           SourceoffsetHi,
                           DestinationHandle,
                           DestinationoffsetLo,
                           DestinationoffsetHi  :Word;
                         end;
  HeaderType            =Array[0..128] of Byte;


Var
  Key,
  OldKey                :Byte;
  XMSRecord             :EMMStructure;
  InputFile             :File;
  Header                :HeaderType;
  Counter,
  flicspeed                 :Integer;
  FileCounter,
  FileSize,
  FrameSize,
  NextTime,
  TimeCounter,
  SecondPos             :LongInt;

  Buffer,
  XMSEntryPoint         :Pointer;
  flicspeedString           :String[2];
  FileName              :String;
  BufferHandle,
  BytesRead,
  FrameNumber,
  Frames,
  Chunks                :Word;


Function UpCaseString(Streng:String):String;

Var
  DummyString           :String;
  Counter               :Integer;
begin
  DummyString:='';
  For Counter:=1 to Length(Streng) do
    DummyString:=DummyString+UpCase(Streng[Counter]);
  UpCaseString:=DummyString;
end;


Procedure GetBlock(Var Buffer; Size:Word);
begin
    BlockRead(InputFile,Buffer,Size);
end;


Procedure InitMode(Mode:Word); Assembler;
Asm
  mov  ax,Mode
  int  10h
end;


Function ModeSupport(Mode:Word):Boolean; Assembler;
Label Exit, Last_Modes, No_Support, Supported;
Var
  DisplayInfo           :Array[1..64] of Byte;
Asm
  push es

  mov  ah,1Bh
  mov  bx,0
  push ds
  pop  es
  mov  di,offset DisplayInfo
  int  10h

  les  di,[dWord ptr es:di]

  mov  cx,Mode
  cmp  cx,13h
  ja   No_Support

  mov  ax,1

  cmp  cx,10h
  jae  Last_Modes

  shl  ax,cl
  test ax,[Word ptr es:di+0]
  jz   No_Support
  jmp  Supported

Last_Modes:
  sub  cx,10h
  shl  ax,cl
  test al,[Byte ptr es:di+2]
  jz   No_Support

Supported:
  mov  al,1
  jmp  Exit

No_Support:
  mov  al,0

Exit:
  pop  es
end;



Procedure InitClock; Assembler;
Asm
  mov  al,00110100b
  out  CMODE,al
  xor  al,al
  out  CDATA,al
  out  CDATA,al
end;


Function GetClock:LongInt; Assembler;
Asm
  mov  ah,0
  int  01ah
  mov  ah,dl
  mov  dl,dh
  mov  dh,cl

  mov  al,0
  out  CMODE,al
  mov  al,1
  out  CMODE,al
  in   al,CDATA
  in   al,CDATA
  neg  al
end;


Procedure TreatFrame(Buffer:Pointer;Chunks:Word); Assembler;
Label
  Color_Loop, Copy_Bytes, Copy_Bytes2, Exit, Fli_Black, Fli_Brun, Fli_Color,
  Fli_Copy, Fli_Lc, Fli_Loop, Jump_Over, Line_Loop, Line_Loop2, Next_Line,
  Next_Line2, Pack_Loop, Pack_Loop2;
Asm
  cli
  push ds
  push es
  lds  si,Buffer

Fli_Loop:
  cmp  Chunks,0
  je   Exit
  dec  Chunks

  mov  ax,[Word ptr ds:si+4]
  add  si,6

  cmp  ax,0Bh
  je   Fli_Color
  cmp  ax,0Ch
  je   Fli_Lc
  cmp  ax,0Dh
  je   Fli_Black
  cmp  ax,0Fh
  je   Fli_Brun
  cmp  ax,10h
  je   Fli_Copy
  jmp  Fli_Loop


Fli_Color:
  mov  bx,[Word ptr ds:si]
  add  si,2
  mov  al,0
  xor  cx,cx

Color_Loop:
  or   bx,bx
  jz   Fli_Loop
  dec  bx

  mov  cl,[Byte ptr ds:si+0]
  add  al,cl
  mov  dx,$3C8
  out  dx,al

  inc  dx
  mov  cl,[Byte ptr ds:si+1]
  or   cl,cl
  jnz  Jump_Over
  inc  ch
Jump_Over:
  add  al,cl
  mov  di,cx
  shl  cx,1
  add  cx,di
  add  si,2
  rep  outsb

  jmp  Color_Loop


Fli_Lc:
  mov  ax,0A000h
  mov  es,ax
  mov  di,[Word ptr ds:si+0]
  mov  ax,di
  shl  ax,8
  shl  di,6
  add  di,ax
  mov  bx,[Word ptr ds:si+2]
  add  si,4
  xor  cx,cx

Line_Loop:
  or   bx,bx
  jz  Fli_Loop
  dec  bx

  mov  dl,[Byte ptr ds:si]
  inc  si
  push di

Pack_Loop:
  or   dl,dl
  jz   Next_Line
  dec  dl
  mov  cl,[Byte ptr ds:si+0]
  add  di,cx
  mov  cl,[Byte ptr ds:si+1]
  or   cl,cl
  jns  Copy_Bytes

  mov  al,[Byte ptr ds:si+2]
  add  si,3
  neg  cl
  rep  stosb
  jmp  Pack_Loop

Copy_Bytes:
  add  si,2
  rep  movsb
  jmp  Pack_Loop

Next_Line:
  pop  di
  add  di,320
  jmp  Line_Loop


Fli_Black:
  mov  ax,0A000h
  mov  es,ax
  xor  di,di
  mov  cx,32000
  xor  ax,ax
  rep  stosw
  jmp  Fli_Loop


Fli_Brun:
  mov  ax,0A000h
  mov  es,ax
  xor  di,di
  mov  bx,200
  xor  cx,cx

Line_Loop2:
  mov  dl,[Byte ptr ds:si]
  inc  si
  push di

Pack_Loop2:
  or   dl,dl
  jz   Next_Line2
  dec  dl
  mov  cl,[Byte ptr ds:si]
  or   cl,cl
  js   Copy_Bytes2

  mov  al,[Byte ptr ds:si+1]
  add  si,2
  rep  stosb
  jmp  Pack_Loop2

Copy_Bytes2:
  inc  si
  neg  cl
  rep  movsb
  jmp  Pack_Loop2

Next_Line2:
  pop  di
  add  di,320
  dec  bx
  jnz  Line_Loop2
  jmp  Fli_Loop


Fli_Copy:
  mov  ax,0A000h
  mov  es,ax
  xor  di,di
  mov  cx,32000
  rep  movsw
  jmp  Fli_Loop


Exit:
  sti
  pop  es
  pop  ds
end;

