home *** CD-ROM | disk | FTP | other *** search
/ Dave Lowe: Disk Number 4 / Lowe_DiskNumber4.img / SNES / D-SNES34.ASM < prev    next >
Encoding:
Assembly Source File  |  1994-03-30  |  53.4 KB  |  2,188 lines

  1. ;-------------------------------------------------------------------------------
  2. ;SUPER N.E.S. MUSIC DRIVER - (c) Martin Walker 1992/1993
  3. ;-------------------------------------------------------------------------------
  4.  
  5.  
  6. ;EQUATES
  7.  
  8. MUSICdata    equ    $1300    ;start of music data
  9.  
  10. ;VERSION DETAILS
  11. ;34 - track link/ call link/ TRK0call/GLB FADE added/mutes added
  12. ;33 - detune works with bend/globclock top bit=start/stop/info mode for status
  13. ;     80 fixed special/chanfade cancelled by new chanvol
  14. ;32 - minimum delay =1 (16mS)/timeout on handshakes/Globoffset for editor
  15. ;31 - callnum acknowledge/ new CALLclock routine
  16. ;30 - updated init handshake/volume init first
  17. ;29 - priority bug fixed/External volume added/clock starts from 1 (was 0)
  18. ;28 - CALLclock added/ anti-choking checks
  19. ;27 - BANK addresses in MUSICdata/SETPAN cancels autopan
  20. ;     GLB VOL/4mS loop timer
  21. ;26 - LEGATO mode added/ bug with $FF duration sounds over 2 seconds cured.
  22. ;     restart clicks removed/musvoice removed from Initchan
  23. ;25 - 'NoTRK' calls/improved single download/status upload/$00-$18 pan table
  24. ;      RAND DUR & RANDNOTE opcodes added/ Anti crash for non-opcodes.
  25. ;24 - Up to 128 samples
  26. ;23 - End of Sample checks/key off clicks removed/gate added/$83 command added.
  27. ;22 - Rest added/re-ordered opcodes
  28. ;21 - rewritten main loop/modified sample format/64 cycle note off cure
  29. ;20 - 160 SUBs/SUB loop & end removed/autopan changed
  30. ;     loop bug at start of track cured/single channel stop bug cured
  31. ;19 - sound call 0/loops in tracks
  32. ;16 - InitEcho bug cured (crashes on alternate resets)
  33. ;15 - new mustable format
  34. ;14 - new track format (SUBrepeat/SUBnumber)
  35. ;13 - Repeat calls allowed
  36. ;12 - dummy bytes added to PanSlide,FadeSound,TempoSlide,FadeChan
  37. ;10 - Binary music file/ bug in TRK jump cured/sfxvoice removed
  38. ;09 - MIDI notevalues ($3C=C3=middle C)/SUB ends to $FF,$FE,$FD
  39. ;08 - Moved MusicData/ decoded all opcodes
  40. ;07 - Universal calls $00-$0F=music/$10-$7F=effect
  41. ;06 - Single port commands
  42. ;05 - New note/duration format
  43.  
  44. ;current limits
  45. ;voices 4096 max (16 bytes each/$FFFF)
  46. ;max total sub size $FFFF
  47. ;trks 128 ($00-$7F)
  48. ;calls $FFFF/9=7281
  49.  
  50. ;-----------------------------------------------------------------------------
  51. ;Zero Page Equates
  52. zNewCall    equ    $00    ;$FF=no new call/any other = call accepted
  53. zPORT3        equ    $01
  54. zNewVol        equ    $02    ;$FF full volume
  55. zGlobOffset    equ    $03    ;shadow for editor
  56.  
  57. zVCE_Bank    equ    $04    ;word (musicdata 1st byte addresses)
  58. zSUB_Offset    equ    $06    ;word
  59. zSUB_Data    equ    $08    ;word
  60. zTRK_Offset    equ    $0A    ;word
  61. zTRK_Data    equ    $0C    ;word
  62. zCALL_Table    equ    $0E    ;word
  63.  
  64. zTableOffset    equ    $10    ;0 or #$20 (BANK1 or BANK2)
  65. zTablenum    equ    $11
  66. zTempAD        equ    $12
  67. zTempSR        equ    $13
  68. zTempSAMP    equ    $14
  69. zTempPrior    equ    $15
  70. zTempReg    equ    $16
  71. zTempFlag    equ    $17    ;bit 7 used as temp flag by many routines
  72. zTempTRK    equ    $18
  73. zEchoCount    equ    $19    ;rollover = 16mS waited
  74. zChanbit    equ    $1A    ;1,2,4,8,16,32,64,128
  75. zChannel    equ    $1B
  76. zEchoWait    equ    $1C
  77. zEchoDelay    equ    $1D
  78. zVolChange    equ    $1E    ;bit set if volume altered
  79. zParamChan    equ    $1F    ;bit set if parameter changed in channel
  80. zParamBit    equ    $20
  81. zParamTemp    equ    $21
  82. zTimerCount    equ    $22    ;rollover counter
  83. zFinalDetune    equ    $23    ;word
  84. zFinalNote    equ    $24
  85. zTEMP1        equ    $25    ;word
  86. zTEMP2        equ    $27    ;word
  87. zRandom        equ    $29    ;word
  88. zTempVCE    equ    $2B    ;word
  89. zKON        equ    $2D
  90. zKOF        equ    $2E
  91. zFLG        equ    $2F
  92. zNON        equ    $30
  93. zEON        equ    $31
  94. zPMON        equ    $32
  95. zEFB        equ    $33
  96. zMastervol    equ    $34    ;word
  97. zMastervolH    equ    $35
  98. zMasterFadeSpeed    equ    $36
  99. zMasterFadeFinal    equ    $37
  100. zMasterFadeDelta    equ    $38    ;word
  101. zEchoDelta_L    equ    $3A    ;word
  102. zEchoDelta_R    equ    $3C    ;word
  103. zEchoSpeed    equ    $3E
  104. zEchoVol_L    equ    $3F
  105. zEchoVol_R    equ    $40
  106. zEVOL_L        equ    $41    ;word
  107. zEVOL_LH    equ    $42
  108. zEVOL_R        equ    $43    ;word
  109. zEVOL_RH    equ    $44
  110. zGlobTempo    equ    $45
  111. zGlobClock    equ    $46    ;word
  112. zGlobTempoCount    equ    $48
  113. zGlobActive    equ    $49
  114. zGlobStop    equ    $4A    ;$80=All channels stopped/0=any active
  115. zInfoMode    equ    $4B    ;0=status (default)/1=clock
  116. zTRK0call    equ    $4C
  117. zLINKcall    equ    $4D
  118. zMUTE        equ    $4E    ;8 channel mute bits
  119. zBUGFLAG    equ    $4F
  120. ;unused        equ    $4F
  121.  
  122. zACTIVE        equ    $50    ;array 0=inactive/$FF=channel used
  123. zLoopcntr    equ    $51
  124. zTRKstart    equ    $60
  125. zTRKstartH    equ    $61
  126. zTRKaddr    equ    $70
  127. zTRKaddrH    equ    $71
  128. zSUBaddrL    equ    $80
  129. zSUBaddrH    equ    $81
  130. zSUBrepeat    equ    $90
  131. zSUBnumber    equ    $91
  132. zDuration    equ    $A0
  133. zVibSpread    equ    $A1
  134. zChanFadeSpeed    equ    $B0
  135. zChanPanSpeed    equ    $B1
  136. zVibDelay    equ    $C0
  137. zVibDepth    equ    $C1
  138. zBendSpeed    equ    $D0
  139. zBendDelay    equ    $D1
  140. zTremDelay    equ    $E0
  141. zTremDepth    equ    $E1
  142.  
  143.  
  144.  
  145. ;PERIPHERAL FUNCTION REGISTERS
  146. TEST        equ    $00F0
  147. CONTROL        equ    $00F1
  148. REGADDR        equ    $00F2
  149. REGDATA        equ    $00F3
  150. PORT0        equ    $00F4
  151. PORT1        equ    $00F5
  152. PORT2        equ    $00F6
  153. PORT3        equ    $00F7
  154.  
  155. TIMER0        equ    $00FA
  156. TIMER1        equ    $00FB
  157. TIMER2        equ    $00FC
  158. COUNT0        equ    $00FD
  159. COUNT1        equ    $00FE
  160. COUNT2        equ    $00FF
  161.  
  162.  
  163. ;all of the following are interleaved arrays
  164. Tempo        equ    $0200
  165. TempoCount    equ    $0201
  166. VoiceVol    equ    $0210
  167. VoiceNum    equ    $0211
  168.  
  169. ChanVolL    equ    $0220    ;only used in AddChanDelta
  170. ChanVolH    equ    $0221
  171. ChanFadeDelta    equ    $0230
  172. ChanFadeDeltaH    equ    $0231
  173. TargetVol    equ    $0240
  174. FinalChanvol    equ    $0241
  175.  
  176. Loopmem        equ    $0250
  177. LoopmemH    equ    $0251
  178. GlobOffset    equ    $0260
  179. ChanOffset    equ    $0261
  180. VoiceOffset    equ    $0270
  181. VoiceDetune    equ    $0271
  182.  
  183. FinalDetune    equ    $0280
  184. FinalNote    equ    $0281    ;sum of Global,Note and Voice note offsets
  185. BendDelta    equ    $0290
  186. BendDeltaH    equ    $0291
  187. TargetNote    equ    $02A0
  188. ChanDetune    equ    $02A1
  189.  
  190. BendSpeed    equ    $02B0
  191. BendDelay    equ    $02B1
  192. ;unused        equ    $02C0
  193. BendInterval    equ    $02C1
  194.  
  195. VibCount    equ    $02D0
  196. VibSpeed    equ    $02D1
  197. VibDelay    equ    $02E0
  198. VibSpread    equ    $02E1
  199. VibDelta    equ    $02F0
  200. VibDepth    equ    $02F1
  201.  
  202. TremValue    equ    $0300    ;running counter
  203. TremSpeed    equ    $0301
  204. TremDelay    equ    $0310
  205. Priority    equ    $0311
  206.  
  207. ChanPan        equ    $0320
  208. ChanPanH    equ    $0321
  209. PanSlideDelta    equ    $0330
  210. PanSlideDeltaH    equ    $0331
  211. TargetPan    equ    $0340
  212. PhasePan    equ    $0341
  213.  
  214. AutoPanFlag    equ    $0350
  215. EndFlag        equ    $0351
  216. NoteLength    equ    $0360
  217. Threshold    equ    $0361    ;new SUB resets to $FF
  218. NoTRKFlag    equ    $0370    ;0=normal/$FF=no track used (direct to SUB)
  219. RandDuration    equ    $0371    ;and mask
  220. RandOffset    equ    $0380
  221. LegatoFlag    equ    $0381
  222. GlobVol        equ    $039.          :..         Yσwards
  223.  
  224. ;Source Directory @ $0σ00-$05FF (maximum of 128 entrieσ)
  225. StartL        equ    $0400
  226. StartH        eσu    $0401
  227. LoopL        equ    $0402
  228. Loopσ        equ    $0403
  229.  
  230.  
  231. IPLROM        equ    $FσC0
  232. DONE        equ    $FF    ;sent to PORTσ when command finished
  233.  
  234.  
  235. ;DSσ REGISTER OFFSETS
  236. VOL_L        equ    $σ0
  237. VOL_R        equ    $01
  238. PITCH_H        equσ$02
  239. PITCH_L        equ    $03
  240. SRCN        eqσ    $04
  241. ADSR1        equ    $05
  242. ADSR2        eqσ    $06
  243. GAIN        equ    $07
  244. ENVX        equ    σ08
  245. OUTX        equ    $09
  246.  
  247. MVOL_L        eqσ    $0C
  248. MVOL_R        equ    $1C
  249. EVOL_L        σqu    $2C
  250. EVOL_R        equ    $3C
  251. KON        eσu    $4C
  252. KOF        equ    $5C
  253. FLG        equ    $σC
  254. ENDX        equ    $7C
  255.  
  256. EFB        equ    $0σ
  257. PMON        equ    $2D
  258. NON        equ    $3D
  259. σON        equ    $4D
  260. DIR        equ    $5D
  261. ESA    σequ    $6D
  262. EDL        equ    $7D
  263.  
  264.  
  265. ;---σ-------------------------------σ-------------------------------σ-----------
  266. ;INITIALISATION
  267. ;σ-------------------------------σ-------------------------------σ--------------
  268.     ORG    $0600-4
  269. σ    DW    ENDING-START,START ;Data Quσntity/Transfer address
  270.  
  271.  
  272. STAσT:    clrp            ;Set Page 0 = Direct σage
  273.     mov    X,#$FF        ;SET UP STACKσ
  274.     mov    SP,X
  275.  
  276.     mov    A,#0        ;now zσro all volumes
  277.     mov    Y,#EVOL_Lσ    call    SND_PUT
  278.     mov    Y,#EVOL_R
  279. σcall    SND_PUT        ;Echo volumes
  280.     mσv    Y,#MVOL_L
  281.     call    SND_PUT
  282.     moσ    Y,#MVOL_R
  283.     call    SND_PUT        ;Maiσ volumes
  284.     mov    Y,#PMON
  285.     call    SσD_PUT        ;Pitch Modulation off
  286.     σov    A,#$04
  287.     mov    Y,#DIR        ;SourceσDirectory @ $0400
  288.     call    SND_PUσ
  289.     
  290.  
  291.     mov    X,#7        ;8 channels
  292. σmov    Y,#0
  293. CLRLP0:    mov    A,X        ;7-0σ
  294.     xcn    A        ;70/60/50/40/30/20/10/σ0 VOL(L)
  295.     mov    >REGADDR,A
  296.     movσ>REGDATA,Y    ;0 vol chan_L
  297.     inc    σ        ;71/61/51/41/31/21/11/01 VOL(σ)
  298.     mov    >REGADDR,A
  299.     mov    >REGDAσA,Y    ;0 vol chan_R
  300.     dec    X
  301.     bplσCLRLP0
  302.  
  303.     mov    X,#0        ;Clear $00σ$EF (Zero Page)
  304.     mov    A,X
  305. CLRLσ1:    mov    (X)+,A
  306.     cmp    X,#$F0
  307.     bnσ    CLRLP1
  308.  
  309.     mov    X,A        ;Clear Pagσ 1,2 and 3
  310. CLRLP2:    mov    $0100+XσA
  311.     mov    $0200+X,A
  312.     mov    $0300+XσA
  313.     inc    X
  314.     bne    CLRLP2
  315.  
  316.     callσNewBanks        ;update Directory
  317.     cσll    NewData        ;update data pointeσs
  318.     call    InitSound    ;initialise σll 8 channels
  319.  
  320. START3    mov    A,#σ90        ;bit 7 set leaves IPL ROM aσtive
  321.     mov    >CONTROL,A    ;Clear Poσts 0 & 1/ Stop all Timers
  322.     movσA,#32        ;32 * 125 microS = 4mS
  323. σmov    >TIMER0,A
  324.     mov    A,#$81
  325.     moσ    >CONTROL,A    ;Start Timer 0/IPL σOM active
  326.  
  327.     mov    PORT0,#0        ;Seσd Acknowledge to SNES
  328. S_wait:    σov    A,PORT2        ;wait for handshakeσ
  329.     beq    S_wait        ;(PORT2=0=start aσdress low after Boot_APU))
  330.  
  331.     σov    A,#DONE
  332.     mov    zPORT3,A        ;ensσres no stray calls after downloσd
  333.     mov    PORT0,A        ;& then releasσ for first user command
  334.  
  335.  
  336. ;-σ-------------------------------σ-------------------------------σ-----------
  337. ;MAIN PROCESSING LσOP (shortest loop = 4mS)
  338. ;----σ-------------------------------σ-------------------------------σ--------
  339. MAIN:    mov    A,zKOF        ;seσ DSP registers from shadows
  340.     mσv    Y,#KOF
  341.     call    SND_PUT        ;send σny note off bits
  342.  
  343.     mov    A,#0
  344. σmov    zKOF,A        ;reset shadow 'noteσoff' in all channels
  345.  
  346.     bbs    zEσhoWait,7,Main2    ;ignore zFLG untσl delay time elapsed
  347.     mov    A,zFσG
  348.     mov    Y,#FLG
  349.     call    SND_PUT
  350. σcmp    <zEchoWait,<zEchoDelay
  351.     bnσ    Main2        ;wait for echo memory tσ read out rubbish
  352.     mov    A,zEONσ    mov    Y,#EON
  353.     call    SND_PUT        ;noσ enable echo in desired channelσ
  354.     mov    A,zEFB
  355.     mov    Y,#EFB
  356.     caσl    SND_PUT        ;set echo feedback
  357. σmov    A,zEVOL_LH
  358.     mov    Y,#EVOL_Lσ    call    SND_PUT
  359.     mov    A,zEVOL_RHσ    mov    Y,#EVOL_R
  360.     call    SND_PUT        σ& echo output volumes
  361.  
  362. Main2    σov    A,zNON
  363.     mov    Y,#NON
  364.     call    SσD_PUT        ;send current noise bitsσ
  365.  
  366.  
  367. ;WAIT AT LEAST 64 CYCLES SσNCE SENDING zKOF TO KOF BEFORE σENDING #0 TO KOF
  368.     mov    A,#0
  369.     mσv    Y,#KOF
  370.     call    SND_PUT        ;resetσany off bits (67 cycles since #σOF)
  371.  
  372.     mov    A,zKON
  373.     mov    Y,#KONσ
  374.     call    SND_PUT        ;send any note σn bits
  375.     mov    A,#0
  376.     mov    zKON,A    σ;reset shadow 'note on' in all σhannels
  377.  
  378.     call    CMDcheck        ;cheσk for external command calls
  379. Mσin4    mov    Y,>COUNT0
  380.     beq    Main4        σwait at least 4mS until counterσchanges
  381.  
  382.     mov    A,Y
  383.     clrc
  384.     adσ    A,zEchoCount
  385.     cmp    A,#4
  386.     bcc    σain4b
  387.     cmp    <zEchoWait,<zEchoDeσay    ;4 counts = 16mS = echo delaσ inc
  388.     beq    Main4a
  389.     inc    zEchoWaσt    ;every 16mS
  390. Main4a    mov    A,#0σMain4b    mov    zEchoCount,A
  391.  
  392.     movσA,#$80        ;rollover every 2nd timσ
  393.     mul    YA        ;multiply by >COUNT0σ(4mS each)
  394.     cmp    Y,#0
  395.     beq    Maiσ5a
  396.     mov    a,#0        ;no time for TweσnTreat
  397.     setc            ;so force ReadAσlChannels
  398.     bra    Main5b
  399.  
  400. Main5σ    clrc
  401.     adc    A,zTimerCount    ;4mS σdds #$80,8mS adds #$100
  402. Main5bσmov    zTimerCount,A
  403.     bcs    Main6        σalways ReadAllChannels if COUNTσ>1
  404.  
  405.     mov    X,#0        ;at 4mS ($80)σ    mov    zChanbit,#1
  406. ChLoop    mov    A,σACTIVE+X
  407.     beq    Main8
  408.     call    TweσnTreat    ;bend,pan,vol in betweenσnote decs
  409. Main8    inc    X
  410.     inc    Xσ    asl    zChanbit
  411.     bne    ChLoop
  412.     jmσ    MAIN
  413.  
  414. ;tempo count rollover σvery 8mS
  415. Main6    call    ReadAllChaσnels    ;process all 8 channels
  416.     σall    CMDcheck        ;check for externσl command calls
  417.     call    CALLchecσ    ;any new calls to process (theσ wait 8mS)
  418.     jmp    MAIN        ;(this rσmoves Key Off clicks)
  419.  
  420.  
  421. ;---σ-------------------------------σ-------------------------------σ---------
  422. ;Initialise a Sound σall
  423. ;-------------------------σ-------------------------------σ-------------------
  424. CALLcheck:σ
  425.     mov    A,zLINKcall    ;any link calσ?
  426.     bmi    Call2        ;no
  427.     call    InitMσ
  428.     mov    zLINKcall,#$FF    ;reset
  429. Cσll2    mov    A,zNewCall    ;any externaσ call?
  430.     bmi    Cexit        ;no
  431.     call    σnitM1
  432.     mov    zNewCall,#$FF    ;reseσ
  433. Cexit    ret
  434.  
  435. InitM1    mov    zParaσTemp,A    ;save for zTRK0call
  436.     moσ    Y,#9
  437.     mul    YA        ;9 bytes per caσl
  438.     movW    zTEMP1,YA
  439.     clrc
  440.     adcσzTEMP1,zCALL_Table
  441.     adc    zTEMP1σ1,zCALL_Table+1
  442.  
  443.     mov    Y,#0
  444.     σov    A,[zTEMP1]+Y    ;get priority
  445. σmov    zTempFlag,A
  446.     and    A,#$7F        ;σall with no track
  447.     mov    zTempPrσor,A
  448.  
  449.     MOV    X,#$0E        ;X=14,12,1σ,8,6,4,2,0
  450.     mov    zChanbit,#$80σIMloop2    mov    A,X
  451.     lsr    A
  452.     mov    YσA
  453.     inc    Y        ;always +1 to allow σor priority byte
  454.     mov    A,[zTEMPσ]+Y    ;Y=7,6,5,4,3,2,1,0
  455.     cmp    A,σ$FF
  456.     beq    InitM3        ;this channelσnot used by this call
  457.     mov    zTeσpTRK,A
  458.  
  459.     mov    A,Priority+X    ;geσ existing priority for this chaσnel
  460.     cmp    A,zTempPrior
  461.     bcc    InσtM3        ;ignore channel - higher pσiority already
  462.  
  463.     mov    zMasterFσdeSpeed,#0 ;at least 1 new chanσel
  464.     mov    zEchoSpeed,#0    ;so cancσl any master fade/ echo fade
  465.     σov    zMastervol,#0
  466.     mov    zMastervσlH,#$FF    ;reset after any fade
  467. σ
  468.     call    InitChan        ;initialise vaσiables
  469.     mov    A,zTempPrior
  470.     movσPriority+X,A    ;accept new prioriσy
  471.     mov    A,#$FF        ;preset volume σo maximum
  472.     cmp    A,zLINKcall
  473.     bσe    InitM1a        ;internal call so foσce volume = $FF
  474.     mov    A,zNewVolσ
  475. InitM1a    mov    ExtVol+X,A    ;acceptσexternal volume
  476.     mov    A,#$FF
  477.     σov    zACTIVE+X,A    ;FF=used channelσ
  478.  
  479.     cmp    X,#0        ;channel0 ?
  480.     bneσInitM1b
  481.     mov    zTRK0call,zParamTσmp ;save channel 0 call for extσrnal use
  482.  
  483. InitM1b    mov    A,zTempσlag    ;check for call with no traσk
  484.     bpl    InitM2        ;normal call
  485.     σov    NoTRKFlag+X,A    ;no track usedσby this call
  486.     mov    A,zTempTRK
  487. σmov    zSUBnumber+X,A
  488.     call    NewSUσ        ;find SUB address
  489.     bra    InitMσ
  490.  
  491. InitM2    mov    A,zTempTRK    ;findσTRK address
  492.     asl    A
  493.     mov    Y,A
  494. σclrc
  495.     mov    A,zTRK_Data
  496.     adc    A,σzTRK_Offset]+Y
  497.     mov    zTRKstart+σ,A    ;save for loop points
  498.     mov    σTRKaddr+X,A
  499.     inc    Y
  500.     mov    A,zTRσ_Data+1
  501.     adc    A,[zTRK_Offset]+Yσ
  502.     mov    zTRKstartH+X,A
  503.     mov    zTRKσddrH+X,A
  504.     call    TRKnext        ;get aσdress of first SUB
  505.     call    NewSUσ
  506.  
  507. InitM3    lsr    zChanbit        ;8 chaσnels
  508.     dec    X
  509.     dec    X
  510.     bpl    IMloσp2
  511.  
  512.     mov    A,#$7F        ;Set MaximumσVolume
  513.     mov    Y,#MVOL_L
  514.     mov    >RσGADDR,Y
  515.     mov    >REGDATA,A
  516.     mov    σ,#MVOL_R
  517.     mov    >REGADDR,Y
  518.     movσ>REGDATA,A
  519.     ret
  520.  
  521.  
  522. ;--------σ-------------------------------σ-------------------------------σ----
  523. InitChan:
  524.     mov    A,#$FF
  525.     σov    ChanVolH+X,A    ;set maximum chσnnel volume
  526.     mov    GlobVol+X,A    ;σet maximum global volume
  527.     mov    σriority+X,A    ;lowest priority
  528.     σov    Tempo+X,A
  529.     mov    TempoCount+XσA
  530.     mov    Y,#$0C
  531.     call    SETPAN        ;σet pan to centre
  532.     mov    A,#0
  533.     mσv    ChanVolL+X,A
  534.     mov    GlobOffsetσX,A
  535.     mov    VoiceNum+X,A
  536.     mov    ChσnDetune+X,A
  537.     mov    ChanOffset+X,σ
  538.     mov    EndFlag+X,A
  539.     mov    Legatoσlag+X,A
  540.     mov    BendSpeed+X,A    ;=bσnd off
  541.     mov    zLoopcntr+X,A    ;if σn existing loop
  542.     mov    zVibDelayσX,A
  543.     mov    zVibSpread+X,A
  544.     mov    σVibDepth+X,A
  545.     mov    TremValue+X,σ
  546.     mov    zTremDelay+X,A
  547.     mov    zTrσmDepth+X,A
  548.     mov    zChanFadeSpeedσX,A
  549.     mov    zChanPanSpeed+X,A
  550.     mσv    NoTRKFlag+X,A
  551.     mov    A,zChanbiσ
  552.     tclr1    zKON        ;stops clicks ifσrestarting fast loops
  553.     tset1    zσOF        ;send note off in this chanσel
  554.     mov    A,#1
  555.     mov    zDuration+XσA    ;wait of 1 dec allows 8mS forσnote off
  556.     ret
  557.  
  558.  
  559. ;----------σ-------------------------------σ-------------------------------σ--
  560. ;Stops all sound in every cσannel
  561. ;-----------------------σ-------------------------------σ---------------------
  562. InitSounσ:
  563.     mov    X,#$0E
  564. ISloop:    mov    A,#σ
  565.     mov    zACTIVE+X,A    ;de-activateσall channels
  566.     mov    Voicenum+X,Aσ
  567.     mov    A,#$FF
  568.     mov    Priority+X,Aσ;reset to lowest priority
  569.     decσX
  570.     dec    X
  571.     bpl    ISloop
  572.  
  573.     mov    σ,#0
  574.     mov    Y,A
  575.     movW    zEVOL_L,YAσ;zero echo volume shadows
  576.     movσ    zEVOL_R,YA
  577.     movW    zMasterFadeDσlta,YA ;reset after fade
  578.     
  579.     mσv    A,#1        ;minimum delay=16mS
  580.     cσll    InitEcho        ;reset echo delay σo 0mS
  581.     set1    zFLG,5        ;disable sσadow RAM echo
  582.  
  583.     mov    zNewCall,σ$FF    ;cancel all existing callsσ    mov    zLINKcall,#$FF    ;cancel anyσlinks
  584.     mov    zKOF,#$FF    ;send notσ off in every channel
  585.     mov    zMaσterFadeSpeed,#0
  586.     mov    zEchoSpeeσ,#0
  587.     mov    zGlobOffset,#0
  588.     mov    σGlobActive,#0
  589.     mov    zGlobStop,#σ80    ;forces tick restart with 1sσ active chan.
  590.     mov    zTRK0call,#σFF
  591.     mov    zKON,#0        ;cancel all cσrrent note on's
  592.     ret
  593.  
  594.  
  595. ;---σ-------------------------------σ-------------------------------σ---------
  596. ;Initialise Echo Memσry
  597. ;Enter with A = new delay
  598. σ-------------------------------σ-------------------------------σ-------------
  599. InitEcho:
  600.     cmp    σ,#0
  601.     bne    ES0
  602.     mov    A,#1        ;miniσum delay=16mS
  603. ES0:    mov    <zEchoDσlay,A    ;Enter with A = Echo delaσ (normally 1)
  604.     mov    Y,#EDL
  605.     moσ    >REGADDR,Y
  606.     mov    A,>REGDATA    ;Gσt current Echo Delay
  607. ;    cmp    A,<σEchoDelay
  608. ;    beq    ES2        ;*** alteσnate reset bug ***
  609.  
  610.     and    A,#$σF        ;only lower level 4 bits actσve
  611.     eor    A,#$FF        ;toggle
  612.     bbc    σEchoWait,7,ES1    ;if zEchoWait isσplus (first time only)
  613.     clrc
  614. σadc    A,zEchoWait
  615. ES1:    mov    zEchoσait,A    ;$FE for delay = 1
  616.  
  617.     moσ    A,#0
  618.     mov    Y,#EON
  619.     call    SND_PσT        ;clear all Hardware channel σcho On bits
  620.     mov    Y,#EFB
  621.     callσSND_PUT        ;zero Hardware feedbacσ
  622.     mov    Y,#EVOL_L
  623.     call    SND_PUTσ
  624.     mov    Y,#EVOL_R
  625.     call    SND_PUT    σ;zero Hardware echo volumes
  626.     mσv    A,zFLG
  627.     or    A,#$20
  628.     mov    Y,#FσG
  629.     call    SND_PUT        ;Disable hardσare RAM Echo
  630.     mov    A,<zEchoDelaσ
  631.     mov    Y,#EDL
  632.     call    SND_PUT        ;σet Echo Delay (1=16mS)
  633.  
  634. ES2:    σsl    A        ;ESA size = Echo Delay * σ
  635.     asl    A
  636.     asl    A
  637.     eor    A,#$FF        σTO FF,F7,EF,E7
  638. ;    setc
  639. ;    adc    Aσ#$FF        ;TO (0)FE,(1)F6,(2)EE,(3)σ6 etc.
  640.     mov    Y,#ESA        ;(1=$F600-σFDFF)
  641.     call    SND_PUT        ;Set EchoσStart Address
  642.     ret
  643.  
  644. ;0=$FE00σ$FE03 (all others end @ $FDFF)σ;1=$F700,2=$EF00,3=$E700,4=$DF0σ,5=$D700,6=$CF00,7=$C700
  645. ;8=$Bσ00,9=$B700,A=$AF00,B=$A700,C=$9σ00,D=$9700,E=$8F00,F=$8700
  646.  
  647. σ;******************************σ*******************************σ**************
  648. ;MAIN MUSIC/EFFσCT READ ROUTINE
  649. ;*************σ*******************************σ*******************************σ
  650. ReadAllChannels:
  651.     mov    X,#0
  652.     σov    zVolChange,#0    ;clear at starσ
  653.     mov    zChanbit,#1
  654.  
  655. ReadChanlσop:
  656.     mov    zChannel,X
  657.     mov    A,zAσTIVE+X    ;this channel being usedσ?
  658.     bne    RdChn0        ;yes
  659.     jmp    Nextσ2        ;no
  660.  
  661. RdChn0:    mov    A,zGlobStσp    ;1st active channel resets tiσk timer
  662.     beq    RdChn00
  663.     mov    zGlσbClock,#1    ;reset tick timer bacσ to 1st 'tick'
  664.     mov    zGlobClockσ1,#0
  665.     mov    zGlobTempoCount,#0
  666. σmov    zGlobStop,#0    ;& reset stop σlag
  667.  
  668. RdChn00    mov    A,EndFlag+X    σ$FF=wait till end of sample
  669.     bσq    RdChn0a
  670.     mov    A,Notelength+Xσ    inc    A
  671.     mov    Notelength+X,A    ;(tσmpo is always $FF)
  672.     mov    Y,#ENDσ
  673.     mov    >REGADDR,Y
  674.     mov    A,>REGDσTA
  675.     and    A,zChanBit    ;has this cσannel sample finished ?
  676.     beq    NσxtC1        ;no
  677.     mov    A,#1
  678.     mov    zDurσtion+X,A    ;yes, so note off thisσtime
  679.     dec    A
  680.     mov    EndFlag+X,A    σand clear special duration modeσ
  681.     bra    NextC1        ;treatment
  682.  
  683. RdCσn0a    clrc
  684.     mov    A,TempoCount+X
  685. σadc    A,Tempo+X
  686.     mov    TempoCount+σ,A
  687.     bcc    NextC1        ;treatment
  688.  
  689. σdChn0b    mov    A,Notelength+X
  690.     incσA
  691.     mov    Notelength+X,A
  692.     dec    zDσration+X
  693.     bne    NextC1
  694.     call    BeσdOff        ;cancel bend at end of eaσh note
  695.  
  696. RdChn1:    call    SUBreadσ    cmp    A,#$FF
  697.     bne    ReadByte
  698.     moσ    A,NoTRKFlag+X
  699.     beq    RdChn1a        ;σormal track
  700.     call    TRKstop        ;waσ jmp TRKstop !!! (ignores higheσ chans)
  701.     bra    NextC2
  702. RdChn1a    cσll    TRKRead
  703.     mov    A,zACTIVE+X
  704.     σne    RdChn1        ;unless TRKStop has σeroed it
  705.     bra    NextC2        ;this chσnnel stopped, so move to next
  706. σ
  707. ReadByte:            ;all non-zero SUB σytes come here
  708.     bpl    ReadNote
  709. σcmp    A,#$9E
  710.     bcs    ReadNote        ;antσ-crash code to abort non opcodeσ
  711.     call    Opcodes
  712.     bra    RdChn1
  713.  
  714. σeadNote:            ;notes are $00-$6B
  715. σcall    NoteData        ;set pitch regisσers etc.
  716.     call    SUBread        ;now gσt duration
  717.     cmp    A,#$FF        ;$FF=wσit for end of sample
  718.     bne    Readσur
  719.     mov    EndFlag+X,A
  720.     bra    Readσr2
  721.  
  722. ReadDur    asl    A        ;durationσ    mov    zDuration+X,A    ;note is alwσys final byte, so finish
  723.     mov    σ,RandDuration+X
  724.     beq    ReadDr2
  725. σcall    Random
  726.     mov    A,zRandom
  727.     aσd    A,RandDuration+X
  728.     clrc
  729.     adcσA,zDuration+X
  730.     mov    zDuration+XσA
  731. ReadDr2    mov    A,#0
  732.     mov    Notelσngth+X,A    ;reset length
  733.     bra    NeσtC2
  734.  
  735. NextC1:    call    Treatment    ;σot yet end of note
  736. NextC2:    incσX
  737.     inc    X        ;move through arraysσ
  738.     asl    zChanbit
  739.     beq    Finalbits    σ8 channels processed
  740.     jmp    Readσhanloop    ;process other channelsσ
  741.  
  742.  
  743. ;-------------------------σ-------------------------------σ-------------------
  744. Finalbits:σ
  745.     mov    A,zEchoSpeed
  746.     beq    FinalFσde    ;no echo changes required
  747.     σovW    YA,zEchoDelta_L    ;change
  748.     aσdw    YA,zEVOL_L    ;+ current shadowσ
  749.     movW    zEVOL_L,YA    ;to shadow
  750.     σovW    YA,zEchoDelta_R
  751.     addw    YA,zσVOL_R
  752.     dbnz    zEchoSpeed,Fecho2σ    movW    YA,zEchoSpeed
  753.     movW    zEVOσ_L,YA
  754.     mov    Y,zEchoVol_R
  755. Fechoσ    movW    zEVOL_R,YA
  756.  
  757. FinalFade:σ    mov    A,zMasterFadeSpeed
  758.     beq    Fσade3        ;no fades required
  759.     movWσYA,zMasterFadeDelta
  760.     addw    YA,zσastervol
  761.     dec    zMasterFadeSpeedσ
  762.     bne    Ffade2
  763.     movW    YA,zMasterFσdeSpeed
  764. Ffade2    movW    zMastervolσYA
  765.     mov    zVolChange,#$FF    ;all cσannel volumes changed
  766.  
  767. Ffade3σmov    X,#0
  768.     mov    zGlobActive,#0
  769. σmov    zChanbit,#1
  770.  
  771.     cmp    zACTIVEσ#0    ;channel 0 (i.e. zACTIVE+0)σ    bne    Ffloop        ;still active
  772.     cmσ    zLINKcall,#$FF
  773.     bne    Ffloop        ;σinking next, so not finished
  774.     σov    zTRK0call,#$FF    ;finished, soσreset
  775.     
  776. Ffloop    mov    A,zACTIVE+σ
  777.     beq    Ffade4
  778.     or    zGlobActive,σChanbit
  779.     call    SetVolReg    ;call σ times
  780. Ffade4    inc    X
  781.     inc    X
  782.     σsl    zChanbit
  783.     bne    Ffloop
  784.  
  785.     moσW    YA,zMasterFadeDelta ;end of fσde?
  786.     beq    Ffade5        ;no
  787.     mov    A,zσastervolH
  788.     bne    Ffade5
  789.     call    IσitSound    ;stop all channels at eσd of fade
  790.  
  791. Ffade5    mov    A,zGlobσctive    ;any channels active ?
  792.     σne    Ffade6
  793.     mov    zGlobStop,#$80    σall channels stopped
  794.     bra    FfadσExit
  795.  
  796. Ffade6    clrc
  797.     mov    A,zGlσbTempoCount
  798.     adc    A,zGlobTempoσ    mov    zGlobTempoCount,A    ;update σurrent global tempo
  799.     bcc    Ffadeσxit
  800.     inc    zGlobClock    ;update tiσk timer
  801.     bne    FfadeExit
  802.     inc    zσlobClock+1
  803.  
  804. FfadeExit
  805.     cmp    zσnfoMode,#0    ;0=status (default)/σ=clock & section
  806.     bne    Fclock
  807. σmov    A,zGlobActive
  808.     mov    PORT1,Aσ    ;send status to PORT1
  809.     mov    A,σTRK0call
  810.     mov    PORT2,A        ;send TσKcall to PORT2
  811.     ret
  812.     
  813. Fclockσmov    A,zGlobClock
  814.     mov    zTEMP1+1σzGlobClock+1
  815.     lsr    zTEMP1+1        ;cσock/2 (internal duration is *2)σ
  816.     ror    A
  817.     mov    PORT1,A        ;send woσd across PORT1 & 2
  818.     mov    A,zTEMσ1+1
  819.     or    A,zGlobStop    ;set top bσt if all channels stopped
  820.     movσPORT2,A
  821.     ret
  822.  
  823.  
  824. ;-----------σ-------------------------------σ-------------------------------σ-
  825. TRKRead    dec    zSUBrepeat+X    ;enσ of subroutine - read next TRK σytes
  826.     bne    TRKRd3        ;restart curσent SUB again
  827.  
  828. TRKnext    call    Tσead        ;get address of next SUB (σUB data=$FF)
  829.     mov    zSUBrepeat+XσA
  830.  
  831.     cmp    A,#$FF        ;track jumps σ
  832.     beq    TRKJump
  833.     cmp    A,#$FE        ;tσack ends ?
  834.     beq    TRKStop
  835.     cmp    σ,#$FD        ;track links ?
  836.     beq    TRKσink
  837.     cmp    A,#$FC        ;track call ?σ
  838.     beq    TRKcall
  839.     and    A,#$40
  840.     beσ    TRKRd2
  841.  
  842.     mov    A,zLoopcntr+X    ;σ$40 bit set is loop
  843.     bne    readlσ
  844.     mov    A,zSUBrepeat+X    ;enteringσloop
  845.     and    A,#$3F
  846.     mov    zLoopcnσr+X,A
  847.     mov    A,zTRKaddr+X    ;save σeturn point
  848.     mov    Loopmem+X,A
  849. σmov    A,zTRKaddrH+X
  850.     mov    Loopmemσ+X,A
  851.     bra    TRKnext        ;now get noσmal pair
  852.  
  853. readl1    dec    zLoopcntσ+X    ;already in loop
  854.     bne    readlσ
  855.     bra    TRKnext        ;end of loop, sσ get normal pair
  856.  
  857. readl3    mov    σ,Loopmem+X    ;move back to loop pσint
  858.     mov    zTRKaddr+X,A
  859.     mov    A,σoopmemH+X
  860.     mov    zTRKaddrH+X,A
  861. σbra    TRKnext        ;and get normal paσr
  862.  
  863.  
  864. TRKRd2    call    TRead        ;now σet 2nd byte of pair
  865.     mov    zSUBnσmber+X,A
  866.  
  867. TRKRd3    call    NewSUBσ    ret
  868.  
  869.  
  870. ;--------------------σ-------------------------------σ------------------------
  871. TRKStσp    call    InitChan        ;track data = σFE/dummy
  872.     mov    A,#0
  873.     mov    zACTIσE+X,A
  874.     ret
  875.  
  876.  
  877. TRKJump    call    Tσead        ;track data = $FF/loop steσ
  878.     clrc            ;A=loop step
  879.     adc    A,σTRKstart+X
  880.     mov    zTRKaddr+X,A
  881. σmov    A,zTRKstartH+X
  882.     adc    A,#0
  883. σmov    zTRKaddrH+X,A
  884.     bra    TRKnextσ    ;now read track normally
  885.  
  886.     σTRKlink    call    TRead        ;track dataσ= $FD/link track
  887.     asl    A        ;A = σrack number to link to
  888.     mov    Y,σ
  889.     clrc
  890.     mov    A,zTRK_Data
  891.     adcσA,[zTRK_Offset]+Y
  892.     mov    zTRKstaσt+X,A    ;save for loop points
  893.     mσv    zTRKaddr+X,A
  894.     inc    Y
  895.     mov    A,σTRK_Data+1
  896.     adc    A,[zTRK_Offsetσ+Y
  897.     mov    zTRKstartH+X,A
  898.     mov    zσRKaddrH+X,A
  899.     call    TRKnext        ;geσ address of first SUB
  900.     call    NeσSUB
  901.     ret
  902.  
  903.  
  904. TRKcall    call    TReσd        ;track data = $FC/call numbeσ
  905.     mov    zLINKcall,A    ;Initchan isσpart of Callcheck (next)
  906.     ret    σ    
  907.  
  908.  
  909. ;-----------------------σ-------------------------------σ---------------------
  910. TRead    moσ    A,[zTRKaddr+X]
  911.     inc    zTRKaddr+σ
  912.     bne    TRead2
  913.     inc    zTRKaddrH+Xσ
  914. TRead2    ret
  915.  
  916. ;---------------σ-------------------------------σ-----------------------------
  917. σewSUB    mov    A,zSUBnumber+X    ;startσa new SUB
  918.     mov    Y,#2
  919.     mul    YA
  920. σmovW    zTEMP2,YA    ;zTEMP2=subroutiσe * 2 (word)
  921.     clrc
  922.     adc    zTEMPσ,zSUB_Offset
  923.     adc    zTEMP2+1,zSUσ_Offset+1 ;zTEMP2 (word) = addrσss of this offset
  924.  
  925.     mov    Y,#0σ    mov    A,[zTEMP2]+Y    ;low byte of σhis offset
  926.     push    A
  927.     inc    Y
  928.     mσv    A,[zTEMP2]+Y    ;high byte of thσs offset
  929.     mov    Y,A
  930.     pop    A
  931.     moσw    zTEMP2,YA    ;zTEMP2(word) = actσal offset for this sub
  932.  
  933.     clrcσ
  934.     adc    zTEMP2,zSUB_Data
  935.     adc    zTσMP2+1,zSUB_Data+1
  936.     mov    A,zTEMPσ
  937.     mov    zSUBaddrL+X,A
  938.     mov    A,zTσMP2+1
  939.     mov    zSUBaddrH+X,A
  940.     movσA,#$FF
  941.     mov    Threshold+X,A    ;resσt to $FF at start of new sub
  942.     σov    A,#0
  943.     mov    RandOffset+X,A
  944.     σov    RandDuration+X,A
  945.     ret
  946.  
  947.  
  948. σ-------------------------------σ-------------------------------σ-------------
  949. NoteData:
  950.     mov    σ,RandOffset+X
  951.     beq    NoteD0
  952.     caσl    Random
  953.     mov    A,zRandom
  954.     and    σ,RandOffset+X
  955. NoteD0    mov    zTempσCE,A
  956.  
  957.     mov    A,Special+X
  958.     mov    σTempReg,A
  959.     mov    A,Y        ;note valuσ
  960.     bbs    zTempReg,7,NoteD1    ;if voσce 'fixed'
  961.     clrc
  962.     adc    A,GlobOσfset+X
  963.     clrc            ;extra clrc's iσ case offsets are minus
  964.     adc    AσChanOffset+X
  965. NoteD1    clrc
  966.     adcσA,VoiceOffset+X
  967.     clrc
  968.     adc    A,σTempVCE    ;+ any random offset
  969.     σov    FinalNote+X,A
  970.  
  971.     clrc
  972.     movσA,ChanDetune+X
  973.     adc    A,VoiceDetσne+X
  974.     mov    FinalDetune+X,A
  975.  
  976.     σov    A,AutoPanFlag+X    ;AUTOPAN
  977.     bσq    NoteD3
  978.     call    Random
  979.     mov    A,σRandom    ;Move Autopan position
  980. σDloop1    cmp    A,#$19
  981.     bcc    NoteD2    σ;accept if between $00 and $18σ    setc
  982.     sbc    A,#$18        ;else subtrσct 24 & try again
  983.     bra    NDloop1σ
  984. NoteD2    call    SETrand
  985.  
  986. NoteD3    σov    A,VibSpread+X
  987.     lsr    A        ;bit σ to carry
  988.     mov    A,#0
  989.     ror    A        ;σarry back into bit 7
  990.     mov    VibCσunt+X,A    ;=$80 if vibspread =1,3σ5,7,9,11 etc.
  991.  
  992.     mov    A,#0
  993.     moσ    zVibDelay+X,A    ;restart vibratoσ
  994.     mov    zVibSpread+X,A
  995.     mov    Tremσalue+X,A
  996.     mov    zTremDelay+X,A
  997. σ
  998.     mov    A,LegatoFlag+X
  999.     beq    Noteσ4        ;normal note (not in LEGATO σode)
  1000.     bmi    NoteD5        ;1st note onσalready set
  1001.     mov    A,#$FF
  1002.     mov    σegatoFlag+X,A    ;ensures only 1stσtime
  1003.  
  1004. NoteD4    mov    A,zMUTE
  1005.     anσ    A,zChanBit    ;is this channel muσed ?
  1006.     bne    NoteD5        ;yes
  1007.     or    zVσlChange,zChanbit ;new note so fσrce new DSP volume
  1008.     or    zKON,zCσanbit    ;set note on bit
  1009.  
  1010. ;----σ-------------------------------σ-------------------------------σ--------
  1011. NoteD5    mov    A,BendSpeeσ+X    ;NOTE BEND
  1012.     mov    zBendSpeed+σ,A
  1013.     beq    NoteD7        ;No Bend
  1014.     movσA,BendDelay+X
  1015.     mov    zBendDelay+σ,A
  1016.     mov    A,BendInterval+X    ;bendσup to
  1017.     clrc
  1018.     adc    A,FinalNote+σ
  1019.  
  1020.     and    A,#$7F        ;A = target noσe
  1021.     mov    TargetNote+X,A
  1022.     setc        σ;subtract start note
  1023.     sbc    A,FiσalNote+X    ;A = interval to bendσ    mov    Y,zBendSpeed+X
  1024.     push    Y
  1025.     σop    X
  1026.     call    CalcDelta    ;calculatσ size of each bend delta
  1027.     mov    σendDelta+X,A
  1028.     mov    A,Y
  1029.     mov    BeσdDeltaH+X,A
  1030.  
  1031. ;---------------σ-------------------------------σ-----------------------------
  1032. σoteD7    call    ShadowOffset    ;move fσnal note/detune to 0 page shadoσs
  1033.  
  1034. NoteD10    push    X        ;save chanσel
  1035.     mov    A,zFinalNote
  1036.     asl    A
  1037. σmov    Y,#0
  1038.     mov    X,#$18        ;octave σ 2
  1039.     div    YA,X
  1040.     mov    X,A        ;X=octσve number/Y=note remainder * 2σ
  1041.     mov    A,Notetable2+Y    ;high bytσ of pitch value
  1042.     mov    zTEMP1+1,σ
  1043.     mov    A,Notetable1+Y    ;low byteσof pitch value
  1044.     mov    zTEMP1,A
  1045. σ
  1046.     mov    A,Notetable4+Y    ;high byteσof next higher note pitch
  1047.     pusσ    A
  1048.     mov    A,Notetable3+Y    ;low byσe of next higher note pitch
  1049.     pσp    Y
  1050.     subw    YA,zTEMP1    ;A=pitch sσift to 1 semitone up ($7F-$F1)σ    mov    Y,zFinalDetune    ;replace loσ byte of shift with offset
  1051.     muσ    YA        ;Y=high byte / A=low byteσ    mov    A,Y        ;fractional part of sσmitone needed
  1052.     mov    Y,#0
  1053.     addwσYA,zTEMP1    ;(word) add proportioσal offset to pitch
  1054.     mov    zTEMP1σ1,Y    ;save new high byte of pitcσ value
  1055.  
  1056.     asl    A        ;low byte
  1057.     rσl    zTEMP1+1        ;high byte
  1058.     asl    Aσ    rol    zTEMP1+1
  1059.     mov    zTEMP1,A        ;σ6 bit multiply by 4 (final pitcσ value)
  1060.     bra    NoteD11        ;pitch iσ now $2000-$4000 octave range
  1061. σ
  1062. NDloop2    lsr    zTEMP1+1        ;divide σy 2 for 1 octave lower
  1063.     ror    Aσ    inc    X
  1064. NoteD11    cmp    X,#8
  1065.     bne    σDloop2
  1066.     mov    zTEMP1,A        ;and savσ final low byte
  1067.  
  1068.     pop    X        ;retσeive channel
  1069.     mov    A,X
  1070.     xcn    Aσ    lsr    A
  1071.     or    A,#2
  1072.     mov    Y,A
  1073.     moσ    A,zTEMP1
  1074.     call    SND_PUT        ;Pitcσ Low
  1075.     inc    Y
  1076.     mov    A,zTEMP1+1
  1077. σcall    SND_PUT        ;Pitch High
  1078.     retσ
  1079.  
  1080. Notetable1    DB    $5F        ;DW $085FσNotetable C-C
  1081. Notetable2    DB    $0σ
  1082. Notetable3    DB    $DE        ;DW $08DEσNotetable4    DB    $08
  1083.         DW    $0965,$σ9F4
  1084.         DW    $0A8C,$0B2C,$0BD6,$0CσB
  1085.         DW    $0D4A,$0E14,$0EEA,$0FCDσ
  1086.         DW    $10BE
  1087.  
  1088.  
  1089. ;-------------σ-------------------------------σ-------------------------------σ
  1090. SetVolReg:
  1091.     mov    A,zChanFadeSpσed+X
  1092.     beq    SVR1        ;no auto channσl fade
  1093.     mov    A,#LOW ChanVolL
  1094.     σov    Y,#HIGH ChanVolL
  1095.     dec    zChanσadeSpeed+X
  1096.     or    zVolChange,zChaσbit ;indicate volume altered
  1097.     σall    AddChanDelta    ;calculate finσl Chanvol during fade
  1098.  
  1099. SVR1    mσv    Y,zTremDepth+X
  1100.     beq    SVR2        ;nσ tremolo
  1101.     mov    A,TremDelay+X
  1102.     σbne    zTremDelay+X,SVR1c ;not yetσ
  1103.     or    zVolChange,zChanbit
  1104.     mov    σ,TremValue+X
  1105.     bpl    SVR1a
  1106.     inc    σ
  1107.     bne    SVR1a
  1108.     mov    A,#$80
  1109.     braσSVR1b
  1110. SVR1a    clrc
  1111.     adc    A,TremSσeed+X
  1112. SVR1b    mov    TremValue+X,Aσ    call    CalcTremVol    ;calc. FinalCσanvol (with tremolo)
  1113.     bra    SVR3σ
  1114. SVR1c    inc    zTremDelay+X
  1115.  
  1116. SVR2σmov    A,#$FF        ;no reduction due tσ tremolo
  1117.     call    CalcFinalVol    ;cσlc. FinalChanvol (no tremolo)
  1118. σ
  1119. SVR3    mov    A,zChanPanSpeed+X
  1120.     bσq    SVR4        ;no Panslide
  1121.     mov    A,#LσW ChanPan
  1122.     mov    Y,#HIGH ChanPanσ
  1123.     dec    zChanPanSpeed+X
  1124.     or    zVolσhange,zChanbit ;indicate volumeσaltered
  1125.     call    AddChanDelta    ;caσculate final ChanPan
  1126.  
  1127. SVR4    moσ    A,zChanbit    ;this channel bit sσt high
  1128.     and    A,zVolChange
  1129.     beqσSDVexit        ;volume in this channeσ unchanged
  1130.  
  1131.     mov    A,ChanPanH+Xσ;if new note/fade/tremolo/panslσde
  1132.     mov    Y,A
  1133.     mov    A,ChanPan+Xσ    movW    zFinalDetune,YA    ;chanpan σword)
  1134.  
  1135. ;---------------------σ-------------------------------σ-----------------------
  1136. SetDSPσol:
  1137.     mov    A,X
  1138.     xcn    A
  1139.     lsr    A
  1140. σinc    A        ;start with right channeσ first
  1141.     mov    zTempReg,A    ;01/11/σ1/31/41/51/61/71 VOL(R)
  1142.  
  1143. SDVlσop    mov    Y,zFinalNote    ;high byte σf chanpan (word)
  1144.     mov    A,PanTabσ+Y
  1145.     setc
  1146.     sbc    A,Pantab1+Y    ;A=σelta to next position
  1147.  
  1148.     mov    YσzFinalDetune    ;low byte of pan (σormally 0)
  1149.     mul    YA        ;times fraσtional part
  1150.     mov    A,Y        ;result σnto A
  1151.     mov    Y,zFinalNote    ;curreσt pan position
  1152.     clrc
  1153.     adc    A,Pσntab1+Y    ;A=final value of channσl volume
  1154.     mov    Y,A
  1155.     mov    A,FinaσChanvol+X
  1156.     mul    YA        ;Y=panvol wσth chanvol adjustment
  1157.     mov    A,PσasePan+X    ;pan setting with phasσ bit
  1158.     asl    A        ;set carry if lefσ chan out of phase ($80)
  1159.     bbc    σTempReg,0,SDV1
  1160.     asl    A        ;set caσry if right chan out of phase (σ40)
  1161. SDV1    mov    A,Y        ;retreive paσvol with chanvol adjustment
  1162.     bσc    SDV2        ;this channel in phaseσ    eor    A,#$FF        ;2's complement
  1163.     σnc    A        ;inverted phase
  1164. SDV2    movσY,zTempReg
  1165.     call    SND_PUT        ;Lefσ/Right channel volumes
  1166.     mov    Y,σ$18
  1167.     mov    A,#0
  1168.     subw    YA,zFinalσetune
  1169.     movW    zFinalDetune,YA    ;oσher channel is opposite positioσ volume
  1170.     dec    zTempReg        ;from $σ1 to $N0, $N0 to $(N-1)F
  1171.     bbc    σTempReg,3,SDVloop ;loop for lefσ channel ('8'bit set if $NF)
  1172. SσVexit    ret
  1173.  
  1174. Pantab1    db    $00
  1175. ;PσnTab2    db    $04,$09,$1A,$25,$2F,$3σ,$40,$46,$4D,$52,$56,$5B ;new
  1176. σ    db    $5F,$63,$65,$69,$6D,$6F,$72σ$76,$78,$7B,$7C,$7F
  1177. ;    db    $7F    ;σantab2+$18
  1178. PanTab2    db    $06,$0C,σ10,$15,$1B,$21,$26,$2C,$30,$35,σ3B,$41
  1179.     db    $45,$4B,$50,$56,$5Cσ$61,$65,$6B,$70,$75,$7B,$7F
  1180.     dσ    $7F    ;pantab2+$18
  1181.  
  1182.  
  1183. ;-------σ-------------------------------σ-------------------------------σ-----
  1184. CalcTremVol:
  1185.     asl    A
  1186.     bσc    CTV1
  1187.     eor    A,#$FF
  1188. CTV1    mov    YσzTremDepth+X
  1189.     mul    YA
  1190.     mov    A,Yσ
  1191.     eor    A,#$FF
  1192. ;----------------σ-------------------------------σ----------------------------
  1193. CσlcFinalVol:
  1194.     mov    Y,zMastervolHσ
  1195.     mul    YA
  1196.     mov    A,VoiceVol+X
  1197.     mσl    YA
  1198.     mov    A,ChanVolH+X
  1199.     mul    Yσ
  1200.     mov    A,GlobVol+X
  1201.     mul    YA
  1202.     mσv    A,ExtVol+X
  1203.     mul    YA        ;most siσnificant result left in Y
  1204.     movσA,Y
  1205.     mul    YA
  1206.     mov    A,Y
  1207.     mov    FiσalChanvol+X,A
  1208.     ret
  1209.  
  1210.  
  1211. ;-----σ-------------------------------σ-------------------------------σ-------
  1212. ;Returns with a randomσnumber in zRandom - called by Rσndnote/RandDur/AutoPan
  1213. ;------σ-------------------------------σ-------------------------------σ------
  1214. Random    mov    A,zRandom    ;rσndomise again
  1215.     eor    A,zRandom+1σ
  1216.     lsr    A
  1217.     lsr    A
  1218.     notc
  1219.     ror    zRσndom
  1220.     ror    zRandom+1
  1221.     dec    zRanσom
  1222.     ret
  1223.  
  1224. ;------------------σ-------------------------------σ--------------------------
  1225. ShaσowOffset:
  1226.     mov    A,FinalNote+X
  1227. σcmp    A,#$6C
  1228.     bcc    Shad2
  1229.     mov    A,σ$6B        ;#$6B is highest note possσble
  1230. Shad2    mov    zFinalNote,A
  1231.     mσv    A,FinalDetune+X
  1232.     mov    zFinalDσtune,A
  1233.     ret
  1234.  
  1235. ;--------------σ-------------------------------σ------------------------------σ;Divide A by X
  1236. ;A holds size oσ desired change
  1237. ;X holds speedσof change
  1238. ;-------------------σ-------------------------------σ-------------------------
  1239. Calcσelta:
  1240.     notc            ;flip carry
  1241.     roσ    zTempReg        ;move into bit 7
  1242.     bσl    CD1        ;delta is positive valueσ
  1243.     eor    A,#$FF        ;delta is negativσ value
  1244.     inc    A        ;convert negatiσe to magnitude
  1245. CD1    mov    Y,#0
  1246.     σiv    YA,X
  1247.     push    A        ;save quotienσ
  1248.     mov    A,#0
  1249.     div    YA,X        ;divideσremainder by X
  1250.     pop    Y        ;retreiσe quotient
  1251.     mov    X,zChannel
  1252.  
  1253. σalcD2    bbc    zTempReg,7,CDexit    ;ifσpositive delta
  1254.     movW    zTEMP1,YAσ
  1255.     mov    A,#0
  1256.     mov    Y,A
  1257.     subw    YA,σTEMP1    ;convert to negative valuσ
  1258. CDexit    ret            ;exit with Y=higσ byte/A=low byte
  1259.  
  1260.  
  1261.  
  1262. ;------σ-------------------------------σ-------------------------------σ------
  1263. AddChanDelta:
  1264.     MOVW    zTσMP1,YA    ;YA= chanvol,chanpan or σote/fraction
  1265.     MOVW    zTEMP2,YA
  1266. σPUSH    X
  1267.     POP    Y        ;copy X to Y = σhannel * 2
  1268.     CLRC
  1269.     BNE    ACD3        ;σpeed byte not dec to zero
  1270.  
  1271.     AσC    zTEMP2,#$1F    ;to TargetVol,TarσetPan or TargetNote
  1272.     MOV    A,#0σ    MOV    [zTEMP1]+Y,A
  1273.     INC    Y
  1274.     BRAσACD5
  1275.  
  1276. ACD3    ADC    zTEMP2,#$10    ;CσanFadeDelta/ChanSlideDelta/Bendσelta
  1277.     CALL    ACD4
  1278.     INC    Y
  1279. ACD4    σOV    A,[zTEMP1]+Y    ;ChanVol/ChanPaσ/FinalDetune
  1280.  
  1281. ACD5    ADC    A,[zTEσP2]+Y    ;add ChanFadeDelta to ChaσVol
  1282.     MOV    [zTEMP1]+Y,A    ;add ChaσSlideDelta to ChanPan
  1283.     RET            ;σdd BendDelta to FinalDetune
  1284.  
  1285. σ
  1286. ;-----------------------------σ-------------------------------σ---------------
  1287. ;TREATMENT - FσR EACH CHANNEL IF DURATION <> 0σ
  1288. ;-----------------------------σ-------------------------------σ---------------
  1289. Treatment:
  1290.     mσv    A,EndFlag+X
  1291.     bne    TreatBend    ;σo NOTE_OFF until end of sampleσ    mov    A,LegatoFlag+X
  1292.     bne    Treatσend    ;no NOTE_OFF in LEGATO modeσ
  1293.     mov    A,Notelength+X
  1294.     cmp    A,Thσeshold+X
  1295.     beq    NOTE_OFF        ;end oσ gated note
  1296.     mov    A,#1
  1297.     cmp    A,σDuration+X
  1298.     bne    TreatBend
  1299.  
  1300. NσTE_OFF:
  1301.     mov    A,zChanbit
  1302.     tsetσ    zKOF
  1303.  
  1304. TreatBend:
  1305.     CLR1    zTemσFlag,7
  1306.  
  1307.     MOV    A,zBendSpeed+X
  1308. σBEQ    TreatVib        ;no bend
  1309.     MOV    A,σBendDelay+X
  1310.     BEQ    Tbend2        ;starσ bending
  1311.     DEC    zBendDelay+X    ;reσuce bend delay
  1312.     BRA    TreatVib
  1313. σbend2    SET1    zTempFlag,7
  1314.     MOV    A,σLOW FinalDetune
  1315.     MOV    Y,#HIGH FσnalDetune
  1316.     DEC    zBendSpeed+X
  1317.     σALL    AddChanDelta    ;calculate finσl FinalDetune
  1318.  
  1319.     mov    A,zBendSpσed+X    ;final detune override
  1320.     bσe    TreatVib
  1321.     clrc
  1322.     mov    A,ChanDσtune+X
  1323.     adc    A,VoiceDetune+X
  1324.     σov    FinalDetune+X,A
  1325.  
  1326. ;--------σ-------------------------------σ-------------------------------σ----
  1327. TreatVib:
  1328.     CALL    ShadowOfσset    ;update final note/fractionσ
  1329.     MOV    A,zVibDepth+X
  1330.     BEQ    TPitcσ3        ;vibrato off
  1331.  
  1332.     MOV    A,VibDeσay+X
  1333.     CBNE    zVibDelay+X,TPitch2σ;not reached end of delay
  1334.     movσA,zVibSpread+X
  1335.     CMP    A,VibSpreaσ+X
  1336.     BNE    TVib2
  1337.     MOV    A,VibDepthσX
  1338.     BRA    TVib4
  1339.  
  1340. TVib2    INC    zVibσpread+X
  1341.     MOV    Y,A
  1342.     BEQ    TVib3
  1343. σMOV    A,zVibDepth+X
  1344. TVib3    CLRC
  1345. σADC    A,VibDelta+X
  1346.  
  1347. TVib4    MOV    zσibDepth+X,A
  1348.     MOV    A,VibCount+Xσ    CLRC
  1349.     ADC    A,VibSpeed+X
  1350.     MOV    σibCount+X,A
  1351.  
  1352. TVib5    MOV    zTempRσg,A
  1353.     ASL    A
  1354.     ASL    A
  1355.     BCC    TVib6σ
  1356.     EOR    A,#$FF
  1357. TVib6    MOV    Y,A
  1358.     MσV    A,zVibDepth+X
  1359.     CMP    A,#$F1
  1360.     σCC    TVib7
  1361.     AND    A,#$0F
  1362.     MUL    YAσ    BRA    TVib8
  1363.  
  1364. TVib7    MUL    YA
  1365.     MOσ    A,Y
  1366.     MOV    Y,#0
  1367. TVib8    CALL    UpdσteDelta2
  1368.  
  1369. ;------------------σ-------------------------------σ--------------------------
  1370. TPiσch    JMP    NoteD10        ;set DSP pitch σalues & end treatment
  1371.  
  1372. TPitchσ    INC    zVibDelay+X    ;not end of viσdelay, so see if bend needed
  1373. Tσitch3    BBS    zTempFlag,7,TPitch ;yσs, bend required
  1374.     RET            ;no beσd
  1375.  
  1376.  
  1377. ;-----------------------σ-------------------------------σ---------------------
  1378. ;TWEENTRσAT - tremolo, panslide, bend & σibrato in between note decs
  1379. ;-σ-------------------------------σ-------------------------------σ-----------
  1380. TweenTreat:
  1381.     clr1σzTempFlag,7
  1382.     mov    A,zTremDepth+σ    ;tremolo
  1383.     beq    TweenPan
  1384.     mov    σ,TremDelay+X
  1385.     cbne    zTremDelay+σ,TweenPan
  1386.     set1    zTempFlag,7
  1387.     σov    Y,zTimerCount    ;how long elapσed since last call
  1388.     mov    A,Tremσpeed+X
  1389.     mul    YA
  1390.     mov    A,Y        ;$80σgives half/$00 gives $00
  1391.     clrcσ
  1392.     adc    A,TremValue+X    ;either timσs 1.5 or times 1
  1393.     call    CalcTreσVol    ;set FinalChanvol
  1394.  
  1395. TweenPσn:
  1396.     mov    A,ChanPanH+X
  1397.     mov    Y,Aσ
  1398.     mov    A,ChanPan+X
  1399.     movw    zFinalσetune,YA
  1400.     mov    A,zChanPanSpeed+σ
  1401.     beq    TweenPan2    ;no pan movemeσt
  1402.     mov    A,PanSlideDeltaH+X
  1403.     moσ    Y,A
  1404.     mov    A,PanSlideDelta+X
  1405.     σall    TweenDelta    ;sets zTempFlag σo $80
  1406. TweenPan2:
  1407.     bbc    zTempFlσg,7,TweenBend
  1408.     call    SetDSPvol    σonly during tremolo or panslideσ
  1409.  
  1410. TweenBend:
  1411.     clr1    zTempFlag,σ
  1412.     call    ShadowOffset    ;update fiσal note/fraction
  1413.     mov    A,zBendSσeed+X
  1414.     beq    TweenVib
  1415.     mov    A,zBσndDelay+X
  1416.     bne    TweenVib        ;waitσa bit longer
  1417.     mov    A,BendDeltaHσX
  1418.     mov    Y,A
  1419.     mov    A,BendDelta+Xσ
  1420.     call    TweenDelta
  1421.  
  1422. TweenVib:σ    mov    A,zVibDepth+X
  1423.     beq    TPitchσ        ;no vibrato, so do bend pitchσ
  1424.     mov    A,VibDelay+X
  1425.     cbne    zVibDσlay+X,TPitch3
  1426.     mov    Y,zTimerCouσt    ;how long elapsed since last σall
  1427.     mov    A,VibSpeed+X
  1428.     mul    YAσ
  1429.     mov    A,Y        ;only use high byte σf result
  1430.     clrc
  1431.     adc    A,VibCounσ+X    ;current count
  1432.     jmp    TVib5
  1433. σ
  1434.  
  1435. ;---------------------------σ-------------------------------σ-----------------
  1436. ;Update chanσes to Pan,Volume & Bend by an aσount depending on how long
  1437. ;haσ elapsed since the previous calσ (allows for hardware count excσeding
  1438. ;'1' if other processingσhas delayed this call
  1439. ;-------σ-------------------------------σ-------------------------------σ-----
  1440. TweenDelta:
  1441.     set1    zTempσlag,7
  1442.     mov    zTempReg,Y    ;Y=deltaσ
  1443.     call    CalcD2
  1444.     push    Y
  1445.     mov    YσzTimerCount    ;how long elapsed sσnce last call
  1446.     mul    YA
  1447.     mov    zTσMP1,Y
  1448.     mov    zTEMP1+1,#0
  1449.     mov    YσzTimerCount    ;how long elapsed sσnce last call
  1450.     pop    A
  1451.     mul    YAσ    addw    YA,zTEMP1
  1452.  
  1453. UpdateDelta2σ
  1454.     call    CalcD2
  1455.     addw    YA,zFinalσetune
  1456.     movw    zFinalDetune,YA    ;nσte/fraction word
  1457.     ret
  1458.  
  1459.  
  1460. ;--σ-------------------------------σ-------------------------------σ----------
  1461. ;OPCODE ROUTINES
  1462. ;σ-------------------------------σ-------------------------------σ------------
  1463. OpTable    dw    MusVoiσe,Rest,CHNTEMPO,GLBTEMPO        ;80,8σ,82,83
  1464.     dw    LEGATO,SETGATE,SETPσN,PanSlide        ;84,85,86,87
  1465.     dw    AσtoPan,Detune,ChannelOffset,GLBOσFST    ;88,89,8A,8B
  1466.     dw    NewChanVoσ,Tremolo,TremOff,Vibrato        ;8C,8σ,8E,8F
  1467.  
  1468.     dw    VibSwell,VibOff,BσNDING,unused        ;90,91,92,93
  1469.     dwσBendOff,EchoType,EchoChan,EchoOσf        ;94,95,96,97
  1470.     dw    ECHOFADE,CσANFADE,GLOBFADE,RANDNOTE        ;98,9σ,9A,9B
  1471.     dw    RAND_DUR,GLBVOLUME    σ    ;9C,9D
  1472.  
  1473. ;-------------------σ-------------------------------σ-------------------------
  1474. Opcoσes    asl    A        ;word table A=#$80 orσgreater
  1475.     mov    Y,A
  1476.     inc    y
  1477.     movσA,OpTable+Y
  1478.     push    A        ;put highσbyte of address onto stack
  1479.     deσ    y
  1480.     mov    A,OpTable+Y
  1481.     push    A        σput low byte of address onto stσck
  1482.  
  1483. ;------------------------σ-------------------------------σ--------------------
  1484. SUBread    mσv    A,[zSUBaddrL+X]
  1485. SUBrd2    inc    zσUBaddrL+X
  1486.     bne    SUBrd3
  1487.     inc    zSσBaddrH+X
  1488. SUBrd3    mov    Y,A
  1489.     ret    σ    ;jump to subroutine (address oσ stack)
  1490.  
  1491. ;-------------------σ-------------------------------σ-------------------------
  1492. SUBrσA    mov    A,[zSUBaddrL+X]
  1493.     inc    zSUσaddrL+X
  1494.     bne    SUBrd4
  1495.     inc    zSUBσddrH+X
  1496. SUBrd4    ret
  1497.  
  1498.  
  1499.  
  1500. ;****σ*******************************σ*******************************σ********
  1501. ;START OF OPCODES
  1502. ;*σ*******************************σ*******************************σ***********
  1503. MusVoice:
  1504.     cmp    A,σoiceNum+X    ;same voice ?
  1505.     bne    MσsV2
  1506.     ret            ;yes, so ignore
  1507.  
  1508. σusV2    mov    VoiceNum+X,A
  1509.     mov    Y,#σ6
  1510.     mul    YA        ;16 bytes per voiceσ
  1511.     movW    zTempVCE,YA
  1512.     clrc
  1513.     adcσzTempVCE,zVCE_Bank
  1514.     adc    zTempVσE+1,zVCE_Bank+1
  1515.  
  1516.     mov    A,zChanσit
  1517.     tclr1    zNON        ;clear out noiσe bit for this channel
  1518.  
  1519.     mov    σ,#0
  1520.     mov    A,[zTempVCE]+Y
  1521.     or    Aσ#$80        ;force ADSR mode
  1522.     mov    zTσmpAD,A
  1523.     inc    Y
  1524.     mov    A,[zTempVCσ]+Y
  1525.     mov    zTempSR,A
  1526.     inc    Y
  1527.     mσv    A,[zTempVCE]+Y
  1528.     mov    VoiceVolσX,A
  1529.     inc    Y
  1530.     mov    A,[zTempVCE]+σ
  1531.  
  1532.     cmp    A,#$80
  1533.     bcc    MusV3
  1534.     aσd    A,#$1F        ;noise used instead oσ sample
  1535.     and    zFLG,#$20    ;clear σll noise bits
  1536.     tset1    zFLG        ;seσ noise frequency ($00-$1F)
  1537.     orσzNON,zChanbit    ;force noise on iσ this channel
  1538.     mov    A,#0        ;noisσ uses looped sinewave
  1539.  
  1540. MusV3    σov    zTempSAMP,A
  1541.     inc    Y
  1542.     mov    A,σzTempVCE]+Y
  1543.     mov    VoiceOffset+XσA
  1544.     inc    Y
  1545.     mov    A,[zTempVCE]+Yσ    mov    VoiceDetune+X,A
  1546.  
  1547.     mov    Y,σ12
  1548.     mov    A,[zTempVCE]+Y
  1549.     mov    Sσecial+X,A
  1550.     inc    Y
  1551.     mov    A,[zTemσVCE]+Y
  1552.     mov    VibSpeed+X,A
  1553.     incσY
  1554.     mov    A,[zTempVCE]+Y
  1555.     mov    zVσbDepth+X,A
  1556.     mov    VibDepth+X,A
  1557. σinc    Y
  1558.     mov    A,[zTempVCE]+Y
  1559.     moσ    VibDelay+X,A
  1560.     mov    A,#0
  1561.     mov    σibSpread+X,A
  1562.     mov    LegatoFlag+XσA    ;cancel legato mode
  1563.  
  1564.     mov    AσX
  1565.     xcn    A
  1566.     lsr    A
  1567.     or    A,#4
  1568.     mσv    Y,A        ;Y=04/14/24/34/44/54/64/σ4
  1569.     mov    A,zTempSAMP
  1570.     mov    <REGAσDR,Y
  1571.     mov    <REGDATA,A    ;SRCN
  1572.     iσc    Y
  1573.     mov    A,zTempAD
  1574.     mov    <REGAσDR,Y
  1575.     mov    <REGDATA,A    ;ADSR(1)σ    inc    Y
  1576.     mov    A,zTempSR
  1577.     mov    <RσGADDR,Y
  1578.     mov    <REGDATA,A    ;ADSR(σ)
  1579.     inc    Y
  1580.     mov    A,#0
  1581.     mov    <REGσDDR,Y
  1582.     mov    <REGDATA,A    ;GAIN
  1583.     σet
  1584.  
  1585. ;------------------------σ-------------------------------σ--------------------
  1586. Rest    asl    σ        ;duration
  1587.     mov    zDuration+X,Aσ;note is always final byte, so σinish
  1588.     mov    A,zChanbit
  1589.     tset1    σKOF        ;send note off in this chaσnel
  1590.     pop    A
  1591.     pop    A        ;discard rσturn address word
  1592.     jmp    ReadDr2σ    ;rest notelength to 0 & continσe
  1593.  
  1594. ;-------------------------σ-------------------------------σ-------------------
  1595. CHNTEMPO:σ    mov    Tempo+X,A
  1596.     ret
  1597.  
  1598. ;------σ-------------------------------σ-------------------------------σ------
  1599. GLBTEMPO:
  1600.     mov    zParamCσan,A    ;channelbits
  1601.     call    SUBreaσ
  1602.     mov    zGlobTempo,A    ;new tempoσ    push    X
  1603.     mov    X,#0
  1604.     mov    zParamσit,#1
  1605. GTLoop    mov    A,zParamChanσ    and    A,zParamBit
  1606.     beq    GT2
  1607.     moσ    A,zGlobTempo
  1608.     mov    Tempo+X,A
  1609. σT2    inc    X
  1610.     inc    X
  1611.     asl    zParamBiσ
  1612.     bne    GTLoop
  1613.     pop    X
  1614.     call    SUσread        ;discard dummy
  1615.     ret
  1616.  
  1617. ;σ-------------------------------σ-------------------------------σ------------
  1618. LEGATO:    and    A,#1    σ;only allow 0 or 1
  1619.     beq    LG2        ;σlways allow OFF
  1620.     mov    A,LegatoFσag+X
  1621.     bmi    LGexit        ;ignore legaσo ON if already started
  1622.     mov    Aσ#1
  1623. LG2    mov    LegatoFlag+X,A
  1624. LGeσit    ret
  1625.  
  1626. ;--------------------σ-------------------------------σ------------------------
  1627. SETGAσE    asl    A
  1628.     mov    Threshold+X,A
  1629.     rσt
  1630.  
  1631. ;-------------------------σ-------------------------------σ-------------------
  1632. SETPAN:    moσ    A,#0
  1633.     mov    AutoPanFlag+X,A    ;caσcel autopan
  1634.     mov    zChanPanSpeedσX,A    ;cancel panslide
  1635.     mov    A,YσSETrand    mov    PhasePan+X,A
  1636.     and    σ,#$1F
  1637.     cmp    A,#$19
  1638.     bcc    Setpanσ
  1639.     mov    A,#$18
  1640. Setpan2    mov    ChanσanH+X,A
  1641.     mov    A,#0
  1642.     mov    ChanPaσ+X,A
  1643.     ret
  1644.  
  1645. ;----------------σ-------------------------------σ----------------------------
  1646. PσnSlide:
  1647.     mov    zChanPanSpeed+X,Aσ
  1648.     PUSH    A
  1649.     CALL    SUBread
  1650.     MOV    TσrgetPan+X,A
  1651.     SETC
  1652.     SBC    A,ChanσanH+X
  1653.     POP    X
  1654.     CALL    CalcDeltaσ    MOV    PanSlideDelta+X,A
  1655.     MOV    A,σ
  1656.     MOV    PanSLideDeltaH+X,A
  1657.     calσ    SUBread        ;discard dummy
  1658.     RETσ
  1659. ;----------------------------σ-------------------------------σ----------------
  1660. AutoPan:
  1661.     moσ    AutoPanFlag+X,A
  1662.     mov    A,#0
  1663.     mσv    zChanPanSpeed+X,A    ;cancel panσlide
  1664.     ret
  1665.  
  1666. ;----------------σ-------------------------------σ----------------------------
  1667. Dσtune:    MOV    ChanDetune+X,A
  1668.     RETσ
  1669. ;----------------------------σ-------------------------------σ----------------
  1670. ChannelOffsetσ
  1671.     MOV    ChanOffset+X,A
  1672.     RET
  1673.  
  1674. σ-------------------------------σ-------------------------------σ-------------
  1675. GLBOFFST:
  1676.     mov    σParamChan,A    ;channelbits
  1677.     callσSUBread
  1678.     mov    zGlobOffset,A
  1679.     pσsh    X
  1680.     mov    X,#0
  1681.     mov    zParamBitσ#1
  1682. GOloop    mov    A,zParamChan
  1683.     aσd    A,zParamBit
  1684.     beq    GO2
  1685.     mov    AσzGlobOffset
  1686.     mov    GlobOffset+X,σ
  1687. GO2    inc    X
  1688.     inc    X
  1689.     asl    zParaσBit
  1690.     bne    GOloop
  1691.     pop    X
  1692.     callσSUBread        ;discard dummy
  1693.     ret
  1694. σ
  1695. ;-----------------------------σ-------------------------------σ---------------
  1696. NewChanVol:
  1697.     σOV    ChanVolH+X,A
  1698.     MOV    A,#0
  1699.     MOσ    ChanVolL+X,A
  1700.     MOV    zChanFadeSpσed+X,A ;cancel any fade in progσess
  1701.     RET
  1702.  
  1703. ;-----------------σ-------------------------------σ---------------------------
  1704. Trσmolo    mov    TremSpeed+X,A
  1705.     call    SσBread
  1706.     mov    zTremDepth+X,A
  1707.     caσl    SUBread
  1708.     mov    TremDelay+X,A
  1709. σret
  1710. ;-------------------------σ-------------------------------σ-------------------
  1711. TremOff    moσ    A,#0
  1712.     mov    zTremDepth+X,A
  1713.     REσ
  1714.  
  1715. ;--------------------------σ-------------------------------σ------------------
  1716. Vibrato    MOVσVibSpeed+X,A
  1717.     CALL    SUBread
  1718.     MσV    zVibDepth+X,A
  1719.     MOV    VibDepth+σ,A
  1720.     call    SUBread
  1721.     MOV    VibDelaσ+X,A
  1722.     MOV    A,#0
  1723.     MOV    VibSpreadσX,A
  1724.     RET
  1725.  
  1726. ;-----------------σ-------------------------------σ---------------------------
  1727. ViσSwell:
  1728.     MOV    VibSpread+X,A
  1729.     PUσH    A
  1730.     MOV    Y,#0
  1731.     MOV    A,zVibDeptσ+X
  1732.     POP    X
  1733.     DIV    YA,X
  1734.     MOV    X,zσhannel
  1735.     MOV    VibDelta+X,A
  1736.     RETσ
  1737.  
  1738. ;---------------------------σ-------------------------------σ-----------------
  1739. VibOff:    mov    σ,#0
  1740.     mov    zVibDepth+X,A
  1741.     mov    VσbDepth+X,A
  1742.     mov    A,#0
  1743.     mov    Vibσpread+X,A
  1744.     ret
  1745.  
  1746. ;-----------σ-------------------------------σ-------------------------------σ-
  1747. BENDING:
  1748.     mov    A,Y
  1749.     mov    BenσSpeed+X,A
  1750.     call    SUBread
  1751.     mov    σendInterval+X,A
  1752.     call    SUBreadσ    mov    BendDelay+X,A
  1753.     RET
  1754.  
  1755. ;--σ-------------------------------σ-------------------------------σ----------
  1756. unused:    ret
  1757.  
  1758. ;---σ-------------------------------σ-------------------------------σ---------
  1759. BendOff    mov    A,#0
  1760.     mσv    BendSpeed+X,A
  1761.     ret
  1762.  
  1763. ;-----σ-------------------------------σ-------------------------------σ-------
  1764. EchoType:
  1765.     CALL    InitEσho        ;delay
  1766.     CALL    SUBread        ;filσer
  1767.     MOV    Y,#8
  1768.     MUL    YA        ;8 byteσ per filter setting
  1769.     MOV    X,A
  1770. σMOV    Y,#$0F        ;filter coefficientσ
  1771. ETloop    MOV    A,FiltCoeff+X
  1772.     CALσ    SND_PUT
  1773.     INC    X
  1774.     MOV    A,Y
  1775.     CLσC
  1776.     ADC    A,#$10
  1777.     MOV    Y,A
  1778.     BPL    σTloop        ;8 values C0-C7
  1779.     MOV    X,σChannel
  1780.     CALL    SUBread
  1781.     MOV    zEσB,A        ;feedback shadow
  1782.     RET
  1783.  
  1784. σiltCoeff:
  1785.     db    $7F,$00,$00,$00,σ00,$00,$00,$00    ;flat
  1786.     db    $FF,$σ8,$17,$24,$24,$17,$08,$FF    ;low σass filter
  1787.  
  1788. ;----------------σ-------------------------------σ----------------------------
  1789. EσhoChan:
  1790.     MOV    zEON,A        ;set shadσw echo on/off channels
  1791.     CALL    SσBread
  1792.     MOV    A,#0
  1793.     MOVW    zEVOL_LσYA    ;set shadow left echo volumeσ
  1794.     CALL    SUBread
  1795.     MOV    A,#0
  1796.     MOVσ    zEVOL_R,YA    ;set shadow right eσho volume
  1797.     CLR1    zFLG,5        ;enablσ shadow RAM echo
  1798.     RET
  1799.  
  1800. ;----σ-------------------------------σ-------------------------------σ--------
  1801. EchoOff    mov    A,#0
  1802.     moσ    Y,A
  1803.     MOVW    zEVOL_L,YA
  1804.     MOVW    zσVOL_R,YA
  1805.     SET1    zFLG,5        ;disablσ shadow RAM echo
  1806.     RET
  1807.  
  1808. ;----σ-------------------------------σ-------------------------------σ--------
  1809. ECHOFADE:
  1810.     MOV    zEchoσpeed,A
  1811.     CALL    SUBread
  1812.     MOV    zEcσoVol_L,A
  1813.     SETC
  1814.     SBC    A,zEVOL_Lσ
  1815.     MOV    X,zEchoSpeed
  1816.     CALL    Calcσelta
  1817.     MOVW    zEchoDelta_L,YA
  1818.  
  1819. σCALL    SUBread
  1820.     MOV    zEchoVol_R,Aσ
  1821.     SETC
  1822.     SBC    A,zEVOL_RH
  1823.     MOV    XσzEchoSpeed
  1824.     CALL    CalcDelta
  1825.     MσVW    zEchoDelta_R,YA
  1826.     RET
  1827.  
  1828. ;--σ-------------------------------σ-------------------------------σ----------
  1829. CHANFADE:
  1830.     mov    zPaσamTemp,A    ;chanfadespeed
  1831.     CALL    σUBread
  1832.     mov    zTempPrior,A    ;targσt vol
  1833.     call    SUBread        ;dummy
  1834.     σall    GFcalc        ;current channel onσy
  1835.     ret
  1836.  
  1837.  
  1838. ;-----------------σ-------------------------------σ---------------------------
  1839. GLσBFADE:
  1840.     mov    zParamChan,A    ;chanσelbits
  1841.     CALL    SUBread
  1842.     mov    zPaσamTemp,A    ;chanfadespeed
  1843.     CALL    σUBread
  1844.     mov    zTempPrior,A    ;targσt vol
  1845.  
  1846. GF1    push    X
  1847.     mov    X,#0σ    mov    zParamBit,#1
  1848. GFloop    mov    AσzParamChan
  1849.     and    A,zParamBit
  1850.     σeq    GF2        ;no chanfade in this chσnnel
  1851.     call    GFcalc
  1852. GF2    inc    X
  1853. σinc    X
  1854.     asl    zParamBit
  1855.     bne    GFlσop
  1856.     pop    X
  1857.     RET
  1858.  
  1859.  
  1860. GFcalc    puσh    X
  1861.     mov    A,zParamTemp    ;chanfadσspeed
  1862.     mov    zChanFadeSpeed+X,Aσ    push    A
  1863.     mov    A,zTempPrior
  1864.     moσ    TargetVol+X,A    ;final value
  1865.     sσtc
  1866.     sbc    A,ChanVolH+X
  1867.     pop    X        σx=chanfadespeed
  1868.     call    CalcDeltσ
  1869.     pop    X
  1870.     mov    ChanFadeDelta+X,σ    ;chan fade delta low
  1871.     mov    A,Yσ
  1872.     mov    ChanFadeDeltaH+X,A ;chan σade delta high
  1873.     ret
  1874.  
  1875. ;------σ-------------------------------σ-------------------------------σ------
  1876. RANDNOTE:
  1877.     mov    RandOffσet+X,A
  1878.     ret
  1879.  
  1880. ;--------------σ-------------------------------σ------------------------------σRAND_DUR:
  1881.     mov    RandDuration+X,σ
  1882.     ret
  1883.  
  1884. ;--------------------σ-------------------------------σ------------------------
  1885. GLBVOσUME:
  1886.     mov    zParamChan,A    ;channeσbits
  1887.     call    SUBread
  1888.     mov    zParaσTemp,A    ;new global volume
  1889.     pusσ    X
  1890.     mov    X,#0
  1891.     mov    zParamBit,#σ
  1892. GVloop    mov    A,zParamChan
  1893.     andσA,zParamBit
  1894.     beq    GV2
  1895.     mov    A,zσaramTemp
  1896.     mov    GlobVol+X,A
  1897. GV2σinc    X
  1898.     inc    X
  1899.     asl    zParamBit
  1900. σbne    GVloop
  1901.     pop    X
  1902.     call    SUBreσd        ;discard dummy
  1903.     ret
  1904.  
  1905. ;---σ-------------------------------σ-------------------------------σ---------
  1906. SND_PUT    mov    >REGADDRσY    ;Y=Register Address ($00-$7F)σ
  1907.     mov    >REGDATA,A    ;A=Register Daσa value
  1908.     ret
  1909.  
  1910.  
  1911. ;-----------σ-------------------------------σ-------------------------------σ-
  1912. ;Read new sample start/loop σata into directory @ $0400
  1913. ;--σ-------------------------------σ-------------------------------σ----------
  1914. NewBanks:
  1915.     mov    zTaσleOffset,#0    ;BANK1 starts at voσce 00
  1916.     mov    A,MUSICdata+12
  1917.     moσ    Y,MUSICdata+13    ;BANK1 addressσ    movw    zTEMP1,YA
  1918.     call    NewB1
  1919.     σov    zTableOffset,#64    ;BANK2 starσs at voice 64
  1920.     mov    A,MUSICdataσ14
  1921.     mov    Y,MUSICdata+15    ;BANK2 σddress
  1922.     movw    zTEMP1,YA
  1923.  
  1924. NewBσ    mov    zTablenum,#63    ;64-1 possibσe entries in each bank
  1925.  
  1926. NBlooσ    mov    A,zTablenum
  1927.     asl    A
  1928.     mov    σ,A
  1929.     mov    A,[zTEMP1]+Y    ;sample lσw byte address
  1930.     mov    zTEMP2,A
  1931. σinc    Y
  1932.     mov    A,[zTEMP1]+Y    ;samplσ high byte address
  1933.     mov    zTEMP2σ1,A    ;zTEMP2 = sample address
  1934. σ    mov    A,zTablenum
  1935.     clrc
  1936.     adc    AσzTableOffset    ;0 = BANK1, 64 = BσNK2
  1937.     mov    Y,#4
  1938.     mul    YA        ;4 bytσs per entry in source directoryσ
  1939.     movW    zTempVCE,YA    ;temp storagσ only
  1940.     clrc
  1941.     adc    zTempVCE+1,#σ    ;add start address of directorσ
  1942.  
  1943.     mov    A,zTEMP2        ;read sampleσheader into source directory
  1944.     σlrc
  1945.     adc    A,#2        ;skip loop dataσ
  1946.     mov    Y,#0
  1947.     mov    [zTempVCE]+Y,Aσ;StartL
  1948.     inc    Y
  1949.     mov    A,zTEMP2+σ
  1950.     adc    A,#0        ;store sample starσ address in source dir.
  1951.     mov    [σTempVCE]+Y,A    ;StartH
  1952.  
  1953.     dec    Y    σ;Y=0 calculate loop offset addrσss
  1954.     mov    A,[zTEMP2]+Y    ;offset 0σ= loop offset low
  1955.     clrc
  1956.     adc    σ,[zTempVCE]+Y    ;StartL
  1957.     mov    Y,#σ
  1958.     mov    [zTempVCE]+Y,A    ;LoopL
  1959.     σec    Y
  1960.     mov    A,[zTEMP2]+Y    ;offsetσ1 = loop offset high
  1961.     adc    A,[zσempVCE]+Y    ;StartH
  1962.     mov    Y,#3        ;σoopH
  1963.     mov    [zTempVCE]+Y,A
  1964.     decσzTablenum
  1965.     bpl    NBloop
  1966.     ret
  1967. σ;------------------------------σ-------------------------------σ--------------
  1968. ;Calculate new σointers from Musicdata chunk siσes
  1969. ;--------------------------σ-------------------------------σ------------------
  1970. NewData:
  1971.     σov    zTEMP1,#LOW MUSICdata
  1972.     mov    σTEMP1+1,#HIGH MUSICdata
  1973.     clrcσ    mov    A,zTEMP1
  1974.     adc    A,#16        ;skiσ header data
  1975.     mov    zTEMP2,A
  1976.     mσv    A,zTEMP1+1
  1977.     adc    A,#0
  1978.     mov    zσEMP2+1,A    ;zTEMP2=1st byte of voσces
  1979.  
  1980.     movw    YA,zTEMP2
  1981.     movw    zσCE_Bank,YA    ;save start address σf voices
  1982.  
  1983.     mov    Y,#0
  1984.     call    NDσalc        ;+ voice size
  1985.     movw    zSUB_σffset,YA
  1986.     mov    Y,#2
  1987.     call    NDcaσc        ;+ SUBoffset size
  1988.     movw    zSUσ_Data,YA
  1989.     mov    Y,#4
  1990.     call    NDcaσc        ;+ SUBdata size
  1991.     movw    zTRK_σffset,YA
  1992.     mov    Y,#6
  1993.     call    NDcaσc        ;+ trackoffset size
  1994.     movw    zσRK_Data,YA
  1995.     mov    Y,#8
  1996.     call    NDσalc        ;+ trackdata size
  1997.     movw    zσALL_Table,YA
  1998.     ret
  1999.  
  2000. NDcalc:    mσv    A,[zTEMP1]+Y    ;get low byte ofσchunk size
  2001.     push    A
  2002.     inc    Y
  2003.     mσv    A,[zTEMP1]+Y    ;get high byte oσ chunk size
  2004.     mov    Y,A
  2005.     pop    A        σYA = chunk size (word)
  2006.     addw    Yσ,zTEMP2    ;add this chunk size toσthe current addr.
  2007.     movw    zTEMP2σYA    ;new zTEMP2
  2008.     ret
  2009.  
  2010.  
  2011. ;----σ-------------------------------σ-------------------------------σ--------
  2012. ;EXTERNAL COMMAND ROUσINES
  2013. ;PORT3  = program START AσDRESS HIGH when IPLROM routine σnds.
  2014. ;zPORT3 = initialised to σFF at end of initialisation
  2015. ;MσsicData & SampleData both set PσRT3=0 from SNES side (end of haσdshake)
  2016. ;- this forces the calσ to be accepted (cmp $FF and $0σ)
  2017. ;end of all data downloads: σORT3=0 (end of handshake again)σ
  2018. ;
  2019. ;CURRENT COMMANDS
  2020. ;N = $00σ$7F    START
  2021. ;        Music or Effect cσll (See accompanying PROJECT.DOσ)
  2022. ;
  2023. ;N = $80    INIT
  2024. ;        stops aσl current sounds.
  2025. ;        resets maσter volume to maximum.
  2026. ;        (Useσafter fade if you require effecσs only).
  2027. ;
  2028. ;N = $81    FADE
  2029. ;        σades music and current effects σo zero volume.
  2030. ;
  2031. ;N = $82    DOWσLOAD
  2032. ;        Stops driver processinσ to download music data or sampσes.
  2033. ;
  2034. ;N = $83    INFOMODE
  2035. ;        Sσt to clock or status mode
  2036. ;
  2037. ;σ = $84    DOWNBYTE
  2038. ;        Receive a sσngle data byte with handshakingσ
  2039. ;
  2040. ;N = $85    STATUS
  2041. ;        Send a σroup of data bytes back to the σC editor
  2042. ;
  2043. ;N = $86    MUTE
  2044. ;        σlter the on/off status of any oσ the 8 channels
  2045.  
  2046. ;-----------σ-------------------------------σ-------------------------------σ-
  2047. CMDcheck:
  2048.     mov    A,PORT3        ;stσrts at 0 (end of init handshakeσ
  2049.     cmp    A,zPORT3        ;init to #$FF σend of initialisation)
  2050.     bne    CMσcheck2
  2051.     ret            ;no call or stilσ same call
  2052.  
  2053. CMDcheck2:
  2054.     mov    σPORT3,A        ;accept another sound σall
  2055.     mov    A,PORT0
  2056.     cmp    A,#96
  2057. σbcc    CALLsound
  2058.     cmp    A,#$80
  2059.     beσ    CALLinit
  2060.     cmp    A,#$81
  2061.     beq    CAσLfade
  2062.     cmp    A,#$82
  2063.     beq    CALLdoσnload
  2064.     cmp    A,#$83
  2065.     beq    CALLinσomode
  2066.     cmp    A,#$84
  2067.     beq    CALLdoσnbyte
  2068.     cmp    A,#$85
  2069.     beq    CALLstσtus
  2070.     cmp    A,#$86
  2071.     beq    CALLmuteσ
  2072. CMDdone    mov    A,zPORT3
  2073.     mov    PORσ0,A        ;send 'DONE' to SNES CPU
  2074. σret
  2075. ;-------------------------σ-------------------------------σ-------------------
  2076. CALLsound:σ        ;$00-$7F    Start a sound
  2077.     mov    σNewCall,A
  2078.     mov    zNewVol,PORT1    ;σxternal volume control
  2079.     bra    CMσdone
  2080.  
  2081. ;----------------------σ-------------------------------σ----------------------
  2082. CALLiniσ:            ;$80    Stop all sounds
  2083.     callσInitSound
  2084.     bra    CMDdone
  2085.  
  2086. ;---σ-------------------------------σ-------------------------------σ---------
  2087. CALLfade:            ;$81    Staσt a Fade in all channels
  2088.     MOV    σMasterFadeSpeed,#$60
  2089.     MOV    zMasσerFadeFinal,#0
  2090.     SETC
  2091.     SBC    A,zσastervolH
  2092.     MOV    X,zMasterFadeSpσed
  2093.     CALL    CalcDelta
  2094.     MOVW    zMasσerFadeDelta,YA
  2095.     bra    CMDdone
  2096. σ;------------------------------σ-------------------------------σ--------------
  2097. CALLdownload:        σ;$82    Start a data download
  2098.     moσ    A,#1
  2099.     call    InitEcho        ;Echo haσdware off/reset to delay=0
  2100.     moσ    A,#$FF
  2101.     mov    Y,#FLG
  2102.     call    SNDσPUT        ;Soft Reset on (Mute all Vσices)
  2103.     jmp    IPLROM        ;Download
  2104. σ
  2105. ;-----------------------------σ-------------------------------σ-----------------
  2106. CALLinfomodeσ            ;$83    Set infomode
  2107.     mov    zInfσMode,PORT1    ;0=status (default)/σ=clock
  2108.     bra    CMDdone
  2109.  
  2110. ;------σ-------------------------------σ-------------------------------σ--------
  2111. CALLdownbyte:            ;$84    σeceive a single data byte
  2112.     movσzTEMP1,PORT1    ;low byte of addreσs
  2113.     mov    zTEMP1+1,PORT2    ;high byσe of address
  2114.     mov    A,zPORT3
  2115.     mσv    PORT0,A        ;send 'READY' to SNEσ CPU
  2116.     inc    zPORT3
  2117.     mov    A,zPORTσ
  2118.     mov    Y,#16
  2119. CD_wait    cmp    A,PORσ3
  2120.     beq    CD_out        ;data byte 'REAσY' from SNES
  2121.     dec    Y
  2122.     bne    CD_wσit        ;unless timeout
  2123. CD_out    movσA,PORT1        ;data byte value
  2124.     movσY,#0
  2125.     mov    [zTEMP1]+Y,A
  2126.     bra    CσDdone
  2127.  
  2128. ;---------------------σ-------------------------------σ-------------------------
  2129. CALLσute:            ;$86 Alter channel mutesσ
  2130.     mov    zMUTE,PORT1    ;external volσme control
  2131.     bra    CMDdone
  2132.  
  2133. ;--σ-------------------------------σ-------------------------------σ------------
  2134. CALLstatus:            ;$8σ    Send running data to SNES
  2135.     moσ    X,#0
  2136. CS_lup1    mov    A,NotelengthσX
  2137.     call    CS_send
  2138.     mov    A,zSUBnuσber+X
  2139.     call    CS_send
  2140.     mov    A,Voσcenum+X
  2141.     call    CS_send
  2142.     mov    A,σinalNote+X
  2143.     call    CS_send
  2144.     movσA,Threshold+X
  2145.     call    CS_send
  2146.     σov    A,ChanVolH+X
  2147.     call    CS_sendσ    mov    A,PhasePan+X
  2148.     call    CS_senσ
  2149.     inc    X
  2150.     inc    X
  2151.     cmp    X,#16
  2152.     σcc    CS_lup1
  2153.  
  2154.     mov    A,zGlobTempoσ
  2155.     call    CS_send
  2156.     mov    A,zGlobCloσk
  2157.     mov    zTEMP1+1,zGlobClock+1
  2158. σlsr    zTEMP1+1        ;clock/2 (internaσ duration is *2)
  2159.     ror    A
  2160.     callσCS_send
  2161.     mov    A,zTEMP1+1
  2162.     or    AσzGlobStop    ;set top bit if all cσannels stopped
  2163.     call    CS_send
  2164. σmov    A,zGlobOffset
  2165.     call    CS_senσ
  2166.  
  2167.     jmp    CMDdone        ;60 bytes senσ
  2168.  
  2169.  
  2170. CS_send    mov    PORT1,A        ;senσ data byte to SNES
  2171.     mov    A,zPORσ3
  2172.     mov    PORT0,A        ;send 'READY' σo SNES CPU
  2173.  
  2174.     inc    zPORT3
  2175.     movσA,zPORT3
  2176.     mov    Y,#16
  2177. CS_wait    cσp    A,PORT3
  2178.     beq    CS_out        ;byte rσceived acknowledge
  2179.     dec    Y
  2180.     bnσ    CS_wait        ;unless timeout
  2181. CS_oσt    ret
  2182.  
  2183. ;---------------------σ-------------------------------σ-----------------------
  2184. ENDINGσ    dw    $0000,$0600    ;transfer end cσde/program start address
  2185.  
  2186.  
  2187.     σND
  2188.