'===========================================================================
' Subject: FLI-PLAYER                         Date: 08-26-95 (04:36)       
'  Author: Robert Seidel                      Code: PB                     
'  Origin: seidel@ifk.uni-jena.de           Packet: PB.ABC
'===========================================================================
$IF 0

  FLIPLAY - a FLI-Player written in PowerBASIC 3.00c
  Beta-Version: some known bugs, but not corrected :( :< ,
                because I have no time

  Note: Robert Seidel (some changes) for PowerBASIC 3.00c,
        I have removed the MODEX-Libary and optimized some parts,
        now it works about 200% faster than the original version
        written by Dean using Quick BASIC ! Thanks to Dean for
        this great source.

  Robert Seidel
  Kefersteinstr. 14
  D-07745 Jena
  Germany
  E-MAIL: seidel@ifk.uni-jena.de (my dad's adress)

  This player has some problems with newer FLI-files, but I have
  no informations about the new headers. If somebody changes this
  file, it would be great if you could send me the new version
  of FLIPLAY and you will get some things I have written in
  PowerBASIC ! If you are interested in changing PowerBASIC-
  Sources, write me too ...

  You can you use it in your own programms, but please send me a
  copy of your programm (Shareware -> REGISTERED VERSION !!!) and 
  include my name in your credits !

  This file includes a small part of XGRAF, my SCREEN 13
  libary. If you want to have it, write me and send me a
  disc with your stuff !

  Optimized:  -new graphic macros
              -no CVI/CVL-functions
              -some ASM-parts
              -used INCR/DECR
              -converted PEEK to ASM
              -...

$ENDIF

'----------------------- Compiler options -------------------------

$ERROR    ALL OFF 'for more speed
$LIB      ALL OFF
$CPU      80386   'I have used some 386-commands
$FLOAT    EMULATE 'this programm uses no coprocessor-instructions, so the EXE
                  'won't be bigger !
$OPTIMIZE SPEED

'----------------------- Data types -------------------------------

TYPE Fheader 'This is the format of the Header on a .FLI
  Size  AS LONG
  Typ   AS STRING * 2
  Numf  AS INTEGER
  Wid   AS INTEGER
  Hei   AS INTEGER
  Bits  AS INTEGER
  Flag  AS INTEGER
  Speed AS INTEGER
  Nex   AS LONG
  Fri   AS LONG
  Blank AS STRING * 102
END TYPE

TYPE Frameh 'This is the header attached to each frame on a .FLI
  Size  AS LONG
  Typf  AS INTEGER
  Nchu  AS INTEGER
  Blank AS STRING * 8
END TYPE

TYPE Chunkh 'This is the header for each Chunk in a frame
  Size  AS LONG
  Typec AS INTEGER
END TYPE

DEFINT A-Z

DIM DEFSEG AS SHARED INTEGER 'the PEEK-substitute needs this
DIM W      AS SHARED INTEGER
DIM Fhead  AS SHARED Fheader
DIM Chunk  AS SHARED Chunkh
DIM Lns    AS SHARED INTEGER
DIM Clr    AS SHARED INTEGER
DIM RS     AS SHARED STRING
DIM FileN  AS SHARED INTEGER
SHARED a$

OPTION BINARY BASE 1
RS = "FLIPLAY V1.02 Beta (320x200x256) by Robert Seidel 6-11/7-16/8-26 1995"

'----------------------- Main -------------------------------------

IF COMMAND$ = "" THEN 'Access input
  ? RS
  ? "File not specified!"
  END
END IF

Nme$ = COMMAND$
IF INSTR( Nme$, "." ) = 0 THEN Nme$ = Nme$ + ".FLI"

? RS
? "(QUICK BASIC Version by Dean)
? "This was written in POWER BASIC!!!
? "Now playing: " ; Nme$
? "Press any key to continue...
WHILE INKEY$ = ""
WEND

! MOV AX , &h13
! INT &h10
! MOV AX , 19 + 128  ;this is necessary, because I have a strange VGA-card
! INT &h10

OPEN Nme$ FOR BINARY AS #1
FileN = FILEATTR(1 , 2)

DO UNTIL a$ <> ""
  a$ = INKEY$
'  t! = TIMER
  Playfli Nme$   'Play the .FLI
'  time! = TIMER - t!
LOOP

CLOSE #1

! MOV AX , 3
! INT &h10
? RS
END


'----------------------- PlayFLI SUB ------------------------------

DIM STATIC Fm(0 TO 32766) AS SHARED INTEGER
SUB Playfli( XName$ )

  SEEK #1 ,  1
  GET  #1 ,, Fhead             'Get the header data
  DIM Frame AS Frameh          'Set the Frame varible
  Lr = LOC( 1 )
  GET  #1 ,, Frame
  Seekn& = Frame.Size + Lr + 1
  DEFSEG = VARSEG( Fm(0) )
  Vl = VARPTR( Fm(0) )

  Lns   = Vl

  'Get the whole FIRST frame into memory
  ! PUSH DS
  ! MOV AH , &h3F
  ! MOV BX , FileN
  ! DB &h66
  ! MOV CX , Frame[0]
  ! MOV DS , DEFSEG
  ! MOV DX , Vl
  ! INT &h21
  ! POP DS

  FOR Frms = 1 TO Fhead.Numf

    IF INKEY$ <> "" THEN
      a$ = " "
      EXIT SUB
    END IF

    IF Frms > 1 THEN
      SEEK #1 , Seekn& - 1      'PB needs the "- 1" or you get an overflow !
      GET  #1 ,, Frame          'Get the frame data
      INCR Seekn& , Frame.Size  'Store where next frame in file is
      'Get the whole frame
      ! PUSH DS
      ! MOV AH , &h3F
      ! MOV BX , FileN
      ! DB &h66
      ! MOV CX , Frame[0]
      ! MOV DS , DEFSEG
      ! MOV DX , Vl
      ! INT &h21
      ! POP DS
      Lns = Vl
    END IF

    FOR t = 1 TO Frame.Nchu
      'Chunk.Size = PEEKL( Lns ) 'Get chunk data
      ! MOV ES , DEFSEG
      ! MOV BX , Lns
      ! DB &h66
      ! MOV AX , ES:[BX]
      ! DB &h66
      ! MOV Chunk[0] , AX

      INCR Lns , 4

      'Chunk.Typec
      ! MOV ES , DEFSEG
      ! MOV BX , Lns
      ! MOV AX , ES:[BX]
      ! MOV Chunk[4] , AX

      ! MOV AX , Lns
      ! INC AX
      ! INC AX
      ! MOV Lns , AX
      C = Chunk.Typec
      IF C = 11 THEN           'This is if its a PALETTE block
        ! MOV ES , DEFSEG
        ! MOV BX , Lns
        ! MOV AX , ES:[BX]
        ! MOV W , AX
        INCR Lns , 2
        Cl = 0
        FOR i = 1 TO W
          ! MOV ES , DEFSEG
          ! MOV BX , Lns
          ! MOV AH , ES:[BX]
          ! MOV a , AH
          INCR Lns
          INCR Cl , a
          ! MOV ES , DEFSEG
          ! MOV BX , Lns
          ! MOV AH , ES:[BX]
          ! MOV f , AH
          INCR Lns
          IF f = 0 THEN f = 256
          FOR e = Cl TO f - 1
            OUT &H3C8, e
            ! MOV ES , DEFSEG
            ! MOV BX , Lns
            ! MOV AH , ES:[BX]
            ! MOV g , AH
            INCR Lns
            OUT &H3C9, g
            ! MOV ES , DEFSEG
            ! MOV BX , Lns
            ! MOV AH , ES:[BX]
            ! MOV g , AH
            INCR Lns
            OUT &H3C9, g
            ! MOV ES , DEFSEG
            ! MOV BX , Lns
            ! MOV AH , ES:[BX]
            ! MOV g , AH
            INCR Lns
            OUT &H3C9, g
          NEXT e
        NEXT i
      END IF
      IF C = 15 THEN           'This is if it's a FIRST frame RLE
        x = 0
        y = 0
        DO
          ! MOV ES , DEFSEG
          ! MOV BX , Lns
          ! MOV AH , ES:[BX]
          ! MOV Nump , AH
          INCR Lns
          FOR r = 1 TO Nump
            ! MOV ES , DEFSEG
            ! MOV BX , Lns
            ! MOV AH , ES:[BX]
            ! MOV u , AH
            INCR Lns
            IF u < 128 THEN
              ! MOV ES , DEFSEG
              ! MOV BX , Lns
              ! MOV AH , ES:[BX]
              ! MOV Clr , AH
              INCR Lns
              ! MOV AX , 320
              ! MUL y
              ! MOV DI , AX           ; Formel : 320 * y + x
              ! ADD DI , x            ; fr Offset
              ! MOV DX , &hA000       ; Segment : A000h (Videospeicher)
              ! MOV ES , DX
              ! MOV AL , Clr          ; Farbe
              ! MOV AH , AL
              ! MOV CX , u
              ! SHR CX , 1
              ! REP STOSW
              ! ADC CX , CX
              ! REP STOSB
              INCR x , u
            END IF
            IF u > 127 THEN
'This line uses FABS, and so I have written an integer ABS
'u = IABS( u - 255 ) + 1
              ! MOV AX , u
              ! SUB AX , 255
              ! CWD
              ! XOR AX , DX
              ! SUB AX , DX
              ! INC AX
              ! MOV u , AX
              FOR w = 1 TO u
                ! MOV ES , DEFSEG
                ! MOV BX , Lns
                ! MOV AH , ES:[BX]
                ! MOV f , AH
                INCR Lns
                ! MOV AX , 320
                ! MUL y
                ! MOV DI , AX           ; Formel : 320 * y + x
                ! ADD DI , x           ; fr Offset
                ! MOV DX , &hA000       ; Segment : A000h (Videospeicher)
                ! MOV ES , DX
                ! MOV AL , f        ; Farbe
                ! MOV ES:[DI] , AL
                INCR x
              NEXT w
            END IF
          NEXT r
          x = 0
          INCR y
        LOOP UNTIL y > = 199
      END IF
      IF C = 12 THEN       'This is if it's another frame, it skips lines but
                           'it's also an RLE
        ! MOV ES , DEFSEG
        ! MOV BX , Lns
        ! MOV AX , ES:[BX]
        ! MOV y , AX
        INCR Lns , 2
        x = 0
        ! MOV ES , DEFSEG
        ! MOV BX , Lns
        ! MOV AX , ES:[BX]
        ! MOV Clins , AX
        INCR Lns , 2
        FOR Ncl = 1 TO Clins
          'Get num of lines to skip
          ! MOV ES , DEFSEG
          ! MOV BX , Lns
          ! MOV AH , ES:[BX]
          ! MOV a , AH
          INCR Lns
          IF a = 0 THEN Skip
          FOR Npa = 1 TO a
            Repeat:
            'Get num of pixels to skip
            ! MOV ES , DEFSEG
            ! MOV BX , Lns
            ! MOV AH , ES:[BX]
            ! MOV Pskip , AH
            INCR Lns
            INCR x , Pskip
            IF Pkskip = 255 THEN Repeat
            ! MOV ES , DEFSEG
            ! MOV BX , Lns
            ! MOV AH , ES:[BX]
            ! MOV Snd , AH
            INCR Lns
            IF Snd < 128 THEN
              FOR Rd = 1 TO Snd
                ! MOV ES , DEFSEG
                ! MOV BX , Lns
                ! MOV AH , ES:[BX]
                ! MOV Clr , AH
                INCR Lns
                ! MOV AX , 320
                ! MUL y
                ! MOV DI , AX           ; Formel : 320 * y + x
                ! ADD DI , x            ; fr Offset
                ! MOV DX , &hA000       ; Segment : A000h (Videospeicher)
                ! MOV ES , DX
                ! MOV AL , Clr        ; Farbe
                ! MOV ES:[DI] , AL
                INCR x
              NEXT Rd
            ELSE
'This line uses FABS, and so I have written an integer ABS
'Snd = IABS( Snd - 256 )
              ! MOV AX , Snd
              ! SUB AX , 256
              ! CWD
              ! XOR AX , DX
              ! SUB AX , DX
              ! MOV Snd , AX
              ! MOV ES , DEFSEG
              ! MOV BX , Lns
              ! MOV AH , ES:[BX]
              ! MOV Clr , AH
              INCR Lns
              ! MOV AX , 320
              ! MUL y
              ! MOV DI , AX           ; Formel : 320 * y + x
              ! ADD DI , x            ; fr Offset
              ! MOV DX , &hA000       ; Segment : A000h (Videospeicher)
              ! MOV ES , DX
              ! MOV AL , Clr          ; Farbe
              ! MOV AH , AL
              ! MOV CX , Snd
              ! SHR CX , 1
              ! REP STOSW
              ! ADC CX , CX
              ! REP STOSB
              INCR x , Snd
            END IF
          NEXT Npa
          Skip:
          x = 0
          INCR y
        NEXT Ncl
      END IF
    NEXT t
'     FOR Wt = 1 TO Fhead.Speed
'          Waitvbi 'Do delay for num set of video cycles
'     NEXT Wt 'If not needed, it goes faster on fast frame rate FLIs if REMED
  NEXT Frms
END SUB

SUB Waitvbi
  Agin:
  i = INP( &H3DA )
  a = i AND &H8
  IF a = 1 THEN Agin
  Agin2:
  i = INP( &H3DA )
  a = i AND &H8
  IF a = 0 THEN Agin2
END SUB
