*************************************************
* Super Hang On Loader by The Source (1988).	*
* Adapted by Mr.STYCKX / Nicolas Pomarède	*
*						*
* Original replay was in $60000.		*
* Replay Speed : 160 Hz ( Timer=$22f6/2 )	*
*						*
* EaglePlayer / Delitracker port : 29/03/97	*
*	Volume					*
*	Balance					*
*	SubSong					*
*	SongEnd					*
*	EP_Voices				*
*	EP_StructInit (Analyzer)		*
*************************************************

	opt	o+

	output	ram:CUST.SuperHangOn_Loader


SHO_CIA		=	$22f6/2

SHO_TEST	=		0	; 0 => BUILD COMPLETE CUSTOM MODULE
					; 1 => BUILD SMALL CODE FOR TESTING

	section	SHO,code



	incdir	"Include:"	include	"misc/DeliPlayer.i"
	include	"misc/EaglePlayer.i"


	IFEQ	SHO_TEST-0			; COMPLETE VERSION


	PLAYERHEADER PlayerTagArray

	dc.b '$VER: Super Hang On Loader Music (1988) custom player V1.0, '
	dc.b 'ripped and adapted by Mr.STYCKX (03/97)',0

	EVEN

PlayerTagArray
	dc.l	DTP_CustomPlayer,1		; CustomPlayer - Tag (important !!!)
	dc.l	DTP_Flags,PLYF_CUSTOM!PLYF_SONGEND

	dc.l	DTP_PlayerVersion,1<<16+0	; v1.0
	dc.l	EP_PlayerVersion,1
	dc.l	DTP_PlayerName,PName
	dc.l	DTP_Creator,CName

	dc.l	DTP_InitPlayer,InitPlay		; alloc audio
	dc.l	DTP_EndPlayer,EndPlay		; free audio
	dc.l	DTP_InitSound,SHO_init		; init custom data
	dc.l	DTP_EndSound,SHO_end		; clear DMA

	dc.l	DTP_SubSongRange,SHO_SubSongRange

	dc.l	DTP_Interrupt,SHO_Play

	dc.l	DTP_Volume,SHO_Volume
	dc.l	DTP_Balance,SHO_Volume

	dc.l	EP_Voices,SHO_SetVoices
	dc.l	EP_StructInit,SHO_StructInit

	dc.l	EP_Flags,EPB_Voices!EPB_Analyzer!EPB_Volume!EPB_Balance!EPB_Songend

	dc.l	TAG_DONE


PName	dc.b	"Super Hang On Loader Custom v1.0",0
CName	dc.b	"Music by The Source (1988).",$a
	dc.b	"Adapted by Mr.STYCKX (30/03/97)",0

	EVEN


SHO_StructAnalyzer			; transmis à EaglePlayer pour gérer
	ds.l	UPS_SizeOF		; les analyzers



*-----------------------------------------------------------------------*
;
; Init Player

InitPlay
	move.l	dtg_SongEnd(a5),SHO_SongEnd

	move.l	dtg_AudioAlloc(a5),a0		; Function
	jmp	(a0)


*-----------------------------------------------------------------------*
;
; End Player

EndPlay
	move.l	dtg_AudioFree(a5),a0		; Function
	jmp	(a0)


*-----------------------------------------------------------------------*
;
; Init Custom Replay Routine

SHO_init
	move.w	#SHO_CIA,dtg_Timer(a5)
	move.l	dtg_SetTimer(a5),a0
	jsr	(a0)
	move.w	dtg_SndNum(a5),d0	; sub song nbr (1..)
	bra	SHO_InitSong

	move.w	#SHO_CIA,dtg_Timer(a5)
	move.l	dtg_SetTimer(a5),a0
	jmp	(a0)



*-----------------------------------------------------------------------*
;
; Clear Audio Reg.

SHO_end
	move.w	#$f,$dff096
	clr.w	$dff0a8
	clr.w	$dff0b8
	clr.w	$dff0c8
	clr.w	$dff0d8
	rts



*-----------------------------------------------------------------------*
;
; Interrupt routine called every 1/80 s

SHO_Play
	bra.s	SHO_InterVBL



*-----------------------------------------------------------------------*
;
; Returns min and max sub song

SHO_SubSongRange
	moveq	#1,d0			; min
	moveq	#1,d1			; max

	rts


