;
; Quadrillion
; Coded by Csabo of LOD, 2004.
;
; #gr1 changes to Assemble with AtAsm Nov 11, 2010
; #gr2 add emulation layer to run on Atari + VBXE
;
;
; Run address not needed with loader
;
;	*=$2e0
;	.word main_start
	*=$4000	; #gr1
;
; RMT Player stuff
;
rmt_music_data	= $a000
rmt_init = $ac00
rmt_play = $ac03

rmt_silence = $ac09
;
;

ctemp	= $80
ctemp2	= $81
text_dest	= $82	; 16 bit
message_ptr	= $84	; 16 bit
cur_col	= $86	; current color
cur_pos	= $88	; current position on screen (pointer)
cur_pos2= $8A	; temp
chk_pos	= $8C	; check position: always points to whole block
chk_pos2= $8E
block_ptr	= $90 ; BC
ptr		= $92 ; C0
baseptr		= $94 ; e4 ; 16 bit
change_palette	= $96	; Flag/count for change of palette 1 entries
palette_pointer	= $97 ; Pointer to currently changing palette entry data
rgbtemp		= $99	; 3 bytes RGB temp data VBlank use
palette_colour	= $9c	; Requested colour for palette 1 fill
; ?ptr? variables must be kept contiguous
lptr2	= $B0		; second pointers for saved lum/col map
cptr2	= $B2
lptr	= $B4		; generic lum/col map pointers
cptr	= $B6
bptr	= $B8		; generic bitmap pointer
zvbtemp1		= $ba	; VBlank use only, 2 bytes
;
; NOTE:  RMT player uses $CB thru $DE
;
; vbxe_ptr also in quadload2 loader module
;
vbxe_ptr	= $e8	; Points to VBXE $D600 or $D700
ztemp1		= $fa	; ea ; temp work variable
ztemp2		= $fc	; 2 bytes temp
ztemp3		= $fe	; mainline code temp


lives		= $413 ; #gr2 change $Fx values to $41x
level		= $414
levels_cleared	= $415
last_level	= $416	; Working variable - current highest allowed level to start/skip to
blocks		= $417	; Number of blocks remaining

current_block	= $418	; for level drawing
current_count	= $419	; number of blocks to put
current_row	= $41A	; number of blocks drawn in current row
abortflag	= $41b	; Esc pressed flag
colour_index	= $41c ; Colour index
skipflag	= $41d	; Skip level flag

bitmap_data	= $2000	; Plus/4 bitmap data screen
plus4attrib	= $1800	; Plus/4 colour+luma attributes

atari_bitmap_data = $6010 ; Atari bitmap data screen (200 scanlines x 40 bytes)

temp_color	= $600 ; a400
temp_lum	= $700 ; a500
sprite_temp	= $800 ; a600
score		= $900 ; a700
score_curr	= $910 ; a800
score_high	= $920 ; a900
message_temp	= $940 ; 18 bytes ? #gr2 Change $Bxxx from $7xxx

ted_shadows	= $0400	; #gr2 Shadow copies of TED Registers

mlen = 18

; get_ROM_byte = $0473	; #gr2 include these routines in program
; set_ptr = $9DCA		; set 3B/3C (X,Y)

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

speed = 7

current_note	= $420
notelen		= $421
step		= $422
step2		= $423
basecnt		= $424
baselen		= $425
baseptrcnt	= $426
music_flag	= $427
pauseflag	= $428
voice1freq	= $429	; 2 bytes
voice2freq	= $42b	; 2 bytes
stick0		= $42d	; Use this to refer to joystick.  VBD routine
sstrig0		= $42e	; Use this to refer to fire button.
inhibit_attr_blitflag = $42f
text_color1	= $430
text_color2	= $431
inhibit_tedsound= $432	; Flag - inhibit TED sound translation
inhibit_vbblits	= $433	; Flag - inhibit all VBlank Blit operations
key_delay	= $434	; Joystick/key delay for menu operations
pf2_fillflag	= $435 ; Nonzero = request VBI to do extra blit for PF2 fill
block_col	= $436	; 92 ; BE
block_col2	= $437	; 93 ; BF
cur_x	= $438	; was 80	; 0-3: position within one char
cur_y	= $439	; 81	; 0-3: position within one char
x_offs	= $43a	; 82	; 0/1: if 1, then on right side of big block
y_offs	= $43b	; 83	; 0/1: if 1, then lower part of big block
cur_dir	= $43c	; 84	; 0 = up, 1=down
cur_lr	= $43d	; was 85	; 0 = straight, 1=right, $FF=left
rmt_start = $43e ; $80 = request new RMT piece start, nonzero = song in progress
rmt_song = $43f	; New RMT song to start
rmt_timer = $440
scroller_offset	= $441	; offset for Scroller start (16-bit)
scroller_fine	= $443	; Fine scroll value
ntsc_counter	= $444	; Countdown for VBD skip for certain routines if NTSC system
value_counter	= $445	; Count for decrement of block value
block_value	= $446	; Value of blocks
value_changed	= $447	; Flag, non-zero = need to update block Value display
nobonus		= $448	; Flag, nonzero = don't give any more bonus lives
instruction_flag = $449 ; Flag, instructions being shown, 0=no 1=yes
starting_level	= $44a ; BCD - save start level selected by player
;
; extracts directional info from PORTA and current keypress
; 
; Atari machine equates
;
pokmsk	= $10
brkflg	= $11
rtclock	= $12
attract	= $4d
vdslst	= $200
vvbi	= $222
vvbd	= $224
sdmctl	= $22f
sdslst	= $230
sskctl	= $232
colpm0	= $2c0
ch	= $2fc
ssflag	= $2ff
strig0	= $d010
pal	= $d014
colpf0	= $d016
colpf1	= $d017
colpf2	= $d018
colpf3	= $d019
colbak	= $d01a
consol	= $d01f
audf1	= $d200
audc1	= $d201
audf2	= $d202
audc2	= $d203
audf3	= $d204
audc3	= $d205
audf4	= $d206
audc4	= $d207
audctl	= $d208
kbcode	= $d209
random	= $d20a
skctl	= $d20f
porta	= $d300
portb	= $d301
chbase	= $d409
wsync	= $d40a
vcount	= $d40b
nmien	= $d40e
;
; VBXE equates
;
v_video_control = $40	; Video control
v_xdl_adr0 = $41 ; XDL address pointer
v_csel	= $44
v_psel	= $45
v_cr	= $46
v_cg	= $47
v_cb	= $48
v_bl_adr0 = $50 ; BCB address pointer
v_blitter_start = $53 ; Blitter start/stop control
v_priority0 = $55 ; Priority register 0
v_memac_control	= $5e ; MEMAC control
v_memac_bank_sel = $5f ; MEMAC bank selection

vbxe_attrib_map	= $8000	; VBXE attribute map within VBXE RAM

;	.opt list
	;
	; init screen
	;
main_start
	jsr atari_init	; #gr2 Initialize Atari stuff
	lda #1
	sta starting_level
	;
	LDA #$00
	LDY #$05
is_00	STA score_high,y	; init high score
	DEY
	BPL is_00
	;
	LDA highest_selectable_level
	STA last_level		; Highest level allowed to start
	;
	jsr zero_score
new_game
	lda random
	jsr set_logo_colour
	lda #0
 	jsr fadeout
	jsr set_inhibit_vbblits
	LDA #$00
	sta nobonus
	sta scroller_offset
	sta scroller_offset+1
	STA lives
;	STA music_flag
	STA level
	STA levels_cleared
	;
	;
	; --- create "status bar"
	;
	LDX #$30
	LDY #$22	; was $2370 go up 1 - $2880, move up 4 lines
	STX text_dest
	STY text_dest+1
	;
	lda #6
	sta text_color2
	LDX #$00
ws_color
	jsr calc_attr_text_dest
	ldy #0
	lda text_data,x
	sta text_color1
	inx
ws_02	
	LDA text_data,x		; read next byte
	BNE ws_01		; non-zero?
	;
	inx
	lda text_data,x
	beq sidebar_done
	sta text_color1
	ldy #40			; was 38
	stx ztemp3
	ldx #9
ws_secondline
	lda text_color1
	jsr put_color
	dex
	bpl ws_secondline
	ldx ztemp3
	LDA text_dest		; $00 means next "line"
	CLC
	ADC #$78		; #gr4 was $d0 then b8
	STA text_dest
	LDA text_dest+1
	ADC #$03		; #gr9 was 4
	STA text_dest+1
	inx
	jmp ws_color
	;
ws_01	
	bmi ws_skip_write	; Don't write chrs >$80
	sty ztemp3
	JSR write_letter
	ldy ztemp3
ws_skip_write
	lda text_color1
	jsr put_color
	;
ws_03	INX
	CPX #text_data_end - text_data
	Bcc ws_02
sidebar_done
	lda #$f7
	ldx #9
do_attr_lname
	sta $1f66,x
	sta $1f8e,x
	dex
	bpl do_attr_lname
	;
	; ---
	;
;	LDA #$B8
;	STA text_dest
;	LDA #$24
;	STA text_dest+1
	;
;	JSR write_title
	;
	; ---
	;
	JSR write_score		; write zeros
	lda starting_level	; Saved start level
	sta level
;	JSR inc_level		; level 1 + write
	;
	;
	JSR draw_level_back
	;
	; ---
	;
	lda #4
	sta cur_col
	lda #$2
	sta text_color2
	lda #$0
	sta text_color1

	JSR clear_large

;	jsr clear_inhibit_attr ; #gr9
	lda #$6
 	sta text_color1
	lda #0
	sta text_color2
 	LDX #$70
 	LDY #$30
 	LDA #<text_pressi
 	JSR write_message_pos
;
	lda #$6
 	sta text_color1
	lda #0
	sta text_color2
 	LDX #$b0
 	LDY #$31
 	LDA #<text_instructions
 	JSR write_message_pos
;
	lda #$da
 	sta text_color1
	lda #0
	sta text_color2
 	LDX #$70
 	LDY #$2b
 	LDA #<text_movejoy
 	JSR write_message_pos
	lda #$da
 	sta text_color1
	lda #0
	sta text_color2
 	LDX #$b0
 	LDY #$2c
 	LDA #<text_toselect
 	JSR write_message_pos
	;
	; ---
	;
	lda #$db
	sta text_color1
	lda #0
	sta text_color2
	LDX #$f0
	LDY #$2d	; was 2f30
	LDA #<text_start_level
	JSR write_message_pos
	;
	JSR write_high_score_status
	;
	; --- music init
	LDA #$03
	STA ted_shadows+$10	; #gr2
	;
	LDX #$FF
	STX baseptrcnt
	INX
	STX step
	STX step2
	STX ptr
	STX basecnt
;	STX reverse+1 ; #gr6 self-mod
	INX
	STX notelen
	STX baselen
	LDA #$80
	STA ptr+1
	;
	LDA #$04
	STA current_note
	jsr clear_inhibit_vbblits
;
; Start main music in RMT
;
 	lda #1
	jsr fadeout
	lda #0
	sta rmt_song
	lda #$80
 	sta rmt_start
	lda #$ff
	sta ch
	;
	JMP ml_02
	;
	; ---
	;
menu_loop
	DEC current_row
	BNE menu_loop1
	;
next_bline
	JSR next_block_line
	;
	LDA bptr+1
	CMP #$28
	BNE ml_03
	;
	LDX #$0A
ml_04	JSR inc_lptr_40
	JSR inc_bptr_140
	DEX
	BNE ml_04
	;
ml_03	LDA bptr+1
	CMP #$3C
	BEQ ml_02
	BNE ml_01
	;
ml_02	JSR init_block_pos
	;
ml_01	LDA #14
	STA current_row
	;
menu_loop1
;	lda consol
;	and #1
	lda rtclock+2
	and #$7f
	bne ml_check_fire
	lda random
	jsr set_logo_colour
ml_check_fire
	lda sstrig0
	bne ml_06	; #gr2
;	BEQ ml_06
	;
	JMP menu_cont
	;
