
	incdir	"Includes:"
	include	"misc/DeliPlayer.i"

;
;
	SECTION Player,Code
;
;

	PLAYERHEADER PlayerTagArray

	dc.b '$VER: Digital Sound Studio 1.15 player module V1.1 (14 Aug 92)',0
	even

PlayerTagArray
	dc.l	DTP_PlayerVersion,0
	dc.l	DTP_PlayerName,PName
	dc.l	DTP_Creator,CName
	dc.l	DTP_Check2,Chk
	dc.l	DTP_Interrupt,Int
	dc.l	DTP_InitPlayer,InitPlayer
	dc.l	DTP_EndPlayer,EndPlayer
	dc.l	DTP_InitSound,InitSnd
	dc.l	DTP_EndSound,RemSnd
	dc.l	TAG_DONE

*-----------------------------------------------------------------------*
;
; Player/Creatorname und lokale Daten

PName	dc.b 'DSS',0
CName	dc.b 'CIS, © by GVP 1991,',10
	dc.b 'adapted by Delirium',0
	even

*-----------------------------------------------------------------------*
;
;Interrupt für Replay

Int
	movem.l	d0-d7/a0-a6,-(sp)
	jsr	PlayRoutine 			; DudelDiDum
	movem.l	(sp)+,d0-d7/a0-a6
	rts

*-----------------------------------------------------------------------*
;
; Testet auf Modul

Chk	move.l	dtg_ChkData(a5),a0		; Check DSS Module
	cmpi.l	#"MMU2",(a0)			; Is it DSS at all ?
	bne.s	ChkFail				; No!

	lea	sng_Len(a0),a1			; Yes, the the next question
	move.w	(a1)+,d0			; is: is this just a DSS song
	subq.w	#1,d0				; or really a playable module?
	moveq	#0,d1				; The only difference between
	move.l	d1,d2				; a DSS module and a DSS song
Chk_Loop					; is that the module includes
	move.b	(a1)+,d1			; the samples at the end of the
	cmp.b	d1,d2				; songdata. So we calculate the
	bhi.s	Chk_NotLast			; end of the songdata and check
	move.b	d1,d2				; if it is not the end of the
Chk_NotLast					; loaded file! if so the file
	dbra	d0,Chk_Loop			; includes the samples and is
	addq.w	#1,d2				; playable.
	moveq	#10,d0
	lsl.l	d0,d2				; size * 1024 (blocksize)
	add.l	#sng_Data,d2			; first sample
	lea	sng_Instr0(a0),a1		; first instrument
	moveq	#MAXINSTR,d0
Chk_AdrLoop
	moveq	#0,d1
	move.w	instr_Len(a1),d1		; len
	beq.s	Chk_NextAdr
	add.l	d1,d1
Chk_ThisAdr
	add.l	d1,d2
	moveq	#0,d1
	cmp.w	#1,instr_RLen(a1)		; rlen
	beq.s	Chk_SampleSize
	move.w	instr_RLen(a1),d1
	add.l	d1,d1
Chk_SampleSize
	add.l	d1,d2
	bclr	#0,instr_Start+3(a1)		; align instr_Start on a word
	add.l	instr_Start(a1),d2		; Start
Chk_NextAdr
	lea	SIZEOF_insdt(a1),a1
	dbra	d0,Chk_AdrLoop

	sub.l	dtg_ChkSize(a5),d2		; test size of file
	cmpi.l	#-64,d2				; - 64 Bytes
	blt.s	ChkFail				; too small
	cmpi.l	#+64,d2				; + 64 Bytes
	bgt.s	ChkFail				; too big

	moveq	#0,d0				; Modul erkannt
	bra.s	ChkEnd
ChkFail
	moveq	#-1,d0				; Modul nicht erkannt
ChkEnd
	rts

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

InitPlayer
	moveq	#0,d0
	move.l	dtg_GetListData(a5),a0		; Function
	jsr	(a0)
	move.l	a0,SongPointer

	move.l	dtg_AudioAlloc(a5),a0		; Function
	jsr	(a0)				; returncode is already set !
	rts

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

