/**********************************************************************/
/*                                                                    */
/*             STARTREKKER V1.0 REPLAY ROUTINE FOR AZTEC-C            */
/*            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~          */
/* Some infos about the replay-routine:                               */
/*   - This routine stops all irq's.                                  */
/*   - Enter the Module lenght at the end of the Routine (at the      */
/*     marked position!)                                              */
/*                                                                    */
/* Here are the instructions for this Replay-Routine.                 */
/*                                                                    */
/* Compile this Programm with the following options:                  */
/*     CC +D +C startrekkerreplay.c                                   */
/*                                                                    */
/* And then link it with the following options:                       */
/*     LN +Cdb startrekkerreplay.o -lcl                               */
/*                                                                    */
/* After linking the programm load the C-monitor and load the         */
/* executable programm to address $40000. Then load the Startrekker-  */
/* module to address $4291a. Then you must save the programm to disk. */
/*                                                                    */
/* F.X. in the C-Monitor:                                             */
/*                                                                    */
/* .L startrekkerreplay 40000                                         */
/* Load $040000-$063530                                               */
/* .L StartrekkerModule 4291a                                         */
/* Load $04291a-61ec0                                                 */
/* .S startrekkerreplay 40000 63530                                   */
/* Save $040000-$063530                                               */
/*                                                                    */
/* After that you must use SCATom to change the hunks. All hunks must */
/* be loaded into CHIP-MEM, otherwise you hear only shit!             */
/*                                                                    */
/* I hope you undestand these instructiuons. If you use this replay-  */
/* Routine in your programms then put it at the top of your Source-   */
/* Code (After the include-files). Then you can load the Startrekker  */
/* Module to the same address.                                        */
/* For more infos write to:                                           */
/*          REFLEX ­ PLK 370527 F ­ 4600 DORTMUND 1 ­ GERMANY         */
/*                                                                    */
/*                                                 BLADERUNNER/REFLEX */
/**********************************************************************/
#include "exec/memory.h"
#include "exec/exec.h"
#include "functions.h"

#asm
;========================================================================
;========================================================================
;===            !!! STARTREKKER 8 CHANNEL REPLAY ROUTINE !!!          === 
;===             CONVERTED TO AZTEC-C BY BLADERUNNER/REFLEX           ===
;===                                                                  ===
;===     REFLEX - PLK 370527 F - 4600 DORTMUND 1 - UNITED GERMANY     ===
;========================================================================
;========================================================================

;================================ macros ================================

mt8_add:macro					;mix two sample-bytes
	move.b	(a0,d0.w),d4			;get sample-byte a
	ext.w	d4
	move.b	(a1,d1.w),d5			;get sample-byte b
	ext.w	d5
	add.w	d5,d4				; & mix them
	asr.w	#1,d4
	move.b	d4,(a5)+
	swap	d0
	swap	d1
	add.l	d2,d0				;increase pointer to next
	add.l	d3,d1				;sample-byte
	swap	d0
	swap	d1
	endm

;============================= test-program =============================

  public _start

_start:	lea	$dff000,a6
	move.w	#$4000,$9a(a6)
	lea	mt8_data,a0			;module => a0
	bsr.s	mt8_init			;stop irq & init player
	moveq	#0,d1
loop:	bsr	mt8_play			;play music
	move.l	$4(a6),d0			;get max raster-time
	lsr.l	#8,d0				; ( => d1 !)
	and.w	#$1ff,d0
	cmp.w	d0,d1
	bhi.s	lab
	move.w	d0,d1
lab:	btst	#6,$bfe001			;wait for mouse
	bne.s	loop
	bsr	mt8_end				;stop player & allow irq
	move.w	#$c000,$9a(a6)
	rts

;============================ initialization ============================

mt8_init:
        movem.l d0-d7/a0-a6,-(a7)
	lea	mt8_mdl,a1			;save module-address
	move.l	a0,(a1)
	move.l	a0,a1
	add.w	#$3b8,a1
	moveq	#$7f,d0
	moveq	#0,d1
mt8_lp1:move.l	d1,d2
	subq.w	#1,d0
