; (c) 1993-1996, 2006 Karel 'Clock' Kulhavy
;       tune (c) 2006 Alan 'Factor6' Petrik
;
;    This program is free software; you can redistribute it and/or modify
;    it under the terms of the GNU General Public License as published by
;    the Free Software Foundation; either version 2 of the License, or
;    (at your option) any later version.
;
;    This program is distributed in the hope that it will be useful, 
;    but WITHOUT ANY WARRANTY; without even the implied warranty of 
;    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;    GNU General Public License for more details.
;  
;    You should have received a copy of the GNU General Public License
;    along with this program; if not, write to the Free Software
;    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

screensrc	equ	29825
itemtextdest	equ	22502
numberdest	equ	itemtextdest+16
nrooms		equ 69 ; More don't fit when the intro starts at 59565
sctarget	equ 20703 ; Where the scroll character is being printed
needitems	equ 0x0395 ; 397 total, 2 uncollectable, BCD format!
ZACMIS	EQU	32768
startroom	equ 0 ; 0-68 is valid

	org 27000
firstaddress
ch1	defb 0x00, 0x00, 0x00, 0x00, 0x02, 0x03, 0x52, 0xf7 ; Joystick
ch2	defb 0x3c, 0x3c, 0x7e, 0x2c, 0x7c, 0x3c, 0x98, 0x7c ; Head
ch3	defb 0xff, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3d ; Table
ch4	defb 0x3f, 0x77, 0x77, 0x77, 0x6d, 0xff, 0xc4, 0xc4 ; Body
ch5	defb 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x52, 0xf7 ; Joystick moved
	
