source: buchla-68k/ram/procpfl.s @ 8325447

Last change on this file since 8325447 was 8325447, checked in by Thomas Lopatic <thomas@…>, 2 years ago

Removed _ prefix.

  • Property mode set to 100644
File size: 24.7 KB
Line 
1| ------------------------------------------------------------------------------
2| procpfl.s -- process pendant functions  (sustain release processing)
3| Version 8 -- 1988-08-31 -- D.N. Lynx Crowe
4| ------------------------------------------------------------------------------
5                .text
6
7                .xdef   procpfl
8
9                .xdef   _curpf_f        | current function (v/p)
10                .xdef   _curpf_l        | current pflist entry
11                .xdef   _curpf_t        | current trigger
12
13                .xref   irand
14                .xref   xgetran
15
16                .xref   expbit
17                .xref   funcndx
18                .xref   pflist
19                .xref   pfqhdr
20                .xref   prstab
21                .xref   ptoftab
22                .xref   timemlt
23                .xref   trgtab
24                .xref   valents
25                .xref   vce2grp
26                .xref   vce2trg
27                .xref   veltab
28
29                .page
30| ------------------------------------------------------------------------------
31| Register usage
32| --------------
33|       d0      scratch
34|       d1      FPU function index
35|       d2      point index from FH_CPT  (idfcpt)
36|       d3      scratch
37|       d4      jump point number from PT_PAR1  (ippar1)
38|       d5      scratch
39
40|       a0      scratch
41|       a1      function header base
42|       a2      point table base
43|       a3      FPU base
44
45| ------------------------------------------------------------------------------
46| FPU definitions
47| ---------------
48
49UPD_BIT         =       0x0001                  | update bit  (1 = update)
50INT_BIT         =       0x0002                  | int. bit    (0 = disable)
51RAT_BIT         =       0x0004                  | ratio bit   (0 = ratio)
52
53VSUBNBIT        =       3                       | new value select bit number
54VAL_BITS        =       0x0018                  | new value select bit mask
55
56MSK_RNVB        =       0x000C                  | new value / ratio bits
57MSK_ONVB        =       0x0010                  | old new value bit
58
59FKILL           =       0x0014                  | kill value for function
60FSEND           =       0x0015                  | send new value to function
61
62CLREXP          =       0x8000                  | clear value for time exponent
63CLRMNT          =       0x8000                  | clear value for time mantissa
64
65| ------------------------------------------------------------------------------
66| Miscellaneous definitions
67| -------------------------
68
69PCHMAX          =       21920                   | maximum pitch value
70VALMAX          =       32000                   | maximum value to send to FPU
71VALMIN          =       -32000                  | minimum value to send to FPU
72
73LSPCH           =       2                       | left shift for sources to freq
74
75VALLEN          =       10                      | length of the 'valent' struct
76VT_VAL          =       8                       | value offset in 'valent'
77
78                .page
79| ------------------------------------------------------------------------------
80| FPU addresses
81| -------------
82
83FPUBASE         =       0x180000                | FPU base address
84
85FPUWST          =       FPUBASE                 | FPU waveshape base
86FPUFUNC         =       FPUBASE+0x4000          | FPU function base
87FPUINT1         =       FPUBASE+0x4000          | FPU int. input address (R/O)
88FPUINT2         =       FPUBASE+0x6000          | FPU int. reset address (W/O)
89FPUCFG          =       FPUBASE+0x5FE0          | FPU config. data address (W/O)
90
91F_CTL           =       0x00                    | control word
92F_VAL10         =       0x02                    | new value "10"
93F_CV1           =       0x08                    | control voltage 1
94F_SF1           =       0x0A                    | scale factor 1
95F_CV2           =       0x0C                    | control voltage 2
96F_SF2           =       0x0E                    | scale factor 2
97F_CV3           =       0x10                    | control voltage 3
98F_SF3           =       0x12                    | scale factor 3
99F_MNT           =       0x14                    | time mantissa
100F_EXP           =       0x16                    | time exponent
101F_VAL01         =       0x1C                    | new value "01"
102
103P_FREQ1         =       0x0020                  | frequency 1
104P_FREQ2         =       0x0060                  | frequency 2
105P_FREQ3         =       0x00A0                  | frequency 3
106P_FREQ4         =       0x00E0                  | frequency 4
107P_FILTER        =       0x0140                  | filter
108P_FILTRQ        =       0x00C0                  | filter q
109
110P_INDEX1        =       0x0120                  | index 1
111P_INDEX2        =       0x0160                  | index 2
112P_INDEX3        =       0x0180                  | index 3
113P_INDEX4        =       0x01A0                  | index 4
114P_INDEX5        =       0x01C0                  | index 5
115P_INDEX6        =       0x01E0                  | index 6
116
117P_LEVEL         =       0x0040                  | level
118
119P_LOCN          =       0x0080                  | location
120P_DYNAM         =       0x0100                  | dynamics
121
122                .page
123| ------------------------------------------------------------------------------
124| Structure definitions
125| ------------------------------------------------------------------------------
126| The following MUST match the idfnhdr structure definition in instdsp.h:
127
128FH_LEN          =       12              | length of the idfnhdr structure
129
130FH_PCH          =       0               | WORD - pitch offset
131FH_MLT          =       2               | WORD - overall value multiplier
132FH_SRC          =       4               | BYTE - overall value source
133FH_PIF          =       5               | BYTE - # of points in the function
134FH_PT1          =       6               | BYTE - index of first point
135FH_TMD          =       7               | BYTE - trigger mode / control bits
136FH_CPT          =       8               | BYTE - current point
137FH_PRM          =       9               | BYTE - misc. function parameter
138FH_TRG          =       10              | WORD - trigger
139
140I_ACTIVE        =       1               | 'Active' bit number        (in FH_TMD)
141
142MSK_CTL         =       0x001C          | mask for FPU hardware bits (in FH_TMD)
143
144| ------------------------------------------------------------------------------
145| The following MUST match the instpnt structure definition in instdsp.h:
146
147PT_LEN          =       12              | length of the instpnt structure
148
149PT_TIM          =       0               | WORD - time (packed)
150PT_VAL          =       2               | WORD - value
151PT_VMLT         =       4               | WORD - value multiplier
152PT_VSRC         =       6               | BYTE - value source
153PT_ACT          =       7               | BYTE - action
154PT_PAR1         =       8               | BYTE - parameter 1
155PT_PAR2         =       9               | BYTE - parameter 2
156PT_PAR3         =       10              | BYTE - parameter 3
157PT_PAD          =       11              | BYTE - padding for even boundary
158
159MSK_MNT         =       0xFFF0          | mask for mantissa  (in PT_TIM)
160MSK_EXP         =       0x000F          | mask for exponent  (in PT_TIM)
161
162MAX_ACT         =       7               | maximum action code value
163
164| ------------------------------------------------------------------------------
165| Source definitions -- must match those in 'smdefs.h'
166
167SM_RAND         =       1               | random
168SM_PTCH         =       5               | pitch
169SM_KPRS         =       6               | key pressure
170SM_KVEL         =       7               | key velocity
171SM_FREQ         =       10              | frequency
172
173                .page
174
175| Layout of pflist entries      32 bytes each
176| ------------------------
177PF_NEXT         =       0               | LONG - next entry pointer
178PF_TRIG         =       4               | WORD - trigger number
179PF_FUNC         =       6               | WORD - fpuifnc value
180PF_D1           =       8               | LONG - d1
181PF_D2           =       12              | LONG - d2
182PF_D4           =       16              | LONG - d4
183PF_A1           =       20              | LONG - a1
184PF_A2           =       24              | LONG - a2
185PF_A3           =       28              | LONG - a3
186
187| Parameter offset
188| ----------------
189TRIG            =       8               | WORD - trigger number
190
191| Register equates
192| ----------------
193RCUR            =       a4              | current pflist entry pointer
194RPRV            =       a5              | previous pflist entry pointer
195
196                .page
197| ------------------------------------------------------------------------------
198| procpfl() -- process pendant functions
199
200|       void
201|       procpfl(trig);
202|       unsigned trig;
203
204|               Processes pendant (sustained) functions by restarting them
205|       when the trigger (trig) that's sustaining them is released.
206|       Invoked by key release processing in msm() and localkb().
207
208| ------------------------------------------------------------------------------
209
210procpfl:        nop                             | FOR DEBUGGING PATCH
211
212                link    a6,#0                   | allocate stack frame
213                movem.l d3-d7/a3-a5,-(a7)       | preserve registers we use
214
215                move.w  sr,d7                   | save interrupt state
216                move.w  #0x2200,sr              | turn off FPU interrupts
217
218                move.w  TRIG(a6),d6             | get trigger we're processing
219                move.w  d6,_curpf_t             | ...
220                movea.l #pflist,RPRV            | point at 'previous' pflist entry
221                bra     pfscan                  | go scan the chain
222
223pfpass:         movea.l RCUR,RPRV               | point at previous entry
224
225pfscan:         move.l  (RPRV),d5               | get next pflist entry pointer
226                beq     pfexit                  | done if no more
227
228                movea.l d5,RCUR                 | point at  current entry
229                move.l  d5,_curpf_l             | ...
230
231                cmp.w   PF_TRIG(RCUR),d6        | see if this entry is wanted
232                bne     pfpass                  | jump if not
233
234                movem.l PF_D1(RCUR),d1-d2/d4/a1-a3      | restore processing state
235                move.w  PF_FUNC(RCUR),_curpf_f          | ...
236
237                btst    #I_ACTIVE,FH_TMD(a1)    | see if function is active
238                bne     doact                   | continue function if so
239
240                bra     stopfn                  | stop function if not
241
242pfnext:         move.l  (RCUR),(RPRV)           | remove entry from pflist
243                move.l  pfqhdr,(RCUR)           | chain entry to free list
244                move.l  RCUR,pfqhdr             | ...
245                bra     pfscan                  | go look at next entry
246
247pfexit:         move.w  d7,sr                   | restore interrupt level
248                movem.l (a7)+,d3-d7/a3-a5       | restore the registers we used
249                unlk    a6                      | deallocate stack frame
250                rts                             | return to caller
251
252                .page
253
254| ------------------------------------------------------------------------------
255| stop a function
256| ------------------------------------------------------------------------------
257stopfn:         move.b  FH_TMD(a1),d0   | get function control bits
258                andi.w  #MSK_RNVB,d0    | mask for ratio / new new-value bit
259                move.w  d0,d3           | isolate new new-value bit
260                add.w   d3,d3           | ... from function header
261                andi.w  #MSK_ONVB,d3    | ... shift to old new-value bit
262                or.w    d3,d0           | ... and put new bit in old bit
263                move.w  d0,F_CTL(a3,d1.W)       | stop the function
264                bclr    #I_ACTIVE,FH_TMD(a1)    | reset the active bit
265                bra     pfnext          | go restore registers and exit
266
267| ------------------------------------------------------------------------------
268| setup for and dispatch to the proper action handler
269| ------------------------------------------------------------------------------
270doact:          clr.w   d2              | get current point index in d2
271                move.b  FH_CPT(a1),d2   | ...
272                lsl.w   #2,d2           | multiply it by the length of a point
273                move.w  d2,d0           | ...  (fast multiply by PT_LEN = 12
274                add.w   d2,d2           | ...   via shift and add)
275                add.w   d0,d2           | ...
276                clr.w   d4              | get jump point # into d4
277                move.b  PT_PAR1(a2,d2.W),d4     | ...
278                clr.w   d3              | get action code in d3
279                move.b  PT_ACT(a2,d2.W),d3      | ...
280                cmpi.b  #MAX_ACT,d3     | check against the limit
281                bgt     stopfn          | stop things if it's a bad action code
282
283                lsl.w   #2,d3           | develop index to action dispatch table
284                lea     actab,a0        | get the address of the action handler
285                movea.l 0(a0,d3.W),a0   | ...
286
287| ------------------------------------------------------------------------------
288| At this point we're ready to do the action associated with the point,
289| and the registers are set up,  and will remain,  as follows:
290
291|       d1      FPU function index      a1      function header base
292|       d2      point table index       a2      point table base
293|                                       a3      FPU function base
294|       d4      jump point number
295
296|       d0, d3, d5, and a0 are used as scratch throughout the code.
297
298| ------------------------------------------------------------------------------
299
300                jmp     (a0)            | dispatch to action handler
301
302                .page
303| ------------------------------------------------------------------------------
304| act0 -- AC_NULL -- no action
305| ----    --------------------
306act0:           move.b  FH_PT1(a1),d0   | get first point number
307                add.b   FH_PIF(a1),d0   | add number of points in function
308                subq.b  #1,d0           | make it last point number
309                cmp.b   FH_CPT(a1),d0   | see if we're at the last point
310                beq     stopfn          | stop function if so
311
312                addq.b  #1,FH_CPT(a1)   | update function header for next point
313                addi.w  #PT_LEN,d2      | advance the point index
314
315| ------------------------------------------------------------------------------
316| outseg -- output a segment
317| ------    ----------------
318outseg:         move.w  PT_TIM(a2,d2.w),d3      | get packed time
319                move.w  d3,d0                   | extract mantissa
320                andi.w  #MSK_MNT,d0             | ...
321                mulu    timemlt,d0              | multiply by panel time pot value
322                lsr.l   #8,d0                   | ... and scale it
323                lsr.l   #7,d0                   | ...
324                move.w  d0,F_MNT(a3,d1.W)       | send mantissa to FPU
325                andi.w  #MSK_EXP,d3             | extract exponent code
326                add.w   d3,d3                   | look up decoded exponent
327                lea     expbit,a0               | ... in expbit
328                move.w  0(a0,d3.W),F_EXP(a3,d1.W)       | send exponent to FPU
329                move.w  PT_VAL(a2,d2.W),d3      | get the function value
330
331                .page
332| ------------------------------------------------------------------------------
333| get the point source, if any
334| ------------------------------------------------------------------------------
335                tst.w   PT_VMLT(a2,d2.W)        | see if we have a point mlt.
336                beq     nosrc                   | don't do anything for zero
337
338                clr.w   d0                      | get the source number
339                move.b  PT_VSRC(a2,d2.W),d0     | ...
340                beq     nosrc                   | don't do anything for zero
341
342| ------------------------------------------------------------------------------
343| SM_RAND -- random
344| ------------------------------------------------------------------------------
345                cmpi.w  #SM_RAND,d0             | is this the random source ?
346                bne     srctyp0                 | jump if not
347
348                movem.l d1-d2/a0-a2,-(a7)       | preserve registers around call
349                move.w  PT_VMLT(a2,d2.W),-(a7)  | pass multiplier to xgetran()
350                jsr     xgetran                 | call for a random number
351                tst.w   (a7)+                   | clean up stack
352                movem.l (a7)+,d1-d2/a0-a2       | restore registers
353                move.w  d0,d5                   | put random value in the value register
354                bra     applym                  | go apply the multiplier
355
356                .page
357| ------------------------------------------------------------------------------
358| SM_FREQ -- frequency
359| ------------------------------------------------------------------------------
360srctyp0:        cmpi.w  #SM_FREQ,d0     | is this the frequency source ?
361                bne     srctyp1         | jump if not
362
363                move.w  (a1),d0         | get the pitch
364                lsr.w   #6,d0           | shift to a word index
365                andi.w  #0x01FE,d0      | mask out extraneous bits
366                lea     ptoftab,a0      | get entry from ptoftab[]
367                move.w  0(a0,d0.W),d5   | ...
368                bra     applym          | go apply the multiplier
369
370| ------------------------------------------------------------------------------
371| SM_PTCH -- pitch
372| ------------------------------------------------------------------------------
373srctyp1:        cmpi.w  #SM_PTCH,d0     | is this the pitch source ?
374                bne     srctyp2         | jump if not
375
376                move.w  (a1),d5         | get the pitch as the value
377                bra     applym          | go apply the multiplier
378
379| ------------------------------------------------------------------------------
380| SM_KVEL -- velocity
381| ------------------------------------------------------------------------------
382srctyp2:        cmpi.w  #SM_KVEL,d0     | is this the key velocity source ?
383                bne     srctyp3         | jump if not
384
385                move.w  FH_TRG(a1),d0   | get the trigger number
386                add.w   d0,d0           | ... as a word index
387                lea     veltab,a0       | ... into veltab[]
388                move.w  0(a0,d0.W),d5   | get the velocity from veltab[trg]
389                bra     applym          | go apply the multiplier
390
391| ------------------------------------------------------------------------------
392| SM_KPRS -- pressure
393| ------------------------------------------------------------------------------
394srctyp3:        cmpi.w  #SM_KPRS,d0     | is this the key pressure source ?
395                bne     srctyp4         | jump if not  (must be an analog input)
396
397                move.w  FH_TRG(a1),d0   | get the trigger number
398                add.w   d0,d0           | ... as a word index
399                lea     prstab,a0       | ... into prstab[]
400                move.w  0(a0,d0.W),d5   | get the pressure from prstab[trg]
401                bra     applym          | go apply the multiplier
402
403                .page
404| ------------------------------------------------------------------------------
405| all other sources come out of the valents[] array
406| ------------------------------------------------------------------------------
407srctyp4:        lea     vce2grp,a0      | point at vce2grp[]
408                move.w  _curpf_f,d5     | get voice number in d5
409                lsr.w   #3,d5           | ...
410                andi.w  #0x001E,d5      | ... as a word index
411                move.w  0(a0,d5.W),d5   | get the group number
412                subq.w  #1,d5           | ...
413                lsl.w   #4,d5           | shift it left a nybble
414                or.w    d5,d0           | OR it into the source number
415                add.w   d0,d0           | make source number a valents[] index
416                move.w  d0,d5           | ... (fast multiply by VALLEN = 10
417                lsl.w   #2,d0           | ...  via shift and add)
418                add.w   d5,d0           | ...
419                lea     valents,a0      | get base of valents[]
420                move.w  VT_VAL(a0,d0.W),d5      | get value
421
422| ------------------------------------------------------------------------------
423| apply the multiplier to the source, and add it to the function value
424| ------------------------------------------------------------------------------
425applym:         muls    PT_VMLT(a2,d2.W),d5     | apply the multiplier
426                asr.l   #7,d5           | scale the result
427                asr.l   #8,d5           | ...
428                ext.l   d3              | add the function value
429                add.l   d3,d5           | ...
430                cmpi.l  #VALMAX,d5      | check for overflow
431                ble     srcmlt1         | jump if no overflow
432
433                move.l  #VALMAX,d5      | limit at VALMAX
434                bra     srcmlt2         | ...
435
436srcmlt1:        cmpi.l  #VALMIN,d5      | check for underflow
437                bge     srcmlt2         | jump if no underflow
438
439                move.l  #VALMIN,d5      | limit at VALMIN
440
441srcmlt2:        move.w  d5,d3           | setup value for output to FPU
442
443                .page
444| ------------------------------------------------------------------------------
445| adjust the value according to the function type
446| ------------------------------------------------------------------------------
447nosrc:          move.w  d1,d0           | get function type
448                andi.w  #0x01E0,d0      | ...
449
450| ------------------------------------------------------------------------------
451| level or location
452| ------------------------------------------------------------------------------
453                cmpi.w  #P_LEVEL,d0     | see if it's the level
454                beq     outsegl         | jump if so
455
456                cmpi.w  #P_LOCN,d0      | see if it's the location
457                bne     outsegf         | jump if not
458
459                tst.w   d3              | check sign of value
460                bpl     outsegc         | jump if positive
461
462                clr.w   d3              | force negative values to 0
463
464outsegc:        asr.w   #5,d3           | shift value to LS bits
465                sub.w   #500,d3         | subtract 5.00 from value
466                asl.w   #6,d3           | readjust to MS bits
467                bra     outseg3         | go output the value
468
469outsegl:        tst.w   d3              | check sign of value
470                bpl     outsegm         | jump if positive
471
472                clr.w   d3              | limit negative values at 0
473
474outsegm:        asr.w   #5,d3           | shift value to LS bits
475                sub.w   #500,d3         | subtract 5.00 from value
476                asl.w   #6,d3           | readjust to MS bits
477                bra     outseg3         | go output the value
478
479                .page
480| ------------------------------------------------------------------------------
481| filter
482| ------------------------------------------------------------------------------
483outsegf:        cmpi.w  #P_FILTER,d0    | see if it's the filter
484                bne     outsegp         | jump if not
485
486                ext.l   d3              | make function value a long
487                asr.l   #1,d3           | multiply function value by .75
488                move.l  d3,d0           | ...  (fast multiply by .75
489                asr.l   #1,d0           | ...   via shift and add)
490                add.l   d0,d3           | ...
491                move.w  (a1),d0         | add pitch
492                ext.l   d0              | ...
493                add.l   d0,d3           | ...
494                cmpi.l  #VALMAX,d3      | see if it's within limits
495                ble     outsega         | ...
496
497                move.w  #VALMAX,d3      | limit at VALMAX
498                bra     outseg3         | ...
499
500outsega:        cmpi.l  #VALMIN,d3      | ...
501                bge     outseg3         | ...
502
503                move.w  #VALMIN,d3      | limit at VALMIN
504                bra     outseg3         | ...
505
506                .page
507| ------------------------------------------------------------------------------
508| freq 1..4
509| ------------------------------------------------------------------------------
510outsegp:        cmpi.w  #P_FREQ1,d0     | see if it's freq1
511                beq     outseg0         | go process freq1
512
513outsegq:        cmpi.w  #P_FREQ2,d0     | see if it's freq2
514                beq     outseg0         | process it if so
515
516                cmpi.w  #P_FREQ3,d0     | see if it's freq3
517                beq     outseg0         | process it if so
518
519                cmpi.w  #P_FREQ4,d0     | see if it's freq4
520                bne     outseg3         | jump if not
521
522outseg0:        ext.l   d3              | scale the point value to cents offset
523                asr.l   #5,d3           | ...
524                sub.l   #500,d3         | ... value - 500
525                asl.l   #LSPCH,d3       | mult. by 2 and scale for 1/2 cent lsb
526                move.w  (a1),d0         | add pitch from function header
527                ext.l   d0              | ...
528                add.l   d0,d3           | ...
529                cmp.l   #PCHMAX,d3      | see if result is valid
530                ble     outseg3         | jump if within pitch limits
531
532                move.l  #PCHMAX,d3      | limit at maximum pitch
533
534| ------------------------------------------------------------------------------
535| send the value to the FPU
536| ------------------------------------------------------------------------------
537outseg3:        move.b  FH_TMD(a1),d0   | get hardware bits from function header
538                eor.w   #VAL_BITS,d0    | toggle new value select bits
539                move.b  d0,FH_TMD(a1)   | store updated word
540                btst.l  #VSUBNBIT,d0    | check which value address to use
541                beq     outseg1
542
543                move.w  d3,F_VAL01(a3,d1.W)     | send value to FPU
544                bra     outseg2
545
546outseg1:        move.w  d3,F_VAL10(a3,d1.W)     | send value to FPU
547
548outseg2:        andi.w  #MSK_CTL,d0             | mask off software bits
549                ori.w   #UPD_BIT+INT_BIT,d0     | set the update & !lastseg bits
550                move.w  d0,F_CTL(a3,d1.W)       | send control word to FPU
551                bra     pfnext                  | done -- exit
552
553                .page
554
555| ------------------------------------------------------------------------------
556| act2 -- AC_ENBL -- stop if key is up
557| ----    ----------------------------
558act2:           move.w  _curpf_f,d0     | get voice as a word index
559                lsr.w   #3,d0           | ...
560                andi.w  #0x001E,d0      | ...
561                lea     vce2trg,a0      | check to see if voice is free
562                move.w  0(a0,d0.W),d0   | ...
563                cmpi.w  #-1,d0          | ...
564                beq     stopfn          | if so, stop the function
565
566                btst    #15,d0          | see if voice is held
567                bne     act0            | continue if so
568
569                btst    #14,d0          | ...
570                bne     act0            | ...
571
572                lea     trgtab,a0       | check trigger table entry
573                tst.b   0(a0,d0.W)      | ...
574                bne     act0            | if trigger is active, continue
575
576                bra     stopfn          | if not, stop the function
577
578| ------------------------------------------------------------------------------
579| act3 -- AC_JUMP -- unconditional jump
580| ----    -----------------------------
581act3:           cmp.b   FH_PIF(a1),d4   | check jump point against limit
582                bcc     stopfn          | stop function if jump point invalid
583
584                clr.w   d2              | get index of first point
585                move.b  FH_PT1(a1),d2   | ...
586                add.b   d4,d2           | add jump point
587                move.b  d2,FH_CPT(a1)   | make it the current point
588                lsl.w   #2,d2           | develop new point index in d2
589                move.w  d2,d0           | ... (fast multiply by PT_LEN = 12
590                add.w   d2,d2           | ...  via shift and add)
591                add.w   d0,d2           | ...
592                bra     outseg          | output the segment
593
594                .page
595
596| ------------------------------------------------------------------------------
597| act4 -- AC_LOOP -- jump to point PT_PAR1 PT_PAR2 times
598| ----    ----------------------------------------------
599act4:           tst.b   PT_PAR3(a2,d2.W)        | check counter
600                bne     act4a                   | jump if it's running
601
602                move.b  PT_PAR2(a2,d2.W),d0     | get parameter
603                subi.w  #90,d0                  | put parameter in random range
604                bmi     act4b                   | treat as normal if < 90
605
606                movem.l d1-d2/a0-a2,-(a7)       | get ranged random number
607                move.w  d0,-(a7)                | ...
608                jsr     irand                   | ...
609                tst.w   (a7)+                   | ...
610                movem.l (a7)+,d1-d2/a0-a2       | ...
611                move.b  d0,PT_PAR3(a2,d2.w)     | set counter
612                beq     act0                    | next segment if cntr set to 0
613
614                bra     act3                    | else jump to the point
615
616act4b:          move.b  PT_PAR2(a2,d2.W),PT_PAR3(a2,d2.W)       | set counter
617                beq     act0                    | next segment if cntr set to 0
618
619                bra     act3                    | else jump to the point
620
621act4a:          subq.b  #1,PT_PAR3(a2,d2.W)     | decrement counter
622                beq     act0                    | next segment if cntr ran out
623
624                bra     act3                    | jump if it's still non-zero
625
626| ------------------------------------------------------------------------------
627| act5 -- AC_KYUP -- jump if key is up
628| ----    ----------------------------
629act5:           move.w  _curpf_f,d0     | get voice as a word index
630                lsr.w   #3,d0           | ...
631                andi.w  #0x001E,d0      | ...
632                lea     vce2trg,a0      | check to see if voice is free
633                move.w  0(a0,d0.W),d0   | ...
634                cmpi.w  #-1,d0          | ...
635                beq     act3            | if so (inactive), do the jump
636
637                btst    #15,d0          | see if voice is held
638                bne     act0            | continue if so
639
640                btst    #14,d0          | ...
641                bne     act0            | ...
642
643                lea     trgtab,a0       | check trigger table entry
644                tst.b   0(a0,d0.W)      | see if the trigger is active
645                beq     act3            | if not, do the jump
646
647                bra     act0            | if so, do next segment
648
649                .page
650
651| ------------------------------------------------------------------------------
652| act6 -- AC_KYDN -- jump if key is down
653| ----    ------------------------------
654act6:           move.w  _curpf_f,d0     | get voice as a word index
655                lsr.w   #3,d0           | ...
656                andi.w  #0x001E,d0      | ...
657                lea     vce2trg,a0      | check to see if voice is free
658                move.w  0(a0,d0.W),d0   | ...
659                cmpi.w  #-1,d0          | ...
660                beq     act0            | if so (inactive), continue
661
662                btst    #15,d0          | see if voice is held
663                bne     act3            | do jump if so
664
665                btst    #14,d0          | ...
666                bne     act3            | ...
667
668                lea     trgtab,a0       | check trigger table entry
669                tst.b   0(a0,d0.W)      | see if the trigger is active
670                bne     act3            | if so, do the jump
671
672                bra     act0            | if not, do next segment
673
674| ------------------------------------------------------------------------------
675act7:           bra     act0            | AC_HERE: treat act7 as AC_NULL
676
677                .page
678
679| act1 -- AC_SUST -- pause if key is down (sustain)
680| ----    -----------------------------------------
681act1:           move.w  _curpf_f,d0     | get voice as a word index
682                lsr.w   #3,d0           | ...
683                andi.w  #0x001E,d0      | ...
684                lea     vce2trg,a0      | point at voice to trigger table
685                move.w  0(a0,d0.W),d0   | get trigger table entry
686                cmpi.w  #-1,d0          | see if voice is free
687                beq     act0            | treat as no-op if so
688
689                btst    #15,d0          | see if voice is held by a pedal
690                bne     act1a           | sustain if so
691
692                btst    #14,d0          | see if voice is sustained by a pedal
693                bne     act1a           | sustain if so
694
695                lea     trgtab,a0       | point at trigger table
696                tst.b   0(a0,d0.W)      | check trigger status
697                beq     act0            | continue if not active
698
699act1a:          move.l  pfqhdr,d3       | see if any pflist entries remain
700                beq     act0            | no-op if not  (shouldn't happen ...)
701
702                move.b  FH_PT1(a1),d0   | get first point number
703                add.b   FH_PIF(a1),d0   | add base to first point
704                subq.b  #1,d0           | make d0 last point number
705                cmp.b   FH_CPT(a1),d0   | check current point number
706                beq     stopfn          | done if this is the last point
707
708                addq.b  #1,FH_CPT(a1)           | update current point number
709                addi.w  #PT_LEN,d2              | update point index
710                movea.l d3,a0                   | acquire a new pflist entry
711                move.l  (a0),pfqhdr             | ...
712                move.l  pflist,(a0)             | ...
713                move.l  a0,pflist               | ...
714                move.w  FH_TRG(a1),PF_TRIG(a0)  | set trigger number in entry
715                move.w  _curpf_f,PF_FUNC(a0)    | set v/p word in entry
716                movem.l d1-d2/d4/a1-a3,PF_D1(a0)        | set registers in entry
717                move.b  FH_TMD(a1),d0           | stop the function
718                andi.w  #MSK_RNVB,d0            | ...
719                move.w  d0,d3                   | ...
720                add.w   d3,d3                   | ...
721                andi.w  #MSK_ONVB,d3            | ...
722                or.w    d3,d0                   | ...
723                move.w  d0,F_CTL(a3,d1.W)       | ...
724                bra     pfnext                  | go do next list entry
725
726                .page
727| ------------------------------------------------------------------------------
728                .data
729| ------------------------------------------------------------------------------
730
731| actab -- action code dispatch table
732| -----    --------------------------
733actab:          .dc.l   act0    | 0 - AC_NULL:  no action
734                .dc.l   act1    | 1 - AC_SUST:  sustain
735                .dc.l   act2    | 2 - AC_ENBL:  enable
736                .dc.l   act3    | 3 - AC_JUMP:  unconditional jump
737                .dc.l   act4    | 4 - AC_LOOP:  jump n times      (loop)
738                .dc.l   act5    | 5 - AC_KYUP:  jump if key up    (enable jump)
739                .dc.l   act6    | 6 - AC_KYDN:  jump if key down  (sustain jump)
740                .dc.l   act7    | 7 - AC_HERE:  here on key up
741
742| ------------------------------------------------------------------------------
743                .bss
744| ------------------------------------------------------------------------------
745
746| ----------------- local variables --------------------------------------------
747
748_curpf_f:       .ds.w   1       | interrupting voice & parameter from FPU
749
750| ----------------- debug variables --------------------------------------------
751
752_curpf_t:       .ds.w   1       | current trigger
753
754_curpf_l:       .ds.l   1       | current pflist entry
755
756| ------------------------------------------------------------------------------
757
758                .end
Note: See TracBrowser for help on using the repository browser.