EndPlayer
	move.l	dtg_AudioFree(a5),a0		; Function
	jsr	(a0)
	rts

*-----------------------------------------------------------------------*
;
; Init Sound

InitSnd
	jsr	InitSampleAdr
	jsr	InitSamples
	jsr	EnablePlayer

	clr.w	PlayOn			; additional cleanup
	clr.w	PlayTimer
	clr.w	CurrentPos
	clr.l	OffsetBlock
	clr.w	AudioDMA
	clr.w	MasterVolume
	clr.w	BreakStatus
	clr.w	NewPosJump
	rts

*-----------------------------------------------------------------------*
;
; Rem Sound

RemSnd
	jsr	DisablePlayer
	rts

*-----------------------------------------------------------------------*
;
;**************************************************************************
;*
;*   DSS MODULE PLAY ROUTINE
;*   -----------------------
;*
;*   If you wish to use some DSS Tracker Modules into your own programs,
;*   you can read the following listing...
;*
;*   This file contains the needed functions for playing a DSS Module.
;*   You have to allocate, to load  and to free the memory (CHIP) yourself.
;*
;*  >Once the Module is loaded in CHIP memory:
;*
;*   -Set the [ SongPointer ] pointer (at the end of this file) with the
;*    Module's address.
;*   -Call the [ InitPlay() ] function.
;*
;*  >To stop the Module, you just have to call the [ RemovePlayer() ]
;*   function.
;*
;*   This program has been writen for the Aztec C 3.6 assembler.
;*   It can be easily adapted to another assembler.
;*
;**************************************************************************

;----- Amiga function ------

_LVOOpenResource        EQU        -498
_LVOAddICRVector        EQU        -6
_LVORemICRVector        EQU        -12

;------- ExecBase ----

SysBase                 EQU     4
PAL                     EQU     50
eb_PowerSupplyFreq      EQU     531

;------- CIAA --------

CIAAPRA         EQU     $bfe001
CIABTALO        EQU     $bfd400
CIABTAHI        EQU     $bfd500
CIABICR         EQU     $bfdd00
CIABCRA         EQU     $bfde00

CIABTBLO        EQU     $bfd600
CIABTBHI        EQU     $bfd700
CIABCRB         EQU     $bfdf00

;------ Song ----------

sng_Tempo       EQU     8
sng_Instr0      EQU     10
sng_Len         EQU     1436
sng_Seq         EQU     1438
sng_Data        EQU     1566

;------ InstrData -----

MAXINSTR        EQU     30
SIZEOF_insdt    EQU     46

instr_Name      EQU     0
instr_Start     EQU     30
instr_Len       EQU     34
instr_RStart    EQU     36
instr_RLen      EQU     40
instr_Vol       EQU     42
instr_Freq      EQU     44

;------- AudioData -

SIZEOF_ad       EQU     24

ad_SampPer      EQU     0
ad_Effet        EQU     2
ad_Info         EQU     3
ad_Volume       EQU     4
ad_SmpAdr       EQU     6
ad_SmpLen       EQU     10
ad_RepAdr       EQU     12
ad_RepLen       EQU     16
ad_ArpPer       EQU     18
ad_DMABit       EQU     20
ad_PitchPer     EQU     22

;------- AudioChips -------

DMACON          EQU     $dff096
DMASET          EQU     $8000

AUD0LCH         EQU     $dff0a0
AUD1LCH         EQU     $dff0b0
AUD2LCH         EQU     $dff0c0
AUD3LCH         EQU     $dff0d0
AUDxLEN         EQU     $4
AUDxPER         EQU     $6
AUDxVOL         EQU     $8
AUDxDAT         EQU     $a
SIZEOF_AUD      EQU     $10

;------ Block ---------

NEXTTRACK       EQU     4
NEXTLINE        EQU     16
BLOCKSIZE       EQU     1024
MAXTRACK        EQU     4

