;******************************************************************************
;            (C) Copyright 1992-1995, Radius, Inc. and Atari Corp.
; Secret and confidential                                   All rights reserved
;******************************************************************************
; This source code and any compilation or derivative thereof is the joint
; property of Radius, Inc. and Atari Corp.  This code is provided pursuant
; to a Software License Agreement and/or Software Development Contract.  This
; code is the proprietary information of Radius, Inc. and Atari Corp. and is
; confidential in nature.  Its use and dissemination by any party other than
; Atari Corp. are strictly limited by the confidential information provisions
; of the Agreement or Contract referenced above.
;******************************************************************************
; Revision 1.3  10/19/94  18:16:10  jpe
; Disabled CD setup and mode selection for RAM playback.
; Fixed bug in calculation of fractional portion of timeIncr.
; Truncated GPU_READY to GPU_READ to keep COFF linker happy.
;
; Revision 1.2  04/27/94  18:46:55  jpe
; CD-BIOS changes incorporated.
;
; Revision 1.1  04/25/94  17:07:10  jpe
; Corrected aspect-ratio problem with video timing.
; Fixed bug which prevented operation without CD-ROM.
; Fixed bug which caused improper handling of empty chunk.
; Added initialization of audio drift rate.
;
; Revision 1.0  04/08/94  13:57:05  jpe
; Initial revision.
;******************************************************************************
; Atari In-House Revisions:
; 1.3.1: SDS
;        Converted to Cinepak Demo Code...not for distribution.
; 1.3.2: SDS
;        Made DSP Code play different format audio.
; 1.3.3: SDS
;        Hold on to your seats...rotation!
; 1.3.4: SDS
;        GPU/DSP now never stop.
; 1.4.0: SDS
;        Triple-Interleaved Buffering.
; 1.4.1: SDS
;        DSP Code Fix/New & Better Startup
; 1.4.2: SDS
;        Correct Expanded RGB Handling
; 1.5.0: SDS
;        Replaced old player, working backwards from CPKDEMO.
;        Now uses our startup, double buffers, enhanced audio,
;        and uses 600Hz timer rather than 60 or 70Hz screen timer.
; 1.5.1: SDS
;        Fixes two problems:
;          1. Movies with only one chunk should now play.
;          2. Their is no search for the first chunk since it should be
;             contiguous in the buffer with the chunk table (The old
;             problem was that the first chunk was searched for from the
;             start of the buffer, not the end of the chunk table.)
;
; 200 05 May 95 DMS     Make it play 1 track on CD, then loop.  Works on 1 trk
;                       on disc 05may95 dms
; 201 06 May 95 DMS     Make it play all tracks on CD, then loop. Use 08may95a
; 202 10 May 95 JPE     Now works with movies which are short enough to fit 
;                       inside the buffer. (Only one CD access is required!)
; 203 16 May 95 JPE     First halting steps toward separating game code, CD
;                       access code and Cinepak player code.
; 204 17 May 95 JPE     Resurrected snapshot in ROMulator memory. CD access
;                       code now separated from Cinepak player code.
; 205 22 May 95 JPE     Split out blitter initialization and operation code
;                       to separate blit.s module. Add call to subtitle and
;                       joystick routines.
; 206 23 May 95 JPE     Fixed bugs in initialization and incrementing of
;                       track number.
; 207 24 May 95 JPE     Eliminated relocation of chunk table. Added code to
;                       deal with optional subtitle atom.
; 208 01 Jun 95 JPE     PlayBuffer routine modified to be driven from block
;                       of parameters.
; 209 07 Jun 95 JPE     Single circular buffer replaced by ping-pong buffers.
; 210 27 Jun 95 JPE     Independent EXECUTIVE, LOADER and PLAYER tasks. Load
;                       and play operations are fully pipelined. Table-driven
;                       looping and branching control. Playlist hand-tailored
;                       for 20JUN95A disk.
; 211 29 Jun 95 JPE     Triple-leadin branching added. Skip title/music on
;                       restart. Playlist hand-tailored for 20JUN95A disk.
; 212 12 Jul 95 JPE     Attenuation of audio at beginning and end of film
;                       segment. Joypad press must occur within time window
;                       during which subtitle is visible. End-game branching
;                       based on path history, plus branching from once-only
;                       loop added. Playlist hand-tailored for 10JUL95C and
;                       11JUL95B disks.
; 213 13 Jul 95 JPE     Two information-only loops added prior to loops when
;                       selections can be made. Audio attenuated by 6 dB on
;                       introduction and endpath tracks. Optional automatic
;                       play of all possible game paths added.
; 214 21 Jul 95 JPE     Player waits for valid start of data. Size of head
;                       start reduced to $6000. Sync search now chases write
;                       pointer.
; 215 22 Aug 95 JPE     Construct voice table from voiceover atom.
; 216 15 Sep 95 JPE     Use bONCE_ONLY is attributes to test for "true" loop.
;                       Modifications for fadeout of exhausted film.
; 217 10 Oct 95 JPE     First steps toward implementation of subtitle atom.
;                       Added fade in following skip-ahead. Added rdBeforeWr
;                       flag for pause control. Added playPause flag.
; 218 24 Oct 95 JPE     Inhibit fadeout of film segment which is target of
;                       reminder (memory jog). Moved voice table stuff to new
;                       module 'auxil.s'. Use hack delay following fadeout in
;                       all cases.
; 219 07 Nov 95 JPE     Added code to handle auxiliary atom.
; 220 05 Dec 95 JPE     Fade keyed to SHOT segments. ONCE_ONLY loop removed.
;                       Added code to handle text slide files.
; 221 02 Feb 96 JPE     Reduced film attribute size to 16 bits. Clean up flags
;                       in control block. Fadeout control using SKIP playlist
;                       structure. Call to ResolveCtrl. Clean up fade control
;                       logic. Eliminate delays in fadeout/fadein. Early
;                       abort of text slide.
; 222 16 Feb 96 JPE     History for loop updated only upon exit. Removed
;                       drift rate hack for SCENE1620.
; 223 20 Feb 96 JPE     Modified logic to also play video whenever audio is
;                       found.
;******************************************************************************

        .nlist
        .include    'memory.inc'
        .include    'jaguar.inc'
        .include    'player.inc'
        .include    'params.inc'
        .include    'offset.inc'
        .list

