/* 
Skool Daze
Atari 8-bit port

TODO:
- check reading small and big letter keys - maybe support for shift is required (done - in C64 version big letters are used, so keyboard emulation is OK)
- speech bubbles (implemented using hardware sprites on C64) (partially done)
- remove colorram accesses to free more RAM
- document memory layout

DONE:
- proper keyboard reading
- PMG color overlays
- hide speech bubble when speech rectangle is shown
- limit screen to 192 lines (currently uses 200 as C64) - this will enable additional $140 bytes of free memory
- DLI dynamic code moved to $ff00 - $fff9
- use sprite memory at $3c00 - this will enable using $c800 - $cbff for code
	- needs sprite routine to be adjusted for new sprite data location
- shields flashing (done on IRQ by inversing colorram on C64)
- fix PrepareScreen for NTSC (currently taking 3 frames to execute causing flashing glitches, PAL version needs 2 frames)
- fix colors for NTSC (need to to patch screen data)
- refresh screen after bubble is hidden by marking tile dirty?
- sound effects (port from C64/SID)
- fix problem of sprites animation under displayed speech bubble
- fix the roof on screen7/8 - it is not colored, as it uses 1 pixels, while it should use 0 pixels
	- this needs a change in graphics data

MEMORY:
0000 - 00ff: zero page
0100 - 013f: C64 VIC sprite registers
0140 - 014c: buffer for PMG routine
0150 - 01ff: stack
0200 - 02ff: backbuffers for software sprites
0300 - 07ff: Atari P/MG memory
0800 - bfff: C64 original game code (with Atari specific patches)
c000 - cbff: Atari code
cc00 - cfff: C64 color memory
d000 - d7ff: Atari hardware registers
d800 - dfff: Atari code
e000 - e00f: free
e010 - fe0f: screen memory
fe10 - feff: free
ff00 - fff9: dynamically generated DLI code
fffa - ffff: NMI/IRQ vectors
*/

vice_dump_offset = $84
; game equates
c64screen		equ $e000
bitmapscreen	equ $e010
spriteregs		equ $0100
gtiatempregs	equ $0140
PMGScanline		equ $014D
PMGScanlinePrevious	equ $014E
FootstepLengthReg	equ $014F
sprite1backbuffer equ $0200
sprite2backbuffer equ $0240
sprite3backbuffer equ $0280
sprite4backbuffer equ $02c0
spriteshapesregs  equ $cff8
spritesbase		  equ $3400
;SpriteDataRectangleBubble1	equ $CAC0
SpriteDataRectangleBubble1	equ spritesbase+$0AC0
SpritePointerCA40 equ spritesbase+$0A40
SpritePointerCA8E equ spritesbase+$0A8E
ScreenSafeRowAddress equ bitmapscreen+9*$140
PMGMemory		equ $0000
DLICode			equ $ff00

irq_c64			equ $39CC; $39C7
irq_c64_end		equ $3A8A

footstep = $84
FootstepLength = 2

; macros
atari_screen_address_dta .macro c64_addr_param
		?c64_addr 	equ :c64_addr_param - c64screen
		?row_low 	equ ?c64_addr & $07
		?row_high 	equ ?c64_addr / $140
		?row = ?row_low | (?row_high << 3)
		?column 	equ (?c64_addr % $140) / 8
		dta a(bitmapscreen + $28*(?row) + (?column))
		.endm

atari_screen_address_equ .macro atari_equ, c64_addr_param
		?c64_addr 	equ :c64_addr_param - c64screen
		?row_low 	equ ?c64_addr & $07
		?row_high 	equ ?c64_addr / $140
		?row = ?row_low | (?row_high << 3)
		?column 	equ (?c64_addr % $140) / 8
		.def :atari_equ = bitmapscreen + $28*(?row) + (?column)
		.endm

.macro DLI_VECTOR
		mva <:1 $fffa
		ift [>:2]<>[>:1]
		mva >:1 $fffb
		eif
.endm
		
; colors
black			equ $00
white			equ $0e

		icl 'atari.hea'
		
		org $c000,$2000
;*************************************************
;**************** Display List *******************
;*************************************************
		
; dlist
dlist	
		dta $70, $70, $70
DListLoadMemory1		
		dta $4f, a(bitmapscreen)
DListBlock1		
		:101 dta $0f
DListLoadMemory2		
		dta $4f, a(bitmapscreen+$1000-$10)
DListBlock2		
		:97-8 dta $0f
		dta $41, a(dlist)
		
;*************************************************
;****************** NMI/IRQ **********************
;*************************************************
	
TimerVBLANK
		dta 0	
C64IRQEnabled		
		dta 0
PMGChangeRequested
		dta 0
VblankPMGEnabled
		dta 0
nmi
		sta nmist ; NMI acknowledge
		
		pha ; prologue
		txa
		pha
		tya
		pha
		
		inc TimerVBLANK ; timer
		
		; check for ESC key
		lda skstat
		and #%100
		bne VBlankPlayMusic
		lda kbcode
		cmp #$1c ; ESC
		bne VBlankPlayMusic
		ldx #$ff
		txs
		jsr ResetPokey		
@		lda vcount	; sync to VBLANK
		bne @-
		lda #$00	; turn off screen
		sta dmactl
		sta nmien
@		lda skstat	; wait for key to go down
		and #%100
		beq @-	
@		lda vcount	; wait for VBLANK
		bne @-
		lda #%00111110
		sta dmactl
		lda #$c0
		sta nmien		
		lda #$00
		sta TitleScreenShownFlag
		jsr $BFDB
		jmp $0800
		
VBlankPlayMusic		
		bit MusicEndFlag ; play music
		bmi @+
		jsr MusicStep
@		
		bit FootstepLengthReg ; footstep sound handling
		bmi @+
		dec FootstepLengthReg
		lda #$80
		sta audc4
		
@		
		bit PMGChangeRequested ; change of PMG requested
		bpl @+
		jsr PrepareScreen
@		bit VblankPMGEnabled	; PMGVblank routine
		bpl @+
		jsr PMGVBlank
@		bit C64IRQEnabled
		bpl irq_end
		jmp irq_c64				; standard C64 IRQ routine
		

irq_end
		pla
		tay
		pla
		tax
		pla
irq
		rti
		
ScrollScreenPrologue
		lda #$80
		sta audc4 ; turn footstep off
		lda #$e0
		sta audc2 ; turn sfx on channels 1-2 off
		
		lda spriteregs+$15
		beq @+
		;lda #$00 ; must preserve old value of sprite enable register
		jsr HideBubble
@		lda #$00
		sta C64IRQEnabled
		lda #$ff
		sta PMGChangeRequested
@		lda PMGChangeRequested
		bne @-
		rts
		
ScrollScreenLeft
		;lda #$00
		;sta C64IRQEnabled
		jsr ScrollScreenPrologue
		jsr $3072
		lda #$08
ScrollScreenEndRestorSprites
		ldx spriteregs+$15
		beq ScrollScreenEnd
		;clc
		;adc LastSpriteX
		;sta LastSpriteX
		;jsr RenderBubbleDirect
		lda #$ff
		sta BubbleSpriteForceFullRenderOnUpdate
ScrollScreenEnd		
		lda $58
		ora #$80
ScrollScreenEnd2		
		sta PMGChangeRequested
		lda #$ff
		sta C64IRQEnabled
		rts
		
ScrollScreenRight		
		;lda #$00
		;sta C64IRQEnabled
		jsr ScrollScreenPrologue
		jsr $3113
		lda #$f8
		jmp ScrollScreenEndRestorSprites
		
ScrollScreenRight5x		
		;lda #$00
		;sta C64IRQEnabled
		jsr ScrollScreenPrologue
		jsr $3113
		jsr $3113
		jsr $3113
		jsr $3113
		jsr $3113
		lda $334c
		bne ScrollScreenEnd
		lda #$ff
		bne ScrollScreenEnd2
		
;*************************************************
;************* Keyboard + joystick ***************
;*************************************************
		
read_joystick
		lda trig0		; read joystick
		lsr @
		lda porta
		;eor #$ff
		and #$0f
		scc:ora #$10
		rts
		
readkey_set_input
		eor #$ff
		sta keys_cols
		eor #$ff
		rts

readkey_invalid
		lda #$ff
		rts
		
readkey_c64
		;eor #$ff
		;sta keys_cols
		lda keys_cols
		beq readkey_invalid
readkey_c64_again
		lda #$ff
		sta key_result
		lda skstat
		and #$04
		bne nokey
		stx rk_save_x+1
		sty rk_save_y+1
		lda kbcode
		bmi key_exit
		tay
		and #$3f
		tax
		lda atari_c64_keys,x
		and #$07
		tax
		lda _bits,x
		and keys_cols
		beq key_exit
		tya
		and #$3f
		tax
		lda atari_c64_keys,x
		lsr @
		lsr @
		lsr @
		lsr @
		tax
		lda _bits,x
		eor #$ff
		sta key_result
key_exit
rk_save_x
		ldx #$00
rk_save_y
		ldy #$00
nokey	lda key_result
		rts

		
keys_cols 	dta $00
key_result	dta $00
		
atari_c64_keys
; c64 keyboard matrix
;  Bit    Col0  Col1  Col2  Col3  Col4  Col5  Col6  Col7
;  Row0   DEL   "3"   "5"   "7"   "9"   "+"   PND   "1"
;  Row1   RET   "W"   "R"   "Y"   "I"   "P"   "*"   <--
;  Row2   RIGHT "A"   "D"   "G"   "J"   "L"   ";"   CTRL
;  Row3   F7    "4"   "6"   "8"   "0"   "-"   HOME  "2"
;  Row4   F1    "Z"   "C"   "B"   "M"   "."  RSHIFT SPC
;  Row5   F3    "S"   "F"   "H"   "K"   ":"   "="   <C=>
;  Row6   F5    "E"   "T"   "U"   "O"   "@"   "^"   "Q"
;  Row7   DOWN LSHIFT "X"   "V"   "N"   ","   "/"   STOP
		dta $25	; L $00
		dta $24	; J $01
		dta $55	; ;: $02
		dta $ff	; F1 $03
		dta $ff	; F2 $04
		dta $54	; K $05
		dta $05	; +\ $06
		dta $16	; *^ $07
		dta $64	; O $08
		dta $ff	;   $09
		dta $15	; P $0A
		dta $63	; U $0B
		dta $10	; RETURN $0C (RET and not <--)
		dta $14	; I $0D
		dta $35	; -_ $0E
		dta $56	; =| $0F
		dta $73	; $10 V
		dta $ff	; $11 HELP
		dta $42	; $12 C
		dta $ff	; $13 F3
		dta $ff	; $14 F4
		dta $43	; $15 B
		dta $72 ; $16 X
		dta $41 ; $17 Z
		dta $31	; $18 4$
		dta $ff ; $19
		dta $01	; $1a 3#
		dta $32	; $1b 6&
		;dta $77 ; $1c ESC (RUN/STOP)
		dta $ff ; $1c ESC
		dta $02	; $1d 5%
		dta $37 ; $1e 2"
		dta $07 ; $1f 1!
		dta $75 ; $20 ,[
		dta $47 ; $21 SPACE
		;dta $77 ; $21 SPACE (RUN/STOP) (PAUSE)
		dta $45	; $22 .]
		dta $74	; $23 N
		dta $ff	; $24
		dta $44	; $25 M
		dta $76	; $26 /?
		dta $46 ; $27 LOGO (RSHIFT)
		dta $12	; $28 R
		dta $ff	; $29
		dta $61	; $2a E
		dta $13 ; $2b Y
		dta $ff	; $2c TAB
		dta $62	; $2d T
		dta $11	; $2e W
		dta $67	; $2f Q
		dta $04	; $30 9(
		dta $ff ; $31
		dta $34 ; $32 0)
		dta $03 ; $33 7'
		dta $00	; $34 BACKSPACE/DEL
		dta $33 ; $35 8@
		dta $ff ; $36 <CLEAR
		dta $ff ; $37 >INS
		dta $52 ; $38 F
		dta $53 ; $39 H
		dta $22 ; $3a D
		dta $ff ; $3b
		dta $ff ; $3c CAPS
		dta $23	; $3d G
		dta $51	; $3e S
		dta $21 ; $3f A
	
_bits	dta $01, $02, $04, $08, $10, $20, $40, $80

;*************************************************
;****************** Fixup code *******************
;*************************************************
		
PrintCharInit
		lda $4e
		sta PrintCharLoop+1
		lda $4f
		sta PrintCharLoop+2
		ldy #$00
		ldx #$00
		rts
		
PrintChar
		jsr PrintCharInit
PrintCharWork		
		clc
PrintCharLoop
		lda $ffff,x
		sta ($50),y
		inx
		bcs PrintCharEnd
		tya
		adc #$28
		tay
		bcc PrintCharLoop
		inc $51
		bcs PrintCharLoop
PrintCharEnd
		dec $51
		rts
		
PrintCharsRowCounter
		dta 0
		
		; parameters
		; $4e-$4f: source pointer
		; $50-$51: destination pointer
		; Y : number of tiles to render
PrintCharsRow
		sty PrintCharsRowCounter
		jsr PrintCharInit
PrintCharsRowLoop
		tya
		pha
		jsr PrintCharWork
		cpx #$00
		sne:inc PrintCharLoop+2
		pla
		tay
		iny	
		cpy #$10
		bne PrintCharsCheckEnd
		tya
		clc
		adc $50
		sta $50
		scc:inc $51
		lda PrintCharsRowCounter
		sec
		sbc #$10
		sta PrintCharsRowCounter
		ldy #$00
PrintCharsCheckEnd		
		cpy PrintCharsRowCounter
		bne PrintCharsRowLoop
		rts
		
sub_2ee6_fixup
		scc:inc $5b
		;lda $5a
		adc #<bitmapscreen
		sta $5a
		lda $5b
		adc #>bitmapscreen
		sta $5b
		lda $5d
		adc #$cc
		sta $5d
		rts
		
;		lda ($5e),y
;		sta ($5a),y
;		jmp sub_33b5_fixup
sub_33b5_fixup
		lda $4001
		ldy #$28
		sta ($5a),y
		lda $4002
		ldy #$50
		sta ($5a),y
		lda $4003
		ldy #$78
		sta ($5a),y
		lda $4004
		ldy #$a0
		sta ($5a),y
		lda $4005
		ldy #$c8
		sta ($5a),y
		lda $4006
		ldy #$f0
		sta ($5a),y
		lda $4007
		ldy #$18
		inc $5b
		sta ($5a),y
		dec $5b
		rts
		
sub_2F28_fixup		
		ldy #$40/8
		jmp PrintCharsRow
		
sub_388F_fixup
		sbc #$C0/8
		sta $50
		lda $4f
		sbc #$00
		sta $51
		lda #$00
		sbc $31
		lsr @
		lsr @
		lsr @
		clc
		adc $50
		sta $50
		scc:inc $51
		sec
		lda #$00
		sbc $31
		sta $4e
		lda #$45
		sta $4f
		lda $31
		lsr @
		lsr @
		lsr @
		tay
		jmp PrintCharsRow
	
sub_3a34_fixup
		sec
		sbc $58
		tax
		ldy #9
		jsr IsTileCoveredBySprite
		bcs @+
		ora #<ScreenSafeRowAddress
		sta $F2
		lda #>ScreenSafeRowAddress
		sta $F3
		jsr $3a90
@		jmp $3a41

sub_36e3_fixup
		stx sub_36e3_fixup_restore_x
		ldx $49
		ldy $4a
		jsr IsTileCoveredBySprite
		ldx #$ff
sub_36e3_fixup_restore_x equ *-1		
		bcs @+
		lda #$08
		sta $52
		jmp $36e7
@		rts		
		
sub_3329_fixup
		lda $27
		cmp #84
		bne sub_3329_no_fix
		lda $28
		cmp #1
		bne sub_3329_no_fix
		lda #$ff
		sta $4007
		ldx #$06
		lda #$00
@		sta $4000,x
		dex
		bpl @-
		ldy #$00
		jmp $3355
sub_3329_no_fix	
		lda $27
		sta $52
		jmp $332d
		
sub_bf58_fixup ; fixup for Enter Name function - allow delet for editing names
		tax
		cpx #$14
		beq EnterNameDel
		cpx #$20
		jmp $BF5B ; go back to original code
EnterNameDel
		cpy #$00 ; check for begin
		bne @+
		jmp $bf50
@		lda #$00
		dey
		sta $4700,y
		jmp $BF72
		
sub_20f5_speedup
		; speedup for rotation routine, used by PrintString function
		ldx #$f8
		stx $56
sub_20f5_20ff		
		ldy $9d
		ldx $56
		rol @
		pha
sub_20f5_2109		
		rol $4500,x
		rol $54
		txa
		sec
		sbc #$08
		tax
		dey
		beq sub_20f5_2124
		ror $54
		jmp sub_20f5_2109
sub_20f5_2124
		pla
		inc $56
		bne sub_20f5_20ff
		rts
		
;*************************************************
;*********** Bubble Sprites Engine ***************
;*************************************************
	
SpriteScreenPtr equ 0
BackBufferPtr	equ 2
SpriteDataPtr	equ 4
SpriteMaskDataPtr equ 6
SpriteX 	dta 0
SpriteY		dta 0
LastSpriteX	dta 0
LastSpriteY	dta 0
SpriteHeight dta 0
		
RenderRectangleBubble
		sta spriteregs+$15
		ldx #<SpriteRender
		ldy #>SpriteRender
		jmp RenderRectangleBubbleWorkerProc
		
RestoreRectangleBubble
		sta spriteregs+$15
		ldx #<SpriteRestore
		ldy #>SpriteRestore
		;jmp RenderRectangleBubbleWorkerProc
		
RenderRectangleBubbleWorkerProc
		; set renderer
		stx RenderCallAddress
		sty RenderCallAddress+1

		;prepare X coordinate of bubble
		lda $9a
		sec
		sbc #($03+2)
		cmp #40-9
		scc:lda #40-9
		sta SpriteX
		
		; prepare Y coordinate of bubble
		lda $fb
		sec
		sbc #$03
		sta SpriteY

		lda #$03
		sta SpriteHeight
				
		; push zero page registers
		ldx #$00
@		lda BackBufferPtr,x
		pha
		inx
		cpx #4
		bne @-

		; prepare PM/G
		lda spriteregs+$15
		beq @+
		lda #21
		ldx #9
		jsr PMGPrepareForSprites
		jmp @+1
@		jsr PMGRestoreAfterSprites
		
		; set first sprite back buffer address
@		lda #<sprite1backbuffer
		sta BackBufferPtr
		lda #>sprite1backbuffer
		sta BackBufferPtr+1
		; set sprite data address
		lda #<SpriteDataRectangleBubble1
		sta SpriteDataPtr
		lda #>SpriteDataRectangleBubble1
		sta SpriteDataPtr+1

		ldx #0
		; loop over three sprites
@		txa
		pha
		; prepare position of sprite on the screen
		ldy SpriteY
		txa
		clc
		adc SpriteX
		tax ; X
		jsr SpriteCalculatePosition
		jsr SpriteRender
RenderCallAddress equ *-2
		ldx #SpriteDataPtr
		jsr SpriteIncrementPointer
		ldx #BackBufferPtr
		jsr SpriteIncrementPointer
		pla
		tax
		inx
		inx
		inx
		cpx #9
		bne @-
		
		; pop zeropage registers
		ldx #3
SpritePopZeroPageRegisters		
@		pla 
		sta BackBufferPtr,x
		dex
		bpl @-
		rts
		
SpriteRender
		ldy #0
@		ldx #3
@		lda (SpriteScreenPtr),y
		sta (BackBufferPtr),y
		lda (SpriteDataPtr),y
		eor #$ff
		sta (SpriteScreenPtr),y
		iny
		dex
		bne @-
		jsr SpriteRenderEpilogue
		bne @-1
		rts
		
SpriteRestore		
		ldy #0
@		ldx #3
@		lda (BackBufferPtr),y
		sta (SpriteScreenPtr),y
		iny
		dex
		bne @-
		jsr SpriteRenderEpilogue
		bne @-1
		rts
		
.if 0		
SpriteRestoreFirstColumn
		ldy #0
@		lda (BackBufferPtr),y
		sta (SpriteScreenPtr),y
		iny
		iny
		iny
		jsr SpriteRenderEpilogue
		bne @-
		rts
.endif
		
SpriteCalculatePosition
		;Y = Y pos
		;X = X pos
		sty SpriteScreenPtr+1 ; Y*$100
		lda #$00 ; Y*$40
		sta SpriteScreenPtr
		tya
		lsr @
		ror SpriteScreenPtr
		lsr @
		ror SpriteScreenPtr
		;clc
		adc SpriteScreenPtr+1
		sta SpriteScreenPtr+1
		txa ; +X
		;clc
		adc SpriteScreenPtr
		sta SpriteScreenPtr
		scc:inc SpriteScreenPtr+1
		clc ; +bitmapscreen
		adc #<bitmapscreen
		sta SpriteScreenPtr
		lda SpriteScreenPtr+1
		adc #>bitmapscreen
		sta SpriteScreenPtr+1
		rts
	
