;-------------------------------------------------------------------------------
; Balls mini-demo
; (c) Sayman 2015
;-------------------------------------------------------------------------------
; процедура модуля совсем не оптимальна, взята из исходника библиотеки C.
;-------------------------------------------------------------------------------

tbuf_addr:	equ 4000h
screen_addr:	equ 0xc000


balls_pgn	equ 1
bgspr_pgn	equ 6
savescr_pgn	equ 6
tbuf_pgn	equ 1

MAX_BALLS	equ 32		; при 96 шариках структура balls_cfg будет 576 байт

balls_pal_size	equ 128
bgspr_pal_size	equ 128

balls_struct:
.x		equ 0		; u16_t
.y		equ 2		; u8_t
.dx		equ 3		; i8_t
.dy		equ 4		; i8_t
.radius		equ 5		; u8_t

balls_struct_bkp:
.x		equ 0		; u16_t
.y		equ 2		; u8_t



		include "dss.inc"
		include "head.inc"


entry:		push ix
		call init
		call read_bgspr
		ld a,(pg_tbl.tbuf)
		out (cpu_w1),a
		ld a,(tmp_hndl)
		call close
		call read_bgpal
		call read_balls_spr
		call read_balls_pal
		call vinit
		call balls_reindex
		call balls_init
		call draw_bgspr
		call CopySCR_1to2
		ld a,0xc0
		out (port_y),a
		ld a,(pg_w3)
		out (cpu_w3),a
		call balls_main
		sub a
		jp quit0
		


		include "misc.asm"
		include "math.inc"


rand16	ld	de,.seed		; Seed is usually 0
	ld	a,d
	ld	h,e
	ld	l,253
	or	a
	sbc	hl,de
	sbc	a,0
	sbc	hl,de
	ld	d,0
	sbc	a,d
	ld	e,a
	sbc	hl,de
	jr	nc,.rand
	inc	hl
.rand	ld	(rand16+1),hl
	ret

.seed:	dw 0



inc_pg1:	ld a,(ix)
		out (cpu_w1),a
		inc ix
		ret

inc_pg3:	ld a,(ix)
		out (cpu_w3),a
		inc ix
		ret


init:		ld c,balls_pgn
		ld hl,pg_tbl.balls
.loop0:		push bc
		push hl
		call gmem
		pop hl
		pop bc
		jp c,gmem_err
		ld (hl),a
		inc hl
		dec c
		jr nz,.loop0
		ld c,bgspr_pgn
.loop1:		push bc
		push hl
		call gmem
		pop hl
		pop bc
		jp c,gmem_err
		ld (hl),a
		inc hl
		dec c
		jr nz,.loop1
		ld c,savescr_pgn
.loop2:		push bc
		push hl
		call gmem
		pop hl
		pop bc
		jp c,gmem_err
		ld (hl),a
		inc hl
		dec c
		jr nz,.loop2
		ld c,tbuf_pgn
.loop3:		push bc
		push hl
		call gmem
		pop hl
		pop bc
		jp c,gmem_err
		ld (hl),a
		inc hl
		dec c
		jr nz,.loop3
		ex af,af
		in a,(cpu_w1)
		ld (pg_w1),a
		in a,(cpu_w3)
		ld (pg_w3),a
		in a,(port_y)
		ld (old_y),a
		ex af,af
		out (cpu_w1),a
		ret



set_scr_w3:	out (cpu_w3),a
		ret

set_scr_w1:	out (cpu_w1),a
		ret



vinit:		ld a,81h
		ld bc,50h
		rst 10h
		call cls
		call set_global_pal
		call CopySCR_1to2
		ld a,norm_scr
		call set_scr_w3
		ret


CopySCR_1to2:	sub	a
		out	(port_y), a
		ld	hl, 0xc000
		ld	de, 0xc140
		ld	bc, 320
		ld	d, d
		ld	a, 0		; 256 bytes
		ld	a, a
