	**************************************************************
	** EaglePlayer/DelitrackerV1.3+ Noisepackerplayroutine      **
	** Eagleplayer Adaption by Buggs & Eagleeye of Defect       **
	**************************************************************

		incdir	Include:
		include "misc/EaglePlayer.i"

	PLAYERHEADER	Tags

	dc.b '$VER: NoisePacker V2.02 Eagleplayer V1.3 (July/21/93)',0,0
		even

Tags:		dc.l	DTP_PlayerVersion,3
		dc.l	DTP_PlayerName,NP_Player
		dc.l	DTP_Creator,NP_Name
		dc.l	DTP_Check2,NP_Check
		dc.l	DTP_Interrupt,NP_Music
		dc.l	DTP_InitPlayer,NP_InitPlay
		dc.l	DTP_EndPlayer,NP_EndPlay
		dc.l	DTP_InitSound,NP_Init
		dc.l	DTP_EndSound,NP_RemSnd
		dc.l	DTP_NextPatt,NP_NextPattern
		dc.l	DTP_PrevPatt,NP_PrevPattern
		dc.l	DTP_Volume,SetVol
		dc.l	DTP_Balance,SetVol
		dc.l	EP_Voices,SetVoices
		dc.l	EP_Get_ModuleInfo,NP_GetInfos
		dc.l	EP_GetPositionNr,NP_GetPosNr
		dc.l	EP_StructInit,StrukInit
		dc.l	EP_Flags,EPB_Save!EPB_Restart!EPB_Songend!EPB_Volume!EPB_Balance!EPB_Voices!EPB_Analyzer!EPB_Moduleinfo!EPB_Nextpatt!EPB_Prevpatt
		dc.l	0

*------------------------------------------------------------------------*
NP_Structadr:	ds.b	UPS_sizeof
NP_Data:	dc.l	0	
NP_RightVol	dc.w	0
NP_LeftVol	dc.w	0
NP_SndVol	dc.w	0

NP_Voice1	dc.w	1
NP_Voice2	dc.w	1
NP_Voice3	dc.w	1
NP_Voice4	dc.w	1
NP_OldVoice1	dc.w	0
NP_OldVoice2	dc.w	0
NP_OldVoice3	dc.w	0
NP_OldVoice4	dc.w	0
NP_SongEndAdr:	dc.l	0

*-----------------------------------------------------------------------*
NP_Name:	dc.b	"Twins of Phenomena,",10
		dc.b	"adapted by DEFECT",0
NP_Player:	dc.b	"NoisePacker 2.x",0
		even
*------------------- Tag-Item Struktur für Module-Info -----------------*
NP_InfoBuffer:	dc.l	MI_Samples,0			;4
		dc.l	MI_Length,0			;12
		dc.l	MI_Pattern,0			;20
		dc.l	MI_SongSize,0			;28
		dc.l	MI_SamplesSize,0		;36
		dc.l	MI_Calcsize,0			;44
		dc.l	MI_Unpacked,0			;52
		dc.l	MI_Unpackedsystem,MIUS_Noisetracker
		dc.l	0

*----------------- Get Infos (Create InfoTag-Itemliste) ----------------*
NP_GetInfos:	move.l	NP_data(pc),a0
		lea	NP_InfoBuffer(pc),a4
		moveq	#16,d3	
		moveq	#0,d0
		moveq	#0,d2
		move.l	a0,a1
		move.w	(a0)+,d0
		move.l	d0,d6
		move.w	(a0)+,d2
		add.l	d2,d6
		add.w	(a0)+,d6
		add.w	(a0)+,d6
		move.l	d6,28(a4)			;SongSize
		move.l	d6,44(a4)			;CalcSize

		moveq	#0,d6
		add.l	d0,a1				;Patternliste
		lsr.w	#4,d0
		move.l	d0,d1
		move.l	d1,4(a4)			;SamplesAnz
		subq.l	#1,d1
		addq.l	#4,a0				;Adr auf Sampleliste
.SucheSample	move.w	(a0),d0
		add.l	d0,d0
		add.l	d0,d6
		add.l	d3,a0
		dbf	d1,.SucheSample
		lsr.w	#1,d2
		move.l	d2,12(a4)			;Length setzen

		move.l	d6,36(a4)			;Samplessize
		move.l	d6,52(a4)			;Unpacked
		add.l	d6,44(a4)			;CalcSize

		subq.l	#1,d2
		moveq	#0,d0