*-----------------------------------------------------------------------*
;
; Set Volume

SHO_Volume
	move.w	dtg_SndLBal(a5),d0	; Vol Left
	mulu	dtg_SndVol(a5),d0	; Vol Max
	lsr.w	#6,d0
	move.w	d0,SHO_MasterVolA	; final Vol Left
	move.w	d0,SHO_MasterVolD

	move.w	dtg_SndRBal(a5),d0
	mulu	dtg_SndVol(a5),d0
	lsr.w	#6,d0
	move.w	d0,SHO_MasterVolB
	move.w	d0,SHO_MasterVolC

	rts


*-----------------------------------------------------------------------*
;
; Set DMA Voices

SHO_SetVoices
	or.w	#$8000,d0
	move.w	d0,SHO_DMA_EP	; bit=1 <=> voice is ON

	rts


*-----------------------------------------------------------------------*
;
; Returns address of the UPS structure to EaglePlayer

SHO_StructInit
	lea	SHO_StructAnalyzer(pc),a0

	rts



*-----------------------------------------------------------------------*


	ELSEIF				; TESTVERSION


;-------
; Small code to test the player under a debugger


	moveq	#1,d0
	bsr	SHO_InitSong

	move.l	$6c.w,Jmp+2
	move.l	#Vbl,$6c.w
	rts


End
;;	bsr	StopSong
	move.l	Jmp+2(pc),$6c.w
	move.w	#$f,$dff096
	rts


Vbl
	btst	#5,$dff01f
	beq.s	Jmp

.wa	cmp.b	#70,$dff006
	blt.s	.wa

	move.w	#$f00,$dff180

	movem.l	d0-a6,-(a7)
	bsr	SHO_InterVBL
	movem.l	(a7)+,d0-a6

	move.w	#$345,$dff180

Jmp	jmp	0.l




SHO_StructAnalyzer			; transmis à EaglePlayer pour gérer
	ds.l	UPS_SizeOF		; les analyzers


	ENDC



;------------------------------------------------------------------------
; Données pour EaglePlayer / Delitracker

SHO_DMA_EP	dc.w	%1111+$8000	; voix actives depuis EaglePlayer

SHO_MasterVolA	dc.w	64		; 0 .. 64
SHO_MasterVolB	dc.w	64
SHO_MasterVolC	dc.w	64
SHO_MasterVolD	dc.w	64

SHO_StructA	dc.l	SHO_StructAnalyzer
SHO_StructB	dc.l	SHO_StructAnalyzer+UPS_Modulo
SHO_StructC	dc.l	SHO_StructAnalyzer+UPS_Modulo*2
SHO_StructD	dc.l	SHO_StructAnalyzer+UPS_Modulo*3

SHO_OldPer1	dc.w	-1
SHO_OldPer2	dc.w	-1
SHO_OldPer3	dc.w	-1
SHO_OldPer4	dc.w	-1



;-----------------------------------------------------------------------
; Super Hang On Loader Music
; Original music by The Source (located in $6000) in 1988.
; Relocated on 29/03/97 by Mr.STYCKX
;
; SHO_InitSong : D0 = 1
; SHO_InterVBL : called every VBL
;



;-----------------------------------------------------------------------
; Init la subsong D0

SHO_InitSong
	subq.w	#1,d0			; de 0 à 4
	lsl.w	#3,d0			; adresse 2 mots longs
	lea	SongsAdr(pc),a0
	move.l	4(a0,d0.w),D1		; music speed
	move.l	(a0,d0.w),D0		; music data
	bra	InitSong
	


;-----------------------------------------------------------------------
; Routine appelée à chaque VBL