;******************************************************************************
;                  M O V I E   P L A Y E R   T A S K
;******************************************************************************

PlayMovie:
        lea     playCtrl,a6             ; Player control block
        tst     playPause(a6)           ; Is pause flag set?
        bne     PlayExit                ; Yes, skip the task

        movea.l playBCtrl(a6),a2        ; Control context for play
        movea.l playEntry,a0            ; Get entry address
        jmp     (a0)                    ; Jump to it

PlayIdle:
        tst     playGo(a6)              ; Go command?
        bne.s   PlayStart               ; Yes, start

        move.l  #PlayIdle,playEntry     ; Where to go next time
        bra     PlayExit                ; Exit

PlayStart:
        clr     playGo(a6)              ; Clear go flag
        clr     catchUp                 ; Clear catchUp flag
        clr     audioSmpCnt             ; Clear audio sample counter
        clr     fadeOut                 ; Clear fadeOut flag
        move    #1,ctrlEnable           ; Enable control
        move.l  #-1,frameNum            ; Clear frame counter
        move    #1,playActive(a2)       ; Set read flag

        movea.l pListAddr(a2),a0        ; Get playlist address
        move    cdIndex(a0),currFilm    ; CD index for this film

        move.l  auxStart(a2),auxAtom    ; Load auxiliary atom pointer
        bsr     SetAuxTrack             ; Set auxiliary track

        tst     skipAhead               ; Is skip-ahead enabled?
        beq     SetupVideo              ; No, disable fadeout

        tst     autoPilot               ; On automatic pilot?
        bne     SetupVideo              ; Yes, override skipAhead

