apucode.asm 76 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326
  1. ;----------------------------------------------------------------------------------------
  2. ;pro tracker (mod) player for the spc700 (c)d4s in 2005
  3. ;----------------------------------------------------------------------------------------
  4. .MEMORYMAP ; Tell WLA that the SPC has RAM at locations ;$0000-$ffff in every bank
  5. SLOTSIZE $10000 ; and that this area is $10000 bytes in size.
  6. DEFAULTSLOT 0 ; There is only a single slot in SNES, other consoles
  7. SLOT 0 $0000 ; may have more slots per bank.
  8. .ENDME
  9. .ROMBANKSIZE $10000 ; Every ROM bank is 64 KBytes in size
  10. .ROMBANKS 1
  11. ;----------------------------------------------------------------------------------------
  12. .BANK 0 SLOT 0
  13. .define SpcCmdUploadSong $f1 ;indicates that a song is to be uploaded
  14. .define SpcCmdUploadSongT1 $f2 ;indicates that data for transfer1 is on apu ports
  15. .define SpcCmdUploadSongT2 $f3 ;indicates that data for transfer2 is on apu ports
  16. .define SpcCmdUploadSongDone $f4 ;indicates that song upload is complete
  17. .define SpcCmdReceiveStream $f5 ;indicates that 65816 wants to stream brr data to spc
  18. .define SpcCmdSubmitStreamNumber $f7 ;indicates that 65816 wants to stream brr data to spc
  19. .define SpcCmdReceiveStreamComplete $f6 ;spc wants to end stream transmission
  20. .define SpcCmdUploadSamplePack $f8 ;indicates that a sample pack is to be uploaded. the rest of the commands are taken from normal song upload
  21. .define SpcCmdUploadSamplePackDone $f9 ;indicates that sample pack upload is complete
  22. .define SpcCmdPlaySoundEffect $fa ;play a sound effect
  23. .define SpcCmdStopSong $fb
  24. .define SpcCmdSetSongSpeed $fc ;set timer speed of mod playback routine
  25. .define SpcCmdSetSongChMask $fd ;song channel mask
  26. .define SpcCmdReportType $fe ;type of data spc should respond with
  27. .define SpcCmdSetSongVolume $ff
  28. .define SpcStreamLatency 7 ;number of frames to load before actually playing sample
  29. .define SpcStreamSampleNumber 33 ;number of dsp sample to use as streamer
  30. .define StreamerTimer0 $00 ;how long to wait before downloading next frame
  31. .define ChannelArray $0
  32. .define ExtSample $20 ;this sample is used for set sample offset effect
  33. .define Stack $ff
  34. .define ApuCodeBaseAdress $300
  35. .define SampleSource $0200 ;$ff bytes long
  36. .define StreamBuffer $fb80 ;480 bytes long
  37. .define HighestPortaPeriod $0071
  38. .define LowestPortaPeriod $0358
  39. .define EchoStartAdress $f8
  40. .define EchoDelay $01
  41. .define SongEffectsUploaded $ef ;flags that indicate whether a song or sample pack have already been uploaded.bit0=song bit1=sample pack. wla is too stupid to recognize a variable here, so we have to use a static one.
  42. ;variables:
  43. ;.........................................................
  44. .enum $60
  45. WaitCounter dw
  46. CurrentPatternPointerLo db
  47. CurrentPatternPointerHi db
  48. InitPatternPointerLo db
  49. InitPatternPointerHi db
  50. PortamentoDownLimitLo db
  51. PortamentoDownLimitHi db
  52. PortamentoUpLimitLo db
  53. PortamentoUpLimitHi db
  54. CurrentChDataLo db
  55. CurrentChDataHi db
  56. TempBuffer1 db
  57. TempBuffer2 db
  58. TempBuffer3 db
  59. TempBuffer4 db
  60. TempBuffer5 db
  61. TempBuffer6 db
  62. TempBuffer7 db
  63. TempBuffer8 db
  64. TempBuffer9 db
  65. TempBuffer10 db
  66. TempVol db
  67. KeyOn db
  68. CurrentChannel db
  69. CurrentVolume db
  70. PitchBufferLo db
  71. PitchBufferHi db
  72. CurrentPatternNumber db
  73. PortamentoSpeedMask db
  74. NotUsedVariable db
  75. CurrentPeriodPointer db
  76. CurrentPeriodPointerHi db
  77. PeriodTablePointerLo db
  78. PeriodTablePointerHi db
  79. SpcDataPointerLo db
  80. SpcDataPointerHi db
  81. ModFilePointerLo db
  82. ModFilePointerHi db
  83. ModFilePointer2Lo db
  84. ModFilePointer2Hi db
  85. ;added variables
  86. ScratchPad1 db
  87. ScratchPad2 db
  88. ScratchPad3 db
  89. PeriodBufferLo db
  90. PeriodBufferHi db
  91. NumberOfPatterns db
  92. PatternSpeed db
  93. NextRowChFadeOuts db ;lower nibble bits0-4:channels to fade out for next row
  94. NextRowChFadeOutTime db ;patternspeed-2
  95. PortamentoLUTLo db ;table for portamento up/down
  96. PortamentoLUTHi db ;table for portamento up/down
  97. TonePortamentoLUTLo db ;table for portamento up/down
  98. TonePortamentoLUTHi db ;table for portamento up/down
  99. CurrentRowPointerLo db
  100. CurrentRowPointerHi db
  101. CurrentLoopPointerLo db
  102. CurrentLoopPointerHi db
  103. LoopCounter db
  104. PatternBreakFlag db ;if bit0 is set, break to next pattern
  105. ;main volume section:
  106. MainVolL db
  107. MainVolR db
  108. EchoVolL db
  109. EchoVolR db
  110. ChannelEnable db
  111. ChannelEchoEnable db
  112. PitchTablePointerLo db
  113. PitchTablePointerHi db
  114. Channel1Array dw
  115. Channel2Array dw
  116. Channel3Array dw
  117. Channel4Array dw
  118. ;apu streaming stuff
  119. StreamState db ;variable for streaming state machine
  120. StreamCurrentBuffer db ;indicates currently active stream buffer out of 8
  121. StreamVolume db
  122. ActiveSoundEffectCh db ;0-3
  123. ModPlayerTimer0 db
  124. SongChannelMask db ;mask variable for 4 song channels. default $0f
  125. SpcReportType db
  126. ModTimecode dw ;timecode for mod currently playing. reset after song upload
  127. SpecialReportCmd db
  128. SoundEffectFlipFlag db
  129. TickSampleStart db ;channel mask to start samples on the next tick. used for delay and retrigger
  130. MusicVol1 db ;mod channel 0,2 volume
  131. MusicVol2 db ;mod channel 1,3 volume
  132. .ende
  133. ;channel variables
  134. .enum $00
  135. ch_instrument db ;00
  136. ch_note db ;01
  137. ch_effect db ;02
  138. ch_effect_data db ;03
  139. ch_finetune db ;04
  140. ch_current_volume db ;05
  141. ch_current_pitch_lo db ;06 this gets updated on portamento etc
  142. ch_current_pitch_hi db ;07 (not directly used in sourcecode)
  143. ch_target_pitch_lo db ;08 (not used at all in sourcecode) target pitch for tone portamento
  144. ch_target_pitch_hi db ;09 (not used at all in sourcecode)
  145. ch_tone_portamento_speed db ;0a
  146. ch_portamento_slide_dir db ;0b bit0 sets up/down
  147. ch_vibrato_command_buffer db ;0c this is a buffer for depth and speed when using vibrato continue
  148. ch_vibrato_position db ;0d
  149. ch_vibrato_tremolo_waveform db ;0e 0=sine, 1=ramp down, 2=square
  150. ch_tremolo_position db ;0f
  151. ch_tremolo_command_buffer db ;10
  152. ch_arpeggio_note_buffer db ;11
  153. ch_tick_delay db ;12
  154. ch_amiga_period_lo db ;13 this is the current amiga period
  155. ch_amiga_period_hi db ;14 (not directly used in sourcecode)
  156. ch_current_amiga_period_lo db ;15 this is the tone portamento target amiga period
  157. ch_current_amiga_period_hi db ;16 (not directly used in sourcecode)
  158. ;next must be the last entry in this array:
  159. ch_current_channelmask db ;last byte in array and mask for channel
  160. .ende
  161. ;.........................................................
  162. .ORGA (ApuCodeBaseAdress-2) ;$2FC
  163. .DW ApuCodeBaseAdress ;spcram copy offset
  164. BootInit:
  165. clrp
  166. mov $f1,#$f0
  167. mov a,#$ff
  168. mov !$fff0,a
  169. mov x,#Stack ;set stack pointer (old: $cf)
  170. mov sp,x
  171. mov a,#$00
  172. mov x,a
  173. jmp !ClearVariables
  174. CopyRight:
  175. .db "matt@dforce3000.de"
  176. CopyRightEnd:
  177. ClearVariables:
  178. mov (x)+,a
  179. cmp x,#$f0
  180. bne ClearVariables
  181. mov MainVolL,#$7f
  182. mov MainVolR,#$7f
  183. mov EchoVolL,#$00
  184. mov EchoVolR,#$00
  185. mov ChannelEnable,#$0f
  186. mov ChannelEchoEnable,#$0f
  187. mov SpcReportType,#0 ;reset report type to void
  188. mov MusicVol1,#$7f ;init volume. narrow stereo, a little bit stereo separation
  189. mov MusicVol2,#$7f
  190. mov SpcDataPointerLo,#(ModFile & $00ff) ;setup mod pointer
  191. mov SpcDataPointerHi,#(ModFile >> 8)
  192. call !ClearAllChannelArray
  193. call !SetupDspRegsAndTimers ;reset dsp regs first.
  194. call !InitVariables ;set up pointers to first pattern
  195. call !UpdateVolEchoVariablesOnly
  196. MainLoop:
  197. mov a,$fd ;clear counter0
  198. MainLoop1:
  199. mov a,$fd ;wait for counter 0 to become zero
  200. beq MainLoop1 ;takes roughly 44 scanlines total
  201. call !MainWaitLoop
  202. call !SendReportData
  203. mov a,$f4 ;check if command present on port0
  204. and a,#$f0
  205. cmp a,#$f0
  206. bne MainLoop ;return to mainloop if there isn't
  207. mov a,$f4 ;get command
  208. and a,#$0f
  209. asl a
  210. mov x,a ;pointer into jump table
  211. jmp [!CommandJumpTable+x]
  212. CommandJumpTable:
  213. .dw CommandVoid ;0
  214. .dw ReceiveSong
  215. .dw CommandVoid
  216. .dw CommandVoid
  217. .dw CommandVoid
  218. .dw ReceiveStream ;5
  219. .dw CommandVoid
  220. .dw CommandVoid
  221. .dw ReceiveSamplePack
  222. .dw CommandVoid
  223. .dw PlaySoundEffect ;10
  224. .dw StopSongStream
  225. .dw SetSongSpeed
  226. .dw SetSongChannelMask
  227. .dw SetReportType
  228. .dw SetSongVolume
  229. ReceiveSong:
  230. ;timers must be reset before receiving a song, else we can't wait properly for the echo buffer to initialize
  231. call !ReceiveSongHandler
  232. call !ClearAllChannelArray
  233. call !SetupSamples ;set up sample offsets
  234. call !SetupDspRegsAndTimers ;reset dsp regs first.
  235. call !InitVariables ;set up pointers to first pattern
  236. call !UpdateVolEchoVariablesOnly
  237. ;return to mainloop:
  238. bra MainLoop
  239. UpdateVolEcho:
  240. call !UpdateVolEchoHandler
  241. bra MainLoop
  242. ResetHandler:
  243. ;clear apu ports:
  244. mov y,#$00
  245. mov $f4,y
  246. mov $f5,y
  247. mov $f6,y
  248. mov $f7,y
  249. ;clear dsp regs:
  250. mov a,#$6c
  251. mov y,#$e0 ;reset dsp, mute on, echo off
  252. movw $f2,ya
  253. mov a,#$0c
  254. movw $f2,ya
  255. mov a,#$1c
  256. movw $f2,ya
  257. mov a,#$2c
  258. movw $f2,ya
  259. mov a,#$3c
  260. movw $f2,ya
  261. mov a,#$4c
  262. movw $f2,ya
  263. mov y,#$ff
  264. mov a,#$5c
  265. movw $f2,ya
  266. mov y,#$00
  267. mov a,#$0d
  268. movw $f2,ya
  269. mov a,#$2d
  270. movw $f2,ya
  271. mov a,#$3d
  272. movw $f2,ya
  273. mov a,#$4d
  274. movw $f2,ya
  275. mov a,#$5d
  276. movw $f2,ya
  277. mov a,#$6d
  278. movw $f2,ya
  279. mov a,#$7d
  280. movw $f2,ya
  281. mov $f1,#$f0
  282. ;jump to ipl rom:
  283. jmp !$ffc0
  284. jmp !$ffc0
  285. MainWaitLoop:
  286. bbs $ef.0,MainWaitLoopSongPresent ;only process song if song has been uploaded before
  287. ret
  288. MainWaitLoopSongPresent:
  289. inc WaitCounter
  290. InnerWaitLoop:
  291. cmp WaitCounter,PatternSpeed ;old #$04 incremet WaitCounter until 4, selfmodying code changes the default speed(command setspeed0x0f) by writing to the second operand
  292. bne UpdateTickBasedEffectsOnly
  293. mov WaitCounter,#$00
  294. mov y,NextRowChFadeOuts
  295. mov a,#$5c
  296. movw $f2,ya
  297. mov a,$fe ;clear 4bit counter
  298. mov y,#2
  299. KofWaitLoop:
  300. mov a,$fe ;wait for 2mS
  301. beq KofWaitLoop
  302. ;**************************************************
  303. dbnz y,KofWaitLoop
  304. call !ProcessNextRow
  305. call !PreTestRow
  306. ret
  307. UpdateTickBasedEffectsOnly:
  308. movw ya,Channel1Array
  309. movw CurrentChDataLo,ya
  310. mov CurrentChannel,#$00
  311. call !CheckForTickBasedEffects
  312. movw ya,Channel2Array
  313. movw CurrentChDataLo,ya
  314. mov CurrentChannel,#$10
  315. call !CheckForTickBasedEffects
  316. movw ya,Channel3Array
  317. movw CurrentChDataLo,ya
  318. mov CurrentChannel,#$20
  319. call !CheckForTickBasedEffects
  320. movw ya,Channel4Array
  321. movw CurrentChDataLo,ya
  322. mov CurrentChannel,#$30
  323. call !CheckForTickBasedEffects
  324. mov a,TickSampleStart
  325. beq UpdateTickBasedEffectsOnlyNoRetrigger
  326. mov $f2,#$4c
  327. mov $f3,a ;retrigger recently started samples
  328. mov TickSampleStart,#0
  329. UpdateTickBasedEffectsOnlyNoRetrigger:
  330. ret
  331. ProcessNextRow:
  332. movw ya,CurrentPatternPointerLo ;mark beginning of current row
  333. movw CurrentRowPointerLo,ya
  334. incw ModTimecode
  335. mov KeyOn,#$00 ;clear key on
  336. movw ya,Channel1Array
  337. movw CurrentChDataLo,ya
  338. mov CurrentChannel,#$00
  339. call !GetDataFromPattern
  340. call !SetVolume
  341. movw ya,Channel2Array
  342. movw CurrentChDataLo,ya
  343. mov CurrentChannel,#$10
  344. call !GetDataFromPattern
  345. call !SetVolume
  346. movw ya,Channel3Array
  347. movw CurrentChDataLo,ya
  348. mov CurrentChannel,#$20
  349. call !GetDataFromPattern
  350. call !SetVolume
  351. movw ya,Channel4Array
  352. movw CurrentChDataLo,ya
  353. mov CurrentChannel,#$30
  354. call !GetDataFromPattern
  355. call !SetVolume
  356. call !KeyOnKeyOff
  357. call !PatternLoopJumper
  358. jmp !GetDataFromPatternCheckPatternPosition
  359. GetDataFromPatternEntryIsVoid:
  360. incw CurrentPatternPointerLo
  361. mov y,#ch_instrument
  362. mov a,#$ff ;store $ff in all 4 channel input buffers
  363. mov [CurrentChDataLo]+y,a
  364. inc y
  365. mov [CurrentChDataLo]+y,a
  366. inc y
  367. mov [CurrentChDataLo]+y,a
  368. inc y
  369. mov [CurrentChDataLo]+y,a
  370. ret
  371. GetDataFromPattern:
  372. mov y,#ch_instrument
  373. mov a,[CurrentChDataLo]+y ;get last rows instrument, pitch and effects
  374. mov TempBuffer1,a
  375. inc y
  376. mov a,[CurrentChDataLo]+y
  377. mov TempBuffer2,a
  378. inc y
  379. mov a,[CurrentChDataLo]+y
  380. mov TempBuffer5,a
  381. inc y
  382. mov a,[CurrentChDataLo]+y
  383. mov TempBuffer6,a
  384. or TempBuffer1,TempBuffer2
  385. or TempBuffer1,TempBuffer5
  386. or TempBuffer1,TempBuffer6 ;check if a note was present
  387. mov a,TempBuffer1
  388. bne GetDataFromPatternEntryContainsNewData
  389. call !GetPitchFromBufferAndSet
  390. GetDataFromPatternEntryContainsNewData:
  391. mov y,#$00
  392. mov a,[CurrentPatternPointerLo]+y
  393. cmp a,#$ff ;compare if channel entry is $ff(skip)
  394. beq GetDataFromPatternEntryIsVoid
  395. ;there is a new note to trigger, copy data from pattern to current channel data buffer:
  396. mov [CurrentChDataLo]+y,a ;copy instrument
  397. inc y
  398. mov a,[CurrentPatternPointerLo]+y ;copy note
  399. mov [CurrentChDataLo]+y,a
  400. inc y
  401. mov a,[CurrentPatternPointerLo]+y ;copy effect
  402. mov [CurrentChDataLo]+y,a
  403. inc y
  404. mov a,[CurrentPatternPointerLo]+y ;copy effect data
  405. mov [CurrentChDataLo]+y,a
  406. incw CurrentPatternPointerLo
  407. incw CurrentPatternPointerLo
  408. incw CurrentPatternPointerLo
  409. incw CurrentPatternPointerLo
  410. mov y,#ch_effect
  411. mov a,[CurrentChDataLo]+y
  412. and a,#$0f
  413. mov TempBuffer1,a
  414. mov y,#ch_effect_data
  415. mov a,[CurrentChDataLo]+y
  416. and a,#$f0
  417. or a,TempBuffer1
  418. cmp a,#$de ;delay sample effect present? if yes, don't trigger sample
  419. beq DontSetNewSample
  420. call !SetNewSample
  421. DontSetNewSample:
  422. ret
  423. SetNewSample:
  424. mov y,#ch_instrument ;a non-present instrument is indicated by $00
  425. mov a,[CurrentChDataLo]+y
  426. beq GetDataFromPatternInstrumentIsVoid
  427. ;trigger new instrument, fetch sample data for current instrument
  428. dec a ;multiply instrument number with 8 to get pointer into sample array
  429. mov y,#$08
  430. mul ya
  431. addw ya,ModFilePointer2Lo
  432. movw TempBuffer1,ya ;tempbuffer1 is now pointer to current sample entry
  433. mov y,#$02 ;get sample finetune
  434. mov a,[TempBuffer1]+y
  435. mov y,#ch_finetune ;save to current channel finetune
  436. mov [CurrentChDataLo]+y,a
  437. mov y,#$03 ;get sample volume
  438. mov a,[TempBuffer1]+y
  439. mov CurrentVolume,a ;save to current volume and current channel volume
  440. mov y,#ch_current_volume
  441. mov [CurrentChDataLo]+y,a
  442. GetDataFromPatternInstrumentIsVoid:
  443. mov y,#ch_note
  444. mov a,[CurrentChDataLo]+y
  445. cmp a,#$ff ;a non-present note is indicated by $ff
  446. beq GetDataFromPatternPeriodIsVoid
  447. mov y,#ch_effect ;check if effect command is $ff
  448. mov a,[CurrentChDataLo]+y
  449. cmp a,#$ff
  450. beq GetDataFromPatternCalculateNewPeriod ;if it is, directly calculate new period (why?)
  451. and a,#$0f ;merge effect command and data to test for finetune command
  452. mov TempBuffer1,a
  453. inc y
  454. mov a,[CurrentChDataLo]+y
  455. and a,#$f0
  456. or a,TempBuffer1
  457. xcn a
  458. cmp a,#$e5 ;finetune
  459. beq FinetuneStep
  460. mov y,#ch_effect
  461. mov a,[CurrentChDataLo]+y ;get current effect
  462. and a,#$0f
  463. cmp a,#$03 ;check if effect is tone portamento
  464. beq GetDataFromPatternPortamento
  465. cmp a,#$05 ;check if effect is tone portamento and volslide
  466. beq GetDataFromPatternPortamento
  467. bra GetDataFromPatternCalculateNewPeriod
  468. FinetuneStep:
  469. call !Finetune
  470. bra GetDataFromPatternCalculateNewPeriod
  471. GetDataFromPatternPortamento:
  472. call !TonePortamento
  473. jmp !GetDataFromPatternCheckEffects
  474. GetDataFromPatternPeriodIsVoid:
  475. jmp !GetDataFromPatternCheckEffects
  476. GetDataFromPatternCalculateNewPeriod:
  477. mov y,#ch_note
  478. mov a,[CurrentChDataLo]+y
  479. mov y,#ch_arpeggio_note_buffer
  480. mov [CurrentChDataLo]+y,a
  481. mov y,a ;put period in y
  482. push y
  483. mov y,#ch_finetune
  484. mov a,[CurrentChDataLo]+y ;calculate finetune
  485. mov y,#$48
  486. mul ya
  487. addw ya,PeriodTablePointerLo
  488. movw CurrentPeriodPointer,ya
  489. pop y ;get corresponding value in 14bit period table
  490. mov a,[CurrentPeriodPointer]+y ;get current period
  491. mov TempBuffer1,a
  492. mov PeriodBufferLo,a
  493. inc y
  494. mov a,[CurrentPeriodPointer]+y
  495. mov TempBuffer2,a
  496. mov PeriodBufferHi,a
  497. ;fetch pitch from pitch table. input: period
  498. mov y,TempBuffer2
  499. mov a,TempBuffer1
  500. addw ya,TempBuffer1 ;multiply by 2
  501. addw ya,PitchTablePointerLo ;add table offset
  502. movw TempBuffer1,ya ;move adress to pointer
  503. mov y,#0
  504. mov a,[TempBuffer1]+y ;get lo pitch byte
  505. mov PitchBufferLo,a ;save new pitch
  506. inc y
  507. mov a,[TempBuffer1]+y
  508. mov PitchBufferHi,a
  509. ;fetch pitch end
  510. mov y,#ch_current_pitch_lo ;save new pitch to array
  511. mov a,PitchBufferLo
  512. mov [CurrentChDataLo]+y,a
  513. inc y
  514. mov a,PitchBufferHi
  515. mov [CurrentChDataLo]+y,a
  516. mov y,#ch_amiga_period_lo ;save new period to array
  517. mov a,PeriodBufferLo
  518. mov [CurrentChDataLo]+y,a
  519. inc y
  520. mov a,PeriodBufferHi
  521. mov [CurrentChDataLo]+y,a
  522. mov y,#ch_vibrato_tremolo_waveform ;check vibrato waveform
  523. mov a,[CurrentChDataLo]+y
  524. cmp a,#$04
  525. bne VibratoRetrigger
  526. mov y,#ch_vibrato_position ;reset vibrato position
  527. mov a,#$00
  528. mov [CurrentChDataLo]+y,a
  529. VibratoRetrigger:
  530. mov y,#ch_vibrato_tremolo_waveform
  531. mov a,[CurrentChDataLo]+y
  532. cmp a,#$40
  533. bne VibratoNoWaveformReset
  534. mov y,#ch_tremolo_position
  535. mov a,#$00
  536. mov [CurrentChDataLo]+y,a
  537. VibratoNoWaveformReset:
  538. mov a,CurrentChannel
  539. or a,#$02
  540. mov x,a
  541. mov y,#ch_current_pitch_lo
  542. mov a,[CurrentChDataLo]+y
  543. mov $f2,x ;set pitch height(hi), dsp reg $x2
  544. mov $f3,a
  545. inc y
  546. inc x
  547. mov a,[CurrentChDataLo]+y
  548. mov $f2,x ;set pitch height(lo), dsp reg $x3
  549. mov $f3,a
  550. inc x
  551. mov y,#ch_instrument ;set source sample number
  552. mov a,[CurrentChDataLo]+y
  553. beq DontUpdateSourceSampleNumber
  554. mov $f2,x
  555. mov $f3,a
  556. inc x
  557. mov $f2,x ;disable adsr, enable gain
  558. mov $f3,#$00 ;old #$0c
  559. inc x
  560. mov $f2,x ;clear adsr2
  561. mov $f3,#$00
  562. inc x
  563. inc x
  564. mov y,#ch_current_channelmask
  565. mov a,[CurrentChDataLo]+y ;trigger note
  566. or a,KeyOn ;set note in key on var
  567. mov KeyOn,a
  568. DontUpdateSourceSampleNumber:
  569. jmp !GetDataFromPatternCheckEffects
  570. GetPitchFromBufferAndSet:
  571. mov a,CurrentChannel
  572. or a,#$02
  573. mov x,a
  574. mov y,#ch_current_pitch_lo
  575. mov a,[CurrentChDataLo]+y
  576. mov $f2,x
  577. mov $f3,a
  578. inc x
  579. inc y
  580. mov a,[CurrentChDataLo]+y
  581. mov $f2,x
  582. mov $f3,a
  583. ret
  584. CheckForTickBasedEffects:
  585. ;check if note cutoff is due
  586. mov y,#ch_effect
  587. mov a,[CurrentChDataLo]+y
  588. cmp a,#$ff
  589. beq GetPitchFromBufferAndSet
  590. ;check for special effects:
  591. and a,#$0f
  592. asl a
  593. mov x,a ;use effect command as pointer into jump table
  594. jmp [!TickBasedEffectJumpTable+x]
  595. TickBasedEffectJumpTable:
  596. .dw TickBasedArpeggio
  597. .dw TickBasedPortamentoUp
  598. .dw TickBasedPortamentoDown
  599. .dw TickBasedTonePortamento
  600. .dw TickBasedVibrato
  601. .dw TickBasedVolslidePorta
  602. .dw VolslideVibrato
  603. .dw TickBasedTremolo
  604. .dw TickBasedVoid
  605. .dw TickBasedVoid
  606. .dw TickbasedVolslide
  607. .dw TickBasedVoid
  608. .dw TickBasedVoid
  609. .dw TickBasedVoid
  610. .dw TickBasedExEffects
  611. .dw TickBasedVoid
  612. TickBasedVoid:
  613. ret
  614. TickBasedExEffects:
  615. mov y,#ch_effect_data
  616. mov a,[CurrentChDataLo]+y ;get ex-effect subtype
  617. and a,#$f0
  618. lsr a
  619. lsr a
  620. lsr a
  621. mov x,a ;use effect command as pointer into jump table
  622. jmp [!TickBasedExEffectJumpTable+x]
  623. TickBasedExEffectJumpTable:
  624. .dw TickBasedExVoid
  625. .dw TickBasedExVoid
  626. .dw TickBasedExVoid
  627. .dw TickBasedExVoid
  628. .dw TickBasedExVoid
  629. .dw TickBasedExVoid
  630. .dw TickBasedExVoid
  631. .dw TickBasedExVoid
  632. .dw TickBasedExVoid
  633. .dw TickBasedExEffectNoteRetrigger
  634. .dw TickBasedExVoid
  635. .dw TickBasedExVoid
  636. .dw TickBasedExEffectNoteCutOff
  637. .dw TickBasedExEffectNoteDelay
  638. .dw TickBasedExVoid
  639. .dw TickBasedExVoid
  640. TickBasedExVoid:
  641. ret
  642. ;check for special effects commands
  643. GetDataFromPatternCheckEffects:
  644. mov y,#ch_effect
  645. mov a,[CurrentChDataLo]+y
  646. cmp a,#$ff ;no effect present?
  647. beq GetPitchFromBufferAndSetLong
  648. and a,#$0f
  649. asl a
  650. mov x,a ;use effect command as pointer into jump table
  651. jmp [!NormalEffectJumpTable+x]
  652. NormalEffectJumpTable:
  653. .dw GetPitchFromBufferAndSet
  654. .dw GetPitchFromBufferAndSet
  655. .dw GetPitchFromBufferAndSet
  656. .dw GetPitchFromBufferAndSet
  657. .dw GetPitchFromBufferAndSet
  658. .dw GetPitchFromBufferAndSet
  659. .dw GetPitchFromBufferAndSet
  660. .dw GetPitchFromBufferAndSet
  661. .dw GetPitchFromBufferAndSet
  662. .dw SetSampleOffset
  663. .dw GetPitchFromBufferAndSet
  664. .dw PositionJump
  665. .dw EffectSetVolume
  666. .dw PatternBreak
  667. .dw GetDataFromPatternCheckExEffects
  668. .dw SetSpeed0x0F
  669. GetPitchFromBufferAndSetLong:
  670. jmp !GetPitchFromBufferAndSet
  671. ;these are the special $Ex effects
  672. GetDataFromPatternCheckExEffects:
  673. mov y,#ch_effect_data
  674. mov a,[CurrentChDataLo]+y
  675. and a,#$f0
  676. mov y,a ;save a
  677. xcn a
  678. asl a
  679. mov x,a ;pointer into jump table
  680. jmp [!ExEffectJumpTable+x]
  681. ExEffectJumpTable:
  682. .dw ExEffectSpecialReportCmd
  683. .dw FinePortamentoUp
  684. .dw FinePortamentoDown
  685. .dw ExEffectVoid
  686. .dw SetVibratoWaveform
  687. .dw Finetune
  688. .dw PatternLoop
  689. .dw ExEffectVoid
  690. .dw ExEffectVoid
  691. .dw EffectNoteRetrigger
  692. .dw FineVolSlideUp
  693. .dw FineVolSlideDown
  694. .dw EffectNoteCutOff
  695. .dw EffectNoteDelay
  696. .dw ExEffectVoid
  697. .dw ExEffectVoid
  698. ExEffectVoid:
  699. ret
  700. TickBasedArpeggio:
  701. mov y,#ch_finetune ;calculate finetune
  702. mov a,[CurrentChDataLo]+y
  703. mov y,#$48
  704. mul ya
  705. addw ya,PeriodTablePointerLo
  706. movw CurrentPeriodPointer,ya
  707. mov y,#ch_current_pitch_lo
  708. mov a,[CurrentChDataLo]+y ;save current pitch to buffer
  709. mov PitchBufferLo,a
  710. inc y
  711. mov a,[CurrentChDataLo]+y
  712. mov PitchBufferHi,a
  713. jmp !ArpeggioToneSelector
  714. TickBasedVolslidePorta:
  715. call !TonePortamentoContinue
  716. jmp !TickbasedVolslide
  717. VolslideVibrato:
  718. call !ContinueVibrato
  719. jmp !TickbasedVolslide
  720. ArpeggioToneSelector:
  721. mov a,WaitCounter ;get waitcounter
  722. mov y,#0 ;clear y
  723. mov x,#3 ;put 3 into x
  724. div ya,x ;divide waitcounter by three
  725. mov TempBuffer1,y ;put remainder(can take values 0-2) into TempBuffer1
  726. cmp TempBuffer1,#$01
  727. beq ArpeggioTone1
  728. cmp TempBuffer1,#$02
  729. beq ArpeggioTone2
  730. cmp TempBuffer1,#$00
  731. beq ArpeggioTone3
  732. ret
  733. ArpeggioTone1:
  734. mov y,#ch_effect_data
  735. mov a,[CurrentChDataLo]+y
  736. xcn a
  737. and a,#$0f
  738. bra ArpeggioCommit
  739. ArpeggioTone2:
  740. mov y,#ch_effect_data
  741. mov a,[CurrentChDataLo]+y
  742. and a,#$0f
  743. bra ArpeggioCommit
  744. ArpeggioTone3:
  745. mov y,#ch_current_pitch_lo ;use current tone as pitch, unchanged
  746. mov a,[CurrentChDataLo]+y
  747. mov TempBuffer1,a
  748. inc y
  749. mov a,[CurrentChDataLo]+y
  750. mov TempBuffer2,a
  751. bra ArpeggioSetPitch
  752. ArpeggioCommit:
  753. asl a
  754. mov TempBuffer1,a
  755. mov y,#ch_arpeggio_note_buffer
  756. mov a,[CurrentChDataLo]+y
  757. clrc
  758. adc a,TempBuffer1
  759. mov y,a
  760. mov a,[CurrentPeriodPointer]+y ;get current period
  761. mov ScratchPad1,a
  762. inc y
  763. mov a,[CurrentPeriodPointer]+y
  764. mov ScratchPad2,a
  765. mov y,ScratchPad2
  766. mov a,ScratchPad1
  767. addw ya,ScratchPad1 ;multiply by 2
  768. addw ya,PitchTablePointerLo ;add table offset
  769. movw ScratchPad1,ya ;move adress to pointer
  770. mov y,#0
  771. mov a,[ScratchPad1]+y ;get lo pitch byte
  772. mov TempBuffer1,a ;save new pitch
  773. inc y
  774. mov a,[ScratchPad1]+y
  775. mov TempBuffer2,a
  776. ArpeggioSetPitch:
  777. mov a,CurrentChannel
  778. or a,#$02
  779. mov $f2,a
  780. mov $f3,TempBuffer1
  781. inc a
  782. mov $f2,a
  783. mov $f3,TempBuffer2
  784. ret
  785. FinePortamentoUp:
  786. cmp WaitCounter,#$00
  787. bne PortamentoExit
  788. mov PortamentoSpeedMask,#$0f ;portamento up, but only with lower nibble of effect value
  789. TickBasedPortamentoUp:
  790. mov a, #(HighestPortaPeriod & $00ff)
  791. mov y, #(HighestPortaPeriod >> 8)
  792. movw TempBuffer5,ya ;put highest slideable period into buffer
  793. mov y,#ch_amiga_period_lo ;get current period
  794. mov a,[CurrentChDataLo]+y
  795. mov TempBuffer1,a ;and save it to temp buffer
  796. inc y
  797. mov a,[CurrentChDataLo]+y
  798. mov TempBuffer2,a
  799. mov y,#ch_effect_data
  800. mov a,[CurrentChDataLo]+y ;get current effect value
  801. and a,PortamentoSpeedMask ;and with mask depeding on normal or finetune portamento
  802. mov y,#$00 ;inverse clear y
  803. movw TempBuffer3,ya ;put ya into tempbuffer3
  804. movw ya,TempBuffer1 ;get current period
  805. subw ya,TempBuffer3 ;substract portamento speed
  806. cmpw ya,TempBuffer5 ;if negative, we've slided too high
  807. bpl PortaUpNoLimit
  808. movw ya,TempBuffer5 ;use limit value if we've slided too high
  809. PortaUpNoLimit:
  810. movw TempBuffer1,ya ;put new pitch to buffer
  811. mov y,#ch_amiga_period_lo ;save back current period
  812. mov a,TempBuffer1
  813. mov [CurrentChDataLo]+y,a
  814. inc y
  815. mov a,TempBuffer2
  816. mov [CurrentChDataLo]+y,a
  817. mov y,TempBuffer2 ;get current period
  818. mov a,TempBuffer1
  819. addw ya,TempBuffer1 ;multiply by 2
  820. addw ya,PitchTablePointerLo ;add table offset
  821. movw TempBuffer3,ya ;move adress to pointer
  822. mov y,#0
  823. mov a,[TempBuffer3]+y ;get lo pitch byte
  824. mov TempBuffer1,a ;save new pitch
  825. inc y
  826. mov a,[TempBuffer3]+y
  827. mov TempBuffer2,a
  828. mov y,#ch_current_pitch_lo ;save new pitch to current pitch and update pitch register
  829. mov a,TempBuffer1
  830. mov [CurrentChDataLo]+y,a
  831. inc y
  832. mov a,TempBuffer2
  833. mov [CurrentChDataLo]+y,a
  834. mov a,CurrentChannel
  835. or a,#$02
  836. mov $f2,a
  837. mov $f3,TempBuffer1
  838. inc a
  839. mov $f2,a
  840. mov $f3,TempBuffer2
  841. PortamentoExit:
  842. mov PortamentoSpeedMask,#$ff
  843. ret
  844. FinePortamentoDown:
  845. cmp WaitCounter,#$00
  846. bne PortamentoExit
  847. mov PortamentoSpeedMask,#$0f
  848. TickBasedPortamentoDown:
  849. mov a, #(LowestPortaPeriod & $00ff)
  850. mov y, #(LowestPortaPeriod >> 8)
  851. movw TempBuffer5,ya ;put lowest slideable period into buffer
  852. mov y,#ch_amiga_period_lo ;get current period
  853. mov a,[CurrentChDataLo]+y
  854. mov TempBuffer1,a ;and save it to temp buffer
  855. inc y
  856. mov a,[CurrentChDataLo]+y
  857. mov TempBuffer2,a
  858. mov y,#ch_effect_data
  859. mov a,[CurrentChDataLo]+y ;get current effect value
  860. and a,PortamentoSpeedMask ;and with mask depeding on normal or finetune portamento
  861. mov y,#$00 ;inverse clear y
  862. addw ya,TempBuffer1 ;add portamento speed
  863. cmpw ya,TempBuffer5 ;if positive, we've slided too high
  864. bmi PortaDownNoLimit
  865. movw ya,TempBuffer5 ;use limit value if we've slided too high
  866. PortaDownNoLimit:
  867. movw TempBuffer1,ya ;put new pitch to buffer
  868. mov y,#ch_amiga_period_lo ;save back current period
  869. mov a,TempBuffer1
  870. mov [CurrentChDataLo]+y,a
  871. inc y
  872. mov a,TempBuffer2
  873. mov [CurrentChDataLo]+y,a
  874. mov y,TempBuffer2 ;get current period
  875. mov a,TempBuffer1
  876. addw ya,TempBuffer1 ;multiply by 2
  877. addw ya,PitchTablePointerLo ;add table offset
  878. movw TempBuffer3,ya ;move adress to pointer
  879. mov y,#0
  880. mov a,[TempBuffer3]+y ;get lo pitch byte
  881. mov TempBuffer1,a ;save new pitch
  882. inc y
  883. mov a,[TempBuffer3]+y
  884. mov TempBuffer2,a
  885. mov y,#ch_current_pitch_lo
  886. mov a,TempBuffer1
  887. mov [CurrentChDataLo]+y,a
  888. inc y
  889. mov a,TempBuffer2
  890. mov [CurrentChDataLo]+y,a
  891. mov a,CurrentChannel
  892. or a,#$02
  893. mov $f2,a
  894. mov $f3,TempBuffer1
  895. inc a
  896. mov $f2,a
  897. mov $f3,TempBuffer2
  898. ret
  899. TonePortamento:
  900. mov y,#ch_note ;get note
  901. mov a,[CurrentChDataLo]+y
  902. mov y,a ;put period in y
  903. push y
  904. mov y,#ch_finetune
  905. mov a,[CurrentChDataLo]+y ;calculate finetune
  906. mov y,#$48
  907. mul ya
  908. addw ya,PeriodTablePointerLo
  909. movw CurrentPeriodPointer,ya
  910. pop y ;get corresponding value in 14bit period table
  911. mov a,[CurrentPeriodPointer]+y ;get current period
  912. mov PeriodBufferLo,a
  913. inc y
  914. mov a,[CurrentPeriodPointer]+y
  915. mov PeriodBufferHi,a
  916. mov y,#ch_current_amiga_period_lo ;this is our target period to slide to
  917. mov a,PeriodBufferLo
  918. mov [CurrentChDataLo]+y,a
  919. inc y
  920. mov a,PeriodBufferHi
  921. mov [CurrentChDataLo]+y,a
  922. mov y,#ch_amiga_period_lo ;get current actual period
  923. mov a,[CurrentChDataLo]+y
  924. mov TempBuffer1,a
  925. inc y
  926. mov a,[CurrentChDataLo]+y
  927. mov TempBuffer2,a
  928. mov y,#ch_portamento_slide_dir
  929. mov a,#$00
  930. mov [CurrentChDataLo]+y,a
  931. movw ya,PeriodBufferLo
  932. cmpw ya,TempBuffer1
  933. beq TonePortamentoEqual ;check if already at target period
  934. bmi TonePortamentoExit ;if plus, the target period is higher(tone is lower) than the current period. slide value must be added in that case
  935. mov y,#ch_portamento_slide_dir ;invert sliding direction
  936. mov a,#$01
  937. mov [CurrentChDataLo]+y,a
  938. TonePortamentoExit:
  939. ret
  940. TonePortamentoEqual:
  941. mov y,#ch_current_amiga_period_lo
  942. mov a,#$00
  943. mov [CurrentChDataLo]+y,a
  944. inc y
  945. mov [CurrentChDataLo]+y,a
  946. ret
  947. TickBasedTonePortamento:
  948. mov y,#ch_effect_data
  949. mov a,[CurrentChDataLo]+y ;get effect data (tone portamento speed value)
  950. beq TonePortamentoContinue ;if zero, continue and dont alter period
  951. mov y,#ch_tone_portamento_speed ;save speed
  952. mov [CurrentChDataLo]+y,a
  953. mov y,#ch_effect_data ;clear effect data
  954. mov a,#$00
  955. mov [CurrentChDataLo]+y,a
  956. TonePortamentoContinue:
  957. mov y,#ch_current_amiga_period_lo ;get target period, put into tempbuffer1
  958. mov a,[CurrentChDataLo]+y
  959. mov TempBuffer1,a
  960. inc y
  961. mov a,[CurrentChDataLo]+y
  962. mov TempBuffer2,a
  963. movw ya,TempBuffer1 ;exit if target period is zero (set before if target period has already been reached
  964. beq TonePortamentoExit
  965. mov y,#ch_tone_portamento_speed
  966. mov a,[CurrentChDataLo]+y ;get current speed value (tone portamento speed)
  967. mov y,#$00 ;clear y
  968. movw TempBuffer3,ya ;put slide amount into tempbuffer3
  969. mov y,#ch_portamento_slide_dir
  970. mov a,[CurrentChDataLo]+y
  971. bne TonePortaSlideDown ;check whether to slide up or down
  972. mov y,#ch_amiga_period_lo ;get current period, put into TempBuffer5
  973. mov a,[CurrentChDataLo]+y
  974. mov TempBuffer5,a
  975. inc y
  976. mov a,[CurrentChDataLo]+y
  977. mov TempBuffer6,a
  978. movw ya,TempBuffer5 ;get current period
  979. subw ya,TempBuffer3 ;substract slidespeed
  980. cmpw ya,TempBuffer1 ;check for overflow
  981. bpl TonePortaSlideDone
  982. mov y,#ch_current_amiga_period_lo ;if overflow occured, clear tone porta target period
  983. mov a,#$00
  984. mov [CurrentChDataLo]+y,a
  985. inc y
  986. mov [CurrentChDataLo]+y,a
  987. movw ya,TempBuffer1 ;and load target period instead
  988. bra TonePortaSlideDone
  989. TonePortaSlideDown:
  990. mov y,#ch_amiga_period_lo ;get current period, put into TempBuffer5
  991. mov a,[CurrentChDataLo]+y
  992. mov TempBuffer5,a
  993. inc y
  994. mov a,[CurrentChDataLo]+y
  995. mov TempBuffer6,a
  996. movw ya,TempBuffer5 ;get current period
  997. addw ya,TempBuffer3 ;substract slidespeed
  998. cmpw ya,TempBuffer1 ;check for overflow
  999. bmi TonePortaSlideDone
  1000. mov y,#ch_current_amiga_period_lo ;if overflow occured, clear tone porta target period
  1001. mov a,#$00
  1002. mov [CurrentChDataLo]+y,a
  1003. inc y
  1004. mov [CurrentChDataLo]+y,a
  1005. movw ya,TempBuffer1 ;and load target period instead
  1006. ; bra TonePortaSlideDone
  1007. TonePortaSlideDone:
  1008. movw TempBuffer1,ya ;save newly calculated period to current period buffer
  1009. mov y,#ch_amiga_period_lo ;save to current period buffer
  1010. mov a,TempBuffer1
  1011. mov [CurrentChDataLo]+y,a
  1012. inc y
  1013. mov a,TempBuffer2
  1014. mov [CurrentChDataLo]+y,a
  1015. ;fetch pitch from pitch table. input: period
  1016. movw ya,TempBuffer1
  1017. addw ya,TempBuffer1 ;multiply by 2
  1018. addw ya,PitchTablePointerLo ;add table offset
  1019. movw TempBuffer1,ya ;move adress to pointer
  1020. mov y,#0
  1021. mov a,[TempBuffer1]+y ;get lo pitch byte
  1022. mov TempBuffer5,a ;save new pitch
  1023. inc y
  1024. mov a,[TempBuffer1]+y
  1025. mov TempBuffer6,a
  1026. mov y,#ch_current_pitch_lo ;save to current pitch buffer
  1027. mov a,TempBuffer5
  1028. mov [CurrentChDataLo]+y,a
  1029. inc y
  1030. mov a,TempBuffer6
  1031. mov [CurrentChDataLo]+y,a
  1032. mov a,CurrentChannel
  1033. or a,#$02
  1034. mov $f2,a ;write to dsp
  1035. mov $f3,TempBuffer5
  1036. inc a
  1037. mov $f2,a
  1038. mov $f3,TempBuffer6
  1039. ret
  1040. TickBasedVibrato:
  1041. mov y,#ch_effect_data
  1042. mov a,[CurrentChDataLo]+y ;if speed & depth are zero, continue vibrato without updating em.
  1043. beq ContinueVibrato
  1044. mov TempBuffer1,a
  1045. mov y,#ch_vibrato_command_buffer ;get vibrato speed & depth buffer
  1046. mov a,[CurrentChDataLo]+y
  1047. mov TempBuffer2,a
  1048. and TempBuffer1,#$0f
  1049. beq VibratoSkipDepthUpdate ;dont update depth if its zero
  1050. and TempBuffer2,#$f0 ;update buffer
  1051. or TempBuffer2,TempBuffer1
  1052. VibratoSkipDepthUpdate:
  1053. mov y,#ch_effect_data
  1054. mov a,[CurrentChDataLo]+y ;get vibrato speed
  1055. mov TempBuffer1,a
  1056. and TempBuffer1,#$f0
  1057. beq VibratoSkipSpeedUpdate ;dont upgrade speed if its zero
  1058. and TempBuffer2,#$0f ;update buffer
  1059. or TempBuffer2,TempBuffer1
  1060. VibratoSkipSpeedUpdate:
  1061. mov y,#ch_vibrato_command_buffer
  1062. mov a,TempBuffer2 ;save back updated vibrato speed & depth
  1063. mov [CurrentChDataLo]+y,a
  1064. ContinueVibrato:
  1065. mov y,#ch_vibrato_position
  1066. mov a,[CurrentChDataLo]+y
  1067. mov TempBuffer2,a ;get current vibrato position, this is our pointer into the vibrato table
  1068. lsr TempBuffer2
  1069. lsr TempBuffer2
  1070. and TempBuffer2,#$1f ;divide by 4 and limit
  1071. mov y,#ch_vibrato_tremolo_waveform
  1072. mov a,[CurrentChDataLo]+y
  1073. and a,#$03 ;select current waveform
  1074. mov TempBuffer3,a
  1075. beq VibratoSelectSine
  1076. asl TempBuffer2 ;multiply table pointer with 8
  1077. asl TempBuffer2
  1078. asl TempBuffer2
  1079. cmp a,#$01
  1080. beq VibratoSelectRampDown
  1081. mov TempBuffer3,#$ff ;this is square vibrato
  1082. bra VibratoSelectSet
  1083. VibratoSelectRampDown:
  1084. mov y,#ch_vibrato_position
  1085. mov a,[CurrentChDataLo]+y ;get current vibrato position
  1086. bpl VibratoSet
  1087. mov TempBuffer3,#$ff
  1088. setc
  1089. sbc TempBuffer3,TempBuffer2
  1090. bra VibratoSelectSet
  1091. VibratoSet:
  1092. mov TempBuffer3,TempBuffer2
  1093. bra VibratoSelectSet
  1094. VibratoSelectSine:
  1095. mov x,TempBuffer2
  1096. mov a,!VibratoTable+x ;access vibrato table
  1097. mov TempBuffer3,a
  1098. VibratoSelectSet:
  1099. mov y,#ch_vibrato_command_buffer
  1100. mov a,[CurrentChDataLo]+y
  1101. and a,#$0f ;get current vibrato depth
  1102. mov y,TempBuffer3
  1103. mul ya ;multiply with selected vibrato position
  1104. movw TempBuffer5,ya
  1105. mov y,#$07
  1106. VibratoDivLoop:
  1107. lsr TempBuffer6 ;divide by 128
  1108. ror TempBuffer5
  1109. dbnz y,VibratoDivLoop
  1110. mov y,#ch_amiga_period_lo ;get current period
  1111. mov a,[CurrentChDataLo]+y
  1112. mov PitchBufferLo,a
  1113. inc y
  1114. mov a,[CurrentChDataLo]+y
  1115. mov PitchBufferHi,a
  1116. mov y,#ch_vibrato_position
  1117. mov a,[CurrentChDataLo]+y ;get vibrato position
  1118. bmi VibratoPosNegative
  1119. movw ya,PitchBufferLo
  1120. subw ya,TempBuffer5
  1121. bra VibratoUpdatePitch
  1122. VibratoPosNegative:
  1123. movw ya,PitchBufferLo
  1124. addw ya,TempBuffer5
  1125. VibratoUpdatePitch:
  1126. movw PitchBufferLo,ya ;this is our new period
  1127. addw ya,PitchBufferLo ;multiply by 2
  1128. addw ya,PitchTablePointerLo ;add table offset
  1129. movw ScratchPad1,ya ;move adress to pointer
  1130. mov y,#0
  1131. mov a,[ScratchPad1]+y ;get lo pitch byte
  1132. mov PitchBufferLo,a ;save new pitch
  1133. inc y
  1134. mov a,[ScratchPad1]+y
  1135. mov PitchBufferHi,a
  1136. mov a,CurrentChannel ;write pitch to dsp
  1137. or a,#$02
  1138. mov $f2,a
  1139. mov $f3,PitchBufferLo
  1140. inc a
  1141. mov $f2,a
  1142. mov $f3,PitchBufferHi
  1143. mov y,#ch_vibrato_command_buffer
  1144. mov a,[CurrentChDataLo]+y
  1145. lsr a
  1146. lsr a
  1147. and a,#$3c
  1148. mov TempBuffer1,a
  1149. mov y,#ch_vibrato_position
  1150. mov a,[CurrentChDataLo]+y
  1151. clrc
  1152. adc a,TempBuffer1
  1153. mov [CurrentChDataLo]+y,a
  1154. ret
  1155. TickBasedTremolo:
  1156. mov y,#ch_effect_data
  1157. mov a,[CurrentChDataLo]+y
  1158. beq TremoloContinue
  1159. mov TempBuffer1,a
  1160. mov y,#ch_tremolo_command_buffer
  1161. mov a,[CurrentChDataLo]+y
  1162. mov TempBuffer2,a
  1163. and TempBuffer1,#$0f
  1164. beq TremoloNoNewSpeed
  1165. and TempBuffer2,#$f0
  1166. or TempBuffer2,TempBuffer1
  1167. TremoloNoNewSpeed:
  1168. mov y,#ch_effect_data
  1169. mov a,[CurrentChDataLo]+y
  1170. mov TempBuffer1,a
  1171. and TempBuffer1,#$f0
  1172. beq TremoloNoNewDepth
  1173. and TempBuffer2,#$0f
  1174. or TempBuffer2,TempBuffer1
  1175. TremoloNoNewDepth:
  1176. mov y,#ch_tremolo_command_buffer
  1177. mov a,TempBuffer2
  1178. mov [CurrentChDataLo]+y,a
  1179. TremoloContinue:
  1180. mov y,#ch_tremolo_position
  1181. mov a,[CurrentChDataLo]+y
  1182. mov TempBuffer2,a
  1183. lsr TempBuffer2
  1184. lsr TempBuffer2
  1185. and TempBuffer2,#$1f
  1186. mov y,#ch_vibrato_tremolo_waveform
  1187. mov a,[CurrentChDataLo]+y
  1188. mov TempBuffer3,a
  1189. lsr TempBuffer3
  1190. lsr TempBuffer3
  1191. lsr TempBuffer3
  1192. lsr TempBuffer3
  1193. and TempBuffer3,#$03
  1194. beq TremolWavSel
  1195. asl TempBuffer2
  1196. asl TempBuffer2
  1197. asl TempBuffer2
  1198. asl TempBuffer2
  1199. cmp TempBuffer3,#$01
  1200. beq TremolWavSel2
  1201. mov TempBuffer3,#$ff
  1202. bra TremoloCommit
  1203. TremolWavSel2:
  1204. mov y,#ch_vibrato_position
  1205. mov a,[CurrentChDataLo]+y
  1206. bpl TremoloCommit2
  1207. mov TempBuffer3,#$ff
  1208. setc
  1209. sbc TempBuffer3,TempBuffer2
  1210. bra TremoloCommit
  1211. TremoloCommit2:
  1212. mov TempBuffer3,TempBuffer2
  1213. bra TremoloCommit
  1214. TremolWavSel:
  1215. mov x,TempBuffer2
  1216. mov a,!VibratoTable+x ;access table #2
  1217. mov TempBuffer3,a
  1218. TremoloCommit:
  1219. mov y,#ch_tremolo_command_buffer
  1220. mov a,[CurrentChDataLo]+y
  1221. and a,#$0f
  1222. mov y,TempBuffer3
  1223. mul ya
  1224. movw TempBuffer5,ya
  1225. mov y,#$06
  1226. TremolDivLoop:
  1227. lsr TempBuffer6
  1228. ror TempBuffer5
  1229. dbnz y,TremolDivLoop
  1230. mov y,#ch_current_volume
  1231. mov a,[CurrentChDataLo]+y
  1232. mov TempBuffer1,a
  1233. mov y,#ch_tremolo_position
  1234. mov a,[CurrentChDataLo]+y
  1235. bmi TremolPosNeg
  1236. clrc
  1237. adc TempBuffer1,TempBuffer5
  1238. bra TremolPosPos
  1239. TremolPosNeg:
  1240. setc
  1241. sbc TempBuffer1,TempBuffer5
  1242. TremolPosPos:
  1243. bpl TremolPosRes
  1244. mov TempBuffer1,#$00
  1245. TremolPosRes:
  1246. cmp TempBuffer1,#$40
  1247. bmi TremolPosRes2
  1248. mov TempBuffer1,#$40
  1249. TremolPosRes2:
  1250. mov a,CurrentChannel
  1251. or a,#$00
  1252. mov $f2,a
  1253. mov $f3,TempBuffer1
  1254. inc a
  1255. mov $f2,a
  1256. mov $f3,TempBuffer1
  1257. mov y,#ch_tremolo_command_buffer
  1258. mov a,[CurrentChDataLo]+y
  1259. lsr a
  1260. lsr a
  1261. and a,#$3c
  1262. mov TempBuffer1,a
  1263. mov y,#ch_tremolo_position
  1264. mov a,[CurrentChDataLo]+y
  1265. clrc
  1266. adc a,TempBuffer1
  1267. mov [CurrentChDataLo]+y,a
  1268. ret
  1269. TickbasedVolslide:
  1270. mov y,#ch_effect_data
  1271. mov a,[CurrentChDataLo]+y
  1272. xcn a
  1273. and a,#$0f
  1274. beq TickbasedVolSlideDown
  1275. mov TempBuffer1,a
  1276. VolSlideUp:
  1277. mov y,#ch_current_volume
  1278. mov a,[CurrentChDataLo]+y
  1279. adc a,TempBuffer1
  1280. cmp a,#$40
  1281. bmi VolSlideUpNoWaveformReset
  1282. mov a,#$40
  1283. VolSlideUpNoWaveformReset:
  1284. mov [CurrentChDataLo]+y,a
  1285. mov CurrentVolume,a
  1286. call !SetVolumeVibrato
  1287. ret
  1288. TickbasedVolSlideDown:
  1289. mov y,#ch_effect_data
  1290. mov a,[CurrentChDataLo]+y
  1291. and a,#$0f
  1292. mov TempBuffer1,a
  1293. VolSlideDown:
  1294. mov y,#ch_current_volume
  1295. mov a,[CurrentChDataLo]+y
  1296. sbc a,TempBuffer1
  1297. bpl VolSlideDownNoReset
  1298. mov a,#$00
  1299. VolSlideDownNoReset:
  1300. mov [CurrentChDataLo]+y,a
  1301. mov CurrentVolume,a
  1302. call !SetVolumeVibrato
  1303. ret
  1304. SetSpeed0x0F:
  1305. mov y,#ch_effect_data
  1306. mov a,[CurrentChDataLo]+y
  1307. mov PatternSpeed,a ;self-modifying code
  1308. dec a
  1309. mov NextRowChFadeOutTime,a
  1310. ret
  1311. SetSampleOffset:
  1312. mov y,#ch_effect_data
  1313. mov a,[CurrentChDataLo]+y
  1314. mov x,a
  1315. mov a,#0
  1316. mov y,#0
  1317. mov TempBuffer3,#$90 ;512/16*9=288, $120
  1318. mov TempBuffer4,#$00
  1319. SetSampleOffsetCalcLoop:
  1320. cmp x,#0
  1321. beq SetSampleOffsetCalcLoopDone
  1322. addw ya,TempBuffer3
  1323. dec x
  1324. bra SetSampleOffsetCalcLoop
  1325. SetSampleOffsetCalcLoopDone:
  1326. movw TempBuffer1,ya
  1327. mov y,#ch_instrument
  1328. mov a,[CurrentChDataLo]+y
  1329. asl a
  1330. asl a
  1331. mov x,a
  1332. mov a,!SampleSource+x ;create a new sample (#3f) that plays with the modified start position
  1333. mov TempBuffer5,a
  1334. mov !(SampleSource+(ExtSample*4)),a
  1335. mov a,!(SampleSource+1)+x
  1336. mov TempBuffer6,a
  1337. mov !(SampleSource+1+(ExtSample*4)),a
  1338. mov a,!(SampleSource+2)+x
  1339. mov !(SampleSource+2+(ExtSample*4)),a
  1340. mov a,!(SampleSource+3)+x
  1341. mov !(SampleSource+3+(ExtSample*4)),a
  1342. movw ya,TempBuffer5
  1343. addw ya,TempBuffer1
  1344. movw TempBuffer5,ya
  1345. mov a,TempBuffer5
  1346. mov !(SampleSource+(ExtSample*4)),a
  1347. mov a,TempBuffer6
  1348. mov !(SampleSource+1+(ExtSample*4)),a
  1349. mov a,CurrentChannel
  1350. or a,#$04
  1351. mov $f2,a
  1352. mov $f3,#ExtSample
  1353. ret
  1354. PositionJump:
  1355. mov y,#ch_effect_data
  1356. mov a,[CurrentChDataLo]+y
  1357. mov CurrentPatternNumber,a
  1358. mov x,a
  1359. mov a,!(ModFile+$fa)+x
  1360. asl a
  1361. mov x,a
  1362. mov a,!(ModFile+$17a)+x
  1363. mov y,a
  1364. mov a,!(ModFile+$17b)+x
  1365. addw ya,InitPatternPointerLo
  1366. movw CurrentPatternPointerLo,ya
  1367. pop a ;need to purge the stack a bit first
  1368. pop a ;else, it would overflow slowly when using the pattern break command constantly
  1369. pop a
  1370. pop a
  1371. pop a
  1372. pop a
  1373. jmp !MainLoop
  1374. ;set channel volume:
  1375. EffectSetVolume:
  1376. mov y,#ch_effect_data
  1377. mov a,[CurrentChDataLo]+y
  1378. mov y,#ch_current_volume
  1379. mov [CurrentChDataLo]+y,a
  1380. mov CurrentVolume,a
  1381. call !SetVolume
  1382. ret
  1383. PatternBreak:
  1384. mov y,#ch_effect_data
  1385. mov a,[CurrentChDataLo]+y ;get break row.
  1386. bne PatternBreakZero ;only breaks to row #0 of next pattern are supported. else dont do anything
  1387. mov PatternBreakFlag,#1 ;set break flag. the actual break gets executed after the current row has been completely processed
  1388. PatternBreakZero:
  1389. ret
  1390. ExEffectSpecialReportCmd:
  1391. inc SpecialReportCmd ;increase special cmd counter.
  1392. ret
  1393. SetVibratoWaveform:
  1394. mov y,#ch_effect_data
  1395. mov a,[CurrentChDataLo]+y
  1396. and a,#$0f
  1397. mov TempBuffer1,a
  1398. mov y,#ch_vibrato_tremolo_waveform ;update vibrato waveform
  1399. mov a,[CurrentChDataLo]+y
  1400. and a,#$f0
  1401. or a,TempBuffer1
  1402. mov [CurrentChDataLo]+y,a
  1403. ret
  1404. Finetune:
  1405. mov y,#ch_effect_data
  1406. mov a,[CurrentChDataLo]+y
  1407. and a,#$0f
  1408. mov y,#ch_finetune ;whats written to chdata $04 here?
  1409. mov [CurrentChDataLo]+y,a
  1410. ret
  1411. FineVolSlideUp:
  1412. mov a,WaitCounter
  1413. bne FineVolSlideUpCancel
  1414. mov y,#ch_effect_data
  1415. mov a,[CurrentChDataLo]+y
  1416. and a,#$0f
  1417. mov TempBuffer1,a
  1418. jmp !VolSlideUp
  1419. FineVolSlideUpCancel:
  1420. ret
  1421. FineVolSlideDown:
  1422. mov a,WaitCounter
  1423. bne FineVolSlideDownCancel
  1424. mov y,#ch_effect_data
  1425. mov a,[CurrentChDataLo]+y
  1426. and a,#$0f
  1427. mov TempBuffer1,a
  1428. jmp !VolSlideDown
  1429. FineVolSlideDownCancel:
  1430. ret
  1431. InitVariables:
  1432. mov WaitCounter,#$00
  1433. mov a,#$06
  1434. mov PatternSpeed,a ;self-modifying code
  1435. dec a
  1436. mov NextRowChFadeOutTime,a
  1437. mov LoopCounter,#0
  1438. mov CurrentPatternNumber,#$00
  1439. mov PortamentoSpeedMask,#$ff
  1440. mov a,!(ModFile+$f8) ;$13d3
  1441. mov NumberOfPatterns,a
  1442. mov TempBuffer1,#$fc ;initial relative adress of pattern tables
  1443. mov TempBuffer2,#$01
  1444. movw ya,ModFilePointerLo
  1445. movw ModFilePointer2Lo,ya
  1446. addw ya,TempBuffer1
  1447. movw CurrentPatternPointerLo,ya
  1448. movw InitPatternPointerLo,ya
  1449. movw CurrentLoopPointerLo,ya
  1450. mov a,!(ModFile+$fa) ;load initial pattern.
  1451. asl a
  1452. mov x,a
  1453. mov a,!(ModFile+$17a)+x ;get pointer to pattern
  1454. mov y,a
  1455. mov a,!(ModFile+$17b)+x
  1456. addw ya,InitPatternPointerLo
  1457. movw CurrentPatternPointerLo,ya
  1458. mov a,#(PeriodTable & $00ff) ;set pointer to amiga period table
  1459. mov PeriodTablePointerLo,a
  1460. mov a,#(PeriodTable >> 8)
  1461. mov PeriodTablePointerHi,a
  1462. mov a,#(PitchTable & $00ff) ;set pointer to snes pitch table
  1463. mov PitchTablePointerLo,a
  1464. mov a,#(PitchTable >> 8)
  1465. mov PitchTablePointerHi,a
  1466. mov PatternBreakFlag,#0
  1467. mov SpecialReportCmd,#0
  1468. ret
  1469. PortamentoDownLimit:
  1470. .dw $01e3
  1471. ;set reset some dsp registers:
  1472. SetupDspRegsAndTimers:
  1473. mov $f1,#$00 ;stop timers
  1474. mov a,$fd ;clear 4bit counters
  1475. mov a,$fe ;clear 4bit counters
  1476. mov a,$ff ;clear 4bit counters
  1477. mov SongChannelMask,#$0f ;enable all 4 mod channels
  1478. mov ModPlayerTimer0,#$a0
  1479. mov $fa,ModPlayerTimer0 ;20 milliSeconds on timer 0
  1480. mov $fb,#$10 ;2 milliSeconds on timer 1
  1481. nop
  1482. nop
  1483. mov $f1,#$03 ;start timer(s)
  1484. mov a,#$00 ;clear all dsp regs
  1485. mov x,a
  1486. DspRegClearLoop:
  1487. cmp x,#$6c
  1488. bne DspRegClearLoopEchoSkip
  1489. mov $f2,x ;disable echo
  1490. mov $f3,#$20
  1491. inc x
  1492. DspRegClearLoopEchoSkip:
  1493. mov $f2,x
  1494. mov $f3,a
  1495. inc x
  1496. bpl DspRegClearLoop
  1497. mov $f2,#$5d ;setup dsp regs
  1498. mov $f3,#(SampleSource >> 8) ;this is the sample info loaction (dir)
  1499. mov $f2,#$6c
  1500. mov $f3,#$20
  1501. mov $f2,#$0c ;set master volume
  1502. mov $f3,MainVolL
  1503. mov $f2,#$1c
  1504. mov $f3,MainVolR
  1505. mov $f2,#$3d
  1506. mov $f3,#$00
  1507. mov $f2,#$7c
  1508. mov $f3,a
  1509. ;setup echo stuff:
  1510. ;set filter:
  1511. mov $f2,#$0f ;fir
  1512. mov $f3,#$30
  1513. mov $f2,#$1f ;fir
  1514. mov $f3,#$00
  1515. mov $f2,#$2f ;fir
  1516. mov $f3,#$00
  1517. mov $f2,#$3f ;fir
  1518. mov $f3,#$00
  1519. mov $f2,#$4f ;fir
  1520. mov $f3,#$00
  1521. mov $f2,#$5f ;fir
  1522. mov $f3,#$00
  1523. mov $f2,#$6f ;fir
  1524. mov $f3,#$20
  1525. mov $f2,#$7f ;fir
  1526. mov $f3,#$30
  1527. ;setup adsr on channels 1-4:
  1528. mov a,CurrentChannel
  1529. push a
  1530. mov CurrentChannel,#$00 ;channel 1
  1531. call !SetupAdsr
  1532. mov CurrentChannel,#$10 ;channel 2
  1533. call !SetupAdsr
  1534. mov CurrentChannel,#$20 ;channel 3
  1535. call !SetupAdsr
  1536. mov CurrentChannel,#$30 ;channel 4
  1537. call !SetupAdsr
  1538. pop a
  1539. ret
  1540. SetupAdsr:
  1541. mov a,#$05 ;dsp reg $x5 (adsr1)
  1542. or a,CurrentChannel ;or with channel number
  1543. mov x,a
  1544. mov $f2,x ;set adsr 1 (winter gold example: $dc) new value: $cb (slower attack an decay)
  1545. mov $f3,#$0e ;old #$0c
  1546. inc x
  1547. mov $f2,x ;set adsr 2 (winter gold example: $2d) new value: $36 (longer release)
  1548. mov $f3,#$2d ;old #$2d
  1549. inc x
  1550. mov a,x
  1551. and a,#$f0 ;only get channel, not register
  1552. mov x,a
  1553. mov a,#$40
  1554. ret
  1555. SetupSamples:
  1556. mov x,#$00
  1557. mov y,#$00
  1558. SetupSamplesLoop:
  1559. inc y
  1560. mov a,[ModFilePointerLo]+y ;get sample relative adress low
  1561. dec y
  1562. clrc
  1563. adc a,ModFilePointerLo ;add modfile position
  1564. mov !(SampleSource+4)+x,a ;store in dsp sample area
  1565. mov a,[ModFilePointerLo]+y ;get sample relative adress hi
  1566. adc a,ModFilePointerHi ;add modfile position, with carry from previous add
  1567. mov !(SampleSource+5)+x,a ;store in dsp sample area
  1568. inc y
  1569. inc y
  1570. inc y
  1571. inc y
  1572. ;repeat the same with loop adress:
  1573. inc y
  1574. mov a,[ModFilePointerLo]+y ;get sample relative adress low
  1575. dec y
  1576. clrc
  1577. adc a,ModFilePointerLo ;add modfile position
  1578. mov !(SampleSource+6)+x,a ;store in dsp sample area
  1579. mov a,[ModFilePointerLo]+y ;get sample relative adress hi
  1580. adc a,ModFilePointerHi ;add modfile position, with carry from previous add
  1581. mov !(SampleSource+7)+x,a ;store in dsp sample area
  1582. inc y
  1583. inc y
  1584. inc y
  1585. inc y
  1586. inc x
  1587. inc x
  1588. inc x
  1589. inc x
  1590. cmp x,#$7c
  1591. bne SetupSamplesLoop
  1592. ret
  1593. ;old:
  1594. clrc
  1595. mov a,!(ModFile+1)+x ;get sample location $12dc
  1596. adc a,#(ModFile & $00ff) ;add #$12db
  1597. mov !(SampleSource+4)+y,a ;store in dsp sample area
  1598. mov a,!ModFile+x
  1599. adc a,#(ModFile >> 8)
  1600. mov !(SampleSource+5)+y,a
  1601. inc x
  1602. inc x
  1603. inc x
  1604. inc x
  1605. clrc
  1606. mov a,!(ModFile+1)+x
  1607. adc a,#(ModFile & $00ff)
  1608. mov !(SampleSource+6)+y,a
  1609. mov a,!ModFile+x
  1610. adc a,#(ModFile >> 8)
  1611. mov !(SampleSource+7)+y,a
  1612. inc x
  1613. inc x
  1614. inc x
  1615. inc x
  1616. inc y
  1617. inc y
  1618. inc y
  1619. inc y
  1620. cmp y,#$7c
  1621. bne SetupSamplesLoop
  1622. ret
  1623. ;setup stream sample adress, sample #33
  1624. SetupStreamSampleAdress:
  1625. mov a,#SpcStreamSampleNumber ;get number of sample to use
  1626. asl a ;multiply by 4
  1627. asl a
  1628. mov y,a ;pointer into sample source table
  1629. mov a,#(StreamBuffer & $00ff) ;get 1st stream buffer adress
  1630. mov !(SampleSource)+y,a ;store in dsp sample area
  1631. mov !(SampleSource+2)+y,a
  1632. mov a,#(StreamBuffer >> 8)
  1633. mov !(SampleSource+1)+y,a
  1634. mov !(SampleSource+3)+y,a
  1635. ret
  1636. KeyOnKeyOff:
  1637. mov y,#0
  1638. mov a,#$5c
  1639. movw $f2,ya
  1640. mov $f2,#$4c
  1641. mov a,KeyOn
  1642. and a,SongChannelMask
  1643. mov $f3,a
  1644. ret
  1645. CutOffChannelGain:
  1646. mov a,#$07 ;select GAIN dsp reg
  1647. or a,CurrentChannel ;
  1648. mov $f2,a ;set gain (winter gold example: $3d)
  1649. mov $f3,#%10011111 ;decrease volume, 8mS ;old #%10111111
  1650. mov y,#ch_current_volume
  1651. mov a,#0 ;clear volume
  1652. mov [CurrentChDataLo]+y,a
  1653. ret ;return
  1654. SetVolumeVibrato:
  1655. ;set channel mod volume
  1656. mov a,#$07 ;select GAIN dsp reg
  1657. or a,CurrentChannel ;
  1658. mov $f2,a ;set gain
  1659. mov a,CurrentVolume
  1660. and a,#$7f ;set direct gain mode
  1661. mov $f3,a
  1662. ;set channel global volume
  1663. mov a,CurrentChannel ;check active channel
  1664. cmp a,#0
  1665. beq SetVolumeLeftCh
  1666. cmp a,#$20
  1667. beq SetVolumeLeftCh
  1668. mov y,MusicVol1
  1669. movw $f2,ya
  1670. inc a
  1671. mov y,MusicVol2
  1672. movw $f2,ya
  1673. ret
  1674. SetVolume:
  1675. ;set channel mod volume
  1676. mov a,#$07 ;select GAIN dsp reg
  1677. or a,CurrentChannel ;
  1678. mov $f2,a ;set gain
  1679. mov y,#ch_current_volume
  1680. mov a,[CurrentChDataLo]+y
  1681. and a,#$7f ;set direct gain mode
  1682. mov $f3,a
  1683. ;set channel global volume
  1684. mov a,CurrentChannel ;check active channel
  1685. cmp a,#0
  1686. beq SetVolumeLeftCh
  1687. cmp a,#$20
  1688. beq SetVolumeLeftCh
  1689. mov y,MusicVol1
  1690. movw $f2,ya
  1691. inc a
  1692. mov y,MusicVol2
  1693. movw $f2,ya
  1694. ret
  1695. SetVolumeLeftCh:
  1696. mov y,MusicVol2
  1697. movw $f2,ya
  1698. inc a
  1699. mov y,MusicVol1
  1700. movw $f2,ya
  1701. ret
  1702. mov a,CurrentChannel ;save current volume
  1703. mov $f2,a
  1704. mov a,$f3
  1705. mov TempVol,a
  1706. SetVolumeLoop:
  1707. cmp CurrentVolume,TempVol ;check if bigger or smaller
  1708. beq SetVolumeExit
  1709. bmi SetVolumeDec ;branch if old value is bigger than new
  1710. inc TempVol
  1711. mov a,CurrentChannel ;check active channel
  1712. mov y,TempVol
  1713. movw $f2,ya
  1714. inc a
  1715. movw $f2,ya
  1716. bra SetVolumeLoop
  1717. SetVolumeDec:
  1718. dec TempVol
  1719. mov a,CurrentChannel ;check active channel
  1720. mov y,TempVol
  1721. movw $f2,ya
  1722. inc a
  1723. movw $f2,ya
  1724. bra SetVolumeLoop
  1725. SetVolumeExit:
  1726. ret
  1727. PreTestRow:
  1728. mov y,#$00
  1729. mov NextRowChFadeOuts,#$00
  1730. mov CurrentChannel,#$01
  1731. call !PreTestChannel
  1732. mov CurrentChannel,#$02
  1733. call !PreTestChannel
  1734. mov CurrentChannel,#$04
  1735. call !PreTestChannel
  1736. mov CurrentChannel,#$08
  1737. jmp !PreTestChannel
  1738. PreTestChannel:
  1739. mov a,[CurrentPatternPointerLo]+y
  1740. cmp a,#$00
  1741. beq PreTestChannelIsEffectOnly
  1742. cmp a,#$ff ;compare if channel entry is $ff(skip)
  1743. beq PreTestChannelIsVoid
  1744. inc y ;check if a period is present
  1745. mov a,[CurrentPatternPointerLo]+y
  1746. cmp a,#$ff
  1747. beq PreTestChannelIsEffectOnly2
  1748. inc y
  1749. mov a,[CurrentPatternPointerLo]+y
  1750. cmp a,#3 ;check if tone portamento (which doesnt actually play a new note, so the old one must not be muted)
  1751. beq PreTestChannelIsEffectOnly3
  1752. and a,#$0f
  1753. mov TempBuffer1,a
  1754. inc y
  1755. mov a,[CurrentPatternPointerLo]+y
  1756. dec y
  1757. and a,#$f0
  1758. or a,TempBuffer1
  1759. cmp a,#$de ;delay sample effect present? if yes, don't trigger sample
  1760. beq PreTestChannelIsEffectOnly3
  1761. mov a,NextRowChFadeOuts
  1762. or a,CurrentChannel ;if theres a note in the next row on this channel, set flag to fade it out before the next row gets processed
  1763. mov NextRowChFadeOuts,a
  1764. bra PreTestChannelIsEffectOnly3
  1765. PreTestChannelIsEffectOnly:
  1766. inc y ;if theres a note, the pattern data entry is 4 bytes long
  1767. PreTestChannelIsEffectOnly2:
  1768. inc y
  1769. PreTestChannelIsEffectOnly3:
  1770. inc y
  1771. PreTestChannelIsVoid:
  1772. inc y
  1773. ret
  1774. PatternLoop:
  1775. ;get effect value
  1776. mov y,#ch_effect_data
  1777. mov a,[CurrentChDataLo]+y ;get current effect value
  1778. and a,#$0f ;and $0f
  1779. bne PatternLoopDontSetLoopPoint
  1780. ;effect value is 0, set loop point:
  1781. movw ya,CurrentRowPointerLo
  1782. movw CurrentLoopPointerLo,ya
  1783. ret
  1784. ;effect value is not 0, check if we are in an active loop
  1785. PatternLoopDontSetLoopPoint:
  1786. mov a,LoopCounter ;check if loop is in progress, must be reset by loop jumper after loop repeat has been finished.
  1787. and a,#$20
  1788. bne PatternLoopDontSetLoopPointButLoop
  1789. ;we arent in a loop, set loop count:
  1790. mov y,#ch_effect_data
  1791. mov a,[CurrentChDataLo]+y ;get current effect value
  1792. and a,#$0f ;and $0f
  1793. or a,#$30 ;set "in loop"-flag and "do jump"-flag
  1794. mov LoopCounter,a
  1795. ret
  1796. PatternLoopDontSetLoopPointButLoop:
  1797. ;we are in a loop, just jump:
  1798. mov a,LoopCounter
  1799. and a,#$0f
  1800. dec a
  1801. mov LoopCounter,a
  1802. beq PatternLoopFinished
  1803. ;do another loop jump
  1804. or LoopCounter,#$30
  1805. PatternLoopFinished:
  1806. ret
  1807. PatternLoopJumper:
  1808. mov a,LoopCounter
  1809. and a,#%00010000
  1810. beq PatternLoopJumperNoJump
  1811. movw ya,CurrentLoopPointerLo
  1812. movw CurrentPatternPointerLo,ya
  1813. mov a,LoopCounter
  1814. and a,#%11101111
  1815. mov LoopCounter,a
  1816. PatternLoopJumperNoJump:
  1817. ret
  1818. EffectNoteRetrigger:
  1819. EffectNoteDelay:
  1820. EffectNoteCutOff:
  1821. mov y,#ch_effect_data
  1822. mov a,[CurrentChDataLo]+y ;get current effect value
  1823. and a,#$0f ;and $0f
  1824. beq EffectNoteCutOffImmediately
  1825. dec a
  1826. EffectNoteCutOffImmediately:
  1827. mov y,#ch_tick_delay
  1828. mov [CurrentChDataLo]+y,a ;write to buffer
  1829. ret
  1830. TickBasedExEffectNoteCutOff:
  1831. mov y,#ch_tick_delay
  1832. mov a,[CurrentChDataLo]+y
  1833. and a,#$0f
  1834. bne CheckForTickBasedEffectsNoteCutOffDec
  1835. mov [CurrentChDataLo]+y,a
  1836. call !CutOffChannelGain
  1837. mov y,#ch_current_channelmask
  1838. mov a,[CurrentChDataLo]+y ;disable channel in keyon reg
  1839. eor a,#$ff
  1840. mov ScratchPad1,a
  1841. and KeyOn,ScratchPad1
  1842. mov CurrentVolume,#$00
  1843. call !SetVolume
  1844. mov y,#ch_effect_data ;clear effect data so this routine isnt triggered on successive ticks of this frame
  1845. mov a,#0
  1846. mov [CurrentChDataLo]+y,a
  1847. ret
  1848. CheckForTickBasedEffectsNoteCutOffDec:
  1849. dec a
  1850. mov [CurrentChDataLo]+y,a
  1851. ;CheckForTickBasedEffectsNoNoteCutOff:
  1852. ret
  1853. TickBasedExEffectNoteRetrigger:
  1854. TickBasedExEffectNoteDelay:
  1855. mov y,#ch_tick_delay
  1856. mov a,[CurrentChDataLo]+y
  1857. and a,#$0f
  1858. bne CheckForTickBasedEffectsNoteDelayDec
  1859. call !SetNewSample
  1860. mov y,#ch_current_channelmask
  1861. mov a,[CurrentChDataLo]+y ;enable channel in keyon reg
  1862. or a,TickSampleStart
  1863. mov TickSampleStart,a
  1864. mov y,#ch_effect_data ;clear effect data so this routine isnt triggered on successive ticks of this frame
  1865. mov a,#0
  1866. mov [CurrentChDataLo]+y,a
  1867. ret
  1868. CheckForTickBasedEffectsNoteDelayDec:
  1869. dec a
  1870. mov [CurrentChDataLo]+y,a
  1871. ret
  1872. SetEchoAndVolume:
  1873. mov $f2,#$2c ;echo volume l
  1874. mov $f3,#$00 ;0d
  1875. mov $f2,#$3c ;echo volume r
  1876. mov $f3,#$00 ;0d
  1877. mov $f2,#$4d ;echo channel enable
  1878. mov $f3,#$00 ;ff
  1879. ret
  1880. ReceiveSongHandler:
  1881. mov $f2,#$0c
  1882. mov $f3,#$00
  1883. mov $f2,#$1c
  1884. mov $f3,#$00
  1885. mov $f2,#$2c
  1886. mov $f3,#$00
  1887. mov $f2,#$3c
  1888. mov $f3,#$00
  1889. mov $f2,#$6c ;disable echo
  1890. mov $f3,#$20
  1891. mov a,#SpcCmdUploadSong ;set "upload song command received"-flag so cpu knows we're ready
  1892. mov $f4,a
  1893. mov a,#$00 ;clear remaining ports
  1894. mov $f5,a
  1895. mov $f6,a
  1896. mov $f7,a
  1897. mov SpcDataPointerLo,#(ModFile & $00ff) ;setup mod pointer
  1898. mov SpcDataPointerHi,#(ModFile >> 8)
  1899. mov ModFilePointerLo,#(ModFile & $00ff) ;setup mod pointer
  1900. mov ModFilePointerHi,#(ModFile >> 8)
  1901. mov y,#$00 ;clear mod pointer counter(actually, this counter always stays 0,just needed for indirect write)
  1902. ReceiveSongWaitLoop2: ;wait for first transfer
  1903. cmp $f4,#SpcCmdUploadSongDone
  1904. beq ReceiveSongComplete ;check if upload complete
  1905. cmp $f4,#SpcCmdUploadSongT1 ;check if data for transfer 1 is stable and on ports
  1906. bne ReceiveSongWaitLoop2
  1907. mov a,$f5 ;get byte
  1908. mov [SpcDataPointerLo]+y,a
  1909. incw SpcDataPointerLo ;increment counter, word
  1910. mov a,$f6 ;get byte
  1911. mov [SpcDataPointerLo]+y,a
  1912. incw SpcDataPointerLo ;increment counter, word
  1913. mov a,$f7 ;get byte
  1914. mov [SpcDataPointerLo]+y,a
  1915. incw SpcDataPointerLo ;increment counter, word
  1916. mov $f4,#SpcCmdUploadSongT1
  1917. ReceiveSongWaitLoop3: ;wait for second transfer
  1918. cmp $f4,#SpcCmdUploadSongT2
  1919. bne ReceiveSongWaitLoop3
  1920. mov a,$f5 ;get byte
  1921. mov [SpcDataPointerLo]+y,a
  1922. incw SpcDataPointerLo ;increment counter, word
  1923. mov a,$f6 ;get byte
  1924. mov [SpcDataPointerLo]+y,a
  1925. incw SpcDataPointerLo ;increment counter, word
  1926. mov a,$f7 ;get byte
  1927. mov [SpcDataPointerLo]+y,a
  1928. incw SpcDataPointerLo ;increment counter, word
  1929. mov $f4,#SpcCmdUploadSongT2
  1930. bra ReceiveSongWaitLoop2
  1931. ReceiveSongComplete:
  1932. mov a,#$00 ;clear apu ports so that cpu knows were ready
  1933. mov $f4,a
  1934. mov $f5,a
  1935. mov $f6,a
  1936. mov $f7,a
  1937. mov ModTimecode,#0 ;clear Timecode
  1938. mov ModTimecode+1,#0
  1939. mov SongEffectsUploaded,#%00000001 ;set "song uploaded" flag, clear "sample pack uploaded" flag
  1940. ret
  1941. ReceiveSamplePack:
  1942. mov a,#SpcCmdUploadSamplePack ;set "upload song command received"-flag so cpu knows we're ready
  1943. mov $f4,a
  1944. mov a,#$00 ;clear remaining ports
  1945. mov $f5,a
  1946. mov $f6,a
  1947. mov $f7,a
  1948. mov $f2,#$5c ;key off all channels
  1949. mov $f3,#%11111111
  1950. movw ya,SpcDataPointerLo ;save offset
  1951. movw TempBuffer1,ya
  1952. mov y,#$00 ;clear mod pointer counter(actually, this counter always stays 0,just needed for indirect write)
  1953. ReceiveSamplePackWaitLoop2: ;wait for first transfer
  1954. cmp $f4,#SpcCmdUploadSamplePackDone
  1955. beq ReceiveSamplePackComplete ;check if upload complete
  1956. cmp $f4,#SpcCmdUploadSongT1 ;check if data for transfer 1 is stable and on ports
  1957. bne ReceiveSamplePackWaitLoop2
  1958. mov a,$f5 ;get byte
  1959. mov [SpcDataPointerLo]+y,a
  1960. incw SpcDataPointerLo ;increment counter, word
  1961. mov a,$f6 ;get byte
  1962. mov [SpcDataPointerLo]+y,a
  1963. incw SpcDataPointerLo ;increment counter, word
  1964. mov a,$f7 ;get byte
  1965. mov [SpcDataPointerLo]+y,a
  1966. incw SpcDataPointerLo ;increment counter, word
  1967. mov $f4,#SpcCmdUploadSongT1
  1968. ReceiveSamplePackWaitLoop3: ;wait for second transfer
  1969. cmp $f4,#SpcCmdUploadSongT2
  1970. bne ReceiveSamplePackWaitLoop3
  1971. mov a,$f5 ;get byte
  1972. mov [SpcDataPointerLo]+y,a
  1973. incw SpcDataPointerLo ;increment counter, word
  1974. mov a,$f6 ;get byte
  1975. mov [SpcDataPointerLo]+y,a
  1976. incw SpcDataPointerLo ;increment counter, word
  1977. mov a,$f7 ;get byte
  1978. mov [SpcDataPointerLo]+y,a
  1979. incw SpcDataPointerLo ;increment counter, word
  1980. mov $f4,#SpcCmdUploadSongT2
  1981. bra ReceiveSamplePackWaitLoop2
  1982. ReceiveSamplePackComplete:
  1983. mov a,#$00 ;clear apu ports so that cpu knows were ready
  1984. mov $f4,a
  1985. mov $f5,a
  1986. mov $f6,a
  1987. mov $f7,a
  1988. movw ya,TempBuffer1 ;restore saved pointer
  1989. movw SpcDataPointerLo,ya
  1990. or SongEffectsUploaded,#%00000010 ;set "sample pack uploaded" flag
  1991. call !SetupEffectSamples
  1992. ;return to mainloop:
  1993. jmp !MainLoop
  1994. SetupEffectSamples:
  1995. mov x,#34*4 ;start copying to 34th dsp sample
  1996. mov y,#$00
  1997. mov a,[SpcDataPointerLo]+y ;get number of sample in pack
  1998. and a,#$1f ;maximum number of samples 31
  1999. mov TempBuffer1,a ;this is our number of samples to process
  2000. inc y ;advance to first byte pointer
  2001. SetupEffectSamplesLoop:
  2002. ;sample adress:
  2003. mov a,[SpcDataPointerLo]+y ;get sample relative adress low
  2004. inc y
  2005. clrc
  2006. adc a,SpcDataPointerLo ;add modfile position
  2007. mov !(SampleSource+0)+x,a ;store in dsp sample area
  2008. mov a,[SpcDataPointerLo]+y ;get sample relative adress hi
  2009. adc a,SpcDataPointerHi ;add modfile position, with carry from previous add
  2010. dec y
  2011. mov !(SampleSource+1)+x,a ;store in dsp sample area
  2012. inc y
  2013. inc y
  2014. ;sample loop adress:
  2015. mov a,[SpcDataPointerLo]+y ;get sample relative adress low
  2016. inc y
  2017. clrc
  2018. adc a,SpcDataPointerLo ;add modfile position
  2019. mov !(SampleSource+2)+x,a ;store in dsp sample area
  2020. mov a,[SpcDataPointerLo]+y ;get sample relative adress hi
  2021. adc a,SpcDataPointerHi ;add modfile position, with carry from previous add
  2022. dec y
  2023. mov !(SampleSource+3)+x,a ;store in dsp sample area
  2024. mov a,y ;increment source pointer by 15 (entry is 16 bytes long)
  2025. clrc
  2026. adc a,#14
  2027. mov y,a
  2028. inc x
  2029. inc x
  2030. inc x
  2031. inc x
  2032. dbnz TempBuffer1,SetupEffectSamplesLoop
  2033. ret
  2034. PlaySoundEffectAbort:
  2035. jmp !MainLoop
  2036. PlaySoundEffect:
  2037. movw ya,$f4 ;save all 4 ports to variables
  2038. movw TempBuffer1,ya ;tempbuffer1:command,tb2:se number,tb3-4:volume/pitch
  2039. movw ya,$f6
  2040. movw TempBuffer3,ya
  2041. mov $f4,#SpcCmdPlaySoundEffect ;echo command received
  2042. bbc $ef.1,PlaySoundEffectAbort ;only process song if song has been uploaded before
  2043. mov a,TempBuffer4
  2044. and a,#$80 ;get flip flag
  2045. eor a,SoundEffectFlipFlag
  2046. bne PlaySoundEffectAbort ;only play effect if this flag has changed as expected
  2047. eor SoundEffectFlipFlag,#$80 ;toggle flag for next soundeffect
  2048. mov y,#0
  2049. mov a,[SpcDataPointerLo]+y ;get number of samples in pack
  2050. mov TempBuffer5,a
  2051. mov a,TempBuffer2
  2052. cmp a,TempBuffer5
  2053. bcs PlaySoundEffectAbort ;return if sound effect to play is bigger than number of samples in pack
  2054. mov a,ActiveSoundEffectCh
  2055. inc a ;goto next channel
  2056. and a,#3 ;maximum number of channels is 3
  2057. mov ActiveSoundEffectCh,a ;save back
  2058. mov x,a
  2059. mov a,!SoundEffectChannelDspRegLUT+x ;get channel value for dsp access
  2060. mov TempBuffer5,a
  2061. mov a,!SoundEffectChannelKofLUT+x ;get channel key off bit
  2062. mov TempBuffer6,a
  2063. mov $f2,#$5c ;key off current channel
  2064. mov $f3,a
  2065. ;wait 8ms for key off to finish
  2066. mov a,$fe ;clear 4bit counter
  2067. mov y,#4
  2068. KofWaitLoop2:
  2069. mov a,$fe ;wait for 2mS
  2070. beq KofWaitLoop2
  2071. dbnz y,KofWaitLoop2
  2072. mov x,TempBuffer5 ;get pointer to dsp channel register set
  2073. mov a,TempBuffer2 ;get sample number
  2074. asl a ;multiply by 16
  2075. asl a
  2076. asl a
  2077. asl a
  2078. inc a ;increment because first byte in sample pack is number of samples
  2079. mov y,a
  2080. inc y
  2081. inc y
  2082. inc y
  2083. inc y
  2084. mov a,TempBuffer4 ;get 65816 command volume
  2085. and a,#$7f ;mask off flip flag
  2086. beq PlaySoundEffectDefaultVol
  2087. ;play SE with custom volume
  2088. and a,#%0001111 ;get volume
  2089. mov TempBuffer7,a
  2090. clrc
  2091. asl a
  2092. asl a
  2093. asl a
  2094. and TempBuffer7,#%00001111 ;add lower bits to get maximum range
  2095. or a,TempBuffer7
  2096. mov TempBuffer7,a
  2097. call !SoundEffectCalcPanL
  2098. mov $f2,x
  2099. mov $f3,a
  2100. inc y
  2101. inc x
  2102. call !SoundEffectCalcPanR
  2103. mov $f2,x
  2104. mov $f3,a
  2105. bra PlaySoundEffectCustomVol
  2106. PlaySoundEffectDefaultVol:
  2107. mov a,[SpcDataPointerLo]+y ;get volume l
  2108. mov $f2,x
  2109. mov $f3,a
  2110. inc y
  2111. inc x
  2112. mov a,[SpcDataPointerLo]+y ;get volume r
  2113. mov $f2,x
  2114. mov $f3,a
  2115. PlaySoundEffectCustomVol:
  2116. inc y
  2117. inc x
  2118. mov a,TempBuffer3 ;get 65816 command pitch
  2119. beq PlaySoundEffectDefaultPitch
  2120. ;play custom pitch. same as mod pitch numbers. valid pitch numbers: 0-59
  2121. push y
  2122. ;**************************************************
  2123. asl a ;asl because each period is 2 bytes long
  2124. mov y,a ;get period number
  2125. mov a,[PeriodTablePointerLo]+y ;get current period
  2126. mov TempBuffer7,a
  2127. inc y
  2128. mov a,[PeriodTablePointerLo]+y
  2129. mov TempBuffer8,a
  2130. ;fetch pitch from pitch table. input: period
  2131. mov y,TempBuffer8
  2132. mov a,TempBuffer7
  2133. addw ya,TempBuffer7 ;multiply by 2
  2134. addw ya,PitchTablePointerLo ;add table offset
  2135. movw TempBuffer7,ya ;move adress to pointer
  2136. mov y,#0
  2137. mov a,[TempBuffer7]+y ;get lo pitch byte
  2138. mov PitchBufferLo,a ;save new pitch
  2139. inc y
  2140. mov a,[TempBuffer7]+y
  2141. mov PitchBufferHi,a
  2142. pop y
  2143. mov a,PitchBufferLo ;get pitch lo
  2144. mov $f2,x
  2145. mov $f3,a
  2146. inc y
  2147. inc x
  2148. mov a,PitchBufferHi ;get pitch hi
  2149. mov $f2,x
  2150. mov $f3,a
  2151. bra PlaySoundEffectCustomPitch
  2152. ;**********************************************+
  2153. PlaySoundEffectDefaultPitch:
  2154. mov a,[SpcDataPointerLo]+y ;get pitch lo
  2155. mov $f2,x
  2156. mov $f3,a
  2157. inc y
  2158. inc x
  2159. mov a,[SpcDataPointerLo]+y ;get pitch hi
  2160. mov $f2,x
  2161. mov $f3,a
  2162. PlaySoundEffectCustomPitch:
  2163. inc x
  2164. mov a,TempBuffer2 ;get sound effect to play
  2165. clrc
  2166. adc a,#34 ;add 34 (sound effects start at dsp sample 34)
  2167. mov $f2,x
  2168. mov $f3,a
  2169. inc y
  2170. inc x
  2171. mov a,[SpcDataPointerLo]+y ;get adsr lo
  2172. mov $f2,x
  2173. mov $f3,a
  2174. inc y
  2175. inc x
  2176. mov a,[SpcDataPointerLo]+y ;get adsr hi
  2177. mov $f2,x
  2178. mov $f3,a
  2179. inc y
  2180. inc x
  2181. mov a,[SpcDataPointerLo]+y ;get gain
  2182. mov $f2,x
  2183. mov $f3,a
  2184. mov $f2,#$5c ;reset key off in case it's still active.(shouldn't, though)
  2185. mov $f3,#%00000000
  2186. mov $f2,#$4c ;key on channel
  2187. mov $f3,TempBuffer6
  2188. jmp !MainLoop
  2189. ;in: TempBuffer4:volume&pan command
  2190. ; TempBuffer7:total channel volume
  2191. ;out: a,8bit: panned channel volume
  2192. ;uses: TempBuffer8
  2193. SoundEffectCalcPanL:
  2194. mov a,TempBuffer4 ;get pan bits
  2195. xcn a ;swap nibbles
  2196. ;put pan bits into lower 4 bits. we're skipping lsr a, asl a here because the pointers in the LUT are words.
  2197. and a,#%00000111 ;mask off rest
  2198. push x
  2199. asl a
  2200. mov x,a ;use as pointer
  2201. mov a,TempBuffer7
  2202. jmp [!PlaySoundEffectLVolLUT+x]
  2203. PlaySoundEffectLVolLUT:
  2204. .dw PlaySoundEffectVolTBL
  2205. .dw PlaySoundEffectVolTBL+1
  2206. .dw PlaySoundEffectVolTBL+2
  2207. .dw PlaySoundEffectVolTBL+3
  2208. .dw PlaySoundEffectVolTBL+4
  2209. .dw PlaySoundEffectVolTBL+5
  2210. .dw PlaySoundEffectVolTBL+6
  2211. .dw PlaySoundEffectVolTBL+7
  2212. SoundEffectCalcPanR:
  2213. mov a,TempBuffer4 ;get pan bits
  2214. xcn a ;swap nibbles
  2215. ;put pan bits into lower 4 bits. we're skipping lsr a, asl a here because the pointers in the LUT are words.
  2216. and a,#%00000111 ;mask off rest
  2217. push x
  2218. asl a
  2219. mov x,a ;use as pointer
  2220. mov a,TempBuffer7
  2221. jmp [!PlaySoundEffectRVolLUT+x]
  2222. PlaySoundEffectRVolLUT:
  2223. .dw PlaySoundEffectVolTBL+7
  2224. .dw PlaySoundEffectVolTBL+6
  2225. .dw PlaySoundEffectVolTBL+5
  2226. .dw PlaySoundEffectVolTBL+4
  2227. .dw PlaySoundEffectVolTBL+3
  2228. .dw PlaySoundEffectVolTBL+2
  2229. .dw PlaySoundEffectVolTBL+1
  2230. .dw PlaySoundEffectVolTBL
  2231. PlaySoundEffectVolTBL:
  2232. lsr a
  2233. lsr a
  2234. lsr a
  2235. lsr a
  2236. lsr a
  2237. lsr a
  2238. lsr a
  2239. nop
  2240. mov TempBuffer8,a ;save
  2241. mov a,TempBuffer7
  2242. setc
  2243. sbc a,TempBuffer8 ;substract calculated pan value
  2244. pop x
  2245. ret
  2246. ReceiveStream:
  2247. mov $f2,#$5c ;key off channels 0-3
  2248. mov $f3,#%00001111
  2249. mov StreamState,#0 ;reset transfer state machine
  2250. mov StreamCurrentBuffer,#0 ;reset to first buffer
  2251. call !SetupStreamSampleAdress
  2252. movw ya,$f5
  2253. movw TempBuffer1,ya ;get total number of samples to transfer
  2254. mov a,#0
  2255. mov y,a
  2256. movw TempBuffer3,ya ;clear current frame counter
  2257. movw $f5,ya ;tell 65816 current frame to transfer
  2258. mov $f4,#SpcCmdReceiveStream
  2259. ReceiveStreamWaitLoop1:
  2260. cmp $f4,#SpcCmdSubmitStreamNumber
  2261. bne ReceiveStreamWaitLoop1
  2262. ;wait for desired frame
  2263. movw ya,$f5
  2264. cmpw ya,TempBuffer3
  2265. bne ReceiveStreamRequestFrame
  2266. mov a,$f7
  2267. mov StreamVolume,a
  2268. beq ReceiveStreamExit ;exit streaming if volume is 0
  2269. ;enter receive state machine
  2270. mov a,StreamState
  2271. asl a
  2272. mov x,a ;pointer into jump table
  2273. jmp [!StreamJumpTable+x]
  2274. ReceiveStreamWaitLoop2:
  2275. cmp $f4,#SpcCmdSubmitStreamNumber ;wait for port0 data to change. Don't know if this works out as desired, but
  2276. beq ReceiveStreamWaitLoop2
  2277. ReceiveStreamTransferLoop: ;66 cycles per scanline. this loop must be exactly 66 bytes long while looping.
  2278. ;26 cycles ;59 cycles per scanline left for actual transfer
  2279. movw ya,$f4
  2280. push a ;save data on stack cause that's the fastest way possible
  2281. push y
  2282. movw ya,$f6
  2283. push a
  2284. push y
  2285. ;waste 33 cyles:
  2286. ;******************************
  2287. mov a,TempBuffer1 ;real snes/bsnes need a total of 33 cycles here
  2288. mov a,TempBuffer1
  2289. mov a,TempBuffer1
  2290. mov a,TempBuffer1
  2291. mov a,TempBuffer1
  2292. mov a,TempBuffer1
  2293. mov a,TempBuffer1
  2294. mov a,TempBuffer1
  2295. mov a,TempBuffer1
  2296. mov a,TempBuffer1
  2297. mov a,TempBuffer1
  2298. ;7 cycles when looping back
  2299. dbnz TempBuffer5,ReceiveStreamTransferLoop
  2300. mov a,#36
  2301. mov TempBuffer5,a
  2302. mov y,#144-1 ;set counter to last byte in buffer(reverse copy because of stack)
  2303. ReceiveStreamSaveLoop:
  2304. pop a ;dummy loop to fix stack
  2305. mov [TempBuffer7]+y,a ;7 -move to buffer
  2306. dec y
  2307. pop a ;dummy loop to fix stack
  2308. mov [TempBuffer7]+y,a ;7 -move to buffer
  2309. dec y
  2310. pop a ;dummy loop to fix stack
  2311. mov [TempBuffer7]+y,a ;7 -move to buffer
  2312. dec y
  2313. pop a ;dummy loop to fix stack
  2314. mov [TempBuffer7]+y,a ;7 -move to buffer
  2315. dec y
  2316. dbnz TempBuffer5,ReceiveStreamSaveLoop
  2317. cmp StreamCurrentBuffer,#SpcStreamLatency
  2318. bne SpcStreamDontSetEndBit
  2319. mov y,#144-9 ;set pointer to last samples header
  2320. mov a,[TempBuffer7]+y ;get header byte
  2321. or a,#%00000011 ;set loop & end bits
  2322. mov [TempBuffer7]+y,a ;save back header byte
  2323. SpcStreamDontSetEndBit:
  2324. incw TempBuffer3 ;request next frame
  2325. inc StreamCurrentBuffer
  2326. and StreamCurrentBuffer,#7 ;maximum number of buffers: 8
  2327. StreamTimerWait: ;wait for 16 brr samples to play / ca. 2 frames to pass, then continue downloading stream
  2328. mov a,$fd
  2329. beq StreamTimerWait
  2330. ReceiveStreamRequestFrame:
  2331. movw ya,TempBuffer3
  2332. movw $f5,ya ;tell 65816 which frame to transfer
  2333. movw ya,TempBuffer1 ;check if done transfering
  2334. cmpw ya,TempBuffer3
  2335. bne ReceiveStreamWaitLoop1
  2336. ReceiveStreamExit:
  2337. mov $f2,#$5c ;key off channels 0-3
  2338. mov $f3,#%00000001
  2339. mov $f4,#SpcCmdReceiveStreamComplete ;tell 65816 we're done
  2340. ;StreamWaitSampleEnd:
  2341. mov $f1,#$00 ;stop timer
  2342. nop
  2343. nop
  2344. mov $fa,ModPlayerTimer0 ;reset timer, return to modplayer
  2345. nop
  2346. nop
  2347. mov $f1,#$03 ;start timer
  2348. jmp !MainLoop ;return
  2349. StreamJumpTable:
  2350. .dw InitStream ;fill buffer, then start playing sample
  2351. .dw StreamContinue ;fill buffer according to timer
  2352. StreamContinue:
  2353. ;setup current stream buffer
  2354. mov TempBuffer7,#(StreamBuffer & $00ff) ;pointer to first stream buffer
  2355. mov TempBuffer8,#(StreamBuffer >> 8)
  2356. mov a,StreamCurrentBuffer
  2357. mov y,#144
  2358. mul ya
  2359. addw ya,TempBuffer7
  2360. movw TempBuffer7,ya ;pointer to current stream buffer in TempBuffer7,8
  2361. mov a,#$00
  2362. mov y,StreamVolume ;update volume
  2363. movw $f2,ya
  2364. inc a
  2365. movw $f2,ya
  2366. mov y,#0 ;clear target copy counter
  2367. mov a,#36 ;amount of scanlines to copy
  2368. mov TempBuffer5,a
  2369. jmp !ReceiveStreamWaitLoop2
  2370. InitStream:
  2371. ;receive stream here:
  2372. ;setup current stream buffer
  2373. mov TempBuffer7,#(StreamBuffer & $00ff) ;pointer to first stream buffer
  2374. mov TempBuffer8,#(StreamBuffer >> 8)
  2375. mov a,StreamCurrentBuffer
  2376. and a,#7 ;maximum number of buffers: 8
  2377. mov y,#144
  2378. mul ya
  2379. addw ya,TempBuffer7
  2380. movw TempBuffer7,ya ;pointer to current stream buffer in TempBuffer7,8
  2381. mov y,#0 ;clear target copy counter
  2382. mov a,#36 ;amount of scanlines to copy
  2383. mov TempBuffer5,a
  2384. cmp StreamCurrentBuffer,#SpcStreamLatency
  2385. bne SpcStreamDontStartSample
  2386. ;setup sample dsp regs on channel 1:
  2387. ;wide stereo effect
  2388. mov a,#$00
  2389. mov y,StreamVolume ;volume
  2390. movw $f2,ya
  2391. inc a
  2392. movw $f2,ya
  2393. inc a
  2394. mov y,#$00 ;pitch lo
  2395. movw $f2,ya
  2396. inc a
  2397. mov y,#$04 ;pitch hi
  2398. movw $f2,ya
  2399. inc a
  2400. mov y,#SpcStreamSampleNumber ;sample number
  2401. movw $f2,ya
  2402. inc a
  2403. mov y,#0 ;adsr1 (use gain instead)
  2404. movw $f2,ya
  2405. inc a
  2406. movw $f2,ya ;adsr2
  2407. inc a
  2408. mov y,#$7f ;volume
  2409. movw $f2,ya
  2410. mov $f2,#$5c ;reset key off in case it's still active.(shouldn't, though)
  2411. mov $f3,#%00000000
  2412. mov $f2,#$4c ;key on channel 1
  2413. mov $f3,#%00000001
  2414. mov $f1,#$00 ;stop timer
  2415. nop
  2416. nop
  2417. mov $fa,#StreamerTimer0 ;32 milliSeconds on timer 0
  2418. nop
  2419. nop
  2420. mov $f1,#$03 ;start timer
  2421. inc StreamState ;goto next state
  2422. SpcStreamDontStartSample:
  2423. jmp !ReceiveStreamWaitLoop2
  2424. UpdateVolEchoHandler:
  2425. mov ModFilePointerLo,#(MainVolL & $00ff) ;setup mod pointer
  2426. mov ModFilePointerHi,#(MainVolL >> 8)
  2427. mov y,#$00 ;clear mod pointer counter(actually, this counter always stays 0,just needed for indirect write)
  2428. mov $f4,#$01
  2429. UpdateVolEchoWaitLoop1:
  2430. cmp $f4,#$00 ;check if another data download is due
  2431. bne UpdateVolEchoWaitLoop1
  2432. mov a,$f5 ;get byte
  2433. mov [ModFilePointerLo]+y,a
  2434. incw ModFilePointerLo ;increment counter, word
  2435. mov a,$f6 ;get byte
  2436. mov [ModFilePointerLo]+y,a
  2437. incw ModFilePointerLo ;increment counter, word
  2438. mov a,$f7 ;get byte
  2439. mov [ModFilePointerLo]+y,a
  2440. incw ModFilePointerLo ;increment counter, word
  2441. mov $f4,#$00
  2442. UpdateVolEchoWaitLoop2:
  2443. cmp $f4,#$01 ;check if another data download is due
  2444. bne UpdateVolEchoWaitLoop2
  2445. mov a,$f5 ;get byte
  2446. mov [ModFilePointerLo]+y,a
  2447. incw ModFilePointerLo ;increment counter, word
  2448. mov a,$f6 ;get byte
  2449. mov [ModFilePointerLo]+y,a
  2450. incw ModFilePointerLo ;increment counter, word
  2451. mov a,$f7 ;get byte
  2452. mov [ModFilePointerLo]+y,a
  2453. incw ModFilePointerLo ;increment counter, word
  2454. mov a,#$00 ;clear apu ports so that cpu knows were ready
  2455. mov $f4,a
  2456. mov $f5,a
  2457. mov $f6,a
  2458. mov $f7,a
  2459. UpdateVolEchoVariablesOnly:
  2460. mov $f2,#$6d ;echo start adress
  2461. mov $f3,#EchoStartAdress ;80
  2462. mov $f2,#$7d ;echo delay
  2463. mov $f3,#EchoDelay ;06
  2464. mov $f2,#$0d ;echo feedback
  2465. mov $f3,#$04 ;04
  2466. mov $f2,#$0c
  2467. mov $f3,MainVolL
  2468. mov $f2,#$1c
  2469. mov $f3,MainVolR
  2470. mov $f2,#$2c
  2471. mov $f3,EchoVolL
  2472. mov $f2,#$3c
  2473. mov $f3,EchoVolR
  2474. mov $f2,#$4d
  2475. mov $f3,ChannelEchoEnable
  2476. ret
  2477. ;set key on/key off here:
  2478. GetDataFromPatternCheckPatternPosition:
  2479. ;***********************************************
  2480. ;check if pattern break is due
  2481. mov a, PatternBreakFlag ;check if pattern break flag is set
  2482. beq CheckPatternBreakExit
  2483. inc CurrentPatternNumber ;increment current pattern
  2484. mov x,CurrentPatternNumber ;check if we overflow
  2485. cmp x,NumberOfPatterns
  2486. bne PatternBreakNoOverflow
  2487. mov CurrentPatternNumber,#$00 ;reset to pattern #0 if overflow occured
  2488. mov x,CurrentPatternNumber
  2489. PatternBreakNoOverflow:
  2490. mov a,!(ModFile+$fa)+x ;get id number of next pattern
  2491. asl a
  2492. mov x,a
  2493. mov a,!(ModFile+$17a)+x ;get word-pointer to that table
  2494. mov y,a
  2495. mov a,!(ModFile+$17b)+x
  2496. addw ya,InitPatternPointerLo
  2497. movw CurrentPatternPointerLo,ya ;update current pattern pointer
  2498. mov PatternBreakFlag,#0 ;clear pattern break flag and exit
  2499. pop a ;need to purge the stack a bit first
  2500. pop a ;else, it would overflow slowly when using the pattern break command constantly
  2501. pop a
  2502. pop a
  2503. jmp !MainLoop
  2504. CheckPatternBreakExit:
  2505. ;check if at end of current pattern
  2506. mov x,CurrentPatternNumber
  2507. mov a,!(ModFile+$fa)+x ;load pattern number
  2508. inc a
  2509. asl a ;multiply, use as pointer into patterntable pointertable list
  2510. mov x,a
  2511. mov a,!(ModFile+$17a)+x ;$1455+x ;(ModFile+$17a) ;$17a
  2512. mov TempBuffer2,a
  2513. mov a,!(ModFile+$17b)+x ;$1456+x ;17b
  2514. mov TempBuffer1,a
  2515. movw ya,CurrentPatternPointerLo
  2516. subw ya,InitPatternPointerLo
  2517. cmpw ya,TempBuffer1
  2518. bpl CheckPatternPositionPatternEnd
  2519. ret
  2520. CheckPatternPositionPatternEnd:
  2521. inc CurrentPatternNumber ;increment position in current pattern
  2522. mov a,CurrentPatternNumber
  2523. cmp a,NumberOfPatterns ;check if at end of pattern
  2524. beq CheckPatternPositionReset
  2525. mov x,a
  2526. mov a,!(ModFile+$fa)+x
  2527. asl a
  2528. mov x,a
  2529. mov a,!(ModFile+$17a)+x
  2530. mov y,a
  2531. mov a,!(ModFile+$17b)+x
  2532. addw ya,InitPatternPointerLo
  2533. movw CurrentPatternPointerLo,ya
  2534. movw CurrentLoopPointerLo,ya
  2535. ret
  2536. CheckPatternPositionReset: ;wrap to pattern 0
  2537. mov $f6,#$50
  2538. mov CurrentPatternNumber,#$00
  2539. mov x,CurrentPatternNumber
  2540. mov a,!(ModFile+$fa)+x
  2541. asl a
  2542. mov x,a
  2543. mov a,!(ModFile+$17a)+x
  2544. mov y,a
  2545. mov a,!(ModFile+$17b)+x
  2546. addw ya,InitPatternPointerLo
  2547. movw CurrentPatternPointerLo,ya
  2548. ret
  2549. ClearAllChannelArray:
  2550. mov a,#(ChannelArray & $ff) ;get pointer to first channel array
  2551. mov y,#(ChannelArray >> 8)
  2552. movw TempBuffer1,ya
  2553. movw Channel1Array,ya
  2554. mov a,#1
  2555. call !ClearChannelArray
  2556. movw Channel2Array,ya
  2557. mov a,#2
  2558. call !ClearChannelArray
  2559. movw Channel3Array,ya
  2560. mov a,#4
  2561. call !ClearChannelArray
  2562. movw Channel4Array,ya
  2563. mov a,#8
  2564. call !ClearChannelArray
  2565. ret
  2566. ClearChannelArray:
  2567. mov y,#ch_current_channelmask ;number of bytes to copy
  2568. mov [TempBuffer1]+y,a ;put channel mask into array pointer + channel mask value
  2569. decw TempBuffer1
  2570. mov a,#0
  2571. ClearChannelArrayLoop:
  2572. mov [TempBuffer1]+y,a ;clear array
  2573. dbnz y,ClearChannelArrayLoop
  2574. incw TempBuffer1
  2575. mov a,#ch_current_channelmask+1 ;get amount of bytes per array and add to current adress
  2576. mov y,#0
  2577. addw ya,TempBuffer1
  2578. movw TempBuffer1,ya ;save adress of next array
  2579. ret
  2580. CommandVoid:
  2581. jmp !MainLoop
  2582. SetSongChannelMask:
  2583. mov SongChannelMask,$f5 ;get new channel mask
  2584. mov $f2,#$5c
  2585. mov a,SongChannelMask
  2586. eor a,#$0f ;invert, switch off masked channels immediately
  2587. mov $f3,a ;key off
  2588. mov $f4,#SpcCmdSetSongChMask ;ack
  2589. jmp !MainLoop ;return
  2590. SetSongSpeed:
  2591. mov ModPlayerTimer0,$f5 ;get new speed
  2592. mov $f1,#$00
  2593. nop
  2594. nop
  2595. mov $fa,ModPlayerTimer0 ;20 milliSeconds on timer 0
  2596. mov $fb,#$10 ;2 milliSeconds on timer 1
  2597. nop
  2598. nop
  2599. mov $f1,#$03 ;start timer(s)
  2600. mov $f4,#SpcCmdSetSongSpeed ;ack
  2601. jmp !MainLoop ;return
  2602. StopSongStream:
  2603. and SongEffectsUploaded,#%11111110 ;clear "song uploaded" flag
  2604. mov $f2,#$5c ;reset key off in case it's still active.(shouldn't, though)
  2605. mov $f3,#%00001111 ;key off all mod/stream channels
  2606. mov $f4,#SpcCmdStopSong ;ack command
  2607. jmp !MainLoop ;return
  2608. SetReportType:
  2609. mov SpcReportType,$f5 ;get new report type
  2610. mov $f4,#SpcCmdReportType ;ack
  2611. jmp !MainLoop
  2612. SetSongVolume:
  2613. mov MusicVol1,$f5 ;get new volume, mod channel 0,1
  2614. mov MusicVol2,$f6 ;get new volume, mod channel 0,1
  2615. mov $f4,#SpcCmdSetSongVolume ;ack
  2616. jmp !MainLoop
  2617. SendReportData:
  2618. mov a,SpcReportType ;get report type
  2619. and a,#$07
  2620. asl a
  2621. mov x,a ;pointer into jump table
  2622. jmp [!ReportJumpTable+x]
  2623. ReportJumpTable:
  2624. .dw ReportVoid
  2625. .dw ReportTimecode
  2626. .dw ReportChannelLevels
  2627. .dw ReportSpecialCmd
  2628. .dw ReportVoid
  2629. .dw ReportVoid
  2630. .dw ReportVoid
  2631. .dw ReportVoid
  2632. ReportVoid:
  2633. mov a,#0
  2634. mov $f5,a ;clear report data
  2635. mov $f6,a
  2636. mov $f7,a
  2637. ret
  2638. ReportTimecode:
  2639. mov $f5,#0 ;clear report byte first
  2640. movw ya,ModTimecode
  2641. movw $f6,ya
  2642. mov a,SpcReportType
  2643. or a,#$e0
  2644. mov $f5,a ;return report type
  2645. ret
  2646. ;report current sample levels of all 4 mod channels as 4bit nibbles unsigned.
  2647. ReportChannelLevels:
  2648. mov $f2,#$09
  2649. mov a,$f3 ;get current wave height ch0
  2650. lsr a
  2651. lsr a
  2652. lsr a
  2653. and a,#$0f
  2654. mov TempBuffer1,a
  2655. mov $f2,#$19
  2656. mov a,$f3 ;get current wave height ch1
  2657. asl a
  2658. and a,#$f0
  2659. or a,TempBuffer1
  2660. mov TempBuffer1,a
  2661. mov $f2,#$29
  2662. mov a,$f3 ;get current wave height ch2
  2663. lsr a
  2664. lsr a
  2665. lsr a
  2666. and a,#$0f
  2667. mov TempBuffer1+1,a
  2668. mov $f2,#$39
  2669. mov a,$f3 ;get current wave height ch3
  2670. asl a
  2671. and a,#$f0
  2672. or a,TempBuffer1+1
  2673. mov TempBuffer1+1,a
  2674. movw ya,TempBuffer1
  2675. mov $f5,#0 ;clear report byte first
  2676. movw $f6,ya ;write data to ports
  2677. mov a,SpcReportType
  2678. or a,#$e0
  2679. mov $f5,a ;return report type
  2680. ret
  2681. ReportSpecialCmd:
  2682. mov $f5,#0 ;clear report byte first
  2683. mov a,SpecialReportCmd
  2684. mov $f6,a
  2685. mov a,SpcReportType
  2686. or a,#$e0
  2687. mov $f5,a ;return report type
  2688. ret
  2689. SoundEffectChannelDspRegLUT:
  2690. .db $40
  2691. .db $50
  2692. .db $60
  2693. .db $70
  2694. SoundEffectChannelKofLUT:
  2695. .db $10
  2696. .db $20
  2697. .db $40
  2698. .db $80
  2699. VibratoTable:
  2700. .incbin "data/apu/vibratotable.tbl"
  2701. PeriodTable:
  2702. .include "data/apu/amigaperiodtable.tbl"
  2703. PitchTable:
  2704. .include "data/apu/pitchtable_new.tbl"
  2705. .incbin "data/apu/pitchtable2.tbl"
  2706. ModFile: