;- "compo fill my heart" ;-) - 256 Byte intro for Deadline 2018 by Kuemmel
;heart based on IQ's heart formulations
;assembled with flat assembler 1.72
org 100h
use16

push 0a000h			;vga
pop es					

;---palette
mov al,13h			;mode 13 init								
mov bl,63			;colour counter
mov dh,bl			;R
mov cl,31			;B try 31 or 0
pal_loop:			
	mov ch,bl   	;G
	int 10h					
	mov ax,1010h	;first entry is skipped for mode init, so colours only from 62 to 0 (if jns) are changed
	dec bx
jns pal_loop		;or jnz to keep black as entry 0

mov ah,80h 			;fs is double buffer
mov fs,ax
mov ah,70h			;gs is background buffer
mov gs,ax

;---background
mov cx,24*40
mov bl,1
background_fill:
	mov ax,0x0e03		;or 0x0e
	int 10h 			;int 10h ah = 0x0e, al = character, bl = colour
loop background_fill

xor si,si
copy_background:
	es lodsb
	mov [gs:si],al 
loop copy_background

mov si,cons
mov word[bp+si],cx		;bp+si is timer ...clear timer for sound init
fldpi					;3.14
;---frame_loop
frame_loop:
	xor bx,bx
	mov ax,0xcccd  		
	mul di				;rrrola's trick => y=dh, x=dl
	sub dh,118			;vertical adjust	
	sub dl,128			;horizontal adjust...adjusting a000h fucks up the textplot
	pusha
	fild word[bx-9]		;x=dl*256				|3.14			
	fabs				;x=abs(x)				|3.14
	fidiv word[si]		;x=abs(x)/f				|3.14
	fld st1				;|3.14					|x
	fsub st0,st1		;3.14-x					|x			|3.14
	fmul dword[si]		;(3.14-x)*0.5			|x			|3.14
	fmul dword[si]		;(3.14-x)*0.5*0.5		|3.14
	fsqrt				;sqrt((3.14-x)*0.25)	|x			|3.14
	fmul st0,st1		;x*sqrt((3.14-x)*0.25)	|x			|3.14
	fild word[bx-8]		;y=dh*256				|xa = x*...	|x			|3.14
	fidiv word[si]		;y=y/f					|xa = x*...	|x			|3.14
	fst	 st4			;y=y/f					|xa = x*...	|x			|3.14		y/f
	faddp st1,st0		;y=y+xa					|x			|3.14		|y/f
	fmul st0,st0		;y*y					|x			|3.14		|y/f
	fxch st1			;x						|y*y		|3.14		|y/f
	fmul st0,st0		;x*x					|y*y		|3.14		|y/f

	;---some nice glitch for outside of the heart	
	fld st3				;y/f					|x*x		|y*y		|3.14		|y/f
	fld st1				;x*x					|y/f		|x*x		|y*y		|3.14		|y/f
	fpatan				;atan(x*x/(y/f))		|x*x		|y*y		|3.14		|y/f
	fimul word[si]		;atan(x*x/(y/f))*f		|x*x		|y*y		|3.14		|y/f
	fistp word[bx-8]	;x*x					|y*y		|3.14		|y/f
	;---

	faddp st1,st0		;x*x+y*y				|3.14		|y/f
	fild word[bp+si]	;timer					|x*x+y*y	|3.14		|y/f
	fdiv st0,st2		;t/tf					|x*x+y*y	|3.14		|y/f				;timer adjust speed
	fdiv st0,st2		;t/tf					|x*x+y*y	|3.14		|y/f				;timer adjust speed
	fld st3				;y/f					|t/tf		|x*x+y*y	|3.14		|y/f	
	fmul dword[si]		;y/f*wf					|t/tf		|x*x+y*y	|3.14		|y/f	;adjust wobblyness or ?	
	faddp st1,st0 		;t/tf+y/f				|x*x+y*y	|3.14		|y/f
	fsin				;sin(t/tf)				|x*x+y*y	|3.14		|y/f
	fmul st0,st0		;sin(t/tf)^2			|x*x+y*y	|3.14		|y/f				;pow^2 gives a more 'pumping' effect
	fmul dword[si]		;sin(t/tf)*wf			|x*x+y*y	|3.14		|y/f				;scale effect on heart
	faddp st1,st0		;sin(t/tf)*wf + x*x+y*y	|3.14		|y/f
	fimul word[si]		;c*f					|3.14		|y/f
	fistp word[bx-5]	;3.14					|y/f					;store and scale down by 256 (bx-5)
	popa
	cmp al,63
	jb inside_heart		;original vga palette for background if outside
		and al,dh
		and al,10000b
		add al,0x4e
		xor al,byte[gs:di-320*5]
	inside_heart:
	mov byte[fs:di],al		
	inc di
shortcut:	
jnz frame_loop

;--midi & instrument init
  mov dx,0x331				
  mov al,0x3f
  out dx,al
  dec dx
  mov al,11000000b			;instrument change
  out dx,al
  mov al,106				;98=crystal, 106=Shamisen, 108=Kalimba are funny
  out dx,al

;---tune check & play
  mov bl,byte[bp+si]
  test bl,00000001b			;check timer
  jnz dont_do_anything
	and bl,111111b
	shr bl,2				;check with jnc later
	mov al,byte[si+bx+4]	;get byte from 4 Bit table, 32 notes/pauses
	jnc note_even			;even or uneven note count ?
		shr al,4			;mask upper half
	note_even:
	and al,00001111b		;mask lower half
	jz dont_do_anything 	;zero note is 'pause'
		push ax
		mov al,10010000b    ;play note 1001cccc | cccc = channel = 0
		out dx,al
		pop ax	
		add al,63;+12		;add base note level 'E'-1 = 63
		out dx,al
		mov al,01111111b	;play loud
		out dx,al
	dont_do_anything:

;---vsync
mov dx,3dah	
vsync:
  in al,dx
  test al,8
jz vsync

;---copy_screen
copy_screen_loop:
  mov al,byte[fs:di]
  stosb
loop copy_screen_loop

add word[bp+si],2		;pseudo timer inc by 2 for melody

;---check_keyboard 
in al,0x60				;check for ESC
dec al					;use dec al, if ah isn't zero...
jnz shortcut
cons:
ret				
db 63			;factor incl. 'ret' for x/y scale
dw 0x3f00		;0.5 "wf" adjust effect
kiss_tune		db 	 1+0*16, 3+0*16, 4+0*16, 6+8*16, 0+8*16, 6+0*16, 4+0*16, 3+0*16
				db 	 1+0*16, 3+0*16, 4+0*16, 6+8*16, 0+8*16, 6+0*16;,      0,      0; skip as DOSBox inits to zero
