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

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

Removed _ prefix.

  • Property mode set to 100644
File size: 24.7 KB
RevLine 
[4f508e6]1| ------------------------------------------------------------------------------
2| procpfl.s -- process pendant functions (sustain release processing)
3| Version 8 -- 1988-08-31 -- D.N. Lynx Crowe
4| ------------------------------------------------------------------------------
[f40a309]5 .text
[4f508e6]6
[8325447]7 .xdef procpfl
[4f508e6]8
9 .xdef _curpf_f | current function (v/p)
10 .xdef _curpf_l | current pflist entry
11 .xdef _curpf_t | current trigger
12
[8325447]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
[4f508e6]28
[f40a309]29 .page
[4f508e6]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
[f40a309]78 .page
[4f508e6]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
[f40a309]122 .page
[4f508e6]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
[f40a309]173 .page
[4f508e6]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
[f40a309]196 .page
[4f508e6]197| ------------------------------------------------------------------------------
[8325447]198| procpfl() -- process pendant functions
[4f508e6]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
[8325447]210procpfl: nop | FOR DEBUGGING PATCH
[4f508e6]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 | ...
[8325447]220 movea.l #pflist,RPRV | point at 'previous' pflist entry
[4f508e6]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
[8325447]243 move.l pfqhdr,(RCUR) | chain entry to free list
244 move.l RCUR,pfqhdr | ...
[4f508e6]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
[f40a309]252 .page
[4f508e6]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
[f40a309]302 .page
[4f508e6]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 | ...
[8325447]321 mulu timemlt,d0 | multiply by panel time pot value
[4f508e6]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
[8325447]327 lea expbit,a0 | ... in expbit
[4f508e6]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
[f40a309]331 .page
[4f508e6]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()
[8325447]350 jsr xgetran | call for a random number
[4f508e6]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
[f40a309]356 .page
[4f508e6]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
[8325447]366 lea ptoftab,a0 | get entry from ptoftab[]
[4f508e6]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
[8325447]387 lea veltab,a0 | ... into veltab[]
[4f508e6]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
[8325447]399 lea prstab,a0 | ... into prstab[]
[4f508e6]400 move.w 0(a0,d0.W),d5 | get the pressure from prstab[trg]
401 bra applym | go apply the multiplier
402
[f40a309]403 .page
[4f508e6]404| ------------------------------------------------------------------------------
405| all other sources come out of the valents[] array
406| ------------------------------------------------------------------------------
[8325447]407srctyp4: lea vce2grp,a0 | point at vce2grp[]
[4f508e6]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 | ...
[8325447]419 lea valents,a0 | get base of valents[]
[4f508e6]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
[f40a309]443 .page
[4f508e6]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
[f40a309]479 .page
[4f508e6]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
[f40a309]506 .page
[4f508e6]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
[f40a309]541 beq outseg1
[4f508e6]542
543 move.w d3,F_VAL01(a3,d1.W) | send value to FPU
[f40a309]544 bra outseg2
[4f508e6]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
[f40a309]553 .page
[4f508e6]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 | ...
[8325447]561 lea vce2trg,a0 | check to see if voice is free
[4f508e6]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
[8325447]572 lea trgtab,a0 | check trigger table entry
[4f508e6]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
[f40a309]594 .page
[4f508e6]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) | ...
[8325447]608 jsr irand | ...
[4f508e6]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 | ...
[8325447]632 lea vce2trg,a0 | check to see if voice is free
[4f508e6]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
[8325447]643 lea trgtab,a0 | check trigger table entry
[4f508e6]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
[f40a309]649 .page
[4f508e6]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 | ...
[8325447]657 lea vce2trg,a0 | check to see if voice is free
[4f508e6]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
[8325447]668 lea trgtab,a0 | check trigger table entry
[4f508e6]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
[f40a309]677 .page
[4f508e6]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 | ...
[8325447]684 lea vce2trg,a0 | point at voice to trigger table
[4f508e6]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
[8325447]695 lea trgtab,a0 | point at trigger table
[4f508e6]696 tst.b 0(a0,d0.W) | check trigger status
697 beq act0 | continue if not active
698
[8325447]699act1a: move.l pfqhdr,d3 | see if any pflist entries remain
[4f508e6]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
[8325447]711 move.l (a0),pfqhdr | ...
712 move.l pflist,(a0) | ...
713 move.l a0,pflist | ...
[4f508e6]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
[f40a309]726 .page
[4f508e6]727| ------------------------------------------------------------------------------
[f40a309]728 .data
[4f508e6]729| ------------------------------------------------------------------------------
730
731| actab -- action code dispatch table
732| ----- --------------------------
[4cfe69a]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
[4f508e6]741
742| ------------------------------------------------------------------------------
[f40a309]743 .bss
[4f508e6]744| ------------------------------------------------------------------------------
745
746| ----------------- local variables --------------------------------------------
747
[4cfe69a]748_curpf_f: .ds.w 1 | interrupting voice & parameter from FPU
[4f508e6]749
750| ----------------- debug variables --------------------------------------------
751
[4cfe69a]752_curpf_t: .ds.w 1 | current trigger
[4f508e6]753
[4cfe69a]754_curpf_l: .ds.l 1 | current pflist entry
[4f508e6]755
756| ------------------------------------------------------------------------------
757
[f40a309]758 .end
Note: See TracBrowser for help on using the repository browser.