;;-----------------------------LICENSE NOTICE------------------------------------
;;  This file is part of Dragon Attack - An entry for CPCRetroDev2016
;;  Copyright (C) 2016  Paul Kooistra
;;
;;  This program is free software: you can redistribute it and/or modify
;;  it under the terms of the GNU General Public License as published by
;;  the Free Software Foundation, either version 3 of the License, or
;;  (at your option) any later version.
;;
;;  This program is distributed in the hope that it will be useful,
;;  but WITHOUT ANY WARRANTY; without even the implied warranty of
;;  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;;  GNU General Public License for more details.
;;
;;  You should have received a copy of the GNU General Public License
;;  along with this program.  If not, see <http://www.gnu.org/licenses/>.
;;
;;  For questions about the source you can PM me, Axelay, on the CPCWiki forums
;;-------------------------------------------------------------------------------
; buffer for holding menu lines as written is same as sprite buffer space and exomizer buffer space
; v5 adds new team logo, drops in game individual credits
MenuDspLineChars equ &8000
MenuDspLineCols equ &8020
MenuMainSelect equ 1
MenuControlSelect equ 2
MenuOptionSelect equ 3
MenuLivesSelect equ 4
MenuHighsSelect equ 5
MenuFireModeSelect equ 6
MenuHighsEntry equ 7

; lookup table which determines the pair of masks used by each of the colour sets
.TitleLogoColours
    defb &0,&f0
    defb &f0,&0
    defb &f,&f0
    defb &f0,&f
    defb &ff,&f0
    defb &f0,&ff
    defb &f,&0
    defb &0,&f
    defb &ff,&0
    defb &0,&ff
    defb &ff,&f
    defb &f,&ff
; lookup table used by high score name entry code
.AsciiTableKeys
    defb 0,0,0,80,91,123,95,93
    defb 48,57,79,73,76,75,77,92
    defb 56,55,85,89,72,74,78,32
    defb 54,53,82,84,71,70,66,86
    defb 52,51,69,87,83,68,67,88
    defb 49,50,0,81,0,65,0,90

.MenuPageTrigger
    defb 1 ; if non zero, display new menu page indicated by value-1
.MenuPageCurrent
    defb 0 ; read input according to value
.MenuInputClear
    defb 1 ; at start of new menu page, check until no keys are pressed to enable input reading
.HighScoreLen
    defb 0 ; current length of high score name entry
.HighScoreAddr
    defw 0 ; screen address of current name entry
.HighScoreData
    defw 0 ; memory position of name being entered in high score table
.HighScoreLastChar
    defb 0 ; store last character to stop repeat on hold
; jump block used by main code to access menu code
.Ind_DrawTitleLogo
    jp DrawTitleLogo
.Ind_ProcessMainMenu
    jp ProcessMainMenu
.Ind_GetROMChars
    jp GetROMChars
.Ind_Init_Display
    jp Init_Display
.Ind_GameDisplayEnding
    jp GameDisplayEnding
; the 4 pieces of music used in the menu only, converted to asm
read "music/MenuMusic5.asm"
read "music/14of12_b.asm"
read "music/Victory3_2.asm"
read "music/Victory1_2.asm"

.DrawTitleLogo
; draw dragon attack logo at top of sreen
    ld ix,LogoColours ; colour data
    ld hl,TitleLogo ; character data
    ld de,&c000 ; scr addr to write to
    ld c,15 ; character lines to write
.MenuWrLogoLp1
    call MenuWriteLine
    dec c
    jr nz,MenuWrLogoLp1
; ix & hl now point to team logo data, write team logo at bottom of screen
    ld de,&c700
    ld c,4
.MenuWrLogoLp2
    call MenuWriteLine
    dec c
    jr nz,MenuWrLogoLp2
    ret

.GameDisplayEnding
; called with hl pointing to colour list, de to location to write to for interrupt colour change
    push hl
    ld (GDEColourAddr+1),de
; want to write 32 lines to screen for ending
    ld de,&c000
    ld c,32
; work out if good or bad ending required
    ld a,(LastGameScore+7) ; find how many of the dragons were killed
    cp a,12
    jr nc,GDEGoodEnding
; display bad ending
; not all dragons destroyed, so show bad ending
    ld ix,GameWonScreen+&400+&800
    ld hl,GameWonScreen+&800
.MenuWrGDEBLp
    call MenuWriteLine
    dec c
    jr nz,MenuWrGDEBLp
    ld a,6 ; set music trigger for bad ending music
    jr GDECommonEnding
.GDEGoodEnding
; display good ending screen
    ld ix,GameWonScreen+&400
    ld hl,GameWonScreen
.MenuWrGDELp
    call MenuWriteLine
    dec c
    jr nz,MenuWrGDELp
    ld a,5 ; set music trigger for good ending music
.GDECommonEnding
; get colour set up info back
    pop hl
.GDEColourAddr
; set up menu colours so ending becomes visible
    ld (&0),hl ; address is set from value held in de when GameDisplayEnding is called
; trigger ending music
    ld (TitleMusic_Control),a ; set game won music control to start
; first wait to make sure no key is pressed
.GDEESCStillPressed
    call GDEGetAnyKey
    or a
    jr nz,GDEESCStillPressed
; now wait for any key to be pressed
.GDEESCNotPressed
    call GDEGetAnyKey
    or a
    jr z,GDEESCNotPressed
; stop playing the game won music
    ld a,2
    ld (TitleMusic_Control),a
; return to main game code loop
    ret

; determine if any key on the keyboard is being pressed
; keys scanned under interrupt
.GDEGetAnyKey
    ld hl,KBMatrixBuf+9
    ld a,(hl)
    dec l
.GDEGetAnyKeyLp
    or a,(hl)
    dec l
    jp p,GDEGetAnyKeyLp
; a contains 0 if no keys are pressed, is non zero if any key pressed
    ret

.MenuWriteLine
; write a single line of characters to the screen
    ld iy,TitleLogoColours ; set up pointer to colour lu table
    ld b,32 ; write 32 characters to the current line
.MenuWrLineLp
    push bc
    ld a,(ix+0)
    inc ix
    add a,a
    ld iyl,a
    ld c,(iy+0)
    ld b,(iy+1)
    ld a,(hl)
    inc hl
    push hl
    call PrintTitleChar
    ex de,hl
    inc de
    pop hl
    pop bc
    djnz MenuWrLineLp
    ret

.PrintTitleChar
; write a single character to the screen
; de points to scr addr to write to, a holds character, bc hold colours
    cp a,5
    jr nz,PrnTCContinue
; is special code, want to move forward just half a character, display nothing
; this is used by by score line set up
    ex de,hl
    ret
.PrnTCContinue
    ld l,a     ;1
    ld h,0     ;2
    add hl,hl  ;3
    add hl,hl  ;3
    add hl,hl  ;3
    add hl,hl  ;3
    ld a,&b0 ;FontBase
    add a,h
    ld h,a
    ld a,8
    push de
.PrnTtlCharLp ; entry with above already determined
    ex af,af'
;
    ld a,(hl)  ;2
    and a,c
    ld (de),a  ;2
    ld a,(hl)
    xor a,&ff
    and a,b
    ex de,hl
    or a,(hl)
    ex de,hl
    ld (de),a
    inc l      ;1
    inc e      ;1
    ld a,(hl)  ;2
    and a,c
    ld (de),a  ;2
    ld a,(hl)
    xor a,&ff
    and a,b
    ex de,hl
    or a,(hl)
    ex de,hl
    ld (de),a
    inc l
    dec e      ;1
    ld a,8
    add a,d
    ld d,a
    ex af,af'
    dec a
    jr nz,PrnTtlCharLp
    pop hl
    inc l
    ret        ; 3 (+5)  total is 114 (119) +14

.GetROMChars
; retrieve the system font from ROM, and convert it to mode 1 compatible data
; set lower rom readable between &0000-&3fff
    ld bc,&7f00+%10001001
    out (c),c
; get ROM ascii set
    ld hl,&3800 ; source of ASCII chars in ROM
    ld de,&b000 ; RAM destination to map them to at 2bpp
    xor a ; 256
.GetRChrLpO
    ex af,af'
    ld b,8
.GetRChrLpI
    ld a,(hl)
    and a,&f0
    ld c,a
    rrca:rrca:rrca:rrca
    or a,c
    ld (de),a
    inc de
    ld a,(hl)
    inc hl
    and a,&f
    ld c,a
    rrca:rrca:rrca:rrca
    or a,c
    ld (de),a
    inc de
    djnz GetRChrLpI
    ex af,af'
    dec a
    jr nz,GetRChrLpO
; set mode 1, roms disabled
    ld bc,&7f00+%10001101
    out (c),c
    ret