SHO_InterVBL
	movem.l	D0/A0,-(SP)

	lea	SHO_StructAnalyzer(pc),a0
	move.w	#-1,UPS_Enabled(a0)
	move.w	#UPSB_Adr!UPSB_Len!UPSB_Per!UPSB_Vol!UPSB_DMACon,UPS_Flags(a0)

	move.w	UPS_Voice1Per(a0),SHO_OldPer1
	move.w	UPS_Voice2Per(a0),SHO_OldPer2
	move.w	UPS_Voice3Per(a0),SHO_OldPer3
	move.w	UPS_Voice4Per(a0),SHO_OldPer4

	clr.w	UPS_Voice1Per(a0)
	clr.w	UPS_Voice2Per(a0)
	clr.w	UPS_Voice3Per(a0)
	clr.w	UPS_Voice4Per(a0)

	move.w	SHO_DMA_EP(pc),d0
	move.w	d0,UPS_DMACon(a0)
	not.w	d0
	and.w	#$f,d0
	move.w	d0,$dff096		; stop voices from EP

	bsr	PlaySong

	; La replay de Nebulus remet la période à chaque VBL,ce qui perturbe
	; les analyzers. On ne transmet donc une période que si elle est
	; différente de la VBL précédente.

	lea	SHO_StructAnalyzer(pc),a0
	move.w	UPS_Voice1Per(a0),d0
	cmp.w	SHO_OldPer1(pc),d0	; nouvelle fréquence
	bne.s	.2			; oui
	clr.w	UPS_Voice1Per(a0)	; non, on remet a 0

.2	move.w	UPS_Voice2Per(a0),d0
	cmp.w	SHO_OldPer2(pc),d0
	bne.s	.3
	clr.w	UPS_Voice2Per(a0)

.3	move.w	UPS_Voice3Per(a0),d0
	cmp.w	SHO_OldPer3(pc),d0
	bne.s	.4
	clr.w	UPS_Voice3Per(a0)

.4	move.w	UPS_Voice4Per(a0),d0
	cmp.w	SHO_OldPer4(pc),d0
	bne.s	.0
	clr.w	UPS_Voice4Per(a0)
.0

	clr.w	UPS_Enabled(a0)

	movem.l	(SP)+,D0/A0
	rts



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


;-----------------------------------------------
;
InitSong

lbC000052
	bsr	lbC000232
	tst.l	D0
	beq.s	lbC0000A4
	movem.l	D0/D1/A0,-(SP)
	move.l	D1,lbL000496
	move.l	D0,D1
	move.l	D0,A0
	add.l	#12,D1
	move.l	D1,lbL00049A
	move.l	D0,D1
	add.l	(A0),D1
	move.l	D1,lbL00049E
	move.l	D0,D1
	add.l	4(A0),D1
	move.l	D1,lbL0004A2
	add.l	8(A0),D0
	move.l	D0,lbL0004A6
	clr.l	lbL000492
	st	lbB0004AA
	movem.l	(SP)+,D0/D1/A0
lbC0000A4	rts



;-----------------------------------------------
;
PlaySong

lbC000130
	tst.w	lbB0004AA
	beq.s	lbC00015C
	movem.l	D0-D7/A0-A6,-(SP)
	bsr	lbC00024A
	bsr	lbC0001EC
	bsr.s	lbC0001A6
	bsr.s	lbC00015E
	move.l	lbL000496,D0
	add.l	D0,lbL000492

	tst.w	lbB0004AA
	bne.s	.NoEnd
	moveq	#1,d0
	bsr	SHO_InitSong

.NoEnd	movem.l	(SP)+,D0-D7/A0-A6
lbC00015C	rts

;-------

lbC00015E
	move.l	SHO_StructD(pc),a5
	move.w	SHO_MasterVolD(pc),d7

	move.l	lbL0004A6,A0
	move.w	lbL000492,D0
	cmp.w	(A0),D0
	bcs.s	lbC00015C
	addq.w	#2,A0
	move.w	(A0)+,D0
	move.l	A0,lbL0004A6
	tst.w	D0
	bmi	lbC000232
	bne.s	lbC000186
	moveq	#3,D0
	bra	lbC0002E4

lbC000186	lea	lbW000404,A1
	and.w	#$7F,D0
	sub.w	#$58,D0
	add.w	D0,D0
	move.w	0(A1,D0.W),D3
	moveq	#3,D0
	moveq	#7,D1
	moveq	#-1,D2
	moveq	#$40,D4
	bra	lbC000312

;-------

lbC0001A6
	move.l	SHO_StructC(pc),a5
	move.w	SHO_MasterVolC(pc),d7

	move.l	lbL0004A2,A0
	move.w	lbL000492,D0
	cmp.w	(A0),D0
	bcs.s	lbC00015C
	addq.w	#2,A0
	move.w	(A0)+,D0
	move.l	A0,lbL0004A2
	tst.w	D0
	bmi.s	lbC000232
	bne.s	lbC0001CC
	moveq	#2,D0
	bra	lbC0002E4