SpriteCalculatePositionF2
		lda SpriteScreenPtr
		pha
		lda SpriteScreenPtr+1
		pha
		jsr SpriteCalculatePosition
		lda SpriteScreenPtr
		sta $F2
		lda SpriteScreenPtr+1
		sta $F3
		pla
		sta SpriteScreenPtr+1
		pla
		sta SpriteScreenPtr
		rts
		
BubbleSpriteForceFullRenderOnUpdate
		dta 0
		
UpdateBubbleWrapper
@		jsr $246b
		bcc @+1
@		lda #0
		jsr HideBubble
		jmp $1d28
@		jsr $246b
		bcs @-1
		
		lda spriteregs+$15 ; hide bubble if it should be hidden
		bne @+
		jmp HideBubble
		
@		
		bit BubbleSpriteForceFullRenderOnUpdate
		bpl UpdateBubble
		lda #0
		sta BubbleSpriteForceFullRenderOnUpdate
		jmp RenderBubble
	
; fall to UpdateBubble
UpdateBubble
		; push zero page registers
		ldx #$00
@		lda BackBufferPtr,x
		pha
		inx
		cpx #6
		bne @-
	
		jsr SpriteBubblePrecalculatePosition
		jcc @+
		jsr SpriteSetBackbufferPtr 	
		
		; calculate pointers for second sprite (left side of text)
		jsr SpriteBubblePrepareSprite2
		; render second sprite (left side of text)
		jsr SpriteRenderFromBackbufferMasked
		
		; calculate pointers for third sprite
		jsr SpriteBubblePrepareSprite3
		; render third sprite (right side of text)
		jsr SpriteRenderFromBackbufferMasked

		; pop zeropage registers
@		
		ldx #5
		jmp SpritePopZeroPageRegisters
		
RenderBubbleDirect
		; push zero page registers
		ldx #$00
@		lda BackBufferPtr,x
		pha
		inx
		cpx #6
		bne @-

		jsr SpriteBubbleRestorePosition
		jmp RenderBubbleMain
		
RenderBubbleWrapper
		sta spriteregs+$15
		jsr $246b
		bcc @+1
@		lda #0
		jsr HideBubble
		jmp $1d28
@		jsr $246b
		bcs @-1
		; fall to RenderBubble
RenderBubble
	
		; push zero page registers
		ldx #$00
@		lda BackBufferPtr,x
		pha
		inx
		cpx #6
		bne @-
	
		jsr SpriteBubblePrecalculatePosition
		jcc @+
	
RenderBubbleMain

		lda #16
		ldx #8
		jsr PMGPrepareForSprites
		
		; calculate pointers for first sprite (left side of balloon)
		ldy SpriteY
		ldx SpriteX
		jsr SpriteCalculatePosition
		lda spriteshapesregs+2
		ldx #SpriteDataPtr
		jsr SpriteCalculateDataAddress
		lda spriteshapesregs+4
		ldx #SpriteMaskDataPtr
		jsr SpriteCalculateDataAddress
		jsr SpriteSetBackbufferPtr
		; render first sprite (left side of balloon)
		jsr SpriteRenderMaskedFirstColumn
		
		; calculate pointers for second sprite (left side of text)
		jsr SpriteBubblePrepareSprite2
		; render second sprite (left side of text)
		jsr SpriteRenderMasked
		
		; calculate pointers for third sprite
		jsr SpriteBubblePrepareSprite3
		; render third sprite (right side of text)
		jsr SpriteRenderMasked
		
		; calculate pointers for fourth sprite (right side of balloon)
		ldy SpriteY
		lda SpriteX
		clc
		adc #$07
		tax
		jsr SpriteCalculatePosition
		lda spriteshapesregs+3
		ldx #SpriteDataPtr
		jsr SpriteCalculateDataAddress
		lda spriteshapesregs+5
		ldx #SpriteMaskDataPtr
		jsr SpriteCalculateDataAddress
		ldx #BackBufferPtr
		jsr SpriteIncrementPointer
		; render fourth sprite (right side of balloon)
		jsr SpriteRenderMaskedFirstColumn
		
@		
		; pop zeropage registers
		ldx #5
		jmp SpritePopZeroPageRegisters
		
	
HideBubble
		sta spriteregs+$15
		
		lda SpriteY
		sta $28
@		lda SpriteX
		clc
		adc $58
		sta $27
@		jsr $3326	; render tile X = $27, Y = $28
		inc $27
		lda $27
		sec
		sbc $58
		cmp #40
		bcs @+
		sec
		sbc SpriteX
		cmp #9
		bcc @-
@		inc $28
		lda $28
		sec
		sbc SpriteY
		cmp #3
		bcc @-2
		
		; push zero page registers
		ldx #$00
@		lda BackBufferPtr,x
		pha
		inx
		cpx #4
		bne @-
		
		jsr PMGRestoreAfterSprites
		
.if 0		
		;jsr SpriteBubblePrecalculatePosition
		jsr SpriteBubbleRestorePosition
		
		ldy SpriteY
		ldx SpriteX
		jsr SpriteCalculatePosition
		jsr SpriteSetBackbufferPtr
		jsr SpriteRestoreFirstColumn
		
		ldy SpriteY
		ldx SpriteX
		inx
		jsr SpriteCalculatePosition
		ldx #BackBufferPtr
		jsr SpriteIncrementPointer
		jsr SpriteRestore

		ldy SpriteY
		lda SpriteX
		clc
		adc #$04
		tax
		jsr SpriteCalculatePosition
		ldx #BackBufferPtr
		jsr SpriteIncrementPointer
		jsr SpriteRestore
		
		ldy SpriteY
		lda SpriteX
		clc
		adc #$07
		tax
		jsr SpriteCalculatePosition
		ldx #BackBufferPtr
		jsr SpriteIncrementPointer
		jsr SpriteRestoreFirstColumn
.endif
		
		; pop zeropage registers
		ldx #3
		jmp SpritePopZeroPageRegisters
		
SpriteSetBackbufferPtr		
		lda #<sprite1backbuffer
		sta BackBufferPtr
		lda #>sprite1backbuffer
		sta BackBufferPtr+1
		rts
		
SpriteBubbleRestorePosition
		lda LastSpriteY
		sta SpriteY
		lda LastSpriteX
		sta SpriteX
		rts
		
SpriteBubblePrecalculatePosition
		; x
		lda $fc
		clc
		adc #$01
		sec
		sbc $58
		cmp #40-8-3
		bcc @+1
		;clc
		;adc #$3
		;and #$1f
		;sec
		;sbc #$38/8
		sbc #$7
@		bpl @+1
		cmp #40
		bcc @+
		
		lda #$0
		jsr HideBubble
		lda #0
		sta SpriteX
		sta LastSpriteX
		sta SpriteY
		sta LastSpriteY
		clc
		rts

		
@		sta SpriteX
		sta LastSpriteX

		; precalculate sprite positions
		; y
		lda $d1
		sec
		sbc #$34
		lsr @
		lsr @
		lsr @
		sta SpriteY
		sta LastSpriteY
;##TRACE "***Sprite (%d,%d) (%d,%d)" db($d1) db($fc) db(SpriteX) db(SpriteY) 		
		sec
		
		lda #$02
		sta SpriteHeight		

		rts
	
SpriteRenderMaskedFirstColumn
		ldy #$00
@		lda (SpriteScreenPtr),y
		sta (BackBufferPtr),y
		eor #$ff
		ora (SpriteMaskDataPtr),y
		eor #$ff
		ora (SpriteDataPtr),y
		sta (SpriteScreenPtr),y
		iny
		iny
		iny
		jsr SpriteRenderEpilogue
		bne @-
		rts
		
SpriteRenderMasked
		ldy #0
@		ldx #3
@		lda (SpriteScreenPtr),y
		sta (BackBufferPtr),y
		eor #$ff
		ora (SpriteMaskDataPtr),y
		eor #$ff
		ora (SpriteDataPtr),y
		sta (SpriteScreenPtr),y
		iny
		dex
		bne @-
		jsr SpriteRenderEpilogue
		bne @-1
		rts
		
SpriteRenderFromBackbufferMasked
		ldy #0
@		ldx #3
@		lda (BackBufferPtr),y
		eor #$ff
		ora (SpriteMaskDataPtr),y
		eor #$ff
		ora (SpriteDataPtr),y
		sta (SpriteScreenPtr),y
		iny
		dex
		bne @-
		jsr SpriteRenderEpilogue
		bne @-1
		rts

SpriteRenderEpilogue
		clc
		lda SpriteScreenPtr
		adc #40-3
		sta SpriteScreenPtr
		scc:inc SpriteScreenPtr+1
		cpy #63
		rts
		
SpriteCalculateDataAddress
		; A*$40
		pha
		lda #$00
		sta $0,x
		pla
		lsr @
		ror $0,x
		lsr @
		ror $0,x
		sta $1,x
		clc
		lda #<spritesbase
		adc $0,x
		sta $0,x
		lda #>spritesbase
		adc $1,x
		sta $1,x
		rts
		
SpriteIncrementPointer
		clc
		lda #$40
		adc $0,x
		sta $0,x
		scc:inc $1,x
		rts
		
SpriteBubblePrepareSprite2
		ldy SpriteY
		ldx SpriteX
		inx
		jsr SpriteCalculatePosition
		lda #<(spritesbase+$29*$40)
		sta SpriteDataPtr
		lda #>(spritesbase+$29*$40)
		sta SpriteDataPtr+1
		lda #<(spritesbase+$28*$40)
		sta SpriteMaskDataPtr
		lda #>(spritesbase+$28*$40)
		sta SpriteMaskDataPtr+1
		ldx #BackBufferPtr
		jmp SpriteIncrementPointer

SpriteBubblePrepareSprite3
		ldy SpriteY
		lda SpriteX
		clc
		adc #$04
		tax
		jsr SpriteCalculatePosition
		ldx #SpriteDataPtr
		jsr SpriteIncrementPointer
		; mask is the same
		ldx #BackBufferPtr
		jmp SpriteIncrementPointer

;*************************************************
;****************** PMG Engine *******************
;*************************************************
		
PMGDataPtr	equ 0

PreparePMGClearPMG
		lda #0
		ldy #$C8-$20
@		sta PMGMemory+$300+$20-1,y
		sta PMGMemory+$400+$20-1,y
		sta PMGMemory+$500+$20-1,y
		sta PMGMemory+$600+$20-1,y
		sta PMGMemory+$700+$20-1,y
		dey
		bne @-
		rts
		
PreparePMG
		sta PMGDataPtr
		stx PMGDataPtr+1
		cpx #$00
		beq PreparePMGClearPMG
		ldy #$00
LoadPMGDataLoop		
		lda (PMGDataPtr),y
		bmi PreparePMGControlCode
		tax ; count
		sta SavePMGUpdateDestPtr+1
		iny
		lda (PMGDataPtr),y ; value
		iny
		
		; do not store zeros, as they are always cleaned by removing PMG
		cmp #$00
		beq SavePMGUpdateDestPtr
		
SavePMGDataLoop		
		sta $ff00,x
		dex
		bne SavePMGDataLoop
		; update dest pointer
SavePMGUpdateDestPtr		
		lda #$00
		clc
		adc SavePMGDataLoop+1
		sta SavePMGDataLoop+1
		jmp LoadPMGDataLoop
PreparePMGControlCode
		cmp #PMGEnd
		beq PreparePMGEnd
		and #$0f
		ora #>PMGMemory
		sta SavePMGDataLoop+2
		lda #$20-1
		sta SavePMGDataLoop+1
		iny
		bne LoadPMGDataLoop
PreparePMGEnd
		rts
		
PMGVBlank
		ldx #13-1
GTIAAddres1
		lda $ffff,x
		sta hposp0,x
		dex
		bpl GTIAAddres1
		ldx #10-1
GTIAAddres2		
		lda $ffff,x
		sta colpm0,x
		dex
		bpl GTIAAddres2
VBlankSetNMILow		
		lda #$ff
		sta $fffa
VBlankSetNMIHigh		
		lda #$ff
		sta $fffb
		rts
		
PrepareVBlankRoutine
		sta GTIAAddres1+1
		stx GTIAAddres1+2
		clc
		adc #13
		sta GTIAAddres2+1
		scc:inx
		stx GTIAAddres2+2
		rts
		
		; dlist
		; 1 line ($0f) with mem address load ($e010)
		; 101 lines ($0f)
		; 1 line ($0f) with mem address load ($f000)
		; 97-8 lines ($0f)
		; screen data until $ff50-$0140
ClearRasterInterrupts
		lda #$4f
		sta DListLoadMemory1
		sta DListLoadMemory2
		ldx #97-1-8
		lda #$0f
ClearRasterInterruptsLoop		
		sta DListBlock1,x
		sta DListBlock2,x
		dex
		bpl ClearRasterInterruptsLoop
		ldx #101-97-1+8
ClearRasterInterruptsLoop2		
		sta DListBlock1+97-8,x
		dex
		bpl ClearRasterInterruptsLoop2
		rts
		
RasterInterruptsDataPtr equ 0
		
SetRasterInterrupts
		sta RasterInterruptsDataPtr
		stx RasterInterruptsDataPtr+1
		jsr ClearRasterInterrupts
		ldy #0
SetRasterInterruptsLoop		
		lda (RasterInterruptsDataPtr),y
		iny
		cmp #$ff
		beq SetRasterInterruptsEnd
		sec
		sbc #$18 ; compensate for empty lines on top
		;cmp #$00
		bne SetRasterInterruptsBlock1
		lda #$CF
		sta DListLoadMemory1
		bne SetRasterInterruptsLoop
SetRasterInterruptsBlock1
		cmp #102
		bcs SetRasterInterruptsBlock2
		beq SetRasterInterruptsLoadMemory2
		tax
		dex
		lda #$8f
		sta DListBlock1,x
		bne SetRasterInterruptsLoop
SetRasterInterruptsLoadMemory2
		lda #$CF
		sta DListLoadMemory2
		bne SetRasterInterruptsLoop
SetRasterInterruptsBlock2
		sec
		sbc #103
		tax
		lda #$8f
		sta DListBlock2,x
		bne SetRasterInterruptsLoop
SetRasterInterruptsEnd
		rts

DLIDataPtr 	equ 0

PrepareDLISetPointer
		sta VBlankSetNMILow+1
		stx VBlankSetNMIHigh+1
		rts
		
PrepareDLI
		sta DLIDataPtr
		stx DLIDataPtr+1
		ldy #00
		lda (DLIDataPtr),y
		cmp #$48 ; pha
		bne @+
		lda DLIDataPtr
		jmp PrepareDLISetPointer
@		lda #<DLICode
		ldx #>DLICode
		jsr PrepareDLISetPointer
		ldx #00
PrepareDLIMainLoop		
		lda #$48 ; pha
		sta DLICode,x
		inx
PrepareDLILoop		
		lda (DLIDataPtr),y
		bmi PrepareDLIControlCode
		; standard store instruction: GTIA register address, register value
		iny
		sta DLICode+3,x
		lda #$D0 ; GTIA page
		sta DLICode+4,x
		lda (DLIDataPtr),y
		iny		
		jsr PrepareDLIGenerateLDAImmSTAAbs
		jmp PrepareDLILoop
PrepareDLIControlCode
		iny
		cmp #$fe ; end of current DLI
		bne PrepareDLIVSYNC
; End of current DLI - set NMI vector low byte + pla/rti
		txa
		clc
		adc #$07
		jsr PrepareDLIGenerateSetNMIVectorLowByte
		jsr PrepareDLIGeneratePLARTI
		jmp PrepareDLIMainLoop
PrepareDLIVSYNC		
		cmp #$fd
		bne PrepareDLIEndOfLastDLI
; VSYNC
		lda #$8d ; sta
		sta DLICode+0,x
		lda #$0a ; <$d40a
		sta DLICode+1,x
		lda #$d4 ; >$d40a
		sta DLICode+2,x
		inx
		inx
		inx
		bne PrepareDLILoop
PrepareDLIEndOfLastDLI
; End of all DLI = set NMI vector + pla/rti
		lda #<Screen1DLI190
		jsr PrepareDLIGenerateSetNMIVectorLowByte
		lda #$FB
		sta DLICode+3,x
		lda #$FF
		sta DLICode+4,x
		lda #>Screen1DLI190
		jsr PrepareDLIGenerateLDAImmSTAAbs
		; fall through
PrepareDLIGeneratePLARTI		
		lda #$68 ; pla
		sta DLICode,x
		inx
		lda #$40 ; rti
		sta DLICode,x
		inx
		rts

PrepareDLIGenerateSetNMIVectorLowByte
		pha
		lda #$FA
		sta DLICode+3,x
		lda #$FF
		sta DLICode+4,x
		pla
		; fall through
PrepareDLIGenerateLDAImmSTAAbs
		sta DLICode+1,x
		lda #$A9
		sta DLICode+0,x
		lda #$8D
		sta DLICode+2,x
		txa
		clc
		adc #$05
		tax
		rts
		
PrepareScreenIndex
		dta 00
				
PrepareScreen
		lda $00
		pha
		lda $01
		pha
		lda #0
		ldx #7
@		sta hposp0,x
		dex
		bpl @-
		lda #$EC
PrepareScreenSetColor2 equ *-1		
		sta color2
		
		lda C64IRQEnabled ; save C64IRQEnabled flag
		pha
		
		lda PMGChangeRequested
		and #$78
		ldx #$00
		stx C64IRQEnabled
		stx PMGChangeRequested
		stx VblankPMGEnabled
		stx nmien
		; handle empty screen
		;lda $58
		;and #$F8
		cmp #64
		scc:lda #ScreenDataEmptyScreen-PrepareScreenData
		sta PrepareScreenIndex
		tay
		ldx PrepareScreenData+1,y
		lda PrepareScreenData,y
		jsr PreparePMG
		ldy PrepareScreenIndex
		ldx PrepareScreenData+3,y
		lda PrepareScreenData+2,y
		jsr PrepareVBlankRoutine
		ldy PrepareScreenIndex
		ldx PrepareScreenData+5,y
		lda PrepareScreenData+4,y
		jsr SetRasterInterrupts
		; set DLIs
		ldy PrepareScreenIndex
		ldx PrepareScreenData+7,y
		lda PrepareScreenData+6,y
		jsr PrepareDLI
		;sta VBlankSetNMILow+1
		;stx VBlankSetNMIHigh+1
		
		; sync
;@		bit nmist
;		bvc @-
; call DLI on line 190
		lda #>PrepareScreenAfterDLI
		pha
		lda #<PrepareScreenAfterDLI
		pha
		php
@		lda vcount
		cmp #(190+8)/2
		bne @-
		sta wsync
		jmp Screen1DLI190
		
PrepareScreenAfterDLI		
@		lda vcount
		bne @-
		;lda #$ff
		pla ; restore C64IRQEnabled
		sta C64IRQEnabled
		lda #$ff
		sta VblankPMGEnabled
		lda #$c0
		sta nmien
		
		;lda #00
		;sta PMGChangeRequested
		;lda #$ff
		;sta VblankPMGEnabled
		pla
		sta $01
		pla
		lda $00
		rts
		
NTSCFixColor
		pha
		and #$f0
		cmp #$e0
		beq NTSCFixColorApply
		cmp #$70
		beq NTSCFixColorApply
		cmp #$20
		beq NTSCFixColorApply
		pla
		rts
		
NTSCFixColorApply
		pla
		clc
		adc #$10
		rts
		
VBlankDataPtr equ 0

VBlankPrepareNTSC
		sta VBlankDataPtr
		sty VBlankDataPtr+1
		ldy #13
@		lda (VBlankDataPtr),y
		jsr NTSCFixColor
		sta (VBlankDataPtr),y
		iny 
		cpy #22
		bne @-
		rts
		
DLIPrepareNTSCPtr equ 0
		
DLIPrepareNTSC
		sta DLIPrepareNTSCPtr
		sty DLIPrepareNTSCPtr+1
		ldy #0
DLIPrepareNTSCLoop		
		lda (DLIPrepareNTSCPtr),y
		bmi DLIPrepareNTSCControlCode
		iny
		cmp #<colpm0
		bcc DLIPrepareNTSCNext
		cmp #<colbak+1
		bcs DLIPrepareNTSCNext
		lda (DLIPrepareNTSCPtr),y
		jsr NTSCFixColor
		sta (DLIPrepareNTSCPtr),y