ml_06	
;
; Check for Instructions request
;
ml_chkins
	lda ch
	and #$3f
	cmp #13
	bne not_key_i
	lda #$ff
	sta ch
	jsr show_instructions
	lda #0				; Plain block
	ldx #<(atari_bitmap_data+5443)
	ldy #>(atari_bitmap_data+5443)	; @ 3,17
	jsr write_block_atari
	lda #1				; Star block
	ldx #<(atari_bitmap_data+6083)
	ldy #>(atari_bitmap_data+6083)	; @ 3,19
	jsr write_block_atari
	lda #3				; Disk block
	ldx #<(atari_bitmap_data+6723)
	ldy #>(atari_bitmap_data+6723)	; @ 3,21
	jsr write_block_atari
	lda #2				; Skull block
	ldx #<(atari_bitmap_data+6745)
	ldy #>(atari_bitmap_data+6745)	; @ 25,21 
	jsr write_block_atari
wait_instr
;
; Check for codes
;
	lda ssflag
	beq wait_instr1
	lda ch
	cmp #139	; Unlock
	bne ml_codes1
	lda max_allowable_level
	sta last_level
	lda #$ff
	sta ch
ml_codes1
wait_instr1
	ldx ch
	inx
	bne ml_hideins
;	lda consol
;	and #1
	lda sstrig0
	beq ml_hideins
	lda porta
	and #$c
	eor #$c
	bne ml_hideins
	lda rtclock+2
	and #$7f
	bne wait_instr
	lda random
	jsr set_logo_colour
	jmp wait_instr

ml_hideins
	lda #$ff
	sta ch
	jsr hide_instructions
not_key_i
	LDA vcount	; #gr2 was $FF1D
	CMP #$08	; #gr3 was $20
	BCS ml_06b
	;
;	LDX #$01
;	STX music_flag
	;
ml_06b	CMP #$68	; #gr2 was $CC
	BCs ml_06ba
jmenu1
	jmp menu_loop1
ml_06ba
	;
;	LDA music_flag
;	BEQ jmenu1
	;
;	DEC music_flag
	;
	; --------
	;
;	LDX notelen ; #gr6 
;	DEX ; #gr6 
;	BNE ml_23 ; #gr6 
	;
;	LDA #$BF		; check joystick right
	lda key_delay
	beq ml_checkkey
	lda #$f
	bne ml_checkkey2
ml_checkkey
	JSR query_keyboard
ml_checkkey2
	TAY
	AND #$08
	BNE ml_20
	;
	LDA level
	CMP last_level
	BCS ml_20
	;
	JSR inc_level

	;
	JMP ml_23
	;
ml_20	TYA			; check joystick left
	AND #$04
	BNE ml_23a
	;
	SED
	LDA level
	SEC
	SBC #$01
	CLD
	BEQ ml_23
	STA level
	;
ml_23
;	JSR write_level		; Don't do it in status area on menu
	lda #6
	sta key_delay
	;
ml_23a	; - write level into box
	;	
	LDX #$70
	STX text_dest
	LDX #$2e	; was 2fb0
	STX text_dest+1
	;
	LDA level
	JSR write_two_digits
	;
	; -----------------------------
	; MUSIC
	;  This part replaced - RMT tune
	;
rest1	
;b2	
;b1	
;nowrap	
;not_chord	
;ch2	
;ex1	
;now1    ;
;reverse	
;not_neg
;do_rev	
;not_above
quiet	
;set_freq
	;
music_end
	;
	lda random
	AND #$0F
;	tax
;	lda block_colours,x
	JSR change_block_col_new	; was without _new
	;
	LDX #$00
;	lda random
;	and #3
;	tax
	JSR draw_new_block	; draw top/bottom blocks
	;
	JMP menu_loop
	;
	; ---
	;
menu_cont
;	;JSR wait_space
	;
	LDA #$00
	STA ted_shadows+$11		; sound off
	;
	jsr zero_score
	jsr write_score
	LDA #$02		; 2 (+1 when level starts)
	STA lives
	lda level
	sta starting_level
	BNE new_level_noinc	; always jump
	;
	; ###############################################################
	;
new_level
	JSR inc_level
	;
new_level_noinc
	lda rmt_timer
	beq new_level2
	lda sstrig0
	bne new_level_noinc
	lda #1
	sta rmt_timer
new_level2
;	LDA lives
;	CMP #$06
;	BEQ dont_add_lives
	lda nobonus
	bne dont_add_lives	; No bonus lives once Level 20 completed
 	INC lives
dont_add_lives
	;
	; -------------
	;
level_restart
	jsr rmt_silence	
	lda #120
	sta rmt_timer
	lda #$0e
	sta rmt_song
	lda #$80
	sta rmt_start	; Request RMT start for level music
	lda #0
	jsr fadeout	; #gr9 testing
	lda #0
	sta xdl_scroller_adr
	lda #$20
	sta xdl_scroller_adr+1		; Reset scroller
	sta inhibit_attr_blitflag
	lda #<blits_large_window_lores
	jsr doblit_setres_middle
	lda #$ff
	sta pf2_fillflag
	JSR draw_level_back
	;
	; --- ------------------------------------------------
	; DRAW LEVEL
	;
	LDA #$48		; default ball start pos (if not specified by level)
	STA cur_pos
	LDA #$26
	STA cur_pos+1
	;
	JSR init_block_pos
	;
	LDA #$00
	STA blocks	; reset number of blocks per level
	STA current_row
	;
	LDA #$11
	STA block_col2	; default color (if not specified by level)
	;
	LDX level
	LDY level_ptr_hi-1,x
	LDA level_ptr_lo-1,x
	TAX
	;
	;LDY #$B2
	;LDX #$0D
	;
	JSR set_ptr	; set 3B/3C
	;
data_loop
	JSR get_ROM_byte	; get one byte
	TAX			; save it for later
	bne data_loop1
	jmp level_done
data_loop1
	;
	CMP #$07 		; 07 = ball start position
	BNE not_start_pos
	;
	LDA bptr		; copy current position
	STA cur_pos
	LDA bptr+1
	STA cur_pos+1
	;
	BNE data_loop		; always jump
not_start_pos
	;
	AND #$07
	STA current_block
	;
	LDA block_col2		; restore color that may have been changed by a single piece
	STA block_col
	;
	TXA
	LSR a			; upper 5 bits = repetition
	LSR a
	LSR a
	STA current_count
	BNE not_col_change
	;
	LDA current_block
	JSR change_block_col_new
	STA block_col2		; set permanent color
	BNE data_loop		; always jump
	;
not_col_change
	CMP #$10
	BCC block_loop
	;
	LDA current_count	; single piece
	JSR change_block_col_new
	;
	LDA #$01
	STA current_count
	;
block_loop
	LDX current_block
	BNE dont_count_block
	;
	SED
	LDA blocks
	CLC
	ADC #$01
	STA blocks
	CLD
	;
dont_count_block
	CPX #$07
	BEQ skip_draw
	;
	LDA bptr+1		; safety check...
	CMP #$3C		; make sure we stop at bottom of screen.
	BEQ level_done
	;
	JSR draw_new_block
	JMP d1
	;
skip_draw
	JSR skip_block
	;
d1	INC current_row
	LDA current_row
	CMP #14
	BNE not_row_end
	;
	; ---
	LDA #$00
	STA current_row
	;
	JSR next_block_line
	;
not_row_end
	;
	DEC current_count
	BNE block_loop
	;
	JMP data_loop
	;
set_logo_colour_ball
	lda cur_col
set_logo_colour
	lsr a
	lsr a
	lsr a
	lsr a
	cmp palette_colour
	beq set_logo_c1
	sta palette_colour	; Ball colour fill for logo
	sec
	ror change_palette
set_logo_c1
	rts
level_done
	; ----------------
	JSR get_ROM_byte	; read one more byte: color
	and #$f
	tax
	lda block_colours,x
	;
	STA cur_col
	jsr set_logo_colour
	lda cur_col
	and #$f0
	ora #$c
	sta pf2_attribute
;	ORA #$70
;	STA ted_shadows+$16
	lda #$ff
	sta pf2_fillflag
	;
	; ----------------
	;
	LDX #$38
	STX text_dest
	LDX #$3b	; #gr8 was $3c78
	STX text_dest+1
	;
	LDA level
	ASL a
	ASL a
	STA ptr	; #gr2
	LDA #$00
	STA ptr+1	; #gr2
	;
	ASL ptr
	ROL ptr+1
	ASL ptr
	ROL ptr+1
	;
	LDA ptr
	CLC
	ADC #<(level_names-17)	; #gr1
	STA ptr
	LDA ptr+1
	ADC #>(level_names-17)		; #gr1
	STA ptr+1
	;
	JSR write_level_name
	;
	INC text_dest+1		; add $140 ($40 already added)
	;
	JSR write_level_name
	;
	; ---
	;
	JSR write_blocks
	;
	; ---
	;
	LDX #$01		; down
	STX cur_dir
	DEX
	STX cur_x
	STX cur_y
	STX y_offs
	STX x_offs
	STX cur_lr		; clear left/right movement
	;
	lda #$25
	sta block_value
	sta value_changed
	jsr write_value
	jsr write_level
	lda #$02
	sta text_color2
	lda #$84
	sta text_color1
	lda #1
	jsr fadeout
	JSR clear_middle

	;
	LDA #<text_press_space	; #gr1
	LDX #>text_press_space	; #gr1
	JSR do_pause
	lda #1
	sta rmt_timer
	;
	JSR save_background	; pre-save
	;
	; ##################################################################
	; game loop
	;
	lda #0
	sta value_counter
	sta abortflag
	sta skipflag
game_loop	
	;
	LDA ted_shadows+$11		; decrease volume in every frame
	AND #$0F		; unless it's zero already
	BEQ no_sound_dec
	DEC ted_shadows+$11		; decrease by 2
	DEC ted_shadows+$11
no_sound_dec
		;
	;DEC $FF19		; debug
	;
sync2	LDA vcount	; #gr2 was $FF1D
	CMP #$30	; #gr2 was $68, $BB
	BCS sync2
	;
sync0	LDA #$32	; was $6a, $BB ; SYNC to BB: two lines above lower edge
	cmp vcount	; #gr2 was $ff1d
	BCC sync1
	;
	INC ted_shadows+$0F		; adjust freq lower byte for "punchier" sound effect
	;
;	LDA #$BF		; query keyboard
;	JSR query_keyboard	; #grfix Add abort function later
;	TAY			; save for later
;	AND #$10
	bit abortflag		; #gr2 abort function
	Bpl check_lr
	;
	JMP died		; ESC PRESSED
	;
check_lr
	lda value_changed
	beq check_lr2
	jsr write_value
check_lr2
	LDA cur_x		; only allow left/right control when
	ORA cur_y
	BNE sync0		; fully inside character
	;
	TYA
	AND #$01		; CHECK CURSOR LEFT
	BNE check_right_key
	;
kleft	LDA #$FF		; mark LEFT
ksetdir	STA cur_lr
	JMP sync0
	;
check_right_key
	TYA
	AND #$08		; CHECK CURSOR RIGHT
	BNE check_pause
	;
kright	LDA #$01
	BNE ksetdir		; mark RIGHT; always jump
	;
check_pause
;	LDA #$7F		; query "P" key
;	JSR query_keyboard
;	TAY
;	AND #$10
;	BNE check_joy
	lda pauseflag
	beq check_joy	; #gr2 different pause detection
	;
	JMP pause
	;
check_joy
;	TYA
	;AND #$20		; C=
;	AND #$A4		; C= + CTRL + Run/Stop
;	BNE cj_01
	bit skipflag	; User wants to skip level
	bpl cj_01
;	lda #0
;	sta skipflag
	lda level
	cmp last_level
	bcs cj_noskipping ; Don't allow skipping non-completed levels
;	cmp #20
;	bcs cj_01	; Only allow skipping up to level 15
	lda nobonus
	bne cj_noskipping	; No skipping levels once past 20

	;
	JMP skip_level
cj_noskipping
	lda #0
	sta skipflag
	;
