;-------------------------------------------------------------------------------
; ZX X-MAS '19 - MAIN CODE (COMPILE THIZ)
;
; Load 48.sna or 128.sna into ZX Spin 0.7, then main.asm into Spin's
; assemblre, compile and RUN. Enable ULA Plus, it's nicer colors.
;
;       (/&&&/\&\  /%/  \&\  /%/   /%)(#)(&\ /%###&\ /###)  ()/%|  /&&&\
;         /%/  \&\/%/    \&\/%/,--,|#||#||#| |#| |#| |&&\     |#| (&___&)
;        /%/   /%/\&\    /%/\&\'--'|#||#||#| |###|#|  \&&|    |#|    (&&)
;       /&&&/)/%/  \&\  /%/  \&\   |#||#||#| |#| |#| (###/    |#| (&&&&/
;
; Copyright AbaddoN (C)2018-2019
; Code and gfx by: G.o.D. / AbaddoN
; Mzx by: ern0 / AbaddoN
;-------------------------------------------------------------------------------

INCLUDE 'memory_mapping.inc'		; memory mapping constants
;-------------------------------------------------------------------------------
ORG	MZX_INIT_PROC
INCBIN "mzx_player_song '19.bin"	; mzx player and tracked song data

;-------------------------------------------------------------------------------
ORG	MAIN_CODE_ADDR	; RANDOMIZE USR 28360 - CLEAR 24063
MAIN:
	di
; VVV for testing purposes --- 8< --- 8< --- 8< --- 8< --- 8< --- 8< --- 8< ---
	; ld	(saved_sp+1),sp		; save SP for returning to BASIC
	; ld	sp,0
	; exx						; save registers for returning to BASIC
	; push	bc
	; push	de
	; push	hl
	; exx
	; push	ix
	; push	iy

	; ld	a,0					; 0:normal colors / 1:ULA Plus
; ^^^ for testing purposes --- 8< --- 8< --- 8< --- 8< --- 8< --- 8< --- 8< ---

	; Initialize color "constants" and set palette if ULA Plus detected
	call	COLORS_INIT

	; Generate screen line addresses lookup table
	call	GEN_SCR_LOOKUP

	; Initialize music player
	call	MZX_INIT_PROC

	; Calculate scrolled KKU text gfx first phase
	call CALC_KKU_TEXT_PHASE

	; Put background screen
	; call	PUT_BACKGROUND_SCREEN	; for testing only

	; Set IM2 mode and process
	ld	de,IM2_STARTUP			; set IM 2 startup routine
	call	IM2_INIT
WAIT_LOOP:
	ei
	halt
	di

	ld	bc,$7FFE
	in	a,(c)
	bit	0,a
	jr	nz,WAIT_LOOP			; jump back until SPACE is pressed
	ld	b,$FE
	in	a,(c)
	bit	0,a
	jr	nz,WAIT_LOOP			; jump back until CAPS SHIFT is pressed

	ld	a,(STARTUP_PHASE+2)
	inc	a
	jr	nz,WAIT_LOOP

	ld	hl,DRAW_SNOWFALL		; stop snowfall
	ld	(hl),OPCODE_RET

	ld	de,$4820+12			; write "Hidden part found." text
	ld	ix,HiddenPartFoundText
	call	WRITE_TEXT
	ld	de,$48E0+12			; write hidden part's keys text
	ld	ix,HiddenPartKeys
	call	WRITE_TEXT

HIDDEN_PART_LOOP:
	ei
	halt
	di
HiddenPartLines:
	ld	e,175
	ld	bc,$FBFE
	in	a,(c)
	bit	0,a
	jr	nz,HP_No_Q			; jump if Q not pressed
	dec	e
	jr	nz,HP_No_Q
	inc	e
HP_No_Q:
	ld	b,$FD
	in	a,(c)
	bit	0,a
	jr	nz,HP_No_A			; jump if A not pressed
	inc	e
	ld	a,176
	cp	e
	jr	nz,HP_No_A
	dec	e