DLIPrepareNTSCNext		
		iny
		jmp DLIPrepareNTSCLoop
DLIPrepareNTSCControlCode
		cmp #$ff
		bne DLIPrepareNTSCNext
		rts
		
PrepareScreenPrepareNTSC
		ldx #$00
@		lda PrepareScreenData+2,x
		ldy PrepareScreenData+3,x
		jsr VBlankPrepareNTSC
		lda PrepareScreenData+6,x
		ldy PrepareScreenData+7,x
		jsr DLIPrepareNTSC
		txa
		clc
		adc #$08
		tax
		cpx #ScreenDataEnd-PrepareScreenData
		bne @-
		rts
		
PMGRestoreAfterSprites
		ldy PrepareScreenIndex
		ldx PrepareScreenData+1,y
		lda PrepareScreenData,y
		jmp PreparePMG
		
SpriteYInScanlines
		dta 0
		
PMGPrepareForSprites
;##TRACE "PMGPrepareForSprites SpriteX = %d, SpriteY = %d" db(SpriteX)*8 db(SpriteY)*8
		stx PMGPrepareForSpritesWidth
		;stx PMGPrepareForSpritesWidth2
		
		sta PMGSpriteHeight
		clc
		adc #$18
		sta PMGSpriteHeightPlusScanlines
		
		lda SpriteY
		asl @
		asl @
		asl @
		sta SpriteYInScanlines
		ldx PrepareScreenIndex
		
		; prepare initial GTIA values (by copying VBlank table)
		lda PrepareScreenData+3,x
		sta PMGDataPtr+1
		lda PrepareScreenData+2,x
		sta PMGDataPtr
		ldy #$c
@		lda (PMGDataPtr),y
		sta gtiatempregs,y
		dey
		bpl @-
		lda #$00
		sta PMGScanline
		sta PMGScanlinePrevious
		sta DLIDataPtrIndex
		
		; prepare raster table scanning
		lda PrepareScreenData+5,x
		sta PMGPrepareForSpritesRaster+2
		lda PrepareScreenData+4,x
		sta PMGPrepareForSpritesRaster+1

		; prepare for DLI scanning
		lda PrepareScreenData+7,x
		sta DLIDataPtr+1
		lda PrepareScreenData+6,x
		sta DLIDataPtr
		
		; main loop
PMGPrepareForSpritesLoop	
		lda PMGScanline
		sta PMGScanlinePrevious
		; get scanline number
PMGPrepareForSpritesRaster
		lda $ffff
		sta PMGScanline
		; adjust scanline read pointer
		inc PMGPrepareForSpritesRaster+1
		sne:inc PMGPrepareForSpritesRaster+2
		; check for end
		;cmp #$ff
		;jeq PMGPrepareForSprites
		; check if within bubble
		; convert to screen
		sec
		sbc #$18
		sec
		sbc SpriteYInScanlines
		jmi PMGPrepareForSpritesScanDLI ; current raster line above sprite, continue searching
		;cmp #21 ; sprite height
		;bcs PMGPrepareForSpritesEnd ; current raster line below sprite, finish searching
; we are inside sprite now

;##TRACE "Scanning until scanline %d" db(PMGScanline)
; check hpos registers to check which players collide with sprite
		ldy #$00
PMGPrepareForSpritesPMGLoop	
		;ldx #$ff
		lda gtiatempregs,y
;##TRACE "X position of PMG %d is %d" y db(gtiatempregs+y)
		sec
		sbc #48 ; convert to pixel position
		;cmp #$80 ; divide by 4 keeping sign
		rol @
		eor #$01
		ror @ ; invert carry
		ror @ ; divide by 4 keeping the sign
		ror @
		;lsr @
		;lsr @   ; convert to tiles position
		sec
		sbc SpriteX
		sta PMGTemp
;##TRACE "Difference between PMG and SpriteX is %d" db(PMGTemp)
		;bmi PMGPrepareForSpritesPMGLoopNext
		bpl PMGPrepareForSpritesPMGOnTheRight
		; difference is negative, so PMG is on the left side of Sprite
		eor #$ff ; check how much on the left we are
		sec
		adc #$00
		sta PMGTemp
;##TRACE "Difference is negative, negated difference is %d" db(PMGTemp)
		cmp PMGWidths,y ; if more than PMG width, then skip this sprite
		jcs PMGPrepareForSpritesPMGLoopNext
		; we are within sprite width
		; reverse subtract
		eor #$ff
		sec
		adc PMGWidths,y
		tax
		lda PMGMasksPMGOnTheLeftSideOfTheSprite,x
		cpy #$04 ; check if we are clearing missile
		bcc PMGPrepareForSpritesCalculateMask
		jsr PMGShiftMaskForMissile
		jmp PMGPrepareForSpritesCalculateMask
PMGPrepareForSpritesPMGOnTheRight
		cmp #9 ; check if we are not too far on the right
PMGPrepareForSpritesWidth equ *-1		
		jcs PMGPrepareForSpritesPMGLoopNext
		cmp PMGWidths,y
		bcs @+
;##TRACE "Clearing PMG on the right"
		; reverse subtract
		;eor #$ff
		;sec
		;adc PMGWidths,y
		tax
		lda PMGMasksPMGOnTheLeftSideOfTheSprite-1,x
		eor #$ff
		cpy #$04
		bcc PMGPrepareForSpritesCalculateMask
		jsr PMGShiftMaskForMissile
		jmp PMGPrepareForSpritesCalculateMask
@		cpy #$04 ; check for missile
		bcc @+
		tax
		lda PMGMasksPMGMissile,x
		jsr PMGShiftMaskForMissile
		jmp PMGByteSetMask
		
@		
;		eor #$ff ; reverse subtract (11 - A)
;		sec
;		adc #9
;PMGPrepareForSpritesWidth2 equ *-1		
;		tax
;		lda PMGMasksPMGOnTheLeftSideOfTheSprite,x
		tax
		lda PMGMasksPMGOnTheLeftSideOfTheSprite-1,x
		eor #$ff
		sta PMGTemp
;##TRACE "Clearing PMG on the right side with mask = %02X" db(PMGTemp)
		eor #$ff
		cpy #$04
		bcc PMGPrepareForSpritesCalculateMask
		jsr PMGShiftMaskForMissile
PMGPrepareForSpritesCalculateMask		
PMGByteSetMask	
		sta PMGByteMask
		
; clear PMG starting from max(PMGScanlinePrevious,SpriteTop) to min (PMGScanline,SpriteBottom)
		lda SpriteYInScanlines
		clc
		adc #$18 ; convert to scanline
		tax
		lda PMGScanlinePrevious
		jsr GetMax
		sta PMGClearLoop-1
		lda SpriteYInScanlines
		clc
		adc #21+$18 ; sprite height + convert to scanline
PMGSpriteHeightPlusScanlines equ *-1		
		tax
		lda PMGScanline
		jsr GetMin
		cmp PMGClearLoop-1 ; if we calculate to clear 0 lines wide area, then skip clearing
		bcc PMGPrepareForSpritesPMGLoopNext
		beq PMGPrepareForSpritesPMGLoopNext
		sta PMGClearEnd
;##TRACE "======> Clearing. PMG = %d, Start = %d, End = %d, Mask = %02X" y db(PMGClearLoop-1) db(PMGClearEnd) db(PMGByteMask)
		lda #$3	; determine PMG address
		cpy #4
		bcs @+
		tya
		adc #4
@		ora #>PMGMemory
		sta PMGClearLoop+2
		sta PMGClearLoopSave+2
		lda #$00
		ldx #$00
PMGClearLoop
		lda $ff00+$20-$18,x
		and #$00
PMGByteMask equ *-1
PMGClearLoopSave		
		sta $ff00+$20-$18,x
		inx
		cpx #$ff
PMGClearEnd equ *-1		
		bne PMGClearLoop

; next iteration of the PMG registers scan loop
PMGPrepareForSpritesPMGLoopNext
		iny
		cpy #8
		jne PMGPrepareForSpritesPMGLoop
		
; check for end by comparing if scanline is greater than sprite height
		lda PMGScanline
		sec
		sbc #$18
		sec
		sbc SpriteYInScanlines
		cmp #21 ; sprite height
PMGSpriteHeight equ *-1
		bcs PMGPrepareForSpritesEnd ; current raster line below sprite, finish searching
		
; scan raster program and fill gtia regs
PMGPrepareForSpritesScanDLI
		ldy #0
DLIDataPtrIndex equ *-1

PMGPrepareForSpritesDLILoop
		lda (DLIDataPtr),y
		iny
		cmp #$FF
		beq PMGPrepareForSpritesDLIEnd ; end of raster program
		cmp #$FE
		beq PMGPrepareForSpritesDLIEnd ; end of raster program
		cmp #$FD
		beq PMGPrepareForSpritesDLILoop ; WSYNC, skip
		cmp #$0C
		bcs PMGPrepareForSpritesDLINext ; not hpos register, skip
		tax
		lda (DLIDataPtr),y
		sta gtiatempregs,x
PMGPrepareForSpritesDLINext		
		iny
		jmp PMGPrepareForSpritesDLILoop
PMGPrepareForSpritesDLIEnd	
		sty DLIDataPtrIndex
				
		jmp PMGPrepareForSpritesLoop
		
PMGPrepareForSpritesEnd		
		rts
		
MinMaxTempReg
		dta 0
GetMin	; return min of A,X
		stx MinMaxTempReg
		cmp MinMaxTempReg
		bcc @+
		txa
@		rts

GetMax	; return max of A,X
		stx MinMaxTempReg
		cmp MinMaxTempReg
		bcs @+
		txa
@		rts

PMGShiftMaskForMissile
		and #%00000011 ; handle mask on missile
		ora #%11111100
		pha
		tya
		sec
		sbc #4
		tax
		pla
		cpx #0
		beq @+1
@		sec
		rol @
		sec
		rol @
		dex
		bne @-
@		rts
		
PMGWidths
		dta 8,8,8,8,2,2,2,2
		
		dta %11111111
PMGMasksPMGOnTheLeftSideOfTheSprite
		dta %11111111,%11111110,%11111100,%11111000,%11110000,%11100000,%11000000,%10000000,%00000000
PMGMasksPMGMissile
		dta %00,%00,%00,%00,%00,%00,%00,%00,%01,%11 ; depends on sprite width?
PMGTemp	dta 0

IsTileCoveredBySprite
		pha
		lda spriteregs+$15
		beq ReturnNotCovered
		txa
		sec
		sbc SpriteX
		cmp #9
		bcs ReturnNotCovered
		tya
		sec
		sbc SpriteY
		;cmp #3
		cmp SpriteHeight
		bcs ReturnNotCovered
		pla
		sec
		rts
ReturnNotCovered
		pla
		clc
		rts
		
ResetPokey		
		; init POKEY
		ldx #$08
		lda #$00
		sta skctl
		sta $d20e
@		sta $d200,x
		dex
		bpl @-
		lda #$03
		sta skctl
		
		lda #%11010000 ; 17bit noise, 1/2 channels connected, channel 1 uses 1,79MHz
		sta audctl
		
		rts

WaitVBLANK		
@		lda TimerVBLANK
@		cmp TimerVBLANK
		beq @-
		dex
		bne @-1
		rts
		
		ert * > $CBFF
		
		org $d800,$3000
;*************************************************
;****************** PMG data *********************
;*************************************************

PMGMissile	= 3 | $80
PMGPlayer0	= 4 | $80
PMGPlayer1	= 5 | $80
PMGPlayer2	= 6 | $80
PMGPlayer3	= 7 | $80
PMGEnd		= 8 | $80

PrepareScreenData
		dta a(PMGScreen1),a(VBlankScreen1),a(RasterScreen1),a(DLIScreen1Data)		
		dta a(PMGScreen2),a(VBlankScreen2),a(RasterScreen2),a(DLIScreen2Data)
		dta a(PMGScreen3),a(VBlankScreen3),a(RasterScreen3),a(DLIScreen3Data)
		dta a(PMGScreen4),a(VBlankScreen4),a(RasterScreen4),a(DLIScreen4Data)
		dta a(PMGScreen5),a(VBlankScreen5),a(RasterScreen5),a(DLIScreen5Data)
		dta a(PMGScreen6),a(VBlankScreen6),a(RasterScreen6),a(DLIScreen6Data)
		dta a(PMGScreen7),a(VBlankScreen7),a(RasterScreen7),a(DLIScreen7Data)
		dta a(PMGScreen8),a(VBlankScreen8),a(RasterScreen8),a(DLIScreen8Data)
		; data for next screens
ScreenDataEmptyScreen		
		dta a(0),a(VBlankEmptyScreen),a(RasterScreenEmpty),a(Screen1DLI190)
ScreenDataEnd

; data for screen start at byte $20 and end at byte $c7 (inclusive)
PMGscreen1
		dta PMGMissile
		dta 16, $00
		dta 8, $24
		dta 16, $03
		dta 32, $00
		dta 8, $DF
		dta 8, $DB
		dta 24, $00
		dta 16, $C0
		dta 40, $00
		dta PMGPlayer0
		dta 1, $00
		dta 2, $80
		dta 3, $C0
		dta 2, $E0
		dta 3, $F0
		dta 3, $F8
		dta 2, $FC
		dta 8, $FE
		dta 17, $F8
		dta 3, $FC
		dta 12, $F8
		dta 4, $00
		dta 4, $20
		dta 1, $30
		dta 7, $10
		dta 1, $98
		dta 7, $88
		dta 1, $8C
		dta 7, $84
		dta 1, $06
		dta 7, $02
		dta 1, $03
		dta 9, $01
		dta 6, $00
		dta 8, $20
		dta 1, $30
		dta 7, $10
		dta 1, $18
		dta 7, $08
		dta 1, $0C
		dta 7, $04
		dta 1, $06
		dta 7, $02
		dta 1, $03
		dta 7, $01
		dta 8, $00
		dta PMGPlayer1
		dta 14, $00
		dta 2, $70
		dta 8, $60
		dta 18, $00
		dta 2, $70
		dta 12, $F0
		dta 2, $00
		dta 1, $80
		dta 1, $C0
		dta 1, $E0
		dta 1, $F0
		dta 1, $F8
		dta 8, $FC
		dta 1, $9C
		dta 15, $84
		dta 2, $9C
		dta 17, $FC
		dta 2, $F8
		dta 2, $F0
		dta 1, $E0
		dta 1, $00
		dta 42, $FC
		dta 2, $F8
		dta 3, $F0
		dta 3, $E0
		dta 3, $C0
		dta 2, $80
		dta 1, $00
		dta PMGPlayer2
		dta 16, $00
		dta 8, $DB
		dta 40, $00
		dta 40, $7F
		dta 8, $00
		dta 8, $88
		dta 48, $00
		dta PMGPlayer3
		dta 16, $00
		dta 8, $DB
		dta 40, $00
		dta 40, $FE
		dta 8, $00
		dta 8, $A1
		dta 8, $01
		dta 40, $00
		dta PMGEnd
		
PMGscreen2
		dta PMGMissile
		dta 15, $00
		dta 9, $02
		dta 16, $C0
		dta 24, $00
		dta 8, $02
		dta 8, $DF
		dta 8, $D7
		dta 24, $00
		dta 16, $03
		dta 40, $00
		dta PMGPlayer0
		dta 16, $00
		dta 8, $01
		dta 18, $00
		dta 14, $80
		dta 2, $00
		dta 6, $20
		dta 1, $30
		dta 7, $10
		dta 1, $98
		dta 7, $88
		dta 1, $8C
		dta 7, $84
		dta 1, $06
		dta 7, $02
		dta 1, $03
		dta 8, $01
		dta 7, $00
		dta 8, $20
		dta 1, $30
		dta 7, $10
		dta 1, $18
		dta 7, $08
		dta 1, $0C
		dta 7, $04
		dta 1, $06
		dta 7, $02
		dta 1, $03
		dta 7, $01
		dta 8, $00
		dta PMGPlayer1
		dta 16, $00
		dta 8, $DB
		dta 48, $00
		dta 16, $7F
		dta 24, $00
		dta 16, $FF
		dta 40, $00
		dta PMGPlayer2
		dta 16, $00
		dta 8, $DB
		dta 40, $00
		dta 40, $7F
		dta 8, $00
		dta 8, $44
		dta 48, $00
		dta PMGPlayer3
		dta 16, $00
		dta 8, $DB
		dta 16, $3F
		dta 24, $00
		dta 40, $FE
		dta 8, $00
		dta 8, $A1
		dta 8, $01
		dta 40, $00
		dta PMGEnd

PMGscreen3
		dta PMGMissile
		dta 16, $00
		dta 8, $3F
		dta 16, $02
		dta 24, $00
		dta 8, $20
		dta 16, $34
		dta 24, $00
		dta 16, $0D
		dta 40, $00
		dta PMGPlayer0
		dta 16, $00
		dta 8, $DB
		dta 40, $00
		dta 8, $08
		dta 8, $00
		dta 8, $80
		dta 8, $40
		dta 9, $20
		dta 7, $00
		dta 8, $11
		dta 16, $00
		dta 8, $80
		dta 8, $40
		dta 8, $20
		dta 8, $00
		dta PMGPlayer1
		dta 16, $00
		dta 8, $DB
		dta 40, $00
		dta 8, $01
		dta 16, $FF
		dta 24, $00
		dta 8, $A1
		dta 8, $01
		dta 40, $00
		dta PMGPlayer2
		dta 16, $00
		dta 8, $DF
		dta 16, $FF
		dta 24, $00
		dta 40, $FF
		dta 8, $00
		dta 16, $FF
		dta 40, $00
		dta PMGPlayer3
		dta 16, $00
		dta 8, $90
		dta 40, $00
		dta 40, $FC
		dta 8, $00
		dta 16, $FF
		dta 40, $00
		dta PMGEnd


PMGscreen4
		dta PMGMissile
		dta 16, $00
		dta 8, $FF
		dta 40, $00
		dta 8, $02
		dta 40, $00
		dta 16, $FD
		dta 40, $00
		dta PMGPlayer0
		dta 16, $00
		dta 8, $DB
		dta 40, $00
		dta 8, $84
		dta 16, $FF
		dta 24, $00
		dta 16, $FF
		dta 40, $00
		dta PMGPlayer1
		dta 16, $00
		dta 8, $DB
		dta 40, $00
		dta 8, $21
		dta 40, $00
		dta 16, $FF
		dta 40, $00
		dta PMGPlayer2
		dta 16, $00
		dta 8, $DF
		dta 16, $FF
		dta 24, $00
		dta 40, $7F
		dta 8, $00
		dta 8, $A1
		dta 8, $01
		dta 40, $00
		dta PMGPlayer3
		dta 16, $00
		dta 8, $90
		dta 24, $1F
		dta 16, $00
		dta 40, $FE
		dta 8, $00
		dta 8, $88
		dta 48, $00
		dta PMGEnd

PMGscreen5
		dta PMGMissile
		dta 16, $00
		dta 8, $FF
		dta 16, $01
		dta 24, $00
		dta 8, $0A
		dta 16, $10
		dta 24, $00
		dta 8, $05
		dta 48, $00
		dta PMGPlayer0
		dta 16, $00
		dta 8, $DF
		dta 16, $FF
		dta 32, $00
		dta 16, $FF
		dta 24, $00
		dta 16, $FF
		dta 40, $00
		dta PMGPlayer1
		dta 16, $00
		dta 8, $90
		dta 40, $00
		dta 40, $FE
		dta 8, $00
		dta 16, $13
		dta 40, $00
		dta PMGPlayer2
		dta 16, $00
		dta 8, $DB
		dta 24, $FC
		dta 16, $00
		dta 8, $84
		dta 40, $00
		dta 16, $F8
		dta 40, $00
		dta PMGPlayer3
		dta 16, $00
		dta 8, $B6
		dta 40, $00
		dta 8, $21
		dta 40, $00
		dta 16, $FF
		dta 40, $00
		dta PMGEnd
	
PMGscreen6
		dta PMGMissile
		dta 16, $00
		dta 8, $FA
		dta 16, $03
		dta 24, $00
		dta 8, $88
		dta 16, $20
		dta 24, $00
		dta 8, $05
		dta 48, $00
		dta PMGPlayer0
		dta 16, $00
		dta 8, $DF
		dta 16, $FF
		dta 32, $00
		dta 16, $FF
		dta 24, $00
		dta 16, $FF
		dta 40, $00
		dta PMGPlayer1
		dta 16, $00
		dta 8, $90
		dta 36, $00
		dta 4, $01
		dta 1, $03
		dta 7, $02
		dta 1, $06
		dta 7, $04
		dta 1, $0C
		dta 7, $08
		dta 1, $18
		dta 7, $10
		dta 1, $30
		dta 8, $20
		dta 7, $00
		dta 8, $01
		dta 1, $03
		dta 7, $02
		dta 1, $06
		dta 7, $04
		dta 1, $0C
		dta 7, $08
		dta 1, $18
		dta 7, $10
		dta 1, $30
		dta 7, $20
		dta 8, $00
		dta PMGPlayer2
		dta 16, $00
		dta 7, $DA
		dta 1, $D8
		dta 24, $FC
		dta 16, $00
		dta 8, $84
		dta 40, $00
		dta 16, $FF
		dta 40, $00
		dta PMGPlayer3
		dta 16, $00
		dta 8, $D8
		dta 40, $00
		dta 8, $84
		dta 40, $00
		dta 16, $F8
		dta 40, $00
		dta PMGEnd