.EndRomGet


.Init_Display
; called to set up score line before a game
    ld ix,ScoreLineCols1
    ld hl,ScoreLineChars1
    ld de,&c001
    call MenuWriteLine
    ld ix,ScoreLineCols2
    ld hl,ScoreLineChars2
    ld de,&c040
    call MenuWriteLine
    ret

.RefreshMenuPage
; called with a holding the page number to draw to the menu part of the title screen
; first step, find the list of 13 lines for the menu page held in a
    add a,a
    ld hl,PageList
    ld d,0
    ld e,a
    add hl,de
    ld e,(hl)
    inc hl
    ld d,(hl)
    ex de,hl ; hl now points to list of 13 text lines
    exx
    ld de,&c3c0 ; ld de' with position of first character to write
    exx
    ld b,13
.RMPWrLineLp
; first step is to retreive the line and write to the buffer
    ld a,(hl)
    inc hl
    push hl
    push bc
    call RMPInflateLine
    pop bc
    pop hl
; second step is to write the inflate 32 character line of text to the current line pointed to be de'
    exx
    ld ix,MenuDspLineCols ; line colour buffer just inflated to
    ld hl,MenuDspLineChars ; line character buffer
    call MenuWriteLine
    exx
    djnz RMPWrLineLp
    ret

.RMPInflateLine
; inflate a line of menu text (stored rle) for writing to the menu, a holds line number
    add a,a
    ld hl,LineIndex
    ld d,0
    ld e,a
    add hl,de
    ld e,(hl)
    inc hl
    ld d,(hl)
    ex de,hl ; hl now points to text line to write to the buffer
    ld de,MenuDspLineChars ; buffer to write to
.RMPInflateLineLp
    ld a,(hl)
    cp a,255
    ret z ; have reached the end
    inc hl ; point to next byte in list
    bit 6,a
    jr z,RMPInflateLineString
; have got a byte to repeat 'a' times
    and a,&3f ; mask out control bits to get length
    ld b,a
    ld a,(hl) ; get byte to repeat
    inc hl ; move to next byte in list for next control byte
.RMPInflateLineRepeatLp
    ld (de),a
    inc e
    djnz RMPInflateLineRepeatLp
    jr RMPInflateLineLp
.RMPInflateLineString
; have got a list of bytes to simpl copy, so get length and copy
    and a,&3f ; mask out control bits to get length
    ld c,a
    ld b,0
    ldir ; hl and de already point to appropriate source and dest
    jr RMPInflateLineLp

; prints a white line under present high score character entry position
; or not, according to timer
.PrintHSCursor
    ld a,0
    add a,16
    ld (PrintHSCursor+1),a
    rla
    ret nc
    ld a,&ff
    jr ClrHSCurSkip
.ClearHSCursor
; clear the cursor
    xor a
.ClrHSCurSkip
    ld hl,(HighScoreAddr)
    ld de,&40
    add hl,de
    ld (hl),a
    inc hl
    ld (hl),a
    ret

; get input from the key buffer and check if delete or a character
.ProcessHSCharEntry
    or a
    jr nz,PHSC_ValidChar
; if no valid char
    ld (HighScoreLastChar),a
    ret
.PHSC_ValidChar
; check if same as last character - no auto repeat, so ignore if it is
    ld c,a
    ld a,(HighScoreLastChar)
    cp a,c
    ret z
    ld a,c
    ld (HighScoreLastChar),a
    cp a,8
    jr z,ProcHSCharDel
; check if room for extra char
    ld b,a ; save ascii char
    ld a,(HighScoreLen)
    cp a,14
    ret nc ; no char space left
; is a valid ascii char with room to display, so print it
    inc a
    ld (HighScoreLen),a
; now apply shift status if needed
    ld a,(KBmatrixbuf+2)
    bit 5,a
    ld a,b
    jr nz,ProcHSCharShiftCheckDone ; no shift
    cp a,65
    jr c,ProcHSCharShiftCheckDone ; shift not allowed under this
    cp a,91
    jr nc,ProcHSCharShiftCheckDone ; or over this
    add a,32
.ProcHSCharShiftCheckDone
; now write the new character
    ld de,(HighScoreAddr)
    ld hl,(HighScoreData)
    ld (hl),a
    inc hl
    ld (HighScoreData),hl
    ld bc,&f0
    call PrintTitleChar
    inc hl
    ld (HighScoreAddr),hl