;------- Notes -------

DO2             EQU     1712
SI5             EQU     113
STOP            EQU     $7ff

;------- Effects -----

MASK_EFF        EQU     7
MASK_VAL        EQU     $f

ARPEGGIO        EQU     0
PITCHUP         EQU     1
PITCHDOWN       EQU     2
VOLUME          EQU     3
MASTERVOL       EQU     4
TEMPO           EQU     5
JUMP            EQU     6
FILTER          EQU     7

MAX_VOL         EQU     64
BREAK           EQU     $ff


        CSEG

;------------------ functions to call -----------------

; Timer interruption installation and Player initialization routines
; Return 0 (zero) if successful.
; Return 1 if the installation is not possible.

;InitPlay:
;        movem.l d1-d2/a0-a3/a6,-(sp)
;        move.l  SysBase,a6
;        lea     CiabName,a1
;        moveq   #0,d0
;        jsr     _LVOOpenResource(a6)
;        move.l  d0,CiabBase
;        beq.s   InitPlayError
;        cmp.b   #PAL,eb_PowerSupplyFreq(a6)
;        beq.s   initsong
;        move.w  #2,IsNTSC
;initsong:
;        bsr.s   InitSampleAdr
;        bsr.s   InitSamples
;        bsr.s   InitInterrupt
;        tst.l   d0
;        beq.s   EndInitPlay
;InitPlayError:
;        moveq   #1,d0
;EndInitPlay:
;        movem.l (sp)+,d1-d2/a0-a3/a6
;        rts

; Stop to play the module

;RemovePlayer:
;        movem.l d0-d1/a0-a1/a6,-(sp)
;        bsr.s   DisablePlayer
;        move.l  CiabBase,a6
;        lea     TimerInt,a1
;        moveq   #1,d0
;        jsr     _LVORemICRVector(a6)
;        bclr    #1,CIAAPRA
;        movem.l (sp)+,d0-d1/a0-a1/a6
;        rts

;-------------- internal functions -----------------

;InitInterrupt:
;        bsr.s   EnablePlayer
;        move.l  CiabBase,a6
;        lea     TimerInt,a1
;        moveq   #1,d0
;        jsr     _LVOAddICRVector(a6)
;        tst.l   d0
;        bne.s   InitInterruptEnd
;        move.b  CIABCRB,d0
;        and.b   #%10000000,d0
;        or.b    #1,d0
;        move.b  d0,CIABCRB
;        move.b  #$82,CIABICR
;        lea     TimerTable,a0
;        move.w  IsNTSC,d0
;        move.b  1(a0,d0),CIABTBLO
;        move.b  (a0,d0),CIABTBHI
;        moveq   #0,d0
;InitInterruptEnd:
;        rts

InitSampleAdr:
        move.l  SongPointer,a1
        lea     sng_Len(a1),a0
        move.w  (a0)+,d0                ; d0 = songlen
        subq.w  #1,d0
        moveq   #0,d1
        move.l  d1,d2
SeekLastBlockLoop:
        move.b  (a0)+,d2
        cmp.b   d2,d1
        bhi.s   NotLastBlock
        move.b  d2,d1
NotLastBlock:
        dbra    d0,SeekLastBlockLoop
        addq.w  #1,d1
        moveq   #10,d0
        lsl.l   d0,d1                   ; d1 = block size
        lea     sng_Data(a1),a0
        add.l   d1,a0                   ; a0 -> first sample
        lea     sng_Instr0(a1),a2       ; a2 -> first instrument
        lea     SampleAdrTable,a3
        moveq   #MAXINSTR,d0
InitAdrLoop:
	clr.l	(a3)			; clear pointer to prevent from illegal clear
        moveq   #0,d1
        move.w  instr_Len(a2),d1        ; len ?
        beq.s   InitNextAdr
InitThisAdr:
        move.l  a0,(a3)
        moveq   #0,d2
        cmp.w   #1,instr_RLen(a2)       ; rlen
        beq.s   GetSampleSize
        move.w  instr_RLen(a2),d2
        add.l   d2,d1