cj_01	
;	LDA #$F9		; allow both ports
	JSR query_joystick	; query joy
	TAY
	AND #$04		; left?
	BEQ kleft
	TYA
	AND #$08		; right?
	BEQ kright
	;
	; alternative keys
	;
	jmp sync0	; #gr2 was BEQ sync0	
	;
sync1
	;INC $FF19		; debug
	;
	; - update score if needed
	;
	JSR check_score
	;
	; - restore old background
	;
	LDY #$0F
rs_01	LDA sprite_temp,y
	STA (cur_pos),y
	DEY
	BPL rs_01
	;
	JSR cur_pos2_down
	;
	LDY #$0F
rs_02	LDA sprite_temp+$10,y
	STA (cur_pos2),y
	DEY
	BPL rs_02
	;
	; - move ball ######################################################
	; ##################################################################
	;
	JSR move_up_down
	;
	; ---
	;
	LDA cur_pos		; copy current position to check position
	STA chk_pos
	LDA cur_pos+1
	STA chk_pos+1
	;
	LDA cur_lr		; determine left or right or straight
	BMI check_left
	BNE j_check_right
	JMP go_straight
j_check_right
	jmp check_right
	;
check_left			; PLAYER INTENDS TO MOVE LEFT
	LDA cur_x		; check only when starting to change columns
	BNE go_left
	;
	JSR sub_chk_pos_8	; check position on the left
	;
	JSR check_small_collision
	BCS swr_1
	;
	; -------------
	LDA x_offs		; if offset=1, we can always go left
	BNE go_left
	;
	;			; otherwise left one more char
	JSR sub_chk_pos_8	; (which means we are checking 2 chars over)
	;
	LDA cur_dir
	BNE cl_d1
	;
	LDA y_offs
	BEQ no_yadd_1
	;
	JSR add_chk_pos_140
	JMP no_yadd_1
	;
cl_d1	LDA y_offs
	BEQ no_yadd_1
	;
	JSR sub_chk_pos_140	; up one line
	;
no_yadd_1
	;
	LDA chk_pos		; disk dest position: 2 chars left
	SEC
	SBC #$10
	STA chk_pos2
	LDA chk_pos+1
	SBC #$00
	STA chk_pos2+1
	;
	JSR check_collision
	BCC no_switch_right
	;
swr_1	JMP switch_right
	;
no_switch_right
	LDA y_offs
	BEQ go_left
	;
	LDA cur_dir
	BNE cl_d2
	;
	JSR sub_chk_pos_280	; check diagonally LEFT/ABOVE
	;
	JMP cl_d3
	;
cl_d2	JSR add_chk_pos_280	; check diagonally LEFT/BELOW - two lines down
	;
cl_d3	JSR check_collision_diag
	BCS switch_right_diag	; DIAGONAL hit
	;
	BCC go_left
	;
switch_left_diag
	JSR switch_up_down
	;	
switch_left
	LDA #$FF		; SWITCH direction
	STA cur_lr
	;
go_left	LDX cur_x		; MOVE LEFT is possible, do it
	DEX
	BPL mv_01
	;
	LDA cur_pos		; * MOVE LEFT
	SEC
	SBC #$08
	STA cur_pos
	BCS mv_02
	DEC cur_pos+1
mv_02	;
	LDA x_offs		; switch x offset
	EOR #$01
	STA x_offs
	;
	LDX #$03
mv_01	STX cur_x		; x will be checked
	;
	JMP check_lr_end
	;
	; --- move right -------------
	;
check_right
	LDA cur_x		; check only when starting to change columns
	BNE go_right
	;
	JSR add_chk_pos_8	; check position on the right
	;
	JSR check_small_collision
	BCS switch_left
	;
	; ----------
	LDA x_offs		; if x_offs=0 we can always go right
	BEQ go_right
	;			; x position is already set (one to the right)
	;
	LDA y_offs
	BEQ no_yadd_2
	;
	LDA cur_dir
	BNE cr_d1
	;
	JSR add_chk_pos_140	; position that needs to be checked it BELOW
	JMP no_yadd_2
	;
cr_d1	JSR sub_chk_pos_140
	;
no_yadd_2
	;
	LDA chk_pos		; disk dest pos: 2 chars right
	CLC
	ADC #$10
	STA chk_pos2
	LDA chk_pos+1
	ADC #$00
	STA chk_pos2+1
	;
	JSR check_collision
	BCS switch_left
	;
	; --------------------- ; no side hit, check diagonal
	;
	LDA y_offs
	BEQ go_right
	;
	LDA cur_dir
	BNE cr_d2
	;
	JSR sub_chk_pos_280	; CHECK diagonally UP/RIGHT
	;
	JMP cr_d3
	;
cr_d2	JSR add_chk_pos_280	; check diagonally DOWN/RIGHT - two lines down
	;
cr_d3	JSR check_collision_diag
	BCS switch_left_diag	; DIAGONAL hit
	;
	BCC go_right
	;
switch_right_diag
	JSR switch_up_down
	;
switch_right
	LDA #$01		; CHANGE direction
	STA cur_lr
	;
go_right
	LDX cur_x		; move right is possible
	INX
	CPX #$04
	BNE mv_10
	;
	LDA cur_pos		; * MOVE RIGHT
	CLC
	ADC #$08
	STA cur_pos
	BCC mv_11
	INC cur_pos+1
mv_11	;
	LDA x_offs		; switch x offset
	EOR #$01
	STA x_offs
	;
	LDX #$00
mv_10	STX cur_x
	;
check_lr_end
	CPX #$00		; is x=0? (arrived to next character?)
	BNE go_straight
	;
	STX cur_lr		; yes, stop horizontal movement
	;
go_straight
	;
	; ##################################################################
	;
	LDA cur_pos
	STA chk_pos
	LDA cur_pos+1
	STA chk_pos+1
	;
	LDA cur_dir
	BNE down
	;
	; - up
	;
	LDA cur_y
	BNE no_upper_check
	;
	; --- ! check above
	;
	JSR sub_chk_pos_140
	;
	JSR check_small_collision
	BCS ud_reverse
	;
	; -------------
	LDA y_offs
	BNE no_upper_check
	;
	JSR sub_chk_pos_140		; up one more
	;
	LDA x_offs
	BEQ no_xadd
	;
	JSR sub_chk_pos_8
	;
no_xadd
	;
	LDA chk_pos
	SEC
	SBC #$80
	STA chk_pos2
	LDA chk_pos+1
	SBC #$02
	STA chk_pos2+1
	;
	JSR check_collision
	;
	BCC no_upper_check
	;
ud_reverse
	LDA cur_dir			; reverse direction
	EOR #$01
	STA cur_dir
	;
no_upper_check
	JMP no_down_check
	;
	; ----------------------
	;
down	LDA cur_y
	BNE no_down_check
	;
	JSR add_chk_pos_140	; check down one line
	;
	JSR check_small_collision
	BCS ud_reverse_2
	;
	;-----------------
	LDA y_offs
	BEQ no_down_check
	;
	LDA x_offs
	BEQ no_xadd_2
	;
	JSR sub_chk_pos_8
	;
no_xadd_2
	;
	LDA chk_pos		; disk dest pos: 2 lines down
	CLC
	ADC #$80
	STA chk_pos2
	LDA chk_pos+1
	ADC #$02
	STA chk_pos2+1
	;
	JSR check_collision
	;
	BCC no_down_check
	;
ud_reverse_2
	LDA cur_dir			; reverse direction
	EOR #$01
	STA cur_dir
	;
no_down_check
	;
	; - save new background ------------------------------------------
	;
	JSR save_background
	;
	; - draw sprite
	;
	LDX cur_x
	LDA cur_y		; add 8,6,4,2 to sprite pos to shift it up
	EOR #$03
	ASL a
	CLC
	ADC #$02
	ADC sprite_ptrs_lo,x	; look up sprite mask according to x position
	STA chk_pos		; (each one is x shifted)
	LDA sprite_ptrs_hi,x
	ADC #$00
	STA chk_pos+1
	;
	LDA cur_y		; y stop value
	ASL a
	STA dr_02+1
	ORA #$08
	STA dr_04+1
	;
	SEC
	SBC #$01
	STA dr_07+1
	SEC
	SBC #$08
	STA dr_05+1
	;
	LDY #$07
dr_01	LDA (chk_pos),y		; top/left corner
	ORA (cur_pos),y
	STA (cur_pos),y
	DEY
dr_02	CPY #$00
	BPL dr_01
	;
	LDY #$0F		; top/right corner
dr_03	LDA (chk_pos),y
	ORA (cur_pos),y
	STA (cur_pos),y
	DEY
dr_04	CPY #$00
	BPL dr_03
	;
	JSR cur_pos2_down	; down one line
	;
	JSR add_chk_pos_8	; inc sprite pos
	;
dr_05	LDY #$07
	BMI dr_09
dr_06	LDA (chk_pos),y		; bottom/left
	ORA (cur_pos2),y
	STA (cur_pos2),y
	DEY
	BPL dr_06
	;
dr_07	LDY #$0F
dr_08	LDA (chk_pos),y		; bottom/right
	ORA (cur_pos2),y
	STA (cur_pos2),y
	DEY
	CPY #$07
	BNE dr_08
dr_09	;
	LDA blocks
	BEQ next_level
	;
	JMP game_loop
	
	;
	; *** NEXT LEVEL ***
	;
skip_level
	DEC lives		; so that they don't gain a life when skipping levels
	;
next_level
	jsr sync_score
	INC levels_cleared
	;
	lda #2
	sta text_color2
	JSR clear_middle
	;
	lda #$0c
	sta text_color1
	lda #5
	sta text_color2
	LDA #<text_level_cleared
	bit skipflag
	bpl next_level_notskipped
	lda #<text_level_skipped
next_level_notskipped
	JSR write_message
	lda #0
	sta skipflag
	;
;	LDA #$20
;	JSR do_noise
	lda #120
	sta rmt_timer
	lda #$10
	sta rmt_song
	sec
	ror rmt_start
		;
	LDA level		; is there a next level?
	CMP #$20
	Bcc next_level2
	lda #4
	sta level		; After Level 20, resume at 5
	sta nobonus		; And don't allow bonus lives
	;
next_level2
	JMP new_level		; yes, go to new one
	
	;
	; *** player dies
	;
died	DEC lives		; decrease number
	jsr sync_score
	JSR write_lives		; and erase lost one
	;
	; play some noise + pause
	;
	LDA #$40
	JSR do_noise
	lda #2
	sta text_color2
	jsr clear_middle
	lda #$36
	sta text_color1
	lda #0
	sta text_color2
	lda #<text_died
	ldy #>text_died
	bit abortflag
	bpl died_write
	lda #<text_aborted
	ldy #>text_aborted
died_write
	sty message_ptr+1
	jsr write_message_ext
	lda #120
	sta rmt_timer
	lda #$12
	sta rmt_song
	sec
	ror rmt_start
;	lda lives
;	bne died_wait1
died_wait0
	lda sstrig0
	beq died_wait1
	lda rmt_timer
	bne died_wait0
	beq died_nowait
died_wait1
	jsr wait_release
;	jsr wait_space
	lda #1
	sta rmt_timer
died_nowait
	jsr restore_middle
	;
	; --- decrease lives
	;
	LDA lives
	BEQ game_over
	;
	JMP level_restart
;
zero_score
	LDY #$05
	lda #0
zs_01	STA score,y		; init score
	STA score_curr,y
	DEY
	BPL zs_01
	rts
;
game_over
	lda rmt_timer
	bne game_over	; Wait for music to finish
	LDA level
	ldx nobonus
	beq game_ov2
	lda #$20
game_ov2
	CMP last_level
	BCC go_0
	STA last_level		; store last reached level
	;
	; check for new high score
	;
;	lda $d7ff		; Breakpoint testing
	cld
go_0	LDX #$00
chs_01	LDA score,x
	CMP score_high,x
	beq chs_01a
	BCS new_high_score
	bcc go_2
chs_01a
	inx
;	DEX
	cpx #5
	Bne chs_01
	Beq go_2
new_high_score
	;
	LDX #$05
