; --------------------------------------------- ;
;    DELTA MUSIC REPLAY-ROUTINE V1.0 (PACKED)   ;
; --------------------------------------------- ;
;						;
;   CODED BY :  BENT "SHOGUN" NIELSEN		;
;		KYRADSERVEJ 19 B		;
;		8700 HORSENS			;
;		DENMARK				;
;		TEL. +45 75-601-868		;
;						;
; --------------------------------------------- ;
;     COPYRIGHT 1991, BARRICADE SOFTWARE tm	;
; --------------------------------------------- ;
;						;
;  This routine has been optimized a lot, but	;
;  I know it can be faster than this ....	;
;						;
;  All the text on the right side of the	;
;  source, is made to help those who want to	;
;  optimize it a little bit more, so please	;
;  don't remove it !!!!				;
;						;
;  By the way, it is 100% PC-relative, so you	;
;  can place it wherever you like .....		;
;						;
; --------------------------------------------- ;
;						;
;  HOW TO USE IT:				;
;  ~~~~~~~~~~~~~~				;
;						;
;  It's quite easy to use. You call INIT_MUSIC	;
;  once, and then you call REPLAY_MUSIC	every	;
;  vertical blanking .....			;
;						;
;  Remember to load a packed module into the	;
;  label call MODULE .....			;
;						;
; --------------------------------------------- ;


	org	$40000
	load	$40000


>extern	"DH1:ShogunMix",Module		; load module "ShogunMix"
					; to the module label

J:
	tst.l	module			; test if module has been loaded
	beq.s	exit			; if not exit

	move.l	$4,A6			; forbid multi-tasking
	jsr	-132(A6)

	bsr	Init_Music		; init music

Loop:
	cmp.b	#199,$dff006		; wait for rasterline 199
	bne.s	Loop

	move.w	#$ff0,$dff180		; set a color
	bsr	Replay_Music		; play music
	move.w	#$008,$dff180		; reset color

	btst	#6,$bfe001		; test for left-mouse
	bne.s	Loop

	move.w	#$000f,$dff096		; stop audio dma
	move.l	$4,A6			; permit multi-tasking
	jsr	-138(A6)

Exit:
	rts				; exit !!!!!



; --------------------------------------------- ;
;                  init music                   ;
; --------------------------------------------- ;

Init_Music:
	movem.l	D0-D7/A0-A6,-(A7)	; save all registers

	lea	Module(PC),A0		; get module pointer
	lea	Song_Data(PC),A1	; get song data list

	move.l	(A0)+,62(A1)		; save track1 repeat & length
	move.l	(A0)+,66(A1)		; save track2 repeat & length
	move.l	(A0)+,70(A1)		; save track3 repeat & length
	move.l	(A0)+,74(A1)		; save track4 repeat & length

	move.l	A0,10(A1)		; save track1 pointer
	add.w	64(A1),A0		; add track1 length
	move.l	A0,14(A1)		; save track2 pointer
	add.w	68(A1),A0		; add track2 length
	move.l	A0,18(A1)		; save track3 pointer
	add.w	72(A1),A0		; add track3 length
	move.l	A0,22(A1)		; save track4 pointer
	add.w	76(A1),A0		; add track4 length

	move.w	(A0)+,D0		; get arpeggio length
	move.l	A0,58(A1)		; save arpeggio pointer
	add.w	d0,A0			; add arpeggio length

	move.w	(A0)+,D0		; get sound offset length
	move.l	A0,6(A1)		; save sound offsets pointer
	add.w	D0,A0			; add sound offset length
	move.l	A0,2(A1)		; save sound pointer
	move.w	-2(A0),D0		; get highest sound offset
	add.l	#88,D0			; add one instrument
	add.w	D0,A0			; add highest sound offset

	move.w	(A0)+,D0		; get waveform offset length
	move.l	A0,78(A1)		; save waveform offset pointer
	add.w	D0,A0			; add waveform offset length
	move.w	(A0)+,D0		; waveform length
	move.l	A0,82(A1)		; save waveform pointer
	add.w	D0,A0			; add waveform length

	move.l	(A0)+,D0		; get block length
	move.l	A0,26(A1)		; save block pointer
	add.l	D0,A0			; add block length

	move.l	A0,38(A1)		; save sample offset pointer
	add.w	#32,A0			; add sample offset length
	move.l	A0,34(A1)		; save sample pointer

