Changeset 4f508e6 in buchla-68k for ram/procpfl.s
- Timestamp:
- 07/01/2017 02:34:46 PM (7 years ago)
- Branches:
- master
- Children:
- 08e1da1
- Parents:
- f40a309
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
ram/procpfl.s
rf40a309 r4f508e6 1 *------------------------------------------------------------------------------2 *procpfl.s -- process pendant functions (sustain release processing)3 *Version 8 -- 1988-08-31 -- D.N. Lynx Crowe4 *------------------------------------------------------------------------------1 | ------------------------------------------------------------------------------ 2 | procpfl.s -- process pendant functions (sustain release processing) 3 | Version 8 -- 1988-08-31 -- D.N. Lynx Crowe 4 | ------------------------------------------------------------------------------ 5 5 .text 6 * 6 7 7 .xdef _procpfl 8 * 9 .xdef _curpf_f *current function (v/p)10 .xdef _curpf_l *current pflist entry11 .xdef _curpf_t *current trigger12 * 8 9 .xdef _curpf_f | current function (v/p) 10 .xdef _curpf_l | current pflist entry 11 .xdef _curpf_t | current trigger 12 13 13 .xref _irand 14 14 .xref _xgetran 15 * 15 16 16 .xref _expbit 17 17 .xref _funcndx … … 26 26 .xref _vce2trg 27 27 .xref _veltab 28 * 29 .page 30 *------------------------------------------------------------------------------31 *Register usage32 *--------------33 *d0 scratch34 *d1 FPU function index35 *d2 point index from FH_CPT (idfcpt)36 *d3 scratch37 *d4 jump point number from PT_PAR1 (ippar1)38 *d5 scratch39 * 40 *a0 scratch41 *a1 function header base42 *a2 point table base43 *a3 FPU base44 * 45 *------------------------------------------------------------------------------46 *FPU definitions47 *---------------48 * 49 UPD_BIT .equ $0001 *update bit (1 = update)50 INT_BIT .equ $0002 *int. bit (0 = disable)51 RAT_BIT .equ $0004 *ratio bit (0 = ratio)52 * 53 VSUBNBIT .equ 3 *new value select bit number54 VAL_BITS .equ $0018 *new value select bit mask55 * 56 MSK_RNVB .equ $000C *new value / ratio bits57 MSK_ONVB .equ $0010 *old new value bit58 * 59 FKILL .equ $0014 *kill value for function60 FSEND .equ $0015 *send new value to function61 * 62 CLREXP .equ $8000 *clear value for time exponent63 CLRMNT .equ $8000 *clear value for time mantissa64 * 65 *------------------------------------------------------------------------------66 *Miscellaneous definitions67 *-------------------------68 * 69 PCHMAX .equ 21920 *maximum pitch value70 VALMAX .equ 32000 *maximum value to send to FPU71 VALMIN .equ -32000 *minimum value to send to FPU72 * 73 LSPCH .equ 2 *left shift for sources to freq74 * 75 VALLEN .equ 10 *length of the 'valent' struct76 VT_VAL .equ 8 *value offset in 'valent'77 * 78 .page 79 *------------------------------------------------------------------------------80 *FPU addresses81 *-------------82 * 83 FPUBASE .equ $180000 *FPU base address84 * 85 FPUWST .equ FPUBASE *FPU waveshape base86 FPUFUNC .equ FPUBASE+$4000 *FPU function base87 FPUINT1 .equ FPUBASE+$4000 *FPU int. input address (R/O)88 FPUINT2 .equ FPUBASE+$6000 *FPU int. reset address (W/O)89 FPUCFG .equ FPUBASE+$5FE0 *FPU config. data address (W/O)90 * 91 F_CTL .equ $00 *control word92 F_VAL10 .equ $02 *new value "10"93 F_CV1 .equ $08 *control voltage 194 F_SF1 .equ $0A *scale factor 195 F_CV2 .equ $0C *control voltage 296 F_SF2 .equ $0E *scale factor 297 F_CV3 .equ $10 *control voltage 398 F_SF3 .equ $12 *scale factor 399 F_MNT .equ $14 *time mantissa100 F_EXP .equ $16 *time exponent101 F_VAL01 .equ $1C *new value "01"102 * 103 P_FREQ1 .equ $0020 *frequency 1104 P_FREQ2 .equ $0060 *frequency 2105 P_FREQ3 .equ $00A0 *frequency 3106 P_FREQ4 .equ $00E0 *frequency 4107 P_FILTER .equ $0140 *filter108 P_FILTRQ .equ $00C0 *filter q109 * 110 P_INDEX1 .equ $0120 *index 1111 P_INDEX2 .equ $0160 *index 2112 P_INDEX3 .equ $0180 *index 3113 P_INDEX4 .equ $01A0 *index 4114 P_INDEX5 .equ $01C0 *index 5115 P_INDEX6 .equ $01E0 *index 6116 * 117 P_LEVEL .equ $0040 *level118 * 119 P_LOCN .equ $0080 *location120 P_DYNAM .equ $0100 *dynamics121 * 122 .page 123 *------------------------------------------------------------------------------124 *Structure definitions125 *------------------------------------------------------------------------------126 *The following MUST match the idfnhdr structure definition in instdsp.h:127 * 128 FH_LEN .equ 12 *length of the idfnhdr structure129 * 130 FH_PCH .equ 0 *WORD - pitch offset131 FH_MLT .equ 2 *WORD - overall value multiplier132 FH_SRC .equ 4 *BYTE - overall value source133 FH_PIF .equ 5 *BYTE - # of points in the function134 FH_PT1 .equ 6 *BYTE - index of first point135 FH_TMD .equ 7 *BYTE - trigger mode / control bits136 FH_CPT .equ 8 *BYTE - current point137 FH_PRM .equ 9 *BYTE - misc. function parameter138 FH_TRG .equ 10 *WORD - trigger139 * 140 I_ACTIVE .equ 1 *'Active' bit number (in FH_TMD)141 * 142 MSK_CTL .equ $001C *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 .equ 12 *length of the instpnt structure148 * 149 PT_TIM .equ 0 *WORD - time (packed)150 PT_VAL .equ 2 *WORD - value151 PT_VMLT .equ 4 *WORD - value multiplier152 PT_VSRC .equ 6 *BYTE - value source153 PT_ACT .equ 7 *BYTE - action154 PT_PAR1 .equ 8 *BYTE - parameter 1155 PT_PAR2 .equ 9 *BYTE - parameter 2156 PT_PAR3 .equ 10 *BYTE - parameter 3157 PT_PAD .equ 11 *BYTE - padding for even boundary158 * 159 MSK_MNT .equ $FFF0 *mask for mantissa (in PT_TIM)160 MSK_EXP .equ $000F *mask for exponent (in PT_TIM)161 * 162 MAX_ACT .equ 7 *maximum action code value163 * 164 *------------------------------------------------------------------------------165 *Source definitions -- must match those in 'smdefs.h'166 * 167 SM_RAND .equ 1 *random168 SM_PTCH .equ 5 *pitch169 SM_KPRS .equ 6 *key pressure170 SM_KVEL .equ 7 *key velocity171 SM_FREQ .equ 10 *frequency172 * 173 .page 174 * 175 *Layout of pflist entries 32 bytes each176 *------------------------177 PF_NEXT .equ 0 *LONG - next entry pointer178 PF_TRIG .equ 4 *WORD - trigger number179 PF_FUNC .equ 6 *WORD - fpuifnc value180 PF_D1 .equ 8 *LONG - d1181 PF_D2 .equ 12 *LONG - d2182 PF_D4 .equ 16 *LONG - d4183 PF_A1 .equ 20 *LONG - a1184 PF_A2 .equ 24 *LONG - a2185 PF_A3 .equ 28 *LONG - a3186 * 187 *Parameter offset188 *----------------189 TRIG .equ 8 *WORD - trigger number190 * 191 *Register equates192 *----------------193 RCUR .equ a4 *current pflist entry pointer194 RPRV .equ a5 *previous pflist entry pointer195 * 196 .page 197 *------------------------------------------------------------------------------198 *_procpfl() -- process pendant functions199 * 200 *void201 *procpfl(trig);202 *unsigned trig;203 * 204 *Processes pendant (sustained) functions by restarting them205 *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 PATCH211 * 212 link a6,#0 *allocate stack frame213 movem.l d3-d7/a3-a5,-(a7) *preserve registers we use214 * 215 move.w sr,d7 *save interrupt state216 move.w # $2200,sr *turn off FPU interrupts217 * 218 move.w TRIG(a6),d6 *get trigger we're processing219 move.w d6,_curpf_t *...220 movea.l #_pflist,RPRV *point at 'previous' pflist entry221 bra pfscan *go scan the chain222 * 223 pfpass: movea.l RCUR,RPRV *point at previous entry224 * 225 pfscan: move.l (RPRV),d5 *get next pflist entry pointer226 beq pfexit *done if no more227 * 228 movea.l d5,RCUR *point at current entry229 move.l d5,_curpf_l *...230 * 231 cmp.w PF_TRIG(RCUR),d6 *see if this entry is wanted232 bne pfpass *jump if not233 * 234 movem.l PF_D1(RCUR),d1-d2/d4/a1-a3 *restore processing state235 move.w PF_FUNC(RCUR),_curpf_f *...236 * 237 btst #I_ACTIVE,FH_TMD(a1) *see if function is active238 bne doact *continue function if so239 * 240 bra stopfn *stop function if not241 * 242 pfnext: move.l (RCUR),(RPRV) *remove entry from pflist243 move.l _pfqhdr,(RCUR) *chain entry to free list244 move.l RCUR,_pfqhdr *...245 bra pfscan *go look at next entry246 * 247 pfexit: move.w d7,sr *restore interrupt level248 movem.l (a7)+,d3-d7/a3-a5 *restore the registers we used249 unlk a6 *deallocate stack frame250 rts *return to caller251 * 252 .page 253 * 254 *------------------------------------------------------------------------------255 *stop a function256 *------------------------------------------------------------------------------257 stopfn: move.b FH_TMD(a1),d0 *get function control bits258 andi.w #MSK_RNVB,d0 *mask for ratio / new new-value bit259 move.w d0,d3 *isolate new new-value bit260 add.w d3,d3 *... from function header261 andi.w #MSK_ONVB,d3 *... shift to old new-value bit262 or.w d3,d0 * ... and put new bit in old bit263 move.w d0,F_CTL(a3,d1.W) *stop the function264 bclr #I_ACTIVE,FH_TMD(a1) *reset the active bit265 bra pfnext *go restore registers and exit266 * 267 *------------------------------------------------------------------------------268 *setup for and dispatch to the proper action handler269 *------------------------------------------------------------------------------270 doact: clr.w d2 *get current point index in d2271 move.b FH_CPT(a1),d2 *...272 lsl.w #2,d2 *multiply it by the length of a point273 move.w d2,d0 *... (fast multiply by PT_LEN = 12274 add.w d2,d2 *... via shift and add)275 add.w d0,d2 *...276 clr.w d4 *get jump point # into d4277 move.b PT_PAR1(a2,d2.W),d4 *...278 clr.w d3 *get action code in d3279 move.b PT_ACT(a2,d2.W),d3 *...280 cmpi.b #MAX_ACT,d3 *check against the limit281 bgt stopfn *stop things if it's a bad action code282 * 283 lsl.w #2,d3 *develop index to action dispatch table284 lea actab,a0 *get the address of the action handler285 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 base292 *d2 point table index a2 point table base293 *a3 FPU function base294 *d4 jump point number295 * 296 *d0, d3, d5, and a0 are used as scratch throughout the code.297 * 298 *------------------------------------------------------------------------------299 * 300 jmp (a0) *dispatch to action handler301 * 302 .page 303 *------------------------------------------------------------------------------304 *act0 -- AC_NULL -- no action305 *---- --------------------306 act0: move.b FH_PT1(a1),d0 *get first point number307 add.b FH_PIF(a1),d0 *add number of points in function308 subq.b #1,d0 *make it last point number309 cmp.b FH_CPT(a1),d0 *see if we're at the last point310 beq stopfn *stop function if so311 * 312 addq.b #1,FH_CPT(a1) *update function header for next point313 addi.w #PT_LEN,d2 *advance the point index314 * 315 *------------------------------------------------------------------------------316 *outseg -- output a segment317 *------ ----------------318 outseg: move.w PT_TIM(a2,d2.w),d3 *get packed time319 move.w d3,d0 *extract mantissa320 andi.w #MSK_MNT,d0 *...321 mulu _timemlt,d0 *multiply by panel time pot value322 lsr.l #8,d0 *... and scale it323 lsr.l #7,d0 *...324 move.w d0,F_MNT(a3,d1.W) *send mantissa to FPU325 andi.w #MSK_EXP,d3 *extract exponent code326 add.w d3,d3 *look up decoded exponent327 lea _expbit,a0 *... in expbit328 move.w 0(a0,d3.W),F_EXP(a3,d1.W) *send exponent to FPU329 move.w PT_VAL(a2,d2.W),d3 *get the function value330 * 331 .page 332 *------------------------------------------------------------------------------333 *get the point source, if any334 *------------------------------------------------------------------------------335 tst.w PT_VMLT(a2,d2.W) *see if we have a point mlt.336 beq nosrc *don't do anything for zero337 * 338 clr.w d0 *get the source number339 move.b PT_VSRC(a2,d2.W),d0 *...340 beq nosrc *don't do anything for zero341 * 342 *------------------------------------------------------------------------------343 *SM_RAND -- random344 *------------------------------------------------------------------------------345 cmpi.w #SM_RAND,d0 *is this the random source ?346 bne srctyp0 *jump if not347 * 348 movem.l d1-d2/a0-a2,-(a7) *preserve registers around call349 move.w PT_VMLT(a2,d2.W),-(a7) *pass multiplier to xgetran()350 jsr _xgetran *call for a random number351 tst.w (a7)+ *clean up stack352 movem.l (a7)+,d1-d2/a0-a2 *restore registers353 move.w d0,d5 *put random value in the value register354 bra applym *go apply the multiplier355 * 356 .page 357 *------------------------------------------------------------------------------358 *SM_FREQ -- frequency359 *------------------------------------------------------------------------------360 srctyp0: cmpi.w #SM_FREQ,d0 *is this the frequency source ?361 bne srctyp1 *jump if not362 * 363 move.w (a1),d0 *get the pitch364 lsr.w #6,d0 *shift to a word index365 andi.w # $01FE,d0 *mask out extraneous bits366 lea _ptoftab,a0 *get entry from ptoftab[]367 move.w 0(a0,d0.W),d5 *...368 bra applym *go apply the multiplier369 * 370 *------------------------------------------------------------------------------371 *SM_PTCH -- pitch372 *------------------------------------------------------------------------------373 srctyp1: cmpi.w #SM_PTCH,d0 *is this the pitch source ?374 bne srctyp2 *jump if not375 * 376 move.w (a1),d5 *get the pitch as the value377 bra applym *go apply the multiplier378 * 379 *------------------------------------------------------------------------------380 *SM_KVEL -- velocity381 *------------------------------------------------------------------------------382 srctyp2: cmpi.w #SM_KVEL,d0 *is this the key velocity source ?383 bne srctyp3 *jump if not384 * 385 move.w FH_TRG(a1),d0 *get the trigger number386 add.w d0,d0 *... as a word index387 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 multiplier390 * 391 *------------------------------------------------------------------------------392 *SM_KPRS -- pressure393 *------------------------------------------------------------------------------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 number398 add.w d0,d0 *... as a word index399 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 multiplier402 * 403 .page 404 *------------------------------------------------------------------------------405 *all other sources come out of the valents[] array406 *------------------------------------------------------------------------------407 srctyp4: lea _vce2grp,a0 *point at vce2grp[]408 move.w _curpf_f,d5 *get voice number in d5409 lsr.w #3,d5 *...410 andi.w # $001E,d5 *... as a word index411 move.w 0(a0,d5.W),d5 *get the group number412 subq.w #1,d5 *...413 lsl.w #4,d5 *shift it left a nybble414 or.w d5,d0 *OR it into the source number415 add.w d0,d0 *make source number a valents[] index416 move.w d0,d5 *... (fast multiply by VALLEN = 10417 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 value421 * 422 *------------------------------------------------------------------------------423 *apply the multiplier to the source, and add it to the function value424 *------------------------------------------------------------------------------425 applym: muls PT_VMLT(a2,d2.W),d5 *apply the multiplier426 asr.l #7,d5 *scale the result427 asr.l #8,d5 *...428 ext.l d3 *add the function value429 add.l d3,d5 *...430 cmpi.l #VALMAX,d5 *check for overflow431 ble srcmlt1 *jump if no overflow432 * 433 move.l #VALMAX,d5 *limit at VALMAX434 bra srcmlt2 *...435 * 436 srcmlt1: cmpi.l #VALMIN,d5 *check for underflow437 bge srcmlt2 *jump if no underflow438 * 439 move.l #VALMIN,d5 *limit at VALMIN440 * 441 srcmlt2: move.w d5,d3 *setup value for output to FPU442 * 443 .page 444 *------------------------------------------------------------------------------445 *adjust the value according to the function type446 *------------------------------------------------------------------------------447 nosrc: move.w d1,d0 *get function type448 andi.w # $01E0,d0 *...449 * 450 *------------------------------------------------------------------------------451 *level or location452 *------------------------------------------------------------------------------453 cmpi.w #P_LEVEL,d0 *see if it's the level454 beq outsegl *jump if so455 * 456 cmpi.w #P_LOCN,d0 *see if it's the location457 bne outsegf *jump if not458 * 459 tst.w d3 *check sign of value460 bpl outsegc *jump if positive461 * 462 clr.w d3 *force negative values to 0463 * 464 outsegc: asr.w #5,d3 *shift value to LS bits465 sub.w #500,d3 *subtract 5.00 from value466 asl.w #6,d3 *readjust to MS bits467 bra outseg3 *go output the value468 * 469 outsegl: tst.w d3 *check sign of value470 bpl outsegm *jump if positive471 * 472 clr.w d3 *limit negative values at 0473 * 474 outsegm: asr.w #5,d3 *shift value to LS bits475 sub.w #500,d3 *subtract 5.00 from value476 asl.w #6,d3 *readjust to MS bits477 bra outseg3 *go output the value478 * 479 .page 480 *------------------------------------------------------------------------------481 *filter482 *------------------------------------------------------------------------------483 outsegf: cmpi.w #P_FILTER,d0 *see if it's the filter484 bne outsegp *jump if not485 * 486 ext.l d3 *make function value a long487 asr.l #1,d3 *multiply function value by .75488 move.l d3,d0 *... (fast multiply by .75489 asr.l #1,d0 *... via shift and add)490 add.l d0,d3 *...491 move.w (a1),d0 *add pitch492 ext.l d0 *...493 add.l d0,d3 *...494 cmpi.l #VALMAX,d3 *see if it's within limits495 ble outsega *...496 * 497 move.w #VALMAX,d3 *limit at VALMAX498 bra outseg3 *...499 * 500 outsega: cmpi.l #VALMIN,d3 *...501 bge outseg3 *...502 * 503 move.w #VALMIN,d3 *limit at VALMIN504 bra outseg3 *...505 * 506 .page 507 *------------------------------------------------------------------------------508 *freq 1..4509 *------------------------------------------------------------------------------510 outsegp: cmpi.w #P_FREQ1,d0 *see if it's freq1511 beq outseg0 *go process freq1512 * 513 outsegq: cmpi.w #P_FREQ2,d0 *see if it's freq2514 beq outseg0 *process it if so515 * 516 cmpi.w #P_FREQ3,d0 *see if it's freq3517 beq outseg0 *process it if so518 * 519 cmpi.w #P_FREQ4,d0 *see if it's freq4520 bne outseg3 *jump if not521 * 522 outseg0: ext.l d3 *scale the point value to cents offset523 asr.l #5,d3 *...524 sub.l #500,d3 *... value - 500525 asl.l #LSPCH,d3 *mult. by 2 and scale for 1/2 cent lsb526 move.w (a1),d0 *add pitch from function header527 ext.l d0 *...528 add.l d0,d3 *...529 cmp.l #PCHMAX,d3 *see if result is valid530 ble outseg3 *jump if within pitch limits531 * 532 move.l #PCHMAX,d3 *limit at maximum pitch533 * 534 *------------------------------------------------------------------------------535 *send the value to the FPU536 *------------------------------------------------------------------------------537 outseg3: move.b FH_TMD(a1),d0 *get hardware bits from function header538 eor.w #VAL_BITS,d0 *toggle new value select bits539 move.b d0,FH_TMD(a1) *store updated word540 btst.l #VSUBNBIT,d0 *check which value address to use28 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 541 beq outseg1 542 * 543 move.w d3,F_VAL01(a3,d1.W) *send value to FPU542 543 move.w d3,F_VAL01(a3,d1.W) | send value to FPU 544 544 bra outseg2 545 * 546 outseg1: move.w d3,F_VAL10(a3,d1.W) *send value to FPU547 * 548 outseg2: andi.w #MSK_CTL,d0 *mask off software bits549 ori.w #UPD_BIT+INT_BIT,d0 *set the update & !lastseg bits550 move.w d0,F_CTL(a3,d1.W) *send control word to FPU551 bra pfnext *done -- exit552 * 553 .page 554 * 555 *------------------------------------------------------------------------------556 *act2 -- AC_ENBL -- stop if key is up557 *---- ----------------------------558 act2: move.w _curpf_f,d0 *get voice as a word index559 lsr.w #3,d0 *...560 andi.w # $001E,d0 *...561 lea _vce2trg,a0 *check to see if voice is free562 move.w 0(a0,d0.W),d0 *...563 cmpi.w #-1,d0 *...564 beq stopfn *if so, stop the function565 * 566 btst #15,d0 *see if voice is held567 bne act0 *continue if so568 * 569 btst #14,d0 *...570 bne act0 *...571 * 572 lea _trgtab,a0 *check trigger table entry573 tst.b 0(a0,d0.W) *...574 bne act0 *if trigger is active, continue575 * 576 bra stopfn *if not, stop the function577 * 578 *------------------------------------------------------------------------------579 *act3 -- AC_JUMP -- unconditional jump580 *---- -----------------------------581 act3: cmp.b FH_PIF(a1),d4 *check jump point against limit582 bcc stopfn *stop function if jump point invalid583 * 584 clr.w d2 *get index of first point585 move.b FH_PT1(a1),d2 *...586 add.b d4,d2 *add jump point587 move.b d2,FH_CPT(a1) *make it the current point588 lsl.w #2,d2 *develop new point index in d2589 move.w d2,d0 *... (fast multiply by PT_LEN = 12590 add.w d2,d2 *... via shift and add)591 add.w d0,d2 *...592 bra outseg *output the segment593 * 594 .page 595 * 596 *------------------------------------------------------------------------------597 *act4 -- AC_LOOP -- jump to point PT_PAR1 PT_PAR2 times598 *---- ----------------------------------------------599 act4: tst.b PT_PAR3(a2,d2.W) *check counter600 bne act4a *jump if it's running601 * 602 move.b PT_PAR2(a2,d2.W),d0 *get parameter603 subi.w #90,d0 *put parameter in random range604 bmi act4b *treat as normal if < 90605 * 606 movem.l d1-d2/a0-a2,-(a7) *get ranged random number607 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 counter612 beq act0 *next segment if cntr set to 0613 * 614 bra act3 *else jump to the point615 * 616 act4b: move.b PT_PAR2(a2,d2.W),PT_PAR3(a2,d2.W) *set counter617 beq act0 *next segment if cntr set to 0618 * 619 bra act3 *else jump to the point620 * 621 act4a: subq.b #1,PT_PAR3(a2,d2.W) *decrement counter622 beq act0 *next segment if cntr ran out623 * 624 bra act3 *jump if it's still non-zero625 * 626 *------------------------------------------------------------------------------627 *act5 -- AC_KYUP -- jump if key is up628 *---- ----------------------------629 act5: move.w _curpf_f,d0 *get voice as a word index630 lsr.w #3,d0 *...631 andi.w # $001E,d0 *...632 lea _vce2trg,a0 *check to see if voice is free633 move.w 0(a0,d0.W),d0 *...634 cmpi.w #-1,d0 *...635 beq act3 *if so (inactive), do the jump636 * 637 btst #15,d0 *see if voice is held638 bne act0 *continue if so639 * 640 btst #14,d0 *...641 bne act0 *...642 * 643 lea _trgtab,a0 *check trigger table entry644 tst.b 0(a0,d0.W) *see if the trigger is active645 beq act3 *if not, do the jump646 * 647 bra act0 *if so, do next segment648 * 649 .page 650 * 651 *------------------------------------------------------------------------------652 *act6 -- AC_KYDN -- jump if key is down653 *---- ------------------------------654 act6: move.w _curpf_f,d0 *get voice as a word index655 lsr.w #3,d0 *...656 andi.w # $001E,d0 *...657 lea _vce2trg,a0 *check to see if voice is free658 move.w 0(a0,d0.W),d0 *...659 cmpi.w #-1,d0 *...660 beq act0 *if so (inactive), continue661 * 662 btst #15,d0 *see if voice is held663 bne act3 *do jump if so664 * 665 btst #14,d0 *...666 bne act3 *...667 * 668 lea _trgtab,a0 *check trigger table entry669 tst.b 0(a0,d0.W) *see if the trigger is active670 bne act3 *if so, do the jump671 * 672 bra act0 *if not, do next segment673 * 674 *------------------------------------------------------------------------------675 act7: bra act0 *AC_HERE: treat act7 as AC_NULL676 * 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 index682 lsr.w #3,d0 *...683 andi.w # $001E,d0 *...684 lea _vce2trg,a0 *point at voice to trigger table685 move.w 0(a0,d0.W),d0 *get trigger table entry686 cmpi.w #-1,d0 *see if voice is free687 beq act0 *treat as no-op if so688 * 689 btst #15,d0 *see if voice is held by a pedal690 bne act1a *sustain if so691 * 692 btst #14,d0 *see if voice is sustained by a pedal693 bne act1a *sustain if so694 * 695 lea _trgtab,a0 *point at trigger table696 tst.b 0(a0,d0.W) *check trigger status697 beq act0 *continue if not active698 * 699 act1a: move.l _pfqhdr,d3 *see if any pflist entries remain700 beq act0 *no-op if not (shouldn't happen ...)701 * 702 move.b FH_PT1(a1),d0 *get first point number703 add.b FH_PIF(a1),d0 *add base to first point704 subq.b #1,d0 *make d0 last point number705 cmp.b FH_CPT(a1),d0 *check current point number706 beq stopfn *done if this is the last point707 * 708 addq.b #1,FH_CPT(a1) *update current point number709 addi.w #PT_LEN,d2 *update point index710 movea.l d3,a0 *acquire a new pflist entry711 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 entry715 move.w _curpf_f,PF_FUNC(a0) *set v/p word in entry716 movem.l d1-d2/d4/a1-a3,PF_D1(a0) *set registers in entry717 move.b FH_TMD(a1),d0 *stop the function718 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 entry725 * 726 .page 727 *------------------------------------------------------------------------------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 728 .data 729 *------------------------------------------------------------------------------730 * 731 *actab -- action code dispatch table732 *----- --------------------------733 actab: dc.l act0 *0 - AC_NULL: no action734 dc.l act1 *1 - AC_SUST: sustain735 dc.l act2 *2 - AC_ENBL: enable736 dc.l act3 *3 - AC_JUMP: unconditional jump737 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 up741 * 742 *------------------------------------------------------------------------------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 743 .bss 744 *------------------------------------------------------------------------------745 * 746 *----------------- local variables --------------------------------------------747 * 748 _curpf_f: ds.w 1 *interrupting voice & parameter from FPU749 * 750 *----------------- debug variables --------------------------------------------751 * 752 _curpf_t: ds.w 1 *current trigger753 * 754 _curpf_l: ds.l 1 *current pflist entry755 * 756 *------------------------------------------------------------------------------757 * 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 758 .end
Note:
See TracChangeset
for help on using the changeset viewer.