.ORIG x3000
         
;;; ***************************************************************************

;;; MAIN
;;; Register Input
;;;   None
;;; Register Output
;;;   None

MAIN:   
        ; DRAW GOOD SNAKE HEAD
        LD R6, GOOD_SNAKE_PTR
        LDR R0, R6, 5
        LDR R1, R6, 6
        LDR R2, R6, 4
        TRAP x40 ; DRAW_BLOCK
        
        ; DRAW EVIL SNAKE HEAD
        LD R4, EVIL_SNAKE_PTR
        LDR R0, R4, 5
        LDR R1, R4, 6
        LDR R2, R4, 4
        TRAP x40 ; DRAW_BLOCK
        
        ; Place five apples
        JSR PLACE_RANDOM_APPLE
        JSR PLACE_RANDOM_APPLE
        JSR PLACE_RANDOM_APPLE
        JSR PLACE_RANDOM_APPLE
        JSR PLACE_RANDOM_APPLE
        
GAME_LOOP:      

        ; *** INSERT CODE HERE ***
        ;; ~25 lines of code or so

        HALT

;;; ***************************************************************************

GOOD_SNAKE_PTR:    .FILL GOOD_SNAKE
EVIL_SNAKE_PTR:    .FILL EVIL_SNAKE

;;; ***************************************************************************

;;; ENQUEUE_POS
;;; Register Input
;;;   r0: address of snake object
;;;   r5: x
;;;   r6: y
;;; Register Output
;;;   none

EPR0:   .FILL x0
EPR1:   .FILL x0
EPR2:   .FILL x0
EPR3:   .FILL x0
EPR4:   .FILL x0
EPR5:   .FILL x0
EPR6:   .FILL x0
EPR7:   .FILL x0

ENQUEUE_POS:    

        ; Register Saving
        ST R0, EPR0
        ST R1, EPR1
        ST R2, EPR2
        ST R3, EPR3
        ST R4, EPR4
        ST R5, EPR5
        ST R6, EPR6
        ST R7, EPR7
        
        ; *** INSERT CODE HERE ***
        ;; ~15 lines of code or so
                
        ; Register Restoring
        LD R0, EPR0
        LD R1, EPR1
        LD R2, EPR2
        LD R3, EPR3
        LD R4, EPR4
        LD R5, EPR5
        LD R6, EPR6
        LD R7, EPR7

        RET

;;; ***************************************************************************
        
;;; DEQUEUE_POS
;;; Register Input
;;;   r0: address of snake object
;;; Register Output
;;;   r5: x
;;;   r6: y

DPR0:   .FILL x0
DPR1:   .FILL x0
DPR2:   .FILL x0
DPR3:   .FILL x0
DPR4:   .FILL x0
DPR5:   .FILL x0
DPR6:   .FILL x0
DPR7:   .FILL x0

DEQUEUE_POS:    

        ; Register Saving
        ST R0, DPR0
        ST R1, DPR1
        ST R2, DPR2
        ST R3, DPR3
        ST R4, DPR4
        ST R5, DPR5
        ST R6, DPR6
        ST R7, DPR7
        
        ; *** INSERT CODE HERE ***
        ;; ~15 lines of code or so

        ; Register Restoring
        LD R0, DPR0
        LD R1, DPR1
        LD R2, DPR2
        LD R3, DPR3
        LD R4, DPR4
        ;; don't restore R5 because it holds a return value
        ;; don't restore R6 because it holds a return value
        LD R7, DPR7

        RET

;;; ***************************************************************************

;;; QUEUE_FULL
;;; Register Input
;;;   r0: address of snake object
;;; Register Output
;;;   r5: 1 if queue full, 0 otherwise

QFR0:   .FILL x0
QFR1:   .FILL x0
QFR2:   .FILL x0
QFR3:   .FILL x0
QFR4:   .FILL x0
QFR5:   .FILL x0
QFR6:   .FILL x0
QFR7:   .FILL x0

QUEUE_FULL:     

        ; Register Saving
        ST R0, QFR0
        ST R1, QFR1
        ST R2, QFR2
        ST R3, QFR3
        ST R4, QFR4
        ST R5, QFR5
        ST R6, QFR6
        ST R7, QFR7

        ; *** INSERT CODE HERE ***
        ;; ~15 lines of code or so
                
        ; Register Restoring
        LD R0, QFR0
        LD R1, QFR1
        LD R2, QFR2
        LD R3, QFR3
        LD R4, QFR4
        ;; don't restore R5 because it holds the return value
        LD R6, QFR6
        LD R7, QFR7

        RET

;;; ***************************************************************************
;;; Global constants

SNAKE_MAX_MASK:   .FILL x7F     ; 0000000001111111
BACKGROUND_COLOR: .FILL x0000
APPLE_COLOR:      .FILL x07B0

;;; ***************************************************************************
        
;;; CHECK_COLLISION
;;; Register Input
;;;   r0: address of snake object
;;; Register Output
;;;   r5: >1 if collision at location, 0 if no collision, <0 if apple

CCR0:   .FILL x0
CCR1:   .FILL x0
CCR2:   .FILL x0
CCR3:   .FILL x0
CCR4:   .FILL x0
CCR5:   .FILL x0
CCR6:   .FILL x0
CCR7:   .FILL x0

CHECK_COLLISION:        

        ; Register Saving
        ST R0, CCR0
        ST R1, CCR1
        ST R2, CCR2
        ST R3, CCR3
        ST R4, CCR4
        ST R5, CCR5
        ST R6, CCR6
        ST R7, CCR7
        
        ; *** INSERT CODE HERE ***
        ;; ~25 lines of code or so

        ; Register Restoring
        LD R0, CCR0
        LD R1, CCR1
        LD R2, CCR2
        LD R3, CCR3
        LD R4, CCR4
        ;; don't restore R5 because it holds the return value
        LD R6, CCR6
        LD R7, CCR7

        RET

