Changeset 4f508e6 in buchla-68k for ram/procpfl.s


Ignore:
Timestamp:
07/01/2017 02:34:46 PM (7 years ago)
Author:
Thomas Lopatic <thomas@…>
Branches:
master
Children:
08e1da1
Parents:
f40a309
Message:

Converted assembly language files.

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