; --------------------------------------------- ; ; DELTA MUSIC REPLAY-ROUTINE V1.0 (PACKED) ; ; --------------------------------------------- ; ; ; ; CODED BY : BENT "SHOGUN" NIELSEN ; ; KYRADSERVEJ 19 B ; ; 8700 HORSENS ; ; DENMARK ; ; TEL. +45 75-601-868 ; ; ; ; --------------------------------------------- ; ; COPYRIGHT 1991, BARRICADE SOFTWARE tm ; ; --------------------------------------------- ; ; ; ; This routine has been optimized a lot, but ; ; I know it can be faster than this .... ; ; ; ; All the text on the right side of the ; ; source, is made to help those who want to ; ; optimize it a little bit more, so please ; ; don't remove it !!!! ; ; ; ; By the way, it is 100% PC-relative, so you ; ; can place it wherever you like ..... ; ; ; ; --------------------------------------------- ; ; ; ; HOW TO USE IT: ; ; ~~~~~~~~~~~~~~ ; ; ; ; It's quite easy to use. You call INIT_MUSIC ; ; once, and then you call REPLAY_MUSIC every ; ; vertical blanking ..... ; ; ; ; Remember to load a packed module into the ; ; label call MODULE ..... ; ; ; ; --------------------------------------------- ; org $40000 load $40000 >extern "DH1:ShogunMix",Module ; load module "ShogunMix" ; to the module label J: tst.l module ; test if module has been loaded beq.s exit ; if not exit move.l $4,A6 ; forbid multi-tasking jsr -132(A6) bsr Init_Music ; init music Loop: cmp.b #199,$dff006 ; wait for rasterline 199 bne.s Loop move.w #$ff0,$dff180 ; set a color bsr Replay_Music ; play music move.w #$008,$dff180 ; reset color btst #6,$bfe001 ; test for left-mouse bne.s Loop move.w #$000f,$dff096 ; stop audio dma move.l $4,A6 ; permit multi-tasking jsr -138(A6) Exit: rts ; exit !!!!! ; --------------------------------------------- ; ; init music ; ; --------------------------------------------- ; Init_Music: movem.l D0-D7/A0-A6,-(A7) ; save all registers lea Module(PC),A0 ; get module pointer lea Song_Data(PC),A1 ; get song data list move.l (A0)+,62(A1) ; save track1 repeat & length move.l (A0)+,66(A1) ; save track2 repeat & length move.l (A0)+,70(A1) ; save track3 repeat & length move.l (A0)+,74(A1) ; save track4 repeat & length move.l A0,10(A1) ; save track1 pointer add.w 64(A1),A0 ; add track1 length move.l A0,14(A1) ; save track2 pointer add.w 68(A1),A0 ; add track2 length move.l A0,18(A1) ; save track3 pointer add.w 72(A1),A0 ; add track3 length move.l A0,22(A1) ; save track4 pointer add.w 76(A1),A0 ; add track4 length move.w (A0)+,D0 ; get arpeggio length move.l A0,58(A1) ; save arpeggio pointer add.w d0,A0 ; add arpeggio length move.w (A0)+,D0 ; get sound offset length move.l A0,6(A1) ; save sound offsets pointer add.w D0,A0 ; add sound offset length move.l A0,2(A1) ; save sound pointer move.w -2(A0),D0 ; get highest sound offset add.l #88,D0 ; add one instrument add.w D0,A0 ; add highest sound offset move.w (A0)+,D0 ; get waveform offset length move.l A0,78(A1) ; save waveform offset pointer add.w D0,A0 ; add waveform offset length move.w (A0)+,D0 ; waveform length move.l A0,82(A1) ; save waveform pointer add.w D0,A0 ; add waveform length move.l (A0)+,D0 ; get block length move.l A0,26(A1) ; save block pointer add.l D0,A0 ; add block length move.l A0,38(A1) ; save sample offset pointer add.w #32,A0 ; add sample offset length move.l A0,34(A1) ; save sample pointer ;;;;;;; NORMAL SETTINGS clr.b 30(A1) ; stop random noise move.l 78(A1),A0 ; get sound offset pointer move.w 2(A0),D0 ; get offset number 1 sub.w (A0),D0 ; sub offset number 0 cmp.w #$40,D0 ; test for noise on/off bmi.s Init_Con ; if minus, no move.b #1,30(A1) ; start random noise Init_Con: clr.b 48(A1) ; clear playspeed counter bset #1,$bfe001 lea Null_Waveform(PC),A0 ; get null waveform lea $dff000,A2 ; get custom move.w #$000f,$96(A2) ; stop audio dma move.w #$0780,$9a(A2) ; stop audio irq move.l A0,$a0(A2) ; set hardware addresses move.l A0,$b0(A2) move.l A0,$c0(A2) move.l A0,$d0(A2) move.w #4,$a4(A2) ; set hardware sample length move.w #4,$b4(A2) move.w #4,$c4(A2) move.w #4,$d4(A2) move.w #0,$a6(A2) ; set hardware periods move.w #0,$b6(A2) move.w #0,$c6(A2) move.w #0,$d6(A2) move.w #0,$a8(A2) ; set hardware volume move.w #0,$b8(A2) move.w #0,$c8(A2) move.w #0,$d8(A2) lea Null_Sound(PC),A2 ; get null sound lea Voice1(PC),A0 ; get voice1 move.l 10(A1),10(A0) ; set voice1 track pointer move.l 62(A1),54(A0) ; set track1 repeat & length bsr.w Init_Voice ; init voice lea Voice2(PC),A0 ; get voice2 move.l 14(A1),10(A0) ; set voice2 track pointer move.l 66(A1),54(A0) ; set track2 repeat & length bsr.s Init_Voice ; init voice lea Voice3(PC),A0 ; get voice3 move.l 18(A1),10(A0) ; set voice3 track pointer move.l 70(A1),54(A0) ; set track3 repeat & length bsr.s Init_Voice ; init voice lea Voice4(PC),A0 ; get voice4 move.l 22(A1),10(A0) ; set voice4 track pointer move.l 74(A1),54(A0) ; set track4 repeat & length bsr.s Init_Voice ; init voice movem.l (A7)+,D0-D7/A0-A6 ; restore all registers rts Init_Voice: clr.l 18(A0) ; clear track & block counter move.l A2,6(A0) ; set null sound clr.b 51(A0) ; clear sound technique clr.w 48(A0) ; clear arpeggio counter move.l 58(A1),44(A0) ; set arpeggio pointer clr.l 32(A0) ; clear volume counter & volume clr.w 36(A0) ; clear volume sustain & portamento clr.w 30(A0) ; clear bendrate move.b #$3f,29(A0) ; set channel volume rts Replay_Music: movem.l D0-D7/A0-A6,-(A7) ; save all registers lea Song_Data(PC),A6 ; get song data pointer clr.b 1(A6) ; disable hardware dma ; --------------------------------------------- ; ; random noise calculator ; ; --------------------------------------------- ; tst.b 30(A6) ; test noise on/off beq.s No_Noise ; if zero, no noise move.l 82(A6),A3 ; get random noise waveform move.l 42(A6),D1 ; get random noise value moveq #16-1,D0 Noise_Loop: rol.l #7,D1 add.l #$6eca756d,D1 eor.l #$9e59a92b,D1 move.l D1,(A3)+ dbf D0,Noise_Loop move.l D1,42(A6) ; save random noise value No_Noise: subq.b #1,48(A6) ; decrease playspeed counter bpl.s Playspeed_Ok ; if plus, continue move.b 47(A6),48(A6) ; reset playspeed Playspeed_Ok: lea Voice1(PC),A0 ; get voice1 bsr.l Play_Voice ; play voice lea Voice2(PC),A0 ; get voice2 bsr.l Play_Voice ; play voice lea Voice3(PC),A0 ; get voice3 bsr.l Play_Voice ; play voice lea Voice4(PC),A0 ; get voice4 bsr.l Play_Voice ; play voice move.w 0(A6),$dff096 ; enable hardware dma movem.l (A7)+,d0-d7/a0-a6 ; restore all registers rts ; return .... Play_Voice: move.l 0(A0),A1 ; get hardware pointer move.l 6(A0),A2 ; get sound pointer ; --------------------------------------------- ; ; sample handler ; ; --------------------------------------------- ; tst.b 51(A0) ; test sound technique bpl.s Track_Handler ; if plus, skip clr.b 51(A0) ; clear sound technique move.l 38(A6),A3 ; get samples offset move.b 39(A2),D0 ; get sample number and.w #7,D0 ; max. 8 samples add.w D0,D0 ; mulu with 4 add.w D0,D0 add.w D0,A3 ; add sample number move.l (A3),A4 ; get sample offset add.l 34(A6),A4 ; add sample pointer moveq #0,D0 move.w 4(A2),4(A1) ; set sample repeat length move.w 2(A2),D0 ; get sample repeat clr.w (A4) ; clear first word of sample add.w D0,A4 ; add sample repeat move.l A4,0(A1) ; set hardware address ; --------------------------------------------- ; ; track handler ; ; --------------------------------------------- ; Track_Handler tst.b 48(A6) ; test playspeed counter bne.l Sound_Handler tst.w 20(A0) ; test block counter bne.s Block_Handler ; if not zero, skip moveq #0,D0 ; clear d0 move.l 10(A0),A3 ; get track pointer move.w 18(A0),D1 ; get track counter move.b 0(A3,D1.W),D0 ; get block number move.b 1(A3,D1.W),43(A0) ; set transpose asl.l #6,D0 ; mulu with 64 add.l 26(A6),D0 ; add block pointer move.l D0,14(A0) ; set block pointer addq.w #2,D1 ; add one track step move.w D1,18(A0) ; set track counter cmp.w 56(A0),D1 ; compare track length & track counter bmi.s Block_Handler ; if minus, skip move.w 54(A0),18(A0) ; reset track counter ; --------------------------------------------- ; ; block handler ; ; --------------------------------------------- ; Block_Handler: move.l 14(A0),A3 ; get block pointer add.w 20(A0),A3 ; add track counter moveq #0,D0 ; clear d0 move.b (A3),D0 ; get note beq.l Block_FX ; if zero, try fx move.w 4(A0),$dff096 ; stop audio dma move.b D0,28(A0) ; save frequency number lea frequency_table(pc),A4 add.b 43(A0),D0 ; add transpose add.w D0,D0 ; mulu with 2 move.w 0(A4,D0.W),26(A0) ; set frequency compare moveq #0,D1 ; clear d1 move.b 1(A3),D1 ; get sound number subq.w #1,D1 ; sub an instrument add.w D1,D1 ; mulu with 2 move.l 6(A6),A4 ; get sound offset pointer add.w D1,A4 ; calculate actual offset move.l 2(A6),A2 ; get sound pointer add.w (A4),A2 ; add sound offset move.l A2,6(A0) ; save new sound pointer move.b 38(A2),51(A0) ; set sound technique bpl.s Block_Con ; if plus, synthetic move.l 38(A6),A4 ; get sample offset pointer move.b 39(A2),D0 ; get sample number and.w #7,D0 ; max. 8 samples add.w D0,D0 ; mulu with 4 add.w D0,D0 add.w D0,A4 ; add sample number move.l (A4),A4 ; get sample offset add.l 34(A6),A4 ; add sample pointer move.l A4,0(A1) ; set hardware address move.w 0(A2),4(A1) ; set hardware length Block_Con: clr.w 22(A0) ; clear synthetic delay & counter clr.l 32(A0) ; clear volume counter & volume clr.b 36(A0) ; clear volume sustain clr.w 48(A0) ; clear arpeggio counter clr.l 38(A0) ; clear vibrato wait, status & value move.b 22(A2),42(A0) ; reset vibrato counter clr.b 52(A0) ; clear vibrato counter 2 move.b 23(A2),53(A0) ; reset vibrato sustain Block_FX: move.b 2(A3),D0 ; get effect byte subq.b #1,D0 ; decrease effect bmi.s Increase_Block ; if minus, no effect move.b 3(A3),D1 ; get effect data and.w #7,D0 ; max. 8 effects add.w D0,D0 ; mulu with 4 add.w D0,D0 jmp Effect_Table(PC,D0.W) Effect_Table: bra.l Effect01 bra.l Effect02 bra.l Effect03 bra.l Effect04 bra.l Effect05 bra.l Effect06 bra.l Effect07 bra.l Effect08 Increase_Block: addq.w #4,20(A0) ; increase block counter and.w #$3f,20(A0) ; mask block counter ; --------------------------------------------- ; ; sound handler ; ; --------------------------------------------- ; Sound_Handler: tst.b 38(A2) ; test sound technique bmi.s Vibrato_Handler ; if minus, skip tst.b 22(A0) ; test synthetic delay beq.s Do_Sound ; if zero, do sound subq.b #1,22(A0) ; decrease synthetic delay bra.s Vibrato_Handler ; done ... Do_Sound: move.b 39(A2),22(A0) ; reset synthetic delay moveq #0,D0 ; clear d0 moveq #0,D2 ; clear d2 lea 40(A2),A3 ; get waveform table move.b 23(A0),D0 ; get synthetic counter addq.b #1,23(A0) ; increase synthetic counter move.b (A3,D0.W),D2 ; get waveform number cmp.b #$ff,D2 ; test for 'end of table' bne.s Sound_Con ; if not, skip move.b 1(A3,D0.W),D0 ; get loop point move.b D0,23(A0) ; reset synthetic counter move.b (A3,D0.W),D2 ; get new waveform number cmp.b #$ff,D2 ; test if still 'end of table' bne.s Sound_Con ; if not, reset bra.s Vibrato_Handler ; done ... Sound_Con: add.w d2,d2 ; mulu with 2 add.l 78(A6),D2 ; add waveform offset pointer move.l D2,A3 ; d2 to a3 move.w (A3),D2 ; get waveform offset move.l 82(A6),A3 ; get waveform pointer add.w D2,A3 ; add waveform offset move.l A3,0(A1) ; set hardware address move.w 0(A2),4(A1) ; set hardware length ; --------------------------------------------- ; ; vibrato handler ; ; --------------------------------------------- ; Vibrato_Handler: moveq #0,D0 ; clear d0 lea 21(A2),A3 ; get vibrato table move.b 52(A0),D0 ; get vibrato counter 2 add.w D0,A3 ; add vibrato counter 2 move.b 0(A3),D0 ; get vibrato step tst.b 39(A0) ; test vibrato status bne.s Vibrato_Minus add.w D0,40(A0) ; increase vibrato value bra.s Vibrato_Dec ; jump Vibrato_Minus: sub.w D0,40(A0) ; decrease vibrato value Vibrato_Dec: subq.b #1,42(A0) ; decrease vibrato counter bne.s Vibrato_Con ; if not zero, skip move.b 1(A3),42(A0) ; reset vibrato counter not.b 39(A0) ; reverse vibrato status Vibrato_Con: tst.b 53(A0) ; test vibrato sustain beq.s Vibrato_Con2 ; if zero, skip subq.b #1,53(A0) ; decrease vibrato sustain bra.s Volume_Handler ; done ... Vibrato_Con2: addq.b #3,52(A0) ; increase vibrato counter 2 cmp.b #15,52(A0) ; test vibrato counter 2 bne.s Vibrato_Con3 move.b #12,52(A0) ; reset vibrato counter 2 Vibrato_Con3: move.b 5(A3),53(A0) ; reset vibrato sustain ; --------------------------------------------- ; ; volume handler ; ; --------------------------------------------- ; Volume_Handler: tst.b 36(A0) ; test volume sustain beq.s Do_Volume ; if zero, do volume subq.b #1,36(A0) ; decrease volume sustain bra.s Portamento_Handler ; done ... Do_Volume: moveq #0,D0 ; clear d0 moveq #0,D1 ; clear d1 move.w 34(A0),D0 ; get volume counter lea 6(A2),A3 ; get volume table add.w D0,A3 ; add volume counter move.b (A3),D0 ; get volume rate move.b 1(A3),D1 ; get volume level cmp.w 32(A0),D1 ; compare volume with level bpl.s Volume_Plus ; if plus, skip sub.w D0,32(A0) ; decrease volume cmp.w 32(A0),D1 ; compare volume with level bmi.s Portamento_Handler ; if still minus, skip move.w D1,32(A0) ; set volume to level bra.s Volume_Con ; skip Volume_Plus: add.w D0,32(A0) ; increase volume cmp.w 32(A0),D1 ; compare volume with level bpl.s Portamento_Handler ; if still plus, skip move.w D1,32(A0) ; set volume to level Volume_Con: move.b 2(A3),36(A0) ; reset volume sustain addq.w #3,34(A0) ; increase volume counter cmp.w #15,34(A0) ; test volume counter bne.s Portamento_Handler move.w #12,34(A0) ; reset volume counter ; --------------------------------------------- ; ; portamento handler ; ; --------------------------------------------- ; Portamento_Handler: moveq #0,D0 ; clear d0 move.b 37(A0),D0 ; get portamento beq.s Arpeggio_Handler ; if zero, done ... move.w 26(A0),D1 ; get frequency compare cmp.w 24(A0),D1 ; test frequency bpl.s Porta_Plus ; if plus, porta plus sub.w D0,24(A0) ; decrease frequency cmp.w 24(A0),D1 ; test frequency bmi.s Arpeggio_Handler ; if still minus, skip move.w D1,24(A0) ; reset frequency bra.s Arpeggio_Handler ; done ... Porta_Plus: add.w D0,24(A0) ; increase frequency cmp.w 24(A0),D1 ; test frequency bpl.s Arpeggio_Handler ; if still plus, skip move.w D1,24(A0) ; reset frequency ; --------------------------------------------- ; ; arpeggio handler ; ; --------------------------------------------- ; Arpeggio_Handler: moveq #0,D0 ; clear d0 Arp_Repeat: move.l 44(A0),A3 ; get arpeggio pointer add.w 48(A0),A3 ; add arpeggio counter move.b (A3),D0 cmp.b #$80,D0 ; test for arpeggio repeat bne.s Arp_Con ; if not, skip tst.w 48(A0) ; test arpeggio counter beq.s Arp_Con clr.w 48(A0) ; reset arpeggio counter bra.s Arp_Repeat Arp_Con: addq.w #1,48(A0) ; increase arpeggio counter and.w #15,48(A0) ; max. 16 arpeggio bytes tst.b 37(A0) ; test portamento beq.s No_Porta move.w 24(A0),D0 ; get frequency bra.s Set_Freq No_Porta: lea Frequency_Table(PC),A3 ; get frequency table add.b 28(A0),D0 ; add note number add.b 43(A0),D0 ; add transpose add.w D0,D0 ; mulu with 2 move.w 0(A3,D0.W),D0 ; get frequency move.w D0,24(A0) ; set frequency Set_Freq: move.w 36(A2),D1 ; get volume sustain sub.w 30(A0),D1 ; sub channel bendrate sub.w D1,40(A0) ; decrease vibrato value add.w 40(A0),D0 ; add vibrato value move.w D0,6(A1) ; set hardware frequency move.w 32(A0),D0 ; get volume asr.w #2,D0 ; divu with 4 cmp.b 29(A0),D0 ; compare volume with channel volume bmi.s Vol_Minus ; if <, skip move.b 29(A0),D0 ; set volume to channel volume Vol_Minus: cmp.b 46(A6),D0 ; compare volume with song volume bmi.s Vol_Minus2 ; if <, skip move.b 46(A6),D0 ; set volume to song volume Vol_Minus2: move.w D0,8(A1) ; set hardware volume move.w 4(A0),D0 ; get audio dma on or.w D0,0(A6) rts ; --------------------------------------------- ; ; block effect routines ; ; --------------------------------------------- ; Effect01: and.b #15,D1 move.b D1,47(A6) bra.l Increase_Block Effect02: tst.b D1 bne.s FX02 bset #1,$bfe001 bra.l Increase_Block FX02: bclr #1,$bfe001 bra.l Increase_Block Effect03: and.w #$ff,D1 neg.w D1 move.w D1,30(A0) bra.l Increase_Block Effect04: and.w #$ff,D1 move.w D1,30(A0) bra.l Increase_Block Effect05: move.b D1,37(A0) bra.l Increase_Block Effect06: and.b #$3f,D1 move.b D1,29(A0) bra.l Increase_Block Effect07: and.b #$3f,D1 move.b D1,46(A6) bra.l Increase_Block Effect08: and.l #$3f,D1 asl.l #4,D1 move.l 58(A6),A4 add.l D1,A4 move.l A4,44(A0) bra.l Increase_Block Voice1: dc.l $dff0a0 ; 0 ; hardware pointer dc.w $0001 ; 4 ; DMA bit dc.l 0 ; 6 ; sound pointer dc.l 0 ; 10 ; track pointer dc.l 0 ; 14 ; block pointer dc.w 0 ; 18 ; track counter dc.w 0 ; 20 ; block counter dc.b 0 ; 22 ; synthetic delay dc.b 0 ; 23 ; synthetic counter dc.w 0 ; 24 ; frequency dc.w 0 ; 26 ; frequency compare dc.b 0 ; 28 ; note number dc.b 0 ; 29 ; channel volume dc.w 0 ; 30 ; bendrate dc.w 0 ; 32 ; volume counter dc.w 0 ; 34 ; volume dc.b 0 ; 36 ; volume sustain dc.b 0 ; 37 ; portamento dc.b 0 ; 38 ; vibrato wait dc.b 0 ; 39 ; vibrato status dc.w 0 ; 40 ; vibrato value dc.b 0 ; 42 ; vibrato counter dc.b 0 ; 43 ; transpose dc.l 0 ; 44 ; arpeggio pointer dc.w 0 ; 48 ; arpeggio counter dc.b 0 ; 50 ; unused (has once been used) dc.b 0 ; 51 ; sound technique dc.b 0 ; 52 ; vibrato counter dc.b 0 ; 53 ; vibrato sustain dc.w 0 ; 54 ; track repeat dc.w 0 ; 56 ; track length even Voice2: dc.l $dff0b0 ; 0 ; hardware pointer dc.w $0002 ; 4 ; DMA bit blk.b Voice2-Voice1-6 Voice3: dc.l $dff0c0 ; 0 ; hardware pointer dc.w $0004 ; 4 ; DMA bit blk.b Voice2-Voice1-6 Voice4: dc.l $dff0d0 ; 0 ; hardware pointer dc.w $0008 ; 4 ; DMA bit blk.b Voice2-Voice1-6 Frequency_Table: dc.w 0000 dc.w 6848,6464,6096,5760,5424,5120,4832,4560,4304,4064,3840,3616 dc.w 3424,3232,3048,2880,2712,2560,2416,2280,2152,2032,1920,1808 dc.w 1712,1616,1524,1440,1356,1280,1208,1140,1076,1016,0960,0904 dc.w 0856,0808,0762,0720,0678,0640,0604,0570,0538,0508,0480,0452 dc.w 0428,0404,0381,0360,0339,0320,0302,0285,0269,0254,0240,0226 dc.w 0214,0202,0190,0180,0170,0160,0151,0143,0135,0127,0120,0113 dc.w 0113,0113,0113,0113,0113,0113,0113,0113,0113,0113,0113,0113 Song_Data: dc.w $8000 ; 0 ; hardware dma dc.l 0 ; 2 ; sound pointer dc.l 0 ; 6 ; sound offset pointer dc.l 0 ; 10 ; track1 pointer dc.l 0 ; 14 ; track2 pointer dc.l 0 ; 18 ; track3 pointer dc.l 0 ; 22 ; track4 pointer dc.l 0 ; 26 ; block pointer dc.b 0 ; 30 ; random noise on/off (0=off) dc.b 0 ; 31 ; unused (it has once been used) dc.w 0 ; 32 ; unused (it has once been used) dc.l 0 ; 34 ; samples pointer dc.l 0 ; 38 ; samples offset pointer dc.l 0 ; 42 ; random noise value dc.b 63 ; 46 ; song volume dc.b 0 ; 47 ; play speed (reset) dc.b 0 ; 48 ; play speed counter dc.b 0 ; 49 ; sound fx (1 = fx) dc.w 0 ; 50 ; unused (it has once been used) dc.w 0 ; 52 ; unused (it has once been used) dc.w 0 ; 54 ; unused (it has once been used) dc.w 0 ; 56 ; unused (it has once been used) dc.l 0 ; 58 ; arpeggio pointer dc.w 0 ; 62 ; voice1 repeat dc.w 0 ; 64 ; voice1 length dc.w 0 ; 66 ; voice2 repeat dc.w 0 ; 68 ; voice2 length dc.w 0 ; 70 ; voice3 repeat dc.w 0 ; 72 ; voice3 length dc.w 0 ; 74 ; voice4 repeat dc.w 0 ; 76 ; voice4 length dc.l 0 ; 78 ; waveform offset pointer dc.l 0 ; 82 ; waveform pointer even Null_Waveform: blk.b 8,0 Null_Sound: dc.w 2/2 ; 0 ; waveform length/2 dc.w 0 ; 2 ; repeat dc.w 0 ; 4 ; repeat length/2 dc.b 255,1,255 ; 6 ; volume rate/level/sus dc.b 0,0,255 ; 9 ; volume rate/level/sus dc.b 0,0,255 ; 12 ; volume rate/level/sus dc.b 0,0,255 ; 15 ; volume rate/level/sus dc.b 0,0,255 ; 18 ; volume rate/level/sus dc.b 0,1,255 ; 21 ; vibrato step/len/sus dc.b 0,1,255 ; 24 ; vibrato step/len/sus dc.b 0,1,255 ; 27 ; vibrato step/len/sus dc.b 0,1,255 ; 30 ; vibrato step/len/sus dc.b 0,1,255 ; 33 ; vibrato step/len/sus dc.w 0 ; 36 ; bendrate dc.b 0 ; 38 ; technique dc.b 254 ; 39 ; table speed dc.b 0,$ff,0 ; 40 ; waveform table even Module: blk.b 4,0