; stop character auto repeating
    ld a,1
    ld (MenuInputClear),a ; block input on new char until all input clear (bar shift)
    ret
.ProcHSCharDel
; check if delete valid (any char to delete?)
    ld a,(HighScoreLen)
    or a
    ret z ; no char to del
; otherwise, delete char
    dec a
    ld (HighScoreLen),a ; reduce char count by 1
; move back one pos in data table
    ld hl,(HighScoreData)
    dec hl
    ld a,(hl)
    ld (hl),32
    ld (HighScoreData),hl
; move back one char on screen and blank deleted char
    ld hl,(HighScoreAddr)
    dec hl
    dec hl
    ld (HighScoreAddr),hl
    ld de,&800-1
    xor a
    ld b,8
.ProcHSDelBlnkLp
    ld (hl),a
    inc hl
    ld (hl),a
    add hl,de
    djnz ProcHSDelBlnkLp
; stop delete auto repeating
    ld a,1
    ld (MenuInputClear),a ; block input on new char until all input clear (bar shift)
    ret

.MMLProcessHSEntry
; read key map for name entry input
    call ClearHSCursor
    call GetAscii ; get current character pressed
    cp a,13
    jr nz,MMLProcessHSENotDone ; is not enter, check entry
; is enter, so end name entry and return to normal menu loop
    ld a,4
    ld (TitleMusic_Control),a ; set title music to immediate start
    jp MenuCmdViewHighsSelection ; entry complete, go to standard high score screen state
.MMLProcessHSENotDone
    call ProcessHSCharEntry
    call PrintHSCursor
    jr MainMenuLoop

; used after enetering new menu screen to ensure input not read until no keys
; are being pressed for 1 frame to avoid unintended input
.CheckMenuInputCleared
    ld hl,KBMatrixBuf+9
    push hl
    pop ix
    ld c,(ix-6) ; line 2, preserve shift state
    res 5,(ix-6); clear shift state if set
    xor a
.CMICLp
    or a,(hl)
    dec l
    jp p,CMICLp
; now restore shift state
    ld (ix-6),c
; have read every input byte from keyboard (scanned under interrupt)
    or a
    jr nz,MainMenuLoop ; key pressed, need to continue waiting
; no keys pressed, clear input block so input can now be processed
    ld (MenuInputClear),a
    jr MainMenuLoop

.UpdateMainMenuDisplay
    dec a
    ld (MenuPageCurrent),a ; set current page for options loop
    call RefreshMenuPage
    xor a
    ld (MenuPageTrigger),a ; clear menu update trigger
    inc a
    ld (MenuInputClear),a ; block input on new menu until all input clear
    jr MainMenuLoop

.ProcessMainMenu
; before loop, set up initial entry conditions
    ld a,MenuMainSelect
    ld (MenuPageTrigger),a ; trigger first menu
    call CheckForHighScore ; if high score entry required, MenuPageTrigger is changed
; now enter main loop
    ld a,(MenuPageTrigger)
    cp a,MenuMainSelect
    jr z,PMMSetMainTheme
    ld a,3
    jr PMMSkipMainTheme
.PMMSetMainTheme
    ld a,1
.PMMSkipMainTheme
    ld (TitleMusic_Control),a ; set title music control to start
; read the keyboard input for option changes and then start game
.MainMenuLoop
    call wait_int
; increment random number seed based on delay in player start of game
    ld hl,cpct_randlcgu8_seed
    inc (hl)
; check if new menu display triggered
    ld a,(MenuPageTrigger)
    or a
    jr nz,UpdateMainMenuDisplay
; if no new menu triggered, grab current menu list and check if in high score entry state
    ld a,(MenuPageCurrent)
    ld c,a ; preserve current page for below
; check a for hi score entry indicator and go jump to alternate routine
    cp a,MenuHighsEntry-1
    jr z,MMLProcessHSEntry
; if not in high score entry mode, check if input has cleared since entered new menu
    ld a,(MenuInputClear)
    or a
    jr nz,CheckMenuInputCleared
; now ok to process input, so get current menu list back from c
    ld a,c
; not high score entry, continue with normal menu input processing
; this involves checking a list of inputs according to the menu id
; and jumping to the matching routine in the list if a key is pressed
    add a,a
    ld e,a
    ld d,0
    ld hl,InputIndex
    add hl,de
    ld e,(hl)
    inc hl
    ld d,(hl)
    ex de,hl ; hl now points to list of inputs and commands
    ld d,KBMatrixBuf/256
