;******************************************************************************
;            (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.
;******************************************************************************
; 100 11 Oct 95 JPE     Initial revision.
; 101 24 Oct 95 JPE     Added control of jogMode to configuration. Correct
;                       implementation of configuration interface and end-
;                       game analysis.
; 102 08 Nov 95 JPE     Save and restore functions added. Endpath converted
;                       to utilize menu-driven machinery. NEITHER option
;                       added to subtitle menu.
; 103 15 Nov 95 JPE     Timeout from endpath menu.
; 104 02 Feb 96 JPE     Implemented parental control locking mechanisms.
;                       Eliminated filmShowings array. Added DEMO hacks.
;                       Increased memory allocation for pathRecord.
; 105 16 Feb 96 JPE     Eliminated node record and node count. Moved state
;                       and configuration variables to "state.s" module.
;******************************************************************************

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

;==============================================================================
;                              ConfigSys
;==============================================================================
;   Routine to display and select options during pause.
;
;   Input:  None
;
;   Output: d0.w = ???
;==============================================================================

ConfigSys::
        move.l  #configPrompt,pStr      ; Set prompt string
        move.l  #configMenu,pTop        ; Set menu pointer
        move.l  #600,cycleTime          ; 1-second menu cycle time
        move    #1,configFlag           ; Set configure flag
        bsr     MenuShell               ; Enter shell
        rts                             ; Return code in d0

;==============================================================================
;                     TOP-LEVEL CONFIGURATION MENU
;==============================================================================

configMenu:
        dc.w    16                      ; Record length
        dc.l    configEnd               ; End of record list

;------ Subtitles/voiceover ---------------------------------------------------

        dc.l    subVoiceText            ; Text
        dc.l    subVoiceMenu            ; Menu
        dc.l    AlwaysEnable            ; Enabler
        dc.l    ExecNormal              ; Handler

;------ Difficulty ------------------------------------------------------------

        dc.l    difficultyText          ; Text
        dc.l    difficultyMenu          ; Menu
        dc.l    AlwaysEnable            ; Enabler
        dc.l    ExecNormal              ; Handler

;------ Parental control ------------------------------------------------------

        dc.l    parentalText            ; Text
        dc.l    parentalMenu            ; Menu
        dc.l    PCtrlEnable             ; Enabler
        dc.l    ExecNormal              ; Handler

;------ Save/restore film -----------------------------------------------------

        dc.l    saveRestText            ; Text
        dc.l    saveRestMenu            ; Menu
        dc.l    SaveRestEnable          ; Enabler
        dc.l    ExecNormal              ; Handler

;------ Skip-ahead ------------------------------------------------------------

        dc.l    skipAheadText           ; Text
        dc.l    skipAheadMenu           ; Menu
        dc.l    AlwaysEnable            ; Enabler
        dc.l    ExecNormal              ; Handler

;------ Reminder (memory-jog) -------------------------------------------------

        dc.l    reminderText            ; Text
        dc.l    reminderMenu            ; Menu
        dc.l    AlwaysEnable            ; Enabler
        dc.l    ExecNormal              ; Handler

;------ Status (score/profile) ------------------------------------------------

        dc.l    statusText              ; Text
        dc.l    0                       ; Menu
        dc.l    AlwaysEnable            ; Enabler
        dc.l    ExecStatus              ; Handler

configEnd:

;==============================================================================
;                       SUBTITLE/VOICEOVER MENU
;==============================================================================

subVoiceMenu:
        dc.w    18                      ; Record length
        dc.l    subVoiceEnd             ; End of record list

;------ SUBTITLES AND VOICEOVER option ----------------------------------------

        dc.l    bothText                ; Text
        dc.l    0                       ; Menu
        dc.l    AlwaysEnable            ; Enabler
        dc.l    ExecNormal              ; Handler
        dc.w    SUB_VOICE               ; Value

;------ SUBTITLES ONLY option -------------------------------------------------

        dc.l    subText                 ; Text
        dc.l    0                       ; Menu
        dc.l    AlwaysEnable            ; Enabler
        dc.l    ExecNormal              ; Handler
        dc.w    SUBTITLES               ; Value

;------ VOICEOVER ONLY option -------------------------------------------------

        dc.l    voiceText               ; Text
        dc.l    0                       ; Menu
        dc.l    AlwaysEnable            ; Enabler
        dc.l    ExecNormal              ; Handler
        dc.w    VOICEOVER               ; Value

;------ NEITHER option --------------------------------------------------------

        dc.l    neitherText             ; Text
        dc.l    0                       ; Menu
        dc.l    AlwaysEnable            ; Enabler
        dc.l    ExecNormal              ; Handler
        dc.w    NEITHER                 ; Value

subVoiceEnd:
        dc.l    cueOption

subVoiceText:   dc.b    'SUBTITLES',0
bothText:       dc.b    'SUBTITLES AND VOICEOVER',0
subText:        dc.b    'SUBTITLES ONLY',0
voiceText:      dc.b    'VOICEOVER ONLY',0
neitherText:    dc.b    'NO SUBTITLES OR VOICEOVER',0

        .even

;==============================================================================
;                           DIFFICULTY MENU
;==============================================================================

difficultyMenu:
        dc.w    18                      ; Record length
        dc.l    difficultyEnd           ; End of record list

;------ EASY option -----------------------------------------------------------

        dc.l    easyText                ; Text
        dc.l    0                       ; Menu
        dc.l    AlwaysEnable            ; Enabler
        dc.l    ExecNormal              ; Handler
        dc.w    EASY                    ; Value

;------ MEDIUM option ---------------------------------------------------------

        dc.l    mediText                ; Text
        dc.l    0                       ; Menu
        dc.l    AlwaysEnable            ; Enabler
        dc.l    ExecNormal              ; Handler
        dc.w    MEDIUM                  ; Value

;------ HARD option -----------------------------------------------------------

        dc.l    hardText                ; Text
        dc.l    0                       ; Menu
        dc.l    AlwaysEnable            ; Enabler
        dc.l    ExecNormal              ; Handler
        dc.w    HARD                    ; Value

difficultyEnd:
        dc.l    difficulty

difficultyText: dc.b    'DIFFICULTY',0
easyText:       dc.b    'EASY',0
mediText:       dc.b    'MEDIUM',0
hardText:       dc.b    'HARD',0

        .even

;==============================================================================
;                        PARENTAL CONTROL MENU
;==============================================================================

parentalMenu:
        dc.w    16                      ; Record length
        dc.l    parentalEnd             ; End of record list

;------ MINIMIZE SEX option ---------------------------------------------------

        dc.l    sexText                 ; Text
        dc.l    sexMenu                 ; Menu
        dc.l    AlwaysEnable            ; Enabler
        dc.l    ExecNormal              ; Handler

;------ MINIMIZE VIOLENCE option ----------------------------------------------

        dc.l    violText                ; Text
        dc.l    violMenu                ; Menu
        dc.l    AlwaysEnable            ; Enabler
        dc.l    ExecNormal              ; Handler

parentalEnd:

;------------------------------------------------------------------------------
;                               SEX MENU
;------------------------------------------------------------------------------

sexMenu:
        dc.w    18                      ; Record length
        dc.l    sexEnd                  ; End of record list

;------ YES option ------------------------------------------------------------

        dc.l    yesText                 ; Text
        dc.l    0                       ; Menu
        dc.l    AlwaysEnable            ; Enabler
        dc.l    ExecNormal              ; Handler
        dc.w    TRUE                    ; Value

;------ NO option -------------------------------------------------------------

        dc.l    noText                  ; Text
        dc.l    0                       ; Menu
        dc.l    AlwaysEnable            ; Enabler
        dc.l    ExecNormal              ; Handler
        dc.w    FALSE                   ; Value

sexEnd:
        dc.l    minSex

;------------------------------------------------------------------------------
;                            VIOLENCE MENU
;------------------------------------------------------------------------------

violMenu:
        dc.w    18                      ; Record length
        dc.l    violEnd                 ; End of record list

;------ YES option ------------------------------------------------------------

        dc.l    yesText                 ; Text
        dc.l    0                       ; Menu
        dc.l    AlwaysEnable            ; Enabler
        dc.l    ExecNormal              ; Handler
        dc.w    TRUE                    ; Value

;------ NO option -------------------------------------------------------------

        dc.l    noText                  ; Text
        dc.l    0                       ; Menu
        dc.l    AlwaysEnable            ; Enabler
        dc.l    ExecNormal              ; Handler
        dc.w    FALSE                   ; Value

violEnd:
        dc.l    minViolence

parentalText:   dc.b    'PARENTAL CONTROL',0
sexText:        dc.b    'MINIMIZE SEX?',0
violText:       dc.b    'MINIMIZE VIOLENCE?',0
yesText:        dc.b    'YES',0
noText:         dc.b    'NO',0

        .even

;==============================================================================
;                          SAVE/RESTORE MENU
;==============================================================================

saveRestMenu:
        dc.w    16                      ; Record length
        dc.l    saveRestEnd             ; End of record list

;------ SAVE option -----------------------------------------------------------

        dc.l    saveText                ; Text
        dc.l    saveMenu                ; Menu
        dc.l    SaveEnable              ; Enabler
        dc.l    ExecNormal              ; Handler

;------ RESTORE option --------------------------------------------------------

        dc.l    restText                ; Text
        dc.l    restMenu                ; Menu
        dc.l    RestoreEnable           ; Enabler
        dc.l    ExecNormal              ; Handler

saveRestEnd:

;------------------------------------------------------------------------------
;                              SAVE MENU
;------------------------------------------------------------------------------

saveMenu:
        dc.w    18                      ; Record length
        dc.l    saveEnd                 ; End of record list

        dc.l    save1Text               ; Text
        dc.l    0                       ; Menu
        dc.l    AlwaysEnable            ; Enabler
        dc.l    ExecSave                ; Handler
        dc.w    $f0ba                   ; Value

        dc.l    save2Text               ; Text
        dc.l    0                       ; Menu
        dc.l    AlwaysEnable            ; Enabler
        dc.l    ExecSave                ; Handler
        dc.w    $f0ba                   ; Value

        dc.l    save3Text               ; Text
        dc.l    0                       ; Menu
        dc.l    AlwaysEnable            ; Enabler
        dc.l    ExecSave                ; Handler
        dc.w    $f0ba                   ; Value

saveEnd:
        dc.l    saveDummy

;------------------------------------------------------------------------------
;                             RESTORE MENU
;------------------------------------------------------------------------------

restMenu:
        dc.w    18                      ; Record length
        dc.l    restEnd                 ; End of record list

        dc.l    rest1Text               ; Text
        dc.l    0                       ; Menu
        dc.l    FilmNEnable             ; Enabler
        dc.l    ExecRestore             ; Handler
        dc.w    $f0ba                   ; Value

        dc.l    rest2Text               ; Text
        dc.l    0                       ; Menu
        dc.l    FilmNEnable             ; Enabler
        dc.l    ExecRestore             ; Handler
        dc.w    $f0ba                   ; Value

        dc.l    rest3Text               ; Text
        dc.l    0                       ; Menu
        dc.l    FilmNEnable             ; Enabler
        dc.l    ExecRestore             ; Handler
        dc.w    $f0ba                   ; Value

restEnd:
        dc.l    restDummy

saveRestText:   dc.b    'SAVE/RESTORE FILM',0
saveText:       dc.b    'SAVE A FILM?',0
restText:       dc.b    'RESTORE A FILM?',0
save1Text:      dc.b    'SAVE AS FILM 1?',0
save2Text:      dc.b    'SAVE AS FILM 2?',0
save3Text:      dc.b    'SAVE AS FILM 3?',0
rest1Text:      dc.b    'RESTORE FILM 1?',0
rest2Text:      dc.b    'RESTORE FILM 2?',0
rest3Text:      dc.b    'RESTORE FILM 3?',0

        .even

saveDummy:  dc.w    0                   ; Dummy variable
restDummy:  dc.w    0                   ; Dummy variable

;==============================================================================
;                           SKIP-AHEAD MENU
;==============================================================================

skipAheadMenu:
        dc.w    18                      ; Record length
        dc.l    skipAheadEnd            ; End of record list

        dc.l    skipText                ; Text
        dc.l    0                       ; Menu
        dc.l    AlwaysEnable            ; Enabler
        dc.l    ExecNormal              ; Handler
        dc.w    TRUE                    ; Value

        dc.l    dontText                ; Text
        dc.l    0                       ; Menu
        dc.l    AlwaysEnable            ; Enabler
        dc.l    ExecNormal              ; Handler
        dc.w    FALSE                   ; Value

skipAheadEnd:
        dc.l    skipAhead

skipAheadText:  dc.b    'SKIP-AHEAD',0
skipText:       dc.b    'OK TO SKIP AHEAD',0
dontText:       dc.b    'DO NOT SKIP AHEAD',0

        .even

;==============================================================================
;                      REMINDER (MEMORY-JOG) MENU
;==============================================================================

reminderMenu:
        dc.w    18                      ; Record length
        dc.l    reminderEnd             ; End of record list

        dc.l    playText                ; Text
        dc.l    0                       ; Menu
        dc.l    AlwaysEnable            ; Enabler
        dc.l    ExecNormal              ; Handler
        dc.w    REVIEW                  ; Value

        dc.l    jumpText                ; Text
        dc.l    0                       ; Menu
        dc.l    AlwaysEnable            ; Enabler
        dc.l    ExecNormal              ; Handler
        dc.w    JUMP                    ; Value

reminderEnd:
        dc.l    jogMode

reminderText:   dc.b    'REMINDER',0
playText:       dc.b    'REVIEW ENTIRE PATH',0
jumpText:       dc.b    'JUMP TO LAST BRANCH POINT',0

        .even

;==============================================================================
;                             STATUS MENU
;==============================================================================

statusText:     dc.b    'SHOW STATUS',0

        .even

;==============================================================================
;                               EndPath
;==============================================================================
;   Routine to display and select options following completion of a path.
;
;   Input:  None
;
;   Output: d0.w = RESTART if restart option selected
;           d0.w = CONTINUE if continue option selected
;           d0.w = REPLAY if replay ("playback") option selected
;==============================================================================

EndPath::
        move.l  #endPrompt,pStr         ; Set prompt string
        move.l  #endPathMenu,pTop       ; Set menu pointer
        move.l  #1200,cycleTime         ; 2-second menu cycle time
        move.l  time,timeLimit          ; Copy current time
        addi.l  #5*60*600,timeLimit     ; Set 5-minute time limit
        clr     configFlag              ; Clear configure flag
        bsr     MenuShell               ; Enter shell
        rts                             ; Return code in d0

;==============================================================================
;                       TOP-LEVEL END-PATH MENU
;==============================================================================

endPathMenu:
        dc.w    18                      ; Record length
        dc.l    endPathEnd              ; End of record list

;------ Restart ---------------------------------------------------------------

        dc.l    restartText             ; Text
        dc.l    0                       ; Menu
        dc.l    AlwaysEnable            ; Enabler
        dc.l    ExecRestart             ; Handler
        dc.w    $f0ba                   ; Value

;------ Continue --------------------------------------------------------------

        dc.l    continueText            ; Text
        dc.l    0                       ; Menu
        dc.l    ContinueEnable          ; Enabler
        dc.l    ExecContinue            ; Handler
        dc.w    $f0ba                   ; Value

;------ Playback --------------------------------------------------------------

        dc.l    playbackText            ; Text
        dc.l    0                       ; Menu
        dc.l    PlaybackEnable          ; Enabler
        dc.l    ExecPlayback            ; Handler
        dc.w    $f0ba                   ; Value

;------ Save/restore film -----------------------------------------------------

        dc.l    saveRestText            ; Text
        dc.l    saveRestMenu            ; Menu
        dc.l    SaveRestEnable          ; Enabler
        dc.l    ExecNormal              ; Handler
        dc.w    $f0ba                   ; Value

;------ Status (score/profile) ------------------------------------------------

        dc.l    statusText              ; Text
        dc.l    0                       ; Menu
        dc.l    AlwaysEnable            ; Enabler
        dc.l    ExecStatus              ; Handler
        dc.w    $f0ba                   ; Value

endPathEnd:
        dc.l    endDummy

restartText:    dc.b    'RESTART',0
continueText:   dc.b    'CONTINUE',0
playbackText:   dc.b    'PLAYBACK',0

        .even

endDummy:   dc.w    0                   ; Dummy variable

;==============================================================================
;                              MenuShell
;==============================================================================
;   Shell interface to menu display and option selection
;
;   Input:  pStr = pointer to prompt string
;           pTop = address of top-level menu
;
;   Output: d0.w = return code
;==============================================================================

MenuShell:
        move.l  d1,-(sp)                ; Save registers

        clr     timeout                 ; Clear timeout flag
        move    #NOTHING,returnVal      ; Default return value
        bsr     ClearOnScreen           ; Clear on-screen buffers

        move    #GREEN,d1               ; Draw with green
        bsr     ShowPrompt              ; Display prompt

        pea     returnVal               ; Pointer to return value
        move.l  pTop,-(sp)              ; Top-level menu
        move    #96,-(sp)               ; Start display at line 96
        move    #0,-(sp)                ; Start at level 0
        bsr     PushLevel               ; Start at top level
        lea     ARG_SIZE(sp),sp         ; Balance stack

        move    #BLACK,d1               ; Draw with black
        bsr     ShowPrompt              ; Erase prompt
        bsr     ClearJoy                ; Let joypad clear

        move    returnVal,d0            ; Return flag to caller
        move.l  (sp)+,d1                ; Restore registers
        rts

;==============================================================================
;                              PushLevel
;==============================================================================
;   Recursively called routine cycles through menu options at a given level.
;   When the 'A' key is pressed above the bottom level, the routine pushes to
;   the next lower level. At the bottom level, the required action is taken
;   (flag setting, status display, etc.). When the 'C' key is pressed at any
;   level, the routine pops to the next higher level.
;
;   Input:  $8(sp) = display line number for text display
;           $a(sp) = pointer to menu data structure
;
;   Output: None
;==============================================================================

;------ Stack frame data structure --------------------------------------------

        .offset 0

            ds.l    1                   ; Old frame pointer
            ds.l    1                   ; Return address

args:                                   ; Arguments
level:      ds.w    1                   ; Level in hierarchy
lineNum:    ds.w    1                   ; Line number for text
pMenu:      ds.l    1                   ; Pointer to menu structure
pRtnValue:  ds.l    1                   ; Pointer to return value

ARG_SIZE    .equ    *-args              ; Size of argument list

;---------- Menu header data structure ----------------------------------------

        .offset 0

recLength:  ds.w    1                   ; Length of a record
target:                                 ; Target variable address
endRecord:  ds.l    1                   ; End address of records
records:                                ; Record storage

;---------- Menu record data structure ----------------------------------------

        .offset 0

text:       ds.l    1                   ; Address of text string
nextLevel:  ds.l    1                   ; Address of next lower level
enabler:    ds.l    1                   ; Address of enabler
handler:    ds.l    1                   ; Address of handler
value:      ds.w    1                   ; Value of target parameter

        .text

PushLevel:
        link    a6,#-0                  ; Allocate stack frame
        movem.l d0-d3/a0-a3,-(sp)       ; Save registers

        move.l  pMenu(a6),a0            ; Menu structure for this level
        lea     records(a0),a1          ; Records for this level
        clr     d2                      ; Record index

ShowOption:
        bsr     TimedOut                ; Check time limit
        tst     timeout                 ; Timed out?
        bne     PopLevel                ; Break out if time exceeded

CallEnable:
        movea.l enabler(a1,d2),a3       ; Address of enabler
        jsr     (a3)                    ; Call it
        bsr     Draw                    ; Draw text string

        move.l  time,d3                 ; Get current time
        add.l   cycleTime,d3            ; Add cycle time

GetPress:
        bsr     GetAny                  ; Get code in d0

        move    level(a6),d1            ; Get hierarchy level
        or      configFlag,d1           ; Or with configure flag
        beq.s   CheckA                  ; Ignore 'C' if zero

        btst.l  #bC,d0                  ; 'C' pressed?
        bne.s   PopLevel                ; Yes, exit

CheckA:
        btst.l  #bA,d0                  ; 'A' pressed?
        beq.s   CheckTime               ; No, continue

        tst     optEnable               ; Is option enabled?
        bne.s   ExecOption              ; Yes, execute it

        bsr     ClearJoy                ; Let joypad clear
        bra.s   CheckTime               ; Check timer

ExecOption:
        bsr     Highlight               ; Overwrite with hot color
        movea.l handler(a1,d2),a3       ; Address of handler
        jmp     (a3)                    ; Jump to it

ExecNormal:
        tst.l   nextLevel(a1,d2)        ; At bottom level?
        bne.s   MoveDown                ; No, move down one

        movea.l target(a0),a2           ; Handle to target variable
        movea.l (a2),a2                 ; Get its address
        move    value(a1,d2),(a2)       ; Set with current selection
        bsr     Draw                    ; Draw text string
        bsr     ClearJoy                ; Clear joypad
        bra.s   CheckTime               ; Check time

MoveDown:
        bsr     ClearJoy                ; Clear joypad
        move.l  pRtnValue(a6),-(sp)     ; Pointer to return value
        move.l  nextLevel(a1,d2),-(sp)  ; Menu for next level
        move    lineNum(a6),-(sp)       ; Push line number
        addi    #24,(sp)                ; Next level is 24 lines down
        move    level(a6),-(sp)         ; Push hierarchy level
        addq    #1,(sp)                 ; Increment it
        bsr     PushLevel               ; Call ourselves recursively
        lea     ARG_SIZE(sp),sp         ; Balance stack

CheckTime:
        cmp.l   time,d3                 ; Time expired?
        bge.s   GetPress                ; No, try joystick again

        bsr     Erase                   ; Erase text string

        add     recLength(a0),d2        ; Next record index
        lea     text(a1,d2),a2          ; Position in table
        cmpa.l  endRecord(a0),a2        ; Beyond last record?
        bne     ShowOption              ; No, proceed

        clr     d2                      ; Reset record index
        bra     ShowOption              ; Loop again

PopLevel:
        bsr     ClearJoy                ; Wait for joypad to clear
        bsr     Erase                   ; Erase text string

        movem.l (sp)+,d0-d3/a0-a3       ; Restore registers
        unlk    a6                      ; Deallocate stack frame
        rts

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

ExecContinue:
        move.l  pRtnValue(a6),a3        ; Pointer to return value
        move    #CONTINUE,(a3)          ; Return flag
        bra.s   PopLevel                ; Exit to caller

ExecPlayback:
        move.l  pRtnValue(a6),a3        ; Pointer to return value
        move    #PLAYBACK,(a3)          ; Return flag
        bra.s   PopLevel                ; Exit to caller

ExecRestart:
        move.l  pRtnValue(a6),a3        ; Pointer to return value
        move    #RESTART,(a3)           ; Return flag
        bra.s   PopLevel                ; Exit to caller

ExecRestore:
        bsr     Restore                 ; Handle RESTORE
        move    #1,restoreFlag          ; Set global flag
        bra     CheckTime               ; Check time

ExecSave:
        move    configFlag,saveEnv      ; Set save environment
        bsr     Save                    ; Handle SAVE
        bra     CheckTime               ; Check time

ExecStatus:
        bsr     ClearJoy                ; Let joypad clear
        bsr     ShowStatus              ; Handle STATUS
        bra     CheckTime               ; Check time

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

AlwaysEnable:
        move    #1,optEnable            ; Set flag true
        rts

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

ContinueEnable:
        movem.l d0-d1,-(sp)             ; Save registers

        move.l  contNode,d0             ; Continuation node address
        move    d0,d1                   ; Low half
        swap    d0                      ; Swap halves
        or      d0,d1                   ; Or high with low
        move    d1,optEnable            ; Write flag

        movem.l (sp)+,d0-d1             ; Restore registers
        rts

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

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

        clr     optEnable               ; Disable by default

        clr.l   d0                      ; Clear high word
        move    d2,d0                   ; Offset in table
        divu    recLength(a0),d0        ; Convert to file index
        mulu    #FREC_SIZE,d0           ; Offset to record
        lea     fileControl,a0          ; Start of file control
        lea     0(a0,d0),a0             ; Record for this file

        tst     exist(a0)               ; Does the file exist?
        beq.s   FilmNExit               ; Exit (disable) if not

        move    minSex,d0               ; Sex control
        lsl     #1,d0                   ; Make room for violence
        or      minViolence,d0          ; 2-bit system attribute

        move    mSex(a0),d1             ; Sex control
        lsl     #1,d1                   ; Make room for violence
        or      mViol(a0),d1            ; 2-bit file attribute

        eor     d0,d1                   ; System ^ File -> File
        and     d0,d1                   ; Mask with system attributes
        bne.s   FilmNExit               ; Prohibit if non-zero

        move    #1,optEnable            ; Otherwise, enable

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

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

PCtrlEnable:
        move.l  d0,-(sp)                ; Save register

        move    minSex,d0               ; Get minSex flag
        or      minViolence,d0          ; Or with minViolence flag
        eori    #1,d0                   ; Toggle
        move    d0,optEnable            ; Write flag

        move.l  (sp)+,d0                ; Restore register
        rts

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

PlaybackEnable:
        tst     restoreFlag             ; Have we done a restore?
        beq.s   UseVCR                  ; No, use vcrMode flag

        move    saveEnv,optEnable       ; Copy config[1]/endpath[0] flag
        eori    #1,optEnable            ; True if endpath
        rts

UseVCR:
        move    vcrMode,optEnable       ; Get vcrMode flag
        eori    #1,optEnable            ; Invert
        rts

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

RestoreEnable:
        move.l  d0,-(sp)                ; Save register

        move    fileExist1,d0           ; File 1 flag
        or      fileExist2,d0           ; Or with file 2 flag
        or      fileExist3,d0           ; Or with file 3 flag
        move    d0,optEnable            ; Write flag

        move.l  (sp)+,d0                ; Restore register
        rts

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

SaveEnable:
        move    vcrMode,optEnable       ; Copy vcrMode flag
        eori    #1,optEnable            ; Toggle it
        rts

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

SaveRestEnable:
        move    nvmPresent,optEnable    ; Write flag
        rts

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

Erase:
        move    #BLACK,d1               ; Select black
        bra.s   DrawIt                  ; Go do it

Draw:
        tst     optEnable               ; Is option enabled?
        beq.s   DrawCold                ; No, draw with cold color

        tst.l   nextLevel(a1,d2)        ; At bottom level?
        bne.s   DrawCool                ; No, draw with cool color

        movea.l target(a0),a2           ; Handle to target variable
        movea.l (a2),a2                 ; Get its address
        move    (a2),d0                 ; Get its value
        cmp     value(a1,d2),d0         ; Same as selected value?
        bne.s   DrawCool                ; No, draw with cool color

Highlight:
        move    #MAGENTA,d1             ; Yes, use hot color
        bra.s   DrawIt                  ; Go do it

DrawCool:
        move    #CYAN,d1                ; Use cool color
        bra.s   DrawIt                  ; Go do it

DrawCold:
        move    #GREY34,d1              ; Use cold color

DrawIt:
        move.l  #$ffff0000,d0           ; Center text
        add     lineNum(a6),d0          ; Merge line number
        movea.l text(a1,d2),a2          ; Text string
        bsr     Print                   ; Display option
        rts

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

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

        move    #BLACK,d1               ; Draw with black
        bsr     ShowPrompt              ; Erase caller's prompt

        move.l  pStr,saveStr            ; Save prompt string
        move    #GREEN,d1               ; Draw with green
        move.l  #statusPrompt,pStr      ; Set prompt string
        bsr     ShowPrompt              ; Display status prompt

        lea     statusParams,a0         ; Parameter table
        moveq   #0,d2                   ; Table index

StatusLoop:
        bsr     TimedOut                ; Check time limit
        tst     timeout                 ; Timed out?
        bne.s   StatusExit              ; Break out if time exceeded

        move    #CYAN,d1                ; Draw with cyan
        movea.l 0(a0,d2),a1             ; Display routine
        jsr     (a1)                    ; Show data

        move.l  time,d1                 ; Current time reading
        add.l   4(a0,d2),d1             ; Add delay

WaitStatus:
        bsr     GetAny                  ; Read joypad
        btst.l  #bC,d0                  ; 'C' pressed?
        bne.s   StatusBreak             ; Yes, break out

        cmp.l   time,d1                 ; Timed out?
        bge.s   WaitStatus              ; No, wait until we do

        move    #BLACK,d1               ; Draw with black
        jsr     (a1)                    ; Erase data

        addq    #8,d2                   ; 8 bytes per table entry
        andi    #$f,d2                  ; Limit index to 0,8
        bra.s   StatusLoop              ; Loop again

StatusBreak:
        bsr     ClearJoy                ; Let joypad clear

        move    #BLACK,d1               ; Draw with black
        jsr     (a1)                    ; Erase data
        bsr     ShowPrompt              ; Erase status prompt

        move    #GREEN,d1               ; Draw with green
        move.l  saveStr,pStr            ; Restore prompt string
        bsr     ShowPrompt              ; Display caller's prompt

StatusExit:
        movem.l (sp)+,d0-d2/a0-a1       ; Restore registers
        rts

statusParams:
        dc.l    ShowScore               ; Score display routine
        dc.l    600                     ; Display for 1 second
        dc.l    ShowProfile             ; Profile display routine
        dc.l    3000                    ; Display for 5 seconds

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

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

        bsr     NVM_Params              ; Get save/restore parameters
        bsr     SaveNVM                 ; Save data to NVM

        movem.l (sp)+,d0-d1/a0          ; Restore registers
        rts

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

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

        bsr     NVM_Params              ; Get save/restore parameters
        bsr     RestoreNVM              ; Restore data from NVM

        movem.l (sp)+,d0-d1/a0          ; Restore registers
        rts

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

NVM_Params:
        clr.l   d0                      ; Clear high word
        move    d2,d0                   ; Offset in table
        divu    recLength(a0),d0        ; Convert to file index
        lea     configData,a0           ; Start of data set
        move.l  configSize,d1           ; Size of data set
        rts

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

;   Input:  d1.w = color

ShowPrompt:
        movem.l d0/a2,-(sp)             ; Save registers

        move.l  #$ffff00c0,d0           ; Draw at (Xcenter,192)
        movea.l pStr,a2                 ; Pointer to prompt text
        bsr     Print                   ; Print score message

        movem.l (sp)+,d0/a2             ; Restore registers
        rts

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

;   Input:  d1.w = color

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

        move.l  score,d0                ; Player's score
        lea     scoreVal,a0             ; Where to put string
        bsr     LToA                    ; Convert score to ASCII

        move.l  #$ffff0060,d0           ; Draw at (Xcenter,96)
        lea     scoreMsg,a2             ; Pointer to score text
        bsr     Print                   ; Print score message

        movem.l (sp)+,d0/a0-a1          ; Restore registers
        rts

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

;   Input:  d1.w = color

ShowProfile:
        movem.l d0/d2-d3/a0-a4,-(sp)    ; Save registers

        move.l  #$ffff0030,d3           ; Start at (Xcenter,48)

        lea     profile,a4              ; Start of profile data
        lea     profileStr,a3           ; Start of string table
        move    #5-1,d2                 ; Count 5 attributes

ShowAttrib:
        clr.l   d0                      ; Clear high word
        move    (a4)+,d0                ; Get attribute value
        movea.l (a3)+,a0                ; Where to put string
        bsr     LToA                    ; Convert value to ASCII

        move.l  d3,d0                   ; (x,y) position
        movea.l (a3)+,a2                ; Pointer to attribute text
        bsr     Print                   ; Print attribute message
        addi.l  #24,d3                  ; Move down 24 lines
        dbra    d2,ShowAttrib           ; Loop until done

        movem.l (sp)+,d0/d2-d3/a0-a4    ; Restore registers
        rts

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

TimedOut:
        move.l  d0,-(sp)                ; Save resgister

        clr     timeout                 ; Clear timeout flag
        tst     configFlag              ; Called from configure?
        bne.s   ExitTimeout             ; Yes, skip timeout

        move.l  timeLimit,d0            ; Get time limit
        cmp.l   time,d0                 ; Compare current time
        bge.s   ExitTimeout             ; Skip if time left

        bsr     ClearOnScreen           ; Clear visible screen
        move    #1,timeout              ; Set timeout flag

ExitTimeout:
        move.l  (sp)+,d0                ; Restore register
        rts

;==============================================================================
;                              InitPCtrl
;==============================================================================
;   Initialize parental control settings.
;==============================================================================

InitPCtrl::
        movem.l d0-d3/a0-a1,-(sp)       ; Save registers

        clr     d2                      ; Clear prototype minSex
        clr     d3                      ; Clear prototype minViolence
        tst     nvmPresent              ; Is there a memory cartridge?
        beq.s   InitPCExit              ; Exit if not

CheckSaved:
        lea     fileControl,a1          ; Start of NVM file control
        moveq   #0,d0                   ; Initial file index
        lea     configData,a0           ; Start of data set
        move.l  pCtrlSize,d1            ; Size of parental control data

InitPCLoop:
        tst     exist(a1)               ; Does the file exist?
        beq.s   InitPCNext              ; No, try next one

        bsr     RestoreNVM              ; Do temporary restore
        move    minSex,mSex(a1)         ; Sex control for file
        or      minSex,d2               ; Or with composite
        move    minViolence,mViol(a1)   ; Violence control for file
        or      minViolence,d3          ; Or with composite

InitPCNext:
        lea     FREC_SIZE(a1),a1        ; Next file record
        addq    #1,d0                   ; Increment file index
        cmpi    #3,d0                   ; Reached limit?
        bne.s   InitPCLoop              ; Continue if not

InitPCExit:
        move    d2,minSex               ; Composite setting
        move    d3,minViolence          ; Composite setting

        movem.l (sp)+,d0-d3/a0-a1       ; Restore registers
        rts

;==============================================================================
;   Declare storage.
;==============================================================================

profileStr:     dc.l    aggresVal, aggresMsg
                dc.l    decisiVal, decisiMsg
                dc.l    analytVal, analytMsg
                dc.l    libidoVal, libidoMsg
                dc.l    energyVal, energyMsg

configPrompt:   dc.b    'A TO ACCEPT, C TO CANCEL',0
endPrompt:      dc.b    'PRESS A TO ACCEPT',0
statusPrompt:   dc.b    'PRESS C TO CANCEL',0

scoreMsg:       dc.b    'YOUR SCORE IS: '
scoreVal:       dcb.b   12,0

aggresMsg:      dc.b    'AGGRESSION: '
aggresVal:      dcb.b   12,0
decisiMsg:      dc.b    'DECISIVENESS: '
decisiVal:      dcb.b   12,0
analytMsg:      dc.b    'ANALYTICAL: '
analytVal:      dcb.b   12,0
libidoMsg:      dc.b    'LIBIDO: '
libidoVal:      dcb.b   12,0
energyMsg:      dc.b    'ENERGY: '
energyVal:      dcb.b   12,0

        .even

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

        .bss

cycleTime:      ds.l    1
pStr:           ds.l    1
pTop:           ds.l    1
saveStr:        ds.l    1
timeLimit:      ds.l    1

optEnable:      ds.w    1
returnVal:      ds.w    1
configFlag:     ds.w    1               ; Config or endpath environment?
timeout:        ds.w    1

;------------------------------------------------------------------------------
;   Declare externals.
;------------------------------------------------------------------------------

        .extern Clear
        .extern ClearJoy
        .extern ClearOnScreen
        .extern GetAny
        .extern GetJoy
        .extern LToA
        .extern Print
        .extern RestoreNVM
        .extern SaveNVM

        .extern configData
        .extern configSize
        .extern contNode
        .extern cueOption
        .extern difficulty
        .extern fileControl
        .extern fileExist1
        .extern fileExist2
        .extern fileExist3
        .extern jogMode
        .extern minSex
        .extern minViolence
        .extern nvmPresent
        .extern pCtrlSize
        .extern profile
        .extern restoreFlag
        .extern saveEnv
        .extern score
        .extern skipAhead
        .extern time
        .extern vcrMode

        .end