tunestart ; main voice, second voice. The third used to be length but was removed as unnecessary
          ; to save space.

	defb 0x3c, 0x29
	defb 0x41, 0x29
	defb 0x44, 0x29

	defb 0x3c, 0x29
	defb 0x41, 0x29
	defb 0x44, 0x29

	defb 0x3c, 0x29
	defb 0x41, 0x29
	defb 0x44, 0x29

	defb 0x3c, 0x29
	defb 0x41, 0x29
	defb 0x44, 0x29

	defb 0x3c, 0x29
	defb 0x41, 0x29
	defb 0x44, 0x29

	defb 0x3c, 0x29
	defb 0x41, 0x29
	defb 0x44, 0x29

	defb 0x3c, 0x29
	defb 0x41, 0x29
	defb 0x44, 0x29

	defb 0x3c, 0x29
	defb 0x41, 0x29
	defb 0x44, 0x29

	defb 0x3d, 0x25
	defb 0x41, 0x25
	defb 0x44, 0x25

	defb 0x3d, 0x25
	defb 0x41, 0x25
	defb 0x44, 0x25

	defb 0x3d, 0x25
	defb 0x41, 0x25
	defb 0x44, 0x25

	defb 0x3d, 0x25
	defb 0x41, 0x25
	defb 0x44, 0x25

	defb 0x3d, 0x2a
	defb 0x42, 0x2a
	defb 0x46, 0x2a

	defb 0x3d, 0x2a
	defb 0x42, 0x2a
	defb 0x46, 0x2a

	defb 0x3c, 0x24
	defb 0x43, 0x24
	defb 0x46, 0x24

	defb 0x3c, 0x2b
	defb 0x40, 0x2b
	defb 0x43, 0x2b

	defb 0x35, 0x29
	defb 0x38, 0x29
	defb 0x3c, 0x29

	defb 0x38, 0x29
	defb 0x3c, 0x29
	defb 0x41, 0x29

	defb 0x3c, 0x29
	defb 0x41, 0x29
	defb 0x44, 0x29

	defb 0x41, 0x29
	defb 0x44, 0x29
	defb 0x48, 0x29

	defb 0x48, 0x30
	defb 0x43, 0x30
	defb 0x46, 0x30

	defb 0x3c, 0x30
	defb 0x43, 0x30
	defb 0x46, 0x30

	defb 0x3c, 0x30
	defb 0x43, 0x30
	defb 0x46, 0x30

	defb 0x3c, 0x30
	defb 0x43, 0x30
	defb 0x48, 0x30

	defb 0x48, 0x29
	defb 0x41, 0x29
	defb 0x44, 0x29
	
	defb 0x3c, 0x29
	defb 0x41, 0x29
	defb 0x44, 0x29
	
	defb 0x49, 0x31
	defb 0x41, 0x31
	defb 0x46, 0x31
	
	defb 0x3d, 0x31
	defb 0x41, 0x31
	defb 0x46, 0x31
	
	defb 0x48, 0x2e
	defb 0x41, 0x2e
	defb 0x44, 0x2e
	
	defb 0x3c, 0x2e
	defb 0x41, 0x2e
	defb 0x44, 0x2e
	
	defb 0x46, 0x2b
	defb 0x40, 0x2b
	defb 0x43, 0x2b
	
	defb 0x3a, 0x28
	defb 0x40, 0x28
	defb 0x43, 0x28

	defb 0x35, 0x29
	defb 0x38, 0x29
	defb 0x3c, 0x29
	
	defb 0x38, 0x29
	defb 0x3c, 0x29
	defb 0x41, 0x29
	
	defb 0x3c, 0x29
	defb 0x41, 0x29
	defb 0x44, 0x29
	
	defb 0x41, 0x29
	defb 0x44, 0x29
	defb 0x48, 0x29
	
	defb 0x48, 0x30
	defb 0x43, 0x30
	defb 0x46, 0x30
	
	defb 0x3c, 0x30
	defb 0x43, 0x30
	defb 0x46, 0x30
	
	defb 0x3c, 0x30
	defb 0x43, 0x30
	defb 0x46, 0x30
	
	defb 0x3c, 0x30
	defb 0x43, 0x30
	defb 0x48, 0x30
	
	defb 0x48, 0x31
	defb 0x41, 0x31
	defb 0x44, 0x31
	
	defb 0x3c, 0x31
	defb 0x41, 0x31
	defb 0x44, 0x31
	
	defb 0x49, 0x2e
	defb 0x41, 0x2e
	defb 0x46, 0x2e
	
	defb 0x3d, 0x2e
	defb 0x41, 0x2e
	defb 0x46, 0x2e
	
	defb 0x48, 0x30
	defb 0x40, 0x30
	defb 0x43, 0x30
	
	defb 0x3c, 0x30
	defb 0x40, 0x30
	defb 0x43, 0x30
	
	defb 0x46, 0x28
	defb 0x40, 0x28
	defb 0x43, 0x28

	defb 0x3a, 0x28
	defb 0x40, 0x28
	defb 0x43, 0x28
	
	;------------------
	defb 0x41, 0x29
	defb 0x00, 0x35
	defb 0x41, 0x24
	defb 0x00, 0x30

	defb 0x00, 0x29
	defb 0x00, 0x35
	defb 0x00, 0x24
	defb 0x00, 0x30

	defb 0x00, 0x29
	defb 0x00, 0x35
	defb 0x00, 0x24
	defb 0x00, 0x30

	defb 0x00, 0x29
	defb 0x00, 0x35
	defb 0x00, 0x24
	defb 0x00, 0x30
	;------------------
	defb 0x48, 0x29
	defb 0x46, 0x35
	defb 0x48, 0x24
	defb 0x46, 0x30
                       
	defb 0x45, 0x29
	defb 0x45, 0x35
	defb 0x41, 0x24
	defb 0x41, 0x30
                       
	defb 0x41, 0x29
	defb 0x41, 0x35
	defb 0x45, 0x24
	defb 0x46, 0x30
                       
	defb 0x48, 0x29
	defb 0x46, 0x35
	defb 0x45, 0x24
	defb 0x46, 0x30
                       
	defb 0x48, 0x2c
	defb 0x4a, 0x38
	defb 0x48, 0x27
	defb 0x4a, 0x33
                       
	defb 0x4b, 0x2c
	defb 0x4a, 0x38
	defb 0x4b, 0x27
	defb 0x4a, 0x33
                       
	defb 0x48, 0x2c
	defb 0x48, 0x38
	defb 0x48, 0x27
	defb 0x48, 0x33
                       
	defb 0x48, 0x2c
	defb 0x48, 0x38
	defb 0x48, 0x27
	defb 0x48, 0x33
                       
	defb 0x4d, 0x29
	defb 0x4d, 0x35
	defb 0x4d, 0x24
	defb 0x4d, 0x30
                       
	defb 0x4c, 0x29
	defb 0x4c, 0x35
	defb 0x4a, 0x24
	defb 0x4a, 0x30
                       
	defb 0x48, 0x29
	defb 0x46, 0x35
	defb 0x45, 0x24
	defb 0x46, 0x30
	               
	defb 0x48, 0x29
	defb 0x48, 0x35
	defb 0x45, 0x24
	defb 0x45, 0x30
	               
	defb 0x49, 0x2c
	defb 0x48, 0x38
	defb 0x46, 0x27
	defb 0x48, 0x33
	               
	defb 0x49, 0x2c
	defb 0x49, 0x38
	defb 0x46, 0x27
	defb 0x46, 0x33
	               
	defb 0x4d, 0x2c
	defb 0x4d, 0x38
	defb 0x4d, 0x27
	defb 0x4d, 0x33
	               
	defb 0x4d, 0x2c
	defb 0x4d, 0x38
	defb 0x4d, 0x27
	defb 0x4d, 0x33
	               
	defb 0x48, 0x29
	defb 0x46, 0x35
	defb 0x48, 0x24
	defb 0x46, 0x30
                       
	defb 0x45, 0x29
	defb 0x45, 0x35
	defb 0x41, 0x24
	defb 0x41, 0x30
                       
	defb 0x41, 0x29
	defb 0x41, 0x35
	defb 0x45, 0x24
	defb 0x46, 0x30
                       
	defb 0x48, 0x29
	defb 0x46, 0x35
	defb 0x45, 0x24
	defb 0x46, 0x30
	               
	defb 0x48, 0x2c
	defb 0x4a, 0x38
	defb 0x48, 0x27
	defb 0x4a, 0x33
	               
	defb 0x4b, 0x2c
	defb 0x4a, 0x38
	defb 0x4b, 0x27
	defb 0x4a, 0x33
	               
	defb 0x48, 0x2c
	defb 0x48, 0x38
	defb 0x48, 0x27
	defb 0x48, 0x33
	               
	defb 0x48, 0x2c
	defb 0x48, 0x38
	defb 0x48, 0x27
	defb 0x48, 0x33
	               
	defb 0x4d, 0x29
	defb 0x4d, 0x35
	defb 0x4d, 0x24
	defb 0x4d, 0x30
                       
	defb 0x4c, 0x29
	defb 0x4c, 0x35
	defb 0x4a, 0x24
	defb 0x4a, 0x30
                       
	defb 0x48, 0x29
	defb 0x46, 0x35
	defb 0x45, 0x24
	defb 0x46, 0x30
                       
	defb 0x48, 0x29
	defb 0x48, 0x35
	defb 0x45, 0x24
	defb 0x45, 0x30
	               
	defb 0x49, 0x2c
	defb 0x48, 0x38
	defb 0x46, 0x27
	defb 0x48, 0x33
	               
	defb 0x49, 0x2c
	defb 0x49, 0x38
	defb 0x46, 0x27
	defb 0x46, 0x33
	               
	defb 0x4d, 0x2c
	defb 0x4d, 0x38
	defb 0x4d, 0x27
	defb 0x4d, 0x33
	               
	defb 0x4d, 0x2c
	defb 0x4d, 0x38
	defb 0x4d, 0x27
	defb 0x4d, 0x33
	
	defb 0x48, 0x29
	defb 0x46, 0x35
	defb 0x48, 0x24
	defb 0x46, 0x30
                       
	defb 0x45, 0x29
	defb 0x45, 0x35
	defb 0x41, 0x24
	defb 0x41, 0x30
                       
	defb 0x41, 0x29
	defb 0x41, 0x35
	defb 0x45, 0x24
	defb 0x46, 0x30
                       
	defb 0x48, 0x29
	defb 0x46, 0x35
	defb 0x45, 0x24
	defb 0x46, 0x30
	               
	defb 0x48, 0x2c
	defb 0x4a, 0x38
	defb 0x48, 0x27
	defb 0x4a, 0x33
	               
	defb 0x4b, 0x2c
	defb 0x4a, 0x38
	defb 0x4b, 0x27
	defb 0x4a, 0x33
	               
	defb 0x48, 0x2c
	defb 0x48, 0x38
	defb 0x48, 0x27
	defb 0x48, 0x33
	               
	defb 0x48, 0x2c
	defb 0x48, 0x38
	defb 0x48, 0x27
	defb 0x48, 0x33
	               
	defb 0x4d, 0x29
	defb 0x4d, 0x35
	defb 0x4d, 0x24
	defb 0x4d, 0x30
                       
	defb 0x4c, 0x29
	defb 0x4c, 0x35
	defb 0x4a, 0x24
	defb 0x4a, 0x30
                       
	defb 0x48, 0x29
	defb 0x46, 0x35
	defb 0x45, 0x24
	defb 0x46, 0x30
                       
	defb 0x48, 0x29
	defb 0x48, 0x35
	defb 0x45, 0x24
	defb 0x45, 0x30
	               
	defb 0x49, 0x2c
	defb 0x48, 0x38
	defb 0x46, 0x27
	defb 0x48, 0x33
	               
	defb 0x49, 0x2c
	defb 0x49, 0x38
	defb 0x46, 0x27
	defb 0x46, 0x33
	               
	defb 0x4d, 0x2c
	defb 0x4d, 0x38
	defb 0x4d, 0x27
	defb 0x4d, 0x33
	               
	defb 0x4d, 0x2c
	defb 0x4d, 0x38
	defb 0x4d, 0x27
	defb 0x4d, 0x33
	
	defb 0x48, 0x29
	defb 0x46, 0x35
	defb 0x48, 0x24
	defb 0x46, 0x30
                       
	defb 0x45, 0x29
	defb 0x45, 0x35
	defb 0x41, 0x24
	defb 0x41, 0x30
                       
	defb 0x41, 0x29
	defb 0x41, 0x35
	defb 0x45, 0x24
	defb 0x46, 0x30
                       
	defb 0x48, 0x29
	defb 0x46, 0x35
	defb 0x45, 0x24
	defb 0x46, 0x30
                       
	defb 0x48, 0x2c
	defb 0x4a, 0x38
	defb 0x48, 0x27
	defb 0x4a, 0x33
                       
	defb 0x4b, 0x2c
	defb 0x4a, 0x38
	defb 0x4b, 0x27
	defb 0x4a, 0x33
                       
	defb 0x48, 0x2c
	defb 0x48, 0x38
	defb 0x48, 0x27
	defb 0x48, 0x33
                       
	defb 0x48, 0x2c
	defb 0x48, 0x38
	defb 0x48, 0x27
	defb 0x48, 0x33

	defb 0x4d, 0x29
	defb 0x4d, 0x35
	defb 0x4d, 0x24
	defb 0x4d, 0x30

	defb 0x4c, 0x29
	defb 0x4c, 0x35
	defb 0x4a, 0x24
	defb 0x4a, 0x30

	defb 0x48, 0x29
	defb 0x46, 0x35
	defb 0x45, 0x24
	defb 0x46, 0x30

	defb 0x48, 0x29
	defb 0x48, 0x35
	defb 0x45, 0x24
	defb 0x45, 0x30

	defb 0x49, 0x2c
	defb 0x48, 0x38
	defb 0x46, 0x27
	defb 0x48, 0x33

	defb 0x49, 0x2c
	defb 0x49, 0x38
	defb 0x46, 0x27
	defb 0x46, 0x33

	defb 0x4d, 0x2c
	defb 0x4d, 0x38
	defb 0x4d, 0x27
	defb 0x4d, 0x33

	defb 0x4d, 0x2c
	defb 0x4d, 0x38
	defb 0x4d, 0x27
	defb 0x4d, 0x33

	;------ DJ clock added

	defb 0x49, 0x2c
	defb 0x48, 0x38
	defb 0x46, 0x27
	defb 0x48, 0x33

	defb 0x49, 0x2c
	defb 0x49, 0x38
	defb 0x46, 0x27
	defb 0x46, 0x33

	defb 0x49, 0x2c
	defb 0x48, 0x38
	defb 0x46, 0x27
	defb 0x48, 0x33

	defb 0x49, 0x2c
	defb 0x49, 0x38
	defb 0x46, 0x27
	defb 0x46, 0x33

	defb 0x4d, 0x2c
	defb 0x4d, 0x38
	defb 0x4d, 0x27
	defb 0x4d, 0x33

	defb 0x4d, 0x2c
	defb 0x4d, 0x38
	defb 0x4d, 0x27
	defb 0x4d, 0x33

	defb 0x00, 0x2c
	defb 0x00, 0x38
	defb 0x00, 0x27
	defb 0x00, 0x33

	defb 0x00, 0x2c
	defb 0x00, 0x38
	defb 0x00, 0x27
	defb 0x00, 0x33

	defb 0x48, 0x29
	defb 0x46, 0x35
	defb 0x48, 0x24
	defb 0x46, 0x30
                       
	defb 0x45, 0x29
	defb 0x45, 0x35
	defb 0x41, 0x24
	defb 0x41, 0x30
                       
	defb 0x41, 0x29
	defb 0x41, 0x35
	defb 0x41, 0x24
	defb 0x41, 0x30

	defb 0x00, 0x29
	defb 0x00, 0x35
	defb 0x00, 0x24
	defb 0x00, 0x30

	defb 0x00, 0x29
	defb 0x00, 0x35
	defb 0x00, 0x24
	defb 0x00, 0x30

	defb 0x00, 0x29
	defb 0x00, 0x35
	defb 0x00, 0x24
	defb 0x00, 0x30

	defb 0x00, 0x29
	defb 0x00, 0x35
	defb 0x00, 0x24
	defb 0x00, 0x30


