;
; lightp.txt
;
; V. Crisafulli 1/20/2013
;
; 

; Shooting Stars - A game where you use the light phaser to
;                  shoot stars that fly across the screen.
;
;   

; Add sound effects. 

.sdsctag 1.01, "Shooting Stars", "Version 1.00", "VAC2013"

;---------------------------------------
; Constants 
;---------------------------------------
; This file defines constants used in the program.
; MEMORY --------------------------------------------------------------------
.DEFINE         PAGE_SIZE               $4000
.DEFINE         PAGE_0                  $0000
.DEFINE         PAGE_1                  (PAGE_0 + PAGE_SIZE)
.DEFINE         PAGE_2                  (PAGE_1 + PAGE_SIZE)
.DEFINE         PAGE_3                  (PAGE_2 + PAGE_SIZE)
.DEFINE         RAM                     $C000
.DEFINE         RAM_LEN                 $1FF8
.DEFINE         RAM_MIRROR              $E000
.DEFINE         REG_MAP_SRAM            $FFFC
.DEFINE         REG_MAP_0               $FFFD
.DEFINE         REG_MAP_1               $FFFE
.DEFINE         REG_MAP_2               $FFFF
;----------------------------------------------------------------------------

; VIDEO ---------------------------------------------------------------------
.DEFINE         VDP_DATA                $BE
.DEFINE         VDP_ADDR                $BF
.DEFINE         VDP_STATUS              $BF
.DEFINE         VRAM_TILES              $0000
.DEFINE         VRAM_BG_MAP             $3800
.DEFINE         VRAM_SPR_MAP            $3F00
.DEFINE         VRAM_SPR_LAST           208
;----------------------------------------------------------------------------
.DEFINE         VRAM_SIZE               $4000
.DEFINE         VRAM_TILE_SIZE          32            ; (8 * 8) * 4 bits = 32 bytes
;----------------------------------------------------------------------------
.DEFINE         VREG_CONFIG0            $80
.DEFINE         VREG_CONFIG1            $81
; ..
.DEFINE         VREG_BORDER_COL         $87
.DEFINE         VREG_HSCROLL            $88
.DEFINE         VREG_VSCROLL            $89
.DEFINE         VREG_LINES_CNT          $8A
;----------------------------------------------------------------------------

; INPUTS --------------------------------------------------------------------
.DEFINE         PORT_INPUT1             $DC
.DEFINE         P1_UP                   $01
.DEFINE         P1_DOWN                 $02
.DEFINE         P1_LEFT                 $04
.DEFINE         P1_RIGHT                $08
.DEFINE         P1_BUTTON1              $10
.DEFINE         P1_BUTTON2              $20
.DEFINE         P2_UP                   $40
.DEFINE         P2_DOWN                 $80
;----------------------------------------------------------------------------
.DEFINE         PORT_INPUT2             $DD
.DEFINE         P2_LEFT                 $01
.DEFINE         P2_RIGHT                $02
.DEFINE         P2_BUTTON1              $04
.DEFINE         P2_BUTTON2              $08
.DEFINE         RESET_BUTTON            $10
; Unused                                $20
.DEFINE         LIGHTGUN1               $40
.DEFINE         LIGHTGUN2               $80
;----------------------------------------------------------------------------
.DEFINE         PORT_INPUTGG            $00
.DEFINE         START_BUTTON            $80
;----------------------------------------------------------------------------

; SOUND ---------------------------------------------------------------------
.DEFINE         PORT_PSG                $7F
.DEFINE         PORT_FM_ADDR            $F0
.DEFINE         PORT_FM_DATA            $F1
.DEFINE         PORT_FM_LATCH           $F2
;----------------------------------------------------------------------------

; MISCELLANEOUS -------------------------------------------------------------
.DEFINE         PORT_NATION             $3F
.DEFINE         PORT_VLINE              $7E
.DEFINE         PORT_HLINE              $7F
;----------------------------------------------------------------------------

; HEADER --------------------------------------------------------------------
.DEFINE         HEADER                  $7FF0
.DEFINE         HEADER_ID               $7FF0 ; TMR SEGA
; ..
.DEFINE         HEADER_CHECKSUM         $7FFA
; ..
.DEFINE         HEADER_SYS_SIZE         $7FFF
;----------------------------------------------------------------------------


;------------------------------------------
; Assembler Defines
;------------------------------------------
.EMPTYFILL $00


; $0000 - $3FFF = bank 0
; $4000 - $7FFF = bank 1
; $8000 - $BFFF = bank 2 (not mapped for 32kb)
; $C000 - $FFFF = bank 3 (working RAM, not mapped)
.MEMORYMAP
   SLOTSIZE $4000
   SLOT 0 START $0000 
   SLOT 1 START $4000 
;   SLOT 2 START $8000 
   DEFAULTSLOT 0
.ENDME

.ROMBANKMAP
   BANKSTOTAL 2
   BANKSIZE $4000
   BANKS 2
.ENDRO


;------------------------------------------
; RAM, Variable Defines 
;------------------------------------------
.DEFINE     RAM_RASTER_LINE      $C000
.DEFINE     RAM_LIGHT_GUN_READ   $C001
.DEFINE     RAM_COLOR_BLINK      $C002
.DEFINE     RAM_VPOS_READ        $C003
.DEFINE     RAM_HPOS_READ        $C004
.DEFINE     GAME_STATE           $C005
.DEFINE     RAM_COLOR_TO_BLINK   $C006

.DEFINE     RAM_STAR_A_STATE     $C007
.DEFINE     RAM_STAR_B_STATE     $C008
.DEFINE     RAM_STAR_C_STATE     $C009
.DEFINE     RAM_STAR_D_STATE     $C00A
.DEFINE     RAM_STAR_E_STATE     $C00B
.DEFINE     RAM_STAR_F_STATE     $C00C
.DEFINE     RAM_STAR_G_STATE     $C00D
.DEFINE     RAM_STAR_H_STATE     $C00E
.DEFINE     RAM_STAR_I_STATE     $C00F
.DEFINE     RAM_STAR_J_STATE     $C010
.DEFINE     RAM_STAR_K_STATE     $C011
.DEFINE     RAM_STAR_L_STATE     $C012
.DEFINE     RAM_ALIEN_STATE      $C013

.DEFINE     RAM_PREV_TRIGGER     $C014
.DEFINE     RAM_COLL_X1          $C015
.DEFINE     RAM_COLL_Y1          $C016
.DEFINE     RAM_COLL_RESULT      $C017
.DEFINE     RAM_COLL_SPRITE      $C018
.DEFINE     RAM_TIMER            $C019
.DEFINE     RAM_COLL_STATE       $C01A
.DEFINE     RAM_X_BG_SCROLL      $C01B

.DEFINE     RAM_SOUND_A          $C01C
.DEFINE     RAM_SOUND_B          $C01D

.DEFINE     RAM_SOUND_ADDRESS    $C01E
.DEFINE     RAM_SOUND_DURATION   $C021
.DEFINE     RAM_SOUND_ENABLE     $C022

.DEFINE     RAM_BLINK_TBL_INDEX  $C0FF     
.DEFINE     RAM_RESTORE_COLOR    $C100
.DEFINE     RAM_VPOS_SPRITE      $C120
.DEFINE     RAM_HPOS_SPRITE      $C200
.DEFINE     RAM_TOP_TWO_ROWS     $C300
.DEFINE     RAM_SCANLINE_COLORS  $C400

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

.DEFINE     GS_TITLE             0
.DEFINE     GS_ROUND1            1
.DEFINE     GS_END_RD1           2
.DEFINE     GS_ROUND2            3
.DEFINE     GS_END_RD2           4
.DEFINE     GS_ROUND3            5
.DEFINE     GS_END_RD3           6

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



;------------------------------------------
; Page 0
;------------------------------------------

;------------------------------------------
; Main program 
;------------------------------------------

;----------------------------------------
; Vectors at $0000
.BANK 0 SLOT 0
.org $0000

;----------------------------------------
; Power up vector
.org $0000
   JP start_sms                ; Jump to start of program

;---------------------------------------
; H blank/ V blank
.org $0038
   IN a,(VDP_STATUS)           ; Acknowledge the IRQ
   CALL h_blank                ; h_blank routine
   EI                          ; Enable interrupts
   RETN                        ; End interrupt

;---------------------------------------
; Pause interrupt vector 
.org $0066
   CALL pause_routine          ; Jump to pause routine
   RETN                        ; End interrupt


;---------------------------------------
; The program starts here.
start_sms:
   DI                          ; Disable interrupts
   IM 1                        ; Set SMS interrupt mode
   LD sp,$dff0                 ; Set the stack pointer

; Initialize registers
   LD c,VDP_ADDR               ; Set c <- VDP_ADDR
   LD b,$80                    ; VDP Register
   LD hl, vdp_init_data        ; Set initialization data.
  
vdp_init_loop:
   LD a,(hl)                   ; Load data
   OUT (c), a                  ; Write to VDP
   LD a, b                     ; Load register number
   OUT (c), a                  ;

   INC hl                      ; Increment data pointer
   INC a                       ; Increment B
   LD b, a                     ;
   CP $8B                      ; Stop before 11
   JP NZ, vdp_init_loop        ; Loop

; 0 = enable, ON
; 1 = disable, OFF
; 7654 3210
; +----------- Expansion slot OFF
;  +---------- Cart slot      ON
;   +--------- Card slot      OFF
;    +-------- Work RAM       ON
;      +------ BIOS ROM       OFF
;       +----- I/O Chip       ON
;        +---- Unknown        ON
;         +--- Unknown        ON
;
; BIOS ROM leaves this data in $C000
; But Genesis does not have BIOS ROM so don't rely on it.
; $A8 is the default for SMS carts.
;
   LD a, $A8                   ; Set memory enables
   OUT ($3E), a                ;

; Set up the title screen.
; Clear RAM! SMS BIOS clears RAM, but Genesis does not.
restart_game:
   CALL tool_clear_RAM         ; Clears all RAM. Not selective.
   CALL tool_clear_sprites     ; Clear sprites.

; Game state is title screen.
   LD a, $00                   ; Turn off options
   LD (RAM_LIGHT_GUN_READ), a  ; Do not read light gun
   LD (GAME_STATE), a          ; State <- title screen
   LD (RAM_X_BG_SCROLL), a     ; No BG scroll
   LD a, $7F                   ; Turn on options
   LD (RAM_COLOR_BLINK), a     ; Do blink colors
   LD a, $0F                   ; White blinks
   LD (RAM_COLOR_TO_BLINK), a  ;

   CALL prime_pg001_sound      ; Prepare title screen sound
   CALL se_reset               ; Reset sound effects
   LD a, $00                   ;
   LD (RAM_SOUND_ENABLE), a    ; Disable sound effects

   LD hl, lightp_bg            ;
   CALL load_bg_data_00        ; Load background data
   LD hl, lightp_tile          ;
   CALL load_tile_data_comp0   ; Load tile data
   CALL load_palette_data00    ; Set palette data

   CALL tool_score_to_RAM      ; Setup score RAM
   IN a, ($DC)                 ; Read light gun 1
   LD (RAM_PREV_TRIGGER), a    ; Store previous value

; Turn on the screen
   CALL VDP_on                 ; Screen on

   EI                          ; Enable interrupts

main_loop:
   NOP
   NOP
   NOP
   JP main_loop

; VDP Register initialization data.
; This is kinda important.
vdp_init_data:
 .db $56 $00 $FF $FF $FF $FF $FB $00 $00 $00 $00

;----------------------------------------------------------
; sound_off (9 lines)
;
; Turn the sound off
;----------------------------------------------------------
sound_off:
   LD a, $9F                   ; PSG1 off
   OUT (PORT_PSG), a           ;

   LD a, $BF                   ; PSG2 off
   OUT (PORT_PSG), a           ;

   LD a, $DF                   ; PSG3 off
   OUT (PORT_PSG), a           ;

   LD a, $FF                   ; Noise off
   OUT (PORT_PSG), a           ;
   
   RET                         ; End subroutine
;---------------------------------------


;----------------------------------------------------------
; VDP_off (6 lines)
;
; Turn the screen off
;----------------------------------------------------------
VDP_off:
   LD c,VDP_ADDR               ; Write to VDP

   LD a,$80                    ; Set VDP 1 <- $80
   OUT (c),a                   ; IE  = 0
   LD a,$81                    ;
   OUT (c),a                   ;

   RET                         ;
;---------------------------------------

;----------------------------------------------------------
; VDP_on (6 lines)
;
; Turn the screen on
;
; NOTE: Interrupt occurs almost as 
;       soon as you write to register 1.
;----------------------------------------------------------
VDP_on:
   LD c,VDP_ADDR               ; Write to VDP 

; Turn on the screen
   LD a, $E0                   ; Set VDP 1 <- $E0
   OUT (c), a                  ; IE  = 1  
   LD a, $81                   ; 
   OUT (c), a                  ; 

   RET                         ;
;---------------------------------------


;------------------------------------------
;------------------------------------------
; Horizontal Line Routines 
;------------------------------------------
;------------------------------------------

;------------------------------------------
; h_blank (15 lines)
;
; This interrupt occurs each horizontal line drawn.
; On line 191, vertical blank interrupt.
;
; v_blank - Most of game takes place here
; h_light_gun_read - Read light gun info for one frame
; h_color_blink - Make the color white blink
;------------------------------------------
h_blank:
; Read and increment raster line
   IN a, ($7E)                ; Load
   LD (RAM_RASTER_LINE), a    ; Store

   CP 192                     ; Reset if last raster line
   JP NZ, h_blank_cont        ;

; If raster line is 191, perform v_blank operations
   LD a, $00                  ; Clear raster line counter
   LD (RAM_RASTER_LINE), a    ; Store
   CALL v_blank               ; Perform v_blank operations
   JP h_blank_end             ;

h_blank_cont:
; Else raster line is not 191
;    If reading light gun data, perform read
;    If on title screen, make colors blink
   LD a, (RAM_LIGHT_GUN_READ) ; Reading from light gun?
   CP $7F                     ; $7F => ON, $00 => OFF
   CALL Z, h_light_gun_read   ; 

   LD a, (RAM_COLOR_BLINK)    ; Make colors blink?
   CP $7F                     ; $7F => ON, $00 => OFF
   CALL Z, h_color_blink      ; 

h_blank_end:
   RET                        ; End subroutine


;------------------------------------------
; Handle Pause 
;------------------------------------------
pause_routine:
   RET                        ; End subroutine

;------------------------------------------
; h_light_gun_read (27 lines) 
;
; Color 1 -> 0? Light phaser sees white.
; If so,
;    Read hpos
;    Read vpos
; If raster line 191, 
;    Restore color
;    Calculate hpos
;
; NOTE: For MEKA emulator, 
;       HPOS = (most recent HPOS * 2) - 32
;       VPOS = most recent VPOS
;------------------------------------------
h_light_gun_read:
; Color 1 -> 0? Light phaser sees white.
   IN a, ($DD)                 ; Read I/O
   CP $BF                      ; 1->0 for bit 6?
   JP NZ, hlgr_next2           ; Skip if no light seen

; If so,
;    Read hpos
;    Read vpos
   IN a, ($7E)                  ; vertical position
   SUB 4                        ; a = a - 4 (center)
   LD (RAM_VPOS_READ), a        ;
   IN a, ($7F)                  ; horizontal postion  
   RLA                          ; a <- a << 1  <- a * 2
   SUB 32                       ; a <= a - 32
   SUB 4                        ; a = a - 4 (center)
   LD (RAM_HPOS_READ), a        ;
  
; If raster line 191, 
;    Restore color
;    Restore state
hlgr_next2:
   LD a, (RAM_RASTER_LINE)      ;  Line 191?
   CP 191                       ;
   JP NZ, h_light_gun_read_end  ;

   CALL tool_restore_screen     ;
   LD a, $00                    ; Clear A
   LD (RAM_LIGHT_GUN_READ), a   ; Reading for light gun is done

   LD a, (RAM_VPOS_READ)       ; Setup vpos
   LD (RAM_VPOS_SPRITE), a     ;

   LD a, (RAM_HPOS_READ)       ; Setup hpos
   LD (RAM_HPOS_SPRITE), a     ;
   LD a, $1D                   ; Tile $1D is target  
   LD (RAM_HPOS_SPRITE + 1), a ;

   LD a, $7F                   ;
   LD (RAM_SOUND_ENABLE), a    ; Enable sound effects

   CALL collision_detection_rd001 ; Did a star get hit?
   CALL collision_detection_rd002 ; Did a star get hit?
   CALL collision_detection_rd003 ; Did a star get hit?