.MMLRdKeyLp
    ld a,(hl)
    cp a,255
    jr z,MainMenuLoop ; end of key list
    ld e,a ; de points to key line
    inc hl
    ld a,(de)
    and a,(hl)
    jr nz,MMLRdKeyFound
; this key not pressed, skip routine and check next one
    inc hl
    inc hl
    inc hl
    jr MMLRdKeyLp
.MMLRdKeyFound
; have identified a pressed key, get routine address and jump
    inc hl
    ld e,(hl)
    inc hl
    ld d,(hl)
    ex de,hl
    jp (hl)

; if game start triggered, simply return from menu
.MenuCmdSetStartGame
    ret

; routines that perform actions for menu options
.MenuCmdSetFMNormal
    ld a,(OptionsByte)
    res 3,a
    jr ChngOpCommon
.MenuCmdSetFMInverted
    ld a,(OptionsByte)
    set 3,a
    jr ChngOpCommon
.MenuCmdSetJoystick
    ld a,(OptionsByte)
    set 0,a
    res 1,a
    res 2,a
    jr ChngOpCommon
.MenuCmdSetKeyboard
    ld a,(OptionsByte)
    set 1,a
    res 0,a
    res 2,a
    jr ChngOpCommon
.MenuCmdSetMultiplay
    ld a,(OptionsByte)
    res 0,a
    res 1,a
    res 2,a
    jr ChngOpCommon
.MenuCmdSetCursor
    ld a,(OptionsByte)
    set 2,a
    res 0,a
    res 1,a
.ChngOpCommon
    ld (OptionsByte),a
    jr MenuCmdOptionsSelection

.MenuCmdFireModeSelection
    ld a,MenuFireModeSelect
    jr MenuCmdChangeCommon
.MenuCmdViewHighsEntry
    ld a,MenuHighsEntry
    jr MenuCmdChangeCommon
.MenuCmdViewHighsSelection
    ld a,MenuHighsSelect
    jr MenuCmdChangeCommon
.MenuCmdLivesSelection
    ld a,MenuLivesSelect
    jr MenuCmdChangeCommon
.MenuCmdReturntoMainMenu
    ld a,MenuMainSelect
    jr MenuCmdChangeCommon
.MenuCmdControlSelection
    ld a,MenuControlSelect
    jr MenuCmdChangeCommon
.MenuCmdOptionsSelection
    ld a,MenuOptionSelect
.MenuCmdChangeCommon
    ld (MenuPageTrigger),a
    jp MainMenuLoop

.MenuCmdSetLives1
    ld a,1
    jr MenuCmdLivesSetCommon
.MenuCmdSetLives2
    ld a,2
    jr MenuCmdLivesSetCommon
.MenuCmdSetLives3
    ld a,3
    jr MenuCmdLivesSetCommon
.MenuCmdSetLives4
    ld a,4
    jr MenuCmdLivesSetCommon
.MenuCmdSetLives5
    ld a,5
    jr MenuCmdLivesSetCommon
.MenuCmdSetLives6
    ld a,6
    jr MenuCmdLivesSetCommon
.MenuCmdSetLives7
    ld a,7
    jr MenuCmdLivesSetCommon
.MenuCmdSetLives8
    ld a,8
    jr MenuCmdLivesSetCommon
.MenuCmdSetLives9
    ld a,9
.MenuCmdLivesSetCommon
    ld (StartLives),a
    jr MenuCmdOptionsSelection

; routine used to check if a high score has been attained in the last game played
.CheckForHighScore
    ld ix,Line22+3 ; last entry in high score table
    ld iy,LastGameScore
    call CompareScores
    or a
    ret z
; last score at least higher than the lowest entry on high score table, so find position in table
    ld b,4
    ld ix,Line21+3 ; second last entry in high score table
.CFHSCfindloc
    call CompareScores
    or a ; if a=0, score is not higher, so have found position
    jr z,CFHSCFoundLoc
    push ix
    push ix
    ld de,-47
    add ix,de
    pop hl
    ld de,47
    add hl,de
    ex de,hl
    pop hl
    push bc
    ld bc,44
    ldir
    pop bc
    djnz CFHSCfindloc
.CFHSCFoundLoc
    ld a,b
    ld (CFHSC_FindScreenLoc+1),a ; store b for finding screen address of name to be entered
    ld de,47
    add ix,de ; set ix back down to last entry new score was higher than