DecideFade:
        move.b  attrib(a0),d0           ; Get film attributes
        btst.l  #bLEADIN,d0             ; Leadin?
        beq.s   CheckPending            ; No, see if fade pending

        tst.b   history(a0)             ; Have we seen this one?
        beq.s   CheckPending            ; No, see if fade pending

        btst.l  #bSPECIAL,d0            ; Special case?
        beq.s   SetPending              ; No, set fade pending flag

        cmpi.b  #SKIP,fRule(a0)         ; SKIP structure?
        bne.s   SetPending              ; No, set fade pending flag

        bsr     GetFanMask              ; Get fan-in mask in d0
        and     skPathRec(a0),d0        ; Done this path before?
        beq.s   SetupVideo              ; No, don't fade the clip

SetPending:
        move    #1,fadePending          ; Set fade pending flag

CheckPending:
        tst     fadePending             ; Is a fade pending?
        beq.s   SetupVideo              ; Continue if not

        move.b  attrib(a0),d0           ; Get attributes
        btst.l  #bSPECIAL,d0            ; Special film?
        beq.s   CheckScene              ; No, continue

        cmpi.b  #HYPER,fRule(a0)        ; HYPER segment?
        beq.s   ClearPending            ; Yes, clear pending flag

CheckScene:
        btst.l  #bSCENE,d0              ; Is this a scene?
        beq.s   SetupVideo              ; Continue if not

        move    #1,fadeOut              ; Set fadeOut flag
        move    #0,fadeStep             ; Initialize step index
        move    #1,huntLeadout          ; Set flag for navigator

ClearPending:
        clr     fadePending             ; Clear fade pending flag

SetupVideo:
        move    vCRYmovie(a2),CRYmovie  ; Load CRYmovie flag
        move    vVMODE(a2),VMODE        ; Set video mode
        move.l  movieWidth(a2),d0       ; Width of movie
        move.l  movieHeight(a2),d1      ; Height of movie
        bsr     InitBlit                ; Initialize blitter

        move.l  vADSC(a2),AUDIO_DESC    ; Audio mode
        move.l  vSCLK(a2),SCLK          ; Serial clock
        move.l  vDRIFT(a2),AUDIO_DRIFT  ; Drift rate
        move    txtSlide(a2),textSlide  ; Text slide flag
        move.l  vChunks(a2),chunksLeft  ; Chunk counter
        move.l  vTimeIncr(a2),timeIncr  ; Time units per PIT tick
        move.l  vMaxDelay(a2),maxDelay  ; Maximum video/audio delay

        move.l  cTabStart(a2),pChunkTable ; Start of chunk table

        move.l  time,time0              ; Set time base for this film

BufferLoop:
        tst.l   chunksLeft              ; Any chunks left?
        beq.s   PlayDone                ; No, movie done

        move    #1,rdBeforeWr           ; Read before write pointer
        bra     PlayBuffer              ; Yes, play the buffer

BuffDone:
        bra.s   BufferLoop              ; No, finish what's in buffer

PlayDone:
        tst     fadeOut                 ; Was this a fadeout?
        beq.s   PlayCleanup             ; No, perform cleanup tasks

        move    #1,loadAbort(a2)        ; Tell loader to abort this film
        move    #1,fadeIn               ; Set fadeIn flag
        move    #0,fadeStep             ; Initialize step index

PlayCleanup:
        clr     playActive(a2)          ; Clear read flag
        clr.l   textExpire              ; May be left pending!!!

        tst     autoPilot               ; On automatic pilot?
        bne.s   ExitCleanup             ; Skip if yes

        bsr     UpdateHistory           ; Update playlist history

ExitCleanup:
        move.l  pListAddr(a2),prevList  ; Remember current playlist address
        move    #1,playDone(a6)         ; Set done flag

        tst     loopFlag                ; Are we in a loop?
        bne     PlayIdle                ; Yes, wait to unlock

        clr     bufLocked(a2)           ; Unlock buffer
        clr     bufReady(a2)            ; Clear ready flag
        
        bra     PlayIdle                ; Wait for next command

