;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; File Name :   invUtil.asm
; Purpose   :   Space Invaders Wrist App Common Utility Routines
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;DO NOT MODIFY THE FOLLOWING SUBROUTINE DEFINITION;;;;;;;;;;;;;;;;;

                IF @DEF('SUBROUTINE')
                    UNDEF SUBROUTINE
                ENDIF
                DEFINE  SUBROUTINE      "'invutil'"
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

                ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

            GLOBAL invUpdatePositions

invUpdatePositions:

                ;update ship position
                ld      HL, #INVShipStepRate
                dec     [HL]
                jr      NZ, invUpdateAlien0Pos

                ld      [HL], #INVSHIPSTEPRATE

                ld      HL, #INVDisplayStatus
                bit     [HL], #bINVShipState
                jr      Z, invUpdateAlien0Pos

                ld      A, [INVShipPosX]
                add     A, [INVShipDirection]
                cp      A, #INVMAXXPOS-1
                jr      NZ, checkforshipminimum

                ;leave ship at max position
                ld      A, #INVMAXXPOS-2
                jr      shipposokay1

checkforshipminimum:
                cp      A, #INVMINXPOS-1
                jr      NZ, shipposokay1

                ;leave ship at min position
                ld      A, #INVMINXPOS

shipposokay1:
                ld      [INVShipPosX], A



invUpdateAlien0Pos:

                ;move alien ship only when time to move
                ld      HL, #INVAlienShipStepRateCurrent
                dec     [HL]
                jr      NZ, updatealienshippositionexit
                ld      A, [INVAlienShipStepRate]
                ld      [HL], A

                ;update alien0 & alien1 & alien2 positions
                ld      A, [INVAlien0PosX]
                ld      B, [INVAlien0Direction]
                add     A, B

                cp      B, #01
                jr      Z, alienrightdirection

alienleftdirection:

                ld      B, [INVAlienMinXPosition]
                jr      aliencheckminmaxpositions

alienrightdirection:

                ld      B, [INVAlienMaxXPosition]

aliencheckminmaxpositions:
                cp      A, B
                jr      NZ, aliensetupnewposition
                ld      A, B

alienreversedirection:

                ld      HL, #INVAlien0Direction
                neg     [HL]

aliensetupnewposition:

                ld      [INVAlien0PosX], A
                add     A, #5
                ld      [INVAlien1PosX], A
                add     A, #5
                ld      [INVAlien2PosX], A

updatealienshippositionexit:
                ret

                ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

            GLOBAL invUpdateMissilePosition
invUpdateMissilePosition:

                ; update missile position only at specified rates
                ld      HL,   [CORECurrentASDAddress]
                add     HL,   #INVSHIPMISSILERATEOFFSET
                dec     [HL]
                jr      NZ,   missilepositionupdateexit

                ; allow missile to move...
                ld      [HL], #INVSHIPMISSILERATE

                ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                ;update ship missle position
                ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

                ld      HL, #INVDisplayStatus
                bit     [HL], #bINVShipMissleState
                jr      Z, updateshipmissileexit

                ;clear old missile position
                ld      IY, #INVShipMissilePosX
                car     invClearMissile

                ;compute new missile position
                ld      HL, #INVShipMissilePosY
                dec     [HL]
                jr      NZ, missileposokay

                ld      IY, #INVShipMissilePosX
                car     invClearMissile
                ld      A, #@LOW(~bINVShipMissleState)
                car     UpdateDisplayState
                jr      updateshipmissileexit

missileposokay: 

                ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                ; check if missile hit something
                ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

                ; check if missile hit alien missile 0
                ; check if missile hit alien missile 1
                ; check if missile hit alien missile 2

                ; check if missile hit an alien
                ld      IY, #INVShipMissilePosX
                ld      A, #@LOW(~(bINVShipState|bINVAlienMissle2State))
                car     invCheckAlienHitByMissile

                ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

updateshipmissileexit:

                ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                ;update alien 0 missile position
                ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

                ld      HL, #INVDisplayStatus
                bit     [HL], #bINVAlienMissle0State
                jr      Z, updatealien0missileexit

                ;clear old missile position
                ld      IY, #INVAlien0MissilePosX
                car     invClearMissile

                ld      HL, #INVAlien0MissilePosY
                inc     [HL]
                cp      [HL], #12
                jr      NZ, missileposokay1

                ld      A, #@LOW(~bINVAlienMissle0State)
                car     UpdateDisplayState
                jr      updatealien0missileexit