HP_No_A:
	ld	a,e
	ld	(HiddenPartLines+1),a
	call	SET_MLTCOL_HEIGHT

	ld	bc,$BFFE
	in	a,(c)
	bit	0,a
	jr	nz,HIDDEN_PART_LOOP		; jump back until ENTER is pressed

	ld	de,$4820+12			; erase "Hidden part found." text
	ld	ix,HiddenPartTextErase
	call	WRITE_TEXT
	ld	de,$48E0+12			; erase hidden part's keys text
	ld	ix,HiddenPartTextErase
	call	WRITE_TEXT

	ld	a,191				; set back multicolor area
	call	SET_MLTCOL_HEIGHT

	ld	hl,DRAW_SNOWFALL		; start snowfall
	ld	(hl),OPCODE_LD_SP_NNNN
	jp	WAIT_LOOP

; VVV for testing purposes --- 8< --- 8< --- 8< --- 8< --- 8< --- 8< --- 8< ---
	; di

	; call	IM2_TERMINATE				; Restore interrupt mode

	; call	MZX_MUTE_PROC			; Stop music

	; pop	iy
	; pop	ix
	; exx
	; pop	hl
	; pop	de
	; pop	bc
	; exx
; SAVED_SP:
	; ld	sp,0					; #selfmod - restore SP
	; ei
	; ret						; return to BASIC
; ^^^ for testing purposes --- 8< --- 8< --- 8< --- 8< --- 8< --- 8< --- 8< ---


;-------------------------------------------------------------------------------
; Write 1 line of text to screen. Only bitmap, no attr. Works only if text is
; inside 1/3 screen, and text's top position mod 8 = 0
; in:  IX: 0 terminated text
;      DE: screen memory address to write to
; out: -
; mod: AF,BC,HL,IX
; stack: 1

SYS_CHARS				EQU	$5C36	; 256 less than address of character set
								; (which starts with space and carries on
								; to the copyright symbol). Normally in
								; ROM, but you can set up your own in
								; RAM and make CHARS point to it.

WRITE_TEXT:

WT_TextLoop:
	ld	l,(ix+0)				; C=next character
	inc	ix
	
	xor	a					; since CHAR_EOS=0
	cp	l
	ret	z

	ld	h,a					; BC=character to write
	add	hl,hl				; CF=false because of CP 0 before
	add	hl,hl				; Chr$(c)*8+SYS_CHARS=chr bitmap addr.
	add	hl,hl

	ld	bc,(SYS_CHARS)			; HL=characters gfx addr. - $100
	add	hl,bc
	push	de
	ld	bc,$900
WT_CharLoop:
	ldi
	dec	e
	inc	d
	djnz	WT_CharLoop
	
	pop	de
	inc	e
	jr	WT_TextLoop

HiddenPartFoundText:
	defb	"Hidden part found.", 0
HiddenPartKeys:
	defb	"Q:up/A:dn/Ent:exit",0
HiddenPartTextErase:
	defb	"                  ", 0
;-------------------------------------------------------------------------------
; Generate screen line lookup table.
; Full 192 length table is generated to SCRLINE_LOOKUP memory area (it is in the
; contended RAM).
; For quick access to put KKU text the 32 length (64 bytes) portion of the table
; is copied to SCRLINE_LOOKUP_KKU memory address, after the IM 2 routine.
;
; in:  -
; out: -
; mod: AF,BC,DE,HL

GEN_SCR_LOOKUP:
	; generate the whole table into contended memory
	ld	de,$4000
	ld	hl,SCRLINE_LOOKUP

	ld	b,$C0
GSL_LineLoop:
	ld	(hl),e				; store low byte
	inc	h
	ld	(hl),d				; store high byte
	dec	h
	inc	l

	inc	d
	ld	a,d
	and	7
	jr	nz,GSL_NextLine
	ld	a,e
	add	a,$20
	ld	e,a
	jr	c,GSL_NextLine
	ld	a,d
	sub	8
	ld	d,a