PlayExit:
        bra     Executive               ; Switch to next task

;------------------------------------------------------------------------------

PlayBuffer:
        tst.l   dataStart(a2)           ; Valid data?
        bne.s   ValidData               ; Yes, proceed

        addq.l  #1,waitCount            ; Counter for debug

        move.l  #PlayBuffer,playEntry   ; Where to go next time
        bra.s   PlayExit                ; Exit

ValidData:
        move.l  buffChunks(a2),nChunks  ; Number of chunks in buffer
        addi.l  #$10,pChunkTable        ; Advance chunk table pointer
        move.l  dataStart(a2),pChunk    ; Start of fresh data
        movea.l pChunk,a3               ; Start of chunk
        lea     SYNC_SIZE(a3),a3        ; Skip over sync field
        tst     loopFlag                ; Is loop flag set?
        bne.s   ChunkLoop               ; Yes, don't reset pointer

        clr.l   dataStart(a2)           ; No, reset it

ChunkLoop:
        move.l  $c(a3),nSamples         ; Number of samples
        move.l  a3,pCpkStream           ; Bitstream pointer
        move.l  4(a3),d0                ; Sample table atom size
        add.l   d0,pCpkStream           ; Base of sample data
        lea     $10(a3),a3              ; Base of sample table
        move.l  a3,pSampleTable         ; Save place in sample table

SampleLoop:
        move.l  #BeginSample,playEntry  ; Where to go next time
        bra     PlayExit                ; Exit

BeginSample:
        bsr     Snapshot                ; Take a snapshot for debug

        move.l  textExpire,d0           ; Get text expiration time
        beq.s   GetSample               ; Skip if zero

        cmp.l   time,d0                 ; Past expiration time?
        bgt.s   GetSample               ; No, continue

        clr.l   textExpire              ; Clear flag
        bsr     ClearOnScreen           ; Erase current text

        tst     skipAhead               ; Is skip-ahead enabled?
        beq.s   GetSample               ; No, continue

        tst     autoPilot               ; On automatic pilot?
        bne     GetSample               ; Yes, override skipAhead

        movea.l pListAddr(a2),a0        ; Get playlist address
        tst.b   history(a0)             ; Have we seen this?
        beq.s   GetSample               ; No, continue

        move    #1,loadAbort(a2)        ; Tell loader to abort
        bra     PlayCleanup             ; Clean up and exit

GetSample:
        movea.l pSampleTable,a3         ; Get place in sample table
        cmpi.l  #-1,8(a3)               ; s->Time == -1?
        bne     DoDisplay               ; No, it's video/slides



        addq    #1,audioSmpCnt          ; Increment audio sample counter
        cmpi    #2,audioSmpCnt          ; Second sample?
        bne.s   LoadDSPArgs             ; No, continue

        move.l  #16,ATTEN_SHIFT         ; 0 dB attenuation
.if 0   ;---------------------------------------------------------------------- ; this is from JIM, not HMK!!!
        move.l  #'CATN',d0              ; ASCII 'clear attenuation'
        clr.l   d1
        move    audioSmpCnt,d1          ; Audio sample count
        move.l  4(a3),d2                ; Sample size
        bsr     RecordEvent             ; Leave crumb for debug
.endif  ;----------------------------------------------------------------------

LoadDSPArgs:

;	*** HMK 6/28/96 - We still have problesm with text slide audio, so we skip it!
;	***		  

	cmp.l	#1, txtSldFlag
	beq	NextSample

; +++++++++++++++++++++++++++++++++++++
; +++ 3/22/96 hmk CSX Audio testing +++
; +++++++++++++++++++++++++++++++++++++
.if 0			