h_light_gun_read_end: 
   RET                          ; End subroutine

;------------------------------------------
; h_color_blink (9 lines) 
;
;------------------------------------------
h_color_blink:
   LD c, VDP_ADDR               ; Setup the address
 
   LD a, (RAM_COLOR_TO_BLINK)   ; XX0F
   OUT (c), a                   ;
   LD a, $C0                    ; C0XX 
   OUT (c), a                   ;

   LD c, VDP_DATA               ; Setup the data

   LD a, (RAM_RASTER_LINE)      ; Read raster line
   OUT (c), a                   ; Write color

hcb_end:   
   RET                          ; End subroutine

;------------------------------------------
;------------------------------------------
; Tool Routines 
;------------------------------------------
;------------------------------------------

;------------------------------------------
; tool_white_screen (12 lines) 
;
; Set all colors to white ($3F)
;------------------------------------------
tool_white_screen:
   LD c, VDP_ADDR             ; Setup the address
 
   LD a, $00                  ; XX00
   OUT (c), a                 ;
   LD a, $C0                  ; C0XX 
   OUT (c), a                 ;

   LD c, VDP_DATA             ; Setup the data
   LD b, 31                   ;

tws_loop:
   LD a, $3F                  ; Set A for white color
   OUT (c), a                 ; Write to color RAM

   DEC b                      ; Loop until all color RAM is written.
   JP NZ, tws_loop            ; 
 
   RET                        ; End subroutine

;------------------------------------------
; tool_restore_screen (14 lines) 
;
; Restore colors to contents from $C100
;------------------------------------------
tool_restore_screen:
   LD c, VDP_ADDR             ; Setup the address
 
   LD a, $00                  ; XX00
   OUT (c), a                 ;
   LD a, $C0                  ; C0XX 
   OUT (c), a                 ;

   LD c, VDP_DATA             ; Setup the data
   LD b, 31                   ;

   LD hl, RAM_RESTORE_COLOR   ;

trs_loop:
   LD a, (hl)                 ; Read a color
   INC hl                     ; Increment for next read
   OUT (c), a                 ; Write to color RAM

   DEC b                      ; Loop until all color RAM is written.
   JP NZ, trs_loop            ; 
 
   RET                        ; End subroutine


;------------------------------------------
; tool_clear_RAM (8 lines)
;
; SMS BIOS clears RAM, but Genesis does not.
;------------------------------------------
tool_clear_RAM:
   LD hl, $C000               ; Set to start of RAM

tcRAM_loop:
   LD a, $00                  ; Clear A
   LD (hl), a                 ; Clear RAM byte
   INC hl                     ; Increment

   LD a, h                    ; Stop when HL is C3XX
   CP $C3                     ;
   JP NZ, tcRAM_loop          ;      

   RET                        ; End subroutine

;------------------------------------------
; tool_clear_sprites (8 lines)
;
; Show no sprites.
;------------------------------------------
tool_clear_sprites:
   LD a, $FF                   ; Low address byte
   OUT (VDP_ADDR),a            ;
   LD a, $3E                   ; High address byte
   OUT (VDP_ADDR),a            ;

   LD hl, sprite_data          ; tile_data is defined below
   LD c, VDP_DATA              ; C <- $BE;   
   LD b, 2                     ; Set up counter 
   CALL tool_copy_loop         ; Copy data from HL to C  

   LD a, $7F                   ; Low address byte
   OUT (VDP_ADDR),a            ;
   LD a, $3F                   ; High address byte
   OUT (VDP_ADDR),a            ;

   LD hl, sprite_data2         ; tile_data is defined below
   LD c, VDP_DATA              ; C <- $BE;   
   LD b, 3                     ; Set up counter 
   CALL tool_copy_loop         ; Copy data from HL to C 

   RET                        ; End subroutine

;------------------------------------------
; tool_copy_sprites (8 lines)
;
; Show no sprites.
;------------------------------------------
tool_copy_sprites:
   LD a, $FF                   ; Low address byte
   OUT (VDP_ADDR),a            ;
   LD a, $3E                   ; High address byte
   OUT (VDP_ADDR),a            ;

   LD hl, RAM_VPOS_SPRITE      ; tile_data is defined below
   LD c, VDP_DATA              ; C <- $BE;   
   LD b, 58                    ; Set up counter 
   CALL tool_copy_loop         ; Copy data from HL to C  

   LD a, $7F                   ; Low address byte
   OUT (VDP_ADDR),a            ;
   LD a, $3F                   ; High address byte
   OUT (VDP_ADDR),a            ;

   LD hl, RAM_HPOS_SPRITE      ; tile_data is defined below
   LD c, VDP_DATA              ; C <- $BE;   
   LD b, 116                   ; Set up counter 
   CALL tool_copy_loop         ; Copy data from HL to C 

   RET                        ; End subroutine

;-----------------------------------------
; tool_increment_score (54 lines)
;
;-----------------------------------------
tool_increment_score:
   LD hl, $C31E               ; Load address of digit 1.
tool_increment:
   LD a, (hl)                 ; Load digit 1

   INC a                      ; Increment digit.
   LD (hl), a                 ;

   CP $A5                     ; if 0, increment next digit.
   JP Z, tis_next1            ;

   CP $A6                     ; if above 0, goto 1.
   JP NZ, tis_end             ;
   LD a, $9C                  ;
   LD (hl), a                 ;
   JP tis_end                 ; 

tis_next1:
   DEC hl                     ; Decrement address to next digit
   DEC hl                     ;

   LD a, (hl)                 ; Load digit 1
   INC a                      ; Increment digit.
   LD (hl), a                 ;
   CP $A5                     ; if 0, increment next digit.
   JP Z, tis_next2            ;

   CP $A6                     ; if above 0, goto 1.
   JP NZ, tis_end             ;
   LD a, $9C                  ;
   LD (hl), a                 ;
   JP tis_end                 ; 

tis_next2:
   DEC hl                     ; Decrement address to next digit
   DEC hl                     ;

   LD a, (hl)                 ; Load digit 1
   INC a                      ; Increment digit.
   LD (hl), a                 ;
   CP $A5                     ; if 0, increment next digit.
   JP Z, tis_next3            ;

   CP $A6                     ; if above 0, goto 1.
   JP NZ, tis_end             ;
   LD a, $9C                  ;
   LD (hl), a                 ;
   JP tis_end                 ; 

tis_next3:
   DEC hl                     ; Decrement address to next digit
   DEC hl                     ;

   LD a, (hl)                 ; Load digit 1
   INC a                      ; Increment digit.
   LD (hl), a                 ;
   CP $A5                     ; if 0, increment next digit.
   JP Z, tis_next3            ;

   CP $A6                     ; if above 0, goto 1.
   JP NZ, tis_end             ;
   LD a, $9C                  ;
   LD (hl), a                 ;
   JP tis_end                 ; 

tis_next4:
   DEC hl                     ; Decrement address to next digit
   DEC hl                     ;

   LD a, (hl)                 ; Load digit 1
   INC a                      ; Increment digit.
   LD (hl), a                 ;
   CP $A5                     ; if 0, increment next digit.
   JP Z, tis_next5            ;

   CP $A6                     ; if above 0, goto 1.
   JP NZ, tis_end             ;
   LD a, $9C                  ;
   LD (hl), a                 ;
   JP tis_end                 ; 

tis_next5:
   DEC hl                     ; Decrement address to next digit
   DEC hl                     ;

   LD a, (hl)                 ; Load digit 1
   INC a                      ; Increment digit.
   LD (hl), a                 ;
   CP $A5                     ; if 0, increment next digit.
   JP Z, tis_end              ;

   CP $A6                     ; if above 0, goto 1.
   JP NZ, tis_end             ;
   LD a, $9C                  ;
   LD (hl), a                 ;
   JP tis_end                 ; 

tis_end:
   RET                        ; End subroutine

;-----------------------------------------
; tool_increment_goal (3 lines)
;
;-----------------------------------------
tool_increment_goal:
   LD hl, $C35E               ; Load address of goal.
   CALL tool_increment        ; Increment goal

   RET                        ; End subroutine

;-----------------------------------------
; tool_increment_goal_10 (3 lines)
;
;-----------------------------------------
tool_increment_goal_10:
   LD hl, $C35C               ; Load address of goal.
   CALL tool_increment        ; Increment goal

   RET                        ; End subroutine

;-----------------------------------------
; tool_decrement_time (36 lines)
;
;-----------------------------------------
tool_decrement_time:
   LD hl, $C334               ; Load address of time.
   LD a, (hl)                 ; Load
   CP $9C                     ; 1 -> 0
   JP NZ, tdt_skip1           ;
   LD a, $A5                  ;
   LD (hl), a                 ;
   JP tdt_end                 ;
  
tdt_skip1:
   DEC a                      ; Decrement
   LD (hl), a                 ; Store
   CP $A4                     ; Decrement next digit?
   JP NZ, tdt_end             ;

   DEC hl                     ; Look at next digit
   DEC hl                     ;

   LD a, (hl)                 ; Load
   CP $9C                     ; 1 -> 0
   JP NZ, tdt_skip2           ;
   LD a, $A5                  ;
   LD (hl), a                 ;
   JP tdt_end                 ;
  
tdt_skip2:
   DEC a                      ; Decrement
   LD (hl), a                 ; Store
   CP $A4                     ; Decrement next digit?
   JP NZ, tdt_end             ;

   DEC hl                     ; Look at next digit
   DEC hl                     ;

   LD a, (hl)                 ; Load
   CP $9C                     ; 1 -> 0
   JP NZ, tdt_skip3           ;
   LD a, $A5                  ;
   LD (hl), a                 ;
   JP tdt_end                 ;
  
tdt_skip3:
   DEC a                      ; Decrement
   LD (hl), a                 ; Store

tdt_end:
   RET                        ; End subroutine

;-----------------------------------------
; tool_increment_round (3 lines)
;
;-----------------------------------------
tool_increment_round:
   LD hl, $C374               ; Round starting address
   CALL tool_increment        ; Increment goal

   RET                        ; End subroutine

;-----------------------------------------
; tool_score_to_RAM (10 lines)
;
; Copy score from BG to RAM
;-----------------------------------------
tool_score_to_RAM:
   LD hl, lightp_bg001_bg     ; Source
   LD de, RAM_TOP_TWO_ROWS    ; Destination
   LD b, 128                  ; Copy two rows

tstr_loop:
   LD a, (hl)                 ; Load 
   LD (de), a                 ; Store
   INC hl                     ; Increment
   INC de                     ;
   DEC b                      ;
   JP NZ, tstr_loop           ;
   
   RET                        ; End subroutine 

;-----------------------------------------
; tool_score_to_VRAM (10 lines)
;
;-----------------------------------------
tool_score_to_VRAM:
   LD c, VDP_ADDR             ; Setup the address
 
   LD a, $FF                  ; XXFF
   OUT (c), a                 ;
   LD a, $37                  ; 37XX 
   OUT (c), a                 ;

   LD c, VDP_DATA             ; Setup the data
   LD e, 2                    ; 2 rows

   LD hl, RAM_TOP_TWO_ROWS    ; Source
   CALL bg00_loop             ;

   RET                        ; End subroutine 

;-----------------------------------------
; tool_sprites_to_RAM (7 lines)
;
; Copy sprites from BG to RAM
; Load hl with source
; Load de with destination
; Load b with size
;-----------------------------------------
tool_sprites_to_RAM:
   LD a, (hl)                 ; Load 
   LD (de), a                 ; Store
   INC hl                     ; Increment
   INC de                     ;
   DEC b                      ;
   JP NZ, tool_sprites_to_RAM ;
   
   RET                        ; End subroutine 

;-----------------------------------------
; tool_tiles_to_RAM (8 lines)
;
; Copy tiles from ROM to RAM
; Load hl with source
; Load de with destination
; Load b with size
;-----------------------------------------
tool_tiles_to_RAM:
   LD a, (hl)                 ; Load 
   LD (de), a                 ; Store
   INC hl                     ; Increment
   INC de                     ;
   INC de                     ;
   DEC b                      ;
   JP NZ, tool_tiles_to_RAM   ;
   
   RET                        ; End subroutine 


;------------------------------------------
;------------------------------------------
; Vertical Blank Routines 
;------------------------------------------
;------------------------------------------

;------------------------------------------
; v_blank (28 lines) 
;
; Handle state machine
; Get d-pad input (if connected)
; If trigger is pulled, 
;    setup to read trigger input.
;------------------------------------------
v_blank:
; Handle changes in state
   CALL game_state_machine     ; Run the game
   CALL get_dpad_input         ; Get dpad input

; When the light phaser trigger is pressed,
;    Turn the screen white 
;    Start reading light gun info
   LD a, (RAM_PREV_TRIGGER)    ; Load previous value
   AND $10                     ; Mask unwanted bits
   CP $10                      ; Detect 1 -> 0
   JP NZ, vb_skip2             ; Skip if trigger was depressed

   IN a, ($DC)                 ; Read light gun 1
   AND $10                     ; Mask unwanted bits
   CP $10                      ; Detect 1 -> 0
   JP Z, vb_skip2              ; Skip if trigger is off

   CALL tool_white_screen      ; Trun screen white
   LD a, $7F                   ; Turn on read routine
   LD (RAM_LIGHT_GUN_READ), a  ;
   LD a, $00                   ; Turn on options
   LD (RAM_COLOR_BLINK), a     ; Do not blink colors

; Place sprite 0 into light gun coordinates.
   LD a, (RAM_VPOS_READ)       ; Setup vpos
   LD (RAM_VPOS_SPRITE), a     ;

   LD a, (RAM_HPOS_READ)       ; Setup hpos
   LD (RAM_HPOS_SPRITE), a     ;
   LD a, $1D                   ; Tile $1D is target  
   LD (RAM_HPOS_SPRITE + 1), a ;

; If title screen, start level 1.
   LD a, (GAME_STATE)          ;
   CP $00                      ; Title screen
   JP NZ, vb_skip2             ;
   INC a                       ; Set state to 1
   LD (GAME_STATE), a          ;
   CALL gsm_load_round_1       ; Setup round 1

vb_skip2:
   CALL tool_copy_sprites      ; Setup sprites

   IN a, ($DC)                 ; Read light gun 1
   LD (RAM_PREV_TRIGGER), a    ; Store previous value

   RET                         ; End subroutine

sprite_data:
 .db $00, $D0
sprite_data2:
 .db $00, $00, $D0

;-----------------------------------------
; get_dpad_input (36 lines)
;
; If the D-pad is connected, 
; move the target.
;-----------------------------------------
get_dpad_input:
; If directional pad is pressed, change coordinates.
   IN a, ($DC)                 ; Read light gun 1 
   AND $01                     ; Mask unwanted bits
   CP $00                      ;
   JP NZ, vb_skip_up           ;

   LD a, (RAM_VPOS_SPRITE)     ; Go up with d-pad
   DEC a                       ;
   DEC a                       ;
   LD (RAM_VPOS_SPRITE), a     ; 
   LD (RAM_VPOS_READ), a       ; 

vb_skip_up:
   IN a, ($DC)                 ; Read light gun 1 
   AND $02                     ; Mask unwanted bits
   CP $00                      ;
   JP NZ, vb_skip_down         ;

   LD a, (RAM_VPOS_SPRITE)     ; Go down with d-pad
   INC a                       ;
   INC a                       ;
   LD (RAM_VPOS_SPRITE), a     ; 
   LD (RAM_VPOS_READ), a       ; 

vb_skip_down:
   IN a, ($DC)                 ; Read light gun 1 
   AND $04                     ; Mask unwanted bits
   CP $00                      ;
   JP NZ, vb_skip_left         ;

   LD a, (RAM_HPOS_SPRITE)     ; Go left with d-pad
   DEC a                       ;
   DEC a                       ;
   LD (RAM_HPOS_SPRITE), a     ; 
   LD (RAM_HPOS_READ), a       ; 