tuneend
tunelen	equ tuneend-tunestart
iter	defb 1 ; Frame counter for the current tone
addr	defw tunestart
ITEMTEXT	DEFM	"Items collected "
FCIFS 		defm	"0000"

halftones ; 16 halftones
	; Starts at C2 (0x24)
	; C 261.6 Hz is 1097.2299264
	; halftone 1.05946309435929526455
	defw	 274, 291, 308, 326
	defw	 346, 366, 388, 411
	defw	 435, 461, 489, 518
	defw	 549, 581, 616, 652
	defw	 691, 732, 776, 822
	defw	 871, 923, 978,1036
	defw	1097,1162,1232,1305
	defw	1382,1465,1552,1644
	defw	1742,1845,1955,2071
	defw	2194,2325,2463,2610
	defw	2765,2929 ;3103,3288
	;defw	3483,3691,3910,4143
	;defw	4389,4650,4926,5219

	; keyboard test routine
kbt1:	LD A,191 ; Enter halfrow
	IN A,(0xfe)
	AND 1 ; Lowest bit is the edge key
	RET NZ
	POP HL ; Destroy return address
	JP one ; 60430

pokedprint
	push	hl
	ld	hl,ch1
	ld	(poke3),hl
	pop	hl
	call	print
	push	hl
	ld	hl,syscharset
	ld	(poke3),hl
	pop	hl
	ret

kbtest:
	LD A,191
	IN A,(0xfe) ; Keyboard read
	AND 1
	RET NZ
	POP HL ; Destroy return address
intogame:	CALL WODE
	OR A
	JP Z,one ; 60430 probably jump if not completed game
gaming:	
	LD DE,str1
	LD HL, 20527
	LD BC,2 ; Length, BC=2
	CALL pokedprint ; PR-STRING, DE adress, BC length
	LD L,79 ; HL=20606
	LD C,2 ; BC=2
	CALL pokedprint ; Print position 1 of the gaming guy
	call tensyn
	LD L, 47 ; HL=20527
	inc c ; BC=1 - length
	CALL pokedprint ; Print position 2 of the gaming guy
	CALL tensyn
	CALL kbt1 
	JR gaming

hexdigit:
	and	15
	cp	10
	jr	c,nohex
	add	a,'A'-('9'+1)
nohex:	add	a,48
	ld	(de),a
	inc	de
	ret

hextext: ; updates hex item count from HL. Destroys DE.
	ld	de,FCIFS
	ld	a,h
	rrca
	rrca
	rrca
	rrca
	call	hexdigit
	ld	a,h
	call	hexdigit
	ld	a,l
	rrca
	rrca
	rrca
	rrca
	call	hexdigit
	ld	a,l
	call	hexdigit
	ret

	; Called tensyn because used to wait 10x vsync
	; But now it waits 12 so the guy wiggles the joystick in sync to
	; the tune ;-)
	; Clobbers B, sets it to 0
	; Preserves	af,bc,de,ix,iy
tensyn:	LD B,12
	push	hl
	ld	hl,(sctl2)
	push	hl
tensyn1 
	ld	hl,0x1080
	ld	(sctl2),hl
	ld	hl,(0)
tensyn2:
tensynp equ tensyn2-2
	ld	(freq2),hl
	ld	hl,(tensynp)
	inc	hl
	inc	hl
	ld	(tensynp),hl
	push	bc
	push	de
	call	hextext
	call	tune
	call	prtfcifs	; print the hex items
	pop	de
	pop	bc
	DJNZ tensyn1
	pop	hl
	ld	(sctl2),hl
	pop	hl
	ret

SLOHBOD ld hl,(newxpos)
	call getsix
	ld a,(newxpos)
	and 7
	jr z,U51
	ld a,(six+1)
	cp 6
	jr nz,U49
	inc l
	jr KONECC
U49     ld a,(six+3)
	cp 6
	jr nz,U50
	inc l
	inc h
	jr KONECC
U50     ld a,(six+5)
	cp 6
	jr nz,U51
	inc l
	inc h
	inc h
	jr KONECC
U51     ld a,(six)
	cp 6
	jr z,KONECC
	ld a,(six+2)
	cp 6
	jr nz,U52
	inc h
	jr KONECC
U52     ld a,(six+4)
	cp 6
	ret nz
	inc h
	inc h
KONECC  push hl
	ld	hl,(sctl2)
	push	hl
	ld	hl,0x1680 ; Yellow, full volume
	ld	(sctl2),hl
	ld	hl,800
	ld	de,(freq2)
	ld	b,5
CYK10   
	ld	(freq2), hl
	call	tune
	add	hl,hl
	djnz	cyk10
	pop	hl
	ld	(sctl2),hl
	ld	(freq2),de
	pop hl
	push hl
	call ROOMADDR
	or a
	push af
	ld a,(hl)
	jr z,U46
	rrca 
	rrca 
	rrca 
	rrca 
U46     or 15
	ld b,a
	pop af
	ld a,b
	jr z,U47
	rrca 
	rrca 
	rrca 
	rrca 
U47     ld (hl),a ; Erase the item (set the char in room to 0xf)
	pop bc
	ld h,b
	ld l,c
	call GRCHAR
	ld (bc),a
	push de
	push hl
	ld bc,(oldxpos)
	call paintwilly
	pop hl
	pop de
	ld b,8
CYK11   ld a,(de) ; 7
	ld (hl),a ; 7
	inc de ; 6
	inc h ; 4
	djnz CYK11 ; 13
	ld bc,(newxpos)
	call GBS	; Get Background from the Screen
	ld bc,(newxpos)
	call OPBS
	ld hl,itemsbcd
	ld a,(hl)
	add a,1
	daa 
	ld (hl),a
	inc hl
	ld	a,(hl)
	adc	a,0
	daa
	ld	(hl),a
	call	PRTNR
	pop	hl
	jp	NZSB

	; These 3 labels must be in sequence
str1 defb 0,1
str2 defb 2,3
str3 defb 4

scrolltext
	defm " Press ENTER to start. "
	defm " Twibright Labs present Jet Set Willy X. "
	defm "Left: 9ol, joys. "
	defm "Right: 0pENTER, joys. JUMP: 6yh, joys. "
	defm "Sound control: jk " 
	defm "You would like to play games on your ZX Spectrum, "
	defm "but your strict wife doesn't allow you to until you "
	defm "collect all items in the city she wants. "
	defm "ZX Spectrum forever! "
	defm "(c) 1993-1996, 2006 Karel 'Clock' Kulhavy, music by "
	defm "Alan 'Factor6' Petrik. "
	defm "This program is free software; you can redistribute "
	defm "it and/or modify it under the terms of the GNU General "
	defm "Public License as published by the Free Software Foundation; "
	defm "either version 2 of the License, or (at your option) any later "
	defm "version. "
	defm "Good luck! *****PRESS ENTER TO START*****"
scrolltextend

	org 	firstaddress-2 ; Stack address in sna_header
	defw introstart ; Return address for the SNA snapshot

	ORG 59540
SYS	; System variable area

currentroom	equ	sys+0
oldxpos		equ	sys+1
oldypos		equ	sys+2
newxpos		equ	sys+3
newypos		equ	sys+4
jumppos		equ	sys+5
unk7		equ	sys+7
enterpos	equ	sys+9	; Where Willy entered the screen.
unk11		equ	sys+11
unk13		equ	sys+13
croomaddr	equ	sys+16 ; Current room address 
itemsbcd	equ	sys+18 ; Packed BCD how many items collected.
bgstorage	equ	sys+20 ; Storage for graphics background
six		equ	sys+52 
	; 0 1
	; 2 3
	; 4 5
jumptable 	EQU	SYS+58
	; 52 jump position, 2 bytes each -> 104 bytes. 58+104=162
njumppos equ 52
WILLY	EQU	SYS+162
	; 2 directions, each direction 8 positions
	; each position 16 pixels high and 16 pixels (2 bytes) wide
	; 512 bytes total

CHARSET EQU	SYS+674
SYSCHARSET EQU 15360 ; The ZX Spectrum ROM charset
	; 256 chars, 8 bytes each. Total 2048 bytes.
	
	; The code starts here.
	ORG	SYS+2722

introstart
	DI
	LD	A,58 ; A table full of ff
	LD	I,A
	IM	2 ; Vector table
	xor	a
	out	(254),a	; black border
one:	call decomp_scr
	LD hl,ZACMIS ; Room file start addr.
	LD DE,32 ; Room name length?
	ADD HL,DE ; 
	LD B,nrooms