.NextPattern:	cmp.w	(a1),d0
		bge.s	.AddAdr
		move.w	(a1),d0
.AddAdr:	addq.l	#2,a1
		dbf	d2,.NextPattern
		lsr.w	#3,d0
		addq.l	#1,d0
		move.l	d0,20(a4)			;Pattern
		mulu	#1024,d0
		add.l	#$43c,d0
		add.l	d0,52(a4)

		move.l	a4,a0
NP_Return:	rts

*------------------------ Test auf Noisepacker II ---------------------------*
NP_Check:	move.l	dtg_ChkData(a5),a0
		moveq	#-1,d0
		move.l	a0,a1

		move.w	(a0),d5		;Anzahl der Samples
		move.w	d5,d1		;merken
		and.w	#$f,d5		;jedes NP Modul beginnt mit
					;(Anzahl der Samples*16) OR 12
		cmp.w	#$c,d5		;ist die 12 vorhanden ?
		bne	.NP_Fail	;nö
		lsr.w	#4,d1		;$c rausrotieren
		cmp.w	#$1f,d1		;Anzahl der Samples > 32 (0..31)
		bhi	.NP_Fail	;ja,Fehler

		move.w	4(a0),d2	;Offset Patterns
		btst	#0,d2		;Ungerade ?
		bne	.np_fail	;->Fehler
		add.w	(a0),a1		;auf Pointer addieren
		move.w	-4(a1),d5	;Höchste Patternnummer ist 2 mal eingetragen
		btst	#0,d5		;Ungerade ?
		bne	.np_fail	;->Fehler
		cmp.w	2(a0),d5	;Vergleich
		bne	.NP_fail	;Unstimmigkeit,Ende der Vorstellung

		move.l	a0,a1		;Pointer auf Modul saven
		add.w	(a1),a0		;Liste der Patterns für jeweilige Songposition
		move.w	-4(a0),d1	;Länge des Songs
		asr.w	#1,d1		;durch 2 dividieren
		subq.w	#1,d1
					;in A0 Zeiger auf Tabelle für die
					;Zeiger auf die Patternnummer für die
					;jeweilige Songposition

		moveq	#0,d5
		move.w	d1,d4		;brauchen wir noch
.check2:	move.w	(a0)+,d3	;Patternnummer
		cmp.w	d5,d3		;mit derzeit höchster vergleichen
		bls.s	.check1		;kleiner -> weiter
		move.w	d3,d5		;höchste Patternnr. merken
.check1		dbf	d1,.check2	;alle Patterns
		addq.l	#8,d5		;+8
		cmp.w	d5,d2		;Gegenvergleich
		bne	.np_fail	;passt nicht -> Fehler
		and.w	#7,d5		;ausmaskieren (Patternnummer muß durch 8 
					;teilbar sein)
		bne	.np_fail	;nein->Fehler

			;A0 muß hier auf dem Anfang der Offsettabelle der
			;Patterns stehen

		moveq	#0,d5		;d5 killen
		move.w	(a1),d5		;Pointer auf Patternliste
		add.w	2(a1),a1	;Länge dieser Patternliste
		add.l	d5,a1		;zusammenaddieren = Pointer auf Patternoffsets

		cmp.l	a0,a1		;stimmt das ?
		bne	.np_fail	;wieso auch ?

			;an dieser Stelle kann als gesichert gelten,daß
			;es sich um ein Noisepackermodul handelt,es bleibt
			;nur die Unterscheidung zum Noisepacker 3

		move.w	#$c0,d1		;die Patternoffsets bei NP2.02 
				;sind Vielfache von 192
.Untersch:	moveq	#0,d5		;d5 löschen
		move.w	(a1)+,d5	;Offset holen
		divu	d1,d5		;durch 192 dividieren
		clr.w	d5		;Ergebnis löschen (unteres Wort)
		tst.l	d5		;Rest (oberes Wort) = 0 ,d.h. Offset durch 192
					;teilbar
		bne.s	.np_fail	;nein,ertappt
		dbf	d4,.Untersch	;alle testen
.NP_ok:		moveq	#0,d0		;alles klar
.NP_Fail:	tst.l	d0
		rts