;***	Right now only LEAD OUT 006 has compressed CSX audio. It contains 17
;***	sound chunks. We start with that lead out, so we allow only 17 audio chunks
;***	to be played. Then we don't play anymore in order to not confuse the CSX module
;*** 	and to not have to listen to garbage.

	cmp.w	#17, hmk_audio_test
	bge	NextSample
	add.w	#1, hmk_audio_test

.endif			; +++ 3/22/96 hmk testing

;	--------------------
;	DSP Argument Loading
;	--------------------

.if 1	
; ----  Begin CSX Way
;	*** CSX Argument Loading!
;	*** This is slightly different. The compressor tool pads the audio sections to
;	*** be long aligned to conform with the Quicktime/Jaguar Movie format. But that
;	*** means that the table size information does not reflect the real size. The
; 	*** real size information is found in the first long word of the CSX audio
;	*** chunk. That's the difference to normal audio chunks. They don't contain
;	*** a size header.

        lea     DSP_ARGS,a0             ; DSP argument list
        move.l  pCpkStream,a4
	move.l	(a4)+, d2		; Get actual size of compressed audio data!!
					; it's stored in the first 4 bytes of audio data

        move.l  a4,4(a0)        	; Transfer *audioData (Do first!!)	
        move.l  d2,(a0)                 ; Transfer count
; ----  End CSX Way
.else
; ----  Begin Normal Way
        lea     DSP_ARGS,a0             ; DSP argument list
        move.l  pCpkStream,4(a0)        ; Transfer *audioData (Do first!!)
        move.l  4(a3),(a0)              ; Transfer count
; ----  End Normal Way
.endif
        tst     textSlide               ; Is this a text slide?
        bne     NextSample              ; Yes, proceed

        cmpi.l  #AUD_CHUNK,4(a3)        ; Standard size?
        beq     NextSample              ; Yes, proceed

        move.l  #19,ATTEN_SHIFT         ; 18 dB attenuation on last sample

.if 0   ;---------------------------------------------------------------------- ; this is from JIM, not HMK!!!
        move.l  #'SATN',d0              ; ASCII 'set attenuation'
        clr.l   d1
        move    audioSmpCnt,d1          ; Audio sample count
        move.l  4(a3),d2                ; Sample size
        bsr     RecordEvent             ; Leave crumb for debug
.endif  ;----------------------------------------------------------------------
        bra     NextSample              ; We're done with audio

DoDisplay:
        tst     textSlide               ; Is this a text slide file?
        bne     NoFade                  ; Yes, skip video stuff

        addq.l  #1,frameNum             ; Increment frame counter

        tst     fadeOut                 ; Are we fading out?
        bne     DoFadeOut               ; Yes, do it

        tst     fadeIn                  ; Are we fading in?
        beq     NoFade                  ; No, continue

        move.l  #0,-(a7)                ; Return value
        move.l  pCpkStream,-(a7)        ; Pointer to frame
        bsr     CheckKeyFrame

        lea     $4(a7),a7               ; Balance stack
        move.l  (a7)+,d0                ; Pop return value
        tst.l   d0                      ; Is it a key frame?
        beq     NoFade                  ; No, can't fade

        lea     rgbTables,a0            ; Source in DRAM
        move    fadeStep,d0             ; Get step value
        subq    #4,d0                   ; Reverse index
        neg     d0                      ; Make positive
        blt.s   LastFade                ; If negative, avoid tables

        mulu    #RGB_SIZE,d0            ; Compute offset
        lea     0(a0,d0),a0             ; Source in DRAM

        movea.l #G_RAM+GPU_OFFSET+RGB_OFFSET,a1 ; Destination in GPU

        move.l  #RGB_SIZE,d0            ; Byte count
        bsr     BlockMove               ; Copy RGB table to GPU SRAM
        bra.s   IncStep                 ; Increment step

LastFade:
        movea.l #DECOMP_S,a0            ; Start of GPU code in DRAM
        adda.l  #RGB_OFFSET,a0          ; Source in DRAM

        movea.l #G_RAM+GPU_OFFSET+RGB_OFFSET,a1 ; Destination in GPU

        move.l  #RGB_SIZE,d0            ; Byte count
        bsr     BlockMove               ; Copy RGB table to GPU SRAM