;		ldir
.loop:		REPT 64
		ldi
		ENDM
		jp pe,.loop
	
		ld	b, b
		ld	hl, 0xc3E0
		ld	de, 0xc3E4
;		ld	bc, 0004h
		ld	a, a
                ldi
                ldi
                ldi
                ldi
;		ldir	
		ld	b, b
		ret


cls:		ld hl,0xc3E0
		ld de,0
		ld d,d
		ld a,0
		ld b,b
		ld b,4
.loop1:		ld a,d
		out (port_y),a
		ld e,e
		ld (hl),e
		ld b,b
		inc hl
		djnz .loop1

		ld hl,0xc000
		ld de,0
		ld bc,320
		ld d,d
		ld a,0
		ld b,b
.loop2:		ld a,d
		out (port_y),a
		ld e,e
		ld (hl),e
		ld b,b
		inc hl
		dec bc
		ld a,b
		or c
		jr nz,.loop2
		ret

set_global_pal:	ld bc,0ffa4h
		ld hl,pal
                ld de,0
                sub a
		rst 8
                ret



read_bgspr:	ld hl,data_files.bgspr
		push hl
		call open
		pop hl
		ld (open_err.err_file+1),hl
		jp c,open_err
		ld (rd_err.err_file+1),hl
		ld (tmp_hndl),a
		ld ix,pg_tbl.bgspr
.loop:		call inc_pg1
		ld a,(tmp_hndl)
		ld hl,tbuf_addr
		ld de,16320
		push ix
		call read
		pop ix
		jp c,rd_err
		or a
		ret nz
		jr .loop

read_bgpal:	ld hl,data_files.bgpal
		push hl
		call open
		pop hl
		ld (open_err.err_file+1),hl
		jp c,open_err
		ld (rd_err.err_file+1),hl
		ld (tmp_hndl),a
		ld hl,pal
		ld de,bgspr_pal_size*4
		call read
		jp c,rd_err
		ld a,(tmp_hndl)
		call close
		ret

read_balls_spr:	ld hl,data_files.balls
		push hl
		call open
		pop hl
		ld (open_err.err_file+1),hl
		jp c,open_err
		ld (rd_err.err_file+1),hl
		ld (tmp_hndl),a
		ld hl,balls_spr
		ld de,1024
		call read
		jp c,rd_err
		ld a,(tmp_hndl)
		call close
		ret

read_balls_pal:	ld hl,data_files.balls_pal
		push hl
		call open
		pop hl
		ld (open_err.err_file+1),hl
		jp c,open_err
		ld (rd_err.err_file+1),hl
		ld (tmp_hndl),a
		ld hl,pal+bgspr_pal_size*4
		ld de,balls_pal_size*4
		call read
		jp c,rd_err
		ld a,(tmp_hndl)
		call close
		ret


balls_reindex:	ld hl,balls_spr
		ld c,128
		ld de,1024
.loop0:		ld a,(hl)
		inc a
		jr z,.loop1
		dec a
		add a,c
		ld (hl),a
.loop1:		inc hl
		dec de
		ld a,e
		or d
		jr nz,.loop0
		ret


balls_init:	ld hl,balls_cfg
		ld de,balls_cfg+1
		ld bc,MAX_BALLS*6
		xor a
		ld (hl),a
		ldir
		ld hl,balls_bkp
		ld de,balls_bkp+1
		ld bc,MAX_BALLS*3
		xor a
		ld (hl),a
		ldir
		ld iy,MAX_BALLS
		ld ix,balls_cfg
.loop0:		ld de,320-16		; размеры каждого шарика 16на16
		push de
		call rand16		; берём случайную координату X
		pop de
		inc hl
		push de
		call lmod
		pop de
		ex de,hl
.next0:		ld (ix+balls_struct.x),e
		ld (ix+balls_struct.x+1),d
		ld de,256-16
		push de
		call rand16
		pop de
		inc hl
		push de
		call lmod
		pop de
		ex de,hl