*-----------------------------------------------------------------------*
NP_InitPlay:	lea	NP_OldVoice1(pc),a0	;Voices 0 setzen=alle an
		clr.l	(a0)+			; Old Voice löschen
		clr.l	(a0)+

		moveq	#0,d0
		move.l	dtg_GetListData(a5),a0	; Function
		jsr	(a0)
		lea	NP_Data(pc),a1
		move.l	a0,(a1)
		move.l	DTG_SongEnd(a5),NP_SongEndAdr-NP_Data(a1)
		move.l	dtg_AudioAlloc(a5),a0	; Function
		jmp	(a0)			; returncode is already set !

*-----------------------------------------------------------------------*
NP_EndPlay:	move.l	dtg_AudioFree(a5),a0		; Function
		jmp	(a0)


*-----------------------------------------------------------------------*
NP_RemSnd:	lea	$dff000,a0
		moveq	#0,d0
		move.w	d0,$a8(a0)
		move.w	d0,$b8(a0)
		move.w	d0,$c8(a0)
		move.w	d0,$d8(a0)
		move.w	#$F,$96(a0)			; End Sound
		rts

*------------------------- Struktur übergeben ---------------------------*
Strukinit:	lea	NP_StructAdr(pc),a0
		rts

*----------------- Daten in die Userprogramm-Struktur übergeben ---------*
NP_Getvoice:	movem.l	d0-d1/a1,-(sp)
		lea	NP_Structadr(pc),a1	;1.Kanal
		cmp.l	#$dff0a0,a4
		beq.s	.yes
		lea	NP_Structadr+ups_modulo(pc),a1	;2.Kanal
		cmp.l	#$dff0b0,a4
		beq.s	.yes
		lea	NP_Structadr+ups_modulo*2(pc),a1	;3.Kanal
		cmp.l	#$dff0c0,a4
		beq.s	.yes
		lea	NP_Structadr+ups_modulo*3(pc),a1	;4.Kanal
.yes:		move.w	24(a2),UPS_Voice1Per(a1)	;Sampleperiode
		move.l	(a3),UPS_Voice1Adr(a1)		;Sampleadresse
		moveq	#0,d1
		cmp.w	#1,12(a3)	;Repeat on ?
		bne.s	.ok
		moveq	#1,d1		;nein,Repeat "off" setzen
.ok		move.w	d1,UPS_Voice1Repeat(a1)
		move.w	4(a3),UPS_Voice1len(a1)	;Länge
		movem.l	(sp)+,d0-d1/a1
		rts

*-----------------------------------------------------------------------*
*		d0 Bit 0-3 = Set Voices Bit=1 Voice on			*
SetVoices:	lea	NP_Voice1(pc),a0
		lea	NP_StructAdr(pc),a1
		moveq	#1,d1
		move.w	d1,(a0)+			Voice1=0 setzen
		btst	#0,d0
		bne.s	.NoVoice1
		clr.w	-2(a0)
		clr.w	$dff0a8
		clr.w	UPS_Voice1Vol(a1)
.NoVoice1:	move.w	d1,(a0)+			Voice2=0 setzen
		btst	#1,d0
		bne.s	.NoVoice2
		clr.w	-2(a0)
		clr.w	$dff0b8
		clr.w	UPS_Voice2Vol(a1)
.NoVoice2:	move.w	d1,(a0)+			Voice3=0 setzen
		btst	#2,d0
		bne.s	.NoVoice3
		clr.w	-2(a0)
		clr.w	$dff0c8
		clr.w	UPS_Voice3Vol(a1)
.NoVoice3:	move.w	d1,(a0)+			Voice4=0 setzen
		btst	#3,d0
		bne.s	.NoVoice4
		clr.w	-2(a0)
		clr.w	$dff0d8
		clr.w	UPS_Voice4Vol(a1)
.NoVoice4:	move.w	d0,UPS_DMACON(a1)
		moveq	#0,d0
		rts

*-----------------------------------------------------------------------*
SetVol:		move.w	DTG_SndLBal(a5),d0
		mulu	DTG_SndVol(a5),d0
		lsr.w	#6,d0				; durch 64
		move.w	d0,NP_LeftVol			; Left Volume

		move.w	DTG_SndRBal(a5),d0
		mulu	DTG_SndVol(a5),d0
		lsr.w	#6,d0				; durch 64
		move.w	d0,NP_RightVol			; Right Volume


		lea	NP_OldVoice1(pc),a0
		lea	$dff0a0,a5
		moveq	#3,d1
