	include	lvo/dos_lib.i
	include	lvo/exec_lib.i
	include	dos/dos.i

print	macro
	move.l	DOSBASE,a6
	lea	.\@a(pc),a0
	move.l	a0,d1
	jsr	_LVOPutStr(a6)
	bra.s	.\@b
.\@a	dc.b	"\1\n",0
	cnop	0,4
.\@b
	endm
	
	machine	68020

	move.l	4.w,a6
	lea	dosname,a1
	moveq	#37,d0
	jsr	_LVOOpenLibrary(a6)
	move.l	d0,DOSBASE
	beq.s	.fail3

	;-----------
	print	<Generating sine table>
	bsr	SINE_GEN
	print	<Generating samples>
	bsr	GENERATE_SAMPS

	;-----------
	lea	s1name(pc),a0
	bsr	Open
	beq	.fail1

	print	<Generating song 1 - Man On Mars>
	move.l	#3156,SPL
	move.l	#30,PATS
	move.l	#SONG_1,PATLIST
	bsr	GENERATE_SONG

	print	<Saving 'Push_ManOnMars.svx'>
	bsr	Save
.fail1
	;-----------
	lea	s2name(pc),a0
	bsr	Open
	beq	.fail2

	print	<Generating song 2 - Lost Love>
	move.l	#4584,SPL
	move.l	#18,PATS
	move.l	#SONG_2,PATLIST
	bsr	GENERATE_SONG

	print	<Saving 'Push_LostLove.svx'>
	bsr	Save
	print	<done>
.fail2
	;-----------
	move.l	DOSBASE,a1
	move.l	4.w,a6
	jsr	_LVOCloseLibrary(a6)
.fail3	moveq	#0,d0
	rts


Open	move.l	a0,d1
	move.l	#MODE_NEWFILE,d2
	move.l	DOSBASE,a6
	jsr	_LVOOpen(a6)
	move.l	d0,FH
	rts

Save	move.l	#SONG_BUFFER,d0
	move.l	a5,d1
	sub.l	d0,d1
	addq.l	#3,d1
	andi.w	#-4,d1
	move.l	d1,_len
	move.l	d1,_len2
	add.l	#40,d1
	move.l	d1,_len40
	move.l	FH,d1
	move.l	#header,d2
	moveq	#48,d3
	move.l	DOSBASE,a6
	jsr	_LVOWrite(a6)
	move.l	FH,d1
	move.l	#SONG_BUFFER,d2
	move.l	a5,d3
	sub.l	d2,d3
	jsr	_LVOWrite(a6)
	move.l	FH,d1
	jsr	_LVOClose(a6)
	rts

dosname	dc.b	'dos.library',0
s1name	dc.b	'Push_ManOnMars.svx',0
s2name	dc.b	'Push_LostLove.svx',0
	cnop	0,4

header	dc.l	"FORM"
_len40	dc.l	0	; = length+40
	dc.l	"8SVX"
	dc.l	"VHDR"
	dc.l	20
_len	dc.l	0	; = length
	dc.l	0
	dc.l	0
	dc.l	(28003<<16) + (1<<8) + 0
	dc.l	$10000
	dc.l	"BODY"
_len2	dc.l	0	; = length


SPL	dc.l	0	; SPL=number of samples per line of trackdate
PATS	dc.l	0	; number of patterns in patternlist
PATLIST	dc.l	0	; patternlist
DOSBASE	dc.l	0
FH	dc.l	0

SINE_GEN
	lea	SINE_BUFFER,a1
	move.w	#$7FFF,d0
	move.l	#$145F,d5
	mulu.w	d5,d0
	moveq	#0,d2
	moveq	#0,d7
.gen	move.l	d2,d3
	divs.l	d5,d3
	sub.l	d3,d0
	move.l	d0,d1
	divs.l	d5,d1
	add.l	d1,d2
	move.w	d3,(a1,d7.w*4)		;d7*8+0
	move.w	d1,(2,a1,d7.w*4)	;d7*8+2
	addq.w	#1,d7
	move.w	d3,(a1,d7.w*4)		;d7*8+4
	move.w	d1,(2,a1,d7.w*4)	;d7*8+6
	addq.w	#1,d7
	bne.b	.gen	; loop d7=0 to 65535
	rts