mt8_lp2:move.b	(a1)+,d1
	cmp.b	d2,d1				;get highest pattern
	bgt.s	mt8_lp1
	dbf	d0,mt8_lp2
	addq.b	#1,d2

	lea	mt8_ins,a1			;instrument-list => a1
	moveq	#10,d3
	asl.l	d3,d2
	move.l	d2,a2
	add.w	#$43c,a2
	add.l	a0,a2				;sample-offset => a2
	moveq	#$1e,d0				;init 31 instruments
mt8_lp3:clr.l	(a2)
	move.l	a2,(a1)+			;pointer => liste
	moveq	#0,d1
	move.w	42(a0),d1
	add.l	d1,d1
	add.l	d1,a2
	add.w	#$1e,a0
	dbf	d0,mt8_lp3

	move.l	mt8_mdl,a0
	add.w	#$3b8,a0
	moveq	#0,d1
	move.b	(a0),d1				;get first pattern
	moveq	#10,d0
	lsl.l	d0,d1
	add.w	#$42c-$3b8,a0
	add.l	a0,d1
	lea	mt8_evn,a0
	move.l	d1,(a0)+
	add.l	#$400,d1
	move.l	d1,(a0)

	bset	#1,$bfe001			;filter off

	lea	mt8_ctr,a0
	move.w	#$0006,(a0)+			;set speed
	clr.w	(a0)+
	clr.w	(a0)+
	move.w	#$139,(a0)			;set buffer 2

	lea	mt8_dat,a0
	move.w	#$37+$272,d0
mt8_cl1:clr.l	(a0)+				;clear buffer
	dbf	d0,mt8_cl1

	lea	mt8_smp,a1
	lea	mt8_dat,a0
	moveq	#7,d0
mt8_lp4:move.l	a0,(a1)+			;clear now-played instr.
	add.w	#$1c,a0
	dbf	d0,mt8_lp4

	lea	$dff000,a6
	move.w	#15,$96(a6)			;stop audio-dma
	lea	mt8_ch1,a0
	move.l	a0,$a0(a6)			;init audio-dma
	add.w	#$272,a0
	move.l	a0,$b0(a6)
	add.w	#$272,a0
	move.l	a0,$c0(a6)
	add.w	#$272,a0
	move.l	a0,$d0(a6)
	move.w	#$139,d0			;length 313 sample-bytes
	move.w	d0,$a4(a6)
	move.w	d0,$b4(a6)
	move.w	d0,$c4(a6)
	move.w	d0,$d4(a6)
	move.w	#$e3,d0				;play one sample per line
	move.w	d0,$a6(a6)
	move.w	d0,$b6(a6)
	move.w	d0,$c6(a6)
	move.w	d0,$d6(a6)
	moveq	#$40,d0				;volumen 64
	move.w	d0,$a8(a6)
	move.w	d0,$b8(a6)
	move.w	d0,$c8(a6)
	move.w	d0,$d8(a6)

mt8_wt1:move.l	$4(a6),d0			;wait for line $12d
	lsr.l	#8,d0
	and.w	#$1ff,d0
	cmp.w	#$12d,d0
	bne.s	mt8_wt1

	moveq	#9,d0
mt8_wt2:dbf	d0,mt8_wt2
	move.w	#$800f,$96(a6)			;start dma

	movem.l	(a7)+,d0-d7/a0-a6
	rts

;============================= main-routine =============================

mt8_play:
        movem.l d0/a2-a5,-(a7)
	lea	mt8_chg,a2
	eor.w	#$139,(a2)			;change between buffer
	move.w	(a2),d0
	bsr	mt8_get				;get next note
	lea	mt8_smp,a2
	movem.l	(a2)+,a3/a4
	lea	mt8_ch1,a5
	add.w	d0,a5
	bsr	mt8_mix				;mix channel 1 & 2
	movem.l	(a2)+,a3/a4
	lea	mt8_ch2,a5
	add.w	d0,a5
	bsr	mt8_mix				;mix channel 3 & 4
	movem.l	(a2)+,a3/a4
	lea	mt8_ch3,a5
	add.w	d0,a5
	bsr	mt8_mix				;mix channel 5 & 6
	movem.l	(a2)+,a3/a4
	lea	mt8_ch4,a5
	add.w	d0,a5
	bsr	mt8_mix				;mix channel 7 & 8
	movem.l	(a7)+,d0/a2-a5
	rts

;================================ stop ==================================