l15:	PUSH BC ;
	LD BC,320 ; 320 bytes beginning 24632 are processed in place.
z6:	LD A,(HL) ; HL is 24632
	AND 15
	CP 15
	JR NZ,a1 ; if lower 4 bits of (HL) are not all set, jr to a1
	LD A,(HL)
	AND 240
	OR 6
	LD (HL),A ; Replace lower 4 bits of (HL) with 6
a1:	LD A,(HL)
	AND 240
	CP 240
	JR NZ,z5
	LD A,(HL)
	AND 15
	OR 96
	LD (HL),A
z5:	INC HL
	DEC BC
	LD A,B
	OR C
	JR NZ,z6
	LD BC,68 ; The room has 388 bytes, we processed 320, 68 remain
	ADD HL,BC
	POP BC
	DJNZ l15
	LD IX,scrolltext ; IX - address in text
	LD HL,scrolltextend-scrolltext ; Width of the scrolled text?
roll4:	PUSH HL
	PUSH IX
	POP DE
	PUSH DE
	ld hl,sctarget
	LD BC,1 ; Length 1
	CALL PRINT
	LD DE,287 ; 256+31
	LD A,8 ; 8 rotations until we print another char
roll3:	
	ld c,a
	ld a,191
	in a,(0xfe)
	and 1
	jr nz, noent
	; ENTER was pressed
	pop hl ; Destroy saved registers
	pop hl
	jp intogame
noent:	ld a,c
	LD HL,sctarget ; Within screen bitmap
	LD C,8 ; 8 microlines
	EI
	HALT ; Wait for VSYNC
roll2:	LD B,31 ; Text width + 1
	OR A ; Reset the carry?
roll1:	RL (HL) ; Left scroll 1 pixel
	DEC HL
	DJNZ roll1
	ADD HL,DE
	DEC C ; Microlines
	JR NZ,roll2
	DEC A
	JR NZ,roll3
	POP IX
	POP HL
	INC IX
	DEC HL
	LD A,H
	OR L
	JR NZ,roll4 ; If HL is not zero, jump
waitforstart:	CALL kbtest ; 0xeca1 = 60577, 0x94 offset in this program
	JR waitforstart

	; Decompresses the title screen into the videoram
	; Clobbers AF, BC, DE, HL
decomp_scr:
	ld	bc,screensrc
	ld	de,16384
	ld	hl,decomp1
decomp1:
	ld	a,(bc) ;7
	inc	bc ;6
	or	a ;4
	jr	z,decomp_zero ;7
	ld	(de),a ;7
	inc	de ;6
	jp	(hl) ;4

decomp_zero:
	ld	a,(bc)
	inc	bc
	or	a
	ret	z
	ld	l,b
	ld	b,a
	xor	a
decomp_block:
	ld	(de),a
	inc	de
	djnz	decomp_block
	ld	b,l
	ld	l,decomp1&255
	jp	(hl)
	

	


	; One rooms takes 388 bytes:
	; 32 bytes name
	; 320 bytes data (32x20, 2 chars per byte)
	; 4 bytes exits (in what sequence?)
	       
	; The code begins at 62522 (0xF43A)
	; Refresh taken items into untaken ones
RFSHITS	LD	HL,ZACMIS+32
	LD	D,nrooms
RFS2	LD	BC,320 ; Room data area length
RFS1	LD	A,(HL)
	OR	240
	INC	A
	JR	Z,RFL
	LD	A,(HL)
BRFL	OR	15
	INC	A
	JR	Z,RFH
BRFH	INC	HL
	DEC	BC
	LD	A,B
	OR	C
	JP	NZ,RFS1
	LD	BC,68 ; 388-320
	ADD	HL,BC
	DEC	D
	JP	NZ,RFS2
	RET
RFL	LD	A,(HL)
	AND	240
	OR	6
	LD	(HL),A
	JP	BRFL
RFH	LD	A,(HL)
	AND	15
	OR	96
	LD	(HL),A
	JP	BRFH

	; Prints the conveyors and flashes the items on the screen.
	; 32 records by 5 byte holding flashing items
	; and rolling conveyors.
	; 0 conveyor screen address L
	; 1 conveyor screen address H
	; 2 bit 7 - 1 item, 0 conveyor, then lower bits length of the
	;   conveyor. 0=empty record.
	; 3 coveyor upper content / item phase in lower 4 bits the rest
	; ignored.
	; 4 conveyor lower content
	; Conserves AF, BC, DE, HL, IX
ROLLS	DEFS	160 ;160-byte space , 5*32

ROLL	PUSH	AF
	PUSH	BC
	PUSH	DE
	PUSH	HL
	PUSH	IX
	LD	B,32
	LD	IX,ROLLS
MCYK	PUSH	BC
	PUSH	IX
	CALL	BLOCK
	POP	IX
	LD	BC,5
	ADD	IX,BC
	POP	BC
	DJNZ	MCYK
	POP	IX
	POP	HL
	POP	DE
	POP	BC
	POP	AF
	RET
	
	; Prints the conveyors to the screen actually
	; IX - input of a 5-byte record
	; Clobbers IX
BLOCK
	LD	A,(IX+2)
	or	a
	ret	z ; Empty item
	BIT	7,A ; 8
	JR	NZ,ITEM ; 7
	LD	D,(IX+3) ; 19
	LD	E,(IX+4) ; 19
	BIT	6,A ; 8
	JR	NZ,LEFT ; 7
RIGHT	RRC	D ; 8
	RLC	E ; 8
	JP	COMMON ; 10
LEFT	RLC	D
	RRC	E
COMMON	LD	(IX+3),D ; 19
	LD	(IX+4),E ; 19
	LD	L,(IX+0) ; 19
	LD	H,(IX+1) ; 19
	AND	0x3f ; 7
	CP	33 ; 7
	RET	NC ; 5
	OR	A ; A is conveyor length
	RET	Z 
	LD	B,A
	LD	C,A
	LD	A,H
        AND     0xf8
	LD	H,A
	CP	64
	RET	C
	CP	88
	RET	NC
PUTCY1	LD	(HL),D ; 0th line of the conveyor
	INC	L
	DJNZ	PUTCY1 ; B is the conveyor length.
	INC	H
	INC	H	; 2 pixels down
	LD	B,C
PUTCY2	dec	l	; Go backwards
	LD	(HL),e ; 2nd line of the conveyor
	DJNZ	PUTCY2
	RET

	; jumped to only from BLOCK.
ITEM
	LD	HL,(croomaddr)
	LD	DE,32
	ADD	HL,DE
	LD	E,(IX+0)
	LD	A,(IX+1)
	CP	88
	RET	C
	CP	91
	RET	NC
	AND	3
	LD	D,A
	SRL	D
	RR	E
	RLA
	ADD	HL,DE
	AND	1
	LD	A,(HL)
	JR	Z,NROT
	RRCA
	RRCA
	RRCA
	RRCA
NROT	AND	15
	CP	6 ; is 6 an item?
	RET	NZ ; Return if not an item?
	LD	A,(IX+3) ; Item phase?
	INC	A ; Increase item phase? 
	LD	(IX+3),A ; Write item phase back?
	AND	31 ; Item cycle 32 phases
	LD	HL,itemcolours ; Item colour table

	; Add A to HL
	ADD	A,L
	LD	L,A
	ADC	A,H
	SUB	L
	LD	H,A
	
	LD	A,(HL) ; Fetch item colour
	LD	L,(IX+0) ; (IX+0) and (IX+1) hold the address of the item
			 ; attribute we want to change
	LD	H,(IX+1)
	XOR	(HL)
	AND	7 ; Change only the ink
	XOR	(HL)
	LD	(HL),A ; Write attr back
	RET
	
	; Item colour flash table
itemcolours
	DEFB	0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7
	DEFB	7,7,6,6,5,5,4,4,3,3,2,2,1,1,0,0

	; Clobbers seemingly everything.
WODE
	CALL	RFSHITS
	LD	HL,22528
	LD	DE,22529
	LD	BC,767
	EI
	HALT
	LD	(HL),0
	LDIR ; Set attributes to zero
	LD	HL,16384
	LD	DE,16385
	LD	BC,6143
	LD	(HL),0
	LDIR ; Clear the screen
	LD	HL,22528
	LD	DE,22529
	LD	BC,767
	EI
	HALT
	LD	(HL),71 ; Bright white on black
	LDIR ; Set the whole screen bright white on black
	LD	HL,itemtextdest ; Lowermost row, 6 chars from left
	LD	BC,20 ; 20 chars wide, centered
	LD	DE,ITEMTEXT ; Items collected: xxxx
	CALL	PRINT ; 
WCM	LD	A,startroom
	ld	(currentroom),a