GSL_NextLine:
	djnz	GSL_LineLoop

	; copy KKU text gfx screen line position
	ld	hl,SCRLINE_LOOKUP+KKU_GFX_Y_PX_POS
	ld	de,SCRPOS_LOOKUP_KKU
	ld	bc,$100*KKU_HEIGHT_PX+$FF
GSL_KKUPosGenLoop:
	ld	a,(hl)
	inc	h
	add	a,KKU_GFX_X_BYTE_POS	; horizontal start byte position
	ld	(de),a
	inc	de
	ldi
	dec	h
	djnz	GSL_KKUPosGenLoop
	ret

;-------------------------------------------------------------------------------
; Put background screen to screen area
PUT_BACKGROUND_SCREEN:
	; ld	hl,BACKGROUND_SCREEN
	ld	hl,LOADING_SCREEN
	ld	de,$4000
	ld	bc,$1C00
	ldir
	ret

;-------------------------------------------------------------------------------
INCLUDE 'im2.inc'				; IM 2 library

;-------------------------------------------------------------------------------
CALC_KKU_TEXT_PHASE:
	ld	hl,COS_LOOKUP_TABLE		; #selfmod: HL=sinus table pos.
	ld	a,(hl)				; A=bit position of scrolled area of KKU gfx
	cp	$FF
	jr	nz,CKT_NoCosTableOverflow
	ld	hl,COS_LOOKUP_TABLE		; end of cosine table, go to the start of it
	ld	a,(hl)
CKT_NoCosTableOverflow:
	inc	hl
	ld	e,(hl)				; E=byte position of scrolled area of KKU gfx
	inc	hl
	ld	(CALC_KKU_TEXT_PHASE+1),hl ; store cosine table position
	ld	c,a
	ld	b,0					; BC=(shift right 0-7)*2
	ld	d,0					; DE=add bytes

	ld	hl,KKU_PHASES_ADDR_LOOKUP
	add	hl,bc
	ld	c,(hl)
	inc	hl
	ld	b,(hl)
	ld	h,b
	ld	l,c
	add	hl,de
	ld	(DKT_KKU_STARTADDR_HL+1),hl ; area left top to draw in next frame
	ret

;-------------------------------------------------------------------------------
INCLUDE 'precalc.inc'			; precalculation routines
INCLUDE "startup_fx '19.inc"		; startup effects (low memory part of it)

;-------------------------------------------------------------------------------
; COLOR VARIABLES, LOOKUP TABLES, ETC.

; Colors for middle and top/bottom widescreen border
COLOR_BORDER_MID:
	db	$13
COLOR_BORDER_WIDESCREEEN:
	db	$13
; Color of 2 right bottom attributes
COLOR_RIGHTBOTTOM_ATTR:
	db	$13
; Color left bottom area
COLOR_LEFTBOTTOM_ATTR:
	db	$13

;-------------------------------------------------------------------------------
; Setup multicolor height
; in:  A:lines of multicolor from the top (0:1 line,1:2 lines,191:every line)
; out: -
; mod: AF
;$7813
OPCODE_RET		EQU	$C9
OPCODE_LD_DE_NNNN	EQU	$11
OPCODE_LD_SP_NNNN	EQU	$31

STARTUP_MLTCOL_HEIGHT:
SMH_Phase:
	ld	a,0
	inc	a
	ld	(SMH_Phase+1),a
	cp	192
	jr	nz,SET_MLTCOL_HEIGHT

	; put right bottom gfx and attrs
	ld	hl,$2B09
	ld	($5800-2),hl
	ld	hl,$5B00-2
	ld	a,(COLOR_RIGHTBOTTOM_ATTR)
	ld	(hl),a
	inc	l
	ld	(hl),a

	jp	CALC_SNOWFALL_SCR		; Calculate snowfall's screen position for
							; erase buffer filling and set IM2 snowfall
							; call address
SET_MLTCOL_HEIGHT:
	ld	hl,MLTCOL_CODE_PROC+$1C	; 1st line's LD DE,nnnn (0th line skipped)
	ld	bc,($100*OPCODE_LD_DE_NNNN)+OPCODE_RET
	ld	de,$19
