*******************************************************************************
* Pro-Runner v2.4					 Copyright © EX4 1994 *
* ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ *
* Updated by :	2-Cool/EX4 © 1994					      *
* Original v2.0 by Cosmos/Sanity © 1992					      *
*									      *
* Notice:								      *
* ¯¯¯¯¯¯¯								      *
* This version of Pro-Runner is using CIAA timing with (h/w) a NON-OS Level   *
* 6 Interrupt! The sample dma is running off a RASTERTIMING to enable this!   *
* You should only really use this player if you NEED to, as CIAA timing is a  *
* real pain in the rear and this VBL version therefore needs more rasters...  *
*									      *
* Compatible with: »	Pro-Runner v2.0 Packed,	(CIAA_TIMING) Modules	      *
*		   »	Pro-Tracker (Normal),	(CIAA_TIMING) Modules	      *
*******************************************************************************

		section	PR_CIAA,code
	
*-------------- Init Pro-Runner CIAA Timing & Interrupts..

		bsr	pr_setciaa

*-------------- Init Pro-Runner pattern data..

		lea	pr_data,a0
		bsr	pr_init
	
WaitLMB:	btst	#6,$bfe001		;LMB Pressed?
		bne.s	WaitLMB
		btst	#10,$dff016		;And RMB Pressed?
		bne.s	WaitLMB

*-------------- Turn off CIAA Timing & Interrupts

		bsr	pr_clrciaa

*-------------- Turn off sound dma..

		bsr	pr_end
		rts

*******************************************************************************
* Level 6 MC680x0 Autovector Interrupt (CIAA Timed)
* ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
*******************************************************************************

Level6:		tst.b	$bfdd00			; restart ciaa timer
		movem.l	d0-d7/a0-a6,-(sp)	; preserve registers
		andi.w	#$2008,$dff01e		; check for ports interrupt
		beq.s 	No_Level6
		move.w	#$2008,$dff09c		; clear request

		bsr	pr_music

No_Level6:	movem.l	(sp)+,d0-d7/a0-a6	; restore registers
		rte


*******************************************************************************
* Pro-Runner CIAA TIMING initialization routines...
*******************************************************************************