chs_02	LDA score,x		; it's a new high score, copy it
	STA score_high,x
	DEX
	BPL chs_02
	;
	lda #$fc
	sta text_color1
	JSR clear_large		; larger box
	;
	lda #0
	sta text_color2
	lda #$fe
	sta text_color1
	lda #$cd
	LDX #$70
	LDY #$30
	LDA #text_congrats & 255	; congrats message
	JSR write_message_pos
	;
;	lda #$b
;	sta text_color1
	JSR write_high_score		; display actual high score
	;
	JMP go_2a
	;
	; --- all levels cleared
	;
go_2	
;	LDA levels_cleared
;	CMP #20				; decimal 20!
;	Bcc go_3
	;
;	JSR clear_large
	;
go_2a	
;	LDA levels_cleared
;	CMP #20				; decimal 20!
;	Bcc go_3
	;       
;	LDX #$70
;	LDY #$2B
;	LDA #<text_all_levels_cleared	; special message
;	JSR write_message_pos
	;
go_3	
	JSR clear_middle		; display standard game over message
	;
	lda #$3c
	sta text_color1
	LDA #<text_game_over
	JSR write_message
	lda #200
	sta rmt_timer
	lda #$0c
	sta rmt_song
	sec
	ror rmt_start
	;	
	JSR wait_space
	JMP new_game
	
	;
	; --- pauses the game, waits for space keypress
	;
pause
	lda #$01
	sta text_color2
	JSR clear_middle
	;
	LDA #<text_paused
	JSR do_pause
	;
	lda #0
	sta skipflag
	lda porta
	tay
	JMP sync0

do_pause
	pha
	lda #1
	sta pauseflag
	LDY #$00		; volume off
	STY ted_shadows+$11
	lda #$ca
	sta text_color1
	lda #0
	sta text_color2
	pla
	JSR write_message
	;
	JSR wait_space
	;
	JSR restore_middle
	;
	RTS
	
	;
	; pauses the program until space is pressed
	;
wait_space
	lda #1
	sta pauseflag
;	JSR wait_release
	;
wsp_1	JSR check_score
	;
	lda pauseflag
	bne wsp_1	; #gr2
;	LDA #$7F
;	JSR query_keyboard
;	CMP #$FF
;	BEQ wsp_1
	;
wait_release
	lda sstrig0
	beq wait_release
;	LDA #$7F		; wait until released
;	JSR query_keyboard
;	CMP #$FF
;	BNE wait_release
	;
	RTS
	
query_keyboard
;	STA $FD30	; #gr2
query_joystick
;	STA $FF08
	LDA stick0	; #gr2 was $FF08
	and #$f
	RTS
	
	;
	; displays a message in the middle of the screen
	; expected: A: LO pointer to message
	;
write_message_pos           
	STX text_dest
	STY text_dest+1
	;
write_message
	;
	LDY #>text_author 	; high byte is always the same #gr1
	STY message_ptr+1
;
; Alternate entry point, assumes caller has setup >message_ptr already
;
write_message_ext
	STA message_ptr	
	;
	LDA #mlen
write_message_3
	STA message_len+1
	;
;	LDA block_col	; was #$47
	lda text_color2
	sta put_shade+1
	jsr calc_attr_text_dest
	;
	LDY #$00
wm_01	TYA
	PHA
	LDA (message_ptr),y
	JSR write_letter
	PLA
	TAY
	LDA text_color1	; was $11 gray
	JSR put_color
	;
message_len
	CPY #mlen
	BNE wm_01
	;
	RTS
	
clear_large
	lda text_color2
	sta pf2_attribute
	sta cur_col
	sta attr_set_hires+2
	lda text_color1
	sta attr_set_hires+1
	lda #$ff
	sta pf2_fillflag
	jsr wait_frame
;
	LDY #$28-1
	LDA #$2A
	LDX #$07
	JSR clear_generic
	jsr set_inhibit_attr
	lda #<blits_large_window_hires
	jsr doblit_setres_middle
	ldy #19
set_attr_large
	lda #$00
	sta $1805+(40*8),y	; Set PF0
	sta $1805+(40*9),y
	sta $1805+(40*10),y
	sta $1805+(40*11),y
	sta $1805+(40*12),y
	sta $1805+(40*13),y
	sta $1805+(40*14),y
	sta $1805+(40*15),y
	lda text_color1
	sta $1c05+(40*8),y	; Set PF1
	sta $1c05+(40*9),y
	sta $1c05+(40*10),y
	sta $1c05+(40*11),y
	sta $1c05+(40*12),y
	sta $1c05+(40*13),y
	sta $1c05+(40*14),y
	sta $1c05+(40*15),y
	dey
	bpl set_attr_large
	jsr clear_inhibit_attr
	;
	LDA #$30
	STA chk_pos
	LDA #$2A
	STA chk_pos+1
	;
	JSR calc_lum_col_chk
	;
	JSR reset_message_pos
	;
	RTS
doblit_setres_middle
	pha
	ldy #v_blitter_start
xm_waitblit
	lda (vbxe_ptr),y
	bne xm_waitblit	; Wait for blitter inactive
	ldy #v_bl_adr0
	pla
	sta (vbxe_ptr),y
	iny
	lda #>(blits_vblank-$1000)
	sta (vbxe_ptr),y
	iny
	lda #0
	sta (vbxe_ptr),y	; Setup blit address
	iny
	lda #1
	sta (vbxe_ptr),y	; Start blit
	rts
; Subs to inhibit/enable atrribute copy operations
clear_inhibit_attr
	lda #$ff
	sta pf2_fillflag	; Request PF2 store
	lda #0
	beq store_inhibit_attr
set_inhibit_attr
	lda #$ff
store_inhibit_attr
	sta inhibit_attr_blitflag
	rts
restore_middle
	lda #<blits_small_window_lores
	jsr doblit_setres_middle
	jsr clear_inhibit_attr
	LDX #mlen
rm_01	LDA message_temp,X
	STA $19BE,X
	LDA message_temp+$20,X
	STA $1DBE,X
	DEX
	BPL rm_01
	;
	lda #0
	sta inhibit_attr_blitflag
	LDA #$bC	; #grfix Was $6c (restore buffer address) ? #gr7
	BNE cm_11		; always jump
	;
clear_middle
	jsr wait_frame
	jsr wait_frame		; Give blit a chance to copy attributes
	lda text_color2
	sta attr_set_hires+2
	lda text_color1
 	sta attr_set_hires+1
 	jsr set_inhibit_attr	; Disable Attribute blits during VBI
 	lda #<blits_small_window_hires
	jsr doblit_setres_middle
	LDX #mlen
cm_10	LDA $19BE,X
	STA message_temp,X
	LDA $1DBE,X
	STA message_temp+$20,X
	DEX
	BPL cm_10
	;
	LDA #$2C

cm_11	
	LDY #$A8-1
	;
	LDX #$02		; number of lines to clear-1
	jsr clear_generic
	rts
	;
	; at this entry point:  X = lines
	;			Y = lo
	;			A = hi
	;
clear_generic
	STY chk_pos
	STY bptr
	;	
	STA chk_pos+1
	EOR #$90	; #grfix was $40 80 #gr7 
	STA bptr+1
	;
cm_03	LDY #(mlen+2)*8
cm_02	LDA (chk_pos),y
	STA (bptr),y	
	LDA #$00
	STA (chk_pos),y
	DEY
	BNE cm_02
	;
	JSR add_chk_pos_140
	JSR inc_bptr_140
	;
	DEX
	BPL cm_03
	;
	; ---
	;
reset_message_pos
	LDA #$F0
	STA text_dest
	LDA #$2D
	STA text_dest+1
	;
	LDA #$BE
	STA lptr
	STA cptr
	LDA #$19
	STA lptr+1
	ORA #$04
	STA cptr+1
	;
	RTS
	
;sync	LDA $FF1D
;	CMP #$C3
;	BNE sync
;	RTS
	
	;
	; ##################################################################
	;
switch_up_down
	LDA cur_dir		; switch the flag first
	EOR #$01
	STA cur_dir
	;
	JSR move_up_down	; step back (to compensate)
	;			; then step one in the right direction
	;
move_up_down	
	LDA cur_dir
	BNE mv_down
	;
	; - up
	;
	LDX cur_y
	DEX
	BPL mv_03
	;
	LDA cur_pos		; * UP one char
	SEC
	SBC #$40
	STA cur_pos
	LDA cur_pos+1
	SBC #$01
	STA cur_pos+1
	;
	LDA y_offs		; switch y offset
	EOR #$01
	STA y_offs
	;
	LDX #$03
	;
mv_03	STX cur_y
	RTS
	;
	; ----------------------
	;
mv_down	LDX cur_y
	INX
	CPX #$04
	BNE mv_04
	;
	LDA cur_pos		; * DOWN one line
	CLC
	ADC #$40
	STA cur_pos
	LDA cur_pos+1
	ADC #$01
	STA cur_pos+1
	;
	LDA y_offs		; switch y offset
	EOR #$01
	STA y_offs
	;
	LDX #$00
mv_04	STX cur_y
	;
	RTS
	
	;
	; ##################################################################
	;
sub_chk_pos_280
	JSR sub_chk_pos_140
sub_chk_pos_140
	DEC chk_pos+1		; up one line
	LDA #$40
	.byte $2c	; #gr1
;	DB $2C
sub_chk_pos_8
	LDA #$08		; left one char
sub_chk_pos
	STA sub_val+1
	;
	LDA chk_pos
	SEC
sub_val	SBC #$00
	STA chk_pos
	BCS scp_1
	DEC chk_pos+1
scp_1	;
	RTS

add_chk_pos_280
	JSR add_chk_pos_140	
add_chk_pos_140
	INC chk_pos+1		; down one line
	LDA #$40
	.byte $2c	; #gr1
;	DB $2C
add_chk_pos_8
	LDA #$08		; right one char
add_chk_pos
	CLC
	ADC chk_pos
	STA chk_pos
	BCC acp_1
	INC chk_pos+1
acp_1	;
	RTS
;	
draw_level_back
; Use different routine for background attributes

	ldy #$7f
	lda random
	and #$f0
	sta ztemp1+1
draw_level_b0
	ldx #$e
	lda random
	and #$f0
	sta ztemp1
draw_level_b1	
	lda luma1_table+1,x
	ora ztemp1+1
	sta temp_color,y
	lda luma1_table,x
	ora ztemp1
	sta temp_lum,y
	lda ztemp1
	sta ztemp1+1
	dey
	bmi draw_level_b2
	dex
	dex
	bmi draw_level_b0
	bpl draw_level_b1

draw_level_b2
	;
	; --- write lives
	;
	JSR write_lives
	;
	; ---------
	;
	LDX #$10
il_01	LDA #$00		; init bitmap and lum pointers
	STA bptr-$10,x
	TXA
	ASL A			; tricky: each pointer is $0400 + previous
	STA bptr-$10+1,x
	DEX
	DEX
	BPL il_01
	;
	; ---
	;
	LDA #$46
	STA put_shade+1
	;
	JSR draw_top_bot_border	; top
	;
	; ---
	;
	LDA #28
	STA ctemp
	;
d_01	JSR draw_smallblock	; left side
	;
	LDX #28-1		; middle bitmap
cs_02	LDY #$07		; loop from 7-0
cs_01	LDA background_pattern,y	; with pattern repeating every 8 bytes
	STA (bptr),y
	DEY
	BPL cs_01
	;
	JSR inc_bptr_8		; increase bitmap pointer by 8 bytes
	;
	DEX
	BPL cs_02
	;
	LDY #28-1
	LDX ctemp
cs_10	LDA temp_color,x	; draw background colors
	STA (cptr),y
	STA (cptr2),y		; and save them too...
	LDA temp_lum,x
	STA (lptr),y
	STA (lptr2),y
	DEX
	DEY
	BPL cs_10
	;
	INC ctemp
	LDA #28
	JSR inc_lptr
	;
	JSR draw_smallblock	; right side
	JSR skip_10
	;
	LDA bptr+1
	CMP #$3C
	BNE d_01
	;
	; ---
	;
	;JSR draw_top_bot_border	; bottom
	
draw_top_bot_border
	LDX #30-1