SML_Loop:
	ld	(hl),b
	add	hl,de
	dec	a
	jr	nz,SML_Loop
	ld	(hl),c
	ret


;-------------------------------------------------------------------------------
; SNOWFALL ROUTINES

SNOWFLAKES_NUM		EQU	32		; number of snowflakes

; Move snowflakes down 1px and left/right random. Move to top if dropped out at
; the bottom and keep them horizontally between 80px and 239px.
; in:  -
; out: -
; mod: AF,BC,DE,HL

MOVE_SNOWFALL:
MS_StoredSeed_HL:
	ld	hl,SNOWFALL_RANDOM_MOVING ; #selfmod: random seed pointer
MS_NoRandomEnd:
	ld	de,SNOWFLAKES_POS
	ld	bc,$100*SNOWFLAKES_NUM
MS_Loop:
	ld	a,(de)				; snowflake's Y position
	
	inc	a					; move down
	cp	84
	jp	c,MS_CanMoveDown
	ld	a,68					; back to top if dropped out
	ld	(de),a
	inc	e
	push	hl
MS_StartXPos_HL:
	ld	hl,SNOWFLAKES_START_X_POS ; #selfmod: snowflakes start X positions
	inc	hl					 ; at the top
	ld	a,(hl)
	or	a
	jr	nz,MS_StartXNoEnd
	ld	hl,SNOWFLAKES_START_X_POS ; back to the lookup table start
	ld	a,(hl)
MS_StartXNoEnd:
	ld	(MS_StartXPos_HL+1),hl
	pop	hl
	inc	l
	ld	(de),a
	inc	e
	djnz	MS_Loop
	jr	MS_MoveEnd
MS_CanMoveDown:
	ld	(de),a
	inc	e

	ld	a,(de)				; move left/right
	add	a,(hl)				; add a random number $00, $01, $FF=-1
	inc	l

	cp	80					; left move can be max. 1 px,
	adc	a,c					; CF=1 if left overflow

	cp	239					; right move can be max. 1 px,
	ccf
	sbc	a,c					; CF=1 if right overflow

	ld	(de),a
	inc	e
	
	djnz	MS_Loop
MS_MoveEnd:
	add	a,l					; randomize a bit
	ld	l,a
 	ld	(MS_StoredSeed_HL+1),hl
	
	ld	hl,CALC_SNOWFALL_SCR	; set IM2 call to the next snowfall routine
	ld	(IM2_SNOWFALL_CALL+1),hl
	ret

; Calculate snowflakes screen addresses. Because it is the slowest routine of
; the 3 snowfall routines, the pixel position inside the screen byte and the
; corresponding byte mask is not calculated here, instead in the next routine.
; in:  -
; out: -
; mod: AF,BC,DE,HL

CALC_SNOWFALL_SCR:
	ld	(CSS_SavedSP+1),sp
CSS_CurrentAddrBuf:
	ld	sp,SNOWFLAKES_CALC_ADDR_2+SNOWFLAKES_CALC_BUF_LEN ; #selfmod: curr.buf

	ld	de,SNOWFLAKES_POS
	ld	b,SNOWFLAKES_NUM
CSS_Loop:
	ld	a,(de)				; snowflake's Y pos
	ld	l,a
	inc	e

	ld	h,SCRLINE_LOOKUP>>8
	ld	c,(hl)
	inc	h
	ld	h,(hl)
	ld	l,c					; HL=snowflake screen line beginning

	ld	a,(de)				; snowflake X pos
	inc	e

	ld	c,a					; calculate screen address
	and	$F8
	rra
	rra
	rra
	add	a,l
	ld	l,a					; HL=snowflake memory address
	push	hl					; store screen memory address
	push	bc					; store X position (in C)

	djnz	CSS_Loop

	; exchange buffers: one is for drawing snowflakes and one is for erasing
	ld	hl,SNOWFLAKES_CALC_ADDR_1
	sbc	hl,sp				; CF=false caused by and $F8+3*rra before
	ld	hl,SNOWFLAKES_CALC_ADDR_1+SNOWFLAKES_CALC_BUF_LEN
	jp	nz,CSS_NoChangeBuffer
	ld	hl,SNOWFLAKES_CALC_ADDR_2+SNOWFLAKES_CALC_BUF_LEN