mt8_end:move.l	a6,-(a7)
	lea	$dff000,a6
	move.w	#$f,$96(a6)			;stop dma
	clr.w	$a8(a6)				;set vol to 0
	clr.w	$b8(a6)
	clr.w	$c8(a6)
	clr.w	$d8(a6)
	bclr	#1,$bfe001			;filter off
	move.l	(a7)+,a6
	rts

;============================== routines ================================

mt8_get:movem.l	d0-d7/a0-a6,-(a7)
	lea	$dff004,a0
mt8_wt3:move.l	(a0),d0
	lsr.l	#8,d0
	and.w	#$1ff,d0
	cmp.w	#$12d,d0			;wait for line $12d
	bne.s	mt8_wt3

	lea	mt8_ctr,a0
	tst.b	(a0)				;new note ?
	bne.s	mt8_l07
	bsr.s	mt8_gt2				; => get data
mt8_l07:subq.b	#1,(a0)
	movem.l	(a7)+,d0-d7/a0-a6
	rts

mt8_gt2:move.l	a0,-(a7)
	move.b	1(a0),(a0)			;set speed

	moveq	#16,d0
	lea	mt8_evn,a0
	add.l	d0,(a0)+			;point to next note
	add.l	d0,(a0)+
	lea	mt8_ins,a0
	move.l	mt8_mdl,a1
	add.w	#$2a,a1
	lea	mt8_dat,a3
	lea	mt8_smp,a5
	move.l	mt8_evn,a2			;even pattern
	bsr.s	mt8_set
	move.l	mt8_odd,a2			;odd pattern
	bsr.s	mt8_set

	lea	mt8_nte,a0
	lea	mt8_pos,a1
	move.w	(a1),d0				;add pattern-pos
	addq.w	#1,(a0)
	cmp.w	#$40,(a0)
	bne.s	mt8_ed2
	addq.w	#1,d0
mt8_nxt:clr.w	(a0)
	move.l	mt8_mdl,a0
	addq.b	#1,d0				;remove bug
	cmp.b	$3b6(a0),d0			;end of song ?
	blt.s	mt8_l14
	move.b	$3b7(a0),d0			;ja, restart !
	addq.w	#1,d0
mt8_l14:add.w	#$3b8,a0
	subq.w	#1,d0
	move.w	d0,(a1)
	moveq	#0,d1
	move.b	(a0,d0.w),d1
	moveq	#10,d0
	lsl.l	d0,d1
	add.w	#$42c-$3b8,a0
	add.l	a0,d1
	lea	mt8_evn,a0
	move.l	d1,(a0)+
	add.l	#$400,d1
	move.l	d1,(a0)
mt8_ed2:move.l	(a7)+,a0
	rts

mt8_set:lea	$dff0a9,a6
	moveq	#3,d7
mt8_lp5:moveq	#0,d0
	moveq	#0,d1
	move.b	2(a2),d0			;get command
	and.b	#15,d0
	cmp.b	#15,d0				;speed ?
	bne.s	mt8_l08
	lea	mt8_spd,a4
	move.b	3(a2),(a4)
mt8_l08:cmp.b	#12,d0				;get vol
	bne.s	mt8_l09
	move.b	3(a2),(a6)
	st 	d1
mt8_l09:move.w	(a2),d0
	and.w	#$fff,d0
	beq.s	mt8_l13				;new note ?
	tst.b	d1
	bne.s	mt8_l10
	move.b	#$40,(a6)
mt8_l10:move.l	a3,(a5)
	move.l	#$38c000,d1			;get sample-speed
	divu	d0,d1
	swap	d1
	clr.w	d1
	swap	d1
	add.l	d1,d1
	add.l	d1,d1
	move.l	d1,8(a3)
	moveq	#0,d0
	move.b	2(a2),d0
	lsr.b	#4,d0
	btst	#7,(a2)
	beq.s	mt8_l11				;instrument 16...31 ?
	add.b	#$10,d0
mt8_l11:move.w	d0,d1
	beq.s	mt8_l13
	subq.w	#1,d1
	add.w	d0,d0
	add.w	d0,d0
	move.l	-4(a0,d0.w),(a3)		;set sample-address
	mulu	#$1e,d1
	move.w	(a1,d1.w),d0
	add.l	d0,d0
	move.l	d0,4(a3)			;set sample-length
	tst.w	4(a1,d1.w)
	beq.s	mt8_l12				;loop ?
	move.l	(a3),12(a3)			; => set loop
	moveq	#0,d0
	move.w	4(a1,d1.w),d0
	add.l	d0,d0
	add.l	d0,12(a3)
	move.w	6(a1,d1.w),d0			;set loop-length
	add.l	d0,d0
	move.l	d0,16(a3)
	bra.s	mt8_l13