PMGscreen7
		dta PMGMissile
		dta 14, $F0
		dta 2, $C0
		dta 8, $CF
		dta 16, $F0
		dta 16, $C0
		dta 8, $00
		dta 8, $02
		dta 16, $20
		dta 24, $00
		dta 8, $05
		dta 48, $00
		dta PMGPlayer0
		dta 2, $0C
		dta 2, $0E
		dta 8, $0F
		dta 1, $3F
		dta 2, $FF
		dta 1, $00
		dta 8, $DB
		dta 13, $C0
		dta 35, $00
		dta 16, $80
		dta 24, $00
		dta 16, $1F
		dta 40, $00
		dta PMGPlayer1
		dta 6, $00
		dta 2, $80
		dta 2, $C0
		dta 2, $E0
		dta 2, $F0
		dta 1, $F8
		dta 1, $00
		dta 8, $80
		dta 16, $18
		dta 20, $00
		dta 4, $01
		dta 1, $03
		dta 7, $02
		dta 1, $06
		dta 7, $04
		dta 1, $0C
		dta 7, $08
		dta 1, $18
		dta 7, $10
		dta 1, $30
		dta 8, $20
		dta 7, $00
		dta 8, $01
		dta 1, $03
		dta 7, $02
		dta 1, $06
		dta 7, $04
		dta 1, $0C
		dta 7, $08
		dta 1, $18
		dta 7, $10
		dta 1, $30
		dta 7, $20
		dta 8, $00
		dta PMGPlayer2
		dta 16, $00
		dta 8, $DA
		dta 24, $FC
		dta 16, $00
		dta 8, $84
		dta 15, $00
		dta 24, $78
		dta 33, $F8
		dta 1, $48
		dta 1, $08
		dta 22, $00
		dta PMGPlayer3
		dta 16, $00
		dta 8, $80
		dta 40, $00
		dta 8, $84
		dta 40, $00
		dta 16, $FF
		dta 40, $00
		dta PMGEnd


PMGscreen8
		dta PMGMissile
		dta 16, $00
		dta 8, $0F
		dta 16, $30
		dta 24, $00
		dta 8, $20
		dta 1, $00
		dta 15, $80
		dta 24, $00
		dta 8, $05
		dta 48, $00
		dta PMGPlayer0
		dta 2, $0C
		dta 2, $0E
		dta 7, $0F
		dta 1, $1F
		dta 1, $7F
		dta 2, $FF
		dta 1, $00
		dta 8, $DA
		dta 24, $FC
		dta 16, $00
		dta 8, $20
		dta 96, $00
		dta PMGPlayer1
		dta 6, $00
		dta 2, $80
		dta 2, $C0
		dta 2, $E0
		dta 2, $F0
		dta 1, $F8
		dta 1, $00
		dta 8, $02
		dta 16, $06
		dta 20, $00
		dta 4, $02
		dta 1, $06
		dta 7, $04
		dta 8, $08
		dta 8, $10
		dta 8, $20
		dta 9, $40
		dta 7, $00
		dta 8, $02
		dta 8, $04
		dta 8, $08
		dta 8, $10
		dta 8, $20
		dta 8, $40
		dta 8, $00
		dta PMGPlayer2
		dta 15, $0F
		dta 1, $07
		dta 40, $03
		dta 31, $00
		dta 25, $78
		dta 32, $F8
		dta 1, $48
		dta 1, $08
		dta 22, $00
		dta PMGPlayer3
		dta 56, $FF
		dta 56, $00
		dta 16, $F8
		dta 40, $00
		dta PMGEnd
		
	
VBlankEmptyScreen
		dta $00; HPOSP0
		dta $00; HPOSP1
		dta $00; HPOSP2
		dta $00; HPOSP3
		dta $00; HPOSM0
		dta $00; HPOSM1
		dta $00; HPOSM2
		dta $00; HPOSM3
		dta $03; SIZEP0
		dta $03; SIZEP1
		dta $03; SIZEP2
		dta $03; SIZEP3
		dta $30; SIZEM
		; GRAFP0
		; GRAFP1
		; GRAFP2
		; GRAFP3
		; GRAFM
		dta $00; COLPM0
		dta $00; COLPM1
		dta $00; COLPM2
		dta $00; COLPM3
		dta $00; COLPF0
		dta $00; COLPF1
		dta $EC; COLPF2
		dta $8C; COLPF3
		dta $72; COLBAK
		dta $31; GTIACTL
	
VBlankScreen1
; registers sequence
; HPOSP0
; HPOSP1
; HPOSP2
; HPOSP3
; HPOSM0
; HPOSM1
; HPOSM2
; HPOSM3
; SIZEP0
; SIZEP1
; SIZEP2
; SIZEP3
; SIZEM
; GRAFP0
; GRAFP1
; GRAFP2
; GRAFP3
; GRAFM
; COLPM0
; COLPM1
; COLPM2
; COLPM3
; COLPF0
; COLPF1
; COLPF2
; COLPF3
; COLBAK
; GTIACTL

		dta $30; HPOSP0
		dta $44; HPOSP1
		dta $84; HPOSP2
		dta $a8; HPOSP3
		dta $6C; HPOSM0
		dta $C8; HPOSM1
		dta $50; HPOSM2
		dta $84; HPOSM3
		dta $03; SIZEP0
		dta $03; SIZEP1
		dta $03; SIZEP2
		dta $03; SIZEP3
		dta $30; SIZEM
		; GRAFP0
		; GRAFP1
		; GRAFP2
		; GRAFP3
		; GRAFM
		dta $8A; COLPM0
		dta $7E; COLPM1
		dta $8C; COLPM2
		dta $8C; COLPM3
		dta $00; COLPF0
		dta $00; COLPF1
		dta $EC; COLPF2
		dta $8C; COLPF3
		dta $72; COLBAK
		dta $31; GTIACTL

		
RasterScreen1
		dta 40,48,80,82-1,86,91,92,128,133
RasterScreenEmpty		
		dta 190+1,$FF
		
DLIScreen1Data
		dta <sizem,$3C,$FE ; line 40
		dta <sizem,$03,$FE ; line 48
		dta <hposp0,$5C,<colpm0,$0a,$FE ; line 80
		dta $FD,<hposp1,$30,<colpm1,$DE,$FE ; line 82
		dta <hposp2,$90,<colpm2,$0E,<hposp3,$B0,<colpm3,$0E,$FE ; line 86+87
		dta <hposm0,$34,$FE ; line 91
		dta <sizem,$FF,<hposm1,$3C,<hposm2,$7C,<hposm0,$4C,<hposm1,$54,$FE ; line 92-95
		dta <color3,$DC,$FE ; line 128
		dta <hposp3,$A0,<colpm3,$DC,<hposp2,$98,<colpm2,$3A,<colpm1,$1A,<hposm3,$C8,$FF
		
Screen1DLI190
		pha
		lda #$70
		sta hposp1
		lda #$0E
		sta colpm1
		lda #$40
		sta hposp0
		lda #$A0
		sta hposp2
		lda #$4E
		sta colpm0
		lda #$AE
		sta colpm2
		lda #$26
		sta color2
		DLI_VECTOR nmi Screen1DLI190		
		pla
		rti
		
RasterScreen2
		dta 47,48,56,80,86,93,95,128,135,191,$ff
		
DLIScreen2Data
		dta <sizem,$C3,$FE ; line 47
		dta <hposp3,$B0,<colpm3,$0E,$FE ; line 48
		dta <hposp0,$30,<colpm0,$7E,$FE ; line 56
		dta <hposp0,$3C,<colpm0,$0A,$FE ; line 80
		dta <hposp2,$70,<colpm2,$0E,<hposp3,$90,<hposm0,$C4,$FE ; line 86+87+88
		dta <hposm3,$64,$FE ; line 93
		dta <sizem,$FF,<colpm1,$0E,<hposp1,$B0,<hposm0,$30,$FE ; line 95+96
		dta <color3,$DC,$FE ; line 128
		dta <hposp3,$80,<colpm1,$DC,<colpm3,$DC,<hposp2,$74,<hposm0,$A8,<colpm2,$3A,$FF ; line 135+136
				
VBlankScreen2
		dta $B0; HPOSP0
		dta $64; HPOSP1
		dta $88; HPOSP2
		dta $AC; HPOSP3
		dta $30; HPOSM0
		dta $38; HPOSM1
		dta $5C; HPOSM2
		dta $4C; HPOSM3
		dta $03; SIZEP0
		dta $03; SIZEP1
		dta $03; SIZEP2
		dta $03; SIZEP3
		dta $03; SIZEM
		; GRAFP0
		; GRAFP1
		; GRAFP2
		; GRAFP3
		; GRAFM
		dta $AE; COLPM0
		dta $8C; COLPM1
		dta $8C; COLPM2
		dta $8C; COLPM3
		dta $00; COLPF0
		dta $00; COLPF1
		dta $EC; COLPF2
		dta $AE; COLPF3
		dta $72; COLBAK
		dta $31; GTIACTL

VBlankScreen3
		dta $44; HPOSP0
		dta $68; HPOSP1
		dta $98; HPOSP2
		dta $AC; HPOSP3
		dta $8C; HPOSM0
		dta $BC; HPOSM1
		dta $C8; HPOSM2
		dta $00; HPOSM3
		dta $03; SIZEP0
		dta $03; SIZEP1
		dta $03; SIZEP2
		dta $03; SIZEP3
		dta $3F; SIZEM
		; GRAFP0
		; GRAFP1
		; GRAFP2
		; GRAFP3
		; GRAFM
		dta $8C; COLPM0
		dta $8C; COLPM1
		dta $8C; COLPM2
		dta $2A; COLPM3
		dta $00; COLPF0
		dta $00; COLPF1
		dta $EC; COLPF2
		dta $8C; COLPF3
		dta $72; COLBAK
		dta $31; GTIACTL
		
RasterScreen3
		dta 48-1,85,94,96-1,104,112,131,160-1,190+1,$ff
		
DLIScreen3Data
		dta $FD,<hposm0,$30,<colpm0,$6A,<colpm2,$0E,$FE ; line 48
		dta <hposp3,$74,<colpm3,$0E,<hposp0,$A8,<hposp2,$54,<hposp1,$B0,<colpm1,$7A,<hposm2,$A4,$FE ; line 85
		dta <hposm1,$3C,$FE ; line 94
		dta $FD,<hposp1,$94,<hposm2,$44,<colpm1,$0E,$FE
		dta <hposp0,$30,<colpm0,$0A,$FE ; line 96
		dta <color3,$DC,$FE
		dta <hposm0,$84,<colpm0,$3A,<hposm1,$8C,<colpm1,$DC,<hposp1,$60,<hposp3,$B0,<colpm3,$DC,<hposp2,$94,<colpm2,$DC,<hposp0, $4C,$FE
		dta <hposp0,$30,<colpm0,$0A,$FF
				
VBlankScreen4
		dta $30; HPOSP0
		dta $54; HPOSP1
		dta $78; HPOSP2
		dta $8C; HPOSP3
		dta $9C; HPOSM0
		dta $A8; HPOSM1
		dta $B8; HPOSM2
		dta $C4; HPOSM3
		dta $03; SIZEP0
		dta $03; SIZEP1
		dta $03; SIZEP2
		dta $03; SIZEP3
		dta $FF; SIZEM
		; GRAFP0
		; GRAFP1
		; GRAFP2
		; GRAFP3
		; GRAFM
		dta $8C; COLPM0
		dta $8C; COLPM1
		dta $8C; COLPM2
		dta $2A; COLPM3
		dta $00; COLPF0
		dta $00; COLPF1
		dta $EC; COLPF2
		dta $8C; COLPF3
		dta $72; COLBAK
		dta $31; GTIACTL
		
RasterScreen4
		dta 48-1,80,83,86,88-1,96-1,112,128,131,136-1,190+1,$ff
		
DLIScreen4Data
		dta $FD,<hposp3,$B0,<colpm2,$0E,<colpm3,$0C,$FE ; line 48
		dta <hposp0,$98,<hposm0,$84,<colpm0,$6A,$FE ; line 80
		dta <hposp1,$A4,<colpm1,$5A,$FE ; line 83
		dta <hposp2,$30,$FE ; line 86
		dta <hposp3,$50,<colpm3,$0E,$FE ; line 88
		dta $FD,<hposp0,$74,<colpm0,$0E,$FE ; line 96
		dta <color3,$DC,$FE ; line 112
		dta <hposp1,$94,<hposm0,$68,<colpm1,$DC,<hposm1,$70,<hposm2,$B4,$FE ; line 128
		dta <hposp2,$40,<hposm3,$BC,<colpm2,$DC,<colpm3,$3A,<colpm0,$DC,$FE ; line 131
		dta $FD,<hposp3,$38,<hposm0,$64,<hposm1,$6C,$FF ; line 136
		
VBlankScreen5
		dta $58; HPOSP0
		dta $6C; HPOSP1
		dta $34; HPOSP2
		dta $B0; HPOSP3
		dta $7C; HPOSM0
		dta $88; HPOSM1
		dta $98; HPOSM2
		dta $A4; HPOSM3
		dta $03; SIZEP0
		dta $03; SIZEP1
		dta $03; SIZEP2
		dta $03; SIZEP3
		dta $FF; SIZEM
		; GRAFP0
		; GRAFP1
		; GRAFP2
		; GRAFP3
		; GRAFM
		dta $8C; COLPM0
		dta $2A; COLPM1
		dta $8C; COLPM2
		dta $8C; COLPM3
		dta $00; COLPF0
		dta $00; COLPF1
		dta $EC; COLPF2
		dta $8C; COLPF3
		dta $72; COLBAK
		dta $31; GTIACTL
		
RasterScreen5
		dta 48-1,72,80,86,96-1,120,133,190+1,$ff
		
DLIScreen5Data
		dta $FD,<hposp2,$98,<colpm2,$0C,<colpm0,$0E,<hposm0,$DC,$FE ; line 48
		dta <colpm2,$6A,$FE ; line 72
		dta <hposm0,$64,<hposm1,$B4,$FE ; line 80
		dta <hposp2,$78,<hposp3,$84,<colpm3,$5A,<hposp1,$30,<colpm1,$0E,$FE ; line 86-88
		dta $FD,<hposp0,$54,<hposm2,$C8,$FE ; line 96
		dta <color3,$6A,$FE ; line 120
		dta <hposm0,$B0,<colpm0,$DC,<hposp0,$64,<hposm1,$B8,<hposp2,$50,<colpm3,$DC,<colpm1,$DC,<colpm2,$DC,$FF
		

VBlankScreen6
		dta $38; HPOSP0
		dta $4C; HPOSP1
		dta $78; HPOSP2
		dta $98; HPOSP3
		dta $30; HPOSM0
		dta $C8; HPOSM1
		dta $5C; HPOSM2
		dta $68; HPOSM3
		dta $03; SIZEP0
		dta $03; SIZEP1
		dta $03; SIZEP2
		dta $03; SIZEP3
		dta $FF; SIZEM
		; GRAFP0
		; GRAFP1
		; GRAFP2
		; GRAFP3
		; GRAFM
		dta $8C; COLPM0
		dta $2A; COLPM1
		dta $8C; COLPM2
		dta $8C; COLPM3
		dta $00; COLPF0
		dta $00; COLPF1
		dta $EC; COLPF2
		dta $8C; COLPF3
		dta $72; COLBAK
		dta $21; GTIACTL
		
RasterScreen6
		dta 48-1,72,84-1,86,94,96-1,112,128,132-1,190+1,$ff
	
DLIScreen6Data
		dta $FD,<gtictl,$31,<hposm0,$BC,<colpm0,$0E,<colpm2,$0C,$FE ; line 48
		dta <colpm2,$6A,$FE ; line 72
		dta $FD,<hposp1,$AC,<colpm1,$0A,<hposp2,$58,<hposp3,$80,<colpm3,$5A,$FE ; line 84
		dta <hposp3,$6C,<hposm3,$44,<hposm1,$94,$FE ; line 86
		dta <hposm2,$AC,$FE ; line 94
		dta $FD,<hposp0,$34,$FE ; line 96
		dta <color3,$3A,$FE ; line 112
		dta <color3,$6A,$FE ; line 128
		dta $FD,<hposp0,$30,<colpm0,$DC,$FD ; line 132
		dta <hposp2,$50,<hposm0,$90,<colpm2,$DC,$FD,<hposm1,$98,$FD,<hposp3,$70,<colpm3,$DC,$FF ; line 133
		
		
VBlankScreen7
		dta $BC; HPOSP0
		dta $C4; HPOSP1
		dta $58; HPOSP2
		dta $38; HPOSP3
		dta $78; HPOSM0
		dta $84; HPOSM1
		dta $C0; HPOSM2
		dta $C8; HPOSM3
		dta $00; SIZEP0
		dta $00; SIZEP1
		dta $03; SIZEP2
		dta $03; SIZEP3
		dta $FF; SIZEM
		; GRAFP0
		; GRAFP1
		; GRAFP2
		; GRAFP3
		; GRAFM
		dta $26; COLPM0
		dta $26; COLPM1
		dta $8C; COLPM2
		dta $2A; COLPM3
		dta $00; COLPF0
		dta $00; COLPF1
		dta $EC; COLPF2
		dta $8C; COLPF3
		dta $72; COLBAK
		dta $31; GTIACTL
		
RasterScreen7
		dta 39,47,83,85,88,94,104,111-1,128,133,190+1,$ff
	
DLIScreen7Data
		dta <sizep0,$03,<hposp0,$30,<colpm0,$8C,<sizep1,$03,<hposp1,$A8,<colpm1,$2A,$FE ; 39
		dta $FD,<hposm2,$9C,<hposp1,$B0,<colpm0,$0E,<colpm1,$1A,<colpm2,$0C,$FE ; 47
		dta <hposp1,$8C,<colpm1,$0A,$FE ; 83
		dta <hposp2,$38,<colpm2,$6A,$FD ; 85
		dta <hposp3,$4C,<colpm3,$5A,$FE ; 86
		dta <hposm0,$74,$FE ; 88
		dta <hposm2,$8C,$FE ; 94
		dta <colpm2,$E8,$FE ; 104
		dta $FD,<hposp2,$B0,$FE ; 111
		dta <color3,$6A,$FE ; 128
		dta <hposm0,$70,<colpm0,$DC,<hposp0,$24,<hposm1,$78,<hposp3,$44,<colpm3,$DC,$FF ; 133
		
VBlankScreen8
		dta $9C; HPOSP0
		dta $A4; HPOSP1
		dta $90; HPOSP2
		dta $B0; HPOSP3
		dta $58; HPOSM0
		dta $64; HPOSM1
		dta $7C; HPOSM2
		dta $6C; HPOSM3
		dta $00; SIZEP0
		dta $00; SIZEP1
		dta $03; SIZEP2
		dta $03; SIZEP3
		dta $0F; SIZEM
		; GRAFP0
		; GRAFP1
		; GRAFP2
		; GRAFP3
		; GRAFM
		dta $26; COLPM0
		dta $26; COLPM1
		dta $8C; COLPM2
		dta $8C; COLPM3
		dta $00; COLPF0
		dta $00; COLPF1
		dta $EC; COLPF2
		dta $8C; COLPF3
		dta $72; COLBAK
		dta $31; GTIACTL
		
RasterScreen8
		dta 39,47,82,87,96,111,128,133,190+1,$ff
	
DLIScreen8Data
		dta <sizep0,$03,<hposp0,$38,<colpm1,$3A,<sizep1,$03,<hposp1,$70,<colpm0,$8C,$FE ; line 39
		dta <sizem,$3F,$FD ; line 47+48
		dta <hposp1,$88,<colpm1,$1A,<colpm0,$0C,$FE
		dta <hposp1,$70,<colpm1,$0A,$FE ; line 82
		dta <hposp3,$54,<colpm0,$FA,<hposm2,$54,$FE ; line 87+88
		dta <sizem,$C0,$FE ; line 96
		dta <colpm2,$E8,$FE ; line 111
		dta <color3,$6A,$FE ; line 128
		dta <sizem,$0F,<hposm1,$58,<hposm0,$50,<colpm0,$DC,<hposp3,$30,<colpm3,$DC,$FF ; line 133
				
		ert * > $DFFF
	
	
		org $600