WSR	ld	hl,34940
	ld	(oldxpos),hl
	ld	(newxpos),hl
	ld	(enterpos),hl
	LD	HL,0
	ld	(jumppos),hl
	ld	(unk7),hl
	ld	(unk11),hl
	ld	(unk13),hl
WAM	ld	hl,ZACMIS+388*startroom
	ld	(croomaddr),hl
WPB	LD	HL,0
	ld	(itemsbcd),hl
	call	prtnr
	call	PRTSCRN
	JP	VPADL
CYK7	ld	a,127
	in	a,(0xfe)
	and	1
	jr	nz,U60
	ld	a,254
	in	a,(0xfe) ; test break
	and	1
	jr	nz,U60
	xor	a
	ret
U60	ld	a,(currentroom)
	or	a
	jr	nz,U61
	ld	a,(oldxpos)
WEXS	cp	124
	jr	nz,U61
	ld	a,(oldypos)
WEYS	cp	136
	jr	nz,U61
	ld	hl,(itemsbcd) ; number of items collected?
WEPB	ld	bc,needitems ; number of items to collect
	or	a
	sbc	hl,bc
	jr	c,U61
	ld	a,1 ; All items collected
	ret
U61	;in	a,(31)
	;and	31
	xor a ; Joystick disabled
	ld	(SYS+15),a
	ld	a,143
	in	a,(254)
	or	224
	cpl
	ld	hl,SYS+15
	or	(hl)
	ld	(hl),a
	call	MUZPAD
	ld	a,(jumppos)
	or	a
	jr	nz,U2
	ld	hl,SYS+6
	bit	0,(hl)
	jr	z,U1
	ld	hl,newypos
	inc	(hl)
	jr	nz,XXA
	dec	(hl)
XXA	jr	U3
U1	ld	a,36
	ld	hl,SYS+8
	cp	(hl)
	jp	c,KILL
	xor	a
	ld	(hl),a
	call	OVLADANI
U2	call	SKOK
U3 call ZABILSE
	or a
	jr z,U7
	jp KILL
VPADL
	CALL	ROLL	; Redraws the conveyors and the flashing items
	EI
	halt		; Wait for vertical blank
	jr U11
U7      call ZED
	call NVDP
U4      call edge
	or a
	jr nz,VPADL
	call SLOHBOD
U10     ld bc,(oldxpos)
	call paintwilly
U11     ld bc,(newxpos)
	call GBS	; Get Background from the Screen.
	ld bc,(newxpos)
	call OPBS
NZSB    ld hl,(newxpos)
	ld (oldxpos),hl
	call getsix
	LD	A,(SYS+6)
	RES	5,A
	BIT	1,A
	JR	Z,CFLZ
	SET	5,A
CFLZ	LD	(SYS+6),A
	jp CYK7
	
	; Paints the willy and 
paintwilly
	ld	a,c
	and	7
	RRCA
	RRCA
	RRCA
	LD	E,A
	LD	A,(SYS+6)
	AND	32
	ADD	A,255
	SBC	A,A
	AND	1
	LD	D,A
	call	scaddr
	LD	IX,WILLY
	ADD	IX,DE
	LD	DE,bgstorage
	CALL	ROLL
	call tune ; Itself waits for an interrupt and then disables it back.
	ld	b,16
	; b counter (16)
	; ix Willy addr
	; hl screen addr
	; de probably background addr
pwcyc
	ld	a,(DE) 	; Take the background
	inc	DE 	; Move the background pointer
	XOR	(HL)	;
	AND	(IX+0)  ; Where Willy is, screen content will be placed,
	                ; otherwise the background store content
	INC	IX
	XOR	(HL)
	ld	(hl),a  ; Put back to the screen
	inc	hl 	;Not supposed to roll over
	ld	a,(DE)
	inc	DE
	XOR	(HL)
	AND	(IX+0)
	INC	IX
	XOR	(HL)
	ld	(hl),a
	dec	hl
	inc	h
	ld	a,h
	and	0x07
	call	z,fixhl
	djnz	pwcyc	; 16 times
	ret
	
	; Get Background from Screen
	; bc - input coords in pixels
GBS     ld de,bgstorage
	call SCADDR
	ld	bc,0x10ff
NN      
	; a counter (16)
	; bc screen coords
	; hl screen addr
	; de background storage addr
	ldi
	ldi	
	dec	hl	; This cannot be dec l since it can overflow when
			; the guy is at the right edge of the screen.
	dec	hl
	inc	h
	ld	a,h
	and	0x07
	call	z,fixhl
	djnz	nn
	ret 
	
OPBS    ld a,(newxpos)	; Willy X position in pixels
	and 7		; Take the lowest 3 bits	
	rrca 
	rrca 
	rrca 		; Multiply by 32
	ld e,a
	ld a,(SYS+6)
	and 2		; Which way he is looking
	rrca 
	ld d,a
	push bc
	ld	bc,WILLY
	ex	de,hl
	add hl,bc
	ex	de,hl
	pop bc
	call SCADDR
	ld b,16
CYK3    
	ld a,(de)
	inc de
	or (hl)
	ld (hl),a
	inc hl ; never crosses the boundary
	;inc l
	ld	a,(de)
	inc	de
	or	(hl)
	ld	(hl),a
	dec	hl
	inc	h
	ld	a,h
	and	7
	call	z,fixhl
	djnz	CYK3
	ret 
	
	; input - hl after h was incremented to go 1 pixel lower
	; and h&7 happened to be 0
	; output - hl - corrected hl so it really points 1 pixel lower how
	; it was intended
fixhl	ld a,l
	add a,0x20
	ld l,a
	ret c ; l overflowed, the original value of h is OK
	ld a,h
	sub 0x08
	ld h,a
	ret

SCADDR  ld a,b
	rrca 
	rrca 
	rrca 
	ld l,a
	xor b
	and 248
	xor b
	and 31
	or 64
	ld h,a
	ld a,l
	xor c
	and 7
	xor c
	rrca 
	rrca 
	rrca 
	ld l,a
	ret 

SCRADR	DEFS	2
ATTADR	DEFS	2
IRMADR	DEFS	2

	; Prints a room. Layout - lines:
	; 0-19: room
	; 20 - empty
	; 21 - room name
	; 22 - empty
	; 23: Items collected: xxxx
PRTSCRN
	LD	HL,16384
	LD	(SCRADR),HL
	LD	H,22528/256	
	LD	(ATTADR),HL
	LD	HL,(croomaddr)
	LD	DE,32
	ADD	HL,DE
	LD	(IRMADR),HL
	LD	BC,320  ; 32 chars wide, 20 high, 2 chars per byte
PRTS1	LD	HL,(IRMADR)
	LD	A,(HL)
	CALL	PRCHAR
	LD	HL,(IRMADR)
	LD	A,(HL)
	INC	HL
	LD	(IRMADR),HL
	RRCA
	RRCA
	RRCA
	RRCA
	CALL	PRCHAR
	DEC	BC
	LD	A,B
	OR	C
	JP	NZ,PRTS1
	LD	HL,(croomaddr)
	LD	DE,356
	ADD	HL,DE
	EX	DE,HL
	LD	HL,20640 ; Screen target address of the room name
	LD	BC,32
	CALL	PRINT ; Print the room name
	LD	HL,ROLLS
	LD	DE,ROLLS+1
	LD	BC,159
	LD	(HL),0
	LDIR
	LD	IX,(croomaddr)
	LD	A,(IX+13)
	AND	7
	RLCA
	LD	C,(IX+4)
	LD	E,(IX+6)
	CALL	PRP1
	LD	(BTSR),BC
	LD	C,E
	CALL	PRP1
	LD	(BTSL),BC
	LD	BC,320
	LD	IX,ROLLS-5
	XOR	A
	LD	(ENTS),A
	INC	A
	LD	(STEP),A
	LD	HL,(croomaddr)
	LD	DE,32
	ADD	HL,DE
	LD	DE,16384
PRTS2	LD	A,(HL)
	CALL	TZNAK
	CALL	POSDE
	LD	A,(HL)
	RRCA
	RRCA
	RRCA
	RRCA
	CALL	TZNAK
	CALL	POSDE
	INC	HL
	DEC	BC
	LD	A,B
	OR	C
	JR	NZ,PRTS2
	RET
POSDE	INC	E
	RET	NZ
	LD	A,D
	ADD	A,8
	LD	D,A
	RET

	; Loads conveyor contents
PRP1	LD	B,0
	SLA	C
	RL	B
	SLA	C
	RL	B
	SLA	C
	RL	B
	LD	IX,CHARSET
	ADD	IX,BC
	LD	C,(IX+0)
	LD	B,(IX+2)
	RET

STEP	DEFS	1
ENTS	DEFS	1
TZNAK	PUSH	BC
	PUSH	HL
	AND	15
	LD	B,A
	LD	A,(ENTS)
	CP	32
	JP	NC,TZRET
	LD	A,B
	CP	6
	JP	Z,TZITEM
	CP	2
	JP	Z,TZPRIG
	CP	3
	JP	NZ,JZNAK