missileposokay1: 

                ;check for a hit of my ship
                ld      IY, #INVAlien0MissilePosX
                ld      A, #@LOW(~bINVAlienMissle0State)
                car     invCheckHitOnShip


updatealien0missileexit:



;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

                ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                ;update alien 1 missile position
                ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

                ld      HL, #INVDisplayStatus
                bit     [HL], #bINVAlienMissle1State
                jr      Z, updatealien1missileexit

                ;clear old missile position
                ld      IY, #INVAlien1MissilePosX
                car     invClearMissile

                ld      HL, #INVAlien1MissilePosY
                inc     [HL]
                cp      [HL], #12
                jr      NZ, missileposokay11

                ld      A, #@LOW(~bINVAlienMissle1State)
                car     UpdateDisplayState
                jr      updatealien1missileexit

missileposokay11: 

                ;check for a hit of my ship
                ld      IY, #INVAlien1MissilePosX
                ld      A, #@LOW(~bINVAlienMissle1State)
                car     invCheckHitOnShip


updatealien1missileexit:


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

                ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                ;update alien 2 missile position
                ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

                ld      HL, #INVDisplayStatus
                bit     [HL], #bINVAlienMissle2State
                jr      Z, updatealien2missileexit

                ;clear old missile position
                ld      IY, #INVAlien2MissilePosX
                car     invClearMissile

                ld      HL, #INVAlien2MissilePosY
                inc     [HL]
                cp      [HL], #12
                jr      NZ, missileposokay12

                ld      A, #@LOW(~bINVAlienMissle2State)
                car     UpdateDisplayState
                jr      updatealien2missileexit

missileposokay12: 

                ;check for a hit of my ship
                ld      IY, #INVAlien2MissilePosX
                ld      A, #@LOW(~bINVAlienMissle1State)
                car     invCheckHitOnShip


updatealien2missileexit:

missilepositionupdateexit:

                ret



;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

        GLOBAL invCheckAlienHitByMissile
invCheckAlienHitByMissile:

                ;IY missle x,y coordinate
                ;A = bit complement to clear

				;check if row of missile matches row of the alien
				ld		A, [INVAlien0PosY]
				ld		B, [IY+1]
				cp		A, B
				jr		NZ, invCheckAlienHitByMissileExit

                ld      A, [IY]
                ld      B, [IY+1]
                LCD_GET_STATE_OF_PIXEL
                jr      Z, invCheckAlienHitByMissileExit

                ;alien hit, clear missile
                push    IY
                ld      IY, #INVShipMissilePosX
                car     invClearMissile
                pop     IY
                ld      HL, #INVDisplayStatus
                and     [HL], #@LOW(~bINVShipMissleState)

                ;alien hit, determine which alien
                ld      HL, #INVAlien1PosX
                cp      [HL], [IY]
                jr      C, checkforalien2hit

                ;alien 0 got hit
                ld      IY, #INVAlien0PosX
                car     invClearAlien
                ld      A, #@LOW(~bINVAlien0State)
                jr      ClearTheAlienHit

checkforalien2hit:

                ld      HL, #INVAlien2PosX
                cp      [HL], [IY]
                jr      C, checkforalien3hit

                ;alien 1 got hit
                ld      IY, #INVAlien1PosX
                car     invClearAlien
                ld      A, #@LOW(~bINVAlien1State)
                jr      ClearTheAlienHit

checkforalien3hit:

                ;alien 2 got hit
                ld      IY, #INVAlien2PosX
                car     invClearAlien
                ld      A, #@LOW(~bINVAlien2State)

ClearTheAlienHit:
UpdateDisplayState:

                ;ship hit, clear its status flag
                ld      HL, #INVDisplayStatus
                and     [HL], A

invCheckAlienHitByMissileExit:

                ret


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

            GLOBAL invCheckHitOnShip
invCheckHitOnShip:

                ;check for a hit of my ship
                ;[IY+0] - missile position X
                ;[IY+1] - missile position Y
                ;A - bit complement of the missile status
                ld      B, [IY+1]
                cp      B, #11
                jr      NZ, invCheckHitOnShipExit

                push    A
                ld      A, [IY]
                ld      B, [IY+1]
                LCD_GET_STATE_OF_PIXEL
                pop     A
                jr      Z, invCheckHitOnShipExit

                ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                ; SHIP HIT
                ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

                ;clear alien missile
                and     A, #@LOW(~bINVShipState)
                car     UpdateDisplayState

invCheckHitOnShipExit:

                ret