ldsrc	equ $fc
lddest	equ $fe

		sei
		lda #$0
		sta nmien
		lda portb
		ora #$02
		and #$fe
		sta portb
		
		lda #$20
		ldy #$c0
		ldx #$0c
		jsr ldcopy

		lda #$30
		ldy #$d8
		ldx #$08
		jsr ldcopy
		
		lda portb
		ora #$01
		sta portb
		lda #$40
		sta nmien
		cli
		rts
		
		org $06e0
ldcopy	sta ldsrc+1
		sty lddest+1
		ldy #$0
		sty ldsrc
		sty lddest
ld1		lda (ldsrc),y
		sta (lddest),y
		iny
		bne ld1
		inc ldsrc+1
		inc lddest+1
		dex
		bne ld1
		rts
		ert *>$06ff
		
		ini $600
		
		org $0800
		ins 'sd_game_0800.vsf',+$0800+vice_dump_offset,$b800

; patches

;$080D  20 00 BA  JSR L_JSR_($BA00)_($080D) OK	; Play startup music
		org $080D
		;jsr PlayMusic1
		jsr TitleScreen

;$0813  A9 01     LDA #$01
;$0815  85 2E     STA $2E 
		org $0813
		lda #$00 ; initial frame counter, game runs at 25Hz (see code at 0919 for sync)
		
;$084A  A9 80     LDA #$80
;$084C  8D 12 D4  STA $D412                          // Voice 3: Control Register
		org $084A
		lda #$80
		sta audc4
		;:5 nop
		
; sync to vblank: disabling doesn't seem to cause problems?
;$0919  A5 2E     LDA $2E 
;$091B  10 FC     BPL L_BRS_($0919)_($091B) OK
;		org $0919
;		:4 nop
		
;$0A21  AD 1B D4  LDA $D41B                          // Oscillator 3 Output
		org $0A21
		lda $d20a
		
;$0A2D  AD 1B D4  LDA $D41B                          // Oscillator 3 Output
		org $0A2D
		lda $d20a
		
;$0A68  AD 1B D4  LDA $D41B                          // Oscillator 3 Output
		org $0A68
		lda $d20a
		
;$0A9F  AD 1B D4  LDA $D41B                          // Oscillator 3 Output
		org $0A9F
		lda $d20a
		
;$0AE9  AD 1B D4  LDA $D41B                          // Oscillator 3 Output
		org $0AE9
		lda $d20a
		
;$0AF5  AD 1B D4  LDA $D41B                          // Oscillator 3 Output
		org $0AF5
		lda $d20a
		
;$0B1C  AD 1B D4  LDA $D41B                          // Oscillator 3 Output
		org $0B1C
		lda $d20a
		
;$0DDC  A9 CA     LDA #$CA	; TODO: Sprite data pointer ($CAxx)
;$0DDE  85 51     STA $51 
;$0DE0  A9 C0     LDA #$C0
;$0DE2  18        CLC 
;$0DE3  65 57     ADC $57 
;$0DE5  85 50     STA $50 
		org $0ddc
		lda #>SpriteDataRectangleBubble1
		sta $51
		lda #<SpriteDataRectangleBubble1
		
;$105B  AD 1B D4  LDA $D41B                          // Oscillator 3 Output
		org $105B
		lda $d20a
		
;$114E  AD 1B D4  LDA $D41B                          // Oscillator 3 Output
		org $114E
		lda $d20a
		
;$15D9  A9 1A     LDA #$1A
;$15DB  8D 13 D4  STA $D413                          // Voice 3: Attack / Decay Cycle Control
;$15DE  A9 81     LDA #$81
;$15E0  8D 12 D4  STA $D412                          // Voice 3: Control Register
		org $15D9
		lda #footstep
		sta audc4
		lda #FootstepLength
		sta FootstepLengthReg
		:10-5-5 nop
		
;$182F  A9 10     LDA #$10
;$1831  8D 08 D4  STA $D408                          // Voice 2: Frequency Control - High-Byte
;$1834  A9 00     LDA #$00
;$1836  8D 07 D4  STA $D407                          // Voice 2: Frequency Control - Low-Byte
;$1839  A9 34     LDA #$34
;$183B  8D 0C D4  STA $D40C                          // Voice 2: Attack / Decay Cycle Control
;$183E  A9 00     LDA #$00
;$1840  8D 0D D4  STA $D40D                          // Voice 2: Sustain / Release Cycle Control
;$1843  A9 81     LDA #$81
;$1845  8D 0B D4  STA $D40B                          // Voice 2: Control Register
		org $182F
		lda #<$0E5F
		sta audf1
		lda #>$0E5F
		sta audf2
		lda #$8f
		sta audc2		
		:25-15 nop
		
;$1923  A9 10     LDA #$10
;$1925  8D 0B D4  STA $D40B                          // Voice 2: Control Register
		org $1923
		lda #$00
		sta audc2
		;:5 nop
		
;$1957  A9 30     LDA #$30
;$1959  8D 08 D4  STA $D408                          // Voice 2: Frequency Control - High-Byte
;$195C  A9 00     LDA #$00
;$195E  8D 07 D4  STA $D407                          // Voice 2: Frequency Control - Low-Byte
;$1961  A9 1B     LDA #$1B
;$1963  8D 0C D4  STA $D40C                          // Voice 2: Attack / Decay Cycle Control
;$1966  A9 00     LDA #$00
;$1968  8D 0D D4  STA $D40D                          // Voice 2: Sustain / Release Cycle Control
;$196B  A9 11     LDA #$11
;$196D  8D 0B D4  STA $D40B                          // Voice 2: Control Register
		org $1957
		lda #<$04C5 ; catapult shoot sound
		sta audf1
		lda #>$04C5
		sta audf2
		lda #$ef
		sta audc2		
		:25-15 nop
		
;$1A37  AD 1B D4  LDA $D41B                          // Oscillator 3 Output
		org $1A37
		lda $d20a
		
;$1DB7  AD 15 D0  LDA $D015                          // Sprite display Enable
		org $1DB7
		lda spriteregs+$15
		
;$1DE9  AD 1B D4  LDA $D41B                          // Oscillator 3 Output
		org $1DE9
		lda $d20a
		
;$1E48  A9 00     LDA #$00
;$1E4A  8D 05 D4  STA $D405                          // Voice 1: Attack / Decay Cycle Control
;$1E4D  8D 00 D4  STA $D400                          // Voice 1: Frequency Control - Low-Byte
;$1E50  A9 F8     LDA #$F8
;$1E52  8D 06 D4  STA $D406                          // Voice 1: Sustain / Release Cycle Control
;$1E55  A9 31     LDA #$31
;$1E57  8D 01 D4  STA $D401                          // Voice 1: Frequency Control - High-Byte
;$1E5A  A9 21     LDA #$21
;$1E5C  8D 04 D4  STA $D404                          // Voice 1: Control Register
		org $1E48
		lda #$00
		sta audc2	; silence effects plaing on channels 1-2
		lda #$2a	; sound effect lines
		sta audf3
		lda #$ef
		sta audc3		
		:23-10-5 nop
		
;$1EAD  A9 29     LDA #$29
;$1EAF  8D 01 D4  STA $D401                          // Voice 1: Frequency Control - High-Byte
		org $1EAD
		lda #$32
		sta audf3
		
;$1EB5  A9 20     LDA #$20
;$1EB7  8D 04 D4  STA $D404                          // Voice 1: Control Register
		org $1EB5
		lda #$e0
		sta audc3
		
;$2080  8E 10 D0  STX $D010                          // Sprites 0-7 MSB of X coordinate
		org $2080
		stx spriteregs+$10
		
;$2088  8E 10 D0  STX $D010                          // Sprites 0-7 MSB of X coordinate
		org $2088
		stx spriteregs+$10
		
;$2099  8D 2B D0  STA $D02B                          // Sprite 4 Color
;$209C  8D 2C D0  STA $D02C                          // Sprite 5 Color
		org $2099
		sta spriteregs+$2b
		sta spriteregs+$2c
		
;$20A1  8D 28 D0  STA $D028                          // Sprite 1 Color
;$20A4  8D 29 D0  STA $D029                          // Sprite 2 Color
;$20A7  8D 2A D0  STA $D02A                          // Sprite 3 Color
		org $20A1
		sta spriteregs+$28
		sta spriteregs+$29
		sta spriteregs+$2a
		
;$20DD  8D 15 D0  STA $D015                          // Sprite display Enable
		org $20DD
		;sta spriteregs+$15
		jsr RenderRectangleBubble

;$20E0  20 DF 31  JSR L_JSR_($31DF)_($20E0) OK	; Delay
;$20E3  20 DF 31  JSR L_JSR_($31DF)_($20E3) OK	; Delay
;$20E6  20 DF 31  JSR L_JSR_($31DF)_($20E6) OK	; Delay
;$20E9  20 DF 31  JSR L_JSR_($31DF)_($20E9) OK	; Delay
;$20EC  20 DF 31  JSR L_JSR_($31DF)_($20EC) OK	; Delay
		org $20E0
		ldx #75
		jsr WaitVBLANK
		:$20ef-* nop
		
;$20F1  8D 15 D0  STA $D015                          // Sprite display Enable
		org $20F1
		;sta spriteregs+$15
		jsr RestoreRectangleBubble
		
		org $20f5
		jmp sub_20f5_speedup
		
;$212A  A9 45     LDA #$45
;$212C  85 4F     STA $4F 
;$212E  A9 00     LDA #$00
;$2130  85 4E     STA $4E 
;$2132  A8        TAY 
;//------------------------------
;L_BRS_($2133)_($2136) OK
;//------------------------------
;$2133  91 4E     STA ($4E),Y 
;$2135  C8        INY 
;$2136  D0 FB     BNE L_BRS_($2133)_($2136) OK
;$2138  85 A2     STA $A2 
;$213A  60        RTS 
;		org $212a ; speedup
;		lda #0
;		sta $a2
;		ldy #$80
;@		sta $4500,y
;		sta $4580,y
;		dey
;		bne @-
;		rts
;		ert *>=$213b
		
;$23A7  AD 15 D0  LDA $D015                          // Sprite display Enable
		org $23A7
		lda spriteregs+$15
		
;$23B7  A9 CA     LDA #$CA	; TODO: Sprite data pointer ($CAxx)
;$23B9  85 4F     STA $4F 
;$23BB  A9 40     LDA #$40
;$23BD  85 4E     STA $4E 
		org $23b7
		lda #>SpritePointerCA40
		sta $4F
		lda #<SpritePointerCA40
		sta $4E
		
;$23FD  8D 10 D0  STA $D010                          // Sprites 0-7 MSB of X coordinate
		org $23FD
		sta spriteregs+$10
		
;$240F  8E 10 D0  STX $D010                          // Sprites 0-7 MSB of X coordinate
		org $240F
		stx spriteregs+$10
		
;$2420  8D 1D D0  STA $D01D                          // Sprites Expand 2x Horizontal (X)
		org $2420
		sta spriteregs+$1d

;$2425  8D 27 D0  STA $D027                          // Sprite 0 Color
;$2428  8D 28 D0  STA $D028                          // Sprite 1 Color
;$242B  8D 29 D0  STA $D029                          // Sprite 2 Color
;$242E  8D 2A D0  STA $D02A                          // Sprite 3 Color
		org $2425
		sta spriteregs+$27
		sta spriteregs+$28
		sta spriteregs+$29
		sta spriteregs+$2a
		
;$2433  8D 2B D0  STA $D02B                          // Sprite 4 Color
;$2436  8D 2C D0  STA $D02C                          // Sprite 5 Color
;$2439  8D 2D D0  STA $D02D                          // Sprite 6 Color
		org $2433
		sta spriteregs+$2b
		sta spriteregs+$2c
		sta spriteregs+$2d
		
;$243E  8D 01 D0  STA $D001                          // Sprite 0 Y Pos
;$2441  8D 03 D0  STA $D003                          // Sprite 1 Y Pos
;$2444  8D 05 D0  STA $D005                          // Sprite 2 Y Pos
;$2447  8D 07 D0  STA $D007                          // Sprite 3 Y Pos
;$244A  8D 09 D0  STA $D009                          // Sprite 4 Y Pos
;$244D  8D 0B D0  STA $D00B                          // Sprite 5 Y Pos
;$2450  8D 0D D0  STA $D00D                          // Sprite 6 Y Pos
		org $243E
		sta spriteregs+$01
		sta spriteregs+$03
		sta spriteregs+$05
		sta spriteregs+$07
		sta spriteregs+$09
		sta spriteregs+$0b
		sta spriteregs+$0d
		
;$2455  8D 15 D0  STA $D015                          // Sprite display Enable
		org $2455
		;sta spriteregs+$15
		;jsr RenderBubble
		jmp RenderBubbleWrapper
		jmp UpdateBubbleWrapper
		
;$245F  8D 15 D0  STA $D015                          // Sprite display Enable
		org $245F
		;sta spriteregs+$15
		jsr HideBubble

;$24AA  A9 CA     LDA #$CA	; TODO: Sprite data pointer ($CAxx)
;$24AC  85 53     STA $53 
;$24AE  A9 8E     LDA #$8E
;$24B0  85 52     STA $52 
		org $24aa
		lda #>SpritePointerCA8E
		sta $53
		lda #<SpritePointerCA8E
		sta $52
		
;$2500  AD 1B D4  LDA $D41B                          // Oscillator 3 Output
		org $2500
		lda $d20a
		
;$250E  AD 1B D4  LDA $D41B                          // Oscillator 3 Output
		org $250E
		lda $d20a
		
;$2547  AD 1B D4  LDA $D41B                          // Oscillator 3 Output
		org $2547
		lda $d20a
		
;$2555  AD 1B D4  LDA $D41B                          // Oscillator 3 Output
		org $2555
		lda $d20a
		
;$2646  A9 FB     LDA #$FB	; TODO: screen pointer
;$2648  85 51     STA $51 
;$264A  A9 40     LDA #$40
;$264C  85 50     STA $50 
		org $2646
		atari_screen_address_equ screen_fb40,$fb40
		lda #>screen_fb40
		sta $51
		lda #<screen_fb40
		sta $50
		
;$2655  A9 FC     LDA #$FC	; TODO: screen pointer
;$2657  85 51     STA $51 
;$2659  A9 80     LDA #$80
;$265B  85 50     STA $50 
		org $2655
		atari_screen_address_equ screen_fc80,$fc80
		lda #>screen_fc80
		sta $51
		lda #<screen_fc80
		sta $50
		
;$2660  A9 FD     LDA #$FD	; TODO: Screen pointer
;$2662  85 51     STA $51 
;$2664  A9 C0     LDA #$C0
;$2666  85 50     STA $50 
		org $2660
		atari_screen_address_equ screen_fdc0,$fdc0
		lda #>screen_fdc0
		sta $51
		lda #<screen_fdc0
		sta $50
		
;$2672  B1 4E     LDA ($4E),Y 
;$2674  91 50     STA ($50),Y 
;$2676  88        DEY 
;$2677  10 F9     BPL L_BRS_($2672)_($2677) OK
;$2679  60        RTS 
		org $2672
		ldy #$03
		jmp PrintCharsRow
		:$267A-* nop
		
;$2931  AD 1B D4  LDA $D41B                          // Oscillator 3 Output
		org $2931
		lda $d20a
		
;$294C  AD 1B D4  LDA $D41B                          // Oscillator 3 Output
		org $294C
		lda $d20a
		
;$295A  AD 1B D4  LDA $D41B                          // Oscillator 3 Output
		org $295A
		lda $d20a
		
;$29B3  AD 15 D0  LDA $D015                          // Sprite display Enable
		org $29B3
		lda spriteregs+$15
		
;$2AAA  AD 1B D4  LDA $D41B                          // Oscillator 3 Output
		org $2AAA
		lda $d20a
		
;$2C51  20 48 BA  JSR L_JSR_($BA48)_($2C51) OK	; music
		org $2C51
		jsr PlayMusic2
		
;$2C9C  20 00 BA  JSR L_JSR_($BA00)_($2C9C) OK
		org $2C9C
		jsr PlayMusic1
		
;$2CB5  AD 1B D4  LDA $D41B                          // Oscillator 3 Output
		org $2CB5
		lda $d20a
		
;$2CDE  A9 39     LDA #$39
;$2CE0  8D FF FF  STA $FFFF 
;$2CE3  A9 C7     LDA #$C7
;$2CE5  8D FE FF  STA $FFFE                          // Vector: IRQ
;$2CE8  A9 3A     LDA #$3A
;$2CEA  8D FD FF  STA $FFFD 
;$2CED  8D FB FF  STA $FFFB 
;$2CF0  A9 8F     LDA #$8F
;$2CF2  8D FC FF  STA $FFFC                          // Vector: RESET
;$2CF5  8D FA FF  STA $FFFA                          // Vector: NMI
;$2CF8  58        CLI 
		org $2CDE
		lda #$ff
		sta C64IRQEnabled
		lda #$00
		tax
@		sta PMGMemory+$300,x
		sta PMGMemory+$400,x
		sta PMGMemory+$500,x
		sta PMGMemory+$600,x
		sta PMGMemory+$700,x
		inx
		bne @-
		:27-5-21 nop
		
;$2D18  A5 01     LDA $01 	; Init RAM mode: $D000 - $DFFF: I/O, other: RAM
;$2D1A  29 FD     AND #$FD
;$2D1C  85 01     STA $01 
;$2D1E  60        RTS 
		org $2D18
		lda #$ff
		sta PMGChangeRequested
		:6-5 nop
		
;$2D1F  AD 02 DD  LDA $DD02                          // Data Direction Register A
;$2D22  09 03     ORA #$03
;$2D24  8D 02 DD  STA $DD02                          // Data Direction Register A
;$2D27  AD 00 DD  LDA $DD00                          // Data Port A (Serial Bus, RS232, VIC Base Mem.)
;$2D2A  29 FC     AND #$FC
;$2D2C  09 00     ORA #$00
;$2D2E  8D 00 DD  STA $DD00                          // Data Port A (Serial Bus, RS232, VIC Base Mem.)	// VIC mem at $C000
;$2D31  AD 18 D0  LDA $D018                          // Memory Control Register
;$2D34  29 0F     AND #$0F
;$2D36  09 30     ORA #$30							// Video Matrix at $CC00
;$2D38  09 08     ORA #$08							// Bitmap at $E000
;$2D3A  8D 18 D0  STA $D018                          // Memory Control Register
;$2D3D  60        RTS 
		org $2D1F
		lda #$ff
		ldx #$18-1
@		sta PMGMemory+$400+$c8,x
		sta PMGMemory+$500+$c8,x
		sta PMGMemory+$600+$c8,x
		dex
		bpl @-
		:30-16 nop
		
;$2D3E  AD 11 D0  LDA $D011                          // Control Register 1
;$2D41  09 20     ORA #$20							// Enable bitmap mode
;$2D43  8D 11 D0  STA $D011                          // Control Register 1
		org $2D3E
		:8 nop
		
;$2D57  A9 00     LDA #$00
;$2D59  85 5A     STA $5A 
;$2D5B  A9 E0     LDA #$E0		; TODO: Screen pointer
;$2D5D  85 5B     STA $5B 
		org $2D57
		atari_screen_address_equ screen_e000,$e000
		lda #<screen_e000
		sta $5a
		lda #>screen_e000
		sta $5b
		
;$2D81  8D 15 D0  STA $D015                          // Sprite display Enable
		org $2D81
		sta spriteregs+$15
		
;$2D8E  AD 1B D4  LDA $D41B                          // Oscillator 3 Output
		org $2D8E
		lda $d20a
		
;$2DAD  A9 E0     LDA #$E0		; Clear screen ($1F37 bytes at $E000)
;$2DAF  85 4F     STA $4F 
;$2DB1  A9 00     LDA #$00		; TODO: screen pointer
;$2DB3  85 4E     STA $4E 
		;org $2DAD
		; TODO: 0 was used to set value for clearing
		;lda #>screen_e000
		;sta $4f
		;lda #<screen_e000
		;sta $4e
		
;$2DC3  A0 37     LDY #$37
		org $2DC3
		ldy #$37+$10+$10	; since we clear from $e000 and not from $e010, we need to clear $10 bytes more
		
;$2DD5  8D 20 D0  STA $D020                          // Border Color
		org $2DD5
		:3 nop
		