.SetNew		move.w	(a0)+,d0
		bsr.s	NP_SetVoices
		addq.l	#8,a5
		addq.l	#8,a5
		dbf	d1,.SetNew
		rts

*-----------------------------------------------------------------------*
NP_SetVolume:	movem.l	d0/a5,-(a7)
		move.w	4(a2),d0
		bra.s	NP_SetVolume3
NP_SetVolume2:	movem.l	d0/a5,-(a7)
		move.w	4(a0),d0
NP_SetVolume3:	move.l	a4,a5
		bsr.s	NP_SetVoices
		movem.l	(a7)+,d0/a5
		rts

*-----------------------------------------------------------------------*
NP_SetVoices:	and.w	#$7f,d0
		cmp.l	#$dff0a0,a5			;Left Volume
		bne.s	.NoVoice1
		move.w	d0,NP_OldVoice1
		tst.w	NP_Voice1
		bne.s	.Voice1On
		moveq	#0,d0
.Voice1On:	move.w	d0,NP_StructAdr+UPS_Voice1Vol
		mulu.w	NP_LeftVol(pc),d0
		lsr.w	#6,d0
		move.w	d0,8(a5)
		rts
.NoVoice1:	cmp.l	#$dff0b0,a5			;Right Volume
		bne.s	.NoVoice2
		move.w	d0,NP_OldVoice2
		tst.w	NP_Voice2
		bne.s	.Voice2On
		moveq	#0,d0
.Voice2On:	move.w	d0,NP_StructAdr+UPS_Voice2Vol
		mulu.w	NP_RightVol(pc),d0
		lsr.w	#6,d0
		move.w	d0,8(a5)
		rts
.NoVoice2:	cmp.l	#$dff0c0,a5			;Right Volume
		bne.s	.NoVoice3
		move.w	d0,NP_OldVoice3
		tst.w	NP_Voice3
		bne.w	.Voice3On
		moveq	#0,d0
.Voice3On:	move.w	d0,NP_StructAdr+UPS_Voice3Vol
		mulu.w	NP_RightVol(pc),d0
		lsr.w	#6,d0
		move.w	d0,8(a5)
		rts
.NoVoice3:	move.w	d0,NP_OldVoice4
		tst.w	NP_Voice4
		bne.w	.Voice4On
		moveq	#0,d0
.Voice4On:	move.w	d0,NP_StructAdr+UPS_Voice4Vol
		mulu.w	NP_LeftVol(pc),d0
		lsr.w	#6,d0
		move.w	d0,8(a5)
.Return:	rts

*-----------------------------------------------------------------------*
NP_NextPattern:	lea	np_block(pc),a6
		move.l	np_position(pc),a0
		addq	#2,6(a6)
		move	6(a6),d0
		cmp	-4(a0),d0
		bne.s	.next
		move	-2(a0),6(a6)	;End
		move.l	NP_SongendAdr(pc),a0
		jsr	(a0)
.next		clr.w	8(a6)		;PattPos löschen
		move.w	6(a6),d0
		asr.w	#1,d0
		rts

*-----------------------------------------------------------------------*
NP_PrevPattern:	lea	np_block(pc),a6
		move.l	np_position(pc),a0
		move.w	6(a6),d0
		subq.w	#2,d0
		bgt.s	.no
		move.w	-4(a0),d0
		subq.w	#2,d0
.no:		move.w	d0,6(a6)
		move.w	#0,8(A6)	
		asr.w	#1,d0
		rts

*-----------------------------------------------------------------------*
NP_GetPosNr:	move.w	np_block+6(pc),d0
		asr.w	#1,d0
		rts


* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* NoisePacker V2.02 PlayRoutine ©1990 Twins of Phenomena. *
* Used registers are d0-d7/a0-a6.     Not using lev6irq.  *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
np_init:	move.l	NP_data(pc),a0
		move.l	a0,a4
		lea	$dff000,a5
		lea	np_position(pc),a6
		moveq	#2,d0
		moveq	#0,d1
		move.l	a4,a3