;;;;;;; NORMAL SETTINGS

	clr.b	30(A1)			; stop random noise
	move.l	78(A1),A0		; get sound offset pointer
	move.w	2(A0),D0		; get offset number 1
	sub.w	(A0),D0			; sub offset number 0
	cmp.w	#$40,D0			; test for noise on/off
	bmi.s	Init_Con		; if minus, no
	move.b	#1,30(A1)		; start random noise

Init_Con:
	clr.b	48(A1)			; clear playspeed counter

	bset	#1,$bfe001
	lea	Null_Waveform(PC),A0	; get null waveform
	lea	$dff000,A2		; get custom
	move.w	#$000f,$96(A2)		; stop audio dma
	move.w	#$0780,$9a(A2)		; stop audio irq
	move.l	A0,$a0(A2)		; set hardware addresses
	move.l	A0,$b0(A2)
	move.l	A0,$c0(A2)
	move.l	A0,$d0(A2)
	move.w	#4,$a4(A2)		; set hardware sample length
	move.w	#4,$b4(A2)
	move.w	#4,$c4(A2)
	move.w	#4,$d4(A2)
	move.w	#0,$a6(A2)		; set hardware periods
	move.w	#0,$b6(A2)
	move.w	#0,$c6(A2)
	move.w	#0,$d6(A2)
	move.w	#0,$a8(A2)		; set hardware volume
	move.w	#0,$b8(A2)
	move.w	#0,$c8(A2)
	move.w	#0,$d8(A2)

	lea	Null_Sound(PC),A2	; get null sound
	lea	Voice1(PC),A0		; get voice1
	move.l	10(A1),10(A0)		; set voice1 track pointer
	move.l	62(A1),54(A0)		; set track1 repeat & length
	bsr.w	Init_Voice		; init voice

	lea	Voice2(PC),A0		; get voice2
	move.l	14(A1),10(A0)		; set voice2 track pointer
	move.l	66(A1),54(A0)		; set track2 repeat & length
	bsr.s	Init_Voice		; init voice

	lea	Voice3(PC),A0		; get voice3
	move.l	18(A1),10(A0)		; set voice3 track pointer
	move.l	70(A1),54(A0)		; set track3 repeat & length
	bsr.s	Init_Voice		; init voice

	lea	Voice4(PC),A0		; get voice4
	move.l	22(A1),10(A0)		; set voice4 track pointer
	move.l	74(A1),54(A0)		; set track4 repeat & length
	bsr.s	Init_Voice		; init voice

	movem.l	(A7)+,D0-D7/A0-A6	; restore all registers
	rts

Init_Voice:
	clr.l	18(A0)			; clear track & block counter
	move.l	A2,6(A0)		; set null sound
	clr.b	51(A0)			; clear sound technique
	clr.w	48(A0)			; clear arpeggio counter
	move.l	58(A1),44(A0)		; set arpeggio pointer
	clr.l	32(A0)			; clear volume counter & volume
	clr.w	36(A0)			; clear volume sustain & portamento
	clr.w	30(A0)			; clear bendrate
	move.b	#$3f,29(A0)		; set channel volume
	rts


Replay_Music:
	movem.l	D0-D7/A0-A6,-(A7)	; save all registers
	lea	Song_Data(PC),A6	; get song data pointer
	clr.b   1(A6)			; disable hardware dma

; --------------------------------------------- ;
;            random noise calculator            ;
; --------------------------------------------- ;

	tst.b	30(A6)			; test noise on/off
	beq.s	No_Noise		; if zero, no noise

	move.l	82(A6),A3		; get random noise waveform
	move.l	42(A6),D1		; get random noise value
	moveq	#16-1,D0
Noise_Loop:
	rol.l	#7,D1
	add.l	#$6eca756d,D1
	eor.l	#$9e59a92b,D1
	move.l	D1,(A3)+
	dbf	D0,Noise_Loop
	move.l	D1,42(A6)		; save random noise value

