;"Rotterdam'92 speaker membrane penetration" by Kuemmel for Outline demo compo 2019
use16
org	100h
;---screen init
push 0a000h-70			;modified to center x
aas						;aspect ratio constant part
pop es
mov al,0x13
int 0x10
;---sound irq init
mov dx,irq				;new handler address
mov al,110				;PIT counter divisor => 1,19318181818 MHz / 110 = 10847 Hz
out 40h,al				;write PIT counter divisor low byte
salc					;al=0, carry zero here
out 40h,al				;write PIT counter divisor high byte
mov ax,251ch			;251ch instead of 2508h, saves 4 Bytes in the int loop, might crash on some DOS ?
int 21h
;---graphics
screen_loop:
	mov	ax,0xcccd
	mul	di
	sub dh,100			;align vertically...can't use byte[si] as it's the changing top timer
	pusha
	fild word[bx-8] 
	fmul st0,st0
	fild word[bx-9]
	fmul dword[si]		;aspect ratio correction
	fmul st0,st0	
	fadd st0,st1
	fsqrt
	fistp dword[bx-5]
	popa
	add al,byte[bp+si]	;get sound byte from bass drum
	shr al,3
	adc al,16			;start at greyscale from standard palette
	stosb
jmp screen_loop
;---bytebeat interrupt subroutine based on ideas from http://www.pouet.net/topic.php?which=8357&page=1
irq:
pusha
mov ax,0				;ax: timer => word needed for self modifying code
.counter:
;--- (Math.sqrt(t&4095)<<7) => proper bass drum at around 160 BPM
mov word[bp+si],ax
and word[bp+si],0000111111111000b ;default is 4095, but lowering that gives dirtier/fancier results
fild word[bp+si]
fsqrt
fistp word[bp+si]		;preserved for sound visualisation also :-)
mov bl,byte[bp+si]		;shr byte[bp+si],7 would be possible and saves bytes but kills the visualisation...
shl bl,7
;--- ((t|t>>6|t>>7)*(t<<pattern))&127 => 'melody' ;-)
mov cx,ax
mov dx,ax
shr cx,6
or dx,cx
shr cx,1
or dx,cx				;dx = (t|t>>6|>>7)
mov cl,ch				;cl = (t>>15) => ch already t>>7
;--- the following results in 4 consecutive patterns (t>>1),(t),(t>>1),(t<<1)
;--- patterns change every 3 s (2^16/10847/2) => track repeats about every 12 s
shl ax,cl
shr ax,1
test byte[si],cl
jz skip_shift_left
	shl ax,1
skip_shift_left:
;--- final sound design	
mul dx					;(t|t>>6|t>>7)*(t<<pattern)
and al,127				;limit range between 0 and 127 for bass drum OR-ing, try also shr al,1 or skip line
or al,bl				;finally glue together bass & melody
mov dx,0378h			;LPT1 parallel port address
out dx,al				;write 8 bit sample data
inc word[si-0x100+irq.counter-2];inc timer each interrupt call within code
popa
jnz skip_inc_top_timer
	inc byte[si]		;top timer, lowest byte of dword aspect ratio correction not important :-)
skip_inc_top_timer: 
iret