; copy actual score
    push ix
    pop hl
    ld de,38
    add hl,de
    ex de,hl
    ld hl,LastGameScore
    ld bc,6
    ldir
; create ascii score
    push ix
    pop hl
    ld de,15
    add hl,de
; hl now points to write pos of score
    call WriteScoreToTable
; hl now points to pos of round
    ld (ix+35),5 ; set colour for if round>9
    ld a,(LastGameScore+6) ; get round number
; check if won game = 13
    cp a,13
    jr nz,CFHSC_GameNotCompleted
; game was completed, so just put two dashes on the round indicator
    ld a,"-"-48
    ld c,a
    jr CFHSC_RoundNoLeading0 ; put the two dashes to the high score table
.CFHSC_GameNotCompleted
    ld c,10
    call FindNumber8bit ; may need an indirect call
; b now holds 10's, a the units
    ld c,a
    ld a,b
    or a
    jr nz,CFHSC_RoundNoLeading0
    ld a,-16 ; print blank char rather than 0
    ld (ix+35),1 ; set colour for if round<=9
.CFHSC_RoundNoLeading0
    add a,48
    ld (ix+28),a
    ld a,c
    add a,48
    ld (ix+29),a

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
.CFHSC_FindScreenLoc
    ld a,0
    ld hl,&c544-&100
    ld de,&80
.CFHSCFindScrAddrLp
    or a
    jr z,CFHSCScrAddrFound
    add hl,de
    dec a
    jr CFHSCFindScrAddrLp
.CFHSCScrAddrFound
    ld (HighScoreAddr),hl ; save start of name position at screen address for name entry
    ld (HighScoreData),ix ; save start of name position in high score table for name entry
; clear old name from high score table entry
    ld a,&20
    ld b,14
.CFHSCClrNameLp
    ld (ix+0),a
    inc ix
    djnz CFHSCClrNameLp
; change leading 0's to full stops
    inc ix
    ld a,&30
    ld bc,&82e
.CFHSCClrLead0Lp
    cp a,(ix+0)
    jr nz,CFHSCDoneLead0
    ld (ix+0),c
    inc ix
    djnz CFHSCClrLead0Lp
.CFHSCDoneLead0
    xor a
    ld (HighScoreLastChar),a ; blank last char entered
    ld (HighScoreLen),a ; set current name length to 0
    ld a,MenuHighsEntry
    ld (MenuPageTrigger),a ; trigger first menu
    ret


.WriteScoreToTable
    ld b,h
    ld c,l
    ld iy,LastGameScore
    ld a,3
.WSTTLoop
    push af
    ld l,(iy+0)
    inc iy
    ld h,(iy+0)
    inc iy
    ld de,-1000
    call FindNumber ;Ind_FindNumber
    add a,48
    ld (bc),a
    inc bc
    ld de,-100
    call FindNumber ;Ind_FindNumber
    add a,48
    ld (bc),a
    inc bc
    ld de,-10
    call FindNumber ;Ind_FindNumber
    add a,48
    ld (bc),a
    inc bc
    ld a,l
    add a,48
    ld (bc),a
    inc bc
    pop af
    dec a
    jr nz,WSTTLoop
    ret

; check if a high score is lower than the new score - used to find both if a new high score
; is achieved, and where it is in the table
.CompareScores
; test with iy=new score, ix=pointer to table
; a returns 1 if new score is higher, 0 otherwise
    ld e,(ix+39)
    ld a,(iy+1)
    cp a,e
    jp c,CompScoreFalse
    jr nz,CompScoreTrue
    ld e,(ix+38)
    ld a,(iy+0)
    cp a,e
    jp c,CompScoreFalse
    jr nz,CompScoreTrue
    ld e,(ix+41)
    ld a,(iy+3)
    cp a,e
    jp c,CompScoreFalse
    jr nz,CompScoreTrue
    ld e,(ix+40)
    ld a,(iy+2)
    cp a,e
    jp c,CompScoreFalse
    jr nz,CompScoreTrue
    ld e,(ix+43)
    ld a,(iy+5)
    cp a,e
    jp c,CompScoreFalse
    jr nz,CompScoreTrue
    ld a,(ix+42)
    cp a,(iy+4)
    jp nc,CompScoreFalse
.CompScoreTrue
    ld a,1
    ret
.CompScoreFalse
    xor a
    ret