No_Noise:
	subq.b	#1,48(A6)		; decrease playspeed counter
	bpl.s	Playspeed_Ok		; if plus, continue
	move.b	47(A6),48(A6)		; reset playspeed

Playspeed_Ok:
	lea	Voice1(PC),A0		; get voice1
	bsr.l	Play_Voice		; play voice

	lea	Voice2(PC),A0		; get voice2
	bsr.l	Play_Voice		; play voice

	lea	Voice3(PC),A0		; get voice3
	bsr.l	Play_Voice		; play voice

	lea	Voice4(PC),A0		; get voice4
	bsr.l	Play_Voice		; play voice

	move.w	0(A6),$dff096		; enable hardware dma
	movem.l	(A7)+,d0-d7/a0-a6	; restore all registers
	rts				; return ....

Play_Voice:
	move.l  0(A0),A1		; get hardware pointer
	move.l  6(A0),A2		; get sound pointer

; --------------------------------------------- ;
;                sample handler                 ;
; --------------------------------------------- ;

	tst.b	51(A0)			; test sound technique
	bpl.s	Track_Handler		; if plus, skip
	clr.b	51(A0)			; clear sound technique

	move.l	38(A6),A3		; get samples offset
	move.b	39(A2),D0		; get sample number
	and.w	#7,D0			; max. 8 samples
	add.w	D0,D0			; mulu with 4
	add.w	D0,D0
	add.w	D0,A3			; add sample number
	move.l	(A3),A4			; get sample offset
	add.l	34(A6),A4		; add sample pointer

	moveq	#0,D0
	move.w	4(A2),4(A1)		; set sample repeat length
	move.w	2(A2),D0		; get sample repeat
	clr.w	(A4)			; clear first word of sample
	add.w	D0,A4			; add sample repeat
	move.l	A4,0(A1)		; set hardware address

; --------------------------------------------- ;
;                 track handler                 ;
; --------------------------------------------- ;

Track_Handler
	tst.b	48(A6)			; test playspeed counter
	bne.l	Sound_Handler

	tst.w	20(A0)			; test block counter
	bne.s	Block_Handler		; if not zero, skip
	moveq	#0,D0			; clear d0
	move.l	10(A0),A3		; get track pointer
	move.w	18(A0),D1		; get track counter
	move.b	0(A3,D1.W),D0		; get block number
	move.b	1(A3,D1.W),43(A0)	; set transpose
	asl.l	#6,D0			; mulu with 64
	add.l	26(A6),D0		; add block pointer
	move.l	D0,14(A0)		; set block pointer
	addq.w	#2,D1			; add one track step
	move.w	D1,18(A0)		; set track counter
	cmp.w	56(A0),D1		; compare track length & track counter
	bmi.s	Block_Handler		; if minus, skip
	move.w	54(A0),18(A0)		; reset track counter

; --------------------------------------------- ;
;                 block handler                 ;
; --------------------------------------------- ;

Block_Handler:
	move.l	14(A0),A3		; get block pointer
	add.w	20(A0),A3		; add track counter
	moveq	#0,D0			; clear d0
	move.b	(A3),D0			; get note
	beq.l	Block_FX		; if zero, try fx
	move.w	4(A0),$dff096		; stop audio dma
	move.b	D0,28(A0)		; save frequency number
	lea	frequency_table(pc),A4
	add.b	43(A0),D0		; add transpose
	add.w	D0,D0			; mulu with 2
	move.w	0(A4,D0.W),26(A0)	; set frequency compare

	moveq	#0,D1			; clear d1
	move.b	1(A3),D1		; get sound number
	subq.w	#1,D1			; sub an instrument
	add.w	D1,D1			; mulu with 2
	move.l	6(A6),A4		; get sound offset pointer
	add.w	D1,A4			; calculate actual offset

	move.l	2(A6),A2		; get sound pointer
	add.w	(A4),A2			; add sound offset
	move.l	A2,6(A0)		; save new sound pointer
	move.b	38(A2),51(A0)		; set sound technique
	bpl.s	Block_Con		; if plus, synthetic

	move.l	38(A6),A4		; get sample offset pointer
	move.b	39(A2),D0		; get sample number
	and.w	#7,D0			; max. 8 samples
	add.w	D0,D0			; mulu with 4
	add.w	D0,D0
	add.w	D0,A4			; add sample number
	move.l	(A4),A4			; get sample offset
	add.l	34(A6),A4		; add sample pointer
	move.l	A4,0(A1)		; set hardware address
	move.w	0(A2),4(A1)		; set hardware length