.next1:		ld (ix+balls_struct.y),e
		call rand16
		ld a,l
		and 1
		jr nz,.next2
		ld a,-1
.next2:		ld (ix+balls_struct.dx),a
		call rand16
		ld a,l
		and 1
		jr nz,.next3
		ld a,-1
.next3:		ld (ix+balls_struct.dy),a
		ld de,6
		add ix,de
		dec iy
		ld a,iyl
		or iyh
		jr nz,.loop0
		ret


draw_bgspr:	ld ix,pg_tbl.bgspr
		call inc_pg1
		ld hl,tbuf_addr
		ld c,51
		ld a,0
.loop:		ld de,screen_addr
		out (port_y),a
		ex af,af
		di
		ld d,d
		ld a,0
		ld l,l
		ld a,(hl)
		ld (de),a
		ld b,b
		inc h
		inc d
		ld d,d
		ld a,64
		ld l,l
		ld a,(hl)
		ld (de),a
		ld b,b
		ld a,64
		add a,l
		ld l,a
		adc a,h
		sub l
		ld h,a
		dec c
		call z,nextpage
		ex af,af
		inc a
		jr nz,.loop
		ei
		halt
		di
		ret

nextpage:	call inc_pg1
		ld hl,tbuf_addr
		ld c,51
 		ret


balls_main:

.loop1:		ld iy,MAX_BALLS
		ld ix,balls_cfg
		call save_coords
		push ix
		push iy
.loop0:		ld e,(ix+balls_struct.x)
		ld d,(ix+balls_struct.x+1)
		ld hl,320-16
		call check_x
		ld c,(ix+balls_struct.y)
		ld hl,256-16
		call check_y
		ld a,(ix+balls_struct.dx)
		ld h,0
		ld l,a
		rlca
		jr nc,.a1
		dec h
.a1:		rrca
		add hl,de
		ex de,hl
		ld (ix+balls_struct.x),e
		ld (ix+balls_struct.x+1),d
		ld a,(ix+balls_struct.dy)
		add a,c
		ld (ix+balls_struct.y),a
		ld de,6
		add ix,de
		dec iy
		ld a,iyl
		or iyh
		jr nz,.loop0
		pop iy
		pop ix

		ld a,norm_scr|trans_scr|tmp_scr
		call set_scr_w3

.loop2:		ld hl,balls_spr
		ld a,iyl
		and 3
		ld e,(ix+balls_struct.x)
		ld d,(ix+balls_struct.x+1)
		ld c,(ix+balls_struct.y)
		call draw_balls
		ld de,6
		add ix,de
		dec iy
		ld a,iyl
		or iyh
		jr nz,.loop2

		ei
		halt
		di
		in a,(rgmod)
		and 1
		xor 1
		out (rgmod),a

		ld a,norm_scr
		call set_scr_w3
		ld iy,MAX_BALLS
		ld ix,balls_bkp
.loop3:		ld e,(ix+balls_struct.x)
		ld d,(ix+balls_struct.x+1)
		ld c,(ix+balls_struct.y)
		call restore_bg
		ld de,3
		add ix,de
		dec iy
		ld a,iyl
		or iyh
		jr nz,.loop3

.blah:		call check_key
		jr c,._ret_
		jp .loop1
._ret_:		ret

save_coords:	push ix
		push iy
		ld hl,balls_bkp
.loop:		ld e,(ix+balls_struct.x)
		ld d,(ix+balls_struct.x+1)
		ld c,(ix+balls_struct.y)
		ld (hl),e
		inc hl
		ld (hl),d
		inc hl
		ld (hl),c
		inc hl
		ld de,6
		add ix,de
		dec iy
		ld a,iyh
		or iyl
		jr nz,.loop
		pop iy
		pop ix
		ret