;$2F13  69 E0     ADC #$E0	; TODO: screen address?
;$2F15  85 5B     STA $5B 
;		org $2F13
;		jsr sub_2ee6_fixup
;		nop
;//------------------------------
;L_JSR_($2EE6)_($3326) OK
;//------------------------------
;$2EE6  A5 27     LDA $27 	; calculate screen address? ; $27 is X
;$2EE8  38        SEC 
;$2EE9  E5 58     SBC $58 
;$2EEB  85 5A     STA $5A 
;$2EED  A9 00     LDA #$00
;$2EEF  85 5D     STA $5D 
;$2EF1  A5 28     LDA $28 	; $28 is Y
;$2EF3  0A        ASL A 		; Y*2
;$2EF4  0A        ASL A 		; Y*4
;$2EF5  65 28     ADC $28 	; Y*5
;$2EF7  0A        ASL A 		; Y*10
;$2EF8  0A        ASL A 		; Y*20
;$2EF9  26 5D     ROL $5D 
;$2EFB  0A        ASL A 		; Y*40
;$2EFC  26 5D     ROL $5D 
;$2EFE  65 5A     ADC $5A 	; Y*40+X
;$2F00  85 5A     STA $5A 
;$2F02  85 5C     STA $5C 
;$2F04  90 02     BCC L_BRS_($2F08)_($2F04) OK
;$2F06  E6 5D     INC $5D 
;//------------------------------
;L_BRS_($2F08)_($2F04) OK
;//------------------------------
;$2F08  A5 5D     LDA $5D 
;$2F0A  06 5A     ASL $5A 
;$2F0C  2A        ROL A 
;$2F0D  06 5A     ASL $5A 
;$2F0F  2A        ROL A 
;$2F10  06 5A     ASL $5A 
;$2F12  2A        ROL A 
;$2F13  69 E0     ADC #$E0	; TODO: screen address?
;$2F15  85 5B     STA $5B 
;$2F17  A5 5D     LDA $5D 
;$2F19  69 CC     ADC #$CC	; TODO: color ram adress?
;$2F1B  85 5D     STA $5D 
;$2F1D  69 28     ADC #$28
;$2F1F  60        RTS 
		org $2EE6
		lda $27
		sec
		sbc $58
		sta $5c
		lda #$00
		sta $5a
		lda $28
		sta $5b
		lsr @
		ror $5a
		lsr @
		ror $5a
		;clc
		adc $5b
		sta $5b
		lda $5a
		adc $5c
		sta $5a
		scc:inc $5b
		adc #<bitmapscreen
		sta $5a
		lda $5b
		adc #>bitmapscreen
		sta $5b
		lda #$cc
		sta $5d
		rts
;		lda $27
;		sec
;		sbc $58
;		sta $00
;		lda #$00
;		sta $5b
;		sta $5d
;		lda $28
;		asl @
;		asl @
;		adc $28
;		asl @
;		asl @
;		rol $5d
;		asl @
;		rol $5d
;		sta $5a
;		adc $00
;		sta $5c
;		scc:inc $5d
;		lda $5d
;		sta $5b
;		lda $5a
;		asl @
;		rol $5b
;		asl @
;		rol $5b
;		asl @
;		rol $5b
;		adc $00
;		sta $5a
;		jmp sub_2ee6_fixup
		:$2F20-* nop
		ert * <> $2F20
		
;$2F28  A9 FA     LDA #$FA	; TODO: screen pointer
;$2F2A  85 51     STA $51 
;$2F2C  A9 60     LDA #$60
;$2F2E  85 50     STA $50 
;$2F30  A0 00     LDY #$00
;//------------------------------
;L_BRS_($2F32)_($2F39) OK
;//------------------------------
;$2F32  B1 4E     LDA ($4E),Y 
;$2F34  91 50     STA ($50),Y 
;$2F36  C8        INY 
;$2F37  C0 40     CPY #$40
;$2F39  D0 F7     BNE L_BRS_($2F32)_($2F39) OK

		org $2F28
		atari_screen_address_equ screen_fa60,$fa60
		lda #>screen_fa60
		sta $51
		lda #<screen_fa60
		sta $50
		ldy #$40/8
		jsr PrintCharsRow
		;jmp $2f3b
		;:$2f3b-* nop
;$2F3B  A9 FB     LDA #$FB
;$2F3D  85 51     STA $51 
;//------------------------------
;L_BRS_($2F3F)_($2F46) OK
;//------------------------------
;$2F3F  B1 4E     LDA ($4E),Y 
;$2F41  91 50     STA ($50),Y 
;$2F43  C8        INY 
;$2F44  C0 80     CPY #$80
;$2F46  D0 F7     BNE L_BRS_($2F3F)_($2F46) OK
		;org $2F3B
		atari_screen_address_equ screen_fba0,$fba0
		lda #>screen_fba0
		sta $51
		lda #<screen_fba0
		sta $50
		lda #$20+$40
		sta $4e
		ldy #$40/8
		jsr PrintCharsRow
		;jmp $2f48
		;:$2f48-* nop
;$2F48  A9 FC     LDA #$FC
;$2F4A  85 51     STA $51 
;//------------------------------
;L_BRS_($2F4C)_($2F53) OK
;//------------------------------
;$2F4C  B1 4E     LDA ($4E),Y 
;$2F4E  91 50     STA ($50),Y 
;$2F50  C8        INY 
;$2F51  C0 C0     CPY #$C0
;$2F53  D0 F7     BNE L_BRS_($2F4C)_($2F53) OK
;$2F55  60        RTS 
		atari_screen_address_equ screen_fce0,$fce0
		lda #>screen_fce0
		sta $51
		lda #<screen_fce0
		sta $50
		lda #$20+$40+$40
		sta $4e
		;ldy #$40/8
		;jsr PrintCharsRow
		;rts
		;jmp PrintCharsRow
		jmp sub_2F28_fixup
		:$2f56-* nop
		ert * <> $2f56
		
;$2F5E  A9 FB     LDA #$FB	; TODO: screen pointer
;$2F60  85 51     STA $51 
;$2F62  A9 20     LDA #$20
;$2F64  85 50     STA $50 
;$2F66  A0 00     LDY #$00
;//------------------------------
;L_BRS_($2F68)_($2F6F) OK
;//------------------------------
;$2F68  B1 4E     LDA ($4E),Y 
;$2F6A  91 50     STA ($50),Y 
;$2F6C  C8        INY 
;$2F6D  C0 40     CPY #$40
;$2F6F  D0 F7     BNE L_BRS_($2F68)_($2F6F) OK

		org $2F5E
		atari_screen_address_equ screen_fb20,$fb20
		lda #>screen_fb20
		sta $51
		lda #<screen_fb20
		sta $50
		ldy #$40/8
		jsr PrintCharsRow
;$2F71  A9 FC     LDA #$FC
;$2F73  85 51     STA $51 
;//------------------------------
;L_BRS_($2F75)_($2F7C) OK
;//------------------------------
;$2F75  B1 4E     LDA ($4E),Y 
;$2F77  91 50     STA ($50),Y 
;$2F79  C8        INY 
;$2F7A  C0 80     CPY #$80
;$2F7C  D0 F7     BNE L_BRS_($2F75)_($2F7C) OK
		atari_screen_address_equ screen_fc60,$fc60
		lda #>screen_fc60
		sta $51
		lda #<screen_fc60
		sta $50
		lda #$20+$40
		sta $4e
		ldy #$40/8
		jsr PrintCharsRow
;$2F7E  A9 FD     LDA #$FD
;$2F80  85 51     STA $51 
;//------------------------------
;L_BRS_($2F82)_($2F89) OK
;//------------------------------
;$2F82  B1 4E     LDA ($4E),Y 
;$2F84  91 50     STA ($50),Y 
;$2F86  C8        INY 
;$2F87  C0 C0     CPY #$C0
;$2F89  D0 F7     BNE L_BRS_($2F82)_($2F89) OK
;$2F8B  60        RTS 
		atari_screen_address_equ screen_fda0,$fda0
		lda #>screen_fda0
		sta $51
		lda #<screen_fda0
		sta $50
		lda #$20+$40+$40
		sta $4e
		;ldy #$40/8
		;jsr PrintCharsRow
		;rts
		jmp sub_2F28_fixup
		:$2F8C-* nop
		ert * <> $2F8C
		
;$2FB8  A0 00     LDY #$00		; TODO: move tile?
;$2FBA  B1 4E     LDA ($4E),Y 
;$2FBC  91 52     STA ($52),Y 
;$2FBE  C8        INY 
;$2FBF  B1 4E     LDA ($4E),Y 
;$2FC1  91 52     STA ($52),Y 
;$2FC3  C8        INY 
;$2FC4  B1 4E     LDA ($4E),Y 
;$2FC6  91 52     STA ($52),Y 
;$2FC8  C8        INY 
;$2FC9  B1 4E     LDA ($4E),Y 
;$2FCB  91 52     STA ($52),Y 
;$2FCD  C8        INY 
;$2FCE  B1 4E     LDA ($4E),Y 
;$2FD0  91 52     STA ($52),Y 
;$2FD2  C8        INY 
;$2FD3  B1 4E     LDA ($4E),Y 
;$2FD5  91 52     STA ($52),Y 
;$2FD7  C8        INY 
;$2FD8  B1 4E     LDA ($4E),Y 
;$2FDA  91 52     STA ($52),Y 
;$2FDC  C8        INY 
;$2FDD  B1 4E     LDA ($4E),Y 
;$2FDF  91 52     STA ($52),Y 
;$2FE1  A4 54     LDY $54 
;$2FE3  B1 50     LDA ($50),Y 
;$2FE5  A4 55     LDY $55 
;$2FE7  91 50     STA ($50),Y 
;$2FE9  A5 4E     LDA $4E 
;$2FEB  E6 4F     INC $4F 
;$2FED  18        CLC 
;$2FEE  69 40     ADC #$40
;$2FF0  90 02     BCC L_BRS_($2FF4)_($2FF0) OK
;$2FF2  E6 4F     INC $4F 
;//------------------------------
;L_BRS_($2FF4)_($2FF0) OK
;//------------------------------
;$2FF4  85 4E     STA $4E 
;$2FF6  A5 52     LDA $52 
;$2FF8  E6 53     INC $53 
;$2FFA  18        CLC 
;$2FFB  69 40     ADC #$40
;$2FFD  90 02     BCC L_BRS_($3001)_($2FFD) OK
;$2FFF  E6 53     INC $53 
;//------------------------------
;L_BRS_($3001)_($2FFD) OK
;//------------------------------
;$3001  85 52     STA $52 
;$3003  A5 50     LDA $50 
;$3005  18        CLC 
;$3006  69 28     ADC #$28
;$3008  90 02     BCC L_BRS_($300C)_($3008) OK
;$300A  E6 51     INC $51 
;//------------------------------
;L_BRS_($300C)_($3008) OK
;//------------------------------
;$300C  85 50     STA $50 
;$300E  CA        DEX 
;$300F  D0 A7     BNE L_BRS_($2FB8)_($300F) OK
;$3011  60        RTS 
		org $2FB8
		ldy #$00
		lda ($4e),y
		sta ($52),y
		ldy #$28
		lda ($4e),y
		sta ($52),y
		ldy #$50
		lda ($4e),y
		sta ($52),y
		ldy #$78
		lda ($4e),y
		sta ($52),y
		ldy #$a0
		lda ($4e),y
		sta ($52),y
		ldy #$c8
		lda ($4e),y
		sta ($52),y
		ldy #$f0
		lda ($4e),y
		sta ($52),y
		inc $4f
		inc $53
		ldy #$18
		lda ($4e),y
		sta ($52),y
		dec $4f
		dec $53
		inc $4f
		lda $4e
		clc
		adc #$40
		sta $4e
		scc:inc $4f
		inc $53
		lda $52
		clc
		adc #$40
		sta $52
		scc:inc $53
		dex
		bne $2fb8
		rts
		:$3012-* nop
		ert * <> $3012
		
;$301A  20 13 31  JSR L_JSR_($3113)_($301A) OK
;$301D  20 13 31  JSR L_JSR_($3113)_($301D) OK
;$3020  20 13 31  JSR L_JSR_($3113)_($3020) OK
;$3023  20 13 31  JSR L_JSR_($3113)_($3023) OK
;$3026  20 13 31  JSR L_JSR_($3113)_($3026) OK
		org $301A
		jsr ScrollScreenRight5x
		:4*3 nop
		;jsr ScrollScreenRight
		;jsr ScrollScreenRight
		;jsr ScrollScreenRight
		;jsr ScrollScreenRight
		;jsr ScrollScreenRight

;$302A  A9 80     LDA #$80		; Init SID (for random number generator only?)
;$302C  8D 0E D4  STA $D40E                          // Voice 3: Frequency Control - Low-Byte
;$302F  8D 0F D4  STA $D40F                          // Voice 3: Frequency Control - High-Byte
;$3032  8D 12 D4  STA $D412                          // Voice 3: Control Register
;$3035  A9 0F     LDA #$0F
;$3037  8D 18 D4  STA $D418                          // Select Filter Mode and Volume
;$303A  A9 01     LDA #$01
;$303C  8D 13 D4  STA $D413                          // Voice 3: Attack / Decay Cycle Control
;$303F  A9 00     LDA #$00
;$3041  8D 14 D4  STA $D414                          // Voice 3: Sustain / Release Cycle Control
;$3044  A9 80     LDA #$80
;$3046  60        RTS 
		org $302A
		lda #$0f
		sta audf4
		lda #$00
		sta audc4
		:28-10 nop
		
;$3049  8D 15 D0  STA $D015                          // Sprite display Enable
;$304C  8D 1D D0  STA $D01D                          // Sprites Expand 2x Horizontal (X)
		org $3049
		sta spriteregs+$15
		sta spriteregs+$1d
		:$3071-* nop ; patch copying sprite data from 3c00 to c800
		
;$3084  A9 F8     LDA #$F8
;$3086  85 5A     STA $5A 
;$3088  A9 E0     LDA #$E0	; TODO: screen pointer?
;$308A  85 5B     STA $5B 
		org $3084
		atari_screen_address_equ screen_e0f8,$e0f8
		lda #<screen_e0f8
		sta $5a
		lda #>screen_e0f8
		sta $5b
		
;$30B1  A5 52     LDA $52 
;$30B3  18        CLC 
;$30B4  69 40     ADC #$40
;$30B6  90 02     BCC L_BRS_($30BA)_($30B6) OK
;$30B8  E6 53     INC $53 
; stride for next 8 columns
		org $30b4
		adc #$08
		
;$30C1  18        CLC 
;$30C2  69 F8     ADC #$F8
;$30C4  C9 F8     CMP #$F8
		org $30C2
		adc #$ff	; this is actually sbc #$08, stride for previous byte
		cmp #$ff
		
;$30D2  A9 38     LDA #$38
;$30D4  85 5A     STA $5A 
;$30D6  A9 E0     LDA #$E0	; TODO: screen address?
;$30D8  85 5B     STA $5B 
		org $30D2
		atari_screen_address_equ screen_e038,$e038
		lda #<screen_e038
		sta $5a
		lda #>screen_e038
		sta $5b
		
;$3106  E9 08     SBC #$08
		org $3106
		sbc #$01	; stride for next byte in one line
		
;$3125  A9 00     LDA #$00
;$3127  85 5A     STA $5A 
;$3129  A9 E0     LDA #$E0
;$312B  85 5B     STA $5B 	; TODO: screen address?
		org $3125
		lda #<screen_e000
		sta $5a
		lda #>screen_e000
		sta $5b
		
;$3155  69 40     ADC #$40
		org $3155
		adc #$40/8	; stride for next 8 bytes in one line
		
;$3163  69 08     ADC #$08
		org $3163
		adc #$01	; stride for next byte in one line
		
;$3173  A9 00     LDA #$00
;$3175  85 5A     STA $5A 
;$3177  A9 E1     LDA #$E1	; TODO: screen address?
;$3179  85 5B     STA $5B 
		org $3173
		atari_screen_address_equ screen_e100,$e100
		lda #<screen_e100
		sta $5a
		lda #>screen_e100
		sta $5b
	
;$31A9  69 08     ADC #$08
		org $31A9
		adc #$01	; stride for next byte in one line
		
;$327D  A9 78     LDA #$78
;$327F  85 4F     STA $4F 
;$3281  A6 60     LDX $60 
;$3283  F0 05     BEQ L_BRS_($328A)_($3283) OK
;//------------------------------
;L_BRS_($3285)_($3288) OK
;//------------------------------
;$3285  E6 4F     INC $4F 
;$3287  CA        DEX 
;$3288  D0 FB     BNE L_BRS_($3285)_($3288) OK
;Speedup
		org $327d
		lda #$78
		clc
		adc $60
		sta $4f
		ldx #$00
		jmp $328a
		nop
		ert * != $328a
		
;$3329  A5 27     LDA $27 
;$332B  85 52     STA $52 ; low byte of tilemap cell address
		org $3329
		jmp sub_3329_fixup
		nop
		
;$33B5  A0 07     LDY #$07		; TODO: draw tile on screen?
;//------------------------------
;L_BRS_($33B7)_($33BC) OK
;//------------------------------
;$33B7  B1 5E     LDA ($5E),Y 
;$33B9  91 5A     STA ($5A),Y 
;$33BB  88        DEY 
;$33BC  10 F9     BPL L_BRS_($33B7)_($33BC) OK
;$33BE  60        RTS 
		org $33B5
		ldy #$00
		lda $4000
		sta ($5a),y
		jmp sub_33b5_fixup
		
;$33C3  A9 78     LDA #$78
;$33C5  85 4F     STA $4F 
;$33C7  A6 60     LDX $60 
;$33C9  F0 05     BEQ L_BRS_($33D0)_($33C9) OK
;//------------------------------
;L_BRS_($33CB)_($33CE) OK
;//------------------------------
;$33CB  E6 4F     INC $4F 
;$33CD  CA        DEX 
;$33CE  D0 FB     BNE L_BRS_($33CB)_($33CE) OK
; Speedup
		org $33C3
		lda #$78
		clc
		adc $60
		sta $4f
		ldx #$00
		jmp $33d0
		nop
		ert * != $33d0
		
;$3481  A9 1A     LDA #$1A
;$3483  8D 13 D4  STA $D413                          // Voice 3: Attack / Decay Cycle Control
;$3486  A9 81     LDA #$81
;$3488  8D 12 D4  STA $D412                          // Voice 3: Control Register
		org $3481
		lda #footstep
		sta audc4
		lda #FootstepLength
		sta FootstepLengthReg
		:10-5-5 nop
		
;$361E  A9 01     LDA #$01
;$3620  8D 13 D4  STA $D413                          // Voice 3: Attack / Decay Cycle Control
;$3623  A9 81     LDA #$81
;$3625  8D 12 D4  STA $D412                          // Voice 3: Control Register
		org $361E
		lda #footstep
		sta audc4
		lda #FootstepLength
		sta FootstepLengthReg
		:10-5-5 nop
		
;$3635  20 72 30  JSR L_JSR_($3072)_($3635) OK
		org $3635
		jsr ScrollScreenLeft
		
;$364A  20 13 31  JSR L_JSR_($3113)_($364A) OK
		org $364A
		jsr ScrollScreenRight
		
;$367C  A9 01     LDA #$01
;$367E  8D 13 D4  STA $D413                          // Voice 3: Attack / Decay Cycle Control
;$3681  A9 81     LDA #$81
;$3683  8D 12 D4  STA $D412                          // Voice 3: Control Register
		org $367C
		lda #footstep
		sta audc4
		lda #FootstepLength
		sta FootstepLengthReg
		:10-5-5 nop
		
;$3687  A9 1A     LDA #$1A
;$3689  8D 13 D4  STA $D413                          // Voice 3: Attack / Decay Cycle Control
;$368C  A9 81     LDA #$81
;$368E  8D 12 D4  STA $D412                          // Voice 3: Control Register
		org $3687
		lda #footstep
		sta audc4
		lda #FootstepLength
		sta FootstepLengthReg
		:10-5-5 nop
		
;$36E3  A9 08     LDA #$08
;$36E5  85 52     STA $52 
		org $36E3
		jmp sub_36e3_fixup
		nop
		
;$36EB  A9 00     LDA #$00
;$36ED  A4 4A     LDY $4A 
;$36EF  F0 06     BEQ L_BRS_($36F7)_($36EF) OK
;//------------------------------
;L_BRS_($36F1)_($36F5) OK
;//------------------------------
;$36F1  18        CLC 
;$36F2  69 05     ADC #$05
;$36F4  88        DEY 
;$36F5  D0 FA     BNE L_BRS_($36F1)_($36F5) OK
; Speedup
		org $36eb
		; A = $4A*5
		lda $4A
		asl @
		asl @
		clc
		adc $4A
		jmp $36f7
		nop
		nop
		ert * != $36F7
		