GetSampleSize:
        add.l   d1,d1
        bclr    #0,instr_Start+3(a2)    ; align instr_Start on a word
        add.l   instr_Start(a2),d1      ; Start
        add.l   d1,a0                   ; a0 -> nextsample
InitNextAdr:
        addq.l  #4,a3
        add.l   #SIZEOF_insdt,a2
        dbra    d0,InitAdrLoop
        rts

InitSamples:
        lea     SampleAdrTable,a0
        moveq   #MAXINSTR,d0
InitSamplesLoop:
        move.l  (a0)+,d1
        beq.s   InitSamplesLoopEnd
        move.l  d1,a1
        moveq   #3,d2
Clear4Bytes:
        clr.b   (a1)+
        dbra    d2,Clear4Bytes
InitSamplesLoopEnd:
        dbra    d0,InitSamplesLoop
        rts


DisablePlayer:
        clr.w   AUD0LCH+AUDxVOL
        clr.w   AUD1LCH+AUDxVOL
        clr.w   AUD2LCH+AUDxVOL
        clr.w   AUD3LCH+AUDxVOL
        move.w  #$0f,DMACON
        rts

EnablePlayer:
        clr.w   AUD0LCH+AUDxVOL
        clr.w   AUD1LCH+AUDxVOL
        clr.w   AUD2LCH+AUDxVOL
        clr.w   AUD3LCH+AUDxVOL
        rts

TimerIntRoutine:
        movem.l d1-d7/a0-a6,-(sp)
        bsr.s   PlayRoutine
        movem.l (sp)+,d1-d7/a0-a6
        moveq   #0,d0
        rts

PlayRoutine:
        move.l  SongPointer,a6
        move.w  8(a6),d0
        addq.w  #1,PlayTimer
        cmp.w   PlayTimer,d0            ; tempo == playtimer ?
        bne.s   PlayEffects             ; no, play effects
        clr.w   PlayTimer               ; yes, reset timer to zero
        bra     PlaySound               ; play note

PlayEffects:
        lea     ChannelData0,a0
        lea     AUD0LCH,a1
        moveq   #MAXTRACK-1,d3          ; 4 tracks
PlayEffLoop:
        move.w  (a0),d0
        and.w   #$7ff,d0
        cmp.w   #STOP,d0                ; note == STOP ?
        beq.s   PlayEffLoopEnd
        tst.b   ad_Info(a0)             ; effect value == 0 ?
        beq.s   PlayEffLoopEnd
        bsr.s   MakeEffects
PlayEffLoopEnd:
        add.l   #SIZEOF_ad,a0           ; a0 -> next channeldata
        add.w   #SIZEOF_AUD,a1          ; a1 -> next audio register
        dbra    d3,PlayEffLoop
        rts

MakeEffects:
        move.b  ad_Effet(a0),d0
        beq.s   EffArpeggio
        cmp.b   #PITCHUP,d0
        beq.s   EffPitchUp
        cmp.b   #PITCHDOWN,d0
        beq.s   EffPitchDown
        rts

EffArpeggio:
        moveq   #0,d0
        move.w  PlayTimer,d0
        cmp.w   #1,d0
        beq.s   EffArpOne
        cmp.w   #2,d0
        beq.s   EffArpTwo
        cmp.w   #3,d0
        beq.s   EffArpThree
        cmp.w   #4,d0
        beq.s   EffArpTwo
        cmp.w   #5,d0
        beq.s   EffArpOne
        rts

EffArpOne:
        move.b  ad_Info(a0),d0
        lsr.b   #4,d0                   ; d0 = high nibble value
        bra.s   EffArpSeek
EffArpTwo:
        move.b  ad_Info(a0),d0
        and.b   #MASK_VAL,d0            ; d0 = low nibble value
        bra.s   EffArpSeek
EffArpThree:
        move.w  ad_ArpPer(a0),d2        ; d2 = normal period
        bra.s   EffArpFound