GENERATE_SAMPS
	lea	(SINE_BUFFER).l,a5
	lea	(SAMP_LIST).l,a4
	lea	(SAMPLES_BUFFER).l,a6
	moveq	#-1,d7
	move.l	a6,(a4)+
	clr.l	(a4)+
	move.l	#$1234567,d0
	move.l	#$10010010,d6
	move.l	#$1010040,d5
	move.l	#$A010160,d4
	move.l	#$30001,d3
	movea.w	#$10,a1
	bsr.w	GENERATE_SAM_1
	bsr.w	.write_list
	move.l	#$12345678,d0
	move.l	#$1010010,d6
	move.l	#$2010100,d5
	move.l	#$FFFF6000,d4
	move.l	#$10004,d3
	movea.w	#1,a1
	bsr.w	GENERATE_SAM_1
	bsr.w	.write_list
	move.l	#$23456789,d0
	move.l	#$1010100,d6
	move.l	#$1010100,d5
	move.l	#$FFFF6000,d4
	move.l	#$40010,d3
	movea.w	#1,a1
	bsr.w	GENERATE_SAM_1
	bsr.w	.write_list
	move.l	#$3456789A,d0
	move.l	#$1010100,d6
	move.l	#$2010080,d5
	move.l	#$FFFF7000,d4
	move.l	#$10001,d3
	suba.w	a1,a1
	bsr.w	GENERATE_SAM_1
	bsr.w	.write_list
	move.l	#$456789AB,d0
	move.l	#$4010004,d6
	move.l	#$4800008,d5
	move.l	#$1400400,d4
	move.l	#$10001,d3
	movea.w	#2,a1
	bsr.w	GENERATE_SAM_1
	bsr.w	.write_list
	move.l	#$56789ABC,d0
	move.l	#$3010010,d6
	move.l	#$3010004,d5
	move.l	#$4010240,d4
	move.l	#$10001,d3
	movea.w	#2,a1
	bsr.w	GENERATE_SAM_1
	bsr.w	.write_list_2
	lea	(s1,pc),a0
	bsr.w	GENERATE_SAM_2
	bsr.w	.write_list_2
	lea	(s2,pc),a0
	bsr.w	GENERATE_SAM_2
	bsr.w	.write_list_2
	lea	(s3,pc),a0
	bsr.w	GENERATE_SAM_2
	bsr.w	.write_list_2
	lea	(s4,pc),a0
	bsr.w	GENERATE_SAM_2
	bsr.w	.write_list_2
	lea	(s5,pc),a0
	bsr.w	GENERATE_SAM_2
	bsr.w	.write_list_2
	lea	(s6,pc),a0
	bsr.w	GENERATE_SAM_2
	bsr.w	.write_list_2
	lea	(s7,pc),a0
	bsr.w	GENERATE_SAM_2
	bsr.w	.write_list
	move.l	#$DEADBEEF,d0
	moveq	#-1,d7
.noise	ror.l	d0,d0
	add.l	d7,d0
	addq.l	#5,d0
	move.w	d0,d1
	ext.w	d1
	move.w	d1,(a6)+
	dbra	d7,.noise
	bsr.w	.write_list_2
	lea	(s8,pc),a0
	bsr.w	GENERATE_SAM_2
	movea.l	(-8,a4),a6
	moveq	#-1,d7
1$	move.w	(a6),d0
	muls.w	#$A6,d0
	asr.w	#8,d0
	move.w	d0,(a6)+
	dbra	d7,1$
	bsr.w	.write_list_2
	move.w	#$800,d0
	move.w	#$403,d1
	move.w	#$805,d2
	move.w	#$407,d3
	move.w	#$100,d4
	moveq	#7,d5
	bsr.w	GENERATE_SAM_3
	bsr.w	.write_list_2
	move.l	a6,(a4)+
	move.l	#$C0,(a4)+
	move.l	#$800,d0
	move.l	#$1005,d1
	move.l	#$815,d2
	move.l	#$1025,d3
	bsr.w	GENERATE_SAM_4
	bsr.w	.write_list_2
	move.l	#$800,d0
	move.l	#$805,d1
	move.l	#$815,d2
	move.l	#$825,d3
	bsr.w	GENERATE_SAM_4
	bsr.w	.write_list_2
	move.w	#$1000,d0
	move.w	#$1002,d1
	move.w	#$803,d2
	move.w	#$2004,d3
	move.w	#$400,d4
	moveq	#-1,d5
	bsr.w	GENERATE_SAM_3
	movea.l	(-8,a4),a6
	adda.l	#$20000,a6
	move.l	a6,(a4)+
	move.l	#$60,(a4)+
	lea	(PIANO_SAM).l,a0
	move.w	#$349D,d7