CSS_NoChangeBuffer:
	ld	(CSS_CurrentAddrBuf+1),hl

	ld	(DS_CurrentDrawBuf+1),sp	; set addrs for drawing snowflakes
	ld	(DS_CurrentEraseBuf+1),hl

CSS_SavedSP:
	ld	sp,$1313				; #selfmod: restore SP what is used in loop
	
	ld	hl,DRAW_SNOWFALL		; set IM2 call to the next snowfall routine
	ld	(IM2_SNOWFALL_CALL+1),hl
	ret

; Draw snowflakes
DRAW_SNOWFALL:
	ld	(DS_SavedSP+1),sp

DS_CurrentEraseBuf:
	ld	de,$1313				; #selfmod: current erase buffer
	dec	de
DS_CurrentDrawBuf:
	ld	sp,$1313				; #selfmod: current draw buffer

	ld	bc,$100*SNOWFLAKES_NUM
DS_ShowFlakesLoop:
	ld	a,(de)				; HL=erase screen address
	ld	h,a
	dec	e
	ld	a,(de)
	ld	l,a
	dec	e
	ld	(hl),c				; erase snowflake at previous phase
	dec	e
	dec	e

	pop	hl					; L=draw X position
	ld	a,l
	and	$07
	ld	l,a
	ld	h,CSS_PlotBit>>8
	ld	a,(hl)				; A=mask for plotting (1 bit is set)

	pop	hl					; HL=draw screen address
	or	(hl)
	ld	(hl),a				; put snowflake

	djnz	DS_ShowFlakesLoop

DS_SavedSP:
	ld	sp,$1313				; #selfmod: restore SP what is used in loop

	ld	hl,MOVE_SNOWFALL		; set IM2 call to the first snowfall routine
	ld	(IM2_SNOWFALL_CALL+1),hl
	ret

SNOWFLAKES_START_X_POS:
	defb	$7E, $A7, $BB, $93, $D2, $84, $E4, $B8
	defb	$EA, $7E, $90, $88, $7E, $EE, $E7, $6A
	defb	$91, $D8, $EF, $85, $98, $87, $BD, $6D
	defb	$65, $B6, $7A, $C0, $C2, $B0, $89, $00

; ALIGN	$100
SNOWFALL_RANDOM_MOVING	EQU	$7D00
ORG	SNOWFALL_RANDOM_MOVING
	defb	$FF, $00, $01, $00, $01, $00, $00, $01
	defb	$00, $FF, $01, $01, $00, $FF, $00, $00
	defb	$00, $00, $00, $FF, $01, $00, $00, $00
	defb	$01, $FF, $01, $01, $FF, $01, $00, $01
	defb	$00, $01, $00, $00, $00, $00, $01, $00
	defb	$FF, $00, $01, $01, $01, $00, $FF, $FF
	defb	$00, $00, $00, $00, $01, $00, $00, $01
	defb	$00, $00, $00, $01, $00, $00, $01, $00
	defb	$00, $00, $FF, $01, $FF, $01, $01, $FF
	defb	$FF, $01, $FF, $01, $FF, $FF, $FF, $00
	defb	$01, $00, $00, $FF, $00, $00, $00, $00
	defb	$00, $00, $00, $00, $FF, $01, $00, $00
	defb	$FF, $00, $FF, $00, $01, $00, $00, $FF
	defb	$00, $00, $00, $01, $01, $FF, $00, $00
	defb	$00, $00, $01, $00, $FF, $00, $FF, $FF
	defb	$00, $00, $FF, $01, $00, $01, $FF, $00
	defb	$00, $FF, $00, $00, $00, $00, $00, $00
	defb	$01, $FF, $01, $00, $FF, $FF, $01, $01
	defb	$FF, $01, $FF, $00, $00, $00, $01, $FF
	defb	$FF, $01, $FF, $01, $FF, $00, $00, $01
	defb	$00, $FF, $01, $00, $00, $FF, $FF, $00
	defb	$01, $FF, $FF, $00, $00, $00, $01, $00
	defb	$00, $FF, $00, $00, $FF, $01, $00, $00
	defb	$01, $00, $00, $FF, $00, $00, $01, $00
	defb	$01, $00, $00, $01, $FF, $01, $01, $01
	defb	$01, $FF, $FF, $FF, $01, $00, $FF, $FF
	defb	$00, $01, $01, $FF, $00, $00, $00, $00
	defb	$01, $FF, $00, $01, $00, $00, $00, $00
	defb	$00, $00, $00, $00, $01, $FF, $00, $01
	defb	$FF, $01, $FF, $01, $00, $01, $FF, $01
	defb	$00, $01, $00, $00, $00, $FF, $01, $FF
	defb	$00, $FF, $FF, $FF, $00, $00, $01, $00


