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 |
|
---|
49 | UPD_BIT = 0x0001 | update bit (1 = update)
|
---|
50 | INT_BIT = 0x0002 | int. bit (0 = disable)
|
---|
51 | RAT_BIT = 0x0004 | ratio bit (0 = ratio)
|
---|
52 |
|
---|
53 | VSUBNBIT = 3 | new value select bit number
|
---|
54 | VAL_BITS = 0x0018 | new value select bit mask
|
---|
55 |
|
---|
56 | MSK_RNVB = 0x000C | new value / ratio bits
|
---|
57 | MSK_ONVB = 0x0010 | old new value bit
|
---|
58 |
|
---|
59 | FKILL = 0x0014 | kill value for function
|
---|
60 | FSEND = 0x0015 | send new value to function
|
---|
61 |
|
---|
62 | CLREXP = 0x8000 | clear value for time exponent
|
---|
63 | CLRMNT = 0x8000 | clear value for time mantissa
|
---|
64 |
|
---|
65 | | ------------------------------------------------------------------------------
|
---|
66 | | Miscellaneous definitions
|
---|
67 | | -------------------------
|
---|
68 |
|
---|
69 | PCHMAX = 21920 | maximum pitch value
|
---|
70 | VALMAX = 32000 | maximum value to send to FPU
|
---|
71 | VALMIN = -32000 | minimum value to send to FPU
|
---|
72 |
|
---|
73 | LSPCH = 2 | left shift for sources to freq
|
---|
74 |
|
---|
75 | VALLEN = 10 | length of the 'valent' struct
|
---|
76 | VT_VAL = 8 | value offset in 'valent'
|
---|
77 |
|
---|
78 | .page
|
---|
79 | | ------------------------------------------------------------------------------
|
---|
80 | | FPU addresses
|
---|
81 | | -------------
|
---|
82 |
|
---|
83 | FPUBASE = 0x180000 | FPU base address
|
---|
84 |
|
---|
85 | FPUWST = FPUBASE | FPU waveshape base
|
---|
86 | FPUFUNC = FPUBASE+0x4000 | FPU function base
|
---|
87 | FPUINT1 = FPUBASE+0x4000 | FPU int. input address (R/O)
|
---|
88 | FPUINT2 = FPUBASE+0x6000 | FPU int. reset address (W/O)
|
---|
89 | FPUCFG = FPUBASE+0x5FE0 | FPU config. data address (W/O)
|
---|
90 |
|
---|
91 | F_CTL = 0x00 | control word
|
---|
92 | F_VAL10 = 0x02 | new value "10"
|
---|
93 | F_CV1 = 0x08 | control voltage 1
|
---|
94 | F_SF1 = 0x0A | scale factor 1
|
---|
95 | F_CV2 = 0x0C | control voltage 2
|
---|
96 | F_SF2 = 0x0E | scale factor 2
|
---|
97 | F_CV3 = 0x10 | control voltage 3
|
---|
98 | F_SF3 = 0x12 | scale factor 3
|
---|
99 | F_MNT = 0x14 | time mantissa
|
---|
100 | F_EXP = 0x16 | time exponent
|
---|
101 | F_VAL01 = 0x1C | new value "01"
|
---|
102 |
|
---|
103 | P_FREQ1 = 0x0020 | frequency 1
|
---|
104 | P_FREQ2 = 0x0060 | frequency 2
|
---|
105 | P_FREQ3 = 0x00A0 | frequency 3
|
---|
106 | P_FREQ4 = 0x00E0 | frequency 4
|
---|
107 | P_FILTER = 0x0140 | filter
|
---|
108 | P_FILTRQ = 0x00C0 | filter q
|
---|
109 |
|
---|
110 | P_INDEX1 = 0x0120 | index 1
|
---|
111 | P_INDEX2 = 0x0160 | index 2
|
---|
112 | P_INDEX3 = 0x0180 | index 3
|
---|
113 | P_INDEX4 = 0x01A0 | index 4
|
---|
114 | P_INDEX5 = 0x01C0 | index 5
|
---|
115 | P_INDEX6 = 0x01E0 | index 6
|
---|
116 |
|
---|
117 | P_LEVEL = 0x0040 | level
|
---|
118 |
|
---|
119 | P_LOCN = 0x0080 | location
|
---|
120 | P_DYNAM = 0x0100 | dynamics
|
---|
121 |
|
---|
122 | .page
|
---|
123 | | ------------------------------------------------------------------------------
|
---|
124 | | Structure definitions
|
---|
125 | | ------------------------------------------------------------------------------
|
---|
126 | | The following MUST match the idfnhdr structure definition in instdsp.h:
|
---|
127 |
|
---|
128 | FH_LEN = 12 | length of the idfnhdr structure
|
---|
129 |
|
---|
130 | FH_PCH = 0 | WORD - pitch offset
|
---|
131 | FH_MLT = 2 | WORD - overall value multiplier
|
---|
132 | FH_SRC = 4 | BYTE - overall value source
|
---|
133 | FH_PIF = 5 | BYTE - # of points in the function
|
---|
134 | FH_PT1 = 6 | BYTE - index of first point
|
---|
135 | FH_TMD = 7 | BYTE - trigger mode / control bits
|
---|
136 | FH_CPT = 8 | BYTE - current point
|
---|
137 | FH_PRM = 9 | BYTE - misc. function parameter
|
---|
138 | FH_TRG = 10 | WORD - trigger
|
---|
139 |
|
---|
140 | I_ACTIVE = 1 | 'Active' bit number (in FH_TMD)
|
---|
141 |
|
---|
142 | MSK_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 |
|
---|
147 | PT_LEN = 12 | length of the instpnt structure
|
---|
148 |
|
---|
149 | PT_TIM = 0 | WORD - time (packed)
|
---|
150 | PT_VAL = 2 | WORD - value
|
---|
151 | PT_VMLT = 4 | WORD - value multiplier
|
---|
152 | PT_VSRC = 6 | BYTE - value source
|
---|
153 | PT_ACT = 7 | BYTE - action
|
---|
154 | PT_PAR1 = 8 | BYTE - parameter 1
|
---|
155 | PT_PAR2 = 9 | BYTE - parameter 2
|
---|
156 | PT_PAR3 = 10 | BYTE - parameter 3
|
---|
157 | PT_PAD = 11 | BYTE - padding for even boundary
|
---|
158 |
|
---|
159 | MSK_MNT = 0xFFF0 | mask for mantissa (in PT_TIM)
|
---|
160 | MSK_EXP = 0x000F | mask for exponent (in PT_TIM)
|
---|
161 |
|
---|
162 | MAX_ACT = 7 | maximum action code value
|
---|
163 |
|
---|
164 | | ------------------------------------------------------------------------------
|
---|
165 | | Source definitions -- must match those in 'smdefs.h'
|
---|
166 |
|
---|
167 | SM_RAND = 1 | random
|
---|
168 | SM_PTCH = 5 | pitch
|
---|
169 | SM_KPRS = 6 | key pressure
|
---|
170 | SM_KVEL = 7 | key velocity
|
---|
171 | SM_FREQ = 10 | frequency
|
---|
172 |
|
---|
173 | .page
|
---|
174 |
|
---|
175 | | Layout of pflist entries 32 bytes each
|
---|
176 | | ------------------------
|
---|
177 | PF_NEXT = 0 | LONG - next entry pointer
|
---|
178 | PF_TRIG = 4 | WORD - trigger number
|
---|
179 | PF_FUNC = 6 | WORD - fpuifnc value
|
---|
180 | PF_D1 = 8 | LONG - d1
|
---|
181 | PF_D2 = 12 | LONG - d2
|
---|
182 | PF_D4 = 16 | LONG - d4
|
---|
183 | PF_A1 = 20 | LONG - a1
|
---|
184 | PF_A2 = 24 | LONG - a2
|
---|
185 | PF_A3 = 28 | LONG - a3
|
---|
186 |
|
---|
187 | | Parameter offset
|
---|
188 | | ----------------
|
---|
189 | TRIG = 8 | WORD - trigger number
|
---|
190 |
|
---|
191 | | Register equates
|
---|
192 | | ----------------
|
---|
193 | RCUR = a4 | current pflist entry pointer
|
---|
194 | RPRV = 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 |
|
---|
210 | _procpfl: 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 |
|
---|
223 | pfpass: movea.l RCUR,RPRV | point at previous entry
|
---|
224 |
|
---|
225 | pfscan: 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 |
|
---|
242 | pfnext: 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 |
|
---|
247 | pfexit: 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 | | ------------------------------------------------------------------------------
|
---|
257 | stopfn: 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 | | ------------------------------------------------------------------------------
|
---|
270 | doact: 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 | | ---- --------------------
|
---|
306 | act0: 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 | | ------ ----------------
|
---|
318 | outseg: 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 | | ------------------------------------------------------------------------------
|
---|
360 | srctyp0: 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 | | ------------------------------------------------------------------------------
|
---|
373 | srctyp1: 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 | | ------------------------------------------------------------------------------
|
---|
382 | srctyp2: 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 | | ------------------------------------------------------------------------------
|
---|
394 | srctyp3: 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 | | ------------------------------------------------------------------------------
|
---|
407 | srctyp4: 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 | | ------------------------------------------------------------------------------
|
---|
425 | applym: 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 |
|
---|
436 | srcmlt1: cmpi.l #VALMIN,d5 | check for underflow
|
---|
437 | bge srcmlt2 | jump if no underflow
|
---|
438 |
|
---|
439 | move.l #VALMIN,d5 | limit at VALMIN
|
---|
440 |
|
---|
441 | srcmlt2: move.w d5,d3 | setup value for output to FPU
|
---|
442 |
|
---|
443 | .page
|
---|
444 | | ------------------------------------------------------------------------------
|
---|
445 | | adjust the value according to the function type
|
---|
446 | | ------------------------------------------------------------------------------
|
---|
447 | nosrc: 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 |
|
---|
464 | outsegc: 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 |
|
---|
469 | outsegl: tst.w d3 | check sign of value
|
---|
470 | bpl outsegm | jump if positive
|
---|
471 |
|
---|
472 | clr.w d3 | limit negative values at 0
|
---|
473 |
|
---|
474 | outsegm: 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 | | ------------------------------------------------------------------------------
|
---|
483 | outsegf: 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 |
|
---|
500 | outsega: 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 | | ------------------------------------------------------------------------------
|
---|
510 | outsegp: cmpi.w #P_FREQ1,d0 | see if it's freq1
|
---|
511 | beq outseg0 | go process freq1
|
---|
512 |
|
---|
513 | outsegq: 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 |
|
---|
522 | outseg0: 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 | | ------------------------------------------------------------------------------
|
---|
537 | outseg3: 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 |
|
---|
546 | outseg1: move.w d3,F_VAL10(a3,d1.W) | send value to FPU
|
---|
547 |
|
---|
548 | outseg2: 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 | | ---- ----------------------------
|
---|
558 | act2: 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 | | ---- -----------------------------
|
---|
581 | act3: 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 | | ---- ----------------------------------------------
|
---|
599 | act4: 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 |
|
---|
616 | act4b: 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 |
|
---|
621 | act4a: 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 | | ---- ----------------------------
|
---|
629 | act5: 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 | | ---- ------------------------------
|
---|
654 | act6: 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 | | ------------------------------------------------------------------------------
|
---|
675 | act7: bra act0 | AC_HERE: treat act7 as AC_NULL
|
---|
676 |
|
---|
677 | .page
|
---|
678 |
|
---|
679 | | act1 -- AC_SUST -- pause if key is down (sustain)
|
---|
680 | | ---- -----------------------------------------
|
---|
681 | act1: 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 |
|
---|
699 | act1a: 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 | | ----- --------------------------
|
---|
733 | actab: 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
|
---|