Block_Con:
	clr.w	22(A0)			; clear synthetic delay & counter
	clr.l	32(A0)			; clear volume counter & volume
	clr.b	36(A0)			; clear volume sustain
	clr.w	48(A0)			; clear arpeggio counter
	clr.l	38(A0)			; clear vibrato wait, status & value
	move.b	22(A2),42(A0)		; reset vibrato counter
	clr.b	52(A0)			; clear vibrato counter 2
	move.b	23(A2),53(A0)		; reset vibrato sustain

Block_FX:
	move.b	2(A3),D0		; get effect byte
	subq.b	#1,D0			; decrease effect
	bmi.s	Increase_Block		; if minus, no effect
	move.b	3(A3),D1		; get effect data
	and.w	#7,D0			; max. 8 effects
	add.w	D0,D0			; mulu with 4
	add.w	D0,D0
	jmp	Effect_Table(PC,D0.W)

Effect_Table:
	bra.l	Effect01
	bra.l	Effect02
	bra.l	Effect03
	bra.l	Effect04
	bra.l	Effect05
	bra.l	Effect06
	bra.l	Effect07
	bra.l	Effect08

Increase_Block:
	addq.w	#4,20(A0)		; increase block counter
	and.w	#$3f,20(A0)		; mask block counter


; --------------------------------------------- ;
;                 sound handler                 ;
; --------------------------------------------- ;

Sound_Handler:
	tst.b	38(A2)			; test sound technique
	bmi.s	Vibrato_Handler		; if minus, skip

	tst.b	22(A0)			; test synthetic delay
	beq.s	Do_Sound		; if zero, do sound
	subq.b	#1,22(A0)		; decrease synthetic delay
	bra.s	Vibrato_Handler		; done ...

Do_Sound:
	move.b	39(A2),22(A0)		; reset synthetic delay
	moveq	#0,D0			; clear d0
	moveq	#0,D2			; clear d2
	lea	40(A2),A3		; get waveform table
	move.b	23(A0),D0		; get synthetic counter
	addq.b	#1,23(A0)		; increase synthetic counter

	move.b	(A3,D0.W),D2		; get waveform number
	cmp.b	#$ff,D2			; test for 'end of table'
	bne.s	Sound_Con		; if not, skip
	move.b	1(A3,D0.W),D0		; get loop point
	move.b	D0,23(A0)		; reset synthetic counter
	move.b	(A3,D0.W),D2		; get new waveform number
	cmp.b	#$ff,D2			; test if still 'end of table'
	bne.s	Sound_Con		; if not, reset
	bra.s	Vibrato_Handler		; done ...

Sound_Con:
	add.w	d2,d2			; mulu with 2
	add.l	78(A6),D2		; add waveform offset pointer
	move.l	D2,A3			; d2 to a3
	move.w	(A3),D2			; get waveform offset
	move.l	82(A6),A3		; get waveform pointer
	add.w	D2,A3			; add waveform offset
	move.l	A3,0(A1)		; set hardware address
	move.w	0(A2),4(A1)		; set hardware length

; --------------------------------------------- ;
;                vibrato handler                ;
; --------------------------------------------- ;

Vibrato_Handler:
	moveq	#0,D0			; clear d0
	lea	21(A2),A3		; get vibrato table
	move.b	52(A0),D0		; get vibrato counter 2
	add.w	D0,A3			; add vibrato counter 2
	move.b	0(A3),D0		; get vibrato step
	tst.b	39(A0)			; test vibrato status
	bne.s	Vibrato_Minus
	add.w	D0,40(A0)		; increase vibrato value
	bra.s	Vibrato_Dec		; jump
Vibrato_Minus:
	sub.w	D0,40(A0)		; decrease vibrato value