TZPLEF	LD	A,(STEP)
	RRCA
	JP	C,PLSTP
	LD	A,(IX+2)
	AND	192
	CP	64
	JP	NZ,PLSTP
	LD	A,(IX+0)
	AND	31
	LD	B,A
	LD	A,(IX+2)
	AND	63
	ADD	A,B
	CP	32
	JP	NC,PLSTP
	INC	(IX+2)
	JP	TZRET
PLSTP	LD	HL,(BTSL)
	LD	(IX+7),65
	JP	CMSTP
TZPRIG	LD	A,(STEP)
	RRCA
	JP	C,PRSTP
	LD	A,(IX+2)
	AND	192
	JP	NZ,PRSTP
	LD	A,(IX+0)
	AND	31
	LD	B,A
	LD	A,(IX+2)
	AND	63
	ADD	A,B
	CP	32
	JP	NC,PRSTP
	INC	(IX+2)
	JP	TZRET
PRSTP	LD	(IX+7),1
	LD	HL,(BTSR)
CMSTP	LD	BC,5
	ADD	IX,BC
	LD	(IX+0),E
	LD	(IX+1),D
	LD	(IX+3),L
	LD	(IX+4),H
	XOR	A
	LD	(STEP),A
	LD	A,(ENTS)
	INC	A
	LD	(ENTS),A
	JP	TZRET
TZITEM	LD	BC,5
	ADD	IX,BC
	LD	(IX+0),E
	LD	A,D
	RRCA
	RRCA
	RRCA
	AND	3
	OR	88
	LD	(IX+1),A
	LD	(IX+2),128 ; Set bit 7 - means item.
	ld	a,r
	LD	(IX+3),A
	LD	A,1
	LD	(STEP),A
	LD	A,(ENTS)
	INC	A
	LD	(ENTS),A
TZRET	POP	HL
	POP	BC
	RET
JZNAK	LD	A,1
	LD	(STEP),A
	JP	TZRET




	; Prints the lower 4 bits as a room character.

PRCHAR	AND	15
	RLCA
	LD	HL,(croomaddr)
	ADD	A,L
	LD	L,A
	ADC	A,H
	SUB	L
	LD	H,A
	LD	A,(HL)
	INC	HL
	LD	E,(HL)
	LD	HL,(ATTADR)
	LD	(HL),E
	INC	HL
	LD	(ATTADR),HL
	LD	E,A
	LD	D,0
	SLA	E
	RL	D
	SLA	E
	RL	D
	SLA	E
	RL	D
	LD	HL,CHARSET
	ADD	HL,DE
	LD	DE,(SCRADR)
	PUSH	BC
	LD	B,8
PRCH1	LD	A,(HL)
	LD	(DE),A
	INC	HL
	INC	D
	DJNZ	PRCH1
	POP	BC
	LD	HL,(SCRADR)
	INC	L
	LD	(SCRADR),HL
	RET	NZ
	LD	A,H
	ADD	A,8
	LD	(SCRADR+1),A
	RET

PRTNR	LD	DE,FCIFS
	LD	HL,(itemsbcd)
	CALL	ONEB
	LD	H,L
	CALL	ONEB
prtfcifs
	ld	hl,numberdest
	ld	de,fcifs
	ld	bc,4
	call	print
	ret

;ZNAKY
;MENI:DE,HL,A
ONEB	LD	A,H
	RRCA
	RRCA
	RRCA
	RRCA
	CALL	ASCII
	LD	(DE),A
	INC	DE
	LD	A,H
	CALL	ASCII
	LD	(DE),A
	INC	DE
	RET
ASCII	AND	15
	ADD	A,48
	RET

GRCHAR	call	GCHAR
	ex	de,hl
	ld	hl,(croomaddr)
	ld	b,0
	sla	a
	ld	c,a
	add	hl,bc
	ld	c,(hl)
	inc	hl
	ld	a,(hl)
	push	af
	ld	hl,CHARSET
	sla	c
	rl	b
	sla	c
	rl	b
	sla	c
	rl	b
	add	hl,bc
	ex	de,hl
	ld	b,h
	ld	c,l
	sla	c
	sla	c
	sla	c
	sla	b
	sla	b
	sla	b
	call	SCADDR
	call	ATTRADDR
	pop	af
	ret


	; retval in a
	; if l>31 or h>19, returns 0
	; Preserves bc, de, hl
GCHAR	ld	a,31
	cp	l
	jr	c,gchar1
	ld	a,19
	cp	h
	jr	c,gchar1
	push	hl
	push	de
	call	ROOMADDR
	or	a
	ld	a,(hl)
	jr	z,PR3
	rrca
	rrca
	rrca
	rrca
PR3	pop	de
	pop	hl
	and	15
	ret
gchar1:	xor	a
	ret

	; Input: H - Y coord in chars (5 bits)
	;        L - X coord in chars (5 bits)
	; Output - HL=32+croomaddr+16*y+(x>>1),
	;             where x and y are treated as signed.
	;          A - lowest bit of input x coord
	; BC, DE is preserved
ROOMADDR 
	push	bc
	ld	c,h

	; hl=((int)l)>>1
	xor	a
	sra	l
	rla
	push	af ; Save the lowest bit for return
	ld	a,l
	add	a,a
	sbc	a,a
	ld	h,a

	; bc=((int)c)<<4
	sla	c
	sbc	a,a
	ld	b,a
	sla	c
	rl	b
	sla	c
	rl	b
	sla	c
	rl	b
	add	hl,bc ; Add together
	ld	bc,(croomaddr)
	add	hl,bc ; Add the current room address
	ld	bc,32 ; Skip the charset at the beginning
	; OPTIM - replace with inc h, inc h at the beginning!
	add	hl,bc
	pop	af
	pop	bc
	ret

ATTRADDR	ld	a,h
	rrca
	rrca
	rrca
	and	3
	or	88
	ld	b,a
	ld	c,l
	ret


	; Input H - y addr (pixels) of the Willy position
	; Input L - x addr (pixels) of the Willy position
	; The Willy is apparently allowed to stick couple of pixels off the screen boundary.
	; Clobbers HL, IX, IY, AF
getsix:
	push	bc

	ld	b,h
	ld	c,l

	; Convert pixels to chars
	srl	h
	srl	h
	srl	h
	srl	l
	srl	l
	srl	l

	ld	a,b
	cp	223
	jr	c,XXB
	; Willy sticks out from the top.
	ld	h,255

XXB	ld	a,c
	cp	253
	jr	c,XXC
	; Willy sticks out from the left.
	ld	l,255

XXC:	push	hl
	ld	b,l
	call	ROOMADDR
	push	hl
	pop	ix
	ld	iy,six
	; In even case, the left column is loaded loaded without rotation, the right one with rotation
	; In odd case, the left column is loaded with rotation, the right one without rotation from a higher address.
	; Let's assume IX is source and IY destination. to make the rotations static in the code:
	; In even case, the unrotated is loaded from IX, IX+16 and IX+32 and put into IY, IY+2 and IY+4.
	; In odd case, the unrotated is loaded from 1+IX, 1+IX+16 and 1+IX+32 and put into 1+IY, 1+IY+2 and 1+IY+4.
	; In even case, the rotated is loaded from IX, IX+16 and IX+32 and put into IY+1, IY+3, IY+5
	; In odd case, the rotated is loaded from IX, IX+16 and IX+32 and put into IY, IY+2 and IY+4
	; There will be a core code that will load unrotated from IX, IX+16 and IX+32 and put into IY, IY+2 and IY+4
	; and then load from IX, IX+16 and IX+32 and put into IY, IY+2 and IY+4.
	ld	a,b
	and	1
	jr	z,getsix1 ; Even jumps */
	inc	ix
	inc	iy
getsix1:
	; Get the unrotated column	
	ld	a,(IX+0)
	ld	(IY+0),a
	ld 	a,(IX+16)
	ld	(IY+2),a
	ld	a,(IX+32)
	ld	(IY+4),a
	jr	z,getsix2 ; Even jumps
	dec	ix
	dec	iy
	jp	getsix3
getsix2:
	inc	iy
getsix3:
	; Get the rotated column
	ld	a,(IX+0)
	rrca
	rrca
	rrca
	rrca
	ld	(IY+0),a
	ld 	a,(IX+16)
	rrca
	rrca
	rrca
	rrca
	ld	(IY+2),a
	ld	a,(IX+32)
	rrca
	rrca
	rrca
	rrca
	ld	(IY+4),a

	; Fix the contents of six - take
	; only lower 4 bits and apply an
	; identity.
	ld 	b,6
	ld	hl,six
getsix4:
	ld	a,(hl)
	and 	0xf
	cp	10
	jr	c, getsix5
	cp	13
	jr	nc, getsix5
	; Apply the identity
	and	7