;$3729  8D 03 D0  STA $D003                          // Sprite 1 Y Pos
;$372C  8D 05 D0  STA $D005                          // Sprite 2 Y Pos
;$372F  8D 07 D0  STA $D007                          // Sprite 3 Y Pos
;$3732  8D 09 D0  STA $D009                          // Sprite 4 Y Pos
;$3735  8D 0B D0  STA $D00B                          // Sprite 5 Y Pos
;$3738  AD 10 D0  LDA $D010                          // Sprites 0-7 MSB of X coordinate
		org $3729
		sta spriteregs+$03
		sta spriteregs+$05
		sta spriteregs+$07
		sta spriteregs+$09
		sta spriteregs+$0b
		sta spriteregs+$10
		
;$373F  8D 10 D0  STA $D010                          // Sprites 0-7 MSB of X coordinate
		org $373F
		sta spriteregs+$10
		
;$3744  8D 02 D0  STA $D002                          // Sprite 1 X Pos
;$3747  8D 08 D0  STA $D008                          // Sprite 4 X Pos
		org $3744
		sta spriteregs+$02
		sta spriteregs+$08
		
;$374D  8D 0A D0  STA $D00A                          // Sprite 5 X Pos
		org $374D
		sta spriteregs+$0A
		
;$3754  0D 10 D0  ORA $D010                         // Sprites 0-7 MSB of X coordinate
;$3757  8D 10 D0  STA $D010                          // Sprites 0-7 MSB of X coordinate
;//------------------------------
;L_BRS_($375A)_($3750) OK
;//------------------------------
;$375A  AD 0A D0  LDA $D00A                          // Sprite 5 X Pos
		org $3754
		ora spriteregs+$10
		sta spriteregs+$10
		sta spriteregs+$0a
		
;$3760  8D 04 D0  STA $D004                          // Sprite 2 X Pos
		org $3760
		sta spriteregs+$04
		
;$3767  0D 10 D0  ORA $D010                         // Sprites 0-7 MSB of X coordinate
;$376A  8D 10 D0  STA $D010                          // Sprites 0-7 MSB of X coordinate
;//------------------------------
;L_BRS_($376D)_($3763) OK
;//------------------------------
;$376D  AD 04 D0  LDA $D004                          // Sprite 2 X Pos
		org $3767
		ora spriteregs+$10
		sta spriteregs+$10
		sta spriteregs+$04
		
;$3773  8D 06 D0  STA $D006                          // Sprite 3 X Pos
		org $3773
		sta spriteregs+$06
		
;$377A  0D 10 D0  ORA $D010                         // Sprites 0-7 MSB of X coordinate
;$377D  8D 10 D0  STA $D010                          // Sprites 0-7 MSB of X coordinate
		org $377A
		ora spriteregs+$10
		sta spriteregs+$10

;$3780  A9 30     LDA #$30
;$3782  8D 1D D0  STA $D01D                          // Sprites Expand 2x Horizontal (X)
;$3785  A9 2B     LDA #$2B
;$3787  8D F9 CF  STA $CFF9 
;$378A  A9 2C     LDA #$2C
;$378C  8D FA CF  STA $CFFA 
;$378F  A9 2D     LDA #$2D
;$3791  8D FB CF  STA $CFFB 
;$3794  A9 2E     LDA #$2E
;$3796  8D FC CF  STA $CFFC 
;$3799  A9 2F     LDA #$2F
;$379B  8D FD CF  STA $CFFD 
		org $3780
		lda #$30
		sta spriteregs+$1d
		
;$379F  8D 04 D0  STA $D004                          // Sprite 2 X Pos
;$37A2  8D 08 D0  STA $D008                          // Sprite 4 X Pos
;$37A5  18        CLC 
;$37A6  69 08     ADC #$08
;$37A8  8D 00 D0  STA $D000                          // Sprite 0 X Pos
;$37AB  8D 0C D0  STA $D00C                          // Sprite 6 X Pos
;$37AE  90 08     BCC L_BRS_($37B8)_($37AE) OK
;$37B0  A9 6B     LDA #$6B
;$37B2  0D 10 D0  ORA $D010                         // Sprites 0-7 MSB of X coordinate
;$37B5  8D 10 D0  STA $D010                          // Sprites 0-7 MSB of X coordinate
;//------------------------------
;L_BRS_($37B8)_($37AE) OK
;//------------------------------
;$37B8  AD 00 D0  LDA $D000                          // Sprite 0 X Pos
;$37BB  18        CLC 
;$37BC  69 18     ADC #$18
;$37BE  8D 02 D0  STA $D002                          // Sprite 1 X Pos
;$37C1  90 08     BCC L_BRS_($37CB)_($37C1) OK
;$37C3  A9 2A     LDA #$2A
;$37C5  0D 10 D0  ORA $D010                         // Sprites 0-7 MSB of X coordinate
;$37C8  8D 10 D0  STA $D010                          // Sprites 0-7 MSB of X coordinate
;//------------------------------
;L_BRS_($37CB)_($37C1) OK
;//------------------------------
;$37CB  AD 02 D0  LDA $D002                          // Sprite 1 X Pos
;$37CE  18        CLC 
;$37CF  69 18     ADC #$18
;$37D1  8D 06 D0  STA $D006                          // Sprite 3 X Pos
;$37D4  8D 0A D0  STA $D00A                          // Sprite 5 X Pos
;$37D7  90 08     BCC L_BRS_($37E1)_($37D7) OK
;$37D9  A9 28     LDA #$28
;$37DB  0D 10 D0  ORA $D010                         // Sprites 0-7 MSB of X coordinate
;$37DE  8D 10 D0  STA $D010                          // Sprites 0-7 MSB of X coordinate
		org $379F
		sta spriteregs+$04
		sta spriteregs+$08
		clc
		adc #$08
		sta spriteregs+$00
		sta spriteregs+$0c
		bcc $37b8
		lda #$6b
		ora spriteregs+$10
		sta spriteregs+$10
		ert * <> $37b8
		lda spriteregs+$00
		clc
		adc #$18
		sta spriteregs+$02
		bcc $37cb
		lda #$2a
		ora spriteregs+$10
		sta spriteregs+$10
		ert * <> $37cb
		lda spriteregs+$02
		clc
		adc #$18
		sta spriteregs+$06
		sta spriteregs+$0a
		bcc $37e1
		lda #$28
		ora spriteregs+$10
		sta spriteregs+$10
		ert *<>$37e1
		
;$3805  8D 06 D0  STA $D006                          // Sprite 3 X Pos
;$3808  8D 0A D0  STA $D00A                          // Sprite 5 X Pos
;$380B  38        SEC 
;$380C  E9 38     SBC #$38
;$380E  8D 04 D0  STA $D004                          // Sprite 2 X Pos
;$3811  8D 08 D0  STA $D008                          // Sprite 4 X Pos
;$3814  90 05     BCC L_BRS_($381B)_($3814) OK
;$3816  A9 FF     LDA #$FF
;$3818  8D 10 D0  STA $D010                          // Sprites 0-7 MSB of X coordinate
;//------------------------------
;L_BRS_($381B)_($3814) OK
;//------------------------------
;$381B  AD 04 D0  LDA $D004                          // Sprite 2 X Pos
;$381E  18        CLC 
;$381F  69 08     ADC #$08
;$3821  8D 00 D0  STA $D000                          // Sprite 0 X Pos
;$3824  8D 0C D0  STA $D00C                          // Sprite 6 X Pos
;$3827  90 08     BCC L_BRS_($3831)_($3827) OK
;$3829  A9 43     LDA #$43
;$382B  0D 10 D0  ORA $D010                         // Sprites 0-7 MSB of X coordinate
;$382E  8D 10 D0  STA $D010                          // Sprites 0-7 MSB of X coordinate
;//------------------------------
;L_BRS_($3831)_($3827) OK
;//------------------------------
;$3831  AD 0C D0  LDA $D00C                          // Sprite 6 X Pos
;$3834  18        CLC 
;$3835  69 18     ADC #$18
;$3837  8D 02 D0  STA $D002                          // Sprite 1 X Pos
;$383A  90 08     BCC L_BRS_($3844)_($383A) OK
;$383C  A9 02     LDA #$02
;$383E  0D 10 D0  ORA $D010                         // Sprites 0-7 MSB of X coordinate
;$3841  8D 10 D0  STA $D010                          // Sprites 0-7 MSB of X coordinate
		org $3805
		sta spriteregs+$06
		sta spriteregs+$0a
		sec
		sbc #$38
		sta spriteregs+$04
		sta spriteregs+$08
		bcc $381b
		lda #$ff
		sta spriteregs+$10
		ert *<>$381b
		lda spriteregs+$04
		clc
		adc #$08
		sta spriteregs+$00
		sta spriteregs+$0c
		bcc $3831
		lda #$43
		ora spriteregs+$10
		sta spriteregs+$10
		ert * <> $3831
		lda spriteregs+$0c
		clc
		adc #$18
		sta spriteregs+$02
		bcc $3844
		lda #$02
		ora spriteregs+$10
		sta spriteregs+$10
		ert * <> $3844
		
;$3868  A9 E0     LDA #$E0	; TODO: screen pointer
;$386A  85 4F     STA $4F 
;$386C  A9 00     LDA #$00
;$386E  85 4E     STA $4E 
		org $3868
		lda #>screen_e000
		sta $4f
		lda #<screen_e000
		sta $4e
;$3883  69 08     ADC #$08
		org $3883
		adc #$01
		
;$388F  E9 C0     SBC #$C0
;$3891  B0 02     BCS L_BRS_($3895)_($3891) OK
;$3893  C6 4F     DEC $4F 
;//------------------------------
;L_BRS_($3895)_($3891) OK
;//------------------------------
;$3895  85 4E     STA $4E 
;$3897  A9 45     LDA #$45
;$3899  85 51     STA $51 
;$389B  A9 00     LDA #$00
;$389D  85 50     STA $50 
		org $388F
		jmp sub_388f_fixup
		
		
;$38B2  A9 D0     LDA #$D0
		org $38B2
		lda #>spriteregs
		
;$38DE  8D 15 D0  STA $D015                          // Sprite display Enable
		org $38DE
		;sta spriteregs+$15
		jsr HideBubble
	
;$38EF  A0 10     LDY #$10		; TODO: Restore sprites
;$38F1  A9 00     LDA #$00
;$38F3  85 4E     STA $4E 
;$38F5  A9 D0     LDA #$D0
;$38F7  85 4F     STA $4F 
;$38F9  A9 00     LDA #$00
;$38FB  85 50     STA $50 
;$38FD  A9 B9     LDA #$B9
;$38FF  85 51     STA $51 
;//------------------------------
;L_BRS_($3901)_($3906) OK
;//------------------------------
;$3901  B1 50     LDA ($50),Y 
;$3903  91 4E     STA ($4E),Y 
;$3905  88        DEY 
;$3906  10 F9     BPL L_BRS_($3901)_($3906) OK
;$3908  A0 15     LDY #$15
;$390A  B1 50     LDA ($50),Y 
;$390C  91 4E     STA ($4E),Y 
;$390E  A0 1D     LDY #$1D
;$3910  B1 50     LDA ($50),Y 
;$3912  91 4E     STA ($4E),Y 
;$3914  A0 27     LDY #$27
;//------------------------------
;L_BRS_($3916)_($391D) OK
;//------------------------------
;$3916  B1 50     LDA ($50),Y 
;$3918  91 4E     STA ($4E),Y 
;$391A  C8        INY 
;$391B  C0 2F     CPY #$2F
;$391D  D0 F7     BNE L_BRS_($3916)_($391D) OK
;$391F  A2 00     LDX #$00
;//------------------------------
;L_BRS_($3921)_($392A) OK
;//------------------------------
;$3921  BD 30 B9  LDA $B930,X 
;$3924  9D F8 CF  STA $CFF8,X 
;$3927  E8        INX 
;$3928  E0 08     CPX #$08
;$392A  D0 F5     BNE L_BRS_($3921)_($392A) OK
;$392C  60        RTS 

		org $38ef
		ldy #$10
@		lda $b900,y
		sta spriteregs,y
		dey
		bpl @-
		lda $b91d
		sta spriteregs+$1d
		ldy #$27
@		lda $b900,y
		sta spriteregs,y
		iny
		cpy #$2f
		bne @-
		ldx #$00
@		lda $b930,x
		sta $cff8,x
		inx
		cpx #$08
		bne @-
		lda $b915
		sta spriteregs+$15
		beq @+
		jsr RenderBubbleDirect
@		rts
		:$392d-* nop

		
;$38F5  A9 D0     LDA #$D0
;		org $38F5
;		lda #>spriteregs
		
;$395A  8D 00 DC  STA $DC00                          // Data Port A (Keyboard, Joystick, Paddles)
;$395D  AE 01 DC  LDX $DC01                          // Data Port B (Keyboard, Joystick, Paddles)
;$3960  E0 FF     CPX #$FF
;$3962  F0 62     BEQ L_BRS_($39C6)_($3962) OK

		org $395A
		jsr readkey_set_input
		jsr readkey_c64
		cmp #$ff
		
;$396C  A9 FE     LDA #$FE
;$396E  8D 00 DC  STA $DC00                          // Data Port A (Keyboard, Joystick, Paddles)
		org $396E
		jsr readkey_set_input
		
;$3974  AD 01 DC  LDA $DC01                          // Data Port B (Keyboard, Joystick, Paddles)
;$3977  CD 01 DC  CMP $DC01                          // Data Port B (Keyboard, Joystick, Paddles)
;$397A  D0 F8     BNE L_BRS_($3974)_($397A) OK
		org $3974
		jsr readkey_c64
		:5 nop

;$399E  8D 00 DC  STA $DC00                          // Data Port A (Keyboard, Joystick, Paddles)
		org $399E
		jsr readkey_set_input
		
		
;$3A01  A9 CC     LDA #$CC	; TODO: Colorram pointer
;$3A03  85 F3     STA $F3 
;$3A05  A9 00     LDA #$00
;$3A07  85 F2     STA $F2 
;$3A09  A4 F0     LDY $F0 
;$3A0B  F0 0E     BEQ L_BRS_($3A1B)_($3A0B) OK
;//------------------------------
;L_BRS_($3A0D)_($3A19) OK
;//------------------------------
;$3A0D  A5 F2     LDA $F2 
;$3A0F  18        CLC 
;$3A10  69 28     ADC #$28
;$3A12  90 02     BCC L_BRS_($3A16)_($3A12) OK
;$3A14  E6 F3     INC $F3 
;//------------------------------
;L_BRS_($3A16)_($3A12) OK
;//------------------------------
;$3A16  85 F2     STA $F2 
;$3A18  88        DEY 
;$3A19  D0 F2     BNE L_BRS_($3A0D)_($3A19) OK
;//------------------------------
;L_BRS_($3A1B)_($3A0B) OK
;//------------------------------
;$3A1B  A5 EF     LDA $EF 
;$3A1D  20 90 3A  JSR L_JSR_($3A90)_($3A1D) OK

; code for shields blinking
		org $3a01
		stx sub_3a01_restore_x+1
		lda $EF ; x coordinate
		sec
		sbc $58
		tax
		ldy $F0 ; y coordinate
		jsr IsTileCoveredBySprite
		bcs sub_3a01_restore_x
		jsr SpriteCalculatePositionF2
		jsr $3a90
sub_3a01_restore_x		
		ldx #$ff
		jmp $3a20
		:$3a20-* nop
		
;$3A34  A9 CD     LDA #$CD	; TODO: Colorram pointer
;$3A36  85 F3     STA $F3 
;$3A38  A9 68     LDA #$68
;$3A3A  85 F2     STA $F2 
;$3A3C  A9 0A     LDA #$0A
;$3A3E  20 90 3A  JSR L_JSR_($3A90)_($3A3E) OK

; blinking of safe
		org $3a34
		;:$3a41-* nop
		jmp sub_3a34_fixup
		:$3a41-* nop
		ert *>$3a41
		
;$3A41  AD 0D DC  LDA $DC0D                          // Interrupt (IRQ) Control Register
		org $3A41
		:3 nop
		
;$3A4B  A9 00     LDA #$00
;$3A4D  8D 02 DC  STA $DC02                          // Data Direction Register A
;$3A50  AD 00 DC  LDA $DC00                          // Data Port A (Keyboard, Joystick, Paddles)
		org $3A4B
		;lda #$ff
		;jsr readkey_set_input
		;jsr readkey_c64
		jsr read_joystick
		jmp $3A53
		nop
		nop
		
;L_JSR_($3A90)_($3A1D) OK
;L_JSR_($3A90)_($3A3E) OK
;//------------------------------
;$3A90  38        SEC 			; Flip color attribute
;$3A91  E5 58     SBC $58 
;$3A93  18        CLC 
;$3A94  65 F2     ADC $F2 
;$3A96  90 02     BCC L_BRS_($3A9A)_($3A96) OK
;$3A98  E6 F3     INC $F3 
;//------------------------------
;L_BRS_($3A9A)_($3A96) OK
;//------------------------------
;$3A9A  85 F2     STA $F2 
;$3A9C  A0 00     LDY #$00
;$3A9E  84 F5     STY $F5 
;$3AA0  B1 F2     LDA ($F2),Y 
;$3AA2  4A        LSR A 
;$3AA3  66 F5     ROR $F5 
;$3AA5  4A        LSR A 
;$3AA6  66 F5     ROR $F5 
;$3AA8  4A        LSR A 
;$3AA9  66 F5     ROR $F5 
;$3AAB  4A        LSR A 
;$3AAC  66 F5     ROR $F5 
;$3AAE  05 F5     ORA $F5
;$3AB0  91 F2     STA ($F2),Y 
;$3AB2  60        RTS 

		org $3a90
		ldy #$00
		ldx #$08
@		lda ($F2),y
		eor #$ff
		sta ($F2),y
		tya
		clc
		adc #$28
		tay
		scc:inc $F3
		dex
		bne @-
		rts
		:$3AB3-* nop
		
;$3A87  8D 02 DC  STA $DC02                          // Data Direction Register A
		org $3A87
		:3 nop
		
;$3B50  AD 1B D4  LDA $D41B                          // Oscillator 3 Output
		org $3B50
		lda random
		
;$3B7A  AD 1B D4  LDA $D41B                          // Oscillator 3 Output
		org $3B7A
		lda random
		
; this adds original fonts and tilemaps from Spectrum version
; to keep dithered shading Spectrum used		
		org $6000
		ins 'sd_spectrum_font.bin'
		
		org $7800
		ins 'sd_spectrum_tilemap.bin',+$0000,$60 ; 00
		org $7900
		ins 'sd_spectrum_tilemap.bin',+$0100,$60 ; 01
		org $7A00
		ins 'sd_spectrum_tilemap.bin',+$0200,$60 ; 02
		org $7B00
		ins 'sd_spectrum_tilemap.bin',+$0300,$60 ; 03
		org $7C00
		ins 'sd_spectrum_tilemap.bin',+$0400,$60 ; 04
		org $7D00
		ins 'sd_spectrum_tilemap.bin',+$0500,$60 ; 05
		org $7E00
		ins 'sd_spectrum_tilemap.bin',+$0600,$60 ; 06
		org $7F00
		ins 'sd_spectrum_tilemap.bin',+$0700,$60 ; 07
		org $8000
		ins 'sd_spectrum_tilemap.bin',+$0800,$60 ; 08
		org $8100
		ins 'sd_spectrum_tilemap.bin',+$0900,$60 ; 09
		org $8200
		ins 'sd_spectrum_tilemap.bin',+$0A00,$60 ; 10
		org $8300
		ins 'sd_spectrum_tilemap.bin',+$0B00,$60 ; 11
		org $8400
		ins 'sd_spectrum_tilemap.bin',+$0C00,$60 ; 12
		org $8500
		ins 'sd_spectrum_tilemap.bin',+$0D00,$60 ; 13
		org $8600
		ins 'sd_spectrum_tilemap.bin',+$0E00,$60 ; 14
		org $8700
		ins 'sd_spectrum_tilemap.bin',+$0F00,$60 ; 15
		org $8800
		ins 'sd_spectrum_tilemap.bin',+$1000,$60 ; 16
		org $8900
		ins 'sd_spectrum_tilemap.bin',+$1100,$60 ; 17
		org $8A00
		ins 'sd_spectrum_tilemap.bin',+$1200,$60 ; 18
		org $8B00
		ins 'sd_spectrum_tilemap.bin',+$1300,$60 ; 19
		org $8C00
		ins 'sd_spectrum_tilemap.bin',+$1400,$60 ; 20
		
;$91F0  8E 10 D0  STX $D010                          // Sprites 0-7 MSB of X coordinate
		org $91F0
		stx spriteregs+$10
		
;$92E8  AD 00 D0  LDA $D000                          // Sprite 0 X Pos
		org $92E8
		lda spriteregs+$00
		
;$92EE  8D 00 D0  STA $D000                          // Sprite 0 X Pos
		org $92EE
		sta spriteregs+$00
		