IncStep:
        addi    #1,fadeStep             ; Increment step value
        cmpi    #6,fadeStep             ; Finished last step?
        bne.s   NoFade                  ; No, proceed

        clr     fadeIn                  ; Yes, clear flag
        bra.s   NoFade                  ; We're done

DoFadeOut:
        move.l  #0,-(a7)                ; Return value
        move.l  pCpkStream,-(a7)        ; Pointer to frame
        bsr     CheckKeyFrame

        lea     $4(a7),a7               ; Balance stack
        move.l  (a7)+,d0                ; Pop return value
        tst.l   d0                      ; Is it a key frame?
        beq     NoFade                  ; No, can't fade

        lea     rgbTables,a0            ; Source in DRAM
        move    fadeStep,d0             ; Get step value
        mulu    #RGB_SIZE,d0            ; Compute offset
        lea     0(a0,d0),a0             ; Source in DRAM

        movea.l #G_RAM+GPU_OFFSET+RGB_OFFSET,a1 ; Destination in GPU

        move.l  #RGB_SIZE,d0            ; Byte count
        bsr     BlockMove               ; Copy RGB table to GPU SRAM

        addi    #1,fadeStep             ; Increment step value

NoFade:
        move.l  8(a3),d2                ; s->Time
        bclr    #31,d2                  ; Get rid of MSB

KillTime:
        move.l  time,d0                 ; Get current time
        sub.l   time0,d0                ; Elapsed time for movie
        cmp.l   d0,d2                   ; Ahead of schedule?
        bgt.s   KillTime                ; Yes, wait

        tst     textSlide               ; Is this a text slide file?
        beq.s   DoMovie                 ; No, it's a movie

        movea.l pCpkStream,a0           ; Pointer to bitstream
        cmpi.l  #'TXT!',(a0)            ; Text atom?
        beq.s   ShowText                ; Yes, display text

        cmpi.l  #'TDSC',(a0)            ; Text description atom?
        beq     IncSample               ; Yes, ignore for now

        illegal                         ; Trap error

ShowText:
        lea     8(a0),a2                ; Pointer to string
        move    #WHITE,d1               ; Draw with white
        bsr     Printf                  ; Print formatted text
        move.l  time,d0                 ; Current time
        add.l   $c(a3),d0               ; Add sample duration
        move.l  d0,textExpire           ; Expiration time
        bra     IncSample               ; Done with this sample

DoMovie:
        tst     catchUp                 ; Is catch-up flag set?
        bne.s   LookForKey              ; Yes, look for key frame

        sub.l   d2,d0                   ; Amount we've slipped
        cmp.l   maxDelay,d0             ; Are we too far behind?
        bmi.s   DisplayFrame            ; Not yet, continue

        move    #1,catchUp              ; Yes, set catch-up flag

LookForKey:
        move.l  #0,-(a7)                ; Return value
        move.l  pCpkStream,-(a7)        ; Pointer to frame
        bsr     CheckKeyFrame

        lea     $4(a7),a7               ; Balance stack
        move.l  (a7)+,d0                ; Pop return value
        tst.l   d0                      ; Is it a key frame?
        beq     NextSample              ; No, skip the frame

        clr     catchUp                 ; Yes, clear flag and display frame

DisplayFrame:
        move.l  #1,-(a7)                ; Return value      
        move.l  #CINEPAK_DATA,-(a7)     ; c
        move.l  pCpkStream,-(a7)        ; (Ptr)data
        move    CRYmovie,-(a7)          ; CRYmovie
        bsr     PreDecompress

        lea     $a(a7),a7               ; Balance stack
        move.l  (a7)+,d0                ; Pop return value
        tst.l   d0                      ; Did we get an error?
        beq.s   StartDecomp             ; No, continue  

        move.l  #PREDEC_ERR,d0          ; Load error flag
        illegal                         ; Trap error