Vibrato_Dec:
	subq.b	#1,42(A0)		; decrease vibrato counter
	bne.s	Vibrato_Con		; if not zero, skip
	move.b	1(A3),42(A0)		; reset vibrato counter
	not.b	39(A0)			; reverse vibrato status
Vibrato_Con:
	tst.b	53(A0)			; test vibrato sustain
	beq.s	Vibrato_Con2		; if zero, skip
	subq.b	#1,53(A0)		; decrease vibrato sustain
	bra.s	Volume_Handler		; done ...
Vibrato_Con2:
	addq.b	#3,52(A0)		; increase vibrato counter 2
	cmp.b	#15,52(A0)		; test vibrato counter 2
	bne.s	Vibrato_Con3
	move.b	#12,52(A0)		; reset vibrato counter 2
Vibrato_Con3:
	move.b	5(A3),53(A0)		; reset vibrato sustain

; --------------------------------------------- ;
;                volume handler                 ;
; --------------------------------------------- ;

Volume_Handler:
	tst.b	36(A0)			; test volume sustain
	beq.s	Do_Volume		; if zero, do volume
	subq.b	#1,36(A0)		; decrease volume sustain
	bra.s	Portamento_Handler	; done ...
Do_Volume:
	moveq	#0,D0			; clear d0
	moveq	#0,D1			; clear d1
	move.w	34(A0),D0		; get volume counter
	lea	6(A2),A3		; get volume table
	add.w	D0,A3			; add volume counter
	move.b	(A3),D0			; get volume rate
	move.b	1(A3),D1		; get volume level
	cmp.w	32(A0),D1		; compare volume with level
	bpl.s	Volume_Plus		; if plus, skip
	sub.w	D0,32(A0)		; decrease volume
	cmp.w	32(A0),D1		; compare volume with level
	bmi.s	Portamento_Handler	; if still minus, skip
	move.w	D1,32(A0)		; set volume to level
	bra.s	Volume_Con		; skip
Volume_Plus:
	add.w	D0,32(A0)		; increase volume
	cmp.w	32(A0),D1		; compare volume with level
	bpl.s	Portamento_Handler	; if still plus, skip
	move.w	D1,32(A0)		; set volume to level
Volume_Con:
	move.b	2(A3),36(A0)		; reset volume sustain
	addq.w	#3,34(A0)		; increase volume counter
	cmp.w	#15,34(A0)		; test volume counter
	bne.s	Portamento_Handler
	move.w	#12,34(A0)		; reset volume counter

; --------------------------------------------- ;
;              portamento handler               ;
; --------------------------------------------- ;

Portamento_Handler:
	moveq	#0,D0			; clear d0
	move.b	37(A0),D0		; get portamento
	beq.s	Arpeggio_Handler	; if zero, done ...
	move.w	26(A0),D1		; get frequency compare
	cmp.w	24(A0),D1		; test frequency
	bpl.s	Porta_Plus		; if plus, porta plus
	sub.w	D0,24(A0)		; decrease frequency
	cmp.w	24(A0),D1		; test frequency
	bmi.s	Arpeggio_Handler	; if still minus, skip
	move.w	D1,24(A0)		; reset frequency
	bra.s	Arpeggio_Handler	; done ...
Porta_Plus:
	add.w	D0,24(A0)		; increase frequency
	cmp.w	24(A0),D1		; test frequency
	bpl.s	Arpeggio_Handler	; if still plus, skip
	move.w	D1,24(A0)		; reset frequency

; --------------------------------------------- ;
;               arpeggio handler                ;
; --------------------------------------------- ;

Arpeggio_Handler:
	moveq	#0,D0			; clear d0
Arp_Repeat:
	move.l	44(A0),A3		; get arpeggio pointer
	add.w	48(A0),A3		; add arpeggio counter
	move.b	(A3),D0
	cmp.b	#$80,D0			; test for arpeggio repeat
	bne.s	Arp_Con			; if not, skip
	tst.w	48(A0)			; test arpeggio counter
	beq.s	Arp_Con
	clr.w	48(A0)			; reset arpeggio counter
	bra.s	Arp_Repeat