lbC0001CC	lea	lbW000404,A1
	and.w	#$7F,D0
	sub.w	#$58,D0
	add.w	D0,D0
	move.w	0(A1,D0.W),D3
	moveq	#2,D0
	moveq	#7,D1
	moveq	#-1,D2
	moveq	#$40,D4
	bra	lbC000312

;-------

lbC0001EC
	move.l	SHO_StructB(pc),a5
	move.w	SHO_MasterVolB(pc),d7

	move.l	lbL00049E,A0
	move.w	lbL000492,D0
	cmp.w	(A0),D0
	bcs.s	lbC00026A
	addq.w	#2,A0
	move.w	(A0)+,D0
	move.l	A0,lbL00049E
	tst.w	D0
	bmi.s	lbC000232
	bne.s	lbC000212
	moveq	#1,D0
	bra	lbC0002E4

lbC000212
	lea	lbW000404,A1
	and.w	#$7F,D0
	sub.w	#$32,D0
	add.w	D0,D0
	move.w	0(A1,D0.W),D3
	moveq	#1,D0
	moveq	#6,D1
	moveq	#2,D2
	moveq	#$40,D4
	bra	lbC000312


lbC000232	clr.w	lbB0004AA
;;	move.w	#$380,$DFF09A
	move.w	#7+8,$DFF096
	IFEQ	SHO_TEST-0
	move.l	SHO_SongEnd(pc),a0
	jsr	(a0)
	ENDC
	rts

;-------

lbC00024A
	move.l	SHO_StructA(pc),a5
	move.w	SHO_MasterVolA(pc),d7

	move.l	lbL00049A,A0
	move.w	lbL000492,D0
	cmp.w	(A0),D0
	bcs.s	lbC00026A
	addq.w	#2,A0
	move.w	(A0)+,D0
	move.l	A0,lbL00049A
	tst.w	D0
	bmi.s	lbC000232
	bne.s	lbC00026C
lbC00026A	rts

lbC00026C	cmp.b	#$24,D0
	bne.s	lbC000282
	moveq	#0,D0
	moveq	#1,D1
	moveq	#2,D2
	move.w	#$E0,D3
	moveq	#$40,D4
	bra	lbC000312

lbC000282	cmp.b	#$25,D0
	bne.s	lbC000298
	moveq	#0,D0
	moveq	#2,D1
	moveq	#2,D2
	move.w	#$E0,D3
	moveq	#$40,D4
	bra.s	lbC000312

lbC000298	cmp.b	#$27,D0
	bne.s	lbC0002AE
	moveq	#0,D0
	moveq	#3,D1
	moveq	#2,D2
	move.w	#$E0,D3
	moveq	#$40,D4
	bra.s	lbC000312

lbC0002AE	cmp.b	#$28,D0
	bne.s	lbC0002C4
	moveq	#0,D0
	moveq	#4,D1
	moveq	#2,D2
	move.w	#$E0,D3
	moveq	#$40,D4
	bra.s	lbC000312

lbC0002C4	lea	lbW000404,A1
	and.w	#$7F,D0
	sub.w	#$30,D0
	add.w	D0,D0
	move.w	0(A1,D0.W),D3
	moveq	#0,D0
	moveq	#5,D1
	moveq	#2,D2
	moveq	#$40,D4
	bra.s	lbC000312

lbC0002E4	movem.l	D0/A0/A1,-(SP)
	bsr.s	lbC0002F0
	movem.l	(SP)+,D0/A0/A1
	rts

lbC0002F0	and.w	#3,D0
	lea	lbL00042A,A0
	lsl.w	#2,D0
	lea	0(A0,D0.W),A0
	move.w	$12(A0),$DFF096		; DMA OFF
;;	move.w	$10(A0),$DFF09A		; INTENA OFF
	rts

lbC000312	tst.w	D1
	beq.s	lbC0002E4
	cmp.w	#$10,D1
	bhi.s	lbC0002E4
	movem.l	D0-D7/A0-A2,-(SP)
	cmp.w	#$7C,D3
	bcc.s	lbC00032C
	move.w	#$7C,D3
lbC00032C	cmp.w	#$41,D4
	bcs.s	lbC000336
	move.w	#$40,D4