d_sb_01	JSR draw_smallblock	; draw top border
	DEX
	BPL d_sb_01
	;
skip_10
	LDA #10*8
	JSR inc_bptr
	LDA #10
	.byte $2c	; #gr1
;	DB $2C
	
inc_lptr_40
	LDA #$28
inc_lptr
	CLC
	ADC lptr
	STA lptr
	STA cptr
	STA lptr2
	STA cptr2
	BCC noi2
	INC lptr+1
	INC cptr+1
	INC lptr2+1
	INC cptr2+1
noi2	RTS

inc_bptr_140
	INC bptr+1
	LDA #$40
	.byte $2c	; #gr1
;	DB $2C
	
inc_bptr_8
	LDA #$08
inc_bptr
	CLC
	ADC bptr
	STA bptr
	BCC noi1
	INC bptr+1
noi1	RTS

next_block_line
	LDA #40+12		; next line of blocks
	JSR inc_lptr
	;
	LDA #$A0
	JSR inc_bptr
	INC bptr+1
	;
	RTS

init_block_pos
	LDA #$48
	STA bptr
	LDA #$21
	STA bptr+1
	;
	LDA #$29
	STA lptr
	STA cptr
	LDA #$18
	STA lptr+1
	ORA #$04
	STA cptr+1
	;
	RTS

	;
	; *** draws a small gray 1x1 block on screen
	;     position is given by bptr/lptr/cptr
	;
	;     then moves to next character position
	;	
draw_smallblock
	LDY #$07
sb_01	LDA small_block,y
	STA (bptr),y
	DEY
	BPL sb_01
	;
	INY			; Y=0
	lda #$09		; border colour for small blocks
	STA put_shade+1
	LDA #$05		; #gr3 was $11 gray
	JSR put_color
	;
	TYA			; Y=1, inc lum/col map by 1
	JSR inc_lptr
	;
	JMP inc_bptr_8		; inc bitmap by 8
	
	;
	; *** draws a block according to X
	;
draw_new_block
	LDA blocks_ptr_lo,x
	STA block_ptr
	LDA blocks_ptr_hi,x
	STA block_ptr+1
	;
	; *** draws a big 2x2 block on screen
	;     dest position specified by bptr
	;
draw_block
	LDY #$0F
db_01	LDA (block_ptr),y	; copy top of block
	STA (bptr),y
	DEY
	BPL db_01
	;
	INY			; place color codes
	JSR put_color3
	LDY #$28
	JSR put_color2
	;
	LDA #$30
	JSR inc_bptr
	INC bptr+1
	;
	LDY #$1F		; bottom of block
db_02	LDA (block_ptr),y
	STA (bptr),y
	DEY
	CPY #$0F
	BNE db_02
	;
	; -
	;
	LDA bptr
	SEC
	SBC #$20
	STA bptr
	LDA bptr+1
	SBC #$01
	STA bptr+1
	;
db_03	LDA #$02
	JMP inc_lptr
	
skip_block
	LDA #$10
	JSR inc_bptr
	JMP db_03

put_color3
	LDA block_col
	pha
	and #$f0
	sta ztemp1
	pla
;	AND #$0F
	lsr a
	lsr a
	lsr a
	lsr a
	TAX
	LDA shades,x
	ora ztemp1
	STA put_shade+1
	;
put_color2
	JSR put_color1
put_color1
	LDA block_col
;	ldx block_col
;	lda block_colours,x
put_color
	STA (cptr),y
put_shade
	LDA #$47		; shades, self-mod
	STA (lptr),y
	INY
	RTS
	
;write_title
;	LDX #$00
;ws_04	LDA text_title,x
;	JSR write_letter
;	INX
;	CPX #text_title_end - text_title
;	BNE ws_04
	;
;	DEC text_dest+1
;	LDY #$B8+7
;	LDA #$26
;	STA (text_dest),y
;	LDY #$E3
;	LDA #$44
;	STA (text_dest),y
;	LDY #$E3+8
;	STA (text_dest),y
;	LDA #$04
;	LDY #$E1
;	STA (text_dest),y
;	LDA #$40
;	LDY #$E1+8
;	STA (text_dest),y
	;
;	RTS
	
write_level_name
	LDX #$07
ln_01	JSR get_ROM_byte
	JSR write_letter
	DEX
	BPL ln_01
	;
	RTS
	
	;
	; *** writes a number (converts to ascii)
	;
write_number
;	CMP #$00
;	BNE wn_1
;	LDA #"O"-64		; change "0" to "O"
;	LDA #240		; #gr1 fix for AtAsm
;	.byte $2c	; #gr1
;	DB $2C
wn_1	ORA #$30	
	;
	; *** writes one letter on screen
	;     letter is expected in "A"
	;     uses Y, leaves X
	;
write_letter
	;
wl_02	
wl_05	
wl_04	
	sta ztemp1
	rol a
	rol a
	rol a
	rol a
	and #3
	tay
	lda ztemp1
	eor screen_table,y	; Fix characters ATASCII -> screen codes

	STA wl_01+1		; store letter
	;
	LDA #$e0/8	; >> 3		; #gr2 was "address is $D000 + letter * 8"
	STA wl_01+2
	;
	ASL wl_01+1		; * 8 (16bit)
	ROL wl_01+2
	ASL wl_01+1
	ROL wl_01+2
	ASL wl_01+1
	ROL wl_01+2
	;
wl_03	LDY #$07		; copy!
wl_01	LDA $0A0A,y		; self-mod
	STA (text_dest),y	; draw
	DEY
	BPL wl_01
	;
	LDA text_dest		; go to next character position
	CLC
	ADC #$08
	STA text_dest
	BCC wl_noi1
	INC text_dest+1
wl_noi1	;
	RTS
	
	;
	; checks for immediate collisiont (side of screen)
	; position in: chk_pos
	;
check_small_collision
	LDY #$04
	LDA (chk_pos),y		; check immediate next char...
	CMP #$68		; for small block (side of screen)
	BEQ its_smallblock
	;
	CLC			; way is clear!
	RTS
	;
its_smallblock
	LDA #$00
	JSR do_sound
	;
	SEC			; flag reverse direction
	RTS
	
	;
	; this is called when player presses left/right
	;
	; if there's a block there,
	; (remove block then)
	; direction is reversed.
	;
	; also called during up/down move.
	;
	; the first position to be checked is in cur_pos2
	; the second position is chk_pos
	;
check_collision_diag
	LDA #$00
	STA chk_pos2+1
	;
check_collision
	;
	JSR calc_lum_col_chk
	;
	LDY #$00		; pre-load block color
	LDA (cptr),y
	STA block_col
	;
	LDY #$03
	LDA (chk_pos),y		; check next big char
	;
	CMP #$65		; check "die" block
	BNE not_die
	;
	JMP died		; change this to cheat
	;
not_die	CMP #$66		; check "star" block
	BNE not_star
	;
	LDA block_col		; it's a star!
	STA cur_col
	jsr set_logo_colour
	lda cur_col
	and #$f0
	ora #$0c
	sta pf2_attribute	; Copy to bcb for fill

;	AND #$0F
;	ORA #$60
;	STA ted_shadows+$16
	;
	lda #$ff
	sta pf2_fillflag	; Flag so VBI can run extra blit
	LDA #$02
	JSR do_sound
	;
	SEC
	RTS
	;
not_star
	CMP #$40
	BNE not_disk
	;
	LDA chk_pos2+1		; can we move it? (high byte = 0 means flag NOT to move)
	BEQ cant_remove
	;
	LDY #$03
	LDA (chk_pos2),y	; check if disk can move
	CMP #$56
	BNE cant_remove
	;
	LDA block_col		; check color
	CMP cur_col
	BNE cant_remove		; if color is not matching, can't move disk
	;
	; *** MOVE DISK
	;	
	JSR clear_block		; erase it from the old position
	;
	LDA chk_pos2		; new pos
	STA lptr
	STA bptr
	LDA chk_pos2+1
	STA lptr+1
	STA bptr+1
	;
	JSR calc_lum_col	; calc lum/col map pos
	;
	LDX #$03		; value for disk
	JSR draw_new_block	; and draw it
	;
	LDA #$01		; mid freq sound
	JMP block_sound		; it's a disk
	;
not_disk
	CMP #$6A		; check for block
	BNE not_block
	;
	LDA block_col
	CMP cur_col
	;
	BNE cant_remove		; cannot remove block, not the right color
	;
	JSR clear_block		; remove it!
	;
	SED
	LDA blocks
	SEC
	SBC #$01
	STA blocks		; decrease number of blocks
	CLD
	;
	JSR write_blocks	; update screen
	;
	LDX #$05		; was 4 (tens)
;	LDA block_col		; #gr8
;	AND #$0F
	lda block_value
	and #$f
	JSR add_score		; units
	ldx #4
	lda block_value
	lsr a
	lsr a
	lsr a
	lsr a
	jsr add_score		; tens
	;
	LDA #$03		; high freq sound
	.byte $2c	; #gr1
;	DB $2C
cant_remove
	LDA #$00		; low freq sound
	;
block_sound
	JSR do_sound
	;
	SEC
	RTS
	;
not_block
	CMP #$68		; check for small blocks
	BEQ cant_remove
	;
	CLC			; way is clear!
	RTS
	
	; --------------------------------------
do_sound
	STA ted_shadows+$10
	LDA #$28
	STA ted_shadows+$11
	STA ted_shadows+$0F
	;
	RTS
	
do_noise
	STA noise0+1
	;
	LDX #$00
noise2	TXA
	TAY
noise1	STY ted_shadows+$0E
	TYA
	LSR a
	LSR a
	LSR a
	LSR a
	LSR a
noise0	ORA #$40
	STA ted_shadows+$11
	STA ted_shadows+$10
	;
	DEY
	BNE noise1
	;
	DEX
	BNE noise2
	;
	RTS
	
	;
	; *** increases scrore: X: digit to add, A: value to add
	;
add_score
	CLC
	ADC score,x
	STA score,x
	CMP #10
	BCC as_01
	SBC #10
	STA score,x
	DEX
	LDA #$01
	BNE add_score
	;
as_01	RTS
sync_score
	ldx #5
sync_score1
	lda score,x
	sta score_curr,x
	dex
	bpl sync_score1
	bmi write_score
check_score
	LDX #$05
csc_01	LDA score_curr,x
	CMP score,x
	BCC needs_update
	DEX
	BPL csc_01
	RTS
	;
needs_update
	LDX #$05
csc_02	LDA score_curr,x
	CLC
	ADC #$01
	STA score_curr,x
	CMP #$0A
	BCC write_score
	SBC #$0A
	STA score_curr,x
	DEX
	BPL csc_02
	;	
write_score
	LDA #$80
	STA text_dest
	LDA #$23	; #gr8 was $24c0 #gr4 was $29
	STA text_dest+1
	;
	LDX #$00
as_02	LDA score_curr,x
	JSR write_number
	INX
	CPX #$06
	BNE as_02
	;
	RTS
write_high_score_status
	lda #6
	sta text_color2
	lda #$b5
	sta text_color1
	LDA #$40
	STA text_dest
	LDA #$36
	STA text_dest+1
	bne whs01
write_high_score
	lda #0
	sta text_color2
	LDA #$B0
	STA text_dest
	LDA #$31
	STA text_dest+1
	;
	LDA #<text_high
	LDX #>text_high
	STA message_ptr
	STX message_ptr+1
	;
	LDA #12
	JSR write_message_3
	;
whs01
	LDX #$00
as_03	LDA score_high,x
	JSR write_number
	INX
	CPX #$06
	BNE as_03
	;
	RTS
write_value
	lda #$d0
	sta text_dest
	lda #$2e
	sta text_dest+1
	lda block_value
	jmp write_two_digits
inc_level
	SED
	LDA level
	CLC
	ADC #$01
	STA level
	CLD
	rts
	;	
write_level
	lda level
write_level_a
	LDX #$90
	STX text_dest
	LDX #$32	; #gr8 was $33d0 #gr4 was $38
	STX text_dest+1
	;
	JMP write_two_digits
	