Arp_Con:
	addq.w	#1,48(A0)		; increase arpeggio counter
	and.w	#15,48(A0)		; max. 16 arpeggio bytes

	tst.b	37(A0)			; test portamento
	beq.s	No_Porta
	move.w	24(A0),D0		; get frequency
	bra.s	Set_Freq
No_Porta:
	lea	Frequency_Table(PC),A3	; get frequency table
	add.b	28(A0),D0		; add note number
	add.b	43(A0),D0		; add transpose
	add.w	D0,D0			; mulu with 2
	move.w	0(A3,D0.W),D0		; get frequency
	move.w	D0,24(A0)		; set frequency

Set_Freq:
	move.w	36(A2),D1		; get volume sustain
	sub.w	30(A0),D1		; sub channel bendrate
	sub.w	D1,40(A0)		; decrease vibrato value
	add.w	40(A0),D0		; add vibrato value

	move.w	D0,6(A1)		; set hardware frequency
	move.w	32(A0),D0		; get volume
	asr.w	#2,D0			; divu with 4
	cmp.b	29(A0),D0		; compare volume with channel volume
	bmi.s	Vol_Minus		; if <, skip
	move.b	29(A0),D0		; set volume to channel volume
Vol_Minus:
	cmp.b	46(A6),D0		; compare volume with song volume
	bmi.s	Vol_Minus2		; if <, skip
	move.b	46(A6),D0		; set volume to song volume

Vol_Minus2:
	move.w	D0,8(A1)		; set hardware volume
	move.w	4(A0),D0		; get audio dma on
	or.w	D0,0(A6)
	rts


; --------------------------------------------- ;
;             block effect routines             ;
; --------------------------------------------- ;

Effect01:
	and.b	#15,D1
	move.b	D1,47(A6)
	bra.l	Increase_Block

Effect02:
	tst.b	D1
	bne.s	FX02
	bset	#1,$bfe001
	bra.l	Increase_Block
FX02:
	bclr	#1,$bfe001
	bra.l	Increase_Block

Effect03:
	and.w	#$ff,D1
	neg.w	D1
	move.w	D1,30(A0)
	bra.l	Increase_Block

Effect04:
	and.w	#$ff,D1
	move.w	D1,30(A0)
	bra.l	Increase_Block

Effect05:
	move.b	D1,37(A0)
	bra.l	Increase_Block

Effect06:
	and.b	#$3f,D1
	move.b	D1,29(A0)
	bra.l	Increase_Block

Effect07:
	and.b	#$3f,D1
	move.b	D1,46(A6)
	bra.l	Increase_Block

Effect08:
	and.l	#$3f,D1
	asl.l	#4,D1
	move.l	58(A6),A4
	add.l	D1,A4
	move.l	A4,44(A0)
	bra.l	Increase_Block

Voice1:
	dc.l	$dff0a0		; 0	; hardware pointer
	dc.w	$0001		; 4	; DMA bit
	dc.l	0		; 6	; sound pointer
	dc.l	0		; 10	; track pointer
	dc.l	0		; 14	; block pointer
	dc.w	0		; 18	; track counter
	dc.w	0		; 20	; block counter
	dc.b	0		; 22	; synthetic delay
	dc.b	0		; 23	; synthetic counter
	dc.w	0		; 24	; frequency
	dc.w	0		; 26	; frequency compare
	dc.b	0		; 28	; note number
	dc.b	0		; 29	; channel volume
	dc.w	0		; 30	; bendrate
	dc.w	0		; 32	; volume counter
	dc.w	0		; 34	; volume
	dc.b	0		; 36	; volume sustain
	dc.b	0		; 37	; portamento
	dc.b	0		; 38	; vibrato wait
	dc.b	0		; 39	; vibrato status
	dc.w	0		; 40	; vibrato value
	dc.b	0		; 42	; vibrato counter
	dc.b	0		; 43	; transpose
	dc.l	0		; 44	; arpeggio pointer
	dc.w	0		; 48	; arpeggio counter
	dc.b	0		; 50	; unused (has once been used)
	dc.b	0		; 51	; sound technique
	dc.b	0		; 52	; vibrato counter
	dc.b	0		; 53	; vibrato sustain
	dc.w	0		; 54	; track repeat
	dc.w	0		; 56	; track length
	even