.psam	move.b	(a0)+,d0
	ext.w	d0
	move.w	d0,(a6)+
	dbra	d7,.psam
	bsr.w	.write_list_2
	move.l	a6,(a4)+
	clr.l	(a4)+
	move.l	a6,(a4)+
	clr.l	(a4)+
	move.l	a6,(a4)+
	move.l	#$C0,(a4)+
	lea	(s9,pc),a0
	bsr.w	GENERATE_SAM_2
	rts

.write_list	movea.l	(-8,a4),a6
	adda.l	#$20000,a6
	move.l	a6,(a4)+
	clr.l	(a4)+
	rts

.write_list_2	movea.l	(-8,a4),a6
	adda.l	#$20000,a6
	move.l	a6,(a4)+
	move.l	#$C0,(a4)+
	rts

s1	dc.w	$7F,$1FF,0,$180,$8000,$100,1,0,0,0,0,0,0,0
s2	dc.w	$3F,$1FF,2,$40,0,$100,0,1,$400,$2000,$20,$FFD0,$100,$FFFF
s3	dc.w	$3F,$1FF,2,$40,0,$100,0,1,$600,$2000,$20,$FFB0,$100,$FFFF
s4	dc.w	$3F,$1FF,2,$40,0,$100,0,1,$800,$2000,$20,$FF90,$100,$FFFF
s5	dc.w	$3F,$1FF,2,$40,0,$100,0,1,$A00,$2000,$20,$FF70,$100,$FFFF
s6	dc.w	$7FF,$1F,0,$A00,0,$200,$20,0,$1000,$1000,$40,4,0,0
s7	dc.w	$FF,$3F,1,$400,$A000,$180,$10,4,$81B,$2000,$20,$FFF0,$FFF0,0
s8	dc.w	$FF,$3F,1,$400,$A000,$180,$10,4,$81B,$2000,$20,$FFF0,$FFF0,0
s9	dc.w	2,$1F,4,$400,$E000,$100,$20,$10,$2000,$1000,$40,$FF80,$FF40,$FFF8
s10	dc.w	$7FF,15,0,$A00,0,$200,$20,0,$2000,$1000,$80,8,0,0

GENERATE_SAM_3	movea.w	#$123,a0
	movea.w	#$4567,a1
	movea.w	#$89AB,a2
	movea.w	#$CDEF,a3
	moveq	#-1,d7
1$	move.l	d5,-(sp)
	move.w	(a5,a0.w*4),d6
	ext.l	d6
	move.w	(a5,a1.w*4),d5
	ext.l	d5
	add.l	d5,d6
	move.w	(a5,a2.w*4),d5
	ext.l	d5
	asr.l	#1,d5
	add.l	d5,d6
	move.w	(a5,a3.w*4),d5
	ext.l	d5
	asr.l	#1,d5
	add.l	d5,d6
	move.l	(sp)+,d5
	divs.w	d4,d6
	cmp.w	#$7F,d6
	blt.b	2$
	moveq	#$7F,d6
2$	cmp.w	#$FF80,d6
	bgt.b	3$
	moveq	#-$80,d6
3$	move.w	d6,(a6)+
	adda.w	d0,a0
	adda.w	d1,a1
	adda.w	d2,a2
	adda.w	d3,a3
	tst.w	d5
	bmi.b	4$
	move.w	d7,d6
	and.w	d5,d6
	bne.b	4$
	addq.w	#1,d4
	bpl.b	4$
	subq.w	#1,d4
4$	dbra	d7,1$
	rts

GENERATE_SAM_4	suba.l	a0,a0
	suba.l	a1,a1
	suba.l	a2,a2
	suba.l	a3,a3
	moveq	#-1,d7
1$	move.w	(a5,a0.w*4),d6
	ext.l	d6
	move.w	(a5,a1.w*4),d5
	ext.l	d5
	add.l	d5,d6
	move.w	(a5,a2.w*4),d5
	ext.l	d5
	add.l	d5,d6
	move.w	(a5,a3.w*4),d5
	ext.l	d5
	add.l	d5,d6
	asr.l	#8,d6
	asr.l	#2,d6
	move.w	d6,(a6)+
	adda.w	d0,a0
	adda.w	d1,a1
	adda.w	d2,a2
	adda.w	d3,a3
	dbra	d7,1$
	rts