vb_skip_left:
   IN a, ($DC)                 ; Read light gun 1 
   AND $08                     ; Mask unwanted bits
   CP $00                      ;
   JP NZ, vb_skip_right        ;

   LD a, (RAM_HPOS_SPRITE)     ; Go left with d-pad
   INC a                       ;
   INC a                       ;
   LD (RAM_HPOS_SPRITE), a     ; 
   LD (RAM_HPOS_READ), a       ; 

vb_skip_right:
   RET                         ; End subroutine

;-----------------------------------------
; set_timer_030 (6 lines)
;
; Set timer to 30 seconds
;-----------------------------------------
set_timer_030:
   LD a, $9E                   ; Digit 3
   LD ($C332), a               ;

   LD a, $A5                   ; Digit 0
   LD ($C330), a               ;
   LD ($C334), a               ;

   RET                         ; End subroutine

;-----------------------------------------
; set_timer_010 (6 lines)
;
; Set timer to 10 seconds
;-----------------------------------------
set_timer_010:
   LD a, $9C                   ; Digit 1
   LD ($C332), a               ;

   LD a, $A5                   ; Digit 0
   LD ($C330), a               ;
   LD ($C334), a               ;

   RET                         ; End subroutine

;-----------------------------------------
; run_timer (22 lines)
;
; 60 frames = 1 second
; Stop round when time is 000.
;-----------------------------------------
run_timer:
   LD hl, RAM_TIMER            ; Increment timer
   INC (hl)                    ;
 
   LD a, (hl)                  ; 60 frames = 1 second
   CP 60                       ;
   JP NZ, run_timer_end        ;

   LD a, $00                   ; Clear frame counter
   LD (hl), a                  ;
   CALL tool_decrement_time    ; Decrement by 1 second

   LD a, ($C330)               ; 
   CP $A5                      ; 3 digit 0?
   JP NZ, run_timer_end        ;
   LD a, ($C332)               ; 
   CP $A5                      ; 2 digit 0?
   JP NZ, run_timer_end        ;
   LD a, ($C334)               ; 
   CP $A5                      ; 1 digit 0?
   JP NZ, run_timer_end        ;
 
   LD a, (GAME_STATE)          ; Read current state 
   INC a                       ; Set game state to next round
   LD (GAME_STATE), a          ;

   CALL game_over_or_congrats  ; GAME OVER or G O A L ?
   CALL set_timer_010          ;

run_timer_end:
   RET                         ; End subroutine

;-----------------------------------------
; run_timer2 (41 lines)
;
; 60 frames = 1 second
; Stop round when time is 000.
;-----------------------------------------
run_timer2:
   LD a, (RAM_X_BG_SCROLL)     ; Scroll BG
   INC a                       ;
   LD (RAM_X_BG_SCROLL), a     ;

   LD hl, RAM_TIMER            ; Increment timer
   INC (hl)                    ;
 
   LD a, (hl)                  ; 60 frames = 1 second
   CP 60                       ;
   JP NZ, run_timer_end2       ;

   LD a, $00                   ; Clear frame counter
   LD (hl), a                  ;
   CALL tool_decrement_time    ; Decrement by 1 second

   LD a, ($C330)               ; 
   CP $A5                      ; 3 digit 0?
   JP NZ, run_timer_end2       ;
   LD a, ($C332)               ; 
   CP $A5                      ; 2 digit 0?
   JP NZ, run_timer_end2       ;
   LD a, ($C334)               ; 
   CP $A5                      ; 1 digit 0?
   JP NZ, run_timer_end2       ;
 
   LD a, (GAME_STATE)          ; Read current state 
   INC a                       ; Set game state to next round
   LD (GAME_STATE), a          ;

   CP $0D                      ; Maximum game state?
   JP NZ, rt2_skip1            ;
   LD a, $01                   ; Reset game state
   LD (GAME_STATE), a          ;
   CALL tool_increment_goal_10 ; 
   CALL tool_increment_goal_10 ; Add 20 to goal for lapping game
rt2_skip1:
   LD a, ($C205)               ; g_A_me over or g_O_al?
   CP $82                      ; equals _A_
   JP NZ, rt2_next_rd          ;
  
   CALL VDP_off                ; Turn VDP off
   CALL restart_game           ; Reload the title screen
   JP run_timer_end2           ;

rt2_next_rd:
   LD a, (GAME_STATE)          ; Read current state 
   CP $0B                      ; Load round 6?
   CALL Z, gsm_load_round_6    ;
   LD a, (GAME_STATE)          ; Read current state 
   CP $09                      ; Load round 5?
   CALL Z, gsm_load_round_5    ;
   LD a, (GAME_STATE)          ; Read current state 
   CP $07                      ; Load round 4?
   CALL Z, gsm_load_round_4    ;
   LD a, (GAME_STATE)          ; Read current state 
   CP $05                      ; Load round 3?
   CALL Z, gsm_load_round_3    ;
   LD a, (GAME_STATE)          ; Read current state 
   CP $03                      ; Load round 2?
   CALL Z, gsm_load_round_2    ;
   LD a, (GAME_STATE)          ; Read current state 
   CP $01                      ; Load round 1?
   CALL Z, gsm_load_round_1    ;

run_timer_end2:
   RET                         ; End subroutine

;-----------------------------------------
; game_state_machine ( lines)
;
;-----------------------------------------
game_state_machine:
   LD a, (GAME_STATE)          ; Load the game state.
   CP $00                      ;
   JP Z, gsm_title_screen      ; 0 == title screen
   CP $01                      ;
   JP Z, gsm_round_001         ; 1 == round 001
   CP $02                      ;
   JP Z, gsm_end_of_round      ; 2 == game over or qualify
   CP $03                      ;
   JP Z, gsm_round_002         ; 3 == round 002
   CP $04                      ;
   JP Z, gsm_end_of_round      ; 4 == game over or qualify
   CP $05                      ;
   JP Z, gsm_round_003         ; 5 == round 003
   CP $06                      ;
   JP Z, gsm_end_of_round      ; 6 == game over or qualify
   CP $07                      ;
   JP Z, gsm_round_004         ; 7 == round 004
   CP $08                      ;
   JP Z, gsm_end_of_round      ; 8 == game over or qualify
   CP $09                      ;
   JP Z, gsm_round_005         ; 9 == round 005
   CP $0A                      ;
   JP Z, gsm_end_of_round      ; 10 == game over or qualify
   CP $0B                      ;
   JP Z, gsm_round_006         ; 11 == round 006
   CP $0C                      ;
   JP Z, gsm_end_of_round      ; 12 == game over or qualify

   JP gsm_end                  ; Jump to end if invalid state

; Title screen
; If player pulls trigger, go to round 1.
gsm_title_screen:
;   CALL pg001_sound            ; Play title music.

   LD a, (RAM_COLOR_BLINK)     ; If color blink is off, advance to next stage.
   CP $00                      ;
   JP NZ, gsm_end              ; Skip if still in title screen

gsm_load_round_1:
   CALL VDP_off                ; Turn off screen

   CALL sound_off              ; Turn off sound

   LD hl, lightp_sp001_tile    ; 
   CALL load_tile_data_comp0   ; Load tile data

   LD hl, lightp_bg001_tile    ; 
   CALL load_tile_data_100     ; Load bg tile data at $2000 (tile $100)

   LD hl, lightp_bg001_bg      ;
   CALL load_bg_data_00        ; Load background data 

   CALL load_palette_data00    ; Set palette data

   LD hl, round_one_vpos       ;
   LD de, RAM_VPOS_SPRITE      ;
   LD b, 58
   CALL tool_sprites_to_RAM    ; Copy sprites to RAM

   LD hl, round_one_hpos       ;
   LD de, RAM_HPOS_SPRITE      ;
   LD b, 116
   CALL tool_sprites_to_RAM    ; Copy sprites to RAM

   LD a, $00                   ; No blinking
   LD (RAM_COLOR_BLINK), a     ;

   CALL set_timer_030          ; Set timer
   CALL tool_increment_goal_10 ;
   CALL tool_increment_goal_10 ; Goal = Goal + 20
   CALL tool_increment_round   ; Set round number 

   CALL clear_foe_states       ; Clear foe state machines
   
   CALL VDP_on                 ; Turn on VDP. Immediate interrupt is likely to occur.

   JP gsm_end                  ; Jump to end when done.

; Round 1 - Shoot big stars.
gsm_round_001:
   CALL tool_score_to_VRAM     ; Copy score from working RAM to VRAM
   CALL move_round_001_foes    ; Move the stars
   CALL round_001_star_respawn ;
   CALL round_001_star_blink   ; Make sprites blink
   CALL run_timer              ; Run the timer

   JP gsm_end                  ; Jump to end when done.

; Round 2 - Shoot little stars
gsm_round_002:
   CALL tool_score_to_VRAM     ; Copy score from working RAM to VRAM
   CALL move_round_002_foes    ;
   CALL run_timer              ; Run the timer

   JP gsm_end                  ; Jump to end when done.

; Round 3 - Aliens
gsm_round_003:
   CALL tool_score_to_VRAM     ; Copy score from working RAM to VRAM
   CALL move_round_003_foes    ; Move the stars
   CALL round_003_star_respawn ;
   CALL round_003_star_blink   ; Make sprites blink
   CALL run_timer              ; Run the timer

   JP gsm_end                  ; Jump to end when done.

; Round 4 - Shoot big stars.
gsm_round_004:
   CALL tool_score_to_VRAM     ; Copy score from working RAM to VRAM
   CALL move_round_001_foes    ; Move the stars
   CALL move_round_001_foes    ; Move the stars
   CALL round_001_star_respawn ;
   CALL round_001_star_blink   ; Make sprites blink
   CALL run_timer              ; Run the timer

   LD a, $7F                   ; Turn on options
   LD (RAM_COLOR_BLINK), a     ; Do blink colors
   LD a, $0E                   ; Cyan blinks
   LD (RAM_COLOR_TO_BLINK), a  ;

   JP gsm_end                  ; Jump to end when done.

; Round 5 - Aliens
gsm_round_005:
   CALL tool_score_to_VRAM     ; Copy score from working RAM to VRAM
   CALL move_round_003_foes    ; Move the stars
   CALL move_round_003_foes    ; Move the stars
   CALL round_003_star_respawn ;
   CALL round_003_star_blink   ; Make sprites blink
   CALL run_timer              ; Run the timer

   JP gsm_end                  ; Jump to end when done.

; Round 2 - Shoot little stars
gsm_round_006:
   CALL tool_score_to_VRAM     ; Copy score from working RAM to VRAM
   CALL move_round_002_foes    ;
   CALL run_timer              ; Run the timer

   JP gsm_end                  ; Jump to end when done.

; End of round - Get qualify message or game over message?
gsm_end_of_round:            
   CALL tool_score_to_VRAM     ; Copy score from working RAM to VRAM
   CALL run_timer2             ; Run the timer

gsm_end:
   CALL sound_effects          ; Play sound effects
   RET                         ; End subroutine

;------------------------------------------
; clear_foe_states (17 lines)
;
;------------------------------------------
clear_foe_states:
   LD a, $00                   ; Clear
   LD (RAM_STAR_A_STATE), a    ;
   LD (RAM_STAR_B_STATE), a    ;
   LD (RAM_STAR_C_STATE), a    ;
   LD (RAM_STAR_D_STATE), a    ;
   LD (RAM_STAR_E_STATE), a    ;
   LD (RAM_STAR_F_STATE), a    ;
   LD (RAM_STAR_G_STATE), a    ;
   LD (RAM_STAR_H_STATE), a    ;
   LD (RAM_STAR_I_STATE), a    ;
   LD (RAM_STAR_J_STATE), a    ;
   LD (RAM_STAR_K_STATE), a    ;
   LD (RAM_STAR_L_STATE), a    ;
   LD (RAM_ALIEN_STATE), a     ;

   RET                         ; End subroutine


;-----------------------------------------
; Round 1 routines
;-----------------------------------------

;-----------------------------------------
; move_sprites_hl_dist_b_right (8 lines)
;
; Move sprites stored in worinkg RAM.
; hl = start address
; b = number of sprites
;-----------------------------------------
move_sprites_hl_dist_b_right:
   LD a, (hl)                  ; Load
   INC a                       ; a <- a + 1
   LD (hl), a                  ; Store

   INC hl                      ; Go to next sprite
   INC hl                      ;

   DEC b                       ; Decrement counter
   JP NZ, move_sprites_hl_dist_b_right ;

   RET                         ; End subroutine

;-----------------------------------------
; move_sprites_hl_dist_b_left (8 lines)
;
; Move sprites stored in worinkg RAM.
; hl = start address
; b = number of sprites
;-----------------------------------------
move_sprites_hl_dist_b_left:
   LD a, (hl)                  ; Load
   DEC a                       ; a <- a + 1
   LD (hl), a                  ; Store

   INC hl                      ; Go to next sprite
   INC hl                      ;

   DEC b                       ; Decrement counter
   JP NZ, move_sprites_hl_dist_b_left ;

   RET                         ; End subroutine

;-----------------------------------------
; move_sprites_hl_dist_b_up (7 lines)
;
; Move sprites stored in worinkg RAM.
; hl = start address
; b = number of sprites
;-----------------------------------------
move_sprites_hl_dist_b_up:
   LD a, (hl)                  ; Load
   DEC a                       ; a <- a + 1
   LD (hl), a                  ; Store

   INC hl                      ; Go to next sprite

   DEC b                       ; Decrement counter
   JP NZ, move_sprites_hl_dist_b_up ;

   RET                         ; End subroutine

;-----------------------------------------
; move_sprites_hl_dist_b_down (7 lines)
;
; Move sprites stored in worinkg RAM.
; hl = start address
; b = number of sprites
;-----------------------------------------
move_sprites_hl_dist_b_down:
   LD a, (hl)                  ; Load
   INC a                       ; a <- a + 1
   LD (hl), a                  ; Store

   INC hl                      ; Go to next sprite

   DEC b                       ; Decrement counter
   JP NZ, move_sprites_hl_dist_b_down ;

   RET                         ; End subroutine

;-----------------------------------------
; move_round_001_foes (43 lines)
;
; RAM_STAR_A_STATE
; RAM_STAR_B_STATE
; RAM_STAR_C_STATE
; RAM_STAR_D_STATE
;
; RAM_STAR_E_STATE
; RAM_STAR_F_STATE
; RAM_STAR_G_STATE
; RAM_STAR_H_STATE
;
; RAM_STAR_I_STATE
; RAM_STAR_J_STATE
; RAM_STAR_K_STATE
; RAM_STAR_L_STATE
;
; RAM_ALIEN_STATE
;
;-----------------------------------------
move_round_001_foes:
;------------------
   LD a, (RAM_ALIEN_STATE)     ; Alien 
   CP $7F                      ; 
   JP Z, rd001_down1           ;

   LD hl, $C262                ; Move alien
   LD b, 8                     ; 8 sprites
   CALL move_sprites_hl_dist_b_right ; Go right
   LD hl, $C262                ; Move alien
   LD b, 8                     ; 8 sprites
   CALL move_sprites_hl_dist_b_right ; Go right
   JP rd001_starA              ;

rd001_down1:
   LD hl, $C151                ; Move alien
   LD b, 8                     ; 8 sprites
   CALL move_sprites_hl_dist_b_down ; Go right

;------------------
rd001_starA:
   LD a, (RAM_STAR_A_STATE)    ; Star A
   CP $7F                      ; 
   JP Z, rd001_down2           ;

   LD hl, $C202                ; Move star
   LD b, 16                    ; 8 sprites
   CALL move_sprites_hl_dist_b_left ; Go left
   JP rd001_starE              ;

rd001_down2:
   LD hl, $C121                ; Move star
   LD b, 16                    ; 8 sprites
   CALL move_sprites_hl_dist_b_down ; Go down

;------------------
rd001_starE:
   LD a, (RAM_STAR_E_STATE)    ; Star E
   CP $7F                      ; 
   JP Z, rd001_down3           ;

   LD hl, $C222                ; Move star
   LD b, 16                    ; 8 sprites
   CALL move_sprites_hl_dist_b_right ; Go right
   JP rd001_starI              ;

