-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathP6112-Play.asm
4302 lines (3998 loc) · 95.3 KB
/
P6112-Play.asm
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
; #-----+-----------------------------------------#
; |Name:| P6112 Example Source |
; +-----+-----------------------------------------+
; |V1.06| P6112,E1x/E2x fix |
; |V1.05| P6111,Edx fix,init/exit patch,Dxx note. |
; |V1.04| P6110 final, E6x command fix+new option |
; |V1.03| Final, compatibility changes only. |
; |V1.02| Made more user friendly |
; |V1.01| Plays the example P61 song until you |
; | | press the left mouse button. |
; +-----+-----------------------------------------+
; | Photon/Scoopex |
; #-----------------------------------------------#
;Tutorial here: http://youtu.be/xBtHO-IuN9E
;Put it in your demo: http://youtu.be/JYLcIR6tyO4
;Relevant Protracker, P61, music, and code articles on http://coppershade.org
;I'm leaving the P61 project. Read sources and docs.
;I now strictly follow a "Don't ask, don't tell" policy :D
;(I know I said the same in P6111, but I made an exception because it would be
;unnecessarily hard to spot the erroneous line for a coder coming in.)
;If the song works here but not in your demo, the playroutine is okay. Check
;that you have selected the right mode. P61_Music is called automatically in
;p61mode 1 (CIA interrupt, remember?),so don't call it anywhere in your source.
;older notes:
;NOTE: it is now extra important that you SET THE USECODE. See the Special Note
;in P6112-Play.i for why. TIP: using 80x for syncing (timing) instead of E8x
;won't make the song sound worse in non-legacy trackers. It's plug and play,
;just swap them out.
;This example demonstrates simple syncing Set visuctrs=1 to see them :)
;There also 3 commands you can use for module-controller syncing (80x recommen-
;ded), and an oscilloscope ptrs option as well.
;This source demonstrates non-system, non-exec mode. (That means that it can
;also be used in trackmos where you're using ALL low chipmem ;) )
;It uses an AGA compatible startup that shows a simple copper with a copper
;interrupt request trigger that you poll in the frame loop to wait for a raster
;position. (I.e. you can turn it into a proper copper interrupt).
;Compatibility: You can assemble with or without Label: option.
;Any case-sensitivity and "special operators" issues should be gone.
;Esau/Traktor sent me a nice module to include (thanks!), if it's too big for
;your chipmem left, try one of the smaller ones.
;IT CAN BE USED IN 4 MODES:
;-------------------------
; 1 CIA mode. Plays any song. Uses the CIA interrupt.
; - (default, P61_Music should not be called, easiest to use)
; 2 VBLANK mode. No F20 or higher commands must be used in the song.
; - (use when you want to decide when P61_Music should be called.)
; 3 COPPER mode. No F20 or higher commands must be used in the song.
; - (requires a timed call to P61_Music and a timed copper command
; 11 scanlines later to set sound DMA.)
; 4 MAXOPTI mode. No F20 or higher commands must be used in the song.
; - (requires a timed call to P61_Music and a timed copper command
; 11 scanlines later to set sound DMA. Maximum optimized.)
P61mode =1 ;Try other modes ONLY IF there are no Fxx commands >= 20.
;(f.ex., P61.new_ditty only works with P61mode=1)
;; --- options common to all P61modes ---
usecode =$9600 ;CHANGE! to the USE hexcode from P61con for a big
;CPU-time gain! (See module usecodes at end of source)
;Multiple songs, single playroutine? Just "OR" the
;usecodes together!
;...STOP! Have you changed it yet!? ;)
;You will LOSE RASTERTIME AND FEATURES if you don't.
P61pl=usecode&$400000
split4 =0 ;Great time gain, but INCOMPATIBLE with F03, F02, and F01
;speeds in the song! That's the ONLY reason it's default 0.
;So ==> PLEASE try split4=1 in ANY mode!
;Overrides splitchans to decrunch 1 chan/frame.
;See ;@@ note for P61_SetPosition.
splitchans=1 ;#channels to be split off to be decrunched at "playtime frame"
;0=use normal "decrunch all channels in the same frame"
;Experiment to find minimum rastertime, but it should be 1 or 2
;for 3-4 channels songs and 0 or 1 with less channels.
visuctrs=1 ;enables visualizers in this example: P61_visuctr0..3.w
;containing #frames (#lev6ints if cia=1) elapsed since last
;instrument triggered. (0=triggered this frame.)
;Easy alternative to E8x or 1Fx sync commands.
asmonereport =0 ;ONLY for printing a settings report on assembly. Use
;if you get problems (only works in AsmOne/AsmPro, tho)
p61system=0 ;1=system-friendly. Use for DOS/Workbench programs.
p61exec =0 ;0 if execbase is destroyed, such as in a trackmo.
p61fade =0 ;enable channel volume fading from your demo
channels=4 ;<4 for game sound effects in the higher channels. Incompatible
; with splitchans/split4.
playflag=0 ;1=enable music on/off capability (at run-time). .If 0, you can
;still do this by just, you know, not calling P61_Music...
;It's a convenience function to "pause" music in CIA mode.
p61bigjtab=0 ;1 to waste 480b and save max 56 cycles on 68000.
opt020 =0 ;1=enable optimizations for 020+. Please be 68000 compatible!
;splitchans will already give MUCH bigger gains, and you can
;try the MAXOPTI mode.
p61jump =0 ;0 to leave out P61_SetPosition (size gain)
;1 if you need to force-start at a given position fex in a game
C =0 ;If you happen to have some $dffxxx value in a6, you can
;change this to $xxx to not have to load it before P61_Music.
clraudxdat=0 ;enable smoother start of quiet sounds. probably not needed.
optjmp =1 ;0=safety check for jump beyond end of song. Clear it if you
;play unknown P61 songs with erroneous Bxx/Dxx commands in them
oscillo =0 ;1 to get a sample window (ptr, size) to read and display for
;oscilloscope type effects (beta, noshorts=1, pad instruments)
;IMPORTANT: see ;@@ note about chipmem dc.w buffer.
quietstart=0 ;attempt to avoid the very first click in some modules
;IMPORTANT: see ;@@ note about chipmem dc.w buffer.
use1Fx=0 ;Optional extra effect-sync trigger (*). If your module is free
;from E commands, and you add E8x to sync stuff, this will
;change the usecode to include a whole code block for all E
;commands. You can avoid this by only using 1Fx. (You can
;also use this as an extra sync command if E8x is not enough,
;of course.)
;(*) Slideup values>116 causes bugs in Protracker, and E8 causes extra-code
;for all E-commands, so I used this. It's only faster if your song contains 0
;E-commands, so it's only useful to a few, I guess. Bit of cyclemania. :)
;Just like E8x, you will get the trigger after the P61_Music call, 1 frame
;BEFORE it's heard. This is good, because it allows double-buffered graphics
;or effects running at < 50 fps to show the trigger synced properly.
;; --- CIA mode options (default) ---
ifeq P61mode-1
p61cia =1 ;call P61_Music on the CIA interrupt instead of every frame.
lev6 =1 ;1=keep the timer B int at least for setting DMA.
;0="FBI mode" - ie. "Free the B-timer Interrupt".
;0 requires noshorts=1, p61system=0, and that YOU make sure DMA
;is set at 11 scanlines (700 usecs) after P61_Music is called.
;AsmOne will warn you if requirements are wrong.
;DMA bits will be poked in the address you pass in A4 to
;P61_init. (Update P61_DMApokeAddr during playing if necessary,
;for example if switching Coppers.)
;P61_Init will still save old timer B settings, and initialize
;it. P61_End will still restore timer B settings from P61_Init.
;So don't count on it 'across calls' to these routines.
;Using it after P61_Init and before P61_End is fine.
noshorts=0 ;1 saves ~1 scanline, requires Lev6=0. Use if no instrument is
;shorter than ~300 bytes (or extend them to > 300 bytes).
;It does this by setting repeatpos/length the next frame
;instead of after a few scanlines,so incompatible with MAXOPTI
dupedec =0 ;0=save 500 bytes and lose 26 cycles - I don't blame you. :)
;1=splitchans or split4 must be on.
suppF01 =1 ;0 is incompatible with CIA mode. It moves ~100 cycles of
;next-pattern code to the less busy 2nd frame of a notestep.
;If you really need it, you have to experiment as the support
;is quite complex. Basically set it to 1 and try the various
;P61modes, if none work, change some settings.
endc
;; --- VBLANK mode options ---
ifeq P61mode-2
p61cia =0
lev6 =1 ;still set sound DMA with a simple interrupt.
noshorts=0 ;try 1 (and pad short instruments if nec) for 1 scanline gain
dupedec =0
suppF01 =P61pl ;if 1, split4=1 may cause sound errors. but try it anyway. :)
endc
;; --- COPPER mode options ---
ifeq P61mode-3
p61cia =0
lev6 =0 ;don't set sound DMA with an interrupt.
;(use the copper to set sound DMA 11 scanlines after P61_Music)
noshorts=1 ;You must pad instruments < 300 bytes for this mode to work.
dupedec =0
suppF01 =P61pl ;if 1, split4=1 may cause sound errors. but try it anyway. :)
endc
;; --- MAXOPTI mode options ---
ifeq P61mode-4
p61cia =0
lev6 =0
noshorts=1 ;You must pad instruments < 300 bytes for this mode to work.
dupedec =1
suppF01 =P61pl ;if 1, split4=1 may cause sound errors. but try it anyway. :)
endc
; #-----+-----------------------------------------#
; |Name:| P6112 - Optimized Player 6.1 Playroutine|
; +-----+-----------------------------------------+
; |V1.06| P6112,E1x/E2x fix |
; |V1.05| P6111, EDx fix,better init/exit,Dxx note|
; |V1.04| P6110, E6x command fix+new option |
; |V1.03| P6109, compatibility changes only. |
; |V1.02| Cleaned up P6108 with minor changes. |
; |V1.01| 2.4-3 scanlines faster than my p6107. |
; | | SLen (song length) bug fixed |
; | | lev6 implemented with "poke DMA here" |
; | | Two options for clickless sound start |
; | | P61_Osc precis samplewindow tracking |
; | | Many optimization options - read the |
; | | info or leave them at defaults. |
; +-----+-----------------------------------------+
; | by Photon/Scoopex |
; #-----------------------------------------------#
;SPECIAL NOTE FOR THIS VERSION:
;-----------------------------
;Tutorial here: http://youtu.be/xBtHO-IuN9E
;Put it in your demo: http://youtu.be/JYLcIR6tyO4
;I'm leaving the P61 project, feeling I've left it in good shape.
;There is nothing left to optimize, and I've gone through everything I could
;find that was bad and fixed it.
;I support this only with the readme.txt and all the comment documentation.
;Please follow the advice in my Youtube tutorial specifically made for adding
;P61 to your demo before deciding the playroutine is at fault. If you are sure
;you have found a bug, fix it yourself.
;A song must fail in the example source and play correctly in P61con, before
;you can suspect the playroutine is at fault.
;A note on syncing: apart from the new options for $1Fx, channel triggers, and
;oscilloscope ptrs I added, you should no longer ask musicians to scatter E8x
;commands in the song. Don't worry, it plays fine in P61 and always has.
;But some non-legacy trackers destroy the loop with a filter where E8x commands
;are used. 80x is an alternative, which works in all trackers, according to
;them. To use it, just replace E8x with 80x in the module and you need change
;nothing else.
;P6112:
;E1x/E2x fix. One line changed in the source, in the GetNote macro used by
;these two effects combined with a note trigger (i.e. for F-3 E1x, not --- E1x)
;P6111:
;- Fix notedelay bug introduced in P6108
;- Fix in legacy code, CIA regs were modified in init/exit even when p61_cia=0.
;- Verified that $9xx offset behavior takes effect at loop end, a behavior
;used by chip musicians.
;Dxx command: P61 has never implemented Dxx support other than for xx=00.
;I took a good look, and the way I see it, only pointers to previously
;decrunched notesteps are stored. This means patternloop backjumps work, but
;forward jumps to some offset from the pattern start pointer - doesn't.
;xx steps must first be decrunched. This will cause a spike in rastertime
;(CPU load) used, which is counter to my efforts to make the P61 playroutine
;match the performance of optimized normal Protracker playroutines.
;So I've decided to not implement it. Instead, musicians are recommended to
;copy the jumped-to pattern and delete xx notes to make the offset=0. Then
;the Dxx command can be changed to a D00 command, which is supported.
;The copied pattern will only add 16 bytes or so to the filesize, and
;performance will remain excellent.
;---
;P6110: A bug regarding Patternloops (E6x) was introduced in P6108 when I added
;super optimization flags. This is fixed, but it also revealed the obvious:
;that Patternloop is incompatible with suppF01=0. The example will set this
;automatically for you, but you will not get the great speed gains if you try
;split4=1 unless you SET THE USECODE PROPERLY.
;Of course all modes will work properly if you leave everything at default
;in the example, but I recommend to set the usecode to get the most out of p61
; - not just the size gain.
;Also, new option: set visuctrs=1 to get elapsed time since last instrument
;trigger in P61visuctr0..3.
;NOTE: vasm users MUST turn optimizations off for the jmp xx(PC) instructions
;in the jump tables and at P61_motuuli. If not, the source will assemble
;without errors, but generate bra.b which WILL cause fatal run-time errors.
;May the Source be with you! //Photon
;Credits to Jarno for V6.1A, and bugfixers up to 6.1.0.6.
;(Notes from previous versions below.)
* The Player 6.1A - by Guru / Sahara Surfers
* Interrupt problem with 060 fixed by NoName/Haujobb^Sector 7
* Some Enforcer Hits fixed by Platon42
* Memory trashing bug in routine P61_End fixed by Tolkien
* Bug in routine P61_Init (when opt020=1) fixed by The Dark Coder/Trinity^Morbid Visions
* for Devpac 3, ASM-One, PhxAss and maybe some other assemblers
*
* NEEDS: Default sizes must be words (ASM-One default...)
* Preferably no optimizations on (the jump table must be word jumps)
*
* Tested with Devpac 3.04 by Guru
* Tested with PhxAss 4.14, Asm-Pro 1.1 and ASM-One 1.29
*
* Note 1:All the bugfixes done after version 610.2 (the latest release from
* Guru / Sahara Surfers) are marked with the comment "* BUGFIX"
* followed by some explanations, so that if can quickly copy them
* into a previous version tailored to your needs.
*
* Note 2:The unelegant double WRITE to INTREQ unforunately seems to be
* the best solution to the "interrupt problem" that occurs on
* some 040/060 equipped Amiga. On many 040/060 Amigas it is enough
* to put an access to whatever hardware register and a NOP between
* the first write to INTREQ and he RTE. However we had reports that
* on some Amiga it is really necessary to do a double write to INTREQ
********************************
* Player 6.1A � *
* All in one-version *
* Version 610.6 *
* � 1992-95 Jarno Paananen *
* All rights reserved *
* Fixed by: NoName, Platon42, *
* Tolkien and The Dark Coder *
********************************
nowaveforms=noshorts
copdma=1-lev6
Custom_Block_Size=16 ;d7 used to replace clr.* instead of this const
ifnd player61_i
player61_i:set 1
ifnd exec_types_i
exec_types_i:set 1
include_version:equ 40
extern_lib:macro
xref _lvo\1
endm
structure:macro
\1:equ 0
soffset:set \2
endm
fptr:macro
\1:equ soffset
soffset:set soffset+4
endm
bool:macro
\1:equ soffset
soffset:set soffset+2
endm
byte:macro
\1:equ soffset
soffset:set soffset+1
endm
ubyte:macro
\1:equ soffset
soffset:set soffset+1
endm
word:macro
\1:equ soffset
soffset:set soffset+2
endm
uword:macro
\1:equ soffset
soffset:set soffset+2
endm
short:macro
\1:equ soffset
soffset:set soffset+2
endm
ushort:macro
\1:equ soffset
soffset:set soffset+2
endm
long:macro
\1:equ soffset
soffset:set soffset+4
endm
ulong:macro
\1:equ soffset
soffset:set soffset+4
endm
float:macro
\1:equ soffset
soffset:set soffset+4
endm
double:macro
\1:equ soffset
soffset:set soffset+8
endm
aptr:macro
\1:equ soffset
soffset:set soffset+4
endm
cptr:macro
\1:equ soffset
soffset:set soffset+4
endm
rptr:macro
\1:equ soffset
soffset:set soffset+2
endm
label:macro
\1:equ soffset
endm
struct:macro
\1:equ soffset
soffset:set soffset+\2
endm
alignword:macro
soffset:set (soffset+1)&$fffffffe
endm
alignlong:macro
soffset:set (soffset+3)&$fffffffc
endm
enum:macro
ifc '\1',''
eoffset:set 0
endc
ifnc '\1',''
eoffset:set \1
endc
endm
eitem:macro
\1:equ eoffset
eoffset:set eoffset+1
endm
bitdef0:macro
\1\3\2:equ \4
endm
bitdef:macro
bitdef0 \1,\2,b_,\3
\@bitdef:set 1<<\3
bitdef0 \1,\2,f_,\@bitdef
endm
library_minimum:equ 33
endc ;ifnd
structure Player_Header,0
ulong P61_InitOffset
ulong P61_MusicOffset
ulong P61_EndOffset
ulong P61_SetRepeatOffset
ulong P61_SetPositionOffset
uword P61_MasterVolume
uword P61_UseTempo
uword P61_PlayFlag
uword P61_E8_info
aptr P61_UseVBR
uword P61_Position
uword P61_Pattern
uword P61_Row
aptr P61_Cha0Offset
aptr P61_Cha1Offset
aptr P61_Cha2Offset
aptr P61_Cha3Offset
label Player_Header_SIZE
structure Channel_Block,0
ubyte P61_SN_Note
ubyte P61_Command
ubyte P61_Info
ubyte P61_Pack
aptr P61_Sample
uword P61_OnOff
aptr P61_ChaPos
aptr P61_TempPos
uword P61_TempLen
uword P61_Note
uword P61_Period
uword P61_Volume
uword P61_Fine
uword P61_Offset
uword P61_LOffset
uword P61_ToPeriod
uword P61_TPSpeed
ubyte P61_VibCmd
ubyte P61_VibPos
ubyte P61_TreCmd
ubyte P61_TrePos
uword P61_RetrigCount
ubyte P61_Funkspd
ubyte P61_Funkoff
aptr P61_Wave
uword P61_TData
aptr P61_TChaPos
aptr P61_TTempPos
uword P61_TTempLen
uword P61_Shadow
ifne oscillo ;Filled in by P61_osc call (div ptrs by 4)
aptr P61_oscptr ;points to end of current frame's sample-chunk.
uword P61_oscptrrem ;remainder for precision (internal use only)
aptr P61_oscptrWrap ;wrap (end) pointer for current Paula soundloop
endc
uword P61_DMABit
label Channel_Block_Size
structure Sample_Block,0
aptr P61_SampleOffset
uword P61_SampleLength
aptr P61_RepeatOffset
uword P61_RepeatLength
uword P61_SampleVolume
uword P61_FineTune
label Sample_Block_SIZE
P61_ft=usecode&1
P61_pu=usecode&2
P61_pd=usecode&4
P61_tp=usecode&40
P61_vib=usecode&80
P61_tpvs=usecode&32
P61_vbvs=usecode&64
P61_tre=usecode&$80
P61_arp=usecode&$100
P61_sof=usecode&$200
P61_vs=usecode&$400
P61_pj=usecode&$800
P61_vl=usecode&$1000
P61_pb=usecode&$2800
P61_sd=usecode&$8000
P61_ec=usecode&$ffff0000
P61_fi=usecode&$10000
P61_fsu=usecode&$20000
P61_fsd=usecode&$40000
P61_sft=usecode&$200000
P61_pl=usecode&$400000&((1-split4)*$400000) ;incompatible with split4.
P61_timing=usecode&$1000000
P61_rt=usecode&$2000000
P61_fvu=usecode&$4000000
P61_fvd=usecode&$8000000
P61_nc=usecode&$10000000
P61_nd=usecode&$20000000
P61_pde=usecode&$40000000
P61_il=usecode&$80000000
endc
ifne asmonereport
********** REPORT **********
printt ""
printt "Options used:"
printt "-------------"
ifne p61fade
printt "Mastervolume on"
else
printt "Mastervolume off"
endc
ifne p61system
printt "System friendly"
else
printt "System killer"
endc
ifne p61cia
printt "CIA-tempo on"
else
printt "CIA-tempo off"
endc
ifne p61exec
printt "ExecBase valid"
else
printt "ExecBase invalid"
endc
;; --- wicked nasty nested ifs ---
ifne lev6
printt "Level 6 IRQ on"
else
ifeq (noshorts&(1-p61system))
printt "FAIL: Non-lev6 NOT available for p61system=1 or noshorts=0!"
else
printt "Non-lev6 implemented with 'poke DMAbits byte to a specified address'."
printt "* READ DOCS for how to specify it and how it works."
endc ;noshorts&(1-p61system)
endc ;lev6
;; --- end of wicked nasty nested ifs ---
ifne opt020
printt "MC68020 optimizations"
else
printt "Normal MC68000 code"
endc
printt "Channels:"
printv channels
ifgt channels-4
printt "FAIL: More than 4 channels."
endc
ifeq channels
printt "FAIL: Can't have 0 channels."
endc
printt "UseCode:"
printv usecode
printt "Player binary size:"
printv P61E-P61B
********** REPORT END **********
endc ;ifne asmonereport
P61B:
P61_motuuli:
jmp P61_Init(PC)
ifeq p61cia
jmp P61_Music(PC)
else
rts
rts
endc
jmp P61_End(PC)
rts ;no P61_SetRepeat
rts
ifne p61jump
jmp P61_SetPosition(PC)
else
rts
rts
endc
P61_Master:
dc.w 64
P61_Tempo:
dc.w 1
P61_Play:
dc.w 1
P61_E8:
dc.w 0
P61_VBR:
dc.l 0
P61_Pos:
dc.w 0
P61_Patt:
dc.w 0
P61_CRow:
dc.w 0
P61_Temp0Offset:
dc.l P61_temp0-P61_motuuli
P61_Temp1Offset:
dc.l P61_temp1-P61_motuuli
P61_Temp2Offset:
dc.l P61_temp2-P61_motuuli
P61_Temp3Offset:
dc.l P61_temp3-P61_motuuli
P61_getnote:macro
moveq #$7e,d0
and.b (a5),d0
beq.b .nonote
ifne P61_vib
clr.b P61_VibPos(a5)
endc
ifne P61_tre
clr.b P61_TrePos(a5)
endc
ifne P61_ft
add P61_Fine(a5),d0
endc
move d0,P61_Note(a5)
move P61_periods-P61_cn(a3,d0),P61_Period(a5) ;P6112 fix.
.nonote:
endm
ifeq p61system
ifne p61cia
P61_intti:
movem.l d0-a6,-(sp)
tst.b $bfdd00
lea $dff000+C,a6
move #$2000,$9c-C(a6)
move #$2000,$9c-C(a6)
bsr P61_Music
movem.l (sp)+,d0-a6
nop
rte
endc
endc
ifne p61system
P61_lev6server:
movem.l d2-d7/a2-a6,-(sp)
lea P61_timeron(pc),a0
tst (a0)
beq.b P61_ohi
lea $dff000+C,a6
move P61_server(pc),d0
beq.b P61_musica
subq #1,d0
beq P61_dmason
ifeq nowaveforms
bra P61_setrepeat
else
bra.b P61_ohi
endc
P61_musica:
bsr P61_Music
P61_ohi:
movem.l (sp)+,d2-d7/a2-a6
moveq #1,d0
rts
endc
********** P61_Init **********
* Input: A0=P61-module addr.
* A1 [LONG] = 0 if samples are internal to the module
* Address of samples otherwise
* A2 [LONG] = Address of sample buffer if the module uses packed
* samples, otherwise can be left uninitialized
* A4 [LONG] = Address where 'DMA ON' byte (low 8 bits of DMACON)
* should be poked. ONLY used together with lev6=0.
* D0 [WORD] = 0 autodetect CIA Timer frequency, if ExecBase
* is valid otherwise assume PAL
* 1 assume PAL
* 2 assume NTSC
* [Used only in CIA-enabled mode]
* Uses: D0-A7, A6 set to $dff000+C (your custombase) at exit.
* Returns: D0=0 if okay (i.e. P61 module!). No need to change D0.l.
* NOTE: the define 'start' has been made runtime. move.w #<startpos>,P61_InitPos instead.
_P61_Init:
P61_Init:
lea $dff000+C,a6
ifeq p61system
ifne quietstart
move.w #$f,$96-C(A6) ;audiodma off
lea $a0-C(A6),a5 ;chan 0
lea P61_Quiet(PC),a3
moveq #0,d1
moveq #channels-1,d5
.choffl:move.l a3,(a5)+ ;ptr
move.l #1<<16+124,(a5)+ ;len, 'fastest common' period
move.l d1,(a5)+ ;quiet volume & audchan.
addq.w #4,a5
dbf d5,.choffl
endc
endc
cmp.l #"P61A",(a0)+
beq.b .modok
subq.l #4,a0
.modok:
ifne p61cia
move d0,-(sp)
endc
moveq #0,d0
cmp.l d0,a1
bne.b .redirect
move (a0),d0
lea (a0,d0.l),a1
.redirect:
move.l a2,a6
lea 8(a0),a2
moveq #$40,d0
and.b 3(a0),d0
bne.b .buffer
move.l a1,a6
subq.l #4,a2
.buffer:
lea P61_cn(pc),a3
move.w #$ff00,d1
move.w d1,P61_OnOff+P61_temp0-P61_cn(a3) ;stop active decsteps
move.w d1,P61_OnOff+P61_temp1-P61_cn(a3)
move.w d1,P61_OnOff+P61_temp2-P61_cn(a3)
move.w d1,P61_OnOff+P61_temp3-P61_cn(a3)
ifne copdma
move.l a4,p61_DMApokeAddr-P61_cn(a3)
endc
moveq #$1f,d1
and.b 3(a0),d1
move.l a0,-(sp)
;; --- insert pan/echo in this loop ---
lea P61_samples(pc),a4
subq #1,d1
moveq #0,d4
P61_lopos:
move.l a6,(a4)+
move (a2)+,d4
bpl.b P61_kook
neg d4
lea P61_samples-16(pc),a5
ifeq opt020
asl #4,d4
move.l (a5,d4),d6
else
add d4,d4
move.l (a5,d4*8),d6
endc
move.l d6,-4(a4)
ifeq opt020
move 4(a5,d4),d4
else
move 4(a5,d4*8),d4
endc
sub.l d4,a6
sub.l d4,a6
bra.b P61_jatk
P61_kook:
move.l a6,d6
tst.b 3(a0)
bpl.b P61_jatk
tst.b (a2)
bmi.b P61_jatk
move d4,d0
subq #2,d0
bmi.b P61_jatk
move.l a1,a5
move.b (a5)+,d2
sub.b (a5),d2
move.b d2,(a5)+
.loop:sub.b (a5),d2
move.b d2,(a5)+
sub.b (a5),d2
move.b d2,(a5)+
dbf d0,.loop
P61_jatk:
move d4,(a4)+
moveq #0,d2
move.b (a2)+,d2
moveq #0,d3
move.b (a2)+,d3
moveq #0,d0
move (a2)+,d0
bmi.b .norepeat
move d4,d5
sub d0,d5
move.l d6,a5
add.l d0,a5
add.l d0,a5
move.l a5,(a4)+
move d5,(a4)+
bra.b P61_gene
.norepeat:
move.l d6,(a4)+
move #1,(a4)+
P61_gene:
move d3,(a4)+
moveq #$f,d0
and d2,d0
mulu #74,d0
move d0,(a4)+
tst -6(a2)
bmi.b .nobuffer
moveq #$40,d0
and.b 3(a0),d0
beq.b .nobuffer
move d4,d7
tst.b d2
bpl.b .copy
subq #1,d7
moveq #0,d5
moveq #0,d4
.lo: move.b (a1)+,d4
moveq #$f,d3
and d4,d3
lsr #4,d4
sub.b .table(pc,d4),d5
move.b d5,(a6)+
sub.b .table(pc,d3),d5
move.b d5,(a6)+
dbf d7,.lo
bra.b .kop
.copy:
add d7,d7
subq #1,d7
.cob:
move.b (a1)+,(a6)+
dbf d7,.cob
bra.b .kop
.table:
dc.b 0,1,2,4,8,16,32,64,128,-64,-32,-16,-8,-4,-2,-1
.nobuffer:
move.l d4,d6
add.l d6,d6
add.l d6,a6
add.l d6,a1
.kop:
dbf d1,P61_lopos
move.l (sp)+,a0
and.b #$7f,3(a0)
move.l a2,-(sp)
lea P61_temp0(pc),a1
lea P61_temp1(pc),a2
lea P61_temp2(pc),a4
lea P61_temp3(pc),a5
moveq #Channel_Block_Size/2-2,d0
moveq #0,d1
.cl: move d1,(a1)+
move d1,(a2)+
move d1,(a4)+
move d1,(a5)+
dbf d0,.cl
lea P61_temp0-P61_cn(a3),a1
lea P61_emptysample-P61_cn(a3),a2
moveq #channels-1,d0
.loo:
move.l a2,P61_Sample(a1)
lea Channel_Block_Size(a1),a1
dbf d0,.loo
move.l (sp)+,a2
move.l a2,P61_positionbase-P61_cn(a3)
moveq #$7f,d1
and.b 2(a0),d1
ifeq opt020
lsl #3,d1
lea (a2,d1.l),a4
else
lea (a2,d1.l*8),a4
endc
move.l a4,P61_possibase-P61_cn(a3) ;base to pos. indices.
move.l a4,a1
moveq #-1,d0
.search:
cmp.b (a1)+,d0
bne.b .search
move.l a1,P61_patternbase-P61_cn(a3)
move.l a1,d0
sub.l a4,d0
subq.w #1,d0 ;this is the * BUGFIX! whoa!
move d0,P61_slen-P61_cn(a3)
;; --- Bugfix: P61_Init gives P61_slen=actual songlength +1.
;; --- This did not affect NextPattern, because it looks for endbyte flag.
;; --- It did affect Bxx/Dxx, but I guess nobody has tried to jump or
;; --- break to Last Pattern, ever. Now fixed to set correct SLen and
;; --- suddenly Bxx/Dxx/Setposition works as they should. //Photon
add.w P61_InitPos(pc),a4 ;position from which to start playing the song
moveq #0,d0
move.b (a4)+,d0
move.l a4,P61_spos-P61_cn(a3)
lsl #3,d0
add.l d0,a2
move.l a1,a4
moveq #0,d0 ;hi word must be clear to manage >32K of patterns
move (a2)+,d0 ;and no movem-signextend. This code is correct.
lea (a4,d0.l),a1