-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathWave_IRQDriver.s
More file actions
2189 lines (1943 loc) · 38.4 KB
/
Wave_IRQDriver.s
File metadata and controls
2189 lines (1943 loc) · 38.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
;Wave_IRQDriver.s
SetupIRQ
sei
;Redirect Main IRQ vector to IRQDriver
ldx SYS_IRQVECTOR
lda #$20
sta SYS_IRQVECTOR
ldy SYS_IRQVECTOR+1
lda #$00
sta SYS_IRQVECTOR+1
stx BasicsIRQVector
sty BasicsIRQVector+1
;Copy Zero Page Routine
ldx #00
.(
loop1 lda BaseCopyAddress,x
sta $20,x
inx
bne loop1
.)
;Set T1 counters high (to ensure they do not trigger IRQ below)
lda #$FF
sta VIA_T1CL
sta VIA_T1CH
;Clear T1 IRQ
CMP VIA_T1CL
;Set Column register to %00010000 before entering irq
lda #$0E
sta VIA_PORTA
lda #$FF
sta VIA_PCR
lda #$FD
sta VIA_PCR
lda #%00010000
sta VIA_PORTA
lda #$DD
sta VIA_PCR
;Set 50Hz Counter
lda #100
sta MusicCountdown
;Set T1 to 5Khz
lda #<200
sta VIA_T1LL
sta VIA_T1CL
lda #>200
sta VIA_T1LH
sta VIA_T1CH
jsr StopSID
jsr StopSample
cli
rts
BaseCopyAddress
*=$20
ZeroPageRoutineStart
;IRQ Driver resides in zero page to optimise Sample and SID playing to 5Khz(Every 200 cycles)
;The Fast register is (by default) for SID so sample momentarily switches registers
;1x 16 Bit Fractional Stepping Sample Channel
;1x 16 Bit Fractional Stepping SID Channel
;Total Bytes 179 ($B3)Bytes
;CPU Demand 38-83%
;cpu cycles include entering irq(12), Page2 jump(3) and RTI(6)
;Average SID+SAM 75%
;Average SAM 70%
;Average SID 44%
;Based on 5Khz IRQ(200 Cycles)
;137 Bytes (42 Less Bytes than previous and 3% faster)
;Based on 5Khz IRQ(200 Cycles)
;CPU Load is between 23% and 80%
;No Sample or SID 45 Cycles - 23%
;SampleLo+SID 160 Cycles - 80%
;SampleHi+SID 149 Cycles - 75%
;SampleLo Only 77 Cycles - 39%
;SampleHi Only 66 Cycles - 33%
;SID Only 131 Cycles - 66%
;Unfortunately XA is being lame and using absolute addresses for everything, so i am forced
;to calculate zp addresses myself.
irqDriver
;Reset IRQ
bit VIA_T1CL ;20/21/22
;Record Acc
sta $A0 ;23/24 (OriginalAccumulator+1)
;Countdown Music IRQ
dec $A9 ;25/26 (MusicCountdown)
bne SIDPatch ;27/28
lda #100 ;29/2A
sta $A9 ;2B/2C (MusicCountdown)
sta $AA ;2D/2E (MusicProcessFlag)
;Either Patched with Jmp or Perform 16 bit fractional stepping for SID
FracSIDLC
SIDPatch
jmp ProcSAM ;2F/30/31
; lda #00 ;
; sec ;
FracSIDLR adc #00 ;32/33
sta $30 ;34/35 (FracSIDLC+1)
FracSIDHC
lda #00 ;36/37
FracSIDHR
adc #00 ;38/39
sta $37 ;3A/3B (FracSIDHC+1)
bcc ProcSAM ;3C/3D
;Set SID AY Register
lda #$FF ;3E/3F
sta VIA_PCR ;40/41/42
SIDRegister
lda #08 ;43/44
sta VIA_PORTA ;45/46/47
lda #$DD ;48/49
sta VIA_PCR ;4A/4B/4C
;Process SID and store
RegSIDVal lda #00 ;4D/4E
RegSIDEOR eor #00 ;4F/50
sta $4E ;51/52 (RegSIDVal+1)
sta VIA_PORTA ;53/54/55
;Write SID to AY
lda #$FD ;56/57
sta VIA_PCR ;58/59/5A
;Restore Sample AY Register
lda #$FF ;5B/5C
sta VIA_PCR ;5D/5E/5F
SAMRegister
lda #14 ;60/61
sta VIA_PORTA ;62/63/64
lda #$DD ;65/66
sta VIA_PCR ;67/68/69
;Write last Sample value
SAMValue lda #00 ;6A/6B
and #15 ;6C/6D
sta VIA_PORTA ;6E/6F/70
lda #$FD ;71/72
sta VIA_PCR ;73/74/75
ProcSAM ;Jump either to High Nibble Process, Low Nibble Process or No Sample
SAMVector jmp $009F ;76/77/78
ProcSAMHi ;Process High Nibble Sample
lda $6B ;79/7A (SAMValue+1)
lsr ;7B
lsr ;7C
lsr ;7D
lsr ;7E
sta VIA_PORTA ;7F/80/81
;Switch to Process Low Nibble next time
lda #<ProcSAMLo ;82/83
sta $77 ;84/85 (SAMVector+1)
lda $A0 ;86/87 (OriginalAccumulator+1)
rti ;88
ProcSAMLo
SAMMemory ;Process Low Nibble Sample
lda $dead ;89/8A/8B
beq EndSample ;8C/8D
sta $6B ;8E/8F (SAMValue+1)
and #15 ;90/91
sta VIA_PORTA ;92/93/94
;Switch to process High Nibble next time
lda #<ProcSAMHi ;95/96
sta $77 ;97/98 (SAMVector+1)
;Increment Sample Address
inc $8A ;99/9A (SAMMemory+1)
bne SAMNoSAM ;9B/9C
inc $8B ;9D/9E (SAMMemory+2)
SAMNoSAM
OriginalAccumulator
lda #00 ;9F/A0
rti ;A1
EndSample ;We'll keep things simple with Sample and limit to 5Khz with no looping
lda #<SAMNoSAM ;A2/A3
sta $77 ;A4/A5 (SAMVector+1)
jmp SAMNoSAM ;A6/A7/A8
;50/100Hz Counter
MusicCountdown .byt 0 ;A9
MusicProcessFlag .byt 0 ;AA
;Pitchbend Tables
pzTempPitchHi .byt 0 ;DA
pzTempPitchLo .byt 0 ;DB
;pbDestinationPitchLo .byt 0,0,0 ;DC
;pbDestinationPitchHi .byt 0,0,0 ;DF
;Keyboard Variables
pzKeyRegister .byt 0 ;E2
;B0 Effect Channel A Active(1) or Inactive(0)
;B1 Effect Channel B Active(1) or Inactive(0)
;B2 Effect Channel C Active(1) or Inactive(0)
;B3 Ornament Channel A Active(1) or Inactive(0)
;B4 Ornament Channel B Active(1) or Inactive(0)
;B5 Ornament Channel C Active(1) or Inactive(0)
;B6 Pattern Playing Active
;B7 List(Music) Playing Active
pzMusicElementActivity .byt 0 ;E4
;Other Music Variables
pzNoteTempoCount .byt 0 ;E5
pzIntermediatePitchLo .byt 0 ;E9
pzIntermediatePitchHi .byt 0 ;EA
pzPatternRowPlayFlag .byt 0 ;EB
;AY Bank
ayBankCurrent
ayPitchLo .byt 0,0,0 ;EC
ayPitchHi .byt 0,0,0 ;EF
ayNoise .byt 0 ;F2
ayStatus .byt %01111000 ;F3
ayVolume .byt 0,0,0 ;F4
ayEGPeriod .byt 0,0 ;F7
ayCycle .byt 0 ;F9
;Music Pointers
pmPattern .byt 0,0 ;FA
pmOrnament .byt 0,0 ;FC
pmEffect .byt 0,0 ;FE
peTemp02 .byt 0
ZeroPageRoutineEnd
*=BaseCopyAddress+(ZeroPageRoutineEnd-ZeroPageRoutineStart)
BaseCopyEndAddress
SIDActivity .byt 0 ;
SAMActivity .byt 0 ;
pzPatternRowCounter .byt 64 ;£6
pzListIndex .byt 0 ;E7
pzTemp01 .byt 0 ;E8
Main50HzIRQ
;Reset 50Hz Countdown(actually 100Hz)
lda #50
sta MusicCountdown
;Check Music
lda pzMusicElementActivity
.(
beq skip2
;Progress music elements
jsr ProcMusic
;Send AY
sei
lda #$DD
sta VIA_PCR
ldx #13
loop1 lda ayBankCurrent,x
cmp ayBankReference,x
beq skip1
sta ayBankReference,x
ldy ayRealRegister,x
sty VIA_PORTA
ldy #$FF
sty VIA_PCR
ldy #$DD
sty VIA_PCR
sta VIA_PORTA
lda #$FD
sta VIA_PCR
sty VIA_PCR
skip1 dex
bpl loop1
skip2 cli
.)
;Read Keyboard every 2nd Interrupt
AlternateKeyscan
lda #00
eor #128
sta AlternateKeyscan+1
.(
bmi skip1
jsr RapidKeyScan
skip1 ;Is SID FastReg being used?
.)
ldx #$DD
lda $77
cmp #<SAMNoSAM
beq irqskip1
;Restore SAM Register
sei
stx VIA_PCR
ldy SAMRegister+1
sty VIA_PORTA
ldy #$FF
sty VIA_PCR
lda $6B
and #15
stx VIA_PCR
sta VIA_PORTA
ldx #$FD
irqskip1 stx VIA_PCR
cli
;Process Counter
pzIRQCounter
lda #00
.(
beq skip1
dec pzIRQCounter+1
skip1
.)
;Return
rts
pzKeyInDelayPhase .byt 0 ;E3
;To improve performance, rather than interrupt SID, automatically setup Column 00
;before calling keyscan for first time and after keyscan for next time. In this way
;No keys will not interrupt Sound through SEI.
;Rapidly scan for keys
;Scan Shift,Ctrl,Func Seperately
;0-63 Key
;+64 Shift
;+128 Ctrl
;+192 Func
;Then combine into single byte with a specific code when nothing pressed.
RapidKeyScan
ldy #07 ;Row
.(
loop1 sty VIA_PORTB
jsr KeyDelay
lda VIA_PORTB
and #8
bne skip1
dey
bpl loop1
lda #NULLKEYCODE
sta pzKeyRegister
rts
skip1 ;Found row with key activity(column in Y) - now isolate key
;Which means we must NOW have virtual Key column register
sei
lda #$FF
sta VIA_PCR
lda #$0E
sta VIA_PORTA
lda #$FD
sta VIA_PCR
ldx #6
loop2 lda pmKeyColumn,x
sta VIA_PORTA
jsr KeyDelay
lda VIA_PORTB
and #8
bne skip2
dex
bpl loop2
jsr RestoreSIDRegisterAndCLI
lda #NULLKEYCODE
sta pzKeyRegister
rts
skip2 ;Found exact key - remember position
sty pmKeyFoundRow+1
;Now scan Soft column
lda #%11101111
sta VIA_PORTA
ldy #3
loop3 lda pmSoftRow,y
sta VIA_PORTB
jsr KeyDelay
lda VIA_PORTB
and #8
bne skip3
dey
bpl loop3
ldy #4
skip3 ;Fetch Row
.)
pmKeyFoundRow
lda #00
ora pmColumnBits,x ;8
ora pmSoftBits,y ;5
sta pzKeyRegister
RestoreSIDRegisterAndCLI
;Restore Key column %00010000
lda #$FF
sta VIA_PCR
lda #$0E
sta VIA_PORTA
lda #$FD
sta VIA_PCR
lda #%00010000
sta VIA_PORTA
;Restore SID register
lda #$FF
sta VIA_PCR
lda SIDRegister+1
sta VIA_PORTA
lda #$DD
sta VIA_PCR
cli
rts
KeyDelay
nop
nop
rts
;To optimise pitch and Volume processing ProcMusic processes the music as follows
;If NoteCount times out then procpattern (To capture Pattern Note and PatternVolume)
;Then for each channel
; Ornament The relative Note offset
; convert to pitch
; Effect The relative Pitch offset The accumulative Note offset
; convert to ayvolume
; Pitchbend Accumulative Pitch offset
; convert to ayPitch
ProcMusic
;Check Pattern Note
lda pzMusicElementActivity
asl
.(
bpl skip1
;Process Pattern and List
dec pzNoteTempoCount
bne skip1
lda pmMusicTempo
sta pzNoteTempoCount
jsr ProcPattern
skip1
.)
;Process Effects, Ornaments, Pitchbend, Rapid Register and Conversions
ldx #2
.(
loop1 ;Check Ornament
lda pzMusicElementActivity
and pmOrnamentBits,x
cmp #1
lda pmPatternNote,x
bcc skip1
;Process Ornament
ldy pmOrnamentID,x
lda pmOrnamentAddressLo,y
sta pmOrnament
lda pmOrnamentAddressHi,y
sta pmOrnament+1
loop2 ldy pmOrnamentIndex,x
lda (pmOrnament),y
bne skip2
ldy pmOrnamentID,x
lda mmOrnamentLoops,y
bmi skip6
sta pmOrnamentIndex,x
jmp loop2
skip6 lda pzMusicElementActivity
and pmNoiseMask,x
sta pzMusicElementActivity
lda #00
skip2 clc
adc pmPatternNote,x
and #127
inc pmOrnamentIndex,x
;Check Pitchbend
;If Pitchbend off then calc rapid register pitch from PatternNote+OrnamentOffset
;If Pitchbend on then calc rapid register pitch from semitone stuff
skip1 tay
lda pbFlag,x
beq skip3
dec pbDelayCount,x
bpl skip10
lda pbDelayRefer,x
sta pbDelayCount,x
jsr pbProcPitchbend
jmp skip7
skip10 ;Ensure that current pitchbend interpolation is stored during a delay
cmp #128
bcc ContinueDescendHold
jsr ContinueAscending4
jmp skip7
ContinueDescendHold
jsr ContinueDescending4
jmp skip7
skip3 ;Convert to Pitch
lda pmPitchTableHi,y
sta pzIntermediatePitchHi
lda pmPitchTableLo,y
sta pzIntermediatePitchLo
;Check if either SID is active
cpx SIDActivity
bne skip7
skip11 ;Check Note no less than C-2(24)
; cpy #24
; bcs skip8
; ldy #24
skip8 ;Check note no more than D#6(75)
cpy #76
bcc skip9
ldy #75
skip9 ;Convert to 16 bit SID Frac
lda rssFracStepLo,y
sta FracSIDLR+1
lda rssFracStepHi,y
sta FracSIDHR+1
skip7 ;Check Effect
lda pzMusicElementActivity
and pmEffectBits,x
beq skip4
;Process Effect
ldy pmEffectID,x
lda pmEffectAddressLo,y
sta pmEffect
lda pmEffectAddressHi,y
sta pmEffect+1
ldy pmEffectIndex,x
loop3 lda (pmEffect),y
and #%11100000
lsr
sta vector1+1
lda (pmEffect),y
iny
and #31
adc #255-15
clc
vector1 jsr pmeLoopOrEnd
bcs loop3
tya
sta pmEffectIndex,x
skip4 ;Transfer Intermediate Pitch to AY Registers
lda pzIntermediatePitchLo
sta ayPitchLo,x
lda pzIntermediatePitchHi
sta ayPitchHi,x
;Progress to next Effect/Ornament
dex
bmi skip5
jmp loop1
skip5 rts
.)
;1) Process pitchbend of channel pitch
;2) Process rapid-register if on
;Both pzTempPitchLo and pzTempPitchHi must be zp
pbProcPitchbend
lda pbFlag,x
bpl Descend
jmp Ascend
Descend ;Descend
dec pmStepCount,x
bpl ContinueDescending
;Set up next Semitone Interpolation
;Decrement Pattern Note
dec pmPatternNote,x
;But Use Note after Ornament has dealt with it(A-1)
tya
dey
cmp pbDestinationNote,x
.(
bne skip1
inc pmPatternNote,x
lda #00
sta pbFlag,x
;Still need to setup intermidiate pitch
lda pmPitchTableLo+1,y
sta pzIntermediatePitchLo
lda pmPitchTableHi+1,y
sta pzIntermediatePitchHi
rts
skip1 ;Fetch pitch of this semitone, subtract from next to get difference
.)
lda pmPitchTableLo,y
sec
sbc pmPitchTableLo+1,y
sta pzTempPitchLo
lda pmPitchTableHi,y
sbc pmPitchTableHi+1,y
sta pzTempPitchHi
;Shift Down Difference to get step size through semitone
jsr pbPerformShifts
;Transfer result to Channel Pitch Interpolation Step Tables
lda pzTempPitchLo
sta pbChannelInterpolationStepLo,x
lda pzTempPitchHi
sta pbChannelInterpolationStepHi,x
;Reset Interpolation Step accumulator
lda #00
sta pbChannelInterpolationAccumulatorLo,x
sta pbChannelInterpolationAccumulatorHi,x
;Reset Count
lda pmStepRefer,x
sta pmStepCount,x
;If either SID or Sample RapidReg used then perform shifting on fractional step too
;Is SID Active on this channel?
cpx SIDActivity
bne ContinueDescending3
;Calculate Difference in Fracs
lda rssFracStepLo+1,y
sec
sbc rssFracStepLo,y
sta pzTempPitchLo
lda rssFracStepHi+1,y
sbc rssFracStepHi,y
sta pzTempPitchHi
;Shift Down Difference to get step size through semitone
jsr pbPerformShifts
;Transfer result to Rapid Pitch Interpolation Step Tables
lda pzTempPitchLo
sta pbRapidInterpolationStepLo,x
lda pzTempPitchHi
sta pbRapidInterpolationStepHi,x
;Reset Interpolation Step accumulator
lda #00
sta pbRapidInterpolationAccumulatorLo,x
sta pbRapidInterpolationAccumulatorHi,x
;Fetch Current Ornament resultant note
jmp ContinueDescending2
ContinueDescending
;Transfer Current Ornament resultant note to Y
; tay
;Process Rapid Register Pitchbend?
cpx SIDActivity
bne ContinueDescending3
ContinueDescending2
;Accumulate Interpolation Steps in Accumulator
jsr AccumulateSIDInterpolationSteps
;Subtract from Current Ornament resultant note(Y) pitch and store result to SID Frac
lda rssFracStepLo,y
clc
adc pbRapidInterpolationAccumulatorLo,x
sta FracSIDLR+1
lda rssFracStepHi,y
adc pbRapidInterpolationAccumulatorHi,x
sta FracSIDHR+1
ContinueDescending3
;Process Channel Pitchbend (Note in Y)
;Accumulate Interpolation Steps in Accumulator
jsr AccumulateInterpolationSteps
ContinueDescending4
;Subtract from Current Ornament resultant note(Y) pitch
lda pmPitchTableLo,y
adc pbChannelInterpolationAccumulatorLo,x
sta pzIntermediatePitchLo
lda pmPitchTableHi,y
adc pbChannelInterpolationAccumulatorHi,x
sta pzIntermediatePitchHi
rts
Ascend ;Ascend
dec pmStepCount,x
bpl ContinueAscending
;Set up next Semitone Interpolation
;Increment Pattern Note
inc pmPatternNote,x
;But Use Note after Ornament has dealt with it(A-1)
tya
iny
cmp pbDestinationNote,x
.(
bne skip1
lda #00
sta pbFlag,x
;Still need to setup intermidiate pitch
dec pmPatternNote,x
lda pmPitchTableLo-1,y
sta pzIntermediatePitchLo
lda pmPitchTableHi-1,y
sta pzIntermediatePitchHi
rts
skip1 ;Fetch pitch of this semitone, subtract from next to get difference
.)
lda pmPitchTableLo-1,y
sec
sbc pmPitchTableLo,y
sta pzTempPitchLo
lda pmPitchTableHi-1,y
sbc pmPitchTableHi,y
sta pzTempPitchHi
;Shift Down Difference to get step size through semitone
jsr pbPerformShifts
;Transfer result to Channel Pitch Interpolation Step Tables
lda pzTempPitchLo
sta pbChannelInterpolationStepLo,x
lda pzTempPitchHi
sta pbChannelInterpolationStepHi,x
;Reset Interpolation Step accumulator
lda #00
sta pbChannelInterpolationAccumulatorLo,x
sta pbChannelInterpolationAccumulatorHi,x
;Reset Count
lda pmStepRefer,x
sta pmStepCount,x
;If Rapid Register used(2+) then perform shifting on fractional step too
cpx SIDActivity
bne ContinueAscending3
;Calculate Difference in Fracs
lda rssFracStepLo,y
sec
sbc rssFracStepLo-1,y
sta pzTempPitchLo
lda rssFracStepHi,y
sbc rssFracStepHi-1,y
sta pzTempPitchHi
;Shift Down Difference to get step size through semitone
jsr pbPerformShifts
;Transfer result to Rapid Pitch Interpolation Step Tables
lda pzTempPitchLo
sta pbRapidInterpolationStepLo,x
lda pzTempPitchHi
sta pbRapidInterpolationStepHi,x
;Reset Interpolation Step accumulator
lda #00
sta pbRapidInterpolationAccumulatorLo,x
sta pbRapidInterpolationAccumulatorHi,x
;Fetch Current Ornament resultant note
jmp ContinueAscending2
ContinueAscending
;Transfer Current Ornament resultant note to Y
; tay
;Process SID Pitchbend?
cpx SIDActivity
bne ContinueAscending3
ContinueAscending2
;Accumulate Interpolation Steps in Accumulator
jsr AccumulateSIDInterpolationSteps
;Add to Current Ornament resultant note(Y) pitch to SID
lda rssFracStepLo,y
sec
sbc pbRapidInterpolationAccumulatorLo,x
sta FracSIDLR+1
lda rssFracStepHi,y
sbc pbRapidInterpolationAccumulatorHi,x
sta FracSIDHR+1
ContinueAscending3
;Process Channel Pitchbend (Note in Y)
;Accumulate Interpolation Steps in Accumulator
jsr AccumulateInterpolationSteps
ContinueAscending4
;Add to Current Ornament resultant note(Y) pitch
lda pmPitchTableLo,y
sec
sbc pbChannelInterpolationAccumulatorLo,x
sta pzIntermediatePitchLo
lda pmPitchTableHi,y
sbc pbChannelInterpolationAccumulatorHi,x
sta pzIntermediatePitchHi
rts
;Shift Down steps through semitone
pbPerformShifts
;Fetch Number of Shifts
lda pbBranchStep,x ;0,4,8,etc.
sta pbBranchVector+1
pbBranchVector
bne ShiftCod1
ShiftCode lsr pzTempPitchHi ;0
ror pzTempPitchLo
ShiftCod1 lsr pzTempPitchHi ;1
ror pzTempPitchLo
lsr pzTempPitchHi ;2
ror pzTempPitchLo
lsr pzTempPitchHi ;3
ror pzTempPitchLo
lsr pzTempPitchHi ;4
ror pzTempPitchLo
lsr pzTempPitchHi ;5
ror pzTempPitchLo
lsr pzTempPitchHi ;6
ror pzTempPitchLo
;7 (Glissando)
rts
AccumulateInterpolationSteps
lda pbChannelInterpolationAccumulatorLo,x
clc
adc pbChannelInterpolationStepLo,x
sta pbChannelInterpolationAccumulatorLo,x
lda pbChannelInterpolationAccumulatorHi,x
adc pbChannelInterpolationStepHi,x
sta pbChannelInterpolationAccumulatorHi,x
rts
AccumulateSIDInterpolationSteps
lda pbRapidInterpolationAccumulatorLo,x
clc
adc pbRapidInterpolationStepLo,x
sta pbRapidInterpolationAccumulatorLo,x
lda pbRapidInterpolationAccumulatorHi,x
adc pbRapidInterpolationStepHi,x
sta pbRapidInterpolationAccumulatorHi,x
rts
;Effect Modifiers
; xx00 Loop or End(0)
; xx10 Noise Off
; xx20 EG Off
; xx30 Tone Off
; xx40 Volume Offset >>
; xx50 Noise Offset +Noise On
; xx60 EGPeriod Offset +EG On>>
; xx70 Pitch Offset +Tone On
PageAllignedEffectCommands
.dsb 256-(*&255)
pmeLoopOrEnd ;00
ldy pmEffectID,x
lda mmEffectLoops,y
bpl pmeLoop
;Just End
lda pzMusicElementActivity
and pmToneMask,x
sta pzMusicElementActivity
rts
pmeNoiseOff ;10
lda ayStatus
ora pmNoiseBit,x
sta ayStatus
sec
rts
;space to 16 bytes
pmeLoop tay
sec
rts
CompositeKey .byt 0
PatternID .byt 0
PatternCursorX .byt 0
PatternCursorY .byt 0
pmeEGOff ;20
lda ayVolume,x
and #15
sta ayVolume,x
lda #00
sta pmEGActiveFlag,x
sec
rts
;space to 16 bytes
OrnamentID .byt 0
OrnamentBaseIndex .byt 0
OrnamentCursorY .byt 0
pmeToneOff ;30
lda ayStatus
ora pmToneBit,x
sta ayStatus
sec
rts
;space to 16 bytes
EffectID .byt 0
EffectBaseIndex .byt 0
EffectCursorY .byt 0
EffectLoopIndex .byt 0
EffectTemp01 .byt 0
dsTemp01 .byt 0
Grabbed_EffectEntryByte .byt 0
pmeVolumeOFS ;40
adc pmPatternVolume,x
cmp #16
bcs EndEffect
sta pmPatternVolume,x
sta ayVolume,x
clc
rts
;space to 16 bytes
SourceIndex .byt 0
ScreenRows .byt 0
pmeNoiseOFS ;15
adc ayNoise
and #31
sta ayNoise
lda ayStatus
and pmNoiseMask,x
sta ayStatus
sec
rts
;space to 16 bytes
SampleCursorY .byt 0
pmeEGPerOFS ;15
adc ayEGPeriod
sta ayEGPeriod
lda ayVolume,x
ora #16
sta ayVolume,x
sta pmEGActiveFlag,x
clc
rts
;space to 16 bytes
PreviousEditorID .byt 0
pmePitchOFS ;-
.(
;A pitch offset is always relative to the Intermediate Pitch
sta pzTemp01
adc pzIntermediatePitchLo
sta pzIntermediatePitchLo
bit pzTemp01
bmi skip2
bcc skip1