write_blocks
	LDA #$10
	STA text_dest
	LDA #$2b	; #gr8 was 2d90 $2ed0 #gr4 was $33
	STA text_dest+1
	;
	LDA blocks
	;
write_two_digits
	PHA
	LSR a
	LSR a
	LSR a
	LSR a
	JSR write_number
	PLA
	AND #$0F
	JSR write_number
	;
	RTS
	
write_lives
	LDA #$40
	STA bptr
	LDA #$27	; #gr8 was $2880 $29c0 #gr4 was $2e
	STA bptr+1
	;
	LDX lives
	BEQ erase_lives
	cpx #9
	bcc wli_02
	ldx #8
	;
wli_02	LDY #$07
wli_01	LDA sprite_lives,y
	STA (bptr),y
	DEY
	BPL wli_01
	;
	JSR inc_bptr_8
	DEX
	BNE wli_02
	;
erase_lives
	LDA #$08
	SEC
	SBC lives
	bmi wli_ret
	ASL a
	ASL a
	ASL a
	TAY
	DEY
	LDA #$00
wli_03	STA (bptr),y
	DEY
	BPL wli_03
	;
wli_ret
	RTS
	
	;
	; ***
	;
change_block_col_new
	stx ztemp1
	and #$f
	tax
	lda block_colours,x
	sta block_col
	ldx ztemp1
	rts
	;
	; *** erases one 2x2 block from the screen
	;
clear_block	
	LDY #$0F
clb_01	LDA background_pattern,y	; clear bitmap top
	STA (chk_pos),y
	DEY
	BPL clb_01
	;
	JSR add_chk_pos_140		; down one line
	;
	LDY #$0F
clb_02	LDA background_pattern,y	; clear bitmap bottom
	STA (chk_pos),y
	DEY
	BPL clb_02
	;
	; ---
	;
	LDY #$00
	JSR copy_two_colors	; copy top two bytes
	LDY #$28		; and lower two bytes
copy_two_colors
	JSR copy_one_color
copy_one_color
	LDA (lptr2),y
	STA (lptr),y
	LDA (cptr2),y
	STA (cptr),y
	INY
	RTS
;
; Recompute attr address based on bitmap pointer
calc_attr_text_dest
	lda text_dest
	sta lptr
	lda text_dest+1
	sta lptr+1
	jmp calc_lum_col
calc_lum_col_chk
	LDA chk_pos		; copy chk_pos lum/col address
	STA lptr
	LDA chk_pos+1
	STA lptr+1
	;
calc_lum_col
	LSR lptr+1		; calculate lum map pointer
	ROR lptr		; /8 (16 bit)
	LSR lptr+1
	ROR lptr
	LSR lptr+1
	ROR lptr
	;
	LDA lptr		; copy to other 3 pointers
	STA cptr
	STA lptr2
	STA cptr2
	;
	LDA lptr+1		; adjust high byte
	CLC
	ADC #$14		; add $14 instead of $18
	STA lptr+1		; $2000>>3=$400 already added
	EOR #$08
	STA lptr2+1
	EOR #$0C
	STA cptr+1
	EOR #$08
	STA cptr2+1
	;
	RTS
	
cur_pos2_down
	LDA cur_pos
	CLC
	ADC #$40
	STA cur_pos2
	LDA cur_pos+1
	ADC #$01
	STA cur_pos2+1
	RTS
	
	;
	; *** saves the background under the sprite
	;
save_background
	LDY #$0F
sv_01	LDA (cur_pos),y
	STA sprite_temp,y
	DEY
	BPL sv_01
	;
	JSR cur_pos2_down
	;
	LDY #$0F
sv_02	LDA (cur_pos2),y
	STA sprite_temp+$10,y
	DEY
	BPL sv_02
	;
	RTS
;
; #gr2 Get ROM Byte and Set Ptr routines
get_ROM_byte
	inc ptr
	bne get_rb1
	inc ptr+1
get_rb1
	ldy #0
	lda (ptr),y
	rts
set_ptr
	stx ptr
	sty ptr+1
	rts
;
; Fade out routine, A=Fade Table to use
;
fadeout
	and #1
	asl a
	asl a
	asl a
	asl a
	tax
	ldy #8
fadeout_1
	jsr wait_frame
	lda fade_table+3,x
	sta bitmap_mask3
	sta bitmap_mask4
	lda fade_table+2,x
	sta bitmap_mask2
	sta bitmap_mask5
	lda fade_table+1,x
	sta bitmap_mask1
	sta bitmap_mask6
	lda fade_table,x
	sta bitmap_mask0
	sta bitmap_mask7
	inx
	dey
	bne fadeout_1
	rts
;
; Hide instructions within XDL
;
hide_instructions
	lda xdl_t1
	and #$fc
	ora #4
	sta xdl_t1
	lda xdl_t2
	and #$fc
	ora #4
	sta xdl_t2
	lda xdl_t3
	and #$fc
	ora #4
	sta xdl_t3
	lda xdl_t4
	and #$fc
	ora #4
	sta xdl_t4
	jsr clear_inhibit_vbblits
	rts
show_instructions
	jsr set_inhibit_vbblits	; Disallow all blits
	jsr clear_atari_window
	lda xdl_t1
	and #$fb
	ora #1
	sta xdl_t1
	lda xdl_t2
	and #$fb
	ora #1
	sta xdl_t2
	lda xdl_t3
	and #$fb
	ora #1
	sta xdl_t3
	lda xdl_t4
	and #$fb
	ora #1
	sta xdl_t4
	rts
;
; Clear some lines from the Atari screen
;
clear_atari_window
	lda #<(atari_bitmap_data+321)
	sta ztemp1
	lda #>(atari_bitmap_data+321)
	sta ztemp1+1		; Point to cell (1,1)
	ldx #48			; Clear 48 scanlines
	jsr clear_atari0
	lda #<(atari_bitmap_data+5441)
	sta ztemp1
	lda #>(atari_bitmap_data+5441)
	sta ztemp1+1		; Point to cell (1,17)
	ldx #48
clear_atari0
	ldy #0
	tya
clear_atari1
	sta (ztemp1),y
	iny
	cpy #28			; Clear 28 character width
	bcc clear_atari1
	lda ztemp1
	clc
	adc #40
	sta ztemp1
	bcc clear_atari2
	inc ztemp1+1
clear_atari2
	dex
	bne clear_atari0
	rts
;
; Do half a block shape onto Atari bitmap
;
write_block_atari
	stx ztemp2
	sty ztemp2+1		; Destination address
	tax			; Block type
	lda blocks_ptr_lo,x
	sta ztemp1
	lda blocks_ptr_hi,x
	sta ztemp1+1		; Source
	jsr write_block_a0
	lda ztemp1
	clc
	adc #8
	sta ztemp1		; Point to bottom characters for second pass
	bcc write_block_a0
	inc ztemp1+1
write_block_a0
	ldx #8
write_block_a1
	ldy #0
	lda (ztemp1),y
	sta (ztemp2),y
	ldy #8
	lda (ztemp1),y
	ldy #1
	sta (ztemp2),y
	inc ztemp1
	bne write_block_a2
	inc ztemp1+1
write_block_a2
	lda ztemp2
	clc 
	adc #40
	sta ztemp2
	bcc write_block_a3
	inc ztemp2+1
write_block_a3
	dex
	bne write_block_a1
	rts


;
fade_table
; Diamond fadeout
	.byte $ff,$ff,$ff,$ff,$ff,$e7,$c3,$81
	.byte 0,0,0,0,0,0,0,0,0
; Diamond fadein
	.byte 0,0,$81,$c3,$e7,$ff,$ff,$ff
	.byte $ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff

; Masks to store in Attribute BCBs, dependant on if instructions being viewed
title_masks
	.byte $ff,$f3
	
	;
	; ########################################################################################
	; data
	;
; #gr1 change all "DB" to ".btye"
;
; Palette entries for Colours, Luma=3 through 10 from Real.act
;
rgb_table
; COL 0
	.BYTE 91,91,91,106,105,106,121,120,121,136,135,136,151,151,151,161,160,161,175,175,175,190,190,190
; COL 1
	.BYTE 136,88,0,148,103,12,165,118,27,178,132,42,193,148,58,202,157,67,218,173,83,232,187,98
; COL 2
	.BYTE 146,78,17,158,93,34,175,108,49,188,123,65,204,138,80,213,147,91,228,163,105,242,177,121
; COL 3
	.BYTE 157,64,67,170,78,80,184,94,96,198,109,111,213,125,127,222,135,135,237,149,150,252,164,165
; COL 4
	.BYTE 138,57,152,150,71,165,165,87,181,179,101,195,195,117,209,205,126,218,220,141,233,234,151,247
; COL 5
	.BYTE 127,58,172,141,72,186,155,88,199,169,103,213,184,119,229,194,128,237,208,144,252,223,159,255
; COL 6
	.BYTE 110,65,187,124,79,200,138,94,214,153,109,227,168,124,242,177,133,251,192,149,255,207,163,255
; COL 7
	.BYTE 75,83,186,89,97,199,104,111,213,119,126,226,135,142,242,144,151,250,150,166,255,174,181,255
; COL 8
	.BYTE 58,94,170,72,108,183,88,123,197,103,138,210,118,153,226,128,162,235,143,178,249,158,192,255
; COL 9
	.BYTE 47,104,150,62,117,164,77,131,178,92,146,193,108,161,210,116,171,217,131,186,231,147,201,246
; COL 10
	.BYTE 29,129,68,44,142,80,59,157,96,74,172,111,89,187,126,99,196,135,114,211,150,130,226,165
; COL 11
	.BYTE 50,131,0,63,145,11,79,160,27,94,174,42,110,189,59,119,198,68,135,213,83,150,227,99
; COL 12
	.BYTE 69,126,0,83,140,0,98,155,7,112,169,22,128,185,38,137,194,47,153,209,62,168,223,77
; COL 13
	.BYTE 93,115,0,106,130,0,122,145,0,136,158,15,152,174,31,161,183,40,186,198,56,191,213,72
; COL 14
	.BYTE 116,101,0,129,116,0,144,131,7,159,145,22,174,161,38,183,170,46,199,186,62,213,199,77
; COL 15
	.BYTE 137,88,0,149,103,10,164,118,27,178,131,42,194,148,58,203,157,68,218,172,83,232,186,98
;
text_data
	.byte $0b,"  Score  ",$00,$0d
	.byte $b9,"  Lives  ",$00,$bb
	.byte $37,"  Blocks ",$00,$39
	.byte $1a,"  Value  ",$00,$1c
	.byte $76,"  Level  ",$00,$78
	.byte $57," Hi Score",$00,$59
	.byte 0,0
text_data_end
; Align to page boundary
;
	*=(*+256)&$FF00
text_author
text_level_skipped
	.byte "  Level  skipped  "
text_pressi
	.byte "    Press I for   "
text_instructions
	.byte "   Instructions   "
text_movejoy
	.byte " Move joystick ",30,32,31
text_toselect
	.byte "    to select     "
text_start_level
	.byte "Starting level:   "
	
text_high
	.byte "High score: "

text_paused
	.byte "   Game  paused   "
	
text_press_space
	.byte "   Press  FIRE    "
	
text_level_cleared
	.byte "  Level  cleared  "

text_all_levels_cleared
	.byte "All levels cleared"
	
text_congrats
	.byte " CONGRATULATIONS! "
	
text_game_over
	.byte " G A M E  O V E R "
;text_title
;	.byte "OuadrHHon"
;text_title_end
;
text_died
	.byte "    You  died     "
text_aborted
	.byte "  Level Aborted   "

block_colours
	.byte $08,$b7,$34,$f9,$45,$a8,$75,$16
	.byte $27,$e6,$89,$a5,$f5,$68,$55,$05
	
; shades get mixed with block colours for edge parts
; mix is indexed by colour nybble of palette index
shades
	.byte $0c,$0a,$0b,$0b,$0a,$0c,$0c,$09
	.byte $0d,$0c,$0c,$0b,$08,$08,$0b,$0d
;	.byte $00,$46,$37,$47,$47,$47,$37,$57