EffArpSeek:
        add.w   d0,d0                   ; d0 = offset notetable
        move.w  ad_ArpPer(a0),d1        ; d1 = normal period
        lea     NoteTable,a2
EffArpLoop:
        move.w  (a2,d0.w),d2            ; d2 = new period
        cmp.w   (a2)+,d1                ; (a2) == normal period
        bne.s   EffArpLoop
EffArpFound:
        move.w  d2,AUDxPER(a1)
        rts

EffPitchUp:
        moveq   #0,d0
        move.b  ad_Info(a0),d0          ; d0 = effect value
        sub.w   d0,ad_PitchPer(a0)
        cmp.w   #SI5,ad_PitchPer(a0)    ; less than lowest period ?
        bpl.s   EffPitchOK
        move.w  #SI5,ad_PitchPer(a0)
        bra.s   EffPitchOK
EffPitchDown:
        moveq   #0,d0
        move.b  ad_Info(a0),d0
        add.w   d0,ad_PitchPer(a0)
        cmp.w   #DO2,ad_PitchPer(a0)    ; more than highest period ?
        bmi.s   EffPitchOK
        move.w  #DO2,ad_PitchPer(a0)
EffPitchOK:
        move.w  ad_PitchPer(a0),AUDxPER(a1)
        rts

PlaySound:
        lea     sng_Data(a6),a0
        lea     sng_Seq(a6),a1
        move.w  CurrentPos,d0
        move.w  d0,NewPosJump
        moveq   #0,d1
        move.b  0(a1,d0.w),d1           ; d1 = block number
        moveq   #10,d0
        lsl.l   d0,d1
        add.l   OffsetBlock,d1          ; d1 = offset into block data
        clr.w   AudioDMA

        lea     AUD0LCH,a3
        lea     ChannelData0,a4
        moveq   #MAXTRACK-1,d7          ; 4 tracks
PlayLoop:
        bsr     PlayInstr
        add.w   #SIZEOF_AUD,a3
        add.l   #SIZEOF_ad,a4
        dbra    d7,PlayLoop

        move.w  AudioDMA,d0             ; start audio DMA
        or.w    #DMASET,d0
        move.w  d0,DMACON

	bsr	DMAwait			; !!!

;        move.b  CIABCRA,d1              ; buh : busy waiting with cia timer !!!
;        move.b  d1,d0
;        and.b   #%11000000,d0
;        or.b    #%00001000,d0
;        move.b  d0,CIABCRA
;        move.b  #$2f,CIABTALO
;        move.b  #1,CIABTAHI
;PlayDelay1:
;        btst.b  #0,CIABCRA
;        bne.s   PlayDelay1
;        move.b  d1,CIABCRA
;        move.b  #%00000001,CIABICR

        lea     ChannelData0,a0         ; set new value into audio registers
        lea     AUD0LCH,a1
        moveq   #MAXTRACK-1,d0
SetNewValue:
        move.l  ad_RepAdr(a0),(a1)
        move.w  ad_RepLen(a0),AUDxLEN(a1)
        add.l   #SIZEOF_ad,a0
        add.w   #SIZEOF_AUD,a1
        dbra    d0,SetNewValue
        cmp.l   #BLOCKSIZE-NEXTLINE,OffsetBlock  ; end of block ?
        beq.s   ChangePosition
        add.l   #NEXTLINE,OffsetBlock   ; modif. offsetblock
        tst.w   BreakStatus             ; jump or break ?
        beq.s   PlaySoundEnd
        clr.w   BreakStatus
ChangePosition:
        clr.l   OffsetBlock             ; offset block = 0
        move.w  NewPosJump,CurrentPos
        addq.w  #1,CurrentPos           ; new position
        move.w  sng_Len(a6),d0
        move.w  CurrentPos,d1
        cmp.w   d0,d1                   ; end of song ?
        bne.s   PlaySoundEnd
        clr.w   CurrentPos              ; position = 0
PlaySoundEnd:
        rts