lbC000336	lea	lbL000452,A2
	lsl.w	#3,D1
	lea	0(A2,D1.W),A2
	bsr.s	lbC0002F0
	move.l	(A0),A1
	move.l	(a2),UPS_Voice1Adr(a5)
	move.l	(A2)+,(A1)
	move.w	(a2),UPS_Voice1Len(a5)
	move.w	(A2)+,4(A1)
	move.w	D3,6(A1)
	move.w	d3,UPS_Voice1Per(a5)
	move.w	d4,UPS_Voice1Vol(a5)
	mulu	d7,d4			; mastervol
	lsr.w	#6,d4
	move.w	D4,8(A1)
	clr.w	UPS_Voice1Repeat(a5)	; repeat ON

;	move.w	#$C8,D0
;lbC000358	dbra	D0,lbC000358
	moveq	#4-1,d0
wa1	move.b	$dff006,d1
wa12	cmp.b	$dff006,d1
	beq.s	wa12
	dbf	d0,wa1

	move.w	$22(A0),d0		; DMA ON
	and.w	SHO_DMA_EP(pc),d0
	move.w	d0,$DFF096
	tst.w	D2
	bmi.s	lbC00037C

;	move.w	#$C8,D0
;lbC00036C	dbra	D0,lbC00036C
	moveq	#4-1,d0
wa2	move.b	$dff006,d1
wa22	cmp.b	$dff006,d1
	beq.s	wa22
	dbf	d0,wa2

	move.l	#lbL00041A,(A1)
	move.w	#8,4(A1)
	st	UPS_Voice1Repeat(a5)	; repeat OFF

lbC00037C	movem.l	(SP)+,D0-D7/A0-A2
	rts

lbC000382	move.w	#$780,$DFF09C
	rte

;fiX Label expected
	dc.w	$1BF8,$1A65,$18EA,$1784,$1632,$14F3,$13C6,$12AA
	dc.w	$119E,$10A1,$FB2,$ED0,$DFC,$D33,$C75,$BC2,$B19
	dc.w	$A7A,$9E3,$955,$8CF,$850,$7D9,$768,$6FE,$699,$63B
	dc.w	$5E1,$58D,$53D,$4F2,$4AB,$467,$428,$3EC,$3B4,$37F
	dc.w	$34D,$31D,$2F1,$2C6,$29E,$279,$255,$234,$214,$1F6
	dc.w	$1DA,$1BF,$1A6,$18F,$178,$163,$14F,$13C,$12B,$11A
	dc.w	$10A,$FB,$ED
lbW000404	dc.w	$E0,$D3,$C7,$BC,$B2,$A8,$9E,$95,$8D,$85,$7E
lbL00042A
	dc.l	$DFF0A0,$DFF0B0,$DFF0C0,$DFF0D0
	dc.l	$00800001,$01000002,$02000004,$04000008
	dc.l	$80808001,$81008002,$82008004,$84008008


SAMPLE_START	=	$604AC

SampleAdr
	dc.l	$69454-SAMPLE_START+SampleData,$2830000
	dc.l	$6995A-SAMPLE_START+SampleData,$4E10000
	dc.l	$60D42-SAMPLE_START+SampleData,$21D0000
	dc.l	$6117C-SAMPLE_START+SampleData,$A810000
	dc.l	$6267E-SAMPLE_START+SampleData,$14A60000
	dc.l	$64FCA-SAMPLE_START+SampleData,$187C0000
	dc.l	$680C2-SAMPLE_START+SampleData,$9C30000

lbL000452 = SampleAdr-8


lbL000492	dc.l	0
lbL000496	dc.l	$10000
lbL00049A	dc.l	0
lbL00049E	dc.l	0
lbL0004A2	dc.l	0
lbL0004A6	dc.l	0
lbB0004AA	dcb.b	2,0


;-------

SHO_SongEnd	dc.l	0		; SongEnd rout adr


SongsAdr
	dc.l	MusicData,$15000


MusicData					; $6a31c .. $6cdef
	incbin	b:SuperHangOn/SHO_Loader.mus


;-------

	section	SHO_smp,data_c

lbL00041A	dcb.l	4,0			; EmptySample

SampleData					; $604ac .. 6a31c
	incbin	b:SuperHangOn/SHO_Loader.smp

;-------

	end