GENERATE_SAM_2	move.l	a4,-(sp)
	move.w	#$7FFF,d7
	move.w	#$4000,d3
	move.w	(a0)+,d4
1$	move.w	(a0),d5
	movea.w	(4,a0),a4
	move.w	(6,a0),d6
	movea.w	(14,a0),a2
	move.w	($10,a0),d2
	movea.w	#$8000,a1
2$	move.w	(a5,d6.w*4),d1
	ext.l	d1
	lsl.l	#8,d1
	move.w	(8,a0),d0
	ext.l	d0
	divs.l	d0,d1
	move.w	(a5,a1.w*4),d0
	muls.w	d2,d0
	asr.l	#8,d0
	asr.l	#6,d0
	add.l	d0,d1
	move.w	(a5,d3.w*4),d0
	asr.w	#3,d0
	ext.l	d0
	muls.l	d0,d1
	swap	d1
	asr.w	#4,d1
	bsr.w	CLAMP
	move.w	d1,(a6)+
	adda.w	a2,a1
	sub.w	($12,a0),d2
	bpl.b	3$
	moveq	#0,d2
3$	add.w	(2,a0),d3
	bpl.b	4$
	move.w	#$7FFF,d3
4$	add.w	a4,d6
	suba.w	(10,a0),a4
	dbra	d5,2$
	move.w	(12,a0),d2
	add.w	d2,(8,a0)
	move.w	($14,a0),d2
	add.w	d2,(14,a0)
	move.w	($16,a0),d2
	add.w	d2,($10,a0)
	move.w	($18,a0),d2
	add.w	d2,($12,a0)
	dbra	d4,1$
	movea.l	(sp)+,a4
	rts

GENERATE_SAM_1	move.w	#$7FFF,d7
	suba.l	a0,a0
1$	ror.l	d0,d0
	addq.l	#7,d0
	move.w	d0,d2
	ext.l	d2
	move.w	a1,d1
	asr.l	d1,d2
	divs.w	d5,d2
	move.w	(a5,a0.w*4),d1
	ext.l	d1
	divs.w	d6,d1
	add.w	d2,d1
	bsr.w	CLAMP
	move.w	d1,(a6)+
	swap	d6
	subq.b	#1,d6
	bne.b	4$
	move.w	d6,d1
	lsr.w	#8,d1
	move.b	d1,d6
	swap	d6
	add.w	d3,d6
	bmi.b	2$
	bne.b	3$
2$	move.w	#$7FFF,d6
3$	swap	d6
4$	swap	d6
	swap	d3
	swap	d5
	subq.b	#1,d5
	bne.b	7$
	move.w	d5,d1
	lsr.w	#8,d1
	move.b	d1,d5
	swap	d5
	add.w	d3,d5
	bmi.b	5$
	bne.b	6$
5$	move.w	#$7FFF,d5
6$	swap	d5
7$	swap	d5
	swap	d3
	swap	d4
	subq.b	#1,d4
	bne.b	9$
	move.w	d4,d1
	lsr.w	#8,d1
	move.b	d1,d4
	swap	d4
	cmp.w	#$30,d4
	beq.b	8$
	subq.w	#1,d4
8$	swap	d4
9$	swap	d4
	adda.w	d4,a0
	dbra	d7,1$
	rts

CLAMP	cmp.w	#$7F,d1
	ble.b	1$
	moveq	#$7F,d1
1$	cmp.w	#$FF80,d1
	bge.b	2$
	moveq	#-$80,d1
2$	rts


GENERATE_SONG
	move.l	PATS,d3
	lea	SONG_BUFFER,a5
	move.l	PATLIST,a4
.pat	moveq	#0,d0
	move.b	(a4)+,d0
	lea	(SONG_DATA).l,a0
	move.l	(a0,d0.w*4),d0
	lea	(a0,d0.l),a6
	lea	PATTERN_BUFFER,a2
	bsr.w	.generate_pattern
	lea	PATTERN_BUFFER,a0
	moveq	#$7F,d1
	moveq	#-$80,d2
	move.l	SPL,d7
	asl.l	#6,d7
.samp	move.w	(a0),d0
	clr.w	(a0)+
	asr.w	#2,d0	; crap 4 channel mixdown -> 1 channel
	cmp.w	d1,d0	; clamp between -$80 and $7f
	ble.b	.lo
	move.w	d1,d0
.lo	cmp.w	d2,d0
	bge.b	.hi
	move.w	d2,d0