PlayInstr:
        lea     sng_Instr0(a6),a2
        move.l  (a0,d1.l),ad_SampPer(a4)
        addq.l  #NEXTTRACK,d1
        moveq   #0,d0
        move.b  ad_SampPer(a4),d0
        lsr.b   #3,d0                   ; d0 = instrument number
        tst.b   d0                      ; d0 == 0 ?
        beq.s   NoSampleChange

        lea     SampleAdrTable,a5
        subq.b  #1,d0
        move.l  d0,d3
        lsl.w   #2,d0                   ; d0 = SampleAdrTable offset
        mulu    #SIZEOF_insdt,d3
        add.l   #instr_Start,d3
        add.l   d3,a2                   ; a2 -> Start InstrData
        move.l  (a5,d0.w),d4
        add.l   (a2)+,d4                ; Start
        move.l  d4,ad_SmpAdr(a4)
        beq.s   NoSampleChange
        move.w  (a2)+,ad_SmpLen(a4)     ; Len
        move.l  (a2)+,d5                ; RStart
        move.w  (a2)+,d2                ; RLen
        bne.s   SetRepeat
        moveq   #1,d2
        moveq   #0,d5
SetRepeat:
        move.w  d2,ad_RepLen(a4)
        add.l   ad_SmpAdr(a4),d5
        move.l  d5,ad_RepAdr(a4)
        move.w  (a2),ad_Volume(a4)      ; Volume
NoSampleChange:
        move.w  ad_SampPer(a4),d6
        and.w   #$7ff,d6                ; note == 0 ?
        beq.s   TestEffects
        move.w  d6,ad_ArpPer(a4)
        move.w  ad_DMABit(a4),d0
        move.w  d0,DMACON               ; cut DMA audio for this track

	bsr	DMAwait			; !!!

;        move.b  CIABCRA,d2              ; wait loop
;        move.b  d2,d3
;        and.b   #%11000000,d3
;        or.b    #%00001000,d3
;        move.b  d3,CIABCRA
;        move.b  #$2f,CIABTALO
;        move.b  #1,CIABTAHI
;PlayDelay2:
;        btst.b  #0,CIABCRA
;        bne.s   PlayDelay2
;        move.b  d2,CIABCRA
;        move.b  #%00000001,CIABICR

        cmp.w   #STOP,d6                ; note == 'OFF' ?
        bne.s   SetPlayRegs
        clr.w   AUDxVOL(a3)             ; set audio volume to 0
        or.w    d0,AudioDMA
        rts

DMAwait:moveq	#4,d3
DMAwai2:move.b	$dff006,d2
DMAwai3:cmp.b	$dff006,d2
	beq.s	DMAwai3
	dbf	d3,DMAwai2
	rts

SetPlayRegs:
        move.l  ad_SmpAdr(a4),(a3)      ; sample address == NULL ?
        beq.s   TestEffects
        move.w  ad_SmpLen(a4),AUDxLEN(a3)
        move.w  d6,AUDxPER(a3)
        or.w    d0,AudioDMA
        move.w  d6,ad_PitchPer(a4)
TestEffects:
        move.b  ad_Effet(a4),d0         ; d0 = effect
        bsr.s   EffVolume
        tst.b   d0
        beq.s   TestEffectsEnd
;        cmp.b   #FILTER,d0
;        beq.s   EffFilter
        cmp.b   #MASTERVOL,d0
        beq.s   EffMaster
        cmp.b   #TEMPO,d0
        beq.s   EffSpeed
        cmp.b   #JUMP,d0
        beq.s   EffJump
TestEffectsEnd:
        rts

EffVolume:                              ; modify volume
        cmp.w   #VOLUME,d0
        bne.s   UseInstrVol
        moveq   #0,d2
        move.b  ad_Info(a4),d2          ; d0 = new volume
        bra.s   SetInstrVol
UseInstrVol:
        tst.w   d6
        beq.s   EffVolumeEnd
        move.w  ad_Volume(a4),d2