; ALIGN	$100
CSS_PlotBit	EQU	$7E00
ORG	CSS_PlotBit
	defb	$80,$40,$20,$10,$08,$04,$02,$01		; must be $100 aligned
SNOWFLAKES_POS:	; Y pos, X pos
	defb	$4F, $D8, $52, $B2, $4F, $75, $4F, $BA	; Snowflakes  1- 4
	defb	$4D, $DA, $4C, $80, $4F, $5C, $53, $94	; Snowflakes  5- 8
	defb	$45, $86, $4D, $7A, $4E, $D6, $46, $82	; Snowflakes  9-12
	defb	$47, $A7, $4D, $EF, $49, $D3, $48, $92	; Snowflakes 13-16
	defb	$52, $BF, $4C, $A8, $45, $D7, $46, $9D	; Snowflakes 16-20
	defb	$4A, $54, $52, $81, $4E, $A8, $48, $9E	; Snowflakes 21-24
	defb	$49, $7E, $50, $6A, $44, $C7, $52, $68	; Snowflakes 25-28
	defb	$48, $A9, $50, $A8, $4E, $6A, $50, $B1	; Snowflakes 29-32

; ALIGN	$100
SNOWFLAKES_CALC_BUF_LEN	EQU	4*SNOWFLAKES_NUM

SNOWFLAKES_CALC_ADDR_1	EQU	$7F00
ORG	SNOWFLAKES_CALC_ADDR_1
	defs	SNOWFLAKES_CALC_BUF_LEN, $13
SNOWFLAKES_CALC_ADDR_2:
	defs	SNOWFLAKES_CALC_BUF_LEN, $13

;-------------------------------------------------------------------------------
; Screen line address lookup table.
ORG	SCRLINE_LOOKUP
	defs	2*$100

;-------------------------------------------------------------------------------
;-------------------------------------------------------------------------------
; "KELLEMES KARÁCSONYI ÜNNEPEKET!" gfx (length: 2752 ($0AC0) bytes)
ORG	KKU_ORIG_TEXT_GFX_ADDR
INCLUDE "kku_text '19.inc"

;-------------------------------------------------------------------------------
;-------------------------------------------------------------------------------
ORG	PRECALC_HIGH_MEM_FX
INCLUDE 'startup_fx_high.inc'
INCLUDE "colors_init '19.inc"

;-------------------------------------------------------------------------------
;-------------------------------------------------------------------------------
ORG	IM2_PROC_ADDR

; IM2 process for scrolling KKU text, make snowfall and play music.
IM2_PROC:
	; Draw KKU text gfx - HiMem
	call	DRAW_KKU_TEXT_PROC			; 11764T

	; Delay for 86T
	ld	b,6