Voice2:
	dc.l	$dff0b0		; 0	; hardware pointer
	dc.w	$0002		; 4	; DMA bit
	blk.b	Voice2-Voice1-6

Voice3:
	dc.l	$dff0c0		; 0	; hardware pointer
	dc.w	$0004		; 4	; DMA bit
	blk.b	Voice2-Voice1-6

Voice4:
	dc.l	$dff0d0		; 0	; hardware pointer
	dc.w	$0008		; 4	; DMA bit
	blk.b	Voice2-Voice1-6

Frequency_Table:
	dc.w	0000
	dc.w	6848,6464,6096,5760,5424,5120,4832,4560,4304,4064,3840,3616
	dc.w	3424,3232,3048,2880,2712,2560,2416,2280,2152,2032,1920,1808
	dc.w	1712,1616,1524,1440,1356,1280,1208,1140,1076,1016,0960,0904
	dc.w	0856,0808,0762,0720,0678,0640,0604,0570,0538,0508,0480,0452
	dc.w	0428,0404,0381,0360,0339,0320,0302,0285,0269,0254,0240,0226
	dc.w	0214,0202,0190,0180,0170,0160,0151,0143,0135,0127,0120,0113
	dc.w	0113,0113,0113,0113,0113,0113,0113,0113,0113,0113,0113,0113


Song_Data:
	dc.w	$8000		; 0	; hardware dma
	dc.l	0		; 2	; sound pointer
	dc.l	0		; 6	; sound offset pointer
	dc.l	0		; 10	; track1 pointer
	dc.l	0		; 14	; track2 pointer
	dc.l	0		; 18	; track3 pointer
	dc.l	0		; 22	; track4 pointer
	dc.l	0		; 26	; block pointer
	dc.b	0		; 30	; random noise on/off (0=off)
	dc.b	0		; 31	; unused (it has once been used)
	dc.w	0		; 32	; unused (it has once been used)
	dc.l	0		; 34	; samples pointer
	dc.l	0		; 38	; samples offset pointer
	dc.l	0		; 42	; random noise value
	dc.b	63		; 46	; song volume
	dc.b	0		; 47	; play speed (reset)
	dc.b	0		; 48	; play speed counter
	dc.b	0		; 49	; sound fx (1 = fx)
	dc.w	0		; 50	; unused (it has once been used)
	dc.w	0		; 52	; unused (it has once been used)
	dc.w	0		; 54	; unused (it has once been used)
	dc.w	0		; 56	; unused (it has once been used)
	dc.l	0		; 58	; arpeggio pointer
	dc.w	0		; 62	; voice1 repeat
	dc.w	0		; 64	; voice1 length
	dc.w	0		; 66	; voice2 repeat
	dc.w	0		; 68	; voice2 length
	dc.w	0		; 70	; voice3 repeat
	dc.w	0		; 72	; voice3 length
	dc.w	0		; 74	; voice4 repeat
	dc.w	0		; 76	; voice4 length
	dc.l	0		; 78	; waveform offset pointer
	dc.l	0		; 82	; waveform pointer
	even

Null_Waveform:
	blk.b	8,0

Null_Sound:
	dc.w	2/2		; 0	; waveform length/2
	dc.w	0		; 2	; repeat
	dc.w	0		; 4	; repeat length/2
	dc.b	255,1,255	; 6	; volume rate/level/sus
	dc.b	0,0,255		; 9	; volume rate/level/sus
	dc.b	0,0,255		; 12	; volume rate/level/sus
	dc.b	0,0,255		; 15	; volume rate/level/sus
	dc.b	0,0,255		; 18	; volume rate/level/sus
	dc.b	0,1,255		; 21	; vibrato step/len/sus
	dc.b	0,1,255		; 24	; vibrato step/len/sus
	dc.b	0,1,255		; 27	; vibrato step/len/sus
	dc.b	0,1,255		; 30	; vibrato step/len/sus
	dc.b	0,1,255		; 33	; vibrato step/len/sus
	dc.w	0		; 36	; bendrate
	dc.b	0		; 38	; technique
	dc.b	254		; 39	; table speed
	dc.b	0,$ff,0		; 40	; waveform table
	even


Module:
	blk.b	4,0