SetInstrVol:
        sub.w   MasterVolume,d2         ; new volume - master >= 0
        bge.s   SetVolumeReg
        moveq   #0,d2                   ; new volume = 0
SetVolumeReg:
        move.w  d2,AUDxVOL(a3)          ; new volume into audio reg
EffVolumeEnd:
        rts

EffMaster:                              ; modify master volume
        moveq   #MAX_VOL,d2
        move.b  ad_Info(a4),d0
        sub.b   d0,d2
        blt.s   EffMasterEnd
        move.b  d2,MasterVolume+1
EffMasterEnd:
        rts

EffSpeed:                               ; modify tempo
        move.b  ad_Info(a4),d0
        beq.s   EffSpeedEnd
        clr.w   PlayTimer
        move.b  d0,sng_Tempo+1(a6)
EffSpeedEnd:
        rts

EffJump:                                ; jump or break
        move.w  #1,BreakStatus
        move.b  ad_Info(a4),d0
        cmp.b   #BREAK,d0
        beq.s   EffBreak
        subq.b  #2,d0
        ext.w   d0
        move.w  d0,NewPosJump
        rts
EffBreak:
        move.w  CurrentPos,NewPosJump
        rts

;EffFilter:                              ; filter on/off
;        move.b  ad_Info(a4),d0
;        bne.s   SetFilter
;        bset    #1,CIAAPRA
;        rts
;SetFilter:
;        bclr    #1,CIAAPRA
;        rts

        DSEG

;CiabBase:       dc.l    0
;IsNTSC:         dc.w    0

;CiabName:       dc.b    'ciab.resource',0
;TimerIntName:   dc.b    'DSS Tracker Player',0
;                cnop    0,2

;TimerInt:
;        dc.l  0                 ; Interrupt.is_Node.ln_Succ
;        dc.l  0                 ; Interrupt.is_Node.ln_Pred
;        dc.b  2                 ; Interrupt.is_Node.ln_Type = NT_INTERRUPT
;        dc.b  -10               ; Interrupt.is_Node.ln_Pri
;        dc.l  TimerIntName      ; Interrupt.is_Node.ln_Name
;        dc.l  0                 ; Interrupt.is_Data
;        dc.l  TimerIntRoutine   ; Interrupt.is_Code


PlayOn:         dc.w    0
PlayTimer:      dc.w    0
CurrentPos:     dc.w    0
OffsetBlock:    dc.l    0
AudioDMA:       dc.w    0
MasterVolume:   dc.w    0
BreakStatus:    dc.w    0
NewPosJump:     dc.w    0

ChannelData0:
        dc.w    0               ; Period                0
        dc.w    0               ; Sample+Info           2
        dc.w    0               ; Volume                4
        dc.l    0               ; Sample address        6
        dc.w    0               ; Sample length        10
        dc.l    0               ; Repeat address       12
        dc.w    0               ; Repeat length        16
        dc.w    0               ; Shazam period        18
        dc.w    1               ; DMA bit              20
        dc.w    0               ; Pitch  period        22
ChannelData1:
        ds.w    10
        dc.w    2
        dc.w    0
ChannelData2:
        ds.w    10
        dc.w    4
        dc.w    0
ChannelData3:
        ds.w    10
        dc.w    8
        dc.w    0

        dc.w    1712
NoteTable:
        dc.w    1712,1616,1524,1440,1356,1280,1208,1140,1076,1016,960,906
        dc.w    856,808,762,720,678,640,604,570,538,508,480,453
        dc.w    428,404,381,360,339,320,302,285,269,254,240,226
        dc.w    214,202,190,180,170,160,151,143,135,127,120,113
        dc.w    113,113,113,113,113,113,113,113,113,113,113,113
        dc.w    113,113,113,113,113,113,113,113,113,113,113,113
        dc.w    113,113,113,113,113,113

SampleAdrTable: ds.l    31

;TimerTable:     dc.w    14187,14318

SongPointer:    dc.l    0               ; address of Module in CHIP memory