.GetAscii
    ld a,(KBmatrixbuf+2)
    and a,4
    jr z,GANotEnter
    ld a,13
    ret
.GANotEnter
    ld a,(KBmatrixbuf+9)
    and a,128
    jr z,GANotDelete
    ld a,8
    ret
.GANotDelete
    ld c,6
    ld hl,KBmatrixbuf+3
    ld de,AsciiTableKeys
.GetAscOuter
    ld a,(hl)
    ld b,8
.GetAscInner
    rra
    jr c,GetAscFound
    inc de
    djnz GetAscInner
    inc hl
    dec c
    jr nz,GetAscOuter
; if here, no character was found
    xor a
    ret
.GetAscFound
    ld a,(de)
    ret

; menu lookup tables
.InputIndex
; main menu screen
    defw MenuInput0
; control select screen
    defw MenuInput1
; option screen
    defw MenuInput2
; lives select screen
    defw MenuInput3
; view highs screen
    defw MenuInput4
; fire mode select screen
    defw MenuInput5
; format is line,bit mask,routine to jump to
; with end of list marked by 255
.MenuInput0 ; main menu
    defb 4,4 ;o
    defw MenuCmdOptionsSelection
    defb 6,128 ;v
    defw MenuCmdViewHighsSelection
    defb 7,16 ;s
    defw MenuCmdSetStartGame
    defb 255 ; end marker
.MenuInput1 ; control
    defb 5,32 ;j
    defw MenuCmdSetJoystick
    defb 4,32 ;k
    defw MenuCmdSetKeyboard
    defb 7,64 ;c
    defw MenuCmdSetCursor
    defb 4,64 ;m
    defw MenuCmdSetMultiplay
    defb 255 ; end marker
.MenuInput2 ; option screen
    defb 7,64 ;c
    defw MenuCmdControlSelection
    defb 4,16 ;l
    defw MenuCmdLivesSelection
    defb 6,32 ;f
    defw MenuCmdFireModeSelection
    defb 8,4 ;esc
    defw MenuCmdReturntoMainMenu
    defb 255 ; end marker
.MenuInput3 ; lives
    defb 8,1 ;1
    defw MenuCmdSetLives1
    defb 8,2 ;2
    defw MenuCmdSetLives2
    defb 7,2 ;3
    defw MenuCmdSetLives3
    defb 7,1 ;4
    defw MenuCmdSetLives4
    defb 6,2 ;5
    defw MenuCmdSetLives5
    defb 6,1 ;6
    defw MenuCmdSetLives6
    defb 5,2 ;7
    defw MenuCmdSetLives7
    defb 5,1 ;8
    defw MenuCmdSetLives8
    defb 4,2 ;9
    defw MenuCmdSetLives9
    defb 255 ; end marker
.MenuInput4 ; view highs screen
    defb 8,4 ;esc
    defw MenuCmdReturntoMainMenu
    defb 255 ; end marker
.MenuInput5 ; fire mode
    defb 7,16 ;s
    defw MenuCmdSetFMNormal
    defb 4,8 ;i
    defw MenuCmdSetFMInverted
    defb 255 ; end marker

; score line char lists
.ScoreLineChars1
db #11,5,#8f,#8f,#8f,#db,#db,#53
db #63,#6f,#72,#65,#d9,#d9,#8f,#8f
db #8f,#8f,#db,#db,#4d,#75,#6c,#74
db #d9,#d9,#8f,#8f,#f4,#8f,5,#07
.ScoreLineChars2
db #8f,#30,#8f,#8f,#30,#30,#30,#30
db #30,#30,#30,#30,#30,#30,#30,#30
db #8f,#92,#3d,#3d,#3d,#3d,#3d,#98
db #78,#30,#30,#8f,#30,#8f,#8f,#30
;score line colour lists
.ScoreLineCols1
db #01,#00,#00,#00,#00,#01,#00,#02
db #02,#02,#02,#02,#00,#01,#00,#00
db #00,#00,#01,#00,#02,#02,#02,#02
db #00,#01,#00,#00,#01,#00,#00,#01
.ScoreLineCols2
db #00,#08,#00,#00,#08,#08,#08,#08
db #08,#08,#08,#08,#08,#08,#08,#08
db #00,#01,#01,#01,#01,#01,#01,#01
db #01,#08,#08,#00,#08,#00,#00,#08

read "DA_Menu_DisplayPageLists2.asm"

.GameWonScreen
read "DA_Gamewon_Both2.asm"