restore_bg:
		in a,(rgmod)
		or a
		ld a,0xc0
		jr nz,.restore_to_0
		ld a,0xc1
		jr .restore_to_1		
.restore_to_0:	add a,d
		ld d,a
		ld h,d
		ld l,e
		jr .restore
.restore_to_1:	add a,d
		ld d,a
		ld a,0x40
		add a,e
		ld e,a
		adc a,d
		sub e
		ld d,a
		ld h,d
		ld l,e
.restore:	ld a,c
		out (port_y),a
		ld b,16
		di
.loop:		ld d,d
		ld a,16
		ld l,l
		ld a,(hl)
		ld (de),a
		ld b,b
		in a,(port_y)
		inc a
		out (port_y),a
		djnz .loop
		ret
		
		

draw_balls:	ld b,a
		in a,(rgmod)
		or a
		ld a,0xc1
		jr z,.draw_to_1			; если включён 0й экран, рисуем на 1й
		ld a,0xc0			; иначе (1й) рисуем в 0й
.draw_to_0:	add a,d
		ld d,a
		jr .draw
.draw_to_1:	add a,d
		ld d,a
		ld a,0x40
		add a,e
		ld e,a
		adc a,d
		sub e
		ld d,a

.draw:		ld a,b
		add a,a
		add a,a
		add a,a
		add a,a
		add a,l
		ld l,a
		adc a,h
		sub l
		ld h,a			; номер спрайта*256 = адрес спрайта в картинке
		ld a,c
		out (port_y),a
		ld b,16
		di
.loop:
		ld d,d
		ld a,16
		ld l,l
		ld a,(hl)
		ld a,a
		ld (de),a
		ld b,b
		ld a,c
		out (port_y),a
		ld a,l
		add a,64
		ld l,a
		ld a,0
		adc a,h
		ld h,a
		inc de
		djnz .loop
		ret

check_x:	ld a,e
		or d
		jr z,.next0
		sbc hl,de
		jr z,.next1
		jr c,.next1
		ret
.next0:		ld a,1
		ld (ix+balls_struct.dx),a
		ret
.next1:		ld a,-1
		ld (ix+balls_struct.dx),a
		ret


check_y:	ld a,c
		or a
		jr z,.next0
		ld a,l
		sub c
		jr z,.next1
		jr c,.next1
		ret
.next0:		ld a,1
		ld (ix+balls_struct.dy),a
		ret
.next1:		ld a,-1
		ld (ix+balls_struct.dy),a
		ret


sync:		ei
		halt
		di
		ret


check_key:	push hl
		push de
		push bc
		push ix
		push iy		
		ld c,scankey
		rst 10h
		pop iy
		pop ix
		pop bc
		pop de
		pop hl
		xor 1bh			; код Esc...
		ret nz
.esc:		scf
		ret
		



pg_tbl:
.balls:		db 0
.bgspr:		ds 6
.savescr:	ds 6
.tbuf:		db 0

pg_w0:		db 0
pg_w1:		db 0
pg_w2:		db 0
pg_w3:		db 0
old_y:		db 0


data_files:
.balls:		db "balls.spr",0
.balls_pal:	db "balls.act",0
.bgspr:		db "bgspr.spr",0
.bgpal:		db "bgspr.act",0

tmp_hndl:	db 0


open_err_str:	db "Can't open file ",0
read_err_str:	db "Failed to read file ",0
gmem_err_str:	db "PANIC: Can not allocate memory!",cr,lf,0
vm_err_str:	db "PANIC: Unable to set videomode!",cr,lf,0

crlf0:		db " ",cr,lf,0


pal:		equ ($/80h)*80h+80h
balls_spr:	equ ((pal+1024)/80h)*80h+80h
balls_cfg:	equ ((balls_spr+1024)/80h)*80h+80h
balls_bkp:	equ (((balls_cfg)+6*MAX_BALLS)/80h)*80h+80h