getsix5:
	ld (hl),a
	inc	hl
	djnz	getsix4
	; Here B will be 0. We use that now:

	; If the right column pops out of the screen,
	; zero it out
	pop	hl

	ld	a,l
	cp	31
	jr	c,getsix7
	; Now the x is popping out somewhere
	; 31 (right pop) or 255 (left pop) here
	ld	ix,six
	jp	m,getsix6
	; 31 (right pop) here
	inc	ix ; Clear the right column instead of the left one
getsix6:

	ld	(ix+0),b
	ld	(ix+2),b
	ld	(ix+4),b
getsix7:
	ld	a,h
	cp	18
	jr	c,getsix9
	; 18 (bottom pop) or 255 (top pop) here.
	ld	ix,six
	jp	m, getsix8
	; 18 (bottom pop) here
	ld	(ix+4),b
	ld	(ix+5),b
	jp	getsix9
getsix8:
	ld	(ix+0),b
	ld	(ix+1),b
getsix9:
	pop	bc
	ret

OVLADANI	ld	d,0
	ld	b,2
	ld	c,3
	call	PASNEKAM
	or	a
	jr	z,U40
	inc	d
	jr	U40A
U40	ld	b,3
	ld	c,2
	call	PASNEKAM
	or	a
	jr	z,U40A
	dec	d
U40A	ld	hl,SYS+6
	ld	a,(SYS+15)
	ld	e,a
	or	252
	inc	a
	ld	a,e
	jr	z,NAV2
	bit	0,a
	jr	z,NAV1
	inc	d
	set	1,(hl)
NAV1	bit	1,a
	jr	z,NAV2
	dec	d
	res 1,(hl)
NAV2    ld a,d
	or a
	jr z,SNV2
	jp m,SNV3
	ld a,1
	set 1,(hl)
	ld d,a
	ex af,af'
	call TESTR
	ex af,af'
	jr SNV2
SNV3    ld a,255
	res 1,(hl)
	ld d,a
	ex af,af'
	call TESTL
	ex af,af'
SNV2    ld hl,oldxpos
	add a,(hl)
	inc hl
	inc hl
	ld (hl),a
	ld a,e
	bit 4,a
	jr z,KONEC1
	ld hl,jumppos
	inc (hl)
	ld a,d
	or a
	jr nz,SNV1
	xor a
	ld (unk7),a
	jr KONEC1
SNV1    ld a,255
	ld (unk7),a
	ld hl,SYS+6
	jp m,SNV4
	res 2,(hl)
	jr KONEC1
SNV4    set 2,(hl)
KONEC1  ret 
	
SKOK    ld a,(jumppos) ; Jump position
	or a
	jr z,KONEC2
	cp	njumppos+1
	jr nz,U16
	xor a
	ld (jumppos),a
	jr KONEC2
U16     ld c,a
	ld b,0
	ld hl,jumptable
	sla c
	rl b
	add hl,bc
	dec hl
	dec hl
	ld a,(hl)
	ex	de,hl
	ld hl,oldypos
	add a,(hl)
	ld (newypos),a
	ex de,hl
	inc hl
	ld de,SYS+6
	ld a,(de)
	bit 2,a
	ld a,(hl)
	jr z,PR4
	neg 
PR4     ld hl,unk7
	and (hl)
	ld hl,oldxpos
	add a,(hl)
	ld (newxpos),a
	ld hl,jumppos
	inc (hl)
KONEC2  ret 
	
	
edge  	ld c,0
	push bc
VYLZNOV ld de,(newxpos)
	ld a,e
	cp 249
	jr c,U19
	ld a,252
	cp e
	jr c,U19
	ld e,0
	ld bc,355
	jr U22
U19     ld a,e
	cp 253
	jr c,U20
	ld a,255
	cp e
	jr c,U20
	ld e,248
	ld bc,354
	jr U22
U20     ld a,d
	cp 145
	jr c,U21
	ld a,200
	cp d
	jr c,U21
	ld	d,0
	ld bc,353
	jr U22
U21     ld a,d
	cp 201
	jr c,KONEC3
	ld a,255
	cp d
	jr c,KONEC3
	ld d,136
	ld bc,352
	jr U22
KONEC3  pop bc
	ld a,c
	ret 
U22     ld hl,(croomaddr)
	add hl,bc
	ld a,(hl)
	ld (currentroom),a
	ld (newxpos),de
	pop bc
	ld c,1
	push bc
	ex de,hl
	ld (oldxpos),hl
	ld (enterpos),hl
	ld hl,(jumppos)
	ld (unk11),hl
	ld hl,(unk7)
	ld (unk13),hl
	ld a,(currentroom)
	ld l,0
	ld h,a
	ld c,a
	ld b,0
	sla c
	rl b
	sla c
	rl b
	add hl,bc
	ld b,a
	ld c,0
	srl b
	rr c
	add hl,bc
NAVES4	ld	bc,ZACMIS
	add hl,bc
	ld (croomaddr),hl
	call PRTSCRN
	jp VYLZNOV
	
MUZPAD  ld a,(oldxpos)
	ld d,a
	ld a,(oldypos)
	ld e,a
	and 7
	jr nz,U24
	ld a,d
	and 7
	jr z,U23
	ld a,(six+5)
	or a
	jr z,U23
	cp 5
	jr z,U23
	cp 6
	jr z,U23
	cp 15
	jr z,U23
	cp 8
	jr z,U23
	jp KONEC5
U23     ld a,(six+4)
	or a
	jp z,KONEC4
	cp 5
	jp z,KONEC4
	cp 6
	jr z,KONEC4
	cp 15
	jr z,KONEC4
	cp 7
	jr nz,KONEC5
	ld a,d
	and 7
	jr nz,KONEC4
	jr KONEC5
U24     ld a,d
	and 7
	jr z,U26
	ld a,(six+5)
	cp 8
	jr nz,U25
	ld a,d
	and 7
	ld b,a
	ld a,e
	and 7
	add a,b
	cp 8
	jr nc,KONEC5
	jr U26
U25     ld a,(six+5)
	cp 7
	jr nz,U26
	ld a,d
	and 7
	ld b,a
	ld a,e
	and 7
	cp b
	jr c,KONEC5
U26     ld a,(six+4)
	cp 8
	jr nz,U27
	ld a,d
	and 7
	ld b,a
	ld a,e
	and 7
	add a,b
	cp 9
	jr c,KONEC5
	jr KONEC4
U27     ld a,(six+4)
	cp 7
	jr nz,KONEC4
	ld a,d
	and 7
	ld b,a
	ld a,e
	and 7
	cp b
	jr nc,KONEC5
	jr KONEC4
KONEC5  ld hl,SYS+6
	res 0,(hl)
	ret 
KONEC4  ld hl,SYS+6
	set 0,(hl)
	ret 
	
NVDP    ld a,(newypos)
	ld b,a
	cp 223
	ret nc
	ld a,(oldypos)
	cp b
	jr nc,KONEC6
	ld hl,SYS+6
	bit 0,(hl)
	jr nz,BLV
	ld hl,(oldxpos)
	ld (newxpos),hl
	xor a
	ld (jumppos),a
KONEC6 ret 
BLV     ld hl,SYS+8
	inc (hl)
	jr nz,KONEC6
	dec (hl)
	ret 
	
ZED     ld hl,(newxpos)
	call getsix
	ld a,(newypos)
	and 7
	jr nz,U30
	ld a,(newxpos)
	and 7
	jr z,U29
	jr U31
U30     ld a,(newxpos)
	and 7
	jr z,U28
	ld a,(six+1)
	cp 4
	jr z,U32
	ld a,(six+3)
	cp 4
	jr z,U32
	ld a,(six+5)
	cp 4
	jr z,U32
U28     ld a,(six+4)
	cp 4
	jr z,U32
U29     ld a,(six+2)
	cp 4
	jr z,U32
	ld a,(six)
	cp 4
	jr z,U32
	ret 
U31     ld a,(six)
	cp 4
	jr z,U32
	ld a,(six+1)
	cp 4
	jr z,U32
	ld a,(six+2)
	cp 4
	jr z,U32
	ld a,(six+3)
	cp 4
	jr z,U32
	ret 
U32     ld a,(oldxpos)
	ld hl,newxpos
	cp (hl)
	jr z,U33
	ld a,(oldypos)
	ld hl,newypos
	cp (hl)
	jr z,U33
	jr U34
U33     ld a,(oldypos)
	ld hl,newypos
	cp (hl)
	ld hl,(oldxpos)
	ld (newxpos),hl
	jr z,U35
	xor a
	ld (jumppos),a
U35     ret 
U34     ld a,(oldxpos)
	ld (newxpos),a
	jp ZED
	
TESTR   ld a,(newxpos)
	and 7
	ld b,a
	ld a,(newypos)
	and 7
	add a,b
	and 7
	jr nz,U37
	ld a,(newxpos)
	and 7
	jr nz,U36
	ld a,(six+3)
	cp 8
	jr nz,U37
	ld hl,newypos
	dec (hl)
	ret 