rd001_down3:
   LD hl, $C131                ; Move star
   LD b, 16                    ; 8 sprites
   CALL move_sprites_hl_dist_b_down ; Go down

;------------------
rd001_starI:
   LD a, (RAM_STAR_I_STATE)    ; Star E
   CP $7F                      ; 
   JP Z, rd001_down4           ;

   LD hl, $C242                ; Move star
   LD b, 16                    ; 8 sprites
   CALL move_sprites_hl_dist_b_left ; Go left
   JP rd001_star_end           ;

rd001_down4:
   LD hl, $C141                ; Move star
   LD b, 16                    ; 8 sprites
   CALL move_sprites_hl_dist_b_down ; Go down

rd001_star_end:
   RET                         ; End subroutine

;------------------------------------------------
; collision_detection_rd001 (52 lines)
;
;------------------------------------------------
collision_detection_rd001:
   LD a, (GAME_STATE)          ; Round 1?
   CP $01                      ;
   JP Z, cldt_okusa            ; Skip 
   CP $07                      ;
   JP Z, cldt_okusa            ; Skip 

   JP cldt_skip4               ; Skip unless round 1, 4

cldt_okusa:
; Star A, B, C, D
; Use star A
   LD a, (RAM_STAR_A_STATE)    ;
   LD (RAM_COLL_STATE), a      ; Pass state machine value
   LD a, ($C121)               ; Y
   LD (RAM_COLL_Y1), a         ;
   LD a, ($C202)               ; X
   LD (RAM_COLL_X1), a         ;
   CALL xy_collision_detect    ; Detect collision
   
   LD a, (RAM_COLL_RESULT)     ; If collision change state
   CP $7F                      ;
   JP NZ, cdrd001_star_e       ;
   LD a, $7F                   ;
   LD (RAM_STAR_A_STATE), a    ;

; Star E, F, G, H
; Use star E
cdrd001_star_e:
   LD a, (RAM_STAR_E_STATE)    ;
   LD (RAM_COLL_STATE), a      ; Pass state machine value
   LD a, ($C131)               ; Y
   LD (RAM_COLL_Y1), a         ;
   LD a, ($C222)               ; X
   LD (RAM_COLL_X1), a         ;
   CALL xy_collision_detect    ; Detect collision
   
   LD a, (RAM_COLL_RESULT)     ; If collision change state
   CP $7F                      ;
   JP NZ, cdrd001_star_i       ;
   LD a, $7F                   ;
   LD (RAM_STAR_E_STATE), a    ;

; Star I, J, K, L
; Use star I
cdrd001_star_i:
   LD a, (RAM_STAR_I_STATE)    ;
   LD (RAM_COLL_STATE), a      ; Pass state machine value
   LD a, ($C141)               ; Y
   LD (RAM_COLL_Y1), a         ;
   LD a, ($C242)               ; X
   LD (RAM_COLL_X1), a         ;
   CALL xy_collision_detect    ; Detect collision
   
   LD a, (RAM_COLL_RESULT)     ; If collision change state
   CP $7F                      ;
   JP NZ, cdrd001_alien        ;
   LD a, $7F                   ;
   LD (RAM_STAR_I_STATE), a    ;

; Alien
cdrd001_alien:
   LD a, (RAM_ALIEN_STATE)     ;
   LD (RAM_COLL_STATE), a      ; Pass state machine value
   LD a, ($C151)               ; Y
   LD (RAM_COLL_Y1), a         ;
   LD a, ($C262)               ; X
   LD (RAM_COLL_X1), a         ;
   CALL xy_collision_detect    ; Detect collision
   
   LD a, (RAM_COLL_RESULT)     ; If collision change state
   CP $7F                      ;
   JP NZ, cldt_skip4           ;
   LD a, $7F                   ;
   LD (RAM_ALIEN_STATE), a     ;

cldt_skip4:    
   RET                         ; End subroutine
 
;-----------------------------------------
; xy_collision_detect (23 lines)
;
; RAM_COLL_X1     = x1
; RAM_COLL_Y1     = y1
; RAM_COLL_RESULT = result, $00 => miss, $01 => hit
;
; Is (x2,y2) within 32x32 box with
; top corner at (x1,y1)?
;
;-----------------------------------------
xy_collision_detect:
   LD a, (RAM_COLL_STATE)      ; Don't check if already hit!
   CP $7F                      ;
   JP Z, xycd_end              ;

   LD a, $00                   ; Assume miss until hit
   LD (RAM_COLL_RESULT), a     ;

   LD a, (RAM_COLL_Y1)         ; y1
   LD b, a                     ;
   LD a, ($C120)               ; y2
   SUB b                       ; a = y2 - y1
   AND $E0                     ; mask unwanted bits
   CP $00                      ; If difference is less than 32 pixels, declare hit
   JP NZ, xycd_end             ;

   LD a, (RAM_COLL_X1)         ; x1
   LD b, a                     ;
   LD a, ($C200)               ; x2
   SUB b                       ; a = x2 - x1
   AND $E0                     ; mask unwanted bits
   CP $00                      ; If difference is less than 32 pixels, declare hit
   JP NZ, xycd_end             ;

   LD a, $7F                   ; Proven hit
   LD (RAM_COLL_RESULT), a     ;

   CALL tool_increment_score   ; Add to the score

xycd_end: 
   RET                         ; End subroutine

;-----------------------------------------
; round_001_star_respawn (42 lines)
; 
;-----------------------------------------
round_001_star_respawn:
; A B C D big stars?
   LD a, ($C121)               ; Too low?
   CP $E0                      ;
   JP NZ, r001sr1              ;

   LD a, $00                   ; Clear hit detection
   LD (RAM_STAR_A_STATE), a    ;

   LD hl, round_one_vpos + 1   ; Source
   LD de, $C121                ; Destination
   LD b, 16
   CALL tool_sprites_to_RAM    ; Copy
   LD hl, round_one_hpos + 2   ; Source
   LD de, $C202                ; Destination
   LD b, 32
   CALL tool_sprites_to_RAM    ; Copy

; E F G H big stars?
r001sr1:
   LD a, ($C131)               ; Too low?
   CP $E0                      ;
   JP NZ, r001sr2              ;

   LD a, $00                   ; Clear hit detection
   LD (RAM_STAR_E_STATE), a    ;

   LD hl, round_one_vpos + 17  ; Source
   LD de, $C131                ; Destination
   LD b, 16
   CALL tool_sprites_to_RAM    ; Copy
   LD hl, round_one_hpos + 34  ; Source
   LD de, $C222                ; Destination
   LD b, 32
   CALL tool_sprites_to_RAM    ; Copy

; I J K L big stars?
r001sr2:
   LD a, ($C141)               ; Too low?
   CP $E0                      ;
   JP NZ, r001sr3              ;

   LD a, $00                   ; Clear hit detection
   LD (RAM_STAR_I_STATE), a    ;

   LD hl, round_one_vpos + 33  ; Source
   LD de, $C141                ; Destination
   LD b, 16
   CALL tool_sprites_to_RAM    ; Copy
   LD hl, round_one_hpos + 66  ; Source
   LD de, $C242                ; Destination
   LD b, 32
   CALL tool_sprites_to_RAM    ; Copy

; Alien respawn?
r001sr3:
   LD a, ($C151)               ; Too low?
   CP $E0                      ;
   JP NZ, r001sr4              ;

   LD a, $00                   ; Clear hit detection
   LD (RAM_ALIEN_STATE), a     ;

   LD hl, round_one_vpos + 49  ; Source
   LD de, $C151                ; Destination
   LD b, 8
   CALL tool_sprites_to_RAM    ; Copy
   LD hl, round_one_hpos + 98  ; Source
   LD de, $C262                ; Destination
   LD b, 16
   CALL tool_sprites_to_RAM    ; Copy

r001sr4:  
   RET                         ; End subroutine

;-----------------------------------------
; round_001_star_blink (83 lines)
;
;-----------------------------------------
round_001_star_blink:
   LD a, (RAM_TIMER)           ; Load timer
   AND $30                     ; Mask unwanted bits
   CP $00                      ;
   JP Z, rd001sb_blink1        ; Blink 1
   CP $10                      ;
   JP Z, rd001sb_blink2        ; Blink 2
   CP $20                      ;
   JP Z, rd001sb_blink3        ; Blink 3
   CP $30                      ;
   JP Z, rd001sb_blink4        ; Blink 4

rd001sb_blink1:
   LD hl, big_star_tiles_1     ;
   LD de, $C203                ; Tiles
   LD b, 16                    ; 16 sprites
   CALL tool_tiles_to_RAM      ; Copy tiles to working RAM
   LD hl, big_star_tiles_2     ;
   LD de, $C223                ; Tiles
   LD b, 16                    ; 16 sprites
   CALL tool_tiles_to_RAM      ; Copy tiles to working RAM
   LD hl, big_star_tiles_3     ;
   LD de, $C243                ; Tiles
   LD b, 16                    ; 16 sprites
   CALL tool_tiles_to_RAM      ; Copy tiles to working RAM
   JP rd001sb_end              ;

rd001sb_blink2:
   LD hl, big_star_tiles_3     ;
   LD de, $C203                ; Tiles
   LD b, 16                    ; 16 sprites
   CALL tool_tiles_to_RAM      ; Copy tiles to working RAM
   LD hl, big_star_tiles_1     ;
   LD de, $C223                ; Tiles
   LD b, 16                    ; 16 sprites
   CALL tool_tiles_to_RAM      ; Copy tiles to working RAM
   LD hl, big_star_tiles_2     ;
   LD de, $C243                ; Tiles
   LD b, 16                    ; 16 sprites
   CALL tool_tiles_to_RAM      ; Copy tiles to working RAM
   JP rd001sb_end              ;

rd001sb_blink3:
   LD hl, big_star_tiles_2     ;
   LD de, $C203                ; Tiles
   LD b, 16                    ; 16 sprites
   CALL tool_tiles_to_RAM      ; Copy tiles to working RAM
   LD hl, big_star_tiles_3     ;
   LD de, $C223                ; Tiles
   LD b, 16                    ; 16 sprites
   CALL tool_tiles_to_RAM      ; Copy tiles to working RAM
   LD hl, big_star_tiles_1     ;
   LD de, $C243                ; Tiles
   LD b, 16                    ; 16 sprites
   CALL tool_tiles_to_RAM      ; Copy tiles to working RAM
   JP rd001sb_end              ;

rd001sb_blink4:
   LD hl, big_star_tiles_1     ;
   LD de, $C203                ; Tiles
   LD b, 16                    ; 16 sprites
   CALL tool_tiles_to_RAM      ; Copy tiles to working RAM
   LD hl, big_star_tiles_3     ;
   LD de, $C223                ; Tiles
   LD b, 16                    ; 16 sprites
   CALL tool_tiles_to_RAM      ; Copy tiles to working RAM
   LD hl, big_star_tiles_1     ;
   LD de, $C243                ; Tiles
   LD b, 16                    ; 16 sprites
   CALL tool_tiles_to_RAM      ; Copy tiles to working RAM

;---------------------------------
rd001sb_end:
   LD hl, big_star_XX          ;
   LD de, $C203                ; Tiles
   LD b, 16                    ; 16 sprites
   LD a, (RAM_STAR_A_STATE)    ; Load doom sprite?
   CP $7F                      ;
   CALL Z, tool_tiles_to_RAM   ; Copy tiles to working RAM

   LD hl, big_star_XX          ;
   LD de, $C223                ; Tiles
   LD b, 16                    ; 16 sprites
   LD a, (RAM_STAR_E_STATE)    ; Load doom sprite?
   CP $7F                      ;
   CALL Z, tool_tiles_to_RAM   ; Copy tiles to working RAM

   LD hl, big_star_XX          ;
   LD de, $C243                ; Tiles
   LD b, 16                    ; 16 sprites
   LD a, (RAM_STAR_I_STATE)    ; Load doom sprite?
   CP $7F                      ;
   CALL Z, tool_tiles_to_RAM   ; Copy tiles to working RAM

   LD hl, alien_parachute      ;
   LD de, $C263                ; Tiles
   LD b, 8                     ; 8 sprites
   LD a, (RAM_ALIEN_STATE)     ; Load doom sprite?
   CP $7F                      ;
   CALL Z, tool_tiles_to_RAM   ; Copy tiles to working RAM

   RET                         ; End subroutine

big_star_tiles_1:
 .db $00 $37 $45 $46  
 .db $38 $00 $47 $48
 .db $5D $5E $73 $74 
 .db $5F $60 $75 $76

big_star_tiles_2:
 .db $00 $39 $49 $4A
 .db $3A $00 $4B $48
 .db $5D $61 $73 $74
 .db $62 $60 $75 $76

big_star_tiles_3:
 .db $00 $37 $45 $4C 
 .db $38 $00 $4D $48 
 .db $5D $63 $73 $74  
 .db $64 $60 $75 $76

big_star_XX:
 .db $00 $37 $45 $52 
 .db $38 $00 $53 $48 
 .db $5D $67 $73 $74  
 .db $68 $60 $75 $76

alien_1:
 .db $3B $3C $3D $3E
 .db $54 $55 $56 $57

alien_2:
 .db $69 $6A $6B $6C
 .db $78 $79 $7A $7B

alien_parachute:
 .db $3F $40 $41 $42
 .db $58 $59 $5A $00

;-----------------------------------------
; game_over_or_congrats (41 lines)
;
; Display "GAME OVER" or
;         "G O A L". 
;-----------------------------------------
game_over_or_congrats:
; Compare Goal to Score
   LD hl, $C34C                ; Goal address - 2
   LD de, $C30C                ; Score address - 2
   LD c, 11                    ; Number of digits + 1

gooc_loop:   
   INC hl                      ; Increment address
   INC hl                      ;
   INC de                      ; Increment address
   INC de                      ;
   DEC c                       ; Decrement counter
   JP Z, gooc_gameover         ; Skip if counter expired

   LD a, (de)                  ; Load score
   CP $A5                      ; 0 => use $9B
   JP NZ, gooc_next1           ;
   LD a, $9B                   ;
gooc_next1:
   LD b, a                     ; 
   LD a, (hl)                  ; Load goal
   CP $A5                      ; 0 => use $9B
   JP NZ, gooc_next2           ;
   LD a, $9B                   ;
gooc_next2:
   SUB b                       ; a <- goal - score

   JP Z, gooc_loop             ; Equal, check next digit        
   JP P, gooc_gameover         ; Positive, game over

gooc_congratulations:
   LD hl, congrats_sprites_vpos   ; Source
   LD de, $C121                ; Destination
   LD b, 5                     ;
   CALL tool_sprites_to_RAM    ; Copy
   LD hl, congrats_sprites_hpos   ; Source
   LD de, $C202                ; Destination
   LD b, 9                     ;
   CALL tool_sprites_to_RAM    ; Copy
   JP gooc_end                 ;

gooc_gameover:
   LD hl, game_over_sprites_vpos   ; Source
   LD de, $C121                ; Destination
   LD b, 9                     ;
   CALL tool_sprites_to_RAM    ; Copy
   LD hl, game_over_sprites_hpos   ; Source
   LD de, $C202                ; Destination
   LD b, 17                    ;
   CALL tool_sprites_to_RAM    ; Copy

gooc_end: 
   RET                         ; End subroutine

game_over_sprites_vpos:
.db $70 $70 $70 $70 $70 $70 $70 $70 $D0
game_over_sprites_hpos:
.db $60 $88 $68 $82 $70 $8E $78 $86  $88 $90 $90 $97 $98 $86 $A0 $93  $D0 ; $88 $82 $8E $86  $90 $97 $86 $93

congrats_sprites_vpos:
.db $70 $70 $70 $70 $D0
congrats_sprites_hpos:
.db $60 $88 $70 $90 $80 $82 $90 $8D  $D0 ; $88 $90 $82 $8D  

;-------------------------------------------------------------------------------------
;-------------------------------------------------------------------------------------
; Round 2
;-------------------------------------------------------------------------------------
;-------------------------------------------------------------------------------------