np_init1:	add	(a4)+,a3
		move.l	a3,(a6)+
		dbf	d0,np_init1
		move	(a4)+,d0
		add.l	d0,a3

		move.l	#$01060100,(a6)+
		move	#$8200,(a6)+
		move.l	d1,(a6)+
		move.l	#np_portup,(a6)+
		move.l	#np_portdown,(a6)+
		move.l	#np_port,(a6)+
		move.l	#np_vib,(a6)+
		move.l	#np_port2,(a6)+
		move.l	#np_vib2,(a6)+
		move.l	#np_volslide,(a6)+
		move.l	#np_arp,(a6)+
		move.l	#np_songjmp,(a6)+
		move.l	#np_setvol,(a6)+
		move.l	#np_pattbreak,(a6)+
		move.l	#np_filter,(a6)+
		move.l	#np_setspeed,(a6)+

		moveq	#0,d0
		move.l	a4,a6
		add	-8(a4),a6
		sub	#12,a6
np_init2:	move.l	a3,(a4)
		move.l	a3,a2
		move	14(a4),d0
		add	d0,d0
		add.l	d0,a2
		move.l	a2,8(a4)
		move	4(a4),d0
		add	d0,d0
		add.l	d0,a3
		add	#16,a4
		cmp.l	a4,a6
		bne.s	np_init2
		rts

*--------------------------------------------------------------------------*
NP_Music:	movem.l	d1-a6,-(a7)
		lea	NP_StructAdr(pc),a0
		move.w	#UPSB_Adr!UPSB_LEN!UPSB_Per!UPSB_Vol!UPSB_DMACON,UPS_Flags(a0)
		clr.w	UPS_Voice1per(a0)
		clr.w	UPS_Voice2per(a0)
		clr.w	UPS_Voice3per(a0)
		clr.w	UPS_Voice4per(a0)
		move.w	#1,UPS_Enabled(A0)

		bsr.s	NP_Music2
		lea	NP_StructAdr(pc),a0
		clr.w	UPS_Enabled(A0)
		movem.l	(a7)+,d1-a6
		moveq	#0,d0
		rts
		
NP_Music2:	moveq	#0,d6
		lea	$dff000,a5
		lea	$d0(a5),a4
		lea	np_block(pc),a6
		subq.b	#1,(a6)			;SpeedCounter
		bhi.w	np_nonew

		lea	np_position(pc),a3
		move.l	(a3)+,a0		;Position Adresse
		add	6(a6),a0
		move	(a0),d0			;Patternnummer
		move.l	(a3)+,a0		;Pattern Adresse
		add	d0,a0
		move.l	(a3)+,a1		;Voice Adresse
		add	8(a6),a1
		lea	np_voidat1(pc),a2

		moveq	#8,d0
		moveq	#0,d5
np_loop1:	moveq	#0,d1
		move	(a0)+,d1
		lea	(a1,d1.l),a3
		move.b	(a3)+,d1
		move.b	(a3)+,d3
		move.b	(a3)+,d4

		move.b	d3,d7
		lsr.b	#4,d7
		move.b	d1,d2
		and	#1,d2
		beq.s	np_loop2
		moveq	#$10,d2
np_loop2:	move.l	NP_data(pc),a3		;hier aufpassen
		subq.l	#8,a3
		or.b	d7,d2
		bne.s	np_loop3

		move.b	1(a2),d2
		lsl	#4,d2
		add	d2,a3
		bra.s	np_loop4

np_loop3:	move.b	d2,1(a2)
		lsl	#4,d2
		add	d2,a3
		move	6(a3),4(a2)
np_loop4:	and	#$f,d3
		move.b	d3,2(a2)
		move.b	d4,3(a2)

		and	#$fe,d1
		beq.s	np_loop5

		move	np_periods-2(pc,d1.w),d7

		subq	#3,d3
		beq.w	np_setport
		subq	#2,d3
		beq.w	np_setport

		or	d0,d5
		move.b	d1,(a2)
		move.b	d6,49(a2)
		move	d7,24(a2)	;
	bsr	np_getvoice
		move.l	(a3)+,(a4)	;Adresse		   (a3)
		move	(a3)+,4(a4)	;Länge/2=Anzahl der Worte 4(a3)
		addq.l	#2,a3		;Lautstärke		  6(a3)
		move.l	(a3)+,72(a2)	;Repeatadresse		  8(a3)
		move	(a3)+,76(a2)	;Repeatlänge/2		 12(a3)

		subq	#6,d3
		bmi.s	np_loop6
		add	d3,d3
		add	d3,d3
		move.l	42(a6,d3.w),a3
		jmp	(a3)