IM2_WaitTop:
	djnz	IM2_WaitTop
	add	a,$13

	; Draw multicolor lines - HiMem
	ld	hl,MLTCOL_LINES_ATTR_ADDR+2	; 10T
								; skip 1st 2 attr. because 2 LDI is
								; missing in the 1st line, replaced
								; by LD A,[border_col] / OUT ($FE),A
	call	MLTCOL_CODE_PROC

	; Set wide screen bottom dark border
	ld	a,(COLOR_BORDER_WIDESCREEEN)	; 13T
	out	($FE),a					; 11T

	; Play music - LoMem-contended
	call	MZX_PLAY_PROC

	; Calculate scrolled KKU text gfx next phase - LoMem-contended
	call CALC_KKU_TEXT_PHASE

IM2_SNOWFALL_CALL:
	; Move and draw snowfall
	; call	MOVE_SNOWFALL
	call	STARTUP_MLTCOL_HEIGHT	; at first interval do mltcol roll down
							; STARTUP_MLTCOL_HEIGHT will set this call
							; to MOVE_SNOWFALL when it finished
	ei
	reti

;-------------------------------------------------------------------------------
; Draw KKU text gfx. It takes constant time, so can be run at the top part of
; frame.
; in:  -
; out: -
; mod: AF,BC,DE,HL,IXL,HL'
DRAW_KKU_TEXT_PROC:
	ld	(DKT_SavedSP+1),sp		; 20T
	ld	sp,SCRPOS_LOOKUP_KKU	; 10T
DKT_KKU_STARTADDR_HL:
	ld	hl,$1313				; 10T / #selfmod: KKU gfx to put start addr
	exx
	ld	hl,KKU_GFX_LEFT_MASK	; 10T
	ld	ixl,KKU_HEIGHT_PX		; 11T
	exx
DKT_Loop:
	pop	de					; 10T / DE=screen address
	ld	a,(hl)				; 7T	 / A=1st byte of KKU's line
	inc	hl					; 4T
	exx						; 4T
	and	(hl)					; 7T  / mask the left side of KKU gfx
	inc	l					; 4T
	or	(hl)					; 7T
	inc	l					; 4T
	exx						; 4T
	ld	(de),a				; 7T  / put the line's 1st byte to screen
	inc	e					; 4T
	ldi						; 19*16T=304T
	ldi						;    / put the next 19 bytes to screen
	ldi
	ldi
	ldi
	ldi
	ldi
	ldi
	ldi
	ldi
	ldi
	ldi
	ldi
	ldi
	ldi
	ldi
	ldi
	ldi
	ldi
	ld	a,(hl)				; 7T  / mask the right side of KKU gfx.
	; and	%11111100				; 7T
	; or	%00000001				; 7T
	and	%11111111				; 7T
	or	%00000000				; 7T
	ld	(de),a				; 7T
	
	ld	de,KKU_GFX_WIDTH_BYTE-SCREEN_WIDTH_BYTES+KKU_GFX_X_BYTE_POS+1
							; ^^^ 10T
	add	hl,de				; 15T

	dec	ixl					; 8T
	jp	nz,DKT_Loop			; 10T

DKT_SavedSP:
	ld	sp,$1313				; 10T / #selfmod: restore SP
	ret						; 10T --- Sum with a call instr.:11764T


SCRPOS_LOOKUP_KKU:
	defw	$1313, $1313, $1313, $1313, $1313, $1313, $1313, $1313
	defw	$1313, $1313, $1313, $1313, $1313, $1313, $1313, $1313
	defw	$1313, $1313, $1313, $1313, $1313, $1313, $1313, $1313
	defw	$1313, $1313, $1313, $1313, $1313, $1313, $1313, $1313