;------------------------------------------
; gsm_load_round_2 (17 lines)
;
;------------------------------------------
gsm_load_round_2:
   CALL VDP_off                ; Turn off screen

   CALL load_palette_data02    ; Set palette data

   LD hl, round_two_vpos       ;
   LD de, RAM_VPOS_SPRITE      ;
   LD b, 58
   CALL tool_sprites_to_RAM    ; Copy sprites to RAM

   LD hl, round_two_hpos       ;
   LD de, RAM_HPOS_SPRITE      ;
   LD b, 116
   CALL tool_sprites_to_RAM    ; Copy sprites to RAM

   LD a, $00                   ; No blinking
   LD (RAM_COLOR_BLINK), a     ;

   CALL set_timer_030          ; Set timer
   CALL tool_increment_goal_10 ; Goal = Goal + 10
   CALL tool_increment_round   ; Setup round number

   CALL clear_foe_states       ; Clear foe state machines

   CALL VDP_on                 ; Turn on VDP. Immediate interrupt is likely to occur.

   RET                         ; End subroutine

;---------------------------------------------------------
; move_round_002_foes (39 lines)
;
;---------------------------------------------------------
move_round_002_foes:
   LD hl, $C121                ; Set vpos address
   LD de, $C202                ; Set hpos address

;-------------------------------------   
   LD a, (RAM_STAR_A_STATE)      ;
   CALL round_002_bounce_sprites ; Bounce a sprite
   LD (RAM_STAR_A_STATE), a      ;

   LD a, (RAM_STAR_B_STATE)      ;
   CALL round_002_bounce_sprites ; Bounce a sprite
   LD (RAM_STAR_B_STATE), a      ;

   LD a, (RAM_STAR_C_STATE)      ;
   CALL round_002_bounce_sprites ; Bounce a sprite
   LD (RAM_STAR_C_STATE), a      ;

   LD a, (RAM_STAR_D_STATE)      ;
   CALL round_002_bounce_sprites ; Bounce a sprite
   LD (RAM_STAR_D_STATE), a      ;

;-------------------------------------   
   LD a, (RAM_STAR_E_STATE)      ;
   CALL round_002_bounce_sprites ; Bounce a sprite
   LD (RAM_STAR_E_STATE), a      ;

   LD a, (RAM_STAR_F_STATE)      ;
   CALL round_002_bounce_sprites ; Bounce a sprite
   LD (RAM_STAR_F_STATE), a      ;

   LD a, (RAM_STAR_G_STATE)      ;
   CALL round_002_bounce_sprites ; Bounce a sprite
   LD (RAM_STAR_G_STATE), a      ;

   LD a, (RAM_STAR_H_STATE)      ;
   CALL round_002_bounce_sprites ; Bounce a sprite
   LD (RAM_STAR_H_STATE), a      ;

;-------------------------------------   
   LD a, (RAM_STAR_I_STATE)      ;
   CALL round_002_bounce_sprites ; Bounce a sprite
   LD (RAM_STAR_I_STATE), a      ;

   LD a, (RAM_STAR_J_STATE)      ;
   CALL round_002_bounce_sprites ; Bounce a sprite
   LD (RAM_STAR_J_STATE), a      ;

   LD a, (RAM_STAR_K_STATE)      ;
   CALL round_002_bounce_sprites ; Bounce a sprite
   LD (RAM_STAR_K_STATE), a      ;

   LD a, (RAM_STAR_L_STATE)      ;
   CALL round_002_bounce_sprites ; Bounce a sprite
   LD (RAM_STAR_L_STATE), a      ;

   RET                         ; End subroutine


;---------------------------------------------------------
; round_002_bounce_sprites (51 lines)
;
; a = current direction & new direction
; hl = vpos address
; de = hpos address
;---------------------------------------------------------
round_002_bounce_sprites:
   LD b, a                     ; save A
   CP $00                      ; DR
   JP Z, r002bs_down_right     ;
   CP $01                      ; DL
   JP Z, r002bs_down_left      ;
   CP $02                      ; UL
   JP Z, r002bs_up_left        ;
   CP $03                      ; UR
   JP Z, r002bs_up_right       ;

; Star has been shot.
; Clear when point hits top of screen.
   LD a, (hl)                  ;
   CP $10                      ;
   JP Z, r002_clear_tiles      ;

   LD a, (hl)                  ;
   CP $10                      ;
   JP NZ, r002_one_tiles       ;

r002bs_down_right:
   LD a, (de)                  ; right wall
   CP $F0                      ;
   JP Z, r002_incb             ; Next state

   CALL hl_down                ;
   CALL hl_down                ;
   CALL hl_down                ;
   CALL hl_down                ;
   CALL de_right_star          ;
   JP r002bs_end               ;

r002bs_down_left:
   LD a, (hl)                  ; floor
   CP $C0                      ;
   JP Z, r002_incb             ; Next state

   CALL hl_down                ;
   CALL hl_down                ;
   CALL hl_down                ;
   CALL hl_down                ;
   CALL de_left_star           ;
   JP r002bs_end               ;

r002bs_up_left:
   LD a, (de)                  ; left wall
   CP $10                      ;
   JP Z, r002_incb             ; Next state

   CALL hl_up                  ;
   CALL hl_up                  ;
   CALL hl_up                  ;
   CALL hl_up                  ;
   CALL de_left_star           ;
   JP r002bs_end               ;

r002bs_up_right:
   LD a, (hl)                  ; ceiling
   CP $10                      ;
   JP Z, r002_zerob            ; Next state

   CALL hl_up                  ;
   CALL hl_up                  ;
   CALL hl_up                  ;
   CALL hl_up                  ;
   CALL de_right_star          ;

r002bs_end:
   LD a, b                     ; Restore A

   RET                         ; End subroutine

;---------------------------------------------------------
; hl_down (5 lines)
;---------------------------------------------------------
hl_down:
   LD a, (hl)                  ; Down
   INC a                       ;
   LD (hl), a                  ;
   INC hl                      ;

   RET                         ; End subroutine

;---------------------------------------------------------
; hl_up (5 lines)
;---------------------------------------------------------
hl_up:
   LD a, (hl)                  ; Down
   DEC a                       ;
   LD (hl), a                  ;
   INC hl                      ;

   RET                         ; End subroutine

;---------------------------------------------------------
; de_right (6 lines)
;---------------------------------------------------------
de_right:
   LD a, (de)                  ; Down
   INC a                       ;
   LD (de), a                  ;
   INC de                      ;
   INC de                      ;

   RET                         ; End subroutine

;---------------------------------------------------------
; de_left (6 lines)
;---------------------------------------------------------
de_left:
   LD a, (de)                  ; Down
   DEC a                       ;
   LD (de), a                  ;
   INC de                      ;
   INC de                      ;

   RET                         ; End subroutine

;---------------------------------------------------------
; r002_incb (4 lines)
;---------------------------------------------------------
r002_incb:
   LD a, b                     ;
   INC a                       ; Next B
   LD b, a                     ;

   JP r002bs_end               ; Don't move. End routine.

;---------------------------------------------------------
; r002_zerob (2 lines)
;---------------------------------------------------------
r002_zerob:
   LD b, $00                   ; Clear B

   JP r002bs_end               ; Don't move. End routine.

;---------------------------------------------------------
; r002_clear_tiles (20 lines)
;---------------------------------------------------------
r002_clear_tiles:
   LD a, $00                   ; Clear all tiles
   INC de                      ;
   LD (de), a                  ;
   INC de                      ;
   INC de                      ;
   LD (de), a                  ;
   INC de                      ;
   INC de                      ;
   LD (de), a                  ;
   INC de                      ;
   INC de                      ;
   LD (de), a                  ;
   INC de                      ; Point to next vpos

   INC hl                      ;
   INC hl                      ;
   INC hl                      ;
   INC hl                      ;

   JP r002bs_end               ; Don't move. End routine.  

;---------------------------------------------------------
; r002_one_tiles (23 lines)
;
; $01 $02 $1E $23
;---------------------------------------------------------
r002_one_tiles:
   LD a, $01                   ; Clear all tiles
   INC de                      ;
   LD (de), a                  ;
   INC de                      ;
   INC de                      ;
   LD a, $02                   ; Clear all tiles
   LD (de), a                  ;
   INC de                      ;
   INC de                      ;
   LD a, $1E                   ; Clear all tiles
   LD (de), a                  ;
   INC de                      ;
   INC de                      ;
   LD a, $23                   ; Clear all tiles
   LD (de), a                  ;
   INC de                      ; Point to next vpos

   CALL hl_up                  ;
   CALL hl_up                  ;
   CALL hl_up                  ;
   CALL hl_up                  ;

   JP r002bs_end               ; Don't move. End routine.  

;---------------------------------------------------------
; de_left_star (28 lines)
;---------------------------------------------------------
de_left_star:
   LD a, (de)                  ; Go left
   DEC a                       ;
   LD (de), a                  ;
   INC de                      ;

   LD a, $15                   ; Set tiles
   LD (de), a                  ;
   INC de                      ;

   LD a, (de)                  ; Go left
   DEC a                       ;
   LD (de), a                  ;
   INC de                      ;

   LD a, $16                   ; Set tiles
   LD (de), a                  ;
   INC de                      ;

   LD a, (de)                  ; Go left
   DEC a                       ;
   LD (de), a                  ;
   INC de                      ;

   LD a, $30                   ; Set tiles
   LD (de), a                  ;
   INC de                      ;

   LD a, (de)                  ; Go left
   DEC a                       ;
   LD (de), a                  ;
   INC de                      ;

   LD a, $31                   ; Set tiles
   LD (de), a                  ;
   INC de                      ;

   RET                         ; End subroutine

;---------------------------------------------------------
; de_right_star (28 lines)
;---------------------------------------------------------
de_right_star:
   LD a, (de)                  ; Go right
   INC a                       ;
   LD (de), a                  ;
   INC de                      ;

   LD a, $15                   ; Set tiles
   LD (de), a                  ;
   INC de                      ;

   LD a, (de)                  ; Go right
   INC a                       ;
   LD (de), a                  ;
   INC de                      ;

   LD a, $16                   ; Set tiles
   LD (de), a                  ;
   INC de                      ;

   LD a, (de)                  ; Go right
   INC a                       ;
   LD (de), a                  ;
   INC de                      ;

   LD a, $30                   ; Set tiles
   LD (de), a                  ;
   INC de                      ;

   LD a, (de)                  ; Go rigt
   INC a                       ;
   LD (de), a                  ;
   INC de                      ;

   LD a, $31                   ; Clear all tiles
   LD (de), a                  ;
   INC de                      ;

   RET                         ; End subroutine

;-----------------------------------------
; xy_collision_detect_small (25 lines)
;
; RAM_COLL_X1     = x1
; RAM_COLL_Y1     = y1
; RAM_COLL_RESULT = result, $00 => miss, $01 => hit
;
; Is (x2,y2) within 32x32 box with
; top corner at (x1,y1)?
;
;-----------------------------------------
xy_collision_detect_small:
   LD a, (RAM_COLL_STATE)      ; Don't check if already hit!
   CP $7F                      ;
   JP Z, xycd_end              ;
  
   LD a, $00                   ; Assume miss until hit
   LD (RAM_COLL_RESULT), a     ;

   LD a, (RAM_COLL_Y1)         ; y1
   SUB 4                       ; center is 4 pixels from top corner
   LD b, a                     ;
   LD a, ($C120)               ; y2
   SUB b                       ; a = y2 - y1
   AND $F0                     ; mask unwanted bits
   CP $00                      ; If difference is less than 16 pixels, declare hit
   JP NZ, xycds_end            ;

   LD a, (RAM_COLL_X1)         ; x1
   SUB 4                       ; center is 4 pixels from top corner
   LD b, a                     ;
   LD a, ($C200)               ; x2
   SUB b                       ; a = x2 - x1
   AND $F0                     ; mask unwanted bits
   CP $00                      ; If difference is less than 16 pixels, declare hit
   JP NZ, xycds_end            ;

   LD a, $7F                   ; Proven hit
   LD (RAM_COLL_RESULT), a     ;

   CALL tool_increment_score   ; Add to the score

xycds_end: 
   RET                         ; End subroutine

;------------------------------------------------
; collision_detection_rd002 (160 lines)
;
;------------------------------------------------
collision_detection_rd002:
   LD a, (GAME_STATE)          ; 
   CP $03                      ; Round 2?
   JP Z, cldt_start            ;
   CP $0B                      ; Round 6?
   JP Z, cldt_start            ;

   JP cldt_skip002             ; Skip unless round 2, 6

; Collision detection

cldt_start:
; Star A
   LD a, (RAM_STAR_A_STATE)    ; Load current state
   LD (RAM_COLL_STATE), a      ;
   LD a, ($C121)               ; Y
   LD (RAM_COLL_Y1), a         ;
   LD a, ($C202)               ; X
   LD (RAM_COLL_X1), a         ;
   CALL xy_collision_detect_small ; Detect collision
   
   LD a, (RAM_COLL_RESULT)     ; If collision change state
   CP $7F                      ;
   JP NZ, cdrd002_next         ;
   LD a, $7F                   ;
   LD (RAM_STAR_A_STATE), a    ;

cdrd002_next:
; Star B
   LD a, (RAM_STAR_B_STATE)    ; Load current state
   LD (RAM_COLL_STATE), a      ;
   LD a, ($C121 + 4)           ; Y
   LD (RAM_COLL_Y1), a         ;
   LD a, ($C202 + 8)           ; X
   LD (RAM_COLL_X1), a         ;
   CALL xy_collision_detect_small ; Detect collision
   
   LD a, (RAM_COLL_RESULT)     ; If collision change state
   CP $7F                      ;
   JP NZ, cdrd002_next2        ;
   LD a, $7F                   ;
   LD (RAM_STAR_B_STATE), a    ;

cdrd002_next2:
; Star C
   LD a, (RAM_STAR_C_STATE)    ; Load current state
   LD (RAM_COLL_STATE), a      ;
   LD a, ($C121 + 4*2)         ; Y
   LD (RAM_COLL_Y1), a         ;
   LD a, ($C202 + 8*2)         ; X
   LD (RAM_COLL_X1), a         ;
   CALL xy_collision_detect_small ; Detect collision
   
   LD a, (RAM_COLL_RESULT)     ; If collision change state
   CP $7F                      ;
   JP NZ, cdrd002_next3        ;
   LD a, $7F                   ;
   LD (RAM_STAR_C_STATE), a    ;

cdrd002_next3:
; Star D
   LD a, (RAM_STAR_D_STATE)    ; Load current state
   LD (RAM_COLL_STATE), a      ;
   LD a, ($C121 + 4*3)         ; Y
   LD (RAM_COLL_Y1), a         ;
   LD a, ($C202 + 8*3)         ; X
   LD (RAM_COLL_X1), a         ;
   CALL xy_collision_detect_small ; Detect collision
   
   LD a, (RAM_COLL_RESULT)     ; If collision change state
   CP $7F                      ;
   JP NZ, cdrd002_next4        ;
   LD a, $7F                   ;
   LD (RAM_STAR_D_STATE), a    ;

cdrd002_next4:   
; Star E
   LD a, (RAM_STAR_E_STATE)    ; Load current state
   LD (RAM_COLL_STATE), a      ;
   LD a, ($C121 + 4*4)         ; Y
   LD (RAM_COLL_Y1), a         ;
   LD a, ($C202 + 8*4)         ; X
   LD (RAM_COLL_X1), a         ;
   CALL xy_collision_detect_small ; Detect collision
   
   LD a, (RAM_COLL_RESULT)     ; If collision change state
   CP $7F                      ;
   JP NZ, cdrd002_next5        ;
   LD a, $7F                   ;
   LD (RAM_STAR_E_STATE), a    ;

cdrd002_next5: 
; Star F
   LD a, (RAM_STAR_F_STATE)    ; Load current state
   LD (RAM_COLL_STATE), a      ;
   LD a, ($C121 + 4*5)         ; Y
   LD (RAM_COLL_Y1), a         ;
   LD a, ($C202 + 8*5)         ; X
   LD (RAM_COLL_X1), a         ;
   CALL xy_collision_detect_small ; Detect collision
   
   LD a, (RAM_COLL_RESULT)     ; If collision change state
   CP $7F                      ;
   JP NZ, cdrd002_next6        ;
   LD a, $7F                   ;
   LD (RAM_STAR_F_STATE), a    ;