np_loop5:	sub	#11,d3
		bmi.s	np_loop6
		add	d3,d3
		add	d3,d3
		move.l	42(a6,d3.w),a3
		jmp	(a3)

np_periods:	dc.w	$0358,$0328,$02fa,$02d0,$02a6,$0280,$025c,$023a,$021a
		dc.w	$01fc,$01e0,$01c5,$01ac,$0194,$017d,$0168,$0153,$0140
		dc.w	$012e,$011d,$010d,$00fe,$00f0,$00e2,$00d6,$00ca,$00be
		dc.w	$00b4,$00aa,$00a0,$0097,$008f,$0087,$007f,$0078,$0071

np_loop6:	move	24(a2),6(a4)			;Sampleperiode

np_loop7:	bsr.w	NP_SetVolume

	;	move	4(a2),8(a4)			;Vol 1

		addq	#6,a2
		sub	#$10,a4
		lsr	#1,d0
		bne.w	np_loop1

		move	d5,$96(a5)
		move.b	d5,5(a6)
		move.b	1(a6),(a6)

	bsr	NP_Waitdma

;		move	#270,d0		;hätte auf Turbokarten keinen Sinn !
;np_wait1:	dbf	d0,np_wait1

		move	4(a6),$96(a5)

	bsr	NP_Waitdma

;		moveq	#80,d0		;Turbokarten und sogar 68010-er
;np_wait2:	dbf	d0,np_wait2	;Prozessoren versagen hier;
					;typischer A500 Code
					;aber ich hab ja selber einen :-)

		move.l	np_position(pc),a0
		bset	#0,2(a6)
		beq.w	np_break
		addq	#3,8(a6)
		cmp	#192,8(a6)
		bne.s	np_next
np_break:	move	d6,8(a6)
		addq	#2,6(a6)
		move	6(a6),d0
		cmp	-4(a0),d0
		bne.s	np_next
		move	-2(a0),6(a6)

		move.l	NP_SongEndAdr(pc),a0
		jsr	(a0)

np_next:	lea	np_voidat2(pc),a0
		move.l	(a0)+,$d0(a5)
		move	(a0)+,$d4(a5)
		move.l	(a0)+,$c0(a5)
		move	(a0)+,$c4(a5)
		move.l	(a0)+,$b0(a5)
		move	(a0)+,$b4(a5)
		move.l	(a0)+,$a0(a5)
		move	(a0)+,$a4(a5)
		rts

np_setvol:	move.b	d4,5(a2)
		bra.w	np_loop6

np_pattbreak:	move	d6,2(a6)
		bra.w	np_loop6

np_songjmp:	move	d6,2(a6)
		move.b	d4,7(a6)
		bra.w	np_loop6

np_setspeed:	move.b	d4,1(a6)
		bra.w	np_loop6

np_filter:
;		and.b	#$fd,$bfe001
;		or.b	d4,$bfe001
		bra.w	np_loop6

np_setport:	move.b	d6,50(a2)
		move	d7,26(a2)
		cmp	24(a2),d7
		beq.s	np_clrport
		bge.w	np_loop7
		move.b	#1,50(a2)
		bra.w	np_loop7

np_clrport:	move	d6,26(a2)
		bra.w	np_loop7

np_nonew:	lea	np_voidat1(pc),a0
		moveq	#3,d0
np_lop1:	moveq	#0,d1
		move.b	2(a0),d1
		beq.s	np_lop2
		subq	#8,d1
		bhi.s	np_lop2
		addq	#7,d1
		add	d1,d1
		add	d1,d1
		move.l	10(a6,d1.w),a3
		jmp	(a3)
np_lop2:	addq	#6,a0
		sub	#$10,a4
		dbf	d0,np_lop1
		rts

np_portup:	moveq	#0,d2
		move.b	3(a0),d2
		sub	d2,24(a0)
		cmp	#$71,24(a0)
		bpl.s	np_portup2
		move	#$71,24(a0)
np_portup2:	move	24(a0),6(a4)
		bra.s	np_lop2