pr_setciaa:		
;-------------- Configure Level_6 CIAA`s

		move.l	4.w,a6			; execbase
		move.b	530(a6),d0		; execbase VBLANK_FREQUENCY

		move.l	#1773447,d7 		; PAL cia time
		cmp.b	#50,d0			; check if 50hz
		beq.s	_pal			

		move.l	#1789773,d7	 	; NTSC cia time

_pal:		lea	pr_defspeed(pc),a0
		move.l	d7,(a0)
		divu	#125,D7 		; Default to normal 50 Hz timer
		move.w	d7,pr_ciatime-pr_defspeed(a0)

		lea	$bfd000,a4
		move.b	#%01111111,$d00(a4)	; all cia timers off
		move.b	#%00010001,$e00(a4)	; ciaa cra (control register)
		move.b	#%10000001,$d00(a4)	; ciaa icr (irq control)
		move.b	d7,$400(a4)		; set timer (upper byte)
		lsr.w	#8,d7
		move.b	d7,$500(a4)		; set timer (lower byte)

;-------------- Install Level_6 IRQ

		bsr	GetVBR			; on exit, a4=VBR base
		lea	Level6(pc),a0
		move.l	$78(a4),OldLev6-Level6(a0)	; store old level 6
		move.l	a0,$78(a4)		; install my level 6
		move.w	#$a000,$dff09a		; enable level 6 int
		rts

pr_clrciaa:	bsr	GetVBR
		move.l	oldlev6(pc),$78(a4)	; restore old level 6
		move.l	#$10,$dff09a 		; Disable Level 3 Interupt
		moveq	#0,d0			; fin
		rts
		
GetVBR:		movem.l	d0-d7/a0-a3/a5-a6,-(a7)
		move.l	4.w,a6
		moveq	#15,d7
		and	296(a6),d7
		beq	.68000
		lea	PutBase(pc),a5
		jsr	-30(a6)
.68000		move.l	d7,a4
		movem.l	(a7)+,d0-d7/a0-a3/a5-a6
		rts

PutBase		movec	vbr,d7
		rte

OldLev6:	dc.l	0			; store old Level6

*****************************************
* PRORUNNER_VBL (CONFIGURED FOR CIAA)	*
*****************************************
*					*
* Supporting the following effects:	*
*					*
*	- Running with 68010/20/30/40	*
*	- Using VBR-register		*
*	- Packed/Normal PT-Moduleformat	*
*	- Fade Sound in/out		*
*	- Variable Musicfadespeed	*
*	- Variable Interrupt-timing	*
*	- Finetune			*
*	- Normal play or Arpeggio	*
*	- Slide Frequenz up		*
*	- Slide	Frequenz down		*
*	- Tone Portamento		*
*	- Vibrato			*
*	- Tone Portamento+Volume Slide	*
*	- Vibrato + Volume Slide	*
*	- Tremolo			*
*	- Set SampleOffset		*
*	- Volume Slide			*
*	- Position Jump			*
*	- Set Volume			*
*	- Pattern Break			*
*	- Set Speed (CIAA_TIMING)	*
* - E-Commands:				*
*	- Set Filter			*
*	- Fine Slide Up			*
*	- Fine Slide Down		*
*	- Glissando Control		*
*	- Set Vibrato Waveform		*
*	- Set Finetune			*
*	- Set Loop / Jump to Loop	*
*	- Set Tremolo Waveform		*
*	- Retrig Note			*
*	- Fine VolumeSlide Up		*
*	- Fine VolumeSlide Down		*
*	- NoteCut			*
*	- NoteDelay			*
*	- PatternDelay			*
*	- FunkRepeat			*
*					*
*****************************************

YES				EQU	1
NO				EQU	0

INCLUDEFADINGROUTINE		EQU	YES
PACKEDSONGFORMAT		EQU	NO	;Change for Pro-Runner Packed!

FADINGSTEPS			EQU	8	; ( 0< FADINGSTEPS <9 )
MAXVOLUME			EQU	2^FADINGSTEPS
DMARASTERS			EQU	5	;rasters waits for dma...

SAMPLELENGTHOFFSET		EQU	4
SAMPLEVOLUMEOFFSET		EQU	6
SAMPLEREPEATPOINTOFFSET		EQU	8
SAMPLEWITHLOOP			EQU	12
SAMPLEREPEATLENGTHOFFSET	EQU	14
SAMPLEFINETUNEOFFSET		EQU	16

* Init-Routine *******************************************************

pr_init:
	lea	pr_framecounter(pc),a6
	move.l	a0,pr_module-pr_framecounter(a6)
	move.w	#$7fff,pr_oldledvalue-pr_framecounter(a6)
	cmp.l	#0,a0
	bne.s	pr_init1
	rts
pr_init1:
	IFEQ	PACKEDSONGFORMAT-YES
	cmp.l	#'SNT!',(a0)
	beq.s	pr_init2
	ELSE
	cmp.l	#'M.K.',1080(a0)
	beq.s	pr_init2
	cmp.l	#'SNT.',1080(a0)
	beq.s	pr_init2
	ENDC
	rts
pr_init2:
	IFEQ	PACKEDSONGFORMAT-YES
	lea	8(a0),a1
	ELSE
	lea	20(a0),a1
	ENDC
	lea	pr_Sampleinfos(pc),a2
	moveq.l	#32,d7
	moveq	#30,d0
pr_init3:
	IFNE	PACKEDSONGFORMAT-YES
	lea	22(a1),a1		; Samplenamen überspringen
	ENDC
	move.w	(a1)+,SAMPLELENGTHOFFSET(a2)	; Samplelength in Words
	lea	pr_periods(pc),a3
	moveq	#$f,d2
	and.b	(a1)+,d2		; Finetuning
	mulu.w	#36*2,d2
	add.l	d2,a3
	move.l	a3,SAMPLEFINETUNEOFFSET(a2)
	moveq	#0,d1
	move.b	(a1)+,d1
	move.w	d1,SAMPLEVOLUMEOFFSET(a2)	; Volume
	moveq.l	#0,d1
	move.w	(a1)+,d1		; Repeatpoint in Bytes
	add.l	d1,d1
	move.l	d1,SAMPLEREPEATPOINTOFFSET(a2)
	move.w	(a1)+,d1
	clr.w	SAMPLEWITHLOOP(a2)
	cmp.w	#1,d1
	bls.s	pr_init3_2
	addq.w	#1,SAMPLEWITHLOOP(a2)
pr_init3_2:
	move.w	d1,SAMPLEREPEATLENGTHOFFSET(a2)	; Repeatlength
	add.l	d7,a2
	dbf	d0,pr_init3

	moveq	#0,d0
	IFEQ	PACKEDSONGFORMAT-YES
	move.b	256(a0),d0
	ELSE
	move.b	950(a0),d0		; Number of patterns
	ENDC
	subq.w	#1,d0
	move.w	d0,pr_highestpattern-pr_framecounter(a6)
	moveq.l	#0,d1
	lea	pr_Patternpositions(pc),a3
	IFEQ	PACKEDSONGFORMAT-YES
	lea	258(a0),a1		; 1.Patternpos
	lea	770(a0),a2		; 1.Patterndata
	lea	642(a0),a4		; 1.Patternoffset
pr_init4:
	moveq.l	#0,d2
	move.b	(a1)+,d2
	add.w	d2,d2
	move.w	(a4,d2.w),d2
	add.l	a2,d2
	move.l	d2,(a3)+
	dbf	d0,pr_init4
	ELSE
	lea	952(a0),a1		; 1. Patternpos
	lea	1084(a0),a2		; 1. Patterndata
pr_init4:
	move.b	(a1)+,d2		; x. Patternpos
	moveq.l	#0,d3
	move.b	d2,d3
	mulu.w	#1024,d3
	add.l	a2,d3
	move.l	d3,(a3)+
	dbf	d0,pr_init4
	ENDC

	IFEQ	PACKEDSONGFORMAT-YES
	move.l	4(a0),d2
	add.l	a0,d2
	ELSE
	lea	952(a0),a1
	moveq.l	#0,d1
	moveq	#127,d0
pr_init4_1:
	move.b	(a1)+,d2
	cmp.b	d1,d2			; Highest Pattern ?
	bls.s	pr_init4_2
	move.b	d2,d1
pr_init4_2:
	dbf	d0,pr_init4_1
	addq.w	#1,d1
	move.l	a0,d2
	mulu.w	#1024,d1		; Highest Pattern * 1024 Bytes
	add.l	#1084,d2
	add.l	d1,d2
	ENDC
	lea	pr_Sampleinfos(pc),a3
	lea	pr_Sampleinfos+SAMPLELENGTHOFFSET(pc),a2
	moveq.l	#32,d7
	move.l	d2,(a3)
	moveq	#29,d0
pr_init4_3:
	move.l	(a3),d1
	add.l	d7,a3
	moveq.l	#0,d2
	move.w	(a2),d2
	add.l	d7,a2
	add.l	d2,d2
	add.l	d2,d1
	move.l	d1,(a3)
	dbf	d0,pr_init4_3

	lea	pr_Sampleinfos(pc),a2
	lea	pr_Sampleinfos+SAMPLEREPEATPOINTOFFSET(pc),a3
	moveq.l	#32,d7
	moveq	#30,d0
pr_init4_4:
	move.l	(a2),d1
	add.l	d1,(a3)
	add.l	d7,a2
	add.l	d7,a3
	dbf	d0,pr_init4_4
	
	IFNE	PACKEDSONGFORMAT-YES
	
	cmp.l	#'SNT.',1080(a0)
	beq.s	pr_init7
	
	lea	1084(a0),a1
	move.l	pr_Sampleinfos(pc),a2
	move.b	#$f0,d6
	move.w	#$fff,d7
pr_init5:
	move.b	(a1),d0
	move.b	2(a1),d1
	move.w	(a1),d2
	and.w	d7,2(a1)
	and.w	d7,d2
	
	and.b	d6,d0
	lsr.b	#4,d1
	or.b	d1,d0
	move.b	d0,(a1)
	
	tst.w	d2
	beq.s	pr_init5_3
	lea	pr_periods(pc),a4
	moveq	#0,d1
pr_init5_2:
	addq.w	#1,d1
	cmp.w	(a4)+,d2
	bne.s	pr_init5_2
	move.b	d1,1(a1)
pr_init5_3:
	cmp.b	#$d,2(a1)
	bne.s	pr_init5_4

	moveq	#0,d1
	move.b	3(a1),d1
	moveq	#$f,d2
	and.w	d1,d2
	lsr.w	#4,d1
	mulu.w	#10,d1
	add.w	d2,d1
	cmp.b	#63,d1
	bls.s	pr_init5_3_2
	moveq	#63,d1
pr_init5_3_2:
	move.b	d1,3(a1)
pr_init5_4:
	addq.l	#4,a1
	cmp.l	a2,a1
	blt.s	pr_init5	

	move.l	#'SNT.',1080(a0)

	ENDC
	
pr_init7:
	lea	pr_Arpeggiofastlist(pc),a2
	lea	pr_Arpeggiofastlistperiods(pc),a1
	lea	35*2(a1),a1		; to the end of list...
	moveq	#0,d0
	moveq	#35,d1
	move.w	#999,d2
	moveq	#0,d6
pr_init8:
	move.w	-(a1),d7
	addq.w	#1,d6
pr_init8_2:
	cmp.w	d7,d0
	blt.s	pr_init8_4
	subq.w	#1,d1
	tst.b	d1
	bne.s	pr_init8
pr_init8_3:
	move.b	d1,(a2)+
	dbf	d2,pr_init8_3
	bra.s	pr_init8_5	
pr_init8_4:
	move.b	d1,(a2)+
	addq.w	#1,d0
	dbf	d2,pr_init8_2
pr_init8_5:

	lea	pr_Channel0(pc),a1
	move.w	#1,pr_Channel1-pr_Channel0(a1)
	move.w	#1,pr_Channel2-pr_Channel0(a1)
	move.w	#1,pr_Channel3-pr_Channel0(a1)
	move.w	#1,(a1)+
	moveq	#(pr_Channel1-pr_Channel0)/2-2,d0
pr_init9_2:
	clr.w	pr_Channel1-pr_Channel0(a1)
	clr.w	pr_Channel2-pr_Channel0(a1)
	clr.w	pr_Channel3-pr_Channel0(a1)
	clr.w	(a1)+
	dbf	d0,pr_init9_2

	lea	pr_fastperiodlist(pc),a1
	lea	pr_periods(pc),a2
	move.l	a2,(a1)
	moveq.l	#36*2,d1
	moveq	#14,d0
pr_init9_3:
	move.l	(a1)+,d2
	add.l	d1,d2
	move.l	d2,(a1)
	dbf	d0,pr_init9_3
		
	lea	pr_Arpeggiofastdivisionlist(pc),a1
	moveq	#0,d1
	move.w	#$ff,d0
pr_init9_4:
	move.b	d1,(a1)+
	subq.b	#1,d1
	bpl.s	pr_init9_4_2
	moveq	#2,d1
pr_init9_4_2:
	dbf	d0,pr_init9_4
	
	move.w	#6,pr_speed-pr_framecounter(a6)
	move.w	pr_speed(pc),(a6)
	clr.w	pr_Patternct-pr_framecounter(a6)
	move.w	pr_highestpattern(pc),d0
	move.w	pr_startposition(pc),d1
	blt.s	pr_init9_5
	cmp.w	d0,d1
	bls.s	pr_init9_5_2
pr_init9_5:
	clr.w	pr_startposition-pr_framecounter(a6)
pr_init9_5_2:
	move.w	pr_startposition(pc),pr_currentpattern-pr_framecounter(a6)
	
	lea	pr_Patternpositions(pc),a3
	move.l	a3,d0
	moveq.l	#0,d1
	move.w	pr_startposition(pc),d1
	lsl.l	#2,d1
	add.l	d1,d0
	move.l	d0,pr_Patternpt-pr_framecounter(a6)
	move.l	pr_Patternpt(pc),a5
	move.l	(a5),pr_Currentposition-pr_fram