.hi	move.b	d0,(a5)+
	subq.l	#1,d7
	bne.b	.samp
	bsr.s	.print
	dbra	d3,.pat
	rts

.print	movem.l	a0/d0-d2/a6,-(sp)
	lea	.msg(pc),a0
	move.l	a0,d1
	lea	.togo(pc),a0
	move.w	d3,(a0)
	move.l	a0,d2
	move.l	DOSBASE,a6
	jsr	_LVOVPrintf(a6)
	movem.l	(sp)+,a0/d0-d2/a6
	rts
.togo	dc.w	0
.msg	dc.b	'%d patterns to go\n',0
	cnop	0,4

.generate_pattern
	moveq	#$3F,d5
1$	move.b	(a6)+,d0
	beq.w	6$
	move.w	d0,d1
	andi.w	#$F0,d1
	lea	(BLAH_1).l,a0
	adda.w	d1,a0
	btst	#0,d0
	beq.b	2$
	moveq	#0,d1
	move.b	(a6)+,d1
	move.l	d1,d2
	lsr.b	#4,d2
	mulu.w	#12,d2
	andi.w	#15,d1
	add.w	d1,d2
2$	btst	#1,d0
	beq.b	3$
	moveq	#0,d1
	move.b	(a6)+,d1
	lea	(BLAH_2).l,a1
	move.w	(6,a1,d1.w*8),(12,a0)
	move.l	(a1,d1.w*8),d1
	addi.l	#$10000,d1
	move.l	d1,(8,a0)
	move.w	#$40,(14,a0)
3$	btst	#0,d0
	beq.b	4$
	lea	PERIOD_TABLE,a1
	add.w	(12,a0),d2
	move.w	(-$18,a1,d2.w*2),d2
	move.l	#$1F00000,d1
	divu.l	d2,d1
	move.l	#$80000000,(a0)
	move.l	d1,(4,a0)
4$	btst	#2,d0
	beq.b	5$
	move.b	(a6)+,(15,a0)
5$	bra.w	1$

6$	lea	(BLAH_1).l,a0
	moveq	#15,d6
7$	movea.l	a2,a3
	move.l	(a0)+,d0
	move.l	(a0)+,d1
	movea.l	(a0)+,a1
	move.l	(a0)+,d2
	tst.w	d2
	beq.b	11$

	move.w	SPL+2,d7	; samples to write
	subq.w	#1,d7
	cmp.w	#$40,d2
	blt.b	9$
8$	move.w	(a3),d4
	swap	d0
	add.w	(a1,d0.w*2),d4
	swap	d0
	add.l	d1,d0
	move.w	d4,(a3)+
	dbra	d7,8$
	bra.b	10$

9$	swap	d0
	move.w	(a1,d0.w*2),d4
	swap	d0
	add.l	d1,d0
	muls.w	d2,d4
	lsr.l	#6,d4
	add.w	d4,(a3)+
	dbra	d7,9$
10$	move.l	d0,(-$10,a0)
11$	dbra	d6,7$

	move.w	SPL+2,d1
	lea	(a2,d1.w*2),a2	; samples per line * 2 bytes (16bit)
	dbra	d5,1$
	rts

;---------------------------------------------------------------------------

	section	2,data
PERIOD_TABLE	incbin	pertab
SONG_DATA	incbin	song_data
PIANO_SAM	incbin	piano.sam
SONG_1		dc.b	6,7,$17,$18,0,1,2,3,8,$23,$14,9,10,11,$1F,$20,$10
		dc.b	$11,8,$23,$25,9,$12,$13,12,13,$21,$22,$24,$15,$16
SONG_2		dc.b	$1C,$1D,$19,$1A,$1B,$1E,$29,$2D,$32,$33,$30,$31
		dc.b	$2E,$2F,$34,$35,$36,$37,$38


;---------------------------------------------------------------------------

	section	3,bss
SINE_BUFFER=*+(32768*4+4)
	ds.b	65536*4+8	; what would the C64 think of that?

	section	4,bss
SAMPLES_BUFFER	equ	*+$000000
PATTERN_BUFFER	equ	*+$2A4000	; shocking
SONG_BUFFER	equ	*+$337400	; disgraceful
		ds.b	  $93FF00	; call the memory police

	section	5,bss
BLAH_2		equ	*-8		; yes, we want it pointing at hunk size
SAMP_LIST	ds.l	$40
BLAH_1		ds.l	$40