cdrd002_next6: 
; Star G
   LD a, (RAM_STAR_G_STATE)    ; Load current state
   LD (RAM_COLL_STATE), a      ;
   LD a, ($C121 + 4*6)         ; Y
   LD (RAM_COLL_Y1), a         ;
   LD a, ($C202 + 8*6)         ; X
   LD (RAM_COLL_X1), a         ;
   CALL xy_collision_detect_small ; Detect collision
   
   LD a, (RAM_COLL_RESULT)     ; If collision change state
   CP $7F                      ;
   JP NZ, cdrd002_next7        ;
   LD a, $7F                   ;
   LD (RAM_STAR_G_STATE), a    ;

cdrd002_next7: 
; Star H
   LD a, (RAM_STAR_H_STATE)    ; Load current state
   LD (RAM_COLL_STATE), a      ;
   LD a, ($C121 + 4*7)         ; Y
   LD (RAM_COLL_Y1), a         ;
   LD a, ($C202 + 8*7)         ; X
   LD (RAM_COLL_X1), a         ;
   CALL xy_collision_detect_small ; Detect collision
   
   LD a, (RAM_COLL_RESULT)     ; If collision change state
   CP $7F                      ;
   JP NZ, cdrd002_next8        ;
   LD a, $7F                   ;
   LD (RAM_STAR_H_STATE), a    ;

cdrd002_next8: 
; Star I
   LD a, (RAM_STAR_I_STATE)    ; Load current state
   LD (RAM_COLL_STATE), a      ;
   LD a, ($C121 + 4*8)         ; Y
   LD (RAM_COLL_Y1), a         ;
   LD a, ($C202 + 8*8)         ; X
   LD (RAM_COLL_X1), a         ;
   CALL xy_collision_detect_small ; Detect collision
   
   LD a, (RAM_COLL_RESULT)     ; If collision change state
   CP $7F                      ;
   JP NZ, cdrd002_next9        ;
   LD a, $7F                   ;
   LD (RAM_STAR_I_STATE), a    ;

cdrd002_next9: 
; Star J
   LD a, (RAM_STAR_J_STATE)    ; Load current state
   LD (RAM_COLL_STATE), a      ;
   LD a, ($C121 + 4*9)         ; Y
   LD (RAM_COLL_Y1), a         ;
   LD a, ($C202 + 8*9)         ; X
   LD (RAM_COLL_X1), a         ;
   CALL xy_collision_detect_small ; Detect collision
   
   LD a, (RAM_COLL_RESULT)     ; If collision change state
   CP $7F                      ;
   JP NZ, cdrd002_next10        ;
   LD a, $7F                   ;
   LD (RAM_STAR_J_STATE), a    ;

cdrd002_next10: 
; Star K
   LD a, (RAM_STAR_K_STATE)    ; Load current state
   LD (RAM_COLL_STATE), a      ;
   LD a, ($C121 + 4*10)        ; Y
   LD (RAM_COLL_Y1), a         ;
   LD a, ($C202 + 8*10)        ; X
   LD (RAM_COLL_X1), a         ;
   CALL xy_collision_detect_small ; Detect collision
   
   LD a, (RAM_COLL_RESULT)     ; If collision change state
   CP $7F                      ;
   JP NZ, cdrd002_next11       ;
   LD a, $7F                   ;
   LD (RAM_STAR_K_STATE), a    ;

cdrd002_next11: 
; Star L
   LD a, (RAM_STAR_L_STATE)    ; Load current state
   LD (RAM_COLL_STATE), a      ;
   LD a, ($C121 + 4*11)        ; Y
   LD (RAM_COLL_Y1), a         ;
   LD a, ($C202 + 8*11)        ; X
   LD (RAM_COLL_X1), a         ;
   CALL xy_collision_detect_small ; Detect collision
   
   LD a, (RAM_COLL_RESULT)     ; If collision change state
   CP $7F                      ;
   JP NZ, cdrd002_next12       ;
   LD a, $7F                   ;
   LD (RAM_STAR_L_STATE), a    ;

cdrd002_next12: 
cldt_skip002:
   RET                         ; End subroutine

;-------------------------------------------------------------------------------------
;-------------------------------------------------------------------------------------
; Round 3
;-------------------------------------------------------------------------------------
;-------------------------------------------------------------------------------------

;------------------------------------------
; gsm_load_round_3 (17 lines)
;
;------------------------------------------
gsm_load_round_3:
   CALL VDP_off                ; Turn off screen

   CALL load_palette_data03    ; Set palette data

   LD hl, round_3_vpos         ;
   LD de, RAM_VPOS_SPRITE      ;
   LD b, 58
   CALL tool_sprites_to_RAM    ; Copy sprites to RAM

   LD hl, round_3_hpos         ;
   LD de, RAM_HPOS_SPRITE      ;
   LD b, 116
   CALL tool_sprites_to_RAM    ; Copy sprites to RAM

   LD a, $00                   ; No blinking
   LD (RAM_COLOR_BLINK), a     ;

   CALL set_timer_030          ; Set timer
   CALL tool_increment_goal_10 ; Goal
   CALL tool_increment_goal_10 ; Goal
   CALL tool_increment_goal_10 ; Goal = Goal + 30
   CALL tool_increment_round   ; Setup round number

   CALL clear_foe_states       ; Clear foe state machines

   CALL VDP_on                 ; Turn on VDP. Immediate interrupt is likely to occur.

   RET                         ; End subroutine

;---------------------------------------------------------
; move_round_003_foes (85 lines)
;
;---------------------------------------------------------
move_round_003_foes:
   LD a, (RAM_STAR_A_STATE)    ; Alien 1
   CP $7F                      ; 
   JP Z, rd003_down1           ;

   LD hl, $C202                ; Move alien
   LD b, 8                     ; 8 sprites
   CALL move_sprites_hl_dist_b_right ; Go right
   LD hl, $C202                ; Move alien
   LD b, 8                     ; 8 sprites
   CALL move_sprites_hl_dist_b_right ; Go right
   JP rd003_alien2             ;

rd003_down1:
   LD hl, $C121                ; Move alien
   LD b, 8                     ; 8 sprites
   CALL move_sprites_hl_dist_b_down ; Go down

;------------------
rd003_alien2:
   LD a, (RAM_STAR_B_STATE)    ; Alien 2
   CP $7F                      ; 
   JP Z, rd003_down2           ;

   LD hl, $C212                ; Move alien
   LD b, 8                     ; 8 sprites
   CALL move_sprites_hl_dist_b_right ; Go right
   JP rd003_alien3             ;

rd003_down2:
   LD hl, $C129                ; Move alien
   LD b, 8                     ; 8 sprites
   CALL move_sprites_hl_dist_b_down ; Go down

;------------------
rd003_alien3:
   LD a, (RAM_STAR_C_STATE)    ; Alien 3
   CP $7F                      ; 
   JP Z, rd003_down3           ;

   LD hl, $C222                ; Move alien
   LD b, 8                     ; 8 sprites
   CALL move_sprites_hl_dist_b_left ; Go left
   LD hl, $C222                ; Move alien
   LD b, 8                     ; 8 sprites
   CALL move_sprites_hl_dist_b_left ; Go left
   JP rd003_alien4             ;

rd003_down3:
   LD hl, $C131                ; Move alien
   LD b, 8                     ; 8 sprites
   CALL move_sprites_hl_dist_b_down ; Go down

;------------------
rd003_alien4:
   LD a, (RAM_STAR_D_STATE)    ; Alien 4
   CP $7F                      ; 
   JP Z, rd003_down4           ;

   LD hl, $C232                ; Move alien
   LD b, 8                     ; 8 sprites
   CALL move_sprites_hl_dist_b_left ; Go left
   JP rd003_alien5             ;

rd003_down4:
   LD hl, $C139                ; Move alien
   LD b, 8                     ; 8 sprites
   CALL move_sprites_hl_dist_b_down ; Go down

;------------------
rd003_alien5:
   LD a, (RAM_STAR_E_STATE)    ; Alien 5
   CP $7F                      ; 
   JP Z, rd003_down5           ;

   LD hl, $C242                ; Move alien
   LD b, 8                     ; 8 sprites
   CALL move_sprites_hl_dist_b_right ; Go right
   LD hl, $C242                ; Move alien
   LD b, 8                     ; 8 sprites
   CALL move_sprites_hl_dist_b_right ; Go right
   LD hl, $C242                ; Move alien
   LD b, 8                     ; 8 sprites
   CALL move_sprites_hl_dist_b_right ; Go right
   JP rd003_alien6             ;

rd003_down5:
   LD hl, $C141                ; Move alien
   LD b, 8                     ; 8 sprites
   CALL move_sprites_hl_dist_b_down ; Go down

;------------------
rd003_alien6:
   LD a, (RAM_STAR_F_STATE)    ; Alien 6
   CP $7F                      ; 
   JP Z, rd003_down6           ;

   LD hl, $C252                ; Move alien
   LD b, 8                     ; 8 sprites
   CALL move_sprites_hl_dist_b_right ; Go right
   JP rd003_alien7             ;

rd003_down6:
   LD hl, $C149                ; Move alien
   LD b, 8                     ; 8 sprites
   CALL move_sprites_hl_dist_b_down ; Go down

;------------------
rd003_alien7:
   LD a, (RAM_STAR_G_STATE)    ; Alien 7
   CP $7F                      ; 
   JP Z, rd003_down7           ;

   LD hl, $C262                ; Move alien
   LD b, 8                     ; 8 sprites
   CALL move_sprites_hl_dist_b_left ; Go left
   JP rd003_alien8             ;

rd003_down7:
   LD hl, $C151                ; Move alien
   LD b, 8                     ; 8 sprites
   CALL move_sprites_hl_dist_b_down ; Go down

;------------------
rd003_alien8:

rd003_star_end:
   RET                         ; End subroutine