KKU_GFX_LEFT_MASK:
	defb	%11111111, %00000000
	defb	%11111111, %00000000
	defb	%11111111, %00000000
	defb	%11111111, %00000000
	defb	%11111111, %00000000
	defb	%01111111, %00000000
	defb	%01111111, %00000000
	defb	%00111111, %00000000
	defb	%00011111, %00000000
	defb	%00001111, %00000000
	defb	%00001111, %00000000
	defb	%00001111, %00000000
	defb	%00001111, %00000000
	defb	%00001111, %00000000
	defb	%00011111, %00000000
	defb	%00011111, %00000000
	defb	%00001111, %00000000
	defb	%00001111, %00000000
	defb	%00000111, %00000000
	defb	%00000111, %00000000
	defb	%00000111, %00000000
	defb	%00000011, %00000000
	defb	%00000011, %00000000
	defb	%00000011, %00000000
	defb	%00000011, %00000000
	defb	%00000001, %00000000
	defb	%00000001, %10000000
	defb	%00000001, %01000000
	defb	%00000000, %11000000
	defb	%00000000, %11100000
	defb	%00000000, %11110000
	defb	%00000000, %11111000

;-------------------------------------------------------------------------------
; Multicolor attribute of lines. ULA Plus and normal color.
ORG	MLTCOL_ULAPLUS_ATTR
INCLUDE 'mltcol_lines_attr_ulaplus.inc'
ORG	MLTCOL_NORMCOL_ATTR
INCLUDE 'mltcol_lines_attr_normcol.inc'

;-------------------------------------------------------------------------------
; Background's right area attributes. ULA Plus and normal color.
ORG	BKG_RIGHT_ATTR_ULAPLUS
INCLUDE "background_right_attr_8x8_22by24_ulaplus '19.inc"
ORG	BKG_RIGHT_ATTR_NORMCOL
INCLUDE "background_right_attr_8x8_22by24_normcol '19.inc"

;-------------------------------------------------------------------------------
; Background tree gfx and ULA Plus colors 8+1 bytes. After that only the
; attributes of normal colors. When using normal colors, the BKG_TREE_IMAGE's
; +1 attr bytes has to be changed to BKG_TREE_NORMCOL_ATTR attribute bytes.
ORG BKG_TREE_IMAGE
INCLUDE "background_tree_8x8_15by24_ulaplus '19.inc"
ORG	BKG_TREE_NORMCOL_ATTR
INCLUDE "background_tree_attr_8x8_15by24_normcol '19.inc"

;-------------------------------------------------------------------------------
; Images for vaporizing in. They are separated because only a small area can be
; done in one frame, so it takes 8 frame to do one vaporizing phase.
ORG BKG_SOCKS_IMAGE_1
INCLUDE 'background_socks_8x8_1_22by1.inc'
BKG_SOCKS_IMAGE_2:
INCLUDE 'background_socks_8x8_2_20by7.inc'
BKG_SOCKS_IMAGE_3:
INCLUDE 'background_socks_8x8_3_9by1.inc'

ORG BKG_BELLS_IMAGE_1
INCLUDE 'background_bells_8x8_1_3by1.inc'
BKG_BELLS_IMAGE_2:
INCLUDE 'background_bells_8x8_2_10by1.inc'
BKG_BELLS_IMAGE_3:
INCLUDE 'background_bells_8x8_3_17by2.inc'
BKG_BELLS_IMAGE_4:
INCLUDE 'background_bells_8x8_4_2by2.inc'
BKG_BELLS_IMAGE_5:
INCLUDE 'background_bells_8x8_5_12by3.inc'
BKG_BELLS_IMAGE_6:
INCLUDE 'background_bells_8x8_6_3by1.inc'

;-------------------------------------------------------------------------------
; Scrolled in texts. Only bitmap w/o attributes.
ORG	SCROLL_ABADDON_IMAGE
INCLUDE 'scrolltext_abaddon_2by9.inc'

ORG	SCROLL_SCENERZ_IMAGE
INCLUDE "scrolltext_scenerz_7by2 '19.inc"

ORG	SCROLL_SINCLAIR_IMAGE	; in fact, it has been changed to www.abaddon.hu
INCLUDE 'scrolltext_abaddon_hu_7by1.inc'


;-------------------------------------------------------------------------------
; Background screen in ZX Spectrum SCR format and ULA Plus palette. Only for
; testing purposes.
ORG	LOADING_SCREEN
; INCBIN 'loading_screen_8x8_ulaplus.scr'
; INCBIN 'loading_screen_8x8_normcol.scr'