background_pattern
	.byte $56,$55,$5A,$56,$6A,$5A,$AA,$6A	; 1 char twice, for clearing blocks
	.byte $56,$55,$5A,$56,$6A,$5A,$AA,$6A
background_lum
	.byte $e1,$e2,$e3,$e4,$e5,$e4,$e3,$e2,$e1
;	.byte $00,$20,$32,$43,$54,$45,$34,$23,$02
background_lum_end

blocks_ptr_lo
	.byte <block
	.byte <block_star
	.byte <block_die
	.byte <block_disk
	.byte <small_block
	.byte <small_block
	.byte <small_block
	
sprite_ptrs_lo
	.byte <sprite0
	.byte <sprite1
	.byte <sprite2
	.byte <sprite3

blocks_ptr_hi	
	.byte >block
	.byte >block_star
	.byte >block_die
	.byte >block_disk
	.byte >small_block
	.byte >small_block
	.byte >small_block
	
sprite_ptrs_hi
	.byte >sprite0
	.byte >sprite1
	.byte >sprite2
	.byte >sprite3
	
block	; 16*16
	.byte $55,$6A,$6A,$6A,$6A,$6A,$6A,$6A
	.byte $56,$A8,$A8,$A8,$A8,$A8,$A8,$A8

	.byte $6A,$6A,$6A,$6A,$6A,$6A,$6A,$80
	.byte $A8,$A8,$A8,$A8,$A8,$A8,$A8,$00
	
block_star	; 16*16
	.byte $55,$6A,$6A,$66,$66,$65,$69,$55
	.byte $56,$A8,$A8,$98,$98,$58,$68,$54

	.byte $55,$69,$65,$66,$66,$6A,$6A,$80
	.byte $54,$68,$58,$98,$98,$A8,$A8,$00
	
block_die	; 16*16
	.byte $55,$6A,$69,$65,$65,$61,$61,$65
	.byte $56,$A8,$68,$58,$58,$48,$48,$58

	.byte $68,$69,$6A,$66,$65,$66,$6A,$80
	.byte $28,$68,$A8,$98,$58,$98,$A8,$00
	
block_disk	; 16*16
	.byte $55,$6A,$40,$40,$6A,$6A,$69,$69
	.byte $56,$A8,$A8,$A8,$A8,$A8,$68,$28

	.byte $68,$6A,$69,$69,$69,$68,$6A,$80
	.byte $28,$A8,$68,$28,$28,$28,$A8,$00

small_block
	.byte $56,$68,$68,$68,$68,$68,$68,$80
	.byte $56,$68,$68,$68,$68,$68,$68,$80
	
	.byte $56,$68,$68,$68,$68,$68,$68,$80
	.byte $56,$68,$68,$68,$68,$68,$68,$80

sprite_lives
	.byte $30,$FC,$FC,$FC,$FC,$FC,$30,$00	; smaller ball for "lives"
sprite0
	.byte $00,$00,$00,$00,$00,$00,$00,$00
	.byte $3C,$FF,$FF,$FF,$FF,$FF,$FF,$3C
	.byte $00,$00,$00,$00,$00,$00,$00,$00
sprite1
	.byte $00,$00,$00,$00,$00,$00,$00,$00
	.byte $0F,$3F,$3F,$3F,$3F,$3F,$3F,$0F
	.byte $00,$C0,$C0,$C0,$C0,$C0,$C0,$00
	.byte $00,$00,$00,$00,$00,$00,$00,$00
sprite2
	.byte $00,$00,$00,$00,$00,$00,$00,$00
	.byte $03,$0F,$0F,$0F,$0F,$0F,$0F,$03
	.byte $C0,$F0,$F0,$F0,$F0,$F0,$F0,$C0
	.byte $00,$00,$00,$00,$00,$00,$00,$00
sprite3
	.byte $00,$00,$00,$00,$00,$00,$00,$00
	.byte $00,$03,$03,$03,$03,$03,$03,$00
	.byte $F0,$FC,$FC,$FC,$FC,$FC,$FC,$F0
	.byte $00,$00,$00,$00,$00,$00,$00,$00
	
; Change ATASCII -> screen codes table
screen_table
	.byte $40,$20,$60,$00
colour1_table
	.byte $20,$21,$21,$22,$22,$23,$23,$24
	.byte $24,$23,$23,$22,$22,$21,$21,$20
	.byte $70,$71,$72,$73,$74,$75,$76,$77
	.byte $77,$76,$75,$74,$73,$72,$71,$70
	.byte $a0,$a1,$a2,$a3,$a4,$a5,$a6,$a7
	.byte $a7,$a6,$a5,$a4,$a3,$a2,$a1,$a0
	.byte $e0,$e1,$e2,$e3,$e4,$e5,$e6,$e7
	.byte $e7,$e6,$e5,$e4,$e3,$e2,$e1,$e0
luma1_table
  	.byte 2,3,3,4,4,5,5,7
 	.byte 7,5,5,4,4,3,3,2
; 	.byte 1,2,2,3,3,4,4,6
; 	.byte 6,4,4,3,3,2,2,1

gtia_colours
	.byte 0,0,0,0 ; PMG colours
	.byte 0,$1b,$82,$82,0	; PF colours
;
	.opt list
xdl_gamescreen
	.byte $20,$00,5 ; Repeat 6 blank
;
	.byte $62	; Overlay, Repeat, overlay adr
	.byte $0c	; Map parms
	.byte 21	; repeat 22
	.byte 0,$00,1	; Overlay @ $10000
	.word 256	; Step 256
	.byte 0,0,0,0	; Attribute H/Vscrol, size
	.byte $10,255	; narrow width, palette 1, priority
;
 	.byte $24,$00,1 ; Overlay Off, repeat 2 blank
; Initial attribute line
	.byte $28,$0e	; Repeat, overlay+mapadr+parms+parms, Overlay Off
	.byte 7		; Repeat 8 lines
	.word vbxe_attrib_map
	.byte 0		; Map address $8000 in VBXE RAM
	.word 160	; 160 bytes per line
	.word 0		; HScroll, VScroll = 0,0
	.byte 7,7	; Width, Height of each cell = 8 pixels
	.byte 1,0	; Normal width screen, priority to GTIA graphics

; Next 6, attributes continued, text mode start
xdl_t1
	.byte $e1	; Text on, repeat, set overlay address, set scroll
	.byte $09	; Chbase, overlay attributes
	.byte 47	; Repeat 48 scanlines
	.byte 0,$28,$01	; Text at $12800 in VRAM
	.byte 160,0	; Step 160
	.byte 0,0	; H/VScrol
	.byte $28	; CHBase
	.byte 1,$ff	; Palettes 0, normal width, Overlay has priority
; Next 10, attributes continued, text mode off
	.byte $24,0,79	; 80 scanlines continue with overlay off
; Next 1, attributes continued, text mode again
xdl_t2
	.byte $21,0	; Text on, repeat
	.byte 7		; 48 scanlines
; Next 1, attr cont, text off
	.byte $24,0,7	; 8 scanlines
; Next 1 attr cont, text on
xdl_t3
	.byte $21,0
	.byte 7
; Next 1, attr cont, text off
	.byte $24,0,7	; 8 scanlines
; Next 2 attr cont, text on
xdl_t4
	.byte $21,0
	.byte 15	; 16 scanlines
; Last 1, attributes cont, text mode off
	.byte $24,0	; Text off, repeat
	.byte 7		; 8 scanlines
; 1 blank scanline
	.byte $30,0,0	; 1 scanlines Blank
;
	.byte $F1	; Text mode, attr off, repeat, set overlay mem, set overlay scroll
	.byte $09	; Chbase, overlay attributes
	.byte 7		; Repeat 8
xdl_scroller_adr
	.byte 0,$20,$01	; Scroller @ $12000 in VRAM
	.word 160	; Step 160
xdl_scroller_hscrol
	.byte 0,0	; HSCROL/VSCROL for Text
	.byte 40	; CHSET = 80K into VRAM, $14000
	.byte $01,$ff	; Normal width, palette 0, overlay gets priority
	.byte $80,$80	; For Altirra, reset Attribute scrolling
	.byte 0,0	; H/VScrol to 0,0
	.opt no list
	.dc 8 0	; Filler for now
; Patterns for blit fills
attr_set_hires
	.byte 0,$0a,$23,4
attr_set_lores
	.byte 0,0,0,0
;
;
	*=(*+256)&$ff00
;
; BCBs to copy bitmap data from Plus4 screen @$2000 to Atari screen at $6000
;
	.include quad_blits.src
;


;
atari_init
	jsr hide_instructions
	ldx #0
	stx sdmctl
	ldy #8
init_set_colours
	lda gtia_colours,y
	sta colpm0,y
	dey
	bpl init_set_colours
	txa
	ldy #8
atari_i1
	sta audf1,y
	dey
	bpl atari_i1
	ldy #3
	sty sskctl
	sty skctl	; Clear Pokey sound and SIO noise
	txa
ai_wipe1
	sta $400,x
	inx
	bpl ai_wipe1	; Clear $400-$47f
	jsr wait_frame
	lda #3
	ldy #v_video_control	
	sta (vbxe_ptr),y		; #fix Enable XDL, extended GTIA colours, transparencies
	lda #<(xdl_gamescreen-$1000)
	iny
	sta (vbxe_ptr),y		; XDL 0
	lda #>(xdl_gamescreen-$1000)
	iny
	sta (vbxe_ptr),y		; XDL 1
	lda #0
	iny
	sta (vbxe_ptr),y		; XDL 3 address pointer
	lda #<blit_set_attribs
	ldy #v_bl_adr0
	sta (vbxe_ptr),y		; BCB 0
	lda #>(blit_set_attribs-$1000)
	iny
	sta (vbxe_ptr),y		; BCB 1Setup initial blit to setup attributes
	lda #0
	iny				; BCB 2
	sta (vbxe_ptr),y
	ldy #v_priority0
	lda #0
	sta (vbxe_ptr),y		; Priority 0
	iny
	sta (vbxe_ptr),y		; P1
	iny
	sta (vbxe_ptr),y		; P2
	iny
	sta (vbxe_ptr),y		; P3
	lda #1
	ldy #v_blitter_start		; Run first blit
	sta (vbxe_ptr),y
	jsr wait_frame
	jsr wait_frame

	ldx #<dlist_gamescreen
	ldy #>dlist_gamescreen
	stx sdslst
	sty sdslst+1
	ldx #<vbi
	ldy #>vbi
	stx vvbi
	sty vvbi+1
	ldx #<vbd
	ldy #>vbd
	stx vvbd
	sty vvbd+1
	jsr wait_frame
	lda #$22
	sta sdmctl		; Re-enable Antic DMA

	rts
;
wait_frame
	lda rtclock+2
wait_f1
	cmp rtclock+2
	beq wait_f1
	rts
;
; VBlank Immediate Routine
;
vbi
	cld
	lda ch
	and #$3f
	cmp #33
	bne vbi_not_space
	lda #$ff
	sta ch
	lda pauseflag
	eor #1
	sta pauseflag	; Toggle Pause mode
	jmp vbi_cont
vbi_not_space
	cmp #28
	bne vbi_not_esc
	lda ch
	ldx #$ff
	stx ch
	stx abortflag	; Esc aborts level
	cmp #28+64	; SHIFT-Esc aborts game
	bne vbi_cont
	lda #1
	sta lives
	bne vbi_cont
vbi_not_esc
	cmp #44		; TAB skips level
	bne vbi_not_skip
	lda #$ff
	sta ch
	sta skipflag
vbi_not_skip
vbi_cont
	lda pauseflag
	and sstrig0
	sta pauseflag	; Pause off if fire button pressed
	bit inhibit_vbblits
	bmi vbi_finish	; all blits inhibited
	ldy #v_bl_adr0
	bit inhibit_attr_blitflag
	bmi vbi_noattr	; Attribute blits inhibited
	lda #<(blits_copy_attribs-$1000)
	jmp vbi_checkfill
vbi_noattr
	lda #<(blits_copy_pf1-$1000)