StartDecomp:
        move.l  #1,-(a7)                ; Return value
        move.l  #CINEPAK_DATA,-(a7)     ; c
        move.l  pCpkStream,-(a7)        ; (Ptr)data
        move.l  dest,-(a7)              ; data offset
        move    #NPIXELS*2,-(a7)        ; WORLD->bytewidth
        move    #2,-(a7)                ; Triple buffering
        bsr     Decompress

        lea     $10(a7),a7              ; Balance stack
        move.l  (a7)+,d0                ; Pop return value
        tst.l   d0                      ; Did we get an error?
        beq.s   EndDecomp               ; No, continue  

        move.l  #DECOMP_ERR,d0          ; Load error flag
        illegal                         ; Trap error

EndDecomp:
        bsr     DoBlit                  ; Blit to active buffer

NextSample:
        tst     fadeOut                 ; Is this a fadeout?
        beq.s   IncSample               ; No, proceed

        cmpi    #6,fadeStep             ; Finished last step?
        beq     PlayDone                ; Yes, force early exit

IncSample:
        move.l  4(a3),d0                ; Size of sample just finished
        add.l   d0,pCpkStream           ; Data for sample[m+1]
        lea     $10(a3),a3              ; Advance sample table pointer
        move.l  a3,pSampleTable         ; Save place in sample table
        subq.l  #1,nSamples             ; Decrement sample counter
        bne     SampleLoop              ; If not zero, loop again

NextChunk:
        subq.l  #1,chunksLeft           ; Decrement total chunk counter
        subq.l  #1,nChunks              ; Decrement buffer chunk counter
        beq     BuffDone                ; If zero, we've finished

        movea.l pChunkTable,a0          ; Pointer to chunk table
        addi.l  #$10,pChunkTable        ; Advance chunk table pointer
        move.l  4(a0),d0                ; Size of chunk just finished
        add.l   d0,pChunk               ; Next chunk in FIFO
        movea.l pChunk,a3               ; Start of chunk
        lea     SYNC_SIZE(a3),a3        ; Skip over sync field
        tst.l   $c(a3)                  ; Is the chunk empty?
        beq.s   NextChunk               ; Yes, skip it

        bra     ChunkLoop               ; No, do it

;------------------------------------------------------------------------------
;                            UpdateHistory
;------------------------------------------------------------------------------

UpdateHistory:
        movem.l d0/a0,-(sp)             ; Save registers

        bsr     ResolveCtrl             ; Resolve attached controls
        movea.l pListAddr(a2),a0        ; Playlist address

        btst.b  #bLOOP,attrib(a0)       ; Is this a loop?
        bne.s   CheckSpecial            ; Yes, defer history update

IncHistory:
        addq.b  #1,history(a0)          ; Increment counter
        beq.s   IncHistory              ; On rollover, skip 0

CheckSpecial:
        btst.b  #bSPECIAL,attrib(a0)    ; Special case?
        beq.s   ExitUpdate              ; Exit if not

        cmpi.b  #SKIP,fRule(a0)         ; SKIP rule?
        bne.s   ExitUpdate              ; Exit if not

        bsr.s   GetFanMask              ; Get fan-in mask in d0
        or      d0,skPathRec(a0)        ; Set bit in path record

ExitUpdate:
        movem.l (sp)+,d0/a0             ; Restore registers
        rts

;------------------------------------------------------------------------------
;                              GetFanMask
;------------------------------------------------------------------------------
;   Builds a single-bit mask by comparing playlist address of previously
;   played film with address computed from list of relative addresses in
;   the SKIP element fan-in list. If no match is found, a clear mask is
;   returned.
;
;   Input:  a0 = address of "SKIP" playlist entry
;
;   Output: d0 = 16-bit mask
;------------------------------------------------------------------------------