U36     ld a,(six+5)
	cp 8
	jr nz,U37
	ld hl,newypos
	dec (hl)
	ret 
U37     ld a,(newxpos)
	and 7
	ld b,a
	ld a,(newypos)
	and 7
	cp b
	ret nz
	ld a,(six+4)
	cp 7
	ret nz
	ld hl,newypos
	inc (hl)
	ld hl,SYS+6
	set 0,(hl)
	ret 
	
TESTL   ld a,(newxpos)
	and 7
	ld b,a
	ld a,(newypos)
	and 7
	cp b
	jr nz,U38
	ld hl,(newxpos)
	srl h
	srl h
	srl h
	srl l
	srl l
	srl l
	inc h
	dec l
	ld a,(newxpos)
	and 7
	ld a,(six+4)
	call z,GCHAR
	cp 7
	jr nz,U38
	ld hl,newypos
	dec (hl)
	ret 
U38     ld a,(newxpos)
	and 7
	ld b,a
	ld a,(newypos)
	and 7
	add a,b
	and 7
	ret nz
	ld a,(newxpos)
	and 7
	ld a,(six+5)
	jr nz,U39
	ld a,(six+4)
U39     cp 8
	ret nz
	ld hl,newypos
	inc (hl)
	ld hl,SYS+6
	set 0,(hl)
	ret 
	
PASNEKAM ld a,(oldypos)
	and 7
	ld a,0
	ret nz
	ld a,(oldxpos)
	and 7
	jr z,U43
	ld a,(six+5)
	cp b
	jr z,U41
	ld a,(six+4)
	cp b
	jr z,U42
	jr KONEC7
U41     ld a,(six+4)
	cp c
	jr z,KONEC7
	jr KONEC8
U42     ld a,(six+5)
	cp c
	jr nz,KONEC8
	jr KONEC7
U43     ld a,(six+4)
	cp b
	jr nz,KONEC7
	jr KONEC8
KONEC7  xor a
	ret 
KONEC8  ld a,1
	ret 
	
	
KILL 	
	ld	hl,(sctl2)
	push	hl
	ld	hl,(freq2)
	push	hl
	ld	hl,0x1280 ; Red, full volume
	ld	(sctl2),hl
	ld	hl,9000
	ld	b,9
CYK8    
	ld	(freq2),hl
	call	tune
	push	hl
	pop	de
	srl	d
	rr	e
	srl	d
	rr	e
	or	a
	sbc	hl,de
	djnz	cyk8
	pop	hl
	ld	(freq2),hl
	pop	hl
	ld	(sctl2),hl
	ld hl,(enterpos)
	ld (oldxpos),hl
	ld (newxpos),hl
	ld hl,(unk11)
	ld (jumppos),hl
	ld hl,(unk13)
	ld (unk7),hl
	call PRTSCRN
	jp VPADL
	
ZABILSE ld a,(oldxpos)
	and 7
	jr z,U48
	ld a,(six+5)
	cp 5
	jr z,KONECA
	ld a,(six+3)
	cp 5
	jr z,KONECA
	ld a,(six+1)
	cp 5
	jr z,KONECA
U48     ld a,(six+4)
	cp 5
	jr z,KONECA
	ld a,(six+2)
	cp 5
	jr z,KONECA
	ld a,(six)
	cp 5
	jr z,KONECA
KONEC9  xor a
	ret 
KONECA  ld a,1
	ret 
	
tuneprefill
	; Puts 0x10fe into the bc
	; If DE is 0, puts 0 into HL, otherwise 0x80
	; Clobbers a
	ld a,d
	or e
	cp 1 ; nonzero -> nc, zero -> c
	sbc a,a ; nonzero -> 0, zero -> 0xff
	ld h,a
	ld l,a ; For de=0 hl=0xffff, otherwise 0x0000
	ret

calcfreq ; de - where to store the freq
         ; a - semitone no
	 ; clobbers a, de
	 or	a
	 jr	z,silence
	 sub	0x24
	 add a,a
	 add a,halftones&255
	 push hl
	 ld l,a
	 adc a,halftones>>8
	 sub l
	 ld h,a
	 ldi
	 ldi
	 pop hl
	 inc bc
	 inc bc
	 ret
silence	
	ld	(de),a
	inc	de
	ld	(de),a
	ret


	; Doesn't clobber anything. No input. Plays until interrupt comes.
tune	
	push af
	xor a
	push bc
	push de
	push hl
	ld	bc,0x1080
tunea	
volume1	equ tunea-2
sborder1	equ tunea-1

	ld de,(freq1)
	call tuneprefill
	exx
	push bc ; We need to store all because we don't know in what
	; phase the exx will be when the interrupt hits
	push de
	push hl
	ld	bc,0x1080
tuneb	
sctl2	equ tuneb-2 ; Total sound control
volume2	equ tuneb-2
sborder2	equ tuneb-1

	ld de,(freq2)
	call tuneprefill
	ld a,0x18 ; JR opcode
	ld (intpoke),a
	ei
	
	; Zilog says during the paper, ULA reads for 6T every 8T and when
	; you hit this time, you wait until ULA stops reading.
tune1:	; 112 cycles total = 31.25 kHz exactly and is not slowed down by the ULA
        ; because it synchronizes on a 2-tick usable window every 8 ticks.
	; The line is 224 ticks (15.625kHz, 64us), which is 28*8.
	; Volume ratio of the two voices is 1:1
	ld a,h ; 4
	cp c ; 4
	sbc a,a ;4
	and b ; 4
	add hl,de ; 11
	out (254),a ; 11
	exx ; 4
	nop ; 4
	jp tune1 ; 10
	
longjump: ; Interrupt jumps out of the tune1 loop.
	pop hl ; Discard the return address
	ld a,201 ; RET
	ld (intpoke),a
	xor a
	out (254),a

	ld a,(iter)
	dec a
	ld (iter),a
	jr nz, noadvance

	; Next tone
	ld bc,(addr)
	ld a,(bc) ; First voice
	ld de,freq1
	call calcfreq
	inc bc
	ld a,(bc) ; Second voice 
	ld de,freq2
	call calcfreq
	inc bc
	; ld a,(bc) ; Length
	; inc bc
	ld a,12
	ld (iter),a
	ld a,b
	cp tuneend>>8
	jr c,notuneend
	jr nz, tunereload
	ld a,c
	cp tuneend&255
	jr c,notuneend
tunereload:	ld bc,tunestart
notuneend:
	ld (addr),bc

noadvance:
	pop hl
	pop de
	pop bc
	exx
	ld	a,191
	in	a,(0xfe)
	or	0xf3
	inc	a
	jr	z,vol_inactive
	cp	-7
	sbc	a,a
	ld	b,0xff
	or	1 ; -1 or +1
	ld	hl,volume1
	add	a,(hl) ; Inc or dec 
	cp	b ; Underflow -> nc
	sbc	a,b ; nc->inc, c-> nothing
	cp	0x81 ; overflow -> nc
	adc	a,b ; nc->dec, c-> nothing
	ld	(hl),a
	ld	(volume2),a

vol_inactive:
	pop hl
	pop de
	pop bc
	pop af
	ret

	; Prints a string from the system charset
	; BC length of string - when it doesn't run out of screen, will
	; be 0
	; HL screen address - will be advanced
	; DE string source - will be advanced
	; Clobbers AF
PRINT
PRIN2	LD	A,B
	OR	C
	RET	Z
	LD	A,H
	AND	0x18
	OR	0x40
	LD	H,A
	CP	88
	RET	NC
	PUSH	HL ; HL is the screen address
	LD	A,(DE)
	INC	DE
	PUSH	DE
	LD	E,A ; Charnum
	LD	D,0
	SLA	E ; Mul by 8
	RL	D
	SLA	E
	RL	D
	SLA	E
	RL	D
	EX	DE,HL
	PUSH	BC
	LD	BC,SYSCHARSET
poke3	equ pke1-2
pke1	ADD	HL,BC
	EX	DE,HL
	LD	B,8
mline	LD	A,(DE)
	LD	(HL),A
	INC	H
	INC	DE
	DJNZ	mline
	POP	BC
	POP	DE
	POP	HL
	DEC	BC
	INC	L
	JP	PRIN2


	org 65524
	jp longjump ; 3 bytes
	; 65527 here, we can still stuff 8 bytes of variables here ;-)

BTSR	DEFS	2
BTSL	DEFS	2

freq1	defw 0 ; Main voice
freq2	defw 0 ; Second voice

	ORG	65535
intpoke	RET ; Interrupt ret. Will be overpoked by a jr to when playing
            ; the (de)tune. The byte at addr. 0 is 243 (DI) and that causes
	    ; a relative jump to 65524.