;$93F0  8E 10 D0  STX $D010                          // Sprites 0-7 MSB of X coordinate
		org $93F0
		stx spriteregs+$10
		
;$94E8	AD 00 D0   LDA $D000						// Sprite 0 X Pos
		org $94E8
		lda spriteregs+$00

;$94EE  8D 00 D0  STA $D000                          // Sprite 0 X Pos
		org $94EE
		sta spriteregs+$00
		
;$95E8  AD 15 D0  LDA $D015                          // Sprite display Enable
;$95EB  F0 0F     BEQ L_BRS_($95FC)_($95EB) OK
;$95ED  AC 04 D0  LDY $D004                          // Sprite 2 X Pos
;$95F0  A9 00     LDA #$00
;$95F2  8D 15 D0  STA $D015                          // Sprite display Enable
;$95F5  AD 10 D0  LDA $D010                          // Sprites 0-7 MSB of X coordinate
		org $95E8
		lda spriteregs+$15
		beq $95fc
		ldy spriteregs+$04
		lda #$00
		sta spriteregs+$15
		;jsr HideBubble ; can't do it here, as screen already scrolled
		lda spriteregs+$10
		
;$9879  8D 15 D0  STA $D015                          // Sprite display Enable
		org $9879
		sta spriteregs+$15
		
		org $b940
SetupMusic1
		ldy #0
		beq @+
SetupMusic2
		ldy #6
@		jsr MusicInit
		jmp ResetPokey
		
PlayMusic1
		ldy #0
		beq @+
PlayMusic2		
		ldy #6
@		jsr MusicInit
		jsr ResetPokey

SyncMusic		
@		bit MusicEndFlag
		bmi PlayMusicEnd
		lda trig0
		lsr @
		bcc PlayMusicEnd
		lda consol
		and #%111
		cmp #%111
		bne PlayMusicEnd
		lda skstat
		and #%100
		beq PlayMusicEnd
		bne @-
		
PlayMusicEnd
		lda #$ff
		sta MusicEndFlag
		jmp ResetPokey
		
MusicEndFlag			dta $ff
MusicMainCounter		dta 0
MusicChannel1Index		dta 0
MusicChannel1Counter	dta 0
MusicChannel1Volume		dta a(0)
MusicChannel1VolumeStep	dta a($0020)
MusicChannel2Index		dta 0
MusicChannel2Counter	dta 0
MusicChannel2Volume		dta a(0)
MusicChannel2VolumeStep	dta a($0199)
MusicChannel3Index		dta 0
MusicChannel3Counter	dta 0
MusicChannel3Volume		dta a(0)
MusicChannel3VolumeStep	dta a($0020)
MusicChannelDataSize	= MusicChannel2Index-MusicChannel1Index
MusicRegistersEnd		equ *

MusicInit
		lda #$00
		sta MusicMainCounter
		tax
@		sta MusicChannel1Index,x
		sta MusicChannel2Index,x
		sta MusicChannel3Index,x
		inx
		cpx #MusicChannel1VolumeStep-MusicChannel1Index
		bne @-
		
		lda MusicDefinitions,y
		sta MusicChannel1GetData+1
		lda MusicDefinitions+1,y
		sta MusicChannel1GetData+2
		lda MusicDefinitions+2,y
		sta MusicChannel2GetData+1
		lda MusicDefinitions+3,y
		sta MusicChannel2GetData+2
		lda MusicDefinitions+4,y
		sta MusicChannel3GetData+1
		lda MusicDefinitions+5,y
		sta MusicChannel3GetData+2
		
		lda #$00
		sta MusicEndFlag		
		rts
		
MusicDefinitions
		dta a(Song1Channel1),a(Song1Channel2),a(Song1Channel3)
		dta a(Song2Channel1),a(Song2Channel2),a(Song1Channel3)
		
MusicEnvelope
		lda MusicChannel1Volume+1,x
		beq @+1
		lda MusicChannel1Volume,x
		sec
		sbc MusicChannel1VolumeStep,x
		sta MusicChannel1Volume,x
		lda MusicChannel1Volume+1,x
		sbc MusicChannel1VolumeStep+1,x
		bpl @+
		lda #$00
@		sta MusicChannel1Volume+1,x
@		ora #$e0
		rts

MusicChannel1GetData
		lda Song1Channel1,x
		rts

MusicChannel2GetData
		lda Song1Channel2,x
		rts

MusicChannel3GetData
		lda Song1Channel3,x
		rts
		
MusicNTSCCounter
		dta 5
		
MusicStep
		ldx PAL
		dex
		beq @+
		dec MusicNTSCCounter
		bpl @+
		mva #5 MusicNTSCCounter
		rts

@		ldx #$0
		jsr MusicEnvelope
		sta audc2
		ldx #MusicChannelDataSize
		jsr MusicEnvelope
		sta audc3
		ldx #2*MusicChannelDataSize
		jsr MusicEnvelope
		sta audc4
		
		inc MusicMainCounter
		lda MusicMainCounter
		cmp #$04
		beq MusicNote
		rts
MusicEnd
		lda #$ff
		sta MusicEndFlag
		rts
MusicNote
		lda #$00
		sta MusicMainCounter
		
		lda MusicChannel1Counter
		bne MusicChannel2
		ldx MusicChannel1Index
		jsr MusicChannel1GetData
		cmp #$ff
		beq MusicEnd
		sta audf1
		inx
		jsr MusicChannel1GetData
		sta audf2
		inx
		jsr MusicChannel1GetData
		sta MusicChannel1Counter
		inx
		stx MusicChannel1Index
		lda #$ef
		sta audc2
		lda #$0f
		sta MusicChannel1Volume+1
		lda #$00
		sta MusicChannel1Volume
		
MusicChannel2
		dec MusicChannel1Counter
		
		lda MusicChannel2Counter
		bne MusicChannel3
		ldx MusicChannel2Index
		
		jsr MusicChannel2GetData
		cmp #$ff
		beq MusicEnd
		sta audf3
		inx
		jsr MusicChannel2GetData
		sta MusicChannel2Counter
		inx
		stx MusicChannel2Index
		lda #$ef
		sta audc3
		lda #$0f
		sta MusicChannel2Volume+1
		lda #$00
		sta MusicChannel2Volume
		
MusicChannel3
		dec MusicChannel2Counter
		
		lda MusicChannel3Counter
		bne MusicChannelEnd
		ldx MusicChannel3Index
		jsr MusicChannel3GetData
		cmp #$ff
		beq MusicEnd
		sta audf4
		inx
		jsr MusicChannel3GetData
		sta MusicChannel3Counter
		inx
		stx MusicChannel3Index

		lda #$ef
		sta audc4
		lda #$0f
		sta MusicChannel3Volume+1
		lda #$00
		sta MusicChannel3Volume
		
MusicChannelEnd
		dec MusicChannel3Counter
		rts
	
Song1Channel2
		dta 41
		dta 4
		dta 49
		dta 2
		dta 46
		dta 4
		dta 55
		dta 2
		dta 41
		dta 4
		dta 49
		dta 2
		dta 62
		dta 4
		dta 62
		dta 2
		dta 55
		dta 4
		dta 49
		dta 2
		dta 46
		dta 2
		dta 49
		dta 2
		dta 55
		dta 2
		dta 41
		dta 4
		dta 49
		dta 2
		dta 62
		dta 6
		dta 41
		dta 4
		dta 49
		dta 2
		dta 46
		dta 4
		dta 55
		dta 2
		dta 41
		dta 4
		dta 49
		dta 2
		dta 62
		dta 4
		dta 62
		dta 2
		dta 55
		dta 4
		dta 49
		dta 2
		dta 46
		dta 2
		dta 49
		dta 2
		dta 55
		dta 2
		dta 41
		dta 4
		dta 49
		dta 2
		dta 62
		dta 18
		dta 255

Song1Channel3
		dta 167
		dta 6
		dta 187
		dta 6
		dta 167
		dta 12
		dta 199
		dta 6
		dta 187
		dta 6
		dta 167
		dta 12
		dta 167
		dta 6
		dta 187
		dta 6
		dta 167
		dta 12
		dta 140
		dta 6
		dta 148
		dta 6
		dta 167
		dta 24
		dta 255

Song1Channel1
		dta a(7032)
		dta 6
		dta a(7894)
		dta 6
		dta a(7032)
		dta 12
		dta a(8363)
		dta 6
		dta a(7894)
		dta 6
		dta a(7032)
		dta 12
		dta a(7032)
		dta 6
		dta a(7894)
		dta 6
		dta a(7032)
		dta 12
		dta a(5912)
		dta 6
		dta a(6264)
		dta 6
		dta a(7032)
		dta 24
		dta 255

Song2Channel1
		dta a(1167)
		dta 2
		dta a(1167)
		dta 2
		dta a(1167)
		dta 2
		dta a(1039)
		dta 2
		dta a(925)
		dta 4
		dta a(1039)
		dta 4
		dta a(1167)
		dta 2
		dta a(925)
		dta 2
		dta a(1039)
		dta 2
		dta a(1039)
		dta 2
		dta a(1167)
		dta 8
		dta a(1167)
		dta 2
		dta a(1167)
		dta 2
		dta a(1167)
		dta 2
		dta a(1039)
		dta 2
		dta a(925)
		dta 4
		dta a(1039)
		dta 4
		dta a(1167)
		dta 2
		dta a(925)
		dta 2
		dta a(1039)
		dta 2
		dta a(1039)
		dta 2
		dta a(1167)
		dta 8
		dta 255

Song2Channel3
		dta 111
		dta 4
		dta 99
		dta 4
		dta 88
		dta 4
		dta 99
		dta 4
		dta 111
		dta 4
		dta 99
		dta 4
		dta 88
		dta 4
		dta 99
		dta 4
		dta 99
		dta 4
		dta 105
		dta 4
		dta 111
		dta 2
		dta 93
		dta 2
		dta 99
		dta 2
		dta 105
		dta 2
		dta 111
		dta 2
		dta 99
		dta 2
		dta 99
		dta 2
		dta 88
		dta 2
		dta 83
		dta 8
		dta 255

Song2Channel2
		dta 167
		dta 16
		dta 167
		dta 16
		dta 118
		dta 4
		dta 125
		dta 4
		dta 132
		dta 4
		dta 125
		dta 4
		dta 132
		dta 2
		dta 125
		dta 2
		dta 118
		dta 2
		dta 111
		dta 2
		dta 167
		dta 8
		dta 255


TitleScreen
		bit TitleScreenShownFlag
		bmi TitleScreenEnd
		lda #$ff
		sta TitleScreenShownFlag
		ldy #$00
		jsr MusicInit
		lda #$10
		sta $9d
		lda #$80
		sta $31
		ldx #$00
		stx TitleScreenIndex
@		lda TitleScreenData,x
		sta $d6
		lda TitleScreenData+1,x
		sta $d7
		stx TitleScreenIndex
		jsr $bff5
		ldx TitleScreenIndex
		lda TitleScreenData+2,x
		tay
		ldx #$14
		jsr $3868
		ldx TitleScreenIndex
		inx
		inx
		inx
		cpx #TitleScreenDataEnd-TitleScreenData
		bne @-
		jmp SyncMusic
TitleScreenEnd		
		jmp PlayMusic1
		
TitleScreenData
		dta a(TextSkoolDaze),$02+2
		dta a(TextOriginalGame),$04+2
		dta a(TextByMicrosphere),$05+2
		dta a(TextCodedBy),$06+2
		dta a(TextKeith),$07+2
		dta a(TextAtariVersion),$0a+2
		dta a(TextAtariPortedFromC64),$0b+2
		dta a(TextAtariMariusz),$0c+2
		dta a(TextAtariJose),$0d+2
TitleScreenDataEnd
TextSkoolDaze
		dta c'SKOOL DAZE',0
TextOriginalGame		
		dta c'Original game by',0
TextByMicrosphere		
		dta c'Microsphere (c) 1984',0
TextCodedBy
		dta c'by David and Helen Reidy',0
TextKeith
		dta c'and Keith Warrington',0
TextAtariVersion
		dta c'Atari version 2017',0
TextAtariPortedFromC64
		dta c'ported from C64',0
TextAtariMariusz
		dta c'Code Mariusz',0		
TextAtariJose
		dta c'Graphics Jose Pereira',0
		
TitleScreenIndex
		dta 0
TitleScreenShownFlag
		dta 0
		
		ert *>$bcff
		
		org $bd00
SoundEffectBD00
		ldy $2c
		beq SoundEffectBD00End
		lda SoundEffectBD00JumpTable-1,y
		sta SoundEffectJump
		dec $2d
		beq SoundEffectBD00Clear
		ldy $2d
		jmp SoundEffectBD00
SoundEffectJump equ *-2

SoundEffectBD00Clear
		lda #$00
		sta audf1
		sta audf2
		sta audc1
		sta audc2
		sta $2c
		sta $2d
SoundEffectBD00End
		rts

SoundEffectBD00JumpTable
		dta <SoundEffectBD00_1
		dta <SoundEffectBD00_2
		dta <SoundEffectBD00_3
		
SoundEffectBD00_1
		lda SoundEffectBD00_1DataLow-1,y
		sta audf1
		lda SoundEffectBD00_1DataHigh-1,y
SoundEffectBD00Epilogue		
		sta audf2
		lda #$ef
		sta audc2
		rts

SoundEffectBD00_2
		lda SoundEffectBD00_2DataLow-1,y
		sta audf1
		lda #$01
		jmp SoundEffectBD00Epilogue
		
SoundEffectBD00_3
		cpy #$20
		bne @+
		; $3800
		lda #<$0417
		sta audf1
		lda #>$0417
		jmp SoundEffectBD00Epilogue
@		tya
		and #$01
		tay
		lda SoundEffectBD00_3DataLow,y
		sta audf1
		lda #$04
		jmp SoundEffectBD00Epilogue
		
SoundEffectBD00_1DataLow
		dta <$013A ; $B800
		dta <$0148 ; $B000
		dta <$0158 ; $A800
		dta <$016A ; $A000
		dta <$017D ; $9800
		dta <$0193 ; $9000
		dta <$01AB ; $8800
		dta <$01C6 ; $8000
		dta <$01E4 ; $7800
		dta <$0208 ; $7000
		dta <$0230 ; $6800
		dta <$025F ; $6000
		dta <$0297 ; $5800
		dta <$02DA ; $5000
		dta <$032C ; $4800
		dta <$0393 ; $4000

SoundEffectBD00_1DataHigh
		dta >$013A ; $B800
		dta >$0148 ; $B000
		dta >$0158 ; $A800
		dta >$016A ; $A000
		dta >$017D ; $9800
		dta >$0193 ; $9000
		dta >$01AB ; $8800
		dta >$01C6 ; $8000
		dta >$01E4 ; $7800
		dta >$0208 ; $7000
		dta >$0230 ; $6800
		dta >$025F ; $6000
		dta >$0297 ; $5800
		dta >$02DA ; $5000
		dta >$032C ; $4800
		dta >$0393 ; $4000

SoundEffectBD00_2DataLow
		dta <$0103 ; $DE00
		dta <$0105 ; $DC00
		dta <$0108 ; $DA00
		dta <$010A ; $D800
		dta <$010D ; $D600
		dta <$010F ; $D400
		dta <$0112 ; $D200
		dta <$0115 ; $D000
		dta <$0117 ; $CE00
		dta <$011A ; $CC00
		dta <$011D ; $CA00
		dta <$0120 ; $C800
		dta <$0123 ; $C600
		dta <$0126 ; $C400
		dta <$0129 ; $C200
		dta <$012C ; $C000
		dta <$012F ; $BE00
		dta <$0133 ; $BC00
		dta <$0136 ; $BA00
		dta <$013A ; $B800
		dta <$013D ; $B600
		dta <$0141 ; $B400
		dta <$0144 ; $B200
		dta <$0148 ; $B000
		dta <$014C ; $AE00
		dta <$0150 ; $AC00
		dta <$0154 ; $AA00
		dta <$0158 ; $A800
		dta <$015C ; $A600
		dta <$0161 ; $A400
		dta <$0165 ; $A200
		dta <$0169 ; $A000
	
SoundEffectBD00_3DataLow
		dta <$042A ; $3700
		dta <$0404 ; $3900
		
;$BF58  AA        TAX 
;$BF59  E0 20     CPX #$20
		org $BF58
		jmp sub_bf58_fixup
		
;$BEEA  A2 3F     LDX #$3F
;//------------------------------
;L_BRS_($BEEC)_($BEF2) OK
;//------------------------------
;$BEEC  A0 FF     LDY #$FF
;//------------------------------
;L_BRS_($BEEE)_($BEEF) OK
;//------------------------------
;$BEEE  88        DEY 
;$BEEF  D0 FD     BNE L_BRS_($BEEE)_($BEEF) OK
;$BEF1  CA        DEX 
;$BEF2  D0 F8     BNE L_BRS_($BEEC)_($BEF2) OK
		
		org $BEEA
		ldx #2
		jsr WaitVBLANK
		:$bef4-* nop
		
;$BFB2  A2 3F     LDX #$3F
;//------------------------------
;L_BRS_($BFB4)_($BFBA) OK
;//------------------------------
;$BFB4  A0 FF     LDY #$FF
;//------------------------------
;L_BRS_($BFB6)_($BFB7) OK
;//------------------------------
;$BFB6  88        DEY 
;$BFB7  D0 FD     BNE L_BRS_($BFB6)_($BFB7) OK
;$BFB9  CA        DEX 
;$BFBA  D0 F8     BNE L_BRS_($BFB4)_($BFBA) OK

		org $BFB2
		ldx #2
		jsr WaitVBLANK
		:$BFBC-* nop
		
; startup
		org $0600
start	
		sei
		lda #$0
		sta nmien
		sta dmactl
		lda portb
		ora #$02
		and #$fe
		sta portb

		cld
		ldx #$ff
		txs	

		stx FootstepLengthReg
		
		lda #<nmi
		sta $fffa
		lda #>nmi
		sta $fffb
		lda #<irq
		sta $fffe
		lda #>irq
		sta $ffff

		; init POKEY
		ldx #$08
		lda #$00
		sta skctl
		sta $d20e
clear	sta $d200,x
		dex
		bpl clear
		lda #$03
		sta skctl
		
		lda #%11010000 ; 17bit noise, 1/2 channels connected, channel 1 uses 1,79MHz
		sta audctl
		
		; init GTIA
		ldx #$0f
		lda #$00
cleargtia	sta $d000,x
		dex
		bpl cleargtia
		
		; set colors
		lda #white
		;lda #$ec
		sta colpf2
		lda #black
		;lda #$e0
		sta colpf1
		lda #$72
		sta colbak
		
		; pmg
		lda #$03
		sta pmcntl
		lda #>PMGMemory
		sta pmbase

		; clear memory
		lda #>bitmapscreen
		ldx #$1f
		jsr memclear
		
		; NTSC update
		lda PAL
		cmp #1
		beq @+
		jsr PrepareScreenPrepareNTSC
		lda #$FC
		sta PrepareScreenSetColor2
@		
		ldx #0
TileMainLoop
		lda TilesPatchAddress,x
		bmi PatchEnd
		tay
		inx
		lda TilesPatchAddress,x
		sta TileClearLoop+1
		inx
		lda TilesPatchAddress,x
		sta TileClearLoop+2
		inx
		lda #$00
TileClearLoop
		sta $ffff
		dec TileClearLoop+2
		dey
		bne TileClearLoop
		beq TileMainLoop
PatchEnd
		lda #$80
		sta $7676
		lda #$c0
		sta $7576
		lda #$f8
		sta $7476
		
		lda #<$67db
		ldx #>$67db
		jsr InvertTile
		;lda #<$6734
		;ldx #>$6734
		;jsr InvertTile
		

		; set screen
		lda #<dlist
		sta dlptr
		lda #>dlist
		sta dlptr+1
@		lda vcount
		bne @-
		lda #%00111110
		sta dmactl
		lda #$c0
		sta nmien

		
		jmp $0800

InvertTile
		sta $00
		stx $01
		ldx #$00
		ldy #$08
@		lda ($00,x)
		eor #$ff
		sta ($00,x)
		dec $01
		dey
		bne @-
		rts
		
TilesPatchAddress
		dta 8,a($777b)
		dta 8,a($7784)
		dta 7,a($7785-$100)
		dta 2,a($7789-$100)
		;dta 3+$40,a($7776-$100),$80,$c0,$07 
						; $ff,  $ff,$ff,$7f, $0f, $01, $01, $01
		dta $ff
		
memclear
		sta $03
		ldy #$00
		sty $02
		tya
mc1		sta ($02),y
		iny
		bne mc1
		inc $03
		dex
		bne mc1
		rts
		
		ert *>=$800
		
		run start		