;------------------------------------------------
; collision_detection_rd003 (52 lines)
;
;------------------------------------------------
collision_detection_rd003:
   LD a, (GAME_STATE)          ; Round 3?
   CP $05                      ; ((RD# * 2) - 1)
   JP Z, cldt_aokusa           ;
   CP $09                      ; ((RD# * 2) - 1)
   JP Z, cldt_aokusa           ;

   JP cldt_skip003             ; Skip unless round 3, 5

cldt_aokusa:
; Alien 1
   LD a, (RAM_STAR_A_STATE)    ;
   LD (RAM_COLL_STATE), a      ; Pass state machine value
   LD a, ($C121)               ; Y
   LD (RAM_COLL_Y1), a         ;
   LD a, ($C202)               ; X
   LD (RAM_COLL_X1), a         ;
   CALL xy_collision_detect    ; Detect collision
   
   LD a, (RAM_COLL_RESULT)     ; If collision change state
   CP $7F                      ;
   JP NZ, cdrd001_alien2       ;
   LD a, $7F                   ;
   LD (RAM_STAR_A_STATE), a    ;

; Alien 2
cdrd001_alien2:
   LD a, (RAM_STAR_B_STATE)    ;
   LD (RAM_COLL_STATE), a      ; Pass state machine value
   LD a, ($C129)               ; Y
   LD (RAM_COLL_Y1), a         ;
   LD a, ($C212)               ; X
   LD (RAM_COLL_X1), a         ;
   CALL xy_collision_detect    ; Detect collision
   
   LD a, (RAM_COLL_RESULT)     ; If collision change state
   CP $7F                      ;
   JP NZ, cdrd001_alien3       ;
   LD a, $7F                   ;
   LD (RAM_STAR_B_STATE), a    ;

; Alien 3
cdrd001_alien3:
   LD a, (RAM_STAR_C_STATE)    ;
   LD (RAM_COLL_STATE), a      ; Pass state machine value
   LD a, ($C131)               ; Y
   LD (RAM_COLL_Y1), a         ;
   LD a, ($C222)               ; X
   LD (RAM_COLL_X1), a         ;
   CALL xy_collision_detect    ; Detect collision
   
   LD a, (RAM_COLL_RESULT)     ; If collision change state
   CP $7F                      ;
   JP NZ, cdrd001_alien4       ;
   LD a, $7F                   ;
   LD (RAM_STAR_C_STATE), a    ;

; Alien 4
cdrd001_alien4:
   LD a, (RAM_STAR_D_STATE)    ;
   LD (RAM_COLL_STATE), a      ; Pass state machine value
   LD a, ($C139)               ; Y
   LD (RAM_COLL_Y1), a         ;
   LD a, ($C232)               ; X
   LD (RAM_COLL_X1), a         ;
   CALL xy_collision_detect    ; Detect collision
   
   LD a, (RAM_COLL_RESULT)     ; If collision change state
   CP $7F                      ;
   JP NZ, cdrd001_alien5       ;
   LD a, $7F                   ;
   LD (RAM_STAR_D_STATE), a    ;

; Alien 5
cdrd001_alien5:
   LD a, (RAM_STAR_E_STATE)    ;
   LD (RAM_COLL_STATE), a      ; Pass state machine value
   LD a, ($C141)               ; Y
   LD (RAM_COLL_Y1), a         ;
   LD a, ($C242)               ; X
   LD (RAM_COLL_X1), a         ;
   CALL xy_collision_detect    ; Detect collision
   
   LD a, (RAM_COLL_RESULT)     ; If collision change state
   CP $7F                      ;
   JP NZ, cdrd001_alien6       ;
   LD a, $7F                   ;
   LD (RAM_STAR_E_STATE), a    ;

; Alien 6
cdrd001_alien6:
   LD a, (RAM_STAR_F_STATE)    ;
   LD (RAM_COLL_STATE), a      ; Pass state machine value
   LD a, ($C149)               ; Y
   LD (RAM_COLL_Y1), a         ;
   LD a, ($C252)               ; X
   LD (RAM_COLL_X1), a         ;
   CALL xy_collision_detect    ; Detect collision
   
   LD a, (RAM_COLL_RESULT)     ; If collision change state
   CP $7F                      ;
   JP NZ, cdrd001_alien7       ;
   LD a, $7F                   ;
   LD (RAM_STAR_F_STATE), a    ;

; Alien 7
cdrd001_alien7:
   LD a, (RAM_STAR_G_STATE)    ;
   LD (RAM_COLL_STATE), a      ; Pass state machine value
   LD a, ($C151)               ; Y
   LD (RAM_COLL_Y1), a         ;
   LD a, ($C262)               ; X
   LD (RAM_COLL_X1), a         ;
   CALL xy_collision_detect    ; Detect collision
   
   LD a, (RAM_COLL_RESULT)     ; If collision change state
   CP $7F                      ;
   JP NZ, cldt_skip003         ;
   LD a, $7F                   ;
   LD (RAM_STAR_G_STATE), a    ;

cldt_skip003:    
   RET                         ; End subroutine

;-----------------------------------------
; round_003_star_respawn (95 lines)
; 
;-----------------------------------------
round_003_star_respawn:
; Alien 1
   LD a, ($C121)               ; Too low?
   CP $E0                      ;
   JP NZ, r003sr1              ;

   LD a, $00                   ; Clear hit detection
   LD (RAM_STAR_A_STATE), a    ;

   LD hl, round_3_vpos + 1     ; Source
   LD de, $C121                ; Destination
   LD b, 8
   CALL tool_sprites_to_RAM    ; Copy
   LD hl, round_3_hpos + 2     ; Source
   LD de, $C202                ; Destination
   LD b, 16
   CALL tool_sprites_to_RAM    ; Copy

; Alien 2
r003sr1:
   LD a, ($C129)               ; Too low?
   CP $E0                      ;
   JP NZ, r003sr2              ;

   LD a, $00                   ; Clear hit detection
   LD (RAM_STAR_B_STATE), a    ;

   LD hl, round_3_vpos + 9     ; Source
   LD de, $C129                ; Destination
   LD b, 8
   CALL tool_sprites_to_RAM    ; Copy
   LD hl, round_3_hpos + 18    ; Source
   LD de, $C212                ; Destination
   LD b, 16
   CALL tool_sprites_to_RAM    ; Copy

; Alien 3
r003sr2:
   LD a, ($C131)               ; Too low?
   CP $E0                      ;
   JP NZ, r003sr3              ;

   LD a, $00                   ; Clear hit detection
   LD (RAM_STAR_C_STATE), a    ;

   LD hl, round_3_vpos + 17    ; Source
   LD de, $C131                ; Destination
   LD b, 8
   CALL tool_sprites_to_RAM    ; Copy
   LD hl, round_3_hpos + 34    ; Source
   LD de, $C222                ; Destination
   LD b, 16
   CALL tool_sprites_to_RAM    ; Copy

; Alien 4
r003sr3:
   LD a, ($C139)               ; Too low?
   CP $E0                      ;
   JP NZ, r003sr4              ;

   LD a, $00                   ; Clear hit detection
   LD (RAM_STAR_D_STATE), a    ;

   LD hl, round_3_vpos + 1 + 3*8 ; Source
   LD de, $C139                ; Destination
   LD b, 8
   CALL tool_sprites_to_RAM    ; Copy
   LD hl, round_3_hpos + 2 + 3*16 ; Source
   LD de, $C232                ; Destination
   LD b, 16
   CALL tool_sprites_to_RAM    ; Copy

; Alien 5
r003sr4:
   LD a, ($C141)               ; Too low?
   CP $E0                      ;
   JP NZ, r003sr5              ;

   LD a, $00                   ; Clear hit detection
   LD (RAM_STAR_E_STATE), a    ;

   LD hl, round_3_vpos + 1 + 4*8 ; Source
   LD de, $C141                ; Destination
   LD b, 8
   CALL tool_sprites_to_RAM    ; Copy
   LD hl, round_3_hpos + 2 + 4*16 ; Source
   LD de, $C242                ; Destination
   LD b, 16
   CALL tool_sprites_to_RAM    ; Copy

; Alien 6
r003sr5:
   LD a, ($C149)               ; Too low?
   CP $E0                      ;
   JP NZ, r003sr6              ;

   LD a, $00                   ; Clear hit detection
   LD (RAM_STAR_F_STATE), a    ;

   LD hl, round_3_vpos + 1 + 5*8 ; Source
   LD de, $C149                ; Destination
   LD b, 8
   CALL tool_sprites_to_RAM    ; Copy
   LD hl, round_3_hpos + 2 + 5*16 ; Source
   LD de, $C252                ; Destination
   LD b, 16
   CALL tool_sprites_to_RAM    ; Copy

; Alien 7
r003sr6:
   LD a, ($C151)               ; Too low?
   CP $E0                      ;
   JP NZ, r003sr7              ;

   LD a, $00                   ; Clear hit detection
   LD (RAM_STAR_G_STATE), a    ;

   LD hl, round_3_vpos + 1 + 6*8 ; Source
   LD de, $C151                ; Destination
   LD b, 8
   CALL tool_sprites_to_RAM    ; Copy
   LD hl, round_3_hpos + 2 + 6*16 ; Source
   LD de, $C262                ; Destination
   LD b, 16
   CALL tool_sprites_to_RAM    ; Copy

r003sr7:
   RET                         ; End subroutine

;-----------------------------------------
; round_003_star_blink (43 lines)
;
;-----------------------------------------
round_003_star_blink:

; Alien 1
   LD hl, alien_parachute      ;
   LD de, $C202 + 1             ; Tiles
   LD b, 8                     ; 8 sprites
   LD a, (RAM_STAR_A_STATE)    ; Load doom sprite?
   CP $7F                      ;
   CALL Z, tool_tiles_to_RAM   ; Copy tiles to working RAM

; Alien 2
   LD hl, alien_parachute      ;
   LD de, $C212 + 1            ; Tiles
   LD b, 8                     ; 8 sprites
   LD a, (RAM_STAR_B_STATE)    ; Load doom sprite?
   CP $7F                      ;
   CALL Z, tool_tiles_to_RAM   ; Copy tiles to working RAM

; Alien 3
   LD hl, alien_parachute      ;
   LD de, $C222 + 1            ; Tiles
   LD b, 8                     ; 8 sprites
   LD a, (RAM_STAR_C_STATE)    ; Load doom sprite?
   CP $7F                      ;
   CALL Z, tool_tiles_to_RAM   ; Copy tiles to working RAM

; Alien 4
   LD hl, alien_parachute      ;
   LD de, $C232 + 1            ; Tiles
   LD b, 8                     ; 8 sprites
   LD a, (RAM_STAR_D_STATE)    ; Load doom sprite?
   CP $7F                      ;
   CALL Z, tool_tiles_to_RAM   ; Copy tiles to working RAM

; Alien 5
   LD hl, alien_parachute      ;
   LD de, $C242 + 1            ; Tiles
   LD b, 8                     ; 8 sprites
   LD a, (RAM_STAR_E_STATE)    ; Load doom sprite?
   CP $7F                      ;
   CALL Z, tool_tiles_to_RAM   ; Copy tiles to working RAM

; Alien 6
   LD hl, alien_parachute      ;
   LD de, $C252 + 1            ; Tiles
   LD b, 8                     ; 8 sprites
   LD a, (RAM_STAR_F_STATE)    ; Load doom sprite?
   CP $7F                      ;
   CALL Z, tool_tiles_to_RAM   ; Copy tiles to working RAM

; Alien 7
   LD hl, alien_parachute      ;
   LD de, $C262 + 1            ; Tiles
   LD b, 8                     ; 8 sprites
   LD a, (RAM_STAR_G_STATE)    ; Load doom sprite?
   CP $7F                      ;
   CALL Z, tool_tiles_to_RAM   ; Copy tiles to working RAM

   RET                         ; End subroutine


;-------------------------------------------------------------------------------------
;-------------------------------------------------------------------------------------
; Round 4
;-------------------------------------------------------------------------------------
;-------------------------------------------------------------------------------------
gsm_load_round_4:
   CALL VDP_off                ; Turn off screen

   LD hl, lightp_sp001_tile    ; 
   CALL load_tile_data_comp0   ; Load tile data

   CALL load_palette_data04    ; Set palette data

   LD hl, round_one_vpos       ;
   LD de, RAM_VPOS_SPRITE      ;
   LD b, 58
   CALL tool_sprites_to_RAM    ; Copy sprites to RAM

   LD hl, round_one_hpos       ;
   LD de, RAM_HPOS_SPRITE      ;
   LD b, 116
   CALL tool_sprites_to_RAM    ; Copy sprites to RAM

   LD a, $00                   ; No blinking
   LD (RAM_COLOR_BLINK), a     ;

   CALL set_timer_030          ; Set timer
   CALL tool_increment_goal_10 ;
   CALL tool_increment_goal_10 ; Goal = Goal + 20
   CALL tool_increment_round   ; Setup round number
   CALL clear_foe_states       ; Clear foe state machines

   CALL VDP_on                 ; Turn on VDP. Immediate interrupt is likely to occur.

   RET                        ; End subroutine

;-------------------------------------------------------------------------------------
;-------------------------------------------------------------------------------------
; Round 5
;-------------------------------------------------------------------------------------
;-------------------------------------------------------------------------------------

;------------------------------------------
; gsm_load_round_3 (17 lines)
;
;------------------------------------------
gsm_load_round_5:
   CALL VDP_off                ; Turn off screen

   CALL load_palette_data05    ; Set palette data

   LD hl, round_3_vpos         ;
   LD de, RAM_VPOS_SPRITE      ;
   LD b, 58
   CALL tool_sprites_to_RAM    ; Copy sprites to RAM

   LD hl, round_3_hpos         ;
   LD de, RAM_HPOS_SPRITE      ;
   LD b, 116
   CALL tool_sprites_to_RAM    ; Copy sprites to RAM

   LD a, $00                   ; No blinking
   LD (RAM_COLOR_BLINK), a     ;

   CALL set_timer_030          ; Set timer
   CALL tool_increment_goal_10 ; Goal
   CALL tool_increment_goal_10 ; Goal
   CALL tool_increment_goal_10 ; Goal = Goal + 30
   CALL tool_increment_round   ; Setup round number

   CALL clear_foe_states       ; Clear foe state machines

   CALL VDP_on                 ; Turn on VDP. Immediate interrupt is likely to occur.

   RET                         ; End subroutine

;-------------------------------------------------------------------------------------
;-------------------------------------------------------------------------------------
; Round 6
;-------------------------------------------------------------------------------------
;-------------------------------------------------------------------------------------

;------------------------------------------
; gsm_load_round_6 (17 lines)
;
;------------------------------------------
gsm_load_round_6:
   CALL VDP_off                ; Turn off screen

   CALL load_palette_data02    ; Set palette data

   LD hl, round_two_vpos       ;
   LD de, RAM_VPOS_SPRITE      ;
   LD b, 58
   CALL tool_sprites_to_RAM    ; Copy sprites to RAM

   LD hl, round_two_hpos       ;
   LD de, RAM_HPOS_SPRITE      ;
   LD b, 116
   CALL tool_sprites_to_RAM    ; Copy sprites to RAM

   LD a, $00                   ; No blinking
   LD (RAM_COLOR_BLINK), a     ;

   CALL set_timer_030          ; Set timer
   CALL tool_increment_goal_10 ; Goal = Goal + 10
   CALL tool_increment_round   ; Setup round number

   CALL clear_foe_states       ; Clear foe state machines

   CALL VDP_on                 ; Turn on VDP. Immediate interrupt is likely to occur.

   RET                         ; End subroutine

;-------------------------------------------------------------------------------------
;-------------------------------------------------------------------------------------
; Sound
;-------------------------------------------------------------------------------------
;-------------------------------------------------------------------------------------

;----------------------------------------------------------
; pg001_sound (40 lines)
;
; Play sound for page 001, title screen
;
; RAM_SOUND_A = index (2 byte)
; $C02C = counter
;
; Read frame delay.
; Decrement frame delay.
; Frame delay 0? Load next data.
; Load sound index.
; Read byte 1 - volume
; Read byte 2 - note
; Read byte 3 - note
; Read byte 4 - delay
;
; hl - must equal pointer to start
; $C02C - must equal $01 to load first value
;
;----------------------------------------------------------
pg001_sound:
; Read frame delay.
   LD a, ($C02C)                ; Load 

; Decrement frame delay.
   DEC a                        ; Decrement
   LD ($C02C), a                ; Save

; Frame delay 0? Load next data.
   CP 0                         ; Compare
   JP NZ, pg001_sound_end       ; Skip to end if not zero

; Load sound index.
   LD a, (RAM_SOUND_A)          ; Load index to HL
   LD h, a                      ;
   LD a, (RAM_SOUND_B)          ;
   LD l, a                      ;
      
; Read byte 1 - volume.
   LD a, (hl)                   ; Read volume

; Check for delimiter
   CP $7F                       ; Delimiter
   JP NZ, pg001_sound_next1     ;

prime_pg001_sound:
   LD hl, pop_goes_the_weasel   ; Reset index
   LD a, h                      ;
   LD (RAM_SOUND_A), a          ;
   LD a, l                      ;
   LD (RAM_SOUND_B), a          ;
   LD a, $01                    ; A = $01
   LD ($C02C), a                ; Set delay
   JP pg001_sound_end           ; End routine

pg001_sound_next1:  
   INC hl                       ;
   OUT ($7F), a                 ; to PSG 

; Read byte 2 - note.
   LD a, (hl)                   ; Read note
   INC hl                       ;
   OUT ($7F), a                 ; to PSG   

; Read byte 3 - note
   LD a, (hl)                   ; Read note
   INC hl                       ;
   OUT ($7F), a                 ; to PSG   

; Read byte 4 - delay
   LD a, (hl)                   ; Read delay
   INC hl                       ;
   LD ($C02C), a                ; to working RAM   

; Store updated pointer
   LD a, h                      ;
   LD (RAM_SOUND_A), a          ; to working RAM  
   LD a, l                      ;
   LD (RAM_SOUND_B), a          ;

pg001_sound_end:
   RET                         ; End subroutine

; Define sound constants
.DEFINE  BLANK_DELAY  2
.DEFINE  SDLY         7
.DEFINE  L_SDLY       14

; Need new data
pop_goes_the_weasel:
 .db $9F, $80, $00, 1  ; ch 1 no volume , note low, note high, frame delay  
 .db $BF, $A0, $00, 1  ; ch 2 no volume , note low, note high, frame delay  
 .db $DF, $C0, $00, 1  ; ch 3 no volume , note low, note high, frame delay  
 .db $FF, $80, $00, 1  ; noise no volume , note low, note high, frame delay  

; Line 1 - ff gg acaf
 .db $B3, $A3, $0B, 1    ;
 .db $D3, $C3, $0B, 1    ;
 .db $90, $83, $0B, SDLY ; F4
 .db $9F, $80, $00, 1  ; pause
 .db $BF, $80, $00, 1  ; pause
 .db $DF, $80, $00, BLANK_DELAY  ; pause
 .db $B3, $A3, $0B, 1    ;
 .db $D3, $C3, $0B, 1    ;
 .db $90, $83, $0B, SDLY ; F4
 .db $9F, $80, $00, 1  ; pause
 .db $BF, $80, $00, 1  ; pause
 .db $DF, $80, $00, BLANK_DELAY  ; pause
 .db $B3, $AF, $09, 1    ;
 .db $D3, $CF, $09, 1    ;
 .db $90, $8F, $09, SDLY ; G4
 .db $9F, $80, $00, 1  ; pause
 .db $BF, $80, $00, 1  ; pause
 .db $DF, $80, $00, BLANK_DELAY  ; pause
 .db $B3, $AF, $09, 1    ;
 .db $D3, $CF, $09, 1    ;
 .db $90, $8F, $09, SDLY ; G4
 .db $9F, $80, $00, 1  ; pause
 .db $BF, $80, $00, 1  ; pause
 .db $DF, $80, $00, BLANK_DELAY  ; pause
 .db $B3, $AE, $08, 1    ;
 .db $D3, $CE, $08, 1    ;
 .db $90, $8E, $08, SDLY ; A5
 .db $9F, $80, $00, 1  ; pause
 .db $BF, $80, $00, 1  ; pause
 .db $DF, $80, $00, BLANK_DELAY  ; pause
 .db $B3, $A7, $07, 1    ;
 .db $D3, $C7, $07, 1    ;
 .db $90, $87, $07, SDLY ; C5
 .db $9F, $80, $00, 1  ; pause
 .db $BF, $80, $00, 1  ; pause
 .db $DF, $80, $00, BLANK_DELAY  ; pause
 .db $B3, $AE, $08, 1    ;
 .db $D3, $CE, $08, 1    ;
 .db $90, $8E, $08, SDLY ; A5
 .db $9F, $80, $00, 1  ; pause
 .db $BF, $80, $00, 1  ; pause
 .db $DF, $80, $00, BLANK_DELAY  ; pause
 .db $B3, $A3, $0B, 1    ;
 .db $D3, $C3, $0B, 1    ;
 .db $90, $83, $0B, L_SDLY ; F4
 .db $9F, $80, $00, 1  ; pause
 .db $BF, $80, $00, 1  ; pause
 .db $DF, $80, $00, BLANK_DELAY*2  ; pause

; Line 2 - c ff gg af
 .db $B3, $A7, $07, 1    ;
 .db $D3, $C7, $07, 1    ;
 .db $90, $87, $07, SDLY ; C5
 .db $9F, $80, $00, 1  ; pause
 .db $BF, $80, $00, 1  ; pause
 .db $DF, $80, $00, BLANK_DELAY  ; pause
 .db $B3, $A3, $0B, 1    ;
 .db $D3, $C3, $0B, 1    ;
 .db $90, $83, $0B, SDLY ; F4
 .db $9F, $80, $00, 1  ; pause
 .db $BF, $80, $00, 1  ; pause
 .db $DF, $80, $00, BLANK_DELAY  ; pause
 .db $B3, $A3, $0B, 1    ;
 .db $D3, $C3, $0B, 1    ;
 .db $90, $83, $0B, SDLY ; F4
 .db $9F, $80, $00, 1  ; pause
 .db $BF, $80, $00, 1  ; pause
 .db $DF, $80, $00, BLANK_DELAY  ; pause
 .db $B3, $AF, $09, 1    ;
 .db $D3, $CF, $09, 1    ;
 .db $90, $8F, $09, SDLY ; G4
 .db $9F, $80, $00, 1  ; pause
 .db $BF, $80, $00, 1  ; pause
 .db $DF, $80, $00, BLANK_DELAY  ; pause
 .db $B3, $AF, $09, 1    ;
 .db $D3, $CF, $09, 1    ;
 .db $90, $8F, $09, L_SDLY ; G4
 .db $9F, $80, $00, 1  ; pause
 .db $BF, $80, $00, 1  ; pause
 .db $DF, $80, $00, BLANK_DELAY  ; pause
 .db $B3, $AE, $08, 1    ;
 .db $D3, $CE, $08, 1    ;
 .db $90, $8E, $08, SDLY ; A5
 .db $9F, $80, $00, 1  ; pause
 .db $BF, $80, $00, 1  ; pause
 .db $DF, $80, $00, BLANK_DELAY  ; pause
 .db $B3, $A3, $0B, 1    ;
 .db $D3, $C3, $0B, 1    ;
 .db $90, $83, $0B, L_SDLY ; F4
 .db $9F, $80, $00, 1  ; pause
 .db $BF, $80, $00, 1  ; pause
 .db $DF, $80, $00, BLANK_DELAY*2  ; pause

; Line 3 - c ff gg acaf
 .db $B3, $A7, $07, 1    ;
 .db $D3, $C7, $07, 1    ;
 .db $90, $87, $07, L_SDLY ; C5
 .db $9F, $80, $00, 1  ; pause
 .db $BF, $80, $00, 1  ; pause
 .db $DF, $80, $00, BLANK_DELAY  ; pause
 .db $B3, $A3, $0B, 1    ;
 .db $D3, $C3, $0B, 1    ;
 .db $90, $83, $0B, SDLY ; F4
 .db $9F, $80, $00, 1  ; pause
 .db $BF, $80, $00, 1  ; pause
 .db $DF, $80, $00, BLANK_DELAY  ; pause
 .db $B3, $A3, $0B, 1    ;
 .db $D3, $C3, $0B, 1    ;
 .db $90, $83, $0B, L_SDLY ; F4
 .db $9F, $80, $00, 1  ; pause
 .db $BF, $80, $00, 1  ; pause
 .db $DF, $80, $00, BLANK_DELAY  ; pause
 .db $B3, $AF, $09, 1    ;
 .db $D3, $CF, $09, 1    ;
 .db $90, $8F, $09, SDLY ; G4
 .db $9F, $80, $00, 1  ; pause
 .db $BF, $80, $00, 1  ; pause
 .db $DF, $80, $00, BLANK_DELAY  ; pause
 .db $B3, $AF, $09, 1    ;
 .db $D3, $CF, $09, 1    ;
 .db $90, $8F, $09, L_SDLY ; G4
 .db $9F, $80, $00, 1  ; pause
 .db $BF, $80, $00, 1  ; pause
 .db $DF, $80, $00, BLANK_DELAY  ; pause
 .db $B3, $AE, $08, 1    ;
 .db $D3, $CE, $08, 1    ;
 .db $90, $8E, $08, SDLY ; A5
 .db $9F, $80, $00, 1  ; pause
 .db $BF, $80, $00, 1  ; pause
 .db $DF, $80, $00, BLANK_DELAY  ; pause
 .db $B3, $A7, $07, 1    ;
 .db $D3, $C7, $07, 1    ;
 .db $90, $87, $07, SDLY ; C5
 .db $9F, $80, $00, 1  ; pause
 .db $BF, $80, $00, 1  ; pause
 .db $DF, $80, $00, BLANK_DELAY  ; pause
 .db $B3, $AE, $08, 1    ;
 .db $D3, $CE, $08, 1    ;
 .db $90, $8E, $08, SDLY ; A5
 .db $9F, $80, $00, 1  ; pause
 .db $BF, $80, $00, 1  ; pause
 .db $DF, $80, $00, BLANK_DELAY  ; pause
 .db $B3, $A3, $0B, 1    ;
 .db $D3, $C3, $0B, 1    ;
 .db $90, $83, $0B, L_SDLY ; F4
 .db $9F, $80, $00, 1  ; pause
 .db $BF, $80, $00, 1  ; pause
 .db $DF, $80, $00, BLANK_DELAY*2  ; pause

; Line 4 - d' g b a f

 .db $B3, $A9, $0C, 1    ;
 .db $D3, $C9, $0C, 1    ;
 .db $90, $89, $0C, L_SDLY ; Ds4
 .db $9F, $80, $00, 1  ; pause
 .db $BF, $80, $00, 1  ; pause
 .db $DF, $80, $00, BLANK_DELAY*2  ; pause
 .db $B3, $AF, $09, 1    ;
 .db $D3, $CF, $09, 1    ;
 .db $90, $8F, $09, SDLY ; G4
 .db $9F, $80, $00, 1  ; pause
 .db $BF, $80, $00, 1  ; pause
 .db $DF, $80, $00, BLANK_DELAY*2  ; pause
 .db $B3, $AF, $07, 1    ;
 .db $D3, $CF, $07, 1    ;
 .db $90, $8F, $07, SDLY ; B5
 .db $9F, $80, $00, 1  ; pause
 .db $BF, $80, $00, 1  ; pause
 .db $DF, $80, $00, BLANK_DELAY*2  ; pause
 .db $B3, $AE, $08, 1    ;
 .db $D3, $CE, $08, 1    ;
 .db $90, $8E, $08, SDLY ; A5
 .db $9F, $80, $00, 1  ; pause
 .db $BF, $80, $00, 1  ; pause
 .db $DF, $80, $00, BLANK_DELAY*2  ; pause
 .db $B3, $A3, $0B, 1    ;
 .db $D3, $C3, $0B, 1    ;
 .db $90, $83, $0B, L_SDLY*2 ; F4
 .db $9F, $80, $00, 1  ; pause
 .db $BF, $80, $00, 1  ; pause
 .db $DF, $80, $00, BLANK_DELAY*2  ; pause

 .db $7F               ; Delimiter
 
; Need to know when data ends


; low byte, then high byte 
;----------------------
pg001_note_table:
;    LOW  HIGH
; .db $00, $00  ; No sound - pause
; .db $08, $0E  ; G3 2
; .db $02, $0E  ; GS3 4
; .db $08, $0C  ; A4 6
; .db $01, $0C  ; AS4 8
; .db $0D, $0F  ; B4 10
; .db $0E, $0F  ; C4 12
; .db $01, $0E  ; CS4 14
; .db $05, $0D  ; D4 16
; .db $09, $0C  ; DS4 18
; .db $0E, $0B  ; E4 20
; .db $03, $0B  ; F4 22
; .db $09, $0A  ; FS4 24
; .db $0F, $09  ; G4 26
; .db $07, $09  ; GS4 28
; .db $0E, $08  ; A5 30
; .db $06, $08  ; AS5 32
; .db $0F, $07  ; B5 34
; .db $07, $07  ; C5 36
;----------------------
 
;FF GG ACAF
;C FF GG AF
;C FF GG ACAF
;D' G B A F

;-----------------------------------
; sound_effects (27 lines)
;
; RAM_SOUND_ADDRESS    $C01E <-- Must be primed before calling this routine
; RAM_SOUND_DURATION   $C021
; RAM_SOUND_ENABLE     $C022
;
;-----------------------------------
sound_effects:
   LD a, (RAM_SOUND_ENABLE)   ; If sound is disabled, skip.
   CP $00                     ;
   JP Z, se_end1              ;

   LD a, (RAM_SOUND_DURATION) ; If sound is playing, skip.
   DEC a                      ; Decrement
   JP NZ, se_end2             ;

   LD hl, (RAM_SOUND_ADDRESS) ;
   LD a, (hl)                 ; Load volume
  
   CP $D0                     ; Delimiter reached?
   JP Z, se_reset             ; Reset address   

   INC hl                     ;
   OUT ($7F), a               ; to PSG 

   LD a, (hl)                 ; Load noise byte
   INC hl                     ;
   OUT ($7F), a               ; to PSG 

   LD a, (hl)                 ; Load duration
   INC hl                     ;

   LD (RAM_SOUND_ADDRESS), hl ; Save new address

se_end2:
   LD (RAM_SOUND_DURATION), a ; Store new duration
se_end1
   RET                        ; End subroutine

se_reset:
   LD hl, SHOT_NOISE          ; Reset address
   LD (RAM_SOUND_ADDRESS), hl ;
   LD a, $00                  ; Disable sound
   LD (RAM_SOUND_ENABLE), a   ;
   LD a, $01                  ; Set duration to expire

   JP se_end2                 ;

SHOT_NOISE:
 .db $F3, $E0, 4   ; noise volume, noise data, duration
 .db $F3, $E1, 4   ; noise volume, noise data, duration
 .db $F3, $E2, 4   ; noise volume, noise data, duration
 .db $F3, $E3, 4   ; noise volume, noise data, duration
 .db $FF, $E7, 1   ; noise volume, noise data, duration
 .db $D0, $D0, $D0 ; Delimiter
  



;------------------------------------------
;------------------------------------------
; Tile Data 
;------------------------------------------
;------------------------------------------


;-----------------------------------------
; Sprite Data
;-----------------------------------------

; Round 1 sprites
.include "threestarsprites.txt"

; Round 2 sprites
.include "stardragonsp.txt"

; Round 3 sprites
.include "aliensprites.txt"

;-----------------------------------------
; Background Data
;-----------------------------------------


; Not compressed
lightp_bg001_bg:
.include "bg001bg.txt"

; Not compressed
lightp_bg:
.include "lp_bg.txt"


;----------------------------------------
; Tile data at $4000
.BANK 1 SLOT 1
.org $0000

;------------------------------------------
;------------------------------------------
; Tile Data 
;------------------------------------------
;------------------------------------------

tool_copy_loop:
   LD a, (hl)                 ; Read tile data
   OUT (c), a                 ; Write to VRAM
   INC hl                     ; Increment hl

   DEC b                      ; Loop until all data is copied.
   JP NZ, tool_copy_loop      ; 

   RET                        ; End subroutine

;------------------------------------------
; load_tile_data_comp0 (26 lines) 
;
; Load compressed tile data. HL -> VRAM
; Make sure HL is loaded before calling this routine!
;
; nn != $7F => Normal load
; $7F nn yy => Load nn, yy times
; Stop if yy equals $7F
;
;------------------------------------------
load_tile_data_comp0:
   LD c, VDP_ADDR             ; Setup the address
 
   LD a, $00                  ; XX00
   OUT (c), a                 ;
   LD a, $00                  ; 00XX 
   OUT (c), a                 ;

   LD c, VDP_DATA             ; Setup the data

ltdc0_loop:
   LD a, (hl)                 ; Read data
   INC hl                     ;
   CP $7F                     ; Multiple load?
   JP NZ, ltdc0_byte          ;

   LD a, (hl)                 ; Read data
   INC hl                     ;
   LD e, a                    ;
   LD a, (hl)                 ; Read number to load   
   INC hl                     ;
   CP $7F                     ; If number to reload is $7F, stop loading.
   JP Z, ltdc0_end            ;  
   LD b, a                    ;
   LD a, e                    ; Put data back in a

ltdc0_multibyte:
   OUT (c), a                 ; Write data
   DEC b                      ; Decrement
   JP NZ, ltdc0_multibyte     ; Write until b is 0
   JP ltdc0_loop              ;   

ltdc0_byte:
   OUT (c), a                 ; Copy one byte
   JP ltdc0_loop              ;

ltdc0_end:
   RET                        ; End subroutine

;------------------------------------------
; load_bg_data_00 (12 lines) 
;
; Load background data. HL -> VRAM
; Load HL before calling this routine!
;------------------------------------------
load_bg_data_00:
   LD c, VDP_ADDR             ; Setup the address
 
   LD a, $FF                  ; XXFF
   OUT (c), a                 ;
   LD a, $37                  ; 37XX 
   OUT (c), a                 ;

   LD c, VDP_DATA             ; Setup the data
   LD e, 24                   ; 24 rows

bg00_loop:
   LD b, 64                   ; 64 bytes per row
   CALL tool_copy_loop        ;

   DEC e                      ; Loop until all rows are written.
   JP NZ, bg00_loop           ;

   RET                        ; End subroutine


;------------------------------------------
; load_tile_data_100 (8 lines) 
;
; Load background data. HL -> VRAM $0100
; Load HL before calling this routine!
;------------------------------------------
load_tile_data_100:
   LD c, VDP_ADDR             ; Setup the address
 
   LD a, $00                  ; XX00
   OUT (c), a                 ;
   LD a, $20                  ; 20XX 
   OUT (c), a                 ;

   LD c, VDP_DATA             ; Setup the data

   CALL ltdc0_loop            ; Load compressed data

   RET                        ; End subroutine

;----------------------------------------------------------
; load_palette_data00 (17 lines)
;
; Load palette data to RAM_FRAME_CTR.
;----------------------------------------------------------
load_palette_data00:
   LD hl, palette_data00       ; tile_data is defined in another file
load_palette_data:
   LD c, VDP_ADDR              ; Setup the address

   LD a, $00                   ; Low address byte
   OUT (c),a                   ;
   LD a, $C0                   ; High address byte
   OUT (c),a                   ;

   LD c, VDP_DATA              ; Setup the data
   LD b, 32                    ;
   LD de, RAM_RESTORE_COLOR    ; 

color_copy_loop:
   LD a, (hl)                  ; Read tile data
   OUT (c), a                  ; Write to color RAM
   LD (de), a                  ; Copy to RAM
   INC hl                      ; Increment hl
   INC de                      ; Increment de

   DEC b                       ; Loop until all tile data is copied.
   JP NZ, color_copy_loop      ; 
   
   RET                         ; End subroutine  

load_palette_data01:
   LD hl, palette_data01       ; tile_data is defined in another file
   CALL load_palette_data      ;
   RET                         ; End subroutine  

load_palette_data02:
   LD hl, palette_data02       ; tile_data is defined in another file
   CALL load_palette_data      ;
   RET                         ; End subroutine  

load_palette_data03:
   LD hl, palette_data03       ; tile_data is defined in another file
   CALL load_palette_data      ;
   RET                         ; End subroutine  

load_palette_data04:
   LD hl, palette_data04       ; tile_data is defined in another file
   CALL load_palette_data      ;
   RET                         ; End subroutine  

load_palette_data05:
   LD hl, palette_data05       ; tile_data is defined in another file
   CALL load_palette_data      ;
   RET                         ; End subroutine  

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

; color bytes 0, 7, and 13 determine BG

palette_data00:
.db $00 $0A $0F $1A $01 $22 $28 $25 $2A $03 $0C $1F $30 $33 $3C $3F
.db $00 $0A $0F $1A $01 $22 $28 $25 $2A $03 $0C $1F $30 $33 $3C $3F
 
palette_data01:
.db $00 $0A $0F $1A $01 $22 $28 $25 $2A $03 $0C $1F $30 $33 $3C $3F
.db $00 $0A $0F $1A $01 $22 $28 $25 $2A $03 $0C $1F $30 $33 $3C $3F

palette_data02:
.db $00 $0A $0F $1A $01 $22 $28 $25 $2A $03 $0C $1F $30 $33 $3C $3F
.db $00 $0A $0F $1A $01 $22 $28 $25 $2A $03 $0C $1F $30 $33 $3C $3F

palette_data03:
.db $00 $0A $0F $1A $01 $22 $28 $25 $2A $03 $0C $1F $30 $33 $3C $3F
.db $00 $0A $0F $1A $01 $22 $28 $25 $2A $03 $0C $1F $30 $33 $3C $3F

palette_data04:
.db $00 $0A $0F $1A $01 $22 $28 $25 $2A $03 $0C $1F $30 $33 $3C $3F
.db $00 $0A $0F $1A $01 $22 $28 $25 $2A $03 $0C $1F $30 $33 $3C $3F

palette_data05:
.db $00 $0A $0F $1A $01 $22 $28 $25 $2A $03 $0C $1F $30 $33 $3C $3F
.db $00 $0A $0F $1A $01 $22 $28 $25 $2A $03 $0C $1F $30 $33 $3C $3F

;-----------------------------------------
; Tile Data
;-----------------------------------------

; Compressed
lightp_tile:
.include "lpc_tile.txt"

; Compressed
lightp_sp001_tile:
.include "sp001c.txt"

; Not compressed
lightp_bg001_tile:
.include "bg001c.txt"