np_portdown:	moveq	#0,d2
		move.b	3(a0),d2
		add	d2,24(a0)
		cmp	#$358,24(a0)
		bmi.s	np_portdown2
		move	#$358,24(a0)
np_portdown2:	move	24(a0),6(a4)
		bra.s	np_lop2

np_arp:		moveq	#0,d2
		move.b	(a6),d2
		sub.b	1(a6),d2
		neg.b	d2
		move.b	np_arplist(pc,d2.w),d2
		beq.s	np_arp0
		subq.b	#2,d2
		beq.s	np_arp2
np_arp1:	move.b	3(a0),d2
		lsr	#3,d2
		and	#$e,d2
		bra.s	np_arp3

np_arp2:	move.b	3(a0),d2
		and	#$f,d2
		add	d2,d2
np_arp3:	add.b	(a0),d2
		cmp	#$48,d2
		bls.s	np_arp4
		moveq	#$48,d2
np_arp4:	lea	np_periods-2(pc),a3
		move	(a3,d2.w),6(a4)
		bra.w	np_lop2
np_arp0:	move	24(a0),6(a4)
		bra.w	np_lop2

np_arplist:dc.b 0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1

np_sin:	dc.b $00,$18,$31,$4a,$61,$78,$8d,$a1,$b4,$c5,$d4,$e0,$eb,$f4,$fa,$fd
	dc.b $ff,$fd,$fa,$f4,$eb,$e0,$d4,$c5,$b4,$a1,$8d,$78,$61,$4a,$31,$18

np_vib:		move.b	3(a0),d3
		beq.s	np_vib2
		move.b	d3,48(a0)
np_vib2:	move.b	49(a0),d3
		lsr.b	#2,d3
		and	#$1f,d3
		moveq	#0,d2
		move.b	np_sin(pc,d3.w),d2
		move.b	48(a0),d3
		and	#$f,d3
		mulu	d3,d2
		lsr	#7,d2
		move	24(a0),d3
		tst.b	49(a0)
		bmi.s	np_vibsub
		add	d2,d3
		bra.s	np_vib3
np_vibsub:	sub	d2,d3
np_vib3:	move	d3,6(a4)
		move.b	48(a0),d3
		lsr.b	#2,d3
		and	#$3c,d3
		add.b	d3,49(a0)
		cmp.b	#20,d1
		bne.w	np_lop2

np_volslide:	move.b	3(a0),d2
		add.b	d2,5(a0)
		bmi.s	np_vol3
		cmp.b	#$40,5(a0)
		bmi.s	np_vol2
		move	#$40,4(a0)
np_vol2:	bsr.w	NP_SetVolume2
	;	move	4(a0),8(a4)			;Vol2
		bra.w	np_lop2

np_vol3:	move	d6,4(a0)
		bsr.w	NP_SetVolume2
	;	move	4(a0),8(a4)			;Vol3
		bra.w	np_lop2

np_port:	move.b	3(a0),d2
		beq.s	np_port2
		move.b	d2,29(a0)

np_port2:	move	26(a0),d2
		beq.s	np_rts
		move	28(a0),d3
		tst.b	50(a0)
		bne.s	np_sub
		add	d3,24(a0)
		cmp	24(a0),d2
		bgt.s	np_portok
		move	d2,24(a0)
		move	d6,26(a0)
np_portok:	move	24(a0),6(a4)
np_rts:		cmp.b	#16,d1
		beq.s	np_volslide
		bra.w	np_lop2

np_sub:		sub	d3,24(a0)
		cmp	24(a0),d2
		blt.s	np_portok
		move	d2,24(a0)
		move	d6,26(a0)
		move	24(a0),6(a4)
		cmp.b	#16,d1
		beq.w	np_volslide
		bra.w	np_lop2

NP_waitdma
	movem.l	d0-d1,-(sp)
	moveq	#8,d0
.dma1	move.b	$dff006,d1
.dma2	cmp.b	$dff006,d1
	beq	.dma2
	dbeq	d0,.dma1
	movem.l	(sp)+,d0-d1
	rts	

np_position:	dc.l	0
np_pattern:	dc.l	0

np_voice:	dc.l	0
np_block:	blk.w	31,0
np_voidat1:	blk.l	18,0
np_voidat2:	blk.l	6,0