mt8_l12:clr.l	12(a3)				;clear loop
	clr.l	16(a3)
	clr.l	20(a3)
mt8_l13:addq.w	#4,a2				;set pointer to next
	add.w	#28,a3				;channel
	addq.w	#4,a5
	add.w	#16,a6
	dbf	d7,mt8_lp5
	rts

mt8_mix:movem.l	d0-d7/a0-a6,-(a7)
	move.l	8(a3),d0			;get sample-position
	move.l	8(a4),d1
	asr.l	#3,d0
	asr.l	#3,d1
	muls	#$139,d0
	muls	#$139,d1
	lsl.l	#3,d0
	lsl.l	#3,d1
	swap	d0
	swap	d1
	ext.l	d0
	ext.l	d1
	move.l	4(a3),d2
	move.l	4(a4),d3
	tst.l	8(a3)
	bpl.s	mt8_l01
	exg	d0,d2
mt8_l01:tst.l	8(a4)
	bpl.s	mt8_l02
	exg	d1,d3
mt8_l02:cmp.l	d2,d0				;end of sample a ?
	blt.s	mt8_l04
	tst.l	12(a3)
	beq.s	mt8_l03
	move.l	12(a3),(a3)			;set loop
	move.l	$10(a3),4(a3)
	bra.s	mt8_l04

mt8_l03:clr.l	(a3)				;clear loop
	clr.l	4(a3)
	clr.l	8(a3)
mt8_l04:cmp.l	d3,d1				;end of sample b ?
	blt.s	mt8_l06
	tst.l	12(a4)
	beq.s	mt8_l05
	move.l	12(a4),(a4)			;set loop
	move.l	$10(a4),4(a4)
	bra.s	mt8_l06

mt8_l05:clr.l	(a4)				;clear loop
	clr.l	4(a4)
	clr.l	8(a4)
mt8_l06:move.l	(a3),a0				;sample/speed => a0/d2
	move.l	8(a3),d2
	move.l	(a4),a1				;sample/speed => a1/d3
	move.l	8(a4),d3
	moveq	#0,d0				;start-offsets 0
	moveq	#0,d1

	mt8_add					;mix 313 sample-bytes
	mt8_add					;it's about 8 rasterlines
	mt8_add					;faster than using a dbf !
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add

	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add

	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add

	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add

	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add

	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add

	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add

	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add

	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add

	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add

	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add

	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add

	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add

	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add

	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add

	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add

	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add

	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add

	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add

	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add

	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add

	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add

	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add

	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add

	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add

	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add

	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add

	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add

	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add

	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add

	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add
	mt8_add

	mt8_add
	mt8_add
	mt8_add

	ext.l	d0
	ext.l	d1
	add.l	d0,a0				;get new sample-address
	add.l	d1,a1
	move.l	a0,(a3)
	move.l	a1,(a4)
	sub.l	d0,4(a3)
	sub.l	d1,4(a4)
	movem.l	(a7)+,d0-d7/a0-a6
	rts

;================================ data ==================================

  dseg

mt8_mdl:
    dc.l	0			;zeiger auf module
mt8_ins:
    ds.l	31,0			;intrument-list
mt8_ctr:
    dc.b	0			;speed-counter
mt8_spd:
    dc.b	6			;speed
mt8_pos:
    dc.w	0			;song-pos
mt8_nte:
    dc.w	0			;note-pos
mt8_chg:
    dc.w	$139			;buffer-change
mt8_evn:
    dc.l	0			;even pattern
mt8_odd:
    dc.l	0			;odd pattern
mt8_smp:
    ds.l	8,0			;now-played samples
mt8_dat:
    ds.l	$38,0			;now-played sample-data

mt8_ch1:
    ds.b	$272,0			;channel mix-buffer
mt8_ch2:
    ds.b	$272,0
mt8_ch3:
    ds.b	$272,0
mt8_ch4:
    ds.b	$272,0

mt8_stp:

  cseg

mt8_data:
    ds.b	128422,0			;module

#endasm



main()
{
  start();     /* Start the Raplayroutine. */
}
