               INCLUDE HPFIXUPS
               TITLE "PERF_MIDI"
***************************************************************************************************
***************************************************************************************************
***                                                                                             ***
***            PERF_MIDI - YOU CONNECT THE DOTS .....                                           ***
***                                                                                             ***
***************************************************************************************************
***************************************************************************************************
;
NEG_EXT        EQU     0FFFFFF00H      ;USE IN MOVEQ INSTRUCTIONS WHERE ARG IS
                                       ;80H OR LARGER - HP XASM DOES NOT HANDLE
                                       ;SIGN-EXTEND CORRECTLY.  COSMETIC, KEEPS
                                       ;ACTUAL BYTE VALUE CLEARER.
;
               ABS_SHORT

               GLB     PRO_MIDI,MIDI_GARBAGE,GET_BYTE,STAT_BYTE,GRAB_BYTE
               GLB     KILL_ACTIVE_PERF,DEACTIVATE_PERF,UPDATE_A_PAD

               EXTERNAL  BACK_HANDLER,UNLOAD_LEVEL_6,VOICE_GATE_OFF,VOICE_ASSIGN
               EXTERNAL  TOGGLE_ALT_PARAMS
               EXTERNAL  UPDATE_CUR_STUFF,CUR_MIDI_PROG,INSTALL_KIT
               EXTERNAL  SEQ_NOTE_OFF,SEQ_NOTE_ON,S_3_BYTE,S_2_BYTE,BLIND_ECHO_3,BLIND_ECHO_2
               EXTERNAL  ECHO_2,ECHO_3
               EXTERNAL  POLY_OFF_SEQ_PAD,POLY_ON_SEQ_PAD
               EXTERNAL  MAPPED_OFF_SEQ_PAD,MAPPED_ON_SEQ_PAD
               EXTERNAL  SEQ_MOD,SEQ_PRESS
               EXTERNAL  QUICK_LOG_IN,QUICK_LOG_OUT
               EXTERNAL  INITIAL_PAN_SUB,LIVE_VOICES_OFF
               EXTERNAL  MIDI_KIT_ASSIGN_SUB
;890313               EXTERNAL  SYS_EX
;890313               EXTERNAL  SEQ_EX
               .IMPORT SYS_EX_IN
;
               EXTERNAL  MIDI_ROUTINE_PENDING,MA_RCV_CNT,MIDI_MODE,MIDI_IN_CHANNEL
               EXTERNAL  LAST_MIDI_CHANNEL,LAST_MIDI_KEYNUM,LAST_MIDI_VELOCITY
               EXTERNAL  BG_TEMP_1_B,BG_TEMP_9_B
               EXTERNAL  L6_TEMP_1_B
               EXTERNAL  ASSIGN_BLOCK,ALT_PARAM_FLAG,PAD_PANS,PAD_LEVELS
               EXTERNAL  BUILD_KIT_FLAG
               EXTERNAL  MAP_ARRAY_TBL,MAP_ARRAY_2TBL,LAST_PRESSURE,LAST_MOD_WHL
               EXTERNAL  SUBFUN_INSTALL,CURRENT_SOUND
               EXTERNAL  LAST_STAT_BYTE,MIDI_KEY_MAP,P_KEY_MAP
               EXTERNAL  PAD_SOUNDS,PAD_PITCHES,FAKE_KEY_MAP,CURRENT_SEQUENCE
               EXTERNAL  PAD_RED,SOUND_RED,ALT_P_RED,PITCH_RED,PAN_RED,LEVEL_RED
               EXTERNAL  CUR_L_MAP,CUR_R_MAP,CUR_TRIG_FLAG,HOLD_TO_ALT_FLAG
               EXTERNAL  MOD_PIT,MOD_PAN,MOD_LEV,PWHL_PIT,PWHL_PAN,PWHL_LEV,PRESS_PIT,PRESS_PAN,PRESS_LEV
               EXTERNAL  M_COM_PIT,M_COM_PAN,M_COM_LEV,M_PIT_ACT,M_PAN_ACT,M_LEV_ACT
               EXTERNAL  CUR_MOD_ROUT,CUR_PWHL_ROUT,CUR_PRESSURE_ROUT,M_VOL_ROUT
               EXTERNAL  PAN_PAN_PAN,LEVEL_LEVEL_LEVEL,SONG_SEL_ENABLE
               EXTERNAL  MIDI_DATA_1,MIDI_DATA_2,SOUND_SEQ_SWITCH
               EXTERNAL  LAST_MIDI
               EXTERNAL  CURRENT_VOLUME
               EXTERNAL  MIDI_DEFAULT_VEL
               EXTERNAL  CUR_SUB_BLOCK
               EXTERNAL  EDIT_KIT_INDEX
               EXTERNAL  PAD_JUST_HIT
               EXTERNAL  INT_ERASE_MAP,ERASING
               EXTERNAL  SAMPLED_SOUNDS,AUTORPT_FLAG

;VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
;
;             'ELLO.  BACKGROUND ENTERS HERE 'CAUSE IT DETECTED SOMETHING IN THE MIDI IN BUFFER.
;              WE RESPOND BY BRANCHING TO THE LAST ROUTINE WE WERE IN (WE MAY HAVE BEEN IN THE
;              MIDDLE OF A MESSAGE, ETC.).
;
;             THE GET_BYTE ROUTINE IS THE FIRST THING CALLED.  IT DETECTS IF A BYTE IS A NEW
;              STATUS BYTE (IF SO, PROCESSES THAT FROM SCRATCH) OR A DATA BYTE - IF THAT,
;              CARRIES IT OFF TO THE APROPOS ADDRESS.
;
;             WE HAVE TWO BASIC MODES OF OPERATION, OF WHICH I WILL FILL YOU IN ABOUT AFTER
;              THE BMF.  ONE IS HERE NOW.....
;
;AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
               SKIP
;VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
;
;             BACKGROUND ENTRY POINT
;
PRO_MIDI
               MOVE.L  MIDI_ROUTINE_PENDING,-(A7)     ;PUT OLD RET ADDRESS BACK ON STACK
               BRA.S   GET_BYTE             ;WE ARE HERE 'CAUSE THERE IS A BYTE TO FETCH
;;;;           MOVE.L  MIDI_ROUTINE_PENDING,A0   ;IF WE CAME BACK, A DATA BYTE - GO CONTINUE PROCESSING
;;;;           JMP     (A0)



MIDI_GARBAGE   ; WE SIT HERE IF WE HAVING NOTHING DISTINCT TO DO (ie. RIDING OUT AN UNRECOGNIZED
; STATUS BYTE, ETC.).  WE EXIT WHEN GET_BYTE GETS ANOTHER STATUS BYTE.
               BSR     GET_BYTE
               BRA     MIDI_GARBAGE         ;CIRCULATE HERE 'TILL SOMETHING VALID HITS


;890313
;890313
;890313REAL_RET       ;SYSTEM REAL-TIME BYTE CAME IN THE MIDDLE OF A MESSAGE - GOTTA PICK UP FROM WHERE WE WERE
;890313               MOVE.L  MIDI_ROUTINE_PENDING,-(A7)     ;PUT OLD RET ADDRESS BACK ON STACK
;890313; FALL INTO GET_BYTE
;890313
;890313        this has been moved to where it is actually used ....
;890313


GET_BYTE       ; CALLED WHEN YOU WANT A BYTE OUT OF THE BUFFER.  IF NOBODY HOME, POPS AND REMEMBERS
; THE ADDRESS OF WHO CALLED US AND SAVE IT; RETURN TO BACKGROUND.  IF A NEW STATUS BYTE, FORGET WHO
; CALLED US AND GO PROCESS.  IF A DATA BYTE, RETURN IN D0.B.  ALSO TRASHES 10.
               TST     MA_RCV_CNT           ;ANYTHING PENDING?
               BEQ.S   SEE_YOU_LATER        ;    IF NOT, THEN GIT

               BSR     UNLOAD_LEVEL_6       ;PRY A BYTE AWAY FROM THE UART IN BUFFER
               EXT     D0                   ;SEE IF STATUS BYTE
               BMI.S   NEW_FACE             ;    IF YES, HANDLE
               RTS                          ;         ELSE, GIVE BYTE TO CALLING ROUTINE

NEW_FACE
               CMP.B   #0F8H,D0             ;IF REALTIME, IGNORE
               BCC     GET_BYTE
               MOVE.L  (A7)+,MIDI_ROUTINE_PENDING     ;POP & SAVE RETURN ADDRESS
               BRA.S   STAT_BYTE

SEE_YOU_LATER
               MOVE.L  (A7)+,MIDI_ROUTINE_PENDING     ;POP & SAVE THIS CALLER'S ADDRESS FOR LATER REF
               BRA     BACK_HANDLER         ;CONTINUE WITH OTRA CHORES.



GRAB_BYTE      ; HANG AROUND UNTIL A NEW BYTE APPEARS - DO NOT GO BACK TO BACKGROUND
               TST     MA_RCV_CNT           ;NEW SPECIMEN YET?
               BEQ.S   GRAB_BYTE            ;    IF NOT, WAIT (NEW ONE WILL CAUSE INT & MAGICALLY APPEAR)
               BSR     UNLOAD_LEVEL_6       ;GET NEW BYTE
               ANDI    #0FFH,D0             ;    CLEAN UP INTO A WORD
               RTS     ;               GIVE BACK
;
;AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
               SKIP
;VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
;
;             HAVE A NEW STATUS BYTE - CHECK WHAT MODE WE'RE IN, AND BRANCH TO THE APROPOS ROUTINE.
;
STAT_BYTE
               MOVE.B  D0,LAST_STAT_BYTE    ;SAVE FOR FUTURE CHECKING

               CMPI.B  #0F0H,D0             ;IF A SYSTEM BYTE, HANDLE BY ITSELF
               BCC     MIDI_SYSTEM

               TST     SOUND_SEQ_SWITCH     ;SEE IF AIMED AT SOUNDS OR SEQUENCER
               BNE     FOR_SEQUENCER

               MOVE    #MULTI_STAT_TBL,A0  ;PRE-LOAD TO HANDLE MAPPED MODE

               MOVE    MIDI_MODE,D1         ;CHECK THE MODE - 0=OFF, 1=OMNI, 2=POLY, 3=MULTI.
               BEQ.S   KING_CRIMSON         ;IF MIDI OFF, IGNORE MESSAGE, BUT HANDLE POSSIBLE ECHO
               CMPI    #3,D1                ;MULTI MODE?
               BEQ     MULTI_STAT_BYTE      ;    IF SO, PROCESS
               CMPI    #1,D1                ;OMNI MODE?
               BEQ     PRO_STAT_BYTE        ;    IF SO, PROCESS, REGARDLESS OF CHANNEL
                                            ;         ELSE, CHANNEL-FILTER IT.
               MOVE    D0,D1                ;MAKE A COPY OF STAT BYTE
               ANDI    #0FH,D1              ;MASK DOWN TO CHANNEL
               CMP     MIDI_IN_CHANNEL,D1   ; SEE IF RECEIVED CHANNEL MATCHES ALLOWED ONE
               BEQ.S   PRO_STAT_BYTE        ;    IF MATCH, GO FOR IT
KING_CRIMSON                                ;         ELSE, MERELY BUNDLE FOR POSSIBLE ECHO
               MOVE    #BLIND_ECHO_TBL,A0
               BRA.S   MULTI_STAT_BYTE
PRO_STAT_BYTE
               MOVE    #POLY_STAT_TBL,A0    ;LOAD UP ADDRESS OF STAT BYTE JUMP TABLE
MULTI_STAT_BYTE
               MOVE    D0,D1                ;MAKE ANOTHER COPY OF DATA BYTE
               ANDI    #0F0H,D1             ; MASK TO JUST STATUS NIBBLE
               SUB     #80H,D1              ; KNOCK OFF OFFSET (80H = NOTE OFF = FIRST STAT BYTE)
               LSR     #3,D1                ; CONVERT INTO A JUMP TABLE OFFSET
               MOVE    0(A0,D1),A0
               JMP     (A0)                 ;  AND OFF WE GO...



FOR_SEQUENCER
               MOVE    #SEQ_STAT_TBL,A0
               BRA     MULTI_STAT_BYTE


POLY_STAT_TBL          ; OMNI/POLY MODE ROUTINES
               DC.W    POLY_NOTE_OFF        ;8NH - NOTE OFF
               DC.W    POLY_NOTE_ON         ;9NH - NOTE ON
               DC.W    BLIND_ECHO_3         ;ANH - KEY PRESSURE
               DC.W    CONTROLLER           ;BNH - CONTROLLERS
               DC.W    PROGRAM              ;CNH - PROGRAM CHANGE
               DC.W    PRESSURE             ;DNH - CHANNEL PRESSURE
               DC.W    PITCH_WHEEL          ;ENH - PITCH BEND


MULTI_STAT_TBL         ; MULTI MODE ROUTINES
               DC.W    MULTI_NOTE_OFF       ;8NH - NOTE OFF
               DC.W    MULTI_NOTE_ON        ;9NH - NOTE ON
               DC.W    BLIND_ECHO_3         ;ANH - KEY PRESSURE
               DC.W    CONTROLLER           ;BNH - CONTROLLERS
               DC.W    BLIND_ECHO_2         ;CNH - PROGRAM CHANGE
               DC.W    PRESSURE             ;DNH - CHANNEL PRESSURE
               DC.W    BLIND_ECHO_3         ;ENH - PITCH BEND


SEQ_STAT_TBL           ; SEQUENCER PACKING ROUTINES
               DC.W    SEQ_NOTE_OFF         ;8NH - NOTE OFF
               DC.W    SEQ_NOTE_ON          ;9NH - NOTE ON
               DC.W    S_3_BYTE             ;ANH - KEY PRESSURE
               DC.W    SEQ_MOD              ;BNH - CONTROLLERS
               DC.W    S_2_BYTE             ;CNH - PROGRAM CHANGE
               DC.W    SEQ_PRESS            ;DNH - CHANNEL PRESSURE
               DC.W    S_3_BYTE             ;ENH - PITCH BEND


BLIND_ECHO_TBL         ; RECEIVE & PACK MIDI FOR POSSIBLE ECHO - NOTHING ELSE
               DC.W    BLIND_ECHO_3         ;8NH - NOTE OFF
               DC.W    BLIND_ECHO_3         ;9NH - NOTE ON
               DC.W    BLIND_ECHO_3         ;ANH - KEY PRESSURE
               DC.W    BLIND_ECHO_3         ;BNH - CONTROLLERS
               DC.W    BLIND_ECHO_2         ;CNH - PROGRAM CHANGE
               DC.W    BLIND_ECHO_2         ;DNH - CHANNEL PRESSURE
               DC.W    BLIND_ECHO_3         ;ENH - PITCH BEND
;
;AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
               TITLE   "POLY MODE RECEIVE ROUTINES"
               SKIP
;VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
;VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
;VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
;
;             POLY MODE NOTE OFF - ENTER w/ STAT BYTE (WORTHLESS) IN D0.  GATHER IN KEYNUM AND
;              VELOCITY, SEE IF PITCH KEY OR 'DRUM' KEY.  CLEAR THIS KEY OUT OF MASK.  GENERATE
;              APROPOS NOTE OFFS AND RUN THROUGH VOICE_GATE_OFF.  THERE IS A POTENTIAL NOTE ON
;              FOR EVERY DRUM KEY, EACH DRUM KEY TIMES EACH PITCH KEY, AND (CONVERSELY) EACH PITCH
;              KEY TIMES EACH DRUM KEY.
;
POLY_NTE_OFF
               BSR     ECHO_3               ;SEE IF HAVE TO ECHO LAST MESSAGE