;;; ***************************************************************************

;;; GET_NEXT
;;; Register Input
;;;   r0: address of snake object
;;; Register Output
;;;   r5: x`
;;;   r6: y`

GNR0:   .FILL x0
GNR1:   .FILL x0
GNR2:   .FILL x0
GNR3:   .FILL x0
GNR4:   .FILL x0
GNR5:   .FILL x0
GNR6:   .FILL x0
GNR7:   .FILL x0

GET_NEXT:       

        ; Register Saving
        ST R0, GNR0
        ST R1, GNR1
        ST R2, GNR2
        ST R3, GNR3
        ST R4, GNR4
        ST R5, GNR5
        ST R6, GNR6
        ST R7, GNR7

        ; *** INSERT CODE HERE ***
        ;; ~35 lines of code or so

        ; Register Restoring
        LD R0, GNR0
        LD R1, GNR1
        LD R2, GNR2
        LD R3, GNR3
        LD R4, GNR4
        ;; don't restore R5 because it holds a return value
        ;; don't restore R6 because it holds a return value
        LD R7, GNR7

        RET

;;; ***************************************************************************

;;; EVIL_SNAKE_AI
;;; Register Input
;;;   r0: address of snake object
;;; Register Output
;;;   None

ESAIR0: .FILL x0
ESAIR1: .FILL x0
ESAIR2: .FILL x0
ESAIR3: .FILL x0
ESAIR4: .FILL x0
ESAIR5: .FILL x0
ESAIR6: .FILL x0
ESAIR7: .FILL x0

EVIL_SNAKE_AI:  

        ; Register Saving
        ST R0, ESAIR0
        ST R1, ESAIR1
        ST R2, ESAIR2
        ST R3, ESAIR3
        ST R4, ESAIR4
        ST R5, ESAIR5
        ST R6, ESAIR6
        ST R7, ESAIR7

        ; *** INSERT CODE HERE ***
        ;; ~25 lines of code or so

        ; Register Restoring
        LD R0, ESAIR0
        LD R1, ESAIR1
        LD R2, ESAIR2
        LD R3, ESAIR3
        LD R4, ESAIR4
        LD R5, ESAIR5
        LD R6, ESAIR6
        LD R7, ESAIR7

        RET

;;; ***************************************************************************

;;; PLACE_RANDOM_APPLE
;;; Register Input
;;;   None
;;; Register Output
;;;   None

PRAR0:  .FILL x0
PRAR1:  .FILL x0
PRAR2:  .FILL x0
PRAR3:  .FILL x0
PRAR4:  .FILL x0
PRAR5:  .FILL x0
PRAR6:  .FILL x0
PRAR7:  .FILL x0

; PLACE_RANDOM_APPLE local variables
LEVEL_MASK:  .FILL x1F
MAX_Y:       .FILL -30

PLACE_RANDOM_APPLE:     

        ; Register Saving
        ST R0, PRAR0
        ST R1, PRAR1
        ST R2, PRAR2
        ST R3, PRAR3
        ST R4, PRAR4
        ST R5, PRAR5
        ST R6, PRAR6
        ST R7, PRAR7

        ; *** INSERT CODE HERE ***
        ;; ~20 lines of code or so

        ; Register Restoring
        LD R0, PRAR0
        LD R1, PRAR1
        LD R2, PRAR2
        LD R3, PRAR3
        LD R4, PRAR4
        LD R5, PRAR5
        LD R6, PRAR6
        LD R7, PRAR7

        RET

;;; ***************************************************************************

;;; ADVANCE_SNAKE
;;; Register Input
;;;   r0: address of snake object
;;; Register Output
;;;   None

ASR0:   .FILL x0
ASR1:   .FILL x0
ASR2:   .FILL x0
ASR3:   .FILL x0
ASR4:   .FILL x0
ASR5:   .FILL x0
ASR6:   .FILL x0
ASR7:   .FILL x0

ADVANCE_SNAKE:  

        ; Register Saving
        ST R0, ASR0
        ST R1, ASR1
        ST R2, ASR2
        ST R3, ASR3
        ST R4, ASR4
        ST R5, ASR5
        ST R6, ASR6
        ST R7, ASR7

        ; *** INSERT CODE HERE ***
        ;; ~60 lines of code or so
        
        ; Register Restoring
        LD R0, ASR0
        LD R1, ASR1
        LD R2, ASR2
        LD R3, ASR3
        LD R4, ASR4
        LD R5, ASR5
        LD R6, ASR6
        LD R7, ASR7

        RET

;;; ***************************************************************************

;;; SNAKE DATA

GOOD_SNAKE:     
        .FILL x0000  ; HeadOff +0
        .FILL x0000  ; TailOff +1
        .FILL x4     ; GrowCount +2
        .FILL x3     ; Direction +3
        .FILL x8AA8  ; Color +4
        .FILL 20     ; Start of Position Queue +5
        .FILL 10
        .BLKW 254 ;2x128-2

EVIL_SNAKE:     
        .FILL x0000  ; HeadOff +0
        .FILL x0000  ; TailOff +1
        .FILL x4     ; GrowCount +2
        .FILL x1     ; Direction +3
        .FILL x4444  ; Color +4
        .FILL 10     ; Start of Position Queue +5
        .FILL 20
        .BLKW 254 ;2x128-2
        