vbi_checkfill
	bit pf2_fillflag
	bpl vbi_nofill	; Check if PF2 attribute fill requested
	lda #0
	sta pf2_fillflag
	lda #<(blits_copy_pf2-$1000)	; Set extra blit
vbi_nofill
	sta (vbxe_ptr),y
	iny
	lda #>(blits_copy_attribs-$1000)
	sta (vbxe_ptr),y
	iny
	lda #0
	sta attract
	sta (vbxe_ptr),y	; Setup BCB address
	iny	; points to blitter_start
	lda #1
	sta (vbxe_ptr),y	; Start blit
vbi_finish
	jmp $e45f
;
; Deferred VBlank - do TED -> Pokey sound conversion
vbd
	lda key_delay
	beq vbd_nokeyd
	dec key_delay	; Delay counter for joystick during menu
vbd_nokeyd
	lda rmt_start	; Is RMT playing music?
	beq do_ted_sounds	; No, play TED Sounds
	jmp vbd_keys
do_ted_sounds
	lda #$78
	sta audctl	; Set AUDCTL, 2 x 16-bit voices
	lda ted_shadows+$12
	and #3
	sta voice1freq+1	; V1 freq high
	lda ted_shadows+$0e
	sta voice1freq		; V1 freq low
	lda ted_shadows+$10
	and #3
	sta voice2freq+1	; V2 freq high
	lda ted_shadows+$0f
	sta voice2freq		; V2 freq low
	ldx #4
	ldy #2
; Convert frequencies to AUDFn values (16-bit)
vbd_audf_copy
	lda #0
	sec
	sbc voice1freq,y
	sta zvbtemp1
	lda #4	;	<1024
	sbc voice1freq+1,y
	asl a
	asl a
	asl a
	sta zvbtemp1+1
	lda zvbtemp1
	lsr a
	lsr a
	lsr a
	lsr a
	lsr a		; Get top 3 bits of freq low part
	ora zvbtemp1+1
	sta zvbtemp1+1
	lda zvbtemp1
	asl a
	asl a
	asl a
	sta audf1,x	; Store in AUDF1 and 3
	lda zvbtemp1+1
	sta audf2,x	; Store in AUDF2 and 4
	ldx #0
	dey
	dey
	bpl vbd_audf_copy
	lda ted_shadows+$11	; TED Sound Control
	tax
	and #$60	; Keep voice 2 control stuff only
	lsr a
	lsr a
	sta zvbtemp1
	txa
	and #7
	ora zvbtemp1
	tax		; Merge master volume with voice 2 control
	lda voice2_table,x
	sta audc4	; Copy to AUDC4
	lda ted_shadows+$11
	tax
	and #$10
	lsr a
	sta zvbtemp1
	txa
	and #7
	ora zvbtemp1
	tax		; Merge master volume with voice 1 control
	lda voice1_table,x
	sta audc2	; Copy to AUDC2
; 
; Read joystick/keyboard here
; If Stick0 not moved, allow keys for movement
vbd_keys
	lda skctl	; check bit 3 (SHIFT)
	tax
	lsr a
	lsr a
	lsr a
	and #1
	and consol
	and strig0	; SHIFT also performs fire button funtion
	sta sstrig0
	lda porta
	and #$f
	sta stick0
	cmp #$f
	bne vbd_finish	; skip keycheck if stick moved
; No stick input, check keys
	txa
	and #4
	bne vbd_finish		; No key input right now
	ldy #$f			; Assume no keys
	lda kbcode
	and #$3f
	cmp #32			; Check left
	bne vbd_key2
	ldy #11
vbd_key2
	cmp #34			; Check right
	bne vbd_key3
	ldy #7
vbd_key3
	sty stick0
vbd_finish
	bit rmt_start	; RMT start requested?
	bpl vbd_finish1	; No
	lda rmt_song
	ldx #<rmt_music_data
	ldy #>rmt_music_data
	jsr rmt_init	; Init RMT for new song start
	ldx rmt_song
	inx
	stx rmt_start	; Set to song playing (+1) 
vbd_finish1
	inc ntsc_counter
	ldy #0
	lda ntsc_counter
	cmp #6
	bne vbd_checkrmt
	sty ntsc_counter
	lda pal
	cmp #1		; PAL ?
	bne vbd_finish2	; Skip RMT each 6th if NTSC system
vbd_checkrmt
	lda rmt_start
	beq vbd_finish2	; No song in progress
	jsr rmt_play
	lda rmt_song
	beq vbd_finish2	; No timer if main song playing
	dec rmt_timer
	bne vbd_finish2
	jsr rmt_silence
	lda #0
	sta rmt_start	; Clear RMT play flag
vbd_finish2
; Do scroller
	lda rmt_song
	bne vbd_noscroll	; Don't scroll if not in main menu
	lda scroller_fine
	clc
	adc #3
	tay
	and #$f 
	sta scroller_fine
	lsr a
	sta xdl_scroller_hscrol
	tya
	lsr a
	lsr a
	lsr a
	and #2
	clc
	adc scroller_offset
	sta scroller_offset
	sta xdl_scroller_adr
	lda scroller_offset+1
	adc #0
	cmp #5
	bne vbd_scroll2
	lda #0
vbd_scroll2
	sta scroller_offset+1
	ora #$20
	sta xdl_scroller_adr+1
vbd_noscroll
	lda change_palette
	beq vbd_nopalette_change
	bpl vbd_palette_change2
	lda #10	; was 2
	sta change_palette
; palette_change1
	lda palette_colour
	and #$f
	asl a
	asl a
	asl a		; * 8
	sta palette_pointer
	asl a		; *16
	clc 
	adc palette_pointer
	sta palette_pointer
	lda #0
	adc #>rgb_table
	sta palette_pointer+1
	lda #<rgb_table
	clc
	adc palette_pointer
	sta palette_pointer
	bcc vbd_palette_change2
	inc palette_pointer+1
vbd_palette_change2
	lda rtclock+2
	and #7
	bne vbd_nopalette_change
	lda change_palette
	clc
	sbc #2
	sta rgbtemp
	asl a
	adc rgbtemp
	tay	; Y=(change_palette-2)*3
	lda (palette_pointer),y
	sta rgbtemp
	iny
	lda (palette_pointer),y
	sta rgbtemp+1
	iny
	lda (palette_pointer),y
	sta rgbtemp+2
	lda change_palette
	tax
	dex	; was inx
	cpx #1	; was 11
	bne vbd_palette_change3
	ldx #0
vbd_palette_change3
	stx change_palette
	ldy #v_psel
	tax
	lda #1
	sta (vbxe_ptr),y	; PSEL= 1
	txa
	dey
	sta (vbxe_ptr),y	; CSEL
	ldy #v_cr
	lda rgbtemp
	sta (vbxe_ptr),y	; Set Red
	iny
	lda rgbtemp+1
	sta (vbxe_ptr),y	; Set Green
	iny
	lda rgbtemp+2
	sta (vbxe_ptr),y	; Set Blue
vbd_nopalette_change
	lda pauseflag
	bne vbd_novalue		; Don't do value counter if paused
	lda ntsc_counter
	bne vbd_dovalue
	lda pal
	cmp #1
	bne vbd_novalue		; Skip counter stuff each 6th if NTSC
vbd_dovalue
	inc value_counter
	lda value_counter
	cmp #100		; Block value decreases every 2 seconds
	bne vbd_novalue
	lda #0
	sta value_counter
	lda block_value
	sed
	sec
	sbc #1
	cld
	cmp #0
	beq vbd_novalue		; Don't decrease block value under 1
	sta block_value
	sta value_changed	; Flag that value has changed (nonzero)
vbd_novalue

	jmp $e462
;
set_inhibit_vbblits
	lda #$ff
	bne store_inhibit_vbblits
clear_inhibit_vbblits
	lda #0
store_inhibit_vbblits
	sta inhibit_vbblits
	rts
;
; Translation tables for TED to Pokey sound control
; V1, 16 entries - bit 3 = voice enable, bits 2-0 = volume
;
voice1_table
	.byte 0,0,0,0,0,0,0,0
 	.byte $a0,$a2,$a3,$a4,$a5,$a6,$a8,$aa
; V2, 32 entries - as voice 1 + bit 4 = noise
voice2_table
	.byte 0,0,0,0,0,0,0,0
	.byte $a0,$a2,$a3,$a4,$a5,$a6,$a8,$aa
	.byte $80,$82,$83,$84,$85,$86,$88,$8a
	.byte $80,$82,$83,$84,$85,$86,$88,$8a

;
;	Align to 256 byte boundary
;
	*=(*+256)&$FF00
dlist_gamescreen
	.byte $70,$70,$70,$50	; 30 Blank
	.byte $4e
	.word atari_bitmap_data
	.dc 101 $0e		;
	.byte $4e
	.word $7000	; Second LMS
	.dc 89 $0e
	.byte 0			; 1 Blank
;	.byte $42
;	.word atext_status	; 1 Mode 2 line for messages
	.byte $41
	.word dlist_gamescreen	; JVB back
	.dc 80 0	; Filler

;atext_status
;	.sbyte "   Quadrillion Test -  1 Dec, 2010    " 
	.dc 10 0 ; Filler
;
; Level related stuff follows
;
	*=$9100
max_allowable_level
	.byte $20	; Highest Level that can be played
restart_at_level
	.byte 5		; Level number to wrap around to once last one completed
highest_selectable_level
	.byte 8
level_names
	.byte "Colored ","  Gem   "	; 1
	.byte "Meet the","Blockers"	; 2
	.byte " Candy  ","  Shop  "	; 3
	.byte "Fill  or","  File  "
	.byte "  BIG   ","  Wall  "	; 5
	.byte "Storage ","Facility"	; 6
	.byte " I made "," this ! "	; 7
	.byte " Trade  ","  Mark  "
	.byte " in da  "," house  "
	;
	.byte "        ","        "
	.byte "        ","        "
	.byte "        ","        "
	.byte "        ","        "
	.byte "        ","        "
	.byte "        ","        "
	;
	.byte "  Real  ","  Easy  "	; 10
	.byte "  Four  ","  Turns "	; 11
	.byte "   GO   "," Around "
	.byte " Ghost  ","  Town  "
	.byte "Rainbow "," Icicles"
	.byte "  Wire  ","  Fence "	; 15
	.byte "Shop Re-","visited "	; 16
	.byte "Only one","  Green " 	; 17
	.byte " Mine-  ","  Field "	; 18
	.byte " Corner "," Bounce "	; 19
	;
	.byte "        ","        "
	.byte "        ","        "
	.byte "        ","        "
	.byte "        ","        "
	.byte "        ","        "
	.byte "        ","        "
	;
	.byte "Lando's "," Trap!  "	; 20

level_ptr_lo
	.byte <(level01-1)
	.byte <(level02-1)
	.byte <(level03-1)
	.byte <(level04-1)
	.byte <(level05-1)
	.byte <(level06-1)
	.byte <(level07-1)
	.byte <(level08-1)
	.byte <(level09-1)
	.byte 0,0,0,0,0,0
	.byte <(level10-1)
	.byte <(level11-1)
	.byte <(level12-1)
	.byte <(level13-1)
	.byte <(level14-1)
	.byte <(level15-1)
	.byte <(level16-1)
	.byte <(level17-1)
	.byte <(level18-1)
	.byte <(level19-1)
	.byte 0,0,0,0,0,0
	.byte <(level20-1)
	
level_ptr_hi
	.byte >(level01-1) 
	.byte >(level02-1) 
	.byte >(level03-1) 
	.byte >(level04-1) 
	.byte >(level05-1) 
	.byte >(level06-1) 
	.byte >(level07-1) 
	.byte >(level08-1) 
	.byte >(level09-1) 
	.byte 0,0,0,0,0,0
	.byte >(level10-1) 
	.byte >(level11-1) 
	.byte >(level12-1) 
	.byte >(level13-1) 
	.byte >(level14-1) 
	.byte >(level15-1) 
	.byte >(level16-1) 
	.byte >(level17-1) 
	.byte >(level18-1) 
	.byte >(level19-1) 
	.byte 0,0,0,0,0,0
	.byte >(level20-1) 
;
	.include quad_leveldata.src