POLY_NOTE_OFF
               BSR     GET_BYTE             ;GET KEYNUM BYTE (RETS IN D0.B)
               MOVE.B  D0,MIDI_DATA_1       ; (SAVE FOR POSSIBLE ECHO)
               SUB     #23H,D0              ;KNOCK DOWN OFFSET TO LOWEST 'DRUM' KEY
               BCS     EAT_OFF_VELOCITY     ;    IF BELOW LEGAL RANCH, EAT THIS KEY & IGNORE
               MOVE    D0,LAST_MIDI_KEYNUM  ;    (SAVE FOR REFERENCE)

               CMP     #1AH,D0              ;SEE IF OFFSET KEY IS ABOVE LEGAL 'DRUM' KEY RANGE
               BCC     P_KEY_OFF            ;    IF SO, POSSIBLE PITCH KEY - HANDLE

               BSR     GET_BYTE             ;GET VELOCITY
               MOVE.B  D0,MIDI_DATA_2       ; (SAVE FOR POSSIBLE ECHO)
POLY_OFF_OFF
               MOVE.L  #80000000H,D0        ;PRE-SEED KEY-OFF SEARCH MASK
               LEA     KEY_CONV_TBL,A0      ;A0 -> TBL THAT CONVERTS FROM MIDI KEYNUMS TO 'PADS'
               MOVE    LAST_MIDI_KEYNUM,D1
               LSL     #1,D1                ; (WORD INDEX)
               MOVE    0(A0,D1),D0          ;GET PADNUM (IS OUR 'CHANNEL' TO MATCH)
               BMI     RUN_NOTE_OFF         ; IF UNMAPPED KEY, IGNORE - GET ANOTHER

               MOVE    D0,D4                ;SAVE PADNUM ASIDE FOR SEQUENCER DUTIES
               AND     #7,D4                ; MASK OFF GUNK (LIKE 'RIGHT PADS' BIT)

               MOVE    MIDI_KEY_MAP,D1      ;LOAD MAP OF KEY/PADS DOWN
               BCLR    D0,D1                ; TURN THIS KEY OFF
               MOVE    D1,MIDI_KEY_MAP

               TST.B   ERASING              ;IF NOT ERASING
               BEQ     OREGON_3             ;    THEN JUST TURN OFF
                                            ;         ELSE....
               MOVE    D0,D1                ;FIND SOUNDNUM AND LOG OUT OF ERASE_MAP
               MOVE    CUR_L_MAP,D2         ;SEE WHICH KIT IS BEING PLAYED
               BCLR    #3,D1                ; MASK OUT UPPER/LOWER KIT BIT - IN DOING SO, SEE WHO PLAYED
               BEQ.S   OREGON_1
               MOVE    CUR_R_MAP,D2         ;  (BIT SET MEANT PLAYING RIGHT, OR UPPER, KIT)
OREGON_1
               TST     D2                   ;    IF NO KIT ASSIGNED FOR THIS KYBD REGION
               BMI     RUN_NOTE_OFF         ;         THEN FORGET IT
               LSL     #3,D2                ;KIT * 8
               ADD     D1,D2                ;         + PADNUM
               MOVE    D2,A1                ;                    = PAD ARRAY INDEX
               MOVE.B  PAD_SOUNDS(A1),D5    ;SEE WHICH SOUND RESIDES UNDER THIS KIT/PAD LOCATION
               LSR     #1,D5                ; ROTATE OFF ALT_PARAM BIT
               BCC.S   OREGON_2             ;  AND IN DOING SO, SEE WHICH ARRAY (NORM OR ALT_P) WAS IN

               MOVE.L  INT_ERASE_MAP+4,D1   ;FLAG THIS SOUNDNUM OFF IN ERASE_MAP
               BCLR    D5,D1                ; (ALT_PARAM VERSION)
               MOVE.L  D1,INT_ERASE_MAP+4
               BRA.S   OREGON_3
OREGON_2
               MOVE.L  INT_ERASE_MAP,D1     ;FLAG THIS SOUNDNUM OFF IN ERASE_MAP
               BCLR    D5,D1                ; (NORMAL_PARAM VERSION)
               MOVE.L  D1,INT_ERASE_MAP
OREGON_3

;08AUG               LSR     #1,D0                ;ROTATE L/R MAP BIT OF PADNUM
               OR      #0C000H,D0           ;MASK ON 'GATE ON' BITS
               SWAP    D0

; AT THIS POINT, HAVE BUILT V_IDENTITY IN D0.  NOW, SEARCH FOR OCCURANCES OF THIS PAD AT ALL
; HELD PITCH KEYS.  IF NONE HELD, MOVE ON TO KILL JUST THE SOUND KEY (SEE BELOW).
;
; V_IDENTITY LOOKS LIKE:  1100 0aaa aaaa bbbb 80 00  WHERE aaaaaaa IS THE 'KEYNUM' (IN OUR
; CASE, PITCH), bbbb IS THE CHANNEL (IN OUR CASE, PADNUM), AND FF FF FLAGS US AS BEING MIDI.
               MOVE.L  P_KEY_MAP,D2         ;LOAD UP MAP OF PITCH KEYS ON
               BEQ     LOOK_FOR_SOUND_KEY   ;    IF ANY ON, GO KILL THOSE
               MOVEQ   #7,D3                ;SILLY TO KILL OFF MORE THAN 8 VOICES - COUNT 'EM OFF
               MOVEQ   #31,D1               ;POSSIBLE PITCHES ARE 00->31
SEARCH_AND_DESTROY
               BTST    D1,D2                ;SEE IF THIS PITCH IS A VIABLE CANIDATE TO KILL
               BEQ.S   SKIP_IT_1            ;    IF NOT, SKIP AROUND & TRY ANOTHER

               SWAP    D0                   ; (WORK ON LOWER WORD OF V_IDENTITY)
               ANDI    #0F00FH,D0           ;WIPE OUT OLD KEYNUM
               LSL     #4,D1                ; ROTATE PITCH INTO 'KEYNUM' POSITION
               OR      D1,D0                ; MASK IN NEW KEYNUM
               LSR     #4,D1                ; (RESTORE D1 TO ORIG CONDITION)
               MOVE    D1,D5                ; MAKE A COPY OF PITCH FOR SEQUENCER DUTIES
               SWAP    D0
               BSR     POLY_OFF_SEQ_PAD     ;SEE IF SEQUENCER RUNNING; IF SO, STUFF THIS EVENT OFF TO IT
               BSR     VOICE_GATE_OFF       ;GO TURN THIS SUCKER OFF

               TST.B   BG_TEMP_9_B          ;SEE IF WE ACTUALLY FOUND THIS GUY
               BNE.S   SKIP_IT_1            ;    IF NOT, WELL, TRY ANOTHER...
               DBRA    D3,SKIP_IT_1         ;         ELSE - ONE MORE DEAD (ONLY 8 VOICES - STOP THERE)
               BRA.S   LOOK_FOR_SOUND_KEY   ;         IF 8 KILLED, DONE (STOP KILLING FRENZY)
                                            ;         (BUT - STILL WRITE ANOTHER 32 PAD OFFS INTO
                                            ;         SEQUENCER, SINCE VIA VOICE STEALING, MAY HAVE
                                            ;         ONE - SUBSEQUENT PLAYS WILL ERASE PAD OFFS
                                            ;         WITHOUT MATCHING PAD OMS, SO EXCESS IS TEMPORARY)
SKIP_IT_1
               DBRA    D1,SEARCH_AND_DESTROY     ;GO FOR WHOLE SKEIN


LOOK_FOR_SOUND_KEY
;NOW - SE IF THE SOUND KEY WAS ALLOWED TO TURN ON A VOICE.  IF NOT, THEN  DONE.  ELSE, TURNED ON
; A VOICE AT WE-DON'T-KNOW-WHAT PITCH - THEREFORE, GOTTA TRY TO KILL AT ALL PITCHES.  AS SOON AS
; WE FIND ONE, THAT WAS IT - GIT.
;
; V_IDENTITY LOOKS LIKE:  1100 0aaa aaaa bbbb 80 00  WHERE aaaaaaa IS THE 'KEYNUM' (IN OUR
; CASE, PITCH), bbbb IS THE CHANNEL (IN OUR CASE, PADNUM), AND FF FF FLAGS US AS BEING MIDI.
               TST     CUR_TRIG_FLAG        ;IF LEFT-HAND KEYS ALSO TURN VOICES ON
               BEQ     DONE_WITH_KILLING
               MOVEQ   #31,D1               ;GO LOOK FOR EVERY POSSIBLE PITCH

DESTROY_LAST_ONE
               SWAP    D0                   ; (WORK ON LOWER WORD OF V_IDENTITY)
               ANDI    #0F00FH,D0           ;WIPE OUT OLD KEYNUM
               LSL     #4,D1                ; ROTATE PITCH INTO 'KEYNUM' POSITION
               OR      D1,D0                ; MASK IN NEW KEYNUM
               LSR     #4,D1                ; (RESTORE D1 TO ORIG CONDITION)
               MOVE    D1,D5                ; MAKE A COPY OF PITCH FOR SEQUENCER DUTIES
               SWAP    D0
               BSR     POLY_OFF_SEQ_PAD     ;SEE IF SEQUENCER RUNNING; IF SO, STUFF THIS EVENT OFF TO IT
               BSR     VOICE_GATE_OFF       ;GO TURN THIS SUCKER OFF

               TST.B   BG_TEMP_9_B          ;SEE IF WE ACTUALLY FOUND THIS GUY
               BEQ.S   DONE_WITH_KILLING    ;    IF YES, DONE.
               DBRA    D1,DESTROY_LAST_ONE  ;GO FOR WHOLE SKEIN

DONE_WITH_KILLING
               TST     MIDI_KEY_MAP         ;IF ALL NOTES NOW OFF, DISABLE ALL ACTIVE PERFORMANCE EDITS
               BNE.S   RUN_NOTE_OFF
               BSR     DEACTIVATE_PERF

RUN_NOTE_OFF   ;WE'RE DONE - NOW CHECK LAST STAT TO SEE IF WE RUNNING STATUS TO A NOTE ON OR
; A NOTE OFF.
               BSR     QUICK_LOG_OUT        ; LOG OUT OF HOLDING_BUFF
               BTST    #4,LAST_STAT_BYTE    ;NOTE ON IS A 90 - NOTE OFF IS AN 80.
               BNE     POLY_NTE_ON
               BRA     POLY_NTE_OFF
;
;AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
               SKIP
;VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
;
P_KEY_OFF      ;NOTE OFF KEYNUM IS UP IN THE PITCH KEY RANGE - HANDLE BY CLEARING OUR OF PITCH
; KEY MAP, AND SEARCH FOR ALL 'PADS' ON THAT MIGHT HAVE THIS PITCH (SO AS TO KILL THEM).
               SUB     #1EH,D0              ;KNOCK DOWN SO THAT LOWEST PITCH KEY NOW = 00.
               BCS     EAT_OFF_VELOCITY     ;    IF OFF BOTTOM, IGNORE
               CMP     #20H,D0              ;ONLY 32 PITCH KEYS
               BCC     EAT_OFF_VELOCITY     ;    IF OFF TOP, IGNORE

               MOVE    D0,LAST_MIDI_KEYNUM  ;SAVE

               BSR     GET_BYTE             ;GET (AND IGNORE) VELOCITY
               MOVE.B  D0,MIDI_DATA_2       ; (SAVE FOR POSSIBLE ECHO)
P_KEY_OFF_OFF
               MOVE    LAST_MIDI_KEYNUM,D2
               MOVE    D2,D5                ;MAKE COPY OF PITCH FOR SEQUENCER DUTIES
               MOVE.L  P_KEY_MAP,D1         ;KILL THIS SUCKER OFF
               BCLR    D2,D1
               MOVE.L  D1,P_KEY_MAP

               MOVE.L  #0C0008000H,D0       ;INIT V_IDENTITY FOR KILLING SPREE
               MOVEQ   #15,D1               ;LOAD NUMBER OF 'PADS' TO CHECK
               LSL     #4,D2                ;PRE-ROTATE PITCH ('KEYNUM') FOR MASKING
               MOVE    MIDI_KEY_MAP,D3      ;LOAD UP MAP ITSELF
               BEQ     RUN_NOTE_OFF         ;    IF NO PADKEYS ON, NOBODY TO TURN OFF
PITCH_BASED_DESTROY
               BTST    D1,D3                ;IS THIS PAD ON?
               BEQ     SKIP_ON_2            ;    IF NOT, TRY ANOTHER

               SWAP    D0                   ;         ELSE....
               MOVE    D2,D0                ;MOVE IN PITCH (KEYNUM)
               OR      D1,D0                ;MASK IN PADNUM ('CHANNEL')
               OR      #0C000H,D0           ; GATE ON FLAG
               SWAP    D0
               MOVE    D1,D4                ;MAKE COPY OF PADNUM FOR SEQUENCER DUTIES
               AND     #7,D4                ; (MASK OFF GUNK)
               BSR     POLY_OFF_SEQ_PAD     ;SEE IF SEQUENCER RUNNING; IF SO, STUFF THIS EVENT OFF TO IT
               BSR     VOICE_GATE_OFF       ; TURN THIS SUCKER OFF

SKIP_ON_2
               DBRA    D1,PITCH_BASED_DESTROY    ;LOOK THROUGH ALL 16 'PADS'

               TST.L   P_KEY_MAP            ;IF ALL PITCH KEYS OFF
               BNE     RUN_NOTE_OFF
               SF      M_PIT_ACT            ;    THEN CLEAR PENDING PITCH

               BRA     RUN_NOTE_OFF         ;DONE HERE, BOSS.... GO GET ANOTHER


EAT_OFF_VELOCITY       ;GOT AN ILLEGAL KEYNUM - WASTE THE VELOCITY, GO AGAIN.
               BSR     GET_BYTE
               MOVE.B  D0,MIDI_DATA_2       ; (SAVE FOR POSSIBLE ECHO)
               BSR     QUICK_LOG_OUT        ; LOG OUT OF HOLDING_BUFF
               BRA     RUN_NOTE_OFF
;
;AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
;AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
;AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
               SKIP
;VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
;VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
;VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
;
; POLY NOTE ON.  NOTE COULD EITHER BE IN THE 'PAD' OR 'PITCH' KEY REGION (OR ILLEGAL).
;  PAD KEYS MAP ON TO A PAIR OF KITS (VIA 'PRESETS').  PITCH KEYS ARE A RANGE OF 32
;  STARTING AT 41H.
;
; AND NOW, FOR THE RULES:
;  1)      IF A PAD KEY GOES ON, AND NO PITCH KEYS ARE HELD, THE SAMPLE CORRESPONDING
;  TO THE PAD TURNS ON WITH A PITCH/PAN/LEVEL PULLED OUT OF THE PAD ARRAYS.
;  2)      IF A PAD KEY GOES ON AND PITCH KEYS ARE HELD, THE SAMPLE ASSIGNED TO THAT
;  PAD GOES ON AT ALL THE PITCHES HELD (PAN AND LEVEL PULLED OUT OF PAD ARRAYS).
;  3)      IF A PITCH KEY GOES ON AND NO PAD KEYS ARE HELD, NOTHING REALLY SPECIAL
;  HAPPENS.
;  4)      IF A PITCH KEY GOES ON AND PAD KEYS ARE HELD, ALL SOUNDS ASSIGNED TO ALL
;  PAD KEYS HELD GO ON WITH THIS PITCH (WITH PAN AND LEVEL PULLED FROM THE PAD ARRAYS).
;
; NOW, FOR THE EXCEPTIONS - THERE IS A FLAG PER PRESET THAT MUTES THE PAD KEYS.  IN
;  OTHER WORDS, A PAD KEY STRUCK DOES NOT SOUND UNTIL PITCH KEYS ARE STRUCK.  THE OTRA
;  'EXCEPTION' IS THAT EACH NEW PITCH KEY STRIKE ACTS LIKE A CHANGE IN THE PITCH KNOB
;  FROM THE FRONT PANEL - KITS ARE EDITED, ETC.  WE LET THE BACKGROUND PICK THAT UP,
;  SINCE WE ARE USING OUR OWN PITCH IN REALTIME.  ( ? I don't see this -
;  is this still true? - Matt).
;
; IN GENERAL, LET ME NOTE THAT I TRIED TO EXECUTE AS MUCH CODE BETWEEN THE KEYNUM AND
;  VELOCITY AS POSSIBLE.  THIS IS BECAUSE IT WILL BE AT LEAST 320 usec UNTIL WE SEE THE
;  VELOCITY, AND THAT WOULD OTHERWISE BE TIME WASTED.  ALSO, IF WE WENT TO LOOK FOR THE
;  VELOCITY RIGHT AWAY AND IT WASN'T THERE, WE WOULD RETURN TO BACKGROUND AND HAVE TO GO
;  AROUND THERE UNTIL IT ARRIVED AND WE NOTICED IT.  TO THIS END, SOMETIMES EVEN DO STUFF
;  I MAY HAVE TO UNDO IF THE NOTE REALLY TURNS OUT TO BE A NOTE OFF - BUT SINCE AURAL
;  TIMING OF NOTE OFFS IS A LOT LESS CRITICAL THAN NOTE ONS, FUCK IT - AND IN THE MEANTIME,
;  WE SHAVE A BIT OF TIME, WHICH I KNOW BODDICKER CAN HEAR...
;
POLY_NTE_ON
               BSR     ECHO_3               ;POSSIBLE ECHO
               MOVE.B  MIDI_DATA_1,LAST_MIDI+1   ;MAKE NOTE OF LAST MIDI NOTEON.
POLY_NOTE_ON
               BSR     GET_BYTE             ;GO AFTER THE KEYNUM (COMES BACK IN D0.B)
               MOVE.B  D0,MIDI_DATA_1       ; (SAVE FOR POSSIBLE ECHO)
               SUB     #23H,D0              ;KNOCK DOWN SO THAT LOWEST LEGAL PAD KEY = 00.
               BCS     EAT_VELOCITY         ;    IF BELOW THE LEGAL RANGE, FUCK IT
               MOVE    D0,LAST_MIDI_KEYNUM  ;    (SAVE FOR FUTURE REF)
               CMP     #1AH,D0              ;EQUAL THE ALT PARAM TOGGLE KEY?
               BEQ     ALT_P_KEY            ;    IF SO, GO SERVICE
               BCC     P_KEY_ON             ;    IF HERE OR ABOVE, POSSIBLE PITCH KEY - SERVICE

               LEA     KEY_CONV_TBL,A0      ;         ELSE, OURS!
               LSL     #1,D0                ; (WORD INDEX)
               MOVE    0(A0,D0),D1          ;COVERT FROM KEYNUM INTO A PADNUM
               BMI     EAT_VELOCITY         ;    IF AN UNASSIGNED KEY, FUCK IT
               MOVE    D1,PAD_RED           ;REMEMBER LAST PADNUM INVOLVED
               LSR     #1,D0

               MOVE    CUR_L_MAP,D2         ;NOW, CROSS-REFERENCE PAD TO THE ACTIVE KITS
               BCLR    #3,D1                ; BIT 3 SEZ IF LEFT (0) OR RIGHT (1) KIT
               BEQ.S   ALEX_1
               MOVE    CUR_R_MAP,D2
ALEX_1
               TST     D2                   ;IF NO KIT ASSIGNED, SPLIT
               BMI     EAT_VELOCITY
               MOVE    D1,PAD_JUST_HIT      ;ELSE, UPDATE INDEXES FOR MOST RECENT PAD HIT,
               MOVE    D2,EDIT_KIT_INDEX    ;LAST KIT FROM WHICH LIVE EVENT WAS PLAYED.

               TST.B   BUILD_KIT_FLAG       ;ARE WE IN KIT-BUILD SCREEN?
               BEQ.S   GLORTH_10            ;BRANCH IF NOT, ALL IS COOLNESS -
               ADD     #32,D2               ;YES - TACK ON AN OFFSET TO CAUSE PERF-PARAM ACCESS
                                            ;FROM KIT PRESET ARRAYS INSTEAD OF LIVE PAD ARRAYS.
GLORTH_10
               LSL     #3,D2                ;KIT * 8
               ADD     D1,D2                ;        + PAD = PROPER OFFSET INTO PAD ARRAYS
               MOVE    D2,A1                ;A1 IS NOW PERFORMANCE PARAMETER ARRAY INDEX.

               MOVE    PAD_RED,D1           ;RECOVER UNCASTRATED PADNUM
               CLR     D4
               BSET    D1,D4
               MOVE    D4,FAKE_KEY_MAP      ; FAKE KEYMAP OF JUST THIS NEW KEY

               MOVE.L  D1,-(A7)             ;PROTECT REGGIES...
               BSR     MIDI_PERF_EDITS      ;              ...WHILE UPDATING PITCH/PAN/LEVEL EDITS
               MOVE.L  (A7)+,D1

               CLR     D5                   ;START WITH A CLEAN SLATE

               MOVE.B  PAD_SOUNDS(A1),D5    ;GET SOUND NUMBER / ALT-PARAMS SETTING FOR THIS 'PAD'.
               MOVE    D5,D4
               LSR     #1,D5                ;ISOLATE SOUND NUMBER IN D5,
               AND     #1,D4                ;ISOLATE ALT-PARAMS SETTING IN D4.
;
               MOVE.L  SAMPLED_SOUNDS,D3    ;SEE IF THIS SOUND IS SAMPLED.
               BTST    D5,D3
               BEQ     EAT_VELOCITY         ;SKIP ON OUTA HERE IF NOT.

;23NOV               MOVE    D5,A0                ;SEE IF THIS SOUND IS SAMPLED
;23NOV               BSR     GET_S_BLK_PTR        ; LOOK AT THIS SOUND'S BLOCK
;23NOV               BTST    #SAMPLED_BIT,S_STATUS(A0)
;23NOV               BEQ     EAT_VELOCITY         ;    IF NOT, SKIP

               MOVE    D5,SOUND_RED         ;NOTE THAT WE ARE DOING AS MUCH PRIOR CALCULATION AS POSSIBLE
               MOVE    D4,ALT_P_RED         ; WHILE WAITING FOR VELOCITY.  THESE END UP IN ASSIGN_BLOCK.

               TST.B   ERASING              ;IF NOT ERASING
               BEQ.S   ORANGE_1             ;    THEN JUST TURN ON
                                            ;         ELSE....
               TST     D4
               BEQ.S   LOG_ERASE_NORM       ;MAINTAIN BIT FLAGS OF SOUNDS ON FOR ERASING.
LOG_ERASE_ALT
               MOVE.L  INT_ERASE_MAP+4,D0   ; ABOVE CHECK SAID ALT PARAM - SET IN THAT LONG WORD
               BSET    D5,D0
               MOVE.L  D0,INT_ERASE_MAP+4
               BRA.S   ORANGE_1
LOG_ERASE_NORM
               MOVE.L  INT_ERASE_MAP,D0     ; ABOVE CHECK SAID NORMAL - SET IN THAT LONG WORD
               BSET    D5,D0
               MOVE.L  D0,INT_ERASE_MAP
ORANGE_1
               CLR     D3                   ;CLEAN SLATES-VILLE FOR D3, HERE.

               MOVE.B  PAD_LEVELS(A1),D3    ;GET LEVEL
               MOVE    D3,LEVEL_RED

               MOVE.B  PAD_PITCHES(A1),D3   ;GET PITCH
               MOVE    D3,PITCH_RED

               MOVE.B  PAD_PANS(A1),D3      ;GET PAN
               MOVE    D3,PAN_RED

               MOVE    MIDI_KEY_MAP,D3      ;FLICK THIS KEY ON - MAY HAVE TO TURN IT OFF LATER
               BSET    D1,D3                ; IF THIS GUY PROVES TO BE A NOTE OFF, BUT THAT'S LIFE
               MOVE    D3,MIDI_KEY_MAP

               BSR     GET_BYTE             ;GET VELOCITY
               TST     D0                   ; IF 0, A NOTE OFF - OTHER PLANS
               BEQ.S   CHROME_3

               CMP     #40H,D0              ;IF ABOVE MEDIAN VELOCITY
               BCC.S   NON_OCTA_1           ;    THEN PASS
               LSL     #1,D0                ;         ELSE, DESENSITIZE LOWER REGION FOR OCTAPADS
               SUB     #40H,D0              ;DO THIS BY * 2 - 40H.  THIS MEANS A VALUE OF 20H = OUR
               BEQ.S   NO_ZERO_1            ; LOWEST VELOCITY, AND FOLLOW THAT SLOPE UP TO THE MEDIAN.
               BCC.S   NON_OCTA_1
NO_ZERO_1
               MOVEQ   #1,D0
NON_OCTA_1
               TST     MIDI_DEFAULT_VEL     ; ARE WE SUPPOSED TO SUBSTITUTE WITH A DEFAULT?
               BEQ.S   CHROME_3             ;    IF NOT, KEEP WHAT WE GOT
               MOVE    MIDI_DEFAULT_VEL,D0  ;         ELSE, SUBSTITUTE
CHROME_3
               MOVE.B  D0,MIDI_DATA_2       ; (SAVE FOR POSSIBLE ECHO)

               BEQ     POLY_OFF_OFF         ; IF VELOCITY = 0, THEN REALLY A NOTE OFF - DEAL WITH!
;
               MOVE    D5,CURRENT_SOUND     ;NOT A NOTE OFF - UPDATE CURRENT_SOUND.

               ADD     #3,D0                ;OFFSET MIDI VELOCITY FOR ROUNDING ERRORS BELOW
               BTST    #7,D0                ; ALSO MAKE SUREIN DOING THIS THAT VEL <> 0 AFTER ROTATING
               BEQ.S   SNEEZE_1
               MOVEQ   #7FH,D0
SNEEZE_1
               LSR     #2,D0                ;ROTATE VELOCITY DOWN TO 5 BITS
               MOVE    D0,LAST_MIDI_VELOCITY     ; SAVE

               MOVE    #4,ASSIGN_BLOCK      ;BUILD ASSIGN BLOCK
               MOVE    SOUND_RED,ASSIGN_BLOCK+2
               MOVE    ALT_P_RED,ASSIGN_BLOCK+4
               MOVE    PITCH_RED,ASSIGN_BLOCK+6
               MOVE    LEVEL_RED,ASSIGN_BLOCK+8
               MOVE    PAN_RED,ASSIGN_BLOCK+10
               MOVE    LAST_MIDI_VELOCITY,ASSIGN_BLOCK+12
               MOVE    PAD_RED,ASSIGN_BLOCK+14   ; (FAKING PAD AS CHANNEL NUMBER)
               MOVE    PITCH_RED,ASSIGN_BLOCK+16 ; (FAKING PITCH AS KEYNUM)

               TST.L   P_KEY_MAP            ;ARE ANY PITCH KEYS CURRENTLY HELD DOWN?
               BNE.S   POLY_PITCH_PLAY      ;    IF SO, GO PLAY THIS PAD AT THOSE PITCHES
               TST     CUR_TRIG_FLAG        ;ARE THE PAD KEYS MUTED?
               BEQ     POLY_NTE_ON          ;    IF SO, DON'T PLAY THIS - POISED FOR PITCH KEYON

               TST.B   ERASING              ;IF ERASING
               BNE.S   BUDDY_2              ;    WE'RE SUCKING OUT SOUNDS; NOT PLAYING THEM!

               BSR     VOICE_ASSIGN         ;START ONE VOICE IN RESPONSE TO THIS PAD KEY
               BSR     POLY_ON_SEQ_PAD      ;SEE IF SEQUENCER RUNNING; IF SO, STUFF THIS EVENT OFF TO IT
BUDDY_2
               BSR     QUICK_LOG_IN         ; LOG IN TO HOLDING_BUFF
               BRA     POLY_NTE_ON          ; RUNNING STATUS ANOTHER
;
;AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
               SKIP
;VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
;
POLY_PITCH_PLAY        ;NEW PAD KEY ON, AND PITCH KEYS ON - PLAY THIS PAD AT ALL PITCHES
; ASSIGN_BLOCK IS FULLY LOADED AT THIS POINT - JUST OVERWRITE THE PITCH, AND START.
               TST.B   ERASING              ;IF ERASING
               BNE.S   BUDDY_1              ;    WE'RE SUCKING OUT SOUNDS; NOT PLAYING THEM!

               MOVEQ   #31,D0               ;POSSIBLE PITCH KEYS ARE 00->31
               MOVEQ   #7,D2                ; SINCE WE HAVE ONLY 8 VOICES, DON'T DO MORE THAN NEEDED
               MOVE.L  P_KEY_MAP,D1         ;  LOAD UP P_KEY MAP
TURN_ON_MANY
               BTST    D0,D1                ;ES DIS P_KEY ON?
               BEQ.S   ALEX_3               ;    IF NOT, TRY NEXT ONE

               MOVE    D0,ASSIGN_BLOCK+6    ;         ELSE, TURN ON THIS PITCH
               MOVE    D0,ASSIGN_BLOCK+16
               BSR     VOICE_ASSIGN         ;TURN ON VOICE
               BSR     POLY_ON_SEQ_PAD      ;SEE IF SEQUENCER RUNNING; IF SO, STUFF THIS EVENT OFF TO IT

               DBRA    D2,ALEX_3            ;IF LESS THAN 8 VOICES STARTED BY US, CONTINUE
               BRA     POLY_NTE_ON          ;    ELSE, DONE - GO LOOK FOR ANOTHER KEY
ALEX_3
               DBRA    D0,TURN_ON_MANY      ;GO FOR ANOTHER
BUDDY_1
               BSR     QUICK_LOG_IN         ; LOG IN TO HOLDING_BUFF
               BRA     POLY_NTE_ON          ;    WHEN DONE, LOOK FOR ANOTHER KEY
;
;AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
               SKIP
;VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
;
P_KEY_ON       ;AT THIS POINT, HAVE KEYNUM - 23H IN D0.  THE REST IS UP TO US.....
               SUB     #1EH,D0              ;KNOCK DOWN FURTHER SO THAT LOWEST P-KEY = 00.
               BCS     EAT_VELOCITY         ; IF KEY IN LOMBO BELOW THIS AND ABOVE PADS, FUCK IT
               CMP     #20H,D0              ;CHECK UPPER LIMIT (ALLOW 32 PITCHES)
               BCC     EAT_VELOCITY
               MOVE    D0,LAST_MIDI_KEYNUM  ; IF LEGIT, SAVE

               MOVE.L  P_KEY_MAP,D1         ;SWITCH THIS KEY ON, WITH FULL KNOWLEDGE THAT THIS MAY
               BSET    D0,D1                ; MAY REALLY BE A NOTE OFF (BUT IF NOT, WE SAVED SOME
               MOVE.L  D1,P_KEY_MAP         ; PRECIOUS EXECUTION TIME).

               MOVE    LAST_MIDI_KEYNUM,M_COM_PIT     ;WANT TO UPDATE THIS AS NEW PITCH TO BE SAVED
               ST      M_PIT_ACT            ; (FLAG CHANGE CURRENT)
               BSR     MIDI_PERF_BIG_EDITS  ;(NOTE WE DO STUFF IN THE TIME 'TWEEN KEYNUM AND VELOCITY)

               BSR     GET_BYTE             ;GET VELOCITY BYTE
               TST     D0                   ; IF = 0, A NOTE OFF - DIFFERENT PLANS
               BEQ.S   CHROME_4

               CMP     #40H,D0              ;IF ABOVE MEDIAN VELOCITY
               BCC.S   NON_OCTA_2           ;    THEN PASS
               LSL     #1,D0                ;         ELSE, DESENSITIZE LOWER REGION FOR OCTAPADS
               SUB     #40H,D0              ;DO THIS BY * 2 - 40H.  THIS MEANS A VALUE OF 20H = OUR
               BEQ.S   NO_ZERO_2            ; LOWEST VELOCITY, AND FOLLOW THAT SLOPE UP TO THE MEDIAN.
               BCC.S   NON_OCTA_2
NO_ZERO_2
               MOVEQ   #1,D0
NON_OCTA_2
               TST     MIDI_DEFAULT_VEL     ; ARE WE SUPPOSED TO SUBSTITUTE WITH A DEFAULT?
               BEQ.S   CHROME_4             ;    IF NOT, KEEP WHAT WE GOT
               MOVE    MIDI_DEFAULT_VEL,D0  ;         ELSE, SUBSTITUTE
CHROME_4
               MOVE.B  D0,MIDI_DATA_2       ; (SAVE FOR POSSIBLE ECHO)
               BEQ     P_KEY_OFF_OFF        ; IF ZERO, REALLY A NOTE OFF - HANDLE

               ADD     #3,D0                ;OFFSET MIDI VELOCITY FOR ROUNDING ERRORS BELOW
               BTST    #7,D0                ; ALSO MAKE SUREIN DOING THIS THAT VEL <> 0 AFTER ROTATING
               BEQ.S   SNEEZE_2
               MOVEQ   #7FH,D0
SNEEZE_2
               LSR     #2,D0                ;    IF LEGIT, SCALE DOWN TO 5 BITS
               MOVE    D0,LAST_MIDI_VELOCITY     ;AND SAVE.

               MOVE    MIDI_KEY_MAP,D1      ;ANY PAD KEYS ON?
               BEQ.S   FULLMOON_1           ;    IF NOT, WE BE DONE FOR NOW

               TST.B   ERASING              ;IF ERASING
               BNE.S   FULLMOON_1           ;    WE'RE SUCKING OUT SOUNDS; NOT PLAYING THEM!

               MOVE    LAST_MIDI_KEYNUM,D0  ;LOAD THIS PITCH
               MOVEQ   #15,D2               ;RETRIGGER EACH PAD KEY ON TO THIS PITCH
               MOVEQ   #7,D3                ; (BEING AN 8-VOICE INSTRUMENT, DON'T OVERDO IT...)
P_KEY_ON_LOOP
               BTST    D2,D1                ;IS THIS PAD KEY ON?
               BEQ.S   ALEX_4               ;    IF NOT, TRY ANOTHER

               BSR     BUILD_A_BLOCK        ;BUILD UP AN ASSIGN_BLOCK BASED ON THIS SOUND
               MOVE    D0,ASSIGN_BLOCK+6    ; LOAD THIS PITCH AS PITCH TO PLAY AT
               MOVE    D0,ASSIGN_BLOCK+16
               BSR     VOICE_ASSIGN         ;  START A VOICE
               BSR     POLY_ON_SEQ_PAD      ;SEE IF SEQUENCER RUNNING; IF SO, STUFF THIS EVENT OFF TO IT

               DBRA    D3,ALEX_4            ;ONLY BOTHER STARTING 8 VOICES TOTAL
               BRA     FULLMOON_1           ;    IF HAVE FILLED OUR QUOTA, DONE.
ALEX_4
               DBRA    D2,P_KEY_ON_LOOP     ;CHECK ALL 16 PAD KEYS
FULLMOON_1
               BSR     QUICK_LOG_IN         ; LOG IN TO HOLDING_BUFF
               BRA     POLY_NTE_ON          ;GO HANDLE NEXT KEY
;
;AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
               SKIP
;VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
;
BUILD_A_BLOCK  ;ENTER w/D2 = PADNUM - ASSUME WE CAN'T TRASH D0-D3.  BUILD AN ASSIGN_BLOCK
;BASED AROUND THIS PAD'S PARAMTERS.
               MOVE    D2,D7                ;MAKE A COPY
               MOVE    CUR_L_MAP,D4         ;POINT TO CORRECT MAP
               BCLR    #3,D7                ; BIT 3 SET = RIGHT MAP
               BEQ.S   LE_ORME_1
               MOVE    CUR_R_MAP,D4
LE_ORME_1
               LSL     #3,D4                ;MAP * 8
               ADD     D7,D4                ;        + PADNUM = INDEX INTO CORRECT PAD ARRAY
               CLR     D7

               MOVE    #4,ASSIGN_BLOCK      ;BUILD ASSIGN BLOCK.  SIGNAL AS FROM MIDI

               LEA     PAD_SOUNDS,A0
               MOVE.B  0(A0,D4),D7          ;GET SOUND NOMBRE
               CLR     D5                   ; NEED TO FIGURE IF ALT PARAMS SET OR NOT
               LSR     #1,D7                ;  ROTATE OFF ALT PARAM BIT
               BCC     LE_ORME_2
               MOVEQ   #-1,D5
LE_ORME_2
               MOVE    D7,ASSIGN_BLOCK+2    ;SOUNDNUM
               MOVE    D5,ASSIGN_BLOCK+4    ;ALT PARAM STATUS

               LEA     PAD_PITCHES,A0       ;PITCH
               MOVE.B  0(A0,D4),D7
               MOVE    D7,ASSIGN_BLOCK+6
               MOVE    D7,ASSIGN_BLOCK+16   ;PITCH IS FAKE 'KEYNUM'

               LEA     PAD_LEVELS,A0        ;LEVEL
               MOVE.B  0(A0,D4),D7
               MOVE    D7,ASSIGN_BLOCK+8

               LEA     PAD_PANS,A0          ;PAN
               MOVE.B  0(A0,D4),D7
               MOVE    D7,ASSIGN_BLOCK+10

               MOVE    LAST_MIDI_VELOCITY,ASSIGN_BLOCK+12  ;VELOCITY
               MOVE    D2,ASSIGN_BLOCK+14   ;PADNUM SERVES AS 'CHANNEL'

               RTS
;
;AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
                SKIP
;VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
;
EAT_VELOCITY   ; HAVING DECIDED THAT KEYNUM WAS BOGUAD, EAT VELOCITY & TRY AGAIN
               BSR     GET_BYTE
               MOVE.B  D0,MIDI_DATA_2       ; (SAVE FOR POSSIBLE ECHO)
               BEQ.S   Y_COOL_1             ;IF A NOTE OFF, LOG OUT OF HOLDING_BUFF
               BSR     QUICK_LOG_IN         ;    ELSE, LOG IN
               BRA     POLY_NTE_ON
Y_COOL_1
               BSR     QUICK_LOG_OUT
               BRA     POLY_NTE_ON



ALT_P_KEY      ;THIS KEY GOING ON SIGNIFIES A TOGGLING OF THE ALT_PARAM STATUS.
               BSR     GET_BYTE             ;GET VELOCITY OUT OF THE WAY
               MOVE.B  D0,MIDI_DATA_2       ; (SAVE FOR POSSIBLE ECHO)
;              TST.B   D0
               BEQ.S   LE_ORME_3            ;    IF REALLY A NOTE OFF, IGNORE

                ABS_LONG
               JSR     TOGGLE_ALT_PARAMS
                ABS_SHORT
LE_ORME_3
               BRA     POLY_NTE_ON
;
;AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
;AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
;AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
               SKIP
;VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
;VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
;VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
;
;             CONTROLLERS.
;
;             THERE ARE UP TO 128 CONTROLLERS.  WE ONLY RECOGNIZE A HANDFUL OF THEM:
;
;                      01 = MOD WHEEL  (POSSIBLY ROUTED TO PITCH, PAN, OR VOLUME)
;                      02 = BREATH CONTROLLER (TREATED JUST LIKE PRESSURE)
;                      03 = OLD DX-7 PRESSURE (   "      "    "      "   )
;                      04 = FOOT CONTROLLER   (   "      "    "      "   )
;                      07 = MAIN VOLUME (POSSIBLY ROUTED TO OUR MAIN VOLUME,OR LEVEL)
;                      0A = PAN (YEP, TREATED AS OUR PAN)
;                      40 = HOLD PEDAL (POSSIBLY TREATED AS OUT ALT PARAM SWITCH FOR OUR LEFT KIT)
;
;             ROUTINGS OF A LOT OF THE ABOVE DEPENDS ON WHICH PROGRAM IS CURRENTLY ACTIVE.  WE
;              DON'T HAVE TO WORRY WHICH - CURRENT PARAMETERS AND ROUTINGS ARE ALREADY DOWNLOADED
;              INTO 'CUR_something'.
;
CNTROLLER
               BSR     ECHO_3               ;SEE IF WE HAVE TO ECHO THE LAST MESSAGE
CONTROLLER
               BSR     GET_BYTE             ;SEE WHO IS KNOCKING
               MOVE.B  D0,MIDI_DATA_1       ; (SAVE FOR POSSIBLE ECHO)
               CMP     #0BH,D0              ;ABOVE LEGIT CONTINUOUS CONTROLER RANGE?
               BCC.S   TRY_SWITCHES         ;    IF SO, SEE IF HOLD PEDAL

               LSL     #1,D0                ;INTO AN INDEX TO SEE HOW TO SERVICE IT
               MOVE    CONT_TBL(PC,D0),A0
               JMP     (A0)                 ; DEAL WITH IT...


CONT_TBL
               DC.W    DISABLED_CONT        ;00 = UNUSED
               DC.W    MOD_WHEEL            ;01 = MOD WHEEL
               DC.W    PRESSURE             ;02 = BREATH CONTROLLER
               DC.W    PRESSURE             ;03 = OLD DX-7 PRESSURE
               DC.W    PRESSURE             ;04 = FOOT CONTROLLER
               DC.W    DISABLED_CONT        ;05 = PORTAMENTO TIME (IGNORED)
               DC.W    DISABLED_CONT        ;06 = DATA ENTRY (IGNORED)
               DC.W    MAIN_VOLUME          ;07 = MAIN VOLUME
               DC.W    DISABLED_CONT        ;08 = EXPRESSION PEDAL (IGNORED)
               DC.W    DISABLED_CONT        ;09 = BALANCE (IGNORED)
               DC.W    DISABLED_CONT        ;0A = PAN


DISABLED_CONT  ; IF DON'T RECOGNIZE THIS CONTROLLER, EAT VALUE, AND TRY ANOTHER
               BSR     GET_BYTE
               MOVE.B  D0,MIDI_DATA_2       ; (SAVE FOR POSSIBLE ECHO)
               BRA     CNTROLLER
;
;AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
               SKIP
;VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
;
TRY_SWITCHES   ; SEE IF HOLD PEDAL.  IF NOT, FROGET.  ELSE, IF ENABLED, DOUBLE AS ALT_PARAM.
               CMP     #40H,D0              ;HOLD PEDAL?
               BNE.S   DISABLED_CONT        ;    IF NOT, FORGET
               TST     HOLD_TO_ALT_FLAG     ;ENABLED TO ACT AS ALT_PARAM?
               BEQ.S   DISABLED_CONT        ;    IF NOT, FORGET

               BSR     GET_BYTE             ;         ELSE, GET VALUE (IN D0.B)
               MOVE.B  D0,MIDI_DATA_2       ; (SAVE FOR POSSIBLE ECHO)
               BTST    #6,D0                ;IF 40H OR ABOVE
               BNE.S   HOLD_ON              ;    THEN PEDAL GOING ON
                                            ;         ELSE PEDAL GOING OFF
HOLD_OFF
               TST     ALT_PARAM_FLAG       ;IF ALREADY OFF
               BEQ     CNTROLLER            ;    THEN WE HAVE NOTHING TO DO
               BRA     TOGG_HOLD            ;         ELSE, TOGGLE STATUS
HOLD_ON
               TST     ALT_PARAM_FLAG       ;IF ALREADY ON
               BNE     CNTROLLER            ;    THEN NOTHING TO DO
                                            ;         ELSE, TOGGLE ALT_PARAM_FLAG
TOGG_HOLD
                ABS_LONG
               JSR     TOGGLE_ALT_PARAMS
                ABS_SHORT
               BRA     CNTROLLER            ; RUNNING STATUS TO NEXT CONTROLLER
;
;AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

;VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
;
MAIN_VOLUME    ; SEE IF TO BE IGNORED, TO REPLACE OUR OWN MAIN VOLUME, OR TO BE A 'LEVEL' EDIT.
               TST     M_VOL_ROUT           ;WELL - WHAT ARE WE?
               BMI     DISABLED_CONT        ;    IF DISABLED, FORGET
               BEQ.S   DO_MAIN_VOLUME       ;    IF TO REPLACE MAIN VOLUME, HANDLE
                                            ;         ELSE, TO REPLACE LEVEL
               BSR     GET_BYTE             ;GET VALUE
               MOVE.B  D0,MIDI_DATA_2       ; (SAVE FOR POSSIBLE ECHO)
               SUB     #40H,D0              ; BALANCE ABOUT 0 (ORIG. RANGE WAS 00->7F)
               ASR     #2,D0                ;  KNOCK DOWN TO 5 BITS (SIGN-EXTENDED)
               MOVE    D0,LEVEL_LEVEL_LEVEL ;   SAVE
               BSR     NEW_LEVEL_PERF       ;    SUM WITH OTHER LEVEL MODULATIONS, ACT UPON
               BRA     CNTROLLER            ;     WHEN DONE, LOOK FOR ANOTHER


DO_MAIN_VOLUME
               BSR     GET_BYTE             ;GET VALUE
               MOVE.B  D0,MIDI_DATA_2       ; (SAVE FOR POSSIBLE ECHO)
               EXT     D0
               MOVE    D0,CURRENT_VOLUME    ;SUB FOR CURRENT VOLUME

               BRA     CNTROLLER            ;LOOK FOR OTHERS OF OUR KIND.
;
;AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

;VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
;
PAN            ; GOT A PAN - SUM WITH OTHER PAN MODULATIONS, UPDATE ACTIVE MIDI 'PADS'
               BSR     GET_BYTE             ;GET PAN VALUE (IN D0.B)
               MOVE.B  D0,MIDI_DATA_2       ; (SAVE FOR POSSIBLE ECHO)

               CMP     #3,MIDI_MODE         ;IF MAPPED MODE
               BEQ     CNTROLLER            ;    THEN LAST_ WAS ALL WE REALLY WANTED

               SUB     40H,D0               ;BALANCE ABOUT 0 (3FH -> -40H)
               ASR     #2,D0                ; ROTATE DOWN TO 5 BITS (SIGN XTENDED)
               MOVE    D0,PAN_PAN_PAN       ;  SAVE
               BSR     NEW_PAN_PERF         ;   SUM, ACT UPON
               BRA     CNTROLLER            ;RUNNING STAT AONTHER CONTROLLER
;
;AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

;VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
;
;             MODUALTION WHEEL - CAN BE ROUTED TO PITCH, LEVEL, OR PAN ('NORMAL' OR 'INVERTED').
;              WE FIGURE WHERE AIMED, AND SEND IT OUT OT SUM WITH OTHERS OF ITS KIND.  ALSO
;              UPDATE PADKEYS HELD TO THIS NEW VALUE.
;
;             ROUTING VALUE LOOKS LIKE THIS:
;                      00 = PITCH (ADD)     01 = PITCH (INV)
;                      02 = PAN (ADD)       03 = PAN (INV)
;                      04 = LEVEL (ADD)     05 = LEVEL (ADD)
;                              FFFF = DISABLED
;
MOD_WHEEL
               BSR     GET_BYTE             ;GET VALUE (00->7F, IN D0.B)
               MOVE.B  D0,MIDI_DATA_2       ; (SAVE FOR POSSIBLE ECHO)

               MOVE    D0,LAST_MOD_WHL      ;SAVE LAST VALUE (POSSIBLY FOR AUTOREPEATING)

               CMP     #3,MIDI_MODE         ;IF MAPPED MODE
               BEQ     CNTROLLER            ;    THEN LAST_ WAS ALL WE REALLY WANTED

               SUB     #40H,D0              ;BALANCE ABOUT 0
               ASR     #2,D0                ;ROTATE INTO 5-BIT VALUE (SIGN KEPT)

               MOVE    CUR_MOD_ROUT,D1      ;SEE WHERE AIMED BY THE CURRENT PRESET
               BMI     CNTROLLER            ;    IF DISABLED, GO BACK AND LOOK FOR OTRA CONTROLLERS

               BCLR    #0,D1                ;SEE IF SUPPOSED TO BE INVERTED (AND TURN INTO WORD INDEX)
               BEQ.S   PINK_1
               NEG     D0
PINK_1
               MOVE    MOD_ROUT_TBL(PC,D1),A0    ;LOAD ADDRESS OF WHERE VALUE GOES
               MOVE    MOD_ACT_TBL(PC,D1),A1     ;LOAD ADDRESS OF UPDATE ROUTINE TO EXECUTE
               MOVE    D0,(A0)              ;SAVE VALUE
               JSR     (A1)                 ;SUM, UPDATE HELD PADKEYS

               BRA     CNTROLLER            ;WHEN DONE, RUNNIING STATUS A LOOK FOR OTHERS


MOD_ROUT_TBL
               DC.W    MOD_PIT
               DC.W    MOD_PAN
               DC.W    MOD_LEV


PRESS_ACT_TBL
MOD_ACT_TBL
               DC.W    NEW_PITCH_PERF
               DC.W    NEW_PAN_PERF
               DC.W    NEW_LEVEL_PERF
;
;AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
;AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
;AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
               SKIP
;VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
;VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
;VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
;
;             PRESSURE - CAN BE ROUTED TO PITCH, LEVEL, OR PAN ('NORMAL' OR 'INVERTED').
;              WE FIGURE WHERE AIMED, AND SEND IT OUT OT SUM WITH OTHERS OF ITS KIND.  ALSO
;              UPDATE PADKEYS HELD TO THIS NEW VALUE.
;
;             NOTE THAT SEVERAL CONTROLLERS PRETEND THEY'RE US.  WHEN DONE, HAVE TO CHECK WHO
;              CALLED US, AND RUNNING-STAT BACK TO HIM.
;
;             ROUTING VALUE LOOKS LIKE THIS:
;                      00 = PITCH (ADD)     01 = PITCH (INV)
;                      02 = PAN (ADD)       03 = PAN (INV)
;                      04 = LEVEL (ADD)     05 = LEVEL (ADD)
;                              FFFF = DISABLED
;
PRSSURE
               BSR     ECHO_2               ;CHECK POSSIBLE ECHO
PRESSURE
               BSR     GET_BYTE             ;GET VALUE (00->7F, IN D0.B)
               MOVE.B  D0,MIDI_DATA_2       ; (SAVE FOR POSSIBLE ECHO)

               MOVE    D0,LAST_PRESSURE     ;SAVE LAST VALUE (POSSIBLY FOR AUTOREPEATING)

               CMP     #3,MIDI_MODE         ;IF MAPPED MODE
               BEQ     EXIT_PRESSURE        ;    THEN LAST_ WAS ALL WE REALLY WANTED

               SUB     #40H,D0              ;BALANCE ABOUT 0
               ASR     #2,D0                ;ROTATE INTO 5-BIT VALUE (SIGN KEPT)

               MOVE    CUR_PRESSURE_ROUT,D1 ;SEE WHERE AIMED BY THE CURRENT PRESET
               BMI     EXIT_PRESSURE        ;    IF DISABLED, GO BACK AND LOOK FOR OTRA CONTROLLERS

               BCLR    #0,D1                ;SEE IF SUPPOSED TO BE INVERTED (AND TURN INTO WORD INDEX)
               BEQ.S   PINK_2
               NEG     D0
PINK_2
               MOVE    PRESS_ROUT_TBL(PC,D1),A0  ;LOAD ADDRESS OF WHERE VALUE GOES
               MOVE    PRESS_ACT_TBL(PC,D1),A1   ;LOAD ADDRESS OF UPDATE ROUTINE TO EXECUTE
               MOVE    D0,(A0)              ;SAVE VALUE
               JSR     (A1)                 ;SUM, UPDATE HELD PADKEYS

EXIT_PRESSURE
               MOVE.B  LAST_STAT_BYTE,D0    ;SEE WHO ACTIVE STATUS BYTE IS
               AND     #0F0H,D0             ; (CLEAR OFF CHANNEL, UPPER BYTE)
               CMP     #0D0H,D0             ;    IF INDEED PRESSURE
               BEQ     PRSSURE              ;         THEN CONTINUE THE LOOK FOR OURSELVES
               BRA     CNTROLLER            ;              ELSE, WAS A CONTROLLER IN DISGUISE...


PRESS_ROUT_TBL
               DC.W    PRESS_PIT
               DC.W    PRESS_PAN
               DC.W    PRESS_LEV
;
;AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
;AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
;AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
               SKIP
;VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
;VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
;VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
;
;             PITCH WHEEL - CAN BE ROUTED TO PITCH, LEVEL, OR PAN ('NORMAL' OR 'INVERTED').
;              WE FIGURE WHERE AIMED, AND SEND IT OUT OT SUM WITH OTHERS OF ITS KIND.  ALSO
;              UPDATE PADKEYS HELD TO THIS NEW VALUE.
;
;             ROUTING VALUE LOOKS LIKE THIS:
;                      00 = PITCH (ADD)     01 = PITCH (INV)
;                      02 = PAN (ADD)       03 = PAN (INV)
;                      04 = LEVEL (ADD)     05 = LEVEL (ADD)
;                              FFFF = DISABLED
;
PTCH_WHEEL
               BSR     ECHO_3               ;POSSIBLE ECHO
PITCH_WHEEL
               BSR     GET_BYTE             ;EAT LSB OF PITCH BEND - TOO FINE A RESOLUTION FOR US
               MOVE.B  D0,MIDI_DATA_1       ; (SAVE FOR POSSIBLE ECHO)

               BSR     GET_BYTE             ;GET VALUE (00->7F, IN D0.B)
               MOVE.B  D0,MIDI_DATA_2       ; (SAVE FOR POSSIBLE ECHO)
               SUB     #40H,D0              ;BALANCE ABOUT 0
               ASR     #2,D0                ;ROTATE INTO 5-BIT VALUE (SIGN KEPT)

               MOVE    CUR_PWHL_ROUT,D1     ;SEE WHERE AIMED BY THE CURRENT PRESET
               BMI     PTCH_WHEEL           ;    IF DISABLED, GO BACK AND LOOK FOR OTRA CONTROLLERS

               BCLR    #0,D1                ;SEE IF SUPPOSED TO BE INVERTED (AND TURN INTO WORD INDEX)
               BEQ.S   PINK_3
               NEG     D0
PINK_3
               MOVE    PWHL_ROUT_TBL(PC,D1),A0   ;LOAD ADDRESS OF WHERE VALUE GOES
               MOVE    PWHL_ACT_TBL(PC,D1),A1    ;LOAD ADDRESS OF UPDATE ROUTINE TO EXECUTE
               MOVE    D0,(A0)              ;SAVE VALUE
               JSR     (A1)                 ;SUM, UPDATE HELD PADKEYS

               BRA     PTCH_WHEEL           ;WHEN DONE, RUNNING STATUS A LOOK FOR OTHERS


PWHL_ROUT_TBL
               DC.W    PWHL_PIT
               DC.W    PWHL_PAN
               DC.W    PWHL_LEV

PWHL_ACT_TBL
               DC.W    NEW_PITCH_PERF
               DC.W    NEW_PAN_PERF
               DC.W    NEW_LEVEL_PERF
;
;AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
               SKIP
;VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
;VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
;VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
;
;             MIDI PROGRAM CHANGES.  CHANGES OUR CURRENT PERFORMANCE MAPPING IN OMNI/POLY MODE.
;              THIS ENTAILS WHICH KITS/BANKS ARE ON THE KEYBOARD, WHETHER OR NOT PADKEYS ARE
;              MUTED, AND HOW THE MIDI CONTROLLERS ARE ROUTED TO PITCH/PAN/LEVEL.
;
;             CHANGE CURRENT PROGRAM (1->16, OR 00->0F, IF YOU PLEASE), UPDATE 'CURRENT' KITS,
;              ROUTINGS, ET AL, AND CLEAR OUT CURRENT DRONING NOTES AND PERFORAMNCE PARAMETERS.
;
PRGRAM
               BSR     ECHO_2
PROGRAM
               BSR     GET_BYTE             ;GET PROGRAM NOMBRE
               MOVE.B  D0,MIDI_DATA_2       ; (SAVE FOR POSSIBLE ECHO)
               CMP     #10H,D0              ;    IF OVER 16
               BCC     PRGRAM               ;         THEN IGNORE (BUT RUNNING STATUS ONWARD, ANYWAY)

               MOVE    D0,CUR_MIDI_PROG     ;              ELSE, MAKE CURRENT PROGRAM
                ABS_LONG
               JSR     UPDATE_CUR_STUFF     ;              AND UPDATE STUFF
                ABS_SHORT

               MOVE    CUR_R_MAP,D0         ;INSTALL BOTH KITS ONTO LIVE PAD ARRAYS -
                ABS_LONG
               JSR     INSTALL_KIT
                ABS_SHORT
               MOVE    CUR_L_MAP,D0         ;KIT_INDEX FOLLOWS "LEFT" MAP KIT NUMBER,
                ABS_LONG
               JSR     INSTALL_KIT          ;DO LEFT MAP KIT-INSTALL AFTER RIGHT MAP KIT-INSTALL.
                ABS_SHORT
               CMP.L   #MIDI_KIT_ASSIGN_SUB,CUR_SUB_BLOCK  ;LOOKING AT MIDI PROGRAM INFO IN LC?
               BNE     PRGRAM                              ;BRANCH IF NOT,
               ST      SUBFUN_INSTALL                      ;ELSE, UPDATE LCD TO REFLECT PGM CHANGE.
               BRA     PRGRAM               ; (RUNNING STAT ANOTHER)
;
;AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
;AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
;AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
               TITLE   "POLY/OMNI MODE SUBROUTINES"
               SKIP
;VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
;VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
;VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
;
;             SUBROUTINES FOR TAKING NEW CHANGES IN PERFORMANCE PARAMETERS (PITCH/PAN/LEVEL),
;              SUMMING ALL THE SOURCES TOGETHER, AND UPDATING THE KIT/BANK ARRAYS FOR HELD PADKEYS.
;
;             VALUE CAME FROM SOMEWHERE.  SUM ALL TOGETHER, GO OFF AND UPDATE BANK/KIT ARRAYS.  NOTE
;              THAT WE FUCK WITH REGISTERS D0-D3/A0.  DON'T PROTECT 'CAUSE SEVERAL ENTRY POINTS,
;              PLUS DON'T ENTER NEEDING ANYTHING.
;
NEW_PITCH_PERF
               MOVE    MOD_PIT,D0           ;TAKE CURRENT PITCH FROM THE MOD WHEEL
               ADD     PWHL_PIT,D0          ;    ADD THAT FROM THE PITCH WHEEL
               ADD     PRESS_PIT,D0         ;         ADD THAT FROM PRESSURE
               ADD     #10H,D0              ;CAME TO US 5-BIT BALANCED ABOUT 00 - RAISE UP

               BMI.S   FLOYD_1              ;    IF NEG, CLIP AT 00
               CMPI    #1FH,D0              ;CLIP TOP AT 1FH
               BCS.S   FLOYD_2
               MOVEQ   #1FH,D0
               BRA.S   FLOYD_2
FLOYD_1
               CLR     D0
FLOYD_2
               MOVE    D0,M_COM_PIT         ;SAVE AS COMMUNAL PITCH
               ST      M_PIT_ACT            ;FLAG AS CHANGE ACTIVE
               BRA     MIDI_PERF_BIG_EDITS  ;    UPDATE BANK/KIT PADARRAYS (RET FROM THERE)



NEW_PAN_PERF
               MOVE    MOD_PAN,D0           ;TAKE CURRENT PAN FROM THE MOD WHEEL
               ADD     PWHL_PAN,D0          ;    ADD THAT FROM THE PITCH WHEEL
               ADD     PRESS_PAN,D0         ;         ADD THAT FROM PRESSURE
               ADD     PAN_PAN_PAN,D0       ;              ADD THAT FROM THE PAN CONTROLLER
               ADD     #10H,D0              ;CAME TO US 5-BIT BALANCED ABOUT 00 - RAISE UP

               BMI.S   FLOYD_3              ;    IF NEG, CLIP AT 00
               CMPI    #1FH,D0              ;CLIP TOP AT 1FH
               BCS.S   FLOYD_4
               MOVEQ   #1FH,D0
               BRA.S   FLOYD_4
FLOYD_3
               CLR     D0
FLOYD_4
               MOVE    D0,M_COM_PAN         ;SAVE AS COMMUNAL PAN
               ST      M_PAN_ACT            ;FLAG AS CHANGE ACTIVE
               BRA.S   MIDI_PERF_BIG_EDITS  ;    UPDATE BANK/KIT PADARRAYS (RET FROM THERE)



NEW_LEVEL_PERF
               MOVE    MOD_LEV,D0           ;TAKE CURRENT LEVEL FROM THE MOD WHEEL
               ADD     PWHL_LEV,D0          ;    ADD THAT FROM THE PITCH WHEEL
               ADD     PRESS_LEV,D0         ;         ADD THAT FROM PRESSURE
               ADD     LEVEL_LEVEL_LEVEL,D0 ;              ADD THAT FROM THE MAIN VOLUME CONTROLLER
               ADD     #10H,D0              ;CAME TO US 5-BIT BALANCED ABOUT 00 - RAISE UP

               BMI.S   FLOYD_5              ;    IF NEG, CLIP AT 00
               CMPI    #1FH,D0              ;CLIP TOP AT 1FH
               BCS.S   FLOYD_6
               MOVEQ   #1FH,D0
               BRA.S   FLOYD_6
FLOYD_5
               CLR     D0
FLOYD_6
               MOVE    D0,M_COM_LEV         ;SAVE AS COMMUNAL PITCH
               ST      M_LEV_ACT            ;FLAG AS CHANGE ACTIVE
;881025               BRA.S   MIDI_PERF_BIG_EDITS  ;    UPDATE BANK/KIT PADARRAYS (RET FROM THERE)
               NOP                          ;PLACE-HOLDER FOR ABOVE INSTRUCTION,
                                            ;WHICH ASSEMBLED AS 'NOP' ON HP64000.
                                            ;STRICTLY FOR INITIAL LINK-MAP MATCH-UP,
                                            ;SHOULD BE DELETED AFTERWARDS .....

                                            ; IE, FALL THRU INTO MIDI_PERF_BIG_EDITS
;
;AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
               SKIP
;VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
;
; UPDATE PERFORMANCE PARAMETERS.  CALLED EITHER BY A CHANGE IN THE PERFORMANCE
;  PARAMETERS THEMSELVES, BY A KEY ON, OR A KEY OFF.
;
; IF CALLED BY A CONTROLLER, SEES IF ANY PADKEYS HELD, AND IF SO, UPDATES THOSE PADS.
;  NOTE THAT THE POLY MODE PITCH KEYS MASQUERADE AS CONTROLLERS.
;
; IF CALLED BY A KEY ON, DOWNLOAD ANY ACTIVE PERFORMANCE PARAMETER CHANGES TO THIS
;  PADKEY (A FAKE MIDI_KEY_MAP IS LOADED THAT REFLECTS ONLY THE NEW KEY ON).  DONE
;  BEFORE ACTUALLY PLAYING THIS PAD (DONE, ODDLY ENOUGH, OUT OF THE ARRAYS WE EDIT HERE).
;
; IF CALLED BY A KEY OFF, CALLED BEFORE MIDI_KEY_MAP ACTUALLY UPDATED, TO MAKE SURE
;  ALL KEYS HELD WHILE A PERF CHANGE OCCURED GET THIS VALUE.  THIS STEP MAY BE NOT
;  NEEDED, AND UNPLUGGED LATER (I GUESS CONTROLLER CHANGES THEMSELVES WIIL KEEP THE
;  WORLD UP TO DATE).
;
; CAN BE ENTERED AT 'UPDATE_A_PAD' TO UPDATE JUST ONE SOUND IN A BANK (NO KIT),
;  REGARDLESS OF CURRENT KITS (THAT'S RIGHT - MAPPED/MULTI MODE).  TO DO THIS, MUST
;  HAVE A0=PAD INDEX (SOUNDNUM + 32), D0=0 (SO AS TO EXIT RIGHT AWAY), AND D2=-1 (NOT KIT) -
;
; WE MESS WITH REGGIES D0-D3/A0.
;
MIDI_PERF_BIG_EDITS    ;ENTER HERE TO WORK ON ALL HELD PADKEYS
               MOVE    MIDI_KEY_MAP,FAKE_KEY_MAP

MIDI_PERF_EDITS        ;ENTER HERE TO WORK ON AN ALTERNATE SELECTION (TYPICALLY, ONLY 1)
               MOVEQ   #15,D0               ;UP TO 16 PAD KEYS TO SEARCH
               MOVE    FAKE_KEY_MAP,D1      ;LOAD UP BIT MAP OF PADS TO UPDATE
               BEQ     EXIT_PERF_EDIT       ;    IF NONE ON, QUIT NOW
PERF_ED_LOOP
               BTST    D0,D1                ;WELL, NOW - IS THIS PADKEY ON?
               BEQ     LOOP_ED_PERF         ;    IF NOT, TRY ANOTHER

               MOVE    CUR_L_MAP,D2         ;HMMM... WHICH KIT IS THIS IN?
               MOVE    D0,D3
               BCLR    #3,D3                ;(PADNUMS 8->F ARE IN RIGHT MAP)
               BEQ.S   P_F_0
               MOVE    CUR_R_MAP,D2
P_F_0
               LSL     #3,D2                ;KIT * 8
               MOVE    D2,A0                ;GETS US TO SELECTED KIT ARRAYS -
               ADD     D3,A0                ;PAD NUMBER GETS US TO THE CELLS WE WANT.
               TST.B   BUILD_KIT_FLAG       ;ARE WE IN KIT-BUILD SCREEN?
               BEQ.S   ZEUT_10              ;BRANCH IF NOT, ALL IS COOLNESS -
               ST      SUBFUN_INSTALL       ;YES - GONNA EDIT DISPLAYED KIT, SO REQUEST REDISPLAY.
               ADD     #256,A0              ;OFFSET ARRAY INDEX TO HIT PRESET, NOT LIVE PAD ARRAYS.
ZEUT_10

UPDATE_A_PAD
               TST     M_PIT_ACT            ;PITCH CHANGE PENDING?
               BEQ.S   P_F_1
               MOVE.B  M_COM_PIT+1,PAD_PITCHES(A0)    ;IF YES, WRITE NEW PITCH
P_F_1
               TST     M_PAN_ACT            ;PAN CHANGE PENDING?
               BEQ.S   P_F_2
               MOVE.B  M_COM_PAN+1,PAD_PANS(A0)       ;IF YES, WRITE NEW PAN VALUE
P_F_2
               TST     M_LEV_ACT            ;LEVEL CHANGE PENDING?
               BEQ.S   P_F_3
               MOVE.B  M_COM_LEV+1,PAD_LEVELS(A0)     ;IF YES, WRITE NEW LEVEL
P_F_3
;
;23NOV; IF WE COME THROUGH HERE, WE'RE NOT IN KIT-BUILD MODE, OR AT LEAST
;23NOV; WE'RE NOT DEALING WITH A CELL IN THE CURRENT EDIT-TARGET KIT -
;23NOV; HENCE, IF IN USER KIT SPACE, BEGONE - WE'VE ALREADY EDITED THE LIVE
;23NOV; PAD ARRAY, AND DON'T WANT TO TOUCH THE USER KIT PRESET ARRAY.
;23NOV; IF WORKING FROM FIXED BANK SPACE, WE ALWAYS EDIT BOTH LIVE PAD AND
;23NOV; BANK PRESET ARRAYS - THEY HAVE NO SEPARATE EXISTENCE, KIT-BUILD DOES
;23NOV; NOT APPLY TO THEM.
;23NOV;
;23NOV               BTST    #5,D2                ;IF PAD_ARRAY INDEX < 32, PLAYING FROM USER KIT -
;23NOV               BEQ.S   LOOP_ED_PERF         ;AS PER ABOVE SPIEL, LEAVE KIT PRESET ARRAYS ALONE.
;23NOV                                            ;FOR FIXED BANK, FALL THRU TO EDIT BANK PRESET ARRAYS.
;23NOV
;23NOVSLEEP_1
;23NOV               TST     M_PIT_ACT            ;PITCH CHANGE PENDING?
;23NOV               BEQ.S   P_F_01
;23NOV               MOVE.B  M_COM_PIT+1,KIT_PITCHES(A0)    ;IF YES, WRITE NEW PITCH
;23NOVP_F_01
;23NOV               TST     M_PAN_ACT            ;PAN CHANGE PENDING?
;23NOV               BEQ.S   P_F_02
;23NOV               MOVE.B  M_COM_PAN+1,KIT_PANS(A0)       ;IF YES, WRITE NEW PAN VALUE
;23NOVP_F_02
;23NOV               TST     M_LEV_ACT            ;LEVEL CHANGE PENDING?
;23NOV               BEQ.S   P_F_03
;23NOV               MOVE.B  M_COM_LEV+1,KIT_LEVELS(A0)     ;IF YES, WRITE NEW LEVEL
;23NOVP_F_03

LOOP_ED_PERF
               DBRA    D0,PERF_ED_LOOP      ;SHAKE DOWN ALL 16 PADKEYS
;
               TST     M_PAN_ACT            ;WAS A PAN EDIT PENDING?
               BEQ.S   EXIT_PERF_EDIT       ;BRANCH IF NO, DON'T CARE WHETHER WE'RE IN PAN SCREEN.
               CMP.L   #INITIAL_PAN_SUB,CUR_SUB_BLOCK ;ELSE REDISPLAY IF WE'RE IN PAN SCREEN -
               BNE.S   EXIT_PERF_EDIT                 ;THIS IS THE ONLY SCREEN BESIDES KIT-BUILD
               ST      SUBFUN_INSTALL                 ;WHERE LIVE EDITS ARE VISIBLE.

EXIT_PERF_EDIT
               RTS
;
;AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
               SKIP
;VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
;
;             SUBBIES TO NEUTRALIZE MIDI.  KILL_ACTIVE_PERF KILLS OFF THE WHOLE SHEBANG - ANY MIDI
;              NOTES DRONING, THE KEY MAPS, THE MODULATION VALUES, AND THE ACTIVE EDITS.  JUMP IN
;              LOWER ('DEACTIVATE_PERF') JUST TO KILL PENDING CHANGES.
;
;             SHOULD BE CALLED IN ENTIRITY WHENEVER PART OF MIDI SET-UP CHANGES (CHANGE MAY RESULT
;              IN US MISSING LATER ACTION - LIKE A NOTE OFF, ETC.).
;
;             EXPECTS NOTHING ON WAY IN; TOUCHES NO REGISTERS.
;
KILL_ACTIVE_PERF

               BSR     LIVE_VOICES_OFF      ;ZORCH VOICES OFF

               CLR.L   P_KEY_MAP            ;ZORCH ALL KEYS AS OFF.
               CLR     MIDI_KEY_MAP
               CLR     FAKE_KEY_MAP

               CLR     MOD_PIT              ;CLEAR MOST-RECENTLY-RECEIVED MODUALTIONS
               CLR     MOD_PAN
               CLR     MOD_LEV
               CLR     PWHL_PIT
               CLR     PWHL_PAN
               CLR     PWHL_LEV
               CLR     PRESS_PIT
               CLR     PRESS_PAN
               CLR     PRESS_LEV

               CLR     M_COM_PIT            ;CLEAR SUMMED MODULATIONS
               CLR     M_COM_PAN
               CLR     M_COM_LEV

;              CLR     PAN_PAN_PAN          ;XTRA CONTROLLERS TO CLEAR
               CLR     LEVEL_LEVEL_LEVEL    ; (MAYBE KEEP PAN ALIVE, SINCE ALWAYS ENABLED)
DEACTIVATE_PERF
               CLR     M_PIT_ACT            ;KILL 'EDIT PENDING' FLAGS
               CLR     M_PAN_ACT
               CLR     M_LEV_ACT

               RTS
;
;AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
;AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
;AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
               SKIP
;VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
;
;             TABLE TO CONVERT FROM INCOMING KEYNUMS TO INTO 'PAD' NUMBERS.
;
KEY_CONV_TBL
               DC.W    0               ;MIDI KEY 23H
               DC.W    0               ;  "   "  24H
               DC.W    7               ;  "   "  25H
               DC.W    1               ;  "   "  26H
               DC.W    7               ;  "   "  27H
               DC.W    1               ;  "   "  28H
               DC.W    2               ;  "   "  29H
               DC.W    5               ;  "   "  2AH
               DC.W    2               ;  "   "  2BH
               DC.W    5               ;  "   "  2CH
               DC.W    3               ;  "   "  2DH
               DC.W    4               ;  "   "  2EH  LEFT KIT
               DC.W    3               ;  "   "  2FH  \
               DC.W    8               ;  "   "  30H    \
               DC.W    6               ;  "   "  31H      \
               DC.W    9               ;  "   "  32H        \
               DC.W    6               ;  "   "  33H          \
               DC.W    10              ;  "   "  34H  RIGHT KIT
               DC.W    11              ;  "   "  35H
               DC.W    11              ;  "   "  36H  (A NEGATIVE VALUE MEANS NOT ASSIGNED)
               DC.W    12              ;  "   "  37H
               DC.W    12              ;  "   "  38H
               DC.W    13              ;  "   "  39H
               DC.W    13              ;  "   "  3AH
               DC.W    14              ;  "   "  3BH
               DC.W    15              ;  "   "  3CH
;
;AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
               TITLE   'MULTI MODE ROUTINES'
               SKIP
;VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
;VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
;VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
;
;             NOTE OFF - GATHER IN, FORM INTO V_IDENTITY, CALL VOICE_GAT_OFF.
;
;             ENTER w/ D0.B = NEW STAT BYTE.
;
RUN_MULTI_OFF
               BSR     ECHO_3               ;POSSIBLE ECHO
MULTI_NOTE_OFF
;
               MOVE.B  LAST_STAT_BYTE,D0    ;RELOAD LAST STAT BYTE (IN CASE OF RUNNING STATUS)
                                  ; note - this line added 901024 - actually it
                                  ; was copied from MULTI_NOTE_ON (below) so
                                  ; that this part of MULTI_NOTE_OFF is now
                                  ; just like corresponding part of that one.
                                  ; this was an attempt at a fix for a bug
                                  ; discovered by Peter Rudolfi, which was
                                  ; determined to be a case of failure to
                                  ; correctly track running status of 8x kk vv
                                  ; note-off messages in mapped mode,
                                  ; resulting in stuck notes.
                                  ; it's clear from inspection that ECHO_3,
                                  ; which calls XMIT_2_PA/B, results in the
                                  ; value in d0 being randomly altered
                                  ; (actually it winds up with the most recent
                                  ; velocity byte), so that the value of
                                  ; LAST_MIDI_CHANNEL which gets pulled up for
                                  ; any subsequent note-off message on an 8x
                                  ; running status will probably be incorrect,
                                  ; and the note-off handler will be aimed at
                                  ; the wrong map table.
                                  ; did it work?  we'll try it and see ....
                                  ; and fuck you chris and your bogus running
                                  ; status midi receive handler (oops, sorry).
;
               ANDI    #0FH,D0              ;MASK TO CHANNEL NOMBRE.
               LSL     #2,D0                ; PRE-ROTATE FOR A LONG_WORD TABLE OFFSET
               MOVE    D0,LAST_MIDI_CHANNEL

               BSR     GET_BYTE             ;GET KEYNUM
               MOVE.B  D0,MIDI_DATA_1       ; (SAVE FOR POSSIBLE ECHO)
               SUBI    #15H,D0              ;KNOCK DOWN (CONVERING 88-KEY RANGE)
               BCS     EAT_MULT_OFF_VEL     ;    IF BELOW LEGAL RANGE, GIT
               CMPI    #87,D0               ;CHECK TOP OF RANGE
               BCC     EAT_MULT_OFF_VEL     ;    IF ABOVE LEGAL RANGE, GIT
               LSL     #2,D0                ;PARTIALLY PRE-ROTATE INTO V_IDENTITY POSTION
               MOVE    D0,LAST_MIDI_KEYNUM  ; (A NOTE ON w/ VEL=0 COMES THIS WAY)

; HAVE ENOUGH TO LOOK UP THIS EVENT IN THE PROPER KEYMAP ARRAY

               MOVE    LAST_MIDI_CHANNEL,D1 ;GRAB THAT CHANNEL
               MOVE.L  #MAP_ARRAY_TBL,A3
               MOVE.L  0(A3,D1),A3    ;SAVE PARAMS FOR LOWER KEYBOARD
               MOVE.L  0(A3,D0),L6_TEMP_1_B
               MOVE.L  #MAP_ARRAY_2TBL,A3
               MOVE.L  0(A3,D1),A3
;12FEB               MOVE.L  0(A3,D0),L6_TEMP_5_B      ;SAVE PARAMS FOR UPPER KEYBOARD
               MOVE.L  0(A3,D0),L6_TEMP_1_B+4    ;SAVE PARAMS FOR UPPER KEYBOARD

               BSR     GET_BYTE             ;GET THE VELOCITY (ULTIMATELY IGNORE)
               MOVE.B  D0,MIDI_DATA_2       ; (SAVE FOR POSSIBLE ECHO)
BOGUN_NOTE_OFF
               MOVE    D0,LAST_MIDI_VELOCITY     ;(GOTTA SAVE SOMETHIN' HERE...)

               TST.B   AUTORPT_FLAG         ;IF AUTOREPEATING
               BNE     JIMI_1               ;    THEN DO NOT PLAY - OTTO WILL HANDLE THAT

               TST.B   ERASING              ;IF NOT ERASING
               BEQ     ORANGE_5             ;    THEN JUST TURN OFF
                                            ;         ELSE...
               TST.B   L6_TEMP_1_B          ;SEE IF THIS KEY WAS ASSIGNED A SAMPLE
               BEQ.S   ORANGE_4             ;    IF NOT, SEE IF LOWER KEYBOARD VALID

;12FEB               MOVE.B  L6_TEMP_4_B,D5       ;SOUND NUNBER
               MOVE.B  L6_TEMP_1_B+3,D5     ;SOUND NUNBER
               EXT     D5
               TST     ALT_PARAM_FLAG       ;ALT PARAM STATUS
               BEQ.S   FIG_ERASE_NORM       ;MAINTAIN BIT FLAGS OF SOUNDS ON FOR ERASING.
FIG_ERASE_ALT
               MOVE.L  INT_ERASE_MAP+4,D6   ; ABOVE CHECK SAID ALT PARAM - CLR IN THAT LONG WORD
               BCLR    D5,D6
               MOVE.L  D6,INT_ERASE_MAP+4
               BRA.S   ORANGE_4
FIG_ERASE_NORM
               MOVE.L  INT_ERASE_MAP,D6     ; ABOVE CHECK SAID NORMAL - CLR IN THAT LONG WORD
               BCLR    D5,D6
               MOVE.L  D6,INT_ERASE_MAP
ORANGE_4
;12FEB               TST.B   L6_TEMP_5_B          ;SEE IF THIS KEY WAS ASSIGNED A SAMPLE
               TST.B   L6_TEMP_1_B+4        ;SEE IF THIS KEY WAS ASSIGNED A SAMPLE
               BEQ     ORANGE_5             ;    IF NOT, SEE IF LOWER KEYBOARD VALID

;12FEB               MOVE.B  L6_TEMP_8_B,D5       ;SOUND NUMBER
               MOVE.B  L6_TEMP_1_B+7,D5     ;SOUND NUMBER
               EXT     D5
               TST     ALT_PARAM_FLAG       ;ALT PARAM STATUS

               BEQ.S   BIG_ERASE_NORM       ;MAINTAIN BIT FLAGS OF SOUNDS ON FOR ERASING.
BIG_ERASE_ALT
               MOVE.L  INT_ERASE_MAP+4,D6   ; ABOVE CHECK SAID ALT PARAM - SET IN THAT LONG WORD
               BCLR    D5,D6
               MOVE.L  D6,INT_ERASE_MAP+4
               BRA.S   ORANGE_5
BIG_ERASE_NORM
               MOVE.L  INT_ERASE_MAP,D6     ; ABOVE CHECK SAID NORMAL - SET IN THAT LONG WORD
               BCLR    D5,D6
               MOVE.L  D6,INT_ERASE_MAP
ORANGE_5

               MOVE    LAST_MIDI_KEYNUM,D0  ;GET READY TO TURN OFF BY FORMING V_IDENTITY
               LSL     #4,D0                ; ROTATE UP TO 000x xxxx xx00 0000
               OR      LAST_MIDI_CHANNEL,D0 ;MASK ON ROTATED CHANNEL (000x xxx xxyy yy00)
               LSR     #2,D0                ;ROTATE BACK DOWN TO 0000 0xxx xxxx yyyy
               ORI     #0C000H,D0           ;MASK ON ID
               SWAP    D0
               MOVE    #8000H,D0            ;MASK ON AS FROM MIDI
               MOVE.L  D0,BG_TEMP_1_B       ; MAKE A COPY
               BSR     VOICE_GATE_OFF       ;GO SHUT OFF
               MOVEQ   #0,D1                ;  LOAD UP PITCH, FOR SEQ_OFF & LOG_OUT
;12FEB               MOVE.B  L6_TEMP_3_B,D1
               MOVE.B  L6_TEMP_1_B+2,D1
;12FEB               MOVE.B  L6_TEMP_4_B,D0       ;   SOUND NUMBER MODULA 8 FAKES AS 'PADNUM'
               MOVE.B  L6_TEMP_1_B+3,D0     ;   SOUND NUMBER MODULA 8 FAKES AS 'PADNUM'
               AND.L   #7,D0
               BSR     MAPPED_OFF_SEQ_PAD   ;SEE IF SEQUENCER RUNNING; IF SO, STUFF THIS EVENT OFF TO IT

               MOVE.L  BG_TEMP_1_B,D0       ;MAY HAVE TURNED ON 2 NOTES - KILL OFF 2
               BSR     VOICE_GATE_OFF
               MOVEQ   #0,D1                ;  LOAD UP PITCH, FOR SEQ_OFF & LOG_OUT
;12FEB               MOVE.B  L6_TEMP_7_B,D1
               MOVE.B  L6_TEMP_1_B+6,D1
;12FEB               MOVE.B  L6_TEMP_8_B,D0       ;   SOUND NUMBER MODULA 8 FAKES AS 'PADNUM'
               MOVE.B  L6_TEMP_1_B+7,D0     ;   SOUND NUMBER MODULA 8 FAKES AS 'PADNUM'
               AND.L   #7,D0
               BSR     MAPPED_OFF_SEQ_PAD   ;SEE IF SEQUENCER RUNNING; IF SO, STUFF THIS EVENT OFF TO IT
JIMI_1
               BSR     DEACTIVATE_PERF      ;KILL OF PITCH/PAN/LEVEL EDITS

               BSR     QUICK_LOG_OUT        ; LOG OUT OF HOLDING_BUFF
               BTST    #4,LAST_STAT_BYTE    ;NOTE OFF, OR A NOTE ON w/ VELOCITY = 0?
               BNE.S   RUN_MULTI_ON
               BRA     RUN_MULTI_OFF        ;THANK YOU, SIR, MAY I HAVE ANOTHER...




EAT_MULT_OFF_VEL       ; NO PLAY - OUT OF RANGE - DISPOSE OF VELOCITY; TRY AGAIN
               BSR     GET_BYTE
               MOVE.B  D0,MIDI_DATA_2
               BRA     JIMI_1
;
;AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
;AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
;AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
               SKIP
;VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
;VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
;VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
;
;             MULTI NOTE ON - READ IN, LOOK UP THIS CHANNEL AND KEYNUM IN THE KEYMAP ARRAYS TO
;              FIGURE OUT WHAT SOUND AND TRANSPOSITION THIS MEANS.  CALL ASSIGN_VOICE WITH THAT INFO.
;
;             ENTER w/ D0.B = NEW STATUS BYTE
;
RUN_MULTI_ON
               BSR     ECHO_3               ;HANDLE POSSIBLE ECHO
               MOVE.B  MIDI_DATA_1,LAST_MIDI+1   ;MAKE NOTE OF LAST MIDI KEYNUM ON
MULTI_NOTE_ON
               MOVE.B  LAST_STAT_BYTE,D0    ;RELOAD LAST STAT BYTE (IN CASE OF RUNNING STATUS)
               ANDI    #0FH,D0              ;MASK DOWN TO CHANNEL
               LSL     #2,D0                ; PRE-ROTATE INTO A LONG INDEX
               MOVE    D0,LAST_MIDI_CHANNEL ;  SAVE...

               BSR     GET_BYTE             ;GET THE KEYNUM
               MOVE.B  D0,MIDI_DATA_1       ; (SAVE FOR POSSIBLE ECHO)
               SUBI    #15H,D0              ;KNOCK DOWN (CONVERING 88-KEY RANGE)
               BCS     EAT_MULT_ON_VEL      ;    IF BELOW LEGAL RANGE, GIT
               CMPI    #87,D0               ;CHECK TOP OF RANGE
               BCC     EAT_MULT_ON_VEL      ;    IF ABOVE LEGAL RANGE, GIT
               LSL     #2,D0                ;PRE-ROTATE INTO A LONG-WORD OFFSET
               MOVE    D0,LAST_MIDI_KEYNUM

; HAVE ENOUGH TO LOOK UP THIS EVENT IN THE PROPER KEYMAP ARRAY

               MOVE    LAST_MIDI_CHANNEL,D1 ;GRAB THAT CHANNEL
               MOVE.L  #MAP_ARRAY_TBL,A3
               MOVE.L  0(A3,D1),A3    ;SAVE PARAMS FOR LOWER KEYBOARD
               MOVE.L  0(A3,D0),L6_TEMP_1_B
               MOVE.L  #MAP_ARRAY_2TBL,A3
               MOVE.L  0(A3,D1),A3
;12FEB               MOVE.L  0(A3,D0),L6_TEMP_5_B      ;SAVE PARAMS FOR UPPER KEYBOARD
               MOVE.L  0(A3,D0),L6_TEMP_1_B+4    ;SAVE PARAMS FOR UPPER KEYBOARD

               BSR     GET_BYTE             ;GET THE VELOCITY
               TST     D0                   ; IF = 0, A NOTE OFF- OTHER PLANS
               BEQ.S   CHROME_6

               CMP     #40H,D0              ;IF ABOVE MEDIAN VELOCITY
               BCC.S   NON_OCTA_3           ;    THEN PASS
               LSL     #1,D0                ;         ELSE, DESENSITIZE LOWER REGION FOR OCTAPADS
               SUB     #40H,D0              ;DO THIS BY * 2 - 40H.  THIS MEANS A VALUE OF 20H = OUR
               BEQ.S   NO_ZERO_3            ; LOWEST VELOCITY, AND FOLLOW THAT SLOPE UP TO THE MEDIAN.
               BCC.S   NON_OCTA_3
NO_ZERO_3
               MOVEQ   #1,D0
NON_OCTA_3
               TST     MIDI_DEFAULT_VEL     ; ARE WE SUPPOSED TO SUBSTITUTE WITH A DEFAULT?
               BEQ.S   CHROME_6             ;    IF NOT, KEEP WHAT WE GOT
               MOVE    MIDI_DEFAULT_VEL,D0  ;         ELSE, SUBSTITUTE
CHROME_6
               MOVE.B  D0,MIDI_DATA_2       ; (SAVE FOR POSSIBLE ECHO)
               BEQ     BOGUN_NOTE_OFF       ;  VEL = 0 = NOTE OFF!!!!
               ADD     #3,D0                ;OFFSET MIDI VELOCITY FOR ROUNDING ERRORS BELOW
               BTST    #7,D0                ; ALSO MAKE SUREIN DOING THIS THAT VEL <> 0 AFTER ROTATING
               BEQ.S   SNEEZE_3
               MOVEQ   #7FH,D0
SNEEZE_3
               LSR     #2,D0                ;ELSE, VALID - ROTATE DOWN...
               MOVE    D0,LAST_MIDI_VELOCITY     ; (SAVE)

               TST.B   AUTORPT_FLAG         ;IF AUTOREPEATING
               BNE     JIMI_2               ;    THEN NO PLAYING OURSELF - LET OTTO DO THAT

               CLR     D7                   ;(BY CLEARING, NOW A MASK FOR TURNING BYTES INTO WORDS)

               TST.B   L6_TEMP_1_B          ;SEE IF THIS KEY WAS ASSIGNED A SAMPLE
               BEQ     TRY_FOR_SECOND_NOTE  ;    IF NOT, SEE IF LOWER KEYBOARD VALID
;
;
;
;

               MOVE    #4,ASSIGN_BLOCK      ;BUILD ASSIGN BLOCK.  MIDI EVENT...

;12FEB               MOVE.B  L6_TEMP_4_B,D7       ;SOUND NUM-BAH.
               MOVE.B  L6_TEMP_1_B+3,D7     ;SOUND NUM-BAH.
               MOVE    D7,ASSIGN_BLOCK+2
               MOVE    D7,CURRENT_SOUND     ;UPDATE EDIT DISPLAYS TO THIS SOUND NUMBER.
               MOVE    D7,D5
               AND     #7,D5                ;DERIVE "PAD" NUMBER FROM SOUND NUMBER,
               MOVE    D5,PAD_JUST_HIT      ;UPDATE LIVE EVENT TRACKER VARIABLE.
               MOVE    D7,D5                ;SOUND NUMBER AGAIN.
               LSR     #3,D5                ;DERIVE "KIT" INDEX -
               AND     #1FH,D5
               ADDQ    #4,D5                ;GOTTA BE 4-7 (BANK A-D).
               MOVE    D5,EDIT_KIT_INDEX    ;UPDATE DISYEAH OTHER TRACKER VARIABLE.
               MOVE    D7,D5                ;SOUND NUMBER ONE MORE TIME.
               AND     #1FH,D5              ;MASK DOWN SOUND NUMBER.
               ADD     #32,D5               ;INDEX PAST THE USER KITS TO FIXED BANKS.
               MOVE    D5,A1                ;A1 IS INDEX INTO PAD ARRAYS.
               TST.B   BUILD_KIT_FLAG       ;ARE WE IN KIT-BUILD SCREEN/MODE?
               BEQ.S   ZARCH_10             ;NO - PLAY FROM LIVE PAD ARRAYS.
               ADD     #256,A1              ;YES - SET UP OFFSET TO GET US INTO PRESET ARRAYS.
ZARCH_10
               MOVE.B  PAD_SOUNDS(A1),D4    ;FETCH ALT-PARAMS VALUE FROM BANK PAD OR PRESET ARRAY.
               AND     #1,D4                ;ISOLATE IT.
;23NOV
;23NOV               MOVE    ALT_PARAM_FLAG,ASSIGN_BLOCK+4  ;ALT PARAM STATUS
;23NOV
               MOVE    D4,ASSIGN_BLOCK+4    ;PLOP ALT-PARAMS SETTING INTO ASSIGN_BLOCK.
;
               TST.B   ERASING              ;ERASING?
               BEQ.S   ORANGE_2             ;NO - JUST PLAY THE DAMN NOTE.
                                            ;ELSE, UPDATE ERASE MAP -
               TST     D4                   ;WE GOT ALT-PARAMS HAPPENIN' HERE?
               BEQ.S   FOG_ERASE_NORM       ;NO, WE GOT IT NOT.
FOG_ERASE_ALT
               MOVE.L  INT_ERASE_MAP+4,D6   ; ABOVE CHECK SAID ALT PARAM - SET IN THAT LONG WORD
               BSET    D7,D6
               MOVE.L  D6,INT_ERASE_MAP+4
               BRA.S   ORANGE_2
FOG_ERASE_NORM
               MOVE.L  INT_ERASE_MAP,D6     ; ABOVE CHECK SAID NORMAL - SET IN THAT LONG WORD
               BSET    D7,D6
               MOVE.L  D6,INT_ERASE_MAP
ORANGE_2
;12FEB               MOVE.B  L6_TEMP_3_B,D7       ;SOUND PITCH
               MOVE.B  L6_TEMP_1_B+2,D7     ;SOUND PITCH
               MOVE    D7,ASSIGN_BLOCK+6

               MOVE    D0,ASSIGN_BLOCK+12   ;VELOCITY

               MOVE    LAST_MIDI_CHANNEL,D6 ;CHANNEL
               LSR     #2,D6
               MOVE    D6,ASSIGN_BLOCK+14

               MOVE    LAST_MIDI_KEYNUM,D6  ;KEYNUM
               LSR     #2,D6
               MOVE    D6,ASSIGN_BLOCK+16

;23NOV               ANDI    #0FFH,D5             ;MASK DOWN SOUNDNUM
;23NOV               ADD     #32,D5               ; (INDEX PAST THE USER KITS TO FIXED BANKS)
;23NOV               MOVE    D5,A1                ;INDEX INTO PAD ARRAYS

               CLR     D0                   ; (SET SOUND COUNT TO END WITH THIS ONE)
;23NOV               MOVEQ   #-1,D2               ;FLAG THAT INDEED A BANK TO EDIT
               MOVE    A1,A0
               BSR     UPDATE_A_PAD

               MOVE.B  PAD_LEVELS(A1),D7    ;LEVEL
               MOVE    D7,ASSIGN_BLOCK+8

               MOVE.B  PAD_PANS(A1),D7      ;PAN
               MOVE    D7,ASSIGN_BLOCK+10

               TST.B   ERASING              ;IF ERASING
               BNE.S   TRY_FOR_SECOND_NOTE  ;    WE'RE SUCKING OUT SOUNDS; NOT PLAYING THEM!

               BSR     VOICE_ASSIGN         ;GO START THIS GUY UP
               BSR     MAPPED_ON_SEQ_PAD      ;SEE IF SEQUENCER RUNNING; IF SO, STUFF THIS EVENT OFF TO IT
;
;
;
;
;

TRY_FOR_SECOND_NOTE    ; GO FOR UPPER KEYBOARD
;12FEB               TST.B   L6_TEMP_5_B          ;SEE IF THIS KEY WAS ASSIGNED A SAMPLE
               TST.B   L6_TEMP_1_B+4        ;SEE IF THIS KEY WAS ASSIGNED A SAMPLE
               BEQ     DONE_STARTING_VOICES ;    IF NOT, SEE IF LOWER KEYBOARD VALID

               MOVE    #4,ASSIGN_BLOCK      ;BUILD ASSIGN BLOCK.  MIDI EVENT...

;12FEB               MOVE.B  L6_TEMP_8_B,D7       ;SOUND NOMBRE
               MOVE.B  L6_TEMP_1_B+7,D7     ;SOUND NOMBRE
               MOVE    D7,ASSIGN_BLOCK+2
               MOVE    D7,CURRENT_SOUND     ;UPDATE EDIT DISPLAYS TO THIS SOUND NUMBER.
               MOVE    D7,D5
               AND     #7,D5                ;DERIVE "PAD" NUMBER FROM SOUND NUMBER,
               MOVE    D5,PAD_JUST_HIT      ;UPDATE LIVE EVENT TRACKER VARIABLE.
               MOVE    D7,D5                ;SOUND NUMBER AGAIN.
               LSR     #3,D5                ;DERIVE "KIT" INDEX -
               AND     #1FH,D5
               ADDQ    #4,D5                ;GOTTA BE 4-7 (BANK A-D).
               MOVE    D5,EDIT_KIT_INDEX    ;UPDATE DISYEAH OTHER TRACKER VARIABLE.
               MOVE    D7,D5                ;SOUND NUMBER ONE MORE TIME.
               AND     #1FH,D5              ;MASK DOWN SOUND NUMBER.
               ADD     #32,D5               ;INDEX PAST THE USER KITS TO FIXED BANKS.
               MOVE    D5,A1                ;A1 IS INDEX INTO PAD ARRAYS.
               TST.B   BUILD_KIT_FLAG       ;ARE WE IN KIT-BUILD SCREEN/MODE?
               BEQ.S   ZARCH_20             ;NO - PLAY FROM LIVE PAD ARRAYS.
               ADD     #256,A1              ;YES - SET UP OFFSET TO GET US INTO PRESET ARRAYS.
ZARCH_20
               MOVE.B  PAD_SOUNDS(A1),D4    ;FETCH ALT-PARAMS VALUE FROM BANK PAD OR PRESET ARRAY.
               AND     #1,D4                ;ISOLATE IT.
;23NOV
;23NOV               MOVE    ALT_PARAM_FLAG,ASSIGN_BLOCK+4  ;ALT PARAM STATUS
;23NOV
               MOVE    D4,ASSIGN_BLOCK+4    ;PLOP ALT-PARAMS SETTING INTO ASSIGN_BLOCK.
;
               TST.B   ERASING              ;ERASING?
               BEQ.S   ORANGE_3             ;NO - JUST PLAY THE DAMN NOTE.
                                            ;ELSE, UPDATE ERASE MAP -
               TST     D4                   ;WE GOT ALT-PARAMS HAPPENIN' HERE?
               BEQ.S   BOG_ERASE_NORM       ;NO, WE GOT IT NOT.
BOG_ERASE_ALT
               MOVE.L  INT_ERASE_MAP+4,D6   ; ABOVE CHECK SAID ALT PARAM - SET IN THAT LONG WORD
               BSET    D7,D6
               MOVE.L  D6,INT_ERASE_MAP+4
               BRA.S   ORANGE_3
BOG_ERASE_NORM
               MOVE.L  INT_ERASE_MAP,D6     ; ABOVE CHECK SAID NORMAL - SET IN THAT LONG WORD
               BSET    D7,D6
               MOVE.L  D6,INT_ERASE_MAP
ORANGE_3
;12FEB               MOVE.B  L6_TEMP_7_B,D7       ;SOUND PITCH
               MOVE.B  L6_TEMP_1_B+6,D7     ;SOUND PITCH
               MOVE    D7,ASSIGN_BLOCK+6

               MOVE    LAST_MIDI_VELOCITY,ASSIGN_BLOCK+12  ;VELOCITY

               MOVE    LAST_MIDI_CHANNEL,D6 ;CHANNEL
               LSR     #2,D6
               MOVE    D6,ASSIGN_BLOCK+14

               MOVE    LAST_MIDI_KEYNUM,D6  ;KEYNUM
               LSR     #2,D6
               MOVE    D6,ASSIGN_BLOCK+16

;23NOV               EXT     D5
;23NOV               ADD     #32,D5               ;INDEX PAST USER KITS TO FIXED BANKS.
;23NOV               MOVE    D5,A1                ;INDEX INTO PAD ARRAYS

               CLR     D0                   ; (SET SOUND COUNT TO END WITH THIS ONE)
;23NOV               MOVEQ   #-1,D2               ;FLAG THAT INDEED A BANK TO EDIT
               MOVE    A1,A0
               BSR     UPDATE_A_PAD

               MOVE.B  PAD_LEVELS(A1),D7    ;LEVEL
               MOVE    D7,ASSIGN_BLOCK+8

               MOVE.B  PAD_PANS(A1),D7      ;PAN
               MOVE    D7,ASSIGN_BLOCK+10

               TST.B   ERASING              ;IF ERASING
               BNE.S   JIMI_2               ;    WE'RE SUCKING OUT SOUNDS; NOT PLAYING THEM!

               BSR     VOICE_ASSIGN         ;GO START THIS GUY UP
               BSR     MAPPED_ON_SEQ_PAD      ;SEE IF SEQUENCER RUNNING; IF SO, STUFF THIS EVENT OFF TO IT
JIMI_2
DONE_STARTING_VOICES   ;ASSIGN BLOCK BUILT AND DELIVERED - WE DONE!
               BSR     QUICK_LOG_IN         ; LOG IN TO HOLDING_BUFF
               BRA     RUN_MULTI_ON




EAT_MULT_ON_VEL        ; NO PLAY - OUT OF RANGE - DISPOSE OF VELOCITY; TRY AGAIN
               BSR     GET_BYTE
               MOVE.B  D0,MIDI_DATA_2
               BRA     JIMI_2
;
;AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
;AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
;AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
               TITLE   "MIDI SYSTEM ROUTINES (SANS SYSEX)"
               SKIP
;VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
;
;             MIDI SYSTEM ROUTINES
;
;
;890313;
;890313MIDI_SYSTEM
;890313               ANDI    #0FH,D0              ;STRIP TO JUST LSNIBBLE (MESSAGE IDENTIFIER)
;890313               ADD     D0,D0                ; (ROTATE INTO A WORD INDEX)
;890313               ADD     D0,D0                ;  (MAKE THAT A LONG WORD)
;890313               TST     SOUND_SEQ_SWITCH     ;    HANDLE DIFF IF AIMED AT US OR SEQUENCER
;890313               BEQ.S   EPITAPH_1
;890313               ADD     #40H,D0
;890313EPITAPH_1
;890313               EXT.L   D0                   ;WE DOING LONG WORD STUFF (SYS_EX OVER ADDRESS 8000H)
;890313               MOVE.L  SYS_JMP_TBL(PC,D0),A0
;890313               JMP     (A0)                 ;GO TO IT, BUNKY...
;890313
;890313
;890313SYS_JMP_TBL
;890313               DC.L    SYS_EX               ;F0 - system exclusive
;890313               DC.L    MIDI_GARBAGE         ;F1 - midi time code - handled by tc thru sync jacks
;890313               DC.L    SONG_POSITION        ;F2 - SONG POSITION POINTER
;890313               DC.L    SONG_SELECT          ;F3 - SONG SELECT
;890313               DC.L    MIDI_GARBAGE         ;F4 - undefined
;890313               DC.L    MIDI_GARBAGE         ;F5 - undefined
;890313               DC.L    MIDI_GARBAGE         ;F6 - tune - ignored
;890313               DC.L    MIDI_GARBAGE         ;F7 - eox - garbage if we get to see it
;890313
;890313               DC.L    REAL_RET             ;F8 - time clock - all midi clocking handled by tc
;890313               DC.L    REAL_RET             ;F9 - undefined
;890313               DC.L    REAL_RET             ;FA - midi start -  "    "      "       "     "  "
;890313               DC.L    REAL_RET             ;FB - midi continue - "  "      "       "     "  "
;890313               DC.L    REAL_RET             ;FC - midi stop -   "    "      "       "     "  "
;890313               DC.L    REAL_RET             ;FD - undefined
;890313               DC.L    REAL_RET             ;FE - active sensing - ignored
;890313               DC.L    REAL_RET             ;FF - system reset - ignored
;890313SEQ_JMP_TBL
;890313               DC.L    SEQ_EX               ;F0 - system exclusive
;890313               DC.L    MIDI_GARBAGE         ;F1 - midi time code - handled by tc thru sync jacks
;890313               DC.L    S_3_BYTE             ;F2 - SONG POSITION POINTER
;890313               DC.L    S_2_BYTE             ;F3 - SONG SELECT
;890313               DC.L    MIDI_GARBAGE         ;F4 - undefined
;890313               DC.L    MIDI_GARBAGE         ;F5 - undefined
;890313               DC.L    MIDI_GARBAGE         ;F6 - tune - ignored
;890313               DC.L    MIDI_GARBAGE         ;F7 - eox - garbage if we get to see it
;890313
;890313               DC.L    REAL_RET             ;F8 - time clock - all midi clocking handled by tc
;890313               DC.L    REAL_RET             ;F9 - undefined
;890313               DC.L    REAL_RET             ;FA - midi start -  "    "      "       "     "  "
;890313               DC.L    REAL_RET             ;FB - midi continue - "  "      "       "     "  "
;890313               DC.L    REAL_RET             ;FC - midi stop -   "    "      "       "     "  "
;890313               DC.L    REAL_RET             ;FD - undefined
;890313               DC.L    REAL_RET             ;FE - active sensing - ignored
;890313               DC.L    REAL_RET             ;FF - system reset - ignored
;890313;
;
;
MIDI_SYSTEM
               CMPI.B  #0F8H,D0             ; real time message received?
               BCS.S   MIDISYS_20           ; nope, something of lower status.
               MOVE.L  MIDI_ROUTINE_PENDING,-(A7)     ; yes - restore previous
                                                      ; receive vector, act like
               BRA     GET_BYTE                       ; nothing happened.
;
MIDISYS_20
               CMPI.B  #0F0H,D0             ; is this an SOX?
               BNE     MIDI_GARBAGE         ; branch if not, ignore all else.
               JMP     SYS_EX_IN            ; else, go handle a sys ex message.
;
;
;890313;
;890313MIDISYS_20
;890313               CMPI.B  #0F4H,D0             ; EOX, tune req or undefined msg?
;890313               BCC     MIDI_GARBAGE         ; branch if yes, we ride 'em out.
;890313
;890313;
;890313MIDISYS_40
;890313                                            ; got a message we'll deal with:
;890313               ANDI.W  #0FH,D0              ; isolate message type,
;890313               ADD.W   D0,D0                ; convert to word offset.
;890313               TST.W   SOUND_SEQ_SWITCH     ; response depends on MIDI routing.
;890313               BEQ.S   MIDISYS_44           ; branch if MIDI IN goes to sounds,
;890313               ADDQ.W  #8,D0                ; else bump offset to other table.
;890313MIDISYS_44
;890313               MOVEA.W MIDISYS_TBL(PC,D0),A0     ; fetch response routine addr,
;890313               JMP     (A0)                      ; go be that routine.
;890313
;890313
;890313MIDISYS_TBL
;890313                                            ; for MIDI IN to sounds:
;890313               DC.W    SYS_EX_IN            ; F0 - SOX.
;890313               DC.W    MIDI_GARBAGE         ; F1 - MIDI time code (not us).
;890313               DC.W    MIDI_GARBAGE         ; F2 - song position pointer.
;890313               DC.W    SONG_SELECT          ; F3 - song select.
;890313;
;890313                                            ; for MIDI IN to sequencer:
;890313               DC.W    SYS_EX_IN            ; F0 - SOX.
;890313               DC.W    MIDI_GARBAGE         ; F1 - MIDI time code (not us).
;890313               DC.W    MIDI_GARBAGE         ; F2 - song position pointer.
;890313               DC.W    MIDI_GARBAGE         ; F3 - song select.
;
;
;AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
               SKIP
;890313;VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
;890313;
;890313;
;890313;       These functions are received via 6803 only, handled in PRO_TC -
;890313;       stuff here was pretty off-base anyways ....
;890313;
;890313;
;890313;             SYSTEM ROUTINES
;890313;
;890313SONG_POSITION          ; GATHER IN 2 BYTES - THESE ARE THE NUMBER OF 16th NOTES FROM THE START
;890313; OF THE CURRENT SEQUENCE THAT WE ARE SUPPOSED TO CUE UP TO.
;890313               BSR     GET_BYTE             ;GET LSBYTE
;890313               MOVE.B  D0,MIDI_DATA_1
;890313               BSR     GET_BYTE             ;GET MSBYTE
;890313
;890313               LSL     #7,D0                ;ROTATE UPWARDS 7 BITS
;890313               OR.B    MIDI_DATA_1,D0       ; MASK ON LSB
;890313
;890313;
;890313;***** WHEN SEQUENCER EXISTS, FORWARD APROPOS NOMBRE OF 16th NOTES
;890313;
;890313
;890313               BRA     MIDI_GARBAGE         ;WAIT FOR SOMETHING ELSE OF INTEREST...
;890313
;890313
;890313SONG_SELECT            ; SWITCH TO SONG NUMBER INDICATED IN SECOND BYTE - IF ALLOWED TO
;890313               TST     SONG_SEL_ENABLE      ;ALLOWED?
;890313               BEQ     MIDI_GARBAGE         ; IF NOT, SPLIT
;890313
;890313               BSR     GET_BYTE
;890313               CMP     #100,D0              ;LIMIT TO 00->99
;890313               BCC.S   GRRR_PHIL
;890313               MOVE    D0,CURRENT_SEQUENCE
;890313GRRR_PHIL
;890313               BRA     MIDI_GARBAGE
;890313;
;890313;AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