GetFanMask:
        movem.l d1-d2/a0-a1,-(sp)       ; Save registers

        lea     skFanIn(a0),a0          ; Start of fan-in data
        move    #1,d0                   ; Initialize mask
        move    (a0)+,d1                ; Watchdog counter
        move.l  prevList,d2             ; Previous playlist address

GetFanLoop:
        movea.l a0,a1                   ; Copy location in fanin list
        lea     2(a0),a0                ; Next fanin entry
        adda    (a1),a1                 ; Address of referenced entry
        cmp.l   a1,d2                   ; Compare previous film address
        beq.s   GetFanExit              ; Break out if equal

        lsl     #1,d0                   ; Shift mask 1 place to left
        subq    #1,d1                   ; Decrement counter
        bne.s   GetFanLoop              ; Repeat if not zero

        clr     d0                      ; Couldn't match index!

GetFanExit:
        movem.l (sp)+,d1-d2/a0-a1       ; Restore regsiters
        rts

;------------------------------------------------------------------------------
;   Declare storage for flags and variables.
;------------------------------------------------------------------------------

semaphore:      dc.w    0
CRYmovie:       dc.w    0
catchUp:        dc.w    0

        .long
                dc.w    0       ; Keep this...
time:           dc.l    0       ; +2 is read by GPU as longword!
                dc.w    0

timeIncr:       dc.l    0       ; Read by GPU as LONG!
chunksLeft:     dc.l    0
maxDelay:       dc.l    0
textExpire:     dc.l    0
waitCount:      dc.l    0
fadeIn:         dc.w    0

hmk_audio_test:	dc.w	0	; +++ HMK 3/22/96 - for CSX testing

;------------------------------------------------------------------------------
;   Declare uninitialized storage.
;------------------------------------------------------------------------------

        .bss
        .long

time0:          ds.l    1
pChunkTable:    ds.l    1
nChunks:        ds.l    1
nSamples:       ds.l    1
pCpkStream:     ds.l    1
pChunk:         ds.l    1
pSampleTable:   ds.l    1
prevList:       ds.l    1

audioSmpCnt:    ds.w    1
fadeOut:        ds.w    1
fadeStep:       ds.w    1
textSlide:      ds.w    1
fadePending:    ds.w    1
huntLeadout:    ds.w    1

;------------------------------------------------------------------------------
;   Declare externals and globals.
;------------------------------------------------------------------------------

        .extern DSP_ARGS        ; Where to put DSP arguments
        .extern AUDIO_DRIFT     ; Audio drift rate
        .extern AUDIO_DESC      ; Audio data description
        .extern ATTEN_SHIFT     ; Audio attenuation shift
        .extern DECOMP_S        ; Start of GPU code in DRAM

        .extern CheckKeyFrame   ; Check for key frame
        .extern PreDecompress   ; Cinepak codebook expansion
        .extern Decompress      ; Cinepak frame drawing
        .extern HaltCpk         ; Cinepak Shutdown

        .extern Snapshot        ; Make debug snapshot in ROM

        .extern DoBlit          ;
        .extern InitBlit        ;

        .extern autoPilot
        .extern frameNum
        .extern ctrlEnable
        .extern loopFlag
        .extern rgbTables
        .extern dest
        .extern rdBeforeWr
        .extern skipAhead

        .extern playCtrl
        .extern playEntry
        .extern Executive
        .extern RecordEvent
        .extern BlockMove
        .extern auxAtom
        .extern SetAuxTrack
        .extern currFilm
        .extern Printf
        .extern ClearOnScreen
        .extern ResolveCtrl
	.extern txtSldFlag

        .globl  PlayIdle
        .globl  PlayMovie

        .globl  catchUp
        .globl  dest
        .globl  semaphore
        .globl  time
        .globl  time0
        .globl  timeIncr
        .globl  fadeOut
        .globl  pChunkTable
        .globl  pSampleTable
        .globl  nChunks
        .globl  nSamples
        .globl  pCpkStream
        .globl  pChunk
        .globl  fadeIn
        .globl  huntLeadout
        .globl  fadePending

        .end
